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