Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=4ac63ad6c52e9cdefbcb54ec4575ab12b78b49d9
Commit:     4ac63ad6c52e9cdefbcb54ec4575ab12b78b49d9
Parent:     a014bc8f0f0a3a0cac4fef656f101cdfb77b71eb
Author:     Pavel Emelyanov <[EMAIL PROTECTED]>
AuthorDate: Tue Dec 4 00:45:06 2007 -0800
Committer:  David S. Miller <[EMAIL PROTECTED]>
CommitDate: Wed Dec 5 05:37:27 2007 -0800

    [IPVS]: Fix sched registration race when checking for name collision.
    
    The register_ip_vs_scheduler() checks for the scheduler with the
    same name under the read-locked __ip_vs_sched_lock, then drops,
    takes it for writing and puts the scheduler in list.
    
    This is racy, since we can have a race window between the lock
    being re-locked for writing.
    
    The fix is to search the scheduler with the given name right under
    the write-locked __ip_vs_sched_lock.
    
    Signed-off-by: Pavel Emelyanov <[EMAIL PROTECTED]>
    Acked-by: Simon Horman <[EMAIL PROTECTED]>
    Signed-off-by: David S. Miller <[EMAIL PROTECTED]>
---
 net/ipv4/ipvs/ip_vs_sched.c |   27 ++++++++++++++-------------
 1 files changed, 14 insertions(+), 13 deletions(-)

diff --git a/net/ipv4/ipvs/ip_vs_sched.c b/net/ipv4/ipvs/ip_vs_sched.c
index 1602304..4322358 100644
--- a/net/ipv4/ipvs/ip_vs_sched.c
+++ b/net/ipv4/ipvs/ip_vs_sched.c
@@ -183,19 +183,6 @@ int register_ip_vs_scheduler(struct ip_vs_scheduler 
*scheduler)
        /* increase the module use count */
        ip_vs_use_count_inc();
 
-       /*
-        *  Make sure that the scheduler with this name doesn't exist
-        *  in the scheduler list.
-        */
-       sched = ip_vs_sched_getbyname(scheduler->name);
-       if (sched) {
-               ip_vs_scheduler_put(sched);
-               ip_vs_use_count_dec();
-               IP_VS_ERR("register_ip_vs_scheduler(): [%s] scheduler "
-                         "already existed in the system\n", scheduler->name);
-               return -EINVAL;
-       }
-
        write_lock_bh(&__ip_vs_sched_lock);
 
        if (scheduler->n_list.next != &scheduler->n_list) {
@@ -207,6 +194,20 @@ int register_ip_vs_scheduler(struct ip_vs_scheduler 
*scheduler)
        }
 
        /*
+        *  Make sure that the scheduler with this name doesn't exist
+        *  in the scheduler list.
+        */
+       list_for_each_entry(sched, &ip_vs_schedulers, n_list) {
+               if (strcmp(scheduler->name, sched->name) == 0) {
+                       write_unlock_bh(&__ip_vs_sched_lock);
+                       ip_vs_use_count_dec();
+                       IP_VS_ERR("register_ip_vs_scheduler(): [%s] scheduler "
+                                       "already existed in the system\n",
+                                       scheduler->name);
+                       return -EINVAL;
+               }
+       }
+       /*
         *      Add it into the d-linked scheduler list
         */
        list_add(&scheduler->n_list, &ip_vs_schedulers);
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to