lkml.org 
[lkml]   [2005]   [Jul]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[PATCH linux-2.6-block:master] block: fix try_module_get race in elevator_find
 Hello, Jens.

This patch removes try_module_get race in elevator_find.
try_module_get should always be called with the spinlock protecting
what the module init/cleanup routines register/unregister to held. In
the case of elevators, we should be holding elv_list to avoid it going
away between spin_unlock_irq and try_module_get.

This currently doesn't cause any problem as elevators are never
unloaded, but the fix is simple and it's always nice to be correct.

Signed-off-by: Tejun Heo <htejun@gmail.com>

Index: blk-fixes/drivers/block/elevator.c
===================================================================
--- blk-fixes.orig/drivers/block/elevator.c 2005-07-25 23:16:11.000000000 +0900
+++ blk-fixes/drivers/block/elevator.c 2005-07-25 23:20:30.000000000 +0900
@@ -97,7 +97,6 @@ static struct elevator_type *elevator_fi
struct elevator_type *e = NULL;
struct list_head *entry;

- spin_lock_irq(&elv_list_lock);
list_for_each(entry, &elv_list) {
struct elevator_type *__e;

@@ -108,7 +107,6 @@ static struct elevator_type *elevator_fi
break;
}
}
- spin_unlock_irq(&elv_list_lock);

return e;
}
@@ -120,12 +118,15 @@ static void elevator_put(struct elevator

static struct elevator_type *elevator_get(const char *name)
{
- struct elevator_type *e = elevator_find(name);
+ struct elevator_type *e;

- if (!e)
- return NULL;
- if (!try_module_get(e->elevator_owner))
- return NULL;
+ spin_lock_irq(&elv_list_lock);
+
+ e = elevator_find(name);
+ if (e && !try_module_get(e->elevator_owner))
+ e = NULL;
+
+ spin_unlock_irq(&elv_list_lock);

return e;
}
@@ -153,11 +154,15 @@ static char chosen_elevator[16];

static void elevator_setup_default(void)
{
+ struct elevator_type *e;
+
/*
* check if default is set and exists
*/
- if (chosen_elevator[0] && elevator_find(chosen_elevator))
+ if (chosen_elevator[0] && (e = elevator_get(chosen_elevator))) {
+ elevator_put(e);
return;
+ }

#if defined(CONFIG_IOSCHED_AS)
strcpy(chosen_elevator, "anticipatory");
@@ -554,10 +559,9 @@ void elv_unregister_queue(struct request

int elv_register(struct elevator_type *e)
{
+ spin_lock_irq(&elv_list_lock);
if (elevator_find(e->elevator_name))
BUG();
-
- spin_lock_irq(&elv_list_lock);
list_add_tail(&e->list, &elv_list);
spin_unlock_irq(&elv_list_lock);

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
\
 
 \ /
  Last update: 2005-07-26 15:24    [W:0.040 / U:2.272 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site