Commit 8814ce8a authored by Bart Van Assche's avatar Bart Van Assche Committed by Jens Axboe

block: Introduce blk_queue_flag_{set,clear,test_and_{set,clear}}()

Introduce functions that modify the queue flags and that protect
these modifications with the request queue lock. Except for moving
one wake_up_all() call from inside to outside a critical section,
this patch does not change any functionality.

Cc: Christoph Hellwig <hch@lst.de>
Cc: Hannes Reinecke <hare@suse.de>
Cc: Ming Lei <ming.lei@redhat.com>
Reviewed-by: default avatarJohannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: default avatarBart Van Assche <bart.vanassche@wdc.com>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent f78bac2c
...@@ -71,6 +71,78 @@ struct kmem_cache *blk_requestq_cachep; ...@@ -71,6 +71,78 @@ struct kmem_cache *blk_requestq_cachep;
*/ */
static struct workqueue_struct *kblockd_workqueue; static struct workqueue_struct *kblockd_workqueue;
/**
* blk_queue_flag_set - atomically set a queue flag
* @flag: flag to be set
* @q: request queue
*/
void blk_queue_flag_set(unsigned int flag, struct request_queue *q)
{
unsigned long flags;
spin_lock_irqsave(q->queue_lock, flags);
queue_flag_set(flag, q);
spin_unlock_irqrestore(q->queue_lock, flags);
}
EXPORT_SYMBOL(blk_queue_flag_set);
/**
* blk_queue_flag_clear - atomically clear a queue flag
* @flag: flag to be cleared
* @q: request queue
*/
void blk_queue_flag_clear(unsigned int flag, struct request_queue *q)
{
unsigned long flags;
spin_lock_irqsave(q->queue_lock, flags);
queue_flag_clear(flag, q);
spin_unlock_irqrestore(q->queue_lock, flags);
}
EXPORT_SYMBOL(blk_queue_flag_clear);
/**
* blk_queue_flag_test_and_set - atomically test and set a queue flag
* @flag: flag to be set
* @q: request queue
*
* Returns the previous value of @flag - 0 if the flag was not set and 1 if
* the flag was already set.
*/
bool blk_queue_flag_test_and_set(unsigned int flag, struct request_queue *q)
{
unsigned long flags;
bool res;
spin_lock_irqsave(q->queue_lock, flags);
res = queue_flag_test_and_set(flag, q);
spin_unlock_irqrestore(q->queue_lock, flags);
return res;
}
EXPORT_SYMBOL_GPL(blk_queue_flag_test_and_set);
/**
* blk_queue_flag_test_and_clear - atomically test and clear a queue flag
* @flag: flag to be cleared
* @q: request queue
*
* Returns the previous value of @flag - 0 if the flag was not set and 1 if
* the flag was set.
*/
bool blk_queue_flag_test_and_clear(unsigned int flag, struct request_queue *q)
{
unsigned long flags;
bool res;
spin_lock_irqsave(q->queue_lock, flags);
res = queue_flag_test_and_clear(flag, q);
spin_unlock_irqrestore(q->queue_lock, flags);
return res;
}
EXPORT_SYMBOL_GPL(blk_queue_flag_test_and_clear);
static void blk_clear_congested(struct request_list *rl, int sync) static void blk_clear_congested(struct request_list *rl, int sync)
{ {
#ifdef CONFIG_CGROUP_WRITEBACK #ifdef CONFIG_CGROUP_WRITEBACK
...@@ -361,25 +433,14 @@ EXPORT_SYMBOL(blk_sync_queue); ...@@ -361,25 +433,14 @@ EXPORT_SYMBOL(blk_sync_queue);
*/ */
int blk_set_preempt_only(struct request_queue *q) int blk_set_preempt_only(struct request_queue *q)
{ {
unsigned long flags; return blk_queue_flag_test_and_set(QUEUE_FLAG_PREEMPT_ONLY, q);
int res;
spin_lock_irqsave(q->queue_lock, flags);
res = queue_flag_test_and_set(QUEUE_FLAG_PREEMPT_ONLY, q);
spin_unlock_irqrestore(q->queue_lock, flags);
return res;
} }
EXPORT_SYMBOL_GPL(blk_set_preempt_only); EXPORT_SYMBOL_GPL(blk_set_preempt_only);
void blk_clear_preempt_only(struct request_queue *q) void blk_clear_preempt_only(struct request_queue *q)
{ {
unsigned long flags; blk_queue_flag_clear(QUEUE_FLAG_PREEMPT_ONLY, q);
spin_lock_irqsave(q->queue_lock, flags);
queue_flag_clear(QUEUE_FLAG_PREEMPT_ONLY, q);
wake_up_all(&q->mq_freeze_wq); wake_up_all(&q->mq_freeze_wq);
spin_unlock_irqrestore(q->queue_lock, flags);
} }
EXPORT_SYMBOL_GPL(blk_clear_preempt_only); EXPORT_SYMBOL_GPL(blk_clear_preempt_only);
...@@ -629,9 +690,7 @@ EXPORT_SYMBOL_GPL(blk_queue_bypass_end); ...@@ -629,9 +690,7 @@ EXPORT_SYMBOL_GPL(blk_queue_bypass_end);
void blk_set_queue_dying(struct request_queue *q) void blk_set_queue_dying(struct request_queue *q)
{ {
spin_lock_irq(q->queue_lock); blk_queue_flag_set(QUEUE_FLAG_DYING, q);
queue_flag_set(QUEUE_FLAG_DYING, q);
spin_unlock_irq(q->queue_lock);
/* /*
* When queue DYING flag is set, we need to block new req * When queue DYING flag is set, we need to block new req
......
...@@ -194,11 +194,7 @@ EXPORT_SYMBOL_GPL(blk_mq_unfreeze_queue); ...@@ -194,11 +194,7 @@ EXPORT_SYMBOL_GPL(blk_mq_unfreeze_queue);
*/ */
void blk_mq_quiesce_queue_nowait(struct request_queue *q) void blk_mq_quiesce_queue_nowait(struct request_queue *q)
{ {
unsigned long flags; blk_queue_flag_set(QUEUE_FLAG_QUIESCED, q);
spin_lock_irqsave(q->queue_lock, flags);
queue_flag_set(QUEUE_FLAG_QUIESCED, q);
spin_unlock_irqrestore(q->queue_lock, flags);
} }
EXPORT_SYMBOL_GPL(blk_mq_quiesce_queue_nowait); EXPORT_SYMBOL_GPL(blk_mq_quiesce_queue_nowait);
...@@ -239,11 +235,7 @@ EXPORT_SYMBOL_GPL(blk_mq_quiesce_queue); ...@@ -239,11 +235,7 @@ EXPORT_SYMBOL_GPL(blk_mq_quiesce_queue);
*/ */
void blk_mq_unquiesce_queue(struct request_queue *q) void blk_mq_unquiesce_queue(struct request_queue *q)
{ {
unsigned long flags; blk_queue_flag_clear(QUEUE_FLAG_QUIESCED, q);
spin_lock_irqsave(q->queue_lock, flags);
queue_flag_clear(QUEUE_FLAG_QUIESCED, q);
spin_unlock_irqrestore(q->queue_lock, flags);
/* dispatch requests which are inserted during quiescing */ /* dispatch requests which are inserted during quiescing */
blk_mq_run_hw_queues(q, true); blk_mq_run_hw_queues(q, true);
......
...@@ -859,12 +859,10 @@ EXPORT_SYMBOL(blk_queue_update_dma_alignment); ...@@ -859,12 +859,10 @@ EXPORT_SYMBOL(blk_queue_update_dma_alignment);
void blk_queue_flush_queueable(struct request_queue *q, bool queueable) void blk_queue_flush_queueable(struct request_queue *q, bool queueable)
{ {
spin_lock_irq(q->queue_lock);
if (queueable) if (queueable)
queue_flag_clear(QUEUE_FLAG_FLUSH_NQ, q); blk_queue_flag_clear(QUEUE_FLAG_FLUSH_NQ, q);
else else
queue_flag_set(QUEUE_FLAG_FLUSH_NQ, q); blk_queue_flag_set(QUEUE_FLAG_FLUSH_NQ, q);
spin_unlock_irq(q->queue_lock);
} }
EXPORT_SYMBOL_GPL(blk_queue_flush_queueable); EXPORT_SYMBOL_GPL(blk_queue_flush_queueable);
......
...@@ -276,12 +276,10 @@ queue_store_##name(struct request_queue *q, const char *page, size_t count) \ ...@@ -276,12 +276,10 @@ queue_store_##name(struct request_queue *q, const char *page, size_t count) \
if (neg) \ if (neg) \
val = !val; \ val = !val; \
\ \
spin_lock_irq(q->queue_lock); \
if (val) \ if (val) \
queue_flag_set(QUEUE_FLAG_##flag, q); \ blk_queue_flag_set(QUEUE_FLAG_##flag, q); \
else \ else \
queue_flag_clear(QUEUE_FLAG_##flag, q); \ blk_queue_flag_clear(QUEUE_FLAG_##flag, q); \
spin_unlock_irq(q->queue_lock); \
return ret; \ return ret; \
} }
...@@ -414,12 +412,10 @@ static ssize_t queue_poll_store(struct request_queue *q, const char *page, ...@@ -414,12 +412,10 @@ static ssize_t queue_poll_store(struct request_queue *q, const char *page,
if (ret < 0) if (ret < 0)
return ret; return ret;
spin_lock_irq(q->queue_lock);
if (poll_on) if (poll_on)
queue_flag_set(QUEUE_FLAG_POLL, q); blk_queue_flag_set(QUEUE_FLAG_POLL, q);
else else
queue_flag_clear(QUEUE_FLAG_POLL, q); blk_queue_flag_clear(QUEUE_FLAG_POLL, q);
spin_unlock_irq(q->queue_lock);
return ret; return ret;
} }
...@@ -487,12 +483,10 @@ static ssize_t queue_wc_store(struct request_queue *q, const char *page, ...@@ -487,12 +483,10 @@ static ssize_t queue_wc_store(struct request_queue *q, const char *page,
if (set == -1) if (set == -1)
return -EINVAL; return -EINVAL;
spin_lock_irq(q->queue_lock);
if (set) if (set)
queue_flag_set(QUEUE_FLAG_WC, q); blk_queue_flag_set(QUEUE_FLAG_WC, q);
else else
queue_flag_clear(QUEUE_FLAG_WC, q); blk_queue_flag_clear(QUEUE_FLAG_WC, q);
spin_unlock_irq(q->queue_lock);
return count; return count;
} }
...@@ -946,9 +940,7 @@ void blk_unregister_queue(struct gendisk *disk) ...@@ -946,9 +940,7 @@ void blk_unregister_queue(struct gendisk *disk)
*/ */
mutex_lock(&q->sysfs_lock); mutex_lock(&q->sysfs_lock);
spin_lock_irq(q->queue_lock); blk_queue_flag_clear(QUEUE_FLAG_REGISTERED, q);
queue_flag_clear(QUEUE_FLAG_REGISTERED, q);
spin_unlock_irq(q->queue_lock);
/* /*
* Remove the sysfs attributes before unregistering the queue data * Remove the sysfs attributes before unregistering the queue data
......
...@@ -57,12 +57,10 @@ ssize_t part_timeout_store(struct device *dev, struct device_attribute *attr, ...@@ -57,12 +57,10 @@ ssize_t part_timeout_store(struct device *dev, struct device_attribute *attr,
char *p = (char *) buf; char *p = (char *) buf;
val = simple_strtoul(p, &p, 10); val = simple_strtoul(p, &p, 10);
spin_lock_irq(q->queue_lock);
if (val) if (val)
queue_flag_set(QUEUE_FLAG_FAIL_IO, q); blk_queue_flag_set(QUEUE_FLAG_FAIL_IO, q);
else else
queue_flag_clear(QUEUE_FLAG_FAIL_IO, q); blk_queue_flag_clear(QUEUE_FLAG_FAIL_IO, q);
spin_unlock_irq(q->queue_lock);
} }
return count; return count;
......
...@@ -707,6 +707,11 @@ struct request_queue { ...@@ -707,6 +707,11 @@ struct request_queue {
(1 << QUEUE_FLAG_SAME_COMP) | \ (1 << QUEUE_FLAG_SAME_COMP) | \
(1 << QUEUE_FLAG_POLL)) (1 << QUEUE_FLAG_POLL))
void blk_queue_flag_set(unsigned int flag, struct request_queue *q);
void blk_queue_flag_clear(unsigned int flag, struct request_queue *q);
bool blk_queue_flag_test_and_set(unsigned int flag, struct request_queue *q);
bool blk_queue_flag_test_and_clear(unsigned int flag, struct request_queue *q);
/* /*
* @q->queue_lock is set while a queue is being initialized. Since we know * @q->queue_lock is set while a queue is being initialized. Since we know
* that no other threads access the queue object before @q->queue_lock has * that no other threads access the queue object before @q->queue_lock has
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment