From 7c0547a7dd732a9d127e427452a95e689a2c38de Mon Sep 17 00:00:00 2001 From: James Simmons Date: Mon, 19 Aug 2019 09:17:29 -0400 Subject: [PATCH] LU-12137 osd-ldiskfs: create locked and unlocked versions of osd lookup code The inode_lock is expected to be taken when lookup_one_len() is called. Rename osd_ios_lookup_one_len() to osd_lookup_one_len() since it now doesn't take the inode_lock manually. Instead it expects the called to have already called inode_lock(). The osd_lookup_one_len_unlocked() function will always take the inode_lock itself. Currently osd-ldiskfs always uses osd_lookup_one_len_unlocked(). Change-Id: Ie406db5e24f983e52ea8a89bca66546ab9d25148 Signed-off-by: James Simmons Reviewed-on: https://review.whamcloud.com/35594 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Neil Brown Reviewed-by: Andreas Dilger Reviewed-by: Alex Zhuravlev Reviewed-by: Oleg Drokin --- lustre/osd-ldiskfs/osd_compat.c | 69 ++++++++++++++++++++++++++------------- lustre/osd-ldiskfs/osd_internal.h | 5 ++- lustre/osd-ldiskfs/osd_oi.h | 1 + lustre/osd-ldiskfs/osd_scrub.c | 36 ++++++++++---------- 4 files changed, 68 insertions(+), 43 deletions(-) diff --git a/lustre/osd-ldiskfs/osd_compat.c b/lustre/osd-ldiskfs/osd_compat.c index 298ce2f..15c395f 100644 --- a/lustre/osd-ldiskfs/osd_compat.c +++ b/lustre/osd-ldiskfs/osd_compat.c @@ -66,27 +66,32 @@ static void osd_push_ctxt(const struct osd_device *dev, push_ctxt(save, newctxt); } -/** - * osd_lookup_one_len_unlocked - * - * @dev: obd device we are searching - * @name: pathname component to lookup - * @base: base directory to lookup from - * @len: maximum length @len should be interpreted to - * - * This should be called without the parent - * i_mutex held, and will take the i_mutex itself. - */ -struct dentry *osd_lookup_one_len_unlocked(struct osd_device *dev, - const char *name, - struct dentry *base, int len) +struct dentry *osd_lookup_one_len_common(struct osd_device *dev, + const char *name, + struct dentry *base, int len, + enum oi_check_flags flags) { struct dentry *dchild; - inode_lock(base->d_inode); - dchild = lookup_one_len(name, base, len); - inode_unlock(base->d_inode); - + /* + * We can't use inode_is_locked() directly since we can't know + * if the current thread context took the lock earlier or if + * another thread context took the lock. OI_LOCKED tells us + * if the current thread context has already taken the lock. + */ + if (!(flags & OI_LOCKED)) { + /* If another thread took this lock already we will + * just have to wait until the other thread is done. + */ + inode_lock(base->d_inode); + dchild = lookup_one_len(name, base, len); + inode_unlock(base->d_inode); + } else { + /* This thread context already has taken the lock. + * Other threads will have to wait until we are done. + */ + dchild = lookup_one_len(name, base, len); + } if (IS_ERR(dchild)) return dchild; @@ -102,17 +107,37 @@ struct dentry *osd_lookup_one_len_unlocked(struct osd_device *dev, } /** - * osd_ios_lookup_one_len - lookup single pathname component + * osd_lookup_one_len_unlocked + * + * @dev: obd device we are searching + * @name: pathname component to lookup + * @base: base directory to lookup from + * @len: maximum length @len should be interpreted to + * + * Unlike osd_lookup_one_len, this should be called without the parent + * i_mutex held, and will take the i_mutex itself. + */ +struct dentry *osd_lookup_one_len_unlocked(struct osd_device *dev, + const char *name, + struct dentry *base, int len) +{ + return osd_lookup_one_len_common(dev, name, base, len, ~OI_LOCKED); +} + +/** + * osd_lookup_one_len - lookup single pathname component * * @dev: obd device we are searching * @name: pathname component to lookup * @base: base directory to lookup from * @len: maximum length @len should be interpreted to + * + * The caller must hold inode lock */ -struct dentry *osd_ios_lookup_one_len(struct osd_device *dev, const char *name, - struct dentry *base, int len) +struct dentry *osd_lookup_one_len(struct osd_device *dev, const char *name, + struct dentry *base, int len) { - return osd_lookup_one_len_unlocked(dev, name, base, len); + return osd_lookup_one_len_common(dev, name, base, len, OI_LOCKED); } /* utility to make a directory */ diff --git a/lustre/osd-ldiskfs/osd_internal.h b/lustre/osd-ldiskfs/osd_internal.h index c76b2a0..fc9ab44 100644 --- a/lustre/osd-ldiskfs/osd_internal.h +++ b/lustre/osd-ldiskfs/osd_internal.h @@ -800,9 +800,8 @@ void osd_scrub_dump(struct seq_file *m, struct osd_device *dev); struct dentry *osd_lookup_one_len_unlocked(struct osd_device *dev, const char *name, struct dentry *base, int len); -struct dentry *osd_ios_lookup_one_len(struct osd_device *dev, - const char *name, - struct dentry *base, int len); +struct dentry *osd_lookup_one_len(struct osd_device *dev, const char *name, + struct dentry *base, int len); int osd_fld_lookup(const struct lu_env *env, struct osd_device *osd, u64 seq, struct lu_seq_range *range); diff --git a/lustre/osd-ldiskfs/osd_oi.h b/lustre/osd-ldiskfs/osd_oi.h index 697b81b..7e0c377 100644 --- a/lustre/osd-ldiskfs/osd_oi.h +++ b/lustre/osd-ldiskfs/osd_oi.h @@ -131,6 +131,7 @@ static inline int osd_id_eq_strict(const struct osd_inode_id *id0, enum oi_check_flags { OI_CHECK_FLD = 0x00000001, OI_KNOWN_ON_OST = 0x00000002, + OI_LOCKED = 0x00000004, }; extern unsigned int osd_oi_count; diff --git a/lustre/osd-ldiskfs/osd_scrub.c b/lustre/osd-ldiskfs/osd_scrub.c index adabfd3..31b01fa 100644 --- a/lustre/osd-ldiskfs/osd_scrub.c +++ b/lustre/osd-ldiskfs/osd_scrub.c @@ -2022,7 +2022,7 @@ static int osd_ios_lf_fill(void *buf, RETURN(0); scrub->os_lf_scanned++; - child = osd_ios_lookup_one_len(dev, name, parent, namelen); + child = osd_lookup_one_len_unlocked(dev, name, parent, namelen); if (IS_ERR(child)) { CDEBUG(D_LFSCK, "%s: cannot lookup child '%.*s': rc = %d\n", osd_name(dev), namelen, name, (int)PTR_ERR(child)); @@ -2096,8 +2096,8 @@ static int osd_ios_varfid_fill(void *buf, if (name[0] == '.') RETURN(0); - child = osd_ios_lookup_one_len(dev, name, fill_buf->oifb_dentry, - namelen); + child = osd_lookup_one_len_unlocked(dev, name, fill_buf->oifb_dentry, + namelen); if (IS_ERR(child)) RETURN(PTR_ERR(child)); @@ -2145,8 +2145,8 @@ static int osd_ios_dl_fill(void *buf, if (map->olm_name == NULL) RETURN(0); - child = osd_ios_lookup_one_len(dev, name, fill_buf->oifb_dentry, - namelen); + child = osd_lookup_one_len_unlocked(dev, name, fill_buf->oifb_dentry, + namelen); if (IS_ERR(child)) RETURN(PTR_ERR(child)); @@ -2180,8 +2180,8 @@ static int osd_ios_uld_fill(void *buf, if (name[0] != '[') RETURN(0); - child = osd_ios_lookup_one_len(dev, name, fill_buf->oifb_dentry, - namelen); + child = osd_lookup_one_len_unlocked(dev, name, fill_buf->oifb_dentry, + namelen); if (IS_ERR(child)) RETURN(PTR_ERR(child)); @@ -2231,8 +2231,8 @@ static int osd_ios_root_fill(void *buf, if (map->olm_name == NULL) RETURN(0); - child = osd_ios_lookup_one_len(dev, name, fill_buf->oifb_dentry, - namelen); + child = osd_lookup_one_len_unlocked(dev, name, fill_buf->oifb_dentry, + namelen); if (IS_ERR(child)) RETURN(PTR_ERR(child)); else if (!child->d_inode) @@ -2322,8 +2322,8 @@ osd_ios_ROOT_scan(struct osd_thread_info *info, struct osd_device *dev, * OI mapping crashed or lost also, then we have to give up under * double failure cases. */ scrub->os_convert_igif = 1; - child = osd_ios_lookup_one_len(dev, dot_lustre_name, dentry, - strlen(dot_lustre_name)); + child = osd_lookup_one_len_unlocked(dev, dot_lustre_name, dentry, + strlen(dot_lustre_name)); if (IS_ERR(child)) { if (PTR_ERR(child) != -ENOENT) RETURN(PTR_ERR(child)); @@ -2395,8 +2395,8 @@ osd_ios_OBJECTS_scan(struct osd_thread_info *info, struct osd_device *dev, RETURN(rc); } - child = osd_ios_lookup_one_len(dev, ADMIN_USR, dentry, - strlen(ADMIN_USR)); + child = osd_lookup_one_len_unlocked(dev, ADMIN_USR, dentry, + strlen(ADMIN_USR)); if (IS_ERR(child)) { rc = PTR_ERR(child); } else { @@ -2409,8 +2409,8 @@ osd_ios_OBJECTS_scan(struct osd_thread_info *info, struct osd_device *dev, if (rc != 0 && rc != -ENOENT) GOTO(out, rc); - child = osd_ios_lookup_one_len(dev, ADMIN_GRP, dentry, - strlen(ADMIN_GRP)); + child = osd_lookup_one_len_unlocked(dev, ADMIN_GRP, dentry, + strlen(ADMIN_GRP)); if (IS_ERR(child)) GOTO(out, rc = PTR_ERR(child)); @@ -2466,9 +2466,9 @@ static void osd_initial_OI_scrub(struct osd_thread_info *info, continue; } - child = osd_ios_lookup_one_len(dev, map->olm_name, - osd_sb(dev)->s_root, - map->olm_namelen); + child = osd_lookup_one_len_unlocked(dev, map->olm_name, + osd_sb(dev)->s_root, + map->olm_namelen); if (PTR_ERR(child) == -ENOENT || (!IS_ERR(child) && !child->d_inode)) osd_scrub_refresh_mapping(info, dev, &map->olm_fid, -- 1.8.3.1