From 102a0743326a03cd1a1202ceda21e175b7d3575c Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Tue, 20 Feb 2024 01:20:52 +0000 Subject: [PATCH] add new system file --- kernel/fs/incfs/data_mgmt.c | 87 +++++++++++++++++++++---------------------- 1 files changed, 42 insertions(+), 45 deletions(-) diff --git a/kernel/fs/incfs/data_mgmt.c b/kernel/fs/incfs/data_mgmt.c index fbab68a..6381f8f 100644 --- a/kernel/fs/incfs/data_mgmt.c +++ b/kernel/fs/incfs/data_mgmt.c @@ -3,7 +3,6 @@ * Copyright 2019 Google LLC */ #include <linux/crc32.h> -#include <linux/delay.h> #include <linux/file.h> #include <linux/fsverity.h> #include <linux/gfp.h> @@ -1104,25 +1103,10 @@ wake_up_all(&mi->mi_blocks_written_notif_wq); } -static int usleep_interruptible(u32 us) -{ - /* See: - * https://www.kernel.org/doc/Documentation/timers/timers-howto.txt - * for explanation - */ - if (us < 10) { - udelay(us); - return 0; - } else if (us < 20000) { - usleep_range(us, us + us / 10); - return 0; - } else - return msleep_interruptible(us / 1000); -} - static int wait_for_data_block(struct data_file *df, int block_index, struct data_file_block *res_block, - struct incfs_read_data_file_timeouts *timeouts) + struct incfs_read_data_file_timeouts *timeouts, + unsigned int *delayed_min_us) { struct data_file_block block = {}; struct data_file_segment *segment = NULL; @@ -1130,7 +1114,7 @@ struct mount_info *mi = NULL; int error; int wait_res = 0; - unsigned int delayed_pending_us = 0, delayed_min_us = 0; + unsigned int delayed_pending_us = 0; bool delayed_pending = false; if (!df || !res_block) @@ -1161,8 +1145,7 @@ if (is_data_block_present(&block)) { *res_block = block; if (timeouts && timeouts->min_time_us) { - delayed_min_us = timeouts->min_time_us; - error = usleep_interruptible(delayed_min_us); + *delayed_min_us = timeouts->min_time_us; goto out; } return 0; @@ -1209,13 +1192,9 @@ delayed_pending = true; delayed_pending_us = timeouts->max_pending_time_us - jiffies_to_usecs(wait_res); - if (timeouts->min_pending_time_us > delayed_pending_us) { - delayed_min_us = timeouts->min_pending_time_us - + if (timeouts->min_pending_time_us > delayed_pending_us) + *delayed_min_us = timeouts->min_pending_time_us - delayed_pending_us; - error = usleep_interruptible(delayed_min_us); - if (error) - return error; - } error = down_read_killable(&segment->rwsem); if (error) @@ -1250,9 +1229,9 @@ delayed_pending_us; } - if (delayed_min_us) { + if (delayed_min_us && *delayed_min_us) { mi->mi_reads_delayed_min++; - mi->mi_reads_delayed_min_us += delayed_min_us; + mi->mi_reads_delayed_min_us += *delayed_min_us; } return 0; @@ -1282,7 +1261,8 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f, int index, struct mem_range tmp, - struct incfs_read_data_file_timeouts *timeouts) + struct incfs_read_data_file_timeouts *timeouts, + unsigned int *delayed_min_us) { loff_t pos; ssize_t result; @@ -1301,7 +1281,8 @@ mi = df->df_mount_info; bfc = df->df_backing_file_context; - result = wait_for_data_block(df, index, &block, timeouts); + result = wait_for_data_block(df, index, &block, timeouts, + delayed_min_us); if (result < 0) goto out; @@ -1379,7 +1360,8 @@ } int incfs_process_new_data_block(struct data_file *df, - struct incfs_fill_block *block, u8 *data) + struct incfs_fill_block *block, u8 *data, + bool *complete) { struct mount_info *mi = NULL; struct backing_file_context *bfc = NULL; @@ -1418,27 +1400,42 @@ if (error) return error; - if (is_data_block_present(&existing_block)) { + if (is_data_block_present(&existing_block)) /* Block is already present, nothing to do here */ return 0; - } error = down_write_killable(&segment->rwsem); if (error) return error; - error = mutex_lock_interruptible(&bfc->bc_mutex); - if (!error) { - error = incfs_write_data_block_to_backing_file( - bfc, range(data, block->data_len), block->block_index, - df->df_blockmap_off, flags); - mutex_unlock(&bfc->bc_mutex); - } - if (!error) { - notify_pending_reads(mi, segment, block->block_index); - atomic_inc(&df->df_data_blocks_written); - } + /* Recheck inside write lock */ + error = get_data_file_block(df, block->block_index, &existing_block); + if (error) + goto out_up_write; + if (is_data_block_present(&existing_block)) + goto out_up_write; + + error = mutex_lock_interruptible(&bfc->bc_mutex); + if (error) + goto out_up_write; + + error = incfs_write_data_block_to_backing_file(bfc, + range(data, block->data_len), block->block_index, + df->df_blockmap_off, flags); + if (error) + goto out_mutex_unlock; + + if (atomic_inc_return(&df->df_data_blocks_written) + >= df->df_data_block_count) + *complete = true; + +out_mutex_unlock: + mutex_unlock(&bfc->bc_mutex); + if (!error) + notify_pending_reads(mi, segment, block->block_index); + +out_up_write: up_write(&segment->rwsem); if (error) -- Gitblit v1.6.2