Blame misc/mk_hugefiles.c

Packit a62e42
/*
Packit a62e42
 * mk_hugefiles.c -- create huge files
Packit a62e42
 */
Packit a62e42
Packit a62e42
#define _XOPEN_SOURCE 600 /* for inclusion of PATH_MAX in Solaris */
Packit a62e42
#define _BSD_SOURCE	  /* for makedev() and major() */
Packit a62e42
#define _DEFAULT_SOURCE	  /* since glibc 2.20 _BSD_SOURCE is deprecated */
Packit a62e42
Packit a62e42
#include "config.h"
Packit a62e42
#include <stdio.h>
Packit a62e42
#include <stdarg.h>
Packit a62e42
#include <string.h>
Packit a62e42
#include <strings.h>
Packit a62e42
#include <fcntl.h>
Packit a62e42
#include <ctype.h>
Packit a62e42
#include <time.h>
Packit a62e42
#ifdef __linux__
Packit a62e42
#include <sys/utsname.h>
Packit a62e42
#endif
Packit a62e42
#ifdef HAVE_GETOPT_H
Packit a62e42
#include <getopt.h>
Packit a62e42
#else
Packit a62e42
extern char *optarg;
Packit a62e42
extern int optind;
Packit a62e42
#endif
Packit a62e42
#ifdef HAVE_UNISTD_H
Packit a62e42
#include <unistd.h>
Packit a62e42
#endif
Packit a62e42
#ifdef HAVE_STDLIB_H
Packit a62e42
#include <stdlib.h>
Packit a62e42
#endif
Packit a62e42
#ifdef HAVE_ERRNO_H
Packit a62e42
#include <errno.h>
Packit a62e42
#endif
Packit a62e42
#ifdef HAVE_SYS_IOCTL_H
Packit a62e42
#include <sys/ioctl.h>
Packit a62e42
#endif
Packit a62e42
#include <sys/types.h>
Packit a62e42
#include <sys/stat.h>
Packit a62e42
#ifdef HAVE_SYS_SYSMACROS_H
Packit a62e42
#include <sys/sysmacros.h>
Packit a62e42
#endif
Packit a62e42
#include <libgen.h>
Packit a62e42
#include <limits.h>
Packit a62e42
#include <blkid/blkid.h>
Packit a62e42
Packit a62e42
#include "ext2fs/ext2_fs.h"
Packit a62e42
#include "ext2fs/ext2fsP.h"
Packit a62e42
#include "et/com_err.h"
Packit a62e42
#include "uuid/uuid.h"
Packit a62e42
#include "e2p/e2p.h"
Packit a62e42
#include "ext2fs/ext2fs.h"
Packit a62e42
#include "util.h"
Packit a62e42
#include "support/profile.h"
Packit a62e42
#include "support/prof_err.h"
Packit a62e42
#include "support/nls-enable.h"
Packit a62e42
#include "mke2fs.h"
Packit a62e42
Packit a62e42
static int uid;
Packit a62e42
static int gid;
Packit a62e42
static blk64_t num_blocks;
Packit a62e42
static blk64_t num_slack;
Packit a62e42
static unsigned long num_files;
Packit a62e42
static blk64_t goal;
Packit a62e42
static char *fn_prefix;
Packit a62e42
static int idx_digits;
Packit a62e42
static char *fn_buf;
Packit a62e42
static char *fn_numbuf;
Packit a62e42
int zero_hugefile = 1;
Packit a62e42
Packit a62e42
#define SYSFS_PATH_LEN 300
Packit a62e42
typedef char sysfs_path_t[SYSFS_PATH_LEN];
Packit a62e42
Packit a62e42
#ifndef HAVE_SNPRINTF
Packit a62e42
/*
Packit a62e42
 * We are very careful to avoid needing to worry about buffer
Packit a62e42
 * overflows, so we don't really need to use snprintf() except as an
Packit a62e42
 * additional safety check.  So if snprintf() is not present, it's
Packit a62e42
 * safe to fall back to vsprintf().  This provides portability since
Packit a62e42
 * vsprintf() is guaranteed by C89, while snprintf() is only
Packit a62e42
 * guaranteed by C99 --- which for example, Microsoft Visual Studio
Packit a62e42
 * has *still* not bothered to implement.  :-/  (Not that I expect
Packit a62e42
 * mke2fs to be ported to MS Visual Studio any time soon, but
Packit a62e42
 * libext2fs *does* get built on Microsoft platforms, and we might
Packit a62e42
 * want to move this into libext2fs some day.)
Packit a62e42
 */
