diff options
author | Yan, Zheng <zyan@redhat.com> | 2016-05-10 13:09:06 +0200 |
---|---|---|
committer | Ilya Dryomov <idryomov@gmail.com> | 2016-05-26 01:15:40 +0200 |
commit | f0b33df57a5f03c637f75ead7cb4d978c59cc63d (patch) | |
tree | ae28f322669bce6c48ca4469c0e7d97cc0516fb0 /fs | |
parent | ceph: make fault/page_mkwrite return VM_FAULT_OOM for -ENOMEM (diff) | |
download | linux-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.c | 28 |
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; |