* [PATCH 0/2] rbd: fix two memory leaks
@ 2012-11-30 16:03 Alex Elder
2012-11-30 16:04 ` [PATCH 1/2] rbd: don't leak rbd_req on synchronous requests Alex Elder
2012-11-30 16:05 ` [PATCH 2/2] rbd: don't leak rbd_req for rbd_req_sync_notify_ack() Alex Elder
0 siblings, 2 replies; 5+ messages in thread
From: Alex Elder @ 2012-11-30 16:03 UTC (permalink / raw)
To: ceph-devel
This series fixes two memory leaks that occur whenever a "special"
(non I/O) osd request in rbd.
-Alex
[PATCH 1/2] rbd: don't leak rbd_req on synchronous requests
[PATCH 2/2] rbd: don't leak rbd_req for rbd_req_sync_notify_ack()
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/2] rbd: don't leak rbd_req on synchronous requests
2012-11-30 16:03 [PATCH 0/2] rbd: fix two memory leaks Alex Elder
@ 2012-11-30 16:04 ` Alex Elder
2012-12-03 21:06 ` Josh Durgin
2012-11-30 16:05 ` [PATCH 2/2] rbd: don't leak rbd_req for rbd_req_sync_notify_ack() Alex Elder
1 sibling, 1 reply; 5+ messages in thread
From: Alex Elder @ 2012-11-30 16:04 UTC (permalink / raw)
To: ceph-devel
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>
---
drivers/block/rbd.c | 48 ++++++++++++++++++++++++------------------------
1 file changed, 24 insertions(+), 24 deletions(-)
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index acdb4a6..78493e7 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -1160,20 +1160,11 @@ static int rbd_do_request(struct request *rq,
struct ceph_msg *),
u64 *ver)
{
+ struct ceph_osd_client *osdc;
struct ceph_osd_request *osd_req;
- int ret;
+ struct rbd_request *rbd_req = NULL;
struct timespec mtime = CURRENT_TIME;
- struct rbd_request *rbd_req;
- struct ceph_osd_client *osdc;
-
- rbd_req = kzalloc(sizeof(*rbd_req), GFP_NOIO);
- if (!rbd_req)
- return -ENOMEM;
-
- if (coll) {
- rbd_req->coll = coll;
- rbd_req->coll_index = coll_index;
- }
+ int ret;
dout("rbd_do_request object_name=%s ofs=%llu len=%llu coll=%p[%d]\n",
object_name, (unsigned long long) ofs,
@@ -1181,10 +1172,8 @@ static int rbd_do_request(struct request *rq,
osdc = &rbd_dev->rbd_client->client->osdc;
osd_req = ceph_osdc_alloc_request(osdc, snapc, 1, false, GFP_NOIO);
- if (!osd_req) {
- ret = -ENOMEM;
- goto done_pages;
- }
+ if (!osd_req)
+ return -ENOMEM;
osd_req->r_flags = flags;
osd_req->r_pages = pages;
@@ -1192,13 +1181,22 @@ static int rbd_do_request(struct request *rq,
osd_req->r_bio = bio;
bio_get(osd_req->r_bio);
}
- osd_req->r_callback = rbd_cb;
- rbd_req->rq = rq;
- rbd_req->bio = bio;
- rbd_req->pages = pages;
- rbd_req->len = len;
+ if (rbd_cb) {
+ ret = -ENOMEM;
+ rbd_req = kmalloc(sizeof(*rbd_req), GFP_NOIO);
+ if (!rbd_req)
+ goto done_osd_req;
+
+ rbd_req->rq = rq;
+ rbd_req->bio = bio;
+ rbd_req->pages = pages;
+ rbd_req->len = len;
+ rbd_req->coll = coll;
+ rbd_req->coll_index = coll ? coll_index : 0;
+ }
+ osd_req->r_callback = rbd_cb;
osd_req->r_priv = rbd_req;
strncpy(osd_req->r_oid, object_name, sizeof(osd_req->r_oid));
@@ -1233,10 +1231,12 @@ static int rbd_do_request(struct request *rq,
return ret;
done_err:
- bio_chain_put(rbd_req->bio);
- ceph_osdc_put_request(osd_req);
-done_pages:
+ if (bio)
+ bio_chain_put(osd_req->r_bio);
kfree(rbd_req);
+done_osd_req:
+ ceph_osdc_put_request(osd_req);
+
return ret;
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/2] rbd: don't leak rbd_req for rbd_req_sync_notify_ack()
2012-11-30 16:03 [PATCH 0/2] rbd: fix two memory leaks Alex Elder
2012-11-30 16:04 ` [PATCH 1/2] rbd: don't leak rbd_req on synchronous requests Alex Elder
@ 2012-11-30 16:05 ` Alex Elder
2012-12-03 21:07 ` Josh Durgin
1 sibling, 1 reply; 5+ messages in thread
From: Alex Elder @ 2012-11-30 16:05 UTC (permalink / raw)
To: ceph-devel
When rbd_req_sync_notify_ack() calls rbd_do_request() it supplies
rbd_simple_req_cb() as its callback function. Because the callback
is supplied, an rbd_req structure gets allocated and populated so it
can be used by the callback. However rbd_simple_req_cb() is not
freeing (or even using) the rbd_req structure, so it's getting
leaked.
Since rbd_simple_req_cb() has no need for the rbd_req structure,
just avoid allocating one for this case. Of the three calls to
rbd_do_request(), only the one from rbd_do_op() needs the rbd_req
structure, and that call can be distinguished from the other two
because it supplies a non-null rbd_collection pointer.
So fix this leak by only allocating the rbd_req structure if a
non-null "coll" value is provided to rbd_do_request().
Signed-off-by: Alex Elder <elder@inktank.com>
---
drivers/block/rbd.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 78493e7..fca0ebf 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -1182,7 +1182,7 @@ static int rbd_do_request(struct request *rq,
bio_get(osd_req->r_bio);
}
- if (rbd_cb) {
+ if (coll) {
ret = -ENOMEM;
rbd_req = kmalloc(sizeof(*rbd_req), GFP_NOIO);
if (!rbd_req)
@@ -1193,7 +1193,7 @@ static int rbd_do_request(struct request *rq,
rbd_req->pages = pages;
rbd_req->len = len;
rbd_req->coll = coll;
- rbd_req->coll_index = coll ? coll_index : 0;
+ rbd_req->coll_index = coll_index;
}
osd_req->r_callback = rbd_cb;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 1/2] rbd: don't leak rbd_req on synchronous requests
2012-11-30 16:04 ` [PATCH 1/2] rbd: don't leak rbd_req on synchronous requests Alex Elder
@ 2012-12-03 21:06 ` Josh Durgin
0 siblings, 0 replies; 5+ messages in thread
From: Josh Durgin @ 2012-12-03 21:06 UTC (permalink / raw)
To: Alex Elder; +Cc: ceph-devel
Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
On 11/30/2012 08:04 AM, Alex Elder wrote:
> 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>
> ---
> drivers/block/rbd.c | 48 ++++++++++++++++++++++++------------------------
> 1 file changed, 24 insertions(+), 24 deletions(-)
>
> diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
> index acdb4a6..78493e7 100644
> --- a/drivers/block/rbd.c
> +++ b/drivers/block/rbd.c
> @@ -1160,20 +1160,11 @@ static int rbd_do_request(struct request *rq,
> struct ceph_msg *),
> u64 *ver)
> {
> + struct ceph_osd_client *osdc;
> struct ceph_osd_request *osd_req;
> - int ret;
> + struct rbd_request *rbd_req = NULL;
> struct timespec mtime = CURRENT_TIME;
> - struct rbd_request *rbd_req;
> - struct ceph_osd_client *osdc;
> -
> - rbd_req = kzalloc(sizeof(*rbd_req), GFP_NOIO);
> - if (!rbd_req)
> - return -ENOMEM;
> -
> - if (coll) {
> - rbd_req->coll = coll;
> - rbd_req->coll_index = coll_index;
> - }
> + int ret;
>
> dout("rbd_do_request object_name=%s ofs=%llu len=%llu coll=%p[%d]\n",
> object_name, (unsigned long long) ofs,
> @@ -1181,10 +1172,8 @@ static int rbd_do_request(struct request *rq,
>
> osdc = &rbd_dev->rbd_client->client->osdc;
> osd_req = ceph_osdc_alloc_request(osdc, snapc, 1, false, GFP_NOIO);
> - if (!osd_req) {
> - ret = -ENOMEM;
> - goto done_pages;
> - }
> + if (!osd_req)
> + return -ENOMEM;
>
> osd_req->r_flags = flags;
> osd_req->r_pages = pages;
> @@ -1192,13 +1181,22 @@ static int rbd_do_request(struct request *rq,
> osd_req->r_bio = bio;
> bio_get(osd_req->r_bio);
> }
> - osd_req->r_callback = rbd_cb;
>
> - rbd_req->rq = rq;
> - rbd_req->bio = bio;
> - rbd_req->pages = pages;
> - rbd_req->len = len;
> + if (rbd_cb) {
> + ret = -ENOMEM;
> + rbd_req = kmalloc(sizeof(*rbd_req), GFP_NOIO);
> + if (!rbd_req)
> + goto done_osd_req;
> +
> + rbd_req->rq = rq;
> + rbd_req->bio = bio;
> + rbd_req->pages = pages;
> + rbd_req->len = len;
> + rbd_req->coll = coll;
> + rbd_req->coll_index = coll ? coll_index : 0;
> + }
>
> + osd_req->r_callback = rbd_cb;
> osd_req->r_priv = rbd_req;
>
> strncpy(osd_req->r_oid, object_name, sizeof(osd_req->r_oid));
> @@ -1233,10 +1231,12 @@ static int rbd_do_request(struct request *rq,
> return ret;
>
> done_err:
> - bio_chain_put(rbd_req->bio);
> - ceph_osdc_put_request(osd_req);
> -done_pages:
> + if (bio)
> + bio_chain_put(osd_req->r_bio);
> kfree(rbd_req);
> +done_osd_req:
> + ceph_osdc_put_request(osd_req);
> +
> return ret;
> }
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] rbd: don't leak rbd_req for rbd_req_sync_notify_ack()
2012-11-30 16:05 ` [PATCH 2/2] rbd: don't leak rbd_req for rbd_req_sync_notify_ack() Alex Elder
@ 2012-12-03 21:07 ` Josh Durgin
0 siblings, 0 replies; 5+ messages in thread
From: Josh Durgin @ 2012-12-03 21:07 UTC (permalink / raw)
To: Alex Elder; +Cc: ceph-devel
Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
On 11/30/2012 08:05 AM, Alex Elder wrote:
> When rbd_req_sync_notify_ack() calls rbd_do_request() it supplies
> rbd_simple_req_cb() as its callback function. Because the callback
> is supplied, an rbd_req structure gets allocated and populated so it
> can be used by the callback. However rbd_simple_req_cb() is not
> freeing (or even using) the rbd_req structure, so it's getting
> leaked.
>
> Since rbd_simple_req_cb() has no need for the rbd_req structure,
> just avoid allocating one for this case. Of the three calls to
> rbd_do_request(), only the one from rbd_do_op() needs the rbd_req
> structure, and that call can be distinguished from the other two
> because it supplies a non-null rbd_collection pointer.
>
> So fix this leak by only allocating the rbd_req structure if a
> non-null "coll" value is provided to rbd_do_request().
>
> Signed-off-by: Alex Elder <elder@inktank.com>
> ---
> drivers/block/rbd.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
> index 78493e7..fca0ebf 100644
> --- a/drivers/block/rbd.c
> +++ b/drivers/block/rbd.c
> @@ -1182,7 +1182,7 @@ static int rbd_do_request(struct request *rq,
> bio_get(osd_req->r_bio);
> }
>
> - if (rbd_cb) {
> + if (coll) {
> ret = -ENOMEM;
> rbd_req = kmalloc(sizeof(*rbd_req), GFP_NOIO);
> if (!rbd_req)
> @@ -1193,7 +1193,7 @@ static int rbd_do_request(struct request *rq,
> rbd_req->pages = pages;
> rbd_req->len = len;
> rbd_req->coll = coll;
> - rbd_req->coll_index = coll ? coll_index : 0;
> + rbd_req->coll_index = coll_index;
> }
>
> osd_req->r_callback = rbd_cb;
>
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2012-12-03 21:08 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-11-30 16:03 [PATCH 0/2] rbd: fix two memory leaks Alex Elder
2012-11-30 16:04 ` [PATCH 1/2] rbd: don't leak rbd_req on synchronous requests Alex Elder
2012-12-03 21:06 ` Josh Durgin
2012-11-30 16:05 ` [PATCH 2/2] rbd: don't leak rbd_req for rbd_req_sync_notify_ack() Alex Elder
2012-12-03 21:07 ` Josh Durgin
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.