aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-04 22:36:58 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-04 22:36:58 -0400
commit7e20ef030dde0e52dd5a57220ee82fa9facbea4e (patch)
tree5006db4f85a2d7be2777748aaff2966e79dddc6f /fs
parenta3d52136ee8f7399859f9a0824470fd49b1d1a00 (diff)
parent07d939677166cc4f000c767196872a9becc2697b (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/Kconfig1
-rw-r--r--fs/afs/Makefile2
-rw-r--r--fs/afs/callback.c2
-rw-r--r--fs/afs/cmservice.c1
-rw-r--r--fs/afs/fsclient.c3
-rw-r--r--fs/afs/internal.h7
-rw-r--r--fs/afs/main.c2
-rw-r--r--fs/afs/netdevices.c68
-rw-r--r--fs/afs/super.c100
-rw-r--r--fs/afs/use-rtnetlink.c473
-rw-r--r--fs/afs/vlocation.c2
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 */
471void __exit afs_callback_update_kill(void) 471void 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 */
351struct afs_interface { 351struct 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 *);
392extern void afs_dispatch_give_up_callbacks(struct work_struct *); 391extern void afs_dispatch_give_up_callbacks(struct work_struct *);
393extern void afs_flush_callback_breaks(struct afs_server *); 392extern void afs_flush_callback_breaks(struct afs_server *);
394extern int __init afs_callback_update_init(void); 393extern int __init afs_callback_update_init(void);
395extern void __exit afs_callback_update_kill(void); 394extern 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 */
566extern int afs_get_ipv4_interfaces(struct afs_interface *, size_t, bool); 565extern int afs_get_ipv4_interfaces(struct afs_interface *, size_t, bool);
567extern int afs_get_MAC_address(u8 [6]); 566extern 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);
593extern void afs_put_vlocation(struct afs_vlocation *); 592extern void afs_put_vlocation(struct afs_vlocation *);
594extern void __exit afs_vlocation_purge(void); 593extern 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 */
17int 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 */
40int 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 }
65out:
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
48static const struct super_operations afs_super_ops = { 49static const struct super_operations afs_super_ops = {
@@ -58,6 +59,20 @@ static const struct super_operations afs_super_ops = {
58static struct kmem_cache *afs_inode_cachep; 59static struct kmem_cache *afs_inode_cachep;
59static atomic_t afs_count_active_inodes; 60static atomic_t afs_count_active_inodes;
60 61
62enum {
63 afs_no_opt,
64 afs_opt_cell,
65 afs_opt_rwpath,
66 afs_opt_vol,
67};
68
69static 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 */
120static 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 */
132static 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");
190error: 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 */
366static int afs_get_sb(struct file_system_type *fs_type, 353static 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(&params, dev_name); 376 ret = afs_parse_device_name(&params, 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
19struct 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 */
37static 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 */
91static 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
113found:
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 */
146static 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 */
201static 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 */
282static 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 */
315static 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 */
348static 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 */
374int 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
422error:
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 */
433int 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
469error:
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 */
605void __exit afs_vlocation_purge(void) 605void afs_vlocation_purge(void)
606{ 606{
607 afs_vlocation_timeout = 0; 607 afs_vlocation_timeout = 0;
608 608