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)
}
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;
}
/*
......
......@@ -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;
}
/*
......
......@@ -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
......
......@@ -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
......
......@@ -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 *,
......
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