Files
rockchip-kernel/include/linux
J. R. Okajima 53d6660836 loop: add ioctl to resize a loop device
Add the ability to 'resize' the loop device on the fly.

One practical application is a loop file with XFS filesystem, already
mounted: You can easily enlarge the file (append some bytes) and then call
ioctl(fd, LOOP_SET_CAPACITY, new); The loop driver will learn about the
new size and you can use xfs_growfs later on, which will allow you to use
full capacity of the loop file without the need to unmount.

Test app:

#include <linux/fs.h>
#include <linux/loop.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define _GNU_SOURCE
#include <getopt.h>

char *me;

void usage(FILE *f)
{
	fprintf(f, "%s [options] loop_dev [backend_file]\n"
		"-s, --set new_size_in_bytes\n"
		"\twhen backend_file is given, "
		"it will be expanded too while keeping the original contents\n",
		me);
}

struct option opts[] = {
	{
		.name		= "set",
		.has_arg	= 1,
		.flag		= NULL,
		.val		= 's'
	},
	{
		.name		= "help",
		.has_arg	= 0,
		.flag		= NULL,
		.val		= 'h'
	}
};

void err_size(char *name, __u64 old)
{
	fprintf(stderr, "size must be larger than current %s (%llu)\n",
		name, old);
}

int main(int argc, char *argv[])
{
	int fd, err, c, i, bfd;
	ssize_t ssz;
	size_t sz;
	__u64 old, new, append;
	char a[BUFSIZ];
	struct stat st;
	FILE *out;
	char *backend, *dev;

	err = EINVAL;
	out = stderr;
	me = argv[0];
	new = 0;
	while ((c = getopt_long(argc, argv, "s:h", opts, &i)) != -1) {
		switch (c) {
		case 's':
			errno = 0;
			new = strtoull(optarg, NULL, 0);
			if (errno) {
				err = errno;
				perror(argv[i]);
				goto out;
			}
			break;

		case 'h':
			err = 0;
			out = stdout;
			goto err;

		default:
			perror(argv[i]);
			goto err;
		}
	}

	if (optind < argc)
		dev = argv[optind++];
	else
		goto err;

	fd = open(dev, O_RDONLY);
	if (fd < 0) {
		err = errno;
		perror(dev);
		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;
		err_size(dev, old);
		goto out;
	}

	if (optind < argc) {
		backend = argv[optind++];
		bfd = open(backend, O_WRONLY|O_APPEND);
		if (bfd < 0) {
			err = errno;
			perror(backend);
			goto out;
		}
		err = fstat(bfd, &st);
		if (err) {
			err = errno;
			perror(backend);
			goto out;
		}
		if (new < st.st_size) {
			err = EINVAL;
			err_size(backend, st.st_size);
			goto out;
		}
		append = new - st.st_size;
		sz = sizeof(a);
		while (append > 0) {
			if (append < sz)
				sz = append;
			ssz = write(bfd, a, sz);
			if (ssz != sz) {
				err = errno;
				perror(backend);
				goto out;
			}
			append -= sz;
		}
		err = fsync(bfd);
		if (err) {
			err = errno;
			perror(backend);
			goto out;
		}
	}

	err = ioctl(fd, LOOP_SET_CAPACITY, new);
	if (err) {
		err = errno;
		perror("ioctl LOOP_SET_CAPACITY");
	}
	goto out;

 err:
	usage(out);
 out:
	return err;
}

