@@ -48,6 +53,10 @@ void *__page_frag_cache_prepare(struct page_frag_cache *nc, unsigned int fragsz,
unsigned int __page_frag_cache_commit_noref(struct page_frag_cache *nc,
struct page_frag *pfrag,
unsigned int used_sz);
+void *__page_frag_alloc_refill_probe_align(struct page_frag_cache *nc,
+ unsigned int fragsz,
+ struct page_frag *pfrag,
+ unsigned int align_mask);
static inline unsigned int __page_frag_cache_commit(struct page_frag_cache *nc,
struct page_frag *pfrag,
@@ -90,6 +99,132 @@ 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, 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(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, 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_noref(nc, pfrag, 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@@ -117,6 +117,27 @@ unsigned int __page_frag_cache_commit_noref(struct page_frag_cache *nc,
}
EXPORT_SYMBOL(__page_frag_cache_commit_noref);
+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;
+}
+EXPORT_SYMBOL(__page_frag_alloc_refill_probe_align);
+
void *__page_frag_cache_prepare(struct page_frag_cache *nc, unsigned int fragsz,
struct page_frag *pfrag, gfp_t gfp_mask,
unsigned int align_mask)