Whamcloud - gitweb
LU-17888 osd-ldiskfs: osd_scrub_refresh_mapping deadlock 67/55267/4
authorAlexander Zarochentsev <alexander.zarochentsev@hpe.com>
Thu, 30 May 2024 16:23:25 +0000 (16:23 +0000)
committerOleg Drokin <green@whamcloud.com>
Fri, 21 Jun 2024 04:57:24 +0000 (04:57 +0000)
After copying a lustre special file (last_rcvd for example)
to a new inode, lustre mount hangs with the following stack trace:

[root@testbed ~]# cat /proc/pidof mount.lustre/stack
[<0>] rwsem_down_write_slowpath+0x32a/0x610
[<0>] osd_obj_update_entry.isra.22+0xb7/0x900 [osd_ldiskfs]
[<0>] osd_obj_spec_update+0x146/0x160 [osd_ldiskfs]
[<0>] osd_scrub_refresh_mapping+0x282/0x420 [osd_ldiskfs]
[<0>] osd_ios_scan_one+0x5df/0xe10 [osd_ldiskfs]
[<0>] osd_ios_root_fill+0x267/0x300 [osd_ldiskfs]
[<0>] call_filldir+0xb0/0x120 [ldiskfs]
[<0>] ldiskfs_readdir+0x7a7/0xac0 [ldiskfs]
[<0>] iterate_dir+0x13c/0x190
[<0>] osd_ios_general_scan+0x10e/0x250 [osd_ldiskfs]
[<0>] osd_initial_OI_scrub+0x72/0x920 [osd_ldiskfs]
[<0>] osd_scrub_setup+0x8ab/0x9e0 [osd_ldiskfs]
[<0>] osd_device_init0+0x447/0x810 [osd_ldiskfs]
[<0>] osd_device_alloc+0x186/0x220 [osd_ldiskfs]
[<0>] obd_setup+0x115/0x2d0 [obdclass]
[<0>] class_setup+0x57f/0x790 [obdclass]
[<0>] class_process_config+0x1104/0x2460 [obdclass]
[<0>] do_lcfg+0x21d/0x530 [obdclass]
[<0>] lustre_start_simple+0x77/0x1d0 [obdclass]
[<0>] osd_start+0x408/0x7f0 [obdclass]
[<0>] server_fill_super+0x382/0x10d0 [obdclass]
[<0>] lustre_fill_super+0x3a1/0x3f0 [lustre]
[<0>] mount_nodev+0x48/0xa0
[<0>] legacy_get_tree+0x27/0x40
[<0>] vfs_get_tree+0x25/0xb0
[<0>] do_mount+0x2e2/0x950
[<0>] ksys_mount+0xb6/0xd0
[<0>] __x64_sys_mount+0x21/0x30
[<0>] do_syscall_64+0x5b/0x1a0
[<0>] entry_SYSCALL_64_after_hwframe+0x65/0xca

root inode lock is attempted to be taken twice,
once in iterate_dir() and another attempt in
osd_obj_update_entry().

HPE-bug-id: LUS-12368
Signed-off-by: Alexander Zarochentsev <alexander.zarochentsev@hpe.com>
Change-Id: Idc5f9bd2a20d25dfb5eb4a044ddd00ff7eb4558b
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/55267
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andrew Perepechko <andrew.perepechko@hpe.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/osd-ldiskfs/osd_compat.c
lustre/osd-ldiskfs/osd_internal.h
lustre/osd-ldiskfs/osd_oi.c
lustre/osd-ldiskfs/osd_scrub.c

index 0e72416..b806940 100644 (file)
@@ -689,7 +689,7 @@ static int osd_obj_update_entry(struct osd_thread_info *info,
                                struct dentry *dir, const char *name,
                                const struct lu_fid *fid,
                                const struct osd_inode_id *id,
-                               handle_t *th)
+                               handle_t *th, bool locked)
 {
        struct inode *parent = dir->d_inode;
        struct dentry *child;
@@ -714,7 +714,8 @@ static int osd_obj_update_entry(struct osd_thread_info *info,
        child->d_name.len = strlen(name);
 
        dquot_initialize(parent);
-       inode_lock(parent);
+       if (!locked)
+               inode_lock(parent);
        bh = osd_ldiskfs_find_entry(parent, &child->d_name, &de, NULL, NULL);
        if (IS_ERR(bh))
                GOTO(out, rc = PTR_ERR(bh));
@@ -819,7 +820,8 @@ update:
 out:
        if (!IS_ERR(bh))
                brelse(bh);
-       inode_unlock(parent);
+       if (!locked)
+               inode_unlock(parent);
        return rc;
 }
 
@@ -863,7 +865,7 @@ static int osd_obj_add_entry(struct osd_thread_info *info,
                             struct osd_device *osd,
                             struct dentry *dir, char *name,
                             const struct osd_inode_id *id,
-                            handle_t *th)
+                            handle_t *th, bool locked)
 {
        struct dentry *child;
        struct inode *inode;
@@ -902,9 +904,11 @@ static int osd_obj_add_entry(struct osd_thread_info *info,
                inode->i_ino++;
 
        dquot_initialize(dir->d_inode);
-       inode_lock(dir->d_inode);
+       if (!locked)
+               inode_lock(dir->d_inode);
        rc = osd_ldiskfs_add_entry(info, osd, th, child, inode, NULL);
-       inode_unlock(dir->d_inode);
+       if (!locked)
+               inode_unlock(dir->d_inode);
 
        RETURN(rc);
 }
@@ -1147,9 +1151,10 @@ int osd_obj_map_insert(struct osd_thread_info *info,
        osd_oid_name(name, sizeof(name), fid, oid);
 
 again:
-       rc = osd_obj_add_entry(info, osd, d, name, id, th);
+       rc = osd_obj_add_entry(info, osd, d, name, id, th, false);
        if (rc == -EEXIST) {
-               rc = osd_obj_update_entry(info, osd, d, name, fid, id, th);
+               rc = osd_obj_update_entry(info, osd, d, name, fid, id, th,
+                                         false);
                if (unlikely(rc == -ENOENT))
                        goto again;
 
@@ -1216,7 +1221,7 @@ int osd_obj_map_update(struct osd_thread_info *info,
        LASSERT(d);
 
        osd_oid_name(name, sizeof(name), fid, ostid_id(ostid));
-       rc = osd_obj_update_entry(info, osd, d, name, fid, id, th);
+       rc = osd_obj_update_entry(info, osd, d, name, fid, id, th, false);
 
        RETURN(rc);
 }
@@ -1375,7 +1380,7 @@ osd_object_spec_find(struct osd_thread_info *info, struct osd_device *osd,
 
 int osd_obj_spec_update(struct osd_thread_info *info, struct osd_device *osd,
                        const struct lu_fid *fid, const struct osd_inode_id *id,
-                       handle_t *th)
+                       handle_t *th, bool locked)
 {
        struct dentry *root;
        char *name = NULL;
@@ -1385,7 +1390,8 @@ int osd_obj_spec_update(struct osd_thread_info *info, struct osd_device *osd,
 
        root = osd_object_spec_find(info, osd, fid, &name);
        if (!IS_ERR(root)) {
-               rc = osd_obj_update_entry(info, osd, root, name, fid, id, th);
+               rc = osd_obj_update_entry(info, osd, root, name, fid, id, th,
+                                         locked);
        } else {
                rc = PTR_ERR(root);
                if (rc == -ENOENT)
@@ -1397,7 +1403,7 @@ int osd_obj_spec_update(struct osd_thread_info *info, struct osd_device *osd,
 
 int osd_obj_spec_insert(struct osd_thread_info *info, struct osd_device *osd,
                        const struct lu_fid *fid, const struct osd_inode_id *id,
-                       handle_t *th)
+                       handle_t *th, bool locked)
 {
        struct dentry *root;
        char *name = NULL;
@@ -1407,7 +1413,7 @@ int osd_obj_spec_insert(struct osd_thread_info *info, struct osd_device *osd,
 
        root = osd_object_spec_find(info, osd, fid, &name);
        if (!IS_ERR(root)) {
-               rc = osd_obj_add_entry(info, osd, root, name, id, th);
+               rc = osd_obj_add_entry(info, osd, root, name, id, th, locked);
        } else {
                rc = PTR_ERR(root);
                if (rc == -ENOENT)
index 7d38ad3..bd7ed43 100644 (file)
@@ -870,10 +870,10 @@ int osd_obj_spec_lookup(struct osd_thread_info *info, struct osd_device *osd,
                        enum oi_check_flags flags);
 int osd_obj_spec_insert(struct osd_thread_info *info, struct osd_device *osd,
                        const struct lu_fid *fid, const struct osd_inode_id *id,
-                       handle_t *th);
+                       handle_t *th, bool locked);
 int osd_obj_spec_update(struct osd_thread_info *info, struct osd_device *osd,
                        const struct lu_fid *fid, const struct osd_inode_id *id,
-                       handle_t *th);
+                       handle_t *th, bool locked);
 int osd_obj_del_entry(struct osd_thread_info *info, struct osd_device *osd,
                      struct dentry *dird, char *name, int namelen,
                      handle_t *th);
index 849eb8d..fd53f1b 100644 (file)
@@ -705,11 +705,12 @@ int osd_oi_insert(struct osd_thread_info *info, struct osd_device *osd,
        struct lu_fid       *oi_fid = &info->oti_fid2;
        struct osd_inode_id *oi_id  = &info->oti_id2;
        int                  rc     = 0;
+       bool                 locked = !!(flags & OI_LOCKED);
 
        CDEBUG(D_INODE, "insert OI for "DFID"\n", PFID(fid));
 
        if (unlikely(fid_is_last_id(fid)))
-               return osd_obj_spec_insert(info, osd, fid, id, th);
+               return osd_obj_spec_insert(info, osd, fid, id, th, locked);
 
        if (fid_is_llog(fid) || fid_is_on_ost(info, osd, fid, flags))
                return osd_obj_map_insert(info, osd, fid, id, th);
@@ -774,7 +775,7 @@ update:
        }
 
        if (unlikely(fid_seq(fid) == FID_SEQ_LOCAL_FILE))
-               rc = osd_obj_spec_insert(info, osd, fid, id, th);
+               rc = osd_obj_spec_insert(info, osd, fid, id, th, locked);
        return rc;
 }
 
@@ -834,11 +835,12 @@ int osd_oi_update(struct osd_thread_info *info, struct osd_device *osd,
        struct lu_fid       *oi_fid = &info->oti_fid2;
        struct osd_inode_id *oi_id  = &info->oti_id2;
        int                  rc     = 0;
+       bool                 locked = !!(flags & OI_LOCKED);
 
        CDEBUG(D_INODE, "update OI for "DFID"\n", PFID(fid));
 
        if (unlikely(fid_is_last_id(fid)))
-               return osd_obj_spec_update(info, osd, fid, id, th);
+               return osd_obj_spec_update(info, osd, fid, id, th, locked);
 
        if (fid_is_llog(fid) || fid_is_on_ost(info, osd, fid, flags))
                return osd_obj_map_update(info, osd, fid, id, th);
@@ -852,7 +854,7 @@ int osd_oi_update(struct osd_thread_info *info, struct osd_device *osd,
                return rc;
 
        if (unlikely(fid_seq(fid) == FID_SEQ_LOCAL_FILE))
-               rc = osd_obj_spec_update(info, osd, fid, id, th);
+               rc = osd_obj_spec_update(info, osd, fid, id, th, locked);
        return rc;
 }
 
index 5daff18..c2802d0 100644 (file)
@@ -1950,7 +1950,8 @@ osd_ios_scan_one(struct osd_thread_info *info, struct osd_device *dev,
                        RETURN(rc);
 
                rc = osd_scrub_refresh_mapping(info, dev, &tfid, id,
-                                              DTO_INDEX_INSERT, true, 0, NULL);
+                                              DTO_INDEX_INSERT, true,
+                                              OI_LOCKED, NULL);
                if (rc > 0)
                        rc = 0;
 
@@ -1968,7 +1969,8 @@ osd_ios_scan_one(struct osd_thread_info *info, struct osd_device *dev,
        }
 
        rc = osd_scrub_refresh_mapping(info, dev, &tfid, id,
-                                      DTO_INDEX_UPDATE, true, 0, NULL);
+                                      DTO_INDEX_UPDATE, true,
+                                      OI_LOCKED, NULL);
        if (rc > 0)
                rc = 0;