diff options
author | jiangyiwen <jiangyiwen@huawei.com> | 2014-04-03 17:47:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-03 19:20:57 -0400 |
commit | 43b10a20372d9a1c08391f33f1c8bd86179ddc5f (patch) | |
tree | ed5fd7ca5fd34c4d84393e7fb3d65b8512594382 /fs/ocfs2 | |
parent | 7dc3e83901b342ea7fe36262329c3784f2937361 (diff) |
ocfs2: avoid system inode ref confusion by adding mutex lock
The following case may lead to the same system inode ref in confusion.
A thread B thread
ocfs2_get_system_file_inode
->get_local_system_inode
->_ocfs2_get_system_file_inode
because of *arr == NULL,
ocfs2_get_system_file_inode
->get_local_system_inode
->_ocfs2_get_system_file_inode
gets first ref thru
_ocfs2_get_system_file_inode,
gets second ref thru igrab and
set *arr = inode
at the moment, B thread also gets
two refs, so lead to one more
inode ref.
So add mutex lock to avoid multi thread set two inode ref once at the
same time.
Signed-off-by: jiangyiwen <jiangyiwen@huawei.com>
Reviewed-by: Joseph Qi <joseph.qi@huawei.com>
Cc: Joel Becker <jlbec@evilplan.org>
Cc: Mark Fasheh <mfasheh@suse.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/ocfs2')
-rw-r--r-- | fs/ocfs2/ocfs2.h | 2 | ||||
-rw-r--r-- | fs/ocfs2/super.c | 2 | ||||
-rw-r--r-- | fs/ocfs2/sysfile.c | 3 |
3 files changed, 7 insertions, 0 deletions
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index a780e20d4fba..8d64a97a9d5e 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h | |||
@@ -446,6 +446,8 @@ struct ocfs2_super | |||
446 | /* rb tree root for refcount lock. */ | 446 | /* rb tree root for refcount lock. */ |
447 | struct rb_root osb_rf_lock_tree; | 447 | struct rb_root osb_rf_lock_tree; |
448 | struct ocfs2_refcount_tree *osb_ref_tree_lru; | 448 | struct ocfs2_refcount_tree *osb_ref_tree_lru; |
449 | |||
450 | struct mutex system_file_mutex; | ||
449 | }; | 451 | }; |
450 | 452 | ||
451 | #define OCFS2_SB(sb) ((struct ocfs2_super *)(sb)->s_fs_info) | 453 | #define OCFS2_SB(sb) ((struct ocfs2_super *)(sb)->s_fs_info) |
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 888a1457af96..1aecd626e645 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c | |||
@@ -2100,6 +2100,8 @@ static int ocfs2_initialize_super(struct super_block *sb, | |||
2100 | spin_lock_init(&osb->osb_xattr_lock); | 2100 | spin_lock_init(&osb->osb_xattr_lock); |
2101 | ocfs2_init_steal_slots(osb); | 2101 | ocfs2_init_steal_slots(osb); |
2102 | 2102 | ||
2103 | mutex_init(&osb->system_file_mutex); | ||
2104 | |||
2103 | atomic_set(&osb->alloc_stats.moves, 0); | 2105 | atomic_set(&osb->alloc_stats.moves, 0); |
2104 | atomic_set(&osb->alloc_stats.local_data, 0); | 2106 | atomic_set(&osb->alloc_stats.local_data, 0); |
2105 | atomic_set(&osb->alloc_stats.bitmap_data, 0); | 2107 | atomic_set(&osb->alloc_stats.bitmap_data, 0); |
diff --git a/fs/ocfs2/sysfile.c b/fs/ocfs2/sysfile.c index f053688d22a3..af155c183123 100644 --- a/fs/ocfs2/sysfile.c +++ b/fs/ocfs2/sysfile.c | |||
@@ -113,9 +113,11 @@ struct inode *ocfs2_get_system_file_inode(struct ocfs2_super *osb, | |||
113 | } else | 113 | } else |
114 | arr = get_local_system_inode(osb, type, slot); | 114 | arr = get_local_system_inode(osb, type, slot); |
115 | 115 | ||
116 | mutex_lock(&osb->system_file_mutex); | ||
116 | if (arr && ((inode = *arr) != NULL)) { | 117 | if (arr && ((inode = *arr) != NULL)) { |
117 | /* get a ref in addition to the array ref */ | 118 | /* get a ref in addition to the array ref */ |
118 | inode = igrab(inode); | 119 | inode = igrab(inode); |
120 | mutex_unlock(&osb->system_file_mutex); | ||
119 | BUG_ON(!inode); | 121 | BUG_ON(!inode); |
120 | 122 | ||
121 | return inode; | 123 | return inode; |
@@ -129,6 +131,7 @@ struct inode *ocfs2_get_system_file_inode(struct ocfs2_super *osb, | |||
129 | *arr = igrab(inode); | 131 | *arr = igrab(inode); |
130 | BUG_ON(!*arr); | 132 | BUG_ON(!*arr); |
131 | } | 133 | } |
134 | mutex_unlock(&osb->system_file_mutex); | ||
132 | return inode; | 135 | return inode; |
133 | } | 136 | } |
134 | 137 | ||