diff options
author | Eric Paris <eparis@redhat.com> | 2009-07-15 15:49:52 -0400 |
---|---|---|
committer | Eric Paris <eparis@redhat.com> | 2009-07-21 15:26:27 -0400 |
commit | f44aebcc566d1d6275f7191867b9633dc11de2ee (patch) | |
tree | a5faaf5ca8e1360f359ee22ad29582992596c3e6 /fs/notify/notification.c | |
parent | c05594b62125c528d93af3a78229793aae36df7f (diff) |
inotify: use GFP_NOFS under potential memory pressure
inotify can have a watchs removed under filesystem reclaim.
=================================
[ INFO: inconsistent lock state ]
2.6.31-rc2 #16
---------------------------------
inconsistent {IN-RECLAIM_FS-W} -> {RECLAIM_FS-ON-W} usage.
khubd/217 [HC0[0]:SC0[0]:HE1:SE1] takes:
(iprune_mutex){+.+.?.}, at: [<c10ba899>] invalidate_inodes+0x20/0xe3
{IN-RECLAIM_FS-W} state was registered at:
[<c10536ab>] __lock_acquire+0x2c9/0xac4
[<c1053f45>] lock_acquire+0x9f/0xc2
[<c1308872>] __mutex_lock_common+0x2d/0x323
[<c1308c00>] mutex_lock_nested+0x2e/0x36
[<c10ba6ff>] shrink_icache_memory+0x38/0x1b2
[<c108bfb6>] shrink_slab+0xe2/0x13c
[<c108c3e1>] kswapd+0x3d1/0x55d
[<c10449b5>] kthread+0x66/0x6b
[<c1003fdf>] kernel_thread_helper+0x7/0x10
[<ffffffff>] 0xffffffff
Two things are needed to fix this. First we need a method to tell
fsnotify_create_event() to use GFP_NOFS and second we need to stop using
one global IN_IGNORED event and allocate them one at a time. This solves
current issues with multiple IN_IGNORED on a queue having tail drop
problems and simplifies the allocations since we don't have to worry about
two tasks opperating on the IGNORED event concurrently.
Signed-off-by: Eric Paris <eparis@redhat.com>
Diffstat (limited to 'fs/notify/notification.c')
-rw-r--r-- | fs/notify/notification.c | 9 |
1 files changed, 5 insertions, 4 deletions
diff --git a/fs/notify/notification.c b/fs/notify/notification.c index 2b20feaf263a..521368574e97 100644 --- a/fs/notify/notification.c +++ b/fs/notify/notification.c | |||
@@ -153,7 +153,7 @@ static bool event_compare(struct fsnotify_event *old, struct fsnotify_event *new | |||
153 | return true; | 153 | return true; |
154 | break; | 154 | break; |
155 | case (FSNOTIFY_EVENT_NONE): | 155 | case (FSNOTIFY_EVENT_NONE): |
156 | return true; | 156 | return false; |
157 | }; | 157 | }; |
158 | } | 158 | } |
159 | return false; | 159 | return false; |
@@ -345,18 +345,19 @@ static void initialize_event(struct fsnotify_event *event) | |||
345 | * @name the filename, if available | 345 | * @name the filename, if available |
346 | */ | 346 | */ |
347 | struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask, void *data, | 347 | struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask, void *data, |
348 | int data_type, const char *name, u32 cookie) | 348 | int data_type, const char *name, u32 cookie, |
349 | gfp_t gfp) | ||
349 | { | 350 | { |
350 | struct fsnotify_event *event; | 351 | struct fsnotify_event *event; |
351 | 352 | ||
352 | event = kmem_cache_alloc(fsnotify_event_cachep, GFP_KERNEL); | 353 | event = kmem_cache_alloc(fsnotify_event_cachep, gfp); |
353 | if (!event) | 354 | if (!event) |
354 | return NULL; | 355 | return NULL; |
355 | 356 | ||
356 | initialize_event(event); | 357 | initialize_event(event); |
357 | 358 | ||
358 | if (name) { | 359 | if (name) { |
359 | event->file_name = kstrdup(name, GFP_KERNEL); | 360 | event->file_name = kstrdup(name, gfp); |
360 | if (!event->file_name) { | 361 | if (!event->file_name) { |
361 | kmem_cache_free(fsnotify_event_cachep, event); | 362 | kmem_cache_free(fsnotify_event_cachep, event); |
362 | return NULL; | 363 | return NULL; |