Lines Matching +full:1 +full:- +full:cell
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* AFS cell and server record management
15 #include <keys/rxrpc-type.h>
29 if (atomic_dec_and_test(&net->cells_outstanding)) in afs_dec_cells_outstanding()
30 wake_up_var(&net->cells_outstanding); in afs_dec_cells_outstanding()
33 static void afs_set_cell_state(struct afs_cell *cell, enum afs_cell_state state) in afs_set_cell_state() argument
35 smp_store_release(&cell->state, state); /* Commit cell changes before state */ in afs_set_cell_state()
36 smp_wmb(); /* Set cell state before task state */ in afs_set_cell_state()
37 wake_up_var(&cell->state); in afs_set_cell_state()
41 * Look up and get an activation reference on a cell record. The caller must
42 * hold net->cells_lock at least read-locked.
48 struct afs_cell *cell = NULL; in afs_find_cell_locked() local
55 return ERR_PTR(-EINVAL); in afs_find_cell_locked()
57 return ERR_PTR(-ENAMETOOLONG); in afs_find_cell_locked()
60 cell = rcu_dereference_protected(net->ws_cell, in afs_find_cell_locked()
61 lockdep_is_held(&net->cells_lock)); in afs_find_cell_locked()
62 if (!cell) in afs_find_cell_locked()
63 return ERR_PTR(-EDESTADDRREQ); in afs_find_cell_locked()
67 p = net->cells.rb_node; in afs_find_cell_locked()
69 cell = rb_entry(p, struct afs_cell, net_node); in afs_find_cell_locked()
71 n = strncasecmp(cell->name, name, in afs_find_cell_locked()
72 min_t(size_t, cell->name_len, namesz)); in afs_find_cell_locked()
74 n = cell->name_len - namesz; in afs_find_cell_locked()
76 p = p->rb_left; in afs_find_cell_locked()
78 p = p->rb_right; in afs_find_cell_locked()
83 return ERR_PTR(-ENOENT); in afs_find_cell_locked()
86 return afs_use_cell(cell, reason); in afs_find_cell_locked()
90 * Look up and get an activation reference on a cell record.
96 struct afs_cell *cell; in afs_find_cell() local
98 down_read(&net->cells_lock); in afs_find_cell()
99 cell = afs_find_cell_locked(net, name, namesz, reason); in afs_find_cell()
100 up_read(&net->cells_lock); in afs_find_cell()
101 return cell; in afs_find_cell()
105 * Set up a cell record and fill in its name, VL server address list and
113 struct afs_cell *cell; in afs_alloc_cell() local
118 return ERR_PTR(-EINVAL); in afs_alloc_cell()
120 _leave(" = -ENAMETOOLONG"); in afs_alloc_cell()
121 return ERR_PTR(-ENAMETOOLONG); in afs_alloc_cell()
124 /* Prohibit cell names that contain unprintable chars, '/' and '@' or in afs_alloc_cell()
125 * that begin with a dot. This also precludes "@cell". in afs_alloc_cell()
128 return ERR_PTR(-EINVAL); in afs_alloc_cell()
132 return ERR_PTR(-EINVAL); in afs_alloc_cell()
137 cell = kzalloc(sizeof(struct afs_cell), GFP_KERNEL); in afs_alloc_cell()
138 if (!cell) { in afs_alloc_cell()
139 _leave(" = -ENOMEM"); in afs_alloc_cell()
140 return ERR_PTR(-ENOMEM); in afs_alloc_cell()
143 cell->name = kmalloc(1 + namelen + 1, GFP_KERNEL); in afs_alloc_cell()
144 if (!cell->name) { in afs_alloc_cell()
145 kfree(cell); in afs_alloc_cell()
146 return ERR_PTR(-ENOMEM); in afs_alloc_cell()
149 cell->name[0] = '.'; in afs_alloc_cell()
150 cell->name++; in afs_alloc_cell()
151 cell->name_len = namelen; in afs_alloc_cell()
153 cell->name[i] = tolower(name[i]); in afs_alloc_cell()
154 cell->name[i] = 0; in afs_alloc_cell()
156 cell->net = net; in afs_alloc_cell()
157 refcount_set(&cell->ref, 1); in afs_alloc_cell()
158 atomic_set(&cell->active, 0); in afs_alloc_cell()
159 INIT_WORK(&cell->destroyer, afs_destroy_cell_work); in afs_alloc_cell()
160 INIT_WORK(&cell->manager, afs_manage_cell_work); in afs_alloc_cell()
161 timer_setup(&cell->management_timer, afs_cell_timer, 0); in afs_alloc_cell()
162 init_rwsem(&cell->vs_lock); in afs_alloc_cell()
163 cell->volumes = RB_ROOT; in afs_alloc_cell()
164 INIT_HLIST_HEAD(&cell->proc_volumes); in afs_alloc_cell()
165 seqlock_init(&cell->volume_lock); in afs_alloc_cell()
166 cell->fs_servers = RB_ROOT; in afs_alloc_cell()
167 init_rwsem(&cell->fs_lock); in afs_alloc_cell()
168 rwlock_init(&cell->vl_servers_lock); in afs_alloc_cell()
169 cell->flags = (1 << AFS_CELL_FL_CHECK_ALIAS); in afs_alloc_cell()
183 vllist->source = DNS_RECORD_FROM_CONFIG; in afs_alloc_cell()
184 vllist->status = DNS_LOOKUP_NOT_DONE; in afs_alloc_cell()
185 cell->dns_expiry = TIME64_MAX; in afs_alloc_cell()
187 ret = -ENOMEM; in afs_alloc_cell()
191 vllist->source = DNS_RECORD_UNAVAILABLE; in afs_alloc_cell()
192 vllist->status = DNS_LOOKUP_NOT_DONE; in afs_alloc_cell()
193 cell->dns_expiry = ktime_get_real_seconds(); in afs_alloc_cell()
196 rcu_assign_pointer(cell->vl_servers, vllist); in afs_alloc_cell()
198 cell->dns_source = vllist->source; in afs_alloc_cell()
199 cell->dns_status = vllist->status; in afs_alloc_cell()
200 smp_store_release(&cell->dns_lookup_count, 1); /* vs source/status */ in afs_alloc_cell()
201 atomic_inc(&net->cells_outstanding); in afs_alloc_cell()
202 ret = idr_alloc_cyclic(&net->cells_dyn_ino, cell, in afs_alloc_cell()
206 cell->dynroot_ino = ret; in afs_alloc_cell()
207 cell->debug_id = atomic_inc_return(&cell_debug_id); in afs_alloc_cell()
209 trace_afs_cell(cell->debug_id, 1, 0, afs_cell_trace_alloc); in afs_alloc_cell()
211 _leave(" = %p", cell); in afs_alloc_cell()
212 return cell; in afs_alloc_cell()
215 if (ret == -EINVAL) in afs_alloc_cell()
218 afs_put_vlserverlist(cell->net, vllist); in afs_alloc_cell()
219 kfree(cell->name - 1); in afs_alloc_cell()
220 kfree(cell); in afs_alloc_cell()
226 * afs_lookup_cell - Look up or create a cell record.
228 * @name: The name of the cell.
229 * @namesz: The strlen of the cell name.
231 * @excl: T if an error should be given if the cell name already exists.
234 * Look up a cell record by name and query the DNS for VL server addresses if
237 * cell records to be shared even if not yet fully constructed.
244 struct afs_cell *cell, *candidate, *cursor; in afs_lookup_cell() local
252 cell = afs_find_cell(net, name, namesz, trace); in afs_lookup_cell()
253 if (!IS_ERR(cell)) in afs_lookup_cell()
257 /* Assume we're probably going to create a cell and preallocate and in afs_lookup_cell()
271 * cell whilst we were allocating. in afs_lookup_cell()
273 down_write(&net->cells_lock); in afs_lookup_cell()
275 pp = &net->cells.rb_node; in afs_lookup_cell()
281 n = strncasecmp(cursor->name, name, in afs_lookup_cell()
282 min_t(size_t, cursor->name_len, namesz)); in afs_lookup_cell()
284 n = cursor->name_len - namesz; in afs_lookup_cell()
286 pp = &(*pp)->rb_left; in afs_lookup_cell()
288 pp = &(*pp)->rb_right; in afs_lookup_cell()
293 cell = candidate; in afs_lookup_cell()
295 afs_use_cell(cell, trace); in afs_lookup_cell()
296 rb_link_node_rcu(&cell->net_node, parent, pp); in afs_lookup_cell()
297 rb_insert_color(&cell->net_node, &net->cells); in afs_lookup_cell()
298 up_write(&net->cells_lock); in afs_lookup_cell()
300 afs_queue_cell(cell, afs_cell_trace_queue_new); in afs_lookup_cell()
304 state = smp_load_acquire(&cell->state); /* vs error */ in afs_lookup_cell()
307 afs_see_cell(cell, afs_cell_trace_wait); in afs_lookup_cell()
308 wait_var_event(&cell->state, in afs_lookup_cell()
310 state = smp_load_acquire(&cell->state); /* vs error */ in afs_lookup_cell()
317 ret = cell->error; in afs_lookup_cell()
321 _leave(" = %p [cell]", cell); in afs_lookup_cell()
322 return cell; in afs_lookup_cell()
325 _debug("cell exists"); in afs_lookup_cell()
326 cell = cursor; in afs_lookup_cell()
328 ret = -EEXIST; in afs_lookup_cell()
333 up_write(&net->cells_lock); in afs_lookup_cell()
340 afs_unuse_cell(cell, afs_cell_trace_unuse_lookup_error); in afs_lookup_cell()
347 * set the root cell information
348 * - can be called with a module parameter string
349 * - can be called from a write to /proc/fs/afs/rootcell
361 * - in the future we might initialize cell DB here. in afs_cell_init()
373 vllist = cp + 1; in afs_cell_init()
374 len = cp - rootcell; in afs_cell_init()
377 if (len == 0 || !rootcell[0] || rootcell[0] == '.' || rootcell[len - 1] == '.') in afs_cell_init()
378 return -EINVAL; in afs_cell_init()
380 return -EINVAL; in afs_cell_init()
383 return -EINVAL; in afs_cell_init()
385 /* allocate a cell record for the root/workstation cell */ in afs_cell_init()
393 if (!test_and_set_bit(AFS_CELL_FL_NO_GC, &new_root->flags)) in afs_cell_init()
396 /* install the new cell */ in afs_cell_init()
397 down_write(&net->cells_lock); in afs_cell_init()
398 old_root = rcu_replace_pointer(net->ws_cell, new_root, in afs_cell_init()
399 lockdep_is_held(&net->cells_lock)); in afs_cell_init()
400 up_write(&net->cells_lock); in afs_cell_init()
408 * Update a cell's VL server address list from the DNS.
410 static int afs_update_cell(struct afs_cell *cell) in afs_update_cell() argument
418 _enter("%s", cell->name); in afs_update_cell()
420 vllist = afs_dns_query(cell, &expiry); in afs_update_cell()
424 _debug("%s: fail %d", cell->name, ret); in afs_update_cell()
425 if (ret == -ENOMEM) in afs_update_cell()
431 ret = -ENOMEM; in afs_update_cell()
436 case -ENODATA: in afs_update_cell()
437 case -EDESTADDRREQ: in afs_update_cell()
438 vllist->status = DNS_LOOKUP_GOT_NOT_FOUND; in afs_update_cell()
440 case -EAGAIN: in afs_update_cell()
441 case -ECONNREFUSED: in afs_update_cell()
442 vllist->status = DNS_LOOKUP_GOT_TEMP_FAILURE; in afs_update_cell()
445 vllist->status = DNS_LOOKUP_GOT_LOCAL_FAILURE; in afs_update_cell()
450 _debug("%s: got list %d %d", cell->name, vllist->source, vllist->status); in afs_update_cell()
451 cell->dns_status = vllist->status; in afs_update_cell()
461 _debug("%s: status %d", cell->name, vllist->status); in afs_update_cell()
462 if (vllist->source == DNS_RECORD_UNAVAILABLE) { in afs_update_cell()
463 switch (vllist->status) { in afs_update_cell()
465 /* The DNS said that the cell does not exist or there in afs_update_cell()
468 cell->dns_expiry = expiry; in afs_update_cell()
476 cell->dns_expiry = now + 10; in afs_update_cell()
480 cell->dns_expiry = expiry; in afs_update_cell()
486 write_lock(&cell->vl_servers_lock); in afs_update_cell()
487 p = rcu_dereference_protected(cell->vl_servers, true); in afs_update_cell()
488 if (vllist->nr_servers > 0 || p->nr_servers == 0) { in afs_update_cell()
489 rcu_assign_pointer(cell->vl_servers, vllist); in afs_update_cell()
490 cell->dns_source = vllist->source; in afs_update_cell()
493 write_unlock(&cell->vl_servers_lock); in afs_update_cell()
494 afs_put_vlserverlist(cell->net, old); in afs_update_cell()
497 smp_store_release(&cell->dns_lookup_count, in afs_update_cell()
498 cell->dns_lookup_count + 1); /* vs source/status */ in afs_update_cell()
499 wake_up_var(&cell->dns_lookup_count); in afs_update_cell()
505 * Destroy a cell record
509 struct afs_cell *cell = container_of(rcu, struct afs_cell, rcu); in afs_cell_destroy() local
510 struct afs_net *net = cell->net; in afs_cell_destroy()
513 _enter("%p{%s}", cell, cell->name); in afs_cell_destroy()
515 r = refcount_read(&cell->ref); in afs_cell_destroy()
517 trace_afs_cell(cell->debug_id, r, atomic_read(&cell->active), afs_cell_trace_free); in afs_cell_destroy()
519 afs_put_vlserverlist(net, rcu_access_pointer(cell->vl_servers)); in afs_cell_destroy()
520 afs_unuse_cell(cell->alias_of, afs_cell_trace_unuse_alias); in afs_cell_destroy()
521 key_put(cell->anonymous_key); in afs_cell_destroy()
522 idr_remove(&net->cells_dyn_ino, cell->dynroot_ino); in afs_cell_destroy()
523 kfree(cell->name - 1); in afs_cell_destroy()
524 kfree(cell); in afs_cell_destroy()
532 struct afs_cell *cell = container_of(work, struct afs_cell, destroyer); in afs_destroy_cell_work() local
534 afs_see_cell(cell, afs_cell_trace_destroy); in afs_destroy_cell_work()
535 timer_delete_sync(&cell->management_timer); in afs_destroy_cell_work()
536 cancel_work_sync(&cell->manager); in afs_destroy_cell_work()
537 call_rcu(&cell->rcu, afs_cell_destroy); in afs_destroy_cell_work()
541 * Get a reference on a cell record.
543 struct afs_cell *afs_get_cell(struct afs_cell *cell, enum afs_cell_trace reason) in afs_get_cell() argument
547 __refcount_inc(&cell->ref, &r); in afs_get_cell()
548 trace_afs_cell(cell->debug_id, r + 1, atomic_read(&cell->active), reason); in afs_get_cell()
549 return cell; in afs_get_cell()
553 * Drop a reference on a cell record.
555 void afs_put_cell(struct afs_cell *cell, enum afs_cell_trace reason) in afs_put_cell() argument
557 if (cell) { in afs_put_cell()
558 unsigned int debug_id = cell->debug_id; in afs_put_cell()
563 a = atomic_read(&cell->active); in afs_put_cell()
564 zero = __refcount_dec_and_test(&cell->ref, &r); in afs_put_cell()
565 trace_afs_cell(debug_id, r - 1, a, reason); in afs_put_cell()
567 a = atomic_read(&cell->active); in afs_put_cell()
568 WARN(a != 0, "Cell active count %u > 0\n", a); in afs_put_cell()
569 WARN_ON(!queue_work(afs_wq, &cell->destroyer)); in afs_put_cell()
575 * Note a cell becoming more active.
577 struct afs_cell *afs_use_cell(struct afs_cell *cell, enum afs_cell_trace reason) in afs_use_cell() argument
581 __refcount_inc(&cell->ref, &r); in afs_use_cell()
582 a = atomic_inc_return(&cell->active); in afs_use_cell()
583 trace_afs_cell(cell->debug_id, r + 1, a, reason); in afs_use_cell()
584 return cell; in afs_use_cell()
588 * Record a cell becoming less active. When the active counter reaches 1, it
591 void afs_unuse_cell(struct afs_cell *cell, enum afs_cell_trace reason) in afs_unuse_cell() argument
598 if (!cell) in afs_unuse_cell()
601 _enter("%s", cell->name); in afs_unuse_cell()
604 cell->last_inactive = now; in afs_unuse_cell()
606 if (cell->vl_servers->nr_servers) in afs_unuse_cell()
609 debug_id = cell->debug_id; in afs_unuse_cell()
610 a = atomic_dec_return(&cell->active); in afs_unuse_cell()
612 /* 'cell' may now be garbage collected. */ in afs_unuse_cell()
613 afs_set_cell_timer(cell, expire_delay); in afs_unuse_cell()
615 zero = __refcount_dec_and_test(&cell->ref, &r); in afs_unuse_cell()
616 trace_afs_cell(debug_id, r - 1, a, reason); in afs_unuse_cell()
618 WARN_ON(!queue_work(afs_wq, &cell->destroyer)); in afs_unuse_cell()
622 * Note that a cell has been seen.
624 void afs_see_cell(struct afs_cell *cell, enum afs_cell_trace reason) in afs_see_cell() argument
628 r = refcount_read(&cell->ref); in afs_see_cell()
629 a = atomic_read(&cell->active); in afs_see_cell()
630 trace_afs_cell(cell->debug_id, r, a, reason); in afs_see_cell()
634 * Queue a cell for management, giving the workqueue a ref to hold.
636 void afs_queue_cell(struct afs_cell *cell, enum afs_cell_trace reason) in afs_queue_cell() argument
638 queue_work(afs_wq, &cell->manager); in afs_queue_cell()
642 * Cell-specific management timer.
646 struct afs_cell *cell = container_of(timer, struct afs_cell, management_timer); in afs_cell_timer() local
648 afs_see_cell(cell, afs_cell_trace_see_mgmt_timer); in afs_cell_timer()
649 if (refcount_read(&cell->ref) > 0 && cell->net->live) in afs_cell_timer()
650 queue_work(afs_wq, &cell->manager); in afs_cell_timer()
654 * Set/reduce the cell timer.
656 void afs_set_cell_timer(struct afs_cell *cell, unsigned int delay_secs) in afs_set_cell_timer() argument
658 timer_reduce(&cell->management_timer, jiffies + delay_secs * HZ); in afs_set_cell_timer()
664 static int afs_alloc_anon_key(struct afs_cell *cell) in afs_alloc_anon_key() argument
667 char keyname[4 + AFS_MAXCELLNAME + 1], *cp, *dp; in afs_alloc_anon_key()
672 cp = cell->name; in afs_alloc_anon_key()
681 cell->anonymous_key = key; in afs_alloc_anon_key()
684 cell->anonymous_key, key_serial(cell->anonymous_key)); in afs_alloc_anon_key()
689 * Activate a cell.
691 static int afs_activate_cell(struct afs_net *net, struct afs_cell *cell) in afs_activate_cell() argument
697 if (!cell->anonymous_key) { in afs_activate_cell()
698 ret = afs_alloc_anon_key(cell); in afs_activate_cell()
703 ret = afs_proc_cell_setup(cell); in afs_activate_cell()
707 mutex_lock(&net->proc_cells_lock); in afs_activate_cell()
708 for (p = &net->proc_cells.first; *p; p = &(*p)->next) { in afs_activate_cell()
710 if (strcmp(cell->name, pcell->name) < 0) in afs_activate_cell()
714 cell->proc_link.pprev = p; in afs_activate_cell()
715 cell->proc_link.next = *p; in afs_activate_cell()
716 rcu_assign_pointer(*p, &cell->proc_link.next); in afs_activate_cell()
717 if (cell->proc_link.next) in afs_activate_cell()
718 cell->proc_link.next->pprev = &cell->proc_link.next; in afs_activate_cell()
720 mutex_unlock(&net->proc_cells_lock); in afs_activate_cell()
725 * Deactivate a cell.
727 static void afs_deactivate_cell(struct afs_net *net, struct afs_cell *cell) in afs_deactivate_cell() argument
729 _enter("%s", cell->name); in afs_deactivate_cell()
731 afs_proc_cell_remove(cell); in afs_deactivate_cell()
733 mutex_lock(&net->proc_cells_lock); in afs_deactivate_cell()
734 if (!hlist_unhashed(&cell->proc_link)) in afs_deactivate_cell()
735 hlist_del_rcu(&cell->proc_link); in afs_deactivate_cell()
736 mutex_unlock(&net->proc_cells_lock); in afs_deactivate_cell()
741 static bool afs_has_cell_expired(struct afs_cell *cell, time64_t *_next_manage) in afs_has_cell_expired() argument
744 time64_t expire_at = cell->last_inactive; in afs_has_cell_expired()
747 if (atomic_read(&cell->active)) in afs_has_cell_expired()
749 if (!cell->net->live) in afs_has_cell_expired()
752 vllist = rcu_dereference_protected(cell->vl_servers, true); in afs_has_cell_expired()
753 if (vllist && vllist->nr_servers > 0) in afs_has_cell_expired()
764 * Manage a cell record, initialising and destroying it, maintaining its DNS
767 static bool afs_manage_cell(struct afs_cell *cell) in afs_manage_cell() argument
769 struct afs_net *net = cell->net; in afs_manage_cell()
773 _enter("%s", cell->name); in afs_manage_cell()
775 _debug("state %u", cell->state); in afs_manage_cell()
776 switch (cell->state) { in afs_manage_cell()
782 WARN_ON_ONCE(1); in afs_manage_cell()
787 _debug("bad state %u", cell->state); in afs_manage_cell()
788 WARN_ON_ONCE(1); /* Unhandled state */ in afs_manage_cell()
793 ret = afs_activate_cell(net, cell); in afs_manage_cell()
795 cell->error = ret; in afs_manage_cell()
799 afs_set_cell_state(cell, AFS_CELL_ACTIVE); in afs_manage_cell()
802 if (afs_has_cell_expired(cell, &next_manage)) in afs_manage_cell()
805 if (test_and_clear_bit(AFS_CELL_FL_DO_LOOKUP, &cell->flags)) { in afs_manage_cell()
806 ret = afs_update_cell(cell); in afs_manage_cell()
808 cell->error = ret; in afs_manage_cell()
811 if (next_manage < TIME64_MAX && cell->net->live) { in afs_manage_cell()
814 if (next_manage - now <= 0) in afs_manage_cell()
815 afs_queue_cell(cell, afs_cell_trace_queue_again); in afs_manage_cell()
817 afs_set_cell_timer(cell, next_manage - now); in afs_manage_cell()
819 _leave(" [done %u]", cell->state); in afs_manage_cell()
823 down_write(&net->cells_lock); in afs_manage_cell()
825 if (atomic_read(&cell->active)) { in afs_manage_cell()
826 up_write(&net->cells_lock); in afs_manage_cell()
831 * that the cell is caput. in afs_manage_cell()
833 afs_set_cell_state(cell, AFS_CELL_REMOVING); in afs_manage_cell()
835 afs_deactivate_cell(net, cell); in afs_manage_cell()
836 afs_purge_servers(cell); in afs_manage_cell()
838 rb_erase(&cell->net_node, &net->cells); in afs_manage_cell()
839 afs_see_cell(cell, afs_cell_trace_unuse_delete); in afs_manage_cell()
840 up_write(&net->cells_lock); in afs_manage_cell()
842 /* The root volume is pinning the cell */ in afs_manage_cell()
843 afs_put_volume(cell->root_volume, afs_volume_trace_put_cell_root); in afs_manage_cell()
844 cell->root_volume = NULL; in afs_manage_cell()
846 afs_set_cell_state(cell, AFS_CELL_DEAD); in afs_manage_cell()
852 struct afs_cell *cell = container_of(work, struct afs_cell, manager); in afs_manage_cell_work() local
855 afs_see_cell(cell, afs_cell_trace_manage); in afs_manage_cell_work()
856 final_put = afs_manage_cell(cell); in afs_manage_cell_work()
857 afs_see_cell(cell, afs_cell_trace_managed); in afs_manage_cell_work()
859 afs_put_cell(cell, afs_cell_trace_put_final); in afs_manage_cell_work()
863 * Purge in-memory cell database.
872 down_write(&net->cells_lock); in afs_cell_purge()
873 ws = rcu_replace_pointer(net->ws_cell, NULL, in afs_cell_purge()
874 lockdep_is_held(&net->cells_lock)); in afs_cell_purge()
875 up_write(&net->cells_lock); in afs_cell_purge()
879 down_read(&net->cells_lock); in afs_cell_purge()
880 for (cursor = rb_first(&net->cells); cursor; cursor = rb_next(cursor)) { in afs_cell_purge()
881 struct afs_cell *cell = rb_entry(cursor, struct afs_cell, net_node); in afs_cell_purge() local
883 afs_see_cell(cell, afs_cell_trace_purge); in afs_cell_purge()
885 if (test_and_clear_bit(AFS_CELL_FL_NO_GC, &cell->flags)) in afs_cell_purge()
886 afs_unuse_cell(cell, afs_cell_trace_unuse_pin); in afs_cell_purge()
888 afs_queue_cell(cell, afs_cell_trace_queue_purge); in afs_cell_purge()
890 up_read(&net->cells_lock); in afs_cell_purge()
893 wait_var_event(&net->cells_outstanding, in afs_cell_purge()
894 !atomic_read(&net->cells_outstanding)); in afs_cell_purge()