diff --git a/sbin/dumpfs/dumpfs.8 b/sbin/dumpfs/dumpfs.8 index 8879f783e3cb..53e7f62baf3d 100644 --- a/sbin/dumpfs/dumpfs.8 +++ b/sbin/dumpfs/dumpfs.8 @@ -36,15 +36,18 @@ .Nd dump file system information .Sh SYNOPSIS .Nm +.Op Fl f .Op Fl m .Ar filesys | device .Sh DESCRIPTION The .Nm utility prints out the super block and cylinder group information -for the file system or special device specified, unless +for the file system or special device specified, unless the +.Fl f +or .Fl m -is specified. +flag is specified. The listing is very long and detailed. This command is useful mostly for finding out certain file system @@ -52,6 +55,15 @@ information such as the file system block size and minimum free space percentage. .Pp If +.Fl f +is specified, a sorted list of all free fragments and free fragment ranges, +as represented in cylinder group block free lists, is printed. +If the flag is specified twice, contiguous free fragments are not collapsed +into ranges and instead printed in a simple list. +Fragment numbers may be converted to raw byte offsets by multiplying by the +fragment size, which may be useful when recovering deleted data. +.Pp +If .Fl m is specified, a .Xr newfs 8 diff --git a/sbin/dumpfs/dumpfs.c b/sbin/dumpfs/dumpfs.c index e0b809e1b5e0..14f6ea2c0203 100644 --- a/sbin/dumpfs/dumpfs.c +++ b/sbin/dumpfs/dumpfs.c @@ -1,4 +1,10 @@ /* + * Copyright (c) 2009 Robert N. M. Watson + * All rights reserved. + * + * This software was developed at the University of Cambridge Computer + * Laboratory with support from a grant from Google, Inc. + * * Copyright (c) 2002 Networks Associates Technology, Inc. * All rights reserved. * @@ -74,8 +80,11 @@ struct uufsd disk; int dumpfs(const char *); int dumpcg(void); +int dumpfreespace(const char *, int); +void dumpfreespacecg(int); int marshal(const char *); void pbits(void *, int); +void pblklist(void *, int, off_t, int); void ufserr(const char *); void usage(void) __dead2; @@ -83,12 +92,15 @@ int main(int argc, char *argv[]) { const char *name; - int ch, domarshal, eval; + int ch, dofreespace, domarshal, eval; - domarshal = eval = 0; + dofreespace = domarshal = eval = 0; - while ((ch = getopt(argc, argv, "m")) != -1) { + while ((ch = getopt(argc, argv, "fm")) != -1) { switch (ch) { + case 'f': + dofreespace++; + break; case 'm': domarshal = 1; break; @@ -102,6 +114,10 @@ main(int argc, char *argv[]) if (argc < 1) usage(); + if (dofreespace && domarshal) + usage(); + if (dofreespace > 2) + usage(); while ((name = *argv++) != NULL) { if (ufs_disk_fillout(&disk, name) == -1) { @@ -109,7 +125,9 @@ main(int argc, char *argv[]) eval |= 1; continue; } - if (domarshal) + if (dofreespace) + eval |= dumpfreespace(name, dofreespace); + else if (domarshal) eval |= marshal(name); else eval |= dumpfs(name); @@ -332,6 +350,30 @@ dumpcg(void) return (0); } +int +dumpfreespace(const char *name, int fflag) +{ + int i; + + while ((i = cgread(&disk)) != 0) { + if (i == -1) + goto err; + dumpfreespacecg(fflag); + } + return (0); +err: + ufserr(name); + return (1); +} + +void +dumpfreespacecg(int fflag) +{ + + pblklist(cg_blksfree(&acg), afs.fs_fpg, disk.d_lcg * afs.fs_fpg, + fflag); +} + int marshal(const char *name) { @@ -400,6 +442,27 @@ pbits(void *vp, int max) printf("\n"); } +void +pblklist(void *vp, int max, off_t offset, int fflag) +{ + int i, j; + char *p; + + for (i = 0, p = vp; i < max; i++) { + if (isset(p, i)) { + printf("%jd", (intmax_t)(i + offset)); + if (fflag < 2) { + j = i; + while ((i+1)