Skip to content

Commit

Permalink
NFS: Cleanup of NFS write code in preparation for asynchronous o_direct
Browse files Browse the repository at this point in the history
This patch inverts the callback hierarchy for NFS write calls.

Instead of having the NFSv2/v3/v4-specific code set up the RPC callback
ops, we allow the original caller to do so. This allows for more
flexibility w.r.t. how to set up and tear down the nfs_write_data
structure while still allowing the NFSv3/v4 code to perform error
handling.

The greater flexibility is needed by the asynchronous O_DIRECT code, which
wants to be able to hold on to the original nfs_write_data structures after
the WRITE RPC call has completed in order to be able to replay them if the
COMMIT call determines that the server has rebooted.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
  • Loading branch information
Trond Myklebust authored and Trond Myklebust committed Mar 20, 2006
1 parent 7117bf3 commit 788e7a8
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 143 deletions.
66 changes: 17 additions & 49 deletions fs/nfs/nfs3proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -849,88 +849,54 @@ nfs3_proc_read_setup(struct nfs_read_data *data)
rpc_call_setup(task, &msg, 0);
}

static void nfs3_write_done(struct rpc_task *task, void *calldata)
static int nfs3_write_done(struct rpc_task *task, struct nfs_write_data *data)
{
struct nfs_write_data *data = calldata;

if (nfs3_async_handle_jukebox(task, data->inode))
return;
return -EAGAIN;
if (task->tk_status >= 0)
nfs_post_op_update_inode(data->inode, data->res.fattr);
nfs_writeback_done(task, calldata);
return 0;
}

static const struct rpc_call_ops nfs3_write_ops = {
.rpc_call_done = nfs3_write_done,
.rpc_release = nfs_writedata_release,
};

static void
nfs3_proc_write_setup(struct nfs_write_data *data, int how)
static void nfs3_proc_write_setup(struct nfs_write_data *data, int how)
{
struct rpc_task *task = &data->task;
struct inode *inode = data->inode;
int stable;
int flags;
struct rpc_message msg = {
.rpc_proc = &nfs3_procedures[NFS3PROC_WRITE],
.rpc_argp = &data->args,
.rpc_resp = &data->res,
.rpc_cred = data->cred,
};

data->args.stable = NFS_UNSTABLE;
if (how & FLUSH_STABLE) {
if (!NFS_I(inode)->ncommit)
stable = NFS_FILE_SYNC;
else
stable = NFS_DATA_SYNC;
} else
stable = NFS_UNSTABLE;
data->args.stable = stable;

/* Set the initial flags for the task. */
flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
data->args.stable = NFS_FILE_SYNC;
if (NFS_I(data->inode)->ncommit)
data->args.stable = NFS_DATA_SYNC;
}

/* Finalize the task. */
rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs3_write_ops, data);
rpc_call_setup(task, &msg, 0);
rpc_call_setup(&data->task, &msg, 0);
}

static void nfs3_commit_done(struct rpc_task *task, void *calldata)
static int nfs3_commit_done(struct rpc_task *task, struct nfs_write_data *data)
{
struct nfs_write_data *data = calldata;

if (nfs3_async_handle_jukebox(task, data->inode))
return;
return -EAGAIN;
if (task->tk_status >= 0)
nfs_post_op_update_inode(data->inode, data->res.fattr);
nfs_commit_done(task, calldata);
return 0;
}

static const struct rpc_call_ops nfs3_commit_ops = {
.rpc_call_done = nfs3_commit_done,
.rpc_release = nfs_commit_release,
};

static void
nfs3_proc_commit_setup(struct nfs_write_data *data, int how)
static void nfs3_proc_commit_setup(struct nfs_write_data *data, int how)
{
struct rpc_task *task = &data->task;
struct inode *inode = data->inode;
int flags;
struct rpc_message msg = {
.rpc_proc = &nfs3_procedures[NFS3PROC_COMMIT],
.rpc_argp = &data->args,
.rpc_resp = &data->res,
.rpc_cred = data->cred,
};

/* Set the initial flags for the task. */
flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;

/* Finalize the task. */
rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs3_commit_ops, data);
rpc_call_setup(task, &msg, 0);
rpc_call_setup(&data->task, &msg, 0);
}

static int
Expand Down Expand Up @@ -970,7 +936,9 @@ struct nfs_rpc_ops nfs_v3_clientops = {
.decode_dirent = nfs3_decode_dirent,
.read_setup = nfs3_proc_read_setup,
.write_setup = nfs3_proc_write_setup,
.write_done = nfs3_write_done,
.commit_setup = nfs3_proc_commit_setup,
.commit_done = nfs3_commit_done,
.file_open = nfs_open,
.file_release = nfs_release,
.lock = nfs3_proc_lock,
Expand Down
54 changes: 13 additions & 41 deletions fs/nfs/nfs4proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2388,32 +2388,23 @@ nfs4_proc_read_setup(struct nfs_read_data *data)
rpc_call_setup(task, &msg, 0);
}

static void nfs4_write_done(struct rpc_task *task, void *calldata)
static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data)
{
struct nfs_write_data *data = calldata;
struct inode *inode = data->inode;

if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) {
rpc_restart_call(task);
return;
return -EAGAIN;
}
if (task->tk_status >= 0) {
renew_lease(NFS_SERVER(inode), data->timestamp);
nfs_post_op_update_inode(inode, data->res.fattr);
}
/* Call back common NFS writeback processing */
nfs_writeback_done(task, calldata);
return 0;
}

