diff -urN linux-2.5.72/drivers/block/nbd.c linux-2.5.72-patched/drivers/block/nbd.c --- linux-2.5.72/drivers/block/nbd.c 2003-06-16 22:19:44.000000000 -0600 +++ linux-2.5.72-patched/drivers/block/nbd.c 2003-06-21 15:30:17.860967573 -0600 @@ -28,6 +28,7 @@ * the transmit lock. * 02-10-11 Allow hung xmit to be aborted via SIGKILL & various fixes. * + * 03-06-21 Fix memory corruption from module removal. * * possible FIXME: make set_sock / set_blksize / set_size / do_it one syscall * why not: would need verify_area and friends, would share yet another @@ -63,7 +64,18 @@ static struct nbd_device nbd_dev[MAX_NBD]; -static spinlock_t nbd_lock = SPIN_LOCK_UNLOCKED; +/* + * Have these per nbd_device as is now required by the new block layer. + * This also helps prevent I/O bottle necks between multiple nbd_devices + * resulting in better overall response times! + * + * ldl: Keep these out from nbd_device for now till the whole 2.5 blockdev + * reworking shakes out. Who knows... maybe struct request_queue's + * queue_lock field will someday actually be the spinlock instead of just + * being a pointer to it! + */ +static struct request_queue nbd_queue[MAX_NBD]; +static spinlock_t nbd_lock[MAX_NBD]; #define DEBUG( s ) /* #define DEBUG( s ) printk( s ) @@ -538,8 +550,6 @@ * (Just smiley confuses emacs :-) */ -static struct request_queue nbd_queue; - static int __init nbd_init(void) { int err = -ENOMEM; @@ -551,6 +561,11 @@ } for (i = 0; i < MAX_NBD; i++) { + nbd_lock[i] = SPIN_LOCK_UNLOCKED; + blk_init_queue(&nbd_queue[i], do_nbd_request, &nbd_lock[i]); + } + + for (i = 0; i < MAX_NBD; i++) { struct gendisk *disk = alloc_disk(1); if (!disk) goto out; @@ -564,7 +579,6 @@ #ifdef MODULE printk("nbd: registered device at major %d\n", NBD_MAJOR); #endif - blk_init_queue(&nbd_queue, do_nbd_request, &nbd_lock); devfs_mk_dir("nbd"); for (i = 0; i < MAX_NBD; i++) { struct gendisk *disk = nbd_dev[i].disk; @@ -582,7 +596,7 @@ disk->first_minor = i; disk->fops = &nbd_fops; disk->private_data = &nbd_dev[i]; - disk->queue = &nbd_queue; + disk->queue = &nbd_queue[i]; sprintf(disk->disk_name, "nbd%d", i); sprintf(disk->devfs_name, "nbd/%d", i); set_capacity(disk, 0x3ffffe); @@ -602,9 +616,9 @@ for (i = 0; i < MAX_NBD; i++) { del_gendisk(nbd_dev[i].disk); put_disk(nbd_dev[i].disk); + blk_cleanup_queue(&nbd_queue[i]); } devfs_remove("nbd"); - blk_cleanup_queue(&nbd_queue); unregister_blkdev(NBD_MAJOR, "nbd"); }