mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-28 19:34:43 +01:00
inotify: Unconditionally generate IN_IGNORED events for files/dirs
The implementation previously only generated an IN_IGNORED event for a deleted watched file if the watch explicitly requested IN_DELETE_SELF. This is not correct, IN_IGNORED should always be raised when the watched subject is deleted. Adjust the implementation of inotify_log_one() accordingly. This also fixes a problem where a deleted watched file's watch would not be removed if IN_DELETE_SELF was not in the watch's event mask, in which case the unlinked vnode would linger until the inotify descriptor itself is closed. Add a regression test. Reported by: jrtc27 Reviewed by: jrtc27 MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D58050
This commit is contained in:
1 parent
4805b88edb
commit
b70997c8c7
2 files changed
+47
-12
No files matched your search
+23
-12
@@ -614,25 +614,37 @@ inotify_log_one(struct inotify_watch *watch, const char *name, size_t namelen,
|
||||
struct inotify_watch key;
|
||||
struct inotify_softc *sc;
|
||||
struct inotify_record *rec;
|
||||
bool allocfail;
|
||||
bool allocfail, delete, notify, oneshot, unmount;
|
||||
|
||||
mtx_assert(&watch->vp->v_pollinfo->vpi_lock, MA_OWNED);
|
||||
|
||||
sc = watch->sc;
|
||||
rec = inotify_alloc_record(watch->wd, name, namelen, event, cookie,
|
||||
M_NOWAIT);
|
||||
if (rec == NULL) {
|
||||
rec = &sc->overflow;
|
||||
allocfail = true;
|
||||
|
||||
delete = (event & IN_DELETE_SELF) != 0;
|
||||
notify = (watch->mask & event) != 0;
|
||||
oneshot = (watch->mask & IN_ONESHOT) != 0;
|
||||
unmount = (event & IN_UNMOUNT) != 0;
|
||||
if (!notify && !delete && !unmount)
|
||||
return;
|
||||
|
||||
if (notify || unmount) {
|
||||
rec = inotify_alloc_record(watch->wd, name, namelen, event,
|
||||
cookie, M_NOWAIT);
|
||||
if (rec == NULL) {
|
||||
rec = &sc->overflow;
|
||||
allocfail = true;
|
||||
} else {
|
||||
allocfail = false;
|
||||
}
|
||||
} else {
|
||||
allocfail = false;
|
||||
rec = NULL;
|
||||
}
|
||||
|
||||
mtx_lock(&sc->lock);
|
||||
if (!inotify_queue_record(sc, rec) && rec != &sc->overflow)
|
||||
if (rec != NULL && !inotify_queue_record(sc, rec) &&
|
||||
rec != &sc->overflow)
|
||||
free(rec, M_INOTIFY);
|
||||
if ((watch->mask & IN_ONESHOT) != 0 ||
|
||||
(event & (IN_DELETE_SELF | IN_UNMOUNT)) != 0) {
|
||||
if (oneshot || delete || unmount) {
|
||||
if (!allocfail) {
|
||||
rec = inotify_alloc_record(watch->wd, NULL, 0,
|
||||
IN_IGNORED, 0, M_NOWAIT);
|
||||
@@ -676,8 +688,7 @@ inotify_log(struct vnode *vp, const char *name, size_t namelen, int event,
|
||||
TAILQ_FOREACH_SAFE(watch, &vp->v_pollinfo->vpi_inotify, vlink, tmp) {
|
||||
KASSERT(watch->vp == vp,
|
||||
("inotify_log: watch %p vp != vp", watch));
|
||||
if ((watch->mask & event) != 0 || event == IN_UNMOUNT)
|
||||
inotify_log_one(watch, name, namelen, event, cookie);
|
||||
inotify_log_one(watch, name, namelen, event, cookie);
|
||||
}
|
||||
mtx_unlock(&vp->v_pollinfo->vpi_lock);
|
||||
}
|
||||
|
||||
@@ -54,6 +54,8 @@ ev2name(int event)
|
||||
return ("IN_MOVED_TO");
|
||||
case IN_OPEN:
|
||||
return ("IN_OPEN");
|
||||
case IN_IGNORED:
|
||||
return ("IN_IGNORED");
|
||||
default:
|
||||
return (NULL);
|
||||
}
|
||||
@@ -832,6 +834,27 @@ ATF_TC_BODY(inotify_event_delete, tc)
|
||||
close_inotify(ifd);
|
||||
}
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(inotify_event_delete_ignored);
|
||||
ATF_TC_BODY(inotify_event_delete_ignored, tc)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
int error, ifd, wd;
|
||||
|
||||
ifd = inotify(IN_NONBLOCK);
|
||||
|
||||
wd = watch_dir(ifd, IN_DELETE, path);
|
||||
|
||||
/*
|
||||
* IN_IGNORED should be generated when a watched directory is removed,
|
||||
* even if the watch was not configured to raise IN_DELETE_SELF.
|
||||
*/
|
||||
error = rmdir(path);
|
||||
ATF_REQUIRE(error == 0);
|
||||
consume_event(ifd, wd, 0, IN_IGNORED, NULL);
|
||||
|
||||
close_inotify(ifd);
|
||||
}
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(inotify_event_move);
|
||||
ATF_TC_BODY(inotify_event_move, tc)
|
||||
{
|
||||
@@ -999,6 +1022,7 @@ ATF_TP_ADD_TCS(tp)
|
||||
ATF_TP_ADD_TC(tp, inotify_event_close_write);
|
||||
ATF_TP_ADD_TC(tp, inotify_event_create);
|
||||
ATF_TP_ADD_TC(tp, inotify_event_delete);
|
||||
ATF_TP_ADD_TC(tp, inotify_event_delete_ignored);
|
||||
ATF_TP_ADD_TC(tp, inotify_event_move);
|
||||
ATF_TP_ADD_TC(tp, inotify_event_move_dir);
|
||||
ATF_TP_ADD_TC(tp, inotify_event_open);
|
||||
|
||||
Reference in new issue
Block a user