aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph/mds_client.c
diff options
context:
space:
mode:
authorYan, Zheng <zyan@redhat.com>2014-09-16 19:15:28 +0800
committerSage Weil <sage@redhat.com>2014-10-14 12:56:49 -0700
commit25e6bae356502cde283f1804111b44e6fad20fc2 (patch)
tree8825e784ff921f4dd27e42b321c1a26cf26b9632 /fs/ceph/mds_client.c
parentlibceph: reference counting pagelist (diff)
downloadlinux-dev-25e6bae356502cde283f1804111b44e6fad20fc2.tar.xz
linux-dev-25e6bae356502cde283f1804111b44e6fad20fc2.zip
ceph: use pagelist to present MDS request data
Current code uses page array to present MDS request data. Pages in the array are allocated/freed by caller of ceph_mdsc_do_request(). If request is interrupted, the pages can be freed while they are still being used by the request message. The fix is use pagelist to present MDS request data. Pagelist is reference counted. Signed-off-by: Yan, Zheng <zyan@redhat.com> Reviewed-by: Sage Weil <sage@redhat.com>
Diffstat (limited to 'fs/ceph/mds_client.c')
-rw-r--r--fs/ceph/mds_client.c14
1 files changed, 9 insertions, 5 deletions
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index b4430ce1b3f6..f8f774e6f868 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -543,6 +543,8 @@ void ceph_mdsc_release_request(struct kref *kref)
}
kfree(req->r_path1);
kfree(req->r_path2);
+ if (req->r_pagelist)
+ ceph_pagelist_release(req->r_pagelist);
put_request_session(req);
ceph_unreserve_caps(req->r_mdsc, &req->r_caps_reservation);
kfree(req);
@@ -1916,13 +1918,15 @@ static struct ceph_msg *create_request_message(struct ceph_mds_client *mdsc,
msg->front.iov_len = p - msg->front.iov_base;
msg->hdr.front_len = cpu_to_le32(msg->front.iov_len);
- if (req->r_data_len) {
- /* outbound data set only by ceph_sync_setxattr() */
- BUG_ON(!req->r_pages);
- ceph_msg_data_add_pages(msg, req->r_pages, req->r_data_len, 0);
+ if (req->r_pagelist) {
+ struct ceph_pagelist *pagelist = req->r_pagelist;
+ atomic_inc(&pagelist->refcnt);
+ ceph_msg_data_add_pagelist(msg, pagelist);
+ msg->hdr.data_len = cpu_to_le32(pagelist->length);
+ } else {
+ msg->hdr.data_len = 0;
}
- msg->hdr.data_len = cpu_to_le32(req->r_data_len);
msg->hdr.data_off = cpu_to_le16(0);
out_free2: