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