aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/super.c
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /fs/nfs/super.c
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'fs/nfs/super.c')
-rw-r--r--fs/nfs/super.c148
1 files changed, 119 insertions, 29 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 90be551b80c1..b4148fc00f9f 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -48,6 +48,7 @@
48#include <linux/vfs.h> 48#include <linux/vfs.h>
49#include <linux/inet.h> 49#include <linux/inet.h>
50#include <linux/in6.h> 50#include <linux/in6.h>
51#include <linux/slab.h>
51#include <net/ipv6.h> 52#include <net/ipv6.h>
52#include <linux/netdevice.h> 53#include <linux/netdevice.h>
53#include <linux/nfs_xdr.h> 54#include <linux/nfs_xdr.h>
@@ -175,14 +176,16 @@ static const match_table_t nfs_mount_option_tokens = {
175}; 176};
176 177
177enum { 178enum {
178 Opt_xprt_udp, Opt_xprt_tcp, Opt_xprt_rdma, 179 Opt_xprt_udp, Opt_xprt_udp6, Opt_xprt_tcp, Opt_xprt_tcp6, Opt_xprt_rdma,
179 180
180 Opt_xprt_err 181 Opt_xprt_err
181}; 182};
182 183
183static const match_table_t nfs_xprt_protocol_tokens = { 184static const match_table_t nfs_xprt_protocol_tokens = {
184 { Opt_xprt_udp, "udp" }, 185 { Opt_xprt_udp, "udp" },
186 { Opt_xprt_udp6, "udp6" },
185 { Opt_xprt_tcp, "tcp" }, 187 { Opt_xprt_tcp, "tcp" },
188 { Opt_xprt_tcp6, "tcp6" },
186 { Opt_xprt_rdma, "rdma" }, 189 { Opt_xprt_rdma, "rdma" },
187 190
188 { Opt_xprt_err, NULL } 191 { Opt_xprt_err, NULL }
@@ -241,6 +244,7 @@ static int nfs_show_stats(struct seq_file *, struct vfsmount *);
241static int nfs_get_sb(struct file_system_type *, int, const char *, void *, struct vfsmount *); 244static int nfs_get_sb(struct file_system_type *, int, const char *, void *, struct vfsmount *);
242static int nfs_xdev_get_sb(struct file_system_type *fs_type, 245static int nfs_xdev_get_sb(struct file_system_type *fs_type,
243 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); 246 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
247static void nfs_put_super(struct super_block *);
244static void nfs_kill_super(struct super_block *); 248static void nfs_kill_super(struct super_block *);
245static int nfs_remount(struct super_block *sb, int *flags, char *raw_data); 249static int nfs_remount(struct super_block *sb, int *flags, char *raw_data);
246 250
@@ -264,6 +268,7 @@ static const struct super_operations nfs_sops = {
264 .alloc_inode = nfs_alloc_inode, 268 .alloc_inode = nfs_alloc_inode,
265 .destroy_inode = nfs_destroy_inode, 269 .destroy_inode = nfs_destroy_inode,
266 .write_inode = nfs_write_inode, 270 .write_inode = nfs_write_inode,
271 .put_super = nfs_put_super,
267 .statfs = nfs_statfs, 272 .statfs = nfs_statfs,
268 .clear_inode = nfs_clear_inode, 273 .clear_inode = nfs_clear_inode,
269 .umount_begin = nfs_umount_begin, 274 .umount_begin = nfs_umount_begin,
@@ -333,6 +338,7 @@ static const struct super_operations nfs4_sops = {
333 .alloc_inode = nfs_alloc_inode, 338 .alloc_inode = nfs_alloc_inode,
334 .destroy_inode = nfs_destroy_inode, 339 .destroy_inode = nfs_destroy_inode,
335 .write_inode = nfs_write_inode, 340 .write_inode = nfs_write_inode,
341 .put_super = nfs_put_super,
336 .statfs = nfs_statfs, 342 .statfs = nfs_statfs,
337 .clear_inode = nfs4_clear_inode, 343 .clear_inode = nfs4_clear_inode,
338 .umount_begin = nfs_umount_begin, 344 .umount_begin = nfs_umount_begin,
@@ -492,6 +498,45 @@ static const char *nfs_pseudoflavour_to_name(rpc_authflavor_t flavour)
492 return sec_flavours[i].str; 498 return sec_flavours[i].str;
493} 499}
494 500
501static void nfs_show_mountd_netid(struct seq_file *m, struct nfs_server *nfss,
502 int showdefaults)
503{
504 struct sockaddr *sap = (struct sockaddr *) &nfss->mountd_address;
505
506 seq_printf(m, ",mountproto=");
507 switch (sap->sa_family) {
508 case AF_INET:
509 switch (nfss->mountd_protocol) {
510 case IPPROTO_UDP:
511 seq_printf(m, RPCBIND_NETID_UDP);
512 break;
513 case IPPROTO_TCP:
514 seq_printf(m, RPCBIND_NETID_TCP);
515 break;
516 default:
517 if (showdefaults)
518 seq_printf(m, "auto");
519 }
520 break;
521 case AF_INET6:
522 switch (nfss->mountd_protocol) {
523 case IPPROTO_UDP:
524 seq_printf(m, RPCBIND_NETID_UDP6);
525 break;
526 case IPPROTO_TCP:
527 seq_printf(m, RPCBIND_NETID_TCP6);
528 break;
529 default:
530 if (showdefaults)
531 seq_printf(m, "auto");
532 }
533 break;
534 default:
535 if (showdefaults)
536 seq_printf(m, "auto");
537 }
538}
539
495static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss, 540static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss,
496 int showdefaults) 541 int showdefaults)
497{ 542{
@@ -505,7 +550,7 @@ static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss,
505 } 550 }
506 case AF_INET6: { 551 case AF_INET6: {
507 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; 552 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
508 seq_printf(m, ",mountaddr=%pI6", &sin6->sin6_addr); 553 seq_printf(m, ",mountaddr=%pI6c", &sin6->sin6_addr);
509 break; 554 break;
510 } 555 }
511 default: 556 default:
@@ -518,17 +563,7 @@ static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss,
518 if (nfss->mountd_port || showdefaults) 563 if (nfss->mountd_port || showdefaults)
519 seq_printf(m, ",mountport=%u", nfss->mountd_port); 564 seq_printf(m, ",mountport=%u", nfss->mountd_port);
520 565
521 switch (nfss->mountd_protocol) { 566 nfs_show_mountd_netid(m, nfss, showdefaults);
522 case IPPROTO_UDP:
523 seq_printf(m, ",mountproto=udp");
524 break;
525 case IPPROTO_TCP:
526 seq_printf(m, ",mountproto=tcp");
527 break;
528 default:
529 if (showdefaults)
530 seq_printf(m, ",mountproto=auto");
531 }
532} 567}
533 568
534/* 569/*
@@ -578,7 +613,7 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
578 seq_puts(m, nfs_infop->nostr); 613 seq_puts(m, nfs_infop->nostr);
579 } 614 }
580 seq_printf(m, ",proto=%s", 615 seq_printf(m, ",proto=%s",
581 rpc_peeraddr2str(nfss->client, RPC_DISPLAY_PROTO)); 616 rpc_peeraddr2str(nfss->client, RPC_DISPLAY_NETID));
582 if (version == 4) { 617 if (version == 4) {
583 if (nfss->port != NFS_PORT) 618 if (nfss->port != NFS_PORT)
584 seq_printf(m, ",port=%u", nfss->port); 619 seq_printf(m, ",port=%u", nfss->port);
@@ -714,8 +749,6 @@ static void nfs_umount_begin(struct super_block *sb)
714 struct nfs_server *server; 749 struct nfs_server *server;
715 struct rpc_clnt *rpc; 750 struct rpc_clnt *rpc;
716 751
717 lock_kernel();
718
719 server = NFS_SB(sb); 752 server = NFS_SB(sb);
720 /* -EIO all pending I/O */ 753 /* -EIO all pending I/O */
721 rpc = server->client_acl; 754 rpc = server->client_acl;
@@ -724,8 +757,6 @@ static void nfs_umount_begin(struct super_block *sb)
724 rpc = server->client; 757 rpc = server->client;
725 if (!IS_ERR(rpc)) 758 if (!IS_ERR(rpc))
726 rpc_killall_tasks(rpc); 759 rpc_killall_tasks(rpc);
727
728 unlock_kernel();
729} 760}
730 761
731static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(unsigned int version) 762static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(unsigned int version)
@@ -734,8 +765,6 @@ static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(unsigned int ve
734 765
735 data = kzalloc(sizeof(*data), GFP_KERNEL); 766 data = kzalloc(sizeof(*data), GFP_KERNEL);
736 if (data) { 767 if (data) {
737 data->rsize = NFS_MAX_FILE_IO_SIZE;
738 data->wsize = NFS_MAX_FILE_IO_SIZE;
739 data->acregmin = NFS_DEF_ACREGMIN; 768 data->acregmin = NFS_DEF_ACREGMIN;
740 data->acregmax = NFS_DEF_ACREGMAX; 769 data->acregmax = NFS_DEF_ACREGMAX;
741 data->acdirmin = NFS_DEF_ACDIRMIN; 770 data->acdirmin = NFS_DEF_ACDIRMIN;
@@ -887,6 +916,8 @@ static int nfs_parse_mount_options(char *raw,
887{ 916{
888 char *p, *string, *secdata; 917 char *p, *string, *secdata;
889 int rc, sloppy = 0, invalid_option = 0; 918 int rc, sloppy = 0, invalid_option = 0;
919 unsigned short protofamily = AF_UNSPEC;
920 unsigned short mountfamily = AF_UNSPEC;
890 921
891 if (!raw) { 922 if (!raw) {
892 dfprintk(MOUNT, "NFS: mount options string was NULL.\n"); 923 dfprintk(MOUNT, "NFS: mount options string was NULL.\n");
@@ -1232,12 +1263,17 @@ static int nfs_parse_mount_options(char *raw,
1232 token = match_token(string, 1263 token = match_token(string,
1233 nfs_xprt_protocol_tokens, args); 1264 nfs_xprt_protocol_tokens, args);
1234 1265
1266 protofamily = AF_INET;
1235 switch (token) { 1267 switch (token) {
1268 case Opt_xprt_udp6:
1269 protofamily = AF_INET6;
1236 case Opt_xprt_udp: 1270 case Opt_xprt_udp:
1237 mnt->flags &= ~NFS_MOUNT_TCP; 1271 mnt->flags &= ~NFS_MOUNT_TCP;
1238 mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP; 1272 mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP;
1239 kfree(string); 1273 kfree(string);
1240 break; 1274 break;
1275 case Opt_xprt_tcp6:
1276 protofamily = AF_INET6;
1241 case Opt_xprt_tcp: 1277 case Opt_xprt_tcp:
1242 mnt->flags |= NFS_MOUNT_TCP; 1278 mnt->flags |= NFS_MOUNT_TCP;
1243 mnt->nfs_server.protocol = XPRT_TRANSPORT_TCP; 1279 mnt->nfs_server.protocol = XPRT_TRANSPORT_TCP;
@@ -1265,10 +1301,15 @@ static int nfs_parse_mount_options(char *raw,
1265 nfs_xprt_protocol_tokens, args); 1301 nfs_xprt_protocol_tokens, args);
1266 kfree(string); 1302 kfree(string);
1267 1303
1304 mountfamily = AF_INET;
1268 switch (token) { 1305 switch (token) {
1306 case Opt_xprt_udp6:
1307 mountfamily = AF_INET6;
1269 case Opt_xprt_udp: 1308 case Opt_xprt_udp:
1270 mnt->mount_server.protocol = XPRT_TRANSPORT_UDP; 1309 mnt->mount_server.protocol = XPRT_TRANSPORT_UDP;
1271 break; 1310 break;
1311 case Opt_xprt_tcp6:
1312 mountfamily = AF_INET6;
1272 case Opt_xprt_tcp: 1313 case Opt_xprt_tcp:
1273 mnt->mount_server.protocol = XPRT_TRANSPORT_TCP; 1314 mnt->mount_server.protocol = XPRT_TRANSPORT_TCP;
1274 break; 1315 break;
@@ -1367,8 +1408,33 @@ static int nfs_parse_mount_options(char *raw,
1367 if (!sloppy && invalid_option) 1408 if (!sloppy && invalid_option)
1368 return 0; 1409 return 0;
1369 1410
1411 /*
1412 * verify that any proto=/mountproto= options match the address
1413 * familiies in the addr=/mountaddr= options.
1414 */
1415 if (protofamily != AF_UNSPEC &&
1416 protofamily != mnt->nfs_server.address.ss_family)
1417 goto out_proto_mismatch;
1418
1419 if (mountfamily != AF_UNSPEC) {
1420 if (mnt->mount_server.addrlen) {
1421 if (mountfamily != mnt->mount_server.address.ss_family)
1422 goto out_mountproto_mismatch;
1423 } else {
1424 if (mountfamily != mnt->nfs_server.address.ss_family)
1425 goto out_mountproto_mismatch;
1426 }
1427 }
1428
1370 return 1; 1429 return 1;
1371 1430
1431out_mountproto_mismatch:
1432 printk(KERN_INFO "NFS: mount server address does not match mountproto= "
1433 "option\n");
1434 return 0;
1435out_proto_mismatch:
1436 printk(KERN_INFO "NFS: server address does not match proto= option\n");
1437 return 0;
1372out_invalid_address: 1438out_invalid_address:
1373 printk(KERN_INFO "NFS: bad IP address specified: %s\n", p); 1439 printk(KERN_INFO "NFS: bad IP address specified: %s\n", p);
1374 return 0; 1440 return 0;
@@ -1881,7 +1947,6 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data)
1881 if (data == NULL) 1947 if (data == NULL)
1882 return -ENOMEM; 1948 return -ENOMEM;
1883 1949
1884 lock_kernel();
1885 /* fill out struct with values from existing mount */ 1950 /* fill out struct with values from existing mount */
1886 data->flags = nfss->flags; 1951 data->flags = nfss->flags;
1887 data->rsize = nfss->rsize; 1952 data->rsize = nfss->rsize;
@@ -1907,7 +1972,6 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data)
1907 error = nfs_compare_remount_data(nfss, data); 1972 error = nfs_compare_remount_data(nfss, data);
1908out: 1973out:
1909 kfree(data); 1974 kfree(data);
1910 unlock_kernel();
1911 return error; 1975 return error;
1912} 1976}
1913 1977
@@ -2123,6 +2187,7 @@ static int nfs_get_sb(struct file_system_type *fs_type,
2123 if (data->version == 4) { 2187 if (data->version == 4) {
2124 error = nfs4_try_mount(flags, dev_name, data, mnt); 2188 error = nfs4_try_mount(flags, dev_name, data, mnt);
2125 kfree(data->client_address); 2189 kfree(data->client_address);
2190 kfree(data->nfs_server.export_path);
2126 goto out; 2191 goto out;
2127 } 2192 }
2128#endif /* CONFIG_NFS_V4 */ 2193#endif /* CONFIG_NFS_V4 */
@@ -2151,7 +2216,7 @@ static int nfs_get_sb(struct file_system_type *fs_type,
2151 } else { 2216 } else {
2152 error = nfs_bdi_register(server); 2217 error = nfs_bdi_register(server);
2153 if (error) 2218 if (error)
2154 goto error_splat_super; 2219 goto error_splat_bdi;
2155 } 2220 }
2156 2221
2157 if (!s->s_root) { 2222 if (!s->s_root) {
@@ -2193,11 +2258,25 @@ out_err_nosb:
2193error_splat_root: 2258error_splat_root:
2194 dput(mntroot); 2259 dput(mntroot);
2195error_splat_super: 2260error_splat_super:
2261 if (server && !s->s_root)
2262 bdi_unregister(&server->backing_dev_info);
2263error_splat_bdi:
2196 deactivate_locked_super(s); 2264 deactivate_locked_super(s);
2197 goto out; 2265 goto out;
2198} 2266}
2199 2267
2200/* 2268/*
2269 * Ensure that we unregister the bdi before kill_anon_super
2270 * releases the device name
2271 */
2272static void nfs_put_super(struct super_block *s)
2273{
2274 struct nfs_server *server = NFS_SB(s);
2275
2276 bdi_unregister(&server->backing_dev_info);
2277}
2278
2279/*
2201 * Destroy an NFS2/3 superblock 2280 * Destroy an NFS2/3 superblock
2202 */ 2281 */
2203static void nfs_kill_super(struct super_block *s) 2282static void nfs_kill_super(struct super_block *s)
@@ -2205,7 +2284,6 @@ static void nfs_kill_super(struct super_block *s)
2205 struct nfs_server *server = NFS_SB(s); 2284 struct nfs_server *server = NFS_SB(s);
2206 2285
2207 kill_anon_super(s); 2286 kill_anon_super(s);
2208 bdi_unregister(&server->backing_dev_info);
2209 nfs_fscache_release_super_cookie(s); 2287 nfs_fscache_release_super_cookie(s);
2210 nfs_free_server(server); 2288 nfs_free_server(server);
2211} 2289}
@@ -2253,7 +2331,7 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags,
2253 } else { 2331 } else {
2254 error = nfs_bdi_register(server); 2332 error = nfs_bdi_register(server);
2255 if (error) 2333 if (error)
2256 goto error_splat_super; 2334 goto error_splat_bdi;
2257 } 2335 }
2258 2336
2259 if (!s->s_root) { 2337 if (!s->s_root) {
@@ -2290,6 +2368,9 @@ out_err_noserver:
2290 return error; 2368 return error;
2291 2369
2292error_splat_super: 2370error_splat_super:
2371 if (server && !s->s_root)
2372 bdi_unregister(&server->backing_dev_info);
2373error_splat_bdi:
2293 deactivate_locked_super(s); 2374 deactivate_locked_super(s);
2294 dprintk("<-- nfs_xdev_get_sb() = %d [splat]\n", error); 2375 dprintk("<-- nfs_xdev_get_sb() = %d [splat]\n", error);
2295 return error; 2376 return error;
@@ -2505,7 +2586,7 @@ static int nfs4_remote_get_sb(struct file_system_type *fs_type,
2505 } else { 2586 } else {
2506 error = nfs_bdi_register(server); 2587 error = nfs_bdi_register(server);
2507 if (error) 2588 if (error)
2508 goto error_splat_super; 2589 goto error_splat_bdi;
2509 } 2590 }
2510 2591
2511 if (!s->s_root) { 2592 if (!s->s_root) {
@@ -2543,6 +2624,9 @@ out_free:
2543error_splat_root: 2624error_splat_root:
2544 dput(mntroot); 2625 dput(mntroot);
2545error_splat_super: 2626error_splat_super:
2627 if (server && !s->s_root)
2628 bdi_unregister(&server->backing_dev_info);
2629error_splat_bdi:
2546 deactivate_locked_super(s); 2630 deactivate_locked_super(s);
2547 goto out; 2631 goto out;
2548} 2632}
@@ -2574,7 +2658,7 @@ static void nfs_fix_devname(const struct path *path, struct vfsmount *mnt)
2574 devname = nfs_path(path->mnt->mnt_devname, 2658 devname = nfs_path(path->mnt->mnt_devname,
2575 path->mnt->mnt_root, path->dentry, 2659 path->mnt->mnt_root, path->dentry,
2576 page, PAGE_SIZE); 2660 page, PAGE_SIZE);
2577 if (devname == NULL) 2661 if (IS_ERR(devname))
2578 goto out_freepage; 2662 goto out_freepage;
2579 tmp = kstrdup(devname, GFP_KERNEL); 2663 tmp = kstrdup(devname, GFP_KERNEL);
2580 if (tmp == NULL) 2664 if (tmp == NULL)
@@ -2738,7 +2822,7 @@ static int nfs4_xdev_get_sb(struct file_system_type *fs_type, int flags,
2738 } else { 2822 } else {
2739 error = nfs_bdi_register(server); 2823 error = nfs_bdi_register(server);
2740 if (error) 2824 if (error)
2741 goto error_splat_super; 2825 goto error_splat_bdi;
2742 } 2826 }
2743 2827
2744 if (!s->s_root) { 2828 if (!s->s_root) {
@@ -2774,6 +2858,9 @@ out_err_noserver:
2774 return error; 2858 return error;
2775 2859
2776error_splat_super: 2860error_splat_super:
2861 if (server && !s->s_root)
2862 bdi_unregister(&server->backing_dev_info);
2863error_splat_bdi:
2777 deactivate_locked_super(s); 2864 deactivate_locked_super(s);
2778 dprintk("<-- nfs4_xdev_get_sb() = %d [splat]\n", error); 2865 dprintk("<-- nfs4_xdev_get_sb() = %d [splat]\n", error);
2779 return error; 2866 return error;
@@ -2820,7 +2907,7 @@ static int nfs4_remote_referral_get_sb(struct file_system_type *fs_type,
2820 } else { 2907 } else {
2821 error = nfs_bdi_register(server); 2908 error = nfs_bdi_register(server);
2822 if (error) 2909 if (error)
2823 goto error_splat_super; 2910 goto error_splat_bdi;
2824 } 2911 }
2825 2912
2826 if (!s->s_root) { 2913 if (!s->s_root) {
@@ -2856,6 +2943,9 @@ out_err_noserver:
2856 return error; 2943 return error;
2857 2944
2858error_splat_super: 2945error_splat_super:
2946 if (server && !s->s_root)
2947 bdi_unregister(&server->backing_dev_info);
2948error_splat_bdi:
2859 deactivate_locked_super(s); 2949 deactivate_locked_super(s);
2860 dprintk("<-- nfs4_referral_get_sb() = %d [splat]\n", error); 2950 dprintk("<-- nfs4_referral_get_sb() = %d [splat]\n", error);
2861 return error; 2951 return error;