.. | .. |
---|
3 | 3 | * Copyright 2019 Google LLC |
---|
4 | 4 | */ |
---|
5 | 5 | #include <linux/crc32.h> |
---|
6 | | -#include <linux/delay.h> |
---|
7 | 6 | #include <linux/file.h> |
---|
8 | 7 | #include <linux/fsverity.h> |
---|
9 | 8 | #include <linux/gfp.h> |
---|
.. | .. |
---|
1104 | 1103 | wake_up_all(&mi->mi_blocks_written_notif_wq); |
---|
1105 | 1104 | } |
---|
1106 | 1105 | |
---|
1107 | | -static int usleep_interruptible(u32 us) |
---|
1108 | | -{ |
---|
1109 | | - /* See: |
---|
1110 | | - * https://www.kernel.org/doc/Documentation/timers/timers-howto.txt |
---|
1111 | | - * for explanation |
---|
1112 | | - */ |
---|
1113 | | - if (us < 10) { |
---|
1114 | | - udelay(us); |
---|
1115 | | - return 0; |
---|
1116 | | - } else if (us < 20000) { |
---|
1117 | | - usleep_range(us, us + us / 10); |
---|
1118 | | - return 0; |
---|
1119 | | - } else |
---|
1120 | | - return msleep_interruptible(us / 1000); |
---|
1121 | | -} |
---|
1122 | | - |
---|
1123 | 1106 | static int wait_for_data_block(struct data_file *df, int block_index, |
---|
1124 | 1107 | struct data_file_block *res_block, |
---|
1125 | | - struct incfs_read_data_file_timeouts *timeouts) |
---|
| 1108 | + struct incfs_read_data_file_timeouts *timeouts, |
---|
| 1109 | + unsigned int *delayed_min_us) |
---|
1126 | 1110 | { |
---|
1127 | 1111 | struct data_file_block block = {}; |
---|
1128 | 1112 | struct data_file_segment *segment = NULL; |
---|
.. | .. |
---|
1130 | 1114 | struct mount_info *mi = NULL; |
---|
1131 | 1115 | int error; |
---|
1132 | 1116 | int wait_res = 0; |
---|
1133 | | - unsigned int delayed_pending_us = 0, delayed_min_us = 0; |
---|
| 1117 | + unsigned int delayed_pending_us = 0; |
---|
1134 | 1118 | bool delayed_pending = false; |
---|
1135 | 1119 | |
---|
1136 | 1120 | if (!df || !res_block) |
---|
.. | .. |
---|
1161 | 1145 | if (is_data_block_present(&block)) { |
---|
1162 | 1146 | *res_block = block; |
---|
1163 | 1147 | if (timeouts && timeouts->min_time_us) { |
---|
1164 | | - delayed_min_us = timeouts->min_time_us; |
---|
1165 | | - error = usleep_interruptible(delayed_min_us); |
---|
| 1148 | + *delayed_min_us = timeouts->min_time_us; |
---|
1166 | 1149 | goto out; |
---|
1167 | 1150 | } |
---|
1168 | 1151 | return 0; |
---|
.. | .. |
---|
1209 | 1192 | delayed_pending = true; |
---|
1210 | 1193 | delayed_pending_us = timeouts->max_pending_time_us - |
---|
1211 | 1194 | jiffies_to_usecs(wait_res); |
---|
1212 | | - if (timeouts->min_pending_time_us > delayed_pending_us) { |
---|
1213 | | - delayed_min_us = timeouts->min_pending_time_us - |
---|
| 1195 | + if (timeouts->min_pending_time_us > delayed_pending_us) |
---|
| 1196 | + *delayed_min_us = timeouts->min_pending_time_us - |
---|
1214 | 1197 | delayed_pending_us; |
---|
1215 | | - error = usleep_interruptible(delayed_min_us); |
---|
1216 | | - if (error) |
---|
1217 | | - return error; |
---|
1218 | | - } |
---|
1219 | 1198 | |
---|
1220 | 1199 | error = down_read_killable(&segment->rwsem); |
---|
1221 | 1200 | if (error) |
---|
.. | .. |
---|
1250 | 1229 | delayed_pending_us; |
---|
1251 | 1230 | } |
---|
1252 | 1231 | |
---|
1253 | | - if (delayed_min_us) { |
---|
| 1232 | + if (delayed_min_us && *delayed_min_us) { |
---|
1254 | 1233 | mi->mi_reads_delayed_min++; |
---|
1255 | | - mi->mi_reads_delayed_min_us += delayed_min_us; |
---|
| 1234 | + mi->mi_reads_delayed_min_us += *delayed_min_us; |
---|
1256 | 1235 | } |
---|
1257 | 1236 | |
---|
1258 | 1237 | return 0; |
---|
.. | .. |
---|
1282 | 1261 | |
---|
1283 | 1262 | ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f, |
---|
1284 | 1263 | int index, struct mem_range tmp, |
---|
1285 | | - struct incfs_read_data_file_timeouts *timeouts) |
---|
| 1264 | + struct incfs_read_data_file_timeouts *timeouts, |
---|
| 1265 | + unsigned int *delayed_min_us) |
---|
1286 | 1266 | { |
---|
1287 | 1267 | loff_t pos; |
---|
1288 | 1268 | ssize_t result; |
---|
.. | .. |
---|
1301 | 1281 | mi = df->df_mount_info; |
---|
1302 | 1282 | bfc = df->df_backing_file_context; |
---|
1303 | 1283 | |
---|
1304 | | - result = wait_for_data_block(df, index, &block, timeouts); |
---|
| 1284 | + result = wait_for_data_block(df, index, &block, timeouts, |
---|
| 1285 | + delayed_min_us); |
---|
1305 | 1286 | if (result < 0) |
---|
1306 | 1287 | goto out; |
---|
1307 | 1288 | |
---|
.. | .. |
---|
1379 | 1360 | } |
---|
1380 | 1361 | |
---|
1381 | 1362 | int incfs_process_new_data_block(struct data_file *df, |
---|
1382 | | - struct incfs_fill_block *block, u8 *data) |
---|
| 1363 | + struct incfs_fill_block *block, u8 *data, |
---|
| 1364 | + bool *complete) |
---|
1383 | 1365 | { |
---|
1384 | 1366 | struct mount_info *mi = NULL; |
---|
1385 | 1367 | struct backing_file_context *bfc = NULL; |
---|
.. | .. |
---|
1418 | 1400 | |
---|
1419 | 1401 | if (error) |
---|
1420 | 1402 | return error; |
---|
1421 | | - if (is_data_block_present(&existing_block)) { |
---|
| 1403 | + if (is_data_block_present(&existing_block)) |
---|
1422 | 1404 | /* Block is already present, nothing to do here */ |
---|
1423 | 1405 | return 0; |
---|
1424 | | - } |
---|
1425 | 1406 | |
---|
1426 | 1407 | error = down_write_killable(&segment->rwsem); |
---|
1427 | 1408 | if (error) |
---|
1428 | 1409 | return error; |
---|
1429 | 1410 | |
---|
1430 | | - error = mutex_lock_interruptible(&bfc->bc_mutex); |
---|
1431 | | - if (!error) { |
---|
1432 | | - error = incfs_write_data_block_to_backing_file( |
---|
1433 | | - bfc, range(data, block->data_len), block->block_index, |
---|
1434 | | - df->df_blockmap_off, flags); |
---|
1435 | | - mutex_unlock(&bfc->bc_mutex); |
---|
1436 | | - } |
---|
1437 | | - if (!error) { |
---|
1438 | | - notify_pending_reads(mi, segment, block->block_index); |
---|
1439 | | - atomic_inc(&df->df_data_blocks_written); |
---|
1440 | | - } |
---|
| 1411 | + /* Recheck inside write lock */ |
---|
| 1412 | + error = get_data_file_block(df, block->block_index, &existing_block); |
---|
| 1413 | + if (error) |
---|
| 1414 | + goto out_up_write; |
---|
1441 | 1415 | |
---|
| 1416 | + if (is_data_block_present(&existing_block)) |
---|
| 1417 | + goto out_up_write; |
---|
| 1418 | + |
---|
| 1419 | + error = mutex_lock_interruptible(&bfc->bc_mutex); |
---|
| 1420 | + if (error) |
---|
| 1421 | + goto out_up_write; |
---|
| 1422 | + |
---|
| 1423 | + error = incfs_write_data_block_to_backing_file(bfc, |
---|
| 1424 | + range(data, block->data_len), block->block_index, |
---|
| 1425 | + df->df_blockmap_off, flags); |
---|
| 1426 | + if (error) |
---|
| 1427 | + goto out_mutex_unlock; |
---|
| 1428 | + |
---|
| 1429 | + if (atomic_inc_return(&df->df_data_blocks_written) |
---|
| 1430 | + >= df->df_data_block_count) |
---|
| 1431 | + *complete = true; |
---|
| 1432 | + |
---|
| 1433 | +out_mutex_unlock: |
---|
| 1434 | + mutex_unlock(&bfc->bc_mutex); |
---|
| 1435 | + if (!error) |
---|
| 1436 | + notify_pending_reads(mi, segment, block->block_index); |
---|
| 1437 | + |
---|
| 1438 | +out_up_write: |
---|
1442 | 1439 | up_write(&segment->rwsem); |
---|
1443 | 1440 | |
---|
1444 | 1441 | if (error) |
---|