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