mirror of https://gitee.com/openkylin/linux.git
tap: Tap character device creation/destroy API
This patch provides tap device create/destroy APIs in tap.c. Signed-off-by: Sainath Grandhi <sainath.grandhi@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
635b8c8ecd
commit
ebc05ba7e8
|
@ -28,7 +28,6 @@
|
|||
* Variables for dealing with macvtaps device numbers.
|
||||
*/
|
||||
static dev_t macvtap_major;
|
||||
#define MACVTAP_NUM_DEVS (1U << MINORBITS)
|
||||
|
||||
static const void *macvtap_net_namespace(struct device *d)
|
||||
{
|
||||
|
@ -159,57 +158,46 @@ static struct notifier_block macvtap_notifier_block __read_mostly = {
|
|||
.notifier_call = macvtap_device_event,
|
||||
};
|
||||
|
||||
extern struct file_operations tap_fops;
|
||||
static int macvtap_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = alloc_chrdev_region(&macvtap_major, 0,
|
||||
MACVTAP_NUM_DEVS, "macvtap");
|
||||
err = tap_create_cdev(&macvtap_cdev, &macvtap_major, "macvtap");
|
||||
|
||||
if (err)
|
||||
goto out1;
|
||||
|
||||
cdev_init(&macvtap_cdev, &tap_fops);
|
||||
err = cdev_add(&macvtap_cdev, macvtap_major, MACVTAP_NUM_DEVS);
|
||||
err = class_register(&macvtap_class);
|
||||
if (err)
|
||||
goto out2;
|
||||
|
||||
err = class_register(&macvtap_class);
|
||||
err = register_netdevice_notifier(&macvtap_notifier_block);
|
||||
if (err)
|
||||
goto out3;
|
||||
|
||||
err = register_netdevice_notifier(&macvtap_notifier_block);
|
||||
err = macvlan_link_register(&macvtap_link_ops);
|
||||
if (err)
|
||||
goto out4;
|
||||
|
||||
err = macvlan_link_register(&macvtap_link_ops);
|
||||
if (err)
|
||||
goto out5;
|
||||
|
||||
return 0;
|
||||
|
||||
out5:
|
||||
unregister_netdevice_notifier(&macvtap_notifier_block);
|
||||
out4:
|
||||
class_unregister(&macvtap_class);
|
||||
unregister_netdevice_notifier(&macvtap_notifier_block);
|
||||
out3:
|
||||
cdev_del(&macvtap_cdev);
|
||||
class_unregister(&macvtap_class);
|
||||
out2:
|
||||
unregister_chrdev_region(macvtap_major, MACVTAP_NUM_DEVS);
|
||||
tap_destroy_cdev(macvtap_major, &macvtap_cdev);
|
||||
out1:
|
||||
return err;
|
||||
}
|
||||
module_init(macvtap_init);
|
||||
|
||||
extern struct idr minor_idr;
|
||||
static void macvtap_exit(void)
|
||||
{
|
||||
rtnl_link_unregister(&macvtap_link_ops);
|
||||
unregister_netdevice_notifier(&macvtap_notifier_block);
|
||||
class_unregister(&macvtap_class);
|
||||
cdev_del(&macvtap_cdev);
|
||||
unregister_chrdev_region(macvtap_major, MACVTAP_NUM_DEVS);
|
||||
idr_destroy(&minor_idr);
|
||||
tap_destroy_cdev(macvtap_major, &macvtap_cdev);
|
||||
}
|
||||
module_exit(macvtap_exit);
|
||||
|
||||
|
|
|
@ -123,8 +123,12 @@ static struct proto tap_proto = {
|
|||
};
|
||||
|
||||
#define TAP_NUM_DEVS (1U << MINORBITS)
|
||||
static DEFINE_MUTEX(minor_lock);
|
||||
DEFINE_IDR(minor_idr);
|
||||
struct major_info {
|
||||
dev_t major;
|
||||
struct idr minor_idr;
|
||||
struct mutex minor_lock;
|
||||
const char *device_name;
|
||||
} macvtap_major;
|
||||
|
||||
#define GOODCOPY_LEN 128
|
||||
|
||||
|
@ -413,26 +417,26 @@ int tap_get_minor(struct macvlan_dev *vlan)
|
|||
{
|
||||
int retval = -ENOMEM;
|
||||
|
||||
mutex_lock(&minor_lock);
|
||||
retval = idr_alloc(&minor_idr, vlan, 1, TAP_NUM_DEVS, GFP_KERNEL);
|
||||
mutex_lock(&macvtap_major.minor_lock);
|
||||
retval = idr_alloc(&macvtap_major.minor_idr, vlan, 1, TAP_NUM_DEVS, GFP_KERNEL);
|
||||
if (retval >= 0) {
|
||||
vlan->minor = retval;
|
||||
} else if (retval == -ENOSPC) {
|
||||
netdev_err(vlan->dev, "Too many tap devices\n");
|
||||
retval = -EINVAL;
|
||||
}
|
||||
mutex_unlock(&minor_lock);
|
||||
mutex_unlock(&macvtap_major.minor_lock);
|
||||
return retval < 0 ? retval : 0;
|
||||
}
|
||||
|
||||
void tap_free_minor(struct macvlan_dev *vlan)
|
||||
{
|
||||
mutex_lock(&minor_lock);
|
||||
mutex_lock(&macvtap_major.minor_lock);
|
||||
if (vlan->minor) {
|
||||
idr_remove(&minor_idr, vlan->minor);
|
||||
idr_remove(&macvtap_major.minor_idr, vlan->minor);
|
||||
vlan->minor = 0;
|
||||
}
|
||||
mutex_unlock(&minor_lock);
|
||||
mutex_unlock(&macvtap_major.minor_lock);
|
||||
}
|
||||
|
||||
static struct net_device *dev_get_by_tap_minor(int minor)
|
||||
|
@ -440,13 +444,13 @@ static struct net_device *dev_get_by_tap_minor(int minor)
|
|||
struct net_device *dev = NULL;
|
||||
struct macvlan_dev *vlan;
|
||||
|
||||
mutex_lock(&minor_lock);
|
||||
vlan = idr_find(&minor_idr, minor);
|
||||
mutex_lock(&macvtap_major.minor_lock);
|
||||
vlan = idr_find(&macvtap_major.minor_idr, minor);
|
||||
if (vlan) {
|
||||
dev = vlan->dev;
|
||||
dev_hold(dev);
|
||||
}
|
||||
mutex_unlock(&minor_lock);
|
||||
mutex_unlock(&macvtap_major.minor_lock);
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
@ -1184,3 +1188,39 @@ int tap_queue_resize(struct macvlan_dev *vlan)
|
|||
kfree(arrays);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tap_create_cdev(struct cdev *tap_cdev,
|
||||
dev_t *tap_major, const char *device_name)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = alloc_chrdev_region(tap_major, 0, TAP_NUM_DEVS, device_name);
|
||||
if (err)
|
||||
goto out1;
|
||||
|
||||
cdev_init(tap_cdev, &tap_fops);
|
||||
err = cdev_add(tap_cdev, *tap_major, TAP_NUM_DEVS);
|
||||
if (err)
|
||||
goto out2;
|
||||
|
||||
macvtap_major.major = MAJOR(*tap_major);
|
||||
|
||||
idr_init(&macvtap_major.minor_idr);
|
||||
mutex_init(&macvtap_major.minor_lock);
|
||||
|
||||
macvtap_major.device_name = device_name;
|
||||
|
||||
return 0;
|
||||
|
||||
out2:
|
||||
unregister_chrdev_region(*tap_major, TAP_NUM_DEVS);
|
||||
out1:
|
||||
return err;
|
||||
}
|
||||
|
||||
void tap_destroy_cdev(dev_t major, struct cdev *tap_cdev)
|
||||
{
|
||||
cdev_del(tap_cdev);
|
||||
unregister_chrdev_region(major, TAP_NUM_DEVS);
|
||||
idr_destroy(&macvtap_major.minor_idr);
|
||||
}
|
||||
|
|
|
@ -19,5 +19,8 @@ void tap_del_queues(struct net_device *dev);
|
|||
int tap_get_minor(struct macvlan_dev *vlan);
|
||||
void tap_free_minor(struct macvlan_dev *vlan);
|
||||
int tap_queue_resize(struct macvlan_dev *vlan);
|
||||
int tap_create_cdev(struct cdev *tap_cdev,
|
||||
dev_t *tap_major, const char *device_name);
|
||||
void tap_destroy_cdev(dev_t major, struct cdev *tap_cdev);
|
||||
|
||||
#endif /*_LINUX_IF_TAP_H_*/
|
||||
|
|
Loading…
Reference in New Issue