null_blk: Fix missing mutex_destroy() at module removal
[linux-block.git] / drivers / block / null_blk / main.c
index 71c39bcd872c7ecaabc67e91f35aa2fb267d6826..8c0e5e3fd1edbc0adffc433e068b67caf1ead508 100644 (file)
@@ -225,6 +225,10 @@ static unsigned long g_cache_size;
 module_param_named(cache_size, g_cache_size, ulong, 0444);
 MODULE_PARM_DESC(mbps, "Cache size in MiB for memory-backed device. Default: 0 (none)");
 
+static bool g_fua = true;
+module_param_named(fua, g_fua, bool, 0444);
+MODULE_PARM_DESC(zoned, "Enable/disable FUA support when cache_size is used. Default: true");
+
 static unsigned int g_mbps;
 module_param_named(mbps, g_mbps, uint, 0444);
 MODULE_PARM_DESC(mbps, "Limit maximum bandwidth (in MiB/s). Default: 0 (no limit)");
@@ -253,6 +257,11 @@ static unsigned int g_zone_max_active;
 module_param_named(zone_max_active, g_zone_max_active, uint, 0444);
 MODULE_PARM_DESC(zone_max_active, "Maximum number of active zones when block device is zoned. Default: 0 (no limit)");
 
+static int g_zone_append_max_sectors = INT_MAX;
+module_param_named(zone_append_max_sectors, g_zone_append_max_sectors, int, 0444);
+MODULE_PARM_DESC(zone_append_max_sectors,
+                "Maximum size of a zone append command (in 512B sectors). Specify 0 for zone append emulation");
+
 static struct nullb_device *null_alloc_dev(void);
 static void null_free_dev(struct nullb_device *dev);
 static void null_del_dev(struct nullb *nullb);
@@ -436,10 +445,12 @@ NULLB_DEVICE_ATTR(zone_capacity, ulong, NULL);
 NULLB_DEVICE_ATTR(zone_nr_conv, uint, NULL);
 NULLB_DEVICE_ATTR(zone_max_open, uint, NULL);
 NULLB_DEVICE_ATTR(zone_max_active, uint, NULL);
+NULLB_DEVICE_ATTR(zone_append_max_sectors, uint, NULL);
 NULLB_DEVICE_ATTR(virt_boundary, bool, NULL);
 NULLB_DEVICE_ATTR(no_sched, bool, NULL);
 NULLB_DEVICE_ATTR(shared_tags, bool, NULL);
 NULLB_DEVICE_ATTR(shared_tag_bitmap, bool, NULL);
+NULLB_DEVICE_ATTR(fua, bool, NULL);
 
 static ssize_t nullb_device_power_show(struct config_item *item, char *page)
 {
@@ -580,12 +591,14 @@ static struct configfs_attribute *nullb_device_attrs[] = {
        &nullb_device_attr_zone_nr_conv,
        &nullb_device_attr_zone_max_open,
        &nullb_device_attr_zone_max_active,
+       &nullb_device_attr_zone_append_max_sectors,
        &nullb_device_attr_zone_readonly,
        &nullb_device_attr_zone_offline,
        &nullb_device_attr_virt_boundary,
        &nullb_device_attr_no_sched,
        &nullb_device_attr_shared_tags,
        &nullb_device_attr_shared_tag_bitmap,
+       &nullb_device_attr_fua,
        NULL,
 };
 
@@ -664,14 +677,14 @@ nullb_group_drop_item(struct config_group *group, struct config_item *item)
 static ssize_t memb_group_features_show(struct config_item *item, char *page)
 {
        return snprintf(page, PAGE_SIZE,
-                       "badblocks,blocking,blocksize,cache_size,"
+                       "badblocks,blocking,blocksize,cache_size,fua,"
                        "completion_nsec,discard,home_node,hw_queue_depth,"
                        "irqmode,max_sectors,mbps,memory_backed,no_sched,"
                        "poll_queues,power,queue_mode,shared_tag_bitmap,"
                        "shared_tags,size,submit_queues,use_per_node_hctx,"
                        "virt_boundary,zoned,zone_capacity,zone_max_active,"
                        "zone_max_open,zone_nr_conv,zone_offline,zone_readonly,"
-                       "zone_size\n");
+                       "zone_size,zone_append_max_sectors\n");
 }
 
 CONFIGFS_ATTR_RO(memb_group_, features);
