From: Chen Linxuan me@black-desk.cn
When using fsconfig(..., FSCONFIG_CMD_CREATE, ...), the filesystem context is retrieved from the file descriptor. Since the file structure persists across syscall restarts, the context state is preserved:
// fs/fsopen.c SYSCALL_DEFINE5(fsconfig, ...) { ... fc = fd_file(f)->private_data; ... ret = vfs_fsconfig_locked(fc, cmd, ¶m); ... }
In vfs_cmd_create(), the context phase is transitioned to FS_CONTEXT_CREATING before calling vfs_get_tree():
// fs/fsopen.c static int vfs_cmd_create(struct fs_context *fc, bool exclusive) { ... fc->phase = FS_CONTEXT_CREATING; ... ret = vfs_get_tree(fc); ... }
However, vfs_get_tree() may return -ERESTARTNOINTR if the filesystem implementation needs to restart the syscall. For example, cgroup v1 does this when it encounters a race condition where the root is dying:
// kernel/cgroup/cgroup-v1.c int cgroup1_get_tree(struct fs_context *fc) { ... if (unlikely(ret > 0)) { msleep(10); return restart_syscall(); } return ret; }
If the syscall is restarted, fsconfig() is called again and retrieves the *same* fs_context. However, vfs_cmd_create() rejects the call because the phase was left as FS_CONTEXT_CREATING during the first attempt:
if (fc->phase != FS_CONTEXT_CREATE_PARAMS) return -EBUSY;
Fix this by resetting fc->phase back to FS_CONTEXT_CREATE_PARAMS if vfs_get_tree() returns -ERESTARTNOINTR.
Cc: stable@vger.kernel.org Signed-off-by: Chen Linxuan me@black-desk.cn --- fs/fsopen.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/fs/fsopen.c b/fs/fsopen.c index f645c99204eb..8a7cb031af50 100644 --- a/fs/fsopen.c +++ b/fs/fsopen.c @@ -229,6 +229,10 @@ static int vfs_cmd_create(struct fs_context *fc, bool exclusive) fc->exclusive = exclusive;
ret = vfs_get_tree(fc); + if (ret == -ERESTARTNOINTR) { + fc->phase = FS_CONTEXT_CREATE_PARAMS; + return ret; + } if (ret) { fc->phase = FS_CONTEXT_FAILED; return ret;
--- base-commit: 187d0801404f415f22c0b31531982c7ea97fa341 change-id: 20251213-mount-ebusy-8ee3888a7e4f
Best regards,
linux-stable-mirror@lists.linaro.org