#include <lustre_mds.h>
#include <lustre_fid.h>
#include <lustre_lmv.h>
+#include <lustre_idmap.h>
#include "mdd_internal.h"
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)))
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);
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)
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)
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))
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);
}
if (check_perm)
rc = mdd_permission_internal_locked(env, pobj, pattr,
MAY_WRITE | MAY_EXEC,
- MOR_TGT_PARENT);
+ DT_TGT_PARENT);
RETURN(rc);
}
rc = mdd_permission_internal_locked(env, pobj, pattr,
MAY_WRITE | MAY_EXEC,
- MOR_TGT_PARENT);
+ DT_TGT_PARENT);
if (rc != 0)
RETURN(rc);
int rc;
rc = mdd_permission_internal_locked(env, pobj, pattr,
MAY_WRITE | MAY_EXEC,
- MOR_TGT_PARENT);
+ DT_TGT_PARENT);
if (rc)
RETURN(rc);
}
/* 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);
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;
}
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);
}
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,
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));
}
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
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;
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);
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));
}
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,
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,
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);
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))
/* 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);
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)
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;
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;
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))
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;
/* 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)
{
}
} 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);
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);
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);
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:
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);
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);
}
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,
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, "
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;
}
}
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;
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,
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)) {
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);
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;
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);
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)
* 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);
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 */
#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,
* \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)
{
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;
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);
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);
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;
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. */
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) {
/* 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,
};
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. */
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);
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;
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)
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;
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
* 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 */
}
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);
}
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);
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);
return rc;
}
+static int mdd_dir_declare_destroy_stripe(const struct lu_env *env,
+ struct mdd_object *obj,
+ struct mdd_object *stripe,
+ const struct lu_buf *lmv_buf,
+ const struct lu_buf *lmu_buf,
+ int index,
+ struct thandle *handle)
+{
+ struct lmv_user_md *lmu = lmu_buf->lb_buf;
+ __u32 shrink_offset = le32_to_cpu(lmu->lum_stripe_count);
+ int rc;
+
+ if (index < shrink_offset) {
+ if (shrink_offset < 2)
+ return 0;
+ return mdo_declare_xattr_set(env, stripe, lmv_buf,
+ XATTR_NAME_LMV".set", 0, handle);
+ }
+
+ rc = mdo_declare_ref_del(env, stripe, handle);
+ if (rc)
+ return rc;
+
+ rc = mdo_declare_destroy(env, stripe, handle);
+
+ return rc;
+}
+
+static int mdd_dir_destroy_stripe(const struct lu_env *env,
+ struct mdd_object *obj,
+ struct mdd_object *stripe,
+ const struct lu_buf *lmv_buf,
+ const struct lu_buf *lmu_buf,
+ int index,
+ struct thandle *handle)
+{
+ struct mdd_thread_info *info = mdd_env_info(env);
+ struct lmv_mds_md_v1 *lmv = lmv_buf->lb_buf;
+ struct lmv_user_md *lmu = lmu_buf->lb_buf;
+ __u32 shrink_offset = le32_to_cpu(lmu->lum_stripe_count);
+ int rc;
+
+ ENTRY;
+
+ /* update remaining stripes' LMV */
+ if (index < shrink_offset) {
+ struct lmv_mds_md_v1 *slave_lmv;
+ struct lu_buf slave_buf = {
+ .lb_buf = &info->mti_lmv.lmv_md_v1,
+ .lb_len = sizeof(*slave_lmv)
+ };
+ __u32 version = le32_to_cpu(lmv->lmv_layout_version);
+
+ /* if dir will be shrunk to 1-stripe, don't update */
+ if (shrink_offset < 2)
+ RETURN(0);
+
+ slave_lmv = slave_buf.lb_buf;
+ memset(slave_lmv, 0, sizeof(*slave_lmv));
+ slave_lmv->lmv_magic = cpu_to_le32(LMV_MAGIC_STRIPE);
+ slave_lmv->lmv_stripe_count = lmu->lum_stripe_count;
+ slave_lmv->lmv_master_mdt_index = cpu_to_le32(index);
+ slave_lmv->lmv_hash_type = lmv->lmv_hash_type &
+ cpu_to_le32(LMV_HASH_TYPE_MASK);
+ slave_lmv->lmv_layout_version = cpu_to_le32(++version);
+
+ rc = mdo_xattr_set(env, stripe, &slave_buf,
+ XATTR_NAME_LMV".set", 0, handle);
+ RETURN(rc);
+ }
+
+ mdd_write_lock(env, stripe, DT_SRC_CHILD);
+ rc = mdo_ref_del(env, stripe, handle);
+ if (!rc)
+ rc = mdo_destroy(env, stripe, handle);
+ mdd_write_unlock(env, stripe);
+
+ RETURN(rc);
+}
+
+static int mdd_shrink_stripe_is_empty(const struct lu_env *env,
+ struct mdd_object *obj,
+ struct mdd_object *stripe,
+ const struct lu_buf *lmv_buf,
+ const struct lu_buf *lmu_buf,
+ int index,
+ struct thandle *handle)
+{
+ struct lmv_user_md *lmu = lmu_buf->lb_buf;
+ __u32 shrink_offset = le32_to_cpu(lmu->lum_stripe_count);
+
+ /* the default value is 0, but it means 1 */
+ if (!shrink_offset)
+ shrink_offset = 1;
+
+ if (index < shrink_offset)
+ return 0;
+
+ return mdd_dir_is_empty(env, stripe);
+}
+
/*
* iterate stripes of striped directory on remote MDT, local striped directory
* is accessed via LOD.
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));
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;
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;
}
}
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);
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)) {
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);
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);
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);
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);
}
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);
struct lu_buf lmu_buf = { NULL };
if (lmv) {
- struct lmv_user_md *lmu = (typeof(lmu))info->mti_key;
+ struct lmv_user_md *lmu = &info->mti_lmv.lmv_user_md;
lmu->lum_stripe_count = 0;
lmu_buf.lb_buf = lmu;
}
rc = mdd_dir_declare_layout_delete(env, sobj, sbuf, &lmu_buf,
- handle);
+ handle);
if (rc)
return rc;
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;
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);
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;
if (sbuf->lb_buf) {
struct mdd_thread_info *info = mdd_env_info(env);
- struct lmv_user_md *lmu = (typeof(lmu))info->mti_key;
+ struct lmv_user_md *lmu = &info->mti_lmv.lmv_user_md;
lmu->lum_stripe_count = 0;
lmu_buf.lb_buf = lmu;
* 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)
/* 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);
}
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;
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,
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)
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)
* 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);
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;
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))
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);
return rc;
}
+static int __mdd_dir_declare_layout_shrink(const struct lu_env *env,
+ struct mdd_object *pobj,
+ struct mdd_object *obj,
+ struct mdd_object *stripe,
+ struct lu_attr *attr,
+ struct lu_buf *lmv_buf,
+ const struct lu_buf *lmu_buf,
+ struct lu_name *lname,
+ struct thandle *handle)
+{
+ struct mdd_thread_info *info = mdd_env_info(env);
+ struct lmv_mds_md_v1 *lmv = lmv_buf->lb_buf;
+ struct lmv_user_md *lmu = (typeof(lmu))info->mti_key;
+ struct lu_buf shrink_buf = { .lb_buf = lmu,
+ .lb_len = sizeof(*lmu) };
+ int rc;
+
+ LASSERT(lmv);
+
+ memcpy(lmu, lmu_buf->lb_buf, sizeof(*lmu));
+
+ if (le32_to_cpu(lmu->lum_stripe_count) < 2)
+ lmu->lum_stripe_count = 0;
+
+ rc = mdd_dir_declare_layout_delete(env, obj, lmv_buf, &shrink_buf,
+ handle);
+ if (rc)
+ return rc;
+
+ if (lmu->lum_stripe_count == 0) {
+ lmu->lum_stripe_count = cpu_to_le32(1);
+
+ rc = mdo_declare_xattr_del(env, obj, XATTR_NAME_LMV, handle);
+ if (rc)
+ return rc;
+ }
+
+ rc = mdd_dir_iterate_stripes(env, obj, lmv_buf, &shrink_buf, handle,
+ mdd_dir_declare_destroy_stripe);
+ if (rc)
+ return rc;
+
+ if (le32_to_cpu(lmu->lum_stripe_count) > 1)
+ return mdo_declare_xattr_set(env, obj, lmv_buf,
+ XATTR_NAME_LMV".set", 0, handle);
+
+ rc = mdo_declare_index_insert(env, stripe, mdd_object_fid(pobj),
+ S_IFDIR, dotdot, handle);
+ if (rc)
+ return rc;
+
+ rc = mdd_iterate_xattrs(env, obj, stripe, false, handle,
+ mdo_declare_xattr_set);
+ if (rc)
+ return rc;
+
+ rc = mdo_declare_xattr_del(env, stripe, XATTR_NAME_LMV, handle);
+ if (rc)
+ return rc;
+
+ rc = mdo_declare_attr_set(env, stripe, attr, handle);
+ if (rc)
+ return rc;
+
+ rc = mdo_declare_index_delete(env, pobj, lname->ln_name, handle);
+ if (rc)
+ return rc;
+
+ rc = mdo_declare_index_insert(env, pobj, mdd_object_fid(stripe),
+ attr->la_mode, lname->ln_name, handle);
+ if (rc)
+ return rc;
+
+ rc = mdo_declare_ref_del(env, obj, handle);
+ if (rc)
+ return rc;
+
+ rc = mdo_declare_ref_del(env, obj, handle);
+ if (rc)
+ return rc;
+
+ rc = mdo_declare_destroy(env, obj, handle);
+ if (rc)
+ return rc;
+
+ return rc;
+
+}
+
+/*
+ * after files under \a obj were migrated, shrink old stripes from \a obj,
+ * furthermore, if it becomes a 1-stripe directory, convert it to a normal one.
+ */
+static int __mdd_dir_layout_shrink(const struct lu_env *env,
+ struct mdd_object *pobj,
+ struct mdd_object *obj,
+ struct mdd_object *stripe,
+ struct lu_attr *attr,
+ struct lu_buf *lmv_buf,
+ const struct lu_buf *lmu_buf,
+ struct lu_name *lname,
+ struct thandle *handle)
+{
+ struct mdd_thread_info *info = mdd_env_info(env);
+ struct lmv_mds_md_v1 *lmv = lmv_buf->lb_buf;
+ struct lmv_user_md *lmu = (typeof(lmu))info->mti_key;
+ struct lu_buf shrink_buf = { .lb_buf = lmu,
+ .lb_len = sizeof(*lmu) };
+ int len = lmv_buf->lb_len;
+ __u32 version = le32_to_cpu(lmv->lmv_layout_version);
+ int rc;
+
+ ENTRY;
+
+ /* lmu needs to be altered, but lmu_buf is const */
+ memcpy(lmu, lmu_buf->lb_buf, sizeof(*lmu));
+
+ /*
+ * if dir will be shrunk to 1-stripe, delete all stripes, because it
+ * will be converted to normal dir.
+ */
+ if (le32_to_cpu(lmu->lum_stripe_count) == 1)
+ lmu->lum_stripe_count = 0;
+
+ /* delete stripes after lmu_stripe_count */
+ rc = mdd_dir_layout_delete(env, obj, lmv_buf, &shrink_buf, handle);
+ if (rc)
+ RETURN(rc);
+
+ if (lmu->lum_stripe_count == 0) {
+ lmu->lum_stripe_count = cpu_to_le32(1);
+
+ /* delete LMV to avoid deleting stripes again upon destroy */
+ 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)
+ RETURN(rc);
+ }
+
+ /* destroy stripes after lmu_stripe_count */
+ 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);
+
+ if (le32_to_cpu(lmu->lum_stripe_count) > 1) {
+ /* update dir LMV, that's all if it's still striped. */
+ lmv->lmv_stripe_count = lmu->lum_stripe_count;
+ lmv->lmv_hash_type &= ~cpu_to_le32(LMV_HASH_FLAG_MIGRATION);
+ lmv->lmv_migrate_offset = 0;
+ lmv->lmv_migrate_hash = 0;
+ lmv->lmv_layout_version = cpu_to_le32(++version);
+
+ lmv_buf->lb_len = sizeof(*lmv);
+ rc = mdo_xattr_set(env, obj, lmv_buf, XATTR_NAME_LMV".set", 0,
+ handle);
+ lmv_buf->lb_len = len;
+ RETURN(rc);
+ }
+
+ /* replace directory with its remaining stripe */
+ LASSERT(pobj);
+ LASSERT(stripe);
+
+ 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, mdd_object_fid(pobj),
+ S_IFDIR, dotdot, handle);
+ if (rc)
+ GOTO(out, rc);
+
+ /* copy xattrs including linkea */
+ rc = mdd_iterate_xattrs(env, obj, stripe, false, handle, mdo_xattr_set);
+ if (rc)
+ GOTO(out, rc);
+
+ /* delete LMV */
+ rc = mdo_xattr_del(env, stripe, XATTR_NAME_LMV, handle);
+ if (rc)
+ GOTO(out, rc);
+
+ /* don't set nlink from parent */
+ attr->la_valid &= ~LA_NLINK;
+
+ rc = mdo_attr_set(env, stripe, attr, handle);
+ if (rc)
+ GOTO(out, rc);
+
+ /* delete dir name from parent */
+ rc = __mdd_index_delete_only(env, pobj, lname->ln_name, handle);
+ if (rc)
+ GOTO(out, rc);
+
+ /* insert stripe to parent with dir name */
+ rc = __mdd_index_insert_only(env, pobj, mdd_object_fid(stripe),
+ attr->la_mode, lname->ln_name, handle);
+ if (rc)
+ GOTO(out, rc);
+
+ /* destroy dir obj */
+ rc = mdo_ref_del(env, obj, handle);
+ if (rc)
+ GOTO(out, rc);
+
+ rc = mdo_ref_del(env, obj, handle);
+ if (rc)
+ GOTO(out, rc);
+
+ rc = mdo_destroy(env, obj, handle);
+ if (rc)
+ GOTO(out, rc);
+
+ EXIT;
+out:
+ mdd_write_unlock(env, obj);
+ mdd_write_unlock(env, pobj);
+
+ return rc;
+}
+
+/*
+ * shrink directory stripes to lum_stripe_count specified by lum_mds_md.
+ */
+int mdd_dir_layout_shrink(const struct lu_env *env,
+ struct md_object *md_obj,
+ const struct lu_buf *lmu_buf)
+{
+ struct mdd_device *mdd = mdo2mdd(md_obj);
+ struct mdd_thread_info *info = mdd_env_info(env);
+ struct mdd_object *obj = md2mdd_obj(md_obj);
+ struct mdd_object *pobj = NULL;
+ struct mdd_object *stripe = NULL;
+ struct lu_attr *attr = &info->mti_pattr;
+ struct lu_fid *fid = &info->mti_fid2;
+ struct lu_name lname = { NULL };
+ struct lu_buf lmv_buf = { NULL };
+ struct lmv_mds_md_v1 *lmv;
+ struct lmv_user_md *lmu;
+ struct thandle *handle;
+ int rc;
+
+ ENTRY;
+
+ rc = mdd_la_get(env, obj, attr);
+ if (rc)
+ RETURN(rc);
+
+ if (!S_ISDIR(attr->la_mode))
+ RETURN(-ENOTDIR);
+
+ rc = mdd_stripe_get(env, obj, &lmv_buf, XATTR_NAME_LMV);
+ if (rc < 0)
+ RETURN(rc);
+
+ lmv = lmv_buf.lb_buf;
+ lmu = lmu_buf->lb_buf;
+
+ /* this was checked in MDT */
+ LASSERT(le32_to_cpu(lmu->lum_stripe_count) <
+ le32_to_cpu(lmv->lmv_stripe_count));
+
+ rc = mdd_dir_iterate_stripes(env, obj, &lmv_buf, lmu_buf, NULL,
+ mdd_shrink_stripe_is_empty);
+ if (rc < 0)
+ GOTO(out, rc);
+ else if (rc != 0)
+ GOTO(out, rc = -ENOTEMPTY);
+
+ /*
+ * if obj stripe count will be shrunk to 1, we need to convert it to a
+ * normal dir, which will change its fid and update parent namespace,
+ * get obj name and parent fid from linkea.
+ */
+ if (le32_to_cpu(lmu->lum_stripe_count) < 2) {
+ struct linkea_data *ldata = &info->mti_link_data;
+ char *filename = info->mti_name;
+
+ rc = mdd_links_read(env, obj, ldata);
+ if (rc)
+ GOTO(out, rc);
+
+ if (ldata->ld_leh->leh_reccount > 1)
+ GOTO(out, rc = -EINVAL);
+
+ linkea_first_entry(ldata);
+ if (!ldata->ld_lee)
+ GOTO(out, rc = -ENODATA);
+
+ linkea_entry_unpack(ldata->ld_lee, &ldata->ld_reclen, &lname,
+ fid);
+
+ /* Note: lname might miss \0 at the end */
+ snprintf(filename, sizeof(info->mti_name), "%.*s",
+ lname.ln_namelen, lname.ln_name);
+ lname.ln_name = filename;
+
+ pobj = mdd_object_find(env, mdd, fid);
+ if (IS_ERR(pobj)) {
+ rc = PTR_ERR(pobj);
+ pobj = NULL;
+ GOTO(out, rc);
+ }
+
+ fid_le_to_cpu(fid, &lmv->lmv_stripe_fids[0]);
+
+ stripe = mdd_object_find(env, mdd, fid);
+ if (IS_ERR(stripe)) {
+ mdd_object_put(env, pobj);
+ pobj = NULL;
+ GOTO(out, rc = PTR_ERR(stripe));
+ }
+ }
+
+ handle = mdd_trans_create(env, mdd);
+ if (IS_ERR(handle))
+ GOTO(out, rc = PTR_ERR(handle));
+
+ rc = __mdd_dir_declare_layout_shrink(env, pobj, obj, stripe, attr,
+ &lmv_buf, lmu_buf, &lname, handle);
+ if (rc)
+ GOTO(stop_trans, rc);
+
+ rc = mdd_declare_changelog_store(env, mdd, CL_LAYOUT, NULL, NULL,
+ handle);
+ if (rc)
+ GOTO(stop_trans, rc);
+
+ rc = mdd_trans_start(env, mdd, handle);
+ if (rc)
+ GOTO(stop_trans, rc);
+
+ rc = __mdd_dir_layout_shrink(env, pobj, obj, stripe, attr, &lmv_buf,
+ lmu_buf, &lname, handle);
+ if (rc)
+ GOTO(stop_trans, rc);
+
+ rc = mdd_changelog_data_store_xattr(env, mdd, CL_LAYOUT, 0, obj,
+ XATTR_NAME_LMV, handle);
+ GOTO(stop_trans, rc);
+
+stop_trans:
+ rc = mdd_trans_stop(env, mdd, rc, handle);
+out:
+ if (pobj) {
+ mdd_object_put(env, stripe);
+ mdd_object_put(env, pobj);
+ }
+ lu_buf_free(&lmv_buf);
+ return rc;
+}
+
const struct md_dir_operations mdd_dir_ops = {
.mdo_is_subdir = mdd_is_subdir,
.mdo_lookup = mdd_lookup,