[RHEL7,COMMIT] cgroup: rework reference acquisition for cgroup_find_inode

Submitted by Vasily Averin on Dec. 3, 2020, 8:17 a.m.

Details

Message ID 202012030817.0B38HfU2019817@vz7build.vvs.sw.ru
State New
Series "cgroup: rework reference acquisition for cgroup_find_inode"
Headers show

Commit Message

Vasily Averin Dec. 3, 2020, 8:17 a.m.
The commit is pushed to "branch-rh7-3.10.0-1160.6.1.vz7.171.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-1160.6.1.vz7.171.1
------>
commit cca684ad7d7ef2f7b7492fd6be2c1c7c5b597fef
Author: Andrey Zhadchenko <andrey.zhadchenko@virtuozzo.com>
Date:   Thu Dec 3 11:17:41 2020 +0300

    cgroup: rework reference acquisition for cgroup_find_inode
    
    Use more generic igrab instead of atomic inc. Move cgroup_hash_del to eviction
    stage to avoid deadlock.
    
    v2: adjusted function call order in cgroup_evict_inode to match existing code
    Fixes: ("cgroup: add export_operations to cgroup super block")
    
    Signed-off-by: Andrey Zhadchenko <andrey.zhadchenko@virtuozzo.com>
    Reviewed-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
    
    Signed-off-by: Andrey Zhadchenko <andrey.zhadchenko@virtuozzo.com>
---
 kernel/cgroup.c | 25 ++++++++-----------------
 1 file changed, 8 insertions(+), 17 deletions(-)

Patch hide | download patch | download mbox

diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index c7ed3c2..a05a00e 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -1517,21 +1517,10 @@  static struct inode *cgroup_find_inode(unsigned long fh[2], char take_ref)
 	struct inode *ret = NULL;
 
 	spin_lock(&cgroup_inode_table_lock);
-	item = cgroup_find_item_no_lock(fh);
 
-	/*
-	 * If we need to increase refcount, we should be aware of possible
-	 * deadlock. Another thread may have started deleting this inode:
-	 * iput->iput_final->cgroup_delete_inode->cgroup_hash_del
-	 * If we just call igrab, it will try to take i_lock and this will
-	 * result in deadlock, because deleting thread has already taken it
-	 * and waits on cgroup_inode_table_lock to find inode in hashtable.
-	 *
-	 * If i_count is zero, someone is deleting it -> skip.
-	 */
-	if (take_ref && item)
-		if (!atomic_inc_not_zero(&item->inode->i_count))
-			item = NULL;
+	item = cgroup_find_item_no_lock(fh);
+	if (item && take_ref && !igrab(item->inode))
+		item = NULL;
 
 	spin_unlock(&cgroup_inode_table_lock);
 
@@ -1629,15 +1618,17 @@  static const struct export_operations cgroup_export_ops = {
 	.fh_to_dentry	= cgroup_fh_to_dentry,
 };
 
-static int cgroup_delete_inode(struct inode *inode)
+static void cgroup_evict_inode(struct inode *inode)
 {
+	truncate_inode_pages_final(&inode->i_data);
+	clear_inode(inode);
 	cgroup_hash_del(inode);
-	return generic_delete_inode(inode);
 }
 
 static const struct super_operations cgroup_ops = {
 	.statfs = simple_statfs,
-	.drop_inode = cgroup_delete_inode,
+	.drop_inode = generic_delete_inode,
+	.evict_inode = cgroup_evict_inode,
 	.show_options = cgroup_show_options,
 #ifdef CONFIG_VE
 	.show_path = cgroup_show_path,