mirror of
https://github.com/a52xq-dev/kernel.git
synced 2026-10-18 21:58:11 +07:00
NFS client updates for Linux 4.13
Stable bugfixes: - Fix -EACCESS on commit to DS handling - Fix initialization of nfs_page_array->npages - Only invalidate dentries that are actually invalid Features: - Enable NFSoRDMA transparent state migration - Add support for lookup-by-filehandle - Add support for nfs re-exporting Other bugfixes and cleanups: - Christoph cleaned up the way we declare NFS operations - Clean up various internal structures - Various cleanups to commits - Various improvements to error handling - Set the dt_type of . and .. entries in NFS v4 - Make slot allocation more reliable - Fix fscache stat printing - Fix uninitialized variable warnings - Fix potential list overrun in nfs_atomic_open() - Fix a race in NFSoRDMA RPC reply handler - Fix return size for nfs42_proc_copy() - Fix against MAC forgery timing attacks -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEnZ5MQTpR7cLU7KEp18tUv7ClQOsFAlln4jEACgkQ18tUv7Cl QOv2ZxAAwbQN9Dtx4rOZmPe0Xszua23sNN0ja891PodkCjIiZrRelZhLIBAf1rfP uSR+jTD8EsBHGt3bzTXg2DHz+o8cGDZuH+uuZX+wRWJPQcKA2pC7zElqnse8nmn5 4Z1UUdzf42vE4NZ/G1ucqpEiAmOqGJ3s7pCRLLXPvOSSQXqOhiomNDAcGxX05FIv Ly4Kr6RIfg/O4oNOZBuuL/tZHodeyOj1vbyjt/4bDQ5MEXlUQfcjJZEsz/2EcNh6 rAgbquxr1pGCD072pPBwYNH2vLGbgNN41KDDMGI0clp+8p6EhV6BOlgcEoGtZM86 c0yro2oBOB2vPCv9nGr6JgTOHPKG6ksJ7vWVXrtQEjBGP82AbFfAawLgqZ6Ae8dP Sqpx55j4xdm4nyNglCuhq5PlPAogARq/eibR+RbY973Lhzr5bZb3XqlairCkNNEv 4RbTlxbWjhgrKJ56jVf+KpUDJAVG5viKMD7YDx/bOfLtvPwALbozD7ONrunz5v43 PgQEvWvVtnQAKp27pqHemTsLFhU6M6eGUEctRnAfB/0ogWZh1X8QXgulpDlqG3kb g12kr5hfA0pSfcB0aGXVzJNnHKfW3IY3WBWtxq4xaMY22YkHtuB+78+9/yk3jCAi dvimjT2Ko9fE9MnltJ/hC5BU+T+xUxg+1vfwWnKMvMH8SIqjyu4= =OpLj -----END PGP SIGNATURE----- Merge tag 'nfs-for-4.13-1' of git://git.linux-nfs.org/projects/anna/linux-nfs Pull NFS client updates from Anna Schumaker: "Stable bugfixes: - Fix -EACCESS on commit to DS handling - Fix initialization of nfs_page_array->npages - Only invalidate dentries that are actually invalid Features: - Enable NFSoRDMA transparent state migration - Add support for lookup-by-filehandle - Add support for nfs re-exporting Other bugfixes and cleanups: - Christoph cleaned up the way we declare NFS operations - Clean up various internal structures - Various cleanups to commits - Various improvements to error handling - Set the dt_type of . and .. entries in NFS v4 - Make slot allocation more reliable - Fix fscache stat printing - Fix uninitialized variable warnings - Fix potential list overrun in nfs_atomic_open() - Fix a race in NFSoRDMA RPC reply handler - Fix return size for nfs42_proc_copy() - Fix against MAC forgery timing attacks" * tag 'nfs-for-4.13-1' of git://git.linux-nfs.org/projects/anna/linux-nfs: (68 commits) NFS: Don't run wake_up_bit() when nobody is waiting... nfs: add export operations nfs4: add NFSv4 LOOKUPP handlers nfs: add a nfs_ilookup helper nfs: replace d_add with d_splice_alias in atomic_open sunrpc: use constant time memory comparison for mac NFSv4.2 fix size storage for nfs42_proc_copy xprtrdma: Fix documenting comments in frwr_ops.c xprtrdma: Replace PAGE_MASK with offset_in_page() xprtrdma: FMR does not need list_del_init() xprtrdma: Demote "connect" log messages NFSv4.1: Use seqid returned by EXCHANGE_ID after state migration NFSv4.1: Handle EXCHGID4_FLAG_CONFIRMED_R during NFSv4.1 migration xprtrdma: Don't defer MR recovery if ro_map fails xprtrdma: Fix FRWR invalidation error recovery xprtrdma: Fix client lock-up after application signal fires xprtrdma: Rename rpcrdma_req::rl_free xprtrdma: Pass only the list of registered MRs to ro_unmap_sync xprtrdma: Pre-mark remotely invalidated MRs xprtrdma: On invalidation failure, remove MWs from rl_registered ...
This commit is contained in:
commit
b86faee6d1
35 changed files with 777 additions and 289 deletions
|
|
@ -7,7 +7,7 @@ obj-$(CONFIG_NFS_FS) += nfs.o
|
|||
CFLAGS_nfstrace.o += -I$(src)
|
||||
nfs-y := client.o dir.o file.o getroot.o inode.o super.o \
|
||||
io.o direct.o pagelist.o read.o symlink.o unlink.o \
|
||||
write.o namespace.o mount_clnt.o nfstrace.o
|
||||
write.o namespace.o mount_clnt.o nfstrace.o export.o
|
||||
nfs-$(CONFIG_ROOT_NFS) += nfsroot.o
|
||||
nfs-$(CONFIG_SYSCTL) += sysctl.o
|
||||
nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o
|
||||
|
|
|
|||
42
fs/nfs/dir.c
42
fs/nfs/dir.c
|
|
@ -151,7 +151,7 @@ struct nfs_cache_array {
|
|||
struct nfs_cache_array_entry array[0];
|
||||
};
|
||||
|
||||
typedef int (*decode_dirent_t)(struct xdr_stream *, struct nfs_entry *, int);
|
||||
typedef int (*decode_dirent_t)(struct xdr_stream *, struct nfs_entry *, bool);
|
||||
typedef struct {
|
||||
struct file *file;
|
||||
struct page *page;
|
||||
|
|
@ -165,8 +165,8 @@ typedef struct {
|
|||
unsigned long timestamp;
|
||||
unsigned long gencount;
|
||||
unsigned int cache_entry_index;
|
||||
unsigned int plus:1;
|
||||
unsigned int eof:1;
|
||||
bool plus;
|
||||
bool eof;
|
||||
} nfs_readdir_descriptor_t;
|
||||
|
||||
/*
|
||||
|
|
@ -355,7 +355,7 @@ int nfs_readdir_xdr_filler(struct page **pages, nfs_readdir_descriptor_t *desc,
|
|||
if (error == -ENOTSUPP && desc->plus) {
|
||||
NFS_SERVER(inode)->caps &= ~NFS_CAP_READDIRPLUS;
|
||||
clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags);
|
||||
desc->plus = 0;
|
||||
desc->plus = false;
|
||||
goto again;
|
||||
}
|
||||
goto error;
|
||||
|
|
@ -557,7 +557,7 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en
|
|||
|
||||
count++;
|
||||
|
||||
if (desc->plus != 0)
|
||||
if (desc->plus)
|
||||
nfs_prime_dcache(file_dentry(desc->file), entry);
|
||||
|
||||
status = nfs_readdir_add_to_array(entry, page);
|
||||
|
|
@ -860,7 +860,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
|
|||
desc->ctx = ctx;
|
||||
desc->dir_cookie = &dir_ctx->dir_cookie;
|
||||
desc->decode = NFS_PROTO(inode)->decode_dirent;
|
||||
desc->plus = nfs_use_readdirplus(inode, ctx) ? 1 : 0;
|
||||
desc->plus = nfs_use_readdirplus(inode, ctx);
|
||||
|
||||
if (ctx->pos == 0 || nfs_attribute_cache_expired(inode))
|
||||
res = nfs_revalidate_mapping(inode, file->f_mapping);
|
||||
|
|
@ -885,8 +885,8 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
|
|||
clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags);
|
||||
nfs_zap_caches(inode);
|
||||
desc->page_index = 0;
|
||||
desc->plus = 0;
|
||||
desc->eof = 0;
|
||||
desc->plus = false;
|
||||
desc->eof = false;
|
||||
continue;
|
||||
}
|
||||
if (res < 0)
|
||||
|
|
@ -1115,11 +1115,13 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
|
|||
/* Force a full look up iff the parent directory has changed */
|
||||
if (!nfs_is_exclusive_create(dir, flags) &&
|
||||
nfs_check_verifier(dir, dentry, flags & LOOKUP_RCU)) {
|
||||
|
||||
if (nfs_lookup_verify_inode(inode, flags)) {
|
||||
error = nfs_lookup_verify_inode(inode, flags);
|
||||
if (error) {
|
||||
if (flags & LOOKUP_RCU)
|
||||
return -ECHILD;
|
||||
goto out_zap_parent;
|
||||
if (error == -ESTALE)
|
||||
goto out_zap_parent;
|
||||
goto out_error;
|
||||
}
|
||||
nfs_advise_use_readdirplus(dir);
|
||||
goto out_valid;
|
||||
|
|
@ -1144,8 +1146,10 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
|
|||
trace_nfs_lookup_revalidate_enter(dir, dentry, flags);
|
||||
error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label);
|
||||
trace_nfs_lookup_revalidate_exit(dir, dentry, flags, error);
|
||||
if (error)
|
||||
if (error == -ESTALE || error == -ENOENT)
|
||||
goto out_bad;
|
||||
if (error)
|
||||
goto out_error;
|
||||
if (nfs_compare_fh(NFS_FH(inode), fhandle))
|
||||
goto out_bad;
|
||||
if ((error = nfs_refresh_inode(inode, fattr)) != 0)
|
||||
|
|
@ -1427,8 +1431,10 @@ static int nfs_finish_open(struct nfs_open_context *ctx,
|
|||
err = finish_open(file, dentry, do_open, opened);
|
||||
if (err)
|
||||
goto out;
|
||||
nfs_file_set_open_context(file, ctx);
|
||||
|
||||
if (S_ISREG(file->f_path.dentry->d_inode->i_mode))
|
||||
nfs_file_set_open_context(file, ctx);
|
||||
else
|
||||
err = -ESTALE;
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
|
@ -1512,7 +1518,7 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
|
|||
d_drop(dentry);
|
||||
switch (err) {
|
||||
case -ENOENT:
|
||||
d_add(dentry, NULL);
|
||||
d_splice_alias(NULL, dentry);
|
||||
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
|
||||
break;
|
||||
case -EISDIR:
|
||||
|
|
@ -2035,7 +2041,11 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|||
}
|
||||
|
||||
error = rpc_wait_for_completion_task(task);
|
||||
if (error == 0)
|
||||
if (error != 0) {
|
||||
((struct nfs_renamedata *)task->tk_calldata)->cancelled = 1;
|
||||
/* Paired with the atomic_dec_and_test() barrier in rpc_do_put_task() */
|
||||
smp_wmb();
|
||||
} else
|
||||
error = task->tk_status;
|
||||
rpc_put_task(task);
|
||||
nfs_mark_for_revalidate(old_inode);
|
||||
|
|
|
|||
177
fs/nfs/export.c
Normal file
177
fs/nfs/export.c
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Primary Data, Inc. All rights reserved.
|
||||
*
|
||||
* Tao Peng <bergwolf@primarydata.com>
|
||||
*/
|
||||
#include <linux/dcache.h>
|
||||
#include <linux/exportfs.h>
|
||||
#include <linux/nfs.h>
|
||||
#include <linux/nfs_fs.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "nfstrace.h"
|
||||
|
||||
#define NFSDBG_FACILITY NFSDBG_VFS
|
||||
|
||||
enum {
|
||||
FILEID_HIGH_OFF = 0, /* inode fileid high */
|
||||
FILEID_LOW_OFF, /* inode fileid low */
|
||||
FILE_I_TYPE_OFF, /* inode type */
|
||||
EMBED_FH_OFF /* embeded server fh */
|
||||
};
|
||||
|
||||
|
||||
static struct nfs_fh *nfs_exp_embedfh(__u32 *p)
|
||||
{
|
||||
return (struct nfs_fh *)(p + EMBED_FH_OFF);
|
||||
}
|
||||
|
||||
/*
|
||||
* Let's break subtree checking for now... otherwise we'll have to embed parent fh
|
||||
* but there might not be enough space.
|
||||
*/
|
||||
static int
|
||||
nfs_encode_fh(struct inode *inode, __u32 *p, int *max_len, struct inode *parent)
|
||||
{
|
||||
struct nfs_fh *server_fh = NFS_FH(inode);
|
||||
struct nfs_fh *clnt_fh = nfs_exp_embedfh(p);
|
||||
size_t fh_size = offsetof(struct nfs_fh, data) + server_fh->size;
|
||||
int len = EMBED_FH_OFF + XDR_QUADLEN(fh_size);
|
||||
|
||||
dprintk("%s: max fh len %d inode %p parent %p",
|
||||
__func__, *max_len, inode, parent);
|
||||
|
||||
if (*max_len < len || IS_AUTOMOUNT(inode)) {
|
||||
dprintk("%s: fh len %d too small, required %d\n",
|
||||
__func__, *max_len, len);
|
||||
*max_len = len;
|
||||
return FILEID_INVALID;
|
||||
}
|
||||
if (IS_AUTOMOUNT(inode)) {
|
||||
*max_len = FILEID_INVALID;
|
||||
goto out;
|
||||
}
|
||||
|
||||
p[FILEID_HIGH_OFF] = NFS_FILEID(inode) >> 32;
|
||||
p[FILEID_LOW_OFF] = NFS_FILEID(inode);
|
||||
p[FILE_I_TYPE_OFF] = inode->i_mode & S_IFMT;
|
||||
p[len - 1] = 0; /* Padding */
|
||||
nfs_copy_fh(clnt_fh, server_fh);
|
||||
*max_len = len;
|
||||
out:
|
||||
dprintk("%s: result fh fileid %llu mode %u size %d\n",
|
||||
__func__, NFS_FILEID(inode), inode->i_mode, *max_len);
|
||||
return *max_len;
|
||||
}
|
||||
|
||||
static struct dentry *
|
||||
nfs_fh_to_dentry(struct super_block *sb, struct fid *fid,
|
||||
int fh_len, int fh_type)
|
||||
{
|
||||
struct nfs4_label *label = NULL;
|
||||
struct nfs_fattr *fattr = NULL;
|
||||
struct nfs_fh *server_fh = nfs_exp_embedfh(fid->raw);
|
||||
size_t fh_size = offsetof(struct nfs_fh, data) + server_fh->size;
|
||||
const struct nfs_rpc_ops *rpc_ops;
|
||||
struct dentry *dentry;
|
||||
struct inode *inode;
|
||||
int len = EMBED_FH_OFF + XDR_QUADLEN(fh_size);
|
||||
u32 *p = fid->raw;
|
||||
int ret;
|
||||
|
||||
/* NULL translates to ESTALE */
|
||||
if (fh_len < len || fh_type != len)
|
||||
return NULL;
|
||||
|
||||
fattr = nfs_alloc_fattr();
|
||||
if (fattr == NULL) {
|
||||
dentry = ERR_PTR(-ENOMEM);
|
||||
goto out;
|
||||
}
|
||||
|
||||
fattr->fileid = ((u64)p[FILEID_HIGH_OFF] << 32) + p[FILEID_LOW_OFF];
|
||||
fattr->mode = p[FILE_I_TYPE_OFF];
|
||||
fattr->valid |= NFS_ATTR_FATTR_FILEID | NFS_ATTR_FATTR_TYPE;
|
||||
|
||||
dprintk("%s: fileid %llu mode %d\n", __func__, fattr->fileid, fattr->mode);
|
||||
|
||||
inode = nfs_ilookup(sb, fattr, server_fh);
|
||||
if (inode)
|
||||
goto out_found;
|
||||
|
||||
label = nfs4_label_alloc(NFS_SB(sb), GFP_KERNEL);
|
||||
if (IS_ERR(label)) {
|
||||
dentry = ERR_CAST(label);
|
||||
goto out_free_fattr;
|
||||
}
|
||||
|
||||
rpc_ops = NFS_SB(sb)->nfs_client->rpc_ops;
|
||||
ret = rpc_ops->getattr(NFS_SB(sb), server_fh, fattr, label);
|
||||
if (ret) {
|
||||
dprintk("%s: getattr failed %d\n", __func__, ret);
|
||||
dentry = ERR_PTR(ret);
|
||||
goto out_free_label;
|
||||
}
|
||||
|
||||
inode = nfs_fhget(sb, server_fh, fattr, label);
|
||||
|
||||
out_found:
|
||||
dentry = d_obtain_alias(inode);
|
||||
|
||||
out_free_label:
|
||||
nfs4_label_free(label);
|
||||
out_free_fattr:
|
||||
nfs_free_fattr(fattr);
|
||||
out:
|
||||
return dentry;
|
||||
}
|
||||
|
||||
static struct dentry *
|
||||
nfs_get_parent(struct dentry *dentry)
|
||||
{
|
||||
int ret;
|
||||
struct inode *inode = d_inode(dentry), *pinode;
|
||||
struct super_block *sb = inode->i_sb;
|
||||
struct nfs_server *server = NFS_SB(sb);
|
||||
struct nfs_fattr *fattr = NULL;
|
||||
struct nfs4_label *label = NULL;
|
||||
struct dentry *parent;
|
||||
struct nfs_rpc_ops const *ops = server->nfs_client->rpc_ops;
|
||||
struct nfs_fh fh;
|
||||
|
||||
if (!ops->lookupp)
|
||||
return ERR_PTR(-EACCES);
|
||||
|
||||
fattr = nfs_alloc_fattr();
|
||||
if (fattr == NULL) {
|
||||
parent = ERR_PTR(-ENOMEM);
|
||||
goto out;
|
||||
}
|
||||
|
||||
label = nfs4_label_alloc(server, GFP_KERNEL);
|
||||
if (IS_ERR(label)) {
|
||||
parent = ERR_CAST(label);
|
||||
goto out_free_fattr;
|
||||
}
|
||||
|
||||
ret = ops->lookupp(inode, &fh, fattr, label);
|
||||
if (ret) {
|
||||
parent = ERR_PTR(ret);
|
||||
goto out_free_label;
|
||||
}
|
||||
|
||||
pinode = nfs_fhget(sb, &fh, fattr, label);
|
||||
parent = d_obtain_alias(pinode);
|
||||
out_free_label:
|
||||
nfs4_label_free(label);
|
||||
out_free_fattr:
|
||||
nfs_free_fattr(fattr);
|
||||
out:
|
||||
return parent;
|
||||
}
|
||||
|
||||
const struct export_operations nfs_export_ops = {
|
||||
.encode_fh = nfs_encode_fh,
|
||||
.fh_to_dentry = nfs_fh_to_dentry,
|
||||
.get_parent = nfs_get_parent,
|
||||
};
|
||||
|
|
@ -126,32 +126,13 @@ static int filelayout_async_handle_error(struct rpc_task *task,
|
|||
{
|
||||
struct pnfs_layout_hdr *lo = lseg->pls_layout;
|
||||
struct inode *inode = lo->plh_inode;
|
||||
struct nfs_server *mds_server = NFS_SERVER(inode);
|
||||
struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg);
|
||||
struct nfs_client *mds_client = mds_server->nfs_client;
|
||||
struct nfs4_slot_table *tbl = &clp->cl_session->fc_slot_table;
|
||||
|
||||
if (task->tk_status >= 0)
|
||||
return 0;
|
||||
|
||||
switch (task->tk_status) {
|
||||
/* MDS state errors */
|
||||
case -NFS4ERR_DELEG_REVOKED:
|
||||
case -NFS4ERR_ADMIN_REVOKED:
|
||||
case -NFS4ERR_BAD_STATEID:
|
||||
case -NFS4ERR_OPENMODE:
|
||||
if (state == NULL)
|
||||
break;
|
||||
if (nfs4_schedule_stateid_recovery(mds_server, state) < 0)
|
||||
goto out_bad_stateid;
|
||||
goto wait_on_recovery;
|
||||
case -NFS4ERR_EXPIRED:
|
||||
if (state != NULL) {
|
||||
if (nfs4_schedule_stateid_recovery(mds_server, state) < 0)
|
||||
goto out_bad_stateid;
|
||||
}
|
||||
nfs4_schedule_lease_recovery(mds_client);
|
||||
goto wait_on_recovery;
|
||||
/* DS session errors */
|
||||
case -NFS4ERR_BADSESSION:
|
||||
case -NFS4ERR_BADSLOT:
|
||||
|
|
@ -172,6 +153,7 @@ static int filelayout_async_handle_error(struct rpc_task *task,
|
|||
case -NFS4ERR_RETRY_UNCACHED_REP:
|
||||
break;
|
||||
/* Invalidate Layout errors */
|
||||
case -NFS4ERR_ACCESS:
|
||||
case -NFS4ERR_PNFS_NO_LAYOUT:
|
||||
case -ESTALE: /* mapped NFS4ERR_STALE */
|
||||
case -EBADHANDLE: /* mapped NFS4ERR_BADHANDLE */
|
||||
|
|
@ -202,26 +184,17 @@ static int filelayout_async_handle_error(struct rpc_task *task,
|
|||
task->tk_status);
|
||||
nfs4_mark_deviceid_unavailable(devid);
|
||||
pnfs_error_mark_layout_for_return(inode, lseg);
|
||||
pnfs_set_lo_fail(lseg);
|
||||
rpc_wake_up(&tbl->slot_tbl_waitq);
|
||||
/* fall through */
|
||||
default:
|
||||
pnfs_set_lo_fail(lseg);
|
||||
reset:
|
||||
dprintk("%s Retry through MDS. Error %d\n", __func__,
|
||||
task->tk_status);
|
||||
return -NFS4ERR_RESET_TO_MDS;
|
||||
}
|
||||
out:
|
||||
task->tk_status = 0;
|
||||
return -EAGAIN;
|
||||
out_bad_stateid:
|
||||
task->tk_status = -EIO;
|
||||
return 0;
|
||||
wait_on_recovery:
|
||||
rpc_sleep_on(&mds_client->cl_rpcwaitq, task, NULL);
|
||||
if (test_bit(NFS4CLNT_MANAGER_RUNNING, &mds_client->cl_state) == 0)
|
||||
rpc_wake_up_queued_task(&mds_client->cl_rpcwaitq, task);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* NFS_PROTO call done callback routines */
|
||||
|
|
|
|||
|
|
@ -1050,34 +1050,10 @@ static int ff_layout_async_handle_error_v4(struct rpc_task *task,
|
|||
{
|
||||
struct pnfs_layout_hdr *lo = lseg->pls_layout;
|
||||
struct inode *inode = lo->plh_inode;
|
||||
struct nfs_server *mds_server = NFS_SERVER(inode);
|
||||
|
||||
struct nfs4_deviceid_node *devid = FF_LAYOUT_DEVID_NODE(lseg, idx);
|
||||
struct nfs_client *mds_client = mds_server->nfs_client;
|
||||
struct nfs4_slot_table *tbl = &clp->cl_session->fc_slot_table;
|
||||
|
||||
switch (task->tk_status) {
|
||||
/* MDS state errors */
|
||||
case -NFS4ERR_DELEG_REVOKED:
|
||||
case -NFS4ERR_ADMIN_REVOKED:
|
||||
case -NFS4ERR_BAD_STATEID:
|
||||
if (state == NULL)
|
||||
break;
|
||||
nfs_remove_bad_delegation(state->inode, NULL);
|
||||
case -NFS4ERR_OPENMODE:
|
||||
if (state == NULL)
|
||||
break;
|
||||
if (nfs4_schedule_stateid_recovery(mds_server, state) < 0)
|
||||
goto out_bad_stateid;
|
||||
goto wait_on_recovery;
|
||||
case -NFS4ERR_EXPIRED:
|
||||
if (state != NULL) {
|
||||
if (nfs4_schedule_stateid_recovery(mds_server, state) < 0)
|
||||
goto out_bad_stateid;
|
||||
}
|
||||
nfs4_schedule_lease_recovery(mds_client);
|
||||
goto wait_on_recovery;
|
||||
/* DS session errors */
|
||||
case -NFS4ERR_BADSESSION:
|
||||
case -NFS4ERR_BADSLOT:
|
||||
case -NFS4ERR_BAD_HIGH_SLOT:
|
||||
|
|
@ -1137,17 +1113,8 @@ reset:
|
|||
task->tk_status);
|
||||
return -NFS4ERR_RESET_TO_MDS;
|
||||
}
|
||||
out:
|
||||
task->tk_status = 0;
|
||||
return -EAGAIN;
|
||||
out_bad_stateid:
|
||||
task->tk_status = -EIO;
|
||||
return 0;
|
||||
wait_on_recovery:
|
||||
rpc_sleep_on(&mds_client->cl_rpcwaitq, task, NULL);
|
||||
if (test_bit(NFS4CLNT_MANAGER_RUNNING, &mds_client->cl_state) == 0)
|
||||
rpc_wake_up_queued_task(&mds_client->cl_rpcwaitq, task);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Retry all errors through either pNFS or MDS except for -EJUKEBOX */
|
||||
|
|
|
|||
|
|
@ -386,6 +386,28 @@ void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr,
|
|||
#endif
|
||||
EXPORT_SYMBOL_GPL(nfs_setsecurity);
|
||||
|
||||
/* Search for inode identified by fh, fileid and i_mode in inode cache. */
|
||||
struct inode *
|
||||
nfs_ilookup(struct super_block *sb, struct nfs_fattr *fattr, struct nfs_fh *fh)
|
||||
{
|
||||
struct nfs_find_desc desc = {
|
||||
.fh = fh,
|
||||
.fattr = fattr,
|
||||
};
|
||||
struct inode *inode;
|
||||
unsigned long hash;
|
||||
|
||||
if (!(fattr->valid & NFS_ATTR_FATTR_FILEID) ||
|
||||
!(fattr->valid & NFS_ATTR_FATTR_TYPE))
|
||||
return NULL;
|
||||
|
||||
hash = nfs_fattr_to_ino_t(fattr);
|
||||
inode = ilookup5(sb, hash, nfs_find_actor, &desc);
|
||||
|
||||
dprintk("%s: returning %p\n", __func__, inode);
|
||||
return inode;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is our front-end to iget that looks up inodes by file handle
|
||||
* instead of inode number.
|
||||
|
|
@ -525,8 +547,14 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st
|
|||
nfs_fscache_init_inode(inode);
|
||||
|
||||
unlock_new_inode(inode);
|
||||
} else
|
||||
nfs_refresh_inode(inode, fattr);
|
||||
} else {
|
||||
int err = nfs_refresh_inode(inode, fattr);
|
||||
if (err < 0) {
|
||||
iput(inode);
|
||||
inode = ERR_PTR(err);
|
||||
goto out_no_inode;
|
||||
}
|
||||
}
|
||||
dprintk("NFS: nfs_fhget(%s/%Lu fh_crc=0x%08x ct=%d)\n",
|
||||
inode->i_sb->s_id,
|
||||
(unsigned long long)NFS_FILEID(inode),
|
||||
|
|
@ -1315,9 +1343,9 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat
|
|||
return 0;
|
||||
/* Has the inode gone and changed behind our back? */
|
||||
if ((fattr->valid & NFS_ATTR_FATTR_FILEID) && nfsi->fileid != fattr->fileid)
|
||||
return -EIO;
|
||||
return -ESTALE;
|
||||
if ((fattr->valid & NFS_ATTR_FATTR_TYPE) && (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT))
|
||||
return -EIO;
|
||||
return -ESTALE;
|
||||
|
||||
if (!nfs_file_has_buffered_writers(nfsi)) {
|
||||
/* Verify a few of the more important attributes */
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
#define NFS_MS_MASK (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_SYNCHRONOUS)
|
||||
|
||||
extern const struct export_operations nfs_export_ops;
|
||||
|
||||
struct nfs_string;
|
||||
|
||||
/* Maximum number of readahead requests
|
||||
|
|
@ -273,17 +275,17 @@ static inline bool nfs_match_open_context(const struct nfs_open_context *ctx1,
|
|||
/* nfs2xdr.c */
|
||||
extern const struct rpc_procinfo nfs_procedures[];
|
||||
extern int nfs2_decode_dirent(struct xdr_stream *,
|
||||
struct nfs_entry *, int);
|
||||
struct nfs_entry *, bool);
|
||||
|
||||
/* nfs3xdr.c */
|
||||
extern const struct rpc_procinfo nfs3_procedures[];
|
||||
extern int nfs3_decode_dirent(struct xdr_stream *,
|
||||
struct nfs_entry *, int);
|
||||
struct nfs_entry *, bool);
|
||||
|
||||
/* nfs4xdr.c */
|
||||
#if IS_ENABLED(CONFIG_NFS_V4)
|
||||
extern int nfs4_decode_dirent(struct xdr_stream *,
|
||||
struct nfs_entry *, int);
|
||||
struct nfs_entry *, bool);
|
||||
#endif
|
||||
#ifdef CONFIG_NFS_V4_1
|
||||
extern const u32 nfs41_maxread_overhead;
|
||||
|
|
|
|||
|
|
@ -939,7 +939,7 @@ static int nfs2_xdr_dec_writeres(struct rpc_rqst *req, struct xdr_stream *xdr,
|
|||
* };
|
||||
*/
|
||||
int nfs2_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
|
||||
int plus)
|
||||
bool plus)
|
||||
{
|
||||
__be32 *p;
|
||||
int error;
|
||||
|
|
|
|||
|
|
@ -621,7 +621,7 @@ out:
|
|||
*/
|
||||
static int
|
||||
nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
|
||||
u64 cookie, struct page **pages, unsigned int count, int plus)
|
||||
u64 cookie, struct page **pages, unsigned int count, bool plus)
|
||||
{
|
||||
struct inode *dir = d_inode(dentry);
|
||||
__be32 *verf = NFS_I(dir)->cookieverf;
|
||||
|
|
|
|||
|
|
@ -1991,7 +1991,7 @@ out_status:
|
|||
* };
|
||||
*/
|
||||
int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
|
||||
int plus)
|
||||
bool plus)
|
||||
{
|
||||
struct nfs_entry old = *entry;
|
||||
__be32 *p;
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ static ssize_t _nfs42_proc_copy(struct file *src,
|
|||
loff_t pos_src = args->src_pos;
|
||||
loff_t pos_dst = args->dst_pos;
|
||||
size_t count = args->count;
|
||||
int status;
|
||||
ssize_t status;
|
||||
|
||||
status = nfs4_set_rw_stateid(&args->src_stateid, src_lock->open_context,
|
||||
src_lock, FMODE_READ);
|
||||
|
|
|
|||
|
|
@ -414,6 +414,7 @@ struct nfs_client *nfs4_init_client(struct nfs_client *clp,
|
|||
if (clp != old)
|
||||
clp->cl_preserve_clid = true;
|
||||
nfs_put_client(clp);
|
||||
clear_bit(NFS_CS_TSM_POSSIBLE, &clp->cl_flags);
|
||||
return old;
|
||||
|
||||
error:
|
||||
|
|
@ -852,6 +853,8 @@ static int nfs4_set_client(struct nfs_server *server,
|
|||
set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags);
|
||||
if (server->options & NFS_OPTION_MIGRATION)
|
||||
set_bit(NFS_CS_MIGRATION, &cl_init.init_flags);
|
||||
if (test_bit(NFS_MIG_TSM_POSSIBLE, &server->mig_status))
|
||||
set_bit(NFS_CS_TSM_POSSIBLE, &cl_init.init_flags);
|
||||
|
||||
/* Allocate or find a client reference we can use */
|
||||
clp = nfs_get_client(&cl_init);
|
||||
|
|
@ -1212,9 +1215,11 @@ int nfs4_update_server(struct nfs_server *server, const char *hostname,
|
|||
return -EAFNOSUPPORT;
|
||||
|
||||
nfs_server_remove_lists(server);
|
||||
set_bit(NFS_MIG_TSM_POSSIBLE, &server->mig_status);
|
||||
error = nfs4_set_client(server, hostname, sap, salen, buf,
|
||||
clp->cl_proto, clnt->cl_timeout,
|
||||
clp->cl_minorversion, net);
|
||||
clear_bit(NFS_MIG_TSM_POSSIBLE, &server->mig_status);
|
||||
nfs_put_client(clp);
|
||||
if (error != 0) {
|
||||
nfs_server_insert_lists(server);
|
||||
|
|
|
|||
|
|
@ -364,7 +364,8 @@ static int nfs_idmap_lookup_id(const char *name, size_t namelen, const char *typ
|
|||
ret = -EINVAL;
|
||||
} else {
|
||||
ret = kstrtol(id_str, 10, &id_long);
|
||||
*id = (__u32)id_long;
|
||||
if (!ret)
|
||||
*id = (__u32)id_long;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -275,6 +275,7 @@ const u32 nfs4_fs_locations_bitmap[3] = {
|
|||
static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dentry,
|
||||
struct nfs4_readdir_arg *readdir)
|
||||
{
|
||||
unsigned int attrs = FATTR4_WORD0_FILEID | FATTR4_WORD0_TYPE;
|
||||
__be32 *start, *p;
|
||||
|
||||
if (cookie > 2) {
|
||||
|
|
@ -305,8 +306,9 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent
|
|||
memcpy(p, ".\0\0\0", 4); /* entry */
|
||||
p++;
|
||||
*p++ = xdr_one; /* bitmap length */
|
||||
*p++ = htonl(FATTR4_WORD0_FILEID); /* bitmap */
|
||||
*p++ = htonl(8); /* attribute buffer length */
|
||||
*p++ = htonl(attrs); /* bitmap */
|
||||
*p++ = htonl(12); /* attribute buffer length */
|
||||
*p++ = htonl(NF4DIR);
|
||||
p = xdr_encode_hyper(p, NFS_FILEID(d_inode(dentry)));
|
||||
}
|
||||
|
||||
|
|
@ -317,8 +319,9 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent
|
|||
memcpy(p, "..\0\0", 4); /* entry */
|
||||
p++;
|
||||
*p++ = xdr_one; /* bitmap length */
|
||||
*p++ = htonl(FATTR4_WORD0_FILEID); /* bitmap */
|
||||
*p++ = htonl(8); /* attribute buffer length */
|
||||
*p++ = htonl(attrs); /* bitmap */
|
||||
*p++ = htonl(12); /* attribute buffer length */
|
||||
*p++ = htonl(NF4DIR);
|
||||
p = xdr_encode_hyper(p, NFS_FILEID(d_inode(dentry->d_parent)));
|
||||
|
||||
readdir->pgbase = (char *)p - (char *)start;
|
||||
|
|
@ -1034,11 +1037,11 @@ struct nfs4_opendata {
|
|||
struct nfs4_state *state;
|
||||
struct iattr attrs;
|
||||
unsigned long timestamp;
|
||||
unsigned int rpc_done : 1;
|
||||
unsigned int file_created : 1;
|
||||
unsigned int is_recover : 1;
|
||||
bool rpc_done;
|
||||
bool file_created;
|
||||
bool is_recover;
|
||||
bool cancelled;
|
||||
int rpc_status;
|
||||
int cancelled;
|
||||
};
|
||||
|
||||
static bool nfs4_clear_cap_atomic_open_v1(struct nfs_server *server,
|
||||
|
|
@ -1962,7 +1965,7 @@ static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata)
|
|||
nfs4_stateid_copy(&data->o_res.stateid, &data->c_res.stateid);
|
||||
nfs_confirm_seqid(&data->owner->so_seqid, 0);
|
||||
renew_lease(data->o_res.server, data->timestamp);
|
||||
data->rpc_done = 1;
|
||||
data->rpc_done = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1972,7 +1975,7 @@ static void nfs4_open_confirm_release(void *calldata)
|
|||
struct nfs4_state *state = NULL;
|
||||
|
||||
/* If this request hasn't been cancelled, do nothing */
|
||||
if (data->cancelled == 0)
|
||||
if (!data->cancelled)
|
||||
goto out_free;
|
||||
/* In case of error, no cleanup! */
|
||||
if (!data->rpc_done)
|
||||
|
|
@ -2015,7 +2018,7 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data)
|
|||
|
||||
nfs4_init_sequence(&data->c_arg.seq_args, &data->c_res.seq_res, 1);
|
||||
kref_get(&data->kref);
|
||||
data->rpc_done = 0;
|
||||
data->rpc_done = false;
|
||||
data->rpc_status = 0;
|
||||
data->timestamp = jiffies;
|
||||
if (data->is_recover)
|
||||
|
|
@ -2025,7 +2028,7 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data)
|
|||
return PTR_ERR(task);
|
||||
status = rpc_wait_for_completion_task(task);
|
||||
if (status != 0) {
|
||||
data->cancelled = 1;
|
||||
data->cancelled = true;
|
||||
smp_wmb();
|
||||
} else
|
||||
status = data->rpc_status;
|
||||
|
|
@ -2124,7 +2127,7 @@ static void nfs4_open_done(struct rpc_task *task, void *calldata)
|
|||
if (!(data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM))
|
||||
nfs_confirm_seqid(&data->owner->so_seqid, 0);
|
||||
}
|
||||
data->rpc_done = 1;
|
||||
data->rpc_done = true;
|
||||
}
|
||||
|
||||
static void nfs4_open_release(void *calldata)
|
||||
|
|
@ -2133,7 +2136,7 @@ static void nfs4_open_release(void *calldata)
|
|||
struct nfs4_state *state = NULL;
|
||||
|
||||
/* If this request hasn't been cancelled, do nothing */
|
||||
if (data->cancelled == 0)
|
||||
if (!data->cancelled)
|
||||
goto out_free;
|
||||
/* In case of error, no cleanup! */
|
||||
if (data->rpc_status != 0 || !data->rpc_done)
|
||||
|
|
@ -2179,20 +2182,20 @@ static int nfs4_run_open_task(struct nfs4_opendata *data, int isrecover)
|
|||
|
||||
nfs4_init_sequence(&o_arg->seq_args, &o_res->seq_res, 1);
|
||||
kref_get(&data->kref);
|
||||
data->rpc_done = 0;
|
||||
data->rpc_done = false;
|
||||
data->rpc_status = 0;
|
||||
data->cancelled = 0;
|
||||
data->is_recover = 0;
|
||||
data->cancelled = false;
|
||||
data->is_recover = false;
|
||||
if (isrecover) {
|
||||
nfs4_set_sequence_privileged(&o_arg->seq_args);
|
||||
data->is_recover = 1;
|
||||
data->is_recover = true;
|
||||
}
|
||||
task = rpc_run_task(&task_setup_data);
|
||||
if (IS_ERR(task))
|
||||
return PTR_ERR(task);
|
||||
status = rpc_wait_for_completion_task(task);
|
||||
if (status != 0) {
|
||||
data->cancelled = 1;
|
||||
data->cancelled = true;
|
||||
smp_wmb();
|
||||
} else
|
||||
status = data->rpc_status;
|
||||
|
|
@ -2287,9 +2290,9 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
|
|||
|
||||
if (o_arg->open_flags & O_CREAT) {
|
||||
if (o_arg->open_flags & O_EXCL)
|
||||
data->file_created = 1;
|
||||
data->file_created = true;
|
||||
else if (o_res->cinfo.before != o_res->cinfo.after)
|
||||
data->file_created = 1;
|
||||
data->file_created = true;
|
||||
if (data->file_created || dir->i_version != o_res->cinfo.after)
|
||||
update_changeattr(dir, &o_res->cinfo,
|
||||
o_res->f_attr->time_start);
|
||||
|
|
@ -3803,6 +3806,54 @@ nfs4_proc_lookup_mountpoint(struct inode *dir, const struct qstr *name,
|
|||
return (client == NFS_CLIENT(dir)) ? rpc_clone_client(client) : client;
|
||||
}
|
||||
|
||||
static int _nfs4_proc_lookupp(struct inode *inode,
|
||||
struct nfs_fh *fhandle, struct nfs_fattr *fattr,
|
||||
struct nfs4_label *label)
|
||||
{
|
||||
struct rpc_clnt *clnt = NFS_CLIENT(inode);
|
||||
struct nfs_server *server = NFS_SERVER(inode);
|
||||
int status;
|
||||
struct nfs4_lookupp_arg args = {
|
||||
.bitmask = server->attr_bitmask,
|
||||
.fh = NFS_FH(inode),
|
||||
};
|
||||
struct nfs4_lookupp_res res = {
|
||||
.server = server,
|
||||
.fattr = fattr,
|
||||
.label = label,
|
||||
.fh = fhandle,
|
||||
};
|
||||
struct rpc_message msg = {
|
||||
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUPP],
|
||||
.rpc_argp = &args,
|
||||
.rpc_resp = &res,
|
||||
};
|
||||
|
||||
args.bitmask = nfs4_bitmask(server, label);
|
||||
|
||||
nfs_fattr_init(fattr);
|
||||
|
||||
dprintk("NFS call lookupp ino=0x%lx\n", inode->i_ino);
|
||||
status = nfs4_call_sync(clnt, server, &msg, &args.seq_args,
|
||||
&res.seq_res, 0);
|
||||
dprintk("NFS reply lookupp: %d\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
static int nfs4_proc_lookupp(struct inode *inode, struct nfs_fh *fhandle,
|
||||
struct nfs_fattr *fattr, struct nfs4_label *label)
|
||||
{
|
||||
struct nfs4_exception exception = { };
|
||||
int err;
|
||||
do {
|
||||
err = _nfs4_proc_lookupp(inode, fhandle, fattr, label);
|
||||
trace_nfs4_lookupp(inode, err);
|
||||
err = nfs4_handle_exception(NFS_SERVER(inode), err,
|
||||
&exception);
|
||||
} while (exception.retry);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry)
|
||||
{
|
||||
struct nfs_server *server = NFS_SERVER(inode);
|
||||
|
|
@ -4273,7 +4324,7 @@ static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
|
|||
}
|
||||
|
||||
static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
|
||||
u64 cookie, struct page **pages, unsigned int count, int plus)
|
||||
u64 cookie, struct page **pages, unsigned int count, bool plus)
|
||||
{
|
||||
struct inode *dir = d_inode(dentry);
|
||||
struct nfs4_readdir_arg args = {
|
||||
|
|
@ -4311,7 +4362,7 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
|
|||
}
|
||||
|
||||
static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
|
||||
u64 cookie, struct page **pages, unsigned int count, int plus)
|
||||
u64 cookie, struct page **pages, unsigned int count, bool plus)
|
||||
{
|
||||
struct nfs4_exception exception = { };
|
||||
int err;
|
||||
|
|
@ -6135,7 +6186,7 @@ static void nfs4_lock_release(void *calldata)
|
|||
|
||||
dprintk("%s: begin!\n", __func__);
|
||||
nfs_free_seqid(data->arg.open_seqid);
|
||||
if (data->cancelled != 0) {
|
||||
if (data->cancelled) {
|
||||
struct rpc_task *task;
|
||||
task = nfs4_do_unlck(&data->fl, data->ctx, data->lsp,
|
||||
data->arg.lock_seqid);
|
||||
|
|
@ -6218,7 +6269,7 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f
|
|||
nfs4_handle_setlk_error(data->server, data->lsp,
|
||||
data->arg.new_lock_owner, ret);
|
||||
} else
|
||||
data->cancelled = 1;
|
||||
data->cancelled = true;
|
||||
rpc_put_task(task);
|
||||
dprintk("%s: done, ret = %d!\n", __func__, ret);
|
||||
trace_nfs4_set_lock(fl, state, &data->res.stateid, cmd, ret);
|
||||
|
|
@ -7376,12 +7427,11 @@ static void nfs4_exchange_id_done(struct rpc_task *task, void *data)
|
|||
if (status == 0) {
|
||||
clp->cl_clientid = cdata->res.clientid;
|
||||
clp->cl_exchange_flags = cdata->res.flags;
|
||||
clp->cl_seqid = cdata->res.seqid;
|
||||
/* Client ID is not confirmed */
|
||||
if (!(cdata->res.flags & EXCHGID4_FLAG_CONFIRMED_R)) {
|
||||
if (!(cdata->res.flags & EXCHGID4_FLAG_CONFIRMED_R))
|
||||
clear_bit(NFS4_SESSION_ESTABLISHED,
|
||||
&clp->cl_session->session_state);
|
||||
clp->cl_seqid = cdata->res.seqid;
|
||||
}
|
||||
&clp->cl_session->session_state);
|
||||
|
||||
kfree(clp->cl_serverowner);
|
||||
clp->cl_serverowner = cdata->res.server_owner;
|
||||
|
|
@ -9313,6 +9363,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
|
|||
.getattr = nfs4_proc_getattr,
|
||||
.setattr = nfs4_proc_setattr,
|
||||
.lookup = nfs4_proc_lookup,
|
||||
.lookupp = nfs4_proc_lookupp,
|
||||
.access = nfs4_proc_access,
|
||||
.readlink = nfs4_proc_readlink,
|
||||
.create = nfs4_proc_create,
|
||||
|
|
|
|||
|
|
@ -352,11 +352,17 @@ int nfs41_discover_server_trunking(struct nfs_client *clp,
|
|||
if (clp != *result)
|
||||
return 0;
|
||||
|
||||
/* Purge state if the client id was established in a prior instance */
|
||||
if (clp->cl_exchange_flags & EXCHGID4_FLAG_CONFIRMED_R)
|
||||
set_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state);
|
||||
else
|
||||
set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
|
||||
/*
|
||||
* Purge state if the client id was established in a prior
|
||||
* instance and the client id could not have arrived on the
|
||||
* server via Transparent State Migration.
|
||||
*/
|
||||
if (clp->cl_exchange_flags & EXCHGID4_FLAG_CONFIRMED_R) {
|
||||
if (!test_bit(NFS_CS_TSM_POSSIBLE, &clp->cl_flags))
|
||||
set_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state);
|
||||
else
|
||||
set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
|
||||
}
|
||||
nfs4_schedule_state_manager(clp);
|
||||
status = nfs_wait_client_init_complete(clp);
|
||||
if (status < 0)
|
||||
|
|
|
|||
|
|
@ -891,6 +891,35 @@ DEFINE_NFS4_LOOKUP_EVENT(nfs4_remove);
|
|||
DEFINE_NFS4_LOOKUP_EVENT(nfs4_get_fs_locations);
|
||||
DEFINE_NFS4_LOOKUP_EVENT(nfs4_secinfo);
|
||||
|
||||
TRACE_EVENT(nfs4_lookupp,
|
||||
TP_PROTO(
|
||||
const struct inode *inode,
|
||||
int error
|
||||
),
|
||||
|
||||
TP_ARGS(inode, error),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(dev_t, dev)
|
||||
__field(u64, ino)
|
||||
__field(int, error)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->dev = inode->i_sb->s_dev;
|
||||
__entry->ino = NFS_FILEID(inode);
|
||||
__entry->error = error;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
"error=%d (%s) inode=%02x:%02x:%llu",
|
||||
__entry->error,
|
||||
show_nfsv4_errors(__entry->error),
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
(unsigned long long)__entry->ino
|
||||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(nfs4_rename,
|
||||
TP_PROTO(
|
||||
const struct inode *olddir,
|
||||
|
|
|
|||
|
|
@ -159,6 +159,8 @@ static int nfs4_stat_to_errno(int);
|
|||
(op_decode_hdr_maxsz)
|
||||
#define encode_lookup_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz)
|
||||
#define decode_lookup_maxsz (op_decode_hdr_maxsz)
|
||||
#define encode_lookupp_maxsz (op_encode_hdr_maxsz)
|
||||
#define decode_lookupp_maxsz (op_decode_hdr_maxsz)
|
||||
#define encode_share_access_maxsz \
|
||||
(2)
|
||||
#define encode_createmode_maxsz (1 + encode_attrs_maxsz + encode_verifier_maxsz)
|
||||
|
|
@ -618,6 +620,18 @@ static int nfs4_stat_to_errno(int);
|
|||
decode_lookup_maxsz + \
|
||||
decode_getattr_maxsz + \
|
||||
decode_getfh_maxsz)
|
||||
#define NFS4_enc_lookupp_sz (compound_encode_hdr_maxsz + \
|
||||
encode_sequence_maxsz + \
|
||||
encode_putfh_maxsz + \
|
||||
encode_lookupp_maxsz + \
|
||||
encode_getattr_maxsz + \
|
||||
encode_getfh_maxsz)
|
||||
#define NFS4_dec_lookupp_sz (compound_decode_hdr_maxsz + \
|
||||
decode_sequence_maxsz + \
|
||||
decode_putfh_maxsz + \
|
||||
decode_lookupp_maxsz + \
|
||||
decode_getattr_maxsz + \
|
||||
decode_getfh_maxsz)
|
||||
#define NFS4_enc_lookup_root_sz (compound_encode_hdr_maxsz + \
|
||||
encode_sequence_maxsz + \
|
||||
encode_putrootfh_maxsz + \
|
||||
|
|
@ -1368,6 +1382,11 @@ static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struc
|
|||
encode_string(xdr, name->len, name->name);
|
||||
}
|
||||
|
||||
static void encode_lookupp(struct xdr_stream *xdr, struct compound_hdr *hdr)
|
||||
{
|
||||
encode_op_hdr(xdr, OP_LOOKUPP, decode_lookupp_maxsz, hdr);
|
||||
}
|
||||
|
||||
static void encode_share_access(struct xdr_stream *xdr, u32 share_access)
|
||||
{
|
||||
__be32 *p;
|
||||
|
|
@ -2122,6 +2141,26 @@ static void nfs4_xdr_enc_lookup(struct rpc_rqst *req, struct xdr_stream *xdr,
|
|||
encode_nops(&hdr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode LOOKUPP request
|
||||
*/
|
||||
static void nfs4_xdr_enc_lookupp(struct rpc_rqst *req, struct xdr_stream *xdr,
|
||||
const void *data)
|
||||
{
|
||||
const struct nfs4_lookupp_arg *args = data;
|
||||
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_lookupp(xdr, &hdr);
|
||||
encode_getfh(xdr, &hdr);
|
||||
encode_getfattr(xdr, args->bitmask, &hdr);
|
||||
encode_nops(&hdr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode LOOKUP_ROOT request
|
||||
*/
|
||||
|
|
@ -5058,6 +5097,11 @@ static int decode_lookup(struct xdr_stream *xdr)
|
|||
return decode_op_hdr(xdr, OP_LOOKUP);
|
||||
}
|
||||
|
||||
static int decode_lookupp(struct xdr_stream *xdr)
|
||||
{
|
||||
return decode_op_hdr(xdr, OP_LOOKUPP);
|
||||
}
|
||||
|
||||
/* This is too sick! */
|
||||
static int decode_space_limit(struct xdr_stream *xdr,
|
||||
unsigned long *pagemod_limit)
|
||||
|
|
@ -6237,6 +6281,36 @@ out:
|
|||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode LOOKUPP response
|
||||
*/
|
||||
static int nfs4_xdr_dec_lookupp(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
|
||||
void *data)
|
||||
{
|
||||
struct nfs4_lookupp_res *res = data;
|
||||
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_lookupp(xdr);
|
||||
if (status)
|
||||
goto out;
|
||||
status = decode_getfh(xdr, res->fh);
|
||||
if (status)
|
||||
goto out;
|
||||
status = decode_getfattr_label(xdr, res->fattr, res->label, res->server);
|
||||
out:
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode LOOKUP_ROOT response
|
||||
*/
|
||||
|
|
@ -7447,7 +7521,7 @@ out:
|
|||
* on a directory already in our cache.
|
||||
*/
|
||||
int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
|
||||
int plus)
|
||||
bool plus)
|
||||
{
|
||||
unsigned int savep;
|
||||
uint32_t bitmap[3] = {0};
|
||||
|
|
@ -7614,6 +7688,7 @@ const struct rpc_procinfo nfs4_procedures[] = {
|
|||
PROC(ACCESS, enc_access, dec_access),
|
||||
PROC(GETATTR, enc_getattr, dec_getattr),
|
||||
PROC(LOOKUP, enc_lookup, dec_lookup),
|
||||
PROC(LOOKUPP, enc_lookupp, dec_lookupp),
|
||||
PROC(LOOKUP_ROOT, enc_lookup_root, dec_lookup_root),
|
||||
PROC(REMOVE, enc_remove, dec_remove),
|
||||
PROC(RENAME, enc_rename, dec_rename),
|
||||
|
|
|
|||
|
|
@ -50,8 +50,8 @@ void nfs_pgheader_init(struct nfs_pageio_descriptor *desc,
|
|||
hdr->cred = hdr->req->wb_context->cred;
|
||||
hdr->io_start = req_offset(hdr->req);
|
||||
hdr->good_bytes = mirror->pg_count;
|
||||
hdr->io_completion = desc->pg_io_completion;
|
||||
hdr->dreq = desc->pg_dreq;
|
||||
hdr->layout_private = desc->pg_layout_private;
|
||||
hdr->release = release;
|
||||
hdr->completion_ops = desc->pg_completion_ops;
|
||||
if (hdr->completion_ops->init_hdr)
|
||||
|
|
@ -155,9 +155,12 @@ nfs_page_group_lock(struct nfs_page *req, bool nonblock)
|
|||
if (!test_and_set_bit(PG_HEADLOCK, &head->wb_flags))
|
||||
return 0;
|
||||
|
||||
if (!nonblock)
|
||||
if (!nonblock) {
|
||||
set_bit(PG_CONTENDED1, &head->wb_flags);
|
||||
smp_mb__after_atomic();
|
||||
return wait_on_bit_lock(&head->wb_flags, PG_HEADLOCK,
|
||||
TASK_UNINTERRUPTIBLE);
|
||||
}
|
||||
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
|
@ -175,6 +178,10 @@ nfs_page_group_lock_wait(struct nfs_page *req)
|
|||
|
||||
WARN_ON_ONCE(head != head->wb_head);
|
||||
|
||||
if (!test_bit(PG_HEADLOCK, &head->wb_flags))
|
||||
return;
|
||||
set_bit(PG_CONTENDED1, &head->wb_flags);
|
||||
smp_mb__after_atomic();
|
||||
wait_on_bit(&head->wb_flags, PG_HEADLOCK,
|
||||
TASK_UNINTERRUPTIBLE);
|
||||
}
|
||||
|
|
@ -193,6 +200,8 @@ nfs_page_group_unlock(struct nfs_page *req)
|
|||
smp_mb__before_atomic();
|
||||
clear_bit(PG_HEADLOCK, &head->wb_flags);
|
||||
smp_mb__after_atomic();
|
||||
if (!test_bit(PG_CONTENDED1, &head->wb_flags))
|
||||
return;
|
||||
wake_up_bit(&head->wb_flags, PG_HEADLOCK);
|
||||
}
|
||||
|
||||
|
|
@ -383,6 +392,8 @@ void nfs_unlock_request(struct nfs_page *req)
|
|||
smp_mb__before_atomic();
|
||||
clear_bit(PG_BUSY, &req->wb_flags);
|
||||
smp_mb__after_atomic();
|
||||
if (!test_bit(PG_CONTENDED2, &req->wb_flags))
|
||||
return;
|
||||
wake_up_bit(&req->wb_flags, PG_BUSY);
|
||||
}
|
||||
|
||||
|
|
@ -465,6 +476,10 @@ void nfs_release_request(struct nfs_page *req)
|
|||
int
|
||||
nfs_wait_on_request(struct nfs_page *req)
|
||||
{
|
||||
if (!test_bit(PG_BUSY, &req->wb_flags))
|
||||
return 0;
|
||||
set_bit(PG_CONTENDED2, &req->wb_flags);
|
||||
smp_mb__after_atomic();
|
||||
return wait_on_bit_io(&req->wb_flags, PG_BUSY,
|
||||
TASK_UNINTERRUPTIBLE);
|
||||
}
|
||||
|
|
@ -710,8 +725,8 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
|
|||
desc->pg_ioflags = io_flags;
|
||||
desc->pg_error = 0;
|
||||
desc->pg_lseg = NULL;
|
||||
desc->pg_io_completion = NULL;
|
||||
desc->pg_dreq = NULL;
|
||||
desc->pg_layout_private = NULL;
|
||||
desc->pg_bsize = bsize;
|
||||
|
||||
desc->pg_mirror_count = 1;
|
||||
|
|
@ -779,6 +794,7 @@ int nfs_generic_pgio(struct nfs_pageio_descriptor *desc,
|
|||
gfp_t gfp_flags = GFP_KERNEL;
|
||||
|
||||
pagecount = nfs_page_array_len(mirror->pg_base, mirror->pg_count);
|
||||
pg_array->npages = pagecount;
|
||||
|
||||
if (pagecount <= ARRAY_SIZE(pg_array->page_array))
|
||||
pg_array->pagevec = pg_array->page_array;
|
||||
|
|
@ -1233,6 +1249,7 @@ int nfs_pageio_resend(struct nfs_pageio_descriptor *desc,
|
|||
{
|
||||
LIST_HEAD(failed);
|
||||
|
||||
desc->pg_io_completion = hdr->io_completion;
|
||||
desc->pg_dreq = hdr->dreq;
|
||||
while (!list_empty(&hdr->pages)) {
|
||||
struct nfs_page *req = nfs_list_entry(hdr->pages.next);
|
||||
|
|
|
|||
|
|
@ -485,7 +485,7 @@ nfs_proc_rmdir(struct inode *dir, const struct qstr *name)
|
|||
*/
|
||||
static int
|
||||
nfs_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
|
||||
u64 cookie, struct page **pages, unsigned int count, int plus)
|
||||
u64 cookie, struct page **pages, unsigned int count, bool plus)
|
||||
{
|
||||
struct inode *dir = d_inode(dentry);
|
||||
struct nfs_readdirargs arg = {
|
||||
|
|
|
|||
|
|
@ -879,7 +879,7 @@ int nfs_show_stats(struct seq_file *m, struct dentry *root)
|
|||
if (nfss->options & NFS_OPTION_FSCACHE) {
|
||||
seq_printf(m, "\n\tfsc:\t");
|
||||
for (i = 0; i < __NFSIOS_FSCACHEMAX; i++)
|
||||
seq_printf(m, "%Lu ", totals.bytes[i]);
|
||||
seq_printf(m, "%Lu ", totals.fscache[i]);
|
||||
}
|
||||
#endif
|
||||
seq_printf(m, "\n");
|
||||
|
|
@ -2339,6 +2339,7 @@ void nfs_fill_super(struct super_block *sb, struct nfs_mount_info *mount_info)
|
|||
*/
|
||||
sb->s_flags |= MS_POSIXACL;
|
||||
sb->s_time_gran = 1;
|
||||
sb->s_export_op = &nfs_export_ops;
|
||||
}
|
||||
|
||||
nfs_initialise_sb(sb);
|
||||
|
|
@ -2360,6 +2361,7 @@ static void nfs_clone_super(struct super_block *sb,
|
|||
sb->s_xattr = old_sb->s_xattr;
|
||||
sb->s_op = old_sb->s_op;
|
||||
sb->s_time_gran = 1;
|
||||
sb->s_export_op = old_sb->s_export_op;
|
||||
|
||||
if (server->nfs_client->rpc_ops->version != 2) {
|
||||
/* The VFS shouldn't apply the umask to mode bits. We will do
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue