Whamcloud - gitweb
LU-15902 obdclass: dt_try_as_dir() check dir exists 83/47483/7
authorLai Siyao <lai.siyao@whamcloud.com>
Thu, 19 May 2022 22:31:07 +0000 (18:31 -0400)
committerOleg Drokin <green@whamcloud.com>
Mon, 18 Jul 2022 20:24:59 +0000 (20:24 +0000)
If an object is not directory, but dt_lookup() is called on it, it
may crash because .do_lookup is NULL for non-directory file.

Add argument to check object existence and type in dt_try_as_dir(),
and for object to create, skip this check.

Signed-off-by: Lai Siyao <lai.siyao@whamcloud.com>
Change-Id: I51df0cbb5a4e7abca370ee27dac678f995b76159
Reviewed-on: https://review.whamcloud.com/47483
Tested-by: jenkins <devops@whamcloud.com>
Reviewed-by: John L. Hammond <jhammond@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
21 files changed:
lustre/include/dt_object.h
lustre/lfsck/lfsck_bookmark.c
lustre/lfsck/lfsck_engine.c
lustre/lfsck/lfsck_layout.c
lustre/lfsck/lfsck_lib.c
lustre/lfsck/lfsck_namespace.c
lustre/lfsck/lfsck_striped_dir.c
lustre/lod/lod_object.c
lustre/mdd/mdd_dir.c
lustre/mdd/mdd_internal.h
lustre/mdd/mdd_object.c
lustre/mdd/mdd_orphans.c
lustre/mgs/mgs_fs.c
lustre/obdclass/dt_object.c
lustre/obdclass/llog_osd.c
lustre/obdclass/local_storage.c
lustre/obdclass/scrub.c
lustre/quota/lquota_disk.c
lustre/target/out_handler.c
lustre/target/out_lib.c
lustre/target/update_recovery.c

index cb386cd..3009070 100644 (file)
@@ -2055,7 +2055,7 @@ int dt_txn_hook_start(const struct lu_env *env,
                       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.
index 0aa94fa..e8f1ec9 100644 (file)
@@ -166,7 +166,7 @@ int lfsck_bookmark_setup(const struct lu_env *env,
        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);
index d6fb21d..7487ea4 100644 (file)
@@ -350,7 +350,7 @@ int lfsck_open_dir(const struct lu_env *env,
        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) {
index 30d0c82..034f63a 100644 (file)
@@ -6978,7 +6978,7 @@ int lfsck_layout_setup(const struct lu_env *env, struct lfsck_instance *lfsck)
        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,
index 7e36a18..64da238 100644 (file)
@@ -697,7 +697,7 @@ static int lfsck_create_lpf_local(const struct lu_env *env,
        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 */
@@ -875,7 +875,7 @@ static int lfsck_create_lpf_remote(const struct lu_env *env,
        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 */
@@ -1077,8 +1077,8 @@ static int lfsck_create_lpf(const struct lu_env *env,
        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;
@@ -1293,13 +1293,7 @@ static int lfsck_verify_lpf_pairs(const struct lu_env *env,
        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));
@@ -1450,7 +1444,7 @@ int lfsck_verify_lpf(const struct lu_env *env, struct lfsck_instance *lfsck)
 
        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);
@@ -1499,7 +1493,7 @@ int lfsck_verify_lpf(const struct lu_env *env, struct lfsck_instance *lfsck)
                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:
@@ -1562,7 +1556,7 @@ 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;
@@ -1583,7 +1577,7 @@ check_child2:
 
 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;
@@ -2021,7 +2015,7 @@ lfsck_assistant_object_load(const struct lu_env *env,
                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);
@@ -3738,9 +3732,6 @@ int lfsck_register(const struct lu_env *env, struct dt_device *key,
                        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)
index df57d18..3bdcbe6 100644 (file)
@@ -1317,7 +1317,7 @@ static int lfsck_namespace_insert_normal(const struct lu_env *env,
                }
        }
 
-       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);
@@ -1480,7 +1480,7 @@ static int lfsck_namespace_create_orphan_dir(const struct lu_env *env,
                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))
@@ -1552,7 +1552,7 @@ again:
        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);
@@ -1954,7 +1954,7 @@ static int lfsck_namespace_replace_cond(const struct lu_env *env,
        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,
@@ -2226,7 +2226,7 @@ int lfsck_namespace_repair_dirent(const struct lu_env *env,
        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)
@@ -2657,7 +2657,7 @@ lost_parent:
        } /* !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
@@ -2913,7 +2913,7 @@ again:
                }
 
                /* 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;
@@ -3256,7 +3256,7 @@ static int lfsck_namespace_double_scan_dir(const struct lu_env *env,
                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
@@ -3861,7 +3861,7 @@ lost_parent:
                } /* !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);
@@ -4237,7 +4237,7 @@ static int lfsck_namespace_reset(const struct lu_env *env,
        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);
@@ -5323,7 +5323,7 @@ int lfsck_namespace_repair_dangling(const struct lu_env *env,
        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);
@@ -5395,7 +5395,7 @@ int lfsck_namespace_repair_dangling(const struct lu_env *env,
                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 */
