svn commit: r204133 - in user/kib/vm6/tools/tools/ufs: . fragc
Konstantin Belousov
kib at FreeBSD.org
Sat Feb 20 16:38:49 UTC 2010
Author: kib
Date: Sat Feb 20 16:38:48 2010
New Revision: 204133
URL: http://svn.freebsd.org/changeset/base/204133
Log:
Tool to calculate fragmentation of the UFS volume
Added:
user/kib/vm6/tools/tools/ufs/
user/kib/vm6/tools/tools/ufs/fragc/
user/kib/vm6/tools/tools/ufs/fragc/fragc.c
Added: user/kib/vm6/tools/tools/ufs/fragc/fragc.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ user/kib/vm6/tools/tools/ufs/fragc/fragc.c Sat Feb 20 16:38:48 2010 (r204133)
@@ -0,0 +1,215 @@
+/* $Id: fragc.c,v 1.9 2010/02/07 14:32:22 kostik Exp kostik $ */
+
+/* /usr/local/opt/gcc-4.4.3/bin/gcc -g -Wall -Wextra -O -o fragc fragc.c -lufs */
+
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <ufs/ufs/ufsmount.h>
+#include <ufs/ufs/dinode.h>
+#include <ufs/ffs/fs.h>
+#include <libufs.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static const int blocksz = 512;
+
+static int verbose;
+
+static void
+usage(void)
+{
+
+ fprintf(stderr, "Usage: fragc [-v] devname\n");
+}
+
+static ufs2_daddr_t blks_total;
+static ufs2_daddr_t blks_breaks;
+
+static void
+block_pair(struct fs *fs, ufs2_daddr_t *prev, ufs2_daddr_t curr)
+{
+
+ blks_total++;
+ if (curr != 0) {
+ if (*prev != 0 &&
+ (*prev) + fs->fs_bsize / fs->fs_fsize != curr) {
+ blks_breaks++;
+ if (verbose)
+ putchar('|');
+ }
+ if (verbose)
+ printf(" %jd", (intmax_t)curr);
+ }
+ *prev = curr;
+}
+
+static void
+count_indir(struct uufsd *u, struct fs *fs, int level, int maxlevel,
+ ufs2_daddr_t ib, ufs2_daddr_t *prev)
+{
+ ufs2_daddr_t *b;
+ unsigned i;
+
+ if (ib == 0)
+ return;
+ b = malloc(fs->fs_bsize);
+ if (bread(u, ib * fs->fs_fsize / blocksz, b, fs->fs_bsize) == -1) {
+ printf("\nRead block %jd: %s\n", (intmax_t)ib, u->d_error);
+ goto out;
+ }
+ for (i = 0; i < fs->fs_bsize / sizeof(ufs2_daddr_t); i++) {
+ if (level == maxlevel)
+ block_pair(fs, prev, b[i]);
+ else
+ count_indir(u, fs, level + 1, maxlevel, b[i], prev);
+ }
+ out:
+ free(b);
+}
+
+static void
+count_ino_ufs1(struct uufsd *u, struct fs *fs, struct ufs1_dinode *dp)
+{
+ ufs2_daddr_t prev;
+ unsigned i;
+
+ if (dp->di_size == 0)
+ return;
+ if ((dp->di_mode & IFMT) == IFLNK && dp->di_size <
+ (u_int64_t)fs->fs_maxsymlinklen)
+ return;
+
+ prev = 0;
+ for (i = 0; i < NDADDR; i++)
+ block_pair(fs, &prev, dp->di_db[i]);
+ for (i = 0; i < NIADDR; i++) {
+ if (0 && verbose)
+ printf(" [%d]", dp->di_ib[i]);
+ count_indir(u, fs, 0, i, dp->di_ib[i], &prev);
+ }
+}
+
+static void
+count_ino_ufs2(struct uufsd *u, struct fs *fs, struct ufs2_dinode *dp)
+{
+ ufs2_daddr_t prev;
+ unsigned i;
+
+ if (dp->di_size == 0)
+ return;
+ if ((dp->di_mode & IFMT) == IFLNK && dp->di_size <
+ (u_int64_t)fs->fs_maxsymlinklen)
+ return;
+
+ prev = 0;
+ for (i = 0; i < NDADDR; i++)
+ block_pair(fs, &prev, dp->di_db[i]);
+ for (i = 0; i < NIADDR; i++) {
+ if (0 && verbose)
+ printf(" [%jd]", (intmax_t)(dp->di_ib[i]));
+ count_indir(u, fs, 0, i, dp->di_ib[i], &prev);
+ }
+}
+
+static void
+frag_calc(struct uufsd *u)
+{
+ struct fs *fs;
+ struct cg *cg;
+ void *dino;
+ int32_t cgno;
+ uint32_t ino, inoused, cgino, next_cg_ino;
+ int mode;
+ u_int8_t *cp;
+
+ fs = &u->d_fs;
+ if (verbose)
+ printf("%s UFS%d\n", u->d_name, u->d_ufs);
+ ino = 0;
+ for (cgno = 0; cgread(u); cgno++) {
+ cg = &u->d_cg;
+ if (u->d_ufs == 1)
+ inoused = fs->fs_ipg;
+ else
+ inoused = cg->cg_initediblk;
+ if (verbose)
+ printf("cg %d inodes %u\n", cgno, inoused);
+ cp = cg_inosused(cg);
+ next_cg_ino = ino + fs->fs_ipg;
+ for (cgino = 0; cgino < inoused; cgino++, ino++) {
+ if ((cp[cgino / CHAR_BIT] & (1 << (cgino % CHAR_BIT)))
+ != 0 && ino != 0 && ino != 1) {
+ if (verbose)
+ printf(" ino %u:", ino);
+ if (getino(u, &dino, ino, &mode) == -1) {
+ printf("\nReading ino %u: %s\n",
+ ino, u->d_error);
+ return;
+ }
+ if (mode == 0) {
+ printf(
+"\nIno %u/%u is allocated in bitmap, but mode is 0\n",
+ ino, ino % fs->fs_ipg);
+ continue;
+ }
+ if (mode != IFDIR && mode != IFREG &&
+ mode != IFLNK)
+ continue;
+
+ if (u->d_ufs == 1)
+ count_ino_ufs1(u, fs, dino);
+ else
+ count_ino_ufs2(u, fs, dino);
+ if (verbose)
+ putchar('\n');
+ }
+ }
+ ino = next_cg_ino;
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct uufsd ufsd;
+ int c;
+
+ verbose = 0;
+ while ((c = getopt(argc, argv, "hv")) != -1) {
+ switch (c) {
+ case 'h':
+ usage();
+ return (0);
+ case 'v':
+ verbose = 1;
+ break;
+ default:
+ usage();
+ return (2);
+ }
+ }
+ if (optind + 1 != argc) {
+ usage();
+ return (2);
+ }
+
+ if (ufs_disk_fillout(&ufsd, argv[optind]) == -1) {
+ fprintf(stderr, "Fillout: %s\n", ufsd.d_error);
+ return (1);
+ }
+
+ frag_calc(&ufsd);
+
+ if (ufs_disk_close(&ufsd) == -1) {
+ fprintf(stderr, "Disk close: %s\n", ufsd.d_error);
+ return (1);
+ }
+
+ printf("Total %jd data blocks, %jd breaks, %02.2f%% fragmentation.\n",
+ (intmax_t)blks_total, (intmax_t)blks_breaks,
+ (double)blks_breaks * 100.0 / blks_total);
+
+ return (0);
+}
More information about the svn-src-user
mailing list