diff options
author | Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> | 2009-06-07 12:39:29 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2009-06-11 21:36:17 -0400 |
commit | 33c8e57c86d1bd1548c12a4f7c4bceb94b862cca (patch) | |
tree | 8e2052a81dc1036e64d78da1082ab6af01ae4bbd /fs/nilfs2/the_nilfs.c | |
parent | 81fc20bd0e75ba6357bce2403767d7c2585d8f28 (diff) |
nilfs2: get rid of sget use for acquiring nilfs object
This will change the way to obtain nilfs object in nilfs_get_sb()
function.
Previously, a preliminary sget() call was performed, and the nilfs
object was acquired from a super block instance found by the sget()
call.
This patch, instead, instroduces a new dedicated function
find_or_create_nilfs(); as the name implies, the function finds an
existent nilfs object from a global list or creates a new one if no
object is found on the device.
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/nilfs2/the_nilfs.c')
-rw-r--r-- | fs/nilfs2/the_nilfs.c | 57 |
1 files changed, 54 insertions, 3 deletions
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index a91f15b8673c..45dbf6a61744 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c | |||
@@ -35,6 +35,10 @@ | |||
35 | #include "seglist.h" | 35 | #include "seglist.h" |
36 | #include "segbuf.h" | 36 | #include "segbuf.h" |
37 | 37 | ||
38 | |||
39 | static LIST_HEAD(nilfs_objects); | ||
40 | static DEFINE_SPINLOCK(nilfs_lock); | ||
41 | |||
38 | void nilfs_set_last_segment(struct the_nilfs *nilfs, | 42 | void nilfs_set_last_segment(struct the_nilfs *nilfs, |
39 | sector_t start_blocknr, u64 seq, __u64 cno) | 43 | sector_t start_blocknr, u64 seq, __u64 cno) |
40 | { | 44 | { |
@@ -55,7 +59,7 @@ void nilfs_set_last_segment(struct the_nilfs *nilfs, | |||
55 | * Return Value: On success, pointer to the_nilfs is returned. | 59 | * Return Value: On success, pointer to the_nilfs is returned. |
56 | * On error, NULL is returned. | 60 | * On error, NULL is returned. |
57 | */ | 61 | */ |
58 | struct the_nilfs *alloc_nilfs(struct block_device *bdev) | 62 | static struct the_nilfs *alloc_nilfs(struct block_device *bdev) |
59 | { | 63 | { |
60 | struct the_nilfs *nilfs; | 64 | struct the_nilfs *nilfs; |
61 | 65 | ||
@@ -69,6 +73,7 @@ struct the_nilfs *alloc_nilfs(struct block_device *bdev) | |||
69 | atomic_set(&nilfs->ns_ndirtyblks, 0); | 73 | atomic_set(&nilfs->ns_ndirtyblks, 0); |
70 | init_rwsem(&nilfs->ns_sem); | 74 | init_rwsem(&nilfs->ns_sem); |
71 | mutex_init(&nilfs->ns_writer_mutex); | 75 | mutex_init(&nilfs->ns_writer_mutex); |
76 | INIT_LIST_HEAD(&nilfs->ns_list); | ||
72 | INIT_LIST_HEAD(&nilfs->ns_supers); | 77 | INIT_LIST_HEAD(&nilfs->ns_supers); |
73 | spin_lock_init(&nilfs->ns_last_segment_lock); | 78 | spin_lock_init(&nilfs->ns_last_segment_lock); |
74 | nilfs->ns_gc_inodes_h = NULL; | 79 | nilfs->ns_gc_inodes_h = NULL; |
@@ -78,6 +83,45 @@ struct the_nilfs *alloc_nilfs(struct block_device *bdev) | |||
78 | } | 83 | } |
79 | 84 | ||
80 | /** | 85 | /** |
86 | * find_or_create_nilfs - find or create nilfs object | ||
87 | * @bdev: block device to which the_nilfs is related | ||
88 | * | ||
89 | * find_nilfs() looks up an existent nilfs object created on the | ||
90 | * device and gets the reference count of the object. If no nilfs object | ||
91 | * is found on the device, a new nilfs object is allocated. | ||
92 | * | ||
93 | * Return Value: On success, pointer to the nilfs object is returned. | ||
94 | * On error, NULL is returned. | ||
95 | */ | ||
96 | struct the_nilfs *find_or_create_nilfs(struct block_device *bdev) | ||
97 | { | ||
98 | struct the_nilfs *nilfs, *new = NULL; | ||
99 | |||
100 | retry: | ||
101 | spin_lock(&nilfs_lock); | ||
102 | list_for_each_entry(nilfs, &nilfs_objects, ns_list) { | ||
103 | if (nilfs->ns_bdev == bdev) { | ||
104 | get_nilfs(nilfs); | ||
105 | spin_unlock(&nilfs_lock); | ||
106 | if (new) | ||
107 | put_nilfs(new); | ||
108 | return nilfs; /* existing object */ | ||
109 | } | ||
110 | } | ||
111 | if (new) { | ||
112 | list_add_tail(&new->ns_list, &nilfs_objects); | ||
113 | spin_unlock(&nilfs_lock); | ||
114 | return new; /* new object */ | ||
115 | } | ||
116 | spin_unlock(&nilfs_lock); | ||
117 | |||
118 | new = alloc_nilfs(bdev); | ||
119 | if (new) | ||
120 | goto retry; | ||
121 | return NULL; /* insufficient memory */ | ||
122 | } | ||
123 | |||
124 | /** | ||
81 | * put_nilfs - release a reference to the_nilfs | 125 | * put_nilfs - release a reference to the_nilfs |
82 | * @nilfs: the_nilfs structure to be released | 126 | * @nilfs: the_nilfs structure to be released |
83 | * | 127 | * |
@@ -86,13 +130,20 @@ struct the_nilfs *alloc_nilfs(struct block_device *bdev) | |||
86 | */ | 130 | */ |
87 | void put_nilfs(struct the_nilfs *nilfs) | 131 | void put_nilfs(struct the_nilfs *nilfs) |
88 | { | 132 | { |
89 | if (!atomic_dec_and_test(&nilfs->ns_count)) | 133 | spin_lock(&nilfs_lock); |
134 | if (!atomic_dec_and_test(&nilfs->ns_count)) { | ||
135 | spin_unlock(&nilfs_lock); | ||
90 | return; | 136 | return; |
137 | } | ||
138 | list_del_init(&nilfs->ns_list); | ||
139 | spin_unlock(&nilfs_lock); | ||
140 | |||
91 | /* | 141 | /* |
92 | * Increment of ns_count never occur below because the caller | 142 | * Increment of ns_count never occurs below because the caller |
93 | * of get_nilfs() holds at least one reference to the_nilfs. | 143 | * of get_nilfs() holds at least one reference to the_nilfs. |
94 | * Thus its exclusion control is not required here. | 144 | * Thus its exclusion control is not required here. |
95 | */ | 145 | */ |
146 | |||
96 | might_sleep(); | 147 | might_sleep(); |
97 | if (nilfs_loaded(nilfs)) { | 148 | if (nilfs_loaded(nilfs)) { |
98 | nilfs_mdt_clear(nilfs->ns_sufile); | 149 | nilfs_mdt_clear(nilfs->ns_sufile); |