Skip to content

Commit bed50b9

Browse files
Hao Xushiloong
authored andcommitted
ck: jbd2: add proc entry to control whether doing buffer copy-out
fix #32728070 When jbd2 tries to get write access to one buffer, and if this buffer is under writeback with BH_Shadow flag, jbd2 will wait until this buffer has been written to disk, but sometimes the time taken to wait may be much long, especially disk capacity is almost full. Here add a proc entry "force-copy", if its value is not zero, jbd2 will always do meta buffer copy-cout, then we can eliminate the unnecessary waiting time here, and reduce long tail latency for buffered-write. I construct such test case below: $cat offline.fio ; fio-rand-RW.job for fiotest [global] name=fio-rand-RW filename=fio-rand-RW rw=randrw rwmixread=60 rwmixwrite=40 bs=4K direct=0 numjobs=4 time_based=1 runtime=900 [file1] size=60G ioengine=sync iodepth=16 $cat online.fio ; fio-seq-write.job for fiotest [global] name=fio-seq-write filename=fio-seq-write rw=write bs=256K direct=0 numjobs=1 time_based=1 runtime=60 [file1] rate=50m size=10G ioengine=sync iodepth=16 With this patch: $cat /proc/fs/jbd2/sda5-8/force_copy 0 online fio almost always get such long tail latency: Jobs: 1 (f=1), 0B/s-0B/s: [W(1)][100.0%][w=50.0MiB/s][w=200 IOPS][eta 00m:00s] file1: (groupid=0, jobs=1): err= 0: pid=17855: Thu Nov 15 09:45:57 2018 write: IOPS=200, BW=50.0MiB/s (52.4MB/s)(3000MiB/60001msec) clat (usec): min=135, max=4086.6k, avg=867.21, stdev=50338.22 lat (usec): min=139, max=4086.6k, avg=871.16, stdev=50338.22 clat percentiles (usec): | 1.00th=[ 141], 5.00th=[ 143], 10.00th=[ 145], | 20.00th=[ 147], 30.00th=[ 147], 40.00th=[ 149], | 50.00th=[ 149], 60.00th=[ 151], 70.00th=[ 153], | 80.00th=[ 155], 90.00th=[ 159], 95.00th=[ 163], | 99.00th=[ 255], 99.50th=[ 273], 99.90th=[ 429], | 99.95th=[ 441], 99.99th=[3640656] $cat /proc/fs/jbd2/sda5-8/force_copy 1 online fio latency is much better. Jobs: 1 (f=1), 0B/s-0B/s: [W(1)][100.0%][w=50.0MiB/s][w=200 IOPS][eta 00m:00s] file1: (groupid=0, jobs=1): err= 0: pid=8084: Thu Nov 15 09:31:15 2018 write: IOPS=200, BW=50.0MiB/s (52.4MB/s)(3000MiB/60001msec) clat (usec): min=137, max=545, avg=151.35, stdev=16.22 lat (usec): min=140, max=548, avg=155.31, stdev=16.65 clat percentiles (usec): | 1.00th=[ 143], 5.00th=[ 145], 10.00th=[ 145], 20.00th=[ 147], | 30.00th=[ 147], 40.00th=[ 147], 50.00th=[ 149], 60.00th=[ 149], | 70.00th=[ 151], 80.00th=[ 155], 90.00th=[ 157], 95.00th=[ 161], | 99.00th=[ 239], 99.50th=[ 269], 99.90th=[ 420], 99.95th=[ 429], | 99.99th=[ 537] As to the cost: because we'll always need to copy meta buffer, will consume minor cpu time and some memory(at most 32MB for 128MB journal size). Signed-off-by: Xiaoguang Wang <[email protected]> Reviewed-by: Liu Bo <[email protected]> Signed-off-by: Joseph Qi <[email protected]> Acked-by: Caspar Zhang <[email protected]> Signed-off-by: Hao Xu <[email protected]> Acked-by: Joseph Qi <[email protected]> Conflicts: fs/jbd2/journal.c
1 parent bbbbf3a commit bed50b9

File tree

2 files changed

+62
-0
lines changed

2 files changed

+62
-0
lines changed

fs/jbd2/journal.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,9 @@ int jbd2_journal_write_metadata_buffer(transaction_t *transaction,
455455
}
456456
kunmap_atomic(mapped_data);
457457

458+
/* force copy-out */
459+
if (need_copy_out == 0 && journal->j_force_copy)
460+
need_copy_out = 1;
458461
/*
459462
* Do we need to do a data copy?
460463
*/
@@ -1406,6 +1409,57 @@ static const struct proc_ops jbd2_stats_proc_ops = {
14061409
.proc_release = jbd2_seq_stats_release,
14071410
};
14081411

1412+
static int jbd2_seq_force_copy_show(struct seq_file *m, void *v)
1413+
{
1414+
journal_t *journal = m->private;
1415+
1416+
seq_printf(m, "%u\n", journal->j_force_copy);
1417+
return 0;
1418+
}
1419+
1420+
static int jbd2_seq_force_copy_open(struct inode *inode, struct file *filp)
1421+
{
1422+
journal_t *journal = PDE_DATA(inode);
1423+
1424+
return single_open(filp, jbd2_seq_force_copy_show, journal);
1425+
}
1426+
1427+
/* Worst case buffer size needed for holding an integer. */
1428+
#define PROC_NUMBUF 13
1429+
1430+
static ssize_t jbd2_seq_force_copy_write(struct file *file,
1431+
const char __user *buf, size_t count, loff_t *offset)
1432+
{
1433+
struct inode *inode = file_inode(file);
1434+
journal_t *journal = PDE_DATA(inode);
1435+
char buffer[PROC_NUMBUF];
1436+
unsigned int force_copy;
1437+
int err;
1438+
1439+
memset(buffer, 0, sizeof(buffer));
1440+
if (count > sizeof(buffer) - 1)
1441+
count = sizeof(buffer) - 1;
1442+
if (copy_from_user(buffer, buf, count)) {
1443+
err = -EFAULT;
1444+
goto out;
1445+
}
1446+
1447+
err = kstrtouint(strstrip(buffer), 0, &force_copy);
1448+
if (err)
1449+
goto out;
1450+
journal->j_force_copy = force_copy;
1451+
out:
1452+
return err < 0 ? err : count;
1453+
}
1454+
1455+
static const struct proc_ops jbd2_force_copy_proc_ops = {
1456+
.proc_open = jbd2_seq_force_copy_open,
1457+
.proc_read = seq_read,
1458+
.proc_write = jbd2_seq_force_copy_write,
1459+
.proc_lseek = seq_lseek,
1460+
.proc_release = single_release,
1461+
};
1462+
14091463
static struct proc_dir_entry *proc_jbd2_stats;
14101464

14111465
static void jbd2_stats_proc_init(journal_t *journal)
@@ -1414,6 +1468,8 @@ static void jbd2_stats_proc_init(journal_t *journal)
14141468
if (journal->j_proc_entry) {
14151469
proc_create_data("info", S_IRUGO, journal->j_proc_entry,
14161470
&jbd2_info_proc_ops, journal);
1471+
proc_create_data("force_copy", 0644, journal->j_proc_entry,
1472+
&jbd2_force_copy_proc_ops, journal);
14171473
proc_create_data("stats", 0444, journal->j_proc_entry,
14181474
&jbd2_stats_proc_ops, journal);
14191475
}
@@ -1422,6 +1478,7 @@ static void jbd2_stats_proc_init(journal_t *journal)
14221478
static void jbd2_stats_proc_exit(journal_t *journal)
14231479
{
14241480
remove_proc_entry("info", journal->j_proc_entry);
1481+
remove_proc_entry("force_copy", journal->j_proc_entry);
14251482
remove_proc_entry("stats", journal->j_proc_entry);
14261483
remove_proc_entry(journal->j_devname, proc_jbd2_stats);
14271484
}

include/linux/jbd2.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,6 +1227,11 @@ struct journal_s
12271227
*/
12281228
struct transaction_stats_s j_stats;
12291229

1230+
/**
1231+
* @j_force_copy: if not zero, force to do buffer copy-out.
1232+
*/
1233+
unsigned int j_force_copy;
1234+
12301235
/**
12311236
* @j_failed_commit: Failed journal commit ID.
12321237
*/

0 commit comments

Comments
 (0)