Commit a044dab5 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'nfs-for-6.2-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs

Pull NFS client updates from Trond Myklebust
 "Bugfixes:
   - Fix NULL pointer dereference in the mount parser
   - Fix memory stomp in decode_attr_security_label
   - Fix credential leak in _nfs4_discover_trunking()
   - Fix buffer leak in rpcrdma_req_create()
   - Fix leaked socket in rpc_sockname()
   - Fix deadlock between nfs4_open_recover_helper() and delegreturn
   - Fix an Oops in nfs_d_automount()
   - Fix potential race in nfs_call_unlink()
   - Multiple fixes for the open context mode
   - NFSv4.2 READ_PLUS fixes
   - Fix a regression in which small rsize/wsize values are being
     forbidden
   - Fail client initialisation if the NFSv4.x state manager thread
     can't run
   - Avoid spurious warning of lost lock that is being unlocked.
   - Ensure the initialisation of struct nfs4_label

  Features and cleanups:
   - Trigger the "ls -l" readdir heuristic sooner
   - Clear the file access cache upon login to ensure supplementary
     group info is in sync between the client and server
   - pnfs: Fix up the logging of layout stateids
   - NFSv4.2: Change the default KConfig value for READ_PLUS
   - Use sysfs_emit() instead of scnprintf() where appropriate"

* tag 'nfs-for-6.2-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (24 commits)
  NFSv4.2: Change the default KConfig value for READ_PLUS
  NFSv4.x: Fail client initialisation if state manager thread can't run
  fs: nfs: sysfs: use sysfs_emit() to instead of scnprintf()
  NFS: use sysfs_emit() to instead of scnprintf()
  NFS: Allow very small rsize & wsize again
  NFSv4.2: Fix up READ_PLUS alignment
  NFSv4.2: Set the correct size scratch buffer for decoding READ_PLUS
  SUNRPC: Fix missing release socket in rpc_sockname()
  xprtrdma: Fix regbuf data not freed in rpcrdma_req_create()
  NFS: avoid spurious warning of lost lock that is being unlocked.
  nfs: fix possible null-ptr-deref when parsing param
  NFSv4: check FMODE_EXEC from open context mode in nfs4_opendata_access()
  NFS: make sure open context mode have FMODE_EXEC when file open for exec
  NFS4.x/pnfs: Fix up logging of layout stateids
  NFS: Fix a race in nfs_call_unlink()
  NFS: Fix an Oops in nfs_d_automount()
  NFSv4: Fix a deadlock between nfs4_open_recover_helper() and delegreturn
  NFSv4: Fix a credential leak in _nfs4_discover_trunking()
  NFS: Trigger the "ls -l" readdir heuristic sooner
  NFSv4.2: Fix initialisation of struct nfs4_label
  ...
