diff options
author | Alex Elder <elder@inktank.com> | 2012-11-30 10:59:47 -0500 |
---|---|---|
committer | Alex Elder <elder@inktank.com> | 2013-01-17 17:34:58 -0500 |
commit | 2e53c6c379b65372df21f4d6019f6eb63af81384 (patch) | |
tree | 8ce8eff65955717f60c9185b86351333d5fd37e0 /drivers/block | |
parent | 907703d050df92979b3848ee42f88d5c9c6c13fe (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.c | 48 |
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 | ||
1195 | done_err: | 1193 | done_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); |
1198 | done_pages: | ||
1199 | kfree(rbd_req); | 1196 | kfree(rbd_req); |
1197 | done_osd_req: | ||
1198 | ceph_osdc_put_request(osd_req); | ||
1199 | |||
1200 | return ret; | 1200 | return ret; |
1201 | } | 1201 | } |
1202 | 1202 | ||