Whamcloud - gitweb
LU-5423 llite: pack suppgid to MDS correctly
[fs/lustre-release.git] / lustre / llite / namei.c
index 2254efa..97ea1f1 100644 (file)
@@ -27,7 +27,7 @@
  * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
- * Copyright (c) 2011, 2013, Intel Corporation.
+ * Copyright (c) 2011, 2014, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
@@ -46,7 +46,6 @@
 
 #include <obd_support.h>
 #include <lustre_fid.h>
-#include <lustre_lite.h>
 #include <lustre_dlm.h>
 #include <lustre_ver.h>
 #include "llite_internal.h"
@@ -140,7 +139,6 @@ struct inode *ll_iget(struct super_block *sb, ino_t hash,
                CDEBUG(D_VFSTRACE, "got inode: "DFID"(%p): rc = %d\n",
                       PFID(&md->body->mbo_fid1), inode, rc);
                if (rc != 0) {
-                       make_bad_inode(inode);
                        iput(inode);
                        inode = ERR_PTR(rc);
                }
@@ -517,10 +515,10 @@ static int ll_lookup_it_finish(struct ptlrpc_request *request,
 static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
                                   struct lookup_intent *it)
 {
-        struct lookup_intent lookup_it = { .it_op = IT_LOOKUP };
-        struct dentry *save = dentry, *retval;
-        struct ptlrpc_request *req = NULL;
-        struct md_op_data *op_data;
+       struct lookup_intent lookup_it = { .it_op = IT_LOOKUP };
+       struct dentry *save = dentry, *retval;
+       struct ptlrpc_request *req = NULL;
+       struct md_op_data *op_data = NULL;
         __u32 opc;
         int rc;
         ENTRY;
@@ -538,14 +536,11 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
        if (it == NULL || it->it_op == IT_GETXATTR)
                it = &lookup_it;
 
-        if (it->it_op == IT_GETATTR) {
-                rc = ll_statahead_enter(parent, &dentry, 0);
-                if (rc == 1) {
-                        if (dentry == save)
-                                GOTO(out, retval = NULL);
-                        GOTO(out, retval = dentry);
-                }
-        }
+       if (it->it_op == IT_GETATTR && dentry_may_statahead(parent, dentry)) {
+               rc = ll_statahead(parent, &dentry, 0);
+               if (rc == 1)
+                       RETURN(dentry == save ? NULL : dentry);
+       }
 
        if (it->it_op & IT_CREAT)
                opc = LUSTRE_OPC_CREATE;
@@ -554,18 +549,43 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
 
        op_data = ll_prep_md_op_data(NULL, parent, NULL, dentry->d_name.name,
                                     dentry->d_name.len, 0, opc, NULL);
-        if (IS_ERR(op_data))
-                RETURN((void *)op_data);
+       if (IS_ERR(op_data))
+               RETURN((void *)op_data);
 
-        /* enforce umask if acl disabled or MDS doesn't support umask */
-        if (!IS_POSIXACL(parent) || !exp_connect_umask(ll_i2mdexp(parent)))
+       /* enforce umask if acl disabled or MDS doesn't support umask */
+       if (!IS_POSIXACL(parent) || !exp_connect_umask(ll_i2mdexp(parent)))
                it->it_create_mode &= ~current_umask();
 
        rc = md_intent_lock(ll_i2mdexp(parent), op_data, it, &req,
                            &ll_md_blocking_ast, 0);
-        ll_finish_md_op_data(op_data);
-        if (rc < 0)
-                GOTO(out, retval = ERR_PTR(rc));
+       /* If the MDS allows the client to chgrp (CFS_SETGRP_PERM), but the
+        * client does not know which suppgid should be sent to the MDS, or
+        * some other(s) changed the target file's GID after this RPC sent
+        * to the MDS with the suppgid as the original GID, then we should
+        * try again with right suppgid. */
+       if (rc == -EACCES && it->it_op & IT_OPEN &&
+           it_disposition(it, DISP_OPEN_DENY)) {
+               struct mdt_body *body;
+
+               LASSERT(req != NULL);
+
+               body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
+               if (op_data->op_suppgids[0] == body->mbo_gid ||
+                   op_data->op_suppgids[1] == body->mbo_gid ||
+                   !in_group_p(make_kgid(&init_user_ns, body->mbo_gid)))
+                       GOTO(out, retval = ERR_PTR(-EACCES));
+
+               fid_zero(&op_data->op_fid2);
+               op_data->op_suppgids[1] = body->mbo_gid;
+               ptlrpc_req_finished(req);
+               req = NULL;
+               ll_intent_release(it);
+               rc = md_intent_lock(ll_i2mdexp(parent), op_data, it, &req,
+                                   &ll_md_blocking_ast, 0);
+       }
+
+       if (rc < 0)
+               GOTO(out, retval = ERR_PTR(rc));
 
        rc = ll_lookup_it_finish(req, it, parent, &dentry);
         if (rc != 0) {
@@ -580,16 +600,14 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
         }
         ll_lookup_finish_locks(it, dentry);
 
-        if (dentry == save)
-                GOTO(out, retval = NULL);
-        else
-                GOTO(out, retval = dentry);
- out:
-        if (req)
-                ptlrpc_req_finished(req);
-        if (it->it_op == IT_GETATTR && (retval == NULL || retval == dentry))
-                ll_statahead_mark(parent, dentry);
-        return retval;
+       GOTO(out, retval = (dentry == save) ? NULL : dentry);
+
+out:
+       if (op_data != NULL && !IS_ERR(op_data))
+               ll_finish_md_op_data(op_data);
+
+       ptlrpc_req_finished(req);
+       return retval;
 }
 
 #ifdef HAVE_IOP_ATOMIC_OPEN
@@ -1169,82 +1187,6 @@ int ll_rmdir_entry(struct inode *dir, char *name, int namelen)
        RETURN(rc);
 }
 
