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

Commit 86066201 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "block: Make del_gendisk() safer for disks without queues"

parents fc7e286c 340b5ba6
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -582,8 +582,6 @@ void blk_cleanup_queue(struct request_queue *q)
		q->queue_lock = &q->__queue_lock;
	spin_unlock_irq(lock);

	bdi_unregister(q->backing_dev_info);

	/* @q is and will stay empty, shutdown and put */
	blk_put_queue(q);
}
+10 −1
Original line number Diff line number Diff line
@@ -660,7 +660,16 @@ void del_gendisk(struct gendisk *disk)
	disk->flags &= ~GENHD_FL_UP;

	sysfs_remove_link(&disk_to_dev(disk)->kobj, "bdi");
	if (disk->queue) {
		/*
		 * Unregister bdi before releasing device numbers (as they can
		 * get reused and we'd get clashes in sysfs).
		 */
		bdi_unregister(disk->queue->backing_dev_info);
		blk_unregister_queue(disk);
	} else {
		WARN_ON(1);
	}
	blk_unregister_region(disk_devt(disk), disk->minors);

	part_stat_set_all(&disk->part0, 0);
+28 −15
Original line number Diff line number Diff line
@@ -682,33 +682,26 @@ static int cgwb_bdi_init(struct backing_dev_info *bdi)
static void cgwb_bdi_destroy(struct backing_dev_info *bdi)
{
	struct radix_tree_iter iter;
	struct rb_node *rbn;
	void **slot;

	WARN_ON(test_bit(WB_registered, &bdi->wb.state));

	spin_lock_irq(&cgwb_lock);

	radix_tree_for_each_slot(slot, &bdi->cgwb_tree, &iter, 0)
		cgwb_kill(*slot);

	while ((rbn = rb_first(&bdi->cgwb_congested_tree))) {
		struct bdi_writeback_congested *congested =
			rb_entry(rbn, struct bdi_writeback_congested, rb_node);

		rb_erase(rbn, &bdi->cgwb_congested_tree);
		congested->bdi = NULL;	/* mark @congested unlinked */
	}

	spin_unlock_irq(&cgwb_lock);

	/*
	 * All cgwb's and their congested states must be shutdown and
	 * released before returning.  Drain the usage counter to wait for
	 * all cgwb's and cgwb_congested's ever created on @bdi.
	 * All cgwb's must be shutdown and released before returning.  Drain
	 * the usage counter to wait for all cgwb's ever created on @bdi.
	 */
	atomic_dec(&bdi->usage_cnt);
	wait_event(cgwb_release_wait, !atomic_read(&bdi->usage_cnt));
	/*
	 * Grab back our reference so that we hold it when @bdi gets
	 * re-registered.
	 */
	atomic_inc(&bdi->usage_cnt);
}

/**
@@ -748,6 +741,21 @@ void wb_blkcg_offline(struct blkcg *blkcg)
	spin_unlock_irq(&cgwb_lock);
}

static void cgwb_bdi_exit(struct backing_dev_info *bdi)
{
	struct rb_node *rbn;

	spin_lock_irq(&cgwb_lock);
	while ((rbn = rb_first(&bdi->cgwb_congested_tree))) {
		struct bdi_writeback_congested *congested =
			rb_entry(rbn, struct bdi_writeback_congested, rb_node);

		rb_erase(rbn, &bdi->cgwb_congested_tree);
		congested->bdi = NULL;	/* mark @congested unlinked */
	}
	spin_unlock_irq(&cgwb_lock);
}

#else	/* CONFIG_CGROUP_WRITEBACK */

static int cgwb_bdi_init(struct backing_dev_info *bdi)
@@ -768,7 +776,9 @@ static int cgwb_bdi_init(struct backing_dev_info *bdi)
	return 0;
}

static void cgwb_bdi_destroy(struct backing_dev_info *bdi)
static void cgwb_bdi_destroy(struct backing_dev_info *bdi) { }

static void cgwb_bdi_exit(struct backing_dev_info *bdi)
{
	wb_congested_put(bdi->wb_congested);
}
@@ -856,6 +866,8 @@ int bdi_register_owner(struct backing_dev_info *bdi, struct device *owner)
			MINOR(owner->devt));
	if (rc)
		return rc;
	/* Leaking owner reference... */
	WARN_ON(bdi->owner);
	bdi->owner = owner;
	get_device(owner);
	return 0;
@@ -897,6 +909,7 @@ static void bdi_exit(struct backing_dev_info *bdi)
{
	WARN_ON_ONCE(bdi->dev);
	wb_exit(&bdi->wb);
	cgwb_bdi_exit(bdi);
}

static void release_bdi(struct kref *ref)