+ int rc;
+ ENTRY;
+
+ if (S_ISLNK(la->la_mode)) {
+ acl_buf->lb_len = 0;
+ def_acl_buf->lb_len = 0;
+ RETURN(0);
+ }
+
+ mdd_read_lock(env, pobj, MOR_TGT_PARENT);
+ rc = mdo_xattr_get(env, pobj, def_acl_buf,
+ XATTR_NAME_ACL_DEFAULT);
+ mdd_read_unlock(env, pobj);
+ if (rc > 0) {
+ /* If there are default ACL, fix mode/ACL by default ACL */
+ def_acl_buf->lb_len = rc;
+ LASSERT(def_acl_buf->lb_len <= acl_buf->lb_len);
+ memcpy(acl_buf->lb_buf, def_acl_buf->lb_buf, rc);
+ acl_buf->lb_len = rc;
+ rc = __mdd_fix_mode_acl(env, acl_buf, &la->la_mode);
+ if (rc < 0)
+ RETURN(rc);
+ } else if (rc == -ENODATA || rc == -EOPNOTSUPP) {
+ /* If there are no default ACL, fix mode by mask */
+ struct lu_ucred *uc = lu_ucred(env);
+
+ /* The create triggered by MDT internal events, such as
+ * LFSCK reset, will not contain valid "uc". */
+ if (unlikely(uc != NULL))
+ la->la_mode &= ~uc->uc_umask;
+ rc = 0;
+ acl_buf->lb_len = 0;
+ def_acl_buf->lb_len = 0;
+ }
+
+ RETURN(rc);
+}
+
+/**
+ * Create a metadata object and initialize it, set acl, xattr.
+ **/
+static int mdd_object_create(const struct lu_env *env, struct mdd_object *pobj,
+ struct mdd_object *son, struct lu_attr *attr,
+ struct md_op_spec *spec, struct lu_buf *acl_buf,
+ struct lu_buf *def_acl_buf,
+ struct dt_allocation_hint *hint,
+ struct thandle *handle)
+{
+ int rc;
+
+ mdd_write_lock(env, son, MOR_TGT_CHILD);
+ rc = mdd_object_create_internal(env, NULL, son, attr, handle, spec,
+ hint);
+ if (rc)
+ GOTO(unlock, rc);
+
+ /* Note: In DNE phase I, for striped dir, though sub-stripes will be
+ * created in declare phase, they also needs to be added to master
+ * object as sub-directory entry. So it has to initialize the master
+ * object, then set dir striped EA.(in mdo_xattr_set) */
+ rc = mdd_object_initialize(env, mdo2fid(pobj), son, attr, handle,
+ spec);
+ if (rc != 0)
+ GOTO(err_destroy, rc);
+
+ /*
+ * in case of replay we just set LOVEA provided by the client
+ * XXX: I think it would be interesting to try "old" way where
+ * MDT calls this xattr_set(LOV) in a different transaction.
+ * probably this way we code can be made better.
+ */
+
+ /* During creation, there are only a few cases we need do xattr_set to
+ * create stripes.
+ * 1. regular file: see comments above.
+ * 2. dir: inherit default striping or pool settings from parent.
+ * 3. create striped directory with provided stripeEA.
+ * 4. create striped directory because inherit default layout from the
+ * parent.
+ */
+ if (spec->no_create ||
+ (S_ISREG(attr->la_mode) && spec->sp_cr_flags & MDS_OPEN_HAS_EA) ||
+ S_ISDIR(attr->la_mode)) {
+ const struct lu_buf *buf;
+
+ buf = mdd_buf_get_const(env, spec->u.sp_ea.eadata,
+ spec->u.sp_ea.eadatalen);
+ rc = mdo_xattr_set(env, son, buf,
+ S_ISDIR(attr->la_mode) ? XATTR_NAME_LMV :
+ XATTR_NAME_LOV, 0,
+ handle);
+ if (rc != 0)
+ GOTO(err_destroy, rc);
+ }
+
+#ifdef CONFIG_FS_POSIX_ACL
+ if (def_acl_buf != NULL && def_acl_buf->lb_len > 0 &&
+ S_ISDIR(attr->la_mode)) {
+ /* set default acl */
+ rc = mdo_xattr_set(env, son, def_acl_buf,
+ XATTR_NAME_ACL_DEFAULT, 0,
+ handle);
+ if (rc)
+ GOTO(err_destroy, rc);
+ }
+ /* set its own acl */
+ if (acl_buf != NULL && acl_buf->lb_len > 0) {
+ rc = mdo_xattr_set(env, son, acl_buf,
+ XATTR_NAME_ACL_ACCESS,
+ 0, handle);
+ if (rc)
+ GOTO(err_destroy, rc);
+ }
+#endif
+
+ if (S_ISLNK(attr->la_mode)) {
+ struct lu_ucred *uc = lu_ucred_assert(env);
+ struct dt_object *dt = mdd_object_child(son);
+ const char *target_name = spec->u.sp_symname;
+ int sym_len = strlen(target_name);
+ const struct lu_buf *buf;
+ loff_t pos = 0;
+
+ buf = mdd_buf_get_const(env, target_name, sym_len);
+ rc = dt->do_body_ops->dbo_write(env, dt, buf, &pos, handle,
+ uc->uc_cap &
+ CFS_CAP_SYS_RESOURCE_MASK);
+
+ if (rc == sym_len)
+ rc = 0;
+ else
+ GOTO(err_initlized, rc = -EFAULT);
+ }
+
+err_initlized:
+ if (unlikely(rc != 0)) {
+ int rc2;
+ if (S_ISDIR(attr->la_mode)) {
+ /* Drop the reference, no need to delete "."/"..",
+ * because the object to be destroied directly. */
+ rc2 = mdo_ref_del(env, son, handle);
+ if (rc2 != 0)
+ GOTO(unlock, rc);
+ }
+ rc2 = mdo_ref_del(env, son, handle);
+ if (rc2 != 0)
+ GOTO(unlock, rc);
+err_destroy:
+ mdo_destroy(env, son, handle);
+ }
+unlock:
+ mdd_write_unlock(env, son);
+ RETURN(rc);
+}
+
+/*
+ * Create object and insert it into namespace.
+ */
+static int mdd_create(const struct lu_env *env, struct md_object *pobj,
+ const struct lu_name *lname, struct md_object *child,
+ struct md_op_spec *spec, struct md_attr* ma)
+{
+ struct mdd_thread_info *info = mdd_env_info(env);
+ struct lu_attr *la = &info->mti_la_for_fix;
+ struct mdd_object *mdd_pobj = md2mdd_obj(pobj);
+ struct mdd_object *son = md2mdd_obj(child);
+ struct mdd_device *mdd = mdo2mdd(pobj);
+ struct lu_attr *attr = &ma->ma_attr;
+ struct thandle *handle;
+ struct lu_attr *pattr = &info->mti_pattr;
+ struct lu_buf acl_buf;
+ struct lu_buf def_acl_buf;
+ struct linkea_data *ldata = &info->mti_link_data;
+ const char *name = lname->ln_name;
+ struct dt_allocation_hint *hint = &mdd_env_info(env)->mti_hint;
+ int rc;
+ int rc2;
+ ENTRY;