ceph: handle errors during osd client init

Unwind initializing if we get ENOMEM during client initialization.

Signed-off-by: Sage Weil <sage@newdream.net>
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index fdecf99..69feeb1 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -2552,7 +2552,7 @@
 }
 
 
-void ceph_mdsc_init(struct ceph_mds_client *mdsc, struct ceph_client *client)
+int ceph_mdsc_init(struct ceph_mds_client *mdsc, struct ceph_client *client)
 {
 	mdsc->client = client;
 	mutex_init(&mdsc->mutex);
@@ -2582,6 +2582,7 @@
 	init_waitqueue_head(&mdsc->cap_flushing_wq);
 	spin_lock_init(&mdsc->dentry_lru_lock);
 	INIT_LIST_HEAD(&mdsc->dentry_lru);
+	return 0;
 }
 
 /*
diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h
index 0751b82..7c43948 100644
--- a/fs/ceph/mds_client.h
+++ b/fs/ceph/mds_client.h
@@ -282,7 +282,7 @@
 extern int ceph_send_msg_mds(struct ceph_mds_client *mdsc,
 			     struct ceph_msg *msg, int mds);
 
-extern void ceph_mdsc_init(struct ceph_mds_client *mdsc,
+extern int ceph_mdsc_init(struct ceph_mds_client *mdsc,
 			   struct ceph_client *client);
 extern void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc);
 extern void ceph_mdsc_stop(struct ceph_mds_client *mdsc);
diff --git a/fs/ceph/osd_client.c b/fs/ceph/osd_client.c
index bcb9fe6..0a16c4f 100644
--- a/fs/ceph/osd_client.c
+++ b/fs/ceph/osd_client.c
@@ -1127,19 +1127,26 @@
 	osdc->num_requests = 0;
 	INIT_DELAYED_WORK(&osdc->timeout_work, handle_timeout);
 
+	err = -ENOMEM;
 	osdc->req_mempool = mempool_create_kmalloc_pool(10,
 					sizeof(struct ceph_osd_request));
 	if (!osdc->req_mempool)
-		return -ENOMEM;
+		goto out;
 
 	err = ceph_msgpool_init(&osdc->msgpool_op, 4096, 10, true);
 	if (err < 0)
-		return -ENOMEM;
+		goto out_mempool;
 	err = ceph_msgpool_init(&osdc->msgpool_op_reply, 512, 0, false);
 	if (err < 0)
-		return -ENOMEM;
-
+		goto out_msgpool;
 	return 0;
+
+out_msgpool:
+	ceph_msgpool_destroy(&osdc->msgpool_op);
+out_mempool:
+	mempool_destroy(osdc->req_mempool);
+out:
+	return err;
 }
 
 void ceph_osdc_stop(struct ceph_osd_client *osdc)
diff --git a/fs/ceph/super.c b/fs/ceph/super.c
index 1ac7b07..fe0a596 100644
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@ -530,9 +530,13 @@
 	err = ceph_osdc_init(&client->osdc, client);
 	if (err < 0)
 		goto fail_monc;
-	ceph_mdsc_init(&client->mdsc, client);
+	err = ceph_mdsc_init(&client->mdsc, client);
+	if (err < 0)
+		goto fail_osdc;
 	return client;
 
+fail_osdc:
+	ceph_osdc_stop(&client->osdc);
 fail_monc:
 	ceph_monc_stop(&client->monc);
 fail_trunc_wq: