|
@@ -99,6 +99,8 @@ struct ubiblock {
|
|
|
|
|
|
/* Linked list of all ubiblock instances */
|
|
|
static LIST_HEAD(ubiblock_devices);
|
|
|
+static DEFINE_IDR(ubiblock_minor_idr);
|
|
|
+/* Protects ubiblock_devices and ubiblock_minor_idr */
|
|
|
static DEFINE_MUTEX(devices_mutex);
|
|
|
static int ubiblock_major;
|
|
|
|
|
@@ -351,8 +353,6 @@ static const struct blk_mq_ops ubiblock_mq_ops = {
|
|
|
.init_request = ubiblock_init_request,
|
|
|
};
|
|
|
|
|
|
-static DEFINE_IDR(ubiblock_minor_idr);
|
|
|
-
|
|
|
int ubiblock_create(struct ubi_volume_info *vi)
|
|
|
{
|
|
|
struct ubiblock *dev;
|
|
@@ -365,14 +365,15 @@ int ubiblock_create(struct ubi_volume_info *vi)
|
|
|
/* Check that the volume isn't already handled */
|
|
|
mutex_lock(&devices_mutex);
|
|
|
if (find_dev_nolock(vi->ubi_num, vi->vol_id)) {
|
|
|
- mutex_unlock(&devices_mutex);
|
|
|
- return -EEXIST;
|
|
|
+ ret = -EEXIST;
|
|
|
+ goto out_unlock;
|
|
|
}
|
|
|
- mutex_unlock(&devices_mutex);
|
|
|
|
|
|
dev = kzalloc(sizeof(struct ubiblock), GFP_KERNEL);
|
|
|
- if (!dev)
|
|
|
- return -ENOMEM;
|
|
|
+ if (!dev) {
|
|
|
+ ret = -ENOMEM;
|
|
|
+ goto out_unlock;
|
|
|
+ }
|
|
|
|
|
|
mutex_init(&dev->dev_mutex);
|
|
|
|
|
@@ -437,14 +438,13 @@ int ubiblock_create(struct ubi_volume_info *vi)
|
|
|
goto out_free_queue;
|
|
|
}
|
|
|
|
|
|
- mutex_lock(&devices_mutex);
|
|
|
list_add_tail(&dev->list, &ubiblock_devices);
|
|
|
- mutex_unlock(&devices_mutex);
|
|
|
|
|
|
/* Must be the last step: anyone can call file ops from now on */
|
|
|
add_disk(dev->gd);
|
|
|
dev_info(disk_to_dev(dev->gd), "created from ubi%d:%d(%s)",
|
|
|
dev->ubi_num, dev->vol_id, vi->name);
|
|
|
+ mutex_unlock(&devices_mutex);
|
|
|
return 0;
|
|
|
|
|
|
out_free_queue:
|
|
@@ -457,6 +457,8 @@ out_put_disk:
|
|
|
put_disk(dev->gd);
|
|
|
out_free_dev:
|
|
|
kfree(dev);
|
|
|
+out_unlock:
|
|
|
+ mutex_unlock(&devices_mutex);
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
@@ -478,30 +480,36 @@ static void ubiblock_cleanup(struct ubiblock *dev)
|
|
|
int ubiblock_remove(struct ubi_volume_info *vi)
|
|
|
{
|
|
|
struct ubiblock *dev;
|
|
|
+ int ret;
|
|
|
|
|
|
mutex_lock(&devices_mutex);
|
|
|
dev = find_dev_nolock(vi->ubi_num, vi->vol_id);
|
|
|
if (!dev) {
|
|
|
- mutex_unlock(&devices_mutex);
|
|
|
- return -ENODEV;
|
|
|
+ ret = -ENODEV;
|
|
|
+ goto out_unlock;
|
|
|
}
|
|
|
|
|
|
/* Found a device, let's lock it so we can check if it's busy */
|
|
|
mutex_lock(&dev->dev_mutex);
|
|
|
if (dev->refcnt > 0) {
|
|
|
- mutex_unlock(&dev->dev_mutex);
|
|
|
- mutex_unlock(&devices_mutex);
|
|
|
- return -EBUSY;
|
|
|
+ ret = -EBUSY;
|
|
|
+ goto out_unlock_dev;
|
|
|
}
|
|
|
|
|
|
/* Remove from device list */
|
|
|
list_del(&dev->list);
|
|
|
- mutex_unlock(&devices_mutex);
|
|
|
-
|
|
|
ubiblock_cleanup(dev);
|
|
|
mutex_unlock(&dev->dev_mutex);
|
|
|
+ mutex_unlock(&devices_mutex);
|
|
|
+
|
|
|
kfree(dev);
|
|
|
return 0;
|
|
|
+
|
|
|
+out_unlock_dev:
|
|
|
+ mutex_unlock(&dev->dev_mutex);
|
|
|
+out_unlock:
|
|
|
+ mutex_unlock(&devices_mutex);
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
static int ubiblock_resize(struct ubi_volume_info *vi)
|
|
@@ -630,6 +638,7 @@ static void ubiblock_remove_all(void)
|
|
|
struct ubiblock *next;
|
|
|
struct ubiblock *dev;
|
|
|
|
|
|
+ mutex_lock(&devices_mutex);
|
|
|
list_for_each_entry_safe(dev, next, &ubiblock_devices, list) {
|
|
|
/* The module is being forcefully removed */
|
|
|
WARN_ON(dev->desc);
|
|
@@ -638,6 +647,7 @@ static void ubiblock_remove_all(void)
|
|
|
ubiblock_cleanup(dev);
|
|
|
kfree(dev);
|
|
|
}
|
|
|
+ mutex_unlock(&devices_mutex);
|
|
|
}
|
|
|
|
|
|
int __init ubiblock_init(void)
|