📄 output-rait.c
字号:
/* NOTE: this driver is *deprecated* and should not be used. See the Device API * in device-src/ for the new implementation. */#ifdef NO_AMANDA#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <errno.h>#include <fcntl.h>#include <sys/stat.h>#include <sys/wait.h>#include <sys/ioctl.h>#else#include "amanda.h"#include "tapeio.h"#endif#include "output-rait.h"#include "output-tape.h"#ifdef NO_AMANDA#define amfree(x) do { \ if (x) { \ int save_errno = errno; \ free(x); \ (x) = NULL; \ errno = save_errno; \ }} while(0)#define tape_open open#define tapefd_read read#define tapefd_write write#define tapefd_close close#define tape_access access#define tape_stat stat#define tapefd_fsf tape_tapefd_fsf#define tapefd_rewind tape_tapefd_rewind#define tapefd_status tape_tapefd_status#define tapefd_unload tape_tapefd_unload#define tapefd_weof tape_tapefd_weofint tapeio_init_devname (char * dev, char **dev_left, char **dev_right, char **dev_next);char *tapeio_next_devname (char * dev_left, char * dev_right, char **dev_next);#endif/*** RAIT -- redundant array of (inexpensive?) tapes**** Author: Marc Mengel <mengel@fnal.gov>**** This package provides for striping input/output across** multiple tape drives.** Table of Contents rait.c..................................................1 MAX_RAITS.........................................2 rait_table........................................2 rait_open(char *dev, int flags, mode_t mode)......2 rait_close(int fd)................................3 rait_lseek(int fd, long pos, int whence)..........4 rait_write(int fd, const char *buf, size_t len) ..5 rait_read(int fd, char *buf, size_t len)..........6 rait_ioctl(int fd, int op, void *p)...............8 rait_access(devname, R_OK|W_OK)...................8 rait_stat(devname, struct statbuf*)...............8 rait_copy(char *f1, char *f2).....................9 ifndef NO_AMANDA rait_tapefd_fsf(rait_tapefd, count)..........10 rait_tapefd_rewind(rait_tapefd)..............10 rait_tapefd_resetofs(rait_tapefd)............10 rait_tapefd_unload(rait_tapefd)..............10 rait_tapefd_status(rait_tapefd, stat)........10 rait_tapefd_weof(rait_tapefd, count).........10 rait.h.................................................1 typedef RAIT......................................1 ifdef RAIT_REDIRECT...............................1 open.........................................1 close........................................1 ioctl........................................1 read.........................................1 write........................................1*//**//*** rait_open takes a string like:** "/dev/rmt/tps0d{3,5,7,19}nrnsv"** and opens** "/dev/rmt/tps0d3nrnsv"** "/dev/rmt/tps0d5nrnsv"** "/dev/rmt/tps0d7nrnsv"** "/dev/rmt/tps0d19nrnsv"** as a RAIT.**** If it has no curly brace, we treat it as a plain device,** and do a normal open, and do normal operations on it.*/#ifdef RAIT_DEBUG#define rait_debug(...) do { \ int save_errno = errno; \ \ if (0 != getenv("RAIT_DEBUG")) { \ dbprintf(__VA_ARGS__); \ } \ errno = save_errno; \} while (0)#else#define rait_debug(...)#endifstatic RAIT *rait_table = 0; /* table to keep track of RAITS */static size_t rait_table_count;#ifdef NO_AMANDA/* * amtable_alloc -- (re)allocate enough space for some number of elements. * * input: table -- pointer to pointer to table * current -- pointer to current number of elements * elsize -- size of a table element * count -- desired number of elements * bump -- round up factor * output: table -- possibly adjusted to point to new table area * current -- possibly adjusted to new number of elements */static intamtable_alloc( void ** table, int * current, size_t elsize, int count, int bump, void * dummy){ void *table_new; int table_count_new; if (count >= *current) { table_count_new = ((count + bump) / bump) * bump; table_new = alloc(table_count_new * elsize); if (0 != *table) { memcpy(table_new, *table, *current * elsize); amfree(*table); } *table = table_new; memset(((char *)*table) + *current * elsize, 0, (table_count_new - *current) * elsize); *current = table_count_new; } return 0;}/* * amtable_free -- release a table. * * input: table -- pointer to pointer to table * current -- pointer to current number of elements * output: table -- possibly adjusted to point to new table area * current -- possibly adjusted to new number of elements */voidamtable_free( void ** table, int * current){ amfree(*table); *current = 0;}#endif#define rait_table_alloc(fd) amtable_alloc((void **)rait_table_p, \ &rait_table_count, \ SIZEOF(*rait_table), \ (size_t)(fd), \ 10, \ NULL)intrait_open( char * dev, int flags, mode_t mask){ int fd; /* the file descriptor number to return */ RAIT *res; /* resulting RAIT structure */ char *dev_left; /* string before { */ char *dev_right; /* string after } */ char *dev_next; /* string inside {} */ char *dev_real; /* parsed device name */ int rait_flag; /* true if RAIT syntax in dev */ int save_errno; int r; RAIT **rait_table_p = &rait_table; int **fds_p; rait_debug(stderr,_("rait_open( %s, %d, %d )\n"), dev, flags, mask); rait_flag = (0 != strchr(dev, '{')); if (rait_flag) { /* ** we have to return a valid file descriptor, so use ** a dummy one to /dev/null */ fd = open("/dev/null",flags,mask); } else { /* ** call the normal tape_open function if we are not ** going to do RAIT */ fd = tape_open(dev,flags,mask); } if(-1 == fd) { rait_debug(stderr, _("rait_open:returning %d: %s\n"), fd, strerror(errno)); return fd; } if(0 != rait_table_alloc(fd + 1)) { save_errno = errno; (void)tapefd_close(fd); errno = save_errno; rait_debug(stderr, _("rait_open:returning %d: %s\n"), -1, strerror(errno)); return -1; } res = &rait_table[fd]; memset(res, 0, SIZEOF(*res)); res->nopen = 1; res->fd_count = 0; if (rait_flag) { /* copy and parse the dev string so we can scribble on it */ dev = stralloc(dev); if (0 == dev) { rait_debug(stderr, _("rait_open:returning %d: %s\n"), -1, _("out of stralloc memory")); return -1; } if (0 != tapeio_init_devname(dev, &dev_left, &dev_right, &dev_next)) { rait_debug(stderr, _("rait_open:returning %d: %s\n"), -1, strerror(errno)); return -1; } while (0 != (dev_real = tapeio_next_devname(dev_left, dev_right, &dev_next))) { fds_p = &(res->fds); r = amtable_alloc((void **)fds_p, &res->fd_count, SIZEOF(*res->fds), (size_t)res->nfds + 1, 10, NULL); if (0 != r) { (void)rait_close(fd); fd = -1; amfree(dev_real); break; } res->fds[ res->nfds ] = tape_open(dev_real,flags,mask); rait_debug(stderr,_("rait_open:opening %s yields %d\n"), dev_real, res->fds[res->nfds] ); if ( res->fds[res->nfds] < 0 ) { save_errno = errno; (void)rait_close(fd); amfree(dev_real); errno = save_errno; fd = -1; break; } tapefd_set_master_fd(res->fds[res->nfds], fd); amfree(dev_real); res->nfds++; } /* clean up our copied string */ amfree(dev); } else { /* ** set things up to treat this as a normal tape if we ever ** come in here again */ res->nfds = 0; fds_p = &(res->fds); r = amtable_alloc((void **)fds_p, &res->fd_count, SIZEOF(*res->fds), (size_t)res->nfds + 1, 1, NULL); if (0 != r) { (void)tapefd_close(fd); memset(res, 0, SIZEOF(*res)); errno = ENOMEM; fd = -1; } else { res->fds[res->nfds] = fd; res->nfds++; } } if (fd >= 0 && res->nfds > 0) { res->readres = alloc(res->nfds * SIZEOF(*res->readres)); memset(res->readres, 0, res->nfds * SIZEOF(*res->readres)); } rait_debug(stderr, _("rait_open:returning %d%s%s\n"), fd, (fd < 0) ? ": " : "", (fd < 0) ? strerror(errno) : ""); return fd;}#ifdef NO_AMANDAinttapeio_init_devname( char * dev, char ** dev_left, char ** dev_right, char ** dev_next){ /* ** find the first { and then the first } that follows it */ if ( 0 == (*dev_next = strchr(dev, '{')) || 0 == (*dev_right = strchr(*dev_next + 1, '}')) ) { /* we dont have a {} pair */ amfree(dev); errno = EINVAL; return -1; } *dev_left = dev; /* before the { */ **dev_next = 0; /* zap the { */ (*dev_next)++; (*dev_right)++; /* after the } */ return 0;}char *tapeio_next_devname( char * dev_left, char * dev_right, char ** dev_next){ char *dev_real = 0; char *next; int len; next = *dev_next; if (0 != (*dev_next = strchr(next, ',')) || 0 != (*dev_next = strchr(next, '}'))){ **dev_next = 0; /* zap the terminator */ (*dev_next)++; /* ** we have one string picked out, build it into the buffer */ len = strlen(dev_left) + strlen(next) + strlen(dev_right) + 1; dev_real = alloc(len); strcpy(dev_real, dev_left); /* safe */ strcat(dev_real, next); /* safe */ strcat(dev_real, dev_right); /* safe */ } return dev_real;}#endif/*** close everything we opened and free our memory.*/intrait_close( int fd){ int i; /* index into RAIT drives */ int j; /* individual tapefd_close result */ int res; /* result from close */ RAIT *pr; /* RAIT entry from table */ int save_errno = errno; pid_t kid; int **fds_p; rait_debug(stderr,_("rait_close( %d )\n"), fd); if ((fd < 0) || ((size_t)fd >= rait_table_count)) { errno = EBADF; rait_debug(stderr, _("rait_close:returning %d: %s\n"), -1, strerror(errno)); return -1; } pr = &rait_table[fd]; if (0 == pr->nopen) { errno = EBADF; rait_debug(stderr, _("rait_close:returning %d: %s\n"), -1, strerror(errno)); return -1; } if (0 == pr->readres && 0 < pr->nfds) { pr->readres = alloc(pr->nfds * SIZEOF(*pr->readres)); memset(pr->readres, 0, pr->nfds * SIZEOF(*pr->readres)); } res = 0; /* ** this looks strange, but we start kids who are going to close the ** drives in parallel just after the parent has closed their copy of ** the descriptor. ('cause closing tape devices usually causes slow ** activities like filemark writes, etc.) */ for( i = 0; i < pr->nfds; i++ ) { if(tapefd_can_fork(pr->fds[i])) { if ((kid = fork()) == 0) { /* we are the child process */ sleep(0); j = tapefd_close(pr->fds[i]); exit(j); } else { /* remember who the child is or that an error happened */ pr->readres[i] = (ssize_t)kid; } } else { j = tapefd_close(pr->fds[i]); if ( j != 0 ) res = j; pr->readres[i] = -1; } } for( i = 0; i < pr->nfds; i++ ) { j = tapefd_close(pr->fds[i]); if ( j != 0 ) res = j; } for( i = 0; i < pr->nfds; i++ ) { int stat; if(pr->readres[i] != -1) { waitpid((pid_t)pr->readres[i], &stat, 0); if( WEXITSTATUS(stat) != 0 ) { res = WEXITSTATUS(stat); if( res == 255 ) res = -1; } } } if (pr->nfds > 1) { (void)close(fd); /* close the dummy /dev/null descriptor */ } if (0 != pr->fds) { fds_p = &pr->fds; amtable_free((void **)fds_p, &pr->fd_count); } if (0 != pr->readres) { amfree(pr->readres); } if (0 != pr->xorbuf) { amfree(pr->xorbuf); } pr->nopen = 0; errno = save_errno; rait_debug(stderr, _("rait_close:returning %d%s%s\n"), res, (res < 0) ? ": " : "", (res < 0) ? strerror(errno) : ""); return res;}/**//*** seek out to the nth byte on the RAIT set.** this is assumed to be evenly divided across all the stripes*/off_trait_lseek( int fd, off_t pos, int whence){ int i; /* drive number in RAIT */ off_t res, /* result of lseeks */ total; /* total of results */ RAIT *pr; /* RAIT slot in table */ rait_debug(stderr, _("rait_lseek(%d, %lld, %d)\n"), fd, (long long)pos, whence); if ((fd < 0) || ((size_t)fd >= rait_table_count)) { errno = EBADF; rait_debug(stderr, _("rait_lseek:returning %d: %s\n"), -1, strerror(errno)); return (off_t)-1; } pr = &rait_table[fd]; if (0 == pr->nopen) { errno = EBADF; rait_debug(stderr, _("rait_lseek:returning %d: %s\n"), -1, strerror(errno)); return (off_t)-1; } if ((pr->nfds > 1) && ((pos % (off_t)(pr->nfds-1)) != (off_t)0)) { errno = EDOM; total = (off_t)-1; } else { total = (off_t)0; pos = pos / (off_t)pr->nfds; for( i = 0; i < pr->nfds; i++ ) { if ((off_t)0 >= (res = lseek(pr->fds[i], pos, whence))) { total = res; break; } total += res; } } rait_debug(stderr, _("rait_lseek:returning %ld%s%s\n"), total, (total < 0) ? ": " : "", (total < 0) ? strerror(errno) : ""); return total;}/**//*** if we only have one stream, just do a write,** otherwise compute an xor sum, and do several** writes...*/ssize_trait_write( int fd, const void *bufptr, size_t len){ const char *buf = bufptr; int i; /* drive number */ size_t j; /* byte offset */ RAIT *pr; /* RAIT structure for this RAIT */ ssize_t res; ssize_t total = 0; int data_fds; /* number of data stream file descriptors */ rait_debug(stderr, _("rait_write(%d,%lx,%d)\n"),fd,(unsigned long)buf,len); if ((fd < 0) || ((size_t)fd >= rait_table_count)) { errno = EBADF; rait_debug(stderr, _("rait_write:returning %d: %s\n"), -1, strerror(errno)); return -1; } pr = &rait_table[fd]; if (0 == pr->nopen) { errno = EBADF; rait_debug(stderr, _("rait_write:returning %d: %s\n"), -1, strerror(errno)); return -1; } /* need to be able to slice it up evenly... */ if (pr->nfds > 1) { data_fds = pr->nfds - 1; if (0 != len % data_fds) { errno = EDOM; rait_debug(stderr, _("rait_write:returning %d: %s\n"), -1, strerror(errno)); return -1; } /* each slice gets an even portion */ len = len / data_fds; /* make sure we have enough buffer space */ if (len > (size_t)pr->xorbuflen) { if (0 != pr->xorbuf) { amfree(pr->xorbuf); } pr->xorbuf = alloc(len); pr->xorbuflen = len; } /* compute the sum */ memcpy(pr->xorbuf, buf, len); for( i = 1; i < data_fds; i++ ) { for( j = 0; j < len; j++ ) { pr->xorbuf[j] ^= buf[len * i + j]; } } } else { data_fds = pr->nfds; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -