static void h_remove(struct hash_table *ht, struct entry *e) { unsigned h = hash_64(from_oblock(e->oblock), ht->hash_bits); struct entry *prev; /* * The down side of using a singly linked list is we have to * iterate the bucket to remove an item. */ e = __h_lookup(ht, h, e->oblock, &prev); if (e) __h_unlink(ht, h, e, prev); }
static struct entry *hash_lookup(struct mq_policy *mq, dm_oblock_t oblock) { unsigned h = hash_64(from_oblock(oblock), mq->hash_bits); struct hlist_head *bucket = mq->table + h; struct entry *e; hlist_for_each_entry(e, bucket, hlist) if (e->oblock == oblock) { hlist_del(&e->hlist); hlist_add_head(&e->hlist, bucket); return e; } return NULL; }
/* * Also moves each entry to the front of the bucket. */ static struct entry *h_lookup(struct hash_table *ht, dm_oblock_t oblock) { struct entry *e, *prev; unsigned h = hash_64(from_oblock(oblock), ht->hash_bits); e = __h_lookup(ht, h, oblock, &prev); if (e && prev) { /* * Move to the front because this entry is likely * to be hit again. */ __h_unlink(ht, h, e, prev); __h_insert(ht, h, e); } return e; }
static void iot_update_stats(struct io_tracker *t, struct bio *bio) { if (bio->bi_iter.bi_sector == from_oblock(t->last_end_oblock) + 1) t->nr_seq_samples++; else { /* * Just one non-sequential IO is enough to reset the * counters. */ if (t->nr_seq_samples) { t->nr_seq_samples = 0; t->nr_rand_samples = 0; } t->nr_rand_samples++; } t->last_end_oblock = to_oblock(bio_end_sector(bio) - 1); }
/* * Simple hash table implementation. Should replace with the standard hash * table that's making its way upstream. */ static void hash_insert(struct mq_policy *mq, struct entry *e) { unsigned h = hash_64(from_oblock(e->oblock), mq->hash_bits); hlist_add_head(&e->hlist, mq->table + h); }
static void h_insert(struct hash_table *ht, struct entry *e) { unsigned h = hash_64(from_oblock(e->oblock), ht->hash_bits); __h_insert(ht, h, e); }
static dm_oblock_t to_hblock(struct smq_policy *mq, dm_oblock_t b) { sector_t r = from_oblock(b); (void) sector_div(r, mq->cache_blocks_per_hotspot_block); return to_oblock(r); }