⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lloop.c

📁 lustre 1.6.5 source code
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * * Lustre virtual block device emulator. * *  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. *//* *  linux/drivers/block/loop.c * *  Written by Theodore Ts'o, 3/29/93 * * Copyright 1993 by Theodore Ts'o.  Redistribution of this file is * permitted under the GNU General Public License. * * DES encryption plus some minor changes by Werner Almesberger, 30-MAY-1993 * more DES encryption plus IDEA encryption by Nicholas J. Leon, June 20, 1996 * * Modularized and updated for 1.1.16 kernel - Mitch Dsouza 28th May 1994 * Adapted for 1.3.59 kernel - Andries Brouwer, 1 Feb 1996 * * Fixed do_loop_request() re-entrancy - Vincent.Renardias@waw.com Mar 20, 1997 * * Added devfs support - Richard Gooch <rgooch@atnf.csiro.au> 16-Jan-1998 * * Handle sparse backing files correctly - Kenn Humborg, Jun 28, 1998 * * Loadable modules and other fixes by AK, 1998 * * Make real block number available to downstream transfer functions, enables * CBC (and relatives) mode encryption requiring unique IVs per data block. * Reed H. Petty, rhp@draper.net * * Maximum number of loop devices now dynamic via max_loop module parameter. * Russell Kroll <rkroll@exploits.org> 19990701 * * Maximum number of loop devices when compiled-in now selectable by passing * max_loop=<1-255> to the kernel on boot. * Erik I. Bols?, <eriki@himolde.no>, Oct 31, 1999 * * Completely rewrite request handling to be make_request_fn style and * non blocking, pushing work to a helper thread. Lots of fixes from * Al Viro too. * Jens Axboe <axboe@suse.de>, Nov 2000 * * Support up to 256 loop devices * Heinz Mauelshagen <mge@sistina.com>, Feb 2002 * * Support for falling back on the write file operation when the address space * operations prepare_write and/or commit_write are not available on the * backing filesystem. * Anton Altaparmakov, 16 Feb 2005 * * Still To Fix: * - Advisory locking is ignored here. * - Should use an own CAP_* category instead of CAP_SYS_ADMIN * */#ifndef AUTOCONF_INCLUDED#include <linux/config.h>#endif#include <linux/module.h>#include <linux/sched.h>#include <linux/fs.h>#include <linux/file.h>#include <linux/stat.h>#include <linux/errno.h>#include <linux/major.h>#include <linux/wait.h>#include <linux/blkdev.h>#include <linux/blkpg.h>#include <linux/init.h>#include <linux/smp_lock.h>#include <linux/swap.h>#include <linux/slab.h>#include <linux/suspend.h>#include <linux/writeback.h>#include <linux/buffer_head.h>                /* for invalidate_bdev() */#include <linux/completion.h>#include <linux/highmem.h>#include <linux/gfp.h>#include <linux/swap.h>#include <linux/pagevec.h>#include <asm/uaccess.h>#include <lustre_lib.h>#include <lustre_lite.h>#include "llite_internal.h"#define LLOOP_MAX_SEGMENTS        PTLRPC_MAX_BRW_PAGES/* Possible states of device */enum {        LLOOP_UNBOUND,        LLOOP_BOUND,        LLOOP_RUNDOWN,};struct lloop_device {        int                lo_number;        int                lo_refcnt;        loff_t             lo_offset;        loff_t             lo_sizelimit;        int                lo_flags;        int                (*ioctl)(struct lloop_device *, int cmd,                                  unsigned long arg);         struct file *      lo_backing_file;        struct block_device *lo_device;        unsigned           lo_blocksize;        int                old_gfp_mask;        spinlock_t         lo_lock;        struct bio         *lo_bio;        struct bio         *lo_biotail;        int                lo_state;        struct semaphore   lo_sem;        struct semaphore   lo_ctl_mutex;        struct semaphore   lo_bh_mutex;        atomic_t           lo_pending;        request_queue_t    *lo_queue;        /* data to handle bio for lustre. */        struct lo_request_data {                struct brw_page    lrd_pages[LLOOP_MAX_SEGMENTS];                struct obdo        lrd_oa;        } lo_requests[1];};/* * Loop flags */enum {        LO_FLAGS_READ_ONLY       = 1,};static int lloop_major;static int max_loop = 8;static struct lloop_device *loop_dev;static struct gendisk **disks;static struct semaphore lloop_mutex;static void *ll_iocontrol_magic = NULL;static loff_t get_loop_size(struct lloop_device *lo, struct file *file){        loff_t size, offset, loopsize;        /* Compute loopsize in bytes */        size = i_size_read(file->f_mapping->host);        offset = lo->lo_offset;        loopsize = size - offset;        if (lo->lo_sizelimit > 0 && lo->lo_sizelimit < loopsize)                loopsize = lo->lo_sizelimit;        /*         * Unfortunately, if we want to do I/O on the device,         * the number of 512-byte sectors has to fit into a sector_t.         */        return loopsize >> 9;}static int do_bio_filebacked(struct lloop_device *lo, struct bio *bio){        struct inode *inode = lo->lo_backing_file->f_dentry->d_inode;        struct ll_inode_info *lli = ll_i2info(inode);        struct lov_stripe_md *lsm = lli->lli_smd;        struct obd_info oinfo = {{{0}}};        struct brw_page *pg = lo->lo_requests[0].lrd_pages;        struct obdo *oa = &lo->lo_requests[0].lrd_oa;        pgoff_t offset;        int ret, cmd, i;        struct bio_vec *bvec;        BUG_ON(bio->bi_hw_segments > LLOOP_MAX_SEGMENTS);        offset = (pgoff_t)(bio->bi_sector << 9) + lo->lo_offset;        bio_for_each_segment(bvec, bio, i) {                BUG_ON(bvec->bv_offset != 0);                BUG_ON(bvec->bv_len != CFS_PAGE_SIZE);                pg->pg = bvec->bv_page;                pg->off = offset;                pg->count = bvec->bv_len;                pg->flag = OBD_BRW_SRVLOCK;                pg++;                offset += bvec->bv_len;        }        oa->o_mode = inode->i_mode;        oa->o_id = lsm->lsm_object_id;        oa->o_valid = OBD_MD_FLID | OBD_MD_FLMODE | OBD_MD_FLTYPE;        obdo_from_inode(oa, inode, OBD_MD_FLFID | OBD_MD_FLGENER);        cmd = OBD_BRW_READ;        if (bio_rw(bio) == WRITE)                cmd = OBD_BRW_WRITE;        if (cmd == OBD_BRW_WRITE)                ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_BRW_WRITE, bio->bi_size);        else                ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_BRW_READ, bio->bi_size);        oinfo.oi_oa = oa;        oinfo.oi_md = lsm;        ret = obd_brw(cmd, ll_i2obdexp(inode), &oinfo,                       (obd_count)(i - bio->bi_idx),                       lo->lo_requests[0].lrd_pages, NULL);        if (ret == 0)                obdo_to_inode(inode, oa, OBD_MD_FLBLOCKS);        return ret;}/* * Add bio to back of pending list */static void loop_add_bio(struct lloop_device *lo, struct bio *bio){        unsigned long flags;        spin_lock_irqsave(&lo->lo_lock, flags);        if (lo->lo_biotail) {                lo->lo_biotail->bi_next = bio;                lo->lo_biotail = bio;        } else                lo->lo_bio = lo->lo_biotail = bio;        spin_unlock_irqrestore(&lo->lo_lock, flags);        up(&lo->lo_bh_mutex);}/* * Grab first pending buffer */static struct bio *loop_get_bio(struct lloop_device *lo){        struct bio *bio;        spin_lock_irq(&lo->lo_lock);        if ((bio = lo->lo_bio)) {                if (bio == lo->lo_biotail)                        lo->lo_biotail = NULL;                lo->lo_bio = bio->bi_next;                bio->bi_next = NULL;        }        spin_unlock_irq(&lo->lo_lock);        return bio;}static int loop_make_request(request_queue_t *q, struct bio *old_bio){        struct lloop_device *lo = q->queuedata;        int rw = bio_rw(old_bio);        if (!lo)                goto out;        spin_lock_irq(&lo->lo_lock);        if (lo->lo_state != LLOOP_BOUND)                goto inactive;        atomic_inc(&lo->lo_pending);        spin_unlock_irq(&lo->lo_lock);        if (rw == WRITE) {                if (lo->lo_flags & LO_FLAGS_READ_ONLY)                        goto err;        } else if (rw == READA) {                rw = READ;        } else if (rw != READ) {                CERROR("lloop: unknown command (%x)\n", rw);                goto err;        }        loop_add_bio(lo, old_bio);        return 0;err:        if (atomic_dec_and_test(&lo->lo_pending))                up(&lo->lo_bh_mutex);out:        bio_io_error(old_bio, old_bio->bi_size);        return 0;inactive:        spin_unlock_irq(&lo->lo_lock);        goto out;}/* * kick off io on the underlying address space */static void loop_unplug(request_queue_t *q){        struct lloop_device *lo = q->queuedata;        clear_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags);        blk_run_address_space(lo->lo_backing_file->f_mapping);}static inline void loop_handle_bio(struct lloop_device *lo, struct bio *bio){        int ret;        ret = do_bio_filebacked(lo, bio);        bio_endio(bio, bio->bi_size, ret);}/* * worker thread that handles reads/writes to file backed loop devices, * to avoid blocking in our make_request_fn. it also does loop decrypting * on reads for block backed loop, as that is too heavy to do from * b_end_io context where irqs may be disabled. */static int loop_thread(void *data){        struct lloop_device *lo = data;        struct bio *bio;        daemonize("lloop%d", lo->lo_number);        set_user_nice(current, -20);        lo->lo_state = LLOOP_BOUND;        atomic_inc(&lo->lo_pending);        /*         * up sem, we are running         */        up(&lo->lo_sem);        for (;;) {                down_interruptible(&lo->lo_bh_mutex);                /*                 * could be upped because of tear-down, not because of                 * pending work                 */                if (!atomic_read(&lo->lo_pending))                        break;                bio = loop_get_bio(lo);                if (!bio) {                        CWARN("lloop(minor: %d): missing bio\n", lo->lo_number);                        continue;                }                loop_handle_bio(lo, bio);                /*                 * upped both for pending work and tear-down, lo_pending                 * will hit zero then                 */                if (atomic_dec_and_test(&lo->lo_pending))                        break;        }        up(&lo->lo_sem);        return 0;}static int loop_set_fd(struct lloop_device *lo, struct file *unused,                       struct block_device *bdev, struct file *file){        struct inode        *inode;        struct address_space *mapping;        int                lo_flags = 0;

⌨️ 快捷键说明

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