diff options
-rw-r--r-- | fs/nfs/super.c | 203 |
1 files changed, 128 insertions, 75 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 4bbdbf6de417..47cf83e917be 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -92,8 +92,8 @@ enum { | |||
92 | Opt_sec, Opt_proto, Opt_mountproto, Opt_mounthost, | 92 | Opt_sec, Opt_proto, Opt_mountproto, Opt_mounthost, |
93 | Opt_addr, Opt_mountaddr, Opt_clientaddr, | 93 | Opt_addr, Opt_mountaddr, Opt_clientaddr, |
94 | 94 | ||
95 | /* Mount options that are ignored */ | 95 | /* Special mount options */ |
96 | Opt_userspace, Opt_deprecated, | 96 | Opt_userspace, Opt_deprecated, Opt_sloppy, |
97 | 97 | ||
98 | Opt_err | 98 | Opt_err |
99 | }; | 99 | }; |
@@ -103,6 +103,8 @@ static match_table_t nfs_mount_option_tokens = { | |||
103 | { Opt_userspace, "fg" }, | 103 | { Opt_userspace, "fg" }, |
104 | { Opt_userspace, "retry=%s" }, | 104 | { Opt_userspace, "retry=%s" }, |
105 | 105 | ||
106 | { Opt_sloppy, "sloppy" }, | ||
107 | |||
106 | { Opt_soft, "soft" }, | 108 | { Opt_soft, "soft" }, |
107 | { Opt_hard, "hard" }, | 109 | { Opt_hard, "hard" }, |
108 | { Opt_deprecated, "intr" }, | 110 | { Opt_deprecated, "intr" }, |
@@ -917,15 +919,22 @@ static int nfs_parse_security_flavors(char *value, | |||
917 | return 1; | 919 | return 1; |
918 | } | 920 | } |
919 | 921 | ||
922 | static void nfs_parse_invalid_value(const char *option) | ||
923 | { | ||
924 | dfprintk(MOUNT, "NFS: bad value specified for %s option\n", option); | ||
925 | } | ||
926 | |||
920 | /* | 927 | /* |
921 | * Error-check and convert a string of mount options from user space into | 928 | * Error-check and convert a string of mount options from user space into |
922 | * a data structure | 929 | * a data structure. The whole mount string is processed; bad options are |
930 | * skipped as they are encountered. If there were no errors, return 1; | ||
931 | * otherwise return 0 (zero). | ||
923 | */ | 932 | */ |
924 | static int nfs_parse_mount_options(char *raw, | 933 | static int nfs_parse_mount_options(char *raw, |
925 | struct nfs_parsed_mount_data *mnt) | 934 | struct nfs_parsed_mount_data *mnt) |
926 | { | 935 | { |
927 | char *p, *string, *secdata; | 936 | char *p, *string, *secdata; |
928 | int rc; | 937 | int rc, sloppy = 0, errors = 0; |
929 | 938 | ||
930 | if (!raw) { | 939 | if (!raw) { |
931 | dfprintk(MOUNT, "NFS: mount options string was NULL.\n"); | 940 | dfprintk(MOUNT, "NFS: mount options string was NULL.\n"); |
@@ -958,6 +967,10 @@ static int nfs_parse_mount_options(char *raw, | |||
958 | 967 | ||
959 | token = match_token(p, nfs_mount_option_tokens, args); | 968 | token = match_token(p, nfs_mount_option_tokens, args); |
960 | switch (token) { | 969 | switch (token) { |
970 | |||
971 | /* | ||
972 | * boolean options: foo/nofoo | ||
973 | */ | ||
961 | case Opt_soft: | 974 | case Opt_soft: |
962 | mnt->flags |= NFS_MOUNT_SOFT; | 975 | mnt->flags |= NFS_MOUNT_SOFT; |
963 | break; | 976 | break; |
@@ -1025,103 +1038,145 @@ static int nfs_parse_mount_options(char *raw, | |||
1025 | mnt->flags |= NFS_MOUNT_UNSHARED; | 1038 | mnt->flags |= NFS_MOUNT_UNSHARED; |
1026 | break; | 1039 | break; |
1027 | 1040 | ||
1041 | /* | ||
1042 | * options that take numeric values | ||
1043 | */ | ||
1028 | case Opt_port: | 1044 | case Opt_port: |
1029 | if (match_int(args, &option)) | 1045 | if (match_int(args, &option) || |
1030 | return 0; | 1046 | option < 0 || option > USHORT_MAX) { |
1031 | if (option < 0 || option > 65535) | 1047 | errors++; |
1032 | return 0; | 1048 | nfs_parse_invalid_value("port"); |
1033 | mnt->nfs_server.port = option; | 1049 | } else |
1050 | mnt->nfs_server.port = option; | ||
1034 | break; | 1051 | break; |
1035 | case Opt_rsize: | 1052 | case Opt_rsize: |
1036 | if (match_int(args, &mnt->rsize)) | 1053 | if (match_int(args, &option) || option < 0) { |
1037 | return 0; | 1054 | errors++; |
1055 | nfs_parse_invalid_value("rsize"); | ||
1056 | } else | ||
1057 | mnt->rsize = option; | ||
1038 | break; | 1058 | break; |
1039 | case Opt_wsize: | 1059 | case Opt_wsize: |
1040 | if (match_int(args, &mnt->wsize)) | 1060 | if (match_int(args, &option) || option < 0) { |
1041 | return 0; | 1061 | errors++; |
1062 | nfs_parse_invalid_value("wsize"); | ||
1063 | } else | ||
1064 | mnt->wsize = option; | ||
1042 | break; | 1065 | break; |
1043 | case Opt_bsize: | 1066 | case Opt_bsize: |
1044 | if (match_int(args, &option)) | 1067 | if (match_int(args, &option) || option < 0) { |
1045 | return 0; | 1068 | errors++; |
1046 | if (option < 0) | 1069 | nfs_parse_invalid_value("bsize"); |
1047 | return 0; | 1070 | } else |
1048 | mnt->bsize = option; | 1071 | mnt->bsize = option; |
1049 | break; | 1072 | break; |
1050 | case Opt_timeo: | 1073 | case Opt_timeo: |
1051 | if (match_int(args, &mnt->timeo)) | 1074 | if (match_int(args, &option) || option <= 0) { |
1052 | return 0; | 1075 | errors++; |
1076 | nfs_parse_invalid_value("timeo"); | ||
1077 | } else | ||
1078 | mnt->timeo = option; | ||
1053 | break; | 1079 | break; |
1054 | case Opt_retrans: | 1080 | case Opt_retrans: |
1055 | if (match_int(args, &mnt->retrans)) | 1081 | if (match_int(args, &option) || option <= 0) { |
1056 | return 0; | 1082 | errors++; |
1083 | nfs_parse_invalid_value("retrans"); | ||
1084 | } else | ||
1085 | mnt->retrans = option; | ||
1057 | break; | 1086 | break; |
1058 | case Opt_acregmin: | 1087 | case Opt_acregmin: |
1059 | if (match_int(args, &mnt->acregmin)) | 1088 | if (match_int(args, &option) || option < 0) { |
1060 | return 0; | 1089 | errors++; |
1090 | nfs_parse_invalid_value("acregmin"); | ||
1091 | } else | ||
1092 | mnt->acregmin = option; | ||
1061 | break; | 1093 | break; |
1062 | case Opt_acregmax: | 1094 | case Opt_acregmax: |
1063 | if (match_int(args, &mnt->acregmax)) | 1095 | if (match_int(args, &option) || option < 0) { |
1064 | return 0; | 1096 | errors++; |
1097 | nfs_parse_invalid_value("acregmax"); | ||
1098 | } else | ||
1099 | mnt->acregmax = option; | ||
1065 | break; | 1100 | break; |
1066 | case Opt_acdirmin: | 1101 | case Opt_acdirmin: |
1067 | if (match_int(args, &mnt->acdirmin)) | 1102 | if (match_int(args, &option) || option < 0) { |
1068 | return 0; | 1103 | errors++; |
1104 | nfs_parse_invalid_value("acdirmin"); | ||
1105 | } else | ||
1106 | mnt->acdirmin = option; | ||
1069 | break; | 1107 | break; |
1070 | case Opt_acdirmax: | 1108 | case Opt_acdirmax: |
1071 | if (match_int(args, &mnt->acdirmax)) | 1109 | if (match_int(args, &option) || option < 0) { |
1072 | return 0; | 1110 | errors++; |
1111 | nfs_parse_invalid_value("acdirmax"); | ||
1112 | } else | ||
1113 | mnt->acdirmax = option; | ||
1073 | break; | 1114 | break; |
1074 | case Opt_actimeo: | 1115 | case Opt_actimeo: |
1075 | if (match_int(args, &option)) | 1116 | if (match_int(args, &option) || option < 0) { |
1076 | return 0; | 1117 | errors++; |
1077 | if (option < 0) | 1118 | nfs_parse_invalid_value("actimeo"); |
1078 | return 0; | 1119 | } else |
1079 | mnt->acregmin = | 1120 | mnt->acregmin = mnt->acregmax = |
1080 | mnt->acregmax = | 1121 | mnt->acdirmin = mnt->acdirmax = option; |
1081 | mnt->acdirmin = | ||
1082 | mnt->acdirmax = option; | ||
1083 | break; | 1122 | break; |
1084 | case Opt_namelen: | 1123 | case Opt_namelen: |
1085 | if (match_int(args, &mnt->namlen)) | 1124 | if (match_int(args, &option) || option < 0) { |
1086 | return 0; | 1125 | errors++; |
1126 | nfs_parse_invalid_value("namlen"); | ||
1127 | } else | ||
1128 | mnt->namlen = option; | ||
1087 | break; | 1129 | break; |
1088 | case Opt_mountport: | 1130 | case Opt_mountport: |
1089 | if (match_int(args, &option)) | 1131 | if (match_int(args, &option) || |
1090 | return 0; | 1132 | option < 0 || option > USHORT_MAX) { |
1091 | if (option < 0 || option > 65535) | 1133 | errors++; |
1092 | return 0; | 1134 | nfs_parse_invalid_value("mountport"); |
1093 | mnt->mount_server.port = option; | 1135 | } else |
1136 | mnt->mount_server.port = option; | ||
1094 | break; | 1137 | break; |
1095 | case Opt_mountvers: | 1138 | case Opt_mountvers: |
1096 | if (match_int(args, &option)) | 1139 | if (match_int(args, &option) || |
1097 | return 0; | 1140 | option < NFS_MNT_VERSION || |
1098 | if (option < 0) | 1141 | option > NFS_MNT3_VERSION) { |
1099 | return 0; | 1142 | errors++; |
1100 | mnt->mount_server.version = option; | 1143 | nfs_parse_invalid_value("mountvers"); |
1144 | } else | ||
1145 | mnt->mount_server.version = option; | ||
1101 | break; | 1146 | break; |
1102 | case Opt_nfsvers: | 1147 | case Opt_nfsvers: |
1103 | if (match_int(args, &option)) | 1148 | if (match_int(args, &option)) { |
1104 | return 0; | 1149 | errors++; |
1150 | nfs_parse_invalid_value("nfsvers"); | ||
1151 | break; | ||
1152 | } | ||
1105 | switch (option) { | 1153 | switch (option) { |
1106 | case 2: | 1154 | case NFS2_VERSION: |
1107 | mnt->flags &= ~NFS_MOUNT_VER3; | 1155 | mnt->flags &= ~NFS_MOUNT_VER3; |
1108 | break; | 1156 | break; |
1109 | case 3: | 1157 | case NFS3_VERSION: |
1110 | mnt->flags |= NFS_MOUNT_VER3; | 1158 | mnt->flags |= NFS_MOUNT_VER3; |
1111 | break; | 1159 | break; |
1112 | default: | 1160 | default: |
1113 | goto out_unrec_vers; | 1161 | errors++; |
1162 | nfs_parse_invalid_value("nfsvers"); | ||
1114 | } | 1163 | } |
1115 | break; | 1164 | break; |
1116 | 1165 | ||
1166 | /* | ||
1167 | * options that take text values | ||
1168 | */ | ||
1117 | case Opt_sec: | 1169 | case Opt_sec: |
1118 | string = match_strdup(args); | 1170 | string = match_strdup(args); |
1119 | if (string == NULL) | 1171 | if (string == NULL) |
1120 | goto out_nomem; | 1172 | goto out_nomem; |
1121 | rc = nfs_parse_security_flavors(string, mnt); | 1173 | rc = nfs_parse_security_flavors(string, mnt); |
1122 | kfree(string); | 1174 | kfree(string); |
1123 | if (!rc) | 1175 | if (!rc) { |
1124 | goto out_unrec_sec; | 1176 | errors++; |
1177 | dfprintk(MOUNT, "NFS: unrecognized " | ||
1178 | "security flavor\n"); | ||
1179 | } | ||
1125 | break; | 1180 | break; |
1126 | case Opt_proto: | 1181 | case Opt_proto: |
1127 | string = match_strdup(args); | 1182 | string = match_strdup(args); |
@@ -1146,7 +1201,9 @@ static int nfs_parse_mount_options(char *raw, | |||
1146 | mnt->nfs_server.protocol = XPRT_TRANSPORT_RDMA; | 1201 | mnt->nfs_server.protocol = XPRT_TRANSPORT_RDMA; |
1147 | break; | 1202 | break; |
1148 | default: | 1203 | default: |
1149 | goto out_unrec_xprt; | 1204 | errors++; |
1205 | dfprintk(MOUNT, "NFS: unrecognized " | ||
1206 | "transport protocol\n"); | ||
1150 | } | 1207 | } |
1151 | break; | 1208 | break; |
1152 | case Opt_mountproto: | 1209 | case Opt_mountproto: |
@@ -1166,7 +1223,9 @@ static int nfs_parse_mount_options(char *raw, | |||
1166 | break; | 1223 | break; |
1167 | case Opt_xprt_rdma: /* not used for side protocols */ | 1224 | case Opt_xprt_rdma: /* not used for side protocols */ |
1168 | default: | 1225 | default: |
1169 | goto out_unrec_xprt; | 1226 | errors++; |
1227 | dfprintk(MOUNT, "NFS: unrecognized " | ||
1228 | "transport protocol\n"); | ||
1170 | } | 1229 | } |
1171 | break; | 1230 | break; |
1172 | case Opt_addr: | 1231 | case Opt_addr: |
@@ -1204,6 +1263,13 @@ static int nfs_parse_mount_options(char *raw, | |||
1204 | kfree(string); | 1263 | kfree(string); |
1205 | break; | 1264 | break; |
1206 | 1265 | ||
1266 | /* | ||
1267 | * Special options | ||
1268 | */ | ||
1269 | case Opt_sloppy: | ||
1270 | sloppy = 1; | ||
1271 | dfprintk(MOUNT, "NFS: relaxing parsing rules\n"); | ||
1272 | break; | ||
1207 | case Opt_userspace: | 1273 | case Opt_userspace: |
1208 | case Opt_deprecated: | 1274 | case Opt_deprecated: |
1209 | dfprintk(MOUNT, "NFS: ignoring mount option " | 1275 | dfprintk(MOUNT, "NFS: ignoring mount option " |
@@ -1211,7 +1277,9 @@ static int nfs_parse_mount_options(char *raw, | |||
1211 | break; | 1277 | break; |
1212 | 1278 | ||
1213 | default: | 1279 | default: |
1214 | goto out_unknown; | 1280 | errors++; |
1281 | dfprintk(MOUNT, "NFS: unrecognized mount option " | ||
1282 | "'%s'\n", p); | ||
1215 | } | 1283 | } |
1216 | } | 1284 | } |
1217 | 1285 | ||
@@ -1224,21 +1292,6 @@ out_security_failure: | |||
1224 | free_secdata(secdata); | 1292 | free_secdata(secdata); |
1225 | printk(KERN_INFO "NFS: security options invalid: %d\n", rc); | 1293 | printk(KERN_INFO "NFS: security options invalid: %d\n", rc); |
1226 | return 0; | 1294 | return 0; |
1227 | out_unrec_vers: | ||
1228 | printk(KERN_INFO "NFS: unrecognized NFS version number\n"); | ||
1229 | return 0; | ||
1230 | |||
1231 | out_unrec_xprt: | ||
1232 | printk(KERN_INFO "NFS: unrecognized transport protocol\n"); | ||
1233 | return 0; | ||
1234 | |||
1235 | out_unrec_sec: | ||
1236 | printk(KERN_INFO "NFS: unrecognized security flavor\n"); | ||
1237 | return 0; | ||
1238 | |||
1239 | out_unknown: | ||
1240 | printk(KERN_INFO "NFS: unknown mount option: %s\n", p); | ||
1241 | return 0; | ||
1242 | } | 1295 | } |
1243 | 1296 | ||
1244 | /* | 1297 | /* |