Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 5 Jan 2012 09:39:29 +0000 (UTC)
From:      Martin Matuska <mm@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r229566 - in stable/8: cddl/contrib/opensolaris/cmd/zfs cddl/contrib/opensolaris/lib/libzfs/common sys/cddl/contrib/opensolaris/uts/common/fs/zfs sys/cddl/contrib/opensolaris/uts/common...
Message-ID:  <201201050939.q059dTr7024532@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mm
Date: Thu Jan  5 09:39:29 2012
New Revision: 229566
URL: http://svn.freebsd.org/changeset/base/229566

Log:
  MFC r226676, r226678, r226700, r226705, r226706, r226707:
  
  MFC r226676 (pjd):
  Allow to rename file systems without remounting if it is possible.
  It is possible for file systems with 'mountpoint' preperty set to 'legacy'
  or 'none' - we don't have to change mount directory for them.
  Currently such file systems are unmounted on rename and not even mounted back.
  
  This introduces layering violation, as we need to update 'f_mntfromname'
  field in statfs structure related to mountpoint (for the dataset we are
  renaming and all its children).
  
  In my opinion it is worth it, as it allow to update FreeBSD in even cleaner
  way - in ZFS-only configuration root file system is ZFS file system with
  'mountpoint' property set to 'legacy'. If root dataset is named system/rootfs,
  we can snapshot it (system/rootfs@upgrade), clone it (system/oldrootfs),
  update FreeBSD and if it doesn't boot we can boot back from system/oldrootfs
  and rename it back to system/rootfs while it is mounted as /. Before it was
  not possible, because unmounting / was not possible.
  
  MFC r227768 (pjd):
  Include <sys/zfs_vfsops.h> only when compiling kernel module.
  
  MFC r226700 (pjd):
  Don't forget to rename mounted snapshots of the file system being renamed.
  
  MFC r226705 (pjd):
  Extend r226676 to allow rename without unmount even for file systems with
  non-legacy mountpoints. It is better to be able to rename such file systems and
  let them be mounted in old places until next reboot than using live CD, etc. to
  rename with remount.
  
  This is implemented by adding -u option to 'zfs rename'. If file system's
  mountpoint property is set to 'legacy' or 'none', there is no need to specify -u.
  
  Update zfs(8) manual page to reflect this addition.
  
  MFC r226706 (pjd):
  Update copyright to include myself.
  
  MFC r226707 (pjd):
  - Use better naming now that we allow to rename any mounted file system (not
    only legacy).
  - Update copyright to include myself.
  
  Approved by:	pjd

Modified:
  stable/8/cddl/contrib/opensolaris/cmd/zfs/zfs.8
  stable/8/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c
  stable/8/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h
  stable/8/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_changelist.c
  stable/8/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
  stable/8/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h
  stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
  stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c
  stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h
  stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dir.h
  stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_vfsops.h
  stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c
  stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
  stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
Directory Properties:
  stable/8/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)

Modified: stable/8/cddl/contrib/opensolaris/cmd/zfs/zfs.8
==============================================================================
--- stable/8/cddl/contrib/opensolaris/cmd/zfs/zfs.8	Thu Jan  5 09:37:31 2012	(r229565)
+++ stable/8/cddl/contrib/opensolaris/cmd/zfs/zfs.8	Thu Jan  5 09:39:29 2012	(r229566)
@@ -76,6 +76,11 @@ zfs \- configures ZFS file systems
 
 .LP
 .nf
+\fBzfs\fR \fBrename\fR \fB-u\fR [\fB-p\fR] \fIfilesystem\fR \fIfilesystem\fR
+.fi
+
+.LP
+.nf
 \fBzfs\fR \fBlist\fR [\fB-r\fR|\fB-d\fR \fIdepth\fR][\fB-H\fR][\fB-o\fR \fIproperty\fR[,...]] [\fB-t\fR \fItype\fR[,...]]
      [\fB-s\fR \fIproperty\fR] ... [\fB-S\fR \fIproperty\fR] ... [\fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR] ...
 .fi
@@ -1479,6 +1484,10 @@ The snapshot that was cloned, and any sn
 .na
 \fB\fBzfs rename\fR [\fB-p\fR] \fIfilesystem\fR|\fIvolume\fR \fIfilesystem\fR|\fIvolume\fR\fR
 .ad
