1912 lines · 46.4 KB · C
RawDownload
/* *  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 write_begin is 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 * */ #include <linux/module.h>#include <linux/moduleparam.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/swap.h>#include <linux/slab.h>#include <linux/loop.h>#include <linux/compat.h>#include <linux/suspend.h>#include <linux/freezer.h>#include <linux/mutex.h>#include <linux/writeback.h>#include <linux/buffer_head.h>		/* for invalidate_bdev() */#include <linux/completion.h>#include <linux/highmem.h>#include <linux/kthread.h>#include <linux/splice.h>#include <linux/sysfs.h>#include <linux/miscdevice.h>#include <linux/falloc.h> #include <asm/uaccess.h> static DEFINE_IDR(loop_index_idr);static DEFINE_MUTEX(loop_index_mutex); static int max_part;static int part_shift; /* * Transfer functions */static int transfer_none(struct loop_device *lo, int cmd,			 struct page *raw_page, unsigned raw_off,			 struct page *loop_page, unsigned loop_off,			 int size, sector_t real_block){	char *raw_buf = kmap_atomic(raw_page, KM_USER0) + raw_off;	char *loop_buf = kmap_atomic(loop_page, KM_USER1) + loop_off; 	if (cmd == READ)		memcpy(loop_buf, raw_buf, size);	else		memcpy(raw_buf, loop_buf, size); 	kunmap_atomic(loop_buf, KM_USER1);	kunmap_atomic(raw_buf, KM_USER0);	cond_resched();	return 0;} static int transfer_xor(struct loop_device *lo, int cmd,			struct page *raw_page, unsigned raw_off,			struct page *loop_page, unsigned loop_off,			int size, sector_t real_block){	char *raw_buf = kmap_atomic(raw_page, KM_USER0) + raw_off;	char *loop_buf = kmap_atomic(loop_page, KM_USER1) + loop_off;	char *in, *out, *key;	int i, keysize; 	if (cmd == READ) {		in = raw_buf;		out = loop_buf;	} else {		in = loop_buf;		out = raw_buf;	} 	key = lo->lo_encrypt_key;	keysize = lo->lo_encrypt_key_size;	for (i = 0; i < size; i++)		*out++ = *in++ ^ key[(i & 511) % keysize]; 	kunmap_atomic(loop_buf, KM_USER1);	kunmap_atomic(raw_buf, KM_USER0);	cond_resched();	return 0;} static int xor_init(struct loop_device *lo, const struct loop_info64 *info){	if (unlikely(info->lo_encrypt_key_size <= 0))		return -EINVAL;	return 0;} static struct loop_func_table none_funcs = {	.number = LO_CRYPT_NONE,	.transfer = transfer_none,}; 	 static struct loop_func_table xor_funcs = {	.number = LO_CRYPT_XOR,	.transfer = transfer_xor,	.init = xor_init}; 	 /* xfer_funcs[0] is special - its release function is never called */static struct loop_func_table *xfer_funcs[MAX_LO_CRYPT] = {	&none_funcs,	&xor_funcs}; static loff_t get_size(loff_t offset, loff_t sizelimit, struct file *file){	loff_t size, loopsize; 	/* Compute loopsize in bytes */	size = i_size_read(file->f_mapping->host);	loopsize = size - offset;	/* offset is beyond i_size, wierd but possible */	if (loopsize < 0)		return 0; 	if (sizelimit > 0 && sizelimit < loopsize)		loopsize = 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 loff_t get_loop_size(struct loop_device *lo, struct file *file){	return get_size(lo->lo_offset, lo->lo_sizelimit, file);} static intfigure_loop_size(struct loop_device *lo, loff_t offset, loff_t sizelimit){	loff_t size = get_size(offset, sizelimit, lo->lo_backing_file);	sector_t x = (sector_t)size; 	if (unlikely((loff_t)x != size))		return -EFBIG;	if (lo->lo_offset != offset)		lo->lo_offset = offset;	if (lo->lo_sizelimit != sizelimit)		lo->lo_sizelimit = sizelimit;	set_capacity(lo->lo_disk, x);	return 0;} static inline intlo_do_transfer(struct loop_device *lo, int cmd,	       struct page *rpage, unsigned roffs,	       struct page *lpage, unsigned loffs,	       int size, sector_t rblock){	if (unlikely(!lo->transfer))		return 0; 	return lo->transfer(lo, cmd, rpage, roffs, lpage, loffs, size, rblock);} /** * __do_lo_send_write - helper for writing data to a loop device * * This helper just factors out common code between do_lo_send_direct_write() * and do_lo_send_write(). */static int __do_lo_send_write(struct file *file,		u8 *buf, const int len, loff_t pos){	ssize_t bw;	mm_segment_t old_fs = get_fs(); 	set_fs(get_ds());	bw = file->f_op->write(file, buf, len, &pos);	set_fs(old_fs);	if (likely(bw == len))		return 0;	printk(KERN_ERR "loop: Write error at byte offset %llu, length %i.\n",			(unsigned long long)pos, len);	if (bw >= 0)		bw = -EIO;	return bw;} /** * do_lo_send_direct_write - helper for writing data to a loop device * * This is the fast, non-transforming version that does not need double * buffering. */static int do_lo_send_direct_write(struct loop_device *lo,		struct bio_vec *bvec, loff_t pos, struct page *page){	ssize_t bw = __do_lo_send_write(lo->lo_backing_file,			kmap(bvec->bv_page) + bvec->bv_offset,			bvec->bv_len, pos);	kunmap(bvec->bv_page);	cond_resched();	return bw;} /** * do_lo_send_write - helper for writing data to a loop device * * This is the slow, transforming version that needs to double buffer the * data as it cannot do the transformations in place without having direct * access to the destination pages of the backing file. */static int do_lo_send_write(struct loop_device *lo, struct bio_vec *bvec,		loff_t pos, struct page *page){	int ret = lo_do_transfer(lo, WRITE, page, 0, bvec->bv_page,			bvec->bv_offset, bvec->bv_len, pos >> 9);	if (likely(!ret))		return __do_lo_send_write(lo->lo_backing_file,				page_address(page), bvec->bv_len,				pos);	printk(KERN_ERR "loop: Transfer error at byte offset %llu, "			"length %i.\n", (unsigned long long)pos, bvec->bv_len);	if (ret > 0)		ret = -EIO;	return ret;} static int lo_send(struct loop_device *lo, struct bio *bio, loff_t pos){	int (*do_lo_send)(struct loop_device *, struct bio_vec *, loff_t,			struct page *page);	struct bio_vec *bvec;	struct page *page = NULL;	int i, ret = 0; 	if (lo->transfer != transfer_none) {		page = alloc_page(GFP_NOIO | __GFP_HIGHMEM);		if (unlikely(!page))			goto fail;		kmap(page);		do_lo_send = do_lo_send_write;	} else {		do_lo_send = do_lo_send_direct_write;	} 	bio_for_each_segment(bvec, bio, i) {		ret = do_lo_send(lo, bvec, pos, page);		if (ret < 0)			break;		pos += bvec->bv_len;	}	if (page) {		kunmap(page);		__free_page(page);	}out:	return ret;fail:	printk(KERN_ERR "loop: Failed to allocate temporary page for write.\n");	ret = -ENOMEM;	goto out;} struct lo_read_data {	struct loop_device *lo;	struct page *page;	unsigned offset;	int bsize;}; static intlo_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf,		struct splice_desc *sd){	struct lo_read_data *p = sd->u.data;	struct loop_device *lo = p->lo;	struct page *page = buf->page;	sector_t IV;	int size; 	IV = ((sector_t) page->index << (PAGE_CACHE_SHIFT - 9)) +							(buf->offset >> 9);	size = sd->len;	if (size > p->bsize)		size = p->bsize; 	if (lo_do_transfer(lo, READ, page, buf->offset, p->page, p->offset, size, IV)) {		printk(KERN_ERR "loop: transfer error block %ld\n",		       page->index);		size = -EINVAL;	} 	flush_dcache_page(p->page); 	if (size > 0)		p->offset += size; 	return size;} static intlo_direct_splice_actor(struct pipe_inode_info *pipe, struct splice_desc *sd){	return __splice_from_pipe(pipe, sd, lo_splice_actor);} static intdo_lo_receive(struct loop_device *lo,	      struct bio_vec *bvec, int bsize, loff_t pos){	struct lo_read_data cookie;	struct splice_desc sd;	struct file *file;	long retval; 	cookie.lo = lo;	cookie.page = bvec->bv_page;	cookie.offset = bvec->bv_offset;	cookie.bsize = bsize; 	sd.len = 0;	sd.total_len = bvec->bv_len;	sd.flags = 0;	sd.pos = pos;	sd.u.data = &cookie; 	file = lo->lo_backing_file;	retval = splice_direct_to_actor(file, &sd, lo_direct_splice_actor); 	if (retval < 0)		return retval;	if (retval != bvec->bv_len)		return -EIO;	return 0;} static intlo_receive(struct loop_device *lo, struct bio *bio, int bsize, loff_t pos){	struct bio_vec *bvec;	int i, ret = 0; 	bio_for_each_segment(bvec, bio, i) {		ret = do_lo_receive(lo, bvec, bsize, pos);		if (ret < 0)			break;		pos += bvec->bv_len;	}	return ret;} static int do_bio_filebacked(struct loop_device *lo, struct bio *bio){	loff_t pos;	int ret; 	pos = ((loff_t) bio->bi_sector << 9) + lo->lo_offset; 	if (bio_rw(bio) == WRITE) {		struct file *file = lo->lo_backing_file; 		if (bio->bi_rw & REQ_FLUSH) {			ret = vfs_fsync(file, 0);			if (unlikely(ret && ret != -EINVAL)) {				ret = -EIO;				goto out;			}		} 		/*		 * We use punch hole to reclaim the free space used by the		 * image a.k.a. discard. However we do not support discard if		 * encryption is enabled, because it may give an attacker		 * useful information.		 */		if (bio->bi_rw & REQ_DISCARD) {			struct file *file = lo->lo_backing_file;			int mode = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE; 			if ((!file->f_op->fallocate) ||			    lo->lo_encrypt_key_size) {				ret = -EOPNOTSUPP;				goto out;			}			ret = file->f_op->fallocate(file, mode, pos,						    bio->bi_size);			if (unlikely(ret && ret != -EINVAL &&				     ret != -EOPNOTSUPP))				ret = -EIO;			goto out;		} 		ret = lo_send(lo, bio, pos); 		if ((bio->bi_rw & REQ_FUA) && !ret) {			ret = vfs_fsync(file, 0);			if (unlikely(ret && ret != -EINVAL))				ret = -EIO;		}	} else		ret = lo_receive(lo, bio, lo->lo_blocksize, pos); out:	return ret;} /* * Add bio to back of pending list */static void loop_add_bio(struct loop_device *lo, struct bio *bio){	bio_list_add(&lo->lo_bio_list, bio);} /* * Grab first pending buffer */static struct bio *loop_get_bio(struct loop_device *lo){	return bio_list_pop(&lo->lo_bio_list);} static void loop_make_request(struct request_queue *q, struct bio *old_bio){	struct loop_device *lo = q->queuedata;	int rw = bio_rw(old_bio); 	if (rw == READA)		rw = READ; 	BUG_ON(!lo || (rw != READ && rw != WRITE)); 	spin_lock_irq(&lo->lo_lock);	if (lo->lo_state != Lo_bound)		goto out;	if (unlikely(rw == WRITE && (lo->lo_flags & LO_FLAGS_READ_ONLY)))		goto out;	loop_add_bio(lo, old_bio);	wake_up(&lo->lo_event);	spin_unlock_irq(&lo->lo_lock);	return; out:	spin_unlock_irq(&lo->lo_lock);	bio_io_error(old_bio);} 

Lines 1–500 of 1912.