forked from openzfs/zfs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Wait for all znodes to be released before tearing down the superblock
By the time we're tearing down our superblock the VFS has started releasing all our inodes/znodes. Some of this work may have been handed off to our iput taskq so we need to wait for that work to complete. However the iput from the taskq can itself result in additional work being added to the taskq: dsl_pool_iput_taskq iput iput_final evict destroy_inode zpl_inode_destroy zfs_inode_destroy zfs_iput_async(ZTOI(zp->z_xattr_parent)) taskq_dispatch(dsl_pool_iput_taskq..., iput, ...) Let's wait until all our znodes have been released. Signed-off-by: Chris Dunlop <[email protected]> Closes openzfs#3281
- Loading branch information
Showing
1 changed file
with
9 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1130,15 +1130,20 @@ EXPORT_SYMBOL(zfs_sb_prune); | |
int | ||
zfs_sb_teardown(zfs_sb_t *zsb, boolean_t unmounting) | ||
{ | ||
znode_t *zp; | ||
|
||
/* | ||
* If someone has not already unmounted this file system, | ||
* drain the iput_taskq to ensure all active references to the | ||
* zfs_sb_t have been handled only then can it be safely destroyed. | ||
* | ||
* We can safely read z_nr_znodes without locking because the VFS | ||
* has already blocked operations which add to the z_all_znodes | ||
* list and increment z_nr_znodes. | ||
*/ | ||
if (zsb->z_os) | ||
taskq_wait(dsl_pool_iput_taskq(dmu_objset_pool(zsb->z_os))); | ||
while (zsb->z_nr_znodes) { | ||
schedule(); | ||
taskq_wait(dsl_pool_iput_taskq(dmu_objset_pool( | ||
zsb->z_os))); | ||
} | ||
This comment has been minimized.
Sorry, something went wrong. |
||
|
||
rrw_enter(&zsb->z_teardown_lock, RW_WRITER, FTAG); | ||
|
||
|
@@ -1175,21 +1180,6 @@ zfs_sb_teardown(zfs_sb_t *zsb, boolean_t unmounting) | |
return (SET_ERROR(EIO)); | ||
} | ||
|
||
/* | ||
* At this point there are no VFS ops active, and any new VFS ops | ||
* will fail with EIO since we have z_teardown_lock for writer (only | ||
* relevant for forced unmount). | ||
* | ||
* Release all holds on dbufs. | ||
*/ | ||
mutex_enter(&zsb->z_znodes_lock); | ||
for (zp = list_head(&zsb->z_all_znodes); zp != NULL; | ||
zp = list_next(&zsb->z_all_znodes, zp)) { | ||
if (zp->z_sa_hdl) | ||
zfs_znode_dmu_fini(zp); | ||
} | ||
mutex_exit(&zsb->z_znodes_lock); | ||
|
||
This comment has been minimized.
Sorry, something went wrong.
behlendorf
|
||
/* | ||
* If we are unmounting, set the unmounted flag and let new VFS ops | ||
* unblock. zfs_inactive will have the unmounted behavior, and all | ||
|
Yes, this is very close to what I had in mind, just a few comments.
zsb->z_nr_znodes
will drop to 0 in theunmounted == TRUE
case. For something like a rollback or a zfs receive there could potentially still be znodes pinned by open files.while (zsb->z_nr_znodes > 0) { }