Lines Matching +full:1 +full:- +full:cell
1 /* AFS cell and server record management
19 #include <keys/rxrpc-type.h>
28 if (atomic_dec_and_test(&net->cells_outstanding)) in afs_dec_cells_outstanding()
29 wake_up_var(&net->cells_outstanding); in afs_dec_cells_outstanding()
33 * Set the cell timer to fire after a given delay, assuming it's not already
38 if (net->live) { in afs_set_cell_timer()
39 atomic_inc(&net->cells_outstanding); in afs_set_cell_timer()
40 if (timer_reduce(&net->cells_timer, jiffies + delay * HZ)) in afs_set_cell_timer()
46 * Look up and get an activation reference on a cell record under RCU
52 struct afs_cell *cell = NULL; in afs_lookup_cell_rcu() local
59 return ERR_PTR(-EINVAL); in afs_lookup_cell_rcu()
61 return ERR_PTR(-ENAMETOOLONG); in afs_lookup_cell_rcu()
68 if (cell) in afs_lookup_cell_rcu()
69 afs_put_cell(net, cell); in afs_lookup_cell_rcu()
70 cell = NULL; in afs_lookup_cell_rcu()
71 ret = -ENOENT; in afs_lookup_cell_rcu()
73 read_seqbegin_or_lock(&net->cells_lock, &seq); in afs_lookup_cell_rcu()
76 cell = rcu_dereference_raw(net->ws_cell); in afs_lookup_cell_rcu()
77 if (cell) { in afs_lookup_cell_rcu()
78 afs_get_cell(cell); in afs_lookup_cell_rcu()
82 ret = -EDESTADDRREQ; in afs_lookup_cell_rcu()
86 p = rcu_dereference_raw(net->cells.rb_node); in afs_lookup_cell_rcu()
88 cell = rb_entry(p, struct afs_cell, net_node); in afs_lookup_cell_rcu()
90 n = strncasecmp(cell->name, name, in afs_lookup_cell_rcu()
91 min_t(size_t, cell->name_len, namesz)); in afs_lookup_cell_rcu()
93 n = cell->name_len - namesz; in afs_lookup_cell_rcu()
95 p = rcu_dereference_raw(p->rb_left); in afs_lookup_cell_rcu()
97 p = rcu_dereference_raw(p->rb_right); in afs_lookup_cell_rcu()
99 if (atomic_inc_not_zero(&cell->usage)) { in afs_lookup_cell_rcu()
107 cell = NULL; in afs_lookup_cell_rcu()
110 } while (need_seqretry(&net->cells_lock, seq)); in afs_lookup_cell_rcu()
112 done_seqretry(&net->cells_lock, seq); in afs_lookup_cell_rcu()
114 if (ret != 0 && cell) in afs_lookup_cell_rcu()
115 afs_put_cell(net, cell); in afs_lookup_cell_rcu()
117 return ret == 0 ? cell : ERR_PTR(ret); in afs_lookup_cell_rcu()
121 * Set up a cell record and fill in its name, VL server address list and
128 struct afs_cell *cell; in afs_alloc_cell() local
133 return ERR_PTR(-EINVAL); in afs_alloc_cell()
135 _leave(" = -ENAMETOOLONG"); in afs_alloc_cell()
136 return ERR_PTR(-ENAMETOOLONG); in afs_alloc_cell()
139 /* Prohibit cell names that contain unprintable chars, '/' and '@' or in afs_alloc_cell()
140 * that begin with a dot. This also precludes "@cell". in afs_alloc_cell()
143 return ERR_PTR(-EINVAL); in afs_alloc_cell()
147 return ERR_PTR(-EINVAL); in afs_alloc_cell()
152 cell = kzalloc(sizeof(struct afs_cell), GFP_KERNEL); in afs_alloc_cell()
153 if (!cell) { in afs_alloc_cell()
154 _leave(" = -ENOMEM"); in afs_alloc_cell()
155 return ERR_PTR(-ENOMEM); in afs_alloc_cell()
158 cell->net = net; in afs_alloc_cell()
159 cell->name_len = namelen; in afs_alloc_cell()
161 cell->name[i] = tolower(name[i]); in afs_alloc_cell()
163 atomic_set(&cell->usage, 2); in afs_alloc_cell()
164 INIT_WORK(&cell->manager, afs_manage_cell); in afs_alloc_cell()
165 cell->flags = ((1 << AFS_CELL_FL_NOT_READY) | in afs_alloc_cell()
166 (1 << AFS_CELL_FL_NO_LOOKUP_YET)); in afs_alloc_cell()
167 INIT_LIST_HEAD(&cell->proc_volumes); in afs_alloc_cell()
168 rwlock_init(&cell->proc_lock); in afs_alloc_cell()
169 rwlock_init(&cell->vl_addrs_lock); in afs_alloc_cell()
184 rcu_assign_pointer(cell->vl_addrs, alist); in afs_alloc_cell()
185 cell->dns_expiry = TIME64_MAX; in afs_alloc_cell()
188 _leave(" = %p", cell); in afs_alloc_cell()
189 return cell; in afs_alloc_cell()
192 if (ret == -EINVAL) in afs_alloc_cell()
194 kfree(cell); in afs_alloc_cell()
200 * afs_lookup_cell - Look up or create a cell record.
202 * @name: The name of the cell.
203 * @namesz: The strlen of the cell name.
205 * @excl: T if an error should be given if the cell name already exists.
207 * Look up a cell record by name and query the DNS for VL server addresses if
210 * cell records to be shared even if not yet fully constructed.
216 struct afs_cell *cell, *candidate, *cursor; in afs_lookup_cell() local
224 cell = afs_lookup_cell_rcu(net, name, namesz); in afs_lookup_cell()
226 if (!IS_ERR(cell)) in afs_lookup_cell()
230 /* Assume we're probably going to create a cell and preallocate and in afs_lookup_cell()
244 * cell whilst we were allocating. in afs_lookup_cell()
246 write_seqlock(&net->cells_lock); in afs_lookup_cell()
248 pp = &net->cells.rb_node; in afs_lookup_cell()
254 n = strncasecmp(cursor->name, name, in afs_lookup_cell()
255 min_t(size_t, cursor->name_len, namesz)); in afs_lookup_cell()
257 n = cursor->name_len - namesz; in afs_lookup_cell()
259 pp = &(*pp)->rb_left; in afs_lookup_cell()
261 pp = &(*pp)->rb_right; in afs_lookup_cell()
266 cell = candidate; in afs_lookup_cell()
268 rb_link_node_rcu(&cell->net_node, parent, pp); in afs_lookup_cell()
269 rb_insert_color(&cell->net_node, &net->cells); in afs_lookup_cell()
270 atomic_inc(&net->cells_outstanding); in afs_lookup_cell()
271 write_sequnlock(&net->cells_lock); in afs_lookup_cell()
273 queue_work(afs_wq, &cell->manager); in afs_lookup_cell()
277 ret = wait_on_bit(&cell->flags, AFS_CELL_FL_NOT_READY, TASK_INTERRUPTIBLE); in afs_lookup_cell()
280 switch (READ_ONCE(cell->state)) { in afs_lookup_cell()
282 ret = cell->error; in afs_lookup_cell()
285 _debug("weird %u %d", cell->state, cell->error); in afs_lookup_cell()
291 _leave(" = %p [cell]", cell); in afs_lookup_cell()
292 return cell; in afs_lookup_cell()
295 _debug("cell exists"); in afs_lookup_cell()
296 cell = cursor; in afs_lookup_cell()
298 ret = -EEXIST; in afs_lookup_cell()
303 write_sequnlock(&net->cells_lock); in afs_lookup_cell()
309 afs_put_cell(net, cell); in afs_lookup_cell()
316 * set the root cell information
317 * - can be called with a module parameter string
318 * - can be called from a write to /proc/fs/afs/rootcell
330 * - in the future we might initialize cell DB here. in afs_cell_init()
342 vllist = cp + 1; in afs_cell_init()
343 len = cp - rootcell; in afs_cell_init()
346 /* allocate a cell record for the root cell */ in afs_cell_init()
353 if (!test_and_set_bit(AFS_CELL_FL_NO_GC, &new_root->flags)) in afs_cell_init()
356 /* install the new cell */ in afs_cell_init()
357 write_seqlock(&net->cells_lock); in afs_cell_init()
358 old_root = rcu_access_pointer(net->ws_cell); in afs_cell_init()
359 rcu_assign_pointer(net->ws_cell, new_root); in afs_cell_init()
360 write_sequnlock(&net->cells_lock); in afs_cell_init()
368 * Update a cell's VL server address list from the DNS.
370 static void afs_update_cell(struct afs_cell *cell) in afs_update_cell() argument
375 _enter("%s", cell->name); in afs_update_cell()
377 alist = afs_dns_query(cell, &expiry); in afs_update_cell()
380 case -ENODATA: in afs_update_cell()
381 /* The DNS said that the cell does not exist */ in afs_update_cell()
382 set_bit(AFS_CELL_FL_NOT_FOUND, &cell->flags); in afs_update_cell()
383 clear_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags); in afs_update_cell()
384 cell->dns_expiry = ktime_get_real_seconds() + 61; in afs_update_cell()
387 case -EAGAIN: in afs_update_cell()
388 case -ECONNREFUSED: in afs_update_cell()
390 set_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags); in afs_update_cell()
391 cell->dns_expiry = ktime_get_real_seconds() + 10; in afs_update_cell()
395 cell->error = -EDESTADDRREQ; in afs_update_cell()
397 clear_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags); in afs_update_cell()
398 clear_bit(AFS_CELL_FL_NOT_FOUND, &cell->flags); in afs_update_cell()
401 * non-reentrant work item. in afs_update_cell()
403 old = rcu_dereference_protected(cell->vl_addrs, true); in afs_update_cell()
404 rcu_assign_pointer(cell->vl_addrs, alist); in afs_update_cell()
405 cell->dns_expiry = expiry; in afs_update_cell()
411 if (test_and_clear_bit(AFS_CELL_FL_NO_LOOKUP_YET, &cell->flags)) in afs_update_cell()
412 wake_up_bit(&cell->flags, AFS_CELL_FL_NO_LOOKUP_YET); in afs_update_cell()
415 afs_set_cell_timer(cell->net, cell->dns_expiry - now); in afs_update_cell()
420 * Destroy a cell record
424 struct afs_cell *cell = container_of(rcu, struct afs_cell, rcu); in afs_cell_destroy() local
426 _enter("%p{%s}", cell, cell->name); in afs_cell_destroy()
428 ASSERTCMP(atomic_read(&cell->usage), ==, 0); in afs_cell_destroy()
430 afs_put_addrlist(rcu_access_pointer(cell->vl_addrs)); in afs_cell_destroy()
431 key_put(cell->anonymous_key); in afs_cell_destroy()
432 kfree(cell); in afs_cell_destroy()
438 * Queue the cell manager.
442 int outstanding = atomic_inc_return(&net->cells_outstanding); in afs_queue_cell_manager()
446 if (!queue_work(afs_wq, &net->cells_manager)) in afs_queue_cell_manager()
451 * Cell management timer. We have an increment on cells_outstanding that we
459 if (!queue_work(afs_wq, &net->cells_manager)) in afs_cells_timer()
464 * Get a reference on a cell record.
466 struct afs_cell *afs_get_cell(struct afs_cell *cell) in afs_get_cell() argument
468 atomic_inc(&cell->usage); in afs_get_cell()
469 return cell; in afs_get_cell()
473 * Drop a reference on a cell record.
475 void afs_put_cell(struct afs_net *net, struct afs_cell *cell) in afs_put_cell() argument
479 if (!cell) in afs_put_cell()
482 _enter("%s", cell->name); in afs_put_cell()
485 cell->last_inactive = now; in afs_put_cell()
487 if (!test_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags) && in afs_put_cell()
488 !test_bit(AFS_CELL_FL_NOT_FOUND, &cell->flags)) in afs_put_cell()
491 if (atomic_dec_return(&cell->usage) > 1) in afs_put_cell()
494 /* 'cell' may now be garbage collected. */ in afs_put_cell()
501 static int afs_alloc_anon_key(struct afs_cell *cell) in afs_alloc_anon_key() argument
504 char keyname[4 + AFS_MAXCELLNAME + 1], *cp, *dp; in afs_alloc_anon_key()
509 cp = cell->name; in afs_alloc_anon_key()
518 cell->anonymous_key = key; in afs_alloc_anon_key()
521 cell->anonymous_key, key_serial(cell->anonymous_key)); in afs_alloc_anon_key()
526 * Activate a cell.
528 static int afs_activate_cell(struct afs_net *net, struct afs_cell *cell) in afs_activate_cell() argument
534 if (!cell->anonymous_key) { in afs_activate_cell()
535 ret = afs_alloc_anon_key(cell); in afs_activate_cell()
541 cell->cache = fscache_acquire_cookie(afs_cache_netfs.primary_index, in afs_activate_cell()
543 cell->name, strlen(cell->name), in afs_activate_cell()
545 cell, 0, true); in afs_activate_cell()
547 ret = afs_proc_cell_setup(cell); in afs_activate_cell()
551 mutex_lock(&net->proc_cells_lock); in afs_activate_cell()
552 for (p = &net->proc_cells.first; *p; p = &(*p)->next) { in afs_activate_cell()
554 if (strcmp(cell->name, pcell->name) < 0) in afs_activate_cell()
558 cell->proc_link.pprev = p; in afs_activate_cell()
559 cell->proc_link.next = *p; in afs_activate_cell()
560 rcu_assign_pointer(*p, &cell->proc_link.next); in afs_activate_cell()
561 if (cell->proc_link.next) in afs_activate_cell()
562 cell->proc_link.next->pprev = &cell->proc_link.next; in afs_activate_cell()
564 afs_dynroot_mkdir(net, cell); in afs_activate_cell()
565 mutex_unlock(&net->proc_cells_lock); in afs_activate_cell()
570 * Deactivate a cell.
572 static void afs_deactivate_cell(struct afs_net *net, struct afs_cell *cell) in afs_deactivate_cell() argument
574 _enter("%s", cell->name); in afs_deactivate_cell()
576 afs_proc_cell_remove(cell); in afs_deactivate_cell()
578 mutex_lock(&net->proc_cells_lock); in afs_deactivate_cell()
579 hlist_del_rcu(&cell->proc_link); in afs_deactivate_cell()
580 afs_dynroot_rmdir(net, cell); in afs_deactivate_cell()
581 mutex_unlock(&net->proc_cells_lock); in afs_deactivate_cell()
584 fscache_relinquish_cookie(cell->cache, NULL, false); in afs_deactivate_cell()
585 cell->cache = NULL; in afs_deactivate_cell()
592 * Manage a cell record, initialising and destroying it, maintaining its DNS
597 struct afs_cell *cell = container_of(work, struct afs_cell, manager); in afs_manage_cell() local
598 struct afs_net *net = cell->net; in afs_manage_cell()
602 _enter("%s", cell->name); in afs_manage_cell()
605 _debug("state %u", cell->state); in afs_manage_cell()
606 switch (cell->state) { in afs_manage_cell()
609 write_seqlock(&net->cells_lock); in afs_manage_cell()
610 usage = 1; in afs_manage_cell()
611 deleted = atomic_try_cmpxchg_relaxed(&cell->usage, &usage, 0); in afs_manage_cell()
613 rb_erase(&cell->net_node, &net->cells); in afs_manage_cell()
614 write_sequnlock(&net->cells_lock); in afs_manage_cell()
617 if (cell->state == AFS_CELL_FAILED) in afs_manage_cell()
619 cell->state = AFS_CELL_UNSET; in afs_manage_cell()
623 cell->state = AFS_CELL_ACTIVATING; in afs_manage_cell()
627 ret = afs_activate_cell(net, cell); in afs_manage_cell()
631 cell->state = AFS_CELL_ACTIVE; in afs_manage_cell()
633 clear_bit(AFS_CELL_FL_NOT_READY, &cell->flags); in afs_manage_cell()
634 wake_up_bit(&cell->flags, AFS_CELL_FL_NOT_READY); in afs_manage_cell()
638 if (atomic_read(&cell->usage) > 1) { in afs_manage_cell()
640 if (cell->dns_expiry <= now && net->live) in afs_manage_cell()
641 afs_update_cell(cell); in afs_manage_cell()
644 cell->state = AFS_CELL_DEACTIVATING; in afs_manage_cell()
648 set_bit(AFS_CELL_FL_NOT_READY, &cell->flags); in afs_manage_cell()
649 if (atomic_read(&cell->usage) > 1) in afs_manage_cell()
651 afs_deactivate_cell(net, cell); in afs_manage_cell()
652 cell->state = AFS_CELL_INACTIVE; in afs_manage_cell()
658 _debug("bad state %u", cell->state); in afs_manage_cell()
662 cell->error = ret; in afs_manage_cell()
663 afs_deactivate_cell(net, cell); in afs_manage_cell()
665 cell->state = AFS_CELL_FAILED; in afs_manage_cell()
667 if (test_and_clear_bit(AFS_CELL_FL_NOT_READY, &cell->flags)) in afs_manage_cell()
668 wake_up_bit(&cell->flags, AFS_CELL_FL_NOT_READY); in afs_manage_cell()
672 cell->state = AFS_CELL_ACTIVE; in afs_manage_cell()
674 clear_bit(AFS_CELL_FL_NOT_READY, &cell->flags); in afs_manage_cell()
675 wake_up_bit(&cell->flags, AFS_CELL_FL_NOT_READY); in afs_manage_cell()
676 _leave(" [deact->act]"); in afs_manage_cell()
680 _leave(" [done %u]", cell->state); in afs_manage_cell()
684 call_rcu(&cell->rcu, afs_cell_destroy); in afs_manage_cell()
686 _leave(" [destruct %d]", atomic_read(&net->cells_outstanding)); in afs_manage_cell()
694 * Note that constructed cell records may only be removed from net->cells by
699 * Note also that we were given an increment on net->cells_outstanding by
707 bool purging = !net->live; in afs_manage_cells()
711 /* Trawl the cell database looking for cells that have expired from in afs_manage_cells()
715 read_seqlock_excl(&net->cells_lock); in afs_manage_cells()
717 for (cursor = rb_first(&net->cells); cursor; cursor = rb_next(cursor)) { in afs_manage_cells()
718 struct afs_cell *cell = in afs_manage_cells() local
723 usage = atomic_read(&cell->usage); in afs_manage_cells()
724 _debug("manage %s %u", cell->name, usage); in afs_manage_cells()
726 ASSERTCMP(usage, >=, 1); in afs_manage_cells()
729 if (test_and_clear_bit(AFS_CELL_FL_NO_GC, &cell->flags)) in afs_manage_cells()
730 usage = atomic_dec_return(&cell->usage); in afs_manage_cells()
731 ASSERTCMP(usage, ==, 1); in afs_manage_cells()
734 if (usage == 1) { in afs_manage_cells()
735 time64_t expire_at = cell->last_inactive; in afs_manage_cells()
737 if (!test_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags) && in afs_manage_cells()
738 !test_bit(AFS_CELL_FL_NOT_FOUND, &cell->flags)) in afs_manage_cells()
747 if (cell->dns_expiry <= now) in afs_manage_cells()
749 else if (cell->dns_expiry <= next_manage) in afs_manage_cells()
750 next_manage = cell->dns_expiry; in afs_manage_cells()
754 queue_work(afs_wq, &cell->manager); in afs_manage_cells()
757 read_sequnlock_excl(&net->cells_lock); in afs_manage_cells()
766 if (next_manage - now <= 0) { in afs_manage_cells()
767 if (queue_work(afs_wq, &net->cells_manager)) in afs_manage_cells()
768 atomic_inc(&net->cells_outstanding); in afs_manage_cells()
770 afs_set_cell_timer(net, next_manage - now); in afs_manage_cells()
775 _leave(" [%d]", atomic_read(&net->cells_outstanding)); in afs_manage_cells()
779 * Purge in-memory cell database.
787 write_seqlock(&net->cells_lock); in afs_cell_purge()
788 ws = rcu_access_pointer(net->ws_cell); in afs_cell_purge()
789 RCU_INIT_POINTER(net->ws_cell, NULL); in afs_cell_purge()
790 write_sequnlock(&net->cells_lock); in afs_cell_purge()
794 if (del_timer_sync(&net->cells_timer)) in afs_cell_purge()
795 atomic_dec(&net->cells_outstanding); in afs_cell_purge()
801 wait_var_event(&net->cells_outstanding, in afs_cell_purge()
802 !atomic_read(&net->cells_outstanding)); in afs_cell_purge()