Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+134
+92
fs/nilfs2/the_nilfs.c
··· 89 89 INIT_LIST_HEAD(&nilfs->ns_supers); 90 90 INIT_LIST_HEAD(&nilfs->ns_gc_inodes); 91 91 spin_lock_init(&nilfs->ns_last_segment_lock); 92 + nilfs->ns_cptree = RB_ROOT; 93 + spin_lock_init(&nilfs->ns_cptree_lock); 92 94 init_rwsem(&nilfs->ns_segctor_sem); 93 95 94 96 return nilfs; ··· 809 807 nilfs->ns_blocks_per_segment + 1; 810 808 811 809 return ncleansegs <= nilfs->ns_nrsvsegs + nincsegs; 810 + } 811 + 812 + struct nilfs_root *nilfs_lookup_root(struct the_nilfs *nilfs, __u64 cno) 813 + { 814 + struct rb_node *n; 815 + struct nilfs_root *root; 816 + 817 + spin_lock(&nilfs->ns_cptree_lock); 818 + n = nilfs->ns_cptree.rb_node; 819 + while (n) { 820 + root = rb_entry(n, struct nilfs_root, rb_node); 821 + 822 + if (cno < root->cno) { 823 + n = n->rb_left; 824 + } else if (cno > root->cno) { 825 + n = n->rb_right; 826 + } else { 827 + atomic_inc(&root->count); 828 + spin_unlock(&nilfs->ns_cptree_lock); 829 + return root; 830 + } 831 + } 832 + spin_unlock(&nilfs->ns_cptree_lock); 833 + 834 + return NULL; 835 + } 836 + 837 + struct nilfs_root * 838 + nilfs_find_or_create_root(struct the_nilfs *nilfs, __u64 cno) 839 + { 840 + struct rb_node **p, *parent; 841 + struct nilfs_root *root, *new; 842 + 843 + root = nilfs_lookup_root(nilfs, cno); 844 + if (root) 845 + return root; 846 + 847 + new = kmalloc(sizeof(*root), GFP_KERNEL); 848 + if (!new) 849 + return NULL; 850 + 851 + spin_lock(&nilfs->ns_cptree_lock); 852 + 853 + p = &nilfs->ns_cptree.rb_node; 854 + parent = NULL; 855 + 856 + while (*p) { 857 + parent = *p; 858 + root = rb_entry(parent, struct nilfs_root, rb_node); 859 + 860 + if (cno < root->cno) { 861 + p = &(*p)->rb_left; 862 + } else if (cno > root->cno) { 863 + p = &(*p)->rb_right; 864 + } else { 865 + atomic_inc(&root->count); 866 + spin_unlock(&nilfs->ns_cptree_lock); 867 + kfree(new); 868 + return root; 869 + } 870 + } 871 + 872 + new->cno = cno; 873 + new->ifile = NULL; 874 + new->nilfs = nilfs; 875 + atomic_set(&new->count, 1); 876 + atomic_set(&new->inodes_count, 0); 877 + atomic_set(&new->blocks_count, 0); 878 + 879 + rb_link_node(&new->rb_node, parent, p); 880 + rb_insert_color(&new->rb_node, &nilfs->ns_cptree); 881 + 882 + spin_unlock(&nilfs->ns_cptree_lock); 883 + 884 + return new; 885 + } 886 + 887 + void nilfs_put_root(struct nilfs_root *root) 888 + { 889 + if (atomic_dec_and_test(&root->count)) { 890 + struct the_nilfs *nilfs = root->nilfs; 891 + 892 + spin_lock(&nilfs->ns_cptree_lock); 893 + rb_erase(&root->rb_node, &nilfs->ns_cptree); 894 + spin_unlock(&nilfs->ns_cptree_lock); 895 + if (root->ifile) 896 + nilfs_mdt_destroy(root->ifile); 897 + 898 + kfree(root); 899 + } 812 900 } 813 901 814 902 /**
+42
fs/nilfs2/the_nilfs.h
··· 26 26 27 27 #include <linux/types.h> 28 28 #include <linux/buffer_head.h> 29 + #include <linux/rbtree.h> 29 30 #include <linux/fs.h> 30 31 #include <linux/blkdev.h> 31 32 #include <linux/backing-dev.h> ··· 81 80 * @ns_cpfile: checkpoint file inode 82 81 * @ns_sufile: segusage file inode 83 82 * @ns_gc_dat: shadow inode of the DAT file inode for GC 83 + * @ns_cptree: rb-tree of all mounted checkpoints (nilfs_root) 84 + * @ns_cptree_lock: lock protecting @ns_cptree 84 85 * @ns_gc_inodes: dummy inodes to keep live blocks 85 86 * @ns_blocksize_bits: bit length of block size 86 87 * @ns_blocksize: block size ··· 167 164 struct inode *ns_sufile; 168 165 struct inode *ns_gc_dat; 169 166 167 + /* Checkpoint tree */ 168 + struct rb_root ns_cptree; 169 + spinlock_t ns_cptree_lock; 170 + 170 171 /* GC inode list */ 171 172 struct list_head ns_gc_inodes; 172 173 ··· 207 200 THE_NILFS_FNS(GC_RUNNING, gc_running) 208 201 THE_NILFS_FNS(SB_DIRTY, sb_dirty) 209 202 203 + /** 204 + * struct nilfs_root - nilfs root object 205 + * @cno: checkpoint number 206 + * @rb_node: red-black tree node 207 + * @count: refcount of this structure 208 + * @nilfs: nilfs object 209 + * @ifile: inode file 210 + * @root: root inode 211 + * @inodes_count: number of inodes 212 + * @blocks_count: number of blocks (Reserved) 213 + */ 214 + struct nilfs_root { 215 + __u64 cno; 216 + struct rb_node rb_node; 217 + 218 + atomic_t count; 219 + struct the_nilfs *nilfs; 220 + struct inode *ifile; 221 + 222 + atomic_t inodes_count; 223 + atomic_t blocks_count; 224 + }; 225 + 226 + /* Special checkpoint number */ 227 + #define NILFS_CPTREE_CURRENT_CNO 0 228 + 210 229 /* Minimum interval of periodical update of superblocks (in seconds) */ 211 230 #define NILFS_SB_FREQ 10 212 231 ··· 255 222 int load_nilfs(struct the_nilfs *, struct nilfs_sb_info *); 256 223 int nilfs_discard_segments(struct the_nilfs *, __u64 *, size_t); 257 224 int nilfs_count_free_blocks(struct the_nilfs *, sector_t *); 225 + struct nilfs_root *nilfs_lookup_root(struct the_nilfs *nilfs, __u64 cno); 226 + struct nilfs_root *nilfs_find_or_create_root(struct the_nilfs *nilfs, 227 + __u64 cno); 228 + void nilfs_put_root(struct nilfs_root *root); 258 229 struct nilfs_sb_info *nilfs_find_sbinfo(struct the_nilfs *, int, __u64); 259 230 int nilfs_checkpoint_is_mounted(struct the_nilfs *, __u64, int); 260 231 int nilfs_near_disk_full(struct the_nilfs *); ··· 270 233 { 271 234 /* Caller must have at least one reference of the_nilfs. */ 272 235 atomic_inc(&nilfs->ns_count); 236 + } 237 + 238 + static inline void nilfs_get_root(struct nilfs_root *root) 239 + { 240 + atomic_inc(&root->count); 273 241 } 274 242 275 243 static inline void