Skip to content

Commit 7cf2b0f

Browse files
Dave ChinnerDarrick J. Wong
authored andcommitted
xfs: bound maximum wait time for inodegc work
Currently inodegc work can sit queued on the per-cpu queue until the workqueue is either flushed of the queue reaches a depth that triggers work queuing (and later throttling). This means that we could queue work that waits for a long time for some other event to trigger flushing. Hence instead of just queueing work at a specific depth, use a delayed work that queues the work at a bound time. We can still schedule the work immediately at a given depth, but we no long need to worry about leaving a number of items on the list that won't get processed until external events prevail. Signed-off-by: Dave Chinner <[email protected]> Reviewed-by: Darrick J. Wong <[email protected]> Signed-off-by: Darrick J. Wong <[email protected]>
1 parent e89ab76 commit 7cf2b0f

File tree

3 files changed

+24
-16
lines changed

3 files changed

+24
-16
lines changed

fs/xfs/xfs_icache.c

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ xfs_inodegc_queue_all(
440440
for_each_online_cpu(cpu) {
441441
gc = per_cpu_ptr(mp->m_inodegc, cpu);
442442
if (!llist_empty(&gc->list))
443-
queue_work_on(cpu, mp->m_inodegc_wq, &gc->work);
443+
mod_delayed_work_on(cpu, mp->m_inodegc_wq, &gc->work, 0);
444444
}
445445
}
446446

@@ -1841,8 +1841,8 @@ void
18411841
xfs_inodegc_worker(
18421842
struct work_struct *work)
18431843
{
1844-
struct xfs_inodegc *gc = container_of(work, struct xfs_inodegc,
1845-
work);
1844+
struct xfs_inodegc *gc = container_of(to_delayed_work(work),
1845+
struct xfs_inodegc, work);
18461846
struct llist_node *node = llist_del_all(&gc->list);
18471847
struct xfs_inode *ip, *n;
18481848

@@ -2014,6 +2014,7 @@ xfs_inodegc_queue(
20142014
struct xfs_inodegc *gc;
20152015
int items;
20162016
unsigned int shrinker_hits;
2017+
unsigned long queue_delay = 1;
20172018

20182019
trace_xfs_inode_set_need_inactive(ip);
20192020
spin_lock(&ip->i_flags_lock);
@@ -2025,19 +2026,26 @@ xfs_inodegc_queue(
20252026
items = READ_ONCE(gc->items);
20262027
WRITE_ONCE(gc->items, items + 1);
20272028
shrinker_hits = READ_ONCE(gc->shrinker_hits);
2028-
put_cpu_ptr(gc);
20292029

2030-
if (!xfs_is_inodegc_enabled(mp))
2030+
/*
2031+
* We queue the work while holding the current CPU so that the work
2032+
* is scheduled to run on this CPU.
2033+
*/
2034+
if (!xfs_is_inodegc_enabled(mp)) {
2035+
put_cpu_ptr(gc);
20312036
return;
2032-
2033-
if (xfs_inodegc_want_queue_work(ip, items)) {
2034-
trace_xfs_inodegc_queue(mp, __return_address);
2035-
queue_work(mp->m_inodegc_wq, &gc->work);
20362037
}
20372038

2039+
if (xfs_inodegc_want_queue_work(ip, items))
2040+
queue_delay = 0;
2041+
2042+
trace_xfs_inodegc_queue(mp, __return_address);
2043+
mod_delayed_work(mp->m_inodegc_wq, &gc->work, queue_delay);
2044+
put_cpu_ptr(gc);
2045+
20382046
if (xfs_inodegc_want_flush_work(ip, items, shrinker_hits)) {
20392047
trace_xfs_inodegc_throttle(mp, __return_address);
2040-
flush_work(&gc->work);
2048+
flush_delayed_work(&gc->work);
20412049
}
20422050
}
20432051

@@ -2054,7 +2062,7 @@ xfs_inodegc_cpu_dead(
20542062
unsigned int count = 0;
20552063

20562064
dead_gc = per_cpu_ptr(mp->m_inodegc, dead_cpu);
2057-
cancel_work_sync(&dead_gc->work);
2065+
cancel_delayed_work_sync(&dead_gc->work);
20582066

20592067
if (llist_empty(&dead_gc->list))
20602068
return;
@@ -2073,12 +2081,12 @@ xfs_inodegc_cpu_dead(
20732081
llist_add_batch(first, last, &gc->list);
20742082
count += READ_ONCE(gc->items);
20752083
WRITE_ONCE(gc->items, count);
2076-
put_cpu_ptr(gc);
20772084

20782085
if (xfs_is_inodegc_enabled(mp)) {
20792086
trace_xfs_inodegc_queue(mp, __return_address);
2080-
queue_work(mp->m_inodegc_wq, &gc->work);
2087+
mod_delayed_work(mp->m_inodegc_wq, &gc->work, 0);
20812088
}
2089+
put_cpu_ptr(gc);
20822090
}
20832091

20842092
/*
@@ -2173,7 +2181,7 @@ xfs_inodegc_shrinker_scan(
21732181
unsigned int h = READ_ONCE(gc->shrinker_hits);
21742182

21752183
WRITE_ONCE(gc->shrinker_hits, h + 1);
2176-
queue_work_on(cpu, mp->m_inodegc_wq, &gc->work);
2184+
mod_delayed_work_on(cpu, mp->m_inodegc_wq, &gc->work, 0);
21772185
no_items = false;
21782186
}
21792187
}

fs/xfs/xfs_mount.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ struct xfs_error_cfg {
6161
*/
6262
struct xfs_inodegc {
6363
struct llist_head list;
64-
struct work_struct work;
64+
struct delayed_work work;
6565

6666
/* approximate count of inodes in the list */
6767
unsigned int items;

fs/xfs/xfs_super.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1074,7 +1074,7 @@ xfs_inodegc_init_percpu(
10741074
gc = per_cpu_ptr(mp->m_inodegc, cpu);
10751075
init_llist_head(&gc->list);
10761076
gc->items = 0;
1077-
INIT_WORK(&gc->work, xfs_inodegc_worker);
1077+
INIT_DELAYED_WORK(&gc->work, xfs_inodegc_worker);
10781078
}
10791079
return 0;
10801080
}

0 commit comments

Comments
 (0)