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

Commit ea1ee5ff authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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

Pull block layer fixes from Jens Axboe:
 "A final set of fixes for 4.3.

  It is (again) bigger than I would have liked, but it's all been
  through the testing mill and has been carefully reviewed by multiple
  parties.  Each fix is either a regression fix for this cycle, or is
  marked stable.  You can scold me at KS.  The pull request contains:

   - Three simple fixes for NVMe, fixing regressions since 4.3.  From
     Arnd, Christoph, and Keith.

   - A single xen-blkfront fix from Cathy, fixing a NULL dereference if
     an error is returned through the staste change callback.

   - Fixup for some bad/sloppy code in nbd that got introduced earlier
     in this cycle.  From Markus Pargmann.

   - A blk-mq tagset use-after-free fix from Junichi.

   - A backing device lifetime fix from Tejun, fixing a crash.

   - And finally, a set of regression/stable fixes for cgroup writeback
     from Tejun"

* 'for-linus' of git://git.kernel.dk/linux-block:
  writeback: remove broken rbtree_postorder_for_each_entry_safe() usage in cgwb_bdi_destroy()
  NVMe: Fix memory leak on retried commands
  block: don't release bdi while request_queue has live references
  nvme: use an integer value to Linux errno values
  blk-mq: fix use-after-free in blk_mq_free_tag_set()
  nvme: fix 32-bit build warning
  writeback: fix incorrect calculation of available memory for memcg domains
  writeback: memcg dirty_throttle_control should be initialized with wb->memcg_completions
  writeback: bdi_writeback iteration must not skip dying ones
  writeback: fix bdi_writeback iteration in wakeup_dirtytime_writeback()
  writeback: laptop_mode_timer_fn() needs rcu_read_lock() around bdi_writeback iteration
  nbd: Add locking for tasks
  xen-blkfront: check for null drvdata in blkback_changed (XenbusStateClosing)
parents ef594c42 e27c5b9d
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -576,7 +576,7 @@ void blk_cleanup_queue(struct request_queue *q)
		q->queue_lock = &q->__queue_lock;
		q->queue_lock = &q->__queue_lock;
	spin_unlock_irq(lock);
	spin_unlock_irq(lock);


	bdi_destroy(&q->backing_dev_info);
	bdi_unregister(&q->backing_dev_info);


	/* @q is and will stay empty, shutdown and put */
	/* @q is and will stay empty, shutdown and put */
	blk_put_queue(q);
	blk_put_queue(q);
+1 −0
Original line number Original line Diff line number Diff line
@@ -641,6 +641,7 @@ void blk_mq_free_tags(struct blk_mq_tags *tags)
{
{
	bt_free(&tags->bitmap_tags);
	bt_free(&tags->bitmap_tags);
	bt_free(&tags->breserved_tags);
	bt_free(&tags->breserved_tags);
	free_cpumask_var(tags->cpumask);
	kfree(tags);
	kfree(tags);
}
}


+1 −3
Original line number Original line Diff line number Diff line
@@ -2296,10 +2296,8 @@ void blk_mq_free_tag_set(struct blk_mq_tag_set *set)
	int i;
	int i;


	for (i = 0; i < set->nr_hw_queues; i++) {
	for (i = 0; i < set->nr_hw_queues; i++) {
		if (set->tags[i]) {
		if (set->tags[i])
			blk_mq_free_rq_map(set, set->tags[i], i);
			blk_mq_free_rq_map(set, set->tags[i], i);
			free_cpumask_var(set->tags[i]->cpumask);
		}
	}
	}


	kfree(set->tags);
	kfree(set->tags);
