Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 14 Apr 2017 18:19:49 +0000 (UTC)
From:      Andriy Gapon <avg@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-vendor@freebsd.org
Subject:   svn commit: r316906 - in vendor-sys/illumos/dist/uts/common: fs fs/zfs sys
Message-ID:  <201704141819.v3EIJnoY066587@repo.freebsd.org>

Next in thread | Raw E-Mail | Index | Archive | Help
Author: avg
Date: Fri Apr 14 18:19:48 2017
New Revision: 316906
URL: https://svnweb.freebsd.org/changeset/base/316906

Log:
  4242 file rename event fires before the rename happens
  
  illumos/illumos-gate@54207fd2e1e7ed01d0416da8cf296dbef920fbfc
  https://github.com/illumos/illumos-gate/commit/54207fd2e1e7ed01d0416da8cf296dbef920fbfc
  
  https://www.illumos.org/issues/4242
    From Joyent's OS-2557:
    So we're basically just doing a check here that after we got a 'rename' event
    for our file, the file has actually been moved out of the way.
    What I've seen in bh1-stage2 is that this happens as you'd expect for all zones
    but many times over the last week it's failed because when we do the fs.exists
    () check here, the file that we got the rename event for, still exists.
    I've confirmed what's happening using the following dtrace script:
    #!/usr/sbin/dtrace -s
  
    #pragma D option quiet
    #pragma D option bufsize=256k
  
    syscall::open:entry,
    syscall::open64:entry
    /copyinstr(arg0) == "/var/svc/provisioning" || (strlen(copyinstr(arg0)) == 69
    && substr(copyinstr(arg0), 48) == "/var/svc/provisioning")/
    {
        this->watching_open = 1;
        printf("%d zone %s process %s(%d) [%s] open(%s)\\n",
            timestamp,
            zonename,
            execname,
            pid,
            curpsinfo->pr_psargs,
            copyinstr(arg0));
    }
  
    syscall::open:return,
    syscall::open64:return
    /this->watching_open == 1/
  
  Reviewed by: Robert Mustacchi <rm@joyent.com>
  Reviewed by: Marcel Telka <marcel@telka.sk>
  Approved by: Dan McDonald <danmcd@omniti.com>
  Author: Jerry Jelinek <jerry.jelinek@joyent.com>

Modified:
  vendor-sys/illumos/dist/uts/common/fs/vnode.c
  vendor-sys/illumos/dist/uts/common/fs/zfs/zfs_vnops.c
  vendor-sys/illumos/dist/uts/common/sys/vnode.h

Modified: vendor-sys/illumos/dist/uts/common/fs/vnode.c
==============================================================================
--- vendor-sys/illumos/dist/uts/common/fs/vnode.c	Fri Apr 14 18:15:47 2017	(r316905)
+++ vendor-sys/illumos/dist/uts/common/fs/vnode.c	Fri Apr 14 18:19:48 2017	(r316906)
@@ -2557,6 +2557,36 @@ vnevent_rmdir(vnode_t *vp, vnode_t *dvp,
 }
 
 void
+vnevent_pre_rename_src(vnode_t *vp, vnode_t *dvp, char *name,
+    caller_context_t *ct)
+{
+	if (vp == NULL || vp->v_femhead == NULL) {
+		return;
+	}
+	(void) VOP_VNEVENT(vp, VE_PRE_RENAME_SRC, dvp, name, ct);
+}
+
+void
+vnevent_pre_rename_dest(vnode_t *vp, vnode_t *dvp, char *name,
+    caller_context_t *ct)
+{
+	if (vp == NULL || vp->v_femhead == NULL) {
+		return;
+	}
+	(void) VOP_VNEVENT(vp, VE_PRE_RENAME_DEST, dvp, name, ct);
+}
+
+void
+vnevent_pre_rename_dest_dir(vnode_t *vp, vnode_t *nvp, char *name,
+    caller_context_t *ct)
+{
+	if (vp == NULL || vp->v_femhead == NULL) {
+		return;
+	}
+	(void) VOP_VNEVENT(vp, VE_PRE_RENAME_DEST_DIR, nvp, name, ct);
+}
+
+void
 vnevent_create(vnode_t *vp, caller_context_t *ct)
 {
 	if (vp == NULL || vp->v_femhead == NULL) {

Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/zfs_vnops.c
==============================================================================
--- vendor-sys/illumos/dist/uts/common/fs/zfs/zfs_vnops.c	Fri Apr 14 18:15:47 2017	(r316905)
+++ vendor-sys/illumos/dist/uts/common/fs/zfs/zfs_vnops.c	Fri Apr 14 18:19:48 2017	(r316906)
@@ -23,6 +23,7 @@
  * Copyright (c) 2012, 2015 by Delphix. All rights reserved.
  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
  * Copyright (c) 2014 Integros [integros.com]
+ * Copyright 2015 Joyent, Inc.
  */
 
 /* Portions Copyright 2007 Jeremy Teo */
@@ -3447,7 +3448,7 @@ zfs_rename(vnode_t *sdvp, char *snm, vno
 	dmu_tx_t	*tx;
 	zfs_zlock_t	*zl;
 	int		cmp, serr, terr;
-	int		error = 0;
+	int		error = 0, rm_err = 0;
 	int		zflg = 0;
 	boolean_t	waited = B_FALSE;
 
@@ -3659,16 +3660,16 @@ top:
 		}
 	}
 
-	vnevent_rename_src(ZTOV(szp), sdvp, snm, ct);
+	vnevent_pre_rename_src(ZTOV(szp), sdvp, snm, ct);
 	if (tzp)
-		vnevent_rename_dest(ZTOV(tzp), tdvp, tnm, ct);
+		vnevent_pre_rename_dest(ZTOV(tzp), tdvp, tnm, ct);
 
 	/*
 	 * notify the target directory if it is not the same
 	 * as source directory.
 	 */
 	if (tdvp != sdvp) {
-		vnevent_rename_dest_dir(tdvp, ct);
+		vnevent_pre_rename_dest_dir(tdvp, ZTOV(szp), tnm, ct);
 	}
 
 	tx = dmu_tx_create(zfsvfs->z_os);
@@ -3712,7 +3713,7 @@ top:
 	}
 
 	if (tzp)	/* Attempt to remove the existing target */
