ext3 ファイル システムで、ジャーナル モードの場合、間接ブロック、二重間接ブロック、および三重間接ブロックはメタデータ ブロックと見なされ、ジャーナル処理されますか?
1 に答える
0
Linuxfs/ext3/inode.c
からのソースである Luke を使用します(リンクの行番号はこの記事の記述どおりですが、URL は Linus のヘッド ツリーであるため、最終的に変更される可能性があります)。
/*
* Note that we always start a transaction even if we're not journalling
* data. This is to preserve ordering: any hole instantiation within
* __block_write_full_page -> ext3_get_block() should be journalled
* along with the data so we don't crash and then get metadata which
* refers to old data.
[ ... ]
static int ext3_ordered_writepage(struct page *page,
struct writeback_control *wbc)
{
struct inode *inode = page->mapping->host;
struct buffer_head *page_bufs;
handle_t *handle = NULL;
int ret = 0;
int err;
[ ... ]
handle = ext3_journal_start(inode, ext3_writepage_trans_blocks(inode));
[ ... ]
ret = block_write_full_page(page, ext3_get_block, wbc);
[ ... ]
/*
* And attach them to the current transaction. But only if
* block_write_full_page() succeeded. Otherwise they are unmapped,
* and generally junk.
*/
if (ret == 0) {
err = walk_page_buffers(handle, page_bufs, 0, PAGE_CACHE_SIZE,
NULL, journal_dirty_data_fn);
if (!ret)
ret = err;
}
walk_page_buffers(handle, page_bufs, 0,
PAGE_CACHE_SIZE, NULL, bput_one);
err = ext3_journal_stop(handle);
if (!ret)
ret = err;
[ ... ]
return ret;
}
[ ... ]
/*
* ext3_truncate()
*
* We block out ext3_get_block() block instantiations across the entire
* transaction, and VFS/VM ensures that ext3_truncate() cannot run
* simultaneously on behalf of the same inode.
*
* As we work through the truncate and commit bits of it to the journal there
* is one core, guiding principle: the file's tree must always be consistent on
* disk. We must be able to restart the truncate after a crash.
*
[ ... ]
*/
void ext3_truncate(struct inode *inode)
{
handle_t *handle;
[ ... ]
handle = start_transaction(inode);
[ ... ]
/*
* OK. This truncate is going to happen. We add the inode to the
* orphan list, so that if this truncate spans multiple transactions,
* and we crash, we will resume the truncate when the filesystem
* recovers. It also marks the inode dirty, to catch the new size.
*
* Implication: the file must always be in a sane, consistent
* truncatable state while each transaction commits.
*/
if (ext3_orphan_add(handle, inode))
goto out_stop;
[ ... ]
if (n == 1) { /* direct blocks */
ext3_free_data(handle, inode, NULL, i_data+offsets[0],
i_data + EXT3_NDIR_BLOCKS);
goto do_indirects;
}
[ ... ]
do_indirects:
/* Kill the remaining (whole) subtrees */
switch (offsets[0]) {
default:
nr = i_data[EXT3_IND_BLOCK];
if (nr) {
ext3_free_branches(handle, inode, NULL, &nr, &nr+1, 1);
i_data[EXT3_IND_BLOCK] = 0;
}
case EXT3_IND_BLOCK:
nr = i_data[EXT3_DIND_BLOCK];
if (nr) {
ext3_free_branches(handle, inode, NULL, &nr, &nr+1, 2);
i_data[EXT3_DIND_BLOCK] = 0;
}
case EXT3_DIND_BLOCK:
nr = i_data[EXT3_TIND_BLOCK];
if (nr) {
ext3_free_branches(handle, inode, NULL, &nr, &nr+1, 3);
i_data[EXT3_TIND_BLOCK] = 0;
}
case EXT3_TIND_BLOCK:
;
}
[ ... ]
ext3_journal_stop(handle);
[ ... ]
}
これは、ファイルの拡張子/切り捨て (つまり、任意のレベルの直接/間接ブロックの割り当ておよび/または解放) が常に処理されることを明確に示しています。ext3_get_blocks()
以前にトランザクションを作成せずに呼び出された場合でも、トランザクションを開くコード自体もあります。これは、直接 I/O 書き込みに使用されます。
つまり、ext3 にジャーナルがある限り、任意のレベルの直接/間接ブロックの変更は常に処理されます。
于 2013-02-15T11:07:33.367 に答える