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; }
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; }
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; }