Author: trasz
Date: Sat Jun 23 19:15:12 2012
New Revision: 237501
URL: http://svn.freebsd.org/changeset/base/237501

Log:
  MFC r234846:
  
  Improve growfs(8) in a few ways; unfortunately, it's somewhat hard to untangle
  them and commit separately.
  
  1. Rewrite the way growfs(8) finds the device and mount point.  This makes
     it possible to use e.g. "growfs /mnt"; it's also used to display more
     helpful messages.
  
  2. Be more user-friendly, using descriptive messages, like this:
  
     OK to grow filesystem on /dev/md0, mounted on /mnt, from 9.8GB to 20GB? 
[Yes/No]"
  
  3. Allow to specify the size (-s option) just like with mdconfig(8), i.e. with
     postfixes ("mdconfig -s 10g").4. Reload read-only filesystem after growing.
  
  Reviewed by:    kib, mckusick (earlier version)
  Sponsored by:   The FreeBSD Foundation
  
  MFC r235079:
  
  Fix offset calculation to actually rewrite the _last_ block.

Modified:
  stable/9/sbin/growfs/Makefile
  stable/9/sbin/growfs/growfs.8
  stable/9/sbin/growfs/growfs.c
Directory Properties:
  stable/9/sbin/growfs/   (props changed)

Modified: stable/9/sbin/growfs/Makefile
==============================================================================
--- stable/9/sbin/growfs/Makefile       Sat Jun 23 19:08:24 2012        
(r237500)
+++ stable/9/sbin/growfs/Makefile       Sat Jun 23 19:15:12 2012        
(r237501)
@@ -6,12 +6,18 @@
 
 #GFSDBG=
 
+.PATH: ${.CURDIR}/../mount
+
 PROG=   growfs
-SRCS=   growfs.c
+SRCS=   growfs.c getmntopts.c
 MAN=   growfs.8
+CFLAGS+=-I${.CURDIR}/../mount
 
 .if defined(GFSDBG)
 SRCS+=  debug.c
 .endif  
 
+DPADD= ${LIBUTIL}
+LDADD= -lutil
+
 .include <bsd.prog.mk>      

Modified: stable/9/sbin/growfs/growfs.8
==============================================================================
--- stable/9/sbin/growfs/growfs.8       Sat Jun 23 19:08:24 2012        
(r237500)
+++ stable/9/sbin/growfs/growfs.8       Sat Jun 23 19:15:12 2012        
(r237501)
@@ -37,7 +37,7 @@
 .\" $TSHeader: src/sbin/growfs/growfs.8,v 1.3 2000/12/12 19:31:00 tomsoft Exp $
 .\" $FreeBSD$
 .\"
-.Dd June 29, 2011
+.Dd April 30, 2012
 .Dt GROWFS 8
 .Os
 .Sh NAME
@@ -47,41 +47,20 @@
 .Nm
 .Op Fl Ny
 .Op Fl s Ar size
-.Ar special
+.Ar special | filesystem
 .Sh DESCRIPTION
 The
 .Nm
-utility extends the
-.Xr newfs 8
-program.
-Before starting
-.Nm
-the disk must be labeled to a bigger size using
-.Xr bsdlabel 8 .
-If you wish to grow a file system beyond the boundary of
-the slice it resides in, you must re-size the slice using
-.Xr gpart 8
-before running
-.Nm .
+utility makes it possible to expand an UFS file system.
+Before running
+.Nm
+the partition or slice containing the file system must be extended using
+.Xr gpart 8 .
 If you are using volumes you must enlarge them by using
 .Xr gvinum 8 .
 The
 .Nm
 utility extends the size of the file system on the specified special file.
-Currently
-.Nm
-can only enlarge unmounted file systems.
-Do not try enlarging a mounted file system, your system may panic and you will
-not be able to use the file system any longer.
-Most of the
-.Xr newfs 8
-options cannot be changed by
-.Nm .
-In fact, you can only increase the size of the file system.
-Use
-.Xr tunefs 8
-for other changes.
-.Pp
 The following options are available:
 .Bl -tag -width indent
 .It Fl N
@@ -103,6 +82,13 @@ So use this option with great care!
 Determines the
 .Ar size
 of the file system after enlarging in sectors.
+.Ar Size
+is the number of 512 byte sectors unless suffixed with a
+.Cm b , k , m , g ,
+or
+.Cm t
+which
+denotes byte, kilobyte, megabyte, gigabyte and terabyte respectively.
 This value defaults to the size of the raw partition specified in
 .Ar special
 (in other words,
@@ -110,19 +96,18 @@ This value defaults to the size of the r
 will enlarge the file system to the size of the entire partition).
 .El
 .Sh EXAMPLES
-.Dl growfs -s 4194304 /dev/vinum/testvol
+.Dl growfs -s 2G /dev/ada0p1
 .Pp
 will enlarge
-.Pa /dev/vinum/testvol
+.Pa /dev/ada0p1
 up to 2GB if there is enough space in
-.Pa /dev/vinum/testvol .
+.Pa /dev/ada0p1 .
 .Sh SEE ALSO
-.Xr bsdlabel 8 ,
 .Xr dumpfs 8 ,
 .Xr ffsinfo 8 ,
 .Xr fsck 8 ,
+.Xr fsdb 8 ,
 .Xr gpart 8 ,
-.Xr gvinum 8 ,
 .Xr newfs 8 ,
 .Xr tunefs 8
 .Sh HISTORY
@@ -134,61 +119,12 @@ utility first appeared in
 .An Christoph Herrmann Aq c...@freebsd.org
 .An Thomas-Henning von Kamptz Aq toms...@freebsd.org
 .An The GROWFS team Aq gro...@tomsoft.com
+.An Edward Tomasz Napierala Aq tr...@freebsd.org
 .Sh BUGS
-The
-.Nm
-utility works starting with
-.Fx
-3.x.
-There may be cases on
-.Fx
-3.x only, when
-.Nm
-does not recognize properly whether or not the file system is mounted and
-exits with an error message.
-Then please use
-.Nm
-.Fl y
-if you are sure that the file system is not mounted.
-It is also recommended to always use
-.Xr fsck 8
-after enlarging (just to be on the safe side).
-.Pp
-For enlarging beyond certain limits, it is essential to have some free blocks
-available in the first cylinder group.
-If that space is not available in the first cylinder group, a critical data
-structure has to be relocated into one of the new available cylinder groups.
-On
-.Fx
-3.x this will cause problems with
-.Xr fsck 8
-afterwards.
-So
-.Xr fsck 8
-needs to be patched if you want to use
-.Nm
-for
-.Fx
-3.x.
-This patch is already integrated in
-.Fx
-starting with
-.Fx 4.4 .
-To avoid an unexpected relocation of that structure it is possible to use
-.Nm ffsinfo
-.Fl g Ar 0
-.Fl l Ar 4
-on the first cylinder group to verify that
-.Em nbfree
-in the CYLINDER SUMMARY (internal cs) of the CYLINDER GROUP
-.Em cgr0
-has enough blocks.
-As a rule of thumb for default file system parameters one block is needed for
-every 2 GB of total file system size.
 .Pp
 Normally
 .Nm
-writes this critical structure to disk and reads it again later for doing more
+writes cylinder group summary to disk and reads it again later for doing more
 updates.
 This read operation will provide unexpected data when using
 .Fl N .

