Turn BUG_ON to WARN_ON on xsegbd
[archipelago] / xseg / peers / kernel / xsegbd.c
index d437e2b..38aa85f 100644 (file)
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2012 GRNET S.A.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
 /* xsegbd.c
  *
  */
@@ -25,8 +44,6 @@
 
 #define XSEGBD_MINORS 1
 /* define max request size to be used in xsegbd */
-//FIXME should we make this 4MB instead of 256KB ?
-//#define XSEGBD_MAX_REQUEST_SIZE 262144U
 #define XSEGBD_MAX_REQUEST_SIZE 4194304U
 
 MODULE_DESCRIPTION("xsegbd");
@@ -36,13 +53,16 @@ MODULE_LICENSE("GPL");
 static long sector_size = 0;
 static long blksize = 512;
 static int major = 0;
-static int max_dev = 1024;
+static int max_dev = 200;
+static long start_portno = 0;
+static long end_portno = 199;
 static char name[XSEGBD_SEGMENT_NAMELEN] = "xsegbd";
-static char spec[256] = "segdev:xsegbd:4:1024:12";
+static char spec[256] = "segdev:xsegbd:512:1024:12";
 
 module_param(sector_size, long, 0644);
 module_param(blksize, long, 0644);
-module_param(max_dev, int, 0644);
+module_param(start_portno, long, 0644);
+module_param(end_portno, long, 0644);
 module_param(major, int, 0644);
 module_param_string(name, name, sizeof(name), 0644);
 module_param_string(spec, spec, sizeof(spec), 0644);
@@ -64,6 +84,11 @@ struct xsegbd_device *__xsegbd_get_dev(unsigned long id)
        return xsegbd_dev;
 }
 
+static int src_portno_to_id(xport src_portno)
+{
+       return (src_portno - start_portno);
+}
+
 /* ************************* */
 /* ***** sysfs helpers ***** */
 /* ************************* */
@@ -222,12 +247,12 @@ static int xsegbd_dev_init(struct xsegbd_device *xsegbd_dev)
        queue_flag_set_unlocked(QUEUE_FLAG_NONROT, xsegbd_dev->blk_queue);
 
        /* vkoukis says we don't need partitions */
-       xsegbd_dev->gd = disk = alloc_disk(1);
+       xsegbd_dev->gd = disk = alloc_disk(XSEGBD_MINORS);
        if (!disk)
                goto out;
 
        disk->major = xsegbd_dev->major;
-       disk->first_minor = 0; // id * XSEGBD_MINORS;
+       disk->first_minor = xsegbd_dev->id * XSEGBD_MINORS;
        disk->fops = &xsegbd_ops;
        disk->queue = xsegbd_dev->blk_queue;
        disk->private_data = xsegbd_dev;
@@ -235,7 +260,7 @@ static int xsegbd_dev_init(struct xsegbd_device *xsegbd_dev)
        snprintf(disk->disk_name, 32, "xsegbd%u", xsegbd_dev->id);
 
        ret = 0;
-       
+
        /* allow a non-zero sector_size parameter to override the disk size */
        if (sector_size)
                xsegbd_dev->sectors = sector_size;
@@ -263,13 +288,13 @@ static void xsegbd_dev_release(struct device *dev)
        if (xsegbd_dev->gd) {
                if (xsegbd_dev->gd->flags & GENHD_FL_UP)
                        del_gendisk(xsegbd_dev->gd);
-               
+
                xsegbd_mapclose(xsegbd_dev);
        }
-       
+
        spin_lock(&xsegbd_devices_lock);
-       BUG_ON(xsegbd_devices[xsegbd_dev->src_portno] != xsegbd_dev);
-       xsegbd_devices[xsegbd_dev->src_portno] = NULL;
+       BUG_ON(xsegbd_devices[xsegbd_dev->id] != xsegbd_dev);
+       xsegbd_devices[xsegbd_dev->id] = NULL;
        spin_unlock(&xsegbd_devices_lock);
 
        XSEGLOG("releasing id: %d", xsegbd_dev->id);
@@ -281,7 +306,7 @@ static void xsegbd_dev_release(struct device *dev)
        if (xsegbd_dev->gd)
                put_disk(xsegbd_dev->gd);
 
-//     if (xseg_free_requests(xsegbd_dev->xseg, 
+//     if (xseg_free_requests(xsegbd_dev->xseg,
 //                     xsegbd_dev->src_portno, xsegbd_dev->nr_requests) < 0)
 //             XSEGLOG("Error trying to free requests!\n");
 
@@ -290,8 +315,6 @@ static void xsegbd_dev_release(struct device *dev)
                xsegbd_dev->xseg = NULL;
        }
 
-       unregister_blkdev(xsegbd_dev->major, XSEGBD_NAME);
-
        if (xsegbd_dev->blk_req_pending){
                kfree(xsegbd_dev->blk_req_pending);
                xsegbd_dev->blk_req_pending = NULL;
@@ -368,14 +391,14 @@ static void xseg_request_fn(struct request_queue *rq)
                                                xsegbd_dev->src_portno);
                if (blkreq_idx == Noneidx)
                        break;
-               
+
                if (blkreq_idx >= xsegbd_dev->nr_requests) {
                        XSEGLOG("blkreq_idx >= xsegbd_dev->nr_requests");
-                       BUG_ON(1);
+                       WARN_ON(1);
                        break;
                }
 
-               
+
                spin_lock_irqsave(&xsegbd_dev->rqlock, flags);
                blkreq = blk_fetch_request(rq);
                if (!blkreq){
@@ -402,14 +425,14 @@ static void xseg_request_fn(struct request_queue *rq)
                if (r < 0) {
                        XSEGLOG("couldn't prep request");
                        blk_end_request_err(blkreq, r);
-                       BUG_ON(1);
+                       WARN_ON(1);
                        break;
                }
                r = -ENOMEM;
                if (xreq->bufferlen - xsegbd_dev->targetlen < datalen){
                        XSEGLOG("malformed req buffers");
                        blk_end_request_err(blkreq, r);
-                       BUG_ON(1);
+                       WARN_ON(1);
                        break;
                }
 
@@ -420,7 +443,7 @@ static void xseg_request_fn(struct request_queue *rq)
                pending->dev = xsegbd_dev;
                pending->request = blkreq;
                pending->comp = NULL;
-               
+
                xreq->size = datalen;
                xreq->offset = blk_rq_pos(blkreq) << 9;
                xreq->priv = (uint64_t) blkreq_idx;
@@ -460,10 +483,10 @@ static void xseg_request_fn(struct request_queue *rq)
                WARN_ON(xseg_signal(xsegbd_dev->xsegbd->xseg, p) < 0);
        }
        if (xreq)
