]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/block.c
Vacation updates -- see kes06Oct02
[bacula/bacula] / bacula / src / stored / block.c
1 /*
2  *
3  *   block.c -- tape block handling functions
4  *
5  *              Kern Sibbald, March MMI
6  *
7  *   Version $Id$
8  *
9  */
10 /*
11    Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
12
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.
17
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.
22
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,
26    MA 02111-1307, USA.
27
28  */
29
30
31 #include "bacula.h"
32 #include "stored.h"
33
34 extern int debug_level;
35
36 /*
37  * Dump the block header, then walk through
38  * the block printing out the record headers.
39  */
40 void dump_block(DEV_BLOCK *b, char *msg)
41 {
42    ser_declare;
43    char *p;
44    char Id[BLKHDR_ID_LENGTH+1];
45    uint32_t CheckSum, BlockCheckSum;
46    uint32_t block_len;
47    uint32_t BlockNumber;
48    uint32_t VolSessionId, VolSessionTime, data_len;
49    int32_t  FileIndex;
50    int32_t  Stream;
51    int bhl, rhl;
52
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;
60    if (Id[3] == '2') {
61       unser_uint32(VolSessionId);
62       unser_uint32(VolSessionTime);
63       bhl = BLKHDR2_LENGTH;
64       rhl = RECHDR2_LENGTH;
65    } else {
66       VolSessionId = VolSessionTime = 0;
67       bhl = BLKHDR1_LENGTH;
68       rhl = RECHDR1_LENGTH;
69    }
70
71    if (block_len > 100000) {
72       Dmsg3(20, "Dump block %s %s blocksize too big %d\n", msg, b, block_len);
73       return;
74    }
75
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);
81    p = b->buf + bhl;
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);
87       }
88       unser_int32(FileIndex);
89       unser_int32(Stream);
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),
93            data_len, p);
94       p += data_len + rhl;
95   }
96 }
97     
98 /*
99  * Create a new block structure.                           
100  * We pass device so that the block can inherit the
101  * min and max block sizes.
102  */
103 DEV_BLOCK *new_block(DEVICE *dev)
104 {
105    DEV_BLOCK *block = (DEV_BLOCK *)get_memory(sizeof(DEV_BLOCK));
106
107    memset(block, 0, sizeof(DEV_BLOCK));
108
109    if (dev->max_block_size == 0) {
110       block->buf_len = DEFAULT_BLOCK_SIZE;
111    } else {
112       block->buf_len = dev->max_block_size;
113    }
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;
119    }
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);
125       return NULL;
126    }
127    empty_block(block);
128    block->BlockVer = BLOCK_VER;       /* default write version */
129    Dmsg1(90, "Returning new block=%x\n", block);
130    return block;
131 }
132
133 /*
134  * Free block 
135  */
136 void free_block(DEV_BLOCK *block)
137 {
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);
142 }
143
144 /* Empty the block -- for writing */
145 void empty_block(DEV_BLOCK *block)
146 {
147    block->binbuf = WRITE_BLKHDR_LENGTH;
148    block->bufp = block->buf + block->binbuf;
149    block->read_len = 0;
150    block->failed_write = FALSE;
151 }
152
153 /*
154  * Create block header just before write. The space
155  * in the buffer should have already been reserved by
156  * init_block.
157  */
158 static void ser_block_header(DEV_BLOCK *block)
159 {
160    ser_declare;
161    uint32_t CheckSum = 0;
162    uint32_t block_len = block->binbuf;
163    
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);
173    }
174
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 */
181 }
182
183 /*
184  * Unserialized the block header for reading block.
185  *  This includes setting all the buffer pointers correctly.
186  *
187  *  Returns: 0 on failure (not a block)
188  *           1 on success
189  */
190 static int unser_block_header(DEVICE *dev, DEV_BLOCK *block)
191 {
192    ser_declare;
193    char Id[BLKHDR_ID_LENGTH+1];
194    uint32_t CheckSum, BlockCheckSum;
195    uint32_t block_len;
196    uint32_t EndBlock;
197    uint32_t BlockNumber;
198    int bhl;
199
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);
206
207    Id[BLKHDR_ID_LENGTH] = 0;
208    if (Id[3] == '1') {
209       bhl = BLKHDR1_LENGTH;
210       block->BlockVer = 1;
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"),
214             BLKHDR1_ID, Id);
215       Emsg0(M_ERROR, 0, dev->errmsg);
216       return 0;
217    }
218    } else {
219       unser_uint32(block->VolSessionId);
220       unser_uint32(block->VolSessionTime);
221       bhl = BLKHDR2_LENGTH;
222       block->BlockVer = 2;
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"),
226             BLKHDR2_ID, Id);
227          Emsg0(M_ERROR, 0, dev->errmsg);
228          return 0;
229       }
230    }
231
232    ASSERT(block_len < MAX_BLOCK_LENGTH);    /* temp sanity check */
233
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;
238    } else {
239       EndBlock = block_len;
240    }
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,
245       bhl, block_len);
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);
250       return 0;
251    }
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,
257             CheckSum);
258          Mmsg2(&dev->errmsg, _("Block checksum mismatch: calc=%x blk=%x\n"), BlockCheckSum,
259             CheckSum);
260          return 0;
261       }
262    }
263    return 1;
264 }
265
266 /*  
267  * Write a block to the device, with locking and unlocking
268  *
269  * Returns: 1 on success
270  *        : 0 on failure
271  *
272  */
273 int write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
274 {
275    int stat = 1;
276    lock_device(dev);
277    if (!write_block_to_dev(dev, block)) {
278        stat = fixup_device_block_write_error(jcr, dev, block);
279    }
280    unlock_device(dev);
281    return stat;
282 }
283
284 /*
285  * Write a block to the device 
286  *
287  *  Returns: 1 on success or EOT
288  *           0 on hard error
289  */
290 int write_block_to_dev(DEVICE *dev, DEV_BLOCK *block)
291 {
292    size_t stat = 0;
293    uint32_t wlen;                     /* length to write */
294
295 #ifdef NO_TAPE_WRITE_TEST
296    empty_block(block);
297    return 1;
298 #endif
299    ASSERT(block->binbuf == ((uint32_t) (block->bufp - block->buf)));
300
301    /* dump_block(block, "before write"); */
302    if (dev->state & ST_WEOT) {
303       Dmsg0(100, "return write_block_to_dev with ST_WEOT\n");
304       return 0;
305    }
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");
309       return 1;
310    }
311    /* 
312     * Clear to the end of the buffer if it is not full,
313     *  and on tape devices, apply min and fixed blocking.
314     */
315    if (wlen != block->buf_len) {
316       uint32_t blen;                  /* current buffer length */
317
318       Dmsg2(200, "binbuf=%d buf_len=%d\n", block->binbuf, block->buf_len);
319       blen = wlen;
320
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;
325          }
326          if (dev->min_block_size == dev->max_block_size) {
327             wlen = block->buf_len;    /* fixed block size already rounded */
328          }
329       }
330       if (wlen-blen > 0) {
331          memset(block->bufp, 0, wlen-blen); /* clear garbage */
332       }
333    }  
334
335    dev->block_num++;
336    block->BlockNumber = dev->block_num;
337    ser_block_header(block);
338
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 */
350       return 0;
351    }
352
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.
362        */
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);
366
367       if (dev->dev_errno == 0) {
368          dev->dev_errno = ENOSPC;        /* out of space */
369       }
370
371       Dmsg2(0, "=== Write error errno=%d: ERR=%s\n", dev->dev_errno,
372          strerror(dev->dev_errno));
373
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 */
379       return 0;
380    }
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;
385
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 */
390    }
391    }
392
393    Dmsg2(190, "write_block: wrote block %d bytes=%d\n", dev->block_num,
394       wlen);
395    empty_block(block);
396    return 1;
397 }
398
399 /*  
400  * Read block with locking
401  *
402  */
403 int read_block_from_device(DEVICE *dev, DEV_BLOCK *block)
404 {
405    int stat;
406    Dmsg0(90, "Enter read_block_from_device\n");
407    lock_device(dev);
408    stat = read_block_from_dev(dev, block);
409    unlock_device(dev);
410    Dmsg0(90, "Leave read_block_from_device\n");
411    return stat;
412 }
413
414 /*
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.
418  */
419 int read_block_from_dev(DEVICE *dev, DEV_BLOCK *block)
420 {
421    size_t stat;
422
423    Dmsg1(100, "Full read() in read_block_from_device() len=%d\n",
424          block->buf_len);
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) {
427
428 /* ***FIXME****  add code to detect buffer too small, and
429    reallocate buffer, backspace, and reread.
430    ENOMEM
431  */
432
433       Dmsg1(90, "Read device got: ERR=%s\n", strerror(errno));
434       clrerror_dev(dev, -1);
435       block->read_len = 0;
436       Mmsg2(&dev->errmsg, _("Read error on device %s. ERR=%s.\n"), 
437          dev->dev_name, strerror(dev->dev_errno));
438       return 0;
439    }
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 */
447          return 0;
448       }
449       dev->file++;              /* increment file */
450       dev->state |= ST_EOF;     /* set EOF read */
451       return 0;                 /* return eof */
452    }
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 */
461    }  
462    if (!unser_block_header(dev, block)) {
463       return 0;
464    }
465
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 */
472    }  
473
474    /* Make sure block size is not too big (temporary
475     * sanity check) and that we read the full block.
476     */
477    ASSERT(block->block_len < MAX_BLOCK_LENGTH);
478
479    dev->state &= ~(ST_EOF|ST_SHORT); /* clear EOF and short block */
480    dev->block_num++;
481
482    /*
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.
488     *
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.
494     */
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,
501             block->read_len);
502    }
503    Dmsg2(200, "Exit read_block read_len=%d block_len=%d\n",
504       block->read_len, block->block_len);
505    return 1;
506 }