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 | /* |
