4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1991,1996,1998 by Sun Microsystems, Inc.
24 * All rights reserved.
27 #pragma ident "%Z%%M% %I% %E% SMI"
34 * Uncomment if using mmap'ing of files for pre-fetch.
35 * #define ENABLE_MMAP 1
39 ino_t id_inumber
; /* inode number */
40 long id_gen
; /* generation number */
41 struct inodesc
*id_next
; /* next on linked list */
44 static struct inodesc ilist
; /* list of used inodesc structs */
45 static struct inodesc
*last
; /* last inodesc init'd or matched */
46 static struct inodesc
*freeinodesc
; /* free list of inodesc structs */
47 static struct inodesc
**ialloc
; /* allocated chunks, for freeing */
48 static int nchunks
; /* number of allocations */
50 #ifdef ENABLE_MMAP /* XXX part of mmap support */
52 * If an mmap'ed file is truncated as it is being dumped or
53 * faulted in, we are delivered a SIGBUS.
55 static jmp_buf truncate_buf
;
56 static void (*savebus
)();
60 static void onsigbus(int);
62 static void onsigbus();
65 #endif /* ENABLE_MMAP */
71 #ifdef ENABLE_MMAP /* XXX part of mmap support */
81 longjmp(truncate_buf
, 1);
84 #endif /* ENABLE_MMAP */
96 maxino
= (unsigned)(sblock
->fs_ipg
* sblock
->fs_ncg
);
97 if (maxino
> ULONG_MAX
) {
98 msg(gettext("allocino: filesystem too large\n"));
102 /* LINTED maxino guaranteed to fit into a size_t by above test */
103 nused
= maxino
- sblock
->fs_cstotal
.cs_nifree
;
104 freeinodesc
= (struct inodesc
*)xcalloc(nused
, sizeof (*freeinodesc
));
105 if (freeinodesc
== (struct inodesc
*)0) {
106 msg(gettext("%s: out of memory\n"), "allocino");
112 (struct inodesc
**)xmalloc(2*sizeof (*ialloc
));
113 ialloc
[0] = freeinodesc
;
114 ialloc
[1] = (struct inodesc
*)0;
127 if (ialloc
== (struct inodesc
**)0)
129 for (i
= 0; i
< nchunks
; i
++)
133 ialloc
= (struct inodesc
**)0;
140 last
= ilist
.id_next
;
141 while (last
&& last
->id_inumber
< ino
)
142 last
= last
->id_next
;
150 extern char *getfullblkname();
152 dp
= getfullblkname(cp
);
159 if (dp
== cp
) /* caller wants to always free() dp */
166 * Determine if specified device is mounted at
167 * specified mount point. Returns 1 if mounted,
168 * 0 if not mounted, -1 on error.
171 lf_ismounted(devname
, dirname
)
172 char *devname
; /* name of device (raw or block) */
173 char *dirname
; /* name of f/s mount point */
176 char *blockname
; /* name of block device */
180 if ((blockname
= unrawname(devname
)) == NULL
) {
181 msg(gettext("Cannot obtain block name from `%s'\n"), devname
);
184 if (stat64(blockname
, &st
) < 0) {
186 msg(gettext("Cannot obtain status of device `%s': %s\n"),
187 blockname
, strerror(saverr
));
193 if (stat64(dirname
, &st
) < 0) {
195 msg(gettext("Cannot obtain status of device `%s': %s\n"),
196 dirname
, strerror(saverr
));
199 if (dev
== st
.st_dev
)
204 #ifdef ENABLE_MMAP /* XXX mapped-file support */
205 #define MINMAPSIZE 1024*1024
206 #define MAXMAPSIZE 1024*1024*32
208 static caddr_t mapbase
; /* base of mapped data */
209 static caddr_t mapend
; /* last byte of mapped data */
210 static size_t mapsize
; /* amount of mapped data */
212 * Map a file prior to dumping and start faulting in its
213 * pages. Stop if we catch a signal indicating our turn
214 * to dump has arrived. If the file is truncated out from
215 * under us, immediately return.
216 * NB: the base of the mapped data may not coincide
217 * exactly to the requested offset, due to alignment
221 mapfile(fd
, offset
, bytes
, fetch
)
223 off_t offset
; /* offset within file */
224 off_t bytes
; /* number of bytes to map */
225 int fetch
; /* start faulting in pages */
227 /*LINTED [c used during pre-fetch faulting]*/
229 int stride
= (int)sysconf(_SC_PAGESIZE
);
230 extern int caught
; /* pre-fetch until set */
231 caddr_t mapstart
; /* beginning of file's mapped data */
232 off_t mapoffset
; /* page-aligned offset */
235 mapbase
= mapend
= (caddr_t
)0;
240 * mmap the file for reading
242 mapoffset
= offset
& ~(stride
- 1);
243 /* LINTED: "bytes" will always fit into a size_t */
244 mapsize
= bytes
+ (offset
- mapoffset
);
245 if (mapsize
> MAXMAPSIZE
)
246 mapsize
= MAXMAPSIZE
;
247 while ((mapbase
= mmap((caddr_t
)0, mapsize
, PROT_READ
,
248 MAP_SHARED
, fd
, mapoffset
)) == (caddr_t
)-1 &&
249 errno
== ENOMEM
&& mapsize
>= MINMAPSIZE
) {
251 * Due to address space limitations, we
252 * may not be able to map as much as we want.
254 mapsize
/= 2; /* exponential back-off */
257 if (mapbase
== (caddr_t
)-1) {
259 msg(gettext("Cannot map file at inode `%lu' into memory: %s\n"),
260 ino
, strerror(saverr
));
261 /* XXX why not call dumpailing() here? */
263 "Do you want to attempt to continue? (\"yes\" or \"no\") "))) {
267 mapbase
= (caddr_t
)0;
271 (void) madvise(mapbase
, mapsize
, MADV_SEQUENTIAL
);
272 mapstart
= mapbase
+ (offset
- mapoffset
);
273 mapend
= mapbase
+ (mapsize
- 1);
278 if (setjmp(truncate_buf
) == 0) {
279 savebus
= signal(SIGBUS
, onsigbus
);
281 * Touch each page to pre-fetch by faulting. At least
282 * one of c or *p must be declared volatile, lest the
283 * optimizer eliminate the assignment in the loop.
286 for (p
= mapbase
; !caught
&& p
<= mapend
; p
+= stride
) {
287 /* LINTED: c is used for its side-effects */
294 /* XGETTEXT: #ifdef DEBUG only */
296 "FILE TRUNCATED (fault): Interrupting pre-fetch\n"));
298 (void) signal(SIGBUS
, savebus
);
310 /* XXX we're unmapping it, so what does this gain us? */
311 (void) msync(mapbase
, mapsize
, MS_ASYNC
|MS_INVALIDATE
);
312 (void) munmap(mapbase
, mapsize
);
313 mapbase
= (caddr_t
)0;
316 #endif /* ENABLE_MMAP */
325 static int passno
= 1; /* active file pass number */
328 static char defext
[] = ".retry";
331 msg(gettext("Cannot re-dump active files to `%s'\n"), tape
);
337 (void) snprintf(buf
, sizeof (buf
), gettext(
338 "%d files were active and will be re-dumped\n"), active
);
340 (void) snprintf(buf
, sizeof (buf
), gettext(
341 "1 file was active and will be re-dumped\n"));
346 reset(); /* reset tape params */
347 spcl
.c_ddate
= spcl
.c_date
; /* chain with last dump/pass */
350 * If archiving, create a new
356 ext
= strstr(old
, defext
);
357 if (ext
!= (char *)NULL
)
358 *ext
= '\0'; /* just want the base name */
360 /* The two is for the trailing \0 and rounding up log10() */
361 archivefile
= xmalloc(strlen(old
) + strlen(defext
) +
362 (int)log10((double)passno
) + 2);
365 (void) sprintf(archivefile
, "%s%s%d", old
, defext
, passno
);
372 * A "rewind" tape device. When we do
373 * the close, we will lose our position.
374 * Be nice and switch volumes.
376 (void) snprintf(buf
, sizeof (buf
), gettext(
377 "Warning - cannot dump active files to rewind device `%s'\n"),
389 * Not a tape. Do a volume switch.
390 * This will advance to the next file
391 * if using a sequence of files, next
392 * diskette if using diskettes, or
393 * let the user move the old file out
397 changevol(); /* switch files */
399 (void) snprintf(buf
, sizeof (buf
), gettext(
400 "Dumping active files (retry pass %d) to `%s'\n"), passno
, tape
);