if (op->server_states) { for (i = 0; i < op->server_list->nr_servers; i++)
afs_put_endpoint_state(op->server_states[i].endpoint_state,
afs_estate_trace_put_server_state);
kfree(op->server_states);
}
}
cb_server = vnode->cb_server; if (cb_server) { /* See if the vnode's preferred record is still available */ for (i = 0; i < op->server_list->nr_servers; i++) {
server = op->server_list->servers[i].server; if (server == cb_server) {
op->server_index = i; goto found_interest;
}
}
/* If we have a lock outstanding on a server that's no longer *servingthisvnode,thenwecan'tswitchtoanotherserver *andhavetoreturnanerror.
*/ if (op->flags & AFS_OPERATION_CUR_ONLY) {
afs_op_set_error(op, -ESTALE);
trace_afs_rotate(op, afs_rotate_trace_stale_lock, 0); returnfalse;
}
/* Note that the callback promise is effectively broken */
write_seqlock(&vnode->cb_lock);
ASSERTCMP(cb_server, ==, vnode->cb_server);
vnode->cb_server = NULL; if (afs_clear_cb_promise(vnode, afs_cb_promise_clear_rotate_server))
vnode->cb_break++;
write_sequnlock(&vnode->cb_lock);
}
switch (abort_code) { case VOFFLINE: m = "offline"; break; case VRESTARTING: m = "restarting"; break; case VSALVAGING: m = "being salvaged"; break; default: m = "busy"; break;
}
pr_notice("kAFS: Volume %llu '%s' on server %pU is %s\n",
op->volume->vid, op->volume->name, &op->server->uuid, m);
}
/* Evaluate the result of the previous operation, if there was one. */ switch (op->call_error) { case0:
clear_bit(AFS_SE_VOLUME_OFFLINE,
&op->server_list->servers[op->server_index].flags);
clear_bit(AFS_SE_VOLUME_BUSY,
&op->server_list->servers[op->server_index].flags);
op->cumul_error.responded = true;
/* We succeeded, but we may need to redo the op from another *serverifwe'relookingatasetofROvolumeswheresomeof *theservershavenotyetbeenbroughtuptodatelestwe *regressthedata.Weonlyswitchtothenewversiononce *>=50%oftheserversareupdated.
*/
error = afs_update_volume_state(op); if (error != 0) { if (error == 1) {
afs_sleep_and_retry(op); goto restart_from_beginning;
}
afs_op_set_error(op, error); goto failed;
}
fallthrough; default: /* Success or local failure. Stop. */
afs_op_set_error(op, error);
op->flags |= AFS_OPERATION_STOP;
trace_afs_rotate(op, afs_rotate_trace_stop, error);
_leave(" = f [okay/local %d]", error); returnfalse;
case -ECONNABORTED: /* The far side rejected the operation on some grounds. This *mightinvolvetheserverbeingbusyorthevolumehavingbeenmoved. * *NotethatvariousV*errorsshouldnotbesenttoacachemanager *byafileserverastheyshouldbetranslatedtomoremodernUAE* *errorsinstead.IBMAFSandOpenAFSfileservers,however,doleak *theseabortcodes.
*/
trace_afs_rotate(op, afs_rotate_trace_aborted, abort_code);
op->cumul_error.responded = true; switch (abort_code) { case VNOVOL: /* This fileserver doesn't know about the volume. *-MayindicatethattheVLiswrong-retryonceandcompare *theresults. *-Mayindicatethatthefileservercouldn'tattachtothevol. *-Thevolumemighthavebeentemporarilyremovedsothatitcan *bereplacedbyavolumerestore."vos"mighthaveendedone *transactionandhasyettocreatethenext. *-Thevolumemightnotbeblessedormightnotbein-service *(administrativeaction).
*/ if (op->flags & AFS_OPERATION_VNOVOL) {
afs_op_accumulate_error(op, -EREMOTEIO, abort_code); goto next_server;
}
if (test_bit(AFS_VOLUME_DELETED, &op->volume->flags)) {
afs_op_set_error(op, -ENOMEDIUM); goto failed;
}
/* If the server list didn't change, then assume that *it'sthefileserverhavingtrouble.
*/ if (rcu_access_pointer(op->volume->servers) == op->server_list) {
afs_op_accumulate_error(op, -EREMOTEIO, abort_code); goto next_server;
}
/* Try again */
op->flags |= AFS_OPERATION_VNOVOL;
_leave(" = t [vnovol]"); returntrue;
case VVOLEXISTS: case VONLINE: /* These should not be returned from the fileserver. */
pr_warn("Fileserver returned unexpected abort %d\n",
abort_code);
afs_op_accumulate_error(op, -EREMOTEIO, abort_code); goto next_server;
case VNOSERVICE: /* Prior to AFS 3.2 VNOSERVICE was returned from the fileserver *ifthevolumewasneitherin-servicenoradministratively *blessed.AllusagewasreplacedbyVNOVOLbecauseAFS3.1and *earliercachemanagersdidnothandleVNOSERVICEandassumed *itwastheclientOSeserrno105. * *StartingwithOpenAFS1.4.8VNOSERVICEwasrepurposedasthe *fileserveridledeadtimeerrorwhichwassentinplaceof *RX_CALL_TIMEOUT(-3).Theerrorwasintendedtobesentifthe *fileservertooktoolongtosendareplytotheclient. *RX_CALL_TIMEOUTwouldhavecausedthecachemanagertomarkthe *serverdownwhereasVNOSERVICEsinceAFS3.2wouldcausecache *managertotemporarily(upto15minutes)markthevolume *instanceasunusable. * *Theidledeadlogicresultedincacheinconsistencysincea *statechangingcallthatthecachemanagerassumedwasdead *couldstillbeprocessedtocompletionbythefileserver.This *logicwasremovedinOpenAFS1.8.0andVNOSERVICEisnolonger *returned.However,many1.4.8through1.6.24fileserversare *stillinexistence. * *AuriStorFSfileservershaveneverreturnedVNOSERVICE. * *VNOSERVICEshouldbetreatedasanaliasforRX_CALL_TIMEOUT.
*/ case RX_CALL_TIMEOUT:
afs_op_accumulate_error(op, -ETIMEDOUT, abort_code); goto next_server;
case VSALVAGING: /* This error should not be leaked to cache managers *butisfromOpenAFSdemandattachfileservers. *ItshouldbetreatedasanaliasforVOFFLINE.
*/ case VSALVAGE: /* VSALVAGE should be treated as a synonym of VOFFLINE */ case VOFFLINE: /* The volume is in use by the volserver or another volume utility *foranoperationthatmightalterthecontents.Thevolumeis *expectedtocomebackbutitmighttakealongtime(couldbe *days).
*/ if (!test_and_set_bit(AFS_SE_VOLUME_OFFLINE,
&op->server_list->servers[op->server_index].flags)) {
afs_busy(op, abort_code);
clear_bit(AFS_SE_VOLUME_BUSY,
&op->server_list->servers[op->server_index].flags);
} if (op->flags & AFS_OPERATION_NO_VSLEEP) {
afs_op_set_error(op, -EADV); goto failed;
} goto busy;
case VRESTARTING: /* The fileserver is either shutting down or starting up. */ case VBUSY: /* The volume is in use by the volserver or another volume *utilityforanoperationthatisnotexpectedtoalterthe *contentsofthevolume.VBUSYdoesnotneedtobereturned *foraROVOLorBACKVOLboundtoanITBusyvolserver *transaction.Thefileserverispermittedtocontinueserving *contentfromROVOLsandBACKVOLsduringanITBusytransaction *becausethecontentwillnotchange.However,manyfileserver *releasesdoreturnVBUSYforROVOLandBACKVOLinstancesunder *manycircumstances. * *Retryaftergoingroundalltheserversunlesswehaveafile *lockweneedtomaintain.
*/ if (op->flags & AFS_OPERATION_NO_VSLEEP) {
afs_op_set_error(op, -EBUSY); goto failed;
} if (!test_and_set_bit(AFS_SE_VOLUME_BUSY,
&op->server_list->servers[op->server_index].flags)) {
afs_busy(op, abort_code);
clear_bit(AFS_SE_VOLUME_OFFLINE,
&op->server_list->servers[op->server_index].flags);
}
busy: if (op->flags & AFS_OPERATION_CUR_ONLY) { if (!afs_sleep_and_retry(op)) goto failed;
/* Retry with same server & address */
_leave(" = t [vbusy]"); returntrue;
}
case VMOVED: /* The volume migrated to another server. We consider *consideralllocksandcallbacksbrokenandrequest *anupdatefromtheVLDB. * *WealsolimitthenumberofVMOVEDhopswewill *honour,justincasesomeonesetsupaloop.
*/ if (op->flags & AFS_OPERATION_VMOVED) {
afs_op_set_error(op, -EREMOTEIO); goto failed;
}
op->flags |= AFS_OPERATION_VMOVED;
/* If the server list didn't change, then the VLDB is *outofsyncwiththefileservers.Thisishopefully *atemporarycondition,however,sowedon'twantto *permanentlyblockaccesstothefile. * *TODO:Tryotherfileserversifwecan. * *TODO:Retryafewtimeswithsleeps.
*/ if (rcu_access_pointer(op->volume->servers) == op->server_list) {
afs_op_accumulate_error(op, -ENOMEDIUM, abort_code); goto failed;
}
goto restart_from_beginning;
case UAEIO: case VIO:
afs_op_accumulate_error(op, -EREMOTEIO, abort_code); if (op->volume->type != AFSVL_RWVOL) goto next_server; goto failed;
case VDISKFULL: case UAENOSPC: /* The partition is full. Only applies to RWVOLs. *TranslatelocallyandreturnENOSPC. *Noreplicastofailoverto.
*/
afs_op_set_error(op, -ENOSPC); goto failed_but_online;
case VOVERQUOTA: case UAEDQUOT: /* Volume is full. Only applies to RWVOLs. *TranslatelocallyandreturnEDQUOT. *Noreplicastofailoverto.
*/
afs_op_set_error(op, -EDQUOT); goto failed_but_online;
case -ETIMEDOUT: case -ETIME: if (afs_op_error(op) != -EDESTADDRREQ) goto iterate_address;
fallthrough; case -ERFKILL: case -EADDRNOTAVAIL: case -ENETUNREACH: case -EHOSTUNREACH: case -EHOSTDOWN: case -ECONNREFUSED:
_debug("no conn");
afs_op_accumulate_error(op, error, 0); goto iterate_address;
restart_from_beginning:
trace_afs_rotate(op, afs_rotate_trace_restart, 0);
_debug("restart");
op->estate = NULL;
op->server = NULL;
afs_clear_server_states(op);
op->server_states = NULL;
afs_put_serverlist(op->net, op->server_list);
op->server_list = NULL;
start:
_debug("start");
ASSERTCMP(op->estate, ==, NULL); /* See if we need to do an update of the volume record. Note that the *volumemayhavemovedorevenhavebeendeleted.
*/
error = afs_check_volume_status(op->volume, op);
trace_afs_rotate(op, afs_rotate_trace_check_vol_status, error); if (error < 0) {
afs_op_set_error(op, error); goto failed;
}
if (!afs_start_fs_iteration(op, vnode)) goto failed;
/* We're starting on a different fileserver from the list. We need to *checkit,createacallbackintercept,finditsaddresslistand *probeitscapabilitiesbeforeweuseit.
*/
ASSERTCMP(op->estate, ==, NULL);
server = op->server_list->servers[op->server_index].server;
if (!afs_check_server_record(op, server, op->key)) goto failed;
iterate_address: /* Iterate over the current server's address list to try and find an *addressonwhichitwillrespondtous.
*/
op->estate = op->server_states[op->server_index].endpoint_state;
set = READ_ONCE(op->estate->responsive_set);
failed = READ_ONCE(op->estate->failed_set);
_debug("iterate ES=%x rs=%lx fs=%lx", op->estate->probe_seq, set, failed);
set &= ~(failed | op->addr_tried);
trace_afs_rotate(op, afs_rotate_trace_iterate_addr, set); if (!set) goto wait_for_more_probe_results;
alist = op->estate->addresses;
best_prio = -1;
addr_index = 0; for (i = 0; i < alist->nr_addrs; i++) { if (!(set & (1 << i))) continue; if (alist->addrs[i].prio > best_prio) {
addr_index = i;
best_prio = alist->addrs[i].prio;
}
}
no_more_servers: /* That's all the servers poked to no good effect. Try again if some *ofthemwerebusy.
*/
trace_afs_rotate(op, afs_rotate_trace_no_more_servers, 0); if (op->flags & AFS_OPERATION_VBUSY) {
afs_sleep_and_retry(op);
op->flags &= ~AFS_OPERATION_VBUSY; goto restart_from_beginning;
}
rcu_read_lock(); for (i = 0; i < op->server_list->nr_servers; i++) { struct afs_endpoint_state *estate;
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.