Merge tag 'nfsd-5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 31 Aug 2021 17:57:06 +0000 (10:57 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 31 Aug 2021 17:57:06 +0000 (10:57 -0700)
Pull nfsd updates from Chuck Lever:
 "New features:

   - Support for server-side disconnect injection via debugfs

   - Protocol definitions for new RPC_AUTH_TLS authentication flavor

  Performance improvements:

   - Reduce page allocator traffic in the NFSD splice read actor

   - Reduce CPU utilization in svcrdma's Send completion handler

  Notable bug fixes:

   - Stabilize lockd operation when re-exporting NFS mounts

   - Fix the use of %.*s in NFSD tracepoints

   - Fix /proc/sys/fs/nfs/nsm_use_hostnames"

* tag 'nfsd-5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux: (31 commits)
  nfsd: fix crash on LOCKT on reexported NFSv3
  nfs: don't allow reexport reclaims
  lockd: don't attempt blocking locks on nfs reexports
  nfs: don't atempt blocking locks on nfs reexports
  Keep read and write fds with each nlm_file
  lockd: update nlm_lookup_file reexport comment
  nlm: minor refactoring
  nlm: minor nlm_lookup_file argument change
  lockd: lockd server-side shouldn't set fl_ops
  SUNRPC: Add documentation for the fail_sunrpc/ directory
  SUNRPC: Server-side disconnect injection
  SUNRPC: Move client-side disconnect injection
  SUNRPC: Add a /sys/kernel/debug/fail_sunrpc/ directory
  svcrdma: xpt_bc_xprt is already clear in __svc_rdma_free()
  nfsd4: Fix forced-expiry locking
  rpc: fix gss_svc_init cleanup on failure
  SUNRPC: Add RPC_AUTH_TLS protocol numbers
  lockd: change the proc_handler for nsm_use_hostnames
  sysctl: introduce new proc handler proc_dobool
  SUNRPC: Fix a NULL pointer deref in trace_svc_stats_latency()
  ...

1  2 
fs/nfs/file.c
fs/nfsd/nfs4state.c
fs/nfsd/vfs.c
include/linux/fs.h
lib/Kconfig.debug
net/sunrpc/svc_xprt.c

diff --combined fs/nfs/file.c
@@@ -806,6 -806,13 +806,9 @@@ int nfs_lock(struct file *filp, int cmd
  
        nfs_inc_stats(inode, NFSIOS_VFSLOCK);
  
 -      /* No mandatory locks over NFS */
 -      if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK)
 -              goto out_err;
 -
+       if (fl->fl_flags & FL_RECLAIM)
+               return -ENOGRACE;
        if (NFS_SERVER(inode)->flags & NFS_MOUNT_LOCAL_FCNTL)
                is_local = 1;
  
