pagelist.c 1.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. #include <linux/gfp.h>
  2. #include <linux/pagemap.h>
  3. #include <linux/highmem.h>
  4. #include "pagelist.h"
  5. int ceph_pagelist_release(struct ceph_pagelist *pl)
  6. {
  7. if (pl->mapped_tail)
  8. kunmap(pl->mapped_tail);
  9. while (!list_empty(&pl->head)) {
  10. struct page *page = list_first_entry(&pl->head, struct page,
  11. lru);
  12. list_del(&page->lru);
  13. __free_page(page);
  14. }
  15. return 0;
  16. }
  17. static int ceph_pagelist_addpage(struct ceph_pagelist *pl)
  18. {
  19. struct page *page = __page_cache_alloc(GFP_NOFS);
  20. if (!page)
  21. return -ENOMEM;
  22. pl->room += PAGE_SIZE;
  23. list_add_tail(&page->lru, &pl->head);
  24. if (pl->mapped_tail)
  25. kunmap(pl->mapped_tail);
  26. pl->mapped_tail = kmap(page);
  27. return 0;
  28. }
  29. int ceph_pagelist_append(struct ceph_pagelist *pl, void *buf, size_t len)
  30. {
  31. while (pl->room < len) {
  32. size_t bit = pl->room;
  33. int ret;
  34. memcpy(pl->mapped_tail + (pl->length & ~PAGE_CACHE_MASK),
  35. buf, bit);
  36. pl->length += bit;
  37. pl->room -= bit;
  38. buf += bit;
  39. len -= bit;
  40. ret = ceph_pagelist_addpage(pl);
  41. if (ret)
  42. return ret;
  43. }
  44. memcpy(pl->mapped_tail + (pl->length & ~PAGE_CACHE_MASK), buf, len);
  45. pl->length += len;
  46. pl->room -= len;
  47. return 0;
  48. }