vlocation.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 955 行 · 第 1/2 页
C
955 行
/* move to graveyard queue */ list_del(&vlocation->link); list_add_tail(&vlocation->link,&cell->vl_graveyard); /* remove from pending timeout queue (refcounted if actually being * updated) */ list_del_init(&vlocation->upd_op.link); /* time out in 10 secs */ afs_kafstimod_del_timer(&vlocation->upd_timer); afs_kafstimod_add_timer(&vlocation->timeout, 10 * HZ); spin_unlock(&cell->vl_gylock); _leave(" [killed]");} /* end __afs_put_vlocation() *//*****************************************************************************//* * finish using a volume location record */void afs_put_vlocation(struct afs_vlocation *vlocation){ if (vlocation) { struct afs_cell *cell = vlocation->cell; down_write(&cell->vl_sem); __afs_put_vlocation(vlocation); up_write(&cell->vl_sem); }} /* end afs_put_vlocation() *//*****************************************************************************//* * timeout vlocation record * - removes from the cell's graveyard if the usage count is zero */void afs_vlocation_do_timeout(struct afs_vlocation *vlocation){ struct afs_cell *cell; _enter("%s", vlocation->vldb.name); cell = vlocation->cell; BUG_ON(atomic_read(&vlocation->usage) < 0); /* remove from graveyard if still dead */ spin_lock(&cell->vl_gylock); if (atomic_read(&vlocation->usage) == 0) list_del_init(&vlocation->link); else vlocation = NULL; spin_unlock(&cell->vl_gylock); if (!vlocation) { _leave(""); return; /* resurrected */ } /* we can now destroy it properly */#ifdef AFS_CACHING_SUPPORT cachefs_relinquish_cookie(vlocation->cache, 0);#endif afs_put_cell(cell); kfree(vlocation); _leave(" [destroyed]");} /* end afs_vlocation_do_timeout() *//*****************************************************************************//* * send an update operation to the currently selected server */static int afs_vlocation_update_begin(struct afs_vlocation *vlocation){ afs_voltype_t voltype; afs_volid_t vid; int ret; _enter("%s{ufs=%u ucs=%u}", vlocation->vldb.name, vlocation->upd_first_svix, vlocation->upd_curr_svix); /* try to look up a cached volume in the cell VL databases by ID */ if (vlocation->vldb.vidmask & AFS_VOL_VTM_RW) { vid = vlocation->vldb.vid[0]; voltype = AFSVL_RWVOL; } else if (vlocation->vldb.vidmask & AFS_VOL_VTM_RO) { vid = vlocation->vldb.vid[1]; voltype = AFSVL_ROVOL; } else if (vlocation->vldb.vidmask & AFS_VOL_VTM_BAK) { vid = vlocation->vldb.vid[2]; voltype = AFSVL_BACKVOL; } else { BUG(); vid = 0; voltype = 0; } /* contact the chosen server */ ret = afs_server_lookup( vlocation->cell, &vlocation->cell->vl_addrs[vlocation->upd_curr_svix], &vlocation->upd_op.server); switch (ret) { case 0: break; case -ENOMEM: case -ENONET: default: _leave(" = %d", ret); return ret; } /* initiate the update operation */ ret = afs_rxvl_get_entry_by_id_async(&vlocation->upd_op, vid, voltype); if (ret < 0) { _leave(" = %d", ret); return ret; } _leave(" = %d", ret); return ret;} /* end afs_vlocation_update_begin() *//*****************************************************************************//* * abandon updating a VL record * - does not restart the update timer */static void afs_vlocation_update_abandon(struct afs_vlocation *vlocation, afs_vlocation_upd_t state, int ret){ _enter("%s,%u", vlocation->vldb.name, state); if (ret < 0) printk("kAFS: Abandoning VL update '%s': %d\n", vlocation->vldb.name, ret); /* discard the server record */ afs_put_server(vlocation->upd_op.server); vlocation->upd_op.server = NULL; spin_lock(&afs_vlocation_update_lock); afs_vlocation_update = NULL; vlocation->upd_state = state; /* TODO: start updating next VL record on pending list */ spin_unlock(&afs_vlocation_update_lock); _leave("");} /* end afs_vlocation_update_abandon() *//*****************************************************************************//* * handle periodic update timeouts and busy retry timeouts * - called from kafstimod */static void afs_vlocation_update_timer(struct afs_timer *timer){ struct afs_vlocation *vlocation = list_entry(timer, struct afs_vlocation, upd_timer); int ret; _enter("%s", vlocation->vldb.name); /* only update if not in the graveyard (defend against putting too) */ spin_lock(&vlocation->cell->vl_gylock); if (!atomic_read(&vlocation->usage)) goto out_unlock1; spin_lock(&afs_vlocation_update_lock); /* if we were woken up due to EBUSY sleep then restart immediately if * possible or else jump to front of pending queue */ if (vlocation->upd_state == AFS_VLUPD_BUSYSLEEP) { if (afs_vlocation_update) { list_add(&vlocation->upd_op.link, &afs_vlocation_update_pendq); } else { afs_get_vlocation(vlocation); afs_vlocation_update = vlocation; vlocation->upd_state = AFS_VLUPD_INPROGRESS; } goto out_unlock2; } /* put on pending queue if there's already another update in progress */ if (afs_vlocation_update) { vlocation->upd_state = AFS_VLUPD_PENDING; list_add_tail(&vlocation->upd_op.link, &afs_vlocation_update_pendq); goto out_unlock2; } /* hold a ref on it while actually updating */ afs_get_vlocation(vlocation); afs_vlocation_update = vlocation; vlocation->upd_state = AFS_VLUPD_INPROGRESS; spin_unlock(&afs_vlocation_update_lock); spin_unlock(&vlocation->cell->vl_gylock); /* okay... we can start the update */ _debug("BEGIN VL UPDATE [%s]", vlocation->vldb.name); vlocation->upd_first_svix = vlocation->cell->vl_curr_svix; vlocation->upd_curr_svix = vlocation->upd_first_svix; vlocation->upd_rej_cnt = 0; vlocation->upd_busy_cnt = 0; ret = afs_vlocation_update_begin(vlocation); if (ret < 0) { afs_vlocation_update_abandon(vlocation, AFS_VLUPD_SLEEP, ret); afs_kafstimod_add_timer(&vlocation->upd_timer, AFS_VLDB_TIMEOUT); afs_put_vlocation(vlocation); } _leave(""); return; out_unlock2: spin_unlock(&afs_vlocation_update_lock); out_unlock1: spin_unlock(&vlocation->cell->vl_gylock); _leave(""); return;} /* end afs_vlocation_update_timer() *//*****************************************************************************//* * attend to an update operation upon which an event happened * - called in kafsasyncd context */static void afs_vlocation_update_attend(struct afs_async_op *op){ struct afs_cache_vlocation vldb; struct afs_vlocation *vlocation = list_entry(op, struct afs_vlocation, upd_op); unsigned tmp; int ret; _enter("%s", vlocation->vldb.name); ret = afs_rxvl_get_entry_by_id_async2(op, &vldb); switch (ret) { case -EAGAIN: _leave(" [unfinished]"); return; case 0: _debug("END VL UPDATE: %d\n", ret); vlocation->valid = 1; _debug("Done VL Lookup: %02x { %08x(%x) %08x(%x) %08x(%x) }", vldb.vidmask, ntohl(vldb.servers[0].s_addr), vldb.srvtmask[0], ntohl(vldb.servers[1].s_addr), vldb.srvtmask[1], ntohl(vldb.servers[2].s_addr), vldb.srvtmask[2] ); _debug("Vids: %08x %08x %08x", vldb.vid[0], vldb.vid[1], vldb.vid[2]); afs_vlocation_update_abandon(vlocation, AFS_VLUPD_SLEEP, 0); down_write(&vlocation->cell->vl_sem); /* actually update the cache */ if (strncmp(vldb.name, vlocation->vldb.name, sizeof(vlocation->vldb.name)) != 0) printk("kAFS: name of volume '%s'" " changed to '%s' on server\n", vlocation->vldb.name, vldb.name); memcpy(&vlocation->vldb, &vldb, sizeof(vlocation->vldb));#if 0 /* TODO update volume entry in local cache */#endif up_write(&vlocation->cell->vl_sem); if (ret < 0) printk("kAFS: failed to update local cache: %d\n", ret); afs_kafstimod_add_timer(&vlocation->upd_timer, AFS_VLDB_TIMEOUT); afs_put_vlocation(vlocation); _leave(" [found]"); return; case -ENOMEDIUM: vlocation->upd_rej_cnt++; goto try_next; /* the server is locked - retry in a very short while */ case -EBUSY: vlocation->upd_busy_cnt++; if (vlocation->upd_busy_cnt > 3) goto try_next; /* too many retries */ afs_vlocation_update_abandon(vlocation, AFS_VLUPD_BUSYSLEEP, 0); afs_kafstimod_add_timer(&vlocation->upd_timer, HZ / 2); afs_put_vlocation(vlocation); _leave(" [busy]"); return; case -ENETUNREACH: case -EHOSTUNREACH: case -ECONNREFUSED: case -EREMOTEIO: /* record bad vlserver info in the cell too * - TODO: use down_write_trylock() if available */ if (vlocation->upd_curr_svix == vlocation->cell->vl_curr_svix) vlocation->cell->vl_curr_svix = vlocation->cell->vl_curr_svix % vlocation->cell->vl_naddrs; case -EBADRQC: case -EINVAL: case -EACCES: case -EBADMSG: goto try_next; default: goto abandon; } /* try contacting the next server */ try_next: vlocation->upd_busy_cnt = 0; /* discard the server record */ afs_put_server(vlocation->upd_op.server); vlocation->upd_op.server = NULL; tmp = vlocation->cell->vl_naddrs; if (tmp == 0) goto abandon; vlocation->upd_curr_svix++; if (vlocation->upd_curr_svix >= tmp) vlocation->upd_curr_svix = 0; if (vlocation->upd_first_svix >= tmp) vlocation->upd_first_svix = tmp - 1; /* move to the next server */ if (vlocation->upd_curr_svix != vlocation->upd_first_svix) { afs_vlocation_update_begin(vlocation); _leave(" [next]"); return; } /* run out of servers to try - was the volume rejected? */ if (vlocation->upd_rej_cnt > 0) { printk("kAFS: Active volume no longer valid '%s'\n", vlocation->vldb.name); vlocation->valid = 0; afs_vlocation_update_abandon(vlocation, AFS_VLUPD_SLEEP, 0); afs_kafstimod_add_timer(&vlocation->upd_timer, AFS_VLDB_TIMEOUT); afs_put_vlocation(vlocation); _leave(" [invalidated]"); return; } /* abandon the update */ abandon: afs_vlocation_update_abandon(vlocation, AFS_VLUPD_SLEEP, ret); afs_kafstimod_add_timer(&vlocation->upd_timer, HZ * 10); afs_put_vlocation(vlocation); _leave(" [abandoned]");} /* end afs_vlocation_update_attend() *//*****************************************************************************//* * deal with an update operation being discarded * - called in kafsasyncd context when it's dying due to rmmod * - the call has already been aborted and put()'d */static void afs_vlocation_update_discard(struct afs_async_op *op){ struct afs_vlocation *vlocation = list_entry(op, struct afs_vlocation, upd_op); _enter("%s", vlocation->vldb.name); afs_put_server(op->server); op->server = NULL; afs_put_vlocation(vlocation); _leave("");} /* end afs_vlocation_update_discard() *//*****************************************************************************//* * match a VLDB record stored in the cache * - may also load target from entry */#ifdef AFS_CACHING_SUPPORTstatic cachefs_match_val_t afs_vlocation_cache_match(void *target, const void *entry){ const struct afs_cache_vlocation *vldb = entry; struct afs_vlocation *vlocation = target; _enter("{%s},{%s}", vlocation->vldb.name, vldb->name); if (strncmp(vlocation->vldb.name, vldb->name, sizeof(vldb->name)) == 0 ) { if (!vlocation->valid || vlocation->vldb.rtime == vldb->rtime ) { vlocation->vldb = *vldb; vlocation->valid = 1; _leave(" = SUCCESS [c->m]"); return CACHEFS_MATCH_SUCCESS; } /* need to update cache if cached info differs */ else if (memcmp(&vlocation->vldb, vldb, sizeof(*vldb)) != 0) { /* delete if VIDs for this name differ */ if (memcmp(&vlocation->vldb.vid, &vldb->vid, sizeof(vldb->vid)) != 0) { _leave(" = DELETE"); return CACHEFS_MATCH_SUCCESS_DELETE; } _leave(" = UPDATE"); return CACHEFS_MATCH_SUCCESS_UPDATE; } else { _leave(" = SUCCESS"); return CACHEFS_MATCH_SUCCESS; } } _leave(" = FAILED"); return CACHEFS_MATCH_FAILED;} /* end afs_vlocation_cache_match() */#endif/*****************************************************************************//* * update a VLDB record stored in the cache */#ifdef AFS_CACHING_SUPPORTstatic void afs_vlocation_cache_update(void *source, void *entry){ struct afs_cache_vlocation *vldb = entry; struct afs_vlocation *vlocation = source; _enter(""); *vldb = vlocation->vldb;} /* end afs_vlocation_cache_update() */#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?