lov_obd.c

来自「lustre 1.6.5 source code」· C语言 代码 · 共 1,866 行 · 第 1/5 页

C
1,866
字号
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * * Copyright (C) 2002-2006 Cluster File Systems, Inc. * Author: Phil Schwan <phil@clusterfs.com> *         Peter Braam <braam@clusterfs.com> *         Mike Shaver <shaver@clusterfs.com> *         Nathan Rutman <nathan@clusterfs.com> * *   This file is part of the Lustre file system, http://www.lustre.org *   Lustre is a trademark of Cluster File Systems, Inc. * *   You may have signed or agreed to another license before downloading *   this software.  If so, you are bound by the terms and conditions *   of that agreement, and the following does not apply to you.  See the *   LICENSE file included with this distribution for more information. * *   If you did not agree to a different license, then this copy of Lustre *   is open source software; you can redistribute it and/or modify it *   under the terms of version 2 of the GNU General Public License as *   published by the Free Software Foundation. * *   In either case, Lustre is distributed in the hope that it will be *   useful, but WITHOUT ANY WARRANTY; without even the implied warranty *   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   license text for more details. */#ifndef EXPORT_SYMTAB# define EXPORT_SYMTAB#endif#define DEBUG_SUBSYSTEM S_LOV#ifdef __KERNEL__#include <libcfs/libcfs.h>#else#include <liblustre.h>#endif#include <obd_support.h>#include <lustre_lib.h>#include <lustre_net.h>#include <lustre/lustre_idl.h>#include <lustre_dlm.h>#include <lustre_mds.h>#include <lustre_debug.h>#include <obd_class.h>#include <obd_lov.h>#include <obd_ost.h>#include <lprocfs_status.h>#include <lustre_param.h>#include <lustre_cache.h>#include "lov_internal.h"/* Keep a refcount of lov->tgt usage to prevent racing with addition/deletion.   Any function that expects lov_tgts to remain stationary must take a ref. */void lov_getref(struct obd_device *obd){        struct lov_obd *lov = &obd->u.lov;        /* nobody gets through here until lov_putref is done */        mutex_down(&lov->lov_lock);        atomic_inc(&lov->lov_refcount);        mutex_up(&lov->lov_lock);        return;}static void __lov_del_obd(struct obd_device *obd, __u32 index);void lov_putref(struct obd_device *obd){        struct lov_obd *lov = &obd->u.lov;        mutex_down(&lov->lov_lock);        /* ok to dec to 0 more than once -- ltd_exp's will be null */        if (atomic_dec_and_test(&lov->lov_refcount) && lov->lov_death_row) {                int i;                CDEBUG(D_CONFIG, "destroying %d lov targets\n",                        lov->lov_death_row);                for (i = 0; i < lov->desc.ld_tgt_count; i++) {                        if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_reap)                                continue;                        /* Disconnect and delete from list */                        __lov_del_obd(obd, i);                        lov->lov_death_row--;                }        }        mutex_up(&lov->lov_lock);}static int lov_register_page_removal_cb(struct obd_export *exp,                                        obd_page_removal_cb_t func,                                        obd_pin_extent_cb pin_cb){        struct lov_obd *lov = &exp->exp_obd->u.lov;        int i, rc = 0;        if (lov->lov_page_removal_cb && lov->lov_page_removal_cb != func)                return -EBUSY;        if (lov->lov_page_pin_cb && lov->lov_page_pin_cb != pin_cb)                return -EBUSY;        for (i = 0; i < lov->desc.ld_tgt_count; i++) {                if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_exp)                        continue;                rc |= obd_register_page_removal_cb(lov->lov_tgts[i]->ltd_exp,                                                   func, pin_cb);        }        lov->lov_page_removal_cb = func;        lov->lov_page_pin_cb = pin_cb;        return rc;}static int lov_unregister_page_removal_cb(struct obd_export *exp,                                        obd_page_removal_cb_t func){        struct lov_obd *lov = &exp->exp_obd->u.lov;        int i, rc = 0;        if (lov->lov_page_removal_cb && lov->lov_page_removal_cb != func)                return -EINVAL;        lov->lov_page_removal_cb = NULL;        lov->lov_page_pin_cb = NULL;        for (i = 0; i < lov->desc.ld_tgt_count; i++) {                if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_exp)                        continue;                rc |= obd_unregister_page_removal_cb(lov->lov_tgts[i]->ltd_exp,                                                     func);        }        return rc;}static int lov_register_lock_cancel_cb(struct obd_export *exp,                                         obd_lock_cancel_cb func){        struct lov_obd *lov = &exp->exp_obd->u.lov;        int i, rc = 0;        if (lov->lov_lock_cancel_cb && lov->lov_lock_cancel_cb != func)                return -EBUSY;        for (i = 0; i < lov->desc.ld_tgt_count; i++) {                if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_exp)                        continue;                rc |= obd_register_lock_cancel_cb(lov->lov_tgts[i]->ltd_exp,                                                  func);        }        lov->lov_lock_cancel_cb = func;        return rc;}static int lov_unregister_lock_cancel_cb(struct obd_export *exp,                                         obd_lock_cancel_cb func){        struct lov_obd *lov = &exp->exp_obd->u.lov;        int i, rc = 0;        if (lov->lov_lock_cancel_cb && lov->lov_lock_cancel_cb != func)                return -EINVAL;        for (i = 0; i < lov->desc.ld_tgt_count; i++) {                if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_exp)                        continue;                rc |= obd_unregister_lock_cancel_cb(lov->lov_tgts[i]->ltd_exp,                                                    func);        }        lov->lov_lock_cancel_cb = NULL;        return rc;}#define MAX_STRING_SIZE 128static int lov_connect_obd(struct obd_device *obd, __u32 index, int activate,                            struct obd_connect_data *data){        struct lov_obd *lov = &obd->u.lov;        struct obd_uuid tgt_uuid;        struct obd_device *tgt_obd;        struct obd_uuid lov_osc_uuid = { "LOV_OSC_UUID" };        struct lustre_handle conn = {0, };        struct obd_import *imp;#ifdef __KERNEL__        cfs_proc_dir_entry_t *lov_proc_dir;#endif        int rc;        ENTRY;        if (!lov->lov_tgts[index])                RETURN(-EINVAL);        tgt_uuid = lov->lov_tgts[index]->ltd_uuid;        tgt_obd = class_find_client_obd(&tgt_uuid, LUSTRE_OSC_NAME,                                        &obd->obd_uuid);        if (!tgt_obd) {                CERROR("Target %s not attached\n", obd_uuid2str(&tgt_uuid));                RETURN(-EINVAL);        }                if (!tgt_obd->obd_set_up) {                CERROR("Target %s not set up\n", obd_uuid2str(&tgt_uuid));                RETURN(-EINVAL);        }        if (data && (data->ocd_connect_flags & OBD_CONNECT_INDEX))                data->ocd_index = index;        /*         * Divine LOV knows that OBDs under it are OSCs.         */        imp = tgt_obd->u.cli.cl_import;        if (activate) {                tgt_obd->obd_no_recov = 0;                /* FIXME this is probably supposed to be                    ptlrpc_set_import_active.  Horrible naming. */                ptlrpc_activate_import(imp);        }        if (imp->imp_invalid) {                CERROR("not connecting OSC %s; administratively "                       "disabled\n", obd_uuid2str(&tgt_uuid));                rc = obd_register_observer(tgt_obd, obd);                if (rc) {                        CERROR("Target %s register_observer error %d; "                               "will not be able to reactivate\n",                               obd_uuid2str(&tgt_uuid), rc);                }                RETURN(0);        }        rc = obd_connect(&conn, tgt_obd, &lov_osc_uuid, data, NULL);        if (rc) {                CERROR("Target %s connect error %d\n",                       obd_uuid2str(&tgt_uuid), rc);                RETURN(rc);        }        lov->lov_tgts[index]->ltd_exp = class_conn2export(&conn);        if (!lov->lov_tgts[index]->ltd_exp) {                CERROR("Target %s: null export!\n", obd_uuid2str(&tgt_uuid));                RETURN(-ENODEV);        }        rc = obd_register_page_removal_cb(lov->lov_tgts[index]->ltd_exp,                                          lov->lov_page_removal_cb,                                          lov->lov_page_pin_cb);        if (rc) {                obd_disconnect(lov->lov_tgts[index]->ltd_exp);                lov->lov_tgts[index]->ltd_exp = NULL;                RETURN(rc);        }        rc = obd_register_lock_cancel_cb(lov->lov_tgts[index]->ltd_exp,                                         lov->lov_lock_cancel_cb);        if (rc) {                obd_unregister_page_removal_cb(lov->lov_tgts[index]->ltd_exp,                                               lov->lov_page_removal_cb);                obd_disconnect(lov->lov_tgts[index]->ltd_exp);                lov->lov_tgts[index]->ltd_exp = NULL;                RETURN(rc);        }        rc = obd_register_observer(tgt_obd, obd);        if (rc) {                CERROR("Target %s register_observer error %d\n",                       obd_uuid2str(&tgt_uuid), rc);                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);                obd_disconnect(lov->lov_tgts[index]->ltd_exp);                lov->lov_tgts[index]->ltd_exp = NULL;                RETURN(rc);        }        lov->lov_tgts[index]->ltd_reap = 0;        if (activate) {                lov->lov_tgts[index]->ltd_active = 1;                lov->desc.ld_active_tgt_count++;                lov->lov_tgts[index]->ltd_exp->exp_obd->obd_inactive = 0;        }        CDEBUG(D_CONFIG, "Connected tgt idx %d %s (%s) %sactive\n", index,               obd_uuid2str(&tgt_uuid), tgt_obd->obd_name, activate ? "":"in");#ifdef __KERNEL__        lov_proc_dir = lprocfs_srch(obd->obd_proc_entry, "target_obds");        if (lov_proc_dir) {                struct obd_device *osc_obd = class_conn2obd(&conn);                cfs_proc_dir_entry_t *osc_symlink;                char name[MAX_STRING_SIZE];                LASSERT(osc_obd != NULL);                LASSERT(osc_obd->obd_magic == OBD_DEVICE_MAGIC);                LASSERT(osc_obd->obd_type->typ_name != NULL);                snprintf(name, MAX_STRING_SIZE, "../../../%s/%s",                         osc_obd->obd_type->typ_name,                         osc_obd->obd_name);                osc_symlink = proc_symlink(osc_obd->obd_name, lov_proc_dir,                                           name);                if (osc_symlink == NULL) {                        CERROR("could not register LOV target "                               "/proc/fs/lustre/%s/%s/target_obds/%s.",                               obd->obd_type->typ_name, obd->obd_name,                               osc_obd->obd_name);                        lprocfs_remove(&lov_proc_dir);                }        }#endif        rc = qos_add_tgt(obd, index);        if (rc)                 CERROR("qos_add_tgt failed %d\n", rc);        RETURN(0);}static int lov_connect(struct lustre_handle *conn, struct obd_device *obd,                       struct obd_uuid *cluuid, struct obd_connect_data *data,                       void *localdata){        struct lov_obd *lov = &obd->u.lov;        struct lov_tgt_desc *tgt;        int i, rc;        ENTRY;        CDEBUG(D_CONFIG, "connect #%d\n", lov->lov_connects);        rc = class_connect(conn, obd, cluuid);        if (rc)                RETURN(rc);        /* Why should there ever be more than 1 connect? */        lov->lov_connects++;        LASSERT(lov->lov_connects == 1);                memset(&lov->lov_ocd, 0, sizeof(lov->lov_ocd));        if (data)                lov->lov_ocd = *data;        lov_getref(obd);        for (i = 0; i < lov->desc.ld_tgt_count; i++) {                tgt = lov->lov_tgts[i];                if (!tgt || obd_uuid_empty(&tgt->ltd_uuid))                        continue;                /* Flags will be lowest common denominator */                rc = lov_connect_obd(obd, i, lov->lov_tgts[i]->ltd_activate,                                     &lov->lov_ocd);                if (rc) {                        CERROR("%s: lov connect tgt %d failed: %d\n",                                obd->obd_name, i, rc);                        continue;                }        }        lov_putref(obd);                RETURN(0);}static int lov_disconnect_obd(struct obd_device *obd, __u32 index){        cfs_proc_dir_entry_t *lov_proc_dir;        struct lov_obd *lov = &obd->u.lov;        struct obd_device *osc_obd =                class_exp2obd(lov->lov_tgts[index]->ltd_exp);        int rc;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?