[Ocfs2-tools-commits] jlbec commits r356 - trunk/libocfs2
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Mon Nov 1 22:43:00 CST 2004
Author: jlbec
Date: 2004-11-01 22:42:58 -0600 (Mon, 01 Nov 2004)
New Revision: 356
Added:
trunk/libocfs2/chainalloc.c
Log:
Im an ididot
Added: trunk/libocfs2/chainalloc.c
===================================================================
--- trunk/libocfs2/chainalloc.c 2004-11-02 03:50:20 UTC (rev 355)
+++ trunk/libocfs2/chainalloc.c 2004-11-02 04:42:58 UTC (rev 356)
@@ -0,0 +1,533 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * chainalloc.c
+ *
+ * Functions to use the chain allocators for the OCFS2 userspace
+ * library.
+ *
+ * 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.
+ */
+
+#define _XOPEN_SOURCE 600 /* Triggers magic in features.h */
+#define _LARGEFILE64_SOURCE
+
+#include <string.h>
+#include <inttypes.h>
+
+#include "ocfs2.h"
+
+#include "bitmap.h"
+#include "kernel-rbtree.h"
+
+
+struct chainalloc_bitmap_private {
+ ocfs2_cached_inode *cb_cinode;
+ errcode_t cb_errcode;
+};
+
+struct chainalloc_region_private {
+ struct chainalloc_bitmap_private *cr_cb;
+ struct _ocfs2_group_desc *cr_ag;
+ int cr_dirty;
+};
+
+
+static void chainalloc_destroy_notify(ocfs2_bitmap *bitmap)
+{
+ struct rb_node *node = NULL;
+ struct ocfs2_bitmap_region *br;
+
+ for (node = rb_first(&bitmap->b_regions); node; node = rb_next(node)) {
+ br = rb_entry(node, struct ocfs2_bitmap_region, br_node);
+ ocfs2_free(&br->br_private);
+ }
+
+ ocfs2_free(&bitmap->b_private);
+}
+
+static int chainalloc_process_group(ocfs2_filesys *fs,
+ uint64_t gd_blkno,
+ int chain_num,
+ void *priv_data)
+{
+ ocfs2_bitmap *bitmap = priv_data;
+ struct ocfs2_bitmap_region *br;
+ struct chainalloc_bitmap_private *cb = bitmap->b_private;
+ struct chainalloc_region_private *cr;
+ char *gd_buf;
+
+ cb->cb_errcode = ocfs2_malloc_block(fs->fs_io, &gd_buf);
+ if (cb->cb_errcode)
+ return OCFS2_CHAIN_ABORT;
+
+ cb->cb_errcode = ocfs2_read_group_desc(fs, gd_blkno, gd_buf);
+ if (cb->cb_errcode)
+ goto out_free_buf;
+
+ cb->cb_errcode = ocfs2_malloc0(sizeof(struct chainalloc_region_private),
+ &cr);
+ if (cb->cb_errcode)
+ goto out_free_buf;
+
+ cr->cr_cb = cb;
+ cr->cr_ag = (ocfs2_group_desc *)gd_buf;
+
+ cb->cb_errcode = OCFS2_ET_CORRUPT_GROUP_DESC;
+ if (cr->cr_ag->bg_bits % 8)
+ goto out_free_cr;
+
+ cb->cb_errcode = ocfs2_bitmap_alloc_region(bitmap,
+ gd_blkno,
+ cr->cr_ag->bg_bits,
+ &br);
+ if (cb->cb_errcode)
+ goto out_free_cr;
+
+ br->br_private = cr;
+ memcpy(br->br_bitmap, cr->cr_ag->bg_bitmap,
+ cr->cr_ag->bg_bits / 8);
+ br->br_set_bits = cr->cr_ag->bg_bits -
+ cr->cr_ag->bg_free_bits_count;
+
+ cb->cb_errcode = ocfs2_bitmap_insert_region(bitmap, br);
+ if (cb->cb_errcode)
+ goto out_free_region;
+
+ return 0;
+
+out_free_region:
+ ocfs2_bitmap_free_region(br);
+
+out_free_cr:
+ ocfs2_free(&cr);
+
+out_free_buf:
+ ocfs2_free(&gd_buf);
+
+ return OCFS2_CHAIN_ABORT;
+}
+
+
+static errcode_t chainalloc_read_bitmap(ocfs2_bitmap *bitmap)
+{
+ errcode_t ret;
+ struct chainalloc_bitmap_private *cb = bitmap->b_private;
+
+ if (!cb->cb_cinode)
+ return OCFS2_ET_INVALID_ARGUMENT;
+
+ ret = ocfs2_chain_iterate(bitmap->b_fs,
+ cb->cb_cinode->ci_blkno,
+ chainalloc_process_group,
+ bitmap);
+
+ return ret;
+}
+
+static int chainalloc_merge_region(ocfs2_bitmap *bitmap,
+ struct ocfs2_bitmap_region *prev,
+ struct ocfs2_bitmap_region *next)
+{
+ /* Can't merge */
+ return 0;
+}
+
+static struct ocfs2_bitmap_operations chainalloc_bitmap_ops = {
+ .set_bit = ocfs2_bitmap_set_generic,
+ .clear_bit = ocfs2_bitmap_clear_generic,
+ .test_bit = ocfs2_bitmap_test_generic,
+ .find_next_set = ocfs2_bitmap_find_next_set_generic,
+ .find_next_clear = ocfs2_bitmap_find_next_clear_generic,
+ .merge_region = chainalloc_merge_region,
+ .read_bitmap = chainalloc_read_bitmap,
+ .destroy_notify = chainalloc_destroy_notify,
+};
+
+static errcode_t ocfs2_chainalloc_bitmap_new(ocfs2_filesys *fs,
+ const char *description,
+ ocfs2_bitmap **ret_bitmap)
+{
+ errcode_t ret;
+ ocfs2_bitmap *bitmap;
+ struct chainalloc_bitmap_private *cb;
+
+ ret = ocfs2_malloc0(sizeof(struct chainalloc_bitmap_private),
+ &cb);
+ if (ret)
+ return ret;
+
+ ret = ocfs2_bitmap_new(fs,
+ fs->fs_blocks,
+ description ? description :
+ "Generic chain allocator bitmap",
+ &chainalloc_bitmap_ops,
+ cb,
+ &bitmap);
+ if (ret)
+ return ret;
+
+ *ret_bitmap = bitmap;
+
+ return 0;
+}
+
+static void ocfs2_chainalloc_set_cinode(ocfs2_bitmap *bitmap,
+ ocfs2_cached_inode *cinode)
+{
+ struct chainalloc_bitmap_private *cb = bitmap->b_private;
+
+ cb->cb_cinode = cinode;
+}
+
+errcode_t ocfs2_load_chain_allocator(ocfs2_filesys *fs,
+ ocfs2_cached_inode *cinode)
+{
+ errcode_t ret;
+ char name[256];
+
+ if (cinode->ci_chains)
+ ocfs2_bitmap_free(cinode->ci_chains);
+
+ snprintf(name, sizeof(name),
+ "Chain allocator inode %llu", cinode->ci_blkno);
+ ret = ocfs2_chainalloc_bitmap_new(fs, name, &cinode->ci_chains);
+ if (ret)
+ return ret;
+
+ ocfs2_chainalloc_set_cinode(cinode->ci_chains,
+ cinode);
+ ret = ocfs2_bitmap_read(cinode->ci_chains);
+ if (ret) {
+ ocfs2_bitmap_free(cinode->ci_chains);
+ return ret;
+ }
+
+ return 0;
+}
+
+errcode_t ocfs2_write_chain_allocator(ocfs2_filesys *fs,
+ ocfs2_cached_inode *cinode)
+{
+ if (!cinode->ci_chains)
+ return OCFS2_ET_INVALID_ARGUMENT;
+
+ return ocfs2_bitmap_write(cinode->ci_chains);
+}
+
+#ifdef DEBUG_EXE
+#include <stdlib.h>
+#include <getopt.h>
+#include <limits.h>
+
+static uint64_t read_number(const char *num)
+{
+ uint64_t val;
+ char *ptr;
+
+ val = strtoull(num, &ptr, 0);
+ if (!ptr || *ptr)
+ return 0;
+
+ return val;
+}
+
+static void print_usage(void)
+{
+ fprintf(stderr,
+ "debug_bitmap [-i <blkno>] <filename>\n");
+}
+
+extern int opterr, optind;
+extern char *optarg;
+
+static void dump_regions(ocfs2_bitmap *bitmap)
+{
+ struct ocfs2_bitmap_region *br;
+ struct rb_node *node;
+
+ fprintf(stdout, "Bitmap \"%s\": total = %"PRIu64", set = %"PRIu64"\n",
+ bitmap->b_description, bitmap->b_total_bits,
+ bitmap->b_set_bits);
+
+ for (node = rb_first(&bitmap->b_regions);node; node = rb_next(node)) {
+ br = rb_entry(node, struct ocfs2_bitmap_region, br_node);
+
+ fprintf(stdout,
+ "(start: %"PRIu64", n: %d, set: %d)\n",
+ br->br_start_bit, br->br_total_bits,
+ br->br_set_bits);
+ }
+}
+
+static void print_bitmap(ocfs2_bitmap *bitmap)
+{
+ uint64_t bitno;
+ uint64_t gap_start = 0; /* GCC is dumb */
+ errcode_t ret;
+ int val, gap;
+
+ gap = 0;
+ for (bitno = 0; bitno < bitmap->b_total_bits; bitno++) {
+ ret = ocfs2_bitmap_test(bitmap, bitno, &val);
+ if (ret) {
+ if (ret == OCFS2_ET_INVALID_BIT) {
+ if (!gap) {
+ gap = 1;
+ gap_start = bitno;
+ }
+ continue;
+ }
+ com_err("print_bitmap", ret,
+ "while testing bit %"PRIu64"\n", bitno);
+ break;
+ }
+ if (gap) {
+ fprintf(stdout,
+ "\nGap of length %"PRIu64" at %"PRIu64"\n",
+ bitno - gap_start, gap_start);
+ gap = bitno % 72;
+ gap += gap / 8;
+ for (; gap; gap--)
+ fprintf(stdout, " ");
+ fflush(stdout);
+ } else {
+ if (bitno && !(bitno % 72))
+ fprintf(stdout, "\n");
+ else if (bitno && !(bitno % 8))
+ fprintf(stdout, " ");
+ }
+ fprintf(stdout, "%d", val);
+ fflush(stdout);
+ }
+
+ if ((bitno - 1) % 72)
+ fprintf(stdout, "\n");
+}
+
+static int try_op(ocfs2_bitmap *bitmap,
+ errcode_t (*func)(ocfs2_bitmap *bitmap,
+ uint64_t bitno,
+ int *val),
+ char *bit_val, int *ret_val)
+{
+ errcode_t ret;
+ uint64_t bitno;
+ char *ptr;
+
+ if (!bit_val) {
+ fprintf(stderr, "You must provide a bit offset\n");
+ return 1;
+ }
+
+ bitno = read_number(bit_val);
+ if (!bitno) {
+ for (ptr = bit_val; *ptr; ptr++) {
+ if (*ptr != '0')
+ break;
+ }
+ if ((ptr == bit_val) || *ptr) {
+ fprintf(stderr, "Invalid bit offset: %s\n",
+ bit_val);
+ return 1;
+ }
+ }
+
+ ret = (*func)(bitmap, bitno, ret_val);
+ if (ret) {
+ com_err("try_op", ret, "while setting bit %"PRIu64"\n", bitno);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int try_op64(ocfs2_bitmap *bitmap,
+ errcode_t (*func)(ocfs2_bitmap *bitmap,
+ uint64_t bitno,
+ uint64_t *val),
+ char *bit_val, uint64_t *ret_val)
+{
+ errcode_t ret;
+ uint64_t bitno;
+ char *ptr;
+
+ if (!bit_val) {
+ fprintf(stderr, "You must provide a bit offset\n");
+ return 1;
+ }
+
+ bitno = read_number(bit_val);
+ if (!bitno) {
+ for (ptr = bit_val; *ptr; ptr++) {
+ if (*ptr != '0')
+ break;
+ }
+ if ((ptr == bit_val) || *ptr) {
+ fprintf(stderr, "Invalid bit offset: %s\n",
+ bit_val);
+ return 1;
+ }
+ }
+
+ ret = (*func)(bitmap, bitno, ret_val);
+ if (ret) {
+ com_err("try_op64", ret, "while setting bit %"PRIu64"\n", bitno);
+ return 1;
+ }
+
+ return 0;
+}
+
+
+static void run_test(ocfs2_bitmap *bitmap)
+{
+ char buf[256];
+ char *ptr, *cmd;
+ uint64_t val64;
+ int val;
+
+ while (1) {
+ fprintf(stdout, "Command: ");
+ fflush(stdout);
+
+ if (!fgets(buf, sizeof(buf), stdin))
+ break;
+
+ ptr = buf + strlen(buf) - 1;
+ if (*ptr == '\n')
+ *ptr = '\0';
+
+ for (cmd = buf; (*cmd == ' ') || (*cmd == '\t'); cmd++);
+
+ if (!(*cmd))
+ continue;
+
+ ptr = strchr(cmd, ' ');
+ if (ptr) {
+ *ptr = '\0';
+ ptr++;
+ }
+
+ if (!strcmp(cmd, "set")) {
+ try_op(bitmap, ocfs2_bitmap_set, ptr, NULL);
+ } else if (!strcmp(cmd, "clear")) {
+ try_op(bitmap, ocfs2_bitmap_clear, ptr, NULL);
+ } else if (!strcmp(cmd, "test")) {
+ if (!try_op(bitmap, ocfs2_bitmap_test, ptr,
+ &val)) {
+ fprintf(stdout, "Bit %s is %s\n",
+ ptr, val ? "set" : "clear");
+ }
+ } else if (!strcmp(cmd, "fns")) {
+ if (!try_op64(bitmap,
+ ocfs2_bitmap_find_next_set,
+ ptr, &val64)) {
+ fprintf(stdout, "Found %"PRIu64"\n",
+ val64);
+ }
+ } else if (!strcmp(cmd, "fnc")) {
+ if (!try_op64(bitmap,
+ ocfs2_bitmap_find_next_clear,
+ ptr, &val64)) {
+ fprintf(stdout, "Found %"PRIu64"\n",
+ val64);
+ }
+ } else if (!strcmp(cmd, "print")) {
+ print_bitmap(bitmap);
+ } else if (!strcmp(cmd, "dump")) {
+ dump_regions(bitmap);
+ } else if (!strcmp(cmd, "quit")) {
+ break;
+ } else {
+ fprintf(stderr, "Invalid command: \"%s\"\n",
+ cmd);
+ }
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ errcode_t ret;
+ int c;
+ char *filename;
+ uint64_t blkno = 0;
+ ocfs2_filesys *fs;
+ ocfs2_cached_inode *cinode;
+
+ initialize_ocfs_error_table();
+
+ while ((c = getopt(argc, argv, "i:")) != EOF) {
+ switch (c) {
+ case 'i':
+ blkno = read_number(optarg);
+ if (!blkno) {
+ print_usage();
+ return 1;
+ }
+ break;
+
+ default:
+ print_usage();
+ return 1;
+ break;
+ }
+ }
+
+ if (optind >= argc) {
+ fprintf(stderr, "Missing filename\n");
+ print_usage();
+ return 1;
+ }
+ filename = argv[optind];
+
+ ret = ocfs2_open(filename, OCFS2_FLAG_RO, 0, 0, &fs);
+ if (ret) {
+ com_err(argv[0], ret,
+ "while opening file \"%s\"", filename);
+ return 1;
+ }
+
+ ret = ocfs2_read_cached_inode(fs, blkno,
+ &cinode);
+ if (ret) {
+ com_err(argv[0], ret,
+ "while reading inode %"PRIu64, blkno);
+ goto out_close;
+ }
+
+ ret = ocfs2_load_chain_allocator(fs, cinode);
+ if (ret) {
+ com_err(argv[0], ret,
+ "while loading chain allocator");
+ goto out_free_inode;
+ }
+
+ run_test(cinode->ci_chains);
+
+out_free_inode:
+ ocfs2_free_cached_inode(fs, cinode);
+
+out_close:
+ ocfs2_close(fs);
+
+ return ret;
+}
+
+
+
+#endif /* DEBUG_EXE */
More information about the Ocfs2-tools-commits
mailing list