#include #include #include #include "pagelist.h" static void ceph_pagelist_unmap_tail(struct ceph_pagelist *pl) { struct page *page = list_entry(pl->head.prev, struct page, lru); kunmap(page); } int ceph_pagelist_release(struct ceph_pagelist *pl) { if (pl->mapped_tail) ceph_pagelist_unmap_tail(pl); while (!list_empty(&pl->head)) { struct page *page = list_first_entry(&pl->head, struct page, lru); list_del(&page->lru); __free_page(page); } return 0; } static int ceph_pagelist_addpage(struct ceph_pagelist *pl) { struct page *page = __page_cache_alloc(GFP_NOFS); if (!page) return -ENOMEM; pl->room += PAGE_SIZE; list_add_tail(&page->lru, &pl->head); if (pl->mapped_tail) ceph_pagelist_unmap_tail(pl); pl->mapped_tail = kmap(page); return 0; } int ceph_pagelist_append(struct ceph_pagelist *pl, const void *buf, size_t len) { while (pl->room < len) { size_t bit = pl->room; int ret; memcpy(pl->mapped_tail + (pl->length & ~PAGE_CACHE_MASK), buf, bit); pl->length += bit; pl->room -= bit; buf += bit; len -= bit; ret = ceph_pagelist_addpage(pl); if (ret) return ret; } memcpy(pl->mapped_tail + (pl->length & ~PAGE_CACHE_MASK), buf, len); pl->length += len; pl->room -= len; return 0; }