Revert "misc: uidstat: avoid create_stat() race and blockage."
authorAmit Pundir <amit.pundir@linaro.org>
Mon, 25 Apr 2016 11:30:43 +0000 (17:00 +0530)
committerAmit Pundir <amit.pundir@linaro.org>
Mon, 25 Apr 2016 16:49:46 +0000 (22:19 +0530)
This reverts commit f7a812174033fe620509e6e8ca7022abd924b1c4.

Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
drivers/misc/uid_stat.c

index 509822c81e97b74863db6d5247f659cf06c3eb41..2141124a6c1291e2ace75a465c5c3b803364531c 100644 (file)
@@ -38,13 +38,17 @@ struct uid_stat {
 };
 
 static struct uid_stat *find_uid_stat(uid_t uid) {
+       unsigned long flags;
        struct uid_stat *entry;
 
+       spin_lock_irqsave(&uid_lock, flags);
        list_for_each_entry(entry, &uid_list, link) {
                if (entry->uid == uid) {
+                       spin_unlock_irqrestore(&uid_lock, flags);
                        return entry;
                }
        }
+       spin_unlock_irqrestore(&uid_lock, flags);
        return NULL;
 }
 
@@ -86,10 +90,13 @@ static int tcp_rcv_read_proc(char *page, char **start, off_t off,
 
 /* Create a new entry for tracking the specified uid. */
 static struct uid_stat *create_stat(uid_t uid) {
+       unsigned long flags;
+       char uid_s[32];
        struct uid_stat *new_uid;
+       struct proc_dir_entry *entry;
+
        /* Create the uid stat struct and append it to the list. */
-       new_uid = kmalloc(sizeof(struct uid_stat), GFP_ATOMIC);
-       if (!new_uid)
+       if ((new_uid = kmalloc(sizeof(struct uid_stat), GFP_KERNEL)) == NULL)
                return NULL;
 
        new_uid->uid = uid;
@@ -97,15 +104,11 @@ static struct uid_stat *create_stat(uid_t uid) {
        atomic_set(&new_uid->tcp_rcv, INT_MIN);
        atomic_set(&new_uid->tcp_snd, INT_MIN);
 
+       spin_lock_irqsave(&uid_lock, flags);
        list_add_tail(&new_uid->link, &uid_list);
-       return new_uid;
-}
+       spin_unlock_irqrestore(&uid_lock, flags);
 
-static void create_stat_proc(struct uid_stat *new_uid)
-{
-       char uid_s[32];
-       struct proc_dir_entry *entry;
-       sprintf(uid_s, "%d", new_uid->uid);
+       sprintf(uid_s, "%d", uid);
        entry = proc_mkdir(uid_s, parent);
 
        /* Keep reference to uid_stat so we know what uid to read stats from. */
@@ -114,31 +117,17 @@ static void create_stat_proc(struct uid_stat *new_uid)
 
        create_proc_read_entry("tcp_rcv", S_IRUGO, entry, tcp_rcv_read_proc,
                (void *) new_uid);
-}
 
-static struct uid_stat *find_or_create_uid_stat(uid_t uid)
-{
-       struct uid_stat *entry;
-       unsigned long flags;
-       spin_lock_irqsave(&uid_lock, flags);
-       entry = find_uid_stat(uid);
-       if (entry) {
-               spin_unlock_irqrestore(&uid_lock, flags);
-               return entry;
-       }
-       entry = create_stat(uid);
-       spin_unlock_irqrestore(&uid_lock, flags);
-       if (entry)
-               create_stat_proc(entry);
-       return entry;
+       return new_uid;
 }
 
 int uid_stat_tcp_snd(uid_t uid, int size) {
        struct uid_stat *entry;
        activity_stats_update();
-       entry = find_or_create_uid_stat(uid);
-       if (!entry)
-               return -1;
+       if ((entry = find_uid_stat(uid)) == NULL &&
+               ((entry = create_stat(uid)) == NULL)) {
+                       return -1;
+       }
        atomic_add(size, &entry->tcp_snd);
        return 0;
 }
@@ -146,9 +135,10 @@ int uid_stat_tcp_snd(uid_t uid, int size) {
 int uid_stat_tcp_rcv(uid_t uid, int size) {
        struct uid_stat *entry;
        activity_stats_update();
-       entry = find_or_create_uid_stat(uid);
-       if (!entry)
-               return -1;
+       if ((entry = find_uid_stat(uid)) == NULL &&
+               ((entry = create_stat(uid)) == NULL)) {
+                       return -1;
+       }
        atomic_add(size, &entry->tcp_rcv);
        return 0;
 }