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 + -
显示快捷键?