usr/src/uts/common/fs/zfs/zfs_ctldir.c
author eschrock
Fri, 03 Mar 2006 20:08:16 -0800
changeset 1544 938876158511
parent 1512 dad2d74ca2cb
child 1566 93e41df9efa5
permissions -rw-r--r--
PSARC 2006/077 zpool clear PSARC 2006/139 FMA for ZFS 6284889 arc should replace the znode cache 6333006 DMU & DSL should not panic upon I/O error 6333092 concurrent reads to a file not scaling with number of readers 6338081 ZFS/FMA phase 1 6338386 need persistent error log 6341326 i/o error causes arc buf hash table corruption 6341639 zfs backup/restore should compute/verify checksum of backup stream 6348002 out of space due to changing properties 6354724 inaccurate error message from zfs restore 6354872 dmu_sync() blows predictive accounting 6355416 zpool scrubbing consumes all memory, system hung 6363995 df should only load libzfs when it encounters a ZFS filesystem 6366320 zfs backup/restore doesn't like signals 6368892 mount -m support needed for legacy mounts 6368902 boot archive fstat support needed for ZFS Mountroot 6369424 BFU complains when bfu'ing a ZFS root filesystem 6374062 mountroot support needed for ZFS 6376356 dirtying dbuf obj=43 lvl=0 blkid=0 but not tx_held 6378391 unused members of dmu_objset_stats_t 6378392 clean up zfs_cmd_t structure 6378685 buf_init should allocate its hash table more carefully 6378976 ziltest should be a first class citizen 6381086 zdb segfaults if there is a spa deferred-free bplist 6381203 deadlock due to i/o while assigning (tc_lock held) 6381209 freed space is not immediately available 6381344 'zpool clear' 6381345 FAULTED devices should really be UNAVAIL 6381346 import should mark devices as persistently unavailable 6383272 recursive mutex_enter() during log replay with zfs root 6386326 origin property is not displayed 6386354 libzfs does too much in its _init section, calls exit(1) 6386624 zpool should not complain about non-existent devices from libdiskmgt 6386910 spa needs to be i/o error hardened 6387735 need a mechanism to inject faults into ZFS 6387736 internal ZFS utilities should be placed in an ON-private package 6389928 libzfs should ship a lint library 6390609 malformed vdev config panics on zpool_create() 6390677 version number checking makes upgrades challenging 6390713 ztest hangs in zil_suspend() 6391873 metadata compression should be turned back on 6392113 ztest sometimes reports leaked blocks because ZIL isn't resilvered 6393004 minor memory leak in unique_insert()
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     1
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     2
 * CDDL HEADER START
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     3
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     4
 * The contents of this file are subject to the terms of the
1512
dad2d74ca2cb 6391609 zfs_fid() missing ZFS_EXIT()
ek110237
parents: 1298
diff changeset
     5
 * Common Development and Distribution License (the "License").
