lib-move.c

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

C
1,970
字号
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * * lib/lib-move.c * Data movement routines * *  Copyright (c) 2001-2003 Cluster File Systems, Inc. * *   This file is part of Lustre, http://www.lustre.org * *   Lustre is free 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. * *   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 *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with Lustre; if not, write to the Free Software *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#define DEBUG_SUBSYSTEM S_LNET#include <lnet/lib-lnet.h>static int local_nid_dist_zero = 1;CFS_MODULE_PARM(local_nid_dist_zero, "i", int, 0444,                "Reserved");/* forward ref */static void lnet_commit_md (lnet_libmd_t *md, lnet_msg_t *msg);static void lnet_drop_delayed_put(lnet_msg_t *msg, char *reason);#define LNET_MATCHMD_NONE     0   /* Didn't match */#define LNET_MATCHMD_OK       1   /* Matched OK */#define LNET_MATCHMD_DROP     2   /* Must be discarded */static intlnet_try_match_md (int index, int op_mask, lnet_process_id_t src,                   unsigned int rlength, unsigned int roffset,                    __u64 match_bits, lnet_libmd_t *md, lnet_msg_t *msg,                   unsigned int *mlength_out, unsigned int *offset_out){        /* ALWAYS called holding the LNET_LOCK, and can't LNET_UNLOCK;         * lnet_match_blocked_msg() relies on this to avoid races */        unsigned int  offset;        unsigned int  mlength;        lnet_me_t    *me = md->md_me;        /* mismatched MD op */        if ((md->md_options & op_mask) == 0)                return LNET_MATCHMD_NONE;        /* MD exhausted */        if (lnet_md_exhausted(md))                return LNET_MATCHMD_NONE;        /* mismatched ME nid/pid? */        if (me->me_match_id.nid != LNET_NID_ANY &&            me->me_match_id.nid != src.nid)                return LNET_MATCHMD_NONE;        if (me->me_match_id.pid != LNET_PID_ANY &&            me->me_match_id.pid != src.pid)                return LNET_MATCHMD_NONE;        /* mismatched ME matchbits? */        if (((me->me_match_bits ^ match_bits) & ~me->me_ignore_bits) != 0)                return LNET_MATCHMD_NONE;        /* Hurrah! This _is_ a match; check it out... */        if ((md->md_options & LNET_MD_MANAGE_REMOTE) == 0)                offset = md->md_offset;        else                offset = roffset;        if ((md->md_options & LNET_MD_MAX_SIZE) != 0) {                mlength = md->md_max_size;                LASSERT (md->md_offset + mlength <= md->md_length);        } else {                mlength = md->md_length - offset;        }        if (rlength <= mlength) {        /* fits in allowed space */                mlength = rlength;        } else if ((md->md_options & LNET_MD_TRUNCATE) == 0) {                /* this packet _really_ is too big */                CERROR("Matching packet from %s, match "LPU64                       " length %d too big: %d left, %d allowed\n",                        libcfs_id2str(src), match_bits, rlength,                       md->md_length - offset, mlength);                return LNET_MATCHMD_DROP;        }        /* Commit to this ME/MD */        CDEBUG(D_NET, "Incoming %s index %x from %s of "               "length %d/%d into md "LPX64" [%d] + %d\n",               (op_mask == LNET_MD_OP_PUT) ? "put" : "get",               index, libcfs_id2str(src), mlength, rlength,               md->md_lh.lh_cookie, md->md_niov, offset);        lnet_commit_md(md, msg);        md->md_offset = offset + mlength;        /* NB Caller will set ev.type and ev.hdr_data */        msg->msg_ev.initiator = src;        msg->msg_ev.pt_index = index;        msg->msg_ev.match_bits = match_bits;        msg->msg_ev.rlength = rlength;        msg->msg_ev.mlength = mlength;        msg->msg_ev.offset = offset;        lnet_md_deconstruct(md, &msg->msg_ev.md);        lnet_md2handle(&msg->msg_ev.md_handle, md);        *offset_out = offset;        *mlength_out = mlength;        /* Auto-unlink NOW, so the ME gets unlinked if required.         * We bumped md->md_refcount above so the MD just gets flagged         * for unlink when it is finalized. */        if ((md->md_flags & LNET_MD_FLAG_AUTO_UNLINK) != 0 &&            lnet_md_exhausted(md)) {                lnet_md_unlink(md);        }        return LNET_MATCHMD_OK;}static intlnet_match_md(int index, int op_mask, lnet_process_id_t src,              unsigned int rlength, unsigned int roffset,              __u64 match_bits, lnet_msg_t *msg,              unsigned int *mlength_out, unsigned int *offset_out,              lnet_libmd_t **md_out){        lnet_portal_t    *ptl = &the_lnet.ln_portals[index];        lnet_me_t        *me;        lnet_me_t        *tmp;        lnet_libmd_t     *md;        int               rc;        CDEBUG (D_NET, "Request from %s of length %d into portal %d "                "MB="LPX64"\n", libcfs_id2str(src), rlength, index, match_bits);        if (index < 0 || index >= the_lnet.ln_nportals) {                CERROR("Invalid portal %d not in [0-%d]\n",                       index, the_lnet.ln_nportals);                return LNET_MATCHMD_DROP;        }        list_for_each_entry_safe (me, tmp, &ptl->ptl_ml, me_list) {                md = me->me_md;                /* ME attached but MD not attached yet */                if (md == NULL)                        continue;                LASSERT (me == md->md_me);                rc = lnet_try_match_md(index, op_mask, src, rlength,                                        roffset, match_bits, md, msg,                                       mlength_out, offset_out);                switch (rc) {                default:                        LBUG();                                        case LNET_MATCHMD_NONE:                        continue;                                        case LNET_MATCHMD_OK:                        *md_out = md;                        return LNET_MATCHMD_OK;                                        case LNET_MATCHMD_DROP:                        return LNET_MATCHMD_DROP;                }                /* not reached */        }        if (op_mask == LNET_MD_OP_GET ||            (ptl->ptl_options & LNET_PTL_LAZY) == 0)                return LNET_MATCHMD_DROP;                return LNET_MATCHMD_NONE;}intlnet_fail_nid (lnet_nid_t nid, unsigned int threshold){        lnet_test_peer_t   *tp;        struct list_head  *el;        struct list_head  *next;        struct list_head   cull;        LASSERT (the_lnet.ln_init);                if (threshold != 0) {                /* Adding a new entry */                LIBCFS_ALLOC(tp, sizeof(*tp));                if (tp == NULL)                        return -ENOMEM;                tp->tp_nid = nid;                tp->tp_threshold = threshold;                LNET_LOCK();                list_add_tail (&tp->tp_list, &the_lnet.ln_test_peers);                LNET_UNLOCK();                return 0;        }        /* removing entries */        CFS_INIT_LIST_HEAD (&cull);        LNET_LOCK();        list_for_each_safe (el, next, &the_lnet.ln_test_peers) {                tp = list_entry (el, lnet_test_peer_t, tp_list);                if (tp->tp_threshold == 0 ||    /* needs culling anyway */                    nid == LNET_NID_ANY ||       /* removing all entries */                    tp->tp_nid == nid)          /* matched this one */                {                        list_del (&tp->tp_list);                        list_add (&tp->tp_list, &cull);                }        }        LNET_UNLOCK();        while (!list_empty (&cull)) {                tp = list_entry (cull.next, lnet_test_peer_t, tp_list);                list_del (&tp->tp_list);                LIBCFS_FREE(tp, sizeof (*tp));        }        return 0;}static intfail_peer (lnet_nid_t nid, int outgoing){        lnet_test_peer_t  *tp;        struct list_head *el;        struct list_head *next;        struct list_head  cull;        int               fail = 0;        CFS_INIT_LIST_HEAD (&cull);        LNET_LOCK();        list_for_each_safe (el, next, &the_lnet.ln_test_peers) {                tp = list_entry (el, lnet_test_peer_t, tp_list);                if (tp->tp_threshold == 0) {                        /* zombie entry */                        if (outgoing) {                                /* only cull zombies on outgoing tests,                                 * since we may be at interrupt priority on                                 * incoming messages. */                                list_del (&tp->tp_list);                                list_add (&tp->tp_list, &cull);                        }                        continue;                }                if (tp->tp_nid == LNET_NID_ANY || /* fail every peer */                    nid == tp->tp_nid) {        /* fail this peer */                        fail = 1;                        if (tp->tp_threshold != LNET_MD_THRESH_INF) {                                tp->tp_threshold--;                                if (outgoing &&                                    tp->tp_threshold == 0) {                                        /* see above */                                        list_del (&tp->tp_list);                                        list_add (&tp->tp_list, &cull);                                }                        }                        break;                }        }        LNET_UNLOCK ();        while (!list_empty (&cull)) {                tp = list_entry (cull.next, lnet_test_peer_t, tp_list);                list_del (&tp->tp_list);                LIBCFS_FREE(tp, sizeof (*tp));        }        return (fail);}unsigned intlnet_iov_nob (unsigned int niov, struct iovec *iov){        unsigned int nob = 0;        while (niov-- > 0)                nob += (iov++)->iov_len;        return (nob);}voidlnet_copy_iov2iov (unsigned int ndiov, struct iovec *diov, unsigned int doffset,                   unsigned int nsiov, struct iovec *siov, unsigned int soffset,                   unsigned int nob){        /* NB diov, siov are READ-ONLY */        unsigned int  this_nob;        if (nob == 0)                return;        /* skip complete frags before 'doffset' */        LASSERT (ndiov > 0);        while (doffset >= diov->iov_len) {                doffset -= diov->iov_len;                diov++;                ndiov--;                LASSERT (ndiov > 0);        }                /* skip complete frags before 'soffset' */        LASSERT (nsiov > 0);        while (soffset >= siov->iov_len) {                soffset -= siov->iov_len;                siov++;                nsiov--;                LASSERT (nsiov > 0);        }        do {                LASSERT (ndiov > 0);                LASSERT (nsiov > 0);                this_nob = MIN(diov->iov_len - doffset,                               siov->iov_len - soffset);                this_nob = MIN(this_nob, nob);                memcpy ((char *)diov->iov_base + doffset,                        (char *)siov->iov_base + soffset, this_nob);                nob -= this_nob;                if (diov->iov_len > doffset + this_nob) {                        doffset += this_nob;                } else {                        diov++;                        ndiov--;                        doffset = 0;                }                                if (siov->iov_len > soffset + this_nob) {                        soffset += this_nob;                } else {                        siov++;                        nsiov--;                        soffset = 0;                }        } while (nob > 0);}intlnet_extract_iov (int dst_niov, struct iovec *dst,                  int src_niov, struct iovec *src,                  unsigned int offset, unsigned int len){        /* Initialise 'dst' to the subset of 'src' starting at 'offset',         * for exactly 'len' bytes, and return the number of entries.         * NB not destructive to 'src' */        unsigned int    frag_len;        unsigned int    niov;        if (len == 0)                           /* no data => */                return (0);                     /* no frags */        LASSERT (src_niov > 0);        while (offset >= src->iov_len) {      /* skip initial frags */                offset -= src->iov_len;                src_niov--;                src++;                LASSERT (src_niov > 0);        }        niov = 1;

⌨️ 快捷键说明

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