From a4fbc1fa507d65b0969fd71d624c299667120443 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Fri, 25 Feb 2011 14:44:26 -0800 Subject: [PATCH] --- yaml --- r: 233699 b: refs/heads/master c: 3bd9a5d734c7cc7533b27abf451416c7f50095a7 h: refs/heads/master i: 233697: fbf8c65de1b2706f2baa53177ac1c938afdda654 233695: 32478136cbe425a4ab392d99dad703d4f4f5cb08 v: v3 --- [refs] | 2 +- trunk/fs/aio.c | 35 ++++++++++++++++++++++++----------- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/[refs] b/[refs] index 2401012031b6..f0bda59d0bf7 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 29723fccc837d20039078f7a571e8d457eb0d6c6 +refs/heads/master: 3bd9a5d734c7cc7533b27abf451416c7f50095a7 diff --git a/trunk/fs/aio.c b/trunk/fs/aio.c index fc557a3be0a9..b4dd668fbccc 100644 --- a/trunk/fs/aio.c +++ b/trunk/fs/aio.c @@ -239,15 +239,23 @@ static void __put_ioctx(struct kioctx *ctx) call_rcu(&ctx->rcu_head, ctx_rcu_free); } -#define get_ioctx(kioctx) do { \ - BUG_ON(atomic_read(&(kioctx)->users) <= 0); \ - atomic_inc(&(kioctx)->users); \ -} while (0) -#define put_ioctx(kioctx) do { \ - BUG_ON(atomic_read(&(kioctx)->users) <= 0); \ - if (unlikely(atomic_dec_and_test(&(kioctx)->users))) \ - __put_ioctx(kioctx); \ -} while (0) +static inline void get_ioctx(struct kioctx *kioctx) +{ + BUG_ON(atomic_read(&kioctx->users) <= 0); + atomic_inc(&kioctx->users); +} + +static inline int try_get_ioctx(struct kioctx *kioctx) +{ + return atomic_inc_not_zero(&kioctx->users); +} + +static inline void put_ioctx(struct kioctx *kioctx) +{ + BUG_ON(atomic_read(&kioctx->users) <= 0); + if (unlikely(atomic_dec_and_test(&kioctx->users))) + __put_ioctx(kioctx); +} /* ioctx_alloc * 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) rcu_read_lock(); hlist_for_each_entry_rcu(ctx, n, &mm->ioctx_list, list) { - if (ctx->user_id == ctx_id && !ctx->dead) { - get_ioctx(ctx); + /* + * RCU protects us against accessing freed memory but + * we have to be careful not to get a reference when the + * reference count already dropped to 0 (ctx->dead test + * is unreliable because of races). + */ + if (ctx->user_id == ctx_id && !ctx->dead && try_get_ioctx(ctx)){ ret = ctx; break; }