filter_io_26.c

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

C
811
字号
/* -*- 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. */#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 <linux/buffer_head.h>#define DEBUG_SUBSYSTEM S_FILTER#include <obd_class.h>#include <lustre_fsfilt.h>#include <lustre_quota.h>#include "filter_internal.h"/* 512byte block min */#define MAX_BLOCKS_PER_PAGE (CFS_PAGE_SIZE / 512)struct filter_iobuf {        atomic_t          dr_numreqs;  /* number of reqs being processed */        wait_queue_head_t dr_wait;        int               dr_max_pages;        int               dr_npages;        int               dr_error;        struct page     **dr_pages;        unsigned long    *dr_blocks;        spinlock_t        dr_lock;              /* IRQ lock */        unsigned int      dr_ignore_quota:1;        struct filter_obd *dr_filter;};static void record_start_io(struct filter_iobuf *iobuf, int rw, int size,                            struct obd_export *exp){        struct filter_obd *filter = iobuf->dr_filter;        atomic_inc(&iobuf->dr_numreqs);        if (rw == OBD_BRW_READ) {                atomic_inc(&filter->fo_r_in_flight);                lprocfs_oh_tally(&filter->fo_filter_stats.hist[BRW_R_RPC_HIST],                                 atomic_read(&filter->fo_r_in_flight));                lprocfs_oh_tally_log2(&filter->fo_filter_stats.hist[BRW_R_DISK_IOSIZE], size);                lprocfs_oh_tally(&exp->exp_filter_data.fed_brw_stats.hist[BRW_R_RPC_HIST],                                 atomic_read(&filter->fo_r_in_flight));                lprocfs_oh_tally_log2(&exp->exp_filter_data.fed_brw_stats.hist[BRW_R_DISK_IOSIZE], size);        } else {                atomic_inc(&filter->fo_w_in_flight);                lprocfs_oh_tally(&filter->fo_filter_stats.hist[BRW_W_RPC_HIST],                                 atomic_read(&filter->fo_w_in_flight));                lprocfs_oh_tally_log2(&filter->fo_filter_stats.hist[BRW_W_DISK_IOSIZE], size);                lprocfs_oh_tally(&exp->exp_filter_data.fed_brw_stats.hist[BRW_W_RPC_HIST],                                 atomic_read(&filter->fo_w_in_flight));                lprocfs_oh_tally_log2(&exp->exp_filter_data.fed_brw_stats.hist[BRW_W_DISK_IOSIZE], size);        }}static void record_finish_io(struct filter_iobuf *iobuf, int rw, int rc){        struct filter_obd *filter = iobuf->dr_filter;        /* CAVEAT EMPTOR: possibly in IRQ context          * DO NOT record procfs stats here!!! */        if (rw == OBD_BRW_READ)                atomic_dec(&filter->fo_r_in_flight);        else                atomic_dec(&filter->fo_w_in_flight);        if (atomic_dec_and_test(&iobuf->dr_numreqs))                wake_up(&iobuf->dr_wait);}static int dio_complete_routine(struct bio *bio, unsigned int done, int error){        struct filter_iobuf *iobuf = bio->bi_private;        unsigned long        flags;#ifdef HAVE_PAGE_CONSTANT        struct bio_vec *bvl;        int i;#endif        /* CAVEAT EMPTOR: possibly in IRQ context          * DO NOT record procfs stats here!!! */        if (bio->bi_size)                       /* Not complete */                return 1;        if (iobuf == NULL) {                CERROR("***** bio->bi_private is NULL!  This should never "                       "happen.  Normally, I would crash here, but instead I "                       "will dump the bio contents to the console.  Please "                       "report this to CFS, along with any interesting "                       "messages leading up to this point (like SCSI errors, "                       "perhaps).  Because bi_private is NULL, I can't wake up "                       "the thread that initiated this I/O -- so you will "                       "probably have to reboot this node.\n");                CERROR("bi_next: %p, bi_flags: %lx, bi_rw: %lu, bi_vcnt: %d, "                       "bi_idx: %d, bi->size: %d, bi_end_io: %p, bi_cnt: %d, "                       "bi_private: %p\n", bio->bi_next, bio->bi_flags,                       bio->bi_rw, bio->bi_vcnt, bio->bi_idx, bio->bi_size,                       bio->bi_end_io, atomic_read(&bio->bi_cnt),                       bio->bi_private);                return 0;        }#ifdef HAVE_PAGE_CONSTANT        bio_for_each_segment(bvl, bio, i)                ClearPageConstant(bvl->bv_page);#endif        spin_lock_irqsave(&iobuf->dr_lock, flags);        if (iobuf->dr_error == 0)                iobuf->dr_error = error;        spin_unlock_irqrestore(&iobuf->dr_lock, flags);        record_finish_io(iobuf, test_bit(BIO_RW, &bio->bi_rw) ?                         OBD_BRW_WRITE : OBD_BRW_READ, error);        /* Completed bios used to be chained off iobuf->dr_bios and freed in         * filter_clear_dreq().  It was then possible to exhaust the biovec-256         * mempool when serious on-disk fragmentation was encountered,         * deadlocking the OST.  The bios are now released as soon as complete         * so the pool cannot be exhausted while IOs are competing. bug 10076 */        bio_put(bio);        return 0;}static int can_be_merged(struct bio *bio, sector_t sector){        unsigned int size;        if (!bio)                return 0;        size = bio->bi_size >> 9;        return bio->bi_sector + size == sector ? 1 : 0;}struct filter_iobuf *filter_alloc_iobuf(struct filter_obd *filter,                                        int rw, int num_pages){        struct filter_iobuf *iobuf;        LASSERTF(rw == OBD_BRW_WRITE || rw == OBD_BRW_READ, "%x\n", rw);        OBD_ALLOC(iobuf, sizeof(*iobuf));        if (iobuf == NULL)                goto failed_0;        OBD_ALLOC(iobuf->dr_pages, num_pages * sizeof(*iobuf->dr_pages));        if (iobuf->dr_pages == NULL)                goto failed_1;        OBD_ALLOC(iobuf->dr_blocks,                  MAX_BLOCKS_PER_PAGE * num_pages * sizeof(*iobuf->dr_blocks));        if (iobuf->dr_blocks == NULL)                goto failed_2;        iobuf->dr_filter = filter;        init_waitqueue_head(&iobuf->dr_wait);        atomic_set(&iobuf->dr_numreqs, 0);        spin_lock_init(&iobuf->dr_lock);        iobuf->dr_max_pages = num_pages;        iobuf->dr_npages = 0;        iobuf->dr_error = 0;        RETURN(iobuf); failed_2:        OBD_FREE(iobuf->dr_pages,                 num_pages * sizeof(*iobuf->dr_pages)); failed_1:        OBD_FREE(iobuf, sizeof(*iobuf)); failed_0:        RETURN(ERR_PTR(-ENOMEM));}static void filter_clear_iobuf(struct filter_iobuf *iobuf){        iobuf->dr_npages = 0;        iobuf->dr_error = 0;        atomic_set(&iobuf->dr_numreqs, 0);}void filter_free_iobuf(struct filter_iobuf *iobuf){        int num_pages = iobuf->dr_max_pages;        filter_clear_iobuf(iobuf);        OBD_FREE(iobuf->dr_blocks,                 MAX_BLOCKS_PER_PAGE * num_pages * sizeof(*iobuf->dr_blocks));        OBD_FREE(iobuf->dr_pages,                 num_pages * sizeof(*iobuf->dr_pages));        OBD_FREE_PTR(iobuf);}void filter_iobuf_put(struct filter_obd *filter, struct filter_iobuf *iobuf,                      struct obd_trans_info *oti){        int thread_id = oti ? oti->oti_thread_id : -1;        if (unlikely(thread_id < 0)) {                filter_free_iobuf(iobuf);                return;        }        LASSERTF(filter->fo_iobuf_pool[thread_id] == iobuf,                 "iobuf mismatch for thread %d: pool %p iobuf %p\n",                 thread_id, filter->fo_iobuf_pool[thread_id], iobuf);        filter_clear_iobuf(iobuf);}int filter_iobuf_add_page(struct obd_device *obd, struct filter_iobuf *iobuf,                          struct inode *inode, struct page *page){        LASSERT(iobuf->dr_npages < iobuf->dr_max_pages);        iobuf->dr_pages[iobuf->dr_npages++] = page;        return 0;}int filter_do_bio(struct obd_export *exp, struct inode *inode,                  struct filter_iobuf *iobuf, int rw){        struct obd_device *obd = exp->exp_obd;        int            blocks_per_page = CFS_PAGE_SIZE >> inode->i_blkbits;        struct page  **pages = iobuf->dr_pages;        int            npages = iobuf->dr_npages;        unsigned long *blocks = iobuf->dr_blocks;        int            total_blocks = npages * blocks_per_page;        int            sector_bits = inode->i_sb->s_blocksize_bits - 9;        unsigned int   blocksize = inode->i_sb->s_blocksize;        struct bio    *bio = NULL;        int            frags = 0;        unsigned long  start_time = jiffies;        struct page   *page;        unsigned int   page_offset;        sector_t       sector;        int            nblocks;        int            block_idx;

⌨️ 快捷键说明

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