From patchwork Mon Mar 5 03:08:23 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Theodore Ts'o X-Patchwork-Id: 144573 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 15A3EB7083 for ; Mon, 5 Mar 2012 14:08:35 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755237Ab2CEDIc (ORCPT ); Sun, 4 Mar 2012 22:08:32 -0500 Received: from li9-11.members.linode.com ([67.18.176.11]:41872 "EHLO test.thunk.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755010Ab2CEDI0 (ORCPT ); Sun, 4 Mar 2012 22:08:26 -0500 Received: from root (helo=tytso-glaptop.cam.corp.google.com) by test.thunk.org with local-esmtp (Exim 4.69) (envelope-from ) id 1S4OHh-0004uD-6Q; Mon, 05 Mar 2012 03:08:25 +0000 Received: from tytso by tytso-glaptop.cam.corp.google.com with local (Exim 4.71) (envelope-from ) id 1S4OHh-0001ZY-JT; Sun, 04 Mar 2012 22:08:25 -0500 From: Theodore Ts'o To: Ext4 Developers List Cc: Theodore Ts'o Subject: [PATCH 09/11] ext4: add debugging /proc file showing file system options Date: Sun, 4 Mar 2012 22:08:23 -0500 Message-Id: <1330916905-5976-9-git-send-email-tytso@mit.edu> X-Mailer: git-send-email 1.7.9.107.g97f9a In-Reply-To: <1330916905-5976-1-git-send-email-tytso@mit.edu> References: <1330916905-5976-1-git-send-email-tytso@mit.edu> X-SA-Exim-Connect-IP: X-SA-Exim-Mail-From: tytso@thunk.org X-SA-Exim-Scanned: No (on test.thunk.org); SAEximRunCond expanded to false Sender: linux-ext4-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org 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" --- 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 7082869..27d490d 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -847,6 +847,7 @@ static void ext4_put_super(struct super_block *sb) ext4_commit_super(sb, 1); } if (sbi->s_proc) { + remove_proc_entry("options", sbi->s_proc); remove_proc_entry(sb->s_id, ext4_proc_root); } kobject_del(&sbi->s_kobj); @@ -1683,16 +1684,17 @@ static const char *token2str(int token) * - it's set to a non-default value OR * - if the per-sb default is different from the global default */ -static int ext4_show_options(struct seq_file *seq, struct dentry *root) +static int _ext4_show_options(struct seq_file *seq, struct super_block *sb, + int nodefs) { - int def_errors; - struct super_block *sb = root->d_sb; struct ext4_sb_info *sbi = EXT4_SB(sb); struct ext4_super_block *es = sbi->s_es; + int def_errors, def_mount_opt = nodefs ? 0 : sbi->s_def_mount_opt; const struct mount_opts *m; + char sep = nodefs ? '\n' : ','; -#define SEQ_OPTS_PUTS(str) seq_printf(seq, "," str) -#define SEQ_OPTS_PRINT(str, arg) seq_printf(seq, "," str, arg) +#define SEQ_OPTS_PUTS(str) seq_printf(seq, "%c" str, sep) +#define SEQ_OPTS_PRINT(str, arg) seq_printf(seq, "%c" str, sep, arg) if (sbi->s_sb_block != 1) 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) if (((m->flags & (MOPT_SET|MOPT_CLEAR)) == 0) || (m->flags & MOPT_CLEAR_ERR)) continue; - if (!(m->mount_opt & (sbi->s_mount_opt ^ sbi->s_def_mount_opt))) + if (!(m->mount_opt & (sbi->s_mount_opt ^ def_mount_opt))) continue; /* skip if same as the default */ if ((want_set && (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) SEQ_OPTS_PRINT("%s", token2str(m->token)); } - if (sbi->s_resuid != EXT4_DEF_RESUID || + if (nodefs || sbi->s_resuid != EXT4_DEF_RESUID || le16_to_cpu(es->s_def_resuid) != EXT4_DEF_RESUID) SEQ_OPTS_PRINT("resuid=%u", sbi->s_resuid); - if (sbi->s_resgid != EXT4_DEF_RESGID || + if (nodefs || sbi->s_resgid != EXT4_DEF_RESGID || le16_to_cpu(es->s_def_resgid) != EXT4_DEF_RESGID) SEQ_OPTS_PRINT("resgid=%u", sbi->s_resgid); - def_errors = le16_to_cpu(es->s_errors); + def_errors = nodefs ? -1 : le16_to_cpu(es->s_errors); if (test_opt(sb, ERRORS_RO) && def_errors != EXT4_ERRORS_RO) SEQ_OPTS_PUTS("errors=remount-ro"); if (test_opt(sb, ERRORS_CONT) && def_errors != EXT4_ERRORS_CONTINUE) SEQ_OPTS_PUTS("errors=continue"); if (test_opt(sb, ERRORS_PANIC) && def_errors != EXT4_ERRORS_PANIC) SEQ_OPTS_PUTS("errors=panic"); - if (sbi->s_commit_interval != JBD2_DEFAULT_MAX_COMMIT_AGE*HZ) + if (nodefs || sbi->s_commit_interval != JBD2_DEFAULT_MAX_COMMIT_AGE*HZ) SEQ_OPTS_PRINT("commit=%lu", sbi->s_commit_interval / HZ); - if (sbi->s_min_batch_time != EXT4_DEF_MIN_BATCH_TIME) + if (nodefs || sbi->s_min_batch_time != EXT4_DEF_MIN_BATCH_TIME) SEQ_OPTS_PRINT("min_batch_time=%u", sbi->s_min_batch_time); - if (sbi->s_max_batch_time != EXT4_DEF_MAX_BATCH_TIME) + if (nodefs || sbi->s_max_batch_time != EXT4_DEF_MAX_BATCH_TIME) SEQ_OPTS_PRINT("max_batch_time=%u", sbi->s_max_batch_time); if (sb->s_flags & MS_I_VERSION) SEQ_OPTS_PUTS("i_version"); - if (sbi->s_stripe) + if (nodefs || sbi->s_stripe) SEQ_OPTS_PRINT("stripe=%lu", sbi->s_stripe); - if (EXT4_MOUNT_DATA_FLAGS & (sbi->s_mount_opt ^ sbi->s_def_mount_opt)) { + if (EXT4_MOUNT_DATA_FLAGS & (sbi->s_mount_opt ^ def_mount_opt)) { if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) SEQ_OPTS_PUTS("data=journal"); 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) else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA) SEQ_OPTS_PUTS("data=writeback"); } - if (sbi->s_inode_readahead_blks != EXT4_DEF_INODE_READAHEAD_BLKS) + if (nodefs || + sbi->s_inode_readahead_blks != EXT4_DEF_INODE_READAHEAD_BLKS) SEQ_OPTS_PRINT("inode_readahead_blks=%u", sbi->s_inode_readahead_blks); - if (test_opt(sb, INIT_INODE_TABLE) && - (sbi->s_li_wait_mult != EXT4_DEF_LI_WAIT_MULT)) + if (nodefs || (test_opt(sb, INIT_INODE_TABLE) && + (sbi->s_li_wait_mult != EXT4_DEF_LI_WAIT_MULT))) SEQ_OPTS_PRINT("init_itable=%u", sbi->s_li_wait_mult); ext4_show_quota_options(seq, sb); return 0; } +static int ext4_show_options(struct seq_file *seq, struct dentry *root) +{ + return _ext4_show_options(seq, root->d_sb, 0); +} + +static int options_seq_show(struct seq_file *seq, void *offset) +{ + struct super_block *sb = seq->private; + int rc; + + seq_puts(seq, (sb->s_flags & MS_RDONLY) ? "ro" : "rw"); + rc = _ext4_show_options(seq, sb, 1); + seq_puts(seq, "\n"); + return rc; +} + +static int options_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, options_seq_show, PDE(inode)->data); +} + +static const struct file_operations ext4_seq_options_fops = { + .owner = THIS_MODULE, + .open = options_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es, int read_only) { @@ -3350,6 +3382,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) if (ext4_proc_root) sbi->s_proc = proc_mkdir(sb->s_id, ext4_proc_root); + if (sbi->s_proc) + proc_create_data("options", S_IRUGO, sbi->s_proc, + &ext4_seq_options_fops, sb); + bgl_lock_init(sbi->s_blockgroup_lock); for (i = 0; i < db_count; i++) { @@ -3674,6 +3710,7 @@ failed_mount2: ext4_kvfree(sbi->s_group_desc); failed_mount: if (sbi->s_proc) { + remove_proc_entry("options", sbi->s_proc); remove_proc_entry(sb->s_id, ext4_proc_root); } #ifdef CONFIG_QUOTA