[Ocfs2-tools-commits] smushran commits r1102 - in branches/tunefs-resize: libocfs2/include tunefs.ocfs2

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Wed Oct 19 19:44:22 CDT 2005


Author: smushran
Date: 2005-10-19 19:44:21 -0500 (Wed, 19 Oct 2005)
New Revision: 1102

Modified:
   branches/tunefs-resize/libocfs2/include/ocfs2.h
   branches/tunefs-resize/tunefs.ocfs2/tunefs.c
Log:
resize now extends volumesize in tunefs

Modified: branches/tunefs-resize/libocfs2/include/ocfs2.h
===================================================================
--- branches/tunefs-resize/libocfs2/include/ocfs2.h	2005-10-20 00:38:30 UTC (rev 1101)
+++ branches/tunefs-resize/libocfs2/include/ocfs2.h	2005-10-20 00:44:21 UTC (rev 1102)
@@ -657,6 +657,21 @@
 		cgs->cgs_tail_group_bits = cgs->cgs_cpg;
 }
 
+/* given a cluster offset, calculate which block group it belongs to
+ * and return that block offset. */
+static inline uint64_t ocfs2_which_cluster_group(ocfs2_filesys *fs,
+						 uint16_t cpg,
+						 uint32_t cluster)
+{
+	ocfs2_super_block *sb = OCFS2_RAW_SB(fs->fs_super);
+	uint32_t group_no;
+
+	group_no = cluster / cpg;
+	if (!group_no)
+		return sb->s_first_cluster_group;
+	return ocfs2_clusters_to_blocks(fs, group_no * cpg);
+}
+
 /*
  * shamelessly lifted from the kernel
  *

Modified: branches/tunefs-resize/tunefs.ocfs2/tunefs.c
===================================================================
--- branches/tunefs-resize/tunefs.ocfs2/tunefs.c	2005-10-20 00:38:30 UTC (rev 1101)
+++ branches/tunefs-resize/tunefs.ocfs2/tunefs.c	2005-10-20 00:44:21 UTC (rev 1102)
@@ -64,7 +64,7 @@
 
 typedef struct _ocfs2_tune_opts {
 	uint16_t num_slots;
-	uint64_t vol_size;
+	uint64_t num_blocks;
 	uint64_t jrnl_size;
 	char *vol_label;
 	char *progname;
@@ -79,13 +79,14 @@
 static ocfs2_tune_opts opts;
 static ocfs2_filesys *fs_gbl = NULL;
 static int cluster_locked = 0;
+static int resize = 1;
 
 static void usage(const char *progname)
 {
 	fprintf(stderr, "usage: %s [-N number-of-node-slots] "
 			"[-L volume-label]\n"
-			"\t[-J journal-options] [-S volume-size] [-qvV] "
-			"device\n",
+			"\t[-J journal-options] [-S] [-qvV] "
+			"device [blocks-count]\n",
 			progname);
 	exit(0);
 }
@@ -233,9 +234,8 @@
 {
 	int c;
 	int show_version = 0;
-	int ret;
 	char *dummy;
-	uint64_t val;
+	int resize = 0;
 
 	static struct option long_options[] = {
 		{ "label", 1, 0, 'L' },
@@ -256,7 +256,7 @@
 	opts.prompt = 1;
 
 	while (1) {
-		c = getopt_long(argc, argv, "L:N:J:S:vqVx", long_options, 
+		c = getopt_long(argc, argv, "L:N:J:SvqVx", long_options, 
 				NULL);
 
 		if (c == -1)
@@ -299,10 +299,7 @@
 			break;
 
 		case 'S':
-			ret = get_number(optarg, &val);
-			if (ret)
-				exit(1);
-			opts.vol_size = val;
+			resize = 1;
 			break;
 
 		case 'v':
@@ -337,12 +334,78 @@
 		usage(opts.progname);
 
 	opts.device = strdup(argv[optind]);
+	optind++;
 
+	if (optind < argc) {
+		opts.num_blocks = strtoull(argv[optind], &dummy, 0);
+		if ((*dummy)) {
+			com_err(opts.progname, 0, "Block count bad - %s",
+				argv[optind]);
+			exit(1);
+		}
+		optind++;
+	}
+
+	if (optind < argc)
+		usage(opts.progname);
+
 	opts.tune_time = time(NULL);
 
 	return ;
 }
 
+static void get_vol_size(ocfs2_filesys *fs)
+{
+	errcode_t ret = 0;
+	uint64_t num_blocks;
+
+	ret = ocfs2_get_device_size(opts.device, fs->fs_blocksize,
+				    &num_blocks);
+	if (ret) {
+		com_err(opts.progname, ret, "while getting size of device %s",
+			opts.device);
+		exit(1);
+	}
+
+	if (!opts.num_blocks)
+		opts.num_blocks = num_blocks;
+
+	if (opts.num_blocks > num_blocks) {
+		fprintf(stderr, "The containing partition (or device) "
+			"is only %"PRIu64" blocks.\n", num_blocks);
+		exit(1);
+	}
+
+	return ;
+}
+
+static int validate_vol_size(ocfs2_filesys *fs)
+{
+	uint64_t num_blocks;
+
+	if (opts.num_blocks == fs->fs_blocks) {
+		fprintf(stderr, "The filesystem is already "
+			"%"PRIu64" blocks\n", fs->fs_blocks);
+		return -1;
+	}
+
+	if (opts.num_blocks < fs->fs_blocks) {
+		fprintf(stderr, "Cannot reduce volume size from "
+		       "%"PRIu64" blocks to %"PRIu64" blocks\n",
+		       fs->fs_blocks, opts.num_blocks);
+		return -1;
+	}
+
+	num_blocks = ocfs2_clusters_to_blocks(fs, 1);
+	if (num_blocks > (opts.num_blocks - fs->fs_blocks)) {
+		fprintf(stderr, "Cannot increase volume size less than "
+		       "%d blocks\n", num_blocks);
+		return -1;
+	}
+
+	return 0;
+}
+
 static errcode_t add_slots(ocfs2_filesys *fs)
 {
 	errcode_t ret = 0;
@@ -631,8 +694,156 @@
 
 static errcode_t update_volume_size(ocfs2_filesys *fs, int *changed)
 {
-	printf("TODO: update_volume_size\n");
-	return 0;
+	errcode_t ret = 0;
+	ocfs2_dinode *di;
+	uint64_t bm_blkno;
+	uint64_t gd_blkno;
+	char *in_buf = NULL;
+	char *gd_buf = NULL;
+	ocfs2_chain_list *cl;
+	ocfs2_chain_rec *cr;
+	ocfs2_group_desc *gd;
+	uint32_t cluster_chunk;
+	uint32_t num_new_clusters, save_new_clusters;
+	uint32_t first_new_cluster;
+	uint16_t chain;
+	uint32_t used_bits;
+	uint32_t total_bits;
+	uint32_t num_bits;
+
+	ret = ocfs2_malloc_block(fs->fs_io, &in_buf);
+	if (ret)
+		goto bail;
+
+	ret = ocfs2_malloc_block(fs->fs_io, &gd_buf);
+	if (ret)
+		goto bail;
+
+	/* read global bitmap */
+	ret = ocfs2_lookup_system_inode(fs, GLOBAL_BITMAP_SYSTEM_INODE, 0,
+					&bm_blkno);
+	if (ret)
+		goto bail;
+
+	ret = ocfs2_read_inode(fs, bm_blkno, in_buf);
+	if (ret)
+		goto bail;
+
+	di = (ocfs2_dinode *)in_buf;
+	cl = &(di->id2.i_chain);
+
+	total_bits = di->id1.bitmap1.i_total;
+	used_bits = di->id1.bitmap1.i_used;
+
+	first_new_cluster = di->i_clusters;
+	save_new_clusters = num_new_clusters =
+	       	ocfs2_blocks_to_clusters(fs, opts.num_blocks) - di->i_clusters;
+
+	/* Find the blknum of the last cluster group */
+	gd_blkno = ocfs2_which_cluster_group(fs, cl->cl_cpg, first_new_cluster - 1);
+
+	ret = ocfs2_read_group_desc(fs, gd_blkno, gd_buf);
+	if (ret)
+		goto bail;
+
+	gd = (ocfs2_group_desc *)gd_buf;
+
+	/* If only one cluster group then see if we need to adjust up cl_cpg */
+	if (cl->cl_next_free_rec == 1) {
+		if (cl->cl_cpg < 8 * gd->bg_size)
+			cl->cl_cpg = 8 * gd->bg_size;
+	}
+
+	chain = gd->bg_chain;
+
+	/* If possible round off the last group to cpg */
+	cluster_chunk = MIN(num_new_clusters,
+			    (cl->cl_cpg - (gd->bg_bits/cl->cl_bpc)));
+	if (cluster_chunk) {
+		num_new_clusters -= cluster_chunk;
+		first_new_cluster += cluster_chunk;
+
+		num_bits = cluster_chunk * cl->cl_bpc;
+
+		gd->bg_bits += num_bits;
+		gd->bg_free_bits_count += num_bits;
+
+		cr = &(cl->cl_recs[chain]);
+		cr->c_total += num_bits;
+		cr->c_free += num_bits;
+
+		total_bits += num_bits;
+
+		fs->fs_clusters += cluster_chunk;
+		fs->fs_blocks += ocfs2_clusters_to_blocks(fs, cluster_chunk);
+
+		ret = ocfs2_write_group_desc(fs, gd_blkno, (char *)gd);
+		if (ret)
+			goto bail;
+	}
+
+#define NEXT_CHAIN(_cl, _cur)	\
+			(((_cur) + 1) >= (_cl)->cl_count ? 0 : ((_cur) + 1))
+
+	/* Init the new groups and write to disk */
+	/* Add these groups one by one starting from the first chain after */
+	/* the one containing the last group */
+
+	while(num_new_clusters) {
+		gd_blkno = ocfs2_which_cluster_group(fs, cl->cl_cpg, first_new_cluster);
+		cluster_chunk = MIN(num_new_clusters, cl->cl_cpg);
+		num_new_clusters -= cluster_chunk;
+		first_new_cluster += cluster_chunk;
+		chain = NEXT_CHAIN(cl, chain);
+
+		ocfs2_init_group_desc(fs, gd, gd_blkno,
+			fs->fs_super->i_fs_generation, di->i_blkno,
+			(cluster_chunk *cl->cl_bpc), chain);
+
+		/* Add group to chain */
+		cr = &(cl->cl_recs[chain]);
+		if (chain >= cl->cl_next_free_rec) {
+			cl->cl_next_free_rec++;
+			cr->c_free = cr->c_total = cr->c_blkno = 0;
+		}
+
+		gd->bg_next_group = cr->c_blkno;
+		cr->c_blkno = gd_blkno;
+		cr->c_free += gd->bg_free_bits_count;
+		cr->c_total += gd->bg_bits;
+
+		used_bits += (gd->bg_bits - gd->bg_free_bits_count);
+		total_bits += gd->bg_bits;
+
+		fs->fs_clusters += cluster_chunk;
+		fs->fs_blocks += ocfs2_clusters_to_blocks(fs, cluster_chunk);
+
+		ret = ocfs2_write_group_desc(fs, gd_blkno, gd_buf);
+		if (ret)
+			goto bail;
+	}
+
+	di->id1.bitmap1.i_total = total_bits;
+	di->id1.bitmap1.i_used = used_bits;
+
+	di->i_clusters += save_new_clusters;
+	di->i_size = (uint64_t) di->i_clusters * fs->fs_clustersize;
+
+	fs->fs_super->i_clusters = di->i_clusters;
+
+	ret = ocfs2_write_inode(fs, bm_blkno, in_buf);
+	if (ret)
+		goto bail;
+
+	*changed = 1;
+
+bail:
+	if (in_buf)
+		ocfs2_free(&in_buf);
+	if (gd_buf)
+		ocfs2_free(&gd_buf);
+
+	return ret;
 }
 
 int main(int argc, char **argv)
@@ -642,11 +853,10 @@
 	int upd_label = 0;
 	int upd_slots = 0;
 	int upd_jrnls = 0;
-	int upd_vsize = 0;
+	int upd_blocks = 0;
 	uint16_t tmp;
 	uint64_t def_jrnl_size = 0;
 	uint64_t num_clusters;
-	uint64_t vol_size = 0;
 	int dirty = 0;
 
 	initialize_ocfs_error_table();
@@ -683,6 +893,9 @@
 	}
 	fs_gbl = fs;
 
+	if (resize)
+		get_vol_size(fs);
+
 	ret = ocfs2_initialize_dlm(fs);
 	if (ret) {
 		com_err(opts.progname, ret, " ");
@@ -717,8 +930,8 @@
 			printf("Changing number of node slots from %d to %d\n",
 			       tmp, opts.num_slots);
 		} else {
-			printf("ERROR: Node slots (%d) has to be larger than "
-			       "configured node slots (%d)\n", 
+			fprintf(stderr, "Node slots (%d) has to be larger than "
+				"configured node slots (%d)\n", 
 			       opts.num_slots, tmp);
 			goto unlock;
 		}
@@ -740,25 +953,28 @@
 			       def_jrnl_size, opts.jrnl_size);
 		else {
 			if (!opts.num_slots) {
-				printf("ERROR: Journal size %"PRIu64" has to be larger "
-				       "than %"PRIu64"\n", opts.jrnl_size, def_jrnl_size);
+				fprintf(stderr, "Journal size %"PRIu64" has to "
+					"be larger " "than %"PRIu64"\n",
+					opts.jrnl_size, def_jrnl_size);
 				goto unlock;
 			}
 		}
 	}
 
 	/* validate volume size */
