From: "Amit K. Arora" Subject: [PATCH 0/6][TAKE7] fallocate system call Date: Fri, 13 Jul 2007 18:08:16 +0530 Message-ID: <20070713123816.GA18000@amitarora.in.ibm.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Cc: xfs@oss.sgi.com, michael.kerrisk@gmx.net, tytso@mit.edu, cmm@us.ibm.com, suparna@in.ibm.com, adilger@clusterfs.com, dgc@sgi.com To: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-ext4@vger.kernel.org Return-path: Received: from e31.co.us.ibm.com ([32.97.110.149]:60415 "EHLO e31.co.us.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753710AbXGMMiJ (ORCPT ); Fri, 13 Jul 2007 08:38:09 -0400 Content-Disposition: inline Sender: linux-ext4-owner@vger.kernel.org List-Id: linux-ext4.vger.kernel.org This is the latest fallocate patchset and is based on 2.6.22. * Following are the changes from TAKE6: 1) We now just have two modes (and no deallocation modes). 2) Updated the man page 3) Added a new patch submitted by David P. Quigley (Patch 3/6). 4) Used EXT_INIT_MAX_LEN instead of 0x8000 in Patch 6/6. 5) Included below in the end is a small testcase to test fallocate. * Following are the changes from TAKE5 to TAKE6: 1) Rebased to 2.6.22 2) Added compat wrapper for x86_64 3) Dropped s390 and ia64 patches, since the platform maintaners can add the support for fallocate once it is in mainline. 4) Added a change suggested by Andreas for better extent-to-group alignment in ext4 (Patch 6/6). Please refer following post: http://www.mail-archive.com/linux-ext4@vger.kernel.org/msg02445.html 5) Renamed mode flags and values from "FA_" to "FALLOC_" 6) Added manpage (updated version of the one initially submitted by David Chinner). Todos: ----- 1> Implementation on other architectures (other than i386, x86_64, and ppc64). s390(x) and ia64 patches are ready and will be pushed by platform maintaners when the fallocate is in mainline. 2> A generic file system operation to handle fallocate (generic_fallocate), for filesystems that do _not_ have the fallocate inode operation implemented. 3> Changes to glibc, a) to support fallocate() system call b) to make posix_fallocate() and posix_fallocate64() call fallocate() 4> Patch to e2fsprogs to recognize and display uninitialized extents. Following patches follow: Patch 1/6 : manpage for fallocate Patch 2/6 : fallocate() implementation in i386, x86_64 and powerpc Patch 3/6 : revalidate write permissions for fallocate Patch 4/6 : ext4: fallocate support in ext4 Patch 5/6 : ext4: write support for preallocated blocks Patch 6/6 : ext4: change for better extent-to-group alignment Note: Attached below is a small testcase to test fallocate. The __NR_fallocate will need to be changed depending on the system call number in the kernel (it may get changed due to merge) and also depending on the architecture. -- Regards, Amit Arora #include #include #include #include #include #include #include #define VERBOSE 0 #define __NR_fallocate 324 #define FALLOC_FL_KEEP_SIZE 0x01 #define FALLOC_ALLOCATE 0x0 #define FALLOC_RESV_SPACE FALLOC_FL_KEEP_SIZE int do_fallocate(int fd, int mode, loff_t offset, loff_t len) { int ret; if (VERBOSE) printf("Trying to preallocate blocks (offset=%llu, len=%llu)\n", offset, len); ret = syscall(__NR_fallocate, fd, mode, offset, len); if (ret <0) { printf("SYSCALL: received error %d, ret=%d\n", errno, ret); close(fd); return(1); } if (VERBOSE) printf("fallocate system call succedded ! ret=%d\n", ret); return ret; } int test_fallocate(int fd, int mode, loff_t offset, loff_t len) { int ret, blocks; struct stat statbuf1, statbuf2; fstat(fd, &statbuf1); ret = do_fallocate(fd, mode, offset, len); fstat(fd, &statbuf2); /* check file size after preallocation */ if (mode == FALLOC_ALLOCATE) { if (!ret && statbuf1.st_size < (offset + len) && statbuf2.st_size != (offset + len)) { printf("Error: fallocate succeeded, but the file size did not " "change, where it should have!\n"); ret = 1; } } else if (statbuf1.st_size != statbuf2.st_size) { printf("Error : File size changed, when it should not have!\n"); ret = 1; } blocks = ((statbuf2.st_blocks - statbuf1.st_blocks) * 512)/ statbuf2.st_blksize; /* Print report */ printf("# FALLOCATE TEST REPORT #\n"); printf("\tNew blocks preallocated = %d.\n", blocks); printf("\tNumber of bytes preallocated = %d\n", blocks * statbuf2.st_blksize); printf("\tOld file size = %d, New file size %d.\n", statbuf1.st_size, statbuf2.st_size); printf("\tOld num blocks = %d, New num blocks %d.\n", (statbuf1.st_blocks * 512)/1024, (statbuf2.st_blocks * 512)/1024); return ret; } int do_write(int fd, loff_t offset, loff_t len) { int ret; char *buf; buf = (char *)malloc(len); if (!buf) { printf("error: malloc failed.\n"); return(-1); } if (VERBOSE) printf("Trying to write to file (offset=%llu, len=%llu)\n", offset, len); ret = lseek(fd, offset, SEEK_SET); if (ret != offset) { printf("lseek() failed error=%d, ret=%d\n", errno, ret); close(fd); return(-1); } ret = write(fd, buf, len); if (ret != len) { printf("write() failed error=%d, ret=%d\n", errno, ret); close(fd); return(-1); } if (VERBOSE) printf("Write succedded ! Written %llu bytes ret=%d\n", len, ret); return ret; } int test_write(int fd, loff_t offset, loff_t len) { int ret; ret = do_write(fd, offset, len); printf("# WRITE TEST REPORT #\n"); if (ret > 0) printf("\t written %d bytes.\n", ret); else printf("\t write operation failed!\n"); if (ret > 0) return 0; else return 1; } void usage(char **argv) { printf("\n%s