aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorAlex Elder <elder@inktank.com>2012-11-30 10:59:47 -0500
committerAlex Elder <elder@inktank.com>2013-01-17 17:34:58 -0500
commit2e53c6c379b65372df21f4d6019f6eb63af81384 (patch)
tree8ce8eff65955717f60c9185b86351333d5fd37e0 /drivers/block
parent907703d050df92979b3848ee42f88d5c9c6c13fe (diff)
rbd: don't leak rbd_req on synchronous requests
When rbd_do_request() is called it allocates and populates an rbd_req structure to hold information about the osd request to be sent. This is done for the benefit of the callback function (in particular, rbd_req_cb()), which uses this in processing when the request completes. Synchronous requests provide no callback function, in which case rbd_do_request() waits for the request to complete before returning. This case is not handling the needed free of the rbd_req structure like it should, so it is getting leaked. Note however that the synchronous case has no need for the rbd_req structure at all. So rather than simply freeing this structure for synchronous requests, just don't allocate it to begin with. Signed-off-by: Alex Elder <elder@inktank.com> Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/rbd.c48
1 files changed, 24 insertions, 24 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 9d21fcd7e188..28b62367ff93 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -1113,20 +1113,11 @@ static int rbd_do_request(struct request *rq,
1113 struct ceph_osd_request **linger_req, 1113 struct ceph_osd_request **linger_req,
1114 u64 *ver) 1114 u64 *ver)
1115{ 1115{
1116 struct ceph_osd_client *osdc;
1116 struct ceph_osd_request *osd_req; 1117 struct ceph_osd_request *osd_req;
1117 int ret; 1118 struct rbd_request *rbd_req = NULL;
1118 struct timespec mtime = CURRENT_TIME; 1119 struct timespec mtime = CURRENT_TIME;
1119 struct rbd_request *rbd_req; 1120 int ret;
1120 struct ceph_osd_client *osdc;
1121
1122 rbd_req = kzalloc(sizeof(*rbd_req), GFP_NOIO);
1123 if (!rbd_req)
1124 return -ENOMEM;
1125
1126 if (coll) {
1127 rbd_req->coll = coll;
1128 rbd_req->coll_index = coll_index;
1129 }
1130 1121
1131 dout("rbd_do_request object_name=%s ofs=%llu len=%llu coll=%p[%d]\n", 1122 dout("rbd_do_request object_name=%s ofs=%llu len=%llu coll=%p[%d]\n",
1132 object_name, (unsigned long long) ofs, 1123 object_name, (unsigned long long) ofs,
@@ -1134,10 +1125,8 @@ static int rbd_do_request(struct request *rq,
1134 1125
1135 osdc = &rbd_dev->rbd_client->client->osdc; 1126 osdc = &rbd_dev->rbd_client->client->osdc;
1136 osd_req = ceph_osdc_alloc_request(osdc, snapc, 1, false, GFP_NOIO); 1127 osd_req = ceph_osdc_alloc_request(osdc, snapc, 1, false, GFP_NOIO);
1137 if (!osd_req) { 1128 if (!osd_req)
1138 ret = -ENOMEM; 1129 return -ENOMEM;
1139 goto done_pages;
1140 }
1141 1130
1142 osd_req->r_flags = flags; 1131 osd_req->r_flags = flags;
1143 osd_req->r_pages = pages; 1132 osd_req->r_pages = pages;
@@ -1145,13 +1134,22 @@ static int rbd_do_request(struct request *rq,
1145 osd_req->r_bio = bio; 1134 osd_req->r_bio = bio;
1146 bio_get(osd_req->r_bio); 1135 bio_get(osd_req->r_bio);
1147 } 1136 }
1148 osd_req->r_callback = rbd_cb;
1149 1137
1150 rbd_req->rq = rq; 1138 if (rbd_cb) {
1151 rbd_req->bio = bio; 1139 ret = -ENOMEM;
1152 rbd_req->pages = pages; 1140 rbd_req = kmalloc(sizeof(*rbd_req), GFP_NOIO);
1153 rbd_req->len = len; 1141 if (!rbd_req)
1142 goto done_osd_req;
1143
1144 rbd_req->rq = rq;
1145 rbd_req->bio = bio;
1146 rbd_req->pages = pages;
1147 rbd_req->len = len;
1148 rbd_req->coll = coll;
1149 rbd_req->coll_index = coll ? coll_index : 0;
1150 }
1154 1151
1152 osd_req->r_callback = rbd_cb;
1155 osd_req->r_priv = rbd_req; 1153 osd_req->r_priv = rbd_req;
1156 1154
1157 strncpy(osd_req->r_oid, object_name, sizeof(osd_req->r_oid)); 1155 strncpy(osd_req->r_oid, object_name, sizeof(osd_req->r_oid));
@@ -1193,10 +1191,12 @@ static int rbd_do_request(struct request *rq,
1193 return ret; 1191 return ret;
1194 1192
1195done_err: 1193done_err:
1196 bio_chain_put(rbd_req->bio); 1194 if (bio)
1197 ceph_osdc_put_request(osd_req); 1195 bio_chain_put(osd_req->r_bio);
1198done_pages:
1199 kfree(rbd_req); 1196 kfree(rbd_req);
1197done_osd_req:
1198 ceph_osdc_put_request(osd_req);
1199
1200 return ret; 1200 return ret;
1201} 1201}
1202 1202