diff options
author | Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> | 2009-08-02 09:45:33 -0400 |
---|---|---|
committer | Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> | 2009-09-14 05:27:13 -0400 |
commit | 027d6404eb4327878454db72a006adfcb8001bb8 (patch) | |
tree | 671c0d84ee5fd19ef85a3ff15d99a3519c1ed8bf /fs/nilfs2/the_nilfs.h | |
parent | b5696e5e0dbfb6323277d51d67d230317c18aba9 (diff) |
nilfs2: use semaphore to protect pointer to a writable FS-instance
will get rid of nilfs_get_writer() and nilfs_put_writer() pair used to
retain a writable FS-instance for a period.
The pair functions were making up some kind of recursive lock with a
mutex, but they became overkill since the commit
201913ed746c7724a40d33ee5a0b6a1fd2ef3193. Furthermore, they caused
the following lockdep warning because the mutex can be released by a
task which didn't lock it:
=====================================
[ BUG: bad unlock balance detected! ]
-------------------------------------
kswapd0/422 is trying to release lock (&nilfs->ns_writer_mutex) at:
[<c1359ff5>] mutex_unlock+0x8/0xa
but there are no more locks to release!
other info that might help us debug this:
no locks held by kswapd0/422.
stack backtrace:
Pid: 422, comm: kswapd0 Not tainted 2.6.31-rc4-nilfs #51
Call Trace:
[<c1358f97>] ? printk+0xf/0x18
[<c104fea7>] print_unlock_inbalance_bug+0xcc/0xd7
[<c11578de>] ? prop_put_global+0x3/0x35
[<c1050195>] lock_release+0xed/0x1dc
[<c1359ff5>] ? mutex_unlock+0x8/0xa
[<c1359f83>] __mutex_unlock_slowpath+0xaf/0x119
[<c1359ff5>] mutex_unlock+0x8/0xa
[<d1284add>] nilfs_mdt_write_page+0xd8/0xe1 [nilfs2]
[<c1092653>] shrink_page_list+0x379/0x68d
[<c109171b>] ? isolate_pages_global+0xb4/0x18c
[<c1092bd2>] shrink_list+0x26b/0x54b
[<c10930be>] shrink_zone+0x20c/0x2a2
[<c10936b7>] kswapd+0x407/0x591
[<c1091667>] ? isolate_pages_global+0x0/0x18c
[<c1040603>] ? autoremove_wake_function+0x0/0x33
[<c10932b0>] ? kswapd+0x0/0x591
[<c104033b>] kthread+0x69/0x6e
[<c10402d2>] ? kthread+0x0/0x6e
[<c1003e33>] kernel_thread_helper+0x7/0x1a
This patch uses a reader/writer semaphore instead of the own lock and
kills this warning.
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Diffstat (limited to 'fs/nilfs2/the_nilfs.h')
-rw-r--r-- | fs/nilfs2/the_nilfs.h | 27 |
1 files changed, 6 insertions, 21 deletions
diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index 1b9caafb8662..fa3a1dfe4053 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h | |||
@@ -50,8 +50,7 @@ enum { | |||
50 | * @ns_sem: semaphore for shared states | 50 | * @ns_sem: semaphore for shared states |
51 | * @ns_super_sem: semaphore for global operations across super block instances | 51 | * @ns_super_sem: semaphore for global operations across super block instances |
52 | * @ns_mount_mutex: mutex protecting mount process of nilfs | 52 | * @ns_mount_mutex: mutex protecting mount process of nilfs |
53 | * @ns_writer_mutex: mutex protecting ns_writer attach/detach | 53 | * @ns_writer_sem: semaphore protecting ns_writer attach/detach |
54 | * @ns_writer_refcount: number of referrers on ns_writer | ||
55 | * @ns_current: back pointer to current mount | 54 | * @ns_current: back pointer to current mount |
56 | * @ns_sbh: buffer heads of on-disk super blocks | 55 | * @ns_sbh: buffer heads of on-disk super blocks |
57 | * @ns_sbp: pointers to super block data | 56 | * @ns_sbp: pointers to super block data |
@@ -100,8 +99,7 @@ struct the_nilfs { | |||
100 | struct rw_semaphore ns_sem; | 99 | struct rw_semaphore ns_sem; |
101 | struct rw_semaphore ns_super_sem; | 100 | struct rw_semaphore ns_super_sem; |
102 | struct mutex ns_mount_mutex; | 101 | struct mutex ns_mount_mutex; |
103 | struct mutex ns_writer_mutex; | 102 | struct rw_semaphore ns_writer_sem; |
104 | atomic_t ns_writer_refcount; | ||
105 | 103 | ||
106 | /* | 104 | /* |
107 | * components protected by ns_super_sem | 105 | * components protected by ns_super_sem |
@@ -221,34 +219,21 @@ static inline void get_nilfs(struct the_nilfs *nilfs) | |||
221 | atomic_inc(&nilfs->ns_count); | 219 | atomic_inc(&nilfs->ns_count); |
222 | } | 220 | } |
223 | 221 | ||
224 | static inline struct nilfs_sb_info *nilfs_get_writer(struct the_nilfs *nilfs) | ||
225 | { | ||
226 | if (atomic_inc_and_test(&nilfs->ns_writer_refcount)) | ||
227 | mutex_lock(&nilfs->ns_writer_mutex); | ||
228 | return nilfs->ns_writer; | ||
229 | } | ||
230 | |||
231 | static inline void nilfs_put_writer(struct the_nilfs *nilfs) | ||
232 | { | ||
233 | if (atomic_add_negative(-1, &nilfs->ns_writer_refcount)) | ||
234 | mutex_unlock(&nilfs->ns_writer_mutex); | ||
235 | } | ||
236 | |||
237 | static inline void | 222 | static inline void |
238 | nilfs_attach_writer(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) | 223 | nilfs_attach_writer(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) |
239 | { | 224 | { |
240 | mutex_lock(&nilfs->ns_writer_mutex); | 225 | down_write(&nilfs->ns_writer_sem); |
241 | nilfs->ns_writer = sbi; | 226 | nilfs->ns_writer = sbi; |
242 | mutex_unlock(&nilfs->ns_writer_mutex); | 227 | up_write(&nilfs->ns_writer_sem); |
243 | } | 228 | } |
244 | 229 | ||
245 | static inline void | 230 | static inline void |
246 | nilfs_detach_writer(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) | 231 | nilfs_detach_writer(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) |
247 | { | 232 | { |
248 | mutex_lock(&nilfs->ns_writer_mutex); | 233 | down_write(&nilfs->ns_writer_sem); |
249 | if (sbi == nilfs->ns_writer) | 234 | if (sbi == nilfs->ns_writer) |
250 | nilfs->ns_writer = NULL; | 235 | nilfs->ns_writer = NULL; |
251 | mutex_unlock(&nilfs->ns_writer_mutex); | 236 | up_write(&nilfs->ns_writer_sem); |
252 | } | 237 | } |
253 | 238 | ||
254 | static inline void nilfs_put_sbinfo(struct nilfs_sb_info *sbi) | 239 | static inline void nilfs_put_sbinfo(struct nilfs_sb_info *sbi) |