]> git.sur5r.net Git - bacula/bacula/blob - bacula/patches/testing/faketape2.patch
ebl update
[bacula/bacula] / bacula / patches / testing / faketape2.patch
1 Index: src/stored/faketape.c
2 ===================================================================
3 --- src/stored/faketape.c       (révision 7092)
4 +++ src/stored/faketape.c       (copie de travail)
5 @@ -63,7 +63,7 @@
6  #ifdef USE_FAKETAPE
7  #include "faketape.h"
8  
9 -static int dbglevel = 10;
10 +static int dbglevel = 0;
11  #define FILE_OFFSET 30
12  faketape *ftape_list[FTAPE_MAX_DRIVE];
13  
14 @@ -170,6 +170,7 @@
15  int faketape::tape_op(struct mtop *mt_com)
16  {
17     int result=0;
18 +   int count = mt_com->mt_count;
19  
20     if (!online) {
21        errno = ENOMEDIUM;
22 @@ -193,11 +194,15 @@
23        break;
24  
25     case MTFSF:                  /* Forward space over mt_count filemarks. */
26 -      result = fsf(mt_com->mt_count);
27 +      do {
28 +        result = fsf();
29 +      } while (--count > 0 && result == 0);
30        break;
31  
32     case MTBSF:                  /* Backward space over mt_count filemarks. */
33 -      result = bsf(mt_com->mt_count);
34 +      do {
35 +        result = bsf();
36 +      } while (--count > 0 && result == 0);
37        break;
38  
39     case MTFSR:      /* Forward space over mt_count records (tape blocks). */
40 @@ -222,16 +227,20 @@
41        break;
42  
43     case MTWEOF:                 /* Write mt_count filemarks. */
44 -      result = weof(mt_com->mt_count);
45 +      do {
46 +        result = weof();
47 +      } while (result == 0 && --count > 0);
48        break;
49  
50     case MTREW:                  /* Rewind. */
51        Dmsg0(dbglevel, "rewind faketape\n");
52 +      check_eof();
53        atEOF = atEOD = false;
54        atBOT = true;
55        current_file = 0;
56        current_block = 0;
57 -      seek_file();
58 +      lseek(fd, 0, SEEK_SET);
59 +      read_next_fm(true);
60        break;
61  
62     case MTOFFL:                 /* put tape offline */
63 @@ -253,19 +262,30 @@
64        break;
65  
66     case MTEOM:/* Go to the end of the recorded media (for appending files). */
67 +      while (next_FM) {
68 +        lseek(fd, next_FM, SEEK_SET);
69 +        if (read_next_fm(true)) {
70 +           current_file++;
71 +        }
72 +      }
73 +      off_t l;
74 +      while (::read(fd, &l, sizeof(l)) > 0) {
75 +        if (l) {
76 +           lseek(fd, l, SEEK_CUR);
77 +        } else {
78 +           ASSERT(0);
79 +        }
80 +        Dmsg0(dbglevel, "skip 1 block\n");
81 +      }
82 +      current_block = -1;
83 +      atEOF = false;
84 +      atEOD = true;
85 +
86  /*
87     file number = 3
88     block number = -1
89  */
90        /* Can be at EOM */
91 -      atBOT = false;
92 -      atEOF = false;
93 -      atEOD = true;
94 -      atEOT = false;
95 -
96 -      current_file = last_file;
97 -      current_block = -1;
98 -      seek_file();
99        break;
100  
101     case MTERASE:                /* not used by bacula */
102 @@ -275,7 +295,8 @@
103  
104        current_file = 0;
105        current_block = -1;
106 -      seek_file();
107 +      lseek(fd, 0, SEEK_SET);
108 +      read_next_fm(true);
109        truncate_file();
110        break;
111  
112 @@ -405,8 +426,8 @@
113     atEOT = false;
114     atEOD = false;
115     online = false;
116 -   inplace = false;
117     needEOF = false;
118 +   eot_count = 0;
119  
120     file_block = 0;
121     last_file = 0;
122 @@ -444,8 +465,6 @@
123        return -1;
124     }
125  
126 -   check_inplace();
127 -
128     if (!atEOD) {                /* if not at the end of the data */
129        truncate_file();
130     }
131 @@ -460,14 +479,6 @@
132  
133     needEOF = true;              /* next operation need EOF mark */
134  
135 -//   if ((count + file_size) > max_size) {
136 -//      Dmsg2(dbglevel, 
137 -//          "EOT writing only %i of %i requested\n", 
138 -//          max_size - file_size, count);
139 -//      count = max_size - file_size;
140 -//      atEOT = true;
141 -//   }
142 -
143     uint32_t size = count;
144     ::write(fd, &size, sizeof(uint32_t));
145     nb = ::write(fd, buffer, count);
146 @@ -484,43 +495,68 @@
147     return nb;
148  }
149  
150 -int faketape::weof(int count)
151 +/*
152 + *  +---+---------+---+------------------+---+-------------------+
153 + *  |00N|  DATA   |0LN|   DATA           |0LC|     DATA          |
154 + *  +---+---------+---+------------------+---+-------------------+
155 + *
156 + *  0 : zero
157 + *  L : Last FileMark offset
158 + *  N : Next FileMark offset
159 + *  C : Current FileMark Offset
160 + */
161 +int faketape::weof()
162  {
163     ASSERT(online);
164     ASSERT(current_file >= 0);
165     Dmsg3(dbglevel, "Writing EOF %i:%i last=%i\n", 
166           current_file, current_block,last_file);
167 +
168 +   off_t cur_FM;
169 +
170     if (atEOT) {
171        errno = ENOSPC;
172        current_block = -1;
173        return -1;
174     }
175 -   needEOF = false;
176  
177 -   check_inplace();
178 -   truncate_file();             /* nothing after this point */
179 +   if (!atEOD) {
180 +      truncate_file();             /* nothing after this point */
181 +   }
182 +   
183 +   cur_FM = lseek(fd, 0, SEEK_CUR); // current position
184  
185 +   /* update previous next_FM  */
186 +   lseek(fd, last_FM + sizeof(uint32_t)+sizeof(off_t), SEEK_SET);
187 +   ::write(fd, &cur_FM, sizeof(off_t));
188 +   lseek(fd, cur_FM, SEEK_SET);
189 +
190 +   prev_FM = last_FM;
191 +   last_FM = cur_FM;
192 +   next_FM = 0;
193 +
194     uint32_t c=0;
195 -   ::write(fd, &c, sizeof(uint32_t));
196 +   ::write(fd, &c,       sizeof(uint32_t)); // EOF
197 +   ::write(fd, &last_FM, sizeof(last_FM));  // F-1
198 +   ::write(fd, &next_FM, sizeof(next_FM));  // F   (will be updated next time)
199  
200 -   current_file += count;
201 +   current_file++;
202     current_block = 0;
203 -   seek_file();
204  
205 -   c=0;
206 -   ::write(fd, &c, sizeof(uint32_t));   
207 -   lseek(fd, lseek(fd, 0, SEEK_CUR) - sizeof(uint32_t), SEEK_SET);
208 -
209 +   needEOF = false;
210     atEOD = false;
211     atBOT = false;
212     atEOF = true;
213  
214 -   update_pos();
215 +   last_file = MAX(current_file, last_file);
216  
217     return 0;
218  }
219  
220 -int faketape::fsf(int count)
221 +/*
222 + * Go to next FM
223 + */
224 +int faketape::fsf()
225  {   
226     ASSERT(online);
227     ASSERT(current_file >= 0);
228 @@ -528,24 +564,33 @@
229  /*
230   * 1 0 -> fsf -> 2 0 -> fsf -> 2 -1
231   */
232 -   check_inplace();
233 -   check_eof();
234  
235 -   int ret;
236 +   int ret=0;
237     if (atEOT || atEOD) {
238        errno = EIO;
239        current_block = -1;
240        return -1;
241     }
242  
243 -   atBOT = atEOF = false;
244 -   Dmsg3(dbglevel+1, "fsf %i+%i <= %i\n", current_file, count, last_file);
245 +   atBOT = false;
246 +   Dmsg2(dbglevel+1, "fsf %i <= %i\n", current_file, last_file);
247  
248 -   if ((current_file + count) <= last_file) {
249 -      current_file += count;
250 -      current_block = 0;
251 +   if (next_FM > last_FM) {    /* not the last file */
252 +      lseek(fd, next_FM, SEEK_SET);
253 +      read_next_fm(true);
254 +      current_file++;
255 +      atEOF = true;
256        ret = 0;
257 -   } else {
258 +
259 +   } else if (atEOF) {         /* last file mark */
260 +      current_block=-1;
261 +      errno = EIO;
262 +      atEOF = false;
263 +      atEOD = true;
264 +
265 +   } else {                    /* last file, but no at the end */
266 +      fsr(100000);
267 +
268        Dmsg0(dbglevel, "Try to FSF after EOT\n");
269        errno = EIO;
270        current_file = last_file ;
271 @@ -553,10 +598,44 @@
272        atEOD=true;
273        ret = -1;
274     }
275 -   seek_file();
276     return ret;
277  }
278  
279 +/* /------------\ /---------------\
280 + * +---+------+---+---------------+-+
281 + * |OLN|      |0LN|               | |
282 + * +---+------+---+---------------+-+
283 + */
284 +bool faketape::read_next_fm(bool read_all /* read the 0 byte */)
285 +{
286 +   prev_FM = last_FM;
287 +   return read_fm(read_all);
288 +}
289 +
290 +bool faketape::read_fm(bool read_all /* read the 0 byte */)
291 +{
292 +   int ret;
293 +   uint32_t c;
294 +   if (read_all) {
295 +      ::read(fd, &c, sizeof(c));
296 +      if (c != 0) {
297 +        lseek(fd, lseek(fd, 0, SEEK_CUR) - sizeof(c), SEEK_SET);
298 +        return false;
299 +      }
300 +   }
301 +   ::read(fd, &last_FM, sizeof(last_FM));
302 +   ret = ::read(fd, &next_FM, sizeof(next_FM));
303 +
304 +   current_block=0;
305 +   
306 +   Dmsg1(dbglevel, "Read FM next=%lli\n", next_FM);
307 +
308 +   return (ret == sizeof(next_FM));
309 +}
310 +
311 +/*
312 + * TODO: Check fsr with EOF
313 + */
314  int faketape::fsr(int count)
315  {
316     ASSERT(online);
317 @@ -568,7 +647,6 @@
318     uint32_t s;
319     Dmsg3(dbglevel, "fsr %i:%i count=%i\n", current_file,current_block, count);
320  
321 -   check_inplace();
322     check_eof();
323  
324     if (atEOT) {
325 @@ -595,20 +673,23 @@
326                 current_file, current_block, nb,s);
327           errno = EIO;
328           ret = -1;
329 -         if (current_file < last_file) {
330 +        if (next_FM) {
331              current_block = 0;
332              current_file++;
333 -            seek_file();
334 -         }
335 +           read_next_fm(false);
336 +        }
337           atEOF = true;          /* stop the loop */
338        }
339     }
340  
341 -   find_maxfile();              /* refresh stats */
342 -
343     return ret;
344  }
345  
346 +/*
347 + * BSR + EOF => begin of EOF + EIO
348 + * BSR + BSR + EOF => last block
349 + * current_block = -1
350 + */
351  int faketape::bsr(int count)
352  {
353     Dmsg2(dbglevel, "bsr current_block=%i count=%i\n", 
354 @@ -619,7 +700,6 @@
355     ASSERT(count == 1);
356     ASSERT(fd >= 0);
357  
358 -   check_inplace();
359     check_eof();
360  
361     if (!count) {
362 @@ -641,22 +721,21 @@
363        return -1;
364     }
365  
366 +   /* at EOF 0:-1 BOT=0 EOD=0 EOF=0 ERR: Input/output error  */
367     if (atEOF) {
368 -      if (!current_block) {
369 -        if (current_file > 0) {
370 -           current_file--;
371 -        }
372 -        current_block=-1;
373 -        errno = EIO;
374 -        return -1;
375 -
376 -      } else {
377 -        atEOF=false;
378 -      }
379 +      lseek(fd, last_FM, SEEK_CUR);
380 +      atEOF = false;
381 +      current_block=-1;
382 +      errno = EIO;
383 +      return -1;
384     }
385  
386 -   current_block=0;
387 -   seek_file();
388 +   /*
389 +    * First, go to last_FM and read all blocks to find the good one
390 +    */
391 +   
392 +   lseek(fd, last_FM, SEEK_CUR);
393 +   read_fm(true);
394  
395     do {
396        if (!atEOF) {
397 @@ -700,31 +779,35 @@
398     return 0;
399  }
400  
401 -int faketape::bsf(int count)
402 +/* BSF => just before last EOF
403 + * EOF + BSF => just before EOF
404 + * file 0 + BSF => BOT + errno
405 + */
406 +int faketape::bsf()
407  {
408     ASSERT(online);
409     ASSERT(current_file >= 0);
410 -   Dmsg3(dbglevel, "bsf %i:%i count=%i\n", current_file, current_block, count);
411 +   Dmsg2(dbglevel, "bsf %i:%i count=%i\n", current_file, current_block);
412     int ret = 0;
413  
414 -   check_inplace();
415     check_eof();
416  
417     atBOT = atEOF = atEOT = atEOD = false;
418  
419 -   if (current_file - count < 0) {
420 +   if (current_file == 0) {/* BOT + errno */      
421 +      lseek(fd, 0, SEEK_SET);
422 +      read_fm(true);
423 +      prev_FM = 0;
424        current_file = 0;
425        current_block = 0;
426        atBOT = true;
427        errno = EIO;
428        ret = -1;
429     } else {
430 -      current_file = current_file - count + 1;
431 -      current_block = -1;
432 -      seek_file();
433 +      Dmsg1(dbglevel, "bfs last=%lli\n", last_FM);
434 +      lseek(fd, last_FM, SEEK_SET);
435        current_file--;
436 -      /* go just before last EOF */
437 -      lseek(fd, lseek(fd, 0, SEEK_CUR) - sizeof(uint32_t), SEEK_SET);
438 +      current_block=-1;
439     }
440     return ret;
441  }
442 @@ -749,6 +832,9 @@
443     return 0;
444  }
445  
446 +/* A filemark is automatically written to tape if the last tape operation
447 + * before close was a write.
448 + */
449  int faketape::close()
450  {
451     check_eof();
452 @@ -756,18 +842,15 @@
453     fd = -1;
454     return 0;
455  }
456 +
457  /*
458 - **rb
459 - **status
460 - * EOF Bacula status: file=2 block=0
461 - * Device status: EOF ONLINE IM_REP_EN file=2 block=0
462 - **rb
463 - **status
464 - * EOD EOF Bacula status: file=2 block=0
465 - * Device status: EOD ONLINE IM_REP_EN file=2 block=-1
466 - *
467 + * When a filemark is encountered while reading, the following happens.  If
468 + * there are data remaining in the buffer when the filemark is found, the
469 + * buffered data is returned.  The next read returns zero bytes.  The following
470 + * read returns data from the next file.  The end of recorded data is sig‐
471 + * naled by returning zero bytes for two consecutive read calls.  The third
472 + * read returns an error.
473   */
474 -
475  int faketape::read(void *buffer, unsigned int count)
476  {
477     ASSERT(online);
478 @@ -778,6 +861,10 @@
479     Dmsg2(dbglevel, "read %i:%i\n", current_file, current_block);
480  
481     if (atEOT || atEOD) {
482 +      if (eot_count < 2) {     // first two reads return 0, after EIO
483 +        eot_count++;
484 +        return 0;
485 +      }
486        errno = EIO;
487        return -1;
488     }
489 @@ -792,10 +879,10 @@
490        atEOF=false;
491     }
492  
493 -   check_inplace();
494     check_eof();
495  
496     atEOD = atBOT = false;
497 +   eot_count = 0;
498  
499     /* reading size of data */
500     nb = ::read(fd, &s, sizeof(uint32_t));
501 @@ -813,11 +900,10 @@
502  
503     if (!s) {                    /* EOF */
504        atEOF = true;
505 -      if (current_file < last_file) { /* move to next file if possible */
506 -         current_file++;
507 -         current_block = 0;
508 -         inplace=false;
509 +      if (read_next_fm(false)) {
510 +        current_file++;
511        }
512 +
513        return 0;
514     }
515  
516 @@ -825,7 +911,7 @@
517     nb = ::read(fd, buffer, s);
518     if (s != nb) {              /* read error */
519        errno=EIO;
520 -      atEOT = true;
521 +      set_eot();
522        current_block = -1;
523        Dmsg0(dbglevel, "EOT during reading\n");
524        return -1;
525 @@ -860,36 +946,25 @@
526        return -1;
527     }
528  
529 -   /* open volume descriptor and get this->fd */
530 -   find_maxfile();
531 -
532     file_block = 0;
533     current_block = 0;
534     current_file = 0;
535 +   prev_FM = next_FM = last_FM = 0;
536 +   eot_count = 0;
537     needEOF = false;
538 -   inplace = true;
539     atBOT = true;
540     atEOT = atEOD = false;
541  
542 -   return fd;
543 -}
544 -
545 -/*
546 - * read volume to get the last file number
547 - */
548 -int faketape::find_maxfile()
549 -{
550 -   struct stat statp;
551 -   if (fstat(fd, &statp) != 0) {
552 -      return 0;
553 +   
554 +   if (!read_fm(true)) {
555 +      weof();
556 +      last_file = current_file=0;
557     }
558 -   last_file = statp.st_size>>FILE_OFFSET;
559 -      
560 -   Dmsg1(dbglevel+1, "last_file=%i\n", last_file);
561  
562 -   return last_file;
563 +   return fd;
564  }
565  
566 +/* use this to track file usage */
567  void faketape::update_pos()
568  {
569     ASSERT(online);
570 @@ -901,32 +976,12 @@
571     Dmsg1(dbglevel+1, "update_pos=%i\n", file_block);
572  
573     if (file_block > max_block) {
574 -      atEOT = true;
575 +      set_eot();
576     } else {
577        atEOT = false;
578     }
579  }
580  
581 -int faketape::seek_file()
582 -{
583 -   ASSERT(online);
584 -   ASSERT(current_file >= 0);
585 -   Dmsg2(dbglevel, "seek_file %i:%i\n", current_file, current_block);
586 -   inplace = true;
587 -
588 -   off_t pos = ((off_t)current_file)<<FILE_OFFSET;
589 -   if(lseek(fd, pos, SEEK_SET) == -1) {
590 -      return -1;
591 -   }
592 -
593 -   last_file = MAX(last_file, current_file);
594 -   if (current_block > 0) {
595 -      fsr(current_block);
596 -   }
597 -
598 -   return 0;
599 -}
600 -
601  void faketape::dump()
602  {
603     Dmsg0(dbglevel+1, "===================\n");
604 Index: src/stored/faketape.h
605 ===================================================================
606 --- src/stored/faketape.h       (révision 7084)
607 +++ src/stored/faketape.h       (copie de travail)
608 @@ -56,35 +56,39 @@
609  private:
610     int         fd;              /* Our file descriptor */
611  
612 -   off_t       file_block;       /* size */
613 +   off_t       file_block;     /* size */
614     off_t       max_block;
615  
616 +   off_t       prev_FM;                /* previous file mark */
617 +   off_t       last_FM;                /* last file mark (current file) */
618 +   off_t       next_FM;
619 +
620     bool        atEOF;           /* End of file */
621     bool        atEOT;           /* End of media */
622     bool        atEOD;           /* End of data */
623     bool        atBOT;           /* Begin of tape */
624     bool        online;          /* volume online */
625 -   bool        inplace;         /* have to seek before writing ? */
626     bool        needEOF;         /* check if last operation need eof */
627  
628     int32_t     last_file;       /* last file of the volume */
629     int32_t     current_file;    /* current position */
630     int32_t     current_block;   /* current position */
631 +   int         eot_count;      /* count eot reads */
632  
633     void destroy();
634 -   int find_maxfile();
635     int offline();
636     int truncate_file();
637 -   int seek_file();
638 -   void check_eof() { if(needEOF) weof(1);};
639 -   void check_inplace() { if (!inplace) seek_file();};
640 +   void check_eof() { if(needEOF) weof();};
641     void update_pos();
642 +   bool read_fm(bool readfirst);
643 +   bool read_next_fm(bool readfirst);
644 +   void set_eot() { eot_count=0; atEOT=true;};
645  
646  public:
647 -   int fsf(int count);
648 +   int fsf();
649     int fsr(int count);
650 -   int weof(int count);
651 -   int bsf(int count);
652 +   int weof();
653 +   int bsf();
654     int bsr(int count);
655  
656     faketape();