-		error = zfs_link_destroy(tdl, tzp, tx, zflg, NULL);
+		error = rm_err = zfs_link_destroy(tdl, tzp, tx, zflg, NULL);
 
 	if (error == 0) {
 		error = zfs_link_create(tdl, szp, tx, ZRENAMING);
@@ -3754,6 +3755,16 @@ top:
 	}
 
 	dmu_tx_commit(tx);
+
+	if (tzp && rm_err == 0)
+		vnevent_rename_dest(ZTOV(tzp), tdvp, tnm, ct);
+
+	if (error == 0) {
+		vnevent_rename_src(ZTOV(szp), sdvp, snm, ct);
+		/* notify the target dir if it is not the same as source dir */
+		if (tdvp != sdvp)
+			vnevent_rename_dest_dir(tdvp, ct);
+	}
 out:
 	if (zl != NULL)
 		zfs_rename_unlock(&zl);

Modified: vendor-sys/illumos/dist/uts/common/sys/vnode.h
==============================================================================
--- vendor-sys/illumos/dist/uts/common/sys/vnode.h	Fri Apr 14 18:15:47 2017	(r316905)
+++ vendor-sys/illumos/dist/uts/common/sys/vnode.h	Fri Apr 14 18:19:48 2017	(r316906)
@@ -724,7 +724,12 @@ typedef enum symfollow	symfollow_t;
 typedef enum vcexcl	vcexcl_t;
 typedef enum create	create_t;
 
-/* Vnode Events - Used by VOP_VNEVENT */
+/*
+ * Vnode Events - Used by VOP_VNEVENT
+ * The VE_PRE_RENAME_* events fire before the rename operation and are
+ * primarily used for specialized applications, such as NFSv4 delegation, which
+ * need to know about rename before it occurs.
+ */
 typedef enum vnevent	{
 	VE_SUPPORT	= 0,	/* Query */
 	VE_RENAME_SRC	= 1,	/* Rename, with vnode as source */
@@ -735,7 +740,10 @@ typedef enum vnevent	{
 	VE_LINK		= 6, 	/* Link with vnode's name as source */
 	VE_RENAME_DEST_DIR	= 7, 	/* Rename with vnode as target dir */
 	VE_MOUNTEDOVER	= 8, 	/* File or Filesystem got mounted over vnode */
-	VE_TRUNCATE = 9		/* Truncate */
+	VE_TRUNCATE = 9,	/* Truncate */
+	VE_PRE_RENAME_SRC = 10,	/* Pre-rename, with vnode as source */
+	VE_PRE_RENAME_DEST = 11, /* Pre-rename, with vnode as target/dest. */
+	VE_PRE_RENAME_DEST_DIR = 12 /* Pre-rename with vnode as target dir */
 } vnevent_t;
 
 /*
@@ -1294,6 +1302,12 @@ void	vnevent_rename_dest_dir(vnode_t *, 
 void	vnevent_mountedover(vnode_t *, caller_context_t *);
 void	vnevent_truncate(vnode_t *, caller_context_t *);
 int	vnevent_support(vnode_t *, caller_context_t *);
+void	vnevent_pre_rename_src(vnode_t *, vnode_t *, char *,
+	    caller_context_t *);
+void	vnevent_pre_rename_dest(vnode_t *, vnode_t *, char *,
+	    caller_context_t *);
+void	vnevent_pre_rename_dest_dir(vnode_t *, vnode_t *, char *,
+	    caller_context_t *);
 
 /* Vnode specific data */
 void vsd_create(uint_t *, void (*)(void *));



Want to link to this message? Use this URL: <http://docs.FreeBSD.org/cgi/mid.cgi?201704141819.v3EIJnoY066587>