📄 lloop.c
字号:
/* -*- 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 + -