@@ -751,10 +764,13 @@ static struct nullb_device *null_alloc_dev(void)
        dev->zone_nr_conv = g_zone_nr_conv;
        dev->zone_max_open = g_zone_max_open;
        dev->zone_max_active = g_zone_max_active;
+       dev->zone_append_max_sectors = g_zone_append_max_sectors;
        dev->virt_boundary = g_virt_boundary;
        dev->no_sched = g_no_sched;
        dev->shared_tags = g_shared_tags;
        dev->shared_tag_bitmap = g_shared_tag_bitmap;
+       dev->fua = g_fua;
+
        return dev;
 }
 
@@ -1151,7 +1167,7 @@ blk_status_t null_handle_discard(struct nullb_device *dev,
        return BLK_STS_OK;
 }
 
-static int null_handle_flush(struct nullb *nullb)
+static blk_status_t null_handle_flush(struct nullb *nullb)
 {
        int err;
 
@@ -1168,7 +1184,7 @@ static int null_handle_flush(struct nullb *nullb)
 
        WARN_ON(!radix_tree_empty(&nullb->dev->cache));
        spin_unlock_irq(&nullb->lock);
-       return err;
+       return errno_to_blk_status(err);
 }
 
 static int null_transfer(struct nullb *nullb, struct page *page,
@@ -1206,7 +1222,7 @@ static int null_handle_rq(struct nullb_cmd *cmd)
 {
        struct request *rq = blk_mq_rq_from_pdu(cmd);
        struct nullb *nullb = cmd->nq->dev->nullb;
-       int err;
+       int err = 0;
        unsigned int len;
        sector_t sector = blk_rq_pos(rq);
        struct req_iterator iter;
@@ -1218,15 +1234,13 @@ static int null_handle_rq(struct nullb_cmd *cmd)
                err = null_transfer(nullb, bvec.bv_page, len, bvec.bv_offset,
                                     op_is_write(req_op(rq)), sector,
                                     rq->cmd_flags & REQ_FUA);
-               if (err) {
-                       spin_unlock_irq(&nullb->lock);
-                       return err;
-               }
+               if (err)
+                       break;
                sector += len >> SECTOR_SHIFT;
        }
        spin_unlock_irq(&nullb->lock);
 
-       return 0;
+       return errno_to_blk_status(err);
 }
 
 static inline blk_status_t null_handle_throttled(struct nullb_cmd *cmd)
@@ -1273,8 +1287,8 @@ static inline blk_status_t null_handle_memory_backed(struct nullb_cmd *cmd,
 
        if (op == REQ_OP_DISCARD)
                return null_handle_discard(dev, sector, nr_sectors);
-       return errno_to_blk_status(null_handle_rq(cmd));
 
+       return null_handle_rq(cmd);
 }
 
 static void nullb_zero_read_cmd_buffer(struct nullb_cmd *cmd)
@@ -1343,7 +1357,7 @@ static void null_handle_cmd(struct nullb_cmd *cmd, sector_t sector,
        blk_status_t sts;
 
        if (op == REQ_OP_FLUSH) {
-               cmd->error = errno_to_blk_status(null_handle_flush(nullb));
+               cmd->error = null_handle_flush(nullb);
                goto out;
        }
 
@@ -1912,7 +1926,7 @@ static int null_add_dev(struct nullb_device *dev)
 
        if (dev->cache_size > 0) {
                set_bit(NULLB_DEV_FL_CACHE, &nullb->dev->flags);
-               blk_queue_write_cache(nullb->q, true, true);
+               blk_queue_write_cache(nullb->q, true, dev->fua);
        }
 
        nullb->q->queuedata = nullb;
@@ -2113,6 +2127,8 @@ static void __exit null_exit(void)
 
        if (tag_set.ops)
                blk_mq_free_tag_set(&tag_set);
+
+       mutex_destroy(&lock);
 }
 
 module_init(null_init);