fs/nfs/nfs3proc.c | 44 ++++++++--------------------- fs/nfs/nfs4proc.c | 48 ++++++++++++-------------------- fs/nfs/proc.c | 50 ++++++++++++--------------------- fs/nfs/write.c | 71 ++++++++++++++++++++++++++---------------------- include/linux/nfs_xdr.h | 6 +--- 5 files changed, 92 insertions(+), 127 deletions(-) diff -puN fs/nfs/nfs3proc.c~23-write_proc fs/nfs/nfs3proc.c --- 25/fs/nfs/nfs3proc.c~23-write_proc 2003-06-20 14:00:46.000000000 -0700 +++ 25-akpm/fs/nfs/nfs3proc.c 2003-06-20 14:00:46.000000000 -0700 @@ -249,45 +249,27 @@ nfs3_proc_read(struct nfs_read_data *rda } 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) -{ - 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, - }; +nfs3_proc_write(struct nfs_write_data *wdata) +{ + 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 -puN fs/nfs/nfs4proc.c~23-write_proc fs/nfs/nfs4proc.c --- 25/fs/nfs/nfs4proc.c~23-write_proc 2003-06-20 14:00:46.000000000 -0700 +++ 25-akpm/fs/nfs/nfs4proc.c 2003-06-20 14:00:46.000000000 -0700 @@ -1056,51 +1056,41 @@ nfs4_proc_read(struct nfs_read_data *rda } 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_shareowner *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_shareowner *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 -puN fs/nfs/proc.c~23-write_proc fs/nfs/proc.c --- 25/fs/nfs/proc.c~23-write_proc 2003-06-20 14:00:46.000000000 -0700 +++ 25-akpm/fs/nfs/proc.c 2003-06-20 14:00:46.000000000 -0700 @@ -178,45 +178,33 @@ nfs_proc_read(struct nfs_read_data *rdat } 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) -{ - 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 - }; +nfs_proc_write(struct nfs_write_data *wdata) +{ + 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); - + /* NFSv2 writes don't return a byte count or write + * verifier, so we make up values here. Note that + * v2 writes are always NFS_FILE_SYNC writes. */ + 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 -puN fs/nfs/write.c~23-write_proc fs/nfs/write.c --- 25/fs/nfs/write.c~23-write_proc 2003-06-20 14:00:46.000000000 -0700 +++ 25-akpm/fs/nfs/write.c 2003-06-20 14:00:46.000000000 -0700 @@ -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 > inode->i_size) - inode->i_size = base; + if (wdata.args.offset > inode->i_size) + inode->i_size = 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 -puN include/linux/nfs_xdr.h~23-write_proc include/linux/nfs_xdr.h --- 25/include/linux/nfs_xdr.h~23-write_proc 2003-06-20 14:00:46.000000000 -0700 +++ 25-akpm/include/linux/nfs_xdr.h 2003-06-20 14:00:46.000000000 -0700 @@ -606,6 +606,7 @@ struct nfs_read_data { }; struct nfs_write_data { + int flags; struct rpc_task task; struct inode *inode; struct rpc_cred *cred; @@ -636,10 +637,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 *, _