Not a huge fan of introducing a ton of new API calls and then having
to have them all applied at once in the follow-on patches. Ideally the
functions and the header documentation for them would be introduced in
the same patch as well as examples on how it would be used.
I really think we should break these up as some are used in one case,
and others in another and it is a pain to have a pile of abstractions
that are all using these functions in different ways.
+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;
+}
+
We should probably have the same checks here you had on the earlier
commit. We should not be allowing blind changes. If we are using the
commit or abort interfaces we should be verifying a page frag with
them to verify that the request to modify this is legitimate.
void page_frag_free(void *addr);
#endif
diff --git a/mm/page_frag_cache.c b/mm/page_frag_cache.c
index f55d34cf7d43..5ea4b663ab8e 100644
--- a/mm/page_frag_cache.c
+++ b/mm/page_frag_cache.c
@@ -112,6 +112,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_SIZE << encoded_page_decode_order(encoded_page);
+ offset = __ALIGN_KERNEL_MASK(nc->offset, ~align_mask);
+ if (unlikely(!encoded_page || offset + fragsz > size))
+ return NULL;
+
+ pfrag->page = encoded_page_decode_page(encoded_page);
+ pfrag->size = size - offset;
+ pfrag->offset = offset;
+
+ return encoded_page_decode_virt(encoded_page) + offset;
+}
+EXPORT_SYMBOL(__page_frag_alloc_refill_probe_align);
+
If I am not mistaken this would be the equivalent of allocating a size
0 fragment right? The only difference is that you are copying out the
"remaining" size, but we could get that from the offset if we knew the
size couldn't we? Would it maybe make sense to look at limiting this
to PAGE_SIZE instead of passing the size of the actual fragment?
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)
--
2.33.0