From ed0d8aa9e009916d1eac0d64707d06dc40aa68ba Mon Sep 17 00:00:00 2001 From: Eric Bollengier Date: Mon, 2 Jun 2008 22:15:40 +0000 Subject: [PATCH] ebl tweak faketape with variable file length git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@7096 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/patches/testing/faketape2.patch | 645 +++++++++++++++++++++++++ 1 file changed, 645 insertions(+) create mode 100644 bacula/patches/testing/faketape2.patch diff --git a/bacula/patches/testing/faketape2.patch b/bacula/patches/testing/faketape2.patch new file mode 100644 index 0000000000..34ebb519a3 --- /dev/null +++ b/bacula/patches/testing/faketape2.patch @@ -0,0 +1,645 @@ +Index: src/stored/faketape.c +=================================================================== +--- src/stored/faketape.c (révision 7092) ++++ src/stored/faketape.c (copie de travail) +@@ -170,6 +170,7 @@ + int faketape::tape_op(struct mtop *mt_com) + { + int result=0; ++ int count = mt_com->mt_count; + + if (!online) { + errno = ENOMEDIUM; +@@ -193,11 +194,15 @@ + break; + + case MTFSF: /* Forward space over mt_count filemarks. */ +- result = fsf(mt_com->mt_count); ++ do { ++ result = fsf(); ++ } while (--count > 0 && result == 0); + break; + + case MTBSF: /* Backward space over mt_count filemarks. */ +- result = bsf(mt_com->mt_count); ++ do { ++ result = bsf(); ++ } while (--count > 0 && result == 0); + break; + + case MTFSR: /* Forward space over mt_count records (tape blocks). */ +@@ -222,16 +227,20 @@ + break; + + case MTWEOF: /* Write mt_count filemarks. */ +- result = weof(mt_com->mt_count); ++ do { ++ result = weof(); ++ } while (result == 0 && --count > 0); + break; + + case MTREW: /* Rewind. */ + Dmsg0(dbglevel, "rewind faketape\n"); ++ check_eof(); + atEOF = atEOD = false; + atBOT = true; + current_file = 0; + current_block = 0; +- seek_file(); ++ lseek(fd, 0, SEEK_SET); ++ read_next_fm(true); + break; + + case MTOFFL: /* put tape offline */ +@@ -253,19 +262,28 @@ + break; + + case MTEOM:/* Go to the end of the recorded media (for appending files). */ ++ while (next_FM) { ++ lseek(fd, next_FM, SEEK_SET); ++ read_next_fm(true); ++ } ++ off_t l; ++ while (::read(fd, &l, sizeof(l)) > 0) { ++ if (l) { ++ lseek(fd, l, SEEK_CUR); ++ } else { ++ ASSERT(0); ++ } ++ Dmsg0(dbglevel, "skip 1 block\n"); ++ } ++ current_block = -1; ++ atEOF = false; ++ atEOD = true; ++ + /* + file number = 3 + block number = -1 + */ + /* Can be at EOM */ +- atBOT = false; +- atEOF = false; +- atEOD = true; +- atEOT = false; +- +- current_file = last_file; +- current_block = -1; +- seek_file(); + break; + + case MTERASE: /* not used by bacula */ +@@ -275,7 +293,8 @@ + + current_file = 0; + current_block = -1; +- seek_file(); ++ lseek(fd, 0, SEEK_SET); ++ read_next_fm(true); + truncate_file(); + break; + +@@ -405,8 +424,8 @@ + atEOT = false; + atEOD = false; + online = false; +- inplace = false; + needEOF = false; ++ eot_count = 0; + + file_block = 0; + last_file = 0; +@@ -444,8 +463,6 @@ + return -1; + } + +- check_inplace(); +- + if (!atEOD) { /* if not at the end of the data */ + truncate_file(); + } +@@ -460,14 +477,6 @@ + + needEOF = true; /* next operation need EOF mark */ + +-// if ((count + file_size) > max_size) { +-// Dmsg2(dbglevel, +-// "EOT writing only %i of %i requested\n", +-// max_size - file_size, count); +-// count = max_size - file_size; +-// atEOT = true; +-// } +- + uint32_t size = count; + ::write(fd, &size, sizeof(uint32_t)); + nb = ::write(fd, buffer, count); +@@ -484,43 +493,68 @@ + return nb; + } + +-int faketape::weof(int count) ++/* ++ * +---+---------+---+------------------+---+-------------------+ ++ * |00N| DATA |0LN| DATA |0LC| DATA | ++ * +---+---------+---+------------------+---+-------------------+ ++ * ++ * 0 : zero ++ * L : Last FileMark offset ++ * N : Next FileMark offset ++ * C : Current FileMark Offset ++ */ ++int faketape::weof() + { + ASSERT(online); + ASSERT(current_file >= 0); + Dmsg3(dbglevel, "Writing EOF %i:%i last=%i\n", + current_file, current_block,last_file); ++ ++ off_t cur_FM; ++ + if (atEOT) { + errno = ENOSPC; + current_block = -1; + return -1; + } +- needEOF = false; + +- check_inplace(); +- truncate_file(); /* nothing after this point */ ++ if (!atEOD) { ++ truncate_file(); /* nothing after this point */ ++ } ++ ++ cur_FM = lseek(fd, 0, SEEK_CUR); // current position + ++ /* update previous next_FM */ ++ lseek(fd, last_FM + sizeof(uint32_t)+sizeof(off_t), SEEK_SET); ++ ::write(fd, &cur_FM, sizeof(off_t)); ++ lseek(fd, cur_FM, SEEK_SET); ++ ++ prev_FM = last_FM; ++ last_FM = cur_FM; ++ next_FM = 0; ++ + uint32_t c=0; +- ::write(fd, &c, sizeof(uint32_t)); ++ ::write(fd, &c, sizeof(uint32_t)); // EOF ++ ::write(fd, &last_FM, sizeof(last_FM)); // F-1 ++ ::write(fd, &next_FM, sizeof(next_FM)); // F (will be updated next time) + +- current_file += count; ++ current_file++; + current_block = 0; +- seek_file(); + +- c=0; +- ::write(fd, &c, sizeof(uint32_t)); +- lseek(fd, lseek(fd, 0, SEEK_CUR) - sizeof(uint32_t), SEEK_SET); +- ++ needEOF = false; + atEOD = false; + atBOT = false; + atEOF = true; + +- update_pos(); ++ last_file = MAX(current_file, last_file); + + return 0; + } + +-int faketape::fsf(int count) ++/* ++ * Go to next FM ++ */ ++int faketape::fsf() + { + ASSERT(online); + ASSERT(current_file >= 0); +@@ -528,24 +562,33 @@ + /* + * 1 0 -> fsf -> 2 0 -> fsf -> 2 -1 + */ +- check_inplace(); +- check_eof(); + +- int ret; ++ int ret=0; + if (atEOT || atEOD) { + errno = EIO; + current_block = -1; + return -1; + } + +- atBOT = atEOF = false; +- Dmsg3(dbglevel+1, "fsf %i+%i <= %i\n", current_file, count, last_file); ++ atBOT = false; ++ Dmsg2(dbglevel+1, "fsf %i <= %i\n", current_file, last_file); + +- if ((current_file + count) <= last_file) { +- current_file += count; +- current_block = 0; ++ if (next_FM > last_FM) { /* not the last file */ ++ lseek(fd, next_FM, SEEK_SET); ++ read_next_fm(true); ++ current_file++; ++ atEOF = true; + ret = 0; +- } else { ++ ++ } else if (atEOF) { /* last file mark */ ++ current_block=-1; ++ errno = EIO; ++ atEOF = false; ++ atEOD = true; ++ ++ } else { /* last file, but no at the end */ ++ fsr(100000); ++ + Dmsg0(dbglevel, "Try to FSF after EOT\n"); + errno = EIO; + current_file = last_file ; +@@ -553,10 +596,44 @@ + atEOD=true; + ret = -1; + } +- seek_file(); + return ret; + } + ++/* /------------\ /---------------\ ++ * +---+------+---+---------------+-+ ++ * |OLN| |0LN| | | ++ * +---+------+---+---------------+-+ ++ */ ++bool faketape::read_next_fm(bool read_all /* read the 0 byte */) ++{ ++ prev_FM = last_FM; ++ return read_fm(read_all); ++} ++ ++bool faketape::read_fm(bool read_all /* read the 0 byte */) ++{ ++ int ret; ++ uint32_t c; ++ if (read_all) { ++ ::read(fd, &c, sizeof(c)); ++ if (c != 0) { ++ lseek(fd, lseek(fd, 0, SEEK_CUR) - sizeof(c), SEEK_SET); ++ return false; ++ } ++ } ++ ::read(fd, &last_FM, sizeof(last_FM)); ++ ret = ::read(fd, &next_FM, sizeof(next_FM)); ++ ++ current_block=0; ++ ++ Dmsg1(dbglevel, "Read FM next=%lli\n", next_FM); ++ ++ return (ret == sizeof(next_FM)); ++} ++ ++/* ++ * TODO: Check fsr with EOF ++ */ + int faketape::fsr(int count) + { + ASSERT(online); +@@ -568,7 +645,6 @@ + uint32_t s; + Dmsg3(dbglevel, "fsr %i:%i count=%i\n", current_file,current_block, count); + +- check_inplace(); + check_eof(); + + if (atEOT) { +@@ -595,20 +671,23 @@ + current_file, current_block, nb,s); + errno = EIO; + ret = -1; +- if (current_file < last_file) { ++ if (next_FM) { + current_block = 0; + current_file++; +- seek_file(); +- } ++ read_next_fm(false); ++ } + atEOF = true; /* stop the loop */ + } + } + +- find_maxfile(); /* refresh stats */ +- + return ret; + } + ++/* ++ * BSR + EOF => begin of EOF + EIO ++ * BSR + BSR + EOF => last block ++ * current_block = -1 ++ */ + int faketape::bsr(int count) + { + Dmsg2(dbglevel, "bsr current_block=%i count=%i\n", +@@ -619,7 +698,6 @@ + ASSERT(count == 1); + ASSERT(fd >= 0); + +- check_inplace(); + check_eof(); + + if (!count) { +@@ -641,22 +719,21 @@ + return -1; + } + ++ /* at EOF 0:-1 BOT=0 EOD=0 EOF=0 ERR: Input/output error */ + if (atEOF) { +- if (!current_block) { +- if (current_file > 0) { +- current_file--; +- } +- current_block=-1; +- errno = EIO; +- return -1; +- +- } else { +- atEOF=false; +- } ++ lseek(fd, last_FM, SEEK_CUR); ++ atEOF = false; ++ current_block=-1; ++ errno = EIO; ++ return -1; + } + +- current_block=0; +- seek_file(); ++ /* ++ * First, go to last_FM and read all blocks to find the good one ++ */ ++ ++ lseek(fd, last_FM, SEEK_CUR); ++ read_fm(true); + + do { + if (!atEOF) { +@@ -700,31 +777,35 @@ + return 0; + } + +-int faketape::bsf(int count) ++/* BSF => just before last EOF ++ * EOF + BSF => just before EOF ++ * file 0 + BSF => BOT + errno ++ */ ++int faketape::bsf() + { + ASSERT(online); + ASSERT(current_file >= 0); +- Dmsg3(dbglevel, "bsf %i:%i count=%i\n", current_file, current_block, count); ++ Dmsg2(dbglevel, "bsf %i:%i count=%i\n", current_file, current_block); + int ret = 0; + +- check_inplace(); + check_eof(); + + atBOT = atEOF = atEOT = atEOD = false; + +- if (current_file - count < 0) { ++ if (current_file == 0) {/* BOT + errno */ ++ lseek(fd, 0, SEEK_SET); ++ read_fm(true); ++ prev_FM = 0; + current_file = 0; + current_block = 0; + atBOT = true; + errno = EIO; + ret = -1; + } else { +- current_file = current_file - count + 1; +- current_block = -1; +- seek_file(); ++ Dmsg1(dbglevel, "bfs last=%lli\n", last_FM); ++ lseek(fd, last_FM, SEEK_SET); + current_file--; +- /* go just before last EOF */ +- lseek(fd, lseek(fd, 0, SEEK_CUR) - sizeof(uint32_t), SEEK_SET); ++ current_block=-1; + } + return ret; + } +@@ -749,6 +830,9 @@ + return 0; + } + ++/* A filemark is automatically written to tape if the last tape operation ++ * before close was a write. ++ */ + int faketape::close() + { + check_eof(); +@@ -756,18 +840,15 @@ + fd = -1; + return 0; + } ++ + /* +- **rb +- **status +- * EOF Bacula status: file=2 block=0 +- * Device status: EOF ONLINE IM_REP_EN file=2 block=0 +- **rb +- **status +- * EOD EOF Bacula status: file=2 block=0 +- * Device status: EOD ONLINE IM_REP_EN file=2 block=-1 +- * ++ * When a filemark is encountered while reading, the following happens. If ++ * there are data remaining in the buffer when the filemark is found, the ++ * buffered data is returned. The next read returns zero bytes. The following ++ * read returns data from the next file. The end of recorded data is sig‐ ++ * naled by returning zero bytes for two consecutive read calls. The third ++ * read returns an error. + */ +- + int faketape::read(void *buffer, unsigned int count) + { + ASSERT(online); +@@ -778,6 +859,10 @@ + Dmsg2(dbglevel, "read %i:%i\n", current_file, current_block); + + if (atEOT || atEOD) { ++ if (eot_count < 2) { // first two reads return 0, after EIO ++ eot_count++; ++ return 0; ++ } + errno = EIO; + return -1; + } +@@ -792,10 +877,10 @@ + atEOF=false; + } + +- check_inplace(); + check_eof(); + + atEOD = atBOT = false; ++ eot_count = 0; + + /* reading size of data */ + nb = ::read(fd, &s, sizeof(uint32_t)); +@@ -813,11 +898,10 @@ + + if (!s) { /* EOF */ + atEOF = true; +- if (current_file < last_file) { /* move to next file if possible */ +- current_file++; +- current_block = 0; +- inplace=false; ++ if (read_next_fm(false)) { ++ current_file++; + } ++ + return 0; + } + +@@ -825,7 +909,7 @@ + nb = ::read(fd, buffer, s); + if (s != nb) { /* read error */ + errno=EIO; +- atEOT = true; ++ set_eot(); + current_block = -1; + Dmsg0(dbglevel, "EOT during reading\n"); + return -1; +@@ -860,36 +944,25 @@ + return -1; + } + +- /* open volume descriptor and get this->fd */ +- find_maxfile(); +- + file_block = 0; + current_block = 0; + current_file = 0; ++ prev_FM = next_FM = last_FM = 0; ++ eot_count = 0; + needEOF = false; +- inplace = true; + atBOT = true; + atEOT = atEOD = false; + +- return fd; +-} +- +-/* +- * read volume to get the last file number +- */ +-int faketape::find_maxfile() +-{ +- struct stat statp; +- if (fstat(fd, &statp) != 0) { +- return 0; ++ ++ if (!read_fm(true)) { ++ weof(); ++ last_file = current_file=0; + } +- last_file = statp.st_size>>FILE_OFFSET; +- +- Dmsg1(dbglevel+1, "last_file=%i\n", last_file); + +- return last_file; ++ return fd; + } + ++/* use this to track file usage */ + void faketape::update_pos() + { + ASSERT(online); +@@ -901,32 +974,12 @@ + Dmsg1(dbglevel+1, "update_pos=%i\n", file_block); + + if (file_block > max_block) { +- atEOT = true; ++ set_eot(); + } else { + atEOT = false; + } + } + +-int faketape::seek_file() +-{ +- ASSERT(online); +- ASSERT(current_file >= 0); +- Dmsg2(dbglevel, "seek_file %i:%i\n", current_file, current_block); +- inplace = true; +- +- off_t pos = ((off_t)current_file)< 0) { +- fsr(current_block); +- } +- +- return 0; +-} +- + void faketape::dump() + { + Dmsg0(dbglevel+1, "===================\n"); +Index: src/stored/faketape.h +=================================================================== +--- src/stored/faketape.h (révision 7084) ++++ src/stored/faketape.h (copie de travail) +@@ -56,35 +56,39 @@ + private: + int fd; /* Our file descriptor */ + +- off_t file_block; /* size */ ++ off_t file_block; /* size */ + off_t max_block; + ++ off_t prev_FM; /* previous file mark */ ++ off_t last_FM; /* last file mark (current file) */ ++ off_t next_FM; ++ + bool atEOF; /* End of file */ + bool atEOT; /* End of media */ + bool atEOD; /* End of data */ + bool atBOT; /* Begin of tape */ + bool online; /* volume online */ +- bool inplace; /* have to seek before writing ? */ + bool needEOF; /* check if last operation need eof */ + + int32_t last_file; /* last file of the volume */ + int32_t current_file; /* current position */ + int32_t current_block; /* current position */ ++ int eot_count; /* count eot reads */ + + void destroy(); +- int find_maxfile(); + int offline(); + int truncate_file(); +- int seek_file(); +- void check_eof() { if(needEOF) weof(1);}; +- void check_inplace() { if (!inplace) seek_file();}; ++ void check_eof() { if(needEOF) weof();}; + void update_pos(); ++ bool read_fm(bool readfirst); ++ bool read_next_fm(bool readfirst); ++ void set_eot() { eot_count=0; atEOT=true;}; + + public: +- int fsf(int count); ++ int fsf(); + int fsr(int count); +- int weof(int count); +- int bsf(int count); ++ int weof(); ++ int bsf(); + int bsr(int count); + + faketape(); -- 2.39.5