mirror of
https://github.com/versity/scoutfs.git
synced 2026-06-08 04:32:35 +00:00
scoutfs: force locks idle as shutdown frees
Usually lock_free() is called as users finish using a lock and when its state shows that it is idle and won't be freed out from under another use. During shutdown we manually call lock_free() on all locks because shutdown promises that there will be no more lock users, including networking callbacks. But there is a case where network requests can be pending and we shutdown before waiting for their reply. This trips BUG_ON assertions in lock_free() that would otherwise catch unsafe calls of lock_free(). This is easiest to reproduce by interrupting a mount (which is waiting on a lock to read the root inode). The fix is to update each lock's state during shutdown to reflect the promise made by shutdown. Requests aren't actually pending because we've shutdown networking befrore getting here. Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
@@ -1492,14 +1492,19 @@ void scoutfs_lock_destroy(struct super_block *sb)
|
||||
debugfs_remove(linfo->tseq_dentry);
|
||||
|
||||
/*
|
||||
* This is very clumsy and brute force. This will be cleaned up
|
||||
* as we add proper lock recovery.
|
||||
* Usually lock_free is only called once locks are idle but all
|
||||
* locks are idle by definition during shutdown. We need to
|
||||
* manually update the lock's state to reflect that we've given
|
||||
* up on pending work that would otherwise prevent free from
|
||||
* being called (and would trip assertions in our manual calling
|
||||
* of free).
|
||||
*/
|
||||
spin_lock(&linfo->lock);
|
||||
node = rb_first(&linfo->lock_tree);
|
||||
while (node) {
|
||||
lock = rb_entry(node, struct scoutfs_lock, node);
|
||||
node = rb_next(node);
|
||||
lock->request_pending = 0;
|
||||
if (!list_empty(&lock->lru_head))
|
||||
__lock_del_lru(linfo, lock);
|
||||
lock_remove(linfo, lock);
|
||||
|
||||
Reference in New Issue
Block a user