Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

WANG Cong and committed by
David S. Miller
ffa423fb 6a146f3a

+9 -9
+9 -9
drivers/net/tap.c
··· 106 106 struct rcu_head rcu; 107 107 dev_t major; 108 108 struct idr minor_idr; 109 - struct mutex minor_lock; 109 + spinlock_t minor_lock; 110 110 const char *device_name; 111 111 struct list_head next; 112 112 }; ··· 416 416 goto unlock; 417 417 } 418 418 419 - mutex_lock(&tap_major->minor_lock); 420 - retval = idr_alloc(&tap_major->minor_idr, tap, 1, TAP_NUM_DEVS, GFP_KERNEL); 419 + spin_lock(&tap_major->minor_lock); 420 + retval = idr_alloc(&tap_major->minor_idr, tap, 1, TAP_NUM_DEVS, GFP_ATOMIC); 421 421 if (retval >= 0) { 422 422 tap->minor = retval; 423 423 } else if (retval == -ENOSPC) { 424 424 netdev_err(tap->dev, "Too many tap devices\n"); 425 425 retval = -EINVAL; 426 426 } 427 - mutex_unlock(&tap_major->minor_lock); 427 + spin_unlock(&tap_major->minor_lock); 428 428 429 429 unlock: 430 430 rcu_read_unlock(); ··· 442 442 goto unlock; 443 443 } 444 444 445 - mutex_lock(&tap_major->minor_lock); 445 + spin_lock(&tap_major->minor_lock); 446 446 if (tap->minor) { 447 447 idr_remove(&tap_major->minor_idr, tap->minor); 448 448 tap->minor = 0; 449 449 } 450 - mutex_unlock(&tap_major->minor_lock); 450 + spin_unlock(&tap_major->minor_lock); 451 451 452 452 unlock: 453 453 rcu_read_unlock(); ··· 467 467 goto unlock; 468 468 } 469 469 470 - mutex_lock(&tap_major->minor_lock); 470 + spin_lock(&tap_major->minor_lock); 471 471 tap = idr_find(&tap_major->minor_idr, minor); 472 472 if (tap) { 473 473 dev = tap->dev; 474 474 dev_hold(dev); 475 475 } 476 - mutex_unlock(&tap_major->minor_lock); 476 + spin_unlock(&tap_major->minor_lock); 477 477 478 478 unlock: 479 479 rcu_read_unlock(); ··· 1244 1244 tap_major->major = MAJOR(major); 1245 1245 1246 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 1249 tap_major->device_name = device_name; 1250 1250