aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/super.c
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2012-03-04 20:21:38 -0500
committerTheodore Ts'o <tytso@mit.edu>2012-03-04 20:21:38 -0500
commit66acdcf4ea37f67e59a955509289e82e5f59a5d0 (patch)
tree6ded862dbcab3eadc75ccc256d15427044672cc1 /fs/ext4/super.c
parent5a916be1b31de9e833aa764de6faf27bb79f9b83 (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.c71
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 */
1686static int ext4_show_options(struct seq_file *seq, struct dentry *root) 1687static 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
1760static int ext4_show_options(struct seq_file *seq, struct dentry *root)
1761{
1762 return _ext4_show_options(seq, root->d_sb, 0);
1763}
1764
1765static 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
1776static int options_open_fs(struct inode *inode, struct file *file)
1777{
1778 return single_open(file, options_seq_show, PDE(inode)->data);
1779}
1780
1781static 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
1757static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es, 1789static 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);
3675failed_mount: 3711failed_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