nfsd: fix b0rken error value for setattr on read-only mount
[pandora-kernel.git] / fs / nfsd / nfs4proc.c
index 53636ff..694d526 100644 (file)
@@ -193,10 +193,13 @@ static __be32 nfsd_check_obj_isreg(struct svc_fh *fh)
 static __be32
 do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
 {
-       struct svc_fh resfh;
+       struct svc_fh *resfh;
        __be32 status;
 
-       fh_init(&resfh, NFS4_FHSIZE);
+       resfh = kmalloc(sizeof(struct svc_fh), GFP_KERNEL);
+       if (!resfh)
+               return nfserr_jukebox;
+       fh_init(resfh, NFS4_FHSIZE);
        open->op_truncate = 0;
 
        if (open->op_create) {
@@ -221,7 +224,7 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o
                 */
                status = do_nfsd_create(rqstp, current_fh, open->op_fname.data,
                                        open->op_fname.len, &open->op_iattr,
-                                       &resfh, open->op_createmode,
+                                       resfh, open->op_createmode,
                                        (u32 *)open->op_verf.data,
                                        &open->op_truncate, &open->op_created);
 
@@ -235,30 +238,29 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o
                                                FATTR4_WORD1_TIME_MODIFY);
        } else {
                status = nfsd_lookup(rqstp, current_fh,
-                                    open->op_fname.data, open->op_fname.len, &resfh);
+                                    open->op_fname.data, open->op_fname.len, resfh);
                fh_unlock(current_fh);
                if (status)
                        goto out;
-               status = nfsd_check_obj_isreg(&resfh);
+               status = nfsd_check_obj_isreg(resfh);
        }
        if (status)
                goto out;
 
        if (is_create_with_attrs(open) && open->op_acl != NULL)
-               do_set_nfs4_acl(rqstp, &resfh, open->op_acl, open->op_bmval);
-
-       set_change_info(&open->op_cinfo, current_fh);
-       fh_dup2(current_fh, &resfh);
+               do_set_nfs4_acl(rqstp, resfh, open->op_acl, open->op_bmval);
 
        /* set reply cache */
        fh_copy_shallow(&open->op_openowner->oo_owner.so_replay.rp_openfh,
-                       &resfh.fh_handle);
+                       &resfh->fh_handle);
        if (!open->op_created)
-               status = do_open_permission(rqstp, current_fh, open,
+               status = do_open_permission(rqstp, resfh, open,
                                            NFSD_MAY_NOP);
-
+       set_change_info(&open->op_cinfo, current_fh);
+       fh_dup2(current_fh, resfh);
 out:
-       fh_put(&resfh);
+       fh_put(resfh);
+       kfree(resfh);
        return status;
 }
 
@@ -311,16 +313,14 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL)
                return nfserr_inval;
 
-       /* We don't yet support WANT bits: */
-       open->op_share_access &= NFS4_SHARE_ACCESS_MASK;
-
        open->op_created = 0;
        /*
         * RFC5661 18.51.3
         * Before RECLAIM_COMPLETE done, server should deny new lock
         */
        if (nfsd4_has_session(cstate) &&
-           !cstate->session->se_client->cl_firststate &&
+           !test_bit(NFSD4_CLIENT_RECLAIM_COMPLETE,
+                     &cstate->session->se_client->cl_flags) &&
            open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
                return nfserr_grace;
 
@@ -490,14 +490,20 @@ nfsd4_access(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                           &access->ac_supported);
 }
 
+static void gen_boot_verifier(nfs4_verifier *verifier)
+{
+       __be32 verf[2];
+
+       verf[0] = (__be32)nfssvc_boot.tv_sec;
+       verf[1] = (__be32)nfssvc_boot.tv_usec;
+       memcpy(verifier->data, verf, sizeof(verifier->data));
+}
+
 static __be32
 nfsd4_commit(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
             struct nfsd4_commit *commit)
 {
-       u32 *p = (u32 *)commit->co_verf.data;
-       *p++ = nfssvc_boot.tv_sec;
-       *p++ = nfssvc_boot.tv_usec;
-
+       gen_boot_verifier(&commit->co_verf);
        return nfsd_commit(rqstp, &cstate->current_fh, commit->co_offset,
                             commit->co_count);
 }
@@ -835,6 +841,7 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
              struct nfsd4_setattr *setattr)
 {
        __be32 status = nfs_ok;
+       int err;
 
        if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
                nfs4_lock_state();
@@ -846,9 +853,9 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                        return status;
                }
        }
-       status = fh_want_write(&cstate->current_fh);
-       if (status)
-               return status;
+       err = fh_want_write(&cstate->current_fh);
+       if (err)
+               return nfserrno(err);
        status = nfs_ok;
 
        status = check_attr_support(rqstp, cstate, setattr->sa_bmval,
@@ -874,7 +881,6 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 {
        stateid_t *stateid = &write->wr_stateid;
        struct file *filp = NULL;
-       u32 *p;
        __be32 status = nfs_ok;
        unsigned long cnt;
 
@@ -896,9 +902,7 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 
        cnt = write->wr_buflen;
        write->wr_how_written = write->wr_stable_how;
-       p = (u32 *)write->wr_verifier.data;
-       *p++ = nfssvc_boot.tv_sec;
-       *p++ = nfssvc_boot.tv_usec;
+       gen_boot_verifier(&write->wr_verifier);
 
        status =  nfsd_write(rqstp, &cstate->current_fh, filp,
                             write->wr_offset, rqstp->rq_vec, write->wr_vlen,
@@ -1054,7 +1058,9 @@ struct nfsd4_operation {
 
 static struct nfsd4_operation nfsd4_ops[];
 
+#ifdef NFSD_DEBUG
 static const char *nfsd4_op_name(unsigned opnum);
+#endif
 
 /*
  * Enforce NFSv4.1 COMPOUND ordering rules:
@@ -1715,12 +1721,14 @@ static struct nfsd4_operation nfsd4_ops[] = {
        },
 };
 
+#ifdef NFSD_DEBUG
 static const char *nfsd4_op_name(unsigned opnum)
 {
        if (opnum < ARRAY_SIZE(nfsd4_ops))
                return nfsd4_ops[opnum].op_name;
        return "unknown_operation";
 }
+#endif
 
 #define nfsd4_voidres                  nfsd4_voidargs
 struct nfsd4_voidargs { int dummy; };