static const struct rpc_call_ops nfs4_write_ops = {
.rpc_call_done = nfs4_write_done,
.rpc_release = nfs_writedata_release,
};

static void
nfs4_proc_write_setup(struct nfs_write_data *data, int how)
static void nfs4_proc_write_setup(struct nfs_write_data *data, int how)
{
struct rpc_task *task = &data->task;
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE],
.rpc_argp = &data->args,
Expand All @@ -2423,7 +2414,6 @@ nfs4_proc_write_setup(struct nfs_write_data *data, int how)
struct inode *inode = data->inode;
struct nfs_server *server = NFS_SERVER(inode);
int stable;
int flags;

if (how & FLUSH_STABLE) {
if (!NFS_I(inode)->ncommit)
Expand All @@ -2438,57 +2428,37 @@ nfs4_proc_write_setup(struct nfs_write_data *data, int how)

data->timestamp = jiffies;

/* Set the initial flags for the task. */
flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;

/* Finalize the task. */
rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs4_write_ops, data);
rpc_call_setup(task, &msg, 0);
rpc_call_setup(&data->task, &msg, 0);
}

static void nfs4_commit_done(struct rpc_task *task, void *calldata)
static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data)
{
struct nfs_write_data *data = calldata;
struct inode *inode = data->inode;

if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) {
rpc_restart_call(task);
return;
return -EAGAIN;
}
if (task->tk_status >= 0)
nfs_post_op_update_inode(inode, data->res.fattr);
/* Call back common NFS writeback processing */
nfs_commit_done(task, calldata);
return 0;
}

static const struct rpc_call_ops nfs4_commit_ops = {
.rpc_call_done = nfs4_commit_done,
.rpc_release = nfs_commit_release,
};

static void
nfs4_proc_commit_setup(struct nfs_write_data *data, int how)
static void nfs4_proc_commit_setup(struct nfs_write_data *data, int how)
{
struct rpc_task *task = &data->task;
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT],
.rpc_argp = &data->args,
.rpc_resp = &data->res,
.rpc_cred = data->cred,
};
struct inode *inode = data->inode;
struct nfs_server *server = NFS_SERVER(inode);
int flags;
struct nfs_server *server = NFS_SERVER(data->inode);

data->args.bitmask = server->attr_bitmask;
data->res.server = server;

/* Set the initial flags for the task. */
flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;

/* Finalize the task. */
rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs4_commit_ops, data);
rpc_call_setup(task, &msg, 0);
rpc_call_setup(&data->task, &msg, 0);
}

/*
Expand Down Expand Up @@ -3648,7 +3618,9 @@ struct nfs_rpc_ops nfs_v4_clientops = {
.decode_dirent = nfs4_decode_dirent,
.read_setup = nfs4_proc_read_setup,
.write_setup = nfs4_proc_write_setup,
.write_done = nfs4_write_done,
.commit_setup = nfs4_proc_commit_setup,
.commit_done = nfs4_commit_done,
.file_open = nfs_open,
.file_release = nfs_release,
.lock = nfs4_proc_lock,
Expand Down
24 changes: 5 additions & 19 deletions fs/nfs/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -654,26 +654,15 @@ nfs_proc_read_setup(struct nfs_read_data *data)
rpc_call_setup(task, &msg, 0);
}

static void nfs_write_done(struct rpc_task *task, void *calldata)
static int nfs_write_done(struct rpc_task *task, struct nfs_write_data *data)
{
struct nfs_write_data *data = calldata;

if (task->tk_status >= 0)
nfs_post_op_update_inode(data->inode, data->res.fattr);
nfs_writeback_done(task, calldata);
return 0;
}

static const struct rpc_call_ops nfs_write_ops = {
.rpc_call_done = nfs_write_done,
.rpc_release = nfs_writedata_release,
};

static void
nfs_proc_write_setup(struct nfs_write_data *data, int how)
static void nfs_proc_write_setup(struct nfs_write_data *data, int how)
{
struct rpc_task *task = &data->task;
struct inode *inode = data->inode;
int flags;
struct rpc_message msg = {
.rpc_proc = &nfs_procedures[NFSPROC_WRITE],
.rpc_argp = &data->args,
Expand All @@ -684,12 +673,8 @@ nfs_proc_write_setup(struct nfs_write_data *data, int how)
/* Note: NFSv2 ignores @stable and always uses NFS_FILE_SYNC */
data->args.stable = NFS_FILE_SYNC;

/* Set the initial flags for the task. */
flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;

/* Finalize the task. */
rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs_write_ops, data);
rpc_call_setup(task, &msg, 0);
rpc_call_setup(&data->task, &msg, 0);
}

static void
Expand Down Expand Up @@ -736,6 +721,7 @@ struct nfs_rpc_ops nfs_v2_clientops = {
.decode_dirent = nfs_decode_dirent,
.read_setup = nfs_proc_read_setup,
.write_setup = nfs_proc_write_setup,
.write_done = nfs_write_done,
.commit_setup = nfs_proc_commit_setup,
.file_open = nfs_open,
.file_release = nfs_release,
Expand Down
Loading

0 comments on commit 788e7a8

Please sign in to comment.