diff options
author | Bryan Cantrill <bryan@joyent.com> | 2013-06-19 01:14:17 +0000 |
---|---|---|
committer | Bryan Cantrill <bryan@joyent.com> | 2013-06-19 01:14:17 +0000 |
commit | 419a2474236e929c11570353e419e8882e2516ac (patch) | |
tree | 04f0283ae8a044b7429e4b49197b42c3ba558301 | |
parent | b378a448a6a0c61f7225dbf2a70cb153acea1b29 (diff) | |
download | illumos-joyent-419a2474236e929c11570353e419e8882e2516ac.tar.gz |
OS-2271 'tail -F ...' not resetting the offset of file rotation properly
-rw-r--r-- | usr/src/cmd/tail/tests/tailtests.sh | 79 | ||||
-rw-r--r-- | usr/src/uts/common/fs/portfs/port_fop.c | 17 |
2 files changed, 87 insertions, 9 deletions
diff --git a/usr/src/cmd/tail/tests/tailtests.sh b/usr/src/cmd/tail/tests/tailtests.sh index 1ce5f5df02..c0ae3afcc4 100644 --- a/usr/src/cmd/tail/tests/tailtests.sh +++ b/usr/src/cmd/tail/tests/tailtests.sh @@ -13,7 +13,7 @@ # # Copyright 2010 Chris Love. All rights reserved. -# Copyright (c) 2012, Joyent, Inc. All rights reserved. +# Copyright (c) 2013, Joyent, Inc. All rights reserved. # checktest() @@ -312,8 +312,14 @@ sleep 2 mv $follow $moved echo -e "x\ny\nz" >> $moved + +# +# At this point, tail is polling on stat'ing the missing file; we need to +# be sure to sleep long enough after recreating it to know that it will pick +# it up. +# echo -e "d\ne\nf" > $follow -sleep 1 +sleep 5 kill $child sleep 1 @@ -361,6 +367,75 @@ a=`cat $out` checktest "$a" "$o" 27 rm $follow $moved +if [[ `uname -s` == "SunOS" ]]; then + # + # Use DTrace to truncate the file between the return from port_get() + # and the reassociation of the file object with the port, exposing + # any race conditions whereby FILE_TRUNC events are lost. + # + cat /dev/null > $follow + dtrace -c "$PROG -f $follow" -s /dev/stdin > $out <<EOF + #pragma D option destructive + #pragma D option quiet + + pid\$target::port_get:return + /++i == 5/ + { + stop(); + system("cat /dev/null > $follow"); + system("prun %d", pid); + } + + tick-1sec + { + system("echo %d >> $follow", j++); + } + + tick-1sec + /j == 10/ + { + exit(0); + } +EOF + + o=`echo -e "0\n1\n2\n3\n5\n6\n7\n8\n9\n"` + a=`cat $out` + checktest "$a" "$o" 27a + rm $follow + + cat /dev/null > $follow + dtrace -c "$PROG -f $follow" -s /dev/stdin > $out <<EOF + #pragma D option destructive + #pragma D option quiet + + pid\$target::port_get:return + /++i == 5/ + { + stop(); + system("mv $follow $moved"); + system("cat /dev/null > $moved"); + system("prun %d", pid); + } + + tick-1sec + { + system("echo %d >> %s", j++, + i < 5 ? "$follow" : "$moved"); + } + + tick-1sec + /j == 10/ + { + exit(0); + } +EOF + + o=`echo -e "0\n1\n2\n3\n5\n6\n7\n8\n9\n"` + a=`cat $out` + checktest "$a" "$o" 27b + rm $moved +fi + echo "$CMD: completed" exit $errs diff --git a/usr/src/uts/common/fs/portfs/port_fop.c b/usr/src/uts/common/fs/portfs/port_fop.c index 48792394a5..1094dc160c 100644 --- a/usr/src/uts/common/fs/portfs/port_fop.c +++ b/usr/src/uts/common/fs/portfs/port_fop.c @@ -24,7 +24,7 @@ */ /* - * Copyright (c) 2012, Joyent, Inc. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ /* @@ -1259,7 +1259,7 @@ port_associate_fop(port_t *pp, int source, uintptr_t object, int events, void *user) { portfop_cache_t *pfcp; - vnode_t *vp, *dvp, *oldvp = NULL, *olddvp = NULL; + vnode_t *vp, *dvp, *oldvp = NULL, *olddvp = NULL, *orig; portfop_t *pfp; int error = 0; file_obj_t fobj; @@ -1316,8 +1316,7 @@ port_associate_fop(port_t *pp, int source, uintptr_t object, int events, goto errout; } - vp = port_resolve_vp(vp); - + vp = port_resolve_vp(orig = vp); if (vp != NULL && vnevent_support(vp, NULL)) { error = ENOTSUP; @@ -1325,10 +1324,14 @@ port_associate_fop(port_t *pp, int source, uintptr_t object, int events, } /* - * If dvp belongs to a different filesystem just ignore it. - * Hardlinks cannot exist across filesystems. + * If dvp belongs to a different filesystem just ignore it, as hard + * links cannot exist across filesystems. We make an exception for + * procfs, however, the magic of which we treat semantically as a hard + * link, allowing one to use /proc/[pid]/fd/[fd] for PORT_SOURCE_FILE + * and avoid spurious FILE_RENAME_FROM/FILE_RENAME_TO events. */ - if (dvp != NULL && dvp->v_vfsp != vp->v_vfsp) { + if (dvp != NULL && dvp->v_vfsp != vp->v_vfsp && + !(orig->v_type == VPROC && vp != NULL && vp->v_type != VPROC)) { VN_RELE(dvp); dvp = NULL; } |