diff options
| -rw-r--r-- | fs/aio.c | 35 |
1 files changed, 24 insertions, 11 deletions
| @@ -239,15 +239,23 @@ static void __put_ioctx(struct kioctx *ctx) | |||
| 239 | call_rcu(&ctx->rcu_head, ctx_rcu_free); | 239 | call_rcu(&ctx->rcu_head, ctx_rcu_free); |
| 240 | } | 240 | } |
| 241 | 241 | ||
| 242 | #define get_ioctx(kioctx) do { \ | 242 | static inline void get_ioctx(struct kioctx *kioctx) |
| 243 | BUG_ON(atomic_read(&(kioctx)->users) <= 0); \ | 243 | { |
| 244 | atomic_inc(&(kioctx)->users); \ | 244 | BUG_ON(atomic_read(&kioctx->users) <= 0); |
| 245 | } while (0) | 245 | atomic_inc(&kioctx->users); |
| 246 | #define put_ioctx(kioctx) do { \ | 246 | } |
| 247 | BUG_ON(atomic_read(&(kioctx)->users) <= 0); \ | 247 | |
| 248 | if (unlikely(atomic_dec_and_test(&(kioctx)->users))) \ | 248 | static inline int try_get_ioctx(struct kioctx *kioctx) |
| 249 | __put_ioctx(kioctx); \ | 249 | { |
| 250 | } while (0) | 250 | return atomic_inc_not_zero(&kioctx->users); |
| 251 | } | ||
| 252 | |||
| 253 | static inline void put_ioctx(struct kioctx *kioctx) | ||
| 254 | { | ||
| 255 | BUG_ON(atomic_read(&kioctx->users) <= 0); | ||
| 256 | if (unlikely(atomic_dec_and_test(&kioctx->users))) | ||
| 257 | __put_ioctx(kioctx); | ||
| 258 | } | ||
| 251 | 259 | ||
| 252 | /* ioctx_alloc | 260 | /* ioctx_alloc |
| 253 | * Allocates and initializes an ioctx. Returns an ERR_PTR if it failed. | 261 | * Allocates and initializes an ioctx. Returns an ERR_PTR if it failed. |
| @@ -601,8 +609,13 @@ static struct kioctx *lookup_ioctx(unsigned long ctx_id) | |||
| 601 | rcu_read_lock(); | 609 | rcu_read_lock(); |
| 602 | 610 | ||
| 603 | hlist_for_each_entry_rcu(ctx, n, &mm->ioctx_list, list) { | 611 | hlist_for_each_entry_rcu(ctx, n, &mm->ioctx_list, list) { |
| 604 | if (ctx->user_id == ctx_id && !ctx->dead) { | 612 | /* |
| 605 | get_ioctx(ctx); | 613 | * RCU protects us against accessing freed memory but |
| 614 | * we have to be careful not to get a reference when the | ||
| 615 | * reference count already dropped to 0 (ctx->dead test | ||
| 616 | * is unreliable because of races). | ||
| 617 | */ | ||
| 618 | if (ctx->user_id == ctx_id && !ctx->dead && try_get_ioctx(ctx)){ | ||
| 606 | ret = ctx; | 619 | ret = ctx; |
| 607 | break; | 620 | break; |
| 608 | } | 621 | } |
