Commit f60d81b1 authored by Trond Myklebust's avatar Trond Myklebust Committed by Linus Torvalds

[PATCH] NFS: fix the synchronous READ/WRITE bugs

  - 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.
parent cc7d1ffd
...@@ -1038,7 +1038,6 @@ nfs4_proc_read(struct nfs_read_data *rdata, struct file *filp) ...@@ -1038,7 +1038,6 @@ nfs4_proc_read(struct nfs_read_data *rdata, struct file *filp)
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ], .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ],
.rpc_argp = &rdata->args, .rpc_argp = &rdata->args,
.rpc_resp = &rdata->res, .rpc_resp = &rdata->res,
.rpc_cred = rdata->cred,
}; };
unsigned long timestamp = jiffies; unsigned long timestamp = jiffies;
int status; int status;
...@@ -1053,8 +1052,11 @@ nfs4_proc_read(struct nfs_read_data *rdata, struct file *filp) ...@@ -1053,8 +1052,11 @@ nfs4_proc_read(struct nfs_read_data *rdata, struct file *filp)
struct nfs4_state *state; struct nfs4_state *state;
state = (struct nfs4_state *)filp->private_data; state = (struct nfs4_state *)filp->private_data;
memcpy(&rdata->args.stateid, &state->stateid, sizeof(rdata->args.stateid)); 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)); memcpy(&rdata->args.stateid, &zero_stateid, sizeof(rdata->args.stateid));
msg.rpc_cred = NFS_I(inode)->mm_cred;
}
fattr->valid = 0; fattr->valid = 0;
status = rpc_call_sync(server->client, &msg, flags); status = rpc_call_sync(server->client, &msg, flags);
...@@ -1079,7 +1081,6 @@ nfs4_proc_write(struct nfs_write_data *wdata, struct file *filp) ...@@ -1079,7 +1081,6 @@ nfs4_proc_write(struct nfs_write_data *wdata, struct file *filp)
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE], .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE],
.rpc_argp = &wdata->args, .rpc_argp = &wdata->args,
.rpc_resp = &wdata->res, .rpc_resp = &wdata->res,
.rpc_cred = wdata->cred,
}; };
int status; int status;
...@@ -1093,11 +1094,15 @@ nfs4_proc_write(struct nfs_write_data *wdata, struct file *filp) ...@@ -1093,11 +1094,15 @@ nfs4_proc_write(struct nfs_write_data *wdata, struct file *filp)
struct nfs4_state *state; struct nfs4_state *state;
state = (struct nfs4_state *)filp->private_data; state = (struct nfs4_state *)filp->private_data;
memcpy(&wdata->args.stateid, &state->stateid, sizeof(wdata->args.stateid)); 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)); memcpy(&wdata->args.stateid, &zero_stateid, sizeof(wdata->args.stateid));
msg.rpc_cred = NFS_I(inode)->mm_cred;
}
fattr->valid = 0; fattr->valid = 0;
status = rpc_call_sync(server->client, &msg, rpcflags); status = rpc_call_sync(server->client, &msg, rpcflags);
NFS_CACHEINV(inode);
dprintk("NFS reply write: %d\n", status); dprintk("NFS reply write: %d\n", status);
return status; return status;
} }
......
...@@ -2323,6 +2323,8 @@ nfs4_xdr_dec_read(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_readres *res) ...@@ -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); status = decode_read_getattr(&xdr, res->fattr);
if (!status) if (!status)
status = -nfs_stat_to_errno(hdr.status); status = -nfs_stat_to_errno(hdr.status);
if (!status)
status = res->count;
out: out:
return status; return status;
} }
......
...@@ -715,6 +715,7 @@ xdr_read_pages(struct xdr_stream *xdr, unsigned int len) ...@@ -715,6 +715,7 @@ xdr_read_pages(struct xdr_stream *xdr, unsigned int len)
struct xdr_buf *buf = xdr->buf; struct xdr_buf *buf = xdr->buf;
struct iovec *iov; struct iovec *iov;
ssize_t shift; ssize_t shift;
int padding;
/* Realign pages to current pointer position */ /* Realign pages to current pointer position */
iov = buf->head; iov = buf->head;
...@@ -723,10 +724,10 @@ xdr_read_pages(struct xdr_stream *xdr, unsigned int len) ...@@ -723,10 +724,10 @@ xdr_read_pages(struct xdr_stream *xdr, unsigned int len)
xdr_shrink_bufhead(buf, shift); xdr_shrink_bufhead(buf, shift);
/* Truncate page data and move it into the tail */ /* Truncate page data and move it into the tail */
len = XDR_QUADLEN(len) << 2;
if (buf->page_len > len) if (buf->page_len > len)
xdr_shrink_pagelen(buf, buf->page_len - len); xdr_shrink_pagelen(buf, buf->page_len - len);
padding = (XDR_QUADLEN(len) << 2) - len;
xdr->iov = iov = buf->tail; 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); xdr->end = (uint32_t *)((char *)iov->iov_base + iov->iov_len);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment