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