~daniel-mehrmann/e2fsprogs/master

« back to all changes in this revision

Viewing changes to misc/filefrag.c

  • Committer: Package Import Robot
  • Author(s): Michael Vogt
  • Date: 2014-10-27 09:44:27 UTC
  • mfrom: (8.4.29 sid)
  • Revision ID: package-import@ubuntu.com-20141027094427-g56dce6sg7pasdgm
Tags: 1.42.12-1ubuntu1
* Merge from Debian unstable.  Remaining changes:
  - debian/rules:
      Block pkg-create-dbgsym from operating on this package.
      Build without dietlibc-dev, which is in universe 
      Use the autotools-dev dh addon to update config.guess/config.sub for new
      ports.
  - debian/control:
      Regenerate with ./debian/rules debian/control

Show diffs side-by-side

added added

removed removed

Lines of Context:
103
103
 
104
104
        b = block;
105
105
        ret = ioctl(fd, FIBMAP, &b); /* FIBMAP takes pointer to integer */
106
 
        if (ret < 0) {
107
 
                if (errno == EPERM) {
108
 
                        fprintf(stderr, "No permission to use FIBMAP ioctl; "
109
 
                                "must have root privileges\n");
110
 
                }
111
 
        }
 
106
        if (ret < 0)
 
107
                return -errno;
112
108
        *phy_blk = b;
113
109
 
114
110
        return ret;
124
120
               "expected:");
125
121
}
126
122
 
 
123
static void print_flag(__u32 *flags, __u32 mask, char *buf, const char *name)
 
124
{
 
125
        if ((*flags & mask) == 0)
 
126
                return;
 
127
 
 
128
        strcat(buf, name);
 
129
        *flags &= ~mask;
 
130
}
 
131
 
127
132
static void print_extent_info(struct fiemap_extent *fm_extent, int cur_ex,
128
133
                              unsigned long long expected, int blk_shift,
129
134
                              ext2fs_struct_stat *st)
132
137
        unsigned long long logical_blk;
133
138
        unsigned long long ext_len;
134
139
        unsigned long long ext_blks;
 
140
        __u32 fe_flags, mask;
135
141
        char flags[256] = "";
136
142
 
137
143
        /* For inline data all offsets should be in bytes, not blocks */
141
147
        ext_len = fm_extent->fe_length >> blk_shift;
142
148
        ext_blks = (fm_extent->fe_length - 1) >> blk_shift;
143
149
        logical_blk = fm_extent->fe_logical >> blk_shift;
144
 
        physical_blk = fm_extent->fe_physical >> blk_shift;
 
150
        if (fm_extent->fe_flags & FIEMAP_EXTENT_UNKNOWN) {
 
151
                physical_blk = 0;
 
152
        } else {
 
153
                physical_blk = fm_extent->fe_physical >> blk_shift;
 
154
        }
145
155
 
146
156
        if (expected)
