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