diff -r 2994d2997f9d drivers/xen/blktap/blktap.c --- a/drivers/xen/blktap/blktap.c Thu Feb 10 13:59:02 2011 +0000 +++ b/drivers/xen/blktap/blktap.c Tue Feb 22 14:23:22 2011 +0100 @@ -55,8 +55,7 @@ #include #include -#define MAX_TAP_DEV 256 /*the maximum number of tapdisk ring devices */ -#define MAX_DEV_NAME 100 /*the max tapdisk ring device name e.g. blktap0 */ +#define DEF_MAX_TAP_DEV 256 /* default maximum of tapdisk ring devices */ /* * The maximum number of requests that can be outstanding at any time @@ -120,7 +119,8 @@ struct vm_foreign_map foreign_map; /*Mapping page */ } tap_blkif_t; -static struct tap_blkif *tapfds[MAX_TAP_DEV]; +/* Points to the first of "max_tap_dev" objects. */ +static struct tap_blkif **tapfds; static int blktap_next_minor; /* Run-time switchable: /sys/module/blktap/parameters/ */ @@ -129,6 +129,12 @@ module_param(log_stats, int, 0644); module_param(debug_lvl, int, 0644); +/* Settable only at initialization time. */ +static int max_tap_dev = DEF_MAX_TAP_DEV; +module_param(max_tap_dev, int, 0444); +MODULE_PARM_DESC(max_tap_dev, "maximum number of tapdisk devices, defaults to " + __stringify(DEF_MAX_TAP_DEV)); + /* * Each outstanding request that we've passed to the lower device layers has a * 'pending_req' allocated to it. Each buffer_head that completes decrements @@ -470,7 +476,7 @@ * available. This is done while we are still under * the protection of the pending_free_lock. */ - if (blktap_next_minor < MAX_TAP_DEV) + if (blktap_next_minor < max_tap_dev) minor = blktap_next_minor++; found: spin_unlock_irq(&pending_free_lock); @@ -538,7 +544,7 @@ * if the userland tools set things up wrong, this could be negative; * just don't try to signal in this case */ - if (idx < 0 || idx >= MAX_TAP_DEV) + if (idx < 0 || idx >= max_tap_dev) return; info = tapfds[idx]; @@ -567,7 +573,7 @@ /* ctrl device, treat differently */ if (!idx) return 0; - if (idx < 0 || idx >= MAX_TAP_DEV) { + if (idx < 0 || idx >= max_tap_dev) { WPRINTK("No device /dev/xen/blktap%d\n", idx); return -ENODEV; } @@ -836,7 +842,7 @@ unsigned long dev = arg; unsigned long flags; - if (info || dev >= MAX_TAP_DEV) + if (info || dev >= max_tap_dev) return -EINVAL; info = tapfds[dev]; @@ -854,7 +860,7 @@ if (!info) { unsigned long dev = arg; - if (dev >= MAX_TAP_DEV) + if (dev >= max_tap_dev) return -EINVAL; info = tapfds[dev]; @@ -895,7 +901,7 @@ { tap_blkif_t *info; - if (idx < 0 || idx >= MAX_TAP_DEV) + if (idx < 0 || idx >= max_tap_dev) return; info = tapfds[idx]; @@ -1045,7 +1051,7 @@ struct mm_struct *mm; - if ((tapidx < 0) || (tapidx >= MAX_TAP_DEV) + if ((tapidx < 0) || (tapidx >= max_tap_dev) || !(info = tapfds[tapidx])) { WPRINTK("fast_flush: Couldn't get info!\n"); return; @@ -1298,7 +1304,7 @@ rmb(); /* Ensure we see queued requests up to 'rp'. */ /*Check blkif has corresponding UE ring*/ - if (blkif->dev_num < 0 || blkif->dev_num >= MAX_TAP_DEV) { + if (blkif->dev_num < 0 || blkif->dev_num >= max_tap_dev) { /*oops*/ if (print_dbug) { WPRINTK("Corresponding UE " @@ -1413,7 +1419,7 @@ struct mm_struct *mm; struct vm_area_struct *vma = NULL; - if (blkif->dev_num < 0 || blkif->dev_num >= MAX_TAP_DEV) + if (blkif->dev_num < 0 || blkif->dev_num >= max_tap_dev) goto fail_response; info = tapfds[blkif->dev_num]; @@ -1696,6 +1702,21 @@ notify_remote_via_irq(blkif->irq); } +static int alloc_tapfds(void) +{ + int new = clamp_t(int, max_tap_dev, DEF_MAX_TAP_DEV, + NR_EVENT_CHANNELS); + + if (new != max_tap_dev) { + WPRINTK("clamping max_tap_dev from %d to %d\n", max_tap_dev, + new); + max_tap_dev = new; + } + + tapfds = kmalloc(max_tap_dev * sizeof(*tapfds), GFP_KERNEL); + return tapfds ? 0 : -ENOMEM; +} + static int __init blkif_init(void) { int i, ret; @@ -1704,6 +1725,16 @@ if (!is_running_on_xen()) return -ENODEV; + ret = alloc_tapfds(); + if (ret != 0) { + WPRINTK("failed to allocate tapfds\n"); + return ret; + } + /* Not released on error paths below, because the failure of + * register_chrdev() leaks whatever was allocated by the req_increase() + * calls anyway. + */ + INIT_LIST_HEAD(&pending_free); for(i = 0; i < 2; i++) { ret = req_increase();