+1 −0
Original line number Original line Diff line number Diff line
@@ -540,6 +540,7 @@ static void blk_release_queue(struct kobject *kobj)
	struct request_queue *q =
	struct request_queue *q =
		container_of(kobj, struct request_queue, kobj);
		container_of(kobj, struct request_queue, kobj);


	bdi_exit(&q->backing_dev_info);
	blkcg_exit_queue(q);
	blkcg_exit_queue(q);


	if (q->elevator) {
	if (q->elevator) {
+30 −6
Original line number Original line Diff line number Diff line
@@ -60,6 +60,7 @@ struct nbd_device {
	bool disconnect; /* a disconnect has been requested by user */
	bool disconnect; /* a disconnect has been requested by user */


	struct timer_list timeout_timer;
	struct timer_list timeout_timer;
	spinlock_t tasks_lock;
	struct task_struct *task_recv;
	struct task_struct *task_recv;
	struct task_struct *task_send;
	struct task_struct *task_send;


@@ -140,21 +141,23 @@ static void sock_shutdown(struct nbd_device *nbd)
static void nbd_xmit_timeout(unsigned long arg)
static void nbd_xmit_timeout(unsigned long arg)
{
{
	struct nbd_device *nbd = (struct nbd_device *)arg;
	struct nbd_device *nbd = (struct nbd_device *)arg;
	struct task_struct *task;
	unsigned long flags;


	if (list_empty(&nbd->queue_head))
	if (list_empty(&nbd->queue_head))
		return;
		return;


	nbd->disconnect = true;
	nbd->disconnect = true;


	task = READ_ONCE(nbd->task_recv);
	spin_lock_irqsave(&nbd->tasks_lock, flags);
	if (task)

		force_sig(SIGKILL, task);
	if (nbd->task_recv)
		force_sig(SIGKILL, nbd->task_recv);


	task = READ_ONCE(nbd->task_send);
	if (nbd->task_send)
	if (task)
		force_sig(SIGKILL, nbd->task_send);
		force_sig(SIGKILL, nbd->task_send);


	spin_unlock_irqrestore(&nbd->tasks_lock, flags);

	dev_err(nbd_to_dev(nbd), "Connection timed out, killed receiver and sender, shutting down connection\n");
	dev_err(nbd_to_dev(nbd), "Connection timed out, killed receiver and sender, shutting down connection\n");
}
}


@@ -403,17 +406,24 @@ static int nbd_thread_recv(struct nbd_device *nbd)
{
{
	struct request *req;
	struct request *req;
	int ret;
	int ret;
	unsigned long flags;


	BUG_ON(nbd->magic != NBD_MAGIC);
	BUG_ON(nbd->magic != NBD_MAGIC);


	sk_set_memalloc(nbd->sock->sk);
	sk_set_memalloc(nbd->sock->sk);


	spin_lock_irqsave(&nbd->tasks_lock, flags);
	nbd->task_recv = current;
	nbd->task_recv = current;
	spin_unlock_irqrestore(&nbd->tasks_lock, flags);


	ret = device_create_file(disk_to_dev(nbd->disk), &pid_attr);
	ret = device_create_file(disk_to_dev(nbd->disk), &pid_attr);
	if (ret) {
	if (ret) {
		dev_err(disk_to_dev(nbd->disk), "device_create_file failed!\n");
		dev_err(disk_to_dev(nbd->disk), "device_create_file failed!\n");

		spin_lock_irqsave(&nbd->tasks_lock, flags);
		nbd->task_recv = NULL;
		nbd->task_recv = NULL;
		spin_unlock_irqrestore(&nbd->tasks_lock, flags);

		return ret;
		return ret;
	}
	}


@@ -429,7 +439,9 @@ static int nbd_thread_recv(struct nbd_device *nbd)


	device_remove_file(disk_to_dev(nbd->disk), &pid_attr);
	device_remove_file(disk_to_dev(nbd->disk), &pid_attr);


	spin_lock_irqsave(&nbd->tasks_lock, flags);
	nbd->task_recv = NULL;
	nbd->task_recv = NULL;
	spin_unlock_irqrestore(&nbd->tasks_lock, flags);


	if (signal_pending(current)) {
	if (signal_pending(current)) {
		siginfo_t info;
		siginfo_t info;
@@ -534,8 +546,11 @@ static int nbd_thread_send(void *data)
{
{
	struct nbd_device *nbd = data;
	struct nbd_device *nbd = data;
	struct request *req;
	struct request *req;
	unsigned long flags;


	spin_lock_irqsave(&nbd->tasks_lock, flags);
	nbd->task_send = current;
	nbd->task_send = current;
	spin_unlock_irqrestore(&nbd->tasks_lock, flags);


	set_user_nice(current, MIN_NICE);
	set_user_nice(current, MIN_NICE);
	while (!kthread_should_stop() || !list_empty(&nbd->waiting_queue)) {
	while (!kthread_should_stop() || !list_empty(&nbd->waiting_queue)) {
@@ -572,7 +587,15 @@ static int nbd_thread_send(void *data)
		nbd_handle_req(nbd, req);
		nbd_handle_req(nbd, req);
	}
	}


	spin_lock_irqsave(&nbd->tasks_lock, flags);
	nbd->task_send = NULL;
	nbd->task_send = NULL;
	spin_unlock_irqrestore(&nbd->tasks_lock, flags);

	/* Clear maybe pending signals */
	if (signal_pending(current)) {
		siginfo_t info;
		dequeue_signal_lock(current, &current->blocked, &info);
	}


	return 0;
	return 0;
}
}
@@ -1052,6 +1075,7 @@ static int __init nbd_init(void)
		nbd_dev[i].magic = NBD_MAGIC;
		nbd_dev[i].magic = NBD_MAGIC;
		INIT_LIST_HEAD(&nbd_dev[i].waiting_queue);
		INIT_LIST_HEAD(&nbd_dev[i].waiting_queue);
		spin_lock_init(&nbd_dev[i].queue_lock);
		spin_lock_init(&nbd_dev[i].queue_lock);
		spin_lock_init(&nbd_dev[i].tasks_lock);
		INIT_LIST_HEAD(&nbd_dev[i].queue_head);
		INIT_LIST_HEAD(&nbd_dev[i].queue_head);
		mutex_init(&nbd_dev[i].tx_lock);
		mutex_init(&nbd_dev[i].tx_lock);
		init_timer(&nbd_dev[i].timeout_timer);
		init_timer(&nbd_dev[i].timeout_timer);
Loading