Whamcloud - gitweb
LU-11956 mdd: do not reset original lu_buf.lb_len
[fs/lustre-release.git] / lustre / mdd / mdd_dir.c
index 59072c5..d069874 100644 (file)
@@ -43,6 +43,7 @@
 #include <lustre_mds.h>
 #include <lustre_fid.h>
 #include <lustre_lmv.h>
+#include <lustre_idmap.h>
 
 #include "mdd_internal.h"
 
@@ -91,7 +92,7 @@ __mdd_lookup(const struct lu_env *env, struct md_object *pobj,
        }
 
        rc = mdd_permission_internal_locked(env, mdd_obj, pattr, mask,
-                                           MOR_TGT_PARENT);
+                                           DT_TGT_PARENT);
        if (rc)
                RETURN(rc);
 
@@ -219,7 +220,10 @@ static inline int mdd_parent_fid(const struct lu_env *env,
 
        ENTRY;
 
-       LASSERT(S_ISDIR(mdd_object_type(obj)));
+       LASSERTF(S_ISDIR(mdd_object_type(obj)),
+                "%s: FID "DFID" is not a directory type = %o\n",
+                mdd_obj_dev_name(obj), PFID(mdd_object_fid(obj)),
+                mdd_object_type(obj));
 
        buf = lu_buf_check_and_alloc(buf, PATH_MAX);
        if (buf->lb_buf == NULL)
@@ -381,8 +385,12 @@ static int mdd_dir_is_empty(const struct lu_env *env,
 
                iops->put(env, it);
                iops->fini(env, it);
-       } else
+       } else {
                result = PTR_ERR(it);
+               /* -ENODEV means no valid stripe */
+               if (result == -ENODEV)
+                       RETURN(0);
+       }
        RETURN(result);
 }
 
@@ -446,7 +454,7 @@ int mdd_may_create(const struct lu_env *env, struct mdd_object *pobj,
        if (check_perm)
                rc = mdd_permission_internal_locked(env, pobj, pattr,
                                                    MAY_WRITE | MAY_EXEC,
-                                                   MOR_TGT_PARENT);
+                                                   DT_TGT_PARENT);
        RETURN(rc);
 }
 
@@ -467,7 +475,7 @@ int mdd_may_unlink(const struct lu_env *env, struct mdd_object *pobj,
 
        rc = mdd_permission_internal_locked(env, pobj, pattr,
                                            MAY_WRITE | MAY_EXEC,
-                                           MOR_TGT_PARENT);
+                                           DT_TGT_PARENT);
        if (rc != 0)
                RETURN(rc);
 
@@ -521,7 +529,7 @@ static int mdd_may_delete_entry(const struct lu_env *env,
                int rc;
                rc = mdd_permission_internal_locked(env, pobj, pattr,
                                            MAY_WRITE | MAY_EXEC,
-                                           MOR_TGT_PARENT);
+                                           DT_TGT_PARENT);
                if (rc)
                        RETURN(rc);
        }
