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