Create a .snap directory mode 770 group operator in the root of each

filesystem that is checked in background. Create the snapshot in this
directory rather than in the root. There are two benefits:

1) For terabyte-sized filesystems, the snapshot may require many
   minutes to build. Although the filesystem will not be suspended
   during most of the snapshot build, the snapshot file itself is
   locked during the entire snapshot build period. Thus, if it is
   accessed during the period that it is being built, the process
   trying to access it will block holding its containing directory
   locked. If the snapshot is in the root, the root will lock and
   the system will come to a halt until the snapshot finishes. By
   putting the snapshot in a subdirectory, it is out of the likely
   path of any process traversing through the root and hence much
   less likely to cause a lock race to the root.

2) The dump program is usually run by a non-root user running with
   operator group privilege. Such a user is typically not permitted
   to create files in the root of a filesystem. By having a directory
   in group operator with group write access available, such a user
   will be able to create a snapshot there. Having the dump program
   create its snapshot in a subdirectory below the root will benefit
   from point (1) as well.

Sponsored by:   DARPA & NAI Labs.
This commit is contained in:
Kirk McKusick 2003-10-08 02:14:03 +00:00
parent 146143aa36
commit ff76fc7f16

View File

@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$");
#include <err.h>
#include <errno.h>
#include <fstab.h>
#include <grp.h>
#include <paths.h>
#include <stdint.h>
#include <string.h>
@ -189,6 +190,8 @@ checkfilesys(char *filesys)
struct dups *dp;
struct statfs *mntp;
struct zlncnt *zlnp;
struct stat snapdir;
struct group *grp;
ufs2_daddr_t blks;
int cylno, ret;
ino_t files;
@ -269,8 +272,34 @@ checkfilesys(char *filesys)
close(fsreadfd);
}
if (bkgrdflag) {
snprintf(snapname, sizeof snapname, "%s/.fsck_snapshot",
snprintf(snapname, sizeof snapname, "%s/.snap",
mntp->f_mntonname);
if (stat(snapname, &snapdir) < 0) {
if (errno != ENOENT) {
bkgrdflag = 0;
pfatal("CANNOT FIND %s %s: %s, %s\n",
"SNAPSHOT DIRECTORY",
snapname, strerror(errno),
"CANNOT RUN IN BACKGROUND");
} else if ((grp = getgrnam("operator")) == 0 ||
mkdir(snapname, 0770) < 0 ||
chown(snapname, -1, grp->gr_gid) < 0 ||
chmod(snapname, 0770) < 0) {
bkgrdflag = 0;
pfatal("CANNOT CREATE %s %s: %s, %s\n",
"SNAPSHOT DIRECTORY",
snapname, strerror(errno),
"CANNOT RUN IN BACKGROUND");
}
} else if (!S_ISDIR(snapdir.st_mode)) {
bkgrdflag = 0;
pfatal("%s IS NOT A DIRECTORY, %s\n", snapname,
"CANNOT RUN IN BACKGROUND");
}
}
if (bkgrdflag) {
snprintf(snapname, sizeof snapname,
"%s/.snap/fsck_snapshot", mntp->f_mntonname);
args.fspec = snapname;
while (mount("ffs", mntp->f_mntonname,
mntp->f_flags | MNT_UPDATE | MNT_SNAPSHOT,