]> git.hungrycats.org Git - linux/commitdiff
[PATCH] NFS: fix the synchronous READ/WRITE bugs
authorTrond Myklebust <trond.myklebust@fys.uio.no>
Wed, 8 Oct 2003 11:51:15 +0000 (04:51 -0700)
committerLinus Torvalds <torvalds@home.osdl.org>
Wed, 8 Oct 2003 11:51:15 +0000 (04:51 -0700)
  - Use correct credentials in the NFSv4 synchronous read/write code.
  - Return correct number of read bytes in the NFSv4 synchronous read code.
  - SunRPC XDR fix: NFSv4 reads when caller requests a non-word aligned
    number of bytes was broken.

fs/nfs/nfs4proc.c
fs/nfs/nfs4xdr.c
net/sunrpc/xdr.c

index 2ef48c737a005118118b18371f347341240b5ec3..4bd0e37c9cd94ca6029a46a26ef4e91e17e76527 100644 (file)
@@ -1038,7 +1038,6 @@ nfs4_proc_read(struct nfs_read_data *rdata, struct file *filp)
                .rpc_proc       = &nfs4_procedures[NFSPROC4_CLNT_READ],
                .rpc_argp       = &rdata->args,
                .rpc_resp       = &rdata->res,
-               .rpc_cred       = rdata->cred,
        };
        unsigned long timestamp = jiffies;
        int status;
@@ -1053,8 +1052,11 @@ nfs4_proc_read(struct nfs_read_data *rdata, struct file *filp)
                struct nfs4_state *state;
                state = (struct nfs4_state *)filp->private_data;
                memcpy(&rdata->args.stateid, &state->stateid, sizeof(rdata->args.stateid));
-       } else
+               msg.rpc_cred = state->owner->so_cred;
+       } else {
                memcpy(&rdata->args.stateid, &zero_stateid, sizeof(rdata->args.stateid));
+               msg.rpc_cred = NFS_I(inode)->mm_cred;
+       }
 
        fattr->valid = 0;
        status = rpc_call_sync(server->client, &msg, flags);
@@ -1079,7 +1081,6 @@ nfs4_proc_write(struct nfs_write_data *wdata, struct file *filp)
                .rpc_proc       = &nfs4_procedures[NFSPROC4_CLNT_WRITE],
                .rpc_argp       = &wdata->args,
                .rpc_resp       = &wdata->res,
-               .rpc_cred       = wdata->cred,
        };
        int status;
 
@@ -1093,11 +1094,15 @@ nfs4_proc_write(struct nfs_write_data *wdata, struct file *filp)
                struct nfs4_state *state;
                state = (struct nfs4_state *)filp->private_data;
                memcpy(&wdata->args.stateid, &state->stateid, sizeof(wdata->args.stateid));
-       } else
+               msg.rpc_cred = state->owner->so_cred;
+       } else {
                memcpy(&wdata->args.stateid, &zero_stateid, sizeof(wdata->args.stateid));
+               msg.rpc_cred = NFS_I(inode)->mm_cred;
+       }
 
        fattr->valid = 0;
        status = rpc_call_sync(server->client, &msg, rpcflags);
+       NFS_CACHEINV(inode);
        dprintk("NFS reply write: %d\n", status);
        return status;
 }
index f80cea7b29231bb1d227fa9f421f3f27eb20a040..1ff99644aa498686883960871464f54474469e77 100644 (file)
@@ -2323,6 +2323,8 @@ nfs4_xdr_dec_read(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_readres *res)
        status = decode_read_getattr(&xdr, res->fattr);
        if (!status)
                status = -nfs_stat_to_errno(hdr.status);
+       if (!status)
+               status = res->count;
 out:
        return status;
 }
index f5411631c6b5ea4964a9c1088aa39421b5286f9d..078dad8a90e5c7668254446d3cd0f6bffa26ccda 100644 (file)
@@ -715,6 +715,7 @@ xdr_read_pages(struct xdr_stream *xdr, unsigned int len)
        struct xdr_buf *buf = xdr->buf;
        struct iovec *iov;
        ssize_t shift;
+       int padding;
 
        /* Realign pages to current pointer position */
        iov  = buf->head;
@@ -723,10 +724,10 @@ xdr_read_pages(struct xdr_stream *xdr, unsigned int len)
                xdr_shrink_bufhead(buf, shift);
 
        /* Truncate page data and move it into the tail */
-       len = XDR_QUADLEN(len) << 2;
        if (buf->page_len > len)
                xdr_shrink_pagelen(buf, buf->page_len - len);
+       padding = (XDR_QUADLEN(len) << 2) - len;
        xdr->iov = iov = buf->tail;
-       xdr->p = (uint32_t *)iov->iov_base;
+       xdr->p = (uint32_t *)((char *)iov->iov_base + padding);
        xdr->end = (uint32_t *)((char *)iov->iov_base + iov->iov_len);
 }