From a6c35f74ecef43920a9f479f9a40850757bd75a7 Mon Sep 17 00:00:00 2001 From: Kevin Fenzi Date: Sat, 16 May 2009 00:03:06 +0000 Subject: [PATCH 1/4] Initialize branch F-10 for zerofree --- branch | 1 + 1 file changed, 1 insertion(+) create mode 100644 branch diff --git a/branch b/branch new file mode 100644 index 0000000..dc32377 --- /dev/null +++ b/branch @@ -0,0 +1 @@ +F-10 From 7fc0143204c8c477bf2b360b7493d7afc8ec4b44 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Mon, 18 May 2009 08:14:57 +0000 Subject: [PATCH 2/4] Initial import. --- .cvsignore | 1 + import.log | 1 + index.html | 129 +++++++++++++++++++++++++++++++++ sources | 1 + sparsify.c | 193 ++++++++++++++++++++++++++++++++++++++++++++++++++ zerofree.spec | 78 ++++++++++++++++++++ 6 files changed, 403 insertions(+) create mode 100644 import.log create mode 100644 index.html create mode 100644 sparsify.c create mode 100644 zerofree.spec diff --git a/.cvsignore b/.cvsignore index e69de29..021b6dd 100644 --- a/.cvsignore +++ b/.cvsignore @@ -0,0 +1 @@ +zerofree-1.0.1.tgz diff --git a/import.log b/import.log new file mode 100644 index 0000000..339a0a2 --- /dev/null +++ b/import.log @@ -0,0 +1 @@ +zerofree-1_0_1-5_fc11:F-10:zerofree-1.0.1-5.fc11.src.rpm:1242634379 diff --git a/index.html b/index.html new file mode 100644 index 0000000..92e5b0d --- /dev/null +++ b/index.html @@ -0,0 +1,129 @@ + + +Keeping filesystem images sparse + + +

Keeping filesystem images sparse

+

+Filesystem images in local files can be used by many PC emulators and +virtual machines +(user-mode Linux, +QEMU and +Xen, to name but three). +Typically these filesystems are created as sparse files using +commands like: +

+

+   dd if=/dev/zero of=fs.image bs=1024 seek=2000000 count=0
+   /sbin/mke2fs fs.image
+
+where the enormous seek value causes dd to move +forward by 2GB before writing nothing at all. This results in the +creation of a sparse file which takes disk space only for blocks which are +actually used: +

+

+   $ ls -l fs.image 
+   -rw-rw-r--  1 rmy rmy 2048001024 Apr 18 19:10 fs.image
+   $ du -s fs.image 
+   31692   fs.image
+
+As the filesystem is used, more and more of the non-existent blocks are +filled with data and the size of the file on disk grows. Sometimes it would +be nice to be able to reclaim unused blocks from a filesystem image. However, +deleting files from the image doesn't return the space to the +underlying filesystem: even free blocks in the image still consume space. +Reclaiming the space can be achieved in two stages: + +

+One traditional way to zero unused blocks is to create a file that fills +all the free space: +

+

+   dd if=/dev/zero of=junk
+   sync
+   rm junk
+
+

+The disadvantage of dd in this context is that it destroys +any sparseness that exists: free blocks that were originally represented +as holes in the image file are replaced with actual blocks containing +zeroes. +

+As an alternative approach, and as practice in mucking about with ext2 +filesystems, I've written a utility which scans the free blocks in an +ext2 filesystem and fills any non-zero blocks with zeroes. +(The source, zerofree-1.0.1.tgz, is +available for download.) The zerofree utility is faster +than dd, especially when the filesystem is already partly sparse. +The filesystem to be processed should be unmounted or mounted read-only. +

+Better than either of these would be to have the guest kernel keep the free +blocks empty. My original inspiration was the + +ext2fs privacy (i.e. secure deletion) patch described in a Linux +kernel mailing list thread. I've also made use of a later patch for ext3 +entitled +Secure Deletion Functionality in ext3 +from the linux-fsdevel mailing list. (See also the authors' paper on +Secure Deletion File Systems.) +I've modified the patches to make them more suitable for the present purpose. +

+When a filesystem is mounted with the zerofree option (added +by these patches) all the blocks freed when a file is deleted are filled +with zeroes. +Remember, this extra work will hurt disk performance. +Note that the ext3 patch doesn't support data journalling +mode, so deleted metadata isn't zeroed. It also hasn't been tested +as thoroughly as the patch for ext2. +

+However, the above techniques are only half the story: the empty free +blocks still consume space in the underlying filesystem, so something +must to be done to reclaim that space. One approach would be to +implement a system call, like the legendary + +sys_punch, which could be used to write a utility to make any +suitable file sparse. +

