See following function flows:
CPU0 CPU1
|->grab_cache_page_nowait
|->find_get_page
|->__find_get_page (page unlocked)
|->truncate page
|->trylock_page —->page might has been truncated after this.
So it is possible that page might has been truncated after
grab_cache_page_nowait() return even page lock is held.
We need check wheather vmpage->mapping change in ll_write_begin()
otherwise, we will have truncated page with NULL mapping, which
will trigger assertions in vvp_set_pagevec_dirty().
This patch also fix assertion string doesn't end in newline.
Change-Id: I46e14f560378a39d8ae1353d60cc49c0f0b241c0
Signed-off-by: Wang Shilong <wshilong@ddn.com>
Reviewed-on: https://review.whamcloud.com/38425
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Bobi Jam <bobijam@hotmail.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
-static int ll_tiny_write_begin(struct page *vmpage)
+static int ll_tiny_write_begin(struct page *vmpage, struct address_space *mapping)
{
/* Page must be present, up to date, dirty, and not in writeback. */
if (!vmpage || !PageUptodate(vmpage) || !PageDirty(vmpage) ||
{
/* Page must be present, up to date, dirty, and not in writeback. */
if (!vmpage || !PageUptodate(vmpage) || !PageDirty(vmpage) ||
+ PageWriteback(vmpage) || vmpage->mapping != mapping)
return -ENODATA;
return 0;
return -ENODATA;
return 0;
lcc = ll_cl_find(file);
if (lcc == NULL) {
vmpage = grab_cache_page_nowait(mapping, index);
lcc = ll_cl_find(file);
if (lcc == NULL) {
vmpage = grab_cache_page_nowait(mapping, index);
- result = ll_tiny_write_begin(vmpage);
+ result = ll_tiny_write_begin(vmpage, mapping);
+ /* page was truncated */
+ if (mapping != vmpage->mapping) {
+ CDEBUG(D_VFSTRACE, "page: %lu was truncated\n", index);
+ unlock_page(vmpage);
+ put_page(vmpage);
+ vmpage = NULL;
+ goto again;
+ }
+
page = cl_page_find(env, clob, vmpage->index, vmpage, CPT_CACHEABLE);
if (IS_ERR(page))
GOTO(out, result = PTR_ERR(page));
page = cl_page_find(env, clob, vmpage->index, vmpage, CPT_CACHEABLE);
if (IS_ERR(page))
GOTO(out, result = PTR_ERR(page));
ClearPageReclaim(pvec->pages[i]);
LASSERTF(page->mapping,
ClearPageReclaim(pvec->pages[i]);
LASSERTF(page->mapping,
- "mapping must be set. page %p, page->private (cl_page) %p",
+ "mapping must be set. page %p, page->private (cl_page) %p\n",
page, (void *) page->private);
/* Rest of code derived from __set_page_dirty_nobuffers */
page, (void *) page->private);
/* Rest of code derived from __set_page_dirty_nobuffers */