From 21fa9ec8b08236ceabbf6d3187769279a5a34a33 Mon Sep 17 00:00:00 2001 From: Eric Bollengier Date: Sun, 4 May 2008 20:01:32 +0000 Subject: [PATCH] ebl update fake tape driver git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@6890 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/patches/testing/faketape.c | 242 ++++++++++++++++++++---------- bacula/patches/testing/faketape.h | 8 +- bacula/patches/testing/t.c | 141 +++++++++++++++++ 3 files changed, 307 insertions(+), 84 deletions(-) create mode 100644 bacula/patches/testing/t.c diff --git a/bacula/patches/testing/faketape.c b/bacula/patches/testing/faketape.c index b8fc8efa2f..65792a985d 100644 --- a/bacula/patches/testing/faketape.c +++ b/bacula/patches/testing/faketape.c @@ -31,12 +31,7 @@ #include #include -static int tape_get(int fd, struct mtget *mt_get); -static int tape_op(int fd, struct mtop *mt_com); -static int tape_pos(int fd, struct mtpos *mt_pos); - -static int dbglevel = 0; - +static int dbglevel = 10; faketape *ftape_list[FTAPE_MAX_DRIVE]; @@ -65,6 +60,10 @@ static bool put_tape(faketape *ftape) return true; } +/****************************************************************/ +/* theses function will replace open/read/write/close/ioctl + * in bacula core + */ int faketape_open(const char *pathname, int flags, int mode) { ASSERT(pathname != NULL); @@ -114,30 +113,27 @@ int faketape_ioctl(int fd, unsigned long int request, ...) va_start(argp, request); -// switch (request) { -// case MTIOCTOP: - result = t->tape_op(va_arg(argp, mtop *)); -// break; - -// case MTIOCGET: -// result = tape_get(fd, va_arg(argp, mtget *)); -// break; + if (request == MTIOCTOP) { + result = t->tape_op(va_arg(argp, mtop *)); + } else if (request == MTIOCGET) { + result = t->tape_get(va_arg(argp, mtget *)); + } // // case MTIOCPOS: // result = tape_pos(fd, va_arg(argp, mtpos *)); // break; // -// default: -// errno = ENOTTY; -// result = -1; -// break; -// } - + else { + errno = ENOTTY; + result = -1; + } va_end(argp); return result; } +/****************************************************************/ + int faketape::tape_op(struct mtop *mt_com) { int result=0; @@ -159,6 +155,7 @@ int faketape::tape_op(struct mtop *mt_com) break; case MTFSF: /* Forward space over mt_count filemarks. */ + result = fsf(mt_com->mt_count); break; case MTBSF: /* Backward space over mt_count filemarks. */ @@ -188,7 +185,7 @@ int faketape::tape_op(struct mtop *mt_com) block number = 0 */ /* tester si on se trouve a la fin du fichier */ - lseek(cur_fd, SEEK_CUR, tape_info.block_size*mt_com->mt_count); + result = fsr(mt_com->mt_count); break; case MTBSR: /* Backward space over mt_count records (tape blocks). */ @@ -231,13 +228,17 @@ int faketape::tape_op(struct mtop *mt_com) block number = -1 */ /* Can be at EOM */ + atBOT = false; atEOF = true; + atEOD = true; + close_file(); + current_file = last_file; current_block = -1; /* Ne pas creer le fichier si on est a la fin */ break; - case MTERASE: + case MTERASE: /* not used by bacula */ atEOD = true; atEOF = false; atEOT = false; @@ -320,6 +321,49 @@ int faketape::tape_op(struct mtop *mt_com) int faketape::tape_get(struct mtget *mt_get) { + int density = 1; + + mt_get->mt_type = MT_ISSCSI2; + mt_get->mt_blkno = current_block; + mt_get->mt_fileno = current_file; + + mt_get->mt_resid = -1; +// pos_info.PartitionBlockValid ? pos_info.Partition : (ULONG)-1; + + /* TODO */ + mt_get->mt_dsreg = + ((density << MT_ST_DENSITY_SHIFT) & MT_ST_DENSITY_MASK) | + ((tape_info.block_size << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK); + + + mt_get->mt_gstat = 0x00010000; /* Immediate report mode.*/ + + if (atEOF) { + mt_get->mt_gstat |= 0x80000000; // GMT_EOF + } + + if (atBOT) { + mt_get->mt_gstat |= 0x40000000; // GMT_BOT + } + if (atEOT) { + mt_get->mt_gstat |= 0x20000000; // GMT_EOT + } + + if (atEOD) { + mt_get->mt_gstat |= 0x08000000; // GMT_EOD + } + + if (0) { //WriteProtected) { + mt_get->mt_gstat |= 0x04000000; // GMT_WR_PROT + } + + if (online) { + mt_get->mt_gstat |= 0x01000000; // GMT_ONLINE + } else { + mt_get->mt_gstat |= 0x00040000; // GMT_DR_OPEN + } + mt_get->mt_erreg = 0; + return 0; } @@ -328,6 +372,11 @@ int faketape::tape_pos(struct mtpos *mt_pos) return 0; } +/* + * This function try to emulate the append only behavior + * of a tape. When you wrote something, data after the + * current position are discarded. + */ int faketape::delete_files(int startfile) { int cur,max=0; @@ -394,7 +443,6 @@ faketape::faketape() last_file = 0; current_file = 0; current_block = -1; - max_size = 10000000; volume = get_pool_memory(PM_NAME); cur_file = get_pool_memory(PM_NAME); @@ -416,27 +464,33 @@ int faketape::get_fd() int faketape::write(const void *buffer, unsigned int count) { unsigned int nb; + Dmsg2(dbglevel, "write len=%i blocks=%i\n", count, current_block); check_file(); if (atEOT) { + Dmsg0(dbglevel, "write nothing, EOT !\n"); return 0; } - current_block++; + if (current_block != -1) { + current_block++; + } atBOT = false; + atEOD = true; /* TODO: remove all files > current_file and * remove blocks > current_block */ - if (count + size > max_size) { + if (count + size > tape_info.max_size) { Dmsg2(dbglevel, "EOT writing only %i of %i requested\n", - max_size - size, count); - count = max_size - size; + tape_info.max_size - size, count); + count = tape_info.max_size - size; atEOT = true; } + ::write(cur_fd, &count, sizeof(count)); nb = ::write(cur_fd, buffer, count); if (nb != count) { @@ -451,6 +505,7 @@ int faketape::write(const void *buffer, unsigned int count) int faketape::weof(int count) { + Dmsg2(dbglevel, "Writing EOF %i:%i\n", current_file, current_block); if (atEOT) { current_block = -1; return -1; @@ -458,21 +513,23 @@ int faketape::weof(int count) count--; /* end this file */ ftruncate(cur_fd, lseek(cur_fd, 0, SEEK_CUR)); - close_file(); current_file++; + open_file(); /* we erase all previous information */ if (last_file > current_file) { delete_files(current_file); } - - for (; count>0 ; count--) { - current_file++; - open_file(); - } - current_block=0; atEOF = true; atEOD = false; + + if (count > 0) { + current_block = -1; + return -1; + } else { + current_block = 0; + } + return 0; } @@ -482,7 +539,6 @@ int faketape::fsf(int count) /* * 1 0 -> fsf -> 2 0 -> fsf -> 2 -1 */ - if (atEOT) { current_block = -1; return -1; @@ -490,24 +546,56 @@ int faketape::fsf(int count) close_file(); - if (current_file + count <= last_file) { + atEOF=1; + Dmsg3(dbglevel+1, "fsf %i+%i <= %i\n", current_file, count, last_file); + + if ((current_file + count) <= last_file) { current_file += count; current_block = 0; return 0; } else { - current_file = last_file; + Dmsg0(dbglevel, "Try to FSF after EOT\n"); + current_file = last_file ; current_block = -1; - atEOT=true; + atEOD=true; return -1; } } -int faketape::bsf(int count) +int faketape::fsr(int count) { + int i,nb; + off_t where=0, size; + Dmsg2(dbglevel, "fsr current_block=%i count=%i\n", current_block, count); -/* - * 1 0 -> fsf -> 2 0 -> fsf -> 2 -1 - */ + if (atEOT) { + current_block = -1; + return -1; + } + + check_file(); + + for(i=0; (i < count) && (where != -1) ; i++) { + Dmsg3(dbglevel," fsr ok count=%i i=%i where=%i\n", count, i, where); + nb = ::read(cur_fd, &size, sizeof(size)); + if (nb == sizeof(size)) { + where = lseek(cur_fd, size, SEEK_CUR); + if (where == -1) { + errno = EIO; + return -1; + } + current_block++; + } else { + errno = EIO; + return -1; + } + } + Dmsg2(dbglevel," fsr ok i=%i where=%i\n", i, where); + return 0; +} + +int faketape::bsf(int count) +{ close_file(); atEOT = atEOD = false; @@ -550,6 +638,7 @@ int faketape::offline() int faketape::close_file() { + Dmsg0(dbglevel, "close_file\n"); if (cur_fd > 0) { ::close(cur_fd); cur_fd = -1; @@ -578,7 +667,7 @@ int faketape::close() int faketape::read(void *buffer, unsigned int count) { - unsigned int nb; + unsigned int nb, size; check_file(); if (atEOT || atEOD) { @@ -586,9 +675,16 @@ int faketape::read(void *buffer, unsigned int count) } atBOT = false; + current_block++; - nb = ::read(cur_fd, buffer, count); - if (count != nb) { + nb = ::read(cur_fd, &size, sizeof(size)); + if (size > count) { + lseek(cur_fd, size, SEEK_CUR); + errno = ENOMEM; + return -1; + } + nb = ::read(cur_fd, buffer, size); + if (size != nb) { atEOF = true; if (current_file == last_file) { atEOD = true; @@ -604,7 +700,7 @@ int faketape::read_volinfo() struct stat statp; memset(&tape_info, 0, sizeof(FTAPE_FORMAT)); - Dmsg2(0, "read_volinfo %p %p\n", cur_info, volume); + Dmsg2(dbglevel, "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); @@ -621,7 +717,7 @@ int faketape::read_volinfo() tape_info.version = 1; tape_info.block_max = 2000000; tape_info.block_size = statp.st_blksize; - tape_info.max_file_mark = 2000; + tape_info.max_size = 10000000; lseek(fd, SEEK_SET, 0); nb = ::write(fd, &tape_info, sizeof(FTAPE_FORMAT)); @@ -644,7 +740,7 @@ int faketape::open(const char *pathname, int uflags, int umode) pm_strcpy(volume, pathname); struct stat statp; - if (lstat(volume, &statp) != 0) { + if (stat(volume, &statp) != 0) { Dmsg1(dbglevel, "Can't stat on %s\n", volume); return -1; } @@ -665,6 +761,9 @@ int faketape::open(const char *pathname, int uflags, int umode) return fd; } +/* + * read volume directory to get the last file number + */ int faketape::find_maxfile() { int max=0; @@ -712,9 +811,7 @@ int faketape::find_maxfile() int faketape::open_file() { ASSERT(current_file >= 0); - if (cur_fd > 0) { - ::close(cur_fd); - } + close_file(); Mmsg(cur_file, "%s/%i", volume, current_file); cur_fd = ::open(cur_file, O_CREAT | O_RDWR | O_BINARY, 0640); @@ -724,23 +821,22 @@ int faketape::open_file() current_block = 0; last_file = (last_file > current_file)?last_file:current_file; - Dmsg1(dbglevel, "open_file %s %i\n", cur_file); + Dmsg1(dbglevel, "open_file %s\n", cur_file); return cur_fd; - } void faketape::dump() { - 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_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); + Dmsg0(dbglevel+1, "===================\n"); + Dmsg2(dbglevel, "file:block = %i:%i\n", current_file, current_block); + Dmsg1(dbglevel+1, "last_file=%i\n", last_file); + Dmsg1(dbglevel+1, "volume=%s\n", volume); + Dmsg1(dbglevel+1, "cur_file=%s\n", cur_file); + Dmsg1(dbglevel+1, "size=%i\n", size); + Dmsg1(dbglevel+1, "EOF=%i\n", atEOF); + Dmsg1(dbglevel+1, "EOT=%i\n", atEOT); + Dmsg1(dbglevel+1, "EOD=%i\n", atEOD); } /**************************************************************** @@ -836,27 +932,13 @@ block number = 0 int main() { int fd; + char buf[500]; printf("Starting FakeTape\n"); - mkdir("/tmp/fake", 0777); - fd = faketape_open("/tmp/fake", O_CREAT | O_RDWR | O_BINARY, 0666); - if (fd < 0) { - perror("open ERR"); - return 1; - } + mkdir("/tmp/fake", 0700); + + - 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 28d0a0e917..9d3bb8d05b 100644 --- a/bacula/patches/testing/faketape.h +++ b/bacula/patches/testing/faketape.h @@ -42,9 +42,9 @@ typedef struct { /* format infos */ int16_t version; - int16_t max_file_mark; - int16_t block_size; - int32_t block_max; + int16_t block_size; /* block size */ + int32_t block_max; /* max blocks of volume */ + off_t max_size; /* max size of volume */ } FTAPE_FORMAT; #define FTAPE_MAX_DRIVE 20 @@ -78,7 +78,6 @@ private: 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; @@ -93,6 +92,7 @@ private: public: int fsf(int count); + int fsr(int count); int weof(int count); int bsf(int count); diff --git a/bacula/patches/testing/t.c b/bacula/patches/testing/t.c new file mode 100644 index 0000000000..64b7f47761 --- /dev/null +++ b/bacula/patches/testing/t.c @@ -0,0 +1,141 @@ +#include +#include +#include +#include +#include +#include + +#ifndef FTAPE +#include "faketape.h" + +#define write faketape_write +#define open faketape_open +#define read faketape_read +#define close faketape_close +#define ioctl faketape_ioctl +#endif + +static int fd; +void print_pos() +{ + struct mtget mt_get; + ioctl(fd, MTIOCGET, &mt_get); + printf("file:block %i:%i\n", mt_get.mt_fileno, mt_get.mt_blkno); +} + +int main() +{ + int r1, r2; + char c[200]; + struct mtop mt_com; + + fd = open("/dev/lto2", O_CREAT | O_RDWR, 0700); + + /* rewind */ + mt_com.mt_count = 1; + mt_com.mt_op = MTREW; + r1 = ioctl(fd, MTIOCTOP, &mt_com); + printf("rewind\n"); + print_pos(); + + /* write something */ + write(fd, "abcdefghijklmnopqrstuvwyz", strlen("abcdefghijklmnopqrstuvwyz")+1); + write(fd, "abcdefghijklmnopqrstuvwyz", strlen("abcdefghijklmnopqrstuvwyz")+1); + write(fd, "abcdefghijklmnopqrstuvwyz", strlen("abcdefghijklmnopqrstuvwyz")+1); + printf("write something (3 writes)\n"); + print_pos(); + + /* rewind */ + mt_com.mt_count = 1; + mt_com.mt_op = MTREW; + r1 = ioctl(fd, MTIOCTOP, &mt_com); + printf("rewind\n"); + + /* read something with error */ + errno=0; + r1 = read(fd, c, 2); + c[r1] = 0; + printf("read c=%s len=%i errno=%i\n", c, r1, errno); + perror(""); + print_pos(); + + /* read something */ + errno=0; + r1 = read(fd, c, 200); + c[r1] = 0; + printf("read c=%s len=%i\n", c, r1); + print_pos(); + + /* write something */ + printf("write something\n"); + write(fd, "abcdefghijklmnopqrstuvwyz", strlen("abcdefghijklmnopqrstuvwyz")+1); + print_pos(); + + /* rewind */ + mt_com.mt_count = 1; + mt_com.mt_op = MTREW; + r1 = ioctl(fd, MTIOCTOP, &mt_com); + r1 = read(fd, c, 200); + c[r1] = '\0'; + printf("read c=%s len=%i\n", c, r1); + r1 = read(fd, c, 200); + c[r1] = '\0'; + printf("read c=%s len=%i\n", c, r1); + + /* write EOF */ + printf("WEOF\n"); + mt_com.mt_op = MTWEOF; + mt_com.mt_count = 1; + r1 = ioctl(fd, MTIOCTOP, &mt_com); + print_pos(); + + /* FSF */ + mt_com.mt_op = MTFSF; + mt_com.mt_count = 1; + r1 = ioctl(fd, MTIOCTOP, &mt_com); + printf("fsf r=%i\n", r1); + print_pos(); + + /* write something */ + printf("write something\n"); + write(fd, "abcdefghijklmnopqrstuvwyz", strlen("abcdefghijklmnopqrstuvwyz")+1); + print_pos(); + + /* FSF */ + mt_com.mt_op = MTFSF; + mt_com.mt_count = 1; + r1 = ioctl(fd, MTIOCTOP, &mt_com); + printf("fsf r=%i\n", r1); + print_pos(); + + /* WEOF */ + mt_com.mt_op = MTWEOF; + mt_com.mt_count = 3; + r1 = ioctl(fd, MTIOCTOP, &mt_com); + printf("weof 3 r=%i\n", r1); + print_pos(); + + /* rewind */ + mt_com.mt_count = 1; + mt_com.mt_op = MTREW; + r1 = ioctl(fd, MTIOCTOP, &mt_com); + printf("rewind\n"); + print_pos(); + + /* FSR */ + mt_com.mt_op = MTFSR; + mt_com.mt_count = 10; + r1 = ioctl(fd, MTIOCTOP, &mt_com); + printf("fsr r=%i\n", r1); + print_pos(); + + /* eom */ + mt_com.mt_count = 1; + mt_com.mt_op = MTEOM; + r1 = ioctl(fd, MTIOCTOP, &mt_com); + printf("goto eom\n"); + print_pos(); + + close(fd); + return(0); +} -- 2.39.5