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

Commit a893cd76 authored by Omar Sandoval's avatar Omar Sandoval Committed by Jens Axboe
Browse files

hd: stop sharing request queue across multiple gendisks



Compile-tested only.

Signed-off-by: default avatarOmar Sandoval <osandov@fb.com>
Signed-off-by: default avatarJens Axboe <axboe@fb.com>
parent 53696b8d
Loading
Loading
Loading
Loading
+39 −23
Original line number Diff line number Diff line
@@ -95,7 +95,7 @@
#define ICRC_ERR		0x80	/* new meaning:  CRC error during transfer */

static DEFINE_SPINLOCK(hd_lock);
static struct request_queue *hd_queue;
static unsigned int hd_queue;
static struct request *hd_req;

#define TIMEOUT_VALUE	(6*HZ)
@@ -537,7 +537,7 @@ static void hd_times_out(unsigned long dummy)
	if (!hd_req)
		return;

	spin_lock_irq(hd_queue->queue_lock);
	spin_lock_irq(&hd_lock);
	reset = 1;
	name = hd_req->rq_disk->disk_name;
	printk("%s: timeout\n", name);
@@ -548,7 +548,7 @@ static void hd_times_out(unsigned long dummy)
		hd_end_request_cur(-EIO);
	}
	hd_request();
	spin_unlock_irq(hd_queue->queue_lock);
	spin_unlock_irq(&hd_lock);
}

static int do_special_op(struct hd_i_struct *disk, struct request *req)
@@ -566,6 +566,25 @@ static int do_special_op(struct hd_i_struct *disk, struct request *req)
	return 1;
}

static int set_next_request(void)
{
	struct request_queue *q;
	int old_pos = hd_queue;

	do {
		q = hd_gendisk[hd_queue]->queue;
		if (++hd_queue == NR_HD)
			hd_queue = 0;
		if (q) {
			hd_req = blk_fetch_request(q);
			if (hd_req)
				break;
		}
	} while (hd_queue != old_pos);

	return hd_req != NULL;
}

/*
 * The driver enables interrupts as much as possible.  In order to do this,
 * (a) the device-interrupt is disabled before entering hd_request(),
@@ -587,13 +606,10 @@ static void hd_request(void)
repeat:
	del_timer(&device_timer);

	if (!hd_req) {
		hd_req = blk_fetch_request(hd_queue);
		if (!hd_req) {
	if (!hd_req && !set_next_request()) {
		do_hd = NULL;
		return;
	}
	}
	req = hd_req;

	if (reset) {
@@ -676,7 +692,7 @@ static irqreturn_t hd_interrupt(int irq, void *dev_id)
{
	void (*handler)(void) = do_hd;

	spin_lock(hd_queue->queue_lock);
	spin_lock(&hd_lock);

	do_hd = NULL;
	del_timer(&device_timer);
@@ -684,7 +700,7 @@ static irqreturn_t hd_interrupt(int irq, void *dev_id)
		handler = unexpected_hd_interrupt;
	handler();

	spin_unlock(hd_queue->queue_lock);
	spin_unlock(&hd_lock);

	return IRQ_HANDLED;
}
@@ -700,16 +716,8 @@ static int __init hd_init(void)
	if (register_blkdev(HD_MAJOR, "hd"))
		return -1;

	hd_queue = blk_init_queue(do_hd_request, &hd_lock);
	if (!hd_queue) {
		unregister_blkdev(HD_MAJOR, "hd");
		return -ENOMEM;
	}

	blk_queue_max_hw_sectors(hd_queue, 255);
	init_timer(&device_timer);
	device_timer.function = hd_times_out;
	blk_queue_logical_block_size(hd_queue, 512);

	if (!NR_HD) {
		/*
@@ -742,7 +750,11 @@ static int __init hd_init(void)
		sprintf(disk->disk_name, "hd%c", 'a'+drive);
		disk->private_data = p;
		set_capacity(disk, p->head * p->sect * p->cyl);
		disk->queue = hd_queue;
		disk->queue = blk_init_queue(do_hd_request, &hd_lock);
		if (!disk->queue)
			goto Enomem;
		blk_queue_max_hw_sectors(disk->queue, 255);
		blk_queue_logical_block_size(disk->queue, 512);
		p->unit = drive;
		hd_gendisk[drive] = disk;
		printk("%s: %luMB, CHS=%d/%d/%d\n",
@@ -781,11 +793,15 @@ static int __init hd_init(void)
out:
	del_timer(&device_timer);
	unregister_blkdev(HD_MAJOR, "hd");
	blk_cleanup_queue(hd_queue);
	return -1;
Enomem:
	while (drive--)
	for (drive = 0; drive < NR_HD; drive++) {
		if (hd_gendisk[drive]) {
			if (hd_gendisk[drive]->queue)
				blk_cleanup_queue(hd_gendisk[drive]->queue);
			put_disk(hd_gendisk[drive]);
		}
	}
	goto out;
}