static inline bool has_prefix(const char *str, const char *prefix);
-static fmode_t flags_helper(int flags)
+static unsigned int flags_helper(int flags)
{
- fmode_t mflags = 0;
+ unsigned int mflags = 0;
if (flags & MDS_FMODE_EXEC) {
mflags = MDS_FMODE_EXEC;
} else {
- if (flags & FMODE_READ)
- mflags = FMODE_READ;
- if (flags & (FMODE_WRITE | MDS_OPEN_TRUNC | MDS_OPEN_APPEND))
- mflags |= FMODE_WRITE;
+ if (flags & MDS_FMODE_READ)
+ mflags = MDS_FMODE_READ;
+ if (flags &
+ (MDS_FMODE_WRITE | MDS_OPEN_TRUNC | MDS_OPEN_APPEND))
+ mflags |= MDS_FMODE_WRITE;
}
return mflags;
const char *name)
{
struct mdd_object *mdd_obj = md2mdd_obj(obj);
- struct md_device *md_dev = lu2md_dev(mdd2lu_dev(mdo2mdd(obj)));
+ struct mdd_device *mdd;
int rc;
ENTRY;
rc = mdo_xattr_get(env, mdd_obj, buf, name);
mdd_read_unlock(env, mdd_obj);
+ mdd = mdo2mdd(obj);
+
/* record only getting user xattrs and acls */
if (rc >= 0 &&
+ mdd_changelog_enabled(env, mdd, CL_GETXATTR) &&
(has_prefix(name, XATTR_USER_PREFIX) ||
has_prefix(name, XATTR_NAME_POSIX_ACL_ACCESS) ||
has_prefix(name, XATTR_NAME_POSIX_ACL_DEFAULT))) {
struct thandle *handle;
- struct mdd_device *mdd = lu2mdd_dev(&md_dev->md_lu_dev);
int rc2;
- /* Not recording */
- if (!recording_changelog(env, mdd))
- RETURN(rc);
- if (!(mdd->mdd_cl.mc_mask & (1 << CL_GETXATTR)))
- RETURN(rc);
-
LASSERT(mdo2fid(mdd_obj) != NULL);
handle = mdd_trans_create(env, mdd);
if (IS_ERR(handle))
RETURN(PTR_ERR(handle));
- rc2 = mdd_declare_changelog_store(env, mdd, NULL, NULL, handle);
+ rc2 = mdd_declare_changelog_store(env, mdd, CL_GETXATTR, NULL,
+ NULL, handle);
if (rc2)
GOTO(stop, rc2);
LASSERT(mdd_obj != NULL);
LASSERT(handle != NULL);
- /* Not recording */
- if (!recording_changelog(env, mdd))
- RETURN(0);
- if ((mdd->mdd_cl.mc_mask & (1 << type)) == 0)
+ if (!mdd_changelog_enabled(env, mdd, type))
RETURN(0);
if (mdd_is_volatile_obj(mdd_obj))
RETURN(rc);
}
-static int mdd_changelog_data_store_xattr(const struct lu_env *env,
- struct mdd_device *mdd,
- enum changelog_rec_type type,
- int flags, struct mdd_object *mdd_obj,
- const char *xattr_name,
- struct thandle *handle)
+int mdd_changelog_data_store_xattr(const struct lu_env *env,
+ struct mdd_device *mdd,
+ enum changelog_rec_type type,
+ int flags, struct mdd_object *mdd_obj,
+ const char *xattr_name,
+ struct thandle *handle)
{
int rc;
LASSERT(mdd_obj != NULL);
LASSERT(handle != NULL);
- /* Not recording */
- if (!recording_changelog(env, mdd))
- RETURN(0);
- if ((mdd->mdd_cl.mc_mask & (1 << type)) == 0)
+ if (!mdd_changelog_enabled(env, mdd, type))
RETURN(0);
if (mdd_is_volatile_obj(mdd_obj))
int rc;
ENTRY;
- /* Not recording */
- if (!recording_changelog(env, mdd))
- RETURN(0);
- if (!(mdd->mdd_cl.mc_mask & (1 << type)))
- RETURN(0);
-
LASSERT(fid != NULL);
+ /* We'll check this again below, but we check now before we
+ * start a transaction. */
+ if (!mdd_changelog_enabled(env, mdd, type))
+ RETURN(0);
+
handle = mdd_trans_create(env, mdd);
if (IS_ERR(handle))
RETURN(PTR_ERR(handle));
- rc = mdd_declare_changelog_store(env, mdd, NULL, NULL, handle);
+ rc = mdd_declare_changelog_store(env, mdd, type, NULL, NULL, handle);
if (rc)
GOTO(stop, rc);
}
#endif
- rc = mdd_declare_changelog_store(env, mdd, NULL, NULL, handle);
+ rc = mdd_declare_changelog_store(env, mdd, CL_SETXATTR, NULL, NULL,
+ handle);
return rc;
}
return false;
}
+static inline __u64 mdd_lmm_dom_size(void *buf)
+{
+ struct lov_mds_md *lmm = buf;
+ struct lov_comp_md_v1 *comp_v1;
+ struct lov_mds_md *v1;
+ __u32 off;
+
+ if (lmm == NULL)
+ return 0;
+
+ if (le32_to_cpu(lmm->lmm_magic) != LOV_MAGIC_COMP_V1)
+ return 0;
+
+ comp_v1 = (struct lov_comp_md_v1 *)lmm;
+ off = le32_to_cpu(comp_v1->lcm_entries[0].lcme_offset);
+ v1 = (struct lov_mds_md *)((char *)comp_v1 + off);
+
+ /* DoM entry is the first entry always */
+ if (lov_pattern(le32_to_cpu(v1->lmm_pattern)) == LOV_PATTERN_MDT)
+ return le64_to_cpu(comp_v1->lcm_entries[0].lcme_extent.e_end);
+
+ return 0;
+}
+
/* set attr and LOV EA at once, return updated attr */
int mdd_attr_set(const struct lu_env *env, struct md_object *obj,
const struct md_attr *ma)
la->la_mtime, la->la_ctime);
mdd_write_lock(env, mdd_obj, MOR_TGT_CHILD);
+
+ /* LU-10509: setattr of LA_SIZE should be skipped case of DOM,
+ * otherwise following truncate will do nothing and truncated
+ * data may be read again. This is a quick fix until LU-11033
+ * will be resolved.
+ */
+ if (la_copy->la_valid & LA_SIZE) {
+ struct lu_buf *lov_buf = mdd_buf_get(env, NULL, 0);
+
+ rc = mdd_stripe_get(env, mdd_obj, lov_buf, XATTR_NAME_LOV);
+ if (rc) {
+ rc = 0;
+ } else {
+ if (mdd_lmm_dom_size(lov_buf->lb_buf) > 0)
+ la_copy->la_valid &= ~LA_SIZE;
+ lu_buf_free(lov_buf);
+ }
+ }
+
if (la_copy->la_valid) {
rc = mdd_attr_set_internal(env, mdd_obj, la_copy, handle, 1);
(uc->uc_fsuid != attr->la_uid) &&
!md_capable(uc, CFS_CAP_FOWNER))
RETURN(-EPERM);
- } else {
- if ((uc->uc_fsuid != attr->la_uid) &&
- !md_capable(uc, CFS_CAP_FOWNER))
- RETURN(-EPERM);
+ } else if (strcmp(name, XATTR_NAME_SOM) != 0 &&
+ (uc->uc_fsuid != attr->la_uid) &&
+ !md_capable(uc, CFS_CAP_FOWNER)) {
+ RETURN(-EPERM);
}
RETURN(0);
if (strcmp(XATTR_NAME_HSM, xattr_name) == 0)
return CL_HSM;
+ /* Avoid logging SOM xattr for every file */
+ if (strcmp(XATTR_NAME_SOM, xattr_name) == 0)
+ return CL_NONE;
+
if (has_prefix(xattr_name, XATTR_USER_PREFIX) ||
has_prefix(xattr_name, XATTR_NAME_POSIX_ACL_ACCESS) ||
has_prefix(xattr_name, XATTR_NAME_POSIX_ACL_DEFAULT) ||
has_prefix(xattr_name, XATTR_SECURITY_PREFIX))
return CL_SETXATTR;
- return -1;
+ return CL_NONE;
}
static int mdd_declare_xattr_set(const struct lu_env *env,
const char *name,
int fl, struct thandle *handle)
{
- int rc;
+ enum changelog_rec_type type;
+ int rc;
rc = mdo_declare_xattr_set(env, obj, buf, name, fl, handle);
if (rc)
return rc;
- if (mdd_xattr_changelog_type(env, mdd, name) < 0)
+ type = mdd_xattr_changelog_type(env, mdd, name);
+ if (type < 0)
return 0; /* no changelog to store */
- return mdd_declare_changelog_store(env, mdd, NULL, NULL, handle);
+ return mdd_declare_changelog_store(env, mdd, type, NULL, NULL, handle);
}
/*
/* get EA of victim file */
memset(buf_vic, 0, sizeof(*buf_vic));
- rc = mdd_get_lov_ea(env, vic, buf_vic);
+ rc = mdd_stripe_get(env, vic, buf_vic, XATTR_NAME_LOV);
if (rc < 0) {
if (rc == -ENODATA)
rc = 0;
/* save EA of target file for restore */
memset(buf, 0, sizeof(*buf));
- rc = mdd_get_lov_ea(env, obj, buf);
+ rc = mdd_stripe_get(env, obj, buf, XATTR_NAME_LOV);
if (rc < 0)
GOTO(out, rc);
/* get EA of mirrored file */
memset(buf_save, 0, sizeof(*buf));
- rc = mdd_get_lov_ea(env, obj, buf_save);
+ rc = mdd_stripe_get(env, obj, buf_save, XATTR_NAME_LOV);
if (rc < 0)
GOTO(out, rc);
RETURN(rc);
}
+ if (strcmp(name, XATTR_NAME_LMV) == 0) {
+ rc = mdd_dir_layout_shrink(env, obj, buf);
+ RETURN(rc);
+ }
+
if (strcmp(name, XATTR_NAME_ACL_ACCESS) == 0 ||
strcmp(name, XATTR_NAME_ACL_DEFAULT) == 0) {
struct posix_acl *acl;
const char *name,
struct thandle *handle)
{
+ enum changelog_rec_type type;
int rc;
rc = mdo_declare_xattr_del(env, obj, name, handle);
if (rc)
return rc;
- if (mdd_xattr_changelog_type(env, mdd, name) < 0)
+ type = mdd_xattr_changelog_type(env, mdd, name);
+ if (type < 0)
return 0; /* no changelog to store */
- return mdd_declare_changelog_store(env, mdd, NULL, NULL, handle);
+ return mdd_declare_changelog_store(env, mdd, type, NULL, NULL, handle);
}
/**
}
/*
- * read lov EA of an object
- * return the lov EA in an allocated lu_buf
+ * read lov/lmv EA of an object
+ * return the lov/lmv EA in an allocated lu_buf
*/
-int mdd_get_lov_ea(const struct lu_env *env, struct mdd_object *obj,
- struct lu_buf *lmm_buf)
+int mdd_stripe_get(const struct lu_env *env, struct mdd_object *obj,
+ struct lu_buf *lmm_buf, const char *name)
{
- struct lu_buf *buf = &mdd_env_info(env)->mti_big_buf;
- int rc, bufsize;
+ struct lu_buf *buf = &mdd_env_info(env)->mti_big_buf;
+ int rc;
+
ENTRY;
-repeat:
- rc = mdo_xattr_get(env, obj, buf, XATTR_NAME_LOV);
+ if (buf->lb_buf == NULL) {
+ buf = lu_buf_check_and_alloc(buf, 4096);
+ if (buf->lb_buf == NULL)
+ RETURN(-ENOMEM);
+ }
+repeat:
+ rc = mdo_xattr_get(env, obj, buf, name);
if (rc == -ERANGE) {
/* mti_big_buf is allocated but is too small
* we need to increase it */
buf = lu_buf_check_and_alloc(&mdd_env_info(env)->mti_big_buf,
buf->lb_len * 2);
if (buf->lb_buf == NULL)
- GOTO(out, rc = -ENOMEM);
+ RETURN(-ENOMEM);
goto repeat;
- }
-
- if (rc < 0)
+ } else if (rc < 0) {
RETURN(rc);
-
- if (rc == 0)
+ } else if (rc == 0) {
RETURN(-ENODATA);
-
- bufsize = rc;
- if (memcmp(buf, &LU_BUF_NULL, sizeof(*buf)) == 0) {
- /* mti_big_buf was not allocated, so we have to
- * allocate it based on the ea size */
- buf = lu_buf_check_and_alloc(&mdd_env_info(env)->mti_big_buf,
- bufsize);
- if (buf->lb_buf == NULL)
- GOTO(out, rc = -ENOMEM);
- goto repeat;
}
- lu_buf_alloc(lmm_buf, bufsize);
+ lu_buf_alloc(lmm_buf, rc);
if (lmm_buf->lb_buf == NULL)
- GOTO(out, rc = -ENOMEM);
+ RETURN(-ENOMEM);
- memcpy(lmm_buf->lb_buf, buf->lb_buf, bufsize);
- rc = 0;
- EXIT;
+ /*
+ * we don't use lmm_buf directly, because we don't know xattr size, so
+ * by using mti_big_buf we can avoid calling mdo_xattr_get() twice.
+ */
+ memcpy(lmm_buf->lb_buf, buf->lb_buf, rc);
-out:
- if (rc < 0)
- lu_buf_free(lmm_buf);
- return rc;
+ RETURN(0);
}
static int mdd_xattr_hsm_replace(const struct lu_env *env,
return mdd_lmm_gen(lmm, gen, false);
}
+static int mdd_dom_data_truncate(const struct lu_env *env,
+ struct mdd_device *mdd, struct mdd_object *mo)
+{
+ struct thandle *th;
+ struct dt_object *dom;
+ int rc;
+
+ dom = dt_object_locate(mdd_object_child(mo), mdd->mdd_bottom);
+ if (!dom)
+ GOTO(out, rc = -ENODATA);
+
+ th = dt_trans_create(env, mdd->mdd_bottom);
+ if (IS_ERR(th))
+ GOTO(out, rc = PTR_ERR(th));
+
+ rc = dt_declare_punch(env, dom, 0, OBD_OBJECT_EOF, th);
+ if (rc)
+ GOTO(stop, rc);
+
+ rc = dt_trans_start_local(env, mdd->mdd_bottom, th);
+ if (rc != 0)
+ GOTO(stop, rc);
+
+ rc = dt_punch(env, dom, 0, OBD_OBJECT_EOF, th);
+stop:
+ dt_trans_stop(env, mdd->mdd_bottom, th);
+out:
+ /* Ignore failure but report the error */
+ if (rc)
+ CERROR("%s: "DFID" can't truncate DOM inode data, rc = %d\n",
+ mdd_obj_dev_name(mo), PFID(mdo2fid(mo)), rc);
+ return rc;
+}
+
/**
* swap layouts between 2 lustre objects
*/
static int mdd_swap_layouts(const struct lu_env *env, struct md_object *obj1,
struct md_object *obj2, __u64 flags)
{
- struct mdd_thread_info *info = mdd_env_info(env);
- struct mdd_object *fst_o = md2mdd_obj(obj1);
- struct mdd_object *snd_o = md2mdd_obj(obj2);
- struct lu_attr *fst_la = MDD_ENV_VAR(env, cattr);
- struct lu_attr *snd_la = MDD_ENV_VAR(env, tattr);
- struct mdd_device *mdd = mdo2mdd(obj1);
- struct lov_mds_md *fst_lmm, *snd_lmm;
- struct lu_buf *fst_buf = &info->mti_buf[0];
- struct lu_buf *snd_buf = &info->mti_buf[1];
- struct lu_buf *fst_hsm_buf = &info->mti_buf[2];
- struct lu_buf *snd_hsm_buf = &info->mti_buf[3];
- struct ost_id *saved_oi = NULL;
- struct thandle *handle;
- __u32 fst_gen, snd_gen, saved_gen;
- int fst_fl;
- int rc;
- int rc2;
+ struct mdd_thread_info *info = mdd_env_info(env);
+ struct mdd_object *fst_o = md2mdd_obj(obj1);
+ struct mdd_object *snd_o = md2mdd_obj(obj2);
+ struct lu_attr *fst_la = MDD_ENV_VAR(env, cattr);
+ struct lu_attr *snd_la = MDD_ENV_VAR(env, tattr);
+ struct mdd_device *mdd = mdo2mdd(obj1);
+ struct lov_mds_md *fst_lmm, *snd_lmm;
+ struct lu_buf *fst_buf = &info->mti_buf[0];
+ struct lu_buf *snd_buf = &info->mti_buf[1];
+ struct lu_buf *fst_hsm_buf = &info->mti_buf[2];
+ struct lu_buf *snd_hsm_buf = &info->mti_buf[3];
+ struct ost_id *saved_oi = NULL;
+ struct thandle *handle;
+ struct mdd_object *dom_o = NULL;
+ __u64 domsize_dom, domsize_vlt;
+ __u32 fst_gen, snd_gen, saved_gen;
+ int fst_fl;
+ int rc, rc2;
+
ENTRY;
CLASSERT(ARRAY_SIZE(info->mti_buf) >= 4);
mdd_write_lock(env, fst_o, MOR_TGT_CHILD);
mdd_write_lock(env, snd_o, MOR_TGT_CHILD);
- rc = mdd_get_lov_ea(env, fst_o, fst_buf);
+ rc = mdd_stripe_get(env, fst_o, fst_buf, XATTR_NAME_LOV);
if (rc < 0 && rc != -ENODATA)
GOTO(stop, rc);
- rc = mdd_get_lov_ea(env, snd_o, snd_buf);
+ rc = mdd_stripe_get(env, snd_o, snd_buf, XATTR_NAME_LOV);
if (rc < 0 && rc != -ENODATA)
GOTO(stop, rc);
+ /* check if file has DoM. DoM file can be migrated only to another
+ * DoM layout with the same DoM component size or to an non-DOM
+ * layout. After migration to OSTs layout, local MDT inode data
+ * should be truncated.
+ * Objects are sorted by FIDs, considering that original file's FID
+ * is always smaller the snd_o is always original file we are migrating
+ * from.
+ */
+ domsize_dom = mdd_lmm_dom_size(snd_buf->lb_buf);
+ domsize_vlt = mdd_lmm_dom_size(fst_buf->lb_buf);
+
+ /* Only migration is supported for DoM files, not 'swap_layouts' so
+ * target file must be volatile and orphan.
+ */
+ if (fst_o->mod_flags & (ORPHAN_OBJ | VOLATILE_OBJ)) {
+ dom_o = domsize_dom ? snd_o : NULL;
+ } else if (snd_o->mod_flags & (ORPHAN_OBJ | VOLATILE_OBJ)) {
+ swap(domsize_dom, domsize_vlt);
+ dom_o = domsize_dom ? fst_o : NULL;
+ } else if (domsize_dom > 0 || domsize_vlt > 0) {
+ /* 'lfs swap_layouts' case, neither file should have DoM */
+ rc = -EOPNOTSUPP;
+ CDEBUG(D_LAYOUT, "cannot swap layouts with DOM component, "
+ "use migration instead: rc = %d\n", rc);
+ GOTO(stop, rc);
+ }
+
+ if (domsize_vlt > 0 && domsize_dom == 0) {
+ rc = -EOPNOTSUPP;
+ CDEBUG(D_LAYOUT, "cannot swap layout for "DFID": OST to DOM "
+ "migration is not supported: rc = %d\n",
+ PFID(mdo2fid(snd_o)), rc);
+ GOTO(stop, rc);
+ } else if (domsize_vlt > 0 && domsize_dom != domsize_vlt) {
+ rc = -EOPNOTSUPP;
+ CDEBUG(D_LAYOUT, "cannot swap layout for "DFID": new layout "
+ "must have the same DoM component size: rc = %d\n",
+ PFID(mdo2fid(fst_o)), rc);
+ GOTO(stop, rc);
+ } else if (domsize_vlt > 0) {
+ /* Migration with the same DOM component size, no need to
+ * truncate local data, it is still being used */
+ dom_o = NULL;
+ }
+
/* swapping 2 non existant layouts is a success */
if (fst_buf->lb_buf == NULL && snd_buf->lb_buf == NULL)
GOTO(stop, rc = 0);
stop:
rc = mdd_trans_stop(env, mdd, rc, handle);
+ /* Truncate local DOM data if all went well */
+ if (!rc && dom_o)
+ mdd_dom_data_truncate(env, mdd, dom_o);
+
mdd_write_unlock(env, snd_o);
mdd_write_unlock(env, fst_o);
if (rc)
return rc;
- return mdd_declare_changelog_store(env, mdd, NULL, NULL, handle);
+ return mdd_declare_changelog_store(env, mdd, CL_LAYOUT, NULL, NULL,
+ handle);
}
/* For PFL, this is used to instantiate necessary component objects. */
struct md_layout_change *mlc, struct thandle *handle)
{
struct mdd_device *mdd = mdd_obj2mdd_dev(obj);
+ struct lu_buf *som_buf = &mdd_env_info(env)->mti_buf[1];
+ struct lustre_som_attrs *som = &mlc->mlc_som;
+ int fl = 0;
int rc;
ENTRY;
RETURN(0);
}
+ som_buf->lb_buf = som;
+ som_buf->lb_len = sizeof(*som);
+ rc = mdo_xattr_get(env, obj, som_buf, XATTR_NAME_SOM);
+ if (rc < 0 && rc != -ENODATA)
+ RETURN(rc);
+
+ if (rc > 0) {
+ lustre_som_swab(som);
+ if (som->lsa_valid & SOM_FL_STRICT)
+ fl = LU_XATTR_REPLACE;
+ }
+
rc = mdd_declare_layout_change(env, mdd, obj, mlc, handle);
if (rc)
GOTO(out, rc);
- rc = mdd_declare_xattr_del(env, mdd, obj, XATTR_NAME_SOM, handle);
- if (rc)
- GOTO(out, rc);
+ if (fl) {
+ rc = mdd_declare_xattr_set(env, mdd, obj, som_buf,
+ XATTR_NAME_SOM, fl, handle);
+ if (rc)
+ GOTO(out, rc);
+ }
/* record a changelog for data mover to consume */
- rc = mdd_declare_changelog_store(env, mdd, NULL, NULL, handle);
+ rc = mdd_declare_changelog_store(env, mdd, CL_FLRW, NULL, NULL, handle);
if (rc)
GOTO(out, rc);
mdd_write_lock(env, obj, MOR_TGT_CHILD);
rc = mdo_layout_change(env, obj, mlc, handle);
- if (!rc) {
- rc = mdo_xattr_del(env, obj, XATTR_NAME_SOM, handle);
- if (rc == -ENODATA)
- rc = 0;
+ if (!rc && fl) {
+ /* SOM state transition from STRICT to STALE */
+ som->lsa_valid = SOM_FL_STALE;
+ lustre_som_swab(som);
+ rc = mdo_xattr_set(env, obj, som_buf, XATTR_NAME_SOM,
+ fl, handle);
}
mdd_write_unlock(env, obj);
if (rc)
RETURN(-EBUSY);
}
- if (mlc->mlc_som.lsa_valid & LSOM_FL_VALID) {
+ if (mlc->mlc_som.lsa_valid & SOM_FL_STRICT) {
rc = mdo_xattr_get(env, obj, &LU_BUF_NULL, XATTR_NAME_SOM);
- if (rc && rc != -ENODATA)
+ if (rc < 0 && rc != -ENODATA)
RETURN(rc);
fl = rc == -ENODATA ? LU_XATTR_CREATE : LU_XATTR_REPLACE;
+ lustre_som_swab(&mlc->mlc_som);
som_buf->lb_buf = &mlc->mlc_som;
som_buf->lb_len = sizeof(mlc->mlc_som);
}
GOTO(out, rc);
/* record a changelog for the completion of resync */
- rc = mdd_declare_changelog_store(env, mdd, NULL, NULL, handle);
+ rc = mdd_declare_changelog_store(env, mdd, CL_RESYNC, NULL, NULL,
+ handle);
if (rc)
GOTO(out, rc);
if (IS_ERR(handle))
RETURN(PTR_ERR(handle));
- rc = mdd_get_lov_ea(env, obj, buf);
+ rc = mdd_stripe_get(env, obj, buf, XATTR_NAME_LOV);
if (rc < 0) {
if (rc == -ENODATA)
rc = -EINVAL;
return 0;
}
- if (flags & FMODE_READ)
+ if (flags & MDS_FMODE_READ)
res |= MAY_READ;
- if (flags & (FMODE_WRITE | MDS_OPEN_TRUNC | MDS_OPEN_APPEND))
+ if (flags & (MDS_FMODE_WRITE | MDS_OPEN_TRUNC | MDS_OPEN_APPEND))
res |= MAY_WRITE;
if (flags & MDS_FMODE_EXEC)
res = MAY_EXEC;
int mode, rc;
ENTRY;
- /* EEXIST check */
- if (mdd_is_dead_obj(obj))
+ /* EEXIST check, also opening of *open* orphans is allowed so we can
+ * open-by-handle unlinked files
+ */
+ if (mdd_is_dead_obj(obj) &&
+ likely(!(mdd_is_orphan_obj(obj) && obj->mod_count > 0)))
RETURN(-ENOENT);
if (S_ISLNK(attr->la_mode))
/* For writing append-only file must open it with append mode. */
if (attr->la_flags & LUSTRE_APPEND_FL) {
- if ((flag & FMODE_WRITE) && !(flag & MDS_OPEN_APPEND))
+ if ((flag & MDS_FMODE_WRITE) && !(flag & MDS_OPEN_APPEND))
RETURN(-EPERM);
if (flag & MDS_OPEN_TRUNC)
RETURN(-EPERM);
struct mdd_object_user *mou = NULL;
const struct lu_ucred *uc = lu_ucred(env);
struct mdd_device *mdd = mdo2mdd(obj);
- int type = CL_OPEN;
+ enum changelog_rec_type type = CL_OPEN;
int rc = 0;
mdd_write_lock(env, mdd_obj, MOR_TGT_CHILD);
else
mdd_obj->mod_count++;
- /* Not recording */
- if (!recording_changelog(env, mdd))
- GOTO(out, rc);
- if (!(mdd->mdd_cl.mc_mask & (1 << type)))
+ if (!mdd_changelog_enabled(env, mdd, type))
GOTO(out, rc);
find:
if (rc)
GOTO(stop, rc);
- rc = mdd_declare_changelog_store(env, mdd, NULL, NULL, handle);
+ rc = mdd_declare_changelog_store(env, mdd, CL_CLOSE, NULL, NULL,
+ handle);
if (rc)
GOTO(stop, rc);
/* under mdd write lock */
/* If recording, see if we need to remove UID from list */
- if ((mdd->mdd_cl.mc_flags & CLM_ON) &&
- (mdd->mdd_cl.mc_mask & (1 << CL_OPEN))) {
+ if (mdd_changelog_enabled(env, mdd, CL_OPEN)) {
struct mdd_object_user *mou;
/* look for UID in list */
out:
mdd_write_unlock(env, mdd_obj);
+ if (rc != 0 || blocked ||
+ !mdd_changelog_enabled(env, mdd, CL_CLOSE))
+ GOTO(stop, rc);
+
/* Record CL_CLOSE in changelog only if file was opened in write mode,
* or if CL_OPEN was recorded and it's last close by user.
* Changelogs mask may change between open and close operations, but
* this is not a big deal if we have a CL_CLOSE entry with no matching
* CL_OPEN. Plus Changelogs mask may not change often.
*/
- if (!rc && !blocked &&
- ((!(mdd->mdd_cl.mc_mask & (1 << CL_OPEN)) &&
- (mode & (FMODE_WRITE | MDS_OPEN_APPEND | MDS_OPEN_TRUNC))) ||
+ if (((!(mdd->mdd_cl.mc_mask & (1 << CL_OPEN)) &&
+ (mode & (MDS_FMODE_WRITE | MDS_OPEN_APPEND | MDS_OPEN_TRUNC))) ||
((mdd->mdd_cl.mc_mask & (1 << CL_OPEN)) && last_close_by_uid)) &&
!(ma->ma_valid & MA_FLAGS && ma->ma_attr_flags & MDS_RECOV_OPEN)) {
if (handle == NULL) {
if (IS_ERR(handle))
GOTO(stop, rc = PTR_ERR(handle));
- rc = mdd_declare_changelog_store(env, mdd, NULL, NULL,
- handle);
+ rc = mdd_declare_changelog_store(env, mdd, CL_CLOSE,
+ NULL, NULL, handle);
if (rc)
GOTO(stop, rc);