diff options
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/Kconfig | 17 | ||||
-rw-r--r-- | fs/nfs/blocklayout/blocklayout.h | 1 | ||||
-rw-r--r-- | fs/nfs/blocklayout/extents.c | 2 | ||||
-rw-r--r-- | fs/nfs/callback.c | 3 | ||||
-rw-r--r-- | fs/nfs/client.c | 10 | ||||
-rw-r--r-- | fs/nfs/dir.c | 129 | ||||
-rw-r--r-- | fs/nfs/direct.c | 17 | ||||
-rw-r--r-- | fs/nfs/dns_resolve.c | 2 | ||||
-rw-r--r-- | fs/nfs/file.c | 117 | ||||
-rw-r--r-- | fs/nfs/fscache.c | 202 | ||||
-rw-r--r-- | fs/nfs/fscache.h | 18 | ||||
-rw-r--r-- | fs/nfs/inode.c | 18 | ||||
-rw-r--r-- | fs/nfs/internal.h | 23 | ||||
-rw-r--r-- | fs/nfs/namespace.c | 5 | ||||
-rw-r--r-- | fs/nfs/nfs3proc.c | 8 | ||||
-rw-r--r-- | fs/nfs/nfs4_fs.h | 25 | ||||
-rw-r--r-- | fs/nfs/nfs4client.c | 138 | ||||
-rw-r--r-- | fs/nfs/nfs4file.c | 6 | ||||
-rw-r--r-- | fs/nfs/nfs4namespace.c | 125 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 503 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 273 | ||||
-rw-r--r-- | fs/nfs/nfs4super.c | 12 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 138 | ||||
-rw-r--r-- | fs/nfs/proc.c | 8 | ||||
-rw-r--r-- | fs/nfs/super.c | 200 | ||||
-rw-r--r-- | fs/nfs/unlink.c | 12 | ||||
-rw-r--r-- | fs/nfs/write.c | 6 |
27 files changed, 569 insertions, 1449 deletions
diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig index 3dece03..b5e80b0 100644 --- a/fs/nfs/Kconfig +++ b/fs/nfs/Kconfig @@ -116,17 +116,17 @@ config NFS_V4_2 config PNFS_FILE_LAYOUT tristate depends on NFS_V4_1 - default NFS_V4 + default m config PNFS_BLOCK tristate depends on NFS_V4_1 && BLK_DEV_DM - default NFS_V4 + default m config PNFS_OBJLAYOUT tristate depends on NFS_V4_1 && SCSI_OSD_ULD - default NFS_V4 + default m config NFS_V4_1_IMPLEMENTATION_ID_DOMAIN string "NFSv4.1 Implementation ID Domain" @@ -140,17 +140,6 @@ config NFS_V4_1_IMPLEMENTATION_ID_DOMAIN If the NFS client is unchanged from the upstream kernel, this option should be set to the default "kernel.org". -config NFS_V4_1_MIGRATION - bool "NFSv4.1 client support for migration" - depends on NFS_V4_1 - default n - help - This option makes the NFS client advertise to NFSv4.1 servers that - it can support NFSv4 migration. - - The NFSv4.1 pieces of the Linux NFSv4 migration implementation are - still experimental. If you are not an NFSv4 developer, say N here. - config NFS_V4_SECURITY_LABEL bool depends on NFS_V4_2 && SECURITY diff --git a/fs/nfs/blocklayout/blocklayout.h b/fs/nfs/blocklayout/blocklayout.h index 9838fb0..8485978 100644 --- a/fs/nfs/blocklayout/blocklayout.h +++ b/fs/nfs/blocklayout/blocklayout.h @@ -36,7 +36,6 @@ #include <linux/nfs_fs.h> #include <linux/sunrpc/rpc_pipe_fs.h> -#include "../nfs4_fs.h" #include "../pnfs.h" #include "../netns.h" diff --git a/fs/nfs/blocklayout/extents.c b/fs/nfs/blocklayout/extents.c index 4d01614..9c3e117 100644 --- a/fs/nfs/blocklayout/extents.c +++ b/fs/nfs/blocklayout/extents.c @@ -44,7 +44,7 @@ static inline sector_t normalize(sector_t s, int base) { sector_t tmp = s; /* Since do_div modifies its argument */ - return s - sector_div(tmp, base); + return s - do_div(tmp, base); } static inline sector_t normalize_up(sector_t s, int base) diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index 073b4cf..67cd732 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c @@ -164,7 +164,8 @@ nfs41_callback_up(struct svc_serv *serv) svc_xprt_put(serv->sv_bc_xprt); serv->sv_bc_xprt = NULL; } - dprintk("--> %s return %d\n", __func__, PTR_ERR_OR_ZERO(rqstp)); + dprintk("--> %s return %ld\n", __func__, + IS_ERR(rqstp) ? PTR_ERR(rqstp) : 0); return rqstp; } diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 1d09289..2dceee4 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -590,8 +590,6 @@ int nfs_create_rpc_client(struct nfs_client *clp, if (test_bit(NFS_CS_DISCRTRY, &clp->cl_flags)) args.flags |= RPC_CLNT_CREATE_DISCRTRY; - if (test_bit(NFS_CS_NO_RETRANS_TIMEOUT, &clp->cl_flags)) - args.flags |= RPC_CLNT_CREATE_NO_RETRANS_TIMEOUT; if (test_bit(NFS_CS_NORESVPORT, &clp->cl_flags)) args.flags |= RPC_CLNT_CREATE_NONPRIVPORT; if (test_bit(NFS_CS_INFINITE_SLOTS, &clp->cl_flags)) @@ -786,10 +784,8 @@ static int nfs_init_server(struct nfs_server *server, goto error; server->port = data->nfs_server.port; - server->auth_info = data->auth_info; - error = nfs_init_server_rpcclient(server, &timeparms, - data->selected_flavor); + error = nfs_init_server_rpcclient(server, &timeparms, data->auth_flavors[0]); if (error < 0) goto error; @@ -930,7 +926,6 @@ void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *sour target->acdirmax = source->acdirmax; target->caps = source->caps; target->options = source->options; - target->auth_info = source->auth_info; } EXPORT_SYMBOL_GPL(nfs_server_copy_userdata); @@ -948,7 +943,7 @@ void nfs_server_insert_lists(struct nfs_server *server) } EXPORT_SYMBOL_GPL(nfs_server_insert_lists); -void nfs_server_remove_lists(struct nfs_server *server) +static void nfs_server_remove_lists(struct nfs_server *server) { struct nfs_client *clp = server->nfs_client; struct nfs_net *nn; @@ -965,7 +960,6 @@ void nfs_server_remove_lists(struct nfs_server *server) synchronize_rcu(); } -EXPORT_SYMBOL_GPL(nfs_server_remove_lists); /* * Allocate and initialise a server record diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 812154a..02b0df7 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -98,7 +98,9 @@ nfs_opendir(struct inode *inode, struct file *filp) struct nfs_open_dir_context *ctx; struct rpc_cred *cred; - dfprintk(FILE, "NFS: open dir(%pD2)\n", filp); + dfprintk(FILE, "NFS: open dir(%s/%s)\n", + filp->f_path.dentry->d_parent->d_name.name, + filp->f_path.dentry->d_name.name); nfs_inc_stats(inode, NFSIOS_VFSOPEN); @@ -295,10 +297,11 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des if (ctx->duped > 0 && ctx->dup_cookie == *desc->dir_cookie) { if (printk_ratelimit()) { - pr_notice("NFS: directory %pD2 contains a readdir loop." + pr_notice("NFS: directory %s/%s contains a readdir loop." "Please contact your server vendor. " "The file: %s has duplicate cookie %llu\n", - desc->file, + desc->file->f_dentry->d_parent->d_name.name, + desc->file->f_dentry->d_name.name, array->array[i].string.name, *desc->dir_cookie); } @@ -819,8 +822,9 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) struct nfs_open_dir_context *dir_ctx = file->private_data; int res = 0; - dfprintk(FILE, "NFS: readdir(%pD2) starting at cookie %llu\n", - file, (long long)ctx->pos); + dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n", + dentry->d_parent->d_name.name, dentry->d_name.name, + (long long)ctx->pos); nfs_inc_stats(inode, NFSIOS_VFSGETDENTS); /* @@ -876,17 +880,22 @@ out: nfs_unblock_sillyrename(dentry); if (res > 0) res = 0; - dfprintk(FILE, "NFS: readdir(%pD2) returns %d\n", file, res); + dfprintk(FILE, "NFS: readdir(%s/%s) returns %d\n", + dentry->d_parent->d_name.name, dentry->d_name.name, + res); return res; } static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int whence) { - struct inode *inode = file_inode(filp); + 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(%pD2, %lld, %d)\n", - filp, offset, whence); + dfprintk(FILE, "NFS: llseek dir(%s/%s, %lld, %d)\n", + dentry->d_parent->d_name.name, + dentry->d_name.name, + offset, whence); mutex_lock(&inode->i_mutex); switch (whence) { @@ -916,12 +925,15 @@ out: static int nfs_fsync_dir(struct file *filp, loff_t start, loff_t end, int datasync) { - struct inode *inode = file_inode(filp); + struct dentry *dentry = filp->f_path.dentry; + struct inode *inode = dentry->d_inode; - dfprintk(FILE, "NFS: fsync dir(%pD2) datasync %d\n", filp, datasync); + dfprintk(FILE, "NFS: fsync dir(%s/%s) datasync %d\n", + dentry->d_parent->d_name.name, dentry->d_name.name, + datasync); mutex_lock(&inode->i_mutex); - nfs_inc_stats(inode, NFSIOS_VFSFSYNC); + nfs_inc_stats(dentry->d_inode, NFSIOS_VFSFSYNC); mutex_unlock(&inode->i_mutex); return 0; } @@ -1061,8 +1073,9 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags) } if (is_bad_inode(inode)) { - dfprintk(LOOKUPCACHE, "%s: %pd2 has dud inode\n", - __func__, dentry); + dfprintk(LOOKUPCACHE, "%s: %s/%s has dud inode\n", + __func__, dentry->d_parent->d_name.name, + dentry->d_name.name); goto out_bad; } @@ -1112,8 +1125,9 @@ out_set_verifier: nfs_advise_use_readdirplus(dir); out_valid_noent: dput(parent); - dfprintk(LOOKUPCACHE, "NFS: %s(%pd2) is valid\n", - __func__, dentry); + dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) is valid\n", + __func__, dentry->d_parent->d_name.name, + dentry->d_name.name); return 1; out_zap_parent: nfs_zap_caches(dir); @@ -1125,13 +1139,7 @@ out_zap_parent: if (inode && S_ISDIR(inode->i_mode)) { /* Purge readdir caches. */ nfs_zap_caches(inode); - /* - * We can't d_drop the root of a disconnected tree: - * its d_hash is on the s_anon list and d_drop() would hide - * it from shrink_dcache_for_unmount(), leading to busy - * inodes on unmount and further oopses. - */ - if (IS_ROOT(dentry)) + if (dentry->d_flags & DCACHE_DISCONNECTED) goto out_valid; } /* If we have submounts, don't unhash ! */ @@ -1139,16 +1147,18 @@ out_zap_parent: goto out_valid; dput(parent); - dfprintk(LOOKUPCACHE, "NFS: %s(%pd2) is invalid\n", - __func__, dentry); + dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) is invalid\n", + __func__, dentry->d_parent->d_name.name, + dentry->d_name.name); return 0; out_error: nfs_free_fattr(fattr); nfs_free_fhandle(fhandle); nfs4_label_free(label); dput(parent); - dfprintk(LOOKUPCACHE, "NFS: %s(%pd2) lookup returned error %d\n", - __func__, dentry, error); + dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) lookup returned error %d\n", + __func__, dentry->d_parent->d_name.name, + dentry->d_name.name, error); return error; } @@ -1172,14 +1182,16 @@ static int nfs_weak_revalidate(struct dentry *dentry, unsigned int flags) * eventually need to do something more here. */ if (!inode) { - dfprintk(LOOKUPCACHE, "%s: %pd2 has negative inode\n", - __func__, dentry); + dfprintk(LOOKUPCACHE, "%s: %s/%s has negative inode\n", + __func__, dentry->d_parent->d_name.name, + dentry->d_name.name); return 1; } if (is_bad_inode(inode)) { - dfprintk(LOOKUPCACHE, "%s: %pd2 has dud inode\n", - __func__, dentry); + dfprintk(LOOKUPCACHE, "%s: %s/%s has dud inode\n", + __func__, dentry->d_parent->d_name.name, + dentry->d_name.name); return 0; } @@ -1194,8 +1206,9 @@ static int nfs_weak_revalidate(struct dentry *dentry, unsigned int flags) */ static int nfs_dentry_delete(const struct dentry *dentry) { - dfprintk(VFS, "NFS: dentry_delete(%pd2, %x)\n", - dentry, dentry->d_flags); + dfprintk(VFS, "NFS: dentry_delete(%s/%s, %x)\n", + dentry->d_parent->d_name.name, dentry->d_name.name, + dentry->d_flags); /* Unhash any dentry with a stale inode */ if (dentry->d_inode != NULL && NFS_STALE(dentry->d_inode)) @@ -1273,7 +1286,8 @@ struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned in struct nfs4_label *label = NULL; int error; - dfprintk(VFS, "NFS: lookup(%pd2)\n", dentry); + dfprintk(VFS, "NFS: lookup(%s/%s)\n", + dentry->d_parent->d_name.name, dentry->d_name.name); nfs_inc_stats(dir, NFSIOS_VFSLOOKUP); res = ERR_PTR(-ENAMETOOLONG); @@ -1367,7 +1381,7 @@ static struct nfs_open_context *create_nfs_open_context(struct dentry *dentry, i static int do_open(struct inode *inode, struct file *filp) { - nfs_fscache_open_file(inode, filp); + nfs_fscache_set_inode_cookie(inode, filp); return 0; } @@ -1404,8 +1418,8 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, /* Expect a negative dentry */ BUG_ON(dentry->d_inode); - dfprintk(VFS, "NFS: atomic_open(%s/%ld), %pd\n", - dir->i_sb->s_id, dir->i_ino, dentry); + dfprintk(VFS, "NFS: atomic_open(%s/%ld), %s\n", + dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); err = nfs_check_flags(open_flags); if (err) @@ -1594,8 +1608,8 @@ int nfs_create(struct inode *dir, struct dentry *dentry, int open_flags = excl ? O_CREAT | O_EXCL : O_CREAT; int error; - dfprintk(VFS, "NFS: create(%s/%ld), %pd\n", - dir->i_sb->s_id, dir->i_ino, dentry); + dfprintk(VFS, "NFS: create(%s/%ld), %s\n", + dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); attr.ia_mode = mode; attr.ia_valid = ATTR_MODE; @@ -1621,8 +1635,8 @@ nfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev) struct iattr attr; int status; - dfprintk(VFS, "NFS: mknod(%s/%ld), %pd\n", - dir->i_sb->s_id, dir->i_ino, dentry); + dfprintk(VFS, "NFS: mknod(%s/%ld), %s\n", + dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); if (!new_valid_dev(rdev)) return -EINVAL; @@ -1650,8 +1664,8 @@ int nfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) struct iattr attr; int error; - dfprintk(VFS, "NFS: mkdir(%s/%ld), %pd\n", - dir->i_sb->s_id, dir->i_ino, dentry); + dfprintk(VFS, "NFS: mkdir(%s/%ld), %s\n", + dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); attr.ia_valid = ATTR_MODE; attr.ia_mode = mode | S_IFDIR; @@ -1678,8 +1692,8 @@ int nfs_rmdir(struct inode *dir, struct dentry *dentry) { int error; - dfprintk(VFS, "NFS: rmdir(%s/%ld), %pd\n", - dir->i_sb->s_id, dir->i_ino, dentry); + dfprintk(VFS, "NFS: rmdir(%s/%ld), %s\n", + dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); trace_nfs_rmdir_enter(dir, dentry); if (dentry->d_inode) { @@ -1714,7 +1728,8 @@ static int nfs_safe_remove(struct dentry *dentry) struct inode *inode = dentry->d_inode; int error = -EBUSY; - dfprintk(VFS, "NFS: safe_remove(%pd2)\n", dentry); + dfprintk(VFS, "NFS: safe_remove(%s/%s)\n", + dentry->d_parent->d_name.name, dentry->d_name.name); /* If the dentry was sillyrenamed, we simply call d_delete() */ if (dentry->d_flags & DCACHE_NFSFS_RENAMED) { @@ -1747,8 +1762,8 @@ int nfs_unlink(struct inode *dir, struct dentry *dentry) int error; int need_rehash = 0; - dfprintk(VFS, "NFS: unlink(%s/%ld, %pd)\n", dir->i_sb->s_id, - dir->i_ino, dentry); + dfprintk(VFS, "NFS: unlink(%s/%ld, %s)\n", dir->i_sb->s_id, + dir->i_ino, dentry->d_name.name); trace_nfs_unlink_enter(dir, dentry); spin_lock(&dentry->d_lock); @@ -1798,8 +1813,8 @@ int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) unsigned int pathlen = strlen(symname); int error; - dfprintk(VFS, "NFS: symlink(%s/%ld, %pd, %s)\n", dir->i_sb->s_id, - dir->i_ino, dentry, symname); + dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s)\n", dir->i_sb->s_id, + dir->i_ino, dentry->d_name.name, symname); if (pathlen > PAGE_SIZE) return -ENAMETOOLONG; @@ -1821,9 +1836,9 @@ int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) error = NFS_PROTO(dir)->symlink(dir, dentry, page, pathlen, &attr); trace_nfs_symlink_exit(dir, dentry, error); if (error != 0) { - dfprintk(VFS, "NFS: symlink(%s/%ld, %pd, %s) error %d\n", + dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s) error %d\n", dir->i_sb->s_id, dir->i_ino, - dentry, symname, error); + dentry->d_name.name, symname, error); d_drop(dentry); __free_page(page); return error; @@ -1850,8 +1865,9 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) struct inode *inode = old_dentry->d_inode; int error; - dfprintk(VFS, "NFS: link(%pd2 -> %pd2)\n", - old_dentry, dentry); + dfprintk(VFS, "NFS: link(%s/%s -> %s/%s)\n", + old_dentry->d_parent->d_name.name, old_dentry->d_name.name, + dentry->d_parent->d_name.name, dentry->d_name.name); trace_nfs_link_enter(inode, dir, dentry); NFS_PROTO(inode)->return_delegation(inode); @@ -1899,8 +1915,9 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, struct dentry *dentry = NULL, *rehash = NULL; int error = -EBUSY; - dfprintk(VFS, "NFS: rename(%pd2 -> %pd2, ct=%d)\n", - old_dentry, new_dentry, + dfprintk(VFS, "NFS: rename(%s/%s -> %s/%s, ct=%d)\n", + old_dentry->d_parent->d_name.name, old_dentry->d_name.name, + new_dentry->d_parent->d_name.name, new_dentry->d_name.name, d_count(new_dentry)); trace_nfs_rename_enter(old_dir, old_dentry, new_dir, new_dentry); diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index d71d66c..91ff089 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c @@ -124,8 +124,9 @@ static inline int put_dreq(struct nfs_direct_req *dreq) ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_t pos, unsigned long nr_segs) { #ifndef CONFIG_NFS_SWAP - dprintk("NFS: nfs_direct_IO (%pD) off/no(%Ld/%lu) EINVAL\n", - iocb->ki_filp, (long long) pos, nr_segs); + dprintk("NFS: nfs_direct_IO (%s) off/no(%Ld/%lu) EINVAL\n", + iocb->ki_filp->f_path.dentry->d_name.name, + (long long) pos, nr_segs); return -EINVAL; #else @@ -908,8 +909,10 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov, count = iov_length(iov, nr_segs); nfs_add_stats(mapping->host, NFSIOS_DIRECTREADBYTES, count); - dfprintk(FILE, "NFS: direct read(%pD2, %zd@%Ld)\n", - file, count, (long long) pos); + dfprintk(FILE, "NFS: direct read(%s/%s, %zd@%Ld)\n", + file->f_path.dentry->d_parent->d_name.name, + file->f_path.dentry->d_name.name, + count, (long long) pos); retval = 0; if (!count) @@ -962,8 +965,10 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov, count = iov_length(iov, nr_segs); nfs_add_stats(mapping->host, NFSIOS_DIRECTWRITTENBYTES, count); - dfprintk(FILE, "NFS: direct write(%pD2, %zd@%Ld)\n", - file, count, (long long) pos); + dfprintk(FILE, "NFS: direct write(%s/%s, %zd@%Ld)\n", + file->f_path.dentry->d_parent->d_name.name, + file->f_path.dentry->d_name.name, + count, (long long) pos); retval = generic_write_checks(file, &pos, &count, 0); if (retval) diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c index d25f10f..fc0f95e 100644 --- a/fs/nfs/dns_resolve.c +++ b/fs/nfs/dns_resolve.c @@ -46,9 +46,7 @@ ssize_t nfs_dns_resolve_name(struct net *net, char *name, size_t namelen, #include <linux/sunrpc/cache.h> #include <linux/sunrpc/svcauth.h> #include <linux/sunrpc/rpc_pipe_fs.h> -#include <linux/nfs_fs.h> -#include "nfs4_fs.h" #include "dns_resolve.h" #include "cache_lib.h" #include "netns.h" diff --git a/fs/nfs/file.c b/fs/nfs/file.c index e2fcacf..1e6bfdb 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -65,7 +65,9 @@ nfs_file_open(struct inode *inode, struct file *filp) { int res; - dprintk("NFS: open file(%pD2)\n", filp); + dprintk("NFS: open file(%s/%s)\n", + filp->f_path.dentry->d_parent->d_name.name, + filp->f_path.dentry->d_name.name); nfs_inc_stats(inode, NFSIOS_VFSOPEN); res = nfs_check_flags(filp->f_flags); @@ -79,7 +81,9 @@ nfs_file_open(struct inode *inode, struct file *filp) int nfs_file_release(struct inode *inode, struct file *filp) { - dprintk("NFS: release(%pD2)\n", filp); + dprintk("NFS: release(%s/%s)\n", + filp->f_path.dentry->d_parent->d_name.name, + filp->f_path.dentry->d_name.name); nfs_inc_stats(inode, NFSIOS_VFSRELEASE); return nfs_release(inode, filp); @@ -119,8 +123,10 @@ force_reval: loff_t nfs_file_llseek(struct file *filp, loff_t offset, int whence) { - dprintk("NFS: llseek file(%pD2, %lld, %d)\n", - filp, offset, whence); + dprintk("NFS: llseek file(%s/%s, %lld, %d)\n", + filp->f_path.dentry->d_parent->d_name.name, + filp->f_path.dentry->d_name.name, + offset, whence); /* * whence == SEEK_END || SEEK_DATA || SEEK_HOLE => we must revalidate @@ -144,9 +150,12 @@ EXPORT_SYMBOL_GPL(nfs_file_llseek); int nfs_file_flush(struct file *file, fl_owner_t id) { - struct inode *inode = file_inode(file); + struct dentry *dentry = file->f_path.dentry; + struct inode *inode = dentry->d_inode; - dprintk("NFS: flush(%pD2)\n", file); + dprintk("NFS: flush(%s/%s)\n", + dentry->d_parent->d_name.name, + dentry->d_name.name); nfs_inc_stats(inode, NFSIOS_VFSFLUSH); if ((file->f_mode & FMODE_WRITE) == 0) @@ -168,14 +177,15 @@ ssize_t nfs_file_read(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos) { - struct inode *inode = file_inode(iocb->ki_filp); + struct dentry * dentry = iocb->ki_filp->f_path.dentry; + struct inode * inode = dentry->d_inode; ssize_t result; if (iocb->ki_filp->f_flags & O_DIRECT) return nfs_file_direct_read(iocb, iov, nr_segs, pos, true); - dprintk("NFS: read(%pD2, %lu@%lu)\n", - iocb->ki_filp, + dprintk("NFS: read(%s/%s, %lu@%lu)\n", + dentry->d_parent->d_name.name, dentry->d_name.name, (unsigned long) iov_length(iov, nr_segs), (unsigned long) pos); result = nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping); @@ -193,11 +203,13 @@ nfs_file_splice_read(struct file *filp, loff_t *ppos, struct pipe_inode_info *pipe, size_t count, unsigned int flags) { - struct inode *inode = file_inode(filp); + struct dentry *dentry = filp->f_path.dentry; + struct inode *inode = dentry->d_inode; ssize_t res; - dprintk("NFS: splice_read(%pD2, %lu@%Lu)\n", - filp, (unsigned long) count, (unsigned long long) *ppos); + dprintk("NFS: splice_read(%s/%s, %lu@%Lu)\n", + dentry->d_parent->d_name.name, dentry->d_name.name, + (unsigned long) count, (unsigned long long) *ppos); res = nfs_revalidate_mapping(inode, filp->f_mapping); if (!res) { @@ -212,10 +224,12 @@ EXPORT_SYMBOL_GPL(nfs_file_splice_read); int nfs_file_mmap(struct file * file, struct vm_area_struct * vma) { - struct inode *inode = file_inode(file); + struct dentry *dentry = file->f_path.dentry; + struct inode *inode = dentry->d_inode; int status; - dprintk("NFS: mmap(%pD2)\n", file); + dprintk("NFS: mmap(%s/%s)\n", + dentry->d_parent->d_name.name, dentry->d_name.name); /* Note: generic_file_mmap() returns ENOSYS on nommu systems * so we call that before revalidating the mapping @@ -244,12 +258,15 @@ EXPORT_SYMBOL_GPL(nfs_file_mmap); int nfs_file_fsync_commit(struct file *file, loff_t start, loff_t end, int datasync) { + struct dentry *dentry = file->f_path.dentry; struct nfs_open_context *ctx = nfs_file_open_context(file); - struct inode *inode = file_inode(file); + struct inode *inode = dentry->d_inode; int have_error, do_resend, status; int ret = 0; - dprintk("NFS: fsync file(%pD2) datasync %d\n", file, datasync); + dprintk("NFS: fsync file(%s/%s) datasync %d\n", + dentry->d_parent->d_name.name, dentry->d_name.name, + datasync); nfs_inc_stats(inode, NFSIOS_VFSFSYNC); do_resend = test_and_clear_bit(NFS_CONTEXT_RESEND_WRITES, &ctx->flags); @@ -354,8 +371,10 @@ static int nfs_write_begin(struct file *file, struct address_space *mapping, struct page *page; int once_thru = 0; - dfprintk(PAGECACHE, "NFS: write_begin(%pD2(%ld), %u@%lld)\n", - file, mapping->host->i_ino, len, (long long) pos); + dfprintk(PAGECACHE, "NFS: write_begin(%s/%s(%ld), %u@%lld)\n", + file->f_path.dentry->d_parent->d_name.name, + file->f_path.dentry->d_name.name, + mapping->host->i_ino, len, (long long) pos); start: /* @@ -395,8 +414,10 @@ static int nfs_write_end(struct file *file, struct address_space *mapping, struct nfs_open_context *ctx = nfs_file_open_context(file); int status; - dfprintk(PAGECACHE, "NFS: write_end(%pD2(%ld), %u@%lld)\n", - file, mapping->host->i_ino, len, (long long) pos); + dfprintk(PAGECACHE, "NFS: write_end(%s/%s(%ld), %u@%lld)\n", + file->f_path.dentry->d_parent->d_name.name, + file->f_path.dentry->d_name.name, + mapping->host->i_ino, len, (long long) pos); /* * Zero any uninitialised parts of the page, and then mark the page @@ -580,21 +601,22 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) { struct page *page = vmf->page; struct file *filp = vma->vm_file; - struct inode *inode = file_inode(filp); + struct dentry *dentry = filp->f_path.dentry; unsigned pagelen; int ret = VM_FAULT_NOPAGE; struct address_space *mapping; - dfprintk(PAGECACHE, "NFS: vm_page_mkwrite(%pD2(%ld), offset %lld)\n", - filp, filp->f_mapping->host->i_ino, + dfprintk(PAGECACHE, "NFS: vm_page_mkwrite(%s/%s(%ld), offset %lld)\n", + dentry->d_parent->d_name.name, dentry->d_name.name, + filp->f_mapping->host->i_ino, (long long)page_offset(page)); /* make sure the cache has finished storing the page */ - nfs_fscache_wait_on_page_write(NFS_I(inode), page); + nfs_fscache_wait_on_page_write(NFS_I(dentry->d_inode), page); lock_page(page); mapping = page_file_mapping(page); - if (mapping != inode->i_mapping) + if (mapping != dentry->d_inode->i_mapping) goto out_unlock; wait_on_page_writeback(page); @@ -637,21 +659,22 @@ static int nfs_need_sync_write(struct file *filp, struct inode *inode) ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos) { - struct file *file = iocb->ki_filp; - struct inode *inode = file_inode(file); + struct dentry * dentry = iocb->ki_filp->f_path.dentry; + struct inode * inode = dentry->d_inode; unsigned long written = 0; ssize_t result; size_t count = iov_length(iov, nr_segs); - result = nfs_key_timeout_notify(file, inode); + result = nfs_key_timeout_notify(iocb->ki_filp, inode); if (result) return result; - if (file->f_flags & O_DIRECT) + if (iocb->ki_filp->f_flags & O_DIRECT) return nfs_file_direct_write(iocb, iov, nr_segs, pos, true); - dprintk("NFS: write(%pD2, %lu@%Ld)\n", - file, (unsigned long) count, (long long) pos); + dprintk("NFS: write(%s/%s, %lu@%Ld)\n", + dentry->d_parent->d_name.name, dentry->d_name.name, + (unsigned long) count, (long long) pos); result = -EBUSY; if (IS_SWAPFILE(inode)) @@ -659,8 +682,8 @@ ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov, /* * O_APPEND implies that we must revalidate the file length. */ - if (file->f_flags & O_APPEND) { - result = nfs_revalidate_file_size(inode, file); + if (iocb->ki_filp->f_flags & O_APPEND) { + result = nfs_revalidate_file_size(inode, iocb->ki_filp); if (result) goto out; } @@ -674,8 +697,8 @@ ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov, written = result; /* Return error values for O_DSYNC and IS_SYNC() */ - if (result >= 0 && nfs_need_sync_write(file, inode)) { - int err = vfs_fsync(file, 0); + if (result >= 0 && nfs_need_sync_write(iocb->ki_filp, inode)) { + int err = vfs_fsync(iocb->ki_filp, 0); if (err < 0) result = err; } @@ -694,12 +717,14 @@ ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe, struct file *filp, loff_t *ppos, size_t count, unsigned int flags) { - struct inode *inode = file_inode(filp); + struct dentry *dentry = filp->f_path.dentry; + struct inode *inode = dentry->d_inode; unsigned long written = 0; ssize_t ret; - dprintk("NFS splice_write(%pD2, %lu@%llu)\n", - filp, (unsigned long) count, (unsigned long long) *ppos); + dprintk("NFS splice_write(%s/%s, %lu@%llu)\n", + dentry->d_parent->d_name.name, dentry->d_name.name, + (unsigned long) count, (unsigned long long) *ppos); /* * The combination of splice and an O_APPEND destination is disallowed. @@ -858,8 +883,10 @@ int nfs_lock(struct file *filp, int cmd, struct file_lock *fl) int ret = -ENOLCK; int is_local = 0; - dprintk("NFS: lock(%pD2, t=%x, fl=%x, r=%lld:%lld)\n", - filp, fl->fl_type, fl->fl_flags, + dprintk("NFS: lock(%s/%s, t=%x, fl=%x, r=%lld:%lld)\n", + filp->f_path.dentry->d_parent->d_name.name, + filp->f_path.dentry->d_name.name, + fl->fl_type, fl->fl_flags, (long long)fl->fl_start, (long long)fl->fl_end); nfs_inc_stats(inode, NFSIOS_VFSLOCK); @@ -896,8 +923,10 @@ int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) struct inode *inode = filp->f_mapping->host; int is_local = 0; - dprintk("NFS: flock(%pD2, t=%x, fl=%x)\n", - filp, fl->fl_type, fl->fl_flags); + dprintk("NFS: flock(%s/%s, t=%x, fl=%x)\n", + filp->f_path.dentry->d_parent->d_name.name, + filp->f_path.dentry->d_name.name, + fl->fl_type, fl->fl_flags); if (!(fl->fl_flags & FL_FLOCK)) return -ENOLCK; @@ -931,7 +960,9 @@ EXPORT_SYMBOL_GPL(nfs_flock); */ int nfs_setlease(struct file *file, long arg, struct file_lock **fl) { - dprintk("NFS: setlease(%pD2, arg=%ld)\n", file, arg); + dprintk("NFS: setlease(%s/%s, arg=%ld)\n", + file->f_path.dentry->d_parent->d_name.name, + file->f_path.dentry->d_name.name, arg); return -EINVAL; } EXPORT_SYMBOL_GPL(nfs_setlease); diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c index 3ef01f0..24d1d1c 100644 --- a/fs/nfs/fscache.c +++ b/fs/nfs/fscache.c @@ -39,7 +39,7 @@ void nfs_fscache_get_client_cookie(struct nfs_client *clp) /* create a cache index for looking up filehandles */ clp->fscache = fscache_acquire_cookie(nfs_fscache_netfs.primary_index, &nfs_fscache_server_index_def, - clp, true); + clp); dfprintk(FSCACHE, "NFS: get client cookie (0x%p/0x%p)\n", clp, clp->fscache); } @@ -139,7 +139,7 @@ void nfs_fscache_get_super_cookie(struct super_block *sb, const char *uniq, int /* create a cache index for looking up filehandles */ nfss->fscache = fscache_acquire_cookie(nfss->nfs_client->fscache, &nfs_fscache_super_index_def, - nfss, true); + nfss); dfprintk(FSCACHE, "NFS: get superblock cookie (0x%p/0x%p)\n", nfss, nfss->fscache); return; @@ -178,79 +178,163 @@ void nfs_fscache_release_super_cookie(struct super_block *sb) /* * Initialise the per-inode cache cookie pointer for an NFS inode. */ -void nfs_fscache_init_inode(struct inode *inode) +void nfs_fscache_init_inode_cookie(struct inode *inode) { + NFS_I(inode)->fscache = NULL; + if (S_ISREG(inode->i_mode)) + set_bit(NFS_INO_FSCACHE, &NFS_I(inode)->flags); +} + +/* + * Get the per-inode cache cookie for an NFS inode. + */ +static void nfs_fscache_enable_inode_cookie(struct inode *inode) +{ + struct super_block *sb = inode->i_sb; struct nfs_inode *nfsi = NFS_I(inode); - nfsi->fscache = NULL; - if (!S_ISREG(inode->i_mode)) + if (nfsi->fscache || !NFS_FSCACHE(inode)) return; - nfsi->fscache = fscache_acquire_cookie(NFS_SB(inode->i_sb)->fscache, - &nfs_fscache_inode_object_def, - nfsi, false); + + if ((NFS_SB(sb)->options & NFS_OPTION_FSCACHE)) { + nfsi->fscache = fscache_acquire_cookie( + NFS_SB(sb)->fscache, + &nfs_fscache_inode_object_def, + nfsi); + + dfprintk(FSCACHE, "NFS: get FH cookie (0x%p/0x%p/0x%p)\n", + sb, nfsi, nfsi->fscache); + } } /* * Release a per-inode cookie. */ -void nfs_fscache_clear_inode(struct inode *inode) +void nfs_fscache_release_inode_cookie(struct inode *inode) { struct nfs_inode *nfsi = NFS_I(inode); - struct fscache_cookie *cookie = nfs_i_fscache(inode); - dfprintk(FSCACHE, "NFS: clear cookie (0x%p/0x%p)\n", nfsi, cookie); + dfprintk(FSCACHE, "NFS: clear cookie (0x%p/0x%p)\n", + nfsi, nfsi->fscache); - fscache_relinquish_cookie(cookie, false); + fscache_relinquish_cookie(nfsi->fscache, 0); nfsi->fscache = NULL; } -static bool nfs_fscache_can_enable(void *data) +/* + * Retire a per-inode cookie, destroying the data attached to it. + */ +void nfs_fscache_zap_inode_cookie(struct inode *inode) { - struct inode *inode = data; + struct nfs_inode *nfsi = NFS_I(inode); - return !inode_is_open_for_write(inode); + dfprintk(FSCACHE, "NFS: zapping cookie (0x%p/0x%p)\n", + nfsi, nfsi->fscache); + + fscache_relinquish_cookie(nfsi->fscache, 1); + nfsi->fscache = NULL; } /* - * Enable or disable caching for a file that is being opened as appropriate. - * The cookie is allocated when the inode is initialised, but is not enabled at - * that time. Enablement is deferred to file-open time to avoid stat() and - * access() thrashing the cache. - * - * For now, with NFS, only regular files that are open read-only will be able - * to use the cache. - * - * We enable the cache for an inode if we open it read-only and it isn't - * currently open for writing. We disable the cache if the inode is open - * write-only. - * - * The caller uses the file struct to pin i_writecount on the inode before - * calling us when a file is opened for writing, so we can make use of that. - * - * Note that this may be invoked multiple times in parallel by parallel - * nfs_open() functions. + * Turn off the cache with regard to a per-inode cookie if opened for writing, + * invalidating all the pages in the page cache relating to the associated + * inode to clear the per-page caching. + */ +static void nfs_fscache_disable_inode_cookie(struct inode *inode) +{ + clear_bit(NFS_INO_FSCACHE, &NFS_I(inode)->flags); + + if (NFS_I(inode)->fscache) { + dfprintk(FSCACHE, + "NFS: nfsi 0x%p turning cache off\n", NFS_I(inode)); + + /* Need to uncache any pages attached to this inode that + * fscache knows about before turning off the cache. + */ + fscache_uncache_all_inode_pages(NFS_I(inode)->fscache, inode); + nfs_fscache_zap_inode_cookie(inode); + } +} + +/* + * wait_on_bit() sleep function for uninterruptible waiting */ -void nfs_fscache_open_file(struct inode *inode, struct file *filp) +static int nfs_fscache_wait_bit(void *flags) +{ + schedule(); + return 0; +} + +/* + * Lock against someone else trying to also acquire or relinquish a cookie + */ +static inline void nfs_fscache_inode_lock(struct inode *inode) { struct nfs_inode *nfsi = NFS_I(inode); - struct fscache_cookie *cookie = nfs_i_fscache(inode); - if (!fscache_cookie_valid(cookie)) - return; + while (test_and_set_bit(NFS_INO_FSCACHE_LOCK, &nfsi->flags)) + wait_on_bit(&nfsi->flags, NFS_INO_FSCACHE_LOCK, + nfs_fscache_wait_bit, TASK_UNINTERRUPTIBLE); +} - if (inode_is_open_for_write(inode)) { - dfprintk(FSCACHE, "NFS: nfsi 0x%p disabling cache\n", nfsi); - clear_bit(NFS_INO_FSCACHE, &nfsi->flags); - fscache_disable_cookie(cookie, true); - fscache_uncache_all_inode_pages(cookie, inode); - } else { - dfprintk(FSCACHE, "NFS: nfsi 0x%p enabling cache\n", nfsi); - fscache_enable_cookie(cookie, nfs_fscache_can_enable, inode); - if (fscache_cookie_enabled(cookie)) - set_bit(NFS_INO_FSCACHE, &NFS_I(inode)->flags); +/* + * Unlock cookie management lock + */ +static inline void nfs_fscache_inode_unlock(struct inode *inode) +{ + struct nfs_inode *nfsi = NFS_I(inode); + + smp_mb__before_clear_bit(); + clear_bit(NFS_INO_FSCACHE_LOCK, &nfsi->flags); + smp_mb__after_clear_bit(); + wake_up_bit(&nfsi->flags, NFS_INO_FSCACHE_LOCK); +} + +/* + * Decide if we should enable or disable local caching for this inode. + * - For now, with NFS, only regular files that are open read-only will be able + * to use the cache. + * - May be invoked multiple times in parallel by parallel nfs_open() functions. + */ +void nfs_fscache_set_inode_cookie(struct inode *inode, struct file *filp) +{ + if (NFS_FSCACHE(inode)) { + nfs_fscache_inode_lock(inode); + if ((filp->f_flags & O_ACCMODE) != O_RDONLY) + nfs_fscache_disable_inode_cookie(inode); + else + nfs_fscache_enable_inode_cookie(inode); + nfs_fscache_inode_unlock(inode); + } +} +EXPORT_SYMBOL_GPL(nfs_fscache_set_inode_cookie); + +/* + * Replace a per-inode cookie due to revalidation detecting a file having + * changed on the server. + */ +void nfs_fscache_reset_inode_cookie(struct inode *inode) +{ + struct nfs_inode *nfsi = NFS_I(inode); + struct nfs_server *nfss = NFS_SERVER(inode); + NFS_IFDEBUG(struct fscache_cookie *old = nfsi->fscache); + + nfs_fscache_inode_lock(inode); + if (nfsi->fscache) { + /* retire the current fscache cache and get a new one */ + fscache_relinquish_cookie(nfsi->fscache, 1); + + nfsi->fscache = fscache_acquire_cookie( + nfss->nfs_client->fscache, + &nfs_fscache_inode_object_def, + nfsi); + + dfprintk(FSCACHE, + "NFS: revalidation new cookie (0x%p/0x%p/0x%p/0x%p)\n", + nfss, nfsi, old, nfsi->fscache); } + nfs_fscache_inode_unlock(inode); } -EXPORT_SYMBOL_GPL(nfs_fscache_open_file); /* * Release the caching state associated with a page, if the page isn't busy @@ -260,11 +344,12 @@ EXPORT_SYMBOL_GPL(nfs_fscache_open_file); int nfs_fscache_release_page(struct page *page, gfp_t gfp) { if (PageFsCache(page)) { - struct fscache_cookie *cookie = nfs_i_fscache(page->mapping->host); + struct nfs_inode *nfsi = NFS_I(page->mapping->host); + struct fscache_cookie *cookie = nfsi->fscache; BUG_ON(!cookie); dfprintk(FSCACHE, "NFS: fscache releasepage (0x%p/0x%p/0x%p)\n", - cookie, page, NFS_I(page->mapping->host)); + cookie, page, nfsi); if (!fscache_maybe_release_page(cookie, page, gfp)) return 0; @@ -282,12 +367,13 @@ int nfs_fscache_release_page(struct page *page, gfp_t gfp) */ void __nfs_fscache_invalidate_page(struct page *page, struct inode *inode) { - struct fscache_cookie *cookie = nfs_i_fscache(inode); + struct nfs_inode *nfsi = NFS_I(inode); + struct fscache_cookie *cookie = nfsi->fscache; BUG_ON(!cookie); dfprintk(FSCACHE, "NFS: fscache invalidatepage (0x%p/0x%p/0x%p)\n", - cookie, page, NFS_I(inode)); + cookie, page, nfsi); fscache_wait_on_page_write(cookie, page); @@ -331,9 +417,9 @@ int __nfs_readpage_from_fscache(struct nfs_open_context *ctx, dfprintk(FSCACHE, "NFS: readpage_from_fscache(fsc:%p/p:%p(i:%lx f:%lx)/0x%p)\n", - nfs_i_fscache(inode), page, page->index, page->flags, inode); + NFS_I(inode)->fscache, page, page->index, page->flags, inode); - ret = fscache_read_or_alloc_page(nfs_i_fscache(inode), + ret = fscache_read_or_alloc_page(NFS_I(inode)->fscache, page, nfs_readpage_from_fscache_complete, ctx, @@ -373,9 +459,9 @@ int __nfs_readpages_from_fscache(struct nfs_open_context *ctx, int ret; dfprintk(FSCACHE, "NFS: nfs_getpages_from_fscache (0x%p/%u/0x%p)\n", - nfs_i_fscache(inode), npages, inode); + NFS_I(inode)->fscache, npages, inode); - ret = fscache_read_or_alloc_pages(nfs_i_fscache(inode), + ret = fscache_read_or_alloc_pages(NFS_I(inode)->fscache, mapping, pages, nr_pages, nfs_readpage_from_fscache_complete, ctx, @@ -420,15 +506,15 @@ void __nfs_readpage_to_fscache(struct inode *inode, struct page *page, int sync) dfprintk(FSCACHE, "NFS: readpage_to_fscache(fsc:%p/p:%p(i:%lx f:%lx)/%d)\n", - nfs_i_fscache(inode), page, page->index, page->flags, sync); + NFS_I(inode)->fscache, page, page->index, page->flags, sync); - ret = fscache_write_page(nfs_i_fscache(inode), page, GFP_KERNEL); + ret = fscache_write_page(NFS_I(inode)->fscache, page, GFP_KERNEL); dfprintk(FSCACHE, "NFS: readpage_to_fscache: p:%p(i:%lu f:%lx) ret %d\n", page, page->index, page->flags, ret); if (ret != 0) { - fscache_uncache_page(nfs_i_fscache(inode), page); + fscache_uncache_page(NFS_I(inode)->fscache, page); nfs_add_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_WRITTEN_FAIL, 1); nfs_add_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_UNCACHED, 1); diff --git a/fs/nfs/fscache.h b/fs/nfs/fscache.h index d7fe3e7..4ecb766 100644 --- a/fs/nfs/fscache.h +++ b/fs/nfs/fscache.h @@ -76,9 +76,11 @@ extern void nfs_fscache_release_client_cookie(struct nfs_client *); extern void nfs_fscache_get_super_cookie(struct super_block *, const char *, int); extern void nfs_fscache_release_super_cookie(struct super_block *); -extern void nfs_fscache_init_inode(struct inode *); -extern void nfs_fscache_clear_inode(struct inode *); -extern void nfs_fscache_open_file(struct inode *, struct file *); +extern void nfs_fscache_init_inode_cookie(struct inode *); +extern void nfs_fscache_release_inode_cookie(struct inode *); +extern void nfs_fscache_zap_inode_cookie(struct inode *); +extern void nfs_fscache_set_inode_cookie(struct inode *, struct file *); +extern void nfs_fscache_reset_inode_cookie(struct inode *); extern void __nfs_fscache_invalidate_page(struct page *, struct inode *); extern int nfs_fscache_release_page(struct page *, gfp_t); @@ -185,10 +187,12 @@ static inline void nfs_fscache_release_client_cookie(struct nfs_client *clp) {} static inline void nfs_fscache_release_super_cookie(struct super_block *sb) {} -static inline void nfs_fscache_init_inode(struct inode *inode) {} -static inline void nfs_fscache_clear_inode(struct inode *inode) {} -static inline void nfs_fscache_open_file(struct inode *inode, - struct file *filp) {} +static inline void nfs_fscache_init_inode_cookie(struct inode *inode) {} +static inline void nfs_fscache_release_inode_cookie(struct inode *inode) {} +static inline void nfs_fscache_zap_inode_cookie(struct inode *inode) {} +static inline void nfs_fscache_set_inode_cookie(struct inode *inode, + struct file *filp) {} +static inline void nfs_fscache_reset_inode_cookie(struct inode *inode) {} static inline int nfs_fscache_release_page(struct page *page, gfp_t gfp) { diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 00ad1c2..eda8879 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -122,7 +122,7 @@ void nfs_clear_inode(struct inode *inode) WARN_ON_ONCE(!list_empty(&NFS_I(inode)->open_files)); nfs_zap_acl_cache(inode); nfs_access_zap_cache(inode); - nfs_fscache_clear_inode(inode); + nfs_fscache_release_inode_cookie(inode); } EXPORT_SYMBOL_GPL(nfs_clear_inode); @@ -274,6 +274,12 @@ void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr, if (label == NULL) return; + if (nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL) == 0) + return; + + if (NFS_SERVER(inode)->nfs_client->cl_minorversion < 2) + return; + if ((fattr->valid & NFS_ATTR_FATTR_V4_SECURITY_LABEL) && inode->i_security) { error = security_inode_notifysecctx(inode, label->label, label->len); @@ -312,7 +318,7 @@ struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags) } EXPORT_SYMBOL_GPL(nfs4_label_alloc); #else -void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr, +void inline nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr, struct nfs4_label *label) { } @@ -453,7 +459,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st nfsi->attrtimeo_timestamp = now; nfsi->access_cache = RB_ROOT; - nfs_fscache_init_inode(inode); + nfs_fscache_init_inode_cookie(inode); unlock_new_inode(inode); } else @@ -848,7 +854,7 @@ int nfs_open(struct inode *inode, struct file *filp) return PTR_ERR(ctx); nfs_file_set_open_context(filp, ctx); put_nfs_open_context(ctx); - nfs_fscache_open_file(inode, filp); + nfs_fscache_set_inode_cookie(inode, filp); return 0; } @@ -917,8 +923,6 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) if (nfsi->cache_validity & NFS_INO_INVALID_ACL) nfs_zap_acl_cache(inode); - nfs_setsecurity(inode, fattr, label); - dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n", inode->i_sb->s_id, (long long)NFS_FILEID(inode)); @@ -1205,7 +1209,6 @@ u32 _nfs_display_fhandle_hash(const struct nfs_fh *fh) * not on the result */ return nfs_fhandle_hash(fh); } -EXPORT_SYMBOL_GPL(_nfs_display_fhandle_hash); /* * _nfs_display_fhandle - display an NFS file handle on the console @@ -1250,7 +1253,6 @@ void _nfs_display_fhandle(const struct nfs_fh *fh, const char *caption) } } } -EXPORT_SYMBOL_GPL(_nfs_display_fhandle); #endif /** diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 8b5cc04..38da8c2 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -88,8 +88,8 @@ struct nfs_parsed_mount_data { unsigned int namlen; unsigned int options; unsigned int bsize; - struct nfs_auth_info auth_info; - rpc_authflavor_t selected_flavor; + unsigned int auth_flavor_len; + rpc_authflavor_t auth_flavors[1]; char *client_address; unsigned int version; unsigned int minorversion; @@ -154,7 +154,6 @@ struct nfs_client *nfs_get_client(const struct nfs_client_initdata *, rpc_authflavor_t); int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *, struct nfs_fattr *); void nfs_server_insert_lists(struct nfs_server *); -void nfs_server_remove_lists(struct nfs_server *); void nfs_init_timeout_values(struct rpc_timeout *, int, unsigned int, unsigned int); int nfs_init_server_rpcclient(struct nfs_server *, const struct rpc_timeout *t, rpc_authflavor_t); @@ -175,8 +174,6 @@ extern struct nfs_server *nfs4_create_server( struct nfs_subversion *); extern struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *, struct nfs_fh *); -extern int nfs4_update_server(struct nfs_server *server, const char *hostname, - struct sockaddr *sap, size_t salen); extern void nfs_free_server(struct nfs_server *server); extern struct nfs_server *nfs_clone_server(struct nfs_server *, struct nfs_fh *, @@ -269,21 +266,6 @@ extern const u32 nfs41_maxgetdevinfo_overhead; extern struct rpc_procinfo nfs4_procedures[]; #endif -#ifdef CONFIG_NFS_V4_SECURITY_LABEL -extern struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags); -static inline void nfs4_label_free(struct nfs4_label *label) -{ - if (label) { - kfree(label->label); - kfree(label); - } - return; -} -#else -static inline struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags) { return NULL; } -static inline void nfs4_label_free(void *label) {} -#endif /* CONFIG_NFS_V4_SECURITY_LABEL */ - /* proc.c */ void nfs_close_context(struct nfs_open_context *ctx, int is_sync); extern struct nfs_client *nfs_init_client(struct nfs_client *clp, @@ -341,7 +323,6 @@ extern struct file_system_type nfs_xdev_fs_type; extern struct file_system_type nfs4_xdev_fs_type; extern struct file_system_type nfs4_referral_fs_type; #endif -bool nfs_auth_info_match(const struct nfs_auth_info *, rpc_authflavor_t); struct dentry *nfs_try_mount(int, const char *, struct nfs_mount_info *, struct nfs_subversion *); void nfs_initialise_sb(struct super_block *); diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index b5a0afc..348b535 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c @@ -253,8 +253,9 @@ struct vfsmount *nfs_do_submount(struct dentry *dentry, struct nfs_fh *fh, dprintk("--> nfs_do_submount()\n"); - dprintk("%s: submounting on %pd2\n", __func__, - dentry); + dprintk("%s: submounting on %s/%s\n", __func__, + dentry->d_parent->d_name.name, + dentry->d_name.name); if (page == NULL) goto out; devname = nfs_devname(dentry, page, PAGE_SIZE); diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 01b6f6a..90cb10d 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -321,7 +321,7 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, umode_t mode = sattr->ia_mode; int status = -ENOMEM; - dprintk("NFS call create %pd\n", dentry); + dprintk("NFS call create %s\n", dentry->d_name.name); data = nfs3_alloc_createdata(); if (data == NULL) @@ -548,7 +548,7 @@ nfs3_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page, if (len > NFS3_MAXPATHLEN) return -ENAMETOOLONG; - dprintk("NFS call symlink %pd\n", dentry); + dprintk("NFS call symlink %s\n", dentry->d_name.name); data = nfs3_alloc_createdata(); if (data == NULL) @@ -576,7 +576,7 @@ nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr) umode_t mode = sattr->ia_mode; int status = -ENOMEM; - dprintk("NFS call mkdir %pd\n", dentry); + dprintk("NFS call mkdir %s\n", dentry->d_name.name); sattr->ia_mode &= ~current_umask(); @@ -695,7 +695,7 @@ nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, umode_t mode = sattr->ia_mode; int status = -ENOMEM; - dprintk("NFS call mknod %pd %u:%u\n", dentry, + dprintk("NFS call mknod %s %u:%u\n", dentry->d_name.name, MAJOR(rdev), MINOR(rdev)); sattr->ia_mode &= ~current_umask(); diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 5609edc..28842ab 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -9,14 +9,6 @@ #ifndef __LINUX_FS_NFS_NFS4_FS_H #define __LINUX_FS_NFS_NFS4_FS_H -#if defined(CONFIG_NFS_V4_2) -#define NFS4_MAX_MINOR_VERSION 2 -#elif defined(CONFIG_NFS_V4_1) -#define NFS4_MAX_MINOR_VERSION 1 -#else -#define NFS4_MAX_MINOR_VERSION 0 -#endif - #if IS_ENABLED(CONFIG_NFS_V4) #define NFS4_MAX_LOOP_ON_RECOVER (10) @@ -37,8 +29,6 @@ enum nfs4_client_state { NFS4CLNT_SERVER_SCOPE_MISMATCH, NFS4CLNT_PURGE_STATE, NFS4CLNT_BIND_CONN_TO_SESSION, - NFS4CLNT_MOVED, - NFS4CLNT_LEASE_MOVED, }; #define NFS4_RENEW_TIMEOUT 0x01 @@ -60,7 +50,6 @@ struct nfs4_minor_version_ops { const struct nfs4_state_recovery_ops *reboot_recovery_ops; const struct nfs4_state_recovery_ops *nograce_recovery_ops; const struct nfs4_state_maintenance_ops *state_renewal_ops; - const struct nfs4_mig_recovery_ops *mig_recovery_ops; }; #define NFS_SEQID_CONFIRMED 1 @@ -214,12 +203,6 @@ struct nfs4_state_maintenance_ops { int (*renew_lease)(struct nfs_client *, struct rpc_cred *); }; -struct nfs4_mig_recovery_ops { - int (*get_locations)(struct inode *, struct nfs4_fs_locations *, - struct page *, struct rpc_cred *); - int (*fsid_present)(struct inode *, struct rpc_cred *); -}; - extern const struct dentry_operations nfs4_dentry_operations; /* dir.c */ @@ -230,11 +213,10 @@ int nfs_atomic_open(struct inode *, struct dentry *, struct file *, extern struct file_system_type nfs4_fs_type; /* nfs4namespace.c */ +rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *); struct rpc_clnt *nfs4_create_sec_client(struct rpc_clnt *, struct inode *, struct qstr *); struct vfsmount *nfs4_submount(struct nfs_server *, struct dentry *, struct nfs_fh *, struct nfs_fattr *); -int nfs4_replace_transport(struct nfs_server *server, - const struct nfs4_fs_locations *locations); /* nfs4proc.c */ extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struct rpc_cred *, struct nfs4_setclientid_res *); @@ -249,9 +231,6 @@ extern int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait); extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle); extern int nfs4_proc_fs_locations(struct rpc_clnt *, struct inode *, const struct qstr *, struct nfs4_fs_locations *, struct page *); -extern int nfs4_proc_get_locations(struct inode *, struct nfs4_fs_locations *, - struct page *page, struct rpc_cred *); -extern int nfs4_proc_fsid_present(struct inode *, struct rpc_cred *); extern struct rpc_clnt *nfs4_proc_lookup_mountpoint(struct inode *, struct qstr *, struct nfs_fh *, struct nfs_fattr *); extern int nfs4_proc_secinfo(struct inode *, const struct qstr *, struct nfs4_secinfo_flavors *); @@ -432,8 +411,6 @@ extern int nfs4_client_recover_expired_lease(struct nfs_client *clp); extern void nfs4_schedule_state_manager(struct nfs_client *); extern void nfs4_schedule_path_down_recovery(struct nfs_client *clp); extern int nfs4_schedule_stateid_recovery(const struct nfs_server *, struct nfs4_state *); -extern int nfs4_schedule_migration_recovery(const struct nfs_server *); -extern void nfs4_schedule_lease_moved_recovery(struct nfs_client *); extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags); extern void nfs41_handle_server_scope(struct nfs_client *, struct nfs41_server_scope **); diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index b4a160a..a860ab5 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c @@ -197,7 +197,6 @@ struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init) clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED; clp->cl_minorversion = cl_init->minorversion; clp->cl_mvops = nfs_v4_minor_ops[cl_init->minorversion]; - clp->cl_mig_gen = 1; return clp; error: @@ -369,7 +368,6 @@ struct nfs_client *nfs4_init_client(struct nfs_client *clp, if (clp->cl_minorversion != 0) __set_bit(NFS_CS_INFINITE_SLOTS, &clp->cl_flags); __set_bit(NFS_CS_DISCRTRY, &clp->cl_flags); - __set_bit(NFS_CS_NO_RETRANS_TIMEOUT, &clp->cl_flags); error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_GSS_KRB5I); if (error == -EINVAL) error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_UNIX); @@ -926,7 +924,7 @@ static int nfs4_server_common_setup(struct nfs_server *server, dprintk("Server FSID: %llx:%llx\n", (unsigned long long) server->fsid.major, (unsigned long long) server->fsid.minor); - nfs_display_fhandle(mntfh, "Pseudo-fs root FH"); + dprintk("Mount FH: %d\n", mntfh->size); nfs4_session_set_rwsize(server); @@ -949,8 +947,9 @@ out: * Create a version 4 volume record */ static int nfs4_init_server(struct nfs_server *server, - struct nfs_parsed_mount_data *data) + const struct nfs_parsed_mount_data *data) { + rpc_authflavor_t pseudoflavor = RPC_AUTH_UNIX; struct rpc_timeout timeparms; int error; @@ -962,15 +961,9 @@ static int nfs4_init_server(struct nfs_server *server, /* Initialise the client representation from the mount data */ server->flags = data->flags; server->options = data->options; - server->auth_info = data->auth_info; - /* Use the first specified auth flavor. If this flavor isn't - * allowed by the server, use the SECINFO path to try the - * other specified flavors */ - if (data->auth_info.flavor_len >= 1) - data->selected_flavor = data->auth_info.flavors[0]; - else - data->selected_flavor = RPC_AUTH_UNIX; + if (data->auth_flavor_len >= 1) + pseudoflavor = data->auth_flavors[0]; /* Get a client record */ error = nfs4_set_client(server, @@ -978,7 +971,7 @@ static int nfs4_init_server(struct nfs_server *server, (const struct sockaddr *)&data->nfs_server.address, data->nfs_server.addrlen, data->client_address, - data->selected_flavor, + pseudoflavor, data->nfs_server.protocol, &timeparms, data->minorversion, @@ -998,8 +991,7 @@ static int nfs4_init_server(struct nfs_server *server, server->port = data->nfs_server.port; - error = nfs_init_server_rpcclient(server, &timeparms, - data->selected_flavor); + error = nfs_init_server_rpcclient(server, &timeparms, pseudoflavor); error: /* Done */ @@ -1026,7 +1018,7 @@ struct nfs_server *nfs4_create_server(struct nfs_mount_info *mount_info, if (!server) return ERR_PTR(-ENOMEM); - auth_probe = mount_info->parsed->auth_info.flavor_len < 1; + auth_probe = mount_info->parsed->auth_flavor_len < 1; /* set up the general RPC client */ error = nfs4_init_server(server, mount_info->parsed); @@ -1054,7 +1046,6 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, { struct nfs_client *parent_client; struct nfs_server *server, *parent_server; - bool auth_probe; int error; dprintk("--> nfs4_create_referral_server()\n"); @@ -1087,9 +1078,8 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, if (error < 0) goto error; - auth_probe = parent_server->auth_info.flavor_len < 1; - - error = nfs4_server_common_setup(server, mntfh, auth_probe); + error = nfs4_server_common_setup(server, mntfh, + !(parent_server->flags & NFS_MOUNT_SECFLAVOUR)); if (error < 0) goto error; @@ -1101,111 +1091,3 @@ error: dprintk("<-- nfs4_create_referral_server() = error %d\n", error); return ERR_PTR(error); } - -/* - * Grab the destination's particulars, including lease expiry time. - * - * Returns zero if probe succeeded and retrieved FSID matches the FSID - * we have cached. - */ -static int nfs_probe_destination(struct nfs_server *server) -{ - struct inode *inode = server->super->s_root->d_inode; - struct nfs_fattr *fattr; - int error; - - fattr = nfs_alloc_fattr(); - if (fattr == NULL) - return -ENOMEM; - - /* Sanity: the probe won't work if the destination server - * does not recognize the migrated FH. */ - error = nfs_probe_fsinfo(server, NFS_FH(inode), fattr); - - nfs_free_fattr(fattr); - return error; -} - -/** - * nfs4_update_server - Move an nfs_server to a different nfs_client - * - * @server: represents FSID to be moved - * @hostname: new end-point's hostname - * @sap: new end-point's socket address - * @salen: size of "sap" - * - * The nfs_server must be quiescent before this function is invoked. - * Either its session is drained (NFSv4.1+), or its transport is - * plugged and drained (NFSv4.0). - * - * Returns zero on success, or a negative errno value. - */ -int nfs4_update_server(struct nfs_server *server, const char *hostname, - struct sockaddr *sap, size_t salen) -{ - struct nfs_client *clp = server->nfs_client; - struct rpc_clnt *clnt = server->client; - struct xprt_create xargs = { - .ident = clp->cl_proto, - .net = &init_net, - .dstaddr = sap, - .addrlen = salen, - .servername = hostname, - }; - char buf[INET6_ADDRSTRLEN + 1]; - struct sockaddr_storage address; - struct sockaddr *localaddr = (struct sockaddr *)&address; - int error; - - dprintk("--> %s: move FSID %llx:%llx to \"%s\")\n", __func__, - (unsigned long long)server->fsid.major, - (unsigned long long)server->fsid.minor, - hostname); - - error = rpc_switch_client_transport(clnt, &xargs, clnt->cl_timeout); - if (error != 0) { - dprintk("<-- %s(): rpc_switch_client_transport returned %d\n", - __func__, error); - goto out; - } - - error = rpc_localaddr(clnt, localaddr, sizeof(address)); - if (error != 0) { - dprintk("<-- %s(): rpc_localaddr returned %d\n", - __func__, error); - goto out; - } - - error = -EAFNOSUPPORT; - if (rpc_ntop(localaddr, buf, sizeof(buf)) == 0) { - dprintk("<-- %s(): rpc_ntop returned %d\n", - __func__, error); - goto out; - } - - nfs_server_remove_lists(server); - error = nfs4_set_client(server, hostname, sap, salen, buf, - clp->cl_rpcclient->cl_auth->au_flavor, - clp->cl_proto, clnt->cl_timeout, - clp->cl_minorversion, clp->cl_net); - nfs_put_client(clp); - if (error != 0) { - nfs_server_insert_lists(server); - dprintk("<-- %s(): nfs4_set_client returned %d\n", - __func__, error); - goto out; - } - - if (server->nfs_client->cl_hostname == NULL) - server->nfs_client->cl_hostname = kstrdup(hostname, GFP_KERNEL); - nfs_server_insert_lists(server); - - error = nfs_probe_destination(server); - if (error < 0) - goto out; - - dprintk("<-- %s() succeeded\n", __func__); - -out: - return error; -} diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c index 8de3407..77efaf1 100644 --- a/fs/nfs/nfs4file.c +++ b/fs/nfs/nfs4file.c @@ -31,7 +31,9 @@ nfs4_file_open(struct inode *inode, struct file *filp) * -EOPENSTALE. The VFS will retry the lookup/create/open. */ - dprintk("NFS: open file(%pd2)\n", dentry); + dprintk("NFS: open file(%s/%s)\n", + dentry->d_parent->d_name.name, + dentry->d_name.name); if ((openflags & O_ACCMODE) == 3) openflags--; @@ -73,7 +75,7 @@ nfs4_file_open(struct inode *inode, struct file *filp) nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); nfs_file_set_open_context(filp, ctx); - nfs_fscache_open_file(inode, filp); + nfs_fscache_set_inode_cookie(inode, filp); err = 0; out_put_ctx: diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c index 4e7f05d..2288cd3 100644 --- a/fs/nfs/nfs4namespace.c +++ b/fs/nfs/nfs4namespace.c @@ -137,7 +137,6 @@ static size_t nfs_parse_server_name(char *string, size_t len, /** * nfs_find_best_sec - Find a security mechanism supported locally - * @server: NFS server struct * @flavors: List of security tuples returned by SECINFO procedure * * Return the pseudoflavor of the first security mechanism in @@ -146,8 +145,7 @@ static size_t nfs_parse_server_name(char *string, size_t len, * is searched in the order returned from the server, per RFC 3530 * recommendation. */ -static rpc_authflavor_t nfs_find_best_sec(struct nfs_server *server, - struct nfs4_secinfo_flavors *flavors) +rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors) { rpc_authflavor_t pseudoflavor; struct nfs4_secinfo4 *secinfo; @@ -162,19 +160,12 @@ static rpc_authflavor_t nfs_find_best_sec(struct nfs_server *server, case RPC_AUTH_GSS: pseudoflavor = rpcauth_get_pseudoflavor(secinfo->flavor, &secinfo->flavor_info); - /* make sure pseudoflavor matches sec= mount opt */ - if (pseudoflavor != RPC_AUTH_MAXFLAVOR && - nfs_auth_info_match(&server->auth_info, - pseudoflavor)) + if (pseudoflavor != RPC_AUTH_MAXFLAVOR) return pseudoflavor; break; } } - /* if there were any sec= options then nothing matched */ - if (server->auth_info.flavor_len > 0) - return -EPERM; - return RPC_AUTH_UNIX; } @@ -196,7 +187,7 @@ static rpc_authflavor_t nfs4_negotiate_security(struct inode *inode, struct qstr goto out; } - flavor = nfs_find_best_sec(NFS_SERVER(inode), flavors); + flavor = nfs_find_best_sec(flavors); out: put_page(page); @@ -292,7 +283,8 @@ static struct vfsmount *nfs_follow_referral(struct dentry *dentry, if (locations == NULL || locations->nlocations <= 0) goto out; - dprintk("%s: referral at %pd2\n", __func__, dentry); + dprintk("%s: referral at %s/%s\n", __func__, + dentry->d_parent->d_name.name, dentry->d_name.name); page = (char *) __get_free_page(GFP_USER); if (!page) @@ -356,8 +348,8 @@ static struct vfsmount *nfs_do_refmount(struct rpc_clnt *client, struct dentry * mnt = ERR_PTR(-ENOENT); parent = dget_parent(dentry); - dprintk("%s: getting locations for %pd2\n", - __func__, dentry); + dprintk("%s: getting locations for %s/%s\n", + __func__, parent->d_name.name, dentry->d_name.name); err = nfs4_proc_fs_locations(client, parent->d_inode, &dentry->d_name, fs_locations, page); dput(parent); @@ -398,7 +390,7 @@ struct vfsmount *nfs4_submount(struct nfs_server *server, struct dentry *dentry, if (client->cl_auth->au_flavor != flavor) flavor = client->cl_auth->au_flavor; - else { + else if (!(server->flags & NFS_MOUNT_SECFLAVOUR)) { rpc_authflavor_t new = nfs4_negotiate_security(dir, name); if ((int)new >= 0) flavor = new; @@ -408,104 +400,3 @@ out: rpc_shutdown_client(client); return mnt; } - -/* - * Try one location from the fs_locations array. - * - * Returns zero on success, or a negative errno value. - */ -static int nfs4_try_replacing_one_location(struct nfs_server *server, - char *page, char *page2, - const struct nfs4_fs_location *location) -{ - const size_t addr_bufsize = sizeof(struct sockaddr_storage); - struct sockaddr *sap; - unsigned int s; - size_t salen; - int error; - - sap = kmalloc(addr_bufsize, GFP_KERNEL); - if (sap == NULL) - return -ENOMEM; - - error = -ENOENT; - for (s = 0; s < location->nservers; s++) { - const struct nfs4_string *buf = &location->servers[s]; - char *hostname; - - if (buf->len <= 0 || buf->len > PAGE_SIZE) - continue; - - if (memchr(buf->data, IPV6_SCOPE_DELIMITER, buf->len) != NULL) - continue; - - salen = nfs_parse_server_name(buf->data, buf->len, - sap, addr_bufsize, server); - if (salen == 0) - continue; - rpc_set_port(sap, NFS_PORT); - - error = -ENOMEM; - hostname = kstrndup(buf->data, buf->len, GFP_KERNEL); - if (hostname == NULL) - break; - - error = nfs4_update_server(server, hostname, sap, salen); - kfree(hostname); - if (error == 0) - break; - } - - kfree(sap); - return error; -} - -/** - * nfs4_replace_transport - set up transport to destination server - * - * @server: export being migrated - * @locations: fs_locations array - * - * Returns zero on success, or a negative errno value. - * - * The client tries all the entries in the "locations" array, in the - * order returned by the server, until one works or the end of the - * array is reached. - */ -int nfs4_replace_transport(struct nfs_server *server, - const struct nfs4_fs_locations *locations) -{ - char *page = NULL, *page2 = NULL; - int loc, error; - - error = -ENOENT; - if (locations == NULL || locations->nlocations <= 0) - goto out; - - error = -ENOMEM; - page = (char *) __get_free_page(GFP_USER); - if (!page) - goto out; - page2 = (char *) __get_free_page(GFP_USER); - if (!page2) - goto out; - - for (loc = 0; loc < locations->nlocations; loc++) { - const struct nfs4_fs_location *location = - &locations->locations[loc]; - - if (location == NULL || location->nservers <= 0 || - location->rootpath.ncomponents == 0) - continue; - - error = nfs4_try_replacing_one_location(server, page, - page2, location); - if (error == 0) - break; - } - -out: - free_page((unsigned long)page); - free_page((unsigned long)page2); - return error; -} diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 15052b8..d53d678 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -105,6 +105,9 @@ nfs4_label_init_security(struct inode *dir, struct dentry *dentry, if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL) == 0) return NULL; + if (NFS_SERVER(dir)->nfs_client->cl_minorversion < 2) + return NULL; + err = security_dentry_init_security(dentry, sattr->ia_mode, &dentry->d_name, (void **)&label->label, &label->len); if (err == 0) @@ -381,14 +384,6 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc case -NFS4ERR_STALE_CLIENTID: nfs4_schedule_lease_recovery(clp); goto wait_on_recovery; - case -NFS4ERR_MOVED: - ret = nfs4_schedule_migration_recovery(server); - if (ret < 0) - break; - goto wait_on_recovery; - case -NFS4ERR_LEASE_MOVED: - nfs4_schedule_lease_moved_recovery(clp); - goto wait_on_recovery; #if defined(CONFIG_NFS_V4_1) case -NFS4ERR_BADSESSION: case -NFS4ERR_BADSLOT: @@ -436,8 +431,6 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc return nfs4_map_errors(ret); wait_on_recovery: ret = nfs4_wait_clnt_recover(clp); - if (test_bit(NFS_MIG_FAILED, &server->mig_status)) - return -EIO; if (ret == 0) exception->retry = 1; return ret; @@ -1325,24 +1318,31 @@ _nfs4_opendata_reclaim_to_nfs4_state(struct nfs4_opendata *data) int ret; if (!data->rpc_done) { - if (data->rpc_status) { - ret = data->rpc_status; - goto err; - } - /* cached opens have already been processed */ - goto update; + ret = data->rpc_status; + goto err; } + ret = -ESTALE; + if (!(data->f_attr.valid & NFS_ATTR_FATTR_TYPE) || + !(data->f_attr.valid & NFS_ATTR_FATTR_FILEID) || + !(data->f_attr.valid & NFS_ATTR_FATTR_CHANGE)) + goto err; + + ret = -ENOMEM; + state = nfs4_get_open_state(inode, data->owner); + if (state == NULL) + goto err; + ret = nfs_refresh_inode(inode, &data->f_attr); if (ret) goto err; + nfs_setsecurity(inode, &data->f_attr, data->f_label); + if (data->o_res.delegation_type != 0) nfs4_opendata_check_deleg(data, state); -update: update_open_stateid(state, &data->o_res.stateid, NULL, data->o_arg.fmode); - atomic_inc(&state->count); return state; err: @@ -1575,12 +1575,6 @@ static int nfs4_handle_delegation_recall_error(struct nfs_server *server, struct /* Don't recall a delegation if it was lost */ nfs4_schedule_lease_recovery(server->nfs_client); return -EAGAIN; - case -NFS4ERR_MOVED: - nfs4_schedule_migration_recovery(server); - return -EAGAIN; - case -NFS4ERR_LEASE_MOVED: - nfs4_schedule_lease_moved_recovery(server->nfs_client); - return -EAGAIN; case -NFS4ERR_DELEG_REVOKED: case -NFS4ERR_ADMIN_REVOKED: case -NFS4ERR_BAD_STATEID: @@ -2518,8 +2512,9 @@ static void nfs4_close_done(struct rpc_task *task, void *data) calldata->roc_barrier); nfs_set_open_stateid(state, &calldata->res.stateid, 0); renew_lease(server, calldata->timestamp); + nfs4_close_clear_stateid_flags(state, + calldata->arg.fmode); break; - case -NFS4ERR_ADMIN_REVOKED: case -NFS4ERR_STALE_STATEID: case -NFS4ERR_OLD_STATEID: case -NFS4ERR_BAD_STATEID: @@ -2527,13 +2522,9 @@ static void nfs4_close_done(struct rpc_task *task, void *data) if (calldata->arg.fmode == 0) break; default: - if (nfs4_async_handle_error(task, server, state) == -EAGAIN) { + if (nfs4_async_handle_error(task, server, state) == -EAGAIN) rpc_restart_call_prepare(task); - goto out_release; - } } - nfs4_close_clear_stateid_flags(state, calldata->arg.fmode); -out_release: nfs_release_seqid(calldata->arg.seqid); nfs_refresh_inode(calldata->inode, calldata->res.fattr); dprintk("%s: done, ret = %d!\n", __func__, task->tk_status); @@ -2706,10 +2697,6 @@ static void nfs4_close_context(struct nfs_open_context *ctx, int is_sync) nfs4_close_state(ctx->state, ctx->mode); } -#define FATTR4_WORD1_NFS40_MASK (2*FATTR4_WORD1_MOUNTED_ON_FILEID - 1UL) -#define FATTR4_WORD2_NFS41_MASK (2*FATTR4_WORD2_SUPPATTR_EXCLCREAT - 1UL) -#define FATTR4_WORD2_NFS42_MASK (2*FATTR4_WORD2_CHANGE_SECURITY_LABEL - 1UL) - static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle) { struct nfs4_server_caps_arg args = { @@ -2725,25 +2712,12 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); if (status == 0) { - /* Sanity check the server answers */ - switch (server->nfs_client->cl_minorversion) { - case 0: - res.attr_bitmask[1] &= FATTR4_WORD1_NFS40_MASK; - res.attr_bitmask[2] = 0; - break; - case 1: - res.attr_bitmask[2] &= FATTR4_WORD2_NFS41_MASK; - break; - case 2: - res.attr_bitmask[2] &= FATTR4_WORD2_NFS42_MASK; - } memcpy(server->attr_bitmask, res.attr_bitmask, sizeof(server->attr_bitmask)); server->caps &= ~(NFS_CAP_ACLS|NFS_CAP_HARDLINKS| NFS_CAP_SYMLINKS|NFS_CAP_FILEID| NFS_CAP_MODE|NFS_CAP_NLINK|NFS_CAP_OWNER| NFS_CAP_OWNER_GROUP|NFS_CAP_ATIME| - NFS_CAP_CTIME|NFS_CAP_MTIME| - NFS_CAP_SECURITY_LABEL); + NFS_CAP_CTIME|NFS_CAP_MTIME); if (res.attr_bitmask[0] & FATTR4_WORD0_ACL) server->caps |= NFS_CAP_ACLS; if (res.has_links != 0) @@ -2772,12 +2746,14 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f #endif memcpy(server->attr_bitmask_nl, res.attr_bitmask, sizeof(server->attr_bitmask)); - server->attr_bitmask_nl[2] &= ~FATTR4_WORD2_SECURITY_LABEL; + if (server->caps & NFS_CAP_SECURITY_LABEL) { + server->attr_bitmask_nl[2] &= ~FATTR4_WORD2_SECURITY_LABEL; + res.attr_bitmask[2] &= ~FATTR4_WORD2_SECURITY_LABEL; + } memcpy(server->cache_consistency_bitmask, res.attr_bitmask, sizeof(server->cache_consistency_bitmask)); server->cache_consistency_bitmask[0] &= FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE; server->cache_consistency_bitmask[1] &= FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY; - server->cache_consistency_bitmask[2] = 0; server->acl_bitmask = res.acl_bitmask; server->fh_expire_type = res.fh_expire_type; } @@ -2888,24 +2864,11 @@ static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, int status = -EPERM; size_t i; - if (server->auth_info.flavor_len > 0) { - /* try each flavor specified by user */ - for (i = 0; i < server->auth_info.flavor_len; i++) { - status = nfs4_lookup_root_sec(server, fhandle, info, - server->auth_info.flavors[i]); - if (status == -NFS4ERR_WRONGSEC || status == -EACCES) - continue; - break; - } - } else { - /* no flavors specified by user, try default list */ - for (i = 0; i < ARRAY_SIZE(flav_array); i++) { - status = nfs4_lookup_root_sec(server, fhandle, info, - flav_array[i]); - if (status == -NFS4ERR_WRONGSEC || status == -EACCES) - continue; - break; - } + for (i = 0; i < ARRAY_SIZE(flav_array); i++) { + status = nfs4_lookup_root_sec(server, fhandle, info, flav_array[i]); + if (status == -NFS4ERR_WRONGSEC || status == -EACCES) + continue; + break; } /* @@ -2947,6 +2910,9 @@ int nfs4_proc_get_rootfh(struct nfs_server *server, struct nfs_fh *fhandle, status = nfs4_lookup_root(server, fhandle, info); if (status != -NFS4ERR_WRONGSEC) break; + /* Did user force a 'sec=' mount option? */ + if (server->flags & NFS_MOUNT_SECFLAVOUR) + break; default: status = nfs4_do_find_root_sec(server, fhandle, info); } @@ -3015,16 +2981,11 @@ static int nfs4_get_referral(struct rpc_clnt *client, struct inode *dir, status = nfs4_proc_fs_locations(client, dir, name, locations, page); if (status != 0) goto out; - - /* - * If the fsid didn't change, this is a migration event, not a - * referral. Cause us to drop into the exception handler, which - * will kick off migration recovery. - */ + /* Make sure server returned a different fsid for the referral */ if (nfs_fsid_equal(&NFS_SERVER(dir)->fsid, &locations->fattr.fsid)) { dprintk("%s: server did not return a different fsid for" " a referral at %s\n", __func__, name->name); - status = -NFS4ERR_MOVED; + status = -EIO; goto out; } /* Fixup attributes for the nfs_lookup() call to nfs_fhget() */ @@ -3204,6 +3165,9 @@ static int nfs4_proc_lookup_common(struct rpc_clnt **clnt, struct inode *dir, err = -EPERM; if (client != *clnt) goto out; + /* No security negotiation if the user specified 'sec=' */ + if (NFS_SERVER(dir)->flags & NFS_MOUNT_SECFLAVOUR) + goto out; client = nfs4_create_sec_client(client, dir, name); if (IS_ERR(client)) return PTR_ERR(client); @@ -3774,8 +3738,9 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, }; int status; - dprintk("%s: dentry = %pd2, cookie = %Lu\n", __func__, - dentry, + dprintk("%s: dentry = %s/%s, cookie = %Lu\n", __func__, + dentry->d_parent->d_name.name, + dentry->d_name.name, (unsigned long long)cookie); nfs4_setup_readdir(cookie, NFS_I(dir)->cookieverf, dentry, &args); res.pgbase = args.pgbase; @@ -4256,13 +4221,7 @@ static void nfs4_renew_done(struct rpc_task *task, void *calldata) unsigned long timestamp = data->timestamp; trace_nfs4_renew_async(clp, task->tk_status); - switch (task->tk_status) { - case 0: - break; - case -NFS4ERR_LEASE_MOVED: - nfs4_schedule_lease_moved_recovery(clp); - break; - default: + if (task->tk_status < 0) { /* Unless we're shutting down, schedule state recovery! */ if (test_bit(NFS_CS_RENEWD, &clp->cl_res_state) == 0) return; @@ -4616,7 +4575,7 @@ static int _nfs4_get_security_label(struct inode *inode, void *buf, struct nfs4_label label = {0, 0, buflen, buf}; u32 bitmask[3] = { 0, 0, FATTR4_WORD2_SECURITY_LABEL }; - struct nfs4_getattr_arg arg = { + struct nfs4_getattr_arg args = { .fh = NFS_FH(inode), .bitmask = bitmask, }; @@ -4627,14 +4586,14 @@ static int _nfs4_get_security_label(struct inode *inode, void *buf, }; struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETATTR], - .rpc_argp = &arg, + .rpc_argp = &args, .rpc_resp = &res, }; int ret; nfs_fattr_init(&fattr); - ret = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 0); + ret = rpc_call_sync(server->client, &msg, 0); if (ret) return ret; if (!(fattr.valid & NFS_ATTR_FATTR_V4_SECURITY_LABEL)) @@ -4671,7 +4630,7 @@ static int _nfs4_do_set_security_label(struct inode *inode, struct iattr sattr = {0}; struct nfs_server *server = NFS_SERVER(inode); const u32 bitmask[3] = { 0, 0, FATTR4_WORD2_SECURITY_LABEL }; - struct nfs_setattrargs arg = { + struct nfs_setattrargs args = { .fh = NFS_FH(inode), .iap = &sattr, .server = server, @@ -4685,14 +4644,14 @@ static int _nfs4_do_set_security_label(struct inode *inode, }; struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETATTR], - .rpc_argp = &arg, + .rpc_argp = &args, .rpc_resp = &res, }; int status; - nfs4_stateid_copy(&arg.stateid, &zero_stateid); + nfs4_stateid_copy(&args.stateid, &zero_stateid); - status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); + status = rpc_call_sync(server->client, &msg, 0); if (status) dprintk("%s failed: %d\n", __func__, status); @@ -4776,24 +4735,17 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, if (state == NULL) break; if (nfs4_schedule_stateid_recovery(server, state) < 0) - goto recovery_failed; + goto stateid_invalid; goto wait_on_recovery; case -NFS4ERR_EXPIRED: if (state != NULL) { if (nfs4_schedule_stateid_recovery(server, state) < 0) - goto recovery_failed; + goto stateid_invalid; } case -NFS4ERR_STALE_STATEID: case -NFS4ERR_STALE_CLIENTID: nfs4_schedule_lease_recovery(clp); goto wait_on_recovery; - case -NFS4ERR_MOVED: - if (nfs4_schedule_migration_recovery(server) < 0) - goto recovery_failed; - goto wait_on_recovery; - case -NFS4ERR_LEASE_MOVED: - nfs4_schedule_lease_moved_recovery(clp); - goto wait_on_recovery; #if defined(CONFIG_NFS_V4_1) case -NFS4ERR_BADSESSION: case -NFS4ERR_BADSLOT: @@ -4805,28 +4757,29 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, dprintk("%s ERROR %d, Reset session\n", __func__, task->tk_status); nfs4_schedule_session_recovery(clp->cl_session, task->tk_status); - goto wait_on_recovery; + task->tk_status = 0; + return -EAGAIN; #endif /* CONFIG_NFS_V4_1 */ case -NFS4ERR_DELAY: nfs_inc_server_stats(server, NFSIOS_DELAY); case -NFS4ERR_GRACE: rpc_delay(task, NFS4_POLL_RETRY_MAX); + task->tk_status = 0; + return -EAGAIN; case -NFS4ERR_RETRY_UNCACHED_REP: case -NFS4ERR_OLD_STATEID: - goto restart_call; + task->tk_status = 0; + return -EAGAIN; } task->tk_status = nfs4_map_errors(task->tk_status); return 0; -recovery_failed: +stateid_invalid: task->tk_status = -EIO; return 0; wait_on_recovery: rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL); if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0) rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task); - if (test_bit(NFS_MIG_FAILED, &server->mig_status)) - goto recovery_failed; -restart_call: task->tk_status = 0; return -EAGAIN; } @@ -4990,16 +4943,10 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata) trace_nfs4_delegreturn_exit(&data->args, &data->res, task->tk_status); switch (task->tk_status) { - case 0: - renew_lease(data->res.server, data->timestamp); - break; - case -NFS4ERR_ADMIN_REVOKED: - case -NFS4ERR_DELEG_REVOKED: - case -NFS4ERR_BAD_STATEID: - case -NFS4ERR_OLD_STATEID: case -NFS4ERR_STALE_STATEID: case -NFS4ERR_EXPIRED: - task->tk_status = 0; + case 0: + renew_lease(data->res.server, data->timestamp); break; default: if (nfs4_async_handle_error(task, data->res.server, NULL) == @@ -5159,7 +5106,6 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock status = 0; } request->fl_ops->fl_release_private(request); - request->fl_ops = NULL; out: return status; } @@ -5833,7 +5779,6 @@ struct nfs_release_lockowner_data { struct nfs_release_lockowner_args args; struct nfs4_sequence_args seq_args; struct nfs4_sequence_res seq_res; - unsigned long timestamp; }; static void nfs4_release_lockowner_prepare(struct rpc_task *task, void *calldata) @@ -5841,27 +5786,12 @@ static void nfs4_release_lockowner_prepare(struct rpc_task *task, void *calldata struct nfs_release_lockowner_data *data = calldata; nfs40_setup_sequence(data->server, &data->seq_args, &data->seq_res, task); - data->timestamp = jiffies; } static void nfs4_release_lockowner_done(struct rpc_task *task, void *calldata) { struct nfs_release_lockowner_data *data = calldata; - struct nfs_server *server = data->server; - nfs40_sequence_done(task, &data->seq_res); - - switch (task->tk_status) { - case 0: - renew_lease(server, data->timestamp); - break; - case -NFS4ERR_STALE_CLIENTID: - case -NFS4ERR_EXPIRED: - case -NFS4ERR_LEASE_MOVED: - case -NFS4ERR_DELAY: - if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) - rpc_restart_call_prepare(task); - } } static void nfs4_release_lockowner_release(void *calldata) @@ -6060,283 +5990,6 @@ int nfs4_proc_fs_locations(struct rpc_clnt *client, struct inode *dir, return err; } -/* - * This operation also signals the server that this client is - * performing migration recovery. The server can stop returning - * NFS4ERR_LEASE_MOVED to this client. A RENEW operation is - * appended to this compound to identify the client ID which is - * performing recovery. - */ -static int _nfs40_proc_get_locations(struct inode *inode, - struct nfs4_fs_locations *locations, - struct page *page, struct rpc_cred *cred) -{ - struct nfs_server *server = NFS_SERVER(inode); - struct rpc_clnt *clnt = server->client; - u32 bitmask[2] = { - [0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS, - }; - struct nfs4_fs_locations_arg args = { - .clientid = server->nfs_client->cl_clientid, - .fh = NFS_FH(inode), - .page = page, - .bitmask = bitmask, - .migration = 1, /* skip LOOKUP */ - .renew = 1, /* append RENEW */ - }; - struct nfs4_fs_locations_res res = { - .fs_locations = locations, - .migration = 1, - .renew = 1, - }; - struct rpc_message msg = { - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FS_LOCATIONS], - .rpc_argp = &args, - .rpc_resp = &res, - .rpc_cred = cred, - }; - unsigned long now = jiffies; - int status; - - nfs_fattr_init(&locations->fattr); - locations->server = server; - locations->nlocations = 0; - - nfs4_init_sequence(&args.seq_args, &res.seq_res, 0); - nfs4_set_sequence_privileged(&args.seq_args); - status = nfs4_call_sync_sequence(clnt, server, &msg, - &args.seq_args, &res.seq_res); - if (status) - return status; - - renew_lease(server, now); - return 0; -} - -#ifdef CONFIG_NFS_V4_1 - -/* - * This operation also signals the server that this client is - * performing migration recovery. The server can stop asserting - * SEQ4_STATUS_LEASE_MOVED for this client. The client ID - * performing this operation is identified in the SEQUENCE - * operation in this compound. - * - * When the client supports GETATTR(fs_locations_info), it can - * be plumbed in here. - */ -static int _nfs41_proc_get_locations(struct inode *inode, - struct nfs4_fs_locations *locations, - struct page *page, struct rpc_cred *cred) -{ - struct nfs_server *server = NFS_SERVER(inode); - struct rpc_clnt *clnt = server->client; - u32 bitmask[2] = { - [0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS, - }; - struct nfs4_fs_locations_arg args = { - .fh = NFS_FH(inode), - .page = page, - .bitmask = bitmask, - .migration = 1, /* skip LOOKUP */ - }; - struct nfs4_fs_locations_res res = { - .fs_locations = locations, - .migration = 1, - }; - struct rpc_message msg = { - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FS_LOCATIONS], - .rpc_argp = &args, - .rpc_resp = &res, - .rpc_cred = cred, - }; - int status; - - nfs_fattr_init(&locations->fattr); - locations->server = server; - locations->nlocations = 0; - - nfs4_init_sequence(&args.seq_args, &res.seq_res, 0); - nfs4_set_sequence_privileged(&args.seq_args); - status = nfs4_call_sync_sequence(clnt, server, &msg, - &args.seq_args, &res.seq_res); - if (status == NFS4_OK && - res.seq_res.sr_status_flags & SEQ4_STATUS_LEASE_MOVED) - status = -NFS4ERR_LEASE_MOVED; - return status; -} - -#endif /* CONFIG_NFS_V4_1 */ - -/** - * nfs4_proc_get_locations - discover locations for a migrated FSID - * @inode: inode on FSID that is migrating - * @locations: result of query - * @page: buffer - * @cred: credential to use for this operation - * - * Returns NFS4_OK on success, a negative NFS4ERR status code if the - * operation failed, or a negative errno if a local error occurred. - * - * On success, "locations" is filled in, but if the server has - * no locations information, NFS_ATTR_FATTR_V4_LOCATIONS is not - * asserted. - * - * -NFS4ERR_LEASE_MOVED is returned if the server still has leases - * from this client that require migration recovery. - */ -int nfs4_proc_get_locations(struct inode *inode, - struct nfs4_fs_locations *locations, - struct page *page, struct rpc_cred *cred) -{ - struct nfs_server *server = NFS_SERVER(inode); - struct nfs_client *clp = server->nfs_client; - const struct nfs4_mig_recovery_ops *ops = - clp->cl_mvops->mig_recovery_ops; - struct nfs4_exception exception = { }; - int status; - - dprintk("%s: FSID %llx:%llx on \"%s\"\n", __func__, - (unsigned long long)server->fsid.major, - (unsigned long long)server->fsid.minor, - clp->cl_hostname); - nfs_display_fhandle(NFS_FH(inode), __func__); - - do { - status = ops->get_locations(inode, locations, page, cred); - if (status != -NFS4ERR_DELAY) - break; - nfs4_handle_exception(server, status, &exception); - } while (exception.retry); - return status; -} - -/* - * This operation also signals the server that this client is - * performing "lease moved" recovery. The server can stop - * returning NFS4ERR_LEASE_MOVED to this client. A RENEW operation - * is appended to this compound to identify the client ID which is - * performing recovery. - */ -static int _nfs40_proc_fsid_present(struct inode *inode, struct rpc_cred *cred) -{ - struct nfs_server *server = NFS_SERVER(inode); - struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; - struct rpc_clnt *clnt = server->client; - struct nfs4_fsid_present_arg args = { - .fh = NFS_FH(inode), - .clientid = clp->cl_clientid, - .renew = 1, /* append RENEW */ - }; - struct nfs4_fsid_present_res res = { - .renew = 1, - }; - struct rpc_message msg = { - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FSID_PRESENT], - .rpc_argp = &args, - .rpc_resp = &res, - .rpc_cred = cred, - }; - unsigned long now = jiffies; - int status; - - res.fh = nfs_alloc_fhandle(); - if (res.fh == NULL) - return -ENOMEM; - - nfs4_init_sequence(&args.seq_args, &res.seq_res, 0); - nfs4_set_sequence_privileged(&args.seq_args); - status = nfs4_call_sync_sequence(clnt, server, &msg, - &args.seq_args, &res.seq_res); - nfs_free_fhandle(res.fh); - if (status) - return status; - - do_renew_lease(clp, now); - return 0; -} - -#ifdef CONFIG_NFS_V4_1 - -/* - * This operation also signals the server that this client is - * performing "lease moved" recovery. The server can stop asserting - * SEQ4_STATUS_LEASE_MOVED for this client. The client ID performing - * this operation is identified in the SEQUENCE operation in this - * compound. - */ -static int _nfs41_proc_fsid_present(struct inode *inode, struct rpc_cred *cred) -{ - struct nfs_server *server = NFS_SERVER(inode); - struct rpc_clnt *clnt = server->client; - struct nfs4_fsid_present_arg args = { - .fh = NFS_FH(inode), - }; - struct nfs4_fsid_present_res res = { - }; - struct rpc_message msg = { - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FSID_PRESENT], - .rpc_argp = &args, - .rpc_resp = &res, - .rpc_cred = cred, - }; - int status; - - res.fh = nfs_alloc_fhandle(); - if (res.fh == NULL) - return -ENOMEM; - - nfs4_init_sequence(&args.seq_args, &res.seq_res, 0); - nfs4_set_sequence_privileged(&args.seq_args); - status = nfs4_call_sync_sequence(clnt, server, &msg, - &args.seq_args, &res.seq_res); - nfs_free_fhandle(res.fh); - if (status == NFS4_OK && - res.seq_res.sr_status_flags & SEQ4_STATUS_LEASE_MOVED) - status = -NFS4ERR_LEASE_MOVED; - return status; -} - -#endif /* CONFIG_NFS_V4_1 */ - -/** - * nfs4_proc_fsid_present - Is this FSID present or absent on server? - * @inode: inode on FSID to check - * @cred: credential to use for this operation - * - * Server indicates whether the FSID is present, moved, or not - * recognized. This operation is necessary to clear a LEASE_MOVED - * condition for this client ID. - * - * Returns NFS4_OK if the FSID is present on this server, - * -NFS4ERR_MOVED if the FSID is no longer present, a negative - * NFS4ERR code if some error occurred on the server, or a - * negative errno if a local failure occurred. - */ -int nfs4_proc_fsid_present(struct inode *inode, struct rpc_cred *cred) -{ - struct nfs_server *server = NFS_SERVER(inode); - struct nfs_client *clp = server->nfs_client; - const struct nfs4_mig_recovery_ops *ops = - clp->cl_mvops->mig_recovery_ops; - struct nfs4_exception exception = { }; - int status; - - dprintk("%s: FSID %llx:%llx on \"%s\"\n", __func__, - (unsigned long long)server->fsid.major, - (unsigned long long)server->fsid.minor, - clp->cl_hostname); - nfs_display_fhandle(NFS_FH(inode), __func__); - - do { - status = ops->fsid_present(inode, cred); - if (status != -NFS4ERR_DELAY) - break; - nfs4_handle_exception(server, status, &exception); - } while (exception.retry); - return status; -} - /** * If 'use_integrity' is true and the state managment nfs_client * cl_rpcclient is using krb5i/p, use the integrity protected cl_rpcclient @@ -6623,14 +6276,8 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred, struct nfs41_exchange_id_args args = { .verifier = &verifier, .client = clp, -#ifdef CONFIG_NFS_V4_1_MIGRATION - .flags = EXCHGID4_FLAG_SUPP_MOVED_REFER | - EXCHGID4_FLAG_BIND_PRINC_STATEID | - EXCHGID4_FLAG_SUPP_MOVED_MIGR, -#else .flags = EXCHGID4_FLAG_SUPP_MOVED_REFER | - EXCHGID4_FLAG_BIND_PRINC_STATEID, -#endif + EXCHGID4_FLAG_BIND_PRINC_STATEID, }; struct nfs41_exchange_id_res res = { 0 @@ -7598,14 +7245,7 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata) return; server = NFS_SERVER(lrp->args.inode); - switch (task->tk_status) { - default: - task->tk_status = 0; - case 0: - break; - case -NFS4ERR_DELAY: - if (nfs4_async_handle_error(task, server, NULL) != -EAGAIN) - break; + if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) { rpc_restart_call_prepare(task); return; } @@ -7976,9 +7616,6 @@ nfs41_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, break; } - if (!nfs_auth_info_match(&server->auth_info, flavor)) - flavor = RPC_AUTH_MAXFLAVOR; - if (flavor != RPC_AUTH_MAXFLAVOR) { err = nfs4_lookup_root_sec(server, fhandle, info, flavor); @@ -8250,18 +7887,6 @@ static const struct nfs4_state_maintenance_ops nfs41_state_renewal_ops = { }; #endif -static const struct nfs4_mig_recovery_ops nfs40_mig_recovery_ops = { - .get_locations = _nfs40_proc_get_locations, - .fsid_present = _nfs40_proc_fsid_present, -}; - -#if defined(CONFIG_NFS_V4_1) -static const struct nfs4_mig_recovery_ops nfs41_mig_recovery_ops = { - .get_locations = _nfs41_proc_get_locations, - .fsid_present = _nfs41_proc_fsid_present, -}; -#endif /* CONFIG_NFS_V4_1 */ - static const struct nfs4_minor_version_ops nfs_v4_0_minor_ops = { .minor_version = 0, .init_caps = NFS_CAP_READDIRPLUS @@ -8277,7 +7902,6 @@ static const struct nfs4_minor_version_ops nfs_v4_0_minor_ops = { .reboot_recovery_ops = &nfs40_reboot_recovery_ops, .nograce_recovery_ops = &nfs40_nograce_recovery_ops, .state_renewal_ops = &nfs40_state_renewal_ops, - .mig_recovery_ops = &nfs40_mig_recovery_ops, }; #if defined(CONFIG_NFS_V4_1) @@ -8298,7 +7922,6 @@ static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = { .reboot_recovery_ops = &nfs41_reboot_recovery_ops, .nograce_recovery_ops = &nfs41_nograce_recovery_ops, .state_renewal_ops = &nfs41_state_renewal_ops, - .mig_recovery_ops = &nfs41_mig_recovery_ops, }; #endif diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 059c01b..cc14cbb 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -239,12 +239,14 @@ static void nfs4_end_drain_session(struct nfs_client *clp) } } +#if defined(CONFIG_NFS_V4_1) + static int nfs4_drain_slot_tbl(struct nfs4_slot_table *tbl) { set_bit(NFS4_SLOT_TBL_DRAINING, &tbl->slot_tbl_state); spin_lock(&tbl->slot_tbl_lock); if (tbl->highest_used_slotid != NFS4_NO_SLOT) { - reinit_completion(&tbl->complete); + INIT_COMPLETION(tbl->complete); spin_unlock(&tbl->slot_tbl_lock); return wait_for_completion_interruptible(&tbl->complete); } @@ -268,8 +270,6 @@ static int nfs4_begin_drain_session(struct nfs_client *clp) return nfs4_drain_slot_tbl(&ses->fc_slot_table); } -#if defined(CONFIG_NFS_V4_1) - static int nfs41_setup_state_renewal(struct nfs_client *clp) { int status; @@ -1197,74 +1197,20 @@ void nfs4_schedule_lease_recovery(struct nfs_client *clp) } EXPORT_SYMBOL_GPL(nfs4_schedule_lease_recovery); -/** - * nfs4_schedule_migration_recovery - trigger migration recovery - * - * @server: FSID that is migrating - * - * Returns zero if recovery has started, otherwise a negative NFS4ERR - * value is returned. - */ -int nfs4_schedule_migration_recovery(const struct nfs_server *server) -{ - struct nfs_client *clp = server->nfs_client; - - if (server->fh_expire_type != NFS4_FH_PERSISTENT) { - pr_err("NFS: volatile file handles not supported (server %s)\n", - clp->cl_hostname); - return -NFS4ERR_IO; - } - - if (test_bit(NFS_MIG_FAILED, &server->mig_status)) - return -NFS4ERR_IO; - - dprintk("%s: scheduling migration recovery for (%llx:%llx) on %s\n", - __func__, - (unsigned long long)server->fsid.major, - (unsigned long long)server->fsid.minor, - clp->cl_hostname); - - set_bit(NFS_MIG_IN_TRANSITION, - &((struct nfs_server *)server)->mig_status); - set_bit(NFS4CLNT_MOVED, &clp->cl_state); - - nfs4_schedule_state_manager(clp); - return 0; -} -EXPORT_SYMBOL_GPL(nfs4_schedule_migration_recovery); - -/** - * nfs4_schedule_lease_moved_recovery - start lease-moved recovery - * - * @clp: server to check for moved leases - * - */ -void nfs4_schedule_lease_moved_recovery(struct nfs_client *clp) -{ - dprintk("%s: scheduling lease-moved recovery for client ID %llx on %s\n", - __func__, clp->cl_clientid, clp->cl_hostname); - - set_bit(NFS4CLNT_LEASE_MOVED, &clp->cl_state); - nfs4_schedule_state_manager(clp); -} -EXPORT_SYMBOL_GPL(nfs4_schedule_lease_moved_recovery); - int nfs4_wait_clnt_recover(struct nfs_client *clp) { int res; might_sleep(); - atomic_inc(&clp->cl_count); res = wait_on_bit(&clp->cl_state, NFS4CLNT_MANAGER_RUNNING, nfs_wait_bit_killable, TASK_KILLABLE); if (res) - goto out; + return res; + if (clp->cl_cons_state < 0) - res = clp->cl_cons_state; -out: - nfs_put_client(clp); - return res; + return clp->cl_cons_state; + return 0; } int nfs4_client_recover_expired_lease(struct nfs_client *clp) @@ -1429,8 +1375,8 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_ case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: goto out; default: - printk(KERN_ERR "NFS: %s: unhandled error %d\n", - __func__, status); + printk(KERN_ERR "NFS: %s: unhandled error %d. " + "Zeroing state\n", __func__, status); case -ENOMEM: case -NFS4ERR_DENIED: case -NFS4ERR_RECLAIM_BAD: @@ -1476,7 +1422,7 @@ restart: if (status >= 0) { status = nfs4_reclaim_locks(state, ops); if (status >= 0) { - if (!test_bit(NFS_DELEGATED_STATE, &state->flags)) { + if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0) { spin_lock(&state->state_lock); list_for_each_entry(lock, &state->lock_states, ls_locks) { if (!test_bit(NFS_LOCK_INITIALIZED, &lock->ls_flags)) @@ -1493,12 +1439,15 @@ restart: } switch (status) { default: - printk(KERN_ERR "NFS: %s: unhandled error %d\n", - __func__, status); + printk(KERN_ERR "NFS: %s: unhandled error %d. " + "Zeroing state\n", __func__, status); case -ENOENT: case -ENOMEM: case -ESTALE: - /* Open state on this file cannot be recovered */ + /* + * Open state on this file cannot be recovered + * All we can do is revert to using the zero stateid. + */ nfs4_state_mark_recovery_failed(state, status); break; case -EAGAIN: @@ -1679,6 +1628,7 @@ static int nfs4_recovery_handle_error(struct nfs_client *clp, int error) nfs4_state_end_reclaim_reboot(clp); break; case -NFS4ERR_STALE_CLIENTID: + case -NFS4ERR_LEASE_MOVED: set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); nfs4_state_clear_reclaim_reboot(clp); nfs4_state_start_reclaim_reboot(clp); @@ -1879,168 +1829,6 @@ static int nfs4_purge_lease(struct nfs_client *clp) return 0; } -/* - * Try remote migration of one FSID from a source server to a - * destination server. The source server provides a list of - * potential destinations. - * - * Returns zero or a negative NFS4ERR status code. - */ -static int nfs4_try_migration(struct nfs_server *server, struct rpc_cred *cred) -{ - struct nfs_client *clp = server->nfs_client; - struct nfs4_fs_locations *locations = NULL; - struct inode *inode; - struct page *page; - int status, result; - - dprintk("--> %s: FSID %llx:%llx on \"%s\"\n", __func__, - (unsigned long long)server->fsid.major, - (unsigned long long)server->fsid.minor, - clp->cl_hostname); - - result = 0; - page = alloc_page(GFP_KERNEL); - locations = kmalloc(sizeof(struct nfs4_fs_locations), GFP_KERNEL); - if (page == NULL || locations == NULL) { - dprintk("<-- %s: no memory\n", __func__); - goto out; - } - - inode = server->super->s_root->d_inode; - result = nfs4_proc_get_locations(inode, locations, page, cred); - if (result) { - dprintk("<-- %s: failed to retrieve fs_locations: %d\n", - __func__, result); - goto out; - } - - result = -NFS4ERR_NXIO; - if (!(locations->fattr.valid & NFS_ATTR_FATTR_V4_LOCATIONS)) { - dprintk("<-- %s: No fs_locations data, migration skipped\n", - __func__); - goto out; - } - - nfs4_begin_drain_session(clp); - - status = nfs4_replace_transport(server, locations); - if (status != 0) { - dprintk("<-- %s: failed to replace transport: %d\n", - __func__, status); - goto out; - } - - result = 0; - dprintk("<-- %s: migration succeeded\n", __func__); - -out: - if (page != NULL) - __free_page(page); - kfree(locations); - if (result) { - pr_err("NFS: migration recovery failed (server %s)\n", - clp->cl_hostname); - set_bit(NFS_MIG_FAILED, &server->mig_status); - } - return result; -} - -/* - * Returns zero or a negative NFS4ERR status code. - */ -static int nfs4_handle_migration(struct nfs_client *clp) -{ - const struct nfs4_state_maintenance_ops *ops = - clp->cl_mvops->state_renewal_ops; - struct nfs_server *server; - struct rpc_cred *cred; - - dprintk("%s: migration reported on \"%s\"\n", __func__, - clp->cl_hostname); - - spin_lock(&clp->cl_lock); - cred = ops->get_state_renewal_cred_locked(clp); - spin_unlock(&clp->cl_lock); - if (cred == NULL) - return -NFS4ERR_NOENT; - - clp->cl_mig_gen++; -restart: - rcu_read_lock(); - list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { - int status; - - if (server->mig_gen == clp->cl_mig_gen) - continue; - server->mig_gen = clp->cl_mig_gen; - - if (!test_and_clear_bit(NFS_MIG_IN_TRANSITION, - &server->mig_status)) - continue; - - rcu_read_unlock(); - status = nfs4_try_migration(server, cred); - if (status < 0) { - put_rpccred(cred); - return status; - } - goto restart; - } - rcu_read_unlock(); - put_rpccred(cred); - return 0; -} - -/* - * Test each nfs_server on the clp's cl_superblocks list to see - * if it's moved to another server. Stop when the server no longer - * returns NFS4ERR_LEASE_MOVED. - */ -static int nfs4_handle_lease_moved(struct nfs_client *clp) -{ - const struct nfs4_state_maintenance_ops *ops = - clp->cl_mvops->state_renewal_ops; - struct nfs_server *server; - struct rpc_cred *cred; - - dprintk("%s: lease moved reported on \"%s\"\n", __func__, - clp->cl_hostname); - - spin_lock(&clp->cl_lock); - cred = ops->get_state_renewal_cred_locked(clp); - spin_unlock(&clp->cl_lock); - if (cred == NULL) - return -NFS4ERR_NOENT; - - clp->cl_mig_gen++; -restart: - rcu_read_lock(); - list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { - struct inode *inode; - int status; - - if (server->mig_gen == clp->cl_mig_gen) - continue; - server->mig_gen = clp->cl_mig_gen; - - rcu_read_unlock(); - - inode = server->super->s_root->d_inode; - status = nfs4_proc_fsid_present(inode, cred); - if (status != -NFS4ERR_MOVED) - goto restart; /* wasn't this one */ - if (nfs4_try_migration(server, cred) == -NFS4ERR_LEASE_MOVED) - goto restart; /* there are more */ - goto out; - } - rcu_read_unlock(); - -out: - put_rpccred(cred); - return 0; -} - /** * nfs4_discover_server_trunking - Detect server IP address trunking * @@ -2093,15 +1881,10 @@ again: nfs4_root_machine_cred(clp); goto again; } - if (clnt->cl_auth->au_flavor == RPC_AUTH_UNIX) + if (i > 2) break; case -NFS4ERR_CLID_INUSE: case -NFS4ERR_WRONGSEC: - /* No point in retrying if we already used RPC_AUTH_UNIX */ - if (clnt->cl_auth->au_flavor == RPC_AUTH_UNIX) { - status = -EPERM; - break; - } clnt = rpc_clone_client_set_auth(clnt, RPC_AUTH_UNIX); if (IS_ERR(clnt)) { status = PTR_ERR(clnt); @@ -2234,10 +2017,9 @@ void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags) nfs41_handle_server_reboot(clp); if (flags & (SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED | SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED | - SEQ4_STATUS_ADMIN_STATE_REVOKED)) + SEQ4_STATUS_ADMIN_STATE_REVOKED | + SEQ4_STATUS_LEASE_MOVED)) nfs41_handle_state_revoked(clp); - if (flags & SEQ4_STATUS_LEASE_MOVED) - nfs4_schedule_lease_moved_recovery(clp); if (flags & SEQ4_STATUS_RECALLABLE_STATE_REVOKED) nfs41_handle_recallable_state_revoked(clp); if (flags & SEQ4_STATUS_BACKCHANNEL_FAULT) @@ -2375,20 +2157,7 @@ static void nfs4_state_manager(struct nfs_client *clp) status = nfs4_check_lease(clp); if (status < 0) goto out_error; - } - - if (test_and_clear_bit(NFS4CLNT_MOVED, &clp->cl_state)) { - section = "migration"; - status = nfs4_handle_migration(clp); - if (status < 0) - goto out_error; - } - - if (test_and_clear_bit(NFS4CLNT_LEASE_MOVED, &clp->cl_state)) { - section = "lease moved"; - status = nfs4_handle_lease_moved(clp); - if (status < 0) - goto out_error; + continue; } /* First recover reboot state... */ diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c index 65ab0a0..e26acdd 100644 --- a/fs/nfs/nfs4super.c +++ b/fs/nfs/nfs4super.c @@ -261,9 +261,9 @@ struct dentry *nfs4_try_mount(int flags, const char *dev_name, res = nfs_follow_remote_path(root_mnt, export_path); - dfprintk(MOUNT, "<-- nfs4_try_mount() = %d%s\n", - PTR_ERR_OR_ZERO(res), - IS_ERR(res) ? " [error]" : ""); + dfprintk(MOUNT, "<-- nfs4_try_mount() = %ld%s\n", + IS_ERR(res) ? PTR_ERR(res) : 0, + IS_ERR(res) ? " [error]" : ""); return res; } @@ -319,9 +319,9 @@ static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type, data->mnt_path = export_path; res = nfs_follow_remote_path(root_mnt, export_path); - dprintk("<-- nfs4_referral_mount() = %d%s\n", - PTR_ERR_OR_ZERO(res), - IS_ERR(res) ? " [error]" : ""); + dprintk("<-- nfs4_referral_mount() = %ld%s\n", + IS_ERR(res) ? PTR_ERR(res) : 0, + IS_ERR(res) ? " [error]" : ""); return res; } diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 5be2868..79210d2 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -105,8 +105,12 @@ static int nfs4_stat_to_errno(int); #ifdef CONFIG_NFS_V4_SECURITY_LABEL /* PI(4 bytes) + LFS(4 bytes) + 1(for null terminator?) + MAXLABELLEN */ #define nfs4_label_maxsz (4 + 4 + 1 + XDR_QUADLEN(NFS4_MAXLABELLEN)) +#define encode_readdir_space 24 +#define encode_readdir_bitmask_sz 3 #else #define nfs4_label_maxsz 0 +#define encode_readdir_space 20 +#define encode_readdir_bitmask_sz 2 #endif /* We support only one layout type per file system */ #define decode_mdsthreshold_maxsz (1 + 1 + nfs4_fattr_bitmap_maxsz + 1 + 8) @@ -591,13 +595,11 @@ static int nfs4_stat_to_errno(int); #define NFS4_enc_getattr_sz (compound_encode_hdr_maxsz + \ encode_sequence_maxsz + \ encode_putfh_maxsz + \ - encode_getattr_maxsz + \ - encode_renew_maxsz) + encode_getattr_maxsz) #define NFS4_dec_getattr_sz (compound_decode_hdr_maxsz + \ decode_sequence_maxsz + \ decode_putfh_maxsz + \ - decode_getattr_maxsz + \ - decode_renew_maxsz) + decode_getattr_maxsz) #define NFS4_enc_lookup_sz (compound_encode_hdr_maxsz + \ encode_sequence_maxsz + \ encode_putfh_maxsz + \ @@ -734,15 +736,13 @@ static int nfs4_stat_to_errno(int); encode_sequence_maxsz + \ encode_putfh_maxsz + \ encode_lookup_maxsz + \ - encode_fs_locations_maxsz + \ - encode_renew_maxsz) + encode_fs_locations_maxsz) #define NFS4_dec_fs_locations_sz \ (compound_decode_hdr_maxsz + \ decode_sequence_maxsz + \ decode_putfh_maxsz + \ decode_lookup_maxsz + \ - decode_fs_locations_maxsz + \ - decode_renew_maxsz) + decode_fs_locations_maxsz) #define NFS4_enc_secinfo_sz (compound_encode_hdr_maxsz + \ encode_sequence_maxsz + \ encode_putfh_maxsz + \ @@ -751,18 +751,6 @@ static int nfs4_stat_to_errno(int); decode_sequence_maxsz + \ decode_putfh_maxsz + \ decode_secinfo_maxsz) -#define NFS4_enc_fsid_present_sz \ - (compound_encode_hdr_maxsz + \ - encode_sequence_maxsz + \ - encode_putfh_maxsz + \ - encode_getfh_maxsz + \ - encode_renew_maxsz) -#define NFS4_dec_fsid_present_sz \ - (compound_decode_hdr_maxsz + \ - decode_sequence_maxsz + \ - decode_putfh_maxsz + \ - decode_getfh_maxsz + \ - decode_renew_maxsz) #if defined(CONFIG_NFS_V4_1) #define NFS4_enc_bind_conn_to_session_sz \ (compound_encode_hdr_maxsz + \ @@ -1577,8 +1565,6 @@ static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg }; uint32_t dircount = readdir->count >> 1; __be32 *p, verf[2]; - uint32_t attrlen = 0; - unsigned int i; if (readdir->plus) { attrs[0] |= FATTR4_WORD0_TYPE|FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE| @@ -1587,27 +1573,26 @@ static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg FATTR4_WORD1_OWNER_GROUP|FATTR4_WORD1_RAWDEV| FATTR4_WORD1_SPACE_USED|FATTR4_WORD1_TIME_ACCESS| FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY; - attrs[2] |= FATTR4_WORD2_SECURITY_LABEL; dircount >>= 1; } /* Use mounted_on_fileid only if the server supports it */ if (!(readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)) attrs[0] |= FATTR4_WORD0_FILEID; - for (i = 0; i < ARRAY_SIZE(attrs); i++) { - attrs[i] &= readdir->bitmask[i]; - if (attrs[i] != 0) - attrlen = i+1; - } encode_op_hdr(xdr, OP_READDIR, decode_readdir_maxsz, hdr); encode_uint64(xdr, readdir->cookie); encode_nfs4_verifier(xdr, &readdir->verifier); - p = reserve_space(xdr, 12 + (attrlen << 2)); + p = reserve_space(xdr, encode_readdir_space); *p++ = cpu_to_be32(dircount); *p++ = cpu_to_be32(readdir->count); - *p++ = cpu_to_be32(attrlen); - for (i = 0; i < attrlen; i++) - *p++ = cpu_to_be32(attrs[i]); + *p++ = cpu_to_be32(encode_readdir_bitmask_sz); + *p++ = cpu_to_be32(attrs[0] & readdir->bitmask[0]); + *p = cpu_to_be32(attrs[1] & readdir->bitmask[1]); + if (encode_readdir_bitmask_sz > 2) { + if (hdr->minorversion > 1) + attrs[2] |= FATTR4_WORD2_SECURITY_LABEL; + p++, *p++ = cpu_to_be32(attrs[2] & readdir->bitmask[2]); + } memcpy(verf, readdir->verifier.data, sizeof(verf)); dprintk("%s: cookie = %llu, verifier = %08x:%08x, bitmap = %08x:%08x:%08x\n", @@ -2702,20 +2687,11 @@ static void nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, encode_compound_hdr(xdr, req, &hdr); encode_sequence(xdr, &args->seq_args, &hdr); - if (args->migration) { - encode_putfh(xdr, args->fh, &hdr); - replen = hdr.replen; - encode_fs_locations(xdr, args->bitmask, &hdr); - if (args->renew) - encode_renew(xdr, args->clientid, &hdr); - } else { - encode_putfh(xdr, args->dir_fh, &hdr); - encode_lookup(xdr, args->name, &hdr); - replen = hdr.replen; - encode_fs_locations(xdr, args->bitmask, &hdr); - } + encode_putfh(xdr, args->dir_fh, &hdr); + encode_lookup(xdr, args->name, &hdr); + replen = hdr.replen; /* get the attribute into args->page */ + encode_fs_locations(xdr, args->bitmask, &hdr); - /* Set up reply kvec to capture returned fs_locations array. */ xdr_inline_pages(&req->rq_rcv_buf, replen << 2, &args->page, 0, PAGE_SIZE); encode_nops(&hdr); @@ -2739,26 +2715,6 @@ static void nfs4_xdr_enc_secinfo(struct rpc_rqst *req, encode_nops(&hdr); } -/* - * Encode FSID_PRESENT request - */ -static void nfs4_xdr_enc_fsid_present(struct rpc_rqst *req, - struct xdr_stream *xdr, - struct nfs4_fsid_present_arg *args) -{ - struct compound_hdr hdr = { - .minorversion = nfs4_xdr_minorversion(&args->seq_args), - }; - - encode_compound_hdr(xdr, req, &hdr); - encode_sequence(xdr, &args->seq_args, &hdr); - encode_putfh(xdr, args->fh, &hdr); - encode_getfh(xdr, &hdr); - if (args->renew) - encode_renew(xdr, args->clientid, &hdr); - encode_nops(&hdr); -} - #if defined(CONFIG_NFS_V4_1) /* * BIND_CONN_TO_SESSION request @@ -6868,26 +6824,13 @@ static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, status = decode_putfh(xdr); if (status) goto out; - if (res->migration) { - xdr_enter_page(xdr, PAGE_SIZE); - status = decode_getfattr_generic(xdr, - &res->fs_locations->fattr, - NULL, res->fs_locations, - NULL, res->fs_locations->server); - if (status) - goto out; - if (res->renew) - status = decode_renew(xdr); - } else { - status = decode_lookup(xdr); - if (status) - goto out; - xdr_enter_page(xdr, PAGE_SIZE); - status = decode_getfattr_generic(xdr, - &res->fs_locations->fattr, + status = decode_lookup(xdr); + if (status) + goto out; + xdr_enter_page(xdr, PAGE_SIZE); + status = decode_getfattr_generic(xdr, &res->fs_locations->fattr, NULL, res->fs_locations, NULL, res->fs_locations->server); - } out: return status; } @@ -6916,34 +6859,6 @@ out: return status; } -/* - * Decode FSID_PRESENT response - */ -static int nfs4_xdr_dec_fsid_present(struct rpc_rqst *rqstp, - struct xdr_stream *xdr, - struct nfs4_fsid_present_res *res) -{ - struct compound_hdr hdr; - int status; - - status = decode_compound_hdr(xdr, &hdr); - if (status) - goto out; - status = decode_sequence(xdr, &res->seq_res, rqstp); - if (status) - goto out; - status = decode_putfh(xdr); - if (status) - goto out; - status = decode_getfh(xdr, res->fh); - if (status) - goto out; - if (res->renew) - status = decode_renew(xdr); -out: - return status; -} - #if defined(CONFIG_NFS_V4_1) /* * Decode BIND_CONN_TO_SESSION response @@ -7458,7 +7373,6 @@ struct rpc_procinfo nfs4_procedures[] = { PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations), PROC(RELEASE_LOCKOWNER, enc_release_lockowner, dec_release_lockowner), PROC(SECINFO, enc_secinfo, dec_secinfo), - PROC(FSID_PRESENT, enc_fsid_present, dec_fsid_present), #if defined(CONFIG_NFS_V4_1) PROC(EXCHANGE_ID, enc_exchange_id, dec_exchange_id), PROC(CREATE_SESSION, enc_create_session, dec_create_session), diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index fddbba2..a8f57c7 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c @@ -235,7 +235,7 @@ nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, }; int status = -ENOMEM; - dprintk("NFS call create %pd\n", dentry); + dprintk("NFS call create %s\n", dentry->d_name.name); data = nfs_alloc_createdata(dir, dentry, sattr); if (data == NULL) goto out; @@ -265,7 +265,7 @@ nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, umode_t mode; int status = -ENOMEM; - dprintk("NFS call mknod %pd\n", dentry); + dprintk("NFS call mknod %s\n", dentry->d_name.name); mode = sattr->ia_mode; if (S_ISFIFO(mode)) { @@ -423,7 +423,7 @@ nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page, }; int status = -ENAMETOOLONG; - dprintk("NFS call symlink %pd\n", dentry); + dprintk("NFS call symlink %s\n", dentry->d_name.name); if (len > NFS2_MAXPATHLEN) goto out; @@ -462,7 +462,7 @@ nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr) }; int status = -ENOMEM; - dprintk("NFS call mkdir %pd\n", dentry); + dprintk("NFS call mkdir %s\n", dentry->d_name.name); data = nfs_alloc_createdata(dir, dentry, sattr); if (data == NULL) goto out; diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 910ed90..a03b9c6 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -497,8 +497,7 @@ static const char *nfs_pseudoflavour_to_name(rpc_authflavor_t flavour) static const struct { rpc_authflavor_t flavour; const char *str; - } sec_flavours[NFS_AUTH_INFO_MAX_FLAVORS] = { - /* update NFS_AUTH_INFO_MAX_FLAVORS when this list changes! */ + } sec_flavours[] = { { RPC_AUTH_NULL, "null" }, { RPC_AUTH_UNIX, "sys" }, { RPC_AUTH_GSS_KRB5, "krb5" }, @@ -924,7 +923,8 @@ static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(void) data->mount_server.port = NFS_UNSPEC_PORT; data->nfs_server.port = NFS_UNSPEC_PORT; data->nfs_server.protocol = XPRT_TRANSPORT_TCP; - data->selected_flavor = RPC_AUTH_MAXFLAVOR; + data->auth_flavors[0] = RPC_AUTH_MAXFLAVOR; + data->auth_flavor_len = 0; data->minorversion = 0; data->need_mount = true; data->net = current->nsproxy->net_ns; @@ -1019,51 +1019,12 @@ static void nfs_set_mount_transport_protocol(struct nfs_parsed_mount_data *mnt) } } -/* - * Add 'flavor' to 'auth_info' if not already present. - * Returns true if 'flavor' ends up in the list, false otherwise - */ -static bool nfs_auth_info_add(struct nfs_auth_info *auth_info, - rpc_authflavor_t flavor) -{ - unsigned int i; - unsigned int max_flavor_len = (sizeof(auth_info->flavors) / - sizeof(auth_info->flavors[0])); - - /* make sure this flavor isn't already in the list */ - for (i = 0; i < auth_info->flavor_len; i++) { - if (flavor == auth_info->flavors[i]) - return true; - } - - if (auth_info->flavor_len + 1 >= max_flavor_len) { - dfprintk(MOUNT, "NFS: too many sec= flavors\n"); - return false; - } - - auth_info->flavors[auth_info->flavor_len++] = flavor; - return true; -} - -/* - * Return true if 'match' is in auth_info or auth_info is empty. - * Return false otherwise. - */ -bool nfs_auth_info_match(const struct nfs_auth_info *auth_info, - rpc_authflavor_t match) +static void nfs_set_auth_parsed_mount_data(struct nfs_parsed_mount_data *data, + rpc_authflavor_t pseudoflavor) { - int i; - - if (!auth_info->flavor_len) - return true; - - for (i = 0; i < auth_info->flavor_len; i++) { - if (auth_info->flavors[i] == match) - return true; - } - return false; + data->auth_flavors[0] = pseudoflavor; + data->auth_flavor_len = 1; } -EXPORT_SYMBOL_GPL(nfs_auth_info_match); /* * Parse the value of the 'sec=' option. @@ -1073,55 +1034,49 @@ static int nfs_parse_security_flavors(char *value, { substring_t args[MAX_OPT_ARGS]; rpc_authflavor_t pseudoflavor; - char *p; dfprintk(MOUNT, "NFS: parsing sec=%s option\n", value); - while ((p = strsep(&value, ":")) != NULL) { - switch (match_token(p, nfs_secflavor_tokens, args)) { - case Opt_sec_none: - pseudoflavor = RPC_AUTH_NULL; - break; - case Opt_sec_sys: - pseudoflavor = RPC_AUTH_UNIX; - break; - case Opt_sec_krb5: - pseudoflavor = RPC_AUTH_GSS_KRB5; - break; - case Opt_sec_krb5i: - pseudoflavor = RPC_AUTH_GSS_KRB5I; - break; - case Opt_sec_krb5p: - pseudoflavor = RPC_AUTH_GSS_KRB5P; - break; - case Opt_sec_lkey: - pseudoflavor = RPC_AUTH_GSS_LKEY; - break; - case Opt_sec_lkeyi: - pseudoflavor = RPC_AUTH_GSS_LKEYI; - break; - case Opt_sec_lkeyp: - pseudoflavor = RPC_AUTH_GSS_LKEYP; - break; - case Opt_sec_spkm: - pseudoflavor = RPC_AUTH_GSS_SPKM; - break; - case Opt_sec_spkmi: - pseudoflavor = RPC_AUTH_GSS_SPKMI; - break; - case Opt_sec_spkmp: - pseudoflavor = RPC_AUTH_GSS_SPKMP; - break; - default: - dfprintk(MOUNT, - "NFS: sec= option '%s' not recognized\n", p); - return 0; - } - - if (!nfs_auth_info_add(&mnt->auth_info, pseudoflavor)) - return 0; + switch (match_token(value, nfs_secflavor_tokens, args)) { + case Opt_sec_none: + pseudoflavor = RPC_AUTH_NULL; + break; + case Opt_sec_sys: + pseudoflavor = RPC_AUTH_UNIX; + break; + case Opt_sec_krb5: + pseudoflavor = RPC_AUTH_GSS_KRB5; + break; + case Opt_sec_krb5i: + pseudoflavor = RPC_AUTH_GSS_KRB5I; + break; + case Opt_sec_krb5p: + pseudoflavor = RPC_AUTH_GSS_KRB5P; + break; + case Opt_sec_lkey: + pseudoflavor = RPC_AUTH_GSS_LKEY; + break; + case Opt_sec_lkeyi: + pseudoflavor = RPC_AUTH_GSS_LKEYI; + break; + case Opt_sec_lkeyp: + pseudoflavor = RPC_AUTH_GSS_LKEYP; + break; + case Opt_sec_spkm: + pseudoflavor = RPC_AUTH_GSS_SPKM; + break; + case Opt_sec_spkmi: + pseudoflavor = RPC_AUTH_GSS_SPKMI; + break; + case Opt_sec_spkmp: + pseudoflavor = RPC_AUTH_GSS_SPKMP; + break; + default: + return 0; } + mnt->flags |= NFS_MOUNT_SECFLAVOUR; + nfs_set_auth_parsed_mount_data(mnt, pseudoflavor); return 1; } @@ -1614,7 +1569,7 @@ static int nfs_parse_mount_options(char *raw, goto out_minorversion_mismatch; if (mnt->options & NFS_OPTION_MIGRATION && - (mnt->version != 4 || mnt->minorversion != 0)) + mnt->version != 4 && mnt->minorversion != 0) goto out_migration_misuse; /* @@ -1668,14 +1623,12 @@ out_security_failure: } /* - * Ensure that a specified authtype in args->auth_info is supported by - * the server. Returns 0 and sets args->selected_flavor if it's ok, and - * -EACCES if not. + * Ensure that the specified authtype in args->auth_flavors[0] is supported by + * the server. Returns 0 if it's ok, and -EACCES if not. */ -static int nfs_verify_authflavors(struct nfs_parsed_mount_data *args, +static int nfs_verify_authflavor(struct nfs_parsed_mount_data *args, rpc_authflavor_t *server_authlist, unsigned int count) { - rpc_authflavor_t flavor = RPC_AUTH_MAXFLAVOR; unsigned int i; /* @@ -1687,20 +1640,17 @@ static int nfs_verify_authflavors(struct nfs_parsed_mount_data *args, * can be used. */ for (i = 0; i < count; i++) { - flavor = server_authlist[i]; - - if (nfs_auth_info_match(&args->auth_info, flavor) || - flavor == RPC_AUTH_NULL) + if (args->auth_flavors[0] == server_authlist[i] || + server_authlist[i] == RPC_AUTH_NULL) goto out; } - dfprintk(MOUNT, - "NFS: specified auth flavors not supported by server\n"); + dfprintk(MOUNT, "NFS: auth flavor %u not supported by server\n", + args->auth_flavors[0]); return -EACCES; out: - args->selected_flavor = flavor; - dfprintk(MOUNT, "NFS: using auth flavor %u\n", args->selected_flavor); + dfprintk(MOUNT, "NFS: using auth flavor %u\n", args->auth_flavors[0]); return 0; } @@ -1788,10 +1738,9 @@ static struct nfs_server *nfs_try_mount_request(struct nfs_mount_info *mount_inf * Was a sec= authflavor specified in the options? First, verify * whether the server supports it, and then just try to use it if so. */ - if (args->auth_info.flavor_len > 0) { - status = nfs_verify_authflavors(args, authlist, authlist_len); - dfprintk(MOUNT, "NFS: using auth flavor %u\n", - args->selected_flavor); + if (args->auth_flavor_len > 0) { + status = nfs_verify_authflavor(args, authlist, authlist_len); + dfprintk(MOUNT, "NFS: using auth flavor %u\n", args->auth_flavors[0]); if (status) return ERR_PTR(status); return nfs_mod->rpc_ops->create_server(mount_info, nfs_mod); @@ -1820,7 +1769,7 @@ static struct nfs_server *nfs_try_mount_request(struct nfs_mount_info *mount_inf /* Fallthrough */ } dfprintk(MOUNT, "NFS: attempting to use auth flavor %u\n", flavor); - args->selected_flavor = flavor; + nfs_set_auth_parsed_mount_data(args, flavor); server = nfs_mod->rpc_ops->create_server(mount_info, nfs_mod); if (!IS_ERR(server)) return server; @@ -1836,7 +1785,7 @@ static struct nfs_server *nfs_try_mount_request(struct nfs_mount_info *mount_inf /* Last chance! Try AUTH_UNIX */ dfprintk(MOUNT, "NFS: attempting to use auth flavor %u\n", RPC_AUTH_UNIX); - args->selected_flavor = RPC_AUTH_UNIX; + nfs_set_auth_parsed_mount_data(args, RPC_AUTH_UNIX); return nfs_mod->rpc_ops->create_server(mount_info, nfs_mod); } @@ -2023,9 +1972,9 @@ static int nfs23_validate_mount_data(void *options, args->bsize = data->bsize; if (data->flags & NFS_MOUNT_SECFLAVOUR) - args->selected_flavor = data->pseudoflavor; + nfs_set_auth_parsed_mount_data(args, data->pseudoflavor); else - args->selected_flavor = RPC_AUTH_UNIX; + nfs_set_auth_parsed_mount_data(args, RPC_AUTH_UNIX); if (!args->nfs_server.hostname) goto out_nomem; @@ -2159,6 +2108,9 @@ static int nfs_validate_text_mount_data(void *options, nfs_set_port(sap, &args->nfs_server.port, port); + if (args->auth_flavor_len > 1) + goto out_bad_auth; + return nfs_parse_devname(dev_name, &args->nfs_server.hostname, max_namelen, @@ -2178,6 +2130,10 @@ out_invalid_transport_udp: out_no_address: dfprintk(MOUNT, "NFS: mount program didn't pass remote address\n"); return -EINVAL; + +out_bad_auth: + dfprintk(MOUNT, "NFS: Too many RPC auth flavours specified\n"); + return -EINVAL; } static int @@ -2187,10 +2143,8 @@ nfs_compare_remount_data(struct nfs_server *nfss, if (data->flags != nfss->flags || data->rsize != nfss->rsize || data->wsize != nfss->wsize || - data->version != nfss->nfs_client->rpc_ops->version || - data->minorversion != nfss->nfs_client->cl_minorversion || data->retrans != nfss->client->cl_timeout->to_retries || - data->selected_flavor != nfss->client->cl_auth->au_flavor || + data->auth_flavors[0] != nfss->client->cl_auth->au_flavor || data->acregmin != nfss->acregmin / HZ || data->acregmax != nfss->acregmax / HZ || data->acdirmin != nfss->acdirmin / HZ || @@ -2235,8 +2189,7 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data) data->rsize = nfss->rsize; data->wsize = nfss->wsize; data->retrans = nfss->client->cl_timeout->to_retries; - data->selected_flavor = nfss->client->cl_auth->au_flavor; - data->auth_info = nfss->auth_info; + nfs_set_auth_parsed_mount_data(data, nfss->client->cl_auth->au_flavor); data->acregmin = nfss->acregmin / HZ; data->acregmax = nfss->acregmax / HZ; data->acdirmin = nfss->acdirmin / HZ; @@ -2244,14 +2197,12 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data) data->timeo = 10U * nfss->client->cl_timeout->to_initval / HZ; data->nfs_server.port = nfss->port; data->nfs_server.addrlen = nfss->nfs_client->cl_addrlen; - data->version = nfsvers; - data->minorversion = nfss->nfs_client->cl_minorversion; memcpy(&data->nfs_server.address, &nfss->nfs_client->cl_addr, data->nfs_server.addrlen); /* overwrite those values with any that were specified */ - error = -EINVAL; - if (!nfs_parse_mount_options((char *)options, data)) + error = nfs_parse_mount_options((char *)options, data); + if (error < 0) goto out; /* @@ -2381,7 +2332,7 @@ static int nfs_compare_mount_options(const struct super_block *s, const struct n goto Ebusy; if (a->acdirmax != b->acdirmax) goto Ebusy; - if (b->auth_info.flavor_len > 0 && + if (b->flags & NFS_MOUNT_SECFLAVOUR && clnt_a->cl_auth->au_flavor != clnt_b->cl_auth->au_flavor) goto Ebusy; return 1; @@ -2579,7 +2530,6 @@ struct dentry *nfs_fs_mount_common(struct nfs_server *server, mntroot = ERR_PTR(error); goto error_splat_bdi; } - server->super = s; } if (!s->s_root) { @@ -2763,9 +2713,9 @@ static int nfs4_validate_mount_data(void *options, data->auth_flavours, sizeof(pseudoflavor))) return -EFAULT; - args->selected_flavor = pseudoflavor; + nfs_set_auth_parsed_mount_data(args, pseudoflavor); } else - args->selected_flavor = RPC_AUTH_UNIX; + nfs_set_auth_parsed_mount_data(args, RPC_AUTH_UNIX); c = strndup_user(data->hostname.data, NFS4_MAXNAMLEN); if (IS_ERR(c)) diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c index 11d7894..bb939ed 100644 --- a/fs/nfs/unlink.c +++ b/fs/nfs/unlink.c @@ -493,15 +493,17 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry) unsigned long long fileid; struct dentry *sdentry; struct rpc_task *task; - int error = -EBUSY; + int error = -EIO; - dfprintk(VFS, "NFS: silly-rename(%pd2, ct=%d)\n", - dentry, d_count(dentry)); + dfprintk(VFS, "NFS: silly-rename(%s/%s, ct=%d)\n", + dentry->d_parent->d_name.name, dentry->d_name.name, + d_count(dentry)); nfs_inc_stats(dir, NFSIOS_SILLYRENAME); /* * We don't allow a dentry to be silly-renamed twice. */ + error = -EBUSY; if (dentry->d_flags & DCACHE_NFSFS_RENAMED) goto out; @@ -520,8 +522,8 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry) SILLYNAME_FILEID_LEN, fileid, SILLYNAME_COUNTER_LEN, sillycounter); - dfprintk(VFS, "NFS: trying to rename %pd to %s\n", - dentry, silly); + dfprintk(VFS, "NFS: trying to rename %s to %s\n", + dentry->d_name.name, silly); sdentry = lookup_one_len(silly, dentry->d_parent, slen); /* diff --git a/fs/nfs/write.c b/fs/nfs/write.c index c1d5482..ac1dc33 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -954,8 +954,10 @@ int nfs_updatepage(struct file *file, struct page *page, nfs_inc_stats(inode, NFSIOS_VFSUPDATEPAGE); - dprintk("NFS: nfs_updatepage(%pD2 %d@%lld)\n", - file, count, (long long)(page_file_offset(page) + offset)); + dprintk("NFS: nfs_updatepage(%s/%s %d@%lld)\n", + file->f_path.dentry->d_parent->d_name.name, + file->f_path.dentry->d_name.name, count, + (long long)(page_file_offset(page) + offset)); if (nfs_can_extend_write(file, page, inode)) { count = max(count + offset, nfs_page_length(page)); |