aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph/addr.c
diff options
context:
space:
mode:
authorYan, Zheng <zyan@redhat.com>2014-11-14 09:10:07 -0500
committerIlya Dryomov <idryomov@redhat.com>2014-12-17 12:09:52 -0500
commit3738daa68a5121ad7dd0318bca931e2a6afb0e8c (patch)
tree8cb3a27c974fa834c2241e9f7335be405053492b /fs/ceph/addr.c
parent01deead041e03c9a6b4e1b2dd165dee4cced6112 (diff)
ceph: fetch inline data when getting Fcr cap refs
we can't use getattr to fetch inline data after getting Fcr caps, because it can cause deadlock. The solution is try bringing inline data to page cache when not holding any cap, and hope the inline data page is still there after getting the Fcr caps. If the page is still there, pin it in page cache for later IO. Signed-off-by: Yan, Zheng <zyan@redhat.com>
Diffstat (limited to 'fs/ceph/addr.c')
-rw-r--r--fs/ceph/addr.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index 4a3f55f27ab4..5d2b88e3ff0b 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -1207,6 +1207,7 @@ static int ceph_filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
1207 struct inode *inode = file_inode(vma->vm_file); 1207 struct inode *inode = file_inode(vma->vm_file);
1208 struct ceph_inode_info *ci = ceph_inode(inode); 1208 struct ceph_inode_info *ci = ceph_inode(inode);
1209 struct ceph_file_info *fi = vma->vm_file->private_data; 1209 struct ceph_file_info *fi = vma->vm_file->private_data;
1210 struct page *pinned_page = NULL;
1210 loff_t off = vmf->pgoff << PAGE_CACHE_SHIFT; 1211 loff_t off = vmf->pgoff << PAGE_CACHE_SHIFT;
1211 int want, got, ret; 1212 int want, got, ret;
1212 1213
@@ -1218,7 +1219,8 @@ static int ceph_filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
1218 want = CEPH_CAP_FILE_CACHE; 1219 want = CEPH_CAP_FILE_CACHE;
1219 while (1) { 1220 while (1) {
1220 got = 0; 1221 got = 0;
1221 ret = ceph_get_caps(ci, CEPH_CAP_FILE_RD, want, &got, -1); 1222 ret = ceph_get_caps(ci, CEPH_CAP_FILE_RD, want, -1,
1223 &got, &pinned_page);
1222 if (ret == 0) 1224 if (ret == 0)
1223 break; 1225 break;
1224 if (ret != -ERESTARTSYS) { 1226 if (ret != -ERESTARTSYS) {
@@ -1233,6 +1235,8 @@ static int ceph_filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
1233 1235
1234 dout("filemap_fault %p %llu~%zd dropping cap refs on %s ret %d\n", 1236 dout("filemap_fault %p %llu~%zd dropping cap refs on %s ret %d\n",
1235 inode, off, (size_t)PAGE_CACHE_SIZE, ceph_cap_string(got), ret); 1237 inode, off, (size_t)PAGE_CACHE_SIZE, ceph_cap_string(got), ret);
1238 if (pinned_page)
1239 page_cache_release(pinned_page);
1236 ceph_put_cap_refs(ci, got); 1240 ceph_put_cap_refs(ci, got);
1237 1241
1238 return ret; 1242 return ret;
@@ -1266,7 +1270,8 @@ static int ceph_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
1266 want = CEPH_CAP_FILE_BUFFER; 1270 want = CEPH_CAP_FILE_BUFFER;
1267 while (1) { 1271 while (1) {
1268 got = 0; 1272 got = 0;
1269 ret = ceph_get_caps(ci, CEPH_CAP_FILE_WR, want, &got, off + len); 1273 ret = ceph_get_caps(ci, CEPH_CAP_FILE_WR, want, off + len,
1274 &got, NULL);
1270 if (ret == 0) 1275 if (ret == 0)
1271 break; 1276 break;
1272 if (ret != -ERESTARTSYS) { 1277 if (ret != -ERESTARTSYS) {