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] [thread-next>] [day] [month] [year] [list]
Message-Id: <1206572840.3637.9.camel@localhost.localdomain>
Date:	Wed, 26 Mar 2008 16:07:20 -0700
From:	Mingming Cao <cmm@...ibm.com>
To:	Eric Sandeen <sandeen@...hat.com>
Cc:	ext4 development <linux-ext4@...r.kernel.org>
Subject: Re: [PATCH 0/3] fiemap patches (RFC/testing)

On Wed, 2008-03-26 at 10:37 -0500, Eric Sandeen wrote:
> Since Akira would like to use the fiemap ioctl for defrag, I thought I should
> put what I have so far out on the list, at least.  This could go in the unstable
> part of the tree if you like, though I need to do more testing etc before it's 
> really ready to go.
> 
I added the patches to the unstable queue, just fyi.
> Also, below is a quick test application I was using with the ioctl.
> 
> -Eric
> 
> 
> #include <stdio.h>
> #include <stdlib.h>
> #include <unistd.h>
> #include <fcntl.h>
> #include <string.h>
> #include <sys/ioctl.h>
> #include <sys/types.h>
> #include <sys/stat.h>
> #include <sys/vfs.h>
> #include <ext2fs/ext2_types.h>
> 
> /*************************************************/
> /* All this should come from fiemap.h eventually */
> struct fiemap_extent {
> 	__u64 fe_offset; /* offset in bytes for the start of the extent */
> 	__u64 fe_length; /* length in bytes for the extent */
> 	__u32 fe_flags;  /* returned FIEMAP_EXTENT_* flags for the extent */
> 	__u32 fe_lun;    /* logical device number for extent (starting at 0) */
> };
> 
> struct fiemap {
> 	__u64 fm_start;	 /* logical starting byte offset (in/out) */
> 	__u64 fm_length;	/* logical length of map (in/out) */
> 	__u32 fm_flags;	 /* FIEMAP_FLAG_* flags for request (in/out) */
> 	__u32 fm_extent_count;  /* number of extents in fm_extents (in/out) */
> 	__u64 fm_end_offset;    /* logical offset of end of mapping in last ioctl */
> 	struct fiemap_extent fm_extents[0];
> };
> 
> #define FIEMAP_FLAG_SYNC	0x00000001 /* sync file data before map */
> #define FIEMAP_FLAG_HSM_READ    0x00000002 /* get data from HSM before map */
> #define FIEMAP_FLAG_NUM_EXTENTS 0x00000004 /* return only number of extents */
> #define FIEMAP_FLAG_INCOMPAT    0xff000000 /* error for unknown flags in here */
> #define FIEMAP_FLAG_LUN_OFFSET  0x01000000 /* use lun offsets, instead of
> 					    * logical file offsets */
> 
> #define FIEMAP_EXTENT_HOLE      0x00000001 /* has no data or space allocation */
> #define FIEMAP_EXTENT_UNWRITTEN 0x00000002 /* space allocated, but no data */
> #define FIEMAP_EXTENT_UNMAPPED  0x00000004 /* has data but no space allocation*/
> #define FIEMAP_EXTENT_ERROR     0x00000008 /* mapping error, errno in fe_start*/
> #define FIEMAP_EXTENT_NO_DIRECT 0x00000010 /* cannot access data directly */
> #define FIEMAP_EXTENT_LAST      0x00000020 /* last extent in the file */
> #define FIEMAP_EXTENT_DELALLOC  0x00000040 /* has data but not yet written,
> 					      must have EXTENT_UNKNOWN set */
> #define FIEMAP_EXTENT_SECONDARY 0x00000080 /* data (also) in secondary storage,
> 					      not in primary if EXTENT_UNKNOWN*/
> #define FIEMAP_EXTENT_EOF       0x00000100 /* if fm_start+fm_len is beyond EOF*/
> 
> #define FIGETBSZ	_IO(0x00, 2)    /* get the block size used for bmap */
> #define EXT4_IOC_FIEMAP _IOWR('f', 10, struct fiemap) /* get file extent info*/
> 
> /* End of what should be coming from fiemap.h */
> /**********************************************/
> 
> 
> void usage(void)
> {
> 	printf("Usage: fiemap [-vrSCL] [-s start] [-l length] [-c buf count] [-m max] filename\n");
> 	printf("  -v        : verbose mode\n");
> 	printf("  -r        : raw output: print raw ioctl structure values\n");
> 	printf("  -S        : set FIEMAP_FLAG_SYNC to sync before mapping\n");
> 	printf("  -C        : set FIEMAP_FLAG_NUM_EXTENTS to only get extent count, not mapping\n");
> 	printf("  -L        : set FIEMAP_FLAG_LUN_OFFSET to report extents in lun order\n");
> 	printf("  -s start  : start of mapping in bytes (default 0)\n");
> 	printf("  -l length : length of mapping in bytes (default to end of file)\n");
> 	printf("  -c count  : count of extents in ioctl input structure (default 32)\n");
> 	printf("  -m max    : max nr of ioctls to call before exit (default 512)\n");
> 	exit(EXIT_FAILURE);
> }
> 
> #define EXABYTES(x)     ((long long)(x) << 60)
> #define PETABYTES(x)    ((long long)(x) << 50)
> #define TERABYTES(x)    ((long long)(x) << 40)
> #define GIGABYTES(x)    ((long long)(x) << 30)
> #define MEGABYTES(x)    ((long long)(x) << 20)
> #define KILOBYTES(x)    ((long long)(x) << 10)
> 
> long long
> cvtnum(char *s)
> {
> 	long long	i;
> 	char		*sp;
> 	int		c;
> 
> 	i = strtoll(s, &sp, 0);
> 	if (i == 0 && sp == s)
> 		return -1LL;
> 	if (*sp == '\0')
> 		return i;
> 	if (sp[1] != '\0')
> 		return -1LL;
> 
> 	c = tolower(*sp);
> 	switch (c) {
> 	case 'k':
> 		return KILOBYTES(i);
> 	case 'm':
> 		return MEGABYTES(i);
> 	case 'g':
> 		return GIGABYTES(i);
> 	case 't':
> 		return TERABYTES(i);
> 	case 'p':
> 		return PETABYTES(i);
> 	case 'e':
> 		return  EXABYTES(i);
> 	}
> 
> 	return -1LL;
> }
> 
> void show_extents_table(struct fiemap *fiemap, int blocksize, int start_extent, int *is_last)
> {
> 	unsigned int	i;
> 	__u64		lstart;
> 
> 	lstart = fiemap->fm_start;
> 	for (i = 0; i < fiemap->fm_extent_count; i++) {
> 		__u64	length = fiemap->fm_extents[i].fe_length;
> 		__u64	phys = fiemap->fm_extents[i].fe_offset;
> 		int	flags = fiemap->fm_extents[i].fe_flags;
> 
> 		printf("ext: %3u logical: [%8llu..%8llu] phys: %8llu..%8llu flags: 0x%03X tot: %llu\n",
> 			i + start_extent,
> 			lstart, lstart + length - 1,
> 			(phys / blocksize),
> 			(flags & FIEMAP_EXTENT_HOLE) ? 0 : (phys + length - 1) / blocksize,
> 			flags,
> 			(length / blocksize));
> 
> 		lstart += length;
> 		if (fiemap->fm_extents[i].fe_flags & FIEMAP_EXTENT_LAST) {
> 			*is_last = 1;
> 			return; /* XXX should we?  or should look for exents filled in past last? */
> 		}
> 	}
> }
> 
> void show_extents_raw(struct fiemap *fiemap, int start_extent, int *is_last)
> {
> 	unsigned int	i;
> 
> 	for (i = 0; i < fiemap->fm_extent_count; i++) {
> 		printf("\tExtent %3u: start: %10lld length: %10lld flags 0x%03X lun %3u\n",
> 			i + start_extent,
> 			fiemap->fm_extents[i].fe_offset,
> 			fiemap->fm_extents[i].fe_length,
> 			fiemap->fm_extents[i].fe_flags,
> 			fiemap->fm_extents[i].fe_lun);
> 
> 		if (fiemap->fm_extents[i].fe_flags & FIEMAP_EXTENT_LAST) {
> 			*is_last = 1;
> 			return; /* XXX should we?  or should look for exents filled in past last? */
> 		}
> 	}
> }
> 
> int main(int argc, char**argv)
> {
> 	int	blocksize = 0;	/* filesystem blocksize */
> 	uint	count = 32;	/* extent count */
> 	int	countonly = 0;	/* return only extent count? */
> 	int	fd;		/* file descriptor */
> 	int	last = 0;	/* last extent found */
> 	int	lunwise = 0;	/* return extents lun-wise */
> 	int	maxioctls = 512; /* max ioctls to try */
> 	int	opt;
> 	int	rc;
> 	int	raw = 0;	/* raw output format */
> 	int	sync = 0;	/* sync file before mapping */
> 	int	verbose = 0;	/* verbose output */
> 	char	*fname;		/* filename to map */
> 	char	*fiebuf;	/* fiemap buffer / ioctl argument */
> 	__u64	lstart = 0;	/* logical input mapping start */
> 	__u64	llength = ~0ULL;/* logical input mapping length */
> 	uint	start_ext = 0;	/* starting extent nr. for this batch */
> 	struct fiemap *fiemap;
> 
> 
> 	while ((opt = getopt(argc, argv, "s:l:c:m:rSCLv")) != -1) {
> 		switch(opt) {
> 		/* logical mapping offset */
> 		case 's':
> 			lstart = cvtnum(optarg);
> 			break;
> 		/* logical mapping length */
> 		case 'l':
> 			llength = cvtnum(optarg);
> 			break;
> 		/* count of extent buffers to send */
> 		case 'c':
> 			count = atoi(optarg);
> 			break;
> 		/* max nr. of ioctls to try (safety net) */
> 		case 'm':
> 			maxioctls = atoi(optarg);
> 			break;
> 		/* raw format output */
> 		case 'r':
> 			raw++;
> 			break;
> 		/* sync file before mapping */
> 		case 'S':
> 			sync++;
> 			break;
> 		/* count extents only, no details */
> 		case 'C':
> 			countonly++;
> 			break;
> 		/* return extents in lun order */
> 		case 'L':
> 			lunwise++;
> 			break;
> 		/* be verbose */
> 		case 'v':
> 			verbose++;
> 			break;
> 		default:
> 			usage();
> 		}
> 	}
> 
> 	fname = argv[optind++];
> 	if (!fname)
> 		usage();
> 
> 	/* The whole buffer, extent maps and all */
> 	fiebuf = malloc(sizeof (struct fiemap) + (count * sizeof(struct fiemap_extent)));
> 	if (!fiebuf) {
> 		perror("Could not allocate fiemap buffers");
> 		exit(1);
> 	}
> 
> 	/* Just the header */
> 	fiemap = (struct fiemap *)fiebuf;
> 
> 	fiemap->fm_start = lstart;
> 	fiemap->fm_length = llength;
> 	fiemap->fm_flags = 0;
> 	if (sync)
> 		fiemap->fm_flags |= FIEMAP_FLAG_SYNC;
> 	if (countonly)
> 		fiemap->fm_flags |= FIEMAP_FLAG_NUM_EXTENTS;
> 	if (lunwise)
> 		fiemap->fm_flags |= FIEMAP_FLAG_LUN_OFFSET;
> 
> 	fiemap->fm_extent_count = count;
> 	fiemap->fm_end_offset = 0;	/* output only */
> 
> 	fd = open(fname, O_RDONLY);
> 	if (fd < 0) {
> 		perror("Can't open file");
> 		exit(1);
> 	}
> 
> 	if (ioctl(fd, FIGETBSZ, &blocksize) < 0) {
> 		perror("Can't get block size");
> 		close(fd);
> 		return;
> 	}
> 
> 	do {
> 		if (verbose)
> 			printf("Input:  start %llu length %llu flags 0x%X count %u end_offset %lld\n",
> 				fiemap->fm_start, fiemap->fm_length,
> 				fiemap->fm_flags, fiemap->fm_extent_count,
> 				fiemap->fm_end_offset);
> 
> 		rc = ioctl(fd, EXT4_IOC_FIEMAP, (unsigned long)fiemap);
> 		if (rc < 0) {
> 			perror("FIEMAP ioctl failed");
> 			close(fd);
> 			exit(1);
> 		}
> 
> 		if (verbose)
> 			printf("Output: start %llu length %llu flags 0x%X count %u end_offset %lld\n",
> 				fiemap->fm_start, fiemap->fm_length,
> 				fiemap->fm_flags, fiemap->fm_extent_count,
> 				fiemap->fm_end_offset);
> 		if (raw)
> 			show_extents_raw(fiemap, start_ext, &last);
> 		else
> 			show_extents_table(fiemap, blocksize, start_ext, &last);
> 
> 		start_ext += fiemap->fm_extent_count;
> 
> 		/* Did we finish up the last of the reqest? */
> 		if (fiemap->fm_length >= llength)
> 			break;
> 		/* Set up the next call arguments */
> 		fiemap->fm_start += fiemap->fm_length;
> 		llength -= fiemap->fm_length;
> 		fiemap->fm_length = llength;
> 		fiemap->fm_extent_count = count;
> 
> 		maxioctls--;
> 
> 	} while (!last && maxioctls > 0);
> 
> 	close(fd);
> 
> 	return 0;
> }
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
> the body of a message to majordomo@...r.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