From e105b8bfc769b0545b6f0f395179d1e43cbee822 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 21 Apr 2008 10:51:07 -0700 Subject: sysfs: add /sys/dev/{char,block} to lookup sysfs path by major:minor Why?: There are occasions where userspace would like to access sysfs attributes for a device but it may not know how sysfs has named the device or the path. For example what is the sysfs path for /dev/disk/by-id/ata-ST3160827AS_5MT004CK? With this change a call to stat(2) returns the major:minor then userspace can see that /sys/dev/block/8:32 links to /sys/block/sdc. What are the alternatives?: 1/ Add an ioctl to return the path: Doable, but sysfs is meant to reduce the need to proliferate ioctl interfaces into the kernel, so this seems counter productive. 2/ Use udev to create these symlinks: Also doable, but it adds a udev dependency to utilities that might be running in a limited environment like an initramfs. 3/ Do a full-tree search of sysfs. [kay.sievers@vrfy.org: fix duplicate registrations] [kay.sievers@vrfy.org: cleanup suggestions] Cc: Neil Brown Cc: Tejun Heo Acked-by: Kay Sievers Reviewed-by: SL Baur Acked-by: Kay Sievers Acked-by: Mark Lord Acked-by: H. Peter Anvin Signed-off-by: Dan Williams Signed-off-by: Greg Kroah-Hartman --- block/genhd.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'block') diff --git a/block/genhd.c b/block/genhd.c index 9074f384b097..24e3fc9095fe 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -370,7 +370,10 @@ static struct kobject *base_probe(dev_t devt, int *part, void *data) static int __init genhd_device_init(void) { - int error = class_register(&block_class); + int error; + + block_class.dev_kobj = sysfs_dev_block_kobj; + error = class_register(&block_class); if (unlikely(error)) return error; bdev_map = kobj_map_init(base_probe, &block_class_lock); -- cgit v1.3-18-gd494 From f79f060561d04a38d41e773ade9baafce3c96179 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 21 May 2008 12:52:33 -0700 Subject: device create: block: convert device_create to device_create_drvdata device_create() is race-prone, so use the race-free device_create_drvdata() instead as device_create() is going away. Signed-off-by: Greg Kroah-Hartman --- block/bsg.c | 3 ++- drivers/block/aoe/aoechr.c | 5 +++-- drivers/block/paride/pg.c | 5 +++-- drivers/block/paride/pt.c | 10 ++++++---- drivers/block/pktcdvd.c | 4 +++- 5 files changed, 17 insertions(+), 10 deletions(-) (limited to 'block') diff --git a/block/bsg.c b/block/bsg.c index 5fb9b0bdbe85..5a68b09a69ba 100644 --- a/block/bsg.c +++ b/block/bsg.c @@ -1044,7 +1044,8 @@ int bsg_register_queue(struct request_queue *q, struct device *parent, bcd->release = release; kref_init(&bcd->ref); dev = MKDEV(bsg_major, bcd->minor); - class_dev = device_create(bsg_class, parent, dev, "%s", devname); + class_dev = device_create_drvdata(bsg_class, parent, dev, NULL, + "%s", devname); if (IS_ERR(class_dev)) { ret = PTR_ERR(class_dev); goto put_dev; diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c index d1de68a31920..c04440cd6a32 100644 --- a/drivers/block/aoe/aoechr.c +++ b/drivers/block/aoe/aoechr.c @@ -277,8 +277,9 @@ aoechr_init(void) return PTR_ERR(aoe_class); } for (i = 0; i < ARRAY_SIZE(chardevs); ++i) - device_create(aoe_class, NULL, - MKDEV(AOE_MAJOR, chardevs[i].minor), chardevs[i].name); + device_create_drvdata(aoe_class, NULL, + MKDEV(AOE_MAJOR, chardevs[i].minor), + NULL, chardevs[i].name); return 0; } diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c index 9d92636350e5..d731ca42f802 100644 --- a/drivers/block/paride/pg.c +++ b/drivers/block/paride/pg.c @@ -686,8 +686,9 @@ static int __init pg_init(void) for (unit = 0; unit < PG_UNITS; unit++) { struct pg *dev = &devices[unit]; if (dev->present) - device_create(pg_class, NULL, MKDEV(major, unit), - "pg%u", unit); + device_create_drvdata(pg_class, NULL, + MKDEV(major, unit), NULL, + "pg%u", unit); } err = 0; goto out; diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c index 5c74c3574a5a..673b8b2fd337 100644 --- a/drivers/block/paride/pt.c +++ b/drivers/block/paride/pt.c @@ -979,10 +979,12 @@ static int __init pt_init(void) for (unit = 0; unit < PT_UNITS; unit++) if (pt[unit].present) { - device_create(pt_class, NULL, MKDEV(major, unit), - "pt%d", unit); - device_create(pt_class, NULL, MKDEV(major, unit + 128), - "pt%dn", unit); + device_create_drvdata(pt_class, NULL, + MKDEV(major, unit), NULL, + "pt%d", unit); + device_create_drvdata(pt_class, NULL, + MKDEV(major, unit + 128), NULL, + "pt%dn", unit); } goto out; diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 45bee918c46a..158eed4d5161 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -303,7 +303,9 @@ static struct kobj_type kobj_pkt_type_wqueue = { static void pkt_sysfs_dev_new(struct pktcdvd_device *pd) { if (class_pktcdvd) { - pd->dev = device_create(class_pktcdvd, NULL, pd->pkt_dev, "%s", pd->name); + pd->dev = device_create_drvdata(class_pktcdvd, NULL, + pd->pkt_dev, NULL, + "%s", pd->name); if (IS_ERR(pd->dev)) pd->dev = NULL; } -- cgit v1.3-18-gd494 From 6ffeea77ff014f1456fcd0564eac84b34e9535ca Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 22 May 2008 17:21:08 -0400 Subject: block: fix compiler warning in genhd.c Warn if something really bad happens if we can't create this link. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- block/genhd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'block') diff --git a/block/genhd.c b/block/genhd.c index 24e3fc9095fe..3ccf5c017565 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -183,6 +183,7 @@ static int exact_lock(dev_t devt, void *data) void add_disk(struct gendisk *disk) { struct backing_dev_info *bdi; + int retval; disk->flags |= GENHD_FL_UP; blk_register_region(MKDEV(disk->major, disk->first_minor), @@ -193,7 +194,8 @@ void add_disk(struct gendisk *disk) bdi = &disk->queue->backing_dev_info; bdi_register_dev(bdi, MKDEV(disk->major, disk->first_minor)); - sysfs_create_link(&disk->dev.kobj, &bdi->dev->kobj, "bdi"); + retval = sysfs_create_link(&disk->dev.kobj, &bdi->dev->kobj, "bdi"); + WARN_ON(retval); } EXPORT_SYMBOL(add_disk); -- cgit v1.3-18-gd494 From 5c6f35c5ece8f130cd8ec9ba0d71dc146b46a0f1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 22 May 2008 17:21:08 -0400 Subject: block: make printk_partition use the class iterator function Use the proper class iterator function instead of mucking around in the internals of the class structures. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- block/genhd.c | 93 ++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 50 insertions(+), 43 deletions(-) (limited to 'block') diff --git a/block/genhd.c b/block/genhd.c index 3ccf5c017565..10b9ac46c2da 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -227,58 +227,65 @@ struct gendisk *get_gendisk(dev_t devt, int *part) } /* - * print a full list of all partitions - intended for places where the root - * filesystem can't be mounted and thus to give the victim some idea of what - * went wrong + * print a partitions - intended for places where the root filesystem can't be + * mounted and thus to give the victim some idea of what went wrong */ -void __init printk_all_partitions(void) +static int printk_partition(struct device *dev, void *data) { - struct device *dev; struct gendisk *sgp; char buf[BDEVNAME_SIZE]; int n; - mutex_lock(&block_class_lock); - /* For each block device... */ - list_for_each_entry(dev, &block_class.devices, node) { - if (dev->type != &disk_type) - continue; - sgp = dev_to_disk(dev); - /* - * Don't show empty devices or things that have been surpressed - */ - if (get_capacity(sgp) == 0 || - (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO)) - continue; + if (dev->type != &disk_type) + goto exit; - /* - * Note, unlike /proc/partitions, I am showing the numbers in - * hex - the same format as the root= option takes. - */ - printk("%02x%02x %10llu %s", - sgp->major, sgp->first_minor, - (unsigned long long)get_capacity(sgp) >> 1, - disk_name(sgp, 0, buf)); - if (sgp->driverfs_dev != NULL && - sgp->driverfs_dev->driver != NULL) - printk(" driver: %s\n", - sgp->driverfs_dev->driver->name); - else - printk(" (driver?)\n"); - - /* now show the partitions */ - for (n = 0; n < sgp->minors - 1; ++n) { - if (sgp->part[n] == NULL) - continue; - if (sgp->part[n]->nr_sects == 0) - continue; - printk(" %02x%02x %10llu %s\n", - sgp->major, n + 1 + sgp->first_minor, - (unsigned long long)sgp->part[n]->nr_sects >> 1, - disk_name(sgp, n + 1, buf)); - } + sgp = dev_to_disk(dev); + /* + * Don't show empty devices or things that have been surpressed + */ + if (get_capacity(sgp) == 0 || + (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO)) + goto exit; + + /* + * Note, unlike /proc/partitions, I am showing the numbers in + * hex - the same format as the root= option takes. + */ + printk("%02x%02x %10llu %s", + sgp->major, sgp->first_minor, + (unsigned long long)get_capacity(sgp) >> 1, + disk_name(sgp, 0, buf)); + if (sgp->driverfs_dev != NULL && + sgp->driverfs_dev->driver != NULL) + printk(" driver: %s\n", + sgp->driverfs_dev->driver->name); + else + printk(" (driver?)\n"); + + /* now show the partitions */ + for (n = 0; n < sgp->minors - 1; ++n) { + if (sgp->part[n] == NULL) + goto exit; + if (sgp->part[n]->nr_sects == 0) + goto exit; + printk(" %02x%02x %10llu %s\n", + sgp->major, n + 1 + sgp->first_minor, + (unsigned long long)sgp->part[n]->nr_sects >> 1, + disk_name(sgp, n + 1, buf)); } +exit: + return 0; +} +/* + * print a full list of all partitions - intended for places where the root + * filesystem can't be mounted and thus to give the victim some idea of what + * went wrong + */ +void __init printk_all_partitions(void) +{ + mutex_lock(&block_class_lock); + class_for_each_device(&block_class, NULL, NULL, printk_partition); mutex_unlock(&block_class_lock); } -- cgit v1.3-18-gd494 From a142be856f060ae8106512c0e81a8d6f8746ab0b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 22 May 2008 17:21:08 -0400 Subject: block: make blk_lookup_devt use the class iterator function Use the proper class iterator function instead of mucking around in the internals of the class structures. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- block/genhd.c | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) (limited to 'block') diff --git a/block/genhd.c b/block/genhd.c index 10b9ac46c2da..e8c42bfd12be 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -677,24 +677,38 @@ void genhd_media_change_notify(struct gendisk *disk) EXPORT_SYMBOL_GPL(genhd_media_change_notify); #endif /* 0 */ +struct find_block { + const char *name; + int part; +}; + +static int match_id(struct device *dev, void *data) +{ + struct find_block *find = data; + + if (dev->type != &disk_type) + return 0; + if (strcmp(dev->bus_id, find->name) == 0) { + struct gendisk *disk = dev_to_disk(dev); + if (find->part < disk->minors) + return 1; + } + return 0; +} + dev_t blk_lookup_devt(const char *name, int part) { struct device *dev; dev_t devt = MKDEV(0, 0); + struct find_block find; mutex_lock(&block_class_lock); - list_for_each_entry(dev, &block_class.devices, node) { - if (dev->type != &disk_type) - continue; - if (strcmp(dev->bus_id, name) == 0) { - struct gendisk *disk = dev_to_disk(dev); - - if (part < disk->minors) - devt = MKDEV(MAJOR(dev->devt), - MINOR(dev->devt) + part); - break; - } - } + find.name = name; + find.part = part; + dev = class_find_device(&block_class, NULL, (void *)&find, match_id); + if (dev) + devt = MKDEV(MAJOR(dev->devt), + MINOR(dev->devt) + part); mutex_unlock(&block_class_lock); return devt; -- cgit v1.3-18-gd494 From a6e2ba88774bc5870ab3d9664cb86d70415f7402 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 23 May 2008 09:44:11 -0700 Subject: block: make /proc/diskstats only build if CONFIG_PROC_FS is enabled These functions are only needed if CONFIG_PROC_FS is enabled, so save the space when it is not. This also makes it easier for a patch later in this series to work properly if CONFIG_PROC_FS is not enabled. Signed-off-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- block/genhd.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'block') diff --git a/block/genhd.c b/block/genhd.c index e8c42bfd12be..68a5f28007e4 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -544,6 +544,7 @@ static struct device_type disk_type = { .release = disk_release, }; +#ifdef CONFIG_PROC_FS /* * aggregate disk stat collector. Uses the same stats that the sysfs * entries do, above, but makes them available through one seq_file. @@ -653,6 +654,7 @@ const struct seq_operations diskstats_op = { .stop = diskstats_stop, .show = diskstats_show }; +#endif /* CONFIG_PROC_FS */ static void media_change_notify_thread(struct work_struct *work) { -- cgit v1.3-18-gd494 From 68c4d4a7875c59f2e4b72901ab11ba978e75bde0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 22 May 2008 17:21:08 -0400 Subject: block: make proc files seq_start use the class_find_device() Use the proper class iterator function instead of mucking around in the internals of the class structures. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- block/genhd.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) (limited to 'block') diff --git a/block/genhd.c b/block/genhd.c index 68a5f28007e4..f03bdadc52ac 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -291,18 +291,25 @@ void __init printk_all_partitions(void) #ifdef CONFIG_PROC_FS /* iterator */ +static int find_start(struct device *dev, void *data) +{ + loff_t k = *(loff_t *)data; + + if (dev->type != &disk_type) + return 0; + if (!k--) + return 1; + return 0; +} + static void *part_start(struct seq_file *part, loff_t *pos) { - loff_t k = *pos; struct device *dev; mutex_lock(&block_class_lock); - list_for_each_entry(dev, &block_class.devices, node) { - if (dev->type != &disk_type) - continue; - if (!k--) - return dev_to_disk(dev); - } + dev = class_find_device(&block_class, NULL, (void *)pos, find_start); + if (dev) + return dev_to_disk(dev); return NULL; } @@ -555,16 +562,12 @@ static struct device_type disk_type = { static void *diskstats_start(struct seq_file *part, loff_t *pos) { - loff_t k = *pos; struct device *dev; mutex_lock(&block_class_lock); - list_for_each_entry(dev, &block_class.devices, node) { - if (dev->type != &disk_type) - continue; - if (!k--) - return dev_to_disk(dev); - } + dev = class_find_device(&block_class, NULL, (void *)pos, find_start); + if (dev) + return dev_to_disk(dev); return NULL; } -- cgit v1.3-18-gd494 From 66c64afec16a7b46212ecb2fa99998923bbeea3f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 22 May 2008 17:21:08 -0400 Subject: block: move header for /proc/partitions to seq_start The seq_start call is the better place for the header for the file, that way we don't have to be mucking in the class structure to try to figure out if this is the first partition or not. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- block/genhd.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'block') diff --git a/block/genhd.c b/block/genhd.c index f03bdadc52ac..70f1d7075783 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -305,6 +305,10 @@ static int find_start(struct device *dev, void *data) static void *part_start(struct seq_file *part, loff_t *pos) { struct device *dev; + loff_t n = *pos; + + if (!n) + seq_puts(part, "major minor #blocks name\n\n"); mutex_lock(&block_class_lock); dev = class_find_device(&block_class, NULL, (void *)pos, find_start); @@ -338,9 +342,6 @@ static int show_partition(struct seq_file *part, void *v) int n; char buf[BDEVNAME_SIZE]; - if (&sgp->dev.node == block_class.devices.next) - seq_puts(part, "major minor #blocks name\n\n"); - /* Don't show non-partitionable removeable devices or empty devices */ if (!get_capacity(sgp) || (sgp->minors == 1 && (sgp->flags & GENHD_FL_REMOVABLE))) -- cgit v1.3-18-gd494 From 27f302519148f311307637d4c9a6d0fd87d07e4c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 22 May 2008 17:21:08 -0400 Subject: block: make /proc/partitions and /proc/diskstats use class_find_device() Use the proper class iterator function instead of mucking around in the internals of the class structures. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- block/genhd.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'block') diff --git a/block/genhd.c b/block/genhd.c index 70f1d7075783..c13cc77291af 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -317,17 +317,21 @@ static void *part_start(struct seq_file *part, loff_t *pos) return NULL; } +static int find_next(struct device *dev, void *data) +{ + if (dev->type == &disk_type) + return 1; + return 0; +} + static void *part_next(struct seq_file *part, void *v, loff_t *pos) { struct gendisk *gp = v; struct device *dev; ++*pos; - list_for_each_entry(dev, &gp->dev.node, node) { - if (&dev->node == &block_class.devices) - return NULL; - if (dev->type == &disk_type) - return dev_to_disk(dev); - } + dev = class_find_device(&block_class, &gp->dev, NULL, find_next); + if (dev) + return dev_to_disk(dev); return NULL; } @@ -578,12 +582,9 @@ static void *diskstats_next(struct seq_file *part, void *v, loff_t *pos) struct device *dev; ++*pos; - list_for_each_entry(dev, &gp->dev.node, node) { - if (&dev->node == &block_class.devices) - return NULL; - if (dev->type == &disk_type) - return dev_to_disk(dev); - } + dev = class_find_device(&block_class, &gp->dev, NULL, find_next); + if (dev) + return dev_to_disk(dev); return NULL; } -- cgit v1.3-18-gd494 From 04ebd4aee52b06a2c38127d9208546e5b96f3a19 Mon Sep 17 00:00:00 2001 From: Abdel Benamrouche Date: Fri, 25 Jul 2008 01:48:26 -0700 Subject: block/ioctl.c and fs/partition/check.c: check value returned by add_partition() Now that add_partition() has been aught to propagate errors, let's check them. [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Abdel Benamrouche Cc: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- block/ioctl.c | 5 +++-- fs/partitions/check.c | 10 ++++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'block') diff --git a/block/ioctl.c b/block/ioctl.c index 52d6385216ad..77185e5c026a 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -17,6 +17,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user long long start, length; int part; int i; + int err; if (!capable(CAP_SYS_ADMIN)) return -EACCES; @@ -61,9 +62,9 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user } } /* all seems OK */ - add_partition(disk, part, start, length, ADDPART_FLAG_NONE); + err = add_partition(disk, part, start, length, ADDPART_FLAG_NONE); mutex_unlock(&bdev->bd_mutex); - return 0; + return err; case BLKPG_DEL_PARTITION: if (!disk->part[part-1]) return -ENXIO; diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 2e6413fbd2d8..7d6b34e201db 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -499,10 +499,16 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev) if (!size) continue; if (from + size > get_capacity(disk)) { - printk(" %s: p%d exceeds device capacity\n", + printk(KERN_ERR " %s: p%d exceeds device capacity\n", disk->disk_name, p); + continue; + } + res = add_partition(disk, p, from, size, state->parts[p].flags); + if (res) { + printk(KERN_ERR " %s: p%d could not be added: %d\n", + disk->disk_name, p, -res); + continue; } - add_partition(disk, p, from, size, state->parts[p].flags); #ifdef CONFIG_BLK_DEV_MD if (state->parts[p].flags & ADDPART_FLAG_RAID) md_autodetect_dev(bdev->bd_dev+p); -- cgit v1.3-18-gd494 From a76eef9573c93f8f324ebacfd090a3e319a64d59 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Fri, 25 Jul 2008 19:44:39 -0700 Subject: block/blk-map.c: use the new object_is_on_stack() helper Signed-off-by: FUJITA Tomonori Cc: Bartlomiej Zolnierkiewicz Cc: Thomas Bogendoerfer Cc: Tejun Heo Cc: Jens Axboe Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- block/blk-map.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'block') diff --git a/block/blk-map.c b/block/blk-map.c index ddd96fb11a7d..af37e4ae62f5 100644 --- a/block/blk-map.c +++ b/block/blk-map.c @@ -269,7 +269,6 @@ int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf, int reading = rq_data_dir(rq) == READ; int do_copy = 0; struct bio *bio; - unsigned long stack_mask = ~(THREAD_SIZE - 1); if (len > (q->max_hw_sectors << 9)) return -EINVAL; @@ -278,11 +277,8 @@ int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf, kaddr = (unsigned long)kbuf; alignment = queue_dma_alignment(q) | q->dma_pad_mask; - do_copy = ((kaddr & alignment) || (len & alignment)); - - if (!((kaddr & stack_mask) ^ - ((unsigned long)current->stack & stack_mask))) - do_copy = 1; + do_copy = ((kaddr & alignment) || (len & alignment) || + object_is_on_stack(kbuf)); if (do_copy) bio = bio_copy_kern(q, kbuf, len, gfp_mask, reading); -- cgit v1.3-18-gd494 From 12e0036818eed243c8ed6583ebf98261a2554e12 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Fri, 25 Jul 2008 19:45:38 -0700 Subject: Use WARN() in block/ Use WARN() instead of a printk+WARN_ON() pair; this way the message becomes part of the warning section for better reporting/collection. Signed-off-by: Arjan van de Ven Cc: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- block/as-iosched.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'block') diff --git a/block/as-iosched.c b/block/as-iosched.c index 9735acb5b4f5..cf4eb0eefbbf 100644 --- a/block/as-iosched.c +++ b/block/as-iosched.c @@ -837,8 +837,7 @@ static void as_completed_request(struct request_queue *q, struct request *rq) WARN_ON(!list_empty(&rq->queuelist)); if (RQ_STATE(rq) != AS_RQ_REMOVED) { - printk("rq->state %d\n", RQ_STATE(rq)); - WARN_ON(1); + WARN(1, "rq->state %d\n", RQ_STATE(rq)); goto out; } -- cgit v1.3-18-gd494 From ad337591f4fd20de6a0ca03d6715267a5c1d2b16 Mon Sep 17 00:00:00 2001 From: Tim Wright Date: Sun, 27 Jul 2008 17:50:38 -0700 Subject: [SCSI] block: Fix miscalculation of sg_io timeout in CDROM_SEND_PACKET handler. It seems cdrwtool in the udftools has been unusable on "modern" kernels for some time. A Google search reveals many people with the same issue but no solution (cdrwtool fails to format the disk). After spending some time tracking down the issue, it comes down to the following: The udftools still use the older CDROM_SEND_PACKET interface to send things like FORMAT_UNIT through to the drive. They should really be updated, but that's another story. Since most distros are using libata now, the cd or dvd burner appears as a SCSI device, and we wind up in block/scsi_ioctl.c. Here, the code tries to take the "struct cdrom_generic_command" and translate it and stuff it into a "struct sg_io_hdr" structure so it can pass it to the modern sg_io() routine instead. Unfortunately, there is one error, or rather an omission in the translation. The timeout that is passed in in the "struct cdrom_generic_command" is in HZ=100 units, and this is modified and correctly converted to jiffies by use of clock_t_to_jiffies(). However, a little further down, this cgc.timeout value in jiffies is simply copied into the sg_io_hdr timeout, which should be in milliseconds. Since most modern x86 kernels seems to be getting build with HZ=250, the timeout that is passed to sg_io and eventually converted to the timeout_per_command member of the scsi_cmnd structure is now four times too small. Since cdrwtool tries to set the timeout to one hour for the FORMAT_UNIT command, and it takes about 20 minutes to format a 4x CDRW, the SCSI error-handler kicks in after the FORMAT_UNIT completes because it took longer than the incorrectly-calculated timeout. [jejb: fix up whitespace] Signed-off-by: Tim Wright Cc: Stable Tree Signed-off-by: James Bottomley --- block/scsi_ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'block') diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index c5b9bcfc0a6d..12a5182173f6 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -518,7 +518,7 @@ int scsi_cmd_ioctl(struct file *file, struct request_queue *q, hdr.sbp = cgc.sense; if (hdr.sbp) hdr.mx_sb_len = sizeof(struct request_sense); - hdr.timeout = cgc.timeout; + hdr.timeout = jiffies_to_msecs(cgc.timeout); hdr.cmdp = ((struct cdrom_generic_command __user*) arg)->cmd; hdr.cmd_len = sizeof(cgc.cmd); -- cgit v1.3-18-gd494 From 6c5e0c4d518a37e1d5d794c14433e80284415079 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 1 Aug 2008 20:31:32 +0200 Subject: block: add a blk_plug_device_unlocked() that grabs the queue lock blk_plug_device() must be called with the queue lock held, so callers often just grab and release the lock for that purpose. Add a helper that does just that. Signed-off-by: Jens Axboe --- block/blk-core.c | 18 ++++++++++++++++++ include/linux/blkdev.h | 1 + 2 files changed, 19 insertions(+) (limited to 'block') diff --git a/block/blk-core.c b/block/blk-core.c index fef79ccb2a11..4889eb86a39e 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -212,6 +212,24 @@ void blk_plug_device(struct request_queue *q) } EXPORT_SYMBOL(blk_plug_device); +/** + * blk_plug_device_unlocked - plug a device without queue lock held + * @q: The &struct request_queue to plug + * + * Description: + * Like @blk_plug_device(), but grabs the queue lock and disables + * interrupts. + **/ +void blk_plug_device_unlocked(struct request_queue *q) +{ + unsigned long flags; + + spin_lock_irqsave(q->queue_lock, flags); + blk_plug_device(q); + spin_unlock_irqrestore(q->queue_lock, flags); +} +EXPORT_SYMBOL(blk_plug_device_unlocked); + /* * remove the queue from the plugged list, if present. called with * queue lock held and interrupts disabled. diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 88d68081a0f1..e61f22be4d0e 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -655,6 +655,7 @@ extern struct request *blk_get_request(struct request_queue *, int, gfp_t); extern void blk_insert_request(struct request_queue *, struct request *, int, void *); extern void blk_requeue_request(struct request_queue *, struct request *); extern void blk_plug_device(struct request_queue *); +extern void blk_plug_device_unlocked(struct request_queue *); extern int blk_remove_plug(struct request_queue *); extern void blk_recount_segments(struct request_queue *, struct bio *); extern int scsi_cmd_ioctl(struct file *, struct request_queue *, -- cgit v1.3-18-gd494