Linux block layer
 help / color / mirror / Atom feed
* Re: [PATCH v3] dm: don't allow ioctls to targets that don't map to whole devices
From: Bart Van Assche @ 2017-02-03 21:41 UTC (permalink / raw)
  To: hch@lst.de, jthumshirn@suse.de, snitzer@redhat.com
  Cc: agk@redhat.com, dm-devel@redhat.com, linux-block@vger.kernel.org,
	pbonzini@redhat.com, axboe@kernel.dk
In-Reply-To: <4435311b-80e1-8764-fa12-140203e9231f@suse.de>

On Fri, 2017-02-03 at 19:17 +0100, Johannes Thumshirn wrote:
> Forgotten git add? git commit --amend without git add is such a classic=20
> mistake on my side as well :-/

Are you familiar with the -a option of git commit? Just run

git commit -a --amend

Bart.=

^ permalink raw reply

* [PATCH] nbd: handle single path failures gracefully
From: Josef Bacik @ 2017-02-03 21:18 UTC (permalink / raw)
  To: linux-block, kernel-team, nbd-general

Currently if we have multiple connections and one of them goes down we will tear
down the whole device.  However there's no reason we need to do this as we
could have other connections that are working fine.  Deal with this by keeping
track of the state of the different connections, and if we lose one we mark it
as dead and send all IO destined for that socket to one of the other healthy
sockets.  Any outstanding requests that were on the dead socket will timeout and
be re-submitted properly.

Signed-off-by: Josef Bacik <jbacik@fb.com>
---
 drivers/block/nbd.c | 165 +++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 124 insertions(+), 41 deletions(-)

diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 0be84a3..164a548 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -47,6 +47,8 @@ static DEFINE_MUTEX(nbd_index_mutex);
 struct nbd_sock {
 	struct socket *sock;
 	struct mutex tx_lock;
+	bool dead;
+	int fallback_index;
 };
 
 #define NBD_TIMEDOUT			0
@@ -80,6 +82,7 @@ struct nbd_device {
 
 struct nbd_cmd {
 	struct nbd_device *nbd;
+	int index;
 	struct completion send_complete;
 };
 
@@ -193,7 +196,32 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req,
 	struct nbd_cmd *cmd = blk_mq_rq_to_pdu(req);
 	struct nbd_device *nbd = cmd->nbd;
 
-	dev_err(nbd_to_dev(nbd), "Connection timed out, shutting down connection\n");
+	if (nbd->num_connections > 1) {
+		dev_err_ratelimited(nbd_to_dev(nbd),
+				    "Connection timed out, retrying\n");
+		mutex_lock(&nbd->config_lock);
+		/*
+		 * Hooray we have more connections, requeue this IO, the submit
+		 * path will put it on a real connection.
+		 */
+		if (nbd->socks && nbd->num_connections > 1) {
+			if (cmd->index < nbd->num_connections) {
+				struct nbd_sock *nsock =
+					nbd->socks[cmd->index];
+				mutex_lock(&nsock->tx_lock);
+				nsock->dead = true;
+				kernel_sock_shutdown(nsock->sock, SHUT_RDWR);
+				mutex_unlock(&nsock->tx_lock);
+			}
+			mutex_unlock(&nbd->config_lock);
+			blk_mq_requeue_request(req, true);
+			return BLK_EH_RESET_TIMER;
+		}
+		mutex_unlock(&nbd->config_lock);
+	} else {
+		dev_err_ratelimited(nbd_to_dev(nbd),
+				    "Connection timed out\n");
+	}
 	set_bit(NBD_TIMEDOUT, &nbd->runtime_flags);
 	req->errors++;
 
@@ -299,6 +327,7 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
 		return -EIO;
 	}
 
+	cmd->index = index;
 	memset(&request, 0, sizeof(request));
 	request.magic = htonl(NBD_REQUEST_MAGIC);
 	request.type = htonl(type);
@@ -316,7 +345,7 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
 	if (result <= 0) {
 		dev_err_ratelimited(disk_to_dev(nbd->disk),
 			"Send control failed (result %d)\n", result);
-		return -EIO;
+		return -EAGAIN;
 	}
 
 	if (type != NBD_CMD_WRITE)
@@ -339,7 +368,7 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
 				dev_err(disk_to_dev(nbd->disk),
 					"Send data failed (result %d)\n",
 					result);
-				return -EIO;
+				return -EAGAIN;
 			}
 			/*
 			 * The completion might already have come in,
@@ -366,6 +395,12 @@ static inline int sock_recv_bvec(struct nbd_device *nbd, int index,
 	return result;
 }
 
+static int nbd_disconnected(struct nbd_device *nbd)
+{
+	return test_bit(NBD_DISCONNECTED, &nbd->runtime_flags) ||
+		test_bit(NBD_DISCONNECT_REQUESTED, &nbd->runtime_flags);
+}
+
 /* NULL returned = something went wrong, inform userspace */
 static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index)
 {
@@ -379,8 +414,7 @@ static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index)
 	reply.magic = 0;
 	result = sock_xmit(nbd, index, 0, &reply, sizeof(reply), MSG_WAITALL);
 	if (result <= 0) {
-		if (!test_bit(NBD_DISCONNECTED, &nbd->runtime_flags) &&
-		    !test_bit(NBD_DISCONNECT_REQUESTED, &nbd->runtime_flags))
+		if (!nbd_disconnected(nbd))
 			dev_err(disk_to_dev(nbd->disk),
 				"Receive control failed (result %d)\n", result);
 		return ERR_PTR(result);
@@ -421,8 +455,19 @@ static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index)
 			if (result <= 0) {
 				dev_err(disk_to_dev(nbd->disk), "Receive data failed (result %d)\n",
 					result);
-				req->errors++;
-				return cmd;
+				/*
+				 * If we've disconnected or we only have 1
+				 * connection then we need to make sure we
+				 * complete this request, otherwise error out
+				 * and let the timeout stuff handle resubmitting
+				 * this request onto another connection.
+				 */
+				if (nbd_disconnected(nbd) ||
+				    nbd->num_connections <= 1) {
+					req->errors++;
+					return cmd;
+				}
+				return ERR_PTR(-EIO);
 			}
 			dev_dbg(nbd_to_dev(nbd), "request %p: got %d bytes data\n",
 				cmd, bvec.bv_len);
@@ -467,19 +512,13 @@ static void recv_work(struct work_struct *work)
 	while (1) {
 		cmd = nbd_read_stat(nbd, args->index);
 		if (IS_ERR(cmd)) {
+			nbd->socks[args->index]->dead = true;
 			ret = PTR_ERR(cmd);
 			break;
 		}
 
 		nbd_end_request(cmd);
 	}
-
-	/*
-	 * We got an error, shut everybody down if this wasn't the result of a
-	 * disconnect request.
-	 */
-	if (ret && !test_bit(NBD_DISCONNECT_REQUESTED, &nbd->runtime_flags))
-		sock_shutdown(nbd);
 	atomic_dec(&nbd->recv_threads);
 	wake_up(&nbd->recv_wq);
 }
@@ -503,50 +542,89 @@ static void nbd_clear_que(struct nbd_device *nbd)
 	dev_dbg(disk_to_dev(nbd->disk), "queue cleared\n");
 }
 
+static int find_fallback(struct nbd_device *nbd, int index)
+{
+	int new_index = -1;
+	struct nbd_sock *nsock = nbd->socks[index];
+	int fallback = nsock->fallback_index;
+
+	if (test_bit(NBD_DISCONNECTED, &nbd->runtime_flags))
+		return new_index;
+
+	if (nbd->num_connections <= 1) {
+		dev_err_ratelimited(disk_to_dev(nbd->disk),
+				    "Attempted send on invalid socket\n");
+		return new_index;
+	}
+
+	if (fallback >= 0 && fallback < nbd->num_connections &&
+	    !nbd->socks[fallback]->dead)
+		return fallback;
 
-static void nbd_handle_cmd(struct nbd_cmd *cmd, int index)
+	mutex_lock(&nsock->tx_lock);
+	if (nsock->fallback_index < 0 ||
+	    nsock->fallback_index >= nbd->num_connections ||
+	    nbd->socks[nsock->fallback_index]->dead) {
+		int i;
+		for (i = 0; i < nbd->num_connections; i++) {
+			if (i == index)
+				continue;
+			if (!nbd->socks[i]->dead) {
+				new_index = i;
+				break;
+			}
+		}
+		if (new_index < 0) {
+			mutex_unlock(&nsock->tx_lock);
+			dev_err_ratelimited(disk_to_dev(nbd->disk),
+					    "Dead connection, failed to find a fallback\n");
+			return new_index;
+		}
+		nsock->fallback_index = new_index;
+	}
+	new_index = nsock->fallback_index;
+	mutex_unlock(&nsock->tx_lock);
+	return new_index;
+}
+
+static int nbd_handle_cmd(struct nbd_cmd *cmd, int index)
 {
 	struct request *req = blk_mq_rq_from_pdu(cmd);
 	struct nbd_device *nbd = cmd->nbd;
 	struct nbd_sock *nsock;
+	int ret;
 
 	if (index >= nbd->num_connections) {
 		dev_err_ratelimited(disk_to_dev(nbd->disk),
 				    "Attempted send on invalid socket\n");
-		goto error_out;
-	}
-
-	if (test_bit(NBD_DISCONNECTED, &nbd->runtime_flags)) {
-		dev_err_ratelimited(disk_to_dev(nbd->disk),
-				    "Attempted send on closed socket\n");
-		goto error_out;
+		return -EINVAL;
 	}
-
 	req->errors = 0;
-
+again:
 	nsock = nbd->socks[index];
-	mutex_lock(&nsock->tx_lock);
-	if (unlikely(!nsock->sock)) {
-		mutex_unlock(&nsock->tx_lock);
-		dev_err_ratelimited(disk_to_dev(nbd->disk),
-				    "Attempted send on closed socket\n");
-		goto error_out;
+	if (nsock->dead) {
+		index = find_fallback(nbd, index);
+		if (index < 0)
+			return -EIO;
+		nsock = nbd->socks[index];
 	}
 
-	if (nbd_send_cmd(nbd, cmd, index) != 0) {
+	/*
+	 * Some failures are related to the link going down, so anything that
+	 * returns EAGAIN can be retried on a different socket.
+	 */
+	mutex_lock(&nsock->tx_lock);
+	ret = nbd_send_cmd(nbd, cmd, index);
+	if (ret == -EAGAIN) {
 		dev_err_ratelimited(disk_to_dev(nbd->disk),
-				    "Request send failed\n");
-		req->errors++;
-		nbd_end_request(cmd);
+				    "Request send failed trying another connection\n");
+		nsock->dead = true;
+		mutex_unlock(&nsock->tx_lock);
+		goto again;
 	}
-
 	mutex_unlock(&nsock->tx_lock);
 
-	return;
-
-error_out:
-	req->errors++;
-	nbd_end_request(cmd);
+	return ret;
 }
 
 static int nbd_queue_rq(struct blk_mq_hw_ctx *hctx,
@@ -565,7 +643,10 @@ static int nbd_queue_rq(struct blk_mq_hw_ctx *hctx,
 	 */
 	init_completion(&cmd->send_complete);
 	blk_mq_start_request(bd->rq);
-	nbd_handle_cmd(cmd, hctx->queue_num);
+	if (nbd_handle_cmd(cmd, hctx->queue_num) != 0) {
+		bd->rq->errors++;
+		nbd_end_request(cmd);
+	}
 	complete(&cmd->send_complete);
 
 	return BLK_MQ_RQ_QUEUE_OK;
@@ -594,6 +675,8 @@ static int nbd_add_socket(struct nbd_device *nbd, struct socket *sock)
 
 	nbd->socks = socks;
 
+	nsock->fallback_index = -1;
+	nsock->dead = false;
 	mutex_init(&nsock->tx_lock);
 	nsock->sock = sock;
 	socks[nbd->num_connections++] = nsock;
-- 
2.7.4

^ permalink raw reply related

* [PATCH] blk-mq-sched: separate mark hctx and queue restart operations
From: Omar Sandoval @ 2017-02-03 19:35 UTC (permalink / raw)
  To: Jens Axboe, linux-block; +Cc: kernel-team

From: Omar Sandoval <osandov@fb.com>

In blk_mq_sched_dispatch_requests(), we call blk_mq_sched_mark_restart()
after we dispatch requests left over on our hardware queue dispatch
list. This is so we'll go back and dispatch requests from the scheduler.
In this case, it's only necessary to restart the hardware queue that we
are running; there's no reason to run other hardware queues just because
we are using shared tags.

So, split out blk_mq_sched_mark_restart() into two operations: the "all"
variant is for when we really need to mark the request queue as needing
a restart, and we'll keep the original for just the hardware queue.

Signed-off-by: Omar Sandoval <osandov@fb.com>
---
Based on block/for-next. There might be a better name for this.

 block/blk-mq-sched.h | 15 +++++++++++++++
 block/blk-mq.c       |  2 +-
 2 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/block/blk-mq-sched.h b/block/blk-mq-sched.h
index 5954859c8670..2b42042bf6ea 100644
--- a/block/blk-mq-sched.h
+++ b/block/blk-mq-sched.h
@@ -121,8 +121,23 @@ static inline bool blk_mq_sched_has_work(struct blk_mq_hw_ctx *hctx)
 	return false;
 }
 
+/*
+ * Mark a hardware queue as needing a restart.
+ */
 static inline void blk_mq_sched_mark_restart(struct blk_mq_hw_ctx *hctx)
 {
+	if (!test_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state))
+		set_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state);
+}
+
+/*
+ * Mark a hardware queue as needing a restart. If the hardware queue uses shared
+ * driver tags, also mark the request queue as needing a restart. Use this
+ * instead of blk_mq_sched_mark_restart() if a restart is required because we
+ * failed to allocate a driver tag.
+ */
+static inline void blk_mq_sched_mark_restart_all(struct blk_mq_hw_ctx *hctx)
+{
 	if (!test_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state)) {
 		set_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state);
 		if (hctx->flags & BLK_MQ_F_TAG_SHARED) {
diff --git a/block/blk-mq.c b/block/blk-mq.c
index be183e6115a1..199a6ee470e9 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -937,7 +937,7 @@ bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *list)
 			 * in case the needed IO completed right before we
 			 * marked the queue as needing a restart.
 			 */