-	if (opts.vol_size) {
-		num_clusters = (opts.vol_size + fs->fs_clustersize - 1) >>
-				OCFS2_RAW_SB(fs->fs_super)->s_clustersize_bits;
-		opts.vol_size = num_clusters <<
-				OCFS2_RAW_SB(fs->fs_super)->s_clustersize_bits;
+	if (opts.num_blocks) {
+		if (validate_vol_size(fs))
+			opts.num_blocks = 0;
+		else
+			printf("Changing volume size %"PRIu64" blocks to "
+			       "%"PRIu64" blocks\n", fs->fs_blocks,
+			       opts.num_blocks);
+	}
 
-		vol_size = fs->fs_clusters <<
-			OCFS2_RAW_SB(fs->fs_super)->s_clustersize_bits;
-
-		printf("Changing volume size %"PRIu64" to %"PRIu64"\n",
-		       vol_size, opts.vol_size);
+	if (!opts.vol_label && !opts.num_slots &&
+	    !opts.jrnl_size && !opts.num_blocks) {
+		fprintf(stderr, "Nothing to do. Exiting.\n");
+		goto unlock;
 	}
 
 	/* Abort? */
@@ -802,18 +1018,19 @@
 	}
 
 	/* update volume size */
-	if (opts.vol_size) {
-		ret = update_volume_size(fs, &upd_vsize);
+	if (opts.num_blocks) {
+		ret = update_volume_size(fs, &upd_blocks);
 		if (ret) {
-			com_err(opts.progname, ret, "while updating volume size");
+			com_err(opts.progname, ret,
+				"while updating volume size");
 			goto unlock;
 		}
-		if (upd_vsize)
+		if (upd_blocks)
 			printf("Resized volume\n");
 	}
 
 	/* write superblock */
-	if (upd_label || upd_slots || upd_vsize) {
+	if (upd_label || upd_slots || upd_blocks) {
 		block_signals(SIG_BLOCK);
 		ret = ocfs2_write_super(fs);
 		if (ret) {



More information about the Ocfs2-tools-commits mailing list