1 #include <linux/module.h>
2 #include <linux/sched.h>
3 #include <linux/miscdevice.h>
4 #include <linux/device.h>
5 #include <asm/uaccess.h>
9 DEFINE_MUTEX(blktap_lock);
11 struct blktap **blktaps;
13 static struct blktap_page_pool *default_pool;
15 static struct blktap *
16 blktap_control_get_minor(void)
21 tap = kzalloc(sizeof(*tap), GFP_KERNEL);
25 mutex_lock(&blktap_lock);
27 for (minor = 0; minor < blktap_max_minor; minor++)
31 if (minor == CONFIG_XEN_NR_TAP2_DEVICES)
34 if (minor == blktap_max_minor) {
38 n = min(2 * blktap_max_minor, CONFIG_XEN_NR_TAP2_DEVICES);
39 p = krealloc(blktaps, n * sizeof(blktaps[0]), GFP_KERNEL);
44 minor = blktap_max_minor;
47 memset(&blktaps[minor], 0, (n - minor) * sizeof(blktaps[0]));
53 __module_get(THIS_MODULE);
55 mutex_unlock(&blktap_lock);
59 mutex_unlock(&blktap_lock);
66 blktap_control_put_minor(struct blktap* tap)
68 blktaps[tap->minor] = NULL;
71 module_put(THIS_MODULE);
75 blktap_control_create_tap(void)
80 tap = blktap_control_get_minor();
84 kobject_get(&default_pool->kobj);
85 tap->pool = default_pool;
87 err = blktap_ring_create(tap);
91 err = blktap_sysfs_create(tap);
98 blktap_ring_destroy(tap);
100 blktap_control_put_minor(tap);
106 blktap_control_destroy_tap(struct blktap *tap)
110 err = blktap_ring_destroy(tap);
114 kobject_put(&tap->pool->kobj);
116 blktap_sysfs_destroy(tap);
118 blktap_control_put_minor(tap);
124 blktap_control_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
129 case BLKTAP2_IOCTL_ALLOC_TAP: {
130 struct blktap_handle h;
131 void __user *ptr = (void __user*)arg;
133 tap = blktap_control_create_tap();
137 h.ring = blktap_ring_major;
138 h.device = blktap_device_major;
139 h.minor = tap->minor;
141 if (copy_to_user(ptr, &h, sizeof(h))) {
142 blktap_control_destroy_tap(tap);
149 case BLKTAP2_IOCTL_FREE_TAP: {
152 if (minor > CONFIG_XEN_NR_TAP2_DEVICES)
155 tap = blktaps[minor];
159 return blktap_control_destroy_tap(tap);
166 static const struct file_operations blktap_control_file_operations = {
167 .owner = THIS_MODULE,
168 .unlocked_ioctl = blktap_control_ioctl,
171 static struct miscdevice blktap_control = {
172 .minor = MISC_DYNAMIC_MINOR,
173 .name = "blktap-control",
174 .nodename = BLKTAP2_DEV_DIR "control",
175 .fops = &blktap_control_file_operations,
178 static struct device *control_device;
181 blktap_control_show_default_pool(struct device *device,
182 struct device_attribute *attr,
185 return sprintf(buf, "%s", kobject_name(&default_pool->kobj));
189 blktap_control_store_default_pool(struct device *device,
190 struct device_attribute *attr,
191 const char *buf, size_t size)
193 struct blktap_page_pool *pool, *tmp = default_pool;
195 pool = blktap_page_pool_get(buf);
197 return PTR_ERR(pool);
200 kobject_put(&tmp->kobj);
205 static DEVICE_ATTR(default_pool, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH,
206 blktap_control_show_default_pool,
207 blktap_control_store_default_pool);
210 blktap_control_debug(struct blktap *tap, char *buf, size_t size)
212 char *s = buf, *end = buf + size;
214 s += snprintf(s, end - s,
215 "tap %u:%u name:'%s' flags:%#08lx\n",
216 MAJOR(tap->ring.devno), MINOR(tap->ring.devno),
217 tap->name, tap->dev_inuse);
223 blktap_control_init(void)
227 err = misc_register(&blktap_control);
231 control_device = blktap_control.this_device;
233 blktap_max_minor = min(64, CONFIG_XEN_NR_TAP2_DEVICES);
234 blktaps = kzalloc(blktap_max_minor * sizeof(blktaps[0]), GFP_KERNEL);
236 BTERR("failed to allocate blktap minor map");
240 err = blktap_page_pool_init(&control_device->kobj);
244 default_pool = blktap_page_pool_get("default");
248 err = device_create_file(control_device, &dev_attr_default_pool);
256 blktap_control_exit(void)
259 kobject_put(&default_pool->kobj);
263 blktap_page_pool_exit();
270 if (control_device) {
271 misc_deregister(&blktap_control);
272 control_device = NULL;
279 blktap_control_exit();
282 blktap_device_exit();
290 err = blktap_device_init();
294 err = blktap_ring_init();
298 err = blktap_sysfs_init();
302 err = blktap_control_init();
313 module_init(blktap_init);
314 module_exit(blktap_exit);
315 MODULE_LICENSE("Dual BSD/GPL");
316 MODULE_ALIAS("devname:" BLKTAP2_DEV_DIR "control");