On 2024/10/29 1:53, Alexander Duyck wrote: > On Mon, Oct 28, 2024 at 5:05 AM Yunsheng Lin <linyunsheng@xxxxxxxxxx> wrote: >> >> For some case as tun_build_skb() without the needing of >> using complicated prepare & commit API, add the abort API to >> abort the operation of page_frag_alloc_*() related API for >> error handling knowing that no one else is taking extra >> reference to the just allocated fragment, and add abort_ref >> API to only abort the reference counting of the allocated >> fragment if it is already referenced by someone else. >> ... >> + >> +/** >> + * page_frag_alloc_abort_ref - Abort the reference of allocated fragment. >> + * @nc: page_frag cache to which the page fragment is aborted back >> + * @va: virtual address of page fragment to be aborted >> + * @fragsz: size of the page fragment to be aborted >> + * >> + * It is expected to be called from the same context as the allocation API. >> + * Mostly used for error handling cases to abort the reference of allocated >> + * fragment if the fragment has been referenced for other usages, to aovid the >> + * atomic operation of page_frag_free() API. >> + */ >> +void page_frag_alloc_abort_ref(struct page_frag_cache *nc, void *va, >> + unsigned int fragsz) >> +{ >> + VM_BUG_ON(va + fragsz != >> + encoded_page_decode_virt(nc->encoded_page) + nc->offset); >> + >> + nc->pagecnt_bias++; >> +} >> +EXPORT_SYMBOL(page_frag_alloc_abort_ref); > > It isn't clear to me why you split this over two functions. It seems > like you could just update the offset in this lower function rather > than do it in the upper one since you are passing all the arguments > here anyway. For the usecase in tun_build_skb(), There seems to be XDP_REDIRECT and XDP_TX case that the allocated fragment has been referenced for other usages even when xdp_do_redirect() or tun_xdp_tx() return error, so that caller can call page_frag_alloc_abort_ref() to abort its reference of the allocated fragment, but not abort the whole fragment for later reuse. As the doc mentioned above page_frag_alloc_abort_ref(), it is mainly to avoid the atomic operation of page_frag_free() API when the caller has the allocation context and has the all the arguments page_frag_alloc_abort_ref() needs even though it might be a unlikely case if page_frag_alloc_abort() API is already provided.