[Devel] [PATCH] fs: sync: prevent possible deadlock in sync_collect_filesystems

Alexander Mikhalitsyn alexander.mikhalitsyn at virtuozzo.com
Thu Mar 4 18:59:39 MSK 2021


There are two problems:
1. kmalloc should be called with GFP_NOWAIT to prevent sleep
under spinlock taken

2. spin_lock(&sb_lock) under spinlock(mnt_ns_list)
There we have a small probability of deadlock, to overcome
this let's use spin_trylock(&sb_lock) here.

Cc: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
Cc: Vasily Averin <vvs at virtuozzo.com>
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn at virtuozzo.com>
---
 fs/sync.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/fs/sync.c b/fs/sync.c
index 1cf0f0b38824..b2b72ac75615 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -150,7 +150,7 @@ static int sync_collect_filesystems(struct ve_struct *ve, struct list_head *sync
 		if (sync_filesystem_collected(sync_list, mnt->mnt.mnt_sb))
 			continue;
 
-		ss = kmalloc(sizeof(*ss), GFP_KERNEL);
+		ss = kmalloc(sizeof(*ss), GFP_NOWAIT);
 		if (ss == NULL) {
 			ret = -ENOMEM;
 			break;
@@ -161,7 +161,14 @@ static int sync_collect_filesystems(struct ve_struct *ve, struct list_head *sync
 		 * alive. And it means, that we can safely increase it's usage
 		 * counter.
 		 */
-		spin_lock(&sb_lock);
+		if (unlikely(!spin_trylock(&sb_lock))) {
+			/*
+			 * If we can't take spinlock then just skip that mount to prevent
+			 * possible deadlocks here.
+			 */
+			kfree(ss);
+			continue;
+		}
 		ss->sb->s_count++;
 		spin_unlock(&sb_lock);
 		list_add_tail(&ss->list, sync_list);
-- 
2.28.0



More information about the Devel mailing list