Example #1
0
int main(int argc, char **argv)
{
	errcode_t error;
	struct command_s c;

	initialize_o2dl_error_table();

	prog = argv[0];

	if (argc < 2) {
		dlmfs_path = DEFAULT_DLMFS_PATH;
		printf("No fs path provided, using %s\n", dlmfs_path);
	} else if (!strcmp(argv[1], "-u")) {
		dlmfs_path = NULL;
		printf("Using fsdlm\n");
	} else {
		dlmfs_path = argv[1];
		printf("Using fs at %s\n", dlmfs_path);
	}

	printf("Type \"help\" to see a list of commands\n");

	while (!get_command(&c)) {
		error = exec_command(&c);

		if (error) {
			print_command(&c, "failed!");
			com_err(prog, error, "returned\n");
		} else
			print_command(&c, "succeeded!\n");
	}
	return 0;
}
Example #2
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;
}
Example #3
0
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;
}