diff options
Diffstat (limited to 'fs/nfs/super.c')
-rw-r--r-- | fs/nfs/super.c | 478 |
1 files changed, 176 insertions, 302 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index b68c8607770f..2b8e9a5e366a 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -263,8 +263,11 @@ static match_table_t nfs_local_lock_tokens = { | |||
263 | static void nfs_umount_begin(struct super_block *); | 263 | static void nfs_umount_begin(struct super_block *); |
264 | static int nfs_statfs(struct dentry *, struct kstatfs *); | 264 | static int nfs_statfs(struct dentry *, struct kstatfs *); |
265 | static int nfs_show_options(struct seq_file *, struct vfsmount *); | 265 | static int nfs_show_options(struct seq_file *, struct vfsmount *); |
266 | static int nfs_show_devname(struct seq_file *, struct vfsmount *); | ||
267 | static int nfs_show_path(struct seq_file *, struct vfsmount *); | ||
266 | static int nfs_show_stats(struct seq_file *, struct vfsmount *); | 268 | static int nfs_show_stats(struct seq_file *, struct vfsmount *); |
267 | static int nfs_get_sb(struct file_system_type *, int, const char *, void *, struct vfsmount *); | 269 | static struct dentry *nfs_fs_mount(struct file_system_type *, |
270 | int, const char *, void *); | ||
268 | static struct dentry *nfs_xdev_mount(struct file_system_type *fs_type, | 271 | static struct dentry *nfs_xdev_mount(struct file_system_type *fs_type, |
269 | int flags, const char *dev_name, void *raw_data); | 272 | int flags, const char *dev_name, void *raw_data); |
270 | static void nfs_put_super(struct super_block *); | 273 | static void nfs_put_super(struct super_block *); |
@@ -274,7 +277,7 @@ static int nfs_remount(struct super_block *sb, int *flags, char *raw_data); | |||
274 | static struct file_system_type nfs_fs_type = { | 277 | static struct file_system_type nfs_fs_type = { |
275 | .owner = THIS_MODULE, | 278 | .owner = THIS_MODULE, |
276 | .name = "nfs", | 279 | .name = "nfs", |
277 | .get_sb = nfs_get_sb, | 280 | .mount = nfs_fs_mount, |
278 | .kill_sb = nfs_kill_super, | 281 | .kill_sb = nfs_kill_super, |
279 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | 282 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, |
280 | }; | 283 | }; |
@@ -296,6 +299,8 @@ static const struct super_operations nfs_sops = { | |||
296 | .evict_inode = nfs_evict_inode, | 299 | .evict_inode = nfs_evict_inode, |
297 | .umount_begin = nfs_umount_begin, | 300 | .umount_begin = nfs_umount_begin, |
298 | .show_options = nfs_show_options, | 301 | .show_options = nfs_show_options, |
302 | .show_devname = nfs_show_devname, | ||
303 | .show_path = nfs_show_path, | ||
299 | .show_stats = nfs_show_stats, | 304 | .show_stats = nfs_show_stats, |
300 | .remount_fs = nfs_remount, | 305 | .remount_fs = nfs_remount, |
301 | }; | 306 | }; |
@@ -303,16 +308,16 @@ static const struct super_operations nfs_sops = { | |||
303 | #ifdef CONFIG_NFS_V4 | 308 | #ifdef CONFIG_NFS_V4 |
304 | static int nfs4_validate_text_mount_data(void *options, | 309 | static int nfs4_validate_text_mount_data(void *options, |
305 | struct nfs_parsed_mount_data *args, const char *dev_name); | 310 | struct nfs_parsed_mount_data *args, const char *dev_name); |
306 | static int nfs4_try_mount(int flags, const char *dev_name, | 311 | static struct dentry *nfs4_try_mount(int flags, const char *dev_name, |
307 | struct nfs_parsed_mount_data *data, struct vfsmount *mnt); | 312 | struct nfs_parsed_mount_data *data); |
308 | static int nfs4_get_sb(struct file_system_type *fs_type, | 313 | static struct dentry *nfs4_mount(struct file_system_type *fs_type, |
309 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); | 314 | int flags, const char *dev_name, void *raw_data); |
310 | static struct dentry *nfs4_remote_mount(struct file_system_type *fs_type, | 315 | static struct dentry *nfs4_remote_mount(struct file_system_type *fs_type, |
311 | int flags, const char *dev_name, void *raw_data); | 316 | int flags, const char *dev_name, void *raw_data); |
312 | static struct dentry *nfs4_xdev_mount(struct file_system_type *fs_type, | 317 | static struct dentry *nfs4_xdev_mount(struct file_system_type *fs_type, |
313 | int flags, const char *dev_name, void *raw_data); | 318 | int flags, const char *dev_name, void *raw_data); |
314 | static int nfs4_referral_get_sb(struct file_system_type *fs_type, | 319 | static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type, |
315 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); | 320 | int flags, const char *dev_name, void *raw_data); |
316 | static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_type, | 321 | static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_type, |
317 | int flags, const char *dev_name, void *raw_data); | 322 | int flags, const char *dev_name, void *raw_data); |
318 | static void nfs4_kill_super(struct super_block *sb); | 323 | static void nfs4_kill_super(struct super_block *sb); |
@@ -320,7 +325,7 @@ static void nfs4_kill_super(struct super_block *sb); | |||
320 | static struct file_system_type nfs4_fs_type = { | 325 | static struct file_system_type nfs4_fs_type = { |
321 | .owner = THIS_MODULE, | 326 | .owner = THIS_MODULE, |
322 | .name = "nfs4", | 327 | .name = "nfs4", |
323 | .get_sb = nfs4_get_sb, | 328 | .mount = nfs4_mount, |
324 | .kill_sb = nfs4_kill_super, | 329 | .kill_sb = nfs4_kill_super, |
325 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | 330 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, |
326 | }; | 331 | }; |
@@ -352,7 +357,7 @@ static struct file_system_type nfs4_remote_referral_fs_type = { | |||
352 | struct file_system_type nfs4_referral_fs_type = { | 357 | struct file_system_type nfs4_referral_fs_type = { |
353 | .owner = THIS_MODULE, | 358 | .owner = THIS_MODULE, |
354 | .name = "nfs4", | 359 | .name = "nfs4", |
355 | .get_sb = nfs4_referral_get_sb, | 360 | .mount = nfs4_referral_mount, |
356 | .kill_sb = nfs4_kill_super, | 361 | .kill_sb = nfs4_kill_super, |
357 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | 362 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, |
358 | }; | 363 | }; |
@@ -366,6 +371,8 @@ static const struct super_operations nfs4_sops = { | |||
366 | .evict_inode = nfs4_evict_inode, | 371 | .evict_inode = nfs4_evict_inode, |
367 | .umount_begin = nfs_umount_begin, | 372 | .umount_begin = nfs_umount_begin, |
368 | .show_options = nfs_show_options, | 373 | .show_options = nfs_show_options, |
374 | .show_devname = nfs_show_devname, | ||
375 | .show_path = nfs_show_path, | ||
369 | .show_stats = nfs_show_stats, | 376 | .show_stats = nfs_show_stats, |
370 | .remount_fs = nfs_remount, | 377 | .remount_fs = nfs_remount, |
371 | }; | 378 | }; |
@@ -726,6 +733,28 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt) | |||
726 | return 0; | 733 | return 0; |
727 | } | 734 | } |
728 | 735 | ||
736 | static int nfs_show_devname(struct seq_file *m, struct vfsmount *mnt) | ||
737 | { | ||
738 | char *page = (char *) __get_free_page(GFP_KERNEL); | ||
739 | char *devname, *dummy; | ||
740 | int err = 0; | ||
741 | if (!page) | ||
742 | return -ENOMEM; | ||
743 | devname = nfs_path(&dummy, mnt->mnt_root, page, PAGE_SIZE); | ||
744 | if (IS_ERR(devname)) | ||
745 | err = PTR_ERR(devname); | ||
746 | else | ||
747 | seq_escape(m, devname, " \t\n\\"); | ||
748 | free_page((unsigned long)page); | ||
749 | return err; | ||
750 | } | ||
751 | |||
752 | static int nfs_show_path(struct seq_file *m, struct vfsmount *mnt) | ||
753 | { | ||
754 | seq_puts(m, "/"); | ||
755 | return 0; | ||
756 | } | ||
757 | |||
729 | /* | 758 | /* |
730 | * Present statistical information for this VFS mountpoint | 759 | * Present statistical information for this VFS mountpoint |
731 | */ | 760 | */ |
@@ -979,6 +1008,27 @@ static int nfs_parse_security_flavors(char *value, | |||
979 | return 1; | 1008 | return 1; |
980 | } | 1009 | } |
981 | 1010 | ||
1011 | static int nfs_get_option_str(substring_t args[], char **option) | ||
1012 | { | ||
1013 | kfree(*option); | ||
1014 | *option = match_strdup(args); | ||
1015 | return !option; | ||
1016 | } | ||
1017 | |||
1018 | static int nfs_get_option_ul(substring_t args[], unsigned long *option) | ||
1019 | { | ||
1020 | int rc; | ||
1021 | char *string; | ||
1022 | |||
1023 | string = match_strdup(args); | ||
1024 | if (string == NULL) | ||
1025 | return -ENOMEM; | ||
1026 | rc = strict_strtoul(string, 10, option); | ||
1027 | kfree(string); | ||
1028 | |||
1029 | return rc; | ||
1030 | } | ||
1031 | |||
982 | /* | 1032 | /* |
983 | * Error-check and convert a string of mount options from user space into | 1033 | * Error-check and convert a string of mount options from user space into |
984 | * a data structure. The whole mount string is processed; bad options are | 1034 | * a data structure. The whole mount string is processed; bad options are |
@@ -1127,155 +1177,82 @@ static int nfs_parse_mount_options(char *raw, | |||
1127 | * options that take numeric values | 1177 | * options that take numeric values |
1128 | */ | 1178 | */ |
1129 | case Opt_port: | 1179 | case Opt_port: |
1130 | string = match_strdup(args); | 1180 | if (nfs_get_option_ul(args, &option) || |
1131 | if (string == NULL) | 1181 | option > USHRT_MAX) |
1132 | goto out_nomem; | ||
1133 | rc = strict_strtoul(string, 10, &option); | ||
1134 | kfree(string); | ||
1135 | if (rc != 0 || option > USHRT_MAX) | ||
1136 | goto out_invalid_value; | 1182 | goto out_invalid_value; |
1137 | mnt->nfs_server.port = option; | 1183 | mnt->nfs_server.port = option; |
1138 | break; | 1184 | break; |
1139 | case Opt_rsize: | 1185 | case Opt_rsize: |
1140 | string = match_strdup(args); | 1186 | if (nfs_get_option_ul(args, &option)) |
1141 | if (string == NULL) | ||
1142 | goto out_nomem; | ||
1143 | rc = strict_strtoul(string, 10, &option); | ||
1144 | kfree(string); | ||
1145 | if (rc != 0) | ||
1146 | goto out_invalid_value; | 1187 | goto out_invalid_value; |
1147 | mnt->rsize = option; | 1188 | mnt->rsize = option; |
1148 | break; | 1189 | break; |
1149 | case Opt_wsize: | 1190 | case Opt_wsize: |
1150 | string = match_strdup(args); | 1191 | if (nfs_get_option_ul(args, &option)) |
1151 | if (string == NULL) | ||
1152 | goto out_nomem; | ||
1153 | rc = strict_strtoul(string, 10, &option); | ||
1154 | kfree(string); | ||
1155 | if (rc != 0) | ||
1156 | goto out_invalid_value; | 1192 | goto out_invalid_value; |
1157 | mnt->wsize = option; | 1193 | mnt->wsize = option; |
1158 | break; | 1194 | break; |
1159 | case Opt_bsize: | 1195 | case Opt_bsize: |
1160 | string = match_strdup(args); | 1196 | if (nfs_get_option_ul(args, &option)) |
1161 | if (string == NULL) | ||
1162 | goto out_nomem; | ||
1163 | rc = strict_strtoul(string, 10, &option); | ||
1164 | kfree(string); | ||
1165 | if (rc != 0) | ||
1166 | goto out_invalid_value; | 1197 | goto out_invalid_value; |
1167 | mnt->bsize = option; | 1198 | mnt->bsize = option; |
1168 | break; | 1199 | break; |
1169 | case Opt_timeo: | 1200 | case Opt_timeo: |
1170 | string = match_strdup(args); | 1201 | if (nfs_get_option_ul(args, &option) || option == 0) |
1171 | if (string == NULL) | ||
1172 | goto out_nomem; | ||
1173 | rc = strict_strtoul(string, 10, &option); | ||
1174 | kfree(string); | ||
1175 | if (rc != 0 || option == 0) | ||
1176 | goto out_invalid_value; | 1202 | goto out_invalid_value; |
1177 | mnt->timeo = option; | 1203 | mnt->timeo = option; |
1178 | break; | 1204 | break; |
1179 | case Opt_retrans: | 1205 | case Opt_retrans: |
1180 | string = match_strdup(args); | 1206 | if (nfs_get_option_ul(args, &option) || option == 0) |
1181 | if (string == NULL) | ||
1182 | goto out_nomem; | ||
1183 | rc = strict_strtoul(string, 10, &option); | ||
1184 | kfree(string); | ||
1185 | if (rc != 0 || option == 0) | ||
1186 | goto out_invalid_value; | 1207 | goto out_invalid_value; |
1187 | mnt->retrans = option; | 1208 | mnt->retrans = option; |
1188 | break; | 1209 | break; |
1189 | case Opt_acregmin: | 1210 | case Opt_acregmin: |
1190 | string = match_strdup(args); | 1211 | if (nfs_get_option_ul(args, &option)) |
1191 | if (string == NULL) | ||
1192 | goto out_nomem; | ||
1193 | rc = strict_strtoul(string, 10, &option); | ||
1194 | kfree(string); | ||
1195 | if (rc != 0) | ||
1196 | goto out_invalid_value; | 1212 | goto out_invalid_value; |
1197 | mnt->acregmin = option; | 1213 | mnt->acregmin = option; |
1198 | break; | 1214 | break; |
1199 | case Opt_acregmax: | 1215 | case Opt_acregmax: |
1200 | string = match_strdup(args); | 1216 | if (nfs_get_option_ul(args, &option)) |
1201 | if (string == NULL) | ||
1202 | goto out_nomem; | ||
1203 | rc = strict_strtoul(string, 10, &option); | ||
1204 | kfree(string); | ||
1205 | if (rc != 0) | ||
1206 | goto out_invalid_value; | 1217 | goto out_invalid_value; |
1207 | mnt->acregmax = option; | 1218 | mnt->acregmax = option; |
1208 | break; | 1219 | break; |
1209 | case Opt_acdirmin: | 1220 | case Opt_acdirmin: |
1210 | string = match_strdup(args); | 1221 | if (nfs_get_option_ul(args, &option)) |
1211 | if (string == NULL) | ||
1212 | goto out_nomem; | ||
1213 | rc = strict_strtoul(string, 10, &option); | ||
1214 | kfree(string); | ||
1215 | if (rc != 0) | ||
1216 | goto out_invalid_value; | 1222 | goto out_invalid_value; |
1217 | mnt->acdirmin = option; | 1223 | mnt->acdirmin = option; |
1218 | break; | 1224 | break; |
1219 | case Opt_acdirmax: | 1225 | case Opt_acdirmax: |
1220 | string = match_strdup(args); | 1226 | if (nfs_get_option_ul(args, &option)) |
1221 | if (string == NULL) | ||
1222 | goto out_nomem; | ||
1223 | rc = strict_strtoul(string, 10, &option); | ||
1224 | kfree(string); | ||
1225 | if (rc != 0) | ||
1226 | goto out_invalid_value; | 1227 | goto out_invalid_value; |
1227 | mnt->acdirmax = option; | 1228 | mnt->acdirmax = option; |
1228 | break; | 1229 | break; |
1229 | case Opt_actimeo: | 1230 | case Opt_actimeo: |
1230 | string = match_strdup(args); | 1231 | if (nfs_get_option_ul(args, &option)) |
1231 | if (string == NULL) | ||
1232 | goto out_nomem; | ||
1233 | rc = strict_strtoul(string, 10, &option); | ||
1234 | kfree(string); | ||
1235 | if (rc != 0) | ||
1236 | goto out_invalid_value; | 1232 | goto out_invalid_value; |
1237 | mnt->acregmin = mnt->acregmax = | 1233 | mnt->acregmin = mnt->acregmax = |
1238 | mnt->acdirmin = mnt->acdirmax = option; | 1234 | mnt->acdirmin = mnt->acdirmax = option; |
1239 | break; | 1235 | break; |
1240 | case Opt_namelen: | 1236 | case Opt_namelen: |
1241 | string = match_strdup(args); | 1237 | if (nfs_get_option_ul(args, &option)) |
1242 | if (string == NULL) | ||
1243 | goto out_nomem; | ||
1244 | rc = strict_strtoul(string, 10, &option); | ||
1245 | kfree(string); | ||
1246 | if (rc != 0) | ||
1247 | goto out_invalid_value; | 1238 | goto out_invalid_value; |
1248 | mnt->namlen = option; | 1239 | mnt->namlen = option; |
1249 | break; | 1240 | break; |
1250 | case Opt_mountport: | 1241 | case Opt_mountport: |
1251 | string = match_strdup(args); | 1242 | if (nfs_get_option_ul(args, &option) || |
1252 | if (string == NULL) | 1243 | option > USHRT_MAX) |
1253 | goto out_nomem; | ||
1254 | rc = strict_strtoul(string, 10, &option); | ||
1255 | kfree(string); | ||
1256 | if (rc != 0 || option > USHRT_MAX) | ||
1257 | goto out_invalid_value; | 1244 | goto out_invalid_value; |
1258 | mnt->mount_server.port = option; | 1245 | mnt->mount_server.port = option; |
1259 | break; | 1246 | break; |
1260 | case Opt_mountvers: | 1247 | case Opt_mountvers: |
1261 | string = match_strdup(args); | 1248 | if (nfs_get_option_ul(args, &option) || |
1262 | if (string == NULL) | ||
1263 | goto out_nomem; | ||
1264 | rc = strict_strtoul(string, 10, &option); | ||
1265 | kfree(string); | ||
1266 | if (rc != 0 || | ||
1267 | option < NFS_MNT_VERSION || | 1249 | option < NFS_MNT_VERSION || |
1268 | option > NFS_MNT3_VERSION) | 1250 | option > NFS_MNT3_VERSION) |
1269 | goto out_invalid_value; | 1251 | goto out_invalid_value; |
1270 | mnt->mount_server.version = option; | 1252 | mnt->mount_server.version = option; |
1271 | break; | 1253 | break; |
1272 | case Opt_nfsvers: | 1254 | case Opt_nfsvers: |
1273 | string = match_strdup(args); | 1255 | if (nfs_get_option_ul(args, &option)) |
1274 | if (string == NULL) | ||
1275 | goto out_nomem; | ||
1276 | rc = strict_strtoul(string, 10, &option); | ||
1277 | kfree(string); | ||
1278 | if (rc != 0) | ||
1279 | goto out_invalid_value; | 1256 | goto out_invalid_value; |
1280 | switch (option) { | 1257 | switch (option) { |
1281 | case NFS2_VERSION: | 1258 | case NFS2_VERSION: |
@@ -1295,12 +1272,7 @@ static int nfs_parse_mount_options(char *raw, | |||
1295 | } | 1272 | } |
1296 | break; | 1273 | break; |
1297 | case Opt_minorversion: | 1274 | case Opt_minorversion: |
1298 | string = match_strdup(args); | 1275 | if (nfs_get_option_ul(args, &option)) |
1299 | if (string == NULL) | ||
1300 | goto out_nomem; | ||
1301 | rc = strict_strtoul(string, 10, &option); | ||
1302 | kfree(string); | ||
1303 | if (rc != 0) | ||
1304 | goto out_invalid_value; | 1276 | goto out_invalid_value; |
1305 | if (option > NFS4_MAX_MINOR_VERSION) | 1277 | if (option > NFS4_MAX_MINOR_VERSION) |
1306 | goto out_invalid_value; | 1278 | goto out_invalid_value; |
@@ -1336,21 +1308,18 @@ static int nfs_parse_mount_options(char *raw, | |||
1336 | case Opt_xprt_udp: | 1308 | case Opt_xprt_udp: |
1337 | mnt->flags &= ~NFS_MOUNT_TCP; | 1309 | mnt->flags &= ~NFS_MOUNT_TCP; |
1338 | mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP; | 1310 | mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP; |
1339 | kfree(string); | ||
1340 | break; | 1311 | break; |
1341 | case Opt_xprt_tcp6: | 1312 | case Opt_xprt_tcp6: |
1342 | protofamily = AF_INET6; | 1313 | protofamily = AF_INET6; |
1343 | case Opt_xprt_tcp: | 1314 | case Opt_xprt_tcp: |
1344 | mnt->flags |= NFS_MOUNT_TCP; | 1315 | mnt->flags |= NFS_MOUNT_TCP; |
1345 | mnt->nfs_server.protocol = XPRT_TRANSPORT_TCP; | 1316 | mnt->nfs_server.protocol = XPRT_TRANSPORT_TCP; |
1346 | kfree(string); | ||
1347 | break; | 1317 | break; |
1348 | case Opt_xprt_rdma: | 1318 | case Opt_xprt_rdma: |
1349 | /* vector side protocols to TCP */ | 1319 | /* vector side protocols to TCP */ |
1350 | mnt->flags |= NFS_MOUNT_TCP; | 1320 | mnt->flags |= NFS_MOUNT_TCP; |
1351 | mnt->nfs_server.protocol = XPRT_TRANSPORT_RDMA; | 1321 | mnt->nfs_server.protocol = XPRT_TRANSPORT_RDMA; |
1352 | xprt_load_transport(string); | 1322 | xprt_load_transport(string); |
1353 | kfree(string); | ||
1354 | break; | 1323 | break; |
1355 | default: | 1324 | default: |
1356 | dfprintk(MOUNT, "NFS: unrecognized " | 1325 | dfprintk(MOUNT, "NFS: unrecognized " |
@@ -1358,6 +1327,7 @@ static int nfs_parse_mount_options(char *raw, | |||
1358 | kfree(string); | 1327 | kfree(string); |
1359 | return 0; | 1328 | return 0; |
1360 | } | 1329 | } |
1330 | kfree(string); | ||
1361 | break; | 1331 | break; |
1362 | case Opt_mountproto: | 1332 | case Opt_mountproto: |
1363 | string = match_strdup(args); | 1333 | string = match_strdup(args); |
@@ -1400,18 +1370,13 @@ static int nfs_parse_mount_options(char *raw, | |||
1400 | goto out_invalid_address; | 1370 | goto out_invalid_address; |
1401 | break; | 1371 | break; |
1402 | case Opt_clientaddr: | 1372 | case Opt_clientaddr: |
1403 | string = match_strdup(args); | 1373 | if (nfs_get_option_str(args, &mnt->client_address)) |
1404 | if (string == NULL) | ||
1405 | goto out_nomem; | 1374 | goto out_nomem; |
1406 | kfree(mnt->client_address); | ||
1407 | mnt->client_address = string; | ||
1408 | break; | 1375 | break; |
1409 | case Opt_mounthost: | 1376 | case Opt_mounthost: |
1410 | string = match_strdup(args); | 1377 | if (nfs_get_option_str(args, |
1411 | if (string == NULL) | 1378 | &mnt->mount_server.hostname)) |
1412 | goto out_nomem; | 1379 | goto out_nomem; |
1413 | kfree(mnt->mount_server.hostname); | ||
1414 | mnt->mount_server.hostname = string; | ||
1415 | break; | 1380 | break; |
1416 | case Opt_mountaddr: | 1381 | case Opt_mountaddr: |
1417 | string = match_strdup(args); | 1382 | string = match_strdup(args); |
@@ -1451,11 +1416,8 @@ static int nfs_parse_mount_options(char *raw, | |||
1451 | }; | 1416 | }; |
1452 | break; | 1417 | break; |
1453 | case Opt_fscache_uniq: | 1418 | case Opt_fscache_uniq: |
1454 | string = match_strdup(args); | 1419 | if (nfs_get_option_str(args, &mnt->fscache_uniq)) |
1455 | if (string == NULL) | ||
1456 | goto out_nomem; | 1420 | goto out_nomem; |
1457 | kfree(mnt->fscache_uniq); | ||
1458 | mnt->fscache_uniq = string; | ||
1459 | mnt->options |= NFS_OPTION_FSCACHE; | 1421 | mnt->options |= NFS_OPTION_FSCACHE; |
1460 | break; | 1422 | break; |
1461 | case Opt_local_lock: | 1423 | case Opt_local_lock: |
@@ -1665,99 +1627,59 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args, | |||
1665 | return nfs_walk_authlist(args, &request); | 1627 | return nfs_walk_authlist(args, &request); |
1666 | } | 1628 | } |
1667 | 1629 | ||
1668 | static int nfs_parse_simple_hostname(const char *dev_name, | 1630 | /* |
1669 | char **hostname, size_t maxnamlen, | 1631 | * Split "dev_name" into "hostname:export_path". |
1670 | char **export_path, size_t maxpathlen) | 1632 | * |
1633 | * The leftmost colon demarks the split between the server's hostname | ||
1634 | * and the export path. If the hostname starts with a left square | ||
1635 | * bracket, then it may contain colons. | ||
1636 | * | ||
1637 | * Note: caller frees hostname and export path, even on error. | ||
1638 | */ | ||
1639 | static int nfs_parse_devname(const char *dev_name, | ||
1640 | char **hostname, size_t maxnamlen, | ||
1641 | char **export_path, size_t maxpathlen) | ||
1671 | { | 1642 | { |
1672 | size_t len; | 1643 | size_t len; |
1673 | char *colon, *comma; | 1644 | char *end; |
1674 | |||
1675 | colon = strchr(dev_name, ':'); | ||
1676 | if (colon == NULL) | ||
1677 | goto out_bad_devname; | ||
1678 | |||
1679 | len = colon - dev_name; | ||
1680 | if (len > maxnamlen) | ||
1681 | goto out_hostname; | ||
1682 | 1645 | ||
1683 | /* N.B. caller will free nfs_server.hostname in all cases */ | 1646 | /* Is the host name protected with square brakcets? */ |
1684 | *hostname = kstrndup(dev_name, len, GFP_KERNEL); | 1647 | if (*dev_name == '[') { |
1685 | if (!*hostname) | 1648 | end = strchr(++dev_name, ']'); |
1686 | goto out_nomem; | 1649 | if (end == NULL || end[1] != ':') |
1687 | |||
1688 | /* kill possible hostname list: not supported */ | ||
1689 | comma = strchr(*hostname, ','); | ||
1690 | if (comma != NULL) { | ||
1691 | if (comma == *hostname) | ||
1692 | goto out_bad_devname; | 1650 | goto out_bad_devname; |
1693 | *comma = '\0'; | ||
1694 | } | ||
1695 | 1651 | ||
1696 | colon++; | 1652 | len = end - dev_name; |
1697 | len = strlen(colon); | 1653 | end++; |
1698 | if (len > maxpathlen) | 1654 | } else { |
1699 | goto out_path; | 1655 | char *comma; |
1700 | *export_path = kstrndup(colon, len, GFP_KERNEL); | ||
1701 | if (!*export_path) | ||
1702 | goto out_nomem; | ||
1703 | |||
1704 | dfprintk(MOUNT, "NFS: MNTPATH: '%s'\n", *export_path); | ||
1705 | return 0; | ||
1706 | |||
1707 | out_bad_devname: | ||
1708 | dfprintk(MOUNT, "NFS: device name not in host:path format\n"); | ||
1709 | return -EINVAL; | ||
1710 | |||
1711 | out_nomem: | ||
1712 | dfprintk(MOUNT, "NFS: not enough memory to parse device name\n"); | ||
1713 | return -ENOMEM; | ||
1714 | |||
1715 | out_hostname: | ||
1716 | dfprintk(MOUNT, "NFS: server hostname too long\n"); | ||
1717 | return -ENAMETOOLONG; | ||
1718 | |||
1719 | out_path: | ||
1720 | dfprintk(MOUNT, "NFS: export pathname too long\n"); | ||
1721 | return -ENAMETOOLONG; | ||
1722 | } | ||
1723 | |||
1724 | /* | ||
1725 | * Hostname has square brackets around it because it contains one or | ||
1726 | * more colons. We look for the first closing square bracket, and a | ||
1727 | * colon must follow it. | ||
1728 | */ | ||
1729 | static int nfs_parse_protected_hostname(const char *dev_name, | ||
1730 | char **hostname, size_t maxnamlen, | ||
1731 | char **export_path, size_t maxpathlen) | ||
1732 | { | ||
1733 | size_t len; | ||
1734 | char *start, *end; | ||
1735 | 1656 | ||
1736 | start = (char *)(dev_name + 1); | 1657 | end = strchr(dev_name, ':'); |
1658 | if (end == NULL) | ||
1659 | goto out_bad_devname; | ||
1660 | len = end - dev_name; | ||
1737 | 1661 | ||
1738 | end = strchr(start, ']'); | 1662 | /* kill possible hostname list: not supported */ |
1739 | if (end == NULL) | 1663 | comma = strchr(dev_name, ','); |
1740 | goto out_bad_devname; | 1664 | if (comma != NULL && comma < end) |
1741 | if (*(end + 1) != ':') | 1665 | *comma = 0; |
1742 | goto out_bad_devname; | 1666 | } |
1743 | 1667 | ||
1744 | len = end - start; | ||
1745 | if (len > maxnamlen) | 1668 | if (len > maxnamlen) |
1746 | goto out_hostname; | 1669 | goto out_hostname; |
1747 | 1670 | ||
1748 | /* N.B. caller will free nfs_server.hostname in all cases */ | 1671 | /* N.B. caller will free nfs_server.hostname in all cases */ |
1749 | *hostname = kstrndup(start, len, GFP_KERNEL); | 1672 | *hostname = kstrndup(dev_name, len, GFP_KERNEL); |
1750 | if (*hostname == NULL) | 1673 | if (*hostname == NULL) |
1751 | goto out_nomem; | 1674 | goto out_nomem; |
1752 | 1675 | len = strlen(++end); | |
1753 | end += 2; | ||
1754 | len = strlen(end); | ||
1755 | if (len > maxpathlen) | 1676 | if (len > maxpathlen) |
1756 | goto out_path; | 1677 | goto out_path; |
1757 | *export_path = kstrndup(end, len, GFP_KERNEL); | 1678 | *export_path = kstrndup(end, len, GFP_KERNEL); |
1758 | if (!*export_path) | 1679 | if (!*export_path) |
1759 | goto out_nomem; | 1680 | goto out_nomem; |
1760 | 1681 | ||
1682 | dfprintk(MOUNT, "NFS: MNTPATH: '%s'\n", *export_path); | ||
1761 | return 0; | 1683 | return 0; |
1762 | 1684 | ||
1763 | out_bad_devname: | 1685 | out_bad_devname: |
@@ -1778,29 +1700,6 @@ out_path: | |||
1778 | } | 1700 | } |
1779 | 1701 | ||
1780 | /* | 1702 | /* |
1781 | * Split "dev_name" into "hostname:export_path". | ||
1782 | * | ||
1783 | * The leftmost colon demarks the split between the server's hostname | ||
1784 | * and the export path. If the hostname starts with a left square | ||
1785 | * bracket, then it may contain colons. | ||
1786 | * | ||
1787 | * Note: caller frees hostname and export path, even on error. | ||
1788 | */ | ||
1789 | static int nfs_parse_devname(const char *dev_name, | ||
1790 | char **hostname, size_t maxnamlen, | ||
1791 | char **export_path, size_t maxpathlen) | ||
1792 | { | ||
1793 | if (*dev_name == '[') | ||
1794 | return nfs_parse_protected_hostname(dev_name, | ||
1795 | hostname, maxnamlen, | ||
1796 | export_path, maxpathlen); | ||
1797 | |||
1798 | return nfs_parse_simple_hostname(dev_name, | ||
1799 | hostname, maxnamlen, | ||
1800 | export_path, maxpathlen); | ||
1801 | } | ||
1802 | |||
1803 | /* | ||
1804 | * Validate the NFS2/NFS3 mount data | 1703 | * Validate the NFS2/NFS3 mount data |
1805 | * - fills in the mount root filehandle | 1704 | * - fills in the mount root filehandle |
1806 | * | 1705 | * |
@@ -2267,19 +2166,19 @@ static int nfs_bdi_register(struct nfs_server *server) | |||
2267 | return bdi_register_dev(&server->backing_dev_info, server->s_dev); | 2166 | return bdi_register_dev(&server->backing_dev_info, server->s_dev); |
2268 | } | 2167 | } |
2269 | 2168 | ||
2270 | static int nfs_get_sb(struct file_system_type *fs_type, | 2169 | static struct dentry *nfs_fs_mount(struct file_system_type *fs_type, |
2271 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) | 2170 | int flags, const char *dev_name, void *raw_data) |
2272 | { | 2171 | { |
2273 | struct nfs_server *server = NULL; | 2172 | struct nfs_server *server = NULL; |
2274 | struct super_block *s; | 2173 | struct super_block *s; |
2275 | struct nfs_parsed_mount_data *data; | 2174 | struct nfs_parsed_mount_data *data; |
2276 | struct nfs_fh *mntfh; | 2175 | struct nfs_fh *mntfh; |
2277 | struct dentry *mntroot; | 2176 | struct dentry *mntroot = ERR_PTR(-ENOMEM); |
2278 | int (*compare_super)(struct super_block *, void *) = nfs_compare_super; | 2177 | int (*compare_super)(struct super_block *, void *) = nfs_compare_super; |
2279 | struct nfs_sb_mountdata sb_mntdata = { | 2178 | struct nfs_sb_mountdata sb_mntdata = { |
2280 | .mntflags = flags, | 2179 | .mntflags = flags, |
2281 | }; | 2180 | }; |
2282 | int error = -ENOMEM; | 2181 | int error; |
2283 | 2182 | ||
2284 | data = nfs_alloc_parsed_mount_data(NFS_DEFAULT_VERSION); | 2183 | data = nfs_alloc_parsed_mount_data(NFS_DEFAULT_VERSION); |
2285 | mntfh = nfs_alloc_fhandle(); | 2184 | mntfh = nfs_alloc_fhandle(); |
@@ -2290,12 +2189,14 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
2290 | 2189 | ||
2291 | /* Validate the mount data */ | 2190 | /* Validate the mount data */ |
2292 | error = nfs_validate_mount_data(raw_data, data, mntfh, dev_name); | 2191 | error = nfs_validate_mount_data(raw_data, data, mntfh, dev_name); |
2293 | if (error < 0) | 2192 | if (error < 0) { |
2193 | mntroot = ERR_PTR(error); | ||
2294 | goto out; | 2194 | goto out; |
2195 | } | ||
2295 | 2196 | ||
2296 | #ifdef CONFIG_NFS_V4 | 2197 | #ifdef CONFIG_NFS_V4 |
2297 | if (data->version == 4) { | 2198 | if (data->version == 4) { |
2298 | error = nfs4_try_mount(flags, dev_name, data, mnt); | 2199 | mntroot = nfs4_try_mount(flags, dev_name, data); |
2299 | kfree(data->client_address); | 2200 | kfree(data->client_address); |
2300 | kfree(data->nfs_server.export_path); | 2201 | kfree(data->nfs_server.export_path); |
2301 | goto out; | 2202 | goto out; |
@@ -2305,7 +2206,7 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
2305 | /* Get a volume representation */ | 2206 | /* Get a volume representation */ |
2306 | server = nfs_create_server(data, mntfh); | 2207 | server = nfs_create_server(data, mntfh); |
2307 | if (IS_ERR(server)) { | 2208 | if (IS_ERR(server)) { |
2308 | error = PTR_ERR(server); | 2209 | mntroot = ERR_CAST(server); |
2309 | goto out; | 2210 | goto out; |
2310 | } | 2211 | } |
2311 | sb_mntdata.server = server; | 2212 | sb_mntdata.server = server; |
@@ -2316,7 +2217,7 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
2316 | /* Get a superblock - note that we may end up sharing one that already exists */ | 2217 | /* Get a superblock - note that we may end up sharing one that already exists */ |
2317 | s = sget(fs_type, compare_super, nfs_set_super, &sb_mntdata); | 2218 | s = sget(fs_type, compare_super, nfs_set_super, &sb_mntdata); |
2318 | if (IS_ERR(s)) { | 2219 | if (IS_ERR(s)) { |
2319 | error = PTR_ERR(s); | 2220 | mntroot = ERR_CAST(s); |
2320 | goto out_err_nosb; | 2221 | goto out_err_nosb; |
2321 | } | 2222 | } |
2322 | 2223 | ||
@@ -2325,8 +2226,10 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
2325 | server = NULL; | 2226 | server = NULL; |
2326 | } else { | 2227 | } else { |
2327 | error = nfs_bdi_register(server); | 2228 | error = nfs_bdi_register(server); |
2328 | if (error) | 2229 | if (error) { |
2230 | mntroot = ERR_PTR(error); | ||
2329 | goto error_splat_bdi; | 2231 | goto error_splat_bdi; |
2232 | } | ||
2330 | } | 2233 | } |
2331 | 2234 | ||
2332 | if (!s->s_root) { | 2235 | if (!s->s_root) { |
@@ -2336,20 +2239,15 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
2336 | s, data ? data->fscache_uniq : NULL, NULL); | 2239 | s, data ? data->fscache_uniq : NULL, NULL); |
2337 | } | 2240 | } |
2338 | 2241 | ||
2339 | mntroot = nfs_get_root(s, mntfh); | 2242 | mntroot = nfs_get_root(s, mntfh, dev_name); |
2340 | if (IS_ERR(mntroot)) { | 2243 | if (IS_ERR(mntroot)) |
2341 | error = PTR_ERR(mntroot); | ||
2342 | goto error_splat_super; | 2244 | goto error_splat_super; |
2343 | } | ||
2344 | 2245 | ||
2345 | error = security_sb_set_mnt_opts(s, &data->lsm_opts); | 2246 | error = security_sb_set_mnt_opts(s, &data->lsm_opts); |
2346 | if (error) | 2247 | if (error) |
2347 | goto error_splat_root; | 2248 | goto error_splat_root; |
2348 | 2249 | ||
2349 | s->s_flags |= MS_ACTIVE; | 2250 | s->s_flags |= MS_ACTIVE; |
2350 | mnt->mnt_sb = s; | ||
2351 | mnt->mnt_root = mntroot; | ||
2352 | error = 0; | ||
2353 | 2251 | ||
2354 | out: | 2252 | out: |
2355 | kfree(data->nfs_server.hostname); | 2253 | kfree(data->nfs_server.hostname); |
@@ -2359,7 +2257,7 @@ out: | |||
2359 | out_free_fh: | 2257 | out_free_fh: |
2360 | nfs_free_fhandle(mntfh); | 2258 | nfs_free_fhandle(mntfh); |
2361 | kfree(data); | 2259 | kfree(data); |
2362 | return error; | 2260 | return mntroot; |
2363 | 2261 | ||
2364 | out_err_nosb: | 2262 | out_err_nosb: |
2365 | nfs_free_server(server); | 2263 | nfs_free_server(server); |
@@ -2367,6 +2265,7 @@ out_err_nosb: | |||
2367 | 2265 | ||
2368 | error_splat_root: | 2266 | error_splat_root: |
2369 | dput(mntroot); | 2267 | dput(mntroot); |
2268 | mntroot = ERR_PTR(error); | ||
2370 | error_splat_super: | 2269 | error_splat_super: |
2371 | if (server && !s->s_root) | 2270 | if (server && !s->s_root) |
2372 | bdi_unregister(&server->backing_dev_info); | 2271 | bdi_unregister(&server->backing_dev_info); |
@@ -2450,7 +2349,7 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags, | |||
2450 | nfs_fscache_get_super_cookie(s, NULL, data); | 2349 | nfs_fscache_get_super_cookie(s, NULL, data); |
2451 | } | 2350 | } |
2452 | 2351 | ||
2453 | mntroot = nfs_get_root(s, data->fh); | 2352 | mntroot = nfs_get_root(s, data->fh, dev_name); |
2454 | if (IS_ERR(mntroot)) { | 2353 | if (IS_ERR(mntroot)) { |
2455 | error = PTR_ERR(mntroot); | 2354 | error = PTR_ERR(mntroot); |
2456 | goto error_splat_super; | 2355 | goto error_splat_super; |
@@ -2718,7 +2617,7 @@ nfs4_remote_mount(struct file_system_type *fs_type, int flags, | |||
2718 | s, data ? data->fscache_uniq : NULL, NULL); | 2617 | s, data ? data->fscache_uniq : NULL, NULL); |
2719 | } | 2618 | } |
2720 | 2619 | ||
2721 | mntroot = nfs4_get_root(s, mntfh); | 2620 | mntroot = nfs4_get_root(s, mntfh, dev_name); |
2722 | if (IS_ERR(mntroot)) { | 2621 | if (IS_ERR(mntroot)) { |
2723 | error = PTR_ERR(mntroot); | 2622 | error = PTR_ERR(mntroot); |
2724 | goto error_splat_super; | 2623 | goto error_splat_super; |
@@ -2771,27 +2670,6 @@ static struct vfsmount *nfs_do_root_mount(struct file_system_type *fs_type, | |||
2771 | return root_mnt; | 2670 | return root_mnt; |
2772 | } | 2671 | } |
2773 | 2672 | ||
2774 | static void nfs_fix_devname(const struct path *path, struct vfsmount *mnt) | ||
2775 | { | ||
2776 | char *page = (char *) __get_free_page(GFP_KERNEL); | ||
2777 | char *devname, *tmp; | ||
2778 | |||
2779 | if (page == NULL) | ||
2780 | return; | ||
2781 | devname = nfs_path(path->mnt->mnt_devname, | ||
2782 | path->mnt->mnt_root, path->dentry, | ||
2783 | page, PAGE_SIZE); | ||
2784 | if (IS_ERR(devname)) | ||
2785 | goto out_freepage; | ||
2786 | tmp = kstrdup(devname, GFP_KERNEL); | ||
2787 | if (tmp == NULL) | ||
2788 | goto out_freepage; | ||
2789 | kfree(mnt->mnt_devname); | ||
2790 | mnt->mnt_devname = tmp; | ||
2791 | out_freepage: | ||
2792 | free_page((unsigned long)page); | ||
2793 | } | ||
2794 | |||
2795 | struct nfs_referral_count { | 2673 | struct nfs_referral_count { |
2796 | struct list_head list; | 2674 | struct list_head list; |
2797 | const struct task_struct *task; | 2675 | const struct task_struct *task; |
@@ -2858,17 +2736,18 @@ static void nfs_referral_loop_unprotect(void) | |||
2858 | kfree(p); | 2736 | kfree(p); |
2859 | } | 2737 | } |
2860 | 2738 | ||
2861 | static int nfs_follow_remote_path(struct vfsmount *root_mnt, | 2739 | static struct dentry *nfs_follow_remote_path(struct vfsmount *root_mnt, |
2862 | const char *export_path, struct vfsmount *mnt_target) | 2740 | const char *export_path) |
2863 | { | 2741 | { |
2864 | struct nameidata *nd = NULL; | 2742 | struct nameidata *nd = NULL; |
2865 | struct mnt_namespace *ns_private; | 2743 | struct mnt_namespace *ns_private; |
2866 | struct super_block *s; | 2744 | struct super_block *s; |
2745 | struct dentry *dentry; | ||
2867 | int ret; | 2746 | int ret; |
2868 | 2747 | ||
2869 | nd = kmalloc(sizeof(*nd), GFP_KERNEL); | 2748 | nd = kmalloc(sizeof(*nd), GFP_KERNEL); |
2870 | if (nd == NULL) | 2749 | if (nd == NULL) |
2871 | return -ENOMEM; | 2750 | return ERR_PTR(-ENOMEM); |
2872 | 2751 | ||
2873 | ns_private = create_mnt_ns(root_mnt); | 2752 | ns_private = create_mnt_ns(root_mnt); |
2874 | ret = PTR_ERR(ns_private); | 2753 | ret = PTR_ERR(ns_private); |
@@ -2890,32 +2769,27 @@ static int nfs_follow_remote_path(struct vfsmount *root_mnt, | |||
2890 | 2769 | ||
2891 | s = nd->path.mnt->mnt_sb; | 2770 | s = nd->path.mnt->mnt_sb; |
2892 | atomic_inc(&s->s_active); | 2771 | atomic_inc(&s->s_active); |
2893 | mnt_target->mnt_sb = s; | 2772 | dentry = dget(nd->path.dentry); |
2894 | mnt_target->mnt_root = dget(nd->path.dentry); | ||
2895 | |||
2896 | /* Correct the device pathname */ | ||
2897 | nfs_fix_devname(&nd->path, mnt_target); | ||
2898 | 2773 | ||
2899 | path_put(&nd->path); | 2774 | path_put(&nd->path); |
2900 | kfree(nd); | 2775 | kfree(nd); |
2901 | down_write(&s->s_umount); | 2776 | down_write(&s->s_umount); |
2902 | return 0; | 2777 | return dentry; |
2903 | out_put_mnt_ns: | 2778 | out_put_mnt_ns: |
2904 | put_mnt_ns(ns_private); | 2779 | put_mnt_ns(ns_private); |
2905 | out_mntput: | 2780 | out_mntput: |
2906 | mntput(root_mnt); | 2781 | mntput(root_mnt); |
2907 | out_err: | 2782 | out_err: |
2908 | kfree(nd); | 2783 | kfree(nd); |
2909 | return ret; | 2784 | return ERR_PTR(ret); |
2910 | } | 2785 | } |
2911 | 2786 | ||
2912 | static int nfs4_try_mount(int flags, const char *dev_name, | 2787 | static struct dentry *nfs4_try_mount(int flags, const char *dev_name, |
2913 | struct nfs_parsed_mount_data *data, | 2788 | struct nfs_parsed_mount_data *data) |
2914 | struct vfsmount *mnt) | ||
2915 | { | 2789 | { |
2916 | char *export_path; | 2790 | char *export_path; |
2917 | struct vfsmount *root_mnt; | 2791 | struct vfsmount *root_mnt; |
2918 | int error; | 2792 | struct dentry *res; |
2919 | 2793 | ||
2920 | dfprintk(MOUNT, "--> nfs4_try_mount()\n"); | 2794 | dfprintk(MOUNT, "--> nfs4_try_mount()\n"); |
2921 | 2795 | ||
@@ -2925,26 +2799,25 @@ static int nfs4_try_mount(int flags, const char *dev_name, | |||
2925 | data->nfs_server.hostname); | 2799 | data->nfs_server.hostname); |
2926 | data->nfs_server.export_path = export_path; | 2800 | data->nfs_server.export_path = export_path; |
2927 | 2801 | ||
2928 | error = PTR_ERR(root_mnt); | 2802 | res = ERR_CAST(root_mnt); |
2929 | if (IS_ERR(root_mnt)) | 2803 | if (!IS_ERR(root_mnt)) |
2930 | goto out; | 2804 | res = nfs_follow_remote_path(root_mnt, export_path); |
2931 | |||
2932 | error = nfs_follow_remote_path(root_mnt, export_path, mnt); | ||
2933 | 2805 | ||
2934 | out: | 2806 | dfprintk(MOUNT, "<-- nfs4_try_mount() = %ld%s\n", |
2935 | dfprintk(MOUNT, "<-- nfs4_try_mount() = %d%s\n", error, | 2807 | IS_ERR(res) ? PTR_ERR(res) : 0, |
2936 | error != 0 ? " [error]" : ""); | 2808 | IS_ERR(res) ? " [error]" : ""); |
2937 | return error; | 2809 | return res; |
2938 | } | 2810 | } |
2939 | 2811 | ||
2940 | /* | 2812 | /* |
2941 | * Get the superblock for an NFS4 mountpoint | 2813 | * Get the superblock for an NFS4 mountpoint |
2942 | */ | 2814 | */ |
2943 | static int nfs4_get_sb(struct file_system_type *fs_type, | 2815 | static struct dentry *nfs4_mount(struct file_system_type *fs_type, |
2944 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) | 2816 | int flags, const char *dev_name, void *raw_data) |
2945 | { | 2817 | { |
2946 | struct nfs_parsed_mount_data *data; | 2818 | struct nfs_parsed_mount_data *data; |
2947 | int error = -ENOMEM; | 2819 | int error = -ENOMEM; |
2820 | struct dentry *res = ERR_PTR(-ENOMEM); | ||
2948 | 2821 | ||
2949 | data = nfs_alloc_parsed_mount_data(4); | 2822 | data = nfs_alloc_parsed_mount_data(4); |
2950 | if (data == NULL) | 2823 | if (data == NULL) |
@@ -2952,10 +2825,14 @@ static int nfs4_get_sb(struct file_system_type *fs_type, | |||
2952 | 2825 | ||
2953 | /* Validate the mount data */ | 2826 | /* Validate the mount data */ |
2954 | error = nfs4_validate_mount_data(raw_data, data, dev_name); | 2827 | error = nfs4_validate_mount_data(raw_data, data, dev_name); |
2955 | if (error < 0) | 2828 | if (error < 0) { |
2829 | res = ERR_PTR(error); | ||
2956 | goto out; | 2830 | goto out; |
2831 | } | ||
2957 | 2832 | ||
2958 | error = nfs4_try_mount(flags, dev_name, data, mnt); | 2833 | res = nfs4_try_mount(flags, dev_name, data); |
2834 | if (IS_ERR(res)) | ||
2835 | error = PTR_ERR(res); | ||
2959 | 2836 | ||
2960 | out: | 2837 | out: |
2961 | kfree(data->client_address); | 2838 | kfree(data->client_address); |
@@ -2964,9 +2841,9 @@ out: | |||
2964 | kfree(data->fscache_uniq); | 2841 | kfree(data->fscache_uniq); |
2965 | out_free_data: | 2842 | out_free_data: |
2966 | kfree(data); | 2843 | kfree(data); |
2967 | dprintk("<-- nfs4_get_sb() = %d%s\n", error, | 2844 | dprintk("<-- nfs4_mount() = %d%s\n", error, |
2968 | error != 0 ? " [error]" : ""); | 2845 | error != 0 ? " [error]" : ""); |
2969 | return error; | 2846 | return res; |
2970 | } | 2847 | } |
2971 | 2848 | ||
2972 | static void nfs4_kill_super(struct super_block *sb) | 2849 | static void nfs4_kill_super(struct super_block *sb) |
@@ -3033,7 +2910,7 @@ nfs4_xdev_mount(struct file_system_type *fs_type, int flags, | |||
3033 | nfs_fscache_get_super_cookie(s, NULL, data); | 2910 | nfs_fscache_get_super_cookie(s, NULL, data); |
3034 | } | 2911 | } |
3035 | 2912 | ||
3036 | mntroot = nfs4_get_root(s, data->fh); | 2913 | mntroot = nfs4_get_root(s, data->fh, dev_name); |
3037 | if (IS_ERR(mntroot)) { | 2914 | if (IS_ERR(mntroot)) { |
3038 | error = PTR_ERR(mntroot); | 2915 | error = PTR_ERR(mntroot); |
3039 | goto error_splat_super; | 2916 | goto error_splat_super; |
@@ -3120,7 +2997,7 @@ nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags, | |||
3120 | nfs_fscache_get_super_cookie(s, NULL, data); | 2997 | nfs_fscache_get_super_cookie(s, NULL, data); |
3121 | } | 2998 | } |
3122 | 2999 | ||
3123 | mntroot = nfs4_get_root(s, mntfh); | 3000 | mntroot = nfs4_get_root(s, mntfh, dev_name); |
3124 | if (IS_ERR(mntroot)) { | 3001 | if (IS_ERR(mntroot)) { |
3125 | error = PTR_ERR(mntroot); | 3002 | error = PTR_ERR(mntroot); |
3126 | goto error_splat_super; | 3003 | goto error_splat_super; |
@@ -3160,16 +3037,15 @@ error_splat_bdi: | |||
3160 | /* | 3037 | /* |
3161 | * Create an NFS4 server record on referral traversal | 3038 | * Create an NFS4 server record on referral traversal |
3162 | */ | 3039 | */ |
3163 | static int nfs4_referral_get_sb(struct file_system_type *fs_type, | 3040 | static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type, |
3164 | int flags, const char *dev_name, void *raw_data, | 3041 | int flags, const char *dev_name, void *raw_data) |
3165 | struct vfsmount *mnt) | ||
3166 | { | 3042 | { |
3167 | struct nfs_clone_mount *data = raw_data; | 3043 | struct nfs_clone_mount *data = raw_data; |
3168 | char *export_path; | 3044 | char *export_path; |
3169 | struct vfsmount *root_mnt; | 3045 | struct vfsmount *root_mnt; |
3170 | int error; | 3046 | struct dentry *res; |
3171 | 3047 | ||
3172 | dprintk("--> nfs4_referral_get_sb()\n"); | 3048 | dprintk("--> nfs4_referral_mount()\n"); |
3173 | 3049 | ||
3174 | export_path = data->mnt_path; | 3050 | export_path = data->mnt_path; |
3175 | data->mnt_path = "/"; | 3051 | data->mnt_path = "/"; |
@@ -3178,15 +3054,13 @@ static int nfs4_referral_get_sb(struct file_system_type *fs_type, | |||
3178 | flags, data, data->hostname); | 3054 | flags, data, data->hostname); |
3179 | data->mnt_path = export_path; | 3055 | data->mnt_path = export_path; |
3180 | 3056 | ||
3181 | error = PTR_ERR(root_mnt); | 3057 | res = ERR_CAST(root_mnt); |
3182 | if (IS_ERR(root_mnt)) | 3058 | if (!IS_ERR(root_mnt)) |
3183 | goto out; | 3059 | res = nfs_follow_remote_path(root_mnt, export_path); |
3184 | 3060 | dprintk("<-- nfs4_referral_mount() = %ld%s\n", | |
3185 | error = nfs_follow_remote_path(root_mnt, export_path, mnt); | 3061 | IS_ERR(res) ? PTR_ERR(res) : 0, |
3186 | out: | 3062 | IS_ERR(res) ? " [error]" : ""); |
3187 | dprintk("<-- nfs4_referral_get_sb() = %d%s\n", error, | 3063 | return res; |
3188 | error != 0 ? " [error]" : ""); | ||
3189 | return error; | ||
3190 | } | 3064 | } |
3191 | 3065 | ||
3192 | #endif /* CONFIG_NFS_V4 */ | 3066 | #endif /* CONFIG_NFS_V4 */ |