1 /* $NetBSD: linux_inotify.c,v 1.1 2023/08/19 17:57:54 christos 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.1 2023/08/19 17:57:54 christos 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 struct linux_inotify_event ie_event; 88 char ie_name[NAME_MAX+1]; 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 *); 139 static struct inotify_dir_entries *get_inotify_dir_entries(int); 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 SCARG(&kqa, flags) = 0; 296 if (flags & LINUX_IN_NONBLOCK) 297 SCARG(&kqa, flags) |= O_NONBLOCK; 298 error = sys_kqueue1(l, &kqa, retval); 299 if (error != 0) 300 goto leave0; 301 ifd->ifd_kqfd = *retval; 302 303 error = fd_allocfile(&fp, &fd); 304 if (error != 0) 305 goto leave1; 306 307 fp->f_flag = FREAD; 308 if (flags & LINUX_IN_NONBLOCK) 309 fp->f_flag |= FNONBLOCK; 310 fp->f_type = DTYPE_MISC; 311 fp->f_ops = &inotify_fileops; 312 fp->f_data = ifd; 313 fd_set_exclose(l, fd, (flags & LINUX_IN_CLOEXEC) != 0); 314 fd_affix(p, fp, fd); 315 316 *retval = fd; 317 return 0; 318 319 leave1: 320 KASSERT(fd_getfile(ifd->ifd_kqfd) != NULL); 321 fd_close(ifd->ifd_kqfd); 322 leave0: 323 kmem_free(ifd->ifd_wds, ifd->ifd_nwds * sizeof(*ifd->ifd_wds)); 324 kmem_free(ifd, sizeof(*ifd)); 325 326 mutex_destroy(&ifd->ifd_lock); 327 mutex_destroy(&ifd->ifd_qlock); 328 cv_destroy(&ifd->ifd_qcv); 329 seldestroy(&ifd->ifd_sel); 330 331 return error; 332 } 333 334 /* 335 * inotify_init(2). Initialize a new inotify fd with flags=0. 336 */ 337 int 338 linux_sys_inotify_init(struct lwp *l, const void *v, register_t *retval) 339 { 340 return do_inotify_init(l, retval, 0); 341 } 342 343 /* 344 * inotify_init(2). Initialize a new inotify fd with the given flags. 345 */ 346 int 347 linux_sys_inotify_init1(struct lwp *l, 348 const struct linux_sys_inotify_init1_args *uap, register_t *retval) 349 { 350 /* { 351 syscallarg(int) flags; 352 } */ 353 354 return do_inotify_init(l, retval, SCARG(uap, flags)); 355 } 356 357 /* 358 * Convert inotify mask to the fflags of an equivalent kevent. 359 */ 360 static uint32_t 361 inotify_mask_to_kevent_fflags(uint32_t mask, enum vtype type) 362 { 363 const struct inotify_kevent_mask_pair *type_inotify_to_kevent; 364 uint32_t fflags; 365 size_t i, type_inotify_to_kevent_len; 366 367 switch (type) { 368 case VREG: 369 case VDIR: 370 case VLNK: 371 break; 372 373 default: 374 return 0; 375 } 376 377 /* flags that all watches could have */ 378 fflags = NOTE_DELETE|NOTE_REVOKE; 379 for (i = 0; i < common_inotify_to_kevent_len; i++) 380 if (mask & common_inotify_to_kevent[i].inotify) 381 fflags |= common_inotify_to_kevent[i].kevent; 382 383 /* flags that depend on type */ 384 switch (type) { 385 case VREG: 386 type_inotify_to_kevent = vreg_inotify_to_kevent; 387 type_inotify_to_kevent_len = vreg_inotify_to_kevent_len; 388 break; 389 390 case VDIR: 391 type_inotify_to_kevent = vdir_inotify_to_kevent; 392 type_inotify_to_kevent_len = vdir_inotify_to_kevent_len; 393 break; 394 395 default: 396 type_inotify_to_kevent_len = 0; 397 break; 398 } 399 for (i = 0; i < type_inotify_to_kevent_len; i++) 400 if (mask & type_inotify_to_kevent[i].inotify) 401 fflags |= type_inotify_to_kevent[i].kevent; 402 403 return fflags; 404 } 405 406 /* 407 * inotify_add_watch(2). Open a fd for pathname (if desired by mask) 408 * track it and add an equivalent kqueue event for it in 409 * ifd->ifd_kqfd. 410 */ 411 int 412 linux_sys_inotify_add_watch(struct lwp *l, 413 const struct linux_sys_inotify_add_watch_args *uap, register_t *retval) 414 { 415 /* { 416 syscallarg(int) fd; 417 syscallarg(const char *) pathname; 418 syscallarg(uint32_t) mask; 419 } */ 420 int wd, dup_of_wd, i, error = 0; 421 file_t *fp, *wp, *cur_fp; 422 struct stat wst, cur_st; 423 struct inotifyfd *ifd; 424 struct inotify_dir_entries **new_wds; 425 struct knote *kn, *tmpkn; 426 struct sys_open_args oa; 427 struct kevent kev; 428 enum vtype wtype; 429 struct kevent_ops k_ops = { 430 .keo_private = NULL, 431 .keo_fetch_timeout = NULL, 432 .keo_fetch_changes = inotify_kev_fetch_changes, 433 .keo_put_events = NULL, 434 }; 435 const int fd = SCARG(uap, fd); 436 const uint32_t mask = SCARG(uap, mask); 437 438 if (mask & ~LINUX_IN_ADD_KNOWN) 439 return EINVAL; 440 441 fp = fd_getfile(fd); 442 if (fp == NULL) 443 return EBADF; 444 445 if (fp->f_ops != &inotify_fileops) { 446 /* not an inotify fd */ 447 error = EBADF; 448 goto leave0; 449 } 450 451 ifd = fp->f_data; 452 453 mutex_enter(&ifd->ifd_lock); 454 455 /* open a new file descriptor for the watch descriptor */ 456 SCARG(&oa, path) = SCARG(uap, pathname); 457 SCARG(&oa, mode) = 0; 458 SCARG(&oa, flags) = O_RDONLY; 459 if (mask & LINUX_IN_DONT_FOLLOW) 460 SCARG(&oa, flags) |= O_NOFOLLOW; 461 if (mask & LINUX_IN_ONLYDIR) 462 SCARG(&oa, flags) |= O_DIRECTORY; 463 464 error = sys_open(l, &oa, retval); 465 if (error != 0) 466 goto leave1; 467 wd = *retval; 468 469 wp = fd_getfile(wd); 470 KASSERT(wp != NULL); 471 wtype = wp->f_vnode->v_type; 472 error = vn_stat(wp->f_vnode, &wst); 473 fd_putfile(wd); 474 if (error != 0) 475 goto leave1; 476 477 /* translate the flags */ 478 memset(&kev, 0, sizeof(kev)); 479 EV_SET(&kev, wd, inotify_filtid, EV_ADD|EV_ENABLE, 480 NOTE_DELETE|NOTE_REVOKE, 0, ifd); 481 if (mask & LINUX_IN_ONESHOT) 482 kev.flags |= EV_ONESHOT; 483 kev.fflags |= inotify_mask_to_kevent_fflags(mask, wtype); 484 485 /* Check to see if we already have a descriptor to wd's file. */ 486 dup_of_wd = -1; 487 for (i = 0; i < ifd->ifd_nwds; i++) { 488 if (ifd->ifd_wds[i] != NULL) { 489 cur_fp = fd_getfile(i); 490 if (cur_fp == NULL) { 491 DPRINTF(("%s: wd=%d was closed externally\n", 492 __func__, i)); 493 error = EBADF; 494 goto leave1; 495 } 496 if (cur_fp->f_type != DTYPE_VNODE) { 497 DPRINTF(("%s: wd=%d was replaced " 498 "with a non-vnode\n", __func__, i)); 499 error = EBADF; 500 } 501 if (error == 0) 502 error = vn_stat(cur_fp->f_vnode, &cur_st); 503 fd_putfile(i); 504 if (error != 0) 505 goto leave1; 506 507 if (wst.st_ino == cur_st.st_ino) { 508 dup_of_wd = i; 509 break; 510 } 511 } 512 } 513 514 if (dup_of_wd != -1) { 515 /* 516 * If we do not have a descriptor to wd's file, we need to add 517 * a knote. 518 */ 519 error = kevent1(retval, ifd->ifd_kqfd, &kev, 1, NULL, 0, NULL, 520 &k_ops); 521 if (error != 0) { 522 KASSERT(fd_getfile(wd) != NULL); 523 fd_close(wd); 524 } else { 525 /* Success! */ 526 *retval = wd; 527 528 /* Resize ifd_nwds to accomodate wd. */ 529 if (wd+1 > ifd->ifd_nwds) { 530 new_wds = kmem_zalloc( 531 (wd+1) * sizeof(*ifd->ifd_wds), KM_SLEEP); 532 memcpy(new_wds, ifd->ifd_wds, 533 ifd->ifd_nwds * sizeof(*ifd->ifd_wds)); 534 535 kmem_free(ifd->ifd_wds, 536 ifd->ifd_nwds * sizeof(*ifd->ifd_wds)); 537 538 ifd->ifd_wds = new_wds; 539 ifd->ifd_nwds = wd+1; 540 } 541 542 ifd->ifd_wds[wd] = get_inotify_dir_entries(wd); 543 } 544 } else { 545 /* 546 * If we do have a descriptor to wd's file, try to edit 547 * the relevant knote. 548 */ 549 550 /* We do not need wd anymore. */ 551 fd_getfile(wd); 552 fd_close(wd); 553 554 if (mask & LINUX_IN_MASK_CREATE) { 555 error = EEXIST; 556 goto leave1; 557 } 558 559 wp = fd_getfile(dup_of_wd); 560 if (wp == NULL) { 561 DPRINTF(("%s: wd=%d was closed externally " 562 "(race, probably)\n", __func__, dup_of_wd)); 563 error = EBADF; 564 goto leave1; 565 } 566 567 mutex_enter(wp->f_vnode->v_interlock); 568 569 /* 570 * XXX We are forced to find the appropriate knote 571 * manually because we cannot create a custom f_touch 572 * function for inotify_filtops. See filter_touch() 573 * in kern_event.c for details. 574 */ 575 SLIST_FOREACH_SAFE(kn, &wp->f_vnode->v_klist->vk_klist, 576 kn_selnext, tmpkn) { 577 if (kn->kn_fop == &inotify_filtops 578 && ifd == kn->kn_kevent.udata) { 579 mutex_enter(&kn->kn_kq->kq_lock); 580 if (mask & LINUX_IN_MASK_ADD) 581 kn->kn_sfflags |= kev.fflags; 582 else 583 kn->kn_sfflags = kev.fflags; 584 wp->f_vnode->v_klist->vk_interest |= 585 kn->kn_sfflags; 586 mutex_exit(&kn->kn_kq->kq_lock); 587 } 588 } 589 590 mutex_exit(wp->f_vnode->v_interlock); 591 fd_putfile(dup_of_wd); 592 } 593 594 leave1: 595 mutex_exit(&ifd->ifd_lock); 596 leave0: 597 fd_putfile(fd); 598 return error; 599 } 600 601 /* 602 * Remove a wd from ifd and close wd. 603 */ 604 static int 605 inotify_close_wd(struct inotifyfd *ifd, int wd) 606 { 607 file_t *wp; 608 int error; 609 register_t retval; 610 struct kevent kev; 611 struct kevent_ops k_ops = { 612 .keo_private = NULL, 613 .keo_fetch_timeout = NULL, 614 .keo_fetch_changes = inotify_kev_fetch_changes, 615 .keo_put_events = NULL, 616 }; 617 618 mutex_enter(&ifd->ifd_lock); 619 620 KASSERT(0 <= wd && wd < ifd->ifd_nwds && ifd->ifd_wds[wd] != NULL); 621 622 kmem_free(ifd->ifd_wds[wd], 623 INOTIFY_DIR_ENTRIES_SIZE(ifd->ifd_wds[wd]->ide_count)); 624 ifd->ifd_wds[wd] = NULL; 625 626 mutex_exit(&ifd->ifd_lock); 627 628 wp = fd_getfile(wd); 629 if (wp == NULL) { 630 DPRINTF(("%s: wd=%d is already closed\n", __func__, wd)); 631 return 0; 632 } 633 KASSERT(!mutex_owned(wp->f_vnode->v_interlock)); 634 635 memset(&kev, 0, sizeof(kev)); 636 EV_SET(&kev, wd, EVFILT_VNODE, EV_DELETE, 0, 0, 0); 637 error = kevent1(&retval, ifd->ifd_kqfd, &kev, 1, NULL, 0, NULL, &k_ops); 638 if (error != 0) 639 DPRINTF(("%s: attempt to disable all events for wd=%d " 640 "had error=%d\n", __func__, wd, error)); 641 642 return fd_close(wd); 643 } 644 645 /* 646 * inotify_rm_watch(2). Close wd and remove it from ifd->ifd_wds. 647 */ 648 int 649 linux_sys_inotify_rm_watch(struct lwp *l, 650 const struct linux_sys_inotify_rm_watch_args *uap, register_t *retval) 651 { 652 /* { 653 syscallarg(int) fd; 654 syscallarg(int) wd; 655 } */ 656 struct inotifyfd *ifd; 657 file_t *fp; 658 int error = 0; 659 const int fd = SCARG(uap, fd); 660 const int wd = SCARG(uap, wd); 661 662 fp = fd_getfile(fd); 663 if (fp == NULL) 664 return EBADF; 665 if (fp->f_ops != &inotify_fileops) { 666 /* not an inotify fd */ 667 error = EINVAL; 668 goto leave; 669 } 670 671 ifd = fp->f_data; 672 if (wd < 0 || wd >= ifd->ifd_nwds || ifd->ifd_wds[wd] == NULL) { 673 error = EINVAL; 674 goto leave; 675 } 676 677 error = inotify_close_wd(ifd, wd); 678 679 leave: 680 fd_putfile(fd); 681 return error; 682 } 683 684 /* 685 * Attach the inotify filter. 686 */ 687 static int 688 inotify_filt_attach(struct knote *kn) 689 { 690 file_t *fp = kn->kn_obj; 691 struct vnode *vp; 692 693 KASSERT(fp->f_type == DTYPE_VNODE); 694 vp = fp->f_vnode; 695 696 /* 697 * Needs to be set so that we get the same event handling as 698 * EVFILT_VNODE. Otherwise we don't get any events. 699 * 700 * A consequence of this is that modifications/removals of 701 * this knote need to specify EVFILT_VNODE rather than 702 * inotify_filtid. 703 */ 704 kn->kn_filter = EVFILT_VNODE; 705 706 kn->kn_fop = &inotify_filtops; 707 kn->kn_hook = vp; 708 vn_knote_attach(vp, kn); 709 710 return 0; 711 } 712 713 /* 714 * Detach the inotify filter. 715 */ 716 static void 717 inotify_filt_detach(struct knote *kn) 718 { 719 struct vnode *vp = (struct vnode *)kn->kn_hook; 720 721 vn_knote_detach(vp, kn); 722 } 723 724 /* 725 * Create a single inotify event. 726 */ 727 static void 728 do_kevent_to_inotify(int32_t wd, uint32_t mask, uint32_t cookie, 729 struct inotify_entry *buf, size_t *nbuf, char *name) 730 { 731 KASSERT(*nbuf < LINUX_INOTIFY_MAX_FROM_KEVENT); 732 733 buf += *nbuf; 734 735 memset(buf, 0, sizeof(*buf)); 736 737 buf->ie_event.wd = wd; 738 buf->ie_event.mask = mask; 739 buf->ie_event.cookie = cookie; 740 741 if (name != NULL) { 742 buf->ie_event.len = strlen(name) + 1; 743 KASSERT(buf->ie_event.len < sizeof(buf->ie_name)); 744 strcpy(buf->ie_name, name); 745 } 746 747 ++(*nbuf); 748 } 749 750 /* 751 * Like vn_readdir(), but with vnode locking that depends on if we already have 752 * v_interlock (to avoid double locking in some situations). 753 */ 754 static int 755 inotify_readdir(file_t *fp, struct dirent *dep, int *done) 756 { 757 struct vnode *vp; 758 struct iovec iov; 759 struct uio uio; 760 int error, eofflag; 761 762 KASSERT(fp->f_type == DTYPE_VNODE); 763 vp = fp->f_vnode; 764 KASSERT(vp->v_type == VDIR); 765 766 iov.iov_base = dep; 767 iov.iov_len = sizeof(*dep); 768 769 uio.uio_iov = &iov; 770 uio.uio_iovcnt = 1; 771 uio.uio_rw = UIO_READ; 772 uio.uio_resid = sizeof(*dep); 773 UIO_SETUP_SYSSPACE(&uio); 774 775 mutex_enter(&fp->f_lock); 776 uio.uio_offset = fp->f_offset; 777 mutex_exit(&fp->f_lock); 778 779 /* XXX: should pass whether to lock or not */ 780 if (!mutex_owned(vp->v_interlock)) 781 vn_lock(vp, LK_SHARED | LK_RETRY); 782 error = VOP_READDIR(vp, &uio, fp->f_cred, &eofflag, NULL, NULL); 783 if (!mutex_owned(vp->v_interlock)) 784 VOP_UNLOCK(vp); 785 786 mutex_enter(&fp->f_lock); 787 fp->f_offset = uio.uio_offset; 788 mutex_exit(&fp->f_lock); 789 790 *done = sizeof(*dep) - uio.uio_resid; 791 return error; 792 } 793 794 /* 795 * Create (and allocate) an appropriate inotify_dir_entries struct for wd to be 796 * used on ifd_wds of inotifyfd. If the entries on a directory fail to be read, 797 * NULL is returned. 798 */ 799 static struct inotify_dir_entries * 800 get_inotify_dir_entries(int wd) 801 { 802 struct dirent de; 803 struct dirent *currdep; 804 struct inotify_dir_entries *idep = NULL; 805 file_t *wp; 806 int done, error; 807 size_t i, decount; 808 809 wp = fd_getfile(wd); 810 if (wp == NULL) 811 return NULL; 812 if (wp->f_type != DTYPE_VNODE) 813 goto leave; 814 815 /* for non-directories, we have 0 entries. */ 816 if (wp->f_vnode->v_type != VDIR) { 817 idep = kmem_zalloc(INOTIFY_DIR_ENTRIES_SIZE(0), KM_SLEEP); 818 goto leave; 819 } 820 821 mutex_enter(&wp->f_lock); 822 wp->f_offset = 0; 823 mutex_exit(&wp->f_lock); 824 decount = 0; 825 for (;;) { 826 error = inotify_readdir(wp, &de, &done); 827 if (error != 0) 828 goto leave; 829 if (done == 0) 830 break; 831 832 currdep = &de; 833 while ((char *)currdep < ((char *)&de) + done) { 834 decount++; 835 currdep = _DIRENT_NEXT(currdep); 836 } 837 } 838 839 idep = kmem_zalloc(INOTIFY_DIR_ENTRIES_SIZE(decount), KM_SLEEP); 840 idep->ide_count = decount; 841 842 mutex_enter(&wp->f_lock); 843 wp->f_offset = 0; 844 mutex_exit(&wp->f_lock); 845 for (i = 0; i < decount;) { 846 error = inotify_readdir(wp, &de, &done); 847 if (error != 0 || done == 0) { 848 kmem_free(idep, INOTIFY_DIR_ENTRIES_SIZE(decount)); 849 idep = NULL; 850 goto leave; 851 } 852 853 currdep = &de; 854 while ((char *)currdep < ((char *)&de) + done) { 855 idep->ide_entries[i].fileno = currdep->d_fileno; 856 strcpy(idep->ide_entries[i].name, currdep->d_name); 857 858 currdep = _DIRENT_NEXT(currdep); 859 i++; 860 } 861 } 862 863 leave: 864 fd_putfile(wd); 865 return idep; 866 } 867 868 static size_t 869 find_entry(struct inotify_dir_entries *i1, struct inotify_dir_entries *i2) 870 { 871 for (size_t i = 0; i < i2->ide_count; i++) 872 if (i2->ide_entries[i].fileno != i1->ide_entries[i].fileno) 873 return i; 874 KASSERTMSG(0, "Entry not found"); 875 return -1; 876 } 877 878 static void 879 handle_write(struct inotifyfd *ifd, int wd, struct inotify_entry *buf, 880 size_t *nbuf) 881 { 882 struct inotify_dir_entries *old_idep, *new_idep; 883 size_t i; 884 885 mutex_enter(&ifd->ifd_lock); 886 887 old_idep = ifd->ifd_wds[wd]; 888 KASSERT(old_idep != NULL); 889 new_idep = get_inotify_dir_entries(wd); 890 if (new_idep == NULL) { 891 DPRINTF(("%s: directory for wd=%d could not be read\n", 892 __func__, wd)); 893 mutex_exit(&ifd->ifd_lock); 894 return; 895 } 896 897 898 if (old_idep->ide_count < new_idep->ide_count) { 899 KASSERT(old_idep->ide_count + 1 == new_idep->ide_count); 900 901 /* Find the new entry. */ 902 i = find_entry(new_idep, old_idep); 903 do_kevent_to_inotify(wd, LINUX_IN_CREATE, 0, 904 buf, nbuf, new_idep->ide_entries[i].name); 905 goto out; 906 } 907 908 if (old_idep->ide_count > new_idep->ide_count) { 909 KASSERT(old_idep->ide_count == new_idep->ide_count + 1); 910 911 /* Find the deleted entry. */ 912 i = find_entry(old_idep, new_idep); 913 914 do_kevent_to_inotify(wd, LINUX_IN_DELETE, 0, 915 buf, nbuf, old_idep->ide_entries[i].name); 916 goto out; 917 } 918 919 /* 920 * XXX Because we are not watching the entire 921 * file system, the only time we know for sure 922 * that the event is a LINUX_IN_MOVED_FROM/ 923 * LINUX_IN_MOVED_TO is when the move happens 924 * within a single directory... ie. the number 925 * of directory entries has not changed. 926 * 927 * Otherwise all we can say for sure is that 928 * something was created/deleted. So we issue a 929 * LINUX_IN_CREATE/LINUX_IN_DELETE. 930 */ 931 ino_t changed = new_idep->ide_entries[new_idep->ide_count - 1].fileno; 932 933 /* Find the deleted entry. */ 934 for (i = 0; i < old_idep->ide_count; i++) 935 if (old_idep->ide_entries[i].fileno == changed) 936 break; 937 KASSERT(i != old_idep->ide_count); 938 939 do_kevent_to_inotify(wd, LINUX_IN_MOVED_FROM, changed, buf, nbuf, 940 old_idep->ide_entries[i].name); 941 942 do_kevent_to_inotify(wd, LINUX_IN_MOVED_TO, changed, buf, nbuf, 943 new_idep->ide_entries[new_idep->ide_count - 1].name); 944 945 out: 946 ifd->ifd_wds[wd] = new_idep; 947 mutex_exit(&ifd->ifd_lock); 948 } 949 950 /* 951 * Convert a kevent flags and fflags for EVFILT_VNODE to some number 952 * of inotify events. 953 */ 954 static int 955 kevent_to_inotify(struct inotifyfd *ifd, int wd, enum vtype wtype, 956 uint32_t flags, uint32_t fflags, struct inotify_entry *buf, 957 size_t *nbuf) 958 { 959 struct stat st; 960 file_t *wp; 961 size_t i; 962 int error = 0; 963 964 for (i = 0; i < common_kevent_to_inotify_len; i++) 965 if (fflags & common_kevent_to_inotify[i].kevent) 966 do_kevent_to_inotify(wd, 967 common_kevent_to_inotify[i].inotify, 0, buf, nbuf, 968 NULL); 969 970 if (wtype == VREG) { 971 for (i = 0; i < vreg_kevent_to_inotify_len; i++) 972 if (fflags & vreg_kevent_to_inotify[i].kevent) 973 do_kevent_to_inotify(wd, 974 vreg_kevent_to_inotify[i].inotify, 0, 975 buf, nbuf, NULL); 976 } else if (wtype == VDIR) { 977 for (i = 0; i < *nbuf; i++) 978 if (buf[i].ie_event.mask & 979 (LINUX_IN_ACCESS|LINUX_IN_ATTRIB 980 |LINUX_IN_CLOSE|LINUX_IN_OPEN)) 981 buf[i].ie_event.mask |= LINUX_IN_ISDIR; 982 983 /* Need to disambiguate the possible NOTE_WRITEs. */ 984 if (fflags & NOTE_WRITE) 985 handle_write(ifd, wd, buf, nbuf); 986 } 987 988 /* 989 * Need to check if wd is actually has a link count of 0 to issue a 990 * LINUX_IN_DELETE_SELF. 991 */ 992 if (fflags & NOTE_DELETE) { 993 wp = fd_getfile(wd); 994 KASSERT(wp != NULL); 995 KASSERT(wp->f_type == DTYPE_VNODE); 996 vn_stat(wp->f_vnode, &st); 997 fd_putfile(wd); 998 999 if (st.st_nlink == 0) 1000 do_kevent_to_inotify(wd, LINUX_IN_DELETE_SELF, 0, 1001 buf, nbuf, NULL); 1002 } 1003 1004 /* LINUX_IN_IGNORED must be the last event issued for wd. */ 1005 if ((flags & EV_ONESHOT) || (fflags & (NOTE_REVOKE|NOTE_DELETE))) { 1006 do_kevent_to_inotify(wd, LINUX_IN_IGNORED, 0, buf, nbuf, NULL); 1007 /* 1008 * XXX in theory we could call inotify_close_wd(ifd, wd) but if 1009 * we get here we must already be holding v_interlock for 1010 * wd... so we can't. 1011 * 1012 * For simplicity we do nothing, and so wd will only be closed 1013 * when the inotify fd is closed. 1014 */ 1015 } 1016 1017 return error; 1018 } 1019 1020 /* 1021 * Handle an event. Unlike EVFILT_VNODE, we translate the event to a 1022 * linux_inotify_event and put it in our own custom queue. 1023 */ 1024 static int 1025 inotify_filt_event(struct knote *kn, long hint) 1026 { 1027 struct vnode *vp = (struct vnode *)kn->kn_hook; 1028 struct inotifyfd *ifd; 1029 struct inotify_entry *cur_ie; 1030 size_t nbuf, i; 1031 uint32_t status; 1032 struct inotify_entry buf[LINUX_INOTIFY_MAX_FROM_KEVENT]; 1033 1034 /* 1035 * If KN_WILLDETACH is set then 1036 * 1. kn->kn_kevent.udata has already been trashed with a 1037 * struct lwp *, so we don't have access to a real ifd 1038 * anymore, and 1039 * 2. we're about to detach anyways, so we don't really care 1040 * about the events. 1041 * (Also because of this we need to get ifd under the same 1042 * lock as kn->kn_status.) 1043 */ 1044 mutex_enter(&kn->kn_kq->kq_lock); 1045 status = kn->kn_status; 1046 ifd = kn->kn_kevent.udata; 1047 mutex_exit(&kn->kn_kq->kq_lock); 1048 if (status & KN_WILLDETACH) 1049 return 0; 1050 1051 /* 1052 * Because we use kqueue() and file descriptors underneath, 1053 * functions like inotify_add_watch can actually trigger 1054 * events (ie. we're watching for LINUX_IN_OPEN). In all 1055 * cases where this could happen, we must already own 1056 * ifd->ifd_lock, so we can just drop these events. 1057 */ 1058 /* XXX: why do we need this here? */ 1059 if (mutex_owned(&ifd->ifd_lock)) 1060 return 0; 1061 1062 /* 1063 * If we don't care about the NOTEs in hint, we don't generate 1064 * any events. 1065 */ 1066 hint &= kn->kn_sfflags; 1067 if (hint == 0) 1068 return 0; 1069 1070 KASSERT(mutex_owned(vp->v_interlock)); 1071 1072 mutex_enter(&ifd->ifd_qlock); 1073 1074 /* 1075 * early out: there's no point even traslating the event if we 1076 * have nowhere to put it (and an LINUX_IN_Q_OVERFLOW has 1077 * already been added). 1078 */ 1079 if (ifd->ifd_qcount >= LINUX_INOTIFY_MAX_QUEUED) 1080 goto leave; 1081 1082 nbuf = 0; 1083 (void)kevent_to_inotify(ifd, kn->kn_id, vp->v_type, kn->kn_flags, 1084 hint, buf, &nbuf); 1085 for (i = 0; i < nbuf && ifd->ifd_qcount < LINUX_INOTIFY_MAX_QUEUED-1; 1086 i++) { 1087 cur_ie = kmem_zalloc(sizeof(*cur_ie), KM_SLEEP); 1088 memcpy(cur_ie, &buf[i], sizeof(*cur_ie)); 1089 1090 TAILQ_INSERT_TAIL(&ifd->ifd_qhead, cur_ie, ie_entries); 1091 ifd->ifd_qcount++; 1092 } 1093 /* handle early overflow, by adding an overflow event to the end */ 1094 if (i != nbuf) { 1095 nbuf = 0; 1096 cur_ie = kmem_zalloc(sizeof(*cur_ie), KM_SLEEP); 1097 do_kevent_to_inotify(-1, LINUX_IN_Q_OVERFLOW, 0, 1098 cur_ie, &nbuf, NULL); 1099 1100 TAILQ_INSERT_TAIL(&ifd->ifd_qhead, cur_ie, ie_entries); 1101 ifd->ifd_qcount++; 1102 } 1103 1104 if (nbuf > 0) { 1105 cv_signal(&ifd->ifd_qcv); 1106 1107 mutex_enter(&ifd->ifd_lock); 1108 selnotify(&ifd->ifd_sel, 0, 0); 1109 mutex_exit(&ifd->ifd_lock); 1110 } else 1111 DPRINTF(("%s: hint=%lx resulted in 0 inotify events\n", 1112 __func__, hint)); 1113 1114 leave: 1115 mutex_exit(&ifd->ifd_qlock); 1116 return 0; 1117 } 1118 1119 /* 1120 * Read inotify events from the queue. 1121 */ 1122 static int 1123 inotify_read(file_t *fp, off_t *offp, struct uio *uio, kauth_cred_t cred, 1124 int flags) 1125 { 1126 struct inotify_entry *cur_iep; 1127 size_t cur_size, nread; 1128 int error = 0; 1129 struct inotifyfd *ifd = fp->f_data; 1130 1131 mutex_enter(&ifd->ifd_qlock); 1132 1133 if (ifd->ifd_qcount == 0) { 1134 if (fp->f_flag & O_NONBLOCK) { 1135 error = EAGAIN; 1136 goto leave; 1137 } 1138 1139 while (ifd->ifd_qcount == 0) { 1140 /* wait until there is an event to read */ 1141 error = cv_wait_sig(&ifd->ifd_qcv, &ifd->ifd_qlock); 1142 if (error != 0) { 1143 error = EINTR; 1144 goto leave; 1145 } 1146 } 1147 } 1148 1149 KASSERT(ifd->ifd_qcount > 0); 1150 KASSERT(mutex_owned(&ifd->ifd_qlock)); 1151 1152 nread = 0; 1153 while (ifd->ifd_qcount > 0) { 1154 cur_iep = TAILQ_FIRST(&ifd->ifd_qhead); 1155 KASSERT(cur_iep != NULL); 1156 1157 cur_size = sizeof(cur_iep->ie_event) + cur_iep->ie_event.len; 1158 if (cur_size > uio->uio_resid) { 1159 if (nread == 0) 1160 error = EINVAL; 1161 break; 1162 } 1163 1164 error = uiomove(&cur_iep->ie_event, sizeof(cur_iep->ie_event), 1165 uio); 1166 if (error != 0) 1167 break; 1168 error = uiomove(&cur_iep->ie_name, cur_iep->ie_event.len, uio); 1169 if (error != 0) 1170 break; 1171 1172 /* cleanup */ 1173 TAILQ_REMOVE(&ifd->ifd_qhead, cur_iep, ie_entries); 1174 kmem_free(cur_iep, sizeof(*cur_iep)); 1175 1176 nread++; 1177 ifd->ifd_qcount--; 1178 } 1179 1180 leave: 1181 /* Wake up the next reader, if the queue is not empty. */ 1182 if (ifd->ifd_qcount > 0) 1183 cv_signal(&ifd->ifd_qcv); 1184 1185 mutex_exit(&ifd->ifd_qlock); 1186 return error; 1187 } 1188 1189 /* 1190 * Close all the file descriptors associated with fp. 1191 */ 1192 static int 1193 inotify_close(file_t *fp) 1194 { 1195 int error; 1196 size_t i; 1197 file_t *kqfp; 1198 struct inotifyfd *ifd = fp->f_data; 1199 1200 for (i = 0; i < ifd->ifd_nwds; i++) { 1201 if (ifd->ifd_wds[i] != NULL) { 1202 error = inotify_close_wd(ifd, i); 1203 if (error != 0) 1204 return error; 1205 } 1206 } 1207 1208 /* the reference we need to hold is ifd->ifd_kqfp */ 1209 kqfp = fd_getfile(ifd->ifd_kqfd); 1210 if (kqfp == NULL) { 1211 DPRINTF(("%s: kqfp=%d is already closed\n", __func__, 1212 ifd->ifd_kqfd)); 1213 } else { 1214 error = fd_close(ifd->ifd_kqfd); 1215 if (error != 0) 1216 return error; 1217 } 1218 1219 mutex_destroy(&ifd->ifd_lock); 1220 mutex_destroy(&ifd->ifd_qlock); 1221 cv_destroy(&ifd->ifd_qcv); 1222 seldestroy(&ifd->ifd_sel); 1223 1224 kmem_free(ifd->ifd_wds, ifd->ifd_nwds * sizeof(*ifd->ifd_wds)); 1225 kmem_free(ifd, sizeof(*ifd)); 1226 fp->f_data = NULL; 1227 1228 return 0; 1229 } 1230 1231 /* 1232 * Check if there are pending read events. 1233 */ 1234 static int 1235 inotify_poll(file_t *fp, int events) 1236 { 1237 int revents; 1238 struct inotifyfd *ifd = fp->f_data; 1239 1240 revents = 0; 1241 if (events & (POLLIN|POLLRDNORM)) { 1242 mutex_enter(&ifd->ifd_qlock); 1243 1244 if (ifd->ifd_qcount > 0) 1245 revents |= events & (POLLIN|POLLRDNORM); 1246 1247 mutex_exit(&ifd->ifd_qlock); 1248 } 1249 1250 return revents; 1251 } 1252 1253 /* 1254 * Attach EVFILT_READ to the inotify instance in fp. 1255 * 1256 * This is so you can watch inotify with epoll. No other kqueue 1257 * filter needs to be supported. 1258 */ 1259 static int 1260 inotify_kqfilter(file_t *fp, struct knote *kn) 1261 { 1262 struct inotifyfd *ifd = fp->f_data; 1263 1264 KASSERT(fp == kn->kn_obj); 1265 1266 if (kn->kn_filter != EVFILT_READ) 1267 return EINVAL; 1268 1269 kn->kn_fop = &inotify_read_filtops; 1270 mutex_enter(&ifd->ifd_lock); 1271 selrecord_knote(&ifd->ifd_sel, kn); 1272 mutex_exit(&ifd->ifd_lock); 1273 1274 return 0; 1275 } 1276 1277 /* 1278 * Detach a filter from an inotify instance. 1279 */ 1280 static void 1281 inotify_read_filt_detach(struct knote *kn) 1282 { 1283 struct inotifyfd *ifd = ((file_t *)kn->kn_obj)->f_data; 1284 1285 mutex_enter(&ifd->ifd_lock); 1286 selremove_knote(&ifd->ifd_sel, kn); 1287 mutex_exit(&ifd->ifd_lock); 1288 } 1289 1290 /* 1291 * Handle EVFILT_READ events. Note that nothing is put in kn_data. 1292 */ 1293 static int 1294 inotify_read_filt_event(struct knote *kn, long hint) 1295 { 1296 int rv; 1297 struct inotifyfd *ifd = ((file_t *)kn->kn_obj)->f_data; 1298 1299 mutex_enter(&ifd->ifd_qlock); 1300 rv = (ifd->ifd_qcount > 0); 1301 mutex_exit(&ifd->ifd_qlock); 1302 1303 return rv; 1304 } 1305 1306 /* 1307 * Restart the inotify instance. 1308 */ 1309 static void 1310 inotify_restart(file_t *fp) 1311 { 1312 struct inotifyfd *ifd = fp->f_data; 1313 1314 mutex_enter(&ifd->ifd_qlock); 1315 cv_broadcast(&ifd->ifd_qcv); 1316 mutex_exit(&ifd->ifd_qlock); 1317 } 1318