4242 file rename event fires before the rename happens
illumos/illumos-gate@54207fd2e1
54207fd2e1
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>
This commit is contained in:
parent
9dfe195883
commit
be49e7b29b
@ -2556,6 +2556,36 @@ vnevent_rmdir(vnode_t *vp, vnode_t *dvp, char *name, caller_context_t *ct)
|
||||
(void) VOP_VNEVENT(vp, VE_RMDIR, dvp, name, ct);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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, vnode_t *tdvp, char *tnm, cred_t *cr,
|
||||
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 @@ zfs_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm, cred_t *cr,
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ zfs_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm, cred_t *cr,
|
||||
}
|
||||
|
||||
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 @@ zfs_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm, cred_t *cr,
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -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 *, caller_context_t *ct);
|
||||
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 *));
|
||||
|
Loading…
Reference in New Issue
Block a user