dm-bio-prison.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. /*
  2. * Copyright (C) 2012 Red Hat, Inc.
  3. *
  4. * This file is released under the GPL.
  5. */
  6. #include "dm.h"
  7. #include "dm-bio-prison.h"
  8. #include <linux/spinlock.h>
  9. #include <linux/mempool.h>
  10. #include <linux/module.h>
  11. #include <linux/slab.h>
  12. /*----------------------------------------------------------------*/
  13. struct dm_bio_prison_cell {
  14. struct hlist_node list;
  15. struct dm_bio_prison *prison;
  16. struct dm_cell_key key;
  17. struct bio *holder;
  18. struct bio_list bios;
  19. };
  20. struct dm_bio_prison {
  21. spinlock_t lock;
  22. mempool_t *cell_pool;
  23. unsigned nr_buckets;
  24. unsigned hash_mask;
  25. struct hlist_head *cells;
  26. };
  27. /*----------------------------------------------------------------*/
  28. static uint32_t calc_nr_buckets(unsigned nr_cells)
  29. {
  30. uint32_t n = 128;
  31. nr_cells /= 4;
  32. nr_cells = min(nr_cells, 8192u);
  33. while (n < nr_cells)
  34. n <<= 1;
  35. return n;
  36. }
  37. static struct kmem_cache *_cell_cache;
  38. /*
  39. * @nr_cells should be the number of cells you want in use _concurrently_.
  40. * Don't confuse it with the number of distinct keys.
  41. */
  42. struct dm_bio_prison *dm_bio_prison_create(unsigned nr_cells)
  43. {
  44. unsigned i;
  45. uint32_t nr_buckets = calc_nr_buckets(nr_cells);
  46. size_t len = sizeof(struct dm_bio_prison) +
  47. (sizeof(struct hlist_head) * nr_buckets);
  48. struct dm_bio_prison *prison = kmalloc(len, GFP_KERNEL);
  49. if (!prison)
  50. return NULL;
  51. spin_lock_init(&prison->lock);
  52. prison->cell_pool = mempool_create_slab_pool(nr_cells, _cell_cache);
  53. if (!prison->cell_pool) {
  54. kfree(prison);
  55. return NULL;
  56. }
  57. prison->nr_buckets = nr_buckets;
  58. prison->hash_mask = nr_buckets - 1;
  59. prison->cells = (struct hlist_head *) (prison + 1);
  60. for (i = 0; i < nr_buckets; i++)
  61. INIT_HLIST_HEAD(prison->cells + i);
  62. return prison;
  63. }
  64. EXPORT_SYMBOL_GPL(dm_bio_prison_create);
  65. void dm_bio_prison_destroy(struct dm_bio_prison *prison)
  66. {
  67. mempool_destroy(prison->cell_pool);
  68. kfree(prison);
  69. }
  70. EXPORT_SYMBOL_GPL(dm_bio_prison_destroy);
  71. static uint32_t hash_key(struct dm_bio_prison *prison, struct dm_cell_key *key)
  72. {
  73. const unsigned long BIG_PRIME = 4294967291UL;
  74. uint64_t hash = key->block * BIG_PRIME;
  75. return (uint32_t) (hash & prison->hash_mask);
  76. }
  77. static int keys_equal(struct dm_cell_key *lhs, struct dm_cell_key *rhs)
  78. {
  79. return (lhs->virtual == rhs->virtual) &&
  80. (lhs->dev == rhs->dev) &&
  81. (lhs->block == rhs->block);
  82. }
  83. static struct dm_bio_prison_cell *__search_bucket(struct hlist_head *bucket,
  84. struct dm_cell_key *key)
  85. {
  86. struct dm_bio_prison_cell *cell;
  87. struct hlist_node *tmp;
  88. hlist_for_each_entry(cell, tmp, bucket, list)
  89. if (keys_equal(&cell->key, key))
  90. return cell;
  91. return NULL;
  92. }
  93. /*
  94. * This may block if a new cell needs allocating. You must ensure that
  95. * cells will be unlocked even if the calling thread is blocked.
  96. *
  97. * Returns 1 if the cell was already held, 0 if @inmate is the new holder.
  98. */
  99. int dm_bio_detain(struct dm_bio_prison *prison, struct dm_cell_key *key,
  100. struct bio *inmate, struct dm_bio_prison_cell **ref)
  101. {
  102. int r = 1;
  103. unsigned long flags;
  104. uint32_t hash = hash_key(prison, key);
  105. struct dm_bio_prison_cell *cell, *cell2;
  106. BUG_ON(hash > prison->nr_buckets);
  107. spin_lock_irqsave(&prison->lock, flags);
  108. cell = __search_bucket(prison->cells + hash, key);
  109. if (cell) {
  110. bio_list_add(&cell->bios, inmate);
  111. goto out;
  112. }
  113. /*
  114. * Allocate a new cell
  115. */
  116. spin_unlock_irqrestore(&prison->lock, flags);
  117. cell2 = mempool_alloc(prison->cell_pool, GFP_NOIO);
  118. spin_lock_irqsave(&prison->lock, flags);
  119. /*
  120. * We've been unlocked, so we have to double check that
  121. * nobody else has inserted this cell in the meantime.
  122. */
  123. cell = __search_bucket(prison->cells + hash, key);
  124. if (cell) {
  125. mempool_free(cell2, prison->cell_pool);
  126. bio_list_add(&cell->bios, inmate);
  127. goto out;
  128. }
  129. /*
  130. * Use new cell.
  131. */
  132. cell = cell2;
  133. cell->prison = prison;
  134. memcpy(&cell->key, key, sizeof(cell->key));
  135. cell->holder = inmate;
  136. bio_list_init(&cell->bios);
  137. hlist_add_head(&cell->list, prison->cells + hash);
  138. r = 0;
  139. out:
  140. spin_unlock_irqrestore(&prison->lock, flags);
  141. *ref = cell;
  142. return r;
  143. }
  144. EXPORT_SYMBOL_GPL(dm_bio_detain);
  145. /*
  146. * @inmates must have been initialised prior to this call
  147. */
  148. static void __cell_release(struct dm_bio_prison_cell *cell, struct bio_list *inmates)
  149. {
  150. struct dm_bio_prison *prison = cell->prison;
  151. hlist_del(&cell->list);
  152. if (inmates) {
  153. bio_list_add(inmates, cell->holder);
  154. bio_list_merge(inmates, &cell->bios);
  155. }
  156. mempool_free(cell, prison->cell_pool);
  157. }
  158. void dm_cell_release(struct dm_bio_prison_cell *cell, struct bio_list *bios)
  159. {
  160. unsigned long flags;
  161. struct dm_bio_prison *prison = cell->prison;
  162. spin_lock_irqsave(&prison->lock, flags);
  163. __cell_release(cell, bios);
  164. spin_unlock_irqrestore(&prison->lock, flags);
  165. }
  166. EXPORT_SYMBOL_GPL(dm_cell_release);
  167. /*
  168. * Sometimes we don't want the holder, just the additional bios.
  169. */
  170. static void __cell_release_no_holder(struct dm_bio_prison_cell *cell, struct bio_list *inmates)
  171. {
  172. struct dm_bio_prison *prison = cell->prison;
  173. hlist_del(&cell->list);
  174. bio_list_merge(inmates, &cell->bios);
  175. mempool_free(cell, prison->cell_pool);
  176. }
  177. void dm_cell_release_no_holder(struct dm_bio_prison_cell *cell, struct bio_list *inmates)
  178. {
  179. unsigned long flags;
  180. struct dm_bio_prison *prison = cell->prison;
  181. spin_lock_irqsave(&prison->lock, flags);
  182. __cell_release_no_holder(cell, inmates);
  183. spin_unlock_irqrestore(&prison->lock, flags);
  184. }
  185. EXPORT_SYMBOL_GPL(dm_cell_release_no_holder);
  186. void dm_cell_error(struct dm_bio_prison_cell *cell)
  187. {
  188. struct dm_bio_prison *prison = cell->prison;
  189. struct bio_list bios;
  190. struct bio *bio;
  191. unsigned long flags;
  192. bio_list_init(&bios);
  193. spin_lock_irqsave(&prison->lock, flags);
  194. __cell_release(cell, &bios);
  195. spin_unlock_irqrestore(&prison->lock, flags);
  196. while ((bio = bio_list_pop(&bios)))
  197. bio_io_error(bio);
  198. }
  199. EXPORT_SYMBOL_GPL(dm_cell_error);
  200. /*----------------------------------------------------------------*/
  201. #define DEFERRED_SET_SIZE 64
  202. struct dm_deferred_entry {
  203. struct dm_deferred_set *ds;
  204. unsigned count;
  205. struct list_head work_items;
  206. };
  207. struct dm_deferred_set {
  208. spinlock_t lock;
  209. unsigned current_entry;
  210. unsigned sweeper;
  211. struct dm_deferred_entry entries[DEFERRED_SET_SIZE];
  212. };
  213. struct dm_deferred_set *dm_deferred_set_create(void)
  214. {
  215. int i;
  216. struct dm_deferred_set *ds;
  217. ds = kmalloc(sizeof(*ds), GFP_KERNEL);
  218. if (!ds)
  219. return NULL;
  220. spin_lock_init(&ds->lock);
  221. ds->current_entry = 0;
  222. ds->sweeper = 0;
  223. for (i = 0; i < DEFERRED_SET_SIZE; i++) {
  224. ds->entries[i].ds = ds;
  225. ds->entries[i].count = 0;
  226. INIT_LIST_HEAD(&ds->entries[i].work_items);
  227. }
  228. return ds;
  229. }
  230. EXPORT_SYMBOL_GPL(dm_deferred_set_create);
  231. void dm_deferred_set_destroy(struct dm_deferred_set *ds)
  232. {
  233. kfree(ds);
  234. }
  235. EXPORT_SYMBOL_GPL(dm_deferred_set_destroy);
  236. struct dm_deferred_entry *dm_deferred_entry_inc(struct dm_deferred_set *ds)
  237. {
  238. unsigned long flags;
  239. struct dm_deferred_entry *entry;
  240. spin_lock_irqsave(&ds->lock, flags);
  241. entry = ds->entries + ds->current_entry;
  242. entry->count++;
  243. spin_unlock_irqrestore(&ds->lock, flags);
  244. return entry;
  245. }
  246. EXPORT_SYMBOL_GPL(dm_deferred_entry_inc);
  247. static unsigned ds_next(unsigned index)
  248. {
  249. return (index + 1) % DEFERRED_SET_SIZE;
  250. }
  251. static void __sweep(struct dm_deferred_set *ds, struct list_head *head)
  252. {
  253. while ((ds->sweeper != ds->current_entry) &&
  254. !ds->entries[ds->sweeper].count) {
  255. list_splice_init(&ds->entries[ds->sweeper].work_items, head);
  256. ds->sweeper = ds_next(ds->sweeper);
  257. }
  258. if ((ds->sweeper == ds->current_entry) && !ds->entries[ds->sweeper].count)
  259. list_splice_init(&ds->entries[ds->sweeper].work_items, head);
  260. }
  261. void dm_deferred_entry_dec(struct dm_deferred_entry *entry, struct list_head *head)
  262. {
  263. unsigned long flags;
  264. spin_lock_irqsave(&entry->ds->lock, flags);
  265. BUG_ON(!entry->count);
  266. --entry->count;
  267. __sweep(entry->ds, head);
  268. spin_unlock_irqrestore(&entry->ds->lock, flags);
  269. }
  270. EXPORT_SYMBOL_GPL(dm_deferred_entry_dec);
  271. /*
  272. * Returns 1 if deferred or 0 if no pending items to delay job.
  273. */
  274. int dm_deferred_set_add_work(struct dm_deferred_set *ds, struct list_head *work)
  275. {
  276. int r = 1;
  277. unsigned long flags;
  278. unsigned next_entry;
  279. spin_lock_irqsave(&ds->lock, flags);
  280. if ((ds->sweeper == ds->current_entry) &&
  281. !ds->entries[ds->current_entry].count)
  282. r = 0;
  283. else {
  284. list_add(work, &ds->entries[ds->current_entry].work_items);
  285. next_entry = ds_next(ds->current_entry);
  286. if (!ds->entries[next_entry].count)
  287. ds->current_entry = next_entry;
  288. }
  289. spin_unlock_irqrestore(&ds->lock, flags);
  290. return r;
  291. }
  292. EXPORT_SYMBOL_GPL(dm_deferred_set_add_work);
  293. /*----------------------------------------------------------------*/
  294. static int __init dm_bio_prison_init(void)
  295. {
  296. _cell_cache = KMEM_CACHE(dm_bio_prison_cell, 0);
  297. if (!_cell_cache)
  298. return -ENOMEM;
  299. return 0;
  300. }
  301. static void __exit dm_bio_prison_exit(void)
  302. {
  303. kmem_cache_destroy(_cell_cache);
  304. _cell_cache = NULL;
  305. }
  306. /*
  307. * module hooks
  308. */
  309. module_init(dm_bio_prison_init);
  310. module_exit(dm_bio_prison_exit);
  311. MODULE_DESCRIPTION(DM_NAME " bio prison");
  312. MODULE_AUTHOR("Joe Thornber <dm-devel@redhat.com>");
  313. MODULE_LICENSE("GPL");