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:
Sebastian Andrzej Siewior 2013-03-20 18:06:20 +01:00 committed by Alibek Omarov
parent dd624a5df8
commit 739cec90a6
1 changed files with 20 additions and 14 deletions

View File

@ -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;
}
/**