Whamcloud - gitweb
LU-11668 mdd: use mdd_object_fid() instead of mdo2fid()
[fs/lustre-release.git] / lustre / mdd / mdd_dir.c
index e9380ff..9bc7142 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"
 
@@ -71,12 +72,12 @@ __mdd_lookup(const struct lu_env *env, struct md_object *pobj,
             const struct lu_attr *pattr, const struct lu_name *lname,
             struct lu_fid* fid, int mask)
 {
-       const char *name                = lname->ln_name;
-       const struct dt_key *key        = (const struct dt_key *)name;
-       struct mdd_object *mdd_obj      = md2mdd_obj(pobj);
-       struct mdd_device *m            = mdo2mdd(pobj);
-       struct dt_object *dir           = mdd_object_child(mdd_obj);
-        int rc;
+       const char *name = lname->ln_name;
+       const struct dt_key *key = (const struct dt_key *)name;
+       struct mdd_object *mdd_obj = md2mdd_obj(pobj);
+       struct dt_object *dir = mdd_object_child(mdd_obj);
+       int rc;
+
        ENTRY;
 
        if (unlikely(mdd_is_dead_obj(mdd_obj)))
@@ -86,12 +87,13 @@ __mdd_lookup(const struct lu_env *env, struct md_object *pobj,
                RETURN(-ESTALE);
 
        if (mdd_object_remote(mdd_obj)) {
-               CDEBUG(D_INFO, "%s: Object "DFID" locates on remote server\n",
-                      mdd2obd_dev(m)->obd_name, PFID(mdo2fid(mdd_obj)));
+               CDEBUG(D_INFO, "%s: Object "DFID" located on remote server\n",
+                      mdd_obj_dev_name(mdd_obj),
+                      PFID(mdd_object_fid(mdd_obj)));
        }
 
        rc = mdd_permission_internal_locked(env, mdd_obj, pattr, mask,
-                                           MOR_TGT_PARENT);
+                                           DT_TGT_PARENT);
        if (rc)
                RETURN(rc);
 
@@ -219,7 +221,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)
@@ -230,6 +235,9 @@ static inline int mdd_parent_fid(const struct lu_env *env,
        if (rc != 0)
                GOTO(lookup, rc);
 
+       /* the obj is not locked, don't cache attributes */
+       mdd_invalidate(env, &obj->mod_obj);
+
        LASSERT(ldata.ld_leh != NULL);
        /* Directory should only have 1 parent */
        if (ldata.ld_leh->leh_reccount > 1)
@@ -270,10 +278,10 @@ static int mdd_is_parent(const struct lu_env *env,
        struct lu_fid *pfid;
        int rc;
 
-       LASSERT(!lu_fid_eq(mdo2fid(mo), tfid));
+       LASSERT(!lu_fid_eq(mdd_object_fid(mo), tfid));
        pfid = &mdd_env_info(env)->mti_fid;
 
-       if (mdd_is_root(mdd, mdo2fid(mo)))
+       if (mdd_is_root(mdd, mdd_object_fid(mo)))
                return 0;
 
        if (mdd_is_root(mdd, tfid))
@@ -381,8 +389,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 +458,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 +479,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 +533,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);
        }
@@ -569,12 +581,11 @@ int mdd_may_delete(const struct lu_env *env, struct mdd_object *tpobj,
        /* additional check the rename case */
        if (cattr) {
                if (S_ISDIR(cattr->la_mode)) {
-                       struct mdd_device *mdd = mdo2mdd(&tobj->mod_obj);
-
                        if (!S_ISDIR(tattr->la_mode))
                                RETURN(-ENOTDIR);
 
-                       if (lu_fid_eq(mdo2fid(tobj), &mdd->mdd_root_fid))
+                       if (mdd_is_root(mdo2mdd(&tobj->mod_obj),
+                                       mdd_object_fid(tobj)))
                                RETURN(-EBUSY);
                } else if (S_ISDIR(tattr->la_mode))
                        RETURN(-EISDIR);
@@ -666,15 +677,11 @@ static int __mdd_index_insert_only(const struct lu_env *env,
 
        if (dt_try_as_dir(env, next)) {
                struct dt_insert_rec    *rec = &mdd_env_info(env)->mti_dt_rec;
-               struct lu_ucred         *uc  = lu_ucred_check(env);
-               int                      ignore_quota;
 
                rec->rec_fid = lf;
                rec->rec_type = type;
-               ignore_quota = uc ? uc->uc_cap & CFS_CAP_SYS_RESOURCE_MASK : 1;
                rc = dt_insert(env, next, (const struct dt_rec *)rec,
-                              (const struct dt_key *)name, handle,
-                              ignore_quota);
+                              (const struct dt_key *)name, handle);
        } else {
                rc = -ENOTDIR;
        }
@@ -691,7 +698,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);
        }
@@ -704,17 +711,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,
@@ -722,17 +729,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));
 }
@@ -780,6 +787,47 @@ out_put:
        return rc;
 }
 
+int mdd_changelog_write_rec(const struct lu_env *env,
+                           struct llog_handle *loghandle,
+                           struct llog_rec_hdr *r,
+                           struct llog_cookie *cookie,
+                           int idx, struct thandle *th)
+{
+       int rc;
+
+       if (r->lrh_type == CHANGELOG_REC) {
+               struct mdd_device *mdd;
+               struct llog_changelog_rec *rec;
+
+               mdd = lu2mdd_dev(loghandle->lgh_ctxt->loc_obd->obd_lu_dev);
+               rec = container_of0(r, struct llog_changelog_rec, cr_hdr);
+
+               spin_lock(&mdd->mdd_cl.mc_lock);
+               rec->cr.cr_index = mdd->mdd_cl.mc_index + 1;
+               spin_unlock(&mdd->mdd_cl.mc_lock);
+
+               rc = llog_osd_ops.lop_write_rec(env, loghandle, r,
+                                               cookie, idx, th);
+
+               /*
+                * if current llog is full, we will generate a new
+                * llog, and since it's actually not an error, let's
+                * avoid increasing index so that userspace apps
+                * should not see a gap in the changelog sequence
+                */
+               if (!(rc == -ENOSPC && llog_is_full(loghandle))) {
+                       spin_lock(&mdd->mdd_cl.mc_lock);
+                       ++mdd->mdd_cl.mc_index;
+                       spin_unlock(&mdd->mdd_cl.mc_lock);
+               }
+       } else {
+               rc = llog_osd_ops.lop_write_rec(env, loghandle, r,
+                                               cookie, idx, th);
+       }
+
+       return rc;
+}
+
 /** Add a changelog entry \a rec to the changelog llog
  * \param mdd
  * \param rec
@@ -802,13 +850,6 @@ int mdd_changelog_store(const struct lu_env *env, struct mdd_device *mdd,
        rec->cr_hdr.lrh_type = CHANGELOG_REC;
        rec->cr.cr_time = cl_time();
 
-       spin_lock(&mdd->mdd_cl.mc_lock);
-       /* NB: I suppose it's possible llog_add adds out of order wrt cr_index,
-        * but as long as the MDD transactions are ordered correctly for e.g.
-        * rename conflicts, I don't think this should matter. */
-       rec->cr.cr_index = ++mdd->mdd_cl.mc_index;
-       spin_unlock(&mdd->mdd_cl.mc_lock);
-
        ctxt = llog_get_context(obd, LLOG_CHANGELOG_ORIG_CTXT);
        if (ctxt == NULL)
                return -ENXIO;
@@ -817,6 +858,7 @@ int mdd_changelog_store(const struct lu_env *env, struct mdd_device *mdd,
        if (IS_ERR(llog_th))
                GOTO(out_put, rc = PTR_ERR(llog_th));
 
+       OBD_FAIL_TIMEOUT(OBD_FAIL_MDS_CHANGELOG_REORDER, cfs_fail_val);
        /* nested journal transaction */
        rc = llog_add(env, ctxt->loc_handle, &rec->cr_hdr, NULL, llog_th);
 
@@ -915,17 +957,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));
 }
@@ -944,7 +986,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,
@@ -974,24 +1016,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,
@@ -1005,14 +1047,14 @@ 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)) {
-               rec->cr.cr_tfid = *mdo2fid(target);
+               rec->cr.cr_tfid = *mdd_object_fid(target);
                target->mod_cltime = ktime_get();
        } else {
                fid_zero(&rec->cr.cr_tfid);
@@ -1298,7 +1340,7 @@ static int mdd_declare_link(const struct lu_env *env,
                            struct lu_attr *la,
                            struct linkea_data *data)
 {
-       struct lu_fid tfid = *mdo2fid(c);
+       struct lu_fid tfid = *mdd_object_fid(c);
        int rc;
 
        if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_DANGLING3))
@@ -1379,8 +1421,8 @@ static int mdd_link(const struct lu_env *env, struct md_object *tgt_obj,
        /* Note: even this function will change ldata, but it comes from
         * thread_info, which is completely temporary and only seen in
         * this function, so we do not need reset ldata once it fails.*/
-       rc = mdd_linkea_prepare(env, mdd_sobj, NULL, NULL, mdo2fid(mdd_tobj),
-                               lname, 0, 0, ldata);
+       rc = mdd_linkea_prepare(env, mdd_sobj, NULL, NULL,
+                               mdd_object_fid(mdd_tobj), lname, 0, 0, ldata);
        if (rc != 0)
                GOTO(stop, rc);
 
@@ -1393,7 +1435,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)
@@ -1405,7 +1447,7 @@ static int mdd_link(const struct lu_env *env, struct md_object *tgt_obj,
                        GOTO(out_unlock, rc);
        }
 
