From 58f20817c38a742d5b09b514469c2990088a13bd Mon Sep 17 00:00:00 2001 From: Eric Bollengier Date: Sun, 4 May 2008 14:08:20 +0000 Subject: [PATCH] ebl update git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@6889 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/patches/testing/faketape.c | 379 +++++++++++++++++++++++++----- bacula/patches/testing/faketape.h | 18 +- 2 files changed, 328 insertions(+), 69 deletions(-) diff --git a/bacula/patches/testing/faketape.c b/bacula/patches/testing/faketape.c index c9196d9282..b8fc8efa2f 100644 --- a/bacula/patches/testing/faketape.c +++ b/bacula/patches/testing/faketape.c @@ -67,6 +67,8 @@ static bool put_tape(faketape *ftape) int faketape_open(const char *pathname, int flags, int mode) { + ASSERT(pathname != NULL); + int fd; faketape *tape = new faketape(); fd = tape->open(pathname, flags, mode); @@ -139,7 +141,6 @@ int faketape_ioctl(int fd, unsigned long int request, ...) int faketape::tape_op(struct mtop *mt_com) { int result=0; - struct stat statp; switch (mt_com->mt_op) { @@ -158,23 +159,10 @@ int faketape::tape_op(struct mtop *mt_com) break; case MTFSF: /* Forward space over mt_count filemarks. */ - /* we are already at EOT */ - if (current_file > max_file) { - atEOF = true; - errno = EIO; - result = -1; - } - - /* we are at the last file */ - if (current_file == max_file) { - current_file++; - atEOF = true; - } - break; case MTBSF: /* Backward space over mt_count filemarks. */ - current_file = current_file - mt_op->mt_count; + current_file = current_file - mt_com->mt_count; if (current_file < 0) { current_file = 0; errno = EIO; @@ -182,7 +170,7 @@ int faketape::tape_op(struct mtop *mt_com) } atEOD = false; atEOF = false; - atEOM = false; + atBOT = false; open_file(); break; @@ -200,39 +188,27 @@ int faketape::tape_op(struct mtop *mt_com) block number = 0 */ /* tester si on se trouve a la fin du fichier */ - fseek(cur_fd, SEEK_CUR, tape_info.block_size*mt_op->mt_count); + lseek(cur_fd, SEEK_CUR, tape_info.block_size*mt_com->mt_count); break; case MTBSR: /* Backward space over mt_count records (tape blocks). */ - -/* - file number = 1 - block number = -1 - - mt: /dev/lto2: Erreur d'entrée/sortie - - file number = 0 - block number = -1 -*/ - - fstat(cur_file, &statp); - off_t cur_pos = lseek(cur_fd, 0, SEEK_CUR); - - fseek(cur_fd, SEEK_CUR, tape_info.block_size*mt_op->mt_count); + result = -1; break; case MTWEOF: /* Write mt_count filemarks. */ + weof(mt_com->mt_count); break; case MTREW: /* Rewind. */ - atEOF = atEOD = atEOM = false; + close_file(); + atEOF = atEOD = false; + atBOT = true; current_file = 0; - open_file(); + current_block = 0; break; case MTOFFL: /* put tape offline */ - // check if can_read/can_write - result = 0; + result = offline(); break; case MTRETEN: /* Re-tension tape. */ @@ -361,16 +337,21 @@ int faketape::delete_files(int startfile) struct dirent *dir; struct stat statp; + Dmsg1(dbglevel, "delete_files %i\n", startfile); + fp_dir = opendir(this->volume); if (!fp_dir) { - this->max_file=0; + this->last_file=0; this->size = 0; return -1; } this->size = 0; - /* search for all digit file */ + /* search for all digit files + * and we remove all ones that are greater than + * startfile + */ while ((dir = readdir (fp_dir)) != NULL) { Mmsg(tmp, "%s/%s", this->volume, dir->d_name); @@ -379,11 +360,11 @@ int faketape::delete_files(int startfile) for(p = dir->d_name; *p && isdigit(*p); p++) { cur *= 10; - cur += *p; + cur += *p - '0'; } - if (!*p && cur) { + if (!*p && cur > 0) { if (cur >= startfile) { /* remove it */ - unlink(tmp); + unlink(tmp.c_str()); } else { if (lstat(tmp.c_str(), &statp) == 0) { this->size += statp.st_size; @@ -394,18 +375,26 @@ int faketape::delete_files(int startfile) } closedir(fp_dir); - this->max_file = max; + this->last_file = max; return max; } faketape::faketape() { - fd = 0; - atEOF = 0; - atEOM = 0; + fd = -1; + cur_fd = -1; + + atEOF = false; + atBOT = false; + atEOT = false; + atEOD = false; + online = false; + + size = 0; + last_file = 0; current_file = 0; - current_block = 0; - max_file = 0; + current_block = -1; + max_size = 10000000; volume = get_pool_memory(PM_NAME); cur_file = get_pool_memory(PM_NAME); @@ -426,30 +415,188 @@ int faketape::get_fd() int faketape::write(const void *buffer, unsigned int count) { - ASSERT(cur_fd > 0); - if (current_block == -1) { + unsigned int nb; + check_file(); + + if (atEOT) { + return 0; + } + + current_block++; + + atBOT = false; + + /* TODO: remove all files > current_file and + * remove blocks > current_block + */ + if (count + size > max_size) { + Dmsg2(dbglevel, + "EOT writing only %i of %i requested\n", + max_size - size, count); + count = max_size - size; + atEOT = true; + } + + nb = ::write(cur_fd, buffer, count); + + if (nb != count) { + atEOT = true; + Dmsg2(dbglevel, + "Not enough space writing only %i of %i requested\n", + nb, count); + } + + return nb; +} + +int faketape::weof(int count) +{ + if (atEOT) { + current_block = -1; + return -1; + } + + count--; /* end this file */ + ftruncate(cur_fd, lseek(cur_fd, 0, SEEK_CUR)); + close_file(); + current_file++; + + /* we erase all previous information */ + if (last_file > current_file) { + delete_files(current_file); + } + + for (; count>0 ; count--) { + current_file++; open_file(); } - /* remove all file > current_file */ - return ::write(cur_fd, buffer, count); + current_block=0; + atEOF = true; + atEOD = false; + return 0; } -int faketape::close() +int faketape::fsf(int count) +{ + +/* + * 1 0 -> fsf -> 2 0 -> fsf -> 2 -1 + */ + + if (atEOT) { + current_block = -1; + return -1; + } + + close_file(); + + if (current_file + count <= last_file) { + current_file += count; + current_block = 0; + return 0; + } else { + current_file = last_file; + current_block = -1; + atEOT=true; + return -1; + } +} + +int faketape::bsf(int count) +{ + +/* + * 1 0 -> fsf -> 2 0 -> fsf -> 2 -1 + */ + close_file(); + atEOT = atEOD = false; + + if (current_file - count < 0) { + current_file = 0; + current_block = 0; + atBOT = true; + return -1; + } + + current_file = current_file - count; + current_block = 0; + if (!current_file) { + atBOT = true; + } + + return 1; +} + +/* + * Put faketape in offline mode + */ +int faketape::offline() { ASSERT(cur_fd > 0); - ::close(cur_fd); + + close_file(); + + cur_fd = -1; + atEOF = false; + atEOT = false; + atEOD = false; + atBOT = false; + + current_file = -1; + current_block = -1; + last_file = 0; + return 0; +} + +int faketape::close_file() +{ + if (cur_fd > 0) { + ::close(cur_fd); + cur_fd = -1; + } + return 0; +} + +int faketape::close() +{ + close_file(); ::close(fd); 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 + * + */ int faketape::read(void *buffer, unsigned int count) { - ASSERT(cur_fd > 0); - if (current_block == -1) { - open_file(); + unsigned int nb; + check_file(); + + if (atEOT || atEOD) { + return 0; } - return ::read(cur_fd, buffer, count); + + atBOT = false; + + nb = ::read(cur_fd, buffer, count); + if (count != nb) { + atEOF = true; + if (current_file == last_file) { + atEOD = true; + current_block = -1; + } + Dmsg0(dbglevel, "EOF during reading\n"); + } + return nb; } int faketape::read_volinfo() @@ -457,7 +604,7 @@ int faketape::read_volinfo() struct stat statp; memset(&tape_info, 0, sizeof(FTAPE_FORMAT)); - Dmsg2(0, "Info %p %p\n", cur_info, volume); + Dmsg2(0, "read_volinfo %p %p\n", cur_info, volume); Mmsg(cur_info, "%s/info", volume); fd = ::open(cur_info, O_CREAT | O_RDWR | O_BINARY, 0640); @@ -465,7 +612,7 @@ int faketape::read_volinfo() return -1; } - fstat(cur_info, &statp); + fstat(fd, &statp); /* read volume info */ int nb = ::read(fd, &tape_info, sizeof(FTAPE_FORMAT)); @@ -530,7 +677,7 @@ int faketape::find_maxfile() fp_dir = opendir(this->volume); if (!fp_dir) { - max_file=0; + last_file=0; return -1; } @@ -558,13 +705,14 @@ int faketape::find_maxfile() } closedir(fp_dir); - this->max_file = max; + this->last_file = max; return max; } int faketape::open_file() { - if (cur_fd) { + ASSERT(current_file >= 0); + if (cur_fd > 0) { ::close(cur_fd); } @@ -574,7 +722,9 @@ int faketape::open_file() return -1; } current_block = 0; - max_file = (max_file > current_file)?max_file:current_file; + last_file = (last_file > current_file)?last_file:current_file; + + Dmsg1(dbglevel, "open_file %s %i\n", cur_file); return cur_fd; @@ -582,14 +732,105 @@ int faketape::open_file() void faketape::dump() { - Dmsg1(dbglevel, "max_file=%i\n", max_file); + Dmsg0(dbglevel, "===================\n"); + Dmsg1(dbglevel, "last_file=%i\n", last_file); Dmsg1(dbglevel, "current_file=%i\n", current_file); Dmsg1(dbglevel, "volume=%s\n", volume); - Dmsg1(dbglevel, "cur_info=%s\n", cur_info); Dmsg1(dbglevel, "cur_file=%s\n", cur_file); Dmsg1(dbglevel, "size=%i\n", size); + Dmsg1(dbglevel, "EOF=%i\n", atEOF); + Dmsg1(dbglevel, "EOT=%i\n", atEOT); + Dmsg1(dbglevel, "EOD=%i\n", atEOD); } +/**************************************************************** + +#define GMT_EOF(x) ((x) & 0x80000000) +#define GMT_BOT(x) ((x) & 0x40000000) +#define GMT_EOT(x) ((x) & 0x20000000) +#define GMT_SM(x) ((x) & 0x10000000) +#define GMT_EOD(x) ((x) & 0x08000000) + + + GMT_EOF(x) : La bande est positionnée juste après une filemark (toujours faux + après une opération MTSEEK). + + GMT_BOT(x) : La bande est positionnée juste au début du premier fichier + (toujours faux après une opération MTSEEK). + + GMT_EOT(x) : Une opération a atteint la fin physique de la bande (End Of + Tape). + + GMT_SM(x) : La bande est positionnée sur une setmark (toujours faux après une + opération MTSEEK). + + GMT_EOD(x) : La bande est positionnée à la fin des données enregistrées. + + +blkno = -1 (after MTBSF MTBSS or MTSEEK) +fileno = -1 (after MTBSS or MTSEEK) + +*** mtx load +drive type = Generic SCSI-2 tape +drive status = 0 +sense key error = 0 +residue count = 0 +file number = 0 +block number = 0 +Tape block size 0 bytes. Density code 0x0 (default). +Soft error count since last status=0 +General status bits on (41010000): + BOT ONLINE IM_REP_EN + +*** read empty block +dd if=/dev/lto2 of=/tmp/toto count=1 +dd: lecture de `/dev/lto2': Ne peut allouer de la mémoire +0+0 enregistrements lus +0+0 enregistrements écrits +1 octet (1B) copié, 4,82219 seconde, 0,0 kB/s + +file number = 0 +block number = 1 + +*** read file mark +dd if=/dev/lto2 of=/tmp/toto count=1 +0+0 enregistrements lus +0+0 enregistrements écrits +1 octet (1B) copié, 0,167274 seconde, 0,0 kB/s + +file number = 1 +block number = 0 + + *** write 2 blocks after rewind +dd if=/dev/zero of=/dev/lto2 count=2 +2+0 enregistrements lus +2+0 enregistrements écrits +1024 octets (1,0 kB) copiés, 6,57402 seconde, 0,2 kB/s + +file number = 1 +block number = 0 + +*** write 2 blocks +file number = 2 +block number = 0 + +*** rewind and fsr +file number = 0 +block number = 1 + +*** rewind and 2x fsr (we have just 2 blocks) +file number = 0 +block number = 2 + +*** fsr +mt: /dev/lto2: Erreur +file number = 1 +block number = 0 + + + ****************************************************************/ + + #ifdef TEST int main() @@ -605,8 +846,16 @@ int main() } faketape *tape = get_tape(fd); + tape->write("test", strlen("test")+1); + tape->write("test", strlen("test")+1); tape->dump(); + tape->weof(1); + tape->write("test", strlen("test")+1); + tape->write("test", strlen("test")+1); + tape->dump(); + tape->fsf(2); + tape->dump(); faketape_close(fd); return 0; diff --git a/bacula/patches/testing/faketape.h b/bacula/patches/testing/faketape.h index 47065e530a..28d0a0e917 100644 --- a/bacula/patches/testing/faketape.h +++ b/bacula/patches/testing/faketape.h @@ -62,20 +62,23 @@ class faketape { private: int fd; /* Our file descriptor */ - int cur_fd; /* OS file descriptor */ + int cur_fd; /* OS file descriptor (-1 if not open) */ off_t size; /* size */ bool atEOF; /* End of file */ - bool atEOM; /* End of media */ + bool atEOT; /* End of media */ bool atEOD; /* End of data */ + bool atBOT; /* Begin of tape */ + bool online; /* volume online */ POOLMEM *volume; /* volume name */ POOLMEM *cur_info; /* volume info */ POOLMEM *cur_file; /* current file name */ - int16_t max_file; + int16_t last_file; /* last file of the volume */ int16_t current_file; /* max 65000 files */ int32_t current_block; /* max 4G blocks of 1KB */ + off_t max_size; /* max size of volume */ FTAPE_FORMAT tape_info; @@ -83,9 +86,16 @@ private: int read_volinfo(); /* read current volume format */ int find_maxfile(); int open_file(); - int delete_files(); + int delete_files(int startfile); + void check_file() { if (cur_fd == -1) open_file(); }; + int offline(); + int close_file(); public: + int fsf(int count); + int weof(int count); + int bsf(int count); + faketape(); ~faketape(); -- 2.39.5