summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorYan, Zheng <zyan@redhat.com>2016-05-10 13:09:06 +0200
committerIlya Dryomov <idryomov@gmail.com>2016-05-26 01:15:40 +0200
commitf0b33df57a5f03c637f75ead7cb4d978c59cc63d (patch)
treeae28f322669bce6c48ca4469c0e7d97cc0516fb0 /fs
parentceph: make fault/page_mkwrite return VM_FAULT_OOM for -ENOMEM (diff)
downloadlinux-f0b33df57a5f03c637f75ead7cb4d978c59cc63d.tar.xz
linux-f0b33df57a5f03c637f75ead7cb4d978c59cc63d.zip
ceph: handle -EAGAIN returned by ceph_update_writeable_page()
when ceph_update_writeable_page() return -EAGAIN, caller should lock the page and call ceph_update_writeable_page() again. Signed-off-by: Yan, Zheng <zyan@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/ceph/addr.c28
1 files changed, 15 insertions, 13 deletions
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index d128bb65746d..97ee5d1fbb61 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -1475,21 +1475,23 @@ static int ceph_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
/* Update time before taking page lock */
file_update_time(vma->vm_file);
- lock_page(page);
+ do {
+ lock_page(page);
- if ((off > size) || (page->mapping != inode->i_mapping)) {
- unlock_page(page);
- ret = VM_FAULT_NOPAGE;
- goto out;
- }
+ if ((off > size) || (page->mapping != inode->i_mapping)) {
+ unlock_page(page);
+ ret = VM_FAULT_NOPAGE;
+ break;
+ }
+
+ ret = ceph_update_writeable_page(vma->vm_file, off, len, page);
+ if (ret >= 0) {
+ /* success. we'll keep the page locked. */
+ set_page_dirty(page);
+ ret = VM_FAULT_LOCKED;
+ }
+ } while (ret == -EAGAIN);
- ret = ceph_update_writeable_page(vma->vm_file, off, len, page);
- if (ret >= 0) {
- /* success. we'll keep the page locked. */
- set_page_dirty(page);
- ret = VM_FAULT_LOCKED;
- }
-out:
if (ret == VM_FAULT_LOCKED ||
ci->i_inline_version != CEPH_INLINE_NONE) {
int dirty;