From: Andrew Perepechko Date: Mon, 11 Oct 2021 19:11:05 +0000 (+0300) Subject: LU-15081 vfs: set_nlink() is not race-safe X-Git-Tag: 2.14.56~130 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=12b05772fdb6d080819b6c213fcd7f8705278412 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. Signed-off-by: Andrew Perepechko HPE-bug-id: LUS-9825 Change-Id: I67bc345b9a9e43fb88d919a83246759d11604b03 Reviewed-on: https://review.whamcloud.com/45191 Tested-by: jenkins Reviewed-by: Andreas Dilger Reviewed-by: Alexander Boyko Tested-by: Maloo Reviewed-by: Oleg Drokin --- diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 474c2e5..fa45c70 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -5150,7 +5150,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 e493791..67eecc2 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -2533,8 +2533,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 e3519f8..44d0666 100644 --- a/lustre/llite/namei.c +++ b/lustre/llite/namei.c @@ -1967,8 +1967,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); @@ -2055,8 +2058,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 e9ae2c5..38be08d 100644 --- a/lustre/lmv/lmv_intent.c +++ b/lustre/lmv/lmv_intent.c @@ -250,7 +250,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;