Packit a62e42
static int my_snprintf(char *str, size_t size, const char *format, ...)
Packit a62e42
{
Packit a62e42
	va_list	ap;
Packit a62e42
	int ret;
Packit a62e42
Packit a62e42
	va_start(ap, format);
Packit a62e42
	ret = vsprintf(str, format, ap);
Packit a62e42
	va_end(ap);
Packit a62e42
	return ret;
Packit a62e42
}
Packit a62e42
Packit a62e42
#define snprintf my_snprintf
Packit a62e42
#endif
Packit a62e42
Packit a62e42
/*
Packit a62e42
 * Fall back to Linux's definitions of makedev and major are needed.
Packit a62e42
 * The search_sysfs_block() function is highly unlikely to work on
Packit a62e42
 * non-Linux systems anyway.
Packit a62e42
 */
Packit a62e42
#ifndef makedev
Packit a62e42
#define makedev(maj, min) (((maj) << 8) + (min))
Packit a62e42
#endif
Packit a62e42
Packit a62e42
static char *search_sysfs_block(dev_t devno, sysfs_path_t ret_path)
Packit a62e42
{
Packit a62e42
	struct dirent	*de, *p_de;
Packit a62e42
	DIR		*dir = NULL, *p_dir = NULL;
Packit a62e42
	FILE		*f;
Packit a62e42
	sysfs_path_t	path, p_path;
Packit a62e42
	unsigned int	major, minor;
Packit a62e42
	char		*ret = ret_path;
Packit a62e42
Packit a62e42
	ret_path[0] = 0;
Packit a62e42
	if ((dir = opendir("/sys/block")) == NULL)
Packit a62e42
		return NULL;
Packit a62e42
	while ((de = readdir(dir)) != NULL) {
Packit a62e42
		if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..") ||
Packit a62e42
		    strlen(de->d_name) > sizeof(path)-32)
Packit a62e42
			continue;
Packit a62e42
		snprintf(path, SYSFS_PATH_LEN,
Packit a62e42
			 "/sys/block/%s/dev", de->d_name);
Packit a62e42
		f = fopen(path, "r");
Packit a62e42
		if (f &&
Packit a62e42
		    (fscanf(f, "%u:%u", &major, &minor) == 2)) {
Packit a62e42
			fclose(f); f = NULL;
Packit a62e42
			if (makedev(major, minor) == devno) {
Packit a62e42
				snprintf(ret_path, SYSFS_PATH_LEN,
Packit a62e42
					 "/sys/block/%s", de->d_name);
Packit a62e42
				goto success;
Packit a62e42
			}
Packit a62e42
#ifdef major
Packit a62e42
			if (major(devno) != major)
Packit a62e42
				continue;
Packit a62e42
#endif
Packit a62e42
		}
Packit a62e42
		if (f)
Packit a62e42
			fclose(f);
Packit a62e42
Packit a62e42
		snprintf(path, SYSFS_PATH_LEN, "/sys/block/%s", de->d_name);
Packit a62e42
Packit a62e42
		if (p_dir)
Packit a62e42
			closedir(p_dir);
Packit a62e42
		if ((p_dir = opendir(path)) == NULL)
Packit a62e42
			continue;
Packit a62e42
		while ((p_de = readdir(p_dir)) != NULL) {
Packit a62e42
			if (!strcmp(p_de->d_name, ".") ||
Packit a62e42
			    !strcmp(p_de->d_name, "..") ||
Packit a62e42
			    (strlen(p_de->d_name) >
Packit a62e42
			     SYSFS_PATH_LEN - strlen(path) - 32))
Packit a62e42
				continue;
Packit a62e42
			snprintf(p_path, SYSFS_PATH_LEN, "%s/%s/dev",
Packit a62e42
				 path, p_de->d_name);
Packit a62e42
Packit a62e42
			f = fopen(p_path, "r");
Packit a62e42
			if (f &&
Packit a62e42
			    (fscanf(f, "%u:%u", &major, &minor) == 2) &&
Packit a62e42
			    (((major << 8) + minor) == devno)) {
Packit a62e42
				fclose(f);
Packit a62e42
				snprintf(ret_path, SYSFS_PATH_LEN, "%s/%s",
Packit a62e42
					 path, p_de->d_name);
Packit a62e42
				goto success;
Packit a62e42
			}
Packit a62e42
			if (f)
Packit a62e42
				fclose(f);
Packit a62e42
		}
Packit a62e42
	}
