aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/super.c')
-rw-r--r--fs/nfs/super.c295
1 files changed, 177 insertions, 118 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 26127b69a275..3d460527daab 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -90,6 +90,7 @@ enum {
90 Opt_mountport, 90 Opt_mountport,
91 Opt_mountvers, 91 Opt_mountvers,
92 Opt_nfsvers, 92 Opt_nfsvers,
93 Opt_minorversion,
93 94
94 /* Mount options that take string arguments */ 95 /* Mount options that take string arguments */
95 Opt_sec, Opt_proto, Opt_mountproto, Opt_mounthost, 96 Opt_sec, Opt_proto, Opt_mountproto, Opt_mounthost,
@@ -139,22 +140,23 @@ static const match_table_t nfs_mount_option_tokens = {
139 { Opt_fscache_uniq, "fsc=%s" }, 140 { Opt_fscache_uniq, "fsc=%s" },
140 { Opt_nofscache, "nofsc" }, 141 { Opt_nofscache, "nofsc" },
141 142
142 { Opt_port, "port=%u" }, 143 { Opt_port, "port=%s" },
143 { Opt_rsize, "rsize=%u" }, 144 { Opt_rsize, "rsize=%s" },
144 { Opt_wsize, "wsize=%u" }, 145 { Opt_wsize, "wsize=%s" },
145 { Opt_bsize, "bsize=%u" }, 146 { Opt_bsize, "bsize=%s" },
146 { Opt_timeo, "timeo=%u" }, 147 { Opt_timeo, "timeo=%s" },
147 { Opt_retrans, "retrans=%u" }, 148 { Opt_retrans, "retrans=%s" },
148 { Opt_acregmin, "acregmin=%u" }, 149 { Opt_acregmin, "acregmin=%s" },
149 { Opt_acregmax, "acregmax=%u" }, 150 { Opt_acregmax, "acregmax=%s" },
150 { Opt_acdirmin, "acdirmin=%u" }, 151 { Opt_acdirmin, "acdirmin=%s" },
151 { Opt_acdirmax, "acdirmax=%u" }, 152 { Opt_acdirmax, "acdirmax=%s" },
152 { Opt_actimeo, "actimeo=%u" }, 153 { Opt_actimeo, "actimeo=%s" },
153 { Opt_namelen, "namlen=%u" }, 154 { Opt_namelen, "namlen=%s" },
154 { Opt_mountport, "mountport=%u" }, 155 { Opt_mountport, "mountport=%s" },
155 { Opt_mountvers, "mountvers=%u" }, 156 { Opt_mountvers, "mountvers=%s" },
156 { Opt_nfsvers, "nfsvers=%u" }, 157 { Opt_nfsvers, "nfsvers=%s" },
157 { Opt_nfsvers, "vers=%u" }, 158 { Opt_nfsvers, "vers=%s" },
159 { Opt_minorversion, "minorversion=%u" },
158 160
159 { Opt_sec, "sec=%s" }, 161 { Opt_sec, "sec=%s" },
160 { Opt_proto, "proto=%s" }, 162 { Opt_proto, "proto=%s" },
@@ -514,7 +516,6 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
514 const char *nostr; 516 const char *nostr;
515 } nfs_info[] = { 517 } nfs_info[] = {
516 { NFS_MOUNT_SOFT, ",soft", ",hard" }, 518 { NFS_MOUNT_SOFT, ",soft", ",hard" },
517 { NFS_MOUNT_INTR, ",intr", ",nointr" },
518 { NFS_MOUNT_POSIX, ",posix", "" }, 519 { NFS_MOUNT_POSIX, ",posix", "" },
519 { NFS_MOUNT_NOCTO, ",nocto", "" }, 520 { NFS_MOUNT_NOCTO, ",nocto", "" },
520 { NFS_MOUNT_NOAC, ",noac", "" }, 521 { NFS_MOUNT_NOAC, ",noac", "" },
@@ -943,11 +944,6 @@ static int nfs_parse_security_flavors(char *value,
943 return 1; 944 return 1;
944} 945}
945 946
946static void nfs_parse_invalid_value(const char *option)
947{
948 dfprintk(MOUNT, "NFS: bad value specified for %s option\n", option);
949}
950
951/* 947/*
952 * Error-check and convert a string of mount options from user space into 948 * Error-check and convert a string of mount options from user space into
953 * a data structure. The whole mount string is processed; bad options are 949 * a data structure. The whole mount string is processed; bad options are
@@ -958,7 +954,7 @@ static int nfs_parse_mount_options(char *raw,
958 struct nfs_parsed_mount_data *mnt) 954 struct nfs_parsed_mount_data *mnt)
959{ 955{
960 char *p, *string, *secdata; 956 char *p, *string, *secdata;
961 int rc, sloppy = 0, errors = 0; 957 int rc, sloppy = 0, invalid_option = 0;
962 958
963 if (!raw) { 959 if (!raw) {
964 dfprintk(MOUNT, "NFS: mount options string was NULL.\n"); 960 dfprintk(MOUNT, "NFS: mount options string was NULL.\n");
@@ -982,7 +978,9 @@ static int nfs_parse_mount_options(char *raw,
982 978
983 while ((p = strsep(&raw, ",")) != NULL) { 979 while ((p = strsep(&raw, ",")) != NULL) {
984 substring_t args[MAX_OPT_ARGS]; 980 substring_t args[MAX_OPT_ARGS];
985 int option, token; 981 unsigned long option;
982 int int_option;
983 int token;
986 984
987 if (!*p) 985 if (!*p)
988 continue; 986 continue;
@@ -1091,114 +1089,156 @@ static int nfs_parse_mount_options(char *raw,
1091 * options that take numeric values 1089 * options that take numeric values
1092 */ 1090 */
1093 case Opt_port: 1091 case Opt_port:
1094 if (match_int(args, &option) || 1092 string = match_strdup(args);
1095 option < 0 || option > USHORT_MAX) { 1093 if (string == NULL)
1096 errors++; 1094 goto out_nomem;
1097 nfs_parse_invalid_value("port"); 1095 rc = strict_strtoul(string, 10, &option);
1098 } else 1096 kfree(string);
1099 mnt->nfs_server.port = option; 1097 if (rc != 0 || option > USHORT_MAX)
1098 goto out_invalid_value;
1099 mnt->nfs_server.port = option;
1100 break; 1100 break;
1101 case Opt_rsize: 1101 case Opt_rsize:
1102 if (match_int(args, &option) || option < 0) { 1102 string = match_strdup(args);
1103 errors++; 1103 if (string == NULL)
1104 nfs_parse_invalid_value("rsize"); 1104 goto out_nomem;
1105 } else 1105 rc = strict_strtoul(string, 10, &option);
1106 mnt->rsize = option; 1106 kfree(string);
1107 if (rc != 0)
1108 goto out_invalid_value;
1109 mnt->rsize = option;
1107 break; 1110 break;
1108 case Opt_wsize: 1111 case Opt_wsize:
1109 if (match_int(args, &option) || option < 0) { 1112 string = match_strdup(args);
1110 errors++; 1113 if (string == NULL)
1111 nfs_parse_invalid_value("wsize"); 1114 goto out_nomem;
1112 } else 1115 rc = strict_strtoul(string, 10, &option);
1113 mnt->wsize = option; 1116 kfree(string);
1117 if (rc != 0)
1118 goto out_invalid_value;
1119 mnt->wsize = option;
1114 break; 1120 break;
1115 case Opt_bsize: 1121 case Opt_bsize:
1116 if (match_int(args, &option) || option < 0) { 1122 string = match_strdup(args);
1117 errors++; 1123 if (string == NULL)
1118 nfs_parse_invalid_value("bsize"); 1124 goto out_nomem;
1119 } else 1125 rc = strict_strtoul(string, 10, &option);
1120 mnt->bsize = option; 1126 kfree(string);
1127 if (rc != 0)
1128 goto out_invalid_value;
1129 mnt->bsize = option;
1121 break; 1130 break;
1122 case Opt_timeo: 1131 case Opt_timeo:
1123 if (match_int(args, &option) || option <= 0) { 1132 string = match_strdup(args);
1124 errors++; 1133 if (string == NULL)
1125 nfs_parse_invalid_value("timeo"); 1134 goto out_nomem;
1126 } else 1135 rc = strict_strtoul(string, 10, &option);
1127 mnt->timeo = option; 1136 kfree(string);
1137 if (rc != 0 || option == 0)
1138 goto out_invalid_value;
1139 mnt->timeo = option;
1128 break; 1140 break;
1129 case Opt_retrans: 1141 case Opt_retrans:
1130 if (match_int(args, &option) || option <= 0) { 1142 string = match_strdup(args);
1131 errors++; 1143 if (string == NULL)
1132 nfs_parse_invalid_value("retrans"); 1144 goto out_nomem;
1133 } else 1145 rc = strict_strtoul(string, 10, &option);
1134 mnt->retrans = option; 1146 kfree(string);
1147 if (rc != 0 || option == 0)
1148 goto out_invalid_value;
1149 mnt->retrans = option;
1135 break; 1150 break;
1136 case Opt_acregmin: 1151 case Opt_acregmin:
1137 if (match_int(args, &option) || option < 0) { 1152 string = match_strdup(args);
1138 errors++; 1153 if (string == NULL)
1139 nfs_parse_invalid_value("acregmin"); 1154 goto out_nomem;
1140 } else 1155 rc = strict_strtoul(string, 10, &option);
1141 mnt->acregmin = option; 1156 kfree(string);
1157 if (rc != 0)
1158 goto out_invalid_value;
1159 mnt->acregmin = option;
1142 break; 1160 break;
1143 case Opt_acregmax: 1161 case Opt_acregmax:
1144 if (match_int(args, &option) || option < 0) { 1162 string = match_strdup(args);
1145 errors++; 1163 if (string == NULL)
1146 nfs_parse_invalid_value("acregmax"); 1164 goto out_nomem;
1147 } else 1165 rc = strict_strtoul(string, 10, &option);
1148 mnt->acregmax = option; 1166 kfree(string);
1167 if (rc != 0)
1168 goto out_invalid_value;
1169 mnt->acregmax = option;
1149 break; 1170 break;
1150 case Opt_acdirmin: 1171 case Opt_acdirmin:
1151 if (match_int(args, &option) || option < 0) { 1172 string = match_strdup(args);
1152 errors++; 1173 if (string == NULL)
1153 nfs_parse_invalid_value("acdirmin"); 1174 goto out_nomem;
1154 } else 1175 rc = strict_strtoul(string, 10, &option);
1155 mnt->acdirmin = option; 1176 kfree(string);
1177 if (rc != 0)
1178 goto out_invalid_value;
1179 mnt->acdirmin = option;
1156 break; 1180 break;
1157 case Opt_acdirmax: 1181 case Opt_acdirmax:
1158 if (match_int(args, &option) || option < 0) { 1182 string = match_strdup(args);
1159 errors++; 1183 if (string == NULL)
1160 nfs_parse_invalid_value("acdirmax"); 1184 goto out_nomem;
1161 } else 1185 rc = strict_strtoul(string, 10, &option);
1162 mnt->acdirmax = option; 1186 kfree(string);
1187 if (rc != 0)
1188 goto out_invalid_value;
1189 mnt->acdirmax = option;
1163 break; 1190 break;
1164 case Opt_actimeo: 1191 case Opt_actimeo:
1165 if (match_int(args, &option) || option < 0) { 1192 string = match_strdup(args);
1166 errors++; 1193 if (string == NULL)
1167 nfs_parse_invalid_value("actimeo"); 1194 goto out_nomem;
1168 } else 1195 rc = strict_strtoul(string, 10, &option);
1169 mnt->acregmin = mnt->acregmax = 1196 kfree(string);
1170 mnt->acdirmin = mnt->acdirmax = option; 1197 if (rc != 0)
1198 goto out_invalid_value;
1199 mnt->acregmin = mnt->acregmax =
1200 mnt->acdirmin = mnt->acdirmax = option;
1171 break; 1201 break;
1172 case Opt_namelen: 1202 case Opt_namelen:
1173 if (match_int(args, &option) || option < 0) { 1203 string = match_strdup(args);
1174 errors++; 1204 if (string == NULL)
1175 nfs_parse_invalid_value("namlen"); 1205 goto out_nomem;
1176 } else 1206 rc = strict_strtoul(string, 10, &option);
1177 mnt->namlen = option; 1207 kfree(string);
1208 if (rc != 0)
1209 goto out_invalid_value;
1210 mnt->namlen = option;
1178 break; 1211 break;
1179 case Opt_mountport: 1212 case Opt_mountport:
1180 if (match_int(args, &option) || 1213 string = match_strdup(args);
1181 option < 0 || option > USHORT_MAX) { 1214 if (string == NULL)
1182 errors++; 1215 goto out_nomem;
1183 nfs_parse_invalid_value("mountport"); 1216 rc = strict_strtoul(string, 10, &option);
1184 } else 1217 kfree(string);
1185 mnt->mount_server.port = option; 1218 if (rc != 0 || option > USHORT_MAX)
1219 goto out_invalid_value;
1220 mnt->mount_server.port = option;
1186 break; 1221 break;
1187 case Opt_mountvers: 1222 case Opt_mountvers:
1188 if (match_int(args, &option) || 1223 string = match_strdup(args);
1224 if (string == NULL)
1225 goto out_nomem;
1226 rc = strict_strtoul(string, 10, &option);
1227 kfree(string);
1228 if (rc != 0 ||
1189 option < NFS_MNT_VERSION || 1229 option < NFS_MNT_VERSION ||
1190 option > NFS_MNT3_VERSION) { 1230 option > NFS_MNT3_VERSION)
1191 errors++; 1231 goto out_invalid_value;
1192 nfs_parse_invalid_value("mountvers"); 1232 mnt->mount_server.version = option;
1193 } else
1194 mnt->mount_server.version = option;
1195 break; 1233 break;
1196 case Opt_nfsvers: 1234 case Opt_nfsvers:
1197 if (match_int(args, &option)) { 1235 string = match_strdup(args);
1198 errors++; 1236 if (string == NULL)
1199 nfs_parse_invalid_value("nfsvers"); 1237 goto out_nomem;
1200 break; 1238 rc = strict_strtoul(string, 10, &option);
1201 } 1239 kfree(string);
1240 if (rc != 0)
1241 goto out_invalid_value;
1202 switch (option) { 1242 switch (option) {
1203 case NFS2_VERSION: 1243 case NFS2_VERSION:
1204 mnt->flags &= ~NFS_MOUNT_VER3; 1244 mnt->flags &= ~NFS_MOUNT_VER3;
@@ -1207,10 +1247,16 @@ static int nfs_parse_mount_options(char *raw,
1207 mnt->flags |= NFS_MOUNT_VER3; 1247 mnt->flags |= NFS_MOUNT_VER3;
1208 break; 1248 break;
1209 default: 1249 default:
1210 errors++; 1250 goto out_invalid_value;
1211 nfs_parse_invalid_value("nfsvers");
1212 } 1251 }
1213 break; 1252 break;
1253 case Opt_minorversion:
1254 if (match_int(args, &int_option))
1255 return 0;
1256 if (int_option < 0 || int_option > NFS4_MAX_MINOR_VERSION)
1257 return 0;
1258 mnt->minorversion = int_option;
1259 break;
1214 1260
1215 /* 1261 /*
1216 * options that take text values 1262 * options that take text values
@@ -1222,9 +1268,9 @@ static int nfs_parse_mount_options(char *raw,
1222 rc = nfs_parse_security_flavors(string, mnt); 1268 rc = nfs_parse_security_flavors(string, mnt);
1223 kfree(string); 1269 kfree(string);
1224 if (!rc) { 1270 if (!rc) {
1225 errors++;
1226 dfprintk(MOUNT, "NFS: unrecognized " 1271 dfprintk(MOUNT, "NFS: unrecognized "
1227 "security flavor\n"); 1272 "security flavor\n");
1273 return 0;
1228 } 1274 }
1229 break; 1275 break;
1230 case Opt_proto: 1276 case Opt_proto:
@@ -1238,23 +1284,25 @@ static int nfs_parse_mount_options(char *raw,
1238 case Opt_xprt_udp: 1284 case Opt_xprt_udp:
1239 mnt->flags &= ~NFS_MOUNT_TCP; 1285 mnt->flags &= ~NFS_MOUNT_TCP;
1240 mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP; 1286 mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP;
1287 kfree(string);
1241 break; 1288 break;
1242 case Opt_xprt_tcp: 1289 case Opt_xprt_tcp:
1243 mnt->flags |= NFS_MOUNT_TCP; 1290 mnt->flags |= NFS_MOUNT_TCP;
1244 mnt->nfs_server.protocol = XPRT_TRANSPORT_TCP; 1291 mnt->nfs_server.protocol = XPRT_TRANSPORT_TCP;
1292 kfree(string);
1245 break; 1293 break;
1246 case Opt_xprt_rdma: 1294 case Opt_xprt_rdma:
1247 /* vector side protocols to TCP */ 1295 /* vector side protocols to TCP */
1248 mnt->flags |= NFS_MOUNT_TCP; 1296 mnt->flags |= NFS_MOUNT_TCP;
1249 mnt->nfs_server.protocol = XPRT_TRANSPORT_RDMA; 1297 mnt->nfs_server.protocol = XPRT_TRANSPORT_RDMA;
1250 xprt_load_transport(string); 1298 xprt_load_transport(string);
1299 kfree(string);
1251 break; 1300 break;
1252 default: 1301 default:
1253 errors++;
1254 dfprintk(MOUNT, "NFS: unrecognized " 1302 dfprintk(MOUNT, "NFS: unrecognized "
1255 "transport protocol\n"); 1303 "transport protocol\n");
1304 return 0;
1256 } 1305 }
1257 kfree(string);
1258 break; 1306 break;
1259 case Opt_mountproto: 1307 case Opt_mountproto:
1260 string = match_strdup(args); 1308 string = match_strdup(args);
@@ -1273,9 +1321,9 @@ static int nfs_parse_mount_options(char *raw,
1273 break; 1321 break;
1274 case Opt_xprt_rdma: /* not used for side protocols */ 1322 case Opt_xprt_rdma: /* not used for side protocols */
1275 default: 1323 default:
1276 errors++;
1277 dfprintk(MOUNT, "NFS: unrecognized " 1324 dfprintk(MOUNT, "NFS: unrecognized "
1278 "transport protocol\n"); 1325 "transport protocol\n");
1326 return 0;
1279 } 1327 }
1280 break; 1328 break;
1281 case Opt_addr: 1329 case Opt_addr:
@@ -1331,9 +1379,9 @@ static int nfs_parse_mount_options(char *raw,
1331 mnt->flags |= NFS_MOUNT_LOOKUP_CACHE_NONEG|NFS_MOUNT_LOOKUP_CACHE_NONE; 1379 mnt->flags |= NFS_MOUNT_LOOKUP_CACHE_NONEG|NFS_MOUNT_LOOKUP_CACHE_NONE;
1332 break; 1380 break;
1333 default: 1381 default:
1334 errors++;
1335 dfprintk(MOUNT, "NFS: invalid " 1382 dfprintk(MOUNT, "NFS: invalid "
1336 "lookupcache argument\n"); 1383 "lookupcache argument\n");
1384 return 0;
1337 }; 1385 };
1338 break; 1386 break;
1339 1387
@@ -1351,20 +1399,20 @@ static int nfs_parse_mount_options(char *raw,
1351 break; 1399 break;
1352 1400
1353 default: 1401 default:
1354 errors++; 1402 invalid_option = 1;
1355 dfprintk(MOUNT, "NFS: unrecognized mount option " 1403 dfprintk(MOUNT, "NFS: unrecognized mount option "
1356 "'%s'\n", p); 1404 "'%s'\n", p);
1357 } 1405 }
1358 } 1406 }
1359 1407
1360 if (errors > 0) { 1408 if (!sloppy && invalid_option)
1361 dfprintk(MOUNT, "NFS: parsing encountered %d error%s\n", 1409 return 0;
1362 errors, (errors == 1 ? "" : "s")); 1410
1363 if (!sloppy)
1364 return 0;
1365 }
1366 return 1; 1411 return 1;
1367 1412
1413out_invalid_value:
1414 printk(KERN_INFO "NFS: bad mount option value specified: %s \n", p);
1415 return 0;
1368out_nomem: 1416out_nomem:
1369 printk(KERN_INFO "NFS: not enough memory to parse option\n"); 1417 printk(KERN_INFO "NFS: not enough memory to parse option\n");
1370 return 0; 1418 return 0;
@@ -1381,6 +1429,7 @@ out_security_failure:
1381static int nfs_try_mount(struct nfs_parsed_mount_data *args, 1429static int nfs_try_mount(struct nfs_parsed_mount_data *args,
1382 struct nfs_fh *root_fh) 1430 struct nfs_fh *root_fh)
1383{ 1431{
1432 unsigned int auth_flavor_len = 0;
1384 struct nfs_mount_request request = { 1433 struct nfs_mount_request request = {
1385 .sap = (struct sockaddr *) 1434 .sap = (struct sockaddr *)
1386 &args->mount_server.address, 1435 &args->mount_server.address,
@@ -1388,6 +1437,7 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args,
1388 .protocol = args->mount_server.protocol, 1437 .protocol = args->mount_server.protocol,
1389 .fh = root_fh, 1438 .fh = root_fh,
1390 .noresvport = args->flags & NFS_MOUNT_NORESVPORT, 1439 .noresvport = args->flags & NFS_MOUNT_NORESVPORT,
1440 .auth_flav_len = &auth_flavor_len,
1391 }; 1441 };
1392 int status; 1442 int status;
1393 1443
@@ -2240,6 +2290,11 @@ static void nfs4_fill_super(struct super_block *sb)
2240 nfs_initialise_sb(sb); 2290 nfs_initialise_sb(sb);
2241} 2291}
2242 2292
2293static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *args)
2294{
2295 args->flags &= ~(NFS_MOUNT_NONLM|NFS_MOUNT_NOACL|NFS_MOUNT_VER3);
2296}
2297
2243/* 2298/*
2244 * Validate NFSv4 mount options 2299 * Validate NFSv4 mount options
2245 */ 2300 */
@@ -2263,6 +2318,7 @@ static int nfs4_validate_mount_data(void *options,
2263 args->nfs_server.port = NFS_PORT; /* 2049 unless user set port= */ 2318 args->nfs_server.port = NFS_PORT; /* 2049 unless user set port= */
2264 args->auth_flavors[0] = RPC_AUTH_UNIX; 2319 args->auth_flavors[0] = RPC_AUTH_UNIX;
2265 args->auth_flavor_len = 0; 2320 args->auth_flavor_len = 0;
2321 args->minorversion = 0;
2266 2322
2267 switch (data->version) { 2323 switch (data->version) {
2268 case 1: 2324 case 1:
@@ -2336,6 +2392,8 @@ static int nfs4_validate_mount_data(void *options,
2336 2392
2337 nfs_validate_transport_protocol(args); 2393 nfs_validate_transport_protocol(args);
2338 2394
2395 nfs4_validate_mount_flags(args);
2396
2339 if (args->auth_flavor_len > 1) 2397 if (args->auth_flavor_len > 1)
2340 goto out_inval_auth; 2398 goto out_inval_auth;
2341 2399
@@ -2477,12 +2535,13 @@ static void nfs4_kill_super(struct super_block *sb)
2477{ 2535{
2478 struct nfs_server *server = NFS_SB(sb); 2536 struct nfs_server *server = NFS_SB(sb);
2479 2537
2538 dprintk("--> %s\n", __func__);
2480 nfs_super_return_all_delegations(sb); 2539 nfs_super_return_all_delegations(sb);
2481 kill_anon_super(sb); 2540 kill_anon_super(sb);
2482
2483 nfs4_renewd_prepare_shutdown(server); 2541 nfs4_renewd_prepare_shutdown(server);
2484 nfs_fscache_release_super_cookie(sb); 2542 nfs_fscache_release_super_cookie(sb);
2485 nfs_free_server(server); 2543 nfs_free_server(server);
2544 dprintk("<-- %s\n", __func__);
2486} 2545}
2487 2546
2488/* 2547/*