struct dt_device *dev, struct thandle *txn);
int dt_txn_hook_stop(const struct lu_env *env, struct thandle *txn);
-int dt_try_as_dir(const struct lu_env *env, struct dt_object *obj);
+int dt_try_as_dir(const struct lu_env *env, struct dt_object *obj, bool check);
/**
* Callback function used for parsing path.
if (IS_ERR(root))
RETURN(PTR_ERR(root));
- if (unlikely(!dt_try_as_dir(env, root))) {
+ if (unlikely(!dt_try_as_dir(env, root, true))) {
lfsck_object_put(env, root);
RETURN(-ENOTDIR);
LASSERT(obj != NULL);
LASSERT(di == NULL);
- if (unlikely(!dt_try_as_dir(env, obj)))
+ if (unlikely(!dt_try_as_dir(env, obj, true)))
GOTO(out, rc = -ENOTDIR);
list_for_each_entry(com, &lfsck->li_list_dir, lc_link_dir) {
if (IS_ERR(root))
GOTO(out, rc = PTR_ERR(root));
- if (unlikely(!dt_try_as_dir(env, root)))
+ if (unlikely(!dt_try_as_dir(env, root, true)))
GOTO(out, rc = -ENOTDIR);
obj = local_file_find_or_create(env, lfsck->li_los, root,
if (rc != 0)
GOTO(stop, rc);
- if (!dt_try_as_dir(env, child))
+ if (!dt_try_as_dir(env, child, false))
GOTO(stop, rc = -ENOTDIR);
/* 2a. increase child nlink */
if (rc != 0)
GOTO(stop, rc);
- if (!dt_try_as_dir(env, child))
+ if (!dt_try_as_dir(env, child, false))
GOTO(stop, rc = -ENOTDIR);
/* 2a. increase child nlink */
if (IS_ERR(child))
GOTO(unlock, rc = PTR_ERR(child));
- if (dt_object_exists(child) != 0) {
- if (unlikely(!dt_try_as_dir(env, child)))
+ if (dt_object_exists(child)) {
+ if (unlikely(!dt_try_as_dir(env, child, true)))
rc = -ENOTDIR;
else
lfsck->li_lpf_obj = child;
if (IS_ERR(parent2))
GOTO(linkea, parent2);
- if (!dt_object_exists(parent2)) {
- lfsck_object_put(env, parent2);
-
- GOTO(linkea, parent2 = ERR_PTR(-ENOENT));
- }
-
- if (!dt_try_as_dir(env, parent2)) {
+ if (!dt_try_as_dir(env, parent2, true)) {
lfsck_object_put(env, parent2);
GOTO(linkea, parent2 = ERR_PTR(-ENOTDIR));
LASSERT(dt_object_exists(parent));
- if (unlikely(!dt_try_as_dir(env, parent))) {
+ if (unlikely(!dt_try_as_dir(env, parent, true))) {
lfsck_object_put(env, parent);
GOTO(put, rc = -ENOTDIR);
goto find_child1;
}
- if (unlikely(!dt_try_as_dir(env, child2)))
+ if (unlikely(!dt_try_as_dir(env, child2, true)))
GOTO(put, rc = -ENOTDIR);
find_child1:
goto check_child2;
}
- if (unlikely(!dt_try_as_dir(env, child1))) {
+ if (unlikely(!dt_try_as_dir(env, child1, true))) {
lfsck_object_put(env, child1);
child1 = NULL;
rc = -ENOTDIR;
put:
if (lfsck->li_lpf_obj != NULL) {
- if (unlikely(!dt_try_as_dir(env, lfsck->li_lpf_obj))) {
+ if (unlikely(!dt_try_as_dir(env, lfsck->li_lpf_obj, true))) {
lfsck_object_put(env, lfsck->li_lpf_obj);
lfsck->li_lpf_obj = NULL;
rc = -ENOTDIR;
return ERR_PTR(-ENOENT);
}
- if (lso->lso_is_dir && unlikely(!dt_try_as_dir(env, obj))) {
+ if (lso->lso_is_dir && unlikely(!dt_try_as_dir(env, obj, true))) {
lfsck_object_put(env, obj);
return ERR_PTR(-ENOTDIR);
if (rc != 0)
GOTO(out, rc);
- if (unlikely(!dt_try_as_dir(env, obj)))
- GOTO(out, rc = -ENOTDIR);
-
*pfid = *fid;
rc = dt_lookup_dir(env, obj, lostfound, fid);
if (rc != 0)
}
}
- if (unlikely(!dt_try_as_dir(env, parent)))
+ if (unlikely(!dt_try_as_dir(env, parent, true)))
GOTO(unlock, rc = -ENOTDIR);
th = lfsck_trans_create(env, dev, lfsck);
if (IS_ERR(parent))
GOTO(log, rc = PTR_ERR(parent));
- if (unlikely(!dt_try_as_dir(env, parent)))
+ if (unlikely(!dt_try_as_dir(env, parent, true)))
GOTO(log, rc = -ENOTDIR);
} else {
if (unlikely(lfsck->li_lpf_obj == NULL))
if (rc != 0)
GOTO(stop, rc);
- if (unlikely(!dt_try_as_dir(env, orphan)))
+ if (unlikely(!dt_try_as_dir(env, orphan, false)))
GOTO(stop, rc = -ENOTDIR);
rc = dt_declare_ref_add(env, orphan, th);
if (IS_ERR(parent))
GOTO(log, rc = PTR_ERR(parent));
- if (unlikely(!dt_try_as_dir(env, parent)))
+ if (unlikely(!dt_try_as_dir(env, parent, true)))
GOTO(log, rc = -ENOTDIR);
rc = lfsck_lock(env, lfsck, parent, name, pllh,
if (IS_ERR(parent))
GOTO(log, rc = PTR_ERR(parent));
- if (unlikely(!dt_try_as_dir(env, parent)))
+ if (unlikely(!dt_try_as_dir(env, parent, true)))
GOTO(log, rc = -ENOTDIR);
if (!update || strcmp(name, name2) == 0)
} /* !dt_object_exists(parent) */
/* The unique linkEA entry with bad parent will be handled as orphan. */
- if (unlikely(!dt_try_as_dir(env, parent))) {
+ if (unlikely(!dt_try_as_dir(env, parent, true))) {
if (!lustre_handle_is_used(lh) && retry != NULL)
*retry = true;
else
}
/* The linkEA entry with bad parent will be removed. */
- if (unlikely(!dt_try_as_dir(env, parent))) {
+ if (unlikely(!dt_try_as_dir(env, parent, true))) {
lfsck_object_put(env, parent);
lfsck_linkea_del_buf(ldata, cname);
continue;
RETURN(0);
}
- if (unlikely(!dt_try_as_dir(env, child)))
+ if (unlikely(!dt_try_as_dir(env, child, true)))
GOTO(out, rc = -ENOTDIR);
/* We only take ldlm lock on the @child when required. When the
} /* !dt_object_exists(parent) */
/* The linkEA entry with bad parent will be removed. */
- if (unlikely(!dt_try_as_dir(env, parent))) {
+ if (unlikely(!dt_try_as_dir(env, parent, true))) {
lfsck_object_put(env, parent);
rc = lfsck_namespace_shrink_linkea(env, com, child,
&ldata, cname, pfid, true);
if (IS_ERR(root))
GOTO(log, rc = PTR_ERR(root));
- if (unlikely(!dt_try_as_dir(env, root)))
+ if (unlikely(!dt_try_as_dir(env, root, true)))
GOTO(put, rc = -ENOTDIR);
down_write(&com->lc_sem);
if (IS_ERR(parent))
GOTO(log, rc = PTR_ERR(parent));
- if (unlikely(!dt_try_as_dir(env, parent)))
+ if (unlikely(!dt_try_as_dir(env, parent, true)))
GOTO(log, rc = -ENOTDIR);
child = lfsck_object_locate(dev, child);
GOTO(stop, rc);
if (S_ISDIR(type)) {
- if (unlikely(!dt_try_as_dir(env, child)))
+ if (unlikely(!dt_try_as_dir(env, child, false)))
GOTO(stop, rc = -ENOTDIR);
/* 2a. increase child nlink */
if (!dt_object_exists(parent))
GOTO(out, rc = 0);
- if (unlikely(!dt_try_as_dir(env, parent)))
+ if (unlikely(!dt_try_as_dir(env, parent, true)))
GOTO(out, rc = -ENOTDIR);
CDEBUG(D_LFSCK, "%s: start to scan backend /lost+found\n",
if (IS_ERR(root))
GOTO(out, rc = PTR_ERR(root));
- if (unlikely(!dt_try_as_dir(env, root)))
+ if (unlikely(!dt_try_as_dir(env, root, true)))
GOTO(out, rc = -ENOTDIR);
obj = local_index_find_or_create(env, lfsck->li_los, root,
__u16 type;
ENTRY;
- if (unlikely(!dt_try_as_dir(env, obj)))
+ if (unlikely(!dt_try_as_dir(env, obj, true)))
RETURN(-ENOTDIR);
/* Check whether the shard and the master MDT-object matches or not. */
if (lmv->lmv_magic != LMV_MAGIC_STRIPE)
RETURN(1);
- if (unlikely(!dt_try_as_dir(env, child)))
+ if (unlikely(!dt_try_as_dir(env, child, true)))
RETURN(-ENOTDIR);
OBD_ALLOC_PTR(llmv);
if (unlikely(!dt_object_exists(parent)))
GOTO(out, rc = 1);
- if (unlikely(!dt_try_as_dir(env, parent)))
+ if (unlikely(!dt_try_as_dir(env, parent, true)))
GOTO(out, rc = -ENOTDIR);
rc = lfsck_read_stripe_lmv(env, lfsck, parent, plmv);
memcpy(buf->lb_buf, tbuf.lb_buf, tbuf.lb_len);
}
- if (unlikely(!dt_try_as_dir(env, obj)))
+ if (unlikely(!dt_try_as_dir(env, obj, true)))
RETURN(-ENOTDIR);
memset(&lmv1->lmv_stripe_fids[0], 0, stripes * sizeof(struct lu_fid));
slave_lmv_buf.lb_buf = slave_lmm;
slave_lmv_buf.lb_len = sizeof(*slave_lmm);
- if (!dt_try_as_dir(env, dt_object_child(dt)))
+ if (!dt_try_as_dir(env, dt_object_child(dt), false))
GOTO(out, rc = -EINVAL);
rec->rec_type = S_IFDIR;
if (rc != 0)
GOTO(out, rc);
- if (!dt_try_as_dir(env, dto))
+ if (!dt_try_as_dir(env, dto, false))
GOTO(out, rc = -EINVAL);
rc = lod_sub_declare_ref_add(env, dto, th);
if (!lmv_is_sane(lmv))
RETURN(-EINVAL);
- if (!dt_try_as_dir(env, dt))
- return -ENOTDIR;
+ if (!dt_try_as_dir(env, dt, false))
+ RETURN(-ENOTDIR);
dof->dof_type = DFT_DIR;
stripes[i + lo->ldo_dir_stripe_count] = dto;
- if (!dt_try_as_dir(env, dto))
+ if (!dt_try_as_dir(env, dto, true))
GOTO(out, rc = -ENOTDIR);
rc = lod_sub_declare_ref_add(env, dto, th);
int i;
int rc = 0;
- if (!dt_try_as_dir(env, dt))
+ if (!dt_try_as_dir(env, dt, true))
return -ENOTDIR;
if (!lo->ldo_dir_stripe_count)
if (!dto)
continue;
- if (!dt_try_as_dir(env, dto))
+ if (!dt_try_as_dir(env, dto, true))
return -ENOTDIR;
rc = lod_sub_declare_delete(env, dto,
ENTRY;
- if (!dt_try_as_dir(env, obj))
+ if (!dt_try_as_dir(env, obj, true))
RETURN(-ENOTDIR);
iops = &obj->do_index_ops->dio_it;
LASSERT(lmu);
- if (!dt_try_as_dir(env, dt))
+ if (!dt_try_as_dir(env, dt, true))
return -ENOTDIR;
/* shouldn't be called on plain directory */
if (rc)
RETURN(rc);
- if (likely(S_ISDIR(mdd_object_type(mdd_obj)) &&
- dt_try_as_dir(env, dir)))
+ if (likely(dt_try_as_dir(env, dir, true)))
rc = dt_lookup(env, dir, (struct dt_rec *)fid, key);
else
rc = -ENOTDIR;
ENTRY;
obj = mdd_object_child(dir);
- if (!dt_try_as_dir(env, obj))
+ if (!dt_try_as_dir(env, obj, true))
RETURN(-ENOTDIR);
iops = &obj->do_index_ops->dio_it;
int rc;
ENTRY;
- if (dt_try_as_dir(env, next))
+ if (dt_try_as_dir(env, next, true))
rc = dt_delete(env, next, (struct dt_key *)name, handle);
else
rc = -ENOTDIR;
int rc;
ENTRY;
- if (dt_try_as_dir(env, next)) {
+ if (dt_try_as_dir(env, next, true)) {
struct dt_insert_rec *rec = &mdd_env_info(env)->mdi_dt_rec;
rec->rec_fid = lf;
*/
rc = -ENOTDIR;
- if (dt_try_as_dir(env, next)) {
+ if (dt_try_as_dir(env, next, false)) {
struct dt_insert_rec *rec = &mdd_env_info(env)->mdi_dt_rec;
rec->rec_fid = fid;
static inline
int mdo_declare_index_delete(const struct lu_env *env, struct mdd_object *obj,
- const char *name, struct thandle *handle)
+ const char *name, struct thandle *handle)
{
- struct dt_object *next = mdd_object_child(obj);
+ struct dt_object *next = mdd_object_child(obj);
- if (!dt_try_as_dir(env, next))
- return -ENOTDIR;
+ if (!dt_try_as_dir(env, next, true))
+ return -ENOTDIR;
- return dt_declare_delete(env, next, (const struct dt_key *)name,
- handle);
+ return dt_declare_delete(env, next, (const struct dt_key *)name,
+ handle);
}
static inline int mdo_declare_ref_add(const struct lu_env *env,
* no need check again.
*/
static int mdd_readpage_sanity_check(const struct lu_env *env,
- struct mdd_object *obj)
+ struct mdd_object *obj)
{
- struct dt_object *next = mdd_object_child(obj);
- int rc;
- ENTRY;
-
- if (S_ISDIR(mdd_object_type(obj)) && dt_try_as_dir(env, next))
- rc = 0;
- else
- rc = -ENOTDIR;
+ if (!dt_try_as_dir(env, mdd_object_child(obj), true))
+ return -ENOTDIR;
- RETURN(rc);
+ return 0;
}
static int mdd_dir_page_build(const struct lu_env *env, struct dt_object *obj,
GOTO(out, rc);
mdo_ref_add(env, obj, th);
+
if (!S_ISDIR(mdd_object_type(obj)))
GOTO(out, rc = 0);
dt_ref_add(env, mdd->mdd_orphans, th);
/* try best to fixup directory, do not return errors from here */
- if (!dt_try_as_dir(env, next))
+ if (!dt_try_as_dir(env, next, true))
GOTO(out, rc = 0);
dt_delete(env, next, (const struct dt_key *)dotdot, th);
if (IS_ERR(d))
RETURN(PTR_ERR(d));
LASSERT(lu_object_exists(&d->do_lu));
- if (!dt_try_as_dir(env, d)) {
+ if (!dt_try_as_dir(env, d, true)) {
CERROR("%s: orphan dir '%s' is not an index: rc = %d\n",
mdd2obd_dev(mdd)->obd_name, mdd_orphan_index_name, rc);
dt_object_put(env, d);
if (IS_ERR(o))
GOTO(out_root, rc = PTR_ERR(o));
- if (!dt_try_as_dir(env, o)) {
+ if (!dt_try_as_dir(env, o, true)) {
dt_object_put(env, o);
GOTO(out_root, rc = -ENOTDIR);
}
}
EXPORT_SYMBOL(dt_object_fini);
-int dt_try_as_dir(const struct lu_env *env, struct dt_object *obj)
+/**
+ * Set directory .do_index_ops.
+ *
+ * Set directory index operations, if the caller knows directory exists,
+ * \a check should be set to ensure object is directory and exists, while for
+ * new directories, skip check and the index operations will be used to create
+ * ".." under directory.
+ *
+ * Normally this is called before dt_lookup() to ensure directory objects
+ * exists and .do_index_ops is correctly set.
+ *
+ * \param env lu_env object.
+ * \param obj dt object.
+ * \param check check \a obj existence and type, return if index ops is set.
+ * \retval 1 on success.
+ * \retval 0 on error.
+ */
+int dt_try_as_dir(const struct lu_env *env, struct dt_object *obj, bool check)
{
- if (obj->do_index_ops == NULL)
- obj->do_ops->do_index_try(env, obj, &dt_directory_features);
+ if (check) {
+ if (unlikely(!dt_object_exists(obj)))
+ return 0;
+
+ if (unlikely(!S_ISDIR(lu_object_attr(&obj->do_lu))))
+ return 0;
+
+ if (obj->do_index_ops)
+ return 1;
+ }
+
+ obj->do_ops->do_index_try(env, obj, &dt_directory_features);
+
return obj->do_index_ops != NULL;
}
EXPORT_SYMBOL(dt_try_as_dir);
int dt_lookup_dir(const struct lu_env *env, struct dt_object *dir,
const char *name, struct lu_fid *fid)
{
- if (dt_try_as_dir(env, dir))
+ if (dt_try_as_dir(env, dir, true))
return dt_lookup(env, dir, (struct dt_rec *)fid,
(const struct dt_key *)name);
return -ENOTDIR;
return ERR_PTR(rc);
dir = dt_locate(env, dt, &dti->dti_fid);
- if (!IS_ERR(dir) && !dt_try_as_dir(env, dir)) {
+ if (!IS_ERR(dir) && !dt_try_as_dir(env, dir, true)) {
dt_object_put(env, dir);
return ERR_PTR(-ENOTDIR);
}
if (IS_ERR(dir))
RETURN(dir);
- if (!dt_try_as_dir(env, dir)) {
+ if (!dt_try_as_dir(env, dir, true)) {
dt_object_put(env, dir);
RETURN(ERR_PTR(-ENOTDIR));
}
GOTO(trans_stop, rc);
if (dti->dti_dof.dof_type == DFT_DIR) {
- if (!dt_try_as_dir(env, dto))
+ if (!dt_try_as_dir(env, dto, false))
GOTO(trans_stop, rc = -ENOTDIR);
rec->rec_type = S_IFDIR;
LASSERT(dt_object_exists(parent_obj));
- if (unlikely(!dt_try_as_dir(env, parent_obj)))
+ if (unlikely(!dt_try_as_dir(env, parent_obj, true)))
GOTO(out, rc = -ENOTDIR);
rc = dt_attr_get(env, tgt_obj, la);
if (IS_ERR(qt_dir))
GOTO(out, rc = PTR_ERR(qt_dir));
- if (!dt_try_as_dir(env, qt_dir))
+ if (!dt_try_as_dir(env, qt_dir, true))
GOTO(out, rc = -ENOTDIR);
EXIT;
out:
}
dt_read_lock(env, obj, DT_TGT_CHILD);
- if (!dt_try_as_dir(env, obj))
+ if (!dt_try_as_dir(env, obj, true))
GOTO(out_unlock, rc = -ENOTDIR);
rc = dt_lookup(env, obj, (struct dt_rec *)&tti->tti_fid1,
(char *)key, PFID(((struct dt_insert_rec *)rec)->rec_fid),
((struct dt_insert_rec *)rec)->rec_type);
- if (dt_try_as_dir(env, dt_obj) == 0)
+ if (!dt_try_as_dir(env, dt_obj, true))
return -ENOTDIR;
dt_write_lock(env, dt_obj, DT_TGT_CHILD);
dt_obd_name(th->th_dev), PFID(lu_object_fid(&dt_obj->do_lu)),
(char *)key);
- if (dt_try_as_dir(env, dt_obj) == 0)
+ if (!dt_try_as_dir(env, dt_obj, true))
return -ENOTDIR;
dt_write_lock(env, dt_obj, DT_TGT_CHILD);
struct tx_arg *arg;
int rc;
- if (dt_try_as_dir(env, dt_obj) == 0) {
- rc = -ENOTDIR;
- return rc;
- }
+ if (!dt_try_as_dir(env, dt_obj, false))
+ return -ENOTDIR;
rc = dt_declare_insert(env, dt_obj, rec, key, th);
if (rc != 0)
struct tx_arg *arg;
int rc;
- if (dt_try_as_dir(env, dt_obj) == 0) {
- rc = -ENOTDIR;
- return rc;
- }
+ if (!dt_try_as_dir(env, dt_obj, true))
+ return -ENOTDIR;
LASSERT(ta->ta_handle != NULL);
rc = dt_declare_delete(env, dt_obj, key, th);
RETURN(-EIO);
type = le32_to_cpu(*ptype);
- if (dt_try_as_dir(env, dt_obj) == 0)
+ if (!dt_try_as_dir(env, dt_obj, false))
RETURN(-ENOTDIR);
uti->uti_rec.rec_fid = fid;
if (name == NULL)
RETURN(-EIO);
- if (dt_try_as_dir(env, dt_obj) == 0)
+ if (!dt_try_as_dir(env, dt_obj, true))
RETURN(-ENOTDIR);
rc = out_tx_index_delete(env, dt_obj,