Add information to indicate whether page->mapping should have a value or not, and to log a warning if it is wrong. Signed-off-by: David Howells <dhowells@xxxxxxxxxx> --- fs/cachefiles/rdwr.c | 26 +++++++++++++++++--------- fs/fscache/page.c | 36 +++++++++++++++++++++++++++++++++--- include/linux/fscache-cache.h | 6 ++++-- 3 files changed, 54 insertions(+), 14 deletions(-) diff --git a/fs/cachefiles/rdwr.c b/fs/cachefiles/rdwr.c index 0186fc1..e8c3766 100644 --- a/fs/cachefiles/rdwr.c +++ b/fs/cachefiles/rdwr.c @@ -177,7 +177,7 @@ static void cachefiles_read_copier(struct fscache_operation *_op) if (PageUptodate(monitor->back_page)) { copy_highpage(monitor->netfs_page, monitor->back_page); fscache_mark_page_cached(monitor->op, - monitor->netfs_page); + monitor->netfs_page, true); error = 0; } else if (!PageError(monitor->back_page)) { /* the page has probably been truncated */ @@ -334,7 +334,7 @@ backing_page_already_present: backing_page_already_uptodate: _debug("- uptodate"); - fscache_mark_page_cached(op, netpage); + fscache_mark_page_cached(op, netpage, true); copy_highpage(netpage, backpage); fscache_end_io(op, netpage, 0); @@ -446,7 +446,7 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op, &pagevec); } else if (cachefiles_has_space(cache, 0, 1) == 0) { /* there's space in the cache we can use */ - fscache_mark_page_cached(op, page); + fscache_mark_page_cached(op, page, true); ret = -ENODATA; } else { ret = -ENOBUFS; @@ -622,7 +622,7 @@ static int cachefiles_read_backing_file(struct cachefiles_object *object, page_cache_release(backpage); backpage = NULL; - fscache_mark_page_cached(op, netpage); + fscache_mark_page_cached(op, netpage, true); page_cache_get(netpage); if (!pagevec_add(&lru_pvec, netpage)) @@ -704,6 +704,14 @@ int cachefiles_read_or_alloc_pages(struct fscache_retrieval *op, object->fscache.debug_id, atomic_read(&op->op.usage), *nr_pages); + { + struct page *q, *_q; + list_for_each_entry_safe(q, _q, pages, lru) { + ASSERT(!q->mapping); + ASSERT(!PageFsCache(q)); + } + } + if (!object->backer) return -ENOBUFS; @@ -757,13 +765,13 @@ int cachefiles_read_or_alloc_pages(struct fscache_retrieval *op, (*nr_pages)--; nrbackpages++; } else if (space && pagevec_add(&pagevec, page) == 0) { - fscache_mark_pages_cached(op, &pagevec); + fscache_mark_pages_cached(op, &pagevec, false); ret = -ENODATA; } } if (pagevec_count(&pagevec) > 0) - fscache_mark_pages_cached(op, &pagevec); + fscache_mark_pages_cached(op, &pagevec, false); if (list_empty(pages)) ret = 0; @@ -809,7 +817,7 @@ int cachefiles_allocate_page(struct fscache_retrieval *op, ret = cachefiles_has_space(cache, 0, 1); if (ret == 0) - fscache_mark_page_cached(op, page); + fscache_mark_page_cached(op, page, true); else ret = -ENOBUFS; @@ -852,11 +860,11 @@ int cachefiles_allocate_pages(struct fscache_retrieval *op, list_for_each_entry(page, pages, lru) { if (pagevec_add(&pagevec, page) == 0) - fscache_mark_pages_cached(op, &pagevec); + fscache_mark_pages_cached(op, &pagevec, false); } if (pagevec_count(&pagevec) > 0) - fscache_mark_pages_cached(op, &pagevec); + fscache_mark_pages_cached(op, &pagevec, false); ret = -ENODATA; } else { ret = -ENOBUFS; diff --git a/fs/fscache/page.c b/fs/fscache/page.c index d7c663c..5e793b5 100644 --- a/fs/fscache/page.c +++ b/fs/fscache/page.c @@ -918,11 +918,13 @@ EXPORT_SYMBOL(__fscache_uncache_page); * fscache_mark_page_cached - Mark a page as being cached * @op: The retrieval op pages are being marked for * @page: The page to be marked + * @should_have_mapping: True if the pages should have a mapping set * * Mark a netfs page as being cached. After this is called, the netfs * must call fscache_uncache_page() to remove the mark. */ -void fscache_mark_page_cached(struct fscache_retrieval *op, struct page *page) +void fscache_mark_page_cached(struct fscache_retrieval *op, struct page *page, + bool should_have_mapping) { struct fscache_cookie *cookie = op->op.object->cookie; @@ -941,6 +943,31 @@ void fscache_mark_page_cached(struct fscache_retrieval *op, struct page *page) cookie->def->name, page->index); } } + if (should_have_mapping && !page->mapping) { + static bool once_only; + if (!once_only) { + once_only = 1; + printk(KERN_ALERT + "FSC: page:%p count:%d mapcount:%d NO_MAPPING" + " index:%#lx\n", + page, page_count(page), page_mapcount(page), + page->index); + WARN_ON(1); + } + } + + if (!should_have_mapping && page->mapping) { + static bool once_only; + if (!once_only) { + once_only = 1; + printk(KERN_ALERT + "FSC: page:%p count:%d mapcount:%d MAPPING:%p" + " index:%#lx\n", + page, page_count(page), page_mapcount(page), + page->mapping, page->index); + WARN_ON(1); + } + } if (cookie->def->mark_page_cached) cookie->def->mark_page_cached(cookie->netfs_data, @@ -952,17 +979,20 @@ EXPORT_SYMBOL(fscache_mark_page_cached); * fscache_mark_pages_cached - Mark pages as being cached * @op: The retrieval op pages are being marked for * @pagevec: The pages to be marked + * @should_have_mapping: True if the pages should have a mapping set * * Mark a bunch of netfs pages as being cached. After this is called, * the netfs must call fscache_uncache_page() to remove the mark. */ void fscache_mark_pages_cached(struct fscache_retrieval *op, - struct pagevec *pagevec) + struct pagevec *pagevec, + bool should_have_mapping) { unsigned long loop; for (loop = 0; loop < pagevec->nr; loop++) - fscache_mark_page_cached(op, pagevec->pages[loop]); + fscache_mark_page_cached(op, pagevec->pages[loop], + should_have_mapping); pagevec_reinit(pagevec); } diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h index 485c011..ae155f1 100644 --- a/include/linux/fscache-cache.h +++ b/include/linux/fscache-cache.h @@ -505,10 +505,12 @@ extern void fscache_withdraw_cache(struct fscache_cache *cache); extern void fscache_io_error(struct fscache_cache *cache); extern void fscache_mark_page_cached(struct fscache_retrieval *op, - struct page *page); + struct page *page, + bool should_have_mapping); extern void fscache_mark_pages_cached(struct fscache_retrieval *op, - struct pagevec *pagevec); + struct pagevec *pagevec, + bool should_have_mapping); extern bool fscache_object_sleep_till_congested(signed long *timeoutp); -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html