Skip to content

Commit ba65ae4

Browse files
committed
nilfs2: add checkpoint tree to nilfs object
To hold multiple versions of a filesystem in one sb instance, a new on-memory structure is necessary to handle one or more checkpoints. This adds a red-black tree of checkpoints to nilfs object, and adds lookup and create functions for them. Each checkpoint is represented by "nilfs_root" structure, and this structure has rb_node to configure the rb-tree. The nilfs_root object is identified with a checkpoint number. For each snapshot, a nilfs_root object is allocated and the checkpoint number of snapshot is assigned to it. For a regular mount (i.e. current mode mount), NILFS_CPTREE_CURRENT_CNO constant is assigned to the corresponding nilfs_root object. Each nilfs_root object has an ifile inode and some counters. These items will displace those of nilfs_sb_info structure in successive patches. Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
1 parent 263d90c commit ba65ae4

File tree

2 files changed

+134
-0
lines changed

2 files changed

+134
-0
lines changed

fs/nilfs2/the_nilfs.c

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ static struct the_nilfs *alloc_nilfs(struct block_device *bdev)
8989
INIT_LIST_HEAD(&nilfs->ns_supers);
9090
INIT_LIST_HEAD(&nilfs->ns_gc_inodes);
9191
spin_lock_init(&nilfs->ns_last_segment_lock);
92+
nilfs->ns_cptree = RB_ROOT;
93+
spin_lock_init(&nilfs->ns_cptree_lock);
9294
init_rwsem(&nilfs->ns_segctor_sem);
9395

9496
return nilfs;
@@ -809,6 +811,96 @@ int nilfs_near_disk_full(struct the_nilfs *nilfs)
809811
return ncleansegs <= nilfs->ns_nrsvsegs + nincsegs;
810812
}
811813

814+
struct nilfs_root *nilfs_lookup_root(struct the_nilfs *nilfs, __u64 cno)
815+
{
816+
struct rb_node *n;
817+
struct nilfs_root *root;
818+
819+
spin_lock(&nilfs->ns_cptree_lock);
820+
n = nilfs->ns_cptree.rb_node;
821+
while (n) {
822+
root = rb_entry(n, struct nilfs_root, rb_node);
823+
824+
if (cno < root->cno) {
825+
n = n->rb_left;
826+
} else if (cno > root->cno) {
827+
n = n->rb_right;
828+
} else {
829+
atomic_inc(&root->count);
830+
spin_unlock(&nilfs->ns_cptree_lock);
831+
return root;
832+
}
833+
}
834+
spin_unlock(&nilfs->ns_cptree_lock);
835+
836+
return NULL;
837+
}
838+
839+
struct nilfs_root *
840+
nilfs_find_or_create_root(struct the_nilfs *nilfs, __u64 cno)
841+
{
842+
struct rb_node **p, *parent;
843+
struct nilfs_root *root, *new;
844+
845+
root = nilfs_lookup_root(nilfs, cno);
846+
if (root)
847+
return root;
848+
849+
new = kmalloc(sizeof(*root), GFP_KERNEL);
850+
if (!new)
851+
return NULL;
852+
853+
spin_lock(&nilfs->ns_cptree_lock);
854+
855+
p = &nilfs->ns_cptree.rb_node;
856+
parent = NULL;
857+
858+
while (*p) {
859+
parent = *p;
860+
root = rb_entry(parent, struct nilfs_root, rb_node);
861+
862+
if (cno < root->cno) {
863+
p = &(*p)->rb_left;
864+
} else if (cno > root->cno) {
865+
p = &(*p)->rb_right;
866+
} else {
867+
atomic_inc(&root->count);
868+
spin_unlock(&nilfs->ns_cptree_lock);
869+
kfree(new);
870+
return root;
871+
}
872+
}
873+
874+
new->cno = cno;
875+
new->ifile = NULL;
876+
new->nilfs = nilfs;
877+
atomic_set(&new->count, 1);
878+
atomic_set(&new->inodes_count, 0);
879+
atomic_set(&new->blocks_count, 0);
880+
881+
rb_link_node(&new->rb_node, parent, p);
882+
rb_insert_color(&new->rb_node, &nilfs->ns_cptree);
883+
884+
spin_unlock(&nilfs->ns_cptree_lock);
885+
886+
return new;
887+
}
888+
889+
void nilfs_put_root(struct nilfs_root *root)
890+
{
891+
if (atomic_dec_and_test(&root->count)) {
892+
struct the_nilfs *nilfs = root->nilfs;
893+
894+
spin_lock(&nilfs->ns_cptree_lock);
895+
rb_erase(&root->rb_node, &nilfs->ns_cptree);
896+
spin_unlock(&nilfs->ns_cptree_lock);
897+
if (root->ifile)
898+
nilfs_mdt_destroy(root->ifile);
899+
900+
kfree(root);
901+
}
902+
}
903+
812904
/**
813905
* nilfs_find_sbinfo - find existing nilfs_sb_info structure
814906
* @nilfs: nilfs object

fs/nilfs2/the_nilfs.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
#include <linux/types.h>
2828
#include <linux/buffer_head.h>
29+
#include <linux/rbtree.h>
2930
#include <linux/fs.h>
3031
#include <linux/blkdev.h>
3132
#include <linux/backing-dev.h>
@@ -80,6 +81,8 @@ enum {
8081
* @ns_cpfile: checkpoint file inode
8182
* @ns_sufile: segusage file inode
8283
* @ns_gc_dat: shadow inode of the DAT file inode for GC
84+
* @ns_cptree: rb-tree of all mounted checkpoints (nilfs_root)
85+
* @ns_cptree_lock: lock protecting @ns_cptree
8386
* @ns_gc_inodes: dummy inodes to keep live blocks
8487
* @ns_blocksize_bits: bit length of block size
8588
* @ns_blocksize: block size
@@ -164,6 +167,10 @@ struct the_nilfs {
164167
struct inode *ns_sufile;
165168
struct inode *ns_gc_dat;
166169

170+
/* Checkpoint tree */
171+
struct rb_root ns_cptree;
172+
spinlock_t ns_cptree_lock;
173+
167174
/* GC inode list */
168175
struct list_head ns_gc_inodes;
169176

