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

Commit 9944a0f2 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'rhashtable-New-features-in-walk-and-bucket'



Tom Herbert says:

====================
rhashtable: New features in walk and bucket

This patch contains some changes to related rhashtable:

- Above allow rhashtable_walk_start to return void
- Add a functon to peek at the next entry during a walk
- Abstract out function to compute a has for a table
- A library function to alloc a spinlocks bucket array
- Call the above function for rhashtable locks allocation

Tested: Exercised using various operations on an ILA xlat
table.

v2:
 - Apply feedback from Herbert. Don't change semantics of resize
   event reporting and -EAGAIN, just simplify API for callers that
   ignore those.
 - Add end_of_table in iter to reliably tell when the iterator has
   reached to the eno.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents a0b586fa 64e0cd0d
Loading
Loading
Loading
Loading
+1 −5
Original line number Diff line number Diff line
@@ -1412,11 +1412,7 @@ bnxt_tc_flow_stats_batch_prep(struct bnxt *bp,
	void *flow_node;
	int rc, i;

	rc = rhashtable_walk_start(iter);
	if (rc && rc != -EAGAIN) {
		i = 0;
		goto done;
	}
	rhashtable_walk_start(iter);

	rc = 0;
	for (i = 0; i < BNXT_FLOW_STATS_BATCH_MAX; i++) {
+3 −4
Original line number Diff line number Diff line
@@ -763,9 +763,7 @@ static void ch_flower_stats_handler(struct work_struct *work)

	rhashtable_walk_enter(&adap->flower_tbl, &iter);
	do {
		flower_entry = ERR_PTR(rhashtable_walk_start(&iter));
		if (IS_ERR(flower_entry))
			goto walk_stop;
		rhashtable_walk_start(&iter);

		while ((flower_entry = rhashtable_walk_next(&iter)) &&
		       !IS_ERR(flower_entry)) {
@@ -784,8 +782,9 @@ static void ch_flower_stats_handler(struct work_struct *work)
				spin_unlock(&flower_entry->lock);
			}
		}
walk_stop:

		rhashtable_walk_stop(&iter);

	} while (flower_entry == ERR_PTR(-EAGAIN));
	rhashtable_walk_exit(&iter);
	mod_timer(&adap->flower_stats_timer, jiffies + STATS_CHECK_PERIOD);
+2 −5
Original line number Diff line number Diff line
@@ -1549,16 +1549,13 @@ static void glock_hash_walk(glock_examiner examiner, const struct gfs2_sbd *sdp)
	rhashtable_walk_enter(&gl_hash_table, &iter);

	do {
		gl = ERR_PTR(rhashtable_walk_start(&iter));
		if (IS_ERR(gl))
			goto walk_stop;
		rhashtable_walk_start(&iter);

		while ((gl = rhashtable_walk_next(&iter)) && !IS_ERR(gl))
			if (gl->gl_name.ln_sbd == sdp &&
			    lockref_get_not_dead(&gl->gl_lockref))
				examiner(gl);

walk_stop:
		rhashtable_walk_stop(&iter);
	} while (cond_resched(), gl == ERR_PTR(-EAGAIN));

@@ -1947,7 +1944,7 @@ static void *gfs2_glock_seq_start(struct seq_file *seq, loff_t *pos)
	loff_t n = *pos;

	rhashtable_walk_enter(&gl_hash_table, &gi->hti);
	if (rhashtable_walk_start(&gi->hti) != 0)
	if (rhashtable_walk_start_check(&gi->hti) != 0)
		return NULL;

	do {
+27 −11
Original line number Diff line number Diff line
@@ -207,6 +207,7 @@ struct rhashtable_iter {
	struct rhashtable_walker walker;
	unsigned int slot;
	unsigned int skip;
	bool end_of_table;
};

static inline unsigned long rht_marker(const struct rhashtable *ht, u32 hash)
@@ -239,34 +240,42 @@ static inline unsigned int rht_bucket_index(const struct bucket_table *tbl,
	return (hash >> RHT_HASH_RESERVED_SPACE) & (tbl->size - 1);
}

static inline unsigned int rht_key_hashfn(
	struct rhashtable *ht, const struct bucket_table *tbl,
	const void *key, const struct rhashtable_params params)
static inline unsigned int rht_key_get_hash(struct rhashtable *ht,
	const void *key, const struct rhashtable_params params,
	unsigned int hash_rnd)
{
	unsigned int hash;

	/* params must be equal to ht->p if it isn't constant. */
	if (!__builtin_constant_p(params.key_len))
		hash = ht->p.hashfn(key, ht->key_len, tbl->hash_rnd);
		hash = ht->p.hashfn(key, ht->key_len, hash_rnd);
	else if (params.key_len) {
		unsigned int key_len = params.key_len;

		if (params.hashfn)
			hash = params.hashfn(key, key_len, tbl->hash_rnd);
			hash = params.hashfn(key, key_len, hash_rnd);
		else if (key_len & (sizeof(u32) - 1))
			hash = jhash(key, key_len, tbl->hash_rnd);
			hash = jhash(key, key_len, hash_rnd);
		else
			hash = jhash2(key, key_len / sizeof(u32),
				      tbl->hash_rnd);
			hash = jhash2(key, key_len / sizeof(u32), hash_rnd);
	} else {
		unsigned int key_len = ht->p.key_len;

		if (params.hashfn)
			hash = params.hashfn(key, key_len, tbl->hash_rnd);
			hash = params.hashfn(key, key_len, hash_rnd);
		else
			hash = jhash(key, key_len, tbl->hash_rnd);
			hash = jhash(key, key_len, hash_rnd);
	}

	return hash;
}

static inline unsigned int rht_key_hashfn(
	struct rhashtable *ht, const struct bucket_table *tbl,
	const void *key, const struct rhashtable_params params)
{
	unsigned int hash = rht_key_get_hash(ht, key, params, tbl->hash_rnd);

	return rht_bucket_index(tbl, hash);
}

@@ -378,8 +387,15 @@ void *rhashtable_insert_slow(struct rhashtable *ht, const void *key,
void rhashtable_walk_enter(struct rhashtable *ht,
			   struct rhashtable_iter *iter);
void rhashtable_walk_exit(struct rhashtable_iter *iter);
int rhashtable_walk_start(struct rhashtable_iter *iter) __acquires(RCU);
int rhashtable_walk_start_check(struct rhashtable_iter *iter) __acquires(RCU);

static inline void rhashtable_walk_start(struct rhashtable_iter *iter)
{
	(void)rhashtable_walk_start_check(iter);
}

void *rhashtable_walk_next(struct rhashtable_iter *iter);
void *rhashtable_walk_peek(struct rhashtable_iter *iter);
void rhashtable_walk_stop(struct rhashtable_iter *iter) __releases(RCU);

void rhashtable_free_and_destroy(struct rhashtable *ht,
+6 −0
Original line number Diff line number Diff line
@@ -414,4 +414,10 @@ extern int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock);
#define atomic_dec_and_lock(atomic, lock) \
		__cond_lock(lock, _atomic_dec_and_lock(atomic, lock))

int alloc_bucket_spinlocks(spinlock_t **locks, unsigned int *lock_mask,
			   size_t max_size, unsigned int cpu_mult,
			   gfp_t gfp);

void free_bucket_spinlocks(spinlock_t *locks);

#endif /* __LINUX_SPINLOCK_H */
Loading