NFSv4.2: Always flush out writes in nfs42_proc_fallocate()
authorTrond Myklebust <trond.myklebust@hammerspace.com>
Sun, 28 Mar 2021 22:17:14 +0000 (18:17 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 22 May 2021 08:40:31 +0000 (10:40 +0200)
[ Upstream commit 99f23783224355e7022ceea9b8d9f62c0fd01bd8 ]

Whether we're allocating or delallocating space, we should flush out the
pending writes in order to avoid races with attribute updates.

Fixes: 1e564d3dbd68 ("NFSv4.2: Fix a race in nfs42_proc_deallocate()")
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/nfs/nfs42proc.c

index 5cda392028ce10c66ea235217ad0b1094d0913e2..7e9fb1119bcf707f02e95460e06dad12644b5bcd 100644 (file)
@@ -56,7 +56,8 @@ static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
 static int nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
                                loff_t offset, loff_t len)
 {
-       struct nfs_server *server = NFS_SERVER(file_inode(filep));
+       struct inode *inode = file_inode(filep);
+       struct nfs_server *server = NFS_SERVER(inode);
        struct nfs4_exception exception = { };
        struct nfs_lock_context *lock;
        int err;
@@ -65,9 +66,13 @@ static int nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
        if (IS_ERR(lock))
                return PTR_ERR(lock);
 
-       exception.inode = file_inode(filep);
+       exception.inode = inode;
        exception.state = lock->open_context->state;
 
+       err = nfs_sync_inode(inode);
+       if (err)
+               goto out;
+
        do {
                err = _nfs42_proc_fallocate(msg, filep, lock, offset, len);
                if (err == -ENOTSUPP) {
@@ -76,7 +81,7 @@ static int nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
                }
                err = nfs4_handle_exception(server, err, &exception);
        } while (exception.retry);
-
+out:
        nfs_put_lock_context(lock);
        return err;
 }
@@ -114,16 +119,13 @@ int nfs42_proc_deallocate(struct file *filep, loff_t offset, loff_t len)
                return -EOPNOTSUPP;
 
        inode_lock(inode);
-       err = nfs_sync_inode(inode);
-       if (err)
-               goto out_unlock;
 
        err = nfs42_proc_fallocate(&msg, filep, offset, len);
        if (err == 0)
                truncate_pagecache_range(inode, offset, (offset + len) -1);
        if (err == -EOPNOTSUPP)
                NFS_SERVER(inode)->caps &= ~NFS_CAP_DEALLOCATE;
-out_unlock:
+
        inode_unlock(inode);
        return err;
 }