diff options
Diffstat (limited to 'mm/filemap.c')
-rw-r--r-- | mm/filemap.c | 20 |
1 files changed, 11 insertions, 9 deletions
diff --git a/mm/filemap.c b/mm/filemap.c index a49702445ce0..0b41c8cbeabc 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
@@ -885,6 +885,7 @@ void __init pagecache_init(void) | |||
885 | page_writeback_init(); | 885 | page_writeback_init(); |
886 | } | 886 | } |
887 | 887 | ||
888 | /* This has the same layout as wait_bit_key - see fs/cachefiles/rdwr.c */ | ||
888 | struct wait_page_key { | 889 | struct wait_page_key { |
889 | struct page *page; | 890 | struct page *page; |
890 | int bit_nr; | 891 | int bit_nr; |
@@ -909,8 +910,10 @@ static int wake_page_function(wait_queue_entry_t *wait, unsigned mode, int sync, | |||
909 | 910 | ||
910 | if (wait_page->bit_nr != key->bit_nr) | 911 | if (wait_page->bit_nr != key->bit_nr) |
911 | return 0; | 912 | return 0; |
913 | |||
914 | /* Stop walking if it's locked */ | ||
912 | if (test_bit(key->bit_nr, &key->page->flags)) | 915 | if (test_bit(key->bit_nr, &key->page->flags)) |
913 | return 0; | 916 | return -1; |
914 | 917 | ||
915 | return autoremove_wake_function(wait, mode, sync, key); | 918 | return autoremove_wake_function(wait, mode, sync, key); |
916 | } | 919 | } |
@@ -964,6 +967,7 @@ static inline int wait_on_page_bit_common(wait_queue_head_t *q, | |||
964 | int ret = 0; | 967 | int ret = 0; |
965 | 968 | ||
966 | init_wait(wait); | 969 | init_wait(wait); |
970 | wait->flags = lock ? WQ_FLAG_EXCLUSIVE : 0; | ||
967 | wait->func = wake_page_function; | 971 | wait->func = wake_page_function; |
968 | wait_page.page = page; | 972 | wait_page.page = page; |
969 | wait_page.bit_nr = bit_nr; | 973 | wait_page.bit_nr = bit_nr; |
@@ -972,10 +976,7 @@ static inline int wait_on_page_bit_common(wait_queue_head_t *q, | |||
972 | spin_lock_irq(&q->lock); | 976 | spin_lock_irq(&q->lock); |
973 | 977 | ||
974 | if (likely(list_empty(&wait->entry))) { | 978 | if (likely(list_empty(&wait->entry))) { |
975 | if (lock) | 979 | __add_wait_queue_entry_tail(q, wait); |
976 | __add_wait_queue_entry_tail_exclusive(q, wait); | ||
977 | else | ||
978 | __add_wait_queue(q, wait); | ||
979 | SetPageWaiters(page); | 980 | SetPageWaiters(page); |
980 | } | 981 | } |
981 | 982 | ||
@@ -985,10 +986,6 @@ static inline int wait_on_page_bit_common(wait_queue_head_t *q, | |||
985 | 986 | ||
986 | if (likely(test_bit(bit_nr, &page->flags))) { | 987 | if (likely(test_bit(bit_nr, &page->flags))) { |
987 | io_schedule(); | 988 | io_schedule(); |
988 | if (unlikely(signal_pending_state(state, current))) { | ||
989 | ret = -EINTR; | ||
990 | break; | ||
991 | } | ||
992 | } | 989 | } |
993 | 990 | ||
994 | if (lock) { | 991 | if (lock) { |
@@ -998,6 +995,11 @@ static inline int wait_on_page_bit_common(wait_queue_head_t *q, | |||
998 | if (!test_bit(bit_nr, &page->flags)) | 995 | if (!test_bit(bit_nr, &page->flags)) |
999 | break; | 996 | break; |
1000 | } | 997 | } |
998 | |||
999 | if (unlikely(signal_pending_state(state, current))) { | ||
1000 | ret = -EINTR; | ||
1001 | break; | ||
1002 | } | ||
1001 | } | 1003 | } |
1002 | 1004 | ||
1003 | finish_wait(q, wait); | 1005 | finish_wait(q, wait); |