1 /* cell.c: AFS cell and server record management 2 * 3 * Copyright (C) 2002 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 12 #include <linux/module.h> 13 #include <linux/sched.h> 14 #include <linux/slab.h> 15 #include <rxrpc/peer.h> 16 #include <rxrpc/connection.h> 17 #include "volume.h" 18 #include "cell.h" 19 #include "server.h" 20 #include "transport.h" 21 #include "vlclient.h" 22 #include "kafstimod.h" 23 #include "super.h" 24 #include "internal.h" 25 26 DECLARE_RWSEM(afs_proc_cells_sem); 27 LIST_HEAD(afs_proc_cells); 28 29 static struct list_head afs_cells = LIST_HEAD_INIT(afs_cells); 30 static DEFINE_RWLOCK(afs_cells_lock); 31 static DECLARE_RWSEM(afs_cells_sem); /* add/remove serialisation */ 32 static struct afs_cell *afs_cell_root; 33 34 #ifdef AFS_CACHING_SUPPORT 35 static cachefs_match_val_t afs_cell_cache_match(void *target, 36 const void *entry); 37 static void afs_cell_cache_update(void *source, void *entry); 38 39 struct cachefs_index_def afs_cache_cell_index_def = { 40 .name = "cell_ix", 41 .data_size = sizeof(struct afs_cache_cell), 42 .keys[0] = { CACHEFS_INDEX_KEYS_ASCIIZ, 64 }, 43 .match = afs_cell_cache_match, 44 .update = afs_cell_cache_update, 45 }; 46 #endif 47 48 /*****************************************************************************/ 49 /* 50 * create a cell record 51 * - "name" is the name of the cell 52 * - "vllist" is a colon separated list of IP addresses in "a.b.c.d" format 53 */ 54 int afs_cell_create(const char *name, char *vllist, struct afs_cell **_cell) 55 { 56 struct afs_cell *cell; 57 char *next; 58 int ret; 59 60 _enter("%s", name); 61 62 BUG_ON(!name); /* TODO: want to look up "this cell" in the cache */ 63 64 /* allocate and initialise a cell record */ 65 cell = kmalloc(sizeof(struct afs_cell) + strlen(name) + 1, GFP_KERNEL); 66 if (!cell) { 67 _leave(" = -ENOMEM"); 68 return -ENOMEM; 69 } 70 71 down_write(&afs_cells_sem); 72 73 memset(cell, 0, sizeof(struct afs_cell)); 74 atomic_set(&cell->usage, 0); 75 76 INIT_LIST_HEAD(&cell->link); 77 78 rwlock_init(&cell->sv_lock); 79 INIT_LIST_HEAD(&cell->sv_list); 80 INIT_LIST_HEAD(&cell->sv_graveyard); 81 spin_lock_init(&cell->sv_gylock); 82 83 init_rwsem(&cell->vl_sem); 84 INIT_LIST_HEAD(&cell->vl_list); 85 INIT_LIST_HEAD(&cell->vl_graveyard); 86 spin_lock_init(&cell->vl_gylock); 87 88 strcpy(cell->name,name); 89 90 /* fill in the VL server list from the rest of the string */ 91 ret = -EINVAL; 92 do { 93 unsigned a, b, c, d; 94 95 next = strchr(vllist, ':'); 96 if (next) 97 *next++ = 0; 98 99 if (sscanf(vllist, "%u.%u.%u.%u", &a, &b, &c, &d) != 4) 100 goto badaddr; 101 102 if (a > 255 || b > 255 || c > 255 || d > 255) 103 goto badaddr; 104 105 cell->vl_addrs[cell->vl_naddrs++].s_addr = 106 htonl((a << 24) | (b << 16) | (c << 8) | d); 107 108 if (cell->vl_naddrs >= AFS_CELL_MAX_ADDRS) 109 break; 110 111 } while(vllist = next, vllist); 112 113 /* add a proc dir for this cell */ 114 ret = afs_proc_cell_setup(cell); 115 if (ret < 0) 116 goto error; 117 118 #ifdef AFS_CACHING_SUPPORT 119 /* put it up for caching */ 120 cachefs_acquire_cookie(afs_cache_netfs.primary_index, 121 &afs_vlocation_cache_index_def, 122 cell, 123 &cell->cache); 124 #endif 125 126 /* add to the cell lists */ 127 write_lock(&afs_cells_lock); 128 list_add_tail(&cell->link, &afs_cells); 129 write_unlock(&afs_cells_lock); 130 131 down_write(&afs_proc_cells_sem); 132 list_add_tail(&cell->proc_link, &afs_proc_cells); 133 up_write(&afs_proc_cells_sem); 134 135 *_cell = cell; 136 up_write(&afs_cells_sem); 137 138 _leave(" = 0 (%p)", cell); 139 return 0; 140 141 badaddr: 142 printk(KERN_ERR "kAFS: bad VL server IP address: '%s'\n", vllist); 143 error: 144 up_write(&afs_cells_sem); 145 kfree(cell); 146 _leave(" = %d", ret); 147 return ret; 148 } /* end afs_cell_create() */ 149 150 /*****************************************************************************/ 151 /* 152 * initialise the cell database from module parameters 153 */ 154 int afs_cell_init(char *rootcell) 155 { 156 struct afs_cell *old_root, *new_root; 157 char *cp; 158 int ret; 159 160 _enter(""); 161 162 if (!rootcell) { 163 /* module is loaded with no parameters, or built statically. 164 * - in the future we might initialize cell DB here. 165 */ 166 _leave(" = 0 (but no root)"); 167 return 0; 168 } 169 170 cp = strchr(rootcell, ':'); 171 if (!cp) { 172 printk(KERN_ERR "kAFS: no VL server IP addresses specified\n"); 173 _leave(" = %d (no colon)", -EINVAL); 174 return -EINVAL; 175 } 176 177 /* allocate a cell record for the root cell */ 178 *cp++ = 0; 179 ret = afs_cell_create(rootcell, cp, &new_root); 180 if (ret < 0) { 181 _leave(" = %d", ret); 182 return ret; 183 } 184 185 /* as afs_put_cell() takes locks by itself, we have to do 186 * a little gymnastics to be race-free. 187 */ 188 afs_get_cell(new_root); 189 190 write_lock(&afs_cells_lock); 191 while (afs_cell_root) { 192 old_root = afs_cell_root; 193 afs_cell_root = NULL; 194 write_unlock(&afs_cells_lock); 195 afs_put_cell(old_root); 196 write_lock(&afs_cells_lock); 197 } 198 afs_cell_root = new_root; 199 write_unlock(&afs_cells_lock); 200 201 _leave(" = %d", ret); 202 return ret; 203 204 } /* end afs_cell_init() */ 205 206 /*****************************************************************************/ 207 /* 208 * lookup a cell record 209 */ 210 int afs_cell_lookup(const char *name, unsigned namesz, struct afs_cell **_cell) 211 { 212 struct afs_cell *cell; 213 int ret; 214 215 _enter("\"%*.*s\",", namesz, namesz, name ? name : ""); 216 217 *_cell = NULL; 218 219 if (name) { 220 /* if the cell was named, look for it in the cell record list */ 221 ret = -ENOENT; 222 cell = NULL; 223 read_lock(&afs_cells_lock); 224 225 list_for_each_entry(cell, &afs_cells, link) { 226 if (strncmp(cell->name, name, namesz) == 0) { 227 afs_get_cell(cell); 228 goto found; 229 } 230 } 231 cell = NULL; 232 found: 233 234 read_unlock(&afs_cells_lock); 235 236 if (cell) 237 ret = 0; 238 } 239 else { 240 read_lock(&afs_cells_lock); 241 242 cell = afs_cell_root; 243 if (!cell) { 244 /* this should not happen unless user tries to mount 245 * when root cell is not set. Return an impossibly 246 * bizzare errno to alert the user. Things like 247 * ENOENT might be "more appropriate" but they happen 248 * for other reasons. 249 */ 250 ret = -EDESTADDRREQ; 251 } 252 else { 253 afs_get_cell(cell); 254 ret = 0; 255 } 256 257 read_unlock(&afs_cells_lock); 258 } 259 260 *_cell = cell; 261 _leave(" = %d (%p)", ret, cell); 262 return ret; 263 264 } /* end afs_cell_lookup() */ 265 266 /*****************************************************************************/ 267 /* 268 * try and get a cell record 269 */ 270 struct afs_cell *afs_get_cell_maybe(struct afs_cell **_cell) 271 { 272 struct afs_cell *cell; 273 274 write_lock(&afs_cells_lock); 275 276 cell = *_cell; 277 if (cell && !list_empty(&cell->link)) 278 afs_get_cell(cell); 279 else 280 cell = NULL; 281 282 write_unlock(&afs_cells_lock); 283 284 return cell; 285 } /* end afs_get_cell_maybe() */ 286 287 /*****************************************************************************/ 288 /* 289 * destroy a cell record 290 */ 291 void afs_put_cell(struct afs_cell *cell) 292 { 293 if (!cell) 294 return; 295 296 _enter("%p{%d,%s}", cell, atomic_read(&cell->usage), cell->name); 297 298 /* sanity check */ 299 BUG_ON(atomic_read(&cell->usage) <= 0); 300 301 /* to prevent a race, the decrement and the dequeue must be effectively 302 * atomic */ 303 write_lock(&afs_cells_lock); 304 305 if (likely(!atomic_dec_and_test(&cell->usage))) { 306 write_unlock(&afs_cells_lock); 307 _leave(""); 308 return; 309 } 310 311 write_unlock(&afs_cells_lock); 312 313 BUG_ON(!list_empty(&cell->sv_list)); 314 BUG_ON(!list_empty(&cell->sv_graveyard)); 315 BUG_ON(!list_empty(&cell->vl_list)); 316 BUG_ON(!list_empty(&cell->vl_graveyard)); 317 318 _leave(" [unused]"); 319 } /* end afs_put_cell() */ 320 321 /*****************************************************************************/ 322 /* 323 * destroy a cell record 324 */ 325 static void afs_cell_destroy(struct afs_cell *cell) 326 { 327 _enter("%p{%d,%s}", cell, atomic_read(&cell->usage), cell->name); 328 329 /* to prevent a race, the decrement and the dequeue must be effectively 330 * atomic */ 331 write_lock(&afs_cells_lock); 332 333 /* sanity check */ 334 BUG_ON(atomic_read(&cell->usage) != 0); 335 336 list_del_init(&cell->link); 337 338 write_unlock(&afs_cells_lock); 339 340 down_write(&afs_cells_sem); 341 342 afs_proc_cell_remove(cell); 343 344 down_write(&afs_proc_cells_sem); 345 list_del_init(&cell->proc_link); 346 up_write(&afs_proc_cells_sem); 347 348 #ifdef AFS_CACHING_SUPPORT 349 cachefs_relinquish_cookie(cell->cache, 0); 350 #endif 351 352 up_write(&afs_cells_sem); 353 354 BUG_ON(!list_empty(&cell->sv_list)); 355 BUG_ON(!list_empty(&cell->sv_graveyard)); 356 BUG_ON(!list_empty(&cell->vl_list)); 357 BUG_ON(!list_empty(&cell->vl_graveyard)); 358 359 /* finish cleaning up the cell */ 360 kfree(cell); 361 362 _leave(" [destroyed]"); 363 } /* end afs_cell_destroy() */ 364 365 /*****************************************************************************/ 366 /* 367 * lookup the server record corresponding to an Rx RPC peer 368 */ 369 int afs_server_find_by_peer(const struct rxrpc_peer *peer, 370 struct afs_server **_server) 371 { 372 struct afs_server *server; 373 struct afs_cell *cell; 374 375 _enter("%p{a=%08x},", peer, ntohl(peer->addr.s_addr)); 376 377 /* search the cell list */ 378 read_lock(&afs_cells_lock); 379 380 list_for_each_entry(cell, &afs_cells, link) { 381 382 _debug("? cell %s",cell->name); 383 384 write_lock(&cell->sv_lock); 385 386 /* check the active list */ 387 list_for_each_entry(server, &cell->sv_list, link) { 388 _debug("?? server %08x", ntohl(server->addr.s_addr)); 389 390 if (memcmp(&server->addr, &peer->addr, 391 sizeof(struct in_addr)) == 0) 392 goto found_server; 393 } 394 395 /* check the inactive list */ 396 spin_lock(&cell->sv_gylock); 397 list_for_each_entry(server, &cell->sv_graveyard, link) { 398 _debug("?? dead server %08x", 399 ntohl(server->addr.s_addr)); 400 401 if (memcmp(&server->addr, &peer->addr, 402 sizeof(struct in_addr)) == 0) 403 goto found_dead_server; 404 } 405 spin_unlock(&cell->sv_gylock); 406 407 write_unlock(&cell->sv_lock); 408 } 409 read_unlock(&afs_cells_lock); 410 411 _leave(" = -ENOENT"); 412 return -ENOENT; 413 414 /* we found it in the graveyard - resurrect it */ 415 found_dead_server: 416 list_del(&server->link); 417 list_add_tail(&server->link, &cell->sv_list); 418 afs_get_server(server); 419 afs_kafstimod_del_timer(&server->timeout); 420 spin_unlock(&cell->sv_gylock); 421 goto success; 422 423 /* we found it - increment its ref count and return it */ 424 found_server: 425 afs_get_server(server); 426 427 success: 428 write_unlock(&cell->sv_lock); 429 read_unlock(&afs_cells_lock); 430 431 *_server = server; 432 _leave(" = 0 (s=%p c=%p)", server, cell); 433 return 0; 434 435 } /* end afs_server_find_by_peer() */ 436 437 /*****************************************************************************/ 438 /* 439 * purge in-memory cell database on module unload or afs_init() failure 440 * - the timeout daemon is stopped before calling this 441 */ 442 void afs_cell_purge(void) 443 { 444 struct afs_vlocation *vlocation; 445 struct afs_cell *cell; 446 447 _enter(""); 448 449 afs_put_cell(afs_cell_root); 450 451 while (!list_empty(&afs_cells)) { 452 cell = NULL; 453 454 /* remove the next cell from the front of the list */ 455 write_lock(&afs_cells_lock); 456 457 if (!list_empty(&afs_cells)) { 458 cell = list_entry(afs_cells.next, 459 struct afs_cell, link); 460 list_del_init(&cell->link); 461 } 462 463 write_unlock(&afs_cells_lock); 464 465 if (cell) { 466 _debug("PURGING CELL %s (%d)", 467 cell->name, atomic_read(&cell->usage)); 468 469 BUG_ON(!list_empty(&cell->sv_list)); 470 BUG_ON(!list_empty(&cell->vl_list)); 471 472 /* purge the cell's VL graveyard list */ 473 _debug(" - clearing VL graveyard"); 474 475 spin_lock(&cell->vl_gylock); 476 477 while (!list_empty(&cell->vl_graveyard)) { 478 vlocation = list_entry(cell->vl_graveyard.next, 479 struct afs_vlocation, 480 link); 481 list_del_init(&vlocation->link); 482 483 afs_kafstimod_del_timer(&vlocation->timeout); 484 485 spin_unlock(&cell->vl_gylock); 486 487 afs_vlocation_do_timeout(vlocation); 488 /* TODO: race if move to use krxtimod instead 489 * of kafstimod */ 490 491 spin_lock(&cell->vl_gylock); 492 } 493 494 spin_unlock(&cell->vl_gylock); 495 496 /* purge the cell's server graveyard list */ 497 _debug(" - clearing server graveyard"); 498 499 spin_lock(&cell->sv_gylock); 500 501 while (!list_empty(&cell->sv_graveyard)) { 502 struct afs_server *server; 503 504 server = list_entry(cell->sv_graveyard.next, 505 struct afs_server, link); 506 list_del_init(&server->link); 507 508 afs_kafstimod_del_timer(&server->timeout); 509 510 spin_unlock(&cell->sv_gylock); 511 512 afs_server_do_timeout(server); 513 514 spin_lock(&cell->sv_gylock); 515 } 516 517 spin_unlock(&cell->sv_gylock); 518 519 /* now the cell should be left with no references */ 520 afs_cell_destroy(cell); 521 } 522 } 523 524 _leave(""); 525 } /* end afs_cell_purge() */ 526 527 /*****************************************************************************/ 528 /* 529 * match a cell record obtained from the cache 530 */ 531 #ifdef AFS_CACHING_SUPPORT 532 static cachefs_match_val_t afs_cell_cache_match(void *target, 533 const void *entry) 534 { 535 const struct afs_cache_cell *ccell = entry; 536 struct afs_cell *cell = target; 537 538 _enter("{%s},{%s}", ccell->name, cell->name); 539 540 if (strncmp(ccell->name, cell->name, sizeof(ccell->name)) == 0) { 541 _leave(" = SUCCESS"); 542 return CACHEFS_MATCH_SUCCESS; 543 } 544 545 _leave(" = FAILED"); 546 return CACHEFS_MATCH_FAILED; 547 } /* end afs_cell_cache_match() */ 548 #endif 549 550 /*****************************************************************************/ 551 /* 552 * update a cell record in the cache 553 */ 554 #ifdef AFS_CACHING_SUPPORT 555 static void afs_cell_cache_update(void *source, void *entry) 556 { 557 struct afs_cache_cell *ccell = entry; 558 struct afs_cell *cell = source; 559 560 _enter("%p,%p", source, entry); 561 562 strncpy(ccell->name, cell->name, sizeof(ccell->name)); 563 564 memcpy(ccell->vl_servers, 565 cell->vl_addrs, 566 min(sizeof(ccell->vl_servers), sizeof(cell->vl_addrs))); 567 568 } /* end afs_cell_cache_update() */ 569 #endif 570