diff --combined fs/nfsd/nfs4state.c
@@@ -2687,9 -2687,9 +2687,9 @@@ static void force_expire_client(struct 
  
        trace_nfsd_clid_admin_expired(&clp->cl_clientid);
  
-       spin_lock(&clp->cl_lock);
+       spin_lock(&nn->client_lock);
        clp->cl_time = 0;
-       spin_unlock(&clp->cl_lock);
+       spin_unlock(&nn->client_lock);
  
        wait_event(expiry_wq, atomic_read(&clp->cl_rpc_users) == 0);
        spin_lock(&nn->client_lock);
@@@ -5735,6 -5735,16 +5735,6 @@@ check_special_stateids(struct net *net
                                NFS4_SHARE_DENY_READ);
  }
  
 -/*
 - * Allow READ/WRITE during grace period on recovered state only for files
 - * that are not able to provide mandatory locking.
 - */
 -static inline int
 -grace_disallows_io(struct net *net, struct inode *inode)
 -{
 -      return opens_in_grace(net) && mandatory_lock(inode);
 -}
 -
  static __be32 check_stateid_generation(stateid_t *in, stateid_t *ref, bool has_session)
  {
        /*
@@@ -6016,6 -6026,7 +6016,6 @@@ nfs4_preprocess_stateid_op(struct svc_r
                stateid_t *stateid, int flags, struct nfsd_file **nfp,
                struct nfs4_stid **cstid)
  {
 -      struct inode *ino = d_inode(fhp->fh_dentry);
        struct net *net = SVC_NET(rqstp);
        struct nfsd_net *nn = net_generic(net, nfsd_net_id);
        struct nfs4_stid *s = NULL;
        if (nfp)
                *nfp = NULL;
  
 -      if (grace_disallows_io(net, ino))
 -              return nfserr_grace;
 -
        if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) {
                status = check_special_stateids(net, fhp, stateid, flags);
                goto done;
@@@ -6821,6 -6835,7 +6821,7 @@@ nfsd4_lock(struct svc_rqst *rqstp, stru
        struct nfsd4_blocked_lock *nbl = NULL;
        struct file_lock *file_lock = NULL;
        struct file_lock *conflock = NULL;
+       struct super_block *sb;
        __be32 status = 0;
        int lkflg;
        int err;
                dprintk("NFSD: nfsd4_lock: permission denied!\n");
                return status;
        }
+       sb = cstate->current_fh.fh_dentry->d_sb;
  
        if (lock->lk_is_new) {
                if (nfsd4_has_session(cstate))
        if (!locks_in_grace(net) && lock->lk_reclaim)
                goto out;
  
+       if (lock->lk_reclaim)
+               fl_flags |= FL_RECLAIM;
        fp = lock_stp->st_stid.sc_file;
        switch (lock->lk_type) {
                case NFS4_READW_LT:
-                       if (nfsd4_has_session(cstate))
+                       if (nfsd4_has_session(cstate) &&
+                           !(sb->s_export_op->flags & EXPORT_OP_SYNC_LOCKS))
                                fl_flags |= FL_SLEEP;
                        fallthrough;
                case NFS4_READ_LT:
                        fl_type = F_RDLCK;
                        break;
                case NFS4_WRITEW_LT:
-                       if (nfsd4_has_session(cstate))
+                       if (nfsd4_has_session(cstate) &&
+                           !(sb->s_export_op->flags & EXPORT_OP_SYNC_LOCKS))
                                fl_flags |= FL_SLEEP;
                        fallthrough;
                case NFS4_WRITE_LT:
@@@ -7022,8 -7043,7 +7029,7 @@@ out
  /*
   * The NFSv4 spec allows a client to do a LOCKT without holding an OPEN,
   * so we do a temporary open here just to get an open file to pass to
-  * vfs_test_lock.  (Arguably perhaps test_lock should be done with an
-  * inode operation.)
+  * vfs_test_lock.
   */
  static __be32 nfsd_test_lock(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file_lock *lock)
  {
                                                        NFSD_MAY_READ));
        if (err)
                goto out;
+       lock->fl_file = nf->nf_file;
        err = nfserrno(vfs_test_lock(nf->nf_file, lock));
+       lock->fl_file = NULL;
  out:
        fh_unlock(fhp);
        nfsd_file_put(nf);
diff --combined fs/nfsd/vfs.c
@@@ -244,7 -244,6 +244,6 @@@ out_nfserr
   * returned. Otherwise the covered directory is returned.
   * NOTE: this mountpoint crossing is not supported properly by all
   *   clients and is explicitly disallowed for NFSv3
-  *      NeilBrown <neilb@cse.unsw.edu.au>
   */
  __be32
  nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
@@@ -333,6 -332,7 +332,6 @@@ nfsd_get_write_access(struct svc_rqst *
                struct iattr *iap)
  {
        struct inode *inode = d_inode(fhp->fh_dentry);
 -      int host_err;
  
        if (iap->ia_size < inode->i_size) {
                __be32 err;
                if (err)
                        return err;
        }
 -
 -      host_err = get_write_access(inode);
 -      if (host_err)
 -              goto out_nfserrno;
 -
 -      host_err = locks_verify_truncate(inode, NULL, iap->ia_size);
 -      if (host_err)
 -              goto out_put_write_access;
 -      return 0;
 -
 -out_put_write_access:
 -      put_write_access(inode);
 -out_nfserrno:
 -      return nfserrno(host_err);
 +      return nfserrno(get_write_access(inode));
  }
  
  /*
@@@ -736,6 -749,13 +735,6 @@@ __nfsd_open(struct svc_rqst *rqstp, str
        err = nfserr_perm;
        if (IS_APPEND(inode) && (may_flags & NFSD_MAY_WRITE))
                goto out;
 -      /*
 -       * We must ignore files (but only files) which might have mandatory
 -       * locks on them because there is no way to know if the accesser has
 -       * the lock.
 -       */
 -      if (S_ISREG((inode)->i_mode) && mandatory_lock(inode))
 -              goto out;
  
        if (!inode->i_fop)
                goto out;
@@@ -826,26 -846,16 +825,16 @@@ nfsd_splice_actor(struct pipe_inode_inf
        struct svc_rqst *rqstp = sd->u.data;
        struct page **pp = rqstp->rq_next_page;
        struct page *page = buf->page;
-       size_t size;
-       size = sd->len;
  
        if (rqstp->rq_res.page_len == 0) {
-               get_page(page);
-               put_page(*rqstp->rq_next_page);
-               *(rqstp->rq_next_page++) = page;
+               svc_rqst_replace_page(rqstp, page);
                rqstp->rq_res.page_base = buf->offset;
-               rqstp->rq_res.page_len = size;
        } else if (page != pp[-1]) {
-               get_page(page);
-               if (*rqstp->rq_next_page)
-                       put_page(*rqstp->rq_next_page);
-               *(rqstp->rq_next_page++) = page;
-               rqstp->rq_res.page_len += size;
-       } else
-               rqstp->rq_res.page_len += size;
-       return size;
+               svc_rqst_replace_page(rqstp, page);
+       }
+       rqstp->rq_res.page_len += sd->len;
+       return sd->len;
  }
  
  static int nfsd_direct_splice_actor(struct pipe_inode_info *pipe,
diff --combined include/linux/fs.h
@@@ -319,8 -319,6 +319,8 @@@ enum rw_hint 
  /* iocb->ki_waitq is valid */
  #define IOCB_WAITQ            (1 << 19)
  #define IOCB_NOIO             (1 << 20)
 +/* can use bio alloc cache */
 +#define IOCB_ALLOC_CACHE      (1 << 21)
  
  struct kiocb {
        struct file             *ki_filp;
@@@ -438,10 -436,6 +438,10 @@@ int pagecache_write_end(struct file *, 
   * struct address_space - Contents of a cacheable, mappable object.
   * @host: Owner, either the inode or the block_device.
   * @i_pages: Cached pages.
 + * @invalidate_lock: Guards coherency between page cache contents and
 + *   file offset->disk block mappings in the filesystem during invalidates.
 + *   It is also used to block modification of page cache contents through
 + *   memory mappings.
   * @gfp_mask: Memory allocation flags to use for allocating pages.
   * @i_mmap_writable: Number of VM_SHARED mappings.
   * @nr_thps: Number of THPs in the pagecache (non-shmem only).
  struct address_space {
        struct inode            *host;
        struct xarray           i_pages;
 +      struct rw_semaphore     invalidate_lock;
        gfp_t                   gfp_mask;
        atomic_t                i_mmap_writable;
  #ifdef CONFIG_READ_ONLY_THP_FOR_FS
@@@ -821,42 -814,9 +821,42 @@@ static inline void inode_lock_shared_ne
        down_read_nested(&inode->i_rwsem, subclass);
  }
  
 +static inline void filemap_invalidate_lock(struct address_space *mapping)
 +{
 +      down_write(&mapping->invalidate_lock);
 +}
 +
 +static inline void filemap_invalidate_unlock(struct address_space *mapping)
 +{
 +      up_write(&mapping->invalidate_lock);
 +}
 +
 +static inline void filemap_invalidate_lock_shared(struct address_space *mapping)
 +{
 +      down_read(&mapping->invalidate_lock);
 +}
 +
 +static inline int filemap_invalidate_trylock_shared(
 +                                      struct address_space *mapping)
 +{
 +      return down_read_trylock(&mapping->invalidate_lock);
 +}
 +
 +static inline void filemap_invalidate_unlock_shared(
 +                                      struct address_space *mapping)
 +{
 +      up_read(&mapping->invalidate_lock);
 +}
 +
  void lock_two_nondirectories(struct inode *, struct inode*);
  void unlock_two_nondirectories(struct inode *, struct inode*);
  
 +void filemap_invalidate_lock_two(struct address_space *mapping1,
 +                               struct address_space *mapping2);
 +void filemap_invalidate_unlock_two(struct address_space *mapping1,
 +                                 struct address_space *mapping2);
 +
 +
  /*
   * NOTE: in a 32bit arch with a preemptable kernel and
   * an UP compile the i_size_read/write must be atomic
@@@ -1037,6 -997,7 +1037,7 @@@ static inline struct file *get_file(str
  #define FL_UNLOCK_PENDING     512 /* Lease is being broken */
  #define FL_OFDLCK     1024    /* lock is "owned" by struct file */
  #define FL_LAYOUT     2048    /* outstanding pNFS layout */
+ #define FL_RECLAIM    4096    /* reclaiming from a reboot server */
  
  #define FL_CLOSE_POSIX (FL_POSIX | FL_CLOSE)
  
@@@ -1547,11 -1508,8 +1548,11 @@@ struct super_block 
        /* Number of inodes with nlink == 0 but still referenced */
        atomic_long_t s_remove_count;
  
 -      /* Pending fsnotify inode refs */
 -      atomic_long_t s_fsnotify_inode_refs;
 +      /*
 +       * Number of inode/mount/sb objects that are being watched, note that
 +       * inodes objects are currently double-accounted.
 +       */
 +      atomic_long_t s_fsnotify_connectors;
  
        /* Being remounted read-only */
        int s_readonly_remount;
@@@ -2500,6 -2458,7 +2501,6 @@@ static inline void file_accessed(struc
  
  extern int file_modified(struct file *file);
  
 -int sync_inode(struct inode *inode, struct writeback_control *wbc);
  int sync_inode_metadata(struct inode *inode, int wait);
  
  struct file_system_type {
  
        struct lock_class_key i_lock_key;
        struct lock_class_key i_mutex_key;
 +      struct lock_class_key invalidate_lock_key;
        struct lock_class_key i_mutex_dir_key;
  };
  
@@@ -2613,6 -2571,90 +2614,6 @@@ extern struct kobject *fs_kobj
  
  #define MAX_RW_COUNT (INT_MAX & PAGE_MASK)
  
 -#ifdef CONFIG_MANDATORY_FILE_LOCKING
 -extern int locks_mandatory_locked(struct file *);
 -extern int locks_mandatory_area(struct inode *, struct file *, loff_t, loff_t, unsigned char);
 -
 -/*
 - * Candidates for mandatory locking have the setgid bit set
 - * but no group execute bit -  an otherwise meaningless combination.
 - */
 -
 -static inline int __mandatory_lock(struct inode *ino)
 -{
 -      return (ino->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID;
 -}
 -
 -/*
 - * ... and these candidates should be on SB_MANDLOCK mounted fs,
 - * otherwise these will be advisory locks
 - */
 -
 -static inline int mandatory_lock(struct inode *ino)
 -{
 -      return IS_MANDLOCK(ino) && __mandatory_lock(ino);
 -}
 -
 -static inline int locks_verify_locked(struct file *file)
 -{
 -      if (mandatory_lock(locks_inode(file)))
 -              return locks_mandatory_locked(file);
 -      return 0;
 -}
 -
 -static inline int locks_verify_truncate(struct inode *inode,
 -                                  struct file *f,
 -                                  loff_t size)
 -{
 -      if (!inode->i_flctx || !mandatory_lock(inode))
 -              return 0;
 -
 -      if (size < inode->i_size) {
 -              return locks_mandatory_area(inode, f, size, inode->i_size - 1,
 -                              F_WRLCK);
 -      } else {
 -              return locks_mandatory_area(inode, f, inode->i_size, size - 1,
 -                              F_WRLCK);
 -      }
 -}
 -
 -#else /* !CONFIG_MANDATORY_FILE_LOCKING */
 -
 -static inline int locks_mandatory_locked(struct file *file)
 -{
 -      return 0;
 -}
 -
 -static inline int locks_mandatory_area(struct inode *inode, struct file *filp,
 -                                       loff_t start, loff_t end, unsigned char type)
 -{
 -      return 0;
 -}
 -
 -static inline int __mandatory_lock(struct inode *inode)
 -{
 -      return 0;
 -}
 -
 -static inline int mandatory_lock(struct inode *inode)
 -{
 -      return 0;
 -}
 -
 -static inline int locks_verify_locked(struct file *file)
 -{
 -      return 0;
 -}
 -
 -static inline int locks_verify_truncate(struct inode *inode, struct file *filp,
 -                                      size_t size)
 -{
 -      return 0;
 -}
 -
 -#endif /* CONFIG_MANDATORY_FILE_LOCKING */
 -
 -
  #ifdef CONFIG_FILE_LOCKING
  static inline int break_lease(struct inode *inode, unsigned int mode)
  {
@@@ -2745,7 -2787,6 +2746,7 @@@ static inline struct file *file_clone_o
  extern int filp_close(struct file *, fl_owner_t id);
  
  extern struct filename *getname_flags(const char __user *, int, int *);
 +extern struct filename *getname_uflags(const char __user *, int);
  extern struct filename *getname(const char __user *);
  extern struct filename *getname_kernel(const char *);
  extern void putname(struct filename *name);
@@@ -2851,8 -2892,6 +2852,8 @@@ extern int filemap_fdatawrite_range(str
                                loff_t start, loff_t end);
  extern int filemap_check_errors(struct address_space *mapping);
  extern void __filemap_set_wb_err(struct address_space *mapping, int err);
 +int filemap_fdatawrite_wbc(struct address_space *mapping,
 +                         struct writeback_control *wbc);
  
  static inline int filemap_write_and_wait(struct address_space *mapping)
  {
@@@ -3208,6 -3247,10 +3209,6 @@@ ssize_t vfs_iocb_iter_read(struct file 
  ssize_t vfs_iocb_iter_write(struct file *file, struct kiocb *iocb,
                            struct iov_iter *iter);
  
 -/* fs/block_dev.c */
 -extern int blkdev_fsync(struct file *filp, loff_t start, loff_t end,
 -                      int datasync);
 -
  /* fs/splice.c */
  extern ssize_t generic_file_splice_read(struct file *, loff_t *,
                struct pipe_inode_info *, size_t, unsigned int);
diff --combined lib/Kconfig.debug
@@@ -1235,7 -1235,7 +1235,7 @@@ config PROVE_LOCKIN
        depends on DEBUG_KERNEL && LOCK_DEBUGGING_SUPPORT
        select LOCKDEP
        select DEBUG_SPINLOCK
 -      select DEBUG_MUTEXES
 +      select DEBUG_MUTEXES if !PREEMPT_RT
        select DEBUG_RT_MUTEXES if RT_MUTEXES
        select DEBUG_RWSEMS
        select DEBUG_WW_MUTEX_SLOWPATH
@@@ -1299,7 -1299,7 +1299,7 @@@ config LOCK_STA
        depends on DEBUG_KERNEL && LOCK_DEBUGGING_SUPPORT
        select LOCKDEP
        select DEBUG_SPINLOCK
 -      select DEBUG_MUTEXES
 +      select DEBUG_MUTEXES if !PREEMPT_RT
        select DEBUG_RT_MUTEXES if RT_MUTEXES
        select DEBUG_LOCK_ALLOC
        default n
@@@ -1335,7 -1335,7 +1335,7 @@@ config DEBUG_SPINLOC
  
  config DEBUG_MUTEXES
        bool "Mutex debugging: basic checks"
 -      depends on DEBUG_KERNEL
 +      depends on DEBUG_KERNEL && !PREEMPT_RT
        help
         This feature allows mutex semantics violations to be detected and
         reported.
@@@ -1345,8 -1345,7 +1345,8 @@@ config DEBUG_WW_MUTEX_SLOWPAT
        depends on DEBUG_KERNEL && LOCK_DEBUGGING_SUPPORT
        select DEBUG_LOCK_ALLOC
        select DEBUG_SPINLOCK
 -      select DEBUG_MUTEXES
 +      select DEBUG_MUTEXES if !PREEMPT_RT
 +      select DEBUG_RT_MUTEXES if PREEMPT_RT
        help
         This feature enables slowpath testing for w/w mutex users by
         injecting additional -EDEADLK wound/backoff cases. Together with
@@@ -1369,7 -1368,7 +1369,7 @@@ config DEBUG_LOCK_ALLO
        bool "Lock debugging: detect incorrect freeing of live locks"
        depends on DEBUG_KERNEL && LOCK_DEBUGGING_SUPPORT
        select DEBUG_SPINLOCK
 -      select DEBUG_MUTEXES
 +      select DEBUG_MUTEXES if !PREEMPT_RT
        select DEBUG_RT_MUTEXES if RT_MUTEXES
        select LOCKDEP
        help
@@@ -1680,6 -1679,33 +1680,6 @@@ config DEBUG_WQ_FORCE_RR_CP
          feature by default.  When enabled, memory and cache locality will
          be impacted.
  
 -config DEBUG_BLOCK_EXT_DEVT
 -      bool "Force extended block device numbers and spread them"
 -      depends on DEBUG_KERNEL
 -      depends on BLOCK
 -      default n
 -      help
 -        BIG FAT WARNING: ENABLING THIS OPTION MIGHT BREAK BOOTING ON
 -        SOME DISTRIBUTIONS.  DO NOT ENABLE THIS UNLESS YOU KNOW WHAT
 -        YOU ARE DOING.  Distros, please enable this and fix whatever
 -        is broken.
 -
 -        Conventionally, block device numbers are allocated from
 -        predetermined contiguous area.  However, extended block area
 -        may introduce non-contiguous block device numbers.  This
 -        option forces most block device numbers to be allocated from
 -        the extended space and spreads them to discover kernel or
 -        userland code paths which assume predetermined contiguous
 -        device number allocation.
 -
 -        Note that turning on this debug option shuffles all the
 -        device numbers for all IDE and SCSI devices including libata
 -        ones, so root partition specified using device number
 -        directly (via rdev or root=MAJ:MIN) won't work anymore.
 -        Textual device names (root=/dev/sdXn) will continue to work.
 -
 -        Say N if you are unsure.
 -
  config CPU_HOTPLUG_STATE_CONTROL
        bool "Enable CPU hotplug state control"
        depends on DEBUG_KERNEL
@@@ -1945,6 -1971,13 +1945,13 @@@ config FAIL_MMC_REQUES
          and to test how the mmc host driver handles retries from
          the block device.
  
+ config FAIL_SUNRPC
+       bool "Fault-injection capability for SunRPC"
+       depends on FAULT_INJECTION_DEBUG_FS && SUNRPC_DEBUG
+       help
+         Provide fault-injection capability for SunRPC and
+         its consumers.
  config FAULT_INJECTION_STACKTRACE_FILTER
        bool "stacktrace filter for fault-injection capabilities"
        depends on FAULT_INJECTION_DEBUG_FS && STACKTRACE_SUPPORT
diff --combined net/sunrpc/svc_xprt.c
@@@ -539,6 -539,7 +539,7 @@@ static void svc_xprt_release(struct svc
        kfree(rqstp->rq_deferred);
        rqstp->rq_deferred = NULL;
  
+       pagevec_release(&rqstp->rq_pvec);
        svc_free_res_pages(rqstp);
        rqstp->rq_res.page_len = 0;
        rqstp->rq_res.page_base = 0;
@@@ -664,6 -665,8 +665,8 @@@ static int svc_alloc_arg(struct svc_rqs
        struct xdr_buf *arg = &rqstp->rq_arg;
        unsigned long pages, filled;
  
+       pagevec_init(&rqstp->rq_pvec);
        pages = (serv->sv_max_mesg + 2 * PAGE_SIZE) >> PAGE_SHIFT;
        if (pages > RPCSVC_MAXPAGES) {
                pr_warn_once("svc: warning: pages=%lu > RPCSVC_MAXPAGES=%lu\n",
@@@ -835,8 -838,7 +838,8 @@@ static int svc_handle_xprt(struct svc_r
                rqstp->rq_stime = ktime_get();
                rqstp->rq_reserved = serv->sv_max_mesg;
                atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved);
 -      }
 +      } else
 +              svc_xprt_received(xprt);
  out:
        trace_svc_handle_xprt(xprt, len);
        return len;