aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Elder <elder@inktank.com>2013-05-16 16:04:20 -0400
committerAlex Elder <elder@inktank.com>2013-05-17 13:50:03 -0400
commit7262cfca430a1a0e0707149af29ae86bc0ded230 (patch)
tree30b8e36ffebad551fd4e4392ca9f49fd22d2298c
parent39be95e9c8c0b5668c9f8806ffe29bf9f4bc0f40 (diff)
rbd: don't destroy ceph_opts in rbd_add()
Whether rbd_client_create() successfully creates a new client or not, it takes responsibility for getting the ceph_opts structure it's passed destroyed. If successful, the structure becomes associated with the created client; if not, rbd_client_create() will destroy it. Previously, rbd_get_client() would call ceph_destroy_options() if rbd_get_client() failed, and that meant it got called twice. That led freeing various pointers more than once, which is never a good idea. This resolves: http://tracker.ceph.com/issues/4559 Cc: stable@vger.kernel.org # 3.8+ Reported-by: Dan van der Ster <dan@vanderster.com> Signed-off-by: Alex Elder <elder@inktank.com> Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
-rw-r--r--drivers/block/rbd.c10
1 files changed, 4 insertions, 6 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 6b872f219774..5f64ba77bc7f 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -521,8 +521,8 @@ static const struct block_device_operations rbd_bd_ops = {
521}; 521};
522 522
523/* 523/*
524 * Initialize an rbd client instance. 524 * Initialize an rbd client instance. Success or not, this function
525 * We own *ceph_opts. 525 * consumes ceph_opts.
526 */ 526 */
527static struct rbd_client *rbd_client_create(struct ceph_options *ceph_opts) 527static struct rbd_client *rbd_client_create(struct ceph_options *ceph_opts)
528{ 528{
@@ -677,7 +677,8 @@ static int parse_rbd_opts_token(char *c, void *private)
677 677
678/* 678/*
679 * Get a ceph client with specific addr and configuration, if one does 679 * Get a ceph client with specific addr and configuration, if one does
680 * not exist create it. 680 * not exist create it. Either way, ceph_opts is consumed by this
681 * function.
681 */ 682 */
682static struct rbd_client *rbd_get_client(struct ceph_options *ceph_opts) 683static struct rbd_client *rbd_get_client(struct ceph_options *ceph_opts)
683{ 684{
@@ -4994,7 +4995,6 @@ static ssize_t rbd_add(struct bus_type *bus,
4994 rc = PTR_ERR(rbdc); 4995 rc = PTR_ERR(rbdc);
4995 goto err_out_args; 4996 goto err_out_args;
4996 } 4997 }
4997 ceph_opts = NULL; /* rbd_dev client now owns this */
4998 4998
4999 /* pick the pool */ 4999 /* pick the pool */
5000 osdc = &rbdc->client->osdc; 5000 osdc = &rbdc->client->osdc;
@@ -5038,8 +5038,6 @@ err_out_rbd_dev:
5038err_out_client: 5038err_out_client:
5039 rbd_put_client(rbdc); 5039 rbd_put_client(rbdc);
5040err_out_args: 5040err_out_args:
5041 if (ceph_opts)
5042 ceph_destroy_options(ceph_opts);
5043 kfree(rbd_opts); 5041 kfree(rbd_opts);
5044 rbd_spec_put(spec); 5042 rbd_spec_put(spec);
5045err_out_module: 5043err_out_module: