From: Alexander Zarochentsev Date: Thu, 30 May 2024 16:23:25 +0000 (+0000) Subject: LU-17888 osd-ldiskfs: osd_scrub_refresh_mapping deadlock X-Git-Tag: 2.15.64~45 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=refs%2Fchanges%2F67%2F55267%2F4;p=fs%2Flustre-release.git LU-17888 osd-ldiskfs: osd_scrub_refresh_mapping deadlock 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 Change-Id: Idc5f9bd2a20d25dfb5eb4a044ddd00ff7eb4558b Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/55267 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Andrew Perepechko Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin --- diff --git a/lustre/osd-ldiskfs/osd_compat.c b/lustre/osd-ldiskfs/osd_compat.c index 0e72416..b806940 100644 --- a/lustre/osd-ldiskfs/osd_compat.c +++ b/lustre/osd-ldiskfs/osd_compat.c @@ -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) diff --git a/lustre/osd-ldiskfs/osd_internal.h b/lustre/osd-ldiskfs/osd_internal.h index 7d38ad3..bd7ed43 100644 --- a/lustre/osd-ldiskfs/osd_internal.h +++ b/lustre/osd-ldiskfs/osd_internal.h @@ -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); diff --git a/lustre/osd-ldiskfs/osd_oi.c b/lustre/osd-ldiskfs/osd_oi.c index 849eb8d..fd53f1b 100644 --- a/lustre/osd-ldiskfs/osd_oi.c +++ b/lustre/osd-ldiskfs/osd_oi.c @@ -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; } diff --git a/lustre/osd-ldiskfs/osd_scrub.c b/lustre/osd-ldiskfs/osd_scrub.c index 5daff18..c2802d0 100644 --- a/lustre/osd-ldiskfs/osd_scrub.c +++ b/lustre/osd-ldiskfs/osd_scrub.c @@ -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;