@@ -200,6 +207,32 @@ THE_NILFS_FNS(DISCONTINUED, discontinued)
200207
THE_NILFS_FNS(GC_RUNNING, gc_running)
201208
THE_NILFS_FNS(SB_DIRTY, sb_dirty)
202209

210+
/**
211+
* struct nilfs_root - nilfs root object
212+
* @cno: checkpoint number
213+
* @rb_node: red-black tree node
214+
* @count: refcount of this structure
215+
* @nilfs: nilfs object
216+
* @ifile: inode file
217+
* @root: root inode
218+
* @inodes_count: number of inodes
219+
* @blocks_count: number of blocks (Reserved)
220+
*/
221+
struct nilfs_root {
222+
__u64 cno;
223+
struct rb_node rb_node;
224+
225+
atomic_t count;
226+
struct the_nilfs *nilfs;
227+
struct inode *ifile;
228+
229+
atomic_t inodes_count;
230+
atomic_t blocks_count;
231+
};
232+
233+
/* Special checkpoint number */
234+
#define NILFS_CPTREE_CURRENT_CNO 0
235+
203236
/* Minimum interval of periodical update of superblocks (in seconds) */
204237
#define NILFS_SB_FREQ 10
205238

@@ -222,6 +255,10 @@ int init_nilfs(struct the_nilfs *, struct nilfs_sb_info *, char *);
222255
int load_nilfs(struct the_nilfs *, struct nilfs_sb_info *);
223256
int nilfs_discard_segments(struct the_nilfs *, __u64 *, size_t);
224257
int nilfs_count_free_blocks(struct the_nilfs *, sector_t *);
258+
struct nilfs_root *nilfs_lookup_root(struct the_nilfs *nilfs, __u64 cno);
259+
struct nilfs_root *nilfs_find_or_create_root(struct the_nilfs *nilfs,
260+
__u64 cno);
261+
void nilfs_put_root(struct nilfs_root *root);
225262
struct nilfs_sb_info *nilfs_find_sbinfo(struct the_nilfs *, int, __u64);
226263
int nilfs_checkpoint_is_mounted(struct the_nilfs *, __u64, int);
227264
int nilfs_near_disk_full(struct the_nilfs *);
@@ -235,6 +272,11 @@ static inline void get_nilfs(struct the_nilfs *nilfs)
235272
atomic_inc(&nilfs->ns_count);
236273
}
237274

275+
static inline void nilfs_get_root(struct nilfs_root *root)
276+
{
277+
atomic_inc(&root->count);
278+
}
279+
238280
static inline void
239281
nilfs_attach_writer(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
240282
{

0 commit comments

Comments
 (0)