diff options
Diffstat (limited to 'fs/nilfs2/the_nilfs.c')
-rw-r--r-- | fs/nilfs2/the_nilfs.c | 92 |
1 files changed, 92 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 | ||
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 | |||
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 |