diff options
Diffstat (limited to 'block')
-rw-r--r-- | block/blk-core.c | 41 | ||||
-rw-r--r-- | block/blk-map.c | 7 | ||||
-rw-r--r-- | block/cfq-iosched.c | 16 | ||||
-rw-r--r-- | block/genhd.c | 71 |
4 files changed, 40 insertions, 95 deletions
diff --git a/block/blk-core.c b/block/blk-core.c index f43c8a5840ae..15de223c7f93 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -366,7 +366,14 @@ void blk_drain_queue(struct request_queue *q, bool drain_all) if (drain_all) blk_throtl_drain(q); - __blk_run_queue(q); + /* + * This function might be called on a queue which failed + * driver init after queue creation. Some drivers + * (e.g. fd) get unhappy in such cases. Kick queue iff + * dispatch queue has something on it. + */ + if (!list_empty(&q->queue_head)) + __blk_run_queue(q); if (drain_all) nr_rqs = q->rq.count[0] + q->rq.count[1]; @@ -467,6 +474,7 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) q->backing_dev_info.state = 0; q->backing_dev_info.capabilities = BDI_CAP_MAP_COPY; q->backing_dev_info.name = "block"; + q->node = node_id; err = bdi_init(&q->backing_dev_info); if (err) { @@ -551,7 +559,7 @@ blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id) if (!uninit_q) return NULL; - q = blk_init_allocated_queue_node(uninit_q, rfn, lock, node_id); + q = blk_init_allocated_queue(uninit_q, rfn, lock); if (!q) blk_cleanup_queue(uninit_q); @@ -563,18 +571,9 @@ struct request_queue * blk_init_allocated_queue(struct request_queue *q, request_fn_proc *rfn, spinlock_t *lock) { - return blk_init_allocated_queue_node(q, rfn, lock, -1); -} -EXPORT_SYMBOL(blk_init_allocated_queue); - -struct request_queue * -blk_init_allocated_queue_node(struct request_queue *q, request_fn_proc *rfn, - spinlock_t *lock, int node_id) -{ if (!q) return NULL; - q->node = node_id; if (blk_init_free_list(q)) return NULL; @@ -604,7 +603,7 @@ blk_init_allocated_queue_node(struct request_queue *q, request_fn_proc *rfn, return NULL; } -EXPORT_SYMBOL(blk_init_allocated_queue_node); +EXPORT_SYMBOL(blk_init_allocated_queue); int blk_get_queue(struct request_queue *q) { @@ -1379,15 +1378,19 @@ get_rq: */ if (list_empty(&plug->list)) trace_block_plug(q); - else if (!plug->should_sort) { - struct request *__rq; + else { + if (!plug->should_sort) { + struct request *__rq; - __rq = list_entry_rq(plug->list.prev); - if (__rq->q != q) - plug->should_sort = 1; + __rq = list_entry_rq(plug->list.prev); + if (__rq->q != q) + plug->should_sort = 1; + } + if (request_count >= BLK_MAX_REQUEST_COUNT) { + blk_flush_plug_list(plug, false); + trace_block_plug(q); + } } - if (request_count >= BLK_MAX_REQUEST_COUNT) - blk_flush_plug_list(plug, false); list_add_tail(&req->queuelist, &plug->list); drive_stat_acct(req, 1); } else { diff --git a/block/blk-map.c b/block/blk-map.c index e663ac2d8e68..164cd0059706 100644 --- a/block/blk-map.c +++ b/block/blk-map.c @@ -204,10 +204,11 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq, if (!iov[i].iov_len) return -EINVAL; - if (uaddr & queue_dma_alignment(q)) { + /* + * Keep going so we check length of all segments + */ + if (uaddr & queue_dma_alignment(q)) unaligned = 1; - break; - } } if (unaligned || (q->dma_pad_mask & len) || map_data) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 16ace89613bc..4c12869fcf77 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -3184,7 +3184,7 @@ static int cfq_cic_link(struct cfq_data *cfqd, struct io_context *ioc, } } - if (ret) + if (ret && ret != -EEXIST) printk(KERN_ERR "cfq: cic link failed!\n"); return ret; @@ -3200,6 +3200,7 @@ cfq_get_io_context(struct cfq_data *cfqd, gfp_t gfp_mask) { struct io_context *ioc = NULL; struct cfq_io_context *cic; + int ret; might_sleep_if(gfp_mask & __GFP_WAIT); @@ -3207,6 +3208,7 @@ cfq_get_io_context(struct cfq_data *cfqd, gfp_t gfp_mask) if (!ioc) return NULL; +retry: cic = cfq_cic_lookup(cfqd, ioc); if (cic) goto out; @@ -3215,7 +3217,12 @@ cfq_get_io_context(struct cfq_data *cfqd, gfp_t gfp_mask) if (cic == NULL) goto err; - if (cfq_cic_link(cfqd, ioc, cic, gfp_mask)) + ret = cfq_cic_link(cfqd, ioc, cic, gfp_mask); + if (ret == -EEXIST) { + /* someone has linked cic to ioc already */ + cfq_cic_free(cic); + goto retry; + } else if (ret) goto err_free; out: @@ -4036,6 +4043,11 @@ static void *cfq_init_queue(struct request_queue *q) if (blkio_alloc_blkg_stats(&cfqg->blkg)) { kfree(cfqg); + + spin_lock(&cic_index_lock); + ida_remove(&cic_index_ida, cfqd->cic_index); + spin_unlock(&cic_index_lock); + kfree(cfqd); return NULL; } diff --git a/block/genhd.c b/block/genhd.c index 9253839714ff..02e9fca80825 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -19,7 +19,6 @@ #include <linux/mutex.h> #include <linux/idr.h> #include <linux/log2.h> -#include <linux/ctype.h> #include "blk.h" @@ -916,74 +915,6 @@ static int __init genhd_device_init(void) subsys_initcall(genhd_device_init); -static ssize_t alias_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gendisk *disk = dev_to_disk(dev); - ssize_t ret = 0; - - if (disk->alias) - ret = snprintf(buf, ALIAS_LEN, "%s\n", disk->alias); - return ret; -} - -static ssize_t alias_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct gendisk *disk = dev_to_disk(dev); - char *alias; - char *envp[] = { NULL, NULL }; - unsigned char c; - int i; - ssize_t ret = count; - - if (!count) - return -EINVAL; - - if (count >= ALIAS_LEN) { - printk(KERN_ERR "alias: alias is too long\n"); - return -EINVAL; - } - - /* Validation check */ - for (i = 0; i < count; i++) { - c = buf[i]; - if (i == count - 1 && c == '\n') - break; - if (!isalnum(c) && c != '_' && c != '-') { - printk(KERN_ERR "alias: invalid alias\n"); - return -EINVAL; - } - } - - if (disk->alias) { - printk(KERN_INFO "alias: %s is already assigned (%s)\n", - disk->disk_name, disk->alias); - return -EINVAL; - } - - alias = kasprintf(GFP_KERNEL, "%s", buf); - if (!alias) - return -ENOMEM; - - if (alias[count - 1] == '\n') - alias[count - 1] = '\0'; - - envp[0] = kasprintf(GFP_KERNEL, "ALIAS=%s", alias); - if (!envp[0]) { - kfree(alias); - return -ENOMEM; - } - - disk->alias = alias; - printk(KERN_INFO "alias: assigned %s to %s\n", alias, disk->disk_name); - - kobject_uevent_env(&dev->kobj, KOBJ_ADD, envp); - - kfree(envp[0]); - return ret; -} - static ssize_t disk_range_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1043,7 +974,6 @@ static ssize_t disk_discard_alignment_show(struct device *dev, return sprintf(buf, "%d\n", queue_discard_alignment(disk->queue)); } -static DEVICE_ATTR(alias, S_IRUGO|S_IWUSR, alias_show, alias_store); static DEVICE_ATTR(range, S_IRUGO, disk_range_show, NULL); static DEVICE_ATTR(ext_range, S_IRUGO, disk_ext_range_show, NULL); static DEVICE_ATTR(removable, S_IRUGO, disk_removable_show, NULL); @@ -1066,7 +996,6 @@ static struct device_attribute dev_attr_fail_timeout = #endif static struct attribute *disk_attrs[] = { - &dev_attr_alias.attr, &dev_attr_range.attr, &dev_attr_ext_range.attr, &dev_attr_removable.attr, |