diff options
-rw-r--r-- | Documentation/filesystems/caching/netfs-api.txt | 18 | ||||
-rw-r--r-- | fs/fscache/page.c | 16 | ||||
-rw-r--r-- | include/linux/fscache.h | 22 |
3 files changed, 55 insertions, 1 deletions
diff --git a/Documentation/filesystems/caching/netfs-api.txt b/Documentation/filesystems/caching/netfs-api.txt index 26c1dd5a6a21..11a0a40ce445 100644 --- a/Documentation/filesystems/caching/netfs-api.txt +++ b/Documentation/filesystems/caching/netfs-api.txt | |||
@@ -499,7 +499,7 @@ Else if there's a copy of the page resident in the cache: | |||
499 | (*) An argument that's 0 on success or negative for an error code. | 499 | (*) An argument that's 0 on success or negative for an error code. |
500 | 500 | ||
501 | If an error occurs, it should be assumed that the page contains no usable | 501 | If an error occurs, it should be assumed that the page contains no usable |
502 | data. | 502 | data. fscache_readpages_cancel() may need to be called. |
503 | 503 | ||
504 | end_io_func() will be called in process context if the read is results in | 504 | end_io_func() will be called in process context if the read is results in |
505 | an error, but it might be called in interrupt context if the read is | 505 | an error, but it might be called in interrupt context if the read is |
@@ -623,6 +623,22 @@ some of the pages being read and some being allocated. Those pages will have | |||
623 | been marked appropriately and will need uncaching. | 623 | been marked appropriately and will need uncaching. |
624 | 624 | ||
625 | 625 | ||
626 | CANCELLATION OF UNREAD PAGES | ||
627 | ---------------------------- | ||
628 | |||
629 | If one or more pages are passed to fscache_read_or_alloc_pages() but not then | ||
630 | read from the cache and also not read from the underlying filesystem then | ||
631 | those pages will need to have any marks and reservations removed. This can be | ||
632 | done by calling: | ||
633 | |||
634 | void fscache_readpages_cancel(struct fscache_cookie *cookie, | ||
635 | struct list_head *pages); | ||
636 | |||
637 | prior to returning to the caller. The cookie argument should be as passed to | ||
638 | fscache_read_or_alloc_pages(). Every page in the pages list will be examined | ||
639 | and any that have PG_fscache set will be uncached. | ||
640 | |||
641 | |||
626 | ============== | 642 | ============== |
627 | PAGE UNCACHING | 643 | PAGE UNCACHING |
628 | ============== | 644 | ============== |
diff --git a/fs/fscache/page.c b/fs/fscache/page.c index 793e3d5ca4b5..8702b732109a 100644 --- a/fs/fscache/page.c +++ b/fs/fscache/page.c | |||
@@ -701,6 +701,22 @@ nobufs: | |||
701 | EXPORT_SYMBOL(__fscache_alloc_page); | 701 | EXPORT_SYMBOL(__fscache_alloc_page); |
702 | 702 | ||
703 | /* | 703 | /* |
704 | * Unmark pages allocate in the readahead code path (via: | ||
705 | * fscache_readpages_or_alloc) after delegating to the base filesystem | ||
706 | */ | ||
707 | void __fscache_readpages_cancel(struct fscache_cookie *cookie, | ||
708 | struct list_head *pages) | ||
709 | { | ||
710 | struct page *page; | ||
711 | |||
712 | list_for_each_entry(page, pages, lru) { | ||
713 | if (PageFsCache(page)) | ||
714 | __fscache_uncache_page(cookie, page); | ||
715 | } | ||
716 | } | ||
717 | EXPORT_SYMBOL(__fscache_readpages_cancel); | ||
718 | |||
719 | /* | ||
704 | * release a write op reference | 720 | * release a write op reference |
705 | */ | 721 | */ |
706 | static void fscache_release_write_op(struct fscache_operation *_op) | 722 | static void fscache_release_write_op(struct fscache_operation *_op) |
diff --git a/include/linux/fscache.h b/include/linux/fscache.h index d984aff32a11..19b46458e4e8 100644 --- a/include/linux/fscache.h +++ b/include/linux/fscache.h | |||
@@ -209,6 +209,8 @@ extern bool __fscache_maybe_release_page(struct fscache_cookie *, struct page *, | |||
209 | gfp_t); | 209 | gfp_t); |
210 | extern void __fscache_uncache_all_inode_pages(struct fscache_cookie *, | 210 | extern void __fscache_uncache_all_inode_pages(struct fscache_cookie *, |
211 | struct inode *); | 211 | struct inode *); |
212 | extern void __fscache_readpages_cancel(struct fscache_cookie *cookie, | ||
213 | struct list_head *pages); | ||
212 | 214 | ||
213 | /** | 215 | /** |
214 | * fscache_register_netfs - Register a filesystem as desiring caching services | 216 | * fscache_register_netfs - Register a filesystem as desiring caching services |
@@ -590,6 +592,26 @@ int fscache_alloc_page(struct fscache_cookie *cookie, | |||
590 | } | 592 | } |
591 | 593 | ||
592 | /** | 594 | /** |
595 | * fscache_readpages_cancel - Cancel read/alloc on pages | ||
596 | * @cookie: The cookie representing the inode's cache object. | ||
597 | * @pages: The netfs pages that we canceled write on in readpages() | ||
598 | * | ||
599 | * Uncache/unreserve the pages reserved earlier in readpages() via | ||
600 | * fscache_readpages_or_alloc() and similar. In most successful caches in | ||
601 | * readpages() this doesn't do anything. In cases when the underlying netfs's | ||
602 | * readahead failed we need to clean up the pagelist (unmark and uncache). | ||
603 | * | ||
604 | * This function may sleep as it may have to clean up disk state. | ||
605 | */ | ||
606 | static inline | ||
607 | void fscache_readpages_cancel(struct fscache_cookie *cookie, | ||
608 | struct list_head *pages) | ||
609 | { | ||
610 | if (fscache_cookie_valid(cookie)) | ||
611 | __fscache_readpages_cancel(cookie, pages); | ||
612 | } | ||
613 | |||
614 | /** | ||
593 | * fscache_write_page - Request storage of a page in the cache | 615 | * fscache_write_page - Request storage of a page in the cache |
594 | * @cookie: The cookie representing the cache object | 616 | * @cookie: The cookie representing the cache object |
595 | * @page: The netfs page to store | 617 | * @page: The netfs page to store |