diff options
author | Kent Overstreet <kmo@daterainc.com> | 2014-01-19 03:26:37 -0500 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2014-01-23 15:17:18 -0500 |
commit | 6f6b5d1ec56acdeab0503d2b823f6f88a0af493e (patch) | |
tree | 7a95dca01cc9ddd652ccbfba4df9d5c30abda549 /lib/percpu_ida.c | |
parent | 4a4caa29f1abcb14377e05d57c0793d338fb945d (diff) |
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: Linus 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: Kent Overstreet <kmo@daterainc.com>
Cc: <stable@vger.kernel.org> #3.12+
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'lib/percpu_ida.c')
-rw-r--r-- | lib/percpu_ida.c | 16 |
1 files changed, 9 insertions, 7 deletions
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); |