Re: [PATCH v2 1/4] writeback: Avoid contention on wb->list_lock when switching inodes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri 12-09-25 06:15:49, Tejun Heo wrote:
> Hello,
> 
> On Fri, Sep 12, 2025 at 12:38:35PM +0200, Jan Kara wrote:
> > There can be multiple inode switch works that are trying to switch
> > inodes to / from the same wb. This can happen in particular if some
> > cgroup exits which owns many (thousands) inodes and we need to switch
> > them all. In this case several inode_switch_wbs_work_fn() instances will
> > be just spinning on the same wb->list_lock while only one of them makes
> > forward progress. This wastes CPU cycles and quickly leads to softlockup
> > reports and unusable system.
> > 
> > Instead of running several inode_switch_wbs_work_fn() instances in
> > parallel switching to the same wb and contending on wb->list_lock, run
> > just one work item per wb and manage a queue of isw items switching to
> > this wb.
> > 
> > Signed-off-by: Jan Kara <jack@xxxxxxx>
> 
> Generally looks great to me, but
> 
> > +void inode_switch_wbs_work_fn(struct work_struct *work)
> > +{
> > +	struct bdi_writeback *new_wb = container_of(work, struct bdi_writeback,
> > +						    switch_work);
> > +	struct inode_switch_wbs_context *isw, *next_isw;
> > +	struct llist_node *list;
> > +
> > +	/*
> > +	 * Grab out reference to wb so that it cannot get freed under us
> > +	 * after we process all the isw items.
> > +	 */
> > +	wb_get(new_wb);
> 
> Shouldn't this ref put at the end of the function?

It is put:

> > +	while (1) {
> > +		list = llist_del_all(&new_wb->switch_wbs_ctxs);
> > +		/* Nothing to do? */
> > +		if (!list) {
> > +			wb_put(new_wb);
			^^^^ here
There's no other way how to exit the function... But I can put 'break' here
and do wb_put() at the end of the function. That will likely be less
subtle.

								Honza


> > +			return;
> > +		}
> > +		/*
> > +		 * In addition to synchronizing among switchers, I_WB_SWITCH
> > +		 * tells the RCU protected stat update paths to grab the i_page
> > +		 * lock so that stat transfer can synchronize against them.
> > +		 * Let's continue after I_WB_SWITCH is guaranteed to be
> > +		 * visible.
> > +		 */
> > +		synchronize_rcu();
> > +
> > +		llist_for_each_entry_safe(isw, next_isw, list, list)
> > +			process_inode_switch_wbs_work(new_wb, isw);
> > +	}
> > +}
> 
> Thanks.
> 
> -- 
> tejun
-- 
Jan Kara <jack@xxxxxxxx>
SUSE Labs, CR




[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [NTFS 3]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [NTFS 3]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux