public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* An idea .... with code
@ 2008-08-24  8:53 jassi brar
  2008-08-25 12:22 ` Jochen Voß
                   ` (2 more replies)
  0 siblings, 3 replies; 20+ messages in thread
From: jassi brar @ 2008-08-24  8:53 UTC (permalink / raw)
  To: linux-kernel

Hi,

  Lately a question has been bugging me: Why do we keep complicated(specific ioctls to set up and set free) LOOP driver to emulate a data file as block-device, for it to be mounted/formated.

 Wouldn't it be nice if we didnt have to specify '-o loop' or use losetup -d etc?

 With inspiration from UMS-Gadget and LOOP driver itself, I implemented a proof of concept: A kernel module which creats a node in /sys/devices/ and un/loads files to be emulated as block devices. The interface doesn't implement any new ioctls or a syscall.

To load a file all we need to do is:-

$ echo +filename > /sys/devices/virblk/manage   //NOTE the - sign

To unload a file:- 

$ echo -filename > /sys/devices/virblk/manage   //NOTE the - sign


 The module creates one thread per node and alloc/free the data structures in the runtime thereby neither limiting the max number of files that could be emulated nor hogging space when not necessary.


/*************************/

[root@localhost jmod]# dd if=/dev/zero of=image bs=1024 count=102400

[root@localhost jmod]# echo +image > /sys/devices/virblk/manage 
[root@localhost jmod]# cat /sys/devices/virblk/manage
/home/jassi/jmod/image' as 'v0blk'

[root@localhost jmod]# dmesg -c
File(image) is being emulated as block device v0blk
 v0blk: unknown partition table

[root@localhost jmod]# fdisk /dev/v0blk 
Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel
Building a new DOS disklabel with disk identifier 0x360df22f.
Changes will remain in memory only, until you decide to write them.
After that, of course, the previous content won't be recoverable.

Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite)

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (1-100, default 1): 
Using default value 1
Last cylinder or +size or +sizeM or +sizeK (1-100, default 100): 50

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 2
First cylinder (51-100, default 51): 
Using default value 51
Last cylinder or +size or +sizeM or +sizeK (51-100, default 100): 
Using default value 100

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.

[root@localhost jmod]# mkfs.ext2 /dev/v0blk1 
mke2fs 1.40.8 (13-Mar-2008)
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
12824 inodes, 51184 blocks
2559 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=52428800
7 block groups
8192 blocks per group, 8192 fragments per group
1832 inodes per group
Superblock backups stored on blocks: 
	8193, 24577, 40961

Writing inode tables: done                            
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 36 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.

[root@localhost jmod]# mkfs.ext2 /dev/v0blk2 
mke2fs 1.40.8 (13-Mar-2008)
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
12824 inodes, 51200 blocks
2560 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=52428800
7 block groups
8192 blocks per group, 8192 fragments per group
1832 inodes per group
Superblock backups stored on blocks: 
	8193, 24577, 40961

Writing inode tables: done                            
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 38 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.

[root@localhost jmod]# dmesg -c
 v0blk: v0blk1 v0blk2
 v0blk: v0blk1 v0blk2

[root@localhost jmod]# echo -image > /sys/devices/virblk/manage 
[root@localhost jmod]# dmesg -c
Killed thread 'vblk0_thread'

[root@localhost jmod]# echo +image > /sys/devices/virblk/manage 
[root@localhost jmod]# dmesg 
File(image) is being emulated as block device v0blk
 v0blk: v0blk1 v0blk2

[root@localhost jmod]# parted /dev/v0blk
GNU Parted 1.8.8
Using /dev/v0blk
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) p                                                                
Model: Unknown (unknown)
Disk /dev/v0blk: 105MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos

Number  Start   End     Size    Type     File system  Flags
 1      16.4kB  52.4MB  52.4MB  primary  ext2              
 2      52.4MB  105MB   52.4MB  primary  ext2              

(parted) q                                                                
[root@localhost jmod]# 

/**************************************/


The module source code is attached too:-

--------------------------8<-------------------------------

/*
 * Kernel module to emulate a user space file as a block device transparently.
 *
 * Copyright (C) 2008 Jaswinder Singh Brar <jassi_singh_brar AT yahoo DOT com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

#include <linux/module.h>
#include <linux/init.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/hdreg.h>
#include <linux/blkdev.h>
#include <linux/kthread.h>

#define VBD_MAJOR	121 /* Just some available */
#define VBD_NAME	"vblk"

#define NUM_SPC_BITS	5 /* == 32 */
#define NUM_HEADS_BITS	6 /* == 64 */
#define SECT_SIZE_BITS	9 /* == 512 */
#define NUM_MINORS	16

#define REGBLKDEV  (1<<0)
#define REGPDEV    (1<<1)
#define CRTDEVFL   (1<<2)

/*
 * Various parameters could be configured at module load time or 'echo +' command.
 */
struct vir_blk_dev{
	int                    index;
	int                    heads_bits;
	int                    cylinders;
	int                    sectspercyl_bits;
	int                    sect_size_bits;
	int                    use_count;
	int                    md_change;
	int                    ro;
	loff_t                 sects;
	struct file           *filp;
	struct gendisk        *gd;
	struct request_queue  *rq;
	struct bio            *vbd_biotail;
	struct bio            *vbd_bio;
	struct list_head       vbd_list;
	struct task_struct    *vbd_thread;
	struct semaphore       sem;
	spinlock_t             vbd_lock;
	wait_queue_head_t      vbd_event;
};

static LIST_HEAD(vbd_head);

static struct device vir_dev = {
	.bus_id = "virblk",
};

static int data_xfer(struct vir_blk_dev *vbd, struct page *page, unsigned int len, 
				unsigned int off, int wr, sector_t sector)
{
	ssize_t ret;
	loff_t pos = sector * (1<<(vbd->sect_size_bits));
	void *buf = kmap(page) + off;

	if(sector + (len >> vbd->sect_size_bits) > get_capacity(vbd->gd)){
		printk("Trying to move past the end!\n");
		kunmap(page);
		return -EIO;
	}

	if(wr)
	   ret = vbd->filp->f_op->write(vbd->filp, buf, len, &pos);
	else
	   ret = vbd->filp->f_op->read(vbd->filp, buf, len, &pos);

	kunmap(page);

	if(likely(ret == len))
		return 0;

	if(ret >= 0)
		ret = -EIO;

	return ret;
}

static void handle_bio(struct vir_blk_dev *vbd, struct bio *bio)
{
	int i, ret = -EIO;
	struct bio_vec *bvec;
	sector_t sector;

	sector = bio->bi_sector;
	bio_for_each_segment(bvec, bio, i){

		ret = data_xfer(vbd, bvec->bv_page, bvec->bv_len, bvec->bv_offset, 
							bio_data_dir(bio) == WRITE, sector);
		if(ret){
			break;
		}
		sector += (bvec->bv_len >> vbd->sect_size_bits);
	}

	bio_endio(bio, ret);
}

static int vbd_make_request(struct request_queue *rq, struct bio *bio)
{
	struct vir_blk_dev *vbd = (struct vir_blk_dev *)rq->queuedata;

	spin_lock_irq(&vbd->vbd_lock);

	if(vbd->vbd_biotail != NULL){
		vbd->vbd_biotail->bi_next = bio;
		vbd->vbd_biotail = bio;
	}else{
		vbd->vbd_bio = vbd->vbd_biotail = bio;
	}

	wake_up(&vbd->vbd_event);
	spin_unlock_irq(&vbd->vbd_lock);
	return 0;
} 

static int jmod_open(struct inode *inode, struct file *filp)
{
	struct vir_blk_dev *vbd = (struct vir_blk_dev *)inode->i_bdev->bd_disk->private_data;

	down(&vbd->sem);
	filp->private_data = (void *)vbd;
	vbd->use_count++;
	up(&vbd->sem);

	return 0;
}

static int jmod_release(struct inode *inode, struct file *filp)
{
	struct vir_blk_dev *vbd = (struct vir_blk_dev *)inode->i_bdev->bd_disk->private_data;

	down(&vbd->sem);
	vbd->filp->f_op->fsync(vbd->filp, vbd->filp->f_path.dentry, 1);
	vbd->use_count--;
	up(&vbd->sem);

	return 0;
}

static int jmod_getgeo(struct block_device *bdev, struct hd_geometry *gm)
{
	struct vir_blk_dev *vbd = bdev->bd_disk->private_data;

	down(&vbd->sem);
	gm->heads = 1<<(vbd->heads_bits);
	gm->sectors = 1<<(vbd->sectspercyl_bits);
	gm->cylinders = get_capacity(bdev->bd_disk) >> (vbd->heads_bits + vbd->sectspercyl_bits);
	up(&vbd->sem);

	return 0;
}

static int jmod_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
	return 0;
}


static int jmod_mediachanged(struct gendisk *gd)
{
	struct vir_blk_dev *vbd = gd->private_data;

	return vbd->md_change;
}

static int jmod_revalidatedisk(struct gendisk *gd)
{
	struct vir_blk_dev *vbd = gd->private_data;

	down(&vbd->sem);
	if(vbd->md_change)
		vbd->md_change = 0;
	up(&vbd->sem);

	return 0;
}

static struct block_device_operations vbd_fops = {
	.owner = THIS_MODULE,
	.open = jmod_open,
	.release = jmod_release,
	.ioctl = jmod_ioctl,
	.getgeo = jmod_getgeo,
	.media_changed = jmod_mediachanged,
	.revalidate_disk = jmod_revalidatedisk,
};

/*
 * ind : First minor number of the disk
 * */
static struct vir_blk_dev *vblk_alloc(int ind)
{
	struct gendisk *disk;
	struct vir_blk_dev *vbd;

	vbd = kzalloc(sizeof(*vbd), GFP_KERNEL);
	if (vbd == NULL)
		goto out;

	vbd->filp = NULL;
	vbd->vbd_thread = NULL;
	vbd->use_count = 0;
	vbd->md_change = 1;
	vbd->index = ind;
	vbd->vbd_bio = NULL;
	vbd->vbd_biotail = NULL;

	vbd->rq = blk_alloc_queue(GFP_KERNEL);
	if(vbd->rq == NULL){
		goto out;
	}
	blk_queue_make_request(vbd->rq, vbd_make_request);
	blk_queue_bounce_limit(vbd->rq, BLK_BOUNCE_ANY);

	disk = vbd->gd = alloc_disk(NUM_MINORS);
	if(disk == NULL){
		goto out;
	}
	disk->major		= VBD_MAJOR;
	disk->first_minor	= ind*NUM_MINORS;
	disk->fops		= &vbd_fops;
	disk->private_data	= (void *)vbd;
	vbd->rq->queuedata	= (void *)vbd;
	disk->queue		= vbd->rq;
	disk->flags |= GENHD_FL_REMOVABLE;
	sprintf(disk->disk_name, "v%dblk", ind);
	init_waitqueue_head(&vbd->vbd_event);

	return vbd;

out:
	if(vbd && vbd->rq){
		blk_cleanup_queue(vbd->rq);
	}
	if(vbd){
		kfree(vbd);
	}
	return NULL;
}

static struct file* open_backing_file(const char *filename, int *ro, loff_t *size)
{
	struct file      *filp = NULL;
	struct inode     *inode = NULL;

	*ro = 0;
	*size = 0;

	filp = filp_open(filename, O_RDWR | O_LARGEFILE, 0);
	if (-EROFS == PTR_ERR(filp))
		*ro = 1;
	if (*ro)
		filp = filp_open(filename, O_RDONLY | O_LARGEFILE, 0);
	if (IS_ERR(filp)) {
		printk("unable to open backing file: %s\n", filename);
		return NULL;
	}

	if(!(filp->f_mode & FMODE_WRITE))
		*ro = 1;

	if(filp->f_path.dentry)
		inode = filp->f_path.dentry->d_inode;

	if(inode && S_ISBLK(inode->i_mode)){
		if (bdev_read_only(inode->i_bdev))
			*ro = 1;
	}else if(!inode || !S_ISREG(inode->i_mode)){
		printk("invalid file type: %s\n", filename);
		filp_close(filp, current->files);
		return NULL;
	}

	if (!filp->f_op || !(filp->f_op->read || filp->f_op->aio_read)) {
		printk("file not readable: %s\n", filename);
		filp_close(filp, current->files);
		return NULL;
	}
	if (!(filp->f_op->write || filp->f_op->aio_write))
		*ro = 1;

	*size = i_size_read(inode->i_mapping->host);
	if (*size < 0) {
		printk("unable to find file size: %s\n", filename);
		filp_close(filp, current->files);
		return NULL;
	}

	get_file(filp);

	filp_close(filp, current->files);
	return filp;
}

static int io_handler(void *data)
{
	struct vir_blk_dev* vbd = (struct vir_blk_dev *)data;
	struct bio *bio;

	allow_signal(SIGINT);
	allow_signal(SIGTERM);
	allow_signal(SIGKILL);
	allow_signal(SIGUSR1);

	set_user_nice(current, -20);
	set_fs(get_ds());

	while(!kthread_should_stop()){

		down(&vbd->sem);
		while(vbd->vbd_bio != NULL){
			spin_lock_irq(&vbd->vbd_lock);
			bio = vbd->vbd_bio;
			if(bio == vbd->vbd_biotail){
				vbd->vbd_biotail = NULL;
			}
			vbd->vbd_bio = bio->bi_next;
			bio->bi_next = NULL;
			spin_unlock_irq(&vbd->vbd_lock);

			handle_bio(vbd, bio);
		}
		up(&vbd->sem);

		wait_event_interruptible(vbd->vbd_event, (vbd->vbd_bio!=NULL) || kthread_should_stop());
	}

	down(&vbd->sem);

	/* Flush any pending bio's */
	while(vbd->vbd_bio != NULL){
		spin_lock_irq(&vbd->vbd_lock);

		bio = vbd->vbd_bio;
		if(bio == vbd->vbd_biotail)
			vbd->vbd_biotail = NULL;

		vbd->vbd_bio = bio->bi_next;
		bio->bi_next = NULL;

		spin_unlock_irq(&vbd->vbd_lock);

		bio_endio(bio, -EIO);
	}

	if(vbd->gd)
		del_gendisk(vbd->gd);

	if(vbd->rq)
		blk_cleanup_queue(vbd->rq);

	if(vbd->gd)
		put_disk(vbd->gd);

	vbd->vbd_thread = NULL;

	up(&vbd->sem);

	return 0;
}

static struct vir_blk_dev* create_vbd(int ind, const char *filename)
{
	int ro = 0;
	loff_t size = 0;
	struct file* fl;
	struct vir_blk_dev *vbd = NULL;

	fl = open_backing_file(filename, &ro, &size);
	if(fl == NULL)
		goto retnull;

	/* Check if the file is already being emulated */
	list_for_each_entry(vbd, &vbd_head, vbd_list){
		if(vbd->filp->f_path.dentry->d_name.hash == fl->f_path.dentry->d_name.hash){
			printk("File already being emulated\n");
			return NULL;
		}
	}

	vbd = vblk_alloc(ind);
	if(vbd == NULL){
		printk(KERN_ALERT "Couldn't create anymore VBD!\n");
		goto retnull;
	}

	vbd->filp = fl;
	vbd->ro = ro;

	vbd->sectspercyl_bits = NUM_SPC_BITS;
	vbd->heads_bits = NUM_HEADS_BITS;
	vbd->sect_size_bits = SECT_SIZE_BITS;
	vbd->sects = size >> (vbd->sect_size_bits);

	set_capacity(vbd->gd, vbd->sects);
	vbd->cylinders = get_capacity(vbd->gd) >> (vbd->heads_bits + vbd->sectspercyl_bits);
	spin_lock_init(&vbd->vbd_lock);
	init_MUTEX(&vbd->sem);

	/* Create a thread to handle Read/Write */
	vbd->vbd_thread = kthread_create(io_handler, vbd, "vblk%d_thread", vbd->index);
	if(IS_ERR(vbd->vbd_thread)){
		printk(KERN_ALERT "Unable to create thread for %s!\n", vbd->gd->disk_name);
		goto retnull;
	}
	wake_up_process(vbd->vbd_thread);
	printk("File(%s) is being emulated as block device %s\n", filename, vbd->gd->disk_name);
	add_disk(vbd->gd);

	return vbd;

retnull:
	if(vbd != NULL){
		if(vbd->rq != NULL)
			blk_cleanup_queue(vbd->rq);

		if(vbd->gd != NULL)
			put_disk(vbd->gd);

		kfree(vbd);
	}
	return NULL;
}

static void pdev_release(struct device *dev)
{
	return;
}

static int detach_vbd(const char *filename)
{
	struct file *filp;
	struct vir_blk_dev *next, *vbd;

	filp = filp_open(filename, O_RDONLY | O_LARGEFILE, 0);
	if(IS_ERR(filp))
		return 0;

	list_for_each_entry_safe(vbd, next, &vbd_head, vbd_list){
		if(vbd->filp->f_path.dentry->d_name.hash == filp->f_path.dentry->d_name.hash){
			if(vbd->use_count != 0){
				printk("Can't unload busy device(%s)\n", vbd->gd->disk_name);
				filp_close(filp, current->files);
				return 0;
			}
			kthread_stop(vbd->vbd_thread);
			while(vbd->vbd_thread != NULL)
				schedule();
			printk("Killed thread 'vblk%d_thread'\n", vbd->index);
			list_del(&vbd->vbd_list);
			kfree(vbd);
			filp_close(filp, current->files);
			return 1;
		}
	}
	printk("File(%s) not being emulated\n", filename);
	filp_close(filp, current->files);
	return 0;
}

static int attach_vbd(char *filename)
{
	int ind, i;
	struct vir_blk_dev *vbd = NULL;

	/* Find an available Ind */
	ind = i = 0;
	do{
		i = ind;
		list_for_each_entry(vbd, &vbd_head, vbd_list){
			if(vbd->index == ind){
				ind++;
				break;
			}
		}
	}while(ind != i);

	vbd = create_vbd(ind, filename);
	if(vbd != NULL){
		list_add_tail(&vbd->vbd_list, &vbd_head);
		return 1;
	}else{
		printk("Unable to load(%s)\n", filename);
		return 0;
	}
}

static ssize_t nodes_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	if(count>0 && buf[count-1] == '\n')
		((char *) buf)[count-1] = 0;

	if(buf[0] == '-' && detach_vbd(buf+1))
		return count;
	else if(buf[0] == '+' && attach_vbd(buf+1))
		return count;
	else
		return -EINVAL;
}

static ssize_t nodes_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	ssize_t ret = 0;
	struct vir_blk_dev *vbd;
	char *fname;

	list_for_each_entry(vbd, &vbd_head, vbd_list){
		down(&vbd->sem);
		fname = d_path(&vbd->filp->f_path, buf, PAGE_SIZE - 1);

		if(IS_ERR(fname)){
			ret = PTR_ERR(fname);
			up(&vbd->sem);
			break;
		}
		ret += sprintf(buf+ret, "%s' as '%s'\n", fname, vbd->gd->disk_name);
		up(&vbd->sem);
	}

	return ret;
}

static DEVICE_ATTR(manage, S_IRUGO|S_IWUSR, nodes_show, nodes_store);

static int __init vb_init(void)
{
	int ret = 0;
	int op_done = 0;

	ret = register_blkdev(VBD_MAJOR, VBD_NAME);
	if(ret){
		printk(KERN_NOTICE "Could not register_blkdev!\n");
		ret = -EIO;
		goto cleanup;
	}else{
		op_done |= REGBLKDEV;
	}

	vir_dev.release = pdev_release;
	if(device_register(&vir_dev)){
		ret = -EIO;
		printk(KERN_NOTICE "Could not device_register!\n");
		goto cleanup;
	}else{
		op_done |= REGPDEV;
	}

	if(device_create_file(&vir_dev, &dev_attr_manage)){
		ret = -EIO;
		printk(KERN_NOTICE "Could not device_create_file!\n");
		goto cleanup;
	}else{
		op_done |= CRTDEVFL;
	}

	return ret;

cleanup:
	if(op_done & CRTDEVFL){
		device_remove_file(&vir_dev, &dev_attr_manage);
		op_done &= ~CRTDEVFL;
	}

	if(op_done & REGPDEV){
		device_unregister(&vir_dev);
		op_done &= ~REGPDEV;
	}

	if(op_done & REGBLKDEV){
		unregister_blkdev(VBD_MAJOR, VBD_NAME);
		op_done &= ~REGBLKDEV;
	}

	return ret;
}

static void __exit vb_exit(void)
{
	struct vir_blk_dev *vbd, *next;

	list_for_each_entry_safe(vbd, next, &vbd_head, vbd_list){
		kthread_stop(vbd->vbd_thread);
		while(vbd->vbd_thread != NULL)
			schedule();
		printk("Killed thread 'vblk%d_thread'\n", vbd->index);
		list_del(&vbd->vbd_list);
		kfree(vbd);
	}

	device_remove_file(&vir_dev, &dev_attr_manage);
	device_unregister(&vir_dev);

	unregister_blkdev(VBD_MAJOR, VBD_NAME);
}

module_init(vb_init);
module_exit(vb_exit);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("A Block Device Emulator");
--------------------------8<--------------------------


 If i am not missing why this module shudn't be preferred, i would like to improve upon the code and try to contribute it back.

 Of course, please CC the replies to me too.

Regards,
Jassi


      

^ permalink raw reply	[flat|nested] 20+ messages in thread
* Re: An idea .... with code
@ 2008-08-27  0:44 jassi brar
  0 siblings, 0 replies; 20+ messages in thread
From: jassi brar @ 2008-08-27  0:44 UTC (permalink / raw)
  To: linux-kernel; +Cc: jochen.voss

Hi Jochen, Marcin and Bill,

> Some minor remarks below.
> It's better to check this patch with scripts/checkpatch.pl  
Thanks for the feedback. I admit the code is not near perfection, but then 
 i think that comes after the community finds the idea any worth.

> will it interface with crypto applications like LUKS? 
   It should work with LUKS, as it transparently emulates a file as a block device. 
 Please suggest a test case(webpage?) to verify it against LUKS, as i don't know much about it.

 As i said the code was just as a proof of concept hastily put together. I heard Linux folks hate Ideas without code :)
 Btw, i personally believe not everyone with an idea could code well and not every good programmer is as well creative.
 
Regards,
-Jassi


      

^ permalink raw reply	[flat|nested] 20+ messages in thread
* Re: An idea .... with code
@ 2008-08-27  2:27 jassi brar
  0 siblings, 0 replies; 20+ messages in thread
From: jassi brar @ 2008-08-27  2:27 UTC (permalink / raw)
  To: andi; +Cc: linux-kernel

Hi Andi,

Before starting i would like to point out the 'philosophy' behind the idea.

 Exceptions(special cases) make for entropy and hence complexity. Generalization keeps uniformity and hences Order and Ease.
 We can't escape 'entropy' when emulating something that it is actually not, nevertheless we can minimize it by introducing as least and as localized changes as possible. 
 My idea congregates only determining changes at the lowest level(driver), unlike the respectable LOOP driver which hardcodes limits and adds to the entropy(new ioctls, special utilities etc). I am sure you, being a vetran, understand the point well.
 
 I am not for discarding features from the system, but for implementing them in a way that is lesser intrusive.
 
> Can you please expand a bit why you think losetup is that complicated
> and what the problem is with it?
 Sir, i don't object to losetup as such. It is a utility made(specifically?) for LOOP devices: which implements unnecessary gears and switches to operate.
 I object only to what could be done without using ioctls and not to features that losetup provides for devices other than Loop(are there any?)

> AFAIK you're essentially just moving a minimal version of losetup
> (with missing features like no offsets etc.) into the kernel 
 Its simpler than that :)
 All i do is implement non-ioctl method to load/unload a file as a (emulated)block device. And alloc/free resources for them on need basis rather than limiting them at driver-module load-time.

 Further about some features of LOOP drivers like encryption: i think they are better done at filesystem level.
 I believe any operation that could be done on a real block device shud be possible on an emulated one. And exactly that.
 If there is any need to do some stuff(offsets, encryption etc) then that cud be done on a real block and we would surely already have utilities for doing that on real devices(and hences on a transparent emulated device).
 I am unable to think of something practical that can _only_ be done using the 'offset feature' of losetup on /dev/loop AND which can not be accomplished for (emulated or not)block devices.
 The point is to only make least intrusive and most generic code, for making easy the inheritance of standard system-wide features, utilities and usages.

 LOOP driver was a brilliant idea for the early days of Linux. The days when one could relatively easily define new syscalls/ioctls.
 
> Or rather if you start with losetup, why stop at mount, modprobe, ifconfig, mkfs, fsck, ls[1], ...?
 I am not starting with any application.
 I start with removing redundancy in a driver(LOOP), if by doing that i make obsolete an application... am for it.

>[1] I'm sure someone could come up with some scheme to do ls using sysfs 
> and you could find someone on this list who said "cool" :)
 It would indeed be cool if the one doesn't make use of 'cat' 'grep' et al and the method is more efficient. 
 Otherwise it would just be four motobikes tugging a car :)

Regards,
Jassi



      

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2008-08-30  2:43 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-08-24  8:53 An idea .... with code jassi brar
2008-08-25 12:22 ` Jochen Voß
2008-08-25 20:53   ` Marcin Slusarz
2008-08-26  2:47 ` Bill Davidsen
2008-08-26  8:24 ` Andi Kleen
2008-08-26 10:44   ` Alexey Dobriyan
2008-08-26 11:08     ` Andi Kleen
2008-08-27  7:24   ` jassi brar
2008-08-27  7:47     ` Andi Kleen
2008-08-27  9:57       ` David Newall
2008-08-27 10:01         ` Andi Kleen
2008-08-27 12:38       ` jassi brar
2008-08-27 12:47         ` Andi Kleen
2008-08-27 14:49           ` Kasper Sandberg
2008-08-27 15:02             ` Andi Kleen
2008-08-28  1:24               ` jassi brar
2008-08-28  9:41               ` Kasper Sandberg
2008-08-30  2:57             ` Bill Davidsen
  -- strict thread matches above, loose matches on Subject: below --
2008-08-27  0:44 jassi brar
2008-08-27  2:27 jassi brar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox