Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5309cb38 authored by Jens Axboe's avatar Jens Axboe
Browse files

Add queue resizing support



Just get rid of the preallocated command map, use the slab cache
to get/free commands instead.

Original patch from FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>,
changed by me to not use a mempool.

Signed-off-by: default avatarJens Axboe <jens.axboe@oracle.com>
parent 3862153b
Loading
Loading
Loading
Loading
+32 −64
Original line number Diff line number Diff line
@@ -33,8 +33,6 @@

static char bsg_version[] = "block layer sg (bsg) 0.4";

struct bsg_command;

struct bsg_device {
	struct gendisk *disk;
	request_queue_t *queue;
@@ -46,8 +44,6 @@ struct bsg_device {
	int minor;
	int queued_cmds;
	int done_cmds;
	unsigned long *cmd_bitmap;
	struct bsg_command *cmd_map;
	wait_queue_head_t wq_done;
	wait_queue_head_t wq_free;
	char name[BDEVNAME_SIZE];
@@ -60,14 +56,7 @@ enum {
	BSG_F_WRITE_PERM	= 2,
};

/*
 * command allocation bitmap defines
 */
#define BSG_CMDS_PAGE_ORDER	(1)
#define BSG_CMDS_PER_LONG	(sizeof(unsigned long) * 8)
#define BSG_CMDS_MASK		(BSG_CMDS_PER_LONG - 1)
#define BSG_CMDS_BYTES		(PAGE_SIZE * (1 << BSG_CMDS_PAGE_ORDER))
#define BSG_CMDS		(BSG_CMDS_BYTES / sizeof(struct bsg_command))
#define BSG_DEFAULT_CMDS	64

#undef BSG_DEBUG

@@ -94,6 +83,8 @@ static struct hlist_head bsg_device_list[BSG_LIST_SIZE];
static struct class *bsg_class;
static LIST_HEAD(bsg_class_list);

static struct kmem_cache *bsg_cmd_cachep;

/*
 * our internal command type
 */
@@ -111,14 +102,12 @@ struct bsg_command {
static void bsg_free_command(struct bsg_command *bc)
{
	struct bsg_device *bd = bc->bd;
	unsigned long bitnr = bc - bd->cmd_map;
	unsigned long flags;

	dprintk("%s: command bit offset %lu\n", bd->name, bitnr);
	kmem_cache_free(bsg_cmd_cachep, bc);

	spin_lock_irqsave(&bd->lock, flags);
	bd->queued_cmds--;
	__clear_bit(bitnr, bd->cmd_bitmap);
	spin_unlock_irqrestore(&bd->lock, flags);

	wake_up(&bd->wq_free);
@@ -127,32 +116,29 @@ static void bsg_free_command(struct bsg_command *bc)
static struct bsg_command *__bsg_alloc_command(struct bsg_device *bd)
{
	struct bsg_command *bc = NULL;
	unsigned long *map;
	int free_nr;

	spin_lock_irq(&bd->lock);

	if (bd->queued_cmds >= bd->max_queue)
		goto out;

	for (free_nr = 0, map = bd->cmd_bitmap; *map == ~0UL; map++)
		free_nr += BSG_CMDS_PER_LONG;

	BUG_ON(*map == ~0UL);

	bd->queued_cmds++;
	free_nr += ffz(*map);
	__set_bit(free_nr, bd->cmd_bitmap);
	spin_unlock_irq(&bd->lock);

	bc = bd->cmd_map + free_nr;
	bc = kmem_cache_alloc(bsg_cmd_cachep, GFP_USER);
	if (unlikely(!bc)) {
		spin_lock_irq(&bd->lock);
		goto alloc_fail;
	}

	memset(bc, 0, sizeof(*bc));
	bc->bd = bd;
	INIT_LIST_HEAD(&bc->list);
	dprintk("%s: returning free cmd %p (bit %d)\n", bd->name, bc, free_nr);
	dprintk("%s: returning free cmd %p\n", bd->name, bc);
	return bc;
alloc_fail:
	bd->queued_cmds--;
out:
	dprintk("%s: failed (depth %d)\n", bd->name, bd->queued_cmds);
	spin_unlock_irq(&bd->lock);
	return bc;
}
@@ -356,8 +342,8 @@ static void bsg_rq_end_io(struct request *rq, int uptodate)
	struct bsg_device *bd = bc->bd;
	unsigned long flags;

	dprintk("%s: finished rq %p bc %p, bio %p offset %Zd stat %d\n",
		bd->name, rq, bc, bc->bio, bc - bd->cmd_map, uptodate);
	dprintk("%s: finished rq %p bc %p, bio %p stat %d\n",
		bd->name, rq, bc, bc->bio, uptodate);

	bc->hdr.duration = jiffies_to_msecs(jiffies - bc->hdr.duration);

@@ -703,21 +689,9 @@ bsg_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
	return bytes_read;
}

static void bsg_free_device(struct bsg_device *bd)
{
	if (bd->cmd_map)
		free_pages((unsigned long) bd->cmd_map, BSG_CMDS_PAGE_ORDER);

	kfree(bd->cmd_bitmap);
	kfree(bd);
}

static struct bsg_device *bsg_alloc_device(void)
{
	struct bsg_command *cmd_map;
	unsigned long *cmd_bitmap;
	struct bsg_device *bd;
	int bits;

	bd = kzalloc(sizeof(struct bsg_device), GFP_KERNEL);
	if (unlikely(!bd))
@@ -725,19 +699,7 @@ static struct bsg_device *bsg_alloc_device(void)

	spin_lock_init(&bd->lock);

	bd->max_queue = BSG_CMDS;

	bits = (BSG_CMDS / BSG_CMDS_PER_LONG) + 1;
	cmd_bitmap = kzalloc(bits * sizeof(unsigned long), GFP_KERNEL);
	if (!cmd_bitmap)
		goto out_free_bd;
	bd->cmd_bitmap = cmd_bitmap;

	cmd_map = (void *) __get_free_pages(GFP_KERNEL | __GFP_ZERO,
						BSG_CMDS_PAGE_ORDER);
	if (!cmd_map)
		goto out_free_bitmap;
	bd->cmd_map = cmd_map;
	bd->max_queue = BSG_DEFAULT_CMDS;

	INIT_LIST_HEAD(&bd->busy_list);
	INIT_LIST_HEAD(&bd->done_list);
@@ -746,12 +708,6 @@ static struct bsg_device *bsg_alloc_device(void)
	init_waitqueue_head(&bd->wq_free);
	init_waitqueue_head(&bd->wq_done);
	return bd;

out_free_bitmap:
	kfree(cmd_bitmap);
out_free_bd:
	kfree(bd);
	return NULL;
}

static int bsg_put_device(struct bsg_device *bd)
@@ -779,7 +735,7 @@ static int bsg_put_device(struct bsg_device *bd)

	blk_put_queue(bd->queue);
	hlist_del(&bd->dev_list);
	bsg_free_device(bd);
	kfree(bd);
out:
	mutex_unlock(&bsg_mutex);
	return ret;
@@ -923,10 +879,12 @@ bsg_ioctl(struct inode *inode, struct file *file, unsigned int cmd,

		if (get_user(queue, uarg))
			return -EFAULT;
		if (queue > BSG_CMDS || queue < 1)
		if (queue < 1)
			return -EINVAL;

		spin_lock_irq(&bd->lock);
		bd->max_queue = queue;
		spin_unlock_irq(&bd->lock);
		return 0;
	}

@@ -1035,15 +993,25 @@ static int __init bsg_init(void)
{
	int ret, i;

	bsg_cmd_cachep = kmem_cache_create("bsg_cmd",
				sizeof(struct bsg_command), 0, 0, NULL, NULL);
	if (!bsg_cmd_cachep) {
		printk(KERN_ERR "bsg: failed creating slab cache\n");
		return -ENOMEM;
	}

	for (i = 0; i < BSG_LIST_SIZE; i++)
		INIT_HLIST_HEAD(&bsg_device_list[i]);

	bsg_class = class_create(THIS_MODULE, "bsg");
	if (IS_ERR(bsg_class))
	if (IS_ERR(bsg_class)) {
		kmem_cache_destroy(bsg_cmd_cachep);
		return PTR_ERR(bsg_class);
	}

	ret = register_chrdev(BSG_MAJOR, "bsg", &bsg_fops);
	if (ret) {
		kmem_cache_destroy(bsg_cmd_cachep);
		class_destroy(bsg_class);
		return ret;
	}