All of lore.kernel.org
 help / color / mirror / Atom feed
From: hooanon05@yahoo.co.jp
To: Karel Zak <kzak@redhat.com>
Cc: Andrew Morton <akpm@linux-foundation.org>,
	tomas@slax.org, linux-kernel@vger.kernel.org,
	akinobu.mita@gmail.com, util-linux-ng@vger.kernel.org
Subject: Re: [PATCH] loop file resizable
Date: Mon, 24 Nov 2008 11:08:02 +0900	[thread overview]
Message-ID: <22572.1227492482@jrobl> (raw)
In-Reply-To: <20081121124432.GL2961@nb.net.home>


Karel Zak:
> On Fri, Nov 21, 2008 at 09:23:48PM +0900, hooanon05@yahoo.co.jp wrote:
	:::
> > If you tell me the URL of the base version of losetup, I will make a
> > patch.
> 
>  git://git.kernel.org/pub/scm/utils/util-linux-ng/util-linux-ng.git

Thanx.


>  Note, that I'll commit the patch when the kernel side will be in
>  Linus's tree.

Sure.
Here is the patch.

J. R. Okajima

----------------------------------------------------------------------

Subject: [PATCH 1/1] grow the size of loopback device and its backend file

introduce a new option, "-g | --grow <new_size> <loopdev> [file]" which
requres the kernel patch titled
"Subject: + loop-add-ioctl-to-resize-a-loop-device.patch added to -mm tree"
on 21 Nov 2008.

Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp>
---
 mount/lomount.c |  154 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
 mount/loop.h    |    2 +
 2 files changed, 152 insertions(+), 4 deletions(-)

diff --git a/mount/lomount.c b/mount/lomount.c
index 5675eac..c705b43 100644
--- a/mount/lomount.c
+++ b/mount/lomount.c
@@ -24,6 +24,7 @@
 #include "xmalloc.h"
 #include "realpath.h"
 #include "pathnames.h"
+#include "blkdev.h"
 
 #define SIZE(a) (sizeof(a)/sizeof(a[0]))
 
@@ -827,6 +828,136 @@ del_loop (const char *device) {
 	return 0;
 }
 
+void grow_err(const char *name, unsigned long long old, unsigned long long new)
+{
+	fprintf(stderr, "size (%llu) must be larger than current %s (%llu)\n",
+		new, name, old);
+}
+
+int grow_file(const char *file, unsigned long long new)
+{
+	int err, fd;
+	unsigned long long append;
+	size_t sz;
+	ssize_t ssz;
+	const size_t one_g = 1 << 30;
+	struct stat st;
+	char *p;
+
+	err = -1;
+	fd = open(file, O_WRONLY | O_APPEND);
+	if (fd < 0)
+		goto out_p;
+
+	err = fstat(fd, &st);
+	if (err)
+		goto out_p;
+
+	err = -1;
+	if (new < st.st_size) {
+		grow_err(file, st.st_size, new);
+		goto out;
+	}
+
+	append = new - st.st_size;
+	sz = append;
+	if (sz > one_g)
+		sz = one_g;
+	while (1) {
+		p = calloc(sz, 1);
+		if (p)
+			break;
+		sz >>= 1;
+		if (!sz) {
+			errno = ENOMEM;
+			goto out_p;
+		}
+	}
+
+	/*
+	 * instread of ftrundate(2),
+	 * allocate disk blocks to support ENOSPC
+	 * on the loopback mounted filesystem
+	 */
+	err = 0;
+	while (append > 0) {
+		if (append < sz)
+			sz = append;
+		ssz = write(fd, p, sz);
+		if (ssz == -1) {
+			if (errno == EAGAIN || errno == EINTR)
+				continue;
+			err = errno;
+			break;
+		}
+		append -= ssz;
+	}
+	free(p);
+	if (err) {
+		errno = err;
+		goto out_p;
+	}
+
+	err = fsync(fd);
+	if (err)
+		goto out_p;
+	err = close(fd);
+	if (!err)
+		goto out; /* success */
+
+ out_p:
+	perror(file);
+ out:
+	return err;
+}
+
+int grow_capacity(unsigned long long new, const char *device,
+		  const char *file)
+{
+	int err, fd;
+	unsigned long long old;
+
+	fd = open(device, O_RDONLY);
+	if (fd < 0) {
+		err = errno;
+		perror(device);
+		goto out;
+	}
+
+	err = ioctl(fd, BLKGETSIZE64, &old);
+	if (err) {
+		err = errno;
+		perror("ioctl BLKGETSIZE64");
+		goto out;
+	}
+
+	if (!new) {
+		printf("%llu\n", old);
+		goto out;
+	}
+
+	if (new < old) {
+		err = EINVAL;
+		grow_err(device, old, new);
+		goto out;
+	}
+
+	if (file) {
+		err = grow_file(file, new);
+		if (err)
+			goto out;
+	}
+
+	err = ioctl(fd, LOOP_SET_CAPACITY, new);
+	if (err) {
+		err = errno;
+		perror("ioctl LOOP_SET_CAPACITY");
+	}
+
+ out:
+	return err;
+}
+
 #else /* no LOOP_SET_FD defined */
 static void
 mutter(void) {
@@ -872,6 +1003,7 @@ usage(void) {
   " %1$s -d | --detach <loopdev>                 delete\n"
   " %1$s -f | --find                             find unused\n"
   " %1$s -j | --associated <file> [-o <num>]     list all associated with <file>\n"
+  " %1$s -g | --grow <new_size> <loopdev> [file] grow capacity\n"
   " %1$s [ options ] {-f|--find|loopdev} <file>  setup\n"),
 		progname);
 
