lov_obd.c
来自「lustre 1.6.5 source code」· C语言 代码 · 共 1,866 行 · 第 1/5 页
C
1,866 行
ENTRY; CDEBUG(D_CONFIG, "%s: disconnecting target %s\n", obd->obd_name, osc_obd->obd_name); obd_unregister_lock_cancel_cb(lov->lov_tgts[index]->ltd_exp, lov->lov_lock_cancel_cb); obd_unregister_page_removal_cb(lov->lov_tgts[index]->ltd_exp, lov->lov_page_removal_cb); if (lov->lov_tgts[index]->ltd_active) { lov->lov_tgts[index]->ltd_active = 0; lov->desc.ld_active_tgt_count--; lov->lov_tgts[index]->ltd_exp->exp_obd->obd_inactive = 1; } lov_proc_dir = lprocfs_srch(obd->obd_proc_entry, "target_obds"); if (lov_proc_dir) { cfs_proc_dir_entry_t *osc_symlink; osc_symlink = lprocfs_srch(lov_proc_dir, osc_obd->obd_name); if (osc_symlink) { lprocfs_remove(&osc_symlink); } else { CERROR("/proc/fs/lustre/%s/%s/target_obds/%s missing.", obd->obd_type->typ_name, obd->obd_name, osc_obd->obd_name); } } if (obd->obd_no_recov) { /* Pass it on to our clients. * XXX This should be an argument to disconnect, * XXX not a back-door flag on the OBD. Ah well. */ if (osc_obd) osc_obd->obd_no_recov = 1; } obd_register_observer(osc_obd, NULL); rc = obd_disconnect(lov->lov_tgts[index]->ltd_exp); if (rc) { CERROR("Target %s disconnect error %d\n", lov_uuid2str(lov, index), rc); rc = 0; } qos_del_tgt(obd, index); lov->lov_tgts[index]->ltd_exp = NULL; RETURN(0);}static int lov_del_target(struct obd_device *obd, __u32 index, struct obd_uuid *uuidp, int gen);static int lov_disconnect(struct obd_export *exp){ struct obd_device *obd = class_exp2obd(exp); struct lov_obd *lov = &obd->u.lov; int i, rc; ENTRY; if (!lov->lov_tgts) goto out; /* Only disconnect the underlying layers on the final disconnect. */ lov->lov_connects--; if (lov->lov_connects != 0) { /* why should there be more than 1 connect? */ CERROR("disconnect #%d\n", lov->lov_connects); goto out; } /* Let's hold another reference so lov_del_obd doesn't spin through putref every time */ lov_getref(obd); for (i = 0; i < lov->desc.ld_tgt_count; i++) { if (lov->lov_tgts[i] && lov->lov_tgts[i]->ltd_exp) { /* Disconnection is the last we know about an obd */ lov_del_target(obd, i, 0, lov->lov_tgts[i]->ltd_gen); } } lov_putref(obd);out: rc = class_disconnect(exp); /* bz 9811 */ RETURN(rc);}/* Error codes: * * -EINVAL : UUID can't be found in the LOV's target list * -ENOTCONN: The UUID is found, but the target connection is bad (!) * -EBADF : The UUID is found, but the OBD is the wrong type (!) */static int lov_set_osc_active(struct obd_device *obd, struct obd_uuid *uuid, int activate){ struct lov_obd *lov = &obd->u.lov; struct lov_tgt_desc *tgt; int i, rc = 0; ENTRY; CDEBUG(D_INFO, "Searching in lov %p for uuid %s (activate=%d)\n", lov, uuid->uuid, activate); lov_getref(obd); for (i = 0; i < lov->desc.ld_tgt_count; i++) { tgt = lov->lov_tgts[i]; if (!tgt || !tgt->ltd_exp) continue; CDEBUG(D_INFO, "lov idx %d is %s conn "LPX64"\n", i, obd_uuid2str(&tgt->ltd_uuid), tgt->ltd_exp->exp_handle.h_cookie); if (obd_uuid_equals(uuid, &tgt->ltd_uuid)) break; } if (i == lov->desc.ld_tgt_count) GOTO(out, rc = -EINVAL); if (lov->lov_tgts[i]->ltd_active == activate) { CDEBUG(D_INFO, "OSC %s already %sactive!\n", uuid->uuid, activate ? "" : "in"); GOTO(out, rc); } CDEBUG(D_CONFIG, "Marking OSC %s %sactive\n", obd_uuid2str(uuid), activate ? "" : "in"); lov->lov_tgts[i]->ltd_active = activate; if (activate) { lov->desc.ld_active_tgt_count++; lov->lov_tgts[i]->ltd_exp->exp_obd->obd_inactive = 0; } else { lov->desc.ld_active_tgt_count--; lov->lov_tgts[i]->ltd_exp->exp_obd->obd_inactive = 1; } /* remove any old qos penalty */ lov->lov_tgts[i]->ltd_qos.ltq_penalty = 0; out: lov_putref(obd); RETURN(rc);}static int lov_notify(struct obd_device *obd, struct obd_device *watched, enum obd_notify_event ev, void *data){ int rc = 0; ENTRY; if (ev == OBD_NOTIFY_ACTIVE || ev == OBD_NOTIFY_INACTIVE) { struct obd_uuid *uuid; LASSERT(watched); if (strcmp(watched->obd_type->typ_name, LUSTRE_OSC_NAME)) { CERROR("unexpected notification of %s %s!\n", watched->obd_type->typ_name, watched->obd_name); RETURN(-EINVAL); } uuid = &watched->u.cli.cl_target_uuid; /* Set OSC as active before notifying the observer, so the * observer can use the OSC normally. */ rc = lov_set_osc_active(obd, uuid, ev == OBD_NOTIFY_ACTIVE); if (rc) { CERROR("%sactivation of %s failed: %d\n", (ev == OBD_NOTIFY_ACTIVE) ? "" : "de", obd_uuid2str(uuid), rc); RETURN(rc); } } /* Pass the notification up the chain. */ if (watched) { rc = obd_notify_observer(obd, watched, ev, data); } else { /* NULL watched means all osc's in the lov (only for syncs) */ struct lov_obd *lov = &obd->u.lov; struct obd_device *tgt_obd; int i; lov_getref(obd); for (i = 0; i < lov->desc.ld_tgt_count; i++) { if (!lov->lov_tgts[i]) continue; tgt_obd = class_exp2obd(lov->lov_tgts[i]->ltd_exp); rc = obd_notify_observer(obd, tgt_obd, ev, data); if (rc) { CERROR("%s: notify %s of %s failed %d\n", obd->obd_name, obd->obd_observer->obd_name, tgt_obd->obd_name, rc); break; } } lov_putref(obd); } RETURN(rc);}static int lov_add_target(struct obd_device *obd, struct obd_uuid *uuidp, __u32 index, int gen, int active){ struct lov_obd *lov = &obd->u.lov; struct lov_tgt_desc *tgt; int rc; ENTRY; CDEBUG(D_CONFIG, "uuid:%s idx:%d gen:%d active:%d\n", uuidp->uuid, index, gen, active); if (gen <= 0) { CERROR("request to add OBD %s with invalid generation: %d\n", uuidp->uuid, gen); RETURN(-EINVAL); } mutex_down(&lov->lov_lock); if ((index < lov->lov_tgt_size) && (lov->lov_tgts[index] != NULL)) { tgt = lov->lov_tgts[index]; CERROR("UUID %s already assigned at LOV target index %d\n", obd_uuid2str(&tgt->ltd_uuid), index); mutex_up(&lov->lov_lock); RETURN(-EEXIST); } if (index >= lov->lov_tgt_size) { /* We need to reallocate the lov target array. */ struct lov_tgt_desc **newtgts, **old = NULL; __u32 newsize, oldsize = 0; newsize = max(lov->lov_tgt_size, (__u32)2); while (newsize < index + 1) newsize = newsize << 1; OBD_ALLOC(newtgts, sizeof(*newtgts) * newsize); if (newtgts == NULL) { mutex_up(&lov->lov_lock); RETURN(-ENOMEM); } if (lov->lov_tgt_size) { memcpy(newtgts, lov->lov_tgts, sizeof(*newtgts) * lov->lov_tgt_size); old = lov->lov_tgts; oldsize = lov->lov_tgt_size; } lov->lov_tgts = newtgts; lov->lov_tgt_size = newsize;#ifdef __KERNEL__ smp_rmb();#endif if (old) OBD_FREE(old, sizeof(*old) * oldsize); CDEBUG(D_CONFIG, "tgts: %p size: %d\n", lov->lov_tgts, lov->lov_tgt_size); } OBD_ALLOC_PTR(tgt); if (!tgt) { mutex_up(&lov->lov_lock); RETURN(-ENOMEM); } memset(tgt, 0, sizeof(*tgt)); tgt->ltd_uuid = *uuidp; /* XXX - add a sanity check on the generation number. */ tgt->ltd_gen = gen; tgt->ltd_index = index; tgt->ltd_activate = active; lov->lov_tgts[index] = tgt; if (index >= lov->desc.ld_tgt_count) lov->desc.ld_tgt_count = index + 1; mutex_up(&lov->lov_lock); CDEBUG(D_CONFIG, "idx=%d ltd_gen=%d ld_tgt_count=%d\n", index, tgt->ltd_gen, lov->desc.ld_tgt_count); if (lov->lov_connects == 0) { /* lov_connect hasn't been called yet. We'll do the lov_connect_obd on this target when that fn first runs, because we don't know the connect flags yet. */ RETURN(0); } lov_getref(obd); rc = lov_connect_obd(obd, index, active, &lov->lov_ocd); if (rc) GOTO(out, rc); rc = lov_notify(obd, tgt->ltd_exp->exp_obd, active ? OBD_NOTIFY_ACTIVE : OBD_NOTIFY_INACTIVE, (void *)&index);out: if (rc) { CERROR("add failed (%d), deleting %s\n", rc, obd_uuid2str(&tgt->ltd_uuid)); lov_del_target(obd, index, 0, 0); } lov_putref(obd); RETURN(rc);}/* Schedule a target for deletion */static int lov_del_target(struct obd_device *obd, __u32 index, struct obd_uuid *uuidp, int gen){ struct lov_obd *lov = &obd->u.lov; int count = lov->desc.ld_tgt_count; int rc = 0; ENTRY; if (index >= count) { CERROR("LOV target index %d >= number of LOV OBDs %d.\n", index, count); RETURN(-EINVAL); } lov_getref(obd); if (!lov->lov_tgts[index]) { CERROR("LOV target at index %d is not setup.\n", index); GOTO(out, rc = -EINVAL); } if (uuidp && !obd_uuid_equals(uuidp, &lov->lov_tgts[index]->ltd_uuid)) { CERROR("LOV target UUID %s at index %d doesn't match %s.\n", lov_uuid2str(lov, index), index, obd_uuid2str(uuidp)); GOTO(out, rc = -EINVAL); } CDEBUG(D_CONFIG, "uuid: %s idx: %d gen: %d exp: %p active: %d\n", lov_uuid2str(lov, index), index, lov->lov_tgts[index]->ltd_gen, lov->lov_tgts[index]->ltd_exp, lov->lov_tgts[index]->ltd_active); lov->lov_tgts[index]->ltd_reap = 1; lov->lov_death_row++; /* we really delete it from lov_putref */out: lov_putref(obd); RETURN(rc);}/* We are holding lov_lock */static void __lov_del_obd(struct obd_device *obd, __u32 index){ struct lov_obd *lov = &obd->u.lov; struct obd_device *osc_obd; struct lov_tgt_desc *tgt = lov->lov_tgts[index]; LASSERT(tgt); LASSERT(tgt->ltd_reap); osc_obd = class_exp2obd(tgt->ltd_exp); CDEBUG(D_CONFIG, "Removing tgt %s : %s\n", lov_uuid2str(lov, index), osc_obd ? osc_obd->obd_name : "<no obd>");
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?