parents 76482297 7fd461c4
...@@ -209,8 +209,8 @@ config NFS_DISABLE_UDP_SUPPORT ...@@ -209,8 +209,8 @@ config NFS_DISABLE_UDP_SUPPORT
config NFS_V4_2_READ_PLUS config NFS_V4_2_READ_PLUS
bool "NFS: Enable support for the NFSv4.2 READ_PLUS operation" bool "NFS: Enable support for the NFSv4.2 READ_PLUS operation"
depends on NFS_V4_2 depends on NFS_V4_2
default n default y
help help
This is intended for developers only. The READ_PLUS operation has Choose Y here to enable the use of READ_PLUS over NFS v4.2. READ_PLUS
been shown to have issues under specific conditions and should not attempts to improve read performance by compressing out sparse holes
be used in production. in the file contents.
...@@ -1074,6 +1074,8 @@ static int readdir_search_pagecache(struct nfs_readdir_descriptor *desc) ...@@ -1074,6 +1074,8 @@ static int readdir_search_pagecache(struct nfs_readdir_descriptor *desc)
return res; return res;
} }
#define NFS_READDIR_CACHE_MISS_THRESHOLD (16UL)
/* /*
* Once we've found the start of the dirent within a page: fill 'er up... * Once we've found the start of the dirent within a page: fill 'er up...
*/ */
...@@ -1083,6 +1085,7 @@ static void nfs_do_filldir(struct nfs_readdir_descriptor *desc, ...@@ -1083,6 +1085,7 @@ static void nfs_do_filldir(struct nfs_readdir_descriptor *desc,
struct file *file = desc->file; struct file *file = desc->file;
struct nfs_cache_array *array; struct nfs_cache_array *array;
unsigned int i; unsigned int i;
bool first_emit = !desc->dir_cookie;
array = kmap_local_page(desc->page); array = kmap_local_page(desc->page);
for (i = desc->cache_entry_index; i < array->size; i++) { for (i = desc->cache_entry_index; i < array->size; i++) {
...@@ -1106,6 +1109,10 @@ static void nfs_do_filldir(struct nfs_readdir_descriptor *desc, ...@@ -1106,6 +1109,10 @@ static void nfs_do_filldir(struct nfs_readdir_descriptor *desc,
desc->ctx->pos = desc->dir_cookie; desc->ctx->pos = desc->dir_cookie;
else else
desc->ctx->pos++; desc->ctx->pos++;
if (first_emit && i > NFS_READDIR_CACHE_MISS_THRESHOLD + 1) {
desc->eob = true;
break;
}
} }
if (array->page_is_eof) if (array->page_is_eof)
desc->eof = !desc->eob; desc->eof = !desc->eob;
...@@ -1187,8 +1194,6 @@ static int uncached_readdir(struct nfs_readdir_descriptor *desc) ...@@ -1187,8 +1194,6 @@ static int uncached_readdir(struct nfs_readdir_descriptor *desc)
return status; return status;
} }
#define NFS_READDIR_CACHE_MISS_THRESHOLD (16UL)
static bool nfs_readdir_handle_cache_misses(struct inode *inode, static bool nfs_readdir_handle_cache_misses(struct inode *inode,
struct nfs_readdir_descriptor *desc, struct nfs_readdir_descriptor *desc,
unsigned int cache_misses, unsigned int cache_misses,
...@@ -2948,9 +2953,28 @@ static struct nfs_access_entry *nfs_access_search_rbtree(struct inode *inode, co ...@@ -2948,9 +2953,28 @@ static struct nfs_access_entry *nfs_access_search_rbtree(struct inode *inode, co
return NULL; return NULL;
} }
static u64 nfs_access_login_time(const struct task_struct *task,
const struct cred *cred)
{
const struct task_struct *parent;
u64 ret;
rcu_read_lock();
for (;;) {
parent = rcu_dereference(task->real_parent);
if (parent == task || cred_fscmp(parent->cred, cred) != 0)
break;
task = parent;
}
ret = task->start_time;
rcu_read_unlock();
return ret;
}
static int nfs_access_get_cached_locked(struct inode *inode, const struct cred *cred, u32 *mask, bool may_block) static int nfs_access_get_cached_locked(struct inode *inode, const struct cred *cred, u32 *mask, bool may_block)
{ {
struct nfs_inode *nfsi = NFS_I(inode); struct nfs_inode *nfsi = NFS_I(inode);
u64 login_time = nfs_access_login_time(current, cred);
struct nfs_access_entry *cache; struct nfs_access_entry *cache;
bool retry = true; bool retry = true;
int err; int err;
...@@ -2978,6 +3002,9 @@ static int nfs_access_get_cached_locked(struct inode *inode, const struct cred * ...@@ -2978,6 +3002,9 @@ static int nfs_access_get_cached_locked(struct inode *inode, const struct cred *
spin_lock(&inode->i_lock); spin_lock(&inode->i_lock);
retry = false; retry = false;
} }
err = -ENOENT;
if ((s64)(login_time - cache->timestamp) > 0)
goto out;
*mask = cache->mask; *mask = cache->mask;
list_move_tail(&cache->lru, &nfsi->access_cache_entry_lru); list_move_tail(&cache->lru, &nfsi->access_cache_entry_lru);
err = 0; err = 0;
...@@ -3057,6 +3084,7 @@ static void nfs_access_add_rbtree(struct inode *inode, ...@@ -3057,6 +3084,7 @@ static void nfs_access_add_rbtree(struct inode *inode,
else else
goto found; goto found;
} }
set->timestamp = ktime_get_ns();
rb_link_node(&set->rb_node, parent, p); rb_link_node(&set->rb_node, parent, p);
rb_insert_color(&set->rb_node, root_node); rb_insert_color(&set->rb_node, root_node);
list_add_tail(&set->lru, &nfsi->access_cache_entry_lru); list_add_tail(&set->lru, &nfsi->access_cache_entry_lru);
......
...@@ -684,6 +684,8 @@ static int nfs_fs_context_parse_param(struct fs_context *fc, ...@@ -684,6 +684,8 @@ static int nfs_fs_context_parse_param(struct fs_context *fc,
return ret; return ret;
break; break;
case Opt_vers: case Opt_vers:
if (!param->string)
goto out_invalid_value;
trace_nfs_mount_assign(param->key, param->string); trace_nfs_mount_assign(param->key, param->string);
ret = nfs_parse_version_string(fc, param->string); ret = nfs_parse_version_string(fc, param->string);
if (ret < 0) if (ret < 0)
...@@ -696,6 +698,8 @@ static int nfs_fs_context_parse_param(struct fs_context *fc, ...@@ -696,6 +698,8 @@ static int nfs_fs_context_parse_param(struct fs_context *fc,
break; break;
case Opt_proto: case Opt_proto:
if (!param->string)
goto out_invalid_value;
trace_nfs_mount_assign(param->key, param->string); trace_nfs_mount_assign(param->key, param->string);
protofamily = AF_INET; protofamily = AF_INET;
switch (lookup_constant(nfs_xprt_protocol_tokens, param->string, -1)) { switch (lookup_constant(nfs_xprt_protocol_tokens, param->string, -1)) {
...@@ -732,6 +736,8 @@ static int nfs_fs_context_parse_param(struct fs_context *fc, ...@@ -732,6 +736,8 @@ static int nfs_fs_context_parse_param(struct fs_context *fc,
break; break;
case Opt_mountproto: case Opt_mountproto:
if (!param->string)
goto out_invalid_value;
trace_nfs_mount_assign(param->key, param->string); trace_nfs_mount_assign(param->key, param->string);
mountfamily = AF_INET; mountfamily = AF_INET;
switch (lookup_constant(nfs_xprt_protocol_tokens, param->string, -1)) { switch (lookup_constant(nfs_xprt_protocol_tokens, param->string, -1)) {
......
...@@ -1168,7 +1168,8 @@ int nfs_open(struct inode *inode, struct file *filp) ...@@ -1168,7 +1168,8 @@ int nfs_open(struct inode *inode, struct file *filp)
{ {
struct nfs_open_context *ctx; struct nfs_open_context *ctx;
ctx = alloc_nfs_open_context(file_dentry(filp), filp->f_mode, filp); ctx = alloc_nfs_open_context(file_dentry(filp),
flags_to_mode(filp->f_flags), filp);
if (IS_ERR(ctx)) if (IS_ERR(ctx))
return PTR_ERR(ctx); return PTR_ERR(ctx);
nfs_file_set_open_context(filp, ctx); nfs_file_set_open_context(filp, ctx);
......
...@@ -739,12 +739,10 @@ unsigned long nfs_io_size(unsigned long iosize, enum xprt_transports proto) ...@@ -739,12 +739,10 @@ unsigned long nfs_io_size(unsigned long iosize, enum xprt_transports proto)
iosize = NFS_DEF_FILE_IO_SIZE; iosize = NFS_DEF_FILE_IO_SIZE;
else if (iosize >= NFS_MAX_FILE_IO_SIZE) else if (iosize >= NFS_MAX_FILE_IO_SIZE)
iosize = NFS_MAX_FILE_IO_SIZE; iosize = NFS_MAX_FILE_IO_SIZE;
else
iosize = iosize & PAGE_MASK;
if (proto == XPRT_TRANSPORT_UDP) if (proto == XPRT_TRANSPORT_UDP || iosize < PAGE_SIZE)
return nfs_block_bits(iosize, NULL); return nfs_block_bits(iosize, NULL);
return iosize; return iosize & PAGE_MASK;
} }
/* /*
......
...@@ -147,7 +147,7 @@ struct vfsmount *nfs_d_automount(struct path *path) ...@@ -147,7 +147,7 @@ struct vfsmount *nfs_d_automount(struct path *path)
struct nfs_fs_context *ctx; struct nfs_fs_context *ctx;
struct fs_context *fc; struct fs_context *fc;
struct vfsmount *mnt = ERR_PTR(-ENOMEM); struct vfsmount *mnt = ERR_PTR(-ENOMEM);
struct nfs_server *server = NFS_SERVER(d_inode(path->dentry)); struct nfs_server *server = NFS_SB(path->dentry->d_sb);
struct nfs_client *client = server->nfs_client; struct nfs_client *client = server->nfs_client;
int timeout = READ_ONCE(nfs_mountpoint_expiry_timeout); int timeout = READ_ONCE(nfs_mountpoint_expiry_timeout);
int ret; int ret;
...@@ -354,7 +354,7 @@ static int param_get_nfs_timeout(char *buffer, const struct kernel_param *kp) ...@@ -354,7 +354,7 @@ static int param_get_nfs_timeout(char *buffer, const struct kernel_param *kp)
num = (num + (HZ - 1)) / HZ; num = (num + (HZ - 1)) / HZ;
} else } else
num = -1; num = -1;
return scnprintf(buffer, PAGE_SIZE, "%li\n", num); return sysfs_emit(buffer, "%li\n", num);
} }
static const struct kernel_param_ops param_ops_nfs_timeout = { static const struct kernel_param_ops param_ops_nfs_timeout = {
......
...@@ -47,13 +47,14 @@ ...@@ -47,13 +47,14 @@
#define decode_deallocate_maxsz (op_decode_hdr_maxsz) #define decode_deallocate_maxsz (op_decode_hdr_maxsz)
#define encode_read_plus_maxsz (op_encode_hdr_maxsz + \ #define encode_read_plus_maxsz (op_encode_hdr_maxsz + \
encode_stateid_maxsz + 3) encode_stateid_maxsz + 3)
#define NFS42_READ_PLUS_SEGMENT_SIZE (1 /* data_content4 */ + \ #define NFS42_READ_PLUS_DATA_SEGMENT_SIZE \
(1 /* data_content4 */ + \
2 /* data_info4.di_offset */ + \ 2 /* data_info4.di_offset */ + \
2 /* data_info4.di_length */) 1 /* data_info4.di_length */)
#define decode_read_plus_maxsz (op_decode_hdr_maxsz + \ #define decode_read_plus_maxsz (op_decode_hdr_maxsz + \
1 /* rpr_eof */ + \ 1 /* rpr_eof */ + \
1 /* rpr_contents count */ + \ 1 /* rpr_contents count */ + \
2 * NFS42_READ_PLUS_SEGMENT_SIZE) NFS42_READ_PLUS_DATA_SEGMENT_SIZE)
#define encode_seek_maxsz (op_encode_hdr_maxsz + \ #define encode_seek_maxsz (op_encode_hdr_maxsz + \
encode_stateid_maxsz + \ encode_stateid_maxsz + \
2 /* offset */ + \ 2 /* offset */ + \
...@@ -1142,7 +1143,7 @@ static int decode_read_plus(struct xdr_stream *xdr, struct nfs_pgio_res *res) ...@@ -1142,7 +1143,7 @@ static int decode_read_plus(struct xdr_stream *xdr, struct nfs_pgio_res *res)
if (!segs) if (!segs)
return -ENOMEM; return -ENOMEM;
xdr_set_scratch_buffer(xdr, &scratch_buf, 32); xdr_set_scratch_buffer(xdr, &scratch_buf, sizeof(scratch_buf));
status = -EIO; status = -EIO;
for (i = 0; i < segments; i++) { for (i = 0; i < segments; i++) {
status = decode_read_plus_segment(xdr, &segs[i]); status = decode_read_plus_segment(xdr, &segs[i]);
......
...@@ -149,6 +149,7 @@ struct nfs4_lock_state { ...@@ -149,6 +149,7 @@ struct nfs4_lock_state {
struct nfs4_state * ls_state; /* Pointer to open state */ struct nfs4_state * ls_state; /* Pointer to open state */
#define NFS_LOCK_INITIALIZED 0 #define NFS_LOCK_INITIALIZED 0
#define NFS_LOCK_LOST 1 #define NFS_LOCK_LOST 1
#define NFS_LOCK_UNLOCKING 2
unsigned long ls_flags; unsigned long ls_flags;
struct nfs_seqid_counter ls_seqid; struct nfs_seqid_counter ls_seqid;
nfs4_stateid ls_stateid; nfs4_stateid ls_stateid;
......
...@@ -32,7 +32,6 @@ nfs4_file_open(struct inode *inode, struct file *filp) ...@@ -32,7 +32,6 @@ nfs4_file_open(struct inode *inode, struct file *filp)
struct dentry *parent = NULL; struct dentry *parent = NULL;
struct inode *dir; struct inode *dir;
unsigned openflags = filp->f_flags; unsigned openflags = filp->f_flags;
fmode_t f_mode;
struct iattr attr; struct iattr attr;
int err; int err;
...@@ -51,17 +50,14 @@ nfs4_file_open(struct inode *inode, struct file *filp) ...@@ -51,17 +50,14 @@ nfs4_file_open(struct inode *inode, struct file *filp)
if (err) if (err)
return err; return err;
f_mode = filp->f_mode;
if ((openflags & O_ACCMODE) == 3)
f_mode |= flags_to_mode(openflags);
/* We can't create new files here */ /* We can't create new files here */
openflags &= ~(O_CREAT|O_EXCL); openflags &= ~(O_CREAT|O_EXCL);
parent = dget_parent(dentry); parent = dget_parent(dentry);
dir = d_inode(parent); dir = d_inode(parent);
ctx = alloc_nfs_open_context(file_dentry(filp), f_mode, filp); ctx = alloc_nfs_open_context(file_dentry(filp),
flags_to_mode(openflags), filp);
err = PTR_ERR(ctx); err = PTR_ERR(ctx);
if (IS_ERR(ctx)) if (IS_ERR(ctx))
goto out; goto out;
...@@ -366,8 +362,8 @@ static struct file *__nfs42_ssc_open(struct vfsmount *ss_mnt, ...@@ -366,8 +362,8 @@ static struct file *__nfs42_ssc_open(struct vfsmount *ss_mnt,
goto out_free_name; goto out_free_name;
} }
ctx = alloc_nfs_open_context(filep->f_path.dentry, filep->f_mode, ctx = alloc_nfs_open_context(filep->f_path.dentry,
filep); flags_to_mode(filep->f_flags), filep);
if (IS_ERR(ctx)) { if (IS_ERR(ctx)) {
res = ERR_CAST(ctx); res = ERR_CAST(ctx);
goto out_filep; goto out_filep;
......
...@@ -122,6 +122,11 @@ nfs4_label_init_security(struct inode *dir, struct dentry *dentry, ...@@ -122,6 +122,11 @@ nfs4_label_init_security(struct inode *dir, struct dentry *dentry,
if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL) == 0) if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL) == 0)
return NULL; return NULL;
label->lfs = 0;
label->pi = 0;
label->len = 0;
label->label = NULL;
err = security_dentry_init_security(dentry, sattr->ia_mode, err = security_dentry_init_security(dentry, sattr->ia_mode,
&dentry->d_name, NULL, &dentry->d_name, NULL,
(void **)&label->label, &label->len); (void **)&label->label, &label->len);
...@@ -2126,18 +2131,18 @@ static struct nfs4_opendata *nfs4_open_recoverdata_alloc(struct nfs_open_context ...@@ -2126,18 +2131,18 @@ static struct nfs4_opendata *nfs4_open_recoverdata_alloc(struct nfs_open_context
} }
static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, static int nfs4_open_recover_helper(struct nfs4_opendata *opendata,
fmode_t fmode) fmode_t fmode)
{ {
struct nfs4_state *newstate; struct nfs4_state *newstate;
struct nfs_server *server = NFS_SB(opendata->dentry->d_sb);
int openflags = opendata->o_arg.open_flags;
int ret; int ret;
if (!nfs4_mode_match_open_stateid(opendata->state, fmode)) if (!nfs4_mode_match_open_stateid(opendata->state, fmode))
return 0; return 0;
opendata->o_arg.open_flags = 0;
opendata->o_arg.fmode = fmode; opendata->o_arg.fmode = fmode;
opendata->o_arg.share_access = nfs4_map_atomic_open_share( opendata->o_arg.share_access =
NFS_SB(opendata->dentry->d_sb), nfs4_map_atomic_open_share(server, fmode, openflags);
fmode, 0);
memset(&opendata->o_res, 0, sizeof(opendata->o_res)); memset(&opendata->o_res, 0, sizeof(opendata->o_res));
memset(&opendata->c_res, 0, sizeof(opendata->c_res)); memset(&opendata->c_res, 0, sizeof(opendata->c_res));
nfs4_init_opendata_res(opendata); nfs4_init_opendata_res(opendata);
...@@ -2625,8 +2630,7 @@ static int _nfs4_recover_proc_open(struct nfs4_opendata *data) ...@@ -2625,8 +2630,7 @@ static int _nfs4_recover_proc_open(struct nfs4_opendata *data)
*/ */
static int nfs4_opendata_access(const struct cred *cred, static int nfs4_opendata_access(const struct cred *cred,
struct nfs4_opendata *opendata, struct nfs4_opendata *opendata,
struct nfs4_state *state, fmode_t fmode, struct nfs4_state *state, fmode_t fmode)
int openflags)
{ {
struct nfs_access_entry cache; struct nfs_access_entry cache;
u32 mask, flags; u32 mask, flags;
...@@ -2637,11 +2641,7 @@ static int nfs4_opendata_access(const struct cred *cred, ...@@ -2637,11 +2641,7 @@ static int nfs4_opendata_access(const struct cred *cred,
return 0; return 0;
mask = 0; mask = 0;
/* if (fmode & FMODE_EXEC) {
* Use openflags to check for exec, because fmode won't
* always have FMODE_EXEC set when file open for exec.
*/
if (openflags & __FMODE_EXEC) {
/* ONLY check for exec rights */ /* ONLY check for exec rights */
if (S_ISDIR(state->inode->i_mode)) if (S_ISDIR(state->inode->i_mode))
mask = NFS4_ACCESS_LOOKUP; mask = NFS4_ACCESS_LOOKUP;
...@@ -2719,10 +2719,15 @@ static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *s ...@@ -2719,10 +2719,15 @@ static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *s
struct nfs4_opendata *opendata; struct nfs4_opendata *opendata;
int ret; int ret;
opendata = nfs4_open_recoverdata_alloc(ctx, state, opendata = nfs4_open_recoverdata_alloc(ctx, state, NFS4_OPEN_CLAIM_FH);
NFS4_OPEN_CLAIM_FH);
if (IS_ERR(opendata)) if (IS_ERR(opendata))
return PTR_ERR(opendata); return PTR_ERR(opendata);
/*
* We're not recovering a delegation, so ask for no delegation.
* Otherwise the recovery thread could deadlock with an outstanding
* delegation return.
*/
opendata->o_arg.open_flags = O_DIRECT;
ret = nfs4_open_recover(opendata, state); ret = nfs4_open_recover(opendata, state);
if (ret == -ESTALE) if (ret == -ESTALE)
d_drop(ctx->dentry); d_drop(ctx->dentry);
...@@ -3024,7 +3029,7 @@ static unsigned nfs4_exclusive_attrset(struct nfs4_opendata *opendata, ...@@ -3024,7 +3029,7 @@ static unsigned nfs4_exclusive_attrset(struct nfs4_opendata *opendata,
} }
static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata, static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
int flags, struct nfs_open_context *ctx) struct nfs_open_context *ctx)
{ {
struct nfs4_state_owner *sp = opendata->owner; struct nfs4_state_owner *sp = opendata->owner;
struct nfs_server *server = sp->so_server; struct nfs_server *server = sp->so_server;
...@@ -3085,8 +3090,7 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata, ...@@ -3085,8 +3090,7 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
/* Parse layoutget results before we check for access */ /* Parse layoutget results before we check for access */
pnfs_parse_lgopen(state->inode, opendata->lgp, ctx); pnfs_parse_lgopen(state->inode, opendata->lgp, ctx);
ret = nfs4_opendata_access(sp->so_cred, opendata, state, ret = nfs4_opendata_access(sp->so_cred, opendata, state, acc_mode);
acc_mode, flags);
if (ret != 0) if (ret != 0)
goto out; goto out;
...@@ -3160,7 +3164,7 @@ static int _nfs4_do_open(struct inode *dir, ...@@ -3160,7 +3164,7 @@ static int _nfs4_do_open(struct inode *dir,
if (d_really_is_positive(dentry)) if (d_really_is_positive(dentry))
opendata->state = nfs4_get_open_state(d_inode(dentry), sp); opendata->state = nfs4_get_open_state(d_inode(dentry), sp);
status = _nfs4_open_and_get_state(opendata, flags, ctx); status = _nfs4_open_and_get_state(opendata, ctx);
if (status != 0) if (status != 0)
goto err_opendata_put; goto err_opendata_put;
state = ctx->state; state = ctx->state;
...@@ -3796,7 +3800,7 @@ nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, ...@@ -3796,7 +3800,7 @@ nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx,
int open_flags, struct iattr *attr, int *opened) int open_flags, struct iattr *attr, int *opened)
{ {
struct nfs4_state *state; struct nfs4_state *state;
struct nfs4_label l = {0, 0, 0, NULL}, *label = NULL; struct nfs4_label l, *label;
label = nfs4_label_init_security(dir, ctx->dentry, attr, &l); label = nfs4_label_init_security(dir, ctx->dentry, attr, &l);
...@@ -4013,7 +4017,7 @@ static int _nfs4_discover_trunking(struct nfs_server *server, ...@@ -4013,7 +4017,7 @@ static int _nfs4_discover_trunking(struct nfs_server *server,
page = alloc_page(GFP_KERNEL); page = alloc_page(GFP_KERNEL);
if (!page) if (!page)
return -ENOMEM; goto out_put_cred;
locations = kmalloc(sizeof(struct nfs4_fs_locations), GFP_KERNEL); locations = kmalloc(sizeof(struct nfs4_fs_locations), GFP_KERNEL);
if (!locations) if (!locations)
goto out_free; goto out_free;
...@@ -4035,6 +4039,8 @@ static int _nfs4_discover_trunking(struct nfs_server *server, ...@@ -4035,6 +4039,8 @@ static int _nfs4_discover_trunking(struct nfs_server *server,
kfree(locations); kfree(locations);
out_free: out_free:
__free_page(page); __free_page(page);
out_put_cred:
put_cred(cred);
return status; return status;
} }
...@@ -4682,7 +4688,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, ...@@ -4682,7 +4688,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
int flags) int flags)
{ {
struct nfs_server *server = NFS_SERVER(dir); struct nfs_server *server = NFS_SERVER(dir);
struct nfs4_label l, *ilabel = NULL; struct nfs4_label l, *ilabel;
struct nfs_open_context *ctx; struct nfs_open_context *ctx;
struct nfs4_state *state; struct nfs4_state *state;
int status = 0; int status = 0;
...@@ -5033,7 +5039,7 @@ static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry, ...@@ -5033,7 +5039,7 @@ static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
struct nfs4_exception exception = { struct nfs4_exception exception = {
.interruptible = true, .interruptible = true,
}; };
struct nfs4_label l, *label = NULL; struct nfs4_label l, *label;
int err; int err;
label = nfs4_label_init_security(dir, dentry, sattr, &l); label = nfs4_label_init_security(dir, dentry, sattr, &l);
...@@ -5074,7 +5080,7 @@ static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, ...@@ -5074,7 +5080,7 @@ static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
struct nfs4_exception exception = { struct nfs4_exception exception = {
.interruptible = true, .interruptible = true,
}; };
struct nfs4_label l, *label = NULL; struct nfs4_label l, *label;
int err; int err;
label = nfs4_label_init_security(dir, dentry, sattr, &l); label = nfs4_label_init_security(dir, dentry, sattr, &l);
...@@ -5193,7 +5199,7 @@ static int nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, ...@@ -5193,7 +5199,7 @@ static int nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
struct nfs4_exception exception = { struct nfs4_exception exception = {
.interruptible = true, .interruptible = true,
}; };
struct nfs4_label l, *label = NULL; struct nfs4_label l, *label;
int err; int err;
label = nfs4_label_init_security(dir, dentry, sattr, &l); label = nfs4_label_init_security(dir, dentry, sattr, &l);
...@@ -7017,12 +7023,13 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock * ...@@ -7017,12 +7023,13 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *
mutex_unlock(&sp->so_delegreturn_mutex); mutex_unlock(&sp->so_delegreturn_mutex);
goto out; goto out;
} }
lsp = request->fl_u.nfs4_fl.owner;
set_bit(NFS_LOCK_UNLOCKING, &lsp->ls_flags);
up_read(&nfsi->rwsem); up_read(&nfsi->rwsem);
mutex_unlock(&sp->so_delegreturn_mutex); mutex_unlock(&sp->so_delegreturn_mutex);
if (status != 0) if (status != 0)
goto out; goto out;
/* Is this a delegated lock? */ /* Is this a delegated lock? */
lsp = request->fl_u.nfs4_fl.owner;
if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags) == 0) if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags) == 0)
goto out; goto out;
alloc_seqid = NFS_SERVER(inode)->nfs_client->cl_mvops->alloc_seqid; alloc_seqid = NFS_SERVER(inode)->nfs_client->cl_mvops->alloc_seqid;
......
...@@ -1230,6 +1230,8 @@ void nfs4_schedule_state_manager(struct nfs_client *clp) ...@@ -1230,6 +1230,8 @@ void nfs4_schedule_state_manager(struct nfs_client *clp)
if (IS_ERR(task)) { if (IS_ERR(task)) {
printk(KERN_ERR "%s: kthread_run: %ld\n", printk(KERN_ERR "%s: kthread_run: %ld\n",
__func__, PTR_ERR(task)); __func__, PTR_ERR(task));
if (!nfs_client_init_is_complete(clp))
nfs_mark_client_ready(clp, PTR_ERR(task));
nfs4_clear_state_manager_bit(clp); nfs4_clear_state_manager_bit(clp);
clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state); clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state);
nfs_put_client(clp); nfs_put_client(clp);
...@@ -1619,7 +1621,8 @@ static int __nfs4_reclaim_open_state(struct nfs4_state_owner *sp, struct nfs4_st ...@@ -1619,7 +1621,8 @@ static int __nfs4_reclaim_open_state(struct nfs4_state_owner *sp, struct nfs4_st
spin_lock(&state->state_lock); spin_lock(&state->state_lock);
list_for_each_entry(lock, &state->lock_states, ls_locks) { list_for_each_entry(lock, &state->lock_states, ls_locks) {
trace_nfs4_state_lock_reclaim(state, lock); trace_nfs4_state_lock_reclaim(state, lock);
if (!test_bit(NFS_LOCK_INITIALIZED, &lock->ls_flags)) if (!test_bit(NFS_LOCK_INITIALIZED, &lock->ls_flags) &&
!test_bit(NFS_LOCK_UNLOCKING, &lock->ls_flags))
*lost_locks += 1; *lost_locks += 1;
} }
spin_unlock(&state->state_lock); spin_unlock(&state->state_lock);
......
...@@ -1815,7 +1815,7 @@ TRACE_EVENT(pnfs_update_layout, ...@@ -1815,7 +1815,7 @@ TRACE_EVENT(pnfs_update_layout,
__entry->count = count; __entry->count = count;
__entry->iomode = iomode; __entry->iomode = iomode;
__entry->reason = reason; __entry->reason = reason;
if (lo != NULL) { if (lo != NULL && pnfs_layout_is_valid(lo)) {
__entry->layoutstateid_seq = __entry->layoutstateid_seq =
be32_to_cpu(lo->plh_stateid.seqid); be32_to_cpu(lo->plh_stateid.seqid);
__entry->layoutstateid_hash = __entry->layoutstateid_hash =
...@@ -1869,7 +1869,7 @@ DECLARE_EVENT_CLASS(pnfs_layout_event, ...@@ -1869,7 +1869,7 @@ DECLARE_EVENT_CLASS(pnfs_layout_event,
__entry->pos = pos; __entry->pos = pos;
__entry->count = count; __entry->count = count;
__entry->iomode = iomode; __entry->iomode = iomode;
if (lo != NULL) { if (lo != NULL && pnfs_layout_is_valid(lo)) {
__entry->layoutstateid_seq = __entry->layoutstateid_seq =
be32_to_cpu(lo->plh_stateid.seqid); be32_to_cpu(lo->plh_stateid.seqid);
__entry->layoutstateid_hash = __entry->layoutstateid_hash =
......
...@@ -4234,19 +4234,17 @@ static int decode_attr_security_label(struct xdr_stream *xdr, uint32_t *bitmap, ...@@ -4234,19 +4234,17 @@ static int decode_attr_security_label(struct xdr_stream *xdr, uint32_t *bitmap,
p = xdr_inline_decode(xdr, len); p = xdr_inline_decode(xdr, len);
if (unlikely(!p)) if (unlikely(!p))
return -EIO; return -EIO;
bitmap[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
if (len < NFS4_MAXLABELLEN) { if (len < NFS4_MAXLABELLEN) {
if (label) { if (label && label->len) {
if (label->len) { if (label->len < len)
if (label->len < len) return -ERANGE;
return -ERANGE; memcpy(label->label, p, len);
memcpy(label->label, p, len);
}
label->len = len; label->len = len;
label->pi = pi; label->pi = pi;
label->lfs = lfs; label->lfs = lfs;
status = NFS_ATTR_FATTR_V4_SECURITY_LABEL; status = NFS_ATTR_FATTR_V4_SECURITY_LABEL;
} }
bitmap[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
} else } else
printk(KERN_WARNING "%s: label too long (%u)!\n", printk(KERN_WARNING "%s: label too long (%u)!\n",
__func__, len); __func__, len);
...@@ -4755,12 +4753,10 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, ...@@ -4755,12 +4753,10 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap,
if (status < 0) if (status < 0)
goto xdr_error; goto xdr_error;
if (fattr->label) { status = decode_attr_security_label(xdr, bitmap, fattr->label);
status = decode_attr_security_label(xdr, bitmap, fattr->label); if (status < 0)
if (status < 0) goto xdr_error;
goto xdr_error; fattr->valid |= status;
fattr->valid |= status;
}
xdr_error: xdr_error:
dprintk("%s: xdr returned %d\n", __func__, -status); dprintk("%s: xdr returned %d\n", __func__, -status);
......
...@@ -82,7 +82,7 @@ static ssize_t nfs_netns_identifier_show(struct kobject *kobj, ...@@ -82,7 +82,7 @@ static ssize_t nfs_netns_identifier_show(struct kobject *kobj,
ssize_t ret; ssize_t ret;
rcu_read_lock(); rcu_read_lock();
ret = scnprintf(buf, PAGE_SIZE, "%s\n", rcu_dereference(c->identifier)); ret = sysfs_emit(buf, "%s\n", rcu_dereference(c->identifier));
rcu_read_unlock(); rcu_read_unlock();
return ret; return ret;
} }
......
...@@ -139,6 +139,7 @@ static int nfs_call_unlink(struct dentry *dentry, struct inode *inode, struct nf ...@@ -139,6 +139,7 @@ static int nfs_call_unlink(struct dentry *dentry, struct inode *inode, struct nf
*/ */
spin_lock(&alias->d_lock); spin_lock(&alias->d_lock);
if (d_really_is_positive(alias) && if (d_really_is_positive(alias) &&
!nfs_compare_fh(NFS_FH(inode), NFS_FH(d_inode(alias))) &&
!(alias->d_flags & DCACHE_NFSFS_RENAMED)) { !(alias->d_flags & DCACHE_NFSFS_RENAMED)) {
devname_garbage = alias->d_fsdata; devname_garbage = alias->d_fsdata;
alias->d_fsdata = data; alias->d_fsdata = data;
......
...@@ -59,6 +59,7 @@ struct nfs_access_entry { ...@@ -59,6 +59,7 @@ struct nfs_access_entry {
kuid_t fsuid; kuid_t fsuid;
kgid_t fsgid; kgid_t fsgid;
struct group_info *group_info; struct group_info *group_info;
u64 timestamp;
__u32 mask; __u32 mask;
struct rcu_head rcu_head; struct rcu_head rcu_head;
}; };
......
...@@ -1442,7 +1442,7 @@ static int rpc_sockname(struct net *net, struct sockaddr *sap, size_t salen, ...@@ -1442,7 +1442,7 @@ static int rpc_sockname(struct net *net, struct sockaddr *sap, size_t salen,
break; break;
default: default:
err = -EAFNOSUPPORT; err = -EAFNOSUPPORT;
goto out; goto out_release;
} }
if (err < 0) { if (err < 0) {
dprintk("RPC: can't bind UDP socket (%d)\n", err); dprintk("RPC: can't bind UDP socket (%d)\n", err);
......
...@@ -831,7 +831,7 @@ struct rpcrdma_req *rpcrdma_req_create(struct rpcrdma_xprt *r_xprt, ...@@ -831,7 +831,7 @@ struct rpcrdma_req *rpcrdma_req_create(struct rpcrdma_xprt *r_xprt,
return req; return req;
out3: out3:
kfree(req->rl_sendbuf); rpcrdma_regbuf_free(req->rl_sendbuf);
out2: out2:
kfree(req); kfree(req);
out1: out1:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment