diff options
Diffstat (limited to 'fs/fat/inode.c')
-rw-r--r-- | fs/fat/inode.c | 55 |
1 files changed, 40 insertions, 15 deletions
diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 5bafaad00530..35806813ea4e 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/writeback.h> | 26 | #include <linux/writeback.h> |
27 | #include <linux/log2.h> | 27 | #include <linux/log2.h> |
28 | #include <linux/hash.h> | 28 | #include <linux/hash.h> |
29 | #include <linux/blkdev.h> | ||
29 | #include <asm/unaligned.h> | 30 | #include <asm/unaligned.h> |
30 | #include "fat.h" | 31 | #include "fat.h" |
31 | 32 | ||
@@ -725,7 +726,8 @@ static int fat_show_options(struct seq_file *m, struct dentry *root) | |||
725 | if (opts->allow_utime) | 726 | if (opts->allow_utime) |
726 | seq_printf(m, ",allow_utime=%04o", opts->allow_utime); | 727 | seq_printf(m, ",allow_utime=%04o", opts->allow_utime); |
727 | if (sbi->nls_disk) | 728 | if (sbi->nls_disk) |
728 | seq_printf(m, ",codepage=%s", sbi->nls_disk->charset); | 729 | /* strip "cp" prefix from displayed option */ |
730 | seq_printf(m, ",codepage=%s", &sbi->nls_disk->charset[2]); | ||
729 | if (isvfat) { | 731 | if (isvfat) { |
730 | if (sbi->nls_io) | 732 | if (sbi->nls_io) |
731 | seq_printf(m, ",iocharset=%s", sbi->nls_io->charset); | 733 | seq_printf(m, ",iocharset=%s", sbi->nls_io->charset); |
@@ -777,8 +779,12 @@ static int fat_show_options(struct seq_file *m, struct dentry *root) | |||
777 | } | 779 | } |
778 | if (opts->flush) | 780 | if (opts->flush) |
779 | seq_puts(m, ",flush"); | 781 | seq_puts(m, ",flush"); |
780 | if (opts->tz_utc) | 782 | if (opts->tz_set) { |
781 | seq_puts(m, ",tz=UTC"); | 783 | if (opts->time_offset) |
784 | seq_printf(m, ",time_offset=%d", opts->time_offset); | ||
785 | else | ||
786 | seq_puts(m, ",tz=UTC"); | ||
787 | } | ||
782 | if (opts->errors == FAT_ERRORS_CONT) | 788 | if (opts->errors == FAT_ERRORS_CONT) |
783 | seq_puts(m, ",errors=continue"); | 789 | seq_puts(m, ",errors=continue"); |
784 | else if (opts->errors == FAT_ERRORS_PANIC) | 790 | else if (opts->errors == FAT_ERRORS_PANIC) |
@@ -800,7 +806,8 @@ enum { | |||
800 | Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes, | 806 | Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes, |
801 | Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes, | 807 | Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes, |
802 | Opt_obsolete, Opt_flush, Opt_tz_utc, Opt_rodir, Opt_err_cont, | 808 | Opt_obsolete, Opt_flush, Opt_tz_utc, Opt_rodir, Opt_err_cont, |
803 | Opt_err_panic, Opt_err_ro, Opt_discard, Opt_nfs, Opt_err, | 809 | Opt_err_panic, Opt_err_ro, Opt_discard, Opt_nfs, Opt_time_offset, |
810 | Opt_err, | ||
804 | }; | 811 | }; |
805 | 812 | ||
806 | static const match_table_t fat_tokens = { | 813 | static const match_table_t fat_tokens = { |
@@ -825,6 +832,7 @@ static const match_table_t fat_tokens = { | |||
825 | {Opt_immutable, "sys_immutable"}, | 832 | {Opt_immutable, "sys_immutable"}, |
826 | {Opt_flush, "flush"}, | 833 | {Opt_flush, "flush"}, |
827 | {Opt_tz_utc, "tz=UTC"}, | 834 | {Opt_tz_utc, "tz=UTC"}, |
835 | {Opt_time_offset, "time_offset=%d"}, | ||
828 | {Opt_err_cont, "errors=continue"}, | 836 | {Opt_err_cont, "errors=continue"}, |
829 | {Opt_err_panic, "errors=panic"}, | 837 | {Opt_err_panic, "errors=panic"}, |
830 | {Opt_err_ro, "errors=remount-ro"}, | 838 | {Opt_err_ro, "errors=remount-ro"}, |
@@ -909,7 +917,7 @@ static int parse_options(struct super_block *sb, char *options, int is_vfat, | |||
909 | opts->utf8 = opts->unicode_xlate = 0; | 917 | opts->utf8 = opts->unicode_xlate = 0; |
910 | opts->numtail = 1; | 918 | opts->numtail = 1; |
911 | opts->usefree = opts->nocase = 0; | 919 | opts->usefree = opts->nocase = 0; |
912 | opts->tz_utc = 0; | 920 | opts->tz_set = 0; |
913 | opts->nfs = 0; | 921 | opts->nfs = 0; |
914 | opts->errors = FAT_ERRORS_RO; | 922 | opts->errors = FAT_ERRORS_RO; |
915 | *debug = 0; | 923 | *debug = 0; |
@@ -965,48 +973,57 @@ static int parse_options(struct super_block *sb, char *options, int is_vfat, | |||
965 | break; | 973 | break; |
966 | case Opt_uid: | 974 | case Opt_uid: |
967 | if (match_int(&args[0], &option)) | 975 | if (match_int(&args[0], &option)) |
968 | return 0; | 976 | return -EINVAL; |
969 | opts->fs_uid = make_kuid(current_user_ns(), option); | 977 | opts->fs_uid = make_kuid(current_user_ns(), option); |
970 | if (!uid_valid(opts->fs_uid)) | 978 | if (!uid_valid(opts->fs_uid)) |
971 | return 0; | 979 | return -EINVAL; |
972 | break; | 980 | break; |
973 | case Opt_gid: | 981 | case Opt_gid: |
974 | if (match_int(&args[0], &option)) | 982 | if (match_int(&args[0], &option)) |
975 | return 0; | 983 | return -EINVAL; |
976 | opts->fs_gid = make_kgid(current_user_ns(), option); | 984 | opts->fs_gid = make_kgid(current_user_ns(), option); |
977 | if (!gid_valid(opts->fs_gid)) | 985 | if (!gid_valid(opts->fs_gid)) |
978 | return 0; | 986 | return -EINVAL; |
979 | break; | 987 | break; |
980 | case Opt_umask: | 988 | case Opt_umask: |
981 | if (match_octal(&args[0], &option)) | 989 | if (match_octal(&args[0], &option)) |
982 | return 0; | 990 | return -EINVAL; |
983 | opts->fs_fmask = opts->fs_dmask = option; | 991 | opts->fs_fmask = opts->fs_dmask = option; |
984 | break; | 992 | break; |
985 | case Opt_dmask: | 993 | case Opt_dmask: |
986 | if (match_octal(&args[0], &option)) | 994 | if (match_octal(&args[0], &option)) |
987 | return 0; | 995 | return -EINVAL; |
988 | opts->fs_dmask = option; | 996 | opts->fs_dmask = option; |
989 | break; | 997 | break; |
990 | case Opt_fmask: | 998 | case Opt_fmask: |
991 | if (match_octal(&args[0], &option)) | 999 | if (match_octal(&args[0], &option)) |
992 | return 0; | 1000 | return -EINVAL; |
993 | opts->fs_fmask = option; | 1001 | opts->fs_fmask = option; |
994 | break; | 1002 | break; |
995 | case Opt_allow_utime: | 1003 | case Opt_allow_utime: |
996 | if (match_octal(&args[0], &option)) | 1004 | if (match_octal(&args[0], &option)) |
997 | return 0; | 1005 | return -EINVAL; |
998 | opts->allow_utime = option & (S_IWGRP | S_IWOTH); | 1006 | opts->allow_utime = option & (S_IWGRP | S_IWOTH); |
999 | break; | 1007 | break; |
1000 | case Opt_codepage: | 1008 | case Opt_codepage: |
1001 | if (match_int(&args[0], &option)) | 1009 | if (match_int(&args[0], &option)) |
1002 | return 0; | 1010 | return -EINVAL; |
1003 | opts->codepage = option; | 1011 | opts->codepage = option; |
1004 | break; | 1012 | break; |
1005 | case Opt_flush: | 1013 | case Opt_flush: |
1006 | opts->flush = 1; | 1014 | opts->flush = 1; |
1007 | break; | 1015 | break; |
1016 | case Opt_time_offset: | ||
1017 | if (match_int(&args[0], &option)) | ||
1018 | return -EINVAL; | ||
1019 | if (option < -12 * 60 || option > 12 * 60) | ||
1020 | return -EINVAL; | ||
1021 | opts->tz_set = 1; | ||
1022 | opts->time_offset = option; | ||
1023 | break; | ||
1008 | case Opt_tz_utc: | 1024 | case Opt_tz_utc: |
1009 | opts->tz_utc = 1; | 1025 | opts->tz_set = 1; |
1026 | opts->time_offset = 0; | ||
1010 | break; | 1027 | break; |
1011 | case Opt_err_cont: | 1028 | case Opt_err_cont: |
1012 | opts->errors = FAT_ERRORS_CONT; | 1029 | opts->errors = FAT_ERRORS_CONT; |
@@ -1431,6 +1448,14 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, | |||
1431 | goto out_fail; | 1448 | goto out_fail; |
1432 | } | 1449 | } |
1433 | 1450 | ||
1451 | if (sbi->options.discard) { | ||
1452 | struct request_queue *q = bdev_get_queue(sb->s_bdev); | ||
1453 | if (!blk_queue_discard(q)) | ||
1454 | fat_msg(sb, KERN_WARNING, | ||
1455 | "mounting with \"discard\" option, but " | ||
1456 | "the device does not support discard"); | ||
1457 | } | ||
1458 | |||
1434 | return 0; | 1459 | return 0; |
1435 | 1460 | ||
1436 | out_invalid: | 1461 | out_invalid: |