-       *tfid = *mdo2fid(mdd_sobj);
+       *tfid = *mdd_object_fid(mdd_sobj);
        if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_DANGLING3))
                tfid->f_oid = cfs_fail_val;
 
@@ -1426,7 +1468,7 @@ static int mdd_link(const struct lu_env *env, struct md_object *tgt_obj,
        if (rc == 0)
                /* Note: The failure of links_add should not cause the
                 * link failure, so do not check return value. */
-               mdd_links_add(env, mdd_sobj, mdo2fid(mdd_tobj),
+               mdd_links_add(env, mdd_sobj, mdd_object_fid(mdd_tobj),
                              lname, handle, ldata, 0);
 
        EXIT;
@@ -1434,8 +1476,8 @@ out_unlock:
        mdd_write_unlock(env, mdd_sobj);
        if (rc == 0)
                rc = mdd_changelog_ns_store(env, mdd, CL_HARDLINK, 0, mdd_sobj,
-                                           mdo2fid(mdd_tobj), NULL, NULL,
-                                           lname, NULL, handle);
+                                           mdd_object_fid(mdd_tobj), NULL,
+                                           NULL, lname, NULL, handle);
 stop:
        rc = mdd_trans_stop(env, mdd, rc, handle);
        if (is_vmalloc_addr(ldata->ld_buf))
@@ -1452,9 +1494,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;
 
@@ -1493,7 +1532,7 @@ static int mdd_declare_finish_unlink(const struct lu_env *env,
 /* caller should take a lock before calling */
 int mdd_finish_unlink(const struct lu_env *env,
                      struct mdd_object *obj, struct md_attr *ma,
-                     const struct mdd_object *pobj,
+                     struct mdd_object *pobj,
                      const struct lu_name *lname,
                      struct thandle *th)
 {
@@ -1531,7 +1570,7 @@ int mdd_finish_unlink(const struct lu_env *env,
                }
        } else if (!is_dir) {
                /* old files may not have link ea; ignore errors */
-               mdd_links_del(env, obj, mdo2fid(pobj), lname, th);
+               mdd_links_del(env, obj, mdd_object_fid(pobj), lname, th);
        }
 
        RETURN(rc);
@@ -1712,7 +1751,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);
@@ -1728,7 +1767,7 @@ static int mdd_unlink(const struct lu_env *env, struct md_object *pobj,
                rc = mdo_ref_del(env, mdd_cobj, handle);
                if (rc != 0) {
                        __mdd_index_insert_only(env, mdd_pobj,
-                                               mdo2fid(mdd_cobj),
+                                               mdd_object_fid(mdd_cobj),
                                                mdd_object_type(mdd_cobj),
                                                name, handle);
                        GOTO(cleanup, rc);
@@ -1799,8 +1838,8 @@ cleanup:
 
                rc = mdd_changelog_ns_store(env, mdd,
                        is_dir ? CL_RMDIR : CL_UNLINK, cl_flags,
-                       mdd_cobj, mdo2fid(mdd_pobj), NULL, NULL, lname, NULL,
-                       handle);
+                       mdd_cobj, mdd_object_fid(mdd_pobj), NULL, NULL,
+                       lname, NULL, handle);
        }
 
 stop:
@@ -1921,8 +1960,8 @@ static int mdd_declare_object_initialize(const struct lu_env *env,
        if (!S_ISDIR(attr->la_mode))
                RETURN(0);
 
-       rc = mdo_declare_index_insert(env, child, mdo2fid(child), S_IFDIR,
-                                     dot, handle);
+       rc = mdo_declare_index_insert(env, child, mdd_object_fid(child),
+                                     S_IFDIR, dot, handle);
        if (rc != 0)
                RETURN(rc);
 
@@ -1930,8 +1969,8 @@ static int mdd_declare_object_initialize(const struct lu_env *env,
        if (rc != 0)
                RETURN(rc);
 
-       rc = mdo_declare_index_insert(env, child, mdo2fid(parent), S_IFDIR,
-                                     dotdot, handle);
+       rc = mdo_declare_index_insert(env, child, mdd_object_fid(parent),
+                                     S_IFDIR, dotdot, handle);
 
        RETURN(rc);
 }
@@ -1946,9 +1985,9 @@ static int mdd_object_initialize(const struct lu_env *env,
        ENTRY;
 
        if (S_ISDIR(attr->la_mode)) {
-                /* Add "." and ".." for newly created dir */
-                mdo_ref_add(env, child, handle);
-                rc = __mdd_index_insert_only(env, child, mdo2fid(child),
+               /* Add "." and ".." for newly created dir */
+               mdo_ref_add(env, child, handle);
+               rc = __mdd_index_insert_only(env, child, mdd_object_fid(child),
                                             S_IFDIR, dot, handle);
                if (rc == 0)
                        rc = __mdd_index_insert_only(env, child, pfid, S_IFDIR,
@@ -2021,8 +2060,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, "
@@ -2039,12 +2077,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;
                }
        }
 
@@ -2094,6 +2144,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;
@@ -2104,7 +2155,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,
@@ -2140,6 +2191,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)) {
@@ -2176,12 +2235,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);
 
@@ -2199,8 +2259,9 @@ static int mdd_declare_create(const struct lu_env *env, struct mdd_device *mdd,
                struct lu_attr *la = &mdd_env_info(env)->mti_la_for_fix;
                enum changelog_rec_type type;
 
-               rc = mdo_declare_index_insert(env, p, mdo2fid(c), attr->la_mode,
-                                             name->ln_name, handle);
+               rc = mdo_declare_index_insert(env, p, mdd_object_fid(c),
+                                             attr->la_mode, name->ln_name,
+                                             handle);
                if (rc != 0)
                        return rc;
 
@@ -2240,7 +2301,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);
@@ -2276,13 +2337,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)
+                            struct thandle *handle, bool initsecctx)
 {
        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)