-int ll_objects_destroy(struct ptlrpc_request *request, struct inode *dir)
-{
-        struct mdt_body *body;
-        struct lov_mds_md *eadata;
-        struct lov_stripe_md *lsm = NULL;
-        struct obd_trans_info oti = { 0 };
-        struct obdo *oa;
-        struct obd_capa *oc = NULL;
-        int rc;
-        ENTRY;
-
-        /* req is swabbed so this is safe */
-       body = req_capsule_server_get(&request->rq_pill, &RMF_MDT_BODY);
-       if (!(body->mbo_valid & OBD_MD_FLEASIZE))
-               RETURN(0);
-
-       if (body->mbo_eadatasize == 0) {
-                CERROR("OBD_MD_FLEASIZE set but eadatasize zero\n");
-                GOTO(out, rc = -EPROTO);
-        }
-
-        /* The MDS sent back the EA because we unlinked the last reference
-         * to this file. Use this EA to unlink the objects on the OST.
-         * It's opaque so we don't swab here; we leave it to obd_unpackmd() to
-         * check it is complete and sensible. */
-       eadata = req_capsule_server_sized_get(&request->rq_pill, &RMF_MDT_MD,
-                                             body->mbo_eadatasize);
-       LASSERT(eadata != NULL);
-
-       rc = obd_unpackmd(ll_i2dtexp(dir), &lsm, eadata, body->mbo_eadatasize);
-        if (rc < 0) {
-                CERROR("obd_unpackmd: %d\n", rc);
-                GOTO(out, rc);
-        }
-        LASSERT(rc >= sizeof(*lsm));
-
-        OBDO_ALLOC(oa);
-        if (oa == NULL)
-                GOTO(out_free_memmd, rc = -ENOMEM);
-
-       oa->o_oi = lsm->lsm_oi;
-       oa->o_mode = body->mbo_mode & S_IFMT;
-       oa->o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLGROUP;
-
-       if (body->mbo_valid & OBD_MD_FLCOOKIE) {
-                oa->o_valid |= OBD_MD_FLCOOKIE;
-                oti.oti_logcookies =
-                        req_capsule_server_sized_get(&request->rq_pill,
-                                                     &RMF_LOGCOOKIES,
-                                                   sizeof(struct llog_cookie) *
-                                                     lsm->lsm_stripe_count);
-                if (oti.oti_logcookies == NULL) {
-                        oa->o_valid &= ~OBD_MD_FLCOOKIE;
-                       body->mbo_valid &= ~OBD_MD_FLCOOKIE;
-               }
-       }
-
-       if (body->mbo_valid & OBD_MD_FLOSSCAPA) {
-                rc = md_unpack_capa(ll_i2mdexp(dir), request, &RMF_CAPA2, &oc);
-                if (rc)
-                        GOTO(out_free_memmd, rc);
-        }
-
-       rc = obd_destroy(NULL, ll_i2dtexp(dir), oa, lsm, &oti,
-                        ll_i2mdexp(dir), oc);
-       capa_put(oc);
-       if (rc)
-               CERROR("obd destroy objid "DOSTID" error %d\n",
-                      POSTID(&lsm->lsm_oi), rc);
-out_free_memmd:
-       obd_free_memmd(ll_i2dtexp(dir), &lsm);
-       OBDO_FREE(oa);
-out:
-       return rc;
-}
-
 /* ll_unlink() doesn't update the inode with the new link count.
  * Instead, ll_ddelete() and ll_d_iput() will update it based upon if
  * there is any lock existing. They will recycle dentries and inodes
@@ -1283,7 +1225,6 @@ static int ll_unlink(struct inode *dir, struct dentry *dchild)
         ll_update_times(request, dir);
         ll_stats_ops_tally(ll_i2sbi(dir), LPROC_LL_UNLINK, 1);
 
-        rc = ll_objects_destroy(request, dir);
  out:
         ptlrpc_req_finished(request);
         RETURN(rc);
@@ -1327,7 +1268,6 @@ static int ll_rename(struct inode *src, struct dentry *src_dchild,
                 ll_update_times(request, src);
                 ll_update_times(request, tgt);
                 ll_stats_ops_tally(sbi, LPROC_LL_RENAME, 1);
-                err = ll_objects_destroy(request, src);
         }
 
         ptlrpc_req_finished(request);