Blame view
fs/inotify.c
19.3 KB
0eeca2830
|
1 2 3 4 5 6 7 |
/* * fs/inotify.c - inode-based file event notifications * * Authors: * John McCutchan <ttb@tentacle.dhs.org> * Robert Love <rml@novell.com> * |
2d9048e20
|
8 9 |
* Kernel API added by: Amy Griffis <amy.griffis@hp.com> * |
0eeca2830
|
10 |
* Copyright (C) 2005 John McCutchan |
2d9048e20
|
11 |
* Copyright 2006 Hewlett-Packard Development Company, L.P. |
0eeca2830
|
12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
* * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. */ #include <linux/module.h> #include <linux/kernel.h> |
0eeca2830
|
26 27 28 29 |
#include <linux/spinlock.h> #include <linux/idr.h> #include <linux/slab.h> #include <linux/fs.h> |
914e26379
|
30 |
#include <linux/sched.h> |
0eeca2830
|
31 32 33 34 |
#include <linux/init.h> #include <linux/list.h> #include <linux/writeback.h> #include <linux/inotify.h> |
0eeca2830
|
35 36 |
static atomic_t inotify_cookie; |
0eeca2830
|
37 38 39 40 |
/* * Lock ordering: * * dentry->d_lock (used to keep d_move() away from dentry->d_parent) |
f24075bd0
|
41 |
* iprune_mutex (synchronize shrink_icache_memory()) |
0eeca2830
|
42 |
* inode_lock (protects the super_block->s_inodes list) |
d4f9af9da
|
43 |
* inode->inotify_mutex (protects inode->inotify_watches and watches->i_list) |
2d9048e20
|
44 45 46 47 48 49 |
* inotify_handle->mutex (protects inotify_handle and watches->h_list) * * The inode->inotify_mutex and inotify_handle->mutex and held during execution * of a caller's event handler. Thus, the caller must not hold any locks * taken in their event handler while calling any of the published inotify * interfaces. |
0eeca2830
|
50 51 52 |
*/ /* |
2d9048e20
|
53 |
* Lifetimes of the three main data structures--inotify_handle, inode, and |
0eeca2830
|
54 55 |
* inotify_watch--are managed by reference count. * |
2d9048e20
|
56 57 58 |
* inotify_handle: Lifetime is from inotify_init() to inotify_destroy(). * Additional references can bump the count via get_inotify_handle() and drop * the count via put_inotify_handle(). |
0eeca2830
|
59 |
* |
2d9048e20
|
60 61 62 63 64 65 |
* inotify_watch: for inotify's purposes, lifetime is from inotify_add_watch() * to remove_watch_no_event(). Additional references can bump the count via * get_inotify_watch() and drop the count via put_inotify_watch(). The caller * is reponsible for the final put after receiving IN_IGNORED, or when using * IN_ONESHOT after receiving the first event. Inotify does the final put if * inotify_destroy() is called. |
0eeca2830
|
66 67 |
* * inode: Pinned so long as the inode is associated with a watch, from |
2d9048e20
|
68 |
* inotify_add_watch() to the final put_inotify_watch(). |
0eeca2830
|
69 70 71 |
*/ /* |
2d9048e20
|
72 |
* struct inotify_handle - represents an inotify instance |
0eeca2830
|
73 |
* |
d4f9af9da
|
74 |
* This structure is protected by the mutex 'mutex'. |
0eeca2830
|
75 |
*/ |
2d9048e20
|
76 |
struct inotify_handle { |
0eeca2830
|
77 |
struct idr idr; /* idr mapping wd -> watch */ |
d4f9af9da
|
78 |
struct mutex mutex; /* protects this bad boy */ |
0eeca2830
|
79 80 |
struct list_head watches; /* list of watches */ atomic_t count; /* reference count */ |
b9c55d29e
|
81 |
u32 last_wd; /* the last wd allocated */ |
2d9048e20
|
82 |
const struct inotify_operations *in_ops; /* inotify caller operations */ |
0eeca2830
|
83 |
}; |
2d9048e20
|
84 |
static inline void get_inotify_handle(struct inotify_handle *ih) |
0eeca2830
|
85 |
{ |
2d9048e20
|
86 |
atomic_inc(&ih->count); |
0eeca2830
|
87 |
} |
2d9048e20
|
88 |
static inline void put_inotify_handle(struct inotify_handle *ih) |
0eeca2830
|
89 |
{ |
2d9048e20
|
90 91 92 |
if (atomic_dec_and_test(&ih->count)) { idr_destroy(&ih->idr); kfree(ih); |
0eeca2830
|
93 94 |
} } |
2d9048e20
|
95 96 97 98 99 |
/** * get_inotify_watch - grab a reference to an inotify_watch * @watch: watch to grab */ void get_inotify_watch(struct inotify_watch *watch) |
0eeca2830
|
100 101 102 |
{ atomic_inc(&watch->count); } |
2d9048e20
|
103 |
EXPORT_SYMBOL_GPL(get_inotify_watch); |
0eeca2830
|
104 |
|
2d9048e20
|
105 |
/** |
0eeca2830
|
106 |
* put_inotify_watch - decrements the ref count on a given watch. cleans up |
2d9048e20
|
107 108 109 |
* watch references if the count reaches zero. inotify_watch is freed by * inotify callers via the destroy_watch() op. * @watch: watch to release |
0eeca2830
|
110 |
*/ |
2d9048e20
|
111 |
void put_inotify_watch(struct inotify_watch *watch) |
0eeca2830
|
112 113 |
{ if (atomic_dec_and_test(&watch->count)) { |
2d9048e20
|
114 |
struct inotify_handle *ih = watch->ih; |
0eeca2830
|
115 |
|
2d9048e20
|
116 117 118 |
iput(watch->inode); ih->in_ops->destroy_watch(watch); put_inotify_handle(ih); |
0eeca2830
|
119 120 |
} } |
2d9048e20
|
121 |
EXPORT_SYMBOL_GPL(put_inotify_watch); |
0eeca2830
|
122 123 |
/* |
2d9048e20
|
124 |
* inotify_handle_get_wd - returns the next WD for use by the given handle |
0eeca2830
|
125 |
* |
2d9048e20
|
126 |
* Callers must hold ih->mutex. This function can sleep. |
0eeca2830
|
127 |
*/ |
2d9048e20
|
128 129 |
static int inotify_handle_get_wd(struct inotify_handle *ih, struct inotify_watch *watch) |
0eeca2830
|
130 131 132 133 |
{ int ret; do { |
2d9048e20
|
134 |
if (unlikely(!idr_pre_get(&ih->idr, GFP_KERNEL))) |
0eeca2830
|
135 |
return -ENOSPC; |
2d9048e20
|
136 |
ret = idr_get_new_above(&ih->idr, watch, ih->last_wd+1, &watch->wd); |
0eeca2830
|
137 |
} while (ret == -EAGAIN); |
2d9048e20
|
138 139 |
if (likely(!ret)) ih->last_wd = watch->wd; |
0eeca2830
|
140 |
|
2d9048e20
|
141 |
return ret; |
0eeca2830
|
142 143 144 |
} /* |
c32ccd87b
|
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
* inotify_inode_watched - returns nonzero if there are watches on this inode * and zero otherwise. We call this lockless, we do not care if we race. */ static inline int inotify_inode_watched(struct inode *inode) { return !list_empty(&inode->inotify_watches); } /* * Get child dentry flag into synch with parent inode. * Flag should always be clear for negative dentrys. */ static void set_dentry_child_flags(struct inode *inode, int watched) { struct dentry *alias; spin_lock(&dcache_lock); list_for_each_entry(alias, &inode->i_dentry, d_alias) { struct dentry *child; list_for_each_entry(child, &alias->d_subdirs, d_u.d_child) { if (!child->d_inode) { WARN_ON(child->d_flags & DCACHE_INOTIFY_PARENT_WATCHED); continue; } spin_lock(&child->d_lock); if (watched) { WARN_ON(child->d_flags & DCACHE_INOTIFY_PARENT_WATCHED); child->d_flags |= DCACHE_INOTIFY_PARENT_WATCHED; } else { WARN_ON(!(child->d_flags & DCACHE_INOTIFY_PARENT_WATCHED)); child->d_flags&=~DCACHE_INOTIFY_PARENT_WATCHED; } spin_unlock(&child->d_lock); } } spin_unlock(&dcache_lock); } /* |
2d9048e20
|
187 188 |
* inotify_find_handle - find the watch associated with the given inode and * handle |
0eeca2830
|
189 |
* |
d4f9af9da
|
190 |
* Callers must hold inode->inotify_mutex. |
0eeca2830
|
191 |
*/ |
2d9048e20
|
192 193 |
static struct inotify_watch *inode_find_handle(struct inode *inode, struct inotify_handle *ih) |
0eeca2830
|
194 195 196 197 |
{ struct inotify_watch *watch; list_for_each_entry(watch, &inode->inotify_watches, i_list) { |
2d9048e20
|
198 |
if (watch->ih == ih) |
0eeca2830
|
199 200 201 202 203 204 205 |
return watch; } return NULL; } /* |
3ca10067f
|
206 |
* remove_watch_no_event - remove watch without the IN_IGNORED event. |
2d9048e20
|
207 208 |
* * Callers must hold both inode->inotify_mutex and ih->mutex. |
0eeca2830
|
209 210 |
*/ static void remove_watch_no_event(struct inotify_watch *watch, |
2d9048e20
|
211 |
struct inotify_handle *ih) |
0eeca2830
|
212 213 |
{ list_del(&watch->i_list); |
2d9048e20
|
214 |
list_del(&watch->h_list); |
0eeca2830
|
215 |
|
c32ccd87b
|
216 217 |
if (!inotify_inode_watched(watch->inode)) set_dentry_child_flags(watch->inode, 0); |
2d9048e20
|
218 |
idr_remove(&ih->idr, watch->wd); |
0eeca2830
|
219 |
} |
3ca10067f
|
220 221 222 223 224 225 |
/** * inotify_remove_watch_locked - Remove a watch from both the handle and the * inode. Sends the IN_IGNORED event signifying that the inode is no longer * watched. May be invoked from a caller's event handler. * @ih: inotify handle associated with watch * @watch: watch to remove |
0eeca2830
|
226 |
* |
2d9048e20
|
227 |
* Callers must hold both inode->inotify_mutex and ih->mutex. |
0eeca2830
|
228 |
*/ |
3ca10067f
|
229 230 |
void inotify_remove_watch_locked(struct inotify_handle *ih, struct inotify_watch *watch) |
0eeca2830
|
231 |
{ |
2d9048e20
|
232 |
remove_watch_no_event(watch, ih); |
7c2977228
|
233 |
ih->in_ops->handle_event(watch, watch->wd, IN_IGNORED, 0, NULL, NULL); |
0eeca2830
|
234 |
} |
3ca10067f
|
235 |
EXPORT_SYMBOL_GPL(inotify_remove_watch_locked); |
0eeca2830
|
236 |
|
2d9048e20
|
237 |
/* Kernel API for producing events */ |
c32ccd87b
|
238 |
|
0eeca2830
|
239 |
/* |
c32ccd87b
|
240 |
* inotify_d_instantiate - instantiate dcache entry for inode |
0eeca2830
|
241 |
*/ |
c32ccd87b
|
242 |
void inotify_d_instantiate(struct dentry *entry, struct inode *inode) |
0eeca2830
|
243 |
{ |
c32ccd87b
|
244 245 246 247 248 249 250 251 |
struct dentry *parent; if (!inode) return; WARN_ON(entry->d_flags & DCACHE_INOTIFY_PARENT_WATCHED); spin_lock(&entry->d_lock); parent = entry->d_parent; |
091e881d0
|
252 |
if (parent->d_inode && inotify_inode_watched(parent->d_inode)) |
c32ccd87b
|
253 254 |
entry->d_flags |= DCACHE_INOTIFY_PARENT_WATCHED; spin_unlock(&entry->d_lock); |
0eeca2830
|
255 |
} |
c32ccd87b
|
256 257 258 259 260 261 262 263 264 265 266 267 268 |
/* * inotify_d_move - dcache entry has been moved */ void inotify_d_move(struct dentry *entry) { struct dentry *parent; parent = entry->d_parent; if (inotify_inode_watched(parent->d_inode)) entry->d_flags |= DCACHE_INOTIFY_PARENT_WATCHED; else entry->d_flags &= ~DCACHE_INOTIFY_PARENT_WATCHED; } |
0eeca2830
|
269 270 271 272 273 274 275 |
/** * inotify_inode_queue_event - queue an event to all watches on this inode * @inode: inode event is originating from * @mask: event mask describing this event * @cookie: cookie for synchronization, or zero * @name: filename, if any |
7c2977228
|
276 |
* @n_inode: inode associated with name |
0eeca2830
|
277 278 |
*/ void inotify_inode_queue_event(struct inode *inode, u32 mask, u32 cookie, |
7c2977228
|
279 |
const char *name, struct inode *n_inode) |
0eeca2830
|
280 281 282 283 284 |
{ struct inotify_watch *watch, *next; if (!inotify_inode_watched(inode)) return; |
d4f9af9da
|
285 |
mutex_lock(&inode->inotify_mutex); |
0eeca2830
|
286 287 288 |
list_for_each_entry_safe(watch, next, &inode->inotify_watches, i_list) { u32 watch_mask = watch->mask; if (watch_mask & mask) { |
2d9048e20
|
289 290 |
struct inotify_handle *ih= watch->ih; mutex_lock(&ih->mutex); |
0eeca2830
|
291 |
if (watch_mask & IN_ONESHOT) |
2d9048e20
|
292 |
remove_watch_no_event(watch, ih); |
7c2977228
|
293 294 |
ih->in_ops->handle_event(watch, watch->wd, mask, cookie, name, n_inode); |
2d9048e20
|
295 |
mutex_unlock(&ih->mutex); |
0eeca2830
|
296 297 |
} } |
d4f9af9da
|
298 |
mutex_unlock(&inode->inotify_mutex); |
0eeca2830
|
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 |
} EXPORT_SYMBOL_GPL(inotify_inode_queue_event); /** * inotify_dentry_parent_queue_event - queue an event to a dentry's parent * @dentry: the dentry in question, we queue against this dentry's parent * @mask: event mask describing this event * @cookie: cookie for synchronization, or zero * @name: filename, if any */ void inotify_dentry_parent_queue_event(struct dentry *dentry, u32 mask, u32 cookie, const char *name) { struct dentry *parent; struct inode *inode; |
c32ccd87b
|
314 |
if (!(dentry->d_flags & DCACHE_INOTIFY_PARENT_WATCHED)) |
820249baf
|
315 |
return; |
0eeca2830
|
316 317 318 319 320 321 322 |
spin_lock(&dentry->d_lock); parent = dentry->d_parent; inode = parent->d_inode; if (inotify_inode_watched(inode)) { dget(parent); spin_unlock(&dentry->d_lock); |
7c2977228
|
323 324 |
inotify_inode_queue_event(inode, mask, cookie, name, dentry->d_inode); |
0eeca2830
|
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 |
dput(parent); } else spin_unlock(&dentry->d_lock); } EXPORT_SYMBOL_GPL(inotify_dentry_parent_queue_event); /** * inotify_get_cookie - return a unique cookie for use in synchronizing events. */ u32 inotify_get_cookie(void) { return atomic_inc_return(&inotify_cookie); } EXPORT_SYMBOL_GPL(inotify_get_cookie); /** * inotify_unmount_inodes - an sb is unmounting. handle any watched inodes. * @list: list of inodes being unmounted (sb->s_inodes) * * Called with inode_lock held, protecting the unmounting super block's list |
f24075bd0
|
345 |
* of inodes, and with iprune_mutex held, keeping shrink_icache_memory() at bay. |
0eeca2830
|
346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 |
* We temporarily drop inode_lock, however, and CAN block. */ void inotify_unmount_inodes(struct list_head *list) { struct inode *inode, *next_i, *need_iput = NULL; list_for_each_entry_safe(inode, next_i, list, i_sb_list) { struct inotify_watch *watch, *next_w; struct inode *need_iput_tmp; struct list_head *watches; /* * If i_count is zero, the inode cannot have any watches and * doing an __iget/iput with MS_ACTIVE clear would actually * evict all inodes with zero i_count from icache which is * unnecessarily violent and may in fact be illegal to do. */ if (!atomic_read(&inode->i_count)) continue; /* * We cannot __iget() an inode in state I_CLEAR, I_FREEING, or * I_WILL_FREE which is fine because by that point the inode * cannot have any associated watches. */ if (inode->i_state & (I_CLEAR | I_FREEING | I_WILL_FREE)) continue; need_iput_tmp = need_iput; need_iput = NULL; |
3ca10067f
|
376 |
/* In case inotify_remove_watch_locked() drops a reference. */ |
0eeca2830
|
377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 |
if (inode != need_iput_tmp) __iget(inode); else need_iput_tmp = NULL; /* In case the dropping of a reference would nuke next_i. */ if ((&next_i->i_sb_list != list) && atomic_read(&next_i->i_count) && !(next_i->i_state & (I_CLEAR | I_FREEING | I_WILL_FREE))) { __iget(next_i); need_iput = next_i; } /* * We can safely drop inode_lock here because we hold * references on both inode and next_i. Also no new inodes * will be added since the umount has begun. Finally, |
f24075bd0
|
394 |
* iprune_mutex keeps shrink_icache_memory() away. |
0eeca2830
|
395 396 397 398 399 400 401 |
*/ spin_unlock(&inode_lock); if (need_iput_tmp) iput(need_iput_tmp); /* for each watch, send IN_UNMOUNT and then remove it */ |
d4f9af9da
|
402 |
mutex_lock(&inode->inotify_mutex); |
0eeca2830
|
403 404 |
watches = &inode->inotify_watches; list_for_each_entry_safe(watch, next_w, watches, i_list) { |
2d9048e20
|
405 406 407 |
struct inotify_handle *ih= watch->ih; mutex_lock(&ih->mutex); ih->in_ops->handle_event(watch, watch->wd, IN_UNMOUNT, 0, |
7c2977228
|
408 |
NULL, NULL); |
3ca10067f
|
409 |
inotify_remove_watch_locked(ih, watch); |
2d9048e20
|
410 |
mutex_unlock(&ih->mutex); |
0eeca2830
|
411 |
} |
d4f9af9da
|
412 |
mutex_unlock(&inode->inotify_mutex); |
0eeca2830
|
413 414 415 416 417 418 419 420 421 422 423 424 425 426 |
iput(inode); spin_lock(&inode_lock); } } EXPORT_SYMBOL_GPL(inotify_unmount_inodes); /** * inotify_inode_is_dead - an inode has been deleted, cleanup any watches * @inode: inode that is about to be removed */ void inotify_inode_is_dead(struct inode *inode) { struct inotify_watch *watch, *next; |
d4f9af9da
|
427 |
mutex_lock(&inode->inotify_mutex); |
0eeca2830
|
428 |
list_for_each_entry_safe(watch, next, &inode->inotify_watches, i_list) { |
2d9048e20
|
429 430 |
struct inotify_handle *ih = watch->ih; mutex_lock(&ih->mutex); |
3ca10067f
|
431 |
inotify_remove_watch_locked(ih, watch); |
2d9048e20
|
432 |
mutex_unlock(&ih->mutex); |
0eeca2830
|
433 |
} |
d4f9af9da
|
434 |
mutex_unlock(&inode->inotify_mutex); |
0eeca2830
|
435 436 |
} EXPORT_SYMBOL_GPL(inotify_inode_is_dead); |
2d9048e20
|
437 |
/* Kernel Consumer API */ |
0eeca2830
|
438 |
|
2d9048e20
|
439 440 441 442 443 |
/** * inotify_init - allocate and initialize an inotify instance * @ops: caller's inotify operations */ struct inotify_handle *inotify_init(const struct inotify_operations *ops) |
0eeca2830
|
444 |
{ |
2d9048e20
|
445 |
struct inotify_handle *ih; |
0eeca2830
|
446 |
|
2d9048e20
|
447 448 449 |
ih = kmalloc(sizeof(struct inotify_handle), GFP_KERNEL); if (unlikely(!ih)) return ERR_PTR(-ENOMEM); |
0eeca2830
|
450 |
|
2d9048e20
|
451 452 453 454 455 456 457 |
idr_init(&ih->idr); INIT_LIST_HEAD(&ih->watches); mutex_init(&ih->mutex); ih->last_wd = 0; ih->in_ops = ops; atomic_set(&ih->count, 0); get_inotify_handle(ih); |
0eeca2830
|
458 |
|
2d9048e20
|
459 |
return ih; |
0eeca2830
|
460 |
} |
2d9048e20
|
461 |
EXPORT_SYMBOL_GPL(inotify_init); |
0eeca2830
|
462 |
|
2d9048e20
|
463 |
/** |
a9dc971d3
|
464 465 466 467 468 469 470 471 472 473 474 475 476 |
* inotify_init_watch - initialize an inotify watch * @watch: watch to initialize */ void inotify_init_watch(struct inotify_watch *watch) { INIT_LIST_HEAD(&watch->h_list); INIT_LIST_HEAD(&watch->i_list); atomic_set(&watch->count, 0); get_inotify_watch(watch); /* initial get */ } EXPORT_SYMBOL_GPL(inotify_init_watch); /** |
2d9048e20
|
477 478 479 480 |
* inotify_destroy - clean up and destroy an inotify instance * @ih: inotify handle */ void inotify_destroy(struct inotify_handle *ih) |
0eeca2830
|
481 |
{ |
0eeca2830
|
482 |
/* |
2d9048e20
|
483 |
* Destroy all of the watches for this handle. Unfortunately, not very |
0eeca2830
|
484 485 |
* pretty. We cannot do a simple iteration over the list, because we * do not know the inode until we iterate to the watch. But we need to |
2d9048e20
|
486 |
* hold inode->inotify_mutex before ih->mutex. The following works. |
0eeca2830
|
487 488 489 490 491 |
*/ while (1) { struct inotify_watch *watch; struct list_head *watches; struct inode *inode; |
2d9048e20
|
492 493 |
mutex_lock(&ih->mutex); watches = &ih->watches; |
0eeca2830
|
494 |
if (list_empty(watches)) { |
2d9048e20
|
495 |
mutex_unlock(&ih->mutex); |
0eeca2830
|
496 497 |
break; } |
b5e618181
|
498 |
watch = list_first_entry(watches, struct inotify_watch, h_list); |
0eeca2830
|
499 |
get_inotify_watch(watch); |
2d9048e20
|
500 |
mutex_unlock(&ih->mutex); |
0eeca2830
|
501 502 |
inode = watch->inode; |
d4f9af9da
|
503 |
mutex_lock(&inode->inotify_mutex); |
2d9048e20
|
504 |
mutex_lock(&ih->mutex); |
66055a4e7
|
505 506 |
/* make sure we didn't race with another list removal */ |
2d9048e20
|
507 508 509 510 |
if (likely(idr_find(&ih->idr, watch->wd))) { remove_watch_no_event(watch, ih); put_inotify_watch(watch); } |
66055a4e7
|
511 |
|
2d9048e20
|
512 |
mutex_unlock(&ih->mutex); |
d4f9af9da
|
513 |
mutex_unlock(&inode->inotify_mutex); |
0eeca2830
|
514 515 |
put_inotify_watch(watch); } |
2d9048e20
|
516 517 |
/* free this handle: the put matching the get in inotify_init() */ put_inotify_handle(ih); |
0eeca2830
|
518 |
} |
2d9048e20
|
519 |
EXPORT_SYMBOL_GPL(inotify_destroy); |
0eeca2830
|
520 |
|
2d9048e20
|
521 |
/** |
a9dc971d3
|
522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 |
* inotify_find_watch - find an existing watch for an (ih,inode) pair * @ih: inotify handle * @inode: inode to watch * @watchp: pointer to existing inotify_watch * * Caller must pin given inode (via nameidata). */ s32 inotify_find_watch(struct inotify_handle *ih, struct inode *inode, struct inotify_watch **watchp) { struct inotify_watch *old; int ret = -ENOENT; mutex_lock(&inode->inotify_mutex); mutex_lock(&ih->mutex); old = inode_find_handle(inode, ih); if (unlikely(old)) { get_inotify_watch(old); /* caller must put watch */ *watchp = old; ret = old->wd; } mutex_unlock(&ih->mutex); mutex_unlock(&inode->inotify_mutex); return ret; } EXPORT_SYMBOL_GPL(inotify_find_watch); /** |
2d9048e20
|
553 554 555 556 |
* inotify_find_update_watch - find and update the mask of an existing watch * @ih: inotify handle * @inode: inode's watch to update * @mask: mask of events to watch |
0eeca2830
|
557 |
* |
2d9048e20
|
558 |
* Caller must pin given inode (via nameidata). |
0eeca2830
|
559 |
*/ |
2d9048e20
|
560 561 |
s32 inotify_find_update_watch(struct inotify_handle *ih, struct inode *inode, u32 mask) |
0eeca2830
|
562 |
{ |
2d9048e20
|
563 564 565 |
struct inotify_watch *old; int mask_add = 0; int ret; |
0eeca2830
|
566 |
|
2d9048e20
|
567 568 569 570 571 572 |
if (mask & IN_MASK_ADD) mask_add = 1; /* don't allow invalid bits: we don't want flags set */ mask &= IN_ALL_EVENTS | IN_ONESHOT; if (unlikely(!mask)) |
0eeca2830
|
573 |
return -EINVAL; |
0eeca2830
|
574 |
|
d4f9af9da
|
575 |
mutex_lock(&inode->inotify_mutex); |
2d9048e20
|
576 |
mutex_lock(&ih->mutex); |
0eeca2830
|
577 |
|
2d9048e20
|
578 579 580 581 582 583 584 585 |
/* * Handle the case of re-adding a watch on an (inode,ih) pair that we * are already watching. We just update the mask and return its wd. */ old = inode_find_handle(inode, ih); if (unlikely(!old)) { ret = -ENOENT; goto out; |
0eeca2830
|
586 |
} |
2d9048e20
|
587 588 589 590 591 592 593 594 |
if (mask_add) old->mask |= mask; else old->mask = mask; ret = old->wd; out: mutex_unlock(&ih->mutex); mutex_unlock(&inode->inotify_mutex); |
0eeca2830
|
595 596 |
return ret; } |
2d9048e20
|
597 |
EXPORT_SYMBOL_GPL(inotify_find_update_watch); |
0eeca2830
|
598 |
|
2d9048e20
|
599 600 601 602 603 604 605 606 607 608 609 610 611 |
/** * inotify_add_watch - add a watch to an inotify instance * @ih: inotify handle * @watch: caller allocated watch structure * @inode: inode to watch * @mask: mask of events to watch * * Caller must pin given inode (via nameidata). * Caller must ensure it only calls inotify_add_watch() once per watch. * Calls inotify_handle_get_wd() so may sleep. */ s32 inotify_add_watch(struct inotify_handle *ih, struct inotify_watch *watch, struct inode *inode, u32 mask) |
0eeca2830
|
612 |
{ |
2d9048e20
|
613 |
int ret = 0; |
0eeca2830
|
614 |
|
2d9048e20
|
615 616 617 618 619 |
/* don't allow invalid bits: we don't want flags set */ mask &= IN_ALL_EVENTS | IN_ONESHOT; if (unlikely(!mask)) return -EINVAL; watch->mask = mask; |
783bc29bb
|
620 |
|
2d9048e20
|
621 622 |
mutex_lock(&inode->inotify_mutex); mutex_lock(&ih->mutex); |
8140a5005
|
623 |
|
2d9048e20
|
624 625 |
/* Initialize a new watch */ ret = inotify_handle_get_wd(ih, watch); |
b680716ed
|
626 |
if (unlikely(ret)) |
2d9048e20
|
627 628 |
goto out; ret = watch->wd; |
0eeca2830
|
629 |
|
2d9048e20
|
630 631 632 |
/* save a reference to handle and bump the count to make it official */ get_inotify_handle(ih); watch->ih = ih; |
0eeca2830
|
633 634 |
/* |
2d9048e20
|
635 636 |
* Save a reference to the inode and bump the ref count to make it * official. We hold a reference to nameidata, which makes this safe. |
0eeca2830
|
637 |
*/ |
2d9048e20
|
638 |
watch->inode = igrab(inode); |
0eeca2830
|
639 |
|
c32ccd87b
|
640 641 |
if (!inotify_inode_watched(inode)) set_dentry_child_flags(inode, 1); |
2d9048e20
|
642 643 |
/* Add the watch to the handle's and the inode's list */ list_add(&watch->h_list, &ih->watches); |
0eeca2830
|
644 |
list_add(&watch->i_list, &inode->inotify_watches); |
0eeca2830
|
645 |
out: |
2d9048e20
|
646 |
mutex_unlock(&ih->mutex); |
d4f9af9da
|
647 |
mutex_unlock(&inode->inotify_mutex); |
0eeca2830
|
648 649 |
return ret; } |
2d9048e20
|
650 |
EXPORT_SYMBOL_GPL(inotify_add_watch); |
0eeca2830
|
651 |
|
2d9048e20
|
652 653 654 655 656 657 658 659 |
/** * inotify_rm_wd - remove a watch from an inotify instance * @ih: inotify handle * @wd: watch descriptor to remove * * Can sleep. */ int inotify_rm_wd(struct inotify_handle *ih, u32 wd) |
0eeca2830
|
660 |
{ |
2d9048e20
|
661 662 |
struct inotify_watch *watch; struct inode *inode; |
783bc29bb
|
663 |
|
2d9048e20
|
664 665 666 667 668 |
mutex_lock(&ih->mutex); watch = idr_find(&ih->idr, wd); if (unlikely(!watch)) { mutex_unlock(&ih->mutex); return -EINVAL; |
783bc29bb
|
669 |
} |
2d9048e20
|
670 671 672 |
get_inotify_watch(watch); inode = watch->inode; mutex_unlock(&ih->mutex); |
783bc29bb
|
673 |
|
2d9048e20
|
674 675 |
mutex_lock(&inode->inotify_mutex); mutex_lock(&ih->mutex); |
9a556e890
|
676 |
|
2d9048e20
|
677 678 |
/* make sure that we did not race */ if (likely(idr_find(&ih->idr, wd) == watch)) |
3ca10067f
|
679 |
inotify_remove_watch_locked(ih, watch); |
0eeca2830
|
680 |
|
2d9048e20
|
681 682 683 |
mutex_unlock(&ih->mutex); mutex_unlock(&inode->inotify_mutex); put_inotify_watch(watch); |
0eeca2830
|
684 |
|
2d9048e20
|
685 686 687 |
return 0; } EXPORT_SYMBOL_GPL(inotify_rm_wd); |
0eeca2830
|
688 |
|
a9dc971d3
|
689 690 691 692 693 694 695 696 697 698 699 700 701 |
/** * inotify_rm_watch - remove a watch from an inotify instance * @ih: inotify handle * @watch: watch to remove * * Can sleep. */ int inotify_rm_watch(struct inotify_handle *ih, struct inotify_watch *watch) { return inotify_rm_wd(ih, watch->wd); } EXPORT_SYMBOL_GPL(inotify_rm_watch); |
0eeca2830
|
702 |
/* |
2d9048e20
|
703 |
* inotify_setup - core initialization function |
0eeca2830
|
704 |
*/ |
b680716ed
|
705 |
static int __init inotify_setup(void) |
0eeca2830
|
706 |
{ |
0eeca2830
|
707 |
atomic_set(&inotify_cookie, 0); |
0eeca2830
|
708 709 |
return 0; } |
b680716ed
|
710 |
module_init(inotify_setup); |