Re: [PATCH] ceph: fix refcount leak in write_folio_nounlock()
Viacheslav Dubeyko <[email protected]>
| Newsgroups | org.kernel.vger.ceph-devel,org.kernel.vger.linux-kernel,org.kernel.vger.stable |
|---|---|
| Message-ID | <[email protected]> |
On Thu, 2026-06-11 at 22:34 +0800, WenTao Liang wrote: > write_folio_nounlock() unconditionally increments > fsc->writeback_count before allocating an OSD request. If an > early error causes the function to return without queuing an > active write, the counter is never decremented, leaking a > reference and making the filesystem appear permanently > congested. Three such paths exist: > > - ceph_osdc_new_request() fails: the folio is redirtied, but > writeback_count remains incremented. > > - After the request is allocated, the fscrypt bounce page > allocation fails. The function ends writeback on the folio > and releases the request, but does not drop the > writeback_count reference. > > - The write is interrupted by a signal (e.g. -ERESTARTSYS). > The folio is redirtied and writeback is ended, yet again the > counter is left elevated. > > Fix the leaks by adding an atomic_long_dec() in each of these > early return paths, balancing the initial inc. > > Cc: [email protected] > Fixes: 6390987f2f4c ("ceph: fold ceph_sync_writepages into > writepage_nounlock") > Signed-off-by: WenTao Liang <[email protected]> > --- > fs/ceph/addr.c | 3 +++ > 1 file changed, 3 insertions(+) > > diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c > index 0a86f672cc09..dac2b0ae7d37 100644 > --- a/fs/ceph/addr.c > +++ b/fs/ceph/addr.c > @@ -790,6 +790,7 @@ static int write_folio_nounlock(struct folio > *folio, > ceph_wbc.truncate_size, true); > if (IS_ERR(req)) { > folio_redirty_for_writepage(wbc, folio); > + atomic_long_dec(&fsc->writeback_count); > return PTR_ERR(req); > } > > @@ -809,6 +810,7 @@ static int write_folio_nounlock(struct folio > *folio, > folio_redirty_for_writepage(wbc, folio); > folio_end_writeback(folio); > ceph_osdc_put_request(req); > + atomic_long_dec(&fsc->writeback_count); > return PTR_ERR(bounce_page); > } > } > @@ -847,6 +849,7 @@ static int write_folio_nounlock(struct folio > *folio, > ceph_vinop(inode), folio); > folio_redirty_for_writepage(wbc, folio); > folio_end_writeback(folio); > + atomic_long_dec(&fsc->writeback_count); > return err; > } > if (err == -EBLOCKLISTED) Maybe, I am missing something. But I have the feeling that we already received likewise patch and we've discussed this solution. As I remember correctly, I recommended to use this pattern: if (atomic_long_dec_return(&fsc->writeback_count) < CONGESTION_OFF_THRESH(fsc->mount_options->congestion_kb)) fsc->write_congested = false; Thanks, Slava.