@@ -889,13 +1021,14 @@ usage(void) {
 
 int
 main(int argc, char **argv) {
-	char *p, *offset, *sizelimit, *encryption, *passfd, *device, *file, *assoc;
+	char *p, *offset, *sizelimit, *encryption, *passfd, *device, *file,
+		*assoc, *grow;
 	int delete, find, c, all;
 	int res = 0;
 	int showdev = 0;
 	int ro = 0;
 	int pfd = -1;
-	unsigned long long off, slimit;
+	unsigned long long off, slimit, new_size;
 	struct option longopts[] = {
 		{ "all", 0, 0, 'a' },
 		{ "detach", 0, 0, 'd' },
@@ -903,6 +1036,7 @@ main(int argc, char **argv) {
 		{ "find", 0, 0, 'f' },
 		{ "help", 0, 0, 'h' },
 		{ "associated", 1, 0, 'j' },
+		{ "grow", 1, 0, 'g' },
 		{ "offset", 1, 0, 'o' },
 		{ "sizelimit", 1, 0, 128 },
 		{ "pass-fd", 1, 0, 'p' },
@@ -919,13 +1053,13 @@ main(int argc, char **argv) {
 	delete = find = all = 0;
 	off = 0;
         slimit = 0;
-	assoc = offset = sizelimit = encryption = passfd = NULL;
+	assoc = offset = sizelimit = encryption = passfd = grow = NULL;
 
 	progname = argv[0];
 	if ((p = strrchr(progname, '/')) != NULL)
 		progname = p+1;
 
-	while ((c = getopt_long(argc, argv, "ade:E:fhj:o:p:rsv",
+	while ((c = getopt_long(argc, argv, "ade:E:fg:hj:o:p:rsv",
 				longopts, NULL)) != -1) {
 		switch (c) {
 		case 'a':
@@ -944,6 +1078,9 @@ main(int argc, char **argv) {
 		case 'f':
 			find = 1;
 			break;
+		case 'g':
+			grow = optarg;
+			break;
 		case 'j':
 			assoc = optarg;
 			break;
@@ -984,6 +1121,10 @@ main(int argc, char **argv) {
 	} else if (assoc) {
 		if (encryption || showdev || passfd || ro)
 			usage();
+	} else if (grow) {
+		if (all || assoc || find
+		    || (argc != 4 && argc != 5))
+			usage();
 	} else {
 		if (argc < optind+1 || argc > optind+2)
 			usage();
@@ -995,6 +1136,9 @@ main(int argc, char **argv) {
 	if (sizelimit && sscanf(sizelimit, "%llu", &slimit) != 1)
 		usage();
 
+	if (grow && sscanf(grow, "%llu", &new_size) != 1)
+		usage();
+
 	if (all)
 		return show_used_loop_devices();
 	else if (assoc)
@@ -1020,6 +1164,8 @@ main(int argc, char **argv) {
 
 	if (delete)
 		res = del_loop(device);
+	else if (grow)
+		res = grow_capacity(new_size, device, file);
 	else if (file == NULL)
 		res = show_loop(device);
 	else {
diff --git a/mount/loop.h b/mount/loop.h
index 6068852..c6d244e 100644
--- a/mount/loop.h
+++ b/mount/loop.h
@@ -22,6 +22,8 @@
 #define LOOP_GET_STATUS		0x4C03
 #define LOOP_SET_STATUS64	0x4C04
 #define LOOP_GET_STATUS64	0x4C05
+/* #define LOOP_CHANGE_FD		0x4C06 */
+#define LOOP_SET_CAPACITY	0x4C07
 
 /* Flags for loop_into{64,}->lo_flags */
 enum {
-- 
1.5.5.4.dirty


      reply	other threads:[~2008-11-24  2:08 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-11-17  7:44 [PATCH] loop file resizable Tomas M
2008-11-19  0:42 ` Andrew Morton
2008-11-19  2:07   ` Akinobu Mita
2008-11-19  3:51   ` hooanon05
2008-11-19 18:34     ` Tomas M
2008-11-20 21:26     ` Andrew Morton
2008-11-21  2:37       ` hooanon05
2008-11-21  3:19         ` hooanon05
2008-11-21  4:31       ` [PATCH v2] " hooanon05
2008-11-21 10:12       ` [PATCH] " Karel Zak
2008-11-21 12:23         ` hooanon05
2008-11-21 12:44           ` Karel Zak
2008-11-24  2:08             ` hooanon05 [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=22572.1227492482@jrobl \
    --to=hooanon05@yahoo.co.jp \
    --cc=akinobu.mita@gmail.com \
    --cc=akpm@linux-foundation.org \
    --cc=kzak@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=tomas@slax.org \
    --cc=util-linux-ng@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.