@@ -2292,7 +2354,8 @@ static int mdd_create_object(const struct lu_env *env, struct mdd_object *pobj,
         * created in declare phase, they also needs to be added to master
         * object as sub-directory entry. So it has to initialize the master
         * object, then set dir striped EA.(in mdo_xattr_set) */
-       rc = mdd_object_initialize(env, mdo2fid(pobj), son, attr, handle);
+       rc = mdd_object_initialize(env, mdd_object_fid(pobj), son, attr,
+                                  handle);
        if (rc != 0)
                GOTO(err_destroy, rc);
 
@@ -2324,7 +2387,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 */
@@ -2345,24 +2421,20 @@ static int mdd_create_object(const struct lu_env *env, struct mdd_object *pobj,
 #endif
 
        if (S_ISLNK(attr->la_mode)) {
-               struct lu_ucred  *uc = lu_ucred_assert(env);
                struct dt_object *dt = mdd_object_child(son);
                const char *target_name = spec->u.sp_symname;
                int sym_len = strlen(target_name);
                loff_t pos = 0;
 
                buf = mdd_buf_get_const(env, target_name, sym_len);
-               rc = dt->do_body_ops->dbo_write(env, dt, buf, &pos, handle,
-                                               uc->uc_cap &
-                                               CFS_CAP_SYS_RESOURCE_MASK);
-
+               rc = dt->do_body_ops->dbo_write(env, dt, buf, &pos, handle);
                if (rc == sym_len)
                        rc = 0;
                else
                        GOTO(err_initlized, rc = -EFAULT);
        }
 
-       if (spec->sp_cr_file_secctx_name != NULL) {
+       if (initsecctx && spec->sp_cr_file_secctx_name != NULL) {
                buf = mdd_buf_get_const(env, spec->sp_cr_file_secctx,
                                        spec->sp_cr_file_secctx_size);
                rc = mdo_xattr_set(env, son, buf, spec->sp_cr_file_secctx_name,
@@ -2476,7 +2548,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)
 {
@@ -2490,6 +2562,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;
@@ -2514,7 +2587,8 @@ 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_t(unsigned int, 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);
@@ -2551,9 +2625,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);
 
@@ -2562,23 +2645,23 @@ 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, true);
        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);
        } else {
-               rc = __mdd_index_insert(env, mdd_pobj, mdo2fid(son),
-                                     attr->la_mode, name, handle);
+               rc = __mdd_index_insert(env, mdd_pobj, mdd_object_fid(son),
+                                       attr->la_mode, name, handle);
                if (rc != 0)
                        GOTO(err_created, rc);
 
-               mdd_links_add(env, son, mdo2fid(mdd_pobj), lname, handle,
-                             ldata, 1);
+               mdd_links_add(env, son, mdd_object_fid(mdd_pobj), lname,
+                             handle, ldata, 1);
 
                /* update parent directory mtime/ctime */
                *la = *attr;
@@ -2601,7 +2684,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. */
@@ -2628,14 +2711,14 @@ out_volatile:
                mdd_write_unlock(env, son);
        }
 
-       if (rc == 0 && fid_is_namespace_visible(mdo2fid(son)) &&
+       if (rc == 0 && fid_is_namespace_visible(mdd_object_fid(son)) &&
            likely((spec->sp_cr_flags & MDS_OPEN_VOLATILE) == 0))
                rc = mdd_changelog_ns_store(env, mdd,
                                S_ISDIR(attr->la_mode) ? CL_MKDIR :
                                S_ISREG(attr->la_mode) ? CL_CREATE :
                                S_ISLNK(attr->la_mode) ? CL_SOFTLINK : CL_MKNOD,
-                               0, son, mdo2fid(mdd_pobj), NULL, NULL, lname,
-                               NULL, handle);
+                               0, son, mdd_object_fid(mdd_pobj), NULL, NULL,
+                               lname, NULL, handle);
 out_stop:
        rc2 = mdd_trans_stop(env, mdd, rc, handle);
        if (rc == 0) {
@@ -2653,6 +2736,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,
@@ -2671,36 +2757,36 @@ enum rename_order {
 };
 
 static int mdd_rename_order(const struct lu_env *env,
-                            struct mdd_device *mdd,
-                            struct mdd_object *src_pobj,
+                           struct mdd_device *mdd,
+                           struct mdd_object *src_pobj,
                            const struct lu_attr *pattr,
-                            struct mdd_object *tgt_pobj)
+                           struct mdd_object *tgt_pobj)
 {
-        /* order of locking, 1 - tgt-src, 0 - src-tgt*/
-        int rc;
-        ENTRY;
-
-        if (src_pobj == tgt_pobj)
-                RETURN(MDD_RN_SAME);
+       /* order of locking, 1 - tgt-src, 0 - src-tgt*/
+       int rc;
 
-        /* compared the parent child relationship of src_p&tgt_p */
-        if (lu_fid_eq(&mdd->mdd_root_fid, mdo2fid(src_pobj))){
-                rc = MDD_RN_SRCTGT;
-        } else if (lu_fid_eq(&mdd->mdd_root_fid, mdo2fid(tgt_pobj))) {
-                rc = MDD_RN_TGTSRC;
-        } else {
+       ENTRY;
+       if (src_pobj == tgt_pobj)
+               RETURN(MDD_RN_SAME);
+
+       /* compared the parent child relationship of src_p & tgt_p */
+       if (lu_fid_eq(&mdd->mdd_root_fid, mdd_object_fid(src_pobj))) {
+               rc = MDD_RN_SRCTGT;
+       } else if (lu_fid_eq(&mdd->mdd_root_fid, mdd_object_fid(tgt_pobj))) {
+               rc = MDD_RN_TGTSRC;
+       } else {
                rc = mdd_is_parent(env, mdd, src_pobj, pattr,
-                                  mdo2fid(tgt_pobj));
-                if (rc == -EREMOTE)
-                        rc = 0;
-
-                if (rc == 1)
-                        rc = MDD_RN_TGTSRC;
-                else if (rc == 0)
-                        rc = MDD_RN_SRCTGT;
-        }
+                                  mdd_object_fid(tgt_pobj));
+               if (rc == -EREMOTE)
+                       rc = 0;
 
-        RETURN(rc);
+               if (rc == 1)
+                       rc = MDD_RN_TGTSRC;
+               else if (rc == 0)
+                       rc = MDD_RN_SRCTGT;
+       }
+
+       RETURN(rc);
 }
 
 /* has not mdd_write{read}_lock on any obj yet. */
