// SPDX-License-Identifier: GPL-2.0-or-later /* AFS cell and server record management * *Copyright(C)2002,2017RedHat,Inc.AllRightsReserved. *WrittenbyDavidHowells(dhowells@redhat.com)
*/
staticvoid afs_dec_cells_outstanding(struct afs_net *net)
{ if (atomic_dec_and_test(&net->cells_outstanding))
wake_up_var(&net->cells_outstanding);
}
staticvoid afs_set_cell_state(struct afs_cell *cell, enum afs_cell_state state)
{
smp_store_release(&cell->state, state); /* Commit cell changes before state */
smp_wmb(); /* Set cell state before task state */
wake_up_var(&cell->state);
}
/* Provide a VL server list, filling it in if we were given a list of *addressestouse.
*/ if (addresses) {
vllist = afs_parse_text_addrs(net,
addresses, strlen(addresses), ':',
VL_SERVICE, AFS_VL_PORT); if (IS_ERR(vllist)) {
ret = PTR_ERR(vllist);
vllist = NULL; goto parse_failed;
}
wait_for_cell:
state = smp_load_acquire(&cell->state); /* vs error */ switch (state) { case AFS_CELL_ACTIVE: case AFS_CELL_DEAD: break; case AFS_CELL_UNLOOKED: default: if (reason == AFS_LOOKUP_CELL_PRELOAD ||
reason == AFS_LOOKUP_CELL_ROOTCELL) break;
_debug("wait_for_cell");
afs_see_cell(cell, afs_cell_trace_wait);
wait_var_event(&cell->state,
({
state = smp_load_acquire(&cell->state); /* vs error */
state == AFS_CELL_ACTIVE || state == AFS_CELL_DEAD;
}));
_debug("waited_for_cell %d %d", cell->state, cell->error);
}
no_wait: /* Check the state obtained from the wait check. */
state = smp_load_acquire(&cell->state); /* vs error */ if (state == AFS_CELL_DEAD) {
ret = cell->error; goto error;
} if (state == AFS_CELL_ACTIVE) { switch (cell->dns_status) { case DNS_LOOKUP_NOT_DONE: if (cell->dns_source == DNS_RECORD_FROM_CONFIG) {
ret = 0; break;
}
fallthrough; default:
ret = -EIO; goto error; case DNS_LOOKUP_GOOD: case DNS_LOOKUP_GOOD_WITH_BAD:
ret = 0; break; case DNS_LOOKUP_GOT_NOT_FOUND:
ret = -ENOENT; goto error; case DNS_LOOKUP_BAD:
ret = -EREMOTEIO; goto error; case DNS_LOOKUP_GOT_LOCAL_FAILURE: case DNS_LOOKUP_GOT_TEMP_FAILURE: case DNS_LOOKUP_GOT_NS_FAILURE:
ret = -EDESTADDRREQ; goto error;
}
}
_leave(" = %p [cell]", cell); return cell;
cell_already_exists:
_debug("cell exists");
cell = cursor; if (reason == AFS_LOOKUP_CELL_PRELOAD) {
ret = -EEXIST;
} else {
afs_use_cell(cursor, trace);
ret = 0;
}
up_write(&net->cells_lock); if (candidate)
afs_put_cell(candidate, afs_cell_trace_put_candidate); if (ret == 0) goto wait_for_cell; goto error_noput;
error:
afs_unuse_cell(cell, afs_cell_trace_unuse_lookup_error);
error_noput:
_leave(" = %d [error]", ret); return ERR_PTR(ret);
}
if (!rootcell) { /* module is loaded with no parameters, or built statically. *-inthefuturewemightinitializecellDBhere.
*/
_leave(" = 0 [no root]"); return0;
}
cp = strchr(rootcell, ':'); if (!cp) {
_debug("kAFS: no VL server IP addresses specified");
vllist = NULL;
len = strlen(rootcell);
} else {
vllist = cp + 1;
len = cp - rootcell;
}
now = ktime_get_real_seconds(); if (min_ttl > max_ttl)
max_ttl = min_ttl; if (expiry < now + min_ttl)
expiry = now + min_ttl; elseif (expiry > now + max_ttl)
expiry = now + max_ttl;
_debug("%s: status %d", cell->name, vllist->status); if (vllist->source == DNS_RECORD_UNAVAILABLE) { switch (vllist->status) { case DNS_LOOKUP_GOT_NOT_FOUND: /* The DNS said that the cell does not exist or there *weren'tanyaddressestobehad.
*/
cell->dns_expiry = expiry; break;
case DNS_LOOKUP_BAD: case DNS_LOOKUP_GOT_LOCAL_FAILURE: case DNS_LOOKUP_GOT_TEMP_FAILURE: case DNS_LOOKUP_GOT_NS_FAILURE: default:
cell->dns_expiry = now + 10; break;
}
} else {
cell->dns_expiry = expiry;
}
/* Replace the VL server list if the new record has servers or the old *recorddoesn't.
*/
write_lock(&cell->vl_servers_lock);
p = rcu_dereference_protected(cell->vl_servers, true); if (vllist->nr_servers > 0 || p->nr_servers == 0) {
rcu_assign_pointer(cell->vl_servers, vllist);
cell->dns_source = vllist->source;
old = p;
}
write_unlock(&cell->vl_servers_lock);
afs_put_vlserverlist(cell->net, old);
a = atomic_read(&cell->active);
zero = __refcount_dec_and_test(&cell->ref, &r);
trace_afs_cell(debug_id, r - 1, a, reason); if (zero) {
a = atomic_read(&cell->active);
WARN(a != 0, "Cell active count %u > 0\n", a);
WARN_ON(!queue_work(afs_wq, &cell->destroyer));
}
}
}
now = ktime_get_real_seconds();
cell->last_inactive = now;
expire_delay = 0; if (cell->vl_servers->nr_servers)
expire_delay = afs_cell_gc_delay;
debug_id = cell->debug_id;
a = atomic_dec_return(&cell->active); if (!a) /* 'cell' may now be garbage collected. */
afs_set_cell_timer(cell, expire_delay);
zero = __refcount_dec_and_test(&cell->ref, &r);
trace_afs_cell(debug_id, r - 1, a, reason); if (zero)
WARN_ON(!queue_work(afs_wq, &cell->destroyer));
}
_debug("state %u", cell->state); switch (cell->state) { case AFS_CELL_SETTING_UP: goto set_up_cell; case AFS_CELL_UNLOOKED: case AFS_CELL_ACTIVE: goto cell_is_active; case AFS_CELL_REMOVING:
WARN_ON_ONCE(1); returnfalse; case AFS_CELL_DEAD: returnfalse; default:
_debug("bad state %u", cell->state);
WARN_ON_ONCE(1); /* Unhandled state */ returnfalse;
}
set_up_cell:
ret = afs_activate_cell(net, cell); if (ret < 0) {
cell->error = ret; goto remove_cell;
}
afs_set_cell_state(cell, AFS_CELL_UNLOOKED);
cell_is_active: if (afs_has_cell_expired(cell, &next_manage)) goto remove_cell;
if (test_and_clear_bit(AFS_CELL_FL_DO_LOOKUP, &cell->flags)) {
ret = afs_update_cell(cell); if (ret < 0)
cell->error = ret; if (cell->state == AFS_CELL_UNLOOKED)
afs_set_cell_state(cell, AFS_CELL_ACTIVE);
}
if (next_manage < TIME64_MAX && cell->net->live) {
time64_t now = ktime_get_real_seconds();
if (next_manage - now <= 0)
afs_queue_cell(cell, afs_cell_trace_queue_again); else
afs_set_cell_timer(cell, next_manage - now);
}
_leave(" [done %u]", cell->state); returnfalse;
remove_cell:
down_write(&net->cells_lock);
if (atomic_read(&cell->active)) {
up_write(&net->cells_lock); goto cell_is_active;
}
/* Make sure that the expiring server records are going to see the fact *thatthecelliscaput.
*/
afs_set_cell_state(cell, AFS_CELL_REMOVING);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.