diff options
| author | Mikulas Patocka <mikulas@twibright.com> | 2016-05-24 16:49:18 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-28 19:50:24 -0400 |
| commit | 037369b872940cd923835a0a589763180c4a36bc (patch) | |
| tree | 9a27a8603a270c3bd8464ffc520cb019593abdde | |
| parent | 01d6e08711bf90bc4d7ead14a93a0cbd73b1896a (diff) | |
hpfs: implement the show_options method
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>
Cc: stable@vger.kernel.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
| -rw-r--r-- | fs/hpfs/super.c | 43 |
1 files changed, 32 insertions, 11 deletions
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index 46ad0ef8b4cc..82067ca22f2b 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <linux/sched.h> | 15 | #include <linux/sched.h> |
| 16 | #include <linux/bitmap.h> | 16 | #include <linux/bitmap.h> |
| 17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
| 18 | #include <linux/seq_file.h> | ||
| 18 | 19 | ||
| 19 | /* Mark the filesystem dirty, so that chkdsk checks it when os/2 booted */ | 20 | /* Mark the filesystem dirty, so that chkdsk checks it when os/2 booted */ |
| 20 | 21 | ||
| @@ -453,10 +454,6 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data) | |||
| 453 | int lowercase, eas, chk, errs, chkdsk, timeshift; | 454 | int lowercase, eas, chk, errs, chkdsk, timeshift; |
| 454 | int o; | 455 | int o; |
| 455 | struct hpfs_sb_info *sbi = hpfs_sb(s); | 456 | struct hpfs_sb_info *sbi = hpfs_sb(s); |
| 456 | char *new_opts = kstrdup(data, GFP_KERNEL); | ||
| 457 | |||
| 458 | if (data && !new_opts) | ||
| 459 | return -ENOMEM; | ||
| 460 | 457 | ||
| 461 | sync_filesystem(s); | 458 | sync_filesystem(s); |
| 462 | 459 | ||
| @@ -493,18 +490,44 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data) | |||
| 493 | 490 | ||
| 494 | if (!(*flags & MS_RDONLY)) mark_dirty(s, 1); | 491 | if (!(*flags & MS_RDONLY)) mark_dirty(s, 1); |
| 495 | 492 | ||
| 496 | if (new_opts) | ||
| 497 | replace_mount_options(s, new_opts); | ||
| 498 | |||
| 499 | hpfs_unlock(s); | 493 | hpfs_unlock(s); |
| 500 | return 0; | 494 | return 0; |
| 501 | 495 | ||
| 502 | out_err: | 496 | out_err: |
| 503 | hpfs_unlock(s); | 497 | hpfs_unlock(s); |
| 504 | kfree(new_opts); | ||
| 505 | return -EINVAL; | 498 | return -EINVAL; |
| 506 | } | 499 | } |
| 507 | 500 | ||
| 501 | static int hpfs_show_options(struct seq_file *seq, struct dentry *root) | ||
| 502 | { | ||
| 503 | struct hpfs_sb_info *sbi = hpfs_sb(root->d_sb); | ||
| 504 | |||
| 505 | seq_printf(seq, ",uid=%u", from_kuid_munged(&init_user_ns, sbi->sb_uid)); | ||
| 506 | seq_printf(seq, ",gid=%u", from_kgid_munged(&init_user_ns, sbi->sb_gid)); | ||
| 507 | seq_printf(seq, ",umask=%03o", (~sbi->sb_mode & 0777)); | ||
| 508 | if (sbi->sb_lowercase) | ||
| 509 | seq_printf(seq, ",case=lower"); | ||
| 510 | if (!sbi->sb_chk) | ||
| 511 | seq_printf(seq, ",check=none"); | ||
| 512 | if (sbi->sb_chk == 2) | ||
| 513 | seq_printf(seq, ",check=strict"); | ||
| 514 | if (!sbi->sb_err) | ||
| 515 | seq_printf(seq, ",errors=continue"); | ||
| 516 | if (sbi->sb_err == 2) | ||
| 517 | seq_printf(seq, ",errors=panic"); | ||
| 518 | if (!sbi->sb_chkdsk) | ||
| 519 | seq_printf(seq, ",chkdsk=no"); | ||
| 520 | if (sbi->sb_chkdsk == 2) | ||
| 521 | seq_printf(seq, ",chkdsk=always"); | ||
| 522 | if (!sbi->sb_eas) | ||
| 523 | seq_printf(seq, ",eas=no"); | ||
| 524 | if (sbi->sb_eas == 1) | ||
| 525 | seq_printf(seq, ",eas=ro"); | ||
| 526 | if (sbi->sb_timeshift) | ||
| 527 | seq_printf(seq, ",timeshift=%d", sbi->sb_timeshift); | ||
| 528 | return 0; | ||
| 529 | } | ||
| 530 | |||
| 508 | /* Super operations */ | 531 | /* Super operations */ |
| 509 | 532 | ||
| 510 | static const struct super_operations hpfs_sops = | 533 | static const struct super_operations hpfs_sops = |
| @@ -515,7 +538,7 @@ static const struct super_operations hpfs_sops = | |||
| 515 | .put_super = hpfs_put_super, | 538 | .put_super = hpfs_put_super, |
| 516 | .statfs = hpfs_statfs, | 539 | .statfs = hpfs_statfs, |
| 517 | .remount_fs = hpfs_remount_fs, | 540 | .remount_fs = hpfs_remount_fs, |
| 518 | .show_options = generic_show_options, | 541 | .show_options = hpfs_show_options, |
| 519 | }; | 542 | }; |
| 520 | 543 | ||
| 521 | static int hpfs_fill_super(struct super_block *s, void *options, int silent) | 544 | static int hpfs_fill_super(struct super_block *s, void *options, int silent) |
| @@ -538,8 +561,6 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent) | |||
| 538 | 561 | ||
| 539 | int o; | 562 | int o; |
| 540 | 563 | ||
| 541 | save_mount_options(s, options); | ||
| 542 | |||
| 543 | sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); | 564 | sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); |
| 544 | if (!sbi) { | 565 | if (!sbi) { |
| 545 | return -ENOMEM; | 566 | return -ENOMEM; |
