Re: [PATCH 1/2] ceph: use GFP_NOFS for cap flush allocation in writeback path

From: Viacheslav Dubeyko

Date: Thu Jul 23 2026 - 13:01:58 EST


On Thu, 2026-07-23 at 13:47 +0800, Xiubo Li via B4 Relay wrote:
> From: Xiubo Li <xiubo.li@xxxxxxxxx>
>
> ceph_alloc_cap_flush() is called from ceph_writepages_start() inside
> the writeback layer, where other allocations in the same path
> (ceph_osdc_alloc_request, ceph_osdc_alloc_messages) already use
> GFP_NOFS.  A GFP_KERNEL allocation here can trigger direct reclaim
> that recursively enters the filesystem writeback path:
>
>   ceph_writepages_start()                       // inode A writeback
>     ceph_alloc_cap_flush()
>       kmem_cache_alloc(..., GFP_KERNEL)
>         [direct reclaim]
>           try_to_free_pages()
>             shrink_slab()
>               super_cache_scan()
>                 prune_icache_sb()
>                   inode_lru_isolate()
>                     iput() -> evict(inode_B)
>                       [inode_B has dirty pages]
>                       filemap_flush()
>                         ceph_writepages_start()  // re-enters
> writeback
>                           ceph_alloc_cap_flush()
>                             -> RECURSION / STACK OVERFLOW
>
> All 11 callers of ceph_alloc_cap_flush() are in write or writeback
> contexts: writepages (x2), write_iter, fallocate, copy_file_range,
> setxattr, setattr, and page_mkwrite.
>
> Signed-off-by: Xiubo Li <xiubo.li@xxxxxxxxx>
> ---
>  fs/ceph/caps.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
> index f8d898ad091e..cbaebeac06f7 100644
> --- a/fs/ceph/caps.c
> +++ b/fs/ceph/caps.c
> @@ -1875,7 +1875,7 @@ struct ceph_cap_flush
> *ceph_alloc_cap_flush(void)
>  {
>   struct ceph_cap_flush *cf;
>  
> - cf = kmem_cache_alloc(ceph_cap_flush_cachep, GFP_KERNEL);
> + cf = kmem_cache_alloc(ceph_cap_flush_cachep, GFP_NOFS);
>   if (!cf)
>   return NULL;
>  

Looks good.

Reviewed-by: Viacheslav Dubeyko <slava@xxxxxxxxxxx>

Thanks,
Slava.