From 30964bcc157e3ad76714b7e55491112c3ae8ebad Mon Sep 17 00:00:00 2001
From: ericm <ericm>
Date: Wed, 18 May 2005 23:26:15 +0000
Subject: [PATCH] b=6332 create dir across MDS's, subdir need default ACL of
 its parent to determine its own default ACL and access ACL. API obd_create()
 is added 2 params to hold acl data.

---
 lustre/cmobd/cm_oss_reint.c      |  2 +-
 lustre/cobd/cache_obd.c          |  3 +-
 lustre/include/linux/obd.h       |  1 +
 lustre/include/linux/obd_class.h |  3 +-
 lustre/llite/file.c              |  2 +-
 lustre/lmv/lmv_obd.c             | 14 +++--
 lustre/lov/lov_obd.c             | 16 ++++--
 lustre/lvfs/llog_lvfs.c          |  4 +-
 lustre/mdc/mdc_request.c         | 15 +++--
 lustre/mds/handler.c             | 99 ++++++++++++++++++++++++++++++++
 lustre/mds/mds_fs.c              |  1 +
 lustre/mds/mds_internal.h        |  3 +-
 lustre/mds/mds_lmv.c             |  2 +-
 lustre/mds/mds_lov.c             |  2 +-
 lustre/mds/mds_open.c            |  2 +-
 lustre/mds/mds_reint.c           | 52 ++++++++++++++++-
 lustre/obdecho/echo.c            |  1 +
 lustre/obdecho/echo_client.c     |  2 +-
 lustre/obdfilter/filter.c        |  3 +
 lustre/osc/osc_create.c          |  2 +
 lustre/osc/osc_internal.h        |  1 +
 lustre/ost/ost_handler.c         |  2 +-
 22 files changed, 204 insertions(+), 28 deletions(-)

diff --git a/lustre/cmobd/cm_oss_reint.c b/lustre/cmobd/cm_oss_reint.c
index 18590638fe..cb2fcb3459 100644
--- a/lustre/cmobd/cm_oss_reint.c
+++ b/lustre/cmobd/cm_oss_reint.c
@@ -135,7 +135,7 @@ static int cmobd_create_reint(struct obd_device *obd, void *rec)
                         GOTO(out, rc = -EINVAL);
                 cmobd->master_group = oa->o_gr;
         }
-        rc = obd_create(exp, oa, &lsm, &oti);
+        rc = obd_create(exp, oa, NULL, 0, &lsm, &oti);
 
         cmobd_free_lsm(&lsm);
 out:
