diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2014-01-10 11:13:52 +1100 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2014-01-10 11:13:52 +1100 |
commit | 590d6f9878ac298e49a8d1d5907fb9f2ed8e5f12 (patch) | |
tree | 76a85a2199aa233840586b320509239f8ddd25d4 /fs | |
parent | bc41844220d1ba0b7a7cfe2d178969d9df5790e0 (diff) | |
parent | 7c604e5d6e565f34d0156608be6e63fed5fad5c9 (diff) |
Merge remote-tracking branch 'fscache/fscache'
Diffstat (limited to 'fs')
-rw-r--r-- | fs/fscache/page.c | 37 |
1 files changed, 36 insertions, 1 deletions
diff --git a/fs/fscache/page.c b/fs/fscache/page.c index 7f5c658af755..b4730cf52aec 100644 --- a/fs/fscache/page.c +++ b/fs/fscache/page.c @@ -755,6 +755,7 @@ static void fscache_write_op(struct fscache_operation *_op) struct fscache_object *object = op->op.object; struct fscache_cookie *cookie; struct page *page; + pgoff_t index; unsigned n; void *results[1]; int ret; @@ -803,7 +804,7 @@ static void fscache_write_op(struct fscache_operation *_op) _debug("gang %d [%lx]", n, page->index); if (page->index > op->store_limit) { fscache_stat(&fscache_n_store_pages_over_limit); - goto superseded; + goto page_beyond_limit; } radix_tree_tag_set(&cookie->stores, page->index, @@ -829,6 +830,40 @@ static void fscache_write_op(struct fscache_operation *_op) _leave(""); return; +page_beyond_limit: + spin_unlock(&object->lock); + +page_beyond_limit_unlocked: + /* pages that are now beyond the end of the storage object must have + * their pending storage records cleared. + */ + index = page->index; + radix_tree_tag_clear(&cookie->stores, page->index, + FSCACHE_COOKIE_PENDING_TAG); + if (!radix_tree_tag_get(&cookie->stores, page->index, + FSCACHE_COOKIE_STORING_TAG)) { + fscache_stat(&fscache_n_store_radix_deletes); + radix_tree_delete(&cookie->stores, page->index); + page_cache_release(page); + } + if (!need_resched()) { + n = radix_tree_gang_lookup_tag(&cookie->stores, results, + index + 1, 1, + FSCACHE_COOKIE_PENDING_TAG); + if (n == 1) { + page = results[0]; + goto page_beyond_limit_unlocked; + } + spin_unlock(&cookie->stores_lock); + wake_up_bit(&cookie->flags, 0); + } else { + spin_unlock(&cookie->stores_lock); + } + + fscache_enqueue_operation(&op->op); + _leave(""); + return; + superseded: /* this writer is going away and there aren't any more things to * write */ |