3 * block.c -- tape block handling functions
5 * Kern Sibbald, March MMI
11 Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of
16 the License, or (at your option) any later version.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
23 You should have received a copy of the GNU General Public
24 License along with this program; if not, write to the Free
25 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
34 extern int debug_level;
37 * Dump the block header, then walk through
38 * the block printing out the record headers.
40 void dump_block(DEV_BLOCK *b, char *msg)
44 char Id[BLKHDR_ID_LENGTH+1];
45 uint32_t CheckSum, BlockCheckSum;
48 uint32_t VolSessionId, VolSessionTime, data_len;
53 unser_begin(b->buf, BLKHDR1_LENGTH);
54 unser_uint32(CheckSum);
55 unser_uint32(block_len);
56 unser_uint32(BlockNumber);
57 unser_bytes(Id, BLKHDR_ID_LENGTH);
58 ASSERT(unser_length(b->buf) == BLKHDR1_LENGTH);
59 Id[BLKHDR_ID_LENGTH] = 0;
61 unser_uint32(VolSessionId);
62 unser_uint32(VolSessionTime);
66 VolSessionId = VolSessionTime = 0;
71 if (block_len > 100000) {
72 Dmsg3(20, "Dump block %s %s blocksize too big %d\n", msg, b, block_len);
76 BlockCheckSum = bcrc32((uint8_t *)b->buf+BLKHDR_CS_LENGTH,
77 block_len-BLKHDR_CS_LENGTH);
78 Dmsg6(10, "Dump block %s %x: size=%d BlkNum=%d\n\
79 Hdrcksum=%x cksum=%x\n",
80 msg, b, block_len, BlockNumber, CheckSum, BlockCheckSum);
82 while (p < (b->buf + block_len+WRITE_RECHDR_LENGTH)) {
83 unser_begin(p, WRITE_RECHDR_LENGTH);
84 if (rhl == RECHDR1_LENGTH) {
85 unser_uint32(VolSessionId);
86 unser_uint32(VolSessionTime);
88 unser_int32(FileIndex);
90 unser_uint32(data_len);
91 Dmsg6(10, " Rec: VId=%d VT=%d FI=%s Strm=%s len=%d p=%x\n",
92 VolSessionId, VolSessionTime, FI_to_ascii(FileIndex), stream_to_ascii(Stream),
99 * Create a new block structure.
100 * We pass device so that the block can inherit the
101 * min and max block sizes.
103 DEV_BLOCK *new_block(DEVICE *dev)
105 DEV_BLOCK *block = (DEV_BLOCK *)get_memory(sizeof(DEV_BLOCK));
107 memset(block, 0, sizeof(DEV_BLOCK));
109 if (dev->max_block_size == 0) {
110 block->buf_len = DEFAULT_BLOCK_SIZE;
112 block->buf_len = dev->max_block_size;
114 if (block->buf_len % TAPE_BSIZE != 0) {
115 Mmsg2(&dev->errmsg, _("Block size %d forced to be multiple of %d\n"),
116 block->buf_len, TAPE_BSIZE);
117 Emsg0(M_WARNING, 0, dev->errmsg);
118 block->buf_len = ((block->buf_len + TAPE_BSIZE - 1) / TAPE_BSIZE) * TAPE_BSIZE;
120 block->block_len = block->buf_len; /* default block size */
121 block->buf = get_memory(block->buf_len);
122 if (block->buf == NULL) {
123 Mmsg0(&dev->errmsg, _("Unable to malloc block buffer.\n"));
124 Emsg0(M_FATAL, 0, dev->errmsg);
128 block->BlockVer = BLOCK_VER; /* default write version */
129 Dmsg1(90, "Returning new block=%x\n", block);
136 void free_block(DEV_BLOCK *block)
138 Dmsg1(199, "free_block buffer %x\n", block->buf);
139 free_memory(block->buf);
140 Dmsg1(199, "free_block block %x\n", block);
141 free_memory((POOLMEM *)block);
144 /* Empty the block -- for writing */
145 void empty_block(DEV_BLOCK *block)
147 block->binbuf = WRITE_BLKHDR_LENGTH;
148 block->bufp = block->buf + block->binbuf;
150 block->failed_write = FALSE;
154 * Create block header just before write. The space
155 * in the buffer should have already been reserved by
158 static void ser_block_header(DEV_BLOCK *block)
161 uint32_t CheckSum = 0;
162 uint32_t block_len = block->binbuf;
164 Dmsg1(190, "ser_block_header: block_len=%d\n", block_len);
165 ser_begin(block->buf, BLKHDR2_LENGTH);
166 ser_uint32(CheckSum);
167 ser_uint32(block_len);
168 ser_uint32(block->BlockNumber);
169 ser_bytes(WRITE_BLKHDR_ID, BLKHDR_ID_LENGTH);
170 if (BLOCK_VER >= 2) {
171 ser_uint32(block->VolSessionId);
172 ser_uint32(block->VolSessionTime);
175 /* Checksum whole block except for the checksum */
176 CheckSum = bcrc32((uint8_t *)block->buf+BLKHDR_CS_LENGTH,
177 block_len-BLKHDR_CS_LENGTH);
178 Dmsg1(190, "ser_bloc_header: checksum=%x\n", CheckSum);
179 ser_begin(block->buf, BLKHDR2_LENGTH);
180 ser_uint32(CheckSum); /* now add checksum to block header */
184 * Unserialized the block header for reading block.
185 * This includes setting all the buffer pointers correctly.
187 * Returns: 0 on failure (not a block)
190 static int unser_block_header(DEVICE *dev, DEV_BLOCK *block)
193 char Id[BLKHDR_ID_LENGTH+1];
194 uint32_t CheckSum, BlockCheckSum;
197 uint32_t BlockNumber;
200 unser_begin(block->buf, BLKHDR_LENGTH);
201 unser_uint32(CheckSum);
202 unser_uint32(block_len);
203 unser_uint32(BlockNumber);
204 unser_bytes(Id, BLKHDR_ID_LENGTH);
205 ASSERT(unser_length(block->buf) == BLKHDR1_LENGTH);
207 Id[BLKHDR_ID_LENGTH] = 0;
209 bhl = BLKHDR1_LENGTH;
211 block->bufp = block->buf + bhl;
212 if (strncmp(Id, BLKHDR1_ID, BLKHDR_ID_LENGTH) != 0) {
213 Mmsg2(&dev->errmsg, _("Buffer ID error. Wanted: %s, got %s. Buffer discarded.\n"),
215 Emsg0(M_ERROR, 0, dev->errmsg);
219 unser_uint32(block->VolSessionId);
220 unser_uint32(block->VolSessionTime);
221 bhl = BLKHDR2_LENGTH;
223 block->bufp = block->buf + bhl;
224 if (strncmp(Id, BLKHDR2_ID, BLKHDR_ID_LENGTH) != 0) {
225 Mmsg2(&dev->errmsg, _("Buffer ID error. Wanted: %s, got %s. Buffer discarded.\n"),
227 Emsg0(M_ERROR, 0, dev->errmsg);
232 ASSERT(block_len < MAX_BLOCK_LENGTH); /* temp sanity check */
234 Dmsg1(190, "unser_block_header block_len=%d\n", block_len);
235 /* Find end of block or end of buffer whichever is smaller */
236 if (block_len > block->read_len) {
237 EndBlock = block->read_len;
239 EndBlock = block_len;
241 block->binbuf = EndBlock - bhl;
242 block->block_len = block_len;
243 block->BlockNumber = BlockNumber;
244 Dmsg3(190, "Read binbuf = %d %d block_len=%d\n", block->binbuf,
246 if (block_len > block->buf_len) {
247 Mmsg2(&dev->errmsg, _("Block length %u is greater than buffer %u\n"),
248 block_len, block->buf_len);
249 Emsg0(M_ERROR, 0, dev->errmsg);
252 if (block_len <= block->read_len) {
253 BlockCheckSum = bcrc32((uint8_t *)block->buf+BLKHDR_CS_LENGTH,
254 block_len-BLKHDR_CS_LENGTH);
255 if (BlockCheckSum != CheckSum) {
256 Dmsg2(00, "Block checksum mismatch: calc=%x blk=%x\n", BlockCheckSum,
258 Mmsg2(&dev->errmsg, _("Block checksum mismatch: calc=%x blk=%x\n"), BlockCheckSum,
267 * Write a block to the device, with locking and unlocking
269 * Returns: 1 on success
273 int write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
277 if (!write_block_to_dev(dev, block)) {
278 stat = fixup_device_block_write_error(jcr, dev, block);
285 * Write a block to the device
287 * Returns: 1 on success or EOT
290 int write_block_to_dev(DEVICE *dev, DEV_BLOCK *block)
293 uint32_t wlen; /* length to write */
295 #ifdef NO_TAPE_WRITE_TEST
299 ASSERT(block->binbuf == ((uint32_t) (block->bufp - block->buf)));
301 /* dump_block(block, "before write"); */
302 if (dev->state & ST_WEOT) {
303 Dmsg0(100, "return write_block_to_dev with ST_WEOT\n");
306 wlen = block->binbuf;
307 if (wlen <= WRITE_BLKHDR_LENGTH) { /* Does block have data in it? */
308 Dmsg0(100, "return write_block_to_dev no data to write\n");
312 * Clear to the end of the buffer if it is not full,
313 * and on tape devices, apply min and fixed blocking.
315 if (wlen != block->buf_len) {
316 uint32_t blen; /* current buffer length */
318 Dmsg2(200, "binbuf=%d buf_len=%d\n", block->binbuf, block->buf_len);
321 /* Adjust write size to min/max for tapes only */
322 if (dev->state & ST_TAPE) {
323 if (wlen < dev->min_block_size) {
324 wlen = ((dev->min_block_size + TAPE_BSIZE - 1) / TAPE_BSIZE) * TAPE_BSIZE;
326 if (dev->min_block_size == dev->max_block_size) {
327 wlen = block->buf_len; /* fixed block size already rounded */
331 memset(block->bufp, 0, wlen-blen); /* clear garbage */
336 block->BlockNumber = dev->block_num;
337 ser_block_header(block);
339 /* Limit maximum Volume size to value specified by user */
340 if ((dev->max_volume_size > 0) &&
341 ((dev->VolCatInfo.VolCatBytes + block->binbuf)) >= dev->max_volume_size) {
342 dev->state |= ST_WEOT;
343 Dmsg0(10, "==== Output bytes Triggered medium max capacity.\n");
344 Mmsg2(&dev->errmsg, _("Max. Volume capacity %" lld " exceeded on device %s.\n"),
345 dev->max_volume_size, dev->dev_name);
346 block->failed_write = TRUE;
347 /* ****FIXME**** write EOD record here */
348 weof_dev(dev, 1); /* end the tape */
349 weof_dev(dev, 1); /* write second eof */
353 dev->VolCatInfo.VolCatWrites++;
354 // Dmsg1(000, "Pos before write=%lld\n", lseek(dev->fd, (off_t)0, SEEK_CUR));
355 if ((uint32_t) (stat=write(dev->fd, block->buf, (size_t)wlen)) != wlen) {
356 /* We should check for errno == ENOSPC, BUT many
357 * devices simply report EIO when it is full.
358 * with a little more thought we may be able to check
359 * capacity and distinguish real errors and EOT
360 * conditions. In any case, we probably want to
361 * simulate an End of Medium.
363 /***FIXME**** if we wrote a partial record, back up over it */
364 dev->state |= ST_EOF | ST_EOT | ST_WEOT;
365 clrerror_dev(dev, -1);
367 if (dev->dev_errno == 0) {
368 dev->dev_errno = ENOSPC; /* out of space */
371 Dmsg2(0, "=== Write error errno=%d: ERR=%s\n", dev->dev_errno,
372 strerror(dev->dev_errno));
374 Mmsg2(&dev->errmsg, _("Write error on device %s. ERR=%s.\n"),
375 dev->dev_name, strerror(dev->dev_errno));
376 block->failed_write = TRUE;
377 weof_dev(dev, 1); /* end the tape */
378 weof_dev(dev, 1); /* write second eof */
381 // Dmsg1(000, "Pos after write=%lld\n", lseek(dev->fd, (off_t)0, SEEK_CUR));
382 dev->VolCatInfo.VolCatBytes += block->binbuf;
383 dev->VolCatInfo.VolCatBlocks++;
384 dev->file_bytes += block->binbuf;
386 /* Limit maximum File size on volume to user specified value */
387 if (dev->state & ST_TAPE) {
388 if ((dev->max_file_size > 0) && dev->file_bytes >= dev->max_file_size) {
389 weof_dev(dev, 1); /* write eof */
393 Dmsg2(190, "write_block: wrote block %d bytes=%d\n", dev->block_num,
400 * Read block with locking
403 int read_block_from_device(DEVICE *dev, DEV_BLOCK *block)
406 Dmsg0(90, "Enter read_block_from_device\n");
408 stat = read_block_from_dev(dev, block);
410 Dmsg0(90, "Leave read_block_from_device\n");
415 * Read the next block into the block structure and unserialize
416 * the block header. For a file, the block may be partially
417 * or completely in the current buffer.
419 int read_block_from_dev(DEVICE *dev, DEV_BLOCK *block)
423 Dmsg1(100, "Full read() in read_block_from_device() len=%d\n",
425 // Dmsg1(000, "Pos before read=%lld\n", lseek(dev->fd, (off_t)0, SEEK_CUR));
426 if ((stat=read(dev->fd, block->buf, (size_t)block->buf_len)) < 0) {
428 /* ***FIXME**** add code to detect buffer too small, and
429 reallocate buffer, backspace, and reread.
433 Dmsg1(90, "Read device got: ERR=%s\n", strerror(errno));
434 clrerror_dev(dev, -1);
436 Mmsg2(&dev->errmsg, _("Read error on device %s. ERR=%s.\n"),
437 dev->dev_name, strerror(dev->dev_errno));
440 // Dmsg1(000, "Pos after read=%lld\n", lseek(dev->fd, (off_t)0, SEEK_CUR));
441 Dmsg1(90, "Read device got %d bytes\n", stat);
442 if (stat == 0) { /* Got EOF ! */
443 dev->block_num = block->read_len = 0;
444 Mmsg1(&dev->errmsg, _("Read zero bytes on device %s.\n"), dev->dev_name);
445 if (dev->state & ST_EOF) { /* EOF alread read? */
446 dev->state |= ST_EOT; /* yes, 2 EOFs => EOT */
449 dev->file++; /* increment file */
450 dev->state |= ST_EOF; /* set EOF read */
451 return 0; /* return eof */
453 /* Continue here for successful read */
454 block->read_len = stat; /* save length read */
455 if (block->read_len < BLKHDR2_LENGTH) {
456 Mmsg2(&dev->errmsg, _("Very short block of %d bytes on device %s discarded.\n"),
457 block->read_len, dev->dev_name);
458 dev->state |= ST_SHORT; /* set short block */
459 block->read_len = block->binbuf = 0;
460 return 0; /* return error */
462 if (!unser_block_header(dev, block)) {
466 if (block->block_len > block->read_len) {
467 Mmsg2(&dev->errmsg, _("Short block of %d bytes on device %s discarded.\n"),
468 block->read_len, dev->dev_name);
469 dev->state |= ST_SHORT; /* set short block */
470 block->read_len = block->binbuf = 0;
471 return 0; /* return error */
474 /* Make sure block size is not too big (temporary
475 * sanity check) and that we read the full block.
477 ASSERT(block->block_len < MAX_BLOCK_LENGTH);
479 dev->state &= ~(ST_EOF|ST_SHORT); /* clear EOF and short block */
483 * If we read a short block on disk,
484 * seek to beginning of next block. This saves us
485 * from shuffling blocks around in the buffer. Take a
486 * look at this from an efficiency stand point later, but
487 * it should only happen once at the end of each job.
489 * I've been lseek()ing negative relative to SEEK_CUR for 30
490 * years now. However, it seems that with the new off_t definition,
491 * it is not possible to seek negative amounts, so we use two
492 * lseek(). One to get the position, then the second to do an
493 * absolute positioning -- so much for efficiency. KES Sep 02.
495 Dmsg0(200, "At end of read block\n");
496 if (block->read_len > block->block_len && !(dev->state & ST_TAPE)) {
497 off_t pos = lseek(dev->fd, (off_t)0, SEEK_CUR); /* get curr pos */
498 pos -= (block->read_len - block->block_len);
499 lseek(dev->fd, pos, SEEK_SET);
500 Dmsg2(100, "Did lseek blk_size=%d rdlen=%d\n", block->block_len,
503 Dmsg2(200, "Exit read_block read_len=%d block_len=%d\n",
504 block->read_len, block->block_len);