[Ocfs2-tools-commits] smushran commits r346 - trunk/mkfs.ocfs2

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Tue Oct 26 18:49:03 CDT 2004


Author: smushran
Date: 2004-10-26 18:49:01 -0500 (Tue, 26 Oct 2004)
New Revision: 346

Added:
   trunk/mkfs.ocfs2/mkfs.h
   trunk/mkfs.ocfs2/mkfs2.c
   trunk/mkfs.ocfs2/mkfs_utils.c
   trunk/mkfs.ocfs2/mkfs_utils.h
Modified:
   trunk/mkfs.ocfs2/Makefile
Log:
mkfs.c split into mkfs2.c and mkfs_utils.c

Modified: trunk/mkfs.ocfs2/Makefile
===================================================================
--- trunk/mkfs.ocfs2/Makefile	2004-10-26 19:14:05 UTC (rev 345)
+++ trunk/mkfs.ocfs2/Makefile	2004-10-26 23:49:01 UTC (rev 346)
@@ -11,12 +11,12 @@
 
 CFLAGS = $(OPTS) $(WARNINGS) 
 
-SBIN_PROGRAMS = mkfs.ocfs2
+SBIN_PROGRAMS = mkfs.ocfs2 mkfs2.ocfs2
 
 LIBOCFS2_CFLAGS = -I$(TOPDIR)/libocfs2/include
 LIBOCFS2_LIBS = -L$(TOPDIR)/libocfs2 -locfs2
 
-INCLUDES = $(LIBOCFS2_CFLAGS)
+INCLUDES = $(LIBOCFS2_CFLAGS) -I.
 DEFINES = -DOCFS2_FLAT_INCLUDES -DVERSION=\"$(VERSION)\"
 
 OPTIMIZE = -O2
@@ -33,6 +33,9 @@
 mkfs.ocfs2: $(OBJS)
 	$(LINK) $(LIBOCFS2_LIBS) $(COM_ERR_LIBS)
 
+mkfs2.ocfs2: mkfs2.o mkfs_utils.o
+	$(LINK) $(LIBOCFS2_LIBS) $(COM_ERR_LIBS)
+
 readdir: readdir.o
 	$(LINK) 
 

Added: trunk/mkfs.ocfs2/mkfs.h
===================================================================
--- trunk/mkfs.ocfs2/mkfs.h	2004-10-26 19:14:05 UTC (rev 345)
+++ trunk/mkfs.ocfs2/mkfs.h	2004-10-26 23:49:01 UTC (rev 346)
@@ -0,0 +1,230 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * mkfs.h
+ *
+ * OCFS2 format utility
+ *
+ * Copyright (C) 2004 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, 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.
+ *
+ * Authors: Manish Singh, Kurt Hackel
+ */
+
+#ifndef __MKFS_H__
+#define __MKFS_H__
+
+#define _LARGEFILE64_SOURCE
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <errno.h>
+#include <malloc.h>
+#include <time.h>
+#include <libgen.h>
+#include <netinet/in.h>
+#include <inttypes.h>
+
+#include "ocfs2.h"
+#include "bitops.h"
+
+/* jfs_compat.h defines these */
+#undef cpu_to_be32
+#undef be32_to_cpu
+
+#include "ocfs2_disk_dlm.h"
+#include "ocfs1_fs_compat.h"
+
+typedef unsigned short kdev_t;
+
+#include <signal.h>
+#include <libgen.h>
+
+#include "kernel-jbd.h"
+
+
+#ifndef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+
+#define BITCOUNT(x)     (((BX_(x)+(BX_(x)>>4)) & 0x0F0F0F0F) % 255)
+#define BX_(x)          ((x) - (((x)>>1)&0x77777777) \
+			     - (((x)>>2)&0x33333333) \
+			     - (((x)>>3)&0x11111111))
+
+#define MIN_RESERVED_TAIL_BLOCKS    8
+
+#define LEADING_SPACE_BLOCKS    2
+#define SLOP_BLOCKS             0
+#define FILE_ENTRY_BLOCKS       8
+#define SUPERBLOCK_BLOCKS       1
+#define PUBLISH_BLOCKS(i,min)   (i<min ? min : i)
+#define VOTE_BLOCKS(i,min)      (i<min ? min : i)
+#define AUTOCONF_BLOCKS(i,min)  ((2+4) + (i<min ? min : i))
+#define NUM_LOCAL_SYSTEM_FILES  6
+
+#define OCFS2_OS_LINUX           0
+#define OCFS2_OS_HURD            1
+#define OCFS2_OS_MASIX           2
+#define OCFS2_OS_FREEBSD         3
+#define OCFS2_OS_LITES           4
+
+#define OCFS2_DFL_MAX_MNT_COUNT          20
+#define OCFS2_DFL_CHECKINTERVAL          0
+
+#define SYSTEM_FILE_NAME_MAX   40
+
+#define ONE_GB_SHIFT           30
+
+#define BITMAP_WARNING_LEN     1572864
+#define BITMAP_AUTO_MAX        786432
+
+#define MAX_CLUSTER_SIZE       1048576
+#define MIN_CLUSTER_SIZE       4096
+#define AUTO_CLUSTER_SIZE      65536
+
+
+enum {
+	SFI_JOURNAL,
+	SFI_BITMAP,
+	SFI_LOCAL_ALLOC,
+	SFI_DLM,
+	SFI_CHAIN,
+	SFI_OTHER
+};
+
+
+typedef struct _SystemFileInfo SystemFileInfo;
+
+struct _SystemFileInfo {
+	char *name;
+	int type;
+	int global;
+	int dir;
+};
+
+struct BitInfo {
+	uint32_t used_bits;
+	uint32_t total_bits;
+};
+
+typedef struct _AllocGroup AllocGroup;
+typedef struct _SystemFileDiskRecord SystemFileDiskRecord;
+
+struct _AllocGroup {
+	char *name;
+	ocfs2_group_desc *gd;
+	SystemFileDiskRecord *alloc_inode;
+};
+
+
+struct _SystemFileDiskRecord {
+	uint64_t fe_off;
+        uint16_t suballoc_bit;
+	uint64_t extent_off;
+	uint64_t extent_len;
+	uint64_t file_size;
+
+	uint64_t chain_off;
+	AllocGroup *group;
+
+	struct BitInfo bi;
+
+	int flags;
+	int links;
+	int dir;
+};
+
+typedef struct _AllocBitmap AllocBitmap;
+
+struct _AllocBitmap {
+	void *buf;
+
+	uint32_t valid_bits;
+	uint32_t unit;
+	uint32_t unit_bits;
+
+	char *name;
+
+	uint64_t fe_disk_off;
+
+	SystemFileDiskRecord *bm_record;
+	SystemFileDiskRecord *alloc_record;
+};
+
+typedef struct _DirData DirData;
+
+struct _DirData {
+	uint64_t disk_off;
+	uint64_t disk_len;
+
+	void *buf;
+	int buf_len;
+
+	int last_off;
+	uint64_t fe_disk_off;
+
+	int link_count;
+
+	SystemFileDiskRecord *record;
+};
+
+typedef struct _State State;
+
+struct _State {
+  	char *progname;
+
+	int verbose;
+	int quiet;
+
+	uint32_t blocksize;
+	uint32_t blocksize_bits;
+
+	uint32_t cluster_size;
+	uint32_t cluster_size_bits;
+
+	uint64_t volume_size_in_bytes;
+	uint32_t volume_size_in_clusters;
+	uint64_t volume_size_in_blocks;
+
+	uint32_t pagesize_bits;
+
+	uint64_t reserved_tail_size;
+
+	unsigned int initial_nodes;
+
+	uint64_t journal_size_in_bytes;
+
+	char *vol_label;
+	char *device_name;
+	char *uuid;
+	uint32_t vol_generation;
+
+	int fd;
+
+	time_t format_time;
+
+	AllocBitmap *global_bm;
+	AllocGroup *system_group;
+};
+
+#endif

Added: trunk/mkfs.ocfs2/mkfs2.c
===================================================================
--- trunk/mkfs.ocfs2/mkfs2.c	2004-10-26 19:14:05 UTC (rev 345)
+++ trunk/mkfs.ocfs2/mkfs2.c	2004-10-26 23:49:01 UTC (rev 346)
@@ -0,0 +1,491 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * mkfs.c
+ *
+ * OCFS2 format utility
+ *
+ * Copyright (C) 2004 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, 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.
+ *
+ * Authors: Manish Singh, Kurt Hackel
+ */
+
+#include <mkfs.h>
+#include <mkfs_utils.h>
+
+static State *get_state(int argc, char **argv);
+static void usage(const char *progname);
+static void version(const char *progname);
+extern char *optarg;
+extern int optind, opterr, optopt;
+
+SystemFileInfo system_files[] = {
+	{ "bad_blocks", SFI_OTHER, 1, 0 },
+	{ "global_inode_alloc", SFI_CHAIN, 1, 0 },
+	{ "dlm", SFI_DLM, 1, 0 },
+	{ "global_bitmap", SFI_BITMAP, 1, 0 },
+	{ "orphan_dir", SFI_OTHER, 1, 1 },
+	{ "extent_alloc:%04d", SFI_CHAIN, 0, 0 },
+	{ "inode_alloc:%04d", SFI_CHAIN, 0, 0 },
+	{ "journal:%04d", SFI_JOURNAL, 0, 0 },
+	{ "local_alloc:%04d", SFI_LOCAL_ALLOC, 0, 0 }
+};
+
+int
+main(int argc, char **argv)
+{
+	State *s;
+	SystemFileDiskRecord *record[NUM_SYSTEM_INODES];
+	SystemFileDiskRecord global_alloc_rec;
+	SystemFileDiskRecord crap_rec;
+	SystemFileDiskRecord superblock_rec;
+	SystemFileDiskRecord root_dir_rec;
+	SystemFileDiskRecord system_dir_rec;
+	int i, j, num;
+	DirData *orphan_dir;
+	DirData *root_dir;
+	DirData *system_dir;
+	uint32_t need;
+	uint64_t allocated;
+	SystemFileDiskRecord *tmprec;
+	char fname[SYSTEM_FILE_NAME_MAX];
+
+	setbuf(stdout, NULL);
+	setbuf(stderr, NULL);
+
+	s = get_state(argc, argv);
+
+	open_device(s);
+
+	fill_defaults(s);  
+
+	adjust_volume_size(s);
+
+	generate_uuid (s);
+
+	create_generation(s);
+
+	print_state (s);
+
+	check_32bit_blocks (s);
+
+	init_record(s, &global_alloc_rec, SFI_OTHER, 0);
+	global_alloc_rec.extent_off = 0;
+	global_alloc_rec.extent_len = s->volume_size_in_bytes;
+
+	init_record(s, &superblock_rec, SFI_OTHER, 0);
+	init_record(s, &root_dir_rec, SFI_OTHER, 1);
+	init_record(s, &system_dir_rec, SFI_OTHER, 1);
+
+	for (i = 0; i < NUM_SYSTEM_INODES; i++) {
+		num = system_files[i].global ? 1 : s->initial_nodes;
+		record[i] = do_malloc(s, sizeof(SystemFileDiskRecord) * num);
+
+		for (j = 0; j < num; j++) {
+			init_record(s, &record[i][j],
+				    system_files[i].type, system_files[i].dir);
+		}
+	}
+
+	root_dir = alloc_directory(s);
+	system_dir = alloc_directory(s);
+	orphan_dir = alloc_directory(s);
+
+	need = (s->volume_size_in_clusters + 7) >> 3;
+	need = ((need + s->cluster_size - 1) >> s->cluster_size_bits) << s->cluster_size_bits;
+
+	if (need > BITMAP_WARNING_LEN)
+		fprintf(stderr, "WARNING: bitmap is very large, consider using "
+				"a larger cluster size and/or\na smaller "
+				"volume\n");
+
+	if (!s->quiet)
+		printf("Creating bitmaps: ");
+
+	tmprec = &(record[GLOBAL_BITMAP_SYSTEM_INODE][0]);
+	tmprec->extent_off = 0;
+	tmprec->extent_len = need;
+
+	s->global_bm = initialize_bitmap (s, s->volume_size_in_clusters,
+					  s->cluster_size_bits,
+					  "global bitmap", tmprec,
+					  &global_alloc_rec);
+
+	/*
+	 * Set all bits up to and including the superblock.
+	 */
+	alloc_bytes_from_bitmap(s, (OCFS2_SUPER_BLOCK_BLKNO + 1) << s->blocksize_bits,
+				s->global_bm, &(crap_rec.extent_off),
+				&(crap_rec.extent_len));
+
+	/*
+	 * Alloc a placeholder for the future global chain allocator
+	 */
+	alloc_from_bitmap(s, 1, s->global_bm, &(crap_rec.extent_off),
+                          &(crap_rec.extent_len));
+
+	/*
+	 * Now allocate the global inode alloc group
+	 */
+	tmprec = &(record[GLOBAL_INODE_ALLOC_SYSTEM_INODE][0]);
+
+	need = blocks_needed(s);
+	alloc_bytes_from_bitmap(s, need << s->blocksize_bits,
+                                s->global_bm,
+                                &(crap_rec.extent_off),
+                                &(crap_rec.extent_len));
+
+	s->system_group =
+		initialize_alloc_group(s, "system inode group", tmprec,
+				       crap_rec.extent_off >> s->blocksize_bits,
+				       0,
+                                       crap_rec.extent_len >> s->cluster_size_bits,
+				       s->cluster_size / s->blocksize);
+
+	tmprec->group = s->system_group;
+	tmprec->chain_off =
+		tmprec->group->gd->bg_blkno << s->blocksize_bits;
+
+	if (!s->quiet)
+		printf("done\n");
+
+	if (!s->quiet)
+		printf("Writing superblock: ");
+
+	superblock_rec.fe_off = (uint64_t)OCFS2_SUPER_BLOCK_BLKNO << s->blocksize_bits;
+
+	alloc_from_bitmap (s, 1, s->global_bm,
+			   &root_dir_rec.extent_off,
+			   &root_dir_rec.extent_len);
+
+	root_dir_rec.fe_off = alloc_inode(s, &root_dir_rec.suballoc_bit);
+	root_dir->record = &root_dir_rec;
+
+	add_entry_to_directory(s, root_dir, ".", root_dir_rec.fe_off, OCFS2_FT_DIR);
+	add_entry_to_directory(s, root_dir, "..", root_dir_rec.fe_off, OCFS2_FT_DIR);
+
+	need = system_dir_blocks_needed(s);
+	alloc_from_bitmap (s, need, s->global_bm, &system_dir_rec.extent_off, &system_dir_rec.extent_len);
+	system_dir_rec.fe_off = alloc_inode(s, &system_dir_rec.suballoc_bit);
+	system_dir->record = &system_dir_rec;
+	add_entry_to_directory(s, system_dir, ".", system_dir_rec.fe_off, OCFS2_FT_DIR);
+	add_entry_to_directory(s, system_dir, "..", system_dir_rec.fe_off, OCFS2_FT_DIR);
+
+	for (i = 0; i < NUM_SYSTEM_INODES; i++) {
+		num = (system_files[i].global) ? 1 : s->initial_nodes;
+
+		for (j = 0; j < num; j++) {
+			record[i][j].fe_off = alloc_inode(s, &(record[i][j].suballoc_bit));
+			sprintf(fname, system_files[i].name, j);
+			add_entry_to_directory(s, system_dir, fname,
+					       record[i][j].fe_off,
+					       system_files[i].dir ? OCFS2_FT_DIR
+							           : OCFS2_FT_REG_FILE);
+		}
+	}
+
+	/* back when we initialized the alloc group we hadn't allocated
+	 * an inode for the global allocator yet */
+	tmprec = &(record[GLOBAL_INODE_ALLOC_SYSTEM_INODE][0]);
+	s->system_group->gd->bg_parent_dinode = 
+		cpu_to_le64(tmprec->fe_off >> s->blocksize_bits);
+
+	tmprec = &(record[DLM_SYSTEM_INODE][0]);
+	need = (AUTOCONF_BLOCKS(s->initial_nodes, 32) +
+		PUBLISH_BLOCKS(s->initial_nodes, 32) +
+		VOTE_BLOCKS(s->initial_nodes, 32));
+	alloc_from_bitmap(s, need, s->global_bm, &tmprec->extent_off, &tmprec->extent_len);
+	tmprec->file_size = need << s->blocksize_bits;
+
+	tmprec = &record[ORPHAN_DIR_SYSTEM_INODE][0];
+	orphan_dir->record = tmprec;
+	alloc_from_bitmap(s, 1, s->global_bm, &tmprec->extent_off, &tmprec->extent_len);
+	add_entry_to_directory(s, orphan_dir, ".", tmprec->fe_off, OCFS2_FT_DIR);
+	add_entry_to_directory(s, orphan_dir, "..", system_dir_rec.fe_off, OCFS2_FT_DIR);
+
+	tmprec = s->global_bm->bm_record;
+	alloc_bytes_from_bitmap(s, tmprec->extent_len, s->global_bm,
+				&(tmprec->extent_off), &allocated);
+
+	format_leading_space(s);
+	format_superblock(s, &superblock_rec, &root_dir_rec, &system_dir_rec);
+
+	if (!s->quiet)
+		printf("done\n");
+
+	if (!s->quiet)
+		printf("Writing system files: ");
+
+	format_file(s, &root_dir_rec);
+	format_file(s, &system_dir_rec);
+
+	for (i = 0; i < NUM_SYSTEM_INODES; i++) {
+		num = system_files[i].global ? 1 : s->initial_nodes;
+		for (j = 0; j < num; j++) {
+			tmprec = &(record[i][j]);
+			if (system_files[i].type == SFI_JOURNAL) {
+				alloc_bytes_from_bitmap(s, s->journal_size_in_bytes,
+							s->global_bm,
+							&(tmprec->extent_off),
+							&(tmprec->extent_len));
+				replacement_journal_create(s, tmprec->extent_off);
+				tmprec->file_size = tmprec->extent_len;
+			}
+
+			format_file(s, tmprec);
+		}
+	}
+
+	write_bitmap_data(s, s->global_bm);
+	write_group_data(s, s->system_group);
+
+	write_directory_data(s, root_dir);
+	write_directory_data(s, system_dir);
+	write_directory_data(s, orphan_dir);
+
+	if (!s->quiet)
+		printf("done\n");
+
+	if (!s->quiet)
+		printf("Writing autoconfig header: ");
+
+	write_autoconfig_header(s, &record[DLM_SYSTEM_INODE][0]);
+
+	if (!s->quiet)
+		printf("done\n");
+
+	close_device(s);
+
+	if (!s->quiet)
+		printf("%s successful\n\n", s->progname);
+
+	return 0;
+}
+
+static State *
+get_state(int argc, char **argv)
+{
+	char *progname;
+	unsigned int blocksize = 0;
+	unsigned int cluster_size = 0;
+	char *vol_label = NULL;
+	unsigned int initial_nodes = 0;
+	char *dummy;
+	State *s;
+	int c;
+	int verbose = 0, quiet = 0;
+	int show_version = 0;
+	char *device_name;
+	int ret;
+	uint64_t val;
+	uint64_t journal_size_in_bytes = 0;
+	uint64_t max_journal_size = 500 * ONE_MEGA_BYTE;
+
+	static struct option long_options[] = {
+		{ "blocksize", 1, 0, 'b' },
+		{ "clustersize", 1, 0, 'c' },
+		{ "label", 1, 0, 'L' },
+		{ "nodes", 1, 0, 'n' },
+		{ "verbose", 0, 0, 'v' },
+		{ "quiet", 0, 0, 'q' },
+		{ "version", 0, 0, 'V' },
+		{ "journalsize", 0, 0, 'j'},
+		{ 0, 0, 0, 0}
+	};
+
+	if (argc && *argv)
+		progname = basename(argv[0]);
+	else
+		progname = strdup("mkfs.ocfs2");
+
+	while (1) {
+		c = getopt_long(argc, argv, "b:c:L:n:j:vqV", long_options, 
+				NULL);
+
+		if (c == -1)
+			break;
+
+		switch (c) {
+		case 'b':
+			ret = get_number(optarg, &val);
+
+			if (ret ||
+			    val < OCFS2_MIN_BLOCKSIZE ||
+			    val > OCFS2_MAX_BLOCKSIZE) {
+				com_err(progname, 0,
+					"Invalid blocksize %s: "
+					"must be between %d and %d bytes",
+					optarg,
+					OCFS2_MIN_BLOCKSIZE,
+					OCFS2_MAX_BLOCKSIZE);
+				exit(1);
+			}
+
+			blocksize = (unsigned int) val;
+			break;
+
+		case 'c':
+			ret = get_number(optarg, &val);
+
+			if (ret ||
+			    val < MIN_CLUSTER_SIZE ||
+			    val > MAX_CLUSTER_SIZE) {
+				com_err(progname, 0,
+					"Invalid cluster size %s: "
+					"must be between %d and %d bytes",
+					optarg,
+					MIN_CLUSTER_SIZE,
+					MAX_CLUSTER_SIZE);
+				exit(1);
+			}
+
+			cluster_size = (unsigned int) val;
+			break;
+
+		case 'L':
+			vol_label = strdup(optarg);
+
+			if (strlen(vol_label) >= MAX_VOL_LABEL_LEN) {
+				com_err(progname, 0,
+					"Volume label too long: must be less "
+					"than %d characters",
+					MAX_VOL_LABEL_LEN);
+				exit(1);
+			}
+
+			break;
+
+		case 'n':
+			initial_nodes = strtoul(optarg, &dummy, 0);
+
+			if (initial_nodes > OCFS2_MAX_NODES || *dummy != '\0') {
+				com_err(progname, 0,
+					"Initial nodes must be no more than %d",
+					OCFS2_MAX_NODES);
+				exit(1);
+			} else if (initial_nodes < 2) {
+				com_err(progname, 0,
+					"Initial nodes must be at least 2");
+				exit(1);
+			}
+
+			break;
+
+		case 'j':
+			ret = get_number(optarg, &val);
+
+			if (ret || 
+			    val < OCFS2_MIN_JOURNAL_SIZE ||
+			    val > max_journal_size) {
+				com_err(progname, 0,
+					"Invalid journal size %s: must be "
+					"between %d and %"PRIu64" bytes",
+					optarg,
+					OCFS2_MIN_JOURNAL_SIZE,
+					max_journal_size);
+				exit(1);
+			}
+
+			journal_size_in_bytes = val;
+
+			break;
+
+		case 'v':
+			verbose = 1;
+			break;
+
+		case 'q':
+			quiet = 1;
+			break;
+
+		case 'V':
+			show_version = 1;
+			break;
+
+		default:
+			usage(progname);
+			break;
+		}
+	}
+
+	if ((optind == argc) && !show_version)
+		usage(progname);
+
+	device_name = argv[optind];
+	optind++;
+
+	if (optind < argc) {
+		unsigned long val;
+
+		val = strtoul(argv[optind], &dummy, 0);
+
+		if ((*dummy) || (val > 0xffffffffUL)) {
+			com_err(progname, 0, "Block count bad - %s",
+				argv[optind]);
+			exit(1);
+		}
+
+		optind++;
+	}
+
+	if (optind < argc)
+		usage(progname);
+
+	if (!quiet || show_version)
+		version(progname);
+
+	if (show_version)
+		exit(0);
+
+	s = malloc(sizeof(State));
+	memset(s, 0, sizeof(State));
+
+	s->progname      = progname;
+
+	s->verbose       = verbose;
+	s->quiet         = quiet;
+
+	s->blocksize     = blocksize;
+	s->cluster_size  = cluster_size;
+	s->vol_label     = vol_label;
+	s->initial_nodes = initial_nodes;
+
+	s->device_name   = strdup(device_name);
+
+	s->fd            = -1;
+
+	s->format_time   = time(NULL);
+
+	s->journal_size_in_bytes = journal_size_in_bytes;
+
+	return s;
+}
+
+static void
+usage(const char *progname)
+{
+	fprintf(stderr, "Usage: %s [-b blocksize] [-c cluster-size] [-L volume-label]\n"
+			"\t[-n number-of-nodes] [-j journal-size] [-qvV] device [blocks-count]\n",
+			progname);
+	exit(0);
+}
+
+static void
+version(const char *progname)
+{
+	fprintf(stderr, "%s %s\n", progname, VERSION);
+}

