Skip to content

Commit 2c98425

Browse files
committed
fscache: Fix hanging wait on page discarded by writeback
If the fscache asynchronous write operation elects to discard a page that's pending storage to the cache because the page would be over the store limit then it needs to wake the page as someone may be waiting on completion of the write. The problem is that the store limit may be updated by a different asynchronous operation - and so may miss the write - and that the store limit may not even get updated until later by the netfs. Fix the kernel hang by making fscache_write_op() mark as written any pages that are over the limit. Signed-off-by: David Howells <[email protected]>
1 parent d0fb31e commit 2c98425

File tree

1 file changed

+9
-4
lines changed

1 file changed

+9
-4
lines changed

fs/fscache/page.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -778,6 +778,7 @@ static void fscache_write_op(struct fscache_operation *_op)
778778

779779
_enter("{OP%x,%d}", op->op.debug_id, atomic_read(&op->op.usage));
780780

781+
again:
781782
spin_lock(&object->lock);
782783
cookie = object->cookie;
783784

@@ -819,10 +820,6 @@ static void fscache_write_op(struct fscache_operation *_op)
819820
goto superseded;
820821
page = results[0];
821822
_debug("gang %d [%lx]", n, page->index);
822-
if (page->index >= op->store_limit) {
823-
fscache_stat(&fscache_n_store_pages_over_limit);
824-
goto superseded;
825-
}
826823

827824
radix_tree_tag_set(&cookie->stores, page->index,
828825
FSCACHE_COOKIE_STORING_TAG);
@@ -832,6 +829,9 @@ static void fscache_write_op(struct fscache_operation *_op)
832829
spin_unlock(&cookie->stores_lock);
833830
spin_unlock(&object->lock);
834831

832+
if (page->index >= op->store_limit)
833+
goto discard_page;
834+
835835
fscache_stat(&fscache_n_store_pages);
836836
fscache_stat(&fscache_n_cop_write_page);
837837
ret = object->cache->ops->write_page(op, page);
@@ -847,6 +847,11 @@ static void fscache_write_op(struct fscache_operation *_op)
847847
_leave("");
848848
return;
849849

850+
discard_page:
851+
fscache_stat(&fscache_n_store_pages_over_limit);
852+
fscache_end_page_write(object, page);
853+
goto again;
854+
850855
superseded:
851856
/* this writer is going away and there aren't any more things to
852857
* write */

0 commit comments

Comments
 (0)