From 3e97d5ee3c57592e19e2a7cef0b05dd0e59b9611 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 7 Oct 2003 08:02:09 -0400 Subject: [PATCH] Simplify NFS synchronous write call interface. Pass a pointer to a filled nfs_write_data struct like we do for asynchronous function calls --- fs/nfs/nfs3proc.c | 42 +++++++----------------- fs/nfs/nfs4proc.c | 48 +++++++++++----------------- fs/nfs/proc.c | 45 +++++++++----------------- fs/nfs/write.c | 71 ++++++++++++++++++++++------------------- include/linux/nfs_xdr.h | 6 ++-- 5 files changed, 87 insertions(+), 125 deletions(-) diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index c3fc1fdfc8720..e3d37fbc8e519 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -249,45 +249,27 @@ nfs3_proc_read(struct nfs_read_data *rdata) } static int -nfs3_proc_write(struct inode *inode, struct rpc_cred *cred, - struct nfs_fattr *fattr, int flags, - unsigned int base, unsigned int count, - struct page *page, struct nfs_writeverf *verf) +nfs3_proc_write(struct nfs_write_data *wdata) { - u64 offset = page_offset(page) + base; - struct nfs_writeargs arg = { - .fh = NFS_FH(inode), - .offset = offset, - .count = count, - .stable = NFS_FILE_SYNC, - .pgbase = base, - .pages = &page - }; - struct nfs_writeres res = { - .fattr = fattr, - .verf = verf, - }; + int rpcflags = wdata->flags; + struct inode * inode = wdata->inode; + struct nfs_fattr * fattr = wdata->res.fattr; struct rpc_message msg = { .rpc_proc = &nfs3_procedures[NFS3PROC_WRITE], - .rpc_argp = &arg, - .rpc_resp = &res, - .rpc_cred = cred + .rpc_argp = &wdata->args, + .rpc_resp = &wdata->res, + .rpc_cred = wdata->cred, }; - int status, rpcflags = 0; + int status; - dprintk("NFS call write %d @ %Ld\n", count, (long long)offset); + dprintk("NFS call write %d @ %Ld\n", wdata->args.count, + (long long) wdata->args.offset); fattr->valid = 0; - if (flags & NFS_RW_SWAP) - rpcflags |= NFS_RPC_SWAPFLAGS; - arg.stable = (flags & NFS_RW_SYNC) ? NFS_FILE_SYNC : NFS_UNSTABLE; - status = rpc_call_sync(NFS_CLIENT(inode), &msg, rpcflags); - if (status >= 0) nfs3_write_refresh_inode(inode, fattr); - - dprintk("NFS reply read: %d\n", status); - return status < 0? status : res.count; + dprintk("NFS reply write: %d\n", status); + return status < 0? status : wdata->res.count; } /* diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 5162a38a74ca6..134bd78f56868 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -1061,51 +1061,41 @@ nfs4_proc_read(struct nfs_read_data *rdata) } static int -nfs4_proc_write(struct inode *inode, struct rpc_cred *cred, - struct nfs_fattr *fattr, int flags, - unsigned int base, unsigned int count, - struct page *page, struct nfs_writeverf *verf) +nfs4_proc_write(struct nfs_write_data *wdata) { + int rpcflags = wdata->flags; + struct inode *inode = wdata->inode; + struct nfs_fattr *fattr = wdata->res.fattr; + nfs4_stateid *stateid = &wdata->args.stateid; struct nfs_server *server = NFS_SERVER(inode); - struct nfs4_state_owner *sp; - uint64_t offset = page_offset(page) + base; - struct nfs_writeargs arg = { - .fh = NFS_FH(inode), - .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 nfs4_state_owner *sp; struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE], - .rpc_argp = &arg, - .rpc_resp = &res, - .rpc_cred = cred, + .rpc_argp = &wdata->args, + .rpc_resp = &wdata->res, + .rpc_cred = wdata->cred, }; - int rpcflags = (flags & NFS_RW_SWAP) ? NFS_RPC_SWAPFLAGS : 0; + int status; - dprintk("NFS call write %d @ %Ld\n", count, (long long)offset); + dprintk("NFS call write %d @ %Ld\n", wdata->args.count, + (long long) wdata->args.offset); /* - * Try first to use O_WRONLY, then O_RDWR stateid. - */ + * Try first to use O_WRONLY, then O_RDWR stateid. + */ sp = nfs4_get_inode_share(inode, O_WRONLY); if (!sp) sp = nfs4_get_inode_share(inode, O_RDWR); if (sp) - memcpy(arg.stateid,sp->so_stateid, sizeof(nfs4_stateid)); + memcpy(stateid, sp->so_stateid, sizeof(nfs4_stateid)); else - memcpy(arg.stateid, zero_stateid, sizeof(nfs4_stateid)); + memcpy(stateid, zero_stateid, sizeof(nfs4_stateid)); fattr->valid = 0; - return rpc_call_sync(server->client, &msg, rpcflags); + status = rpc_call_sync(server->client, &msg, rpcflags); + dprintk("NFS reply write: %d\n", status); + return status; } /* diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index a89a89dde4600..d6791db622cac 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c @@ -174,45 +174,30 @@ nfs_proc_read(struct nfs_read_data *rdata) } static int -nfs_proc_write(struct inode *inode, struct rpc_cred *cred, - struct nfs_fattr *fattr, int how, - unsigned int base, unsigned int count, - struct page *page, struct nfs_writeverf *verf) +nfs_proc_write(struct nfs_write_data *wdata) { - u64 offset = page_offset(page) + base; - struct nfs_writeargs arg = { - .fh = NFS_FH(inode), - .offset = offset, - .count = count, - .stable = NFS_FILE_SYNC, - .pgbase = base, - .pages = &page - }; - struct nfs_writeres res = { - .fattr = fattr, - .verf = verf, - .count = count - }; + int flags = wdata->flags; + struct inode * inode = wdata->inode; + struct nfs_fattr * fattr = wdata->res.fattr; struct rpc_message msg = { .rpc_proc = &nfs_procedures[NFSPROC_WRITE], - .rpc_argp = &arg, - .rpc_resp = &res, - .rpc_cred = cred + .rpc_argp = &wdata->args, + .rpc_resp = &wdata->res, + .rpc_cred = wdata->cred }; - int status, flags = 0; + int status; - dprintk("NFS call write %d @ %Ld\n", count, (long long)offset); + dprintk("NFS call write %d @ %Ld\n", wdata->args.count, + (long long) wdata->args.offset); fattr->valid = 0; - if (how & NFS_RW_SWAP) - flags |= NFS_RPC_SWAPFLAGS; status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags); - - if (status >= 0) + if (status >= 0) { nfs_write_refresh_inode(inode, fattr); - + wdata->res.count = wdata->args.count; + wdata->verf.committed = NFS_FILE_SYNC; + } dprintk("NFS reply write: %d\n", status); - verf->committed = NFS_FILE_SYNC; /* NFSv2 always syncs data */ - return status < 0? status : count; + return status < 0? status : wdata->res.count; } static int diff --git a/fs/nfs/write.c b/fs/nfs/write.c index da33af16fbe08..52aec4862ec8d 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -132,66 +132,73 @@ static int nfs_writepage_sync(struct file *file, struct inode *inode, struct page *page, unsigned int offset, unsigned int count) { - struct rpc_cred *cred = NULL; - loff_t base; unsigned int wsize = NFS_SERVER(inode)->wsize; - int result, refresh = 0, written = 0, flags; - u8 *buffer; - struct nfs_fattr fattr; - struct nfs_writeverf verf; - + int result, written = 0; + int swapfile = IS_SWAPFILE(inode); + struct nfs_write_data wdata = { + .flags = swapfile ? NFS_RPC_SWAPFLAGS : 0, + .cred = NULL, + .inode = inode, + .args = { + .fh = NFS_FH(inode), + .pages = &page, + .stable = NFS_FILE_SYNC, + .pgbase = offset, + .count = wsize, + }, + .res = { + .fattr = &wdata.fattr, + .verf = &wdata.verf, + }, + }; if (file) - cred = get_rpccred(nfs_file_cred(file)); - if (!cred) - cred = get_rpccred(NFS_I(inode)->mm_cred); + wdata.cred = get_rpccred(nfs_file_cred(file)); + if (!wdata.cred) + wdata.cred = get_rpccred(NFS_I(inode)->mm_cred); dprintk("NFS: nfs_writepage_sync(%s/%Ld %d@%Ld)\n", inode->i_sb->s_id, (long long)NFS_FILEID(inode), count, (long long)(page_offset(page) + offset)); - base = page_offset(page) + offset; - - flags = ((IS_SWAPFILE(inode)) ? NFS_RW_SWAP : 0) | NFS_RW_SYNC; - do { - if (count < wsize && !IS_SWAPFILE(inode)) - wsize = count; + if (count < wsize && !swapfile) + wdata.args.count = count; + wdata.args.offset = page_offset(page) + wdata.args.pgbase; - result = NFS_PROTO(inode)->write(inode, cred, &fattr, flags, - offset, wsize, page, &verf); + result = NFS_PROTO(inode)->write(&wdata); if (result < 0) { /* Must mark the page invalid after I/O error */ ClearPageUptodate(page); goto io_error; } - if (result != wsize) - printk("NFS: short write, wsize=%u, result=%d\n", - wsize, result); - refresh = 1; - buffer += wsize; - base += wsize; - offset += wsize; - written += wsize; - count -= wsize; + if (result < wdata.args.count) + printk(KERN_WARNING "NFS: short write, count=%u, result=%d\n", + wdata.args.count, result); + + wdata.args.offset += result; + wdata.args.pgbase += result; + written += result; + count -= result; + /* * If we've extended the file, update the inode * now so we don't invalidate the cache. */ - if (base > i_size_read(inode)) - i_size_write(inode, base); + if (wdata.args.offset > i_size_read(inode)) + i_size_write(inode, wdata.args.offset); } while (count); if (PageError(page)) ClearPageError(page); io_error: - if (cred) - put_rpccred(cred); + if (wdata.cred) + put_rpccred(wdata.cred); - return written? written : result; + return written ? written : result; } static int diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index fe5ede12b9e3b..bf8fe562d073e 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -605,6 +605,7 @@ struct nfs_read_data { }; struct nfs_write_data { + int flags; struct rpc_task task; struct inode *inode; struct rpc_cred *cred; @@ -635,10 +636,7 @@ struct nfs_rpc_ops { int (*access) (struct inode *, struct rpc_cred *, int); int (*readlink)(struct inode *, struct page *); int (*read) (struct nfs_read_data *); - int (*write) (struct inode *, struct rpc_cred *, - struct nfs_fattr *, - int, unsigned int, unsigned int, - struct page *, struct nfs_writeverf *verfp); + int (*write) (struct nfs_write_data *); int (*commit) (struct inode *, struct nfs_fattr *, unsigned long, unsigned int); int (*create) (struct inode *, struct qstr *, struct iattr *, -- 2.53.0