Signed-off-by: J. R. Okajima <hooanon05@yahoo.co.jp>
Signed-off-by: Tomas Matejicek <tomas@slax.org>
Cc: <util-linux-ng@vger.kernel.org>
Cc: Karel Zak <kzak@redhat.com>
Cc: Jens Axboe <jens.axboe@oracle.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Akinobu Mita <akinobu.mita@gmail.com>
Cc: <linux-api@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2009-04-01 08:59:17 -07:00
..
2009-01-30 19:50:25 +05:30
2009-03-18 19:45:11 -07:00
2009-01-09 12:37:15 -08:00
2009-01-30 23:30:42 +05:30
2009-01-30 23:32:45 +05:30
2009-03-05 14:39:32 -05:00
2009-02-16 00:43:24 +01:00
2008-10-20 11:01:52 -07:00
2009-01-30 23:38:03 +05:30
2008-12-29 08:29:50 +01:00
2009-01-21 14:02:19 -08:00
2009-01-30 23:38:37 +05:30
2008-12-03 22:12:38 -08:00
2008-12-03 22:12:38 -08:00
2009-02-12 09:40:14 +11:00
2009-01-30 23:39:42 +05:30
2008-10-20 08:52:42 -07:00
2009-01-30 23:40:06 +05:30
2009-01-06 15:59:29 -08:00
2009-01-01 10:12:19 +10:30
2009-01-04 13:33:20 -08:00
2008-11-12 17:17:18 -08:00
2009-01-30 23:44:08 +05:30
2009-03-27 14:43:57 -04:00
2009-01-02 12:19:34 -08:00
2008-12-25 11:01:43 +11:00
2008-11-24 18:57:41 -05:00
2009-03-27 14:43:59 -04:00
2009-03-01 00:19:35 -08:00
2009-01-30 23:46:03 +05:30
2009-01-30 23:46:40 +05:30
2008-10-16 16:53:13 +02:00
2009-01-30 23:48:33 +05:30
2009-02-10 00:41:26 +01:00
2009-03-16 08:32:27 -06:00
2008-12-29 11:27:46 +02:00
2008-10-08 19:44:18 -04:00
2009-02-18 15:37:56 -08:00
2008-12-01 19:14:02 +01:00
2009-03-24 12:35:17 +01:00
2009-01-06 15:59:01 -08:00
2008-10-16 11:21:40 -07:00
2009-01-30 23:50:37 +05:30
2009-01-30 23:51:17 +05:30
2009-04-01 08:59:14 -07:00
2008-10-16 11:21:38 -07:00
2009-01-30 23:51:41 +05:30
2009-01-30 23:52:16 +05:30
2009-01-30 23:53:12 +05:30
2009-01-30 23:53:40 +05:30
2009-01-30 23:54:53 +05:30
2009-01-30 23:55:45 +05:30
2009-01-30 23:56:13 +05:30
2009-01-30 23:56:48 +05:30
2009-01-30 23:57:16 +05:30
2009-02-11 15:27:15 +11:00
2009-02-02 21:40:58 +05:30
2008-10-29 22:02:09 +01:00
2008-10-15 14:24:08 +02:00
2009-01-30 23:58:41 +05:30
2009-01-30 23:59:44 +05:30
2009-01-31 00:00:06 +05:30
2009-03-13 14:32:29 +01:00
2009-01-15 16:39:37 -08:00
2009-01-05 08:40:30 -08:00
2009-01-22 10:18:58 +01:00
2009-03-28 23:55:59 -07:00
2009-03-24 22:52:39 -04:00
2009-04-01 08:59:17 -07:00
2009-01-21 10:39:51 +01:00
2009-01-31 00:00:35 +05:30
2009-04-01 08:59:13 -07:00
2009-03-26 10:56:35 -07:00
2009-01-31 00:01:11 +05:30
2008-12-08 14:31:59 +01:00
2009-01-14 18:09:02 +01:00
2009-03-15 19:59:13 -07:00
2009-01-07 17:38:31 -05:00
2008-12-23 15:21:45 -05:00
2009-03-27 14:43:59 -04:00
2009-03-27 14:43:59 -04:00
2009-03-10 20:33:18 -04:00
2008-12-21 14:21:14 +11:00
2009-01-08 08:31:05 -08:00
2009-04-01 08:59:13 -07:00
2009-04-01 08:59:13 -07:00
2008-10-16 11:21:49 -07:00
2009-01-31 00:02:54 +05:30
2009-01-08 08:31:12 -08:00
2009-01-31 00:03:40 +05:30
2008-10-23 00:11:07 -04:00
2009-04-01 08:59:13 -07:00
2009-01-06 15:59:12 -08:00
2009-03-13 16:09:12 -07:00
2008-12-20 09:15:46 +01:00
2009-03-26 02:18:35 +01:00
2009-01-05 18:31:12 -08:00
2008-10-02 15:53:13 -07:00
2009-01-31 00:05:59 +05:30
2008-11-12 17:17:17 -08:00
2008-11-16 19:39:21 -08:00
2009-02-26 23:42:11 -08:00
2009-03-30 14:28:58 -07:00
2009-01-04 13:33:20 -08:00
2009-02-16 00:03:10 -08:00
2009-01-29 16:56:32 +09:00
2009-02-27 16:53:50 +09:00
2009-01-31 00:06:33 +05:30
2009-02-20 17:57:48 -08:00
2008-09-09 17:41:42 +02:00
2008-11-24 21:27:22 -08:00
2009-01-31 00:07:00 +05:30
2009-04-01 08:59:13 -07:00
2009-04-01 08:59:15 -07:00
2009-01-31 00:07:31 +05:30
2009-02-11 14:25:36 -08:00
2008-10-13 09:51:40 -07:00
2009-01-01 10:12:25 +10:30
2009-02-18 15:37:53 -08:00
2009-02-03 11:23:12 +11:00
2008-09-05 14:39:38 -07:00
2009-03-26 18:14:21 +01:00