Commit 3e97d5ee authored by Trond Myklebust's avatar Trond Myklebust

Simplify NFS synchronous write call interface. Pass

a pointer to a filled nfs_write_data struct like we
do for asynchronous function calls
parent 0b6cfeaa
...@@ -249,45 +249,27 @@ nfs3_proc_read(struct nfs_read_data *rdata) ...@@ -249,45 +249,27 @@ nfs3_proc_read(struct nfs_read_data *rdata)
} }
static int static int
nfs3_proc_write(struct inode *inode, struct rpc_cred *cred, nfs3_proc_write(struct nfs_write_data *wdata)
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; int rpcflags = wdata->flags;
struct nfs_writeargs arg = { struct inode * inode = wdata->inode;
.fh = NFS_FH(inode), struct nfs_fattr * fattr = wdata->res.fattr;
.offset = offset,
.count = count,
.stable = NFS_FILE_SYNC,
.pgbase = base,
.pages = &page
};
struct nfs_writeres res = {
.fattr = fattr,
.verf = verf,
};
struct rpc_message msg = { struct rpc_message msg = {
.rpc_proc = &nfs3_procedures[NFS3PROC_WRITE], .rpc_proc = &nfs3_procedures[NFS3PROC_WRITE],
.rpc_argp = &arg, .rpc_argp = &wdata->args,
.rpc_resp = &res, .rpc_resp = &wdata->res,
.rpc_cred = cred .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; 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); status = rpc_call_sync(NFS_CLIENT(inode), &msg, rpcflags);
if (status >= 0) if (status >= 0)
nfs3_write_refresh_inode(inode, fattr); nfs3_write_refresh_inode(inode, fattr);
dprintk("NFS reply write: %d\n", status);
dprintk("NFS reply read: %d\n", status); return status < 0? status : wdata->res.count;
return status < 0? status : res.count;
} }
/* /*
......
...@@ -1061,51 +1061,41 @@ nfs4_proc_read(struct nfs_read_data *rdata) ...@@ -1061,51 +1061,41 @@ nfs4_proc_read(struct nfs_read_data *rdata)
} }
static int static int
nfs4_proc_write(struct inode *inode, struct rpc_cred *cred, nfs4_proc_write(struct nfs_write_data *wdata)
struct nfs_fattr *fattr, int flags,
unsigned int base, unsigned int count,
struct page *page, struct nfs_writeverf *verf)
{ {
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 nfs_server *server = NFS_SERVER(inode);
struct nfs4_state_owner *sp; 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 rpc_message msg = { struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE], .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE],
.rpc_argp = &arg, .rpc_argp = &wdata->args,
.rpc_resp = &res, .rpc_resp = &wdata->res,
.rpc_cred = cred, .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); sp = nfs4_get_inode_share(inode, O_WRONLY);
if (!sp) if (!sp)
sp = nfs4_get_inode_share(inode, O_RDWR); sp = nfs4_get_inode_share(inode, O_RDWR);
if (sp) if (sp)
memcpy(arg.stateid,sp->so_stateid, sizeof(nfs4_stateid)); memcpy(stateid, sp->so_stateid, sizeof(nfs4_stateid));
else else
memcpy(arg.stateid, zero_stateid, sizeof(nfs4_stateid)); memcpy(stateid, zero_stateid, sizeof(nfs4_stateid));
fattr->valid = 0; 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;
} }
/* /*
......
...@@ -174,45 +174,30 @@ nfs_proc_read(struct nfs_read_data *rdata) ...@@ -174,45 +174,30 @@ nfs_proc_read(struct nfs_read_data *rdata)
} }
static int static int
nfs_proc_write(struct inode *inode, struct rpc_cred *cred, nfs_proc_write(struct nfs_write_data *wdata)
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; int flags = wdata->flags;
struct nfs_writeargs arg = { struct inode * inode = wdata->inode;
.fh = NFS_FH(inode), struct nfs_fattr * fattr = wdata->res.fattr;
.offset = offset,
.count = count,
.stable = NFS_FILE_SYNC,
.pgbase = base,
.pages = &page
};
struct nfs_writeres res = {
.fattr = fattr,
.verf = verf,
.count = count
};
struct rpc_message msg = { struct rpc_message msg = {
.rpc_proc = &nfs_procedures[NFSPROC_WRITE], .rpc_proc = &nfs_procedures[NFSPROC_WRITE],
.rpc_argp = &arg, .rpc_argp = &wdata->args,
.rpc_resp = &res, .rpc_resp = &wdata->res,
.rpc_cred = cred .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; fattr->valid = 0;
if (how & NFS_RW_SWAP)
flags |= NFS_RPC_SWAPFLAGS;
status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags); status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
if (status >= 0) {
if (status >= 0)
nfs_write_refresh_inode(inode, fattr); 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); dprintk("NFS reply write: %d\n", status);
verf->committed = NFS_FILE_SYNC; /* NFSv2 always syncs data */ return status < 0? status : wdata->res.count;
return status < 0? status : count;
} }
static int static int
......
...@@ -132,66 +132,73 @@ static int ...@@ -132,66 +132,73 @@ static int
nfs_writepage_sync(struct file *file, struct inode *inode, struct page *page, nfs_writepage_sync(struct file *file, struct inode *inode, struct page *page,
unsigned int offset, unsigned int count) unsigned int offset, unsigned int count)
{ {
struct rpc_cred *cred = NULL;
loff_t base;
unsigned int wsize = NFS_SERVER(inode)->wsize; unsigned int wsize = NFS_SERVER(inode)->wsize;
int result, refresh = 0, written = 0, flags; int result, written = 0;
u8 *buffer; int swapfile = IS_SWAPFILE(inode);
struct nfs_fattr fattr; struct nfs_write_data wdata = {
struct nfs_writeverf verf; .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) if (file)
cred = get_rpccred(nfs_file_cred(file)); wdata.cred = get_rpccred(nfs_file_cred(file));
if (!cred) if (!wdata.cred)
cred = get_rpccred(NFS_I(inode)->mm_cred); wdata.cred = get_rpccred(NFS_I(inode)->mm_cred);
dprintk("NFS: nfs_writepage_sync(%s/%Ld %d@%Ld)\n", dprintk("NFS: nfs_writepage_sync(%s/%Ld %d@%Ld)\n",
inode->i_sb->s_id, inode->i_sb->s_id,
(long long)NFS_FILEID(inode), (long long)NFS_FILEID(inode),
count, (long long)(page_offset(page) + offset)); count, (long long)(page_offset(page) + offset));
base = page_offset(page) + offset;
flags = ((IS_SWAPFILE(inode)) ? NFS_RW_SWAP : 0) | NFS_RW_SYNC;
do { do {
if (count < wsize && !IS_SWAPFILE(inode)) if (count < wsize && !swapfile)
wsize = count; wdata.args.count = count;
wdata.args.offset = page_offset(page) + wdata.args.pgbase;
result = NFS_PROTO(inode)->write(inode, cred, &fattr, flags, result = NFS_PROTO(inode)->write(&wdata);
offset, wsize, page, &verf);
if (result < 0) { if (result < 0) {
/* Must mark the page invalid after I/O error */ /* Must mark the page invalid after I/O error */
ClearPageUptodate(page); ClearPageUptodate(page);
goto io_error; goto io_error;
} }
if (result != wsize) if (result < wdata.args.count)
printk("NFS: short write, wsize=%u, result=%d\n", printk(KERN_WARNING "NFS: short write, count=%u, result=%d\n",
wsize, result); wdata.args.count, result);
refresh = 1;
buffer += wsize; wdata.args.offset += result;
base += wsize; wdata.args.pgbase += result;
offset += wsize; written += result;
written += wsize; count -= result;
count -= wsize;
/* /*
* If we've extended the file, update the inode * If we've extended the file, update the inode
* now so we don't invalidate the cache. * now so we don't invalidate the cache.
*/ */
if (base > i_size_read(inode)) if (wdata.args.offset > i_size_read(inode))
i_size_write(inode, base); i_size_write(inode, wdata.args.offset);
} while (count); } while (count);
if (PageError(page)) if (PageError(page))
ClearPageError(page); ClearPageError(page);
io_error: io_error:
if (cred) if (wdata.cred)
put_rpccred(cred); put_rpccred(wdata.cred);
return written? written : result; return written ? written : result;
} }
static int static int
......
...@@ -605,6 +605,7 @@ struct nfs_read_data { ...@@ -605,6 +605,7 @@ struct nfs_read_data {
}; };
struct nfs_write_data { struct nfs_write_data {
int flags;
struct rpc_task task; struct rpc_task task;
struct inode *inode; struct inode *inode;
struct rpc_cred *cred; struct rpc_cred *cred;
...@@ -635,10 +636,7 @@ struct nfs_rpc_ops { ...@@ -635,10 +636,7 @@ struct nfs_rpc_ops {
int (*access) (struct inode *, struct rpc_cred *, int); int (*access) (struct inode *, struct rpc_cred *, int);
int (*readlink)(struct inode *, struct page *); int (*readlink)(struct inode *, struct page *);
int (*read) (struct nfs_read_data *); int (*read) (struct nfs_read_data *);
int (*write) (struct inode *, struct rpc_cred *, int (*write) (struct nfs_write_data *);
struct nfs_fattr *,
int, unsigned int, unsigned int,
struct page *, struct nfs_writeverf *verfp);
int (*commit) (struct inode *, struct nfs_fattr *, int (*commit) (struct inode *, struct nfs_fattr *,
unsigned long, unsigned int); unsigned long, unsigned int);
int (*create) (struct inode *, struct qstr *, struct iattr *, int (*create) (struct inode *, struct qstr *, struct iattr *,
......
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