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;
}
/**
- * 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 */
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);
enum oi_check_flags {
OI_CHECK_FLD = 0x00000001,
OI_KNOWN_ON_OST = 0x00000002,
+ OI_LOCKED = 0x00000004,
};
extern unsigned int osd_oi_count;
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));
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));
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));
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));
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)
* 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));
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 {
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));
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,