diff --git a/lustre/cobd/cache_obd.c b/lustre/cobd/cache_obd.c
index bb3bbcf0f2..99707efb8c 100644
--- a/lustre/cobd/cache_obd.c
+++ b/lustre/cobd/cache_obd.c
@@ -315,6 +315,7 @@ static int cobd_unpackmd(struct obd_export *exp,
 }
 
 static int cobd_create(struct obd_export *exp, struct obdo *obdo,
+                       void *acl, int acl_size,
                        struct lov_stripe_md **ea,
                        struct obd_trans_info *oti)
 {
@@ -327,7 +328,7 @@ static int cobd_create(struct obd_export *exp, struct obdo *obdo,
                 return -EINVAL;
         }
         cobd_exp = cobd_get_exp(obd);
-        return obd_create(cobd_exp, obdo, ea, oti); 
+        return obd_create(cobd_exp, obdo, acl, acl_size, ea, oti);
 }
 
 static int cobd_destroy(struct obd_export *exp, struct obdo *obdo,
diff --git a/lustre/include/linux/obd.h b/lustre/include/linux/obd.h
index 30323721ff..35bd876238 100644
--- a/lustre/include/linux/obd.h
+++ b/lustre/include/linux/obd.h
@@ -740,6 +740,7 @@ struct obd_ops {
         int (*o_preallocate)(struct lustre_handle *, obd_count *req,
                              obd_id *ids);
         int (*o_create)(struct obd_export *exp,  struct obdo *oa,
+                        void *acl, int acl_size,
                         struct lov_stripe_md **ea, struct obd_trans_info *oti);
         int (*o_destroy)(struct obd_export *exp, struct obdo *oa,
                          struct lov_stripe_md *ea, struct obd_trans_info *oti);
diff --git a/lustre/include/linux/obd_class.h b/lustre/include/linux/obd_class.h
index 2da67304ac..6e7beb0fd3 100644
--- a/lustre/include/linux/obd_class.h
+++ b/lustre/include/linux/obd_class.h
@@ -495,6 +495,7 @@ static inline int obd_revalidate_md(struct obd_export *exp, struct obdo *obdo,
 }
 
 static inline int obd_create(struct obd_export *exp, struct obdo *obdo,
+                             void *acl, int acl_size,
                              struct lov_stripe_md **ea,
                              struct obd_trans_info *oti)
 {
@@ -504,7 +505,7 @@ static inline int obd_create(struct obd_export *exp, struct obdo *obdo,
         EXP_CHECK_OP(exp, create);
         OBD_COUNTER_INCREMENT(exp->exp_obd, create);
 
-        rc = OBP(exp->exp_obd, create)(exp, obdo, ea, oti);
+        rc = OBP(exp->exp_obd, create)(exp, obdo, acl, acl_size, ea, oti);
         RETURN(rc);
 }
 
diff --git a/lustre/llite/file.c b/lustre/llite/file.c
index 4df7fd714c..6704a7c01c 100644
--- a/lustre/llite/file.c
+++ b/lustre/llite/file.c
@@ -1213,7 +1213,7 @@ static int ll_lov_recreate_obj(struct inode *inode, struct file *file,
 
         oti.oti_objid = NULL;
         memcpy(lsm2, lsm, lsm_size);
-        rc = obd_create(exp, oa, &lsm2, &oti);
+        rc = obd_create(exp, oa, NULL, 0, &lsm2, &oti);
 
         OBD_FREE(lsm2, lsm_size);
         GOTO(out, rc);
diff --git a/lustre/lmv/lmv_obd.c b/lustre/lmv/lmv_obd.c
index 509d2091e4..6c4b487e4e 100644
--- a/lustre/lmv/lmv_obd.c
+++ b/lustre/lmv/lmv_obd.c
@@ -1646,6 +1646,7 @@ int lmv_init_ea_size(struct obd_export *exp, int easize,
 }
 
 int lmv_obd_create_single(struct obd_export *exp, struct obdo *oa,
+                          void *acl, int acl_size,
                           struct lov_stripe_md **ea, struct obd_trans_info *oti)
 {
         struct obd_device *obd = exp->exp_obd;
@@ -1658,8 +1659,8 @@ int lmv_obd_create_single(struct obd_export *exp, struct obdo *oa,
         LASSERT(ea == NULL);
         LASSERT(oa->o_mds < lmv->desc.ld_tgt_count);
 
-        rc = obd_create(lmv->tgts[oa->o_mds].ltd_exp,
-                        oa, &obj_mdp, oti);
+        rc = obd_create(lmv->tgts[oa->o_mds].ltd_exp, oa,
+                        acl, acl_size, &obj_mdp, oti);
 
         RETURN(rc);
 }
@@ -1679,6 +1680,7 @@ int lmv_getready(struct obd_export *exp)
  * values for "master" object, as it will be used.
  */
 int lmv_obd_create(struct obd_export *exp, struct obdo *oa,
+                   void *acl, int acl_size,
                    struct lov_stripe_md **ea, struct obd_trans_info *oti)
 {
         struct obd_device *obd = exp->exp_obd;
@@ -1695,12 +1697,15 @@ int lmv_obd_create(struct obd_export *exp, struct obdo *oa,
         LASSERT(oa != NULL);
         
         if (ea == NULL) {
-                rc = lmv_obd_create_single(exp, oa, NULL, oti);
+                rc = lmv_obd_create_single(exp, oa, acl, acl_size, NULL, oti);
                 if (rc)
                         CERROR("Can't create object, rc = %d\n", rc);
                 RETURN(rc);
         }
 
+        /* acl is only suppied when mds create single remote obj */
+        LASSERT(acl == NULL && acl_size == 0);
+
         if (*ea == NULL) {
                 rc = obd_alloc_diskmd(exp, (struct lov_mds_md **)ea);
                 if (rc < 0) {
@@ -1753,7 +1758,8 @@ int lmv_obd_create(struct obd_export *exp, struct obdo *oa,
                 oa->o_valid = OBD_MD_FLGENER | OBD_MD_FLTYPE | OBD_MD_FLMODE |
                         OBD_MD_FLUID | OBD_MD_FLGID | OBD_MD_FLID;
 
-                rc = obd_create(lmv->tgts[c].ltd_exp, oa, &obj_mdp, oti);
+                rc = obd_create(lmv->tgts[c].ltd_exp, oa, NULL, 0,
+                                &obj_mdp, oti);
                 if (rc) {
                         CERROR("obd_create() failed on MDT target %d, "
                                "error %d\n", c, rc);
diff --git a/lustre/lov/lov_obd.c b/lustre/lov/lov_obd.c
index b2ae65e94d..d2b05520fb 100644
--- a/lustre/lov/lov_obd.c
+++ b/lustre/lov/lov_obd.c
@@ -698,7 +698,8 @@ static int lov_clear_orphans(struct obd_export *export, struct obdo *src_oa,
                 memcpy(tmp_oa, src_oa, sizeof(*tmp_oa));
 
                 /* XXX: LOV STACKING: use real "obj_mdp" sub-data */
-                err = obd_create(lov->tgts[i].ltd_exp, tmp_oa, &obj_mdp, oti);
+                err = obd_create(lov->tgts[i].ltd_exp, tmp_oa, NULL, 0,
+                                 &obj_mdp, oti);
                 if (err)
                         /* This export will be disabled until it is recovered,
                            and then orphan recovery will be completed. */
@@ -713,6 +714,7 @@ static int lov_clear_orphans(struct obd_export *export, struct obdo *src_oa,
 }
 
 static int lov_recreate(struct obd_export *exp, struct obdo *src_oa,
+                        void *acl, int acl_size,
                         struct lov_stripe_md **ea, struct obd_trans_info *oti)
 {
         struct lov_stripe_md *obj_mdp, *lsm;
@@ -745,7 +747,8 @@ static int lov_recreate(struct obd_export *exp, struct obdo *src_oa,
         if (i == lsm->lsm_stripe_count)
                 GOTO(out, rc = -EINVAL);
 
-        rc = obd_create(lov->tgts[ost_idx].ltd_exp, src_oa, &obj_mdp, oti);
+        rc = obd_create(lov->tgts[ost_idx].ltd_exp, src_oa, acl, acl_size,
+                        &obj_mdp, oti);
 out:
         OBD_FREE(obj_mdp, sizeof(*obj_mdp));
         RETURN(rc);
@@ -753,6 +756,7 @@ out:
 
 /* the LOV expects oa->o_id to be set to the LOV object id */
 static int lov_create(struct obd_export *exp, struct obdo *src_oa,
+                      void *acl, int acl_size,
                       struct lov_stripe_md **ea, struct obd_trans_info *oti)
 {
         struct lov_request_set *set = NULL;
@@ -778,7 +782,7 @@ static int lov_create(struct obd_export *exp, struct obdo *src_oa,
         /* Recreate a specific object id at the given OST index */
         if ((src_oa->o_valid & OBD_MD_FLFLAGS) &&
             (src_oa->o_flags & OBD_FL_RECREATE_OBJS)) {
-                 rc = lov_recreate(exp, src_oa, ea, oti);
+                 rc = lov_recreate(exp, src_oa, acl, acl_size, ea, oti);
                  RETURN(rc);
         }
 
@@ -791,8 +795,8 @@ static int lov_create(struct obd_export *exp, struct obdo *src_oa,
                         list_entry(pos, struct lov_request, rq_link);
 
                 /* XXX: LOV STACKING: use real "obj_mdp" sub-data */
-                rc = obd_create(lov->tgts[req->rq_idx].ltd_exp, 
-                                req->rq_oa, &req->rq_md, oti);
+                rc = obd_create(lov->tgts[req->rq_idx].ltd_exp, req->rq_oa,
+                                acl, acl_size, &req->rq_md, oti);
                 lov_update_create_set(set, req, rc);
         }
         rc = lov_fini_create_set(set, ea);
@@ -1091,7 +1095,7 @@ static int lov_revalidate_md(struct obd_export *exp, struct obdo *src_oa,
                 memcpy(tmp_oa, src_oa, sizeof(*tmp_oa));
                 /* XXX: LOV STACKING: use real "obj_mdp" sub-data */
                 osc_exp = lov->tgts[ost_idx].ltd_exp;
-                rc = obd_create(osc_exp, tmp_oa, &obj_mdp, oti);
+                rc = obd_create(osc_exp, tmp_oa, NULL, 0, &obj_mdp, oti);
                 if (rc) {
                         CERROR("error creating new subobj at idx %d; "
                                "rc = %d\n", ost_idx, rc);
diff --git a/lustre/lvfs/llog_lvfs.c b/lustre/lvfs/llog_lvfs.c
index 1b533f4351..b64ef0dc51 100644
--- a/lustre/lvfs/llog_lvfs.c
+++ b/lustre/lvfs/llog_lvfs.c
@@ -671,7 +671,7 @@ llog_object_create_generic(struct llog_ctxt *ctxt, struct llog_logid *lgh_id)
                         oa->o_generation = lgh_id->lgl_ogen;
                         oa->o_gr = lgh_id->lgl_ogr;
                         oa->o_valid = OBD_MD_FLGENER | OBD_MD_FLGROUP;
-                        rc = obd_create(ctxt->loc_exp, oa, NULL, NULL);
+                        rc = obd_create(ctxt->loc_exp, oa, NULL, 0, NULL, NULL);
                         if (rc) {
                                 CDEBUG(D_INODE, "err during create: %d\n", rc);
                                 GOTO(out_free_oa, rc);
@@ -706,7 +706,7 @@ llog_object_create_generic(struct llog_ctxt *ctxt, struct llog_logid *lgh_id)
 
                 oa->o_gr = FILTER_GROUP_LLOG;
                 oa->o_valid = OBD_MD_FLGENER | OBD_MD_FLGROUP;
-                rc = obd_create(ctxt->loc_exp, oa, NULL, NULL);
+                rc = obd_create(ctxt->loc_exp, oa, NULL, 0, NULL, NULL);
                 if (rc)
                         GOTO(out_free_oa, rc);
 
diff --git a/lustre/mdc/mdc_request.c b/lustre/mdc/mdc_request.c
index 260c0c7df8..023951c1e4 100644
--- a/lustre/mdc/mdc_request.c
+++ b/lustre/mdc/mdc_request.c
@@ -1295,24 +1295,31 @@ out_req:
 }
 
 int mdc_obj_create(struct obd_export *exp, struct obdo *oa,
-                    struct lov_stripe_md **ea, struct obd_trans_info *oti)
+                   void *acl, int acl_size,
+                   struct lov_stripe_md **ea, struct obd_trans_info *oti)
 {
         struct ptlrpc_request *request;
         struct ost_body *body;
-        int rc, size = sizeof(*body);
+        char *acl_buf;
+        int rc, size[2] = { sizeof(*body), acl_size };
         ENTRY;
 
         LASSERT(oa);
 
         request = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_OBD_VERSION,
-                                  OST_CREATE, 1, &size, NULL);
+                                  OST_CREATE, 2, size, NULL);
         if (!request)
                 GOTO(out_req, rc = -ENOMEM);
 
         body = lustre_msg_buf(request->rq_reqmsg, 0, sizeof (*body));
         memcpy(&body->oa, oa, sizeof(body->oa));
 
-        request->rq_replen = lustre_msg_size(1, &size);
+        if (acl_size) {
+                acl_buf = lustre_msg_buf(request->rq_reqmsg, 1, acl_size);
+                memcpy(acl_buf, acl, acl_size);
+        }
+
+        request->rq_replen = lustre_msg_size(1, size);
         rc = ptlrpc_queue_wait(request);
         if (rc)
                 GOTO(out_req, rc);
diff --git a/lustre/mds/handler.c b/lustre/mds/handler.c
index f54693a5af..bcd44c44d1 100644
--- a/lustre/mds/handler.c
+++ b/lustre/mds/handler.c
@@ -1973,11 +1973,91 @@ static void reconstruct_create(struct ptlrpc_request *req)
         EXIT;
 }
 
+static int mds_inode_init_acl(struct obd_device *obd, void *handle,
+                              struct dentry *de, void *xattr, int xattr_size)
+{
+        struct inode *inode = de->d_inode;
+        struct posix_acl *acl;
+        mode_t mode;
+        int rc;
+
+        LASSERT(handle);
+        LASSERT(inode);
+        LASSERT(xattr);
+        LASSERT(xattr_size > 0);
+
+        if (!inode->i_op->getxattr || !inode->i_op->setxattr) {
+                CERROR("backend fs dosen't support xattr\n");
+                return -EOPNOTSUPP;
+        }
+
+        /* set default acl */
+        if (S_ISDIR(inode->i_mode)) {
+                rc = inode->i_op->setxattr(de, XATTR_NAME_ACL_DEFAULT,
+                                           xattr, xattr_size, 0);
+                if (rc) {
+                        CERROR("set default acl err: %d\n", rc);
+                        return rc;
+                }
+        }
+
+        /* set access acl */
+        acl = posix_acl_from_xattr(xattr, xattr_size);
+        if (acl == NULL || IS_ERR(acl)) {
+                CERROR("insane attr data\n");
+                return PTR_ERR(acl);
+        }
+
+        if (posix_acl_valid(acl)) {
+                CERROR("default acl not valid: %d\n", rc);
+                rc = -EFAULT;
+                goto out;
+        }
+
+        mode = inode->i_mode;
+        rc = posix_acl_create_masq(acl, &mode);
+        if (rc < 0) {
+                CERROR("create masq err %d\n", rc);
+                goto out;
+        }
+
+        if (inode->i_mode != mode) {
+                struct iattr iattr = { .ia_valid = ATTR_MODE,
+                                       .ia_mode = mode };
+                int rc2;
+
+                rc2 = fsfilt_setattr(obd, de, handle, &iattr, 0);
+                if (rc2) {
+                        CERROR("setattr mode err: %d\n", rc2);
+                        rc = rc2;
+                        goto out;
+                }
+        }
+
+        if (rc > 0) {
+                /* we didn't change acl except mode bits of some
+                 * entries, so should be fit into original size.
+                 */
+                rc = posix_acl_to_xattr(acl, xattr, xattr_size);
+                LASSERT(rc > 0);
+
+                rc = inode->i_op->setxattr(de, XATTR_NAME_ACL_ACCESS,
+                                           xattr, xattr_size, 0);
+                if (rc)
+                        CERROR("set access acl err: %d\n", rc);
+        }
+out:
+        posix_acl_release(acl);
+        return rc;
+}
+
 static int mdt_obj_create(struct ptlrpc_request *req)
 {
         struct obd_device *obd = req->rq_export->exp_obd;
         struct mds_obd *mds = &obd->u.mds;
         struct ost_body *body, *repbody;
+        void *acl = NULL;
+        int acl_size;
         char idname[LL_ID_NAMELEN];
         int size = sizeof(*repbody);
         struct inode *parent_inode;
@@ -2001,6 +2081,17 @@ static int mdt_obj_create(struct ptlrpc_request *req)
         if (body == NULL)
                 RETURN(-EFAULT);
 
+        /* acl data is packed transparently, no swab here */
+        LASSERT(req->rq_reqmsg->bufcount >= 2);
+        acl_size = req->rq_reqmsg->buflens[1];
+        if (acl_size) {
+                acl = lustre_msg_buf(req->rq_reqmsg, 1, acl_size);
+                if (!acl) {
+                        CERROR("No default acl buf?\n");
+                        RETURN(-EFAULT);
+                }
+        }
+
         rc = lustre_pack_reply(req, 1, &size, NULL);
         if (rc)
                 RETURN(rc);
@@ -2106,6 +2197,14 @@ repeat:
 
         rc = vfs_mkdir(parent_inode, new, body->oa.o_mode);
         if (rc == 0) {
+                if (acl) {
+                        rc = mds_inode_init_acl(obd, handle, new,
+                                                acl, acl_size);
+                        if (rc) {
+                                up(&parent_inode->i_sem);
+                                GOTO(cleanup, rc);
+                        }
+                }
                 if ((body->oa.o_flags & OBD_FL_RECREATE_OBJS) ||
                     lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY) {
                         new->d_inode->i_generation = body->oa.o_generation;
diff --git a/lustre/mds/mds_fs.c b/lustre/mds/mds_fs.c
index b8bb10007c..471bd3aab2 100644
--- a/lustre/mds/mds_fs.c
+++ b/lustre/mds/mds_fs.c
@@ -919,6 +919,7 @@ int mds_fs_cleanup(struct obd_device *obd, int flags)
  * performance sensitive, it is accomplished by creating a file, checking the
  * id, and renaming it. */
 int mds_obd_create(struct obd_export *exp, struct obdo *oa,
+                   void *acl, int acl_size,
                    struct lov_stripe_md **ea, struct obd_trans_info *oti)
 {
         struct mds_obd *mds = &exp->exp_obd->u.mds;
diff --git a/lustre/mds/mds_internal.h b/lustre/mds/mds_internal.h
index b01baaf49a..0aac7823ae 100644
--- a/lustre/mds/mds_internal.h
+++ b/lustre/mds/mds_internal.h
@@ -165,7 +165,8 @@ int mds_client_add(struct obd_device *obd, struct mds_obd *mds,
                    struct mds_export_data *med, int cl_off);
 int mds_client_free(struct obd_export *exp, int clear_client);
 int mds_obd_create(struct obd_export *exp, struct obdo *oa,
-                      struct lov_stripe_md **ea, struct obd_trans_info *oti);
+                   void *acl, int acl_size,
+                   struct lov_stripe_md **ea, struct obd_trans_info *oti);
 int mds_obd_destroy(struct obd_export *exp, struct obdo *oa,
                     struct lov_stripe_md *ea, struct obd_trans_info *oti);
 
diff --git a/lustre/mds/mds_lmv.c b/lustre/mds/mds_lmv.c
index c675654c07..c99a387cdf 100644
--- a/lustre/mds/mds_lmv.c
+++ b/lustre/mds/mds_lmv.c
@@ -712,7 +712,7 @@ int mds_try_to_split_dir(struct obd_device *obd, struct dentry *dentry,
         CDEBUG(D_OTHER, "%s: create subdirs with mode %o, uid %u, gid %u\n",
                obd->obd_name, dir->i_mode, dir->i_uid, dir->i_gid);
                         
-        rc = obd_create(mds->mds_md_exp, oa,
+        rc = obd_create(mds->mds_md_exp, oa, NULL, 0,
                         (struct lov_stripe_md **)mea, NULL);
         if (rc) {
                 CERROR("Can't create remote inode, rc = %d\n", rc);
diff --git a/lustre/mds/mds_lov.c b/lustre/mds/mds_lov.c
index 4d30ebf068..6fddf121fa 100644
--- a/lustre/mds/mds_lov.c
+++ b/lustre/mds/mds_lov.c
@@ -146,7 +146,7 @@ int mds_dt_clearorphans(struct mds_obd *mds, struct obd_uuid *ost_uuid)
                 memcpy(&oa->o_inline, ost_uuid, sizeof(*ost_uuid));
                 oa->o_valid |= OBD_MD_FLINLINE;
         }
-        rc = obd_create(mds->mds_dt_exp, oa, &empty_ea, &oti);
+        rc = obd_create(mds->mds_dt_exp, oa, NULL, 0, &empty_ea, &oti);
         obdo_free(oa);
         RETURN(rc);
 }
diff --git a/lustre/mds/mds_open.c b/lustre/mds/mds_open.c
index 52dd8342f0..7fdabe6801 100644
--- a/lustre/mds/mds_open.c
+++ b/lustre/mds/mds_open.c
@@ -417,7 +417,7 @@ static int mds_create_objects(struct ptlrpc_request *req, int offset,
                                 GOTO(out_oa, rc);
                 } 
                 LASSERT(oa->o_gr >= FILTER_GROUP_FIRST_MDS);
-                rc = obd_create(mds->mds_dt_exp, oa, &lsm, &oti);
+                rc = obd_create(mds->mds_dt_exp, oa, NULL, 0, &lsm, &oti);
                 if (rc) {
                         int level = D_ERROR;
                         if (rc == -ENOSPC)
diff --git a/lustre/mds/mds_reint.c b/lustre/mds/mds_reint.c
index cd49c3c0ca..54601248ef 100644
--- a/lustre/mds/mds_reint.c
+++ b/lustre/mds/mds_reint.c
@@ -43,6 +43,7 @@
 #include <linux/lustre_dlm.h>
 #include <linux/lustre_log.h>
 #include <linux/lustre_fsfilt.h>
+#include <linux/lustre_acl.h>
 #include <linux/lustre_lite.h>
 #include "mds_internal.h"
 
@@ -638,6 +639,39 @@ static void reconstruct_reint_create(struct mds_update_record *rec, int offset,
         EXIT;
 }
 
+static int mds_get_default_acl(struct inode *dir, void **pacl)
+{
+        struct dentry de = { .d_inode = dir };
+        int size, size2;
+
+        LASSERT(S_ISDIR(dir->i_mode));
+
+        if (!dir->i_op->getxattr)
+                return 0;
+
+        size = dir->i_op->getxattr(&de, XATTR_NAME_ACL_DEFAULT, NULL, 0);
+        if (size == 0 || size == -ENODATA || size == -EOPNOTSUPP)
+                return 0;
+        else if (size < 0)
+                return size;
+
+        OBD_ALLOC(*pacl, size);
+        if (!*pacl)
+                return -ENOMEM;
+
+        size2 = dir->i_op->getxattr(&de, XATTR_NAME_ACL_DEFAULT, *pacl, size);
+        if (size2 != size) {
+                /* since we already locked the dir, it should not change
+                 * between the 2 getxattr calls
+                 */
+                CERROR("2'nd getxattr got %d, expect %d\n", size2, size);
+                OBD_FREE(*pacl, size);
+                return -EIO;
+        }
+
+        return size;
+}
+
 static int mds_reint_create(struct mds_update_record *rec, int offset,
                             struct ptlrpc_request *req,
                             struct lustre_handle *lh)
@@ -832,7 +866,9 @@ static int mds_reint_create(struct mds_update_record *rec, int offset,
                         /* inode will be created on another MDS */
                         struct obdo *oa = NULL;
                         struct mds_body *body;
-                        
+                        void *acl = NULL;
+                        int acl_size;
+
                         /* first, create that inode */
                         oa = obdo_alloc();
                         if (!oa)
@@ -877,11 +913,23 @@ static int mds_reint_create(struct mds_update_record *rec, int offset,
                                 LASSERT(oa->o_fid != 0);
                         }
 
+                        /* obtain default ACL */
+                        acl_size = mds_get_default_acl(dir, &acl);
+                        if (acl_size < 0) {
+                                obdo_free(oa);
+                                GOTO(cleanup, rc = -ENOMEM);
+                        }
+
                         /* 
                          * before obd_create() is called, o_fid is not known if
                          * this is not recovery of cause.
                          */
-                        rc = obd_create(mds->mds_md_exp, oa, NULL, NULL);
+                        rc = obd_create(mds->mds_md_exp, oa, acl, acl_size,
+                                        NULL, NULL);
+
+                        if (acl)
+                                OBD_FREE(acl, acl_size);
+
                         if (rc) {
                                 CERROR("can't create remote inode: %d\n", rc);
                                 DEBUG_REQ(D_ERROR, req, "parent "LPU64"/%u name %s mode %o",
diff --git a/lustre/obdecho/echo.c b/lustre/obdecho/echo.c
index cdd8845f31..9143ecf6cc 100644
--- a/lustre/obdecho/echo.c
+++ b/lustre/obdecho/echo.c
@@ -114,6 +114,7 @@ static int echo_destroy_export(struct obd_export *exp)
 }
 
 int echo_create(struct obd_export *exp, struct obdo *oa,
+                void *acl, int acl_size,
                 struct lov_stripe_md **ea, struct obd_trans_info *oti)
 {
         struct obd_device *obd = class_exp2obd(exp);
diff --git a/lustre/obdecho/echo_client.c b/lustre/obdecho/echo_client.c
index b52d52b94c..3d5e1457d6 100644
--- a/lustre/obdecho/echo_client.c
+++ b/lustre/obdecho/echo_client.c
@@ -221,7 +221,7 @@ static int echo_create_object(struct obd_device *obd, int on_target,
         if (on_target) {
                 oa->o_gr = FILTER_GROUP_ECHO;
                 oa->o_valid |= OBD_MD_FLGROUP;
-                rc = obd_create(ec->ec_exp, oa, &lsm, oti);
+                rc = obd_create(ec->ec_exp, oa, NULL, 0, &lsm, oti);
                 if (rc != 0)
                         goto failed;
 
diff --git a/lustre/obdfilter/filter.c b/lustre/obdfilter/filter.c
index f59981e21f..a272398a17 100644
--- a/lustre/obdfilter/filter.c
+++ b/lustre/obdfilter/filter.c
@@ -2485,6 +2485,7 @@ static int filter_precreate(struct obd_device *obd, struct obdo *oa,
 }
 
 static int filter_create(struct obd_export *exp, struct obdo *oa,
+                         void *acl, int acl_size,
                          struct lov_stripe_md **ea, struct obd_trans_info *oti)
 {
         struct obd_device *obd = NULL;
@@ -2496,6 +2497,8 @@ static int filter_create(struct obd_export *exp, struct obdo *oa,
         int group = oa->o_gr, rc = 0, diff, recreate_objs = 0;
         ENTRY;
 
+        LASSERT(acl == NULL && acl_size == 0);
+
         if (!(oa->o_valid & OBD_MD_FLGROUP) || group == 0) {
                 portals_nid2str(exp->exp_connection->c_peer.peer_ni->pni_number,
                                 exp->exp_connection->c_peer.peer_id.nid, str);
diff --git a/lustre/osc/osc_create.c b/lustre/osc/osc_create.c
index 184df58fa2..a80cd1adf6 100644
--- a/lustre/osc/osc_create.c
+++ b/lustre/osc/osc_create.c
@@ -238,6 +238,7 @@ int oscc_recovering(struct osc_creator *oscc)
 }
 
 int osc_create(struct obd_export *exp, struct obdo *oa,
+               void *acl, int acl_size,
                struct lov_stripe_md **ea, struct obd_trans_info *oti)
 {
         struct lov_stripe_md *lsm;
@@ -248,6 +249,7 @@ int osc_create(struct obd_export *exp, struct obdo *oa,
         LASSERT(ea);
         LASSERT(oa->o_valid & OBD_MD_FLGROUP);
         LASSERT(oa->o_gr > 0);
+        LASSERT(acl == NULL && acl_size == 0);
 
         if ((oa->o_valid & OBD_MD_FLFLAGS) &&
             oa->o_flags == OBD_FL_RECREATE_OBJS) {
diff --git a/lustre/osc/osc_internal.h b/lustre/osc/osc_internal.h
index b3d69a90c8..227e7c854b 100644
--- a/lustre/osc/osc_internal.h
+++ b/lustre/osc/osc_internal.h
@@ -56,6 +56,7 @@ struct osc_cache_waiter {
 #define OSCC_FLAG_EXITING            0x20
 
 int osc_create(struct obd_export *exp, struct obdo *oa,
+               void *acl, int acl_size,
 	       struct lov_stripe_md **ea, struct obd_trans_info *oti);
 int osc_real_create(struct obd_export *exp, struct obdo *oa,
 	       struct lov_stripe_md **ea, struct obd_trans_info *oti);
diff --git a/lustre/ost/ost_handler.c b/lustre/ost/ost_handler.c
index cf1c6de90d..47e007229a 100644
--- a/lustre/ost/ost_handler.c
+++ b/lustre/ost/ost_handler.c
@@ -155,7 +155,7 @@ static int ost_create(struct obd_export *exp, struct ptlrpc_request *req,
         repbody = lustre_msg_buf (req->rq_repmsg, 0, sizeof(*repbody));
         memcpy(&repbody->oa, &body->oa, sizeof(body->oa));
         oti->oti_logcookies = obdo_logcookie(&repbody->oa);
-        req->rq_status = obd_create(exp, &repbody->oa, NULL, oti);
+        req->rq_status = obd_create(exp, &repbody->oa, NULL, 0, NULL, oti);
         //obd_log_cancel(conn, NULL, 1, oti->oti_logcookies, 0);
         RETURN(0);
 }
-- 
GitLab