filefrag.c revision 2508eaa71e8bbe93155052ded448e5e78d213715
15faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org/*
25faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org * filefrag.c -- report if a particular file is fragmented
35faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org *
45faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org * Copyright 2003 by Theodore Ts'o.
55faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org *
65faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org * %Begin-Header%
75faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org * This file may be redistributed under the terms of the GNU Public
85faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org * License.
95faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org * %End-Header%
105faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org */
118b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org
128b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "config.h"
135faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org#ifndef __linux__
148640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org#include <stdio.h>
155faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org#include <stdlib.h>
163bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org#include <unistd.h>
17d698f77c13d97c61109b861eac4d25b14a5de935bsalomon@google.com
18dbe49f735484f8862e378b63d0a074a301093dd0bsalomon@google.comint main(void) {
192eaaefd7e6a58339b3f93333f1e9cc92252cc303bsalomon@google.com	fputs("This program is only supported on Linux!\n", stderr);
2017fc651dbe2e0624f6c85fb6e081d28a87d5a08bbsalomon@google.com	exit(EXIT_FAILURE);
2117fc651dbe2e0624f6c85fb6e081d28a87d5a08bbsalomon@google.com}
223bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org#else
233bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org#define _LARGEFILE64_SOURCE
24c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
25c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org#include <stdio.h>
26c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org#include <stdlib.h>
27c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org#include <unistd.h>
28c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org#include <string.h>
29c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org#include <time.h>
30c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org#include <fcntl.h>
31c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org#include <errno.h>
32c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org#ifdef HAVE_GETOPT_H
33c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org#include <getopt.h>
34c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org#else
35c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.orgextern char *optarg;
367938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.orgextern int optind;
377938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org#endif
387938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org#include <sys/types.h>
397938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org#include <sys/stat.h>
407938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org#include <sys/vfs.h>
41cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org#include <sys/ioctl.h>
427938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org#include <linux/fd.h>
437938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org#include <ext2fs/ext2fs.h>
447938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org#include <ext2fs/ext2_types.h>
457938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org#include <ext2fs/fiemap.h>
467938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org
475faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.orgint verbose = 0;
485faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.orgint blocksize;		/* Use specified blocksize (default 1kB) */
495faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.orgint sync_file = 0;	/* fsync file before getting the mapping */
50cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.orgint xattr_map = 0;	/* get xattr mapping */
518640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.orgint force_bmap;	/* force use of FIBMAP instead of FIEMAP */
528640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.orgint force_extent;	/* print output in extent format always */
535faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.orgint logical_width = 8;
545faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.orgint physical_width = 10;
555faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.orgchar *ext_fmt = "%4d: %*llu..%*llu: %*llu..%*llu: %6llu: %s\n";
563bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.orgchar *hex_fmt = "%4d: %*llx..%*llx: %*llx..%*llx: %6llx: %s\n";
57cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org
58cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org#define FILEFRAG_FIEMAP_FLAGS_COMPAT (FIEMAP_FLAG_SYNC | FIEMAP_FLAG_XATTR)
595faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
605faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org#define FIBMAP		_IO(0x00, 1)	/* bmap access */
618b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#define FIGETBSZ	_IO(0x00, 2)	/* get the block size used for bmap */
62ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org
63025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org#define LUSTRE_SUPER_MAGIC 0x0BD00BD0
64025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org
65025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org#define	EXT4_EXTENTS_FL			0x00080000 /* Inode uses extents */
665faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org#define	EXT3_IOC_GETFLAGS		_IOR('f', 1, long)
675faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
68d594dbec0407343b7ac13af9c4580ec5933ab060commit-bot@chromium.orgstatic int int_log2(int arg)
69d594dbec0407343b7ac13af9c4580ec5933ab060commit-bot@chromium.org{
70d594dbec0407343b7ac13af9c4580ec5933ab060commit-bot@chromium.org	int     l = 0;
71d594dbec0407343b7ac13af9c4580ec5933ab060commit-bot@chromium.org
72025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org	arg >>= 1;
73025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org	while (arg) {
74d594dbec0407343b7ac13af9c4580ec5933ab060commit-bot@chromium.org		l++;
75025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org		arg >>= 1;
76025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org	}
77d594dbec0407343b7ac13af9c4580ec5933ab060commit-bot@chromium.org	return l;
78d594dbec0407343b7ac13af9c4580ec5933ab060commit-bot@chromium.org}
79d594dbec0407343b7ac13af9c4580ec5933ab060commit-bot@chromium.org
805faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.orgstatic int int_log10(unsigned long long arg)
815faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org{
82cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org	int     l = 0;
83cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org
845faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	arg = arg / 10;
858640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org	while (arg) {
86d594dbec0407343b7ac13af9c4580ec5933ab060commit-bot@chromium.org		l++;
87d594dbec0407343b7ac13af9c4580ec5933ab060commit-bot@chromium.org		arg = arg / 10;
88c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org	}
89c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org	return l;
905faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org}
915faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
928b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgstatic unsigned int div_ceil(unsigned int a, unsigned int b)
935faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org{
945faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	if (!a)
955faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org		return 0;
965faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	return ((a - 1) / b) + 1;
975faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org}
985faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
99cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.orgstatic int get_bmap(int fd, unsigned long block, unsigned long *phy_blk)
100cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org{
1015faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	int	ret;
1028640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org	unsigned int b;
1035faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
1045faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	b = block;
1055faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	ret = ioctl(fd, FIBMAP, &b); /* FIBMAP takes pointer to integer */
1065faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	if (ret < 0) {
1075faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org		if (errno == EPERM) {
1085faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org			fprintf(stderr, "No permission to use FIBMAP ioctl; "
1095faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org				"must have root privileges\n");
1105faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org		}
1117938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org	}
1125faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	*phy_blk = b;
1135faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
1145faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	return ret;
1155faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org}
1165faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
1175faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.orgstatic void print_extent_header(void)
1187938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org{
1197938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org	printf(" ext: %*s %*s length: %*s flags:\n",
1207938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org	       logical_width * 2 + 3,
1215faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	       "logical_offset:",
1225faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	       physical_width * 2 + 3, "physical_offset:",
1235faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	       physical_width + 1,
1245faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	       "expected:");
1255faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org}
1265faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
1277938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.orgstatic void print_extent_info(struct fiemap_extent *fm_extent, int cur_ex,
1287938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org			      unsigned long long expected, int blk_shift,
1297938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org			      ext2fs_struct_stat *st)
1307938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org{
1317938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org	unsigned long long physical_blk;
1325faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	unsigned long long logical_blk;
1337938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org	unsigned long long ext_len;
1347938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org	unsigned long long ext_blks;
1355faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	char flags[256] = "";
1365faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
1375faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	/* For inline data all offsets should be in bytes, not blocks */
1385faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	if (fm_extent->fe_flags & FIEMAP_EXTENT_DATA_INLINE)
1395faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org		blk_shift = 0;
1405faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
1415faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	ext_len = fm_extent->fe_length >> blk_shift;
1427938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org	ext_blks = (fm_extent->fe_length - 1) >> blk_shift;
1437938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org	logical_blk = fm_extent->fe_logical >> blk_shift;
1445faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	physical_blk = fm_extent->fe_physical >> blk_shift;
1455faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
1465faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	if (expected)
1475faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org		sprintf(flags, ext_fmt == hex_fmt ? "%*llx: " : "%*llu: ",
1485faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org			physical_width, expected >> blk_shift);
1495faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	else
1505faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org		sprintf(flags, "%.*s  ", physical_width, "                   ");
1518640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org
1527938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org	if (fm_extent->fe_flags & FIEMAP_EXTENT_UNKNOWN)
1537938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org		strcat(flags, "unknown,");
1547938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org	if (fm_extent->fe_flags & FIEMAP_EXTENT_DELALLOC)
155ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org		strcat(flags, "delalloc,");
1565faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	if (fm_extent->fe_flags & FIEMAP_EXTENT_DATA_ENCRYPTED)
1577938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org		strcat(flags, "encrypted,");
1585faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	if (fm_extent->fe_flags & FIEMAP_EXTENT_NOT_ALIGNED)
1595faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org		strcat(flags, "not_aligned,");
1605faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	if (fm_extent->fe_flags & FIEMAP_EXTENT_DATA_INLINE)
1615faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org		strcat(flags, "inline,");
1627938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org	if (fm_extent->fe_flags & FIEMAP_EXTENT_DATA_TAIL)
163cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org		strcat(flags, "tail_packed,");
164cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org	if (fm_extent->fe_flags & FIEMAP_EXTENT_UNWRITTEN)
1657938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org		strcat(flags, "unwritten,");
1665faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	if (fm_extent->fe_flags & FIEMAP_EXTENT_MERGED)
1678640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org		strcat(flags, "merged,");
1688640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org
1698640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org	if (fm_extent->fe_logical + fm_extent->fe_length >= st->st_size)
1705faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org		strcat(flags, "eof,");
1715faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
1725faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	/* Remove trailing comma, if any */
1735faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	if (flags[0])
1745faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org		flags[strlen(flags) - 1] = '\0';
1758640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org
1768640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org	printf(ext_fmt, cur_ex, logical_width, logical_blk,
1773bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org	       logical_width, logical_blk + ext_blks,
178cc9471c36d3967270f7eb26f8b53ce0f17bc9fbbsenorblanco@chromium.org	       physical_width, physical_blk,
179cc9471c36d3967270f7eb26f8b53ce0f17bc9fbbsenorblanco@chromium.org	       physical_width, physical_blk + ext_blks,
180cc9471c36d3967270f7eb26f8b53ce0f17bc9fbbsenorblanco@chromium.org	       ext_len, flags);
1818640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org}
1827938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org
1838640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.orgstatic int filefrag_fiemap(int fd, int blk_shift, int *num_extents,
1848640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org			   ext2fs_struct_stat *st)
1858640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org{
1868640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org	char buf[16384];
1875faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	struct fiemap *fiemap = (struct fiemap *)buf;
1885faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	struct fiemap_extent *fm_ext = &fiemap->fm_extents[0];
1895faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	int count = (sizeof(buf) - sizeof(*fiemap)) /
1905faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org			sizeof(struct fiemap_extent);
1918640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org	unsigned long long expected = 0;
1927938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org	unsigned long flags = 0;
1937938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org	unsigned int i;
1947938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org	static int fiemap_incompat_printed;
195ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org	int fiemap_header_printed = 0;
1968640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org	int tot_extents = 0, n = 0;
1977938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org	int last = 0;
1988640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org	int rc;
1997938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org
2008640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org	memset(fiemap, 0, sizeof(struct fiemap));
2018640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org
2028640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org	if (sync_file)
2037938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org		flags |= FIEMAP_FLAG_SYNC;
2047938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org
2057938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org	if (xattr_map)
206ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org		flags |= FIEMAP_FLAG_XATTR;
2077938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org
2085faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	do {
2095faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org		fiemap->fm_length = ~0ULL;
2107938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org		fiemap->fm_flags = flags;
2117938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org		fiemap->fm_extent_count = count;
2127938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org		rc = ioctl(fd, FS_IOC_FIEMAP, (unsigned long) fiemap);
213ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org		if (rc < 0) {
2145faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org			if (errno == EBADR && fiemap_incompat_printed == 0) {
2155faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org				printf("FIEMAP failed with unsupported "
2167938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org				       "flags %x\n", fiemap->fm_flags);
2175faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org				fiemap_incompat_printed = 1;
2185faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org			}
2197938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org			return rc;
2205faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org		}
2215faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
2227938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org		/* If 0 extents are returned, then more ioctls are not needed */
2235faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org		if (fiemap->fm_mapped_extents == 0)
2245faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org			break;
2255faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
2265faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org		if (verbose && !fiemap_header_printed) {
227377c14a1e648f4427bd11474fad8ac264d98aff2senorblanco@chromium.org			print_extent_header();
2288640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org			fiemap_header_printed = 1;
2298640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org		}
2308640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org
2318640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org		for (i = 0; i < fiemap->fm_mapped_extents; i++) {
2328640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org			if (fm_ext[i].fe_logical != 0 &&
2338640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org			    fm_ext[i].fe_physical != expected) {
2348640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org				tot_extents++;
2358640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org			} else {
2368640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org				expected = 0;
2378640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org				if (!tot_extents)
2388640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org					tot_extents = 1;
2398640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org			}
2408640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org			if (verbose)
2418640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org				print_extent_info(&fm_ext[i], n, expected,
2428640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org						  blk_shift, st);
2438640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org
2448640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org			expected = fm_ext[i].fe_physical + fm_ext[i].fe_length;
2458640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org			if (fm_ext[i].fe_flags & FIEMAP_EXTENT_LAST)
2468640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org				last = 1;
2478640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org			n++;
2488640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org		}
2498640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org
2508640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org		fiemap->fm_start = (fm_ext[i - 1].fe_logical +
2518640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org				    fm_ext[i - 1].fe_length);
2525faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	} while (last == 0);
2535faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
2545faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	*num_extents = tot_extents;
2555faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
256ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org	return 0;
25768400767be5f72e4b9750ccc8bcf0078d42869a7senorblanco@chromium.org}
2586776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org
2596776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org#define EXT2_DIRECT	12
26068400767be5f72e4b9750ccc8bcf0078d42869a7senorblanco@chromium.org
26168400767be5f72e4b9750ccc8bcf0078d42869a7senorblanco@chromium.orgstatic int filefrag_fibmap(int fd, int blk_shift, int *num_extents,
26268400767be5f72e4b9750ccc8bcf0078d42869a7senorblanco@chromium.org			   ext2fs_struct_stat *st,
263e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org			   unsigned long numblocks, int is_ext2)
2645faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org{
2655faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	struct fiemap_extent	fm_ext;
2665faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	unsigned long		i, last_block;
2677938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org	unsigned long long	logical;
2687938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org				/* Blocks per indirect block */
2696776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org	const long		bpib = st->st_blksize / 4;
2707938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org	int			count;
2717938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org
2727938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org	if (force_extent) {
2737938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org		memset(&fm_ext, 0, sizeof(fm_ext));
2748640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org		fm_ext.fe_flags = FIEMAP_EXTENT_MERGED;
2758640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org	}
2768640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org
2778640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org	if (sync_file)
2785faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org		fsync(fd);
2795faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
2805faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	for (i = 0, logical = 0, *num_extents = 0, count = last_block = 0;
2815faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	     i < numblocks;
2825faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org	     i++, logical += st->st_blksize) {
2837938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org		unsigned long block = 0;
2845faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org		int rc;
285cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org
286cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org		if (is_ext2 && last_block) {
287cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org			if (((i - EXT2_DIRECT) % bpib) == 0)
2885faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org				last_block++;
2896776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org			if (((i - EXT2_DIRECT - bpib) % (bpib * bpib)) == 0)
2906776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org				last_block++;
2916776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org			if (((i - EXT2_DIRECT - bpib - bpib * bpib) %
292cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org			     (((unsigned long long)bpib) * bpib * bpib)) == 0)
293cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org				last_block++;
2947938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org		}
2957938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org		rc = get_bmap(fd, i, &block);
2967938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org		if (rc < 0)
2977938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org			return rc;
2987938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org		if (block == 0)
2997938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org			continue;
3007938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org		if (*num_extents == 0) {
3015faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org			(*num_extents)++;
3027938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org			if (force_extent) {
3037938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org				print_extent_header();
3047938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org				fm_ext.fe_physical = block * st->st_blksize;
3057938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org			}
3067938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org		}
3077938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org		count++;
3085faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org		if (force_extent && last_block != 0 &&
3095faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org		    (block != last_block + 1 ||
3103bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org		     fm_ext.fe_logical + fm_ext.fe_length != logical)) {
3113bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org			print_extent_info(&fm_ext, *num_extents - 1,
3123bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org					  (last_block + 1) * st->st_blksize,
3133bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org					  blk_shift, st);
3143bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org			fm_ext.fe_logical = logical;
3153bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org			fm_ext.fe_physical = block * st->st_blksize;
3163bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org			fm_ext.fe_length = 0;
3173bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org			(*num_extents)++;
3183bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org		} else if (verbose && last_block && (block != last_block + 1)) {
3193bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org			printf("Discontinuity: Block %ld is at %lu (was %lu)\n",
3200ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com			       i, block, last_block + 1);
3217938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org			(*num_extents)++;
3220ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com		}
3230ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com		fm_ext.fe_length += st->st_blksize;
3240ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com		last_block = block;
3250ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com	}
326cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org
3270ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com	if (force_extent)
3280ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com		print_extent_info(&fm_ext, *num_extents - 1,
3296340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com				  last_block * st->st_blksize, blk_shift, st);
3307938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org
3316340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com	return count;
3326340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com}
3336340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com
3346340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.comstatic void frag_report(const char *filename)
335cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org{
3366340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com	static struct statfs fsinfo;
3376340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com	ext2fs_struct_stat st;
338a1ebbe447d5eab098111eb83580e55f2f5f6facabsalomon@google.com	int		blk_shift;
3390ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com	int		bs;
3403bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org	long		fd;
3413bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org	unsigned long	numblocks;
3420263fcd72ee81ccff012bff85dbee89cd524a930bsalomon@google.com	int		data_blocks_per_cyl = 1;
3430263fcd72ee81ccff012bff85dbee89cd524a930bsalomon@google.com	int		num_extents = 1, expected = ~0;
3440263fcd72ee81ccff012bff85dbee89cd524a930bsalomon@google.com	int		is_ext2 = 0;
3450263fcd72ee81ccff012bff85dbee89cd524a930bsalomon@google.com	static dev_t	last_device;
3460263fcd72ee81ccff012bff85dbee89cd524a930bsalomon@google.com	unsigned int	flags;
3470263fcd72ee81ccff012bff85dbee89cd524a930bsalomon@google.com	int		width;
3483bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org
3497938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org#if defined(HAVE_OPEN64) && !defined(__OSX_AVAILABLE_BUT_DEPRECATED)
3503bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org	fd = open64(filename, O_RDONLY);
351cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org#else
3523bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org	fd = open(filename, O_RDONLY);
3533bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org#endif
3543bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org	if (fd < 0) {
3553bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org		perror("open");
3563bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org		return;
3573bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org	}
358422e81aeb1f4078367c85efe591c7df8c33874ecbsalomon@google.com
3593bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org#if defined(HAVE_FSTAT64) && !defined(__OSX_AVAILABLE_BUT_DEPRECATED)
360396e61fe440590744345e0c56970b26ab464591dbsalomon@google.com	if (fstat64(fd, &st) < 0) {
3613bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org#else
3623bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org	if (fstat(fd, &st) < 0) {
3630ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com#endif
3647938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org		perror("stat");
3650ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com		return;
3660ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com	}
3670ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com
3680ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com	if (last_device != st.st_dev) {
369cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org		if (fstatfs(fd, &fsinfo) < 0) {
3700ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com			perror("fstatfs");
3710ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com			return;
3720ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com		}
3738a252f79629b189a03de22cd8ff0312c5bccedd1bsalomon@google.com		if (verbose)
37468b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com			printf("Filesystem type is: %lx\n",
3757938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org			       (unsigned long) fsinfo.f_type);
3763bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org	}
3773bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org	st.st_blksize = fsinfo.f_bsize;
3783bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org	if (ioctl(fd, EXT3_IOC_GETFLAGS, &flags) < 0)
3793bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org		flags = 0;
380cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org	if (!(flags & EXT4_EXTENTS_FL) &&
3813bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org	    ((fsinfo.f_type == 0xef51) || (fsinfo.f_type == 0xef52) ||
3823bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org	     (fsinfo.f_type == 0xef53)))
3833bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org		is_ext2++;
384f271cc7183fe48ac64d2d9a454eb013c91b42d53bsalomon@google.com
3853bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org	if (is_ext2) {
3863bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org		long cylgroups = div_ceil(fsinfo.f_blocks, fsinfo.f_bsize * 8);
3873bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org
3883bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org		if (verbose && last_device != st.st_dev)
38922a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.com			printf("Filesystem cylinder groups approximately %ld\n",
3903bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org			       cylgroups);
391396e61fe440590744345e0c56970b26ab464591dbsalomon@google.com
392c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com		data_blocks_per_cyl = fsinfo.f_bsize * 8 -
39322a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.com					(fsinfo.f_files / 8 / cylgroups) - 3;
394c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com	}
39522a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.com	last_device = st.st_dev;
39622a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.com
39722a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.com	width = int_log10(fsinfo.f_blocks);
39877af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com	if (width > physical_width)
39922a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.com		physical_width = width;
4003bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org
401c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com	numblocks = (st.st_size + fsinfo.f_bsize - 1) / fsinfo.f_bsize;
4023bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org	if (blocksize != 0)
403c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com		blk_shift = int_log2(blocksize);
4043bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org	else
4053bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org		blk_shift = int_log2(fsinfo.f_bsize);
4063bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org
4073bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org	width = int_log10(numblocks);
40817fc651dbe2e0624f6c85fb6e081d28a87d5a08bbsalomon@google.com	if (width > logical_width)
40917fc651dbe2e0624f6c85fb6e081d28a87d5a08bbsalomon@google.com		logical_width = width;
41017fc651dbe2e0624f6c85fb6e081d28a87d5a08bbsalomon@google.com	if (verbose)
41117fc651dbe2e0624f6c85fb6e081d28a87d5a08bbsalomon@google.com		printf("File size of %s is %llu (%lu block%s of %d bytes)\n",
4127938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org		       filename, (unsigned long long)st.st_size,
41317fc651dbe2e0624f6c85fb6e081d28a87d5a08bbsalomon@google.com		       numblocks * fsinfo.f_bsize >> blk_shift,
41417fc651dbe2e0624f6c85fb6e081d28a87d5a08bbsalomon@google.com		       numblocks == 1 ? "" : "s", 1 << blk_shift);
41584cd099704b3896ca66081a96508572a924f850ccommit-bot@chromium.org
41617fc651dbe2e0624f6c85fb6e081d28a87d5a08bbsalomon@google.com	if (force_bmap ||
41717fc651dbe2e0624f6c85fb6e081d28a87d5a08bbsalomon@google.com	    filefrag_fiemap(fd, blk_shift, &num_extents, &st) != 0) {
4183bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org		expected = filefrag_fibmap(fd, blk_shift, &num_extents,
41922a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.com					   &st, numblocks, is_ext2);
4203bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org		if (expected < 0) {
4213bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org			if (errno == EINVAL || errno == ENOTTY) {
422396e61fe440590744345e0c56970b26ab464591dbsalomon@google.com				fprintf(stderr, "%s: FIBMAP unsupported\n",
423c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com					filename);
42477af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com			} else if (errno != EPERM) {
425c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com				fprintf(stderr, "%s: FIBMAP error: %s",
4263bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org					filename, strerror(errno));
4273bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org			}
4283bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org			goto out_close;
4293bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org		}
4303bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org		expected = expected / data_blocks_per_cyl + 1;
4313bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org	}
4323bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org
4333bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org	if (num_extents == 1)
4347938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org		printf("%s: 1 extent found", filename);
4353bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org	else
4363bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org		printf("%s: %d extents found", filename, num_extents);
4373bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org	/* count, and thus expected, only set for indirect FIBMAP'd files */
4383bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org	if (is_ext2 && expected && expected < num_extents)
4397938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org		printf(", perfection would be %d extent%s\n", expected,
4403bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org			(expected > 1) ? "s" : "");
4413bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org	else
4423bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org		fputc('\n', stdout);
4437938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.orgout_close:
4443bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org	close(fd);
4453bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org}
4463bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org
4477938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.orgstatic void usage(const char *progname)
4483bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org{
4493bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org	fprintf(stderr, "Usage: %s [-b{blocksize}] [-BeklsvxX] file ...\n",
45074a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org		progname);
4513bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org	exit(1);
4523bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org}
45322a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.com
454c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.comint main(int argc, char**argv)
45517fc651dbe2e0624f6c85fb6e081d28a87d5a08bbsalomon@google.com{
45622a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.com	char **cpp;
45722a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.com	int c;
45877af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com
45922a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.com	while ((c = getopt(argc, argv, "Bb::eksvxX")) != EOF)
460a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org		switch (c) {
46177af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com		case 'B':
4627938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org			force_bmap++;
4637938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org			break;
46474a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org		case 'b':
46522a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.com			if (optarg) {
46674a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org				char *end;
4677938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org				blocksize = strtoul(optarg, &end, 0);
4687938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org				if (end) {
4697938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org					switch (end[0]) {
47084cd099704b3896ca66081a96508572a924f850ccommit-bot@chromium.org					case 'g':
47184cd099704b3896ca66081a96508572a924f850ccommit-bot@chromium.org					case 'G':
47274a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org						blocksize *= 1024;
47322a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.com						/* no break */
47474a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org					case 'm':
47522a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.com					case 'M':
47622a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.com						blocksize *= 1024;
4777938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org						/* no break */
47884cd099704b3896ca66081a96508572a924f850ccommit-bot@chromium.org					case 'k':
4793bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org					case 'K':
4803bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org						blocksize *= 1024;
4813bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org						break;
4823bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org					default:
4833bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org						break;
4843bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org					}
4853bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org				}
486f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com			} else { /* Allow -b without argument for compat. Remove
487cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org				  * this eventually so "-b {blocksize}" works */
488f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com				fprintf(stderr, "%s: -b needs a blocksize "
489f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com					"option, assuming 1024-byte blocks.\n",
490f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com					argv[0]);
491f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com				blocksize = 1024;
492f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com			}
4937938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org			break;
494f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com		case 'e':
4953bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org			force_extent++;
496f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com			if (!verbose)
4973bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org				verbose++;
498f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com			break;
499f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com		case 'k':
500f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com			blocksize = 1024;
5013bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org			break;
502f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com		case 's':
5037938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org			sync_file++;
5047938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org			break;
5053bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org		case 'v':
506f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com			verbose++;
5077938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org			break;
508f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com		case 'x':
509f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com			xattr_map++;
510f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com			break;
511f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com		case 'X':
5123bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org			ext_fmt = hex_fmt;
5133bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org			break;
5143bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org		default:
5153bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org			usage(argv[0]);
5163bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org			break;
5173bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org		}
5183bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org	if (optind == argc)
5193bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org		usage(argv[0]);
5203bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org	for (cpp=argv+optind; *cpp; cpp++)
521dda28c9bde2a34b98e1383532c210270dacb7ca8skia.committer@gmail.com		frag_report(*cpp);
5223bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org	return 0;
5233bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org}
5243bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org#endif
5253bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org