NFSv4.1 support for NFS4_RESULT_PRESERVER_UNLINKED
authorOlga Kornievskaia <kolga@netapp.com>
Wed, 2 Feb 2022 22:55:02 +0000 (17:55 -0500)
committerTrond Myklebust <trond.myklebust@hammerspace.com>
Fri, 25 Feb 2022 23:50:12 +0000 (18:50 -0500)
In 4.1+, the server is allowed to set a flag
NFS4_RESULT_PRESERVE_UNLINKED in reply to the OPEN, that tells
the client that it does not need to do a silly rename of an
opened file when it's being removed.

Signed-off-by: Olga Kornievskaia <kolga@netapp.com>
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
fs/nfs/dir.c
fs/nfs/nfs4proc.c
include/linux/nfs_fs.h
include/uapi/linux/nfs4.h

index fbb4a52..8b190c8 100644 (file)
@@ -1419,7 +1419,12 @@ int nfs_lookup_verify_inode(struct inode *inode, unsigned int flags)
        if (flags & LOOKUP_REVAL)
                goto out_force;
 out:
-       return (inode->i_nlink == 0) ? -ESTALE : 0;
+       if (inode->i_nlink > 0 ||
+           (inode->i_nlink == 0 &&
+            test_bit(NFS_INO_PRESERVE_UNLINKED, &NFS_I(inode)->flags)))
+               return 0;
+       else
+               return -ESTALE;
 out_force:
        if (flags & LOOKUP_RCU)
                return -ECHILD;
@@ -2330,7 +2335,8 @@ int nfs_unlink(struct inode *dir, struct dentry *dentry)
 
        trace_nfs_unlink_enter(dir, dentry);
        spin_lock(&dentry->d_lock);
-       if (d_count(dentry) > 1) {
+       if (d_count(dentry) > 1 && !test_bit(NFS_INO_PRESERVE_UNLINKED,
+                                            &NFS_I(d_inode(dentry))->flags)) {
                spin_unlock(&dentry->d_lock);
                /* Start asynchronous writeout of the inode */
                write_inode_now(d_inode(dentry), 0);
index b3793b8..73a9b6d 100644 (file)
@@ -3050,6 +3050,8 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
                set_bit(NFS_STATE_POSIX_LOCKS, &state->flags);
        if (opendata->o_res.rflags & NFS4_OPEN_RESULT_MAY_NOTIFY_LOCK)
                set_bit(NFS_STATE_MAY_NOTIFY_LOCK, &state->flags);
+       if (opendata->o_res.rflags & NFS4_OPEN_RESULT_PRESERVE_UNLINKED)
+               set_bit(NFS_INO_PRESERVE_UNLINKED, &NFS_I(state->inode)->flags);
 
        dentry = opendata->dentry;
        if (d_really_is_negative(dentry)) {
index 333ea05..0e79dbb 100644 (file)
@@ -277,6 +277,7 @@ struct nfs4_copy_state {
 #define NFS_INO_STALE          (1)             /* possible stale inode */
 #define NFS_INO_ACL_LRU_SET    (2)             /* Inode is on the LRU list */
 #define NFS_INO_INVALIDATING   (3)             /* inode is being invalidated */
+#define NFS_INO_PRESERVE_UNLINKED (4)          /* preserve file if removed while open */
 #define NFS_INO_FSCACHE                (5)             /* inode can be cached by FS-Cache */
 #define NFS_INO_FORCE_READDIR  (7)             /* force readdirplus */
 #define NFS_INO_LAYOUTCOMMIT   (9)             /* layoutcommit required */
index 800bb0f..1d20437 100644 (file)
@@ -45,6 +45,7 @@
 
 #define NFS4_OPEN_RESULT_CONFIRM               0x0002
 #define NFS4_OPEN_RESULT_LOCKTYPE_POSIX                0x0004
+#define NFS4_OPEN_RESULT_PRESERVE_UNLINKED     0x0008
 #define NFS4_OPEN_RESULT_MAY_NOTIFY_LOCK       0x0020
 
 #define NFS4_SHARE_ACCESS_MASK 0x000F