diff options
author | Theodore Ts'o <tytso@mit.edu> | 2012-03-04 20:21:38 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2012-03-04 20:21:38 -0500 |
commit | 66acdcf4ea37f67e59a955509289e82e5f59a5d0 (patch) | |
tree | 6ded862dbcab3eadc75ccc256d15427044672cc1 /fs/ext4/super.c | |
parent | 5a916be1b31de9e833aa764de6faf27bb79f9b83 (diff) |
ext4: add debugging /proc file showing file system options
Now that /proc/mounts is consistently showing only those mount options
which need to be specified in /etc/fstab or on the mount command line,
it is useful to have file which shows exactly which file system
options are enabled. This can be useful when debugging a user
problem.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/super.c')
-rw-r--r-- | fs/ext4/super.c | 71 |
1 files changed, 54 insertions, 17 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 70828699fa89..27d490d6eb02 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -847,6 +847,7 @@ static void ext4_put_super(struct super_block *sb) | |||
847 | ext4_commit_super(sb, 1); | 847 | ext4_commit_super(sb, 1); |
848 | } | 848 | } |
849 | if (sbi->s_proc) { | 849 | if (sbi->s_proc) { |
850 | remove_proc_entry("options", sbi->s_proc); | ||
850 | remove_proc_entry(sb->s_id, ext4_proc_root); | 851 | remove_proc_entry(sb->s_id, ext4_proc_root); |
851 | } | 852 | } |
852 | kobject_del(&sbi->s_kobj); | 853 | kobject_del(&sbi->s_kobj); |
@@ -1683,16 +1684,17 @@ static const char *token2str(int token) | |||
1683 | * - it's set to a non-default value OR | 1684 | * - it's set to a non-default value OR |
1684 | * - if the per-sb default is different from the global default | 1685 | * - if the per-sb default is different from the global default |
1685 | */ | 1686 | */ |
1686 | static int ext4_show_options(struct seq_file *seq, struct dentry *root) | 1687 | static int _ext4_show_options(struct seq_file *seq, struct super_block *sb, |
1688 | int nodefs) | ||
1687 | { | 1689 | { |
1688 | int def_errors; | ||
1689 | struct super_block *sb = root->d_sb; | ||
1690 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 1690 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
1691 | struct ext4_super_block *es = sbi->s_es; | 1691 | struct ext4_super_block *es = sbi->s_es; |
1692 | int def_errors, def_mount_opt = nodefs ? 0 : sbi->s_def_mount_opt; | ||
1692 | const struct mount_opts *m; | 1693 | const struct mount_opts *m; |
1694 | char sep = nodefs ? '\n' : ','; | ||
1693 | 1695 | ||
1694 | #define SEQ_OPTS_PUTS(str) seq_printf(seq, "," str) | 1696 | #define SEQ_OPTS_PUTS(str) seq_printf(seq, "%c" str, sep) |
1695 | #define SEQ_OPTS_PRINT(str, arg) seq_printf(seq, "," str, arg) | 1697 | #define SEQ_OPTS_PRINT(str, arg) seq_printf(seq, "%c" str, sep, arg) |
1696 | 1698 | ||
1697 | if (sbi->s_sb_block != 1) | 1699 | if (sbi->s_sb_block != 1) |
1698 | SEQ_OPTS_PRINT("sb=%llu", sbi->s_sb_block); | 1700 | SEQ_OPTS_PRINT("sb=%llu", sbi->s_sb_block); |
@@ -1702,7 +1704,7 @@ static int ext4_show_options(struct seq_file *seq, struct dentry *root) | |||
1702 | if (((m->flags & (MOPT_SET|MOPT_CLEAR)) == 0) || | 1704 | if (((m->flags & (MOPT_SET|MOPT_CLEAR)) == 0) || |
1703 | (m->flags & MOPT_CLEAR_ERR)) | 1705 | (m->flags & MOPT_CLEAR_ERR)) |
1704 | continue; | 1706 | continue; |
1705 | if (!(m->mount_opt & (sbi->s_mount_opt ^ sbi->s_def_mount_opt))) | 1707 | if (!(m->mount_opt & (sbi->s_mount_opt ^ def_mount_opt))) |
1706 | continue; /* skip if same as the default */ | 1708 | continue; /* skip if same as the default */ |
1707 | if ((want_set && | 1709 | if ((want_set && |
1708 | (sbi->s_mount_opt & m->mount_opt) != m->mount_opt) || | 1710 | (sbi->s_mount_opt & m->mount_opt) != m->mount_opt) || |
@@ -1711,30 +1713,30 @@ static int ext4_show_options(struct seq_file *seq, struct dentry *root) | |||
1711 | SEQ_OPTS_PRINT("%s", token2str(m->token)); | 1713 | SEQ_OPTS_PRINT("%s", token2str(m->token)); |
1712 | } | 1714 | } |
1713 | 1715 | ||
1714 | if (sbi->s_resuid != EXT4_DEF_RESUID || | 1716 | if (nodefs || sbi->s_resuid != EXT4_DEF_RESUID || |
1715 | le16_to_cpu(es->s_def_resuid) != EXT4_DEF_RESUID) | 1717 | le16_to_cpu(es->s_def_resuid) != EXT4_DEF_RESUID) |
1716 | SEQ_OPTS_PRINT("resuid=%u", sbi->s_resuid); | 1718 | SEQ_OPTS_PRINT("resuid=%u", sbi->s_resuid); |
1717 | if (sbi->s_resgid != EXT4_DEF_RESGID || | 1719 | if (nodefs || sbi->s_resgid != EXT4_DEF_RESGID || |
1718 | le16_to_cpu(es->s_def_resgid) != EXT4_DEF_RESGID) | 1720 | le16_to_cpu(es->s_def_resgid) != EXT4_DEF_RESGID) |
1719 | SEQ_OPTS_PRINT("resgid=%u", sbi->s_resgid); | 1721 | SEQ_OPTS_PRINT("resgid=%u", sbi->s_resgid); |
1720 | def_errors = le16_to_cpu(es->s_errors); | 1722 | def_errors = nodefs ? -1 : le16_to_cpu(es->s_errors); |
1721 | if (test_opt(sb, ERRORS_RO) && def_errors != EXT4_ERRORS_RO) | 1723 | if (test_opt(sb, ERRORS_RO) && def_errors != EXT4_ERRORS_RO) |
1722 | SEQ_OPTS_PUTS("errors=remount-ro"); | 1724 | SEQ_OPTS_PUTS("errors=remount-ro"); |
1723 | if (test_opt(sb, ERRORS_CONT) && def_errors != EXT4_ERRORS_CONTINUE) | 1725 | if (test_opt(sb, ERRORS_CONT) && def_errors != EXT4_ERRORS_CONTINUE) |
1724 | SEQ_OPTS_PUTS("errors=continue"); | 1726 | SEQ_OPTS_PUTS("errors=continue"); |
1725 | if (test_opt(sb, ERRORS_PANIC) && def_errors != EXT4_ERRORS_PANIC) | 1727 | if (test_opt(sb, ERRORS_PANIC) && def_errors != EXT4_ERRORS_PANIC) |
1726 | SEQ_OPTS_PUTS("errors=panic"); | 1728 | SEQ_OPTS_PUTS("errors=panic"); |
1727 | if (sbi->s_commit_interval != JBD2_DEFAULT_MAX_COMMIT_AGE*HZ) | 1729 | if (nodefs || sbi->s_commit_interval != JBD2_DEFAULT_MAX_COMMIT_AGE*HZ) |
1728 | SEQ_OPTS_PRINT("commit=%lu", sbi->s_commit_interval / HZ); | 1730 | SEQ_OPTS_PRINT("commit=%lu", sbi->s_commit_interval / HZ); |
1729 | if (sbi->s_min_batch_time != EXT4_DEF_MIN_BATCH_TIME) | 1731 | if (nodefs || sbi->s_min_batch_time != EXT4_DEF_MIN_BATCH_TIME) |
1730 | SEQ_OPTS_PRINT("min_batch_time=%u", sbi->s_min_batch_time); | 1732 | SEQ_OPTS_PRINT("min_batch_time=%u", sbi->s_min_batch_time); |
1731 | if (sbi->s_max_batch_time != EXT4_DEF_MAX_BATCH_TIME) | 1733 | if (nodefs || sbi->s_max_batch_time != EXT4_DEF_MAX_BATCH_TIME) |
1732 | SEQ_OPTS_PRINT("max_batch_time=%u", sbi->s_max_batch_time); | 1734 | SEQ_OPTS_PRINT("max_batch_time=%u", sbi->s_max_batch_time); |
1733 | if (sb->s_flags & MS_I_VERSION) | 1735 | if (sb->s_flags & MS_I_VERSION) |
1734 | SEQ_OPTS_PUTS("i_version"); | 1736 | SEQ_OPTS_PUTS("i_version"); |
1735 | if (sbi->s_stripe) | 1737 | if (nodefs || sbi->s_stripe) |
1736 | SEQ_OPTS_PRINT("stripe=%lu", sbi->s_stripe); | 1738 | SEQ_OPTS_PRINT("stripe=%lu", sbi->s_stripe); |
1737 | if (EXT4_MOUNT_DATA_FLAGS & (sbi->s_mount_opt ^ sbi->s_def_mount_opt)) { | 1739 | if (EXT4_MOUNT_DATA_FLAGS & (sbi->s_mount_opt ^ def_mount_opt)) { |
1738 | if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) | 1740 | if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) |
1739 | SEQ_OPTS_PUTS("data=journal"); | 1741 | SEQ_OPTS_PUTS("data=journal"); |
1740 | else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA) | 1742 | else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA) |
@@ -1742,18 +1744,48 @@ static int ext4_show_options(struct seq_file *seq, struct dentry *root) | |||
1742 | else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA) | 1744 | else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA) |
1743 | SEQ_OPTS_PUTS("data=writeback"); | 1745 | SEQ_OPTS_PUTS("data=writeback"); |
1744 | } | 1746 | } |
1745 | if (sbi->s_inode_readahead_blks != EXT4_DEF_INODE_READAHEAD_BLKS) | 1747 | if (nodefs || |
1748 | sbi->s_inode_readahead_blks != EXT4_DEF_INODE_READAHEAD_BLKS) | ||
1746 | SEQ_OPTS_PRINT("inode_readahead_blks=%u", | 1749 | SEQ_OPTS_PRINT("inode_readahead_blks=%u", |
1747 | sbi->s_inode_readahead_blks); | 1750 | sbi->s_inode_readahead_blks); |
1748 | 1751 | ||
1749 | if (test_opt(sb, INIT_INODE_TABLE) && | 1752 | if (nodefs || (test_opt(sb, INIT_INODE_TABLE) && |
1750 | (sbi->s_li_wait_mult != EXT4_DEF_LI_WAIT_MULT)) | 1753 | (sbi->s_li_wait_mult != EXT4_DEF_LI_WAIT_MULT))) |
1751 | SEQ_OPTS_PRINT("init_itable=%u", sbi->s_li_wait_mult); | 1754 | SEQ_OPTS_PRINT("init_itable=%u", sbi->s_li_wait_mult); |
1752 | 1755 | ||
1753 | ext4_show_quota_options(seq, sb); | 1756 | ext4_show_quota_options(seq, sb); |
1754 | return 0; | 1757 | return 0; |
1755 | } | 1758 | } |
1756 | 1759 | ||
1760 | static int ext4_show_options(struct seq_file *seq, struct dentry *root) | ||
1761 | { | ||
1762 | return _ext4_show_options(seq, root->d_sb, 0); | ||
1763 | } | ||
1764 | |||
1765 | static int options_seq_show(struct seq_file *seq, void *offset) | ||
1766 | { | ||
1767 | struct super_block *sb = seq->private; | ||
1768 | int rc; | ||
1769 | |||
1770 | seq_puts(seq, (sb->s_flags & MS_RDONLY) ? "ro" : "rw"); | ||
1771 | rc = _ext4_show_options(seq, sb, 1); | ||
1772 | seq_puts(seq, "\n"); | ||
1773 | return rc; | ||
1774 | } | ||
1775 | |||
1776 | static int options_open_fs(struct inode *inode, struct file *file) | ||
1777 | { | ||
1778 | return single_open(file, options_seq_show, PDE(inode)->data); | ||
1779 | } | ||
1780 | |||
1781 | static const struct file_operations ext4_seq_options_fops = { | ||
1782 | .owner = THIS_MODULE, | ||
1783 | .open = options_open_fs, | ||
1784 | .read = seq_read, | ||
1785 | .llseek = seq_lseek, | ||
1786 | .release = single_release, | ||
1787 | }; | ||
1788 | |||
1757 | static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es, | 1789 | static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es, |
1758 | int read_only) | 1790 | int read_only) |
1759 | { | 1791 | { |
@@ -3350,6 +3382,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
3350 | if (ext4_proc_root) | 3382 | if (ext4_proc_root) |
3351 | sbi->s_proc = proc_mkdir(sb->s_id, ext4_proc_root); | 3383 | sbi->s_proc = proc_mkdir(sb->s_id, ext4_proc_root); |
3352 | 3384 | ||
3385 | if (sbi->s_proc) | ||
3386 | proc_create_data("options", S_IRUGO, sbi->s_proc, | ||
3387 | &ext4_seq_options_fops, sb); | ||
3388 | |||
3353 | bgl_lock_init(sbi->s_blockgroup_lock); | 3389 | bgl_lock_init(sbi->s_blockgroup_lock); |
3354 | 3390 | ||
3355 | for (i = 0; i < db_count; i++) { | 3391 | for (i = 0; i < db_count; i++) { |
@@ -3674,6 +3710,7 @@ failed_mount2: | |||
3674 | ext4_kvfree(sbi->s_group_desc); | 3710 | ext4_kvfree(sbi->s_group_desc); |
3675 | failed_mount: | 3711 | failed_mount: |
3676 | if (sbi->s_proc) { | 3712 | if (sbi->s_proc) { |
3713 | remove_proc_entry("options", sbi->s_proc); | ||
3677 | remove_proc_entry(sb->s_id, ext4_proc_root); | 3714 | remove_proc_entry(sb->s_id, ext4_proc_root); |
3678 | } | 3715 | } |
3679 | #ifdef CONFIG_QUOTA | 3716 | #ifdef CONFIG_QUOTA |