#include <linux/smp_lock.h>
#include <linux/nfs_mount.h>
-#include "iostat.h"
-#include "internal.h"
-
#define NFSDBG_FACILITY NFSDBG_PROC
+extern struct rpc_procinfo nfs3_procedures[];
+
/* A wrapper to handle the EJUKEBOX error message */
static int
nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
return res;
}
-#define rpc_call_sync(clnt, msg, flags) nfs3_rpc_wrapper(clnt, msg, flags)
+static inline int
+nfs3_rpc_call_wrapper(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, int flags)
+{
+ struct rpc_message msg = {
+ .rpc_proc = &clnt->cl_procinfo[proc],
+ .rpc_argp = argp,
+ .rpc_resp = resp,
+ };
+ return nfs3_rpc_wrapper(clnt, &msg, flags);
+}
+
+#define rpc_call(clnt, proc, argp, resp, flags) \
+ nfs3_rpc_call_wrapper(clnt, proc, argp, resp, flags)
+#define rpc_call_sync(clnt, msg, flags) \
+ nfs3_rpc_wrapper(clnt, msg, flags)
static int
-nfs3_async_handle_jukebox(struct rpc_task *task, struct inode *inode)
+nfs3_async_handle_jukebox(struct rpc_task *task)
{
if (task->tk_status != -EJUKEBOX)
return 0;
- nfs_inc_stats(inode, NFSIOS_DELAY);
task->tk_status = 0;
rpc_restart_call(task);
rpc_delay(task, NFS_JUKEBOX_RETRY_TIME);
do_proc_get_root(struct rpc_clnt *client, struct nfs_fh *fhandle,
struct nfs_fsinfo *info)
{
- struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_FSINFO],
- .rpc_argp = fhandle,
- .rpc_resp = info,
- };
int status;
dprintk("%s: call fsinfo\n", __FUNCTION__);
nfs_fattr_init(info->fattr);
- status = rpc_call_sync(client, &msg, 0);
+ status = rpc_call(client, NFS3PROC_FSINFO, fhandle, info, 0);
dprintk("%s: reply fsinfo: %d\n", __FUNCTION__, status);
if (!(info->fattr->valid & NFS_ATTR_FATTR)) {
- msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR];
- msg.rpc_resp = info->fattr;
- status = rpc_call_sync(client, &msg, 0);
+ status = rpc_call(client, NFS3PROC_GETATTR, fhandle, info->fattr, 0);
dprintk("%s: reply getattr: %d\n", __FUNCTION__, status);
}
return status;
}
/*
- * Bare-bones access to getattr: this is for nfs_get_root/nfs_get_sb
+ * Bare-bones access to getattr: this is for nfs_read_super.
*/
static int
nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
int status;
status = do_proc_get_root(server->client, fhandle, info);
- if (status && server->nfs_client->cl_rpcclient != server->client)
- status = do_proc_get_root(server->nfs_client->cl_rpcclient, fhandle, info);
+ if (status && server->client_sys != server->client)
+ status = do_proc_get_root(server->client_sys, fhandle, info);
return status;
}
nfs3_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_fattr *fattr)
{
- struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR],
- .rpc_argp = fhandle,
- .rpc_resp = fattr,
- };
int status;
dprintk("NFS call getattr\n");
nfs_fattr_init(fattr);
- status = rpc_call_sync(server->client, &msg, 0);
+ status = rpc_call(server->client, NFS3PROC_GETATTR,
+ fhandle, fattr, 0);
dprintk("NFS reply getattr: %d\n", status);
return status;
}
.fh = NFS_FH(inode),
.sattr = sattr,
};
- struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_SETATTR],
- .rpc_argp = &arg,
- .rpc_resp = fattr,
- };
int status;
dprintk("NFS call setattr\n");
nfs_fattr_init(fattr);
- status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+ status = rpc_call(NFS_CLIENT(inode), NFS3PROC_SETATTR, &arg, fattr, 0);
if (status == 0)
nfs_setattr_update_inode(inode, sattr);
dprintk("NFS reply setattr: %d\n", status);
.fh = fhandle,
.fattr = fattr
};
- struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_LOOKUP],
- .rpc_argp = &arg,
- .rpc_resp = &res,
- };
int status;
dprintk("NFS call lookup %s\n", name->name);
nfs_fattr_init(&dir_attr);
nfs_fattr_init(fattr);
- status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
- if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR)) {
- msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR];
- msg.rpc_argp = fhandle;
- msg.rpc_resp = fattr;
- status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
- }
+ status = rpc_call(NFS_CLIENT(dir), NFS3PROC_LOOKUP, &arg, &res, 0);
+ if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR))
+ status = rpc_call(NFS_CLIENT(dir), NFS3PROC_GETATTR,
+ fhandle, fattr, 0);
dprintk("NFS reply lookup: %d\n", status);
if (status >= 0)
status = nfs_refresh_inode(dir, &dir_attr);
.rpc_proc = &nfs3_procedures[NFS3PROC_ACCESS],
.rpc_argp = &arg,
.rpc_resp = &res,
- .rpc_cred = entry->cred,
+ .rpc_cred = entry->cred
};
int mode = entry->mask;
int status;
.pglen = pglen,
.pages = &page
};
- struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_READLINK],
- .rpc_argp = &args,
- .rpc_resp = &fattr,
- };
int status;
dprintk("NFS call readlink\n");
nfs_fattr_init(&fattr);
- status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+ status = rpc_call(NFS_CLIENT(inode), NFS3PROC_READLINK,
+ &args, &fattr, 0);
nfs_refresh_inode(inode, &fattr);
dprintk("NFS reply readlink: %d\n", status);
return status;
.fh = &fhandle,
.fattr = &fattr
};
- struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_CREATE],
- .rpc_argp = &arg,
- .rpc_resp = &res,
- };
mode_t mode = sattr->ia_mode;
int status;
again:
nfs_fattr_init(&dir_attr);
nfs_fattr_init(&fattr);
- status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
- nfs_refresh_inode(dir, &dir_attr);
+ status = rpc_call(NFS_CLIENT(dir), NFS3PROC_CREATE, &arg, &res, 0);
+ nfs_post_op_update_inode(dir, &dir_attr);
/* If the server doesn't support the exclusive creation semantics,
* try again with simple 'guarded' mode. */
struct rpc_message *msg = &task->tk_msg;
struct nfs_fattr *dir_attr;
- if (nfs3_async_handle_jukebox(task, dir->d_inode))
+ if (nfs3_async_handle_jukebox(task))
return 1;
if (msg->rpc_argp) {
dir_attr = (struct nfs_fattr*)msg->rpc_resp;
.fromattr = &old_dir_attr,
.toattr = &new_dir_attr
};
- struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_RENAME],
- .rpc_argp = &arg,
- .rpc_resp = &res,
- };
int status;
dprintk("NFS call rename %s -> %s\n", old_name->name, new_name->name);
nfs_fattr_init(&old_dir_attr);
nfs_fattr_init(&new_dir_attr);
- status = rpc_call_sync(NFS_CLIENT(old_dir), &msg, 0);
+ status = rpc_call(NFS_CLIENT(old_dir), NFS3PROC_RENAME, &arg, &res, 0);
nfs_post_op_update_inode(old_dir, &old_dir_attr);
nfs_post_op_update_inode(new_dir, &new_dir_attr);
dprintk("NFS reply rename: %d\n", status);
.dir_attr = &dir_attr,
.fattr = &fattr
};
- struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_LINK],
- .rpc_argp = &arg,
- .rpc_resp = &res,
- };
int status;
dprintk("NFS call link %s\n", name->name);
nfs_fattr_init(&dir_attr);
nfs_fattr_init(&fattr);
- status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+ status = rpc_call(NFS_CLIENT(inode), NFS3PROC_LINK, &arg, &res, 0);
nfs_post_op_update_inode(dir, &dir_attr);
nfs_post_op_update_inode(inode, &fattr);
dprintk("NFS reply link: %d\n", status);
.fh = fhandle,
.fattr = fattr
};
- struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_SYMLINK],
- .rpc_argp = &arg,
- .rpc_resp = &res,
- };
int status;
if (path->len > NFS3_MAXPATHLEN)
dprintk("NFS call symlink %s -> %s\n", name->name, path->name);
nfs_fattr_init(&dir_attr);
nfs_fattr_init(fattr);
- status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ status = rpc_call(NFS_CLIENT(dir), NFS3PROC_SYMLINK, &arg, &res, 0);
nfs_post_op_update_inode(dir, &dir_attr);
dprintk("NFS reply symlink: %d\n", status);
return status;
.fh = &fhandle,
.fattr = &fattr
};
- struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_MKDIR],
- .rpc_argp = &arg,
- .rpc_resp = &res,
- };
int mode = sattr->ia_mode;
int status;
nfs_fattr_init(&dir_attr);
nfs_fattr_init(&fattr);
- status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKDIR, &arg, &res, 0);
nfs_post_op_update_inode(dir, &dir_attr);
if (status != 0)
goto out;
.name = name->name,
.len = name->len
};
- struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_RMDIR],
- .rpc_argp = &arg,
- .rpc_resp = &dir_attr,
- };
int status;
dprintk("NFS call rmdir %s\n", name->name);
nfs_fattr_init(&dir_attr);
- status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ status = rpc_call(NFS_CLIENT(dir), NFS3PROC_RMDIR, &arg, &dir_attr, 0);
nfs_post_op_update_inode(dir, &dir_attr);
dprintk("NFS reply rmdir: %d\n", status);
return status;
.fh = &fh,
.fattr = &fattr
};
- struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_MKNOD],
- .rpc_argp = &arg,
- .rpc_resp = &res,
- };
mode_t mode = sattr->ia_mode;
int status;
nfs_fattr_init(&dir_attr);
nfs_fattr_init(&fattr);
- status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKNOD, &arg, &res, 0);
nfs_post_op_update_inode(dir, &dir_attr);
if (status != 0)
goto out;
nfs3_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_fsstat *stat)
{
- struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_FSSTAT],
- .rpc_argp = fhandle,
- .rpc_resp = stat,
- };
int status;
dprintk("NFS call fsstat\n");
nfs_fattr_init(stat->fattr);
- status = rpc_call_sync(server->client, &msg, 0);
+ status = rpc_call(server->client, NFS3PROC_FSSTAT, fhandle, stat, 0);
dprintk("NFS reply statfs: %d\n", status);
return status;
}
nfs3_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_fsinfo *info)
{
- struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_FSINFO],
- .rpc_argp = fhandle,
- .rpc_resp = info,
- };
int status;
dprintk("NFS call fsinfo\n");
nfs_fattr_init(info->fattr);
- status = rpc_call_sync(server->nfs_client->cl_rpcclient, &msg, 0);
+ status = rpc_call(server->client_sys, NFS3PROC_FSINFO, fhandle, info, 0);
dprintk("NFS reply fsinfo: %d\n", status);
return status;
}
nfs3_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_pathconf *info)
{
- struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_PATHCONF],
- .rpc_argp = fhandle,
- .rpc_resp = info,
- };
int status;
dprintk("NFS call pathconf\n");
nfs_fattr_init(info->fattr);
- status = rpc_call_sync(server->client, &msg, 0);
+ status = rpc_call(server->client, NFS3PROC_PATHCONF, fhandle, info, 0);
dprintk("NFS reply pathconf: %d\n", status);
return status;
}
-static int nfs3_read_done(struct rpc_task *task, struct nfs_read_data *data)
+extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int);
+
+static void nfs3_read_done(struct rpc_task *task, void *calldata)
{
- if (nfs3_async_handle_jukebox(task, data->inode))
- return -EAGAIN;
+ struct nfs_read_data *data = calldata;
+
+ if (nfs3_async_handle_jukebox(task))
+ return;
/* Call back common NFS readpage processing */
if (task->tk_status >= 0)
nfs_refresh_inode(data->inode, &data->fattr);
- return 0;
+ nfs_readpage_result(task, calldata);
}
-static void nfs3_proc_read_setup(struct nfs_read_data *data)
+static const struct rpc_call_ops nfs3_read_ops = {
+ .rpc_call_done = nfs3_read_done,
+ .rpc_release = nfs_readdata_release,
+};
+
+static void
+nfs3_proc_read_setup(struct nfs_read_data *data)
{
+ struct rpc_task *task = &data->task;
+ struct inode *inode = data->inode;
+ int flags;
struct rpc_message msg = {
.rpc_proc = &nfs3_procedures[NFS3PROC_READ],
.rpc_argp = &data->args,
.rpc_cred = data->cred,
};
- rpc_call_setup(&data->task, &msg, 0);
+ /* N.B. Do we need to test? Never called for swapfile inode */
+ flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
+
+ /* Finalize the task. */
+ rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs3_read_ops, data);
+ rpc_call_setup(task, &msg, 0);
}
-static int nfs3_write_done(struct rpc_task *task, struct nfs_write_data *data)
+static void nfs3_write_done(struct rpc_task *task, void *calldata)
{
- if (nfs3_async_handle_jukebox(task, data->inode))
- return -EAGAIN;
+ struct nfs_write_data *data = calldata;
+
+ if (nfs3_async_handle_jukebox(task))
+ return;
if (task->tk_status >= 0)
nfs_post_op_update_inode(data->inode, data->res.fattr);
- return 0;
+ nfs_writeback_done(task, calldata);
}
-static void nfs3_proc_write_setup(struct nfs_write_data *data, int how)
+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)
{
+ 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_cred = data->cred,
};
- data->args.stable = NFS_UNSTABLE;
if (how & FLUSH_STABLE) {
- data->args.stable = NFS_FILE_SYNC;
- if (NFS_I(data->inode)->ncommit)
- data->args.stable = NFS_DATA_SYNC;
- }
+ 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;
/* Finalize the task. */
- rpc_call_setup(&data->task, &msg, 0);
+ rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs3_write_ops, data);
+ rpc_call_setup(task, &msg, 0);
}
-static int nfs3_commit_done(struct rpc_task *task, struct nfs_write_data *data)
+static void nfs3_commit_done(struct rpc_task *task, void *calldata)
{
- if (nfs3_async_handle_jukebox(task, data->inode))
- return -EAGAIN;
+ struct nfs_write_data *data = calldata;
+
+ if (nfs3_async_handle_jukebox(task))
+ return;
if (task->tk_status >= 0)
nfs_post_op_update_inode(data->inode, data->res.fattr);
- return 0;
+ nfs_commit_done(task, calldata);
}
-static void nfs3_proc_commit_setup(struct nfs_write_data *data, int how)
+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)
{
+ 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_cred = data->cred,
};
- rpc_call_setup(&data->task, &msg, 0);
+ /* 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);
}
static int
return nlmclnt_proc(filp->f_dentry->d_inode, cmd, fl);
}
-const struct nfs_rpc_ops nfs_v3_clientops = {
+struct nfs_rpc_ops nfs_v3_clientops = {
.version = 3, /* protocol version */
.dentry_ops = &nfs_dentry_operations,
.dir_inode_ops = &nfs3_dir_inode_operations,
.pathconf = nfs3_proc_pathconf,
.decode_dirent = nfs3_decode_dirent,
.read_setup = nfs3_proc_read_setup,
- .read_done = nfs3_read_done,
.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,