@@ -6287,7 +6287,7 @@ static void lfsck_namespace_scan_local_lpf(const struct lu_env *env,
        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",
@@ -7122,7 +7122,7 @@ int lfsck_namespace_setup(const struct lu_env *env,
        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,
index 63a8754..493b42b 100644 (file)
@@ -1171,7 +1171,7 @@ static int lfsck_allow_regenerate_master_lmv(const struct lu_env *env,
        __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. */
@@ -1637,7 +1637,7 @@ int lfsck_namespace_scan_shard(const struct lu_env *env,
        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);
@@ -1782,7 +1782,7 @@ int lfsck_namespace_verify_stripe_slave(const struct lu_env *env,
        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);
index a2d36fa..9e7073b 100644 (file)
@@ -878,7 +878,7 @@ int lod_load_lmv_shards(const struct lu_env *env, struct lod_object *lo,
                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));
@@ -1930,7 +1930,7 @@ static int lod_dir_declare_create_stripes(const struct lu_env *env,
        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;
@@ -1952,7 +1952,7 @@ static int lod_dir_declare_create_stripes(const struct lu_env *env,
                        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);
@@ -8328,8 +8328,8 @@ static int lod_dir_declare_layout_attach(const struct lu_env *env,
        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;
 
@@ -8369,7 +8369,7 @@ static int lod_dir_declare_layout_attach(const struct lu_env *env,
 
                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);
@@ -8462,7 +8462,7 @@ static int lod_dir_declare_layout_detach(const struct lu_env *env,
        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)
@@ -8474,7 +8474,7 @@ static int lod_dir_declare_layout_detach(const struct lu_env *env,
                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,
@@ -8507,7 +8507,7 @@ static int dt_dir_is_empty(const struct lu_env *env,
 
        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;
@@ -8554,7 +8554,7 @@ static int lod_dir_declare_layout_shrink(const struct lu_env *env,
 
        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 */
index 1250bd1..1b83614 100644 (file)
@@ -101,8 +101,7 @@ __mdd_lookup(const struct lu_env *env, struct md_object *pobj,
        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;
@@ -369,7 +368,7 @@ int mdd_dir_is_empty(const struct lu_env *env, struct mdd_object *dir)
        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;
@@ -660,7 +659,7 @@ static int __mdd_index_delete_only(const struct lu_env *env, struct mdd_object *
        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;
@@ -677,7 +676,7 @@ static int __mdd_index_insert_only(const struct lu_env *env,
        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;
index 1986d27..daffa1c 100644 (file)
@@ -740,7 +740,7 @@ int mdo_declare_index_insert(const struct lu_env *env, struct mdd_object *obj,
         */
 
        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;
@@ -754,15 +754,15 @@ int mdo_declare_index_insert(const struct lu_env *env, struct mdd_object *obj,
 
 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,
index 7de1017..b58559a 100644 (file)
@@ -3577,18 +3577,12 @@ stop:
  * 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,
index 1dde5f3..e698390 100644 (file)
@@ -173,6 +173,7 @@ int mdd_orphan_insert(const struct lu_env *env, struct mdd_object *obj,
                GOTO(out, rc);
 
        mdo_ref_add(env, obj, th);
+
        if (!S_ISDIR(mdd_object_type(obj)))
                GOTO(out, rc = 0);
 
@@ -180,7 +181,7 @@ int mdd_orphan_insert(const struct lu_env *env, struct mdd_object *obj,
        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);
@@ -509,7 +510,7 @@ int mdd_orphan_index_init(const struct lu_env *env, struct mdd_device *mdd)
        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);
index 6d3a152..cdbad80 100644 (file)
@@ -150,7 +150,7 @@ int mgs_fs_setup(const struct lu_env *env, struct mgs_device *mgs)
        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);
        }
index 95f54b8..1d0a39c 100644 (file)
@@ -167,10 +167,38 @@ void dt_object_fini(struct dt_object *obj)
 }
 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);
@@ -211,7 +239,7 @@ EXPORT_SYMBOL(dt_mode_to_dft);
 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;
index 8354dd5..33b1133 100644 (file)
@@ -1247,7 +1247,7 @@ static struct dt_object *llog_osd_dir_get(const struct lu_env *env,
                        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);
                }
@@ -1454,7 +1454,7 @@ struct dt_object *llog_osd_get_regular_fid_dir(const struct lu_env *env,
        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));
        }
index 2e2a0c4..91518ac 100644 (file)
@@ -347,7 +347,7 @@ static struct dt_object *__local_file_create(const struct lu_env *env,
                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;
index d3d46b8..0a7b953 100644 (file)
@@ -1168,7 +1168,7 @@ int lustre_index_restore(const struct lu_env *env, struct dt_device *dev,
 
        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);
index bc71833..ac1b220 100644 (file)
@@ -202,7 +202,7 @@ struct dt_object *lquota_disk_dir_find_create(const struct lu_env *env,
        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:
index c09f221..f81a77a 100644 (file)
@@ -370,7 +370,7 @@ static int out_index_lookup(struct tgt_session_info *tsi)
        }
 
        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,
index 5a0c0da..05987a7 100644 (file)
@@ -1069,7 +1069,7 @@ static int out_obj_index_insert(const struct lu_env *env,
               (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);
@@ -1090,7 +1090,7 @@ static int out_obj_index_delete(const struct lu_env *env,
               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);
@@ -1140,10 +1140,8 @@ int out_index_insert_add_exec(const struct lu_env *env,
        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)
@@ -1202,10 +1200,8 @@ int out_index_delete_add_exec(const struct lu_env *env,
        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);
index b483a26..95e28b7 100644 (file)
@@ -948,7 +948,7 @@ static int update_recovery_index_insert(const struct lu_env *env,
                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;
@@ -982,7 +982,7 @@ static int update_recovery_index_delete(const struct lu_env *env,
        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,