summary refs log tree commit diff
path: root/fs/ceph/addr.c
diff options
context:
space:
mode:
authorYan, Zheng <zyan@redhat.com>2016-05-13 17:29:51 +0800
committerIlya Dryomov <idryomov@gmail.com>2016-05-26 01:15:41 +0200
commitad15ec06e51b6eb73981428109e32c75cbad7d3d (patch)
tree9bd43988e2b973ac091648a3fdd422d399aaa896 /fs/ceph/addr.c
parenta78bbd4b29c29784f0addb5e3b35790c7ed178ae (diff)
downloadlinux-ad15ec06e51b6eb73981428109e32c75cbad7d3d.tar.gz
ceph: handle interrupted ceph_writepage()
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>
Diffstat (limited to 'fs/ceph/addr.c')
-rw-r--r--fs/ceph/addr.c22
1 files changed, 18 insertions, 4 deletions
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index 4aa8e375e648..080a9cab3ee1 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -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.