Modified: stable/9/sbin/growfs/growfs.c
==============================================================================
--- stable/9/sbin/growfs/growfs.c       Sat Jun 23 19:08:24 2012        
(r237500)
+++ stable/9/sbin/growfs/growfs.c       Sat Jun 23 19:15:12 2012        
(r237501)
@@ -1,11 +1,15 @@
 /*
- * Copyright (c) 2000 Christoph Herrmann, Thomas-Henning von Kamptz
  * Copyright (c) 1980, 1989, 1993 The Regents of the University of California.
+ * Copyright (c) 2000 Christoph Herrmann, Thomas-Henning von Kamptz
+ * Copyright (c) 2012 The FreeBSD Foundation
  * All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Christoph Herrmann and Thomas-Henning von Kamptz, Munich and Frankfurt.
  *
+ * Portions of this software were developed by Edward Tomasz Napierala
+ * under sponsorship from the FreeBSD Foundation.
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -53,13 +57,18 @@ __FBSDID("$FreeBSD$");
 #include <sys/ioctl.h>
 #include <sys/stat.h>
 #include <sys/disk.h>
+#include <sys/ucred.h>
+#include <sys/mount.h>
 
 #include <stdio.h>
 #include <paths.h>
 #include <ctype.h>
 #include <err.h>
 #include <fcntl.h>
+#include <fstab.h>
+#include <inttypes.h>
 #include <limits.h>
+#include <mntopts.h>
 #include <stdlib.h>
 #include <stdint.h>
 #include <string.h>
@@ -67,6 +76,7 @@ __FBSDID("$FreeBSD$");
 #include <unistd.h>
 #include <ufs/ufs/dinode.h>
 #include <ufs/ffs/fs.h>
+#include <libutil.h>
 
 #include "debug.h"
 
@@ -109,7 +119,7 @@ static void updjcg(int, time_t, int, int
 static void    updcsloc(time_t, int, int, unsigned int);
 static void    frag_adjust(ufs2_daddr_t, int);
 static void    updclst(int);
-static void    get_dev_size(int, int *);
+static void    mount_reload(const struct statfs *stfs);
 
 /*
  * Here we actually start growing the file system. We basically read the
@@ -177,6 +187,7 @@ growfs(int fsi, int fso, unsigned int Nf
        /*
         * Dump out summary information about file system.
         */
+#ifdef FS_DEBUG
 #define B2MBFACTOR (1 / (1024.0 * 1024.0))
        printf("growfs: %.1fMB (%jd sectors) block size %d, fragment size %d\n",
            (float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR,
@@ -188,6 +199,7 @@ growfs(int fsi, int fso, unsigned int Nf
        if (sblock.fs_flags & FS_DOSOFTDEP)
                printf("\twith soft updates\n");
 #undef B2MBFACTOR
+#endif /* FS_DEBUG */
 
        /*
         * Now build the cylinders group blocks and
@@ -774,7 +786,7 @@ updjcg(int cylno, time_t modtime, int fs
 
 /*
  * Here we update the location of the cylinder summary. We have two possible
- * ways of growing the cylinder summary.
+ * ways of growing the cylinder summary:
  * (1) We can try to grow the summary in the current location, and relocate
  *     possibly used blocks within the current cylinder group.
  * (2) Alternatively we can relocate the whole cylinder summary to the first
@@ -1238,24 +1250,104 @@ charsperline(void)
        return (columns);
 }
 
+static int
+is_dev(const char *name)
+{
+       struct stat devstat;
+
+       if (stat(name, &devstat) != 0)
+               return (0);
+       if (!S_ISCHR(devstat.st_mode))
+               return (0);
+       return (1);
+}
+
 /*
- * Get the size of the partition.
- */
-static void
-get_dev_size(int fd, int *size)
+ * Return mountpoint on which the device is currently mounted.
+ */ 
+static const struct statfs *
+dev_to_statfs(const char *dev)
 {
-       int sectorsize;
-       off_t mediasize;
+       struct stat devstat, mntdevstat;
+       struct statfs *mntbuf, *statfsp;
+       char device[MAXPATHLEN];
+       char *mntdevname;
+       int i, mntsize;
+
+       /*
+        * First check the mounted filesystems.
+        */
+       if (stat(dev, &devstat) != 0)
+               return (NULL);
+       if (!S_ISCHR(devstat.st_mode) && !S_ISBLK(devstat.st_mode))
+               return (NULL);
+
+       mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
+       for (i = 0; i < mntsize; i++) {
+               statfsp = &mntbuf[i];
+               mntdevname = statfsp->f_mntfromname;
+               if (*mntdevname != '/') {
+                       strcpy(device, _PATH_DEV);
+                       strcat(device, mntdevname);
+                       mntdevname = device;
+               }
+               if (stat(mntdevname, &mntdevstat) == 0 &&
+                   mntdevstat.st_rdev == devstat.st_rdev)
+                       return (statfsp);
+       }
 
-       if (ioctl(fd, DIOCGSECTORSIZE, &sectorsize) == -1)
-               err(1,"DIOCGSECTORSIZE");
-       if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) == -1)
-               err(1,"DIOCGMEDIASIZE");
+       return (NULL);
+}
 
-       if (sectorsize <= 0)
-               errx(1, "bogus sectorsize: %d", sectorsize);
+static const char *
+mountpoint_to_dev(const char *mountpoint)
+{
+       struct statfs *mntbuf, *statfsp;
+       struct fstab *fs;
+       int i, mntsize;
 
-       *size = mediasize / sectorsize;
+       /*
+        * First check the mounted filesystems.
+        */
+       mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
+       for (i = 0; i < mntsize; i++) {
+               statfsp = &mntbuf[i];
+
+               if (strcmp(statfsp->f_mntonname, mountpoint) == 0)
+                       return (statfsp->f_mntfromname);
+       }
+
+       /*
+        * Check the fstab.
+        */
+       fs = getfsfile(mountpoint);
+       if (fs != NULL)
+               return (fs->fs_spec);
+
+       return (NULL);
+}
+
+static const char *
+getdev(const char *name)
+{
+       static char device[MAXPATHLEN];
+       const char *cp, *dev;
+
+       if (is_dev(name))
+               return (name);
+
+       cp = strrchr(name, '/');
+       if (cp == 0) {
+               snprintf(device, sizeof(device), "%s%s", _PATH_DEV, name);
+               if (is_dev(device))
+                       return (device);
+       }
+
+       dev = mountpoint_to_dev(name);
+       if (dev != NULL && is_dev(dev))
+               return (dev);
+
+       return (NULL);
 }
 
 /*
@@ -1283,17 +1375,13 @@ int
 main(int argc, char **argv)
 {
        DBG_FUNC("main")
-       char *device, *special;
-       int ch;
-       unsigned int size = 0;
-       size_t len;
-       unsigned int Nflag = 0;
-       int ExpertFlag = 0;
-       struct stat st;
-       int i, fsi, fso;
-       u_int32_t p_size;
-       char reply[5];
-       int j;
+       const char *device;
+       const struct statfs *statfsp;
+       uint64_t size = 0;
+       off_t mediasize;
+       int error, i, j, fsi, fso, ch, Nflag = 0, yflag = 0;
+       char *p, reply[5], oldsizebuf[6], newsizebuf[6];
+       void *testbuf;
 
        DBG_ENTER;
 
@@ -1303,14 +1391,27 @@ main(int argc, char **argv)
                        Nflag = 1;
                        break;
                case 's':
-                       size = (size_t)atol(optarg);
-                       if (size < 1)
-                               usage();
+                       size = (off_t)strtoumax(optarg, &p, 0);
+                       if (p == NULL || *p == '\0')
+                               size *= DEV_BSIZE;
+                       else if (*p == 'b' || *p == 'B')
+                               ; /* do nothing */
+                       else if (*p == 'k' || *p == 'K')
+                               size <<= 10;
+                       else if (*p == 'm' || *p == 'M')
+                               size <<= 20;
+                       else if (*p == 'g' || *p == 'G')
+                               size <<= 30;
+                       else if (*p == 't' || *p == 'T') {
+                               size <<= 30;
+                               size <<= 10;
+                       } else
+                               errx(1, "unknown suffix on -s argument");
                        break;
                case 'v': /* for compatibility to newfs */
                        break;
                case 'y':
-                       ExpertFlag = 1;
+                       yflag = 1;
                        break;
                case '?':
                        /* FALLTHROUGH */
@@ -1324,71 +1425,29 @@ main(int argc, char **argv)
        if (argc != 1)
                usage();
 
-       device = *argv;
-
        /*
-        * Now try to guess the (raw)device name.
+        * Now try to guess the device name.
         */
-       if (0 == strrchr(device, '/')) {
-               /*
-                * No path prefix was given, so try in that order:
-                *     /dev/r%s
-                *     /dev/%s
-                *     /dev/vinum/r%s
-                *     /dev/vinum/%s.
-                *
-                * FreeBSD now doesn't distinguish between raw and block
-                * devices any longer, but it should still work this way.
-                */
-               len = strlen(device) + strlen(_PATH_DEV) + 2 + strlen("vinum/");
-               special = (char *)malloc(len);
-               if (special == NULL)
-                       errx(1, "malloc failed");
-               snprintf(special, len, "%sr%s", _PATH_DEV, device);
-               if (stat(special, &st) == -1) {
-                       snprintf(special, len, "%s%s", _PATH_DEV, device);
-                       if (stat(special, &st) == -1) {
-                               snprintf(special, len, "%svinum/r%s",
-                                   _PATH_DEV, device);
-                               if (stat(special, &st) == -1) {
-                                       /* For now this is the 'last resort' */
-                                       snprintf(special, len, "%svinum/%s",
-                                           _PATH_DEV, device);
-                               }
-                       }
-               }
-               device = special;
-       }
+       device = getdev(*argv);
+       if (device == NULL)
+               errx(1, "cannot find special device for %s", *argv);
 
-       /*
-        * Try to access our devices for writing ...
-        */
-       if (Nflag) {
-               fso = -1;
-       } else {
-               fso = open(device, O_WRONLY);
-               if (fso < 0)
-                       err(1, "%s", device);
-       }
+       statfsp = dev_to_statfs(device);
 
-       /*
-        * ... and reading.
-        */
        fsi = open(device, O_RDONLY);
        if (fsi < 0)
                err(1, "%s", device);
 
        /*
-        * Try to guess the slice if not specified. This code should guess
-        * the right thing and avoid to bother the user with the task
-        * of specifying the option -v on vinum volumes.
+        * Try to guess the slice size if not specified.
         */
-       get_dev_size(fsi, &p_size);
+       if (ioctl(fsi, DIOCGMEDIASIZE, &mediasize) == -1)
+               err(1,"DIOCGMEDIASIZE");
 
        /*
         * Check if that partition is suitable for growing a file system.
         */
-       if (p_size < 1)
+       if (mediasize < 1)
                errx(1, "partition is unavailable");
 
        /*
@@ -1414,16 +1473,36 @@ main(int argc, char **argv)
        /*
         * Determine size to grow to. Default to the device size.
         */
-       sblock.fs_size = dbtofsb(&osblock, p_size);
-       if (size != 0) {
-               if (size > p_size)
-                       errx(1, "there is not enough space (%d < %d)",
-                           p_size, size);
-               sblock.fs_size = dbtofsb(&osblock, size);
+       if (size == 0)
+               size = mediasize;
+       else {
+               if (size > (uint64_t)mediasize) {
+                       humanize_number(oldsizebuf, sizeof(oldsizebuf), size,
+                           "B", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
+                       humanize_number(newsizebuf, sizeof(newsizebuf),
+                           mediasize,
+                           "B", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
+
+                       errx(1, "requested size %s is larger "
+                           "than the available %s", oldsizebuf, newsizebuf);
+               }
+       }
+
+       if (size <= (uint64_t)(osblock.fs_size * osblock.fs_fsize)) {
+               humanize_number(oldsizebuf, sizeof(oldsizebuf),
+                   osblock.fs_size * osblock.fs_fsize,
+                   "B", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
+               humanize_number(newsizebuf, sizeof(newsizebuf), size,
+                   "B", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
+
+               errx(1, "requested size %s is not larger than the current "
+                  "filesystem size %s", newsizebuf, oldsizebuf);
        }
 
+       sblock.fs_size = dbtofsb(&osblock, size / DEV_BSIZE);
+
        /*
-        * Are we really growing ?
+        * Are we really growing?
         */
        if (osblock.fs_size >= sblock.fs_size) {
                errx(1, "we are not growing (%jd->%jd)",
@@ -1433,7 +1512,7 @@ main(int argc, char **argv)
        /*
         * Check if we find an active snapshot.
         */
-       if (ExpertFlag == 0) {
+       if (yflag == 0) {
                for (j = 0; j < FSMAXSNAP; j++) {
                        if (sblock.fs_snapinum[j]) {
                                errx(1, "active snapshot found in file system; "
@@ -1445,10 +1524,23 @@ main(int argc, char **argv)
                }
        }
 
-       if (ExpertFlag == 0 && Nflag == 0) {
-               printf("We strongly recommend you to make a backup "
+       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("It's strongly recommended to make a backup "
                    "before growing the file system.\n"
-                   "Did you backup your data (Yes/No)? ");
+                   "OK to grow filesystem on %s", device);
+               if (statfsp != NULL)
+                       printf(", mounted on %s,", statfsp->f_mntonname);
+               humanize_number(oldsizebuf, sizeof(oldsizebuf),
+                   osblock.fs_size * osblock.fs_fsize,
+                   "B", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
+               humanize_number(newsizebuf, sizeof(newsizebuf),
+                   sblock.fs_size * sblock.fs_fsize,
+                   "B", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
+               printf(" from %s to %s? [Yes/No] ", oldsizebuf, newsizebuf);
+               fflush(stdout);
                fgets(reply, (int)sizeof(reply), stdin);
                if (strcmp(reply, "Yes\n")){
                        printf("\nNothing done\n");
@@ -1456,15 +1548,30 @@ main(int argc, char **argv)
                }
        }
 
-       printf("New file system size is %jd frags\n", (intmax_t)sblock.fs_size);
+       /*
+        * Try to access our device for writing.  If it's not mounted,
+        * or mounted read-only, simply open it; otherwise, use UFS
+        * suspension mechanism.
+        */
+       if (Nflag) {
+               fso = -1;
+       } else {
+               fso = open(device, O_WRONLY);
+               if (fso < 0)
+                       err(1, "%s", device);
+       }
 
        /*
-        * Try to access our new last block in the file system. Even if we
-        * later on realize we have to abort our operation, on that block
-        * there should be no data, so we can't destroy something yet.
+        * Try to access our new last block in the file system.
         */
-       wtfs((ufs2_daddr_t)p_size - 1, (size_t)DEV_BSIZE, (void *)&sblock,
-           fso, Nflag);
+       testbuf = malloc(sblock.fs_fsize);
+       if (testbuf == NULL)
+               err(1, "malloc");
+       rdfs((ufs2_daddr_t)((size - sblock.fs_fsize) / DEV_BSIZE),
+           sblock.fs_fsize, testbuf, fsi);
+       wtfs((ufs2_daddr_t)((size - sblock.fs_fsize) / DEV_BSIZE),
+           sblock.fs_fsize, testbuf, fso, Nflag);
+       free(testbuf);
 
        /*
         * Now calculate new superblock values and check for reasonable
@@ -1520,8 +1627,13 @@ main(int argc, char **argv)
        growfs(fsi, fso, Nflag);
 
        close(fsi);
-       if (fso > -1)
-               close(fso);
+       if (fso > -1) {
+               error = close(fso);
+               if (error != 0)
+                       err(1, "close");
+       }
+       if (statfsp != NULL)
+               mount_reload(statfsp);
 
        DBG_CLOSE;
 
@@ -1539,7 +1651,7 @@ usage(void)
 
        DBG_ENTER;
 
-       fprintf(stderr, "usage: growfs [-Ny] [-s size] special\n");
+       fprintf(stderr, "usage: growfs [-Ny] [-s size] special | filesystem\n");
 
        DBG_LEAVE;
        exit(1);
@@ -1586,3 +1698,26 @@ updclst(int block)
        DBG_LEAVE;
        return;
 }
+
+static void
+mount_reload(const struct statfs *stfs)
+{
+       char errmsg[255];
+       struct iovec *iov;
+       int iovlen;
+
+       iov = NULL;
+       iovlen = 0;
+       *errmsg = '\0';
+       build_iovec(&iov, &iovlen, "fstype", __DECONST(char *, "ffs"), 4);
+       build_iovec(&iov, &iovlen, "fspath", __DECONST(char *, 
stfs->f_mntonname), (size_t)-1);
+       build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg));
+       build_iovec(&iov, &iovlen, "update", NULL, 0);
+       build_iovec(&iov, &iovlen, "reload", NULL, 0);
+
+       if (nmount(iov, iovlen, stfs->f_flags) < 0) {
+               errmsg[sizeof(errmsg) - 1] = '\0';
+               err(9, "%s: cannot reload filesystem%s%s", stfs->f_mntonname,
+                   *errmsg != '\0' ? ": " : "", errmsg);
+       }
+}
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to