zfs_ctldir.c revision ecd6cf800b63704be73fb264c3f5b6e0dafc068d
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * CDDL HEADER START
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * The contents of this file are subject to the terms of the
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Common Development and Distribution License (the "License").
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * You may not use this file except in compliance with the License.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * or http://www.opensolaris.org/os/licensing.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * See the License for the specific language governing permissions
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * and limitations under the License.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * When distributing Covered Code, include this CDDL HEADER in each
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * If applicable, add the following below this CDDL HEADER, with the
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * fields enclosed by brackets "[]" replaced with your own identifying
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * information: Portions Copyright [yyyy] [name of copyright owner]
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * CDDL HEADER END
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Use is subject to license terms.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#pragma ident "%Z%%M% %I% %E% SMI"
1d32ba663e202c24a5a1f2e5aef83fffb447cb7fJohn Wren Kennedy * ZFS control directory (a.k.a. ".zfs")
1d32ba663e202c24a5a1f2e5aef83fffb447cb7fJohn Wren Kennedy * This directory provides a common location for all ZFS meta-objects.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Currently, this is only the 'snapshot' directory, but this may expand in the
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * future. The elements are built using the GFS primitives, as the hierarchy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * does not actually exist on disk.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * For 'snapshot', we don't want to have all snapshots always mounted, because
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * this would take up a huge amount of space in /etc/mnttab. We have three
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * types of objects:
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * ctldir ------> snapshotdir -------> snapshot
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * The 'snapshot' node contains just enough information to lookup '..' and act
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * as a mountpoint for the snapshot. Whenever we lookup a specific snapshot, we
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * perform an automount of the underlying filesystem and return the
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * corresponding vnode.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * All mounts are handled automatically by the kernel, but unmounts are
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * (currently) handled from user land. The main reason is that there is no
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * reliable way to auto-unmount the filesystem when it's "no longer in use".
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * When the user unmounts a filesystem, we call zfsctl_unmount(), which
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * unmounts any snapshots within the snapshot directory.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedytypedef struct {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedysnapentry_compare(const void *a, const void *b)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int ret = strcmp(sa->se_name, sb->se_name);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy else if (ret > 0)
1d32ba663e202c24a5a1f2e5aef83fffb447cb7fJohn Wren Kennedystatic const fs_operation_def_t zfsctl_tops_root[];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic const fs_operation_def_t zfsctl_tops_snapdir[];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic const fs_operation_def_t zfsctl_tops_snapshot[];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic vnode_t *zfsctl_mknode_snapdir(vnode_t *);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic vnode_t *zfsctl_snapshot_mknode(vnode_t *, uint64_t objset);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy { ".zfs", zfsctl_tops_root, &zfsctl_ops_root },
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy { ".zfs/snapshot", zfsctl_tops_snapdir, &zfsctl_ops_snapdir },
1d32ba663e202c24a5a1f2e5aef83fffb447cb7fJohn Wren Kennedy { ".zfs/snapshot/vnode", zfsctl_tops_snapshot, &zfsctl_ops_snapshot },
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedytypedef struct zfsctl_node {
typedef struct zfsctl_snapdir {
{ NULL }
zfsctl_init(void)
zfsctl_fini(void)
if (zfsctl_ops_root)
if (zfsctl_ops_snapdir)
if (zfsctl_ops_snapshot)
static ino64_t
return (ZFSCTL_INO_SNAPDIR);
vnode_t *
return (EACCES);
return (EACCES);
return (ENOSPC);
int err;
return (err);
{ NULL }
return (ENAMETOOLONG);
int err;
return (ENOENT);
return (err);
if (err) {
return (err);
char *tail;
int err;
if (err)
return (err);
if (err)
return (err);
return (err);
return (EINVAL);
return (ENOENT);
if (err == 0)
return (err);
int err;
if (err)
return (err);
return (err);
if (err) {
return (err);
return (err);
int err;
if (err)
return (err);
if (err == 0) {
if (err)
return (err);
return (err);
char *mountpoint;
int err;
return (ENOENT);
if (err) {
goto domount;
return (err);
if (err) {
return (err);
return (ENOENT);
if (err == 0) {
if (err == 0) {
if (err) {
return (err);
vnode_t *
return (vp);
void *private;
{ NULL }
static vnode_t *
return (vp);
int error;
if (error != 0)
return (error);
if (error == 0) {
return (error);
int error;
if (error != 0)
return (error);
goto out;
if (error) {
goto out;
out:
return (error);