ceph: move sb->wb_pagevec_pool to be a global mempool
[linux-2.6-microblaze.git] / fs / ceph / super.c
index c9784eb..7ec0e6d 100644 (file)
@@ -27,6 +27,9 @@
 #include <linux/ceph/auth.h>
 #include <linux/ceph/debugfs.h>
 
+static DEFINE_SPINLOCK(ceph_fsc_lock);
+static LIST_HEAD(ceph_fsc_list);
+
 /*
  * Ceph superblock operations
  *
@@ -634,8 +637,6 @@ static struct ceph_fs_client *create_fs_client(struct ceph_mount_options *fsopt,
                                        struct ceph_options *opt)
 {
        struct ceph_fs_client *fsc;
-       int page_count;
-       size_t size;
        int err;
 
        fsc = kzalloc(sizeof(*fsc), GFP_KERNEL);
@@ -683,18 +684,12 @@ static struct ceph_fs_client *create_fs_client(struct ceph_mount_options *fsopt,
        if (!fsc->cap_wq)
                goto fail_inode_wq;
 
-       /* set up mempools */
-       err = -ENOMEM;
-       page_count = fsc->mount_options->wsize >> PAGE_SHIFT;
-       size = sizeof (struct page *) * (page_count ? page_count : 1);
-       fsc->wb_pagevec_pool = mempool_create_kmalloc_pool(10, size);
-       if (!fsc->wb_pagevec_pool)
-               goto fail_cap_wq;
+       spin_lock(&ceph_fsc_lock);
+       list_add_tail(&fsc->metric_wakeup, &ceph_fsc_list);
+       spin_unlock(&ceph_fsc_lock);
 
        return fsc;
 
-fail_cap_wq:
-       destroy_workqueue(fsc->cap_wq);
 fail_inode_wq:
        destroy_workqueue(fsc->inode_wq);
 fail_client:
@@ -717,12 +712,14 @@ static void destroy_fs_client(struct ceph_fs_client *fsc)
 {
        dout("destroy_fs_client %p\n", fsc);
 
+       spin_lock(&ceph_fsc_lock);
+       list_del(&fsc->metric_wakeup);
+       spin_unlock(&ceph_fsc_lock);
+
        ceph_mdsc_destroy(fsc);
        destroy_workqueue(fsc->inode_wq);
        destroy_workqueue(fsc->cap_wq);
 
-       mempool_destroy(fsc->wb_pagevec_pool);
-
        destroy_mount_options(fsc->mount_options);
 
        ceph_destroy_client(fsc->client);
@@ -741,6 +738,7 @@ struct kmem_cache *ceph_dentry_cachep;
 struct kmem_cache *ceph_file_cachep;
 struct kmem_cache *ceph_dir_file_cachep;
 struct kmem_cache *ceph_mds_request_cachep;
+mempool_t *ceph_wb_pagevec_pool;
 
 static void ceph_inode_init_once(void *foo)
 {
@@ -785,6 +783,10 @@ static int __init init_caches(void)
        if (!ceph_mds_request_cachep)
                goto bad_mds_req;
 
+       ceph_wb_pagevec_pool = mempool_create_kmalloc_pool(10, CEPH_MAX_WRITE_SIZE >> PAGE_SHIFT);
+       if (!ceph_wb_pagevec_pool)
+               goto bad_pagevec_pool;
+
        error = ceph_fscache_register();
        if (error)
                goto bad_fscache;
@@ -793,6 +795,8 @@ static int __init init_caches(void)
 
 bad_fscache:
        kmem_cache_destroy(ceph_mds_request_cachep);
+bad_pagevec_pool:
+       mempool_destroy(ceph_wb_pagevec_pool);
 bad_mds_req:
        kmem_cache_destroy(ceph_dir_file_cachep);
 bad_dir_file:
@@ -823,12 +827,13 @@ static void destroy_caches(void)
        kmem_cache_destroy(ceph_file_cachep);
        kmem_cache_destroy(ceph_dir_file_cachep);
        kmem_cache_destroy(ceph_mds_request_cachep);
+       mempool_destroy(ceph_wb_pagevec_pool);
 
        ceph_fscache_unregister();
 }
 
 /*
- * ceph_umount_begin - initiate forced umount.  Tear down down the
+ * ceph_umount_begin - initiate forced umount.  Tear down the
  * mount, skipping steps that may hang while waiting for server(s).
  */
 static void ceph_umount_begin(struct super_block *sb)
@@ -1282,6 +1287,37 @@ static void __exit exit_ceph(void)
        destroy_caches();
 }
 
+static int param_set_metrics(const char *val, const struct kernel_param *kp)
+{
+       struct ceph_fs_client *fsc;
+       int ret;
+
+       ret = param_set_bool(val, kp);
+       if (ret) {
+               pr_err("Failed to parse sending metrics switch value '%s'\n",
+                      val);
+               return ret;
+       } else if (!disable_send_metrics) {
+               // wake up all the mds clients
+               spin_lock(&ceph_fsc_lock);
+               list_for_each_entry(fsc, &ceph_fsc_list, metric_wakeup) {
+                       metric_schedule_delayed(&fsc->mdsc->metric);
+               }
+               spin_unlock(&ceph_fsc_lock);
+       }
+
+       return 0;
+}
+
+static const struct kernel_param_ops param_ops_metrics = {
+       .set = param_set_metrics,
+       .get = param_get_bool,
+};
+
+bool disable_send_metrics = false;
+module_param_cb(disable_send_metrics, &param_ops_metrics, &disable_send_metrics, 0644);
+MODULE_PARM_DESC(disable_send_metrics, "Enable sending perf metrics to ceph cluster (default: on)");
+
 module_init(init_ceph);
 module_exit(exit_ceph);