NFSv4: Add lease breakpoints in case of a delegation recall or return
authorTrond Myklebust <trond.myklebust@hammerspace.com>
Fri, 7 May 2021 13:14:37 +0000 (09:14 -0400)
committerTrond Myklebust <trond.myklebust@hammerspace.com>
Sun, 13 Jun 2021 23:36:28 +0000 (19:36 -0400)
When we add support for application level leases and knfsd delegations
to the NFS client, we we want to have them safely underpinned by a
"real" delegation to provide the caching guarantees. If that real
delegation is recalled, then we need to ensure that the application
leases/delegations are recalled too.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
fs/nfs/delegation.c

index 7c45ac3c3b0b5a04392369cd2ccd917ab3f75f96..11118398f495c1ae180db8a9dcce5e8acee4a73e 100644 (file)
@@ -530,11 +530,18 @@ out:
 static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation *delegation, int issync)
 {
        struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
+       unsigned int mode = O_WRONLY | O_RDWR;
        int err = 0;
 
        if (delegation == NULL)
                return 0;
-       do {
+
+       if (!issync)
+               mode |= O_NONBLOCK;
+       /* Recall of any remaining application leases */
+       err = break_lease(inode, mode);
+
+       while (err == 0) {
                if (test_bit(NFS_DELEGATION_REVOKED, &delegation->flags))
                        break;
                err = nfs_delegation_claim_opens(inode, &delegation->stateid,
@@ -545,7 +552,7 @@ static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation
                 * Guard against state recovery
                 */
                err = nfs4_wait_clnt_recover(clp);
-       } while (err == 0);
+       }
 
        if (err) {
                nfs_abort_delegation_return(delegation, clp, err);
@@ -746,13 +753,14 @@ int nfs4_inode_return_delegation(struct inode *inode)
 {
        struct nfs_inode *nfsi = NFS_I(inode);
        struct nfs_delegation *delegation;
-       int err = 0;
 
-       nfs_wb_all(inode);
        delegation = nfs_start_delegation_return(nfsi);
+       /* Synchronous recall of any application leases */
+       break_lease(inode, O_WRONLY | O_RDWR);
+       nfs_wb_all(inode);
        if (delegation != NULL)
-               err = nfs_end_delegation_return(inode, delegation, 1);
-       return err;
+               return nfs_end_delegation_return(inode, delegation, 1);
+       return 0;
 }
 
 /**
@@ -1051,6 +1059,9 @@ int nfs_async_inode_return_delegation(struct inode *inode,
        nfs_mark_return_delegation(server, delegation);
        rcu_read_unlock();
 
+       /* If there are any application leases or delegations, recall them */
+       break_lease(inode, O_WRONLY | O_RDWR | O_NONBLOCK);
+
        nfs_delegation_run_state_manager(clp);
        return 0;
 out_enoent: