block fixes for 2.6.36-rc5
Subsystems (5)
Hi Linus,
A small batch of fixes. Two important fixes, correcting a bug in the unified request/bio command flags causing blk_rq_map_kern() to flag writes incorrectly, and the oops in CFQ with cgroups and a usb key. The small 3-patch series from Jan fixes a long standing regression dating back to 2.6.32.
Please pull.
git://git.kernel.dk/linux-2.6-block.git for-linus
Benny Halevy (1):
block: fix blk_rq_map_kern bio direction flag
Dan Carpenter (1):
cciss: freeing uninitialized data on error path
Jan Kara (3):
bdi: Initialize noop_backing_dev_info properly
char: Mark /dev/zero and /dev/kmem as not capable of writeback
bdi: Fix warnings in __mark_inode_dirty for /dev/zero and friends
Vivek Goyal (1):
cfq-iosched: fix a kernel OOPs when usb key is inserted
block/blk-map.c | 2 +- block/cfq-iosched.c | 16 +++++++++++++--- drivers/block/cciss.c | 2 +- drivers/char/mem.c | 3 ++- fs/char_dev.c | 4 +++- fs/fs-writeback.c | 23 +++++++++++++++++++++-- mm/backing-dev.c | 2 ++ 7 files changed, 43 insertions(+), 9 deletions(-)
block/blk-map.c +1 -1
@@ -307,7 +307,7 @@ int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf,return PTR_ERR (bio);if (rq_data_dir (rq) ==WRITE ) - bio->bi_rw |= (1 <<REQ_WRITE ); + bio->bi_rw |=REQ_WRITE ;if (do_copy) rq->cmd_flags |=REQ_COPY_USER ;
block/cfq-iosched.c +13 -3
@@ -1019,10 +1019,20 @@ cfq_find_alloc_cfqg(struct cfq_data *cfqd, struct cgroup *cgroup, int create)*/ atomic_set (&cfqg->ref,1 ); -/* Add group onto cgroup list */ -sscanf (dev_name (bdi->dev),"%u:%u" , &major, &minor); -cfq_blkiocg_add_blkio_group (blkcg, &cfqg->blkg, (void *)cfqd, +/* +* Add group onto cgroup list. It might happen that bdi->dev is +* not initiliazed yet. Initialize this new group without major +* and minor info and this info will be filled in once a new thread +* comes for IO. See code above. +*/ +if (bdi->dev) { +sscanf (dev_name (bdi->dev),"%u:%u" , &major, &minor); +cfq_blkiocg_add_blkio_group (blkcg, &cfqg->blkg, (void *)cfqd,MKDEV (major, minor)); + }else +cfq_blkiocg_add_blkio_group (blkcg, &cfqg->blkg, (void *)cfqd, +0 ); + cfqg->weight =blkcg_get_weight (blkcg, cfqg->blkg.dev);/* Add group on cfqd list */
drivers/block/cciss.c +1 -1
@@ -4792,7 +4792,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, clean4:kfree (h->cmd_pool_bits);/* Free up sg elements */ -for (k =0 ; k < h->nr_cmds; k++) +for (k-- ; k >=0 ; k--)kfree (h->scatter_list[k]);kfree (h->scatter_list);cciss_free_sg_chain_blocks (h->cmd_sg_list, h->nr_cmds);
drivers/char/mem.c +2 -1
@@ -788,10 +788,11 @@ static const struct file_operations zero_fops = {/* * capabilities for /dev/zero * - permits private mappings, "copies" are taken of the source of zeros +* - no writeback happens */ static struct backing_dev_info zero_bdi = { .name ="char/mem" , - .capabilities =BDI_CAP_MAP_COPY , + .capabilities =BDI_CAP_MAP_COPY |BDI_CAP_NO_ACCT_AND_WRITEBACK , };static const struct file_operations full_fops = {
fs/char_dev.c +3 -1
@@ -40,7 +40,9 @@ struct backing_dev_info directly_mappable_cdev_bdi = {#endif /* permit direct mmap, for read, write or exec */ BDI_CAP_MAP_DIRECT | - BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP), +BDI_CAP_READ_MAP |BDI_CAP_WRITE_MAP |BDI_CAP_EXEC_MAP | +/* no writeback happens */ + BDI_CAP_NO_ACCT_AND_WRITEBACK), };static struct kobj_map *cdev_map;
fs/fs-writeback.c +21 -2
@@ -52,8 +52,6 @@ struct wb_writeback_work {#define CREATE_TRACE_POINTS #include <trace/events/writeback.h> -#define inode_to_bdi (inode) ((inode)->i_mapping->backing_dev_info) -/* * We don't actually have pdflush, but this one is exported though /proc... */
@@ -71,6 +69,27 @@ int writeback_in_progress(struct backing_dev_info *bdi)return test_bit (BDI_writeback_running, &bdi->state); } +static inline struct backing_dev_info *inode_to_bdi (struct inode *inode) +{ +struct super_block *sb = inode->i_sb; +struct backing_dev_info *bdi = inode->i_mapping->backing_dev_info; + +/* +* For inodes on standard filesystems, we use superblock's bdi. For +* inodes on virtual filesystems, we want to use inode mapping's bdi +* because they can possibly point to something useful (think about +* block_dev filesystem). +*/ +if (sb->s_bdi && sb->s_bdi != &noop_backing_dev_info) { +/* Some device inodes could play dirty tricks. Catch them... */ +WARN (bdi != sb->s_bdi &&bdi_cap_writeback_dirty (bdi), +"Dirtiable inode bdi %s != sb bdi %s\n" , + bdi->name, sb->s_bdi->name); +return sb->s_bdi; + } +return bdi; +} +static void bdi_queue_work (struct backing_dev_info *bdi,struct wb_writeback_work *work) {
mm/backing-dev.c +2 -0
@@ -30,6 +30,7 @@ EXPORT_SYMBOL_GPL(default_backing_dev_info);struct backing_dev_info noop_backing_dev_info = { .name ="noop" , + .capabilities =BDI_CAP_NO_ACCT_AND_WRITEBACK , };EXPORT_SYMBOL_GPL (noop_backing_dev_info);
@@ -243,6 +244,7 @@ static int __init default_bdi_init(void) err =bdi_init (&default_backing_dev_info);if (!err)bdi_register (&default_backing_dev_info,NULL ,"default" ); + err =bdi_init (&noop_backing_dev_info);return err; }
Signature · 1 line
Jens Axboe
Gaah. This is just _incredibly_ ugly:
Quoted 10 lines · Jens Axboe
- /* Add group onto cgroup list */
-sscanf(dev_name(bdi->dev), "%u:%u", &major, &minor);
- cfq_blkiocg_add_blkio_group(blkcg,&cfqg->blkg, (void *)cfqd,
+ /*
+ * Add group onto cgroup list. It might happen thatbdi->devis
+ * not initiliazed yet. Initialize this new group without major
+ * and minor info and this info will be filled in once a new thread
+ * comes for IO. See code above.
+ */
Quoted 8 lines
+ if (
bdi->dev) {
+sscanf(dev_name(bdi->dev), "%u:%u", &major, &minor);
+cfq_blkiocg_add_blkio_group(blkcg, &cfqg->blkg, (void *)cfqd, MKDEV(major, minor));
+ } else
+ cfq_blkiocg_add_blkio_group(blkcg,&cfqg->blkg, (void *)cfqd,
+ 0);
+
and quite frankly, anything that does that kind of thing is total sh*t. Not only is the sscanf() just broken (really? figuring out things from some internal string? Using dev_t in this time and age for kernel internal stuff?) to begin with, but if you have to then do it conditionally, for chrissake do it _cleanly_.
Make a small helper function that does "get me the dev_t of this 'dev'", and make that one do
static unsigned int device_dev_t(struct device *dev)
{
unsigned int major = 0, minor = 0; if (dev)
sscanf(dev_name(bdi->dev), "%u:%u", &major, &minor);
return MKDEV(major, minor);}
and then just have a single 'cfq_blkiocg_add_blkio_group()' there.
But more seriously, why the hell does anything internal to cfq use a 'dev_t' in the first place? Why isn't that 'struct blkio_group' using a pointer to the 'struct device' or something like that instead (or the pointer to the queue, or whatever)? It's just damn wrong to use dev_t in this day and age, and the fact that you need to make it up using sscanf() should have clued people into that fact.
I hate seeing obvious crap-workarounds this late in an -rc.
Linus
Quoted 43 lines · Linus Torvalds
Gaah. This is just _incredibly_ ugly:
Quoted 8 lines · Jens Axboe
block/cfq-iosched.c +4
-3-/* Add group onto cgroup list */ -sscanf (dev_name (bdi->dev),"%u:%u" , &major, &minor); - cfq_blkiocg_add_blkio_group(blkcg, &cfqg->blkg, (void *)cfqd, +/* +* Add group onto cgroup list. It might happen that bdi->dev is +* not initiliazed yet. Initialize this new group without major +* and minor info and this info will be filled in once a new thread block/cfq-iosched.c cfq_find_alloc_cfqg(struct cfq_data *cfqd, struct cgroup *cgroup, int create) · line 1035
Quoted 10 lines
block/cfq-iosched.c +9
-0+* comes for IO. See code above. +*/ +if (bdi->dev) { +sscanf (dev_name (bdi->dev),"%u:%u" , &major, &minor); +cfq_blkiocg_add_blkio_group (blkcg, &cfqg->blkg, (void *)cfqd,MKDEV (major, minor)); + }else +cfq_blkiocg_add_blkio_group (blkcg, &cfqg->blkg, (void *)cfqd, +0 ); +and quite frankly, anything that does that kind of thing is total sh*t. Not only is the
sscanf()just broken (really? figuring out things from some internal string? Usingdev_tin this time and age for kernel internal stuff?) to begin with, but if you have to then do it conditionally, for chrissake do it _cleanly_.Make a small helper function that does "get me the
dev_tof this 'dev'", and make that one dostatic unsigned int device_dev_t(struct device *dev) { unsigned int major = 0, minor = 0;if (dev) sscanf(dev_name(bdi->dev), "%u:%u", &major, &minor); return MKDEV(major, minor);}
and then just have a single '
cfq_blkiocg_add_blkio_group()' there.
Quoted 8 lines
But more seriously, why the hell does anything internal to cfq use a '
dev_t' in the first place? Why isn't that 'structblkio_group' using a pointer to the 'struct device' or something like that instead (or the pointer to the queue, or whatever)? It's just damn wrong to usedev_tin this day and age, and the fact that you need to make it up usingsscanf()should have clued people into that fact.I hate seeing obvious crap-workarounds this late in an -rc.
I don't think anybody will disagree. The major problem here is that we still have some drivers using multiple devices per queue, one of them will be gone for .37 at least and I hope we can get mtd blk converted too. When that happens, we can place a dev in the queue and get rid of this hack and similar hacks on double bdi etc registrations.
So we can put some makeup on the corpse like you describe, or we can just live with this until we can kill off abominations like this for 2.6.37.
Signature · 1 line
Jens Axboe