aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/tap.c
diff options
context:
space:
mode:
authorWANG Cong <xiyou.wangcong@gmail.com>2017-07-10 13:05:50 -0400
committerDavid S. Miller <davem@davemloft.net>2017-07-11 16:41:57 -0400
commitffa423fb3251f8737303ffc3b0659e86e501808e (patch)
tree0d93e56751fc63134f41f2bbb5e38963c6281aa4 /drivers/net/tap.c
parent6a146f3a5894b751cef16feb3d7903e45e3c445c (diff)
tap: convert a mutex to a spinlock
We are not allowed to block on the RCU reader side, so can't just hold the mutex as before. As a quick fix, convert it to a spinlock. Fixes: d9f1f61c0801 ("tap: Extending tap device create/destroy APIs") Reported-by: Christian Borntraeger <borntraeger@de.ibm.com> Tested-by: Christian Borntraeger <borntraeger@de.ibm.com> Cc: Sainath Grandhi <sainath.grandhi@intel.com> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/tap.c')
-rw-r--r--drivers/net/tap.c18
1 files changed, 9 insertions, 9 deletions
diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index 9af3239d6ad5..3570c7576993 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -106,7 +106,7 @@ struct major_info {
106 struct rcu_head rcu; 106 struct rcu_head rcu;
107 dev_t major; 107 dev_t major;
108 struct idr minor_idr; 108 struct idr minor_idr;
109 struct mutex minor_lock; 109 spinlock_t minor_lock;
110 const char *device_name; 110 const char *device_name;
111 struct list_head next; 111 struct list_head next;
112}; 112};
@@ -416,15 +416,15 @@ int tap_get_minor(dev_t major, struct tap_dev *tap)
416 goto unlock; 416 goto unlock;
417 } 417 }
418 418
419 mutex_lock(&tap_major->minor_lock); 419 spin_lock(&tap_major->minor_lock);
420 retval = idr_alloc(&tap_major->minor_idr, tap, 1, TAP_NUM_DEVS, GFP_KERNEL); 420 retval = idr_alloc(&tap_major->minor_idr, tap, 1, TAP_NUM_DEVS, GFP_ATOMIC);
421 if (retval >= 0) { 421 if (retval >= 0) {
422 tap->minor = retval; 422 tap->minor = retval;
423 } else if (retval == -ENOSPC) { 423 } else if (retval == -ENOSPC) {
424 netdev_err(tap->dev, "Too many tap devices\n"); 424 netdev_err(tap->dev, "Too many tap devices\n");
425 retval = -EINVAL; 425 retval = -EINVAL;
426 } 426 }
427 mutex_unlock(&tap_major->minor_lock); 427 spin_unlock(&tap_major->minor_lock);
428 428
429unlock: 429unlock:
430 rcu_read_unlock(); 430 rcu_read_unlock();
@@ -442,12 +442,12 @@ void tap_free_minor(dev_t major, struct tap_dev *tap)
442 goto unlock; 442 goto unlock;
443 } 443 }
444 444
445 mutex_lock(&tap_major->minor_lock); 445 spin_lock(&tap_major->minor_lock);
446 if (tap->minor) { 446 if (tap->minor) {
447 idr_remove(&tap_major->minor_idr, tap->minor); 447 idr_remove(&tap_major->minor_idr, tap->minor);
448 tap->minor = 0; 448 tap->minor = 0;
449 } 449 }
450 mutex_unlock(&tap_major->minor_lock); 450 spin_unlock(&tap_major->minor_lock);
451 451
452unlock: 452unlock:
453 rcu_read_unlock(); 453 rcu_read_unlock();
@@ -467,13 +467,13 @@ static struct tap_dev *dev_get_by_tap_file(int major, int minor)
467 goto unlock; 467 goto unlock;
468 } 468 }
469 469
470 mutex_lock(&tap_major->minor_lock); 470 spin_lock(&tap_major->minor_lock);
471 tap = idr_find(&tap_major->minor_idr, minor); 471 tap = idr_find(&tap_major->minor_idr, minor);
472 if (tap) { 472 if (tap) {
473 dev = tap->dev; 473 dev = tap->dev;
474 dev_hold(dev); 474 dev_hold(dev);
475 } 475 }
476 mutex_unlock(&tap_major->minor_lock); 476 spin_unlock(&tap_major->minor_lock);
477 477
478unlock: 478unlock:
479 rcu_read_unlock(); 479 rcu_read_unlock();
@@ -1244,7 +1244,7 @@ static int tap_list_add(dev_t major, const char *device_name)
1244 tap_major->major = MAJOR(major); 1244 tap_major->major = MAJOR(major);
1245 1245
1246 idr_init(&tap_major->minor_idr); 1246 idr_init(&tap_major->minor_idr);
1247 mutex_init(&tap_major->minor_lock); 1247 spin_lock_init(&tap_major->minor_lock);
1248 1248
1249 tap_major->device_name = device_name; 1249 tap_major->device_name = device_name;
1250 1250