[Ocfs2-tools-devel] [PATCH 1/4] Borrow basic structure from fsck
Goldwyn Rodrigues
rgoldwyn at gmail.com
Wed Mar 17 18:27:41 PDT 2010
Signed-off-by: Goldwyn Rodrigues <rgoldwyn at suse.de>
---
defrag.ocfs2/Makefile | 37 ++++++
defrag.ocfs2/defrag.c | 273 +++++++++++++++++++++++++++++++++++++++++
defrag.ocfs2/include/defrag.h | 46 +++++++
3 files changed, 356 insertions(+), 0 deletions(-)
create mode 100644 defrag.ocfs2/Makefile
create mode 100644 defrag.ocfs2/defrag.c
create mode 100644 defrag.ocfs2/include/defrag.h
diff --git a/defrag.ocfs2/Makefile b/defrag.ocfs2/Makefile
new file mode 100644
index 0000000..b59c6a4
--- /dev/null
+++ b/defrag.ocfs2/Makefile
@@ -0,0 +1,37 @@
+TOPDIR = ..
+
+include $(TOPDIR)/Preamble.make
+
+sbindir = $(root_sbindir)
+SBIN_PROGRAMS = defrag.ocfs2
+
+DEFINES += -DVERSION=\"$(VERSION)\"
+
+INCLUDES = -I$(TOPDIR)/include -Iinclude -I$(TOPDIR)/libocfs2
+LIBOCFS2_LIBS = -L$(TOPDIR)/libocfs2 -locfs2
+LIBOCFS2_DEPS = $(TOPDIR)/libocfs2/libocfs2.a
+
+CFLAGS += -g
+
+CFILES = defrag.c
+
+HFILES = include/defrag.h
+
+
+OBJS = $(subst .c,.o,$(CFILES))
+
+DIST_FILES = $(CFILES) $(HFILES) $(addsuffix .in,$(MANS))
+DIST_RULES = dist-subdircreate
+
+dist-subdircreate:
+ $(TOPDIR)/mkinstalldirs $(DIST_DIR)/include
+
+defrag.ocfs2: $(OBJS) $(LIBOCFS2_DEPS)
+ $(LINK) $(LIBOCFS2_LIBS) $(COM_ERR_LIBS)
+
+CLEAN_RULES += defrag-clean
+.PHONY: defrag-clean
+defrag-clean:
+ rm -f prompt-codes.h
+
+include $(TOPDIR)/Postamble.make
diff --git a/defrag.ocfs2/defrag.c b/defrag.ocfs2/defrag.c
new file mode 100644
index 0000000..cf81aa6
--- /dev/null
+++ b/defrag.ocfs2/defrag.c
@@ -0,0 +1,273 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * Copyright (C) 1993-2004 Theodore Ts'o.
+ * Copyright (C) 2004 Oracle. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License, version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ *
+ */
+#include <getopt.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <inttypes.h>
+#include <signal.h>
+#include <libgen.h>
+
+#include "defrag.h"
+
+
+int verbose = 0;
+char *whoami = "defrag.ocfs2";
+static struct defrag_state dfrag;
+
+extern int opterr, optind;
+extern char *optarg;
+
+static errcode_t check_superblock(struct defrag_state *dst)
+{
+ struct ocfs2_dinode *di = dst->dst_fs->fs_super;
+ struct ocfs2_super_block *sb = OCFS2_RAW_SB(di);
+ errcode_t ret = 0;
+
+ if (sb->s_max_slots == 0) {
+ printf("The superblock max_slots field is set to 0.\n");
+ ret = OCFS2_ET_CORRUPT_SUPERBLOCK;
+ }
+
+ return ret;
+}
+
+static void scale_time(time_t secs, unsigned *scaled, char **units)
+{
+ if (secs < 60) {
+ *units = "seconds";
+ goto done;
+ }
+ secs /= 60;
+
+ if (secs < 60) {
+ *units = "minutes";
+ goto done;
+ }
+ secs /= 60;
+
+ if (secs < 24) {
+ *units = "hours";
+ goto done;
+ }
+ secs /= 24;
+ *units = "days";
+
+done:
+ *scaled = secs;
+}
+
+static int fs_clean(struct ocfs2_super_block *sb, char *filename)
+{
+ time_t now = time(NULL);
+ time_t next = sb->s_lastcheck + sb->s_checkinterval;
+
+ if (sb->s_checkinterval > 0 && now >= next) {
+ unsigned scaled_time;
+ char *scaled_units;
+
+ scale_time(now - sb->s_lastcheck, &scaled_time, &scaled_units);
+ fprintf(stderr, "Filesystem has gone %u %s without"
+ "being checked\n", scaled_time, scaled_units);
+ return 0;
+ }
+
+ if (sb->s_mnt_count > 0) {
+ fprintf(stderr, "Filesystem mounted for %u mounts "
+ "without fsck. ", sb->s_mnt_count);
+ return 0;
+ }
+
+ return 1;
+}
+
+static void print_label(struct defrag_state *dst)
+{
+ unsigned char *label = OCFS2_RAW_SB(dst->dst_fs->fs_super)->s_label;
+ size_t i, max = sizeof(OCFS2_RAW_SB(dst->dst_fs->fs_super)->s_label);
+
+ for (i = 0; i < max && label[i]; i++) {
+ if (isprint(label[i]))
+ printf("%c", label[i]);
+ else
+ printf(".");
+ }
+ if (i == 0)
+ printf("<NONE>");
+
+ printf("\n");
+}
+
+static void print_uuid(struct defrag_state *dst)
+{
+ unsigned char *uuid = OCFS2_RAW_SB(dst->dst_fs->fs_super)->s_uuid;
+ size_t i, max = sizeof(OCFS2_RAW_SB(dst->dst_fs->fs_super)->s_uuid);
+
+ for (i = 0; i < max; i++)
+ printf("%02x ", uuid[i]);
+
+ printf("\n");
+}
+
+static void print_version(void)
+{
+ fprintf(stderr, "%s %s\n", whoami, VERSION);
+}
+
+static void print_help(void)
+{
+ fprintf(stderr, "Usage: %s [-vVp] [ -i <inode numer> device\n", whoami);
+ fprintf(stderr, "Options:\n");
+ fprintf(stderr, "-h\t\t Print this help\n");
+ fprintf(stderr, "-v\t\t Verbose output\n");
+ fprintf(stderr, "-V\t\t Print version information\n");
+}
+
+static errcode_t open_and_check(struct defrag_state *dst, char *filename,
+ int open_flags, uint64_t blkno,
+ uint64_t blksize)
+{
+ errcode_t ret;
+
+ ret = ocfs2_open(filename, open_flags, blkno, blksize, &dst->dst_fs);
+ if (ret) {
+ com_err(whoami, ret, "while opening \"%s\"", filename);
+ goto out;
+ }
+
+ ret = check_superblock(dst);
+ if (ret) {
+ printf("Unrecoverable errors in the super block."
+ "Cannot continue.\n");
+ goto out;
+ }
+
+out:
+ return ret;
+}
+
+int main(int argc, char **argv)
+{
+ char *filename;
+ int64_t blkno, blksize;
+ struct defrag_state *dst = &dfrag;
+ int c, open_flags = OCFS2_FLAG_RW | OCFS2_FLAG_STRICT_COMPAT_CHECK;
+ int retval = DEFRAG_OK;
+ errcode_t ret;
+ int mount_flags;
+
+ memset(dst, 0, sizeof(struct defrag_state));
+
+ /* These mean "autodetect" */
+ blksize = 0;
+ blkno = 0;
+
+ initialize_ocfs_error_table();
+ setlinebuf(stderr);
+ setlinebuf(stdout);
+
+ while ((c = getopt(argc, argv, "vVphi:")) != EOF) {
+ switch (c) {
+ case 'v':
+ verbose = 1;
+ break;
+
+ case 'V':
+ print_version();
+ exit(DEFRAG_USAGE);
+ break;
+ case 'h':
+ print_help();
+ exit(0);
+ break;
+
+ default:
+ retval |= DEFRAG_USAGE;
+ print_help();
+ goto out;
+ break;
+ }
+ }
+
+ if (optind >= argc) {
+ fprintf(stderr, "Missing filename\n");
+ retval |= DEFRAG_USAGE;
+ print_help();
+ goto out;
+ }
+
+ filename = argv[optind];
+ print_version();
+
+ ret = ocfs2_check_if_mounted(filename, &mount_flags);
+ if (ret) {
+ com_err(whoami, ret, "while determining whether %s is mounted.",
+ filename);
+ retval |= DEFRAG_ERROR;
+ goto out;
+ }
+
+ if (mount_flags & (OCFS2_MF_MOUNTED | OCFS2_MF_BUSY)) {
+ if (!(open_flags & OCFS2_FLAG_RW))
+ fprintf(stdout, "\nWARNING!!! Running fsck.ocfs2 (read-"
+ "only) on a mounted filesystem may detect "
+ "invalid errors.\n\n");
+ else
+ fprintf(stdout, "\nWARNING!!! Running fsck.ocfs2 on a "
+ "mounted filesystem may cause SEVERE "
+ "filesystem damage.\n\n");
+ }
+
+ ret = open_and_check(dst, filename, open_flags, blkno, blksize);
+ if (ret) {
+ retval |= DEFRAG_ERROR;
+ goto out;
+ }
+
+ printf("Checking OCFS2 filesystem in %s:\n", filename);
+ printf(" label: ");
+ print_label(dst);
+ printf(" uuid: ");
+ print_uuid(dst);
+ printf(" number of blocks: %"PRIu64"\n", dst->dst_fs->fs_blocks);
+ printf(" bytes per block: %u\n", dst->dst_fs->fs_blocksize);
+ printf(" number of clusters: %"PRIu32"\n", dst->dst_fs->fs_clusters);
+ printf(" bytes per cluster: %u\n", dst->dst_fs->fs_clustersize);
+ printf(" max slots: %u\n\n",
+ OCFS2_RAW_SB(dst->dst_fs->fs_super)->s_max_slots);
+ printf(" System dir block number - %lu\n", dst->dst_fs->fs_sysdir_blkno);
+ printf(" Root dir block number - %lu\n", dst->dst_fs->fs_root_blkno);
+ printf(" FS blocks - %lu\n", dst->dst_fs->fs_blocks);
+
+ if (!fs_clean(OCFS2_RAW_SB(dst->dst_fs->fs_super), filename)) {
+ fprintf(stderr, "Please run fsck.ocfs2 before performing"
+ " defrag\n");
+ retval = DEFRAG_ERROR;
+ goto out;
+ }
+ ocfs2_write_super(dst->dst_fs);
+ ocfs2_close(dst->dst_fs);
+
+out:
+ return retval;
+}
diff --git a/defrag.ocfs2/include/defrag.h b/defrag.ocfs2/include/defrag.h
new file mode 100644
index 0000000..7c25e89
--- /dev/null
+++ b/defrag.ocfs2/include/defrag.h
@@ -0,0 +1,46 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * defrag.h
+ *
+ * Copyright (C) 2002 Oracle Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ *
+ */
+
+#ifndef __OCFS2_DEFRAG_H__
+#define __OCFS2_DEFRAG_H__
+
+#include "ocfs2/ocfs2.h"
+
+#define DEFRAG_OK 0
+#define DEFRAG_USAGE 1
+#define DEFRAG_ERROR 2
+
+struct defrag_state {
+ ocfs2_filesys *dst_fs;
+};
+
+extern int verbose;
+#define verbosef(fmt, args...) do { \
+ if (verbose) \
+ printf("%s:%d | " fmt, __FUNCTION__, __LINE__, args);\
+} while (0)
+
+
+#endif /* __OCFS2_DEFRAG_H__ */
+
--
1.6.4.2
--
Goldwyn
More information about the Ocfs2-tools-devel
mailing list