summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2005-10-28 17:53:00 +0200
committerLinus Torvalds <torvalds@g5.osdl.org>2005-10-28 17:53:00 +0200
commit0ee40c6628434f0535da31deeacc28b61e80d810 (patch)
tree2873b9c932a63943fad22617b8385866e45347f5
parentMerge master.kernel.org:/pub/scm/linux/kernel/git/acme/net-2.6.15 (diff)
parent[PATCH] fix try_module_get race in elevator_find (diff)
downloadlinux-0ee40c6628434f0535da31deeacc28b61e80d810.tar.xz
linux-0ee40c6628434f0535da31deeacc28b61e80d810.zip
Merge branch 'for-linus' of git://brick.kernel.dk/data/git/linux-2.6-block
-rw-r--r--drivers/block/elevator.c24
-rw-r--r--drivers/block/ll_rw_blk.c14
-rw-r--r--fs/partitions/check.c2
-rw-r--r--include/linux/genhd.h2
4 files changed, 24 insertions, 18 deletions
diff --git a/drivers/block/elevator.c b/drivers/block/elevator.c
index c744d2a13062..4f69d222b183 100644
--- a/drivers/block/elevator.c
+++ b/drivers/block/elevator.c
@@ -97,7 +97,6 @@ static struct elevator_type *elevator_find(const char *name)
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_find(const char *name)
break;
}
}
- spin_unlock_irq(&elv_list_lock);
return e;
}
@@ -120,12 +118,15 @@ static void elevator_put(struct elevator_type *e)
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");
@@ -555,10 +560,9 @@ void elv_unregister_queue(struct request_queue *q)
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);
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 0f64ee7d8d27..ac31ea170058 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -2433,13 +2433,15 @@ void disk_round_stats(struct gendisk *disk)
{
unsigned long now = jiffies;
- __disk_stat_add(disk, time_in_queue,
- disk->in_flight * (now - disk->stamp));
- disk->stamp = now;
+ if (now == disk->stamp)
+ return;
- if (disk->in_flight)
- __disk_stat_add(disk, io_ticks, (now - disk->stamp_idle));
- disk->stamp_idle = now;
+ if (disk->in_flight) {
+ __disk_stat_add(disk, time_in_queue,
+ disk->in_flight * (now - disk->stamp));
+ __disk_stat_add(disk, io_ticks, (now - disk->stamp));
+ }
+ disk->stamp = now;
}
/*
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 77e178f13162..1e848648a322 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -430,7 +430,7 @@ void del_gendisk(struct gendisk *disk)
disk->flags &= ~GENHD_FL_UP;
unlink_gendisk(disk);
disk_stat_set_all(disk, 0);
- disk->stamp = disk->stamp_idle = 0;
+ disk->stamp = 0;
devfs_remove_disk(disk);
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 01796c41c951..142e1c1e0689 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -119,7 +119,7 @@ struct gendisk {
int policy;
atomic_t sync_io; /* RAID */
- unsigned long stamp, stamp_idle;
+ unsigned long stamp;
int in_flight;
#ifdef CONFIG_SMP
struct disk_stats *dkstats;