Commit 8b16da68 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull nfsd updates from Chuck Lever:
 "This release completes the SunRPC thread scheduler work that was begun
  in v6.6. The scheduler can now find an svc thread to wake in constant
  time and without a list walk. Thanks again to Neil Brown for this
  overhaul.

  Lorenzo Bianconi contributed infrastructure for a netlink-based NFSD
  control plane. The long-term plan is to provide the same functionality
  as found in /proc/fs/nfsd, plus some interesting additions, and then
  migrate the NFSD user space utilities to netlink.

  A long series to overhaul NFSD's NFSv4 operation encoding was applied
  in this release. The goals are to bring this family of encoding
  functions in line with the matching NFSv4 decoding functions and with
  the NFSv2 and NFSv3 XDR functions, preparing the way for better memory
  safety and maintainability.

  A further improvement to NFSD's write delegation support was
  contributed by Dai Ngo. This adds a CB_GETATTR callback, enabling the
  server to retrieve cached size and mtime data from clients holding
  write delegations. If the server can retrieve this information, it
  does not have to recall the delegation in some cases.

  The usual panoply of bug fixes and minor improvements round out this
  release. As always I am grateful to all contributors, reviewers, and
  testers"

* tag 'nfsd-6.7' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux: (127 commits)
  svcrdma: Fix tracepoint printk format
  svcrdma: Drop connection after an RDMA Read error
  NFSD: clean up alloc_init_deleg()
  NFSD: Fix frame size warning in svc_export_parse()
  NFSD: Rewrite synopsis of nfsd_percpu_counters_init()
  nfsd: Clean up errors in nfs3proc.c
  nfsd: Clean up errors in nfs4state.c
  NFSD: Clean up errors in stats.c
  NFSD: simplify error paths in nfsd_svc()
  NFSD: Clean up nfsd4_encode_seek()
  NFSD: Clean up nfsd4_encode_offset_status()
  NFSD: Clean up nfsd4_encode_copy_notify()
  NFSD: Clean up nfsd4_encode_copy()
  NFSD: Clean up nfsd4_encode_test_stateid()
  NFSD: Clean up nfsd4_encode_exchange_id()
  NFSD: Clean up nfsd4_do_encode_secinfo()
  NFSD: Clean up nfsd4_encode_access()
  NFSD: Clean up nfsd4_encode_readdir()
  NFSD: Clean up nfsd4_encode_entry4()
  NFSD: Add an nfsd4_encode_nfs_cookie4() helper
  ...
parents 14ab6d42 3fd2ca5b
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -241,3 +241,10 @@ following flags are defined:
    all of an inode's dirty data on last close. Exports that behave this
    way should set EXPORT_OP_FLUSH_ON_CLOSE so that NFSD knows to skip
    waiting for writeback when closing such files.

  EXPORT_OP_ASYNC_LOCK - Indicates a capable filesystem to do async lock
    requests from lockd. Only set EXPORT_OP_ASYNC_LOCK if the filesystem has
    it's own ->lock() functionality as core posix_lock_file() implementation
    has no async lock request handling yet. For more information about how to
    indicate an async lock request from a ->lock() file_operations struct, see
    fs/locks.c and comment for the function vfs_lock_file().
+89 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)

name: nfsd
protocol: genetlink
uapi-header: linux/nfsd_netlink.h

doc: NFSD configuration over generic netlink.

attribute-sets:
  -
    name: rpc-status
    attributes:
      -
        name: xid
        type: u32
        byte-order: big-endian
      -
        name: flags
        type: u32
      -
        name: prog
        type: u32
      -
        name: version
        type: u8
      -
        name: proc
        type: u32
      -
        name: service_time
        type: s64
      -
        name: pad
        type: pad
      -
        name: saddr4
        type: u32
        byte-order: big-endian
        display-hint: ipv4
      -
        name: daddr4
        type: u32
        byte-order: big-endian
        display-hint: ipv4
      -
        name: saddr6
        type: binary
        display-hint: ipv6
      -
        name: daddr6
        type: binary
        display-hint: ipv6
      -
        name: sport
        type: u16
        byte-order: big-endian
      -
        name: dport
        type: u16
        byte-order: big-endian
      -
        name: compound-ops
        type: u32
        multi-attr: true

operations:
  list:
    -
      name: rpc-status-get
      doc: dump pending nfsd rpc
      attribute-set: rpc-status
      dump:
        pre: nfsd-nl-rpc-status-get-start
        post: nfsd-nl-rpc-status-get-done
        reply:
          attributes:
            - xid
            - flags
            - prog
            - version
            - proc
            - service_time
            - saddr4
            - daddr4
            - saddr6
            - daddr6
            - sport
            - dport
            - compound-ops
+4 −3
Original line number Diff line number Diff line
@@ -24,7 +24,6 @@
#include <linux/uio.h>
#include <linux/smp.h>
#include <linux/mutex.h>
#include <linux/kthread.h>
#include <linux/freezer.h>
#include <linux/inetdevice.h>

