ceph: handle interrupted ceph_writepage()
authorYan, Zheng <zyan@redhat.com>
Fri, 13 May 2016 09:29:51 +0000 (17:29 +0800)
committerIlya Dryomov <idryomov@gmail.com>
Wed, 25 May 2016 23:15:41 +0000 (01:15 +0200)
writepage() can be interrupted when it's called by direct memory
reclaimer (the direct memory relaimer is killed). To avoid lossing
data, we redirty the page.

Signed-off-by: Yan, Zheng <zyan@redhat.com>
fs/ceph/addr.c

index 4aa8e375e648bc49c3bf8dba6d8d6d545787d706..080a9cab3ee17f3975f759a1846805cc7e8aa4fa 100644 (file)
@@ -544,11 +544,21 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc)
                                   truncate_seq, truncate_size,
                                   &inode->i_mtime, &page, 1);
        if (err < 0) {
-               dout("writepage setting page/mapping error %d %p\n", err, page);
+               struct writeback_control tmp_wbc;
+               if (!wbc)
+                       wbc = &tmp_wbc;
+               if (err == -ERESTARTSYS) {
+                       /* killed by SIGKILL */
+                       dout("writepage interrupted page %p\n", page);
+                       redirty_page_for_writepage(wbc, page);
+                       end_page_writeback(page);
+                       goto out;
+               }
+               dout("writepage setting page/mapping error %d %p\n",
+                    err, page);
                SetPageError(page);
                mapping_set_error(&inode->i_data, err);
-               if (wbc)
-                       wbc->pages_skipped++;
+               wbc->pages_skipped++;
        } else {
                dout("writepage cleaned page %p\n", page);
                err = 0;  /* vfs expects us to return 0 */
@@ -569,12 +579,16 @@ static int ceph_writepage(struct page *page, struct writeback_control *wbc)
        BUG_ON(!inode);
        ihold(inode);
        err = writepage_nounlock(page, wbc);
+       if (err == -ERESTARTSYS) {
+               /* direct memory reclaimer was killed by SIGKILL. return 0
+                * to prevent caller from setting mapping/page error */
+               err = 0;
+       }
        unlock_page(page);
        iput(inode);
        return err;
 }
 
-
 /*
  * lame release_pages helper.  release_pages() isn't exported to
  * modules.