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

Commit 6f6b5d1e authored by Kent Overstreet's avatar Kent Overstreet Committed by Nicholas Bellinger
Browse files

percpu_ida: Make percpu_ida_alloc + callers accept task state bitmask



This patch changes percpu_ida_alloc() + callers to accept task state
bitmask for prepare_to_wait() for code like target/iscsi that needs
it for interruptible sleep, that is provided in a subsequent patch.

It now expects TASK_UNINTERRUPTIBLE when the caller is able to sleep
waiting for a new tag, or TASK_RUNNING when the caller cannot sleep,
and is forced to return a negative value when no tags are available.

v2 changes:
  - Include blk-mq + tcm_fc + vhost/scsi + target/iscsi changes
  - Drop signal_pending_state() call
v3 changes:
  - Only call prepare_to_wait() + finish_wait() when != TASK_RUNNING
    (PeterZ)

Reported-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Jens Axboe <axboe@kernel.dk>
Signed-off-by: default avatarKent Overstreet <kmo@daterainc.com>
Cc: <stable@vger.kernel.org> #3.12+
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
parent 4a4caa29
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -36,7 +36,8 @@ static unsigned int __blk_mq_get_tag(struct blk_mq_tags *tags, gfp_t gfp)
{
	int tag;

	tag = percpu_ida_alloc(&tags->free_tags, gfp);
	tag = percpu_ida_alloc(&tags->free_tags, (gfp & __GFP_WAIT) ?
			       TASK_UNINTERRUPTIBLE : TASK_RUNNING);
	if (tag < 0)
		return BLK_MQ_TAG_FAIL;
	return tag + tags->nr_reserved_tags;
@@ -52,7 +53,8 @@ static unsigned int __blk_mq_get_reserved_tag(struct blk_mq_tags *tags,
		return BLK_MQ_TAG_FAIL;
	}

	tag = percpu_ida_alloc(&tags->reserved_tags, gfp);
	tag = percpu_ida_alloc(&tags->reserved_tags, (gfp & __GFP_WAIT) ?
			       TASK_UNINTERRUPTIBLE : TASK_RUNNING);
	if (tag < 0)
		return BLK_MQ_TAG_FAIL;
	return tag;
+6 −2
Original line number Diff line number Diff line
@@ -156,9 +156,13 @@ struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *conn, gfp_t gfp_mask)
{
	struct iscsi_cmd *cmd;
	struct se_session *se_sess = conn->sess->se_sess;
	int size, tag;
	int size, tag, state = (gfp_mask & __GFP_WAIT) ? TASK_UNINTERRUPTIBLE :
				TASK_RUNNING;

	tag = percpu_ida_alloc(&se_sess->sess_tag_pool, state);
	if (tag < 0)
		return NULL;

	tag = percpu_ida_alloc(&se_sess->sess_tag_pool, gfp_mask);
	size = sizeof(struct iscsi_cmd) + conn->conn_transport->priv_size;
	cmd = (struct iscsi_cmd *)(se_sess->sess_cmd_map + (tag * size));
	memset(cmd, 0, size);
+1 −1
Original line number Diff line number Diff line
@@ -438,7 +438,7 @@ static void ft_recv_cmd(struct ft_sess *sess, struct fc_frame *fp)
	struct se_session *se_sess = sess->se_sess;
	int tag;

	tag = percpu_ida_alloc(&se_sess->sess_tag_pool, GFP_ATOMIC);
	tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING);
	if (tag < 0)
		goto busy;

+1 −1
Original line number Diff line number Diff line
@@ -728,7 +728,7 @@ vhost_scsi_get_tag(struct vhost_virtqueue *vq,
	}
	se_sess = tv_nexus->tvn_se_sess;

	tag = percpu_ida_alloc(&se_sess->sess_tag_pool, GFP_ATOMIC);
	tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING);
	if (tag < 0) {
		pr_err("Unable to obtain tag for tcm_vhost_cmd\n");
		return ERR_PTR(-ENOMEM);
+2 −1
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@
#include <linux/types.h>
#include <linux/bitops.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/spinlock_types.h>
#include <linux/wait.h>
#include <linux/cpumask.h>
@@ -61,7 +62,7 @@ struct percpu_ida {
/* Max size of percpu freelist, */
#define IDA_DEFAULT_PCPU_SIZE	((IDA_DEFAULT_PCPU_BATCH_MOVE * 3) / 2)

int percpu_ida_alloc(struct percpu_ida *pool, gfp_t gfp);
int percpu_ida_alloc(struct percpu_ida *pool, int state);
void percpu_ida_free(struct percpu_ida *pool, unsigned tag);

void percpu_ida_destroy(struct percpu_ida *pool);
Loading