3 * block.c -- tape block handling functions
5 * Kern Sibbald, March MMI
9 Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License as
13 published by the Free Software Foundation; either version 2 of
14 the License, or (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public
22 License along with this program; if not, write to the Free
23 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
32 extern int debug_level;
35 * Dump the block header, then walk through
36 * the block printing out the record headers.
38 void dump_block(DEV_BLOCK *b, char *msg)
42 char Id[BLKHDR_ID_LENGTH+1];
43 uint32_t CheckSum, BlockCheckSum;
46 uint32_t VolSessionId, VolSessionTime, data_len;
50 unser_begin(b->buf, BLKHDR_LENGTH);
51 unser_uint32(CheckSum);
52 unser_uint32(block_len);
53 unser_uint32(BlockNumber);
54 unser_bytes(Id, BLKHDR_ID_LENGTH);
55 ASSERT(unser_length(b->buf) == BLKHDR_LENGTH);
56 Id[BLKHDR_ID_LENGTH] = 0;
58 if (block_len > 100000) {
59 Dmsg3(20, "Dump block %s %s blocksize too big %d\n", msg, b, block_len);
63 BlockCheckSum = bcrc32((uint8_t *)b->buf+BLKHDR_CS_LENGTH,
64 block_len-BLKHDR_CS_LENGTH);
65 Dmsg6(10, "Dump block %s %x: size=%d BlkNum=%d\n\
66 Hdrcksum=%x cksum=%x\n",
67 msg, b, block_len, BlockNumber, CheckSum, BlockCheckSum);
68 p = b->buf + BLKHDR_LENGTH;
69 while (p < (b->buf + block_len+RECHDR_LENGTH)) {
70 unser_begin(p, RECHDR_LENGTH);
71 unser_uint32(VolSessionId);
72 unser_uint32(VolSessionTime);
73 unser_int32(FileIndex);
75 unser_uint32(data_len);
76 Dmsg6(10, "Rec: VId=%d VT=%d FI=%s Strm=%s len=%d p=%x\n",
77 VolSessionId, VolSessionTime, FI_to_ascii(FileIndex), stream_to_ascii(Stream),
79 p += data_len + RECHDR_LENGTH;
85 * Create a new block structure.
86 * We pass device so that the block can inherit the
87 * min and max block sizes.
89 DEV_BLOCK *new_block(DEVICE *dev)
91 DEV_BLOCK *block = (DEV_BLOCK *) get_memory(sizeof(DEV_BLOCK));
93 memset(block, 0, sizeof(DEV_BLOCK));
95 if (dev->max_block_size == 0) {
96 block->buf_len = DEFAULT_BLOCK_SIZE;
98 block->buf_len = dev->max_block_size;
100 if (block->buf_len % TAPE_BSIZE != 0) {
101 Mmsg2(&dev->errmsg, _("Block size %d forced to be multiple of %d\n"),
102 block->buf_len, TAPE_BSIZE);
103 Emsg0(M_WARNING, 0, dev->errmsg);
104 block->buf_len = ((block->buf_len + TAPE_BSIZE - 1) / TAPE_BSIZE) * TAPE_BSIZE;
106 block->block_len = block->buf_len; /* default block size */
107 block->buf = (char *) get_memory(block->buf_len);
108 if (block->buf == NULL) {
109 Mmsg0(&dev->errmsg, _("Unable to malloc block buffer.\n"));
110 Emsg0(M_FATAL, 0, dev->errmsg);
114 Dmsg1(90, "Returning new block=%x\n", block);
121 void free_block(DEV_BLOCK *block)
123 Dmsg1(199, "free_block buffer %x\n", block->buf);
124 free_memory(block->buf);
125 Dmsg1(199, "free_block block %x\n", block);
129 /* Empty the block -- for writing */
130 void empty_block(DEV_BLOCK *block)
132 block->binbuf = BLKHDR_LENGTH;
133 block->bufp = block->buf + block->binbuf;
135 block->failed_write = FALSE;
139 * Create block header just before write. The space
140 * in the buffer should have already been reserved by
143 static void ser_block_header(DEV_BLOCK *block)
146 uint32_t CheckSum = 0;
147 uint32_t block_len = block->binbuf;
149 Dmsg1(190, "ser_block_header: block_len=%d\n", block_len);
150 ser_begin(block->buf, BLKHDR_LENGTH);
151 ser_uint32(CheckSum);
152 ser_uint32(block_len);
153 ser_uint32(block->BlockNumber);
154 ser_bytes(BLKHDR_ID, BLKHDR_ID_LENGTH);
155 ASSERT(ser_length(block->buf) == BLKHDR_LENGTH);
157 /* Checksum whole block except for the checksum */
158 CheckSum = bcrc32((uint8_t *)block->buf+BLKHDR_CS_LENGTH,
159 block_len-BLKHDR_CS_LENGTH);
160 Dmsg1(190, "ser_bloc_header: checksum=%x\n", CheckSum);
161 ser_begin(block->buf, BLKHDR_LENGTH);
162 ser_uint32(CheckSum);
166 * Unserialized the block header for reading block.
167 * This includes setting all the buffer pointers correctly.
169 * Returns: 0 on failure (not a block)
172 static int unser_block_header(DEVICE *dev, DEV_BLOCK *block)
175 char Id[BLKHDR_ID_LENGTH+1];
176 uint32_t CheckSum, BlockCheckSum;
179 uint32_t BlockNumber;
181 unser_begin(block->buf, BLKHDR_LENGTH);
182 unser_uint32(CheckSum);
183 unser_uint32(block_len);
184 unser_uint32(BlockNumber);
185 unser_bytes(Id, BLKHDR_ID_LENGTH);
186 ASSERT(unser_length(block->buf) == BLKHDR_LENGTH);
188 Id[BLKHDR_ID_LENGTH] = 0;
189 block->bufp = block->buf + BLKHDR_LENGTH;
190 if (strncmp(Id, BLKHDR_ID, BLKHDR_ID_LENGTH) != 0) {
191 Mmsg2(&dev->errmsg, _("Buffer ID error. Wanted: %s, got %s. Buffer discarded.\n"),
193 Emsg0(M_ERROR, 0, dev->errmsg);
197 ASSERT(block_len < MAX_BLOCK_LENGTH); /* temp sanity check */
199 Dmsg1(190, "unser_block_header block_len=%d\n", block_len);
200 /* Find end of block or end of buffer whichever is smaller */
201 if (block_len > block->read_len) {
202 EndBlock = block->read_len;
204 EndBlock = block_len;
206 block->binbuf = EndBlock - BLKHDR_LENGTH;
207 block->block_len = block_len;
208 block->BlockNumber = BlockNumber;
209 Dmsg3(190, "Read binbuf = %d %d block_len=%d\n", block->binbuf,
210 BLKHDR_LENGTH, block_len);
211 if (block_len > block->buf_len) {
212 Mmsg2(&dev->errmsg, _("Block length %d is greater than buffer %d\n"),
213 block_len, block->buf_len);
214 Emsg0(M_ERROR, 0, dev->errmsg);
217 if (block_len <= block->read_len) {
218 BlockCheckSum = bcrc32((uint8_t *)block->buf+BLKHDR_CS_LENGTH,
219 block_len-BLKHDR_CS_LENGTH);
220 if (BlockCheckSum != CheckSum) {
221 Dmsg2(00, "Block checksum mismatch: calc=%x blk=%x\n", BlockCheckSum,
223 Mmsg2(&dev->errmsg, _("Block checksum mismatch: calc=%x blk=%x\n"), BlockCheckSum,
232 * Write a block to the device, with locking and unlocking
234 * Returns: 1 on success
238 int write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
242 if (!write_block_to_dev(dev, block)) {
243 stat = fixup_device_block_write_error(jcr, dev, block);
250 * Write a block to the device
252 * Returns: 1 on success or EOT
255 int write_block_to_dev(DEVICE *dev, DEV_BLOCK *block)
258 uint32_t wlen; /* length to write */
260 ASSERT(block->binbuf == ((uint32_t) (block->bufp - block->buf)));
262 /* dump_block(block, "before write"); */
263 if (dev->state & ST_WEOT) {
264 Dmsg0(90, "return write_block_to_dev with ST_WEOT\n");
267 wlen = block->binbuf;
268 if (wlen <= BLKHDR_LENGTH) { /* Does block have data in it? */
269 Dmsg0(190, "return write_block_to_dev no data to write\n");
273 * Clear to the end of the buffer if it is not full,
274 * and on tape devices, apply min and fixed blocking.
276 if (wlen != block->buf_len) {
277 uint32_t blen; /* current buffer length */
279 Dmsg2(200, "binbuf=%d buf_len=%d\n", block->binbuf, block->buf_len);
282 /* Adjust write size to min/max for tapes only */
283 if (dev->state & ST_TAPE) {
284 if (wlen < dev->min_block_size) {
285 wlen = ((dev->min_block_size + TAPE_BSIZE - 1) / TAPE_BSIZE) * TAPE_BSIZE;
287 if (dev->min_block_size == dev->max_block_size) {
288 wlen = block->buf_len; /* fixed block size already rounded */
292 memset(block->bufp, 0, wlen-blen); /* clear garbage */
297 block->BlockNumber = dev->block_num;
298 ser_block_header(block);
300 /* dump_block(block, "after ser_hdr"); */
301 if ((dev->max_volume_size > 0) &&
302 ((int64_t) (dev->VolCatInfo.VolCatBytes + block->binbuf)) >= dev->max_volume_size) {
303 dev->state |= ST_WEOT;
304 Dmsg0(10, "==== Output bytes Triggered medium max capacity.\n");
305 Mmsg2(&dev->errmsg, _("Max. Volume capacity %" lld " exceeded on device %s.\n"),
306 dev->max_volume_size, dev->dev_name);
307 block->failed_write = TRUE;
308 /* ****FIXME**** write EOD record here */
309 weof_dev(dev, 1); /* end the tape */
310 weof_dev(dev, 1); /* write second eof */
314 dev->VolCatInfo.VolCatWrites++;
315 if ((uint32_t) (stat=write(dev->fd, block->buf, wlen)) != wlen) {
316 /* We should check for errno == ENOSPC, BUT many
317 * devices simply report EIO when it is full.
318 * with a little more thought we may be able to check
319 * capacity and distinguish real errors and EOT
320 * conditions. In any case, we probably want to
321 * simulate an End of Medium.
323 /***FIXME**** if we wrote a partial record, back up over it */
324 dev->state |= ST_EOF | ST_EOT | ST_WEOT;
325 clrerror_dev(dev, -1);
327 Dmsg2(0, "=== Write error %d: ERR=%s\n", dev->dev_errno,
328 strerror(dev->dev_errno));
330 if (dev->dev_errno == 0) {
331 dev->dev_errno = ENOSPC; /* out of space */
333 Mmsg2(&dev->errmsg, _("Write error on device %s. ERR=%s.\n"),
334 dev->dev_name, strerror(dev->dev_errno));
335 block->failed_write = TRUE;
336 weof_dev(dev, 1); /* end the tape */
337 weof_dev(dev, 1); /* write second eof */
340 dev->VolCatInfo.VolCatBytes += block->binbuf;
341 dev->VolCatInfo.VolCatBlocks++;
342 Dmsg2(190, "write_block: wrote block %d bytes=%d\n", dev->block_num,
349 * Read block with locking
352 int read_block_from_device(DEVICE *dev, DEV_BLOCK *block)
355 Dmsg0(90, "Enter read_block_from_device\n");
357 stat = read_block_from_dev(dev, block);
359 Dmsg0(90, "Leave read_block_from_device\n");
364 * Read the next block into the block structure and unserialize
365 * the block header. For a file, the block may be partially
366 * or completely in the current buffer.
368 int read_block_from_dev(DEVICE *dev, DEV_BLOCK *block)
372 Dmsg0(90, "Full read() in read_block_from_device()\n");
373 if ((stat=read(dev->fd, block->buf, block->buf_len)) < 0) {
375 /* ***FIXME**** add code to detect buffer too small, and
376 reallocate buffer, backspace, and reread.
380 Dmsg1(90, "Read device got: ERR=%s\n", strerror(errno));
381 clrerror_dev(dev, -1);
383 Mmsg2(&dev->errmsg, _("Read error on device %s. ERR=%s.\n"),
384 dev->dev_name, strerror(dev->dev_errno));
387 Dmsg1(90, "Read device got %d bytes\n", stat);
388 if (stat == 0) { /* Got EOF ! */
389 dev->block_num = block->read_len = 0;
390 Mmsg1(&dev->errmsg, _("Read zero bytes on device %s.\n"), dev->dev_name);
391 if (dev->state & ST_EOF) { /* EOF alread read? */
392 dev->state |= ST_EOT; /* yes, 2 EOFs => EOT */
395 dev->file++; /* increment file */
396 dev->state |= ST_EOF; /* set EOF read */
397 return 0; /* return eof */
399 /* Continue here for successful read */
400 block->read_len = stat; /* save length read */
401 if (block->read_len < BLKHDR_LENGTH) {
402 Mmsg2(&dev->errmsg, _("Very short block of %d bytes on device %s discarded.\n"),
403 block->read_len, dev->dev_name);
404 dev->state |= ST_SHORT; /* set short block */
405 block->read_len = block->binbuf = 0;
406 return 0; /* return error */
408 if (!unser_block_header(dev, block)) {
412 if (block->block_len > block->read_len) {
413 Mmsg2(&dev->errmsg, _("Short block of %d bytes on device %s discarded.\n"),
414 block->read_len, dev->dev_name);
415 dev->state |= ST_SHORT; /* set short block */
416 block->read_len = block->binbuf = 0;
417 return 0; /* return error */
420 /* Make sure block size is not too big (temporary
421 * sanity check) and that we read the full block.
423 ASSERT(block->block_len < MAX_BLOCK_LENGTH);
425 dev->state &= ~(ST_EOF|ST_SHORT); /* clear EOF and short block */
429 * If we read a short block on disk,
430 * seek to beginning of next block. This saves us
431 * from shuffling blocks around in the buffer. Take a
432 * look at this from an efficiency stand point later, but
433 * it should only happen once at the end of each job.
435 Dmsg0(200, "At end of read block\n");
436 if (block->read_len > block->block_len && !(dev->state & ST_TAPE)) {
438 Dmsg3(200, "Block: %d read_len %d > %d block_len\n", dev->block_num,
439 block->read_len, block->block_len);
440 lseek(dev->fd, block->block_len-block->read_len, SEEK_CUR);
441 Dmsg2(90, "Did lseek blk_size=%d rdlen=%d\n", block->block_len,
444 Dmsg2(200, "Exit read_block read_len=%d block_len=%d\n",
445 block->read_len, block->block_len);