Skip to content

Commit 6444f47

Browse files
htejunaxboe
authored andcommitted
writeback, cgroup: inode_switch_wbs() shouldn't give up on wb_switch_rwsem trylock fail
As inode wb switching may make sync(2) miss some inodes, they're synchronized using wb_switch_rwsem so that no wb switching happens while sync(2) is in progress. In addition to synchronizing the actual switching, the rwsem is also used to prevent queueing new switch attempts while sync(2) is in progress. This is to avoid queueing too many instances while the rwsem is held by sync(2). Unfortunately, this is too agressive and can block wb switching for a long time if sync(2) is frequent. The goal is avoiding expolding the number of scheduled switches, not avoiding scheduling anything. Let's use wb_switch_rwsem only for synchronizing the actual switching and sync(2) and use isw_nr_in_flight instead for limiting the maximum number of scheduled switches. The limit is set to 1024 which should be more than enough while still avoiding extreme situations. Reviewed-by: Jan Kara <[email protected]> Signed-off-by: Tejun Heo <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent 55a694d commit 6444f47

File tree

1 file changed

+5
-12
lines changed

1 file changed

+5
-12
lines changed

fs/fs-writeback.c

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ static void wb_wait_for_completion(struct backing_dev_info *bdi,
255255
/* if foreign slots >= 8, switch */
256256
#define WB_FRN_HIST_MAX_SLOTS (WB_FRN_HIST_THR_SLOTS / 2 + 1)
257257
/* one round can affect upto 5 slots */
258+
#define WB_FRN_MAX_IN_FLIGHT 1024 /* don't queue too many concurrently */
258259

259260
static atomic_t isw_nr_in_flight = ATOMIC_INIT(0);
260261
static struct workqueue_struct *isw_wq;
@@ -507,18 +508,13 @@ static void inode_switch_wbs(struct inode *inode, int new_wb_id)
507508
if (inode->i_state & I_WB_SWITCH)
508509
return;
509510

510-
/*
511-
* Avoid starting new switches while sync_inodes_sb() is in
512-
* progress. Otherwise, if the down_write protected issue path
513-
* blocks heavily, we might end up starting a large number of
514-
* switches which will block on the rwsem.
515-
*/
516-
if (!down_read_trylock(&bdi->wb_switch_rwsem))
511+
/* avoid queueing a new switch if too many are already in flight */
512+
if (atomic_read(&isw_nr_in_flight) > WB_FRN_MAX_IN_FLIGHT)
517513
return;
518514

519515
isw = kzalloc(sizeof(*isw), GFP_ATOMIC);
520516
if (!isw)
521-
goto out_unlock;
517+
return;
522518

523519
/* find and pin the new wb */
524520
rcu_read_lock();
@@ -552,15 +548,12 @@ static void inode_switch_wbs(struct inode *inode, int new_wb_id)
552548
call_rcu(&isw->rcu_head, inode_switch_wbs_rcu_fn);
553549

554550
atomic_inc(&isw_nr_in_flight);
555-
556-
goto out_unlock;
551+
return;
557552

558553
out_free:
559554
if (isw->new_wb)
560555
wb_put(isw->new_wb);
561556
kfree(isw);
562-
out_unlock:
563-
up_read(&bdi->wb_switch_rwsem);
564557
}
565558

566559
/**

0 commit comments

Comments
 (0)