int __init blktap_ring_init(void) { dev_t dev = 0; int err; cdev_init(&blktap_ring_cdev, &blktap_ring_file_operations); blktap_ring_cdev.owner = THIS_MODULE; err = alloc_chrdev_region(&dev, 0, MAX_BLKTAP_DEVICE, "blktap2"); if (err < 0) { BTERR("error registering ring devices: %d\n", err); return err; } err = cdev_add(&blktap_ring_cdev, dev, MAX_BLKTAP_DEVICE); if (err) { BTERR("error adding ring device: %d\n", err); unregister_chrdev_region(dev, MAX_BLKTAP_DEVICE); return err; } blktap_ring_major = MAJOR(dev); BTINFO("blktap ring major: %d\n", blktap_ring_major); return 0; }
static void blktap_control_free(void) { int i; for (i = 0; i < MAX_BLKTAP_DEVICE; i++) blktap_control_destroy_device(blktaps[i]); if (blktap_control_registered) if (misc_deregister(&blktap_misc) < 0) BTERR("misc_deregister failed for control device"); }
static int __init blktap_control_init(void) { int err; err = misc_register(&blktap_misc); if (err) { BTERR("misc_register failed for control device"); return err; } blktap_control_registered = 1; return 0; }
static struct blktap * blktap_control_allocate_tap(void) { int err, minor; struct blktap *tap; /* * This is called only from the ioctl, which * means we should always have interrupts enabled. */ BUG_ON(irqs_disabled()); spin_lock_irq(&blktap_control_lock); for (minor = 0; minor < MAX_BLKTAP_DEVICE; minor++) { tap = blktaps[minor]; if (!tap) goto found; if (!tap->dev_inuse) { blktap_control_initialize_tap(tap); goto found; } } tap = NULL; found: spin_unlock_irq(&blktap_control_lock); if (!tap) { tap = blktap_control_create_tap(); if (!tap) return NULL; } err = blktap_ring_create(tap); if (err) { BTERR("ring creation failed: %d\n", err); clear_bit(BLKTAP_CONTROL, &tap->dev_inuse); return NULL; } BTINFO("allocated tap %p\n", tap); return tap; }
static int blktap_control_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { unsigned long dev; struct blktap *tap; switch (cmd) { case BLKTAP2_IOCTL_ALLOC_TAP: { struct blktap_handle h; tap = blktap_control_allocate_tap(); if (!tap) { BTERR("error allocating device\n"); return -ENOMEM; } h.ring = ring_major; h.device = device_major; h.minor = tap->minor; if (copy_to_user((struct blktap_handle __user *)arg, &h, sizeof(h))) { blktap_control_destroy_device(tap); return -EFAULT; } return 0; } case BLKTAP2_IOCTL_FREE_TAP: dev = arg; if (dev >= MAX_BLKTAP_DEVICE || !blktaps[dev]) return -EINVAL; blktap_control_destroy_device(blktaps[dev]); return 0; } return -ENOIOCTLCMD; }