diff options
author | Eric Paris <eparis@redhat.com> | 2009-12-17 21:24:33 -0500 |
---|---|---|
committer | Eric Paris <eparis@redhat.com> | 2010-07-28 09:59:00 -0400 |
commit | b9e4e3bd0495fea9e8f8e712889c9cd8ffa43c94 (patch) | |
tree | 914a16f5098cf0ee3e01e6d47e6c7c9bf3613899 /fs/notify | |
parent | 32a4df13b88afef2a7d869bb7586a7beba90961f (diff) |
fanotify: allow users to set an ignored_mask
Change the sys_fanotify_mark() system call so users can set ignored_masks
on inodes. Remember, if a user new sets a real mask, and only sets ignored
masks, the ignore will never be pinned in memory. Thus ignored_masks can
be lost under memory pressure and the user may again get events they
previously thought were ignored.
Signed-off-by: Eric Paris <eparis@redhat.com>
Diffstat (limited to 'fs/notify')
-rw-r--r-- | fs/notify/fanotify/fanotify_user.c | 54 |
1 files changed, 36 insertions, 18 deletions
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 3320f0c57e31..ad02d475770f 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c | |||
@@ -296,13 +296,20 @@ out: | |||
296 | return ret; | 296 | return ret; |
297 | } | 297 | } |
298 | 298 | ||
299 | static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark, __u32 mask) | 299 | static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark, |
300 | __u32 mask, | ||
301 | unsigned int flags) | ||
300 | { | 302 | { |
301 | __u32 oldmask; | 303 | __u32 oldmask; |
302 | 304 | ||
303 | spin_lock(&fsn_mark->lock); | 305 | spin_lock(&fsn_mark->lock); |
304 | oldmask = fsn_mark->mask; | 306 | if (!(flags & FAN_MARK_IGNORED_MASK)) { |
305 | fsnotify_set_mark_mask_locked(fsn_mark, (oldmask & ~mask)); | 307 | oldmask = fsn_mark->mask; |
308 | fsnotify_set_mark_mask_locked(fsn_mark, (oldmask & ~mask)); | ||
309 | } else { | ||
310 | oldmask = fsn_mark->ignored_mask; | ||
311 | fsnotify_set_mark_ignored_mask_locked(fsn_mark, (oldmask & ~mask)); | ||
312 | } | ||
306 | spin_unlock(&fsn_mark->lock); | 313 | spin_unlock(&fsn_mark->lock); |
307 | 314 | ||
308 | if (!(oldmask & ~mask)) | 315 | if (!(oldmask & ~mask)) |
@@ -312,7 +319,8 @@ static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark, __u3 | |||
312 | } | 319 | } |
313 | 320 | ||
314 | static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group, | 321 | static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group, |
315 | struct vfsmount *mnt, __u32 mask) | 322 | struct vfsmount *mnt, __u32 mask, |
323 | unsigned int flags) | ||
316 | { | 324 | { |
317 | struct fsnotify_mark *fsn_mark = NULL; | 325 | struct fsnotify_mark *fsn_mark = NULL; |
318 | __u32 removed; | 326 | __u32 removed; |
@@ -321,7 +329,7 @@ static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group, | |||
321 | if (!fsn_mark) | 329 | if (!fsn_mark) |
322 | return -ENOENT; | 330 | return -ENOENT; |
323 | 331 | ||
324 | removed = fanotify_mark_remove_from_mask(fsn_mark, mask); | 332 | removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags); |
325 | fsnotify_put_mark(fsn_mark); | 333 | fsnotify_put_mark(fsn_mark); |
326 | if (removed & group->mask) | 334 | if (removed & group->mask) |
327 | fsnotify_recalc_group_mask(group); | 335 | fsnotify_recalc_group_mask(group); |
@@ -332,7 +340,8 @@ static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group, | |||
332 | } | 340 | } |
333 | 341 | ||
334 | static int fanotify_remove_inode_mark(struct fsnotify_group *group, | 342 | static int fanotify_remove_inode_mark(struct fsnotify_group *group, |
335 | struct inode *inode, __u32 mask) | 343 | struct inode *inode, __u32 mask, |
344 | unsigned int flags) | ||
336 | { | 345 | { |
337 | struct fsnotify_mark *fsn_mark = NULL; | 346 | struct fsnotify_mark *fsn_mark = NULL; |
338 | __u32 removed; | 347 | __u32 removed; |
@@ -341,7 +350,7 @@ static int fanotify_remove_inode_mark(struct fsnotify_group *group, | |||
341 | if (!fsn_mark) | 350 | if (!fsn_mark) |
342 | return -ENOENT; | 351 | return -ENOENT; |
343 | 352 | ||
344 | removed = fanotify_mark_remove_from_mask(fsn_mark, mask); | 353 | removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags); |
345 | /* matches the fsnotify_find_inode_mark() */ | 354 | /* matches the fsnotify_find_inode_mark() */ |
346 | fsnotify_put_mark(fsn_mark); | 355 | fsnotify_put_mark(fsn_mark); |
347 | 356 | ||
@@ -353,20 +362,28 @@ static int fanotify_remove_inode_mark(struct fsnotify_group *group, | |||
353 | return 0; | 362 | return 0; |
354 | } | 363 | } |
355 | 364 | ||
356 | static __u32 fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark, __u32 mask) | 365 | static __u32 fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark, |
366 | __u32 mask, | ||
367 | unsigned int flags) | ||
357 | { | 368 | { |
358 | __u32 oldmask; | 369 | __u32 oldmask; |
359 | 370 | ||
360 | spin_lock(&fsn_mark->lock); | 371 | spin_lock(&fsn_mark->lock); |
361 | oldmask = fsn_mark->mask; | 372 | if (!(flags & FAN_MARK_IGNORED_MASK)) { |
362 | fsnotify_set_mark_mask_locked(fsn_mark, (oldmask | mask)); | 373 | oldmask = fsn_mark->mask; |
374 | fsnotify_set_mark_mask_locked(fsn_mark, (oldmask | mask)); | ||
375 | } else { | ||
376 | oldmask = fsn_mark->ignored_mask; | ||
377 | fsnotify_set_mark_ignored_mask_locked(fsn_mark, (oldmask | mask)); | ||
378 | } | ||
363 | spin_unlock(&fsn_mark->lock); | 379 | spin_unlock(&fsn_mark->lock); |
364 | 380 | ||
365 | return mask & ~oldmask; | 381 | return mask & ~oldmask; |
366 | } | 382 | } |
367 | 383 | ||
368 | static int fanotify_add_vfsmount_mark(struct fsnotify_group *group, | 384 | static int fanotify_add_vfsmount_mark(struct fsnotify_group *group, |
369 | struct vfsmount *mnt, __u32 mask) | 385 | struct vfsmount *mnt, __u32 mask, |
386 | unsigned int flags) | ||
370 | { | 387 | { |
371 | struct fsnotify_mark *fsn_mark; | 388 | struct fsnotify_mark *fsn_mark; |
372 | __u32 added; | 389 | __u32 added; |
@@ -386,7 +403,7 @@ static int fanotify_add_vfsmount_mark(struct fsnotify_group *group, | |||
386 | return ret; | 403 | return ret; |
387 | } | 404 | } |
388 | } | 405 | } |
389 | added = fanotify_mark_add_to_mask(fsn_mark, mask); | 406 | added = fanotify_mark_add_to_mask(fsn_mark, mask, flags); |
390 | fsnotify_put_mark(fsn_mark); | 407 | fsnotify_put_mark(fsn_mark); |
391 | if (added) { | 408 | if (added) { |
392 | if (added & ~group->mask) | 409 | if (added & ~group->mask) |
@@ -398,7 +415,8 @@ static int fanotify_add_vfsmount_mark(struct fsnotify_group *group, | |||
398 | } | 415 | } |
399 | 416 | ||
400 | static int fanotify_add_inode_mark(struct fsnotify_group *group, | 417 | static int fanotify_add_inode_mark(struct fsnotify_group *group, |
401 | struct inode *inode, __u32 mask) | 418 | struct inode *inode, __u32 mask, |
419 | unsigned int flags) | ||
402 | { | 420 | { |
403 | struct fsnotify_mark *fsn_mark; | 421 | struct fsnotify_mark *fsn_mark; |
404 | __u32 added; | 422 | __u32 added; |
@@ -420,7 +438,7 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group, | |||
420 | return ret; | 438 | return ret; |
421 | } | 439 | } |
422 | } | 440 | } |
423 | added = fanotify_mark_add_to_mask(fsn_mark, mask); | 441 | added = fanotify_mark_add_to_mask(fsn_mark, mask, flags); |
424 | fsnotify_put_mark(fsn_mark); | 442 | fsnotify_put_mark(fsn_mark); |
425 | if (added) { | 443 | if (added) { |
426 | if (added & ~group->mask) | 444 | if (added & ~group->mask) |
@@ -528,15 +546,15 @@ SYSCALL_DEFINE(fanotify_mark)(int fanotify_fd, unsigned int flags, | |||
528 | switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE)) { | 546 | switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE)) { |
529 | case FAN_MARK_ADD: | 547 | case FAN_MARK_ADD: |
530 | if (flags & FAN_MARK_MOUNT) | 548 | if (flags & FAN_MARK_MOUNT) |
531 | ret = fanotify_add_vfsmount_mark(group, mnt, mask); | 549 | ret = fanotify_add_vfsmount_mark(group, mnt, mask, flags); |
532 | else | 550 | else |
533 | ret = fanotify_add_inode_mark(group, inode, mask); | 551 | ret = fanotify_add_inode_mark(group, inode, mask, flags); |
534 | break; | 552 | break; |
535 | case FAN_MARK_REMOVE: | 553 | case FAN_MARK_REMOVE: |
536 | if (flags & FAN_MARK_MOUNT) | 554 | if (flags & FAN_MARK_MOUNT) |
537 | ret = fanotify_remove_vfsmount_mark(group, mnt, mask); | 555 | ret = fanotify_remove_vfsmount_mark(group, mnt, mask, flags); |
538 | else | 556 | else |
539 | ret = fanotify_remove_inode_mark(group, inode, mask); | 557 | ret = fanotify_remove_inode_mark(group, inode, mask, flags); |
540 | break; | 558 | break; |
541 | default: | 559 | default: |
542 | ret = -EINVAL; | 560 | ret = -EINVAL; |