diff options
Diffstat (limited to 'fs/fscache/cookie.c')
| -rw-r--r-- | fs/fscache/cookie.c | 26 | 
1 files changed, 22 insertions, 4 deletions
| diff --git a/fs/fscache/cookie.c b/fs/fscache/cookie.c index 9d3cf0111709..74920826d8f6 100644 --- a/fs/fscache/cookie.c +++ b/fs/fscache/cookie.c @@ -372,17 +372,22 @@ nomem:  	return NULL;  } +static inline bool fscache_cookie_is_dropped(struct fscache_cookie *cookie) +{ +	return READ_ONCE(cookie->state) == FSCACHE_COOKIE_STATE_DROPPED; +} +  static void fscache_wait_on_collision(struct fscache_cookie *candidate,  				      struct fscache_cookie *wait_for)  {  	enum fscache_cookie_state *statep = &wait_for->state; -	wait_var_event_timeout(statep, READ_ONCE(*statep) == FSCACHE_COOKIE_STATE_DROPPED, +	wait_var_event_timeout(statep, fscache_cookie_is_dropped(wait_for),  			       20 * HZ); -	if (READ_ONCE(*statep) != FSCACHE_COOKIE_STATE_DROPPED) { +	if (!fscache_cookie_is_dropped(wait_for)) {  		pr_notice("Potential collision c=%08x old: c=%08x",  			  candidate->debug_id, wait_for->debug_id); -		wait_var_event(statep, READ_ONCE(*statep) == FSCACHE_COOKIE_STATE_DROPPED); +		wait_var_event(statep, fscache_cookie_is_dropped(wait_for));  	}  } @@ -517,7 +522,14 @@ static void fscache_perform_lookup(struct fscache_cookie *cookie)  	}  	fscache_see_cookie(cookie, fscache_cookie_see_active); -	fscache_set_cookie_state(cookie, FSCACHE_COOKIE_STATE_ACTIVE); +	spin_lock(&cookie->lock); +	if (test_and_clear_bit(FSCACHE_COOKIE_DO_INVALIDATE, &cookie->flags)) +		__fscache_set_cookie_state(cookie, +					   FSCACHE_COOKIE_STATE_INVALIDATING); +	else +		__fscache_set_cookie_state(cookie, FSCACHE_COOKIE_STATE_ACTIVE); +	spin_unlock(&cookie->lock); +	wake_up_cookie_state(cookie);  	trace = fscache_access_lookup_cookie_end;  out: @@ -752,6 +764,9 @@ again_locked:  			spin_lock(&cookie->lock);  		} +		if (test_and_clear_bit(FSCACHE_COOKIE_DO_INVALIDATE, &cookie->flags)) +			fscache_end_cookie_access(cookie, fscache_access_invalidate_cookie_end); +  		switch (state) {  		case FSCACHE_COOKIE_STATE_RELINQUISHING:  			fscache_see_cookie(cookie, fscache_cookie_see_relinquish); @@ -1048,6 +1063,9 @@ void __fscache_invalidate(struct fscache_cookie *cookie,  		return;  	case FSCACHE_COOKIE_STATE_LOOKING_UP: +		__fscache_begin_cookie_access(cookie, fscache_access_invalidate_cookie); +		set_bit(FSCACHE_COOKIE_DO_INVALIDATE, &cookie->flags); +		fallthrough;  	case FSCACHE_COOKIE_STATE_CREATING:  		spin_unlock(&cookie->lock);  		_leave(" [look %x]", cookie->inval_counter); |