Exemplo n.º 1
0
errcode_t o2cbtool_init_cluster_stack(void)
{
	errcode_t ret;
	const char *stack = NULL;

	verbosef(VL_DEBUG, "Initializing cluster stack\n");

	ret = o2cb_init();
	if (ret) {
		tcom_err(ret, "while initializing the cluster");
		goto bail;
	}

	ret = o2cb_get_stack_name(&stack);
	if (ret) {
		tcom_err(ret, "while determining the current cluster stack");
		goto bail;
	}

	if (strcmp(stack, stackname)) {
		ret = -1;
		errorf("This tool supports the '%s' stack, but the '%s' "
		       "stack is in use.\n", stackname, stack);
	}

bail:
	return ret;
}
Exemplo n.º 2
0
static errcode_t create_system_file(ocfs2_filesys *fs, int type, int node)
{
	char fname[OCFS2_MAX_FILENAME_LEN];
	uint64_t blkno;
	errcode_t ret;

	ocfs2_sprintf_system_inode_name(fname, sizeof(fname),
		type, node);
	ret = ocfs2_lookup(fs, fs->fs_sysdir_blkno, fname, strlen(fname), NULL,
			   &blkno);
	if (!ret) {
		verbosef(VL_APP, "System file \"%s\" already exists!\n",
			 fname);
		return 0;
	}
	ret = ocfs2_new_system_inode(fs, &blkno,
				ocfs2_system_inodes[type].si_mode,
				ocfs2_system_inodes[type].si_iflags);
	if (ret) {
		tcom_err(ret, "while creating system file \"%s\"", fname);
		return ret;
	}

	ret = ocfs2_link(fs, fs->fs_sysdir_blkno, fname, blkno,
			 OCFS2_FT_REG_FILE);
	if (ret) {
		tcom_err(ret, "while linking file \"%s\" in the system "
			 "directory", fname);
		return ret;
	}
	return 0;
}
Exemplo n.º 3
0
static errcode_t check_backup_offsets(ocfs2_filesys *fs)
{

	errcode_t ret;
	int i, num, val, failed = 0;
	ocfs2_cached_inode *chain_alloc = NULL;
	uint64_t blocks[OCFS2_MAX_BACKUP_SUPERBLOCKS];

	num = ocfs2_get_backup_super_offsets(fs, blocks,
					     ARRAY_SIZE(blocks));
	if (!num) {
		ret = 1;
		errorf("Volume on device \"%s\" is too small to contain "
		       "backup superblocks\n",
		       fs->fs_devname);
		goto bail;
	}

	ret = load_global_bitmap(fs, &chain_alloc);
	if (ret) {
		tcom_err(ret, "while loading the global bitmap");
		goto bail;
	}

	for (i = 0; i < num; i++) {
		ret = ocfs2_bitmap_test(chain_alloc->ci_chains,
					ocfs2_blocks_to_clusters(fs, blocks[i]),
					&val);
		if (ret) {
			tcom_err(ret,
				 "looking up backup superblock locations "
				 "in the global bitmap");
			goto bail;
		}

		if (val) {
			verbosef(VL_APP,
				 "Backup superblock location %d at block "
				 "%"PRIu64" is in use\n", i, blocks[i]);
			/* in order to verify all the block in the 'blocks',
			 * we don't stop the loop here.
			 */
			failed = 1;
		}
	}

	if (failed) {
		ret = 1;
		errorf("One or more backup superblock locations are "
		       "already in use\n");
	} else
		ret = 0;

	if (chain_alloc)
		ocfs2_free_cached_inode(fs, chain_alloc);

bail:
	return ret;
}
Exemplo n.º 4
0
static int remove_quota_files_iterate(struct ocfs2_dir_entry *dirent,
				      uint64_t blocknr, int offset,
				      int blocksize, char *buf,
				      void *priv_data)
{
	struct remove_quota_files_ctxt *ctxt = priv_data;
	char dname[OCFS2_MAX_FILENAME_LEN];
	char wname[OCFS2_MAX_FILENAME_LEN];
	errcode_t ret;
	int tail, i;
	int ret_flags = 0;

	strncpy(dname, dirent->name, dirent->name_len);
	dname[dirent->name_len] = 0;

	/* Check whether entry is quota file of type we want - i.e. matching
	 * aquota.user:[0-9][0-9][0-9][0-9] or aquota.user for type == USRQUOTA
	 * and similarly for type == GRPQUOTA */
	strcpy(wname, "aquota.");
	strcat(wname, type2name(ctxt->type));
	tail = strlen(wname);
	if (strncmp(dname, wname, tail))
		return 0;
	if (dname[tail] == ':') {	/* May be local file? */
		tail++;
		for (i = 0; i < 4; i++)
			if (dname[tail + i] < '0' || dname[tail + i] > '9')
				return 0;
		if (dname[tail + i])
			return 0;
	} else if (dname[tail])		/* May be global file? */
		return 0;

	verbosef(VL_APP, "Deleting quota file %s\n",
		 dname);
	ret = ocfs2_truncate(ctxt->fs, dirent->inode, 0);
	if (ret) {
		tcom_err(ret, "while truncating quota file \"%s\"", dname);
		ret_flags |= OCFS2_DIRENT_ERROR;
		ctxt->err = ret;
		goto out;
	}
	ret = ocfs2_delete_inode(ctxt->fs, dirent->inode);
	if (ret) {
		tcom_err(ret, "while deleting quota file \"%s\"", dname);
		ret_flags |= OCFS2_DIRENT_ERROR;
		ctxt->err = ret;
	} else {
		dirent->inode = 0;
		ret_flags |= OCFS2_DIRENT_CHANGED;
	}
out:
	return ret_flags;
}
Exemplo n.º 5
0
int main(int argc, char **argv)
{
	errcode_t ret;
	struct o2cb_command *cmd;
	O2CBConfig *oc_config = NULL;

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

	initialize_o2cb_error_table();

	tools_setup_argv0(argv[0]);

	parse_options(argc, argv, &cmd);

	ret = o2cb_config_load(cmd->o_config_file, &oc_config);
	if (ret) {
		tcom_err(ret, "while loading cluster configuration "
			 "file '%s'", cmd->o_config_file);
		goto bail;
	}

	cmd->o_config = oc_config;
	cmd->o_modified = 0;
	cmd->o_print_usage = 1;

	ret = -1;
	if (!cmd->o_action) {
		errorf("Command '%s' has not been implemented\n", cmd->o_name);
		goto bail;
	}

	ret = cmd->o_action(cmd);

	if (cmd->o_print_usage)
		errorf("usage: %s %s\n", cmd->o_name, cmd->o_usage);

	if (ret || !cmd->o_modified)
		goto bail;

	ret = o2cb_config_store(oc_config, cmd->o_config_file);
	if (ret)
		tcom_err(ret, "while storing the cluster configuration in "
			 "file '%s'", cmd->o_config_file);

bail:
	if (oc_config)
		o2cb_config_free(oc_config);

	ret = ret ? 1 : 0;

	return ret;
}
Exemplo n.º 6
0
static int features_parse_option(struct tunefs_operation *op, char *arg)
{
    int rc = 1;
    errcode_t err;
    struct feature_op_state *state = NULL;
    struct check_supported_context ctxt = {
        .sc_string = arg,
    };

    if (!arg) {
        errorf("No features specified\n");
        goto out;
    }

    err = ocfs2_malloc0(sizeof(struct feature_op_state), &state);
    if (err) {
        tcom_err(err, "while processing feature options");
        goto out;
    }

    state->fo_op = op;
    err = ocfs2_parse_feature(arg, &state->fo_feature_set,
                              &state->fo_reverse_set);
    if (err) {
        tcom_err(err, "while parsing feature options \"%s\"", arg);
        goto out;
    }

    ctxt.sc_state = state;
    ctxt.sc_action = FEATURE_ENABLE;
    ocfs2_feature_foreach(&state->fo_feature_set, check_supported_func,
                          &ctxt);
    if (ctxt.sc_error)
        goto out;

    ctxt.sc_action = FEATURE_DISABLE;
    ocfs2_feature_reverse_foreach(&state->fo_reverse_set,
                                  check_supported_func,
                                  &ctxt);
    if (ctxt.sc_error)
        goto out;

    rc = 0;

out:
    if (!rc)
        op->to_private = state;
    else if (state)
        ocfs2_free(&state);

    return rc;
}
Exemplo n.º 7
0
static int enable_backup_super(ocfs2_filesys *fs, int flags)
{
	errcode_t err = 0;
	struct ocfs2_super_block *super = OCFS2_RAW_SB(fs->fs_super);
	struct tools_progress *prog;

	if (OCFS2_HAS_COMPAT_FEATURE(super,
				     OCFS2_FEATURE_COMPAT_BACKUP_SB)) {
		verbosef(VL_APP,
			 "Backup superblock feature is already enabled; "
			 "nothing to enable\n");
		goto out;
	}

	if (!tools_interact("Enable the backup superblock feature on "
			    "device \"%s\"? ",
			    fs->fs_devname))
		goto out;

	prog = tools_progress_start("Enable backup-super", "backup-super",
				    2);
	if (!prog) {
		err = TUNEFS_ET_NO_MEMORY;
		tcom_err(err, "while initializing the progress display");
		goto out;
	}

	tunefs_block_signals();
	err = check_backup_offsets(fs);
	tools_progress_step(prog, 1);
	if (!err)
		err = fill_backup_supers(fs);
	if (!err) {
		super->s_feature_compat |= OCFS2_FEATURE_COMPAT_BACKUP_SB;
		err = ocfs2_write_super(fs);
		if (err)
			tcom_err(err, "while writing out the superblock\n");
	}
	tunefs_unblock_signals();

	tools_progress_step(prog, 1);
	tools_progress_stop(prog);

	if (err)
		errorf("Unable to enable the backup superblock feature on "
		       "device \"%s\"\n",
		       fs->fs_devname);
out:
	return err;
}
Exemplo n.º 8
0
/*
 * When creating printf fields for ourselves, we need to avoid the
 * standard specifiers.  All lowercase specifiers are reserved by C99.
 * Reserved uppercase specifiers are: E, F, G, A, C, S, X, L
 */
static int query_run(struct tunefs_operation *op, ocfs2_filesys *fs,
		     int flags)
{
	char *queryfmt = op->to_private;
	char *fmt;

	fmt = process_escapes(queryfmt);
	if (!fmt) {
		tcom_err(TUNEFS_ET_NO_MEMORY,
			 "while escaping the query format");
		return 1;
	}

	register_printf_function('B', handle_blocksize, handle_arginfo);
	register_printf_function('T', handle_clustersize, handle_arginfo);
	register_printf_function('N', handle_numslots, handle_arginfo);
	register_printf_function('R', handle_rootdir, handle_arginfo);
	register_printf_function('Y', handle_sysdir, handle_arginfo);
	register_printf_function('P', handle_clustergroup, handle_arginfo);

	register_printf_function('V', handle_label, handle_arginfo);
	register_printf_function('U', handle_uuid, handle_arginfo);

	register_printf_function('M', handle_compat, handle_arginfo);
	register_printf_function('H', handle_incompat, handle_arginfo);
	register_printf_function('O', handle_ro_compat, handle_arginfo);

	query_fs = fs;
	fprintf(stdout, fmt);
	query_fs = NULL;

	ocfs2_free(&fmt);

	return 0;
}
Exemplo n.º 9
0
static int set_journal_block64_run(struct tunefs_operation *op,
				ocfs2_filesys *fs, int flags)
{
	errcode_t err;
	int rc = 0;
	ocfs2_fs_options mask, options;
	struct ocfs2_super_block *super = OCFS2_RAW_SB(fs->fs_super);

	memset(&mask, 0, sizeof(ocfs2_fs_options));
	memset(&options, 0, sizeof(ocfs2_fs_options));
	mask.opt_incompat |= JBD2_FEATURE_INCOMPAT_64BIT;
	options.opt_incompat |= JBD2_FEATURE_INCOMPAT_64BIT;

	if (!tools_interact("Enable block64 journal feature on device \"%s\"? ",
			    fs->fs_devname))
		goto out;

	tunefs_block_signals();
	super->s_feature_compat |= OCFS2_FEATURE_COMPAT_JBD2_SB;
	err = ocfs2_write_super(fs);
	if (!err)
		err = tunefs_set_journal_size(fs, 0, mask, options);
	tunefs_unblock_signals();
	if (err) {
		rc = 1;
		tcom_err(err,
			"; unable to enable block64 journal feature on "
			"device \"%s\"", fs->fs_devname);
	}

out:
	return rc;
}
Exemplo n.º 10
0
static void tunefs_inprog_flag_in_str(uint32_t flag, char *buf, size_t len)
{
	errcode_t err;

	err = ocfs2_snprint_tunefs_flags(buf, len, flag);
	if (err)
		tcom_err(err, "while processing inprog flags");
}
Exemplo n.º 11
0
static void ro_compat_flag_in_str(uint32_t flag, char *buf, size_t len)
{
	errcode_t err;
	ocfs2_fs_options flags = {
		.opt_ro_compat = flag,
	};

	err = ocfs2_snprint_feature_flags(buf, len, &flags);
	if (err)
		tcom_err(err, "while processing feature flags");
}
Exemplo n.º 12
0
static int run_feature_func(ocfs2_fs_options *feature, void *user_data)
{
    errcode_t err;
    struct run_features_context *ctxt = user_data;
    struct tunefs_feature *feat = find_feature(feature);

    err = tunefs_feature_run(ctxt->rc_fs, feat);
    if (err && (err != TUNEFS_ET_OPERATION_FAILED))
        tcom_err(err, "while toggling feature \"%s\"",
                 feat->tf_name);

    return err;
}
Exemplo n.º 13
0
static int disable_grpquota(ocfs2_filesys *fs, int flags)
{
	errcode_t ret;
	struct ocfs2_super_block *super = OCFS2_RAW_SB(fs->fs_super);
	struct tools_progress *prog = NULL;

	if (!OCFS2_HAS_RO_COMPAT_FEATURE(super,
	    OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)) {
		verbosef(VL_APP, "Group quotas are already disabled; "
			 "nothing to disable\n");
		return 0;
	}

	if (!tools_interact("Disable group quota feature on device "
			    "\"%s\"? ",
			    fs->fs_devname))
		return 0;
	prog = tools_progress_start("Disabling user quota", "nousrquota", 2);
	if (!prog) {
		ret = TUNEFS_ET_NO_MEMORY;
		tcom_err(ret, "while initializing progress display");
		return ret;
	}

	tunefs_block_signals();
	ret = remove_quota_files(fs, GRPQUOTA, prog);
	if (ret) {
		tcom_err(ret, "while removing group quota files");
		goto bail;
	}
	OCFS2_CLEAR_RO_COMPAT_FEATURE(super,
				      OCFS2_FEATURE_RO_COMPAT_GRPQUOTA);
	ret = ocfs2_write_super(fs);
	tools_progress_step(prog, 1);
bail:
	tools_progress_stop(prog);
	tunefs_unblock_signals();
	return ret;
}
Exemplo n.º 14
0
static errcode_t fill_backup_supers(ocfs2_filesys *fs)
{
	errcode_t ret;
	int num;
	uint64_t blocks[OCFS2_MAX_BACKUP_SUPERBLOCKS];

	num = ocfs2_get_backup_super_offsets(fs, blocks,
					     ARRAY_SIZE(blocks));
	ret = ocfs2_set_backup_super_list(fs, blocks, num);
	if (ret)
		tcom_err(ret, "while backing up the superblock");

	return ret;
}
Exemplo n.º 15
0
static int set_journal_block32_run(struct tunefs_operation *op,
				ocfs2_filesys *fs, int flags)
{
	errcode_t err;
	int rc = 0;
	ocfs2_fs_options mask, options;

	if (fs->fs_blocks > UINT32_MAX) {
		tcom_err(TUNEFS_ET_OPERATION_FAILED,
			"; cannot enable block32 journal feature on "
			"device \"%s\" having more that %u blocks",
			fs->fs_devname, UINT32_MAX);
		rc = 1;
		goto out;
	}

	memset(&mask, 0, sizeof(ocfs2_fs_options));
	memset(&options, 0, sizeof(ocfs2_fs_options));
	mask.opt_incompat |= JBD2_FEATURE_INCOMPAT_64BIT;

	if (!tools_interact("Enable block32 journal feature on device \"%s\" ?",
			    fs->fs_devname))
		goto out;

	tunefs_block_signals();
	err = tunefs_set_journal_size(fs, 0, mask, options);
	tunefs_unblock_signals();
	if (err) {
		rc = 1;
		tcom_err(err, "; unable to enable block32 journal feature on "
			 "device \"%s\"", fs->fs_devname);
	}

out:
	return rc;
}
Exemplo n.º 16
0
static errcode_t empty_backup_supers(ocfs2_filesys *fs)
{
	errcode_t ret;
	int num;
	uint64_t blocks[OCFS2_MAX_BACKUP_SUPERBLOCKS];

	num = ocfs2_get_backup_super_offsets(fs, blocks,
					     ARRAY_SIZE(blocks));
	if (!num)
		return 0;

	ret = ocfs2_clear_backup_super_list(fs, blocks, num);
	if (ret)
		tcom_err(ret, "while freeing backup  superblock locations");

	return ret;
}
Exemplo n.º 17
0
static int cloned_volume_run(struct tunefs_operation *op, ocfs2_filesys *fs,
			     int flags)
{
	errcode_t err;
	int rc = 0;
	char *new_label = op->to_private;

	err = cloned_volume(fs, new_label);
	if (err) {
		tcom_err(err,
			 "- unable to update the uuid and label on "
			 "device \"%s\"",
			 fs->fs_devname);
		rc = 1;
	}

	return rc;
}
Exemplo n.º 18
0
static int set_slot_count_run(struct tunefs_operation *op,
			      ocfs2_filesys *fs, int flags)
{
	errcode_t err;
	int rc = 0;
	int num_slots = (int)(unsigned long)op->to_private;

	err = update_slot_count(fs, num_slots);
	if (err) {
		tcom_err(err,
			 "- unable to update the number of slots on device "
			 "\"%s\"",
			 fs->fs_devname);
		rc = 1;
	}

	return rc;
}
Exemplo n.º 19
0
static errcode_t cloned_volume(ocfs2_filesys *fs, const char *new_label)
{
	errcode_t err;
	struct tools_progress *prog;

	if (!tools_interact_critical(
		"Updating the UUID and label on cloned volume \"%s\".\n"
		"DANGER: THIS WILL MODIFY THE UUID WITHOUT ACCESSING THE "
		"CLUSTER SOFTWARE.  YOU MUST BE ABSOLUTELY SURE THAT NO "
		"OTHER NODE IS USING THIS FILESYSTEM BEFORE MODIFYING "
		"ITS UUID.\n"
	        "Update the UUID and label? ",
		fs->fs_devname))
		return 0;

	prog = tools_progress_start("Cloning volume", "cloning", 3);
	if (!prog) {
		err = TUNEFS_ET_NO_MEMORY;
		tcom_err(err, "while initializing the progress display");
		goto out;
	}

	update_volume_uuid(fs);
	tools_progress_step(prog, 1);

	update_volume_label(fs, new_label);
	tools_progress_step(prog, 1);

	tunefs_block_signals();
	err = ocfs2_write_super(fs);
	tunefs_unblock_signals();
	tools_progress_step(prog, 1);

	tools_progress_stop(prog);

out:
	return err;
}
Exemplo n.º 20
0
static int update_sync_interval(ocfs2_filesys *fs, int type,
				unsigned long syncms)
{
	errcode_t err;
	struct tools_progress *prog;
	int feature = (type == USRQUOTA) ? OCFS2_FEATURE_RO_COMPAT_USRQUOTA :
					   OCFS2_FEATURE_RO_COMPAT_GRPQUOTA;
	struct ocfs2_global_disk_dqinfo *qinfo;

	if (!OCFS2_HAS_RO_COMPAT_FEATURE(OCFS2_RAW_SB(fs->fs_super), feature)) {
		errorf("The %s quota is not enabled on device \"%s\"\n",
		       type2name(type), fs->fs_devname);
		return 1;
	}
	err = ocfs2_init_fs_quota_info(fs, type);
	if (err) {
		tcom_err(err, "while looking up %s quota file on device "
			 "\"%s\"", type2name(type), fs->fs_devname);
		return 1;
	}
	err = ocfs2_read_global_quota_info(fs, type);
	if (err) {
		tcom_err(err, "while reading %s quota info on device \"%s\"",
			 type2name(type), fs->fs_devname);
		return 1;
	}
	qinfo = &fs->qinfo[type].qi_info;
	if (qinfo->dqi_syncms == syncms) {
		verbosef(VL_APP,
			 "Device \"%s\" already has interval %lu set; "
			 "nothing to do\n", fs->fs_devname, syncms);
		return 0;
	}

	if (!tools_interact("Change quota syncing interval on device \"%s\" "
			    "from %lu to %lu? ", fs->fs_devname,
			    (unsigned long)qinfo->dqi_syncms, syncms))
		return 0;

	prog = tools_progress_start("Setting syncing interval", "interval", 1);
	if (!prog) {
		tcom_err(err, "while initializing the progress display");
		return 1;
	}

	tunefs_block_signals();
	qinfo->dqi_syncms = syncms;
	err = ocfs2_write_global_quota_info(fs, type);
	tunefs_unblock_signals();

	tools_progress_step(prog, 1);
	tools_progress_stop(prog);

	if (err) {
		tcom_err(err,
			 "- unable to update %s quota syncing interval on "
			 "device \"%s\"", type2name(type), fs->fs_devname);
		return 1;
	}

	return 0;
}
Exemplo n.º 21
0
static errcode_t create_quota_files(ocfs2_filesys *fs, int type,
				    struct tools_progress *prog)
{
	ocfs2_quota_hash *hash;
	errcode_t ret;
	int num_slots = OCFS2_RAW_SB(fs->fs_super)->s_max_slots;
	int i;
	int local_type = (type == USRQUOTA) ?
				LOCAL_USER_QUOTA_SYSTEM_INODE :
				LOCAL_GROUP_QUOTA_SYSTEM_INODE;
	int global_type = (type == USRQUOTA) ?
				USER_QUOTA_SYSTEM_INODE :
				GROUP_QUOTA_SYSTEM_INODE;

	verbosef(VL_APP, "Creating %s quota system files\n", type2name(type));
	ret = create_system_file(fs, global_type, 0);
	if (ret)
		return ret;
	for (i = 0; i < num_slots; i++) {
		ret = create_system_file(fs, local_type, i);
		if (ret)
			return ret;
	}
	tools_progress_step(prog, 1);

	verbosef(VL_APP, "Initializing global %s quota file\n",
		 type2name(type));
	ret = ocfs2_init_fs_quota_info(fs, type);
	if (ret) {
		tcom_err(ret, "while looking up global %s quota file",
			 type2name(type));
		return ret;
	}
	fs->qinfo[type].flags = OCFS2_QF_INFO_LOADED;
	fs->qinfo[type].qi_info.dqi_syncms = OCFS2_DEF_QUOTA_SYNC;
	fs->qinfo[type].qi_info.dqi_bgrace = OCFS2_DEF_BLOCK_GRACE;
	fs->qinfo[type].qi_info.dqi_igrace = OCFS2_DEF_INODE_GRACE;

	ret = ocfs2_init_global_quota_file(fs, type);
	if (ret) {
		tcom_err(ret, "while initilizing global %s quota files",
			 type2name(type));
		return ret;
	}
	tools_progress_step(prog, 1);

	verbosef(VL_APP, "Initializing local %s quota files\n",
		 type2name(type));
	ret = ocfs2_init_local_quota_files(fs, type);
	if (ret) {
		tcom_err(ret, "while initilizing local %s quota files",
			 type2name(type));
		return ret;
	}
	tools_progress_step(prog, 1);

	verbosef(VL_APP, "Computing %s quota usage\n",
		 type2name(type));
	ret = ocfs2_new_quota_hash(&hash);
	if (ret) {
		tcom_err(ret, "while creating quota hash");
		return ret;
	}
	if (type == USRQUOTA)
		ret = ocfs2_compute_quota_usage(fs, hash, NULL);
	else
		ret = ocfs2_compute_quota_usage(fs, NULL, hash);
	if (ret) {
		tcom_err(ret, "while scanning filesystem to gather "
			 "quota usage");
		return ret;
	}
	tools_progress_step(prog, 1);

	verbosef(VL_APP, "Write %s quotas to file\n",
		 type2name(type));
	ret = ocfs2_write_release_dquots(fs, type, hash);
	if (ret) {
		tcom_err(ret, "while writing %s quota usage to disk",
			 type2name(type));
		return ret;
	}
	tools_progress_step(prog, 1);

	ret = ocfs2_free_quota_hash(hash);
	if (ret)
		tcom_err(ret, "while freeing quota hash");
	return ret;
}
Exemplo n.º 22
0
static errcode_t remove_quota_files(ocfs2_filesys *fs, int type,
				    struct tools_progress *prog)
{
	struct remove_quota_files_ctxt ctxt = {
		.fs = fs,
		.type = type,
		.err = 0,
	};

	ocfs2_dir_iterate(fs, fs->fs_sysdir_blkno,
			  OCFS2_DIRENT_FLAG_EXCLUDE_DOTS, NULL,
			  remove_quota_files_iterate, &ctxt);
	tools_progress_step(prog, 1);
	return ctxt.err;
}

static int enable_usrquota(ocfs2_filesys *fs, int flags)
{
	struct ocfs2_super_block *super = OCFS2_RAW_SB(fs->fs_super);
	errcode_t ret;
	struct tools_progress *prog = NULL;

	if (OCFS2_HAS_RO_COMPAT_FEATURE(super,
	    OCFS2_FEATURE_RO_COMPAT_USRQUOTA)) {
		verbosef(VL_APP, "User quotas are already enabled; "
			 "nothing to enable\n");
		return 0;
	}

	if (!tools_interact("Enable user quota feature on device "
			    "\"%s\"? ",
			    fs->fs_devname))
		return 0;

	prog = tools_progress_start("Enabling user quota", "usrquota", 6);
	if (!prog) {
		ret = TUNEFS_ET_NO_MEMORY;
		tcom_err(ret, "while initializing progress display");
		return ret;
	}
	tunefs_block_signals();
	ret = create_quota_files(fs, USRQUOTA, prog);
	if (ret) {
		tcom_err(ret, "while creating user quota files");
		goto bail;
	}
	OCFS2_SET_RO_COMPAT_FEATURE(super,
				    OCFS2_FEATURE_RO_COMPAT_USRQUOTA);
	ret = ocfs2_write_super(fs);
	tools_progress_step(prog, 1);
bail:
	tunefs_unblock_signals();
	tools_progress_stop(prog);
	return ret;
}

static int disable_usrquota(ocfs2_filesys *fs, int flags)
{
	errcode_t ret;
	struct ocfs2_super_block *super = OCFS2_RAW_SB(fs->fs_super);
	struct tools_progress *prog = NULL;

	if (!OCFS2_HAS_RO_COMPAT_FEATURE(super,
	    OCFS2_FEATURE_RO_COMPAT_USRQUOTA)) {
		verbosef(VL_APP, "User quotas are already disabled; "
			 "nothing to disable\n");
		return 0;
	}

	if (!tools_interact("Disable user quota feature on device "
			    "\"%s\"? ",
			    fs->fs_devname))
		return 0;

	prog = tools_progress_start("Disabling user quota", "nousrquota", 2);
	if (!prog) {
		ret = TUNEFS_ET_NO_MEMORY;
		tcom_err(ret, "while initializing progress display");
		return ret;
	}
	tunefs_block_signals();
	ret = remove_quota_files(fs, USRQUOTA, prog);
	if (ret) {
		tcom_err(ret, "while removing user quota files");
		goto bail;
	}
	OCFS2_CLEAR_RO_COMPAT_FEATURE(super,
				      OCFS2_FEATURE_RO_COMPAT_USRQUOTA);
	ret = ocfs2_write_super(fs);
	tools_progress_step(prog, 1);
bail:
	tunefs_unblock_signals();
	tools_progress_stop(prog);
	return ret;
}