aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2010-08-13 23:59:15 -0400
committerRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2010-10-22 20:24:34 -0400
commitba65ae4729bf81c58d9fc847f67d57eec525b042 (patch)
tree6b2a4499a1e67bf858ce55cfe2e806b24c3697e7 /fs
parent263d90cefc7d82a01c296c59532ff59d67c63509 (diff)
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>
Diffstat (limited to 'fs')
-rw-r--r--fs/nilfs2/the_nilfs.c92
-rw-r--r--fs/nilfs2/the_nilfs.h42
2 files changed, 134 insertions, 0 deletions
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c
index 6a012b9e1b31..f1d599273d9e 100644
--- a/fs/nilfs2/the_nilfs.c
+++ b/fs/nilfs2/the_nilfs.c
@@ -89,6 +89,8 @@ static struct the_nilfs *alloc_nilfs(struct block_device *bdev)
89 INIT_LIST_HEAD(&nilfs->ns_supers); 89 INIT_LIST_HEAD(&nilfs->ns_supers);
90 INIT_LIST_HEAD(&nilfs->ns_gc_inodes); 90 INIT_LIST_HEAD(&nilfs->ns_gc_inodes);
91 spin_lock_init(&nilfs->ns_last_segment_lock); 91 spin_lock_init(&nilfs->ns_last_segment_lock);
92 nilfs->ns_cptree = RB_ROOT;
93 spin_lock_init(&nilfs->ns_cptree_lock);
92 init_rwsem(&nilfs->ns_segctor_sem); 94 init_rwsem(&nilfs->ns_segctor_sem);
93 95
94 return nilfs; 96 return nilfs;
@@ -809,6 +811,96 @@ int nilfs_near_disk_full(struct the_nilfs *nilfs)
809 return ncleansegs <= nilfs->ns_nrsvsegs + nincsegs; 811 return ncleansegs <= nilfs->ns_nrsvsegs + nincsegs;
810} 812}
811 813
814struct 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
839struct nilfs_root *
840nilfs_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
889void 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
812/** 904/**
813 * nilfs_find_sbinfo - find existing nilfs_sb_info structure 905 * nilfs_find_sbinfo - find existing nilfs_sb_info structure
814 * @nilfs: nilfs object 906 * @nilfs: nilfs object
diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h
index c7ecd0c623a3..0afede68a9e1 100644
--- a/fs/nilfs2/the_nilfs.h
+++ b/fs/nilfs2/the_nilfs.h
@@ -26,6 +26,7 @@
26 26
27#include <linux/types.h> 27#include <linux/types.h>
28#include <linux/buffer_head.h> 28#include <linux/buffer_head.h>
29#include <linux/rbtree.h>
29#include <linux/fs.h> 30#include <linux/fs.h>
30#include <linux/blkdev.h> 31#include <linux/blkdev.h>
31#include <linux/backing-dev.h> 32#include <linux/backing-dev.h>
@@ -80,6 +81,8 @@ enum {
80 * @ns_cpfile: checkpoint file inode 81 * @ns_cpfile: checkpoint file inode
81 * @ns_sufile: segusage file inode 82 * @ns_sufile: segusage file inode
82 * @ns_gc_dat: shadow inode of the DAT file inode for GC 83 * @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
83 * @ns_gc_inodes: dummy inodes to keep live blocks 86 * @ns_gc_inodes: dummy inodes to keep live blocks
84 * @ns_blocksize_bits: bit length of block size 87 * @ns_blocksize_bits: bit length of block size
85 * @ns_blocksize: block size 88 * @ns_blocksize: block size
@@ -164,6 +167,10 @@ struct the_nilfs {
164 struct inode *ns_sufile; 167 struct inode *ns_sufile;
165 struct inode *ns_gc_dat; 168 struct inode *ns_gc_dat;
166 169
170 /* Checkpoint tree */
171 struct rb_root ns_cptree;
172 spinlock_t ns_cptree_lock;
173
167 /* GC inode list */ 174 /* GC inode list */
168 struct list_head ns_gc_inodes; 175 struct list_head ns_gc_inodes;
169 176
@@ -200,6 +207,32 @@ THE_NILFS_FNS(DISCONTINUED, discontinued)
200THE_NILFS_FNS(GC_RUNNING, gc_running) 207THE_NILFS_FNS(GC_RUNNING, gc_running)
201THE_NILFS_FNS(SB_DIRTY, sb_dirty) 208THE_NILFS_FNS(SB_DIRTY, sb_dirty)
202 209
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 */
221struct 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
203/* Minimum interval of periodical update of superblocks (in seconds) */ 236/* Minimum interval of periodical update of superblocks (in seconds) */
204#define NILFS_SB_FREQ 10 237#define NILFS_SB_FREQ 10
205 238
@@ -222,6 +255,10 @@ int init_nilfs(struct the_nilfs *, struct nilfs_sb_info *, char *);
222int load_nilfs(struct the_nilfs *, struct nilfs_sb_info *); 255int load_nilfs(struct the_nilfs *, struct nilfs_sb_info *);
223int nilfs_discard_segments(struct the_nilfs *, __u64 *, size_t); 256int nilfs_discard_segments(struct the_nilfs *, __u64 *, size_t);
224int nilfs_count_free_blocks(struct the_nilfs *, sector_t *); 257int nilfs_count_free_blocks(struct the_nilfs *, sector_t *);
258struct nilfs_root *nilfs_lookup_root(struct the_nilfs *nilfs, __u64 cno);
259struct nilfs_root *nilfs_find_or_create_root(struct the_nilfs *nilfs,
260 __u64 cno);
261void nilfs_put_root(struct nilfs_root *root);
225struct nilfs_sb_info *nilfs_find_sbinfo(struct the_nilfs *, int, __u64); 262struct nilfs_sb_info *nilfs_find_sbinfo(struct the_nilfs *, int, __u64);
226int nilfs_checkpoint_is_mounted(struct the_nilfs *, __u64, int); 263int nilfs_checkpoint_is_mounted(struct the_nilfs *, __u64, int);
227int nilfs_near_disk_full(struct the_nilfs *); 264int nilfs_near_disk_full(struct the_nilfs *);
@@ -235,6 +272,11 @@ static inline void get_nilfs(struct the_nilfs *nilfs)
235 atomic_inc(&nilfs->ns_count); 272 atomic_inc(&nilfs->ns_count);
236} 273}
237 274
275static inline void nilfs_get_root(struct nilfs_root *root)
276{
277 atomic_inc(&root->count);
278}
279
238static inline void 280static inline void
239nilfs_attach_writer(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) 281nilfs_attach_writer(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
240{ 282{