summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/kernel/core.c48
1 files changed, 29 insertions, 19 deletions
diff --git a/src/kernel/core.c b/src/kernel/core.c
index 8da2b39..a0854dd 100644
--- a/src/kernel/core.c
+++ b/src/kernel/core.c
@@ -55,12 +55,12 @@
-struct workqueue_struct *dnbd3_wq;
+struct workqueue_struct *dnbd3_wq = NULL;
DEFINE_IDR(dnbd3_index_idr);
DEFINE_MUTEX(dnbd3_index_mutex);
static unsigned int max_devs = NUMBER_DEVICES;
-static struct dnbd3_device *device;
+static struct dnbd3_device *device = NULL;
int major;
/**
@@ -350,8 +350,20 @@ out_free_dnbd3:
*/
static int __init dnbd3_init(void)
{
- int i;
- debug("starting kernel module");
+ int i, retval;
+ debug("initializing dnbd3 kernel module");
+
+ if (max_devs <= 0 || max_devs >= 256) {
+ error("max_devs must be between 1 and 255");
+ return -EINVAL;
+ }
+
+ device = kcalloc(max_devs, sizeof(*device), GFP_KERNEL);
+ if (!device) {
+ error("failed to allocate memory for dnbd3 device structs");
+ retval = -ENOMEM;
+ goto error;
+ }
/*
* allocate a workqueue/thread for this modul
@@ -361,28 +373,20 @@ static int __init dnbd3_init(void)
*/
dnbd3_wq = alloc_workqueue("kdnbd3",
WQ_MEM_RECLAIM | WQ_FREEZABLE | WQ_UNBOUND, 0);
-
- if (max_devs < 0) {
- error("max_devs must be >= 0");
- return -EINVAL;
- }
-
-
- device = kcalloc(max_devs, sizeof(*device), GFP_KERNEL);
- if (!device) {
- error("failed to create dnbd3 device");
- return -ENOMEM;
+ if (!dnbd3_wq) {
+ error("error allocating workqueue");
+ retval = -ENOMEM;
+ goto error;
}
// initialize block device
major = register_blkdev(0, "dnbd3");
if (major == 0) {
error("register_blkdev failed");
- return -EIO;
+ retval = -EIO;
+ goto error;
}
- debug("kernel module loaded. Machine type: " ENDIAN_MODE);
-
// add MAX_NUMBER_DEVICES devices
mutex_lock(&dnbd3_index_mutex);
for (i = 0; i < max_devs; i++) {
@@ -393,6 +397,13 @@ static int __init dnbd3_init(void)
info("init successful (%i devices)", max_devs);
return 0;
+error:
+ if (device) {
+ kfree(device);
+ }
+ if (dnbd3_wq) {
+ destroy_workqueue(dnbd3_wq);
+ }
}
/**
@@ -465,7 +476,6 @@ static void __exit dnbd3_exit(void)
unregister_blkdev(major, "dnbd3");
kfree(device);
-
destroy_workqueue(dnbd3_wq);
info("stopped kernel module");