@@ -687,7 +695,7 @@ static int __mdd_index_insert(const struct lu_env *env, struct mdd_object *pobj,
 
        rc = __mdd_index_insert_only(env, pobj, lf, type, name, handle);
        if (rc == 0 && S_ISDIR(type)) {
-               mdd_write_lock(env, pobj, MOR_TGT_PARENT);
+               mdd_write_lock(env, pobj, DT_TGT_PARENT);
                mdo_ref_add(env, pobj, handle);
                mdd_write_unlock(env, pobj);
        }
@@ -700,17 +708,17 @@ static int __mdd_index_delete(const struct lu_env *env, struct mdd_object *pobj,
                              const char *name, int is_dir,
                              struct thandle *handle)
 {
-        int               rc;
-        ENTRY;
+       int rc;
+       ENTRY;
 
        rc = __mdd_index_delete_only(env, pobj, name, handle);
-        if (rc == 0 && is_dir) {
-                mdd_write_lock(env, pobj, MOR_TGT_PARENT);
-                mdo_ref_del(env, pobj, handle);
-                mdd_write_unlock(env, pobj);
-        }
+       if (rc == 0 && is_dir) {
+               mdd_write_lock(env, pobj, DT_TGT_PARENT);
+               mdo_ref_del(env, pobj, handle);
+               mdd_write_unlock(env, pobj);
+       }
 
-        RETURN(rc);
+       RETURN(rc);
 }
 
 static int mdd_llog_record_calc_size(const struct lu_env *env,
@@ -718,17 +726,17 @@ static int mdd_llog_record_calc_size(const struct lu_env *env,
                                     const struct lu_name *sname)
 {
        const struct lu_ucred   *uc = lu_ucred(env);
-       enum changelog_rec_flags crf = CLF_EXTRA_FLAGS;
+       enum changelog_rec_flags clf_flags = CLF_EXTRA_FLAGS;
        enum changelog_rec_extra_flags crfe = CLFE_UIDGID | CLFE_NID;
 
        if (sname != NULL)
-               crf |= CLF_RENAME;
+               clf_flags |= CLF_RENAME;
 
        if (uc != NULL && uc->uc_jobid[0] != '\0')
-               crf |= CLF_JOBID;
+               clf_flags |= CLF_JOBID;
 
        return llog_data_len(LLOG_CHANGELOG_HDR_SZ +
-                            changelog_rec_offset(crf, crfe) +
+                            changelog_rec_offset(clf_flags, crfe) +
                             (tname != NULL ? tname->ln_namelen : 0) +
                             (sname != NULL ? 1 + sname->ln_namelen : 0));
 }
@@ -911,17 +919,17 @@ void mdd_changelog_rec_extra_nid(struct changelog_rec *rec,
        clnid->cr_nid = nid;
 }
 
-void mdd_changelog_rec_extra_omode(struct changelog_rec *rec, int flags)
+void mdd_changelog_rec_extra_omode(struct changelog_rec *rec, u32 flags)
 {
        struct changelog_ext_openmode *omd = changelog_rec_openmode(rec);
 
-       omd->cr_openflags = (__u32)flags;
+       omd->cr_openflags = flags;
 }
 
 void mdd_changelog_rec_extra_xattr(struct changelog_rec *rec,
                                   const char *xattr_name)
 {
-       struct changelog_ext_xattr    *xattr = changelog_rec_xattr(rec);
+       struct changelog_ext_xattr *xattr = changelog_rec_xattr(rec);
 
        strlcpy(xattr->cr_xattr, xattr_name, sizeof(xattr->cr_xattr));
 }
@@ -940,7 +948,7 @@ void mdd_changelog_rec_extra_xattr(struct changelog_rec *rec,
 int mdd_changelog_ns_store(const struct lu_env *env,
                           struct mdd_device *mdd,
                           enum changelog_rec_type type,
-                          enum changelog_rec_flags crf,
+                          enum changelog_rec_flags clf_flags,
                           struct mdd_object *target,
                           const struct lu_fid *tpfid,
                           const struct lu_fid *sfid,
@@ -970,24 +978,24 @@ int mdd_changelog_ns_store(const struct lu_env *env,
                RETURN(-ENOMEM);
        rec = buf->lb_buf;
 
-       crf &= CLF_FLAGMASK;
-       crf |= CLF_EXTRA_FLAGS;
+       clf_flags &= CLF_FLAGMASK;
+       clf_flags |= CLF_EXTRA_FLAGS;
 
        if (uc) {
                if (uc->uc_jobid[0] != '\0')
-                       crf |= CLF_JOBID;
+                       clf_flags |= CLF_JOBID;
                xflags |= CLFE_UIDGID;
                xflags |= CLFE_NID;
        }
 
        if (sname != NULL)
-               crf |= CLF_RENAME;
+               clf_flags |= CLF_RENAME;
        else
-               crf |= CLF_VERSION;
+               clf_flags |= CLF_VERSION;
 
-       rec->cr.cr_flags = crf;
+       rec->cr.cr_flags = clf_flags;
 
-       if (crf & CLF_EXTRA_FLAGS) {
+       if (clf_flags & CLF_EXTRA_FLAGS) {
                mdd_changelog_rec_ext_extra_flags(&rec->cr, xflags);
                if (xflags & CLFE_UIDGID)
                        mdd_changelog_rec_extra_uidgid(&rec->cr,
@@ -1001,10 +1009,10 @@ int mdd_changelog_ns_store(const struct lu_env *env,
        rec->cr.cr_namelen = tname->ln_namelen;
        memcpy(changelog_rec_name(&rec->cr), tname->ln_name, tname->ln_namelen);
 
-       if (crf & CLF_RENAME)
+       if (clf_flags & CLF_RENAME)
                mdd_changelog_rec_ext_rename(&rec->cr, sfid, spfid, sname);
 
-       if (crf & CLF_JOBID)
+       if (clf_flags & CLF_JOBID)
                mdd_changelog_rec_ext_jobid(&rec->cr, uc->uc_jobid);
 
        if (likely(target != NULL)) {
@@ -1389,7 +1397,7 @@ static int mdd_link(const struct lu_env *env, struct md_object *tgt_obj,
         if (rc)
                 GOTO(stop, rc);
 
-       mdd_write_lock(env, mdd_sobj, MOR_TGT_CHILD);
+       mdd_write_lock(env, mdd_sobj, DT_TGT_CHILD);
        rc = mdd_link_sanity_check(env, mdd_tobj, tattr, lname, mdd_sobj,
                                   cattr);
        if (rc)
@@ -1448,9 +1456,6 @@ static int mdd_mark_orphan_object(const struct lu_env *env,
        struct lu_attr *attr = MDD_ENV_VAR(env, la_for_start);
        int rc;
 
-       if (!S_ISDIR(mdd_object_type(obj)))
-               return 0;
-
        attr->la_valid = LA_FLAGS;
        attr->la_flags = LUSTRE_ORPHAN_FL;
 
@@ -1708,7 +1713,7 @@ static int mdd_unlink(const struct lu_env *env, struct md_object *pobj,
                GOTO(stop, rc);
 
        if (likely(mdd_cobj != NULL))
-               mdd_write_lock(env, mdd_cobj, MOR_TGT_CHILD);
+               mdd_write_lock(env, mdd_cobj, DT_TGT_CHILD);
 
        if (likely(no_name == 0) && !OBD_FAIL_CHECK(OBD_FAIL_LFSCK_DANGLING2)) {
                rc = __mdd_index_delete(env, mdd_pobj, name, is_dir, handle);
@@ -2017,8 +2022,7 @@ static int mdd_create_sanity_check(const struct lu_env *env,
            spec->u.sp_ea.eadata != NULL && spec->u.sp_ea.eadatalen > 0) {
                const struct lmv_user_md *lum = spec->u.sp_ea.eadata;
 
-               if (le32_to_cpu(lum->lum_magic) != LMV_USER_MAGIC &&
-                   le32_to_cpu(lum->lum_magic) != LMV_USER_MAGIC_SPECIFIC &&
+               if (!lmv_magic_supported(le32_to_cpu(lum->lum_magic)) &&
                    le32_to_cpu(lum->lum_magic) != LMV_USER_MAGIC_V0) {
                        rc = -EINVAL;
                        CERROR("%s: invalid lmv_user_md: magic = %x, "
@@ -2035,12 +2039,24 @@ static int mdd_create_sanity_check(const struct lu_env *env,
        if (rc != 0)
                RETURN(rc);
 
-        /* sgid check */
+       /* sgid check */
        if (pattr->la_mode & S_ISGID) {
+               struct lu_ucred *uc = lu_ucred(env);
+
                cattr->la_gid = pattr->la_gid;
+
+               /* Directories are special, and always inherit S_ISGID */
                if (S_ISDIR(cattr->la_mode)) {
                        cattr->la_mode |= S_ISGID;
                        cattr->la_valid |= LA_MODE;
+               } else if ((cattr->la_mode & (S_ISGID | S_IXGRP))
+                               == (S_ISGID | S_IXGRP) &&
+                          !lustre_in_group_p(uc,
+                                             (cattr->la_valid & LA_GID) ?
+                                             cattr->la_gid : pattr->la_gid) &&
+                          !md_capable(uc, CFS_CAP_FSETID)) {
+                       cattr->la_mode &= ~S_ISGID;
+                       cattr->la_valid |= LA_MODE;
                }
        }
 
@@ -2090,6 +2106,7 @@ static int mdd_declare_create_object(const struct lu_env *env,
                                     const struct md_op_spec *spec,
                                     struct lu_buf *def_acl_buf,
                                     struct lu_buf *acl_buf,
+                                    struct lu_buf *hsm_buf,
                                     struct dt_allocation_hint *hint)
 {
        const struct lu_buf *buf;
@@ -2100,7 +2117,7 @@ static int mdd_declare_create_object(const struct lu_env *env,
        if (rc)
                GOTO(out, rc);
 
-#ifdef CONFIG_FS_POSIX_ACL
+#ifdef CONFIG_LUSTRE_FS_POSIX_ACL
        if (def_acl_buf && def_acl_buf->lb_len > 0 && S_ISDIR(attr->la_mode)) {
                /* if dir, then can inherit default ACl */
                rc = mdo_declare_xattr_set(env, c, def_acl_buf,
@@ -2136,6 +2153,14 @@ static int mdd_declare_create_object(const struct lu_env *env,
                                           0, handle);
                if (rc)
                        GOTO(out, rc);
+
+               if (spec->sp_cr_flags & MDS_OPEN_PCC) {
+                       rc = mdo_declare_xattr_set(env, c, hsm_buf,
+                                                  XATTR_NAME_HSM,
+                                                  0, handle);
+                       if (rc)
+                               GOTO(out, rc);
+               }
        }
 
        if (S_ISLNK(attr->la_mode)) {
@@ -2172,12 +2197,13 @@ static int mdd_declare_create(const struct lu_env *env, struct mdd_device *mdd,
                              struct linkea_data *ldata,
                              struct lu_buf *def_acl_buf,
                              struct lu_buf *acl_buf,
+                             struct lu_buf *hsm_buf,
                              struct dt_allocation_hint *hint)
 {
        int rc;
 
        rc = mdd_declare_create_object(env, mdd, p, c, attr, handle, spec,
-                                      def_acl_buf, acl_buf, hint);
+                                      def_acl_buf, acl_buf, hsm_buf, hint);
        if (rc)
                GOTO(out, rc);
 
@@ -2236,7 +2262,7 @@ static int mdd_acl_init(const struct lu_env *env, struct mdd_object *pobj,
                RETURN(0);
        }
 
-       mdd_read_lock(env, pobj, MOR_TGT_PARENT);
+       mdd_read_lock(env, pobj, DT_TGT_PARENT);
        rc = mdo_xattr_get(env, pobj, def_acl_buf,
                           XATTR_NAME_ACL_DEFAULT);
        mdd_read_unlock(env, pobj);
@@ -2272,13 +2298,14 @@ static int mdd_create_object(const struct lu_env *env, struct mdd_object *pobj,
                             struct mdd_object *son, struct lu_attr *attr,
                             struct md_op_spec *spec, struct lu_buf *acl_buf,
                             struct lu_buf *def_acl_buf,
+                            struct lu_buf *hsm_buf,
                             struct dt_allocation_hint *hint,
                             struct thandle *handle)
 {
        const struct lu_buf *buf;
        int rc;
 
-       mdd_write_lock(env, son, MOR_TGT_CHILD);
+       mdd_write_lock(env, son, DT_TGT_CHILD);
        rc = mdd_create_object_internal(env, NULL, son, attr, handle, spec,
                                        hint);
        if (rc)
@@ -2320,7 +2347,20 @@ static int mdd_create_object(const struct lu_env *env, struct mdd_object *pobj,
                        GOTO(err_destroy, rc);
        }
 
-#ifdef CONFIG_FS_POSIX_ACL
+       if (S_ISREG(attr->la_mode) && spec->sp_cr_flags & MDS_OPEN_PCC) {
+               struct md_hsm mh;
+
+               memset(&mh, 0, sizeof(mh));
+               mh.mh_flags = HS_EXISTS | HS_ARCHIVED | HS_RELEASED;
+               mh.mh_arch_id = spec->sp_archive_id;
+               lustre_hsm2buf(hsm_buf->lb_buf, &mh);
+               rc = mdo_xattr_set(env, son, hsm_buf, XATTR_NAME_HSM,
+                                  0, handle);
+               if (rc != 0)
+                       GOTO(err_destroy, rc);
+       }
+
+#ifdef CONFIG_LUSTRE_FS_POSIX_ACL
        if (def_acl_buf != NULL && def_acl_buf->lb_len > 0 &&
            S_ISDIR(attr->la_mode)) {
                /* set default acl */
@@ -2468,7 +2508,7 @@ stop:
  * \retval             0 on success
  * \retval             negative errno on failure
  */
-static int mdd_create(const struct lu_env *env, struct md_object *pobj,
+int mdd_create(const struct lu_env *env, struct md_object *pobj,
                      const struct lu_name *lname, struct md_object *child,
                      struct md_op_spec *spec, struct md_attr *ma)
 {
@@ -2482,6 +2522,7 @@ static int mdd_create(const struct lu_env *env, struct md_object *pobj,
        struct lu_attr          *pattr = &info->mti_pattr;
        struct lu_buf           acl_buf;
        struct lu_buf           def_acl_buf;
+       struct lu_buf           hsm_buf;
        struct linkea_data      *ldata = &info->mti_link_data;
        const char              *name = lname->ln_name;
        struct dt_allocation_hint *hint = &mdd_env_info(env)->mti_hint;
@@ -2506,7 +2547,7 @@ static int mdd_create(const struct lu_env *env, struct md_object *pobj,
                GOTO(out_free, rc = PTR_ERR(handle));
 
        lu_buf_check_and_alloc(&info->mti_xattr_buf,
-                              mdd->mdd_dt_conf.ddp_max_ea_size);
+                       MIN(mdd->mdd_dt_conf.ddp_max_ea_size, XATTR_SIZE_MAX));
        acl_buf = info->mti_xattr_buf;
        def_acl_buf.lb_buf = info->mti_key;
        def_acl_buf.lb_len = sizeof(info->mti_key);
@@ -2543,9 +2584,18 @@ static int mdd_create(const struct lu_env *env, struct md_object *pobj,
                                        lname, 1, 0, ldata);
        }
 
+       if (spec->sp_cr_flags & MDS_OPEN_PCC) {
+               LASSERT(spec->sp_cr_flags & MDS_OPEN_HAS_EA);
+
+               memset(&hsm_buf, 0, sizeof(hsm_buf));
+               lu_buf_alloc(&hsm_buf, sizeof(struct hsm_attrs));
+               if (hsm_buf.lb_buf == NULL)
+                       GOTO(out_stop, rc = -ENOMEM);
+       }
+
        rc = mdd_declare_create(env, mdd, mdd_pobj, son, lname, attr,
                                handle, spec, ldata, &def_acl_buf, &acl_buf,
-                               hint);
+                               &hsm_buf, hint);
        if (rc)
                GOTO(out_stop, rc);
 
@@ -2554,12 +2604,12 @@ static int mdd_create(const struct lu_env *env, struct md_object *pobj,
                GOTO(out_stop, rc);
 
        rc = mdd_create_object(env, mdd_pobj, son, attr, spec, &acl_buf,
-                              &def_acl_buf, hint, handle);
+                              &def_acl_buf, &hsm_buf, hint, handle);
        if (rc != 0)
                GOTO(out_stop, rc);
 
        if (unlikely(spec->sp_cr_flags & MDS_OPEN_VOLATILE)) {
-               mdd_write_lock(env, son, MOR_TGT_CHILD);
+               mdd_write_lock(env, son, DT_TGT_CHILD);
                son->mod_flags |= VOLATILE_OBJ;
                rc = mdd_orphan_insert(env, son, handle);
                GOTO(out_volatile, rc);
@@ -2593,7 +2643,7 @@ err_insert:
                        goto out_stop;
 
 err_created:
-               mdd_write_lock(env, son, MOR_TGT_CHILD);
+               mdd_write_lock(env, son, DT_TGT_CHILD);
                if (S_ISDIR(attr->la_mode)) {
                        /* Drop the reference, no need to delete "."/"..",
                         * because the object is to be destroyed directly. */
@@ -2645,6 +2695,9 @@ out_free:
                /* if we vmalloced a large buffer drop it */
                lu_buf_free(ldata->ld_buf);
 
+       if (spec->sp_cr_flags & MDS_OPEN_PCC)
+               lu_buf_free(&hsm_buf);
+
        /* The child object shouldn't be cached anymore */
        if (rc)
                set_bit(LU_OBJECT_HEARD_BANSHEE,
@@ -3007,7 +3060,7 @@ static int mdd_rename(const struct lu_env *env,
                GOTO(fixup_tpobj, rc);
 
        /* Update the linkEA for the source object */
-       mdd_write_lock(env, mdd_sobj, MOR_SRC_CHILD);
+       mdd_write_lock(env, mdd_sobj, DT_SRC_CHILD);
        rc = mdd_links_rename(env, mdd_sobj, mdo2fid(mdd_spobj), lsname,
                              mdo2fid(mdd_tpobj), ltname, handle, ldata,
                              0, 0);
@@ -3026,7 +3079,7 @@ static int mdd_rename(const struct lu_env *env,
          * it must be local one.
          */
         if (tobj && mdd_object_exists(mdd_tobj)) {
-                mdd_write_lock(env, mdd_tobj, MOR_TGT_CHILD);
+               mdd_write_lock(env, mdd_tobj, DT_TGT_CHILD);
                tobj_locked = 1;
                 if (mdd_is_dead_obj(mdd_tobj)) {
                         /* shld not be dead, something is wrong */
@@ -3197,7 +3250,7 @@ static int mdd_migrate_sanity_check(const struct lu_env *env,
        ENTRY;
 
        if (!mdd_object_remote(sobj)) {
-               mdd_read_lock(env, sobj, MOR_SRC_CHILD);
+               mdd_read_lock(env, sobj, DT_SRC_CHILD);
                if (sobj->mod_count > 0) {
                        CDEBUG(D_INFO, "%s: "DFID" is opened, count %d\n",
                               mdd2obd_dev(mdd)->obd_name, PFID(mdo2fid(sobj)),
@@ -3281,7 +3334,7 @@ static int mdd_dir_delete_stripe(const struct lu_env *env,
        if (index < del_offset)
                RETURN(0);
 
-       mdd_write_lock(env, stripe, MOR_SRC_CHILD);
+       mdd_write_lock(env, stripe, DT_SRC_CHILD);
        rc = __mdd_index_delete_only(env, stripe, dotdot, handle);
        if (rc)
                GOTO(out, rc);
@@ -3372,7 +3425,7 @@ static int mdd_dir_destroy_stripe(const struct lu_env *env,
                RETURN(rc);
        }
 
-       mdd_write_lock(env, stripe, MOR_SRC_CHILD);
+       mdd_write_lock(env, stripe, DT_SRC_CHILD);
        rc = mdo_ref_del(env, stripe, handle);
        if (!rc)
                rc = mdo_destroy(env, stripe, handle);
@@ -3426,6 +3479,9 @@ static int mdd_dir_iterate_stripes(const struct lu_env *env,
 
        for (i = 0; i < le32_to_cpu(lmv->lmv_stripe_count); i++) {
                fid_le_to_cpu(fid, &lmv->lmv_stripe_fids[i]);
+               if (!fid_is_sane(fid))
+                       continue;
+
                stripe = mdd_object_find(env, mdd, fid);
                if (IS_ERR(stripe))
                        RETURN(PTR_ERR(stripe));
@@ -3456,6 +3512,7 @@ static int mdd_iterate_xattrs(const struct lu_env *env,
        struct mdd_thread_info *info = mdd_env_info(env);
        char *xname;
        struct lu_buf list_xbuf;
+       struct lu_buf cbxbuf;
        struct lu_buf xbuf = { NULL };
        int list_xsize;
        int xlen;
@@ -3512,14 +3569,15 @@ static int mdd_iterate_xattrs(const struct lu_env *env,
                if (rc < 0)
                        GOTO(out, rc);
 
+               cbxbuf = xbuf;
 repeat:
-               rc = cb(env, tobj, &xbuf, xname, 0, handle);
+               rc = cb(env, tobj, &cbxbuf, xname, 0, handle);
                if (unlikely(rc == -ENOSPC &&
                             strcmp(xname, XATTR_NAME_LINK) == 0)) {
                        rc = linkea_overflow_shrink(
-                                       (struct linkea_data *)(xbuf.lb_buf));
+                                       (struct linkea_data *)(cbxbuf.lb_buf));
                        if (likely(rc > 0)) {
-                               xbuf.lb_len = rc;
+                               cbxbuf.lb_len = rc;
                                goto repeat;
                        }
                }
@@ -3626,7 +3684,7 @@ static int mdd_update_link(const struct lu_env *env,
                RETURN(-ENOENT);
        }
 
-       mdd_write_lock(env, pobj, MOR_TGT_PARENT);
+       mdd_write_lock(env, pobj, DT_TGT_PARENT);
        rc = __mdd_index_delete_only(env, pobj, lname->ln_name, handle);
        if (!rc)
                rc = __mdd_index_insert_only(env, pobj, mdo2fid(tobj),
@@ -3637,13 +3695,13 @@ static int mdd_update_link(const struct lu_env *env,
        if (rc)
                RETURN(rc);
 
-       mdd_write_lock(env, tobj, MOR_TGT_CHILD);
+       mdd_write_lock(env, tobj, DT_TGT_CHILD);
        rc = mdo_ref_add(env, tobj, handle);
        mdd_write_unlock(env, tobj);
        if (rc)
                RETURN(rc);
 
-       mdd_write_lock(env, sobj, MOR_SRC_CHILD);
+       mdd_write_lock(env, sobj, DT_SRC_CHILD);
        rc = mdo_ref_del(env, sobj, handle);
        mdd_write_unlock(env, sobj);
 
@@ -3825,7 +3883,7 @@ static int mdd_dir_layout_delete(const struct lu_env *env,
 
        ENTRY;
 
-       mdd_write_lock(env, obj, MOR_SRC_PARENT);
+       mdd_write_lock(env, obj, DT_SRC_PARENT);
        if (!lmv_buf->lb_buf)
                /* normal dir */
                rc = __mdd_index_delete_only(env, obj, dotdot, handle);
@@ -3883,7 +3941,7 @@ static int mdd_declare_migrate_create(const struct lu_env *env,
 
        rc = mdd_declare_create(env, mdo2mdd(&tpobj->mod_obj), tpobj, tobj,
                                lname, attr, handle, spec, ldata, NULL, NULL,
-                               hint);
+                               NULL, hint);
        if (rc)
                return rc;
 
@@ -3931,18 +3989,19 @@ static int mdd_declare_migrate_create(const struct lu_env *env,
                return rc;
 
        if (S_ISREG(attr->la_mode)) {
+               struct lu_buf fid_buf;
+
                handle->th_complex = 1;
 
-               rc = mdo_declare_xattr_del(env, sobj, XATTR_NAME_LOV, handle);
+               /* target may be remote, update PFID via sobj. */
+               fid_buf.lb_buf = (void *)mdo2fid(tobj);
+               fid_buf.lb_len = sizeof(struct lu_fid);
+               rc = mdo_declare_xattr_set(env, sobj, &fid_buf, XATTR_NAME_FID,
+                                          0, handle);
                if (rc)
                        return rc;
 
-               /*
-                * target is not initalized because its LOV is copied from
-                * source in mdd_migrate_create(), declare via sobj.
-                */
-               rc = mdo_declare_xattr_set(env, sobj, NULL, XATTR_NAME_FID, 0,
-                                          handle);
+               rc = mdo_declare_xattr_del(env, sobj, XATTR_NAME_LOV, handle);
                if (rc)
                        return rc;
        }
@@ -4030,7 +4089,7 @@ static int mdd_migrate_create(const struct lu_env *env,
                 * stripes again.
                 */
                if (sbuf->lb_buf) {
-                       mdd_write_lock(env, sobj, MOR_SRC_CHILD);
+                       mdd_write_lock(env, sobj, DT_SRC_CHILD);
                        rc = mdo_xattr_del(env, sobj, XATTR_NAME_LMV, handle);
                        mdd_write_unlock(env, sobj);
                        if (rc)
@@ -4041,27 +4100,33 @@ static int mdd_migrate_create(const struct lu_env *env,
        /* don't set nlink from sobj */
        attr->la_valid &= ~LA_NLINK;
 
-       rc = mdd_create_object(env, tpobj, tobj, attr, spec, NULL, NULL, hint,
-                               handle);
+       rc = mdd_create_object(env, tpobj, tobj, attr, spec, NULL, NULL, NULL,
+                              hint, handle);
        if (rc)
                RETURN(rc);
 
-       mdd_write_lock(env, tobj, MOR_TGT_CHILD);
+       mdd_write_lock(env, tobj, DT_TGT_CHILD);
        rc = mdd_iterate_xattrs(env, sobj, tobj, true, handle, mdo_xattr_set);
        mdd_write_unlock(env, tobj);
        if (rc)
                RETURN(rc);
 
+       /* for regular file, update OST objects XATTR_NAME_FID */
        if (S_ISREG(attr->la_mode)) {
-               /* delete LOV to avoid deleting OST objs when destroying sobj */
-               mdd_write_lock(env, sobj, MOR_SRC_CHILD);
-               rc = mdo_xattr_del(env, sobj, XATTR_NAME_LOV, handle);
-               mdd_write_unlock(env, sobj);
+               struct lu_buf fid_buf;
+
+               /* target may be remote, update PFID via sobj. */
+               fid_buf.lb_buf = (void *)mdo2fid(tobj);
+               fid_buf.lb_len = sizeof(struct lu_fid);
+               rc = mdo_xattr_set(env, sobj, &fid_buf, XATTR_NAME_FID, 0,
+                                  handle);
                if (rc)
                        RETURN(rc);
 
-               /* for regular file, update OST objects XATTR_NAME_FID */
-               rc = mdo_xattr_set(env, tobj, NULL, XATTR_NAME_FID, 0, handle);
+               /* delete LOV to avoid deleting OST objs when destroying sobj */
+               mdd_write_lock(env, sobj, DT_SRC_CHILD);
+               rc = mdo_xattr_del(env, sobj, XATTR_NAME_LOV, handle);
+               mdd_write_unlock(env, sobj);
                if (rc)
                        RETURN(rc);
        }
@@ -4188,7 +4253,7 @@ static int mdd_migrate_update(const struct lu_env *env,
 
        la->la_ctime = la->la_mtime = ma->ma_attr.la_ctime;
        la->la_valid = LA_CTIME | LA_MTIME;
-       mdd_write_lock(env, spobj, MOR_SRC_PARENT);
+       mdd_write_lock(env, spobj, DT_SRC_PARENT);
        rc = mdd_update_time(env, spobj, spattr, la, handle);
        mdd_write_unlock(env, spobj);
        if (rc)
@@ -4196,7 +4261,7 @@ static int mdd_migrate_update(const struct lu_env *env,
 
        if (tpobj != spobj) {
                la->la_valid = LA_CTIME | LA_MTIME;
-               mdd_write_lock(env, tpobj, MOR_TGT_PARENT);
+               mdd_write_lock(env, tpobj, DT_TGT_PARENT);
                rc = mdd_update_time(env, tpobj, tpattr, la, handle);
                mdd_write_unlock(env, tpobj);
                if (rc)
@@ -4221,7 +4286,7 @@ static int mdd_migrate_update(const struct lu_env *env,
         *  message, this won't cause any inconsistency or trouble.
         */
        if (do_create && do_destroy) {
-               mdd_write_lock(env, sobj, MOR_SRC_CHILD);
+               mdd_write_lock(env, sobj, DT_SRC_CHILD);
                mdo_ref_del(env, sobj, handle);
                rc = mdo_destroy(env, sobj, handle);
                mdd_write_unlock(env, sobj);
@@ -4472,7 +4537,7 @@ static int mdd_migrate(const struct lu_env *env, struct md_object *md_pobj,
        if (rc)
                GOTO(out, rc);
 
-       mdd_object_make_hint(env, NULL, tobj, attr, spec, hint);
+       mdd_object_make_hint(env, tpobj, tobj, attr, spec, hint);
 
        handle = mdd_trans_create(env, mdd);
        if (IS_ERR(handle))
@@ -4666,7 +4731,7 @@ static int __mdd_dir_layout_shrink(const struct lu_env *env,
                lmu->lum_stripe_count = cpu_to_le32(1);
 
                /* delete LMV to avoid deleting stripes again upon destroy */
-               mdd_write_lock(env, obj, MOR_SRC_CHILD);
+               mdd_write_lock(env, obj, DT_SRC_CHILD);
                rc = mdo_xattr_del(env, obj, XATTR_NAME_LMV, handle);
                mdd_write_unlock(env, obj);
                if (rc)
@@ -4674,7 +4739,7 @@ static int __mdd_dir_layout_shrink(const struct lu_env *env,
        }
 
        /* destroy stripes after lmu_stripe_count */
-       mdd_write_lock(env, obj, MOR_SRC_PARENT);
+       mdd_write_lock(env, obj, DT_SRC_PARENT);
        rc = mdd_dir_iterate_stripes(env, obj, lmv_buf, &shrink_buf, handle,
                                     mdd_dir_destroy_stripe);
        mdd_write_unlock(env, obj);
@@ -4698,8 +4763,8 @@ static int __mdd_dir_layout_shrink(const struct lu_env *env,
        LASSERT(pobj);
        LASSERT(stripe);
 
-       mdd_write_lock(env, pobj, MOR_SRC_PARENT);
-       mdd_write_lock(env, obj, MOR_SRC_CHILD);
+       mdd_write_lock(env, pobj, DT_SRC_PARENT);
+       mdd_write_lock(env, obj, DT_SRC_CHILD);
 
        /* insert dotdot to stripe which points to parent */
        rc = __mdd_index_insert_only(env, stripe, mdo2fid(pobj), S_IFDIR,