Added: trunk/mkfs.ocfs2/mkfs_utils.c
===================================================================
--- trunk/mkfs.ocfs2/mkfs_utils.c	2004-10-26 19:14:05 UTC (rev 345)
+++ trunk/mkfs.ocfs2/mkfs_utils.c	2004-10-26 23:49:01 UTC (rev 346)
@@ -0,0 +1,1009 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * mkfs_utils.c
+ *
+ * OCFS2 format utility
+ *
+ * Copyright (C) 2004 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, 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.
+ *
+ * Authors: Manish Singh, Kurt Hackel
+ */
+
+#include <mkfs.h>
+#include <mkfs_utils.h>
+
+int
+get_number(char *arg, uint64_t *res)
+{
+	char *ptr = NULL;
+	uint64_t num;
+
+	num = strtoull(arg, &ptr, 0);
+
+	if ((ptr == arg) || (num == UINT64_MAX))
+		return(-EINVAL);
+
+	switch (*ptr) {
+	case '\0':
+		break;
+
+	case 'g':
+	case 'G':
+		num *= 1024;
+		/* FALL THROUGH */
+
+	case 'm':
+	case 'M':
+		num *= 1024;
+		/* FALL THROUGH */
+
+	case 'k':
+	case 'K':
+		num *= 1024;
+		/* FALL THROUGH */
+
+	case 'b':
+	case 'B':
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	*res = num;
+
+	return 0;
+}
+
+/* stolen from e2fsprogs */
+uint64_t figure_journal_size(uint64_t size, State *s)
+{
+	unsigned int j_blocks;
+
+	if (s->volume_size_in_blocks < 2048) {
+		fprintf(stderr,	"Filesystem too small for a journal\n");
+		exit(1);
+	}
+
+	if (size > 0) {
+		j_blocks = size >> s->blocksize_bits;
+		/* mke2fs knows about free blocks at this point, but
+		 * we don't so lets just take a wild guess as to what
+		 * the fs overhead we're looking at will be. */
+		if ((j_blocks * s->initial_nodes + 1024) > 
+		    s->volume_size_in_blocks) {
+			fprintf(stderr, 
+				"Journal size too big for filesystem.\n");
+			exit(1);
+		}
+		return size;
+	}
+
+	if (s->volume_size_in_blocks < 32768)
+		j_blocks = 1024;
+	else if (s->volume_size_in_blocks < 262144)
+		j_blocks = 4096;
+	else
+		j_blocks = 8192;
+
+	return j_blocks << s->blocksize_bits;
+}
+
+void
+fill_defaults(State *s)
+{
+	size_t pagesize;
+	errcode_t err;
+	uint32_t ret;
+
+	pagesize = getpagesize();
+
+	s->pagesize_bits = get_bits(s, pagesize);
+
+	if (!s->blocksize)
+		s->blocksize = 4096;
+
+	if (!s->volume_size_in_blocks) {
+		err = ocfs2_get_device_size(s->device_name, s->blocksize, &ret);
+		s->volume_size_in_blocks = ret;
+	}
+
+	s->volume_size_in_bytes = s->volume_size_in_blocks * s->blocksize;
+
+	if (!s->blocksize) {
+		if (s->volume_size_in_bytes <= 1024 * 1024 * 3) {
+			s->blocksize = 512;
+		} else {
+			int shift = 30;
+
+			while (s->blocksize > 1024) {
+				if (s->volume_size_in_bytes >= 1U << shift)
+					break;
+				s->blocksize >>= 1;
+				shift--;
+			}
+		}
+
+		err = ocfs2_get_device_size(s->device_name, s->blocksize, &ret);
+		s->volume_size_in_blocks = ret;
+
+		s->volume_size_in_bytes =
+			s->volume_size_in_blocks * s->blocksize;
+	}
+
+	s->blocksize_bits = get_bits(s, s->blocksize);
+
+	if (!s->cluster_size) {
+		uint32_t volume_size, cluster_size, cluster_size_bits, need;
+
+		for (cluster_size = MIN_CLUSTER_SIZE;
+		     cluster_size < AUTO_CLUSTER_SIZE;
+		     cluster_size <<= 1) {
+			cluster_size_bits = get_bits(s, cluster_size);
+
+			volume_size =
+				s->volume_size_in_bytes >> cluster_size_bits;
+
+			need = (volume_size + 7) >> 3;
+			need = ((need + cluster_size - 1) >>
+				cluster_size_bits) << cluster_size_bits;
+
+			if (need <= BITMAP_AUTO_MAX) 
+				break;
+		}
+
+		s->cluster_size = cluster_size;
+	}
+
+	s->cluster_size_bits = get_bits(s, s->cluster_size);
+
+	s->volume_size_in_clusters = s->volume_size_in_bytes >> s->cluster_size_bits;
+	s->volume_size_in_blocks = (s->volume_size_in_clusters << s->cluster_size_bits) >> s->blocksize_bits;
+	
+	s->reserved_tail_size = 0;
+
+	if (!s->initial_nodes) {
+		s->initial_nodes =
+			initial_nodes_for_volume(s->volume_size_in_bytes);
+	}
+
+	if (!s->vol_label) {
+		  s->vol_label = strdup("");
+	}
+
+	s->journal_size_in_bytes = figure_journal_size(s->journal_size_in_bytes, s);
+}
+
+int
+get_bits(State *s, int num)
+{
+	int i, bits = 0;
+
+	for (i = 32; i >= 0; i--) {
+		if (num == (1U << i))
+			bits = i;
+	}
+
+	if (bits == 0) {
+		com_err(s->progname, 0,
+			"Could not get bits for number %d", num);
+		exit(1);
+	}
+
+	return bits;
+}
+
+void *
+do_malloc(State *s, size_t size)
+{
+	void *buf;
+
+	buf = malloc(size);
+
+	if (buf == NULL) {
+		com_err(s->progname, 0,
+			"Could not allocate %lu bytes of memory",
+			(unsigned long)size);
+		exit(1);
+	}
+
+	return buf;
+}
+
+void
+do_pwrite(State *s, const void *buf, size_t count, uint64_t offset)
+{
+	ssize_t ret;
+
+	ret = pwrite64(s->fd, buf, count, offset);
+
+	if (ret == -1) {
+		com_err(s->progname, 0, "Could not write: %s",
+			strerror(errno));
+		exit(1);
+	}
+}
+
+AllocGroup *
+initialize_alloc_group(State *s, char *name,
+		       SystemFileDiskRecord *alloc_inode,
+		       uint64_t blkno, uint16_t chain,
+		       uint16_t cpg, uint16_t bpc)
+{
+	AllocGroup *group;
+
+	group = do_malloc(s, sizeof(AllocGroup));
+	memset(group, 0, sizeof(AllocGroup));
+
+	group->gd = do_malloc(s, s->blocksize);
+	memset(group->gd, 0, s->blocksize);
+
+	strcpy(group->gd->bg_signature, OCFS2_GROUP_DESC_SIGNATURE);
+	group->gd->bg_generation = cpu_to_le32(s->vol_generation);
+	group->gd->bg_size = (uint32_t)ocfs2_group_bitmap_size(s->blocksize);
+	group->gd->bg_bits = cpg * bpc;
+	group->gd->bg_chain = chain;
+	group->gd->bg_parent_dinode = alloc_inode->fe_off;
+	group->gd->bg_blkno = blkno;
+
+	/* First bit set to account for the descriptor block */
+	ocfs2_set_bit(0, group->gd->bg_bitmap);
+	group->gd->bg_free_bits_count = group->gd->bg_bits - 1;
+
+	alloc_inode->bi.total_bits = group->gd->bg_bits;
+	alloc_inode->bi.used_bits = alloc_inode->bi.total_bits -
+		group->gd->bg_free_bits_count;
+	group->alloc_inode = alloc_inode;
+
+	group->name = strdup(name);
+
+	return group;
+}
+
+AllocBitmap *
+initialize_bitmap(State *s, uint32_t bits, uint32_t unit_bits,
+		  const char *name, SystemFileDiskRecord *bm_record,
+		  SystemFileDiskRecord *alloc_record)
+{
+	AllocBitmap *bitmap;
+	uint64_t bitmap_len = bm_record->extent_len;
+
+	bitmap = do_malloc(s, sizeof(AllocBitmap));
+	memset(bitmap, 0, sizeof(AllocBitmap));
+
+	bitmap->buf = memalign(s->blocksize, bitmap_len);
+	memset(bitmap->buf, 0, bitmap_len);
+
+	bitmap->valid_bits = bits;
+	bitmap->unit_bits = unit_bits;
+	bitmap->unit = 1 << unit_bits;
+	bitmap->name = strdup(name);
+
+	bm_record->file_size = bitmap_len;
+	bm_record->fe_off = 0ULL;
+
+	bm_record->bi.used_bits = 0;
+	bm_record->bi.total_bits = bits;
+
+	alloc_record->file_size = bits << unit_bits;
+	alloc_record->fe_off = 0ULL;
+
+	bitmap->bm_record = bm_record;
+	bitmap->alloc_record = alloc_record;
+
+	return bitmap;
+}
+
+#if 0
+static void
+destroy_bitmap(AllocBitmap *bitmap)
+{
+	free(bitmap->buf);
+	free(bitmap);
+}
+#endif
+
+int
+find_clear_bits(AllocBitmap *bitmap, uint32_t num_bits, uint32_t offset)
+{
+	uint32_t next_zero, off, count = 0, size, first_zero = -1;
+	void *buf;
+
+	buf = bitmap->buf;
+	size = bitmap->valid_bits;
+	off = offset;
+
+	while ((size - off + count >= num_bits) &&
+	       (next_zero = ocfs2_find_next_bit_clear(buf, size, off)) != size) {
+		if (next_zero >= bitmap->valid_bits)
+			break;
+
+		if (next_zero != off) {
+			first_zero = next_zero;
+			off = next_zero + 1;
+			count = 0;
+		} else {
+			off++;
+			if (count == 0)
+				first_zero = next_zero;
+		}
+
+		count++;
+
+		if (count == num_bits)
+			goto bail;
+	}
+
+	first_zero = -1;
+
+bail:
+	if (first_zero != (uint32_t)-1 && first_zero > bitmap->valid_bits) {
+		fprintf(stderr, "erf... first_zero > bitmap->valid_bits "
+				"(%d > %d)", first_zero, bitmap->valid_bits);
+		first_zero = -1;
+	}
+
+	return first_zero;
+}
+
+int
+alloc_bytes_from_bitmap(State *s, uint64_t bytes, AllocBitmap *bitmap,
+			uint64_t *start, uint64_t *num)
+{
+	uint32_t num_bits = 0;
+
+	num_bits = (bytes + bitmap->unit - 1) >> bitmap->unit_bits;
+
+	return alloc_from_bitmap(s, num_bits, bitmap, start, num);
+}
+
+int
+alloc_from_bitmap(State *s, uint64_t num_bits, AllocBitmap *bitmap,
+		  uint64_t *start, uint64_t *num)
+{
+	uint32_t start_bit = 0;
+	void *buf;
+
+	start_bit = find_clear_bits(bitmap, num_bits, 0);
+
+	if (start_bit == (uint32_t)-1) {
+		com_err(s->progname, 0,
+			"Could not allocate %"PRIu64" bits from %s bitmap",
+			num_bits, bitmap->name);
+		exit(1);
+	}
+
+	*start = ((uint64_t)start_bit) << bitmap->unit_bits;
+	*num = ((uint64_t)num_bits) << bitmap->unit_bits;
+
+	buf = do_malloc(s, *num);
+	memset(buf, 0, *num);
+
+	do_pwrite(s, buf, *num, *start);
+
+	bitmap->bm_record->bi.used_bits += num_bits;
+
+	while (num_bits--) {
+		ocfs2_set_bit(start_bit, bitmap->buf);
+		start_bit++;
+	}
+
+	free(buf);
+
+	return 0;
+}
+
+int alloc_from_group(State *s, uint16_t count,
+			    AllocGroup *group, uint64_t *start_blkno,
+			    uint16_t *num_bits)
+{
+	uint16_t start_bit, end_bit;
+
+	start_bit = ocfs2_find_first_bit_clear(group->gd->bg_bitmap,
+					       group->gd->bg_bits);
+
+	while (start_bit < group->gd->bg_bits) {
+		end_bit = ocfs2_find_next_bit_set(group->gd->bg_bitmap,
+						  group->gd->bg_bits,
+						  start_bit);
+		if ((end_bit - start_bit) >= count) {
+			*num_bits = count;
+			for (*num_bits = 0; *num_bits < count; *num_bits += 1) {
+				ocfs2_set_bit(start_bit + *num_bits,
+					      group->gd->bg_bitmap);
+			}
+			group->gd->bg_free_bits_count -= *num_bits;
+			group->alloc_inode->bi.used_bits += *num_bits;
+			*start_blkno = group->gd->bg_blkno + start_bit;
+			return 0;
+		}
+		start_bit = end_bit;
+	}
+
+	com_err(s->progname, 0,
+		"Could not allocate %"PRIu16" bits from %s alloc group",
+		count, group->name);
+	exit(1);
+
+	return 1;
+}
+
+uint64_t
+alloc_inode(State *s, uint16_t *suballoc_bit)
+{
+	uint64_t ret;
+	uint16_t num;
+
+	alloc_from_group(s, 1, s->system_group,
+			 &ret, &num);
+
+        *suballoc_bit = (int)(ret - s->system_group->gd->bg_blkno);
+
+        /* Did I mention I hate this code? */
+	return (ret << s->blocksize_bits);
+}
+
+DirData *
+alloc_directory(State *s)
+{
+	DirData *dir;
+
+	dir = do_malloc(s, sizeof(DirData));
+	memset(dir, 0, sizeof(DirData));
+
+	return dir;
+}
+
+void
+add_entry_to_directory(State *s, DirData *dir, char *name, uint64_t byte_off,
+		       uint8_t type)
+{
+	struct ocfs2_dir_entry *de, *de1;
+	int new_rec_len;
+	void *new_buf, *p;
+	int new_size, rec_len, real_len;
+
+	new_rec_len = OCFS2_DIR_REC_LEN(strlen(name));
+
+	if (dir->buf) {
+		de = (struct ocfs2_dir_entry *)(dir->buf + dir->last_off);
+		rec_len = le16_to_cpu(de->rec_len);
+		real_len = OCFS2_DIR_REC_LEN(de->name_len);
+
+		if ((le64_to_cpu(de->inode) == 0 && rec_len >= new_rec_len) ||
+		    (rec_len >= real_len + new_rec_len)) {
+			if (le64_to_cpu(de->inode)) {
+				de1 =(struct ocfs2_dir_entry *) ((char *) de + real_len);
+				de1->rec_len = cpu_to_le16(le16_to_cpu(de->rec_len) - real_len);
+				de->rec_len = cpu_to_le16(real_len);
+				de = de1;
+			}
+
+			goto got_it;
+		}
+
+		new_size = dir->record->file_size + s->blocksize;
+	} else {
+		new_size = s->blocksize;
+	}
+
+	new_buf = memalign(s->blocksize, new_size);
+
+	if (new_buf == NULL) {
+		com_err(s->progname, 0, "Failed to grow directory");
+		exit(1);
+	}
+
+	if (dir->buf) {
+		memcpy(new_buf, dir->buf, dir->record->file_size);
+		free(dir->buf);
+		p = new_buf + dir->record->file_size;
+		memset(p, 0, s->blocksize);
+	} else {
+		p = new_buf;
+		memset(new_buf, 0, new_size);
+	}
+
+	dir->buf = new_buf;
+	dir->record->file_size = new_size;
+
+	de = (struct ocfs2_dir_entry *)p;
+	de->inode = 0;
+	de->rec_len = cpu_to_le16(s->blocksize);
+
+got_it:
+	de->name_len = strlen(name);
+
+	de->inode = cpu_to_le64(byte_off >> s->blocksize_bits);
+
+	de->file_type = type;
+
+        strcpy(de->name, name);
+
+        dir->last_off = ((char *)de - (char *)dir->buf);
+
+        if (type == OCFS2_FT_DIR)
+                dir->record->links++;
+}
+
+uint32_t
+blocks_needed(State *s)
+{
+	uint32_t num;
+
+	num = LEADING_SPACE_BLOCKS;
+	num += SUPERBLOCK_BLOCKS;
+	num += FILE_ENTRY_BLOCKS;
+	num += AUTOCONF_BLOCKS(s->initial_nodes, 32);
+	num += PUBLISH_BLOCKS(s->initial_nodes, 32);
+	num += VOTE_BLOCKS(s->initial_nodes, 32);
+	num += (s->initial_nodes * NUM_LOCAL_SYSTEM_FILES);
+	num += SLOP_BLOCKS;
+
+	return num;
+}
+
+uint32_t
+system_dir_blocks_needed(State *s)
+{
+	int bytes_needed = 0;
+	int each = OCFS2_DIR_REC_LEN(SYSTEM_FILE_NAME_MAX);
+	int entries_per_block = s->blocksize / each;
+
+	bytes_needed = (blocks_needed(s) + entries_per_block -
+			1 / entries_per_block) << s->blocksize_bits;
+
+	return (bytes_needed + s->cluster_size - 1) >> s->cluster_size_bits;
+}
+
+void
+adjust_volume_size(State *s)
+{
+	uint32_t max;
+	uint64_t vsize = s->volume_size_in_bytes -
+		(MIN_RESERVED_TAIL_BLOCKS << s->blocksize_bits);
+
+	max = MAX(s->pagesize_bits, s->blocksize_bits);
+	max = MAX(max, s->cluster_size_bits);
+
+	vsize >>= max;
+	vsize <<= max;
+
+	s->volume_size_in_blocks = vsize >> s->blocksize_bits;
+	s->volume_size_in_clusters = vsize >> s->cluster_size_bits;
+	s->reserved_tail_size = s->volume_size_in_bytes - vsize;
+	s->volume_size_in_bytes = vsize;
+}
+
+/* this will go away once we have patches to jbd to support 64bit blocks.
+ * ocfs2 will only fail mounts when it finds itself asked to mount a large
+ * device in a kernel that doesn't have a smarter jbd. */
+void
+check_32bit_blocks(State *s)
+{
+	uint64_t max = UINT32_MAX;
+       
+	if (s->volume_size_in_blocks <= max)
+		return;
+
+	fprintf(stderr, "ERROR: jbd can only store block numbers in 32 bits. "
+		"%s can hold %"PRIu64" blocks which overflows this limit. "
+		"Consider increasing the block size or decreasing the device "
+		"size.\n", s->device_name, s->volume_size_in_blocks);
+	exit(1);
+}
+
+void
+format_superblock(State *s, SystemFileDiskRecord *rec,
+		  SystemFileDiskRecord *root_rec, SystemFileDiskRecord *sys_rec)
+{
+	ocfs2_dinode *di;
+	uint64_t super_off = rec->fe_off;
+
+	di = do_malloc(s, s->blocksize);
+	memset(di, 0, s->blocksize);
+
+	strcpy(di->i_signature, OCFS2_SUPER_BLOCK_SIGNATURE);
+	di->i_suballoc_node = cpu_to_le16((__u16)-1);
+	di->i_suballoc_bit = cpu_to_le16((__u16)-1);
+
+	di->i_atime = 0;
+	di->i_ctime = cpu_to_le64(s->format_time);
+	di->i_mtime = cpu_to_le64(s->format_time);
+	di->i_blkno = cpu_to_le64(super_off >> s->blocksize_bits);
+	di->i_flags = cpu_to_le32(OCFS2_VALID_FL | OCFS2_SYSTEM_FL |
+				  OCFS2_SUPER_BLOCK_FL);
+	di->i_clusters = s->volume_size_in_clusters;
+	di->id2.i_super.s_major_rev_level = cpu_to_le16(OCFS2_MAJOR_REV_LEVEL);
+	di->id2.i_super.s_minor_rev_level = cpu_to_le16(OCFS2_MINOR_REV_LEVEL);
+	di->id2.i_super.s_root_blkno = cpu_to_le64(root_rec->fe_off >> s->blocksize_bits);
+	di->id2.i_super.s_system_dir_blkno = cpu_to_le64(sys_rec->fe_off >> s->blocksize_bits);
+	di->id2.i_super.s_mnt_count = 0;
+	di->id2.i_super.s_max_mnt_count = cpu_to_le16(OCFS2_DFL_MAX_MNT_COUNT);
+	di->id2.i_super.s_state = 0;
+	di->id2.i_super.s_errors = 0;
+	di->id2.i_super.s_lastcheck = cpu_to_le64(s->format_time);
+	di->id2.i_super.s_checkinterval = cpu_to_le32(OCFS2_DFL_CHECKINTERVAL);
+	di->id2.i_super.s_creator_os = cpu_to_le32(OCFS2_OS_LINUX);
+	di->id2.i_super.s_blocksize_bits = cpu_to_le32(s->blocksize_bits);
+	di->id2.i_super.s_clustersize_bits = cpu_to_le32(s->cluster_size_bits);
+	di->id2.i_super.s_max_nodes = cpu_to_le32(s->initial_nodes);
+
+	strcpy(di->id2.i_super.s_label, s->vol_label);
+	memcpy(di->id2.i_super.s_uuid, s->uuid, 16);
+
+	do_pwrite(s, di, s->blocksize, super_off);
+	free(di);
+}
+
+int 
+ocfs2_clusters_per_group(int block_size, int cluster_size_bits)
+{
+	int bytes;
+
+	switch (block_size) {
+	case (4096):
+	case (2048):
+		bytes = 4 * ONE_MEGA_BYTE;
+		break;
+	case (1024):
+		bytes = 2 * ONE_MEGA_BYTE;
+		break;
+	case (512):
+	default:
+		bytes = ONE_MEGA_BYTE;
+		break;
+	}
+
+	return(bytes >> cluster_size_bits);
+}
+
+void
+format_file(State *s, SystemFileDiskRecord *rec)
+{
+	ocfs2_dinode *di;
+	int mode;
+	uint32_t clusters;
+
+	mode = rec->dir ? 0755 | S_IFDIR : 0644 | S_IFREG;
+
+	clusters = (rec->extent_len + s->cluster_size - 1) >> s->cluster_size_bits;
+
+	di = do_malloc(s, s->blocksize);
+	memset(di, 0, s->blocksize);
+
+	strcpy(di->i_signature, OCFS2_INODE_SIGNATURE);
+	di->i_generation = cpu_to_le32(s->vol_generation);
+	di->i_suballoc_node = cpu_to_le16(-1);
+        di->i_suballoc_bit = cpu_to_le16(rec->suballoc_bit);
+	di->i_blkno = cpu_to_le64(rec->fe_off >> s->blocksize_bits);
+	di->i_uid = 0;
+	di->i_gid = 0;
+	di->i_size = cpu_to_le64(rec->file_size);
+	di->i_mode = cpu_to_le16(mode);
+	di->i_links_count = cpu_to_le16(rec->links);
+	di->i_flags = cpu_to_le32(rec->flags);
+	di->i_atime = di->i_ctime = di->i_mtime = cpu_to_le64(s->format_time);
+	di->i_dtime = 0;
+	di->i_clusters = cpu_to_le32(clusters);
+
+	if (rec->flags & OCFS2_LOCAL_ALLOC_FL) {
+		di->id2.i_lab.la_size =
+			cpu_to_le16(ocfs2_local_alloc_size(s->blocksize));
+		goto write_out;
+	}
+
+	if (rec->flags & OCFS2_BITMAP_FL) {
+		di->id1.bitmap1.i_used = cpu_to_le32(rec->bi.used_bits);
+		di->id1.bitmap1.i_total = cpu_to_le32(rec->bi.total_bits);
+	}
+
+	if (rec->flags & OCFS2_CHAIN_FL) {
+		di->id2.i_chain.cl_count = 
+			cpu_to_le16(ocfs2_chain_recs_per_inode(s->blocksize));
+		di->id2.i_chain.cl_cpg = 
+			cpu_to_le16(ocfs2_clusters_per_group(s->blocksize, 
+						 s->cluster_size_bits));
+		di->id2.i_chain.cl_bpc = 
+			cpu_to_le16(s->cluster_size / s->blocksize);
+		di->id2.i_chain.cl_next_free_rec = 0;
+
+		if (rec->chain_off) {
+			di->id2.i_chain.cl_next_free_rec =
+				cpu_to_le16(1);
+			di->id2.i_chain.cl_recs[0].c_free =
+				cpu_to_le16(rec->group->gd->bg_free_bits_count);
+			di->id2.i_chain.cl_recs[0].c_total =
+				cpu_to_le16(rec->group->gd->bg_bits);
+			di->id2.i_chain.cl_recs[0].c_blkno =
+				cpu_to_le64(rec->chain_off >> s->blocksize_bits);
+                        di->id2.i_chain.cl_cpg =
+                            cpu_to_le16(rec->group->gd->bg_bits /
+                                        le16_to_cpu(di->id2.i_chain.cl_bpc));
+			di->i_clusters =
+                            cpu_to_le64(di->id2.i_chain.cl_cpg);
+			di->i_size =
+                            cpu_to_le64(di->i_clusters << s->cluster_size_bits);
+		}
+		goto write_out;
+	}
+	di->id2.i_list.l_count =
+		cpu_to_le16(ocfs2_extent_recs_per_inode(s->blocksize));
+	di->id2.i_list.l_next_free_rec = 0;
+	di->id2.i_list.l_tree_depth = 0;
+
+	if (rec->extent_len) {
+		di->id2.i_list.l_next_free_rec = cpu_to_le16(1);
+		di->id2.i_list.l_recs[0].e_cpos = 0;
+		di->id2.i_list.l_recs[0].e_clusters = cpu_to_le32(clusters);
+		di->id2.i_list.l_recs[0].e_blkno =
+			cpu_to_le64(rec->extent_off >> s->blocksize_bits);
+	}
+
+write_out:
+	do_pwrite(s, di, s->blocksize, rec->fe_off);
+	free(di);
+}
+
+void
+write_metadata(State *s, SystemFileDiskRecord *rec, void *src)
+{
+	void *buf;
+
+	buf = do_malloc(s, rec->extent_len);
+	memset(buf, 0, rec->extent_len);
+
+	memcpy(buf, src, rec->file_size);
+
+	do_pwrite(s, buf, rec->extent_len, rec->extent_off);
+
+	free(buf);
+}
+
+void
+write_bitmap_data(State *s, AllocBitmap *bitmap)
+{
+	write_metadata(s, bitmap->bm_record, bitmap->buf);
+}
+
+void
+write_group_data(State *s, AllocGroup *group)
+{
+	do_pwrite(s, group->gd, s->blocksize,
+		  group->gd->bg_blkno << s->blocksize_bits);
+}
+
+void
+write_directory_data(State *s, DirData *dir)
+{
+	write_metadata(s, dir->record, dir->buf);
+}
+
+void
+format_leading_space(State *s)
+{
+	int num_blocks = 2, size;
+	ocfs1_vol_disk_hdr *hdr;
+	ocfs1_vol_label *lbl;
+	void *buf;
+	char *p;
+
+	size = num_blocks << s->blocksize_bits;
+
+	p = buf = do_malloc(s, size);
+	memset(buf, 2, size);
+
+	hdr = buf;
+	strcpy(hdr->signature, "this is an ocfs2 volume");
+	strcpy(hdr->mount_point, "this is an ocfs2 volume");
+
+	p += 512;
+	lbl = (ocfs1_vol_label *)p;
+	strcpy(lbl->label, "this is an ocfs2 volume");
+	strcpy(lbl->cluster_name, "this is an ocfs2 volume");
+
+	do_pwrite(s, buf, size, 0);
+	free(buf);
+}
+
+void
+replacement_journal_create(State *s, uint64_t journal_off)
+{
+	journal_superblock_t *sb;
+	void *buf;
+
+	buf = do_malloc(s, s->journal_size_in_bytes);
+	memset(buf, 0, s->journal_size_in_bytes);
+
+	sb = buf;
+
+	sb->s_header.h_magic     = htonl(JFS_MAGIC_NUMBER);
+	sb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
+
+	sb->s_blocksize = cpu_to_be32(s->blocksize);
+	sb->s_maxlen =
+		cpu_to_be32(s->journal_size_in_bytes >> s->blocksize_bits);
+
+	if (s->blocksize == 512)
+		sb->s_first = htonl(2);
+	else
+		sb->s_first = htonl(1);
+
+	sb->s_start    = htonl(1);
+	sb->s_sequence = htonl(1);
+	sb->s_errno    = htonl(0);
+
+	do_pwrite(s, buf, s->journal_size_in_bytes, journal_off);
+	free(buf);
+}
+
+void
+open_device(State *s)
+{
+	s->fd = open64(s->device_name, O_RDWR);
+
+	if (s->fd == -1) {
+		com_err(s->progname, 0,
+		        "Could not open device %s: %s",
+			s->device_name, strerror (errno));
+		exit(1);
+	}
+}
+
+void
+close_device(State *s)
+{
+	fsync(s->fd);
+	close(s->fd);
+	s->fd = -1;
+}
+
+int
+initial_nodes_for_volume(uint64_t size)
+{
+	int i, shift = ONE_GB_SHIFT;
+	int defaults[4] = { 2, 4, 8, 16 };
+
+	for (i = 0, shift = ONE_GB_SHIFT; i < 4; i++, shift += 3) {
+		size >>= shift;
+
+		if (!size)
+			break;
+	}
+
+	return (i < 4) ? defaults[i] : 32;
+}
+
+/* XXX: Hm, maybe replace this with libuuid? */
+void
+generate_uuid(State *s)
+{
+	int randfd = 0;
+	int readlen = 0;
+	int len = 0;
+
+	if ((randfd = open("/dev/urandom", O_RDONLY)) == -1) {
+		com_err(s->progname, 0,
+			"Error opening /dev/urandom: %s", strerror(errno));
+		exit(1);
+	}
+
+	s->uuid = do_malloc(s, MAX_VOL_ID_LENGTH);
+
+	while (readlen < MAX_VOL_ID_LENGTH) {
+		if ((len = read(randfd, s->uuid + readlen, MAX_VOL_ID_LENGTH - readlen)) == -1) {
+			com_err(s->progname, 0,
+				"Error reading from /dev/urandom: %s",
+				strerror(errno));
+			exit(1);
+		}
+
+		readlen += len;
+	}
+
+	close(randfd);
+}
+
+void create_generation(State *s)
+{
+	int randfd = 0;
+	int readlen = sizeof(s->vol_generation);
+
+	if ((randfd = open("/dev/urandom", O_RDONLY)) == -1) {
+		com_err(s->progname, 0,
+			"Error opening /dev/urandom: %s", strerror(errno));
+		exit(1);
+	}
+
+	if (read(randfd, &s->vol_generation, readlen) != readlen) {
+		com_err(s->progname, 0,
+			"Error reading from /dev/urandom: %s",
+			strerror(errno));
+		exit(1);
+	}
+
+	close(randfd);
+}
+
+void
+write_autoconfig_header(State *s, SystemFileDiskRecord *rec)
+{
+	ocfs_node_config_hdr *hdr;
+
+	hdr = do_malloc(s, s->blocksize);
+	memset(hdr, 0, s->blocksize);
+
+	strcpy(hdr->signature, OCFS2_NODE_CONFIG_HDR_SIGN);
+	hdr->version = OCFS2_NODE_CONFIG_VER;
+	hdr->num_nodes = 0;
+	hdr->disk_lock.dl_master = -1;
+	hdr->last_node = 0;
+
+	do_pwrite(s, hdr, s->blocksize, rec->extent_off);
+	free(hdr);
+}
+
+void
+init_record(State *s, SystemFileDiskRecord *rec, int type, int dir)
+{
+	memset(rec, 0, sizeof(SystemFileDiskRecord));
+
+	rec->flags = OCFS2_VALID_FL | OCFS2_SYSTEM_FL;
+	rec->dir = dir;
+
+	rec->links = dir ? 0 : 1;
+
+	rec->bi.used_bits = rec->bi.total_bits = 0;
+	rec->flags = (OCFS2_VALID_FL | OCFS2_SYSTEM_FL);
+
+	switch (type) {
+	case SFI_JOURNAL:
+		rec->flags |= OCFS2_JOURNAL_FL;
+		break;
+	case SFI_BITMAP:
+		rec->flags |= OCFS2_BITMAP_FL;
+		break;
+	case SFI_LOCAL_ALLOC:
+		rec->flags |= OCFS2_LOCAL_ALLOC_FL;
+		break;
+	case SFI_DLM:
+		rec->flags |= OCFS2_DLM_FL;
+		break;
+	case SFI_CHAIN:
+		rec->flags |= (OCFS2_BITMAP_FL|OCFS2_CHAIN_FL);
+		break;
+	case SFI_OTHER:
+		break;
+	}
+}
+
+
+void
+print_state(State *s)
+{
+	if (s->quiet)
+		return;
+
+	printf("Filesystem label=%s\n", s->vol_label);
+	printf("Block size=%u (bits=%u)\n", s->blocksize, s->blocksize_bits);
+	printf("Cluster size=%u (bits=%u)\n", s->cluster_size, s->cluster_size_bits);
+	printf("Volume size=%llu (%u clusters) (%"PRIu64" blocks)\n",
+	       (unsigned long long) s->volume_size_in_bytes,
+	       s->volume_size_in_clusters, s->volume_size_in_blocks);
+	printf("Initial number of nodes: %u\n", s->initial_nodes);
+}

Added: trunk/mkfs.ocfs2/mkfs_utils.h
===================================================================
--- trunk/mkfs.ocfs2/mkfs_utils.h	2004-10-26 19:14:05 UTC (rev 345)
+++ trunk/mkfs.ocfs2/mkfs_utils.h	2004-10-26 23:49:01 UTC (rev 346)
@@ -0,0 +1,81 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * mkfs_utils.h
+ *
+ * OCFS2 format utility
+ *
+ * Copyright (C) 2004 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, 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.
+ *
+ * Authors: Manish Singh, Kurt Hackel
+ */
+
+#ifndef __MKFS_UTILS_H__
+#define __MKFS_UTILS_H__
+
+#include <mkfs.h>
+
+int get_number(char *arg, uint64_t *res);
+void fill_defaults(State *s);
+int get_bits(State *s, int num);
+void *do_malloc(State *s, size_t size);
+void do_pwrite(State *s, const void *buf, size_t count, uint64_t offset);
+AllocBitmap *initialize_bitmap(State *s, uint32_t bits, uint32_t unit_bits,
+			       const char *name,
+			       SystemFileDiskRecord *bm_record,
+			       SystemFileDiskRecord *alloc_record);
+int find_clear_bits(AllocBitmap *bitmap, uint32_t num_bits, uint32_t offset);
+int alloc_bytes_from_bitmap(State *s, uint64_t bytes, AllocBitmap *bitmap,
+			    uint64_t *start, uint64_t *num);
+int alloc_from_bitmap(State *s, uint64_t num_bits, AllocBitmap *bitmap,
+		      uint64_t *start, uint64_t *num);
+uint64_t alloc_inode(State *s, uint16_t *suballoc_bit);
+DirData *alloc_directory(State *s);
+void add_entry_to_directory(State *s, DirData *dir, char *name,
+			    uint64_t byte_off, uint8_t type);
+uint32_t blocks_needed(State *s);
+uint32_t system_dir_blocks_needed(State *s);
+void adjust_volume_size(State *s);
+void check_32bit_blocks(State *s);
+void format_superblock(State *s, SystemFileDiskRecord *rec,
+		       SystemFileDiskRecord *root_rec,
+		       SystemFileDiskRecord *sys_rec);
+void format_file(State *s, SystemFileDiskRecord *rec);
+void write_metadata(State *s, SystemFileDiskRecord *rec, void *src);
+void write_bitmap_data(State *s, AllocBitmap *bitmap);
+void write_directory_data(State *s, DirData *dir);
+void write_group_data(State *s, AllocGroup *group);
+void format_leading_space(State *s);
+void replacement_journal_create(State *s, uint64_t journal_off);
+void open_device(State *s);
+void close_device(State *s);
+int initial_nodes_for_volume(uint64_t size);
+void generate_uuid(State *s);
+void create_generation(State *s);
+void write_autoconfig_header(State *s, SystemFileDiskRecord *rec);
+void init_record(State *s, SystemFileDiskRecord *rec, int type, int dir);
+void print_state(State *s);
+int ocfs2_clusters_per_group(int block_size,
+			     int cluster_size_bits);
+AllocGroup * initialize_alloc_group(State *s, char *name,
+				    SystemFileDiskRecord *alloc_inode,
+				    uint64_t blkno, uint16_t chain,
+				    uint16_t cpg, uint16_t bpc);
+uint64_t figure_journal_size(uint64_t size, State *s);
+int alloc_from_group(State *s, uint16_t count, AllocGroup *group,
+		     uint64_t *start_blkno, uint16_t *num_bits);
+#endif



More information about the Ocfs2-tools-commits mailing list