Merge tag 'nfs-for-4.13-3' of git://git.linux-nfs.org/projects/anna/linux-nfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 28 Jul 2017 21:44:56 +0000 (14:44 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 28 Jul 2017 21:44:56 +0000 (14:44 -0700)
Pull NFS client fixes from Anna Schumaker:
 "More NFS client bugfixes for 4.13.

  Most of these fix locking bugs that Ben and Neil noticed, but I also
  have a patch to fix one more access bug that was reported after last
  week.

  Stable fixes:
   - Fix a race where CB_NOTIFY_LOCK fails to wake a waiter
   - Invalidate file size when taking a lock to prevent corruption

  Other fixes:
   - Don't excessively generate tiny writes with fallocate
   - Use the raw NFS access mask in nfs4_opendata_access()"

* tag 'nfs-for-4.13-3' of git://git.linux-nfs.org/projects/anna/linux-nfs:
  NFSv4.1: Fix a race where CB_NOTIFY_LOCK fails to wake a waiter
  NFS: Optimize fallocate by refreshing mapping when needed.
  NFS: invalidate file size when taking a lock.
  NFS: Use raw NFS access mask in nfs4_opendata_access()

1  2 
fs/nfs/nfs4proc.c

diff --combined fs/nfs/nfs4proc.c
@@@ -2236,7 -2236,7 +2236,7 @@@ static int nfs4_opendata_access(struct 
                                int openflags)
  {
        struct nfs_access_entry cache;
-       u32 mask;
+       u32 mask, flags;
  
        /* access call failed or for some reason the server doesn't
         * support any access modes -- defer access call until later */
         */
        if (openflags & __FMODE_EXEC) {
                /* ONLY check for exec rights */
-               mask = MAY_EXEC;
+               if (S_ISDIR(state->inode->i_mode))
+                       mask = NFS4_ACCESS_LOOKUP;
+               else
+                       mask = NFS4_ACCESS_EXECUTE;
        } else if ((fmode & FMODE_READ) && !opendata->file_created)
-               mask = MAY_READ;
+               mask = NFS4_ACCESS_READ;
  
        cache.cred = cred;
        cache.jiffies = jiffies;
        nfs_access_set_mask(&cache, opendata->o_res.access_result);
        nfs_access_add_cache(state->inode, &cache);
  
-       if ((mask & ~cache.mask & (MAY_READ | MAY_EXEC)) == 0)
+       flags = NFS4_ACCESS_READ | NFS4_ACCESS_EXECUTE | NFS4_ACCESS_LOOKUP;
+       if ((mask & ~cache.mask & flags) == 0)
                return 0;
  
        return -EACCES;
@@@ -2592,8 -2596,7 +2596,8 @@@ static inline void nfs4_exclusive_attrs
  
        /* Except MODE, it seems harmless of setting twice. */
        if (opendata->o_arg.createmode != NFS4_CREATE_EXCLUSIVE &&
 -              attrset[1] & FATTR4_WORD1_MODE)
 +              (attrset[1] & FATTR4_WORD1_MODE ||
 +               attrset[2] & FATTR4_WORD2_MODE_UMASK))
                sattr->ia_valid &= ~ATTR_MODE;
  
        if (attrset[2] & FATTR4_WORD2_SECURITY_LABEL)
@@@ -6424,7 -6427,7 +6428,7 @@@ struct nfs4_lock_waiter 
  };
  
  static int
 -nfs4_wake_lock_waiter(wait_queue_t *wait, unsigned int mode, int flags, void *key)
 +nfs4_wake_lock_waiter(wait_queue_entry_t *wait, unsigned int mode, int flags, void *key)
  {
        int ret;
        struct cb_notify_lock_args *cbnl = key;
@@@ -6467,7 -6470,7 +6471,7 @@@ nfs4_retry_setlk(struct nfs4_state *sta
                                           .inode = state->inode,
                                           .owner = &owner,
                                           .notified = false };
 -      wait_queue_t wait;
 +      wait_queue_entry_t wait;
  
        /* Don't bother with waitqueue if we don't expect a callback */
        if (!test_bit(NFS_STATE_MAY_NOTIFY_LOCK, &state->flags))
                set_current_state(TASK_INTERRUPTIBLE);
                spin_unlock_irqrestore(&q->lock, flags);
  
-               freezable_schedule_timeout_interruptible(NFS4_LOCK_MAXTIMEOUT);
+               freezable_schedule_timeout(NFS4_LOCK_MAXTIMEOUT);
        }
  
        finish_wait(q, &wait);
@@@ -8467,7 -8470,6 +8471,7 @@@ static void nfs4_layoutget_release(voi
        size_t max_pages = max_response_pages(server);
  
        dprintk("--> %s\n", __func__);
 +      nfs4_sequence_free_slot(&lgp->res.seq_res);
        nfs4_free_pages(lgp->args.layout.pages, max_pages);
        pnfs_put_layout_hdr(NFS_I(inode)->layout);
        put_nfs_open_context(lgp->args.ctx);
@@@ -8542,6 -8544,7 +8546,6 @@@ nfs4_proc_layoutget(struct nfs4_layoutg
        /* if layoutp->len is 0, nfs4_layoutget_prepare called rpc_exit */
        if (status == 0 && lgp->res.layoutp->len)
                lseg = pnfs_layout_process(lgp);
 -      nfs4_sequence_free_slot(&lgp->res.seq_res);
        rpc_put_task(task);
        dprintk("<-- %s status=%d\n", __func__, status);
        if (status)