bin/51138: [PATCH] re-enable growfs(8) to work on vinum volumes in -CURRENT

Lukas Ertl l.ertl at univie.ac.at
Sat Apr 26 10:45:19 PDT 2003


This is an updated patch that applies to rev. 1.14 of growfs.c.

I'd really appreciate it if someone could take a look at it, because I
think it should go into 5.1.

--- growfs.c.diff begins here ---
Index: sbin/growfs/growfs.c
===================================================================
RCS file: /u/cvs/cvs/src/sbin/growfs/growfs.c,v
retrieving revision 1.14
diff -u -r1.14 growfs.c
--- sbin/growfs/growfs.c	26 Apr 2003 15:22:29 -0000	1.14
+++ sbin/growfs/growfs.c	26 Apr 2003 17:40:30 -0000
@@ -56,6 +56,7 @@
 #include <sys/disklabel.h>
 #include <sys/ioctl.h>
 #include <sys/stat.h>
+#include <sys/disk.h>

 #include <stdio.h>
 #include <paths.h>
@@ -110,6 +111,7 @@
 static ufs2_daddr_t 	inoblk;			/* inode block address */
 static char		inobuf[MAXBSIZE];	/* inode block */
 static int		maxino;			/* last valid inode */
+static int		unlabeled;     /* unlabeled partition, e.g. vinum volume etc. */

 /*
  * An array of elements of type struct gfs_bpp describes all blocks to
@@ -148,6 +150,7 @@
 static void	updrefs(int, ino_t, struct gfs_bpp *, int, int, unsigned int);
 static void	indirchk(ufs_lbn_t, ufs_lbn_t, ufs2_daddr_t, ufs_lbn_t,
 		    struct gfs_bpp *, int, int, unsigned int);
+static void	get_dev_size(int, int *);

 /* ************************************************************ growfs ***** */
 /*
@@ -1880,6 +1883,28 @@
 	return columns;
 }

+/* ****************************************************** get_dev_size ***** */
+/*
+ * Get the size of the partition if we can't figure it out from the disklabel,
+ * e.g. from vinum volumes.
+ */
+static void
+get_dev_size(int fd, int *size)
+{
+   int sectorsize;
+   off_t mediasize;
+
+   if (ioctl(fd, DIOCGSECTORSIZE, &sectorsize) == -1)
+        err(1,"DIOCGSECTORSIZE");
+   if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) == -1)
+        err(1,"DIOCGMEDIASIZE");
+
+   if (sectorsize <= 0)
+       errx(1, "bogus sectorsize: %d", sectorsize);
+
+   *size = mediasize / sectorsize;
+}
+
 /* ************************************************************** main ***** */
 /*
  * growfs(8)  is a utility which allows to increase the size of an existing
@@ -1917,6 +1942,7 @@
 	struct disklabel	*lp;
 	struct partition	*pp;
 	int	i,fsi,fso;
+    u_int32_t p_size;
 	char	reply[5];
 #ifdef FSMAXSNAP
 	int	j;
@@ -2016,25 +2042,30 @@
 	 */
 	cp=device+strlen(device)-1;
 	lp = get_disklabel(fsi);
-	if(lp->d_type == DTYPE_VINUM) {
-		pp = &lp->d_partitions[0];
-	} else if (isdigit(*cp)) {
-		pp = &lp->d_partitions[2];
-	} else if (*cp>='a' && *cp<='h') {
-		pp = &lp->d_partitions[*cp - 'a'];
-	} else {
-		errx(1, "unknown device");
-	}
+    if (lp != NULL) {
+        if (isdigit(*cp)) {
+            pp = &lp->d_partitions[2];
+        } else if (*cp>='a' && *cp<='h') {
+            pp = &lp->d_partitions[*cp - 'a'];
+        } else {
+            errx(1, "unknown device");
+        }
+        p_size = pp->p_size;
+    } else {
+        get_dev_size(fsi, &p_size);
+    }

 	/*
 	 * Check if that partition is suitable for growing a file system.
 	 */
-	if (pp->p_size < 1) {
+	if (p_size < 1) {
 		errx(1, "partition is unavailable");
 	}
+/*
 	if (pp->p_fstype != FS_BSDFFS) {
 		errx(1, "partition not 4.2BSD");
 	}
+*/

 	/*
 	 * Read the current superblock, and take a backup.
@@ -2063,11 +2094,11 @@
 	 * Determine size to grow to. Default to the full size specified in
 	 * the disk label.
 	 */
-	sblock.fs_size = dbtofsb(&osblock, pp->p_size);
+	sblock.fs_size = dbtofsb(&osblock, p_size);
 	if (size != 0) {
-		if (size > pp->p_size){
+		if (size > p_size){
 			errx(1, "There is not enough space (%d < %d)",
-			    pp->p_size, size);
+			    p_size, size);
 		}
 		sblock.fs_size = dbtofsb(&osblock, size);
 	}
@@ -2117,7 +2148,7 @@
 	 * later on realize we have to abort our operation, on that block
 	 * there should be no data, so we can't destroy something yet.
 	 */
-	wtfs((ufs2_daddr_t)pp->p_size-1, (size_t)DEV_BSIZE, (void *)&sblock,
+	wtfs((ufs2_daddr_t)p_size-1, (size_t)DEV_BSIZE, (void *)&sblock,
 	    fso, Nflag);

 	/*
@@ -2178,12 +2209,14 @@
 	/*
 	 * Update the disk label.
 	 */
-	pp->p_fsize = sblock.fs_fsize;
-	pp->p_frag = sblock.fs_frag;
-	pp->p_cpg = sblock.fs_fpg;
-
-	return_disklabel(fso, lp, Nflag);
-	DBG_PRINT0("label rewritten\n");
+    if (!unlabeled) {
+        pp->p_fsize = sblock.fs_fsize;
+        pp->p_frag = sblock.fs_frag;
+        pp->p_cpg = sblock.fs_fpg;
+
+        return_disklabel(fso, lp, Nflag);
+        DBG_PRINT0("label rewritten\n");
+    }

 	close(fsi);
 	if(fso>-1) close(fso);
@@ -2247,15 +2280,16 @@
 	DBG_ENTER;

 	lab=(struct disklabel *)malloc(sizeof(struct disklabel));
-	if (!lab) {
+	if (!lab)
 		errx(1, "malloc failed");
-	}
-	if (ioctl(fd, DIOCGDINFO, (char *)lab) < 0) {
-		errx(1, "DIOCGDINFO failed");
-	}
+
+    if (!ioctl(fd, DIOCGDINFO, (char *)lab))
+        return (lab);
+
+    unlabeled++;

 	DBG_LEAVE;
-	return (lab);
+	return (NULL);
 }


--- growfs.c.diff ends here ---

-- 
Lukas Ertl                             eMail: l.ertl at univie.ac.at
UNIX-Systemadministrator               Tel.:  (+43 1) 4277-14073
Zentraler Informatikdienst (ZID)       Fax.:  (+43 1) 4277-9140
der Universität Wien                   http://mailbox.univie.ac.at/~le/


More information about the freebsd-bugs mailing list