147
157
                sprintf(flags, ext_fmt == hex_fmt ? "%*llx: " : "%*llu: ",
149
159
        else
150
160
                sprintf(flags, "%.*s  ", physical_width, "                   ");
151
161
 
152
 
        if (fm_extent->fe_flags & FIEMAP_EXTENT_UNKNOWN)
153
 
                strcat(flags, "unknown,");
154
 
        if (fm_extent->fe_flags & FIEMAP_EXTENT_DELALLOC)
155
 
                strcat(flags, "delalloc,");
156
 
        if (fm_extent->fe_flags & FIEMAP_EXTENT_DATA_ENCRYPTED)
157
 
                strcat(flags, "encrypted,");
158
 
        if (fm_extent->fe_flags & FIEMAP_EXTENT_NOT_ALIGNED)
159
 
                strcat(flags, "not_aligned,");
160
 
        if (fm_extent->fe_flags & FIEMAP_EXTENT_DATA_INLINE)
161
 
                strcat(flags, "inline,");
162
 
        if (fm_extent->fe_flags & FIEMAP_EXTENT_DATA_TAIL)
163
 
                strcat(flags, "tail_packed,");
164
 
        if (fm_extent->fe_flags & FIEMAP_EXTENT_UNWRITTEN)
165
 
                strcat(flags, "unwritten,");
166
 
        if (fm_extent->fe_flags & FIEMAP_EXTENT_MERGED)
167
 
                strcat(flags, "merged,");
168
 
        if (fm_extent->fe_flags & FIEMAP_EXTENT_SHARED)
169
 
                strcat(flags, "shared,");
170
 
 
171
 
        if (fm_extent->fe_logical + fm_extent->fe_length >= (__u64) st->st_size)
 
162
        fe_flags = fm_extent->fe_flags;
 
163
        print_flag(&fe_flags, FIEMAP_EXTENT_LAST, flags, "last,");
 
164
        print_flag(&fe_flags, FIEMAP_EXTENT_UNKNOWN, flags, "unknown_loc,");
 
165
        print_flag(&fe_flags, FIEMAP_EXTENT_DELALLOC, flags, "delalloc,");
 
166
        print_flag(&fe_flags, FIEMAP_EXTENT_ENCODED, flags, "encoded,");
 
167
        print_flag(&fe_flags, FIEMAP_EXTENT_DATA_ENCRYPTED, flags,"encrypted,");
 
168
        print_flag(&fe_flags, FIEMAP_EXTENT_NOT_ALIGNED, flags, "not_aligned,");
 
169
        print_flag(&fe_flags, FIEMAP_EXTENT_DATA_INLINE, flags, "inline,");
 
170
        print_flag(&fe_flags, FIEMAP_EXTENT_DATA_TAIL, flags, "tail_packed,");
 
171
        print_flag(&fe_flags, FIEMAP_EXTENT_UNWRITTEN, flags, "unwritten,");
 
172
        print_flag(&fe_flags, FIEMAP_EXTENT_MERGED, flags, "merged,");
 
173
        print_flag(&fe_flags, FIEMAP_EXTENT_SHARED, flags, "shared,");
 
174
        /* print any unknown flags as hex values */
 
175
        for (mask = 1; fe_flags != 0 && mask != 0; mask <<= 1) {
 
176
                char hex[6];
 
177
 
 
178
                if ((fe_flags & mask) == 0)
 
179
                        continue;
 
180
                sprintf(hex, "%#04x,", mask);
 
181
                print_flag(&fe_flags, mask, flags, hex);
 
182
        }
 
183
 
 
184
        if (fm_extent->fe_logical + fm_extent->fe_length >= st->st_size)
172
185
                strcat(flags, "eof,");
173
186
 
174
187
        /* Remove trailing comma, if any */
175
 
        if (flags[0])
176
 
                flags[strlen(flags) - 1] = '\0';
 
188
        if (flags[0] != '\0')
 
189
                flags[strnlen(flags, sizeof(flags)) - 1] = '\0';
177
190
 
178
191
        printf(ext_fmt, cur_ex, logical_width, logical_blk,
179
192
               logical_width, logical_blk + ext_blks,
193
206
        unsigned long long expected = 0;
194
207
        unsigned long flags = 0;
195
208
        unsigned int i;
196
 
        static int fiemap_incompat_printed;
197
209
        int fiemap_header_printed = 0;
198
210
        int tot_extents = 0, n = 0;
199
211
        int last = 0;
213
225
                fiemap->fm_extent_count = count;
214
226
                rc = ioctl(fd, FS_IOC_FIEMAP, (unsigned long) fiemap);
215
227
                if (rc < 0) {
216
 
                        if (errno == EBADR && fiemap_incompat_printed == 0) {
217
 
                                printf("FIEMAP failed with unsupported "
218
 
                                       "flags %x\n", fiemap->fm_flags);
 
228
                        static int fiemap_incompat_printed;
 
229
 
 
230
                        rc = -errno;
 
231
                        if (rc == -EBADR && !fiemap_incompat_printed) {
 
232
                                fprintf(stderr, "FIEMAP failed with unknown "
 
233
                                                "flags %x\n",
 
234
                                       fiemap->fm_flags);
219
235
                                fiemap_incompat_printed = 1;
220
236
                        }
221
237
                        return rc;
313
329
                        print_extent_info(&fm_ext, *num_extents - 1,
314
330
                                          (last_block + 1) * st->st_blksize,
315
331
                                          blk_shift, st);
316
 
                        fm_ext.fe_logical = logical;
317
 
                        fm_ext.fe_physical = block * st->st_blksize;
318
332
                        fm_ext.fe_length = 0;
319
333
                        (*num_extents)++;
320
 
                } else if (verbose && last_block && (block != last_block + 1)) {
321
 
                        printf("Discontinuity: Block %ld is at %lu (was %lu)\n",
322
 
                               i, block, last_block + 1);
 
334
                } else if (last_block && (block != last_block + 1)) {
 
335
                        if (verbose)
 
336
                                printf("Discontinuity: Block %ld is at %lu (was "
 
337
                                       "%lu)\n", i, block, last_block + 1);
 
338
                        fm_ext.fe_length = 0;
323
339
                        (*num_extents)++;
324
340
                }
 
341
                fm_ext.fe_logical = logical;
 
342
                fm_ext.fe_physical = block * st->st_blksize;
325
343
                fm_ext.fe_length += st->st_blksize;
326
344
                last_block = block;
327
345
        }
333
351
        return count;
334
352
}
335
353
 
336
 
static void frag_report(const char *filename)
 
354
static int frag_report(const char *filename)
337
355
{
338
356
        static struct statfs fsinfo;
 
357
        static unsigned int blksize;
339
358
        ext2fs_struct_stat st;
340
359
        int             blk_shift;
341
360
        long            fd;
342
 
        unsigned long   numblocks;
 
361
        unsigned long long      numblocks;
343
362
        int             data_blocks_per_cyl = 1;
344
363
        int             num_extents = 1, expected = ~0;
345
364
        int             is_ext2 = 0;
346
365
        static dev_t    last_device;
347
 
        unsigned int    flags;
348
366
        int             width;
 
367
        int             rc = 0;
349
368
 
350
369
#if defined(HAVE_OPEN64) && !defined(__OSX_AVAILABLE_BUT_DEPRECATED)
351
370
        fd = open64(filename, O_RDONLY);
353
372
        fd = open(filename, O_RDONLY);
354
373
#endif
355
374
        if (fd < 0) {
 
375
                rc = -errno;
356
376
                perror("open");
357
 
                return;
 
377
                return rc;
358
378
        }
359
379
 
360
380
#if defined(HAVE_FSTAT64) && !defined(__OSX_AVAILABLE_BUT_DEPRECATED)
362
382
#else
363
383
        if (fstat(fd, &st) < 0) {
364
384
#endif
365
 
                close(fd);
 
385
                rc = -errno;
366
386
                perror("stat");
367
 
                return;
 
387
                goto out_close;
368
388
        }
369
389
 
370
390
        if (last_device != st.st_dev) {
371
391
                if (fstatfs(fd, &fsinfo) < 0) {
372
 
                        close(fd);
 
392
                        rc = -errno;
373
393
                        perror("fstatfs");
374
 
                        return;
 
394
                        goto out_close;
375
395
                }
 
396
                if (ioctl(fd, FIGETBSZ, &blksize) < 0)
 
397
                        blksize = fsinfo.f_bsize;
376
398
                if (verbose)
377
399
                        printf("Filesystem type is: %lx\n",
378
 
                               (unsigned long) fsinfo.f_type);
379
 
        }
380
 
        st.st_blksize = fsinfo.f_bsize;
381
 
        if (ioctl(fd, EXT3_IOC_GETFLAGS, &flags) < 0)
382
 
                flags = 0;
383
 
        if (!(flags & EXT4_EXTENTS_FL) &&
384
 
            ((fsinfo.f_type == 0xef51) || (fsinfo.f_type == 0xef52) ||
385
 
             (fsinfo.f_type == 0xef53)))
386
 
                is_ext2++;
 
400
                               (unsigned long)fsinfo.f_type);
 
401
        }
 
402
        st.st_blksize = blksize;
 
403
        if (fsinfo.f_type == 0xef51 || fsinfo.f_type == 0xef52 ||
 
404
            fsinfo.f_type == 0xef53) {
 
405
                unsigned int    flags;
 
406
 
 
407
                if (ioctl(fd, EXT3_IOC_GETFLAGS, &flags) == 0 &&
 
408
                    !(flags & EXT4_EXTENTS_FL))
 
409
                        is_ext2 = 1;
 
410
        }
387
411
 
388
412
        if (is_ext2) {
389
 
                long cylgroups = div_ceil(fsinfo.f_blocks, fsinfo.f_bsize * 8);
 
413
                long cylgroups = div_ceil(fsinfo.f_blocks, blksize * 8);
390
414
 
391
415
                if (verbose && last_device != st.st_dev)
392
416
                        printf("Filesystem cylinder groups approximately %ld\n",
393
417
                               cylgroups);
394
418
 
395
 
                data_blocks_per_cyl = fsinfo.f_bsize * 8 -
 
419
                data_blocks_per_cyl = blksize * 8 -
396
420
                                        (fsinfo.f_files / 8 / cylgroups) - 3;
397
421
        }
398
422
        last_device = st.st_dev;
401
425
        if (width > physical_width)
