Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 989a19b9 authored by NeilBrown's avatar NeilBrown Committed by J. Bruce Fields
Browse files

sunrpc/cache: recheck cache validity after cache_defer_req



If cache_defer_req did not leave the request on a queue, then it could
possibly have waited long enough that the cache became valid.  So check the
status after the call.

Signed-off-by: default avatarNeilBrown <neilb@suse.de>
Signed-off-by: default avatarJ. Bruce Fields <bfields@citi.umich.edu>
parent 5c4d2639
Loading
Loading
Loading
Loading
+33 −20
Original line number Diff line number Diff line
@@ -176,6 +176,22 @@ struct cache_head *sunrpc_cache_update(struct cache_detail *detail,
EXPORT_SYMBOL_GPL(sunrpc_cache_update);

static int cache_make_upcall(struct cache_detail *detail, struct cache_head *h);

static inline int cache_is_valid(struct cache_detail *detail, struct cache_head *h)
{
	if (!test_bit(CACHE_VALID, &h->flags) ||
	    h->expiry_time < get_seconds())
		return -EAGAIN;
	else if (detail->flush_time > h->last_refresh)
		return -EAGAIN;
	else {
		/* entry is valid */
		if (test_bit(CACHE_NEGATIVE, &h->flags))
			return -ENOENT;
		else
			return 0;
	}
}
/*
 * This is the generic cache management routine for all
 * the authentication caches.
@@ -184,8 +200,10 @@ static int cache_make_upcall(struct cache_detail *detail, struct cache_head *h);
 *
 *
 * Returns 0 if the cache_head can be used, or cache_puts it and returns
 * -EAGAIN if upcall is pending,
 * -ETIMEDOUT if upcall failed and should be retried,
 * -EAGAIN if upcall is pending and request has been queued
 * -ETIMEDOUT if upcall failed or request could not be queue or
 *           upcall completed but item is still invalid (implying that
 *           the cache item has been replaced with a newer one).
 * -ENOENT if cache entry was negative
 */
int cache_check(struct cache_detail *detail,
@@ -195,17 +213,7 @@ int cache_check(struct cache_detail *detail,
	long refresh_age, age;

	/* First decide return status as best we can */
	if (!test_bit(CACHE_VALID, &h->flags) ||
	    h->expiry_time < get_seconds())
		rv = -EAGAIN;
	else if (detail->flush_time > h->last_refresh)
		rv = -EAGAIN;
	else {
		/* entry is valid */
		if (test_bit(CACHE_NEGATIVE, &h->flags))
			rv = -ENOENT;
		else rv = 0;
	}
	rv = cache_is_valid(detail, h);

	/* now see if we want to start an upcall */
	refresh_age = (h->expiry_time - h->last_refresh);
@@ -238,10 +246,14 @@ int cache_check(struct cache_detail *detail,
		}
	}

	if (rv == -EAGAIN) {
		if (cache_defer_req(rqstp, h) == 0) {
			/* Request is not deferred */
			rv = cache_is_valid(detail, h);
			if (rv == -EAGAIN)
		if (cache_defer_req(rqstp, h) != 0)
				rv = -ETIMEDOUT;

		}
	}
	if (rv)
		cache_put(h, detail);
	return rv;
@@ -560,11 +572,11 @@ static int cache_defer_req(struct cache_req *req, struct cache_head *item)
		 * or continue and drop the oldest below
		 */
		if (net_random()&1)
			return -ETIMEDOUT;
			return 0;
	}
	dreq = req->defer(req);
	if (dreq == NULL)
		return -ETIMEDOUT;
		return 0;

	dreq->item = item;

@@ -594,9 +606,10 @@ static int cache_defer_req(struct cache_req *req, struct cache_head *item)
	if (!test_bit(CACHE_PENDING, &item->flags)) {
		/* must have just been validated... */
		cache_revisit_request(item);
	}
		return 0;
	}
	return 1;
}

static void cache_revisit_request(struct cache_head *item)
{