return rc;
}
- if (la->la_valid & LA_FLAGS &&
- la->la_flags & LUSTRE_ORPHAN_FL)
+ if (la->la_valid & LA_FLAGS && la->la_flags & LUSTRE_ORPHAN_FL)
obj->mod_flags |= ORPHAN_OBJ | DEAD_OBJ;
return 0;
struct mdd_thread_info *mdd_env_info(const struct lu_env *env)
{
- struct mdd_thread_info *info;
-
- lu_env_refill((struct lu_env *)env);
- info = lu_context_key_get(&env->le_ctx, &mdd_thread_key);
- LASSERT(info != NULL);
- return info;
+ return lu_env_info(env, &mdd_thread_key);
}
struct lu_buf *mdd_buf_get(const struct lu_env *env, void *area, ssize_t len)
strcmp(name, XATTR_NAME_LINK) == 0))
RETURN(-ENOENT);
- mdd_read_lock(env, mdd_obj, MOR_TGT_CHILD);
+ mdd_read_lock(env, mdd_obj, DT_TGT_CHILD);
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 &&
+ if (rc >= 0 && buf->lb_buf &&
mdd_changelog_enabled(env, mdd, CL_GETXATTR) &&
(has_prefix(name, XATTR_USER_PREFIX) ||
has_prefix(name, XATTR_NAME_POSIX_ACL_ACCESS) ||
LASSERT(next != NULL);
LASSERT(next->do_body_ops != NULL);
LASSERT(next->do_body_ops->dbo_read != NULL);
- mdd_read_lock(env, mdd_obj, MOR_TGT_CHILD);
+ mdd_read_lock(env, mdd_obj, DT_TGT_CHILD);
rc = dt_read(env, next, buf, &pos);
mdd_read_unlock(env, mdd_obj);
RETURN(rc);
ENTRY;
- mdd_read_lock(env, mdd_obj, MOR_TGT_CHILD);
+ mdd_read_lock(env, mdd_obj, DT_TGT_CHILD);
rc = mdo_xattr_list(env, mdd_obj, buf);
mdd_read_unlock(env, mdd_obj);
ENTRY;
rc = mdo_attr_set(env, obj, attr, handle);
-#ifdef CONFIG_FS_POSIX_ACL
+#ifdef CONFIG_LUSTRE_FS_POSIX_ACL
if (!rc && (attr->la_valid & LA_MODE) && needacl)
rc = mdd_acl_chmod(env, obj, attr->la_mode, handle);
#endif
RETURN(rc);
}
+
+static bool is_project_state_change(const struct lu_attr *oattr,
+ struct lu_attr *la)
+{
+ if (la->la_valid & LA_PROJID &&
+ oattr->la_projid != la->la_projid)
+ return true;
+
+ if ((la->la_valid & LA_FLAGS) &&
+ (la->la_flags & LUSTRE_PROJINHERIT_FL) !=
+ (oattr->la_flags & LUSTRE_PROJINHERIT_FL))
+ return true;
+
+ return false;
+}
+
/*
* This gives the same functionality as the code between
* sys_chmod and inode_setattr
*/
static int mdd_fix_attr(const struct lu_env *env, struct mdd_object *obj,
const struct lu_attr *oattr, struct lu_attr *la,
- const unsigned long flags)
+ const struct md_attr *ma)
{
struct lu_ucred *uc;
int rc = 0;
+ const unsigned long flags = ma->ma_attr_flags;
+
ENTRY;
if (!la->la_valid)
if (uc == NULL)
RETURN(0);
+ if (is_project_state_change(oattr, la)) {
+ if (!md_capable(uc, CFS_CAP_SYS_RESOURCE) &&
+ !lustre_in_group_p(uc, ma->ma_enable_chprojid_gid) &&
+ !(ma->ma_enable_chprojid_gid == -1 &&
+ mdd_permission_internal(env, obj, oattr, MAY_WRITE)))
+ RETURN(-EPERM);
+ }
+
if (la->la_valid == LA_CTIME) {
if (!(flags & MDS_PERM_BYPASS))
/* This is only for set ctime when rename's source is
RETURN(rc);
}
- if (la->la_valid == LA_ATIME) {
- /* This is an atime-only attribute update for close RPCs. */
- if (la->la_atime < (oattr->la_atime +
+ if (flags & MDS_CLOSE_UPDATE_TIMES &&
+ la->la_valid & (LA_ATIME | LA_MTIME | LA_CTIME)) {
+ /* This is an atime/mtime/ctime attribute update for
+ * close RPCs.
+ */
+ if (la->la_valid & LA_ATIME &&
+ la->la_atime <= (oattr->la_atime +
mdd_obj2mdd_dev(obj)->mdd_atime_diff))
la->la_valid &= ~LA_ATIME;
+ if (la->la_valid & LA_CTIME && la->la_ctime <= oattr->la_ctime)
+ la->la_valid &= ~LA_CTIME;
+ if (la->la_valid & LA_MTIME && la->la_mtime <= oattr->la_mtime)
+ la->la_valid &= ~LA_MTIME;
RETURN(0);
}
bits |= (valid & LA_ATIME) ? 1 << CL_ATIME : 0;
bits = bits & mdd->mdd_cl.mc_mask;
/* This is an implementation limit rather than a protocol limit */
- CLASSERT(CL_LAST <= sizeof(int) * 8);
+ BUILD_BUG_ON(CL_LAST > sizeof(int) * 8);
if (bits == 0)
return 0;
if (rc)
return rc;
-#ifdef CONFIG_FS_POSIX_ACL
+#ifdef CONFIG_LUSTRE_FS_POSIX_ACL
if (attr->la_valid & LA_MODE) {
- mdd_read_lock(env, obj, MOR_TGT_CHILD);
+ mdd_read_lock(env, obj, DT_TGT_CHILD);
rc = mdo_xattr_get(env, obj, &LU_BUF_NULL,
XATTR_NAME_ACL_ACCESS);
mdd_read_unlock(env, obj);
/*
* LU-3671
+ * LU-7239
*
* permission changes may require sync operation, to mitigate performance
* impact, only do this for dir and when permission is reduced.
if (!S_ISDIR(old->la_mode))
return false;
- if (new->la_valid & (LA_UID | LA_GID))
+ if (new->la_valid & LA_UID && old->la_uid != new->la_uid)
return true;
- if (new->la_valid & LA_MODE &&
- new->la_mode & (S_ISUID | S_ISGID | S_ISVTX))
+ if (new->la_valid & LA_GID && old->la_gid != new->la_gid)
return true;
- if ((new->la_valid & LA_MODE) &&
- ((new->la_mode & old->la_mode) & S_IRWXUGO) !=
- (old->la_mode & S_IRWXUGO))
- return true;
+ if (new->la_valid & LA_MODE) {
+ /* turned on sticky bit */
+ if (!(old->la_mode & S_ISVTX) && (new->la_mode & S_ISVTX))
+ return true;
+
+ /* set-GID has no impact on what is allowed, not checked */
+
+ /* turned off setuid bit, or one of rwx for someone */
+ if (((new->la_mode & old->la_mode) & (0777 | S_ISUID)) !=
+ (old->la_mode & (0777 | S_ISUID)))
+ return true;
+ }
return false;
}
RETURN(rc);
*la_copy = ma->ma_attr;
- rc = mdd_fix_attr(env, mdd_obj, attr, la_copy, ma->ma_attr_flags);
+ rc = mdd_fix_attr(env, mdd_obj, attr, la_copy, ma);
if (rc)
RETURN(rc);
/* no need to setattr anymore */
if (la_copy->la_valid == 0) {
- CDEBUG(D_INODE, "%s: no valid attribute on "DFID", previous"
- "valid is %#llx\n", mdd2obd_dev(mdd)->obd_name,
+ CDEBUG(D_INODE,
+ "%s: no valid attribute on "DFID", previous valid is %#llx\n",
+ mdd2obd_dev(mdd)->obd_name,
PFID(mdo2fid(mdd_obj)), la->la_valid);
RETURN(0);
CDEBUG(D_INODE, "setting mtime %llu, ctime %llu\n",
la->la_mtime, la->la_ctime);
- mdd_write_lock(env, mdd_obj, MOR_TGT_CHILD);
+ mdd_write_lock(env, mdd_obj, DT_TGT_CHILD);
/* LU-10509: setattr of LA_SIZE should be skipped case of DOM,
* otherwise following truncate will do nothing and truncated
*
* \param[in] xattr_name Full extended attribute name.
*
- * \return The type of changelog to use, or -1 if no changelog is to be emitted.
+ * \return type of changelog to use, or CL_NONE if no changelog is to be emitted
*/
static enum changelog_rec_type
mdd_xattr_changelog_type(const struct lu_env *env, struct mdd_device *mdd,
{
/* Layout changes systematically recorded */
if (strcmp(XATTR_NAME_LOV, xattr_name) == 0 ||
- strncmp(XATTR_LUSTRE_LOV, xattr_name,
- strlen(XATTR_LUSTRE_LOV)) == 0)
+ strcmp(XATTR_LUSTRE_LOV, xattr_name) == 0 ||
+ allowed_lustre_lov(xattr_name))
return CL_LAYOUT;
/* HSM information changes systematically recorded */
/* Read HSM attrs from disk */
current_buf = lu_buf_check_and_alloc(&info->mti_xattr_buf,
- mdo2mdd(obj)->mdd_dt_conf.ddp_max_ea_size);
+ MIN(mdd_obj2mdd_dev(mdd_obj)->mdd_dt_conf.ddp_max_ea_size,
+ XATTR_SIZE_MAX));
rc = mdo_xattr_get(env, mdd_obj, current_buf, XATTR_NAME_HSM);
rc = lustre_buf2hsm(current_buf->lb_buf, rc, current_mh);
if (rc < 0 && rc != -ENODATA)
RETURN(PTR_ERR(handle));
if (rc > 0) {
- mdd_write_lock(env, obj, MOR_TGT_CHILD);
- mdd_write_lock(env, vic, MOR_TGT_CHILD);
+ mdd_write_lock(env, obj, DT_TGT_CHILD);
+ mdd_write_lock(env, vic, DT_TGT_CHILD);
} else {
- mdd_write_lock(env, vic, MOR_TGT_CHILD);
- mdd_write_lock(env, obj, MOR_TGT_CHILD);
+ mdd_write_lock(env, vic, DT_TGT_CHILD);
+ mdd_write_lock(env, obj, DT_TGT_CHILD);
}
/* get EA of victim file */
return 0;
}
+static int mdd_dom_data_truncate(const struct lu_env *env,
+ struct mdd_device *mdd, struct mdd_object *mo);
+
static int mdd_xattr_split(const struct lu_env *env, struct md_object *md_obj,
struct md_rejig_data *mrd)
{
struct lov_comp_md_v1 *lcm;
struct thandle *handle;
int rc;
+ bool dom_stripe = false;
+
ENTRY;
rc = lu_fid_cmp(mdo2fid(obj), mdo2fid(vic));
RETURN(PTR_ERR(handle));
if (rc > 0) {
- mdd_write_lock(env, obj, MOR_TGT_CHILD);
- mdd_write_lock(env, vic, MOR_TGT_CHILD);
+ mdd_write_lock(env, obj, DT_TGT_CHILD);
+ mdd_write_lock(env, vic, DT_TGT_CHILD);
} else {
- mdd_write_lock(env, vic, MOR_TGT_CHILD);
- mdd_write_lock(env, obj, MOR_TGT_CHILD);
+ mdd_write_lock(env, vic, DT_TGT_CHILD);
+ mdd_write_lock(env, obj, DT_TGT_CHILD);
}
/* get EA of mirrored file */
if (rc < 0)
GOTO(out, rc);
+ dom_stripe = mdd_lmm_dom_size(buf_vic->lb_buf) > 0;
+
rc = mdd_declare_xattr_set(env, mdd, obj, buf, XATTR_NAME_LOV,
LU_XATTR_SPLIT, handle);
if (rc)
mdd_obj_dev_name(obj), PFID(mdo2fid(obj)), rc2);
}
out:
- mdd_trans_stop(env, mdd, rc, handle);
+ rc = mdd_trans_stop(env, mdd, rc, handle);
+
+ /* Truncate local DOM data if all went well */
+ if (!rc && dom_stripe)
+ mdd_dom_data_truncate(env, mdd, obj);
+
mdd_write_unlock(env, obj);
mdd_write_unlock(env, vic);
lu_buf_free(buf_save);
if (rc)
GOTO(stop, rc);
- mdd_write_lock(env, mdd_obj, MOR_TGT_CHILD);
+ mdd_write_lock(env, mdd_obj, DT_TGT_CHILD);
if (strcmp(XATTR_NAME_HSM, name) == 0) {
rc = mdd_hsm_update_locked(env, obj, buf, handle, &clf_flags);
if (rc)
GOTO(stop, rc);
- mdd_write_lock(env, mdd_obj, MOR_TGT_CHILD);
+ mdd_write_lock(env, mdd_obj, DT_TGT_CHILD);
rc = mdo_xattr_del(env, mdd_obj, name, handle);
mdd_write_unlock(env, mdd_obj);
if (rc)
ENTRY;
- CLASSERT(ARRAY_SIZE(info->mti_buf) >= 4);
+ BUILD_BUG_ON(ARRAY_SIZE(info->mti_buf) < 4);
memset(info->mti_buf, 0, sizeof(info->mti_buf));
/* we have to sort the 2 obj, so locking will always
RETURN(PTR_ERR(handle));
/* objects are already sorted */
- mdd_write_lock(env, fst_o, MOR_TGT_CHILD);
- mdd_write_lock(env, snd_o, MOR_TGT_CHILD);
+ mdd_write_lock(env, fst_o, DT_TGT_CHILD);
+ mdd_write_lock(env, snd_o, DT_TGT_CHILD);
rc = mdd_stripe_get(env, fst_o, fst_buf, XATTR_NAME_LOV);
if (rc < 0 && rc != -ENODATA)
if (rc)
RETURN(rc);
- mdd_write_lock(env, obj, MOR_TGT_CHILD);
+ mdd_write_lock(env, obj, DT_TGT_CHILD);
rc = mdo_layout_change(env, obj, mlc, handle);
mdd_write_unlock(env, obj);
if (rc)
/* it needs a sync tx to make FLR to work properly */
handle->th_sync = 1;
- mdd_write_lock(env, obj, MOR_TGT_CHILD);
+ mdd_write_lock(env, obj, DT_TGT_CHILD);
rc = mdo_layout_change(env, obj, mlc, handle);
if (!rc && fl) {
/* SOM state transition from STRICT to STALE */
/* it needs a sync tx to make FLR to work properly */
handle->th_sync = 1;
- mdd_write_lock(env, obj, MOR_TGT_CHILD);
+ mdd_write_lock(env, obj, DT_TGT_CHILD);
rc = mdo_layout_change(env, obj, mlc, handle);
mdd_write_unlock(env, obj);
if (rc)
struct dt_allocation_hint *hint)
{
struct dt_object *np = parent ? mdd_object_child(parent) : NULL;
+ struct mdd_device *mdd = mdd_obj2mdd_dev(child);
struct dt_object *nc = mdd_object_child(child);
memset(hint, 0, sizeof(*hint));
} else {
hint->dah_eadata = NULL;
hint->dah_eadata_len = 0;
+ if (spec->sp_cr_flags & MDS_OPEN_APPEND) {
+ if (mdd->mdd_append_stripe_count != 0 ||
+ mdd->mdd_append_pool[0])
+ CDEBUG(D_INFO,
+ "using O_APPEND file striping\n");
+ if (mdd->mdd_append_stripe_count)
+ hint->dah_append_stripes =
+ mdd->mdd_append_stripe_count;
+ if (mdd->mdd_append_pool[0])
+ hint->dah_append_pool = mdd->mdd_append_pool;
+ } else {
+ hint->dah_append_stripes = 0;
+ }
}
CDEBUG(D_INFO, DFID" eadata %p len %d\n", PFID(mdd_object_fid(child)),
static int mdd_open_sanity_check(const struct lu_env *env,
struct mdd_object *obj,
- const struct lu_attr *attr, u64 open_flags)
+ const struct lu_attr *attr, u64 open_flags,
+ int is_replay)
{
int mode, rc;
ENTRY;
/* EEXIST check, also opening of *open* orphans is allowed so we can
* open-by-handle unlinked files
*/
- if (mdd_is_dead_obj(obj) &&
+ if (mdd_is_dead_obj(obj) && !is_replay &&
likely(!(mdd_is_orphan_obj(obj) && obj->mod_count > 0)))
RETURN(-ENOENT);
}
static int mdd_open(const struct lu_env *env, struct md_object *obj,
- u64 open_flags)
+ u64 open_flags, struct md_op_spec *spec)
{
struct mdd_object *mdd_obj = md2mdd_obj(obj);
struct md_device *md_dev = lu2md_dev(mdd2lu_dev(mdo2mdd(obj)));
struct mdd_device *mdd = mdo2mdd(obj);
enum changelog_rec_type type = CL_OPEN;
int rc = 0;
+ ENTRY;
- mdd_write_lock(env, mdd_obj, MOR_TGT_CHILD);
+ mdd_write_lock(env, mdd_obj, DT_TGT_CHILD);
rc = mdd_la_get(env, mdd_obj, attr);
if (rc != 0)
GOTO(out, rc);
- rc = mdd_open_sanity_check(env, mdd_obj, attr, open_flags);
+ rc = mdd_open_sanity_check(env, mdd_obj, attr, open_flags,
+ spec->no_create);
if ((rc == -EACCES) && (mdd->mdd_cl.mc_mask & (1 << CL_DN_OPEN)))
type = CL_DN_OPEN;
else if (rc != 0)
ENTRY;
if (ma->ma_valid & MA_FLAGS && ma->ma_attr_flags & MDS_KEEP_ORPHAN) {
- mdd_write_lock(env, mdd_obj, MOR_TGT_CHILD);
+ mdd_write_lock(env, mdd_obj, DT_TGT_CHILD);
mdd_obj->mod_count--;
mdd_write_unlock(env, mdd_obj);
}
cont:
- mdd_write_lock(env, mdd_obj, MOR_TGT_CHILD);
+ mdd_write_lock(env, mdd_obj, DT_TGT_CHILD);
rc = mdd_la_get(env, mdd_obj, &ma->ma_attr);
if (rc != 0) {
CERROR("%s: failed to get lu_attr of "DFID": rc = %d\n",
return -ENOENT;
}
- mdd_read_lock(env, mdd_obj, MOR_TGT_CHILD);
+ mdd_read_lock(env, mdd_obj, DT_TGT_CHILD);
rc = mdd_readpage_sanity_check(env, mdd_obj);
if (rc)
GOTO(out_unlock, rc);