-               BUG_ON(xseg_put_request(xsegbd_dev->xsegbd->xseg, xreq, 
+               WARN_ON(xseg_put_request(xsegbd_dev->xsegbd->xseg, xreq, 
                                        xsegbd_dev->src_portno) == -1);
        if (blkreq_idx != Noneidx)
-               BUG_ON(xq_append_head(&xsegbd_dev->blk_queue_pending, 
+               WARN_ON(xq_append_head(&xsegbd_dev->blk_queue_pending, 
                                blkreq_idx, xsegbd_dev->src_portno) == Noneidx);
        spin_lock_irq(&xsegbd_dev->rqlock);
 }
@@ -511,20 +534,20 @@ static int xsegbd_get_size(struct xsegbd_device *xsegbd_dev)
        if (!xreq)
                goto out;
 
-       BUG_ON(xseg_prep_request(xsegbd_dev->xseg, xreq, xsegbd_dev->targetlen, 
+       WARN_ON(xseg_prep_request(xsegbd_dev->xseg, xreq, xsegbd_dev->targetlen, 
                                sizeof(struct xseg_reply_info)));
 
        init_completion(&comp);
        blkreq_idx = xq_pop_head(&xsegbd_dev->blk_queue_pending, 1);
        if (blkreq_idx == Noneidx)
                goto out_put;
-       
+
        pending = &xsegbd_dev->blk_req_pending[blkreq_idx];
        pending->dev = xsegbd_dev;
        pending->request = NULL;
        pending->comp = &comp;
 
-       
+
        xreq->priv = (uint64_t) blkreq_idx;
 
        target = xseg_get_target(xsegbd_dev->xseg, xreq);
@@ -534,11 +557,11 @@ static int xsegbd_get_size(struct xsegbd_device *xsegbd_dev)
        xreq->op = X_INFO;
 
        xseg_prepare_wait(xsegbd_dev->xseg, xsegbd_dev->src_portno);
-       p = xseg_submit(xsegbd_dev->xseg, xreq, 
+       p = xseg_submit(xsegbd_dev->xseg, xreq,
                                xsegbd_dev->src_portno, X_ALLOC);
        if ( p == NoPort) {
                XSEGLOG("couldn't submit request");
-               BUG_ON(1);
+               WARN_ON(1);
                goto out_queue;
        }
        WARN_ON(xseg_signal(xsegbd_dev->xseg, p) < 0);
@@ -553,7 +576,7 @@ out_queue:
        pending->comp = NULL;
        xq_append_head(&xsegbd_dev->blk_queue_pending, blkreq_idx, 1);
 out_put:
-       BUG_ON(xseg_put_request(xsegbd_dev->xseg, xreq, xsegbd_dev->src_portno) == -1);
+       WARN_ON(xseg_put_request(xsegbd_dev->xseg, xreq, xsegbd_dev->src_portno) == -1);
 out:
        return ret;
 }
@@ -573,19 +596,19 @@ static int xsegbd_mapclose(struct xsegbd_device *xsegbd_dev)
        if (!xreq)
                goto out;
 
-       BUG_ON(xseg_prep_request(xsegbd_dev->xseg, xreq, xsegbd_dev->targetlen, 0));
+       WARN_ON(xseg_prep_request(xsegbd_dev->xseg, xreq, xsegbd_dev->targetlen, 0));
 
        init_completion(&comp);
        blkreq_idx = xq_pop_head(&xsegbd_dev->blk_queue_pending, 1);
        if (blkreq_idx == Noneidx)
                goto out_put;
-       
+
        pending = &xsegbd_dev->blk_req_pending[blkreq_idx];
        pending->dev = xsegbd_dev;
        pending->request = NULL;
        pending->comp = &comp;
 
-       
+
        xreq->priv = (uint64_t) blkreq_idx;
 
        target = xseg_get_target(xsegbd_dev->xseg, xreq);
@@ -599,7 +622,7 @@ static int xsegbd_mapclose(struct xsegbd_device *xsegbd_dev)
                                xsegbd_dev->src_portno, X_ALLOC);
        if ( p == NoPort) {
                XSEGLOG("couldn't submit request");
-               BUG_ON(1);
+               WARN_ON(1);
                goto out_queue;
        }
        WARN_ON(xseg_signal(xsegbd_dev->xseg, p) < 0);
@@ -613,7 +636,7 @@ out_queue:
        pending->comp = NULL;
        xq_append_head(&xsegbd_dev->blk_queue_pending, blkreq_idx, 1);
 out_put:
-       BUG_ON(xseg_put_request(xsegbd_dev->xseg, xreq, xsegbd_dev->src_portno) == -1);
+       WARN_ON(xseg_put_request(xsegbd_dev->xseg, xreq, xsegbd_dev->src_portno) == -1);
 out:
        return ret;
 }
@@ -666,14 +689,14 @@ static void xseg_callback(xport portno)
                if (xsegbd_dev != pending->dev) {
                        //FIXME maybe put request?
                        XSEGLOG("xsegbd_dev != pending->dev");
-                       BUG_ON(1);
+                       WARN_ON(1);
                        continue;
                }
                pending->dev = NULL;
                if (!blkreq){
                        //FIXME maybe put request?
                        XSEGLOG("blkreq does not exist");
-                       BUG_ON(1);
+                       WARN_ON(1);
                        continue;
                }
 
@@ -687,10 +710,10 @@ static void xseg_callback(xport portno)
                err = 0;
                if (!rq_data_dir(blkreq)){
                        xseg_to_blk(xsegbd_dev->xseg, xreq, blkreq);
-               }       
+               }
 blk_end:
                blk_end_request_all(blkreq, err);
-               
+
                ridx = xq_append_head(&xsegbd_dev->blk_queue_pending, 
                                        blkreq_idx, xsegbd_dev->src_portno);
                if (ridx == Noneidx) {
@@ -701,7 +724,7 @@ blk_end:
                if (xseg_put_request(xsegbd_dev->xseg, xreq, 
                                                xsegbd_dev->src_portno) < 0){
                        XSEGLOG("couldn't put req");
-                       BUG_ON(1);
+                       WARN_ON(1);
                }
        }
        if (xsegbd_dev) {
@@ -938,30 +961,28 @@ static ssize_t xsegbd_add(struct bus_type *bus, const char *buf, size_t count)
        }
        xsegbd_dev->targetlen = strlen(xsegbd_dev->target);
 
+       if (xsegbd_dev->src_portno < start_portno || xsegbd_dev->src_portno > end_portno){
+               XSEGLOG("Invadid portno");
+               ret = -EINVAL;
+               goto out_dev;
+       }
+       xsegbd_dev->id = src_portno_to_id(xsegbd_dev->src_portno);
+
        spin_lock(&xsegbd_devices_lock);
-       if (xsegbd_devices[xsegbd_dev->src_portno] != NULL) {
+       if (xsegbd_devices[xsegbd_dev->id] != NULL) {
                ret = -EINVAL;
                goto out_unlock;
        }
-       xsegbd_devices[xsegbd_dev->src_portno] = xsegbd_dev;
-       xsegbd_dev->id = xsegbd_dev->src_portno;
+       xsegbd_devices[xsegbd_dev->id] = xsegbd_dev;
        spin_unlock(&xsegbd_devices_lock);
 
-       XSEGLOG("registering block device major %d", major);
-       ret = register_blkdev(major, XSEGBD_NAME);
-       if (ret < 0) {
-               XSEGLOG("cannot register block device!");
-               ret = -EBUSY;
-               goto out_delentry;
-       }
-       xsegbd_dev->major = ret;
-       XSEGLOG("registered block device major %d", xsegbd_dev->major);
+       xsegbd_dev->major = major;
 
        ret = xsegbd_bus_add_dev(xsegbd_dev);
        if (ret)
-               goto out_blkdev;
+               goto out_delentry;
 
-       if (!xq_alloc_seq(&xsegbd_dev->blk_queue_pending, 
+       if (!xq_alloc_seq(&xsegbd_dev->blk_queue_pending,
                                xsegbd_dev->nr_requests,
                                xsegbd_dev->nr_requests))
                goto out_bus;
@@ -972,7 +993,7 @@ static ssize_t xsegbd_add(struct bus_type *bus, const char *buf, size_t count)
        if (!xsegbd_dev->blk_req_pending)
                goto out_bus;
 
-       
+
        XSEGLOG("joining segment");
        //FIXME use xsebd module config for now
        xsegbd_dev->xseg = xseg_join(   xsegbd.config.type,
@@ -981,7 +1002,7 @@ static ssize_t xsegbd_add(struct bus_type *bus, const char *buf, size_t count)
                                        xseg_callback           );
        if (!xsegbd_dev->xseg)
                goto out_bus;
-       
+
        XSEGLOG("%s binding to source port %u (destination %u)", xsegbd_dev->target,
                        xsegbd_dev->src_portno, xsegbd_dev->dst_portno);
        port = xseg_bind_port(xsegbd_dev->xseg, xsegbd_dev->src_portno, NULL);
@@ -994,7 +1015,7 @@ static ssize_t xsegbd_add(struct bus_type *bus, const char *buf, size_t count)
        
        if (xsegbd_dev->src_portno != xseg_portno(xsegbd_dev->xseg, port)) {
                XSEGLOG("portno != xsegbd_dev->src_portno");
-               BUG_ON(1);
+               WARN_ON(1);
                ret = -EFAULT;
                goto out_bus;
        }
@@ -1015,12 +1036,9 @@ out_bus:
        xsegbd_bus_del_dev(xsegbd_dev);
        return ret;
 
-out_blkdev:
-       unregister_blkdev(xsegbd_dev->major, XSEGBD_NAME);
-
 out_delentry:
        spin_lock(&xsegbd_devices_lock);
-       xsegbd_devices[xsegbd_dev->src_portno] = NULL;
+       xsegbd_devices[xsegbd_dev->id] = NULL;
 
 out_unlock:
        spin_unlock(&xsegbd_devices_lock);
@@ -1029,6 +1047,7 @@ out_dev:
        kfree(xsegbd_dev);
 
 out:
+       module_put(THIS_MODULE);
        return ret;
 }
 
@@ -1096,16 +1115,32 @@ static void xsegbd_sysfs_cleanup(void)
 static int __init xsegbd_init(void)
 {
        int ret = -ENOMEM;
+       max_dev = end_portno - start_portno;
+       if (max_dev < 0){
+               XSEGLOG("invalid port numbers");
+               ret = -EINVAL;
+               goto out;
+       }
        xsegbd_devices = kzalloc(max_dev * sizeof(struct xsegbd_devices *), GFP_KERNEL);
        if (!xsegbd_devices)
                goto out;
 
        spin_lock_init(&xsegbd_devices_lock);
 
+       XSEGLOG("registering block device major %d", major);
+       ret = register_blkdev(major, XSEGBD_NAME);
+       if (ret < 0) {
+               XSEGLOG("cannot register block device!");
+               ret = -EBUSY;
+               goto out_free;
+       }
+       major = ret;
+       XSEGLOG("registered block device major %d", major);
+
        ret = -ENOSYS;
        ret = xsegbd_xseg_init();
        if (ret)
-               goto out_free;
+               goto out_unregister;
 
        ret = xsegbd_sysfs_init();
        if (ret)
@@ -1118,7 +1153,10 @@ out:
 
 out_xseg:
        xsegbd_xseg_quit();
-       
+
+out_unregister:
+       unregister_blkdev(major, XSEGBD_NAME);
+
 out_free:
        kfree(xsegbd_devices);
 
@@ -1129,6 +1167,7 @@ static void __exit xsegbd_exit(void)
 {
        xsegbd_sysfs_cleanup();
        xsegbd_xseg_quit();
+       unregister_blkdev(major, XSEGBD_NAME);
 }
 
 module_init(xsegbd_init);