__u32 mode, int count);
extern int lustre_posix_acl_create_masq(posix_acl_xattr_entry *entry,
__u32 *pmode, int count);
+extern int lustre_posix_acl_equiv_mode(posix_acl_xattr_entry *entry, mode_t *mode_p,
+ int count);
extern ext_acl_xattr_header *
lustre_posix_acl_xattr_2ext(posix_acl_xattr_header *header, int size);
const struct lu_name *name,
struct md_attr *ma,
int lmm_size,
+ int got_def_acl,
struct thandle *handle,
const struct md_op_spec *spec)
{
+ struct mdd_thread_info *info = mdd_env_info(env);
struct lu_buf *buf = &mdd_env_info(env)->mti_buf;
int rc = 0;
if (rc)
GOTO(out, rc);
+#ifdef CONFIG_FS_POSIX_ACL
+ if (got_def_acl > 0) {
+ struct lu_buf *acl_buf;
+
+ acl_buf = mdd_buf_get(env, NULL, got_def_acl);
+ /* if dir, then can inherit default ACl */
+ if (S_ISDIR(ma->ma_attr.la_mode)) {
+ rc = mdo_declare_xattr_set(env, c, acl_buf,
+ XATTR_NAME_ACL_DEFAULT,
+ 0, handle);
+ if (rc)
+ GOTO(out, rc);
+ }
+
+ rc = mdo_declare_attr_set(env, c, &info->mti_pattr, handle);
+ if (rc)
+ GOTO(out, rc);
+
+ rc = mdo_declare_xattr_set(env, c, acl_buf,
+ XATTR_NAME_ACL_ACCESS, 0, handle);
+ if (rc)
+ GOTO(out, rc);
+ }
+#endif
+
/* if dir, then can inherit default ACl */
buf->lb_buf = NULL;
buf->lb_len = lmm_size;
- if (S_ISDIR(ma->ma_attr.la_mode)) {
- rc = mdo_declare_xattr_set(env, c, buf, XATTR_NAME_ACL_DEFAULT,
- 0, handle);
- if (rc == 0)
- rc = mdo_declare_ref_add(env, p, handle);
+ if (S_ISDIR(ma->ma_attr.la_mode)) {
+ rc = mdo_declare_ref_add(env, p, handle);
+ if (rc)
+ GOTO(out, rc);
}
- if (rc)
- GOTO(out, rc);
-
- rc = mdo_declare_xattr_set(env, c, buf, XATTR_NAME_ACL_ACCESS,
- 0, handle);
- if (rc)
- GOTO(out, rc);
rc = mdd_declare_object_initialize(env, c, ma, handle);
if (rc)
{
struct mdd_thread_info *info = mdd_env_info(env);
struct lu_attr *la = &info->mti_la_for_fix;
- struct md_attr *ma_acl = &info->mti_ma;
struct mdd_object *mdd_pobj = md2mdd_obj(pobj);
struct mdd_object *son = md2mdd_obj(child);
struct mdd_device *mdd = mdo2mdd(pobj);
}
if (!S_ISLNK(attr->la_mode)) {
- ma_acl->ma_acl_size = sizeof info->mti_xattr_buf;
- ma_acl->ma_acl = info->mti_xattr_buf;
- ma_acl->ma_need = MA_ACL_DEF;
- ma_acl->ma_valid = 0;
+ struct lu_buf *acl_buf;
+ acl_buf = mdd_buf_get(env, info->mti_xattr_buf,
+ sizeof(info->mti_xattr_buf));
mdd_read_lock(env, mdd_pobj, MOR_TGT_PARENT);
- rc = mdd_def_acl_get(env, mdd_pobj, ma_acl);
+ rc = mdo_xattr_get(env, mdd_pobj, acl_buf,
+ XATTR_NAME_ACL_DEFAULT, BYPASS_CAPA);
mdd_read_unlock(env, mdd_pobj);
- if (rc)
- GOTO(out_free, rc);
- else if (ma_acl->ma_valid & MA_ACL_DEF)
- got_def_acl = 1;
+ if (rc > 0)
+ got_def_acl = rc;
+ else if (rc < 0 && rc != -EOPNOTSUPP && rc != -ENODATA)
+ GOTO(out_free, rc);
}
mdd_object_make_hint(env, mdd_pobj, son, attr);
GOTO(out_free, rc = PTR_ERR(handle));
rc = mdd_declare_create(env, mdd, mdd_pobj, son, lname, ma,
- lmm_size, handle, spec);
+ got_def_acl, lmm_size, handle, spec);
if (rc)
GOTO(out_stop, rc);
#ifdef CONFIG_FS_POSIX_ACL
if (got_def_acl) {
- struct lu_buf *acl_buf = &info->mti_buf;
- acl_buf->lb_buf = ma_acl->ma_acl;
- acl_buf->lb_len = ma_acl->ma_acl_size;
+ struct lu_buf *acl_buf;
- rc = __mdd_acl_init(env, son, acl_buf, &attr->la_mode, handle);
- if (rc) {
- mdd_write_unlock(env, son);
- GOTO(cleanup, rc);
- } else {
- ma->ma_attr.la_valid |= LA_MODE;
- }
+ acl_buf = mdd_buf_get(env, info->mti_xattr_buf, got_def_acl);
+ rc = __mdd_acl_init(env, son, acl_buf, &attr->la_mode, handle);
+ if (rc) {
+ mdd_write_unlock(env, son);
+ GOTO(cleanup, rc);
+ }
}
#endif
/* mti_orph_ent and mti_orph_key must be conjoint,
* then mti_orph_ent::lde_name will be mti_orph_key. */
struct lu_dirent mti_orph_ent;
+ struct lu_attr mti_pattr;
+ struct lu_attr mti_cattr;
char mti_orph_key[NAME_MAX + 1];
struct obd_trans_info mti_oti;
struct lu_buf mti_buf;
struct thandle *handle);
int __mdd_declare_acl_init(const struct lu_env *env, struct mdd_object *obj,
int is_dir, struct thandle *handle);
+int mdd_acl_set(const struct lu_env *env, struct mdd_object *obj,
+ const struct lu_buf *buf, int fl);
int __mdd_acl_init(const struct lu_env *env, struct mdd_object *obj,
struct lu_buf *buf, __u32 *mode, struct thandle *handle);
int __mdd_permission_internal(const struct lu_env *env, struct mdd_object *obj,
int rc;
ENTRY;
+ if (!strcmp(name, XATTR_NAME_ACL_ACCESS)) {
+ rc = mdd_acl_set(env, mdd_obj, buf, fl);
+ RETURN(rc);
+ }
+
rc = mdd_xattr_sanity_check(env, mdd_obj);
if (rc)
RETURN(rc);
* Hold write_lock for o.
*/
int mdd_acl_chmod(const struct lu_env *env, struct mdd_object *o, __u32 mode,
- struct thandle *handle)
+ struct thandle *handle)
{
- struct lu_buf *buf;
- posix_acl_xattr_header *head;
- posix_acl_xattr_entry *entry;
- int entry_count;
- int rc;
-
- ENTRY;
-
- buf = mdd_buf_get(env, mdd_env_info(env)->mti_xattr_buf,
- sizeof(mdd_env_info(env)->mti_xattr_buf));
-
- rc = mdo_xattr_get(env, o, buf, XATTR_NAME_ACL_ACCESS, BYPASS_CAPA);
- if ((rc == -EOPNOTSUPP) || (rc == -ENODATA))
- RETURN(0);
- else if (rc <= 0)
- RETURN(rc);
-
- buf->lb_len = rc;
- head = (posix_acl_xattr_header *)(buf->lb_buf);
- entry = head->a_entries;
- entry_count = (buf->lb_len - sizeof(head->a_version)) /
- sizeof(posix_acl_xattr_entry);
- if (entry_count <= 0)
- RETURN(0);
-
- rc = lustre_posix_acl_chmod_masq(entry, mode, entry_count);
- if (rc)
- RETURN(rc);
+ struct lu_buf *buf;
+ posix_acl_xattr_header *head;
+ posix_acl_xattr_entry *entry;
+ int entry_count;
+ int rc;
+
+ ENTRY;
+
+ buf = mdd_buf_get(env, mdd_env_info(env)->mti_xattr_buf,
+ sizeof(mdd_env_info(env)->mti_xattr_buf));
+
+ rc = mdo_xattr_get(env, o, buf, XATTR_NAME_ACL_ACCESS, BYPASS_CAPA);
+ if ((rc == -EOPNOTSUPP) || (rc == -ENODATA))
+ RETURN(0);
+ else if (rc <= 0)
+ RETURN(rc);
+
+ buf->lb_len = rc;
+ head = (posix_acl_xattr_header *)(buf->lb_buf);
+ entry = head->a_entries;
+ entry_count = (buf->lb_len - sizeof(head->a_version)) /
+ sizeof(posix_acl_xattr_entry);
+ if (entry_count <= 0)
+ RETURN(0);
+
+ rc = lustre_posix_acl_chmod_masq(entry, mode, entry_count);
+ if (rc)
+ RETURN(rc);
+
+ rc = mdo_xattr_set(env, o, buf, XATTR_NAME_ACL_ACCESS,
+ 0, handle, BYPASS_CAPA);
+ RETURN(rc);
+}
- rc = mdo_xattr_set(env, o, buf, XATTR_NAME_ACL_ACCESS,
- 0, handle, BYPASS_CAPA);
- RETURN(rc);
+int mdd_acl_set(const struct lu_env *env, struct mdd_object *obj,
+ const struct lu_buf *buf, int fl)
+{
+ struct mdd_device *mdd = mdd_obj2mdd_dev(obj);
+ struct lu_attr *la = &mdd_env_info(env)->mti_la;
+ struct thandle *handle;
+ posix_acl_xattr_header *head;
+ posix_acl_xattr_entry *entry;
+ int rc, entry_count;
+ bool not_equiv, mode_change;
+ mode_t mode;
+ ENTRY;
+
+ rc = mdd_la_get(env, obj, la, BYPASS_CAPA);
+ if (rc)
+ RETURN(rc);
+
+ head = (posix_acl_xattr_header *)(buf->lb_buf);
+ entry = head->a_entries;
+ entry_count = (buf->lb_len - sizeof(head->a_version)) /
+ sizeof(posix_acl_xattr_entry);
+ if (entry_count <= 0)
+ RETURN(0);
+
+ LASSERT(la->la_valid & LA_MODE);
+ mode = la->la_mode;
+ rc = lustre_posix_acl_equiv_mode(entry, &mode, entry_count);
+ if (rc < 0)
+ RETURN(rc);
+
+ not_equiv = (rc > 0);
+ mode_change = (mode != la->la_mode);
+
+ handle = mdd_trans_create(env, mdd);
+ if (IS_ERR(handle))
+ RETURN(PTR_ERR(handle));
+
+ /* rc tells whether ACL can be represented by i_mode only */
+ if (not_equiv)
+ rc = mdo_declare_xattr_set(env, obj, buf,
+ XATTR_NAME_ACL_ACCESS, fl, handle);
+ else
+ rc = mdo_declare_xattr_del(env, obj, XATTR_NAME_ACL_ACCESS,
+ handle);
+ if (rc)
+ GOTO(stop, rc);
+
+ if (mode_change) {
+ la->la_mode = mode;
+ rc = mdo_declare_attr_set(env, obj, la, handle);
+ }
+
+ rc = mdd_trans_start(env, mdd, handle);
+ if (rc)
+ GOTO(stop, rc);
+
+ mdd_write_lock(env, obj, MOR_TGT_CHILD);
+ /* whether ACL can be represented by i_mode only */
+ if (not_equiv)
+ rc = mdo_xattr_set(env, obj, buf, XATTR_NAME_ACL_ACCESS, fl,
+ handle, mdd_object_capa(env, obj));
+ else
+ rc = mdo_xattr_del(env, obj, XATTR_NAME_ACL_ACCESS, handle,
+ mdd_object_capa(env, obj));
+ if (rc)
+ GOTO(unlock, rc);
+
+ if (mode_change)
+ rc = mdo_attr_set(env, obj, la, handle,
+ mdd_object_capa(env, obj));
+
+ /* security-replated changes may require sync */
+ handle->th_sync |= !!mdd->mdd_sync_permission;
+unlock:
+ mdd_write_unlock(env, obj);
+stop:
+ mdd_trans_stop(env, mdd, rc, handle);
+
+ RETURN(rc);
}
/*
posix_acl_xattr_header *head;
posix_acl_xattr_entry *entry;
int entry_count;
- int rc;
+ __u32 old = *mode;
+ int rc, rc2;
ENTRY;
}
rc = lustre_posix_acl_create_masq(entry, mode, entry_count);
- if (rc <= 0)
+ if (rc < 0)
RETURN(rc);
- rc = mdo_xattr_set(env, obj, buf, XATTR_NAME_ACL_ACCESS, 0, handle,
- BYPASS_CAPA);
- RETURN(rc);
+ /* part of ACL went into i_mode */
+ if (*mode != old) {
+ struct mdd_thread_info *info = mdd_env_info(env);
+ struct lu_attr *pattr = &info->mti_pattr;
+
+ /* mode was initialized within object creation,
+ * so we need explict ->attr_set() to update it */
+ pattr->la_valid = LA_MODE;
+ pattr->la_mode = *mode;
+ rc2 = mdo_attr_set(env, obj, pattr, handle, BYPASS_CAPA);
+ if (rc2 < 0)
+ rc = rc2;
+ }
+
+ if (rc > 0)
+ rc = mdo_xattr_set(env, obj, buf, XATTR_NAME_ACL_ACCESS, 0,
+ handle, BYPASS_CAPA);
+ RETURN(rc);
}
#endif
EXPORT_SYMBOL(lustre_posix_acl_chmod_masq);
/*
+ * Returns 0 if the acl can be exactly represented in the traditional
+ * file mode permission bits, or else 1. Returns -E... on error.
+ */
+ int
+lustre_posix_acl_equiv_mode(posix_acl_xattr_entry *entry, mode_t *mode_p,
+ int count)
+{
+ posix_acl_xattr_entry *pa, *pe;
+ mode_t mode = 0;
+ int not_equiv = 0;
+
+ for (pa = &entry[0], pe = &entry[count - 1]; pa <= pe; pa++) {
+ __u16 perm = le16_to_cpu(pa->e_perm);
+ switch (le16_to_cpu(pa->e_tag)) {
+ case ACL_USER_OBJ:
+ mode |= (perm & S_IRWXO) << 6;
+ break;
+ case ACL_GROUP_OBJ:
+ mode |= (perm & S_IRWXO) << 3;
+ break;
+ case ACL_OTHER:
+ mode |= perm & S_IRWXO;
+ break;
+ case ACL_MASK:
+ mode = (mode & ~S_IRWXG) |
+ ((perm & S_IRWXO) << 3);
+ not_equiv = 1;
+ break;
+ case ACL_USER:
+ case ACL_GROUP:
+ not_equiv = 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+ if (mode_p)
+ *mode_p = (*mode_p & ~S_IRWXUGO) | mode;
+ return not_equiv;
+}
+EXPORT_SYMBOL(lustre_posix_acl_equiv_mode);
+
+/*
* Modify acl when creating a new object.
*/
int lustre_posix_acl_create_masq(posix_acl_xattr_entry *entry, __u32 *pmode,