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