[Ocfs-tools-commits] manish commits r167 - trunk/ocfs2/mkfs.ocfs2
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Mon Jul 19 21:28:44 CDT 2004
Author: manish
Date: 2004-07-19 20:28:41 -0500 (Mon, 19 Jul 2004)
New Revision: 167
Added:
trunk/ocfs2/mkfs.ocfs2/mkfs.c
Log:
Land the mkfs redo under a different name, so some side by side tests can be run
Added: trunk/ocfs2/mkfs.ocfs2/mkfs.c
===================================================================
--- trunk/ocfs2/mkfs.ocfs2/mkfs.c 2004-07-20 01:21:35 UTC (rev 166)
+++ trunk/ocfs2/mkfs.ocfs2/mkfs.c 2004-07-20 01:28:41 UTC (rev 167)
@@ -0,0 +1,1279 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * mkfs2.c
+ *
+ * OCFS2 format utility
+ *
+ * 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.
+ *
+ * Authors: Manish Singh, Kurt Hackel
+ */
+
+#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 <linux/bitops.h>
+
+#include "ocfs2.h"
+#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 MAGIC_SUPERBLOCK_BLOCK_NUMBER 2
+
+#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
+
+
+enum {
+ SFI_JOURNAL,
+ SFI_BITMAP,
+ SFI_LOCAL_ALLOC,
+ SFI_DLM,
+ 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 _SystemFileDiskRecord SystemFileDiskRecord;
+
+struct _SystemFileDiskRecord {
+ uint64_t fe_off;
+ uint64_t extent_off;
+ uint64_t extent_len;
+ uint64_t file_size;
+
+ 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;
+
+ char *vol_label;
+ char *device_name;
+ char *uuid;
+
+ int fd;
+
+ time_t format_time;
+
+ AllocBitmap *global_bm;
+ AllocBitmap *system_bm;
+};
+
+
+static State *get_state (int argc, char **argv);
+static void usage(const char *progname);
+static void version(const char *progname);
+static void fill_defaults(State *s);
+static int get_bits(State *s, int num);
+static void *do_malloc(State *s, size_t size);
+static void do_pwrite(State *s, const void *buf, size_t count, uint64_t offset);static AllocBitmap *initialize_bitmap(State *s, uint32_t bits,
+ uint32_t unit_bits, const char *name,
+ SystemFileDiskRecord *bm_record,
+ SystemFileDiskRecord *alloc_record);
+static int find_clear_bits(AllocBitmap *bitmap, uint32_t num_bits,
+ uint32_t offset);
+static int alloc_bytes_from_bitmap(State *s, uint64_t bytes,
+ AllocBitmap *bitmap, uint64_t *start,
+ uint64_t *num);
+static int alloc_from_bitmap(State *s, uint64_t num_bits, AllocBitmap *bitmap,
+ uint64_t *start, uint64_t *num);
+static uint64_t alloc_inode(State *s, int num_blocks);
+static DirData *alloc_directory(State *s);
+static void add_entry_to_directory(State *s, DirData *dir, char *name,
+ uint64_t byte_off, uint8_t type);
+static uint32_t blocks_needed(State *s);
+static uint32_t system_dir_blocks_needed(State *s);
+static void adjust_volume_size(State *s);
+static void format_superblock(State *s, SystemFileDiskRecord *rec,
+ SystemFileDiskRecord *root_rec,
+ SystemFileDiskRecord *sys_rec);
+static void format_file(State *s, SystemFileDiskRecord *rec);
+static void write_metadata(State *s, SystemFileDiskRecord *rec, void *src);
+static void write_bitmap_data(State *s, AllocBitmap *bitmap);
+static void write_directory_data(State *s, DirData *dir);
+static void format_leading_space(State *s, uint64_t start);
+static void replacement_journal_create(State *s, uint64_t journal_off);
+static void open_device(State *s);
+static void close_device(State *s);
+static int initial_nodes_for_volume(uint64_t size);
+static void generate_uuid(State *s);
+static void write_autoconfig_header(State *s, SystemFileDiskRecord *rec);
+static void init_record(State *s, SystemFileDiskRecord *rec, int type, int dir);
+
+
+extern char *optarg;
+extern int optind, opterr, optopt;
+
+SystemFileInfo system_files[] = {
+ { "bad_blocks", SFI_OTHER, 1, 0 },
+ { "global_inode_alloc", SFI_OTHER, 1, 0 },
+ { "global_inode_alloc_bitmap", SFI_BITMAP, 1, 0 },
+ { "dlm", SFI_DLM, 1, 0 },
+ { "global_bitmap", SFI_BITMAP, 1, 0 },
+ { "orphan_dir", SFI_OTHER, 1, 1 },
+ { "extent_alloc:%04d", SFI_OTHER, 0, 0 },
+ { "extent_alloc_bitmap:%04d", SFI_BITMAP, 0, 0 },
+ { "inode_alloc:%04d", SFI_OTHER, 0, 0 },
+ { "inode_alloc_bitmap:%04d", SFI_BITMAP, 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 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;
+ uint64_t leading_space;
+ SystemFileDiskRecord *tmprec, *tmprec2;
+ char fname[SYSTEM_FILE_NAME_MAX];
+
+ s = get_state(argc, argv);
+
+ open_device(s);
+
+ fill_defaults(s);
+
+ adjust_volume_size(s);
+
+ generate_uuid (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;
+
+ 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);
+
+ tmprec = &(record[GLOBAL_INODE_ALLOC_SYSTEM_INODE][0]);
+ tmprec2 = &(record[GLOBAL_INODE_ALLOC_BITMAP_SYSTEM_INODE][0]);
+ need = blocks_needed(s);
+
+ alloc_bytes_from_bitmap (s, need << s->blocksize_bits, s->global_bm,
+ &(tmprec->extent_off), &(tmprec->extent_len));
+
+ need = ((((need + 7) >> 3) + s->cluster_size - 1) >> s->cluster_size_bits) << s->cluster_size_bits;
+ alloc_bytes_from_bitmap (s, need, s->global_bm, &(tmprec2->extent_off),
+ &(tmprec2->extent_len));
+
+ s->system_bm =
+ initialize_bitmap(s, tmprec->extent_len >> s->blocksize_bits,
+ s->blocksize_bits, "system inode bitmap",
+ tmprec2, tmprec);
+
+ leading_space = alloc_inode(s, LEADING_SPACE_BLOCKS);
+ if (leading_space != 0ULL) {
+ com_err(s->progname, 0,
+ "Leading space blocks start at byte %llu, "
+ "must start at 0", leading_space);
+ exit(1);
+ }
+
+ superblock_rec.fe_off = alloc_inode(s, SUPERBLOCK_BLOCKS);
+ if (superblock_rec.fe_off != (__u64)MAGIC_SUPERBLOCK_BLOCK_NUMBER << s->blocksize_bits) {
+ com_err(s->progname, 0,
+ "Superblock starts at byte %llu, "
+ "must start at %llu",
+ superblock_rec.fe_off,
+ MAGIC_SUPERBLOCK_BLOCK_NUMBER << s->blocksize_bits);
+ exit(1);
+ }
+
+ 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, 1);
+ 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, 1);
+ system_dir->record = &system_dir_rec;
+ add_entry_to_directory(s, system_dir, ".", system_dir_rec.extent_off, OCFS2_FT_DIR);
+ add_entry_to_directory(s, system_dir, "..", system_dir_rec.extent_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, 1);
+ 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);
+ }
+ }
+
+ 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->extent_off, OCFS2_FT_DIR);
+ add_entry_to_directory(s, orphan_dir, "..", tmprec->extent_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, leading_space);
+ format_superblock(s, &superblock_rec, &root_dir_rec, &system_dir_rec);
+
+ 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, OCFS2_DEFAULT_JOURNAL_SIZE,
+ 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_bitmap_data(s, s->system_bm);
+
+ write_directory_data(s, root_dir);
+ write_directory_data(s, system_dir);
+ write_directory_data(s, orphan_dir);
+
+ write_autoconfig_header(s, &record[DLM_SYSTEM_INODE][0]);
+
+ close_device(s);
+
+ return 0;
+}
+
+static State *
+get_state(int argc, char **argv)
+{
+ char *progname = "mkfs.ocfs2";
+ 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;
+
+ static struct option long_state[] = {
+ { "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' },
+ { 0, 0, 0, 0}
+ };
+
+ if (argc && *argv) {
+ char *cp;
+ cp = strrchr(argv[0], '/');
+ progname = cp ? cp + 1 : argv[0];
+ }
+
+ while (1) {
+ c = getopt_long(argc, argv, "b:c:L:n:vqV", long_state, NULL);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'b':
+ blocksize = strtoul(optarg, &dummy, 0);
+
+ if (blocksize < OCFS2_MIN_BLOCKSIZE ||
+ blocksize > OCFS2_MAX_BLOCKSIZE ||
+ *dummy != '\0') {
+ com_err(progname, 0,
+ "Invalid blocksize %s: "
+ "must be between %d and %d",
+ optarg,
+ OCFS2_MIN_BLOCKSIZE,
+ OCFS2_MAX_BLOCKSIZE);
+ exit(1);
+ }
+
+ break;
+
+ case 'c':
+ cluster_size = strtoul(optarg, &dummy, 0);
+
+ if (*dummy != '\0') {
+ com_err(progname, 0,
+ "Invalid cluster size %s", optarg);
+ exit(1);
+ }
+
+ 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 '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 = strdup(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);
+
+ return s;
+}
+
+static void
+usage(const char *progname)
+{
+ fprintf(stderr, "Usage: %s [\n", progname);
+ exit(0);
+}
+
+static void
+version(const char *progname)
+{
+ fprintf(stderr, "%s %s %s (build %s)\n", progname,
+ OCFS2_BUILD_VERSION, OCFS2_BUILD_DATE, OCFS2_BUILD_MD5);
+}
+
+static void
+fill_defaults(State *s)
+{
+ /* XXX: Basics, needs to be redone */
+
+ size_t pagesize;
+ errcode_t err;
+ uint32_t ret;
+
+ pagesize = getpagesize();
+
+ s->pagesize_bits = get_bits(s, pagesize);
+
+ if (!s->blocksize) {
+ s->blocksize = 1024;
+ }
+
+ s->blocksize_bits = get_bits(s, s->blocksize);
+
+ if (!s->cluster_size) {
+ s->cluster_size = 4096;
+ }
+
+ s->cluster_size_bits = get_bits(s, s->cluster_size);
+
+ 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;
+ s->volume_size_in_clusters = s->volume_size_in_bytes >> s->cluster_size_bits;
+
+ if (!s->initial_nodes) {
+ s->initial_nodes =
+ initial_nodes_for_volume(s->volume_size_in_bytes);
+ }
+}
+
+static 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;
+}
+
+static 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;
+}
+
+static 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);
+ }
+}
+
+static 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
+
+static 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 = find_next_zero_bit(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;
+}
+
+static 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);
+}
+
+static 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 %llu 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--) {
+ set_bit(start_bit, bitmap->buf);
+ start_bit++;
+ }
+
+ free(buf);
+
+ return 0;
+}
+
+static uint64_t
+alloc_inode(State *s, int num_blocks)
+{
+ uint64_t ret, num;
+
+ alloc_from_bitmap(s, num_blocks, s->system_bm, &ret, &num);
+
+ return ret;
+}
+
+static DirData *
+alloc_directory(State *s)
+{
+ DirData *dir;
+
+ dir = do_malloc(s, sizeof(DirData));
+ memset(dir, 0, sizeof(DirData));
+
+ return dir;
+}
+
+static 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++;
+}
+
+static 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;
+}
+
+static 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;
+}
+
+static 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;
+}
+
+static 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_blkno = cpu_to_le64(super_off >> s->blocksize_bits);
+
+ 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->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);
+}
+
+static 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 = 0;
+ di->i_suballoc_node = cpu_to_le16(-1);
+ di->i_suballoc_blkno = cpu_to_le64(rec->fe_off >> s->blocksize_bits);
+ 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 = 0;
+ 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);
+ }
+
+ 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);
+}
+
+static 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);
+}
+
+static void
+write_bitmap_data(State *s, AllocBitmap *bitmap)
+{
+ write_metadata(s, bitmap->bm_record, bitmap->buf);
+}
+
+static void
+write_directory_data(State *s, DirData *dir)
+{
+ write_metadata(s, dir->record, dir->buf);
+}
+
+static void
+format_leading_space(State *s, uint64_t start)
+{
+ 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, start);
+ free(buf);
+}
+
+static void
+replacement_journal_create(State *s, uint64_t journal_off)
+{
+ journal_superblock_t *sb;
+ void *buf;
+
+ buf = do_malloc(s, OCFS2_DEFAULT_JOURNAL_SIZE);
+ memset(buf, 0, OCFS2_DEFAULT_JOURNAL_SIZE);
+
+ 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(OCFS2_DEFAULT_JOURNAL_SIZE >> 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);
+}
+
+static 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);
+ }
+}
+
+static void
+close_device(State *s)
+{
+ fsync(s->fd);
+ close(s->fd);
+ s->fd = -1;
+}
+
+static 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? */
+static 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);
+}
+
+static 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);
+}
+
+static 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_OTHER:
+ break;
+ }
+}
More information about the Ocfs-tools-commits
mailing list