Packit a62e42
	ret = NULL;
Packit a62e42
success:
Packit a62e42
	if (dir)
Packit a62e42
		closedir(dir);
Packit a62e42
	if (p_dir)
Packit a62e42
		closedir(p_dir);
Packit a62e42
	return ret;
Packit a62e42
}
Packit a62e42
Packit a62e42
static blk64_t get_partition_start(const char *device_name)
Packit a62e42
{
Packit a62e42
	unsigned long long start;
Packit a62e42
	sysfs_path_t	path;
Packit a62e42
	struct stat	st;
Packit a62e42
	FILE		*f;
Packit a62e42
	char		*cp;
Packit a62e42
	int		n;
Packit a62e42
Packit a62e42
	if ((stat(device_name, &st) < 0) || !S_ISBLK(st.st_mode))
Packit a62e42
		return 0;
Packit a62e42
Packit a62e42
	cp = search_sysfs_block(st.st_rdev, path);
Packit a62e42
	if (!cp)
Packit a62e42
		return 0;
Packit a62e42
	if (strlen(path) > SYSFS_PATH_LEN - sizeof("/start"))
Packit a62e42
		return 0;
Packit a62e42
	strcat(path, "/start");
Packit a62e42
	f = fopen(path, "r");
Packit a62e42
	if (!f)
Packit a62e42
		return 0;
Packit a62e42
	n = fscanf(f, "%llu", &start;;
Packit a62e42
	fclose(f);
Packit a62e42
	return (n == 1) ? start : 0;
Packit a62e42
}
Packit a62e42
Packit a62e42
static errcode_t create_directory(ext2_filsys fs, char *dir,
Packit a62e42
				  ext2_ino_t *ret_ino)
Packit a62e42
Packit a62e42
{
Packit a62e42
	struct ext2_inode	inode;
Packit a62e42
	ext2_ino_t		ino = EXT2_ROOT_INO;
Packit a62e42
	ext2_ino_t		newdir;
Packit a62e42
	errcode_t		retval = 0;
Packit a62e42
	char			*fn, *cp, *next;
Packit a62e42
Packit a62e42
	fn = malloc(strlen(dir) + 1);
Packit a62e42
	if (fn == NULL)
Packit a62e42
		return ENOMEM;
Packit a62e42
Packit a62e42
	strcpy(fn, dir);
Packit a62e42
	cp = fn;
Packit a62e42
	while(1) {
Packit a62e42
		next = strchr(cp, '/');
Packit a62e42
		if (next)
Packit a62e42
			*next++ = 0;
Packit a62e42
		if (*cp) {
Packit a62e42
			retval = ext2fs_new_inode(fs, ino, LINUX_S_IFDIR,
Packit a62e42
						  NULL, &newdir);
Packit a62e42
			if (retval)
Packit a62e42
				goto errout;
Packit a62e42
Packit a62e42
			retval = ext2fs_mkdir(fs, ino, newdir, cp);
Packit a62e42
			if (retval)
Packit a62e42
				goto errout;
Packit a62e42
Packit a62e42
			ino = newdir;
Packit a62e42
			retval = ext2fs_read_inode(fs, ino, &inode;;
Packit a62e42
			if (retval)
Packit a62e42
				goto errout;
Packit a62e42
Packit a62e42
			inode.i_uid = uid & 0xFFFF;
Packit a62e42
			ext2fs_set_i_uid_high(inode, (uid >> 16) & 0xffff);
Packit a62e42
			inode.i_gid = gid & 0xFFFF;
Packit a62e42
			ext2fs_set_i_gid_high(inode, (gid >> 16) & 0xffff);
Packit a62e42
			retval = ext2fs_write_inode(fs, ino, &inode;;
Packit a62e42
			if (retval)
Packit a62e42
				goto errout;
Packit a62e42
		}
Packit a62e42
		if (next == NULL || *next == '\0')
Packit a62e42
			break;
Packit a62e42
		cp = next;
Packit a62e42
	}
Packit a62e42
errout:
Packit a62e42
	free(fn);
Packit a62e42
	if (retval == 0)
Packit a62e42
		*ret_ino = ino;
Packit a62e42
	return retval;
Packit a62e42
}
Packit a62e42
Packit a62e42
static errcode_t mk_hugefile(ext2_filsys fs, blk64_t num,
Packit a62e42
			     ext2_ino_t dir, unsigned long idx, ext2_ino_t *ino)
Packit a62e42
Packit a62e42
{
Packit a62e42
	errcode_t		retval;
Packit a62e42
	blk64_t			lblk, bend = 0;
Packit a62e42
	__u64			size;
Packit a62e42
	blk64_t			left;
Packit a62e42
	blk64_t			count = 0;
Packit a62e42
	struct ext2_inode	inode;
Packit a62e42
	ext2_extent_handle_t	handle;
Packit a62e42
Packit a62e42
	retval = ext2fs_new_inode(fs, 0, LINUX_S_IFREG, NULL, ino);
Packit a62e42
	if (retval)
Packit a62e42
		return retval;
Packit a62e42
Packit a62e42
	memset(&inode, 0, sizeof(struct ext2_inode));
Packit a62e42
	inode.i_mode = LINUX_S_IFREG | (0666 & ~fs->umask);
Packit a62e42
	inode.i_links_count = 1;
Packit a62e42
	inode.i_uid = uid & 0xFFFF;
Packit a62e42
	ext2fs_set_i_uid_high(inode, (uid >> 16) & 0xffff);
Packit a62e42
	inode.i_gid = gid & 0xFFFF;
Packit a62e42
	ext2fs_set_i_gid_high(inode, (gid >> 16) & 0xffff);
Packit a62e42
Packit a62e42
	retval = ext2fs_write_new_inode(fs, *ino, &inode;;
Packit a62e42
	if (retval)
Packit a62e42
		return retval;
Packit a62e42
Packit a62e42
	ext2fs_inode_alloc_stats2(fs, *ino, +1, 0);
Packit a62e42
Packit a62e42
	retval = ext2fs_extent_open2(fs, *ino, &inode, &handle);
Packit a62e42
	if (retval)
Packit a62e42
		return retval;
Packit a62e42
Packit a62e42
	/*
Packit a62e42
	 * We don't use ext2fs_fallocate() here because hugefiles are
Packit a62e42
	 * designed to be physically contiguous (if the block group
Packit a62e42
	 * descriptors are configured to be in a single block at the
Packit a62e42
	 * beginning of the file system, by using the
Packit a62e42
	 * packed_meta_blocks layout), with the extent tree blocks
Packit a62e42
	 * allocated near the beginning of the file system.
Packit a62e42
	 */
Packit a62e42
	lblk = 0;
Packit a62e42
	left = num ? num : 1;
Packit a62e42
	while (left) {
Packit a62e42
		blk64_t pblk, end;
Packit a62e42
		blk64_t n = left;
Packit a62e42
Packit a62e42
		retval =  ext2fs_find_first_zero_block_bitmap2(fs->block_map,
Packit a62e42
			goal, ext2fs_blocks_count(fs->super) - 1, &end;;
Packit a62e42
		if (retval)
Packit a62e42
			goto errout;
Packit a62e42
		goal = end;
Packit a62e42
Packit a62e42
		retval =  ext2fs_find_first_set_block_bitmap2(fs->block_map, goal,
Packit a62e42
			       ext2fs_blocks_count(fs->super) - 1, &bend);
Packit a62e42
		if (retval == ENOENT) {
Packit a62e42
			bend = ext2fs_blocks_count(fs->super);
Packit a62e42
			if (num == 0)
Packit a62e42
				left = 0;
Packit a62e42
		}
Packit a62e42
		if (!num || bend - goal < left)
Packit a62e42
			n = bend - goal;
Packit a62e42
		pblk = goal;
Packit a62e42
		if (num)
Packit a62e42
			left -= n;
Packit a62e42
		goal += n;
Packit a62e42
		count += n;
Packit a62e42
		ext2fs_block_alloc_stats_range(fs, pblk, n, +1);
Packit a62e42
Packit a62e42
		if (zero_hugefile) {
Packit a62e42
			blk64_t ret_blk;
Packit a62e42
			retval = ext2fs_zero_blocks2(fs, pblk, n,
Packit a62e42
						     &ret_blk, NULL);
Packit a62e42
Packit a62e42
			if (retval)
Packit a62e42
				com_err(program_name, retval,
Packit a62e42
					_("while zeroing block %llu "
Packit a62e42
					  "for hugefile"), ret_blk);
Packit a62e42
		}
Packit a62e42
Packit a62e42
		while (n) {
Packit a62e42
			blk64_t l = n;
Packit a62e42
			struct ext2fs_extent newextent;
Packit a62e42
Packit a62e42
			if (l > EXT_INIT_MAX_LEN)
Packit a62e42
				l = EXT_INIT_MAX_LEN;
Packit a62e42
Packit a62e42
			newextent.e_len = l;
Packit a62e42
			newextent.e_pblk = pblk;
Packit a62e42
			newextent.e_lblk = lblk;
Packit a62e42
			newextent.e_flags = 0;
Packit a62e42
Packit a62e42
			retval = ext2fs_extent_insert(handle,
Packit a62e42
					EXT2_EXTENT_INSERT_AFTER, &newextent);
Packit a62e42
			if (retval)
Packit a62e42
				return retval;
Packit a62e42
			pblk += l;
Packit a62e42
			lblk += l;
Packit a62e42
			n -= l;
Packit a62e42
		}
Packit a62e42
	}
Packit a62e42
Packit a62e42
	retval = ext2fs_read_inode(fs, *ino, &inode;;
Packit a62e42
	if (retval)
Packit a62e42
		goto errout;
Packit a62e42
Packit a62e42
	retval = ext2fs_iblk_add_blocks(fs, &inode,
Packit a62e42
					count / EXT2FS_CLUSTER_RATIO(fs));
Packit a62e42
	if (retval)
Packit a62e42
		goto errout;
Packit a62e42
	size = (__u64) count * fs->blocksize;
Packit a62e42
	retval = ext2fs_inode_size_set(fs, &inode, size);
Packit a62e42
	if (retval)
Packit a62e42
		goto errout;
Packit a62e42
Packit a62e42
	retval = ext2fs_write_new_inode(fs, *ino, &inode;;
Packit a62e42
	if (retval)
Packit a62e42
		goto errout;
Packit a62e42
Packit a62e42
	if (idx_digits)
Packit a62e42
		sprintf(fn_numbuf, "%0*lu", idx_digits, idx);
Packit a62e42
	else if (num_files > 1)
Packit a62e42
		sprintf(fn_numbuf, "%lu", idx);
Packit a62e42
Packit a62e42
retry:
Packit a62e42
	retval = ext2fs_link(fs, dir, fn_buf, *ino, EXT2_FT_REG_FILE);
Packit a62e42
	if (retval == EXT2_ET_DIR_NO_SPACE) {
Packit a62e42
		retval = ext2fs_expand_dir(fs, dir);
Packit a62e42
		if (retval)
Packit a62e42
			goto errout;
Packit a62e42
		goto retry;
Packit a62e42
	}
Packit a62e42
Packit a62e42
	if (retval)
Packit a62e42
		goto errout;
Packit a62e42
Packit a62e42
errout:
Packit a62e42
	if (handle)
Packit a62e42
		ext2fs_extent_free(handle);
Packit a62e42
Packit a62e42
	return retval;
Packit a62e42
}
Packit a62e42
Packit a62e42
static blk64_t calc_overhead(ext2_filsys fs, blk64_t num)
Packit a62e42
{
Packit a62e42
	blk64_t e_blocks, e_blocks2, e_blocks3, e_blocks4;
Packit a62e42
	int extents_per_block;
Packit a62e42
	int extents = (num + EXT_INIT_MAX_LEN - 1) / EXT_INIT_MAX_LEN;
Packit a62e42
Packit a62e42
	if (extents <= 4)
Packit a62e42
		return 0;
Packit a62e42
Packit a62e42
	/*
Packit a62e42
	 * This calculation is due to the fact that we are inefficient
Packit a62e42
	 * in how handle extent splits when appending to the end of
Packit a62e42
	 * the extent tree.  Sigh.  We should fix this so that we can
Packit a62e42
	 * actually store 340 extents per 4k block, instead of only 170.
Packit a62e42
	 */
Packit a62e42
	extents_per_block = ((fs->blocksize -
Packit a62e42
			      sizeof(struct ext3_extent_header)) /
Packit a62e42
			     sizeof(struct ext3_extent));
Packit a62e42
	extents_per_block = (extents_per_block/ 2) - 1;
Packit a62e42
Packit a62e42
	e_blocks = (extents + extents_per_block - 1) / extents_per_block;
Packit a62e42
	e_blocks2 = (e_blocks + extents_per_block - 1) / extents_per_block;
Packit a62e42
	e_blocks3 = (e_blocks2 + extents_per_block - 1) / extents_per_block;
Packit a62e42
	e_blocks4 = (e_blocks3 + extents_per_block - 1) / extents_per_block;
Packit a62e42
	return (e_blocks + e_blocks2 + e_blocks3 + e_blocks4) *
Packit a62e42
		EXT2FS_CLUSTER_RATIO(fs);
Packit a62e42
}
Packit a62e42
Packit a62e42
/*
Packit a62e42
 * Find the place where we should start allocating blocks for the huge
Packit a62e42
 * files.  Leave <slack> free blocks at the beginning of the file
Packit a62e42
 * system for things like metadata blocks.
Packit a62e42
 */
Packit a62e42
static blk64_t get_start_block(ext2_filsys fs, blk64_t slack)
Packit a62e42
{
Packit a62e42
	errcode_t retval;
Packit a62e42
	blk64_t blk = fs->super->s_first_data_block, next;
Packit a62e42
	blk64_t last_blk = ext2fs_blocks_count(fs->super) - 1;
Packit a62e42
Packit a62e42
	while (slack) {
Packit a62e42
		retval = ext2fs_find_first_zero_block_bitmap2(fs->block_map,
Packit a62e42
						blk, last_blk, &blk);
Packit a62e42
		if (retval)
Packit a62e42
			break;
Packit a62e42
Packit a62e42
		retval = ext2fs_find_first_set_block_bitmap2(fs->block_map,
Packit a62e42
						blk, last_blk, &next;;
Packit a62e42
		if (retval)
Packit a62e42
			next = last_blk;
Packit a62e42
Packit a62e42
		if (next - blk > slack) {
Packit a62e42
			blk += slack;
Packit a62e42
			break;
Packit a62e42
		}
Packit a62e42
Packit a62e42
		slack -= (next - blk);
Packit a62e42
		blk = next;
Packit a62e42
	}
Packit a62e42
	return blk;
Packit a62e42
}
Packit a62e42
Packit a62e42
static blk64_t round_up_align(blk64_t b, unsigned long align,
Packit a62e42
			      blk64_t part_offset)
Packit a62e42
{
Packit a62e42
	unsigned long m;
Packit a62e42
Packit a62e42
	if (align == 0)
Packit a62e42
		return b;
Packit a62e42
	part_offset = part_offset % align;
Packit a62e42
	m = (b + part_offset) % align;
Packit a62e42
	if (m)
Packit a62e42
		b += align - m;
Packit a62e42
	return b;
Packit a62e42
}
Packit a62e42
Packit a62e42
errcode_t mk_hugefiles(ext2_filsys fs, const char *device_name)
Packit a62e42
{
Packit a62e42
	unsigned long	i;
Packit a62e42
	ext2_ino_t	dir;
Packit a62e42
	errcode_t	retval;
Packit a62e42
	blk64_t		fs_blocks, part_offset = 0;
Packit a62e42
	unsigned long	align;
Packit a62e42
	int		d, dsize;
Packit a62e42
	char		*t;
Packit a62e42
Packit a62e42
	if (!get_bool_from_profile(fs_types, "make_hugefiles", 0))
Packit a62e42
		return 0;
Packit a62e42
Packit a62e42
	if (!ext2fs_has_feature_extents(fs->super))
Packit a62e42
		return EXT2_ET_EXTENT_NOT_SUPPORTED;
Packit a62e42
Packit a62e42
	uid = get_int_from_profile(fs_types, "hugefiles_uid", 0);
Packit a62e42
	gid = get_int_from_profile(fs_types, "hugefiles_gid", 0);
Packit a62e42
	fs->umask = get_int_from_profile(fs_types, "hugefiles_umask", 077);
Packit a62e42
	num_files = get_int_from_profile(fs_types, "num_hugefiles", 0);
Packit a62e42
	t = get_string_from_profile(fs_types, "hugefiles_slack", "1M");
Packit a62e42
	num_slack = parse_num_blocks2(t, fs->super->s_log_block_size);
Packit a62e42
	free(t);
Packit a62e42
	t = get_string_from_profile(fs_types, "hugefiles_size", "0");
Packit a62e42
	num_blocks = parse_num_blocks2(t, fs->super->s_log_block_size);
Packit a62e42
	free(t);
Packit a62e42
	t = get_string_from_profile(fs_types, "hugefiles_align", "0");
Packit a62e42
	align = parse_num_blocks2(t, fs->super->s_log_block_size);
Packit a62e42
	free(t);
Packit a62e42
	if (get_bool_from_profile(fs_types, "hugefiles_align_disk", 0)) {
Packit a62e42
		part_offset = get_partition_start(device_name) /
Packit a62e42
			(fs->blocksize / 512);
Packit a62e42
		if (part_offset % EXT2FS_CLUSTER_RATIO(fs)) {
Packit a62e42
			fprintf(stderr,
Packit a62e42
				_("Partition offset of %llu (%uk) blocks "
Packit a62e42
				  "not compatible with cluster size %u.\n"),
Packit a62e42
				part_offset, fs->blocksize,
Packit a62e42
				EXT2_CLUSTER_SIZE(fs->super));
Packit a62e42
			exit(1);
Packit a62e42
		}
Packit a62e42
	}
Packit a62e42
	num_blocks = round_up_align(num_blocks, align, 0);
Packit a62e42
	zero_hugefile = get_bool_from_profile(fs_types, "zero_hugefiles",
Packit a62e42
					      zero_hugefile);
Packit a62e42
Packit a62e42
	t = get_string_from_profile(fs_types, "hugefiles_dir", "/");
Packit a62e42
	retval = create_directory(fs, t, &dir;;
Packit a62e42
	free(t);
Packit a62e42
	if (retval)
Packit a62e42
		return retval;
Packit a62e42
Packit a62e42
	fn_prefix = get_string_from_profile(fs_types, "hugefiles_name",
Packit a62e42
					    "hugefile");
Packit a62e42
	idx_digits = get_int_from_profile(fs_types, "hugefiles_digits", 5);
Packit a62e42
	d = int_log10(num_files) + 1;
Packit a62e42
	if (idx_digits > d)
Packit a62e42
		d = idx_digits;
Packit a62e42
	dsize = strlen(fn_prefix) + d + 16;
Packit a62e42
	fn_buf = malloc(dsize);
Packit a62e42
	if (!fn_buf) {
Packit a62e42
		free(fn_prefix);
Packit a62e42
		return ENOMEM;
Packit a62e42
	}
Packit a62e42
	strcpy(fn_buf, fn_prefix);
Packit a62e42
	fn_numbuf = fn_buf + strlen(fn_prefix);
Packit a62e42
	free(fn_prefix);
Packit a62e42
Packit a62e42
	fs_blocks = ext2fs_free_blocks_count(fs->super);
Packit a62e42
	if (fs_blocks < num_slack + align)
Packit a62e42
		return ENOSPC;
Packit a62e42
	fs_blocks -= num_slack + align;
Packit a62e42
	if (num_blocks && num_blocks > fs_blocks)
Packit a62e42
		return ENOSPC;
Packit a62e42
	if (num_blocks == 0 && num_files == 0)
Packit a62e42
		num_files = 1;
Packit a62e42
Packit a62e42
	if (num_files == 0 && num_blocks) {
Packit a62e42
		num_files = fs_blocks / num_blocks;
Packit a62e42
		fs_blocks -= (num_files / 16) + 1;
Packit a62e42
		fs_blocks -= calc_overhead(fs, num_blocks) * num_files;
Packit a62e42
		num_files = fs_blocks / num_blocks;
Packit a62e42
	}
Packit a62e42
Packit a62e42
	if (num_blocks == 0 && num_files > 1) {
Packit a62e42
		num_blocks = fs_blocks / num_files;
Packit a62e42
		fs_blocks -= (num_files / 16) + 1;
Packit a62e42
		fs_blocks -= calc_overhead(fs, num_blocks) * num_files;
Packit a62e42
		num_blocks = fs_blocks / num_files;
Packit a62e42
	}
Packit a62e42
Packit a62e42
	num_slack += (calc_overhead(fs, num_blocks ? num_blocks : fs_blocks) *
Packit a62e42
		      num_files);
Packit a62e42
	num_slack += (num_files / 16) + 1; /* space for dir entries */
Packit a62e42
	goal = get_start_block(fs, num_slack);
Packit a62e42
	goal = round_up_align(goal, align, part_offset);
Packit a62e42
Packit a62e42
	if ((num_blocks ? num_blocks : fs_blocks) >
Packit a62e42
	    (0x80000000UL / fs->blocksize))
Packit a62e42
		ext2fs_set_feature_large_file(fs->super);
Packit a62e42
Packit a62e42
	if (!quiet) {
Packit a62e42
		if (zero_hugefile && verbose)
Packit a62e42
			printf("%s", _("Huge files will be zero'ed\n"));
Packit a62e42
		printf(_("Creating %lu huge file(s) "), num_files);
Packit a62e42
		if (num_blocks)
Packit a62e42
			printf(_("with %llu blocks each"), num_blocks);
Packit a62e42
		fputs(": ", stdout);
Packit a62e42
	}
Packit a62e42
	for (i=0; i < num_files; i++) {
Packit a62e42
		ext2_ino_t ino;
Packit a62e42
Packit a62e42
		retval = mk_hugefile(fs, num_blocks, dir, i, &ino);
Packit a62e42
		if (retval) {
Packit a62e42
			com_err(program_name, retval,
Packit a62e42
				_("while creating huge file %lu"), i);
Packit a62e42
			goto errout;
Packit a62e42
		}
Packit a62e42
	}
Packit a62e42
	if (!quiet)
Packit a62e42
		fputs(_("done\n"), stdout);
Packit a62e42
Packit a62e42
errout:
Packit a62e42
	free(fn_buf);
Packit a62e42
	return retval;
Packit a62e42
}