402
426
                physical_width = width;
403
427
 
404
 
        numblocks = (st.st_size + fsinfo.f_bsize - 1) / fsinfo.f_bsize;
 
428
        numblocks = (st.st_size + blksize - 1) / blksize;
405
429
        if (blocksize != 0)
406
430
                blk_shift = int_log2(blocksize);
407
431
        else
408
 
                blk_shift = int_log2(fsinfo.f_bsize);
 
432
                blk_shift = int_log2(blksize);
409
433
 
410
434
        width = int_log10(numblocks);
411
435
        if (width > logical_width)
412
436
                logical_width = width;
413
437
        if (verbose)
414
 
                printf("File size of %s is %llu (%lu block%s of %d bytes)\n",
 
438
                printf("File size of %s is %llu (%llu block%s of %d bytes)\n",
415
439
                       filename, (unsigned long long)st.st_size,
416
 
                       numblocks * fsinfo.f_bsize >> blk_shift,
 
440
                       numblocks * blksize >> blk_shift,
417
441
                       numblocks == 1 ? "" : "s", 1 << blk_shift);
418
442
 
419
 
        if (force_bmap ||
420
 
            filefrag_fiemap(fd, blk_shift, &num_extents, &st) != 0) {
 
443
        if (!force_bmap) {
 
444
                rc = filefrag_fiemap(fd, blk_shift, &num_extents, &st);
 
445
                expected = 0;
 
446
        }
 
447
 
 
448
        if (force_bmap || rc < 0) { /* FIEMAP failed, try FIBMAP instead */
421
449
                expected = filefrag_fibmap(fd, blk_shift, &num_extents,
422
450
                                           &st, numblocks, is_ext2);
423
451
                if (expected < 0) {
424
 
                        if (errno == EINVAL || errno == ENOTTY) {
 
452
                        if (expected == -EINVAL || expected == -ENOTTY) {
425
453
                                fprintf(stderr, "%s: FIBMAP unsupported\n",
426
454
                                        filename);
427
 
                        } else if (errno != EPERM) {
 
455
                        } else if (expected == -EPERM) {
 
456
                                fprintf(stderr,
 
457
                                        "%s: FIBMAP requires root privileges\n",
 
458
                                        filename);
 
459
                        } else {
428
460
                                fprintf(stderr, "%s: FIBMAP error: %s",
429
 
                                        filename, strerror(errno));
 
461
                                        filename, strerror(expected));
430
462
                        }
 
463
                        rc = expected;
431
464
                        goto out_close;
 
465
                } else {
 
466
                        rc = 0;
432
467
                }
433
468
                expected = expected / data_blocks_per_cyl + 1;
434
469
        }
445
480
                fputc('\n', stdout);
446
481
out_close:
447
482
        close(fd);
 
483
 
 
484
        return rc;
448
485
}
449
486
 
450
487
static void usage(const char *progname)
457
494
int main(int argc, char**argv)
458
495
{
459
496
        char **cpp;
460
 
        int c;
 
497
        int rc = 0, c;
461
498
 
462
 
        while ((c = getopt(argc, argv, "Bb::eksvxX")) != EOF)
 
499
        while ((c = getopt(argc, argv, "Bb::eksvxX")) != EOF) {
463
500
                switch (c) {
464
501
                case 'B':
465
502
                        force_bmap++;
518
555
                        usage(argv[0]);
519
556
                        break;
520
557
                }
 
558
        }
 
559
 
521
560
        if (optind == argc)
522
561
                usage(argv[0]);
523
 
        for (cpp=argv+optind; *cpp; cpp++)
524
 
                frag_report(*cpp);
525
 
        return 0;
 
562
 
 
563
        for (cpp = argv + optind; *cpp != '\0'; cpp++) {
 
564
                int rc2 = frag_report(*cpp);
 
565
 
 
566
                if (rc2 < 0 && rc == 0)
 
567
                        rc = rc2;
 
568
        }
 
569
 
 
570
        return -rc;
526
571
}
527
572
#endif