- Move from mount(2) to nmount(2). This should allow to convert MNT_SNAPSHOT

flag from a mount flag to FS-specific flag.
- Simplify usage. Instead of 'mksnap_ffs /mnt/foo /mnt/foo/snap' allow to
  give only one argument: 'mksnap_ffs /mnt/foo/snap'. Old usage is also
  accepted for now.
- Add an example of how to mount a snapshot.
This commit is contained in:
Pawel Jakub Dawidek 2009-05-29 19:18:41 +00:00
parent b89fed6747
commit c8cf3f3d0e
3 changed files with 54 additions and 40 deletions

View File

@ -1,8 +1,13 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../mount
PROG= mksnap_ffs
SRCS= mksnap_ffs.c getmntopts.c
MAN= mksnap_ffs.8
CFLAGS+=-I${.CURDIR}/../mount
.if defined(NOSUID)
BINMODE=550
.else

View File

@ -34,7 +34,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd January 19, 2003
.Dd May 29, 2009
.Dt MKSNAP_FFS 8
.Os
.Sh NAME
@ -42,19 +42,12 @@
.Nd take a file system snapshot
.Sh SYNOPSIS
.Nm
.Ar mountpoint
.Ar snapshot_name
.Sh DESCRIPTION
The
.Nm
utility creates a snapshot named
.Ar snapshot_name
on the file system mounted at
.Ar mountpoint .
The
.Ar snapshot_name
argument must be contained within the file system mounted at
.Ar mountpoint .
.Ar snapshot_name .
.Pp
The group ownership of the file is set to
.Dq Li operator ;
@ -64,9 +57,19 @@ The mode of the snapshot is set to be readable by the owner
or members of the
.Dq Li operator
group.
.Sh EXAMPLES
Create a snapshot of
.Pa /usr/home
file system and mount the snapshot elsewhere:
.Bd -literal -offset indent
mksnap_ffs /usr/home/snapshot
mdconfig -a -t vnode -o readonly -f /usr/home/snapshot
mount -o ro /dev/md0 /mnt/
.Ed
.Sh SEE ALSO
.Xr chmod 2 ,
.Xr chown 8 ,
.Xr mdconfig 8,
.Xr mount 8
.Sh CAVEATS
The disk full situation is not handled gracefully and may

View File

@ -44,31 +44,38 @@
#include <fcntl.h>
#include <grp.h>
#include <limits.h>
#include <mntopts.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include <unistd.h>
void usage(void);
static void
usage(void)
{
errx(EX_USAGE, "usage: mksnap_ffs snapshot_name");
}
int
main(int argc, char **argv)
{
char *dir, *cp, path[PATH_MAX];
char errmsg[255], path[PATH_MAX];
char *cp, *snapname;
struct statfs stfsbuf;
struct ufs_args args;
struct group *grp;
struct stat stbuf;
int fd;
struct iovec *iov;
int fd, iovlen;
if (argc != 3)
if (argc == 2)
snapname = argv[1];
else if (argc == 3)
snapname = argv[2]; /* Old usage. */
else
usage();
dir = argv[1];
memset(&args, 0, sizeof args);
args.fspec = argv[2];
/*
* Check that the user running this program has permission
* to create and remove a snapshot file from the directory
@ -77,15 +84,15 @@ main(int argc, char **argv)
* will not be able to remove the snapshot when they are
* done with it.
*/
if (strlen(args.fspec) >= PATH_MAX)
errx(1, "pathname too long %s", args.fspec);
cp = strrchr(args.fspec, '/');
if (strlen(snapname) >= PATH_MAX)
errx(1, "pathname too long %s", snapname);
cp = strrchr(snapname, '/');
if (cp == NULL) {
strlcpy(path, ".", PATH_MAX);
} else if (cp == args.fspec) {
} else if (cp == snapname) {
strlcpy(path, "/", PATH_MAX);
} else {
strlcpy(path, args.fspec, cp - args.fspec + 1);
strlcpy(path, snapname, cp - snapname + 1);
}
if (statfs(path, &stfsbuf) < 0)
err(1, "%s", path);
@ -104,27 +111,26 @@ main(int argc, char **argv)
*/
if ((grp = getgrnam("operator")) == NULL)
errx(1, "Cannot retrieve operator gid");
if (mount("ufs", dir, MNT_UPDATE | MNT_SNAPSHOT | stfsbuf.f_flags,
&args) < 0)
err(1, "Cannot create %s", args.fspec);
if ((fd = open(args.fspec, O_RDONLY)) < 0)
err(1, "Cannot open %s", args.fspec);
build_iovec(&iov, &iovlen, "fstype", "ffs", 4);
build_iovec(&iov, &iovlen, "from", snapname, (size_t)-1);
build_iovec(&iov, &iovlen, "fspath", stfsbuf.f_mntonname, (size_t)-1);
build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg));
build_iovec(&iov, &iovlen, "update", NULL, 0);
build_iovec(&iov, &iovlen, "snapshot", NULL, 0);
if (nmount(iov, iovlen, stfsbuf.f_flags) < 0)
err(1, "Cannot create snapshot %s: %s", snapname, errmsg);
if ((fd = open(snapname, O_RDONLY)) < 0)
err(1, "Cannot open %s", snapname);
if (fstat(fd, &stbuf) != 0)
err(1, "Cannot stat %s", args.fspec);
err(1, "Cannot stat %s", snapname);
if ((stbuf.st_flags & SF_SNAPSHOT) == 0)
errx(1, "File %s is not a snapshot", args.fspec);
errx(1, "File %s is not a snapshot", snapname);
if (fchown(fd, -1, grp->gr_gid) != 0)
err(1, "Cannot chown %s", args.fspec);
err(1, "Cannot chown %s", snapname);
if (fchmod(fd, S_IRUSR | S_IRGRP) != 0)
err(1, "Cannot chmod %s", args.fspec);
err(1, "Cannot chmod %s", snapname);
exit(EXIT_SUCCESS);
}
void
usage()
{
fprintf(stderr, "usage: mksnap_ffs mountpoint snapshot_name\n");
exit(EX_USAGE);
}