diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2005-10-28 17:53:00 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-10-28 17:53:00 +0200 |
commit | 0ee40c6628434f0535da31deeacc28b61e80d810 (patch) | |
tree | 2873b9c932a63943fad22617b8385866e45347f5 | |
parent | Merge 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) | |
download | linux-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.c | 24 | ||||
-rw-r--r-- | drivers/block/ll_rw_blk.c | 14 | ||||
-rw-r--r-- | fs/partitions/check.c | 2 | ||||
-rw-r--r-- | include/linux/genhd.h | 2 |
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; |