lib/rhashtable.c

Source file repositories/reference/linux-study-clean/lib/rhashtable.c

File Facts

System
Linux kernel
Corpus path
lib/rhashtable.c
Extension
.c
Size
36281 bytes
Lines
1407
Domain
Kernel Services
Bucket
lib
Inferred role
Kernel Services: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Shared kernel service surface used by multiple subsystems, including helpers, cryptography, virtualization support, and async I/O infrastructure.

Dependency Surface

Detected Declarations

Annotated Snippet

rhashtable_compare(&arg, rht_obj(ht, head)))) {
			pprev = &head->next;
			continue;
		}

		if (!ht->rhlist)
			return rht_obj(ht, head);

		list = container_of(obj, struct rhlist_head, rhead);
		plist = container_of(head, struct rhlist_head, rhead);

		RCU_INIT_POINTER(list->next, plist);
		head = rht_dereference_bucket(head->next, tbl, hash);
		RCU_INIT_POINTER(list->rhead.next, head);
		if (pprev)
			rcu_assign_pointer(*pprev, obj);
		else
			/* Need to preserve the bit lock */
			rht_assign_locked(bkt, obj);

		return NULL;
	}

	if (elasticity <= 0 && !ht->p.insecure_elasticity)
		return ERR_PTR(-EAGAIN);

	return ERR_PTR(-ENOENT);
}

static struct bucket_table *rhashtable_insert_one(
	struct rhashtable *ht, struct rhash_lock_head __rcu **bkt,
	struct bucket_table *tbl, unsigned int hash, struct rhash_head *obj,
	void *data)
{
	struct bucket_table *new_tbl;
	struct rhash_head *head;

	if (!IS_ERR_OR_NULL(data))
		return ERR_PTR(-EEXIST);

	if (PTR_ERR(data) != -EAGAIN && PTR_ERR(data) != -ENOENT)
		return ERR_CAST(data);

	new_tbl = rht_dereference_rcu(tbl->future_tbl, ht);
	if (new_tbl)
		return new_tbl;

	if (PTR_ERR(data) != -ENOENT)
		return ERR_CAST(data);

	if (unlikely(rht_grow_above_max(ht, tbl)))
		return ERR_PTR(-E2BIG);

	if (unlikely(rht_grow_above_100(ht, tbl)) &&
	    !ht->p.insecure_elasticity)
		return ERR_PTR(-EAGAIN);

	head = rht_ptr(bkt, tbl, hash);

	RCU_INIT_POINTER(obj->next, head);
	if (ht->rhlist) {
		struct rhlist_head *list;

		list = container_of(obj, struct rhlist_head, rhead);
		RCU_INIT_POINTER(list->next, NULL);
	}

	/* bkt is always the head of the list, so it holds
	 * the lock, which we need to preserve
	 */
	rht_assign_locked(bkt, obj);

	return NULL;
}

static void *rhashtable_try_insert(struct rhashtable *ht, const void *key,
				   struct rhash_head *obj)
{
	struct bucket_table *new_tbl;
	struct bucket_table *tbl;
	struct rhash_lock_head __rcu **bkt;
	unsigned long flags;
	unsigned int hash;
	void *data;

	new_tbl = rcu_dereference(ht->tbl);

	do {
		tbl = new_tbl;
		hash = rht_head_hashfn(ht, tbl, obj, ht->p);

Annotation

Implementation Notes