]> rtime.felk.cvut.cz Git - zynq/linux.git/commitdiff
net: Add a mutex around devnet_rename_seq
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>
Wed, 20 Mar 2013 17:06:20 +0000 (18:06 +0100)
committerMichal Sojka <sojka@merica.cz>
Sun, 13 Sep 2015 07:47:40 +0000 (09:47 +0200)
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>
net/core/dev.c

index f0afbf66105fb05de4a062445f0a40b0ca65907e..8f9b87b4bb3f6f9844ae939b776bc1130bb5cf97 100644 (file)
@@ -184,6 +184,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)
 {
@@ -835,7 +836,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;
        }
 
@@ -1104,20 +1106,17 @@ 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;
 
        if (oldname[0] && !strchr(oldname, '%'))
                netdev_info(dev, "renamed from %s\n", oldname);
@@ -1130,11 +1129,12 @@ rollback:
        if (ret) {
                memcpy(dev->name, oldname, IFNAMSIZ);
                dev->name_assign_type = old_assign_type;
-               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);
 
@@ -1155,7 +1155,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);
                        dev->name_assign_type = old_assign_type;
@@ -1168,6 +1169,11 @@ rollback:
        }
 
        return err;
+
+outunlock:
+       __raw_write_seqcount_end(&devnet_rename_seq);
+       mutex_unlock(&devnet_rename_mutex);
+       return err;
 }
 
 /**