- 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 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);
+ }