@@ -139,6 +144,139 @@ static inline void *page_frag_alloc(struct page_frag_cache *nc,
return __page_frag_alloc_align(nc, fragsz, gfp_mask, ~0u);
}
+static inline bool __page_frag_refill_align(struct page_frag_cache *nc, unsigned int fragsz,
+ struct page_frag *pfrag, gfp_t gfp_mask,
+ unsigned int align_mask)
+{
+ if (unlikely(!__page_frag_cache_prepare(nc, fragsz, pfrag, gfp_mask, align_mask)))
+ return false;
+
+ __page_frag_cache_commit(nc, pfrag, true, fragsz);
+ return true;
+}
+
+static inline bool page_frag_refill_align(struct page_frag_cache *nc, unsigned int fragsz,
+ struct page_frag *pfrag, gfp_t gfp_mask,
+ unsigned int align)
+{
+ WARN_ON_ONCE(!is_power_of_2(align));
+ return __page_frag_refill_align(nc, fragsz, pfrag, gfp_mask, -align);
+}
+
+static inline bool page_frag_refill(struct page_frag_cache *nc, unsigned int fragsz,
+ struct page_frag *pfrag, gfp_t gfp_mask)
+{
+ return __page_frag_refill_align(nc, fragsz, pfrag, gfp_mask, ~0u);
+}
+
+static inline bool __page_frag_refill_prepare_align(struct page_frag_cache *nc,
+ unsigned int fragsz,
+ struct page_frag *pfrag,
+ gfp_t gfp_mask,
+ unsigned int align_mask)
+{
+ return !!__page_frag_cache_prepare(nc, fragsz, pfrag, gfp_mask, align_mask);
+}
+
+static inline bool page_frag_refill_prepare_align(struct page_frag_cache *nc,
+ unsigned int fragsz,
+ struct page_frag *pfrag,
+ gfp_t gfp_mask,
+ unsigned int align)
+{
+ WARN_ON_ONCE(!is_power_of_2(align));
+ return __page_frag_refill_prepare_align(nc, fragsz, pfrag, gfp_mask, -align);
+}
+
+static inline bool page_frag_refill_prepare(struct page_frag_cache *nc,
+ unsigned int fragsz,
+ struct page_frag *pfrag,
+ gfp_t gfp_mask)
+{
+ return __page_frag_refill_prepare_align(nc, fragsz, pfrag, gfp_mask, ~0u);
+}
+
+static inline void *__page_frag_alloc_refill_prepare_align(struct page_frag_cache *nc,
+ unsigned int fragsz,
+ struct page_frag *pfrag,
+ gfp_t gfp_mask,
+ unsigned int align_mask)
+{
+ return __page_frag_cache_prepare(nc, fragsz, pfrag, gfp_mask, align_mask);
+}
+
+static inline void *page_frag_alloc_refill_prepare_align(struct page_frag_cache *nc,
+ unsigned int fragsz,
+ struct page_frag *pfrag,
+ gfp_t gfp_mask,
+ unsigned int align)
+{
+ WARN_ON_ONCE(!is_power_of_2(align));
+ return __page_frag_alloc_refill_prepare_align(nc, fragsz, pfrag, gfp_mask, -align);
+}
+
+static inline void *page_frag_alloc_refill_prepare(struct page_frag_cache *nc,
+ unsigned int fragsz,
+ struct page_frag *pfrag,
+ gfp_t gfp_mask)
+{
+ return __page_frag_alloc_refill_prepare_align(nc, fragsz, pfrag, gfp_mask, ~0u);
+}
+
+static inline void *__page_frag_alloc_refill_probe_align(struct page_frag_cache *nc,
+ unsigned int fragsz,
+ struct page_frag *pfrag,
+ unsigned int align_mask)
+{
+ unsigned long encoded_page = nc->encoded_page;
+ unsigned int size, offset;
+
+ size = page_frag_cache_page_size(encoded_page);
+ offset = __ALIGN_KERNEL_MASK(nc->offset, ~align_mask);
+ if (unlikely(!encoded_page || offset + fragsz > size))
+ return NULL;
+
+ pfrag->page = page_frag_encoded_page_ptr(encoded_page);
+ pfrag->size = size - offset;
+ pfrag->offset = offset;
+
+ return page_frag_encoded_page_address(encoded_page) + offset;
+}
+
+static inline void *page_frag_alloc_refill_probe(struct page_frag_cache *nc,
+ unsigned int fragsz,
+ struct page_frag *pfrag)
+{
+ return __page_frag_alloc_refill_probe_align(nc, fragsz, pfrag, ~0u);
+}
+
+static inline bool page_frag_refill_probe(struct page_frag_cache *nc,
+ unsigned int fragsz,
+ struct page_frag *pfrag)
+{
+ return !!page_frag_alloc_refill_probe(nc, fragsz, pfrag);
+}
+
+static inline void page_frag_commit(struct page_frag_cache *nc, struct page_frag *pfrag,
+ unsigned int used_sz)
+{
+ __page_frag_cache_commit(nc, pfrag, true, used_sz);
+}
+
+static inline void page_frag_commit_noref(struct page_frag_cache *nc,
+ struct page_frag *pfrag, unsigned int used_sz)
+{
+ __page_frag_cache_commit(nc, pfrag, false, used_sz);
+}
+
+static inline void page_frag_alloc_abort(struct page_frag_cache *nc, unsigned int fragsz)
+{
+ VM_BUG_ON(fragsz > nc->offset);
+
+ nc->pagecnt_bias++;
+ nc->offset -= fragsz;
+}
+
void page_frag_free(void *addr);
#endif