dm-bio-prison.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  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 bucket {
  14. spinlock_t lock;
  15. struct hlist_head cells;
  16. };
  17. struct dm_bio_prison {
  18. mempool_t *cell_pool;
  19. unsigned nr_buckets;
  20. unsigned hash_mask;
  21. struct bucket *buckets;
  22. };
  23. /*----------------------------------------------------------------*/
  24. static uint32_t calc_nr_buckets(unsigned nr_cells)
  25. {
  26. uint32_t n = 128;
  27. nr_cells /= 4;
  28. nr_cells = min(nr_cells, 8192u);
  29. while (n < nr_cells)
  30. n <<= 1;
  31. return n;
  32. }
  33. static struct kmem_cache *_cell_cache;
  34. static void init_bucket(struct bucket *b)
  35. {
  36. spin_lock_init(&b->lock);
  37. INIT_HLIST_HEAD(&b->cells);
  38. }
  39. /*
  40. * @nr_cells should be the number of cells you want in use _concurrently_.
  41. * Don't confuse it with the number of distinct keys.
  42. */
  43. struct dm_bio_prison *dm_bio_prison_create(unsigned nr_cells)
  44. {
  45. unsigned i;
  46. uint32_t nr_buckets = calc_nr_buckets(nr_cells);
  47. size_t len = sizeof(struct dm_bio_prison) +
  48. (sizeof(struct bucket) * nr_buckets);
  49. struct dm_bio_prison *prison = kmalloc(len, GFP_KERNEL);
  50. if (!prison)
  51. return NULL;
  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->buckets = (struct bucket *) (prison + 1);
  60. for (i = 0; i < nr_buckets; i++)
  61. init_bucket(prison->buckets + 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. struct dm_bio_prison_cell *dm_bio_prison_alloc_cell(struct dm_bio_prison *prison, gfp_t gfp)
  72. {
  73. return mempool_alloc(prison->cell_pool, gfp);
  74. }
  75. EXPORT_SYMBOL_GPL(dm_bio_prison_alloc_cell);
  76. void dm_bio_prison_free_cell(struct dm_bio_prison *prison,
  77. struct dm_bio_prison_cell *cell)
  78. {
  79. mempool_free(cell, prison->cell_pool);
  80. }
  81. EXPORT_SYMBOL_GPL(dm_bio_prison_free_cell);
  82. static uint32_t hash_key(struct dm_bio_prison *prison, struct dm_cell_key *key)
  83. {
  84. const unsigned long BIG_PRIME = 4294967291UL;
  85. uint64_t hash = key->block * BIG_PRIME;
  86. return (uint32_t) (hash & prison->hash_mask);
  87. }
  88. static int keys_equal(struct dm_cell_key *lhs, struct dm_cell_key *rhs)
  89. {
  90. return (lhs->virtual == rhs->virtual) &&
  91. (lhs->dev == rhs->dev) &&
  92. (lhs->block == rhs->block);
  93. }
  94. static struct bucket *get_bucket(struct dm_bio_prison *prison,
  95. struct dm_cell_key *key)
  96. {
  97. return prison->buckets + hash_key(prison, key);
  98. }
  99. static struct dm_bio_prison_cell *__search_bucket(struct bucket *b,
  100. struct dm_cell_key *key)
  101. {
  102. struct dm_bio_prison_cell *cell;
  103. hlist_for_each_entry(cell, &b->cells, list)
  104. if (keys_equal(&cell->key, key))
  105. return cell;
  106. return NULL;
  107. }
  108. static void __setup_new_cell(struct bucket *b,
  109. struct dm_cell_key *key,
  110. struct bio *holder,
  111. struct dm_bio_prison_cell *cell)
  112. {
  113. memcpy(&cell->key, key, sizeof(cell->key));
  114. cell->holder = holder;
  115. bio_list_init(&cell->bios);
  116. hlist_add_head(&cell->list, &b->cells);
  117. }
  118. static int __bio_detain(struct bucket *b,
  119. struct dm_cell_key *key,
  120. struct bio *inmate,
  121. struct dm_bio_prison_cell *cell_prealloc,
  122. struct dm_bio_prison_cell **cell_result)
  123. {
  124. struct dm_bio_prison_cell *cell;
  125. cell = __search_bucket(b, key);
  126. if (cell) {
  127. if (inmate)
  128. bio_list_add(&cell->bios, inmate);
  129. *cell_result = cell;
  130. return 1;
  131. }
  132. __setup_new_cell(b, key, inmate, cell_prealloc);
  133. *cell_result = cell_prealloc;
  134. return 0;
  135. }
  136. static int bio_detain(struct dm_bio_prison *prison,
  137. struct dm_cell_key *key,
  138. struct bio *inmate,
  139. struct dm_bio_prison_cell *cell_prealloc,
  140. struct dm_bio_prison_cell **cell_result)
  141. {
  142. int r;
  143. unsigned long flags;
  144. struct bucket *b = get_bucket(prison, key);
  145. spin_lock_irqsave(&b->lock, flags);
  146. r = __bio_detain(b, key, inmate, cell_prealloc, cell_result);
  147. spin_unlock_irqrestore(&b->lock, flags);
  148. return r;
  149. }
  150. int dm_bio_detain(struct dm_bio_prison *prison,
  151. struct dm_cell_key *key,
  152. struct bio *inmate,
  153. struct dm_bio_prison_cell *cell_prealloc,
  154. struct dm_bio_prison_cell **cell_result)
  155. {
  156. return bio_detain(prison, key, inmate, cell_prealloc, cell_result);
  157. }
  158. EXPORT_SYMBOL_GPL(dm_bio_detain);
  159. int dm_get_cell(struct dm_bio_prison *prison,
  160. struct dm_cell_key *key,
  161. struct dm_bio_prison_cell *cell_prealloc,
  162. struct dm_bio_prison_cell **cell_result)
  163. {
  164. return bio_detain(prison, key, NULL, cell_prealloc, cell_result);
  165. }
  166. EXPORT_SYMBOL_GPL(dm_get_cell);
  167. /*
  168. * @inmates must have been initialised prior to this call
  169. */
  170. static void __cell_release(struct dm_bio_prison_cell *cell,
  171. struct bio_list *inmates)
  172. {
  173. hlist_del(&cell->list);
  174. if (inmates) {
  175. if (cell->holder)
  176. bio_list_add(inmates, cell->holder);
  177. bio_list_merge(inmates, &cell->bios);
  178. }
  179. }
  180. void dm_cell_release(struct dm_bio_prison *prison,
  181. struct dm_bio_prison_cell *cell,
  182. struct bio_list *bios)
  183. {
  184. unsigned long flags;
  185. struct bucket *b = get_bucket(prison, &cell->key);
  186. spin_lock_irqsave(&b->lock, flags);
  187. __cell_release(cell, bios);
  188. spin_unlock_irqrestore(&b->lock, flags);
  189. }
  190. EXPORT_SYMBOL_GPL(dm_cell_release);
  191. /*
  192. * Sometimes we don't want the holder, just the additional bios.
  193. */
  194. static void __cell_release_no_holder(struct dm_bio_prison_cell *cell,
  195. struct bio_list *inmates)
  196. {
  197. hlist_del(&cell->list);
  198. bio_list_merge(inmates, &cell->bios);
  199. }
  200. void dm_cell_release_no_holder(struct dm_bio_prison *prison,
  201. struct dm_bio_prison_cell *cell,
  202. struct bio_list *inmates)
  203. {
  204. unsigned long flags;
  205. struct bucket *b = get_bucket(prison, &cell->key);
  206. spin_lock_irqsave(&b->lock, flags);
  207. __cell_release_no_holder(cell, inmates);
  208. spin_unlock_irqrestore(&b->lock, flags);
  209. }
  210. EXPORT_SYMBOL_GPL(dm_cell_release_no_holder);
  211. void dm_cell_error(struct dm_bio_prison *prison,
  212. struct dm_bio_prison_cell *cell, int error)
  213. {
  214. struct bio_list bios;
  215. struct bio *bio;
  216. bio_list_init(&bios);
  217. dm_cell_release(prison, cell, &bios);
  218. while ((bio = bio_list_pop(&bios)))
  219. bio_endio(bio, error);
  220. }
  221. EXPORT_SYMBOL_GPL(dm_cell_error);
  222. /*----------------------------------------------------------------*/
  223. #define DEFERRED_SET_SIZE 64
  224. struct dm_deferred_entry {
  225. struct dm_deferred_set *ds;
  226. unsigned count;
  227. struct list_head work_items;
  228. };
  229. struct dm_deferred_set {
  230. spinlock_t lock;
  231. unsigned current_entry;
  232. unsigned sweeper;
  233. struct dm_deferred_entry entries[DEFERRED_SET_SIZE];
  234. };
  235. struct dm_deferred_set *dm_deferred_set_create(void)
  236. {
  237. int i;
  238. struct dm_deferred_set *ds;
  239. ds = kmalloc(sizeof(*ds), GFP_KERNEL);
  240. if (!ds)
  241. return NULL;
  242. spin_lock_init(&ds->lock);
  243. ds->current_entry = 0;
  244. ds->sweeper = 0;
  245. for (i = 0; i < DEFERRED_SET_SIZE; i++) {
  246. ds->entries[i].ds = ds;
  247. ds->entries[i].count = 0;
  248. INIT_LIST_HEAD(&ds->entries[i].work_items);
  249. }
  250. return ds;
  251. }
  252. EXPORT_SYMBOL_GPL(dm_deferred_set_create);
  253. void dm_deferred_set_destroy(struct dm_deferred_set *ds)
  254. {
  255. kfree(ds);
  256. }
  257. EXPORT_SYMBOL_GPL(dm_deferred_set_destroy);
  258. struct dm_deferred_entry *dm_deferred_entry_inc(struct dm_deferred_set *ds)
  259. {
  260. unsigned long flags;
  261. struct dm_deferred_entry *entry;
  262. spin_lock_irqsave(&ds->lock, flags);
  263. entry = ds->entries + ds->current_entry;
  264. entry->count++;
  265. spin_unlock_irqrestore(&ds->lock, flags);
  266. return entry;
  267. }
  268. EXPORT_SYMBOL_GPL(dm_deferred_entry_inc);
  269. static unsigned ds_next(unsigned index)
  270. {
  271. return (index + 1) % DEFERRED_SET_SIZE;
  272. }
  273. static void __sweep(struct dm_deferred_set *ds, struct list_head *head)
  274. {
  275. while ((ds->sweeper != ds->current_entry) &&
  276. !ds->entries[ds->sweeper].count) {
  277. list_splice_init(&ds->entries[ds->sweeper].work_items, head);
  278. ds->sweeper = ds_next(ds->sweeper);
  279. }
  280. if ((ds->sweeper == ds->current_entry) && !ds->entries[ds->sweeper].count)
  281. list_splice_init(&ds->entries[ds->sweeper].work_items, head);
  282. }
  283. void dm_deferred_entry_dec(struct dm_deferred_entry *entry, struct list_head *head)
  284. {
  285. unsigned long flags;
  286. spin_lock_irqsave(&entry->ds->lock, flags);
  287. BUG_ON(!entry->count);
  288. --entry->count;
  289. __sweep(entry->ds, head);
  290. spin_unlock_irqrestore(&entry->ds->lock, flags);
  291. }
  292. EXPORT_SYMBOL_GPL(dm_deferred_entry_dec);
  293. /*
  294. * Returns 1 if deferred or 0 if no pending items to delay job.
  295. */
  296. int dm_deferred_set_add_work(struct dm_deferred_set *ds, struct list_head *work)
  297. {
  298. int r = 1;
  299. unsigned long flags;
  300. unsigned next_entry;
  301. spin_lock_irqsave(&ds->lock, flags);
  302. if ((ds->sweeper == ds->current_entry) &&
  303. !ds->entries[ds->current_entry].count)
  304. r = 0;
  305. else {
  306. list_add(work, &ds->entries[ds->current_entry].work_items);
  307. next_entry = ds_next(ds->current_entry);
  308. if (!ds->entries[next_entry].count)
  309. ds->current_entry = next_entry;
  310. }
  311. spin_unlock_irqrestore(&ds->lock, flags);
  312. return r;
  313. }
  314. EXPORT_SYMBOL_GPL(dm_deferred_set_add_work);
  315. /*----------------------------------------------------------------*/
  316. static int __init dm_bio_prison_init(void)
  317. {
  318. _cell_cache = KMEM_CACHE(dm_bio_prison_cell, 0);
  319. if (!_cell_cache)
  320. return -ENOMEM;
  321. return 0;
  322. }
  323. static void __exit dm_bio_prison_exit(void)
  324. {
  325. kmem_cache_destroy(_cell_cache);
  326. _cell_cache = NULL;
  327. }
  328. /*
  329. * module hooks
  330. */
  331. module_init(dm_bio_prison_init);
  332. module_exit(dm_bio_prison_exit);
  333. MODULE_DESCRIPTION(DM_NAME " bio prison");
  334. MODULE_AUTHOR("Joe Thornber <dm-devel@redhat.com>");
  335. MODULE_LICENSE("GPL");