Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 761ab766 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-linus' of git://git.kernel.dk/linux-block

Pull block fixes from Jens Axboe:
 "A collection of fixes from the last few weeks that should go into the
  current series.  This contains:

   - Various fixes for the per-blkcg policy data, fixing regressions
     since 4.1.  From Arianna and Tejun

   - Code cleanup for bcache closure macros from me.  Really just
     flushing this out, it's been sitting in another branch for months

   - FIELD_SIZEOF cleanup from Maninder Singh

   - bio integrity oops fix from Mike

   - Timeout regression fix for blk-mq from Ming Lei"

* 'for-linus' of git://git.kernel.dk/linux-block:
  blk-mq: set default timeout as 30 seconds
  NVMe: Reread partitions on metadata formats
  bcache: don't embed 'return' statements in closure macros
  blkcg: fix blkcg_policy_data allocation bug
  blkcg: implement all_blkcgs list
  blkcg: blkcg_css_alloc() should grab blkcg_pol_mutex while iterating blkcg_policy[]
  blkcg: allow blkcg_pol_mutex to be grabbed from cgroup [file] methods
  block/blk-cgroup.c: free per-blkcg data when freeing the blkcg
  block: use FIELD_SIZEOF to calculate size of a field
  bio integrity: do not assume bio_integrity_pool exists if bioset exists
