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

[PATCH] Clean up NFSv4 READ xdr path

This creates a clean XDR path for the NFSv4 read requests instead of
routing through encode_compound()/decode_compound().  This eliminates
the intermediate step of setting up a struct nfs4_compound before
proceeding to XDR encoding, and removes the large 'switch()' statements
from the codepath altogether.
parent 95ed636d
...@@ -685,11 +685,10 @@ extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int); ...@@ -685,11 +685,10 @@ extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int);
static void static void
nfs3_read_done(struct rpc_task *task) nfs3_read_done(struct rpc_task *task)
{ {
struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata;
if (nfs3_async_handle_jukebox(task)) if (nfs3_async_handle_jukebox(task))
return; return;
nfs_readpage_result(task, data->u.v3.res.count, data->u.v3.res.eof); /* Call back common NFS readpage processing */
nfs_readpage_result(task);
} }
static void static void
...@@ -701,20 +700,20 @@ nfs3_proc_read_setup(struct nfs_read_data *data, unsigned int count) ...@@ -701,20 +700,20 @@ nfs3_proc_read_setup(struct nfs_read_data *data, unsigned int count)
int flags; int flags;
struct rpc_message msg = { struct rpc_message msg = {
.rpc_proc = &nfs3_procedures[NFS3PROC_READ], .rpc_proc = &nfs3_procedures[NFS3PROC_READ],
.rpc_argp = &data->u.v3.args, .rpc_argp = &data->args,
.rpc_resp = &data->u.v3.res, .rpc_resp = &data->res,
.rpc_cred = data->cred, .rpc_cred = data->cred,
}; };
req = nfs_list_entry(data->pages.next); req = nfs_list_entry(data->pages.next);
data->u.v3.args.fh = NFS_FH(inode); data->args.fh = NFS_FH(inode);
data->u.v3.args.offset = req_offset(req) + req->wb_offset; data->args.offset = req_offset(req) + req->wb_offset;
data->u.v3.args.pgbase = req->wb_offset; data->args.pgbase = req->wb_offset;
data->u.v3.args.pages = data->pagevec; data->args.pages = data->pagevec;
data->u.v3.args.count = count; data->args.count = count;
data->u.v3.res.fattr = &data->fattr; data->res.fattr = &data->fattr;
data->u.v3.res.count = count; data->res.count = count;
data->u.v3.res.eof = 0; data->res.eof = 0;
/* N.B. Do we need to test? Never called for swapfile inode */ /* N.B. Do we need to test? Never called for swapfile inode */
flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0); flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
......
...@@ -401,23 +401,6 @@ nfs4_setup_open_confirm(struct nfs4_compound *cp, char *stateid) ...@@ -401,23 +401,6 @@ nfs4_setup_open_confirm(struct nfs4_compound *cp, char *stateid)
cp->renew_index = cp->req_nops; cp->renew_index = cp->req_nops;
} }
static void
nfs4_setup_read(struct nfs4_compound *cp, u64 offset, u32 length,
struct page **pages, unsigned int pgbase, u32 *eofp, u32 *bytes_read)
{
struct nfs4_read *read = GET_OP(cp, read);
read->rd_offset = offset;
read->rd_length = length;
read->rd_pages = pages;
read->rd_pgbase = pgbase;
read->rd_eof = eofp;
read->rd_bytes_read = bytes_read;
OPNUM(cp) = OP_READ;
cp->req_nops++;
}
static void static void
nfs4_setup_readdir(struct nfs4_compound *cp, u64 cookie, u32 *verifier, nfs4_setup_readdir(struct nfs4_compound *cp, u64 cookie, u32 *verifier,
struct page **pages, unsigned int bufsize, struct dentry *dentry) struct page **pages, unsigned int bufsize, struct dentry *dentry)
...@@ -613,11 +596,18 @@ nfs4_setup_write(struct nfs4_compound *cp, u64 offset, u32 length, int stable, ...@@ -613,11 +596,18 @@ nfs4_setup_write(struct nfs4_compound *cp, u64 offset, u32 length, int stable,
cp->req_nops++; cp->req_nops++;
} }
static void
renew_lease(struct nfs_server *server, unsigned long timestamp)
{
spin_lock(&renew_lock);
if (time_before(server->last_renewal,timestamp))
server->last_renewal = timestamp;
spin_unlock(&renew_lock);
}
static inline void static inline void
process_lease(struct nfs4_compound *cp) process_lease(struct nfs4_compound *cp)
{ {
struct nfs_server *server;
/* /*
* Generic lease processing: If this operation contains a * Generic lease processing: If this operation contains a
* lease-renewing operation, and it succeeded, update the RENEW time * lease-renewing operation, and it succeeded, update the RENEW time
...@@ -634,13 +624,8 @@ process_lease(struct nfs4_compound *cp) ...@@ -634,13 +624,8 @@ process_lease(struct nfs4_compound *cp)
*/ */
if (!cp->renew_index) if (!cp->renew_index)
return; return;
if (!cp->toplevel_status || cp->resp_nops > cp->renew_index) { if (!cp->toplevel_status || cp->resp_nops > cp->renew_index)
server = cp->server; renew_lease(cp->server, cp->timestamp);
spin_lock(&renew_lock);
if (server->last_renewal < cp->timestamp)
server->last_renewal = cp->timestamp;
spin_unlock(&renew_lock);
}
} }
static int static int
...@@ -1003,20 +988,35 @@ nfs4_proc_read(struct inode *inode, struct rpc_cred *cred, ...@@ -1003,20 +988,35 @@ nfs4_proc_read(struct inode *inode, struct rpc_cred *cred,
unsigned int base, unsigned int count, unsigned int base, unsigned int count,
struct page *page, int *eofp) struct page *page, int *eofp)
{ {
u64 offset = page_offset(page) + base; struct nfs_server *server = NFS_SERVER(inode);
struct nfs4_compound compound; uint64_t offset = page_offset(page) + base;
struct nfs4_op ops[2]; struct nfs_readargs arg = {
u32 bytes_read; .fh = NFS_FH(inode),
int status; .offset = offset,
.count = count,
.pgbase = base,
.pages = &page,
};
struct nfs_readres res = {
.fattr = fattr,
.count = count,
};
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ],
.rpc_argp = &arg,
.rpc_resp = &res,
.rpc_cred = cred,
};
unsigned long timestamp = jiffies;
int status;
dprintk("NFS call read %d @ %Ld\n", count, (long long)offset);
fattr->valid = 0; fattr->valid = 0;
nfs4_setup_compound(&compound, ops, NFS_SERVER(inode), "read [sync]"); status = rpc_call_sync(server->client, &msg, flags);
nfs4_setup_putfh(&compound, NFS_FH(inode)); if (!status)
nfs4_setup_read(&compound, offset, count, &page, base, eofp, &bytes_read); renew_lease(server, timestamp);
status = nfs4_call_compound(&compound, cred, 0); dprintk("NFS reply read: %d\n", status);
*eofp = res.eof;
if (status >= 0)
status = bytes_read;
return status; return status;
} }
...@@ -1363,31 +1363,35 @@ nfs4_read_done(struct rpc_task *task) ...@@ -1363,31 +1363,35 @@ nfs4_read_done(struct rpc_task *task)
{ {
struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata; struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata;
process_lease(&data->u.v4.compound); if (task->tk_status > 0)
nfs_readpage_result(task, data->u.v4.res_count, data->u.v4.res_eof); renew_lease(NFS_SERVER(data->inode), data->timestamp);
/* Call back common NFS readpage processing */
nfs_readpage_result(task);
} }
static void static void
nfs4_proc_read_setup(struct nfs_read_data *data, unsigned int count) nfs4_proc_read_setup(struct nfs_read_data *data, unsigned int count)
{ {
struct rpc_task *task = &data->task; struct rpc_task *task = &data->task;
struct nfs4_compound *cp = &data->u.v4.compound;
struct rpc_message msg = { struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMPOUND], .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ],
.rpc_argp = cp, .rpc_argp = &data->args,
.rpc_resp = cp, .rpc_resp = &data->res,
.rpc_cred = data->cred, .rpc_cred = data->cred,
}; };
struct inode *inode = data->inode; struct inode *inode = data->inode;
struct nfs_page *req = nfs_list_entry(data->pages.next); struct nfs_page *req = nfs_list_entry(data->pages.next);
int flags; int flags;
nfs4_setup_compound(cp, data->u.v4.ops, NFS_SERVER(inode), "read [async]"); data->args.fh = NFS_FH(inode);
nfs4_setup_putfh(cp, NFS_FH(inode)); data->args.offset = req_offset(req) + req->wb_offset;
nfs4_setup_read(cp, req_offset(req) + req->wb_offset, data->args.pgbase = req->wb_offset;
count, data->pagevec, req->wb_offset, data->args.pages = data->pagevec;
&data->u.v4.res_eof, data->args.count = count;
&data->u.v4.res_count); data->res.fattr = &data->fattr;
data->res.count = count;
data->res.eof = 0;
data->timestamp = jiffies;
/* N.B. Do we need to test? Never called for swapfile inode */ /* N.B. Do we need to test? Never called for swapfile inode */
flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0); flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
......
...@@ -64,8 +64,29 @@ ...@@ -64,8 +64,29 @@
extern int nfs_stat_to_errno(int); extern int nfs_stat_to_errno(int);
/* NFSv4 COMPOUND tags are only wanted for debugging purposes */
#ifdef DEBUG
#define NFS4_MAXTAGLEN 20
#else
#define NFS4_MAXTAGLEN 0
#endif
#define compound_encode_hdr_maxsz 3 + (NFS4_MAXTAGLEN >> 2)
#define compound_decode_hdr_maxsz 2 + (NFS4_MAXTAGLEN >> 2)
#define op_encode_hdr_maxsz 1
#define op_decode_hdr_maxsz 2
#define encode_putfh_maxsz op_encode_hdr_maxsz + 1 + \
(NFS4_FHSIZE >> 2)
#define decode_putfh_maxsz op_decode_hdr_maxsz
#define NFS4_enc_compound_sz 1024 /* XXX: large enough? */ #define NFS4_enc_compound_sz 1024 /* XXX: large enough? */
#define NFS4_dec_compound_sz 1024 /* XXX: large enough? */ #define NFS4_dec_compound_sz 1024 /* XXX: large enough? */
#define NFS4_enc_read_sz compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
op_encode_hdr_maxsz + 7
#define NFS4_dec_read_sz compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \
op_decode_hdr_maxsz + 2
static struct { static struct {
unsigned int mode; unsigned int mode;
...@@ -131,6 +152,7 @@ encode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr) ...@@ -131,6 +152,7 @@ encode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
uint32_t *p; uint32_t *p;
dprintk("encode_compound: tag=%.*s\n", (int)hdr->taglen, hdr->tag); dprintk("encode_compound: tag=%.*s\n", (int)hdr->taglen, hdr->tag);
BUG_ON(hdr->taglen > NFS4_MAXTAGLEN);
RESERVE_SPACE(12+XDR_QUADLEN(hdr->taglen)); RESERVE_SPACE(12+XDR_QUADLEN(hdr->taglen));
WRITE32(hdr->taglen); WRITE32(hdr->taglen);
WRITEMEM(hdr->tag, hdr->taglen); WRITEMEM(hdr->tag, hdr->taglen);
...@@ -472,15 +494,15 @@ encode_open_confirm(struct xdr_stream *xdr, struct nfs4_open_confirm *open_confi ...@@ -472,15 +494,15 @@ encode_open_confirm(struct xdr_stream *xdr, struct nfs4_open_confirm *open_confi
} }
static int static int
encode_putfh(struct xdr_stream *xdr, struct nfs4_putfh *putfh) encode_putfh(struct xdr_stream *xdr, struct nfs_fh *fh)
{ {
int len = putfh->pf_fhandle->size; int len = fh->size;
uint32_t *p; uint32_t *p;
RESERVE_SPACE(8 + len); RESERVE_SPACE(8 + len);
WRITE32(OP_PUTFH); WRITE32(OP_PUTFH);
WRITE32(len); WRITE32(len);
WRITEMEM(putfh->pf_fhandle->data, len); WRITEMEM(fh->data, len);
return 0; return 0;
} }
...@@ -497,10 +519,8 @@ encode_putrootfh(struct xdr_stream *xdr) ...@@ -497,10 +519,8 @@ encode_putrootfh(struct xdr_stream *xdr)
} }
static int static int
encode_read(struct xdr_stream *xdr, struct nfs4_read *read, struct rpc_rqst *req) encode_read(struct xdr_stream *xdr, struct nfs_readargs *args)
{ {
struct rpc_auth *auth = req->rq_task->tk_auth;
int replen;
uint32_t *p; uint32_t *p;
RESERVE_SPACE(32); RESERVE_SPACE(32);
...@@ -509,16 +529,8 @@ encode_read(struct xdr_stream *xdr, struct nfs4_read *read, struct rpc_rqst *req ...@@ -509,16 +529,8 @@ encode_read(struct xdr_stream *xdr, struct nfs4_read *read, struct rpc_rqst *req
WRITE32(0); WRITE32(0);
WRITE32(0); WRITE32(0);
WRITE32(0); WRITE32(0);
WRITE64(read->rd_offset); WRITE64(args->offset);
WRITE32(read->rd_length); WRITE32(args->count);
/* set up reply iovec
* toplevel status + taglen + rescount + OP_PUTFH + status
* + OP_READ + status + eof + datalen = 9
*/
replen = (RPC_REPHDRSIZE + auth->au_rslack + 9) << 2;
xdr_inline_pages(&req->rq_rcv_buf, replen,
read->rd_pages, read->rd_pgbase, read->rd_length);
return 0; return 0;
} }
...@@ -759,14 +771,11 @@ encode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs ...@@ -759,14 +771,11 @@ encode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs
status = encode_open_confirm(xdr, &cp->ops[i].u.open_confirm); status = encode_open_confirm(xdr, &cp->ops[i].u.open_confirm);
break; break;
case OP_PUTFH: case OP_PUTFH:
status = encode_putfh(xdr, &cp->ops[i].u.putfh); status = encode_putfh(xdr, cp->ops[i].u.putfh.pf_fhandle);
break; break;
case OP_PUTROOTFH: case OP_PUTROOTFH:
status = encode_putrootfh(xdr); status = encode_putrootfh(xdr);
break; break;
case OP_READ:
status = encode_read(xdr, &cp->ops[i].u.read, req);
break;
case OP_READDIR: case OP_READDIR:
status = encode_readdir(xdr, &cp->ops[i].u.readdir, req); status = encode_readdir(xdr, &cp->ops[i].u.readdir, req);
break; break;
...@@ -829,6 +838,37 @@ nfs4_xdr_enc_compound(struct rpc_rqst *req, uint32_t *p, struct nfs4_compound *c ...@@ -829,6 +838,37 @@ nfs4_xdr_enc_compound(struct rpc_rqst *req, uint32_t *p, struct nfs4_compound *c
return status; return status;
} }
/*
* Encode a READ request
*/
static int
nfs4_xdr_enc_read(struct rpc_rqst *req, uint32_t *p, struct nfs_readargs *args)
{
struct rpc_auth *auth = req->rq_task->tk_auth;
struct xdr_stream xdr;
struct compound_hdr hdr = {
.nops = 2,
};
int replen, status;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
encode_compound_hdr(&xdr, &hdr);
status = encode_putfh(&xdr, args->fh);
if (status)
goto out;
status = encode_read(&xdr, args);
/* set up reply iovec
* toplevel status + taglen=0 + rescount + OP_PUTFH + status
* + OP_READ + status + eof + datalen = 9
*/
replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS4_dec_read_sz) << 2;
xdr_inline_pages(&req->rq_rcv_buf, replen,
args->pages, args->pgbase, args->count);
out:
return status;
}
/* /*
* START OF "GENERIC" DECODE ROUTINES. * START OF "GENERIC" DECODE ROUTINES.
...@@ -1368,7 +1408,7 @@ decode_putrootfh(struct xdr_stream *xdr) ...@@ -1368,7 +1408,7 @@ decode_putrootfh(struct xdr_stream *xdr)
} }
static int static int
decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs4_read *read) decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs_readres *res)
{ {
struct iovec *iov = req->rq_rvec; struct iovec *iov = req->rq_rvec;
uint32_t *p; uint32_t *p;
...@@ -1382,14 +1422,6 @@ decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs4_read *read ...@@ -1382,14 +1422,6 @@ decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs4_read *read
READ32(eof); READ32(eof);
READ32(count); READ32(count);
hdrlen = (u8 *) p - (u8 *) iov->iov_base; hdrlen = (u8 *) p - (u8 *) iov->iov_base;
if (iov->iov_len < hdrlen) {
printk(KERN_WARNING "NFS: READ reply header overflowed:"
"length %u > %Zu\n", hdrlen, iov->iov_len);
return -errno_NFSERR_IO;
} else if (iov->iov_len != hdrlen) {
dprintk("NFS: READ header is short. iovec will be shifted.\n");
xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen);
}
recvd = req->rq_received - hdrlen; recvd = req->rq_received - hdrlen;
if (count > recvd) { if (count > recvd) {
printk(KERN_WARNING "NFS: server cheating in read reply: " printk(KERN_WARNING "NFS: server cheating in read reply: "
...@@ -1397,9 +1429,9 @@ decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs4_read *read ...@@ -1397,9 +1429,9 @@ decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs4_read *read
count = recvd; count = recvd;
eof = 0; eof = 0;
} }
if (read->rd_eof) xdr_read_pages(xdr, count);
*read->rd_eof = eof; res->eof = eof;
*read->rd_bytes_read = count; res->count = count;
return 0; return 0;
} }
...@@ -1421,17 +1453,10 @@ decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs4_readdir ...@@ -1421,17 +1453,10 @@ decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs4_readdir
COPYMEM(readdir->rd_resp_verifier, 8); COPYMEM(readdir->rd_resp_verifier, 8);
hdrlen = (char *) p - (char *) iov->iov_base; hdrlen = (char *) p - (char *) iov->iov_base;
if (iov->iov_len < hdrlen) {
printk(KERN_WARNING "NFS: READDIR reply header overflowed:"
"length %d > %Zu\n", hdrlen, iov->iov_len);
return -EIO;
} else if (iov->iov_len != hdrlen) {
dprintk("NFS: READDIR header is short. iovec will be shifted.\n");
xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
}
recvd = req->rq_received - hdrlen; recvd = req->rq_received - hdrlen;
if (pglen > recvd) if (pglen > recvd)
pglen = recvd; pglen = recvd;
xdr_read_pages(xdr, pglen);
BUG_ON(pglen + readdir->rd_pgbase > PAGE_CACHE_SIZE); BUG_ON(pglen + readdir->rd_pgbase > PAGE_CACHE_SIZE);
p = (uint32_t *) kmap(page); p = (uint32_t *) kmap(page);
...@@ -1731,9 +1756,6 @@ decode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs ...@@ -1731,9 +1756,6 @@ decode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs
case OP_PUTROOTFH: case OP_PUTROOTFH:
status = decode_putrootfh(xdr); status = decode_putrootfh(xdr);
break; break;
case OP_READ:
status = decode_read(xdr, req, &op->u.read);
break;
case OP_READDIR: case OP_READDIR:
status = decode_readdir(xdr, req, &op->u.readdir); status = decode_readdir(xdr, req, &op->u.readdir);
break; break;
...@@ -1802,6 +1824,30 @@ nfs4_xdr_dec_compound(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_compound ...@@ -1802,6 +1824,30 @@ nfs4_xdr_dec_compound(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_compound
return status; return status;
} }
/*
* Decode Read response
*/
static int
nfs4_xdr_dec_read(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_readres *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
int status;
xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
status = decode_compound_hdr(&xdr, &hdr);
if (status)
goto out;
status = decode_putfh(&xdr);
if (status)
goto out;
status = decode_read(&xdr, rqstp, res);
if (!status)
status = -nfs_stat_to_errno(hdr.status);
out:
return status;
}
uint32_t * uint32_t *
nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus) nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus)
{ {
...@@ -1854,6 +1900,7 @@ nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus) ...@@ -1854,6 +1900,7 @@ nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus)
struct rpc_procinfo nfs4_procedures[] = { struct rpc_procinfo nfs4_procedures[] = {
PROC(COMPOUND, enc_compound, dec_compound), PROC(COMPOUND, enc_compound, dec_compound),
PROC(READ, enc_read, dec_read),
}; };
struct rpc_version nfs_version4 = { struct rpc_version nfs_version4 = {
......
...@@ -520,13 +520,6 @@ nfs_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, ...@@ -520,13 +520,6 @@ nfs_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
extern u32 * nfs_decode_dirent(u32 *, struct nfs_entry *, int); extern u32 * nfs_decode_dirent(u32 *, struct nfs_entry *, int);
static void
nfs_read_done(struct rpc_task *task)
{
struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata;
nfs_readpage_result(task, data->u.v3.res.count, data->u.v3.res.eof);
}
static void static void
nfs_proc_read_setup(struct nfs_read_data *data, unsigned int count) nfs_proc_read_setup(struct nfs_read_data *data, unsigned int count)
{ {
...@@ -536,26 +529,26 @@ nfs_proc_read_setup(struct nfs_read_data *data, unsigned int count) ...@@ -536,26 +529,26 @@ nfs_proc_read_setup(struct nfs_read_data *data, unsigned int count)
int flags; int flags;
struct rpc_message msg = { struct rpc_message msg = {
.rpc_proc = &nfs_procedures[NFSPROC_READ], .rpc_proc = &nfs_procedures[NFSPROC_READ],
.rpc_argp = &data->u.v3.args, .rpc_argp = &data->args,
.rpc_resp = &data->u.v3.res, .rpc_resp = &data->res,
.rpc_cred = data->cred, .rpc_cred = data->cred,
}; };
req = nfs_list_entry(data->pages.next); req = nfs_list_entry(data->pages.next);
data->u.v3.args.fh = NFS_FH(inode); data->args.fh = NFS_FH(inode);
data->u.v3.args.offset = req_offset(req) + req->wb_offset; data->args.offset = req_offset(req) + req->wb_offset;
data->u.v3.args.pgbase = req->wb_offset; data->args.pgbase = req->wb_offset;
data->u.v3.args.pages = data->pagevec; data->args.pages = data->pagevec;
data->u.v3.args.count = count; data->args.count = count;
data->u.v3.res.fattr = &data->fattr; data->res.fattr = &data->fattr;
data->u.v3.res.count = count; data->res.count = count;
data->u.v3.res.eof = 0; data->res.eof = 0;
/* N.B. Do we need to test? Never called for swapfile inode */ /* N.B. Do we need to test? Never called for swapfile inode */
flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0); flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
/* Finalize the task. */ /* Finalize the task. */
rpc_init_task(task, NFS_CLIENT(inode), nfs_read_done, flags); rpc_init_task(task, NFS_CLIENT(inode), nfs_readpage_result, flags);
task->tk_calldata = data; task->tk_calldata = data;
/* Release requests */ /* Release requests */
task->tk_release = nfs_readdata_release; task->tk_release = nfs_readdata_release;
......
...@@ -255,11 +255,12 @@ nfs_pagein_list(struct list_head *head, int rpages) ...@@ -255,11 +255,12 @@ nfs_pagein_list(struct list_head *head, int rpages)
* received or some error occurred (timeout or socket shutdown). * received or some error occurred (timeout or socket shutdown).
*/ */
void void
nfs_readpage_result(struct rpc_task *task, unsigned int count, int eof) nfs_readpage_result(struct rpc_task *task)
{ {
struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata; struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata;
struct inode *inode = data->inode; struct inode *inode = data->inode;
struct nfs_fattr *fattr = &data->fattr; struct nfs_fattr *fattr = &data->fattr;
unsigned int count = data->res.count;
dprintk("NFS: %4d nfs_readpage_result, (status %d)\n", dprintk("NFS: %4d nfs_readpage_result, (status %d)\n",
task->tk_pid, task->tk_status); task->tk_pid, task->tk_status);
...@@ -279,7 +280,7 @@ nfs_readpage_result(struct rpc_task *task, unsigned int count, int eof) ...@@ -279,7 +280,7 @@ nfs_readpage_result(struct rpc_task *task, unsigned int count, int eof)
req->wb_bytes - count); req->wb_bytes - count);
kunmap(page); kunmap(page);
if (eof || if (data->res.eof ||
((fattr->valid & NFS_ATTR_FATTR) && ((fattr->valid & NFS_ATTR_FATTR) &&
((req_offset(req) + req->wb_offset + count) >= fattr->size))) ((req_offset(req) + req->wb_offset + count) >= fattr->size)))
SetPageUptodate(page); SetPageUptodate(page);
......
...@@ -203,6 +203,7 @@ enum open_delegation_type4 { ...@@ -203,6 +203,7 @@ enum open_delegation_type4 {
enum { enum {
NFSPROC4_CLNT_NULL = 0, /* Unused */ NFSPROC4_CLNT_NULL = 0, /* Unused */
NFSPROC4_CLNT_COMPOUND, /* Soon to be unused */ NFSPROC4_CLNT_COMPOUND, /* Soon to be unused */
NFSPROC4_CLNT_READ,
}; };
#endif #endif
......
...@@ -369,7 +369,7 @@ extern int nfs_readpage(struct file *, struct page *); ...@@ -369,7 +369,7 @@ extern int nfs_readpage(struct file *, struct page *);
extern int nfs_readpages(struct file *, struct address_space *, extern int nfs_readpages(struct file *, struct address_space *,
struct list_head *, unsigned); struct list_head *, unsigned);
extern int nfs_pagein_list(struct list_head *, int); extern int nfs_pagein_list(struct list_head *, int);
extern void nfs_readpage_result(struct rpc_task *, unsigned int count, int eof); extern void nfs_readpage_result(struct rpc_task *);
extern void nfs_readdata_release(struct rpc_task *); extern void nfs_readdata_release(struct rpc_task *);
/* /*
......
...@@ -422,15 +422,6 @@ struct nfs4_putfh { ...@@ -422,15 +422,6 @@ struct nfs4_putfh {
struct nfs_fh * pf_fhandle; /* request */ struct nfs_fh * pf_fhandle; /* request */
}; };
struct nfs4_read {
u64 rd_offset; /* request */
u32 rd_length; /* request */
u32 *rd_eof; /* response */
u32 *rd_bytes_read; /* response */
struct page ** rd_pages; /* zero-copy data */
unsigned int rd_pgbase; /* zero-copy data */
};
struct nfs4_readdir { struct nfs4_readdir {
u64 rd_cookie; /* request */ u64 rd_cookie; /* request */
nfs4_verifier rd_req_verifier; /* request */ nfs4_verifier rd_req_verifier; /* request */
...@@ -500,7 +491,6 @@ struct nfs4_op { ...@@ -500,7 +491,6 @@ struct nfs4_op {
struct nfs4_open open; struct nfs4_open open;
struct nfs4_open_confirm open_confirm; struct nfs4_open_confirm open_confirm;
struct nfs4_putfh putfh; struct nfs4_putfh putfh;
struct nfs4_read read;
struct nfs4_readdir readdir; struct nfs4_readdir readdir;
struct nfs4_readlink readlink; struct nfs4_readlink readlink;
struct nfs4_remove remove; struct nfs4_remove remove;
...@@ -548,20 +538,11 @@ struct nfs_read_data { ...@@ -548,20 +538,11 @@ struct nfs_read_data {
struct nfs_fattr fattr; /* fattr storage */ struct nfs_fattr fattr; /* fattr storage */
struct list_head pages; /* Coalesced read requests */ struct list_head pages; /* Coalesced read requests */
struct page *pagevec[NFS_READ_MAXIOV]; struct page *pagevec[NFS_READ_MAXIOV];
union { struct nfs_readargs args;
struct { struct nfs_readres res;
struct nfs_readargs args;
struct nfs_readres res;
} v3; /* also v2 */
#ifdef CONFIG_NFS_V4 #ifdef CONFIG_NFS_V4
struct { unsigned long timestamp; /* For lease renewal */
struct nfs4_compound compound;
struct nfs4_op ops[3];
u32 res_count;
u32 res_eof;
} v4;
#endif #endif
} u;
}; };
struct nfs_write_data { struct nfs_write_data {
......
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