Index: share/man/man9/VOP_VPTOCNP.9 =================================================================== --- share/man/man9/VOP_VPTOCNP.9 (revision 227497) +++ share/man/man9/VOP_VPTOCNP.9 (working copy) @@ -65,9 +65,9 @@ .Nm returns ENOENT. .Sh LOCKS -The vnode should be locked on entry and will still be locked on exit. The -parent directory vnode will be unlocked on a successful exit. However, it -will have its hold count incremented. +The vnode should be locked on entry and will still be locked on exit. +The parent directory vnode will be unlocked on a successful exit. +However, it will have its use count incremented. .Sh RETURN VALUES Zero is returned on success, otherwise an error code is returned. .Sh ERRORS Index: cddl/contrib/opensolaris/cmd/zpool/zpool_main.c =================================================================== --- cddl/contrib/opensolaris/cmd/zpool/zpool_main.c (revision 227497) +++ cddl/contrib/opensolaris/cmd/zpool/zpool_main.c (working copy) @@ -22,6 +22,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. + * Copyright (c) 2011 by Delphix. All rights reserved. */ #include @@ -68,6 +69,8 @@ static int zpool_do_offline(int, char **); static int zpool_do_clear(int, char **); +static int zpool_do_reguid(int, char **); + static int zpool_do_attach(int, char **); static int zpool_do_detach(int, char **); static int zpool_do_replace(int, char **); @@ -126,7 +129,8 @@ HELP_UPGRADE, HELP_GET, HELP_SET, - HELP_SPLIT + HELP_SPLIT, + HELP_REGUID } zpool_help_t; @@ -172,6 +176,7 @@ { "import", zpool_do_import, HELP_IMPORT }, { "export", zpool_do_export, HELP_EXPORT }, { "upgrade", zpool_do_upgrade, HELP_UPGRADE }, + { "reguid", zpool_do_reguid, HELP_REGUID }, { NULL }, { "history", zpool_do_history, HELP_HISTORY }, { "get", zpool_do_get, HELP_GET }, @@ -252,6 +257,8 @@ return (gettext("\tsplit [-n] [-R altroot] [-o mntopts]\n" "\t [-o property=value] " "[ ...]\n")); + case HELP_REGUID: + return (gettext("\treguid \n")); } abort(); @@ -3321,6 +3328,52 @@ return (ret); } +/* + * zpool reguid + */ +int +zpool_do_reguid(int argc, char **argv) +{ + int c; + char *poolname; + zpool_handle_t *zhp; + int ret = 0; + + /* check options */ + while ((c = getopt(argc, argv, "")) != -1) { + switch (c) { + case '?': + (void) fprintf(stderr, gettext("invalid option '%c'\n"), + optopt); + usage(B_FALSE); + } + } + + argc -= optind; + argv += optind; + + /* get pool name and check number of arguments */ + if (argc < 1) { + (void) fprintf(stderr, gettext("missing pool name\n")); + usage(B_FALSE); + } + + if (argc > 1) { + (void) fprintf(stderr, gettext("too many arguments\n")); + usage(B_FALSE); + } + + poolname = argv[0]; + if ((zhp = zpool_open(g_zfs, poolname)) == NULL) + return (1); + + ret = zpool_reguid(zhp); + + zpool_close(zhp); + return (ret); +} + + typedef struct scrub_cbdata { int cb_type; int cb_argc; Index: cddl/contrib/opensolaris/cmd/zpool/zpool.8 =================================================================== --- cddl/contrib/opensolaris/cmd/zpool/zpool.8 (revision 227497) +++ cddl/contrib/opensolaris/cmd/zpool/zpool.8 (working copy) @@ -3,7 +3,7 @@ .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. .\" See the License for the specific language governing permissions and limitations under the License. When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the .\" fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH zpool 1M "21 Sep 2009" "SunOS 5.11" "System Administration Commands" +.TH zpool 1M "25 Oct 2011" "SunOS 5.11" "System Administration Commands" .SH NAME zpool \- configures ZFS storage pools .SH SYNOPSIS @@ -102,6 +102,11 @@ .LP .nf +\fBzpool reguid\fR \fIpool\fR +.fi + +.LP +.nf \fBzpool remove\fR \fIpool\fR \fIdevice\fR ... .fi @@ -1313,6 +1318,17 @@ .ne 2 .mk .na +\fB\fBzpool reguid\fR \fIpool\fR +.ad +.sp .6 +.RS 4n +Generates a new unique identifier for the pool. You must ensure that all devices in this pool are online and +healthy before performing this action. +.RE + +.sp +.ne 2 +.na \fB\fBzpool remove\fR \fIpool\fR \fIdevice\fR ...\fR .ad .sp .6 Index: cddl/contrib/opensolaris/cmd/ztest/ztest.c =================================================================== --- cddl/contrib/opensolaris/cmd/ztest/ztest.c (revision 227497) +++ cddl/contrib/opensolaris/cmd/ztest/ztest.c (working copy) @@ -21,6 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011 by Delphix. All rights reserved. + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. */ /* @@ -259,6 +260,7 @@ ztest_func_t ztest_vdev_add_remove; ztest_func_t ztest_vdev_aux_add_remove; ztest_func_t ztest_split_pool; +ztest_func_t ztest_reguid; uint64_t zopt_always = 0ULL * NANOSEC; /* all the time */ uint64_t zopt_incessant = 1ULL * NANOSEC / 10; /* every 1/10 second */ @@ -289,6 +291,7 @@ { ztest_fault_inject, 1, &zopt_sometimes }, { ztest_ddt_repair, 1, &zopt_sometimes }, { ztest_dmu_snapshot_hold, 1, &zopt_sometimes }, + { ztest_reguid, 1, &zopt_sometimes }, { ztest_spa_rename, 1, &zopt_rarely }, { ztest_scrub, 1, &zopt_rarely }, { ztest_dsl_dataset_promote_busy, 1, &zopt_rarely }, @@ -325,6 +328,7 @@ uint64_t zs_vdev_aux; uint64_t zs_alloc; uint64_t zs_space; + uint64_t zs_guid; mutex_t zs_vdev_lock; rwlock_t zs_name_lock; ztest_info_t zs_info[ZTEST_FUNCS]; @@ -4646,7 +4650,7 @@ object = od[0].od_object; blocksize = od[0].od_blocksize; - pattern = spa_guid(spa) ^ dmu_objset_fsid_guid(os); + pattern = zs->zs_guid ^ dmu_objset_fsid_guid(os); ASSERT(object != 0); @@ -4717,6 +4721,31 @@ } /* + * Change the guid for the pool. + */ +/* ARGSUSED */ +void +ztest_reguid(ztest_ds_t *zd, uint64_t id) +{ + ztest_shared_t *zs = ztest_shared; + spa_t *spa = zs->zs_spa; + uint64_t orig, load; + + orig = spa_guid(spa); + load = spa_load_guid(spa); + if (spa_change_guid(spa) != 0) + return; + + if (zopt_verbose >= 3) { + (void) printf("Changed guid old %llu -> %llu\n", + (u_longlong_t)orig, (u_longlong_t)spa_guid(spa)); + } + + VERIFY3U(orig, !=, spa_guid(spa)); + VERIFY3U(load, ==, spa_load_guid(spa)); +} + +/* * Rename the pool to a different name and then rename it back. */ /* ARGSUSED */ @@ -5145,6 +5174,7 @@ { thread_t *tid; spa_t *spa; + objset_t *os; thread_t resume_tid; int error; @@ -5176,6 +5206,10 @@ spa->spa_debug = B_TRUE; zs->zs_spa = spa; + VERIFY3U(0, ==, dmu_objset_hold(zs->zs_pool, FTAG, &os)); + zs->zs_guid = dmu_objset_fsid_guid(os); + dmu_objset_rele(os, FTAG); + spa->spa_dedup_ditto = 2 * ZIO_DEDUPDITTO_MIN; /* Index: cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h =================================================================== --- cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h (revision 227497) +++ cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h (working copy) @@ -21,8 +21,8 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2010 Nexenta Systems, Inc. All rights reserved. - * Copyright (c) 2011 Pawel Jakub Dawidek . + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. + * Copyright (c) 2011 by Delphix. All rights reserved. * All rights reserved. */ @@ -233,6 +233,7 @@ */ extern int zpool_scan(zpool_handle_t *, pool_scan_func_t); extern int zpool_clear(zpool_handle_t *, const char *, nvlist_t *); +extern int zpool_reguid(zpool_handle_t *); extern int zpool_vdev_online(zpool_handle_t *, const char *, int, vdev_state_t *); Index: cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c =================================================================== --- cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c (revision 227497) +++ cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c (working copy) @@ -21,6 +21,8 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. + * Copyright (c) 2011 by Delphix. All rights reserved. */ #include @@ -3011,6 +3013,26 @@ } /* + * Change the GUID for a pool. + */ +int +zpool_reguid(zpool_handle_t *zhp) +{ + char msg[1024]; + libzfs_handle_t *hdl = zhp->zpool_hdl; + zfs_cmd_t zc = { 0 }; + + (void) snprintf(msg, sizeof (msg), + dgettext(TEXT_DOMAIN, "cannot reguid '%s'"), zhp->zpool_name); + + (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); + if (zfs_ioctl(hdl, ZFS_IOC_POOL_REGUID, &zc) == 0) + return (0); + + return (zpool_standard_error(hdl, errno, msg)); +} + +/* * Convert from a devid string to a path. */ static char * Index: etc/defaults/devfs.rules =================================================================== --- etc/defaults/devfs.rules (revision 227497) +++ etc/defaults/devfs.rules (working copy) @@ -84,3 +84,9 @@ add include $devfsrules_hide_all add include $devfsrules_unhide_basic add include $devfsrules_unhide_login + +# Jail with zfs support +# +[devfsrules_jail_zfs=5] +add include $devfsrules_jail +add path zfs unhide Index: etc/defaults/rc.conf =================================================================== --- etc/defaults/rc.conf (revision 227497) +++ etc/defaults/rc.conf (working copy) @@ -667,19 +667,17 @@ jail_enable="NO" # Set to NO to disable starting of any jails jail_parallel_start="NO" # Start jails in the background jail_list="" # Space separated list of names of jails -jail_set_hostname_allow="YES" # Allow root user in a jail to change its hostname -jail_socket_unixiproute_only="YES" # Route only TCP/IP within a jail -jail_sysvipc_allow="NO" # Allow SystemV IPC use from within a jail # # To use rc's built-in jail infrastructure create entries for # each jail, specified in jail_list, with the following variables. # NOTES: # - replace 'example' with the jail's name. -# - except rootdir, hostname, ip and the _multi addresses, +# - except rootdir, hostname, zfs, ip and the _multi addresses, # all of the following variables may be made global jail variables # if you don't specify a jail name (ie. jail_interface, jail_devfs_ruleset). # +#jail_example_name="myjail" # Jail's name (defaults to name in jail_list) #jail_example_rootdir="/usr/jail/default" # Jail's root directory #jail_example_hostname="default.domain.com" # Jail's hostname #jail_example_interface="" # Jail's interface variable to create IP aliases on @@ -692,13 +690,24 @@ # specified using a trailing number #jail_example_exec_stop="/bin/sh /etc/rc.shutdown" # command to execute in jail for stopping #jail_example_devfs_enable="NO" # mount devfs in the jail -#jail_example_devfs_ruleset="ruleset_name" # devfs ruleset to apply to jail - - # usually you want "devfsrules_jail". +#jail_example_devfs_ruleset="ruleset_name" # devfs ruleset to apply to jail, defaults + # to "devfsrules_jail" or if jail_example_zfs is + # set to "devfsrules_jail_zfs". #jail_example_fdescfs_enable="NO" # mount fdescfs in the jail #jail_example_procfs_enable="NO" # mount procfs in jail #jail_example_mount_enable="NO" # mount/umount jail's fs #jail_example_fstab="" # fstab(5) for mount/umount #jail_example_flags="-l -U root" # flags for jail(8) +#jail_example_persist="NO" # Create a persistent jail. Jail will be made + # non-persistent if stopped via /etc/rc.d/jail +#jail_example_params="" # Space-separated list of additional + # user-supplied parameters for jail(8) +#jail_example_zfs="" # Space-separated list of ZFS datasets to be + # managed from this jail. For proper operation, + # allow.mount=1 and enforce_statfs=1 (or 0) + # must be added to jail_example_params. + # The "jailed" property must be set to "on" + # on these datasets before starting the jail. ############################################################## ### Define source_rc_confs, the mechanism used by /etc/rc.* ## Index: etc/rc.d/jail =================================================================== --- etc/rc.d/jail (revision 227497) +++ etc/rc.d/jail (working copy) @@ -22,7 +22,33 @@ start_precmd="jail_prestart" start_cmd="jail_start" stop_cmd="jail_stop" +extra_commands="status create remove" +status_cmd="jail_status" +create_cmd="jail_create" +remove_cmd="jail_remove" +# init_name _j +# Initialize the name variable for jail _j. +# +init_name() +{ + _j="$1" + + if [ -z "$_j" ]; then + warn "init_name: you must specify a jail" + return + fi + + eval _name=\"\$jail_${_j}_name\" + + if [ -z "${_name}" ]; then + _name=${_j} + fi + + # Debugging aid + debug "$_j name: $_name" +} + # init_variables _j # Initialize the various jail variables for jail _j. # @@ -43,6 +69,8 @@ eval _ip=\"\$jail_${_j}_ip\" eval _interface=\"\${jail_${_j}_interface:-${jail_interface}}\" eval _exec=\"\$jail_${_j}_exec\" + eval _params=\"\${jail_${_j}_params:-${jail_params}}\" + eval _zfs=\"\${jail_${_j}_zfs:-}\" i=0 while : ; do @@ -98,6 +126,11 @@ fi # The default jail ruleset will be used by rc.subr if none is specified. + if [ -n "${_zfs}" ]; then + eval jail_devfs_ruleset=\"${jail_devfs_ruleset:-devfsrules_jail_zfs}\" + else + eval jail_devfs_ruleset=\"${jail_devfs_ruleset:-devfsrules_jail}\" + fi eval _ruleset=\"\${jail_${_j}_devfs_ruleset:-${jail_devfs_ruleset}}\" eval _devfs=\"\${jail_${_j}_devfs_enable:-${jail_devfs_enable}}\" [ -z "${_devfs}" ] && _devfs="NO" @@ -116,6 +149,8 @@ eval _consolelog=\"\${jail_${_j}_consolelog:-${jail_consolelog}}\" [ -z "${_consolelog}" ] && _consolelog="/var/log/jail_${_j}_console.log" eval _fib=\"\${jail_${_j}_fib:-${jail_fib}}\" + eval _persist=\"\${jail_${_j}_persist:-${jail_persist}}\" + [ -z "${_persist}" ] && _persist="NO" # Debugging aid # @@ -134,6 +169,9 @@ debug "$_j procdir: $_procdir" debug "$_j ruleset: $_ruleset" debug "$_j fstab: $_fstab" + debug "$_j persist: $_persist" + debug "$_j params: $_params" + debug "$_j zfs: $_zfs" i=0 while : ; do @@ -194,39 +232,35 @@ debug "$_j flags: $_flags" debug "$_j consolelog: $_consolelog" - if [ -z "${_hostname}" ]; then - err 3 "$name: No hostname has been defined for ${_j}" - fi + _params="${_params} name=${_name}" + [ -n "${_hostname}" ] && _params="${_params} host.hostname=${_hostname}" + if [ -z "${_rootdir}" ]; then err 3 "$name: No root directory has been defined for ${_j}" + else + _params="${_params} path=${_rootdir}" fi -} -# set_sysctl rc_knob mib msg -# If the mib sysctl is set according to what rc_knob -# specifies, this function does nothing. However if -# rc_knob is set differently than mib, then the mib -# is set accordingly and msg is displayed followed by -# an '=" sign and the word 'YES' or 'NO'. -# -set_sysctl() -{ - _knob="$1" - _mib="$2" - _msg="$3" + # Compatibility with old sysctl knobs + # + eval _set_hostname_allow="\${jail_${_j}_set_hostname_allow:-${jail_set_hostname_allow}}" + eval _socket_unixiproute_only="\${jail_${_j}_socket_unixiproute_only:-${jail_socket_unixiproute_only}}" + eval _sysvipc_allow="\${jail_${_j}_sysvipc_allow:-${jail_sysvipc_allow}}" + [ -z "${_set_hostname_allow}" ] && _set_hostname_allow="YES" + [ -z "${_socket_unixiproute_only}" ] && _socket_unixiproute_only="YES" + [ -z "${_sysvipc_allow}" ] && _sysvipc_allow="NO" - _current=`${SYSCTL} -n $_mib 2>/dev/null` - if checkyesno $_knob ; then - if [ "$_current" -ne 1 ]; then - echo -n " ${_msg}=YES" - ${SYSCTL} 1>/dev/null ${_mib}=1 - fi - else - if [ "$_current" -ne 0 ]; then - echo -n " ${_msg}=NO" - ${SYSCTL} 1>/dev/null ${_mib}=0 - fi + if ! checkyesno _set_hostname_allow; then + _params="${_params} allow.set_hostname=0" fi + + if ! checkyesno _socket_unixiproute_only; then + _params="${_params} allow.socket_af=1" + fi + + if checkyesno _sysvipc_allow; then + _params="${_params} allow.sysvipc=1" + fi } # is_current_mountpoint() @@ -329,14 +363,21 @@ # jail_mount_fstab() { - local _device _mountpt _rest + local _device _mountpt _field3 _field4 _field5 _field6 - while read _device _mountpt _rest; do - case ":${_device}" in - :#* | :) + while read _device _mountpt _field3 _field4 _field5 _field6; do + case ":${_device}:" in + :#*:|::) + # empty line or comment continue ;; esac + if [ -z "${_field5}" ]; then + # a fstab entry needs at least 5 fields + # everything else is suspicious + warn "${_device} ${_mountpt} ${_field3} ${_field4} ${_field5} ${_field6} not conforming to 5 or more whitespace separated fields" + return + fi if is_symlinked_mountpoint ${_mountpt}; then warn "${_mountpt} has symlink as parent - not mounting from ${_fstab}" return @@ -345,6 +386,38 @@ mount -a -F "${_fstab}" } +# jail_zfs_jailin +# Make zfs datasets manageable from inside a jail +# the "jailed" dataset property must be set to "on" +jail_zfs_jailin() +{ + if [ -n "${_zfs}" ]; then + for _ds in ${_zfs}; do + _jailed=`zfs get -H jailed ${_ds} 2>/dev/null | awk '{ print $3 }'` + if [ "${_jailed}" = "on" ]; then + debug "${j} jailing zfs dataset: ${_ds}" + zfs jail "${_jail_id}" ${_ds} 2>/dev/null + fi + done + fi +} + +# jail_zfs_jailout +# Unjail zfs datasets +# the "jailed" dataset property must be set to "on" +jail_zfs_jailout() +{ + if [ -n "${_zfs}" ]; then + for _ds in ${_zfs}; do + _jailed=`zfs get -H jailed ${_ds} 2>/dev/null | awk '{ print $3 }'` + if [ "${_jailed}" = "on" ]; then + debug "${j} unjailing zfs dataset: ${_ds}" + zfs unjail "${_jail_id}" ${_ds} 2>/dev/null + fi + done + fi +} + # jail_show_addresses jail # Debug print the input for the given _multi aliases # for a jail for init_variables(). @@ -483,10 +556,27 @@ *) ;; esac - # Append address to list of addresses for the jail command. - case "${_addrl}" in - "") _addrl="${_addr}" ;; - *) _addrl="${_addrl},${_addr}" ;; + case "${_type}" in + inet) + # Append address to list of ipv4 addresses for the + # jail command. + case "${_addrl}" in + "") _addrl="${_addr}" ;; + *) _addrl="${_addrl},${_addr}" ;; + esac + ;; + inet6) + # Append address to list of ipv6 addresses for the + # jail command. + case "${_addrl6}" in + "") _addrl6="${_addr}" ;; + *) _addrl6="${_addrl6},${_addr}" ;; + esac + ;; + *) warn "Could not determine address family. Not going" \ + "to set address '${_addr}' for ${_jail}." + continue + ;; esac # Configure interface alias if requested by a given interface @@ -494,14 +584,7 @@ case "${_iface}" in "") continue ;; esac - case "${_type}" in - inet) ;; - inet6) ;; - *) warn "Could not determine address family. Not going" \ - "to ${_action} address '${_addr}' for ${_jail}." - continue - ;; - esac + case "${_action}" in add) ifconfig ${_iface} ${_type} ${_addr}${_mask} alias ;; @@ -554,86 +637,176 @@ fi } +jail_init() +{ + _jail=$1 + init_name $_jail + init_variables $_jail + _jail_id="$(jls -j ${_name} jid 2>/dev/null)" + if [ -n "${_jail_id}" ]; then + return 1 + fi + _addrl="" + _addrl6="" + jail_ips "add" + + [ -n "${_addrl}" ] && _params="${_params} ip4.addr=${_addrl}" + [ -n "${_addrl6}" ] && _params="${_params} ip6.addr=${_addrl6}" + + if [ -n "${_fib}" ]; then + _setfib="setfib -F '${_fib}'" + else + _setfib="" + fi + if checkyesno _mount; then + info "Mounting fstab for jail ${_jail} (${_fstab})" + if [ ! -f "${_fstab}" ]; then + err 3 "$name: ${_fstab} does not exist" + fi + jail_mount_fstab + fi + if checkyesno _devfs; then + # If devfs is already mounted here, skip it. + df -t devfs "${_devdir}" >/dev/null + if [ $? -ne 0 ]; then + if is_symlinked_mountpoint ${_devdir}; then + warn "${_devdir} has symlink as parent - not starting jail ${_jail}" + return 2 + fi + info "Mounting devfs on ${_devdir}" + devfs_mount_jail "${_devdir}" ${_ruleset} + # Transitional symlink for old binaries + if [ ! -L "${_devdir}/log" ]; then + __pwd="`pwd`" + cd "${_devdir}" + ln -sf ../var/run/log log + cd "$__pwd" + fi + fi + + # XXX - It seems symlinks don't work when there + # is a devfs(5) device of the same name. + # Jail console output + # __pwd="`pwd`" + # cd "${_devdir}" + # ln -sf ../var/log/console console + # cd "$__pwd" + fi + if checkyesno _fdescfs; then + if is_symlinked_mountpoint ${_fdescdir}; then + warn "${_fdescdir} has symlink as parent, not mounting" + else + info "Mounting fdescfs on ${_fdescdir}" + mount -t fdescfs fdesc "${_fdescdir}" + fi + fi + if checkyesno _procfs; then + if is_symlinked_mountpoint ${_procdir}; then + warn "${_procdir} has symlink as parent, not mounting" + else + info "Mounting procfs onto ${_procdir}" + if [ -d "${_procdir}" ] ; then + mount -t procfs proc "${_procdir}" + fi + fi + fi + + _jail_id=`${_setfib} jail -i ${_flags} -c \ + ${_params} persist=1` + + if [ -n "${_jail_id}" ]; then + jail_zfs_jailin + return 0 + else + return 2 + fi +} + +jail_destroy() +{ + _jail=$1 + init_name $_jail + init_variables $_jail + _jail_id="$(jls -j ${_name} jid 2>/dev/null)" + if [ -z "${_jail_id}" ]; then + return 1 + fi + jail -m jid=${_jail_id} persist=1 + killall -j ${_jail_id} -TERM > /dev/null 2>&1 + sleep 1 + killall -j ${_jail_id} -KILL > /dev/null 2>&1 + + jail_umount_fs + jail_zfs_jailout + jail -m jid="${_jail_id}" persist=0 + return 0 +} + +jail_create() +{ + echo -n 'Creating jails:' + for _jail in ${jail_list} + do + init_name $_jail + init_variables $_jail + jail_init $_jail + _ret=$? + if [ "$_ret" -eq 0 ]; then + echo -n " ${_jail}" + elif [ "$_ret" -eq 1 ]; then + echo -n " [${_jail} already exists (JID: ${_jail_id})]" + else + echo -n "[${_jail} init error]" + fi + done + echo "." +} + +jail_remove() +{ + echo -n 'Removing jails:' + for _jail in ${jail_list} + do + init_name $_jail + _jail_id="$(jls -j ${_name} jid 2>/dev/null)" + if [ -z "${_jail_id}" ]; then + continue + elif `pgrep -j ${_jail_id} >/dev/null 2>&1`; then + echo -n " [${_jail} has running processes (JID: ${_jail_id})]" + continue + fi + jail_destroy $_jail + if [ "$?" -eq 0 ] ; then + echo -n " ${_jail}" + fi + done + echo "." +} + jail_start() { - echo -n 'Configuring jails:' - set_sysctl jail_set_hostname_allow security.jail.set_hostname_allowed \ - set_hostname_allow - set_sysctl jail_socket_unixiproute_only \ - security.jail.socket_unixiproute_only unixiproute_only - set_sysctl jail_sysvipc_allow security.jail.sysvipc_allowed \ - sysvipc_allow - echo '.' - echo -n 'Starting jails:' _tmp_dir=`mktemp -d /tmp/jail.XXXXXXXX` || \ err 3 "$name: Can't create temp dir, exiting..." + for _jail in ${jail_list} do + init_name $_jail init_variables $_jail - if [ -f /var/run/jail_${_jail}.id ]; then - echo -n " [${_hostname} already running (/var/run/jail_${_jail}.id exists)]" - continue; - fi - _addrl="" - jail_ips "add" - if [ -n "${_fib}" ]; then - _setfib="setfib -F '${_fib}'" + _jail_id="$(jls -j ${_name} jid 2>/dev/null)" + if [ -n "${_jail_id}" ]; then + if `pgrep -j ${_jail_id} >/dev/null 2>&1`; then + echo -n " [${_jail} already running (JID: ${_jail_id})]" + continue + fi else - _setfib="" - fi - if checkyesno _mount; then - info "Mounting fstab for jail ${_jail} (${_fstab})" - if [ ! -f "${_fstab}" ]; then - err 3 "$name: ${_fstab} does not exist" + jail_init $_jail + if [ "$?" -ne 0 ] ; then + echo -n " [${_jail} initialization error]" + continue fi - jail_mount_fstab fi - if checkyesno _devfs; then - # If devfs is already mounted here, skip it. - df -t devfs "${_devdir}" >/dev/null - if [ $? -ne 0 ]; then - if is_symlinked_mountpoint ${_devdir}; then - warn "${_devdir} has symlink as parent - not starting jail ${_jail}" - continue - fi - info "Mounting devfs on ${_devdir}" - devfs_mount_jail "${_devdir}" ${_ruleset} - # Transitional symlink for old binaries - if [ ! -L "${_devdir}/log" ]; then - __pwd="`pwd`" - cd "${_devdir}" - ln -sf ../var/run/log log - cd "$__pwd" - fi - fi - # XXX - It seems symlinks don't work when there - # is a devfs(5) device of the same name. - # Jail console output - # __pwd="`pwd`" - # cd "${_devdir}" - # ln -sf ../var/log/console console - # cd "$__pwd" - fi - if checkyesno _fdescfs; then - if is_symlinked_mountpoint ${_fdescdir}; then - warn "${_fdescdir} has symlink as parent, not mounting" - else - info "Mounting fdescfs on ${_fdescdir}" - mount -t fdescfs fdesc "${_fdescdir}" - fi - fi - if checkyesno _procfs; then - if is_symlinked_mountpoint ${_procdir}; then - warn "${_procdir} has symlink as parent, not mounting" - else - info "Mounting procfs onto ${_procdir}" - if [ -d "${_procdir}" ] ; then - mount -t procfs proc "${_procdir}" - fi - fi - fi _tmp_jail=${_tmp_dir}/jail.$$ i=0 @@ -644,12 +817,13 @@ i=$((i + 1)) done - eval ${_setfib} jail ${_flags} -i ${_rootdir} ${_hostname} \ - \"${_addrl}\" ${_exec_start} > ${_tmp_jail} 2>&1 \ - ${_tmp_jail} 2>&1 \ + ${_consolelog} - echo ${_jail_id} > /var/run/jail_${_jail}.id - - i=0 - while : ; do - eval out=\"\${_exec_poststart${i}:-''}\" - [ -z "$out" ] && break - ${out} - i=$((i + 1)) - done else - jail_umount_fs - jail_ips "del" echo " cannot start jail \"${_jail}\": " tail +2 ${_tmp_jail} fi rm -f ${_tmp_jail} done - rmdir ${_tmp_dir} - echo '.' + echo "." } jail_stop() @@ -690,46 +851,71 @@ echo -n 'Stopping jails:' for _jail in ${jail_list} do - if [ -f "/var/run/jail_${_jail}.id" ]; then - _jail_id=$(cat /var/run/jail_${_jail}.id) - if [ ! -z "${_jail_id}" ]; then - init_variables $_jail + init_name $_jail + _jail_id=$(jls -j ${_name} jid 2>/dev/null) + if [ -n "${_jail_id}" ]; then + init_variables $_jail - i=0 - while : ; do - eval out=\"\${_exec_prestop${i}:-''}\" - [ -z "$out" ] && break - ${out} - i=$((i + 1)) - done + if ! `pgrep -j ${_jail_id} >/dev/null 2>&1`; then + echo -n " [${_jail} has no running processes (JID: ${_jail_id})]" + continue + fi - if [ -n "${_exec_stop}" ]; then - eval env -i /usr/sbin/jexec ${_jail_id} ${_exec_stop} \ - >> ${_consolelog} 2>&1 - fi - killall -j ${_jail_id} -TERM > /dev/null 2>&1 - sleep 1 - killall -j ${_jail_id} -KILL > /dev/null 2>&1 - jail_umount_fs - echo -n " $_hostname" + i=0 + while : ; do + eval out=\"\${_exec_prestop${i}:-''}\" + [ -z "$out" ] && break + ${out} + i=$((i + 1)) + done - i=0 - while : ; do - eval out=\"\${_exec_poststop${i}:-''}\" - [ -z "$out" ] && break - ${out} - i=$((i + 1)) - done + if [ -n "${_exec_stop}" ]; then + eval env -i /usr/sbin/jexec ${_jail_id} ${_exec_stop} \ + >> ${_consolelog} 2>&1 fi - jail_ips "del" - rm /var/run/jail_${_jail}.id - else - echo " cannot stop jail ${_jail}. No jail id in /var/run" + + jail -m jid=${_jail_id} persist=1 + killall -j ${_jail_id} -TERM > /dev/null 2>&1 + sleep 1 + killall -j ${_jail_id} -KILL > /dev/null 2>&1 + + if ! checkyesno _persist; then + jail_destroy $_jail + fi + echo -n " $_jail" + + i=0 + while : ; do + eval out=\"\${_exec_poststop${i}:-''}\" + [ -z "$out" ] && break + ${out} + i=$((i + 1)) + done + fi + jail_ips "del" done echo '.' } +jail_status() +{ + for _jail in ${jail_list} + do + init_name $_jail + _jail_id="$(jls -j ${_name} jid 2>/dev/null)" + if [ -n "${_jail_id}" ]; then + _procs=`pgrep -j ${_jail_id} | grep -c .` + if [ "${_procs}" -gt 0 ]; then + _procs=$((${_procs} - 1)) + fi + echo "${_jail} online (JID: ${_jail_id}, processes: ${_procs})" + else + echo "${_jail} offline" + fi + done +} + load_rc_config $name cmd="$1" if [ $# -gt 0 ]; then Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c =================================================================== --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c (revision 227497) +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c (working copy) @@ -21,6 +21,8 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. + * Copyright (c) 2011 by Delphix. All rights reserved. */ #include @@ -297,6 +299,7 @@ if (spa->spa_root_vdev == NULL) { ASSERT(ops == &vdev_root_ops); spa->spa_root_vdev = vd; + spa->spa_load_guid = spa_generate_guid(NULL); } if (guid == 0 && ops != &vdev_hole_ops) { Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h =================================================================== --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h (revision 227497) +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h (working copy) @@ -21,6 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011 by Delphix. All rights reserved. + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. */ #ifndef _SYS_SPA_IMPL_H @@ -136,7 +137,8 @@ objset_t *spa_meta_objset; /* copy of dp->dp_meta_objset */ txg_list_t spa_vdev_txg_list; /* per-txg dirty vdev list */ vdev_t *spa_root_vdev; /* top-level vdev container */ - uint64_t spa_load_guid; /* initial guid for spa_load */ + uint64_t spa_config_guid; /* config pool guid */ + uint64_t spa_load_guid; /* spa_load initialized guid */ list_t spa_config_dirty_list; /* vdevs with dirty config */ list_t spa_state_dirty_list; /* vdevs with dirty state */ spa_aux_vdev_t spa_spares; /* hot spares */ Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa.h =================================================================== --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa.h (revision 227497) +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa.h (working copy) @@ -21,6 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011 by Delphix. All rights reserved. + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. */ #ifndef _SYS_SPA_H @@ -578,6 +579,7 @@ extern int spa_sync_pass(spa_t *spa); extern char *spa_name(spa_t *spa); extern uint64_t spa_guid(spa_t *spa); +extern uint64_t spa_load_guid(spa_t *spa); extern uint64_t spa_last_synced_txg(spa_t *spa); extern uint64_t spa_first_txg(spa_t *spa); extern uint64_t spa_syncing_txg(spa_t *spa); @@ -611,6 +613,7 @@ extern uint64_t spa_generate_guid(spa_t *spa); extern void sprintf_blkptr(char *buf, const blkptr_t *bp); extern void spa_freeze(spa_t *spa); +extern int spa_change_guid(spa_t *spa); extern void spa_upgrade(spa_t *spa, uint64_t version); extern void spa_evict_all(void); extern vdev_t *spa_lookup_by_guid(spa_t *spa, uint64_t guid, Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c =================================================================== --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c (revision 227497) +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c (working copy) @@ -21,6 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011 by Delphix. All rights reserved. */ /* @@ -572,6 +573,43 @@ } /* + * Change the GUID for the pool. This is done so that we can later + * re-import a pool built from a clone of our own vdevs. We will modify + * the root vdev's guid, our own pool guid, and then mark all of our + * vdevs dirty. Note that we must make sure that all our vdevs are + * online when we do this, or else any vdevs that weren't present + * would be orphaned from our pool. We are also going to issue a + * sysevent to update any watchers. + */ +int +spa_change_guid(spa_t *spa) +{ + uint64_t oldguid, newguid; + uint64_t txg; + + if (!(spa_mode_global & FWRITE)) + return (EROFS); + + txg = spa_vdev_enter(spa); + + if (spa->spa_root_vdev->vdev_state != VDEV_STATE_HEALTHY) + return (spa_vdev_exit(spa, NULL, txg, ENXIO)); + + oldguid = spa_guid(spa); + newguid = spa_generate_guid(NULL); + ASSERT3U(oldguid, !=, newguid); + + spa->spa_root_vdev->vdev_guid = newguid; + spa->spa_root_vdev->vdev_guid_sum += (newguid - oldguid); + + vdev_config_dirty(spa->spa_root_vdev); + + spa_event_notify(spa, NULL, ESC_ZFS_POOL_REGUID); + + return (spa_vdev_exit(spa, NULL, txg, 0)); +} + +/* * ========================================================================== * SPA state manipulation (open/create/destroy/import/export) * ========================================================================== @@ -1764,7 +1802,7 @@ spa_guid_exists(pool_guid, 0)) { error = EEXIST; } else { - spa->spa_load_guid = pool_guid; + spa->spa_config_guid = pool_guid; if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_SPLIT, &nvl) == 0) { Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c =================================================================== --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c (revision 227497) +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c (working copy) @@ -20,6 +20,8 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. + * Copyright (c) 2011 by Delphix. All rights reserved. */ /* @@ -1365,7 +1367,7 @@ ASSERT(BUF_EMPTY(hdr)); hdr->b_size = size; hdr->b_type = type; - hdr->b_spa = spa_guid(spa); + hdr->b_spa = spa_load_guid(spa); hdr->b_state = arc_anon; hdr->b_arc_access = 0; buf = kmem_cache_alloc(buf_cache, KM_PUSHPAGE); @@ -2146,7 +2148,7 @@ uint64_t guid = 0; if (spa) - guid = spa_guid(spa); + guid = spa_load_guid(spa); while (arc_mru->arcs_lsize[ARC_BUFC_DATA]) { (void) arc_evict(arc_mru, guid, -1, FALSE, ARC_BUFC_DATA); @@ -2936,7 +2938,7 @@ arc_buf_t *buf; kmutex_t *hash_lock; zio_t *rzio; - uint64_t guid = spa_guid(spa); + uint64_t guid = spa_load_guid(spa); top: hdr = buf_hash_find(guid, BP_IDENTITY(bp), BP_PHYSICAL_BIRTH(bp), @@ -4593,7 +4595,7 @@ boolean_t have_lock, full; l2arc_write_callback_t *cb; zio_t *pio, *wzio; - uint64_t guid = spa_guid(spa); + uint64_t guid = spa_load_guid(spa); int try; ASSERT(dev->l2ad_vdev != NULL); Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c =================================================================== --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c (revision 227497) +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c (working copy) @@ -24,6 +24,10 @@ * All rights reserved. * Portions Copyright 2011 Martin Matuska */ +/* + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. + * Copyright (c) 2011 by Delphix. All rights reserved. + */ #include #include @@ -1469,6 +1473,20 @@ } static int +zfs_ioc_pool_reguid(zfs_cmd_t *zc) +{ + spa_t *spa; + int error; + + error = spa_open(zc->zc_name, &spa, FTAG); + if (error == 0) { + error = spa_change_guid(spa); + spa_close(spa, FTAG); + } + return (error); +} + +static int zfs_ioc_dsobj_to_dsname(zfs_cmd_t *zc) { int error; @@ -4795,7 +4813,9 @@ { zfs_ioc_obj_to_stats, zfs_secpolicy_diff, DATASET_NAME, B_FALSE, B_TRUE }, { zfs_ioc_jail, zfs_secpolicy_config, DATASET_NAME, B_TRUE, B_FALSE }, - { zfs_ioc_unjail, zfs_secpolicy_config, DATASET_NAME, B_TRUE, B_FALSE } + { zfs_ioc_unjail, zfs_secpolicy_config, DATASET_NAME, B_TRUE, B_FALSE }, + { zfs_ioc_pool_reguid, zfs_secpolicy_config, POOL_NAME, B_TRUE, + B_TRUE } }; int Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c =================================================================== --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c (revision 227497) +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c (working copy) @@ -21,6 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011 by Delphix. All rights reserved. + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. */ #include @@ -1308,16 +1309,27 @@ /* * If we fail to parse the config during spa_load(), we can go through * the error path (which posts an ereport) and end up here with no root - * vdev. We stash the original pool guid in 'spa_load_guid' to handle + * vdev. We stash the original pool guid in 'spa_config_guid' to handle * this case. */ if (spa->spa_root_vdev != NULL) return (spa->spa_root_vdev->vdev_guid); else - return (spa->spa_load_guid); + return (spa->spa_config_guid); } uint64_t +spa_load_guid(spa_t *spa) +{ + /* + * This is a GUID that exists solely as a reference for the + * purposes of the arc. It is generated at load time, and + * is never written to persistent storage. + */ + return (spa->spa_load_guid); +} + +uint64_t spa_last_synced_txg(spa_t *spa) { return (spa->spa_ubsync.ub_txg); Index: sys/cddl/contrib/opensolaris/uts/common/sys/sysevent/eventdefs.h =================================================================== --- sys/cddl/contrib/opensolaris/uts/common/sys/sysevent/eventdefs.h (revision 227497) +++ sys/cddl/contrib/opensolaris/uts/common/sys/sysevent/eventdefs.h (working copy) @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. */ #ifndef _SYS_SYSEVENT_EVENTDEFS_H @@ -256,6 +257,7 @@ #define ESC_ZFS_SCRUB_FINISH "ESC_ZFS_scrub_finish" #define ESC_ZFS_VDEV_SPARE "ESC_ZFS_vdev_spare" #define ESC_ZFS_BOOTFS_VDEV_ATTACH "ESC_ZFS_bootfs_vdev_attach" +#define ESC_ZFS_POOL_REGUID "ESC_ZFS_pool_reguid" #define ESC_ZFS_VDEV_AUTOEXPAND "ESC_ZFS_vdev_autoexpand" /* Index: sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h =================================================================== --- sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h (revision 227497) +++ sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h (working copy) @@ -22,6 +22,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011 by Delphix. All rights reserved. + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. */ /* Portions Copyright 2010 Robert Milkowski */ @@ -783,6 +784,7 @@ #define ZFS_IOC_OBJ_TO_STATS _IOWR('Z', 57, struct zfs_cmd) #define ZFS_IOC_JAIL _IOWR('Z', 58, struct zfs_cmd) #define ZFS_IOC_UNJAIL _IOWR('Z', 59, struct zfs_cmd) +#define ZFS_IOC_POOL_REGUID _IOWR('Z', 60, struct zfs_cmd) /* * Internal SPA load state. Used by FMA diagnosis engine. @@ -844,6 +846,7 @@ * ESC_ZFS_RESILVER_START * ESC_ZFS_RESILVER_END * ESC_ZFS_POOL_DESTROY + * ESC_ZFS_POOL_REGUID * * ZFS_EV_POOL_NAME DATA_TYPE_STRING * ZFS_EV_POOL_GUID DATA_TYPE_UINT64