From e2af92942fe3f401ad03f196d7b9e962f193ff8c Mon Sep 17 00:00:00 2001 From: jason50123 Date: Thu, 20 Jun 2024 10:54:01 +0800 Subject: [PATCH] Add journal to write function In the current design of simplefs, we can only access the extent metadata and perform the 'journal' action on it. To write inode and other metadata, we might need to emulate `ext4_dirty_inode`. This method primarily uses the content of struct ext4_iloc to find the correct location of the inode on disk and records it in the journal. However, in our current situation, simply using `mark_inode_dirty` to handle dirty inodes does not allow us to obtain the inode's location, thus preventing us from recording it in the journal. But currently, the idea is that we might create a new buffer head, use `jbd2_journal_get_create_access` to put the dirty inode in it, and then use `jbd2_journal_dirty_metadata` to write it to the journal. --- file.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/file.c b/file.c index 73131e8..3a8e074 100644 --- a/file.c +++ b/file.c @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -34,6 +35,20 @@ static int simplefs_file_get_block(struct inode *inode, bh_index = sb_bread(sb, ci->ei_block); if (!bh_index) return -EIO; + + handle_t *handle = journal_current_handle(); + if (!handle) { + brelse(bh_index); + return -EIO; + } + + ret = jbd2_journal_get_write_access(handle, bh_index); + if (ret) { + brelse(bh_index); + pr_info("Can't get write access for bh\n"); + return ret; + } + index = (struct simplefs_file_ei_block *) bh_index->b_data; extent = simplefs_ext_search(index, iblock); @@ -63,6 +78,13 @@ static int simplefs_file_get_block(struct inode *inode, extent ? index->extents[extent - 1].ee_block + index->extents[extent - 1].ee_len : 0; + ret = jbd2_journal_dirty_metadata(handle, bh_index); + if (ret) { + brelse(bh_index); + return ret; + } + mark_buffer_dirty_inode(bh_index, inode); + } else { bno = index->extents[extent].ee_start + iblock - index->extents[extent].ee_block; @@ -133,6 +155,7 @@ static int simplefs_write_begin(struct file *file, struct simplefs_sb_info *sbi = SIMPLEFS_SB(file->f_inode->i_sb); int err; uint32_t nr_allocs = 0; + handle_t *handle; /* Check if the write can be completed (enough space?) */ if (pos + len > SIMPLEFS_MAX_FILESIZE) @@ -146,6 +169,16 @@ static int simplefs_write_begin(struct file *file, if (nr_allocs > sbi->nr_free_blocks) return -ENOSPC; + // handle journal start here + /* + * Fix me: the metadata type we should store into journal + * In the current situation, we only record the location of the extent + * and write that metadata to the journal. + */ + handle = jbd2_journal_start(sbi->journal, 1); + if (IS_ERR(handle)) + return PTR_ERR(handle); + /* prepare the write */ #if SIMPLEFS_AT_LEAST(5, 19, 0) err = block_write_begin(mapping, pos, len, pagep, simplefs_file_get_block); @@ -174,6 +207,16 @@ static int simplefs_write_end(struct file *file, struct inode *inode = file->f_inode; struct simplefs_inode_info *ci = SIMPLEFS_INODE(inode); struct super_block *sb = inode->i_sb; + + handle_t *handle; + + // handle journal start here + handle = journal_current_handle(); + if (!handle) { + pr_err("can't get journal handle\n"); + return -EIO; + } + #if SIMPLEFS_AT_LEAST(6, 6, 0) struct timespec64 cur_time; #endif @@ -223,6 +266,14 @@ static int simplefs_write_end(struct file *file, nr_blocks_old - inode->i_blocks); goto end; } + + int retval = jbd2_journal_get_write_access(handle, bh_index); + if (WARN_ON(retval)) { + brelse(bh_index); + pr_info("cant get journal write access\n"); + return retval; + } + index = (struct simplefs_file_ei_block *) bh_index->b_data; first_ext = simplefs_ext_search(index, inode->i_blocks - 1); @@ -238,9 +289,13 @@ static int simplefs_write_end(struct file *file, index->extents[i].ee_len); memset(&index->extents[i], 0, sizeof(struct simplefs_extent)); } + jbd2_journal_dirty_metadata(handle, bh_index); mark_buffer_dirty(bh_index); brelse(bh_index); } + + jbd2_journal_stop(handle); + end: return ret; }