Commit a044dab5 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
Loading
Loading
Loading
Loading
+4 −4
Original line number Original line Diff line number Diff line
@@ -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.
+30 −2
Original line number Original line Diff line number Diff line
@@ -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,
	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,
			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)
	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
	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 *
		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,
		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);
+6 −0
Original line number Original line Diff line number Diff line
@@ -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,
		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,
		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)) {
+2 −1
Original line number Original line Diff line number Diff line
@@ -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);
+2 −4
Original line number Original line Diff line number Diff line
@@ -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;
}
}


/*
/*
Loading