diff options
| -rw-r--r-- | block/blk-mq-tag.c | 6 | ||||
| -rw-r--r-- | drivers/target/iscsi/iscsi_target_util.c | 8 | ||||
| -rw-r--r-- | drivers/target/tcm_fc/tfc_cmd.c | 2 | ||||
| -rw-r--r-- | drivers/vhost/scsi.c | 2 | ||||
| -rw-r--r-- | include/linux/percpu_ida.h | 3 | ||||
| -rw-r--r-- | lib/percpu_ida.c | 16 |
6 files changed, 23 insertions, 14 deletions
diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c index d64a02fb1f73..5d70edc9855f 100644 --- a/block/blk-mq-tag.c +++ b/block/blk-mq-tag.c | |||
| @@ -36,7 +36,8 @@ static unsigned int __blk_mq_get_tag(struct blk_mq_tags *tags, gfp_t gfp) | |||
| 36 | { | 36 | { |
| 37 | int tag; | 37 | int tag; |
| 38 | 38 | ||
| 39 | tag = percpu_ida_alloc(&tags->free_tags, gfp); | 39 | tag = percpu_ida_alloc(&tags->free_tags, (gfp & __GFP_WAIT) ? |
| 40 | TASK_UNINTERRUPTIBLE : TASK_RUNNING); | ||
| 40 | if (tag < 0) | 41 | if (tag < 0) |
| 41 | return BLK_MQ_TAG_FAIL; | 42 | return BLK_MQ_TAG_FAIL; |
| 42 | return tag + tags->nr_reserved_tags; | 43 | return tag + tags->nr_reserved_tags; |
| @@ -52,7 +53,8 @@ static unsigned int __blk_mq_get_reserved_tag(struct blk_mq_tags *tags, | |||
| 52 | return BLK_MQ_TAG_FAIL; | 53 | return BLK_MQ_TAG_FAIL; |
| 53 | } | 54 | } |
| 54 | 55 | ||
| 55 | tag = percpu_ida_alloc(&tags->reserved_tags, gfp); | 56 | tag = percpu_ida_alloc(&tags->reserved_tags, (gfp & __GFP_WAIT) ? |
| 57 | TASK_UNINTERRUPTIBLE : TASK_RUNNING); | ||
| 56 | if (tag < 0) | 58 | if (tag < 0) |
| 57 | return BLK_MQ_TAG_FAIL; | 59 | return BLK_MQ_TAG_FAIL; |
| 58 | return tag; | 60 | return tag; |
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index 0819e688a398..9b8e1db1257b 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c | |||
| @@ -156,9 +156,13 @@ struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *conn, gfp_t gfp_mask) | |||
| 156 | { | 156 | { |
| 157 | struct iscsi_cmd *cmd; | 157 | struct iscsi_cmd *cmd; |
| 158 | struct se_session *se_sess = conn->sess->se_sess; | 158 | struct se_session *se_sess = conn->sess->se_sess; |
| 159 | int size, tag; | 159 | int size, tag, state = (gfp_mask & __GFP_WAIT) ? TASK_UNINTERRUPTIBLE : |
| 160 | TASK_RUNNING; | ||
| 161 | |||
| 162 | tag = percpu_ida_alloc(&se_sess->sess_tag_pool, state); | ||
| 163 | if (tag < 0) | ||
| 164 | return NULL; | ||
| 160 | 165 | ||
| 161 | tag = percpu_ida_alloc(&se_sess->sess_tag_pool, gfp_mask); | ||
| 162 | size = sizeof(struct iscsi_cmd) + conn->conn_transport->priv_size; | 166 | size = sizeof(struct iscsi_cmd) + conn->conn_transport->priv_size; |
| 163 | cmd = (struct iscsi_cmd *)(se_sess->sess_cmd_map + (tag * size)); | 167 | cmd = (struct iscsi_cmd *)(se_sess->sess_cmd_map + (tag * size)); |
| 164 | memset(cmd, 0, size); | 168 | memset(cmd, 0, size); |
diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index 479ec5621a4e..8b2c1aaf81de 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c | |||
| @@ -438,7 +438,7 @@ static void ft_recv_cmd(struct ft_sess *sess, struct fc_frame *fp) | |||
| 438 | struct se_session *se_sess = sess->se_sess; | 438 | struct se_session *se_sess = sess->se_sess; |
| 439 | int tag; | 439 | int tag; |
| 440 | 440 | ||
| 441 | tag = percpu_ida_alloc(&se_sess->sess_tag_pool, GFP_ATOMIC); | 441 | tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING); |
| 442 | if (tag < 0) | 442 | if (tag < 0) |
| 443 | goto busy; | 443 | goto busy; |
| 444 | 444 | ||
diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index 84488a890b69..2d084fb8d4d3 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c | |||
| @@ -728,7 +728,7 @@ vhost_scsi_get_tag(struct vhost_virtqueue *vq, | |||
| 728 | } | 728 | } |
| 729 | se_sess = tv_nexus->tvn_se_sess; | 729 | se_sess = tv_nexus->tvn_se_sess; |
| 730 | 730 | ||
| 731 | tag = percpu_ida_alloc(&se_sess->sess_tag_pool, GFP_ATOMIC); | 731 | tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING); |
| 732 | if (tag < 0) { | 732 | if (tag < 0) { |
| 733 | pr_err("Unable to obtain tag for tcm_vhost_cmd\n"); | 733 | pr_err("Unable to obtain tag for tcm_vhost_cmd\n"); |
| 734 | return ERR_PTR(-ENOMEM); | 734 | return ERR_PTR(-ENOMEM); |
diff --git a/include/linux/percpu_ida.h b/include/linux/percpu_ida.h index 1900bd0fa639..f5cfdd6a5539 100644 --- a/include/linux/percpu_ida.h +++ b/include/linux/percpu_ida.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | #include <linux/types.h> | 4 | #include <linux/types.h> |
| 5 | #include <linux/bitops.h> | 5 | #include <linux/bitops.h> |
| 6 | #include <linux/init.h> | 6 | #include <linux/init.h> |
| 7 | #include <linux/sched.h> | ||
| 7 | #include <linux/spinlock_types.h> | 8 | #include <linux/spinlock_types.h> |
| 8 | #include <linux/wait.h> | 9 | #include <linux/wait.h> |
| 9 | #include <linux/cpumask.h> | 10 | #include <linux/cpumask.h> |
| @@ -61,7 +62,7 @@ struct percpu_ida { | |||
| 61 | /* Max size of percpu freelist, */ | 62 | /* Max size of percpu freelist, */ |
| 62 | #define IDA_DEFAULT_PCPU_SIZE ((IDA_DEFAULT_PCPU_BATCH_MOVE * 3) / 2) | 63 | #define IDA_DEFAULT_PCPU_SIZE ((IDA_DEFAULT_PCPU_BATCH_MOVE * 3) / 2) |
| 63 | 64 | ||
| 64 | int percpu_ida_alloc(struct percpu_ida *pool, gfp_t gfp); | 65 | int percpu_ida_alloc(struct percpu_ida *pool, int state); |
| 65 | void percpu_ida_free(struct percpu_ida *pool, unsigned tag); | 66 | void percpu_ida_free(struct percpu_ida *pool, unsigned tag); |
| 66 | 67 | ||
| 67 | void percpu_ida_destroy(struct percpu_ida *pool); | 68 | void percpu_ida_destroy(struct percpu_ida *pool); |
diff --git a/lib/percpu_ida.c b/lib/percpu_ida.c index 9d054bf91d0f..58b671484ac2 100644 --- a/lib/percpu_ida.c +++ b/lib/percpu_ida.c | |||
| @@ -132,22 +132,22 @@ static inline unsigned alloc_local_tag(struct percpu_ida_cpu *tags) | |||
| 132 | /** | 132 | /** |
| 133 | * percpu_ida_alloc - allocate a tag | 133 | * percpu_ida_alloc - allocate a tag |
| 134 | * @pool: pool to allocate from | 134 | * @pool: pool to allocate from |
| 135 | * @gfp: gfp flags | 135 | * @state: task state for prepare_to_wait |
| 136 | * | 136 | * |
| 137 | * Returns a tag - an integer in the range [0..nr_tags) (passed to | 137 | * Returns a tag - an integer in the range [0..nr_tags) (passed to |
| 138 | * tag_pool_init()), or otherwise -ENOSPC on allocation failure. | 138 | * tag_pool_init()), or otherwise -ENOSPC on allocation failure. |
| 139 | * | 139 | * |
| 140 | * Safe to be called from interrupt context (assuming it isn't passed | 140 | * Safe to be called from interrupt context (assuming it isn't passed |
| 141 | * __GFP_WAIT, of course). | 141 | * TASK_UNINTERRUPTIBLE, of course). |
| 142 | * | 142 | * |
| 143 | * @gfp indicates whether or not to wait until a free id is available (it's not | 143 | * @gfp indicates whether or not to wait until a free id is available (it's not |
| 144 | * used for internal memory allocations); thus if passed __GFP_WAIT we may sleep | 144 | * used for internal memory allocations); thus if passed __GFP_WAIT we may sleep |
| 145 | * however long it takes until another thread frees an id (same semantics as a | 145 | * however long it takes until another thread frees an id (same semantics as a |
| 146 | * mempool). | 146 | * mempool). |
| 147 | * | 147 | * |
| 148 | * Will not fail if passed __GFP_WAIT. | 148 | * Will not fail if passed TASK_UNINTERRUPTIBLE. |
| 149 | */ | 149 | */ |
| 150 | int percpu_ida_alloc(struct percpu_ida *pool, gfp_t gfp) | 150 | int percpu_ida_alloc(struct percpu_ida *pool, int state) |
| 151 | { | 151 | { |
| 152 | DEFINE_WAIT(wait); | 152 | DEFINE_WAIT(wait); |
| 153 | struct percpu_ida_cpu *tags; | 153 | struct percpu_ida_cpu *tags; |
| @@ -174,7 +174,8 @@ int percpu_ida_alloc(struct percpu_ida *pool, gfp_t gfp) | |||
| 174 | * | 174 | * |
| 175 | * global lock held and irqs disabled, don't need percpu lock | 175 | * global lock held and irqs disabled, don't need percpu lock |
| 176 | */ | 176 | */ |
| 177 | prepare_to_wait(&pool->wait, &wait, TASK_UNINTERRUPTIBLE); | 177 | if (state != TASK_RUNNING) |
| 178 | prepare_to_wait(&pool->wait, &wait, state); | ||
| 178 | 179 | ||
| 179 | if (!tags->nr_free) | 180 | if (!tags->nr_free) |
| 180 | alloc_global_tags(pool, tags); | 181 | alloc_global_tags(pool, tags); |
| @@ -191,7 +192,7 @@ int percpu_ida_alloc(struct percpu_ida *pool, gfp_t gfp) | |||
| 191 | spin_unlock(&pool->lock); | 192 | spin_unlock(&pool->lock); |
| 192 | local_irq_restore(flags); | 193 | local_irq_restore(flags); |
| 193 | 194 | ||
| 194 | if (tag >= 0 || !(gfp & __GFP_WAIT)) | 195 | if (tag >= 0 || state == TASK_RUNNING) |
| 195 | break; | 196 | break; |
| 196 | 197 | ||
| 197 | schedule(); | 198 | schedule(); |
| @@ -199,8 +200,9 @@ int percpu_ida_alloc(struct percpu_ida *pool, gfp_t gfp) | |||
| 199 | local_irq_save(flags); | 200 | local_irq_save(flags); |
| 200 | tags = this_cpu_ptr(pool->tag_cpu); | 201 | tags = this_cpu_ptr(pool->tag_cpu); |
| 201 | } | 202 | } |
| 203 | if (state != TASK_RUNNING) | ||
| 204 | finish_wait(&pool->wait, &wait); | ||
| 202 | 205 | ||
| 203 | finish_wait(&pool->wait, &wait); | ||
| 204 | return tag; | 206 | return tag; |
| 205 | } | 207 | } |
| 206 | EXPORT_SYMBOL_GPL(percpu_ida_alloc); | 208 | EXPORT_SYMBOL_GPL(percpu_ida_alloc); |
