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

[PATCH] Clean up NFSv4 WRITE xdr path

The following patch creates a clean XDR path for the NFSv4 write requests
instead of routing through encode_compound()/decode_compound().
parent fa09df5e
...@@ -730,12 +730,9 @@ nfs3_proc_read_setup(struct nfs_read_data *data, unsigned int count) ...@@ -730,12 +730,9 @@ nfs3_proc_read_setup(struct nfs_read_data *data, unsigned int count)
static void static void
nfs3_write_done(struct rpc_task *task) nfs3_write_done(struct rpc_task *task)
{ {
struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata;
if (nfs3_async_handle_jukebox(task)) if (nfs3_async_handle_jukebox(task))
return; return;
nfs_writeback_done(task, data->u.v3.args.stable, nfs_writeback_done(task);
data->u.v3.args.count, data->u.v3.res.count);
} }
static void static void
...@@ -748,8 +745,8 @@ nfs3_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how) ...@@ -748,8 +745,8 @@ nfs3_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how)
int flags; int flags;
struct rpc_message msg = { struct rpc_message msg = {
.rpc_proc = &nfs3_procedures[NFS3PROC_WRITE], .rpc_proc = &nfs3_procedures[NFS3PROC_WRITE],
.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,
}; };
...@@ -762,15 +759,15 @@ nfs3_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how) ...@@ -762,15 +759,15 @@ nfs3_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how)
stable = NFS_UNSTABLE; stable = NFS_UNSTABLE;
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.count = count; data->args.count = count;
data->u.v3.args.stable = stable; data->args.stable = stable;
data->u.v3.args.pages = data->pagevec; data->args.pages = data->pagevec;
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.verf = &data->verf; data->res.verf = &data->verf;
/* Set the initial flags for the task. */ /* Set the initial flags for the task. */
flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
...@@ -800,17 +797,17 @@ nfs3_proc_commit_setup(struct nfs_write_data *data, u64 start, u32 len, int how) ...@@ -800,17 +797,17 @@ nfs3_proc_commit_setup(struct nfs_write_data *data, u64 start, u32 len, int how)
int flags; int flags;
struct rpc_message msg = { struct rpc_message msg = {
.rpc_proc = &nfs3_procedures[NFS3PROC_COMMIT], .rpc_proc = &nfs3_procedures[NFS3PROC_COMMIT],
.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,
}; };
data->u.v3.args.fh = NFS_FH(data->inode); data->args.fh = NFS_FH(data->inode);
data->u.v3.args.offset = start; data->args.offset = start;
data->u.v3.args.count = len; data->args.count = len;
data->u.v3.res.count = len; data->res.count = len;
data->u.v3.res.fattr = &data->fattr; data->res.fattr = &data->fattr;
data->u.v3.res.verf = &data->verf; data->res.verf = &data->verf;
/* Set the initial flags for the task. */ /* Set the initial flags for the task. */
flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
......
...@@ -93,19 +93,6 @@ nfs4_setup_close(struct nfs4_compound *cp, nfs4_stateid stateid, u32 seqid) ...@@ -93,19 +93,6 @@ nfs4_setup_close(struct nfs4_compound *cp, nfs4_stateid stateid, u32 seqid)
cp->renew_index = cp->req_nops; cp->renew_index = cp->req_nops;
} }
static void
nfs4_setup_commit(struct nfs4_compound *cp, u64 start, u32 len, struct nfs_writeverf *verf)
{
struct nfs4_commit *commit = GET_OP(cp, commit);
commit->co_start = start;
commit->co_len = len;
commit->co_verifier = verf;
OPNUM(cp) = OP_COMMIT;
cp->req_nops++;
}
static void static void
nfs4_setup_create_dir(struct nfs4_compound *cp, struct qstr *name, nfs4_setup_create_dir(struct nfs4_compound *cp, struct qstr *name,
struct iattr *sattr, struct nfs4_change_info *info) struct iattr *sattr, struct nfs4_change_info *info)
...@@ -576,26 +563,6 @@ nfs4_setup_setclientid_confirm(struct nfs4_compound *cp) ...@@ -576,26 +563,6 @@ nfs4_setup_setclientid_confirm(struct nfs4_compound *cp)
cp->renew_index = cp->req_nops; cp->renew_index = cp->req_nops;
} }
static void
nfs4_setup_write(struct nfs4_compound *cp, u64 offset, u32 length, int stable,
struct page **pages, unsigned int pgbase, u32 *bytes_written,
struct nfs_writeverf *verf)
{
struct nfs4_write *write = GET_OP(cp, write);
write->wr_offset = offset;
write->wr_stable_how = stable;
write->wr_len = length;
write->wr_bytes_written = bytes_written;
write->wr_verf = verf;
write->wr_pages = pages;
write->wr_pgbase = pgbase;
OPNUM(cp) = OP_WRITE;
cp->req_nops++;
}
static void static void
renew_lease(struct nfs_server *server, unsigned long timestamp) renew_lease(struct nfs_server *server, unsigned long timestamp)
{ {
...@@ -1026,23 +993,32 @@ nfs4_proc_write(struct inode *inode, struct rpc_cred *cred, ...@@ -1026,23 +993,32 @@ nfs4_proc_write(struct inode *inode, struct rpc_cred *cred,
unsigned int base, unsigned int count, unsigned int base, unsigned int count,
struct page *page, struct nfs_writeverf *verf) struct page *page, struct nfs_writeverf *verf)
{ {
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_writeargs arg = {
u32 bytes_written; .fh = NFS_FH(inode),
int stable = (flags & NFS_RW_SYNC) ? NFS_FILE_SYNC : NFS_UNSTABLE; .offset = offset,
.count = count,
.stable = (flags & NFS_RW_SYNC) ? NFS_FILE_SYNC : NFS_UNSTABLE,
.pgbase = base,
.pages = &page,
};
struct nfs_writeres res = {
.fattr = fattr,
.count = count,
.verf = verf,
};
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE],
.rpc_argp = &arg,
.rpc_resp = &res,
.rpc_cred = cred,
};
int rpcflags = (flags & NFS_RW_SWAP) ? NFS_RPC_SWAPFLAGS : 0; int rpcflags = (flags & NFS_RW_SWAP) ? NFS_RPC_SWAPFLAGS : 0;
int status;
dprintk("NFS call write %d @ %Ld\n", count, (long long)offset);
fattr->valid = 0; fattr->valid = 0;
nfs4_setup_compound(&compound, ops, NFS_SERVER(inode), "write [sync]"); return rpc_call_sync(server->client, &msg, rpcflags);
nfs4_setup_putfh(&compound, NFS_FH(inode));
nfs4_setup_write(&compound, offset, count, stable, &page, base, &bytes_written, verf);
status = nfs4_call_compound(&compound, cred, rpcflags);
if (status >= 0)
status = bytes_written;
return status;
} }
static int static int
...@@ -1410,20 +1386,20 @@ nfs4_write_done(struct rpc_task *task) ...@@ -1410,20 +1386,20 @@ nfs4_write_done(struct rpc_task *task)
{ {
struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata; struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata;
process_lease(&data->u.v4.compound); if (task->tk_status > 0)
nfs_writeback_done(task, data->u.v4.arg_stable, renew_lease(NFS_SERVER(data->inode), data->timestamp);
data->u.v4.arg_count, data->u.v4.res_count); /* Call back common NFS writeback processing */
nfs_writeback_done(task);
} }
static void static void
nfs4_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how) nfs4_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how)
{ {
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_WRITE],
.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;
...@@ -1439,11 +1415,16 @@ nfs4_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how) ...@@ -1439,11 +1415,16 @@ nfs4_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how)
} else } else
stable = NFS_UNSTABLE; stable = NFS_UNSTABLE;
nfs4_setup_compound(cp, data->u.v4.ops, NFS_SERVER(inode), "write [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_write(cp, req_offset(req) + req->wb_offset, data->args.pgbase = req->wb_offset;
count, stable, data->pagevec, req->wb_offset, data->args.count = count;
&data->u.v4.res_count, &data->verf); data->args.stable = stable;
data->args.pages = data->pagevec;
data->res.fattr = &data->fattr;
data->res.count = count;
data->res.verf = &data->verf;
data->timestamp = jiffies;
/* Set the initial flags for the task. */ /* Set the initial flags for the task. */
flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
...@@ -1457,38 +1438,31 @@ nfs4_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how) ...@@ -1457,38 +1438,31 @@ nfs4_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how)
rpc_call_setup(task, &msg, 0); rpc_call_setup(task, &msg, 0);
} }
static void
nfs4_commit_done(struct rpc_task *task)
{
struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata;
process_lease(&data->u.v4.compound);
nfs_commit_done(task);
}
static void static void
nfs4_proc_commit_setup(struct nfs_write_data *data, u64 start, u32 len, int how) nfs4_proc_commit_setup(struct nfs_write_data *data, u64 start, u32 len, int how)
{ {
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_COMMIT],
.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;
int flags; int flags;
nfs4_setup_compound(cp, data->u.v4.ops, NFS_SERVER(inode), "commit [async]"); data->args.fh = NFS_FH(data->inode);
nfs4_setup_putfh(cp, NFS_FH(inode)); data->args.offset = start;
nfs4_setup_commit(cp, start, len, &data->verf); data->args.count = len;
data->res.count = len;
data->res.fattr = &data->fattr;
data->res.verf = &data->verf;
/* Set the initial flags for the task. */ /* Set the initial flags for the task. */
flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
/* Finalize the task. */ /* Finalize the task. */
rpc_init_task(task, NFS_CLIENT(inode), nfs4_commit_done, flags); rpc_init_task(task, NFS_CLIENT(inode), nfs_commit_done, flags);
task->tk_calldata = data; task->tk_calldata = data;
/* Release requests */ /* Release requests */
task->tk_release = nfs_commit_release; task->tk_release = nfs_commit_release;
......
...@@ -87,6 +87,19 @@ extern int nfs_stat_to_errno(int); ...@@ -87,6 +87,19 @@ extern int nfs_stat_to_errno(int);
#define NFS4_dec_read_sz compound_decode_hdr_maxsz + \ #define NFS4_dec_read_sz compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \ decode_putfh_maxsz + \
op_decode_hdr_maxsz + 2 op_decode_hdr_maxsz + 2
#define NFS4_enc_write_sz compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
op_encode_hdr_maxsz + 8
#define NFS4_dec_write_sz compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \
op_decode_hdr_maxsz + 4
#define NFS4_enc_commit_sz compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
op_encode_hdr_maxsz + 3
#define NFS4_dec_commit_sz compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \
op_decode_hdr_maxsz + 2
static struct { static struct {
unsigned int mode; unsigned int mode;
...@@ -332,14 +345,14 @@ encode_close(struct xdr_stream *xdr, struct nfs4_close *close) ...@@ -332,14 +345,14 @@ encode_close(struct xdr_stream *xdr, struct nfs4_close *close)
} }
static int static int
encode_commit(struct xdr_stream *xdr, struct nfs4_commit *commit) encode_commit(struct xdr_stream *xdr, struct nfs_writeargs *args)
{ {
uint32_t *p; uint32_t *p;
RESERVE_SPACE(16); RESERVE_SPACE(16);
WRITE32(OP_COMMIT); WRITE32(OP_COMMIT);
WRITE64(commit->co_start); WRITE64(args->offset);
WRITE32(commit->co_len); WRITE32(args->count);
return 0; return 0;
} }
...@@ -705,9 +718,8 @@ encode_setclientid_confirm(struct xdr_stream *xdr, struct nfs4_client *client_st ...@@ -705,9 +718,8 @@ encode_setclientid_confirm(struct xdr_stream *xdr, struct nfs4_client *client_st
} }
static int static int
encode_write(struct xdr_stream *xdr, struct nfs4_write *write, struct rpc_rqst *req) encode_write(struct xdr_stream *xdr, struct nfs_writeargs *args)
{ {
struct xdr_buf *sndbuf = &req->rq_snd_buf;
uint32_t *p; uint32_t *p;
RESERVE_SPACE(36); RESERVE_SPACE(36);
...@@ -716,11 +728,11 @@ encode_write(struct xdr_stream *xdr, struct nfs4_write *write, struct rpc_rqst * ...@@ -716,11 +728,11 @@ encode_write(struct xdr_stream *xdr, struct nfs4_write *write, struct rpc_rqst *
WRITE32(0xffffffff); WRITE32(0xffffffff);
WRITE32(0xffffffff); WRITE32(0xffffffff);
WRITE32(0xffffffff); WRITE32(0xffffffff);
WRITE64(write->wr_offset); WRITE64(args->offset);
WRITE32(write->wr_stable_how); WRITE32(args->stable);
WRITE32(write->wr_len); WRITE32(args->count);
xdr_encode_pages(sndbuf, write->wr_pages, write->wr_pgbase, write->wr_len); xdr_write_pages(xdr, args->pages, args->pgbase, args->count);
return 0; return 0;
} }
...@@ -746,9 +758,6 @@ encode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs ...@@ -746,9 +758,6 @@ encode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs
case OP_CLOSE: case OP_CLOSE:
status = encode_close(xdr, &cp->ops[i].u.close); status = encode_close(xdr, &cp->ops[i].u.close);
break; break;
case OP_COMMIT:
status = encode_commit(xdr, &cp->ops[i].u.commit);
break;
case OP_CREATE: case OP_CREATE:
status = encode_create(xdr, &cp->ops[i].u.create); status = encode_create(xdr, &cp->ops[i].u.create);
break; break;
...@@ -806,9 +815,6 @@ encode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs ...@@ -806,9 +815,6 @@ encode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs
case OP_SETCLIENTID_CONFIRM: case OP_SETCLIENTID_CONFIRM:
status = encode_setclientid_confirm(xdr, cp->ops[i].u.setclientid_confirm); status = encode_setclientid_confirm(xdr, cp->ops[i].u.setclientid_confirm);
break; break;
case OP_WRITE:
status = encode_write(xdr, &cp->ops[i].u.write, req);
break;
default: default:
BUG(); BUG();
} }
...@@ -869,6 +875,49 @@ nfs4_xdr_enc_read(struct rpc_rqst *req, uint32_t *p, struct nfs_readargs *args) ...@@ -869,6 +875,49 @@ nfs4_xdr_enc_read(struct rpc_rqst *req, uint32_t *p, struct nfs_readargs *args)
return status; return status;
} }
/*
* Encode a WRITE request
*/
static int
nfs4_xdr_enc_write(struct rpc_rqst *req, uint32_t *p, struct nfs_writeargs *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
.nops = 2,
};
int 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_write(&xdr, args);
out:
return status;
}
/*
* Encode a COMMIT request
*/
static int
nfs4_xdr_enc_commit(struct rpc_rqst *req, uint32_t *p, struct nfs_writeargs *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
.nops = 2,
};
int 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_commit(&xdr, args);
out:
return status;
}
/* /*
* START OF "GENERIC" DECODE ROUTINES. * START OF "GENERIC" DECODE ROUTINES.
...@@ -1022,7 +1071,7 @@ decode_close(struct xdr_stream *xdr, struct nfs4_close *close) ...@@ -1022,7 +1071,7 @@ decode_close(struct xdr_stream *xdr, struct nfs4_close *close)
} }
static int static int
decode_commit(struct xdr_stream *xdr, struct nfs4_commit *commit) decode_commit(struct xdr_stream *xdr, struct nfs_writeres *res)
{ {
uint32_t *p; uint32_t *p;
int status; int status;
...@@ -1031,7 +1080,7 @@ decode_commit(struct xdr_stream *xdr, struct nfs4_commit *commit) ...@@ -1031,7 +1080,7 @@ decode_commit(struct xdr_stream *xdr, struct nfs4_commit *commit)
if (status) if (status)
return status; return status;
READ_BUF(8); READ_BUF(8);
COPYMEM(commit->co_verifier->verifier, 8); COPYMEM(res->verf->verifier, 8);
return 0; return 0;
} }
...@@ -1672,7 +1721,7 @@ decode_setclientid_confirm(struct xdr_stream *xdr) ...@@ -1672,7 +1721,7 @@ decode_setclientid_confirm(struct xdr_stream *xdr)
} }
static int static int
decode_write(struct xdr_stream *xdr, struct nfs4_write *write) decode_write(struct xdr_stream *xdr, struct nfs_writeres *res)
{ {
uint32_t *p; uint32_t *p;
int status; int status;
...@@ -1682,11 +1731,9 @@ decode_write(struct xdr_stream *xdr, struct nfs4_write *write) ...@@ -1682,11 +1731,9 @@ decode_write(struct xdr_stream *xdr, struct nfs4_write *write)
return status; return status;
READ_BUF(16); READ_BUF(16);
READ32(*write->wr_bytes_written); READ32(res->count);
if (*write->wr_bytes_written > write->wr_len) READ32(res->verf->committed);
return -EIO; COPYMEM(res->verf->verifier, 8);
READ32(write->wr_verf->committed);
COPYMEM(write->wr_verf->verifier, 8);
return 0; return 0;
} }
...@@ -1726,9 +1773,6 @@ decode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs ...@@ -1726,9 +1773,6 @@ decode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs
case OP_CLOSE: case OP_CLOSE:
status = decode_close(xdr, &op->u.close); status = decode_close(xdr, &op->u.close);
break; break;
case OP_COMMIT:
status = decode_commit(xdr, &op->u.commit);
break;
case OP_CREATE: case OP_CREATE:
status = decode_create(xdr, &op->u.create); status = decode_create(xdr, &op->u.create);
break; break;
...@@ -1786,9 +1830,6 @@ decode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs ...@@ -1786,9 +1830,6 @@ decode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs
case OP_SETCLIENTID_CONFIRM: case OP_SETCLIENTID_CONFIRM:
status = decode_setclientid_confirm(xdr); status = decode_setclientid_confirm(xdr);
break; break;
case OP_WRITE:
status = decode_write(xdr, &op->u.write);
break;
default: default:
BUG(); BUG();
return -EIO; return -EIO;
...@@ -1848,6 +1889,56 @@ nfs4_xdr_dec_read(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_readres *res) ...@@ -1848,6 +1889,56 @@ nfs4_xdr_dec_read(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_readres *res)
return status; return status;
} }
/*
* Decode WRITE response
*/
static int
nfs4_xdr_dec_write(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_writeres *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_write(&xdr, res);
if (!status)
status = -nfs_stat_to_errno(hdr.status);
if (!status)
status = res->count;
out:
return status;
}
/*
* Decode COMMIT response
*/
static int
nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_writeres *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_commit(&xdr, 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)
{ {
...@@ -1901,6 +1992,8 @@ nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus) ...@@ -1901,6 +1992,8 @@ 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), PROC(READ, enc_read, dec_read),
PROC(WRITE, enc_write, dec_write),
PROC(COMMIT, enc_commit, dec_commit),
}; };
struct rpc_version nfs_version4 = { struct rpc_version nfs_version4 = {
......
...@@ -556,14 +556,6 @@ nfs_proc_read_setup(struct nfs_read_data *data, unsigned int count) ...@@ -556,14 +556,6 @@ nfs_proc_read_setup(struct nfs_read_data *data, unsigned int count)
rpc_call_setup(&data->task, &msg, 0); rpc_call_setup(&data->task, &msg, 0);
} }
static void
nfs_write_done(struct rpc_task *task)
{
struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata;
nfs_writeback_done(task, data->u.v3.args.stable,
data->u.v3.args.count, data->u.v3.res.count);
}
static void static void
nfs_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how) nfs_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how)
{ {
...@@ -573,29 +565,29 @@ nfs_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how) ...@@ -573,29 +565,29 @@ nfs_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how)
int flags; int flags;
struct rpc_message msg = { struct rpc_message msg = {
.rpc_proc = &nfs_procedures[NFSPROC_WRITE], .rpc_proc = &nfs_procedures[NFSPROC_WRITE],
.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,
}; };
/* Note: NFSv2 ignores @stable and always uses NFS_FILE_SYNC */ /* Note: NFSv2 ignores @stable and always uses NFS_FILE_SYNC */
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.count = count; data->args.count = count;
data->u.v3.args.stable = NFS_FILE_SYNC; data->args.stable = NFS_FILE_SYNC;
data->u.v3.args.pages = data->pagevec; data->args.pages = data->pagevec;
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.verf = &data->verf; data->res.verf = &data->verf;
/* Set the initial flags for the task. */ /* Set the initial flags for the task. */
flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
/* Finalize the task. */ /* Finalize the task. */
rpc_init_task(task, NFS_CLIENT(inode), nfs_write_done, flags); rpc_init_task(task, NFS_CLIENT(inode), nfs_writeback_done, flags);
task->tk_calldata = data; task->tk_calldata = data;
/* Release requests */ /* Release requests */
task->tk_release = nfs_writedata_release; task->tk_release = nfs_writedata_release;
......
...@@ -841,10 +841,11 @@ nfs_flush_list(struct list_head *head, int wpages, int how) ...@@ -841,10 +841,11 @@ nfs_flush_list(struct list_head *head, int wpages, int how)
* This function is called when the WRITE call is complete. * This function is called when the WRITE call is complete.
*/ */
void void
nfs_writeback_done(struct rpc_task *task, int stable, nfs_writeback_done(struct rpc_task *task)
unsigned int arg_count, unsigned int res_count)
{ {
struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata; struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata;
struct nfs_writeargs *argp = &data->args;
struct nfs_writeres *resp = &data->res;
struct inode *inode = data->inode; struct inode *inode = data->inode;
struct nfs_page *req; struct nfs_page *req;
struct page *page; struct page *page;
...@@ -853,7 +854,7 @@ nfs_writeback_done(struct rpc_task *task, int stable, ...@@ -853,7 +854,7 @@ nfs_writeback_done(struct rpc_task *task, int stable,
task->tk_pid, task->tk_status); task->tk_pid, task->tk_status);
/* We can't handle that yet but we check for it nevertheless */ /* We can't handle that yet but we check for it nevertheless */
if (res_count < arg_count && task->tk_status >= 0) { if (resp->count < argp->count && task->tk_status >= 0) {
static unsigned long complain; static unsigned long complain;
if (time_before(complain, jiffies)) { if (time_before(complain, jiffies)) {
printk(KERN_WARNING printk(KERN_WARNING
...@@ -865,7 +866,7 @@ nfs_writeback_done(struct rpc_task *task, int stable, ...@@ -865,7 +866,7 @@ nfs_writeback_done(struct rpc_task *task, int stable,
task->tk_status = -EIO; task->tk_status = -EIO;
} }
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
if (data->verf.committed < stable && task->tk_status >= 0) { if (data->verf.committed < argp->stable && task->tk_status >= 0) {
/* We tried a write call, but the server did not /* We tried a write call, but the server did not
* commit data to stable storage even though we * commit data to stable storage even though we
* requested it. * requested it.
...@@ -880,7 +881,7 @@ nfs_writeback_done(struct rpc_task *task, int stable, ...@@ -880,7 +881,7 @@ nfs_writeback_done(struct rpc_task *task, int stable,
dprintk("NFS: faulty NFS server %s:" dprintk("NFS: faulty NFS server %s:"
" (committed = %d) != (stable = %d)\n", " (committed = %d) != (stable = %d)\n",
NFS_SERVER(inode)->hostname, NFS_SERVER(inode)->hostname,
data->verf.committed, stable); data->verf.committed, argp->stable);
complain = jiffies + 300 * HZ; complain = jiffies + 300 * HZ;
} }
} }
...@@ -917,7 +918,7 @@ nfs_writeback_done(struct rpc_task *task, int stable, ...@@ -917,7 +918,7 @@ nfs_writeback_done(struct rpc_task *task, int stable,
end_page_writeback(page); end_page_writeback(page);
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
if (stable != NFS_UNSTABLE || data->verf.committed == NFS_FILE_SYNC) { if (argp->stable != NFS_UNSTABLE || data->verf.committed == NFS_FILE_SYNC) {
nfs_inode_remove_request(req); nfs_inode_remove_request(req);
dprintk(" OK\n"); dprintk(" OK\n");
goto next; goto next;
......
...@@ -204,6 +204,8 @@ enum { ...@@ -204,6 +204,8 @@ 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, NFSPROC4_CLNT_READ,
NFSPROC4_CLNT_WRITE,
NFSPROC4_CLNT_COMMIT,
}; };
#endif #endif
......
...@@ -295,8 +295,7 @@ extern int nfs_writepage(struct page *page, struct writeback_control *wbc); ...@@ -295,8 +295,7 @@ extern int nfs_writepage(struct page *page, struct writeback_control *wbc);
extern int nfs_writepages(struct address_space *, struct writeback_control *); extern int nfs_writepages(struct address_space *, struct writeback_control *);
extern int nfs_flush_incompatible(struct file *file, struct page *page); extern int nfs_flush_incompatible(struct file *file, struct page *page);
extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int); extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int);
extern void nfs_writeback_done(struct rpc_task *task, int stable, extern void nfs_writeback_done(struct rpc_task *task);
unsigned int arg_count, unsigned int res_count);
extern void nfs_writedata_release(struct rpc_task *task); extern void nfs_writedata_release(struct rpc_task *task);
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
......
...@@ -346,12 +346,6 @@ struct nfs4_close { ...@@ -346,12 +346,6 @@ struct nfs4_close {
u32 cl_seqid; /* request */ u32 cl_seqid; /* request */
}; };
struct nfs4_commit {
u64 co_start; /* request */
u32 co_len; /* request */
struct nfs_writeverf * co_verifier; /* response */
};
struct nfs4_create { struct nfs4_create {
u32 cr_ftype; /* request */ u32 cr_ftype; /* request */
union { /* request */ union { /* request */
...@@ -467,22 +461,11 @@ struct nfs4_setclientid { ...@@ -467,22 +461,11 @@ struct nfs4_setclientid {
struct nfs4_client * sc_state; /* response */ struct nfs4_client * sc_state; /* response */
}; };
struct nfs4_write {
u64 wr_offset; /* request */
u32 wr_stable_how; /* request */
u32 wr_len; /* request */
u32 * wr_bytes_written; /* response */
struct nfs_writeverf * wr_verf; /* response */
struct page ** wr_pages; /* zero-copy data */
unsigned int wr_pgbase; /* zero-copy data */
};
struct nfs4_op { struct nfs4_op {
u32 opnum; u32 opnum;
union { union {
struct nfs4_access access; struct nfs4_access access;
struct nfs4_close close; struct nfs4_close close;
struct nfs4_commit commit;
struct nfs4_create create; struct nfs4_create create;
struct nfs4_getattr getattr; struct nfs4_getattr getattr;
struct nfs4_getfh getfh; struct nfs4_getfh getfh;
...@@ -499,7 +482,6 @@ struct nfs4_op { ...@@ -499,7 +482,6 @@ struct nfs4_op {
struct nfs4_setattr setattr; struct nfs4_setattr setattr;
struct nfs4_setclientid setclientid; struct nfs4_setclientid setclientid;
struct nfs4_client * setclientid_confirm; struct nfs4_client * setclientid_confirm;
struct nfs4_write write;
} u; } u;
}; };
...@@ -553,21 +535,11 @@ struct nfs_write_data { ...@@ -553,21 +535,11 @@ struct nfs_write_data {
struct nfs_writeverf verf; struct nfs_writeverf verf;
struct list_head pages; /* Coalesced requests we wish to flush */ struct list_head pages; /* Coalesced requests we wish to flush */
struct page *pagevec[NFS_WRITE_MAXIOV]; struct page *pagevec[NFS_WRITE_MAXIOV];
union {
struct {
struct nfs_writeargs args; /* argument struct */ struct nfs_writeargs args; /* argument struct */
struct nfs_writeres res; /* result struct */ struct nfs_writeres res; /* result struct */
} v3;
#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 arg_count;
u32 arg_stable;
u32 res_count;
} v4;
#endif #endif
} u;
}; };
/* /*
......
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