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

📄 loop.c-2.2.original

📁 Fast and transparent file system and swap encryption package for linux. No source code changes to li
💻 ORIGINAL
📖 第 1 页 / 共 2 页
字号:
/* *  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 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 * * 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 *  * Still To Fix: * - Advisory locking is ignored here.  * - Should use an own CAP_* category instead of CAP_SYS_ADMIN  * - Should use the underlying filesystems/devices read function if possible *   to support read ahead (and for write) * * WARNING/FIXME: * - The block number as IV passing to low level transfer functions is broken: *   it passes the underlying device's block number instead of the *   offset. This makes it change for a given block when the file is  *   moved/restored/copied and also doesn't work over NFS.  */ #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/init.h>#include <asm/uaccess.h>#include <linux/loop.h>		#define MAJOR_NR LOOP_MAJOR#define DEVICE_NAME "loop"#define DEVICE_REQUEST do_lo_request#define DEVICE_NR(device) (MINOR(device))#define DEVICE_ON(device)#define DEVICE_OFF(device)#define DEVICE_NO_RANDOM#define TIMEOUT_VALUE (6 * HZ)#include <linux/blk.h>#define MAX_LOOP 8static struct loop_device loop_dev[MAX_LOOP];static int loop_sizes[MAX_LOOP];static int loop_blksizes[MAX_LOOP];#define FALSE 0#define TRUE (!FALSE)/* Forward declaration of function to create missing blocks in the    backing file (can happen if the backing file is sparse) */static int create_missing_block(struct loop_device *lo, int block, int blksize);/* * Transfer functions */static int transfer_none(struct loop_device *lo, int cmd, char *raw_buf,		  char *loop_buf, int size, int real_block){	if (cmd == READ)		memcpy(loop_buf, raw_buf, size);	else		memcpy(raw_buf, loop_buf, size);	return 0;}static int transfer_xor(struct loop_device *lo, int cmd, char *raw_buf,		 char *loop_buf, int size, int real_block){	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];	return 0;}static int none_status(struct loop_device *lo, struct loop_info *info){	return 0; } static int xor_status(struct loop_device *lo, struct loop_info *info){	if (info->lo_encrypt_key_size <= 0)		return -EINVAL;	return 0;}struct loop_func_table none_funcs = { 	number: LO_CRYPT_NONE,	transfer: transfer_none,	init: none_status}; 	struct loop_func_table xor_funcs = { 	number: LO_CRYPT_XOR,	transfer: transfer_xor,	init: xor_status}; 	/* xfer_funcs[0] is special - its release function is never called */ struct loop_func_table *xfer_funcs[MAX_LO_CRYPT] = {	&none_funcs,	&xor_funcs  };#define MAX_DISK_SIZE 1024*1024*1024static void figure_loop_size(struct loop_device *lo){	int	size;	if (S_ISREG(lo->lo_dentry->d_inode->i_mode))		size = (lo->lo_dentry->d_inode->i_size - lo->lo_offset) / BLOCK_SIZE;	else {		kdev_t lodev = lo->lo_device;		if (blk_size[MAJOR(lodev)])			size = blk_size[MAJOR(lodev)][MINOR(lodev)] -                                lo->lo_offset / BLOCK_SIZE;		else			size = MAX_DISK_SIZE;	}	loop_sizes[lo->lo_number] = size;}static void do_lo_request(void){	int	real_block, block, offset, len, blksize, size;	char	*dest_addr;	struct loop_device *lo;	struct buffer_head *bh;	struct request *current_request;	int	block_present;repeat:	INIT_REQUEST;	current_request=CURRENT;	CURRENT=current_request->next;	if (MINOR(current_request->rq_dev) >= MAX_LOOP)		goto error_out;	lo = &loop_dev[MINOR(current_request->rq_dev)];	if (!lo->lo_dentry || !lo->transfer)		goto error_out;	blksize = BLOCK_SIZE;	if (blksize_size[MAJOR(lo->lo_device)]) {	    blksize = blksize_size[MAJOR(lo->lo_device)][MINOR(lo->lo_device)];	    if (!blksize)	      blksize = BLOCK_SIZE;	}	dest_addr = current_request->buffer;		if (blksize < 512) {		block = current_request->sector * (512/blksize);		offset = 0;	} else {		block = current_request->sector / (blksize >> 9);		offset = (current_request->sector % (blksize >> 9)) << 9;	}	block += lo->lo_offset / blksize;	offset += lo->lo_offset % blksize;	if (offset > blksize) {		block++;		offset -= blksize;	}	len = current_request->current_nr_sectors << 9;	if (current_request->cmd == WRITE) {		if (lo->lo_flags & LO_FLAGS_READ_ONLY)			goto error_out;	} else if (current_request->cmd != READ) {		printk(KERN_ERR "unknown loop device command (%d)?!?", current_request->cmd);		goto error_out;	}	spin_unlock_irq(&io_request_lock);	while (len > 0) {		size = blksize - offset;		if (size > len)			size = len;		real_block = block;		block_present = TRUE;		if (lo->lo_flags & LO_FLAGS_DO_BMAP) {			real_block = bmap(lo->lo_dentry->d_inode, block);			if (!real_block) {				/* The backing file is a sparse file and this block				   doesn't exist.  If reading, return zeros.  If				   writing, force the underlying FS to create				   the block */				if (current_request->cmd == READ) {					memset(dest_addr, 0, size);					block_present = FALSE;				} else {					if (!create_missing_block(lo, block, blksize)) {						goto error_out_lock;					}					real_block = bmap(lo->lo_dentry->d_inode, block);				}			}		}		if (block_present) {			bh = getblk(lo->lo_device, real_block, blksize);			if (!bh) {				printk(KERN_ERR "loop: device %s: getblk(-, %d, %d) returned NULL",					kdevname(lo->lo_device),					block, blksize);				goto error_out_lock;			}			if (!buffer_uptodate(bh) && ((current_request->cmd == READ) ||						(offset || (len < blksize)))) {				ll_rw_block(READ, 1, &bh);				wait_on_buffer(bh);				if (!buffer_uptodate(bh)) {					brelse(bh);					goto error_out_lock;				}			}			if ((lo->transfer)(lo, current_request->cmd, bh->b_data + offset,					dest_addr, size, real_block)) {				printk(KERN_ERR "loop: transfer error block %d\n", block);				brelse(bh);				goto error_out_lock;			}			if (current_request->cmd == WRITE) {				mark_buffer_uptodate(bh, 1);				mark_buffer_dirty(bh, 1);			}			brelse(bh);		}		dest_addr += size;		len -= size;		offset = 0;		block++;	}	spin_lock_irq(&io_request_lock);	current_request->next=CURRENT;	CURRENT=current_request;	end_request(1);	goto repeat;error_out_lock:	spin_lock_irq(&io_request_lock);error_out:	current_request->next=CURRENT;	CURRENT=current_request;	end_request(0);	goto repeat;}static int create_missing_block(struct loop_device *lo, int block, int blksize){	struct file     *file;	loff_t          new_offset;	char            zero_buf[1] = { 0 };	ssize_t         retval;	mm_segment_t	old_fs;	struct inode	*inode;	file = lo->lo_backing_file;	if (file == NULL) {		printk(KERN_WARNING "loop: cannot create block - no backing file\n");		return FALSE;	}	if (file->f_op == NULL) {		printk(KERN_WARNING "loop: cannot create block - no file ops\n");		return FALSE;	}	new_offset = block * blksize;	if (file->f_op->llseek != NULL) {		file->f_op->llseek(file, new_offset, 0);	} else {		/* Do what the default llseek() code would have done */		file->f_pos = new_offset;		file->f_reada = 0;		file->f_version = ++global_event;	}	if (file->f_op->write == NULL) {		printk(KERN_WARNING "loop: cannot create block - file not writeable\n");		return FALSE;	}	old_fs = get_fs();	set_fs(get_ds());	inode = file->f_dentry->d_inode;	down(&inode->i_sem); 	retval = file->f_op->write(file, zero_buf, 1, &file->f_pos);	up(&inode->i_sem);		set_fs(old_fs);	if (retval < 0) {		printk(KERN_WARNING		    "loop: cannot create block - FS write failed: code %d\n",		    (int)retval);		return FALSE;	} else {		return TRUE;	}}static int loop_set_fd(struct loop_device *lo, kdev_t dev, unsigned int arg){	struct file	*file;	struct inode	*inode;	int error;	MOD_INC_USE_COUNT;	error = -EBUSY;	if (lo->lo_dentry)		goto out;	error = -EBADF;	file = fget(arg);	if (!file)		goto out;	error = -EINVAL;	inode = file->f_dentry->d_inode;	if (!inode) {		printk(KERN_ERR "loop_set_fd: NULL inode?!?\n");		goto out_putf;	}	if (S_ISBLK(inode->i_mode)) {		error = blkdev_open(inode, file);

⌨️ 快捷键说明

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