sg_pool.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #include <linux/module.h>
  2. #include <linux/scatterlist.h>
  3. #include <linux/mempool.h>
  4. #include <linux/slab.h>
  5. #define SG_MEMPOOL_NR ARRAY_SIZE(sg_pools)
  6. #define SG_MEMPOOL_SIZE 2
  7. struct sg_pool {
  8. size_t size;
  9. char *name;
  10. struct kmem_cache *slab;
  11. mempool_t *pool;
  12. };
  13. #define SP(x) { .size = x, "sgpool-" __stringify(x) }
  14. #if (SG_CHUNK_SIZE < 32)
  15. #error SG_CHUNK_SIZE is too small (must be 32 or greater)
  16. #endif
  17. static struct sg_pool sg_pools[] = {
  18. SP(8),
  19. SP(16),
  20. #if (SG_CHUNK_SIZE > 32)
  21. SP(32),
  22. #if (SG_CHUNK_SIZE > 64)
  23. SP(64),
  24. #if (SG_CHUNK_SIZE > 128)
  25. SP(128),
  26. #if (SG_CHUNK_SIZE > 256)
  27. #error SG_CHUNK_SIZE is too large (256 MAX)
  28. #endif
  29. #endif
  30. #endif
  31. #endif
  32. SP(SG_CHUNK_SIZE)
  33. };
  34. #undef SP
  35. static inline unsigned int sg_pool_index(unsigned short nents)
  36. {
  37. unsigned int index;
  38. BUG_ON(nents > SG_CHUNK_SIZE);
  39. if (nents <= 8)
  40. index = 0;
  41. else
  42. index = get_count_order(nents) - 3;
  43. return index;
  44. }
  45. static void sg_pool_free(struct scatterlist *sgl, unsigned int nents)
  46. {
  47. struct sg_pool *sgp;
  48. sgp = sg_pools + sg_pool_index(nents);
  49. mempool_free(sgl, sgp->pool);
  50. }
  51. static struct scatterlist *sg_pool_alloc(unsigned int nents, gfp_t gfp_mask)
  52. {
  53. struct sg_pool *sgp;
  54. sgp = sg_pools + sg_pool_index(nents);
  55. return mempool_alloc(sgp->pool, gfp_mask);
  56. }
  57. /**
  58. * sg_free_table_chained - Free a previously mapped sg table
  59. * @table: The sg table header to use
  60. * @first_chunk: was first_chunk not NULL in sg_alloc_table_chained?
  61. *
  62. * Description:
  63. * Free an sg table previously allocated and setup with
  64. * sg_alloc_table_chained().
  65. *
  66. **/
  67. void sg_free_table_chained(struct sg_table *table, bool first_chunk)
  68. {
  69. if (first_chunk && table->orig_nents <= SG_CHUNK_SIZE)
  70. return;
  71. __sg_free_table(table, SG_CHUNK_SIZE, first_chunk, sg_pool_free);
  72. }
  73. EXPORT_SYMBOL_GPL(sg_free_table_chained);
  74. /**
  75. * sg_alloc_table_chained - Allocate and chain SGLs in an sg table
  76. * @table: The sg table header to use
  77. * @nents: Number of entries in sg list
  78. * @first_chunk: first SGL
  79. *
  80. * Description:
  81. * Allocate and chain SGLs in an sg table. If @nents@ is larger than
  82. * SG_CHUNK_SIZE a chained sg table will be setup.
  83. *
  84. **/
  85. int sg_alloc_table_chained(struct sg_table *table, int nents,
  86. struct scatterlist *first_chunk)
  87. {
  88. int ret;
  89. BUG_ON(!nents);
  90. if (first_chunk) {
  91. if (nents <= SG_CHUNK_SIZE) {
  92. table->nents = table->orig_nents = nents;
  93. sg_init_table(table->sgl, nents);
  94. return 0;
  95. }
  96. }
  97. ret = __sg_alloc_table(table, nents, SG_CHUNK_SIZE,
  98. first_chunk, GFP_ATOMIC, sg_pool_alloc);
  99. if (unlikely(ret))
  100. sg_free_table_chained(table, (bool)first_chunk);
  101. return ret;
  102. }
  103. EXPORT_SYMBOL_GPL(sg_alloc_table_chained);
  104. static __init int sg_pool_init(void)
  105. {
  106. int i;
  107. for (i = 0; i < SG_MEMPOOL_NR; i++) {
  108. struct sg_pool *sgp = sg_pools + i;
  109. int size = sgp->size * sizeof(struct scatterlist);
  110. sgp->slab = kmem_cache_create(sgp->name, size, 0,
  111. SLAB_HWCACHE_ALIGN, NULL);
  112. if (!sgp->slab) {
  113. printk(KERN_ERR "SG_POOL: can't init sg slab %s\n",
  114. sgp->name);
  115. goto cleanup_sdb;
  116. }
  117. sgp->pool = mempool_create_slab_pool(SG_MEMPOOL_SIZE,
  118. sgp->slab);
  119. if (!sgp->pool) {
  120. printk(KERN_ERR "SG_POOL: can't init sg mempool %s\n",
  121. sgp->name);
  122. goto cleanup_sdb;
  123. }
  124. }
  125. return 0;
  126. cleanup_sdb:
  127. for (i = 0; i < SG_MEMPOOL_NR; i++) {
  128. struct sg_pool *sgp = sg_pools + i;
  129. if (sgp->pool)
  130. mempool_destroy(sgp->pool);
  131. if (sgp->slab)
  132. kmem_cache_destroy(sgp->slab);
  133. }
  134. return -ENOMEM;
  135. }
  136. static __exit void sg_pool_exit(void)
  137. {
  138. int i;
  139. for (i = 0; i < SG_MEMPOOL_NR; i++) {
  140. struct sg_pool *sgp = sg_pools + i;
  141. mempool_destroy(sgp->pool);
  142. kmem_cache_destroy(sgp->slab);
  143. }
  144. }
  145. module_init(sg_pool_init);
  146. module_exit(sg_pool_exit);