All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andreas Dilger <adilger@sun.com>
To: "Theodore Ts'o" <tytso@mit.edu>, linux-ext4@vger.kernel.org
Subject: Re: [PATCH][26/28] e2fsprogs-fiemap.patch
Date: Sat, 02 Feb 2008 01:54:41 -0700	[thread overview]
Message-ID: <20080202085441.GA31694@webber.adilger.int> (raw)
In-Reply-To: <20080202075943.GB23836@webber.adilger.int>


Add support for ioctl(FIEMAP) to filefrag.  If the kernel supports FIEMAP
the filefrag program prefers this more efficient mechanism to get extent
information instead of repeated FIBMAP calls.

Signed-off-by: Kalpak Shah <kalpak@clusterfs.com>
Signed-off-by: Andreas Dilger <adilger@clusterfs.com>

Index: e2fsprogs-1.40.2/misc/filefrag.c
===================================================================
--- e2fsprogs-1.40.2.orig/misc/filefrag.c
+++ e2fsprogs-1.40.2/misc/filefrag.c
@@ -38,11 +38,47 @@ extern int optind;
 #include <sys/vfs.h>
 #include <sys/ioctl.h>
 #include <linux/fd.h>
+#include <ext2fs/ext2_types.h>
 
 int verbose = 0;
 
-#define FIBMAP	   _IO(0x00,1)	/* bmap access */
-#define FIGETBSZ   _IO(0x00,2)	/* get the block size used for bmap */
+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_unused;
+	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_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 FIBMAP		_IO(0x00, 1)	/* bmap access */
+#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*/
 
 #define EXT4_EXTENTS_FL			0x00080000 /* Inode uses extents */
 #define	EXT3_IOC_GETFLAGS		_IOR('f', 1, long)
@@ -71,6 +107,62 @@ static unsigned long get_bmap(int fd, un
 	return b;
 }
 
+int filefrag_fiemap(int fd, int bs, int *num_extents)
+{
+	char buf[4096] = "";
+	struct fiemap *fiemap = (struct fiemap *)buf;
+	int count = (sizeof(buf) - sizeof(*fiemap)) /
+			sizeof(struct fiemap_extent);
+	__u64 logical_blk = 0, last_blk = 0;
+	unsigned long flags;
+	int tot_extents = 0;
+	int eof = 0;
+	int i;
+	int rc;
+
+	memset(fiemap, 0, sizeof(struct fiemap));
+	fiemap->fm_extent_count = count;
+	fiemap->fm_length = ~0ULL;
+	if (!verbose)
+		flags |= FIEMAP_FLAG_NUM_EXTENTS;
+
+	do {
+		fiemap->fm_length = ~0ULL;
+		fiemap->fm_flags = flags;
+		fiemap->fm_extent_count = count;
+		rc = ioctl (fd, EXT4_IOC_FIEMAP, (unsigned long) fiemap);
+		if (rc)
+			return rc;
+
+		if (!verbose) {
+			*num_extents = fiemap->fm_extent_count;
+			goto out;
+		}
+
+		for (i = 0; i < fiemap->fm_extent_count; i++) {
+			__u64 phy_blk;
+			unsigned long ext_len;
+
+			phy_blk = fiemap->fm_extents[i].fe_offset / bs;
+			ext_len = fiemap->fm_extents[i].fe_length / bs;
+			if (logical_blk && (phy_blk != last_blk+1))
+				printf("Discontinuity: Block %llu is at %llu "
+				       "(was %llu)\n", logical_blk, phy_blk,
+				       last_blk);
+			logical_blk += ext_len;
+			last_blk = phy_blk + ext_len - 1;
+			if (fiemap->fm_extents[i].fe_flags & FIEMAP_EXTENT_EOF)
+				eof = 1;
+		}
+		fiemap->fm_start += fiemap->fm_length;
+		tot_extents += fiemap->fm_extent_count;
+	} while (0);
+
+	*num_extents = tot_extents;
+out:
+	return 0;
+}
+
 #define EXT2_DIRECT	12
 
 static void frag_report(const char *filename)
@@ -86,7 +178,7 @@ static void frag_report(const char *file
 	unsigned long	block, last_block = 0, numblocks, i;
 	long		bpib;	/* Blocks per indirect block */
 	long		cylgroups;
-	int		discont = 0, expected;
+	int		num_extents = 0, expected;
 	int		is_ext2 = 0;
 	unsigned int	flags;
 
@@ -135,7 +227,8 @@ static void frag_report(const char *file
 	if (ioctl(fd, EXT3_IOC_GETFLAGS, &flags) < 0)
 		flags = 0;
 	if (flags & EXT4_EXTENTS_FL) {
-		printf("File is stored in extents format\n");
+		if (verbose)
+			printf("File is stored in extents format\n");
 		is_ext2 = 0;
 	}
 	if (verbose)
@@ -148,32 +241,36 @@ static void frag_report(const char *file
 		printf("First block: %lu\nLast block: %lu\n",
 		       get_bmap(fd, 0), get_bmap(fd, numblocks - 1));
 	}
-	for (i=0; i < numblocks; i++) {
-		if (is_ext2 && last_block) {
-			if (((i-EXT2_DIRECT) % bpib) == 0)
-				last_block++;
-			if (((i-EXT2_DIRECT-bpib) % (bpib*bpib)) == 0)
-				last_block++;
-			if (((i-EXT2_DIRECT-bpib-bpib*bpib) % (bpib*bpib*bpib)) == 0)
-				last_block++;
-		}
-		block = get_bmap(fd, i);
-		if (block == 0)
-			continue;
-		if (last_block && (block != last_block +1) ) {
-			if (verbose)
-				printf("Discontinuity: Block %ld is at %lu (was %lu)\n",
-				       i, block, last_block);
-			discont++;
+	if (is_ext2 || (filefrag_fiemap(fd, bs, &num_extents) != 0)) {
+		for (i = 0; i < numblocks; i++) {
+			if (is_ext2 && last_block) {
+				if (((i-EXT2_DIRECT) % bpib) == 0)
+					last_block++;
+				if (((i-EXT2_DIRECT-bpib) % (bpib*bpib)) == 0)
+					last_block++;
+				if (((i-EXT2_DIRECT-bpib-bpib*bpib) %
+							(bpib*bpib*bpib)) == 0)
+					last_block++;
+			}
+			block = get_bmap(fd, i);
+			if (block == 0)
+				continue;
+			if (last_block && (block != last_block+1) ) {
+				if (verbose)
+					printf("Discontinuity: Block %ld is at "
+					       "%lu (was %lu)\n",
+					       i, block, last_block+1);
+				num_extents++;
+			}
+			last_block = block;
 		}
-		last_block = block;
 	}
-	if (discont==0)
+	if (num_extents == 1)
 		printf("%s: 1 extent found", filename);
 	else
-		printf("%s: %d extents found", filename, discont+1);
+		printf("%s: %d extents found", filename, num_extents);
 	expected = (numblocks/((bs*8)-(fsinfo.f_files/8/cylgroups)-3))+1;
-	if (is_ext2 && expected != discont+1)
+	if (is_ext2 && expected != num_extents)
 		printf(", perfection would be %d extent%s\n", expected,
 			(expected>1) ? "s" : "");
 	else

Cheers, Andreas
--
Andreas Dilger
Sr. Staff Engineer, Lustre Group
Sun Microsystems of Canada, Inc.

  parent reply	other threads:[~2008-02-02  8:54 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-02-02  7:59 [PATCH][0/28] Lustre e2fsprogs patch series Andreas Dilger
2008-02-02  8:14 ` [PATCH][1/28] e2fsprogs-specdotin.patch Andreas Dilger
2008-02-02  8:16 ` [PATCH] [2/28] e2fsprogs-eacheck.patch Andreas Dilger
2008-02-02  8:17 ` [PATCH][3/28] e2fsprogs-extended_ops.patch Andreas Dilger
2008-02-02  8:20 ` [PATCH][4/28] e2fsprogs-tests-f_unsorted_EAs.patch Andreas Dilger
2008-02-02  8:22 ` [PATCH][5/28] e2fsprogs-tests-f_ea_checks.patch Andreas Dilger
2008-02-02  8:25 ` [PATCH][6/28] e2fsprogs-nlinks.patch Andreas Dilger
2008-02-02  8:25 ` [PATCH][0/28] e2fsprogs-extents.patch Andreas Dilger
2008-02-02  8:27   ` [PATCH][7/28] e2fsprogs-extents.patch Andreas Dilger
2008-02-18 17:56     ` Eric Sandeen
2008-02-18 18:12       ` Eric Sandeen
2008-02-18 19:53       ` Theodore Tso
2008-02-18 20:48         ` Eric Sandeen
2008-02-18 22:09           ` Theodore Tso
2008-02-19  4:35       ` Andreas Dilger
2008-02-02  8:29 ` [PATCH][8/28] e2fsprogs-config-before-cmdline.patch Andreas Dilger
2008-02-02  8:30 ` [PATCH][9/28] e2fsprogs-SLES10--m-support.patch Andreas Dilger
2008-02-02  8:34 ` [PATCH][10/28] e2fsprogs-uninit.patch Andreas Dilger
2008-03-15 19:41   ` Theodore Tso
2008-03-16  0:34     ` Andreas Dilger
2008-03-17 12:33   ` Theodore Tso
2008-02-02  8:36 ` [PATCH][11/28] e2fsprogs-nlinks-flag.patch Andreas Dilger
2008-02-02  8:36 ` [PATCH][12/28] e2fsprogs-expand-extra-isize.patch Andreas Dilger
2008-02-02  8:40 ` [PATCH][14/28] e2fsprogs-tests-f_expisize_ea_del.patch Andreas Dilger
2008-02-02  8:41 ` [PATCH][15/28] e2fsprogs-ibadness-counter.patch Andreas Dilger
2008-02-02  8:43 ` [PATCH][16/28] e2fsprogs-tests-f_ibadness.patch Andreas Dilger
2008-02-02  8:46 ` [PATCH][18/28] e2fsprogs-tests-f_random_corruption.patch Andreas Dilger
2008-02-02  8:47 ` [PATCH][19/28] e2fsprogs-stride_option.patch Andreas Dilger
2008-02-02  8:48 ` [PATCH][20/28] e2fsprogs-mmp.patch Andreas Dilger
2008-02-02  8:49 ` [PATCH][21/28] e2fsprogs-journal_chksum.patch Andreas Dilger
2008-02-02  8:54 ` [PATCH][25/28] e2fsprogs-i_size-corruption.patch Andreas Dilger
2008-02-02  8:54 ` Andreas Dilger [this message]
2008-02-02  8:56 ` [PATCH][27/28] e2fsprogs-debugfs-supported_features.patch Andreas Dilger
2008-02-02  8:57 ` [PATCH][28/28] e2fsprogs-lts-make_rpms.patch Andreas Dilger
2008-02-11  4:19 ` [PATCH][0/28] Lustre e2fsprogs patch series Theodore Tso
2008-02-11 10:22   ` Aneesh Kumar K.V
2008-02-11 20:09   ` Andreas Dilger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080202085441.GA31694@webber.adilger.int \
    --to=adilger@sun.com \
    --cc=linux-ext4@vger.kernel.org \
    --cc=tytso@mit.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.