summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYan, Zheng <zyan@redhat.com>2016-05-10 18:59:13 +0800
committerIlya Dryomov <idryomov@gmail.com>2016-05-26 01:15:39 +0200
commit6ce026e411c4f36c9e51189d28a5dd9d08095b9d (patch)
tree7810a4214e5cf24ca843ca1d5c2a39003d76677c
parent4f7e89f6ace0f6cd2f20110efd2d405e26bcbf31 (diff)
downloadlwn-6ce026e411c4f36c9e51189d28a5dd9d08095b9d.tar.gz
lwn-6ce026e411c4f36c9e51189d28a5dd9d08095b9d.zip
ceph: make fault/page_mkwrite return VM_FAULT_OOM for -ENOMEM
Signed-off-by: Yan, Zheng <zyan@redhat.com>
-rw-r--r--fs/ceph/addr.c37
1 files changed, 17 insertions, 20 deletions
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index 3e204b9ff9f7..d128bb65746d 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -1351,10 +1351,9 @@ static int ceph_filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
got = 0;
ret = ceph_get_caps(ci, CEPH_CAP_FILE_RD, want, -1, &got, &pinned_page);
- if (ret < 0) {
- ret = VM_FAULT_SIGBUS;
+ if (ret < 0)
goto out_restore;
- }
+
dout("filemap_fault %p %llu~%zd got cap refs on %s\n",
inode, off, (size_t)PAGE_SIZE, ceph_cap_string(got));
@@ -1392,7 +1391,10 @@ static int ceph_filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
if (ret1 < 0 || off >= i_size_read(inode)) {
unlock_page(page);
put_page(page);
- ret = VM_FAULT_SIGBUS;
+ if (ret1 < 0)
+ ret = ret1;
+ else
+ ret = VM_FAULT_SIGBUS;
goto out_inline;
}
if (ret1 < PAGE_SIZE)
@@ -1408,6 +1410,9 @@ out_inline:
}
out_restore:
ceph_restore_sigs(&oldset);
+ if (ret < 0)
+ ret = (ret == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS;
+
return ret;
}
@@ -1429,7 +1434,7 @@ static int ceph_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
prealloc_cf = ceph_alloc_cap_flush();
if (!prealloc_cf)
- return VM_FAULT_SIGBUS;
+ return VM_FAULT_OOM;
ceph_block_sigs(&oldset);
@@ -1442,10 +1447,8 @@ static int ceph_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
ret = ceph_uninline_data(vma->vm_file, locked_page);
if (locked_page)
unlock_page(locked_page);
- if (ret < 0) {
- ret = VM_FAULT_SIGBUS;
+ if (ret < 0)
goto out_free;
- }
}
if (off + PAGE_SIZE <= size)
@@ -1463,10 +1466,9 @@ static int ceph_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
got = 0;
ret = ceph_get_caps(ci, CEPH_CAP_FILE_WR, want, off + len,
&got, NULL);
- if (ret < 0) {
- ret = VM_FAULT_SIGBUS;
+ if (ret < 0)
goto out_free;
- }
+
dout("page_mkwrite %p %llu~%zd got cap refs on %s\n",
inode, off, len, ceph_cap_string(got));
@@ -1475,10 +1477,9 @@ static int ceph_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
lock_page(page);
- ret = VM_FAULT_NOPAGE;
- if ((off > size) ||
- (page->mapping != inode->i_mapping)) {
+ if ((off > size) || (page->mapping != inode->i_mapping)) {
unlock_page(page);
+ ret = VM_FAULT_NOPAGE;
goto out;
}
@@ -1487,11 +1488,6 @@ static int ceph_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
/* success. we'll keep the page locked. */
set_page_dirty(page);
ret = VM_FAULT_LOCKED;
- } else {
- if (ret == -ENOMEM)
- ret = VM_FAULT_OOM;
- else
- ret = VM_FAULT_SIGBUS;
}
out:
if (ret == VM_FAULT_LOCKED ||
@@ -1512,7 +1508,8 @@ out:
out_free:
ceph_restore_sigs(&oldset);
ceph_free_cap_flush(prealloc_cf);
-
+ if (ret < 0)
+ ret = (ret == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS;
return ret;
}