4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
30 * Portions of this source code were derived from Berkeley 4.3 BSD
31 * under license from the Regents of the University of California.
38 #include <sys/mkdev.h>
44 static uint_t writesize
; /* size of malloc()ed buffer for tape */
45 static ino_t inos
[TP_NINOS
]; /* starting inodes on each tape */
48 * The req structure is used to pass commands from the parent
49 * process through the pipes to the slave processes. It comes
50 * in two flavors, depending on which mode dump is operating under:
51 * an inode request (on-line mode) and a disk block request ("old" mode).
54 * The inode request structure is used during on-line mode.
55 * The master passes inode numbers and starting offsets to
56 * the slaves. The tape writer passes out the current inode,
57 * offset, and number of tape records written after completing a volume.
60 ino_t inumber
; /* inode number to open/dump */
61 long igen
; /* inode generation number */
62 off_t offset
; /* starting offset in inode */
63 int count
; /* count for 1st spclrec */
66 * The block request structure is used in off-line mode to pass
67 * commands to dump disk blocks from the parent process through
68 * the pipes to the slave processes.
71 diskaddr_t dblk
; /* disk address to read */
72 size_t size
; /* number of bytes to read from disk */
73 ulong_t spclrec
[1]; /* actually longer */
77 short aflag
; /* write data to archive process as well */
78 short tflag
; /* begin new tape */
80 struct ireq ino
; /* used for on-line mode */
81 struct breq blks
; /* used for off-line mode */
85 #define ir_inumber data.ino.inumber
86 #define ir_igen data.ino.igen
87 #define ir_offset data.ino.offset
88 #define ir_count data.ino.count
90 #define br_dblk data.blks.dblk
91 #define br_size data.blks.size
92 #define br_spcl data.blks.spclrec
94 static int reqsiz
= 0; /* alloctape will initialize */
98 int sl_slavefd
; /* pipe from master to slave */
99 pid_t sl_slavepid
; /* slave pid; used by killall() */
100 ino_t sl_inos
; /* inos, if this record starts tape */
101 int sl_offset
; /* logical blocks written for object */
102 int sl_count
; /* logical blocks left in spclrec */
103 int sl_tapea
; /* header number, if starting tape */
104 int sl_firstrec
; /* number of first block on tape */
105 int sl_state
; /* dump output state */
106 struct req
*sl_req
; /* instruction packet to slave */
108 static struct slaves slaves
[SLAVES
]; /* one per slave */
109 static struct slaves
*slp
; /* pointer to current slave */
110 static struct slaves chkpt
; /* checkpointed data */
113 char *b_data
; /* pointer to buffer data */
114 int b_flags
; /* flags (see below) */
118 * The following variables are in shared memory, and must be
119 * explicitly checkpointed and/or reset.
121 static caddr_t shared
; /* pointer to block of shared memory */
122 static struct bdesc
*bufp
; /* buffer descriptors */
123 static struct bdesc
**current
; /* output buffer to fill */
124 static int *tapea
; /* logical record count */
127 static int *readmissp
; /* number of times writer was idle */
128 static int *idle
; /* number of times slaves were idle */
129 #endif /* INSTRUMENT */
134 #define BUF_EMPTY 0x0 /* nothing in buffer */
135 #define BUF_FULL 0x1 /* data in buffer */
136 #define BUF_SPCLREC 0x2 /* contains special record */
137 #define BUF_ARCHIVE 0x4 /* dump to archive */
139 static int recsout
; /* number of req's sent to slaves */
140 static int totalrecsout
; /* total number of req's sent to slaves */
141 static int rotor
; /* next slave to be instructed */
142 static pid_t master
; /* pid of master, for sending error signals */
143 static int writer
= -1; /* fd of tape writer */
144 static pid_t writepid
; /* pid of tape writer */
145 static int arch
; /* fd of output archiver */
146 static pid_t archivepid
; /* pid of output archiver */
147 static int archivefd
; /* fd of archive file (proper) */
148 static offset_t lf_archoffset
; /* checkpointed offset into archive file */
150 int caught
; /* caught signal -- imported by mapfile() */
157 static void cmdwrterr(void);
158 static void cmdrderr(void);
159 static void freetape(void);
160 static void bufclear(void);
161 static pid_t
setuparchive(void);
162 static pid_t
setupwriter(void);
163 static void nextslave(void);
164 static void tperror(int);
165 static void rollforward(int);
166 static void nap(int);
167 static void alrm(int);
168 static void just_rewind(void);
169 static void killall(void);
170 static void proceed(int);
171 static void die(int);
172 static void enslave(void);
173 static void wait_our_turn(void);
174 static void dumpoffline(int, pid_t
, int);
175 static void onxfsz(int);
176 static void dowrite(int);
177 static void checkpoint(struct bdesc
*, int);
178 static ssize_t
atomic(int (*)(), int, char *, int);
180 static void cmdwrterr();
181 static void cmdrderr();
182 static void freetape();
183 static void bufclear();
184 static pid_t
setuparchive();
185 static pid_t
setupwriter();
186 static void nextslave();
187 static void tperror();
188 static void rollforward();
191 static void just_rewind();
192 static void killall();
193 static void proceed();
195 static void enslave();
196 static void wait_our_turn();
197 static void dumpoffline();
198 static void onxfsz();
199 static void dowrite();
200 static void checkpoint();
201 static ssize_t
atomic();
204 static size_t tapesize
;
207 * Allocate buffers and shared memory variables. Tape buffers are
208 * allocated on page boundaries for tape write() efficiency.
216 struct slaves
*slavep
;
217 ulong_t pgoff
= (unsigned)(getpagesize() - 1); /* 2**n - 1 */
223 writesize
= ntrec
* tp_bsize
;
225 msg(gettext("Writing %d Kilobyte records\n"),
226 writesize
/ TP_BSIZE_MIN
);
229 * set up shared memory seg for here and child
231 mapfd
= open("/dev/zero", O_RDWR
);
234 msg(gettext("Cannot open `%s': %s\n"),
235 "/dev/zero", strerror(saverr
));
240 * Allocate space such that buffers are page-aligned and
241 * pointers are aligned on 4-byte boundaries (for SPARC).
242 * This code assumes that (NBUF * writesize) is a multiple
243 * of the page size and that pages are aligned on 4-byte
244 * boundaries. Space is allocated as follows:
246 * (NBUF * writesize) for the actual buffers
247 * (pagesize - 1) for padding so the buffers are page-aligned
248 * (NBUF * ntrec * sizeof (struct bdesc)) for each buffer
249 * (n * sizeof (int)) for [n] debugging variables/pointers
250 * (n * sizeof (int)) for [n] miscellaneous variables/pointers
253 (NBUF
* writesize
) /* output buffers */
254 /* LINTED: pgoff fits into a size_t */
255 + (size_t)pgoff
/* page alignment */
256 /* buffer descriptors */
257 + (((size_t)sizeof (struct bdesc
)) * NBUF
* ntrec
)
259 + (2 * (size_t)sizeof (int *)) /* instrumentation */
261 /* shared variables */
262 + (size_t)sizeof (struct bdesc
**)
263 + (size_t)sizeof (int *)
264 + (3 * (size_t)sizeof (time_t));
266 shared
= mmap(NULL
, tapesize
, PROT_READ
|PROT_WRITE
,
267 MAP_SHARED
, mapfd
, (off_t
)0);
268 if (shared
== (caddr_t
)-1) {
270 msg(gettext("Cannot memory map output buffers: %s\n"),
278 * Buffers and buffer headers
280 obuf
= (char *)(((ulong_t
)shared
+ pgoff
) & ~pgoff
);
281 /* LINTED obuf and writesize are aligned */
282 bufp
= (struct bdesc
*)(obuf
+ NBUF
*writesize
);
284 * Shared memory variables
286 current
= (struct bdesc
**)&bufp
[NBUF
*ntrec
];
287 tapea
= (int *)(current
+ 1);
288 /* LINTED pointer alignment ok */
289 telapsed
= (time_t *)(tapea
+ 1);
290 tstart_writing
= telapsed
+ 1;
291 tschedule
= tstart_writing
+ 1;
294 * Debugging and instrumentation variables
296 readmissp
= (int *)(tschedule
+ 1);
297 idle
= readmissp
+ 1;
299 for (i
= 0, j
= 0; i
< NBUF
* ntrec
; i
++, j
+= tp_bsize
) {
300 bufp
[i
].b_data
= &obuf
[j
];
303 reqsiz
= sizeof (struct req
) + tp_bsize
- sizeof (long);
304 for (slavep
= slaves
; slavep
< &slaves
[SLAVES
]; slavep
++)
305 slavep
->sl_req
= (struct req
*)xmalloc(reqsiz
);
307 chkpt
.sl_offset
= 0; /* start at offset 0 */
309 chkpt
.sl_inos
= UFSROOTINO
; /* in root inode */
310 chkpt
.sl_firstrec
= 1;
323 (void) timeclock((time_t)0);
324 (void) munmap(shared
, tapesize
);
329 * Reset tape state variables -- called
330 * before a pass to dump active files.
350 chkpt
.sl_offset
= 0; /* start at offset 0 */
352 chkpt
.sl_inos
= UFSROOTINO
; /* in root inode */
353 chkpt
.sl_firstrec
= 1;
367 for (i
= 0, bp
= bufp
; i
< NBUF
* ntrec
; i
++, bp
++)
368 bp
->b_flags
= BUF_EMPTY
;
369 if ((caddr_t
)current
< shared
||
370 (caddr_t
)current
> (shared
+ tapesize
)) {
372 "bufclear: current pointer out of range of shared memory\n"));
376 if ((*current
!= NULL
) &&
377 (*current
< &bufp
[0] || *current
> &bufp
[NBUF
*ntrec
])) {
378 /* ANSI string catenation, to shut cstyle up */
379 msg(gettext("bufclear: current buffer pointer (0x%x) "
380 "out of range of buffer\naddresses (0x%x - 0x%x)\n"),
381 *current
, &bufp
[0], &bufp
[NBUF
*ntrec
]);
389 * Start a process to collect information describing the dump.
390 * This data takes two forms:
391 * the bitmap and directory information being written to
392 * the front of the tape (the "archive" file)
393 * information describing each directory and inode (to
394 * be included in the database tmp file)
395 * Write the data to the files as it is received so huge file
396 * systems don't cause dump to consume large amounts of memory.
401 struct slaves
*slavep
;
411 * Both the archive and database tmp files are
412 * checkpointed by taking their current offsets
413 * (sizes) after completing each volume. Restoring
414 * from a checkpoint involves truncating to the
417 if (archive
&& !doingactive
) {
418 /* It's allowed/expected to exist, so can't use O_EXCL */
419 archivefd
= safe_file_open(archivefile
, O_WRONLY
, 0600);
422 msg(gettext("Cannot open archive file `%s': %s\n"),
423 archivefile
, strerror(saverr
));
430 if (lseek64(archivefd
, lf_archoffset
, 0) < 0) {
433 "Cannot position archive file `%s' : %s\n"),
434 archivefile
, strerror(saverr
));
438 if (ftruncate64(archivefd
, lf_archoffset
) < 0) {
441 "Cannot truncate archive file `%s' : %s\n"),
442 archivefile
, strerror(saverr
));
450 msg(gettext("%s: %s error: %s\n"),
451 "setuparchive", "pipe", strerror(saverr
));
455 if ((pid
= fork()) < 0) {
457 msg(gettext("%s: %s error: %s\n"),
458 "setuparchive", "fork", strerror(saverr
));
464 (void) close(cmd
[0]);
471 (void) signal(SIGINT
, SIG_IGN
); /* master handles this */
473 (void) sleep(4); /* allow time for parent's message to get out */
474 /* XGETTEXT: #ifdef TDEBUG only */
475 msg(gettext("Archiver has pid = %ld\n"), (long)getpid());
477 freeino(); /* release unneeded resources */
479 for (slavep
= &slaves
[0]; slavep
< &slaves
[SLAVES
]; slavep
++) {
480 if (slavep
->sl_slavefd
!= -1) {
481 (void) close(slavep
->sl_slavefd
);
482 slavep
->sl_slavefd
= -1;
488 (void) close(cmd
[1]);
489 data
= xmalloc(tp_bsize
);
491 size
= atomic((int(*)())read
, cmd
[0], (char *)&flags
,
493 if ((unsigned)size
!= sizeof (flags
))
495 size
= atomic((int(*)())read
, cmd
[0], data
, tp_bsize
);
496 if (size
== tp_bsize
) {
497 if (archive
&& flags
& BUF_ARCHIVE
&& !punt
&&
498 (size
= write(archivefd
, data
, tp_bsize
))
503 errmsg
= strdup(gettext(
504 "Output truncated"));
508 errmsg
= strerror(errno
);
511 if (fstat64(archivefd
, &stats
) < 0)
514 /* cast to keep lint&printf happy */
516 "Cannot write archive file `%s' at offset %lld: %s\n"),
517 archivefile
, (longlong_t
)stats
.st_size
,
520 "Archive file will be deleted, dump will continue\n"));
522 if ((size
!= -1) && (*errmsg
!= '\0')) {
530 (void) close(cmd
[0]);
532 (void) close(archivefd
);
536 (void) unlink(archivefile
);
545 * Start a process to read the output buffers and write the data
546 * to the output device.
551 struct slaves
*slavep
;
559 msg(gettext("%s: %s error: %s\n"),
560 "setupwriter", "pipe", strerror(saverr
));
564 if ((pid
= fork()) < 0) {
566 msg(gettext("%s: %s error: %s\n"),
567 "setupwriter", "fork", strerror(saverr
));
575 (void) close(cmd
[0]);
580 * Child (writer) process
582 (void) signal(SIGINT
, SIG_IGN
); /* master handles this */
584 (void) sleep(4); /* allow time for parent's message to get out */
585 /* XGETTEXT: #ifdef TDEBUG only */
586 msg(gettext("Writer has pid = %ld\n"), (long)getpid());
589 freeino(); /* release unneeded resources */
590 for (slavep
= &slaves
[0]; slavep
< &slaves
[SLAVES
]; slavep
++) {
591 if (slavep
->sl_slavefd
!= -1) {
592 (void) close(slavep
->sl_slavefd
);
593 slavep
->sl_slavefd
= -1;
598 (void) close(cmd
[1]);
604 (void) close(cmd
[0]);
619 int flags
= BUF_SPCLREC
;
621 if ((BIT(ino
, shamap
)) && (spcl
.c_type
== TS_INODE
)) {
622 spcl
.c_type
= TS_ADDR
;
623 /* LINTED: result fits in a short */
624 spcl
.c_dinode
.di_mode
&= ~S_IFMT
;
625 /* LINTED: result fits in a short */
626 spcl
.c_dinode
.di_mode
|= IFSHAD
;
630 * Only TS_INODEs should have short metadata, if this
631 * isn't such a spclrec, clear the metadata flag and
632 * the c_shadow contents.
634 if (!(spcl
.c_type
== TS_INODE
&& (spcl
.c_flags
& DR_HASMETA
))) {
635 spcl
.c_flags
&= ~DR_HASMETA
;
636 bcopy(c_shadow_save
, &(spcl
.c_shadow
),
637 sizeof (spcl
.c_shadow
));
640 if (spcl
.c_type
== TS_END
) {
642 spcl
.c_flags
|= DR_INODEINFO
;
643 bcopy((char *)inos
, (char *)spcl
.c_inos
, sizeof (inos
));
644 } else if (spcl
.c_type
== TS_TAPE
) {
645 spcl
.c_flags
|= DR_NEWHEADER
;
647 spcl
.c_flags
|= DR_REDUMP
;
648 } else if (spcl
.c_type
!= TS_INODE
)
650 spcl
.c_tapea
= *tapea
;
651 /* LINTED for now, max inode # is 2**31 (ufs max size is 4TB) */
652 spcl
.c_inumber
= (uint32_t)ino
;
653 spcl
.c_magic
= (tp_bsize
== TP_BSIZE_MIN
) ? NFS_MAGIC
: MTB_MAGIC
;
655 ip
= (int32_t *)&spcl
;
657 assert((tp_bsize
% sizeof (*ip
)) == 0);
658 i
= tp_bsize
/ sizeof (*ip
);
662 s
-= *ip
++; s
-= *ip
++; s
-= *ip
++; s
-= *ip
++;
663 s
-= *ip
++; s
-= *ip
++; s
-= *ip
++; s
-= *ip
++;
666 taprec((uchar_t
*)&spcl
, flags
, sizeof (spcl
));
667 if (spcl
.c_type
== TS_END
)
668 spcl
.c_flags
&= ~DR_INODEINFO
;
669 else if (spcl
.c_type
== TS_TAPE
)
670 spcl
.c_flags
&= ~(DR_NEWHEADER
|DR_REDUMP
|DR_TRUEINC
);
674 * Fill appropriate buffer
677 taprec(uchar_t
*dp
, int flags
, int size
)
679 if (size
> tp_bsize
) {
681 "taprec: Unexpected buffer size, expected %d, got %d.\n"),
687 while ((*current
)->b_flags
& BUF_FULL
)
690 bcopy(dp
, (*current
)->b_data
, (size_t)size
);
691 if (size
< tp_bsize
) {
692 bzero((*current
)->b_data
+ size
, tp_bsize
- size
);
696 flags
|= BUF_ARCHIVE
;
698 /* no locking as we assume only one reader and one writer active */
699 (*current
)->b_flags
= (flags
| BUF_FULL
);
700 if (++*current
>= &bufp
[NBUF
*ntrec
])
701 (*current
) = &bufp
[0];
706 dmpblk(daddr32_t blkno
, size_t size
, off_t offset
)
710 assert((offset
>> DEV_BSHIFT
) <= INT32_MAX
);
711 dblkno
= fsbtodb(sblock
, blkno
) + (offset
>> DEV_BSHIFT
);
712 size
= (size
+ DEV_BSIZE
-1) & ~(DEV_BSIZE
-1);
713 slp
->sl_req
->br_dblk
= dblkno
;
714 slp
->sl_req
->br_size
= size
;
716 /* LINTED: result fits in a short */
717 slp
->sl_req
->aflag
|= BUF_ARCHIVE
;
719 toslave((void(*)())0, ino
);
729 msg(gettext("Write error on %s\n"), tape
);
730 msg(gettext("Cannot recover\n"));
735 broadcast(gettext("WRITE ERROR!\n"));
736 (void) snprintf(buf
, sizeof (buf
),
737 gettext("Do you want to restart?: (\"yes\" or \"no\") "));
742 if (tapeout
&& (isrewind(to
) || offline
)) {
743 /* ANSI string catenation, to shut cstyle up */
744 msg(gettext("This tape will rewind. After "
745 "it is rewound,\nreplace the faulty tape "
746 "with a new one;\nthis dump volume will "
750 broadcast(gettext("TAPE VERIFICATION ERROR!\n"));
751 (void) snprintf(buf
, sizeof (buf
), gettext(
752 "Do you want to rewrite?: (\"yes\" or \"no\") "));
758 "This tape will be rewritten and then verified\n"));
766 * Called by master from pass() to send a request to dump files/blocks
767 * to one of the slaves. Slaves return whether the file was active
768 * when it was being dumped. The tape writer process sends checkpoint
769 * info when it completes a volume.
772 toslave(void (*fn
)(), ino_t inumber
)
776 if (recsout
>= SLAVES
) {
777 if ((unsigned)atomic((int(*)())read
, slp
->sl_slavefd
,
778 (char *)&wasactive
, sizeof (wasactive
)) !=
779 sizeof (wasactive
)) {
787 "The file at inode `%lu' was active and will be recopied\n"),
788 slp
->sl_req
->ir_inumber
);
789 /* LINTED: 32-bit to 8-bit assignment ok */
790 BIS(slp
->sl_req
->ir_inumber
, activemap
);
793 slp
->sl_req
->aflag
= 0;
795 /* LINTED: result fits in a short */
796 slp
->sl_req
->aflag
|= BUF_ARCHIVE
;
801 if (atomic((int(*)())write
, slp
->sl_slavefd
, (char *)slp
->sl_req
,
812 dospcl(ino_t inumber
)
814 /* LINTED for now, max inode # is 2**31 (ufs max size is 1TB) */
815 spcl
.c_inumber
= (uint32_t)inumber
;
816 slp
->sl_req
->br_dblk
= 0;
817 bcopy((char *)&spcl
, (char *)slp
->sl_req
->br_spcl
, tp_bsize
);
827 if (++rotor
>= SLAVES
) {
830 slp
= &slaves
[rotor
];
844 * Retrieve all slave status
846 if (recsout
< SLAVES
) {
850 for (i
= 0; i
< (recsout
< SLAVES
? recsout
: SLAVES
); i
++) {
851 if ((unsigned)atomic((int(*)())read
, slp
->sl_slavefd
,
852 (char *)&wasactive
, sizeof (wasactive
)) !=
853 sizeof (wasactive
)) {
861 "inode %d was active and will be recopied\n"),
862 slp
->sl_req
->ir_inumber
);
863 /* LINTED: 32-bit to 8-bit assignment ok */
864 BIS(slp
->sl_req
->ir_inumber
, activemap
);
877 sigset_t block_set
, oset
; /* hold SIGUSR1 and atomically sleep */
879 (void) sigemptyset(&block_set
);
880 (void) sigaddset(&block_set
, SIGUSR1
);
881 (void) sigprocmask(SIG_BLOCK
, &block_set
, &oset
);
882 (void) kill(writepid
, SIGUSR1
); /* tell writer to flush */
883 (void) sigpause(SIGUSR1
); /* wait for SIGUSR1 from writer */
887 jmp_buf checkpoint_buf
;
890 * Roll forward to the next volume after receiving
891 * an EOT signal from writer. Get checkpoint data
892 * from writer and return if done, otherwise fork
893 * a new process and jump back to main state loop
894 * to begin the next volume. Installed as the master's
895 * signal handler for SIGUSR1.
902 (void) sighold(SIGUSR1
);
905 * Writer sends us checkpoint information after
906 * each volume. A returned state of DS_DONE with no
907 * unwritten (left-over) records differentiates a
908 * clean flush from one in which EOT was encountered.
910 if ((unsigned)atomic((int(*)())read
, writer
, (char *)&chkpt
,
911 sizeof (struct slaves
)) != sizeof (struct slaves
)) {
916 if (atomic((int(*)())read
, writer
, (char *)&spcl
,
917 TP_BSIZE_MIN
) != TP_BSIZE_MIN
) {
922 ino
= chkpt
.sl_inos
- 1;
923 pos
= chkpt
.sl_offset
;
924 leftover
= chkpt
.sl_count
;
925 dumpstate
= chkpt
.sl_state
;
926 blockswritten
= ++chkpt
.sl_tapea
;
928 if (dumpstate
== DS_DONE
) {
931 * If archiving (either archive or
932 * database), signal the archiver
933 * to finish up. This must happen
934 * before the writer exits in order
937 (void) kill(archivepid
, SIGUSR1
);
939 (void) signal(SIGUSR1
, SIG_IGN
);
940 (void) sigrelse(SIGUSR1
);
941 (void) kill(writepid
, SIGUSR1
); /* tell writer to exit */
944 longjmp(checkpoint_buf
, 1);
949 (void) memmove(spcl
.c_addr
,
950 &spcl
.c_addr
[spcl
.c_count
-leftover
], leftover
);
951 bzero(&spcl
.c_addr
[leftover
], TP_NINDIR
-leftover
);
954 (void) kill(writepid
, SIGUSR1
); /* tell writer to exit */
955 (void) close(writer
);
959 (void) waitpid(archivepid
, &status
, 0); /* wait for archiver */
962 /* XGETTEXT: #ifdef TDEBUG only */
963 msg(gettext("Archiver %ld returns with status %d\n"),
964 (long)archivepid
, status
);
969 * Checkpoint archive file
971 if (!doingverify
&& archive
) {
972 lf_archoffset
= lseek64(archivefd
, (off64_t
)0, 2);
973 if (lf_archoffset
< 0) {
975 msg(gettext("Cannot position archive file `%s': %s\n"),
976 archivefile
, strerror(saverr
));
980 (void) close(archivefd
);
985 if (dumpstate
== DS_START
) {
987 "Tape too short: changing volumes and restarting\n"));
992 if (verify
&& !doingverify
)
1000 (void) sigrelse(SIGUSR1
);
1002 longjmp(checkpoint_buf
, 1);
1011 tv
.tv_sec
= ms
/ 1000;
1012 tv
.tv_usec
= (ms
- tv
.tv_sec
* 1000) * 1000;
1013 (void) select(0, (fd_set
*)0, (fd_set
*)0, (fd_set
*)0, &tv
);
1016 static jmp_buf alrm_buf
;
1022 longjmp(alrm_buf
, 1);
1037 * dumpdev is provided for use in prompts and is of
1040 * sdumpdev is of the form:
1042 * for remote devices, and simply:
1044 * for local devices.
1046 if (dumpdev
!= NULL
) {
1047 /* LINTED: dumpdev is not NULL */
1050 /*LINTED [cast to smaller integer]*/
1051 dumpdev
= xmalloc((size_t)((sizeof (spcl
.c_host
) + strlen(tape
) + 2)));
1052 /* LINTED unsigned -> signed cast ok */
1053 (void) sprintf(dumpdev
, "%.*s:%s", (int)sizeof (spcl
.c_host
), cp
, tape
);
1054 if (cp
== spcl
.c_host
)
1055 sdumpdev
= strchr(dumpdev
, ':') + 1;
1061 * Gross hack due to misfeature of mt tape driver that causes
1062 * the device to rewind if we generate any signals. Guess
1063 * whether tape is rewind device or not -- for local devices
1064 * we can just look at the minor number. For rmt devices,
1065 * make an educated guess.
1073 if (fstat64(f
, &sbuf
) < 0) {
1075 "Cannot obtain status of output device `%s'\n"),
1080 rewind
= minor(sbuf
.st_rdev
) & MT_NOREWIND
? 0 : 1;
1091 struct slaves
*slavep
;
1092 char *rewinding
= gettext("Tape rewinding\n");
1094 for (slavep
= &slaves
[0]; slavep
< &slaves
[SLAVES
]; slavep
++) {
1095 if (slavep
->sl_slavepid
> 0) /* signal normal exit */
1096 (void) kill(slavep
->sl_slavepid
, SIGTERM
);
1097 if (slavep
->sl_slavefd
>= 0) {
1098 (void) close(slavep
->sl_slavefd
);
1099 slavep
->sl_slavefd
= -1;
1103 /* wait for any signals from slaves */
1104 while (waitpid(0, (int *)0, 0) >= 0)
1105 /*LINTED [empty body]*/
1113 * Space to the end of the tape.
1114 * Backup first in case we already read the EOF.
1116 static struct mtop bsr
= { MTBSR
, 1 };
1117 static struct mtop eom
= { MTEOM
, 1 };
1118 static struct mtop fsf
= { MTFSF
, 1 };
1120 (void) ioctl(to
, MTIOCTOP
, &bsr
);
1121 if (ioctl(to
, MTIOCTOP
, &eom
) < 0)
1122 (void) ioctl(to
, MTIOCTOP
, &fsf
);
1126 * Guess whether the tape is rewinding so we can tell
1127 * the operator if it's going to take a long time.
1129 if (tapeout
&& isrewind(to
)) {
1130 /* tape is probably rewinding */
1142 (void) timeclock((time_t)0);
1143 if (offline
&& (!verify
|| doingverify
)) {
1158 char *rewinding
= gettext("Tape rewinding\n");
1160 (void) timeclock((time_t)0);
1163 * The check in just_rewind won't catch the case in
1164 * which the current volume is being taken off-line
1165 * and is not mounted on a no-rewind device (and is
1166 * not the last volume, which is not taken off-line).
1168 if (tapeout
&& !isrewind(to
) && offline
) {
1169 /* tape is probably rewinding */
1172 if (offline
|| autoload
) {
1173 static struct mtop offl
= { MTOFFL
, 0 };
1175 (void) ioctl(to
, MTIOCTOP
, &offl
);
1177 (void) ioctl(to
, FDEJECT
, 0);
1190 char buf1
[3000], buf2
[3000];
1191 char volname
[LBLSIZE
+1];
1193 /*CONSTANTCONDITION*/
1194 assert(sizeof (spcl
.c_label
) < sizeof (volname
));
1198 (void) strcpy(spcl
.c_label
, tlabel
);
1200 * Make volume switching as automatic as possible
1201 * while avoiding overwriting volumes. We will
1202 * switch automatically under the following condition:
1203 * 1) The user specified autoloading from the
1205 * At one time, we (in the guise of hsmdump) had the
1206 * concept of a sequence of devices to rotate through,
1207 * but that's never been a ufsdump feature.
1213 * Stop the clock for throughput calculations.
1215 if ((telapsed
!= NULL
) && (tstart_writing
!= NULL
)) {
1216 *telapsed
+= time(NULL
) - *tstart_writing
;
1219 (void) snprintf(volname
, sizeof (volname
), "#%d", tapeno
+1);
1220 (void) snprintf(buf1
, sizeof (buf1
), gettext(
1221 "Mounting volume %s on %s\n"), volname
, dumpdev
);
1226 * Wait for the tape to autoload. Note that the delay
1227 * period doesn't take into account however long it takes
1228 * for the open to fail (measured at 21 seconds for an
1229 * Exabyte 8200 under 2.7 on an Ultra 2).
1231 for (tries
= 0; tries
< autoload_tries
; tries
++) {
1234 m
= (access(tape
, F_OK
) == 0) ? 0 : O_CREAT
;
1235 if ((f
= doingverify
?
1236 safe_device_open(tape
, O_RDONLY
, 0600) :
1237 safe_device_open(tape
, O_RDONLY
|m
, 0600))
1242 (void) sleep(autoload_period
);
1245 * Autoload timed out, ask the operator to do it.
1246 * Note that query() will update *telapsed, and we
1247 * shouldn't charge for the autoload time. So, since
1248 * we updated *telapsed ourselves above, we just set
1249 * tstart_writing to the current time, and query()
1250 * will end up making a null-effect change. This,
1251 * of course, assumes that our caller will be resetting
1252 * *tstart_writing. This is currently the case.
1253 * If tstart_writing is NULL (should never happen),
1254 * we're ok, since time(2) will accept a NULL pointer.
1256 (void) time(tstart_writing
);
1259 if (strncmp(spcl
.c_label
, "none", 5)) {
1260 (void) strncpy(volname
, spcl
.c_label
, sizeof (spcl
.c_label
));
1261 volname
[sizeof (spcl
.c_label
)] = '\0';
1263 (void) snprintf(volname
, sizeof (volname
), "#%d", tapeno
+1);
1265 timeest(1, spcl
.c_tapea
);
1266 (void) snprintf(buf1
, sizeof (buf1
), gettext(
1267 "Change Volumes: Mount volume `%s' on `%s'\n"), volname
, dumpdev
);
1269 broadcast(gettext("CHANGE VOLUMES!\7\7\n"));
1270 (void) snprintf(buf1
, sizeof (buf1
), gettext(
1271 "Is the new volume (%s) mounted on `%s' and ready to go?: %s"),
1272 volname
, dumpdev
, gettext("(\"yes\" or \"no\") "));
1273 while (!query(buf1
)) {
1274 (void) snprintf(buf2
, sizeof (buf2
), gettext(
1275 "Do you want to abort dump?: (\"yes\" or \"no\") "));
1284 * We implement taking and restoring checkpoints on the tape level.
1285 * When each tape is opened, a new process is created by forking; this
1286 * saves all of the necessary context in the parent. The child
1287 * continues the dump; the parent waits around, saving the context.
1288 * If the child returns X_REWRITE, then it had problems writing that tape;
1289 * this causes the parent to fork again, duplicating the context, and
1290 * everything continues as if nothing had happened.
1296 static struct mtget mt
;
1302 struct sigvec sv
, osv
;
1304 sv
.sv_flags
= SA_RESTART
;
1305 (void) sigemptyset(&sv
.sa_mask
);
1306 sv
.sv_handler
= SIG_IGN
;
1307 (void) sigvec(SIGINT
, &sv
, NULL
);
1309 parentpid
= getpid();
1317 restore_check_point
:
1319 sv
.sv_handler
= interrupt
;
1320 (void) sigvec(SIGINT
, &sv
, NULL
);
1321 (void) fflush(stderr
);
1323 * All signals are inherited...
1329 "Context-saving fork failed in parent %ld\n"),
1333 if (childpid
!= 0) {
1336 * save the context by waiting
1337 * until the child doing all of the work returns.
1338 * let the child catch user interrupts
1340 sv
.sv_handler
= SIG_IGN
;
1341 (void) sigvec(SIGINT
, &sv
, NULL
);
1345 /* XGETTEXT: #ifdef TDEBUG only */
1347 "Volume: %d; parent process: %ld child process %ld\n"),
1348 tapeno
+1, (long)parentpid
, (long)childpid
);
1351 waitproc
= waitpid(0, &status
, 0);
1352 if (waitproc
== childpid
)
1355 "Parent %ld waiting for child %ld had another child %ld return\n"),
1356 (long)parentpid
, (long)childpid
, (long)waitproc
);
1358 if (WIFSIGNALED(status
)) {
1359 msg(gettext("Process %ld killed by signal %d: %s\n"),
1360 (long)childpid
, WTERMSIG(status
),
1361 strsignal(WTERMSIG(status
)));
1364 status
= WEXITSTATUS(status
);
1368 /* XGETTEXT: #ifdef TDEBUG only */
1370 "Child %ld finishes X_FINOK\n"), (long)childpid
);
1373 /* XGETTEXT: #ifdef TDEBUG only */
1375 "Child %ld finishes X_ABORT\n"), (long)childpid
);
1378 /* XGETTEXT: #ifdef TDEBUG only */
1380 "Child %ld finishes X_REWRITE\n"), (long)childpid
);
1383 /* XGETTEXT: #ifdef TDEBUG only */
1385 "Child %ld finishes X_RESTART\n"), (long)childpid
);
1388 /* XGETTEXT: #ifdef TDEBUG only */
1390 "Child %ld finishes X_VERIFY\n"), (long)childpid
);
1393 /* XGETTEXT: #ifdef TDEBUG only */
1394 msg(gettext("Child %ld finishes unknown %d\n"),
1395 (long)childpid
, status
);
1401 /* wait for children */
1402 while (waitpid(0, (int *)0, 0) >= 0)
1403 /*LINTED [empty body]*/
1412 goto restore_check_point
;
1417 goto restore_check_point
;
1427 sv
.sv_handler
= interrupt
;
1428 (void) sigvec(SIGINT
, &sv
, NULL
);
1432 msg(gettext("Bad return code from dump: %d\n"), status
);
1437 } else { /* we are the child; just continue */
1441 (void) sleep(4); /* time for parent's message to get out */
1442 /* XGETTEXT: #ifdef TDEBUG only */
1444 "Child on Volume %d has parent %ld, my pid = %ld\n"),
1445 tapeno
+1, (long)parentpid
, (long)getpid());
1447 (void) snprintf(buf
, sizeof (buf
), gettext(
1448 "Cannot open `%s'. Do you want to retry the open?: (\"yes\" or \"no\") "),
1452 while ((to
= pipeout
? 1 :
1453 safe_device_open(tape
, O_RDONLY
, 0600)) < 0) {
1456 if (!query_once(buf
, 1)) {
1469 * If we're using the non-rewinding tape device,
1470 * the tape will be left positioned after the
1471 * EOF mark. We need to back up to the beginning
1472 * of this tape file (cross two tape marks in the
1473 * reverse direction and one in the forward
1474 * direction) before the verify pass.
1476 static struct mtop bsf
= { MTBSF
, 2 };
1477 static struct mtop fsf
= { MTFSF
, 1 };
1478 static struct mtop nbsf
= { MTNBSF
, 1 };
1480 if (ioctl(to
, MTIOCTOP
, &bsf
) >= 0)
1481 (void) ioctl(to
, MTIOCTOP
, &fsf
);
1483 (void) ioctl(to
, MTIOCTOP
, &nbsf
);
1486 * XXX Add logic to test for "tape" being a
1487 * XXX device or a non-existent file.
1488 * Current behaviour is that it must exist,
1489 * and we over-write whatever's there.
1490 * This can be bad if tape == "/etc/passwd".
1492 if (!pipeout
&& doposition
&& (tapeno
== 0)) {
1494 if (setjmp(alrm_buf
)) {
1496 * The tape is rewinding;
1500 "Cannot position tape using rewind device!\n"));
1504 sv
.sv_handler
= alrm
;
1505 (void) sigvec(SIGALRM
, &sv
, &osv
);
1508 while ((to
= safe_device_open(tape
, O_WRONLY
,
1512 (void) sigvec(SIGALRM
, &osv
,
1516 m
= (access(tape
, F_OK
) == 0) ? 0 : O_CREAT
;
1518 * Only verify the tape label if label
1519 * verification is on and we are at BOT
1523 else while ((to
= safe_device_open(tape
,
1524 O_WRONLY
|m
, 0600)) < 0)
1525 if (!query_once(buf
, 1)) {
1532 tapeout
= ioctl(to
, MTIOCGET
, &mt
) >= 0; /* set state */
1534 * Make sure the tape is positioned
1535 * where it is supposed to be
1537 if (tapeout
&& (tapeno
> 0) &&
1538 (mt
.mt_fileno
!= (filenum
-1))) {
1539 (void) snprintf(buf
, sizeof (buf
), gettext(
1540 "Warning - tape positioning error!\n\
1541 \t%s current file %ld, should be %ld\n"),
1542 tape
, mt
.mt_fileno
+1, filenum
);
1547 tapeno
++; /* current tape sequence */
1548 if (tapeno
< TP_NINOS
)
1549 inos
[tapeno
] = chkpt
.sl_inos
;
1550 spcl
.c_firstrec
= chkpt
.sl_firstrec
;
1551 spcl
.c_tapea
= (*tapea
) = chkpt
.sl_tapea
;
1554 enslave(); /* Share tape buffers with slaves */
1558 /* XGETTEXT: #ifdef DEBUG only */
1559 msg(gettext("Checkpoint state:\n"));
1560 msg(" blockswritten %u\n", blockswritten
);
1561 msg(" ino %u\n", ino
);
1562 msg(" pos %u\n", pos
);
1563 msg(" left %u\n", leftover
);
1564 msg(" tapea %u\n", (*tapea
));
1565 msg(" state %d\n", dumpstate
);
1568 spcl
.c_type
= TS_TAPE
;
1569 spcl
.c_tpbsize
= tp_bsize
;
1570 if (leftover
== 0) {
1575 newtape
++; /* new volume indication */
1577 msg(gettext("Starting verify pass\n"));
1578 } else if (tapeno
> 1) {
1580 "Volume %d begins with blocks from inode %lu\n"),
1581 tapeno
, chkpt
.sl_inos
);
1583 (void) timeclock((time_t)1);
1584 (void) time(tstart_writing
);
1585 timeest(0, spcl
.c_tapea
);
1597 if (master
&& master
!= getpid())
1599 * signal master to call dumpabort
1601 (void) kill(master
, SIGTERM
);
1605 if (archivefile
&& archive_opened
)
1606 (void) unlink(archivefile
);
1607 msg(gettext("The ENTIRE dump is aborted.\n"));
1616 broadcast(gettext("DUMP IS AILING!\n"));
1618 "Do you want to attempt to continue? (\"yes\" or \"no\") "))) {
1628 * Clean up message system
1632 /* XGETTEXT: #ifdef TDEBUG only */
1633 msg(gettext("pid = %ld exits with status %d\n"),
1634 (long)getpid(), status
);
1646 struct slaves
*slavep
;
1648 for (slavep
= &slaves
[0]; slavep
< &slaves
[SLAVES
]; slavep
++)
1649 if (slavep
->sl_slavepid
> 0) {
1650 (void) kill(slavep
->sl_slavepid
, SIGKILL
);
1653 /* XGETTEXT: #ifdef TDEBUG only */
1654 msg(gettext("Slave child %ld killed\n"),
1655 (long)slavep
->sl_slavepid
);
1659 (void) kill(writepid
, SIGKILL
);
1662 /* XGETTEXT: #ifdef TDEBUG only */
1663 msg(gettext("Writer child %ld killed\n"), (long)writepid
);
1667 (void) kill(archivepid
, SIGKILL
);
1670 /* XGETTEXT: #ifdef TDEBUG only */
1671 msg(gettext("Archiver child %ld killed\n"), (long)archivepid
);
1697 int cmd
[2]; /* file descriptors */
1700 struct slaves
*slavep
;
1703 sv
.sv_flags
= SA_RESTART
;
1704 (void) sigemptyset(&sv
.sa_mask
);
1707 * slave sends SIGTERM on dumpabort
1709 sv
.sv_handler
= (void(*)(int))dumpabort
;
1710 (void) sigvec(SIGTERM
, &sv
, NULL
);
1711 sv
.sv_handler
= tperror
;
1712 (void) sigvec(SIGUSR2
, &sv
, NULL
);
1713 sv
.sv_handler
= proceed
;
1714 (void) sigvec(SIGUSR1
, &sv
, NULL
);
1715 totalrecsout
+= recsout
;
1720 for (slavep
= &slaves
[0]; slavep
< &slaves
[SLAVES
]; slavep
++)
1721 slavep
->sl_slavefd
= -1;
1722 archivefd
= arch
= writer
= -1;
1723 for (i
= 0; i
< SLAVES
; i
++) {
1724 if (pipe(cmd
) < 0) {
1727 "Cannot create pipe for slave process: %s\n"),
1735 if ((slaves
[i
].sl_slavepid
= fork()) < 0) {
1737 msg(gettext("Cannot create slave process: %s\n"),
1742 slaves
[i
].sl_slavefd
= cmd
[1];
1743 if (slaves
[i
].sl_slavepid
== 0) { /* Slave starts up here */
1744 pid_t next
; /* pid of neighbor */
1746 sv
.sv_handler
= SIG_DFL
;
1747 (void) sigvec(SIGUSR2
, &sv
, NULL
);
1748 sv
.sv_handler
= SIG_IGN
; /* master handler INT */
1749 (void) sigvec(SIGINT
, &sv
, NULL
);
1750 sv
.sv_handler
= die
; /* normal slave exit */
1751 (void) sigvec(SIGTERM
, &sv
, NULL
);
1758 freeino(); /* release unneeded resources */
1760 (void) sleep(4); /* time for parent's message to get out */
1761 /* XGETTEXT: #ifdef TDEBUG only */
1762 msg(gettext("Neighbor has pid = %ld\n"), (long)getpid());
1764 /* Closes cmd[1] as a side-effect */
1765 for (slavep
= &slaves
[0];
1766 slavep
< &slaves
[SLAVES
];
1768 if (slavep
->sl_slavefd
>= 0) {
1769 (void) close(slavep
->sl_slavefd
);
1770 slavep
->sl_slavefd
= -1;
1773 (void) close(fi
); /* Need our own seek ptr */
1776 fi
= open(disk
, O_RDONLY
);
1781 "Cannot open dump device `%s': %s\n"),
1782 disk
, strerror(saverr
));
1787 if ((unsigned)atomic((int(*)())read
, cmd
[0],
1788 (char *)&next
, sizeof (next
)) != sizeof (next
)) {
1793 dumpoffline(cmd
[0], next
, i
);
1796 /* Parent continues here */
1800 (void) close(cmd
[0]);
1804 archivepid
= setuparchive();
1811 writepid
= setupwriter();
1818 (void) close(arch
); /* only writer has this open */
1822 /* Tell each slave who follows it */
1823 for (i
= 0; i
< SLAVES
; i
++) {
1824 if ((unsigned)atomic((int(*)())write
, slaves
[i
].sl_slavefd
,
1825 (char *)&(slaves
[(i
+ 1) % SLAVES
].sl_slavepid
),
1826 sizeof (int)) != sizeof (int)) {
1832 sv
.sv_handler
= rollforward
; /* rcvd from writer on EOT */
1833 (void) sigvec(SIGUSR1
, &sv
, NULL
);
1835 (void) kill(slp
->sl_slavepid
, SIGUSR1
);
1846 (void) sighold(SIGUSR1
);
1852 (void) sigpause(SIGUSR1
);
1855 (void) sigrelse(SIGUSR1
);
1859 dumpoffline(int cmd
, pid_t next
, int mynum
)
1861 struct req
*p
= slaves
[mynum
].sl_req
;
1867 blkbuf
= xmalloc(sblock
->fs_bsize
);
1869 /*CONSTANTCONDITION*/
1870 assert(sizeof (spcl
) == TP_BSIZE_MIN
);
1872 while (atomic((int(*)())read
, cmd
, (char *)p
, reqsiz
) == reqsiz
) {
1874 bread(p
->br_dblk
, (uchar_t
*)blkbuf
, p
->br_size
);
1876 bcopy((char *)p
->br_spcl
, (char *)&spcl
,
1878 ino
= spcl
.c_inumber
;
1880 dumptoarchive
= p
->aflag
& BUF_ARCHIVE
;
1883 for (i
= p
->br_size
, cp
= blkbuf
;
1885 /* LINTED character pointers aren't signed */
1886 cp
+= i
> tp_bsize
? tp_bsize
: i
,
1887 i
-= i
> tp_bsize
? tp_bsize
: i
) {
1888 /* LINTED unsigned to signed conversion ok */
1889 taprec(cp
, 0, i
> tp_bsize
? tp_bsize
: (int)i
);
1893 (void) kill(next
, SIGUSR1
); /* Next slave's turn */
1895 * Note that we lie about file activity since we don't
1898 if ((unsigned)atomic((int(*)())write
, cmd
, (char *)¬active
,
1899 sizeof (notactive
)) != sizeof (notactive
)) {
1909 static int count
; /* tape blocks written since last spclrec */
1915 msg(gettext("File size limit exceeded writing output volume %d\n"),
1917 (void) kill(master
, SIGUSR2
);
1921 static long lastnonaddr
; /* last DS_{INODE,CLRI,BITS} written */
1922 static long lastnonaddrm
; /* and the mode thereof */
1924 * dowrite -- the main body of the output writer process
1929 struct bdesc
*last
=
1930 &bufp
[(NBUF
*ntrec
)-1]; /* last buffer in pool */
1931 struct bdesc
*bp
= bufp
; /* current buf in tape block */
1932 struct bdesc
*begin
= bufp
; /* first buf of tape block */
1933 struct bdesc
*end
= bufp
+ (ntrec
-1); /* last buf of tape block */
1934 int siz
; /* bytes written (block) */
1935 int trecs
; /* records written (block) */
1936 long asize
= 0; /* number of 0.1" units... */
1937 /* ...written on current tape */
1938 char *tp
, *rbuf
= NULL
;
1939 char *recmap
= spcl
.c_addr
; /* current tape record map */
1940 char *endmp
; /* end of valid map data */
1941 char *mp
; /* current map entry */
1944 (void) signal(SIGXFSZ
, onxfsz
);
1946 bzero((char *)&spcl
, sizeof (spcl
));
1950 rbuf
= (char *)malloc((uint_t
)writesize
);
1952 /* Restart from checkpoint */
1953 (void) kill(master
, SIGUSR2
);
1959 /* START: wait until all buffers in tape block are full */
1960 if ((bp
->b_flags
& BUF_FULL
) == 0) {
1961 if (caught
) { /* master signalled flush */
1962 (void) sighold(SIGUSR1
);
1965 (void) kill(master
, SIGUSR1
);
1966 chkpt
.sl_count
= 0; /* signal not at EOT */
1967 checkpoint(bp
-1, cmd
); /* send data */
1968 (void) sigpause(SIGUSR1
);
1981 /* END: wait until all buffers in tape block are full */
1984 (void) sighold(SIGUSR1
);
1986 siz
= write(to
, tp
, writesize
);
1987 else if ((siz
= read(to
, rbuf
, writesize
)) ==
1988 writesize
&& bcmp(rbuf
, tp
, writesize
))
1990 if (siz
< 0 && diskette
&& errno
== ENOSPC
)
1991 siz
= 0; /* really EOF */
1992 (void) sigrelse(SIGUSR1
);
1994 (pipeout
&& siz
!= writesize
)) {
1998 * Isn't i18n wonderful?
2002 (void) snprintf(buf
, sizeof (buf
),
2004 "Verification error %ld blocks into diskette %d\n"),
2007 (void) snprintf(buf
, sizeof (buf
),
2009 "Verification error %ld feet into tape %d\n"),
2010 (cartridge
? asize
/tracks
:
2014 (void) snprintf(buf
, sizeof (buf
),
2016 "Verification error %ld blocks into volume %d\n"),
2021 (void) snprintf(buf
, sizeof (buf
),
2023 "Write error %ld blocks into diskette %d\n"),
2026 (void) snprintf(buf
, sizeof (buf
),
2028 "Write error %ld feet into tape %d\n"),
2029 (cartridge
? asize
/tracks
:
2030 asize
)/120L, tapeno
);
2032 (void) snprintf(buf
, sizeof (buf
),
2034 "Write error %ld blocks into volume %d\n"),
2039 /* Restart from checkpoint */
2042 /* XGETTEXT: #ifdef TDEBUG only */
2043 msg(gettext("sending SIGUSR2 to pid %ld\n"), master
);
2045 (void) kill(master
, SIGUSR2
);
2048 trecs
= siz
/ tp_bsize
;
2050 asize
+= trecs
; /* asize == blocks written */
2052 asize
+= (siz
/density
+ tenthsperirg
);
2054 chkpt
.sl_firstrec
++;
2055 for (bp
= begin
; bp
< begin
+ trecs
; bp
++) {
2056 if ((arch
>= 0) && (bp
->b_flags
& BUF_ARCHIVE
)) {
2057 if ((unsigned)atomic((int(*)())write
, arch
,
2058 (char *)&bp
->b_flags
, sizeof (bp
->b_flags
))
2059 != sizeof (bp
->b_flags
)) {
2064 if (atomic((int(*)())write
, arch
, bp
->b_data
,
2065 tp_bsize
) != tp_bsize
) {
2071 if (bp
->b_flags
& BUF_SPCLREC
) {
2072 /*LINTED [bp->b_data is aligned]*/
2073 sp
= (union u_spcl
*)bp
->b_data
;
2074 if (sp
->s_spcl
.c_type
!= TS_ADDR
) {
2075 lastnonaddr
= sp
->s_spcl
.c_type
;
2077 sp
->s_spcl
.c_dinode
.di_mode
;
2078 if (sp
->s_spcl
.c_type
!= TS_TAPE
)
2079 chkpt
.sl_offset
= 0;
2081 chkpt
.sl_count
= sp
->s_spcl
.c_count
;
2083 (char *)&spcl
, sizeof (spcl
));
2085 endmp
= &recmap
[spcl
.c_count
];
2094 * Adjust for contiguous hole
2096 for (; mp
< endmp
; mp
++) {
2104 * Check for end of tape
2106 if (trecs
< ntrec
||
2107 (!pipeout
&& tsize
> 0 && asize
> tsize
)) {
2109 msg(gettext("End-of-tape detected\n"));
2111 msg(gettext("End-of-file detected\n"));
2112 (void) sighold(SIGUSR1
);
2114 (void) kill(master
, SIGUSR1
); /* signal EOT */
2115 checkpoint(--bp
, cmd
); /* send checkpoint data */
2116 (void) sigpause(SIGUSR1
);
2119 for (bp
= begin
; bp
<= end
; bp
++)
2120 bp
->b_flags
= BUF_EMPTY
;
2121 if (end
+ ntrec
> last
) {
2123 timeest(0, spcl
.c_tapea
);
2126 end
= begin
+ (ntrec
-1);
2133 * Send checkpoint info back to master. This information
2134 * consists of the current inode number, number of logical
2135 * blocks written for that inode (or bitmap), the last logical
2136 * block number written, the number of logical blocks written
2137 * to this volume, the current dump state, and the current
2138 * special record map.
2141 checkpoint(struct bdesc
*bp
, int cmd
)
2146 if (++bp
>= &bufp
[NBUF
*ntrec
])
2150 * If we are dumping files and the record following
2151 * the last written to tape is a special record, use
2152 * it to get an accurate indication of current state.
2154 if ((bp
->b_flags
& BUF_SPCLREC
) && (bp
->b_flags
& BUF_FULL
) &&
2155 lastnonaddr
== TS_INODE
) {
2156 /*LINTED [bp->b_data is aligned]*/
2157 union u_spcl
*nextspcl
= (union u_spcl
*)bp
->b_data
;
2159 if (nextspcl
->s_spcl
.c_type
== TS_INODE
) {
2160 chkpt
.sl_offset
= 0;
2162 } else if (nextspcl
->s_spcl
.c_type
== TS_END
) {
2163 chkpt
.sl_offset
= 0;
2164 chkpt
.sl_count
= 1; /* EOT indicator */
2166 ino
= nextspcl
->s_spcl
.c_inumber
;
2167 type
= nextspcl
->s_spcl
.c_type
;
2170 * If not, use what we have.
2172 ino
= spcl
.c_inumber
;
2176 switch (type
) { /* set output state */
2178 switch (lastnonaddr
) {
2181 if ((lastnonaddrm
& IFMT
) == IFDIR
||
2182 (lastnonaddrm
& IFMT
) == IFATTRDIR
)
2196 if ((spcl
.c_dinode
.di_mode
& IFMT
) == IFDIR
||
2197 (spcl
.c_dinode
.di_mode
& IFMT
) == IFATTRDIR
)
2202 case 0: /* EOT on 1st record */
2214 if (spcl
.c_type
== TS_END
)
2222 * Checkpoint info to be processed by rollforward():
2223 * The inode with which the next volume should begin
2224 * The last inode number on this volume
2225 * The last logical block number on this volume
2226 * The current output state
2227 * The offset within the current inode (already in sl_offset)
2228 * The number of records left from last spclrec (in sl_count)
2229 * The physical block the next vol begins with (in sl_firstrec)
2231 chkpt
.sl_inos
= ino
;
2232 chkpt
.sl_tapea
= spcl
.c_tapea
+ count
;
2233 chkpt
.sl_state
= state
;
2235 if ((unsigned)atomic((int(*)())write
, cmd
, (char *)&chkpt
,
2236 sizeof (chkpt
)) != sizeof (chkpt
)) {
2241 if ((unsigned)atomic((int(*)())write
, cmd
, (char *)&spcl
,
2242 sizeof (spcl
)) != sizeof (spcl
)) {
2249 /* XGETTEXT: #ifdef DEBUG only */
2250 msg(gettext("sent chkpt to master:\n"));
2251 msg(" ino %u\n", chkpt
.sl_inos
);
2252 msg(" 1strec %u\n", chkpt
.sl_firstrec
);
2253 msg(" lastrec %u\n", chkpt
.sl_tapea
);
2254 msg(" written %u\n", chkpt
.sl_offset
);
2255 msg(" left %u\n", chkpt
.sl_count
);
2256 msg(" state %d\n", chkpt
.sl_state
);
2262 * Since a read from a pipe may not return all we asked for,
2263 * or a write may not write all we ask if we get a signal,
2264 * loop until the count is satisfied (or error).
2267 atomic(int (*func
)(), int fd
, char *buf
, int count
)
2269 ssize_t got
= 0, need
= count
;
2271 /* don't inherit random value if immediately get zero back from func */
2274 got
= (*func
)(fd
, buf
, MIN(need
, 4096));
2275 if (got
< 0 && errno
== EINTR
)
2282 /* if we got what was asked for, return count, else failure (got) */
2283 return ((need
!= 0) ? got
: count
);
2288 positiontape(char *msgbuf
)
2290 positiontape(char *msgbuf
)
2293 /* Static as never change, no need to waste stack space */
2294 static struct mtget mt
;
2295 static struct mtop rew
= { MTREW
, 1 };
2296 static struct mtop fsf
= { MTFSF
, 1 };
2297 char *info
= strdup(gettext("Positioning `%s' to file %ld\n"));
2298 char *fail
= strdup(gettext("Cannot position tape to file %d\n"));
2301 /* gettext()'s return value is volatile, hence the strdup()s */
2303 m
= (access(tape
, F_OK
) == 0) ? 0 : O_CREAT
;
2306 * To avoid writing tape marks at inappropriate places, we open the
2307 * device read-only, position it, close it, and reopen it for writing.
2309 while ((to
= safe_device_open(tape
, O_RDONLY
|m
, 0600)) < 0) {
2311 if (!query_once(msgbuf
, 1)) {
2316 if (!query(msgbuf
)) {
2323 if (ioctl(to
, MTIOCGET
, &mt
) >= 0 &&
2324 ioctl(to
, MTIOCTOP
, &rew
) >= 0 &&
2326 msg(info
, dumpdev
, filenum
);
2327 fsf
.mt_count
= filenum
- 1;
2328 if (ioctl(to
, MTIOCTOP
, &fsf
) < 0) {
2349 msg(gettext("Error writing command pipe: %s\n"), strerror(saverr
));
2360 msg(gettext("Error reading command pipe: %s\n"), strerror(saverr
));