--- linux-2.2.18pre16/drivers/block/loop.c.orig Mon Oct 16 22:09:17 2000 +++ linux-2.2.18pre16/drivers/block/loop.c Mon Oct 16 22:14:00 2000 @@ -22,6 +22,8 @@ * CBC (and relatives) mode encryption requiring unique IVs per data block. * Reed H. Petty, rhp@draper.net * + * module parameter for max. number of loop devices - Eric Lammerts, Oct 16, 2000 + * * Still To Fix: * - Advisory locking is ignored here. * - Should use an own CAP_* category instead of CAP_SYS_ADMIN @@ -42,6 +44,7 @@ #include #include #include +#include #include #include @@ -61,10 +64,12 @@ #define TIMEOUT_VALUE (6 * HZ) #include -#define MAX_LOOP 8 -static struct loop_device loop_dev[MAX_LOOP]; -static int loop_sizes[MAX_LOOP]; -static int loop_blksizes[MAX_LOOP]; +static int max_loop = 8; +MODULE_PARM(max_loop, "i"); + +static struct loop_device *loop_dev; +static int *loop_sizes; +static int *loop_blksizes; #define FALSE 0 #define TRUE (!FALSE) @@ -169,7 +174,7 @@ INIT_REQUEST; current_request=CURRENT; CURRENT=current_request->next; - if (MINOR(current_request->rq_dev) >= MAX_LOOP) + if (MINOR(current_request->rq_dev) >= max_loop) goto error_out; lo = &loop_dev[MINOR(current_request->rq_dev)]; if (!lo->lo_dentry || !lo->transfer) @@ -577,7 +582,7 @@ return -ENODEV; } dev = MINOR(inode->i_rdev); - if (dev >= MAX_LOOP) + if (dev >= max_loop) return -ENODEV; lo = &loop_dev[dev]; switch (cmd) { @@ -614,7 +619,7 @@ return -ENODEV; } dev = MINOR(inode->i_rdev); - if (dev >= MAX_LOOP) { + if (dev >= max_loop) { return -ENODEV; } lo = &loop_dev[dev]; @@ -639,7 +644,7 @@ return 0; } dev = MINOR(inode->i_rdev); - if (dev >= MAX_LOOP) + if (dev >= max_loop) return 0; err = fsync_dev(inode->i_rdev); lo = &loop_dev[dev]; @@ -689,7 +694,7 @@ if ((unsigned)number >= MAX_LO_CRYPT) return -EINVAL; - for (lo = &loop_dev[0]; lo < &loop_dev[MAX_LOOP]; lo++) { + for (lo = &loop_dev[0]; lo < &loop_dev[max_loop]; lo++) { int type = lo->lo_encrypt_type; if (type == number) { xfer_funcs[type]->release(lo); @@ -706,34 +711,65 @@ int __init loop_init(void) { - int i; + int i, retval; + + if(max_loop < 1 || max_loop > 256) { + printk(KERN_ERR "loop: 1 <= max_loop <= 256\n"); + return -EINVAL; + } + + retval = -ENOMEM; + loop_dev = kmalloc(sizeof(*loop_dev) * max_loop, GFP_KERNEL); + if(loop_dev == NULL) goto out_nomem; + + loop_sizes = kmalloc(sizeof(*loop_sizes) * max_loop, GFP_KERNEL); + if(loop_sizes == NULL) goto out_nomem_freedev; + + loop_blksizes = kmalloc(sizeof(*loop_blksizes) * max_loop, GFP_KERNEL); + if(loop_blksizes == NULL) goto out_nomem_freesizes; if (register_blkdev(MAJOR_NR, "loop", &lo_fops)) { printk(KERN_WARNING "Unable to get major number %d for loop device\n", MAJOR_NR); - return -EIO; + retval = -EIO; + goto out_nomem_freeblksizes; } #ifndef MODULE printk(KERN_INFO "loop: registered device at major %d\n", MAJOR_NR); #endif blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; - for (i=0; i < MAX_LOOP; i++) { + for (i=0; i < max_loop; i++) { memset(&loop_dev[i], 0, sizeof(struct loop_device)); loop_dev[i].lo_number = i; } - memset(&loop_sizes, 0, sizeof(loop_sizes)); - memset(&loop_blksizes, 0, sizeof(loop_blksizes)); + memset(loop_sizes, 0, sizeof(*loop_sizes) * max_loop); + memset(loop_blksizes, 0, sizeof(*loop_blksizes) * max_loop); blk_size[MAJOR_NR] = loop_sizes; blksize_size[MAJOR_NR] = loop_blksizes; return 0; + +out_nomem_freeblksizes: + kfree(loop_blksizes); +out_nomem_freesizes: + kfree(loop_sizes); +out_nomem_freedev: + kfree(loop_dev); +out_nomem: + return retval; } #ifdef MODULE void cleanup_module(void) { - if (unregister_blkdev(MAJOR_NR, "loop") != 0) + if (unregister_blkdev(MAJOR_NR, "loop") != 0) { printk(KERN_WARNING "loop: cannot unregister blkdev\n"); + return; + } + + kfree(loop_dev); + kfree(loop_sizes); + kfree(loop_blksizes); } #endif