diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-04-27 12:26:46 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-04-27 12:26:46 -0400 |
commit | 15c54033964a943de7b0763efd3bd0ede7326395 (patch) | |
tree | 840b292612d1b5396d5bab5bde537a9013db3ceb /fs/afs/main.c | |
parent | ad5da3cf39a5b11a198929be1f2644e17ecd767e (diff) | |
parent | 912a41a4ab935ce8c4308428ec13fc7f8b1f18f4 (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: (448 commits)
[IPV4] nl_fib_lookup: Initialise res.r before fib_res_put(&res)
[IPV6]: Fix thinko in ipv6_rthdr_rcv() changes.
[IPV4]: Add multipath cached to feature-removal-schedule.txt
[WIRELESS] cfg80211: Clarify locking comment.
[WIRELESS] cfg80211: Fix locking in wiphy_new.
[WEXT] net_device: Don't include wext bits if not required.
[WEXT]: Misc code cleanups.
[WEXT]: Reduce inline abuse.
[WEXT]: Move EXPORT_SYMBOL statements where they belong.
[WEXT]: Cleanup early ioctl call path.
[WEXT]: Remove options.
[WEXT]: Remove dead debug code.
[WEXT]: Clean up how wext is called.
[WEXT]: Move to net/wireless
[AFS]: Eliminate cmpxchg() usage in vlocation code.
[RXRPC]: Fix pointers passed to bitops.
[RXRPC]: Remove bogus atomic_* overrides.
[AFS]: Fix u64 printing in debug logging.
[AFS]: Add "directory write" support.
[AFS]: Implement the CB.InitCallBackState3 operation.
...
Diffstat (limited to 'fs/afs/main.c')
-rw-r--r-- | fs/afs/main.c | 262 |
1 files changed, 79 insertions, 183 deletions
diff --git a/fs/afs/main.c b/fs/afs/main.c index f2704ba53857..40c2704e7557 100644 --- a/fs/afs/main.c +++ b/fs/afs/main.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* main.c: AFS client file system | 1 | /* AFS client file system |
2 | * | 2 | * |
3 | * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. |
4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) |
@@ -13,43 +13,21 @@ | |||
13 | #include <linux/moduleparam.h> | 13 | #include <linux/moduleparam.h> |
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/completion.h> | 15 | #include <linux/completion.h> |
16 | #include <rxrpc/rxrpc.h> | ||
17 | #include <rxrpc/transport.h> | ||
18 | #include <rxrpc/call.h> | ||
19 | #include <rxrpc/peer.h> | ||
20 | #include "cache.h" | ||
21 | #include "cell.h" | ||
22 | #include "server.h" | ||
23 | #include "fsclient.h" | ||
24 | #include "cmservice.h" | ||
25 | #include "kafstimod.h" | ||
26 | #include "kafsasyncd.h" | ||
27 | #include "internal.h" | 16 | #include "internal.h" |
28 | 17 | ||
29 | struct rxrpc_transport *afs_transport; | ||
30 | |||
31 | static int afs_adding_peer(struct rxrpc_peer *peer); | ||
32 | static void afs_discarding_peer(struct rxrpc_peer *peer); | ||
33 | |||
34 | |||
35 | MODULE_DESCRIPTION("AFS Client File System"); | 18 | MODULE_DESCRIPTION("AFS Client File System"); |
36 | MODULE_AUTHOR("Red Hat, Inc."); | 19 | MODULE_AUTHOR("Red Hat, Inc."); |
37 | MODULE_LICENSE("GPL"); | 20 | MODULE_LICENSE("GPL"); |
38 | 21 | ||
22 | unsigned afs_debug; | ||
23 | module_param_named(debug, afs_debug, uint, S_IWUSR | S_IRUGO); | ||
24 | MODULE_PARM_DESC(afs_debug, "AFS debugging mask"); | ||
25 | |||
39 | static char *rootcell; | 26 | static char *rootcell; |
40 | 27 | ||
41 | module_param(rootcell, charp, 0); | 28 | module_param(rootcell, charp, 0); |
42 | MODULE_PARM_DESC(rootcell, "root AFS cell name and VL server IP addr list"); | 29 | MODULE_PARM_DESC(rootcell, "root AFS cell name and VL server IP addr list"); |
43 | 30 | ||
44 | |||
45 | static struct rxrpc_peer_ops afs_peer_ops = { | ||
46 | .adding = afs_adding_peer, | ||
47 | .discarding = afs_discarding_peer, | ||
48 | }; | ||
49 | |||
50 | struct list_head afs_cb_hash_tbl[AFS_CB_HASH_COUNT]; | ||
51 | DEFINE_SPINLOCK(afs_cb_hash_lock); | ||
52 | |||
53 | #ifdef AFS_CACHING_SUPPORT | 31 | #ifdef AFS_CACHING_SUPPORT |
54 | static struct cachefs_netfs_operations afs_cache_ops = { | 32 | static struct cachefs_netfs_operations afs_cache_ops = { |
55 | .get_page_cookie = afs_cache_get_page_cookie, | 33 | .get_page_cookie = afs_cache_get_page_cookie, |
@@ -62,20 +40,63 @@ struct cachefs_netfs afs_cache_netfs = { | |||
62 | }; | 40 | }; |
63 | #endif | 41 | #endif |
64 | 42 | ||
65 | /*****************************************************************************/ | 43 | struct afs_uuid afs_uuid; |
44 | |||
45 | /* | ||
46 | * get a client UUID | ||
47 | */ | ||
48 | static int __init afs_get_client_UUID(void) | ||
49 | { | ||
50 | struct timespec ts; | ||
51 | u64 uuidtime; | ||
52 | u16 clockseq; | ||
53 | int ret; | ||
54 | |||
55 | /* read the MAC address of one of the external interfaces and construct | ||
56 | * a UUID from it */ | ||
57 | ret = afs_get_MAC_address(afs_uuid.node); | ||
58 | if (ret < 0) | ||
59 | return ret; | ||
60 | |||
61 | getnstimeofday(&ts); | ||
62 | uuidtime = (u64) ts.tv_sec * 1000 * 1000 * 10; | ||
63 | uuidtime += ts.tv_nsec / 100; | ||
64 | uuidtime += AFS_UUID_TO_UNIX_TIME; | ||
65 | afs_uuid.time_low = uuidtime; | ||
66 | afs_uuid.time_mid = uuidtime >> 32; | ||
67 | afs_uuid.time_hi_and_version = (uuidtime >> 48) & AFS_UUID_TIMEHI_MASK; | ||
68 | afs_uuid.time_hi_and_version = AFS_UUID_VERSION_TIME; | ||
69 | |||
70 | get_random_bytes(&clockseq, 2); | ||
71 | afs_uuid.clock_seq_low = clockseq; | ||
72 | afs_uuid.clock_seq_hi_and_reserved = | ||
73 | (clockseq >> 8) & AFS_UUID_CLOCKHI_MASK; | ||
74 | afs_uuid.clock_seq_hi_and_reserved = AFS_UUID_VARIANT_STD; | ||
75 | |||
76 | _debug("AFS UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", | ||
77 | afs_uuid.time_low, | ||
78 | afs_uuid.time_mid, | ||
79 | afs_uuid.time_hi_and_version, | ||
80 | afs_uuid.clock_seq_hi_and_reserved, | ||
81 | afs_uuid.clock_seq_low, | ||
82 | afs_uuid.node[0], afs_uuid.node[1], afs_uuid.node[2], | ||
83 | afs_uuid.node[3], afs_uuid.node[4], afs_uuid.node[5]); | ||
84 | |||
85 | return 0; | ||
86 | } | ||
87 | |||
66 | /* | 88 | /* |
67 | * initialise the AFS client FS module | 89 | * initialise the AFS client FS module |
68 | */ | 90 | */ |
69 | static int __init afs_init(void) | 91 | static int __init afs_init(void) |
70 | { | 92 | { |
71 | int loop, ret; | 93 | int ret; |
72 | 94 | ||
73 | printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 registering.\n"); | 95 | printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 registering.\n"); |
74 | 96 | ||
75 | /* initialise the callback hash table */ | 97 | ret = afs_get_client_UUID(); |
76 | spin_lock_init(&afs_cb_hash_lock); | 98 | if (ret < 0) |
77 | for (loop = AFS_CB_HASH_COUNT - 1; loop >= 0; loop--) | 99 | return ret; |
78 | INIT_LIST_HEAD(&afs_cb_hash_tbl[loop]); | ||
79 | 100 | ||
80 | /* register the /proc stuff */ | 101 | /* register the /proc stuff */ |
81 | ret = afs_proc_init(); | 102 | ret = afs_proc_init(); |
@@ -87,70 +108,56 @@ static int __init afs_init(void) | |||
87 | ret = cachefs_register_netfs(&afs_cache_netfs, | 108 | ret = cachefs_register_netfs(&afs_cache_netfs, |
88 | &afs_cache_cell_index_def); | 109 | &afs_cache_cell_index_def); |
89 | if (ret < 0) | 110 | if (ret < 0) |
90 | goto error; | ||
91 | #endif | ||
92 | |||
93 | #ifdef CONFIG_KEYS_TURNED_OFF | ||
94 | ret = afs_key_register(); | ||
95 | if (ret < 0) | ||
96 | goto error_cache; | 111 | goto error_cache; |
97 | #endif | 112 | #endif |
98 | 113 | ||
99 | /* initialise the cell DB */ | 114 | /* initialise the cell DB */ |
100 | ret = afs_cell_init(rootcell); | 115 | ret = afs_cell_init(rootcell); |
101 | if (ret < 0) | 116 | if (ret < 0) |
102 | goto error_keys; | 117 | goto error_cell_init; |
103 | 118 | ||
104 | /* start the timeout daemon */ | 119 | /* initialise the VL update process */ |
105 | ret = afs_kafstimod_start(); | 120 | ret = afs_vlocation_update_init(); |
106 | if (ret < 0) | 121 | if (ret < 0) |
107 | goto error_keys; | 122 | goto error_vl_update_init; |
108 | 123 | ||
109 | /* start the async operation daemon */ | 124 | /* initialise the callback update process */ |
110 | ret = afs_kafsasyncd_start(); | 125 | ret = afs_callback_update_init(); |
111 | if (ret < 0) | ||
112 | goto error_kafstimod; | ||
113 | 126 | ||
114 | /* create the RxRPC transport */ | 127 | /* create the RxRPC transport */ |
115 | ret = rxrpc_create_transport(7001, &afs_transport); | 128 | ret = afs_open_socket(); |
116 | if (ret < 0) | 129 | if (ret < 0) |
117 | goto error_kafsasyncd; | 130 | goto error_open_socket; |
118 | |||
119 | afs_transport->peer_ops = &afs_peer_ops; | ||
120 | 131 | ||
121 | /* register the filesystems */ | 132 | /* register the filesystems */ |
122 | ret = afs_fs_init(); | 133 | ret = afs_fs_init(); |
123 | if (ret < 0) | 134 | if (ret < 0) |
124 | goto error_transport; | 135 | goto error_fs; |
125 | 136 | ||
126 | return ret; | 137 | return ret; |
127 | 138 | ||
128 | error_transport: | 139 | error_fs: |
129 | rxrpc_put_transport(afs_transport); | 140 | afs_close_socket(); |
130 | error_kafsasyncd: | 141 | error_open_socket: |
131 | afs_kafsasyncd_stop(); | 142 | error_vl_update_init: |
132 | error_kafstimod: | 143 | error_cell_init: |
133 | afs_kafstimod_stop(); | ||
134 | error_keys: | ||
135 | #ifdef CONFIG_KEYS_TURNED_OFF | ||
136 | afs_key_unregister(); | ||
137 | error_cache: | ||
138 | #endif | ||
139 | #ifdef AFS_CACHING_SUPPORT | 144 | #ifdef AFS_CACHING_SUPPORT |
140 | cachefs_unregister_netfs(&afs_cache_netfs); | 145 | cachefs_unregister_netfs(&afs_cache_netfs); |
141 | error: | 146 | error_cache: |
142 | #endif | 147 | #endif |
148 | afs_callback_update_kill(); | ||
149 | afs_vlocation_purge(); | ||
143 | afs_cell_purge(); | 150 | afs_cell_purge(); |
144 | afs_proc_cleanup(); | 151 | afs_proc_cleanup(); |
145 | printk(KERN_ERR "kAFS: failed to register: %d\n", ret); | 152 | printk(KERN_ERR "kAFS: failed to register: %d\n", ret); |
146 | return ret; | 153 | return ret; |
147 | } /* end afs_init() */ | 154 | } |
148 | 155 | ||
149 | /* XXX late_initcall is kludgy, but the only alternative seems to create | 156 | /* XXX late_initcall is kludgy, but the only alternative seems to create |
150 | * a transport upon the first mount, which is worse. Or is it? | 157 | * a transport upon the first mount, which is worse. Or is it? |
151 | */ | 158 | */ |
152 | late_initcall(afs_init); /* must be called after net/ to create socket */ | 159 | late_initcall(afs_init); /* must be called after net/ to create socket */ |
153 | /*****************************************************************************/ | 160 | |
154 | /* | 161 | /* |
155 | * clean up on module removal | 162 | * clean up on module removal |
156 | */ | 163 | */ |
@@ -159,127 +166,16 @@ static void __exit afs_exit(void) | |||
159 | printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 unregistering.\n"); | 166 | printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 unregistering.\n"); |
160 | 167 | ||
161 | afs_fs_exit(); | 168 | afs_fs_exit(); |
162 | rxrpc_put_transport(afs_transport); | 169 | afs_close_socket(); |
163 | afs_kafstimod_stop(); | 170 | afs_purge_servers(); |
164 | afs_kafsasyncd_stop(); | 171 | afs_callback_update_kill(); |
172 | afs_vlocation_purge(); | ||
173 | flush_scheduled_work(); | ||
165 | afs_cell_purge(); | 174 | afs_cell_purge(); |
166 | #ifdef CONFIG_KEYS_TURNED_OFF | ||
167 | afs_key_unregister(); | ||
168 | #endif | ||
169 | #ifdef AFS_CACHING_SUPPORT | 175 | #ifdef AFS_CACHING_SUPPORT |
170 | cachefs_unregister_netfs(&afs_cache_netfs); | 176 | cachefs_unregister_netfs(&afs_cache_netfs); |
171 | #endif | 177 | #endif |
172 | afs_proc_cleanup(); | 178 | afs_proc_cleanup(); |
173 | |||
174 | } /* end afs_exit() */ | ||
175 | |||
176 | module_exit(afs_exit); | ||
177 | |||
178 | /*****************************************************************************/ | ||
179 | /* | ||
180 | * notification that new peer record is being added | ||
181 | * - called from krxsecd | ||
182 | * - return an error to induce an abort | ||
183 | * - mustn't sleep (caller holds an rwlock) | ||
184 | */ | ||
185 | static int afs_adding_peer(struct rxrpc_peer *peer) | ||
186 | { | ||
187 | struct afs_server *server; | ||
188 | int ret; | ||
189 | |||
190 | _debug("kAFS: Adding new peer %08x\n", ntohl(peer->addr.s_addr)); | ||
191 | |||
192 | /* determine which server the peer resides in (if any) */ | ||
193 | ret = afs_server_find_by_peer(peer, &server); | ||
194 | if (ret < 0) | ||
195 | return ret; /* none that we recognise, so abort */ | ||
196 | |||
197 | _debug("Server %p{u=%d}\n", server, atomic_read(&server->usage)); | ||
198 | |||
199 | _debug("Cell %p{u=%d}\n", | ||
200 | server->cell, atomic_read(&server->cell->usage)); | ||
201 | |||
202 | /* cross-point the structs under a global lock */ | ||
203 | spin_lock(&afs_server_peer_lock); | ||
204 | peer->user = server; | ||
205 | server->peer = peer; | ||
206 | spin_unlock(&afs_server_peer_lock); | ||
207 | |||
208 | afs_put_server(server); | ||
209 | |||
210 | return 0; | ||
211 | } /* end afs_adding_peer() */ | ||
212 | |||
213 | /*****************************************************************************/ | ||
214 | /* | ||
215 | * notification that a peer record is being discarded | ||
216 | * - called from krxiod or krxsecd | ||
217 | */ | ||
218 | static void afs_discarding_peer(struct rxrpc_peer *peer) | ||
219 | { | ||
220 | struct afs_server *server; | ||
221 | |||
222 | _enter("%p",peer); | ||
223 | |||
224 | _debug("Discarding peer %08x (rtt=%lu.%lumS)\n", | ||
225 | ntohl(peer->addr.s_addr), | ||
226 | (long) (peer->rtt / 1000), | ||
227 | (long) (peer->rtt % 1000)); | ||
228 | |||
229 | /* uncross-point the structs under a global lock */ | ||
230 | spin_lock(&afs_server_peer_lock); | ||
231 | server = peer->user; | ||
232 | if (server) { | ||
233 | peer->user = NULL; | ||
234 | server->peer = NULL; | ||
235 | } | ||
236 | spin_unlock(&afs_server_peer_lock); | ||
237 | |||
238 | _leave(""); | ||
239 | |||
240 | } /* end afs_discarding_peer() */ | ||
241 | |||
242 | /*****************************************************************************/ | ||
243 | /* | ||
244 | * clear the dead space between task_struct and kernel stack | ||
245 | * - called by supplying -finstrument-functions to gcc | ||
246 | */ | ||
247 | #if 0 | ||
248 | void __cyg_profile_func_enter (void *this_fn, void *call_site) | ||
249 | __attribute__((no_instrument_function)); | ||
250 | |||
251 | void __cyg_profile_func_enter (void *this_fn, void *call_site) | ||
252 | { | ||
253 | asm volatile(" movl %%esp,%%edi \n" | ||
254 | " andl %0,%%edi \n" | ||
255 | " addl %1,%%edi \n" | ||
256 | " movl %%esp,%%ecx \n" | ||
257 | " subl %%edi,%%ecx \n" | ||
258 | " shrl $2,%%ecx \n" | ||
259 | " movl $0xedededed,%%eax \n" | ||
260 | " rep stosl \n" | ||
261 | : | ||
262 | : "i"(~(THREAD_SIZE - 1)), "i"(sizeof(struct thread_info)) | ||
263 | : "eax", "ecx", "edi", "memory", "cc" | ||
264 | ); | ||
265 | } | 179 | } |
266 | 180 | ||
267 | void __cyg_profile_func_exit(void *this_fn, void *call_site) | 181 | module_exit(afs_exit); |
268 | __attribute__((no_instrument_function)); | ||
269 | |||
270 | void __cyg_profile_func_exit(void *this_fn, void *call_site) | ||
271 | { | ||
272 | asm volatile(" movl %%esp,%%edi \n" | ||
273 | " andl %0,%%edi \n" | ||
274 | " addl %1,%%edi \n" | ||
275 | " movl %%esp,%%ecx \n" | ||
276 | " subl %%edi,%%ecx \n" | ||
277 | " shrl $2,%%ecx \n" | ||
278 | " movl $0xdadadada,%%eax \n" | ||
279 | " rep stosl \n" | ||
280 | : | ||
281 | : "i"(~(THREAD_SIZE - 1)), "i"(sizeof(struct thread_info)) | ||
282 | : "eax", "ecx", "edi", "memory", "cc" | ||
283 | ); | ||
284 | } | ||
285 | #endif | ||