Commit b1355604 authored by Trond Myklebust's avatar Trond Myklebust

NFSv2/v3/v4: Add support for asynchronous writes even if wsize<PAGE_CACHE_SIZE.

parent 7e19d190
...@@ -259,6 +259,7 @@ nfs_direct_write_seg(struct inode *inode, struct file *file, ...@@ -259,6 +259,7 @@ nfs_direct_write_seg(struct inode *inode, struct file *file,
.inode = inode, .inode = inode,
.args = { .args = {
.fh = NFS_FH(inode), .fh = NFS_FH(inode),
.lockowner = current->files,
}, },
.res = { .res = {
.fattr = &wdata.fattr, .fattr = &wdata.fattr,
......
...@@ -763,11 +763,10 @@ nfs3_write_done(struct rpc_task *task) ...@@ -763,11 +763,10 @@ nfs3_write_done(struct rpc_task *task)
} }
static void static void
nfs3_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how) nfs3_proc_write_setup(struct nfs_write_data *data, int how)
{ {
struct rpc_task *task = &data->task; struct rpc_task *task = &data->task;
struct inode *inode = data->inode; struct inode *inode = data->inode;
struct nfs_page *req;
int stable; int stable;
int flags; int flags;
struct rpc_message msg = { struct rpc_message msg = {
...@@ -784,28 +783,14 @@ nfs3_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how) ...@@ -784,28 +783,14 @@ nfs3_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how)
stable = NFS_DATA_SYNC; stable = NFS_DATA_SYNC;
} else } else
stable = NFS_UNSTABLE; stable = NFS_UNSTABLE;
req = nfs_list_entry(data->pages.next);
data->args.fh = NFS_FH(inode);
data->args.offset = req_offset(req);
data->args.pgbase = req->wb_pgbase;
data->args.count = count;
data->args.stable = stable; data->args.stable = stable;
data->args.pages = data->pagevec;
data->res.fattr = &data->fattr;
data->res.count = count;
data->res.verf = &data->verf;
/* Set the initial flags for the task. */ /* Set the initial flags for the task. */
flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
/* Finalize the task. */ /* Finalize the task. */
rpc_init_task(task, NFS_CLIENT(inode), nfs3_write_done, flags); rpc_init_task(task, NFS_CLIENT(inode), nfs3_write_done, flags);
task->tk_calldata = data; rpc_call_setup(task, &msg, 0);
/* Release requests */
task->tk_release = nfs_writedata_release;
rpc_call_setup(&data->task, &msg, 0);
} }
static void static void
...@@ -822,7 +807,7 @@ nfs3_commit_done(struct rpc_task *task) ...@@ -822,7 +807,7 @@ nfs3_commit_done(struct rpc_task *task)
} }
static void static void
nfs3_proc_commit_setup(struct nfs_write_data *data, u64 start, u32 len, int how) nfs3_proc_commit_setup(struct nfs_write_data *data, int how)
{ {
struct rpc_task *task = &data->task; struct rpc_task *task = &data->task;
struct inode *inode = data->inode; struct inode *inode = data->inode;
...@@ -834,23 +819,12 @@ nfs3_proc_commit_setup(struct nfs_write_data *data, u64 start, u32 len, int how) ...@@ -834,23 +819,12 @@ nfs3_proc_commit_setup(struct nfs_write_data *data, u64 start, u32 len, int how)
.rpc_cred = data->cred, .rpc_cred = data->cred,
}; };
data->args.fh = NFS_FH(data->inode);
data->args.offset = start;
data->args.count = len;
data->res.count = len;
data->res.fattr = &data->fattr;
data->res.verf = &data->verf;
/* Set the initial flags for the task. */ /* Set the initial flags for the task. */
flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
/* Finalize the task. */ /* Finalize the task. */
rpc_init_task(task, NFS_CLIENT(inode), nfs3_commit_done, flags); rpc_init_task(task, NFS_CLIENT(inode), nfs3_commit_done, flags);
task->tk_calldata = data; rpc_call_setup(task, &msg, 0);
/* Release requests */
task->tk_release = nfs_commit_release;
rpc_call_setup(&data->task, &msg, 0);
} }
/* /*
......
...@@ -1134,10 +1134,10 @@ nfs4_proc_write(struct nfs_write_data *wdata, struct file *filp) ...@@ -1134,10 +1134,10 @@ nfs4_proc_write(struct nfs_write_data *wdata, struct file *filp)
if (filp) { if (filp) {
struct nfs4_state *state; struct nfs4_state *state;
state = (struct nfs4_state *)filp->private_data; state = (struct nfs4_state *)filp->private_data;
nfs4_copy_stateid(&wdata->args.stateid, state, wdata->lockowner); wdata->args.state = state;
msg.rpc_cred = state->owner->so_cred; msg.rpc_cred = state->owner->so_cred;
} else { } else {
memcpy(&wdata->args.stateid, &zero_stateid, sizeof(wdata->args.stateid)); wdata->args.state = NULL;
msg.rpc_cred = NFS_I(inode)->mm_cred; msg.rpc_cred = NFS_I(inode)->mm_cred;
} }
...@@ -1166,15 +1166,10 @@ nfs4_proc_commit(struct nfs_write_data *cdata, struct file *filp) ...@@ -1166,15 +1166,10 @@ nfs4_proc_commit(struct nfs_write_data *cdata, struct file *filp)
/* /*
* Try first to use O_WRONLY, then O_RDWR stateid. * Try first to use O_WRONLY, then O_RDWR stateid.
*/ */
if (filp) { if (filp)
struct nfs4_state *state; msg.rpc_cred = ((struct nfs4_state *)filp->private_data)->owner->so_cred;
state = (struct nfs4_state *)filp->private_data; else
nfs4_copy_stateid(&cdata->args.stateid, state, cdata->lockowner);
msg.rpc_cred = state->owner->so_cred;
} else {
memcpy(&cdata->args.stateid, &zero_stateid, sizeof(cdata->args.stateid));
msg.rpc_cred = NFS_I(inode)->mm_cred; msg.rpc_cred = NFS_I(inode)->mm_cred;
}
fattr->valid = 0; fattr->valid = 0;
status = rpc_call_sync(server->client, &msg, 0); status = rpc_call_sync(server->client, &msg, 0);
...@@ -1548,20 +1543,6 @@ nfs4_proc_read_setup(struct nfs_read_data *data) ...@@ -1548,20 +1543,6 @@ nfs4_proc_read_setup(struct nfs_read_data *data)
rpc_call_setup(task, &msg, 0); rpc_call_setup(task, &msg, 0);
} }
static void
nfs4_restart_write(struct rpc_task *task)
{
struct nfs_write_data *data = (struct nfs_write_data *)task->tk_calldata;
struct nfs_page *req;
rpc_restart_call(task);
req = nfs_list_entry(data->pages.next);
if (req->wb_state)
nfs4_copy_stateid(&data->args.stateid, req->wb_state, req->wb_lockowner);
else
memcpy(&data->args.stateid, &zero_stateid, sizeof(data->args.stateid));
}
static void static void
nfs4_write_done(struct rpc_task *task) nfs4_write_done(struct rpc_task *task)
{ {
...@@ -1569,7 +1550,7 @@ nfs4_write_done(struct rpc_task *task) ...@@ -1569,7 +1550,7 @@ nfs4_write_done(struct rpc_task *task)
struct inode *inode = data->inode; struct inode *inode = data->inode;
if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) { if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) {
task->tk_action = nfs4_restart_write; rpc_restart_call(task);
return; return;
} }
if (task->tk_status >= 0) if (task->tk_status >= 0)
...@@ -1579,7 +1560,7 @@ nfs4_write_done(struct rpc_task *task) ...@@ -1579,7 +1560,7 @@ nfs4_write_done(struct rpc_task *task)
} }
static void static void
nfs4_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how) nfs4_proc_write_setup(struct nfs_write_data *data, int how)
{ {
struct rpc_task *task = &data->task; struct rpc_task *task = &data->task;
struct rpc_message msg = { struct rpc_message msg = {
...@@ -1589,7 +1570,6 @@ nfs4_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how) ...@@ -1589,7 +1570,6 @@ nfs4_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how)
.rpc_cred = data->cred, .rpc_cred = data->cred,
}; };
struct inode *inode = data->inode; struct inode *inode = data->inode;
struct nfs_page *req = nfs_list_entry(data->pages.next);
int stable; int stable;
int flags; int flags;
...@@ -1600,33 +1580,15 @@ nfs4_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how) ...@@ -1600,33 +1580,15 @@ nfs4_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how)
stable = NFS_DATA_SYNC; stable = NFS_DATA_SYNC;
} else } else
stable = NFS_UNSTABLE; stable = NFS_UNSTABLE;
data->args.fh = NFS_FH(inode);
data->args.offset = req_offset(req);
data->args.pgbase = req->wb_pgbase;
data->args.count = count;
data->args.stable = stable; data->args.stable = stable;
data->args.pages = data->pagevec;
data->res.fattr = &data->fattr;
data->res.count = count;
data->res.verf = &data->verf;
data->timestamp = jiffies;
data->lockowner = req->wb_lockowner; data->timestamp = jiffies;
if (req->wb_state)
nfs4_copy_stateid(&data->args.stateid, req->wb_state, req->wb_lockowner);
else
memcpy(&data->args.stateid, &zero_stateid, sizeof(data->args.stateid));
/* Set the initial flags for the task. */ /* Set the initial flags for the task. */
flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
/* Finalize the task. */ /* Finalize the task. */
rpc_init_task(task, NFS_CLIENT(inode), nfs4_write_done, flags); rpc_init_task(task, NFS_CLIENT(inode), nfs4_write_done, flags);
task->tk_calldata = data;
/* Release requests */
task->tk_release = nfs_writedata_release;
rpc_call_setup(task, &msg, 0); rpc_call_setup(task, &msg, 0);
} }
...@@ -1637,7 +1599,7 @@ nfs4_commit_done(struct rpc_task *task) ...@@ -1637,7 +1599,7 @@ nfs4_commit_done(struct rpc_task *task)
struct inode *inode = data->inode; struct inode *inode = data->inode;
if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) { if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) {
task->tk_action = nfs4_restart_write; rpc_restart_call(task);
return; return;
} }
/* Call back common NFS writeback processing */ /* Call back common NFS writeback processing */
...@@ -1645,7 +1607,7 @@ nfs4_commit_done(struct rpc_task *task) ...@@ -1645,7 +1607,7 @@ nfs4_commit_done(struct rpc_task *task)
} }
static void static void
nfs4_proc_commit_setup(struct nfs_write_data *data, u64 start, u32 len, int how) nfs4_proc_commit_setup(struct nfs_write_data *data, int how)
{ {
struct rpc_task *task = &data->task; struct rpc_task *task = &data->task;
struct rpc_message msg = { struct rpc_message msg = {
...@@ -1657,22 +1619,11 @@ nfs4_proc_commit_setup(struct nfs_write_data *data, u64 start, u32 len, int how) ...@@ -1657,22 +1619,11 @@ nfs4_proc_commit_setup(struct nfs_write_data *data, u64 start, u32 len, int how)
struct inode *inode = data->inode; struct inode *inode = data->inode;
int flags; int flags;
data->args.fh = NFS_FH(data->inode);
data->args.offset = start;
data->args.count = len;
data->res.count = len;
data->res.fattr = &data->fattr;
data->res.verf = &data->verf;
/* Set the initial flags for the task. */ /* Set the initial flags for the task. */
flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
/* Finalize the task. */ /* Finalize the task. */
rpc_init_task(task, NFS_CLIENT(inode), nfs4_commit_done, flags); rpc_init_task(task, NFS_CLIENT(inode), nfs4_commit_done, flags);
task->tk_calldata = data;
/* Release requests */
task->tk_release = nfs_commit_release;
rpc_call_setup(task, &msg, 0); rpc_call_setup(task, &msg, 0);
} }
......
...@@ -1075,9 +1075,12 @@ encode_write(struct xdr_stream *xdr, struct nfs_writeargs *args) ...@@ -1075,9 +1075,12 @@ encode_write(struct xdr_stream *xdr, struct nfs_writeargs *args)
{ {
uint32_t *p; uint32_t *p;
RESERVE_SPACE(36); RESERVE_SPACE(4);
WRITE32(OP_WRITE); WRITE32(OP_WRITE);
WRITEMEM(args->stateid.data, sizeof(args->stateid.data));
encode_stateid(xdr, args->state, args->lockowner);
RESERVE_SPACE(16);
WRITE64(args->offset); WRITE64(args->offset);
WRITE32(args->stable); WRITE32(args->stable);
WRITE32(args->count); WRITE32(args->count);
......
...@@ -590,11 +590,10 @@ nfs_write_done(struct rpc_task *task) ...@@ -590,11 +590,10 @@ nfs_write_done(struct rpc_task *task)
} }
static void static void
nfs_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how) nfs_proc_write_setup(struct nfs_write_data *data, int how)
{ {
struct rpc_task *task = &data->task; struct rpc_task *task = &data->task;
struct inode *inode = data->inode; struct inode *inode = data->inode;
struct nfs_page *req;
int flags; int flags;
struct rpc_message msg = { struct rpc_message msg = {
.rpc_proc = &nfs_procedures[NFSPROC_WRITE], .rpc_proc = &nfs_procedures[NFSPROC_WRITE],
...@@ -604,32 +603,18 @@ nfs_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how) ...@@ -604,32 +603,18 @@ nfs_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how)
}; };
/* Note: NFSv2 ignores @stable and always uses NFS_FILE_SYNC */ /* Note: NFSv2 ignores @stable and always uses NFS_FILE_SYNC */
req = nfs_list_entry(data->pages.next);
data->args.fh = NFS_FH(inode);
data->args.offset = req_offset(req);
data->args.pgbase = req->wb_pgbase;
data->args.count = count;
data->args.stable = NFS_FILE_SYNC; data->args.stable = NFS_FILE_SYNC;
data->args.pages = data->pagevec;
data->res.fattr = &data->fattr;
data->res.count = count;
data->res.verf = &data->verf;
/* Set the initial flags for the task. */ /* Set the initial flags for the task. */
flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
/* Finalize the task. */ /* Finalize the task. */
rpc_init_task(task, NFS_CLIENT(inode), nfs_write_done, flags); rpc_init_task(task, NFS_CLIENT(inode), nfs_write_done, flags);
task->tk_calldata = data; rpc_call_setup(task, &msg, 0);
/* Release requests */
task->tk_release = nfs_writedata_release;
rpc_call_setup(&data->task, &msg, 0);
} }
static void static void
nfs_proc_commit_setup(struct nfs_write_data *data, u64 start, u32 len, int how) nfs_proc_commit_setup(struct nfs_write_data *data, int how)
{ {
BUG(); BUG();
} }
......
This diff is collapsed.
...@@ -335,10 +335,8 @@ extern int nfs_writepages(struct address_space *, struct writeback_control *); ...@@ -335,10 +335,8 @@ extern int nfs_writepages(struct address_space *, struct writeback_control *);
extern int nfs_flush_incompatible(struct file *file, struct page *page); extern int nfs_flush_incompatible(struct file *file, struct page *page);
extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int); extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int);
extern void nfs_writeback_done(struct rpc_task *task); extern void nfs_writeback_done(struct rpc_task *task);
extern void nfs_writedata_release(struct rpc_task *task);
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
extern void nfs_commit_release(struct rpc_task *task);
extern void nfs_commit_done(struct rpc_task *); extern void nfs_commit_done(struct rpc_task *);
#endif #endif
......
...@@ -253,7 +253,8 @@ struct nfs_readres { ...@@ -253,7 +253,8 @@ struct nfs_readres {
struct nfs_writeargs { struct nfs_writeargs {
struct nfs_fh * fh; struct nfs_fh * fh;
nfs4_stateid stateid; fl_owner_t lockowner;
struct nfs4_state * state;
__u64 offset; __u64 offset;
__u32 count; __u32 count;
enum nfs3_stable_how stable; enum nfs3_stable_how stable;
...@@ -681,7 +682,6 @@ struct nfs_write_data { ...@@ -681,7 +682,6 @@ struct nfs_write_data {
struct rpc_task task; struct rpc_task task;
struct inode *inode; struct inode *inode;
struct rpc_cred *cred; struct rpc_cred *cred;
fl_owner_t lockowner;
struct nfs_fattr fattr; struct nfs_fattr fattr;
struct nfs_writeverf verf; struct nfs_writeverf verf;
struct list_head pages; /* Coalesced requests we wish to flush */ struct list_head pages; /* Coalesced requests we wish to flush */
...@@ -742,8 +742,8 @@ struct nfs_rpc_ops { ...@@ -742,8 +742,8 @@ struct nfs_rpc_ops {
struct nfs_pathconf *); struct nfs_pathconf *);
u32 * (*decode_dirent)(u32 *, struct nfs_entry *, int plus); u32 * (*decode_dirent)(u32 *, struct nfs_entry *, int plus);
void (*read_setup) (struct nfs_read_data *); void (*read_setup) (struct nfs_read_data *);
void (*write_setup) (struct nfs_write_data *, unsigned int count, int how); void (*write_setup) (struct nfs_write_data *, int how);
void (*commit_setup) (struct nfs_write_data *, u64 start, u32 len, int how); void (*commit_setup) (struct nfs_write_data *, int how);
int (*file_open) (struct inode *, struct file *); int (*file_open) (struct inode *, struct file *);
int (*file_release) (struct inode *, struct file *); int (*file_release) (struct inode *, struct file *);
void (*request_init)(struct nfs_page *, struct file *); void (*request_init)(struct nfs_page *, struct file *);
......
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