diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-07-15 04:11:50 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-07-15 04:11:50 +0400 |
commit | 8ec8ba8e7d5b3cdfedf62e46cfa55c8e36172a2d (patch) | |
tree | c66536295556e207d00d011ebff021ac9d1e07c2 | |
parent | 3cf521f7dc87c031617fd47e4b7aa2593c2f3daf (diff) | |
parent | 263782c1c95bbddbb022dc092fd89a36bb8d5577 (diff) | |
download | linux-8ec8ba8e7d5b3cdfedf62e46cfa55c8e36172a2d.tar.xz |
Merge git://git.kvack.org/~bcrl/aio-fixes
Pull another aio fix from Ben LaHaise:
"put_reqs_available() can now be called from within irq context, which
means that it (and its sibling function get_reqs_available()) now need
to be irq-safe, not just preempt-safe"
* git://git.kvack.org/~bcrl/aio-fixes:
aio: protect reqs_available updates from changes in interrupt handlers
-rw-r--r-- | fs/aio.c | 7 |
1 files changed, 7 insertions, 0 deletions
@@ -830,16 +830,20 @@ void exit_aio(struct mm_struct *mm) static void put_reqs_available(struct kioctx *ctx, unsigned nr) { struct kioctx_cpu *kcpu; + unsigned long flags; preempt_disable(); kcpu = this_cpu_ptr(ctx->cpu); + local_irq_save(flags); kcpu->reqs_available += nr; + while (kcpu->reqs_available >= ctx->req_batch * 2) { kcpu->reqs_available -= ctx->req_batch; atomic_add(ctx->req_batch, &ctx->reqs_available); } + local_irq_restore(flags); preempt_enable(); } @@ -847,10 +851,12 @@ static bool get_reqs_available(struct kioctx *ctx) { struct kioctx_cpu *kcpu; bool ret = false; + unsigned long flags; preempt_disable(); kcpu = this_cpu_ptr(ctx->cpu); + local_irq_save(flags); if (!kcpu->reqs_available) { int old, avail = atomic_read(&ctx->reqs_available); @@ -869,6 +875,7 @@ static bool get_reqs_available(struct kioctx *ctx) ret = true; kcpu->reqs_available--; out: + local_irq_restore(flags); preempt_enable(); return ret; } |