Commit 1678b014 authored by Alessandro Rubini's avatar Alessandro Rubini

buffers: use the irqsave version of spin locks

Since the trigger often runs at interrupt time, we need the
irqsave/irqrestore spinlock in the critical sections of buffers.
Signed-off-by: Alessandro Rubini's avatarAlessandro Rubini <rubini@gnudd.com>
Acked-by: 's avatarFederico Vaga <federico.vaga@gmail.com>
parent 035a5814
...@@ -67,16 +67,17 @@ static struct zio_block *zbk_alloc_block(struct zio_bi *bi, ...@@ -67,16 +67,17 @@ static struct zio_block *zbk_alloc_block(struct zio_bi *bi,
struct zbk_instance *zbki = to_zbki(bi); struct zbk_instance *zbki = to_zbki(bi);
struct zbk_item *item; struct zbk_item *item;
struct zio_control *ctrl; struct zio_control *ctrl;
unsigned long flags;
void *data; void *data;
pr_debug("%s:%d\n", __func__, __LINE__); pr_debug("%s:%d\n", __func__, __LINE__);
/* alloc fails if we overflow the buffer size */ /* alloc fails if we overflow the buffer size */
spin_lock(&bi->lock); spin_lock_irqsave(&bi->lock, flags);
if (zbki->nitem >= bi->zattr_set.std_zattr[ZIO_ATTR_ZBUF_MAXLEN].value) if (zbki->nitem >= bi->zattr_set.std_zattr[ZIO_ATTR_ZBUF_MAXLEN].value)
goto out_unlock; goto out_unlock;
zbki->nitem++; zbki->nitem++;
spin_unlock(&bi->lock); spin_unlock_irqrestore(&bi->lock, flags);
/* alloc item and data. Control remains null at this point */ /* alloc item and data. Control remains null at this point */
item = kmem_cache_alloc(zbk_slab, gfp); item = kmem_cache_alloc(zbk_slab, gfp);
...@@ -95,10 +96,10 @@ out_free: ...@@ -95,10 +96,10 @@ out_free:
kfree(data); kfree(data);
kmem_cache_free(zbk_slab, item); kmem_cache_free(zbk_slab, item);
zio_free_control(ctrl); zio_free_control(ctrl);
spin_lock(&bi->lock); spin_lock_irqsave(&bi->lock, flags);
zbki->nitem--; zbki->nitem--;
out_unlock: out_unlock:
spin_unlock(&bi->lock); spin_unlock_irqrestore(&bi->lock, flags);
return NULL; return NULL;
} }
...@@ -107,6 +108,7 @@ static void zbk_free_block(struct zio_bi *bi, struct zio_block *block) ...@@ -107,6 +108,7 @@ static void zbk_free_block(struct zio_bi *bi, struct zio_block *block)
{ {
struct zbk_item *item; struct zbk_item *item;
struct zbk_instance *zbki; struct zbk_instance *zbki;
unsigned long flags;
int awake = 0; int awake = 0;
pr_debug("%s:%d\n", __func__, __LINE__); pr_debug("%s:%d\n", __func__, __LINE__);
...@@ -114,12 +116,12 @@ static void zbk_free_block(struct zio_bi *bi, struct zio_block *block) ...@@ -114,12 +116,12 @@ static void zbk_free_block(struct zio_bi *bi, struct zio_block *block)
item = to_item(block); item = to_item(block);
zbki = item->instance; zbki = item->instance;
spin_lock(&bi->lock); spin_lock_irqsave(&bi->lock, flags);
if ( ((bi->flags & ZIO_DIR) == ZIO_DIR_OUTPUT) && if ( ((bi->flags & ZIO_DIR) == ZIO_DIR_OUTPUT) &&
zbki->nitem < bi->zattr_set.std_zattr[ZIO_ATTR_ZBUF_MAXLEN].value) zbki->nitem < bi->zattr_set.std_zattr[ZIO_ATTR_ZBUF_MAXLEN].value)
awake = 1; awake = 1;
zbki->nitem--; zbki->nitem--;
spin_unlock(&bi->lock); spin_unlock_irqrestore(&bi->lock, flags);
kfree(block->data); kfree(block->data);
zio_free_control(zio_get_ctrl(block)); zio_free_control(zio_get_ctrl(block));
...@@ -144,7 +146,7 @@ static inline int __try_push(struct zio_bi *bi, struct zio_channel *chan, ...@@ -144,7 +146,7 @@ static inline int __try_push(struct zio_bi *bi, struct zio_channel *chan,
* release the lock but also say we can't retrieve now. * release the lock but also say we can't retrieve now.
*/ */
bi->flags |= ZIO_BI_PUSHING; bi->flags |= ZIO_BI_PUSHING;
spin_unlock(&bi->lock); spin_unlock(&bi->lock); /* Don't irqrestore here, keep them disabled */
pushed = (ti->t_op->push_block(ti, chan, block) == 0); pushed = (ti->t_op->push_block(ti, chan, block) == 0);
spin_lock(&bi->lock); spin_lock(&bi->lock);
bi->flags &= ~ZIO_BI_PUSHING; bi->flags &= ~ZIO_BI_PUSHING;
...@@ -157,13 +159,14 @@ static int zbk_store_block(struct zio_bi *bi, struct zio_block *block) ...@@ -157,13 +159,14 @@ static int zbk_store_block(struct zio_bi *bi, struct zio_block *block)
struct zbk_instance *zbki = to_zbki(bi); struct zbk_instance *zbki = to_zbki(bi);
struct zio_channel *chan = bi->chan; struct zio_channel *chan = bi->chan;
struct zbk_item *item = to_item(block); struct zbk_item *item = to_item(block);
unsigned long flags;
int awake = 0, pushed = 0, isempty; int awake = 0, pushed = 0, isempty;
int output = (bi->flags & ZIO_DIR) == ZIO_DIR_OUTPUT; int output = (bi->flags & ZIO_DIR) == ZIO_DIR_OUTPUT;
pr_debug("%s:%d (%p, %p)\n", __func__, __LINE__, bi, block); pr_debug("%s:%d (%p, %p)\n", __func__, __LINE__, bi, block);
/* add to the buffer instance or push to the trigger */ /* add to the buffer instance or push to the trigger */
spin_lock(&bi->lock); spin_lock_irqsave(&bi->lock, flags);
isempty = list_empty(&zbki->list); isempty = list_empty(&zbki->list);
list_add_tail(&item->list, &zbki->list); list_add_tail(&item->list, &zbki->list);
if (isempty) { if (isempty) {
...@@ -174,7 +177,7 @@ static int zbk_store_block(struct zio_bi *bi, struct zio_block *block) ...@@ -174,7 +177,7 @@ static int zbk_store_block(struct zio_bi *bi, struct zio_block *block)
} }
if (pushed) if (pushed)
list_del(&item->list); list_del(&item->list);
spin_unlock(&bi->lock); spin_unlock_irqrestore(&bi->lock, flags);
/* if first input, awake user space */ /* if first input, awake user space */
if (awake) if (awake)
...@@ -189,22 +192,23 @@ static struct zio_block *zbk_retr_block(struct zio_bi *bi) ...@@ -189,22 +192,23 @@ static struct zio_block *zbk_retr_block(struct zio_bi *bi)
struct zbk_instance *zbki; struct zbk_instance *zbki;
struct zio_ti *ti; struct zio_ti *ti;
struct list_head *first; struct list_head *first;
unsigned long flags;
zbki = to_zbki(bi); zbki = to_zbki(bi);
spin_lock(&bi->lock); spin_lock_irqsave(&bi->lock, flags);
if (list_empty(&zbki->list) || bi->flags & ZIO_BI_PUSHING) if (list_empty(&zbki->list) || bi->flags & ZIO_BI_PUSHING)
goto out_unlock; goto out_unlock;
first = zbki->list.next; first = zbki->list.next;
item = list_entry(first, struct zbk_item, list); item = list_entry(first, struct zbk_item, list);
list_del(&item->list); list_del(&item->list);
spin_unlock(&bi->lock); spin_unlock_irqrestore(&bi->lock, flags);
pr_debug("%s:%d (%p, %p)\n", __func__, __LINE__, bi, item); pr_debug("%s:%d (%p, %p)\n", __func__, __LINE__, bi, item);
return &item->block; return &item->block;
out_unlock: out_unlock:
spin_unlock(&bi->lock); spin_unlock_irqrestore(&bi->lock, flags);
/* There is no data in buffer, and we may pull to have data soon */ /* There is no data in buffer, and we may pull to have data soon */
ti = bi->cset->ti; ti = bi->cset->ti;
if ((bi->flags & ZIO_DIR) == ZIO_DIR_INPUT && ti->t_op->pull_block) { if ((bi->flags & ZIO_DIR) == ZIO_DIR_INPUT && ti->t_op->pull_block) {
......
...@@ -202,6 +202,7 @@ static int zbk_store_block(struct zio_bi *bi, struct zio_block *block) ...@@ -202,6 +202,7 @@ static int zbk_store_block(struct zio_bi *bi, struct zio_block *block)
struct zbk_instance *zbki = to_zbki(bi); struct zbk_instance *zbki = to_zbki(bi);
struct zio_channel *chan = bi->chan; struct zio_channel *chan = bi->chan;
struct zbk_item *item; struct zbk_item *item;
unsigned long flags;
int awake = 0, pushed = 0, output, first; int awake = 0, pushed = 0, output, first;
pr_debug("%s:%d (%p, %p)\n", __func__, __LINE__, bi, block); pr_debug("%s:%d (%p, %p)\n", __func__, __LINE__, bi, block);
...@@ -212,7 +213,7 @@ static int zbk_store_block(struct zio_bi *bi, struct zio_block *block) ...@@ -212,7 +213,7 @@ static int zbk_store_block(struct zio_bi *bi, struct zio_block *block)
output = (bi->flags & ZIO_DIR) == ZIO_DIR_OUTPUT; output = (bi->flags & ZIO_DIR) == ZIO_DIR_OUTPUT;
/* add to the buffer instance or push to the trigger */ /* add to the buffer instance or push to the trigger */
spin_lock(&bi->lock); spin_lock_irqsave(&bi->lock, flags);
first = list_empty(&zbki->list); first = list_empty(&zbki->list);
list_add_tail(&item->list, &zbki->list); list_add_tail(&item->list, &zbki->list);
if (first) { if (first) {
...@@ -225,7 +226,7 @@ static int zbk_store_block(struct zio_bi *bi, struct zio_block *block) ...@@ -225,7 +226,7 @@ static int zbk_store_block(struct zio_bi *bi, struct zio_block *block)
list_del(&item->list); list_del(&item->list);
if (!first && zbki->flags & ZBK_FLAG_MERGE_DATA) if (!first && zbki->flags & ZBK_FLAG_MERGE_DATA)
zbk_try_merge(zbki, item); zbk_try_merge(zbki, item);
spin_unlock(&bi->lock); spin_unlock_irqrestore(&bi->lock, flags);
/* if first input, awake user space */ /* if first input, awake user space */
if (awake) if (awake)
...@@ -240,18 +241,19 @@ static struct zio_block *zbk_retr_block(struct zio_bi *bi) ...@@ -240,18 +241,19 @@ static struct zio_block *zbk_retr_block(struct zio_bi *bi)
struct zbk_instance *zbki; struct zbk_instance *zbki;
struct zio_ti *ti; struct zio_ti *ti;
struct list_head *first; struct list_head *first;
unsigned long flags;
int awake = 0; int awake = 0;
zbki = to_zbki(bi); zbki = to_zbki(bi);
spin_lock(&bi->lock); spin_lock_irqsave(&bi->lock, flags);
if (list_empty(&zbki->list) || bi->flags & ZIO_BI_PUSHING) if (list_empty(&zbki->list) || bi->flags & ZIO_BI_PUSHING)
goto out_unlock; goto out_unlock;
first = zbki->list.next; first = zbki->list.next;
item = list_entry(first, struct zbk_item, list); item = list_entry(first, struct zbk_item, list);
list_del(&item->list); list_del(&item->list);
awake = 1; awake = 1;
spin_unlock(&bi->lock); spin_unlock_irqrestore(&bi->lock, flags);
if (awake && ((bi->flags & ZIO_DIR) == ZIO_DIR_OUTPUT)) if (awake && ((bi->flags & ZIO_DIR) == ZIO_DIR_OUTPUT))
wake_up_interruptible(&bi->q); wake_up_interruptible(&bi->q);
...@@ -259,7 +261,7 @@ static struct zio_block *zbk_retr_block(struct zio_bi *bi) ...@@ -259,7 +261,7 @@ static struct zio_block *zbk_retr_block(struct zio_bi *bi)
return &item->block; return &item->block;
out_unlock: out_unlock:
spin_unlock(&bi->lock); spin_unlock_irqrestore(&bi->lock, flags);
/* There is no data in buffer, and we may pull to have data soon */ /* There is no data in buffer, and we may pull to have data soon */
ti = bi->cset->ti; ti = bi->cset->ti;
if ((bi->flags & ZIO_DIR) == ZIO_DIR_INPUT && ti->t_op->pull_block) { if ((bi->flags & ZIO_DIR) == ZIO_DIR_INPUT && ti->t_op->pull_block) {
......
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