From eeb4d63f3bb5676484b2469a90038659facf7e13 Mon Sep 17 00:00:00 2001 From: Andrew Perepechko Date: Mon, 11 Oct 2021 22:11:05 +0300 Subject: [PATCH] LU-15081 vfs: set_nlink() is not race-safe set_nlink() is not atomic wrt race with itself and the following warning may be triggered by VFS: WARNING: CPU: 5 PID: 195090 at fs/inode.c:241 __destroy_inode+0xdb/0xf0 It does not seem important what exact nlink value is the result of the race. However, we need to protect the superblock remove counter. Lustre-change: https://review.whamcloud.com/45191 Lustre-commit: 12b05772fdb6d080819b6c213fcd7f8705278412 Signed-off-by: Andrew Perepechko HPE-bug-id: LUS-9825 Change-Id: I67bc345b9a9e43fb88d919a83246759d11604b03 Reviewed-by: Andreas Dilger Reviewed-by: Alexander Boyko Reviewed-on: https://review.whamcloud.com/c/ex/lustre-release/+/49452 Tested-by: jenkins Tested-by: Maloo --- lustre/llite/file.c | 3 +++ lustre/llite/llite_lib.c | 5 ++++- lustre/llite/namei.c | 10 ++++++++-- lustre/lmv/lmv_intent.c | 2 ++ 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/lustre/llite/file.c b/lustre/llite/file.c index a173134..c6a8381 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -5293,7 +5293,10 @@ static int ll_merge_md_attr(struct inode *inode) if (rc != 0) RETURN(rc); + spin_lock(&inode->i_lock); set_nlink(inode, attr.cat_nlink); + spin_unlock(&inode->i_lock); + inode->i_blocks = attr.cat_blocks; i_size_write(inode, attr.cat_size); diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index feaf411..6b3c982 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -2601,8 +2601,11 @@ int ll_update_inode(struct inode *inode, struct lustre_md *md) inode->i_gid = make_kgid(&init_user_ns, body->mbo_gid); if (body->mbo_valid & OBD_MD_FLPROJID) lli->lli_projid = body->mbo_projid; - if (body->mbo_valid & OBD_MD_FLNLINK) + if (body->mbo_valid & OBD_MD_FLNLINK) { + spin_lock(&inode->i_lock); set_nlink(inode, body->mbo_nlink); + spin_unlock(&inode->i_lock); + } if (body->mbo_valid & OBD_MD_FLRDEV) inode->i_rdev = old_decode_dev(body->mbo_rdev); diff --git a/lustre/llite/namei.c b/lustre/llite/namei.c index 7a51b5f..ea53ee9 100644 --- a/lustre/llite/namei.c +++ b/lustre/llite/namei.c @@ -2101,8 +2101,11 @@ static int ll_rmdir(struct inode *dir, struct dentry *dchild) * immediately. */ body = req_capsule_server_get(&request->rq_pill, &RMF_MDT_BODY); - if (body->mbo_valid & OBD_MD_FLNLINK) + if (body->mbo_valid & OBD_MD_FLNLINK) { + spin_lock(&dchild->d_inode->i_lock); set_nlink(dchild->d_inode, body->mbo_nlink); + spin_unlock(&dchild->d_inode->i_lock); + } } ptlrpc_req_finished(request); @@ -2185,8 +2188,11 @@ static int ll_unlink(struct inode *dir, struct dentry *dchild) * the link count so the inode can be freed immediately. */ body = req_capsule_server_get(&request->rq_pill, &RMF_MDT_BODY); - if (body->mbo_valid & OBD_MD_FLNLINK) + if (body->mbo_valid & OBD_MD_FLNLINK) { + spin_lock(&dchild->d_inode->i_lock); set_nlink(dchild->d_inode, body->mbo_nlink); + spin_unlock(&dchild->d_inode->i_lock); + } ll_update_times(request, dir); diff --git a/lustre/lmv/lmv_intent.c b/lustre/lmv/lmv_intent.c index 2d65138..bd9b4e3 100644 --- a/lustre/lmv/lmv_intent.c +++ b/lustre/lmv/lmv_intent.c @@ -253,7 +253,9 @@ int lmv_revalidate_slaves(struct obd_export *exp, i_size_write(inode, body->mbo_size); inode->i_blocks = body->mbo_blocks; + spin_lock(&inode->i_lock); set_nlink(inode, body->mbo_nlink); + spin_unlock(&inode->i_lock); inode->i_atime.tv_sec = body->mbo_atime; inode->i_ctime.tv_sec = body->mbo_ctime; inode->i_mtime.tv_sec = body->mbo_mtime; -- 1.8.3.1