@@ -135,11 +134,11 @@ lockd(void *vrqstp)
	 * The main request loop. We don't terminate until the last
	 * NFS mount or NFS daemon has gone away.
	 */
	while (!kthread_should_stop()) {
	while (!svc_thread_should_stop(rqstp)) {
		/* update sv_maxconn if it has changed */
		rqstp->rq_server->sv_maxconn = nlm_max_connections;

		nlmsvc_retry_blocked();
		nlmsvc_retry_blocked(rqstp);
		svc_recv(rqstp);
	}
	if (nlmsvc_ops)
@@ -373,7 +372,9 @@ static void lockd_put(void)
	unregister_inet6addr_notifier(&lockd_inet6addr_notifier);
#endif

	svc_get(nlmsvc_serv);
	svc_set_num_threads(nlmsvc_serv, NULL, 0);
	svc_put(nlmsvc_serv);
	timer_delete_sync(&nlmsvc_retry);
	nlmsvc_serv = NULL;
	dprintk("lockd_down: service destroyed\n");
+27 −16
Original line number Diff line number Diff line
@@ -30,7 +30,6 @@
#include <linux/sunrpc/svc_xprt.h>
#include <linux/lockd/nlm.h>
#include <linux/lockd/lockd.h>
#include <linux/kthread.h>
#include <linux/exportfs.h>

#define NLMDBG_FACILITY		NLMDBG_SVCLOCK
@@ -481,9 +480,7 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
	    struct nlm_host *host, struct nlm_lock *lock, int wait,
	    struct nlm_cookie *cookie, int reclaim)
{
#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
	struct inode		*inode = nlmsvc_file_inode(file);
#endif
	struct nlm_block	*block = NULL;
	int			error;
	int			mode;
@@ -497,7 +494,7 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
				(long long)lock->fl.fl_end,
				wait);

	if (nlmsvc_file_file(file)->f_op->lock) {
	if (!exportfs_lock_op_is_async(inode->i_sb->s_export_op)) {
		async_block = wait;
		wait = 0;
	}
@@ -543,6 +540,25 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
		goto out;
	}

	spin_lock(&nlm_blocked_lock);
	/*
	 * If this is a lock request for an already pending
	 * lock request we return nlm_lck_blocked without calling
	 * vfs_lock_file() again. Otherwise we have two pending
	 * requests on the underlaying ->lock() implementation but
	 * only one nlm_block to being granted by lm_grant().
	 */
	if (exportfs_lock_op_is_async(inode->i_sb->s_export_op) &&
	    !list_empty(&block->b_list)) {
		spin_unlock(&nlm_blocked_lock);
		ret = nlm_lck_blocked;
		goto out;
	}

	/* Append to list of blocked */
	nlmsvc_insert_block_locked(block, NLM_NEVER);
	spin_unlock(&nlm_blocked_lock);

	if (!wait)
		lock->fl.fl_flags &= ~FL_SLEEP;
	mode = lock_to_openmode(&lock->fl);
@@ -552,16 +568,12 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
	dprintk("lockd: vfs_lock_file returned %d\n", error);
	switch (error) {
		case 0:
			nlmsvc_remove_block(block);
			ret = nlm_granted;
			goto out;
		case -EAGAIN:
			/*
			 * If this is a blocking request for an
			 * already pending lock request then we need
			 * to put it back on lockd's block list
			 */
			if (wait)
				break;
			if (!wait)
				nlmsvc_remove_block(block);
			ret = async_block ? nlm_lck_blocked : nlm_lck_denied;
			goto out;
		case FILE_LOCK_DEFERRED:
@@ -572,17 +584,16 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
			ret = nlmsvc_defer_lock_rqst(rqstp, block);
			goto out;
		case -EDEADLK:
			nlmsvc_remove_block(block);
			ret = nlm_deadlock;
			goto out;
		default:			/* includes ENOLCK */
			nlmsvc_remove_block(block);
			ret = nlm_lck_denied_nolocks;
			goto out;
	}

	ret = nlm_lck_blocked;

	/* Append to list of blocked */
	nlmsvc_insert_block(block, NLM_NEVER);
out:
	mutex_unlock(&file->f_mutex);
	nlmsvc_release_block(block);
@@ -1020,13 +1031,13 @@ retry_deferred_block(struct nlm_block *block)
 * be retransmitted.
 */
void
nlmsvc_retry_blocked(void)
nlmsvc_retry_blocked(struct svc_rqst *rqstp)
{
	unsigned long	timeout = MAX_SCHEDULE_TIMEOUT;
	struct nlm_block *block;

	spin_lock(&nlm_blocked_lock);
	while (!list_empty(&nlm_blocked) && !kthread_should_stop()) {
	while (!list_empty(&nlm_blocked) && !svc_thread_should_stop(rqstp)) {
		block = list_entry(nlm_blocked.next, struct nlm_block, b_list);

		if (block->b_when == NLM_NEVER)
+7 −5
Original line number Diff line number Diff line
@@ -2264,11 +2264,13 @@ int fcntl_getlk(struct file *filp, unsigned int cmd, struct flock *flock)
 * To avoid blocking kernel daemons, such as lockd, that need to acquire POSIX
 * locks, the ->lock() interface may return asynchronously, before the lock has
 * been granted or denied by the underlying filesystem, if (and only if)
 * lm_grant is set. Callers expecting ->lock() to return asynchronously
 * will only use F_SETLK, not F_SETLKW; they will set FL_SLEEP if (and only if)
 * the request is for a blocking lock. When ->lock() does return asynchronously,
 * it must return FILE_LOCK_DEFERRED, and call ->lm_grant() when the lock
 * request completes.
 * lm_grant is set. Additionally EXPORT_OP_ASYNC_LOCK in export_operations
 * flags need to be set.
 *
 * Callers expecting ->lock() to return asynchronously will only use F_SETLK,
 * not F_SETLKW; they will set FL_SLEEP if (and only if) the request is for a
 * blocking lock. When ->lock() does return asynchronously, it must return
 * FILE_LOCK_DEFERRED, and call ->lm_grant() when the lock request completes.
 * If the request is for non-blocking lock the file system should return
 * FILE_LOCK_DEFERRED then try to get the lock and call the callback routine
 * with the result. If the request timed out the callback routine will return a
Loading