parents f76d94de e56f698b
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -51,7 +51,7 @@ struct bio_integrity_payload *bio_integrity_alloc(struct bio *bio,
	unsigned long idx = BIO_POOL_NONE;
	unsigned long idx = BIO_POOL_NONE;
	unsigned inline_vecs;
	unsigned inline_vecs;


	if (!bs) {
	if (!bs || !bs->bio_integrity_pool) {
		bip = kmalloc(sizeof(struct bio_integrity_payload) +
		bip = kmalloc(sizeof(struct bio_integrity_payload) +
			      sizeof(struct bio_vec) * nr_vecs, gfp_mask);
			      sizeof(struct bio_vec) * nr_vecs, gfp_mask);
		inline_vecs = nr_vecs;
		inline_vecs = nr_vecs;
@@ -104,7 +104,7 @@ void bio_integrity_free(struct bio *bio)
		kfree(page_address(bip->bip_vec->bv_page) +
		kfree(page_address(bip->bip_vec->bv_page) +
		      bip->bip_vec->bv_offset);
		      bip->bip_vec->bv_offset);


	if (bs) {
	if (bs && bs->bio_integrity_pool) {
		if (bip->bip_slab != BIO_POOL_NONE)
		if (bip->bip_slab != BIO_POOL_NONE)
			bvec_free(bs->bvec_integrity_pool, bip->bip_vec,
			bvec_free(bs->bvec_integrity_pool, bip->bip_vec,
				  bip->bip_slab);
				  bip->bip_slab);
+81 −59
Original line number Original line Diff line number Diff line
@@ -29,6 +29,14 @@


#define MAX_KEY_LEN 100
#define MAX_KEY_LEN 100


/*
 * blkcg_pol_mutex protects blkcg_policy[] and policy [de]activation.
 * blkcg_pol_register_mutex nests outside of it and synchronizes entire
 * policy [un]register operations including cgroup file additions /
 * removals.  Putting cgroup file registration outside blkcg_pol_mutex
 * allows grabbing it from cgroup callbacks.
 */
static DEFINE_MUTEX(blkcg_pol_register_mutex);
static DEFINE_MUTEX(blkcg_pol_mutex);
static DEFINE_MUTEX(blkcg_pol_mutex);


struct blkcg blkcg_root;
struct blkcg blkcg_root;
@@ -38,6 +46,8 @@ struct cgroup_subsys_state * const blkcg_root_css = &blkcg_root.css;


static struct blkcg_policy *blkcg_policy[BLKCG_MAX_POLS];
static struct blkcg_policy *blkcg_policy[BLKCG_MAX_POLS];


static LIST_HEAD(all_blkcgs);		/* protected by blkcg_pol_mutex */

static bool blkcg_policy_enabled(struct request_queue *q,
static bool blkcg_policy_enabled(struct request_queue *q,
				 const struct blkcg_policy *pol)
				 const struct blkcg_policy *pol)
{
{
@@ -453,20 +463,7 @@ static int blkcg_reset_stats(struct cgroup_subsys_state *css,
	struct blkcg_gq *blkg;
	struct blkcg_gq *blkg;
	int i;
	int i;


	/*
	mutex_lock(&blkcg_pol_mutex);
	 * XXX: We invoke cgroup_add/rm_cftypes() under blkcg_pol_mutex
	 * which ends up putting cgroup's internal cgroup_tree_mutex under
	 * it; however, cgroup_tree_mutex is nested above cgroup file
	 * active protection and grabbing blkcg_pol_mutex from a cgroup
	 * file operation creates a possible circular dependency.  cgroup
	 * internal locking is planned to go through further simplification
	 * and this issue should go away soon.  For now, let's trylock
	 * blkcg_pol_mutex and restart the write on failure.
	 *
	 * http://lkml.kernel.org/g/5363C04B.4010400@oracle.com
	 */
	if (!mutex_trylock(&blkcg_pol_mutex))
		return restart_syscall();
	spin_lock_irq(&blkcg->lock);
	spin_lock_irq(&blkcg->lock);


	/*
	/*
@@ -822,9 +819,18 @@ static void blkcg_css_free(struct cgroup_subsys_state *css)
{
{
	struct blkcg *blkcg = css_to_blkcg(css);
	struct blkcg *blkcg = css_to_blkcg(css);


	if (blkcg != &blkcg_root)
	mutex_lock(&blkcg_pol_mutex);
	list_del(&blkcg->all_blkcgs_node);
	mutex_unlock(&blkcg_pol_mutex);

	if (blkcg != &blkcg_root) {
		int i;

		for (i = 0; i < BLKCG_MAX_POLS; i++)
			kfree(blkcg->pd[i]);
		kfree(blkcg);
		kfree(blkcg);
	}
	}
}


static struct cgroup_subsys_state *
static struct cgroup_subsys_state *
blkcg_css_alloc(struct cgroup_subsys_state *parent_css)
blkcg_css_alloc(struct cgroup_subsys_state *parent_css)
@@ -833,6 +839,8 @@ blkcg_css_alloc(struct cgroup_subsys_state *parent_css)
	struct cgroup_subsys_state *ret;
	struct cgroup_subsys_state *ret;
	int i;
	int i;


	mutex_lock(&blkcg_pol_mutex);

	if (!parent_css) {
	if (!parent_css) {
		blkcg = &blkcg_root;
		blkcg = &blkcg_root;
		goto done;
		goto done;
@@ -875,14 +883,17 @@ blkcg_css_alloc(struct cgroup_subsys_state *parent_css)
#ifdef CONFIG_CGROUP_WRITEBACK
#ifdef CONFIG_CGROUP_WRITEBACK
	INIT_LIST_HEAD(&blkcg->cgwb_list);
	INIT_LIST_HEAD(&blkcg->cgwb_list);
#endif
#endif
	list_add_tail(&blkcg->all_blkcgs_node, &all_blkcgs);

	mutex_unlock(&blkcg_pol_mutex);
	return &blkcg->css;
	return &blkcg->css;


free_pd_blkcg:
free_pd_blkcg:
	for (i--; i >= 0; i--)
	for (i--; i >= 0; i--)
		kfree(blkcg->pd[i]);
		kfree(blkcg->pd[i]);

free_blkcg:
free_blkcg:
	kfree(blkcg);
	kfree(blkcg);
	mutex_unlock(&blkcg_pol_mutex);
	return ret;
	return ret;
}
}


@@ -1037,10 +1048,8 @@ int blkcg_activate_policy(struct request_queue *q,
			  const struct blkcg_policy *pol)
			  const struct blkcg_policy *pol)
{
{
	LIST_HEAD(pds);
	LIST_HEAD(pds);
	LIST_HEAD(cpds);
	struct blkcg_gq *blkg;
	struct blkcg_gq *blkg;
	struct blkg_policy_data *pd, *nd;
	struct blkg_policy_data *pd, *nd;
	struct blkcg_policy_data *cpd, *cnd;
	int cnt = 0, ret;
	int cnt = 0, ret;


	if (blkcg_policy_enabled(q, pol))
	if (blkcg_policy_enabled(q, pol))
@@ -1053,10 +1062,7 @@ int blkcg_activate_policy(struct request_queue *q,
		cnt++;
		cnt++;
	spin_unlock_irq(q->queue_lock);
	spin_unlock_irq(q->queue_lock);


	/*
	/* allocate per-blkg policy data for all existing blkgs */
	 * Allocate per-blkg and per-blkcg policy data
	 * for all existing blkgs.
	 */
	while (cnt--) {
	while (cnt--) {
		pd = kzalloc_node(pol->pd_size, GFP_KERNEL, q->node);
		pd = kzalloc_node(pol->pd_size, GFP_KERNEL, q->node);
		if (!pd) {
		if (!pd) {
@@ -1064,15 +1070,6 @@ int blkcg_activate_policy(struct request_queue *q,
			goto out_free;
			goto out_free;
		}
		}
		list_add_tail(&pd->alloc_node, &pds);
		list_add_tail(&pd->alloc_node, &pds);

		if (!pol->cpd_size)
			continue;
		cpd = kzalloc_node(pol->cpd_size, GFP_KERNEL, q->node);
		if (!cpd) {
			ret = -ENOMEM;
			goto out_free;
		}
		list_add_tail(&cpd->alloc_node, &cpds);
	}
	}


	/*
	/*
@@ -1082,32 +1079,17 @@ int blkcg_activate_policy(struct request_queue *q,
	spin_lock_irq(q->queue_lock);
	spin_lock_irq(q->queue_lock);


	list_for_each_entry(blkg, &q->blkg_list, q_node) {
	list_for_each_entry(blkg, &q->blkg_list, q_node) {
		if (WARN_ON(list_empty(&pds)) ||
		if (WARN_ON(list_empty(&pds))) {
		    WARN_ON(pol->cpd_size && list_empty(&cpds))) {
			/* umm... this shouldn't happen, just abort */
			/* umm... this shouldn't happen, just abort */
			ret = -ENOMEM;
			ret = -ENOMEM;
			goto out_unlock;
			goto out_unlock;
		}
		}
		cpd = list_first_entry(&cpds, struct blkcg_policy_data,
				       alloc_node);
		list_del_init(&cpd->alloc_node);
		pd = list_first_entry(&pds, struct blkg_policy_data, alloc_node);
		pd = list_first_entry(&pds, struct blkg_policy_data, alloc_node);
		list_del_init(&pd->alloc_node);
		list_del_init(&pd->alloc_node);


		/* grab blkcg lock too while installing @pd on @blkg */
		/* grab blkcg lock too while installing @pd on @blkg */
		spin_lock(&blkg->blkcg->lock);
		spin_lock(&blkg->blkcg->lock);


		if (!pol->cpd_size)
			goto no_cpd;
		if (!blkg->blkcg->pd[pol->plid]) {
			/* Per-policy per-blkcg data */
			blkg->blkcg->pd[pol->plid] = cpd;
			cpd->plid = pol->plid;
			pol->cpd_init_fn(blkg->blkcg);
		} else { /* must free it as it has already been extracted */
			kfree(cpd);
		}
no_cpd:
		blkg->pd[pol->plid] = pd;
		blkg->pd[pol->plid] = pd;
		pd->blkg = blkg;
		pd->blkg = blkg;
		pd->plid = pol->plid;
		pd->plid = pol->plid;
@@ -1124,8 +1106,6 @@ int blkcg_activate_policy(struct request_queue *q,
	blk_queue_bypass_end(q);
	blk_queue_bypass_end(q);
	list_for_each_entry_safe(pd, nd, &pds, alloc_node)
	list_for_each_entry_safe(pd, nd, &pds, alloc_node)
		kfree(pd);
		kfree(pd);
	list_for_each_entry_safe(cpd, cnd, &cpds, alloc_node)
		kfree(cpd);
	return ret;
	return ret;
}
}
EXPORT_SYMBOL_GPL(blkcg_activate_policy);
EXPORT_SYMBOL_GPL(blkcg_activate_policy);
@@ -1162,8 +1142,6 @@ void blkcg_deactivate_policy(struct request_queue *q,


		kfree(blkg->pd[pol->plid]);
		kfree(blkg->pd[pol->plid]);
		blkg->pd[pol->plid] = NULL;
		blkg->pd[pol->plid] = NULL;
		kfree(blkg->blkcg->pd[pol->plid]);
		blkg->blkcg->pd[pol->plid] = NULL;


		spin_unlock(&blkg->blkcg->lock);
		spin_unlock(&blkg->blkcg->lock);
	}
	}
@@ -1182,11 +1160,13 @@ EXPORT_SYMBOL_GPL(blkcg_deactivate_policy);
 */
 */
int blkcg_policy_register(struct blkcg_policy *pol)
int blkcg_policy_register(struct blkcg_policy *pol)
{
{
	struct blkcg *blkcg;
	int i, ret;
	int i, ret;


	if (WARN_ON(pol->pd_size < sizeof(struct blkg_policy_data)))
	if (WARN_ON(pol->pd_size < sizeof(struct blkg_policy_data)))
		return -EINVAL;
		return -EINVAL;


	mutex_lock(&blkcg_pol_register_mutex);
	mutex_lock(&blkcg_pol_mutex);
	mutex_lock(&blkcg_pol_mutex);


	/* find an empty slot */
	/* find an empty slot */
@@ -1195,19 +1175,49 @@ int blkcg_policy_register(struct blkcg_policy *pol)
		if (!blkcg_policy[i])
		if (!blkcg_policy[i])
			break;
			break;
	if (i >= BLKCG_MAX_POLS)
	if (i >= BLKCG_MAX_POLS)
		goto out_unlock;
		goto err_unlock;


	/* register and update blkgs */
	/* register @pol */
	pol->plid = i;
	pol->plid = i;
	blkcg_policy[i] = pol;
	blkcg_policy[pol->plid] = pol;

	/* allocate and install cpd's */
	if (pol->cpd_size) {
		list_for_each_entry(blkcg, &all_blkcgs, all_blkcgs_node) {
			struct blkcg_policy_data *cpd;

			cpd = kzalloc(pol->cpd_size, GFP_KERNEL);
			if (!cpd) {
				mutex_unlock(&blkcg_pol_mutex);
				goto err_free_cpds;
			}

			blkcg->pd[pol->plid] = cpd;
			cpd->plid = pol->plid;
			pol->cpd_init_fn(blkcg);
		}
	}

	mutex_unlock(&blkcg_pol_mutex);


	/* everything is in place, add intf files for the new policy */
	/* everything is in place, add intf files for the new policy */
	if (pol->cftypes)
	if (pol->cftypes)
		WARN_ON(cgroup_add_legacy_cftypes(&blkio_cgrp_subsys,
		WARN_ON(cgroup_add_legacy_cftypes(&blkio_cgrp_subsys,
						  pol->cftypes));
						  pol->cftypes));
	ret = 0;
	mutex_unlock(&blkcg_pol_register_mutex);
out_unlock:
	return 0;

err_free_cpds:
	if (pol->cpd_size) {
		list_for_each_entry(blkcg, &all_blkcgs, all_blkcgs_node) {
			kfree(blkcg->pd[pol->plid]);
			blkcg->pd[pol->plid] = NULL;
		}
	}
	blkcg_policy[pol->plid] = NULL;
err_unlock:
	mutex_unlock(&blkcg_pol_mutex);
	mutex_unlock(&blkcg_pol_mutex);
	mutex_unlock(&blkcg_pol_register_mutex);
	return ret;
	return ret;
}
}
EXPORT_SYMBOL_GPL(blkcg_policy_register);
EXPORT_SYMBOL_GPL(blkcg_policy_register);
@@ -1220,7 +1230,9 @@ EXPORT_SYMBOL_GPL(blkcg_policy_register);
 */
 */
void blkcg_policy_unregister(struct blkcg_policy *pol)
void blkcg_policy_unregister(struct blkcg_policy *pol)
{
{
	mutex_lock(&blkcg_pol_mutex);
	struct blkcg *blkcg;

	mutex_lock(&blkcg_pol_register_mutex);


	if (WARN_ON(blkcg_policy[pol->plid] != pol))
	if (WARN_ON(blkcg_policy[pol->plid] != pol))
		goto out_unlock;
		goto out_unlock;
@@ -1229,9 +1241,19 @@ void blkcg_policy_unregister(struct blkcg_policy *pol)
	if (pol->cftypes)
	if (pol->cftypes)
		cgroup_rm_cftypes(pol->cftypes);
		cgroup_rm_cftypes(pol->cftypes);


	/* unregister and update blkgs */
	/* remove cpds and unregister */
	mutex_lock(&blkcg_pol_mutex);

	if (pol->cpd_size) {
		list_for_each_entry(blkcg, &all_blkcgs, all_blkcgs_node) {
			kfree(blkcg->pd[pol->plid]);
			blkcg->pd[pol->plid] = NULL;
		}
	}
	blkcg_policy[pol->plid] = NULL;
	blkcg_policy[pol->plid] = NULL;
out_unlock:

	mutex_unlock(&blkcg_pol_mutex);
	mutex_unlock(&blkcg_pol_mutex);
out_unlock:
	mutex_unlock(&blkcg_pol_register_mutex);
}
}
EXPORT_SYMBOL_GPL(blkcg_policy_unregister);
EXPORT_SYMBOL_GPL(blkcg_policy_unregister);
+1 −1
Original line number Original line Diff line number Diff line
@@ -3370,7 +3370,7 @@ EXPORT_SYMBOL(blk_post_runtime_resume);
int __init blk_dev_init(void)
int __init blk_dev_init(void)
{
{
	BUILD_BUG_ON(__REQ_NR_BITS > 8 *
	BUILD_BUG_ON(__REQ_NR_BITS > 8 *
			sizeof(((struct request *)0)->cmd_flags));
			FIELD_SIZEOF(struct request, cmd_flags));


	/* used for unplugging and affects IO latency/throughput - HIGHPRI */
	/* used for unplugging and affects IO latency/throughput - HIGHPRI */
	kblockd_workqueue = alloc_workqueue("kblockd",
	kblockd_workqueue = alloc_workqueue("kblockd",
+1 −1
Original line number Original line Diff line number Diff line
@@ -1998,7 +1998,7 @@ struct request_queue *blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
		goto err_hctxs;
		goto err_hctxs;


	setup_timer(&q->timeout, blk_mq_rq_timer, (unsigned long) q);
	setup_timer(&q->timeout, blk_mq_rq_timer, (unsigned long) q);
	blk_queue_rq_timeout(q, set->timeout ? set->timeout : 30000);
	blk_queue_rq_timeout(q, set->timeout ? set->timeout : 30 * HZ);


	q->nr_queues = nr_cpu_ids;
	q->nr_queues = nr_cpu_ids;
	q->nr_hw_queues = set->nr_hw_queues;
	q->nr_hw_queues = set->nr_hw_queues;
+11 −2
Original line number Original line Diff line number Diff line
@@ -2108,8 +2108,17 @@ static void nvme_alloc_ns(struct nvme_dev *dev, unsigned nsid)
		goto out_free_disk;
		goto out_free_disk;


	add_disk(ns->disk);
	add_disk(ns->disk);
	if (ns->ms)
	if (ns->ms) {
		revalidate_disk(ns->disk);
		struct block_device *bd = bdget_disk(ns->disk, 0);
		if (!bd)
			return;
		if (blkdev_get(bd, FMODE_READ, NULL)) {
			bdput(bd);
			return;
		}
		blkdev_reread_part(bd);
		blkdev_put(bd, FMODE_READ);
	}
	return;
	return;
 out_free_disk:
 out_free_disk:
	kfree(disk);
	kfree(disk);
Loading