Skip to content

Commit

Permalink
tap: convert a mutex to a spinlock
Browse files Browse the repository at this point in the history
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: d9f1f61 ("tap: Extending tap device create/destroy APIs")
Reported-by: Christian Borntraeger <[email protected]>
Tested-by: Christian Borntraeger <[email protected]>
Cc: Sainath Grandhi <[email protected]>
Signed-off-by: Cong Wang <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
congwang authored and davem330 committed Jul 11, 2017
1 parent 6a146f3 commit ffa423f
Showing 1 changed file with 9 additions and 9 deletions.
18 changes: 9 additions & 9 deletions drivers/net/tap.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ struct major_info {
struct rcu_head rcu;
dev_t major;
struct idr minor_idr;
struct mutex minor_lock;
spinlock_t minor_lock;
const char *device_name;
struct list_head next;
};
Expand Down Expand Up @@ -416,15 +416,15 @@ int tap_get_minor(dev_t major, struct tap_dev *tap)
goto unlock;
}

mutex_lock(&tap_major->minor_lock);
retval = idr_alloc(&tap_major->minor_idr, tap, 1, TAP_NUM_DEVS, GFP_KERNEL);
spin_lock(&tap_major->minor_lock);
retval = idr_alloc(&tap_major->minor_idr, tap, 1, TAP_NUM_DEVS, GFP_ATOMIC);
if (retval >= 0) {
tap->minor = retval;
} else if (retval == -ENOSPC) {
netdev_err(tap->dev, "Too many tap devices\n");
retval = -EINVAL;
}
mutex_unlock(&tap_major->minor_lock);
spin_unlock(&tap_major->minor_lock);

unlock:
rcu_read_unlock();
Expand All @@ -442,12 +442,12 @@ void tap_free_minor(dev_t major, struct tap_dev *tap)
goto unlock;
}

mutex_lock(&tap_major->minor_lock);
spin_lock(&tap_major->minor_lock);
if (tap->minor) {
idr_remove(&tap_major->minor_idr, tap->minor);
tap->minor = 0;
}
mutex_unlock(&tap_major->minor_lock);
spin_unlock(&tap_major->minor_lock);

unlock:
rcu_read_unlock();
Expand All @@ -467,13 +467,13 @@ static struct tap_dev *dev_get_by_tap_file(int major, int minor)
goto unlock;
}

mutex_lock(&tap_major->minor_lock);
spin_lock(&tap_major->minor_lock);
tap = idr_find(&tap_major->minor_idr, minor);
if (tap) {
dev = tap->dev;
dev_hold(dev);
}
mutex_unlock(&tap_major->minor_lock);
spin_unlock(&tap_major->minor_lock);

unlock:
rcu_read_unlock();
Expand Down Expand Up @@ -1244,7 +1244,7 @@ static int tap_list_add(dev_t major, const char *device_name)
tap_major->major = MAJOR(major);

idr_init(&tap_major->minor_idr);
mutex_init(&tap_major->minor_lock);
spin_lock_init(&tap_major->minor_lock);

tap_major->device_name = device_name;

Expand Down

0 comments on commit ffa423f

Please sign in to comment.