diff options
Diffstat (limited to 'fs/nfs/super.c')
-rw-r--r-- | fs/nfs/super.c | 121 |
1 files changed, 57 insertions, 64 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 2fd28c4df1d4..36a595a63536 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -1041,15 +1041,31 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args, | |||
1041 | * XXX: as far as I can tell, changing the NFS program number is not | 1041 | * XXX: as far as I can tell, changing the NFS program number is not |
1042 | * supported in the NFS client. | 1042 | * supported in the NFS client. |
1043 | */ | 1043 | */ |
1044 | static int nfs_validate_mount_data(struct nfs_mount_data **options, | 1044 | static int nfs_validate_mount_data(void *options, |
1045 | struct nfs_parsed_mount_data *args, | ||
1045 | struct nfs_fh *mntfh, | 1046 | struct nfs_fh *mntfh, |
1046 | const char *dev_name) | 1047 | const char *dev_name) |
1047 | { | 1048 | { |
1048 | struct nfs_mount_data *data = *options; | 1049 | struct nfs_mount_data *data = (struct nfs_mount_data *)options; |
1049 | 1050 | ||
1050 | if (data == NULL) | 1051 | if (data == NULL) |
1051 | goto out_no_data; | 1052 | goto out_no_data; |
1052 | 1053 | ||
1054 | memset(args, 0, sizeof(*args)); | ||
1055 | args->flags = (NFS_MOUNT_VER3 | NFS_MOUNT_TCP); | ||
1056 | args->rsize = NFS_MAX_FILE_IO_SIZE; | ||
1057 | args->wsize = NFS_MAX_FILE_IO_SIZE; | ||
1058 | args->timeo = 600; | ||
1059 | args->retrans = 2; | ||
1060 | args->acregmin = 3; | ||
1061 | args->acregmax = 60; | ||
1062 | args->acdirmin = 30; | ||
1063 | args->acdirmax = 60; | ||
1064 | args->mount_server.protocol = IPPROTO_UDP; | ||
1065 | args->mount_server.program = NFS_MNT_PROGRAM; | ||
1066 | args->nfs_server.protocol = IPPROTO_TCP; | ||
1067 | args->nfs_server.program = NFS_PROGRAM; | ||
1068 | |||
1053 | switch (data->version) { | 1069 | switch (data->version) { |
1054 | case 1: | 1070 | case 1: |
1055 | data->namlen = 0; | 1071 | data->namlen = 0; |
@@ -1078,90 +1094,67 @@ static int nfs_validate_mount_data(struct nfs_mount_data **options, | |||
1078 | if (mntfh->size < sizeof(mntfh->data)) | 1094 | if (mntfh->size < sizeof(mntfh->data)) |
1079 | memset(mntfh->data + mntfh->size, 0, | 1095 | memset(mntfh->data + mntfh->size, 0, |
1080 | sizeof(mntfh->data) - mntfh->size); | 1096 | sizeof(mntfh->data) - mntfh->size); |
1097 | /* | ||
1098 | * Translate to nfs_parsed_mount_data, which nfs_fill_super | ||
1099 | * can deal with. | ||
1100 | */ | ||
1101 | args->flags = data->flags; | ||
1102 | args->rsize = data->rsize; | ||
1103 | args->wsize = data->wsize; | ||
1104 | args->flags = data->flags; | ||
1105 | args->timeo = data->timeo; | ||
1106 | args->retrans = data->retrans; | ||
1107 | args->acregmin = data->acregmin; | ||
1108 | args->acregmax = data->acregmax; | ||
1109 | args->acdirmin = data->acdirmin; | ||
1110 | args->acdirmax = data->acdirmax; | ||
1111 | args->nfs_server.address = data->addr; | ||
1112 | if (!(data->flags & NFS_MOUNT_TCP)) | ||
1113 | args->nfs_server.protocol = IPPROTO_UDP; | ||
1114 | /* N.B. caller will free nfs_server.hostname in all cases */ | ||
1115 | args->nfs_server.hostname = kstrdup(data->hostname, GFP_KERNEL); | ||
1116 | args->namlen = data->namlen; | ||
1117 | args->bsize = data->bsize; | ||
1118 | args->auth_flavors[0] = data->pseudoflavor; | ||
1081 | break; | 1119 | break; |
1082 | default: { | 1120 | default: { |
1083 | unsigned int len; | 1121 | unsigned int len; |
1084 | char *c; | 1122 | char *c; |
1085 | int status; | 1123 | int status; |
1086 | struct nfs_parsed_mount_data args = { | ||
1087 | .flags = (NFS_MOUNT_VER3 | NFS_MOUNT_TCP), | ||
1088 | .rsize = NFS_MAX_FILE_IO_SIZE, | ||
1089 | .wsize = NFS_MAX_FILE_IO_SIZE, | ||
1090 | .timeo = 600, | ||
1091 | .retrans = 2, | ||
1092 | .acregmin = 3, | ||
1093 | .acregmax = 60, | ||
1094 | .acdirmin = 30, | ||
1095 | .acdirmax = 60, | ||
1096 | .mount_server.protocol = IPPROTO_UDP, | ||
1097 | .mount_server.program = NFS_MNT_PROGRAM, | ||
1098 | .nfs_server.protocol = IPPROTO_TCP, | ||
1099 | .nfs_server.program = NFS_PROGRAM, | ||
1100 | }; | ||
1101 | 1124 | ||
1102 | if (nfs_parse_mount_options((char *) *options, &args) == 0) | 1125 | if (nfs_parse_mount_options((char *)options, args) == 0) |
1103 | return -EINVAL; | 1126 | return -EINVAL; |
1104 | 1127 | ||
1105 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
1106 | if (data == NULL) | ||
1107 | return -ENOMEM; | ||
1108 | |||
1109 | /* | ||
1110 | * NB: after this point, caller will free "data" | ||
1111 | * if we return an error | ||
1112 | */ | ||
1113 | *options = data; | ||
1114 | |||
1115 | c = strchr(dev_name, ':'); | 1128 | c = strchr(dev_name, ':'); |
1116 | if (c == NULL) | 1129 | if (c == NULL) |
1117 | return -EINVAL; | 1130 | return -EINVAL; |
1118 | len = c - dev_name; | 1131 | len = c - dev_name; |
1119 | if (len > sizeof(data->hostname)) | 1132 | /* N.B. caller will free nfs_server.hostname in all cases */ |
1120 | return -ENAMETOOLONG; | 1133 | args->nfs_server.hostname = kstrndup(dev_name, len, GFP_KERNEL); |
1121 | strncpy(data->hostname, dev_name, len); | ||
1122 | args.nfs_server.hostname = data->hostname; | ||
1123 | 1134 | ||
1124 | c++; | 1135 | c++; |
1125 | if (strlen(c) > NFS_MAXPATHLEN) | 1136 | if (strlen(c) > NFS_MAXPATHLEN) |
1126 | return -ENAMETOOLONG; | 1137 | return -ENAMETOOLONG; |
1127 | args.nfs_server.export_path = c; | 1138 | args->nfs_server.export_path = c; |
1128 | 1139 | ||
1129 | status = nfs_try_mount(&args, mntfh); | 1140 | status = nfs_try_mount(args, mntfh); |
1130 | if (status) | 1141 | if (status) |
1131 | return status; | 1142 | return status; |
1132 | 1143 | ||
1133 | /* | ||
1134 | * Translate to nfs_mount_data, which nfs_fill_super | ||
1135 | * can deal with. | ||
1136 | */ | ||
1137 | data->version = 6; | ||
1138 | data->flags = args.flags; | ||
1139 | data->rsize = args.rsize; | ||
1140 | data->wsize = args.wsize; | ||
1141 | data->timeo = args.timeo; | ||
1142 | data->retrans = args.retrans; | ||
1143 | data->acregmin = args.acregmin; | ||
1144 | data->acregmax = args.acregmax; | ||
1145 | data->acdirmin = args.acdirmin; | ||
1146 | data->acdirmax = args.acdirmax; | ||
1147 | data->addr = args.nfs_server.address; | ||
1148 | data->namlen = args.namlen; | ||
1149 | data->bsize = args.bsize; | ||
1150 | data->pseudoflavor = args.auth_flavors[0]; | ||
1151 | |||
1152 | break; | 1144 | break; |
1153 | } | 1145 | } |
1154 | } | 1146 | } |
1155 | 1147 | ||
1156 | if (!(data->flags & NFS_MOUNT_SECFLAVOUR)) | 1148 | if (!(args->flags & NFS_MOUNT_SECFLAVOUR)) |
1157 | data->pseudoflavor = RPC_AUTH_UNIX; | 1149 | args->auth_flavors[0] = RPC_AUTH_UNIX; |
1158 | 1150 | ||
1159 | #ifndef CONFIG_NFS_V3 | 1151 | #ifndef CONFIG_NFS_V3 |
1160 | if (data->flags & NFS_MOUNT_VER3) | 1152 | if (args->flags & NFS_MOUNT_VER3) |
1161 | goto out_v3_not_compiled; | 1153 | goto out_v3_not_compiled; |
1162 | #endif /* !CONFIG_NFS_V3 */ | 1154 | #endif /* !CONFIG_NFS_V3 */ |
1163 | 1155 | ||
1164 | if (!nfs_verify_server_address((struct sockaddr *) &data->addr)) | 1156 | if (!nfs_verify_server_address((struct sockaddr *) |
1157 | &args->nfs_server.address)) | ||
1165 | goto out_no_address; | 1158 | goto out_no_address; |
1166 | 1159 | ||
1167 | return 0; | 1160 | return 0; |
@@ -1220,7 +1213,8 @@ static inline void nfs_initialise_sb(struct super_block *sb) | |||
1220 | /* | 1213 | /* |
1221 | * Finish setting up an NFS2/3 superblock | 1214 | * Finish setting up an NFS2/3 superblock |
1222 | */ | 1215 | */ |
1223 | static void nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data) | 1216 | static void nfs_fill_super(struct super_block *sb, |
1217 | struct nfs_parsed_mount_data *data) | ||
1224 | { | 1218 | { |
1225 | struct nfs_server *server = NFS_SB(sb); | 1219 | struct nfs_server *server = NFS_SB(sb); |
1226 | 1220 | ||
@@ -1341,7 +1335,7 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
1341 | struct nfs_server *server = NULL; | 1335 | struct nfs_server *server = NULL; |
1342 | struct super_block *s; | 1336 | struct super_block *s; |
1343 | struct nfs_fh mntfh; | 1337 | struct nfs_fh mntfh; |
1344 | struct nfs_mount_data *data = raw_data; | 1338 | struct nfs_parsed_mount_data data; |
1345 | struct dentry *mntroot; | 1339 | struct dentry *mntroot; |
1346 | int (*compare_super)(struct super_block *, void *) = nfs_compare_super; | 1340 | int (*compare_super)(struct super_block *, void *) = nfs_compare_super; |
1347 | struct nfs_sb_mountdata sb_mntdata = { | 1341 | struct nfs_sb_mountdata sb_mntdata = { |
@@ -1350,12 +1344,12 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
1350 | int error; | 1344 | int error; |
1351 | 1345 | ||
1352 | /* Validate the mount data */ | 1346 | /* Validate the mount data */ |
1353 | error = nfs_validate_mount_data(&data, &mntfh, dev_name); | 1347 | error = nfs_validate_mount_data(raw_data, &data, &mntfh, dev_name); |
1354 | if (error < 0) | 1348 | if (error < 0) |
1355 | goto out; | 1349 | goto out; |
1356 | 1350 | ||
1357 | /* Get a volume representation */ | 1351 | /* Get a volume representation */ |
1358 | server = nfs_create_server(data, &mntfh); | 1352 | server = nfs_create_server(&data, &mntfh); |
1359 | if (IS_ERR(server)) { | 1353 | if (IS_ERR(server)) { |
1360 | error = PTR_ERR(server); | 1354 | error = PTR_ERR(server); |
1361 | goto out; | 1355 | goto out; |
@@ -1379,7 +1373,7 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
1379 | 1373 | ||
1380 | if (!s->s_root) { | 1374 | if (!s->s_root) { |
1381 | /* initial superblock/root creation */ | 1375 | /* initial superblock/root creation */ |
1382 | nfs_fill_super(s, data); | 1376 | nfs_fill_super(s, &data); |
1383 | } | 1377 | } |
1384 | 1378 | ||
1385 | mntroot = nfs_get_root(s, &mntfh); | 1379 | mntroot = nfs_get_root(s, &mntfh); |
@@ -1394,8 +1388,7 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
1394 | error = 0; | 1388 | error = 0; |
1395 | 1389 | ||
1396 | out: | 1390 | out: |
1397 | if (data != raw_data) | 1391 | kfree(data.nfs_server.hostname); |
1398 | kfree(data); | ||
1399 | return error; | 1392 | return error; |
1400 | 1393 | ||
1401 | out_err_nosb: | 1394 | out_err_nosb: |