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
= (ino32_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
= (ino32_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.
1075 if (fstat64(f
, &sbuf
) < 0) {
1077 "Cannot obtain status of output device `%s'\n"),
1082 rewind
= minor(sbuf
.st_rdev
) & MT_NOREWIND
? 0 : 1;
1093 struct slaves
*slavep
;
1094 char *rewinding
= gettext("Tape rewinding\n");
1096 for (slavep
= &slaves
[0]; slavep
< &slaves
[SLAVES
]; slavep
++) {
1097 if (slavep
->sl_slavepid
> 0) /* signal normal exit */
1098 (void) kill(slavep
->sl_slavepid
, SIGTERM
);
1099 if (slavep
->sl_slavefd
>= 0) {
1100 (void) close(slavep
->sl_slavefd
);
1101 slavep
->sl_slavefd
= -1;
1105 /* wait for any signals from slaves */
1106 while (waitpid(0, (int *)0, 0) >= 0)
1107 /*LINTED [empty body]*/
1115 * Space to the end of the tape.
1116 * Backup first in case we already read the EOF.
1118 static struct mtop bsr
= { MTBSR
, 1 };
1119 static struct mtop eom
= { MTEOM
, 1 };
1120 static struct mtop fsf
= { MTFSF
, 1 };
1122 (void) ioctl(to
, MTIOCTOP
, &bsr
);
1123 if (ioctl(to
, MTIOCTOP
, &eom
) < 0)
1124 (void) ioctl(to
, MTIOCTOP
, &fsf
);
1128 * Guess whether the tape is rewinding so we can tell
1129 * the operator if it's going to take a long time.
1131 if (tapeout
&& isrewind(to
)) {
1132 /* tape is probably rewinding */
1144 (void) timeclock((time_t)0);
1145 if (offline
&& (!verify
|| doingverify
)) {
1160 char *rewinding
= gettext("Tape rewinding\n");
1162 (void) timeclock((time_t)0);
1165 * The check in just_rewind won't catch the case in
1166 * which the current volume is being taken off-line
1167 * and is not mounted on a no-rewind device (and is
1168 * not the last volume, which is not taken off-line).
1170 if (tapeout
&& !isrewind(to
) && offline
) {
1171 /* tape is probably rewinding */
1174 if (offline
|| autoload
) {
1175 static struct mtop offl
= { MTOFFL
, 0 };
1177 (void) ioctl(to
, MTIOCTOP
, &offl
);
1179 (void) ioctl(to
, FDEJECT
, 0);
1192 char buf1
[3000], buf2
[3000];
1193 char volname
[LBLSIZE
+1];
1195 /*CONSTANTCONDITION*/
1196 assert(sizeof (spcl
.c_label
) < sizeof (volname
));
1200 (void) strcpy(spcl
.c_label
, tlabel
);
1202 * Make volume switching as automatic as possible
1203 * while avoiding overwriting volumes. We will
1204 * switch automatically under the following condition:
1205 * 1) The user specified autoloading from the
1207 * At one time, we (in the guise of hsmdump) had the
1208 * concept of a sequence of devices to rotate through,
1209 * but that's never been a ufsdump feature.
1215 * Stop the clock for throughput calculations.
1217 if ((telapsed
!= NULL
) && (tstart_writing
!= NULL
)) {
1218 *telapsed
+= time(NULL
) - *tstart_writing
;
1221 (void) snprintf(volname
, sizeof (volname
), "#%d", tapeno
+1);
1222 (void) snprintf(buf1
, sizeof (buf1
), gettext(
1223 "Mounting volume %s on %s\n"), volname
, dumpdev
);
1228 * Wait for the tape to autoload. Note that the delay
1229 * period doesn't take into account however long it takes
1230 * for the open to fail (measured at 21 seconds for an
1231 * Exabyte 8200 under 2.7 on an Ultra 2).
1233 for (tries
= 0; tries
< autoload_tries
; tries
++) {
1236 m
= (access(tape
, F_OK
) == 0) ? 0 : O_CREAT
;
1237 if ((f
= doingverify
?
1238 safe_device_open(tape
, O_RDONLY
, 0600) :
1239 safe_device_open(tape
, O_RDONLY
|m
, 0600))
1244 (void) sleep(autoload_period
);
1247 * Autoload timed out, ask the operator to do it.
1248 * Note that query() will update *telapsed, and we
1249 * shouldn't charge for the autoload time. So, since
1250 * we updated *telapsed ourselves above, we just set
1251 * tstart_writing to the current time, and query()
1252 * will end up making a null-effect change. This,
1253 * of course, assumes that our caller will be resetting
1254 * *tstart_writing. This is currently the case.
1255 * If tstart_writing is NULL (should never happen),
1256 * we're ok, since time(2) will accept a NULL pointer.
1258 (void) time(tstart_writing
);
1261 if (strncmp(spcl
.c_label
, "none", 5)) {
1262 (void) strncpy(volname
, spcl
.c_label
, sizeof (spcl
.c_label
));
1263 volname
[sizeof (spcl
.c_label
)] = '\0';
1265 (void) snprintf(volname
, sizeof (volname
), "#%d", tapeno
+1);
1267 timeest(1, spcl
.c_tapea
);
1268 (void) snprintf(buf1
, sizeof (buf1
), gettext(
1269 "Change Volumes: Mount volume `%s' on `%s'\n"), volname
, dumpdev
);
1271 broadcast(gettext("CHANGE VOLUMES!\7\7\n"));
1272 (void) snprintf(buf1
, sizeof (buf1
), gettext(
1273 "Is the new volume (%s) mounted on `%s' and ready to go?: %s"),
1274 volname
, dumpdev
, gettext("(\"yes\" or \"no\") "));
1275 while (!query(buf1
)) {
1276 (void) snprintf(buf2
, sizeof (buf2
), gettext(
1277 "Do you want to abort dump?: (\"yes\" or \"no\") "));
1286 * We implement taking and restoring checkpoints on the tape level.
1287 * When each tape is opened, a new process is created by forking; this
1288 * saves all of the necessary context in the parent. The child
1289 * continues the dump; the parent waits around, saving the context.
1290 * If the child returns X_REWRITE, then it had problems writing that tape;
1291 * this causes the parent to fork again, duplicating the context, and
1292 * everything continues as if nothing had happened.
1298 static struct mtget mt
;
1304 struct sigvec sv
, osv
;
1306 sv
.sv_flags
= SA_RESTART
;
1307 (void) sigemptyset(&sv
.sa_mask
);
1308 sv
.sv_handler
= SIG_IGN
;
1309 (void) sigvec(SIGINT
, &sv
, NULL
);
1311 parentpid
= getpid();
1319 restore_check_point
:
1321 sv
.sv_handler
= interrupt
;
1322 (void) sigvec(SIGINT
, &sv
, NULL
);
1323 (void) fflush(stderr
);
1325 * All signals are inherited...
1331 "Context-saving fork failed in parent %ld\n"),
1335 if (childpid
!= 0) {
1338 * save the context by waiting
1339 * until the child doing all of the work returns.
1340 * let the child catch user interrupts
1342 sv
.sv_handler
= SIG_IGN
;
1343 (void) sigvec(SIGINT
, &sv
, NULL
);
1347 /* XGETTEXT: #ifdef TDEBUG only */
1349 "Volume: %d; parent process: %ld child process %ld\n"),
1350 tapeno
+1, (long)parentpid
, (long)childpid
);
1353 waitproc
= waitpid(0, &status
, 0);
1354 if (waitproc
== childpid
)
1357 "Parent %ld waiting for child %ld had another child %ld return\n"),
1358 (long)parentpid
, (long)childpid
, (long)waitproc
);
1360 if (WIFSIGNALED(status
)) {
1361 msg(gettext("Process %ld killed by signal %d: %s\n"),
1362 (long)childpid
, WTERMSIG(status
),
1363 strsignal(WTERMSIG(status
)));
1366 status
= WEXITSTATUS(status
);
1370 /* XGETTEXT: #ifdef TDEBUG only */
1372 "Child %ld finishes X_FINOK\n"), (long)childpid
);
1375 /* XGETTEXT: #ifdef TDEBUG only */
1377 "Child %ld finishes X_ABORT\n"), (long)childpid
);
1380 /* XGETTEXT: #ifdef TDEBUG only */
1382 "Child %ld finishes X_REWRITE\n"), (long)childpid
);
1385 /* XGETTEXT: #ifdef TDEBUG only */
1387 "Child %ld finishes X_RESTART\n"), (long)childpid
);
1390 /* XGETTEXT: #ifdef TDEBUG only */
1392 "Child %ld finishes X_VERIFY\n"), (long)childpid
);
1395 /* XGETTEXT: #ifdef TDEBUG only */
1396 msg(gettext("Child %ld finishes unknown %d\n"),
1397 (long)childpid
, status
);
1403 /* wait for children */
1404 while (waitpid(0, (int *)0, 0) >= 0)
1405 /*LINTED [empty body]*/
1414 goto restore_check_point
;
1419 goto restore_check_point
;
1429 sv
.sv_handler
= interrupt
;
1430 (void) sigvec(SIGINT
, &sv
, NULL
);
1434 msg(gettext("Bad return code from dump: %d\n"), status
);
1439 } else { /* we are the child; just continue */
1443 (void) sleep(4); /* time for parent's message to get out */
1444 /* XGETTEXT: #ifdef TDEBUG only */
1446 "Child on Volume %d has parent %ld, my pid = %ld\n"),
1447 tapeno
+1, (long)parentpid
, (long)getpid());
1449 (void) snprintf(buf
, sizeof (buf
), gettext(
1450 "Cannot open `%s'. Do you want to retry the open?: (\"yes\" or \"no\") "),
1454 while ((to
= pipeout
? 1 :
1455 safe_device_open(tape
, O_RDONLY
, 0600)) < 0) {
1458 if (!query_once(buf
, 1)) {
1471 * If we're using the non-rewinding tape device,
1472 * the tape will be left positioned after the
1473 * EOF mark. We need to back up to the beginning
1474 * of this tape file (cross two tape marks in the
1475 * reverse direction and one in the forward
1476 * direction) before the verify pass.
1478 static struct mtop bsf
= { MTBSF
, 2 };
1479 static struct mtop fsf
= { MTFSF
, 1 };
1480 static struct mtop nbsf
= { MTNBSF
, 1 };
1482 if (ioctl(to
, MTIOCTOP
, &bsf
) >= 0)
1483 (void) ioctl(to
, MTIOCTOP
, &fsf
);
1485 (void) ioctl(to
, MTIOCTOP
, &nbsf
);
1488 * XXX Add logic to test for "tape" being a
1489 * XXX device or a non-existent file.
1490 * Current behaviour is that it must exist,
1491 * and we over-write whatever's there.
1492 * This can be bad if tape == "/etc/passwd".
1494 if (!pipeout
&& doposition
&& (tapeno
== 0)) {
1496 if (setjmp(alrm_buf
)) {
1498 * The tape is rewinding;
1502 "Cannot position tape using rewind device!\n"));
1506 sv
.sv_handler
= alrm
;
1507 (void) sigvec(SIGALRM
, &sv
, &osv
);
1510 while ((to
= safe_device_open(tape
, O_WRONLY
,
1514 (void) sigvec(SIGALRM
, &osv
,
1518 m
= (access(tape
, F_OK
) == 0) ? 0 : O_CREAT
;
1520 * Only verify the tape label if label
1521 * verification is on and we are at BOT
1525 else while ((to
= safe_device_open(tape
,
1526 O_WRONLY
|m
, 0600)) < 0)
1527 if (!query_once(buf
, 1)) {
1534 tapeout
= ioctl(to
, MTIOCGET
, &mt
) >= 0; /* set state */
1536 * Make sure the tape is positioned
1537 * where it is supposed to be
1539 if (tapeout
&& (tapeno
> 0) &&
1540 (mt
.mt_fileno
!= (filenum
-1))) {
1541 (void) snprintf(buf
, sizeof (buf
), gettext(
1542 "Warning - tape positioning error!\n\
1543 \t%s current file %ld, should be %ld\n"),
1544 tape
, mt
.mt_fileno
+1, filenum
);
1549 tapeno
++; /* current tape sequence */
1550 if (tapeno
< TP_NINOS
)
1551 inos
[tapeno
] = chkpt
.sl_inos
;
1552 spcl
.c_firstrec
= chkpt
.sl_firstrec
;
1553 spcl
.c_tapea
= (*tapea
) = chkpt
.sl_tapea
;
1556 enslave(); /* Share tape buffers with slaves */
1560 /* XGETTEXT: #ifdef DEBUG only */
1561 msg(gettext("Checkpoint state:\n"));
1562 msg(" blockswritten %u\n", blockswritten
);
1563 msg(" ino %u\n", ino
);
1564 msg(" pos %u\n", pos
);
1565 msg(" left %u\n", leftover
);
1566 msg(" tapea %u\n", (*tapea
));
1567 msg(" state %d\n", dumpstate
);
1570 spcl
.c_type
= TS_TAPE
;
1571 spcl
.c_tpbsize
= tp_bsize
;
1572 if (leftover
== 0) {
1577 newtape
++; /* new volume indication */
1579 msg(gettext("Starting verify pass\n"));
1580 } else if (tapeno
> 1) {
1582 "Volume %d begins with blocks from inode %lu\n"),
1583 tapeno
, chkpt
.sl_inos
);
1585 (void) timeclock((time_t)1);
1586 (void) time(tstart_writing
);
1587 timeest(0, spcl
.c_tapea
);
1599 if (master
&& master
!= getpid())
1601 * signal master to call dumpabort
1603 (void) kill(master
, SIGTERM
);
1607 if (archivefile
&& archive_opened
)
1608 (void) unlink(archivefile
);
1609 msg(gettext("The ENTIRE dump is aborted.\n"));
1618 broadcast(gettext("DUMP IS AILING!\n"));
1620 "Do you want to attempt to continue? (\"yes\" or \"no\") "))) {
1630 * Clean up message system
1634 /* XGETTEXT: #ifdef TDEBUG only */
1635 msg(gettext("pid = %ld exits with status %d\n"),
1636 (long)getpid(), status
);
1648 struct slaves
*slavep
;
1650 for (slavep
= &slaves
[0]; slavep
< &slaves
[SLAVES
]; slavep
++)
1651 if (slavep
->sl_slavepid
> 0) {
1652 (void) kill(slavep
->sl_slavepid
, SIGKILL
);
1655 /* XGETTEXT: #ifdef TDEBUG only */
1656 msg(gettext("Slave child %ld killed\n"),
1657 (long)slavep
->sl_slavepid
);
1661 (void) kill(writepid
, SIGKILL
);
1664 /* XGETTEXT: #ifdef TDEBUG only */
1665 msg(gettext("Writer child %ld killed\n"), (long)writepid
);
1669 (void) kill(archivepid
, SIGKILL
);
1672 /* XGETTEXT: #ifdef TDEBUG only */
1673 msg(gettext("Archiver child %ld killed\n"), (long)archivepid
);
1699 int cmd
[2]; /* file descriptors */
1702 struct slaves
*slavep
;
1705 sv
.sv_flags
= SA_RESTART
;
1706 (void) sigemptyset(&sv
.sa_mask
);
1709 * slave sends SIGTERM on dumpabort
1711 sv
.sv_handler
= (void(*)(int))dumpabort
;
1712 (void) sigvec(SIGTERM
, &sv
, NULL
);
1713 sv
.sv_handler
= tperror
;
1714 (void) sigvec(SIGUSR2
, &sv
, NULL
);
1715 sv
.sv_handler
= proceed
;
1716 (void) sigvec(SIGUSR1
, &sv
, NULL
);
1717 totalrecsout
+= recsout
;
1722 for (slavep
= &slaves
[0]; slavep
< &slaves
[SLAVES
]; slavep
++)
1723 slavep
->sl_slavefd
= -1;
1724 archivefd
= arch
= writer
= -1;
1725 for (i
= 0; i
< SLAVES
; i
++) {
1726 if (pipe(cmd
) < 0) {
1729 "Cannot create pipe for slave process: %s\n"),
1737 if ((slaves
[i
].sl_slavepid
= fork()) < 0) {
1739 msg(gettext("Cannot create slave process: %s\n"),
1744 slaves
[i
].sl_slavefd
= cmd
[1];
1745 if (slaves
[i
].sl_slavepid
== 0) { /* Slave starts up here */
1746 pid_t next
; /* pid of neighbor */
1748 sv
.sv_handler
= SIG_DFL
;
1749 (void) sigvec(SIGUSR2
, &sv
, NULL
);
1750 sv
.sv_handler
= SIG_IGN
; /* master handler INT */
1751 (void) sigvec(SIGINT
, &sv
, NULL
);
1752 sv
.sv_handler
= die
; /* normal slave exit */
1753 (void) sigvec(SIGTERM
, &sv
, NULL
);
1760 freeino(); /* release unneeded resources */
1762 (void) sleep(4); /* time for parent's message to get out */
1763 /* XGETTEXT: #ifdef TDEBUG only */
1764 msg(gettext("Neighbor has pid = %ld\n"), (long)getpid());
1766 /* Closes cmd[1] as a side-effect */
1767 for (slavep
= &slaves
[0];
1768 slavep
< &slaves
[SLAVES
];
1770 if (slavep
->sl_slavefd
>= 0) {
1771 (void) close(slavep
->sl_slavefd
);
1772 slavep
->sl_slavefd
= -1;
1775 (void) close(fi
); /* Need our own seek ptr */
1778 fi
= open(disk
, O_RDONLY
);
1783 "Cannot open dump device `%s': %s\n"),
1784 disk
, strerror(saverr
));
1789 if ((unsigned)atomic((int(*)())read
, cmd
[0],
1790 (char *)&next
, sizeof (next
)) != sizeof (next
)) {
1795 dumpoffline(cmd
[0], next
, i
);
1798 /* Parent continues here */
1802 (void) close(cmd
[0]);
1806 archivepid
= setuparchive();
1813 writepid
= setupwriter();
1820 (void) close(arch
); /* only writer has this open */
1824 /* Tell each slave who follows it */
1825 for (i
= 0; i
< SLAVES
; i
++) {
1826 if ((unsigned)atomic((int(*)())write
, slaves
[i
].sl_slavefd
,
1827 (char *)&(slaves
[(i
+ 1) % SLAVES
].sl_slavepid
),
1828 sizeof (int)) != sizeof (int)) {
1834 sv
.sv_handler
= rollforward
; /* rcvd from writer on EOT */
1835 (void) sigvec(SIGUSR1
, &sv
, NULL
);
1837 (void) kill(slp
->sl_slavepid
, SIGUSR1
);
1848 (void) sighold(SIGUSR1
);
1854 (void) sigpause(SIGUSR1
);
1857 (void) sigrelse(SIGUSR1
);
1861 dumpoffline(int cmd
, pid_t next
, int mynum
)
1863 struct req
*p
= slaves
[mynum
].sl_req
;
1869 blkbuf
= xmalloc(sblock
->fs_bsize
);
1871 /*CONSTANTCONDITION*/
1872 assert(sizeof (spcl
) == TP_BSIZE_MIN
);
1874 while (atomic((int(*)())read
, cmd
, (char *)p
, reqsiz
) == reqsiz
) {
1876 bread(p
->br_dblk
, (uchar_t
*)blkbuf
, p
->br_size
);
1878 bcopy((char *)p
->br_spcl
, (char *)&spcl
,
1880 ino
= spcl
.c_inumber
;
1882 dumptoarchive
= p
->aflag
& BUF_ARCHIVE
;
1885 for (i
= p
->br_size
, cp
= blkbuf
;
1887 /* LINTED character pointers aren't signed */
1888 cp
+= i
> tp_bsize
? tp_bsize
: i
,
1889 i
-= i
> tp_bsize
? tp_bsize
: i
) {
1890 /* LINTED unsigned to signed conversion ok */
1891 taprec(cp
, 0, i
> tp_bsize
? tp_bsize
: (int)i
);
1895 (void) kill(next
, SIGUSR1
); /* Next slave's turn */
1897 * Note that we lie about file activity since we don't
1900 if ((unsigned)atomic((int(*)())write
, cmd
, (char *)¬active
,
1901 sizeof (notactive
)) != sizeof (notactive
)) {
1911 static int count
; /* tape blocks written since last spclrec */
1917 msg(gettext("File size limit exceeded writing output volume %d\n"),
1919 (void) kill(master
, SIGUSR2
);
1923 static long lastnonaddr
; /* last DS_{INODE,CLRI,BITS} written */
1924 static long lastnonaddrm
; /* and the mode thereof */
1926 * dowrite -- the main body of the output writer process
1931 struct bdesc
*last
=
1932 &bufp
[(NBUF
*ntrec
)-1]; /* last buffer in pool */
1933 struct bdesc
*bp
= bufp
; /* current buf in tape block */
1934 struct bdesc
*begin
= bufp
; /* first buf of tape block */
1935 struct bdesc
*end
= bufp
+ (ntrec
-1); /* last buf of tape block */
1936 int siz
; /* bytes written (block) */
1937 int trecs
; /* records written (block) */
1938 long asize
= 0; /* number of 0.1" units... */
1939 /* ...written on current tape */
1940 char *tp
, *rbuf
= NULL
;
1941 char *recmap
= spcl
.c_addr
; /* current tape record map */
1942 char *endmp
; /* end of valid map data */
1943 char *mp
; /* current map entry */
1946 (void) signal(SIGXFSZ
, onxfsz
);
1948 bzero((char *)&spcl
, sizeof (spcl
));
1952 rbuf
= (char *)malloc((uint_t
)writesize
);
1954 /* Restart from checkpoint */
1955 (void) kill(master
, SIGUSR2
);
1961 /* START: wait until all buffers in tape block are full */
1962 if ((bp
->b_flags
& BUF_FULL
) == 0) {
1963 if (caught
) { /* master signalled flush */
1964 (void) sighold(SIGUSR1
);
1967 (void) kill(master
, SIGUSR1
);
1968 chkpt
.sl_count
= 0; /* signal not at EOT */
1969 checkpoint(bp
-1, cmd
); /* send data */
1970 (void) sigpause(SIGUSR1
);
1983 /* END: wait until all buffers in tape block are full */
1986 (void) sighold(SIGUSR1
);
1988 siz
= write(to
, tp
, writesize
);
1989 else if ((siz
= read(to
, rbuf
, writesize
)) ==
1990 writesize
&& bcmp(rbuf
, tp
, writesize
))
1992 if (siz
< 0 && diskette
&& errno
== ENOSPC
)
1993 siz
= 0; /* really EOF */
1994 (void) sigrelse(SIGUSR1
);
1996 (pipeout
&& siz
!= writesize
)) {
2000 * Isn't i18n wonderful?
2004 (void) snprintf(buf
, sizeof (buf
),
2006 "Verification error %ld blocks into diskette %d\n"),
2009 (void) snprintf(buf
, sizeof (buf
),
2011 "Verification error %ld feet into tape %d\n"),
2012 (cartridge
? asize
/tracks
:
2016 (void) snprintf(buf
, sizeof (buf
),
2018 "Verification error %ld blocks into volume %d\n"),
2023 (void) snprintf(buf
, sizeof (buf
),
2025 "Write error %ld blocks into diskette %d\n"),
2028 (void) snprintf(buf
, sizeof (buf
),
2030 "Write error %ld feet into tape %d\n"),
2031 (cartridge
? asize
/tracks
:
2032 asize
)/120L, tapeno
);
2034 (void) snprintf(buf
, sizeof (buf
),
2036 "Write error %ld blocks into volume %d\n"),
2041 /* Restart from checkpoint */
2044 /* XGETTEXT: #ifdef TDEBUG only */
2045 msg(gettext("sending SIGUSR2 to pid %ld\n"), master
);
2047 (void) kill(master
, SIGUSR2
);
2050 trecs
= siz
/ tp_bsize
;
2052 asize
+= trecs
; /* asize == blocks written */
2054 asize
+= (siz
/density
+ tenthsperirg
);
2056 chkpt
.sl_firstrec
++;
2057 for (bp
= begin
; bp
< begin
+ trecs
; bp
++) {
2058 if ((arch
>= 0) && (bp
->b_flags
& BUF_ARCHIVE
)) {
2059 if ((unsigned)atomic((int(*)())write
, arch
,
2060 (char *)&bp
->b_flags
, sizeof (bp
->b_flags
))
2061 != sizeof (bp
->b_flags
)) {
2066 if (atomic((int(*)())write
, arch
, bp
->b_data
,
2067 tp_bsize
) != tp_bsize
) {
2073 if (bp
->b_flags
& BUF_SPCLREC
) {
2074 /*LINTED [bp->b_data is aligned]*/
2075 sp
= (union u_spcl
*)bp
->b_data
;
2076 if (sp
->s_spcl
.c_type
!= TS_ADDR
) {
2077 lastnonaddr
= sp
->s_spcl
.c_type
;
2079 sp
->s_spcl
.c_dinode
.di_mode
;
2080 if (sp
->s_spcl
.c_type
!= TS_TAPE
)
2081 chkpt
.sl_offset
= 0;
2083 chkpt
.sl_count
= sp
->s_spcl
.c_count
;
2085 (char *)&spcl
, sizeof (spcl
));
2087 endmp
= &recmap
[spcl
.c_count
];
2096 * Adjust for contiguous hole
2098 for (; mp
< endmp
; mp
++) {
2106 * Check for end of tape
2108 if (trecs
< ntrec
||
2109 (!pipeout
&& tsize
> 0 && asize
> tsize
)) {
2111 msg(gettext("End-of-tape detected\n"));
2113 msg(gettext("End-of-file detected\n"));
2114 (void) sighold(SIGUSR1
);
2116 (void) kill(master
, SIGUSR1
); /* signal EOT */
2117 checkpoint(--bp
, cmd
); /* send checkpoint data */
2118 (void) sigpause(SIGUSR1
);
2121 for (bp
= begin
; bp
<= end
; bp
++)
2122 bp
->b_flags
= BUF_EMPTY
;
2123 if (end
+ ntrec
> last
) {
2125 timeest(0, spcl
.c_tapea
);
2128 end
= begin
+ (ntrec
-1);
2135 * Send checkpoint info back to master. This information
2136 * consists of the current inode number, number of logical
2137 * blocks written for that inode (or bitmap), the last logical
2138 * block number written, the number of logical blocks written
2139 * to this volume, the current dump state, and the current
2140 * special record map.
2143 checkpoint(struct bdesc
*bp
, int cmd
)
2148 if (++bp
>= &bufp
[NBUF
*ntrec
])
2152 * If we are dumping files and the record following
2153 * the last written to tape is a special record, use
2154 * it to get an accurate indication of current state.
2156 if ((bp
->b_flags
& BUF_SPCLREC
) && (bp
->b_flags
& BUF_FULL
) &&
2157 lastnonaddr
== TS_INODE
) {
2158 /*LINTED [bp->b_data is aligned]*/
2159 union u_spcl
*nextspcl
= (union u_spcl
*)bp
->b_data
;
2161 if (nextspcl
->s_spcl
.c_type
== TS_INODE
) {
2162 chkpt
.sl_offset
= 0;
2164 } else if (nextspcl
->s_spcl
.c_type
== TS_END
) {
2165 chkpt
.sl_offset
= 0;
2166 chkpt
.sl_count
= 1; /* EOT indicator */
2168 ino
= nextspcl
->s_spcl
.c_inumber
;
2169 type
= nextspcl
->s_spcl
.c_type
;
2172 * If not, use what we have.
2174 ino
= spcl
.c_inumber
;
2178 switch (type
) { /* set output state */
2180 switch (lastnonaddr
) {
2183 if ((lastnonaddrm
& IFMT
) == IFDIR
||
2184 (lastnonaddrm
& IFMT
) == IFATTRDIR
)
2198 if ((spcl
.c_dinode
.di_mode
& IFMT
) == IFDIR
||
2199 (spcl
.c_dinode
.di_mode
& IFMT
) == IFATTRDIR
)
2204 case 0: /* EOT on 1st record */
2216 if (spcl
.c_type
== TS_END
)
2224 * Checkpoint info to be processed by rollforward():
2225 * The inode with which the next volume should begin
2226 * The last inode number on this volume
2227 * The last logical block number on this volume
2228 * The current output state
2229 * The offset within the current inode (already in sl_offset)
2230 * The number of records left from last spclrec (in sl_count)
2231 * The physical block the next vol begins with (in sl_firstrec)
2233 chkpt
.sl_inos
= ino
;
2234 chkpt
.sl_tapea
= spcl
.c_tapea
+ count
;
2235 chkpt
.sl_state
= state
;
2237 if ((unsigned)atomic((int(*)())write
, cmd
, (char *)&chkpt
,
2238 sizeof (chkpt
)) != sizeof (chkpt
)) {
2243 if ((unsigned)atomic((int(*)())write
, cmd
, (char *)&spcl
,
2244 sizeof (spcl
)) != sizeof (spcl
)) {
2251 /* XGETTEXT: #ifdef DEBUG only */
2252 msg(gettext("sent chkpt to master:\n"));
2253 msg(" ino %u\n", chkpt
.sl_inos
);
2254 msg(" 1strec %u\n", chkpt
.sl_firstrec
);
2255 msg(" lastrec %u\n", chkpt
.sl_tapea
);
2256 msg(" written %u\n", chkpt
.sl_offset
);
2257 msg(" left %u\n", chkpt
.sl_count
);
2258 msg(" state %d\n", chkpt
.sl_state
);
2264 * Since a read from a pipe may not return all we asked for,
2265 * or a write may not write all we ask if we get a signal,
2266 * loop until the count is satisfied (or error).
2269 atomic(int (*func
)(), int fd
, char *buf
, int count
)
2271 ssize_t got
= 0, need
= count
;
2273 /* don't inherit random value if immediately get zero back from func */
2276 got
= (*func
)(fd
, buf
, MIN(need
, 4096));
2277 if (got
< 0 && errno
== EINTR
)
2284 /* if we got what was asked for, return count, else failure (got) */
2285 return ((need
!= 0) ? got
: count
);
2290 positiontape(char *msgbuf
)
2292 positiontape(char *msgbuf
)
2295 /* Static as never change, no need to waste stack space */
2296 static struct mtget mt
;
2297 static struct mtop rew
= { MTREW
, 1 };
2298 static struct mtop fsf
= { MTFSF
, 1 };
2299 char *info
= strdup(gettext("Positioning `%s' to file %ld\n"));
2300 char *fail
= strdup(gettext("Cannot position tape to file %d\n"));
2303 /* gettext()'s return value is volatile, hence the strdup()s */
2305 m
= (access(tape
, F_OK
) == 0) ? 0 : O_CREAT
;
2308 * To avoid writing tape marks at inappropriate places, we open the
2309 * device read-only, position it, close it, and reopen it for writing.
2311 while ((to
= safe_device_open(tape
, O_RDONLY
|m
, 0600)) < 0) {
2313 if (!query_once(msgbuf
, 1)) {
2318 if (!query(msgbuf
)) {
2325 if (ioctl(to
, MTIOCGET
, &mt
) >= 0 &&
2326 ioctl(to
, MTIOCTOP
, &rew
) >= 0 &&
2328 msg(info
, dumpdev
, filenum
);
2329 fsf
.mt_count
= filenum
- 1;
2330 if (ioctl(to
, MTIOCTOP
, &fsf
) < 0) {
2351 msg(gettext("Error writing command pipe: %s\n"), strerror(saverr
));
2362 msg(gettext("Error reading command pipe: %s\n"), strerror(saverr
));