+.br
+.na
+\fB\fBzfs rename\fR \fB-u\fR [\fB-p\fR] \fIfilesystem\fR \fIfilesystem\fR\fR
+.ad
 .sp .6
 .RS 4n
 Renames the given dataset. The new target can be located anywhere in the \fBZFS\fR hierarchy, with the exception of snapshots. Snapshots can only be renamed within the parent file system or volume. When renaming a snapshot, the parent file system of the snapshot does not need to be specified as part of the second argument. Renamed file systems can inherit new mount points, in which case they are unmounted and remounted at the new mount point.
@@ -1493,6 +1502,17 @@ Renames the given dataset. The new targe
 Creates all the nonexistent parent datasets. Datasets created in this manner are automatically mounted according to the \fBmountpoint\fR property inherited from their parent.
 .RE
 
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-u\fR\fR
+.ad
+.sp .6
+.RS 4n
+Do not remount file systems during rename. If a file system's \fBmountpoint\fR property is set to \fBlegacy\fR or \fBnone\fR, file system is not unmounted even if this option is not given.
+.RE
+
 .RE
 
 .sp

Modified: stable/8/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c
==============================================================================
--- stable/8/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c	Thu Jan  5 09:37:31 2012	(r229565)
+++ stable/8/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c	Thu Jan  5 09:39:29 2012	(r229566)
@@ -22,6 +22,8 @@
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+ * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
+ * All rights reserved.
  */
 
 #include <assert.h>
@@ -253,7 +255,8 @@ get_usage(zfs_help_t idx)
 		return (gettext("\trename <filesystem|volume|snapshot> "
 		    "<filesystem|volume|snapshot>\n"
 		    "\trename -p <filesystem|volume> <filesystem|volume>\n"
-		    "\trename -r <snapshot> <snapshot>"));
+		    "\trename -r <snapshot> <snapshot>\n"
+		    "\trename -u [-p] <filesystem> <filesystem>"));
 	case HELP_ROLLBACK:
 		return (gettext("\trollback [-rRf] <snapshot>\n"));
 	case HELP_SEND:
@@ -2852,6 +2855,7 @@ zfs_do_list(int argc, char **argv)
  * zfs rename <fs | snap | vol> <fs | snap | vol>
  * zfs rename -p <fs | vol> <fs | vol>
  * zfs rename -r <snap> <snap>
+ * zfs rename -u [-p] <fs> <fs>
  *
  * Renames the given dataset to another of the same type.
  *
@@ -2862,19 +2866,21 @@ static int
 zfs_do_rename(int argc, char **argv)
 {
 	zfs_handle_t *zhp;
-	int c;
-	int ret;
-	boolean_t recurse = B_FALSE;
+	renameflags_t flags = { 0 };
+	int c, ret, types;
 	boolean_t parents = B_FALSE;
 
 	/* check options */
-	while ((c = getopt(argc, argv, "pr")) != -1) {
+	while ((c = getopt(argc, argv, "pru")) != -1) {
 		switch (c) {
 		case 'p':
 			parents = B_TRUE;
 			break;
 		case 'r':
-			recurse = B_TRUE;
+			flags.recurse = B_TRUE;
+			break;
+		case 'u':
+			flags.nounmount = B_TRUE;
 			break;
 		case '?':
 		default:
@@ -2903,20 +2909,32 @@ zfs_do_rename(int argc, char **argv)
 		usage(B_FALSE);
 	}
 
-	if (recurse && parents) {
+	if (flags.recurse && parents) {
 		(void) fprintf(stderr, gettext("-p and -r options are mutually "
 		    "exclusive\n"));
 		usage(B_FALSE);
 	}
 
-	if (recurse && strchr(argv[0], '@') == 0) {
+	if (flags.recurse && strchr(argv[0], '@') == 0) {
 		(void) fprintf(stderr, gettext("source dataset for recursive "
 		    "rename must be a snapshot\n"));
 		usage(B_FALSE);
 	}
 
-	if ((zhp = zfs_open(g_zfs, argv[0], parents ? ZFS_TYPE_FILESYSTEM |
-	    ZFS_TYPE_VOLUME : ZFS_TYPE_DATASET)) == NULL)
+	if (flags.nounmount && parents) {
+		(void) fprintf(stderr, gettext("-u and -r options are mutually "
+		    "exclusive\n"));
+		usage(B_FALSE);
+	}
+
+	if (flags.nounmount)
+		types = ZFS_TYPE_FILESYSTEM;
+	else if (parents)
+		types = ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME;
+	else
+		types = ZFS_TYPE_DATASET;
+
+	if ((zhp = zfs_open(g_zfs, argv[0], types)) == NULL)
 		return (1);
 
 	/* If we were asked and the name looks good, try to create ancestors. */
@@ -2926,7 +2944,7 @@ zfs_do_rename(int argc, char **argv)
 		return (1);
 	}
 
-	ret = (zfs_rename(zhp, argv[1], recurse) != 0);
+	ret = (zfs_rename(zhp, argv[1], flags) != 0);
 
 	zfs_close(zhp);
 	return (ret);

Modified: stable/8/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h
==============================================================================
--- stable/8/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h	Thu Jan  5 09:37:31 2012	(r229565)
+++ stable/8/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h	Thu Jan  5 09:39:29 2012	(r229566)
@@ -22,6 +22,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 <pawel@dawidek.net>.
+ * All rights reserved.
  */
 
 #ifndef	_LIBZFS_H
@@ -517,7 +519,16 @@ extern int zfs_destroy_snaps(zfs_handle_
 extern int zfs_clone(zfs_handle_t *, const char *, nvlist_t *);
 extern int zfs_snapshot(libzfs_handle_t *, const char *, boolean_t, nvlist_t *);
 extern int zfs_rollback(zfs_handle_t *, zfs_handle_t *, boolean_t);
-extern int zfs_rename(zfs_handle_t *, const char *, boolean_t);
+
+typedef struct renameflags {
+	/* recursive rename */
+	int recurse : 1;
+
+	/* don't unmount file systems */
+	int nounmount : 1;
+} renameflags_t;
+
+extern int zfs_rename(zfs_handle_t *, const char *, renameflags_t flags);
 
 typedef struct sendflags {
 	/* print informational messages (ie, -v was specified) */

Modified: stable/8/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_changelist.c
==============================================================================
--- stable/8/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_changelist.c	Thu Jan  5 09:37:31 2012	(r229565)
+++ stable/8/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_changelist.c	Thu Jan  5 09:39:29 2012	(r229566)
@@ -24,6 +24,9 @@
  * Use is subject to license terms.
  *
  * Portions Copyright 2007 Ramprakash Jelari
+ *
+ * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
+ * All rights reserved.
  */
 
 #include <libintl.h>
@@ -122,6 +125,8 @@ changelist_prefix(prop_changelist_t *clp
 			 */
 			switch (clp->cl_prop) {
 			case ZFS_PROP_MOUNTPOINT:
+				if (clp->cl_gflags & CL_GATHER_DONT_UNMOUNT)
+					break;
 				if (zfs_unmount(cn->cn_handle, NULL,
 				    clp->cl_mflags) != 0) {
 					ret = -1;
@@ -168,8 +173,10 @@ changelist_postfix(prop_changelist_t *cl
 	if ((cn = uu_list_last(clp->cl_list)) == NULL)
 		return (0);
 
-	if (clp->cl_prop == ZFS_PROP_MOUNTPOINT)
+	if (clp->cl_prop == ZFS_PROP_MOUNTPOINT &&
+	    !(clp->cl_gflags & CL_GATHER_DONT_UNMOUNT)) {
 		remove_mountpoint(cn->cn_handle);
+	}
 
 	/*
 	 * It is possible that the changelist_prefix() used libshare
@@ -224,7 +231,8 @@ changelist_postfix(prop_changelist_t *cl
 		    shareopts, sizeof (shareopts), NULL, NULL, 0,
 		    B_FALSE) == 0) && (strcmp(shareopts, "off") != 0));
 
-		mounted = zfs_is_mounted(cn->cn_handle, NULL);
+		mounted = (clp->cl_gflags & CL_GATHER_DONT_UNMOUNT) ||
+		    zfs_is_mounted(cn->cn_handle, NULL);
 
 		if (!mounted && (cn->cn_mounted ||
 		    ((sharenfs || sharesmb || clp->cl_waslegacy) &&

Modified: stable/8/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
==============================================================================
--- stable/8/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c	Thu Jan  5 09:37:31 2012	(r229565)
+++ stable/8/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c	Thu Jan  5 09:39:29 2012	(r229566)
@@ -23,6 +23,8 @@
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
  * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
+ * All rights reserved.
  */
 
 #include <ctype.h>
@@ -3480,7 +3482,7 @@ zfs_iter_dependents(zfs_handle_t *zhp, b
  * Renames the given dataset.
  */
 int
-zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive)
+zfs_rename(zfs_handle_t *zhp, const char *target, renameflags_t flags)
 {
 	int ret;
 	zfs_cmd_t zc = { 0 };
@@ -3489,6 +3491,7 @@ zfs_rename(zfs_handle_t *zhp, const char
 	zfs_handle_t *zhrp = NULL;
 	char *parentname = NULL;
 	char parent[ZFS_MAXNAMELEN];
+	char property[ZFS_MAXPROPLEN];
 	libzfs_handle_t *hdl = zhp->zfs_hdl;
 	char errbuf[1024];
 
@@ -3535,7 +3538,7 @@ zfs_rename(zfs_handle_t *zhp, const char
 		if (!zfs_validate_name(hdl, target, zhp->zfs_type, B_TRUE))
 			return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
 	} else {
-		if (recursive) {
+		if (flags.recurse) {
 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 			    "recursive rename must be a snapshot"));
 			return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
@@ -3576,7 +3579,20 @@ zfs_rename(zfs_handle_t *zhp, const char
 		return (zfs_error(hdl, EZFS_ZONED, errbuf));
 	}
 
-	if (recursive) {
+	/*
+	 * Avoid unmounting file systems with mountpoint property set to
+	 * 'legacy' or 'none' even if -u option is not given.
+	 */
+	if (zhp->zfs_type == ZFS_TYPE_FILESYSTEM &&
+	    !flags.recurse && !flags.nounmount &&
+	    zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, property,
+	    sizeof (property), NULL, NULL, 0, B_FALSE) == 0 &&
+	    (strcmp(property, "legacy") == 0 ||
+	     strcmp(property, "none") == 0)) {
+		flags.nounmount = B_TRUE;
+	}
+
+	if (flags.recurse) {
 
 		parentname = zfs_strdup(zhp->zfs_hdl, zhp->zfs_name);
 		if (parentname == NULL) {
@@ -3592,8 +3608,10 @@ zfs_rename(zfs_handle_t *zhp, const char
 		}
 
 	} else {
-		if ((cl = changelist_gather(zhp, ZFS_PROP_NAME, 0, 0)) == NULL)
+		if ((cl = changelist_gather(zhp, ZFS_PROP_NAME,
+		    flags.nounmount ? CL_GATHER_DONT_UNMOUNT : 0, 0)) == NULL) {
 			return (-1);
+		}
 
 		if (changelist_haszonedchild(cl)) {
 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
@@ -3615,7 +3633,9 @@ zfs_rename(zfs_handle_t *zhp, const char
 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
 	(void) strlcpy(zc.zc_value, target, sizeof (zc.zc_value));
 
-	zc.zc_cookie = recursive;
+	zc.zc_cookie = flags.recurse ? 1 : 0;
+	if (flags.nounmount)
+		zc.zc_cookie |= 2;
 
 	if ((ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_RENAME, &zc)) != 0) {
 		/*
@@ -3625,7 +3645,7 @@ zfs_rename(zfs_handle_t *zhp, const char
 		(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
 		    "cannot rename '%s'"), zc.zc_name);
 
-		if (recursive && errno == EEXIST) {
+		if (flags.recurse && errno == EEXIST) {
 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 			    "a child dataset already has a snapshot "
 			    "with the new name"));
@@ -3638,10 +3658,10 @@ zfs_rename(zfs_handle_t *zhp, const char
 		 * On failure, we still want to remount any filesystems that
 		 * were previously mounted, so we don't alter the system state.
 		 */
-		if (!recursive)
+		if (!flags.recurse)
 			(void) changelist_postfix(cl);
 	} else {
-		if (!recursive) {
+		if (!flags.recurse) {
 			changelist_rename(cl, zfs_get_name(zhp), target);
 			ret = changelist_postfix(cl);
 		}

Modified: stable/8/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h
==============================================================================
--- stable/8/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h	Thu Jan  5 09:37:31 2012	(r229565)
+++ stable/8/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h	Thu Jan  5 09:39:29 2012	(r229566)
@@ -21,6 +21,8 @@
 
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
+ * All rights reserved.
  */
 
 #ifndef	_LIBFS_IMPL_H
@@ -158,7 +160,11 @@ int zprop_expand_list(libzfs_handle_t *h
  * on each change node regardless of whether or not it is currently
  * mounted.
  */
-#define	CL_GATHER_MOUNT_ALWAYS	1
+#define	CL_GATHER_MOUNT_ALWAYS	0x01
+/*
+ * Use this changelist_gather() flag to prevent unmounting of file systems.
+ */
+#define	CL_GATHER_DONT_UNMOUNT	0x02
 
 typedef struct prop_changelist prop_changelist_t;
 

Modified: stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
==============================================================================
--- stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c	Thu Jan  5 09:37:31 2012	(r229565)
+++ stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c	Thu Jan  5 09:39:29 2012	(r229566)
@@ -21,6 +21,8 @@
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
+ * All rights reserved.
  */
 
 #include <sys/dmu_objset.h>
@@ -2461,7 +2463,7 @@ dsl_valid_rename(const char *oldname, vo
 
 #pragma weak dmu_objset_rename = dsl_dataset_rename
 int
-dsl_dataset_rename(char *oldname, const char *newname, boolean_t recursive)
+dsl_dataset_rename(char *oldname, const char *newname, int flags)
 {
 	dsl_dir_t *dd;
 	dsl_dataset_t *ds;
@@ -2481,7 +2483,7 @@ dsl_dataset_rename(char *oldname, const 
 			    &delta, DS_FIND_CHILDREN | DS_FIND_SNAPSHOTS);
 
 		if (err == 0)
-			err = dsl_dir_rename(dd, newname);
+			err = dsl_dir_rename(dd, newname, flags);
 		dsl_dir_close(dd, FTAG);
 		return (err);
 	}
@@ -2502,7 +2504,7 @@ dsl_dataset_rename(char *oldname, const 
 	if (strncmp(oldname, newname, tail - newname) != 0)
 		return (EXDEV);
 
-	if (recursive) {
+	if (flags & ZFS_RENAME_RECURSIVE) {
 		err = dsl_recursive_rename(oldname, newname);
 	} else {
 		err = dsl_dataset_hold(oldname, FTAG, &ds);

Modified: stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c
==============================================================================
--- stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c	Thu Jan  5 09:37:31 2012	(r229565)
+++ stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c	Thu Jan  5 09:39:29 2012	(r229566)
@@ -20,6 +20,8 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
+ * All rights reserved.
  */
 
 #include <sys/dmu.h>
@@ -37,6 +39,9 @@
 #include <sys/arc.h>
 #include <sys/sunddi.h>
 #include <sys/zvol.h>
+#ifdef _KERNEL
+#include <sys/zfs_vfsops.h>
+#endif
 #include "zfs_namecheck.h"
 
 static uint64_t dsl_dir_space_towrite(dsl_dir_t *dd);
@@ -1245,6 +1250,7 @@ would_change(dsl_dir_t *dd, int64_t delt
 struct renamearg {
 	dsl_dir_t *newparent;
 	const char *mynewname;
+	boolean_t allowmounted;
 };
 
 static int
@@ -1263,9 +1269,12 @@ dsl_dir_rename_check(void *arg1, void *a
 	 * stats), but any that are present in open context will likely
 	 * be gone by syncing context, so only fail from syncing
 	 * context.
+	 * Don't check if we allow renaming of busy (mounted) dataset.
 	 */
-	if (dmu_tx_is_syncing(tx) && dmu_buf_refcount(dd->dd_dbuf) > 1)
+	if (!ra->allowmounted && dmu_tx_is_syncing(tx) &&
+	    dmu_buf_refcount(dd->dd_dbuf) > 1) {
 		return (EBUSY);
+	}
 
 	/* check for existing name */
 	err = zap_lookup(mos, ra->newparent->dd_phys->dd_child_dir_zapobj,
@@ -1302,7 +1311,7 @@ dsl_dir_rename_sync(void *arg1, void *ar
 	objset_t *mos = dp->dp_meta_objset;
 	int err;
 
-	ASSERT(dmu_buf_refcount(dd->dd_dbuf) <= 2);
+	ASSERT(ra->allowmounted || dmu_buf_refcount(dd->dd_dbuf) <= 2);
 
 	if (ra->newparent != dd->dd_parent) {
 		dsl_dir_diduse_space(dd->dd_parent, DD_USED_CHILD,
@@ -1345,6 +1354,7 @@ dsl_dir_rename_sync(void *arg1, void *ar
 	ASSERT3U(err, ==, 0);
 	dsl_dir_name(dd, newname);
 #ifdef _KERNEL
+	zfsvfs_update_fromname(oldname, newname);
 	zvol_rename_minors(oldname, newname);
 #endif
 
@@ -1353,7 +1363,7 @@ dsl_dir_rename_sync(void *arg1, void *ar
 }
 
 int
-dsl_dir_rename(dsl_dir_t *dd, const char *newname)
+dsl_dir_rename(dsl_dir_t *dd, const char *newname, int flags)
 {
 	struct renamearg ra;
 	int err;
@@ -1375,6 +1385,8 @@ dsl_dir_rename(dsl_dir_t *dd, const char
 		goto out;
 	}
 
+	ra.allowmounted = !!(flags & ZFS_RENAME_ALLOW_MOUNTED);
+
 	err = dsl_sync_task_do(dd->dd_pool,
 	    dsl_dir_rename_check, dsl_dir_rename_sync, dd, &ra, 3);
 

Modified: stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h
==============================================================================
--- stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h	Thu Jan  5 09:37:31 2012	(r229565)
+++ stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h	Thu Jan  5 09:39:29 2012	(r229566)
@@ -20,6 +20,8 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
+ * All rights reserved.
  */
 
 #ifndef	_SYS_DSL_DATASET_H
@@ -178,6 +180,12 @@ struct dsl_ds_holdarg {
 	char failed[MAXPATHLEN];
 };
 
+/*
+ * Flags for dsl_dataset_rename().
+ */
+#define	ZFS_RENAME_RECURSIVE		0x01
+#define	ZFS_RENAME_ALLOW_MOUNTED	0x02
+
 #define	dsl_dataset_is_snapshot(ds) \
 	((ds)->ds_phys->ds_num_children != 0)
 
@@ -211,7 +219,7 @@ dsl_syncfunc_t dsl_dataset_destroy_sync;
 dsl_checkfunc_t dsl_dataset_snapshot_check;
 dsl_syncfunc_t dsl_dataset_snapshot_sync;
 dsl_syncfunc_t dsl_dataset_user_hold_sync;
-int dsl_dataset_rename(char *name, const char *newname, boolean_t recursive);
+int dsl_dataset_rename(char *name, const char *newname, int flags);
 int dsl_dataset_promote(const char *name, char *conflsnap);
 int dsl_dataset_clone_swap(dsl_dataset_t *clone, dsl_dataset_t *origin_head,
     boolean_t force);

Modified: stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dir.h
==============================================================================
--- stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dir.h	Thu Jan  5 09:37:31 2012	(r229565)
+++ stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dir.h	Thu Jan  5 09:39:29 2012	(r229566)
@@ -20,6 +20,8 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
+ * All rights reserved.
  */
 
 #ifndef	_SYS_DSL_DIR_H
@@ -131,7 +133,7 @@ int dsl_dir_set_quota(const char *ddname
     uint64_t quota);
 int dsl_dir_set_reservation(const char *ddname, zprop_source_t source,
     uint64_t reservation);
-int dsl_dir_rename(dsl_dir_t *dd, const char *newname);
+int dsl_dir_rename(dsl_dir_t *dd, const char *newname, int flags);
 int dsl_dir_transfer_possible(dsl_dir_t *sdd, dsl_dir_t *tdd, uint64_t space);
 int dsl_dir_set_reservation_check(void *arg1, void *arg2, dmu_tx_t *tx);
 boolean_t dsl_dir_is_clone(dsl_dir_t *dd);

Modified: stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_vfsops.h
==============================================================================
--- stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_vfsops.h	Thu Jan  5 09:37:31 2012	(r229565)
+++ stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_vfsops.h	Thu Jan  5 09:39:29 2012	(r229566)
@@ -20,6 +20,8 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
+ * All rights reserved.
  */
 
 #ifndef	_SYS_FS_ZFS_VFSOPS_H
@@ -153,6 +155,10 @@ extern void zfsvfs_free(zfsvfs_t *zfsvfs
 extern int zfs_check_global_label(const char *dsname, const char *hexsl);
 extern int zfs_vnode_lock(vnode_t *vp, int flags);
 
+#ifdef _KERNEL
+extern void zfsvfs_update_fromname(const char *oldname, const char *newname);
+#endif
+
 #ifdef	__cplusplus
 }
 #endif

Modified: stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c
==============================================================================
--- stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c	Thu Jan  5 09:37:31 2012	(r229565)
+++ stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c	Thu Jan  5 09:39:29 2012	(r229566)
@@ -20,6 +20,8 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
+ * All rights reserved.
  */
 
 /*
@@ -785,7 +787,7 @@ zfsctl_snapdir_rename(vnode_t *sdvp, cha
 		return (ENOENT);
 	}
 
-	err = dmu_objset_rename(from, to, B_FALSE);
+	err = dmu_objset_rename(from, to, 0);
 	if (err == 0)
 		zfsctl_rename_snap(sdp, sep, tnm);
 

Modified: stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
==============================================================================
--- stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c	Thu Jan  5 09:37:31 2012	(r229565)
+++ stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c	Thu Jan  5 09:39:29 2012	(r229566)
@@ -20,6 +20,8 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
+ * All rights reserved.
  * Portions Copyright 2011 Martin Matuska <mm@FreeBSD.org>
  */
 
@@ -3262,7 +3264,12 @@ out:
 static int
 zfs_ioc_rename(zfs_cmd_t *zc)
 {
-	boolean_t recursive = zc->zc_cookie & 1;
+	int flags = 0;
+
+	if (zc->zc_cookie & 1)
+		flags |= ZFS_RENAME_RECURSIVE;
+	if (zc->zc_cookie & 2)
+		flags |= ZFS_RENAME_ALLOW_MOUNTED;
 
 	zc->zc_value[sizeof (zc->zc_value) - 1] = '\0';
 	if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 ||
@@ -3274,13 +3281,14 @@ zfs_ioc_rename(zfs_cmd_t *zc)
 	 * in which case the dataset code figures out which snapshots
 	 * to unmount.
 	 */
-	if (!recursive && strchr(zc->zc_name, '@') != NULL &&
+	if (!(flags & ZFS_RENAME_RECURSIVE) &&
+	    strchr(zc->zc_name, '@') != NULL &&
 	    zc->zc_objset_type == DMU_OST_ZFS) {
 		int err = zfs_unmount_snap(zc->zc_name, NULL);
 		if (err)
 			return (err);
 	}
-	return (dmu_objset_rename(zc->zc_name, zc->zc_value, recursive));
+	return (dmu_objset_rename(zc->zc_name, zc->zc_value, flags));
 }
 
 static int

Modified: stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
==============================================================================
--- stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c	Thu Jan  5 09:37:31 2012	(r229565)
+++ stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c	Thu Jan  5 09:39:29 2012	(r229566)
@@ -20,6 +20,8 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
+ * All rights reserved.
  */
 
 /* Portions Copyright 2010 Robert Milkowski */
@@ -2416,3 +2418,35 @@ zfs_get_zplprop(objset_t *os, zfs_prop_t
 	}
 	return (error);
 }
+
+#ifdef _KERNEL
+void
+zfsvfs_update_fromname(const char *oldname, const char *newname)
+{
+	char tmpbuf[MAXPATHLEN];
+	struct mount *mp;
+	char *fromname;
+	size_t oldlen;
+
+	oldlen = strlen(oldname);
+
+	mtx_lock(&mountlist_mtx);
+	TAILQ_FOREACH(mp, &mountlist, mnt_list) {
+		fromname = mp->mnt_stat.f_mntfromname;
+		if (strcmp(fromname, oldname) == 0) {
+			(void)strlcpy(fromname, newname,
+			    sizeof(mp->mnt_stat.f_mntfromname));
+			continue;
+		}
+		if (strncmp(fromname, oldname, oldlen) == 0 &&
+		    (fromname[oldlen] == '/' || fromname[oldlen] == '@')) {
+			(void)snprintf(tmpbuf, sizeof(tmpbuf), "%s%s",
+			    newname, fromname + oldlen);
+			(void)strlcpy(fromname, tmpbuf,
+			    sizeof(mp->mnt_stat.f_mntfromname));
+			continue;
+		}
+	}
+	mtx_unlock(&mountlist_mtx);
+}
+#endif



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201201050939.q059dTr7024532>