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)
committerTrond Myklebust <trond.myklebust@hammerspace.com>
Mon, 12 Apr 2021 21:14:17 +0000 (17:14 -0400)
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>
fs/nfs/nfs42proc.c

index 597005b..704a524 100644 (file)
@@ -90,7 +90,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;
@@ -99,9 +100,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) {
@@ -110,7 +115,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;
 }
@@ -148,16 +153,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;
 }