Skip to contentSkip to conversation

ocfs2: Avoid system inode ref in confusion by add mutex lock

PATCH New jiangyiwen 2 participants 2 messages Mar 14, 2014 – Apr 1, 2014 OCFS2

lore
Share & tools
lore

jiangyiwen

author
#0 lore raw

PATCH 1/1 ocfs2: Avoid system inode ref in confusion by add 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.

---
 fs/ocfs2/ocfs2.h   | 2 ++
 fs/ocfs2/super.c   | 2 ++
 fs/ocfs2/sysfile.c | 3 +++
 3 files changed, 7 insertions(+)
fs/ocfs2/ocfs2.h +2 -0
index 553f53c..975a70c 100644
@@ -449,6 +449,8 @@ struct ocfs2_super
 	/* rb tree root for refcount lock. */
 	struct rb_root	osb_rf_lock_tree;
 	struct ocfs2_refcount_tree *osb_ref_tree_lru;
+
+	struct mutex system_file_mutex;
 };
 
 #define OCFS2_SB(sb)	    ((struct ocfs2_super *)(sb)->s_fs_info)
fs/ocfs2/super.c +2 -0
index 49d84f8..eb855a7 100644
@@ -2123,6 +2123,8 @@ static int ocfs2_initialize_super(struct super_block *sb,
 	spin_lock_init(&osb->osb_xattr_lock);
 	ocfs2_init_steal_slots(osb);
 
+	mutex_init(&osb->system_file_mutex);
+
 	atomic_set(&osb->alloc_stats.moves, 0);
 	atomic_set(&osb->alloc_stats.local_data, 0);
 	atomic_set(&osb->alloc_stats.bitmap_data, 0);
fs/ocfs2/sysfile.c +3 -0
index f053688..af155c1 100644
@@ -113,9 +113,11 @@ struct inode *ocfs2_get_system_file_inode(struct ocfs2_super *osb,
 	} else
 		arr = get_local_system_inode(osb, type, slot);
 
+	mutex_lock(&osb->system_file_mutex);
 	if (arr && ((inode = *arr) != NULL)) {
 		/* get a ref in addition to the array ref */
 		inode = igrab(inode);
+		mutex_unlock(&osb->system_file_mutex);
 		BUG_ON(!inode);
 
 		return inode;
@@ -129,6 +131,7 @@ struct inode *ocfs2_get_system_file_inode(struct ocfs2_super *osb,
 		*arr = igrab(inode);
 		BUG_ON(!*arr);
 	}
+	mutex_unlock(&osb->system_file_mutex);
 	return inode;
 }
 
Signature · 1 line
1.8.4.3
#1 lore raw

PATCH 1/1 ocfs2: Avoid system inode ref in confusion by add mutex lock

Quoted 18 lines · On Fri, 14 Mar 2014 09:55:36 +0800 jiangyiwen <[email protected]> wrote:

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.

Quoted 2 lines

So add mutex lock to avoid multi thread set two inode ref once at the same time.

Looks good to me. I queued it for 3.15-rc1.

From: jiangyiwen <[email protected]>
Subject: 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.

---

 fs/ocfs2/ocfs2.h   |    2 ++
 fs/ocfs2/super.c   |    2 ++
 fs/ocfs2/sysfile.c |    3 +++
 3 files changed, 7 insertions(+)
fs/ocfs2/ocfs2.h renamed from fs/ocfs2/ocfs2.h~ocfs2-avoid-system-inode-ref-confusion-by-adding-mutex-lock +2 -0
diff -puN fs/ocfs2/ocfs2.h~ocfs2-avoid-system-inode-ref-confusion-by-adding-mutex-lock fs/ocfs2/ocfs2.h
@@ -446,6 +446,8 @@ struct ocfs2_super
 	/* rb tree root for refcount lock. */
 	struct rb_root	osb_rf_lock_tree;
 	struct ocfs2_refcount_tree *osb_ref_tree_lru;
+
+	struct mutex system_file_mutex;
 };
 
 #define OCFS2_SB(sb)	    ((struct ocfs2_super *)(sb)->s_fs_info)
fs/ocfs2/super.c renamed from fs/ocfs2/super.c~ocfs2-avoid-system-inode-ref-confusion-by-adding-mutex-lock +2 -0
diff -puN fs/ocfs2/super.c~ocfs2-avoid-system-inode-ref-confusion-by-adding-mutex-lock fs/ocfs2/super.c
@@ -2100,6 +2100,8 @@ static int ocfs2_initialize_super(struct
 	spin_lock_init(&osb->osb_xattr_lock);
 	ocfs2_init_steal_slots(osb);
 
+	mutex_init(&osb->system_file_mutex);
+
 	atomic_set(&osb->alloc_stats.moves, 0);
 	atomic_set(&osb->alloc_stats.local_data, 0);
 	atomic_set(&osb->alloc_stats.bitmap_data, 0);
fs/ocfs2/sysfile.c renamed from fs/ocfs2/sysfile.c~ocfs2-avoid-system-inode-ref-confusion-by-adding-mutex-lock +3 -0
diff -puN fs/ocfs2/sysfile.c~ocfs2-avoid-system-inode-ref-confusion-by-adding-mutex-lock fs/ocfs2/sysfile.c
@@ -113,9 +113,11 @@ struct inode *ocfs2_get_system_file_inod
 	} else
 		arr = get_local_system_inode(osb, type, slot);
 
+	mutex_lock(&osb->system_file_mutex);
 	if (arr && ((inode = *arr) != NULL)) {
 		/* get a ref in addition to the array ref */
 		inode = igrab(inode);
+		mutex_unlock(&osb->system_file_mutex);
 		BUG_ON(!inode);
 
 		return inode;
@@ -129,6 +131,7 @@ struct inode *ocfs2_get_system_file_inod
 		*arr = igrab(inode);
 		BUG_ON(!*arr);
 	}
+	mutex_unlock(&osb->system_file_mutex);
 	return inode;
 }
 

_