Do not hash unlinked inodes
In zfs_znode_alloc we always hash inodes. If the znode is unlinked, we do not need to hash it. This fixes the problem where zfs_suspend_fs is doing zrele (iput) in an async fashion, and zfs_resume_fs unlinked drain processing will try to hash an inode that could still be hashed, resulting in a panic. Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Alan Somers <asomers@gmail.com> Signed-off-by: Paul Zuchowski <pzuchowski@datto.com> Closes #9741 Closes #11223 Closes #11648 Closes #12210
This commit is contained in:
parent
a416b29e16
commit
bd83c1e0c6
|
@ -606,9 +606,15 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
|
||||||
* number is already hashed for this super block. This can never
|
* number is already hashed for this super block. This can never
|
||||||
* happen because the inode numbers map 1:1 with the object numbers.
|
* happen because the inode numbers map 1:1 with the object numbers.
|
||||||
*
|
*
|
||||||
* The one exception is rolling back a mounted file system, but in
|
* Exceptions include rolling back a mounted file system, either
|
||||||
* this case all the active inode are unhashed during the rollback.
|
* from the zfs rollback or zfs recv command.
|
||||||
|
*
|
||||||
|
* Active inodes are unhashed during the rollback, but since zrele
|
||||||
|
* can happen asynchronously, we can't guarantee they've been
|
||||||
|
* unhashed. This can cause hash collisions in unlinked drain
|
||||||
|
* processing so do not hash unlinked znodes.
|
||||||
*/
|
*/
|
||||||
|
if (links > 0)
|
||||||
VERIFY3S(insert_inode_locked(ip), ==, 0);
|
VERIFY3S(insert_inode_locked(ip), ==, 0);
|
||||||
|
|
||||||
mutex_enter(&zfsvfs->z_znodes_lock);
|
mutex_enter(&zfsvfs->z_znodes_lock);
|
||||||
|
@ -616,6 +622,7 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
|
||||||
zfsvfs->z_nr_znodes++;
|
zfsvfs->z_nr_znodes++;
|
||||||
mutex_exit(&zfsvfs->z_znodes_lock);
|
mutex_exit(&zfsvfs->z_znodes_lock);
|
||||||
|
|
||||||
|
if (links > 0)
|
||||||
unlock_new_inode(ip);
|
unlock_new_inode(ip);
|
||||||
return (zp);
|
return (zp);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue