Example #1
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;
}
Example #2
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;
}
Example #3
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;
}
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;
}
Example #5
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;
}
Example #6
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;
}
static errcode_t remove_slots(ocfs2_filesys *fs, int num_slots)
{
	errcode_t ret;
	uint16_t old_num = OCFS2_RAW_SB(fs->fs_super)->s_max_slots;
	uint16_t removed_slot = old_num - 1;
	struct tools_progress *prog = NULL;

	ret = remove_slot_check(fs, num_slots);
	if (ret)
		goto bail;

	/* We have seven steps in removing each slot */
	prog = tools_progress_start("Removing slots", "rmslots",
				    (old_num - num_slots) * 7);
	if (!prog) {
		ret = TUNEFS_ET_NO_MEMORY;
		goto bail;
	}

	/* This is cleared up in update_slot_count() if everything works */
	ret = tunefs_set_in_progress(fs, OCFS2_TUNEFS_INPROG_REMOVE_SLOT);
	if (ret)
		goto bail;

	/* we will remove the slots once at a time so that fsck.ocfs2 can work
	 * well and we can continue our work easily in case of any panic.
	 */
	while (removed_slot >= num_slots) {
		/* Link the specified extent alloc file to others. */
		ret = relink_system_alloc(fs, removed_slot, num_slots,
					  EXTENT_ALLOC_SYSTEM_INODE);
		if (ret)
			goto bail;
		tools_progress_step(prog, 1);

		/* Link the specified inode alloc file to others. */
		ret = relink_system_alloc(fs, removed_slot, num_slots,
					  INODE_ALLOC_SYSTEM_INODE);
		if (ret)
			goto bail;
		tools_progress_step(prog, 1);

		/* Truncate the orphan dir to release its clusters
		 * to the global bitmap.
		 */
		ret = truncate_orphan_dir(fs, removed_slot);
		if (ret)
			goto bail;
		tools_progress_step(prog, 1);

		/* empty the content of journal and truncate its clusters. */
		ret = empty_and_truncate_journal(fs, removed_slot);
		if (ret)
			goto bail;
		tools_progress_step(prog, 1);

		/* Now, we decrease the max_slots first and then remove the
		 * slots for the reason that:
		 *
		 * 1. ocfs2_lock_down_clusters needs to lock all the journal
		 * files. so if we delete the journal entry first and fail
		 * to decrease the max_slots, the whole cluster can't be
		 * locked any more due to the loss of journals.
		 *
		 * 2. Now all the resources except the inodes are freed
		 * so it is safe to decrease the slots first, and if any
		 * panic happens after we decrease the slots, we can ignore
		 * them, and actually if we want to increase the slot in the
		 * future, we can reuse these inodes.
		 */

		/* The slot number is updated in the super block.*/
		OCFS2_RAW_SB(fs->fs_super)->s_max_slots--;
		ret = ocfs2_write_primary_super(fs);
		if (ret)
			goto bail;
		tools_progress_step(prog, 1);

		/* The extra system dir entries should be removed. */
		ret = remove_slot_entry(fs, removed_slot);
		if (ret)
			goto bail;
		tools_progress_step(prog, 1);

		/* Decrease the i_links_count in system file directory
		 * since the orphan_dir is removed.
		 */
		ret = decrease_link_count(fs, fs->fs_sysdir_blkno);
		if (ret)
			goto bail;
		tools_progress_step(prog, 1);

		removed_slot--;
	}

bail:
	if (prog)
		tools_progress_stop(prog);

	return ret;
}
static errcode_t add_slots(ocfs2_filesys *fs, int num_slots)
{
	errcode_t ret;
	uint16_t old_num = OCFS2_RAW_SB(fs->fs_super)->s_max_slots;
	char fname[OCFS2_MAX_FILENAME_LEN];
	uint64_t blkno;
	int i, j, max_slots;
	int ftype;
	struct tools_progress *prog = NULL;

	if (ocfs2_uses_extended_slot_map(OCFS2_RAW_SB(fs->fs_super))) {
		ret = TUNEFS_ET_TOO_MANY_SLOTS_EXTENDED;
		max_slots = INT16_MAX;
	} else {
		ret = TUNEFS_ET_TOO_MANY_SLOTS_OLD;
		max_slots = OCFS2_MAX_SLOTS;
	}
	if (num_slots > max_slots)
		goto bail;

	prog = tools_progress_start("Adding slots", "addslots",
				    (NUM_SYSTEM_INODES -
				     OCFS2_LAST_GLOBAL_SYSTEM_INODE - 1) *
				    (num_slots - old_num));
	if (!prog) {
		ret = TUNEFS_ET_NO_MEMORY;
		goto bail;
	}

	ret = 0;
	for (i = OCFS2_LAST_GLOBAL_SYSTEM_INODE + 1; i < NUM_SYSTEM_INODES; ++i) {
		for (j = old_num; j < num_slots; ++j) {
			ocfs2_sprintf_system_inode_name(fname,
							OCFS2_MAX_FILENAME_LEN,
							i, j);
			verbosef(VL_APP, "Creating system file \"%s\"\n",
				 fname);

			/* Goto next if file already exists */
			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);
				tools_progress_step(prog, 1);
				continue;
			}

			/* create inode for system file */
			ret = ocfs2_new_system_inode(fs, &blkno,
						     ocfs2_system_inodes[i].si_mode,
						     ocfs2_system_inodes[i].si_iflags);
			if (ret) {
				verbosef(VL_APP,
					 "%s while creating inode for "
					 "system file \"%s\"\n",
					 error_message(ret), fname);
				goto bail;
			}

			ftype = (S_ISDIR(ocfs2_system_inodes[i].si_mode) ?
				 OCFS2_FT_DIR : OCFS2_FT_REG_FILE);

			/* if dir, alloc space to it */
			if (ftype == OCFS2_FT_DIR) {
				ret = ocfs2_init_dir(fs, blkno,
						     fs->fs_sysdir_blkno);
				if (ret) {
					verbosef(VL_APP,
						 "%s while initializing "
						 "directory \"%s\"\n",
						 error_message(ret),
						 fname);
					goto bail;
				}
			}

			/* Add the inode to the system dir */
			ret = ocfs2_link(fs, fs->fs_sysdir_blkno, fname,
					 blkno, ftype);
			if (ret) {
				verbosef(VL_APP,
					"%s while linking inode %"PRIu64" "
					"as \"%s\" in the system "
					"directory\n",
					error_message(ret), blkno, fname);
				goto bail;
			}
			verbosef(VL_APP, "System file \"%s\" created\n",
				 fname);
			tools_progress_step(prog, 1);
		}
	}

bail:
	if (prog)
		tools_progress_stop(prog);

	return ret;
}