summaryrefslogtreecommitdiffstats
path: root/sbin/growfs
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>2013-02-08 16:10:16 +0000
committerobrien <obrien@FreeBSD.org>2013-02-08 16:10:16 +0000
commit3028e3f8aba938dfd0bf9fda987b8a72140b8027 (patch)
treeb2f038222ff8a70f687652441df00d2b564c8abe /sbin/growfs
parent952a6d5a7cd3d3f9007acfa06805262fc04a105f (diff)
parent1d08d5f677c1dfa810e381073590adbae19cc69f (diff)
downloadFreeBSD-src-3028e3f8aba938dfd0bf9fda987b8a72140b8027.zip
FreeBSD-src-3028e3f8aba938dfd0bf9fda987b8a72140b8027.tar.gz
Sync with HEAD.
Diffstat (limited to 'sbin/growfs')
-rw-r--r--sbin/growfs/growfs.85
-rw-r--r--sbin/growfs/growfs.c53
2 files changed, 44 insertions, 14 deletions
diff --git a/sbin/growfs/growfs.8 b/sbin/growfs/growfs.8
index 92508da..664e723 100644
--- a/sbin/growfs/growfs.8
+++ b/sbin/growfs/growfs.8
@@ -115,11 +115,16 @@ The
.Nm
utility first appeared in
.Fx 4.4 .
+The ability to resize mounted filesystems was added in
+.Fx 10.0 .
.Sh AUTHORS
.An Christoph Herrmann Aq chm@FreeBSD.org
.An Thomas-Henning von Kamptz Aq tomsoft@FreeBSD.org
.An The GROWFS team Aq growfs@Tomsoft.COM
.An Edward Tomasz Napierala Aq trasz@FreeBSD.org
+.Sh CAVEATS
+When expanding a file system mounted read-write, any writes to that file system
+will be temporarily suspended until the expansion is finished.
.Sh BUGS
Normally
.Nm
diff --git a/sbin/growfs/growfs.c b/sbin/growfs/growfs.c
index ad837a8..745e9e9 100644
--- a/sbin/growfs/growfs.c
+++ b/sbin/growfs/growfs.c
@@ -69,6 +69,7 @@ __FBSDID("$FreeBSD$");
#include <inttypes.h>
#include <limits.h>
#include <mntopts.h>
+#include <paths.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
@@ -1486,6 +1487,12 @@ main(int argc, char **argv)
}
}
+ /*
+ * Make sure the new size is a multiple of fs_fsize; /dev/ufssuspend
+ * only supports fragment-aligned IO requests.
+ */
+ size -= size % osblock.fs_fsize;
+
if (size <= (uint64_t)(osblock.fs_size * osblock.fs_fsize)) {
humanize_number(oldsizebuf, sizeof(oldsizebuf),
osblock.fs_size * osblock.fs_fsize,
@@ -1525,8 +1532,9 @@ main(int argc, char **argv)
if (yflag == 0 && Nflag == 0) {
if (statfsp != NULL && (statfsp->f_flags & MNT_RDONLY) == 0)
- errx(1, "%s is mounted read-write on %s",
- statfsp->f_mntfromname, statfsp->f_mntonname);
+ printf("Device is mounted read-write; resizing will "
+ "result in temporary write suspension for %s.\n",
+ statfsp->f_mntonname);
printf("It's strongly recommended to make a backup "
"before growing the file system.\n"
"OK to grow filesystem on %s", device);
@@ -1555,9 +1563,18 @@ main(int argc, char **argv)
if (Nflag) {
fso = -1;
} else {
- fso = open(device, O_WRONLY);
- if (fso < 0)
- err(1, "%s", device);
+ if (statfsp != NULL && (statfsp->f_flags & MNT_RDONLY) == 0) {
+ fso = open(_PATH_UFSSUSPEND, O_RDWR);
+ if (fso == -1)
+ err(1, "unable to open %s", _PATH_UFSSUSPEND);
+ error = ioctl(fso, UFSSUSPEND, &statfsp->f_fsid);
+ if (error != 0)
+ err(1, "UFSSUSPEND");
+ } else {
+ fso = open(device, O_WRONLY);
+ if (fso < 0)
+ err(1, "%s", device);
+ }
}
/*
@@ -1594,17 +1611,20 @@ main(int argc, char **argv)
}
sblock.fs_ncg = howmany(sblock.fs_size, sblock.fs_fpg);
+ /*
+ * Allocate last cylinder group only if there is enough room
+ * for at least one data block.
+ */
if (sblock.fs_size % sblock.fs_fpg != 0 &&
- sblock.fs_size % sblock.fs_fpg < cgdmin(&sblock, sblock.fs_ncg)) {
- /*
- * The space in the new last cylinder group is too small,
- * so revert back.
- */
+ sblock.fs_size <= cgdmin(&sblock, sblock.fs_ncg - 1)) {
+ humanize_number(oldsizebuf, sizeof(oldsizebuf),
+ (sblock.fs_size % sblock.fs_fpg) * sblock.fs_fsize,
+ "B", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
+ warnx("no room to allocate last cylinder group; "
+ "leaving %s unused", oldsizebuf);
sblock.fs_ncg--;
if (sblock.fs_magic == FS_UFS1_MAGIC)
sblock.fs_old_ncyl = sblock.fs_ncg * sblock.fs_old_cpg;
- printf("Warning: %jd sector(s) cannot be allocated.\n",
- (intmax_t)fsbtodb(&sblock, sblock.fs_size % sblock.fs_fpg));
sblock.fs_size = sblock.fs_ncg * sblock.fs_fpg;
}
@@ -1627,12 +1647,17 @@ main(int argc, char **argv)
close(fsi);
if (fso > -1) {
+ if (statfsp != NULL && (statfsp->f_flags & MNT_RDONLY) == 0) {
+ error = ioctl(fso, UFSRESUME);
+ if (error != 0)
+ err(1, "UFSRESUME");
+ }
error = close(fso);
if (error != 0)
err(1, "close");
+ if (statfsp != NULL && (statfsp->f_flags & MNT_RDONLY) != 0)
+ mount_reload(statfsp);
}
- if (statfsp != NULL)
- mount_reload(statfsp);
DBG_CLOSE;
OpenPOWER on IntegriCloud