diff options
author | pjd <pjd@FreeBSD.org> | 2009-09-07 21:46:51 +0000 |
---|---|---|
committer | pjd <pjd@FreeBSD.org> | 2009-09-07 21:46:51 +0000 |
commit | a72e4e5b626034fcb1d56c7b5856d1768f18a16a (patch) | |
tree | 7a0f299356a447b98485d1349d76256094832818 /sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c | |
parent | 7761ee5e271ffbe5df4b67f56171d6ed5ad13c86 (diff) | |
download | FreeBSD-src-a72e4e5b626034fcb1d56c7b5856d1768f18a16a.zip FreeBSD-src-a72e4e5b626034fcb1d56c7b5856d1768f18a16a.tar.gz |
When snapshot mount point is busy (for example we are still in it)
we will fail to unmount it, but it won't be removed from the tree,
so in that case there is no need to reinsert it.
This fixes a panic reproducable in the following steps:
# zfs create tank/foo
# zfs snapshot tank/foo@snap
# cd /tank/foo/.zfs/snapshot/snap
# umount /tank/foo
panic: avl_find() succeeded inside avl_add()
Reported by: trasz
MFC after: 3 days
Diffstat (limited to 'sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c')
-rw-r--r-- | sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c index cf99d68..7430c83 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c @@ -1344,7 +1344,15 @@ zfsctl_umount_snapshots(vfs_t *vfsp, int fflags, cred_t *cr) if (vn_ismntpt(sep->se_root)) { error = zfsctl_unmount_snap(sep, fflags, cr); if (error) { - avl_add(&sdp->sd_snaps, sep); + /* + * Before reinserting snapshot to the tree, + * check if it was actually removed. For example + * when snapshot mount point is busy, we will + * have an error here, but there will be no need + * to reinsert snapshot. + */ + if (avl_find(&sdp->sd_snaps, sep, NULL) == NULL) + avl_add(&sdp->sd_snaps, sep); break; } } |