Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit 22a5c32

Browse files
PaulLawrenceGoogleTreehugger Robot
authored andcommitted
ANDROID: incremental fs: Move throttling to outside page lock
Bug: 241479010 Test: incfs_test passes, play confirm behavior in bug is fixed Signed-off-by: Paul Lawrence <paullawrence@google.com> Change-Id: Ie51f2b76d0873057f54fecf7fcc793c66df20969
1 parent 790cf85 commit 22a5c32

File tree

7 files changed

+51
-36
lines changed

7 files changed

+51
-36
lines changed

Documentation/ABI/testing/sysfs-fs-incfs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ Contact: Paul Lawrence <paullawrence@google.com>
1515
Description: Reads 'supported'. Present if zstd compression is supported
1616
for data blocks.
1717

18+
What: /sys/fs/incremental-fs/features/bugfix_throttling
19+
Date: January 2023
20+
Contact: Paul Lawrence <paullawrence@google.com>
21+
Description: Reads 'supported'. Present if the throttling lock bug is fixed
22+
https://android-review.git.corp.google.com/c/kernel/common/+/2381827
23+
1824
What: /sys/fs/incremental-fs/instances/[name]
1925
Date: April 2021
2026
Contact: Paul Lawrence <paullawrence@google.com>

Documentation/filesystems/incfs.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ Features
3535
/sys/fs/incremental-fs/features/zstd
3636
Reads 'supported'. Present if zstd compression is supported for data blocks.
3737

38+
/sys/fs/incremental-fs/features/bugfix_throttling
39+
Reads 'supported'. Present if the throttling lock bug is fixed
40+
3841
Optional per mount
3942
------------------
4043

fs/incfs/data_mgmt.c

Lines changed: 12 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
* Copyright 2019 Google LLC
44
*/
55
#include <linux/crc32.h>
6-
#include <linux/delay.h>
76
#include <linux/file.h>
87
#include <linux/fsverity.h>
98
#include <linux/gfp.h>
@@ -1106,33 +1105,18 @@ static void notify_pending_reads(struct mount_info *mi,
11061105
wake_up_all(&mi->mi_blocks_written_notif_wq);
11071106
}
11081107

1109-
static int usleep_interruptible(u32 us)
1110-
{
1111-
/* See:
1112-
* https://www.kernel.org/doc/Documentation/timers/timers-howto.txt
1113-
* for explanation
1114-
*/
1115-
if (us < 10) {
1116-
udelay(us);
1117-
return 0;
1118-
} else if (us < 20000) {
1119-
usleep_range(us, us + us / 10);
1120-
return 0;
1121-
} else
1122-
return msleep_interruptible(us / 1000);
1123-
}
1124-
11251108
static int wait_for_data_block(struct data_file *df, int block_index,
11261109
struct data_file_block *res_block,
1127-
struct incfs_read_data_file_timeouts *timeouts)
1110+
struct incfs_read_data_file_timeouts *timeouts,
1111+
unsigned int *delayed_min_us)
11281112
{
11291113
struct data_file_block block = {};
11301114
struct data_file_segment *segment = NULL;
11311115
struct pending_read *read = NULL;
11321116
struct mount_info *mi = NULL;
11331117
int error;
11341118
int wait_res = 0;
1135-
unsigned int delayed_pending_us = 0, delayed_min_us = 0;
1119+
unsigned int delayed_pending_us = 0;
11361120
bool delayed_pending = false;
11371121

11381122
if (!df || !res_block)
@@ -1163,8 +1147,7 @@ static int wait_for_data_block(struct data_file *df, int block_index,
11631147
if (is_data_block_present(&block)) {
11641148
*res_block = block;
11651149
if (timeouts && timeouts->min_time_us) {
1166-
delayed_min_us = timeouts->min_time_us;
1167-
error = usleep_interruptible(delayed_min_us);
1150+
*delayed_min_us = timeouts->min_time_us;
11681151
goto out;
11691152
}
11701153
return 0;
@@ -1211,13 +1194,9 @@ static int wait_for_data_block(struct data_file *df, int block_index,
12111194
delayed_pending = true;
12121195
delayed_pending_us = timeouts->max_pending_time_us -
12131196
jiffies_to_usecs(wait_res);
1214-
if (timeouts->min_pending_time_us > delayed_pending_us) {
1215-
delayed_min_us = timeouts->min_pending_time_us -
1197+
if (timeouts->min_pending_time_us > delayed_pending_us)
1198+
*delayed_min_us = timeouts->min_pending_time_us -
12161199
delayed_pending_us;
1217-
error = usleep_interruptible(delayed_min_us);
1218-
if (error)
1219-
return error;
1220-
}
12211200

12221201
error = down_read_killable(&segment->rwsem);
12231202
if (error)
@@ -1252,9 +1231,9 @@ static int wait_for_data_block(struct data_file *df, int block_index,
12521231
delayed_pending_us;
12531232
}
12541233

1255-
if (delayed_min_us) {
1234+
if (delayed_min_us && *delayed_min_us) {
12561235
mi->mi_reads_delayed_min++;
1257-
mi->mi_reads_delayed_min_us += delayed_min_us;
1236+
mi->mi_reads_delayed_min_us += *delayed_min_us;
12581237
}
12591238

12601239
return 0;
@@ -1284,7 +1263,8 @@ static int incfs_update_sysfs_error(struct file *file, int index, int result,
12841263

12851264
ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f,
12861265
int index, struct mem_range tmp,
1287-
struct incfs_read_data_file_timeouts *timeouts)
1266+
struct incfs_read_data_file_timeouts *timeouts,
1267+
unsigned int *delayed_min_us)
12881268
{
12891269
loff_t pos;
12901270
ssize_t result;
@@ -1303,7 +1283,8 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f,
13031283
mi = df->df_mount_info;
13041284
bfc = df->df_backing_file_context;
13051285

1306-
result = wait_for_data_block(df, index, &block, timeouts);
1286+
result = wait_for_data_block(df, index, &block, timeouts,
1287+
delayed_min_us);
13071288
if (result < 0)
13081289
goto out;
13091290

fs/incfs/data_mgmt.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,8 @@ struct incfs_read_data_file_timeouts {
429429

430430
ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f,
431431
int index, struct mem_range tmp,
432-
struct incfs_read_data_file_timeouts *timeouts);
432+
struct incfs_read_data_file_timeouts *timeouts,
433+
unsigned int *delayed_min_us);
433434

434435
ssize_t incfs_read_merkle_tree_blocks(struct mem_range dst,
435436
struct data_file *df, size_t offset);

fs/incfs/sysfs.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,13 @@ static struct kobj_attribute name##_attr = __ATTR_RO(name)
3333
DECLARE_FEATURE_FLAG(corefs);
3434
DECLARE_FEATURE_FLAG(zstd);
3535
DECLARE_FEATURE_FLAG(v2);
36+
DECLARE_FEATURE_FLAG(bugfix_throttling);
3637

3738
static struct attribute *attributes[] = {
3839
&corefs_attr.attr,
3940
&zstd_attr.attr,
4041
&v2_attr.attr,
42+
&bugfix_throttling_attr.attr,
4143
NULL,
4244
};
4345

fs/incfs/verity.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ static int incfs_build_merkle_tree(struct file *f, struct data_file *df,
323323

324324
if (lvl == 0)
325325
result = incfs_read_data_file_block(partial_buf,
326-
f, i, tmp, NULL);
326+
f, i, tmp, NULL, NULL);
327327
else {
328328
hash_level_offset = hash_offset +
329329
hash_tree->hash_level_suboffset[lvl - 1];

fs/incfs/vfs.c

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include <linux/blkdev.h>
77
#include <linux/compat.h>
8+
#include <linux/delay.h>
89
#include <linux/file.h>
910
#include <linux/fs.h>
1011
#include <linux/fs_stack.h>
@@ -483,7 +484,8 @@ static struct dentry *open_or_create_special_dir(struct dentry *backing_dir,
483484

484485
static int read_single_page_timeouts(struct data_file *df, struct file *f,
485486
int block_index, struct mem_range range,
486-
struct mem_range tmp)
487+
struct mem_range tmp,
488+
unsigned int *delayed_min_us)
487489
{
488490
struct mount_info *mi = df->df_mount_info;
489491
struct incfs_read_data_file_timeouts timeouts = {
@@ -515,7 +517,23 @@ static int read_single_page_timeouts(struct data_file *df, struct file *f,
515517
}
516518

517519
return incfs_read_data_file_block(range, f, block_index, tmp,
518-
&timeouts);
520+
&timeouts, delayed_min_us);
521+
}
522+
523+
static int usleep_interruptible(u32 us)
524+
{
525+
/* See:
526+
* https://www.kernel.org/doc/Documentation/timers/timers-howto.txt
527+
* for explanation
528+
*/
529+
if (us < 10) {
530+
udelay(us);
531+
return 0;
532+
} else if (us < 20000) {
533+
usleep_range(us, us + us / 10);
534+
return 0;
535+
} else
536+
return msleep_interruptible(us / 1000);
519537
}
520538

521539
static int read_folio(struct file *f, struct folio *folio)
@@ -529,6 +547,7 @@ static int read_folio(struct file *f, struct folio *folio)
529547
int result = 0;
530548
void *page_start;
531549
int block_index;
550+
unsigned int delayed_min_us = 0;
532551

533552
if (!df) {
534553
SetPageError(page);
@@ -554,7 +573,8 @@ static int read_folio(struct file *f, struct folio *folio)
554573
bytes_to_read = min_t(loff_t, size - offset, PAGE_SIZE);
555574

556575
read_result = read_single_page_timeouts(df, f, block_index,
557-
range(page_start, bytes_to_read), tmp);
576+
range(page_start, bytes_to_read), tmp,
577+
&delayed_min_us);
558578

559579
free_pages((unsigned long)tmp.data, get_order(tmp.len));
560580
} else {
@@ -576,6 +596,8 @@ static int read_folio(struct file *f, struct folio *folio)
576596
flush_dcache_page(page);
577597
kunmap(page);
578598
unlock_page(page);
599+
if (delayed_min_us)
600+
usleep_interruptible(delayed_min_us);
579601
return result;
580602
}
581603

0 commit comments

Comments
 (0)