2225 lines · 56.9 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-only/* * Add configfs and memory store: Kyungchan Koh <kkc6196@fb.com> and * Shaohua Li <shli@fb.com> */#include <linux/module.h> #include <linux/moduleparam.h>#include <linux/sched.h>#include <linux/fs.h>#include <linux/init.h>#include "null_blk.h" #undef pr_fmt#define pr_fmt(fmt)	"null_blk: " fmt #define FREE_BATCH		16 #define TICKS_PER_SEC		50ULL#define TIMER_INTERVAL		(NSEC_PER_SEC / TICKS_PER_SEC) #ifdef CONFIG_BLK_DEV_NULL_BLK_FAULT_INJECTIONstatic DECLARE_FAULT_ATTR(null_timeout_attr);static DECLARE_FAULT_ATTR(null_requeue_attr);static DECLARE_FAULT_ATTR(null_init_hctx_attr);#endif static inline u64 mb_per_tick(int mbps){	return (1 << 20) / TICKS_PER_SEC * ((u64) mbps);} /* * Status flags for nullb_device. * * CONFIGURED:	Device has been configured and turned on. Cannot reconfigure. * UP:		Device is currently on and visible in userspace. * THROTTLED:	Device is being throttled. * CACHE:	Device is using a write-back cache. */enum nullb_device_flags {	NULLB_DEV_FL_CONFIGURED	= 0,	NULLB_DEV_FL_UP		= 1,	NULLB_DEV_FL_THROTTLED	= 2,	NULLB_DEV_FL_CACHE	= 3,}; #define MAP_SZ		((PAGE_SIZE >> SECTOR_SHIFT) + 2)/* * nullb_page is a page in memory for nullb devices. * * @page:	The page holding the data. * @bitmap:	The bitmap represents which sector in the page has data. *		Each bit represents one block size. For example, sector 8 *		will use the 7th bit * The highest 2 bits of bitmap are for special purpose. LOCK means the cache * page is being flushing to storage. FREE means the cache page is freed and * should be skipped from flushing to storage. Please see * null_make_cache_space */struct nullb_page {	struct page *page;	DECLARE_BITMAP(bitmap, MAP_SZ);};#define NULLB_PAGE_LOCK (MAP_SZ - 1)#define NULLB_PAGE_FREE (MAP_SZ - 2) static LIST_HEAD(nullb_list);static DEFINE_MUTEX(lock);static int null_major;static DEFINE_IDA(nullb_indexes);static struct blk_mq_tag_set tag_set; enum {	NULL_IRQ_NONE		= 0,	NULL_IRQ_SOFTIRQ	= 1,	NULL_IRQ_TIMER		= 2,}; static bool g_virt_boundary;module_param_named(virt_boundary, g_virt_boundary, bool, 0444);MODULE_PARM_DESC(virt_boundary, "Require a virtual boundary for the device. Default: False"); static int g_no_sched;module_param_named(no_sched, g_no_sched, int, 0444);MODULE_PARM_DESC(no_sched, "No io scheduler"); static int g_submit_queues = 1;module_param_named(submit_queues, g_submit_queues, int, 0444);MODULE_PARM_DESC(submit_queues, "Number of submission queues"); static int g_poll_queues = 1;module_param_named(poll_queues, g_poll_queues, int, 0444);MODULE_PARM_DESC(poll_queues, "Number of IOPOLL submission queues"); static int g_home_node = NUMA_NO_NODE;module_param_named(home_node, g_home_node, int, 0444);MODULE_PARM_DESC(home_node, "Home node for the device"); #ifdef CONFIG_BLK_DEV_NULL_BLK_FAULT_INJECTION/* * For more details about fault injection, please refer to * Documentation/fault-injection/fault-injection.rst. */static char g_timeout_str[80];module_param_string(timeout, g_timeout_str, sizeof(g_timeout_str), 0444);MODULE_PARM_DESC(timeout, "Fault injection. timeout=<interval>,<probability>,<space>,<times>"); static char g_requeue_str[80];module_param_string(requeue, g_requeue_str, sizeof(g_requeue_str), 0444);MODULE_PARM_DESC(requeue, "Fault injection. requeue=<interval>,<probability>,<space>,<times>"); static char g_init_hctx_str[80];module_param_string(init_hctx, g_init_hctx_str, sizeof(g_init_hctx_str), 0444);MODULE_PARM_DESC(init_hctx, "Fault injection to fail hctx init. init_hctx=<interval>,<probability>,<space>,<times>");#endif /* * Historic queue modes. * * These days nothing but NULL_Q_MQ is actually supported, but we keep it the * enum for error reporting. */enum {	NULL_Q_BIO	= 0,	NULL_Q_RQ	= 1,	NULL_Q_MQ	= 2,}; static int g_queue_mode = NULL_Q_MQ; static int null_param_store_val(const char *str, int *val, int min, int max){	int ret, new_val; 	ret = kstrtoint(str, 10, &new_val);	if (ret)		return -EINVAL; 	if (new_val < min || new_val > max)		return -EINVAL; 	*val = new_val;	return 0;} static int null_set_queue_mode(const char *str, const struct kernel_param *kp){	return null_param_store_val(str, &g_queue_mode, NULL_Q_BIO, NULL_Q_MQ);} static const struct kernel_param_ops null_queue_mode_param_ops = {	.set	= null_set_queue_mode,	.get	= param_get_int,}; device_param_cb(queue_mode, &null_queue_mode_param_ops, &g_queue_mode, 0444);MODULE_PARM_DESC(queue_mode, "Block interface to use (0=bio,1=rq,2=multiqueue)"); static int g_gb = 250;module_param_named(gb, g_gb, int, 0444);MODULE_PARM_DESC(gb, "Size in GB"); static int g_bs = 512;module_param_named(bs, g_bs, int, 0444);MODULE_PARM_DESC(bs, "Block size (in bytes)"); static int g_max_sectors;module_param_named(max_sectors, g_max_sectors, int, 0444);MODULE_PARM_DESC(max_sectors, "Maximum size of a command (in 512B sectors)"); static unsigned int nr_devices = 1;module_param(nr_devices, uint, 0444);MODULE_PARM_DESC(nr_devices, "Number of devices to register"); static bool g_blocking;module_param_named(blocking, g_blocking, bool, 0444);MODULE_PARM_DESC(blocking, "Register as a blocking blk-mq driver device"); static bool g_shared_tags;module_param_named(shared_tags, g_shared_tags, bool, 0444);MODULE_PARM_DESC(shared_tags, "Share tag set between devices for blk-mq"); static bool g_shared_tag_bitmap;module_param_named(shared_tag_bitmap, g_shared_tag_bitmap, bool, 0444);MODULE_PARM_DESC(shared_tag_bitmap, "Use shared tag bitmap for all submission queues for blk-mq"); static int g_irqmode = NULL_IRQ_SOFTIRQ; static int null_set_irqmode(const char *str, const struct kernel_param *kp){	return null_param_store_val(str, &g_irqmode, NULL_IRQ_NONE,					NULL_IRQ_TIMER);} static const struct kernel_param_ops null_irqmode_param_ops = {	.set	= null_set_irqmode,	.get	= param_get_int,}; device_param_cb(irqmode, &null_irqmode_param_ops, &g_irqmode, 0444);MODULE_PARM_DESC(irqmode, "IRQ completion handler. 0-none, 1-softirq, 2-timer"); static unsigned long g_completion_nsec = 10000;module_param_named(completion_nsec, g_completion_nsec, ulong, 0444);MODULE_PARM_DESC(completion_nsec, "Time in ns to complete a request in hardware. Default: 10,000ns"); static int g_hw_queue_depth = 64;module_param_named(hw_queue_depth, g_hw_queue_depth, int, 0444);MODULE_PARM_DESC(hw_queue_depth, "Queue depth for each hardware queue. Default: 64"); static bool g_use_per_node_hctx;module_param_named(use_per_node_hctx, g_use_per_node_hctx, bool, 0444);MODULE_PARM_DESC(use_per_node_hctx, "Use per-node allocation for hardware context queues. Default: false"); static bool g_memory_backed;module_param_named(memory_backed, g_memory_backed, bool, 0444);MODULE_PARM_DESC(memory_backed, "Create a memory-backed block device. Default: false"); static bool g_discard;module_param_named(discard, g_discard, bool, 0444);MODULE_PARM_DESC(discard, "Support discard operations (requires memory-backed null_blk device). Default: false"); static unsigned long g_cache_size;module_param_named(cache_size, g_cache_size, ulong, 0444);MODULE_PARM_DESC(cache_size, "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(fua, "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)"); static bool g_zoned;module_param_named(zoned, g_zoned, bool, S_IRUGO);MODULE_PARM_DESC(zoned, "Make device as a host-managed zoned block device. Default: false"); static unsigned long g_zone_size = 256;module_param_named(zone_size, g_zone_size, ulong, S_IRUGO);MODULE_PARM_DESC(zone_size, "Zone size in MB when block device is zoned. Must be power-of-two: Default: 256"); static unsigned long g_zone_capacity;module_param_named(zone_capacity, g_zone_capacity, ulong, 0444);MODULE_PARM_DESC(zone_capacity, "Zone capacity in MB when block device is zoned. Can be less than or equal to zone size. Default: Zone size"); static unsigned int g_zone_nr_conv;module_param_named(zone_nr_conv, g_zone_nr_conv, uint, 0444);MODULE_PARM_DESC(zone_nr_conv, "Number of conventional zones when block device is zoned. Default: 0"); static unsigned int g_zone_max_open;module_param_named(zone_max_open, g_zone_max_open, uint, 0444);MODULE_PARM_DESC(zone_max_open, "Maximum number of open zones when block device is zoned. Default: 0 (no limit)"); 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 bool g_zone_full;module_param_named(zone_full, g_zone_full, bool, S_IRUGO);MODULE_PARM_DESC(zone_full, "Initialize the sequential write required zones of a zoned device to be full. Default: false"); static bool g_rotational;module_param_named(rotational, g_rotational, bool, S_IRUGO);MODULE_PARM_DESC(rotational, "Set the rotational feature for the device. Default: false"); 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);static int null_add_dev(struct nullb_device *dev);static struct nullb *null_find_dev_by_name(const char *name);static void null_free_device_storage(struct nullb_device *dev, bool is_cache); static inline struct nullb_device *to_nullb_device(struct config_item *item){	return item ? container_of(to_config_group(item), struct nullb_device, group) : NULL;} static inline ssize_t nullb_device_uint_attr_show(unsigned int val, char *page){	return snprintf(page, PAGE_SIZE, "%u\n", val);} static inline ssize_t nullb_device_ulong_attr_show(unsigned long val,	char *page){	return snprintf(page, PAGE_SIZE, "%lu\n", val);} static inline ssize_t nullb_device_bool_attr_show(bool val, char *page){	return snprintf(page, PAGE_SIZE, "%u\n", val);} static ssize_t nullb_device_uint_attr_store(unsigned int *val,	const char *page, size_t count){	unsigned int tmp;	int result; 	result = kstrtouint(page, 0, &tmp);	if (result < 0)		return result; 	*val = tmp;	return count;} static ssize_t nullb_device_ulong_attr_store(unsigned long *val,	const char *page, size_t count){	int result;	unsigned long tmp; 	result = kstrtoul(page, 0, &tmp);	if (result < 0)		return result; 	*val = tmp;	return count;} static ssize_t nullb_device_bool_attr_store(bool *val, const char *page,	size_t count){	bool tmp;	int result; 	result = kstrtobool(page,  &tmp);	if (result < 0)		return result; 	*val = tmp;	return count;} /* * The following macro should only be used with TYPE = {uint, ulong, bool}. * * The device configuration is modified under the global lock to serialize * attribute changes against null_add_dev() and null_del_dev(): without this, * an attribute could be changed while null_add_dev() is running, that is, * before NULLB_DEV_FL_CONFIGURED is set, which would let null_add_dev() * observe inconsistent values for the device configuration. */#define NULLB_DEVICE_ATTR(NAME, TYPE, APPLY)				\static ssize_t								\nullb_device_##NAME##_show(struct config_item *item, char *page)	\{									\	guard(mutex)(&lock);						\	return nullb_device_##TYPE##_attr_show(				\				to_nullb_device(item)->NAME, page);	\}									\static ssize_t								\nullb_device_##NAME##_store(struct config_item *item, const char *page,	\			    size_t count)				\{									\	int (*apply_fn)(struct nullb_device *dev, TYPE new_value) = APPLY;\	struct nullb_device *dev = to_nullb_device(item);		\	TYPE new_value = 0;						\	int ret;							\									\	ret = nullb_device_##TYPE##_attr_store(&new_value, page, count);\	if (ret < 0)							\		return ret;						\	guard(mutex)(&lock);						\	if (apply_fn)							\		ret = apply_fn(dev, new_value);				\	else if (test_bit(NULLB_DEV_FL_CONFIGURED, &dev->flags)) 	\		ret = -EBUSY;						\	if (ret < 0)							\		return ret;						\	dev->NAME = new_value;						\	return count;							\}									\CONFIGFS_ATTR(nullb_device_, NAME); static int nullb_update_nr_hw_queues(struct nullb_device *dev,				     unsigned int submit_queues,				     unsigned int poll_queues) {	struct blk_mq_tag_set *set;	int ret, nr_hw_queues; 	lockdep_assert_held(&lock); 	if (!dev->nullb)		return 0; 	/*	 * A shared tag_set is mapped via the module-wide queue counts, so a	 * per-device resize is meaningless. On shrink it would also leave	 * mq_map[] pointing at NULLed hctx slots, causing a NULL deref in	 * blk_mq_map_swqueue(). Reject it.	 */	if (dev->shared_tags)		return -EINVAL; 	/*	 * Make sure at least one submit queue exists.	 */	if (!submit_queues)		return -EINVAL; 	/*	 * Make sure that null_init_hctx() does not access nullb->queues[] past	 * the end of that array.	 */	if (submit_queues > nr_cpu_ids || poll_queues > g_poll_queues)		return -EINVAL; 	/*	 * Keep previous and new queue numbers in nullb_device for reference in	 * the call back function null_map_queues().	 */	dev->prev_submit_queues = dev->submit_queues;	dev->prev_poll_queues = dev->poll_queues;	dev->submit_queues = submit_queues;	dev->poll_queues = poll_queues; 	set = dev->nullb->tag_set;	nr_hw_queues = submit_queues + poll_queues;	blk_mq_update_nr_hw_queues(set, nr_hw_queues);	ret = set->nr_hw_queues == nr_hw_queues ? 0 : -ENOMEM; 	if (ret) {		/* on error, revert the queue numbers */		dev->submit_queues = dev->prev_submit_queues;		dev->poll_queues = dev->prev_poll_queues;	} 	return ret;} static int nullb_apply_submit_queues(struct nullb_device *dev,				     unsigned int submit_queues){	return nullb_update_nr_hw_queues(dev, submit_queues, dev->poll_queues);} static int nullb_apply_poll_queues(struct nullb_device *dev,				   unsigned int poll_queues){	return nullb_update_nr_hw_queues(dev, dev->submit_queues, poll_queues);} NULLB_DEVICE_ATTR(size, ulong, NULL);NULLB_DEVICE_ATTR(completion_nsec, ulong, NULL);NULLB_DEVICE_ATTR(submit_queues, uint, nullb_apply_submit_queues);NULLB_DEVICE_ATTR(poll_queues, uint, nullb_apply_poll_queues);NULLB_DEVICE_ATTR(home_node, uint, NULL);NULLB_DEVICE_ATTR(queue_mode, uint, NULL);NULLB_DEVICE_ATTR(blocksize, uint, NULL);NULLB_DEVICE_ATTR(max_sectors, uint, NULL);NULLB_DEVICE_ATTR(irqmode, uint, NULL);NULLB_DEVICE_ATTR(hw_queue_depth, uint, NULL);NULLB_DEVICE_ATTR(index, uint, NULL);NULLB_DEVICE_ATTR(blocking, bool, NULL);NULLB_DEVICE_ATTR(use_per_node_hctx, bool, NULL);NULLB_DEVICE_ATTR(memory_backed, bool, NULL);NULLB_DEVICE_ATTR(discard, bool, NULL);NULLB_DEVICE_ATTR(mbps, uint, NULL);NULLB_DEVICE_ATTR(cache_size, ulong, NULL);NULLB_DEVICE_ATTR(zoned, bool, NULL);NULLB_DEVICE_ATTR(zone_size, ulong, NULL);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(zone_full, bool, 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);NULLB_DEVICE_ATTR(rotational, bool, NULL);NULLB_DEVICE_ATTR(badblocks_once, bool, NULL);NULLB_DEVICE_ATTR(badblocks_partial_io, bool, NULL); static ssize_t nullb_device_power_show(struct config_item *item, char *page){	guard(mutex)(&lock);	return nullb_device_bool_attr_show(to_nullb_device(item)->power, page);} static ssize_t nullb_device_power_store(struct config_item *item,				     const char *page, size_t count){	struct nullb_device *dev = to_nullb_device(item);	bool newp = false;	ssize_t ret; 

Lines 1–500 of 2225.