0

In ext3 file system, if it is on journal mode, would indirect block, double indirect block and triple indirect block be considered as metadata blocks and get journaled?

yangsuli
  • 1,252
  • 5
  • 16
  • 33

1 Answers1

0

Use the source, Luke - from Linux fs/ext3/inode.c (line number for the link correct as per this writing, but the URL is Linus' head tree so this may eventually change):

/*
 * 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);
[ ... ]
}

This clearly states file extensions / truncations (i.e. the allocation and/or release of direct/indirect blocks of any level) are always transacted. There's also the code in ext3_get_blocks() itself which will open a transaction even if called without previously having created a transaction - that's used for direct I/O writes.

So in short - yes, as long as the ext3 has a journal, then modifications of direct/indirect blocks of any level are always transacted.

FrankH.
  • 17,675
  • 3
  • 44
  • 63