diff options
author | Frank Mayhar <fmayhar@google.com> | 2009-01-07 00:06:22 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2009-01-07 00:06:22 -0500 |
commit | 0390131ba84fd3f726f9e24fc4553828125700bb (patch) | |
tree | 4c90afad4e8690e25aec0ce069fd450e92ab5f96 /fs/ext4/namei.c | |
parent | ff7ef329b268b603ea4a2303241ef1c3829fd574 (diff) |
ext4: Allow ext4 to run without a journal
A few weeks ago I posted a patch for discussion that allowed ext4 to run
without a journal. Since that time I've integrated the excellent
comments from Andreas and fixed several serious bugs. We're currently
running with this patch and generating some performance numbers against
both ext2 (with backported reservations code) and ext4 with and without
a journal. It just so happens that running without a journal is
slightly faster for most everything.
We did
iozone -T -t 4 s 2g -r 256k -T -I -i0 -i1 -i2
which creates 4 threads, each of which create and do reads and writes on
a 2G file, with a buffer size of 256K, using O_DIRECT for all file opens
to bypass the page cache. Results:
ext2 ext4, default ext4, no journal
initial writes 13.0 MB/s 15.4 MB/s 15.7 MB/s
rewrites 13.1 MB/s 15.6 MB/s 15.9 MB/s
reads 15.2 MB/s 16.9 MB/s 17.2 MB/s
re-reads 15.3 MB/s 16.9 MB/s 17.2 MB/s
random readers 5.6 MB/s 5.6 MB/s 5.7 MB/s
random writers 5.1 MB/s 5.3 MB/s 5.4 MB/s
So it seems that, so far, this was a useful exercise.
Signed-off-by: Frank Mayhar <fmayhar@google.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/namei.c')
-rw-r--r-- | fs/ext4/namei.c | 56 |
1 files changed, 31 insertions, 25 deletions
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 84a68ae623c1..08873e938ab2 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
@@ -1233,10 +1233,10 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, | |||
1233 | de = de2; | 1233 | de = de2; |
1234 | } | 1234 | } |
1235 | dx_insert_block(frame, hash2 + continued, newblock); | 1235 | dx_insert_block(frame, hash2 + continued, newblock); |
1236 | err = ext4_journal_dirty_metadata(handle, bh2); | 1236 | err = ext4_handle_dirty_metadata(handle, dir, bh2); |
1237 | if (err) | 1237 | if (err) |
1238 | goto journal_error; | 1238 | goto journal_error; |
1239 | err = ext4_journal_dirty_metadata(handle, frame->bh); | 1239 | err = ext4_handle_dirty_metadata(handle, dir, frame->bh); |
1240 | if (err) | 1240 | if (err) |
1241 | goto journal_error; | 1241 | goto journal_error; |
1242 | brelse(bh2); | 1242 | brelse(bh2); |
@@ -1340,8 +1340,8 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry, | |||
1340 | ext4_update_dx_flag(dir); | 1340 | ext4_update_dx_flag(dir); |
1341 | dir->i_version++; | 1341 | dir->i_version++; |
1342 | ext4_mark_inode_dirty(handle, dir); | 1342 | ext4_mark_inode_dirty(handle, dir); |
1343 | BUFFER_TRACE(bh, "call ext4_journal_dirty_metadata"); | 1343 | BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); |
1344 | err = ext4_journal_dirty_metadata(handle, bh); | 1344 | err = ext4_handle_dirty_metadata(handle, dir, bh); |
1345 | if (err) | 1345 | if (err) |
1346 | ext4_std_error(dir->i_sb, err); | 1346 | ext4_std_error(dir->i_sb, err); |
1347 | brelse(bh); | 1347 | brelse(bh); |
@@ -1581,7 +1581,7 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry, | |||
1581 | dxtrace(dx_show_index("node", frames[1].entries)); | 1581 | dxtrace(dx_show_index("node", frames[1].entries)); |
1582 | dxtrace(dx_show_index("node", | 1582 | dxtrace(dx_show_index("node", |
1583 | ((struct dx_node *) bh2->b_data)->entries)); | 1583 | ((struct dx_node *) bh2->b_data)->entries)); |
1584 | err = ext4_journal_dirty_metadata(handle, bh2); | 1584 | err = ext4_handle_dirty_metadata(handle, inode, bh2); |
1585 | if (err) | 1585 | if (err) |
1586 | goto journal_error; | 1586 | goto journal_error; |
1587 | brelse (bh2); | 1587 | brelse (bh2); |
@@ -1607,7 +1607,7 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry, | |||
1607 | if (err) | 1607 | if (err) |
1608 | goto journal_error; | 1608 | goto journal_error; |
1609 | } | 1609 | } |
1610 | ext4_journal_dirty_metadata(handle, frames[0].bh); | 1610 | ext4_handle_dirty_metadata(handle, inode, frames[0].bh); |
1611 | } | 1611 | } |
1612 | de = do_split(handle, dir, &bh, frame, &hinfo, &err); | 1612 | de = do_split(handle, dir, &bh, frame, &hinfo, &err); |
1613 | if (!de) | 1613 | if (!de) |
@@ -1653,8 +1653,8 @@ static int ext4_delete_entry(handle_t *handle, | |||
1653 | else | 1653 | else |
1654 | de->inode = 0; | 1654 | de->inode = 0; |
1655 | dir->i_version++; | 1655 | dir->i_version++; |
1656 | BUFFER_TRACE(bh, "call ext4_journal_dirty_metadata"); | 1656 | BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); |
1657 | ext4_journal_dirty_metadata(handle, bh); | 1657 | ext4_handle_dirty_metadata(handle, dir, bh); |
1658 | return 0; | 1658 | return 0; |
1659 | } | 1659 | } |
1660 | i += ext4_rec_len_from_disk(de->rec_len); | 1660 | i += ext4_rec_len_from_disk(de->rec_len); |
@@ -1732,7 +1732,7 @@ retry: | |||
1732 | return PTR_ERR(handle); | 1732 | return PTR_ERR(handle); |
1733 | 1733 | ||
1734 | if (IS_DIRSYNC(dir)) | 1734 | if (IS_DIRSYNC(dir)) |
1735 | handle->h_sync = 1; | 1735 | ext4_handle_sync(handle); |
1736 | 1736 | ||
1737 | inode = ext4_new_inode (handle, dir, mode); | 1737 | inode = ext4_new_inode (handle, dir, mode); |
1738 | err = PTR_ERR(inode); | 1738 | err = PTR_ERR(inode); |
@@ -1766,7 +1766,7 @@ retry: | |||
1766 | return PTR_ERR(handle); | 1766 | return PTR_ERR(handle); |
1767 | 1767 | ||
1768 | if (IS_DIRSYNC(dir)) | 1768 | if (IS_DIRSYNC(dir)) |
1769 | handle->h_sync = 1; | 1769 | ext4_handle_sync(handle); |
1770 | 1770 | ||
1771 | inode = ext4_new_inode(handle, dir, mode); | 1771 | inode = ext4_new_inode(handle, dir, mode); |
1772 | err = PTR_ERR(inode); | 1772 | err = PTR_ERR(inode); |
@@ -1802,7 +1802,7 @@ retry: | |||
1802 | return PTR_ERR(handle); | 1802 | return PTR_ERR(handle); |
1803 | 1803 | ||
1804 | if (IS_DIRSYNC(dir)) | 1804 | if (IS_DIRSYNC(dir)) |
1805 | handle->h_sync = 1; | 1805 | ext4_handle_sync(handle); |
1806 | 1806 | ||
1807 | inode = ext4_new_inode(handle, dir, S_IFDIR | mode); | 1807 | inode = ext4_new_inode(handle, dir, S_IFDIR | mode); |
1808 | err = PTR_ERR(inode); | 1808 | err = PTR_ERR(inode); |
@@ -1831,8 +1831,8 @@ retry: | |||
1831 | strcpy(de->name, ".."); | 1831 | strcpy(de->name, ".."); |
1832 | ext4_set_de_type(dir->i_sb, de, S_IFDIR); | 1832 | ext4_set_de_type(dir->i_sb, de, S_IFDIR); |
1833 | inode->i_nlink = 2; | 1833 | inode->i_nlink = 2; |
1834 | BUFFER_TRACE(dir_block, "call ext4_journal_dirty_metadata"); | 1834 | BUFFER_TRACE(dir_block, "call ext4_handle_dirty_metadata"); |
1835 | ext4_journal_dirty_metadata(handle, dir_block); | 1835 | ext4_handle_dirty_metadata(handle, dir, dir_block); |
1836 | brelse(dir_block); | 1836 | brelse(dir_block); |
1837 | ext4_mark_inode_dirty(handle, inode); | 1837 | ext4_mark_inode_dirty(handle, inode); |
1838 | err = ext4_add_entry(handle, dentry, inode); | 1838 | err = ext4_add_entry(handle, dentry, inode); |
@@ -1944,6 +1944,9 @@ int ext4_orphan_add(handle_t *handle, struct inode *inode) | |||
1944 | struct ext4_iloc iloc; | 1944 | struct ext4_iloc iloc; |
1945 | int err = 0, rc; | 1945 | int err = 0, rc; |
1946 | 1946 | ||
1947 | if (!ext4_handle_valid(handle)) | ||
1948 | return 0; | ||
1949 | |||
1947 | lock_super(sb); | 1950 | lock_super(sb); |
1948 | if (!list_empty(&EXT4_I(inode)->i_orphan)) | 1951 | if (!list_empty(&EXT4_I(inode)->i_orphan)) |
1949 | goto out_unlock; | 1952 | goto out_unlock; |
@@ -1972,7 +1975,7 @@ int ext4_orphan_add(handle_t *handle, struct inode *inode) | |||
1972 | /* Insert this inode at the head of the on-disk orphan list... */ | 1975 | /* Insert this inode at the head of the on-disk orphan list... */ |
1973 | NEXT_ORPHAN(inode) = le32_to_cpu(EXT4_SB(sb)->s_es->s_last_orphan); | 1976 | NEXT_ORPHAN(inode) = le32_to_cpu(EXT4_SB(sb)->s_es->s_last_orphan); |
1974 | EXT4_SB(sb)->s_es->s_last_orphan = cpu_to_le32(inode->i_ino); | 1977 | EXT4_SB(sb)->s_es->s_last_orphan = cpu_to_le32(inode->i_ino); |
1975 | err = ext4_journal_dirty_metadata(handle, EXT4_SB(sb)->s_sbh); | 1978 | err = ext4_handle_dirty_metadata(handle, inode, EXT4_SB(sb)->s_sbh); |
1976 | rc = ext4_mark_iloc_dirty(handle, inode, &iloc); | 1979 | rc = ext4_mark_iloc_dirty(handle, inode, &iloc); |
1977 | if (!err) | 1980 | if (!err) |
1978 | err = rc; | 1981 | err = rc; |
@@ -2010,6 +2013,9 @@ int ext4_orphan_del(handle_t *handle, struct inode *inode) | |||
2010 | struct ext4_iloc iloc; | 2013 | struct ext4_iloc iloc; |
2011 | int err = 0; | 2014 | int err = 0; |
2012 | 2015 | ||
2016 | if (!ext4_handle_valid(handle)) | ||
2017 | return 0; | ||
2018 | |||
2013 | lock_super(inode->i_sb); | 2019 | lock_super(inode->i_sb); |
2014 | if (list_empty(&ei->i_orphan)) { | 2020 | if (list_empty(&ei->i_orphan)) { |
2015 | unlock_super(inode->i_sb); | 2021 | unlock_super(inode->i_sb); |
@@ -2028,7 +2034,7 @@ int ext4_orphan_del(handle_t *handle, struct inode *inode) | |||
2028 | * transaction handle with which to update the orphan list on | 2034 | * transaction handle with which to update the orphan list on |
2029 | * disk, but we still need to remove the inode from the linked | 2035 | * disk, but we still need to remove the inode from the linked |
2030 | * list in memory. */ | 2036 | * list in memory. */ |
2031 | if (!handle) | 2037 | if (sbi->s_journal && !handle) |
2032 | goto out; | 2038 | goto out; |
2033 | 2039 | ||
2034 | err = ext4_reserve_inode_write(handle, inode, &iloc); | 2040 | err = ext4_reserve_inode_write(handle, inode, &iloc); |
@@ -2042,7 +2048,7 @@ int ext4_orphan_del(handle_t *handle, struct inode *inode) | |||
2042 | if (err) | 2048 | if (err) |
2043 | goto out_brelse; | 2049 | goto out_brelse; |
2044 | sbi->s_es->s_last_orphan = cpu_to_le32(ino_next); | 2050 | sbi->s_es->s_last_orphan = cpu_to_le32(ino_next); |
2045 | err = ext4_journal_dirty_metadata(handle, sbi->s_sbh); | 2051 | err = ext4_handle_dirty_metadata(handle, inode, sbi->s_sbh); |
2046 | } else { | 2052 | } else { |
2047 | struct ext4_iloc iloc2; | 2053 | struct ext4_iloc iloc2; |
2048 | struct inode *i_prev = | 2054 | struct inode *i_prev = |
@@ -2093,7 +2099,7 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry) | |||
2093 | goto end_rmdir; | 2099 | goto end_rmdir; |
2094 | 2100 | ||
2095 | if (IS_DIRSYNC(dir)) | 2101 | if (IS_DIRSYNC(dir)) |
2096 | handle->h_sync = 1; | 2102 | ext4_handle_sync(handle); |
2097 | 2103 | ||
2098 | inode = dentry->d_inode; | 2104 | inode = dentry->d_inode; |
2099 | 2105 | ||
@@ -2147,7 +2153,7 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry) | |||
2147 | return PTR_ERR(handle); | 2153 | return PTR_ERR(handle); |
2148 | 2154 | ||
2149 | if (IS_DIRSYNC(dir)) | 2155 | if (IS_DIRSYNC(dir)) |
2150 | handle->h_sync = 1; | 2156 | ext4_handle_sync(handle); |
2151 | 2157 | ||
2152 | retval = -ENOENT; | 2158 | retval = -ENOENT; |
2153 | bh = ext4_find_entry(dir, &dentry->d_name, &de); | 2159 | bh = ext4_find_entry(dir, &dentry->d_name, &de); |
@@ -2204,7 +2210,7 @@ retry: | |||
2204 | return PTR_ERR(handle); | 2210 | return PTR_ERR(handle); |
2205 | 2211 | ||
2206 | if (IS_DIRSYNC(dir)) | 2212 | if (IS_DIRSYNC(dir)) |
2207 | handle->h_sync = 1; | 2213 | ext4_handle_sync(handle); |
2208 | 2214 | ||
2209 | inode = ext4_new_inode(handle, dir, S_IFLNK|S_IRWXUGO); | 2215 | inode = ext4_new_inode(handle, dir, S_IFLNK|S_IRWXUGO); |
2210 | err = PTR_ERR(inode); | 2216 | err = PTR_ERR(inode); |
@@ -2267,7 +2273,7 @@ retry: | |||
2267 | return PTR_ERR(handle); | 2273 | return PTR_ERR(handle); |
2268 | 2274 | ||
2269 | if (IS_DIRSYNC(dir)) | 2275 | if (IS_DIRSYNC(dir)) |
2270 | handle->h_sync = 1; | 2276 | ext4_handle_sync(handle); |
2271 | 2277 | ||
2272 | inode->i_ctime = ext4_current_time(inode); | 2278 | inode->i_ctime = ext4_current_time(inode); |
2273 | ext4_inc_count(handle, inode); | 2279 | ext4_inc_count(handle, inode); |
@@ -2316,7 +2322,7 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
2316 | return PTR_ERR(handle); | 2322 | return PTR_ERR(handle); |
2317 | 2323 | ||
2318 | if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir)) | 2324 | if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir)) |
2319 | handle->h_sync = 1; | 2325 | ext4_handle_sync(handle); |
2320 | 2326 | ||
2321 | old_bh = ext4_find_entry(old_dir, &old_dentry->d_name, &old_de); | 2327 | old_bh = ext4_find_entry(old_dir, &old_dentry->d_name, &old_de); |
2322 | /* | 2328 | /* |
@@ -2370,8 +2376,8 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
2370 | new_dir->i_ctime = new_dir->i_mtime = | 2376 | new_dir->i_ctime = new_dir->i_mtime = |
2371 | ext4_current_time(new_dir); | 2377 | ext4_current_time(new_dir); |
2372 | ext4_mark_inode_dirty(handle, new_dir); | 2378 | ext4_mark_inode_dirty(handle, new_dir); |
2373 | BUFFER_TRACE(new_bh, "call ext4_journal_dirty_metadata"); | 2379 | BUFFER_TRACE(new_bh, "call ext4_handle_dirty_metadata"); |
2374 | ext4_journal_dirty_metadata(handle, new_bh); | 2380 | ext4_handle_dirty_metadata(handle, new_dir, new_bh); |
2375 | brelse(new_bh); | 2381 | brelse(new_bh); |
2376 | new_bh = NULL; | 2382 | new_bh = NULL; |
2377 | } | 2383 | } |
@@ -2421,8 +2427,8 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
2421 | BUFFER_TRACE(dir_bh, "get_write_access"); | 2427 | BUFFER_TRACE(dir_bh, "get_write_access"); |
2422 | ext4_journal_get_write_access(handle, dir_bh); | 2428 | ext4_journal_get_write_access(handle, dir_bh); |
2423 | PARENT_INO(dir_bh->b_data) = cpu_to_le32(new_dir->i_ino); | 2429 | PARENT_INO(dir_bh->b_data) = cpu_to_le32(new_dir->i_ino); |
2424 | BUFFER_TRACE(dir_bh, "call ext4_journal_dirty_metadata"); | 2430 | BUFFER_TRACE(dir_bh, "call ext4_handle_dirty_metadata"); |
2425 | ext4_journal_dirty_metadata(handle, dir_bh); | 2431 | ext4_handle_dirty_metadata(handle, old_dir, dir_bh); |
2426 | ext4_dec_count(handle, old_dir); | 2432 | ext4_dec_count(handle, old_dir); |
2427 | if (new_inode) { | 2433 | if (new_inode) { |
2428 | /* checked empty_dir above, can't have another parent, | 2434 | /* checked empty_dir above, can't have another parent, |