Esempio n. 1
0
/*
 * This is the generic cache management routine for all
 * the authentication caches.
 * It checks the currency of a cache item and will (later)
 * initiate an upcall to fill it if needed.
 *
 *
 * Returns 0 if the cache_head can be used, or cache_puts it and returns
 * -EAGAIN if upcall is pending,
 * -ENOENT if cache entry was negative
 */
int cache_check(struct cache_detail *detail,
		    struct cache_head *h, struct cache_req *rqstp)
{
	int rv;
	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;
	}

	/* now see if we want to start an upcall */
	refresh_age = (h->expiry_time - h->last_refresh);
	age = get_seconds() - h->last_refresh;

	if (rqstp == NULL) {
		if (rv == -EAGAIN)
			rv = -ENOENT;
	} else if (rv == -EAGAIN || age > refresh_age/2) {
		dprintk("Want update, refage=%ld, age=%ld\n", refresh_age, age);
		if (!test_and_set_bit(CACHE_PENDING, &h->flags)) {
			switch (cache_make_upcall(detail, h)) {
			case -EINVAL:
				clear_bit(CACHE_PENDING, &h->flags);
				if (rv == -EAGAIN) {
					set_bit(CACHE_NEGATIVE, &h->flags);
					cache_fresh(detail, h, get_seconds()+CACHE_NEW_EXPIRY);
					rv = -ENOENT;
				}
				break;

			case -EAGAIN:
				clear_bit(CACHE_PENDING, &h->flags);
				cache_revisit_request(h);
				break;
			}
		}
	}

	if (rv == -EAGAIN)
		cache_defer_req(rqstp, h);

	if (rv && h)
		detail->cache_put(h, detail);
	return rv;
}
Esempio n. 2
0
struct auth_domain *
auth_domain_lookup(struct auth_domain *item, int set)
{
	struct auth_domain *tmp = NULL;
	struct cache_head **hp, **head;
	head = &auth_domain_cache.hash_table[auth_domain_hash(item)];

	if (set)
		write_lock(&auth_domain_cache.hash_lock);
	else
		read_lock(&auth_domain_cache.hash_lock);
	for (hp=head; *hp != NULL; hp = &tmp->h.next) {
		tmp = container_of(*hp, struct auth_domain, h);
		if (!auth_domain_match(tmp, item))
			continue;
		cache_get(&tmp->h);
		if (!set)
			goto out_noset;
		*hp = tmp->h.next;
		tmp->h.next = NULL;
		clear_bit(CACHE_HASHED, &tmp->h.flags);
		auth_domain_drop(&tmp->h, &auth_domain_cache);
		goto out_set;
	}
	/* Didn't find anything */
	if (!set)
		goto out_nada;
	auth_domain_cache.entries++;
out_set:
	set_bit(CACHE_HASHED, &item->h.flags);
	item->h.next = *head;
	*head = &item->h;
	write_unlock(&auth_domain_cache.hash_lock);
	cache_fresh(&auth_domain_cache, &item->h, item->h.expiry_time);
	cache_get(&item->h);
	return item;
out_nada:
	tmp = NULL;
out_noset:
	read_unlock(&auth_domain_cache.hash_lock);
	return tmp;
}