Diff markup
1 /* AFS cell and server record management 1 /* AFS cell and server record management
2 * 2 *
3 * Copyright (C) 2002 Red Hat, Inc. All Rights 3 * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.c 4 * Written by David Howells (dhowells@redhat.com)
5 * 5 *
6 * This program is free software; you can redi 6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Genera 7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundatio 8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any l 9 * 2 of the License, or (at your option) any later version.
10 */ 10 */
11 11
12 #include <linux/module.h> 12 #include <linux/module.h>
13 #include <linux/slab.h> 13 #include <linux/slab.h>
14 #include <linux/key.h> 14 #include <linux/key.h>
15 #include <linux/ctype.h> 15 #include <linux/ctype.h>
16 #include <linux/sched.h> 16 #include <linux/sched.h>
17 #include <keys/rxrpc-type.h> 17 #include <keys/rxrpc-type.h>
18 #include "internal.h" 18 #include "internal.h"
19 19
20 DECLARE_RWSEM(afs_proc_cells_sem); 20 DECLARE_RWSEM(afs_proc_cells_sem);
21 LIST_HEAD(afs_proc_cells); 21 LIST_HEAD(afs_proc_cells);
22 22
23 static LIST_HEAD(afs_cells); !! 23 static struct list_head afs_cells = LIST_HEAD_INIT(afs_cells);
24 static DEFINE_RWLOCK(afs_cells_lock); 24 static DEFINE_RWLOCK(afs_cells_lock);
25 static DECLARE_RWSEM(afs_cells_sem); /* add/re 25 static DECLARE_RWSEM(afs_cells_sem); /* add/remove serialisation */
26 static DECLARE_WAIT_QUEUE_HEAD(afs_cells_freea 26 static DECLARE_WAIT_QUEUE_HEAD(afs_cells_freeable_wq);
27 static struct afs_cell *afs_cell_root; 27 static struct afs_cell *afs_cell_root;
28 28
29 /* 29 /*
30 * allocate a cell record and fill in its name 30 * allocate a cell record and fill in its name, VL server address list and
31 * allocate an anonymous key 31 * allocate an anonymous key
32 */ 32 */
33 static struct afs_cell *afs_cell_alloc(const c 33 static struct afs_cell *afs_cell_alloc(const char *name, char *vllist)
34 { 34 {
35 struct afs_cell *cell; 35 struct afs_cell *cell;
36 struct key *key; 36 struct key *key;
37 size_t namelen; 37 size_t namelen;
38 char keyname[4 + AFS_MAXCELLNAME + 1], 38 char keyname[4 + AFS_MAXCELLNAME + 1], *cp, *dp, *next;
39 int ret; 39 int ret;
40 40
41 _enter("%s,%s", name, vllist); 41 _enter("%s,%s", name, vllist);
42 42
43 BUG_ON(!name); /* TODO: want to look u 43 BUG_ON(!name); /* TODO: want to look up "this cell" in the cache */
44 44
45 namelen = strlen(name); 45 namelen = strlen(name);
46 if (namelen > AFS_MAXCELLNAME) 46 if (namelen > AFS_MAXCELLNAME)
47 return ERR_PTR(-ENAMETOOLONG); 47 return ERR_PTR(-ENAMETOOLONG);
48 48
49 /* allocate and initialise a cell reco 49 /* allocate and initialise a cell record */
50 cell = kzalloc(sizeof(struct afs_cell) 50 cell = kzalloc(sizeof(struct afs_cell) + namelen + 1, GFP_KERNEL);
51 if (!cell) { 51 if (!cell) {
52 _leave(" = -ENOMEM"); 52 _leave(" = -ENOMEM");
53 return ERR_PTR(-ENOMEM); 53 return ERR_PTR(-ENOMEM);
54 } 54 }
55 55
56 memcpy(cell->name, name, namelen); 56 memcpy(cell->name, name, namelen);
57 cell->name[namelen] = 0; 57 cell->name[namelen] = 0;
58 58
59 atomic_set(&cell->usage, 1); 59 atomic_set(&cell->usage, 1);
60 INIT_LIST_HEAD(&cell->link); 60 INIT_LIST_HEAD(&cell->link);
61 rwlock_init(&cell->servers_lock); 61 rwlock_init(&cell->servers_lock);
62 INIT_LIST_HEAD(&cell->servers); 62 INIT_LIST_HEAD(&cell->servers);
63 init_rwsem(&cell->vl_sem); 63 init_rwsem(&cell->vl_sem);
64 INIT_LIST_HEAD(&cell->vl_list); 64 INIT_LIST_HEAD(&cell->vl_list);
65 spin_lock_init(&cell->vl_lock); 65 spin_lock_init(&cell->vl_lock);
66 66
67 /* fill in the VL server list from the 67 /* fill in the VL server list from the rest of the string */
68 do { 68 do {
69 unsigned a, b, c, d; 69 unsigned a, b, c, d;
70 70
71 next = strchr(vllist, ':'); 71 next = strchr(vllist, ':');
72 if (next) 72 if (next)
73 *next++ = 0; 73 *next++ = 0;
74 74
75 if (sscanf(vllist, "%u.%u.%u.% 75 if (sscanf(vllist, "%u.%u.%u.%u", &a, &b, &c, &d) != 4)
76 goto bad_address; 76 goto bad_address;
77 77
78 if (a > 255 || b > 255 || c > 78 if (a > 255 || b > 255 || c > 255 || d > 255)
79 goto bad_address; 79 goto bad_address;
80 80
81 cell->vl_addrs[cell->vl_naddrs 81 cell->vl_addrs[cell->vl_naddrs++].s_addr =
82 htonl((a << 24) | (b < 82 htonl((a << 24) | (b << 16) | (c << 8) | d);
83 83
84 } while (cell->vl_naddrs < AFS_CELL_MA 84 } while (cell->vl_naddrs < AFS_CELL_MAX_ADDRS && (vllist = next));
85 85
86 /* create a key to represent an anonym 86 /* create a key to represent an anonymous user */
87 memcpy(keyname, "afs@", 4); 87 memcpy(keyname, "afs@", 4);
88 dp = keyname + 4; 88 dp = keyname + 4;
89 cp = cell->name; 89 cp = cell->name;
90 do { 90 do {
91 *dp++ = toupper(*cp); 91 *dp++ = toupper(*cp);
92 } while (*cp++); 92 } while (*cp++);
93 93
94 key = rxrpc_get_null_key(keyname); 94 key = rxrpc_get_null_key(keyname);
95 if (IS_ERR(key)) { 95 if (IS_ERR(key)) {
96 _debug("no key"); 96 _debug("no key");
97 ret = PTR_ERR(key); 97 ret = PTR_ERR(key);
98 goto error; 98 goto error;
99 } 99 }
100 cell->anonymous_key = key; 100 cell->anonymous_key = key;
101 101
102 _debug("anon key %p{%x}", 102 _debug("anon key %p{%x}",
103 cell->anonymous_key, key_serial 103 cell->anonymous_key, key_serial(cell->anonymous_key));
104 104
105 _leave(" = %p", cell); 105 _leave(" = %p", cell);
106 return cell; 106 return cell;
107 107
108 bad_address: 108 bad_address:
109 printk(KERN_ERR "kAFS: bad VL server I 109 printk(KERN_ERR "kAFS: bad VL server IP address\n");
110 ret = -EINVAL; 110 ret = -EINVAL;
111 error: 111 error:
112 key_put(cell->anonymous_key); 112 key_put(cell->anonymous_key);
113 kfree(cell); 113 kfree(cell);
114 _leave(" = %d", ret); 114 _leave(" = %d", ret);
115 return ERR_PTR(ret); 115 return ERR_PTR(ret);
116 } 116 }
117 117
118 /* 118 /*
119 * create a cell record 119 * create a cell record
120 * - "name" is the name of the cell 120 * - "name" is the name of the cell
121 * - "vllist" is a colon separated list of IP 121 * - "vllist" is a colon separated list of IP addresses in "a.b.c.d" format
122 */ 122 */
123 struct afs_cell *afs_cell_create(const char *n 123 struct afs_cell *afs_cell_create(const char *name, char *vllist)
124 { 124 {
125 struct afs_cell *cell; 125 struct afs_cell *cell;
126 int ret; 126 int ret;
127 127
128 _enter("%s,%s", name, vllist); 128 _enter("%s,%s", name, vllist);
129 129
130 down_write(&afs_cells_sem); 130 down_write(&afs_cells_sem);
131 read_lock(&afs_cells_lock); 131 read_lock(&afs_cells_lock);
132 list_for_each_entry(cell, &afs_cells, 132 list_for_each_entry(cell, &afs_cells, link) {
133 if (strcasecmp(cell->name, nam 133 if (strcasecmp(cell->name, name) == 0)
134 goto duplicate_name; 134 goto duplicate_name;
135 } 135 }
136 read_unlock(&afs_cells_lock); 136 read_unlock(&afs_cells_lock);
137 137
138 cell = afs_cell_alloc(name, vllist); 138 cell = afs_cell_alloc(name, vllist);
139 if (IS_ERR(cell)) { 139 if (IS_ERR(cell)) {
140 _leave(" = %ld", PTR_ERR(cell) 140 _leave(" = %ld", PTR_ERR(cell));
141 up_write(&afs_cells_sem); 141 up_write(&afs_cells_sem);
142 return cell; 142 return cell;
143 } 143 }
144 144
145 /* add a proc directory for this cell 145 /* add a proc directory for this cell */
146 ret = afs_proc_cell_setup(cell); 146 ret = afs_proc_cell_setup(cell);
147 if (ret < 0) 147 if (ret < 0)
148 goto error; 148 goto error;
149 149
150 #ifdef CONFIG_AFS_FSCACHE !! 150 #ifdef AFS_CACHING_SUPPORT
151 /* put it up for caching (this never r !! 151 /* put it up for caching */
152 cell->cache = fscache_acquire_cookie(a !! 152 cachefs_acquire_cookie(afs_cache_netfs.primary_index,
153 & !! 153 &afs_vlocation_cache_index_def,
154 c !! 154 cell,
>> 155 &cell->cache);
155 #endif 156 #endif
156 157
157 /* add to the cell lists */ 158 /* add to the cell lists */
158 write_lock(&afs_cells_lock); 159 write_lock(&afs_cells_lock);
159 list_add_tail(&cell->link, &afs_cells) 160 list_add_tail(&cell->link, &afs_cells);
160 write_unlock(&afs_cells_lock); 161 write_unlock(&afs_cells_lock);
161 162
162 down_write(&afs_proc_cells_sem); 163 down_write(&afs_proc_cells_sem);
163 list_add_tail(&cell->proc_link, &afs_p 164 list_add_tail(&cell->proc_link, &afs_proc_cells);
164 up_write(&afs_proc_cells_sem); 165 up_write(&afs_proc_cells_sem);
165 up_write(&afs_cells_sem); 166 up_write(&afs_cells_sem);
166 167
167 _leave(" = %p", cell); 168 _leave(" = %p", cell);
168 return cell; 169 return cell;
169 170
170 error: 171 error:
171 up_write(&afs_cells_sem); 172 up_write(&afs_cells_sem);
172 key_put(cell->anonymous_key); 173 key_put(cell->anonymous_key);
173 kfree(cell); 174 kfree(cell);
174 _leave(" = %d", ret); 175 _leave(" = %d", ret);
175 return ERR_PTR(ret); 176 return ERR_PTR(ret);
176 177
177 duplicate_name: 178 duplicate_name:
178 read_unlock(&afs_cells_lock); 179 read_unlock(&afs_cells_lock);
179 up_write(&afs_cells_sem); 180 up_write(&afs_cells_sem);
180 return ERR_PTR(-EEXIST); 181 return ERR_PTR(-EEXIST);
181 } 182 }
182 183
183 /* 184 /*
184 * set the root cell information 185 * set the root cell information
185 * - can be called with a module parameter str 186 * - can be called with a module parameter string
186 * - can be called from a write to /proc/fs/af 187 * - can be called from a write to /proc/fs/afs/rootcell
187 */ 188 */
188 int afs_cell_init(char *rootcell) 189 int afs_cell_init(char *rootcell)
189 { 190 {
190 struct afs_cell *old_root, *new_root; 191 struct afs_cell *old_root, *new_root;
191 char *cp; 192 char *cp;
192 193
193 _enter(""); 194 _enter("");
194 195
195 if (!rootcell) { 196 if (!rootcell) {
196 /* module is loaded with no pa 197 /* module is loaded with no parameters, or built statically.
197 * - in the future we might in 198 * - in the future we might initialize cell DB here.
198 */ 199 */
199 _leave(" = 0 [no root]"); 200 _leave(" = 0 [no root]");
200 return 0; 201 return 0;
201 } 202 }
202 203
203 cp = strchr(rootcell, ':'); 204 cp = strchr(rootcell, ':');
204 if (!cp) { 205 if (!cp) {
205 printk(KERN_ERR "kAFS: no VL s 206 printk(KERN_ERR "kAFS: no VL server IP addresses specified\n");
206 _leave(" = -EINVAL"); 207 _leave(" = -EINVAL");
207 return -EINVAL; 208 return -EINVAL;
208 } 209 }
209 210
210 /* allocate a cell record for the root 211 /* allocate a cell record for the root cell */
211 *cp++ = 0; 212 *cp++ = 0;
212 new_root = afs_cell_create(rootcell, c 213 new_root = afs_cell_create(rootcell, cp);
213 if (IS_ERR(new_root)) { 214 if (IS_ERR(new_root)) {
214 _leave(" = %ld", PTR_ERR(new_r 215 _leave(" = %ld", PTR_ERR(new_root));
215 return PTR_ERR(new_root); 216 return PTR_ERR(new_root);
216 } 217 }
217 218
218 /* install the new cell */ 219 /* install the new cell */
219 write_lock(&afs_cells_lock); 220 write_lock(&afs_cells_lock);
220 old_root = afs_cell_root; 221 old_root = afs_cell_root;
221 afs_cell_root = new_root; 222 afs_cell_root = new_root;
222 write_unlock(&afs_cells_lock); 223 write_unlock(&afs_cells_lock);
223 afs_put_cell(old_root); 224 afs_put_cell(old_root);
224 225
225 _leave(" = 0"); 226 _leave(" = 0");
226 return 0; 227 return 0;
227 } 228 }
228 229
229 /* 230 /*
230 * lookup a cell record 231 * lookup a cell record
231 */ 232 */
232 struct afs_cell *afs_cell_lookup(const char *n 233 struct afs_cell *afs_cell_lookup(const char *name, unsigned namesz)
233 { 234 {
234 struct afs_cell *cell; 235 struct afs_cell *cell;
235 236
236 _enter("\"%*.*s\",", namesz, namesz, n 237 _enter("\"%*.*s\",", namesz, namesz, name ? name : "");
237 238
238 down_read(&afs_cells_sem); 239 down_read(&afs_cells_sem);
239 read_lock(&afs_cells_lock); 240 read_lock(&afs_cells_lock);
240 241
241 if (name) { 242 if (name) {
242 /* if the cell was named, look 243 /* if the cell was named, look for it in the cell record list */
243 list_for_each_entry(cell, &afs 244 list_for_each_entry(cell, &afs_cells, link) {
244 if (strncmp(cell->name 245 if (strncmp(cell->name, name, namesz) == 0) {
245 afs_get_cell(c 246 afs_get_cell(cell);
246 goto found; 247 goto found;
247 } 248 }
248 } 249 }
249 cell = ERR_PTR(-ENOENT); 250 cell = ERR_PTR(-ENOENT);
250 found: 251 found:
251 ; 252 ;
252 } else { 253 } else {
253 cell = afs_cell_root; 254 cell = afs_cell_root;
254 if (!cell) { 255 if (!cell) {
255 /* this should not hap 256 /* this should not happen unless user tries to mount
256 * when root cell is n 257 * when root cell is not set. Return an impossibly
257 * bizzare errno to al 258 * bizzare errno to alert the user. Things like
258 * ENOENT might be "mo 259 * ENOENT might be "more appropriate" but they happen
259 * for other reasons. 260 * for other reasons.
260 */ 261 */
261 cell = ERR_PTR(-EDESTA 262 cell = ERR_PTR(-EDESTADDRREQ);
262 } else { 263 } else {
263 afs_get_cell(cell); 264 afs_get_cell(cell);
264 } 265 }
265 266
266 } 267 }
267 268
268 read_unlock(&afs_cells_lock); 269 read_unlock(&afs_cells_lock);
269 up_read(&afs_cells_sem); 270 up_read(&afs_cells_sem);
270 _leave(" = %p", cell); 271 _leave(" = %p", cell);
271 return cell; 272 return cell;
272 } 273 }
273 274
274 #if 0 275 #if 0
275 /* 276 /*
276 * try and get a cell record 277 * try and get a cell record
277 */ 278 */
278 struct afs_cell *afs_get_cell_maybe(struct afs 279 struct afs_cell *afs_get_cell_maybe(struct afs_cell *cell)
279 { 280 {
280 write_lock(&afs_cells_lock); 281 write_lock(&afs_cells_lock);
281 282
282 if (cell && !list_empty(&cell->link)) 283 if (cell && !list_empty(&cell->link))
283 afs_get_cell(cell); 284 afs_get_cell(cell);
284 else 285 else
285 cell = NULL; 286 cell = NULL;
286 287
287 write_unlock(&afs_cells_lock); 288 write_unlock(&afs_cells_lock);
288 return cell; 289 return cell;
289 } 290 }
290 #endif /* 0 */ 291 #endif /* 0 */
291 292
292 /* 293 /*
293 * destroy a cell record 294 * destroy a cell record
294 */ 295 */
295 void afs_put_cell(struct afs_cell *cell) 296 void afs_put_cell(struct afs_cell *cell)
296 { 297 {
297 if (!cell) 298 if (!cell)
298 return; 299 return;
299 300
300 _enter("%p{%d,%s}", cell, atomic_read( 301 _enter("%p{%d,%s}", cell, atomic_read(&cell->usage), cell->name);
301 302
302 ASSERTCMP(atomic_read(&cell->usage), > 303 ASSERTCMP(atomic_read(&cell->usage), >, 0);
303 304
304 /* to prevent a race, the decrement an 305 /* to prevent a race, the decrement and the dequeue must be effectively
305 * atomic */ 306 * atomic */
306 write_lock(&afs_cells_lock); 307 write_lock(&afs_cells_lock);
307 308
308 if (likely(!atomic_dec_and_test(&cell- 309 if (likely(!atomic_dec_and_test(&cell->usage))) {
309 write_unlock(&afs_cells_lock); 310 write_unlock(&afs_cells_lock);
310 _leave(""); 311 _leave("");
311 return; 312 return;
312 } 313 }
313 314
314 ASSERT(list_empty(&cell->servers)); 315 ASSERT(list_empty(&cell->servers));
315 ASSERT(list_empty(&cell->vl_list)); 316 ASSERT(list_empty(&cell->vl_list));
316 317
317 write_unlock(&afs_cells_lock); 318 write_unlock(&afs_cells_lock);
318 319
319 wake_up(&afs_cells_freeable_wq); 320 wake_up(&afs_cells_freeable_wq);
320 321
321 _leave(" [unused]"); 322 _leave(" [unused]");
322 } 323 }
323 324
324 /* 325 /*
325 * destroy a cell record 326 * destroy a cell record
326 * - must be called with the afs_cells_sem wri 327 * - must be called with the afs_cells_sem write-locked
327 * - cell->link should have been broken by the 328 * - cell->link should have been broken by the caller
328 */ 329 */
329 static void afs_cell_destroy(struct afs_cell * 330 static void afs_cell_destroy(struct afs_cell *cell)
330 { 331 {
331 _enter("%p{%d,%s}", cell, atomic_read( 332 _enter("%p{%d,%s}", cell, atomic_read(&cell->usage), cell->name);
332 333
333 ASSERTCMP(atomic_read(&cell->usage), > 334 ASSERTCMP(atomic_read(&cell->usage), >=, 0);
334 ASSERT(list_empty(&cell->link)); 335 ASSERT(list_empty(&cell->link));
335 336
336 /* wait for everyone to stop using the 337 /* wait for everyone to stop using the cell */
337 if (atomic_read(&cell->usage) > 0) { 338 if (atomic_read(&cell->usage) > 0) {
338 DECLARE_WAITQUEUE(myself, curr 339 DECLARE_WAITQUEUE(myself, current);
339 340
340 _debug("wait for cell %s", cel 341 _debug("wait for cell %s", cell->name);
341 set_current_state(TASK_UNINTER 342 set_current_state(TASK_UNINTERRUPTIBLE);
342 add_wait_queue(&afs_cells_free 343 add_wait_queue(&afs_cells_freeable_wq, &myself);
343 344
344 while (atomic_read(&cell->usag 345 while (atomic_read(&cell->usage) > 0) {
345 schedule(); 346 schedule();
346 set_current_state(TASK 347 set_current_state(TASK_UNINTERRUPTIBLE);
347 } 348 }
348 349
349 remove_wait_queue(&afs_cells_f 350 remove_wait_queue(&afs_cells_freeable_wq, &myself);
350 set_current_state(TASK_RUNNING 351 set_current_state(TASK_RUNNING);
351 } 352 }
352 353
353 _debug("cell dead"); 354 _debug("cell dead");
354 ASSERTCMP(atomic_read(&cell->usage), = 355 ASSERTCMP(atomic_read(&cell->usage), ==, 0);
355 ASSERT(list_empty(&cell->servers)); 356 ASSERT(list_empty(&cell->servers));
356 ASSERT(list_empty(&cell->vl_list)); 357 ASSERT(list_empty(&cell->vl_list));
357 358
358 afs_proc_cell_remove(cell); 359 afs_proc_cell_remove(cell);
359 360
360 down_write(&afs_proc_cells_sem); 361 down_write(&afs_proc_cells_sem);
361 list_del_init(&cell->proc_link); 362 list_del_init(&cell->proc_link);
362 up_write(&afs_proc_cells_sem); 363 up_write(&afs_proc_cells_sem);
363 364
364 #ifdef CONFIG_AFS_FSCACHE !! 365 #ifdef AFS_CACHING_SUPPORT
365 fscache_relinquish_cookie(cell->cache, !! 366 cachefs_relinquish_cookie(cell->cache, 0);
366 #endif 367 #endif
>> 368
367 key_put(cell->anonymous_key); 369 key_put(cell->anonymous_key);
368 kfree(cell); 370 kfree(cell);
369 371
370 _leave(" [destroyed]"); 372 _leave(" [destroyed]");
371 } 373 }
372 374
373 /* 375 /*
374 * purge in-memory cell database on module unl 376 * purge in-memory cell database on module unload or afs_init() failure
375 * - the timeout daemon is stopped before call 377 * - the timeout daemon is stopped before calling this
376 */ 378 */
377 void afs_cell_purge(void) 379 void afs_cell_purge(void)
378 { 380 {
379 struct afs_cell *cell; 381 struct afs_cell *cell;
380 382
381 _enter(""); 383 _enter("");
382 384
383 afs_put_cell(afs_cell_root); 385 afs_put_cell(afs_cell_root);
384 386
385 down_write(&afs_cells_sem); 387 down_write(&afs_cells_sem);
386 388
387 while (!list_empty(&afs_cells)) { 389 while (!list_empty(&afs_cells)) {
388 cell = NULL; 390 cell = NULL;
389 391
390 /* remove the next cell from t 392 /* remove the next cell from the front of the list */
391 write_lock(&afs_cells_lock); 393 write_lock(&afs_cells_lock);
392 394
393 if (!list_empty(&afs_cells)) { 395 if (!list_empty(&afs_cells)) {
394 cell = list_entry(afs_ 396 cell = list_entry(afs_cells.next,
395 stru 397 struct afs_cell, link);
396 list_del_init(&cell->l 398 list_del_init(&cell->link);
397 } 399 }
398 400
399 write_unlock(&afs_cells_lock); 401 write_unlock(&afs_cells_lock);
400 402
401 if (cell) { 403 if (cell) {
402 _debug("PURGING CELL % 404 _debug("PURGING CELL %s (%d)",
403 cell->name, ato 405 cell->name, atomic_read(&cell->usage));
404 406
405 /* now the cell should 407 /* now the cell should be left with no references */
406 afs_cell_destroy(cell) 408 afs_cell_destroy(cell);
407 } 409 }
408 } 410 }
409 411
410 up_write(&afs_cells_sem); 412 up_write(&afs_cells_sem);
411 _leave(""); 413 _leave("");
412 } 414 }
413 415
|
This page was automatically generated by the
LXR engine.
|