NetBSD Problem Report #48958

From www@NetBSD.org  Tue Jul  1 20:04:51 2014
Return-Path: <www@NetBSD.org>
Received: from mail.netbsd.org (mail.netbsd.org [149.20.53.66])
	(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
	(Client CN "mail.netbsd.org", Issuer "Postmaster NetBSD.org" (verified OK))
	by mollari.NetBSD.org (Postfix) with ESMTPS id 32C36A653D
	for <gnats-bugs@gnats.NetBSD.org>; Tue,  1 Jul 2014 20:04:51 +0000 (UTC)
Message-Id: <20140701200450.3F7B5A6541@mollari.NetBSD.org>
Date: Tue,  1 Jul 2014 20:04:50 +0000 (UTC)
From: netbsd@eq.cz
Reply-To: netbsd@eq.cz
To: gnats-bugs@NetBSD.org
Subject: kevent(2): EVFILT_VNODE filter miscounting hardlinks
X-Send-Pr-Version: www-1.0

>Number:         48958
>Category:       kern
>Synopsis:       kevent(2): EVFILT_VNODE filter miscounting hardlinks
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          closed
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Jul 01 20:05:00 +0000 2014
>Closed-Date:    Wed Jun 01 04:33:22 +0000 2016
>Last-Modified:  Wed Jun 01 04:33:22 +0000 2016
>Originator:     rudolf
>Release:        6.1_STABLE updated at May 23 2014
>Organization:
>Environment:
NetBSD 6.1_STABLE amd64 
>Description:
If there is a EVFILT_VNODE filter watching a directory (e.g. "/tmp/watchdir"), it does not return NOTE_LINK (it only returns NOTE_WRITE) upon a move of a directory from or into the watched directory (e.g. "mkdir /tmp/foo; mv /tmp/foo /tmp/watchdir/").

The filter correctly returns NOTE_LINK (and NOTE_WRITE) upon a mkdir in the watched directory (e.g. "mkdir /tmp/watchdir/bar").

Observed using a test program from PR kern/34267.
>How-To-Repeat:

>Fix:

>Release-Note:

>Audit-Trail:
From: rudolf <netbsd@eq.cz>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: kern/48958: kevent(2): EVFILT_VNODE filter miscounting hardlinks
Date: Wed, 02 Jul 2014 14:09:58 +0200

 This is a multi-part message in MIME format.
 --------------000306090607060304090203
 Content-Type: text/plain; charset=ISO-8859-1; format=flowed
 Content-Transfer-Encoding: 7bit

 Attached is a test program with two test cases for PR kern/48958. It is 
 suitable for inclusion to the /usr/src/tests/kernel/kqueue directory. 
 Tested under NetBSD 6.1_STABLE amd64.

 r.


 --------------000306090607060304090203
 Content-Type: text/x-csrc;
  name="t_vnode1.c"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: attachment;
  filename="t_vnode1.c"

 #include <sys/event.h>
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <fcntl.h>
 #include <stdio.h>
 #include <unistd.h>

 #include <atf-c.h>

 static const char *dir_target = "dir";
 static const char *dir_inside = "dir/foo";
 static const char *dir_outside = "bar";

 int init_kqueue(int);
 int init_target(void);
 void cleanup(void);

 int
 init_target()
 {
 	if (mkdir(dir_target, S_IRWXU) < 0) {
 		return -1;
 	} else {
 		return open(dir_target, O_RDONLY, 0);
 	}
 }

 int
 init_kqueue(int target_fd)
 {
 	int kq, ke;
 	struct kevent eventlist[1];

 	kq = kqueue();
 	if (kq < 0) {
 		return -1;
 	}
 	EV_SET(&eventlist[0], target_fd, EVFILT_VNODE,
 		EV_ADD | EV_ONESHOT, NOTE_DELETE |
 		NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB |
 		NOTE_LINK | NOTE_RENAME | NOTE_REVOKE, 0, 0);
 	ke = kevent(kq, eventlist, 1, NULL, 0, NULL);
 	if (ke < 0) {
 		return -1;
 	}
 	return kq;
 }

 void
 cleanup(void)
 {
 	(void)unlink(dir_inside);
 	(void)unlink(dir_outside);
 	(void)unlink(dir_target);
 }


 ATF_TC_WITH_CLEANUP(dir_note_link_mv_dir_in);
 ATF_TC_HEAD(dir_note_link_mv_dir_in, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) returns NOTE_LINK for the directory "
 		"'foo' if a directory 'bar' is renamed to 'foo/bar'.");
 }
 ATF_TC_BODY(dir_note_link_mv_dir_in, tc)
 {
 	int kq, target;
 	struct kevent changelist[1];
 	struct timespec ts = {0, 0};

 	target = init_target();
 	ATF_REQUIRE(target != -1);
 	ATF_REQUIRE(mkdir(dir_outside, S_IRWXU) != -1);

 	kq = init_kqueue(target);
 	ATF_REQUIRE(kq != -1);

 	ATF_REQUIRE(rename(dir_outside, dir_inside) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_REQUIRE(changelist[0].fflags & NOTE_LINK);
 }
 ATF_TC_CLEANUP(dir_note_link_mv_dir_in, tc)
 {
 	cleanup();
 }

 ATF_TC_WITH_CLEANUP(dir_note_link_mv_dir_out);
 ATF_TC_HEAD(dir_note_link_mv_dir_out, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) returns NOTE_LINK for the directory "
 		"'foo' if a directory 'foo/bar' is renamed to 'bar'.");
 }
 ATF_TC_BODY(dir_note_link_mv_dir_out, tc)
 {
 	int kq, target;
 	struct kevent changelist[1];
 	struct timespec ts = {0, 0};

 	target = init_target();
 	ATF_REQUIRE(target != -1);
 	ATF_REQUIRE(mkdir(dir_inside, S_IRWXU) != -1);

 	kq = init_kqueue(target);
 	ATF_REQUIRE(kq != -1);

 	ATF_REQUIRE(rename(dir_inside, dir_outside) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_REQUIRE(changelist[0].fflags & NOTE_LINK);
 }
 ATF_TC_CLEANUP(dir_note_link_mv_dir_out, tc)
 {
 	cleanup();
 }

 ATF_TP_ADD_TCS(tp)
 {
 	ATF_TP_ADD_TC(tp, dir_note_link_mv_dir_in);
 	ATF_TP_ADD_TC(tp, dir_note_link_mv_dir_out);
 	return atf_no_error();
 }

 --------------000306090607060304090203--

From: rudolf <netbsd@eq.cz>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: kern/48958: kevent(2): EVFILT_VNODE filter miscounting hardlinks
Date: Thu, 03 Jul 2014 00:14:16 +0200

 This is a multi-part message in MIME format.
 --------------090009000106070409060508
 Content-Type: text/plain; charset=ISO-8859-1; format=flowed
 Content-Transfer-Encoding: 7bit

 Here is an improved version of the ATF test program. Now it contains 14 
 test cases with two of them failing currently under NetBSD 6.1_STABLE amd64.

 r.


 --------------090009000106070409060508
 Content-Type: text/x-csrc;
  name="t_vnode1.c"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: attachment;
  filename="t_vnode1.c"

 #include <sys/event.h>
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <fcntl.h>
 #include <stdio.h>
 #include <unistd.h>

 #include <atf-c.h>

 /*
  * Test cases for events triggered by manipulating a target directory
  * content.  Using EVFILT_VNODE filter on the target directory descriptor.
  *
  */

 static const char *dir_target = "foo";
 static const char *dir_inside = "foo/bar";
 static const char *dir_outside = "bar";
 static const char *file_inside = "foo/baz";
 static const char *file_outside = "qux";
 static const struct timespec ts = {0, 0};
 static int kq = -1;
 static int target = -1;

 int init_target(void);
 int init_kqueue(void);
 int create_file(const char *);
 void cleanup(void);

 int
 init_target()
 {
 	if (mkdir(dir_target, S_IRWXU) < 0) {
 		return -1;
 	}
 	target = open(dir_target, O_RDONLY, 0);
 	return target;
 }

 int
 init_kqueue()
 {
 	struct kevent eventlist[1];

 	kq = kqueue();
 	if (kq < 0) {
 		return -1;
 	}
 	EV_SET(&eventlist[0], target, EVFILT_VNODE,
 		EV_ADD | EV_ONESHOT, NOTE_DELETE |
 		NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB |
 		NOTE_LINK | NOTE_RENAME | NOTE_REVOKE, 0, 0);
 	return kevent(kq, eventlist, 1, NULL, 0, NULL);
 }

 int
 create_file(const char *file)
 {
 	int fd;

 	fd = open(file, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
 	if (fd < 0) {
 		return -1;
 	}
 	return close(fd);
 }

 void
 cleanup(void)
 {
 	(void)unlink(file_inside);
 	(void)unlink(file_outside);
 	(void)rmdir(dir_inside);
 	(void)rmdir(dir_outside);
 	(void)rmdir(dir_target);
 	(void)close(kq);
 	(void)close(target);
 }

 ATF_TC_WITH_CLEANUP(dir_no_note_link_create_file_in);
 ATF_TC_HEAD(dir_no_note_link_create_file_in, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) does not return NOTE_LINK for the directory "
 		"'foo' if a file 'foo/baz' is created.");
 }
 ATF_TC_BODY(dir_no_note_link_create_file_in, tc)
 {
 	struct kevent changelist[1];

 	ATF_REQUIRE(init_target() != -1);
 	ATF_REQUIRE(init_kqueue() != -1);

 	ATF_REQUIRE(create_file(file_inside) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, 0);
 }
 ATF_TC_CLEANUP(dir_no_note_link_create_file_in, tc)
 {
 	cleanup();
 }

 ATF_TC_WITH_CLEANUP(dir_no_note_link_delete_file_in);
 ATF_TC_HEAD(dir_no_note_link_delete_file_in, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) does not return NOTE_LINK for the directory "
 		"'foo' if a file 'foo/baz' is deleted.");
 }
 ATF_TC_BODY(dir_no_note_link_delete_file_in, tc)
 {
 	struct kevent changelist[1];

 	ATF_REQUIRE(init_target() != -1);
 	ATF_REQUIRE(create_file(file_inside) != -1);
 	ATF_REQUIRE(init_kqueue() != -1);

 	ATF_REQUIRE(unlink(file_inside) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, 0);
 }
 ATF_TC_CLEANUP(dir_no_note_link_delete_file_in, tc)
 {
 	cleanup();
 }

 ATF_TC_WITH_CLEANUP(dir_note_link_create_dir_in);
 ATF_TC_HEAD(dir_note_link_create_dir_in, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) returns NOTE_LINK for the directory "
 		"'foo' if a directory 'foo/bar' is created.");
 }
 ATF_TC_BODY(dir_note_link_create_dir_in, tc)
 {
 	struct kevent changelist[1];

 	ATF_REQUIRE(init_target() != -1);
 	ATF_REQUIRE(init_kqueue() != -1);

 	ATF_REQUIRE(mkdir(dir_inside, S_IRWXU) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, NOTE_LINK);
 }
 ATF_TC_CLEANUP(dir_note_link_create_dir_in, tc)
 {
 	cleanup();
 }

 ATF_TC_WITH_CLEANUP(dir_note_link_delete_dir_in);
 ATF_TC_HEAD(dir_note_link_delete_dir_in, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) returns NOTE_LINK for the directory "
 		"'foo' if a directory 'foo/bar' is deleted.");
 }
 ATF_TC_BODY(dir_note_link_delete_dir_in, tc)
 {
 	struct kevent changelist[1];

 	ATF_REQUIRE(init_target() != -1);
 	ATF_REQUIRE(mkdir(dir_inside, S_IRWXU) != -1);
 	ATF_REQUIRE(init_kqueue() != -1);

 	ATF_REQUIRE(rmdir(dir_inside) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, NOTE_LINK);
 }
 ATF_TC_CLEANUP(dir_note_link_delete_dir_in, tc)
 {
 	cleanup();
 }

 ATF_TC_WITH_CLEANUP(dir_note_link_mv_dir_in);
 ATF_TC_HEAD(dir_note_link_mv_dir_in, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) returns NOTE_LINK for the directory "
 		"'foo' if a directory 'bar' is renamed to 'foo/bar'.");
 }
 ATF_TC_BODY(dir_note_link_mv_dir_in, tc)
 {
 	struct kevent changelist[1];

 	ATF_REQUIRE(init_target() != -1);
 	ATF_REQUIRE(mkdir(dir_outside, S_IRWXU) != -1);
 	ATF_REQUIRE(init_kqueue() != -1);

 	ATF_REQUIRE(rename(dir_outside, dir_inside) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, NOTE_LINK);
 }
 ATF_TC_CLEANUP(dir_note_link_mv_dir_in, tc)
 {
 	cleanup();
 }

 ATF_TC_WITH_CLEANUP(dir_note_link_mv_dir_out);
 ATF_TC_HEAD(dir_note_link_mv_dir_out, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) returns NOTE_LINK for the directory "
 		"'foo' if a directory 'foo/bar' is renamed to 'bar'.");
 }
 ATF_TC_BODY(dir_note_link_mv_dir_out, tc)
 {
 	struct kevent changelist[1];

 	ATF_REQUIRE(init_target() != -1);
 	ATF_REQUIRE(mkdir(dir_inside, S_IRWXU) != -1);
 	ATF_REQUIRE(init_kqueue() != -1);

 	ATF_REQUIRE(rename(dir_inside, dir_outside) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, NOTE_LINK);
 }
 ATF_TC_CLEANUP(dir_note_link_mv_dir_out, tc)
 {
 	cleanup();
 }

 ATF_TC_WITH_CLEANUP(dir_note_write_create_dir_in);
 ATF_TC_HEAD(dir_note_write_create_dir_in, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) returns NOTE_WRITE for the directory "
 		"'foo' if a directory 'foo/bar' is created.");
 }
 ATF_TC_BODY(dir_note_write_create_dir_in, tc)
 {
 	struct kevent changelist[1];

 	ATF_REQUIRE(init_target() != -1);
 	ATF_REQUIRE(init_kqueue() != -1);

 	ATF_REQUIRE(mkdir(dir_inside, S_IRWXU) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
 }
 ATF_TC_CLEANUP(dir_note_write_create_dir_in, tc)
 {
 	cleanup();
 }

 ATF_TC_WITH_CLEANUP(dir_note_write_create_file_in);
 ATF_TC_HEAD(dir_note_write_create_file_in, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) returns NOTE_WRITE for the directory "
 		"'foo' if a file 'foo/baz' is created.");
 }
 ATF_TC_BODY(dir_note_write_create_file_in, tc)
 {
 	struct kevent changelist[1];

 	ATF_REQUIRE(init_target() != -1);
 	ATF_REQUIRE(init_kqueue() != -1);

 	ATF_REQUIRE(create_file(file_inside) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
 }
 ATF_TC_CLEANUP(dir_note_write_create_file_in, tc)
 {
 	cleanup();
 }

 ATF_TC_WITH_CLEANUP(dir_note_write_delete_dir_in);
 ATF_TC_HEAD(dir_note_write_delete_dir_in, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) returns NOTE_WRITE for the directory "
 		"'foo' if a directory 'foo/bar' is deleted.");
 }
 ATF_TC_BODY(dir_note_write_delete_dir_in, tc)
 {
 	struct kevent changelist[1];

 	ATF_REQUIRE(init_target() != -1);
 	ATF_REQUIRE(mkdir(dir_inside, S_IRWXU) != -1);
 	ATF_REQUIRE(init_kqueue() != -1);

 	ATF_REQUIRE(rmdir(dir_inside) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
 }
 ATF_TC_CLEANUP(dir_note_write_delete_dir_in, tc)
 {
 	cleanup();
 }

 ATF_TC_WITH_CLEANUP(dir_note_write_delete_file_in);
 ATF_TC_HEAD(dir_note_write_delete_file_in, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) returns NOTE_WRITE for the directory "
 		"'foo' if a file 'foo/baz' is deleted.");
 }
 ATF_TC_BODY(dir_note_write_delete_file_in, tc)
 {
 	struct kevent changelist[1];

 	ATF_REQUIRE(init_target() != -1);
 	ATF_REQUIRE(create_file(file_inside) != -1);
 	ATF_REQUIRE(init_kqueue() != -1);

 	ATF_REQUIRE(unlink(file_inside) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
 }
 ATF_TC_CLEANUP(dir_note_write_delete_file_in, tc)
 {
 	cleanup();
 }

 ATF_TC_WITH_CLEANUP(dir_note_write_mv_dir_in);
 ATF_TC_HEAD(dir_note_write_mv_dir_in, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) returns NOTE_WRITE for the directory "
 		"'foo' if a directory 'bar' is renamed to 'foo/bar'.");
 }
 ATF_TC_BODY(dir_note_write_mv_dir_in, tc)
 {
 	struct kevent changelist[1];

 	ATF_REQUIRE(init_target() != -1);
 	ATF_REQUIRE(mkdir(dir_outside, S_IRWXU) != -1);
 	ATF_REQUIRE(init_kqueue() != -1);

 	ATF_REQUIRE(rename(dir_outside, dir_inside) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
 }
 ATF_TC_CLEANUP(dir_note_write_mv_dir_in, tc)
 {
 	cleanup();
 }

 ATF_TC_WITH_CLEANUP(dir_note_write_mv_dir_out);
 ATF_TC_HEAD(dir_note_write_mv_dir_out, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) returns NOTE_WRITE for the directory "
 		"'foo' if a directory 'foo/bar' is renamed to 'foo'.");
 }
 ATF_TC_BODY(dir_note_write_mv_dir_out, tc)
 {
 	struct kevent changelist[1];

 	ATF_REQUIRE(init_target() != -1);
 	ATF_REQUIRE(mkdir(dir_inside, S_IRWXU) != -1);
 	ATF_REQUIRE(init_kqueue() != -1);

 	ATF_REQUIRE(rename(dir_inside, dir_outside) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
 }
 ATF_TC_CLEANUP(dir_note_write_mv_dir_out, tc)
 {
 	cleanup();
 }

 ATF_TC_WITH_CLEANUP(dir_note_write_mv_file_in);
 ATF_TC_HEAD(dir_note_write_mv_file_in, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) returns NOTE_WRITE for the directory "
 		"'foo' if a file 'qux' is renamed to 'foo/baz'.");
 }
 ATF_TC_BODY(dir_note_write_mv_file_in, tc)
 {
 	struct kevent changelist[1];

 	ATF_REQUIRE(init_target() != -1);
 	ATF_REQUIRE(create_file(file_outside) != -1);
 	ATF_REQUIRE(init_kqueue() != -1);

 	ATF_REQUIRE(rename(file_outside, file_inside) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
 }
 ATF_TC_CLEANUP(dir_note_write_mv_file_in, tc)
 {
 	cleanup();
 }

 ATF_TC_WITH_CLEANUP(dir_note_write_mv_file_out);
 ATF_TC_HEAD(dir_note_write_mv_file_out, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) returns NOTE_WRITE for the directory "
 		"'foo' if a file 'foo/baz' is renamed to 'qux'.");
 }
 ATF_TC_BODY(dir_note_write_mv_file_out, tc)
 {
 	struct kevent changelist[1];

 	ATF_REQUIRE(init_target() != -1);
 	ATF_REQUIRE(create_file(file_inside) != -1);
 	ATF_REQUIRE(init_kqueue() != -1);

 	ATF_REQUIRE(rename(file_inside, file_outside) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
 }
 ATF_TC_CLEANUP(dir_note_write_mv_file_out, tc)
 {
 	cleanup();
 }

 ATF_TP_ADD_TCS(tp)
 {
 	ATF_TP_ADD_TC(tp, dir_no_note_link_create_file_in);
 	ATF_TP_ADD_TC(tp, dir_no_note_link_delete_file_in);
 	ATF_TP_ADD_TC(tp, dir_note_link_create_dir_in);
 	ATF_TP_ADD_TC(tp, dir_note_link_delete_dir_in);
 	ATF_TP_ADD_TC(tp, dir_note_link_mv_dir_in);
 	ATF_TP_ADD_TC(tp, dir_note_link_mv_dir_out);
 	ATF_TP_ADD_TC(tp, dir_note_write_create_dir_in);
 	ATF_TP_ADD_TC(tp, dir_note_write_create_file_in);
 	ATF_TP_ADD_TC(tp, dir_note_write_delete_dir_in);
 	ATF_TP_ADD_TC(tp, dir_note_write_delete_file_in);
 	ATF_TP_ADD_TC(tp, dir_note_write_mv_dir_in);
 	ATF_TP_ADD_TC(tp, dir_note_write_mv_dir_out);
 	ATF_TP_ADD_TC(tp, dir_note_write_mv_file_in);
 	ATF_TP_ADD_TC(tp, dir_note_write_mv_file_out);
 	return atf_no_error();
 }

 --------------090009000106070409060508--

From: rudolf <netbsd@eq.cz>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: kern/48958: kevent(2): EVFILT_VNODE filter miscounting hardlinks
Date: Thu, 03 Jul 2014 09:53:54 +0200

 This is a multi-part message in MIME format.
 --------------010001000906050803000106
 Content-Type: text/plain; charset=ISO-8859-1; format=flowed
 Content-Transfer-Encoding: 7bit

 Attached is a fix for 6.1_STABLE and a final version of the ATF test 
 program with 18 test cases. Without the fix, two of them fail under 
 6.1_STABLE.

 r.


 --------------010001000906050803000106
 Content-Type: text/x-patch;
  name="ufs_vnops.c.diff"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: attachment;
  filename="ufs_vnops.c.diff"

 --- sys/ufs/ufs/ufs_vnops.c.orig	2014-07-03 09:48:25.000000000 +0200
 +++ sys/ufs/ufs/ufs_vnops.c	2014-07-03 09:48:09.000000000 +0200
 @@ -1592,7 +1592,6 @@
  		doingdirectory = 1;
  	}
  	oldparent = fdp->i_number;
 -	VN_KNOTE(fdvp, NOTE_WRITE);		/* XXXLUKEM/XXX: right place? */

  	/*
  	 * Both the directory
 @@ -1696,7 +1695,13 @@
  			}
  			goto bad;
  		}
 -		VN_KNOTE(tdvp, NOTE_WRITE);
 +        	if (doingdirectory && newparent) {
 +                	VN_KNOTE(fdvp, NOTE_WRITE | NOTE_LINK);
 +                	VN_KNOTE(tdvp, NOTE_WRITE | NOTE_LINK);
 +                } else {
 +                	VN_KNOTE(fdvp, NOTE_WRITE);
 +        		VN_KNOTE(tdvp, NOTE_WRITE);
 +                }
  	} else {
  		if (txp->i_dev != tdp->i_dev || txp->i_dev != ip->i_dev)
  			panic("rename: EXDEV");

 --------------010001000906050803000106
 Content-Type: text/x-csrc;
  name="t_vnode1.c"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: attachment;
  filename="t_vnode1.c"

 #include <sys/event.h>
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <fcntl.h>
 #include <stdio.h>
 #include <unistd.h>

 #include <atf-c.h>

 /*
  * Test cases for events triggered by manipulating a target directory
  * content.  Using EVFILT_VNODE filter on the target directory descriptor.
  *
  */

 static const char *dir_target = "foo";
 static const char *dir_inside1 = "foo/bar1";
 static const char *dir_inside2 = "foo/bar2";
 static const char *dir_outside = "bar";
 static const char *file_inside1 = "foo/baz1";
 static const char *file_inside2 = "foo/baz2";
 static const char *file_outside = "qux";
 static const struct timespec ts = {0, 0};
 static int kq = -1;
 static int target = -1;

 int init_target(void);
 int init_kqueue(void);
 int create_file(const char *);
 void cleanup(void);

 int
 init_target()
 {
 	if (mkdir(dir_target, S_IRWXU) < 0) {
 		return -1;
 	}
 	target = open(dir_target, O_RDONLY, 0);
 	return target;
 }

 int
 init_kqueue()
 {
 	struct kevent eventlist[1];

 	kq = kqueue();
 	if (kq < 0) {
 		return -1;
 	}
 	EV_SET(&eventlist[0], target, EVFILT_VNODE,
 		EV_ADD | EV_ONESHOT, NOTE_DELETE |
 		NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB |
 		NOTE_LINK | NOTE_RENAME | NOTE_REVOKE, 0, 0);
 	return kevent(kq, eventlist, 1, NULL, 0, NULL);
 }

 int
 create_file(const char *file)
 {
 	int fd;

 	fd = open(file, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
 	if (fd < 0) {
 		return -1;
 	}
 	return close(fd);
 }

 void
 cleanup(void)
 {
 	(void)unlink(file_inside1);
 	(void)unlink(file_inside2);
 	(void)unlink(file_outside);
 	(void)rmdir(dir_inside1);
 	(void)rmdir(dir_inside2);
 	(void)rmdir(dir_outside);
 	(void)rmdir(dir_target);
 	(void)close(kq);
 	(void)close(target);
 }

 ATF_TC_WITH_CLEANUP(dir_no_note_link_create_file_in);
 ATF_TC_HEAD(dir_no_note_link_create_file_in, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) does not return NOTE_LINK for the directory "
 		"'foo' if a file 'foo/baz' is created.");
 }
 ATF_TC_BODY(dir_no_note_link_create_file_in, tc)
 {
 	struct kevent changelist[1];

 	ATF_REQUIRE(init_target() != -1);
 	ATF_REQUIRE(init_kqueue() != -1);

 	ATF_REQUIRE(create_file(file_inside1) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, 0);
 }
 ATF_TC_CLEANUP(dir_no_note_link_create_file_in, tc)
 {
 	cleanup();
 }

 ATF_TC_WITH_CLEANUP(dir_no_note_link_delete_file_in);
 ATF_TC_HEAD(dir_no_note_link_delete_file_in, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) does not return NOTE_LINK for the directory "
 		"'foo' if a file 'foo/baz' is deleted.");
 }
 ATF_TC_BODY(dir_no_note_link_delete_file_in, tc)
 {
 	struct kevent changelist[1];

 	ATF_REQUIRE(init_target() != -1);
 	ATF_REQUIRE(create_file(file_inside1) != -1);
 	ATF_REQUIRE(init_kqueue() != -1);

 	ATF_REQUIRE(unlink(file_inside1) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, 0);
 }
 ATF_TC_CLEANUP(dir_no_note_link_delete_file_in, tc)
 {
 	cleanup();
 }

 ATF_TC_WITH_CLEANUP(dir_no_note_link_mv_dir_within);
 ATF_TC_HEAD(dir_no_note_link_mv_dir_within, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) does not return NOTE_LINK for the directory "
 		"'foo' if a directory 'foo/bar' is renamed to 'foo/baz'.");
 }
 ATF_TC_BODY(dir_no_note_link_mv_dir_within, tc)
 {
 	struct kevent changelist[1];

 	ATF_REQUIRE(init_target() != -1);
 	ATF_REQUIRE(mkdir(dir_inside1, S_IRWXU) != -1);
 	ATF_REQUIRE(init_kqueue() != -1);

 	ATF_REQUIRE(rename(dir_inside1, dir_inside2) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, 0);
 }
 ATF_TC_CLEANUP(dir_no_note_link_mv_dir_within, tc)
 {
 	cleanup();
 }

 ATF_TC_WITH_CLEANUP(dir_no_note_link_mv_file_within);
 ATF_TC_HEAD(dir_no_note_link_mv_file_within, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) does not returns NOTE_LINK for the directory "
 		"'foo' if a file 'foo/baz' is renamed to 'foo/qux'.");
 }
 ATF_TC_BODY(dir_no_note_link_mv_file_within, tc)
 {
 	struct kevent changelist[1];

 	ATF_REQUIRE(init_target() != -1);
 	ATF_REQUIRE(create_file(file_inside1) != -1);
 	ATF_REQUIRE(init_kqueue() != -1);

 	ATF_REQUIRE(rename(file_inside1, file_inside2) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, 0);
 }
 ATF_TC_CLEANUP(dir_no_note_link_mv_file_within, tc)
 {
 	cleanup();
 }

 ATF_TC_WITH_CLEANUP(dir_note_link_create_dir_in);
 ATF_TC_HEAD(dir_note_link_create_dir_in, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) returns NOTE_LINK for the directory "
 		"'foo' if a directory 'foo/bar' is created.");
 }
 ATF_TC_BODY(dir_note_link_create_dir_in, tc)
 {
 	struct kevent changelist[1];

 	ATF_REQUIRE(init_target() != -1);
 	ATF_REQUIRE(init_kqueue() != -1);

 	ATF_REQUIRE(mkdir(dir_inside1, S_IRWXU) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, NOTE_LINK);
 }
 ATF_TC_CLEANUP(dir_note_link_create_dir_in, tc)
 {
 	cleanup();
 }

 ATF_TC_WITH_CLEANUP(dir_note_link_delete_dir_in);
 ATF_TC_HEAD(dir_note_link_delete_dir_in, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) returns NOTE_LINK for the directory "
 		"'foo' if a directory 'foo/bar' is deleted.");
 }
 ATF_TC_BODY(dir_note_link_delete_dir_in, tc)
 {
 	struct kevent changelist[1];

 	ATF_REQUIRE(init_target() != -1);
 	ATF_REQUIRE(mkdir(dir_inside1, S_IRWXU) != -1);
 	ATF_REQUIRE(init_kqueue() != -1);

 	ATF_REQUIRE(rmdir(dir_inside1) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, NOTE_LINK);
 }
 ATF_TC_CLEANUP(dir_note_link_delete_dir_in, tc)
 {
 	cleanup();
 }

 ATF_TC_WITH_CLEANUP(dir_note_link_mv_dir_in);
 ATF_TC_HEAD(dir_note_link_mv_dir_in, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) returns NOTE_LINK for the directory "
 		"'foo' if a directory 'bar' is renamed to 'foo/bar'.");
 }
 ATF_TC_BODY(dir_note_link_mv_dir_in, tc)
 {
 	struct kevent changelist[1];

 	ATF_REQUIRE(init_target() != -1);
 	ATF_REQUIRE(mkdir(dir_outside, S_IRWXU) != -1);
 	ATF_REQUIRE(init_kqueue() != -1);

 	ATF_REQUIRE(rename(dir_outside, dir_inside1) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, NOTE_LINK);
 }
 ATF_TC_CLEANUP(dir_note_link_mv_dir_in, tc)
 {
 	cleanup();
 }

 ATF_TC_WITH_CLEANUP(dir_note_link_mv_dir_out);
 ATF_TC_HEAD(dir_note_link_mv_dir_out, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) returns NOTE_LINK for the directory "
 		"'foo' if a directory 'foo/bar' is renamed to 'bar'.");
 }
 ATF_TC_BODY(dir_note_link_mv_dir_out, tc)
 {
 	struct kevent changelist[1];

 	ATF_REQUIRE(init_target() != -1);
 	ATF_REQUIRE(mkdir(dir_inside1, S_IRWXU) != -1);
 	ATF_REQUIRE(init_kqueue() != -1);

 	ATF_REQUIRE(rename(dir_inside1, dir_outside) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, NOTE_LINK);
 }
 ATF_TC_CLEANUP(dir_note_link_mv_dir_out, tc)
 {
 	cleanup();
 }

 ATF_TC_WITH_CLEANUP(dir_note_write_create_dir_in);
 ATF_TC_HEAD(dir_note_write_create_dir_in, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) returns NOTE_WRITE for the directory "
 		"'foo' if a directory 'foo/bar' is created.");
 }
 ATF_TC_BODY(dir_note_write_create_dir_in, tc)
 {
 	struct kevent changelist[1];

 	ATF_REQUIRE(init_target() != -1);
 	ATF_REQUIRE(init_kqueue() != -1);

 	ATF_REQUIRE(mkdir(dir_inside1, S_IRWXU) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
 }
 ATF_TC_CLEANUP(dir_note_write_create_dir_in, tc)
 {
 	cleanup();
 }

 ATF_TC_WITH_CLEANUP(dir_note_write_create_file_in);
 ATF_TC_HEAD(dir_note_write_create_file_in, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) returns NOTE_WRITE for the directory "
 		"'foo' if a file 'foo/baz' is created.");
 }
 ATF_TC_BODY(dir_note_write_create_file_in, tc)
 {
 	struct kevent changelist[1];

 	ATF_REQUIRE(init_target() != -1);
 	ATF_REQUIRE(init_kqueue() != -1);

 	ATF_REQUIRE(create_file(file_inside1) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
 }
 ATF_TC_CLEANUP(dir_note_write_create_file_in, tc)
 {
 	cleanup();
 }

 ATF_TC_WITH_CLEANUP(dir_note_write_delete_dir_in);
 ATF_TC_HEAD(dir_note_write_delete_dir_in, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) returns NOTE_WRITE for the directory "
 		"'foo' if a directory 'foo/bar' is deleted.");
 }
 ATF_TC_BODY(dir_note_write_delete_dir_in, tc)
 {
 	struct kevent changelist[1];

 	ATF_REQUIRE(init_target() != -1);
 	ATF_REQUIRE(mkdir(dir_inside1, S_IRWXU) != -1);
 	ATF_REQUIRE(init_kqueue() != -1);

 	ATF_REQUIRE(rmdir(dir_inside1) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
 }
 ATF_TC_CLEANUP(dir_note_write_delete_dir_in, tc)
 {
 	cleanup();
 }

 ATF_TC_WITH_CLEANUP(dir_note_write_delete_file_in);
 ATF_TC_HEAD(dir_note_write_delete_file_in, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) returns NOTE_WRITE for the directory "
 		"'foo' if a file 'foo/baz' is deleted.");
 }
 ATF_TC_BODY(dir_note_write_delete_file_in, tc)
 {
 	struct kevent changelist[1];

 	ATF_REQUIRE(init_target() != -1);
 	ATF_REQUIRE(create_file(file_inside1) != -1);
 	ATF_REQUIRE(init_kqueue() != -1);

 	ATF_REQUIRE(unlink(file_inside1) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
 }
 ATF_TC_CLEANUP(dir_note_write_delete_file_in, tc)
 {
 	cleanup();
 }

 ATF_TC_WITH_CLEANUP(dir_note_write_mv_dir_in);
 ATF_TC_HEAD(dir_note_write_mv_dir_in, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) returns NOTE_WRITE for the directory "
 		"'foo' if a directory 'bar' is renamed to 'foo/bar'.");
 }
 ATF_TC_BODY(dir_note_write_mv_dir_in, tc)
 {
 	struct kevent changelist[1];

 	ATF_REQUIRE(init_target() != -1);
 	ATF_REQUIRE(mkdir(dir_outside, S_IRWXU) != -1);
 	ATF_REQUIRE(init_kqueue() != -1);

 	ATF_REQUIRE(rename(dir_outside, dir_inside1) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
 }
 ATF_TC_CLEANUP(dir_note_write_mv_dir_in, tc)
 {
 	cleanup();
 }

 ATF_TC_WITH_CLEANUP(dir_note_write_mv_dir_out);
 ATF_TC_HEAD(dir_note_write_mv_dir_out, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) returns NOTE_WRITE for the directory "
 		"'foo' if a directory 'foo/bar' is renamed to 'foo'.");
 }
 ATF_TC_BODY(dir_note_write_mv_dir_out, tc)
 {
 	struct kevent changelist[1];

 	ATF_REQUIRE(init_target() != -1);
 	ATF_REQUIRE(mkdir(dir_inside1, S_IRWXU) != -1);
 	ATF_REQUIRE(init_kqueue() != -1);

 	ATF_REQUIRE(rename(dir_inside1, dir_outside) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
 }
 ATF_TC_CLEANUP(dir_note_write_mv_dir_out, tc)
 {
 	cleanup();
 }

 ATF_TC_WITH_CLEANUP(dir_note_write_mv_dir_within);
 ATF_TC_HEAD(dir_note_write_mv_dir_within, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) returns NOTE_WRITE for the directory "
 		"'foo' if a directory 'foo/bar' is renamed to 'foo/baz'.");
 }
 ATF_TC_BODY(dir_note_write_mv_dir_within, tc)
 {
 	struct kevent changelist[1];

 	ATF_REQUIRE(init_target() != -1);
 	ATF_REQUIRE(mkdir(dir_inside1, S_IRWXU) != -1);
 	ATF_REQUIRE(init_kqueue() != -1);

 	ATF_REQUIRE(rename(dir_inside1, dir_inside2) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
 }
 ATF_TC_CLEANUP(dir_note_write_mv_dir_within, tc)
 {
 	cleanup();
 }

 ATF_TC_WITH_CLEANUP(dir_note_write_mv_file_in);
 ATF_TC_HEAD(dir_note_write_mv_file_in, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) returns NOTE_WRITE for the directory "
 		"'foo' if a file 'qux' is renamed to 'foo/baz'.");
 }
 ATF_TC_BODY(dir_note_write_mv_file_in, tc)
 {
 	struct kevent changelist[1];

 	ATF_REQUIRE(init_target() != -1);
 	ATF_REQUIRE(create_file(file_outside) != -1);
 	ATF_REQUIRE(init_kqueue() != -1);

 	ATF_REQUIRE(rename(file_outside, file_inside1) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
 }
 ATF_TC_CLEANUP(dir_note_write_mv_file_in, tc)
 {
 	cleanup();
 }

 ATF_TC_WITH_CLEANUP(dir_note_write_mv_file_out);
 ATF_TC_HEAD(dir_note_write_mv_file_out, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) returns NOTE_WRITE for the directory "
 		"'foo' if a file 'foo/baz' is renamed to 'qux'.");
 }
 ATF_TC_BODY(dir_note_write_mv_file_out, tc)
 {
 	struct kevent changelist[1];

 	ATF_REQUIRE(init_target() != -1);
 	ATF_REQUIRE(create_file(file_inside1) != -1);
 	ATF_REQUIRE(init_kqueue() != -1);

 	ATF_REQUIRE(rename(file_inside1, file_outside) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
 }
 ATF_TC_CLEANUP(dir_note_write_mv_file_out, tc)
 {
 	cleanup();
 }

 ATF_TC_WITH_CLEANUP(dir_note_write_mv_file_within);
 ATF_TC_HEAD(dir_note_write_mv_file_within, tc)
 {
 	atf_tc_set_md_var(tc, "descr", "This test case ensures "
 		"that kevent(2) returns NOTE_WRITE for the directory "
 		"'foo' if a file 'foo/baz' is renamed to 'foo/qux'.");
 }
 ATF_TC_BODY(dir_note_write_mv_file_within, tc)
 {
 	struct kevent changelist[1];

 	ATF_REQUIRE(init_target() != -1);
 	ATF_REQUIRE(create_file(file_inside1) != -1);
 	ATF_REQUIRE(init_kqueue() != -1);

 	ATF_REQUIRE(rename(file_inside1, file_inside2) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
 	ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
 }
 ATF_TC_CLEANUP(dir_note_write_mv_file_within, tc)
 {
 	cleanup();
 }

 ATF_TP_ADD_TCS(tp)
 {
 	ATF_TP_ADD_TC(tp, dir_no_note_link_create_file_in);
 	ATF_TP_ADD_TC(tp, dir_no_note_link_delete_file_in);
 	ATF_TP_ADD_TC(tp, dir_no_note_link_mv_dir_within);
 	ATF_TP_ADD_TC(tp, dir_no_note_link_mv_file_within);
 	ATF_TP_ADD_TC(tp, dir_note_link_create_dir_in);
 	ATF_TP_ADD_TC(tp, dir_note_link_delete_dir_in);
 	ATF_TP_ADD_TC(tp, dir_note_link_mv_dir_in);
 	ATF_TP_ADD_TC(tp, dir_note_link_mv_dir_out);
 	ATF_TP_ADD_TC(tp, dir_note_write_create_dir_in);
 	ATF_TP_ADD_TC(tp, dir_note_write_create_file_in);
 	ATF_TP_ADD_TC(tp, dir_note_write_delete_dir_in);
 	ATF_TP_ADD_TC(tp, dir_note_write_delete_file_in);
 	ATF_TP_ADD_TC(tp, dir_note_write_mv_dir_in);
 	ATF_TP_ADD_TC(tp, dir_note_write_mv_dir_out);
 	ATF_TP_ADD_TC(tp, dir_note_write_mv_dir_within);
 	ATF_TP_ADD_TC(tp, dir_note_write_mv_file_in);
 	ATF_TP_ADD_TC(tp, dir_note_write_mv_file_out);
 	ATF_TP_ADD_TC(tp, dir_note_write_mv_file_within);
 	return atf_no_error();
 }

 --------------010001000906050803000106--

From: "Christos Zoulas" <christos@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/48958 CVS commit: src/tests/kernel/kqueue
Date: Wed, 14 Jan 2015 17:22:14 -0500

 Module Name:	src
 Committed By:	christos
 Date:		Wed Jan 14 22:22:14 UTC 2015

 Added Files:
 	src/tests/kernel/kqueue: t_vnode.c

 Log Message:
 PR/48958: rudolf: EVFILT_VNODE filter miscounting hardlinks (add test)


 To generate a diff of this commit:
 cvs rdiff -u -r0 -r1.1 src/tests/kernel/kqueue/t_vnode.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

From: "Christos Zoulas" <christos@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/48958 CVS commit: src/distrib/sets/lists
Date: Wed, 14 Jan 2015 17:25:05 -0500

 Module Name:	src
 Committed By:	christos
 Date:		Wed Jan 14 22:25:05 UTC 2015

 Modified Files:
 	src/distrib/sets/lists/debug: mi
 	src/distrib/sets/lists/tests: mi

 Log Message:
 add vnode kqueue test from PR/48958


 To generate a diff of this commit:
 cvs rdiff -u -r1.102 -r1.103 src/distrib/sets/lists/debug/mi
 cvs rdiff -u -r1.609 -r1.610 src/distrib/sets/lists/tests/mi

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

State-Changed-From-To: open->closed
State-Changed-By: pgoyette@NetBSD.org
State-Changed-When: Wed, 01 Jun 2016 04:33:22 +0000
State-Changed-Why:
The proposed test cases were committed, and all are now passing.  The
original code where this bug lived no longer exists, so the proposed
fix for the underlying bug is no longer relevant.  Nothing more to do
here.


>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2014 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.