Merge branch 'akpm' (patches from Andrew)
[cascardo/linux.git] / fs / nfsd / nfs4proc.c
index de1ff1d..1fb2227 100644 (file)
@@ -605,8 +605,7 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 
        fh_init(&resfh, NFS4_FHSIZE);
 
-       status = fh_verify(rqstp, &cstate->current_fh, S_IFDIR,
-                          NFSD_MAY_CREATE);
+       status = fh_verify(rqstp, &cstate->current_fh, S_IFDIR, NFSD_MAY_NOP);
        if (status)
                return status;
 
@@ -1219,12 +1218,12 @@ nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 static const struct nfsd4_layout_ops *
 nfsd4_layout_verify(struct svc_export *exp, unsigned int layout_type)
 {
-       if (!exp->ex_layout_type) {
+       if (!exp->ex_layout_types) {
                dprintk("%s: export does not support pNFS\n", __func__);
                return NULL;
        }
 
-       if (exp->ex_layout_type != layout_type) {
+       if (!(exp->ex_layout_types & (1 << layout_type))) {
                dprintk("%s: layout type %d not supported\n",
                        __func__, layout_type);
                return NULL;
@@ -1270,7 +1269,7 @@ nfsd4_getdeviceinfo(struct svc_rqst *rqstp,
        nfserr = nfs_ok;
        if (gdp->gd_maxcount != 0) {
                nfserr = ops->proc_getdeviceinfo(exp->ex_path.mnt->mnt_sb,
-                                       cstate->session->se_client, gdp);
+                               rqstp, cstate->session->se_client, gdp);
        }
 
        gdp->gd_notify_types &= ops->notify_types;
@@ -2335,6 +2334,45 @@ static struct nfsd4_operation nfsd4_ops[] = {
        },
 };
 
+/**
+ * nfsd4_spo_must_allow - Determine if the compound op contains an
+ * operation that is allowed to be sent with machine credentials
+ *
+ * @rqstp: a pointer to the struct svc_rqst
+ *
+ * Checks to see if the compound contains a spo_must_allow op
+ * and confirms that it was sent with the proper machine creds.
+ */
+
+bool nfsd4_spo_must_allow(struct svc_rqst *rqstp)
+{
+       struct nfsd4_compoundres *resp = rqstp->rq_resp;
+       struct nfsd4_compoundargs *argp = rqstp->rq_argp;
+       struct nfsd4_op *this = &argp->ops[resp->opcnt - 1];
+       struct nfsd4_compound_state *cstate = &resp->cstate;
+       struct nfs4_op_map *allow = &cstate->clp->cl_spo_must_allow;
+       u32 opiter;
+
+       if (!cstate->minorversion)
+               return false;
+
+       if (cstate->spo_must_allowed == true)
+               return true;
+
+       opiter = resp->opcnt;
+       while (opiter < argp->opcnt) {
+               this = &argp->ops[opiter++];
+               if (test_bit(this->opnum, allow->u.longs) &&
+                       cstate->clp->cl_mach_cred &&
+                       nfsd4_mach_creds_match(cstate->clp, rqstp)) {
+                       cstate->spo_must_allowed = true;
+                       return true;
+               }
+       }
+       cstate->spo_must_allowed = false;
+       return false;
+}
+
 int nfsd4_max_reply(struct svc_rqst *rqstp, struct nfsd4_op *op)
 {
        struct nfsd4_operation *opdesc;