Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

NFSv4.x: Directory delegations don't require any state recovery

The state recovery code in nfs_end_delegation_return() is intended to
allow regular files to recover cached open and lock state. It has no
function for directory delegations, and may cause corruption.

Fixes: 156b09482933 ("NFS: Request a directory delegation on ACCESS, CREATE, and UNLINK")
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>

+10 -1
+5
fs/nfs/delegation.c
··· 581 581 if (delegation == NULL) 582 582 return 0; 583 583 584 + /* Directory delegations don't require any state recovery */ 585 + if (!S_ISREG(inode->i_mode)) 586 + goto out_return; 587 + 584 588 if (!issync) 585 589 mode |= O_NONBLOCK; 586 590 /* Recall of any remaining application leases */ ··· 608 604 goto out; 609 605 } 610 606 607 + out_return: 611 608 err = nfs_do_return_delegation(inode, delegation, issync); 612 609 out: 613 610 /* Refcount matched in nfs_start_delegation_return_locked() */
+5 -1
fs/nfs/nfs4state.c
··· 1445 1445 struct nfs4_state *state; 1446 1446 bool found = false; 1447 1447 1448 + if (!S_ISREG(inode->i_mode)) 1449 + goto out; 1448 1450 rcu_read_lock(); 1449 1451 list_for_each_entry_rcu(ctx, &nfsi->open_files, list) { 1450 1452 state = ctx->state; ··· 1468 1466 found = true; 1469 1467 } 1470 1468 rcu_read_unlock(); 1471 - 1469 + out: 1472 1470 nfs_inode_find_delegation_state_and_recover(inode, stateid); 1473 1471 if (found) 1474 1472 nfs4_schedule_state_manager(clp); ··· 1480 1478 struct nfs_inode *nfsi = NFS_I(inode); 1481 1479 struct nfs_open_context *ctx; 1482 1480 1481 + if (!S_ISREG(inode->i_mode)) 1482 + return; 1483 1483 rcu_read_lock(); 1484 1484 list_for_each_entry_rcu(ctx, &nfsi->open_files, list) { 1485 1485 if (ctx->state != state)