From: Chuck Lever hi trond, andrew- this patch has several benefits: 1. it changes the NFS read proc to use a single argument rather than six. 2. it allows most of the read request parameters to be initialized once per request, rather than once for every RPC call. 3. it exposes the "offset" field to callers (required for direct I/O). diff -Naurp 21-odirect_cruft/fs/nfs/nfs3proc.c 22-read_offset/fs/nfs/nfs3proc.c fs/nfs/nfs3proc.c | 30 +++++++++--------------------- fs/nfs/nfs4proc.c | 40 +++++++++++++++------------------------- fs/nfs/proc.c | 30 +++++++++--------------------- fs/nfs/read.c | 39 +++++++++++++++++++++++++-------------- include/linux/nfs_xdr.h | 6 ++---- 5 files changed, 60 insertions(+), 85 deletions(-) diff -puN fs/nfs/nfs3proc.c~nfs-O_DIRECT-nfs_read_data fs/nfs/nfs3proc.c --- 25/fs/nfs/nfs3proc.c~nfs-O_DIRECT-nfs_read_data 2003-06-17 16:00:20.000000000 -0700 +++ 25-akpm/fs/nfs/nfs3proc.c 2003-06-17 16:00:20.000000000 -0700 @@ -225,38 +225,26 @@ nfs3_proc_readlink(struct inode *inode, } static int -nfs3_proc_read(struct inode *inode, struct rpc_cred *cred, - struct nfs_fattr *fattr, int flags, - unsigned int base, unsigned int count, struct page *page, - int *eofp) +nfs3_proc_read(struct nfs_read_data *rdata) { - u64 offset = page_offset(page) + base; - struct nfs_readargs arg = { - .fh = NFS_FH(inode), - .offset = offset, - .count = count, - .pgbase = base, - .pages = &page - }; - struct nfs_readres res = { - .fattr = fattr, - .count = count, - }; + int flags = rdata->flags; + struct inode * inode = rdata->inode; + struct nfs_fattr * fattr = rdata->res.fattr; struct rpc_message msg = { .rpc_proc = &nfs3_procedures[NFS3PROC_READ], - .rpc_argp = &arg, - .rpc_resp = &res, - .rpc_cred = cred + .rpc_argp = &rdata->args, + .rpc_resp = &rdata->res, + .rpc_cred = rdata->cred, }; int status; - dprintk("NFS call read %d @ %Ld\n", count, (long long)offset); + dprintk("NFS call read %d @ %Ld\n", rdata->args.count, + (long long) rdata->args.offset); fattr->valid = 0; status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags); if (status >= 0) nfs_refresh_inode(inode, fattr); dprintk("NFS reply read: %d\n", status); - *eofp = res.eof; return status; } diff -puN fs/nfs/nfs4proc.c~nfs-O_DIRECT-nfs_read_data fs/nfs/nfs4proc.c --- 25/fs/nfs/nfs4proc.c~nfs-O_DIRECT-nfs_read_data 2003-06-17 16:00:20.000000000 -0700 +++ 25-akpm/fs/nfs/nfs4proc.c 2003-06-17 16:00:20.000000000 -0700 @@ -1012,45 +1012,36 @@ nfs4_proc_readlink(struct inode *inode, } static int -nfs4_proc_read(struct inode *inode, struct rpc_cred *cred, - struct nfs_fattr *fattr, int flags, - unsigned int base, unsigned int count, - struct page *page, int *eofp) +nfs4_proc_read(struct nfs_read_data *rdata) { + int flags = rdata->flags; + struct inode *inode = rdata->inode; + struct nfs_fattr *fattr = rdata->res.fattr; + nfs4_stateid *stateid = &rdata->args.stateid; struct nfs_server *server = NFS_SERVER(inode); struct nfs4_shareowner *sp; - uint64_t offset = page_offset(page) + base; - struct nfs_readargs arg = { - .fh = NFS_FH(inode), - .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, + .rpc_argp = &rdata->args, + .rpc_resp = &rdata->res, + .rpc_cred = rdata->cred, }; unsigned long timestamp = jiffies; int status; - dprintk("NFS call read %d @ %Ld\n", count, (long long)offset); + dprintk("NFS call read %d @ %Ld\n", rdata->args.count, + (long long) rdata->args.offset); + /* - * Try first to use O_RDONLY, then O_RDWR stateid. - */ + * Try first to use O_RDONLY, then O_RDWR stateid. + */ sp = nfs4_get_inode_share(inode, O_RDONLY); 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; status = rpc_call_sync(server->client, &msg, flags); @@ -1061,7 +1052,6 @@ nfs4_proc_read(struct inode *inode, stru nfs_zap_caches(inode); } dprintk("NFS reply read: %d\n", status); - *eofp = res.eof; return status; } diff -puN fs/nfs/proc.c~nfs-O_DIRECT-nfs_read_data fs/nfs/proc.c --- 25/fs/nfs/proc.c~nfs-O_DIRECT-nfs_read_data 2003-06-17 16:00:20.000000000 -0700 +++ 25-akpm/fs/nfs/proc.c 2003-06-17 16:00:20.000000000 -0700 @@ -149,39 +149,27 @@ nfs_proc_readlink(struct inode *inode, s } static int -nfs_proc_read(struct inode *inode, struct rpc_cred *cred, - struct nfs_fattr *fattr, int flags, - unsigned int base, unsigned int count, struct page *page, - int *eofp) +nfs_proc_read(struct nfs_read_data *rdata) { - u64 offset = page_offset(page) + base; - struct nfs_readargs arg = { - .fh = NFS_FH(inode), - .offset = offset, - .count = count, - .pgbase = base, - .pages = &page - }; - struct nfs_readres res = { - .fattr = fattr, - .count = count - }; + int flags = rdata->flags; + struct inode * inode = rdata->inode; + struct nfs_fattr * fattr = rdata->res.fattr; struct rpc_message msg = { .rpc_proc = &nfs_procedures[NFSPROC_READ], - .rpc_argp = &arg, - .rpc_resp = &res, - .rpc_cred = cred + .rpc_argp = &rdata->args, + .rpc_resp = &rdata->res, + .rpc_cred = rdata->cred, }; int status; - dprintk("NFS call read %d @ %Ld\n", count, (long long)offset); + dprintk("NFS call read %d @ %Ld\n", rdata->args.count, + (long long) rdata->args.offset); fattr->valid = 0; status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags); if (status >= 0) nfs_refresh_inode(inode, fattr); dprintk("NFS reply read: %d\n", status); - *eofp = res.eof; return status; } diff -puN fs/nfs/read.c~nfs-O_DIRECT-nfs_read_data fs/nfs/read.c --- 25/fs/nfs/read.c~nfs-O_DIRECT-nfs_read_data 2003-06-17 16:00:20.000000000 -0700 +++ 25-akpm/fs/nfs/read.c 2003-06-17 16:00:20.000000000 -0700 @@ -69,19 +69,28 @@ void nfs_readdata_release(struct rpc_tas static int nfs_readpage_sync(struct file *file, struct inode *inode, struct page *page) { - struct rpc_cred *cred = NULL; - struct nfs_fattr fattr; - unsigned int offset = 0; unsigned int rsize = NFS_SERVER(inode)->rsize; unsigned int count = PAGE_CACHE_SIZE; int result; - int flags = IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0; - int eof; + struct nfs_read_data rdata = { + .flags = (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0), + .cred = NULL, + .inode = inode, + .args = { + .fh = NFS_FH(inode), + .pages = &page, + .pgbase = 0UL, + .count = rsize, + }, + .res = { + .fattr = &rdata.fattr, + } + }; dprintk("NFS: nfs_readpage_sync(%p)\n", page); if (file) - cred = nfs_file_cred(file); + rdata.cred = nfs_file_cred(file); /* * This works now because the socket layer never tries to DMA @@ -89,17 +98,19 @@ nfs_readpage_sync(struct file *file, str */ do { if (count < rsize) - rsize = count; + rdata.args.count = count; + rdata.res.count = rdata.args.count; + rdata.args.offset = page_offset(page) + rdata.args.pgbase; dprintk("NFS: nfs_proc_read(%s, (%s/%Ld), %Lu, %u)\n", NFS_SERVER(inode)->hostname, inode->i_sb->s_id, (long long)NFS_FILEID(inode), - (unsigned long long)offset, rsize); + (unsigned long long)rdata.args.pgbase, + rdata.args.count); lock_kernel(); - result = NFS_PROTO(inode)->read(inode, cred, &fattr, flags, - offset, rsize, page, &eof); + result = NFS_PROTO(inode)->read(&rdata); unlock_kernel(); /* @@ -111,14 +122,14 @@ nfs_readpage_sync(struct file *file, str result = -EINVAL; goto io_error; } - count -= result; - offset += result; - if (result < rsize) /* NFSv2ism */ + count -= result; + rdata.args.pgbase += result; + if (result < rdata.args.count) /* NFSv2ism */ break; } while (count); if (count) - memclear_highpage_flush(page, offset, count); + memclear_highpage_flush(page, rdata.args.pgbase, count); SetPageUptodate(page); if (PageError(page)) ClearPageError(page); diff -puN include/linux/nfs_xdr.h~nfs-O_DIRECT-nfs_read_data include/linux/nfs_xdr.h --- 25/include/linux/nfs_xdr.h~nfs-O_DIRECT-nfs_read_data 2003-06-17 16:00:20.000000000 -0700 +++ 25-akpm/include/linux/nfs_xdr.h 2003-06-17 16:00:20.000000000 -0700 @@ -591,6 +591,7 @@ struct nfs4_compound { #endif /* CONFIG_NFS_V4 */ struct nfs_read_data { + int flags; struct rpc_task task; struct inode *inode; struct rpc_cred *cred; @@ -634,10 +635,7 @@ struct nfs_rpc_ops { struct nfs_fh *, struct nfs_fattr *); int (*access) (struct inode *, struct rpc_cred *, int); int (*readlink)(struct inode *, struct page *); - int (*read) (struct inode *, struct rpc_cred *, - struct nfs_fattr *, - int, unsigned int, unsigned int, - struct page *, int *eofp); + int (*read) (struct nfs_read_data *); int (*write) (struct inode *, struct rpc_cred *, struct nfs_fattr *, int, unsigned int, unsigned int, _