Author: pjd Date: Sat Sep 26 00:10:45 2009 New Revision: 197515 URL: http://svn.freebsd.org/changeset/base/197515
Log: Handle cases where virtual (GFS) vnodes are referenced when doing forced unmount. In that case we cannot depend on the proper order of invalidating vnodes, so we have to free resources when we have a chance. PR: kern/139062 Reported by: trasz MFC after: 3 days Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c ============================================================================== --- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c Sat Sep 26 00:08:44 2009 (r197514) +++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c Sat Sep 26 00:10:45 2009 (r197515) @@ -1007,15 +1007,24 @@ zfsctl_snapdir_inactive(ap) { vnode_t *vp = ap->a_vp; zfsctl_snapdir_t *sdp = vp->v_data; - void *private; + zfs_snapentry_t *sep; - private = gfs_dir_inactive(vp); - if (private != NULL) { - ASSERT(avl_numnodes(&sdp->sd_snaps) == 0); - mutex_destroy(&sdp->sd_lock); - avl_destroy(&sdp->sd_snaps); - kmem_free(private, sizeof (zfsctl_snapdir_t)); + /* + * On forced unmount we have to free snapshots from here. + */ + mutex_enter(&sdp->sd_lock); + while ((sep = avl_first(&sdp->sd_snaps)) != NULL) { + avl_remove(&sdp->sd_snaps, sep); + kmem_free(sep->se_name, strlen(sep->se_name) + 1); + kmem_free(sep, sizeof (zfs_snapentry_t)); } + mutex_exit(&sdp->sd_lock); + gfs_dir_inactive(vp); + ASSERT(avl_numnodes(&sdp->sd_snaps) == 0); + mutex_destroy(&sdp->sd_lock); + avl_destroy(&sdp->sd_snaps); + kmem_free(sdp, sizeof (zfsctl_snapdir_t)); + return (0); } @@ -1073,6 +1082,9 @@ zfsctl_snapshot_inactive(ap) int locked; vnode_t *dvp; + if (vp->v_count > 0) + goto end; + VERIFY(gfs_dir_lookup(vp, "..", &dvp, cr, 0, NULL, NULL) == 0); sdp = dvp->v_data; VOP_UNLOCK(dvp, 0); @@ -1080,11 +1092,6 @@ zfsctl_snapshot_inactive(ap) if (!(locked = MUTEX_HELD(&sdp->sd_lock))) mutex_enter(&sdp->sd_lock); - if (vp->v_count > 1) { - if (!locked) - mutex_exit(&sdp->sd_lock); - return (0); - } ASSERT(!vn_ismntpt(vp)); sep = avl_first(&sdp->sd_snaps); @@ -1104,6 +1111,7 @@ zfsctl_snapshot_inactive(ap) if (!locked) mutex_exit(&sdp->sd_lock); VN_RELE(dvp); +end: VFS_RELE(vp->v_vfsp); /* Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c ============================================================================== --- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c Sat Sep 26 00:08:44 2009 (r197514) +++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c Sat Sep 26 00:10:45 2009 (r197515) @@ -1107,8 +1107,7 @@ zfs_umount(vfs_t *vfsp, int fflag) if (zfsvfs->z_issnap) { vnode_t *svp = vfsp->mnt_vnodecovered; - ASSERT(svp->v_count == 2 || svp->v_count == 1); - if (svp->v_count == 2) + if (svp->v_count >= 2) VN_RELE(svp); } zfs_freevfs(vfsp); _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"