]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - fs/afs/cell.c
afs: Overhaul volume and server record caching and fileserver rotation
[mirror_ubuntu-bionic-kernel.git] / fs / afs / cell.c
1 /* AFS cell and server record management
2 *
3 * Copyright (C) 2002, 2017 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/slab.h>
13 #include <linux/key.h>
14 #include <linux/ctype.h>
15 #include <linux/dns_resolver.h>
16 #include <linux/sched.h>
17 #include <linux/inet.h>
18 #include <keys/rxrpc-type.h>
19 #include "internal.h"
20
21 unsigned __read_mostly afs_cell_gc_delay = 10;
22
23 static void afs_manage_cell(struct work_struct *);
24
25 static void afs_dec_cells_outstanding(struct afs_net *net)
26 {
27 if (atomic_dec_and_test(&net->cells_outstanding))
28 wake_up_atomic_t(&net->cells_outstanding);
29 }
30
31 /*
32 * Set the cell timer to fire after a given delay, assuming it's not already
33 * set for an earlier time.
34 */
35 static void afs_set_cell_timer(struct afs_net *net, time64_t delay)
36 {
37 if (net->live) {
38 atomic_inc(&net->cells_outstanding);
39 if (timer_reduce(&net->cells_timer, jiffies + delay * HZ))
40 afs_dec_cells_outstanding(net);
41 }
42 }
43
44 /*
45 * Look up and get an activation reference on a cell record under RCU
46 * conditions. The caller must hold the RCU read lock.
47 */
48 struct afs_cell *afs_lookup_cell_rcu(struct afs_net *net,
49 const char *name, unsigned int namesz)
50 {
51 struct afs_cell *cell = NULL;
52 struct rb_node *p;
53 int n, seq = 0, ret = 0;
54
55 _enter("%*.*s", namesz, namesz, name);
56
57 if (name && namesz == 0)
58 return ERR_PTR(-EINVAL);
59 if (namesz > AFS_MAXCELLNAME)
60 return ERR_PTR(-ENAMETOOLONG);
61
62 do {
63 /* Unfortunately, rbtree walking doesn't give reliable results
64 * under just the RCU read lock, so we have to check for
65 * changes.
66 */
67 if (cell)
68 afs_put_cell(net, cell);
69 cell = NULL;
70 ret = -ENOENT;
71
72 read_seqbegin_or_lock(&net->cells_lock, &seq);
73
74 if (!name) {
75 cell = rcu_dereference_raw(net->ws_cell);
76 if (cell) {
77 afs_get_cell(cell);
78 continue;
79 }
80 ret = -EDESTADDRREQ;
81 continue;
82 }
83
84 p = rcu_dereference_raw(net->cells.rb_node);
85 while (p) {
86 cell = rb_entry(p, struct afs_cell, net_node);
87
88 n = strncasecmp(cell->name, name,
89 min_t(size_t, cell->name_len, namesz));
90 if (n == 0)
91 n = cell->name_len - namesz;
92 if (n < 0) {
93 p = rcu_dereference_raw(p->rb_left);
94 } else if (n > 0) {
95 p = rcu_dereference_raw(p->rb_right);
96 } else {
97 if (atomic_inc_not_zero(&cell->usage)) {
98 ret = 0;
99 break;
100 }
101 /* We want to repeat the search, this time with
102 * the lock properly locked.
103 */
104 }
105 cell = NULL;
106 }
107
108 } while (need_seqretry(&net->cells_lock, seq));
109
110 done_seqretry(&net->cells_lock, seq);
111
112 return ret == 0 ? cell : ERR_PTR(ret);
113 }
114
115 /*
116 * Set up a cell record and fill in its name, VL server address list and
117 * allocate an anonymous key
118 */
119 static struct afs_cell *afs_alloc_cell(struct afs_net *net,
120 const char *name, unsigned int namelen,
121 const char *vllist)
122 {
123 struct afs_cell *cell;
124 int i, ret;
125
126 ASSERT(name);
127 if (namelen == 0)
128 return ERR_PTR(-EINVAL);
129 if (namelen > AFS_MAXCELLNAME) {
130 _leave(" = -ENAMETOOLONG");
131 return ERR_PTR(-ENAMETOOLONG);
132 }
133
134 _enter("%*.*s,%s", namelen, namelen, name, vllist);
135
136 cell = kzalloc(sizeof(struct afs_cell), GFP_KERNEL);
137 if (!cell) {
138 _leave(" = -ENOMEM");
139 return ERR_PTR(-ENOMEM);
140 }
141
142 cell->net = net;
143 cell->name_len = namelen;
144 for (i = 0; i < namelen; i++)
145 cell->name[i] = tolower(name[i]);
146
147 atomic_set(&cell->usage, 2);
148 INIT_WORK(&cell->manager, afs_manage_cell);
149 cell->flags = ((1 << AFS_CELL_FL_NOT_READY) |
150 (1 << AFS_CELL_FL_NO_LOOKUP_YET));
151 INIT_LIST_HEAD(&cell->proc_volumes);
152 rwlock_init(&cell->proc_lock);
153 rwlock_init(&cell->vl_addrs_lock);
154
155 /* Fill in the VL server list if we were given a list of addresses to
156 * use.
157 */
158 if (vllist) {
159 struct afs_addr_list *alist;
160
161 alist = afs_parse_text_addrs(vllist, strlen(vllist), ':',
162 VL_SERVICE, AFS_VL_PORT);
163 if (IS_ERR(alist)) {
164 ret = PTR_ERR(alist);
165 goto parse_failed;
166 }
167
168 rcu_assign_pointer(cell->vl_addrs, alist);
169 cell->dns_expiry = TIME64_MAX;
170 }
171
172 _leave(" = %p", cell);
173 return cell;
174
175 parse_failed:
176 if (ret == -EINVAL)
177 printk(KERN_ERR "kAFS: bad VL server IP address\n");
178 kfree(cell);
179 _leave(" = %d", ret);
180 return ERR_PTR(ret);
181 }
182
183 /*
184 * afs_lookup_cell - Look up or create a cell record.
185 * @net: The network namespace
186 * @name: The name of the cell.
187 * @namesz: The strlen of the cell name.
188 * @vllist: A colon/comma separated list of numeric IP addresses or NULL.
189 * @excl: T if an error should be given if the cell name already exists.
190 *
191 * Look up a cell record by name and query the DNS for VL server addresses if
192 * needed. Note that that actual DNS query is punted off to the manager thread
193 * so that this function can return immediately if interrupted whilst allowing
194 * cell records to be shared even if not yet fully constructed.
195 */
196 struct afs_cell *afs_lookup_cell(struct afs_net *net,
197 const char *name, unsigned int namesz,
198 const char *vllist, bool excl)
199 {
200 struct afs_cell *cell, *candidate, *cursor;
201 struct rb_node *parent, **pp;
202 int ret, n;
203
204 _enter("%s,%s", name, vllist);
205
206 if (!excl) {
207 rcu_read_lock();
208 cell = afs_lookup_cell_rcu(net, name, namesz);
209 rcu_read_unlock();
210 if (!IS_ERR(cell)) {
211 if (excl) {
212 afs_put_cell(net, cell);
213 return ERR_PTR(-EEXIST);
214 }
215 goto wait_for_cell;
216 }
217 }
218
219 /* Assume we're probably going to create a cell and preallocate and
220 * mostly set up a candidate record. We can then use this to stash the
221 * name, the net namespace and VL server addresses.
222 *
223 * We also want to do this before we hold any locks as it may involve
224 * upcalling to userspace to make DNS queries.
225 */
226 candidate = afs_alloc_cell(net, name, namesz, vllist);
227 if (IS_ERR(candidate)) {
228 _leave(" = %ld", PTR_ERR(candidate));
229 return candidate;
230 }
231
232 /* Find the insertion point and check to see if someone else added a
233 * cell whilst we were allocating.
234 */
235 write_seqlock(&net->cells_lock);
236
237 pp = &net->cells.rb_node;
238 parent = NULL;
239 while (*pp) {
240 parent = *pp;
241 cursor = rb_entry(parent, struct afs_cell, net_node);
242
243 n = strncasecmp(cursor->name, name,
244 min_t(size_t, cursor->name_len, namesz));
245 if (n == 0)
246 n = cursor->name_len - namesz;
247 if (n < 0)
248 pp = &(*pp)->rb_left;
249 else if (n > 0)
250 pp = &(*pp)->rb_right;
251 else
252 goto cell_already_exists;
253 }
254
255 cell = candidate;
256 candidate = NULL;
257 rb_link_node_rcu(&cell->net_node, parent, pp);
258 rb_insert_color(&cell->net_node, &net->cells);
259 atomic_inc(&net->cells_outstanding);
260 write_sequnlock(&net->cells_lock);
261
262 queue_work(afs_wq, &cell->manager);
263
264 wait_for_cell:
265 _debug("wait_for_cell");
266 ret = wait_on_bit(&cell->flags, AFS_CELL_FL_NOT_READY, TASK_INTERRUPTIBLE);
267 smp_rmb();
268
269 switch (READ_ONCE(cell->state)) {
270 case AFS_CELL_FAILED:
271 ret = cell->error;
272 goto error;
273 default:
274 _debug("weird %u %d", cell->state, cell->error);
275 goto error;
276 case AFS_CELL_ACTIVE:
277 break;
278 }
279
280 _leave(" = %p [cell]", cell);
281 return cell;
282
283 cell_already_exists:
284 _debug("cell exists");
285 cell = cursor;
286 if (excl) {
287 ret = -EEXIST;
288 } else {
289 afs_get_cell(cursor);
290 ret = 0;
291 }
292 write_sequnlock(&net->cells_lock);
293 kfree(candidate);
294 if (ret == 0)
295 goto wait_for_cell;
296 goto error_noput;
297 error:
298 afs_put_cell(net, cell);
299 error_noput:
300 _leave(" = %d [error]", ret);
301 return ERR_PTR(ret);
302 }
303
304 /*
305 * set the root cell information
306 * - can be called with a module parameter string
307 * - can be called from a write to /proc/fs/afs/rootcell
308 */
309 int afs_cell_init(struct afs_net *net, const char *rootcell)
310 {
311 struct afs_cell *old_root, *new_root;
312 const char *cp, *vllist;
313 size_t len;
314
315 _enter("");
316
317 if (!rootcell) {
318 /* module is loaded with no parameters, or built statically.
319 * - in the future we might initialize cell DB here.
320 */
321 _leave(" = 0 [no root]");
322 return 0;
323 }
324
325 cp = strchr(rootcell, ':');
326 if (!cp) {
327 _debug("kAFS: no VL server IP addresses specified");
328 vllist = NULL;
329 len = strlen(rootcell);
330 } else {
331 vllist = cp + 1;
332 len = cp - rootcell;
333 }
334
335 /* allocate a cell record for the root cell */
336 new_root = afs_lookup_cell(net, rootcell, len, vllist, false);
337 if (IS_ERR(new_root)) {
338 _leave(" = %ld", PTR_ERR(new_root));
339 return PTR_ERR(new_root);
340 }
341
342 set_bit(AFS_CELL_FL_NO_GC, &new_root->flags);
343 afs_get_cell(new_root);
344
345 /* install the new cell */
346 write_seqlock(&net->cells_lock);
347 old_root = net->ws_cell;
348 net->ws_cell = new_root;
349 write_sequnlock(&net->cells_lock);
350
351 afs_put_cell(net, old_root);
352 _leave(" = 0");
353 return 0;
354 }
355
356 /*
357 * Update a cell's VL server address list from the DNS.
358 */
359 static void afs_update_cell(struct afs_cell *cell)
360 {
361 struct afs_addr_list *alist, *old;
362 time64_t now, expiry;
363
364 _enter("%s", cell->name);
365
366 alist = afs_dns_query(cell, &expiry);
367 if (IS_ERR(alist)) {
368 switch (PTR_ERR(alist)) {
369 case -ENODATA:
370 /* The DNS said that the cell does not exist */
371 set_bit(AFS_CELL_FL_NOT_FOUND, &cell->flags);
372 clear_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags);
373 cell->dns_expiry = ktime_get_real_seconds() + 61;
374 break;
375
376 case -EAGAIN:
377 case -ECONNREFUSED:
378 default:
379 set_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags);
380 cell->dns_expiry = ktime_get_real_seconds() + 10;
381 break;
382 }
383
384 cell->error = -EDESTADDRREQ;
385 } else {
386 clear_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags);
387 clear_bit(AFS_CELL_FL_NOT_FOUND, &cell->flags);
388
389 /* Exclusion on changing vl_addrs is achieved by a
390 * non-reentrant work item.
391 */
392 old = rcu_dereference_protected(cell->vl_addrs, true);
393 rcu_assign_pointer(cell->vl_addrs, alist);
394 cell->dns_expiry = expiry;
395
396 if (old)
397 afs_put_addrlist(old);
398 }
399
400 if (test_and_clear_bit(AFS_CELL_FL_NO_LOOKUP_YET, &cell->flags))
401 wake_up_bit(&cell->flags, AFS_CELL_FL_NO_LOOKUP_YET);
402
403 now = ktime_get_real_seconds();
404 afs_set_cell_timer(cell->net, cell->dns_expiry - now);
405 _leave("");
406 }
407
408 /*
409 * Destroy a cell record
410 */
411 static void afs_cell_destroy(struct rcu_head *rcu)
412 {
413 struct afs_cell *cell = container_of(rcu, struct afs_cell, rcu);
414
415 _enter("%p{%s}", cell, cell->name);
416
417 ASSERTCMP(atomic_read(&cell->usage), ==, 0);
418
419 afs_put_addrlist(cell->vl_addrs);
420 key_put(cell->anonymous_key);
421 kfree(cell);
422
423 _leave(" [destroyed]");
424 }
425
426 /*
427 * Queue the cell manager.
428 */
429 static void afs_queue_cell_manager(struct afs_net *net)
430 {
431 int outstanding = atomic_inc_return(&net->cells_outstanding);
432
433 _enter("%d", outstanding);
434
435 if (!queue_work(afs_wq, &net->cells_manager))
436 afs_dec_cells_outstanding(net);
437 }
438
439 /*
440 * Cell management timer. We have an increment on cells_outstanding that we
441 * need to pass along to the work item.
442 */
443 void afs_cells_timer(struct timer_list *timer)
444 {
445 struct afs_net *net = container_of(timer, struct afs_net, cells_timer);
446
447 _enter("");
448 if (!queue_work(afs_wq, &net->cells_manager))
449 afs_dec_cells_outstanding(net);
450 }
451
452 /*
453 * Get a reference on a cell record.
454 */
455 struct afs_cell *afs_get_cell(struct afs_cell *cell)
456 {
457 atomic_inc(&cell->usage);
458 return cell;
459 }
460
461 /*
462 * Drop a reference on a cell record.
463 */
464 void afs_put_cell(struct afs_net *net, struct afs_cell *cell)
465 {
466 time64_t now, expire_delay;
467
468 if (!cell)
469 return;
470
471 _enter("%s", cell->name);
472
473 now = ktime_get_real_seconds();
474 cell->last_inactive = now;
475 expire_delay = 0;
476 if (!test_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags) &&
477 !test_bit(AFS_CELL_FL_NOT_FOUND, &cell->flags))
478 expire_delay = afs_cell_gc_delay;
479
480 if (atomic_dec_return(&cell->usage) > 1)
481 return;
482
483 /* 'cell' may now be garbage collected. */
484 afs_set_cell_timer(net, expire_delay);
485 }
486
487 /*
488 * Allocate a key to use as a placeholder for anonymous user security.
489 */
490 static int afs_alloc_anon_key(struct afs_cell *cell)
491 {
492 struct key *key;
493 char keyname[4 + AFS_MAXCELLNAME + 1], *cp, *dp;
494
495 /* Create a key to represent an anonymous user. */
496 memcpy(keyname, "afs@", 4);
497 dp = keyname + 4;
498 cp = cell->name;
499 do {
500 *dp++ = tolower(*cp);
501 } while (*cp++);
502
503 key = rxrpc_get_null_key(keyname);
504 if (IS_ERR(key))
505 return PTR_ERR(key);
506
507 cell->anonymous_key = key;
508
509 _debug("anon key %p{%x}",
510 cell->anonymous_key, key_serial(cell->anonymous_key));
511 return 0;
512 }
513
514 /*
515 * Activate a cell.
516 */
517 static int afs_activate_cell(struct afs_net *net, struct afs_cell *cell)
518 {
519 int ret;
520
521 if (!cell->anonymous_key) {
522 ret = afs_alloc_anon_key(cell);
523 if (ret < 0)
524 return ret;
525 }
526
527 #ifdef CONFIG_AFS_FSCACHE
528 cell->cache = fscache_acquire_cookie(afs_cache_netfs.primary_index,
529 &afs_cell_cache_index_def,
530 cell, true);
531 #endif
532 ret = afs_proc_cell_setup(net, cell);
533 if (ret < 0)
534 return ret;
535 spin_lock(&net->proc_cells_lock);
536 list_add_tail(&cell->proc_link, &net->proc_cells);
537 spin_unlock(&net->proc_cells_lock);
538 return 0;
539 }
540
541 /*
542 * Deactivate a cell.
543 */
544 static void afs_deactivate_cell(struct afs_net *net, struct afs_cell *cell)
545 {
546 _enter("%s", cell->name);
547
548 afs_proc_cell_remove(net, cell);
549
550 spin_lock(&net->proc_cells_lock);
551 list_del_init(&cell->proc_link);
552 spin_unlock(&net->proc_cells_lock);
553
554 #ifdef CONFIG_AFS_FSCACHE
555 fscache_relinquish_cookie(cell->cache, 0);
556 cell->cache = NULL;
557 #endif
558
559 _leave("");
560 }
561
562 /*
563 * Manage a cell record, initialising and destroying it, maintaining its DNS
564 * records.
565 */
566 static void afs_manage_cell(struct work_struct *work)
567 {
568 struct afs_cell *cell = container_of(work, struct afs_cell, manager);
569 struct afs_net *net = cell->net;
570 bool deleted;
571 int ret, usage;
572
573 _enter("%s", cell->name);
574
575 again:
576 _debug("state %u", cell->state);
577 switch (cell->state) {
578 case AFS_CELL_INACTIVE:
579 case AFS_CELL_FAILED:
580 write_seqlock(&net->cells_lock);
581 usage = 1;
582 deleted = atomic_try_cmpxchg_relaxed(&cell->usage, &usage, 0);
583 if (deleted)
584 rb_erase(&cell->net_node, &net->cells);
585 write_sequnlock(&net->cells_lock);
586 if (deleted)
587 goto final_destruction;
588 if (cell->state == AFS_CELL_FAILED)
589 goto done;
590 cell->state = AFS_CELL_UNSET;
591 goto again;
592
593 case AFS_CELL_UNSET:
594 cell->state = AFS_CELL_ACTIVATING;
595 goto again;
596
597 case AFS_CELL_ACTIVATING:
598 ret = afs_activate_cell(net, cell);
599 if (ret < 0)
600 goto activation_failed;
601
602 cell->state = AFS_CELL_ACTIVE;
603 smp_wmb();
604 clear_bit(AFS_CELL_FL_NOT_READY, &cell->flags);
605 wake_up_bit(&cell->flags, AFS_CELL_FL_NOT_READY);
606 goto again;
607
608 case AFS_CELL_ACTIVE:
609 if (atomic_read(&cell->usage) > 1) {
610 time64_t now = ktime_get_real_seconds();
611 if (cell->dns_expiry <= now && net->live)
612 afs_update_cell(cell);
613 goto done;
614 }
615 cell->state = AFS_CELL_DEACTIVATING;
616 goto again;
617
618 case AFS_CELL_DEACTIVATING:
619 set_bit(AFS_CELL_FL_NOT_READY, &cell->flags);
620 if (atomic_read(&cell->usage) > 1)
621 goto reverse_deactivation;
622 afs_deactivate_cell(net, cell);
623 cell->state = AFS_CELL_INACTIVE;
624 goto again;
625
626 default:
627 break;
628 }
629 _debug("bad state %u", cell->state);
630 BUG(); /* Unhandled state */
631
632 activation_failed:
633 cell->error = ret;
634 afs_deactivate_cell(net, cell);
635
636 cell->state = AFS_CELL_FAILED;
637 smp_wmb();
638 if (test_and_clear_bit(AFS_CELL_FL_NOT_READY, &cell->flags))
639 wake_up_bit(&cell->flags, AFS_CELL_FL_NOT_READY);
640 goto again;
641
642 reverse_deactivation:
643 cell->state = AFS_CELL_ACTIVE;
644 smp_wmb();
645 clear_bit(AFS_CELL_FL_NOT_READY, &cell->flags);
646 wake_up_bit(&cell->flags, AFS_CELL_FL_NOT_READY);
647 _leave(" [deact->act]");
648 return;
649
650 done:
651 _leave(" [done %u]", cell->state);
652 return;
653
654 final_destruction:
655 call_rcu(&cell->rcu, afs_cell_destroy);
656 afs_dec_cells_outstanding(net);
657 _leave(" [destruct %d]", atomic_read(&net->cells_outstanding));
658 }
659
660 /*
661 * Manage the records of cells known to a network namespace. This includes
662 * updating the DNS records and garbage collecting unused cells that were
663 * automatically added.
664 *
665 * Note that constructed cell records may only be removed from net->cells by
666 * this work item, so it is safe for this work item to stash a cursor pointing
667 * into the tree and then return to caller (provided it skips cells that are
668 * still under construction).
669 *
670 * Note also that we were given an increment on net->cells_outstanding by
671 * whoever queued us that we need to deal with before returning.
672 */
673 void afs_manage_cells(struct work_struct *work)
674 {
675 struct afs_net *net = container_of(work, struct afs_net, cells_manager);
676 struct rb_node *cursor;
677 time64_t now = ktime_get_real_seconds(), next_manage = TIME64_MAX;
678 bool purging = !net->live;
679
680 _enter("");
681
682 /* Trawl the cell database looking for cells that have expired from
683 * lack of use and cells whose DNS results have expired and dispatch
684 * their managers.
685 */
686 read_seqlock_excl(&net->cells_lock);
687
688 for (cursor = rb_first(&net->cells); cursor; cursor = rb_next(cursor)) {
689 struct afs_cell *cell =
690 rb_entry(cursor, struct afs_cell, net_node);
691 unsigned usage;
692 bool sched_cell = false;
693
694 usage = atomic_read(&cell->usage);
695 _debug("manage %s %u", cell->name, usage);
696
697 ASSERTCMP(usage, >=, 1);
698
699 if (purging) {
700 if (test_and_clear_bit(AFS_CELL_FL_NO_GC, &cell->flags))
701 usage = atomic_dec_return(&cell->usage);
702 ASSERTCMP(usage, ==, 1);
703 }
704
705 if (usage == 1) {
706 time64_t expire_at = cell->last_inactive;
707
708 if (!test_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags) &&
709 !test_bit(AFS_CELL_FL_NOT_FOUND, &cell->flags))
710 expire_at += afs_cell_gc_delay;
711 if (purging || expire_at <= now)
712 sched_cell = true;
713 else if (expire_at < next_manage)
714 next_manage = expire_at;
715 }
716
717 if (!purging) {
718 if (cell->dns_expiry <= now)
719 sched_cell = true;
720 else if (cell->dns_expiry <= next_manage)
721 next_manage = cell->dns_expiry;
722 }
723
724 if (sched_cell)
725 queue_work(afs_wq, &cell->manager);
726 }
727
728 read_sequnlock_excl(&net->cells_lock);
729
730 /* Update the timer on the way out. We have to pass an increment on
731 * cells_outstanding in the namespace that we are in to the timer or
732 * the work scheduler.
733 */
734 if (!purging && next_manage < TIME64_MAX) {
735 now = ktime_get_real_seconds();
736
737 if (next_manage - now <= 0) {
738 if (queue_work(afs_wq, &net->cells_manager))
739 atomic_inc(&net->cells_outstanding);
740 } else {
741 afs_set_cell_timer(net, next_manage - now);
742 }
743 }
744
745 afs_dec_cells_outstanding(net);
746 _leave(" [%d]", atomic_read(&net->cells_outstanding));
747 }
748
749 /*
750 * Purge in-memory cell database.
751 */
752 void afs_cell_purge(struct afs_net *net)
753 {
754 struct afs_cell *ws;
755
756 _enter("");
757
758 write_seqlock(&net->cells_lock);
759 ws = net->ws_cell;
760 net->ws_cell = NULL;
761 write_sequnlock(&net->cells_lock);
762 afs_put_cell(net, ws);
763
764 _debug("del timer");
765 if (del_timer_sync(&net->cells_timer))
766 atomic_dec(&net->cells_outstanding);
767
768 _debug("kick mgr");
769 afs_queue_cell_manager(net);
770
771 _debug("wait");
772 wait_on_atomic_t(&net->cells_outstanding, atomic_t_wait,
773 TASK_UNINTERRUPTIBLE);
774 _leave("");
775 }