-			blk_mq_sched_mark_restart(hctx);
+			blk_mq_sched_mark_restart_all(hctx);
 			if (!blk_mq_get_driver_tag(rq, &hctx, false))
 				break;
 		}
-- 
2.11.0

^ permalink raw reply related

* Re: [PATCH 08/24] btrfs: Convert to separately allocated bdi
From: Liu Bo @ 2017-02-03 18:33 UTC (permalink / raw)
  To: Jan Kara
  Cc: linux-fsdevel, Christoph Hellwig, linux-block, Chris Mason,
	Josef Bacik, David Sterba, linux-btrfs
In-Reply-To: <20170202173422.3240-9-jack@suse.cz>

On Thu, Feb 02, 2017 at 06:34:06PM +0100, Jan Kara wrote:
> Allocate struct backing_dev_info separately instead of embedding it
> inside superblock. This unifies handling of bdi among users.

Looks good.

Reviewed-by: Liu Bo <bo.li.liu@oracle.com>

Thanks,

-liubo

> 
> CC: Chris Mason <clm@fb.com>
> CC: Josef Bacik <jbacik@fb.com>
> CC: David Sterba <dsterba@suse.com>
> CC: linux-btrfs@vger.kernel.org
> Signed-off-by: Jan Kara <jack@suse.cz>
> ---
>  fs/btrfs/ctree.h   |  1 -
>  fs/btrfs/disk-io.c | 36 +++++++-----------------------------
>  fs/btrfs/super.c   |  7 +++++++
>  3 files changed, 14 insertions(+), 30 deletions(-)
> 
> diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
> index 6a823719b6c5..1dc06f66dfcf 100644
> --- a/fs/btrfs/ctree.h
> +++ b/fs/btrfs/ctree.h
> @@ -801,7 +801,6 @@ struct btrfs_fs_info {
>  	struct btrfs_super_block *super_for_commit;
>  	struct super_block *sb;
>  	struct inode *btree_inode;
> -	struct backing_dev_info bdi;
>  	struct mutex tree_log_mutex;
>  	struct mutex transaction_kthread_mutex;
>  	struct mutex cleaner_mutex;
> diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
> index 37a31b12bb0c..b25723e729c0 100644
> --- a/fs/btrfs/disk-io.c
> +++ b/fs/btrfs/disk-io.c
> @@ -1810,21 +1810,6 @@ static int btrfs_congested_fn(void *congested_data, int bdi_bits)
>  	return ret;
>  }
>  
> -static int setup_bdi(struct btrfs_fs_info *info, struct backing_dev_info *bdi)
> -{
> -	int err;
> -
> -	err = bdi_setup_and_register(bdi, "btrfs");
> -	if (err)
> -		return err;
> -
> -	bdi->ra_pages = VM_MAX_READAHEAD * 1024 / PAGE_SIZE;
> -	bdi->congested_fn	= btrfs_congested_fn;
> -	bdi->congested_data	= info;
> -	bdi->capabilities |= BDI_CAP_CGROUP_WRITEBACK;
> -	return 0;
> -}
> -
>  /*
>   * called by the kthread helper functions to finally call the bio end_io
>   * functions.  This is where read checksum verification actually happens
> @@ -2598,16 +2583,10 @@ int open_ctree(struct super_block *sb,
>  		goto fail;
>  	}
>  
> -	ret = setup_bdi(fs_info, &fs_info->bdi);
> -	if (ret) {
> -		err = ret;
> -		goto fail_srcu;
> -	}
> -
>  	ret = percpu_counter_init(&fs_info->dirty_metadata_bytes, 0, GFP_KERNEL);
>  	if (ret) {
>  		err = ret;
> -		goto fail_bdi;
> +		goto fail_srcu;
>  	}
>  	fs_info->dirty_metadata_batch = PAGE_SIZE *
>  					(1 + ilog2(nr_cpu_ids));
> @@ -2715,7 +2694,6 @@ int open_ctree(struct super_block *sb,
>  
>  	sb->s_blocksize = 4096;
>  	sb->s_blocksize_bits = blksize_bits(4096);
> -	sb->s_bdi = &fs_info->bdi;
>  
>  	btrfs_init_btree_inode(fs_info);
>  
> @@ -2912,9 +2890,12 @@ int open_ctree(struct super_block *sb,
>  		goto fail_sb_buffer;
>  	}
>  
> -	fs_info->bdi.ra_pages *= btrfs_super_num_devices(disk_super);
> -	fs_info->bdi.ra_pages = max(fs_info->bdi.ra_pages,
> -				    SZ_4M / PAGE_SIZE);
> +	sb->s_bdi->congested_fn = btrfs_congested_fn;
> +	sb->s_bdi->congested_data = fs_info;
> +	sb->s_bdi->capabilities |= BDI_CAP_CGROUP_WRITEBACK;
> +	sb->s_bdi->ra_pages = VM_MAX_READAHEAD * 1024 / PAGE_SIZE;
> +	sb->s_bdi->ra_pages *= btrfs_super_num_devices(disk_super);
> +	sb->s_bdi->ra_pages = max(sb->s_bdi->ra_pages, SZ_4M / PAGE_SIZE);
>  
>  	sb->s_blocksize = sectorsize;
>  	sb->s_blocksize_bits = blksize_bits(sectorsize);
> @@ -3282,8 +3263,6 @@ int open_ctree(struct super_block *sb,
>  	percpu_counter_destroy(&fs_info->delalloc_bytes);
>  fail_dirty_metadata_bytes:
>  	percpu_counter_destroy(&fs_info->dirty_metadata_bytes);
> -fail_bdi:
> -	bdi_destroy(&fs_info->bdi);
>  fail_srcu:
>  	cleanup_srcu_struct(&fs_info->subvol_srcu);
>  fail:
> @@ -4010,7 +3989,6 @@ void close_ctree(struct btrfs_fs_info *fs_info)
>  	percpu_counter_destroy(&fs_info->dirty_metadata_bytes);
>  	percpu_counter_destroy(&fs_info->delalloc_bytes);
>  	percpu_counter_destroy(&fs_info->bio_counter);
> -	bdi_destroy(&fs_info->bdi);
>  	cleanup_srcu_struct(&fs_info->subvol_srcu);
>  
>  	btrfs_free_stripe_hash_table(fs_info);
> diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
> index b5ae7d3d1896..08ef08b63132 100644
> --- a/fs/btrfs/super.c
> +++ b/fs/btrfs/super.c
> @@ -1133,6 +1133,13 @@ static int btrfs_fill_super(struct super_block *sb,
>  #endif
>  	sb->s_flags |= MS_I_VERSION;
>  	sb->s_iflags |= SB_I_CGROUPWB;
> +
> +	err = super_setup_bdi(sb);
> +	if (err) {
> +		btrfs_err(fs_info, "super_setup_bdi failed");
> +		return err;
> +	}
> +
>  	err = open_ctree(sb, fs_devices, (char *)data);
>  	if (err) {
>  		btrfs_err(fs_info, "open_ctree failed");
> -- 
> 2.10.2
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 04/24] fs: Provide infrastructure for dynamic BDIs in filesystems
From: Liu Bo @ 2017-02-03 18:31 UTC (permalink / raw)
  To: Jan Kara
  Cc: linux-fsdevel, Christoph Hellwig, linux-block, linux-mtd,
	linux-nfs, Petr Vandrovec, linux-nilfs, cluster-devel, osd-dev,
	codalist, linux-afs, ecryptfs, linux-cifs, ceph-devel,
	linux-btrfs, v9fs-developer, lustre-devel
In-Reply-To: <20170203135042.GB5844@quack2.suse.cz>

On Fri, Feb 03, 2017 at 02:50:42PM +0100, Jan Kara wrote:
> On Thu 02-02-17 11:28:27, Liu Bo wrote:
> > Hi,
> > 
> > On Thu, Feb 02, 2017 at 06:34:02PM +0100, Jan Kara wrote:
> > > Provide helper functions for setting up dynamically allocated
> > > backing_dev_info structures for filesystems and cleaning them up on
> > > superblock destruction.
> > 
> > Just one concern, will this cause problems for multiple superblock cases
> > like nfs with nosharecache?
> 
> Can you ellaborate a bit? I've looked for a while what nfs with
> nosharecache does but I didn't see how it would influence anything with
> bdis...

Oh, I missed that bdi_seq was static, then it should be fine.

(I was worried about that nfs with nosharecache would have multiple
superblocks and if each superblock has a bdi using the same bdi name,
nfs-xx.)

Thanks for the reply.

Thanks,

-liubo

^ permalink raw reply

* Re: [PATCH v3] dm: don't allow ioctls to targets that don't map to whole devices
From: Johannes Thumshirn @ 2017-02-03 18:17 UTC (permalink / raw)
  To: Christoph Hellwig, Mike Snitzer
  Cc: axboe, agk, pbonzini, dm-devel, linux-block
In-Reply-To: <20170203164129.GA4755@lst.de>

On 02/03/2017 05:41 PM, Christoph Hellwig wrote:
> On Fri, Feb 03, 2017 at 11:39:22AM -0500, Mike Snitzer wrote:
>> I assume you meant for v3 to remove the newline? ;)
> I did.  And I swear I did edit the file, but I guess the ammend
> didn't work.  I guess it's time for the weekend..  I'll resend after
> I got some rest.

Forgotten git add? git commit --amend without git add is such a classic 
mistake on my side as well :-/


Anyways,

Reviewed-by: Johannes Thumshirn <jthumshirn@kernel.org>

-- 
Johannes Thumshirn                                          Storage
jthumshirn@suse.de                                +49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 N�rnberg
GF: Felix Imend�rffer, Jane Smithard, Graham Norton
HRB 21284 (AG N�rnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850

^ permalink raw reply

* Re: [PATCH 3/6] genirq/affinity: update CPU affinity for CPU hotplug events
From: kbuild test robot @ 2017-02-03 17:13 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: kbuild-all, Thomas Gleixner, Jens Axboe, Keith Busch, linux-nvme,
	linux-block, linux-kernel
In-Reply-To: <20170203143600.32307-4-hch@lst.de>

[-- Attachment #1: Type: text/plain, Size: 22820 bytes --]

Hi Christoph,

[auto build test ERROR on block/for-next]
[also build test ERROR on v4.10-rc6]
[cannot apply to next-20170203]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Christoph-Hellwig/genirq-allow-assigning-affinity-to-present-but-not-online-CPUs/20170203-224056
base:   https://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux-block.git for-next
config: arm-socfpga_defconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm 

All error/warnings (new ones prefixed by >>):

   In file included from kernel/irq/internals.h:8:0,
                    from kernel/irq/affinity.c:9:
>> include/linux/irqdesc.h:52:25: error: field 'irq_common_data' has incomplete type
     struct irq_common_data irq_common_data;
                            ^~~~~~~~~~~~~~~
>> include/linux/irqdesc.h:53:19: error: field 'irq_data' has incomplete type
     struct irq_data  irq_data;
                      ^~~~~~~~
>> include/linux/irqdesc.h:55:2: error: unknown type name 'irq_flow_handler_t'
     irq_flow_handler_t handle_irq;
     ^~~~~~~~~~~~~~~~~~
   In file included from include/linux/interrupt.h:5:0,
                    from kernel/irq/affinity.c:5:
   include/linux/irqdesc.h: In function 'irq_data_to_desc':
>> include/linux/irqdesc.h:111:26: error: dereferencing pointer to incomplete type 'struct irq_data'
     return container_of(data->common, struct irq_desc, irq_common_data);
                             ^
   include/linux/kernel.h:850:49: note: in definition of macro 'container_of'
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                    ^~~
   In file included from kernel/irq/internals.h:8:0,
                    from kernel/irq/affinity.c:9:
   include/linux/irqdesc.h: In function 'generic_handle_irq_desc':
>> include/linux/irqdesc.h:150:2: error: called object is not a function or function pointer
     desc->handle_irq(desc);
     ^~~~
   include/linux/irqdesc.h: At top level:
   include/linux/irqdesc.h:194:8: error: unknown type name 'irq_flow_handler_t'
           irq_flow_handler_t handler)
           ^~~~~~~~~~~~~~~~~~
   include/linux/irqdesc.h:215:6: error: unknown type name 'irq_flow_handler_t'
         irq_flow_handler_t handler, const char *name)
         ^~~~~~~~~~~~~~~~~~
   include/linux/irqdesc.h: In function 'irq_balancing_disabled':
>> include/linux/irqdesc.h:229:38: error: 'IRQ_NO_BALANCING_MASK' undeclared (first use in this function)
     return desc->status_use_accessors & IRQ_NO_BALANCING_MASK;
                                         ^~~~~~~~~~~~~~~~~~~~~
   include/linux/irqdesc.h:229:38: note: each undeclared identifier is reported only once for each function it appears in
   include/linux/irqdesc.h: In function 'irq_is_percpu':
>> include/linux/irqdesc.h:237:38: error: 'IRQ_PER_CPU' undeclared (first use in this function)
     return desc->status_use_accessors & IRQ_PER_CPU;
                                         ^~~~~~~~~~~
   In file included from kernel/irq/internals.h:62:0,
                    from kernel/irq/affinity.c:9:
   kernel/irq/debug.h: In function 'print_irq_desc':
>> kernel/irq/debug.h:16:28: warning: format '%p' expects argument of type 'void *', but argument 2 has type 'int' [-Wformat=]
     printk("->handle_irq():  %p, ", desc->handle_irq);
                               ^
>> kernel/irq/debug.h:26:7: error: 'IRQ_LEVEL' undeclared (first use in this function)
     ___P(IRQ_LEVEL);
          ^
   kernel/irq/debug.h:7:50: note: in definition of macro '___P'
    #define ___P(f) if (desc->status_use_accessors & f) printk("%14s set\n", #f)
                                                     ^
>> kernel/irq/debug.h:27:7: error: 'IRQ_PER_CPU' undeclared (first use in this function)
     ___P(IRQ_PER_CPU);
          ^
   kernel/irq/debug.h:7:50: note: in definition of macro '___P'
    #define ___P(f) if (desc->status_use_accessors & f) printk("%14s set\n", #f)
                                                     ^
>> kernel/irq/debug.h:28:7: error: 'IRQ_NOPROBE' undeclared (first use in this function)
     ___P(IRQ_NOPROBE);
          ^
   kernel/irq/debug.h:7:50: note: in definition of macro '___P'
    #define ___P(f) if (desc->status_use_accessors & f) printk("%14s set\n", #f)
                                                     ^
>> kernel/irq/debug.h:29:7: error: 'IRQ_NOREQUEST' undeclared (first use in this function)
     ___P(IRQ_NOREQUEST);
          ^
   kernel/irq/debug.h:7:50: note: in definition of macro '___P'
    #define ___P(f) if (desc->status_use_accessors & f) printk("%14s set\n", #f)
                                                     ^
>> kernel/irq/debug.h:30:7: error: 'IRQ_NOTHREAD' undeclared (first use in this function)
     ___P(IRQ_NOTHREAD);
          ^
   kernel/irq/debug.h:7:50: note: in definition of macro '___P'
    #define ___P(f) if (desc->status_use_accessors & f) printk("%14s set\n", #f)
                                                     ^
>> kernel/irq/debug.h:31:7: error: 'IRQ_NOAUTOEN' undeclared (first use in this function)
     ___P(IRQ_NOAUTOEN);
          ^
   kernel/irq/debug.h:7:50: note: in definition of macro '___P'
    #define ___P(f) if (desc->status_use_accessors & f) printk("%14s set\n", #f)
                                                     ^
   In file included from kernel/irq/internals.h:63:0,
                    from kernel/irq/affinity.c:9:
   kernel/irq/settings.h: At top level:
>> kernel/irq/settings.h:6:28: error: 'IRQ_DEFAULT_INIT_FLAGS' undeclared here (not in a function)
     _IRQ_DEFAULT_INIT_FLAGS = IRQ_DEFAULT_INIT_FLAGS,
                               ^~~~~~~~~~~~~~~~~~~~~~
>> kernel/irq/settings.h:7:18: error: 'IRQ_PER_CPU' undeclared here (not in a function)
     _IRQ_PER_CPU  = IRQ_PER_CPU,
                     ^~~~~~~~~~~
>> kernel/irq/settings.h:8:16: error: 'IRQ_LEVEL' undeclared here (not in a function)
     _IRQ_LEVEL  = IRQ_LEVEL,
                   ^~~~~~~~~
>> kernel/irq/settings.h:9:18: error: 'IRQ_NOPROBE' undeclared here (not in a function)
     _IRQ_NOPROBE  = IRQ_NOPROBE,
                     ^~~~~~~~~~~
>> kernel/irq/settings.h:10:20: error: 'IRQ_NOREQUEST' undeclared here (not in a function)
     _IRQ_NOREQUEST  = IRQ_NOREQUEST,
                       ^~~~~~~~~~~~~
>> kernel/irq/settings.h:11:19: error: 'IRQ_NOTHREAD' undeclared here (not in a function)
     _IRQ_NOTHREAD  = IRQ_NOTHREAD,
                      ^~~~~~~~~~~~

vim +/irq_data +53 include/linux/irqdesc.h

425a5072 Thomas Gleixner           2015-12-13   46   * @rcu:		rcu head for delayed free
ecb3f394 Craig Gallek              2016-09-13   47   * @kobj:		kobject used to represent this struct in sysfs
e144710b Thomas Gleixner           2010-10-01   48   * @dir:		/proc/irq/ procfs entry
e144710b Thomas Gleixner           2010-10-01   49   * @name:		flow handler name for /proc/interrupts output
e144710b Thomas Gleixner           2010-10-01   50   */
e144710b Thomas Gleixner           2010-10-01   51  struct irq_desc {
0d0b4c86 Jiang Liu                 2015-06-01  @52  	struct irq_common_data	irq_common_data;
e144710b Thomas Gleixner           2010-10-01  @53  	struct irq_data		irq_data;
6c9ae009 Eric Dumazet              2011-01-13   54  	unsigned int __percpu	*kstat_irqs;
e144710b Thomas Gleixner           2010-10-01  @55  	irq_flow_handler_t	handle_irq;
78129576 Thomas Gleixner           2011-02-10   56  #ifdef CONFIG_IRQ_PREFLOW_FASTEOI
78129576 Thomas Gleixner           2011-02-10   57  	irq_preflow_handler_t	preflow_handler;
78129576 Thomas Gleixner           2011-02-10   58  #endif
e144710b Thomas Gleixner           2010-10-01   59  	struct irqaction	*action;	/* IRQ action list */
a6967caf Thomas Gleixner           2011-02-10   60  	unsigned int		status_use_accessors;
dbec07ba Thomas Gleixner           2011-02-07   61  	unsigned int		core_internal_state__do_not_mess_with_it;
e144710b Thomas Gleixner           2010-10-01   62  	unsigned int		depth;		/* nested irq disables */
e144710b Thomas Gleixner           2010-10-01   63  	unsigned int		wake_depth;	/* nested wake enables */
e144710b Thomas Gleixner           2010-10-01   64  	unsigned int		irq_count;	/* For detecting broken IRQs */
e144710b Thomas Gleixner           2010-10-01   65  	unsigned long		last_unhandled;	/* Aging timer for unhandled count */
e144710b Thomas Gleixner           2010-10-01   66  	unsigned int		irqs_unhandled;
1e77d0a1 Thomas Gleixner           2013-03-07   67  	atomic_t		threads_handled;
1e77d0a1 Thomas Gleixner           2013-03-07   68  	int			threads_handled_last;
e144710b Thomas Gleixner           2010-10-01   69  	raw_spinlock_t		lock;
31d9d9b6 Marc Zyngier              2011-09-23   70  	struct cpumask		*percpu_enabled;
222df54f Marc Zyngier              2016-04-11   71  	const struct cpumask	*percpu_affinity;
e144710b Thomas Gleixner           2010-10-01   72  #ifdef CONFIG_SMP
e144710b Thomas Gleixner           2010-10-01   73  	const struct cpumask	*affinity_hint;
cd7eab44 Ben Hutchings             2011-01-19   74  	struct irq_affinity_notify *affinity_notify;
e144710b Thomas Gleixner           2010-10-01   75  #ifdef CONFIG_GENERIC_PENDING_IRQ
e144710b Thomas Gleixner           2010-10-01   76  	cpumask_var_t		pending_mask;
e144710b Thomas Gleixner           2010-10-01   77  #endif
e144710b Thomas Gleixner           2010-10-01   78  #endif
b5faba21 Thomas Gleixner           2011-02-23   79  	unsigned long		threads_oneshot;
e144710b Thomas Gleixner           2010-10-01   80  	atomic_t		threads_active;
e144710b Thomas Gleixner           2010-10-01   81  	wait_queue_head_t       wait_for_threads;
cab303be Thomas Gleixner           2014-08-28   82  #ifdef CONFIG_PM_SLEEP
cab303be Thomas Gleixner           2014-08-28   83  	unsigned int		nr_actions;
cab303be Thomas Gleixner           2014-08-28   84  	unsigned int		no_suspend_depth;
17f48034 Rafael J. Wysocki         2015-02-27   85  	unsigned int		cond_suspend_depth;
cab303be Thomas Gleixner           2014-08-28   86  	unsigned int		force_resume_depth;
cab303be Thomas Gleixner           2014-08-28   87  #endif
e144710b Thomas Gleixner           2010-10-01   88  #ifdef CONFIG_PROC_FS
e144710b Thomas Gleixner           2010-10-01   89  	struct proc_dir_entry	*dir;
e144710b Thomas Gleixner           2010-10-01   90  #endif
425a5072 Thomas Gleixner           2015-12-13   91  #ifdef CONFIG_SPARSE_IRQ
425a5072 Thomas Gleixner           2015-12-13   92  	struct rcu_head		rcu;
ecb3f394 Craig Gallek              2016-09-13   93  	struct kobject		kobj;
425a5072 Thomas Gleixner           2015-12-13   94  #endif
293a7a0a Thomas Gleixner           2012-10-16   95  	int			parent_irq;
b6873807 Sebastian Andrzej Siewior 2011-07-11   96  	struct module		*owner;
e144710b Thomas Gleixner           2010-10-01   97  	const char		*name;
e144710b Thomas Gleixner           2010-10-01   98  } ____cacheline_internodealigned_in_smp;
e144710b Thomas Gleixner           2010-10-01   99  
a8994181 Thomas Gleixner           2015-07-05  100  #ifdef CONFIG_SPARSE_IRQ
a8994181 Thomas Gleixner           2015-07-05  101  extern void irq_lock_sparse(void);
a8994181 Thomas Gleixner           2015-07-05  102  extern void irq_unlock_sparse(void);
a8994181 Thomas Gleixner           2015-07-05  103  #else
a8994181 Thomas Gleixner           2015-07-05  104  static inline void irq_lock_sparse(void) { }
a8994181 Thomas Gleixner           2015-07-05  105  static inline void irq_unlock_sparse(void) { }
e144710b Thomas Gleixner           2010-10-01  106  extern struct irq_desc irq_desc[NR_IRQS];
e144710b Thomas Gleixner           2010-10-01  107  #endif
e144710b Thomas Gleixner           2010-10-01  108  
7bbf1dd2 Jiang Liu                 2015-06-01  109  static inline struct irq_desc *irq_data_to_desc(struct irq_data *data)
7bbf1dd2 Jiang Liu                 2015-06-01  110  {
755d119a Thomas Gleixner           2015-09-16 @111  	return container_of(data->common, struct irq_desc, irq_common_data);
7bbf1dd2 Jiang Liu                 2015-06-01  112  }
7bbf1dd2 Jiang Liu                 2015-06-01  113  
304adf8a Jiang Liu                 2015-06-04  114  static inline unsigned int irq_desc_get_irq(struct irq_desc *desc)
304adf8a Jiang Liu                 2015-06-04  115  {
304adf8a Jiang Liu                 2015-06-04  116  	return desc->irq_data.irq;
304adf8a Jiang Liu                 2015-06-04  117  }
304adf8a Jiang Liu                 2015-06-04  118  
d9936bb3 Thomas Gleixner           2011-03-11  119  static inline struct irq_data *irq_desc_get_irq_data(struct irq_desc *desc)
d9936bb3 Thomas Gleixner           2011-03-11  120  {
d9936bb3 Thomas Gleixner           2011-03-11  121  	return &desc->irq_data;
d9936bb3 Thomas Gleixner           2011-03-11 @122  }
d9936bb3 Thomas Gleixner           2011-03-11  123  
a0cd9ca2 Thomas Gleixner           2011-02-10  124  static inline struct irq_chip *irq_desc_get_chip(struct irq_desc *desc)
a0cd9ca2 Thomas Gleixner           2011-02-10  125  {
a0cd9ca2 Thomas Gleixner           2011-02-10  126  	return desc->irq_data.chip;
a0cd9ca2 Thomas Gleixner           2011-02-10  127  }
a0cd9ca2 Thomas Gleixner           2011-02-10  128  
a0cd9ca2 Thomas Gleixner           2011-02-10  129  static inline void *irq_desc_get_chip_data(struct irq_desc *desc)
a0cd9ca2 Thomas Gleixner           2011-02-10  130  {
a0cd9ca2 Thomas Gleixner           2011-02-10  131  	return desc->irq_data.chip_data;
a0cd9ca2 Thomas Gleixner           2011-02-10  132  }
a0cd9ca2 Thomas Gleixner           2011-02-10  133  
a0cd9ca2 Thomas Gleixner           2011-02-10  134  static inline void *irq_desc_get_handler_data(struct irq_desc *desc)
a0cd9ca2 Thomas Gleixner           2011-02-10  135  {
af7080e0 Jiang Liu                 2015-06-01  136  	return desc->irq_common_data.handler_data;
a0cd9ca2 Thomas Gleixner           2011-02-10  137  }
a0cd9ca2 Thomas Gleixner           2011-02-10  138  
a0cd9ca2 Thomas Gleixner           2011-02-10  139  static inline struct msi_desc *irq_desc_get_msi_desc(struct irq_desc *desc)
a0cd9ca2 Thomas Gleixner           2011-02-10  140  {
b237721c Jiang Liu                 2015-06-01  141  	return desc->irq_common_data.msi_desc;
a0cd9ca2 Thomas Gleixner           2011-02-10  142  }
a0cd9ca2 Thomas Gleixner           2011-02-10  143  
e144710b Thomas Gleixner           2010-10-01  144  /*
e144710b Thomas Gleixner           2010-10-01  145   * Architectures call this to let the generic IRQ layer
6584d84c Huang Shijie              2015-09-01  146   * handle an interrupt.
e144710b Thomas Gleixner           2010-10-01  147   */
bd0b9ac4 Thomas Gleixner           2015-09-14  148  static inline void generic_handle_irq_desc(struct irq_desc *desc)
e144710b Thomas Gleixner           2010-10-01  149  {
bd0b9ac4 Thomas Gleixner           2015-09-14 @150  	desc->handle_irq(desc);
e144710b Thomas Gleixner           2010-10-01  151  }
e144710b Thomas Gleixner           2010-10-01  152  
fe12bc2c Thomas Gleixner           2011-05-18  153  int generic_handle_irq(unsigned int irq);
e144710b Thomas Gleixner           2010-10-01  154  
76ba59f8 Marc Zyngier              2014-08-26  155  #ifdef CONFIG_HANDLE_DOMAIN_IRQ
76ba59f8 Marc Zyngier              2014-08-26  156  /*
76ba59f8 Marc Zyngier              2014-08-26  157   * Convert a HW interrupt number to a logical one using a IRQ domain,
76ba59f8 Marc Zyngier              2014-08-26  158   * and handle the result interrupt number. Return -EINVAL if
76ba59f8 Marc Zyngier              2014-08-26  159   * conversion failed. Providing a NULL domain indicates that the
76ba59f8 Marc Zyngier              2014-08-26  160   * conversion has already been done.
76ba59f8 Marc Zyngier              2014-08-26  161   */
76ba59f8 Marc Zyngier              2014-08-26  162  int __handle_domain_irq(struct irq_domain *domain, unsigned int hwirq,
76ba59f8 Marc Zyngier              2014-08-26  163  			bool lookup, struct pt_regs *regs);
76ba59f8 Marc Zyngier              2014-08-26  164  
76ba59f8 Marc Zyngier              2014-08-26  165  static inline int handle_domain_irq(struct irq_domain *domain,
76ba59f8 Marc Zyngier              2014-08-26  166  				    unsigned int hwirq, struct pt_regs *regs)
76ba59f8 Marc Zyngier              2014-08-26  167  {
76ba59f8 Marc Zyngier              2014-08-26  168  	return __handle_domain_irq(domain, hwirq, true, regs);
76ba59f8 Marc Zyngier              2014-08-26  169  }
76ba59f8 Marc Zyngier              2014-08-26  170  #endif
76ba59f8 Marc Zyngier              2014-08-26  171  
e144710b Thomas Gleixner           2010-10-01  172  /* Test to see if a driver has successfully requested an irq */
f61ae4fb Thomas Gleixner           2015-08-02  173  static inline int irq_desc_has_action(struct irq_desc *desc)
e144710b Thomas Gleixner           2010-10-01  174  {
e144710b Thomas Gleixner           2010-10-01  175  	return desc->action != NULL;
e144710b Thomas Gleixner           2010-10-01  176  }
e144710b Thomas Gleixner           2010-10-01  177  
f61ae4fb Thomas Gleixner           2015-08-02  178  static inline int irq_has_action(unsigned int irq)
f61ae4fb Thomas Gleixner           2015-08-02  179  {
f61ae4fb Thomas Gleixner           2015-08-02  180  	return irq_desc_has_action(irq_to_desc(irq));
f61ae4fb Thomas Gleixner           2015-08-02  181  }
f61ae4fb Thomas Gleixner           2015-08-02  182  
bbc9d21f Thomas Gleixner           2015-06-23  183  /**
bbc9d21f Thomas Gleixner           2015-06-23  184   * irq_set_handler_locked - Set irq handler from a locked region
bbc9d21f Thomas Gleixner           2015-06-23  185   * @data:	Pointer to the irq_data structure which identifies the irq
bbc9d21f Thomas Gleixner           2015-06-23  186   * @handler:	Flow control handler function for this interrupt
bbc9d21f Thomas Gleixner           2015-06-23  187   *
bbc9d21f Thomas Gleixner           2015-06-23  188   * Sets the handler in the irq descriptor associated to @data.
bbc9d21f Thomas Gleixner           2015-06-23  189   *
bbc9d21f Thomas Gleixner           2015-06-23  190   * Must be called with irq_desc locked and valid parameters. Typical
bbc9d21f Thomas Gleixner           2015-06-23  191   * call site is the irq_set_type() callback.
bbc9d21f Thomas Gleixner           2015-06-23  192   */
bbc9d21f Thomas Gleixner           2015-06-23  193  static inline void irq_set_handler_locked(struct irq_data *data,
bbc9d21f Thomas Gleixner           2015-06-23 @194  					  irq_flow_handler_t handler)
bbc9d21f Thomas Gleixner           2015-06-23  195  {
bbc9d21f Thomas Gleixner           2015-06-23  196  	struct irq_desc *desc = irq_data_to_desc(data);
bbc9d21f Thomas Gleixner           2015-06-23  197  
bbc9d21f Thomas Gleixner           2015-06-23  198  	desc->handle_irq = handler;
bbc9d21f Thomas Gleixner           2015-06-23  199  }
bbc9d21f Thomas Gleixner           2015-06-23  200  
bbc9d21f Thomas Gleixner           2015-06-23  201  /**
bbc9d21f Thomas Gleixner           2015-06-23  202   * irq_set_chip_handler_name_locked - Set chip, handler and name from a locked region
bbc9d21f Thomas Gleixner           2015-06-23  203   * @data:	Pointer to the irq_data structure for which the chip is set
bbc9d21f Thomas Gleixner           2015-06-23  204   * @chip:	Pointer to the new irq chip
bbc9d21f Thomas Gleixner           2015-06-23  205   * @handler:	Flow control handler function for this interrupt
bbc9d21f Thomas Gleixner           2015-06-23  206   * @name:	Name of the interrupt
bbc9d21f Thomas Gleixner           2015-06-23  207   *
bbc9d21f Thomas Gleixner           2015-06-23  208   * Replace the irq chip at the proper hierarchy level in @data and
bbc9d21f Thomas Gleixner           2015-06-23  209   * sets the handler and name in the associated irq descriptor.
bbc9d21f Thomas Gleixner           2015-06-23  210   *
bbc9d21f Thomas Gleixner           2015-06-23  211   * Must be called with irq_desc locked and valid parameters.
bbc9d21f Thomas Gleixner           2015-06-23  212   */
bbc9d21f Thomas Gleixner           2015-06-23  213  static inline void
bbc9d21f Thomas Gleixner           2015-06-23  214  irq_set_chip_handler_name_locked(struct irq_data *data, struct irq_chip *chip,
bbc9d21f Thomas Gleixner           2015-06-23 @215  				 irq_flow_handler_t handler, const char *name)
bbc9d21f Thomas Gleixner           2015-06-23  216  {
bbc9d21f Thomas Gleixner           2015-06-23  217  	struct irq_desc *desc = irq_data_to_desc(data);
bbc9d21f Thomas Gleixner           2015-06-23  218  
bbc9d21f Thomas Gleixner           2015-06-23  219  	desc->handle_irq = handler;
bbc9d21f Thomas Gleixner           2015-06-23  220  	desc->name = name;
bbc9d21f Thomas Gleixner           2015-06-23  221  	data->chip = chip;
bbc9d21f Thomas Gleixner           2015-06-23  222  }
bbc9d21f Thomas Gleixner           2015-06-23  223  
a2e8461a Thomas Gleixner           2011-03-23  224  static inline int irq_balancing_disabled(unsigned int irq)
a2e8461a Thomas Gleixner           2011-03-23  225  {
e144710b Thomas Gleixner           2010-10-01  226  	struct irq_desc *desc;
e144710b Thomas Gleixner           2010-10-01  227  
e144710b Thomas Gleixner           2010-10-01  228  	desc = irq_to_desc(irq);
0c6f8a8b Thomas Gleixner           2011-03-28 @229  	return desc->status_use_accessors & IRQ_NO_BALANCING_MASK;
e144710b Thomas Gleixner           2010-10-01  230  }
78129576 Thomas Gleixner           2011-02-10  231  
7f4a8e7b Vinayak Kale              2013-12-04  232  static inline int irq_is_percpu(unsigned int irq)
7f4a8e7b Vinayak Kale              2013-12-04  233  {
7f4a8e7b Vinayak Kale              2013-12-04  234  	struct irq_desc *desc;
7f4a8e7b Vinayak Kale              2013-12-04  235  
7f4a8e7b Vinayak Kale              2013-12-04  236  	desc = irq_to_desc(irq);
7f4a8e7b Vinayak Kale              2013-12-04 @237  	return desc->status_use_accessors & IRQ_PER_CPU;
7f4a8e7b Vinayak Kale              2013-12-04  238  }
7f4a8e7b Vinayak Kale              2013-12-04  239  
d3e17deb Thomas Gleixner           2011-03-22  240  static inline void

:::::: The code at line 53 was first introduced by commit
:::::: e144710b302525de5b90b9c3ba43562458d8957f genirq: Distangle irq.h

:::::: TO: Thomas Gleixner <tglx@linutronix.de>
:::::: CC: Thomas Gleixner <tglx@linutronix.de>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 19463 bytes --]

^ permalink raw reply

* Re: [PATCH v3] dm: don't allow ioctls to targets that don't map to whole devices
From: Paolo Bonzini @ 2017-02-03 16:56 UTC (permalink / raw)
  To: Christoph Hellwig, snitzer, axboe; +Cc: agk, dm-devel, linux-block
In-Reply-To: <20170203163708.13943-1-hch@lst.de>



On 03/02/2017 08:37, Christoph Hellwig wrote:
> .. at least for unprivileged users.  Before we called into the SCSI
> ioctl code to allow excemptions for a few SCSI passthrough ioctls,
> but this is pretty unsafe and except for this call dm knows nothing
> about SCSI ioctls.
> 
> As the SCSI ioctl code is now optional, we really don't want to
> drag it in for DM, and the exception is not very useful anyway.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> Acked-by: Mike Snitzer <snitzer@redhat.com>
> ---
>  drivers/md/dm.c | 13 ++++++++-----
>  1 file changed, 8 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/md/dm.c b/drivers/md/dm.c
> index 9e958bc94fed..fd4331aa2e19 100644
> --- a/drivers/md/dm.c
> +++ b/drivers/md/dm.c
> @@ -465,13 +465,16 @@ static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode,
>  
>  	if (r > 0) {
>  		/*
> -		 * Target determined this ioctl is being issued against
> -		 * a logical partition of the parent bdev; so extra
> -		 * validation is needed.
> +		 * Target determined this ioctl is being issued against a
> +		 * subset of the parent bdev; require extra privileges.
>  		 */
> -		r = scsi_verify_blk_ioctl(NULL, cmd);
> -		if (r)
> +		if (!capable(CAP_SYS_RAWIO)) {
> +			DMWARN_LIMIT(
> +	"%s: sending ioctl %x to DM device without required privilege.\n",
> +				current->comm, cmd);
> +			r = -ENOIOCTLCMD;
>  			goto out;
> +		}
>  	}
>  
>  	r =  __blkdev_driver_ioctl(bdev, mode, cmd, arg);
> 

Acked-by: Paolo Bonzini <pbonzini@redhat.com>

Thanks,

Paolo

^ permalink raw reply

* Re: [PATCH 2/2] block: free merged request in the caller
From: Omar Sandoval @ 2017-02-03 16:44 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-block, paolo.valente
In-Reply-To: <1486051573-13445-3-git-send-email-axboe@fb.com>

On Thu, Feb 02, 2017 at 09:06:13AM -0700, Jens Axboe wrote:
> If we end up doing a request-to-request merge when we have completed
> a bio-to-request merge, we free the request from deep down in that
> path. For blk-mq-sched, the merge path has to hold the appropriate
> lock, but we don't need it for freeing the request. And in fact
> holding the lock is problematic, since we are now calling the
> mq sched put_rq_private() hook with the lock held. Other call paths
> do not hold this lock.
> 
> Fix this inconsistency by ensuring that the caller frees a merged
> request. Then we can do it outside of the lock, making it both more
> efficient and fixing the blk-mq-sched problem of invoking parts of
> the scheduler with an unknown lock state.
> 
> Reported-by: Paolo Valente <paolo.valente@linaro.org>

Reviewed-by: Omar Sandoval <osandov@fb.com>

> Signed-off-by: Jens Axboe <axboe@fb.com>
> ---
>  block/blk-core.c     | 12 +++++++++---
>  block/blk-merge.c    | 15 ++++++++++++---
>  block/blk-mq-sched.c |  9 ++++++---
>  block/blk-mq-sched.h |  3 ++-
>  block/mq-deadline.c  |  8 ++++++--
>  5 files changed, 35 insertions(+), 12 deletions(-)

^ permalink raw reply

* Re: [PATCH 1/2] blk-merge: return the merged request
From: Omar Sandoval @ 2017-02-03 16:42 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-block, paolo.valente
In-Reply-To: <1486051573-13445-2-git-send-email-axboe@fb.com>

On Thu, Feb 02, 2017 at 09:06:12AM -0700, Jens Axboe wrote:
> When we attempt to merge request-to-request, we return a 0/1 if we
> ended up merging or not. Change that to return the pointer to the
> request that we freed. We will use this to move the freeing of
> that request out of the merge logic, so that callers can drop
> locks before freeing the request.
> 
> There should be no functional changes in this patch.

Reviewed-by: Omar Sandoval <osandov@fb.com>

> Signed-off-by: Jens Axboe <axboe@fb.com>
> ---
>  block/blk-merge.c | 31 ++++++++++++++++---------------
>  block/blk.h       |  4 ++--
>  2 files changed, 18 insertions(+), 17 deletions(-)

^ permalink raw reply

* Re: [PATCH v3] dm: don't allow ioctls to targets that don't map to whole devices
From: Christoph Hellwig @ 2017-02-03 16:41 UTC (permalink / raw)
  To: Mike Snitzer
  Cc: Christoph Hellwig, axboe, agk, pbonzini, dm-devel, linux-block
In-Reply-To: <20170203163921.GA823@redhat.com>

On Fri, Feb 03, 2017 at 11:39:22AM -0500, Mike Snitzer wrote:
> I assume you meant for v3 to remove the newline? ;)

I did.  And I swear I did edit the file, but I guess the ammend
didn't work.  I guess it's time for the weekend..  I'll resend after
I got some rest.

^ permalink raw reply

* Re: [PATCH v3] dm: don't allow ioctls to targets that don't map to whole devices
From: Mike Snitzer @ 2017-02-03 16:39 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: axboe, agk, pbonzini, dm-devel, linux-block
In-Reply-To: <20170203163708.13943-1-hch@lst.de>

On Fri, Feb 03 2017 at 11:37am -0500,
Christoph Hellwig <hch@lst.de> wrote:

> .. at least for unprivileged users.  Before we called into the SCSI
> ioctl code to allow excemptions for a few SCSI passthrough ioctls,
> but this is pretty unsafe and except for this call dm knows nothing
> about SCSI ioctls.
> 
> As the SCSI ioctl code is now optional, we really don't want to
> drag it in for DM, and the exception is not very useful anyway.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> Acked-by: Mike Snitzer <snitzer@redhat.com>
> ---
>  drivers/md/dm.c | 13 ++++++++-----
>  1 file changed, 8 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/md/dm.c b/drivers/md/dm.c
> index 9e958bc94fed..fd4331aa2e19 100644
> --- a/drivers/md/dm.c
> +++ b/drivers/md/dm.c
> @@ -465,13 +465,16 @@ static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode,
>  
>  	if (r > 0) {
>  		/*
> -		 * Target determined this ioctl is being issued against
> -		 * a logical partition of the parent bdev; so extra
> -		 * validation is needed.
> +		 * Target determined this ioctl is being issued against a
> +		 * subset of the parent bdev; require extra privileges.
>  		 */
> -		r = scsi_verify_blk_ioctl(NULL, cmd);
> -		if (r)
> +		if (!capable(CAP_SYS_RAWIO)) {
> +			DMWARN_LIMIT(
> +	"%s: sending ioctl %x to DM device without required privilege.\n",

I assume you meant for v3 to remove the newline? ;)

^ permalink raw reply

* [PATCH v3] dm: don't allow ioctls to targets that don't map to whole devices
From: Christoph Hellwig @ 2017-02-03 16:37 UTC (permalink / raw)
  To: snitzer, axboe; +Cc: agk, pbonzini, dm-devel, linux-block

.. at least for unprivileged users.  Before we called into the SCSI
ioctl code to allow excemptions for a few SCSI passthrough ioctls,
but this is pretty unsafe and except for this call dm knows nothing
about SCSI ioctls.

As the SCSI ioctl code is now optional, we really don't want to
drag it in for DM, and the exception is not very useful anyway.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Acked-by: Mike Snitzer <snitzer@redhat.com>
---
 drivers/md/dm.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 9e958bc94fed..fd4331aa2e19 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -465,13 +465,16 @@ static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode,
 
 	if (r > 0) {
 		/*
-		 * Target determined this ioctl is being issued against
-		 * a logical partition of the parent bdev; so extra
-		 * validation is needed.
+		 * Target determined this ioctl is being issued against a
+		 * subset of the parent bdev; require extra privileges.
 		 */
-		r = scsi_verify_blk_ioctl(NULL, cmd);
-		if (r)
+		if (!capable(CAP_SYS_RAWIO)) {
+			DMWARN_LIMIT(
+	"%s: sending ioctl %x to DM device without required privilege.\n",
+				current->comm, cmd);
+			r = -ENOIOCTLCMD;
 			goto out;
+		}
 	}
 
 	r =  __blkdev_driver_ioctl(bdev, mode, cmd, arg);
-- 
2.11.0

^ permalink raw reply related

* Re: [PATCH v2] dm: don't allow ioctls to targets that don't map to whole devices
From: Mike Snitzer @ 2017-02-03 16:29 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: axboe, agk, pbonzini, dm-devel, linux-block
In-Reply-To: <20170203162257.4665-1-hch@lst.de>

On Fri, Feb 03 2017 at 11:22am -0500,
Christoph Hellwig <hch@lst.de> wrote:

> .. at least for unprivileged users.  Before we called into the SCSI
> ioctl code to allow excemptions for a few SCSI passthrough ioctls,
> but this is pretty unsafe and except for this call dm knows nothing
> about SCSI ioctls.
> 
> As the SCSI ioctl code is now optional, we really don't want to
> drag it in for DM, and the exception is not very useful anyway.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> Acked-by: Mike Snitzer <snitzer@redhat.com>
> ---
>  drivers/md/dm.c | 13 ++++++++-----
>  1 file changed, 8 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/md/dm.c b/drivers/md/dm.c
> index 9e958bc94fed..fd4331aa2e19 100644
> --- a/drivers/md/dm.c
> +++ b/drivers/md/dm.c
> @@ -465,13 +465,16 @@ static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode,
>  
>  	if (r > 0) {
>  		/*
> -		 * Target determined this ioctl is being issued against
> -		 * a logical partition of the parent bdev; so extra
> -		 * validation is needed.
> +		 * Target determined this ioctl is being issued against a
> +		 * subset of the parent bdev; require extra privileges.
>  		 */
> -		r = scsi_verify_blk_ioctl(NULL, cmd);
> -		if (r)
> +		if (!capable(CAP_SYS_RAWIO)) {
> +			DMWARN_LIMIT(
> +	"%s: sending ioctl %x to DM device without required privilege.\n",
> +				current->comm, cmd);
> +			r = -ENOIOCTLCMD;
>  			goto out;
> +		}
>  	}
>  
>  	r =  __blkdev_driver_ioctl(bdev, mode, cmd, arg);
> -- 
> 2.11.0
> 

Sorry, should've been clearer (or just sent an incremental patch) but
DMWARN et al don't require a newline at the end of their message strings.

^ permalink raw reply

* [PATCH v2] dm: don't allow ioctls to targets that don't map to whole devices
From: Christoph Hellwig @ 2017-02-03 16:22 UTC (permalink / raw)
  To: snitzer, axboe; +Cc: agk, pbonzini, dm-devel, linux-block

.. at least for unprivileged users.  Before we called into the SCSI
ioctl code to allow excemptions for a few SCSI passthrough ioctls,
but this is pretty unsafe and except for this call dm knows nothing
about SCSI ioctls.

As the SCSI ioctl code is now optional, we really don't want to
drag it in for DM, and the exception is not very useful anyway.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Acked-by: Mike Snitzer <snitzer@redhat.com>
---
 drivers/md/dm.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 9e958bc94fed..fd4331aa2e19 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -465,13 +465,16 @@ static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode,
 
 	if (r > 0) {
 		/*
-		 * Target determined this ioctl is being issued against
-		 * a logical partition of the parent bdev; so extra
-		 * validation is needed.
+		 * Target determined this ioctl is being issued against a
+		 * subset of the parent bdev; require extra privileges.
 		 */
-		r = scsi_verify_blk_ioctl(NULL, cmd);
-		if (r)
+		if (!capable(CAP_SYS_RAWIO)) {
+			DMWARN_LIMIT(
+	"%s: sending ioctl %x to DM device without required privilege.\n",
+				current->comm, cmd);
+			r = -ENOIOCTLCMD;
 			goto out;
+		}
 	}
 
 	r =  __blkdev_driver_ioctl(bdev, mode, cmd, arg);
-- 
2.11.0

^ permalink raw reply related

* Re: [PATCH 3/6] genirq/affinity: update CPU affinity for CPU hotplug events
From: kbuild test robot @ 2017-02-03 16:17 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: kbuild-all, Thomas Gleixner, Jens Axboe, Keith Busch, linux-nvme,
	linux-block, linux-kernel
In-Reply-To: <20170203143600.32307-4-hch@lst.de>

[-- Attachment #1: Type: text/plain, Size: 1718 bytes --]

Hi Christoph,

[auto build test ERROR on block/for-next]
[also build test ERROR on v4.10-rc6]
[cannot apply to next-20170203]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Christoph-Hellwig/genirq-allow-assigning-affinity-to-present-but-not-online-CPUs/20170203-224056
base:   https://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux-block.git for-next
config: ia64-allmodconfig (attached as .config)
compiler: ia64-linux-gcc (GCC) 6.2.0
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=ia64 

All errors (new ones prefixed by >>):

   kernel/irq/affinity.c: In function 'irq_affinity_offline_irq':
>> kernel/irq/affinity.c:264:2: error: implicit declaration of function 'irq_force_complete_move' [-Werror=implicit-function-declaration]
     irq_force_complete_move(desc);
     ^~~~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors

vim +/irq_force_complete_move +264 kernel/irq/affinity.c

   258	
   259		/*
   260		 * Complete the irq move. This cpu is going down and for
   261		 * non intr-remapping case, we can't wait till this interrupt
   262		 * arrives at this cpu before completing the irq move.
   263		 */
 > 264		irq_force_complete_move(desc);
   265	
   266		/*
   267		 * The interrupt descriptor might have been cleaned up

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 45922 bytes --]

^ permalink raw reply

* Re: [REGRESSION v4.10-rc1] blkdev_issue_zeroout() returns -EREMOTEIO on the first call for SCSI device that doesn't support WRITE SAME
From: Jens Axboe @ 2017-02-03 16:14 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Junichi Nomura, linux-block@vger.kernel.org, linux-scsi,
	Chaitanya Kulkarni, Martin K. Petersen
In-Reply-To: <20170203161239.GA3880@lst.de>

On 02/03/2017 09:12 AM, Christoph Hellwig wrote:
> On Fri, Feb 03, 2017 at 08:21:31AM -0700, Jens Axboe wrote:
>>> Error 121 (EREMOTEIO) was returned from blkdev_issue_zeroout().
>>> That came from sd driver because WRITE SAME was sent to the device
>>> which didn't support it.
>>>
>>> The problem was introduced by commit e73c23ff736e ("block: add async
>>> variant of blkdev_issue_zeroout"). Before the commit, blkdev_issue_zeroout
>>> fell back to normal zero writing when WRITE SAME failed and it seems
>>> sd driver's heuristics depends on that behaviour.
>>
>> CC Christoph and Chaitanya.
> 
> And adding Martin as the sd.c Write Same code is his.
> 
> I suspect we'll have to restore the old way this works for 4.10 as it's
> too late in the cycle, but that whole idea of trying Write Same first
> and just disabling it if it doesn't work is a receipe for desaster -
> it kinda works for a synchronous blkdev_issue_zeroout, but if we want
> to be able to submit it asynchronously it's getting too hairy to handle.

I agree, the current approach is a hot and ugly mess.

> I think we should fix sd.c to only send WRITE SAME if either of the
> variants are explicitly listed as supported through
> REPORT SUPPORTED OPERATION CODES, or maybe through a whitelist if
> there are important enough devices.

Yep

-- 
Jens Axboe

^ permalink raw reply

* Re: [REGRESSION v4.10-rc1] blkdev_issue_zeroout() returns -EREMOTEIO on the first call for SCSI device that doesn't support WRITE SAME
From: Christoph Hellwig @ 2017-02-03 16:12 UTC (permalink / raw)
  To: Jens Axboe
  Cc: Junichi Nomura, linux-block@vger.kernel.org, linux-scsi,
	Christoph Hellwig, Chaitanya Kulkarni, Martin K. Petersen
In-Reply-To: <d360a634-2c95-2de5-8647-4e740e92e10a@kernel.dk>

On Fri, Feb 03, 2017 at 08:21:31AM -0700, Jens Axboe wrote:
> > Error 121 (EREMOTEIO) was returned from blkdev_issue_zeroout().
> > That came from sd driver because WRITE SAME was sent to the device
> > which didn't support it.
> > 
> > The problem was introduced by commit e73c23ff736e ("block: add async
> > variant of blkdev_issue_zeroout"). Before the commit, blkdev_issue_zeroout
> > fell back to normal zero writing when WRITE SAME failed and it seems
> > sd driver's heuristics depends on that behaviour.
> 
> CC Christoph and Chaitanya.

And adding Martin as the sd.c Write Same code is his.

I suspect we'll have to restore the old way this works for 4.10 as it's
too late in the cycle, but that whole idea of trying Write Same first
and just disabling it if it doesn't work is a receipe for desaster -
it kinda works for a synchronous blkdev_issue_zeroout, but if we want
to be able to submit it asynchronously it's getting too hairy to handle.

I think we should fix sd.c to only send WRITE SAME if either of the
variants are explicitly listed as supported through
REPORT SUPPORTED OPERATION CODES, or maybe through a whitelist if
there are important enough devices.

^ permalink raw reply

* Re: [PATCH RESEND] blkcg: fix double free of new_blkg in blkcg_init_queue
From: Jens Axboe @ 2017-02-03 15:25 UTC (permalink / raw)
  To: Hou Tao, linux-block; +Cc: tj
In-Reply-To: <1486113547-43833-1-git-send-email-houtao1@huawei.com>

On 02/03/2017 02:19 AM, Hou Tao wrote:
> If blkg_create fails, new_blkg passed as an argument will
> be freed by blkg_create, so there is no need to free it again.

Thanks, looks good to me. Applied.

-- 
Jens Axboe

^ permalink raw reply

* Re: [REGRESSION v4.10-rc1] blkdev_issue_zeroout() returns -EREMOTEIO on the first call for SCSI device that doesn't support WRITE SAME
From: Jens Axboe @ 2017-02-03 15:21 UTC (permalink / raw)
  To: Junichi Nomura, linux-block@vger.kernel.org, linux-scsi
  Cc: Christoph Hellwig, Chaitanya Kulkarni
In-Reply-To: <cc14c28a-0f0a-640a-b576-cdfbaee75dc5@ce.jp.nec.com>

On 02/03/2017 12:55 AM, Junichi Nomura wrote:
> I found following ext4 error occurs on a certain storage since v4.10-rc1:
>   EXT4-fs (sdc1): Delayed block allocation failed for inode 12 at logical offset 100 with max blocks 2 with error 121
>   EXT4-fs (sdc1): This should not happen!! Data will be lost
> 
> Error 121 (EREMOTEIO) was returned from blkdev_issue_zeroout().
> That came from sd driver because WRITE SAME was sent to the device
> which didn't support it.
> 
> The problem was introduced by commit e73c23ff736e ("block: add async
> variant of blkdev_issue_zeroout"). Before the commit, blkdev_issue_zeroout
> fell back to normal zero writing when WRITE SAME failed and it seems
> sd driver's heuristics depends on that behaviour.

CC Christoph and Chaitanya.

-- 
Jens Axboe

^ permalink raw reply

* [PATCH 6/6] nvme: allocate queues for all possible CPUs
From: Christoph Hellwig @ 2017-02-03 14:36 UTC (permalink / raw)
  To: Thomas Gleixner, Jens Axboe
  Cc: Keith Busch, linux-nvme, linux-block, linux-kernel
In-Reply-To: <20170203143600.32307-1-hch@lst.de>

Unlike most drіvers that simply pass the maximum possible vectors to
pci_alloc_irq_vectors NVMe needs to configure the device before allocting
the vectors, so it needs a manual update for the new scheme of using
all present CPUs.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 drivers/nvme/host/pci.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 032237c7ee56..3eaafa25b4fd 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -1405,7 +1405,7 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
 	struct pci_dev *pdev = to_pci_dev(dev->dev);
 	int result, nr_io_queues, size;
 
-	nr_io_queues = num_online_cpus();
+	nr_io_queues = num_present_cpus();
 	result = nvme_set_queue_count(&dev->ctrl, &nr_io_queues);
 	if (result < 0)
 		return result;
-- 
2.11.0

^ permalink raw reply related

* [PATCH 5/6] blk-mq: create hctx for each present CPU
From: Christoph Hellwig @ 2017-02-03 14:35 UTC (permalink / raw)
  To: Thomas Gleixner, Jens Axboe
  Cc: Keith Busch, linux-nvme, linux-block, linux-kernel
In-Reply-To: <20170203143600.32307-1-hch@lst.de>

Currently we only create hctx for online CPUs, which can lead to a lot
of churn due to frequent soft offline / online operations.  Instead
allocate one for each present CPU to avoid this and dramatically simplify
the code.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 block/blk-mq-sysfs.c       |  26 +++------
 block/blk-mq.c             | 137 +++++----------------------------------------
 block/blk-mq.h             |   5 --
 include/linux/cpuhotplug.h |   1 -
 4 files changed, 20 insertions(+), 149 deletions(-)

diff --git a/block/blk-mq-sysfs.c b/block/blk-mq-sysfs.c
index 295e69670c39..c69ec94a2ad8 100644
--- a/block/blk-mq-sysfs.c
+++ b/block/blk-mq-sysfs.c
@@ -239,7 +239,7 @@ static int blk_mq_register_hctx(struct blk_mq_hw_ctx *hctx)
 	return ret;
 }
 
-static void __blk_mq_unregister_dev(struct device *dev, struct request_queue *q)
+void blk_mq_unregister_dev(struct device *dev, struct request_queue *q)
 {
 	struct blk_mq_hw_ctx *hctx;
 	struct blk_mq_ctx *ctx;
@@ -265,13 +265,6 @@ static void __blk_mq_unregister_dev(struct device *dev, struct request_queue *q)
 	q->mq_sysfs_init_done = false;
 }
 
-void blk_mq_unregister_dev(struct device *dev, struct request_queue *q)
-{
-	blk_mq_disable_hotplug();
-	__blk_mq_unregister_dev(dev, q);
-	blk_mq_enable_hotplug();
-}
-
 void blk_mq_hctx_kobj_init(struct blk_mq_hw_ctx *hctx)
 {
 	kobject_init(&hctx->kobj, &blk_mq_hw_ktype);
@@ -295,13 +288,11 @@ int blk_mq_register_dev(struct device *dev, struct request_queue *q)
 	struct blk_mq_hw_ctx *hctx;
 	int ret, i;
 
-	blk_mq_disable_hotplug();
-
 	blk_mq_sysfs_init(q);
 
 	ret = kobject_add(&q->mq_kobj, kobject_get(&dev->kobj), "%s", "mq");
 	if (ret < 0)
-		goto out;
+		return ret;
 
 	kobject_uevent(&q->mq_kobj, KOBJ_ADD);
 
@@ -310,16 +301,13 @@ int blk_mq_register_dev(struct device *dev, struct request_queue *q)
 	queue_for_each_hw_ctx(q, hctx, i) {
 		ret = blk_mq_register_hctx(hctx);
 		if (ret)
-			break;
+			goto fail;
 	}
 
-	if (ret)
-		__blk_mq_unregister_dev(dev, q);
-	else
-		q->mq_sysfs_init_done = true;
-out:
-	blk_mq_enable_hotplug();
-
+	q->mq_sysfs_init_done = true;
+	return 0;
+fail:
+	blk_mq_unregister_dev(dev, q);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(blk_mq_register_dev);
diff --git a/block/blk-mq.c b/block/blk-mq.c
index be183e6115a1..3578d678a871 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -34,9 +34,6 @@
 #include "blk-wbt.h"
 #include "blk-mq-sched.h"
 
-static DEFINE_MUTEX(all_q_mutex);
-static LIST_HEAD(all_q_list);
-
 /*
  * Check if any of the ctx's have pending work in this hardware queue
  */
@@ -1948,8 +1945,8 @@ static void blk_mq_init_cpu_queues(struct request_queue *q,
 		blk_stat_init(&__ctx->stat[BLK_STAT_READ]);
 		blk_stat_init(&__ctx->stat[BLK_STAT_WRITE]);
 
-		/* If the cpu isn't online, the cpu is mapped to first hctx */
-		if (!cpu_online(i))
+		/* If the cpu isn't present, the cpu is mapped to first hctx */
+		if (!cpu_present(i))
 			continue;
 
 		hctx = blk_mq_map_queue(q, i);
@@ -1992,8 +1989,7 @@ static void blk_mq_free_map_and_requests(struct blk_mq_tag_set *set,
 	}
 }
 
-static void blk_mq_map_swqueue(struct request_queue *q,
-			       const struct cpumask *online_mask)
+static void blk_mq_map_swqueue(struct request_queue *q)
 {
 	unsigned int i, hctx_idx;
 	struct blk_mq_hw_ctx *hctx;
@@ -2011,13 +2007,11 @@ static void blk_mq_map_swqueue(struct request_queue *q,
 	}
 
 	/*
-	 * Map software to hardware queues
+	 * Map software to hardware queues.
+	 *
+	 * If the cpu isn't present, the cpu is mapped to first hctx.
 	 */
-	for_each_possible_cpu(i) {
-		/* If the cpu isn't online, the cpu is mapped to first hctx */
-		if (!cpumask_test_cpu(i, online_mask))
-			continue;
-
+	for_each_present_cpu(i) {
 		hctx_idx = q->mq_map[i];
 		/* unmapped hw queue can be remapped after CPU topo changed */
 		if (!set->tags[hctx_idx] &&
@@ -2293,16 +2287,8 @@ struct request_queue *blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
 		blk_queue_softirq_done(q, set->ops->complete);
 
 	blk_mq_init_cpu_queues(q, set->nr_hw_queues);
-
-	get_online_cpus();
-	mutex_lock(&all_q_mutex);
-
-	list_add_tail(&q->all_q_node, &all_q_list);
 	blk_mq_add_queue_tag_set(set, q);
-	blk_mq_map_swqueue(q, cpu_online_mask);
-
-	mutex_unlock(&all_q_mutex);
-	put_online_cpus();
+	blk_mq_map_swqueue(q);
 
 	if (!(set->flags & BLK_MQ_F_NO_SCHED)) {
 		int ret;
@@ -2328,10 +2314,6 @@ void blk_mq_free_queue(struct request_queue *q)
 {
 	struct blk_mq_tag_set	*set = q->tag_set;
 
-	mutex_lock(&all_q_mutex);
-	list_del_init(&q->all_q_node);
-	mutex_unlock(&all_q_mutex);
-
 	wbt_exit(q);
 
 	blk_mq_del_queue_tag_set(q);
@@ -2340,89 +2322,6 @@ void blk_mq_free_queue(struct request_queue *q)
 	blk_mq_free_hw_queues(q, set);
 }
 
-/* Basically redo blk_mq_init_queue with queue frozen */
-static void blk_mq_queue_reinit(struct request_queue *q,
-				const struct cpumask *online_mask)
-{
-	WARN_ON_ONCE(!atomic_read(&q->mq_freeze_depth));
-
-	blk_mq_sysfs_unregister(q);
-
-	/*
-	 * redo blk_mq_init_cpu_queues and blk_mq_init_hw_queues. FIXME: maybe
-	 * we should change hctx numa_node according to new topology (this
-	 * involves free and re-allocate memory, worthy doing?)
-	 */
-
-	blk_mq_map_swqueue(q, online_mask);
-
-	blk_mq_sysfs_register(q);
-}
-
-/*
- * New online cpumask which is going to be set in this hotplug event.
- * Declare this cpumasks as global as cpu-hotplug operation is invoked
- * one-by-one and dynamically allocating this could result in a failure.
- */
-static struct cpumask cpuhp_online_new;
-
-static void blk_mq_queue_reinit_work(void)
-{
-	struct request_queue *q;
-
-	mutex_lock(&all_q_mutex);
-	/*
-	 * We need to freeze and reinit all existing queues.  Freezing
-	 * involves synchronous wait for an RCU grace period and doing it
-	 * one by one may take a long time.  Start freezing all queues in
-	 * one swoop and then wait for the completions so that freezing can
-	 * take place in parallel.
-	 */
-	list_for_each_entry(q, &all_q_list, all_q_node)
-		blk_mq_freeze_queue_start(q);
-	list_for_each_entry(q, &all_q_list, all_q_node)
-		blk_mq_freeze_queue_wait(q);
-
-	list_for_each_entry(q, &all_q_list, all_q_node)
-		blk_mq_queue_reinit(q, &cpuhp_online_new);
-
-	list_for_each_entry(q, &all_q_list, all_q_node)
-		blk_mq_unfreeze_queue(q);
-
-	mutex_unlock(&all_q_mutex);
-}
-
-static int blk_mq_queue_reinit_dead(unsigned int cpu)
-{
-	cpumask_copy(&cpuhp_online_new, cpu_online_mask);
-	blk_mq_queue_reinit_work();
-	return 0;
-}
-
-/*
- * Before hotadded cpu starts handling requests, new mappings must be
- * established.  Otherwise, these requests in hw queue might never be
- * dispatched.
- *
- * For example, there is a single hw queue (hctx) and two CPU queues (ctx0
- * for CPU0, and ctx1 for CPU1).
- *
- * Now CPU1 is just onlined and a request is inserted into ctx1->rq_list
- * and set bit0 in pending bitmap as ctx1->index_hw is still zero.
- *
- * And then while running hw queue, blk_mq_flush_busy_ctxs() finds bit0 is set
- * in pending bitmap and tries to retrieve requests in hctx->ctxs[0]->rq_list.
- * But htx->ctxs[0] is a pointer to ctx0, so the request in ctx1->rq_list is
- * ignored.
- */
-static int blk_mq_queue_reinit_prepare(unsigned int cpu)
-{
-	cpumask_copy(&cpuhp_online_new, cpu_online_mask);
-	cpumask_set_cpu(cpu, &cpuhp_online_new);
-	blk_mq_queue_reinit_work();
-	return 0;
-}
-
 static int __blk_mq_alloc_rq_maps(struct blk_mq_tag_set *set)
 {
 	int i;
@@ -2632,7 +2531,11 @@ void blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, int nr_hw_queues)
 		else
 			blk_queue_make_request(q, blk_sq_make_request);
 
-		blk_mq_queue_reinit(q, cpu_online_mask);
+		/* Basically redo blk_mq_init_queue with queue frozen */
+		WARN_ON_ONCE(!atomic_read(&q->mq_freeze_depth));
+		blk_mq_sysfs_unregister(q);
+		blk_mq_map_swqueue(q);
+		blk_mq_sysfs_register(q);
 	}
 
 	list_for_each_entry(q, &set->tag_list, tag_set_list)
@@ -2802,24 +2705,10 @@ bool blk_mq_poll(struct request_queue *q, blk_qc_t cookie)
 }
 EXPORT_SYMBOL_GPL(blk_mq_poll);
 
-void blk_mq_disable_hotplug(void)
-{
-	mutex_lock(&all_q_mutex);
-}
-
-void blk_mq_enable_hotplug(void)
-{
-	mutex_unlock(&all_q_mutex);
-}
-
 static int __init blk_mq_init(void)
 {
 	cpuhp_setup_state_multi(CPUHP_BLK_MQ_DEAD, "block/mq:dead", NULL,
 				blk_mq_hctx_notify_dead);
-
-	cpuhp_setup_state_nocalls(CPUHP_BLK_MQ_PREPARE, "block/mq:prepare",
-				  blk_mq_queue_reinit_prepare,
-				  blk_mq_queue_reinit_dead);
 	return 0;
 }
 subsys_initcall(blk_mq_init);
diff --git a/block/blk-mq.h b/block/blk-mq.h
index 24b2256186f3..0d77b914d29f 100644
--- a/block/blk-mq.h
+++ b/block/blk-mq.h
@@ -57,11 +57,6 @@ void __blk_mq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
 				bool at_head);
 void blk_mq_insert_requests(struct blk_mq_hw_ctx *hctx, struct blk_mq_ctx *ctx,
 				struct list_head *list);
-/*
- * CPU hotplug helpers
- */
-void blk_mq_enable_hotplug(void);
-void blk_mq_disable_hotplug(void);
 
 /*
  * CPU -> queue mappings
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
index 63406ae5b2df..992a09a297da 100644
--- a/include/linux/cpuhotplug.h
+++ b/include/linux/cpuhotplug.h
@@ -61,7 +61,6 @@ enum cpuhp_state {
 	CPUHP_XEN_EVTCHN_PREPARE,
 	CPUHP_ARM_SHMOBILE_SCU_PREPARE,
 	CPUHP_SH_SH3X_PREPARE,
-	CPUHP_BLK_MQ_PREPARE,
 	CPUHP_NET_FLOW_PREPARE,
 	CPUHP_TOPOLOGY_PREPARE,
 	CPUHP_NET_IUCV_PREPARE,
-- 
2.11.0

^ permalink raw reply related

* [PATCH 4/6] blk-mq: include all present CPUs in the default queue mapping
From: Christoph Hellwig @ 2017-02-03 14:35 UTC (permalink / raw)
  To: Thomas Gleixner, Jens Axboe
  Cc: Keith Busch, linux-nvme, linux-block, linux-kernel
In-Reply-To: <20170203143600.32307-1-hch@lst.de>

This way we get a nice distribution independent of the current cpu
online / offline state.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 block/blk-mq-cpumap.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/block/blk-mq-cpumap.c b/block/blk-mq-cpumap.c
index 8e61e8640e17..5eaecd40f701 100644
--- a/block/blk-mq-cpumap.c
+++ b/block/blk-mq-cpumap.c
@@ -35,7 +35,6 @@ int blk_mq_map_queues(struct blk_mq_tag_set *set)
 {
 	unsigned int *map = set->mq_map;
 	unsigned int nr_queues = set->nr_hw_queues;
-	const struct cpumask *online_mask = cpu_online_mask;
 	unsigned int i, nr_cpus, nr_uniq_cpus, queue, first_sibling;
 	cpumask_var_t cpus;
 
@@ -44,7 +43,7 @@ int blk_mq_map_queues(struct blk_mq_tag_set *set)
 
 	cpumask_clear(cpus);
 	nr_cpus = nr_uniq_cpus = 0;
-	for_each_cpu(i, online_mask) {
+	for_each_present_cpu(i) {
 		nr_cpus++;
 		first_sibling = get_first_sibling(i);
 		if (!cpumask_test_cpu(first_sibling, cpus))
@@ -54,7 +53,7 @@ int blk_mq_map_queues(struct blk_mq_tag_set *set)
 
 	queue = 0;
 	for_each_possible_cpu(i) {
-		if (!cpumask_test_cpu(i, online_mask)) {
+		if (!cpumask_test_cpu(i, cpu_present_mask)) {
 			map[i] = 0;
 			continue;
 		}
-- 
2.11.0

^ permalink raw reply related

* [PATCH 3/6] genirq/affinity: update CPU affinity for CPU hotplug events
From: Christoph Hellwig @ 2017-02-03 14:35 UTC (permalink / raw)
  To: Thomas Gleixner, Jens Axboe
  Cc: Keith Busch, linux-nvme, linux-block, linux-kernel
In-Reply-To: <20170203143600.32307-1-hch@lst.de>

Remove a CPU from the affinity mask when it goes offline and add it
back when it returns.  In case the vetor was assigned only to the CPU
going offline it will be shutdown and re-started when the CPU
reappears.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 arch/x86/kernel/irq.c      |   3 +-
 include/linux/cpuhotplug.h |   1 +
 include/linux/irq.h        |   9 +++
 kernel/cpu.c               |   6 ++
 kernel/irq/affinity.c      | 157 ++++++++++++++++++++++++++++++++++++++++++++-
 5 files changed, 174 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c
index 7c6e9ffe4424..285ef40ae290 100644
--- a/arch/x86/kernel/irq.c
+++ b/arch/x86/kernel/irq.c
@@ -449,7 +449,8 @@ void fixup_irqs(void)
 
 		data = irq_desc_get_irq_data(desc);
 		affinity = irq_data_get_affinity_mask(data);
-		if (!irq_has_action(irq) || irqd_is_per_cpu(data) ||
+		if (irqd_affinity_is_managed(data) ||
+		    !irq_has_action(irq) || irqd_is_per_cpu(data) ||
 		    cpumask_subset(affinity, cpu_online_mask)) {
 			raw_spin_unlock(&desc->lock);
 			continue;
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
index d936a0021839..63406ae5b2df 100644
--- a/include/linux/cpuhotplug.h
+++ b/include/linux/cpuhotplug.h
@@ -127,6 +127,7 @@ enum cpuhp_state {
 	CPUHP_AP_ONLINE_IDLE,
 	CPUHP_AP_SMPBOOT_THREADS,
 	CPUHP_AP_X86_VDSO_VMA_ONLINE,
+	CPUHP_AP_IRQ_AFFINIY_ONLINE,
 	CPUHP_AP_PERF_ONLINE,
 	CPUHP_AP_PERF_X86_ONLINE,
 	CPUHP_AP_PERF_X86_UNCORE_ONLINE,
diff --git a/include/linux/irq.h b/include/linux/irq.h
index e79875574b39..4b2a542b2591 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -214,6 +214,7 @@ enum {
 	IRQD_WAKEUP_ARMED		= (1 << 19),
 	IRQD_FORWARDED_TO_VCPU		= (1 << 20),
 	IRQD_AFFINITY_MANAGED		= (1 << 21),
+	IRQD_AFFINITY_SUSPENDED		= (1 << 22),
 };
 
 #define __irqd_to_state(d) ACCESS_PRIVATE((d)->common, state_use_accessors)
@@ -312,6 +313,11 @@ static inline bool irqd_affinity_is_managed(struct irq_data *d)
 	return __irqd_to_state(d) & IRQD_AFFINITY_MANAGED;
 }
 
+static inline bool irqd_affinity_is_suspended(struct irq_data *d)
+{
+	return __irqd_to_state(d) & IRQD_AFFINITY_SUSPENDED;
+}
+
 #undef __irqd_to_state
 
 static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d)
@@ -989,4 +995,7 @@ int __ipi_send_mask(struct irq_desc *desc, const struct cpumask *dest);
 int ipi_send_single(unsigned int virq, unsigned int cpu);
 int ipi_send_mask(unsigned int virq, const struct cpumask *dest);
 
+int irq_affinity_online_cpu(unsigned int cpu);
+int irq_affinity_offline_cpu(unsigned int cpu);
+
 #endif /* _LINUX_IRQ_H */
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 0a5f630f5c54..fe19af6a896b 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -25,6 +25,7 @@
 #include <linux/smpboot.h>
 #include <linux/relay.h>
 #include <linux/slab.h>
+#include <linux/irq.h>
 
 #include <trace/events/power.h>
 #define CREATE_TRACE_POINTS
@@ -1248,6 +1249,11 @@ static struct cpuhp_step cpuhp_ap_states[] = {
 		.startup.single		= smpboot_unpark_threads,
 		.teardown.single	= NULL,
 	},
+	[CPUHP_AP_IRQ_AFFINIY_ONLINE] = {
+		.name			= "irq/affinity:online",
+		.startup.single		= irq_affinity_online_cpu,
+		.teardown.single	= irq_affinity_offline_cpu,
+	},
 	[CPUHP_AP_PERF_ONLINE] = {
 		.name			= "perf:online",
 		.startup.single		= perf_event_init_cpu,
diff --git a/kernel/irq/affinity.c b/kernel/irq/affinity.c
index 6cd20a569359..74006167892d 100644
--- a/kernel/irq/affinity.c
+++ b/kernel/irq/affinity.c
@@ -1,8 +1,12 @@
-
+/*
+ * Copyright (C) 2016 Thomas Gleixner.
+ * Copyright (C) 2016-2017 Christoph Hellwig.
+ */
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/cpu.h>
+#include "internals.h"
 
 static cpumask_var_t node_to_present_cpumask[MAX_NUMNODES] __read_mostly;
 
@@ -148,6 +152,157 @@ int irq_calc_affinity_vectors(int maxvec, const struct irq_affinity *affd)
 	return min_t(int, cpumask_weight(cpu_present_mask), vecs) + resv;
 }
 
+static void __irq_affinity_set(unsigned int irq, struct irq_desc *desc,
+		cpumask_t *mask)
+{
+	struct irq_data *data = irq_desc_get_irq_data(desc);
+	struct irq_chip *chip = irq_data_get_irq_chip(data);
+	int ret;
+
+	if (!irqd_can_move_in_process_context(data) && chip->irq_mask)
+		chip->irq_mask(data);
+	ret = chip->irq_set_affinity(data, mask, true);
+	WARN_ON_ONCE(ret);
+
+	/*
+	 * We unmask if the irq was not marked masked by the core code.
+	 * That respects the lazy irq disable behaviour.
+	 */
+	if (!irqd_can_move_in_process_context(data) &&
+	    !irqd_irq_masked(data) && chip->irq_unmask)
+		chip->irq_unmask(data);
+}
+
+static void irq_affinity_online_irq(unsigned int irq, struct irq_desc *desc,
+		unsigned int cpu)
+{
+	const struct cpumask *affinity;
+	struct irq_data *data;
+	struct irq_chip *chip;
+	unsigned long flags;
+	cpumask_var_t mask;
+
+	if (!desc)
+		return;
+
+	raw_spin_lock_irqsave(&desc->lock, flags);
+
+	data = irq_desc_get_irq_data(desc);
+	affinity = irq_data_get_affinity_mask(data);
+	if (!irqd_affinity_is_managed(data) ||
+	    !irq_has_action(irq) ||
+	    !cpumask_test_cpu(cpu, affinity))
+		goto out_unlock;
+
+	/*
+	 * The interrupt descriptor might have been cleaned up
+	 * already, but it is not yet removed from the radix tree
+	 */
+	chip = irq_data_get_irq_chip(data);
+	if (!chip)
+		goto out_unlock;
+
+	if (WARN_ON_ONCE(!chip->irq_set_affinity))
+		goto out_unlock;
+
+	if (!zalloc_cpumask_var(&mask, GFP_KERNEL)) {
+		pr_err("failed to allocate memory for cpumask\n");
+		goto out_unlock;
+	}
+
+	cpumask_and(mask, affinity, cpu_online_mask);
+	cpumask_set_cpu(cpu, mask);
+	if (irqd_has_set(data, IRQD_AFFINITY_SUSPENDED)) {
+		irq_startup(desc, false);
+		irqd_clear(data, IRQD_AFFINITY_SUSPENDED);
+	} else {
+		__irq_affinity_set(irq, desc, mask);
+	}
+
+	free_cpumask_var(mask);
+out_unlock:
+	raw_spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+int irq_affinity_online_cpu(unsigned int cpu)
+{
+	struct irq_desc *desc;
+	unsigned int irq;
+
+	for_each_irq_desc(irq, desc)
+		irq_affinity_online_irq(irq, desc, cpu);
+	return 0;
+}
+
+static void irq_affinity_offline_irq(unsigned int irq, struct irq_desc *desc,
+		unsigned int cpu)
+{
+	const struct cpumask *affinity;
+	struct irq_data *data;
+	struct irq_chip *chip;
+	unsigned long flags;
+	cpumask_var_t mask;
+
+	if (!desc)
+		return;
+
+	raw_spin_lock_irqsave(&desc->lock, flags);
+
+	data = irq_desc_get_irq_data(desc);
+	affinity = irq_data_get_affinity_mask(data);
+	if (!irqd_affinity_is_managed(data) ||
+	    !irq_has_action(irq) ||
+	    irqd_has_set(data, IRQD_AFFINITY_SUSPENDED) ||
+	    !cpumask_test_cpu(cpu, affinity))
+		goto out_unlock;
+
+	/*
+	 * Complete the irq move. This cpu is going down and for
+	 * non intr-remapping case, we can't wait till this interrupt
+	 * arrives at this cpu before completing the irq move.
+	 */
+	irq_force_complete_move(desc);
+
+	/*
+	 * The interrupt descriptor might have been cleaned up
+	 * already, but it is not yet removed from the radix tree
+	 */
+	chip = irq_data_get_irq_chip(data);
+	if (!chip)
+		goto out_unlock;
+
+	if (WARN_ON_ONCE(!chip->irq_set_affinity))
+		goto out_unlock;
+
+	if (!zalloc_cpumask_var(&mask, GFP_KERNEL)) {
+		pr_err("failed to allocate memory for cpumask\n");
+		goto out_unlock;
+	}
+
+	cpumask_copy(mask, affinity);
+	cpumask_clear_cpu(cpu, mask);
+	if (cpumask_empty(mask)) {
+		irqd_set(data, IRQD_AFFINITY_SUSPENDED);
+		irq_shutdown(desc);
+	} else {
+		__irq_affinity_set(irq, desc, mask);
+	}
+
+	free_cpumask_var(mask);
+out_unlock:
+	raw_spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+int irq_affinity_offline_cpu(unsigned int cpu)
+{
+	struct irq_desc *desc;
+	unsigned int irq;
+
+	for_each_irq_desc(irq, desc)
+		irq_affinity_offline_irq(irq, desc, cpu);
+	return 0;
+}
+
 static int __init irq_build_cpumap(void)
 {
 	int node, cpu;
-- 
2.11.0

^ permalink raw reply related

* [PATCH 2/6] genirq/affinity: assign vectors to all present CPUs
From: Christoph Hellwig @ 2017-02-03 14:35 UTC (permalink / raw)
  To: Thomas Gleixner, Jens Axboe
  Cc: Keith Busch, linux-nvme, linux-block, linux-kernel
In-Reply-To: <20170203143600.32307-1-hch@lst.de>

Currently we only assign spread vectors to online CPUs, which ties the
IRQ mapping to the currently online devices and doesn't deal nicely with
the fact that CPUs could come and go rapidly due to e.g. power management.

Instead assign vectors to all present CPUs to avoid this churn.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 kernel/irq/affinity.c | 43 ++++++++++++++++++++++++++++---------------
 1 file changed, 28 insertions(+), 15 deletions(-)

diff --git a/kernel/irq/affinity.c b/kernel/irq/affinity.c
index 4544b115f5eb..6cd20a569359 100644
--- a/kernel/irq/affinity.c
+++ b/kernel/irq/affinity.c
@@ -4,6 +4,8 @@
 #include <linux/slab.h>
 #include <linux/cpu.h>
 
+static cpumask_var_t node_to_present_cpumask[MAX_NUMNODES] __read_mostly;
+
 static void irq_spread_init_one(struct cpumask *irqmsk, struct cpumask *nmsk,
 				int cpus_per_vec)
 {
@@ -40,8 +42,8 @@ static int get_nodes_in_cpumask(const struct cpumask *mask, nodemask_t *nodemsk)
 	int n, nodes = 0;
 
 	/* Calculate the number of nodes in the supplied affinity mask */
-	for_each_online_node(n) {
-		if (cpumask_intersects(mask, cpumask_of_node(n))) {
+	for_each_node(n) {
+		if (cpumask_intersects(mask, node_to_present_cpumask[n])) {
 			node_set(n, *nodemsk);
 			nodes++;
 		}
@@ -77,9 +79,7 @@ irq_create_affinity_masks(int nvecs, const struct irq_affinity *affd)
 	for (curvec = 0; curvec < affd->pre_vectors; curvec++)
 		cpumask_copy(masks + curvec, irq_default_affinity);
 
-	/* Stabilize the cpumasks */
-	get_online_cpus();
-	nodes = get_nodes_in_cpumask(cpu_online_mask, &nodemsk);
+	nodes = get_nodes_in_cpumask(cpu_present_mask, &nodemsk);
 
 	/*
 	 * If the number of nodes in the mask is greater than or equal the
@@ -87,7 +87,8 @@ irq_create_affinity_masks(int nvecs, const struct irq_affinity *affd)
 	 */
 	if (affv <= nodes) {
 		for_each_node_mask(n, nodemsk) {
-			cpumask_copy(masks + curvec, cpumask_of_node(n));
+			cpumask_copy(masks + curvec,
+				     node_to_present_cpumask[n]);
 			if (++curvec == last_affv)
 				break;
 		}
@@ -103,7 +104,7 @@ irq_create_affinity_masks(int nvecs, const struct irq_affinity *affd)
 		int ncpus, v, vecs_to_assign = vecs_per_node;
 
 		/* Get the cpus on this node which are in the mask */
-		cpumask_and(nmsk, cpu_online_mask, cpumask_of_node(n));
+		cpumask_and(nmsk, cpu_present_mask, node_to_present_cpumask[n]);
 
 		/* Calculate the number of cpus per vector */
 		ncpus = cpumask_weight(nmsk);
@@ -126,8 +127,6 @@ irq_create_affinity_masks(int nvecs, const struct irq_affinity *affd)
 	}
 
 done:
-	put_online_cpus();
-
 	/* Fill out vectors at the end that don't need affinity */
 	for (; curvec < nvecs; curvec++)
 		cpumask_copy(masks + curvec, irq_default_affinity);
@@ -145,12 +144,26 @@ int irq_calc_affinity_vectors(int maxvec, const struct irq_affinity *affd)
 {
 	int resv = affd->pre_vectors + affd->post_vectors;
 	int vecs = maxvec - resv;
-	int cpus;
 
-	/* Stabilize the cpumasks */
-	get_online_cpus();
-	cpus = cpumask_weight(cpu_online_mask);
-	put_online_cpus();
+	return min_t(int, cpumask_weight(cpu_present_mask), vecs) + resv;
+}
+
+static int __init irq_build_cpumap(void)
+{
+	int node, cpu;
+
+	for (node = 0; node < nr_node_ids; node++) {
+		if (!zalloc_cpumask_var(&node_to_present_cpumask[node],
+				GFP_KERNEL))
+			panic("can't allocate early memory\n");
+	}
 
-	return min(cpus, vecs) + resv;
+	for_each_present_cpu(cpu) {
+		node = cpu_to_node(cpu);
+		cpumask_set_cpu(cpu, node_to_present_cpumask[node]);
+	}
+
+	return 0;
 }
+
+subsys_initcall(irq_build_cpumap);
-- 
2.11.0

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox