public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] loop: online resize support
@ 2006-05-23  7:31 Akinobu Mita
  2006-05-24 19:37 ` Andrew Morton
  0 siblings, 1 reply; 2+ messages in thread
From: Akinobu Mita @ 2006-05-23  7:31 UTC (permalink / raw)
  To: linux-kernel; +Cc: akpm, Jens Axboe, Theodore Ts'o, Akinobu Mita

This patch introduces new ioctl command LOOP_UPDATE_SIZE
which enables to resize online mounted loop device.

EXAMPLE
=======
# Make 10MB disk image
# dd if=/dev/zero of=image bs=1k count=10k
# mkfs.ext3 -j -F image

# Mount
# mkdir loop
# mount -o loop=/dev/loop/0,debug -t ext3 image loop

# Check disk size
# df -h loop
Filesystem            Size  Used Avail Use% Mounted on
/home/mita/looback-test/image
                      9.7M  1.1M  8.2M  12% /home/mita/looback-test/loop

# Extend disk image to 20MB
# dd if=/dev/zero of=appendix bs=1k count=10k
# cat appendix >> image

# Resize
# gcc -o loop-update loop-update.c
# ./loop-update /dev/loop/0
# ext2online -d -v image

# Check disk size again
# df -h loop
Filesystem            Size  Used Avail Use% Mounted on
/home/mita/looback-test/image
                       20M  1.1M   18M   6% /home/mita/looback-test/loop

loop-update.c
=============
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define LOOP_UPDATE_SIZE	0x4C07

int main(int argc, char **argv)
{
	int fd;
	int err;

	if (argc < 2) {
		fprintf(stderr, "usage: loop-update loop_device\n");
		exit(1);
	}

	fd = open(argv[1], O_RDWR);
	if (fd < 0) {
		perror(argv[1]);
		exit(1);
	}

	err = ioctl(fd, LOOP_UPDATE_SIZE, NULL);
	if (err) {
		perror(argv[1]);
		exit(1);
	}
}


CC: Jens Axboe <axboe@suse.de>
CC: "Theodore Ts'o" <tytso@mit.edu>
Signed-off-by: Akinobu Mita <mita@miraclelinux.com>

--- 2.6-mm/include/linux/loop.h.orig	2006-05-23 12:52:54.000000000 +0800
+++ 2.6-mm/include/linux/loop.h	2006-05-23 12:59:14.000000000 +0800
@@ -158,5 +158,6 @@ int loop_unregister_transfer(int number)
 #define LOOP_SET_STATUS64	0x4C04
 #define LOOP_GET_STATUS64	0x4C05
 #define LOOP_CHANGE_FD		0x4C06
+#define LOOP_UPDATE_SIZE	0x4C07
 
 #endif
--- 2.6-mm/drivers/block/loop.c.orig	2006-05-23 12:51:11.000000000 +0800
+++ 2.6-mm/drivers/block/loop.c	2006-05-23 13:50:58.000000000 +0800
@@ -1108,7 +1108,8 @@ loop_set_status64(struct loop_device *lo
 }
 
 static int
-loop_get_status_old(struct loop_device *lo, struct loop_info __user *arg) {
+loop_get_status_old(struct loop_device *lo, struct loop_info __user *arg)
+{
 	struct loop_info info;
 	struct loop_info64 info64;
 	int err = 0;
@@ -1126,7 +1127,8 @@ loop_get_status_old(struct loop_device *
 }
 
 static int
-loop_get_status64(struct loop_device *lo, struct loop_info64 __user *arg) {
+loop_get_status64(struct loop_device *lo, struct loop_info64 __user *arg)
+{
 	struct loop_info64 info64;
 	int err = 0;
 
@@ -1140,6 +1142,17 @@ loop_get_status64(struct loop_device *lo
 	return err;
 }
 
+static int loop_update_size(struct loop_device *lo)
+{
+	int err = figure_loop_size(lo);
+
+	if (!err)
+		i_size_write(lo->lo_device->bd_inode,
+			     (loff_t) get_capacity(disks[lo->lo_number]) << 9);
+
+	return err;
+}
+
 static int lo_ioctl(struct inode * inode, struct file * file,
 	unsigned int cmd, unsigned long arg)
 {
@@ -1169,6 +1182,9 @@ static int lo_ioctl(struct inode * inode
 	case LOOP_GET_STATUS64:
 		err = loop_get_status64(lo, (struct loop_info64 __user *) arg);
 		break;
+	case LOOP_UPDATE_SIZE:
+		err = loop_update_size(lo);
+		break;
 	default:
 		err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL;
 	}

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

* Re: [PATCH] loop: online resize support
  2006-05-23  7:31 [PATCH] loop: online resize support Akinobu Mita
@ 2006-05-24 19:37 ` Andrew Morton
  0 siblings, 0 replies; 2+ messages in thread
From: Andrew Morton @ 2006-05-24 19:37 UTC (permalink / raw)
  To: Akinobu Mita; +Cc: linux-kernel, axboe, tytso, mita

Akinobu Mita <mita@miraclelinux.com> wrote:
>
> This patch introduces new ioctl command LOOP_UPDATE_SIZE
> which enables to resize online mounted loop device.
> 
> EXAMPLE
> =======
> # Make 10MB disk image
> # dd if=/dev/zero of=image bs=1k count=10k
> # mkfs.ext3 -j -F image
> 
> # Mount
> # mkdir loop
> # mount -o loop=/dev/loop/0,debug -t ext3 image loop
> 
> # Check disk size
> # df -h loop
> Filesystem            Size  Used Avail Use% Mounted on
> /home/mita/looback-test/image
>                       9.7M  1.1M  8.2M  12% /home/mita/looback-test/loop
> 
> # Extend disk image to 20MB
> # dd if=/dev/zero of=appendix bs=1k count=10k
> # cat appendix >> image
> 
> # Resize
> # gcc -o loop-update loop-update.c
> # ./loop-update /dev/loop/0
> # ext2online -d -v image
> 
> # Check disk size again
> # df -h loop
> Filesystem            Size  Used Avail Use% Mounted on
> /home/mita/looback-test/image
>                        20M  1.1M   18M   6% /home/mita/looback-test/loop

<tries to remember how loop works>

> +static int loop_update_size(struct loop_device *lo)
> +{
> +	int err = figure_loop_size(lo);
> +
> +	if (!err)
> +		i_size_write(lo->lo_device->bd_inode,
> +			     (loff_t) get_capacity(disks[lo->lo_number]) << 9);
> +
> +	return err;
> +}
> +
>  static int lo_ioctl(struct inode * inode, struct file * file,
>  	unsigned int cmd, unsigned long arg)
>  {
> @@ -1169,6 +1182,9 @@ static int lo_ioctl(struct inode * inode
>  	case LOOP_GET_STATUS64:
>  		err = loop_get_status64(lo, (struct loop_info64 __user *) arg);
>  		break;
> +	case LOOP_UPDATE_SIZE:
> +		err = loop_update_size(lo);
> +		break;
>  	default:
>  		err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL;
>  	}

I don't immediately see any show-stoppers here.

Note that this interface will allow the loop "device" to be larger than the
backing file (in fact that's already the case).  Just ftruncate the backing
file to a shorter size.  Everything should still work after that has
happened - the VFS will just extend the file again once the loop driver
writes to it outside i_size.

Given that, and given that your code is a bit racy anyway, I don't think
the interface should be "resize the device to match the backing file's
size".  I think the interface should be "resize the loop device to this
loff_t".  That's a superset of what you have there, and it permits the
device size to be larger than or smaller than the backing file.

Also, one really should take i_mutex when altering an i_size.  Probably it
doesn't make much difference here, but that's the rule.

Please ensure that the loop driver is well tested with a device size which
is both smaller than and larger than the backing file, and that it's tested
for both do_lo_send_aops()-based and do_lo_send_write()-based backing
filesystems, thanks.


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

end of thread, other threads:[~2006-05-24 19:34 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-05-23  7:31 [PATCH] loop: online resize support Akinobu Mita
2006-05-24 19:37 ` Andrew Morton

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