X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=drivers%2Fblock%2Floop.c;h=5526eadb65926d4318b790a0ede84d9f272a7059;hb=8ff6f48d99a0351bcc9ceab422042ef9d3bad9aa;hp=0d4ccd4a09574fdfa3b72533b2fc333bfb191462;hpb=5cefcab3db2b13093480f2a42bf081574dd72d3d;p=powerpc.git diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 0d4ccd4a09..5526eadb65 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -77,9 +77,8 @@ #include -static int max_loop = 8; -static struct loop_device *loop_dev; -static struct gendisk **disks; +static LIST_HEAD(loop_devices); +static DEFINE_MUTEX(loop_devices_mutex); /* * Transfer functions @@ -183,7 +182,7 @@ figure_loop_size(struct loop_device *lo) if (unlikely((loff_t)x != size)) return -EFBIG; - set_capacity(disks[lo->lo_number], x); + set_capacity(lo->lo_disk, x); return 0; } @@ -244,17 +243,13 @@ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec, transfer_result = lo_do_transfer(lo, WRITE, page, offset, bvec->bv_page, bv_offs, size, IV); if (unlikely(transfer_result)) { - char *kaddr; - /* * The transfer failed, but we still write the data to * keep prepare/commit calls balanced. */ printk(KERN_ERR "loop: transfer error block %llu\n", (unsigned long long)index); - kaddr = kmap_atomic(page, KM_USER0); - memset(kaddr + offset, 0, size); - kunmap_atomic(kaddr, KM_USER0); + zero_user_page(page, offset, size, KM_USER0); } flush_dcache_page(page); ret = aops->commit_write(file, page, offset, @@ -812,7 +807,7 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file, lo->lo_queue->queuedata = lo; lo->lo_queue->unplug_fn = loop_unplug; - set_capacity(disks[lo->lo_number], size); + set_capacity(lo->lo_disk, size); bd_set_size(bdev, size << 9); set_blocksize(bdev, lo_blocksize); @@ -832,7 +827,7 @@ out_clr: lo->lo_device = NULL; lo->lo_backing_file = NULL; lo->lo_flags = 0; - set_capacity(disks[lo->lo_number], 0); + set_capacity(lo->lo_disk, 0); invalidate_bdev(bdev); bd_set_size(bdev, 0); mapping_set_gfp_mask(mapping, lo->old_gfp_mask); @@ -918,7 +913,7 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev) memset(lo->lo_crypt_name, 0, LO_NAME_SIZE); memset(lo->lo_file_name, 0, LO_NAME_SIZE); invalidate_bdev(bdev); - set_capacity(disks[lo->lo_number], 0); + set_capacity(lo->lo_disk, 0); bd_set_size(bdev, 0); mapping_set_gfp_mask(filp->f_mapping, gfp); lo->lo_state = Lo_unbound; @@ -1357,8 +1352,9 @@ static struct block_device_operations lo_fops = { /* * And now the modules code and kernel interface. */ +static int max_loop; module_param(max_loop, int, 0); -MODULE_PARM_DESC(max_loop, "Maximum number of loop devices (1-256)"); +MODULE_PARM_DESC(max_loop, "obsolete, loop device is created on-demand"); MODULE_LICENSE("GPL"); MODULE_ALIAS_BLOCKDEV_MAJOR(LOOP_MAJOR); @@ -1383,7 +1379,7 @@ int loop_unregister_transfer(int number) xfer_funcs[n] = NULL; - for (lo = &loop_dev[0]; lo < &loop_dev[max_loop]; lo++) { + list_for_each_entry(lo, &loop_devices, lo_list) { mutex_lock(&lo->lo_ctl_mutex); if (lo->lo_encryption == xfer) @@ -1398,91 +1394,100 @@ int loop_unregister_transfer(int number) EXPORT_SYMBOL(loop_register_transfer); EXPORT_SYMBOL(loop_unregister_transfer); -static int __init loop_init(void) +static struct loop_device *loop_init_one(int i) { - int i; + struct loop_device *lo; + struct gendisk *disk; - if (max_loop < 1 || max_loop > 256) { - printk(KERN_WARNING "loop: invalid max_loop (must be between" - " 1 and 256), using default (8)\n"); - max_loop = 8; + list_for_each_entry(lo, &loop_devices, lo_list) { + if (lo->lo_number == i) + return lo; } - if (register_blkdev(LOOP_MAJOR, "loop")) - return -EIO; - - loop_dev = kmalloc(max_loop * sizeof(struct loop_device), GFP_KERNEL); - if (!loop_dev) - goto out_mem1; - memset(loop_dev, 0, max_loop * sizeof(struct loop_device)); + lo = kzalloc(sizeof(*lo), GFP_KERNEL); + if (!lo) + goto out; - disks = kmalloc(max_loop * sizeof(struct gendisk *), GFP_KERNEL); - if (!disks) - goto out_mem2; + lo->lo_queue = blk_alloc_queue(GFP_KERNEL); + if (!lo->lo_queue) + goto out_free_dev; + + disk = lo->lo_disk = alloc_disk(1); + if (!disk) + goto out_free_queue; + + mutex_init(&lo->lo_ctl_mutex); + lo->lo_number = i; + lo->lo_thread = NULL; + init_waitqueue_head(&lo->lo_event); + spin_lock_init(&lo->lo_lock); + disk->major = LOOP_MAJOR; + disk->first_minor = i; + disk->fops = &lo_fops; + disk->private_data = lo; + disk->queue = lo->lo_queue; + sprintf(disk->disk_name, "loop%d", i); + add_disk(disk); + list_add_tail(&lo->lo_list, &loop_devices); + return lo; + +out_free_queue: + blk_cleanup_queue(lo->lo_queue); +out_free_dev: + kfree(lo); +out: + return NULL; +} - for (i = 0; i < max_loop; i++) { - disks[i] = alloc_disk(1); - if (!disks[i]) - goto out_mem3; - } +static void loop_del_one(struct loop_device *lo) +{ + del_gendisk(lo->lo_disk); + blk_cleanup_queue(lo->lo_queue); + put_disk(lo->lo_disk); + list_del(&lo->lo_list); + kfree(lo); +} - for (i = 0; i < max_loop; i++) { - struct loop_device *lo = &loop_dev[i]; - struct gendisk *disk = disks[i]; - - memset(lo, 0, sizeof(*lo)); - lo->lo_queue = blk_alloc_queue(GFP_KERNEL); - if (!lo->lo_queue) - goto out_mem4; - mutex_init(&lo->lo_ctl_mutex); - lo->lo_number = i; - lo->lo_thread = NULL; - init_waitqueue_head(&lo->lo_event); - spin_lock_init(&lo->lo_lock); - disk->major = LOOP_MAJOR; - disk->first_minor = i; - disk->fops = &lo_fops; - sprintf(disk->disk_name, "loop%d", i); - disk->private_data = lo; - disk->queue = lo->lo_queue; - } +static struct kobject *loop_probe(dev_t dev, int *part, void *data) +{ + struct loop_device *lo; + struct kobject *kobj; - /* We cannot fail after we call this, so another loop!*/ - for (i = 0; i < max_loop; i++) - add_disk(disks[i]); - printk(KERN_INFO "loop: loaded (max %d devices)\n", max_loop); - return 0; + mutex_lock(&loop_devices_mutex); + lo = loop_init_one(dev & MINORMASK); + kobj = lo ? get_disk(lo->lo_disk) : ERR_PTR(-ENOMEM); + mutex_unlock(&loop_devices_mutex); -out_mem4: - while (i--) - blk_cleanup_queue(loop_dev[i].lo_queue); - i = max_loop; -out_mem3: - while (i--) - put_disk(disks[i]); - kfree(disks); -out_mem2: - kfree(loop_dev); -out_mem1: - unregister_blkdev(LOOP_MAJOR, "loop"); - printk(KERN_ERR "loop: ran out of memory\n"); - return -ENOMEM; + *part = 0; + return kobj; } -static void loop_exit(void) +static int __init loop_init(void) { - int i; + if (register_blkdev(LOOP_MAJOR, "loop")) + return -EIO; + blk_register_region(MKDEV(LOOP_MAJOR, 0), 1UL << MINORBITS, + THIS_MODULE, loop_probe, NULL, NULL); + + if (max_loop) { + printk(KERN_INFO "loop: the max_loop option is obsolete " + "and will be removed in March 2008\n"); - for (i = 0; i < max_loop; i++) { - del_gendisk(disks[i]); - blk_cleanup_queue(loop_dev[i].lo_queue); - put_disk(disks[i]); } + printk(KERN_INFO "loop: module loaded\n"); + return 0; +} + +static void __exit loop_exit(void) +{ + struct loop_device *lo, *next; + + list_for_each_entry_safe(lo, next, &loop_devices, lo_list) + loop_del_one(lo); + + blk_unregister_region(MKDEV(LOOP_MAJOR, 0), 1UL << MINORBITS); if (unregister_blkdev(LOOP_MAJOR, "loop")) printk(KERN_WARNING "loop: cannot unregister blkdev\n"); - - kfree(disks); - kfree(loop_dev); } module_init(loop_init);