| From 037369b872940cd923835a0a589763180c4a36bc Mon Sep 17 00:00:00 2001 |
| From: Mikulas Patocka <mikulas@twibright.com> |
| Date: Tue, 24 May 2016 22:49:18 +0200 |
| Subject: hpfs: implement the show_options method |
| |
| From: Mikulas Patocka <mikulas@twibright.com> |
| |
| commit 037369b872940cd923835a0a589763180c4a36bc upstream. |
| |
| The HPFS filesystem used generic_show_options to produce string that is |
| displayed in /proc/mounts. However, there is a problem that the options |
| may disappear after remount. If we mount the filesystem with option1 |
| and then remount it with option2, /proc/mounts should show both option1 |
| and option2, however it only shows option2 because the whole option |
| string is replaced with replace_mount_options in hpfs_remount_fs. |
| |
| To fix this bug, implement the hpfs_show_options function that prints |
| options that are currently selected. |
| |
| Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/hpfs/super.c | 43 ++++++++++++++++++++++++++++++++----------- |
| 1 file changed, 32 insertions(+), 11 deletions(-) |
| |
| --- a/fs/hpfs/super.c |
| +++ b/fs/hpfs/super.c |
| @@ -15,6 +15,7 @@ |
| #include <linux/sched.h> |
| #include <linux/bitmap.h> |
| #include <linux/slab.h> |
| +#include <linux/seq_file.h> |
| |
| /* Mark the filesystem dirty, so that chkdsk checks it when os/2 booted */ |
| |
| @@ -453,10 +454,6 @@ static int hpfs_remount_fs(struct super_ |
| int lowercase, eas, chk, errs, chkdsk, timeshift; |
| int o; |
| struct hpfs_sb_info *sbi = hpfs_sb(s); |
| - char *new_opts = kstrdup(data, GFP_KERNEL); |
| - |
| - if (data && !new_opts) |
| - return -ENOMEM; |
| |
| sync_filesystem(s); |
| |
| @@ -493,18 +490,44 @@ static int hpfs_remount_fs(struct super_ |
| |
| if (!(*flags & MS_RDONLY)) mark_dirty(s, 1); |
| |
| - if (new_opts) |
| - replace_mount_options(s, new_opts); |
| - |
| hpfs_unlock(s); |
| return 0; |
| |
| out_err: |
| hpfs_unlock(s); |
| - kfree(new_opts); |
| return -EINVAL; |
| } |
| |
| +static int hpfs_show_options(struct seq_file *seq, struct dentry *root) |
| +{ |
| + struct hpfs_sb_info *sbi = hpfs_sb(root->d_sb); |
| + |
| + seq_printf(seq, ",uid=%u", from_kuid_munged(&init_user_ns, sbi->sb_uid)); |
| + seq_printf(seq, ",gid=%u", from_kgid_munged(&init_user_ns, sbi->sb_gid)); |
| + seq_printf(seq, ",umask=%03o", (~sbi->sb_mode & 0777)); |
| + if (sbi->sb_lowercase) |
| + seq_printf(seq, ",case=lower"); |
| + if (!sbi->sb_chk) |
| + seq_printf(seq, ",check=none"); |
| + if (sbi->sb_chk == 2) |
| + seq_printf(seq, ",check=strict"); |
| + if (!sbi->sb_err) |
| + seq_printf(seq, ",errors=continue"); |
| + if (sbi->sb_err == 2) |
| + seq_printf(seq, ",errors=panic"); |
| + if (!sbi->sb_chkdsk) |
| + seq_printf(seq, ",chkdsk=no"); |
| + if (sbi->sb_chkdsk == 2) |
| + seq_printf(seq, ",chkdsk=always"); |
| + if (!sbi->sb_eas) |
| + seq_printf(seq, ",eas=no"); |
| + if (sbi->sb_eas == 1) |
| + seq_printf(seq, ",eas=ro"); |
| + if (sbi->sb_timeshift) |
| + seq_printf(seq, ",timeshift=%d", sbi->sb_timeshift); |
| + return 0; |
| +} |
| + |
| /* Super operations */ |
| |
| static const struct super_operations hpfs_sops = |
| @@ -515,7 +538,7 @@ static const struct super_operations hpf |
| .put_super = hpfs_put_super, |
| .statfs = hpfs_statfs, |
| .remount_fs = hpfs_remount_fs, |
| - .show_options = generic_show_options, |
| + .show_options = hpfs_show_options, |
| }; |
| |
| static int hpfs_fill_super(struct super_block *s, void *options, int silent) |
| @@ -538,8 +561,6 @@ static int hpfs_fill_super(struct super_ |
| |
| int o; |
| |
| - save_mount_options(s, options); |
| - |
| sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); |
| if (!sbi) { |
| return -ENOMEM; |