1 /* $NetBSD: linux_inotify.c,v 1.11 2026/09/20 13:48:00 riastradh Exp $ */ 2 3 /*- 4 * Copyright (c) 2023 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Theodore Preduta. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 #include <sys/cdefs.h> 32 __KERNEL_RCSID(0, "$NetBSD: linux_inotify.c,v 1.11 2026/09/20 13:48:00 riastradh Exp $"); 33 34 #include <sys/param.h> 35 #include <sys/types.h> 36 #include <sys/bitops.h> 37 #include <sys/dirent.h> 38 #include <sys/event.h> 39 #include <sys/eventvar.h> 40 #include <sys/errno.h> 41 #include <sys/file.h> 42 #include <sys/filedesc.h> 43 #include <sys/fcntl.h> 44 #include <sys/poll.h> 45 #include <sys/proc.h> 46 #include <sys/selinfo.h> 47 #include <sys/select.h> 48 #include <sys/signal.h> 49 #include <sys/vnode.h> 50 51 #include <sys/syscallargs.h> 52 53 #include <compat/linux/common/linux_machdep.h> 54 #include <compat/linux/common/linux_fcntl.h> 55 #include <compat/linux/common/linux_inotify.h> 56 #include <compat/linux/common/linux_ipc.h> 57 #include <compat/linux/common/linux_sched.h> 58 #include <compat/linux/common/linux_sem.h> 59 #include <compat/linux/common/linux_signal.h> 60 61 #include <compat/linux/linux_syscallargs.h> 62 63 /* 64 * inotify(2). This interface allows the user to get file system 65 * events and (unlike kqueue(2)) their order is strictly preserved. 66 * While nice, the API has sufficient gotchas that mean we don't want 67 * to add native entry points for it. They are: 68 * 69 * - Because data is returned via read(2), this API is prone to 70 * unaligned memory accesses. There is a note in the Linux man page 71 * that says the name field of struct linux_inotify_event *can* be 72 * used for alignment purposes. In practice, even Linux doesn't 73 * always do this, so for simplicity, we don't ever do this. 74 */ 75 76 #define LINUX_INOTIFY_MAX_QUEUED 16384 77 #define LINUX_INOTIFY_MAX_FROM_KEVENT 3 78 79 #if DEBUG_LINUX 80 #define DPRINTF(x) uprintf x 81 #else 82 #define DPRINTF(x) __nothing 83 #endif 84 85 struct inotify_entry { 86 TAILQ_ENTRY(inotify_entry) ie_entries; 87 char ie_name[NAME_MAX + 1]; 88 struct linux_inotify_event ie_event; 89 }; 90 91 struct inotify_dir_entries { 92 size_t ide_count; 93 struct inotify_dir_entry { 94 char name[NAME_MAX + 1]; 95 ino_t fileno; 96 } ide_entries[]; 97 }; 98 #define INOTIFY_DIR_ENTRIES_SIZE(count) (sizeof(struct inotify_dir_entries) \ 99 + count * sizeof(struct inotify_dir_entry)) 100 101 struct inotifyfd { 102 int ifd_kqfd; /* kqueue fd used by this inotify */ 103 /* instance */ 104 struct selinfo ifd_sel; /* for EVFILT_READ by epoll */ 105 kmutex_t ifd_lock; /* lock for ifd_sel, ifd_wds and */ 106 /* ifd_nwds */ 107 108 struct inotify_dir_entries **ifd_wds; 109 /* keeps track of watch descriptors */ 110 /* for directories: snapshot of the */ 111 /* directory state */ 112 /* for files: an inotify_dir_entries */ 113 /* with ide_count == 0 */ 114 size_t ifd_nwds; /* max watch descriptor that can be */ 115 /* stored in ifd_wds + 1 */ 116 117 TAILQ_HEAD(, inotify_entry) ifd_qhead; /* queue of pending events */ 118 size_t ifd_qcount; /* number of pending events */ 119 kcondvar_t ifd_qcv; /* condvar for blocking reads */ 120 kmutex_t ifd_qlock; /* lock for ifd_q* and interlock */ 121 /* for ifd_qcv */ 122 }; 123 124 struct inotify_kevent_mask_pair { 125 uint32_t inotify; 126 uint32_t kevent; 127 }; 128 129 static int inotify_kev_fetch_changes(void *, const struct kevent *, 130 struct kevent *, size_t, int); 131 static int do_inotify_init(struct lwp *, register_t *, int); 132 static int inotify_close_wd(struct inotifyfd *, int); 133 static uint32_t inotify_mask_to_kevent_fflags(uint32_t, enum vtype); 134 static void do_kevent_to_inotify(int32_t, uint32_t, uint32_t, 135 struct inotify_entry *, size_t *, char *); 136 static int kevent_to_inotify(struct inotifyfd *, int, enum vtype, uint32_t, 137 uint32_t, struct inotify_entry *, size_t *); 138 static int inotify_readdir(file_t *, struct dirent *, int *, bool); 139 static struct inotify_dir_entries *get_inotify_dir_entries(int, bool); 140 141 static int inotify_filt_attach(struct knote *); 142 static void inotify_filt_detach(struct knote *); 143 static int inotify_filt_event(struct knote *, long); 144 static void inotify_read_filt_detach(struct knote *); 145 static int inotify_read_filt_event(struct knote *, long); 146 147 static int inotify_read(file_t *, off_t *, struct uio *, kauth_cred_t, int); 148 static int inotify_close(file_t *); 149 static int inotify_poll(file_t *, int); 150 static int inotify_kqfilter(file_t *, struct knote *); 151 static void inotify_restart(file_t *); 152 153 static const char inotify_filtname[] = "LINUX_INOTIFY"; 154 static int inotify_filtid; 155 156 /* "fake" EVFILT_VNODE that gets attached to ifd_deps */ 157 static const struct filterops inotify_filtops = { 158 .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, 159 .f_attach = inotify_filt_attach, 160 .f_detach = inotify_filt_detach, 161 .f_event = inotify_filt_event, 162 .f_touch = NULL, 163 }; 164 165 /* EVFILT_READ attached to inotifyfd (to support watching via epoll) */ 166 static const struct filterops inotify_read_filtops = { 167 .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, 168 .f_attach = NULL, /* attached via .fo_kqfilter */ 169 .f_detach = inotify_read_filt_detach, 170 .f_event = inotify_read_filt_event, 171 .f_touch = NULL, 172 }; 173 174 static const struct fileops inotify_fileops = { 175 .fo_name = "inotify", 176 .fo_read = inotify_read, 177 .fo_write = fbadop_write, 178 .fo_ioctl = fbadop_ioctl, 179 .fo_fcntl = fnullop_fcntl, 180 .fo_poll = inotify_poll, 181 .fo_stat = fbadop_stat, 182 .fo_close = inotify_close, 183 .fo_kqfilter = inotify_kqfilter, 184 .fo_restart = inotify_restart, 185 .fo_fpathconf = (void *)eopnotsupp, 186 }; 187 188 /* basic flag translations */ 189 static const struct inotify_kevent_mask_pair common_inotify_to_kevent[] = { 190 { .inotify = LINUX_IN_ATTRIB, .kevent = NOTE_ATTRIB, }, 191 { .inotify = LINUX_IN_CLOSE_NOWRITE, .kevent = NOTE_CLOSE, }, 192 { .inotify = LINUX_IN_OPEN, .kevent = NOTE_OPEN, }, 193 { .inotify = LINUX_IN_MOVE_SELF, .kevent = NOTE_RENAME, }, 194 }; 195 static const size_t common_inotify_to_kevent_len = 196 __arraycount(common_inotify_to_kevent); 197 198 static const struct inotify_kevent_mask_pair vreg_inotify_to_kevent[] = { 199 { .inotify = LINUX_IN_ACCESS, .kevent = NOTE_READ, }, 200 { .inotify = LINUX_IN_ATTRIB, .kevent = NOTE_ATTRIB|NOTE_LINK, }, 201 { .inotify = LINUX_IN_CLOSE_WRITE, .kevent = NOTE_CLOSE_WRITE, }, 202 { .inotify = LINUX_IN_MODIFY, .kevent = NOTE_WRITE, }, 203 }; 204 static const size_t vreg_inotify_to_kevent_len = 205 __arraycount(vreg_inotify_to_kevent); 206 207 static const struct inotify_kevent_mask_pair vdir_inotify_to_kevent[] = { 208 { .inotify = LINUX_IN_ACCESS, .kevent = NOTE_READ, }, 209 { .inotify = LINUX_IN_CREATE, .kevent = NOTE_WRITE, }, 210 { .inotify = LINUX_IN_DELETE, .kevent = NOTE_WRITE, }, 211 { .inotify = LINUX_IN_MOVED_FROM, .kevent = NOTE_WRITE, }, 212 { .inotify = LINUX_IN_MOVED_TO, .kevent = NOTE_WRITE, }, 213 }; 214 static const size_t vdir_inotify_to_kevent_len = 215 __arraycount(vdir_inotify_to_kevent); 216 217 static const struct inotify_kevent_mask_pair common_kevent_to_inotify[] = { 218 { .kevent = NOTE_ATTRIB, .inotify = LINUX_IN_ATTRIB, }, 219 { .kevent = NOTE_CLOSE, .inotify = LINUX_IN_CLOSE_NOWRITE, }, 220 { .kevent = NOTE_CLOSE_WRITE, .inotify = LINUX_IN_CLOSE_WRITE, }, 221 { .kevent = NOTE_OPEN, .inotify = LINUX_IN_OPEN, }, 222 { .kevent = NOTE_READ, .inotify = LINUX_IN_ACCESS, }, 223 { .kevent = NOTE_RENAME, .inotify = LINUX_IN_MOVE_SELF, }, 224 { .kevent = NOTE_REVOKE, .inotify = LINUX_IN_UNMOUNT, }, 225 }; 226 static const size_t common_kevent_to_inotify_len = 227 __arraycount(common_kevent_to_inotify); 228 229 static const struct inotify_kevent_mask_pair vreg_kevent_to_inotify[] = { 230 { .kevent = NOTE_DELETE|NOTE_LINK, .inotify = LINUX_IN_ATTRIB, }, 231 { .kevent = NOTE_WRITE, .inotify = LINUX_IN_MODIFY, }, 232 }; 233 static const size_t vreg_kevent_to_inotify_len = 234 __arraycount(vreg_kevent_to_inotify); 235 236 /* 237 * Register the custom kfilter for inotify. 238 */ 239 int 240 linux_inotify_init(void) 241 { 242 return kfilter_register(inotify_filtname, &inotify_filtops, 243 &inotify_filtid); 244 } 245 246 /* 247 * Unregister the custom kfilter for inotify. 248 */ 249 int 250 linux_inotify_fini(void) 251 { 252 return kfilter_unregister(inotify_filtname); 253 } 254 255 /* 256 * Copyin callback used by kevent. This copies already converted 257 * filters from kernel memory to the kevent internal kernel memory. 258 * Hence the memcpy instead of copyin. 259 */ 260 static int 261 inotify_kev_fetch_changes(void *ctx, const struct kevent *changelist, 262 struct kevent *changes, size_t index, int n) 263 { 264 memcpy(changes, changelist + index, n * sizeof(*changes)); 265 266 return 0; 267 } 268 269 /* 270 * Initialize a new inotify fd. 271 */ 272 static int 273 do_inotify_init(struct lwp *l, register_t *retval, int flags) 274 { 275 file_t *fp; 276 int error, fd; 277 struct proc *p = l->l_proc; 278 struct inotifyfd *ifd; 279 struct sys_kqueue1_args kqa; 280 281 if (flags & ~(LINUX_IN_ALL_FLAGS)) 282 return EINVAL; 283 284 ifd = kmem_zalloc(sizeof(*ifd), KM_SLEEP); 285 mutex_init(&ifd->ifd_lock, MUTEX_DEFAULT, IPL_NONE); 286 mutex_init(&ifd->ifd_qlock, MUTEX_DEFAULT, IPL_NONE); 287 cv_init(&ifd->ifd_qcv, "inotify"); 288 selinit(&ifd->ifd_sel); 289 TAILQ_INIT(&ifd->ifd_qhead); 290 291 ifd->ifd_nwds = 1; 292 ifd->ifd_wds = kmem_zalloc(ifd->ifd_nwds * sizeof(*ifd->ifd_wds), 293 KM_SLEEP); 294 295 memset(&kqa, 0, sizeof(kqa)); 296 SCARG(&kqa, flags) = 0; 297 if (flags & LINUX_IN_NONBLOCK) 298 SCARG(&kqa, flags) |= O_NONBLOCK; 299 error = sys_kqueue1(l, &kqa, retval); 300 if (error != 0) 301 goto leave0; 302 ifd->ifd_kqfd = *retval; 303 304 error = fd_allocfile(&fp, &fd); 305 if (error != 0) 306 goto leave1; 307 308 fp->f_flag = FREAD; 309 if (flags & LINUX_IN_NONBLOCK) 310 fp->f_flag |= FNONBLOCK; 311 fp->f_type = DTYPE_MISC; 312 fp->f_ops = &inotify_fileops; 313 fp->f_data = ifd; 314 fd_set_exclose(l, fd, (flags & LINUX_IN_CLOEXEC) != 0); 315 fd_affix(p, fp, fd); 316 317 *retval = fd; 318 return 0; 319 320 leave1: 321 KASSERT(fd_getfile(ifd->ifd_kqfd) != NULL); 322 fd_close(ifd->ifd_kqfd); 323 leave0: 324 kmem_free(ifd->ifd_wds, ifd->ifd_nwds * sizeof(*ifd->ifd_wds)); 325 kmem_free(ifd, sizeof(*ifd)); 326 327 mutex_destroy(&ifd->ifd_lock); 328 mutex_destroy(&ifd->ifd_qlock); 329 cv_destroy(&ifd->ifd_qcv); 330 seldestroy(&ifd->ifd_sel); 331 332 return error; 333 } 334 335 #ifndef __aarch64__ 336 /* 337 * inotify_init(2). Initialize a new inotify fd with flags=0. 338 */ 339 int 340 linux_sys_inotify_init(struct lwp *l, const void *v, register_t *retval) 341 { 342 return do_inotify_init(l, retval, 0); 343 } 344 #endif 345 346 /* 347 * inotify_init(2). Initialize a new inotify fd with the given flags. 348 */ 349 int 350 linux_sys_inotify_init1(struct lwp *l, 351 const struct linux_sys_inotify_init1_args *uap, register_t *retval) 352 { 353 /* { 354 syscallarg(int) flags; 355 } */ 356 357 return do_inotify_init(l, retval, SCARG(uap, flags)); 358 } 359 360 /* 361 * Convert inotify mask to the fflags of an equivalent kevent. 362 */ 363 static uint32_t 364 inotify_mask_to_kevent_fflags(uint32_t mask, enum vtype type) 365 { 366 const struct inotify_kevent_mask_pair *type_inotify_to_kevent; 367 uint32_t fflags; 368 size_t i, type_inotify_to_kevent_len; 369 370 switch (type) { 371 case VREG: 372 case VDIR: 373 case VLNK: 374 break; 375 376 default: 377 return 0; 378 } 379 380 /* flags that all watches could have */ 381 fflags = NOTE_DELETE|NOTE_REVOKE; 382 for (i = 0; i < common_inotify_to_kevent_len; i++) 383 if (mask & common_inotify_to_kevent[i].inotify) 384 fflags |= common_inotify_to_kevent[i].kevent; 385 386 /* flags that depend on type */ 387 switch (type) { 388 case VREG: 389 type_inotify_to_kevent = vreg_inotify_to_kevent; 390 type_inotify_to_kevent_len = vreg_inotify_to_kevent_len; 391 break; 392 393 case VDIR: 394 type_inotify_to_kevent = vdir_inotify_to_kevent; 395 type_inotify_to_kevent_len = vdir_inotify_to_kevent_len; 396 break; 397 398 default: 399 type_inotify_to_kevent_len = 0; 400 break; 401 } 402 for (i = 0; i < type_inotify_to_kevent_len; i++) 403 if (mask & type_inotify_to_kevent[i].inotify) 404 fflags |= type_inotify_to_kevent[i].kevent; 405 406 return fflags; 407 } 408 409 /* 410 * inotify_add_watch(2). Open a fd for pathname (if desired by mask) 411 * track it and add an equivalent kqueue event for it in 412 * ifd->ifd_kqfd. 413 */ 414 int 415 linux_sys_inotify_add_watch(struct lwp *l, 416 const struct linux_sys_inotify_add_watch_args *uap, register_t *retval) 417 { 418 /* { 419 syscallarg(int) fd; 420 syscallarg(const char *) pathname; 421 syscallarg(uint32_t) mask; 422 } */ 423 int wd, i, error = 0; 424 file_t *fp, *wp, *cur_fp; 425 struct inotifyfd *ifd; 426 struct inotify_dir_entries **new_wds; 427 struct knote *kn, *tmpkn; 428 struct sys_open_args oa; 429 struct kevent kev; 430 struct vnode *wvp; 431 namei_simple_flags_t sflags; 432 struct kevent_ops k_ops = { 433 .keo_private = NULL, 434 .keo_fetch_timeout = NULL, 435 .keo_fetch_changes = inotify_kev_fetch_changes, 436 .keo_put_events = NULL, 437 }; 438 const int fd = SCARG(uap, fd); 439 const uint32_t mask = SCARG(uap, mask); 440 441 if (mask & ~LINUX_IN_ADD_KNOWN) 442 return EINVAL; 443 444 fp = fd_getfile(fd); 445 if (fp == NULL) 446 return EBADF; 447 448 if (fp->f_ops != &inotify_fileops) { 449 /* not an inotify fd */ 450 error = EBADF; 451 goto leave0; 452 } 453 454 ifd = fp->f_data; 455 456 mutex_enter(&ifd->ifd_lock); 457 458 if (mask & LINUX_IN_DONT_FOLLOW) 459 sflags = NSM_NOFOLLOW_TRYEMULROOT; 460 else 461 sflags = NSM_FOLLOW_TRYEMULROOT; 462 error = namei_simple_user(SCARG(uap, pathname), sflags, &wvp); 463 if (error != 0) 464 goto leave1; 465 466 /* Check to see if we already have a descriptor to wd's file. */ 467 wd = -1; 468 for (i = 0; i < ifd->ifd_nwds; i++) { 469 if (ifd->ifd_wds[i] != NULL) { 470 cur_fp = fd_getfile(i); 471 if (cur_fp == NULL) { 472 DPRINTF(("%s: wd=%d was closed externally\n", 473 __func__, i)); 474 error = EBADF; 475 goto leave1; 476 } 477 if (cur_fp->f_type != DTYPE_VNODE) { 478 DPRINTF(("%s: wd=%d was replaced " 479 "with a non-vnode\n", __func__, i)); 480 error = EBADF; 481 } 482 if (error == 0 && cur_fp->f_vnode == wvp) 483 wd = i; 484 fd_putfile(i); 485 if (error != 0) 486 goto leave1; 487 488 if (wd != -1) 489 break; 490 } 491 } 492 493 if (wd == -1) { 494 /* 495 * If we do not have a descriptor to wd's file, we 496 * need to open the watch descriptor. 497 */ 498 memset(&oa, 0, sizeof(oa)); 499 SCARG(&oa, path) = SCARG(uap, pathname); 500 SCARG(&oa, mode) = 0; 501 SCARG(&oa, flags) = O_RDONLY; 502 if (mask & LINUX_IN_DONT_FOLLOW) 503 SCARG(&oa, flags) |= O_NOFOLLOW; 504 if (mask & LINUX_IN_ONLYDIR) 505 SCARG(&oa, flags) |= O_DIRECTORY; 506 507 error = sys_open(l, &oa, retval); 508 if (error != 0) 509 goto leave1; 510 wd = *retval; 511 wp = fd_getfile(wd); 512 KASSERT(wp != NULL); 513 KASSERT(wp->f_type == DTYPE_VNODE); 514 515 /* translate the flags */ 516 memset(&kev, 0, sizeof(kev)); 517 EV_SET(&kev, wd, inotify_filtid, EV_ADD|EV_ENABLE, 518 NOTE_DELETE|NOTE_REVOKE, 0, ifd); 519 if (mask & LINUX_IN_ONESHOT) 520 kev.flags |= EV_ONESHOT; 521 kev.fflags |= inotify_mask_to_kevent_fflags(mask, 522 wp->f_vnode->v_type); 523 524 error = kevent1(retval, ifd->ifd_kqfd, &kev, 1, NULL, 0, NULL, 525 &k_ops); 526 if (error != 0) { 527 KASSERT(fd_getfile(wd) != NULL); 528 fd_close(wd); 529 } else { 530 /* Success! */ 531 *retval = wd; 532 533 /* Resize ifd_nwds to accommodate wd. */ 534 if (wd+1 > ifd->ifd_nwds) { 535 new_wds = kmem_zalloc( 536 (wd+1) * sizeof(*ifd->ifd_wds), KM_SLEEP); 537 memcpy(new_wds, ifd->ifd_wds, 538 ifd->ifd_nwds * sizeof(*ifd->ifd_wds)); 539 540 kmem_free(ifd->ifd_wds, 541 ifd->ifd_nwds * sizeof(*ifd->ifd_wds)); 542 543 ifd->ifd_wds = new_wds; 544 ifd->ifd_nwds = wd+1; 545 } 546 547 ifd->ifd_wds[wd] = get_inotify_dir_entries(wd, true); 548 } 549 } else { 550 /* 551 * If we do have a descriptor to wd's file, try to edit 552 * the relevant knote. 553 */ 554 if (mask & LINUX_IN_MASK_CREATE) { 555 error = EEXIST; 556 goto leave1; 557 } 558 559 wp = fd_getfile(wd); 560 if (wp == NULL) { 561 DPRINTF(("%s: wd=%d was closed externally " 562 "(race, probably)\n", __func__, wd)); 563 error = EBADF; 564 goto leave1; 565 } 566 if (wp->f_type != DTYPE_VNODE) { 567 DPRINTF(("%s: wd=%d was replace with a non-vnode " 568 "(race, probably)\n", __func__, wd)); 569 error = EBADF; 570 goto leave2; 571 } 572 573 kev.fflags = NOTE_DELETE | NOTE_REVOKE 574 | inotify_mask_to_kevent_fflags(mask, wp->f_vnode->v_type); 575 576 mutex_enter(wp->f_vnode->v_interlock); 577 578 /* 579 * XXX We are forced to find the appropriate knote 580 * manually because we cannot create a custom f_touch 581 * function for inotify_filtops. See filter_touch() 582 * in kern_event.c for details. 583 */ 584 SLIST_FOREACH_SAFE(kn, &wp->f_vnode->v_klist->vk_klist, 585 kn_selnext, tmpkn) { 586 if (kn->kn_fop == &inotify_filtops 587 && ifd == kn->kn_kevent.udata) { 588 mutex_enter(&kn->kn_kq->kq_lock); 589 if (mask & LINUX_IN_MASK_ADD) 590 kn->kn_sfflags |= kev.fflags; 591 else 592 kn->kn_sfflags = kev.fflags; 593 wp->f_vnode->v_klist->vk_interest |= 594 kn->kn_sfflags; 595 mutex_exit(&kn->kn_kq->kq_lock); 596 } 597 } 598 599 mutex_exit(wp->f_vnode->v_interlock); 600 601 /* Success! */ 602 *retval = wd; 603 } 604 605 leave2: 606 fd_putfile(wd); 607 leave1: 608 mutex_exit(&ifd->ifd_lock); 609 leave0: 610 fd_putfile(fd); 611 return error; 612 } 613 614 /* 615 * Remove a wd from ifd and close wd. 616 */ 617 static int 618 inotify_close_wd(struct inotifyfd *ifd, int wd) 619 { 620 file_t *wp; 621 int error; 622 register_t retval; 623 struct kevent kev; 624 struct kevent_ops k_ops = { 625 .keo_private = NULL, 626 .keo_fetch_timeout = NULL, 627 .keo_fetch_changes = inotify_kev_fetch_changes, 628 .keo_put_events = NULL, 629 }; 630 631 mutex_enter(&ifd->ifd_lock); 632 633 KASSERT(0 <= wd && wd < ifd->ifd_nwds && ifd->ifd_wds[wd] != NULL); 634 635 kmem_free(ifd->ifd_wds[wd], 636 INOTIFY_DIR_ENTRIES_SIZE(ifd->ifd_wds[wd]->ide_count)); 637 ifd->ifd_wds[wd] = NULL; 638 639 mutex_exit(&ifd->ifd_lock); 640 641 wp = fd_getfile(wd); 642 if (wp == NULL) { 643 DPRINTF(("%s: wd=%d is already closed\n", __func__, wd)); 644 return 0; 645 } 646 KASSERT(!mutex_owned(wp->f_vnode->v_interlock)); 647 648 memset(&kev, 0, sizeof(kev)); 649 EV_SET(&kev, wd, EVFILT_VNODE, EV_DELETE, 0, 0, 0); 650 error = kevent1(&retval, ifd->ifd_kqfd, &kev, 1, NULL, 0, NULL, &k_ops); 651 if (error != 0) 652 DPRINTF(("%s: attempt to disable all events for wd=%d " 653 "had error=%d\n", __func__, wd, error)); 654 655 return fd_close(wd); 656 } 657 658 /* 659 * inotify_rm_watch(2). Close wd and remove it from ifd->ifd_wds. 660 */ 661 int 662 linux_sys_inotify_rm_watch(struct lwp *l, 663 const struct linux_sys_inotify_rm_watch_args *uap, register_t *retval) 664 { 665 /* { 666 syscallarg(int) fd; 667 syscallarg(int) wd; 668 } */ 669 struct inotifyfd *ifd; 670 file_t *fp; 671 int error = 0; 672 const int fd = SCARG(uap, fd); 673 const int wd = SCARG(uap, wd); 674 675 fp = fd_getfile(fd); 676 if (fp == NULL) 677 return EBADF; 678 if (fp->f_ops != &inotify_fileops) { 679 /* not an inotify fd */ 680 error = EINVAL; 681 goto leave; 682 } 683 684 ifd = fp->f_data; 685 if (wd < 0 || wd >= ifd->ifd_nwds || ifd->ifd_wds[wd] == NULL) { 686 error = EINVAL; 687 goto leave; 688 } 689 690 error = inotify_close_wd(ifd, wd); 691 692 leave: 693 fd_putfile(fd); 694 return error; 695 } 696 697 /* 698 * Attach the inotify filter. 699 */ 700 static int 701 inotify_filt_attach(struct knote *kn) 702 { 703 file_t *fp = kn->kn_obj; 704 struct vnode *vp; 705 706 KASSERT(fp->f_type == DTYPE_VNODE); 707 vp = fp->f_vnode; 708 709 /* 710 * Needs to be set so that we get the same event handling as 711 * EVFILT_VNODE. Otherwise we don't get any events. 712 * 713 * A consequence of this is that modifications/removals of 714 * this knote need to specify EVFILT_VNODE rather than 715 * inotify_filtid. 716 */ 717 kn->kn_filter = EVFILT_VNODE; 718 719 kn->kn_fop = &inotify_filtops; 720 kn->kn_hook = vp; 721 vn_knote_attach(vp, kn); 722 723 return 0; 724 } 725 726 /* 727 * Detach the inotify filter. 728 */ 729 static void 730 inotify_filt_detach(struct knote *kn) 731 { 732 struct vnode *vp = (struct vnode *)kn->kn_hook; 733 734 vn_knote_detach(vp, kn); 735 } 736 737 /* 738 * Create a single inotify event. 739 */ 740 static void 741 do_kevent_to_inotify(int32_t wd, uint32_t mask, uint32_t cookie, 742 struct inotify_entry *buf, size_t *nbuf, char *name) 743 { 744 KASSERT(*nbuf < LINUX_INOTIFY_MAX_FROM_KEVENT); 745 746 buf += *nbuf; 747 748 memset(buf, 0, sizeof(*buf)); 749 750 buf->ie_event.wd = wd; 751 buf->ie_event.mask = mask; 752 buf->ie_event.cookie = cookie; 753 754 if (name != NULL) { 755 buf->ie_event.len = strlen(name) + 1; 756 KASSERT(buf->ie_event.len <= sizeof(buf->ie_name)); 757 strlcpy(buf->ie_name, name, sizeof(buf->ie_name)); 758 } 759 760 ++(*nbuf); 761 } 762 763 /* 764 * Like vn_readdir(), but with vnode locking only if needs_lock is 765 * true (to avoid double locking in some situations). 766 */ 767 static int 768 inotify_readdir(file_t *fp, struct dirent *dep, int *done, bool needs_lock) 769 { 770 struct vnode *vp; 771 struct iovec iov; 772 struct uio uio; 773 int error, eofflag; 774 775 KASSERT(fp->f_type == DTYPE_VNODE); 776 vp = fp->f_vnode; 777 KASSERT(vp->v_type == VDIR); 778 779 iov.iov_base = dep; 780 iov.iov_len = sizeof(*dep); 781 782 uio.uio_iov = &iov; 783 uio.uio_iovcnt = 1; 784 uio.uio_rw = UIO_READ; 785 uio.uio_resid = sizeof(*dep); 786 UIO_SETUP_SYSSPACE(&uio); 787 788 mutex_enter(&fp->f_lock); 789 uio.uio_offset = fp->f_offset; 790 mutex_exit(&fp->f_lock); 791 792 /* XXX: should pass whether to lock or not */ 793 if (needs_lock) 794 vn_lock(vp, LK_SHARED | LK_RETRY); 795 else 796 /* 797 * XXX We need to temporarily drop v_interlock because 798 * it may be temporarily acquired by biowait(). 799 */ 800 mutex_exit(vp->v_interlock); 801 KASSERT(!mutex_owned(vp->v_interlock)); 802 error = VOP_READDIR(vp, &uio, fp->f_cred, &eofflag, NULL, NULL); 803 if (needs_lock) 804 VOP_UNLOCK(vp); 805 else 806 mutex_enter(vp->v_interlock); 807 808 mutex_enter(&fp->f_lock); 809 fp->f_offset = uio.uio_offset; 810 mutex_exit(&fp->f_lock); 811 812 *done = sizeof(*dep) - uio.uio_resid; 813 return error; 814 } 815 816 /* 817 * Create (and allocate) an appropriate inotify_dir_entries struct for wd to be 818 * used on ifd_wds of inotifyfd. If the entries on a directory fail to be read, 819 * NULL is returned. needs_lock indicates if the vnode's lock is not already 820 * owned. 821 */ 822 static struct inotify_dir_entries * 823 get_inotify_dir_entries(int wd, bool needs_lock) 824 { 825 struct dirent de; 826 struct dirent *currdep; 827 struct inotify_dir_entries *idep = NULL; 828 file_t *wp; 829 int done, error; 830 size_t i, decount; 831 832 wp = fd_getfile(wd); 833 if (wp == NULL) 834 return NULL; 835 if (wp->f_type != DTYPE_VNODE) 836 goto leave; 837 838 /* for non-directories, we have 0 entries. */ 839 if (wp->f_vnode->v_type != VDIR) { 840 idep = kmem_zalloc(INOTIFY_DIR_ENTRIES_SIZE(0), KM_SLEEP); 841 goto leave; 842 } 843 844 mutex_enter(&wp->f_lock); 845 wp->f_offset = 0; 846 mutex_exit(&wp->f_lock); 847 decount = 0; 848 for (;;) { 849 error = inotify_readdir(wp, &de, &done, needs_lock); 850 if (error != 0) 851 goto leave; 852 if (done == 0) 853 break; 854 855 currdep = &de; 856 while ((char *)currdep < ((char *)&de) + done) { 857 decount++; 858 currdep = _DIRENT_NEXT(currdep); 859 } 860 } 861 862 idep = kmem_zalloc(INOTIFY_DIR_ENTRIES_SIZE(decount), KM_SLEEP); 863 idep->ide_count = decount; 864 865 mutex_enter(&wp->f_lock); 866 wp->f_offset = 0; 867 mutex_exit(&wp->f_lock); 868 for (i = 0; i < decount;) { 869 error = inotify_readdir(wp, &de, &done, needs_lock); 870 if (error != 0 || done == 0) { 871 kmem_free(idep, INOTIFY_DIR_ENTRIES_SIZE(decount)); 872 idep = NULL; 873 goto leave; 874 } 875 876 currdep = &de; 877 while ((char *)currdep < ((char *)&de) + done && i < decount) { 878 size_t namlen = MIN(currdep->d_namlen, 879 sizeof(idep->ide_entries[i].name) - 1); 880 881 idep->ide_entries[i].fileno = currdep->d_fileno; 882 memcpy(idep->ide_entries[i].name, currdep->d_name, 883 namlen); 884 idep->ide_entries[i].name[namlen] = '\0'; 885 886 currdep = _DIRENT_NEXT(currdep); 887 i++; 888 } 889 } 890 891 leave: 892 fd_putfile(wd); 893 return idep; 894 } 895 896 static size_t 897 find_entry(struct inotify_dir_entries *i1, struct inotify_dir_entries *i2) 898 { 899 for (size_t i = 0; i < i2->ide_count; i++) 900 if (i2->ide_entries[i].fileno != i1->ide_entries[i].fileno) 901 return i; 902 KASSERTMSG(0, "Entry not found"); 903 return -1; 904 } 905 906 static void 907 handle_write(struct inotifyfd *ifd, int wd, struct inotify_entry *buf, 908 size_t *nbuf) 909 { 910 struct inotify_dir_entries *old_idep, *new_idep; 911 size_t i; 912 913 mutex_enter(&ifd->ifd_lock); 914 915 old_idep = ifd->ifd_wds[wd]; 916 KASSERT(old_idep != NULL); 917 new_idep = get_inotify_dir_entries(wd, false); 918 if (new_idep == NULL) { 919 DPRINTF(("%s: directory for wd=%d could not be read\n", 920 __func__, wd)); 921 mutex_exit(&ifd->ifd_lock); 922 return; 923 } 924 925 926 if (old_idep->ide_count < new_idep->ide_count) { 927 KASSERT(old_idep->ide_count + 1 == new_idep->ide_count); 928 929 /* Find the new entry. */ 930 i = find_entry(new_idep, old_idep); 931 do_kevent_to_inotify(wd, LINUX_IN_CREATE, 0, 932 buf, nbuf, new_idep->ide_entries[i].name); 933 goto out; 934 } 935 936 if (old_idep->ide_count > new_idep->ide_count) { 937 KASSERT(old_idep->ide_count == new_idep->ide_count + 1); 938 939 /* Find the deleted entry. */ 940 i = find_entry(old_idep, new_idep); 941 942 do_kevent_to_inotify(wd, LINUX_IN_DELETE, 0, 943 buf, nbuf, old_idep->ide_entries[i].name); 944 goto out; 945 } 946 947 /* 948 * XXX Because we are not watching the entire 949 * file system, the only time we know for sure 950 * that the event is a LINUX_IN_MOVED_FROM/ 951 * LINUX_IN_MOVED_TO is when the move happens 952 * within a single directory... ie. the number 953 * of directory entries has not changed. 954 * 955 * Otherwise all we can say for sure is that 956 * something was created/deleted. So we issue a 957 * LINUX_IN_CREATE/LINUX_IN_DELETE. 958 */ 959 ino_t changed = new_idep->ide_entries[new_idep->ide_count - 1].fileno; 960 961 /* Find the deleted entry. */ 962 for (i = 0; i < old_idep->ide_count; i++) 963 if (old_idep->ide_entries[i].fileno == changed) 964 break; 965 KASSERT(i != old_idep->ide_count); 966 967 do_kevent_to_inotify(wd, LINUX_IN_MOVED_FROM, changed, buf, nbuf, 968 old_idep->ide_entries[i].name); 969 970 do_kevent_to_inotify(wd, LINUX_IN_MOVED_TO, changed, buf, nbuf, 971 new_idep->ide_entries[new_idep->ide_count - 1].name); 972 973 out: 974 ifd->ifd_wds[wd] = new_idep; 975 mutex_exit(&ifd->ifd_lock); 976 } 977 978 /* 979 * Convert a kevent flags and fflags for EVFILT_VNODE to some number 980 * of inotify events. 981 */ 982 static int 983 kevent_to_inotify(struct inotifyfd *ifd, int wd, enum vtype wtype, 984 uint32_t flags, uint32_t fflags, struct inotify_entry *buf, 985 size_t *nbuf) 986 { 987 struct stat st; 988 file_t *wp; 989 size_t i; 990 int error = 0; 991 992 for (i = 0; i < common_kevent_to_inotify_len; i++) 993 if (fflags & common_kevent_to_inotify[i].kevent) 994 do_kevent_to_inotify(wd, 995 common_kevent_to_inotify[i].inotify, 0, buf, nbuf, 996 NULL); 997 998 if (wtype == VREG) { 999 for (i = 0; i < vreg_kevent_to_inotify_len; i++) 1000 if (fflags & vreg_kevent_to_inotify[i].kevent) 1001 do_kevent_to_inotify(wd, 1002 vreg_kevent_to_inotify[i].inotify, 0, 1003 buf, nbuf, NULL); 1004 } else if (wtype == VDIR) { 1005 for (i = 0; i < *nbuf; i++) 1006 if (buf[i].ie_event.mask & 1007 (LINUX_IN_ACCESS|LINUX_IN_ATTRIB 1008 |LINUX_IN_CLOSE|LINUX_IN_OPEN)) 1009 buf[i].ie_event.mask |= LINUX_IN_ISDIR; 1010 1011 /* Need to disambiguate the possible NOTE_WRITEs. */ 1012 if (fflags & NOTE_WRITE) 1013 handle_write(ifd, wd, buf, nbuf); 1014 } 1015 1016 /* 1017 * Need to check if wd is actually has a link count of 0 to issue a 1018 * LINUX_IN_DELETE_SELF. 1019 */ 1020 if (fflags & NOTE_DELETE) { 1021 wp = fd_getfile(wd); 1022 KASSERT(wp != NULL); 1023 KASSERT(wp->f_type == DTYPE_VNODE); 1024 vn_stat(wp->f_vnode, &st); 1025 fd_putfile(wd); 1026 1027 if (st.st_nlink == 0) 1028 do_kevent_to_inotify(wd, LINUX_IN_DELETE_SELF, 0, 1029 buf, nbuf, NULL); 1030 } 1031 1032 /* LINUX_IN_IGNORED must be the last event issued for wd. */ 1033 if ((flags & EV_ONESHOT) || (fflags & (NOTE_REVOKE|NOTE_DELETE))) { 1034 do_kevent_to_inotify(wd, LINUX_IN_IGNORED, 0, buf, nbuf, NULL); 1035 /* 1036 * XXX in theory we could call inotify_close_wd(ifd, wd) but if 1037 * we get here we must already be holding v_interlock for 1038 * wd... so we can't. 1039 * 1040 * For simplicity we do nothing, and so wd will only be closed 1041 * when the inotify fd is closed. 1042 */ 1043 } 1044 1045 return error; 1046 } 1047 1048 /* 1049 * Handle an event. Unlike EVFILT_VNODE, we translate the event to a 1050 * linux_inotify_event and put it in our own custom queue. 1051 */ 1052 static int 1053 inotify_filt_event(struct knote *kn, long hint) 1054 { 1055 struct vnode *vp = (struct vnode *)kn->kn_hook; 1056 struct inotifyfd *ifd; 1057 struct inotify_entry *cur_ie; 1058 size_t nbuf, i; 1059 uint32_t status; 1060 struct inotify_entry buf[LINUX_INOTIFY_MAX_FROM_KEVENT]; 1061 1062 /* 1063 * If KN_WILLDETACH is set then 1064 * 1. kn->kn_kevent.udata has already been trashed with a 1065 * struct lwp *, so we don't have access to a real ifd 1066 * anymore, and 1067 * 2. we're about to detach anyways, so we don't really care 1068 * about the events. 1069 * (Also because of this we need to get ifd under the same 1070 * lock as kn->kn_status.) 1071 */ 1072 mutex_enter(&kn->kn_kq->kq_lock); 1073 status = kn->kn_status; 1074 ifd = kn->kn_kevent.udata; 1075 mutex_exit(&kn->kn_kq->kq_lock); 1076 if (status & KN_WILLDETACH) 1077 return 0; 1078 1079 /* 1080 * If we don't care about the NOTEs in hint, we don't generate 1081 * any events. 1082 */ 1083 hint &= kn->kn_sfflags; 1084 if (hint == 0) 1085 return 0; 1086 1087 KASSERT(mutex_owned(vp->v_interlock)); 1088 KASSERT(!mutex_owned(&ifd->ifd_lock)); 1089 1090 mutex_enter(&ifd->ifd_qlock); 1091 1092 /* 1093 * early out: there's no point even traslating the event if we 1094 * have nowhere to put it (and an LINUX_IN_Q_OVERFLOW has 1095 * already been added). 1096 */ 1097 if (ifd->ifd_qcount >= LINUX_INOTIFY_MAX_QUEUED) 1098 goto leave; 1099 1100 nbuf = 0; 1101 (void)kevent_to_inotify(ifd, kn->kn_id, vp->v_type, kn->kn_flags, 1102 hint, buf, &nbuf); 1103 for (i = 0; i < nbuf && ifd->ifd_qcount < LINUX_INOTIFY_MAX_QUEUED-1; 1104 i++) { 1105 cur_ie = kmem_zalloc(sizeof(*cur_ie), KM_SLEEP); 1106 memcpy(cur_ie, &buf[i], sizeof(*cur_ie)); 1107 1108 TAILQ_INSERT_TAIL(&ifd->ifd_qhead, cur_ie, ie_entries); 1109 ifd->ifd_qcount++; 1110 } 1111 /* handle early overflow, by adding an overflow event to the end */ 1112 if (i != nbuf) { 1113 nbuf = 0; 1114 cur_ie = kmem_zalloc(sizeof(*cur_ie), KM_SLEEP); 1115 do_kevent_to_inotify(-1, LINUX_IN_Q_OVERFLOW, 0, 1116 cur_ie, &nbuf, NULL); 1117 1118 TAILQ_INSERT_TAIL(&ifd->ifd_qhead, cur_ie, ie_entries); 1119 ifd->ifd_qcount++; 1120 } 1121 1122 if (nbuf > 0) { 1123 cv_signal(&ifd->ifd_qcv); 1124 1125 mutex_enter(&ifd->ifd_lock); 1126 selnotify(&ifd->ifd_sel, 0, NOTE_LOWAT); 1127 mutex_exit(&ifd->ifd_lock); 1128 } else 1129 DPRINTF(("%s: hint=%lx resulted in 0 inotify events\n", 1130 __func__, hint)); 1131 1132 leave: 1133 mutex_exit(&ifd->ifd_qlock); 1134 return 0; 1135 } 1136 1137 /* 1138 * Read inotify events from the queue. 1139 */ 1140 static int 1141 inotify_read(file_t *fp, off_t *offp, struct uio *uio, kauth_cred_t cred, 1142 int flags) 1143 { 1144 struct inotify_entry *cur_iep; 1145 size_t cur_size, nread; 1146 int error = 0; 1147 struct inotifyfd *ifd = fp->f_data; 1148 1149 mutex_enter(&ifd->ifd_qlock); 1150 1151 if (ifd->ifd_qcount == 0) { 1152 if (fp->f_flag & O_NONBLOCK) { 1153 error = EAGAIN; 1154 goto leave; 1155 } 1156 1157 while (ifd->ifd_qcount == 0) { 1158 /* wait until there is an event to read */ 1159 error = cv_wait_sig(&ifd->ifd_qcv, &ifd->ifd_qlock); 1160 if (error != 0) { 1161 error = EINTR; 1162 goto leave; 1163 } 1164 } 1165 } 1166 1167 KASSERT(ifd->ifd_qcount > 0); 1168 KASSERT(mutex_owned(&ifd->ifd_qlock)); 1169 1170 nread = 0; 1171 while (ifd->ifd_qcount > 0) { 1172 cur_iep = TAILQ_FIRST(&ifd->ifd_qhead); 1173 KASSERT(cur_iep != NULL); 1174 1175 cur_size = sizeof(cur_iep->ie_event) + cur_iep->ie_event.len; 1176 if (cur_size > uio->uio_resid) { 1177 if (nread == 0) 1178 error = EINVAL; 1179 break; 1180 } 1181 1182 error = uiomove(&cur_iep->ie_event, sizeof(cur_iep->ie_event), 1183 uio); 1184 if (error != 0) 1185 break; 1186 error = uiomove(&cur_iep->ie_name, cur_iep->ie_event.len, uio); 1187 if (error != 0) 1188 break; 1189 1190 /* cleanup */ 1191 TAILQ_REMOVE(&ifd->ifd_qhead, cur_iep, ie_entries); 1192 kmem_free(cur_iep, sizeof(*cur_iep)); 1193 1194 nread++; 1195 ifd->ifd_qcount--; 1196 } 1197 1198 leave: 1199 /* Wake up the next reader, if the queue is not empty. */ 1200 if (ifd->ifd_qcount > 0) 1201 cv_signal(&ifd->ifd_qcv); 1202 1203 mutex_exit(&ifd->ifd_qlock); 1204 return error; 1205 } 1206 1207 /* 1208 * Close all the file descriptors associated with fp. 1209 */ 1210 static int 1211 inotify_close(file_t *fp) 1212 { 1213 int error; 1214 size_t i; 1215 file_t *kqfp; 1216 struct inotifyfd *ifd = fp->f_data; 1217 1218 for (i = 0; i < ifd->ifd_nwds; i++) { 1219 if (ifd->ifd_wds[i] != NULL) { 1220 error = inotify_close_wd(ifd, i); 1221 if (error != 0) 1222 return error; 1223 } 1224 } 1225 1226 /* the reference we need to hold is ifd->ifd_kqfp */ 1227 kqfp = fd_getfile(ifd->ifd_kqfd); 1228 if (kqfp == NULL) { 1229 DPRINTF(("%s: kqfp=%d is already closed\n", __func__, 1230 ifd->ifd_kqfd)); 1231 } else { 1232 error = fd_close(ifd->ifd_kqfd); 1233 if (error != 0) 1234 return error; 1235 } 1236 1237 mutex_destroy(&ifd->ifd_lock); 1238 mutex_destroy(&ifd->ifd_qlock); 1239 cv_destroy(&ifd->ifd_qcv); 1240 seldestroy(&ifd->ifd_sel); 1241 1242 kmem_free(ifd->ifd_wds, ifd->ifd_nwds * sizeof(*ifd->ifd_wds)); 1243 kmem_free(ifd, sizeof(*ifd)); 1244 fp->f_data = NULL; 1245 1246 return 0; 1247 } 1248 1249 /* 1250 * Check if there are pending read events. 1251 */ 1252 static int 1253 inotify_poll(file_t *fp, int events) 1254 { 1255 int revents; 1256 struct inotifyfd *ifd = fp->f_data; 1257 1258 revents = 0; 1259 if (events & (POLLIN|POLLRDNORM)) { 1260 mutex_enter(&ifd->ifd_qlock); 1261 1262 if (ifd->ifd_qcount > 0) 1263 revents |= events & (POLLIN|POLLRDNORM); 1264 1265 mutex_exit(&ifd->ifd_qlock); 1266 } 1267 1268 return revents; 1269 } 1270 1271 /* 1272 * Attach EVFILT_READ to the inotify instance in fp. 1273 * 1274 * This is so you can watch inotify with epoll. No other kqueue 1275 * filter needs to be supported. 1276 */ 1277 static int 1278 inotify_kqfilter(file_t *fp, struct knote *kn) 1279 { 1280 struct inotifyfd *ifd = fp->f_data; 1281 1282 KASSERT(fp == kn->kn_obj); 1283 1284 if (kn->kn_filter != EVFILT_READ) 1285 return EINVAL; 1286 1287 kn->kn_fop = &inotify_read_filtops; 1288 mutex_enter(&ifd->ifd_lock); 1289 selrecord_knote(&ifd->ifd_sel, kn); 1290 mutex_exit(&ifd->ifd_lock); 1291 1292 return 0; 1293 } 1294 1295 /* 1296 * Detach a filter from an inotify instance. 1297 */ 1298 static void 1299 inotify_read_filt_detach(struct knote *kn) 1300 { 1301 struct inotifyfd *ifd = ((file_t *)kn->kn_obj)->f_data; 1302 1303 mutex_enter(&ifd->ifd_lock); 1304 selremove_knote(&ifd->ifd_sel, kn); 1305 mutex_exit(&ifd->ifd_lock); 1306 } 1307 1308 /* 1309 * Handle EVFILT_READ events. Note that nothing is put in kn_data. 1310 */ 1311 static int 1312 inotify_read_filt_event(struct knote *kn, long hint) 1313 { 1314 struct inotifyfd *ifd = ((file_t *)kn->kn_obj)->f_data; 1315 1316 if (hint != 0) { 1317 KASSERT(mutex_owned(&ifd->ifd_lock)); 1318 KASSERT(mutex_owned(&ifd->ifd_qlock)); 1319 KASSERT(hint == NOTE_LOWAT); 1320 1321 kn->kn_data = ifd->ifd_qcount; 1322 } 1323 1324 return kn->kn_data > 0; 1325 } 1326 1327 /* 1328 * Restart the inotify instance. 1329 */ 1330 static void 1331 inotify_restart(file_t *fp) 1332 { 1333 struct inotifyfd *ifd = fp->f_data; 1334 1335 mutex_enter(&ifd->ifd_qlock); 1336 cv_broadcast(&ifd->ifd_qcv); 1337 mutex_exit(&ifd->ifd_qlock); 1338 } 1339