page_actor.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. /*
  2. * Copyright (c) 2013
  3. * Phillip Lougher <phillip@squashfs.org.uk>
  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/kernel.h>
  9. #include <linux/slab.h>
  10. #include <linux/pagemap.h>
  11. #include "page_actor.h"
  12. /*
  13. * This file contains implementations of page_actor for decompressing into
  14. * an intermediate buffer, and for decompressing directly into the
  15. * page cache.
  16. *
  17. * Calling code should avoid sleeping between calls to squashfs_first_page()
  18. * and squashfs_finish_page().
  19. */
  20. /* Implementation of page_actor for decompressing into intermediate buffer */
  21. static void *cache_first_page(struct squashfs_page_actor *actor)
  22. {
  23. actor->next_page = 1;
  24. return actor->buffer[0];
  25. }
  26. static void *cache_next_page(struct squashfs_page_actor *actor)
  27. {
  28. if (actor->next_page == actor->pages)
  29. return NULL;
  30. return actor->buffer[actor->next_page++];
  31. }
  32. static void cache_finish_page(struct squashfs_page_actor *actor)
  33. {
  34. /* empty */
  35. }
  36. struct squashfs_page_actor *squashfs_page_actor_init(void **buffer,
  37. int pages, int length)
  38. {
  39. struct squashfs_page_actor *actor = kmalloc(sizeof(*actor), GFP_KERNEL);
  40. if (actor == NULL)
  41. return NULL;
  42. actor->length = length ? : pages * PAGE_SIZE;
  43. actor->buffer = buffer;
  44. actor->pages = pages;
  45. actor->next_page = 0;
  46. actor->squashfs_first_page = cache_first_page;
  47. actor->squashfs_next_page = cache_next_page;
  48. actor->squashfs_finish_page = cache_finish_page;
  49. return actor;
  50. }
  51. /* Implementation of page_actor for decompressing directly into page cache. */
  52. static void *direct_first_page(struct squashfs_page_actor *actor)
  53. {
  54. actor->next_page = 1;
  55. return actor->pageaddr = kmap_atomic(actor->page[0]);
  56. }
  57. static void *direct_next_page(struct squashfs_page_actor *actor)
  58. {
  59. if (actor->pageaddr)
  60. kunmap_atomic(actor->pageaddr);
  61. return actor->pageaddr = actor->next_page == actor->pages ? NULL :
  62. kmap_atomic(actor->page[actor->next_page++]);
  63. }
  64. static void direct_finish_page(struct squashfs_page_actor *actor)
  65. {
  66. if (actor->pageaddr)
  67. kunmap_atomic(actor->pageaddr);
  68. }
  69. struct squashfs_page_actor *squashfs_page_actor_init_special(struct page **page,
  70. int pages, int length)
  71. {
  72. struct squashfs_page_actor *actor = kmalloc(sizeof(*actor), GFP_KERNEL);
  73. if (actor == NULL)
  74. return NULL;
  75. actor->length = length ? : pages * PAGE_SIZE;
  76. actor->page = page;
  77. actor->pages = pages;
  78. actor->next_page = 0;
  79. actor->pageaddr = NULL;
  80. actor->squashfs_first_page = direct_first_page;
  81. actor->squashfs_next_page = direct_next_page;
  82. actor->squashfs_finish_page = direct_finish_page;
  83. return actor;
  84. }