@@ -2767,28 +2853,27 @@ static int mdd_declare_rename(const struct lu_env *env,
                              struct linkea_data *ldata,
                              struct thandle *handle)
 {
-       struct lu_attr    *la = &mdd_env_info(env)->mti_la_for_fix;
+       struct lu_attr *la = &mdd_env_info(env)->mti_la_for_fix;
        int rc;
 
        LASSERT(ma->ma_attr.la_valid & LA_CTIME);
        la->la_ctime = la->la_mtime = ma->ma_attr.la_ctime;
 
-        LASSERT(mdd_spobj);
-        LASSERT(mdd_tpobj);
-        LASSERT(mdd_sobj);
+       LASSERT(mdd_spobj);
+       LASSERT(mdd_tpobj);
+       LASSERT(mdd_sobj);
 
-        /* name from source dir */
-        rc = mdo_declare_index_delete(env, mdd_spobj, sname->ln_name, handle);
-        if (rc)
-                return rc;
+       /* name from source dir */
+       rc = mdo_declare_index_delete(env, mdd_spobj, sname->ln_name, handle);
+       if (rc)
+               return rc;
 
-        /* .. from source child */
-        if (S_ISDIR(mdd_object_type(mdd_sobj))) {
-                /* source child can be directory,
-                 * counted by source dir's nlink */
-                rc = mdo_declare_ref_del(env, mdd_spobj, handle);
-                if (rc)
-                        return rc;
+       /* .. from source child */
+       if (S_ISDIR(mdd_object_type(mdd_sobj))) {
+               /* source child can be directory, count by source dir's nlink */
+               rc = mdo_declare_ref_del(env, mdd_spobj, handle);
+               if (rc)
+                       return rc;
                if (mdd_spobj != mdd_tpobj) {
                        rc = mdo_declare_index_delete(env, mdd_sobj, dotdot,
                                                      handle);
@@ -2796,7 +2881,7 @@ static int mdd_declare_rename(const struct lu_env *env,
                                return rc;
 
                        rc = mdo_declare_index_insert(env, mdd_sobj,
-                                                     mdo2fid(mdd_tpobj),
+                                                     mdd_object_fid(mdd_tpobj),
                                                      S_IFDIR, dotdot, handle);
                        if (rc != 0)
                                return rc;
@@ -2828,7 +2913,7 @@ static int mdd_declare_rename(const struct lu_env *env,
                return rc;
 
        /* new name */
-       rc = mdo_declare_index_insert(env, mdd_tpobj, mdo2fid(mdd_sobj),
+       rc = mdo_declare_index_insert(env, mdd_tpobj, mdd_object_fid(mdd_sobj),
                                      mdd_object_type(mdd_sobj),
                                      tname->ln_name, handle);
        if (rc != 0)
@@ -2897,8 +2982,8 @@ static int mdd_rename(const struct lu_env *env,
        struct lu_attr *tpattr = MDD_ENV_VAR(env, tpattr);
        struct thandle *handle;
        struct linkea_data  *ldata = &mdd_env_info(env)->mti_link_data;
-       const struct lu_fid *tpobj_fid = mdo2fid(mdd_tpobj);
-       const struct lu_fid *spobj_fid = mdo2fid(mdd_spobj);
+       const struct lu_fid *tpobj_fid = mdd_object_fid(mdd_tpobj);
+       const struct lu_fid *spobj_fid = mdd_object_fid(mdd_spobj);
        bool is_dir;
        bool tobj_ref = 0;
        bool tobj_locked = 0;
@@ -3015,13 +3100,13 @@ 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);
-       rc = mdd_links_rename(env, mdd_sobj, mdo2fid(mdd_spobj), lsname,
-                             mdo2fid(mdd_tpobj), ltname, handle, ldata,
-                             0, 0);
+       mdd_write_lock(env, mdd_sobj, DT_SRC_CHILD);
+       rc = mdd_links_rename(env, mdd_sobj, mdd_object_fid(mdd_spobj),
+                             lsname, mdd_object_fid(mdd_tpobj), ltname,
+                             handle, ldata, 0, 0);
        if (rc == -ENOENT)
                /* Old files might not have EA entry */
-               mdd_links_add(env, mdd_sobj, mdo2fid(mdd_spobj),
+               mdd_links_add(env, mdd_sobj, mdd_object_fid(mdd_spobj),
                              lsname, handle, NULL, 0);
        mdd_write_unlock(env, mdd_sobj);
        /* We don't fail the transaction if the link ea can't be
@@ -3034,7 +3119,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 */
@@ -3135,9 +3220,9 @@ fixup_tpobj:
                        }
 
                        rc2 = __mdd_index_insert(env, mdd_tpobj,
-                                                 mdo2fid(mdd_tobj),
-                                                 mdd_object_type(mdd_tobj),
-                                                 tname, handle);
+                                                mdd_object_fid(mdd_tobj),
+                                                mdd_object_type(mdd_tobj),
+                                                tname, handle);
                        if (rc2 != 0)
                                CWARN("tp obj fix error: rc = %d\n", rc2);
                }
@@ -3205,10 +3290,11 @@ 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)),
+                              mdd_obj_dev_name(sobj),
+                              PFID(mdd_object_fid(sobj)),
                               sobj->mod_count);
                        mdd_read_unlock(env, sobj);
                        RETURN(-EBUSY);
@@ -3289,7 +3375,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);
@@ -3380,7 +3466,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);
@@ -3434,6 +3520,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));
@@ -3464,6 +3553,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;
@@ -3520,14 +3610,16 @@ static int mdd_iterate_xattrs(const struct lu_env *env,
                if (rc < 0)
                        GOTO(out, rc);
 
+               cbxbuf = xbuf;
+               cbxbuf.lb_len = xsize;
 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;
                        }
                }
@@ -3580,7 +3672,7 @@ static int mdd_declare_update_link(const struct lu_env *env,
 
        rc = mdo_declare_index_delete(env, pobj, lname->ln_name, handle);
        if (!rc)
-               rc = mdo_declare_index_insert(env, pobj, mdo2fid(tobj),
+               rc = mdo_declare_index_insert(env, pobj, mdd_object_fid(tobj),
                                              mdd_object_type(sobj),
                                              lname->ln_name, handle);
        mdd_object_put(env, pobj);
@@ -3619,7 +3711,7 @@ static int mdd_update_link(const struct lu_env *env,
                RETURN(0);
 
        CDEBUG(D_INFO, "update "DFID"/"DNAME":"DFID"\n",
-              PFID(fid), PNAME(lname), PFID(mdo2fid(tobj)));
+              PFID(fid), PNAME(lname), PFID(mdd_object_fid(tobj)));
 
        pobj = mdd_object_find(env, mdd, fid);
        if (IS_ERR(pobj)) {
@@ -3634,10 +3726,10 @@ 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),
+               rc = __mdd_index_insert_only(env, pobj, mdd_object_fid(tobj),
                                             mdd_object_type(sobj),
                                             lname->ln_name, handle);
        mdd_write_unlock(env, pobj);
@@ -3645,13 +3737,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);
 
@@ -3770,8 +3862,8 @@ static int migrate_linkea_prepare(const struct lu_env *env,
        ENTRY;
 
        memset(ldata, 0, sizeof(*ldata));
-       rc = mdd_linkea_prepare(env, sobj, mdo2fid(spobj), lname,
-                               mdo2fid(tpobj), lname, 1, 0, ldata);
+       rc = mdd_linkea_prepare(env, sobj, mdd_object_fid(spobj), lname,
+                               mdd_object_fid(tpobj), lname, 1, 0, ldata);
        if (rc)
                RETURN(rc);
 
@@ -3793,12 +3885,12 @@ static int migrate_linkea_prepare(const struct lu_env *env,
        if (unlikely(ldata->ld_leh->leh_overflow_time))
                RETURN(-EOVERFLOW);
 
-       rc = mdd_fld_lookup(env, mdd, mdo2fid(sobj), &source_mdt_index);
+       rc = mdd_fld_lookup(env, mdd, mdd_object_fid(sobj), &source_mdt_index);
        if (rc)
                RETURN(rc);
 
-       rc = mdd_iterate_linkea(env, sobj, NULL, lname, mdo2fid(tpobj), ldata,
-                               &source_mdt_index, NULL,
+       rc = mdd_iterate_linkea(env, sobj, NULL, lname, mdd_object_fid(tpobj),
+                               ldata, &source_mdt_index, NULL,
                                mdd_is_link_on_source_mdt);
        RETURN(rc);
 }
@@ -3833,7 +3925,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);
@@ -3891,7 +3983,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;
 
@@ -3907,7 +3999,8 @@ static int mdd_declare_migrate_create(const struct lu_env *env,
                        memset(lmv, 0, sizeof(*lmv));
                        lmv->lmv_magic = cpu_to_le32(LMV_MAGIC_V1);
                        lmv->lmv_stripe_count = cpu_to_le32(1);
-                       fid_le_to_cpu(&lmv->lmv_stripe_fids[0], mdo2fid(sobj));
+                       fid_le_to_cpu(&lmv->lmv_stripe_fids[0],
+                                     mdd_object_fid(sobj));
                        sbuf->lb_buf = lmv;
                        sbuf->lb_len = lmv_mds_md_size(1, LMV_MAGIC_V1);
 
@@ -3939,26 +4032,27 @@ 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 *)mdd_object_fid(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;
        }
 
        if (!S_ISDIR(attr->la_mode)) {
-               rc = mdd_iterate_linkea(env, sobj, tobj, lname, mdo2fid(tpobj),
-                                       ldata, NULL, handle,
-                                       mdd_declare_update_link);
+               rc = mdd_iterate_linkea(env, sobj, tobj, lname,
+                                       mdd_object_fid(tpobj), ldata, NULL,
+                                       handle, mdd_declare_update_link);
                if (rc)
                        return rc;
 
@@ -4038,7 +4132,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)
@@ -4049,34 +4143,41 @@ 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, false);
        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 *)mdd_object_fid(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);
        }
 
        if (!S_ISDIR(attr->la_mode))
-               rc = mdd_iterate_linkea(env, sobj, tobj, lname, mdo2fid(tpobj),
-                                       ldata, NULL, handle, mdd_update_link);
+               rc = mdd_iterate_linkea(env, sobj, tobj, lname,
+                                       mdd_object_fid(tpobj), ldata,
+                                       NULL, handle, mdd_update_link);
 
        RETURN(rc);
 }
@@ -4097,7 +4198,7 @@ static int mdd_declare_migrate_update(const struct lu_env *env,
                                      struct thandle *handle)
 {
        struct mdd_thread_info *info = mdd_env_info(env);
-       const struct lu_fid *fid = mdo2fid(do_create ? tobj : sobj);
+       const struct lu_fid *fid = mdd_object_fid(do_create ? tobj : sobj);
        struct lu_attr *la = &info->mti_la_for_fix;
        int rc;
 
@@ -4169,15 +4270,15 @@ static int mdd_migrate_update(const struct lu_env *env,
                              struct thandle *handle)
 {
        struct mdd_thread_info *info = mdd_env_info(env);
-       const struct lu_fid *fid = mdo2fid(do_create ? tobj : sobj);
+       const struct lu_fid *fid = mdd_object_fid(do_create ? tobj : sobj);
        struct lu_attr *la = &info->mti_la_for_fix;
        int rc;
 
        ENTRY;
 
        CDEBUG(D_INFO, "update %s "DFID"/"DFID" to "DFID"/"DFID"\n",
-              lname->ln_name, PFID(mdo2fid(spobj)),
-              PFID(mdo2fid(sobj)), PFID(mdo2fid(tpobj)),
+              lname->ln_name, PFID(mdd_object_fid(spobj)),
+              PFID(mdd_object_fid(sobj)), PFID(mdd_object_fid(tpobj)),
               PFID(fid));
 
        rc = __mdd_index_delete(env, spobj, lname->ln_name,
@@ -4196,7 +4297,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)
@@ -4204,7 +4305,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)
@@ -4229,7 +4330,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);
@@ -4453,8 +4554,8 @@ static int mdd_migrate(const struct lu_env *env, struct md_object *md_pobj,
                if (rc <= 0) {
                        rc = rc ?: -EFAULT;
                        CERROR("%s: "DFID" readlink failed: rc = %d\n",
-                              mdd2obd_dev(mdd)->obd_name,
-                              PFID(mdo2fid(sobj)), rc);
+                              mdd_obj_dev_name(sobj),
+                              PFID(mdd_object_fid(sobj)), rc);
                        GOTO(out, rc);
                }
                spec->u.sp_symname = sbuf.lb_buf;