dad2d74ca2cb 6391609 zfs_fid() missing ZFS_EXIT()
ek110237
parents: 1298
diff changeset
     6
 * You may not use this file except in compliance with the License.
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     7
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     8
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     9
 * or http://www.opensolaris.org/os/licensing.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    10
 * See the License for the specific language governing permissions
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    11
 * and limitations under the License.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    12
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    13
 * When distributing Covered Code, include this CDDL HEADER in each
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    14
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    15
 * If applicable, add the following below this CDDL HEADER, with the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    16
 * fields enclosed by brackets "[]" replaced with your own identifying
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    17
 * information: Portions Copyright [yyyy] [name of copyright owner]
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    18
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    19
 * CDDL HEADER END
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    20
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    21
/*
1298
1a70f57b62f0 6368181 some memleaks found related to zfs mount
perrin
parents: 1154
diff changeset
    22
 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    23
 * Use is subject to license terms.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    24
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    25
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    26
#pragma ident	"%Z%%M%	%I%	%E% SMI"
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    27
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    28
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    29
 * ZFS control directory (a.k.a. ".zfs")
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    30
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    31
 * This directory provides a common location for all ZFS meta-objects.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    32
 * Currently, this is only the 'snapshot' directory, but this may expand in the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    33
 * future.  The elements are built using the GFS primitives, as the hierarchy
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    34
 * does not actually exist on disk.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    35
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    36
 * For 'snapshot', we don't want to have all snapshots always mounted, because
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    37
 * this would take up a huge amount of space in /etc/mnttab.  We have three
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    38
 * types of objects:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    39
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    40
 * 	ctldir ------> snapshotdir -------> snapshot
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    41
 *                                             |
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    42
 *                                             |
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    43
 *                                             V
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    44
 *                                         mounted fs
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    45
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    46
 * The 'snapshot' node contains just enough information to lookup '..' and act
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    47
 * as a mountpoint for the snapshot.  Whenever we lookup a specific snapshot, we
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    48
 * perform an automount of the underlying filesystem and return the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    49
 * corresponding vnode.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    50
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    51
 * All mounts are handled automatically by the kernel, but unmounts are
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    52
 * (currently) handled from user land.  The main reason is that there is no
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    53
 * reliable way to auto-unmount the filesystem when it's "no longer in use".
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    54
 * When the user unmounts a filesystem, we call zfsctl_unmount(), which
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    55
 * unmounts any snapshots within the snapshot directory.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    56
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    57
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    58
#include <fs/fs_subr.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    59
#include <sys/zfs_ctldir.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    60
#include <sys/zfs_ioctl.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    61
#include <sys/zfs_vfsops.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    62
#include <sys/gfs.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    63
#include <sys/stat.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    64
#include <sys/dmu.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    65
#include <sys/mount.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    66
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    67
typedef struct {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    68
	char		*se_name;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    69
	vnode_t		*se_root;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    70
	avl_node_t	se_node;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    71
} zfs_snapentry_t;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    72
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    73
static int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    74
snapentry_compare(const void *a, const void *b)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    75
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    76
	const zfs_snapentry_t *sa = a;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    77
	const zfs_snapentry_t *sb = b;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    78
	int ret = strcmp(sa->se_name, sb->se_name);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    79
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    80
	if (ret < 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    81
		return (-1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    82
	else if (ret > 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    83
		return (1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    84
	else
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    85
		return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    86
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    87
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    88
vnodeops_t *zfsctl_ops_root;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    89
vnodeops_t *zfsctl_ops_snapdir;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    90
vnodeops_t *zfsctl_ops_snapshot;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    91
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    92
static const fs_operation_def_t zfsctl_tops_root[];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    93
static const fs_operation_def_t zfsctl_tops_snapdir[];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    94
static const fs_operation_def_t zfsctl_tops_snapshot[];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    95
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    96
static vnode_t *zfsctl_mknode_snapdir(vnode_t *);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    97
static vnode_t *zfsctl_snapshot_mknode(vnode_t *, uint64_t objset);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    98
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    99
static gfs_opsvec_t zfsctl_opsvec[] = {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   100
	{ ".zfs", zfsctl_tops_root, &zfsctl_ops_root },
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   101
	{ ".zfs/snapshot", zfsctl_tops_snapdir, &zfsctl_ops_snapdir },
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   102
	{ ".zfs/snapshot/vnode", zfsctl_tops_snapshot, &zfsctl_ops_snapshot },
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   103
	{ NULL }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   104
};
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   105
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   106
typedef struct zfsctl_node {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   107
	gfs_dir_t	zc_gfs_private;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   108
	uint64_t	zc_id;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   109
} zfsctl_node_t;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   110
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   111
typedef struct zfsctl_snapdir {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   112
	zfsctl_node_t	sd_node;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   113
	kmutex_t	sd_lock;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   114
	avl_tree_t	sd_snaps;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   115
} zfsctl_snapdir_t;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   116
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   117
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   118
 * Root directory elements.  We have only a single static entry, 'snapshot'.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   119
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   120
static gfs_dirent_t zfsctl_root_entries[] = {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   121
	{ "snapshot", zfsctl_mknode_snapdir, GFS_CACHE_VNODE },
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   122
	{ NULL }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   123
};
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   124
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   125
/* include . and .. in the calculation */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   126
#define	NROOT_ENTRIES	((sizeof (zfsctl_root_entries) / \
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   127
    sizeof (gfs_dirent_t)) + 1)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   128
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   129
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   130
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   131
 * Initialize the various GFS pieces we'll need to create and manipulate .zfs
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   132
 * directories.  This is called from the ZFS init routine, and initializes the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   133
 * vnode ops vectors that we'll be using.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   134
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   135
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   136
zfsctl_init(void)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   137
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   138
	VERIFY(gfs_make_opsvec(zfsctl_opsvec) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   139
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   140
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   141
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   142
zfsctl_fini(void)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   143
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   144
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   145
	 * Remove vfsctl vnode ops
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   146
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   147
	if (zfsctl_ops_root)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   148
		vn_freevnodeops(zfsctl_ops_root);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   149
	if (zfsctl_ops_snapdir)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   150
		vn_freevnodeops(zfsctl_ops_snapdir);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   151
	if (zfsctl_ops_snapshot)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   152
		vn_freevnodeops(zfsctl_ops_snapshot);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   153
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   154
	zfsctl_ops_root = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   155
	zfsctl_ops_snapdir = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   156
	zfsctl_ops_snapshot = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   157
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   158
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   159
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   160
 * Return the inode number associated with the 'snapshot' directory.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   161
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   162
/* ARGSUSED */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   163
static ino64_t
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   164
zfsctl_root_inode_cb(vnode_t *vp, int index)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   165
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   166
	ASSERT(index == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   167
	return (ZFSCTL_INO_SNAPDIR);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   168
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   169
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   170
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   171
 * Create the '.zfs' directory.  This directory is cached as part of the VFS
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   172
 * structure.  This results in a hold on the vfs_t.  The code in zfs_umount()
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   173
 * therefore checks against a vfs_count of 2 instead of 1.  This reference
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   174
 * is removed when the ctldir is destroyed in the unmount.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   175
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   176
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   177
zfsctl_create(zfsvfs_t *zfsvfs)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   178
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   179
	vnode_t *vp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   180
	zfsctl_node_t *zcp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   181
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   182
	ASSERT(zfsvfs->z_ctldir == NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   183
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   184
	vp = gfs_root_create(sizeof (zfsctl_node_t), zfsvfs->z_vfs,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   185
	    zfsctl_ops_root, ZFSCTL_INO_ROOT, zfsctl_root_entries,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   186
	    zfsctl_root_inode_cb, MAXNAMELEN, NULL, NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   187
	zcp = vp->v_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   188
	zcp->zc_id = ZFSCTL_INO_ROOT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   189
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   190
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   191
	 * We're only faking the fact that we have a root of a filesystem for
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   192
	 * the sake of the GFS interfaces.  Undo the flag manipulation it did
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   193
	 * for us.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   194
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   195
	vp->v_flag &= ~(VROOT | VNOCACHE | VNOMAP | VNOSWAP | VNOMOUNT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   196
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   197
	zfsvfs->z_ctldir = vp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   198
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   199
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   200
/*
1298
1a70f57b62f0 6368181 some memleaks found related to zfs mount
perrin
parents: 1154
diff changeset
   201
 * Destroy the '.zfs' directory.  Only called when the filesystem is unmounted.
1a70f57b62f0 6368181 some memleaks found related to zfs mount
perrin
parents: 1154
diff changeset
   202
 * There might still be more references if we were force unmounted, but only
1a70f57b62f0 6368181 some memleaks found related to zfs mount
perrin
parents: 1154
diff changeset
   203
 * new zfs_inactive() calls can occur and they don't reference .zfs
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   204
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   205
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   206
zfsctl_destroy(zfsvfs_t *zfsvfs)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   207
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   208
	VN_RELE(zfsvfs->z_ctldir);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   209
	zfsvfs->z_ctldir = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   210
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   211
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   212
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   213
 * Given a root znode, retrieve the associated .zfs directory.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   214
 * Add a hold to the vnode and return it.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   215
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   216
vnode_t *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   217
zfsctl_root(znode_t *zp)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   218
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   219
	ASSERT(zfs_has_ctldir(zp));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   220
	VN_HOLD(zp->z_zfsvfs->z_ctldir);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   221
	return (zp->z_zfsvfs->z_ctldir);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   222
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   223
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   224
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   225
 * Common open routine.  Disallow any write access.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   226
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   227
/* ARGSUSED */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   228
static int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   229
zfsctl_common_open(vnode_t **vpp, int flags, cred_t *cr)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   230
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   231
	if (flags & FWRITE)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   232
		return (EACCES);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   233
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   234
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   235
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   236
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   237
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   238
 * Common close routine.  Nothing to do here.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   239
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   240
/* ARGSUSED */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   241
static int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   242
zfsctl_common_close(vnode_t *vpp, int flags, int count, offset_t off,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   243
    cred_t *cr)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   244
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   245
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   246
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   247
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   248
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   249
 * Common access routine.  Disallow writes.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   250
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   251
/* ARGSUSED */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   252
static int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   253
zfsctl_common_access(vnode_t *vp, int mode, int flags, cred_t *cr)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   254
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   255
	if (mode & VWRITE)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   256
		return (EACCES);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   257
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   258
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   259
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   260
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   261
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   262
 * Common getattr function.  Fill in basic information.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   263
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   264
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   265
zfsctl_common_getattr(vnode_t *vp, vattr_t *vap)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   266
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   267
	timestruc_t now;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   268
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   269
	vap->va_uid = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   270
	vap->va_gid = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   271
	vap->va_rdev = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   272
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   273
	 * We are a purly virtual object, so we have no
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   274
	 * blocksize or allocated blocks.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   275
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   276
	vap->va_blksize = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   277
	vap->va_nblocks = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   278
	vap->va_seq = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   279
	vap->va_fsid = vp->v_vfsp->vfs_dev;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   280
	vap->va_mode = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP |
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   281
	    S_IROTH | S_IXOTH;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   282
	vap->va_type = VDIR;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   283
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   284
	 * We live in the now.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   285
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   286
	gethrestime(&now);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   287
	vap->va_mtime = vap->va_ctime = vap->va_atime = now;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   288
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   289
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   290
static int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   291
zfsctl_common_fid(vnode_t *vp, fid_t *fidp)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   292
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   293
	zfsvfs_t	*zfsvfs = vp->v_vfsp->vfs_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   294
	zfsctl_node_t	*zcp = vp->v_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   295
	uint64_t	object = zcp->zc_id;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   296
	zfid_short_t	*zfid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   297
	int		i;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   298
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   299
	ZFS_ENTER(zfsvfs);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   300
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   301
	if (fidp->fid_len < SHORT_FID_LEN) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   302
		fidp->fid_len = SHORT_FID_LEN;
1512
dad2d74ca2cb 6391609 zfs_fid() missing ZFS_EXIT()
ek110237
parents: 1298
diff changeset
   303
		ZFS_EXIT(zfsvfs);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   304
		return (ENOSPC);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   305
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   306
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   307
	zfid = (zfid_short_t *)fidp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   308
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   309
	zfid->zf_len = SHORT_FID_LEN;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   310
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   311
	for (i = 0; i < sizeof (zfid->zf_object); i++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   312
		zfid->zf_object[i] = (uint8_t)(object >> (8 * i));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   313
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   314
	/* .zfs znodes always have a generation number of 0 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   315
	for (i = 0; i < sizeof (zfid->zf_gen); i++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   316
		zfid->zf_gen[i] = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   317
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   318
	ZFS_EXIT(zfsvfs);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   319
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   320
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   321
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   322
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   323
 * .zfs inode namespace
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   324
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   325
 * We need to generate unique inode numbers for all files and directories
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   326
 * within the .zfs pseudo-filesystem.  We use the following scheme:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   327
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   328
 * 	ENTRY			ZFSCTL_INODE
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   329
 * 	.zfs			1
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   330
 * 	.zfs/snapshot		2
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   331
 * 	.zfs/snapshot/<snap>	objectid(snap)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   332
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   333
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   334
#define	ZFSCTL_INO_SNAP(id)	(id)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   335
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   336
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   337
 * Get root directory attributes.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   338
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   339
/* ARGSUSED */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   340
static int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   341
zfsctl_root_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   342
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   343
	zfsvfs_t *zfsvfs = vp->v_vfsp->vfs_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   344
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   345
	ZFS_ENTER(zfsvfs);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   346
	vap->va_nodeid = ZFSCTL_INO_ROOT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   347
	vap->va_nlink = vap->va_size = NROOT_ENTRIES;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   348
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   349
	zfsctl_common_getattr(vp, vap);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   350
	ZFS_EXIT(zfsvfs);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   351
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   352
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   353
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   354
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   355
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   356
 * Special case the handling of "..".
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   357
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   358
/* ARGSUSED */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   359
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   360
zfsctl_root_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, pathname_t *pnp,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   361
    int flags, vnode_t *rdir, cred_t *cr)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   362
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   363
	zfsvfs_t *zfsvfs = dvp->v_vfsp->vfs_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   364
	int err;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   365
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   366
	ZFS_ENTER(zfsvfs);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   367
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   368
	if (strcmp(nm, "..") == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   369
		err = VFS_ROOT(dvp->v_vfsp, vpp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   370
	} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   371
		err = gfs_dir_lookup(dvp, nm, vpp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   372
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   373
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   374
	ZFS_EXIT(zfsvfs);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   375
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   376
	return (err);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   377
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   378
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   379
static const fs_operation_def_t zfsctl_tops_root[] = {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   380
	{ VOPNAME_OPEN,		zfsctl_common_open			},
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   381
	{ VOPNAME_CLOSE,	zfsctl_common_close			},
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   382
	{ VOPNAME_IOCTL,	fs_inval				},
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   383
	{ VOPNAME_GETATTR,	zfsctl_root_getattr			},
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   384
	{ VOPNAME_ACCESS,	zfsctl_common_access			},
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   385
	{ VOPNAME_READDIR,	gfs_vop_readdir				},
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   386
	{ VOPNAME_LOOKUP,	zfsctl_root_lookup			},
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   387
	{ VOPNAME_SEEK,		fs_seek					},
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   388
	{ VOPNAME_INACTIVE,	(fs_generic_func_p) gfs_vop_inactive	},
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   389
	{ VOPNAME_FID,		zfsctl_common_fid			},
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   390
	{ NULL }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   391
};
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   392
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   393
static int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   394
zfsctl_snapshot_zname(vnode_t *vp, const char *name, int len, char *zname)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   395
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   396
	objset_t *os = ((zfsvfs_t *)((vp)->v_vfsp->vfs_data))->z_os;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   397
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   398
	dmu_objset_name(os, zname);
1154
08f3f98286fe 6359739 panic in zfsctl_snapshot_zname()
maybee
parents: 816
diff changeset
   399
	if (strlen(zname) + 1 + strlen(name) >= len)
08f3f98286fe 6359739 panic in zfsctl_snapshot_zname()
maybee
parents: 816
diff changeset
   400
		return (ENAMETOOLONG);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   401
	(void) strcat(zname, "@");
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   402
	(void) strcat(zname, name);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   403
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   404
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   405
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   406
static int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   407
zfsctl_unmount_snap(vnode_t *dvp, const char *name, int force, cred_t *cr)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   408
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   409
	zfsctl_snapdir_t *sdp = dvp->v_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   410
	zfs_snapentry_t search, *sep;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   411
	avl_index_t where;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   412
	int err;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   413
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   414
	ASSERT(MUTEX_HELD(&sdp->sd_lock));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   415
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   416
	search.se_name = (char *)name;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   417
	if ((sep = avl_find(&sdp->sd_snaps, &search, &where)) == NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   418
		return (ENOENT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   419
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   420
	ASSERT(vn_ismntpt(sep->se_root));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   421
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   422
	/* this will be dropped by dounmount() */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   423
	if ((err = vn_vfswlock(sep->se_root)) != 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   424
		return (err);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   425
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   426
	VN_HOLD(sep->se_root);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   427
	if ((err = dounmount(vn_mountedvfs(sep->se_root), force, kcred)) != 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   428
		return (err);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   429
	ASSERT(sep->se_root->v_count == 1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   430
	gfs_vop_inactive(sep->se_root, cr);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   431
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   432
	avl_remove(&sdp->sd_snaps, sep);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   433
	kmem_free(sep->se_name, strlen(sep->se_name) + 1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   434
	kmem_free(sep, sizeof (zfs_snapentry_t));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   435
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   436
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   437
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   438
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   439
1154
08f3f98286fe 6359739 panic in zfsctl_snapshot_zname()
maybee
parents: 816
diff changeset
   440
static void
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   441
zfsctl_rename_snap(zfsctl_snapdir_t *sdp, zfs_snapentry_t *sep, const char *nm)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   442
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   443
	avl_index_t where;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   444
	vfs_t *vfsp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   445
	refstr_t *pathref;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   446
	char newpath[MAXNAMELEN];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   447
	const char *oldpath;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   448
	char *tail;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   449
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   450
	ASSERT(MUTEX_HELD(&sdp->sd_lock));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   451
	ASSERT(sep != NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   452
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   453
	vfsp = vn_mountedvfs(sep->se_root);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   454
	ASSERT(vfsp != NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   455
1154
08f3f98286fe 6359739 panic in zfsctl_snapshot_zname()
maybee
parents: 816
diff changeset
   456
	vfs_lock_wait(vfsp);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   457
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   458
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   459
	 * Change the name in the AVL tree.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   460
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   461
	avl_remove(&sdp->sd_snaps, sep);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   462
	kmem_free(sep->se_name, strlen(sep->se_name) + 1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   463
	sep->se_name = kmem_alloc(strlen(nm) + 1, KM_SLEEP);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   464
	(void) strcpy(sep->se_name, nm);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   465
	VERIFY(avl_find(&sdp->sd_snaps, sep, &where) == NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   466
	avl_insert(&sdp->sd_snaps, sep, where);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   467
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   468
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   469
	 * Change the current mountpoint info:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   470
	 * 	- update the tail of the mntpoint path
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   471
	 *	- update the tail of the resource path
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   472
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   473
	pathref = vfs_getmntpoint(vfsp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   474
	oldpath = refstr_value(pathref);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   475
	VERIFY((tail = strrchr(oldpath, '/')) != NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   476
	ASSERT((tail - oldpath) + strlen(nm) + 2 < MAXNAMELEN);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   477
	(void) strncpy(newpath, oldpath, tail - oldpath + 1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   478
	(void) strcat(newpath, nm);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   479
	refstr_rele(pathref);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   480
	vfs_setmntpoint(vfsp, newpath);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   481
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   482
	pathref = vfs_getresource(vfsp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   483
	oldpath = refstr_value(pathref);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   484
	VERIFY((tail = strrchr(oldpath, '@')) != NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   485
	ASSERT((tail - oldpath) + strlen(nm) + 2 < MAXNAMELEN);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   486
	(void) strncpy(newpath, oldpath, tail - oldpath + 1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   487
	(void) strcat(newpath, nm);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   488
	refstr_rele(pathref);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   489
	vfs_setresource(vfsp, newpath);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   490
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   491
	vfs_unlock(vfsp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   492
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   493
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   494
static int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   495
zfsctl_snapdir_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   496
    cred_t *cr)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   497
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   498
	zfsctl_snapdir_t *sdp = sdvp->v_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   499
	zfs_snapentry_t search, *sep;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   500
	avl_index_t where;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   501
	char from[MAXNAMELEN], to[MAXNAMELEN];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   502
	int err;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   503
1154
08f3f98286fe 6359739 panic in zfsctl_snapshot_zname()
maybee
parents: 816
diff changeset
   504
	err = zfsctl_snapshot_zname(sdvp, snm, MAXNAMELEN, from);
08f3f98286fe 6359739 panic in zfsctl_snapshot_zname()
maybee
parents: 816
diff changeset
   505
	if (err)
08f3f98286fe 6359739 panic in zfsctl_snapshot_zname()
maybee
parents: 816
diff changeset
   506
		return (err);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   507
	err = zfs_secpolicy_write(from, NULL, cr);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   508
	if (err)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   509
		return (err);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   510
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   511
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   512
	 * Cannot move snapshots out of the snapdir.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   513
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   514
	if (sdvp != tdvp)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   515
		return (EINVAL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   516
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   517
	if (strcmp(snm, tnm) == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   518
		return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   519
1154
08f3f98286fe 6359739 panic in zfsctl_snapshot_zname()
maybee
parents: 816
diff changeset
   520
	err = zfsctl_snapshot_zname(tdvp, tnm, MAXNAMELEN, to);
08f3f98286fe 6359739 panic in zfsctl_snapshot_zname()
maybee
parents: 816
diff changeset
   521
	if (err)
08f3f98286fe 6359739 panic in zfsctl_snapshot_zname()
maybee
parents: 816
diff changeset
   522
		return (err);
08f3f98286fe 6359739 panic in zfsctl_snapshot_zname()
maybee
parents: 816
diff changeset
   523
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   524
	mutex_enter(&sdp->sd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   525
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   526
	search.se_name = (char *)snm;
1154
08f3f98286fe 6359739 panic in zfsctl_snapshot_zname()
maybee
parents: 816
diff changeset
   527
	if ((sep = avl_find(&sdp->sd_snaps, &search, &where)) == NULL) {
08f3f98286fe 6359739 panic in zfsctl_snapshot_zname()
maybee
parents: 816
diff changeset
   528
		mutex_exit(&sdp->sd_lock);
08f3f98286fe 6359739 panic in zfsctl_snapshot_zname()
maybee
parents: 816
diff changeset
   529
		return (ENOENT);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   530
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   531
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   532
	err = dmu_objset_rename(from, to);
1154
08f3f98286fe 6359739 panic in zfsctl_snapshot_zname()
maybee
parents: 816
diff changeset
   533
	if (err == 0)
08f3f98286fe 6359739 panic in zfsctl_snapshot_zname()
maybee
parents: 816
diff changeset
   534
		zfsctl_rename_snap(sdp, sep, tnm);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   535
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   536
	mutex_exit(&sdp->sd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   537
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   538
	return (err);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   539
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   540
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   541
/* ARGSUSED */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   542
static int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   543
zfsctl_snapdir_remove(vnode_t *dvp, char *name, vnode_t *cwd, cred_t *cr)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   544
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   545
	zfsctl_snapdir_t *sdp = dvp->v_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   546
	char snapname[MAXNAMELEN];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   547
	int err;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   548
1154
08f3f98286fe 6359739 panic in zfsctl_snapshot_zname()
maybee
parents: 816
diff changeset
   549
	err = zfsctl_snapshot_zname(dvp, name, MAXNAMELEN, snapname);
08f3f98286fe 6359739 panic in zfsctl_snapshot_zname()
maybee
parents: 816
diff changeset
   550
	if (err)
08f3f98286fe 6359739 panic in zfsctl_snapshot_zname()
maybee
parents: 816
diff changeset
   551
		return (err);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   552
	err = zfs_secpolicy_write(snapname, NULL, cr);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   553
	if (err)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   554
		return (err);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   555
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   556
	mutex_enter(&sdp->sd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   557
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   558
	err = zfsctl_unmount_snap(dvp, name, 0, cr);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   559
	if (err) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   560
		mutex_exit(&sdp->sd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   561
		return (err);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   562
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   563
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   564
	err = dmu_objset_destroy(snapname);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   565
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   566
	mutex_exit(&sdp->sd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   567
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   568
	return (err);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   569
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   570
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   571
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   572
 * Lookup entry point for the 'snapshot' directory.  Try to open the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   573
 * snapshot if it exist, creating the pseudo filesystem vnode as necessary.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   574
 * Perform a mount of the associated dataset on top of the vnode.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   575
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   576
/* ARGSUSED */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   577
static int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   578
zfsctl_snapdir_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, pathname_t *pnp,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   579
    int flags, vnode_t *rdir, cred_t *cr)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   580
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   581
	zfsctl_snapdir_t *sdp = dvp->v_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   582
	objset_t *snap;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   583
	char snapname[MAXNAMELEN];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   584
	char *mountpoint;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   585
	zfs_snapentry_t *sep, search;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   586
	struct mounta margs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   587
	vfs_t *vfsp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   588
	size_t mountpoint_len;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   589
	avl_index_t where;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   590
	zfsvfs_t *zfsvfs = dvp->v_vfsp->vfs_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   591
	int err;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   592
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   593
	ASSERT(dvp->v_type == VDIR);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   594
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   595
	if (gfs_lookup_dot(vpp, dvp, zfsvfs->z_ctldir, nm) == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   596
		return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   597
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   598
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   599
	 * If we get a recursive call, that means we got called
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   600
	 * from the domount() code while it was trying to look up the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   601
	 * spec (which looks like a local path for zfs).  We need to
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   602
	 * add some flag to domount() to tell it not to do this lookup.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   603
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   604
	if (MUTEX_HELD(&sdp->sd_lock))
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   605
		return (ENOENT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   606
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   607
	ZFS_ENTER(zfsvfs);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   608
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   609
	mutex_enter(&sdp->sd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   610
	search.se_name = (char *)nm;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   611
	if ((sep = avl_find(&sdp->sd_snaps, &search, &where)) != NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   612
		*vpp = sep->se_root;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   613
		VN_HOLD(*vpp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   614
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   615
		 * If the snapshot was unmounted behind our backs, remount it.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   616
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   617
		if (!vn_ismntpt(*vpp))
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   618
			goto domount;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   619
		VERIFY(traverse(vpp) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   620
		mutex_exit(&sdp->sd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   621
		ZFS_EXIT(zfsvfs);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   622
		return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   623
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   624
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   625
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   626
	 * The requested snapshot is not currently mounted, look it up.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   627
	 */
1154
08f3f98286fe 6359739 panic in zfsctl_snapshot_zname()
maybee
parents: 816
diff changeset
   628
	err = zfsctl_snapshot_zname(dvp, nm, MAXNAMELEN, snapname);
08f3f98286fe 6359739 panic in zfsctl_snapshot_zname()
maybee
parents: 816
diff changeset
   629
	if (err) {
08f3f98286fe 6359739 panic in zfsctl_snapshot_zname()
maybee
parents: 816
diff changeset
   630
		mutex_exit(&sdp->sd_lock);
08f3f98286fe 6359739 panic in zfsctl_snapshot_zname()
maybee
parents: 816
diff changeset
   631
		ZFS_EXIT(zfsvfs);
08f3f98286fe 6359739 panic in zfsctl_snapshot_zname()
maybee
parents: 816
diff changeset
   632
		return (err);
08f3f98286fe 6359739 panic in zfsctl_snapshot_zname()
maybee
parents: 816
diff changeset
   633
	}
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   634
	if (dmu_objset_open(snapname, DMU_OST_ZFS,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   635
	    DS_MODE_STANDARD | DS_MODE_READONLY, &snap) != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   636
		mutex_exit(&sdp->sd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   637
		ZFS_EXIT(zfsvfs);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   638
		return (ENOENT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   639
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   640
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   641
	sep = kmem_alloc(sizeof (zfs_snapentry_t), KM_SLEEP);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   642
	sep->se_name = kmem_alloc(strlen(nm) + 1, KM_SLEEP);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   643
	(void) strcpy(sep->se_name, nm);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   644
	*vpp = sep->se_root = zfsctl_snapshot_mknode(dvp, dmu_objset_id(snap));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   645
	avl_insert(&sdp->sd_snaps, sep, where);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   646
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   647
	dmu_objset_close(snap);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   648
domount:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   649
	mountpoint_len = strlen(refstr_value(dvp->v_vfsp->vfs_mntpt)) +
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   650
	    strlen("/.zfs/snapshot/") + strlen(nm) + 1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   651
	mountpoint = kmem_alloc(mountpoint_len, KM_SLEEP);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   652
	(void) snprintf(mountpoint, mountpoint_len, "%s/.zfs/snapshot/%s",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   653
	    refstr_value(dvp->v_vfsp->vfs_mntpt), nm);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   654
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   655
	margs.spec = snapname;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   656
	margs.dir = mountpoint;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   657
	margs.flags = MS_SYSSPACE | MS_NOMNTTAB;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   658
	margs.fstype = "zfs";
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   659
	margs.dataptr = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   660
	margs.datalen = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   661
	margs.optptr = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   662
	margs.optlen = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   663
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   664
	err = domount("zfs", &margs, *vpp, kcred, &vfsp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   665
	kmem_free(mountpoint, mountpoint_len);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   666
816
4a2d51f7b961 6344201 Assertion failed: err == 0 (0x1 == 0x0), file: ../../common/fs/zfs/zfs_ctldir.c, line: 659
maybee
parents: 789
diff changeset
   667
	if (err == 0) {
4a2d51f7b961 6344201 Assertion failed: err == 0 (0x1 == 0x0), file: ../../common/fs/zfs/zfs_ctldir.c, line: 659
maybee
parents: 789
diff changeset
   668
		/*
4a2d51f7b961 6344201 Assertion failed: err == 0 (0x1 == 0x0), file: ../../common/fs/zfs/zfs_ctldir.c, line: 659
maybee
parents: 789
diff changeset
   669
		 * Return the mounted root rather than the covered mount point.
4a2d51f7b961 6344201 Assertion failed: err == 0 (0x1 == 0x0), file: ../../common/fs/zfs/zfs_ctldir.c, line: 659
maybee
parents: 789
diff changeset
   670
		 */
4a2d51f7b961 6344201 Assertion failed: err == 0 (0x1 == 0x0), file: ../../common/fs/zfs/zfs_ctldir.c, line: 659
maybee
parents: 789
diff changeset
   671
		VFS_RELE(vfsp);
4a2d51f7b961 6344201 Assertion failed: err == 0 (0x1 == 0x0), file: ../../common/fs/zfs/zfs_ctldir.c, line: 659
maybee
parents: 789
diff changeset
   672
		err = traverse(vpp);
4a2d51f7b961 6344201 Assertion failed: err == 0 (0x1 == 0x0), file: ../../common/fs/zfs/zfs_ctldir.c, line: 659
maybee
parents: 789
diff changeset
   673
	}
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   674
816
4a2d51f7b961 6344201 Assertion failed: err == 0 (0x1 == 0x0), file: ../../common/fs/zfs/zfs_ctldir.c, line: 659
maybee
parents: 789
diff changeset
   675
	if (err == 0) {
4a2d51f7b961 6344201 Assertion failed: err == 0 (0x1 == 0x0), file: ../../common/fs/zfs/zfs_ctldir.c, line: 659
maybee
parents: 789
diff changeset
   676
		/*
4a2d51f7b961 6344201 Assertion failed: err == 0 (0x1 == 0x0), file: ../../common/fs/zfs/zfs_ctldir.c, line: 659
maybee
parents: 789
diff changeset
   677
		 * Fix up the root vnode.
4a2d51f7b961 6344201 Assertion failed: err == 0 (0x1 == 0x0), file: ../../common/fs/zfs/zfs_ctldir.c, line: 659
maybee
parents: 789
diff changeset
   678
		 */
4a2d51f7b961 6344201 Assertion failed: err == 0 (0x1 == 0x0), file: ../../common/fs/zfs/zfs_ctldir.c, line: 659
maybee
parents: 789
diff changeset
   679
		ASSERT(VTOZ(*vpp)->z_zfsvfs != zfsvfs);
4a2d51f7b961 6344201 Assertion failed: err == 0 (0x1 == 0x0), file: ../../common/fs/zfs/zfs_ctldir.c, line: 659
maybee
parents: 789
diff changeset
   680
		VTOZ(*vpp)->z_zfsvfs->z_parent = zfsvfs;
4a2d51f7b961 6344201 Assertion failed: err == 0 (0x1 == 0x0), file: ../../common/fs/zfs/zfs_ctldir.c, line: 659
maybee
parents: 789
diff changeset
   681
		(*vpp)->v_vfsp = zfsvfs->z_vfs;
4a2d51f7b961 6344201 Assertion failed: err == 0 (0x1 == 0x0), file: ../../common/fs/zfs/zfs_ctldir.c, line: 659
maybee
parents: 789
diff changeset
   682
		(*vpp)->v_flag &= ~VROOT;
4a2d51f7b961 6344201 Assertion failed: err == 0 (0x1 == 0x0), file: ../../common/fs/zfs/zfs_ctldir.c, line: 659
maybee
parents: 789
diff changeset
   683
	}
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   684
	mutex_exit(&sdp->sd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   685
	ZFS_EXIT(zfsvfs);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   686
816
4a2d51f7b961 6344201 Assertion failed: err == 0 (0x1 == 0x0), file: ../../common/fs/zfs/zfs_ctldir.c, line: 659
maybee
parents: 789
diff changeset
   687
	if (err)
4a2d51f7b961 6344201 Assertion failed: err == 0 (0x1 == 0x0), file: ../../common/fs/zfs/zfs_ctldir.c, line: 659
maybee
parents: 789
diff changeset
   688
		VN_RELE(*vpp);
4a2d51f7b961 6344201 Assertion failed: err == 0 (0x1 == 0x0), file: ../../common/fs/zfs/zfs_ctldir.c, line: 659
maybee
parents: 789
diff changeset
   689
	return (err);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   690
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   691
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   692
/* ARGSUSED */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   693
static int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   694
zfsctl_snapdir_readdir_cb(vnode_t *vp, struct dirent64 *dp, int *eofp,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   695
    offset_t *offp, offset_t *nextp, void *data)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   696
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   697
	zfsvfs_t *zfsvfs = vp->v_vfsp->vfs_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   698
	char snapname[MAXNAMELEN];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   699
	uint64_t id, cookie;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   700
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   701
	ZFS_ENTER(zfsvfs);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   702
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   703
	cookie = *offp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   704
	if (dmu_snapshot_list_next(zfsvfs->z_os, MAXNAMELEN, snapname, &id,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   705
	    &cookie) == ENOENT) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   706
		*eofp = 1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   707
		ZFS_EXIT(zfsvfs);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   708
		return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   709
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   710
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   711
	(void) strcpy(dp->d_name, snapname);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   712
	dp->d_ino = ZFSCTL_INO_SNAP(id);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   713
	*nextp = cookie;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   714
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   715
	ZFS_EXIT(zfsvfs);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   716
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   717
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   718
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   719
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   720
vnode_t *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   721
zfsctl_mknode_snapdir(vnode_t *pvp)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   722
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   723
	vnode_t *vp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   724
	zfsctl_snapdir_t *sdp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   725
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   726
	vp = gfs_dir_create(sizeof (zfsctl_snapdir_t), pvp,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   727
	    zfsctl_ops_snapdir, NULL, NULL, MAXNAMELEN,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   728
	    zfsctl_snapdir_readdir_cb, NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   729
	sdp = vp->v_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   730
	sdp->sd_node.zc_id = ZFSCTL_INO_SNAPDIR;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   731
	mutex_init(&sdp->sd_lock, NULL, MUTEX_DEFAULT, NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   732
	avl_create(&sdp->sd_snaps, snapentry_compare,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   733
	    sizeof (zfs_snapentry_t), offsetof(zfs_snapentry_t, se_node));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   734
	return (vp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   735
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   736
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   737
/* ARGSUSED */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   738
static int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   739
zfsctl_snapdir_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   740
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   741
	zfsvfs_t *zfsvfs = vp->v_vfsp->vfs_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   742
	zfsctl_snapdir_t *sdp = vp->v_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   743
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   744
	ZFS_ENTER(zfsvfs);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   745
	zfsctl_common_getattr(vp, vap);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   746
	vap->va_nodeid = gfs_file_inode(vp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   747
	vap->va_nlink = vap->va_size = avl_numnodes(&sdp->sd_snaps) + 2;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   748
	ZFS_EXIT(zfsvfs);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   749
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   750
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   751
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   752
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   753
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   754
zfsctl_snapdir_inactive(vnode_t *vp, cred_t *cr)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   755
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   756
	zfsctl_snapdir_t *sdp = vp->v_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   757
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   758
	ASSERT(avl_numnodes(&sdp->sd_snaps) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   759
	mutex_destroy(&sdp->sd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   760
	avl_destroy(&sdp->sd_snaps);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   761
	gfs_vop_inactive(vp, cr);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   762
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   763
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   764
static const fs_operation_def_t zfsctl_tops_snapdir[] = {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   765
	{ VOPNAME_OPEN,		zfsctl_common_open			},
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   766
	{ VOPNAME_CLOSE,	zfsctl_common_close			},
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   767
	{ VOPNAME_IOCTL,	fs_inval				},
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   768
	{ VOPNAME_GETATTR,	zfsctl_snapdir_getattr			},
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   769
	{ VOPNAME_ACCESS,	zfsctl_common_access			},
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   770
	{ VOPNAME_RENAME,	zfsctl_snapdir_rename			},
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   771
	{ VOPNAME_RMDIR,	zfsctl_snapdir_remove			},
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   772
	{ VOPNAME_READDIR,	gfs_vop_readdir				},
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   773
	{ VOPNAME_LOOKUP,	zfsctl_snapdir_lookup			},
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   774
	{ VOPNAME_SEEK,		fs_seek					},
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   775
	{ VOPNAME_INACTIVE,	(fs_generic_func_p) zfsctl_snapdir_inactive },
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   776
	{ VOPNAME_FID,		zfsctl_common_fid			},
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   777
	{ NULL }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   778
};
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   779
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   780
static vnode_t *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   781
zfsctl_snapshot_mknode(vnode_t *pvp, uint64_t objset)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   782
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   783
	vnode_t *vp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   784
	zfsctl_node_t *zcp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   785
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   786
	vp = gfs_dir_create(sizeof (zfsctl_node_t), pvp,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   787
	    zfsctl_ops_snapshot, NULL, NULL, MAXNAMELEN, NULL, NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   788
	zcp = vp->v_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   789
	zcp->zc_id = objset;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   790
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   791
	return (vp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   792
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   793
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   794
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   795
zfsctl_snapshot_inactive(vnode_t *vp, cred_t *cr)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   796
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   797
	zfsctl_snapdir_t *sdp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   798
	zfs_snapentry_t *sep, *next;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   799
	vnode_t *dvp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   800
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   801
	VERIFY(gfs_dir_lookup(vp, "..", &dvp) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   802
	sdp = dvp->v_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   803
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   804
	mutex_enter(&sdp->sd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   805
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   806
	if (vp->v_count > 1) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   807
		mutex_exit(&sdp->sd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   808
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   809
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   810
	ASSERT(!vn_ismntpt(vp));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   811
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   812
	sep = avl_first(&sdp->sd_snaps);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   813
	while (sep != NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   814
		next = AVL_NEXT(&sdp->sd_snaps, sep);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   815
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   816
		if (sep->se_root == vp) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   817
			avl_remove(&sdp->sd_snaps, sep);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   818
			kmem_free(sep->se_name, strlen(sep->se_name) + 1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   819
			kmem_free(sep, sizeof (zfs_snapentry_t));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   820
			break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   821
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   822
		sep = next;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   823
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   824
	ASSERT(sep != NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   825
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   826
	mutex_exit(&sdp->sd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   827
	VN_RELE(dvp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   828
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   829
	gfs_vop_inactive(vp, cr);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   830
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   831
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   832
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   833
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   834
 * These VP's should never see the light of day.  They should always
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   835
 * be covered.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   836
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   837
static const fs_operation_def_t zfsctl_tops_snapshot[] = {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   838
	VOPNAME_INACTIVE, (fs_generic_func_p) zfsctl_snapshot_inactive,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   839
	NULL, NULL
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   840
};
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   841
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   842
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   843
zfsctl_lookup_objset(vfs_t *vfsp, uint64_t objsetid, zfsvfs_t **zfsvfsp)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   844
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   845
	zfsvfs_t *zfsvfs = vfsp->vfs_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   846
	vnode_t *dvp, *vp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   847
	zfsctl_snapdir_t *sdp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   848
	zfsctl_node_t *zcp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   849
	zfs_snapentry_t *sep;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   850
	int error;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   851
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   852
	ASSERT(zfsvfs->z_ctldir != NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   853
	error = zfsctl_root_lookup(zfsvfs->z_ctldir, "snapshot", &dvp,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   854
	    NULL, 0, NULL, kcred);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   855
	if (error != 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   856
		return (error);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   857
	sdp = dvp->v_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   858
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   859
	mutex_enter(&sdp->sd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   860
	sep = avl_first(&sdp->sd_snaps);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   861
	while (sep != NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   862
		vp = sep->se_root;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   863
		zcp = vp->v_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   864
		if (zcp->zc_id == objsetid)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   865
			break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   866
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   867
		sep = AVL_NEXT(&sdp->sd_snaps, sep);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   868
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   869
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   870
	if (sep != NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   871
		VN_HOLD(vp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   872
		error = traverse(&vp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   873
		if (error == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   874
			*zfsvfsp = VTOZ(vp)->z_zfsvfs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   875
		VN_RELE(vp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   876
	} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   877
		error = EINVAL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   878
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   879
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   880
	mutex_exit(&sdp->sd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   881
	VN_RELE(dvp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   882
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   883
	return (error);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   884
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   885
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   886
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   887
 * Unmount any snapshots for the given filesystem.  This is called from
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   888
 * zfs_umount() - if we have a ctldir, then go through and unmount all the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   889
 * snapshots.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   890
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   891
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   892
zfsctl_umount_snapshots(vfs_t *vfsp, int fflags, cred_t *cr)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   893
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   894
	zfsvfs_t *zfsvfs = vfsp->vfs_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   895
	vnode_t *dvp, *svp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   896
	zfsctl_snapdir_t *sdp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   897
	zfs_snapentry_t *sep, *next;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   898
	int error;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   899
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   900
	ASSERT(zfsvfs->z_ctldir != NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   901
	error = zfsctl_root_lookup(zfsvfs->z_ctldir, "snapshot", &dvp,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   902
	    NULL, 0, NULL, cr);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   903
	if (error != 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   904
		return (error);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   905
	sdp = dvp->v_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   906
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   907
	mutex_enter(&sdp->sd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   908
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   909
	sep = avl_first(&sdp->sd_snaps);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   910
	while (sep != NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   911
		svp = sep->se_root;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   912
		next = AVL_NEXT(&sdp->sd_snaps, sep);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   913
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   914
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   915
		 * If this snapshot is not mounted, then it must
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   916
		 * have just been unmounted by somebody else, and
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   917
		 * will be cleaned up by zfsctl_snapdir_inactive().
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   918
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   919
		if (vn_ismntpt(svp)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   920
			if ((error = vn_vfswlock(svp)) != 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   921
				goto out;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   922
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   923
			VN_HOLD(svp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   924
			error = dounmount(vn_mountedvfs(svp), fflags, cr);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   925
			if (error) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   926
				VN_RELE(svp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   927
				goto out;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   928
			}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   929
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   930
			avl_remove(&sdp->sd_snaps, sep);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   931
			kmem_free(sep->se_name, strlen(sep->se_name) + 1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   932
			kmem_free(sep, sizeof (zfs_snapentry_t));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   933
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   934
			/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   935
			 * We can't use VN_RELE(), as that will try to
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   936
			 * invoke zfsctl_snapdir_inactive(), and that
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   937
			 * would lead to an attempt to re-grab the sd_lock.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   938
			 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   939
			ASSERT3U(svp->v_count, ==, 1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   940
			gfs_vop_inactive(svp, cr);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   941
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   942
		sep = next;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   943
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   944
out:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   945
	mutex_exit(&sdp->sd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   946
	VN_RELE(dvp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   947
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   948
	return (error);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   949
}