decompressor_multi.c 4.6 KB

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