@@ -4480,7 +4581,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))
@@ -4523,8 +4624,9 @@ static int mdd_migrate(const struct lu_env *env, struct md_object *md_pobj,
                GOTO(stop_trans, rc);
 
        rc = mdd_changelog_ns_store(env, mdd, CL_MIGRATE, 0, tobj,
-                                   mdo2fid(spobj), mdo2fid(sobj),
-                                   mdo2fid(tpobj), lname, lname, handle);
+                                   mdd_object_fid(spobj), mdd_object_fid(sobj),
+                                   mdd_object_fid(tpobj), lname, lname,
+                                   handle);
        if (rc)
                GOTO(stop_trans, rc);
 
@@ -4587,8 +4689,8 @@ static int __mdd_dir_declare_layout_shrink(const struct lu_env *env,
                return mdo_declare_xattr_set(env, obj, lmv_buf,
                                             XATTR_NAME_LMV".set", 0, handle);
 
-       rc = mdo_declare_index_insert(env, stripe, mdo2fid(pobj), S_IFDIR,
-                                     dotdot, handle);
+       rc = mdo_declare_index_insert(env, stripe, mdd_object_fid(pobj),
+                                     S_IFDIR, dotdot, handle);
        if (rc)
                return rc;
 
@@ -4609,8 +4711,8 @@ static int __mdd_dir_declare_layout_shrink(const struct lu_env *env,
        if (rc)
                return rc;
 
-       rc = mdo_declare_index_insert(env, pobj, mdo2fid(stripe), attr->la_mode,
-                                     lname->ln_name, handle);
+       rc = mdo_declare_index_insert(env, pobj, mdd_object_fid(stripe),
+                                     attr->la_mode, lname->ln_name, handle);
        if (rc)
                return rc;
 
@@ -4674,7 +4776,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)
@@ -4682,7 +4784,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);
@@ -4706,12 +4808,12 @@ 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,
-                                    dotdot, handle);
+       rc = __mdd_index_insert_only(env, stripe, mdd_object_fid(pobj),
+                                    S_IFDIR, dotdot, handle);
        if (rc)
                GOTO(out, rc);
 
@@ -4738,8 +4840,8 @@ static int __mdd_dir_layout_shrink(const struct lu_env *env,
                GOTO(out, rc);
 
        /* insert stripe to parent with dir name */
-       rc = __mdd_index_insert_only(env, pobj, mdo2fid(stripe), attr->la_mode,
-                                    lname->ln_name, handle);
+       rc = __mdd_index_insert_only(env, pobj, mdd_object_fid(stripe),
+                                    attr->la_mode, lname->ln_name, handle);
        if (rc)
                GOTO(out, rc);