119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * filefrag.c -- report if a particular file is fragmented 33984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * 419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Copyright 2003 by Theodore Ts'o. 519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * %Begin-Header% 719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This file may be redistributed under the terms of the GNU Public 819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * License. 919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * %End-Header% 1019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 1119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 1219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifndef __linux__ 1319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <stdio.h> 1419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <stdlib.h> 153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#include <unistd.h> 1619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 1719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectint main(void) { 1819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fputs("This program is only supported on Linux!\n", stderr); 1919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project exit(EXIT_FAILURE); 2019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 2119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#else 2219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#define _LARGEFILE64_SOURCE 2319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 2419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <stdio.h> 2519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <stdlib.h> 2619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <unistd.h> 2719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <string.h> 2819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <time.h> 2919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <fcntl.h> 3019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <errno.h> 3119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef HAVE_GETOPT_H 3219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <getopt.h> 3319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#else 3419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectextern char *optarg; 3519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectextern int optind; 3619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 3719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <sys/types.h> 3819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <sys/stat.h> 3919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <sys/vfs.h> 4019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <sys/ioctl.h> 4119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <linux/fd.h> 423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#include <ext2fs/ext2_types.h> 433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#include <ext2fs/fiemap.h> 4419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 4519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectint verbose = 0; 463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtint no_bs = 0; /* Don't use the files blocksize, use 1K blocksize */ 473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtint sync_file = 0; /* fsync file before getting the mapping */ 483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtint xattr_map = 0; /* get xattr mapping */ 493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtint force_bmap = 0; 503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtint logical_width = 12; 513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtint physical_width = 14; 523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtunsigned long long filesize; 533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#define FILEFRAG_FIEMAP_FLAGS_COMPAT (FIEMAP_FLAG_SYNC | FIEMAP_FLAG_XATTR) 5519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#define FIBMAP _IO(0x00, 1) /* bmap access */ 573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#define FIGETBSZ _IO(0x00, 2) /* get the block size used for bmap */ 583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#define FS_IOC_FIEMAP _IOWR('f', 11, struct fiemap) 5919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */ 6119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#define EXT3_IOC_GETFLAGS _IOR('f', 1, long) 6219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic int int_log2(int arg) 643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{ 653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt int l = 0; 663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt arg >>= 1; 683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt while (arg) { 693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt l++; 703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt arg >>= 1; 713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return l; 733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt} 743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic int int_log10(unsigned long long arg) 763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{ 773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt int l = 0; 783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt arg = arg / 10; 803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt while (arg) { 813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt l++; 823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt arg = arg / 10; 833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return l; 853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt} 863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 8719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic unsigned int div_ceil(unsigned int a, unsigned int b) 8819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 8919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!a) 9019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 9119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return ((a - 1) / b) + 1; 9219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 9319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic int get_bmap(int fd, unsigned long block, unsigned long *phy_blk) 9519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 9619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int ret; 9719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project unsigned int b; 9819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 9919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project b = block; 1003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ret = ioctl(fd, FIBMAP, &b); /* FIBMAP takes pointer to integer */ 10119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (ret < 0) { 10219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (errno == EPERM) { 1033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt fprintf(stderr, "No permission to use FIBMAP ioctl; " 1043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt "must have root privileges\n"); 10519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project exit(1); 10619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 10719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project perror("FIBMAP"); 10819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 1093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *phy_blk = b; 1103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return ret; 1123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt} 1133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic void print_extent_info(struct fiemap_extent *fm_extent, int cur_ex, 1153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt unsigned long long expected, int blk_shift) 1163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{ 1173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt __u64 phy_blk; 1183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt unsigned long long logical_blk; 1193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt unsigned long ext_len; 1203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt char flags[256] = ""; 1213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt /* For inline data all offsets should be in terms of bytes, not blocks */ 1233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (fm_extent->fe_flags & FIEMAP_EXTENT_DATA_INLINE) 1243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt blk_shift = 0; 1253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ext_len = fm_extent->fe_length >> blk_shift; 1273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt logical_blk = fm_extent->fe_logical >> blk_shift; 1283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt phy_blk = fm_extent->fe_physical >> blk_shift; 1293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (fm_extent->fe_flags & FIEMAP_EXTENT_UNKNOWN) 1313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt strcat(flags, "unknown,"); 1323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (fm_extent->fe_flags & FIEMAP_EXTENT_DELALLOC) 1333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt strcat(flags, "delalloc,"); 1343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (fm_extent->fe_flags & FIEMAP_EXTENT_DATA_ENCRYPTED) 1353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt strcat(flags, "encrypted,"); 1363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (fm_extent->fe_flags & FIEMAP_EXTENT_NOT_ALIGNED) 1373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt strcat(flags, "not_aligned,"); 1383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (fm_extent->fe_flags & FIEMAP_EXTENT_DATA_INLINE) 1393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt strcat(flags, "inline,"); 1403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (fm_extent->fe_flags & FIEMAP_EXTENT_DATA_TAIL) 1413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt strcat(flags, "tail_packed,"); 1423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (fm_extent->fe_flags & FIEMAP_EXTENT_UNWRITTEN) 1433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt strcat(flags, "unwritten,"); 1443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (fm_extent->fe_flags & FIEMAP_EXTENT_MERGED) 1453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt strcat(flags, "merged,"); 1463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (fm_extent->fe_logical + fm_extent->fe_length >= filesize) 1483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt strcat(flags, "eof,"); 1493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt /* Remove trailing comma, if any */ 1513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (flags[0]) 1523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt flags[strlen(flags) - 1] = '\0'; 1533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (expected) 1553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt printf("%4d %*llu %*llu %*llu %6lu %s\n", 1563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt cur_ex, logical_width, logical_blk, 1573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt physical_width, phy_blk, physical_width, expected, 1583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ext_len, flags); 1593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt else 1603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt printf("%4d %*llu %*llu %*s %6lu %s\n", 1613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt cur_ex, logical_width, logical_blk, 1623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt physical_width, phy_blk, physical_width, "", 1633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ext_len, flags); 1643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt} 1653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic int filefrag_fiemap(int fd, int blk_shift, int *num_extents) 1673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{ 1683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt char buf[4096] = ""; 1693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt struct fiemap *fiemap = (struct fiemap *)buf; 1703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt struct fiemap_extent *fm_ext = &fiemap->fm_extents[0]; 1713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt int count = (sizeof(buf) - sizeof(*fiemap)) / 1723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt sizeof(struct fiemap_extent); 1733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt unsigned long long last_blk = 0; 1743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt unsigned long flags = 0; 1753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt unsigned int i; 1763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt static int fiemap_incompat_printed; 1773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt int fiemap_header_printed = 0; 1783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt int tot_extents = 1, n = 0; 1793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt int last = 0; 1803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt int rc; 1813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt fiemap->fm_length = ~0ULL; 1833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt memset(fiemap, 0, sizeof(struct fiemap)); 1853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (!verbose) 1873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt count = 0; 1883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (sync_file) 1903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt flags |= FIEMAP_FLAG_SYNC; 1913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (xattr_map) 1933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt flags |= FIEMAP_FLAG_XATTR; 1943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt do { 1963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt fiemap->fm_length = ~0ULL; 1973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt fiemap->fm_flags = flags; 1983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt fiemap->fm_extent_count = count; 1993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt rc = ioctl(fd, FS_IOC_FIEMAP, (unsigned long) fiemap); 2003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (rc < 0) { 2013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (errno == EBADR && fiemap_incompat_printed == 0) { 2023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt printf("FIEMAP failed with unsupported " 2033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt "flags %x\n", fiemap->fm_flags); 2043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt fiemap_incompat_printed = 1; 2053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 2063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return rc; 2073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 2083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 2093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (verbose && !fiemap_header_printed) { 2103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt printf(" ext %*s %*s %*s length flags\n", logical_width, 2113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt "logical", physical_width, "physical", 2123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt physical_width, "expected"); 2133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt fiemap_header_printed = 1; 2143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 2153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 2163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (!verbose) { 2173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *num_extents = fiemap->fm_mapped_extents; 2183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt goto out; 2193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 2203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 2213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt /* If 0 extents are returned, then more ioctls are not needed */ 2223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (fiemap->fm_mapped_extents == 0) 2233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt break; 2243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 2253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt for (i = 0; i < fiemap->fm_mapped_extents; i++) { 2263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt __u64 phy_blk, logical_blk; 2273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt unsigned long ext_len; 2283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 2293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt phy_blk = fm_ext[i].fe_physical >> blk_shift; 2303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ext_len = fm_ext[i].fe_length >> blk_shift; 2313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt logical_blk = fm_ext[i].fe_logical >> blk_shift; 2323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 2333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (logical_blk && phy_blk != last_blk + 1) 2343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt tot_extents++; 2353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt else 2363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt last_blk = 0; 2373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt print_extent_info(&fm_ext[i], n, last_blk, blk_shift); 2383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 2393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt last_blk = phy_blk + ext_len - 1; 2403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (fm_ext[i].fe_flags & FIEMAP_EXTENT_LAST) 2413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt last = 1; 2423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt n++; 2433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 2443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 2453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt fiemap->fm_start = (fm_ext[i-1].fe_logical + 2463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt fm_ext[i-1].fe_length); 2473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } while (last == 0); 2483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 2493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *num_extents = tot_extents; 2503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtout: 2513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return 0; 25219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 25319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 25419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#define EXT2_DIRECT 12 25519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 25619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void frag_report(const char *filename) 25719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 25819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct statfs fsinfo; 25919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef HAVE_FSTAT64 26019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct stat64 fileinfo; 26119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#else 26219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct stat fileinfo; 26319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 26419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int bs; 26519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project long fd; 2663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt unsigned long block, last_block = 0, numblocks, i, count; 26719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project long bpib; /* Blocks per indirect block */ 26819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project long cylgroups; 2693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt int num_extents = 0, expected; 27019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int is_ext2 = 0; 2713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt static int once = 1; 27219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project unsigned int flags; 2733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt int rc; 2743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 2753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef HAVE_OPEN64 2763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt fd = open64(filename, O_RDONLY); 2773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#else 2783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt fd = open(filename, O_RDONLY); 2793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif 2803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (fd < 0) { 2813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt perror("open"); 2823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return; 2833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 28419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 28519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (statfs(filename, &fsinfo) < 0) { 28619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project perror("statfs"); 28719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 28819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 28919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef HAVE_FSTAT64 29019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (stat64(filename, &fileinfo) < 0) { 29119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#else 29219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (stat(filename, &fileinfo) < 0) { 29319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 29419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project perror("stat"); 29519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 29619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 2973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (ioctl(fd, EXT3_IOC_GETFLAGS, &flags) < 0) 2983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt flags = 0; 2993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (!(flags & EXT4_EXTENTS_FL) && 3003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ((fsinfo.f_type == 0xef51) || (fsinfo.f_type == 0xef52) || 3013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt (fsinfo.f_type == 0xef53))) 30219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project is_ext2++; 3033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (verbose && once) 3043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt printf("Filesystem type is: %lx\n", 30519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project (unsigned long) fsinfo.f_type); 3063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 30719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project cylgroups = div_ceil(fsinfo.f_blocks, fsinfo.f_bsize*8); 3083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (verbose && is_ext2 && once) 3093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt printf("Filesystem cylinder groups is approximately %ld\n", 31019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project cylgroups); 3113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 3123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt physical_width = int_log10(fsinfo.f_blocks); 3133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (physical_width < 8) 3143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt physical_width = 8; 3153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 31619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (ioctl(fd, FIGETBSZ, &bs) < 0) { /* FIGETBSZ takes an int */ 31719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project perror("FIGETBSZ"); 31819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project close(fd); 31919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 32019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 3213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 3223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (no_bs) 3233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt bs = 1024; 3243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 32519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project bpib = bs / 4; 32619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project numblocks = (fileinfo.st_size + (bs-1)) / bs; 3273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt logical_width = int_log10(numblocks); 3283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (logical_width < 7) 3293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt logical_width = 7; 3303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt filesize = (long long)fileinfo.st_size; 3313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (verbose) 3323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt printf("File size of %s is %lld (%ld block%s, blocksize %d)\n", 3333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt filename, (long long) fileinfo.st_size, numblocks, 3343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt numblocks == 1 ? "" : "s", bs); 3353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (force_bmap || 3363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt filefrag_fiemap(fd, int_log2(bs), &num_extents) != 0) { 3373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt for (i = 0, count = 0; i < numblocks; i++) { 3383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (is_ext2 && last_block) { 3393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (((i-EXT2_DIRECT) % bpib) == 0) 3403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt last_block++; 3413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (((i-EXT2_DIRECT-bpib) % (bpib*bpib)) == 0) 3423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt last_block++; 3433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (((i-EXT2_DIRECT-bpib-bpib*bpib) % 3443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt (((__u64) bpib)*bpib*bpib)) == 0) 3453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt last_block++; 3463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 3473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt rc = get_bmap(fd, i, &block); 3483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (block == 0) 3493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt continue; 3503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (!num_extents) 3513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt num_extents++; 3523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt count++; 3533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (last_block && (block != last_block+1) ) { 3543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (verbose) 3553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt printf("Discontinuity: Block %ld is at " 3563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt "%lu (was %lu)\n", 3573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt i, block, last_block+1); 3583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt num_extents++; 3593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 3603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt last_block = block; 36119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 36219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 3633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (num_extents == 1) 36419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project printf("%s: 1 extent found", filename); 36519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project else 3663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt printf("%s: %d extents found", filename, num_extents); 3673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt expected = (count/((bs*8)-(fsinfo.f_files/8/cylgroups)-3))+1; 3683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (is_ext2 && expected < num_extents) 36919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project printf(", perfection would be %d extent%s\n", expected, 37019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project (expected>1) ? "s" : ""); 37119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project else 37219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fputc('\n', stdout); 37319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project close(fd); 3743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt once = 0; 37519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 37619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 37719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void usage(const char *progname) 37819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 3793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt fprintf(stderr, "Usage: %s [-Bbvsx] file ...\n", progname); 38019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project exit(1); 38119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 38219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 38319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectint main(int argc, char**argv) 38419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 38519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char **cpp; 38619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int c; 38719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 3883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt while ((c = getopt(argc, argv, "Bbsvx")) != EOF) 38919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project switch (c) { 3903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt case 'B': 3913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt force_bmap++; 3923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt break; 3933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt case 'b': 3943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt no_bs++; 3953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt break; 39619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project case 'v': 39719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project verbose++; 39819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project break; 3993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt case 's': 4003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt sync_file++; 4013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt break; 4023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt case 'x': 4033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt xattr_map++; 4043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt break; 40519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project default: 40619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project usage(argv[0]); 40719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project break; 40819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 40919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (optind == argc) 41019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project usage(argv[0]); 4113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt for (cpp=argv+optind; *cpp; cpp++) 41219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project frag_report(*cpp); 41319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 41419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 41519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 416