X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fstored%2Fdev.c;h=4d770d3726ef763379130eda81985a92bb675277;hb=c60355e991ba92ec5d7eb3c887b24291f635e16c;hp=ece63bff7e4a1591d74907bc6f5827ae88d4742b;hpb=c5583300c605515be9918909b3ac0dcd83aaca1e;p=bacula%2Fbacula diff --git a/bacula/src/stored/dev.c b/bacula/src/stored/dev.c index ece63bff7e..4d770d3726 100644 --- a/bacula/src/stored/dev.c +++ b/bacula/src/stored/dev.c @@ -2,7 +2,7 @@ * * dev.c -- low level operations on device (storage device) * - * Kern Sibbald + * Kern Sibbald, MM * * NOTE!!!! None of these routines are reentrant. You must * use lock_device() and unlock_device() at a higher level, @@ -57,15 +57,13 @@ * to include ST_EOT, which is ephimeral, and ST_WEOT, which is * persistent. Lots of routines clear ST_EOT, but ST_WEOT is * cleared only when the problem goes away. Now when ST_WEOT - * is set all calls to write_dev() are handled as usual. However, - * in write_block() instead of attempting to write the block to - * the physical device, it is chained into a list of blocks written - * after the EOT condition. In addition, all threads are blocked - * from writing on the tape by calling lock(), and thread other + * is set all calls to write_block_to_device() call the fix_up + * routine. In addition, all threads are blocked + * from writing on the tape by calling lock_dev(), and thread other * than the first thread to hit the EOT will block on a condition * variable. The first thread to hit the EOT will continue to * be able to read and write the tape (he sort of tunnels through - * the locking mechanism -- see lock() for details). + * the locking mechanism -- see lock_dev() for details). * * Now presumably somewhere higher in the chain of command * (device.c), someone will notice the EOT condition and @@ -83,6 +81,7 @@ #include "stored.h" /* Forward referenced functions */ +void set_os_device_parameters(DEVICE *dev); /* * Allocate and initialize the DEVICE structure @@ -99,32 +98,34 @@ DEVICE * init_dev(DEVICE *dev, DEVRES *device) { struct stat statp; - int tape, fifo; + bool tape, fifo; int errstat; + DCR *dcr = NULL; /* Check that device is available */ if (stat(device->device_name, &statp) < 0) { + berrno be; if (dev) { dev->dev_errno = errno; } Emsg2(M_FATAL, 0, "Unable to stat device %s : %s\n", device->device_name, - strerror(errno)); + be.strerror()); return NULL; } - tape = FALSE; - fifo = FALSE; + tape = false; + fifo = false; if (S_ISDIR(statp.st_mode)) { - tape = FALSE; + tape = false; } else if (S_ISCHR(statp.st_mode)) { - tape = TRUE; + tape = true; } else if (S_ISFIFO(statp.st_mode)) { - fifo = TRUE; + fifo = true; } else { if (dev) { dev->dev_errno = ENODEV; } Emsg2(M_FATAL, 0, _("%s is an unknown device type. Must be tape or directory. st_mode=%x\n"), - dev_name, statp.st_mode); + device->device_name, statp.st_mode); return NULL; } if (!dev) { @@ -148,6 +149,8 @@ init_dev(DEVICE *dev, DEVRES *device) dev->max_open_wait = device->max_open_wait; dev->max_open_vols = device->max_open_vols; dev->vol_poll_interval = device->vol_poll_interval; + dev->max_spool_size = device->max_spool_size; + dev->drive_index = device->drive_index; /* Sanity check */ if (dev->vol_poll_interval && dev->vol_poll_interval < 60) { dev->vol_poll_interval = 60; @@ -177,22 +180,40 @@ init_dev(DEVICE *dev, DEVRES *device) *dev->errmsg = 0; if ((errstat = pthread_mutex_init(&dev->mutex, NULL)) != 0) { + berrno be; dev->dev_errno = errstat; - Mmsg1(&dev->errmsg, _("Unable to init mutex: ERR=%s\n"), strerror(errstat)); + Mmsg1(dev->errmsg, _("Unable to init mutex: ERR=%s\n"), be.strerror(errstat)); Emsg0(M_FATAL, 0, dev->errmsg); } if ((errstat = pthread_cond_init(&dev->wait, NULL)) != 0) { + berrno be; dev->dev_errno = errstat; - Mmsg1(&dev->errmsg, _("Unable to init cond variable: ERR=%s\n"), strerror(errstat)); + Mmsg1(dev->errmsg, _("Unable to init cond variable: ERR=%s\n"), be.strerror(errstat)); Emsg0(M_FATAL, 0, dev->errmsg); } if ((errstat = pthread_cond_init(&dev->wait_next_vol, NULL)) != 0) { + berrno be; dev->dev_errno = errstat; - Mmsg1(&dev->errmsg, _("Unable to init cond variable: ERR=%s\n"), strerror(errstat)); + Mmsg1(dev->errmsg, _("Unable to init cond variable: ERR=%s\n"), be.strerror(errstat)); Emsg0(M_FATAL, 0, dev->errmsg); } + if ((errstat = pthread_mutex_init(&dev->spool_mutex, NULL)) != 0) { + berrno be; + dev->dev_errno = errstat; + Mmsg1(dev->errmsg, _("Unable to init mutex: ERR=%s\n"), be.strerror(errstat)); + Emsg0(M_FATAL, 0, dev->errmsg); + } + if ((errstat = rwl_init(&dev->lock)) != 0) { + berrno be; + dev->dev_errno = errstat; + Mmsg1(dev->errmsg, _("Unable to init mutex: ERR=%s\n"), be.strerror(errstat)); + Emsg0(M_FATAL, 0, dev->errmsg); + } + dev->fd = -1; + dev->attached_dcrs = New(dlist(dcr, &dcr->dev_link)); Dmsg2(29, "init_dev: tape=%d dev_name=%s\n", dev_is_tape(dev), dev->dev_name); + return dev; } @@ -277,6 +298,7 @@ open_dev(DEVICE *dev, char *VolName, int mode) dev->state |= ST_OPENED; dev->use_count = 1; update_pos_dev(dev); /* update position */ + set_os_device_parameters(dev); /* do system dependent stuff */ } /* Stop any open() timer we started */ if (dev->tid) { @@ -289,16 +311,16 @@ open_dev(DEVICE *dev, char *VolName, int mode) * Handle opening of File Archive (not a tape) */ if (VolName == NULL || *VolName == 0) { - Mmsg(&dev->errmsg, _("Could not open file device %s. No Volume name given.\n"), + Mmsg(dev->errmsg, _("Could not open file device %s. No Volume name given.\n"), dev->dev_name); return -1; } archive_name = get_pool_memory(PM_FNAME); - pm_strcpy(&archive_name, dev->dev_name); + pm_strcpy(archive_name, dev->dev_name); if (archive_name[strlen(archive_name)] != '/') { - pm_strcat(&archive_name, "/"); + pm_strcat(archive_name, "/"); } - pm_strcat(&archive_name, VolName); + pm_strcat(archive_name, VolName); Dmsg1(29, "open_dev: device is disk %s\n", archive_name); if (mode == OPEN_READ_WRITE) { dev->mode = O_CREAT | O_RDWR | O_BINARY; @@ -432,7 +454,7 @@ eod_dev(DEVICE *dev) if (dev_cap(dev, CAP_FASTFSF) && !dev_cap(dev, CAP_EOM)) { struct mtget mt_stat; - Dmsg0(000,"Using FAST FSF for EOM\n"); + Dmsg0(100,"Using FAST FSF for EOM\n"); if (ioctl(dev->fd, MTIOCGET, (char *)&mt_stat) == 0 && mt_stat.mt_fileno <= 0) { if (!rewind_dev(dev)) { return 0; @@ -450,7 +472,7 @@ eod_dev(DEVICE *dev) } if (dev_cap(dev, CAP_EOM)) { - Dmsg0(000,"Using EOM for EOM\n"); + Dmsg0(100,"Using EOM for EOM\n"); mt_com.mt_op = MTEOM; mt_com.mt_count = 1; } @@ -470,7 +492,7 @@ eod_dev(DEVICE *dev) dev->dev_name, strerror(dev->dev_errno)); return 0; } - Dmsg2(000, "EOD file=%d block=%d\n", mt_stat.mt_fileno, mt_stat.mt_blkno); + Dmsg2(100, "EOD file=%d block=%d\n", mt_stat.mt_fileno, mt_stat.mt_blkno); dev->file = mt_stat.mt_fileno; /* @@ -499,10 +521,10 @@ eod_dev(DEVICE *dev) */ if (file_num == (int)dev->file) { struct mtget mt_stat; - Dmsg1(000, "fsf_dev did not advance from file %d\n", file_num); + Dmsg1(100, "fsf_dev did not advance from file %d\n", file_num); if (ioctl(dev->fd, MTIOCGET, (char *)&mt_stat) == 0 && mt_stat.mt_fileno >= 0) { - Dmsg2(000, "Adjust file from %d to %d\n", dev->file , mt_stat.mt_fileno); + Dmsg2(100, "Adjust file from %d to %d\n", dev->file , mt_stat.mt_fileno); dev->file = mt_stat.mt_fileno; } stat = 0; @@ -521,7 +543,7 @@ eod_dev(DEVICE *dev) stat = bsf_dev(dev, 1); /* If BSF worked and fileno is known (not -1), set file */ if (ioctl(dev->fd, MTIOCGET, (char *)&mt_stat) == 0 && mt_stat.mt_fileno >= 0) { - Dmsg2(000, "Adjust file from %d to %d\n", dev->file , mt_stat.mt_fileno); + Dmsg2(100, "Adjust file from %d to %d\n", dev->file , mt_stat.mt_fileno); dev->file = mt_stat.mt_fileno; } else { dev->file++; /* wing it -- not correct on all OSes */ @@ -537,19 +559,19 @@ eod_dev(DEVICE *dev) /* * Set the position of the device -- only for files * For other devices, there is no generic way to do it. - * Returns: 1 on succes - * 0 on error + * Returns: true on succes + * false on error */ -int update_pos_dev(DEVICE *dev) +bool update_pos_dev(DEVICE *dev) { off_t pos; - int stat = 0; + bool ok = true; if (dev->fd < 0) { dev->dev_errno = EBADF; Mmsg0(&dev->errmsg, _("Bad device call. Archive not open\n")); Emsg0(M_FATAL, 0, dev->errmsg); - return 0; + return false; } /* Find out where we are */ @@ -562,13 +584,12 @@ int update_pos_dev(DEVICE *dev) dev->dev_errno = errno; Mmsg2(&dev->errmsg, _("lseek error on %s. ERR=%s.\n"), dev->dev_name, strerror(dev->dev_errno)); + ok = false; } else { - stat = 1; dev->file_addr = pos; } - return stat; } - return 1; + return ok; } @@ -654,10 +675,10 @@ uint32_t status_dev(DEVICE *dev) /* * Load medium in device - * Returns: 1 on success - * 0 on failure + * Returns: true on success + * false on failure */ -int load_dev(DEVICE *dev) +bool load_dev(DEVICE *dev) { #ifdef MTLOAD struct mtop mt_com; @@ -667,17 +688,17 @@ int load_dev(DEVICE *dev) dev->dev_errno = EBADF; Mmsg0(&dev->errmsg, _("Bad call to load_dev. Archive not open\n")); Emsg0(M_FATAL, 0, dev->errmsg); - return 0; + return false; } if (!(dev->state & ST_TAPE)) { - return 1; + return true; } #ifndef MTLOAD Dmsg0(200, "stored: MTLOAD command not available\n"); dev->dev_errno = ENOTTY; /* function not available */ Mmsg2(&dev->errmsg, _("ioctl MTLOAD error on %s. ERR=%s.\n"), dev->dev_name, strerror(dev->dev_errno)); return 0; - return 0; + return false; #else dev->block_num = dev->file = 0; @@ -688,17 +709,18 @@ int load_dev(DEVICE *dev) dev->dev_errno = errno; Mmsg2(&dev->errmsg, _("ioctl MTLOAD error on %s. ERR=%s.\n"), dev->dev_name, strerror(dev->dev_errno)); return 0; + return false; } - return 1; + return true; #endif } /* * Rewind device and put it offline - * Returns: 1 on success - * 0 on failure + * Returns: true on success + * false on failure */ -int offline_dev(DEVICE *dev) +bool offline_dev(DEVICE *dev) { struct mtop mt_com; @@ -706,10 +728,10 @@ int offline_dev(DEVICE *dev) dev->dev_errno = EBADF; Mmsg0(&dev->errmsg, _("Bad call to offline_dev. Archive not open\n")); Emsg0(M_FATAL, 0, dev->errmsg); - return 0; + return false; } if (!(dev->state & ST_TAPE)) { - return 1; + return true; } dev->state &= ~(ST_APPEND|ST_READ|ST_EOT|ST_EOF|ST_WEOT); /* remove EOF/EOT flags */ @@ -726,10 +748,10 @@ int offline_dev(DEVICE *dev) dev->dev_errno = errno; Mmsg2(&dev->errmsg, _("ioctl MTOFFL error on %s. ERR=%s.\n"), dev->dev_name, strerror(dev->dev_errno)); - return 0; + return false; } Dmsg1(100, "Offlined device %s\n", dev->dev_name); - return 1; + return true; } int offline_or_rewind_dev(DEVICE *dev) @@ -750,10 +772,10 @@ int offline_or_rewind_dev(DEVICE *dev) /* * Foward space a file - * Returns: 1 on success - * 0 on failure + * Returns: true on success + * false on failure */ -int +bool fsf_dev(DEVICE *dev, int num) { struct mtget mt_stat; @@ -764,16 +786,16 @@ fsf_dev(DEVICE *dev, int num) dev->dev_errno = EBADF; Mmsg0(&dev->errmsg, _("Bad call to fsf_dev. Archive not open\n")); Emsg0(M_FATAL, 0, dev->errmsg); - return 0; + return false; } if (!(dev->state & ST_TAPE)) { - return 1; + return true; } if (dev->state & ST_EOT) { dev->dev_errno = 0; - Mmsg1(&dev->errmsg, _("Device %s at End of Tape.\n"), dev->dev_name); - return 0; + Mmsg1(dev->errmsg, _("Device %s at End of Tape.\n"), dev->dev_name); + return false; } if (dev->state & ST_EOF) { Dmsg0(200, "ST_EOF set on entry to FSF\n"); @@ -793,19 +815,20 @@ fsf_dev(DEVICE *dev, int num) mt_com.mt_count = num; stat = ioctl(dev->fd, MTIOCTOP, (char *)&mt_com); if (stat < 0 || ioctl(dev->fd, MTIOCGET, (char *)&mt_stat) < 0) { + berrno be; dev->state |= ST_EOT; Dmsg0(200, "Set ST_EOT\n"); clrerror_dev(dev, MTFSF); - Mmsg2(&dev->errmsg, _("ioctl MTFSF error on %s. ERR=%s.\n"), - dev->dev_name, strerror(dev->dev_errno)); + Mmsg2(dev->errmsg, _("ioctl MTFSF error on %s. ERR=%s.\n"), + dev->dev_name, be.strerror()); Dmsg1(200, "%s", dev->errmsg); - return 0; + return false; } Dmsg2(200, "fsf file=%d block=%d\n", mt_stat.mt_fileno, mt_stat.mt_blkno); dev->file = mt_stat.mt_fileno; dev->state |= ST_EOF; /* just read EOF */ dev->file_addr = 0; - return 1; + return true; /* * Here if CAP_FSF is set, and virtually all drives @@ -832,12 +855,13 @@ fsf_dev(DEVICE *dev, int num) if (errno == ENOMEM) { /* tape record exceeds buf len */ stat = rbuf_len; /* This is OK */ } else { + berrno be; dev->state |= ST_EOT; clrerror_dev(dev, -1); Dmsg2(200, "Set ST_EOT read errno=%d. ERR=%s\n", dev->dev_errno, - strerror(dev->dev_errno)); - Mmsg2(&dev->errmsg, _("read error on %s. ERR=%s.\n"), - dev->dev_name, strerror(dev->dev_errno)); + be.strerror()); + Mmsg2(dev->errmsg, _("read error on %s. ERR=%s.\n"), + dev->dev_name, be.strerror(dev->dev_errno)); Dmsg1(200, "%s", dev->errmsg); break; } @@ -888,7 +912,7 @@ fsf_dev(DEVICE *dev, int num) } if (dev->state & ST_EOT) { dev->dev_errno = 0; - Mmsg1(&dev->errmsg, _("Device %s at End of Tape.\n"), dev->dev_name); + Mmsg1(dev->errmsg, _("Device %s at End of Tape.\n"), dev->dev_name); stat = -1; } else { stat = 0; @@ -901,15 +925,15 @@ fsf_dev(DEVICE *dev, int num) if (dev->state & ST_EOT) Dmsg0(200, "ST_EOT set on exit FSF\n"); Dmsg1(200, "Return from FSF file=%d\n", dev->file); - return stat == 0 ? 1 : 0; + return stat == 0; } /* * Backward space a file - * Returns: 0 on failure - * 1 on success + * Returns: false on failure + * true on success */ -int +bool bsf_dev(DEVICE *dev, int num) { struct mtop mt_com; @@ -917,15 +941,15 @@ bsf_dev(DEVICE *dev, int num) if (dev->fd < 0) { dev->dev_errno = EBADF; - Mmsg0(&dev->errmsg, _("Bad call to bsf_dev. Archive device not open\n")); + Mmsg0(dev->errmsg, _("Bad call to bsf_dev. Archive device not open\n")); Emsg0(M_FATAL, 0, dev->errmsg); - return 0; + return false; } if (!(dev_state(dev, ST_TAPE))) { - Mmsg1(&dev->errmsg, _("Device %s cannot BSF because it is not a tape.\n"), + Mmsg1(dev->errmsg, _("Device %s cannot BSF because it is not a tape.\n"), dev->dev_name); - return 0; + return false; } Dmsg0(29, "bsf_dev\n"); dev->state &= ~(ST_EOT|ST_EOF); @@ -936,20 +960,20 @@ bsf_dev(DEVICE *dev, int num) stat = ioctl(dev->fd, MTIOCTOP, (char *)&mt_com); if (stat < 0) { clrerror_dev(dev, MTBSF); - Mmsg2(&dev->errmsg, _("ioctl MTBSF error on %s. ERR=%s.\n"), + Mmsg2(dev->errmsg, _("ioctl MTBSF error on %s. ERR=%s.\n"), dev->dev_name, strerror(dev->dev_errno)); } update_pos_dev(dev); - return stat == 0 ? 1 : 0; + return stat == 0; } /* * Foward space a record - * Returns: 0 on failure - * 1 on success + * Returns: false on failure + * true on success */ -int +bool fsr_dev(DEVICE *dev, int num) { struct mtop mt_com; @@ -957,16 +981,20 @@ fsr_dev(DEVICE *dev, int num) if (dev->fd < 0) { dev->dev_errno = EBADF; - Mmsg0(&dev->errmsg, _("Bad call to fsr_dev. Archive not open\n")); + Mmsg0(dev->errmsg, _("Bad call to fsr_dev. Archive not open\n")); Emsg0(M_FATAL, 0, dev->errmsg); - return 0; + return false; } if (!(dev_state(dev, ST_TAPE))) { - return 0; + return false; + } + if (!dev_cap(dev, CAP_FSR)) { + Mmsg1(dev->errmsg, _("ioctl MTFSR not permitted on %s.\n"), dev->dev_name); + return false; } + Dmsg0(29, "fsr_dev\n"); - dev->block_num += num; mt_com.mt_op = MTFSR; mt_com.mt_count = num; stat = ioctl(dev->fd, MTIOCTOP, (char *)&mt_com); @@ -974,27 +1002,36 @@ fsr_dev(DEVICE *dev, int num) dev->state &= ~ST_EOF; dev->block_num += num; } else { - if (dev->state & ST_EOF) { - dev->state |= ST_EOT; + struct mtget mt_stat; + if (ioctl(dev->fd, MTIOCGET, (char *)&mt_stat) == 0 && mt_stat.mt_fileno >= 0) { + Dmsg4(100, "Adjust from %d:%d to %d:%d\n", dev->file, + dev->block_num, mt_stat.mt_fileno, mt_stat.mt_blkno); + dev->file = mt_stat.mt_fileno; + dev->block_num = mt_stat.mt_blkno; } else { -// dev->state |= ST_EOF; /* assume EOF */ -// dev->file++; -// dev->file_addr = 0; + if (dev->state & ST_EOF) { + dev->state |= ST_EOT; + } else { + dev->state |= ST_EOF; /* assume EOF */ + dev->file++; + dev->block_num = 0; + dev->file_addr = 0; + } } clrerror_dev(dev, MTFSR); - Mmsg2(&dev->errmsg, _("ioctl MTFSR error on %s. ERR=%s.\n"), + Mmsg2(dev->errmsg, _("ioctl MTFSR error on %s. ERR=%s.\n"), dev->dev_name, strerror(dev->dev_errno)); } update_pos_dev(dev); - return stat == 0 ? 1 : 0; + return stat == 0; } /* * Backward space a record - * Returns: 0 on failure - * 1 on success + * Returns: false on failure + * true on success */ -int +bool bsr_dev(DEVICE *dev, int num) { struct mtop mt_com; @@ -1002,19 +1039,18 @@ bsr_dev(DEVICE *dev, int num) if (dev->fd < 0) { dev->dev_errno = EBADF; - Mmsg0(&dev->errmsg, _("Bad call to bsr_dev. Archive not open\n")); + Mmsg0(dev->errmsg, _("Bad call to bsr_dev. Archive not open\n")); Emsg0(M_FATAL, 0, dev->errmsg); - return 0; + return false; } if (!(dev->state & ST_TAPE)) { - return 0; + return false; } if (!dev_cap(dev, CAP_BSR)) { - Mmsg1(&dev->errmsg, _("ioctl MTBSR not permitted on %s.\n"), - dev->dev_name); - return 0; + Mmsg1(dev->errmsg, _("ioctl MTBSR not permitted on %s.\n"), dev->dev_name); + return false; } Dmsg0(29, "bsr_dev\n"); @@ -1025,56 +1061,66 @@ bsr_dev(DEVICE *dev, int num) stat = ioctl(dev->fd, MTIOCTOP, (char *)&mt_com); if (stat < 0) { clrerror_dev(dev, MTBSR); - Mmsg2(&dev->errmsg, _("ioctl MTBSR error on %s. ERR=%s.\n"), + Mmsg2(dev->errmsg, _("ioctl MTBSR error on %s. ERR=%s.\n"), dev->dev_name, strerror(dev->dev_errno)); } update_pos_dev(dev); - return stat == 0 ? 1 : 0; + return stat == 0; } /* * Reposition the device to file, block - * Currently only works for tapes. - * Returns: 0 on failure - * 1 on success + * Returns: false on failure + * true on success */ -int +bool reposition_dev(DEVICE *dev, uint32_t file, uint32_t block) { if (dev->fd < 0) { dev->dev_errno = EBADF; - Mmsg0(&dev->errmsg, _("Bad call to reposition_dev. Archive not open\n")); + Mmsg0(dev->errmsg, _("Bad call to reposition_dev. Archive not open\n")); Emsg0(M_FATAL, 0, dev->errmsg); - return 0; + return false; } if (!(dev_state(dev, ST_TAPE))) { - return 0; + off_t pos = (((off_t)file)<<32) + block; + Dmsg1(100, "===== lseek to %d\n", (int)pos); + if (lseek(dev->fd, pos, SEEK_SET) == (off_t)-1) { + dev->dev_errno = errno; + Mmsg2(dev->errmsg, _("lseek error on %s. ERR=%s.\n"), + dev->dev_name, strerror(dev->dev_errno)); + return false; + } + dev->file = file; + dev->block_num = block; + dev->file_addr = pos; + return true; } Dmsg4(100, "reposition_dev from %u:%u to %u:%u\n", dev->file, dev->block_num, file, block); if (file < dev->file) { Dmsg0(100, "Rewind_dev\n"); if (!rewind_dev(dev)) { - return 0; + return false; } } if (file > dev->file) { Dmsg1(100, "fsf %d\n", file-dev->file); if (!fsf_dev(dev, file-dev->file)) { - return 0; + return false; } } if (block < dev->block_num) { bsf_dev(dev, 1); fsf_dev(dev, 1); } - if (block > dev->block_num) { + if (dev_cap(dev, CAP_POSITIONBLOCKS) && block > dev->block_num) { /* Ignore errors as Bacula can read to the correct block */ Dmsg1(100, "fsr %d\n", block-dev->block_num); - fsr_dev(dev, block-dev->block_num); + return fsr_dev(dev, block-dev->block_num); } - return 1; + return true; } @@ -1092,7 +1138,7 @@ weof_dev(DEVICE *dev, int num) if (dev->fd < 0) { dev->dev_errno = EBADF; - Mmsg0(&dev->errmsg, _("Bad call to weof_dev. Archive drive not open\n")); + Mmsg0(dev->errmsg, _("Bad call to weof_dev. Archive drive not open\n")); Emsg0(M_FATAL, 0, dev->errmsg); return -1; } @@ -1110,10 +1156,11 @@ weof_dev(DEVICE *dev, int num) dev->file += num; dev->file_addr = 0; } else { + berrno be; clrerror_dev(dev, MTWEOF); if (stat == -1) { - Mmsg2(&dev->errmsg, _("ioctl MTWEOF error on %s. ERR=%s.\n"), - dev->dev_name, strerror(dev->dev_errno)); + Mmsg2(dev->errmsg, _("ioctl MTWEOF error on %s. ERR=%s.\n"), + dev->dev_name, be.strerror()); } } return stat; @@ -1122,7 +1169,7 @@ weof_dev(DEVICE *dev, int num) /* * Return string message with last error in English * Be careful not to call this routine from within dev.c - * while editing an Mmsg(&) or you will end up in a recursive + * while editing an Mmsg() or you will end up in a recursive * loop creating a Segmentation Violation. */ char * @@ -1139,7 +1186,8 @@ strerror_dev(DEVICE *dev) void clrerror_dev(DEVICE *dev, int func) { - char *msg = NULL; + const char *msg = NULL; + struct mtget mt_stat; dev->dev_errno = errno; /* save errno */ if (errno == EIO) { @@ -1190,6 +1238,9 @@ clrerror_dev(DEVICE *dev, int func) Emsg0(M_ERROR, 0, dev->errmsg); } } + /* On some systems such as NetBSD, this clears all errors */ + ioctl(dev->fd, MTIOCGET, (char *)&mt_stat); + /* Found on Linux */ #ifdef MTIOCLRERR { @@ -1212,6 +1263,18 @@ clrerror_dev(DEVICE *dev, int func) ioctl(dev->fd, MTIOCERRSTAT, (char *)&mt_errstat); } #endif + +/* Clear Subsystem Exception OSF1 */ +#ifdef MTCSE +{ + struct mtop mt_com; + mt_com.mt_op = MTCSE; + mt_com.mt_count = 1; + /* Clear any error condition on the tape */ + ioctl(dev->fd, MTIOCTOP, (char *)&mt_com); + Dmsg0(200, "Did MTCSE\n"); +} +#endif } /* @@ -1285,22 +1348,23 @@ void force_close_dev(DEVICE *dev) #endif } -int truncate_dev(DEVICE *dev) +bool truncate_dev(DEVICE *dev) { if (dev->state & ST_TAPE) { - return 1; + return true; /* we don't really truncate tapes */ + /* maybe we should rewind and write and eof ???? */ } if (ftruncate(dev->fd, 0) != 0) { Mmsg1(&dev->errmsg, _("Unable to truncate device. ERR=%s\n"), strerror(errno)); - return 0; + return false; } - return 1; + return true; } -int +bool dev_is_tape(DEVICE *dev) { - return (dev->state & ST_TAPE) ? 1 : 0; + return (dev->state & ST_TAPE) ? true : false; } @@ -1310,14 +1374,14 @@ dev_is_tape(DEVICE *dev) * if we still have a tape (perhaps not if at end of tape * and the job is canceled). */ -int +bool dev_can_write(DEVICE *dev) { if ((dev->state & ST_OPENED) && (dev->state & ST_APPEND) && (dev->state & ST_LABEL) && !(dev->state & ST_WEOT)) { - return 1; + return true; } else { - return 0; + return false; } } @@ -1370,50 +1434,17 @@ term_dev(DEVICE *dev) pthread_mutex_destroy(&dev->mutex); pthread_cond_destroy(&dev->wait); pthread_cond_destroy(&dev->wait_next_vol); + pthread_mutex_destroy(&dev->spool_mutex); + rwl_destroy(&dev->lock); + if (dev->attached_dcrs) { + delete dev->attached_dcrs; + dev->attached_dcrs = NULL; + } if (dev->state & ST_MALLOC) { free_pool_memory((POOLMEM *)dev); } } -/* - * We attach a jcr to the device so that when - * the Volume is full during writing, a - * JobMedia record will be created for this - * Job. - */ -void attach_jcr_to_device(DEVICE *dev, JCR *jcr) -{ - jcr->prev_dev = (JCR *)NULL; - jcr->next_dev = dev->attached_jcrs; - if (dev->attached_jcrs) { - dev->attached_jcrs->prev_dev = jcr; - } - dev->attached_jcrs = jcr; - Dmsg1(100, "Attached Job %s\n", jcr->Job); -} - -void detach_jcr_from_device(DEVICE *dev, JCR *jcr) -{ - if (!jcr->prev_dev) { - dev->attached_jcrs = jcr->next_dev; - } else { - jcr->prev_dev->next_dev = jcr->next_dev; - } - if (jcr->next_dev) { - jcr->next_dev->prev_dev = jcr->prev_dev; - } - jcr->next_dev = jcr->prev_dev = NULL; - Dmsg1(100, "Detached Job %s\n", jcr->Job); -} - -JCR *next_attached_jcr(DEVICE *dev, JCR *jcr) -{ - if (jcr == (JCR *)NULL) { - return dev->attached_jcrs; - } - return jcr->next_dev; -} - /* * This routine initializes the device wait timers */ @@ -1447,3 +1478,76 @@ bool double_dev_wait_time(DEVICE *dev) } return true; } + +void set_os_device_parameters(DEVICE *dev) +{ +#ifdef HAVE_LINUX_OS + struct mtop mt_com; + if (dev->min_block_size == dev->max_block_size && + dev->min_block_size == 0) { /* variable block mode */ + mt_com.mt_op = MTSETBLK; + mt_com.mt_count = 0; + if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) { + clrerror_dev(dev, MTSETBLK); + } + mt_com.mt_op = MTSETDRVBUFFER; + mt_com.mt_count = MT_ST_CLEARBOOLEANS; + if (!dev_cap(dev, CAP_TWOEOF)) { + mt_com.mt_count |= MT_ST_TWO_FM; + } + if (dev_cap(dev, CAP_EOM)) { + mt_com.mt_count |= MT_ST_FAST_MTEOM; + } + if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) { + clrerror_dev(dev, MTSETBLK); + } + } + return; +#endif + +#ifdef HAVE_NETBSD_OS + struct mtop mt_com; + if (dev->min_block_size == dev->max_block_size && + dev->min_block_size == 0) { /* variable block mode */ + mt_com.mt_op = MTSETBSIZ; + mt_com.mt_count = 0; + if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) { + clrerror_dev(dev, MTSETBSIZ); + } + /* Get notified at logical end of tape */ + mt_com.mt_op = MTEWARN; + mt_com.mt_count = 1; + if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) { + clrerror_dev(dev, MTEWARN); + } + } + return; +#endif + +#if HAVE_FREEBSD_OS || HAVE_OPENBSD_OS + struct mtop mt_com; + if (dev->min_block_size == dev->max_block_size && + dev->min_block_size == 0) { /* variable block mode */ + mt_com.mt_op = MTSETBSIZ; + mt_com.mt_count = 0; + if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) { + clrerror_dev(dev, MTSETBSIZ); + } + } + return; +#endif + +#ifdef HAVE_SUN_OS + struct mtop mt_com; + if (dev->min_block_size == dev->max_block_size && + dev->min_block_size == 0) { /* variable block mode */ + mt_com.mt_op = MTSRSZ; + mt_com.mt_count = 0; + if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) { + clrerror_dev(dev, MTSRSZ); + } + } + return; +#endif + +}