int (*moo_xattr_set)(const struct lu_env *env, struct md_object *obj,
const struct lu_buf *buf, const char *name,
- int fl, const struct lu_attr *la);
+ int fl);
int (*moo_xattr_del)(const struct lu_env *env, struct md_object *obj,
- const char *name, const struct lu_attr *la);
+ const char *name);
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 struct lu_attr *la)
+ const char *name)
{
LASSERT(m->mo_ops->moo_xattr_del);
- return m->mo_ops->moo_xattr_del(env, m, name, la);
+ return m->mo_ops->moo_xattr_del(env, m, name);
}
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,
- const struct lu_attr *la)
+ int flags)
{
LASSERT(m->mo_ops->moo_xattr_set);
- return m->mo_ops->moo_xattr_set(env, m, buf, name, flags, la);
+ return m->mo_ops->moo_xattr_set(env, m, buf, name, flags);
}
static inline int mo_xattr_list(const struct lu_env *env,
RETURN(rc);
}
+/**
+ * Make sure the ctime is increased only.
+ */
static inline int mdd_attr_check(const struct lu_env *env,
struct mdd_object *obj,
struct lu_attr *attr)
ENTRY;
needacl = needacl && (attr->la_valid & LA_MODE);
-
if (needacl)
mdd_write_lock(env, obj);
-
rc = mdd_attr_set_internal(env, obj, attr, handle, needacl);
-
if (needacl)
mdd_write_unlock(env, obj);
RETURN(rc);
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);
+ needacl = needacl && (attr->la_valid & LA_MODE);
+ if (needacl)
+ mdd_write_lock(env, obj);
+ rc = mdd_attr_check_set_internal(env, obj, attr, handle, needacl);
+ if (needacl)
+ mdd_write_unlock(env, obj);
RETURN(rc);
}
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 (la->la_valid == LA_CTIME) {
+ if (!(ma->ma_attr_flags & MDS_PERM_BYPASS))
+ /* This is only for set ctime when rename's source is
+ * on remote MDS. */
+ 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);
/* Make sure a caller can chmod. */
if (la->la_valid & LA_MODE) {
- /*
- * Bypass la_vaild == LA_MODE,
- * this is for changing file with SUID or SGID.
- */
+ /* Bypass la_vaild == LA_MODE,
+ * this is for changing file with SUID or SGID. */
if ((la->la_valid & ~LA_MODE) &&
(uc->mu_fsuid != tmp_la->la_uid) &&
!mdd_capable(uc, CAP_FOWNER))
!mdd_capable(uc, CAP_CHOWN))
RETURN(-EPERM);
- /*
- * If the user or group of a non-directory has been
+ /* If the user or group of a non-directory has been
* changed by a non-root user, remove the setuid bit.
* 19981026 David C Niemi <niemi@tux.org>
*
* to avoid some races. This is the behavior we had in
* 2.0. The check for non-root was definitely wrong
* for 2.2 anyway, as it should have been using
- * CAP_FSETID rather than fsuid -- 19990830 SD.
- */
+ * CAP_FSETID rather than fsuid -- 19990830 SD. */
if (((tmp_la->la_mode & S_ISUID) == S_ISUID) &&
!S_ISDIR(tmp_la->la_mode)) {
la->la_mode &= ~S_ISUID;
!mdd_capable(uc, CAP_CHOWN))
RETURN(-EPERM);
- /*
- * Likewise, if the user or group of a non-directory
+ /* Likewise, if the user or group of a non-directory
* has been changed by a non-root user, remove the
* setgid bit UNLESS there is no group execute bit
* (this would be a file marked for mandatory
* locking). 19981026 David C Niemi <niemi@tux.org>
*
* Removed the fsuid check (see the comment above) --
- * 19990830 SD.
- */
+ * 19990830 SD. */
if (((tmp_la->la_mode & (S_ISGID | S_IXGRP)) ==
(S_ISGID | S_IXGRP)) && !S_ISDIR(tmp_la->la_mode)) {
la->la_mode &= ~S_ISGID;
}
}
- 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 both Size-on-MDS case and truncate case,
+ * "la->la_valid & (LA_SIZE | LA_BLOCKS)" are ture.
+ * We distinguish them by "ma->ma_attr_flags & MDS_SOM".
+ * For SOM case, it is true, the MAY_WRITE perm has been checked
+ * when open, no need check again. For truncate case, it is false,
+ * the MAY_WRITE perm should be checked here. */
+ if (ma->ma_attr_flags & MDS_SOM) {
/* For the "Size-on-MDS" setattr update, merge coming
* attributes with the set in the inode. BUG 10641 */
if ((la->la_valid & LA_ATIME) &&
(la->la_ctime <= tmp_la->la_ctime))
la->la_valid &= ~(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) &&
+ if (la->la_valid & (LA_SIZE | LA_BLOCKS)) {
+ if (!((ma->ma_attr_flags & MDS_OPEN_OWNEROVERRIDE) &&
(uc->mu_fsuid == tmp_la->la_uid)) &&
!(ma->ma_attr_flags & MDS_PERM_BYPASS)) {
rc = mdd_permission_internal_locked(env, obj,
RETURN(rc);
}
+/**
+ * The caller should guarantee to update the object ctime
+ * after xattr_set if needed.
+ */
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_attr *la)
+ int fl)
{
- struct lu_attr *la_copy = &mdd_env_info(env)->mti_la_for_fix;
struct mdd_object *mdd_obj = md2mdd_obj(obj);
struct mdd_device *mdd = mdo2mdd(obj);
struct thandle *handle;
RETURN(PTR_ERR(handle));
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_check_set_internal_locked(env, mdd_obj, la_copy,
- handle, 0);
- }
mdd_trans_stop(env, mdd, rc, handle);
RETURN(rc);
}
+/**
+ * The caller should guarantee to update the object ctime
+ * after xattr_set if needed.
+ */
int mdd_xattr_del(const struct lu_env *env, struct md_object *obj,
- const char *name, const struct lu_attr *la)
+ const char *name)
{
- struct lu_attr *la_copy = &mdd_env_info(env)->mti_la_for_fix;
struct mdd_object *mdd_obj = md2mdd_obj(obj);
struct mdd_device *mdd = mdo2mdd(obj);
struct thandle *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 && 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_check_set_internal_locked(env, mdd_obj, la_copy,
- handle, 0);
- }
-
mdd_trans_stop(env, mdd, rc, handle);
RETURN(rc);