}
static int cml_xattr_set(const struct lu_env *env, struct md_object *mo,
- const struct lu_buf *buf,
- const char *name, int fl)
+ const struct lu_buf *buf, const char *name,
+ int fl, const struct lu_attr *la)
{
int rc;
ENTRY;
- rc = mo_xattr_set(env, md_object_next(mo), buf, name, fl);
+ rc = mo_xattr_set(env, md_object_next(mo), buf, name, fl, la);
RETURN(rc);
}
static int cml_xattr_del(const struct lu_env *env, struct md_object *mo,
- const char *name)
+ const char *name, const struct lu_attr *la)
{
int rc;
ENTRY;
- rc = mo_xattr_del(env, md_object_next(mo), name);
+ rc = mo_xattr_del(env, md_object_next(mo), name, la);
RETURN(rc);
}
}
static int cmr_xattr_set(const struct lu_env *env, struct md_object *mo,
- const struct lu_buf *buf, const char *name, int fl)
+ const struct lu_buf *buf, const char *name,
+ int fl, const struct lu_attr *la)
{
return -EFAULT;
}
static int cmr_xattr_del(const struct lu_env *env, struct md_object *mo,
- const char *name)
+ const char *name, const struct lu_attr *la)
{
return -EFAULT;
}
LASSERT(ma->ma_valid & MA_LMV);
buf = cmm_buf_get(env, ma->ma_lmv, ma->ma_lmv_size);
rc = mo_xattr_set(env, md_object_next(mo), buf,
- MDS_LMV_MD_NAME, 0);
+ MDS_LMV_MD_NAME, 0, NULL);
if (rc) {
CERROR("Can't set MEA to master dir, " "rc %d\n", rc);
GOTO(cleanup, rc);
LA_NLINK = 1 << 10,
LA_RDEV = 1 << 11,
LA_BLKSIZE = 1 << 12,
+ LA_TRUNC = 1 << 13,
};
struct lu_attr {
#define MDS_ATTR_CTIME_SET 0x2000ULL /* = 8192 */
#define MDS_ATTR_FROM_OPEN 0x4000ULL /* = 16384, called from open path, ie O_TRUNC */
#define MDS_ATTR_BLOCKS 0x8000ULL /* = 32768 */
+#define MDS_ATTR_TRUNC 0x10000ULL /* = 65536 */
+
+#define ATTR_TRUNC MDS_ATTR_TRUNC
#ifndef FMODE_READ
#define FMODE_READ 00000001
__u32 sx_padding_2;
__u32 sx_padding_3;
__u64 sx_valid;
- __u64 sx_padding_4;
+ __u64 sx_time;
__u64 sx_padding_5;
__u64 sx_padding_6;
__u64 sx_padding_7;
int (*moo_xattr_set)(const struct lu_env *env, struct md_object *obj,
const struct lu_buf *buf, const char *name,
- int fl);
+ int fl, const struct lu_attr *la);
int (*moo_xattr_del)(const struct lu_env *env, struct md_object *obj,
- const char *name);
+ const char *name, const struct lu_attr *la);
int (*moo_readpage)(const struct lu_env *env, struct md_object *obj,
const struct lu_rdpg *rdpg);
static inline int mo_xattr_del(const struct lu_env *env,
struct md_object *m,
- const char *name)
+ const char *name,
+ const struct lu_attr *la)
{
LASSERT(m->mo_ops->moo_xattr_del);
- return m->mo_ops->moo_xattr_del(env, m, name);
+ return m->mo_ops->moo_xattr_del(env, m, name, la);
}
static inline int mo_xattr_set(const struct lu_env *env,
struct md_object *m,
const struct lu_buf *buf,
const char *name,
- int flags)
+ int flags,
+ const struct lu_attr *la)
{
LASSERT(m->mo_ops->moo_xattr_set);
- return m->mo_ops->moo_xattr_set(env, m, buf, name, flags);
+ return m->mo_ops->moo_xattr_set(env, m, buf, name, flags, la);
}
static inline int mo_xattr_list(const struct lu_env *env,
RETURN(-EFBIG);
}
- attr->ia_valid |= ATTR_MTIME | ATTR_CTIME;
+ attr->ia_valid |= ATTR_MTIME | ATTR_CTIME | ATTR_TRUNC;
}
/* We mark all of the fields "set" so MDS/OST does not re-set them */
RETURN(-EFBIG);
}
- attr->ia_valid |= ATTR_MTIME | ATTR_CTIME;
+ attr->ia_valid |= ATTR_MTIME | ATTR_CTIME | ATTR_TRUNC;
}
/* POSIX: check before ATTR_*TIME_SET set (from inode_change_ok) */
sa_valid |= MDS_ATTR_FROM_OPEN;
if (ia_valid & ATTR_BLOCKS)
sa_valid |= MDS_ATTR_BLOCKS;
+ if (ia_valid & ATTR_TRUNC)
+ sa_valid |= MDS_ATTR_TRUNC;
if (ia_valid & MDS_OPEN_OWNEROVERRIDE)
/* NFSD hack (see bug 5781) */
sa_valid |= MDS_OPEN_OWNEROVERRIDE;
rec->sx_fsgid = current->fsgid;
rec->sx_cap = current->cap_effective;
rec->sx_suppgid1 = suppgid;
- rec->sx_suppgid1 = -1;
+ rec->sx_suppgid2 = -1;
rec->sx_fid = *fid;
- rec->sx_valid = valid;
+ rec->sx_valid = valid | OBD_MD_FLCTIME;
+ rec->sx_time = cfs_time_current_sec();
rec->sx_size = output_size;
rec->sx_flags = flags;
la->la_ctime = la->la_mtime = ma->ma_attr.la_ctime;
la->la_valid = LA_CTIME | LA_MTIME;
- rc = mdd_attr_set_internal_locked(env, mdd_tobj, la, handle, 0);
+ rc = mdd_attr_check_set_internal_locked(env, mdd_tobj, la, handle, 0);
if (rc)
GOTO(out_unlock, rc);
la->la_valid = LA_CTIME;
- rc = mdd_attr_set_internal(env, mdd_sobj, la, handle, 0);
+ rc = mdd_attr_check_set_internal(env, mdd_sobj, la, handle, 0);
EXIT;
out_unlock:
mdd_write_unlock(env, mdd_sobj);
la->la_ctime = la->la_mtime = ma->ma_attr.la_ctime;
la->la_valid = LA_CTIME | LA_MTIME;
- rc = mdd_attr_set_internal_locked(env, mdd_pobj, la, handle, 0);
+ rc = mdd_attr_check_set_internal_locked(env, mdd_pobj, la, handle, 0);
if (rc)
GOTO(cleanup, rc);
la->la_valid = LA_CTIME;
- rc = mdd_attr_set_internal(env, mdd_cobj, la, handle, 0);
+ rc = mdd_attr_check_set_internal(env, mdd_cobj, la, handle, 0);
if (rc)
GOTO(cleanup, rc);
if (ma->ma_attr.la_valid & LA_CTIME) {
la->la_ctime = la->la_mtime = ma->ma_attr.la_ctime;
la->la_valid = LA_CTIME | LA_MTIME;
- rc = mdd_attr_set_internal_locked(env, mdd_obj, la, handle, 0);
+ rc = mdd_attr_check_set_internal_locked(env, mdd_obj, la,
+ handle, 0);
}
EXIT;
out_unlock:
if (ma->ma_attr.la_valid & LA_CTIME) {
la->la_ctime = la->la_mtime = ma->ma_attr.la_ctime;
la->la_valid = LA_CTIME | LA_MTIME;
- rc = mdd_attr_set_internal_locked(env, mdd_obj, la, handle, 0);
+ rc = mdd_attr_check_set_internal_locked(env, mdd_obj, la,
+ handle, 0);
}
EXIT;
out_unlock:
la->la_ctime = la->la_mtime = ma->ma_attr.la_ctime;
la->la_valid = LA_CTIME | LA_MTIME;
- rc = mdd_attr_set_internal_locked(env, mdd_tpobj, la, handle, 0);
+ rc = mdd_attr_check_set_internal_locked(env, mdd_tpobj, la, handle, 0);
if (rc)
GOTO(cleanup, rc);
mdo_ref_del(env, mdd_tobj, handle);
la->la_valid = LA_CTIME;
- rc = mdd_attr_set_internal(env, mdd_tobj, la, handle, 0);
+ rc = mdd_attr_check_set_internal(env, mdd_tobj, la, handle, 0);
if (rc)
GOTO(cleanup, rc);
*la = ma->ma_attr;
la->la_valid = LA_CTIME | LA_MTIME;
- rc = mdd_attr_set_internal_locked(env, mdd_pobj, la, handle, 0);
+ rc = mdd_attr_check_set_internal_locked(env, mdd_pobj, la, handle, 0);
if (rc)
GOTO(cleanup, rc);
/* XXX: mdd_sobj must be local one if it is NOT NULL. */
if (mdd_sobj) {
la->la_valid = LA_CTIME;
- rc = mdd_attr_set_internal_locked(env, mdd_sobj, la, handle, 0);
+ rc = mdd_attr_check_set_internal_locked(env, mdd_sobj, la,
+ handle, 0);
if (rc)
GOTO(cleanup, rc);
}
mdo_ref_del(env, mdd_tobj, handle);
la->la_valid = LA_CTIME;
- rc = mdd_attr_set_internal(env, mdd_tobj, la, handle, 0);
+ rc = mdd_attr_check_set_internal(env, mdd_tobj, la, handle, 0);
if (rc)
GOTO(cleanup, rc);
}
la->la_valid = LA_CTIME | LA_MTIME;
- rc = mdd_attr_set_internal_locked(env, mdd_spobj, la, handle, 0);
+ rc = mdd_attr_check_set_internal_locked(env, mdd_spobj, la, handle, 0);
if (rc)
GOTO(cleanup, rc);
if (mdd_spobj != mdd_tpobj) {
la->la_valid = LA_CTIME | LA_MTIME;
- rc = mdd_attr_set_internal_locked(env, mdd_tpobj, la,
+ rc = mdd_attr_check_set_internal_locked(env, mdd_tpobj, la,
handle, 0);
}
void *md, int *md_size, const char *name);
int mdd_la_get(const struct lu_env *env, struct mdd_object *obj,
struct lu_attr *la, struct lustre_capa *capa);
-int mdd_attr_set_internal(const struct lu_env *env, struct mdd_object *o,
- const struct lu_attr *attr, struct thandle *handle,
- const int needacl);
+int mdd_attr_set_internal(const struct lu_env *env,
+ struct mdd_object *obj,
+ struct lu_attr *attr,
+ struct thandle *handle,
+ int needacl);
+int mdd_attr_check_set_internal(const struct lu_env *env,
+ struct mdd_object *obj,
+ struct lu_attr *attr,
+ struct thandle *handle,
+ int needacl);
int mdd_object_kill(const struct lu_env *env, struct mdd_object *obj,
struct md_attr *ma);
int mdd_iattr_get(const struct lu_env *env, struct mdd_object *mdd_obj,
int mdd_object_create_internal(const struct lu_env *env, struct mdd_object *p,
struct mdd_object *c, struct md_attr *ma,
struct thandle *handle);
-int mdd_attr_set_internal_locked(const struct lu_env *env,
- struct mdd_object *o,
- const struct lu_attr *attr,
- struct thandle *handle, const int needacl);
+int mdd_attr_check_set_internal_locked(const struct lu_env *env,
+ struct mdd_object *obj,
+ struct lu_attr *attr,
+ struct thandle *handle,
+ int needacl);
int mdd_lmm_get_locked(const struct lu_env *env, struct mdd_object *mdd_obj,
struct md_attr *ma);
/* mdd_lock.c */
RETURN(rc);
}
+static inline int mdd_attr_check(const struct lu_env *env,
+ struct mdd_object *obj,
+ struct lu_attr *attr)
+{
+ struct lu_attr *tmp_la = &mdd_env_info(env)->mti_la;
+ int rc;
+ ENTRY;
+
+ if (attr->la_valid & LA_CTIME) {
+ rc = mdd_la_get(env, obj, tmp_la, BYPASS_CAPA);
+ if (rc)
+ RETURN(rc);
-int mdd_attr_set_internal(const struct lu_env *env, struct mdd_object *obj,
- const struct lu_attr *attr, struct thandle *handle,
- const int needacl)
+ if (attr->la_ctime < tmp_la->la_ctime)
+ attr->la_valid &= ~(LA_MTIME | LA_CTIME);
+ else if (attr->la_valid == LA_CTIME &&
+ attr->la_ctime == tmp_la->la_ctime)
+ attr->la_valid &= ~LA_CTIME;
+ }
+ RETURN(0);
+}
+
+int mdd_attr_set_internal(const struct lu_env *env,
+ struct mdd_object *obj,
+ struct lu_attr *attr,
+ struct thandle *handle,
+ int needacl)
{
int rc;
ENTRY;
RETURN(rc);
}
-int mdd_attr_set_internal_locked(const struct lu_env *env,
- struct mdd_object *o,
- const struct lu_attr *attr,
- struct thandle *handle, int needacl)
+int mdd_attr_check_set_internal(const struct lu_env *env,
+ struct mdd_object *obj,
+ struct lu_attr *attr,
+ struct thandle *handle,
+ int needacl)
+{
+ int rc;
+ ENTRY;
+
+ rc = mdd_attr_check(env, obj, attr);
+ if (rc)
+ RETURN(rc);
+
+ if (attr->la_valid)
+ rc = mdd_attr_set_internal(env, obj, attr, handle, needacl);
+ RETURN(rc);
+}
+
+static int mdd_attr_set_internal_locked(const struct lu_env *env,
+ struct mdd_object *obj,
+ struct lu_attr *attr,
+ struct thandle *handle,
+ int needacl)
{
int rc;
ENTRY;
needacl = needacl && (attr->la_valid & LA_MODE);
if (needacl)
- mdd_write_lock(env, o);
+ mdd_write_lock(env, obj);
- rc = mdd_attr_set_internal(env, o, attr, handle, needacl);
+ rc = mdd_attr_set_internal(env, obj, attr, handle, needacl);
if (needacl)
- mdd_write_unlock(env, o);
+ mdd_write_unlock(env, obj);
+ RETURN(rc);
+}
+
+int mdd_attr_check_set_internal_locked(const struct lu_env *env,
+ struct mdd_object *obj,
+ struct lu_attr *attr,
+ struct thandle *handle,
+ int needacl)
+{
+ int rc;
+ ENTRY;
+
+ rc = mdd_attr_check(env, obj, attr);
+ if (rc)
+ RETURN(rc);
+
+ if (attr->la_valid)
+ rc = mdd_attr_set_internal_locked(env, obj, attr, handle,
+ needacl);
RETURN(rc);
}
if (la->la_valid & (LA_NLINK | LA_RDEV | LA_BLKSIZE))
RETURN(-EPERM);
+ rc = mdd_la_get(env, obj, tmp_la, BYPASS_CAPA);
+ if (rc)
+ RETURN(rc);
+
/* This is only for set ctime when rename's source is on remote MDS. */
if (unlikely(la->la_valid == LA_CTIME)) {
rc = mdd_may_delete(env, NULL, obj, (struct md_attr *)ma, 1, 0);
+ if (rc == 0 && la->la_ctime <= tmp_la->la_ctime)
+ la->la_valid &= ~LA_CTIME;
RETURN(rc);
}
- rc = mdd_la_get(env, obj, tmp_la, BYPASS_CAPA);
- if (rc)
- RETURN(rc);
-
if (la->la_valid == LA_ATIME) {
/* This is atime only set for read atime update on close. */
if (la->la_atime <= tmp_la->la_atime +
}
}
- /* For truncate (or setsize), we should have MAY_WRITE perm */
- if (la->la_valid & (LA_SIZE | LA_BLOCKS)) {
- if (!((la->la_valid & MDS_OPEN_OWNEROVERRIDE) &&
- (uc->mu_fsuid == tmp_la->la_uid)) &&
- !(ma->ma_attr_flags & MDS_PERM_BYPASS)) {
- rc = mdd_permission_internal_locked(env, obj, tmp_la,
- MAY_WRITE);
- if (rc)
- RETURN(rc);
- }
+ if (la->la_valid & (LA_SIZE | LA_BLOCKS) &&
+ !(la->la_valid & LA_TRUNC)) {
+ /* For "Size-on-MDS" case, the MAY_WRITE perm
+ * has been checked when file open. */
/* For the "Size-on-MDS" setattr update, merge coming
* attributes with the set in the inode. BUG 10641 */
if ((la->la_valid & LA_CTIME) &&
(la->la_ctime <= tmp_la->la_ctime))
la->la_valid &= ~(LA_MTIME | LA_CTIME);
- } else if (la->la_valid & LA_CTIME) {
- /* The pure setattr, it has the priority over what is already
- * set, do not drop it if ctime is equal. */
- if (la->la_ctime < tmp_la->la_ctime)
- la->la_valid &= ~(LA_ATIME | LA_MTIME | LA_CTIME);
+ } else {
+ if (la->la_valid & LA_TRUNC) {
+ /* For truncate, we should have MAY_WRITE perm. */
+ if (!((la->la_valid & MDS_OPEN_OWNEROVERRIDE) &&
+ (uc->mu_fsuid == tmp_la->la_uid)) &&
+ !(ma->ma_attr_flags & MDS_PERM_BYPASS)) {
+ rc = mdd_permission_internal_locked(env, obj,
+ tmp_la, MAY_WRITE);
+ if (rc)
+ RETURN(rc);
+ }
+ }
+ if (la->la_valid & LA_CTIME) {
+ /* The pure setattr, it has the priority over what is
+ * already set, do not drop it if ctime is equal. */
+ if (la->la_ctime < tmp_la->la_ctime)
+ la->la_valid &= ~(LA_ATIME | LA_MTIME |
+ LA_CTIME);
+ }
}
RETURN(0);
}
static int mdd_xattr_set(const struct lu_env *env, struct md_object *obj,
- const struct lu_buf *buf, const char *name, int fl)
+ const struct lu_buf *buf, const char *name,
+ int fl, const struct lu_attr *la)
{
struct lu_attr *la_copy = &mdd_env_info(env)->mti_la_for_fix;
struct mdd_object *mdd_obj = md2mdd_obj(obj);
if (IS_ERR(handle))
RETURN(PTR_ERR(handle));
- rc = mdd_xattr_set_txn(env, md2mdd_obj(obj), buf, name,
- fl, handle);
- if (rc == 0) {
- la_copy->la_ctime = cfs_time_current_sec();
+ rc = mdd_xattr_set_txn(env, mdd_obj, buf, name, fl, handle);
+ if (rc == 0 && likely(la != NULL)) {
+ LASSERT(la->la_valid & LA_CTIME);
+ la_copy->la_ctime = la->la_ctime;
la_copy->la_valid = LA_CTIME;
- rc = mdd_attr_set_internal_locked(env, mdd_obj, la_copy,
- handle, 0);
+ rc = mdd_attr_check_set_internal_locked(env, mdd_obj, la_copy,
+ handle, 0);
}
mdd_trans_stop(env, mdd, rc, handle);
}
int mdd_xattr_del(const struct lu_env *env, struct md_object *obj,
- const char *name)
+ const char *name, const struct lu_attr *la)
{
struct lu_attr *la_copy = &mdd_env_info(env)->mti_la_for_fix;
struct mdd_object *mdd_obj = md2mdd_obj(obj);
RETURN(PTR_ERR(handle));
mdd_write_lock(env, mdd_obj);
- rc = mdo_xattr_del(env, md2mdd_obj(obj), name, handle,
+ rc = mdo_xattr_del(env, mdd_obj, name, handle,
mdd_object_capa(env, mdd_obj));
mdd_write_unlock(env, mdd_obj);
- if (rc == 0) {
- la_copy->la_ctime = cfs_time_current_sec();
+ if (rc == 0 && likely(la != NULL)) {
+ LASSERT(la->la_valid & LA_CTIME);
+ la_copy->la_ctime = la->la_ctime;
la_copy->la_valid = LA_CTIME;
- rc = mdd_attr_set_internal_locked(env, mdd_obj, la_copy,
- handle, 0);
+ rc = mdd_attr_check_set_internal_locked(env, mdd_obj, la_copy,
+ handle, 0);
}
mdd_trans_stop(env, mdd, rc, handle);
la_copy->la_ctime = ma->ma_attr.la_ctime;
la_copy->la_valid = LA_CTIME;
- rc = mdd_attr_set_internal(env, mdd_obj, la_copy, handle, 0);
+ rc = mdd_attr_check_set_internal(env, mdd_obj, la_copy, handle, 0);
if (rc)
GOTO(cleanup, rc);
if (rc)
GOTO(unlock, rc);
- rc = mdd_attr_set_internal(env, mdd_obj, &ma->ma_attr, handle, 0);
+ rc = mdd_attr_set_internal(env, mdd_obj, &ma->ma_attr,
+ handle, 0);
} else {
#ifdef CONFIG_FS_POSIX_ACL
if (spec->sp_cr_flags & MDS_CREATE_RMT_ACL) {
la_copy->la_ctime = ma->ma_attr.la_ctime;
la_copy->la_valid = LA_CTIME;
- rc = mdd_attr_set_internal_locked(env, mdd_obj, la_copy,
- handle, 0);
+ rc = mdd_attr_check_set_internal_locked(env, mdd_obj, la_copy,
+ handle, 0);
}
mdd_trans_stop(env, mdd, 0, handle);
ia_valid |= ATTR_FROM_OPEN;
if (sa_valid & MDS_ATTR_BLOCKS)
ia_valid |= ATTR_BLOCKS;
+ if (sa_valid & MDS_ATTR_TRUNC)
+ ia_valid |= ATTR_TRUNC;
if (sa_valid & MDS_OPEN_OWNEROVERRIDE)
ia_valid |= MDS_OPEN_OWNEROVERRIDE;
return ia_valid;
if (in & ATTR_ATTR_FLAG)
out |= LA_FLAGS;
+ if (in & ATTR_TRUNC)
+ out |= LA_TRUNC;
+
if (in & MDS_OPEN_OWNEROVERRIDE)
out |= MDS_OPEN_OWNEROVERRIDE;
in &= ~(ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_BLOCKS|
ATTR_ATIME|ATTR_MTIME|ATTR_CTIME|ATTR_FROM_OPEN|
ATTR_ATIME_SET|ATTR_CTIME_SET|ATTR_MTIME_SET|
- ATTR_ATTR_FLAG|ATTR_RAW|MDS_OPEN_OWNEROVERRIDE);
+ ATTR_ATTR_FLAG|ATTR_RAW|ATTR_TRUNC|MDS_OPEN_OWNEROVERRIDE);
if (in != 0)
CERROR("Unknown attr bits: %#llx\n", in);
return out;
uc->mu_fsuid = rec->sx_fsuid;
uc->mu_fsgid = rec->sx_fsgid;
uc->mu_cap = rec->sx_cap;
- uc->mu_suppgids[0] = uc->mu_suppgids[1] = -1;
+ uc->mu_suppgids[0] = rec->sx_suppgid1;
+ uc->mu_suppgids[1] = -1;
rr->rr_opcode = rec->sx_opcode;
rr->rr_fid1 = &rec->sx_fid;
attr->la_valid = rec->sx_valid;
+ attr->la_ctime = rec->sx_time;
attr->la_size = rec->sx_size;
attr->la_flags = rec->sx_flags;
RETURN(-ENOMEM);
/* Determine how many bytes we need */
- if ((valid & OBD_MD_FLXATTR) == OBD_MD_FLXATTR) {
+ if (valid & OBD_MD_FLXATTR) {
xattr_name = req_capsule_client_get(pill, &RMF_NAME);
if (!xattr_name)
RETURN(-EFAULT);
size = mo_xattr_get(info->mti_env,
mdt_object_child(info->mti_object),
&LU_BUF_NULL, xattr_name);
- } else if ((valid & OBD_MD_FLXATTRLS) == OBD_MD_FLXATTRLS) {
+ } else if (valid & OBD_MD_FLXATTRLS) {
size = mo_xattr_list(info->mti_env,
mdt_object_child(info->mti_object),
&LU_BUF_NULL);
if (IS_ERR(obj))
GOTO(out, rc = PTR_ERR(obj));
+ if (unlikely(!(valid & OBD_MD_FLCTIME))) {
+ CWARN("client miss to set OBD_MD_FLCTIME when "
+ "setxattr: [object "DFID"] [valid %llu]\n",
+ PFID(rr->rr_fid1), valid);
+ attr->la_ctime = cfs_time_current_sec();
+ }
+ attr->la_valid = LA_CTIME;
child = mdt_object_child(obj);
- if ((valid & OBD_MD_FLXATTR) == OBD_MD_FLXATTR) {
+ if (valid & OBD_MD_FLXATTR) {
char * xattr;
if (!req_capsule_field_present(pill, &RMF_EADATA, RCL_CLIENT)) {
buf->lb_buf = xattr;
buf->lb_len = xattr_len;
- rc = mo_xattr_set(env, child, buf, xattr_name, flags);
+ rc = mo_xattr_set(env, child, buf, xattr_name, flags, attr);
}
- } else if ((valid & OBD_MD_FLXATTRRM) == OBD_MD_FLXATTRRM) {
- rc = mo_xattr_del(env, child, xattr_name);
+ } else if (valid & OBD_MD_FLXATTRRM) {
+ rc = mo_xattr_del(env, child, xattr_name, attr);
} else {
CDEBUG(D_INFO, "valid bits: "LPX64"\n", valid);
rc = -EINVAL;
const struct lu_buf *buf, const char *name, int fl,
struct thandle *handle, struct lustre_capa *capa)
{
- int fs_flags;
-
struct osd_object *obj = osd_dt_obj(dt);
struct inode *inode = obj->oo_inode;
struct osd_thread_info *info = osd_oti_get(env);
struct dentry *dentry = &info->oti_dentry;
+ struct timespec *t = &info->oti_time;
+ int fs_flags = 0, rc;
LASSERT(dt_object_exists(dt));
LASSERT(inode->i_op != NULL && inode->i_op->setxattr != NULL);
if (osd_object_auth(env, dt, capa, CAPA_OPC_META_WRITE))
return -EACCES;
- dentry->d_inode = inode;
-
- fs_flags = 0;
if (fl & LU_XATTR_REPLACE)
fs_flags |= XATTR_REPLACE;
if (fl & LU_XATTR_CREATE)
fs_flags |= XATTR_CREATE;
- return inode->i_op->setxattr(dentry, name,
- buf->lb_buf, buf->lb_len, fs_flags);
+ dentry->d_inode = inode;
+ *t = inode->i_ctime;
+ rc = inode->i_op->setxattr(dentry, name,
+ buf->lb_buf, buf->lb_len, fs_flags);
+ if (likely(rc == 0)) {
+ /* ctime should not be updated with server-side time. */
+ spin_lock(&obj->oo_guard);
+ inode->i_ctime = *t;
+ spin_unlock(&obj->oo_guard);
+ mark_inode_dirty(inode);
+ }
+ return rc;
}
/*
struct inode *inode = obj->oo_inode;
struct osd_thread_info *info = osd_oti_get(env);
struct dentry *dentry = &info->oti_dentry;
+ struct timespec *t = &info->oti_time;
+ int rc;
LASSERT(dt_object_exists(dt));
LASSERT(inode->i_op != NULL && inode->i_op->removexattr != NULL);
return -EACCES;
dentry->d_inode = inode;
- return inode->i_op->removexattr(dentry, name);
+ *t = inode->i_ctime;
+ rc = inode->i_op->removexattr(dentry, name);
+ if (likely(rc == 0)) {
+ /* ctime should not be updated with server-side time. */
+ spin_lock(&obj->oo_guard);
+ inode->i_ctime = *t;
+ spin_unlock(&obj->oo_guard);
+ mark_inode_dirty(inode);
+ }
+ return rc;
}
static struct obd_capa *osd_capa_get(const struct lu_env *env,