Whamcloud - gitweb
LU-13493 llite: check if page truncated in ll_write_begin() 25/38425/2
authorWang Shilong <wshilong@ddn.com>
Thu, 30 Apr 2020 02:27:06 +0000 (10:27 +0800)
committerOleg Drokin <green@whamcloud.com>
Wed, 20 May 2020 08:25:36 +0000 (08:25 +0000)
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>
lustre/llite/rw26.c
lustre/llite/vvp_io.c

index 6e889a1..2dc2f16 100644 (file)
@@ -598,11 +598,11 @@ out:
        return result;
 }
 
-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) ||
-           PageWriteback(vmpage))
+           PageWriteback(vmpage) || vmpage->mapping != mapping)
                return -ENODATA;
 
        return 0;
@@ -630,7 +630,7 @@ static int ll_write_begin(struct file *file, struct address_space *mapping,
        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);
                GOTO(out, result);
        }
 
@@ -689,6 +689,15 @@ again:
                }
        }
 
+       /* 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));
index 6ae1463..55e21fa 100644 (file)
@@ -992,7 +992,7 @@ void vvp_set_pagevec_dirty(struct pagevec *pvec)
                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 */