1 /*
2 BAREOS® - Backup Archiving REcovery Open Sourced
3
4 Copyright (C) 2001-2012 Free Software Foundation Europe e.V.
5 Copyright (C) 2011-2012 Planets Communications B.V.
6 Copyright (C) 2013-2021 Bareos GmbH & Co. KG
7
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version three of the GNU Affero General Public
10 License as published by the Free Software Foundation and included
11 in the file LICENSE.
12
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Affero General Public License for more details.
17
18 You should have received a copy of the GNU Affero General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 02110-1301, USA.
22 */
23 /*
24 * Kern Sibbald, March MMI
25 * added BB02 format October MMII
26 */
27 /**
28 @file
29 * tape block handling functions
30 */
31
32 #include "include/bareos.h"
33 #include "stored/stored.h"
34 #include "stored/crc32/crc32.h"
35 #include "stored/dev.h"
36 #include "stored/device.h"
37 #include "stored/device_control_record.h"
38 #include "stored/label.h"
39 #include "stored/socket_server.h"
40 #include "stored/spool.h"
41 #include "lib/berrno.h"
42 #include "lib/edit.h"
43 #include "include/jcr.h"
44
45 namespace storagedaemon {
46
47 static bool TerminateWritingVolume(DeviceControlRecord* dcr);
48 static bool DoNewFileBookkeeping(DeviceControlRecord* dcr);
49 static void RereadLastBlock(DeviceControlRecord* dcr);
50
51 bool forge_on = false; /* proceed inspite of I/O errors */
52
53 /**
54 * Dump the block header, then walk through
55 * the block printing out the record headers.
56 */
DumpBlock(DeviceBlock * b,const char * msg)57 void DumpBlock(DeviceBlock* b, const char* msg)
58 {
59 ser_declare;
60 char* p;
61 char Id[BLKHDR_ID_LENGTH + 1];
62 uint32_t CheckSum, BlockCheckSum;
63 uint32_t block_len;
64 uint32_t BlockNumber;
65 uint32_t VolSessionId, VolSessionTime, data_len;
66 int32_t FileIndex;
67 int32_t Stream;
68 int bhl, rhl;
69 char buf1[100], buf2[100];
70
71 UnserBegin(b->buf, BLKHDR1_LENGTH);
72 unser_uint32(CheckSum);
73 unser_uint32(block_len);
74 unser_uint32(BlockNumber);
75 UnserBytes(Id, BLKHDR_ID_LENGTH);
76 ASSERT(UnserLength(b->buf) == BLKHDR1_LENGTH);
77 Id[BLKHDR_ID_LENGTH] = 0;
78 if (Id[3] == '2') {
79 unser_uint32(VolSessionId);
80 unser_uint32(VolSessionTime);
81 bhl = BLKHDR2_LENGTH;
82 rhl = RECHDR2_LENGTH;
83 } else {
84 VolSessionId = VolSessionTime = 0;
85 bhl = BLKHDR1_LENGTH;
86 rhl = RECHDR1_LENGTH;
87 }
88
89 if (block_len > 4000000) {
90 Dmsg3(20, "Dump block %s 0x%x blocksize too big %u\n", msg, b, block_len);
91 return;
92 }
93
94 BlockCheckSum = crc32_fast((uint8_t*)b->buf + BLKHDR_CS_LENGTH,
95 block_len - BLKHDR_CS_LENGTH);
96 Pmsg6(000,
97 _("Dump block %s %x: size=%d BlkNum=%d\n"
98 " Hdrcksum=%x cksum=%x\n"),
99 msg, b, block_len, BlockNumber, CheckSum, BlockCheckSum);
100 p = b->buf + bhl;
101 while (p < (b->buf + block_len + WRITE_RECHDR_LENGTH)) {
102 UnserBegin(p, WRITE_RECHDR_LENGTH);
103 if (rhl == RECHDR1_LENGTH) {
104 unser_uint32(VolSessionId);
105 unser_uint32(VolSessionTime);
106 }
107 unser_int32(FileIndex);
108 unser_int32(Stream);
109 unser_uint32(data_len);
110 Pmsg6(000, _(" Rec: VId=%u VT=%u FI=%s Strm=%s len=%d p=%x\n"),
111 VolSessionId, VolSessionTime, FI_to_ascii(buf1, FileIndex),
112 stream_to_ascii(buf2, Stream, FileIndex), data_len, p);
113 p += data_len + rhl;
114 }
115 }
116
117 /**
118 * Create a new block structure.
119 * We pass device so that the block can inherit the
120 * min and max block sizes.
121 */
new_block(Device * dev)122 DeviceBlock* new_block(Device* dev)
123 {
124 DeviceBlock* block = (DeviceBlock*)GetMemory(sizeof(DeviceBlock));
125
126 memset(block, 0, sizeof(DeviceBlock));
127
128 if (dev->max_block_size == 0) {
129 block->buf_len = dev->device_resource->label_block_size;
130 Dmsg1(100,
131 "created new block of blocksize %d (dev->device->label_block_size) "
132 "as dev->max_block_size is zero\n",
133 block->buf_len);
134 } else {
135 block->buf_len = dev->max_block_size;
136 Dmsg1(100, "created new block of blocksize %d (dev->max_block_size)\n",
137 block->buf_len);
138 }
139 block->dev = dev;
140 block->block_len = block->buf_len; /* default block size */
141 block->buf = GetMemory(block->buf_len);
142 EmptyBlock(block);
143 block->BlockVer = BLOCK_VER; /* default write version */
144 Dmsg1(650, "Returning new block=%x\n", block);
145 return block;
146 }
147
148 /**
149 * Duplicate an existing block (eblock)
150 */
dup_block(DeviceBlock * eblock)151 DeviceBlock* dup_block(DeviceBlock* eblock)
152 {
153 DeviceBlock* block = (DeviceBlock*)GetMemory(sizeof(DeviceBlock));
154 int buf_len = SizeofPoolMemory(eblock->buf);
155
156 memcpy(block, eblock, sizeof(DeviceBlock));
157 block->buf = GetMemory(buf_len);
158 memcpy(block->buf, eblock->buf, buf_len);
159 return block;
160 }
161
162 /**
163 * Only the first block checksum error was reported.
164 * If there are more, report it now.
165 */
PrintBlockReadErrors(JobControlRecord * jcr,DeviceBlock * block)166 void PrintBlockReadErrors(JobControlRecord* jcr, DeviceBlock* block)
167 {
168 if (block->read_errors > 1) {
169 Jmsg(jcr, M_ERROR, 0, _("%d block read errors not printed.\n"),
170 block->read_errors);
171 }
172 }
173
174 /**
175 * Free block
176 */
FreeBlock(DeviceBlock * block)177 void FreeBlock(DeviceBlock* block)
178 {
179 if (block) {
180 Dmsg1(999, "FreeBlock buffer %x\n", block->buf);
181 FreeMemory(block->buf);
182 Dmsg1(999, "FreeBlock block %x\n", block);
183 FreeMemory((POOLMEM*)block);
184 }
185 }
186
187 /**
188 * Empty the block -- for writing
189 */
EmptyBlock(DeviceBlock * block)190 void EmptyBlock(DeviceBlock* block)
191 {
192 block->binbuf = WRITE_BLKHDR_LENGTH;
193 block->bufp = block->buf + block->binbuf;
194 block->read_len = 0;
195 block->write_failed = false;
196 block->block_read = false;
197 block->FirstIndex = block->LastIndex = 0;
198 }
199
200 /**
201 * Create block header just before write. The space
202 * in the buffer should have already been reserved by
203 * init_block.
204 */
SerBlockHeader(DeviceBlock * block,bool DoChecksum)205 static uint32_t SerBlockHeader(DeviceBlock* block, bool DoChecksum)
206 {
207 ser_declare;
208 uint32_t CheckSum = 0;
209 uint32_t block_len = block->binbuf;
210
211 Dmsg1(1390, "SerBlockHeader: block_len=%d\n", block_len);
212 SerBegin(block->buf, BLKHDR2_LENGTH);
213 ser_uint32(CheckSum);
214 ser_uint32(block_len);
215 ser_uint32(block->BlockNumber);
216 SerBytes(WRITE_BLKHDR_ID, BLKHDR_ID_LENGTH);
217 if (BLOCK_VER >= 2) {
218 ser_uint32(block->VolSessionId);
219 ser_uint32(block->VolSessionTime);
220 }
221
222 /*
223 * Checksum whole block except for the checksum
224 */
225 if (DoChecksum) {
226 CheckSum = crc32_fast((uint8_t*)block->buf + BLKHDR_CS_LENGTH,
227 block_len - BLKHDR_CS_LENGTH);
228 }
229 Dmsg1(1390, "ser_bloc_header: checksum=%x\n", CheckSum);
230 SerBegin(block->buf, BLKHDR2_LENGTH);
231 ser_uint32(CheckSum); /* now add checksum to block header */
232 return CheckSum;
233 }
234
235 /**
236 * UnSerialize the block header for reading block.
237 * This includes setting all the buffer pointers correctly.
238 *
239 * Returns: false on failure (not a block)
240 * true on success
241 */
unSerBlockHeader(JobControlRecord * jcr,Device * dev,DeviceBlock * block)242 static inline bool unSerBlockHeader(JobControlRecord* jcr,
243 Device* dev,
244 DeviceBlock* block)
245 {
246 ser_declare;
247 char Id[BLKHDR_ID_LENGTH + 1];
248 uint32_t CheckSum, BlockCheckSum;
249 uint32_t block_len;
250 uint32_t block_end;
251 uint32_t BlockNumber;
252 int bhl;
253
254 UnserBegin(block->buf, BLKHDR_LENGTH);
255 unser_uint32(CheckSum);
256 unser_uint32(block_len);
257 unser_uint32(BlockNumber);
258 UnserBytes(Id, BLKHDR_ID_LENGTH);
259 ASSERT(UnserLength(block->buf) == BLKHDR1_LENGTH);
260
261 Id[BLKHDR_ID_LENGTH] = 0;
262 if (Id[3] == '1') {
263 bhl = BLKHDR1_LENGTH;
264 block->BlockVer = 1;
265 block->bufp = block->buf + bhl;
266 if (!bstrncmp(Id, BLKHDR1_ID, BLKHDR_ID_LENGTH)) {
267 dev->dev_errno = EIO;
268 Mmsg4(dev->errmsg,
269 _("Volume data error at %u:%u! Wanted ID: \"%s\", got \"%s\". "
270 "Buffer discarded.\n"),
271 dev->file, dev->block_num, BLKHDR1_ID, Id);
272 if (block->read_errors == 0 || verbose >= 2) {
273 Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
274 }
275 block->read_errors++;
276 return false;
277 }
278 } else if (Id[3] == '2') {
279 unser_uint32(block->VolSessionId);
280 unser_uint32(block->VolSessionTime);
281 bhl = BLKHDR2_LENGTH;
282 block->BlockVer = 2;
283 block->bufp = block->buf + bhl;
284 if (!bstrncmp(Id, BLKHDR2_ID, BLKHDR_ID_LENGTH)) {
285 dev->dev_errno = EIO;
286 Mmsg4(dev->errmsg,
287 _("Volume data error at %u:%u! Wanted ID: \"%s\", got \"%s\". "
288 "Buffer discarded.\n"),
289 dev->file, dev->block_num, BLKHDR2_ID, Id);
290 if (block->read_errors == 0 || verbose >= 2) {
291 Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
292 }
293 block->read_errors++;
294 return false;
295 }
296 } else {
297 dev->dev_errno = EIO;
298 Mmsg4(dev->errmsg,
299 _("Volume data error at %u:%u! Wanted ID: \"%s\", got \"%s\". Buffer "
300 "discarded.\n"),
301 dev->file, dev->block_num, BLKHDR2_ID, Id);
302 Dmsg1(50, "%s", dev->errmsg);
303 if (block->read_errors == 0 || verbose >= 2) {
304 Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
305 }
306 block->read_errors++;
307 unser_uint32(block->VolSessionId);
308 unser_uint32(block->VolSessionTime);
309 return false;
310 }
311
312 /*
313 * Sanity check
314 */
315 if (block_len > MAX_BLOCK_LENGTH) {
316 dev->dev_errno = EIO;
317 Mmsg3(dev->errmsg,
318 _("Volume data error at %u:%u! Block length %u is insane (too "
319 "large), probably due to a bad archive.\n"),
320 dev->file, dev->block_num, block_len);
321 if (block->read_errors == 0 || verbose >= 2) {
322 Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
323 }
324 block->read_errors++;
325 return false;
326 }
327
328 Dmsg1(390, "unSerBlockHeader block_len=%d\n", block_len);
329 /*
330 * Find end of block or end of buffer whichever is smaller
331 */
332 if (block_len > block->read_len) {
333 block_end = block->read_len;
334 } else {
335 block_end = block_len;
336 }
337 block->binbuf = block_end - bhl;
338 block->block_len = block_len;
339 block->BlockNumber = BlockNumber;
340 Dmsg3(390, "Read binbuf = %d %d block_len=%d\n", block->binbuf, bhl,
341 block_len);
342 if (block_len <= block->read_len && dev->DoChecksum()) {
343 BlockCheckSum = crc32_fast((uint8_t*)block->buf + BLKHDR_CS_LENGTH,
344 block_len - BLKHDR_CS_LENGTH);
345 if (BlockCheckSum != CheckSum) {
346 dev->dev_errno = EIO;
347 Mmsg6(dev->errmsg,
348 _("Volume data error at %u:%u!\n"
349 "Block checksum mismatch in block=%u len=%d: calc=%x blk=%x\n"),
350 dev->file, dev->block_num, (unsigned)BlockNumber, block_len,
351 BlockCheckSum, CheckSum);
352 if (block->read_errors == 0 || verbose >= 2) {
353 Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
354 DumpBlock(block, "with checksum error");
355 }
356 block->read_errors++;
357 if (!forge_on) { return false; }
358 }
359 }
360 return true;
361 }
362
RereadLastBlock(DeviceControlRecord * dcr)363 static void RereadLastBlock(DeviceControlRecord* dcr)
364 {
365 #define CHECK_LAST_BLOCK
366 #ifdef CHECK_LAST_BLOCK
367 bool ok = true;
368 Device* dev = dcr->dev;
369 JobControlRecord* jcr = dcr->jcr;
370 DeviceBlock* block = dcr->block;
371 /*
372 * If the device is a tape and it supports backspace record,
373 * we backspace over one or two eof marks depending on
374 * how many we just wrote, then over the last record,
375 * then re-read it and verify that the block number is
376 * correct.
377 */
378 if (dev->IsTape() && dev->HasCap(CAP_BSR)) {
379 /*
380 * Now back up over what we wrote and read the last block
381 */
382 if (!dev->bsf(1)) {
383 BErrNo be;
384 ok = false;
385 Jmsg(jcr, M_ERROR, 0, _("Backspace file at EOT failed. ERR=%s\n"),
386 be.bstrerror(dev->dev_errno));
387 }
388 if (ok && dev->HasCap(CAP_TWOEOF) && !dev->bsf(1)) {
389 BErrNo be;
390 ok = false;
391 Jmsg(jcr, M_ERROR, 0, _("Backspace file at EOT failed. ERR=%s\n"),
392 be.bstrerror(dev->dev_errno));
393 }
394 /*
395 * Backspace over record
396 */
397 if (ok && !dev->bsr(1)) {
398 BErrNo be;
399 ok = false;
400 Jmsg(jcr, M_ERROR, 0, _("Backspace record at EOT failed. ERR=%s\n"),
401 be.bstrerror(dev->dev_errno));
402 /*
403 * On FreeBSD systems, if the user got here, it is likely that his/her
404 * tape drive is "frozen". The correct thing to do is a
405 * rewind(), but if we do that, higher levels in cleaning up, will
406 * most likely write the EOS record over the beginning of the
407 * tape. The rewind *is* done later in mount.c when another
408 * tape is requested. Note, the clrerror() call in bsr()
409 * calls ioctl(MTCERRSTAT), which *should* fix the problem.
410 */
411 }
412 if (ok) {
413 DeviceBlock* lblock = new_block(dev);
414 /*
415 * Note, this can destroy dev->errmsg
416 */
417 dcr->block = lblock;
418 if (DeviceControlRecord::ReadStatus::Ok
419 != dcr->ReadBlockFromDev(NO_BLOCK_NUMBER_CHECK)) {
420 Jmsg(jcr, M_ERROR, 0, _("Re-read last block at EOT failed. ERR=%s"),
421 dev->errmsg);
422 } else {
423 /*
424 * If we wrote block and the block numbers don't agree
425 * we have a possible problem.
426 */
427 if (lblock->BlockNumber != dev->LastBlock) {
428 if (dev->LastBlock > (lblock->BlockNumber + 1)) {
429 Jmsg(jcr, M_FATAL, 0,
430 _("Re-read of last block: block numbers differ by more than "
431 "one.\n"
432 "Probable tape misconfiguration and data loss. Read "
433 "block=%u Want block=%u.\n"),
434 lblock->BlockNumber, dev->LastBlock);
435 } else {
436 Jmsg(jcr, M_ERROR, 0,
437 _("Re-read of last block OK, but block numbers differ. Read "
438 "block=%u Want block=%u.\n"),
439 lblock->BlockNumber, dev->LastBlock);
440 }
441 } else {
442 Jmsg(jcr, M_INFO, 0, _("Re-read of last block succeeded.\n"));
443 }
444 }
445 FreeBlock(lblock);
446 dcr->block = block;
447 }
448 }
449 #endif
450 }
451
452 /**
453 * If this routine is called, we do our bookkeeping and
454 * then assure that the volume will not be written any more.
455 */
TerminateWritingVolume(DeviceControlRecord * dcr)456 static bool TerminateWritingVolume(DeviceControlRecord* dcr)
457 {
458 Device* dev = dcr->dev;
459 bool ok = true;
460
461 /* Create a JobMedia record to indicated end of tape */
462 dev->VolCatInfo.VolCatFiles = dev->file;
463 if (!dcr->DirCreateJobmediaRecord(false)) {
464 Dmsg0(50, "Error from create JobMedia\n");
465 dev->dev_errno = EIO;
466 Mmsg2(dev->errmsg,
467 _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
468 dcr->getVolCatName(), dcr->jcr->Job);
469 Jmsg(dcr->jcr, M_FATAL, 0, "%s", dev->errmsg);
470 ok = false;
471 }
472 dcr->block->write_failed = true;
473 if (!dev->weof(1)) { /* end the tape */
474 dev->VolCatInfo.VolCatErrors++;
475 Jmsg(dcr->jcr, M_ERROR, 0,
476 _("Error writing final EOF to tape. This Volume may not be readable.\n"
477 "%s"),
478 dev->errmsg);
479 ok = false;
480 Dmsg0(50, "Error writing final EOF to volume.\n");
481 }
482 if (ok) {
483 ok = WriteAnsiIbmLabels(dcr, ANSI_EOV_LABEL, dev->VolHdr.VolumeName);
484 }
485 bstrncpy(dev->VolCatInfo.VolCatStatus, "Full",
486 sizeof(dev->VolCatInfo.VolCatStatus));
487 dev->VolCatInfo.VolCatFiles = dev->file; /* set number of files */
488
489 if (!dcr->DirUpdateVolumeInfo(false, true)) {
490 Mmsg(dev->errmsg, _("Error sending Volume info to Director.\n"));
491 ok = false;
492 Dmsg0(50, "Error updating volume info.\n");
493 }
494 Dmsg1(50, "DirUpdateVolumeInfo Terminate writing -- %s\n",
495 ok ? "OK" : "ERROR");
496
497 /*
498 * Walk through all attached dcrs setting flag to call
499 * SetNewFileParameters() when that dcr is next used.
500 */
501 for (auto mdcr : dev->attached_dcrs) {
502 if (mdcr->jcr->JobId == 0) { continue; }
503 mdcr->NewFile = true; /* set reminder to do set_new_file_params */
504 }
505 /*
506 * Set new file/block parameters for current dcr
507 */
508 SetNewFileParameters(dcr);
509
510 if (ok && dev->HasCap(CAP_TWOEOF) && !dev->weof(1)) { /* end the tape */
511 dev->VolCatInfo.VolCatErrors++;
512 /*
513 * This may not be fatal since we already wrote an EOF
514 */
515 Jmsg(dcr->jcr, M_ERROR, 0, "%s", dev->errmsg);
516 Dmsg0(50, "Writing second EOF failed.\n");
517 }
518
519 dev->SetAteot(); /* no more writing this tape */
520 Dmsg1(50, "*** Leave TerminateWritingVolume -- %s\n", ok ? "OK" : "ERROR");
521 return ok;
522 }
523
524 /**
525 * Do bookkeeping when a new file is created on a Volume. This is
526 * also done for disk files to generate the jobmedia records for
527 * quick seeking.
528 */
DoNewFileBookkeeping(DeviceControlRecord * dcr)529 static bool DoNewFileBookkeeping(DeviceControlRecord* dcr)
530 {
531 Device* dev = dcr->dev;
532 JobControlRecord* jcr = dcr->jcr;
533
534 /*
535 * Create a JobMedia record so restore can seek
536 */
537 if (!dcr->DirCreateJobmediaRecord(false)) {
538 Dmsg0(50, "Error from create_job_media.\n");
539 dev->dev_errno = EIO;
540 Jmsg2(jcr, M_FATAL, 0,
541 _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
542 dcr->getVolCatName(), jcr->Job);
543 TerminateWritingVolume(dcr);
544 dev->dev_errno = EIO;
545 return false;
546 }
547 dev->VolCatInfo.VolCatFiles = dev->file;
548 if (!dcr->DirUpdateVolumeInfo(false, false)) {
549 Dmsg0(50, "Error from update_vol_info.\n");
550 TerminateWritingVolume(dcr);
551 dev->dev_errno = EIO;
552 return false;
553 }
554 Dmsg0(100, "DirUpdateVolumeInfo max file size -- OK\n");
555
556 /*
557 * Walk through all attached dcrs setting flag to call
558 * SetNewFileParameters() when that dcr is next used.
559 */
560 for (auto mdcr : dev->attached_dcrs) {
561 if (mdcr->jcr->JobId == 0) { continue; }
562 mdcr->NewFile = true; /* set reminder to do set_new_file_params */
563 }
564 /*
565 * Set new file/block parameters for current dcr
566 */
567 SetNewFileParameters(dcr);
568 return true;
569 }
570
571 #ifdef DEBUG_BLOCK_CHECKSUM
572 static const bool debug_block_checksum = true;
573 #else
574 static const bool debug_block_checksum = false;
575 #endif
576
577 #ifdef NO_TAPE_WRITE_TEST
578 static const bool no_tape_write_test = true;
579 #else
580 static const bool no_tape_write_test = false;
581 #endif
582
583 /**
584 * Write a block to the device
585 *
586 * Returns: true on success or EOT
587 * false on hard error
588 */
WriteBlockToDev()589 bool DeviceControlRecord::WriteBlockToDev()
590 {
591 ssize_t status = 0;
592 uint32_t wlen; /* length to write */
593 int hit_max1, hit_max2;
594 bool ok = true;
595 DeviceControlRecord* dcr = this;
596 uint32_t checksum;
597
598 if (no_tape_write_test) {
599 EmptyBlock(block);
600 return true;
601 }
602 if (JobCanceled(jcr)) {
603 Dmsg0(100, "return WriteBlockToDev, job is canceled\n");
604 return false;
605 }
606
607 ASSERT(block->binbuf == ((uint32_t)(block->bufp - block->buf)));
608
609 wlen = block->binbuf;
610 if (wlen <= WRITE_BLKHDR_LENGTH) { /* Does block have data in it? */
611 Dmsg0(100, "return WriteBlockToDev no data to write\n");
612 return true;
613 }
614
615 /* DumpBlock(block, "before write"); */
616 if (dev->AtWeot()) {
617 Dmsg0(100, "return WriteBlockToDev with ST_WEOT\n");
618 dev->dev_errno = ENOSPC;
619 Jmsg1(jcr, M_FATAL, 0, _("Cannot write block. Device at EOM. dev=%s\n"),
620 dev->print_name());
621 Dmsg1(100, "Attempt to write on read-only Volume. dev=%s\n",
622 dev->print_name());
623 return false;
624 }
625 if (!dev->CanAppend()) {
626 dev->dev_errno = EIO;
627 Jmsg1(jcr, M_FATAL, 0, _("Attempt to write on read-only Volume. dev=%s\n"),
628 dev->print_name());
629 Dmsg1(100, "Attempt to write on read-only Volume. dev=%s\n",
630 dev->print_name());
631 return false;
632 }
633
634 if (!dev->IsOpen()) {
635 Jmsg1(jcr, M_FATAL, 0, _("Attempt to write on closed device=%s\n"),
636 dev->print_name());
637 Dmsg1(100, "Attempt to write on closed device=%s\n", dev->print_name());
638 return false;
639 }
640
641 /*
642 * Clear to the end of the buffer if it is not full,
643 * and on devices with CAP_ADJWRITESIZE set, apply min and fixed blocking.
644 */
645 if (wlen != block->buf_len) {
646 uint32_t blen = wlen; /* current buffer length */
647
648 Dmsg2(250, "binbuf=%d buf_len=%d\n", block->binbuf, block->buf_len);
649
650 if (!dev->HasCap(CAP_ADJWRITESIZE)) {
651 Dmsg1(400, "%s: block write size is not adjustable", dev->print_name());
652 } else {
653 /* (dev->HasCap(CAP_ADJWRITESIZE)) */
654 if (dev->min_block_size == dev->max_block_size) {
655 /*
656 * Fixed block size
657 */
658 wlen = block->buf_len; /* fixed block size already rounded */
659 } else if (wlen < dev->min_block_size) {
660 /*
661 * Min block size
662 */
663 wlen = ((dev->min_block_size + TAPE_BSIZE - 1) / TAPE_BSIZE)
664 * TAPE_BSIZE;
665 } else {
666 /*
667 * Ensure size is rounded
668 */
669 wlen = ((wlen + TAPE_BSIZE - 1) / TAPE_BSIZE) * TAPE_BSIZE;
670 }
671
672 if (wlen - blen > 0) {
673 memset(block->bufp, 0, wlen - blen); /* clear garbage */
674 }
675 }
676 }
677
678 Dmsg5(400,
679 "dev=%s: writing %d bytes as block of %d bytes. Block sizes: min=%d, "
680 "max=%d\n",
681 dev->print_name(), block->binbuf, wlen, dev->min_block_size,
682 dev->max_block_size);
683
684 checksum = SerBlockHeader(block, dev->DoChecksum());
685
686 /*
687 * Limit maximum Volume size to value specified by user
688 */
689 hit_max1 = (dev->max_volume_size > 0)
690 && ((dev->VolCatInfo.VolCatBytes + block->binbuf))
691 >= dev->max_volume_size;
692 hit_max2 = (dev->VolCatInfo.VolCatMaxBytes > 0)
693 && ((dev->VolCatInfo.VolCatBytes + block->binbuf))
694 >= dev->VolCatInfo.VolCatMaxBytes;
695
696 if (hit_max1 || hit_max2) {
697 char ed1[50];
698 uint64_t max_cap;
699
700 Dmsg0(100, "==== Output bytes Triggered medium max capacity.\n");
701 if (hit_max1) {
702 max_cap = dev->max_volume_size;
703 } else {
704 max_cap = dev->VolCatInfo.VolCatMaxBytes;
705 }
706 Jmsg(jcr, M_INFO, 0,
707 _("User defined maximum volume capacity %s exceeded on device %s.\n"),
708 edit_uint64_with_commas(max_cap, ed1), dev->print_name());
709 TerminateWritingVolume(dcr);
710 RereadLastBlock(dcr); /* DEBUG */
711 dev->dev_errno = ENOSPC;
712
713 return false;
714 }
715
716 /*
717 * Limit maximum File size on volume to user specified value
718 */
719 if ((dev->max_file_size > 0)
720 && (dev->file_size + block->binbuf) >= dev->max_file_size) {
721 dev->file_size = 0; /* reset file size */
722
723 if (!dev->weof(1)) { /* write eof */
724 Dmsg0(50, "WEOF error in max file size.\n");
725 Jmsg(jcr, M_FATAL, 0, _("Unable to write EOF. ERR=%s\n"),
726 dev->bstrerror());
727 TerminateWritingVolume(dcr);
728 dev->dev_errno = ENOSPC;
729 return false;
730 }
731 if (!WriteAnsiIbmLabels(dcr, ANSI_EOF_LABEL, dev->VolHdr.VolumeName)) {
732 return false;
733 }
734
735 if (!DoNewFileBookkeeping(dcr)) {
736 /*
737 * Error message already sent
738 */
739 return false;
740 }
741 }
742
743 dev->VolCatInfo.VolCatWrites++;
744 Dmsg1(1300, "Write block of %u bytes\n", wlen);
745 #ifdef DEBUG_BLOCK_ZEROING
746 uint32_t* bp = (uint32_t*)block->buf;
747 if (bp[0] == 0 && bp[1] == 0 && bp[2] == 0 && block->buf[12] == 0) {
748 Jmsg0(jcr, M_ABORT, 0, _("Write block header zeroed.\n"));
749 }
750 #endif
751
752 /*
753 * Do write here,
754 * make a somewhat feeble attempt to recover
755 * from the OS telling us it is busy.
756 */
757 int retry = 0;
758 errno = 0;
759 status = 0;
760 do {
761 if (retry > 0 && status == -1 && errno == EBUSY) {
762 BErrNo be;
763 Dmsg4(100, "===== write retry=%d status=%d errno=%d: ERR=%s\n", retry,
764 status, errno, be.bstrerror());
765 Bmicrosleep(5, 0); /* pause a bit if busy or lots of errors */
766 dev->clrerror(-1);
767 }
768 status = dev->write(block->buf, (size_t)wlen);
769 } while (status == -1 && (errno == EBUSY) && retry++ < 3);
770
771 if (debug_block_checksum) {
772 uint32_t achecksum = SerBlockHeader(block, dev->DoChecksum());
773 if (checksum != achecksum) {
774 Jmsg2(jcr, M_ERROR, 0,
775 _("Block checksum changed during write: before=%ud after=%ud\n"),
776 checksum, achecksum);
777 DumpBlock(block, "with checksum error");
778 }
779 }
780
781 #ifdef DEBUG_BLOCK_ZEROING
782 if (bp[0] == 0 && bp[1] == 0 && bp[2] == 0 && block->buf[12] == 0) {
783 Jmsg0(jcr, M_ABORT, 0, _("Write block header zeroed.\n"));
784 }
785 #endif
786
787 if (status != (ssize_t)wlen) {
788 /*
789 * Some devices simply report EIO when the volume is full.
790 * With a little more thought we may be able to check
791 * capacity and distinguish real errors and EOT
792 * conditions. In any case, we probably want to
793 * simulate an End of Medium.
794 */
795 if (status == -1) {
796 BErrNo be;
797 dev->clrerror(-1);
798 if (dev->dev_errno == 0) { dev->dev_errno = ENOSPC; /* out of space */ }
799 if (dev->dev_errno != ENOSPC) {
800 dev->VolCatInfo.VolCatErrors++;
801 Jmsg4(jcr, M_ERROR, 0,
802 _("Write error at %u:%u on device %s. ERR=%s.\n"), dev->file,
803 dev->block_num, dev->print_name(), be.bstrerror());
804 }
805 } else {
806 dev->dev_errno = ENOSPC; /* out of space */
807 }
808
809 if (dev->dev_errno == ENOSPC) {
810 Jmsg(jcr, M_INFO, 0,
811 _("End of Volume \"%s\" at %u:%u on device %s. Write of %u bytes "
812 "got %d.\n"),
813 dev->getVolCatName(), dev->file, dev->block_num, dev->print_name(),
814 wlen, status);
815 } else {
816 BErrNo be;
817
818 be.SetErrno(dev->dev_errno);
819 Mmsg5(dev->errmsg,
820 _("Write error on fd=%d at file:blk %u:%u on device %s. ERR=%s.\n"),
821 dev->fd, dev->file, dev->block_num, dev->print_name(),
822 be.bstrerror());
823 }
824
825 GeneratePluginEvent(jcr, bSdEventWriteError, dcr);
826
827 if (dev->dev_errno != ENOSPC) { Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); }
828
829 if (debug_level >= 100) {
830 BErrNo be;
831
832 be.SetErrno(dev->dev_errno);
833 Dmsg7(100,
834 "=== Write error. fd=%d size=%u rtn=%d dev_blk=%d blk_blk=%d "
835 "errno=%d: ERR=%s\n",
836 dev->fd, wlen, status, dev->block_num, block->BlockNumber,
837 dev->dev_errno, be.bstrerror(dev->dev_errno));
838 }
839
840 ok = TerminateWritingVolume(dcr);
841 if (!ok && !forge_on) { return false; }
842 if (ok) { RereadLastBlock(dcr); }
843 return false;
844 }
845
846 /*
847 * We successfully wrote the block, now do housekeeping
848 */
849 Dmsg2(1300, "VolCatBytes=%d newVolCatBytes=%d\n",
850 (int)dev->VolCatInfo.VolCatBytes,
851 (int)(dev->VolCatInfo.VolCatBytes + wlen));
852 dev->VolCatInfo.VolCatBytes += wlen;
853 dev->VolCatInfo.VolCatBlocks++;
854 dev->EndBlock = dev->block_num;
855 dev->EndFile = dev->file;
856 dev->LastBlock = block->BlockNumber;
857 block->BlockNumber++;
858
859 /*
860 * Update dcr values
861 */
862 if (dev->IsTape()) {
863 dcr->EndBlock = dev->EndBlock;
864 dcr->EndFile = dev->EndFile;
865 dev->block_num++;
866 } else {
867 /*
868 * Save address of block just written
869 */
870 uint64_t addr = dev->file_addr + wlen - 1;
871 dcr->EndBlock = (uint32_t)addr;
872 dcr->EndFile = (uint32_t)(addr >> 32);
873 dev->block_num = dcr->EndBlock;
874 dev->file = dcr->EndFile;
875 }
876 dcr->VolMediaId = dev->VolCatInfo.VolMediaId;
877 if (dcr->VolFirstIndex == 0 && block->FirstIndex > 0) {
878 dcr->VolFirstIndex = block->FirstIndex;
879 }
880 if (block->LastIndex > 0) { dcr->VolLastIndex = block->LastIndex; }
881 dcr->WroteVol = true;
882 dev->file_addr += wlen; /* update file address */
883 dev->file_size += wlen;
884
885 Dmsg2(1300, "WriteBlock: wrote block %d bytes=%d\n", dev->block_num, wlen);
886 EmptyBlock(block);
887 return true;
888 }
889
890
891 /**
892 * Write a block to the device, with locking and unlocking
893 *
894 * Returns: true on success
895 * : false on failure
896 *
897 */
WriteBlockToDevice()898 bool DeviceControlRecord::WriteBlockToDevice()
899 {
900 bool status = true;
901 DeviceControlRecord* dcr = this;
902
903 if (dcr->spooling) {
904 status = WriteBlockToSpoolFile(dcr);
905 return status;
906 }
907
908 if (!dcr->IsDevLocked()) { /* device already locked? */
909 /*
910 * Note, do not change this to dcr->r_dlock
911 */
912 dev->rLock(); /* no, lock it */
913 }
914
915 /*
916 * If a new volume has been mounted since our last write
917 * Create a JobMedia record for the previous volume written,
918 * and set new parameters to write this volume
919 *
920 * The same applies for if we are in a new file.
921 */
922 if (dcr->NewVol || dcr->NewFile) {
923 if (JobCanceled(jcr)) {
924 status = false;
925 Dmsg0(100, "Canceled\n");
926 goto bail_out;
927 }
928 /* Create a jobmedia record for this job */
929 if (!dcr->DirCreateJobmediaRecord(false)) {
930 dev->dev_errno = EIO;
931 Jmsg2(jcr, M_FATAL, 0,
932 _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
933 dcr->getVolCatName(), jcr->Job);
934 SetNewVolumeParameters(dcr);
935 status = false;
936 Dmsg0(100, "cannot create media record\n");
937 goto bail_out;
938 }
939 if (dcr->NewVol) {
940 /*
941 * Note, setting a new volume also handles any pending new file
942 */
943 SetNewVolumeParameters(dcr);
944 } else {
945 SetNewFileParameters(dcr);
946 }
947 }
948
949 if (!dcr->WriteBlockToDev()) {
950 if (JobCanceled(jcr) || jcr->is_JobType(JT_SYSTEM)) {
951 status = false;
952 } else {
953 status = FixupDeviceBlockWriteError(dcr);
954 }
955 }
956
957 bail_out:
958 if (!dcr->IsDevLocked()) { /* did we lock dev above? */
959 /*
960 * Note, do not change this to dcr->dunlock
961 */
962 dev->Unlock(); /* unlock it now */
963 }
964 return status;
965 }
966
967 /**
968 * Read block with locking
969 */
ReadBlockFromDevice(bool check_block_numbers)970 DeviceControlRecord::ReadStatus DeviceControlRecord::ReadBlockFromDevice(
971 bool check_block_numbers)
972 {
973 ReadStatus status;
974
975 Dmsg0(250, "Enter ReadBlockFromDevice\n");
976 dev->rLock();
977 status = ReadBlockFromDev(check_block_numbers);
978 dev->Unlock();
979 Dmsg0(250, "Leave ReadBlockFromDevice\n");
980 return status;
981 }
982
983 /**
984 * Read the next block into the block structure and unserialize
985 * the block header. For a file, the block may be partially
986 * or completely in the current buffer.
987 */
ReadBlockFromDev(bool check_block_numbers)988 DeviceControlRecord::ReadStatus DeviceControlRecord::ReadBlockFromDev(
989 bool check_block_numbers)
990 {
991 ssize_t status;
992 int looping;
993 int retry;
994 DeviceControlRecord* dcr = this;
995
996 if (JobCanceled(jcr)) {
997 Mmsg(dev->errmsg, _("Job failed or canceled.\n"));
998 block->read_len = 0;
999 return ReadStatus::Error;
1000 }
1001
1002 if (dev->AtEot()) {
1003 Mmsg(dev->errmsg, _("Attempt to read past end of tape or file.\n"));
1004 block->read_len = 0;
1005 return ReadStatus::EndOfTape;
1006 }
1007 looping = 0;
1008 Dmsg1(250, "Full read in ReadBlockFromDevice() len=%d\n", block->buf_len);
1009
1010 if (!dev->IsOpen()) {
1011 Mmsg4(dev->errmsg,
1012 _("Attempt to read closed device: fd=%d at file:blk %u:%u on device "
1013 "%s\n"),
1014 dev->fd, dev->file, dev->block_num, dev->print_name());
1015 Jmsg(dcr->jcr, M_WARNING, 0, "%s", dev->errmsg);
1016 block->read_len = 0;
1017 return ReadStatus::Error;
1018 }
1019
1020 reread:
1021 if (looping > 1) {
1022 dev->dev_errno = EIO;
1023 Mmsg1(dev->errmsg, _("Block buffer size looping problem on device %s\n"),
1024 dev->print_name());
1025 Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
1026 block->read_len = 0;
1027 return ReadStatus::Error;
1028 }
1029
1030 retry = 0;
1031 errno = 0;
1032 status = 0;
1033
1034 do {
1035 if (retry) {
1036 BErrNo be;
1037 Dmsg4(100, "===== read retry=%d status=%d errno=%d: ERR=%s\n", retry,
1038 status, errno, be.bstrerror());
1039 Bmicrosleep(10, 0); /* pause a bit if busy or lots of errors */
1040 dev->clrerror(-1);
1041 }
1042 status = dev->read(block->buf, (size_t)block->buf_len);
1043
1044 } while (status == -1 && (errno == EBUSY || errno == EINTR || errno == EIO)
1045 && retry++ < 3);
1046
1047 if (status < 0) {
1048 BErrNo be;
1049
1050 dev->clrerror(-1);
1051 Dmsg1(250, "Read device got: ERR=%s\n", be.bstrerror());
1052 block->read_len = 0;
1053 Mmsg5(dev->errmsg,
1054 _("Read error on fd=%d at file:blk %u:%u on device %s. ERR=%s.\n"),
1055 dev->fd, dev->file, dev->block_num, dev->print_name(),
1056 be.bstrerror());
1057
1058 GeneratePluginEvent(jcr, bSdEventReadError, dcr);
1059
1060 Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
1061 if (device_resource->eof_on_error_is_eot && dev->AtEof()) {
1062 dev->SetEot();
1063 return ReadStatus::EndOfTape;
1064 }
1065 return ReadStatus::Error;
1066 }
1067
1068 Dmsg3(250, "Read device got %d bytes at %u:%u\n", status, dev->file,
1069 dev->block_num);
1070
1071 if (status == 0) { /* EOF (Berkley I/O Conventions) */
1072 dev->block_num = 0;
1073 block->read_len = 0;
1074 Mmsg3(dev->errmsg, _("Read zero bytes at %u:%u on device %s.\n"), dev->file,
1075 dev->block_num, dev->print_name());
1076 if (dev->AtEof()) { /* EOF already set before means end of tape */
1077 dev->SetEot();
1078 return ReadStatus::EndOfTape;
1079 }
1080 dev->SetAteof();
1081 return ReadStatus::EndOfFile;
1082 }
1083
1084 /*
1085 * successful read (status > 0)
1086 */
1087
1088 block->read_len = status; /* save length read */
1089 if (block->read_len == 80
1090 && (dcr->VolCatInfo.LabelType != B_BAREOS_LABEL
1091 || dcr->device_resource->label_type != B_BAREOS_LABEL)) {
1092 /* ***FIXME*** should check label */
1093 Dmsg2(100, "Ignore 80 byte ANSI label at %u:%u\n", dev->file,
1094 dev->block_num);
1095 dev->ClearEof();
1096 goto reread; /* skip ANSI/IBM label */
1097 }
1098
1099 if (block->read_len < BLKHDR2_LENGTH) {
1100 dev->dev_errno = EIO;
1101 Mmsg4(dev->errmsg,
1102 _("Volume data error at %u:%u! Very short block of %d bytes on "
1103 "device %s discarded.\n"),
1104 dev->file, dev->block_num, block->read_len, dev->print_name());
1105 Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
1106 dev->SetShortBlock();
1107 block->read_len = block->binbuf = 0;
1108 Dmsg2(200, "set block=%p binbuf=%d\n", block, block->binbuf);
1109 return ReadStatus::Error;
1110 }
1111
1112 // BlockNumber = block->BlockNumber + 1;
1113 if (!unSerBlockHeader(jcr, dev, block)) {
1114 if (forge_on) {
1115 dev->file_addr += block->read_len;
1116 dev->file_size += block->read_len;
1117 goto reread;
1118 }
1119 return ReadStatus::Error;
1120 }
1121
1122 /*
1123 * If the block is bigger than the buffer, we Reposition for
1124 * re-reading the block, allocate a buffer of the correct size,
1125 * and go re-read.
1126 */
1127 if (block->block_len > block->buf_len) {
1128 dev->dev_errno = EIO;
1129 Mmsg2(
1130 dev->errmsg,
1131 _("Block length %u is greater than buffer %u. Attempting recovery.\n"),
1132 block->block_len, block->buf_len);
1133 Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
1134 Pmsg1(000, "%s", dev->errmsg);
1135 /*
1136 * Attempt to Reposition to re-read the block
1137 */
1138 if (dev->IsTape()) {
1139 Dmsg0(250, "BootStrapRecord for reread; block too big for buffer.\n");
1140 if (!dev->bsr(1)) {
1141 Mmsg(dev->errmsg, "%s", dev->bstrerror());
1142 Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
1143 block->read_len = 0;
1144 return ReadStatus::Error;
1145 }
1146 } else {
1147 Dmsg0(250, "Seek to beginning of block for reread.\n");
1148 boffset_t pos
1149 = dev->d_lseek(dcr, (boffset_t)0, SEEK_CUR); /* get curr pos */
1150 pos -= block->read_len;
1151 dev->d_lseek(dcr, pos, SEEK_SET);
1152 dev->file_addr = pos;
1153 }
1154 Mmsg1(dev->errmsg, _("Setting block buffer size to %u bytes.\n"),
1155 block->block_len);
1156 Jmsg(jcr, M_INFO, 0, "%s", dev->errmsg);
1157 Pmsg1(000, "%s", dev->errmsg);
1158 /*
1159 * Set new block length
1160 */
1161 dev->max_block_size = block->block_len;
1162 block->buf_len = block->block_len;
1163 FreeMemory(block->buf);
1164 block->buf = GetMemory(block->buf_len);
1165 EmptyBlock(block);
1166 looping++;
1167 goto reread; /* re-read block with correct block size */
1168 }
1169
1170 if (block->block_len > block->read_len) {
1171 dev->dev_errno = EIO;
1172 Mmsg4(dev->errmsg,
1173 _("Volume data error at %u:%u! Short block of %d bytes on device %s "
1174 "discarded.\n"),
1175 dev->file, dev->block_num, block->read_len, dev->print_name());
1176 Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
1177 dev->SetShortBlock();
1178 block->read_len = block->binbuf = 0;
1179 return ReadStatus::Error;
1180 }
1181
1182 dev->ClearShortBlock();
1183 dev->ClearEof();
1184 dev->VolCatInfo.VolCatReads++;
1185 dev->VolCatInfo.VolCatRBytes += block->read_len;
1186
1187 dev->EndBlock = dev->block_num;
1188 dev->EndFile = dev->file;
1189 dev->block_num++;
1190
1191 /*
1192 * Update dcr values
1193 */
1194 if (dev->IsTape()) {
1195 dcr->EndBlock = dev->EndBlock;
1196 dcr->EndFile = dev->EndFile;
1197 } else {
1198 /*
1199 * We need to take care about a short block in EndBlock/File computation
1200 */
1201 uint32_t len = MIN(block->read_len, block->block_len);
1202 uint64_t addr = dev->file_addr + len - 1;
1203 dcr->EndBlock = (uint32_t)addr;
1204 dcr->EndFile = (uint32_t)(addr >> 32);
1205 dev->block_num = dev->EndBlock = dcr->EndBlock;
1206 dev->file = dev->EndFile = dcr->EndFile;
1207 }
1208 dcr->VolMediaId = dev->VolCatInfo.VolMediaId;
1209 dev->file_addr += block->read_len;
1210 dev->file_size += block->read_len;
1211
1212 /*
1213 * If we read a short block on disk,
1214 * seek to beginning of next block. This saves us
1215 * from shuffling blocks around in the buffer. Take a
1216 * look at this from an efficiency stand point later, but
1217 * it should only happen once at the end of each job.
1218 *
1219 * I've been lseek()ing negative relative to SEEK_CUR for 30
1220 * years now. However, it seems that with the new off_t definition,
1221 * it is not possible to seek negative amounts, so we use two
1222 * lseek(). One to get the position, then the second to do an
1223 * absolute positioning -- so much for efficiency. KES Sep 02.
1224 */
1225 Dmsg0(250, "At end of read block\n");
1226 if (block->read_len > block->block_len && !dev->IsTape()) {
1227 char ed1[50];
1228 boffset_t pos
1229 = dev->d_lseek(dcr, (boffset_t)0, SEEK_CUR); /* get curr pos */
1230 Dmsg1(250, "Current lseek pos=%s\n", edit_int64(pos, ed1));
1231 pos -= (block->read_len - block->block_len);
1232 dev->d_lseek(dcr, pos, SEEK_SET);
1233 Dmsg3(250, "Did lseek pos=%s blk_size=%d rdlen=%d\n", edit_int64(pos, ed1),
1234 block->block_len, block->read_len);
1235 dev->file_addr = pos;
1236 dev->file_size = pos;
1237 }
1238 Dmsg2(250, "Exit read_block read_len=%d block_len=%d\n", block->read_len,
1239 block->block_len);
1240 block->block_read = true;
1241 return ReadStatus::Ok;
1242 }
1243
1244 } /* namespace storagedaemon */
1245