net: Add a mutex around devnet_rename_seq
On RT write_seqcount_begin() disables preemption and device_rename() allocates memory with GFP_KERNEL and grabs later the sysfs_mutex mutex. Serialize with a mutex and add use the non preemption disabling __write_seqcount_begin(). To avoid writer starvation, let the reader grab the mutex and release it when it detects a writer in progress. This keeps the normal case (no reader on the fly) fast. [ tglx: Instead of replacing the seqcount by a mutex, add the mutex ] Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
parent
dd624a5df8
commit
739cec90a6
|
@ -181,6 +181,7 @@ static unsigned int napi_gen_id;
|
|||
static DEFINE_HASHTABLE(napi_hash, 8);
|
||||
|
||||
static seqcount_t devnet_rename_seq;
|
||||
static DEFINE_MUTEX(devnet_rename_mutex);
|
||||
|
||||
static inline void dev_base_seq_inc(struct net *net)
|
||||
{
|
||||
|
@ -831,7 +832,8 @@ retry:
|
|||
strcpy(name, dev->name);
|
||||
rcu_read_unlock();
|
||||
if (read_seqcount_retry(&devnet_rename_seq, seq)) {
|
||||
cond_resched();
|
||||
mutex_lock(&devnet_rename_mutex);
|
||||
mutex_unlock(&devnet_rename_mutex);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
|
@ -1097,30 +1099,28 @@ int dev_change_name(struct net_device *dev, const char *newname)
|
|||
if (dev->flags & IFF_UP)
|
||||
return -EBUSY;
|
||||
|
||||
write_seqcount_begin(&devnet_rename_seq);
|
||||
mutex_lock(&devnet_rename_mutex);
|
||||
__raw_write_seqcount_begin(&devnet_rename_seq);
|
||||
|
||||
if (strncmp(newname, dev->name, IFNAMSIZ) == 0) {
|
||||
write_seqcount_end(&devnet_rename_seq);
|
||||
return 0;
|
||||
}
|
||||
if (strncmp(newname, dev->name, IFNAMSIZ) == 0)
|
||||
goto outunlock;
|
||||
|
||||
memcpy(oldname, dev->name, IFNAMSIZ);
|
||||
|
||||
err = dev_get_valid_name(net, dev, newname);
|
||||
if (err < 0) {
|
||||
write_seqcount_end(&devnet_rename_seq);
|
||||
return err;
|
||||
}
|
||||
if (err < 0)
|
||||
goto outunlock;
|
||||
|
||||
rollback:
|
||||
ret = device_rename(&dev->dev, dev->name);
|
||||
if (ret) {
|
||||
memcpy(dev->name, oldname, IFNAMSIZ);
|
||||
write_seqcount_end(&devnet_rename_seq);
|
||||
return ret;
|
||||
err = ret;
|
||||
goto outunlock;
|
||||
}
|
||||
|
||||
write_seqcount_end(&devnet_rename_seq);
|
||||
__raw_write_seqcount_end(&devnet_rename_seq);
|
||||
mutex_unlock(&devnet_rename_mutex);
|
||||
|
||||
netdev_adjacent_rename_links(dev, oldname);
|
||||
|
||||
|
@ -1141,7 +1141,8 @@ rollback:
|
|||
/* err >= 0 after dev_alloc_name() or stores the first errno */
|
||||
if (err >= 0) {
|
||||
err = ret;
|
||||
write_seqcount_begin(&devnet_rename_seq);
|
||||
mutex_lock(&devnet_rename_mutex);
|
||||
__raw_write_seqcount_begin(&devnet_rename_seq);
|
||||
memcpy(dev->name, oldname, IFNAMSIZ);
|
||||
memcpy(oldname, newname, IFNAMSIZ);
|
||||
goto rollback;
|
||||
|
@ -1152,6 +1153,11 @@ rollback:
|
|||
}
|
||||
|
||||
return err;
|
||||
|
||||
outunlock:
|
||||
__raw_write_seqcount_end(&devnet_rename_seq);
|
||||
mutex_unlock(&devnet_rename_mutex);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue