diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-09-22 20:52:16 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-09-22 20:52:16 -0400 |
commit | e2519c2c85c376666c96705239c5c7d1aef14b2d (patch) | |
tree | 7faec5ebe379aabe81d98a6f9f71d73449776793 /fs | |
parent | b0e2a55c6536f255ebe80bc84c3f565c2a8f2a9d (diff) | |
parent | e2cf1f1cc7636bd860e47cd0ad6194da8975f8b5 (diff) |
Merge tag 'fscache-fixes-20140917' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs
Pull fs-cache fixes from David Howells:
- Put a timeout in releasepage() to deal with a recursive hang between
the memory allocator, writeback, ext4 and fscache under memory
pressure.
- Fix a pair of refcount bugs in the fscache error handling.
- Remove a couple of unused pagevecs.
- The cachefiles requirement that the base directory support rename
should permit rename2 as an alternative - otherwise certain
filesystems cannot now be used as backing stores (such as ext4).
* tag 'fscache-fixes-20140917' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs:
CacheFiles: Handle rename2
cachefiles: remove two unused pagevecs.
FS-Cache: refcount becomes corrupt under vma pressure.
FS-Cache: Reduce cookie ref count if submit fails.
FS-Cache: Timeout for releasepage()
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cachefiles/namei.c | 3 | ||||
-rw-r--r-- | fs/cachefiles/rdwr.c | 6 | ||||
-rw-r--r-- | fs/fscache/object.c | 1 | ||||
-rw-r--r-- | fs/fscache/page.c | 25 |
4 files changed, 24 insertions, 11 deletions
diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c index 5bf2b41e66d3..83e9c94ca2cf 100644 --- a/fs/cachefiles/namei.c +++ b/fs/cachefiles/namei.c | |||
@@ -779,7 +779,8 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache, | |||
779 | !subdir->d_inode->i_op->lookup || | 779 | !subdir->d_inode->i_op->lookup || |
780 | !subdir->d_inode->i_op->mkdir || | 780 | !subdir->d_inode->i_op->mkdir || |
781 | !subdir->d_inode->i_op->create || | 781 | !subdir->d_inode->i_op->create || |
782 | !subdir->d_inode->i_op->rename || | 782 | (!subdir->d_inode->i_op->rename && |
783 | !subdir->d_inode->i_op->rename2) || | ||
783 | !subdir->d_inode->i_op->rmdir || | 784 | !subdir->d_inode->i_op->rmdir || |
784 | !subdir->d_inode->i_op->unlink) | 785 | !subdir->d_inode->i_op->unlink) |
785 | goto check_error; | 786 | goto check_error; |
diff --git a/fs/cachefiles/rdwr.c b/fs/cachefiles/rdwr.c index 4b1fb5ca65b8..25e745b8eb1b 100644 --- a/fs/cachefiles/rdwr.c +++ b/fs/cachefiles/rdwr.c | |||
@@ -151,7 +151,6 @@ static void cachefiles_read_copier(struct fscache_operation *_op) | |||
151 | struct cachefiles_one_read *monitor; | 151 | struct cachefiles_one_read *monitor; |
152 | struct cachefiles_object *object; | 152 | struct cachefiles_object *object; |
153 | struct fscache_retrieval *op; | 153 | struct fscache_retrieval *op; |
154 | struct pagevec pagevec; | ||
155 | int error, max; | 154 | int error, max; |
156 | 155 | ||
157 | op = container_of(_op, struct fscache_retrieval, op); | 156 | op = container_of(_op, struct fscache_retrieval, op); |
@@ -160,8 +159,6 @@ static void cachefiles_read_copier(struct fscache_operation *_op) | |||
160 | 159 | ||
161 | _enter("{ino=%lu}", object->backer->d_inode->i_ino); | 160 | _enter("{ino=%lu}", object->backer->d_inode->i_ino); |
162 | 161 | ||
163 | pagevec_init(&pagevec, 0); | ||
164 | |||
165 | max = 8; | 162 | max = 8; |
166 | spin_lock_irq(&object->work_lock); | 163 | spin_lock_irq(&object->work_lock); |
167 | 164 | ||
@@ -396,7 +393,6 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op, | |||
396 | { | 393 | { |
397 | struct cachefiles_object *object; | 394 | struct cachefiles_object *object; |
398 | struct cachefiles_cache *cache; | 395 | struct cachefiles_cache *cache; |
399 | struct pagevec pagevec; | ||
400 | struct inode *inode; | 396 | struct inode *inode; |
401 | sector_t block0, block; | 397 | sector_t block0, block; |
402 | unsigned shift; | 398 | unsigned shift; |
@@ -427,8 +423,6 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op, | |||
427 | op->op.flags |= FSCACHE_OP_ASYNC; | 423 | op->op.flags |= FSCACHE_OP_ASYNC; |
428 | op->op.processor = cachefiles_read_copier; | 424 | op->op.processor = cachefiles_read_copier; |
429 | 425 | ||
430 | pagevec_init(&pagevec, 0); | ||
431 | |||
432 | /* we assume the absence or presence of the first block is a good | 426 | /* we assume the absence or presence of the first block is a good |
433 | * enough indication for the page as a whole | 427 | * enough indication for the page as a whole |
434 | * - TODO: don't use bmap() for this as it is _not_ actually good | 428 | * - TODO: don't use bmap() for this as it is _not_ actually good |
diff --git a/fs/fscache/object.c b/fs/fscache/object.c index d3b4539f1651..da032daf0e0d 100644 --- a/fs/fscache/object.c +++ b/fs/fscache/object.c | |||
@@ -982,6 +982,7 @@ nomem: | |||
982 | submit_op_failed: | 982 | submit_op_failed: |
983 | clear_bit(FSCACHE_OBJECT_IS_LIVE, &object->flags); | 983 | clear_bit(FSCACHE_OBJECT_IS_LIVE, &object->flags); |
984 | spin_unlock(&cookie->lock); | 984 | spin_unlock(&cookie->lock); |
985 | fscache_unuse_cookie(object); | ||
985 | kfree(op); | 986 | kfree(op); |
986 | _leave(" [EIO]"); | 987 | _leave(" [EIO]"); |
987 | return transit_to(KILL_OBJECT); | 988 | return transit_to(KILL_OBJECT); |
diff --git a/fs/fscache/page.c b/fs/fscache/page.c index 85332b9d19d1..de33b3fccca6 100644 --- a/fs/fscache/page.c +++ b/fs/fscache/page.c | |||
@@ -44,6 +44,19 @@ void __fscache_wait_on_page_write(struct fscache_cookie *cookie, struct page *pa | |||
44 | EXPORT_SYMBOL(__fscache_wait_on_page_write); | 44 | EXPORT_SYMBOL(__fscache_wait_on_page_write); |
45 | 45 | ||
46 | /* | 46 | /* |
47 | * wait for a page to finish being written to the cache. Put a timeout here | ||
48 | * since we might be called recursively via parent fs. | ||
49 | */ | ||
50 | static | ||
51 | bool release_page_wait_timeout(struct fscache_cookie *cookie, struct page *page) | ||
52 | { | ||
53 | wait_queue_head_t *wq = bit_waitqueue(&cookie->flags, 0); | ||
54 | |||
55 | return wait_event_timeout(*wq, !__fscache_check_page_write(cookie, page), | ||
56 | HZ); | ||
57 | } | ||
58 | |||
59 | /* | ||
47 | * decide whether a page can be released, possibly by cancelling a store to it | 60 | * decide whether a page can be released, possibly by cancelling a store to it |
48 | * - we're allowed to sleep if __GFP_WAIT is flagged | 61 | * - we're allowed to sleep if __GFP_WAIT is flagged |
49 | */ | 62 | */ |
@@ -115,7 +128,10 @@ page_busy: | |||
115 | } | 128 | } |
116 | 129 | ||
117 | fscache_stat(&fscache_n_store_vmscan_wait); | 130 | fscache_stat(&fscache_n_store_vmscan_wait); |
118 | __fscache_wait_on_page_write(cookie, page); | 131 | if (!release_page_wait_timeout(cookie, page)) |
132 | _debug("fscache writeout timeout page: %p{%lx}", | ||
133 | page, page->index); | ||
134 | |||
119 | gfp &= ~__GFP_WAIT; | 135 | gfp &= ~__GFP_WAIT; |
120 | goto try_again; | 136 | goto try_again; |
121 | } | 137 | } |
@@ -182,7 +198,7 @@ int __fscache_attr_changed(struct fscache_cookie *cookie) | |||
182 | { | 198 | { |
183 | struct fscache_operation *op; | 199 | struct fscache_operation *op; |
184 | struct fscache_object *object; | 200 | struct fscache_object *object; |
185 | bool wake_cookie; | 201 | bool wake_cookie = false; |
186 | 202 | ||
187 | _enter("%p", cookie); | 203 | _enter("%p", cookie); |
188 | 204 | ||
@@ -212,15 +228,16 @@ int __fscache_attr_changed(struct fscache_cookie *cookie) | |||
212 | 228 | ||
213 | __fscache_use_cookie(cookie); | 229 | __fscache_use_cookie(cookie); |
214 | if (fscache_submit_exclusive_op(object, op) < 0) | 230 | if (fscache_submit_exclusive_op(object, op) < 0) |
215 | goto nobufs; | 231 | goto nobufs_dec; |
216 | spin_unlock(&cookie->lock); | 232 | spin_unlock(&cookie->lock); |
217 | fscache_stat(&fscache_n_attr_changed_ok); | 233 | fscache_stat(&fscache_n_attr_changed_ok); |
218 | fscache_put_operation(op); | 234 | fscache_put_operation(op); |
219 | _leave(" = 0"); | 235 | _leave(" = 0"); |
220 | return 0; | 236 | return 0; |
221 | 237 | ||
222 | nobufs: | 238 | nobufs_dec: |
223 | wake_cookie = __fscache_unuse_cookie(cookie); | 239 | wake_cookie = __fscache_unuse_cookie(cookie); |
240 | nobufs: | ||
224 | spin_unlock(&cookie->lock); | 241 | spin_unlock(&cookie->lock); |
225 | kfree(op); | 242 | kfree(op); |
226 | if (wake_cookie) | 243 | if (wake_cookie) |