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.c168
1 files changed, 102 insertions, 66 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 30f939bcb724..b977748553d3 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -107,12 +107,12 @@ struct rpc_program nfsacl_program = {
107#endif /* CONFIG_NFS_V3_ACL */ 107#endif /* CONFIG_NFS_V3_ACL */
108 108
109static void nfs_umount_begin(struct vfsmount *, int); 109static void nfs_umount_begin(struct vfsmount *, int);
110static int nfs_statfs(struct super_block *, struct kstatfs *); 110static int nfs_statfs(struct dentry *, struct kstatfs *);
111static int nfs_show_options(struct seq_file *, struct vfsmount *); 111static int nfs_show_options(struct seq_file *, struct vfsmount *);
112static int nfs_show_stats(struct seq_file *, struct vfsmount *); 112static int nfs_show_stats(struct seq_file *, struct vfsmount *);
113static struct super_block *nfs_get_sb(struct file_system_type *, int, const char *, void *); 113static int nfs_get_sb(struct file_system_type *, int, const char *, void *, struct vfsmount *);
114static struct super_block *nfs_clone_nfs_sb(struct file_system_type *fs_type, 114static int nfs_clone_nfs_sb(struct file_system_type *fs_type,
115 int flags, const char *dev_name, void *raw_data); 115 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
116static void nfs_kill_super(struct super_block *); 116static void nfs_kill_super(struct super_block *);
117 117
118static struct file_system_type nfs_fs_type = { 118static struct file_system_type nfs_fs_type = {
@@ -143,12 +143,12 @@ static struct super_operations nfs_sops = {
143}; 143};
144 144
145#ifdef CONFIG_NFS_V4 145#ifdef CONFIG_NFS_V4
146static struct super_block *nfs4_get_sb(struct file_system_type *fs_type, 146static int nfs4_get_sb(struct file_system_type *fs_type,
147 int flags, const char *dev_name, void *raw_data); 147 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
148static struct super_block *nfs_clone_nfs4_sb(struct file_system_type *fs_type, 148static int nfs_clone_nfs4_sb(struct file_system_type *fs_type,
149 int flags, const char *dev_name, void *raw_data); 149 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
150static struct super_block *nfs_referral_nfs4_sb(struct file_system_type *fs_type, 150static int nfs_referral_nfs4_sb(struct file_system_type *fs_type,
151 int flags, const char *dev_name, void *raw_data); 151 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
152static void nfs4_kill_super(struct super_block *sb); 152static void nfs4_kill_super(struct super_block *sb);
153 153
154static struct file_system_type nfs4_fs_type = { 154static struct file_system_type nfs4_fs_type = {
@@ -263,8 +263,9 @@ void __exit unregister_nfs_fs(void)
263/* 263/*
264 * Deliver file system statistics to userspace 264 * Deliver file system statistics to userspace
265 */ 265 */
266static int nfs_statfs(struct super_block *sb, struct kstatfs *buf) 266static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf)
267{ 267{
268 struct super_block *sb = dentry->d_sb;
268 struct nfs_server *server = NFS_SB(sb); 269 struct nfs_server *server = NFS_SB(sb);
269 unsigned char blockbits; 270 unsigned char blockbits;
270 unsigned long blockres; 271 unsigned long blockres;
@@ -770,15 +771,16 @@ out:
770/* 771/*
771 * Copy an existing superblock and attach revised data 772 * Copy an existing superblock and attach revised data
772 */ 773 */
773static struct super_block *nfs_clone_generic_sb(struct nfs_clone_mount *data, 774static int nfs_clone_generic_sb(struct nfs_clone_mount *data,
774 struct super_block *(*fill_sb)(struct nfs_server *, struct nfs_clone_mount *), 775 struct super_block *(*fill_sb)(struct nfs_server *, struct nfs_clone_mount *),
775 struct nfs_server *(*fill_server)(struct super_block *, struct nfs_clone_mount *)) 776 struct nfs_server *(*fill_server)(struct super_block *, struct nfs_clone_mount *),
777 struct vfsmount *mnt)
776{ 778{
777 struct nfs_server *server; 779 struct nfs_server *server;
778 struct nfs_server *parent = NFS_SB(data->sb); 780 struct nfs_server *parent = NFS_SB(data->sb);
779 struct super_block *sb = ERR_PTR(-EINVAL); 781 struct super_block *sb = ERR_PTR(-EINVAL);
780 void *err = ERR_PTR(-ENOMEM);
781 char *hostname; 782 char *hostname;
783 int error = -ENOMEM;
782 int len; 784 int len;
783 785
784 server = kmalloc(sizeof(struct nfs_server), GFP_KERNEL); 786 server = kmalloc(sizeof(struct nfs_server), GFP_KERNEL);
@@ -791,21 +793,34 @@ static struct super_block *nfs_clone_generic_sb(struct nfs_clone_mount *data,
791 if (server->hostname == NULL) 793 if (server->hostname == NULL)
792 goto free_server; 794 goto free_server;
793 memcpy(server->hostname, hostname, len); 795 memcpy(server->hostname, hostname, len);
794 if (rpciod_up() != 0) 796 error = rpciod_up();
797 if (error != 0)
795 goto free_hostname; 798 goto free_hostname;
796 799
797 sb = fill_sb(server, data); 800 sb = fill_sb(server, data);
798 if (IS_ERR((err = sb)) || sb->s_root) 801 if (IS_ERR(sb)) {
802 error = PTR_ERR(sb);
799 goto kill_rpciod; 803 goto kill_rpciod;
804 }
805
806 if (sb->s_root)
807 goto out_rpciod_down;
800 808
801 server = fill_server(sb, data); 809 server = fill_server(sb, data);
802 if (IS_ERR((err = server))) 810 if (IS_ERR(server)) {
811 error = PTR_ERR(server);
803 goto out_deactivate; 812 goto out_deactivate;
804 return sb; 813 }
814 return simple_set_mnt(mnt, sb);
805out_deactivate: 815out_deactivate:
806 up_write(&sb->s_umount); 816 up_write(&sb->s_umount);
807 deactivate_super(sb); 817 deactivate_super(sb);
808 return (struct super_block *)err; 818 return error;
819out_rpciod_down:
820 rpciod_down();
821 kfree(server->hostname);
822 kfree(server);
823 return simple_set_mnt(mnt, sb);
809kill_rpciod: 824kill_rpciod:
810 rpciod_down(); 825 rpciod_down();
811free_hostname: 826free_hostname:
@@ -813,7 +828,7 @@ free_hostname:
813free_server: 828free_server:
814 kfree(server); 829 kfree(server);
815out_err: 830out_err:
816 return (struct super_block *)err; 831 return error;
817} 832}
818 833
819/* 834/*
@@ -939,8 +954,8 @@ static int nfs_compare_super(struct super_block *sb, void *data)
939 return !nfs_compare_fh(&old->fh, &server->fh); 954 return !nfs_compare_fh(&old->fh, &server->fh);
940} 955}
941 956
942static struct super_block *nfs_get_sb(struct file_system_type *fs_type, 957static int nfs_get_sb(struct file_system_type *fs_type,
943 int flags, const char *dev_name, void *raw_data) 958 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
944{ 959{
945 int error; 960 int error;
946 struct nfs_server *server = NULL; 961 struct nfs_server *server = NULL;
@@ -948,14 +963,14 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
948 struct nfs_fh *root; 963 struct nfs_fh *root;
949 struct nfs_mount_data *data = raw_data; 964 struct nfs_mount_data *data = raw_data;
950 965
951 s = ERR_PTR(-EINVAL); 966 error = -EINVAL;
952 if (data == NULL) { 967 if (data == NULL) {
953 dprintk("%s: missing data argument\n", __FUNCTION__); 968 dprintk("%s: missing data argument\n", __FUNCTION__);
954 goto out_err; 969 goto out_err_noserver;
955 } 970 }
956 if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) { 971 if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) {
957 dprintk("%s: bad mount version\n", __FUNCTION__); 972 dprintk("%s: bad mount version\n", __FUNCTION__);
958 goto out_err; 973 goto out_err_noserver;
959 } 974 }
960 switch (data->version) { 975 switch (data->version) {
961 case 1: 976 case 1:
@@ -967,7 +982,7 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
967 dprintk("%s: mount structure version %d does not support NFSv3\n", 982 dprintk("%s: mount structure version %d does not support NFSv3\n",
968 __FUNCTION__, 983 __FUNCTION__,
969 data->version); 984 data->version);
970 goto out_err; 985 goto out_err_noserver;
971 } 986 }
972 data->root.size = NFS2_FHSIZE; 987 data->root.size = NFS2_FHSIZE;
973 memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE); 988 memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE);
@@ -976,24 +991,24 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
976 dprintk("%s: mount structure version %d does not support strong security\n", 991 dprintk("%s: mount structure version %d does not support strong security\n",
977 __FUNCTION__, 992 __FUNCTION__,
978 data->version); 993 data->version);
979 goto out_err; 994 goto out_err_noserver;
980 } 995 }
981 case 5: 996 case 5:
982 memset(data->context, 0, sizeof(data->context)); 997 memset(data->context, 0, sizeof(data->context));
983 } 998 }
984#ifndef CONFIG_NFS_V3 999#ifndef CONFIG_NFS_V3
985 /* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */ 1000 /* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */
986 s = ERR_PTR(-EPROTONOSUPPORT); 1001 error = -EPROTONOSUPPORT;
987 if (data->flags & NFS_MOUNT_VER3) { 1002 if (data->flags & NFS_MOUNT_VER3) {
988 dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__); 1003 dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__);
989 goto out_err; 1004 goto out_err_noserver;
990 } 1005 }
991#endif /* CONFIG_NFS_V3 */ 1006#endif /* CONFIG_NFS_V3 */
992 1007
993 s = ERR_PTR(-ENOMEM); 1008 error = -ENOMEM;
994 server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL); 1009 server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL);
995 if (!server) 1010 if (!server)
996 goto out_err; 1011 goto out_err_noserver;
997 /* Zero out the NFS state stuff */ 1012 /* Zero out the NFS state stuff */
998 init_nfsv4_state(server); 1013 init_nfsv4_state(server);
999 server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL); 1014 server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL);
@@ -1003,7 +1018,7 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
1003 root->size = data->root.size; 1018 root->size = data->root.size;
1004 else 1019 else
1005 root->size = NFS2_FHSIZE; 1020 root->size = NFS2_FHSIZE;
1006 s = ERR_PTR(-EINVAL); 1021 error = -EINVAL;
1007 if (root->size > sizeof(root->data)) { 1022 if (root->size > sizeof(root->data)) {
1008 dprintk("%s: invalid root filehandle\n", __FUNCTION__); 1023 dprintk("%s: invalid root filehandle\n", __FUNCTION__);
1009 goto out_err; 1024 goto out_err;
@@ -1019,15 +1034,20 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
1019 } 1034 }
1020 1035
1021 /* Fire up rpciod if not yet running */ 1036 /* Fire up rpciod if not yet running */
1022 s = ERR_PTR(rpciod_up()); 1037 error = rpciod_up();
1023 if (IS_ERR(s)) { 1038 if (error < 0) {
1024 dprintk("%s: couldn't start rpciod! Error = %ld\n", 1039 dprintk("%s: couldn't start rpciod! Error = %d\n",
1025 __FUNCTION__, PTR_ERR(s)); 1040 __FUNCTION__, error);
1026 goto out_err; 1041 goto out_err;
1027 } 1042 }
1028 1043
1029 s = sget(fs_type, nfs_compare_super, nfs_set_super, server); 1044 s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
1030 if (IS_ERR(s) || s->s_root) 1045 if (IS_ERR(s)) {
1046 error = PTR_ERR(s);
1047 goto out_err_rpciod;
1048 }
1049
1050 if (s->s_root)
1031 goto out_rpciod_down; 1051 goto out_rpciod_down;
1032 1052
1033 s->s_flags = flags; 1053 s->s_flags = flags;
@@ -1036,15 +1056,22 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
1036 if (error) { 1056 if (error) {
1037 up_write(&s->s_umount); 1057 up_write(&s->s_umount);
1038 deactivate_super(s); 1058 deactivate_super(s);
1039 return ERR_PTR(error); 1059 return error;
1040 } 1060 }
1041 s->s_flags |= MS_ACTIVE; 1061 s->s_flags |= MS_ACTIVE;
1042 return s; 1062 return simple_set_mnt(mnt, s);
1063
1043out_rpciod_down: 1064out_rpciod_down:
1044 rpciod_down(); 1065 rpciod_down();
1066 kfree(server);
1067 return simple_set_mnt(mnt, s);
1068
1069out_err_rpciod:
1070 rpciod_down();
1045out_err: 1071out_err:
1046 kfree(server); 1072 kfree(server);
1047 return s; 1073out_err_noserver:
1074 return error;
1048} 1075}
1049 1076
1050static void nfs_kill_super(struct super_block *s) 1077static void nfs_kill_super(struct super_block *s)
@@ -1083,11 +1110,11 @@ static struct super_block *nfs_clone_sb(struct nfs_server *server, struct nfs_cl
1083 return sb; 1110 return sb;
1084} 1111}
1085 1112
1086static struct super_block *nfs_clone_nfs_sb(struct file_system_type *fs_type, 1113static int nfs_clone_nfs_sb(struct file_system_type *fs_type,
1087 int flags, const char *dev_name, void *raw_data) 1114 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
1088{ 1115{
1089 struct nfs_clone_mount *data = raw_data; 1116 struct nfs_clone_mount *data = raw_data;
1090 return nfs_clone_generic_sb(data, nfs_clone_sb, nfs_clone_server); 1117 return nfs_clone_generic_sb(data, nfs_clone_sb, nfs_clone_server, mnt);
1091} 1118}
1092 1119
1093#ifdef CONFIG_NFS_V4 1120#ifdef CONFIG_NFS_V4
@@ -1266,8 +1293,8 @@ nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen)
1266 return dst; 1293 return dst;
1267} 1294}
1268 1295
1269static struct super_block *nfs4_get_sb(struct file_system_type *fs_type, 1296static int nfs4_get_sb(struct file_system_type *fs_type,
1270 int flags, const char *dev_name, void *raw_data) 1297 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
1271{ 1298{
1272 int error; 1299 int error;
1273 struct nfs_server *server; 1300 struct nfs_server *server;
@@ -1277,16 +1304,16 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type,
1277 1304
1278 if (data == NULL) { 1305 if (data == NULL) {
1279 dprintk("%s: missing data argument\n", __FUNCTION__); 1306 dprintk("%s: missing data argument\n", __FUNCTION__);
1280 return ERR_PTR(-EINVAL); 1307 return -EINVAL;
1281 } 1308 }
1282 if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) { 1309 if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) {
1283 dprintk("%s: bad mount version\n", __FUNCTION__); 1310 dprintk("%s: bad mount version\n", __FUNCTION__);
1284 return ERR_PTR(-EINVAL); 1311 return -EINVAL;
1285 } 1312 }
1286 1313
1287 server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL); 1314 server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL);
1288 if (!server) 1315 if (!server)
1289 return ERR_PTR(-ENOMEM); 1316 return -ENOMEM;
1290 /* Zero out the NFS state stuff */ 1317 /* Zero out the NFS state stuff */
1291 init_nfsv4_state(server); 1318 init_nfsv4_state(server);
1292 server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL); 1319 server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL);
@@ -1308,33 +1335,42 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type,
1308 1335
1309 /* We now require that the mount process passes the remote address */ 1336 /* We now require that the mount process passes the remote address */
1310 if (data->host_addrlen != sizeof(server->addr)) { 1337 if (data->host_addrlen != sizeof(server->addr)) {
1311 s = ERR_PTR(-EINVAL); 1338 error = -EINVAL;
1312 goto out_free; 1339 goto out_free;
1313 } 1340 }
1314 if (copy_from_user(&server->addr, data->host_addr, sizeof(server->addr))) { 1341 if (copy_from_user(&server->addr, data->host_addr, sizeof(server->addr))) {
1315 s = ERR_PTR(-EFAULT); 1342 error = -EFAULT;
1316 goto out_free; 1343 goto out_free;
1317 } 1344 }
1318 if (server->addr.sin_family != AF_INET || 1345 if (server->addr.sin_family != AF_INET ||
1319 server->addr.sin_addr.s_addr == INADDR_ANY) { 1346 server->addr.sin_addr.s_addr == INADDR_ANY) {
1320 dprintk("%s: mount program didn't pass remote IP address!\n", 1347 dprintk("%s: mount program didn't pass remote IP address!\n",
1321 __FUNCTION__); 1348 __FUNCTION__);
1322 s = ERR_PTR(-EINVAL); 1349 error = -EINVAL;
1323 goto out_free; 1350 goto out_free;
1324 } 1351 }
1325 1352
1326 /* Fire up rpciod if not yet running */ 1353 /* Fire up rpciod if not yet running */
1327 s = ERR_PTR(rpciod_up()); 1354 error = rpciod_up();
1328 if (IS_ERR(s)) { 1355 if (error < 0) {
1329 dprintk("%s: couldn't start rpciod! Error = %ld\n", 1356 dprintk("%s: couldn't start rpciod! Error = %d\n",
1330 __FUNCTION__, PTR_ERR(s)); 1357 __FUNCTION__, error);
1331 goto out_free; 1358 goto out_free;
1332 } 1359 }
1333 1360
1334 s = sget(fs_type, nfs4_compare_super, nfs_set_super, server); 1361 s = sget(fs_type, nfs4_compare_super, nfs_set_super, server);
1335 1362
1336 if (IS_ERR(s) || s->s_root) 1363 if (IS_ERR(s)) {
1364 error = PTR_ERR(s);
1337 goto out_free; 1365 goto out_free;
1366 }
1367
1368 if (s->s_root) {
1369 kfree(server->mnt_path);
1370 kfree(server->hostname);
1371 kfree(server);
1372 return simple_set_mnt(mnt, s);
1373 }
1338 1374
1339 s->s_flags = flags; 1375 s->s_flags = flags;
1340 1376
@@ -1342,17 +1378,17 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type,
1342 if (error) { 1378 if (error) {
1343 up_write(&s->s_umount); 1379 up_write(&s->s_umount);
1344 deactivate_super(s); 1380 deactivate_super(s);
1345 return ERR_PTR(error); 1381 return error;
1346 } 1382 }
1347 s->s_flags |= MS_ACTIVE; 1383 s->s_flags |= MS_ACTIVE;
1348 return s; 1384 return simple_set_mnt(mnt, s);
1349out_err: 1385out_err:
1350 s = (struct super_block *)p; 1386 error = PTR_ERR(p);
1351out_free: 1387out_free:
1352 kfree(server->mnt_path); 1388 kfree(server->mnt_path);
1353 kfree(server->hostname); 1389 kfree(server->hostname);
1354 kfree(server); 1390 kfree(server);
1355 return s; 1391 return error;
1356} 1392}
1357 1393
1358static void nfs4_kill_super(struct super_block *sb) 1394static void nfs4_kill_super(struct super_block *sb)
@@ -1430,11 +1466,11 @@ err:
1430 return sb; 1466 return sb;
1431} 1467}
1432 1468
1433static struct super_block *nfs_clone_nfs4_sb(struct file_system_type *fs_type, 1469static int nfs_clone_nfs4_sb(struct file_system_type *fs_type,
1434 int flags, const char *dev_name, void *raw_data) 1470 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
1435{ 1471{
1436 struct nfs_clone_mount *data = raw_data; 1472 struct nfs_clone_mount *data = raw_data;
1437 return nfs_clone_generic_sb(data, nfs4_clone_sb, nfs_clone_server); 1473 return nfs_clone_generic_sb(data, nfs4_clone_sb, nfs_clone_server, mnt);
1438} 1474}
1439 1475
1440static struct super_block *nfs4_referral_sb(struct nfs_server *server, struct nfs_clone_mount *data) 1476static struct super_block *nfs4_referral_sb(struct nfs_server *server, struct nfs_clone_mount *data)
@@ -1487,11 +1523,11 @@ out_err:
1487 return (struct nfs_server *)err; 1523 return (struct nfs_server *)err;
1488} 1524}
1489 1525
1490static struct super_block *nfs_referral_nfs4_sb(struct file_system_type *fs_type, 1526static int nfs_referral_nfs4_sb(struct file_system_type *fs_type,
1491 int flags, const char *dev_name, void *raw_data) 1527 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
1492{ 1528{
1493 struct nfs_clone_mount *data = raw_data; 1529 struct nfs_clone_mount *data = raw_data;
1494 return nfs_clone_generic_sb(data, nfs4_referral_sb, nfs4_referral_server); 1530 return nfs_clone_generic_sb(data, nfs4_referral_sb, nfs4_referral_server, mnt);
1495} 1531}
1496 1532
1497#endif 1533#endif