Merge tag 'nfs-for-4.10-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 16 Dec 2016 02:47:31 +0000 (18:47 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 16 Dec 2016 02:47:31 +0000 (18:47 -0800)
Pull NFS client updates from Trond Myklebust:
 "Highlights include:

  Stable bugfixes:
   - Fix a pnfs deadlock between read resends and layoutreturn
   - Don't invalidate the layout stateid while a layout return is
     outstanding
   - Don't schedule a layoutreturn if the layout stateid is marked as
     invalid
   - On a pNFS error, do not send LAYOUTGET until the LAYOUTRETURN is
     complete
   - SUNRPC: fix refcounting problems with auth_gss messages.

  Features:
   - Add client support for the NFSv4 umask attribute.
   - NFSv4: Correct support for flock() stateids.
   - Add a LAYOUTRETURN operation to CLOSE and DELEGRETURN when
     return-on-close is specified
   - Allow the pNFS/flexfiles layoutstat information to piggyback on
     LAYOUTRETURN
   - Optimise away redundant GETATTR calls when doing state recovery
     and/or when not required by cache revalidation rules or
     close-to-open cache consistency.
   - Attribute cache improvements
   - RPC/RDMA support for SG_GAP devices

  Bugfixes:
   - NFS: Fix performance regressions in readdir
   - pNFS/flexfiles: Fix a deadlock on LAYOUTGET
   - NFSv4: Add missing nfs_put_lock_context()
   - NFSv4.1: Fix regression in callback retry handling
   - Fix false positive NFSv4.0 trunking detection.
   - pNFS/flexfiles: Only send layoutstats updates for mirrors that were
     updated
   - Various layout stateid related bugfixes
   - RPC/RDMA bugfixes"

* tag 'nfs-for-4.10-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (82 commits)
  SUNRPC: fix refcounting problems with auth_gss messages.
  nfs: add support for the umask attribute
  pNFS/flexfiles: Ensure we have enough buffer for layoutreturn
  pNFS/flexfiles: Remove a redundant parameter in ff_layout_encode_ioerr()
  pNFS/flexfiles: Fix a deadlock on LAYOUTGET
  pNFS: Layoutreturn must free the layout after the layout-private data
  pNFS/flexfiles: Fix ff_layout_add_ds_error_locked()
  NFSv4: Add missing nfs_put_lock_context()
  pNFS: Release NFS_LAYOUT_RETURN when invalidating the layout stateid
  NFSv4.1: Don't schedule lease recovery in nfs4_schedule_session_recovery()
  NFSv4.1: Handle NFS4ERR_BADSESSION/NFS4ERR_DEADSESSION replies to OP_SEQUENCE
  NFS: Only look at the change attribute cache state in nfs_check_verifier
  NFS: Fix incorrect size revalidation when holding a delegation
  NFS: Fix incorrect mapping revalidation when holding a delegation
  pNFS/flexfiles: Support sending layoutstats in layoutreturn
  pNFS/flexfiles: Minor refactoring before adding iostats to layoutreturn
  NFS: Fix up read of mirror stats
  pNFS/flexfiles: Clean up layoutstats
  pNFS/flexfiles: Refactor encoding of the layoutreturn payload
  pNFS: Add a layoutreturn callback to performa layout-private setup
  ...

1  2 
fs/nfs/inode.c

diff --combined fs/nfs/inode.c
@@@ -634,15 -634,28 +634,28 @@@ void nfs_setattr_update_inode(struct in
  }
  EXPORT_SYMBOL_GPL(nfs_setattr_update_inode);
  
- static void nfs_request_parent_use_readdirplus(struct dentry *dentry)
+ static void nfs_readdirplus_parent_cache_miss(struct dentry *dentry)
  {
        struct dentry *parent;
  
+       if (!nfs_server_capable(d_inode(dentry), NFS_CAP_READDIRPLUS))
+               return;
        parent = dget_parent(dentry);
        nfs_force_use_readdirplus(d_inode(parent));
        dput(parent);
  }
  
+ static void nfs_readdirplus_parent_cache_hit(struct dentry *dentry)
+ {
+       struct dentry *parent;
+       if (!nfs_server_capable(d_inode(dentry), NFS_CAP_READDIRPLUS))
+               return;
+       parent = dget_parent(dentry);
+       nfs_advise_use_readdirplus(d_inode(parent));
+       dput(parent);
+ }
  static bool nfs_need_revalidate_inode(struct inode *inode)
  {
        if (NFS_I(inode)->cache_validity &
@@@ -683,10 -696,10 +696,10 @@@ int nfs_getattr(struct vfsmount *mnt, s
        if (need_atime || nfs_need_revalidate_inode(inode)) {
                struct nfs_server *server = NFS_SERVER(inode);
  
-               if (server->caps & NFS_CAP_READDIRPLUS)
-                       nfs_request_parent_use_readdirplus(dentry);
+               nfs_readdirplus_parent_cache_miss(dentry);
                err = __nfs_revalidate_inode(server, inode);
-       }
+       } else
+               nfs_readdirplus_parent_cache_hit(dentry);
        if (!err) {
                generic_fillattr(inode, stat);
                stat->ino = nfs_compat_user_ino64(NFS_FILEID(inode));
@@@ -702,8 -715,7 +715,7 @@@ EXPORT_SYMBOL_GPL(nfs_getattr)
  static void nfs_init_lock_context(struct nfs_lock_context *l_ctx)
  {
        atomic_set(&l_ctx->count, 1);
-       l_ctx->lockowner.l_owner = current->files;
-       l_ctx->lockowner.l_pid = current->tgid;
+       l_ctx->lockowner = current->files;
        INIT_LIST_HEAD(&l_ctx->list);
        atomic_set(&l_ctx->io_count, 0);
  }
@@@ -714,9 -726,7 +726,7 @@@ static struct nfs_lock_context *__nfs_f
        struct nfs_lock_context *pos = head;
  
        do {
-               if (pos->lockowner.l_owner != current->files)
-                       continue;
-               if (pos->lockowner.l_pid != current->tgid)
+               if (pos->lockowner != current->files)
                        continue;
                atomic_inc(&pos->count);
                return pos;
@@@ -799,7 -809,9 +809,9 @@@ void nfs_close_context(struct nfs_open_
  }
  EXPORT_SYMBOL_GPL(nfs_close_context);
  
- struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, fmode_t f_mode)
+ struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry,
+                                               fmode_t f_mode,
+                                               struct file *filp)
  {
        struct nfs_open_context *ctx;
        struct rpc_cred *cred = rpc_lookup_cred();
        ctx->mode = f_mode;
        ctx->flags = 0;
        ctx->error = 0;
+       ctx->flock_owner = (fl_owner_t)filp;
        nfs_init_lock_context(&ctx->lock_context);
        ctx->lock_context.open_context = ctx;
        INIT_LIST_HEAD(&ctx->list);
@@@ -942,7 -955,7 +955,7 @@@ int nfs_open(struct inode *inode, struc
  {
        struct nfs_open_context *ctx;
  
-       ctx = alloc_nfs_open_context(file_dentry(filp), filp->f_mode);
+       ctx = alloc_nfs_open_context(file_dentry(filp), filp->f_mode, filp);
        if (IS_ERR(ctx))
                return PTR_ERR(ctx);
        nfs_file_set_open_context(filp, ctx);
@@@ -1099,11 -1112,17 +1112,17 @@@ static int nfs_invalidate_mapping(struc
        return 0;
  }
  
static bool nfs_mapping_need_revalidate_inode(struct inode *inode)
+ bool nfs_mapping_need_revalidate_inode(struct inode *inode)
  {
-       if (nfs_have_delegated_attributes(inode))
-               return false;
-       return (NFS_I(inode)->cache_validity & NFS_INO_REVAL_PAGECACHE)
+       unsigned long cache_validity = NFS_I(inode)->cache_validity;
+       if (NFS_PROTO(inode)->have_delegation(inode, FMODE_READ)) {
+               const unsigned long force_reval =
+                       NFS_INO_REVAL_PAGECACHE|NFS_INO_REVAL_FORCED;
+               return (cache_validity & force_reval) == force_reval;
+       }
+       return (cache_validity & NFS_INO_REVAL_PAGECACHE)
                || nfs_attribute_timeout(inode)
                || NFS_STALE(inode);
  }
@@@ -1317,7 -1336,7 +1336,7 @@@ static int nfs_check_inode_attributes(s
                invalid |= NFS_INO_INVALID_ATIME;
  
        if (invalid != 0)
-               nfs_set_cache_invalid(inode, invalid);
+               nfs_set_cache_invalid(inode, invalid | NFS_INO_REVAL_FORCED);
  
        nfsi->read_cache_jiffies = fattr->time_start;
        return 0;
@@@ -2015,7 -2034,7 +2034,7 @@@ static void nfsiod_stop(void
        destroy_workqueue(wq);
  }
  
 -int nfs_net_id;
 +unsigned int nfs_net_id;
  EXPORT_SYMBOL_GPL(nfs_net_id);
  
  static int nfs_net_init(struct net *net)