From e47c085afb3d16cbc6a4bfb10a3b074bb7c58998 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 23 Mar 2011 08:43:09 -0400 Subject: NFS: Ensure that we update the readdir filp->f_pos correctly If we're doing a search by readdir cookie, we need to ensure that the resulting f_pos is updated. To do so, we need to update the desc->current_index, in the same way that we do in the search by file offset case. Signed-off-by: Trond Myklebust --- fs/nfs/dir.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs/nfs/dir.c') diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 2c3eb33b904..c5c71cb62fb 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -290,7 +290,6 @@ int nfs_readdir_search_for_pos(struct nfs_cache_array *array, nfs_readdir_descri if (diff >= array->size) { if (array->eof_index >= 0) goto out_eof; - desc->current_index += array->size; return -EAGAIN; } @@ -311,6 +310,7 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des for (i = 0; i < array->size; i++) { if (array->array[i].cookie == *desc->dir_cookie) { + desc->file->f_pos = desc->current_index + i; desc->cache_entry_index = i; return 0; } @@ -342,6 +342,7 @@ int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc) if (status == -EAGAIN) { desc->last_cookie = array->last_cookie; + desc->current_index += array->size; desc->page_index++; } nfs_readdir_release_array(desc->page); -- cgit v1.2.3-70-g09d2 From 480c2006ebb44ae03165695db7b3e38c04e0d102 Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Wed, 23 Mar 2011 14:48:29 -0400 Subject: NFS: Create nfs_open_dir_context nfs_opendir() created a context that held much more information than we need for a readdir. This patch introduces a slimmed-down nfs_open_dir_context that contains only the cookie and the cred used for RPC operations. The new context will eventually be used to help detect readdir loops. Signed-off-by: Bryan Schumaker Signed-off-by: Trond Myklebust --- fs/nfs/dir.c | 54 +++++++++++++++++++++++++++++++++++++++++++------- fs/nfs/inode.c | 1 - include/linux/nfs_fs.h | 3 +++ 3 files changed, 50 insertions(+), 8 deletions(-) (limited to 'fs/nfs/dir.c') diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index c5c71cb62fb..cda73814f66 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -44,6 +44,7 @@ /* #define NFS_DEBUG_VERBOSE 1 */ static int nfs_opendir(struct inode *, struct file *); +static int nfs_closedir(struct inode *, struct file *); static int nfs_readdir(struct file *, void *, filldir_t); static struct dentry *nfs_lookup(struct inode *, struct dentry *, struct nameidata *); static int nfs_create(struct inode *, struct dentry *, int, struct nameidata *); @@ -64,7 +65,7 @@ const struct file_operations nfs_dir_operations = { .read = generic_read_dir, .readdir = nfs_readdir, .open = nfs_opendir, - .release = nfs_release, + .release = nfs_closedir, .fsync = nfs_fsync_dir, }; @@ -133,13 +134,33 @@ const struct inode_operations nfs4_dir_inode_operations = { #endif /* CONFIG_NFS_V4 */ +static struct nfs_open_dir_context *alloc_nfs_open_dir_context(struct rpc_cred *cred) +{ + struct nfs_open_dir_context *ctx; + ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); + if (ctx != NULL) { + ctx->dir_cookie = 0; + ctx->cred = get_rpccred(cred); + } else + ctx = ERR_PTR(-ENOMEM); + return ctx; +} + +static void put_nfs_open_dir_context(struct nfs_open_dir_context *ctx) +{ + put_rpccred(ctx->cred); + kfree(ctx); +} + /* * Open file */ static int nfs_opendir(struct inode *inode, struct file *filp) { - int res; + int res = 0; + struct nfs_open_dir_context *ctx; + struct rpc_cred *cred; dfprintk(FILE, "NFS: open dir(%s/%s)\n", filp->f_path.dentry->d_parent->d_name.name, @@ -147,8 +168,15 @@ nfs_opendir(struct inode *inode, struct file *filp) nfs_inc_stats(inode, NFSIOS_VFSOPEN); - /* Call generic open code in order to cache credentials */ - res = nfs_open(inode, filp); + cred = rpc_lookup_cred(); + if (IS_ERR(cred)) + return PTR_ERR(cred); + ctx = alloc_nfs_open_dir_context(cred); + if (IS_ERR(ctx)) { + res = PTR_ERR(ctx); + goto out; + } + filp->private_data = ctx; if (filp->f_path.dentry == filp->f_path.mnt->mnt_root) { /* This is a mountpoint, so d_revalidate will never * have been called, so we need to refresh the @@ -156,9 +184,18 @@ nfs_opendir(struct inode *inode, struct file *filp) */ __nfs_revalidate_inode(NFS_SERVER(inode), inode); } +out: + put_rpccred(cred); return res; } +static int +nfs_closedir(struct inode *inode, struct file *filp) +{ + put_nfs_open_dir_context(filp->private_data); + return 0; +} + struct nfs_cache_array_entry { u64 cookie; u64 ino; @@ -355,7 +392,8 @@ static int nfs_readdir_xdr_filler(struct page **pages, nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, struct file *file, struct inode *inode) { - struct rpc_cred *cred = nfs_file_cred(file); + struct nfs_open_dir_context *ctx = file->private_data; + struct rpc_cred *cred = ctx->cred; unsigned long timestamp, gencount; int error; @@ -786,6 +824,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) struct inode *inode = dentry->d_inode; nfs_readdir_descriptor_t my_desc, *desc = &my_desc; + struct nfs_open_dir_context *dir_ctx = filp->private_data; int res; dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n", @@ -802,7 +841,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) memset(desc, 0, sizeof(*desc)); desc->file = filp; - desc->dir_cookie = &nfs_file_open_context(filp)->dir_cookie; + desc->dir_cookie = &dir_ctx->dir_cookie; desc->decode = NFS_PROTO(inode)->decode_dirent; desc->plus = NFS_USE_READDIRPLUS(inode); @@ -854,6 +893,7 @@ static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin) { struct dentry *dentry = filp->f_path.dentry; struct inode *inode = dentry->d_inode; + struct nfs_open_dir_context *dir_ctx = filp->private_data; dfprintk(FILE, "NFS: llseek dir(%s/%s, %lld, %d)\n", dentry->d_parent->d_name.name, @@ -873,7 +913,7 @@ static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin) } if (offset != filp->f_pos) { filp->f_pos = offset; - nfs_file_open_context(filp)->dir_cookie = 0; + dir_ctx->dir_cookie = 0; } out: mutex_unlock(&inode->i_mutex); diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 2f8e61816d7..477a2e512b3 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -639,7 +639,6 @@ struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct rpc_cr ctx->mode = f_mode; ctx->flags = 0; ctx->error = 0; - ctx->dir_cookie = 0; nfs_init_lock_context(&ctx->lock_context); ctx->lock_context.open_context = ctx; INIT_LIST_HEAD(&ctx->list); diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index cb2add401f2..4b851a02f7f 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -95,7 +95,10 @@ struct nfs_open_context { int error; struct list_head list; +}; +struct nfs_open_dir_context { + struct rpc_cred *cred; __u64 dir_cookie; }; -- cgit v1.2.3-70-g09d2 From 8ef2ce3e16d9bec6cf015207c1c82a5b864046ac Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Wed, 23 Mar 2011 15:04:31 -0400 Subject: NFS: Detect loops in a readdir due to bad cookies Some filesystems (such as ext4) can return the same cookie value for multiple files. If we try to start a readdir with one of these cookies, the server will return the first file found with a cookie of the same value. This can cause the client to enter an infinite loop. Signed-off-by: Bryan Schumaker Signed-off-by: Trond Myklebust --- fs/nfs/dir.c | 28 +++++++++++++++++++++++++++- include/linux/nfs_fs.h | 2 ++ 2 files changed, 29 insertions(+), 1 deletion(-) (limited to 'fs/nfs/dir.c') diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index cda73814f66..db87a7d1109 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -139,7 +139,9 @@ static struct nfs_open_dir_context *alloc_nfs_open_dir_context(struct rpc_cred * struct nfs_open_dir_context *ctx; ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); if (ctx != NULL) { + ctx->duped = 0; ctx->dir_cookie = 0; + ctx->dup_cookie = 0; ctx->cred = get_rpccred(cred); } else ctx = ERR_PTR(-ENOMEM); @@ -321,6 +323,7 @@ int nfs_readdir_search_for_pos(struct nfs_cache_array *array, nfs_readdir_descri { loff_t diff = desc->file->f_pos - desc->current_index; unsigned int index; + struct nfs_open_dir_context *ctx = desc->file->private_data; if (diff < 0) goto out_eof; @@ -333,6 +336,7 @@ int nfs_readdir_search_for_pos(struct nfs_cache_array *array, nfs_readdir_descri index = (unsigned int)diff; *desc->dir_cookie = array->array[index].cookie; desc->cache_entry_index = index; + ctx->duped = 0; return 0; out_eof: desc->eof = 1; @@ -343,11 +347,18 @@ static int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_descriptor_t *desc) { int i; + loff_t new_pos; int status = -EAGAIN; + struct nfs_open_dir_context *ctx = desc->file->private_data; for (i = 0; i < array->size; i++) { if (array->array[i].cookie == *desc->dir_cookie) { - desc->file->f_pos = desc->current_index + i; + new_pos = desc->current_index + i; + if (new_pos < desc->file->f_pos) { + ctx->dup_cookie = *desc->dir_cookie; + ctx->duped = 1; + } + desc->file->f_pos = new_pos; desc->cache_entry_index = i; return 0; } @@ -732,6 +743,20 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent, int i = 0; int res = 0; struct nfs_cache_array *array = NULL; + struct nfs_open_dir_context *ctx = file->private_data; + + if (ctx->duped != 0 && ctx->dup_cookie == *desc->dir_cookie) { + if (printk_ratelimit()) { + pr_notice("NFS: directory %s/%s contains a readdir loop. " + "Please contact your server vendor. " + "Offending cookie: %llu\n", + file->f_dentry->d_parent->d_name.name, + file->f_dentry->d_name.name, + *desc->dir_cookie); + } + res = -ELOOP; + goto out; + } array = nfs_readdir_get_array(desc->page); if (IS_ERR(array)) { @@ -914,6 +939,7 @@ static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin) if (offset != filp->f_pos) { filp->f_pos = offset; dir_ctx->dir_cookie = 0; + dir_ctx->duped = 0; } out: mutex_unlock(&inode->i_mutex); diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 4b851a02f7f..4179c368844 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -100,6 +100,8 @@ struct nfs_open_context { struct nfs_open_dir_context { struct rpc_cred *cred; __u64 dir_cookie; + __u64 dup_cookie; + int duped; }; /* -- cgit v1.2.3-70-g09d2 From 7c5130588d691a3b34d02312f1bd1b6d56fe0100 Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Thu, 24 Mar 2011 17:12:24 +0000 Subject: NFS: lookup supports alternate client A later patch will need to perform a lookup using an alternate client with a different security flavor. This patch adds support for doing that on NFS v4. Signed-off-by: Bryan Schumaker Signed-off-by: Trond Myklebust --- fs/nfs/dir.c | 6 ++-- fs/nfs/internal.h | 6 ++-- fs/nfs/namespace.c | 2 +- fs/nfs/nfs3proc.c | 2 +- fs/nfs/nfs4_fs.h | 3 +- fs/nfs/nfs4proc.c | 86 +++++++++++++++++++++++++++---------------------- fs/nfs/proc.c | 2 +- include/linux/nfs_xdr.h | 2 +- 8 files changed, 60 insertions(+), 49 deletions(-) (limited to 'fs/nfs/dir.c') diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index abdf38d5971..a83cd0d9dfa 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -1068,7 +1068,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd) if (fhandle == NULL || fattr == NULL) goto out_error; - error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); + error = NFS_PROTO(dir)->lookup(NFS_SERVER(dir)->client, dir, &dentry->d_name, fhandle, fattr); if (error) goto out_bad; if (nfs_compare_fh(NFS_FH(inode), fhandle)) @@ -1224,7 +1224,7 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru parent = dentry->d_parent; /* Protect against concurrent sillydeletes */ nfs_block_sillyrename(parent); - error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); + error = NFS_PROTO(dir)->lookup(NFS_SERVER(dir)->client, dir, &dentry->d_name, fhandle, fattr); if (error == -ENOENT) goto no_entry; if (error < 0) { @@ -1562,7 +1562,7 @@ int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle, if (dentry->d_inode) goto out; if (fhandle->size == 0) { - error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); + error = NFS_PROTO(dir)->lookup(NFS_SERVER(dir)->client, dir, &dentry->d_name, fhandle, fattr); if (error) goto out_error; } diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 72e0bddf7a2..1ec5d0662ed 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -296,12 +296,14 @@ extern int nfs4_init_client(struct nfs_client *clp, rpc_authflavor_t authflavour, int noresvport); extern void nfs4_reset_write(struct rpc_task *task, struct nfs_write_data *data); -extern int _nfs4_call_sync(struct nfs_server *server, +extern int _nfs4_call_sync(struct rpc_clnt *clnt, + struct nfs_server *server, struct rpc_message *msg, struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, int cache_reply); -extern int _nfs4_call_sync_session(struct nfs_server *server, +extern int _nfs4_call_sync_session(struct rpc_clnt *clnt, + struct nfs_server *server, struct rpc_message *msg, struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index bf1c68009ff..b02720864de 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c @@ -153,7 +153,7 @@ struct vfsmount *nfs_d_automount(struct path *path) /* Look it up again to get its attributes */ parent = dget_parent(path->dentry); - err = server->nfs_client->rpc_ops->lookup(parent->d_inode, + err = server->nfs_client->rpc_ops->lookup(server->client, parent->d_inode, &path->dentry->d_name, fh, fattr); dput(parent); diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index d0c80d8b3f9..38053d823eb 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -141,7 +141,7 @@ nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, } static int -nfs3_proc_lookup(struct inode *dir, struct qstr *name, +nfs3_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr) { struct nfs3_diropargs arg = { diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index c64be1cff08..72e5f1a2883 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -57,7 +57,8 @@ enum nfs4_session_state { struct nfs4_minor_version_ops { u32 minor_version; - int (*call_sync)(struct nfs_server *server, + int (*call_sync)(struct rpc_clnt *clnt, + struct nfs_server *server, struct rpc_message *msg, struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index e403d7a8446..448657456b6 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -71,7 +71,9 @@ static int _nfs4_proc_open(struct nfs4_opendata *data); static int _nfs4_recover_proc_open(struct nfs4_opendata *data); static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *); -static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr); +static int _nfs4_proc_lookup(struct rpc_clnt *client, struct inode *dir, + const struct qstr *name, struct nfs_fh *fhandle, + struct nfs_fattr *fattr); static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr); static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, struct nfs_fattr *fattr, struct iattr *sattr, @@ -657,7 +659,8 @@ struct rpc_call_ops nfs41_call_priv_sync_ops = { .rpc_call_done = nfs41_call_sync_done, }; -static int nfs4_call_sync_sequence(struct nfs_server *server, +static int nfs4_call_sync_sequence(struct rpc_clnt *clnt, + struct nfs_server *server, struct rpc_message *msg, struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, @@ -673,7 +676,7 @@ static int nfs4_call_sync_sequence(struct nfs_server *server, .cache_reply = cache_reply, }; struct rpc_task_setup task_setup = { - .rpc_client = server->client, + .rpc_client = clnt, .rpc_message = msg, .callback_ops = &nfs41_call_sync_ops, .callback_data = &data @@ -692,13 +695,14 @@ static int nfs4_call_sync_sequence(struct nfs_server *server, return ret; } -int _nfs4_call_sync_session(struct nfs_server *server, +int _nfs4_call_sync_session(struct rpc_clnt *clnt, + struct nfs_server *server, struct rpc_message *msg, struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, int cache_reply) { - return nfs4_call_sync_sequence(server, msg, args, res, cache_reply, 0); + return nfs4_call_sync_sequence(clnt, server, msg, args, res, cache_reply, 0); } #else @@ -709,25 +713,27 @@ static int nfs4_sequence_done(struct rpc_task *task, } #endif /* CONFIG_NFS_V4_1 */ -int _nfs4_call_sync(struct nfs_server *server, +int _nfs4_call_sync(struct rpc_clnt *clnt, + struct nfs_server *server, struct rpc_message *msg, struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, int cache_reply) { args->sa_session = res->sr_session = NULL; - return rpc_call_sync(server->client, msg, 0); + return rpc_call_sync(clnt, msg, 0); } static inline -int nfs4_call_sync(struct nfs_server *server, +int nfs4_call_sync(struct rpc_clnt *clnt, + struct nfs_server *server, struct rpc_message *msg, struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, int cache_reply) { - return server->nfs_client->cl_mvops->call_sync(server, msg, args, - res, cache_reply); + return server->nfs_client->cl_mvops->call_sync(clnt, server, msg, + args, res, cache_reply); } static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) @@ -1838,7 +1844,7 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, } else memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid)); - status = nfs4_call_sync(server, &msg, &arg.seq_args, &res.seq_res, 1); + status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); if (status == 0 && state != NULL) renew_lease(server, timestamp); return status; @@ -2097,7 +2103,7 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f }; int status; - status = nfs4_call_sync(server, &msg, &args.seq_args, &res.seq_res, 0); + status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); if (status == 0) { memcpy(server->attr_bitmask, res.attr_bitmask, sizeof(server->attr_bitmask)); server->caps &= ~(NFS_CAP_ACLS|NFS_CAP_HARDLINKS| @@ -2167,7 +2173,7 @@ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, }; nfs_fattr_init(info->fattr); - return nfs4_call_sync(server, &msg, &args.seq_args, &res.seq_res, 0); + return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); } static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, @@ -2256,7 +2262,7 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, }; nfs_fattr_init(fattr); - return nfs4_call_sync(server, &msg, &args.seq_args, &res.seq_res, 0); + return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); } static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr) @@ -2316,9 +2322,9 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, return status; } -static int _nfs4_proc_lookupfh(struct nfs_server *server, const struct nfs_fh *dirfh, - const struct qstr *name, struct nfs_fh *fhandle, - struct nfs_fattr *fattr) +static int _nfs4_proc_lookupfh(struct rpc_clnt *clnt, struct nfs_server *server, + const struct nfs_fh *dirfh, const struct qstr *name, + struct nfs_fh *fhandle, struct nfs_fattr *fattr) { int status; struct nfs4_lookup_arg args = { @@ -2340,7 +2346,7 @@ static int _nfs4_proc_lookupfh(struct nfs_server *server, const struct nfs_fh *d nfs_fattr_init(fattr); dprintk("NFS call lookupfh %s\n", name->name); - status = nfs4_call_sync(server, &msg, &args.seq_args, &res.seq_res, 0); + status = nfs4_call_sync(clnt, server, &msg, &args.seq_args, &res.seq_res, 0); dprintk("NFS reply lookupfh: %d\n", status); return status; } @@ -2352,7 +2358,7 @@ static int nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh, struct nfs4_exception exception = { }; int err; do { - err = _nfs4_proc_lookupfh(server, dirfh, name, fhandle, fattr); + err = _nfs4_proc_lookupfh(server->client, server, dirfh, name, fhandle, fattr); /* FIXME: !!!! */ if (err == -NFS4ERR_MOVED) { err = -EREMOTE; @@ -2363,26 +2369,28 @@ static int nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh, return err; } -static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, - struct nfs_fh *fhandle, struct nfs_fattr *fattr) +static int _nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, + const struct qstr *name, struct nfs_fh *fhandle, + struct nfs_fattr *fattr) { int status; dprintk("NFS call lookup %s\n", name->name); - status = _nfs4_proc_lookupfh(NFS_SERVER(dir), NFS_FH(dir), name, fhandle, fattr); + status = _nfs4_proc_lookupfh(clnt, NFS_SERVER(dir), NFS_FH(dir), name, fhandle, fattr); if (status == -NFS4ERR_MOVED) status = nfs4_get_referral(dir, name, fattr, fhandle); dprintk("NFS reply lookup: %d\n", status); return status; } -static int nfs4_proc_lookup(struct inode *dir, struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr) +static int nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qstr *name, + struct nfs_fh *fhandle, struct nfs_fattr *fattr) { struct nfs4_exception exception = { }; int err; do { err = nfs4_handle_exception(NFS_SERVER(dir), - _nfs4_proc_lookup(dir, name, fhandle, fattr), + _nfs4_proc_lookup(clnt, dir, name, fhandle, fattr), &exception); } while (exception.retry); return err; @@ -2428,7 +2436,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry if (res.fattr == NULL) return -ENOMEM; - status = nfs4_call_sync(server, &msg, &args.seq_args, &res.seq_res, 0); + status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); if (!status) { entry->mask = 0; if (res.access & NFS4_ACCESS_READ) @@ -2495,7 +2503,7 @@ static int _nfs4_proc_readlink(struct inode *inode, struct page *page, .rpc_resp = &res, }; - return nfs4_call_sync(NFS_SERVER(inode), &msg, &args.seq_args, &res.seq_res, 0); + return nfs4_call_sync(NFS_SERVER(inode)->client, NFS_SERVER(inode), &msg, &args.seq_args, &res.seq_res, 0); } static int nfs4_proc_readlink(struct inode *inode, struct page *page, @@ -2584,7 +2592,7 @@ static int _nfs4_proc_remove(struct inode *dir, struct qstr *name) if (res.dir_attr == NULL) goto out; - status = nfs4_call_sync(server, &msg, &args.seq_args, &res.seq_res, 1); + status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 1); if (status == 0) { update_changeattr(dir, &res.cinfo); nfs_post_op_update_inode(dir, res.dir_attr); @@ -2685,7 +2693,7 @@ static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, if (res.old_fattr == NULL || res.new_fattr == NULL) goto out; - status = nfs4_call_sync(server, &msg, &arg.seq_args, &res.seq_res, 1); + status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); if (!status) { update_changeattr(old_dir, &res.old_cinfo); nfs_post_op_update_inode(old_dir, res.old_fattr); @@ -2736,7 +2744,7 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr * if (res.fattr == NULL || res.dir_attr == NULL) goto out; - status = nfs4_call_sync(server, &msg, &arg.seq_args, &res.seq_res, 1); + status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); if (!status) { update_changeattr(dir, &res.cinfo); nfs_post_op_update_inode(dir, res.dir_attr); @@ -2799,7 +2807,7 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir, static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data) { - int status = nfs4_call_sync(NFS_SERVER(dir), &data->msg, + int status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &data->msg, &data->arg.seq_args, &data->res.seq_res, 1); if (status == 0) { update_changeattr(dir, &data->res.dir_cinfo); @@ -2912,7 +2920,7 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, (unsigned long long)cookie); nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args); res.pgbase = args.pgbase; - status = nfs4_call_sync(NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0); + status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0); if (status >= 0) { memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE); status += args.pgbase; @@ -3004,7 +3012,7 @@ static int _nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, }; nfs_fattr_init(fsstat->fattr); - return nfs4_call_sync(server, &msg, &args.seq_args, &res.seq_res, 0); + return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); } static int nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsstat *fsstat) @@ -3035,7 +3043,7 @@ static int _nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, .rpc_resp = &res, }; - return nfs4_call_sync(server, &msg, &args.seq_args, &res.seq_res, 0); + return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); } static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo) @@ -3080,7 +3088,7 @@ static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle } nfs_fattr_init(pathconf->fattr); - return nfs4_call_sync(server, &msg, &args.seq_args, &res.seq_res, 0); + return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); } static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, @@ -3459,7 +3467,7 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu resp_buf = buf; buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase); } - ret = nfs4_call_sync(NFS_SERVER(inode), &msg, &args.seq_args, &res.seq_res, 0); + ret = nfs4_call_sync(NFS_SERVER(inode)->client, NFS_SERVER(inode), &msg, &args.seq_args, &res.seq_res, 0); if (ret) goto out_free; if (res.acl_len > args.acl_len) @@ -3534,7 +3542,7 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl if (i < 0) return i; nfs_inode_return_delegation(inode); - ret = nfs4_call_sync(server, &msg, &arg.seq_args, &res.seq_res, 1); + ret = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); /* * Free each page after tx, so the only ref left is @@ -3897,7 +3905,7 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock lsp = request->fl_u.nfs4_fl.owner; arg.lock_owner.id = lsp->ls_id.id; arg.lock_owner.s_dev = server->s_dev; - status = nfs4_call_sync(server, &msg, &arg.seq_args, &res.seq_res, 1); + status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); switch (status) { case 0: request->fl_type = F_UNLCK; @@ -4625,7 +4633,7 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, nfs_fattr_init(&fs_locations->fattr); fs_locations->server = server; fs_locations->nlocations = 0; - status = nfs4_call_sync(server, &msg, &args.seq_args, &res.seq_res, 0); + status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); nfs_fixup_referral_attributes(&fs_locations->fattr); dprintk("%s: returned status = %d\n", __func__, status); return status; @@ -5593,7 +5601,7 @@ _nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev) int status; dprintk("--> %s\n", __func__); - status = nfs4_call_sync(server, &msg, &args.seq_args, &res.seq_res, 0); + status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); dprintk("<-- %s status=%d\n", __func__, status); return status; diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index b8ec170f2a0..ac40b8535d7 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c @@ -177,7 +177,7 @@ nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, } static int -nfs_proc_lookup(struct inode *dir, struct qstr *name, +nfs_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr) { struct nfs_diropargs arg = { diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 2c2c67d2eb4..71ee6799db9 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -1071,7 +1071,7 @@ struct nfs_rpc_ops { struct nfs_fattr *); int (*setattr) (struct dentry *, struct nfs_fattr *, struct iattr *); - int (*lookup) (struct inode *, struct qstr *, + int (*lookup) (struct rpc_clnt *clnt, struct inode *, struct qstr *, struct nfs_fh *, struct nfs_fattr *); int (*access) (struct inode *, struct nfs_access_entry *); int (*readlink)(struct inode *, struct page *, unsigned int, -- cgit v1.2.3-70-g09d2