lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Date:	Mon, 24 Nov 2008 11:08:02 +0900
From:	hooanon05@...oo.co.jp
To:	Karel Zak <kzak@...hat.com>
Cc:	Andrew Morton <akpm@...ux-foundation.org>, tomas@...x.org,
	linux-kernel@...r.kernel.org, akinobu.mita@...il.com,
	util-linux-ng@...r.kernel.org
Subject: Re: [PATCH] loop file resizable 


Karel Zak:
> On Fri, Nov 21, 2008 at 09:23:48PM +0900, hooanon05@...oo.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@...oo.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

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