decompressor_multi.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2013
  4. * Minchan Kim <minchan@kernel.org>
  5. */
  6. #include <linux/types.h>
  7. #include <linux/mutex.h>
  8. #include <linux/slab.h>
  9. #include <linux/bio.h>
  10. #include <linux/sched.h>
  11. #include <linux/wait.h>
  12. #include <linux/cpumask.h>
  13. #include "squashfs_fs.h"
  14. #include "squashfs_fs_sb.h"
  15. #include "decompressor.h"
  16. #include "squashfs.h"
  17. /*
  18. * This file implements multi-threaded decompression in the
  19. * decompressor framework
  20. */
  21. /*
  22. * The reason that multiply two is that a CPU can request new I/O
  23. * while it is waiting previous request.
  24. */
  25. #define MAX_DECOMPRESSOR (num_online_cpus() * 2)
  26. int squashfs_max_decompressors(void)
  27. {
  28. return MAX_DECOMPRESSOR;
  29. }
  30. struct squashfs_stream {
  31. void *comp_opts;
  32. struct list_head strm_list;
  33. struct mutex mutex;
  34. int avail_decomp;
  35. wait_queue_head_t wait;
  36. };
  37. struct decomp_stream {
  38. void *stream;
  39. struct list_head list;
  40. };
  41. static void put_decomp_stream(struct decomp_stream *decomp_strm,
  42. struct squashfs_stream *stream)
  43. {
  44. mutex_lock(&stream->mutex);
  45. list_add(&decomp_strm->list, &stream->strm_list);
  46. mutex_unlock(&stream->mutex);
  47. wake_up(&stream->wait);
  48. }
  49. void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
  50. void *comp_opts)
  51. {
  52. struct squashfs_stream *stream;
  53. struct decomp_stream *decomp_strm = NULL;
  54. int err = -ENOMEM;
  55. stream = kzalloc(sizeof(*stream), GFP_KERNEL);
  56. if (!stream)
  57. goto out;
  58. stream->comp_opts = comp_opts;
  59. mutex_init(&stream->mutex);
  60. INIT_LIST_HEAD(&stream->strm_list);
  61. init_waitqueue_head(&stream->wait);
  62. /*
  63. * We should have a decompressor at least as default
  64. * so if we fail to allocate new decompressor dynamically,
  65. * we could always fall back to default decompressor and
  66. * file system works.
  67. */
  68. decomp_strm = kmalloc(sizeof(*decomp_strm), GFP_KERNEL);
  69. if (!decomp_strm)
  70. goto out;
  71. decomp_strm->stream = msblk->decompressor->init(msblk,
  72. stream->comp_opts);
  73. if (IS_ERR(decomp_strm->stream)) {
  74. err = PTR_ERR(decomp_strm->stream);
  75. goto out;
  76. }
  77. list_add(&decomp_strm->list, &stream->strm_list);
  78. stream->avail_decomp = 1;
  79. return stream;
  80. out:
  81. kfree(decomp_strm);
  82. kfree(stream);
  83. return ERR_PTR(err);
  84. }
  85. void squashfs_decompressor_destroy(struct squashfs_sb_info *msblk)
  86. {
  87. struct squashfs_stream *stream = msblk->stream;
  88. if (stream) {
  89. struct decomp_stream *decomp_strm;
  90. while (!list_empty(&stream->strm_list)) {
  91. decomp_strm = list_entry(stream->strm_list.prev,
  92. struct decomp_stream, list);
  93. list_del(&decomp_strm->list);
  94. msblk->decompressor->free(decomp_strm->stream);
  95. kfree(decomp_strm);
  96. stream->avail_decomp--;
  97. }
  98. WARN_ON(stream->avail_decomp);
  99. kfree(stream->comp_opts);
  100. kfree(stream);
  101. }
  102. }
  103. static struct decomp_stream *get_decomp_stream(struct squashfs_sb_info *msblk,
  104. struct squashfs_stream *stream)
  105. {
  106. struct decomp_stream *decomp_strm;
  107. while (1) {
  108. mutex_lock(&stream->mutex);
  109. /* There is available decomp_stream */
  110. if (!list_empty(&stream->strm_list)) {
  111. decomp_strm = list_entry(stream->strm_list.prev,
  112. struct decomp_stream, list);
  113. list_del(&decomp_strm->list);
  114. mutex_unlock(&stream->mutex);
  115. break;
  116. }
  117. /*
  118. * If there is no available decomp and already full,
  119. * let's wait for releasing decomp from other users.
  120. */
  121. if (stream->avail_decomp >= MAX_DECOMPRESSOR)
  122. goto wait;
  123. /* Let's allocate new decomp */
  124. decomp_strm = kmalloc(sizeof(*decomp_strm), GFP_KERNEL);
  125. if (!decomp_strm)
  126. goto wait;
  127. decomp_strm->stream = msblk->decompressor->init(msblk,
  128. stream->comp_opts);
  129. if (IS_ERR(decomp_strm->stream)) {
  130. kfree(decomp_strm);
  131. goto wait;
  132. }
  133. stream->avail_decomp++;
  134. WARN_ON(stream->avail_decomp > MAX_DECOMPRESSOR);
  135. mutex_unlock(&stream->mutex);
  136. break;
  137. wait:
  138. /*
  139. * If system memory is tough, let's for other's
  140. * releasing instead of hurting VM because it could
  141. * make page cache thrashing.
  142. */
  143. mutex_unlock(&stream->mutex);
  144. wait_event(stream->wait,
  145. !list_empty(&stream->strm_list));
  146. }
  147. return decomp_strm;
  148. }
  149. int squashfs_decompress(struct squashfs_sb_info *msblk, struct bio *bio,
  150. int offset, int length,
  151. struct squashfs_page_actor *output)
  152. {
  153. int res;
  154. struct squashfs_stream *stream = msblk->stream;
  155. struct decomp_stream *decomp_stream = get_decomp_stream(msblk, stream);
  156. res = msblk->decompressor->decompress(msblk, decomp_stream->stream,
  157. bio, offset, length, output);
  158. put_decomp_stream(decomp_stream, stream);
  159. if (res < 0)
  160. ERROR("%s decompression failed, data probably corrupt\n",
  161. msblk->decompressor->name);
  162. return res;
  163. }