summaryrefslogtreecommitdiff
path: root/fs/nfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/Kconfig17
-rw-r--r--fs/nfs/blocklayout/blocklayout.h1
-rw-r--r--fs/nfs/blocklayout/extents.c2
-rw-r--r--fs/nfs/callback.c3
-rw-r--r--fs/nfs/client.c10
-rw-r--r--fs/nfs/dir.c129
-rw-r--r--fs/nfs/direct.c17
-rw-r--r--fs/nfs/dns_resolve.c2
-rw-r--r--fs/nfs/file.c117
-rw-r--r--fs/nfs/fscache.c202
-rw-r--r--fs/nfs/fscache.h18
-rw-r--r--fs/nfs/inode.c18
-rw-r--r--fs/nfs/internal.h23
-rw-r--r--fs/nfs/namespace.c5
-rw-r--r--fs/nfs/nfs3proc.c8
-rw-r--r--fs/nfs/nfs4_fs.h25
-rw-r--r--fs/nfs/nfs4client.c138
-rw-r--r--fs/nfs/nfs4file.c6
-rw-r--r--fs/nfs/nfs4namespace.c125
-rw-r--r--fs/nfs/nfs4proc.c503
-rw-r--r--fs/nfs/nfs4state.c273
-rw-r--r--fs/nfs/nfs4super.c12
-rw-r--r--fs/nfs/nfs4xdr.c138
-rw-r--r--fs/nfs/proc.c8
-rw-r--r--fs/nfs/super.c200
-rw-r--r--fs/nfs/unlink.c12
-rw-r--r--fs/nfs/write.c6
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));