diff options
Diffstat (limited to 'fs/ext3')
-rw-r--r-- | fs/ext3/Kconfig | 67 | ||||
-rw-r--r-- | fs/ext3/balloc.c | 3 | ||||
-rw-r--r-- | fs/ext3/dir.c | 30 | ||||
-rw-r--r-- | fs/ext3/inode.c | 7 | ||||
-rw-r--r-- | fs/ext3/resize.c | 3 | ||||
-rw-r--r-- | fs/ext3/super.c | 16 |
6 files changed, 116 insertions, 10 deletions
diff --git a/fs/ext3/Kconfig b/fs/ext3/Kconfig new file mode 100644 index 000000000000..8e0cfe44b0fc --- /dev/null +++ b/fs/ext3/Kconfig | |||
@@ -0,0 +1,67 @@ | |||
1 | config EXT3_FS | ||
2 | tristate "Ext3 journalling file system support" | ||
3 | select JBD | ||
4 | help | ||
5 | This is the journalling version of the Second extended file system | ||
6 | (often called ext3), the de facto standard Linux file system | ||
7 | (method to organize files on a storage device) for hard disks. | ||
8 | |||
9 | The journalling code included in this driver means you do not have | ||
10 | to run e2fsck (file system checker) on your file systems after a | ||
11 | crash. The journal keeps track of any changes that were being made | ||
12 | at the time the system crashed, and can ensure that your file system | ||
13 | is consistent without the need for a lengthy check. | ||
14 | |||
15 | Other than adding the journal to the file system, the on-disk format | ||
16 | of ext3 is identical to ext2. It is possible to freely switch | ||
17 | between using the ext3 driver and the ext2 driver, as long as the | ||
18 | file system has been cleanly unmounted, or e2fsck is run on the file | ||
19 | system. | ||
20 | |||
21 | To add a journal on an existing ext2 file system or change the | ||
22 | behavior of ext3 file systems, you can use the tune2fs utility ("man | ||
23 | tune2fs"). To modify attributes of files and directories on ext3 | ||
24 | file systems, use chattr ("man chattr"). You need to be using | ||
25 | e2fsprogs version 1.20 or later in order to create ext3 journals | ||
26 | (available at <http://sourceforge.net/projects/e2fsprogs/>). | ||
27 | |||
28 | To compile this file system support as a module, choose M here: the | ||
29 | module will be called ext3. | ||
30 | |||
31 | config EXT3_FS_XATTR | ||
32 | bool "Ext3 extended attributes" | ||
33 | depends on EXT3_FS | ||
34 | default y | ||
35 | help | ||
36 | Extended attributes are name:value pairs associated with inodes by | ||
37 | the kernel or by users (see the attr(5) manual page, or visit | ||
38 | <http://acl.bestbits.at/> for details). | ||
39 | |||
40 | If unsure, say N. | ||
41 | |||
42 | You need this for POSIX ACL support on ext3. | ||
43 | |||
44 | config EXT3_FS_POSIX_ACL | ||
45 | bool "Ext3 POSIX Access Control Lists" | ||
46 | depends on EXT3_FS_XATTR | ||
47 | select FS_POSIX_ACL | ||
48 | help | ||
49 | Posix Access Control Lists (ACLs) support permissions for users and | ||
50 | groups beyond the owner/group/world scheme. | ||
51 | |||
52 | To learn more about Access Control Lists, visit the Posix ACLs for | ||
53 | Linux website <http://acl.bestbits.at/>. | ||
54 | |||
55 | If you don't know what Access Control Lists are, say N | ||
56 | |||
57 | config EXT3_FS_SECURITY | ||
58 | bool "Ext3 Security Labels" | ||
59 | depends on EXT3_FS_XATTR | ||
60 | help | ||
61 | Security labels support alternative access control models | ||
62 | implemented by security modules like SELinux. This option | ||
63 | enables an extended attribute handler for file security | ||
64 | labels in the ext3 filesystem. | ||
65 | |||
66 | If you are not using a security module that requires using | ||
67 | extended attributes for file security labels, say N. | ||
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index 92fd0338a6eb..f5b57a2ca35a 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c | |||
@@ -1547,6 +1547,7 @@ retry_alloc: | |||
1547 | * turn off reservation for this allocation | 1547 | * turn off reservation for this allocation |
1548 | */ | 1548 | */ |
1549 | if (my_rsv && (free_blocks < windowsz) | 1549 | if (my_rsv && (free_blocks < windowsz) |
1550 | && (free_blocks > 0) | ||
1550 | && (rsv_is_empty(&my_rsv->rsv_window))) | 1551 | && (rsv_is_empty(&my_rsv->rsv_window))) |
1551 | my_rsv = NULL; | 1552 | my_rsv = NULL; |
1552 | 1553 | ||
@@ -1585,7 +1586,7 @@ retry_alloc: | |||
1585 | * free blocks is less than half of the reservation | 1586 | * free blocks is less than half of the reservation |
1586 | * window size. | 1587 | * window size. |
1587 | */ | 1588 | */ |
1588 | if (free_blocks <= (windowsz/2)) | 1589 | if (my_rsv && (free_blocks <= (windowsz/2))) |
1589 | continue; | 1590 | continue; |
1590 | 1591 | ||
1591 | brelse(bitmap_bh); | 1592 | brelse(bitmap_bh); |
diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c index 2eea96ec78ed..4c82531ea0a8 100644 --- a/fs/ext3/dir.c +++ b/fs/ext3/dir.c | |||
@@ -102,6 +102,7 @@ static int ext3_readdir(struct file * filp, | |||
102 | int err; | 102 | int err; |
103 | struct inode *inode = filp->f_path.dentry->d_inode; | 103 | struct inode *inode = filp->f_path.dentry->d_inode; |
104 | int ret = 0; | 104 | int ret = 0; |
105 | int dir_has_error = 0; | ||
105 | 106 | ||
106 | sb = inode->i_sb; | 107 | sb = inode->i_sb; |
107 | 108 | ||
@@ -148,9 +149,12 @@ static int ext3_readdir(struct file * filp, | |||
148 | * of recovering data when there's a bad sector | 149 | * of recovering data when there's a bad sector |
149 | */ | 150 | */ |
150 | if (!bh) { | 151 | if (!bh) { |
151 | ext3_error (sb, "ext3_readdir", | 152 | if (!dir_has_error) { |
152 | "directory #%lu contains a hole at offset %lu", | 153 | ext3_error(sb, __func__, "directory #%lu " |
153 | inode->i_ino, (unsigned long)filp->f_pos); | 154 | "contains a hole at offset %lld", |
155 | inode->i_ino, filp->f_pos); | ||
156 | dir_has_error = 1; | ||
157 | } | ||
154 | /* corrupt size? Maybe no more blocks to read */ | 158 | /* corrupt size? Maybe no more blocks to read */ |
155 | if (filp->f_pos > inode->i_blocks << 9) | 159 | if (filp->f_pos > inode->i_blocks << 9) |
156 | break; | 160 | break; |
@@ -410,7 +414,7 @@ static int call_filldir(struct file * filp, void * dirent, | |||
410 | get_dtype(sb, fname->file_type)); | 414 | get_dtype(sb, fname->file_type)); |
411 | if (error) { | 415 | if (error) { |
412 | filp->f_pos = curr_pos; | 416 | filp->f_pos = curr_pos; |
413 | info->extra_fname = fname->next; | 417 | info->extra_fname = fname; |
414 | return error; | 418 | return error; |
415 | } | 419 | } |
416 | fname = fname->next; | 420 | fname = fname->next; |
@@ -449,11 +453,21 @@ static int ext3_dx_readdir(struct file * filp, | |||
449 | * If there are any leftover names on the hash collision | 453 | * If there are any leftover names on the hash collision |
450 | * chain, return them first. | 454 | * chain, return them first. |
451 | */ | 455 | */ |
452 | if (info->extra_fname && | 456 | if (info->extra_fname) { |
453 | call_filldir(filp, dirent, filldir, info->extra_fname)) | 457 | if (call_filldir(filp, dirent, filldir, info->extra_fname)) |
454 | goto finished; | 458 | goto finished; |
455 | 459 | ||
456 | if (!info->curr_node) | 460 | info->extra_fname = NULL; |
461 | info->curr_node = rb_next(info->curr_node); | ||
462 | if (!info->curr_node) { | ||
463 | if (info->next_hash == ~0) { | ||
464 | filp->f_pos = EXT3_HTREE_EOF; | ||
465 | goto finished; | ||
466 | } | ||
467 | info->curr_hash = info->next_hash; | ||
468 | info->curr_minor_hash = 0; | ||
469 | } | ||
470 | } else if (!info->curr_node) | ||
457 | info->curr_node = rb_first(&info->root); | 471 | info->curr_node = rb_first(&info->root); |
458 | 472 | ||
459 | while (1) { | 473 | while (1) { |
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index ebfec4d0148e..f8424ad89971 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c | |||
@@ -1186,6 +1186,13 @@ write_begin_failed: | |||
1186 | ext3_journal_stop(handle); | 1186 | ext3_journal_stop(handle); |
1187 | unlock_page(page); | 1187 | unlock_page(page); |
1188 | page_cache_release(page); | 1188 | page_cache_release(page); |
1189 | /* | ||
1190 | * block_write_begin may have instantiated a few blocks | ||
1191 | * outside i_size. Trim these off again. Don't need | ||
1192 | * i_size_read because we hold i_mutex. | ||
1193 | */ | ||
1194 | if (pos + len > inode->i_size) | ||
1195 | vmtruncate(inode, inode->i_size); | ||
1189 | } | 1196 | } |
1190 | if (ret == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries)) | 1197 | if (ret == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries)) |
1191 | goto retry; | 1198 | goto retry; |
diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c index 77278e947e94..78fdf3836370 100644 --- a/fs/ext3/resize.c +++ b/fs/ext3/resize.c | |||
@@ -790,7 +790,8 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input) | |||
790 | 790 | ||
791 | if (reserved_gdb || gdb_off == 0) { | 791 | if (reserved_gdb || gdb_off == 0) { |
792 | if (!EXT3_HAS_COMPAT_FEATURE(sb, | 792 | if (!EXT3_HAS_COMPAT_FEATURE(sb, |
793 | EXT3_FEATURE_COMPAT_RESIZE_INODE)){ | 793 | EXT3_FEATURE_COMPAT_RESIZE_INODE) |
794 | || !le16_to_cpu(es->s_reserved_gdt_blocks)) { | ||
794 | ext3_warning(sb, __func__, | 795 | ext3_warning(sb, __func__, |
795 | "No reserved GDT blocks, can't resize"); | 796 | "No reserved GDT blocks, can't resize"); |
796 | return -EPERM; | 797 | return -EPERM; |
diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 399a96a6c556..3a260af5544d 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c | |||
@@ -625,6 +625,9 @@ static int ext3_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
625 | else if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_WRITEBACK_DATA) | 625 | else if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_WRITEBACK_DATA) |
626 | seq_puts(seq, ",data=writeback"); | 626 | seq_puts(seq, ",data=writeback"); |
627 | 627 | ||
628 | if (test_opt(sb, DATA_ERR_ABORT)) | ||
629 | seq_puts(seq, ",data_err=abort"); | ||
630 | |||
628 | ext3_show_quota_options(seq, sb); | 631 | ext3_show_quota_options(seq, sb); |
629 | 632 | ||
630 | return 0; | 633 | return 0; |
@@ -754,6 +757,7 @@ enum { | |||
754 | Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh, Opt_bh, | 757 | Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh, Opt_bh, |
755 | Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev, | 758 | Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev, |
756 | Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, | 759 | Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, |
760 | Opt_data_err_abort, Opt_data_err_ignore, | ||
757 | Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, | 761 | Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, |
758 | Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota, | 762 | Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota, |
759 | Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota, | 763 | Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota, |
@@ -796,6 +800,8 @@ static const match_table_t tokens = { | |||
796 | {Opt_data_journal, "data=journal"}, | 800 | {Opt_data_journal, "data=journal"}, |
797 | {Opt_data_ordered, "data=ordered"}, | 801 | {Opt_data_ordered, "data=ordered"}, |
798 | {Opt_data_writeback, "data=writeback"}, | 802 | {Opt_data_writeback, "data=writeback"}, |
803 | {Opt_data_err_abort, "data_err=abort"}, | ||
804 | {Opt_data_err_ignore, "data_err=ignore"}, | ||
799 | {Opt_offusrjquota, "usrjquota="}, | 805 | {Opt_offusrjquota, "usrjquota="}, |
800 | {Opt_usrjquota, "usrjquota=%s"}, | 806 | {Opt_usrjquota, "usrjquota=%s"}, |
801 | {Opt_offgrpjquota, "grpjquota="}, | 807 | {Opt_offgrpjquota, "grpjquota="}, |
@@ -1011,6 +1017,12 @@ static int parse_options (char *options, struct super_block *sb, | |||
1011 | sbi->s_mount_opt |= data_opt; | 1017 | sbi->s_mount_opt |= data_opt; |
1012 | } | 1018 | } |
1013 | break; | 1019 | break; |
1020 | case Opt_data_err_abort: | ||
1021 | set_opt(sbi->s_mount_opt, DATA_ERR_ABORT); | ||
1022 | break; | ||
1023 | case Opt_data_err_ignore: | ||
1024 | clear_opt(sbi->s_mount_opt, DATA_ERR_ABORT); | ||
1025 | break; | ||
1014 | #ifdef CONFIG_QUOTA | 1026 | #ifdef CONFIG_QUOTA |
1015 | case Opt_usrjquota: | 1027 | case Opt_usrjquota: |
1016 | qtype = USRQUOTA; | 1028 | qtype = USRQUOTA; |
@@ -1986,6 +1998,10 @@ static void ext3_init_journal_params(struct super_block *sb, journal_t *journal) | |||
1986 | journal->j_flags |= JFS_BARRIER; | 1998 | journal->j_flags |= JFS_BARRIER; |
1987 | else | 1999 | else |
1988 | journal->j_flags &= ~JFS_BARRIER; | 2000 | journal->j_flags &= ~JFS_BARRIER; |
2001 | if (test_opt(sb, DATA_ERR_ABORT)) | ||
2002 | journal->j_flags |= JFS_ABORT_ON_SYNCDATA_ERR; | ||
2003 | else | ||
2004 | journal->j_flags &= ~JFS_ABORT_ON_SYNCDATA_ERR; | ||
1989 | spin_unlock(&journal->j_state_lock); | 2005 | spin_unlock(&journal->j_state_lock); |
1990 | } | 2006 | } |
1991 | 2007 | ||