1 1.39 christos /* $NetBSD: mount_lfs.c,v 1.39 2016/02/21 22:51:29 christos Exp $ */ 2 1.2 cgd 3 1.1 mycroft /*- 4 1.1 mycroft * Copyright (c) 1993, 1994 5 1.1 mycroft * The Regents of the University of California. All rights reserved. 6 1.1 mycroft * 7 1.1 mycroft * Redistribution and use in source and binary forms, with or without 8 1.1 mycroft * modification, are permitted provided that the following conditions 9 1.1 mycroft * are met: 10 1.1 mycroft * 1. Redistributions of source code must retain the above copyright 11 1.1 mycroft * notice, this list of conditions and the following disclaimer. 12 1.1 mycroft * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 mycroft * notice, this list of conditions and the following disclaimer in the 14 1.1 mycroft * documentation and/or other materials provided with the distribution. 15 1.18 agc * 3. Neither the name of the University nor the names of its contributors 16 1.1 mycroft * may be used to endorse or promote products derived from this software 17 1.1 mycroft * without specific prior written permission. 18 1.1 mycroft * 19 1.1 mycroft * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.1 mycroft * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.1 mycroft * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.1 mycroft * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.1 mycroft * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.1 mycroft * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.1 mycroft * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.1 mycroft * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.1 mycroft * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 mycroft * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 mycroft * SUCH DAMAGE. 30 1.1 mycroft */ 31 1.1 mycroft 32 1.5 lukem #include <sys/cdefs.h> 33 1.1 mycroft #ifndef lint 34 1.32 lukem __COPYRIGHT("@(#) Copyright (c) 1993, 1994\ 35 1.32 lukem The Regents of the University of California. All rights reserved."); 36 1.1 mycroft #endif /* not lint */ 37 1.1 mycroft 38 1.1 mycroft #ifndef lint 39 1.2 cgd #if 0 40 1.6 lukem static char sccsid[] = "@(#)mount_lfs.c 8.4 (Berkeley) 4/26/95"; 41 1.2 cgd #else 42 1.39 christos __RCSID("$NetBSD: mount_lfs.c,v 1.39 2016/02/21 22:51:29 christos Exp $"); 43 1.2 cgd #endif 44 1.1 mycroft #endif /* not lint */ 45 1.1 mycroft 46 1.1 mycroft #include <sys/param.h> 47 1.1 mycroft #include <sys/mount.h> 48 1.7 fvdl 49 1.38 dholland #include <ufs/lfs/lfs.h> 50 1.1 mycroft 51 1.1 mycroft #include <err.h> 52 1.8 perseant #include <errno.h> 53 1.1 mycroft #include <stdio.h> 54 1.1 mycroft #include <stdlib.h> 55 1.1 mycroft #include <string.h> 56 1.1 mycroft #include <unistd.h> 57 1.12 perseant #include <paths.h> 58 1.12 perseant 59 1.12 perseant #include <signal.h> 60 1.1 mycroft 61 1.16 jdolecek #include <mntopts.h> 62 1.1 mycroft #include "pathnames.h" 63 1.33 pooka #include "mountprog.h" 64 1.33 pooka #include "mount_lfs.h" 65 1.1 mycroft 66 1.11 jdolecek static const struct mntopt mopts[] = { 67 1.1 mycroft MOPT_STDOPTS, 68 1.1 mycroft MOPT_UPDATE, 69 1.14 christos MOPT_GETARGS, 70 1.15 jdolecek MOPT_NOATIME, 71 1.39 christos MOPT_RELATIME, 72 1.28 christos MOPT_NULL, 73 1.1 mycroft }; 74 1.1 mycroft 75 1.34 joerg __dead static void usage(void); 76 1.33 pooka 77 1.33 pooka #ifdef WANT_CLEANER 78 1.34 joerg __dead static void invoke_cleaner(char *); 79 1.22 xtraeme static void kill_daemon(char *); 80 1.22 xtraeme static void kill_cleaner(char *); 81 1.33 pooka #endif /* WANT_CLEANER */ 82 1.1 mycroft 83 1.33 pooka static int short_rds, cleaner_debug, cleaner_bytes, fs_idle, noclean; 84 1.25 christos static const char *nsegs; 85 1.1 mycroft 86 1.11 jdolecek #ifndef MOUNT_NOMAIN 87 1.1 mycroft int 88 1.22 xtraeme main(int argc, char **argv) 89 1.11 jdolecek { 90 1.33 pooka 91 1.33 pooka setprogname(argv[0]); 92 1.11 jdolecek return mount_lfs(argc, argv); 93 1.11 jdolecek } 94 1.11 jdolecek #endif 95 1.11 jdolecek 96 1.33 pooka void 97 1.33 pooka mount_lfs_parseargs(int argc, char *argv[], 98 1.38 dholland struct ulfs_args *args, int *mntflags, 99 1.33 pooka char *canon_dev, char *canon_dir) 100 1.1 mycroft { 101 1.33 pooka int ch; 102 1.27 christos mntoptparse_t mp; 103 1.12 perseant 104 1.33 pooka memset(args, 0, sizeof(*args)); 105 1.10 perseant nsegs = "4"; 106 1.33 pooka *mntflags = noclean = 0; 107 1.10 perseant cleaner_bytes = 1; 108 1.23 xtraeme while ((ch = getopt(argc, argv, "bdiN:no:s")) != -1) 109 1.1 mycroft switch (ch) { 110 1.10 perseant case 'b': 111 1.10 perseant cleaner_bytes = !cleaner_bytes; 112 1.10 perseant break; 113 1.1 mycroft case 'd': 114 1.1 mycroft cleaner_debug = 1; 115 1.1 mycroft break; 116 1.24 xtraeme case 'i': 117 1.24 xtraeme fs_idle = 1; 118 1.24 xtraeme break; 119 1.1 mycroft case 'n': 120 1.1 mycroft noclean = 1; 121 1.1 mycroft break; 122 1.10 perseant case 'N': 123 1.10 perseant nsegs = optarg; 124 1.10 perseant break; 125 1.1 mycroft case 'o': 126 1.33 pooka mp = getmntopts(optarg, mopts, mntflags, 0); 127 1.27 christos if (mp == NULL) 128 1.27 christos err(1, "getmntopts"); 129 1.27 christos freemntopts(mp); 130 1.1 mycroft break; 131 1.1 mycroft case 's': 132 1.1 mycroft short_rds = 1; 133 1.1 mycroft break; 134 1.1 mycroft case '?': 135 1.1 mycroft default: 136 1.1 mycroft usage(); 137 1.1 mycroft } 138 1.1 mycroft argc -= optind; 139 1.1 mycroft argv += optind; 140 1.1 mycroft 141 1.1 mycroft if (argc != 2) 142 1.1 mycroft usage(); 143 1.1 mycroft 144 1.33 pooka pathadj(argv[0], canon_dev); 145 1.33 pooka args->fspec = canon_dev; 146 1.33 pooka 147 1.33 pooka pathadj(argv[1], canon_dir); 148 1.33 pooka } 149 1.33 pooka 150 1.33 pooka int 151 1.33 pooka mount_lfs(int argc, char *argv[]) 152 1.33 pooka { 153 1.38 dholland struct ulfs_args args; 154 1.33 pooka int mntflags; 155 1.37 christos int mntsize, oldflags, i; 156 1.33 pooka char fs_name[MAXPATHLEN], canon_dev[MAXPATHLEN]; 157 1.33 pooka struct statvfs *mntbuf; 158 1.33 pooka const char *errcause; 159 1.21 erh 160 1.33 pooka mount_lfs_parseargs(argc, argv, &args, &mntflags, canon_dev, fs_name); 161 1.1 mycroft 162 1.12 perseant /* 163 1.12 perseant * Record the previous status of this filesystem (if any) before 164 1.12 perseant * performing the mount, so we can know whether to start or 165 1.12 perseant * kill the cleaner process below. 166 1.12 perseant */ 167 1.37 christos oldflags = MNT_RDONLY; /* If not mounted, pretend r/o */ 168 1.12 perseant if (mntflags & MNT_UPDATE) { 169 1.12 perseant if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) 170 1.12 perseant err(1, "getmntinfo"); 171 1.12 perseant for (i = 0; i < mntsize; i++) { 172 1.12 perseant if (strcmp(mntbuf[i].f_mntfromname, args.fspec) == 0) { 173 1.37 christos oldflags = mntbuf[i].f_flag; 174 1.12 perseant break; 175 1.12 perseant } 176 1.12 perseant } 177 1.12 perseant } 178 1.12 perseant 179 1.30 pooka if (mount(MOUNT_LFS, fs_name, mntflags, &args, sizeof args) == -1) { 180 1.8 perseant switch (errno) { 181 1.8 perseant case EMFILE: 182 1.8 perseant errcause = "mount table full"; 183 1.8 perseant break; 184 1.8 perseant case EINVAL: 185 1.8 perseant if (mntflags & MNT_UPDATE) 186 1.8 perseant errcause = 187 1.8 perseant "specified device does not match mounted device"; 188 1.8 perseant else 189 1.8 perseant errcause = "incorrect super block"; 190 1.8 perseant break; 191 1.8 perseant default: 192 1.8 perseant errcause = strerror(errno); 193 1.8 perseant break; 194 1.8 perseant } 195 1.8 perseant errx(1, "%s on %s: %s", args.fspec, fs_name, errcause); 196 1.8 perseant } 197 1.1 mycroft 198 1.33 pooka #ifdef WANT_CLEANER 199 1.12 perseant /* Not mounting fresh or upgrading to r/w; don't start the cleaner */ 200 1.31 pooka if (!(oldflags & MNT_RDONLY) || (mntflags & MNT_RDONLY) 201 1.31 pooka || (mntflags & MNT_GETARGS)) 202 1.12 perseant noclean = 1; 203 1.1 mycroft if (!noclean) 204 1.1 mycroft invoke_cleaner(fs_name); 205 1.1 mycroft /* NOTREACHED */ 206 1.1 mycroft 207 1.12 perseant /* Downgrade to r/o; kill the cleaner */ 208 1.12 perseant if ((mntflags & MNT_RDONLY) && !(oldflags & MNT_RDONLY)) 209 1.12 perseant kill_cleaner(fs_name); 210 1.37 christos #else 211 1.37 christos __USE(oldflags); 212 1.33 pooka #endif /* WANT_CLEANER */ 213 1.12 perseant 214 1.1 mycroft exit(0); 215 1.12 perseant } 216 1.12 perseant 217 1.33 pooka #ifdef WANT_CLEANER 218 1.12 perseant static void 219 1.22 xtraeme kill_daemon(char *pidname) 220 1.12 perseant { 221 1.12 perseant FILE *fp; 222 1.12 perseant char s[80]; 223 1.12 perseant pid_t pid; 224 1.12 perseant 225 1.12 perseant fp = fopen(pidname, "r"); 226 1.12 perseant if (fp) { 227 1.12 perseant fgets(s, 80, fp); 228 1.12 perseant pid = atoi(s); 229 1.12 perseant if (pid) 230 1.12 perseant kill(pid, SIGINT); 231 1.12 perseant fclose(fp); 232 1.12 perseant } 233 1.12 perseant } 234 1.12 perseant 235 1.12 perseant static void 236 1.22 xtraeme kill_cleaner(char *name) 237 1.12 perseant { 238 1.12 perseant char *pidname; 239 1.12 perseant char *cp; 240 1.12 perseant int off; 241 1.12 perseant 242 1.12 perseant /* Parent first */ 243 1.17 itojun asprintf(&pidname, "%slfs_cleanerd:m:%s.pid", _PATH_VARRUN, name); 244 1.17 itojun if (!pidname) 245 1.17 itojun err(1, "malloc"); 246 1.12 perseant off = strlen(_PATH_VARRUN); 247 1.12 perseant while((cp = strchr(pidname + off, '/')) != NULL) 248 1.12 perseant *cp = '|'; 249 1.12 perseant kill_daemon(pidname); 250 1.17 itojun free(pidname); 251 1.12 perseant 252 1.12 perseant /* Then child */ 253 1.17 itojun asprintf(&pidname, "%slfs_cleanerd:s:%s.pid", _PATH_VARRUN, name); 254 1.17 itojun if (!pidname) 255 1.17 itojun err(1, "malloc"); 256 1.12 perseant off = strlen(_PATH_VARRUN); 257 1.12 perseant while((cp = strchr(pidname + off, '/')) != NULL) 258 1.12 perseant *cp = '|'; 259 1.12 perseant kill_daemon(pidname); 260 1.17 itojun free(pidname); 261 1.1 mycroft } 262 1.1 mycroft 263 1.11 jdolecek static void 264 1.22 xtraeme invoke_cleaner(char *name) 265 1.1 mycroft { 266 1.25 christos const char *args[7], **ap = args; 267 1.1 mycroft 268 1.1 mycroft /* Build the argument list. */ 269 1.1 mycroft *ap++ = _PATH_LFS_CLEANERD; 270 1.10 perseant if (cleaner_bytes) 271 1.10 perseant *ap++ = "-b"; 272 1.10 perseant if (nsegs) { 273 1.10 perseant *ap++ = "-n"; 274 1.10 perseant *ap++ = nsegs; 275 1.10 perseant } 276 1.1 mycroft if (short_rds) 277 1.1 mycroft *ap++ = "-s"; 278 1.1 mycroft if (cleaner_debug) 279 1.1 mycroft *ap++ = "-d"; 280 1.24 xtraeme if (fs_idle) 281 1.24 xtraeme *ap++ = "-f"; 282 1.1 mycroft *ap++ = name; 283 1.1 mycroft *ap = NULL; 284 1.1 mycroft 285 1.25 christos execv(args[0], __UNCONST(args)); 286 1.1 mycroft err(1, "exec %s", _PATH_LFS_CLEANERD); 287 1.1 mycroft } 288 1.33 pooka #endif /* WANT_CLEANER */ 289 1.1 mycroft 290 1.11 jdolecek static void 291 1.22 xtraeme usage(void) 292 1.1 mycroft { 293 1.1 mycroft (void)fprintf(stderr, 294 1.23 xtraeme "usage: %s [-bdins] [-N nsegs] [-o options] special node\n", 295 1.20 wiz getprogname()); 296 1.1 mycroft exit(1); 297 1.1 mycroft } 298