- err = zfsctl_snapshot_zname(dvp, nm, MAXNAMELEN, snapname);
- if (err) {
- mutex_exit(&sdp->sd_lock);
- ZFS_EXIT(zfsvfs);
- /*
- * handle "ls *" or "?" in a graceful manner,
- * forcing EILSEQ to ENOENT.
- * Since shell ultimately passes "*" or "?" as name to lookup
- */
- return (err == EILSEQ ? ENOENT : err);
- }
- if (dmu_objset_open(snapname, DMU_OST_ZFS,
- DS_MODE_USER | DS_MODE_READONLY, &snap) != 0) {
- mutex_exit(&sdp->sd_lock);
- ZFS_EXIT(zfsvfs);
- return (ENOENT);
- }
-
- sep = kmem_alloc(sizeof (zfs_snapentry_t), KM_SLEEP);
- sep->se_name = kmem_alloc(strlen(nm) + 1, KM_SLEEP);
- (void) strcpy(sep->se_name, nm);
- *vpp = sep->se_root = zfsctl_snapshot_mknode(dvp, dmu_objset_id(snap));
- avl_insert(&sdp->sd_snaps, sep, where);
-
- dmu_objset_close(snap);
-domount:
- mountpoint_len = strlen(refstr_value(dvp->v_vfsp->vfs_mntpt)) +
- strlen("/.zfs/snapshot/") + strlen(nm) + 1;
- mountpoint = kmem_alloc(mountpoint_len, KM_SLEEP);
- (void) snprintf(mountpoint, mountpoint_len, "%s/.zfs/snapshot/%s",
- refstr_value(dvp->v_vfsp->vfs_mntpt), nm);
-
- margs.spec = snapname;
- margs.dir = mountpoint;
- margs.flags = MS_SYSSPACE | MS_NOMNTTAB;
- margs.fstype = "zfs";
- margs.dataptr = NULL;
- margs.datalen = 0;
- margs.optptr = NULL;
- margs.optlen = 0;
-
- err = domount("zfs", &margs, *vpp, kcred, &vfsp);
- kmem_free(mountpoint, mountpoint_len);
-
- if (err == 0) {
- /*
- * Return the mounted root rather than the covered mount point.
- * Takes the GFS vnode at .zfs/snapshot/<snapname> and returns
- * the ZFS vnode mounted on top of the GFS node. This ZFS
- * vnode is the root the newly created vfsp.
- */
- VFS_RELE(vfsp);
- err = traverse(vpp);
- }
-
- if (err == 0) {
- /*
- * Fix up the root vnode mounted on .zfs/snapshot/<snapname>.
- *
- * This is where we lie about our v_vfsp in order to
- * make .zfs/snapshot/<snapname> accessible over NFS
- * without requiring manual mounts of <snapname>.
- */
- ASSERT(VTOZ(*vpp)->z_zfsvfs != zfsvfs);
- VTOZ(*vpp)->z_zfsvfs->z_parent = zfsvfs;
- (*vpp)->v_vfsp = zfsvfs->z_vfs;
- (*vpp)->v_flag &= ~VROOT;
- }
- mutex_exit(&sdp->sd_lock);
- ZFS_EXIT(zfsvfs);