diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-04 22:36:58 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-04 22:36:58 -0400 |
commit | 7e20ef030dde0e52dd5a57220ee82fa9facbea4e (patch) | |
tree | 5006db4f85a2d7be2777748aaff2966e79dddc6f /fs | |
parent | a3d52136ee8f7399859f9a0824470fd49b1d1a00 (diff) | |
parent | 07d939677166cc4f000c767196872a9becc2697b (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6: (49 commits)
[SCTP]: Set assoc_id correctly during INIT collision.
[SCTP]: Re-order SCTP initializations to avoid race with sctp_rcv()
[SCTP]: Fix the SO_REUSEADDR handling to be similar to TCP.
[SCTP]: Verify all destination ports in sctp_connectx.
[XFRM] SPD info TLV aggregation
[XFRM] SAD info TLV aggregationx
[AF_RXRPC]: Sort out MTU handling.
[AF_IUCV/IUCV] : Add missing section annotations
[AF_IUCV]: Implementation of a skb backlog queue
[NETLINK]: Remove bogus BUG_ON
[IPV6]: Some cleanups in include/net/ipv6.h
[TCP]: zero out rx_opt in tcp_disconnect()
[BNX2]: Fix TSO problem with small MSS.
[NET]: Rework dev_base via list_head (v3)
[TCP] Highspeed: Limited slow-start is nowadays in tcp_slow_start
[BNX2]: Update version and reldate.
[BNX2]: Print bus information for PCIE devices.
[BNX2]: Add 1-shot MSI handler for 5709.
[BNX2]: Restructure PHY event handling.
[BNX2]: Add indirect spinlock.
...
Diffstat (limited to 'fs')
-rw-r--r-- | fs/Kconfig | 1 | ||||
-rw-r--r-- | fs/afs/Makefile | 2 | ||||
-rw-r--r-- | fs/afs/callback.c | 2 | ||||
-rw-r--r-- | fs/afs/cmservice.c | 1 | ||||
-rw-r--r-- | fs/afs/fsclient.c | 3 | ||||
-rw-r--r-- | fs/afs/internal.h | 7 | ||||
-rw-r--r-- | fs/afs/main.c | 2 | ||||
-rw-r--r-- | fs/afs/netdevices.c | 68 | ||||
-rw-r--r-- | fs/afs/super.c | 100 | ||||
-rw-r--r-- | fs/afs/use-rtnetlink.c | 473 | ||||
-rw-r--r-- | fs/afs/vlocation.c | 2 |
11 files changed, 121 insertions, 540 deletions
diff --git a/fs/Kconfig b/fs/Kconfig index a42f767dcdd5..e33c08924572 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
@@ -2020,7 +2020,6 @@ config AFS_FS | |||
2020 | tristate "Andrew File System support (AFS) (EXPERIMENTAL)" | 2020 | tristate "Andrew File System support (AFS) (EXPERIMENTAL)" |
2021 | depends on INET && EXPERIMENTAL | 2021 | depends on INET && EXPERIMENTAL |
2022 | select AF_RXRPC | 2022 | select AF_RXRPC |
2023 | select KEYS | ||
2024 | help | 2023 | help |
2025 | If you say Y here, you will get an experimental Andrew File System | 2024 | If you say Y here, you will get an experimental Andrew File System |
2026 | driver. It currently only supports unsecured read-only AFS access. | 2025 | driver. It currently only supports unsecured read-only AFS access. |
diff --git a/fs/afs/Makefile b/fs/afs/Makefile index 01545eb1d872..cf83e5d63512 100644 --- a/fs/afs/Makefile +++ b/fs/afs/Makefile | |||
@@ -18,7 +18,7 @@ kafs-objs := \ | |||
18 | security.o \ | 18 | security.o \ |
19 | server.o \ | 19 | server.o \ |
20 | super.o \ | 20 | super.o \ |
21 | use-rtnetlink.o \ | 21 | netdevices.o \ |
22 | vlclient.o \ | 22 | vlclient.o \ |
23 | vlocation.o \ | 23 | vlocation.o \ |
24 | vnode.o \ | 24 | vnode.o \ |
diff --git a/fs/afs/callback.c b/fs/afs/callback.c index 639399f0ab6f..9bdbf36a9aa9 100644 --- a/fs/afs/callback.c +++ b/fs/afs/callback.c | |||
@@ -468,7 +468,7 @@ int __init afs_callback_update_init(void) | |||
468 | /* | 468 | /* |
469 | * shut down the callback update process | 469 | * shut down the callback update process |
470 | */ | 470 | */ |
471 | void __exit afs_callback_update_kill(void) | 471 | void afs_callback_update_kill(void) |
472 | { | 472 | { |
473 | destroy_workqueue(afs_callback_update_worker); | 473 | destroy_workqueue(afs_callback_update_worker); |
474 | } | 474 | } |
diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c index 6685f4cbccb3..d5b2ad6575bc 100644 --- a/fs/afs/cmservice.c +++ b/fs/afs/cmservice.c | |||
@@ -443,6 +443,7 @@ static void SRXAFSCB_GetCapabilities(struct work_struct *work) | |||
443 | reply.ia.netmask[loop] = ifs[loop].netmask.s_addr; | 443 | reply.ia.netmask[loop] = ifs[loop].netmask.s_addr; |
444 | reply.ia.mtu[loop] = htonl(ifs[loop].mtu); | 444 | reply.ia.mtu[loop] = htonl(ifs[loop].mtu); |
445 | } | 445 | } |
446 | kfree(ifs); | ||
446 | } | 447 | } |
447 | 448 | ||
448 | reply.cap.capcount = htonl(1); | 449 | reply.cap.capcount = htonl(1); |
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c index 2393d2a08d79..e54e6c2ad343 100644 --- a/fs/afs/fsclient.c +++ b/fs/afs/fsclient.c | |||
@@ -266,7 +266,8 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call, | |||
266 | call->unmarshall++; | 266 | call->unmarshall++; |
267 | 267 | ||
268 | if (call->count < PAGE_SIZE) { | 268 | if (call->count < PAGE_SIZE) { |
269 | buffer = kmap_atomic(call->reply3, KM_USER0); | 269 | page = call->reply3; |
270 | buffer = kmap_atomic(page, KM_USER0); | ||
270 | memset(buffer + PAGE_SIZE - call->count, 0, | 271 | memset(buffer + PAGE_SIZE - call->count, 0, |
271 | call->count); | 272 | call->count); |
272 | kunmap_atomic(buffer, KM_USER0); | 273 | kunmap_atomic(buffer, KM_USER0); |
diff --git a/fs/afs/internal.h b/fs/afs/internal.h index 34665f7d7a19..d90c158cd934 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h | |||
@@ -349,7 +349,6 @@ struct afs_permits { | |||
349 | * record of one of a system's set of network interfaces | 349 | * record of one of a system's set of network interfaces |
350 | */ | 350 | */ |
351 | struct afs_interface { | 351 | struct afs_interface { |
352 | unsigned index; /* interface index */ | ||
353 | struct in_addr address; /* IPv4 address bound to interface */ | 352 | struct in_addr address; /* IPv4 address bound to interface */ |
354 | struct in_addr netmask; /* netmask applied to address */ | 353 | struct in_addr netmask; /* netmask applied to address */ |
355 | unsigned mtu; /* MTU of interface */ | 354 | unsigned mtu; /* MTU of interface */ |
@@ -392,7 +391,7 @@ extern void afs_give_up_callback(struct afs_vnode *); | |||
392 | extern void afs_dispatch_give_up_callbacks(struct work_struct *); | 391 | extern void afs_dispatch_give_up_callbacks(struct work_struct *); |
393 | extern void afs_flush_callback_breaks(struct afs_server *); | 392 | extern void afs_flush_callback_breaks(struct afs_server *); |
394 | extern int __init afs_callback_update_init(void); | 393 | extern int __init afs_callback_update_init(void); |
395 | extern void __exit afs_callback_update_kill(void); | 394 | extern void afs_callback_update_kill(void); |
396 | 395 | ||
397 | /* | 396 | /* |
398 | * cell.c | 397 | * cell.c |
@@ -564,7 +563,7 @@ extern void afs_fs_exit(void); | |||
564 | * use-rtnetlink.c | 563 | * use-rtnetlink.c |
565 | */ | 564 | */ |
566 | extern int afs_get_ipv4_interfaces(struct afs_interface *, size_t, bool); | 565 | extern int afs_get_ipv4_interfaces(struct afs_interface *, size_t, bool); |
567 | extern int afs_get_MAC_address(u8 [6]); | 566 | extern int afs_get_MAC_address(u8 *, size_t); |
568 | 567 | ||
569 | /* | 568 | /* |
570 | * vlclient.c | 569 | * vlclient.c |
@@ -591,7 +590,7 @@ extern struct afs_vlocation *afs_vlocation_lookup(struct afs_cell *, | |||
591 | struct key *, | 590 | struct key *, |
592 | const char *, size_t); | 591 | const char *, size_t); |
593 | extern void afs_put_vlocation(struct afs_vlocation *); | 592 | extern void afs_put_vlocation(struct afs_vlocation *); |
594 | extern void __exit afs_vlocation_purge(void); | 593 | extern void afs_vlocation_purge(void); |
595 | 594 | ||
596 | /* | 595 | /* |
597 | * vnode.c | 596 | * vnode.c |
diff --git a/fs/afs/main.c b/fs/afs/main.c index 40c2704e7557..80ec6fd19a73 100644 --- a/fs/afs/main.c +++ b/fs/afs/main.c | |||
@@ -54,7 +54,7 @@ static int __init afs_get_client_UUID(void) | |||
54 | 54 | ||
55 | /* read the MAC address of one of the external interfaces and construct | 55 | /* read the MAC address of one of the external interfaces and construct |
56 | * a UUID from it */ | 56 | * a UUID from it */ |
57 | ret = afs_get_MAC_address(afs_uuid.node); | 57 | ret = afs_get_MAC_address(afs_uuid.node, sizeof(afs_uuid.node)); |
58 | if (ret < 0) | 58 | if (ret < 0) |
59 | return ret; | 59 | return ret; |
60 | 60 | ||
diff --git a/fs/afs/netdevices.c b/fs/afs/netdevices.c new file mode 100644 index 000000000000..fc27d4b52e5f --- /dev/null +++ b/fs/afs/netdevices.c | |||
@@ -0,0 +1,68 @@ | |||
1 | /* AFS network device helpers | ||
2 | * | ||
3 | * Copyright (c) 2007 Patrick McHardy <kaber@trash.net> | ||
4 | */ | ||
5 | |||
6 | #include <linux/string.h> | ||
7 | #include <linux/rtnetlink.h> | ||
8 | #include <linux/inetdevice.h> | ||
9 | #include <linux/netdevice.h> | ||
10 | #include <linux/if_arp.h> | ||
11 | #include "internal.h" | ||
12 | |||
13 | /* | ||
14 | * get a MAC address from a random ethernet interface that has a real one | ||
15 | * - the buffer will normally be 6 bytes in size | ||
16 | */ | ||
17 | int afs_get_MAC_address(u8 *mac, size_t maclen) | ||
18 | { | ||
19 | struct net_device *dev; | ||
20 | int ret = -ENODEV; | ||
21 | |||
22 | if (maclen != ETH_ALEN) | ||
23 | BUG(); | ||
24 | |||
25 | rtnl_lock(); | ||
26 | dev = __dev_getfirstbyhwtype(ARPHRD_ETHER); | ||
27 | if (dev) { | ||
28 | memcpy(mac, dev->dev_addr, maclen); | ||
29 | ret = 0; | ||
30 | } | ||
31 | rtnl_unlock(); | ||
32 | return ret; | ||
33 | } | ||
34 | |||
35 | /* | ||
36 | * get a list of this system's interface IPv4 addresses, netmasks and MTUs | ||
37 | * - maxbufs must be at least 1 | ||
38 | * - returns the number of interface records in the buffer | ||
39 | */ | ||
40 | int afs_get_ipv4_interfaces(struct afs_interface *bufs, size_t maxbufs, | ||
41 | bool wantloopback) | ||
42 | { | ||
43 | struct net_device *dev; | ||
44 | struct in_device *idev; | ||
45 | int n = 0; | ||
46 | |||
47 | ASSERT(maxbufs > 0); | ||
48 | |||
49 | rtnl_lock(); | ||
50 | for_each_netdev(dev) { | ||
51 | if (dev->type == ARPHRD_LOOPBACK && !wantloopback) | ||
52 | continue; | ||
53 | idev = __in_dev_get_rtnl(dev); | ||
54 | if (!idev) | ||
55 | continue; | ||
56 | for_primary_ifa(idev) { | ||
57 | bufs[n].address.s_addr = ifa->ifa_address; | ||
58 | bufs[n].netmask.s_addr = ifa->ifa_mask; | ||
59 | bufs[n].mtu = dev->mtu; | ||
60 | n++; | ||
61 | if (n >= maxbufs) | ||
62 | goto out; | ||
63 | } endfor_ifa(idev); | ||
64 | } | ||
65 | out: | ||
66 | rtnl_unlock(); | ||
67 | return n; | ||
68 | } | ||
diff --git a/fs/afs/super.c b/fs/afs/super.c index cebd03c91f57..41173f81ac47 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/fs.h> | 21 | #include <linux/fs.h> |
22 | #include <linux/pagemap.h> | 22 | #include <linux/pagemap.h> |
23 | #include <linux/parser.h> | ||
23 | #include "internal.h" | 24 | #include "internal.h" |
24 | 25 | ||
25 | #define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */ | 26 | #define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */ |
@@ -42,7 +43,7 @@ struct file_system_type afs_fs_type = { | |||
42 | .name = "afs", | 43 | .name = "afs", |
43 | .get_sb = afs_get_sb, | 44 | .get_sb = afs_get_sb, |
44 | .kill_sb = kill_anon_super, | 45 | .kill_sb = kill_anon_super, |
45 | .fs_flags = FS_BINARY_MOUNTDATA, | 46 | .fs_flags = 0, |
46 | }; | 47 | }; |
47 | 48 | ||
48 | static const struct super_operations afs_super_ops = { | 49 | static const struct super_operations afs_super_ops = { |
@@ -58,6 +59,20 @@ static const struct super_operations afs_super_ops = { | |||
58 | static struct kmem_cache *afs_inode_cachep; | 59 | static struct kmem_cache *afs_inode_cachep; |
59 | static atomic_t afs_count_active_inodes; | 60 | static atomic_t afs_count_active_inodes; |
60 | 61 | ||
62 | enum { | ||
63 | afs_no_opt, | ||
64 | afs_opt_cell, | ||
65 | afs_opt_rwpath, | ||
66 | afs_opt_vol, | ||
67 | }; | ||
68 | |||
69 | static const match_table_t afs_options_list = { | ||
70 | { afs_opt_cell, "cell=%s" }, | ||
71 | { afs_opt_rwpath, "rwpath" }, | ||
72 | { afs_opt_vol, "vol=%s" }, | ||
73 | { afs_no_opt, NULL }, | ||
74 | }; | ||
75 | |||
61 | /* | 76 | /* |
62 | * initialise the filesystem | 77 | * initialise the filesystem |
63 | */ | 78 | */ |
@@ -115,31 +130,6 @@ void __exit afs_fs_exit(void) | |||
115 | } | 130 | } |
116 | 131 | ||
117 | /* | 132 | /* |
118 | * check that an argument has a value | ||
119 | */ | ||
120 | static int want_arg(char **_value, const char *option) | ||
121 | { | ||
122 | if (!_value || !*_value || !**_value) { | ||
123 | printk(KERN_NOTICE "kAFS: %s: argument missing\n", option); | ||
124 | return 0; | ||
125 | } | ||
126 | return 1; | ||
127 | } | ||
128 | |||
129 | /* | ||
130 | * check that there's no subsequent value | ||
131 | */ | ||
132 | static int want_no_value(char *const *_value, const char *option) | ||
133 | { | ||
134 | if (*_value && **_value) { | ||
135 | printk(KERN_NOTICE "kAFS: %s: Invalid argument: %s\n", | ||
136 | option, *_value); | ||
137 | return 0; | ||
138 | } | ||
139 | return 1; | ||
140 | } | ||
141 | |||
142 | /* | ||
143 | * parse the mount options | 133 | * parse the mount options |
144 | * - this function has been shamelessly adapted from the ext3 fs which | 134 | * - this function has been shamelessly adapted from the ext3 fs which |
145 | * shamelessly adapted it from the msdos fs | 135 | * shamelessly adapted it from the msdos fs |
@@ -148,48 +138,46 @@ static int afs_parse_options(struct afs_mount_params *params, | |||
148 | char *options, const char **devname) | 138 | char *options, const char **devname) |
149 | { | 139 | { |
150 | struct afs_cell *cell; | 140 | struct afs_cell *cell; |
151 | char *key, *value; | 141 | substring_t args[MAX_OPT_ARGS]; |
152 | int ret; | 142 | char *p; |
143 | int token; | ||
153 | 144 | ||
154 | _enter("%s", options); | 145 | _enter("%s", options); |
155 | 146 | ||
156 | options[PAGE_SIZE - 1] = 0; | 147 | options[PAGE_SIZE - 1] = 0; |
157 | 148 | ||
158 | ret = 0; | 149 | while ((p = strsep(&options, ","))) { |
159 | while ((key = strsep(&options, ","))) { | 150 | if (!*p) |
160 | value = strchr(key, '='); | 151 | continue; |
161 | if (value) | ||
162 | *value++ = 0; | ||
163 | |||
164 | _debug("kAFS: KEY: %s, VAL:%s", key, value ?: "-"); | ||
165 | 152 | ||
166 | if (strcmp(key, "rwpath") == 0) { | 153 | token = match_token(p, afs_options_list, args); |
167 | if (!want_no_value(&value, "rwpath")) | 154 | switch (token) { |
168 | return -EINVAL; | 155 | case afs_opt_cell: |
169 | params->rwpath = 1; | 156 | cell = afs_cell_lookup(args[0].from, |
170 | } else if (strcmp(key, "vol") == 0) { | 157 | args[0].to - args[0].from); |
171 | if (!want_arg(&value, "vol")) | ||
172 | return -EINVAL; | ||
173 | *devname = value; | ||
174 | } else if (strcmp(key, "cell") == 0) { | ||
175 | if (!want_arg(&value, "cell")) | ||
176 | return -EINVAL; | ||
177 | cell = afs_cell_lookup(value, strlen(value)); | ||
178 | if (IS_ERR(cell)) | 158 | if (IS_ERR(cell)) |
179 | return PTR_ERR(cell); | 159 | return PTR_ERR(cell); |
180 | afs_put_cell(params->cell); | 160 | afs_put_cell(params->cell); |
181 | params->cell = cell; | 161 | params->cell = cell; |
182 | } else { | 162 | break; |
183 | printk("kAFS: Unknown mount option: '%s'\n", key); | 163 | |
184 | ret = -EINVAL; | 164 | case afs_opt_rwpath: |
185 | goto error; | 165 | params->rwpath = 1; |
166 | break; | ||
167 | |||
168 | case afs_opt_vol: | ||
169 | *devname = args[0].from; | ||
170 | break; | ||
171 | |||
172 | default: | ||
173 | printk(KERN_ERR "kAFS:" | ||
174 | " Unknown or invalid mount option: '%s'\n", p); | ||
175 | return -EINVAL; | ||
186 | } | 176 | } |
187 | } | 177 | } |
188 | 178 | ||
189 | ret = 0; | 179 | _leave(" = 0"); |
190 | error: | 180 | return 0; |
191 | _leave(" = %d", ret); | ||
192 | return ret; | ||
193 | } | 181 | } |
194 | 182 | ||
195 | /* | 183 | /* |
@@ -361,7 +349,6 @@ error: | |||
361 | 349 | ||
362 | /* | 350 | /* |
363 | * get an AFS superblock | 351 | * get an AFS superblock |
364 | * - TODO: don't use get_sb_nodev(), but rather call sget() directly | ||
365 | */ | 352 | */ |
366 | static int afs_get_sb(struct file_system_type *fs_type, | 353 | static int afs_get_sb(struct file_system_type *fs_type, |
367 | int flags, | 354 | int flags, |
@@ -386,7 +373,6 @@ static int afs_get_sb(struct file_system_type *fs_type, | |||
386 | goto error; | 373 | goto error; |
387 | } | 374 | } |
388 | 375 | ||
389 | |||
390 | ret = afs_parse_device_name(¶ms, dev_name); | 376 | ret = afs_parse_device_name(¶ms, dev_name); |
391 | if (ret < 0) | 377 | if (ret < 0) |
392 | goto error; | 378 | goto error; |
diff --git a/fs/afs/use-rtnetlink.c b/fs/afs/use-rtnetlink.c deleted file mode 100644 index f8991c700e02..000000000000 --- a/fs/afs/use-rtnetlink.c +++ /dev/null | |||
@@ -1,473 +0,0 @@ | |||
1 | /* RTNETLINK client | ||
2 | * | ||
3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | #include <linux/netlink.h> | ||
12 | #include <linux/rtnetlink.h> | ||
13 | #include <linux/if_addr.h> | ||
14 | #include <linux/if_arp.h> | ||
15 | #include <linux/inetdevice.h> | ||
16 | #include <net/netlink.h> | ||
17 | #include "internal.h" | ||
18 | |||
19 | struct afs_rtm_desc { | ||
20 | struct socket *nlsock; | ||
21 | struct afs_interface *bufs; | ||
22 | u8 *mac; | ||
23 | size_t nbufs; | ||
24 | size_t maxbufs; | ||
25 | void *data; | ||
26 | ssize_t datalen; | ||
27 | size_t datamax; | ||
28 | int msg_seq; | ||
29 | unsigned mac_index; | ||
30 | bool wantloopback; | ||
31 | int (*parse)(struct afs_rtm_desc *, struct nlmsghdr *); | ||
32 | }; | ||
33 | |||
34 | /* | ||
35 | * parse an RTM_GETADDR response | ||
36 | */ | ||
37 | static int afs_rtm_getaddr_parse(struct afs_rtm_desc *desc, | ||
38 | struct nlmsghdr *nlhdr) | ||
39 | { | ||
40 | struct afs_interface *this; | ||
41 | struct ifaddrmsg *ifa; | ||
42 | struct rtattr *rtattr; | ||
43 | const char *name; | ||
44 | size_t len; | ||
45 | |||
46 | ifa = (struct ifaddrmsg *) NLMSG_DATA(nlhdr); | ||
47 | |||
48 | _enter("{ix=%d,af=%d}", ifa->ifa_index, ifa->ifa_family); | ||
49 | |||
50 | if (ifa->ifa_family != AF_INET) { | ||
51 | _leave(" = 0 [family %d]", ifa->ifa_family); | ||
52 | return 0; | ||
53 | } | ||
54 | if (desc->nbufs >= desc->maxbufs) { | ||
55 | _leave(" = 0 [max %zu/%zu]", desc->nbufs, desc->maxbufs); | ||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | this = &desc->bufs[desc->nbufs]; | ||
60 | |||
61 | this->index = ifa->ifa_index; | ||
62 | this->netmask.s_addr = inet_make_mask(ifa->ifa_prefixlen); | ||
63 | this->mtu = 0; | ||
64 | |||
65 | rtattr = NLMSG_DATA(nlhdr) + NLMSG_ALIGN(sizeof(struct ifaddrmsg)); | ||
66 | len = NLMSG_PAYLOAD(nlhdr, sizeof(struct ifaddrmsg)); | ||
67 | |||
68 | name = "unknown"; | ||
69 | for (; RTA_OK(rtattr, len); rtattr = RTA_NEXT(rtattr, len)) { | ||
70 | switch (rtattr->rta_type) { | ||
71 | case IFA_ADDRESS: | ||
72 | memcpy(&this->address, RTA_DATA(rtattr), 4); | ||
73 | break; | ||
74 | case IFA_LABEL: | ||
75 | name = RTA_DATA(rtattr); | ||
76 | break; | ||
77 | } | ||
78 | } | ||
79 | |||
80 | _debug("%s: "NIPQUAD_FMT"/"NIPQUAD_FMT, | ||
81 | name, NIPQUAD(this->address), NIPQUAD(this->netmask)); | ||
82 | |||
83 | desc->nbufs++; | ||
84 | _leave(" = 0"); | ||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | /* | ||
89 | * parse an RTM_GETLINK response for MTUs | ||
90 | */ | ||
91 | static int afs_rtm_getlink_if_parse(struct afs_rtm_desc *desc, | ||
92 | struct nlmsghdr *nlhdr) | ||
93 | { | ||
94 | struct afs_interface *this; | ||
95 | struct ifinfomsg *ifi; | ||
96 | struct rtattr *rtattr; | ||
97 | const char *name; | ||
98 | size_t len, loop; | ||
99 | |||
100 | ifi = (struct ifinfomsg *) NLMSG_DATA(nlhdr); | ||
101 | |||
102 | _enter("{ix=%d}", ifi->ifi_index); | ||
103 | |||
104 | for (loop = 0; loop < desc->nbufs; loop++) { | ||
105 | this = &desc->bufs[loop]; | ||
106 | if (this->index == ifi->ifi_index) | ||
107 | goto found; | ||
108 | } | ||
109 | |||
110 | _leave(" = 0 [no match]"); | ||
111 | return 0; | ||
112 | |||
113 | found: | ||
114 | if (ifi->ifi_type == ARPHRD_LOOPBACK && !desc->wantloopback) { | ||
115 | _leave(" = 0 [loopback]"); | ||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | rtattr = NLMSG_DATA(nlhdr) + NLMSG_ALIGN(sizeof(struct ifinfomsg)); | ||
120 | len = NLMSG_PAYLOAD(nlhdr, sizeof(struct ifinfomsg)); | ||
121 | |||
122 | name = "unknown"; | ||
123 | for (; RTA_OK(rtattr, len); rtattr = RTA_NEXT(rtattr, len)) { | ||
124 | switch (rtattr->rta_type) { | ||
125 | case IFLA_MTU: | ||
126 | memcpy(&this->mtu, RTA_DATA(rtattr), 4); | ||
127 | break; | ||
128 | case IFLA_IFNAME: | ||
129 | name = RTA_DATA(rtattr); | ||
130 | break; | ||
131 | } | ||
132 | } | ||
133 | |||
134 | _debug("%s: "NIPQUAD_FMT"/"NIPQUAD_FMT" mtu %u", | ||
135 | name, NIPQUAD(this->address), NIPQUAD(this->netmask), | ||
136 | this->mtu); | ||
137 | |||
138 | _leave(" = 0"); | ||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | /* | ||
143 | * parse an RTM_GETLINK response for the MAC address belonging to the lowest | ||
144 | * non-internal interface | ||
145 | */ | ||
146 | static int afs_rtm_getlink_mac_parse(struct afs_rtm_desc *desc, | ||
147 | struct nlmsghdr *nlhdr) | ||
148 | { | ||
149 | struct ifinfomsg *ifi; | ||
150 | struct rtattr *rtattr; | ||
151 | const char *name; | ||
152 | size_t remain, len; | ||
153 | bool set; | ||
154 | |||
155 | ifi = (struct ifinfomsg *) NLMSG_DATA(nlhdr); | ||
156 | |||
157 | _enter("{ix=%d}", ifi->ifi_index); | ||
158 | |||
159 | if (ifi->ifi_index >= desc->mac_index) { | ||
160 | _leave(" = 0 [high]"); | ||
161 | return 0; | ||
162 | } | ||
163 | if (ifi->ifi_type == ARPHRD_LOOPBACK) { | ||
164 | _leave(" = 0 [loopback]"); | ||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | rtattr = NLMSG_DATA(nlhdr) + NLMSG_ALIGN(sizeof(struct ifinfomsg)); | ||
169 | remain = NLMSG_PAYLOAD(nlhdr, sizeof(struct ifinfomsg)); | ||
170 | |||
171 | name = "unknown"; | ||
172 | set = false; | ||
173 | for (; RTA_OK(rtattr, remain); rtattr = RTA_NEXT(rtattr, remain)) { | ||
174 | switch (rtattr->rta_type) { | ||
175 | case IFLA_ADDRESS: | ||
176 | len = RTA_PAYLOAD(rtattr); | ||
177 | memcpy(desc->mac, RTA_DATA(rtattr), | ||
178 | min_t(size_t, len, 6)); | ||
179 | desc->mac_index = ifi->ifi_index; | ||
180 | set = true; | ||
181 | break; | ||
182 | case IFLA_IFNAME: | ||
183 | name = RTA_DATA(rtattr); | ||
184 | break; | ||
185 | } | ||
186 | } | ||
187 | |||
188 | if (set) | ||
189 | _debug("%s: %02x:%02x:%02x:%02x:%02x:%02x", | ||
190 | name, | ||
191 | desc->mac[0], desc->mac[1], desc->mac[2], | ||
192 | desc->mac[3], desc->mac[4], desc->mac[5]); | ||
193 | |||
194 | _leave(" = 0"); | ||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | /* | ||
199 | * read the rtnetlink response and pass to parsing routine | ||
200 | */ | ||
201 | static int afs_read_rtm(struct afs_rtm_desc *desc) | ||
202 | { | ||
203 | struct nlmsghdr *nlhdr, tmphdr; | ||
204 | struct msghdr msg; | ||
205 | struct kvec iov[1]; | ||
206 | void *data; | ||
207 | bool last = false; | ||
208 | int len, ret, remain; | ||
209 | |||
210 | _enter(""); | ||
211 | |||
212 | do { | ||
213 | /* first of all peek to see how big the packet is */ | ||
214 | memset(&msg, 0, sizeof(msg)); | ||
215 | iov[0].iov_base = &tmphdr; | ||
216 | iov[0].iov_len = sizeof(tmphdr); | ||
217 | len = kernel_recvmsg(desc->nlsock, &msg, iov, 1, | ||
218 | sizeof(tmphdr), MSG_PEEK | MSG_TRUNC); | ||
219 | if (len < 0) { | ||
220 | _leave(" = %d [peek]", len); | ||
221 | return len; | ||
222 | } | ||
223 | if (len == 0) | ||
224 | continue; | ||
225 | if (len < sizeof(tmphdr) || len < NLMSG_PAYLOAD(&tmphdr, 0)) { | ||
226 | _leave(" = -EMSGSIZE"); | ||
227 | return -EMSGSIZE; | ||
228 | } | ||
229 | |||
230 | if (desc->datamax < len) { | ||
231 | kfree(desc->data); | ||
232 | desc->data = NULL; | ||
233 | data = kmalloc(len, GFP_KERNEL); | ||
234 | if (!data) | ||
235 | return -ENOMEM; | ||
236 | desc->data = data; | ||
237 | } | ||
238 | desc->datamax = len; | ||
239 | |||
240 | /* read all the data from this packet */ | ||
241 | iov[0].iov_base = desc->data; | ||
242 | iov[0].iov_len = desc->datamax; | ||
243 | desc->datalen = kernel_recvmsg(desc->nlsock, &msg, iov, 1, | ||
244 | desc->datamax, 0); | ||
245 | if (desc->datalen < 0) { | ||
246 | _leave(" = %zd [recv]", desc->datalen); | ||
247 | return desc->datalen; | ||
248 | } | ||
249 | |||
250 | nlhdr = desc->data; | ||
251 | |||
252 | /* check if the header is valid */ | ||
253 | if (!NLMSG_OK(nlhdr, desc->datalen) || | ||
254 | nlhdr->nlmsg_type == NLMSG_ERROR) { | ||
255 | _leave(" = -EIO"); | ||
256 | return -EIO; | ||
257 | } | ||
258 | |||
259 | /* see if this is the last message */ | ||
260 | if (nlhdr->nlmsg_type == NLMSG_DONE || | ||
261 | !(nlhdr->nlmsg_flags & NLM_F_MULTI)) | ||
262 | last = true; | ||
263 | |||
264 | /* parse the bits we got this time */ | ||
265 | nlmsg_for_each_msg(nlhdr, desc->data, desc->datalen, remain) { | ||
266 | ret = desc->parse(desc, nlhdr); | ||
267 | if (ret < 0) { | ||
268 | _leave(" = %d [parse]", ret); | ||
269 | return ret; | ||
270 | } | ||
271 | } | ||
272 | |||
273 | } while (!last); | ||
274 | |||
275 | _leave(" = 0"); | ||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | /* | ||
280 | * list the interface bound addresses to get the address and netmask | ||
281 | */ | ||
282 | static int afs_rtm_getaddr(struct afs_rtm_desc *desc) | ||
283 | { | ||
284 | struct msghdr msg; | ||
285 | struct kvec iov[1]; | ||
286 | int ret; | ||
287 | |||
288 | struct { | ||
289 | struct nlmsghdr nl_msg __attribute__((aligned(NLMSG_ALIGNTO))); | ||
290 | struct ifaddrmsg addr_msg __attribute__((aligned(NLMSG_ALIGNTO))); | ||
291 | } request; | ||
292 | |||
293 | _enter(""); | ||
294 | |||
295 | memset(&request, 0, sizeof(request)); | ||
296 | |||
297 | request.nl_msg.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); | ||
298 | request.nl_msg.nlmsg_type = RTM_GETADDR; | ||
299 | request.nl_msg.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; | ||
300 | request.nl_msg.nlmsg_seq = desc->msg_seq++; | ||
301 | request.nl_msg.nlmsg_pid = 0; | ||
302 | |||
303 | memset(&msg, 0, sizeof(msg)); | ||
304 | iov[0].iov_base = &request; | ||
305 | iov[0].iov_len = sizeof(request); | ||
306 | |||
307 | ret = kernel_sendmsg(desc->nlsock, &msg, iov, 1, iov[0].iov_len); | ||
308 | _leave(" = %d", ret); | ||
309 | return ret; | ||
310 | } | ||
311 | |||
312 | /* | ||
313 | * list the interface link statuses to get the MTUs | ||
314 | */ | ||
315 | static int afs_rtm_getlink(struct afs_rtm_desc *desc) | ||
316 | { | ||
317 | struct msghdr msg; | ||
318 | struct kvec iov[1]; | ||
319 | int ret; | ||
320 | |||
321 | struct { | ||
322 | struct nlmsghdr nl_msg __attribute__((aligned(NLMSG_ALIGNTO))); | ||
323 | struct ifinfomsg link_msg __attribute__((aligned(NLMSG_ALIGNTO))); | ||
324 | } request; | ||
325 | |||
326 | _enter(""); | ||
327 | |||
328 | memset(&request, 0, sizeof(request)); | ||
329 | |||
330 | request.nl_msg.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); | ||
331 | request.nl_msg.nlmsg_type = RTM_GETLINK; | ||
332 | request.nl_msg.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT; | ||
333 | request.nl_msg.nlmsg_seq = desc->msg_seq++; | ||
334 | request.nl_msg.nlmsg_pid = 0; | ||
335 | |||
336 | memset(&msg, 0, sizeof(msg)); | ||
337 | iov[0].iov_base = &request; | ||
338 | iov[0].iov_len = sizeof(request); | ||
339 | |||
340 | ret = kernel_sendmsg(desc->nlsock, &msg, iov, 1, iov[0].iov_len); | ||
341 | _leave(" = %d", ret); | ||
342 | return ret; | ||
343 | } | ||
344 | |||
345 | /* | ||
346 | * cull any interface records for which there isn't an MTU value | ||
347 | */ | ||
348 | static void afs_cull_interfaces(struct afs_rtm_desc *desc) | ||
349 | { | ||
350 | struct afs_interface *bufs = desc->bufs; | ||
351 | size_t nbufs = desc->nbufs; | ||
352 | int loop, point = 0; | ||
353 | |||
354 | _enter("{%zu}", nbufs); | ||
355 | |||
356 | for (loop = 0; loop < nbufs; loop++) { | ||
357 | if (desc->bufs[loop].mtu != 0) { | ||
358 | if (loop != point) { | ||
359 | ASSERTCMP(loop, >, point); | ||
360 | bufs[point] = bufs[loop]; | ||
361 | } | ||
362 | point++; | ||
363 | } | ||
364 | } | ||
365 | |||
366 | desc->nbufs = point; | ||
367 | _leave(" [%zu/%zu]", desc->nbufs, nbufs); | ||
368 | } | ||
369 | |||
370 | /* | ||
371 | * get a list of this system's interface IPv4 addresses, netmasks and MTUs | ||
372 | * - returns the number of interface records in the buffer | ||
373 | */ | ||
374 | int afs_get_ipv4_interfaces(struct afs_interface *bufs, size_t maxbufs, | ||
375 | bool wantloopback) | ||
376 | { | ||
377 | struct afs_rtm_desc desc; | ||
378 | int ret, loop; | ||
379 | |||
380 | _enter(""); | ||
381 | |||
382 | memset(&desc, 0, sizeof(desc)); | ||
383 | desc.bufs = bufs; | ||
384 | desc.maxbufs = maxbufs; | ||
385 | desc.wantloopback = wantloopback; | ||
386 | |||
387 | ret = sock_create_kern(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE, | ||
388 | &desc.nlsock); | ||
389 | if (ret < 0) { | ||
390 | _leave(" = %d [sock]", ret); | ||
391 | return ret; | ||
392 | } | ||
393 | |||
394 | /* issue RTM_GETADDR */ | ||
395 | desc.parse = afs_rtm_getaddr_parse; | ||
396 | ret = afs_rtm_getaddr(&desc); | ||
397 | if (ret < 0) | ||
398 | goto error; | ||
399 | ret = afs_read_rtm(&desc); | ||
400 | if (ret < 0) | ||
401 | goto error; | ||
402 | |||
403 | /* issue RTM_GETLINK */ | ||
404 | desc.parse = afs_rtm_getlink_if_parse; | ||
405 | ret = afs_rtm_getlink(&desc); | ||
406 | if (ret < 0) | ||
407 | goto error; | ||
408 | ret = afs_read_rtm(&desc); | ||
409 | if (ret < 0) | ||
410 | goto error; | ||
411 | |||
412 | afs_cull_interfaces(&desc); | ||
413 | ret = desc.nbufs; | ||
414 | |||
415 | for (loop = 0; loop < ret; loop++) | ||
416 | _debug("[%d] "NIPQUAD_FMT"/"NIPQUAD_FMT" mtu %u", | ||
417 | bufs[loop].index, | ||
418 | NIPQUAD(bufs[loop].address), | ||
419 | NIPQUAD(bufs[loop].netmask), | ||
420 | bufs[loop].mtu); | ||
421 | |||
422 | error: | ||
423 | kfree(desc.data); | ||
424 | sock_release(desc.nlsock); | ||
425 | _leave(" = %d", ret); | ||
426 | return ret; | ||
427 | } | ||
428 | |||
429 | /* | ||
430 | * get a MAC address from a random ethernet interface that has a real one | ||
431 | * - the buffer should be 6 bytes in size | ||
432 | */ | ||
433 | int afs_get_MAC_address(u8 mac[6]) | ||
434 | { | ||
435 | struct afs_rtm_desc desc; | ||
436 | int ret; | ||
437 | |||
438 | _enter(""); | ||
439 | |||
440 | memset(&desc, 0, sizeof(desc)); | ||
441 | desc.mac = mac; | ||
442 | desc.mac_index = UINT_MAX; | ||
443 | |||
444 | ret = sock_create_kern(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE, | ||
445 | &desc.nlsock); | ||
446 | if (ret < 0) { | ||
447 | _leave(" = %d [sock]", ret); | ||
448 | return ret; | ||
449 | } | ||
450 | |||
451 | /* issue RTM_GETLINK */ | ||
452 | desc.parse = afs_rtm_getlink_mac_parse; | ||
453 | ret = afs_rtm_getlink(&desc); | ||
454 | if (ret < 0) | ||
455 | goto error; | ||
456 | ret = afs_read_rtm(&desc); | ||
457 | if (ret < 0) | ||
458 | goto error; | ||
459 | |||
460 | if (desc.mac_index < UINT_MAX) { | ||
461 | /* got a MAC address */ | ||
462 | _debug("[%d] %02x:%02x:%02x:%02x:%02x:%02x", | ||
463 | desc.mac_index, | ||
464 | mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); | ||
465 | } else { | ||
466 | ret = -ENONET; | ||
467 | } | ||
468 | |||
469 | error: | ||
470 | sock_release(desc.nlsock); | ||
471 | _leave(" = %d", ret); | ||
472 | return ret; | ||
473 | } | ||
diff --git a/fs/afs/vlocation.c b/fs/afs/vlocation.c index 6c8e95a7c2c9..3370cdb72566 100644 --- a/fs/afs/vlocation.c +++ b/fs/afs/vlocation.c | |||
@@ -602,7 +602,7 @@ int __init afs_vlocation_update_init(void) | |||
602 | /* | 602 | /* |
603 | * discard all the volume location records for rmmod | 603 | * discard all the volume location records for rmmod |
604 | */ | 604 | */ |
605 | void __exit afs_vlocation_purge(void) | 605 | void afs_vlocation_purge(void) |
606 | { | 606 | { |
607 | afs_vlocation_timeout = 0; | 607 | afs_vlocation_timeout = 0; |
608 | 608 | ||