예제 #1
0
파일: main.c 프로젝트: djs55/ocfs2-tools
/*
 * main()
 *
 */
int main(int argc, char **argv)
{
	ocfs2_filesys *fs = NULL;
	errcode_t ret = 0;
	int i;

	initialize_ocfs_error_table();

#define INSTALL_SIGNAL(sig)					\
	do {							\
		if (signal(sig, handle_signal) == SIG_ERR) {	\
		    fprintf(stderr, "Could not set " #sig "\n");\
		    goto bail;					\
		}						\
	} while (0)

	INSTALL_SIGNAL(SIGTERM);
	INSTALL_SIGNAL(SIGINT);

	memset(corrupt, 0, sizeof(corrupt));

	ret = read_options(argc, argv);
	if (ret < 0)
		goto bail;

	print_version();

	ret = ocfs2_open(device, OCFS2_FLAG_RW, 0, 0, &fs);
	if (ret) {
		com_err(progname, ret, "while opening \"%s\"", device);
		goto bail;
	}

	for (i = 0; i < NUM_FSCK_TYPE; ++i) {
		if (corrupt[i]) {
			if (!prompt_codes[i].pc_func) {
				fprintf(stderr, "Unimplemented corrupt code "
					"= %s\n", prompt_codes[i].pc_codestr);
				continue;
			}
			fprintf(stdout, "%s: Corrupting %s with code %s (%d)\n",
				progname, device, prompt_codes[i].pc_codestr,
				prompt_codes[i].pc_codenum);
			prompt_codes[i].pc_func(fs, prompt_codes[i].pc_codenum,
						slotnum);
		}
	}

bail:
	if (fs) {
		ret = ocfs2_close(fs);
		if (ret)
			com_err(progname, ret, "while closing \"%s\"", device);
	}

	return ret;
}					/* main */
예제 #2
0
int main (int argc, char **argv)
{
	ocfs2_filesys *fs = NULL;
	errcode_t ret = 1;

	initialize_ocfs_error_table();

#define INSTALL_SIGNAL(sig)					\
	do {							\
		if (signal(sig, handle_signal) == SIG_ERR) {	\
		    printf("Could not set " #sig "\n");		\
		    goto bail;					\
		}						\
	} while (0)

	INSTALL_SIGNAL(SIGTERM);
	INSTALL_SIGNAL(SIGINT);

	memset(&options, 0, sizeof(options));
	if (read_options(argc, argv)) {
		usage(progname);
		goto bail;
	}

	if (!device || !options.ops)
		goto bail;

	ret = ocfs2_open(device, OCFS2_FLAG_RW, 0, 0, &fs);
	if (ret) {
		com_err(progname, ret, "while opening \"%s\"", device);
		goto bail;
	}

	srand((unsigned long)fs);

	switch (options.ops) {
		case CREATE_LOCAL_ALLOC:
			ret = create_local_alloc(fs, options.slot);
			break;

		case CREATE_ORPHAN_FILE:
			ret = create_orphan_file(fs, options.slot);
			break;

		case CREATE_TRUNCATE_LOG:
			ret = create_truncate_log(fs, options.slot);
			break;
	}
bail:
	if (fs)
		ocfs2_close(fs);

	return ret;
}
예제 #3
0
void
initocfs2 (void)
{
  PyObject *m;

  if (PyType_Ready (&DInode_Type) < 0)
    return;

  if (PyType_Ready (&DirEntry_Type) < 0)
    return;

  if (PyType_Ready (&SuperBlock_Type) < 0)
    return;

  if (PyType_Ready (&DirScanIter_Type) < 0)
    return;

  Filesystem_Type.tp_new = PyType_GenericNew;
  if (PyType_Ready (&Filesystem_Type) < 0)
    return;

  initialize_ocfs_error_table ();

  m = Py_InitModule ("ocfs2", ocfs2_methods);

  ocfs2_error = PyErr_NewException ("ocfs2.error", PyExc_RuntimeError, NULL);

  if (ocfs2_error)
    {
      Py_INCREF (ocfs2_error);
      PyModule_AddObject (m, "error", ocfs2_error);
    }

  Py_INCREF (&DInode_Type);
  PyModule_AddObject (m, "DInode", (PyObject *) &DInode_Type);

  Py_INCREF (&DirEntry_Type);
  PyModule_AddObject (m, "DirEntry", (PyObject *) &DirEntry_Type);

  Py_INCREF (&SuperBlock_Type);
  PyModule_AddObject (m, "SuperBlock", (PyObject *) &SuperBlock_Type);

  Py_INCREF (&DirScanIter_Type);
  PyModule_AddObject (m, "DirScanIter", (PyObject *) &DirScanIter_Type);

  Py_INCREF (&Filesystem_Type);
  PyModule_AddObject (m, "Filesystem", (PyObject *) &Filesystem_Type);

  add_constants (m);

  if (PyErr_Occurred ())
    Py_FatalError ("can't initialize module ocfs2");
}
예제 #4
0
파일: openfs.c 프로젝트: pepe5/ocfs2-tools
int main(int argc, char *argv[])
{
	errcode_t ret;
	int c;
	int64_t blkno, blksize;
	char *filename;
	ocfs2_filesys *fs;

	/* These mean "autodetect" */
	blksize = 0;
	blkno = 0;

	initialize_ocfs_error_table();

	while((c = getopt(argc, argv, "s:B:")) != EOF) {
		switch (c) {
			case 's':
				blkno = read_number(optarg);
				if (blkno < OCFS2_SUPER_BLOCK_BLKNO) {
					fprintf(stderr,
						"Invalid blkno: %s\n",
						optarg);
					print_usage();
					return 1;
				}
				break;

			case 'B':
				blksize = read_number(optarg);
				if (blksize < OCFS2_MIN_BLOCKSIZE) {
					fprintf(stderr, 
						"Invalid blksize: %s\n",
						optarg);
					print_usage();
					return 1;
				}
				break;

			default:
				print_usage();
				return 1;
				break;
		}
	}

	if (blksize % OCFS2_MIN_BLOCKSIZE) {
		fprintf(stderr, "Invalid blocksize: %"PRId64"\n", blksize);
		print_usage();
		return 1;
	}

	if (optind >= argc) {
		fprintf(stderr, "Missing filename\n");
		print_usage();
		return 1;
	}

	filename = argv[optind];

	ret = ocfs2_open(filename, OCFS2_FLAG_RO, blkno, blksize, &fs);
	if (ret) {
		com_err(argv[0], ret,
			"while opening file \"%s\"", filename);
		goto out;
	}

	fprintf(stdout, "OCFS2 filesystem on \"%s\":\n", filename);
	fprintf(stdout,
		"\tblocksize = %d\n"
 		"\tclustersize = %d\n"
		"\tclusters = %u\n"
		"\tblocks = %"PRIu64"\n"
		"\troot_blkno = %"PRIu64"\n"
		"\tsystem_dir_blkno = %"PRIu64"\n",
 		fs->fs_blocksize,
		fs->fs_clustersize,
		fs->fs_clusters,
		fs->fs_blocks,
		fs->fs_root_blkno,
		fs->fs_sysdir_blkno);

	ret = ocfs2_close(fs);
	if (ret) {
		com_err(argv[0], ret,
			"while closing file \"%s\"", filename);
	}

out:
	return 0;
}
예제 #5
0
int main(int argc, char *argv[])
{
	errcode_t ret;
	uint64_t blkno;
	char *filename;
	ocfs2_filesys *fs;
	struct walk_path wp;

	blkno = OCFS2_SUPER_BLOCK_BLKNO;

	initialize_ocfs_error_table();

	wp.argv0 = argv[0];
	wp.quiet = 0;
	wp.has_dups = 0;
	wp.check_dups = 0;
	if (argc < 2) {
		fprintf(stderr, "Missing filename\n");
		print_usage();
		return 1;
	}
	filename = argv[1];

	if (argc > 2) {
		if (!strcmp(argv[2], "-q"))
			wp.quiet = 1;
	}
	
	ret = ocfs2_open(filename, OCFS2_FLAG_RO, 0, 0, &fs);
	if (ret) {
		com_err(argv[0], ret,
			"while opening file \"%s\"", filename);
		goto out;
	}
	wp.fs = fs;

	ret = ocfs2_block_bitmap_new(fs, "Inode bitmap", &wp.inode_map);
	if (ret) {
		com_err(argv[0], ret,
			"while creating the inode bitmap");
		goto out_close;
	}

	ret = ocfs2_block_bitmap_new(fs, "Duplicate inode bitmap",
				     &wp.dup_map);
	if (ret) {
		com_err(argv[0], ret,
			"while creating the duplicate inode bitmap");
		goto out_close;
	}

	ocfs2_bitmap_set(wp.inode_map,
			 OCFS2_RAW_SB(fs->fs_super)->s_system_dir_blkno,
			 NULL);
	ocfs2_bitmap_set(wp.inode_map,
			 OCFS2_RAW_SB(fs->fs_super)->s_root_blkno,
			 NULL);

	fprintf(stdout, "Walking system directory...\n");
	wp.path = "<system_dir>/";
	ret = ocfs2_dir_iterate(fs,
				OCFS2_RAW_SB(fs->fs_super)->s_system_dir_blkno,
				0, NULL, walk_tree_func, &wp);
	if (ret) {
		com_err(argv[0], ret,
			"while walking sysdm dir inode %"PRIu64" on \"%s\"\n",
			blkno, filename);
		goto out_close;
	}
	wp.path = "/";
	fprintf(stdout, "Walking root directory...\n");
	ret = ocfs2_dir_iterate(fs,
				OCFS2_RAW_SB(fs->fs_super)->s_root_blkno,
				0, NULL, walk_tree_func, &wp);
	if (ret) {
		com_err(argv[0], ret,
			"while walking root inode %"PRIu64" on \"%s\"\n",
			blkno, filename);
		goto out_close;
	}

	if (wp.has_dups) {
		fprintf(stdout, "Hardlinks found\n");

		wp.check_dups = 1;
		fprintf(stdout, "Scanning system directory for dups...\n");
		wp.path = "<system_dir>/";
		ret = ocfs2_dir_iterate(fs,
					OCFS2_RAW_SB(fs->fs_super)->s_system_dir_blkno,
					0, NULL, walk_tree_func, &wp);
		if (ret) {
			com_err(argv[0], ret,
				"while dup scanning sysdm dir inode %"PRIu64
			        " on \"%s\"\n",
				blkno, filename);
			goto out_close;
		}
		wp.path = "/";
		fprintf(stdout, "Scanning root directory for dups...\n");
		ret = ocfs2_dir_iterate(fs,
					OCFS2_RAW_SB(fs->fs_super)->s_root_blkno,
					0, NULL, walk_tree_func, &wp);
		if (ret) {
			com_err(argv[0], ret,
				"while dup scanning root inode %"PRIu64
			       	" on \"%s\"\n",
				blkno, filename);
			goto out_close;
		}
	}

out_close:
	ret = ocfs2_close(fs);
	if (ret) {
		com_err(argv[0], ret,
			"while closing file \"%s\"", filename);
	}

out:
	return 0;
}
예제 #6
0
int main(int argc, char *argv[])
{
	errcode_t ret;
	int c;
	int64_t blkno, count, blksize;
	char *filename;
	io_channel *channel;
	char *blks;

	/* Some simple defaults */
	blksize = 512;
	blkno = 0;
	count = 1;

	initialize_ocfs_error_table();

	while((c = getopt(argc, argv, "b:c:B:")) != EOF) {
		switch (c) {
			case 'b':
				blkno = read_number(optarg);
				if (blkno < 0) {
					fprintf(stderr,
						"Invalid blkno: %s\n",
						optarg);
					print_usage();
					return 1;
				}
				break;

			case 'c':
				count = read_number(optarg);
				if (!count) {
					fprintf(stderr, 
						"Invalid count: %s\n",
						optarg);
					print_usage();
					return 1;
				}
				break;

			case 'B':
				blksize = read_number(optarg);
				if (!blksize) {
					fprintf(stderr, 
						"Invalid blksize: %s\n",
						optarg);
					print_usage();
					return 1;
				}
				break;

			default:
				print_usage();
				return 1;
				break;
		}
	}

	if (blksize % OCFS2_MIN_BLOCKSIZE) {
		fprintf(stderr, "Invalid blocksize: %"PRId64"\n", blksize);
		print_usage();
		return 1;
	}
	if (count < 0) {
		if (-count > (int64_t)INT_MAX) {
			fprintf(stderr, "Count is too large: %"PRId64"\n",
				count);
			print_usage();
			return 1;
		}
		count = -count / blksize;
	} else  {
		if ((count * blksize) > INT_MAX) {
			fprintf(stderr, "Count is too large: %"PRId64"\n",
				count);
			print_usage();
			return 1;
		}
	}

	if (optind >= argc) {
		fprintf(stderr, "Missing filename\n");
		print_usage();
		return 1;
	}

	filename = argv[optind];

	ret = io_open(filename, OCFS2_FLAG_RO, &channel);
	if (ret) {
		com_err(argv[0], ret,
			"while opening file \"%s\"", filename);
		goto out;
	}

	ret = ocfs2_malloc_blocks(channel, (int)count, &blks);
	if (ret) {
		com_err(argv[0], ret,
			"while allocating %"PRId64" blocks", count);
		goto out_channel;
	}

	ret = io_read_block(channel, blkno, (int)count, blks);
	if (ret) {
		com_err(argv[0], ret,
			"while reading %"PRId64" blocks at block %"PRId64" (%s)",
			count, blkno,
			strerror(io_get_error(channel)));
		goto out_blocks;
	}

	for (c = 0; c < count; c++)
		dump_block(blkno + c, blksize, blks + (c * blksize));

out_blocks:
	ocfs2_free(&blks);

out_channel:
	ret = io_close(channel);
	if (ret) {
		com_err(argv[0], ret,
			"while closing file \"%s\"", filename);
	}

out:
	return 0;
}
예제 #7
0
int main(int argc, char *argv[])
{
	errcode_t ret;
	int c;
	uint64_t blkno = 0, new_size = 0;
	ocfs2_filesys *fs;
	char *device;

	initialize_ocfs_error_table();

	while ((c = getopt(argc, argv, "i:s:")) != EOF) {
		switch (c) {
			case 'i':
				blkno = read_number(optarg);
				if (blkno <= OCFS2_SUPER_BLOCK_BLKNO) {
					fprintf(stderr,
						"Invalid inode block: %s\n",
						optarg);
					print_usage();
					return 1;
				}
				break;

			case 's':
				new_size = read_number(optarg);
				break;

			default:
				print_usage();
				return 1;
				break;
		}
	}

	if (optind >= argc) {
		fprintf(stderr, "Missing device name\n");
		print_usage();
		return 1;
	}
	device = argv[optind];

	if (!blkno || !new_size) {
		print_usage();
		return 1;
	}

	ret = ocfs2_open(device, OCFS2_FLAG_RW, 0, 0, &fs);
	if (ret) {
		com_err(argv[0], ret,
			"while opening file \"%s\"", device);
		return ret;
	}

	ret = ocfs2_truncate(fs, blkno, new_size);
	if (ret)
		com_err(argv[0], ret, "while truncating inode %"PRIu64, blkno);

	ocfs2_close(fs);

	return ret;
}
예제 #8
0
int main(int argc, char **argv)
{
	errcode_t ret = 0;
	struct mount_options mo;
	ocfs2_filesys *fs = NULL;
	struct o2cb_cluster_desc cluster;
	struct o2cb_region_desc desc;
	int clustered = 1;
	int group_join = 0;
	struct stat statbuf;
	const char *spec;
	char *opts_string = NULL;

	initialize_ocfs_error_table();
	initialize_o2dl_error_table();
	initialize_o2cb_error_table();

	setbuf(stdout, NULL);
	setbuf(stderr, NULL);

	if (signal(SIGTERM, handle_signal) == SIG_ERR) {
		fprintf(stderr, "Could not set SIGTERM\n");
		exit(1);
	}

	if (signal(SIGINT, handle_signal) == SIG_ERR) {
		fprintf(stderr, "Could not set SIGINT\n");
		exit(1);
	}

	memset(&mo, 0, sizeof(mo));
	read_options (argc, argv, &mo);

	ret = process_options(&mo);
	if (ret)
		goto bail;

	ret = ocfs2_open(mo.dev, OCFS2_FLAG_RO, 0, 0, &fs); //O_EXCL?
	if (ret) {
		com_err(progname, ret, "while opening device %s", mo.dev);
		goto bail;
	}

	clustered = (0 == ocfs2_mount_local(fs));

	if (ocfs2_is_hard_readonly(fs) && (clustered ||
					   !(mo.flags & MS_RDONLY))) {
		ret = OCFS2_ET_IO;
		com_err(progname, ret,
			"while mounting read-only device in %s mode",
			(clustered ? "clustered" : "read-write"));
		goto bail;
	}

	if (verbose)
		printf("device=%s\n", mo.dev);

	ret = o2cb_setup_stack((char *)OCFS2_RAW_SB(fs->fs_super)->s_cluster_info.ci_stack);
	if (ret) {
		com_err(progname, ret, "while setting up stack\n");
		goto bail;
	}

	if (clustered) {
		ret = o2cb_init();
		if (ret) {
			com_err(progname, ret, "while trying initialize cluster");
			goto bail;
		}

		ret = ocfs2_fill_cluster_desc(fs, &cluster);
		if (ret) {
			com_err(progname, ret,
				"while trying to determine cluster information");
			goto bail;
		}

		ret = ocfs2_fill_heartbeat_desc(fs, &desc);
		if (ret) {
			com_err(progname, ret,
				"while trying to determine heartbeat information");
			goto bail;
		}
		desc.r_persist = 1;
		desc.r_service = OCFS2_FS_NAME;
	}

	ret = add_mount_options(fs, &cluster, &mo.xtra_opts);
	if (ret) {
		com_err(progname, ret, "while adding mount options");
		goto bail;
	}

	/* validate mount dir */
	if (lstat(mo.dir, &statbuf)) {
		com_err(progname, 0, "mount directory %s does not exist",
			mo.dir);
		goto bail;
	} else if (stat(mo.dir, &statbuf)) {
		com_err(progname, 0, "mount directory %s is a broken symbolic "
			"link", mo.dir);
		goto bail;
	} else if (!S_ISDIR(statbuf.st_mode)) {
		com_err(progname, 0, "mount directory %s is not a directory",
			mo.dir);
		goto bail;
	}

	block_signals (SIG_BLOCK);

	if (clustered && !(mo.flags & MS_REMOUNT)) {
		ret = o2cb_begin_group_join(&cluster, &desc);
		if (ret) {
			block_signals (SIG_UNBLOCK);
			com_err(progname, ret,
				"while trying to join the group");
			goto bail;
		}
		group_join = 1;
	}
	spec = canonicalize(mo.dev);
	ret = mount(spec, mo.dir, OCFS2_FS_NAME, mo.flags & ~MS_NOSYS,
		    mo.xtra_opts);
	if (ret) {
		ret = errno;
		if (group_join) {
			/* We ignore the return code because the mount
			 * failure is the important error.
			 * complete_group_join() will handle cleaning up */
			o2cb_complete_group_join(&cluster, &desc, errno);
		}
		block_signals (SIG_UNBLOCK);
		if (ret == -EROFS)
			com_err(progname, OCFS2_ET_RO_FILESYS, "while mounting %s "
				"on %s, please try fixing this by fsck.ocfs2 and then "
				"retry mounting", mo.dev, mo.dir);
		else
			com_err(progname, OCFS2_ET_INTERNAL_FAILURE,
				"while mounting %s on %s. Check 'dmesg' for more "
				"information on this error %d.", mo.dev, mo.dir,
				(int)ret);
		goto bail;
	}
	if (group_join) {
		ret = o2cb_complete_group_join(&cluster, &desc, 0);
		if (ret) {
			com_err(progname, ret,
				"while completing group join (WARNING)");
			/*
			 * XXX: GFS2 allows the mount to continue, so we
			 * will do the same.  I don't know how clean that
			 * is, but I don't have a better solution.
			 */
			ret = 0;
		}
	}

	change_local_hb_io_priority(fs, mo.dev);

	opts_string = fix_opts_string(((mo.flags & ~MS_NOMTAB) |
			(clustered ? MS_NETDEV : 0)),
			mo.xtra_opts, NULL);
	update_mtab_entry(mo.dev, mo.dir, OCFS2_FS_NAME, opts_string,
			mo.flags, 0, 0);

	block_signals (SIG_UNBLOCK);

bail:
	if (fs)
		ocfs2_close(fs);
	if (mo.dev)
		free(mo.dev);
	if (mo.dir)
		free(mo.dir);
	if (mo.opts)
		free(mo.opts);
	if (mo.xtra_opts)
		free(mo.xtra_opts);
	if (mo.type)
		free(mo.type);
	if (opts_string)
		free(opts_string);

	return ret ? 1 : 0;
}
예제 #9
0
파일: chain.c 프로젝트: djs55/ocfs2-tools
int main(int argc, char *argv[])
{
	errcode_t ret;
	uint64_t blkno;
	int c;
	char *filename, *buf;
	ocfs2_filesys *fs;
	struct ocfs2_dinode *di;
	struct walk_it wi;

	blkno = OCFS2_SUPER_BLOCK_BLKNO;

	initialize_ocfs_error_table();

	while ((c = getopt(argc, argv, "bei:")) != EOF) {
		switch (c) {
			case 'i':
				blkno = read_number(optarg);
				if (blkno <= OCFS2_SUPER_BLOCK_BLKNO) {
					fprintf(stderr,
						"Invalid inode block: %s\n",
						optarg);
					print_usage();
					return 1;
				}
				break;

			default:
				print_usage();
				return 1;
				break;
		}
	}
	
	if (blkno == OCFS2_SUPER_BLOCK_BLKNO) {
		fprintf(stderr, "You must specify an inode block\n");
		print_usage();
		return 1;
	}

	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);
		goto out;
	}

	ret = ocfs2_malloc_block(fs->fs_io, &buf);
	if (ret) {
		com_err(argv[0], ret,
			"while allocating inode buffer");
		goto out_close;
	}

	memset(&wi, 0, sizeof(wi));

	ret = ocfs2_read_inode(fs, blkno, buf);
	if (ret) {
		com_err(argv[0], ret, "while reading inode %"PRIu64, blkno);
		goto out_free;
	}

	di = (struct ocfs2_dinode *)buf;

	fprintf(stdout, "OCFS2 inode %"PRIu64" on \"%s\"\n",
		blkno, filename);

	ret = ocfs2_malloc_block(fs->fs_io, &wi.gd_buf);
	if (ret) {
		com_err(argv[0], ret,
			"while allocating gd buffer");
		goto out_free;
	}

	wi.di = di;
	wi.last_chain = -1;
	ret = ocfs2_chain_iterate(fs, blkno,
				  walk_chain_func,
				  &wi);
	if (ret) {
		com_err(argv[0], ret,
			"while walking extents");
	}

out_free:
	if (wi.gd_buf)
		ocfs2_free(&wi.gd_buf);

	ocfs2_free(&buf);

out_close:
	ret = ocfs2_close(fs);
	if (ret) {
		com_err(argv[0], ret,
			"while closing file \"%s\"", filename);
	}

out:
	return 0;
}
예제 #10
0
int main(int argc, char *argv[])
{
	errcode_t ret;
	uint64_t blkno, sys_blkno;
	int c;
	char *filename, *buf;
	const char *bitmap_name = ocfs2_system_inodes[GLOBAL_BITMAP_SYSTEM_INODE].si_name;
	ocfs2_filesys *fs;
	struct ocfs2_dinode *di;
	struct walk_block wb;

	blkno = OCFS2_SUPER_BLOCK_BLKNO;

	initialize_ocfs_error_table();

	while ((c = getopt(argc, argv, "i:")) != EOF) {
		switch (c) {
			case 'i':
				blkno = read_number(optarg);
				if (blkno <= OCFS2_SUPER_BLOCK_BLKNO) {
					fprintf(stderr,
						"Invalid inode block: %s\n",
						optarg);
					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_RW, 0, 0, &fs);
	if (ret) {
		com_err(argv[0], ret,
			"while opening file \"%s\"", filename);
		goto out;
	}

	if (blkno == OCFS2_SUPER_BLOCK_BLKNO) {
		sys_blkno = OCFS2_RAW_SB(fs->fs_super)->s_system_dir_blkno;

		ret = ocfs2_lookup(fs, sys_blkno, bitmap_name, 
				   strlen(bitmap_name), NULL, &blkno);
		if (ret) {
			com_err(argv[0], ret,
				"while looking up \"%s\"", bitmap_name);
			goto out;
		}
	}

	ret = ocfs2_malloc_block(fs->fs_io, &buf);
	if (ret) {
		com_err(argv[0], ret,
			"while allocating inode buffer");
		goto out_close;
	}

	memset(&wb, 0, sizeof(wb));

	ret = ocfs2_read_inode(fs, blkno, buf);
	if (ret) {
		com_err(argv[0], ret, "while reading inode %"PRIu64, blkno);
		goto out_free;
	}

	di = (struct ocfs2_dinode *)buf;

	wb.di = di;
	ret = ocfs2_malloc_block(fs->fs_io, &wb.buf);
	if (ret) {
		com_err(argv[0], ret,
			"while allocating block buffer");
		goto out_free;
	}

	ret = ocfs2_block_iterate(fs, blkno, 0,
				  walk_blocks_func,
				  &wb);
	if (ret) {
		com_err(argv[0], ret,
			"while walking blocks");
		goto out_free;
	}

	di->id1.bitmap1.i_used = wb.used;

	ret = ocfs2_write_inode(fs, blkno, buf);
	if (ret) {
		com_err(argv[0], ret, "while reading inode %"PRIu64, blkno);
		goto out_free;
	}

out_free:
	if (wb.buf)
		ocfs2_free(&wb.buf);

	ocfs2_free(&buf);

out_close:
	ret = ocfs2_close(fs);
	if (ret) {
		com_err(argv[0], ret,
			"while closing file \"%s\"", filename);
	}

out:
	return 0;
}
예제 #11
0
int main(int argc, char *argv[])
{
	errcode_t ret;
	uint64_t blkno, result_blkno;
	int c, len;
	char *filename, *lookup_path, *buf;
	char *filebuf;
	char *p;
	char lookup_name[256];
	ocfs2_filesys *fs;

	blkno = 0;

	initialize_ocfs_error_table();

	while ((c = getopt(argc, argv, "i:")) != EOF) {
		switch (c) {
			case 'i':
				blkno = read_number(optarg);
				if (blkno <= OCFS2_SUPER_BLOCK_BLKNO) {
					fprintf(stderr,
						"Invalid inode block: %s\n",
						optarg);
					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];
	optind++;

	if (optind >= argc) {
		fprintf(stdout, "Missing path to lookup\n");
		print_usage();
		return 1;
	}
	lookup_path = argv[optind];

	ret = ocfs2_open(filename, OCFS2_FLAG_RO, 0, 0, &fs);
	if (ret) {
		com_err(argv[0], ret,
			"while opening file \"%s\"", filename);
		goto out;
	}

	ret = ocfs2_malloc_block(fs->fs_io, &buf);
	if (ret) {
		com_err(argv[0], ret,
			"while allocating inode buffer");
		goto out_close;
	}

	if (!blkno)
		blkno = OCFS2_RAW_SB(fs->fs_super)->s_root_blkno;

	for (p = lookup_path; *p == '/'; p++);

	lookup_path = p;

	for (p = lookup_path; ; p++) {
		if (*p && *p != '/')
			continue;

		memcpy(lookup_name, lookup_path, p - lookup_path);
		lookup_name[p - lookup_path] = '\0';
		ret = ocfs2_lookup(fs, blkno, lookup_name,
				   strlen(lookup_name), NULL,
				   &result_blkno);
		if (ret) {
			com_err(argv[0], ret,
				"while looking up \"%s\" in inode %"PRIu64
			       	" on \"%s\"\n",
				lookup_name, blkno, filename);
			goto out_free;
		}

		blkno = result_blkno;

		for (; *p == '/'; p++);

		lookup_path = p;

		if (!*p)
			break;
	}

	if (ocfs2_check_directory(fs, blkno) != OCFS2_ET_NO_DIRECTORY) {
		com_err(argv[0], ret, "\"%s\" is not a file", filename);
		goto out_free;
	}

	ret = ocfs2_read_whole_file(fs, blkno, &filebuf, &len);
	if (ret) {
		com_err(argv[0], ret,
			"while reading file \"%s\" -- read %d bytes",
			filename, len);
		goto out_free_filebuf;
	}
	if (!len)
		fprintf(stderr, "boo!\n");

	dump_filebuf(filebuf, len);

out_free_filebuf:
	if (len)
		ocfs2_free(&filebuf);

out_free:
	ocfs2_free(&buf);

out_close:
	ret = ocfs2_close(fs);
	if (ret) {
		com_err(argv[0], ret,
			"while closing file \"%s\"", filename);
	}

out:
	return 0;
}
예제 #12
0
int main(int argc, char *argv[])
{
	errcode_t ret;
	uint64_t blkno, contig, blkoff = 0;
	uint16_t ext_flags;
	int count = 0;
	int c, op = 0;
	char *filename;
	ocfs2_filesys *fs;
	ocfs2_cached_inode *cinode;

	blkno = OCFS2_SUPER_BLOCK_BLKNO;

	initialize_ocfs_error_table();

	while ((c = getopt(argc, argv, "i:b:")) != EOF) {
		switch (c) {
			case 'i':
				blkno = read_number(optarg);
				if (blkno <= OCFS2_SUPER_BLOCK_BLKNO) {
					fprintf(stderr,
						"Invalid inode block: %s\n",
						optarg);
					print_usage();
					return 1;
				}
				break;

			case 'b':
				if (op) {
					fprintf(stderr, "Cannot specify more than one operation\n");
					print_usage();
					return 1;
				}
				if (read_b_numbers(optarg,
						   &blkoff, &count)) {
					fprintf(stderr, "Invalid block range: %s\n", optarg);
					print_usage();
					return 1;
				}
				op = OP_LOOKUP_BLOCK;
				break;

			default:
				print_usage();
				return 1;
				break;
		}
	}

	if (!op) {
		fprintf(stderr, "Missing operation\n");
		print_usage();
		return 1;
	}

	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);
		goto out;
	}

	ret = ocfs2_read_cached_inode(fs, blkno, &cinode);
	if (ret) {
		com_err(argv[0], ret, "while reading inode %"PRIu64, blkno);
		goto out_close;
	}

	fprintf(stdout, "OCFS2 inode %"PRIu64" on \"%s\" has depth %"PRId16"\n",
		blkno, filename,
		cinode->ci_inode->id2.i_list.l_tree_depth);

	ret = ocfs2_extent_map_get_blocks(cinode,
					  blkoff,
					  count,
					  &blkno,
					  &contig,
					  &ext_flags);
	if (ret) {
		com_err(argv[0], ret,
			"looking up block range %"PRIu64":%d", blkoff, count);
		goto out_free;
	}
	fprintf(stdout, "Lookup of block range %"PRIu64":%d returned %"PRIu64":%"PRIu64"\n",
		blkoff, count, blkno, contig);

out_free:
	ocfs2_free_cached_inode(fs, cinode);

out_close:
	ret = ocfs2_close(fs);
	if (ret) {
		com_err(argv[0], ret,
			"while closing file \"%s\"", filename);
	}

out:
	return 0;
}
예제 #13
0
파일: main.c 프로젝트: abligh/ocfs2-tools
int main(int argc, char **argv)
{
	char *line;
	struct dbgfs_opts opts;
	FILE *cmd = NULL;

	initialize_o2cb_error_table();
	initialize_ocfs_error_table();

#define INSTALL_SIGNAL(sig)					\
	do {							\
		if (signal(sig, handle_signal) == SIG_ERR) {	\
		    printf("Could not set " #sig "\n");		\
		    goto bail;					\
		}						\
	} while (0)

	INSTALL_SIGNAL(SIGTERM);
	INSTALL_SIGNAL(SIGINT);

	setbuf(stdout, NULL);
	setbuf(stderr, NULL);

	memset(&opts, 0, sizeof(opts));
	memset(&gbls, 0, sizeof(gbls));

	gbls.progname = basename(argv[0]);

	get_options(argc, argv, &opts);

	if (logmode) {
		run_logmode();
		goto bail;
	}

	if (decodemode) {
		process_decode_lockres(argc, argv, arg_ind);
		goto bail;
	}

	if (encodemode) {
		process_encode_lockres(argc, argv, arg_ind);
		goto bail;
	}

	gbls.allow_write = opts.allow_write;
	gbls.imagefile = opts.imagefile;
	if (!opts.cmd_file)
		gbls.interactive++;

	if (opts.device) {
		if (opts.sb_num)
			line = g_strdup_printf("open %s -s %u", opts.device, opts.sb_num);
		else
			line = g_strdup_printf("open %s", opts.device);
		do_command(line);
		g_free(line);
	}

	if (opts.one_cmd) {
		do_command(opts.one_cmd);
		goto bail;
	}

	if (opts.cmd_file) {
		cmd = fopen(opts.cmd_file, "r");
		if (!cmd) {
			com_err(argv[0], errno, "'%s'", opts.cmd_file);
			goto bail;
		}
	}

	if (!opts.no_prompt)
		print_version(gbls.progname);

	while (1) {
		line = get_line(cmd, opts.no_prompt);

		if (line) {
			if (!gbls.interactive && !opts.no_prompt)
				fprintf(stdout, "%s%s\n", PROMPT, line);
			do_command(line);
			if (gbls.interactive)
				free(line);
		} else {
			printf("\n");
			raise(SIGTERM);
			exit(0);
		}
	}

bail:
	if (cmd)
		fclose(cmd);
	if (opts.cmd_file)
		free(opts.cmd_file);
	if (opts.device)
		free(opts.device);
	return 0;
}
예제 #14
0
int main(int argc, char *argv[])
{
	errcode_t ret;
	char *filename;
	ocfs2_filesys *fs;
	uint64_t ino = 0;
	uint32_t new_clusters = 0;
	int c;

	initialize_ocfs_error_table();

	while ((c = getopt(argc, argv, "i:c:")) != EOF) {
		switch (c) {
			case 'i':
				ino = read_number(optarg);
				if (ino <= OCFS2_SUPER_BLOCK_BLKNO) {
					fprintf(stderr,
						"Invalid inode block: %s\n",
						optarg);
					print_usage();
					return 1;
				}
				break;

			case 'c':
				new_clusters = read_number(optarg);
				if (!new_clusters) {
					fprintf(stderr,
						"Invalid cluster count: %s\n",
						optarg);
					print_usage();
					return 1;
				}
				break;

			default:
				print_usage();
				return 1;
				break;
		}
	}

	if (!ino) {
		fprintf(stderr, "You must specify an inode block\n");
		print_usage();
		return 1;
	}

	if (!new_clusters) {
		fprintf(stderr, "You must specify how many clusters to extend\n");
		print_usage();
		return 1;
	}

	if (optind >= argc) {
		fprintf(stderr, "Missing filename\n");
		print_usage();
		return 1;
	}
	filename = argv[optind];

	ret = ocfs2_open(filename, OCFS2_FLAG_RW, 0, 0, &fs);
	if (ret) {
		com_err(argv[0], ret,
			"while opening file \"%s\"", filename);
		goto out;
	}

	ret = ocfs2_extend_allocation(fs, ino, new_clusters);
	if (ret) {
		com_err(argv[0], ret,
			"while extending inode %"PRIu64, ino);
	}

	ret = ocfs2_close(fs);
	if (ret) {
		com_err(argv[0], ret,
			"while closing file \"%s\"", filename);
	}
out:
	return !!ret;
}
예제 #15
0
파일: fsck.c 프로젝트: abligh/ocfs2-tools
int main(int argc, char **argv)
{
	char *filename;
	int64_t blkno, blksize;
	o2fsck_state *ost = &_ost;
	int c, open_flags = OCFS2_FLAG_RW | OCFS2_FLAG_STRICT_COMPAT_CHECK;
	int sb_num = 0;
	int fsck_mask = FSCK_OK;
	int slot_recover_err = 0;
	errcode_t ret;
	int mount_flags;
	int proceed = 1;

	memset(ost, 0, sizeof(o2fsck_state));
	ost->ost_ask = 1;
	ost->ost_dirblocks.db_root = RB_ROOT;
	ost->ost_dir_parents = RB_ROOT;
	ost->ost_refcount_trees = RB_ROOT;

	/* These mean "autodetect" */
	blksize = 0;
	blkno = 0;

	initialize_ocfs_error_table();
	initialize_o2dl_error_table();
	initialize_o2cb_error_table();
	setlinebuf(stderr);
	setlinebuf(stdout);

	tools_progress_disable();

	while ((c = getopt(argc, argv, "b:B:DfFGnupavVytPr:")) != EOF) {
		switch (c) {
			case 'b':
				blkno = read_number(optarg);
				if (blkno < OCFS2_SUPER_BLOCK_BLKNO) {
					fprintf(stderr,
						"Invalid blkno: %s\n",
						optarg);
					fsck_mask |= FSCK_USAGE;
					print_usage();
					goto out;
				}
				break;

			case 'B':
				blksize = read_number(optarg);
				if (blksize < OCFS2_MIN_BLOCKSIZE) {
					fprintf(stderr, 
						"Invalid blksize: %s\n",
						optarg);
					fsck_mask |= FSCK_USAGE;
					print_usage();
					goto out;
				}
				break;
			case 'D':
				ost->ost_compress_dirs = 1;
				break;

			case 'F':
				ost->ost_skip_o2cb = 1;
				break;

			case 'f':
				ost->ost_force = 1;
				break;

			case 'G':
				ost->ost_fix_fs_gen = 1;
				break;

			case 'n':
				open_flags &= ~OCFS2_FLAG_RW;
				open_flags |= OCFS2_FLAG_RO;
				/* Fall through */

			case 'a':
			case 'p':
				/*
				 * Like extN, -a maps to -p, which is
				 * 'preen'.  This means only fix things
				 * that don't require human interaction.
				 * Unlike extN, this is only journal
				 * replay for now.  To make it smarter,
				 * ost->ost_answer needs to learn a
				 * new mode.
				 */
				ost->ost_ask = 0;
				ost->ost_answer = 0;
				break;

			case 'P':
				tools_progress_enable();
				break;

			case 'y':
				ost->ost_ask = 0;
				ost->ost_answer = 1;
				break;

			case 'u':
				open_flags |= OCFS2_FLAG_BUFFERED;
				break;

			case 'v':
				verbose = 1;
				break;

			case 'V':
				print_version();
				exit(FSCK_USAGE);
				break;

			case 'r':
				sb_num = read_number(optarg);
				break;

			case 't':
				if (ost->ost_show_stats)
					ost->ost_show_extended_stats = 1;
				ost->ost_show_stats = 1;
				break;

			default:
				fsck_mask |= FSCK_USAGE;
				print_usage();
				goto out;
				break;
		}
	}

	if (!(open_flags & OCFS2_FLAG_RW) && ost->ost_compress_dirs) {
		fprintf(stderr, "Compress directories (-D) incompatible with read-only mode\n");
		fsck_mask |= FSCK_USAGE;
		print_usage();
		goto out;
	}

	if (blksize % OCFS2_MIN_BLOCKSIZE) {
		fprintf(stderr, "Invalid blocksize: %"PRId64"\n", blksize);
		fsck_mask |= FSCK_USAGE;
		print_usage();
		goto out;
	}

	if (optind >= argc) {
		fprintf(stderr, "Missing filename\n");
		fsck_mask |= FSCK_USAGE;
		print_usage();
		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);
		fsck_mask |= FSCK_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");
		proceed = 0;
	}

	if (proceed && ost->ost_skip_o2cb) {
		fprintf(stdout, "\nWARNING!!! You have disabled the cluster check. "
			"Continue only if you\nare absolutely sure that NO "
			"node has this filesystem mounted or is\notherwise "
			"accessing it. If unsure, do NOT continue.\n\n");
		proceed = 0;
	}

	if (!proceed) {
		fprintf(stdout, "Do you really want to continue (y/N): ");
		if (toupper(getchar()) != 'Y') {
			printf("Aborting operation.\n");
			fsck_mask |= FSCK_CANCELED;
			goto out;
		}
	}

	if (signal(SIGTERM, handle_signal) == SIG_ERR) {
		com_err(whoami, 0, "Could not set SIGTERM");
		exit(1);
	}

	if (signal(SIGINT, handle_signal) == SIG_ERR) {
		com_err(whoami, 0, "Could not set SIGINT");
		exit(1);
	}

	/* recover superblock should be called at first. */
	if (sb_num) {
		ret = recover_backup_super(ost, filename, sb_num);
		if (ret) {
			com_err(whoami, ret, "recover superblock failed.\n");
			fsck_mask |= FSCK_ERROR;
			goto out;
		}

	}

	ret = open_and_check(ost, filename, open_flags, blkno, blksize);
	if (ret) {
		fsck_mask |= FSCK_ERROR;
		goto out;
	}

	if (open_flags & OCFS2_FLAG_RW && !ost->ost_skip_o2cb &&
	    !ocfs2_mount_local(ost->ost_fs)) {
		ret = o2cb_init();
		if (ret) {
			com_err(whoami, ret, "while initializing the cluster");
			goto close;
		}

		block_signals(SIG_BLOCK);
		ret = ocfs2_initialize_dlm(ost->ost_fs, whoami);
		if (ret == O2CB_ET_INVALID_STACK_NAME ||
		    ret == O2CB_ET_INVALID_CLUSTER_NAME ||
		    ret == O2CB_ET_INVALID_HEARTBEAT_MODE) {
			block_signals(SIG_UNBLOCK);
			ret = recover_cluster_info(ost);
			if (ret) {
				com_err(whoami, ret,
					"while recovering cluster information");
				goto close;
			}
			block_signals(SIG_BLOCK);
			ret = ocfs2_initialize_dlm(ost->ost_fs, whoami);
		}
		if (ret) {
			block_signals(SIG_UNBLOCK);
			com_err(whoami, ret, "while initializing the DLM");
			goto close;
		}

		ret = ocfs2_lock_down_cluster(ost->ost_fs);
		if (ret) {
			block_signals(SIG_UNBLOCK);
			com_err(whoami, ret, "while locking down the cluster");
			goto close;
		}
		cluster_locked = 1;
		block_signals(SIG_UNBLOCK);
	}

	printf("Checking OCFS2 filesystem in %s:\n", filename);
	printf("  Label:              ");
	print_label(ost);
	printf("  UUID:               ");
	print_uuid(ost);
	printf("  Number of blocks:   %"PRIu64"\n", ost->ost_fs->fs_blocks);
	printf("  Block size:         %u\n", ost->ost_fs->fs_blocksize);
	printf("  Number of clusters: %"PRIu32"\n", ost->ost_fs->fs_clusters);
	printf("  Cluster size:       %u\n", ost->ost_fs->fs_clustersize);
	printf("  Number of slots:    %u\n\n", 
	       OCFS2_RAW_SB(ost->ost_fs->fs_super)->s_max_slots);

	/* Let's get enough of a cache to replay the journals */
	o2fsck_init_cache(ost, O2FSCK_CACHE_MODE_JOURNAL);

	if (open_flags & OCFS2_FLAG_RW) {
		ret = o2fsck_check_journals(ost);
		if (ret) {
			printf("fsck saw unrecoverable errors in the journal "
				"files and will not continue.\n");
			goto unlock;
		}
	}

	ret = maybe_replay_journals(ost, filename, open_flags, blkno, blksize);
	if (ret) {
		printf("fsck encountered unrecoverable errors while "
		       "replaying the journals and will not continue\n");
		fsck_mask |= FSCK_ERROR;
		goto unlock;
	}

	/* Grow the cache */
	o2fsck_init_cache(ost, O2FSCK_CACHE_MODE_FULL);

	/* allocate all this junk after we've replayed the journal and the
	 * sb should be stable */
	if (o2fsck_state_init(ost->ost_fs, ost)) {
		fprintf(stderr, "error allocating run-time state, exiting..\n");
		fsck_mask |= FSCK_ERROR;
		goto unlock;
	}

	ret = o2fsck_slot_recovery(ost);
	if (ret) {
		printf("fsck encountered errors while recovering slot "
		       "information, check forced.\n");
		slot_recover_err = 1;
		ost->ost_force = 1;
	}

	if (fs_is_clean(ost, filename)) {
		fsck_mask = FSCK_OK;
		goto clear_dirty_flag;
	}

#if 0
	o2fsck_mark_block_used(ost, 0);
	o2fsck_mark_block_used(ost, 1);
	o2fsck_mark_block_used(ost, OCFS2_SUPER_BLOCK_BLKNO);
#endif
	mark_magical_clusters(ost);

	/* XXX we don't use the bad blocks inode, do we? */


	/* XXX for now it is assumed that errors returned from a pass
	 * are fatal.  these can be fixed over time. */
	ret = o2fsck_pass0(ost);
	if (ret) {
		com_err(whoami, ret, "while performing pass 0");
		goto done;
	}

	ret = o2fsck_pass1(ost);
	if (ret) {
		com_err(whoami, ret, "while performing pass 1");
		goto done;
	}

	ret = o2fsck_pass2(ost);
	if (ret) {
		com_err(whoami, ret, "while performing pass 2");
		goto done;
	}

	ret = o2fsck_pass3(ost);
	if (ret) {
		com_err(whoami, ret, "while performing pass 3");
		goto done;
	}

	ret = o2fsck_pass4(ost);
	if (ret) {
		com_err(whoami, ret, "while performing pass 4");
		goto done;
	}

	ret = o2fsck_pass5(ost);
	if (ret) {
		com_err(whoami, ret, "while performing pass 5");
		goto done;
	}

done:
	if (ret)
		fsck_mask |= FSCK_ERROR;
	else {
		fsck_mask = FSCK_OK;
		ost->ost_saw_error = 0;
		printf("All passes succeeded.\n\n");
		o2fsck_print_resource_track(NULL, ost, &ost->ost_rt,
					    ost->ost_fs->fs_io);
		show_stats(ost);
	}

clear_dirty_flag:
	if (ost->ost_fs->fs_flags & OCFS2_FLAG_RW) {
		ret = write_out_superblock(ost);
		if (ret)
			com_err(whoami, ret, "while writing back the "
				"superblock(s)");
		if (fsck_mask == FSCK_OK) {
			if (slot_recover_err) {
				ret = o2fsck_slot_recovery(ost);
				if (ret) {
					com_err(whoami, ret, "while doing slot "
						"recovery.");
					goto unlock;
				}
			}

			ret = o2fsck_clear_journal_flags(ost);
			if (ret) {
				com_err(whoami, ret, "while clear dirty "
					"journal flag.");
				goto unlock;
			}

			ret = ocfs2_format_slot_map(ost->ost_fs);
			if (ret)
				com_err(whoami, ret, "while format slot "
					"map.");
		}
	}

unlock:
	block_signals(SIG_BLOCK);
	if (ost->ost_fs->fs_dlm_ctxt)
		ocfs2_release_cluster(ost->ost_fs);
	cluster_locked = 0;
	block_signals(SIG_UNBLOCK);

close:
	block_signals(SIG_BLOCK);
	if (ost->ost_fs->fs_dlm_ctxt)
		ocfs2_shutdown_dlm(ost->ost_fs, whoami);
	block_signals(SIG_UNBLOCK);

	ret = ocfs2_close(ost->ost_fs);
	if (ret) {
		com_err(whoami, ret, "while closing file \"%s\"", filename);
		/* XXX I wonder about this error.. */
		fsck_mask |= FSCK_ERROR;
	} 

out:
	return fsck_mask;
}
예제 #16
0
int main(int argc, char *argv[])
{
	errcode_t ret;
	uint64_t blkno;
	int c;
	int walk_blocks = 0, walk_extents = 0;
	char *filename, *buf, *eb_buf = NULL;
	ocfs2_filesys *fs;
	struct ocfs2_dinode *di;
	struct walk_it wi;
	struct walk_block wb;

	blkno = OCFS2_SUPER_BLOCK_BLKNO;

	initialize_ocfs_error_table();

	while ((c = getopt(argc, argv, "bei:")) != EOF) {
		switch (c) {
			case 'b':
				walk_blocks = 1;
				break;

			case 'e':
				walk_extents = 1;
				break;

			case 'i':
				blkno = read_number(optarg);
				if (blkno <= OCFS2_SUPER_BLOCK_BLKNO) {
					fprintf(stderr,
						"Invalid inode block: %s\n",
						optarg);
					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];

	if (!(walk_blocks + walk_extents)) {
		fprintf(stderr,
			"No operation specified\n");
		print_usage();
		return 1;
	}

	ret = ocfs2_open(filename, OCFS2_FLAG_RO, 0, 0, &fs);
	if (ret) {
		com_err(argv[0], ret,
			"while opening file \"%s\"", filename);
		goto out;
	}

	ret = ocfs2_malloc_block(fs->fs_io, &buf);
	if (ret) {
		com_err(argv[0], ret,
			"while allocating inode buffer");
		goto out_close;
	}


	ret = ocfs2_read_inode(fs, blkno, buf);
	if (ret) {
		com_err(argv[0], ret, "while reading inode %"PRIu64, blkno);
		goto out_free;
	}

	di = (struct ocfs2_dinode *)buf;

	fprintf(stdout, "OCFS2 inode %"PRIu64" on \"%s\" has depth %"PRId16"\n",
		blkno, filename, di->id2.i_list.l_tree_depth);

	if (walk_extents) {
		if (di->id2.i_list.l_tree_depth) {
			ret = ocfs2_malloc_blocks(fs->fs_io,
						  di->id2.i_list.l_tree_depth,
						  &eb_buf);
			if (ret) {
				com_err(argv[0], ret,
					"while allocating eb buffer");
				goto out_free;
			}
		}

		wi.di = di;
		ret = ocfs2_extent_iterate(fs, blkno, 0,
					   eb_buf,
					   walk_extents_func,
					   &wi);
		if (ret) {
			com_err(argv[0], ret,
				"while walking extents");
			goto out_free;
		}
	}

	if (walk_blocks) {
		wb.di = di;
		wb.run_first_blkno = wb.run_first_bcount =
			wb.run_prev_blkno = 0;
		wb.last_block = (wb.di->i_size +
				 (fs->fs_blocksize - 1)) /
			fs->fs_blocksize;
		ret = ocfs2_block_iterate(fs, blkno, 0,
					  walk_blocks_func,
					  &wb);
		if (ret) {
			com_err(argv[0], ret,
				"while walking blocks");
			goto out_free;
		}
	}

out_free:
	if (eb_buf)
		ocfs2_free(&eb_buf);

	ocfs2_free(&buf);

out_close:
	ret = ocfs2_close(fs);
	if (ret) {
		com_err(argv[0], ret,
			"while closing file \"%s\"", filename);
	}

out:
	return 0;
}