+An existing alternative is to use the sparse file handling capabilities +of the GNU cp command to take a copy of the filesystem image with +cp --sparse=always (though this does require the original +and sparse files to exist at the same time, which may be inconvenient). +

+As an alternative alternative I've written a utility which can make +any specified files on an ext2 filesystem +sparse, sparsify.c. This doesn't require any +additional disk space to work its magic, but it does require that the +filesystem containing the filesystem image is unmounted, which is just a +different sort of inconvenience. +

+(The usual disclaimers apply: this worked for me +when I tested it but it might destroy your data. Only use it on +disposable filesystems, or have a full backup available. e2fsck +is your friend.) +

+As an example, suppose we have an unmounted filesystem +image, fs.image, in the directory /data, which is the +root of the /dev/hda2 filesystem. We can reclaim deleted +blocks and make it sparse like so: +

+

+   zerofree /data/fs.image
+   umount /data
+   sparsify /dev/hda2 /fs.image
+   mount /data
+
+

+


+
+Ron Yorston
+29th July 2008 +
+ + diff --git a/sources b/sources index e69de29..2c5121c 100644 --- a/sources +++ b/sources @@ -0,0 +1 @@ +a8c772fdd134448f25ab4e7e12004595 zerofree-1.0.1.tgz diff --git a/sparsify.c b/sparsify.c new file mode 100644 index 0000000..fbcd71f --- /dev/null +++ b/sparsify.c @@ -0,0 +1,193 @@ +/* + * sparsify - a tool to make files on an ext2 filesystem sparse + * + * Copyright (C) 2004 R M Yorston + * + * This file may be redistributed under the terms of the GNU General Public + * License. + */ +#include +#include +#include +#include + +#define USAGE "usage: %s [-n] [-v] filesystem filename ...\n" + +struct process_data { + struct ext2_inode *inode ; + unsigned char *buf; + int dryrun ; + int changed ; +} ; + +static int process(ext2_filsys fs, blk_t *blocknr, e2_blkcnt_t blockcnt, + blk_t ref_block, int ref_offset, void *priv) +{ + struct process_data *p ; + errcode_t ret ; + int i, group ; + + p = (struct process_data *)priv ; + + if ( blockcnt >= 0 ) { + ret = io_channel_read_blk(fs->io, *blocknr, 1, p->buf); + if ( ret ) { + return BLOCK_ABORT ; + } + + for ( i=0; i < fs->blocksize; ++i ) { + if ( p->buf[i] ) { + break ; + } + } + + if ( i == fs->blocksize && !p->dryrun ) { + ext2fs_unmark_block_bitmap(fs->block_map, *blocknr) ; + group = ext2fs_group_of_blk(fs, *blocknr); + fs->group_desc[group].bg_free_blocks_count++; + fs->super->s_free_blocks_count++ ; + /* the inode counts blocks of 512 bytes */ + p->inode->i_blocks -= fs->blocksize / 512 ; + *blocknr = 0 ; + /* direct blocks need to be zeroed in the inode */ + if ( blockcnt < EXT2_NDIR_BLOCKS ) { + p->inode->i_block[blockcnt] = 0 ; + } + p->changed = 1 ; + return BLOCK_CHANGED ; + } + } + + return 0 ; +} + +int main(int argc, char **argv) +{ + int verbose = 0 ; + int dryrun = 0 ; + errcode_t ret ; + int flags ; + int superblock = 0 ; + int open_flags = EXT2_FLAG_RW ; + int blocksize = 0 ; + ext2_filsys current_fs = NULL; + struct ext2_inode inode ; + ext2_ino_t root, cwd, inum ; + int i, c ; + struct process_data pdata ; + + while ( (c=getopt(argc, argv, "nv")) != -1 ) { + switch (c) { + case 'n' : + dryrun = 1 ; + break ; + case 'v' : + verbose = 1 ; + break ; + default : + fprintf(stderr, USAGE, argv[0]) ; + return 1 ; + } + } + + if ( argc < optind+2 ) { + fprintf(stderr, USAGE, argv[0]) ; + return 1 ; + } + + ret = ext2fs_check_if_mounted(argv[optind], &flags) ; + if ( ret ) { + fprintf(stderr, "%s: failed to determine filesystem mount state %s\n", + argv[0], argv[optind]) ; + return 1 ; + } + + if ( flags & EXT2_MF_MOUNTED ) { + fprintf(stderr, "%s: filesystem %s is mounted\n", + argv[0], argv[optind]) ; + return 1 ; + } + + ret = ext2fs_open(argv[optind], open_flags, superblock, blocksize, + unix_io_manager, ¤t_fs); + if ( ret ) { + fprintf(stderr, "%s: failed to open filesystem %s\n", + argv[0], argv[optind]) ; + return 1 ; + } + + pdata.buf = (unsigned char *)malloc(current_fs->blocksize) ; + if ( pdata.buf == NULL ) { + fprintf(stderr, "%s: out of memory (surely not?)\n", argv[0]) ; + return 1 ; + } + + ret = ext2fs_read_inode_bitmap(current_fs); + if ( ret ) { + fprintf(stderr, "%s: error while reading inode bitmap\n", argv[0]); + return 1 ; + } + + ret = ext2fs_read_block_bitmap(current_fs); + if ( ret ) { + fprintf(stderr, "%s: error while reading block bitmap\n", argv[0]); + return 1 ; + } + + root = cwd = EXT2_ROOT_INO ; + + for ( i=optind+1; i - 1.0.1-5 +- Include the index file as a source file. +- Improve the description, remove spelling mistakes and other typos. +- Use the upstream SRPM directly, unpacking source from it. +- Fix use of dist macro. +- Pass the RPM OPTFLAGS to C compiler (should also fix debuginfo pkg). +- Use 'cp -p' to preserve timestamps when copying index.html file. +- Fix the defattr line. +- License is GPL+ (any version of the GPL including 1). +- Use a simpler install command to install the binary. +- Fix the upstream URL to point to the real original project. +- Add the sparsify command. + +* Thu May 14 2009 Richard W.M. Jones - 1.0.1-1 +- Initial packaging for Fedora, based on R P Herrold's package. + +* Wed May 13 2009 R P Herrold - 1.0.1-1 +- initial packaging From fc39938ed1c098c9b332bbc56b430955f143731e Mon Sep 17 00:00:00 2001 From: Bill Nottingham Date: Thu, 26 Nov 2009 01:08:50 +0000 Subject: [PATCH 3/4] Fix typo that causes a failure to update the common directory. (releng #2781) --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a2abd04..5346315 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ NAME := zerofree SPECFILE = $(firstword $(wildcard *.spec)) define find-makefile-common -for d in common ../common ../../common ; do if [ -f $$d/Makefile.common ] ; then if [ -f $$d/CVS/Root -a -w $$/Makefile.common ] ; then cd $$d ; cvs -Q update ; fi ; echo "$$d/Makefile.common" ; break ; fi ; done +for d in common ../common ../../common ; do if [ -f $$d/Makefile.common ] ; then if [ -f $$d/CVS/Root -a -w $$d/Makefile.common ] ; then cd $$d ; cvs -Q update ; fi ; echo "$$d/Makefile.common" ; break ; fi ; done endef MAKEFILE_COMMON := $(shell $(find-makefile-common)) From 95c50ba416666a6219a68a9f26cb48280e3278d3 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Thu, 29 Jul 2010 16:28:52 +0000 Subject: [PATCH 4/4] dist-git conversion --- .cvsignore => .gitignore | 0 Makefile | 21 --------------------- branch | 1 - import.log | 1 - 4 files changed, 23 deletions(-) rename .cvsignore => .gitignore (100%) delete mode 100644 Makefile delete mode 100644 branch delete mode 100644 import.log diff --git a/.cvsignore b/.gitignore similarity index 100% rename from .cvsignore rename to .gitignore diff --git a/Makefile b/Makefile deleted file mode 100644 index 5346315..0000000 --- a/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# Makefile for source rpm: zerofree -# $Id$ -NAME := zerofree -SPECFILE = $(firstword $(wildcard *.spec)) - -define find-makefile-common -for d in common ../common ../../common ; do if [ -f $$d/Makefile.common ] ; then if [ -f $$d/CVS/Root -a -w $$d/Makefile.common ] ; then cd $$d ; cvs -Q update ; fi ; echo "$$d/Makefile.common" ; break ; fi ; done -endef - -MAKEFILE_COMMON := $(shell $(find-makefile-common)) - -ifeq ($(MAKEFILE_COMMON),) -# attept a checkout -define checkout-makefile-common -test -f CVS/Root && { cvs -Q -d $$(cat CVS/Root) checkout common && echo "common/Makefile.common" ; } || { echo "ERROR: I can't figure out how to checkout the 'common' module." ; exit -1 ; } >&2 -endef - -MAKEFILE_COMMON := $(shell $(checkout-makefile-common)) -endif - -include $(MAKEFILE_COMMON) diff --git a/branch b/branch deleted file mode 100644 index dc32377..0000000 --- a/branch +++ /dev/null @@ -1 +0,0 @@ -F-10 diff --git a/import.log b/import.log deleted file mode 100644 index 339a0a2..0000000 --- a/import.log +++ /dev/null @@ -1 +0,0 @@ -zerofree-1_0_1-5_fc11:F-10:zerofree-1.0.1-5.fc11.src.rpm:1242634379