Whamcloud - gitweb
LU-15081 vfs: set_nlink() is not race-safe 91/45191/2
authorAndrew Perepechko <andrew.perepechko@hpe.com>
Mon, 11 Oct 2021 19:11:05 +0000 (22:11 +0300)
committerOleg Drokin <green@whamcloud.com>
Wed, 27 Oct 2021 00:38:12 +0000 (00:38 +0000)
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 <andrew.perepechko@hpe.com>
HPE-bug-id: LUS-9825
Change-Id: I67bc345b9a9e43fb88d919a83246759d11604b03
Reviewed-on: https://review.whamcloud.com/45191
Tested-by: jenkins <devops@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Alexander Boyko <alexander.boyko@hpe.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/llite/file.c
lustre/llite/llite_lib.c
lustre/llite/namei.c
lustre/lmv/lmv_intent.c

index 474c2e5..fa45c70 100644 (file)
@@ -5150,7 +5150,10 @@ static int ll_merge_md_attr(struct inode *inode)
        if (rc != 0)
                RETURN(rc);
 
        if (rc != 0)
                RETURN(rc);
 
+       spin_lock(&inode->i_lock);
        set_nlink(inode, attr.cat_nlink);
        set_nlink(inode, attr.cat_nlink);
+       spin_unlock(&inode->i_lock);
+
        inode->i_blocks = attr.cat_blocks;
        i_size_write(inode, attr.cat_size);
 
        inode->i_blocks = attr.cat_blocks;
        i_size_write(inode, attr.cat_size);
 
index e493791..67eecc2 100644 (file)
@@ -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;
                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);
                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);
 
        if (body->mbo_valid & OBD_MD_FLRDEV)
                inode->i_rdev = old_decode_dev(body->mbo_rdev);
 
index e3519f8..44d0666 100644 (file)
@@ -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);
                 * 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);
                        set_nlink(dchild->d_inode, body->mbo_nlink);
+                       spin_unlock(&dchild->d_inode->i_lock);
+               }
        }
 
        ptlrpc_req_finished(request);
        }
 
        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);
         * 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);
                set_nlink(dchild->d_inode, body->mbo_nlink);
+               spin_unlock(&dchild->d_inode->i_lock);
+       }
 
        ll_update_times(request, dir);
 
 
        ll_update_times(request, dir);
 
index e9ae2c5..38be08d 100644 (file)
@@ -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;
 
                        i_size_write(inode, body->mbo_size);
                        inode->i_blocks = body->mbo_blocks;
+                       spin_lock(&inode->i_lock);
                        set_nlink(inode, body->mbo_nlink);
                        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;
                        inode->i_atime.tv_sec = body->mbo_atime;
                        inode->i_ctime.tv_sec = body->mbo_ctime;
                        inode->i_mtime.tv_sec = body->mbo_mtime;