filter_io.c

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

C
863
字号
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * *  linux/fs/obdfilter/filter_io.c * *  Copyright (c) 2001-2003 Cluster File Systems, Inc. *   Author: Peter Braam <braam@clusterfs.com> *   Author: Andreas Dilger <adilger@clusterfs.com> *   Author: Phil Schwan <phil@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. */#define DEBUG_SUBSYSTEM S_FILTER#ifndef AUTOCONF_INCLUDED#include <linux/config.h>#endif#include <linux/module.h>#include <linux/pagemap.h> // XXX kill me soon#include <linux/version.h>#include <obd_class.h>#include <lustre_fsfilt.h>#include "filter_internal.h"int *obdfilter_created_scratchpad;static int filter_alloc_dio_page(struct obd_device *obd, struct inode *inode,                                 struct niobuf_local *lnb){        struct page *page;        LASSERT(lnb->page != NULL);        page = lnb->page;#if 0        POISON_PAGE(page, 0xf1);        if (lnb->len != CFS_PAGE_SIZE) {                memset(kmap(page) + lnb->len, 0, CFS_PAGE_SIZE - lnb->len);                kunmap(page);        }#endif        page->index = lnb->offset >> CFS_PAGE_SHIFT;        RETURN(0);}static void filter_free_dio_pages(int objcount, struct obd_ioobj *obj,                           int niocount, struct niobuf_local *res){        int i, j;        for (i = 0; i < objcount; i++, obj++) {                for (j = 0 ; j < obj->ioo_bufcnt ; j++, res++)                                res->page = NULL;        }}/* Grab the dirty and seen grant announcements from the incoming obdo. * We will later calculate the clients new grant and return it. * Caller must hold osfs lock */static void filter_grant_incoming(struct obd_export *exp, struct obdo *oa){        struct filter_export_data *fed;        struct obd_device *obd = exp->exp_obd;        ENTRY;        LASSERT_SPIN_LOCKED(&obd->obd_osfs_lock);        if ((oa->o_valid & (OBD_MD_FLBLOCKS|OBD_MD_FLGRANT)) !=                                        (OBD_MD_FLBLOCKS|OBD_MD_FLGRANT)) {                oa->o_valid &= ~OBD_MD_FLGRANT;                EXIT;                return;        }        fed = &exp->exp_filter_data;        /* Add some margin, since there is a small race if other RPCs arrive         * out-or-order and have already consumed some grant.  We want to         * leave this here in case there is a large error in accounting. */        CDEBUG(D_CACHE,               "%s: cli %s/%p reports grant: "LPU64" dropped: %u, local: %lu\n",               obd->obd_name, exp->exp_client_uuid.uuid, exp, oa->o_grant,               oa->o_dropped, fed->fed_grant);        /* Update our accounting now so that statfs takes it into account.         * Note that fed_dirty is only approximate and can become incorrect         * if RPCs arrive out-of-order.  No important calculations depend         * on fed_dirty however, but we must check sanity to not assert. */        if ((long long)oa->o_dirty < 0)                oa->o_dirty = 0;        else if (oa->o_dirty > fed->fed_grant + 4 * FILTER_GRANT_CHUNK)                oa->o_dirty = fed->fed_grant + 4 * FILTER_GRANT_CHUNK;        obd->u.filter.fo_tot_dirty += oa->o_dirty - fed->fed_dirty;        if (fed->fed_grant < oa->o_dropped) {                CDEBUG(D_CACHE,"%s: cli %s/%p reports %u dropped > grant %lu\n",                       obd->obd_name, exp->exp_client_uuid.uuid, exp,                       oa->o_dropped, fed->fed_grant);                oa->o_dropped = 0;        }        if (obd->u.filter.fo_tot_granted < oa->o_dropped) {                CERROR("%s: cli %s/%p reports %u dropped > tot_grant "LPU64"\n",                       obd->obd_name, exp->exp_client_uuid.uuid, exp,                       oa->o_dropped, obd->u.filter.fo_tot_granted);                oa->o_dropped = 0;        }        obd->u.filter.fo_tot_granted -= oa->o_dropped;        fed->fed_grant -= oa->o_dropped;        fed->fed_dirty = oa->o_dirty;        if (fed->fed_dirty < 0 || fed->fed_grant < 0 || fed->fed_pending < 0) {                CERROR("%s: cli %s/%p dirty %ld pend %ld grant %ld\n",                       obd->obd_name, exp->exp_client_uuid.uuid, exp,                       fed->fed_dirty, fed->fed_pending, fed->fed_grant);                spin_unlock(&obd->obd_osfs_lock);                LBUG();        }        EXIT;}/* Figure out how much space is available between what we've granted * and what remains in the filesystem.  Compensate for ext3 indirect * block overhead when computing how much free space is left ungranted. * * Caller must hold obd_osfs_lock. */obd_size filter_grant_space_left(struct obd_export *exp){        struct obd_device *obd = exp->exp_obd;        int blockbits = obd->u.obt.obt_sb->s_blocksize_bits;        obd_size tot_granted = obd->u.filter.fo_tot_granted, avail, left = 0;        int rc, statfs_done = 0;        LASSERT_SPIN_LOCKED(&obd->obd_osfs_lock);        if (cfs_time_before_64(obd->obd_osfs_age, cfs_time_current_64() - HZ)) {restat:                rc = fsfilt_statfs(obd, obd->u.obt.obt_sb,                                   cfs_time_current_64() + HZ);                if (rc) /* N.B. statfs can't really fail */                        RETURN(0);                statfs_done = 1;        }        avail = obd->obd_osfs.os_bavail;        left = avail - (avail >> (blockbits - 3)); /* (d)indirect */        if (left > GRANT_FOR_LLOG(obd)) {                left = (left - GRANT_FOR_LLOG(obd)) << blockbits;        } else {                left = 0 /* << blockbits */;        }        if (!statfs_done && left < 32 * FILTER_GRANT_CHUNK + tot_granted) {                CDEBUG(D_CACHE, "fs has no space left and statfs too old\n");                goto restat;        }        if (left >= tot_granted) {                left -= tot_granted;        } else {                if (left < tot_granted - obd->u.filter.fo_tot_pending) {                        CERROR("%s: cli %s/%p grant "LPU64" > available "                               LPU64" and pending "LPU64"\n", obd->obd_name,                               exp->exp_client_uuid.uuid, exp, tot_granted,                               left, obd->u.filter.fo_tot_pending);                }                left = 0;        }        CDEBUG(D_CACHE, "%s: cli %s/%p free: "LPU64" avail: "LPU64" grant "LPU64               " left: "LPU64" pending: "LPU64"\n", obd->obd_name,               exp->exp_client_uuid.uuid, exp,               obd->obd_osfs.os_bfree << blockbits, avail << blockbits,               tot_granted, left, obd->u.filter.fo_tot_pending);        return left;}/* Calculate how much grant space to allocate to this client, based on how * much space is currently free and how much of that is already granted. * * Caller must hold obd_osfs_lock. */long filter_grant(struct obd_export *exp, obd_size current_grant,                  obd_size want, obd_size fs_space_left){        struct obd_device *obd = exp->exp_obd;        struct filter_export_data *fed = &exp->exp_filter_data;        int blockbits = obd->u.obt.obt_sb->s_blocksize_bits;        __u64 grant = 0;        LASSERT_SPIN_LOCKED(&obd->obd_osfs_lock);        /* Grant some fraction of the client's requested grant space so that         * they are not always waiting for write credits (not all of it to         * avoid overgranting in face of multiple RPCs in flight).  This         * essentially will be able to control the OSC_MAX_RIF for a client.         *         * If we do have a large disparity between what the client thinks it         * has and what we think it has, don't grant very much and let the         * client consume its grant first.  Either it just has lots of RPCs         * in flight, or it was evicted and its grants will soon be used up. */        if (want > 0x7fffffff) {                CERROR("%s: client %s/%p requesting > 2GB grant "LPU64"\n",                       obd->obd_name, exp->exp_client_uuid.uuid, exp, want);        } else if (current_grant < want &&                   current_grant < fed->fed_grant + FILTER_GRANT_CHUNK) {                grant = min((want >> blockbits),                            (fs_space_left >> blockbits) / 8);                grant <<= blockbits;                if (grant) {                        /* Allow >FILTER_GRANT_CHUNK size when clients                         * reconnect due to a server reboot.                         */                        if ((grant > FILTER_GRANT_CHUNK) &&                            (!obd->obd_recovering))                                grant = FILTER_GRANT_CHUNK;                        obd->u.filter.fo_tot_granted += grant;                        fed->fed_grant += grant;                        if (fed->fed_grant < 0) {                                CERROR("%s: cli %s/%p grant %ld want "LPU64                                       "current"LPU64"\n",                                       obd->obd_name, exp->exp_client_uuid.uuid,                                       exp, fed->fed_grant, want,current_grant);                                spin_unlock(&obd->obd_osfs_lock);                                LBUG();                        }                }        }        CDEBUG(D_CACHE,               "%s: cli %s/%p wants: "LPU64" current grant "LPU64                " granting: "LPU64"\n", obd->obd_name, exp->exp_client_uuid.uuid,               exp, want, current_grant, grant);        CDEBUG(D_CACHE,               "%s: cli %s/%p tot cached:"LPU64" granted:"LPU64               " num_exports: %d\n", obd->obd_name, exp->exp_client_uuid.uuid,               exp, obd->u.filter.fo_tot_dirty,               obd->u.filter.fo_tot_granted, obd->obd_num_exports);        return grant;}static int filter_preprw_read(int cmd, struct obd_export *exp, struct obdo *oa,                              int objcount, struct obd_ioobj *obj,                              int niocount, struct niobuf_remote *nb,                              struct niobuf_local *res,                              struct obd_trans_info *oti){        struct obd_device *obd = exp->exp_obd;        struct lvfs_run_ctxt saved;        struct niobuf_remote *rnb;        struct niobuf_local *lnb;        struct dentry *dentry = NULL;        struct inode *inode;        void *iobuf = NULL;        int rc = 0, i, tot_bytes = 0;        unsigned long now = jiffies;        ENTRY;        /* We are currently not supporting multi-obj BRW_READ RPCS at all.         * When we do this function's dentry cleanup will need to be fixed.         * These values are verified in ost_brw_write() from the wire. */        LASSERTF(objcount == 1, "%d\n", objcount);        LASSERTF(obj->ioo_bufcnt > 0, "%d\n", obj->ioo_bufcnt);        if (oa->o_valid & OBD_MD_FLGRANT) {                spin_lock(&obd->obd_osfs_lock);                filter_grant_incoming(exp, oa);                oa->o_grant = 0;

⌨️ 快捷键说明

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