From fe192e90f49a6f0a3786c6ef45d3fea3d00d32b2 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Wed, 29 Jun 2005 14:24:41 +0000 Subject: [PATCH] - Attempt to fix DVD writing by eliminating a number of the DVD subroutines to simplify. - Modify DEVICE::open() to take dcr as first argument. This will permit providing more info to DVD opening. - Fix scanning for time/size items which in some cases ate the next line. - Eliminate read_dvd_volume_label(). New code (not yet written) *must* open dvd appropriately before calling read_dev_volume_label. - Modify open_first_part() open_next_part() to take DCR as argument. - Make label command from console work on DVDs. - Make mount command from console work on DVDs. Unmount does not work yet. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@2168 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/kernstodo | 5 + bacula/kes-1.37 | 17 +++ bacula/src/cats/make_postgresql_tables.in | 2 +- bacula/src/lib/edit.c | 18 +-- bacula/src/lib/lex.c | 3 +- bacula/src/lib/parse_conf.c | 18 +-- bacula/src/stored/acquire.c | 10 +- bacula/src/stored/append.c | 4 +- bacula/src/stored/askdir.c | 5 + bacula/src/stored/bcopy.c | 2 +- bacula/src/stored/block.c | 13 +- bacula/src/stored/btape.c | 4 +- bacula/src/stored/butil.c | 4 +- bacula/src/stored/dev.c | 74 +++++------ bacula/src/stored/dev.h | 3 +- bacula/src/stored/device.c | 8 +- bacula/src/stored/dircmd.c | 27 ++-- bacula/src/stored/dvd.c | 143 ++++++++++++---------- bacula/src/stored/label.c | 100 --------------- bacula/src/stored/mount.c | 4 - bacula/src/stored/protos.h | 8 +- bacula/src/stored/status.c | 7 +- bacula/src/stored/stored.c | 52 ++++---- bacula/src/stored/stored_conf.c | 12 +- bacula/src/version.h | 6 +- 25 files changed, 242 insertions(+), 307 deletions(-) diff --git a/bacula/kernstodo b/bacula/kernstodo index f740150790..2571adee1d 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -23,6 +23,8 @@ Autochangers: all Volumes from other drives. "update slots all-drives"? Document: +- Port limiting -m in iptables to prevent DoS attacks + could cause broken pipes on Bacula. - Document that Bootstrap files can be written with cataloging turned off. - Pruning with Admin job. @@ -49,6 +51,7 @@ Document: - Document the multiple-drive-changer.txt script. For 1.37: +- Cleaning tapes should have Status "Cleaning" rather than append. - Refuse to prune last valid Full backup. Same goes for Catalog. - Why is SpoolDirectory = /home/bacula/spool; not reported as an error when writing a DVD? @@ -73,6 +76,8 @@ For 1.37: - Add global lock on all devices when creating a device structure. Maybe in 1.37: +- In restore don't compare byte count on a raw device -- directory + entry does not contain bytes. - To mark files as deleted, run essentially a Verify to disk, and when a file is found missing (MarkId != JobId), then create a new File record with FileIndex == -1. This could be done diff --git a/bacula/kes-1.37 b/bacula/kes-1.37 index 0ec0c7c862..5afe0f8e15 100644 --- a/bacula/kes-1.37 +++ b/bacula/kes-1.37 @@ -3,6 +3,23 @@ General: +Changes to 1.37.28: +29Jun05 +- Attempt to fix DVD writing by eliminating a number of the + DVD subroutines to simplify. +- Modify DEVICE::open() to take dcr as first argument. This + will permit providing more info to DVD opening. +- Fix scanning for time/size items which in some cases + ate the next line. +- Eliminate read_dvd_volume_label(). New code (not yet written) + *must* open dvd appropriately before calling + read_dev_volume_label. +- Modify open_first_part() open_next_part() to take DCR as + argument. +- Make label command from console work on DVDs. +- Make mount command from console work on DVDs. + Unmount does not work yet. + Changes to 1.37.27: 27Jun05 - Add Database vendor to CatalogRes tuple for Python. diff --git a/bacula/src/cats/make_postgresql_tables.in b/bacula/src/cats/make_postgresql_tables.in index d1a6ad14df..4c6e9cf0d3 100644 --- a/bacula/src/cats/make_postgresql_tables.in +++ b/bacula/src/cats/make_postgresql_tables.in @@ -129,7 +129,7 @@ CREATE TABLE media volstatus text not null check (volstatus in ('Full','Archive','Append', 'Recycle','Purged','Read-Only','Disabled', - 'Error','Busy','Used','Cleaning',"Scratch')), + 'Error','Busy','Used','Cleaning','Scratch')), recycle smallint not null default 0, volretention bigint not null default 0, voluseduration bigint not null default 0, diff --git a/bacula/src/lib/edit.c b/bacula/src/lib/edit.c index c579569b37..c275a13986 100644 --- a/bacula/src/lib/edit.c +++ b/bacula/src/lib/edit.c @@ -5,24 +5,18 @@ * * Version $Id$ */ - /* - Copyright (C) 2000-2005 Kern Sibbald + Copyright (C) 2002-2005 Kern Sibbald This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. + modify it under the terms of the GNU General Public License + version 2 as ammended with additional clauses defined in the + file LICENSE in the main source directory. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public - License along with this program; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + the file LICENSE for additional details. */ diff --git a/bacula/src/lib/lex.c b/bacula/src/lib/lex.c index 1adec6015d..fdeb700ec4 100644 --- a/bacula/src/lib/lex.c +++ b/bacula/src/lib/lex.c @@ -145,7 +145,7 @@ LEX *lex_open_file(LEX *lf, const char *filename, LEX_ERROR_HANDLER *scan_error) if ((fd = fopen(fname, "r")) == NULL) { return NULL; } - Dmsg1(2000, "Open config file: %s\n", fname); + Dmsg1(400, "Open config file: %s\n", fname); nf = (LEX *)malloc(sizeof(LEX)); if (lf) { memcpy(nf, lf, sizeof(LEX)); @@ -190,6 +190,7 @@ int lex_get_char(LEX *lf) } lf->line_no++; lf->col_no = 0; + Dmsg2(400, "fget line=%d %s", lf->line_no, lf->line); } lf->ch = (uint8_t)lf->line[lf->col_no]; if (lf->ch == 0) { diff --git a/bacula/src/lib/parse_conf.c b/bacula/src/lib/parse_conf.c index 41177e1047..2747dd7026 100755 --- a/bacula/src/lib/parse_conf.c +++ b/bacula/src/lib/parse_conf.c @@ -185,6 +185,7 @@ void init_resource(int type, RES_ITEM *items, int pass) res_all.hdr.rcode = type; res_all.hdr.refcnt = 1; + /* Set defaults in each item */ for (i=0; items[i].name; i++) { Dmsg3(900, "Item=%s def=%s defval=%d\n", items[i].name, (items[i].flags & ITEM_DEFAULT) ? "yes" : "no", @@ -568,17 +569,6 @@ void store_defs(LEX *lc, RES_ITEM *item, int index, int pass) scan_err3(lc, _("Missing config Resource \"%s\" referenced on line %d : %s\n"), lc->str, lc->line_no, lc->line); } - /* for each item not set, we copy the field from res */ -#ifdef xxx - for (int i=0; item->name;; i++, item++) { - if (bit_is_set(i, res->item_present)) { - Dmsg2(900, "Item %d is present in %s\n", i, res->name); - } else { - Dmsg2(900, "Item %d is not present in %s\n", i, res->name); - } - } - /* ***FIXME **** add code */ -#endif } scan_to_eol(lc); } @@ -647,7 +637,9 @@ void store_size(LEX *lc, RES_ITEM *item, int index, int pass) scan_err1(lc, _("expected a size, got: %s"), lc->str); break; } - scan_to_eol(lc); + if (token != T_EOL) { + scan_to_eol(lc); + } set_bit(index, res_all.hdr.item_present); Dmsg0(900, "Leave store_size\n"); } @@ -826,7 +818,7 @@ parse_config(const char *cf, LEX_ERROR_HANDLER *scan_error) return 0; } } - Dmsg1(900, "calling handler for %s\n", items[i].name); + Dmsg1(800, "calling handler for %s\n", items[i].name); /* Call item handler */ items[i].handler(lc, &items[i], i, pass); i = -1; diff --git a/bacula/src/stored/acquire.c b/bacula/src/stored/acquire.c index fea9842ebb..7268ab7aaf 100644 --- a/bacula/src/stored/acquire.c +++ b/bacula/src/stored/acquire.c @@ -175,8 +175,6 @@ DCR *acquire_device_for_read(DCR *dcr) Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg); } - dev->num_parts = dcr->VolCatInfo.VolCatParts; - for (i=0; i<5; i++) { dev->clear_labeled(); /* force reread of label */ if (job_canceled(jcr)) { @@ -190,7 +188,7 @@ DCR *acquire_device_for_read(DCR *dcr) */ for ( ; !dev->is_open(); ) { Dmsg1(120, "bstored: open vol=%s\n", dcr->VolumeName); - if (dev->open(dcr->VolumeName, OPEN_READ_ONLY) < 0) { + if (dev->open(dcr, OPEN_READ_ONLY) < 0) { if (dev->dev_errno == EIO) { /* no tape loaded */ Jmsg3(jcr, M_WARNING, 0, _("Open device %s Volume \"%s\" failed: ERR=%s\n"), dev->print_name(), dcr->VolumeName, strerror_dev(dev)); @@ -211,11 +209,7 @@ DCR *acquire_device_for_read(DCR *dcr) Dmsg1(129, "opened dev %s OK\n", dev->print_name()); } - if (dev->is_dvd()) { - vol_label_status = read_dvd_volume_label(dcr, /*read*/false); - } else { - vol_label_status = read_dev_volume_label(dcr); - } + vol_label_status = read_dev_volume_label(dcr); Dmsg0(200, "calling read-vol-label\n"); switch (vol_label_status) { diff --git a/bacula/src/stored/append.c b/bacula/src/stored/append.c index 284e9fa718..2415c9c02a 100644 --- a/bacula/src/stored/append.c +++ b/bacula/src/stored/append.c @@ -229,9 +229,9 @@ bool do_append_data(JCR *jcr) jcr->dir_bsock->spool = false; } } - Dmsg0(350, "Enter bnet_get\n"); + Dmsg0(650, "Enter bnet_get\n"); } - Dmsg1(350, "End read loop with FD. Stat=%d\n", n); + Dmsg1(650, "End read loop with FD. Stat=%d\n", n); if (is_bnet_error(ds)) { Dmsg1(350, "Network read error from FD. ERR=%s\n", bnet_strerror(ds)); Jmsg1(jcr, M_FATAL, 0, _("Network error on data channel. ERR=%s\n"), diff --git a/bacula/src/stored/askdir.c b/bacula/src/stored/askdir.c index 3d718dc216..0fa4699c76 100644 --- a/bacula/src/stored/askdir.c +++ b/bacula/src/stored/askdir.c @@ -183,6 +183,11 @@ static bool do_get_volume_info(DCR *dcr) bstrncpy(dcr->VolumeName, vol.VolCatName, sizeof(dcr->VolumeName)); memcpy(&dcr->VolCatInfo, &vol, sizeof(dcr->VolCatInfo)); + /* ***FIXME*** we really should not do this but must for the moment */ + if (dcr->dev->num_parts < dcr->VolCatInfo.VolCatParts) { + dcr->dev->num_parts = dcr->VolCatInfo.VolCatParts; + } + Dmsg2(300, "do_reqest_vol_info got slot=%d Volume=%s\n", vol.Slot, vol.VolCatName); return true; diff --git a/bacula/src/stored/bcopy.c b/bacula/src/stored/bcopy.c index a77431ac06..1897cf6dc6 100644 --- a/bacula/src/stored/bcopy.c +++ b/bacula/src/stored/bcopy.c @@ -164,7 +164,7 @@ int main (int argc, char *argv[]) } /* For we must now acquire the device for writing */ lock_device(out_dev); - if (out_dev->open(out_jcr->dcr->VolumeName, OPEN_READ_WRITE) < 0) { + if (out_dev->open(out_jcr->dcr, OPEN_READ_WRITE) < 0) { Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), out_dev->errmsg); unlock_device(out_dev); exit(1); diff --git a/bacula/src/stored/block.c b/bacula/src/stored/block.c index e9528d43e3..3e97f73c7d 100644 --- a/bacula/src/stored/block.c +++ b/bacula/src/stored/block.c @@ -690,7 +690,7 @@ static bool terminate_writing_volume(DCR *dcr) dev->VolCatInfo.VolCatJobs++; /* increment number of jobs */ if (dev->is_dvd()) { /* Write the current (and last) part. */ - open_next_part(dev); + open_next_part(dcr); } if (!dir_update_volume_info(dcr, false)) { @@ -783,13 +783,14 @@ static bool do_dvd_size_checks(DCR *dcr) if (!(dev->is_tape() || dev->is_fifo()) && dev->max_part_size > 0 && (dev->part_size + block->binbuf) >= dev->max_part_size) { if (dev->part < dev->num_parts) { - Jmsg3(dcr->jcr, M_FATAL, 0, _("Error while writing, current part number is less than the total number of parts (%d/%d, device=%s)\n"), + Jmsg3(dcr->jcr, M_FATAL, 0, _("Error while writing, current part number" + " is less than the total number of parts (%d/%d, device=%s)\n"), dev->part, dev->num_parts, dev->print_name()); dev->dev_errno = EIO; return false; } - if (open_next_part(dev) < 0) { + if (open_next_part(dcr) < 0) { Jmsg2(dcr->jcr, M_FATAL, 0, _("Unable to open device next part %s: ERR=%s\n"), dev->print_name(), strerror_dev(dev)); dev->dev_errno = EIO; @@ -889,12 +890,14 @@ reread: Dmsg1(200, "dev->part_size=%u\n", (unsigned int)dev->part_size); Dmsg1(200, "dev->part=%u\n", (unsigned int)dev->part); Dmsg1(200, "dev->VolCatInfo.VolCatParts=%u\n", (unsigned int)dev->VolCatInfo.VolCatParts); - Dmsg3(200, "Tests : %d %d %d\n", (dev->VolCatInfo.VolCatParts > 0), ((dev->file_size-dev->part_start) == dev->part_size), (dev->part <= dev->VolCatInfo.VolCatParts));*/ + Dmsg3(200, "Tests : %d %d %d\n", (dev->VolCatInfo.VolCatParts > 0), + ((dev->file_size-dev->part_start) == dev->part_size), + (dev->part <= dev->VolCatInfo.VolCatParts));*/ /* Check for part file end */ if ((dev->num_parts > 0) && ((dev->file_size-dev->part_start) == dev->part_size) && (dev->part < dev->num_parts)) { - if (open_next_part(dev) < 0) { + if (open_next_part(dcr) < 0) { Jmsg2(dcr->jcr, M_FATAL, 0, _("Unable to open device next part %s: ERR=%s\n"), dev->print_name(), strerror_dev(dev)); dev->dev_errno = EIO; diff --git a/bacula/src/stored/btape.c b/bacula/src/stored/btape.c index b5273ece47..371842635a 100644 --- a/bacula/src/stored/btape.c +++ b/bacula/src/stored/btape.c @@ -326,7 +326,7 @@ static bool open_the_device() lock_device(dev); if (!dev->is_open()) { Dmsg1(200, "Opening device %s\n", dcr->VolumeName); - if (dev->open(dcr->VolumeName, OPEN_READ_WRITE) < 0) { + if (dev->open(dcr, OPEN_READ_WRITE) < 0) { Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), dev->errmsg); unlock_device(dev); free_block(block); @@ -360,7 +360,7 @@ static void labelcmd() } if (!dev->is_open()) { - if (!first_open_device(dev)) { + if (!first_open_device(dcr)) { Pmsg1(0, "Device open failed. ERR=%s\n", strerror_dev(dev)); } } diff --git a/bacula/src/stored/butil.c b/bacula/src/stored/butil.c index c4cda7c9d2..cff36d3d03 100644 --- a/bacula/src/stored/butil.c +++ b/bacula/src/stored/butil.c @@ -170,8 +170,8 @@ static DCR *setup_to_access_device(JCR *jcr, char *dev_name, return NULL; } } else { - if (!first_open_device(dev)) { - Jmsg1(jcr, M_FATAL, 0, _("Cannot open %s\n"), dcr->dev_name); + if (!first_open_device(dcr)) { + Jmsg1(jcr, M_FATAL, 0, _("Cannot open %s\n"), dev->print_name()); return NULL; } } diff --git a/bacula/src/stored/dev.c b/bacula/src/stored/dev.c index c3f5bfb50e..b084a94541 100644 --- a/bacula/src/stored/dev.c +++ b/bacula/src/stored/dev.c @@ -80,16 +80,15 @@ #endif /* Functions in dvd.c */ -void get_filename(DEVICE *dev, char *VolName, POOL_MEM& archive_name); void update_free_space_dev(DEVICE* dev); /* Forward referenced functions */ void set_os_device_parameters(DEVICE *dev); static bool dev_get_os_pos(DEVICE *dev, struct mtget *mt_stat); -static void open_tape_device(DEVICE *dev, int mode); -static void open_file_device(DEVICE *dev, int mode); -static void open_dvd_device(DEVICE *dev, int mode); +static void open_tape_device(DCR *dcr, int mode); +static void open_file_device(DCR *dcr, int mode); +static void open_dvd_device(DCR *dcr, int mode); /* * Allocate and initialize the DEVICE structure @@ -129,7 +128,8 @@ init_dev(JCR *jcr, DEVRES *device) } else if (S_ISFIFO(statp.st_mode)) { fifo = true; } else if (!(device->cap_bits & CAP_REQMOUNT)) { - Jmsg2(jcr, M_ERROR, 0, _("%s is an unknown device type. Must be tape or directory. st_mode=%x\n"), + Jmsg2(jcr, M_ERROR, 0, _("%s is an unknown device type. Must be tape or directory\n" + " or have RequiresMount=yes for DVD. st_mode=%x\n"), device->device_name, statp.st_mode); return NULL; } @@ -264,7 +264,7 @@ init_dev(JCR *jcr, DEVRES *device) * (archive_name) with the VolName concatenated. */ int -DEVICE::open(char *VolName, int mode) +DEVICE::open(DCR *dcr, int mode) { if (is_open()) { if (openmode == mode) { @@ -273,24 +273,20 @@ DEVICE::open(char *VolName, int mode) ::close(fd); /* use system close so correct mode will be used on open */ } } - if (VolName) { - bstrncpy(VolCatInfo.VolCatName, VolName, sizeof(VolCatInfo.VolCatName)); - } else { - VolCatInfo.VolCatName[0] = 0; - } + bstrncpy(VolCatInfo.VolCatName, dcr->VolumeName, sizeof(VolCatInfo.VolCatName)); Dmsg4(29, "open dev: tape=%d dev_name=%s vol=%s mode=%d\n", is_tape(), dev_name, VolCatInfo.VolCatName, mode); state &= ~(ST_LABEL|ST_APPEND|ST_READ|ST_EOT|ST_WEOT|ST_EOF); label_type = B_BACULA_LABEL; if (is_tape() || is_fifo()) { - open_tape_device(this, mode); + open_tape_device(dcr, mode); } else if (is_dvd()) { Dmsg1(100, "call open_dvd_device mode=%d\n", mode); - open_dvd_device(this, mode); + open_dvd_device(dcr, mode); } else { Dmsg1(100, "call open_file_device mode=%d\n", mode); - open_file_device(this, mode); + open_file_device(dcr, mode); } return fd; } @@ -319,8 +315,9 @@ void DEVICE::set_mode(int new_mode) } } -static void open_tape_device(DEVICE *dev, int mode) +static void open_tape_device(DCR *dcr, int mode) { + DEVICE *dev = dcr->dev; int nonblocking = 0;; dev->file_size = 0; int timeout; @@ -399,8 +396,9 @@ open_again: /* * Open a file device */ -static void open_file_device(DEVICE *dev, int mode) +static void open_file_device(DCR *dcr, int mode) { + DEVICE *dev = dcr->dev; POOL_MEM archive_name(PM_FNAME); /* @@ -416,8 +414,11 @@ static void open_file_device(DEVICE *dev, int mode) return; } - Dmsg1(100, "Call get_filename. Vol=%s\n", dev->VolCatInfo.VolCatName); - get_filename(dev, dev->VolCatInfo.VolCatName, archive_name); + pm_strcpy(archive_name, dev->dev_name); + if (archive_name.c_str()[strlen(archive_name.c_str())-1] != '/') { + pm_strcat(archive_name, "/"); + } + pm_strcat(archive_name, dev->VolCatInfo.VolCatName); Dmsg3(29, "open dev: %s dev=%s mode=%d\n", dev->is_dvd()?"DVD":"disk", archive_name.c_str(), mode); @@ -445,10 +446,13 @@ static void open_file_device(DEVICE *dev, int mode) } /* - * Open a DVD device + * Open a DVD device. N.B. at this point, dev->VolCatInfo.VolCatName + * has the desired Volume name, but there is NO assurance that + * any other field of VolCatInfo is correct. */ -static void open_dvd_device(DEVICE *dev, int mode) +static void open_dvd_device(DCR *dcr, int mode) { + DEVICE *dev = dcr->dev; POOL_MEM archive_name(PM_FNAME); struct stat filestat; @@ -470,14 +474,8 @@ static void open_dvd_device(DEVICE *dev, int mode) } dev->part_size = 0; - /* if num_parts has not been set, but VolCatInfo is available, copy - * it from the VolCatInfo.VolCatParts */ - if (dev->num_parts < dev->VolCatInfo.VolCatParts) { - dev->num_parts = dev->VolCatInfo.VolCatParts; - } - - Dmsg1(100, "Call get_filename. Vol=%s\n", dev->VolCatInfo.VolCatName); - get_filename(dev, dev->VolCatInfo.VolCatName, archive_name); + Dmsg1(100, "Call make_dvd_filename. Vol=%s\n", dev->VolCatInfo.VolCatName); + make_dvd_filename(dev, archive_name); if (mount_dev(dev, 1) < 0) { Mmsg(dev->errmsg, _("Could not mount device %s.\n"), @@ -1590,8 +1588,8 @@ static void do_close(DEVICE *dev) struct stat statp; POOL_MEM archive_name(PM_FNAME); dev->part = dev->num_parts; - Dmsg1(100, "Call get_filename. Vol=%s\n", dev->VolCatInfo.VolCatName); - get_filename(dev, dev->VolCatInfo.VolCatName, archive_name); + Dmsg1(100, "Call make_dvd_filename. Vol=%s\n", dev->VolCatInfo.VolCatName); + make_dvd_filename(dev, archive_name); /* Check that the part file is empty */ if ((stat(archive_name.c_str(), &statp) == 0) && (statp.st_size == 0)) { Dmsg1(100, "unlink(%s)\n", archive_name.c_str()); @@ -1649,19 +1647,15 @@ bool truncate_dev(DEVICE *dev) /* maybe we should rewind and write and eof ???? */ } - /* If there is more than one part, open the first one, and then truncate it. */ - if (dev->num_parts > 0) { - dev->num_parts = 0; - dev->VolCatInfo.VolCatParts = 0; - if (open_first_part(dev, OPEN_READ_WRITE) < 0) { - berrno be; - Mmsg1(dev->errmsg, "Unable to truncate device, because I'm unable to open the first part. ERR=%s\n", be.strerror()); - } + if (dev->is_dvd()) { + Mmsg1(dev->errmsg, _("Truncate DVD %s not supported.\n"), dev->print_name()); + return false; /* we cannot truncate DVDs */ } if (ftruncate(dev->fd, 0) != 0) { berrno be; - Mmsg1(dev->errmsg, _("Unable to truncate device. ERR=%s\n"), be.strerror()); + Mmsg2(dev->errmsg, _("Unable to truncate device %s. ERR=%s\n"), + dev->print_name(), be.strerror()); return false; } return true; @@ -1703,8 +1697,8 @@ term_dev(DEVICE *dev) Emsg0(M_FATAL, 0, dev->errmsg); return; } + Dmsg1(29, "term_dev: %s\n", dev->print_name()); do_close(dev); - Dmsg0(29, "term_dev\n"); if (dev->dev_name) { free_memory(dev->dev_name); dev->dev_name = NULL; diff --git a/bacula/src/stored/dev.h b/bacula/src/stored/dev.h index b9380f2a72..9f1114842b 100644 --- a/bacula/src/stored/dev.h +++ b/bacula/src/stored/dev.h @@ -164,6 +164,7 @@ struct DEVRES; /* Device resource defined in stored_conf. int weof_dev(DEVICE *dev, int num); bool rewind_dev(DEVICE *dev); +class DCR; /* forward reference */ /* * Device structure definition. There is one of these for * each physical device. Everything here is "global" to @@ -317,7 +318,7 @@ public: void block(int why); /* in dev.c */ void unblock(); /* in dev.c */ void close(); /* in dev.c */ - int open(char *VolName, int mode); /* in dev.c */ + int open(DCR *dcr, int mode); /* in dev.c */ void set_mode(int mode); /* in dev.c */ void set_blocked(int block) { dev_blocked = block; }; diff --git a/bacula/src/stored/device.c b/bacula/src/stored/device.c index 22ac2e88f2..f5d53743c5 100644 --- a/bacula/src/stored/device.c +++ b/bacula/src/stored/device.c @@ -243,8 +243,10 @@ void set_new_file_parameters(DCR *dcr) * Returns: false on failure * true on success */ -bool first_open_device(DEVICE *dev) +bool first_open_device(DCR *dcr) { + DEVICE *dev = dcr->dev; + Dmsg0(120, "start open_output_device()\n"); if (!dev) { return false; @@ -267,7 +269,7 @@ bool first_open_device(DEVICE *dev) } Dmsg0(129, "Opening device.\n"); dev->open_nowait = true; - if (dev->open(NULL, mode) < 0) { + if (dev->open(dcr, mode) < 0) { Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), dev->errmsg); dev->open_nowait = false; unlock_device(dev); @@ -292,7 +294,7 @@ bool open_device(DCR *dcr) } else { mode = OPEN_READ_WRITE; } - if (dev->open(dcr->VolCatInfo.VolCatName, mode) < 0) { + if (dev->open(dcr, mode) < 0) { /* If polling, ignore the error */ if (!dev->poll) { Jmsg2(dcr->jcr, M_FATAL, 0, _("Unable to open device %s: ERR=%s\n"), diff --git a/bacula/src/stored/dircmd.c b/bacula/src/stored/dircmd.c index 1ac5062c16..d876eff448 100644 --- a/bacula/src/stored/dircmd.c +++ b/bacula/src/stored/dircmd.c @@ -281,7 +281,7 @@ static bool cancel_cmd(JCR *cjcr) } /* - * Label a tape + * Label a Volume * */ static bool label_cmd(JCR *jcr) @@ -374,16 +374,13 @@ static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname, dcr->dev = dev; steal_device_lock(dev, &hold, BST_WRITING_LABEL); + /* Note, try_autoload_device() opens the device */ if (!try_autoload_device(jcr, slot, newname)) { goto bail_out; /* error */ } /* See what we have for a Volume */ - if (dev->is_dvd()) { - label_status = read_dvd_volume_label(dcr, /*write*/true); - } else { - label_status = read_dev_volume_label(dcr); - } + label_status = read_dev_volume_label(dcr); switch(label_status) { case VOL_NAME_ERROR: @@ -607,11 +604,7 @@ static bool mount_cmd(JCR *jcr) "If this is not a blank tape, try unmounting and remounting the Volume.\n"), dev->print_name()); } - } else { - if (!dev->is_tape()) { - /* Nothing to do */ - break; - } + } else if (dev->is_tape()) { if (dev->open(NULL, OPEN_READ_WRITE) < 0) { bnet_fsend(dir, _("3901 open device failed: ERR=%s\n"), strerror_dev(dev)); @@ -626,6 +619,16 @@ static bool mount_cmd(JCR *jcr) "If this is not a blank tape, try unmounting and remounting the Volume.\n"), dev->print_name()); } + } else if (dev->is_dvd()) { + if (mount_dev(dev, 1)) { + bnet_fsend(dir, _("3002 Device %s is mounted.\n"), + dev->print_name()); + } else { + bnet_fsend(dir, "3907 %s", strerror_dev(dev)); + } + } else { /* must be file */ + bnet_fsend(dir, _("3906 File device %s is always mounted.\n"), + dev->print_name()); } break; @@ -908,7 +911,7 @@ static bool try_autoload_device(JCR *jcr, int slot, const char *VolName) /* Ensure that the device is open -- autoload_device() closes it */ for ( ; !dev->is_open(); ) { - if (dev->open(dcr->VolumeName, OPEN_READ_WRITE) < 0) { + if (dev->open(dcr, OPEN_READ_WRITE) < 0) { bnet_fsend(dir, _("3910 Unable to open device %s: ERR=%s\n"), dev->print_name(), dev->strerror()); return false; diff --git a/bacula/src/stored/dvd.c b/bacula/src/stored/dvd.c index 466bf0716b..c5ee187d9b 100644 --- a/bacula/src/stored/dvd.c +++ b/bacula/src/stored/dvd.c @@ -30,47 +30,42 @@ static char *edit_device_codes_dev(DEVICE *dev, char *omsg, const char *imsg); static bool do_mount_dev(DEVICE* dev, int mount, int dotimeout); static int dvd_write_part(DEVICE *dev); - /* * Write the current volume/part filename to archive_name. */ -void get_filename(DEVICE *dev, char *VolumeName, POOL_MEM& archive_name) +void make_dvd_filename(DEVICE *dev, POOL_MEM &archive_name) { char partnumber[20]; - if (dev->is_dvd()) { - /* If we try to open the last part, just open it from disk, - * otherwise, open it from the spooling directory. - */ - Dmsg2(100, "DVD part=%d num_parts=%d\n", dev->part, dev->num_parts); - if (dev->num_parts == 0 || dev->part < dev->num_parts) { - Dmsg1(100, "Arch = mount point: %s\n", dev->device->mount_point); - pm_strcpy(archive_name, dev->device->mount_point); + /* + * If we try to open the last part, just open it from disk, + * otherwise, open it from the spooling directory. + */ + Dmsg2(100, "DVD part=%d num_parts=%d\n", dev->part, dev->num_parts); + if (dev->part < dev->num_parts) { + Dmsg1(100, "Arch = mount point: %s\n", dev->device->mount_point); + pm_strcpy(archive_name, dev->device->mount_point); + } else { + /* Use the working directory if spool directory is not defined */ + if (dev->device->spool_directory) { + pm_strcpy(archive_name, dev->device->spool_directory); } else { - /* Use the working directory if spool directory is not defined */ - if (dev->device->spool_directory) { - Dmsg1(100, "Arch = spool: %s\n", dev->device->spool_directory); - pm_strcpy(archive_name, dev->device->spool_directory); - } else { - Dmsg1(100, "Arch = working: %s\n", working_directory); - pm_strcpy(archive_name, working_directory); - } + pm_strcpy(archive_name, working_directory); } - } else { - pm_strcpy(archive_name, dev->dev_name); } if (archive_name.c_str()[strlen(archive_name.c_str())-1] != '/') { pm_strcat(archive_name, "/"); } - pm_strcat(archive_name, VolumeName); + + pm_strcat(archive_name, dev->VolCatInfo.VolCatName); /* if part != 0, append .# to the filename (where # is the part number) */ - if (dev->is_dvd() && dev->part != 0) { + if (dev->part != 0) { pm_strcat(archive_name, "."); bsnprintf(partnumber, sizeof(partnumber), "%d", dev->part); pm_strcat(archive_name, partnumber); } - Dmsg1(100, "Exit get_filename: arch=%s\n", archive_name.c_str()); + Dmsg1(100, "Exit make_dvd_filename: arch=%s\n", archive_name.c_str()); } /* Mount the device. @@ -170,7 +165,7 @@ get_out: * opened. * Maybe it should open the first part. ***FIXME*** * - * false if an error occured, and read_dvd_volume_label + * false if an error occured, and read_dev_volume_label * must abort with an IO_ERROR. * * To find the Volume name, it lists all the files on the DVD, @@ -185,8 +180,17 @@ get_out: * It is useful, so the operator can be told that a wrong volume is mounted, with * the label name of the current volume. We can also check that the currently * mounted disk is writable. (See also read_dev_volume_label_guess in label.c). + + If we are writing, then there is no need to guess. We should just + check that the Volume does not already exist. + + If we are reading, I don't see the reason to guess since we + know what Volume we want. The file either exists or does not + exist. + * */ +#ifdef xxx bool can_open_mounted_dev(DEVICE *dev) { Dmsg1(29, "Enter: dev=%s\n", dev->dev_name); @@ -325,6 +329,7 @@ bool can_open_mounted_dev(DEVICE *dev) return true; } +#endif /* Update the free space on the device */ @@ -423,15 +428,17 @@ static int dvd_write_part(DEVICE *dev) status = run_program_full_output(ocmd.c_str(), timeout, results); if (status != 0) { - Mmsg1(dev->errmsg, "Error while writing current part to the DVD: %s", results); + Mmsg1(dev->errmsg, "Error while writing current part to the DVD: %s", + results); + Dmsg1(000, "%s", dev->errmsg); dev->dev_errno = EIO; free_pool_memory(results); return -1; } else { - Dmsg1(29, "dvd_write_part: command output=%s\n", results); + Dmsg1(10, "dvd_write_part: command output=%s\n", results); POOL_MEM archive_name(PM_FNAME); Dmsg1(100, "Call get_filename. Vol=%s\n", dev->VolCatInfo.VolCatName); - get_filename(dev, dev->VolCatInfo.VolCatName, archive_name); + make_dvd_filename(dev, archive_name); unlink(archive_name.c_str()); free_pool_memory(results); return 0; @@ -443,8 +450,9 @@ static int dvd_write_part(DEVICE *dev) * - Increment part number * - Reopen the device */ -int open_next_part(DEVICE *dev) +int open_next_part(DCR *dcr) { + DEVICE *dev = dcr->dev; Dmsg3(29, "Enter: open_next_part %s %s %d\n", dev->dev_name, dev->VolCatInfo.VolCatName, dev->openmode); @@ -462,6 +470,10 @@ int open_next_part(DEVICE *dev) dev->fd = -1; dev->clear_opened(); + /* + * If we have a part open for write, then write it to + * DVD before opening the next part. + */ if (dev->is_dvd() && (dev->part == dev->num_parts) && dev->can_append()) { if (dvd_write_part(dev) < 0) { return -1; @@ -472,47 +484,45 @@ int open_next_part(DEVICE *dev) dev->part++; if ((dev->num_parts < dev->part) && dev->can_append()) { - dev->num_parts = dev->part; - - /* Check that the next part file does not exists. - * If it does, move it away... */ POOL_MEM archive_name(PM_FNAME); - POOL_MEM archive_bkp_name(PM_FNAME); struct stat buf; + + /* + * First check what is on DVD. If out part is there, we + * are in trouble, so bail out. + */ + make_dvd_filename(dev, archive_name); /* makes dvd name */ + if (stat(archive_name.c_str(), &buf) == 0) { + /* bad new bail out */ + Mmsg1(&dev->errmsg, _("Next Volume part already exists on DVD. Cannot continue: %s\n"), + archive_name.c_str()); + return -1; + } + + dev->num_parts = dev->part; + make_dvd_filename(dev, archive_name); /* makes spool name */ - Dmsg1(100, "Call get_filename. Vol=%s\n", dev->VolCatInfo.VolCatName); - get_filename(dev, dev->VolCatInfo.VolCatName, archive_name); - - /* Check if the next part exists. */ + /* Check if the next part exists in spool directory . */ if ((stat(archive_name.c_str(), &buf) == 0) || (errno != ENOENT)) { Dmsg1(29, "open_next_part %s is in the way, moving it away...\n", archive_name.c_str()); - pm_strcpy(archive_bkp_name, archive_name.c_str()); - pm_strcat(archive_bkp_name, ".bak"); - unlink(archive_bkp_name.c_str()); - - /* First try to rename it */ - if (rename(archive_name.c_str(), archive_bkp_name.c_str()) < 0) { + /* Then try to unlink it */ + if (unlink(archive_name.c_str()) < 0) { berrno be; - Dmsg3(29, "open_next_part can't rename %s to %s, ERR=%s\n", - archive_name.c_str(), archive_bkp_name.c_str(), be.strerror()); - /* Then try to unlink it */ - if (unlink(archive_name.c_str()) < 0) { - berrno be; - dev->dev_errno = errno; - Mmsg2(&dev->errmsg, _("open_next_part can't unlink existing part %s, ERR=%s\n"), - archive_name.c_str(), be.strerror()); - Emsg0(M_FATAL, 0, dev->errmsg); - return -1; - } + dev->dev_errno = errno; + Mmsg2(dev->errmsg, _("open_next_part can't unlink existing part %s, ERR=%s\n"), + archive_name.c_str(), be.strerror()); + return -1; } } } Dmsg2(50, "Call dev->open(vol=%s, mode=%d", dev->VolCatInfo.VolCatName, dev->openmode); - if (dev->open(dev->VolCatInfo.VolCatName, dev->openmode) < 0) { + /* Open next part */ + if (dev->open(dcr, dev->openmode) < 0) { return -1; } + dev->set_labeled(); /* all next parts are "labeled" */ return dev->fd; } @@ -520,8 +530,9 @@ int open_next_part(DEVICE *dev) * - Close the fd * - Reopen the device */ -int open_first_part(DEVICE *dev, int mode) +int open_first_part(DCR *dcr, int mode) { + DEVICE *dev = dcr->dev; Dmsg3(29, "Enter: open_first_part dev=%s Vol=%s mode=%d\n", dev->dev_name, dev->VolCatInfo.VolCatName, dev->openmode); if (dev->fd >= 0) { @@ -533,9 +544,9 @@ int open_first_part(DEVICE *dev, int mode) dev->part_start = 0; dev->part = 0; - Dmsg2(50, "Call dev->open(vol=%s, mode=%d)\n", dev->VolCatInfo.VolCatName, + Dmsg2(50, "Call dev->open(vol=%s, mode=%d)\n", dcr->VolCatInfo.VolCatName, mode); - if (dev->open(dev->VolCatInfo.VolCatName, mode) < 0) { + if (dev->open(dcr, mode) < 0) { Dmsg0(50, "open dev() failed\n"); return -1; } @@ -548,11 +559,13 @@ int open_first_part(DEVICE *dev, int mode) off_t lseek_dev(DEVICE *dev, off_t offset, int whence) { int pos, openmode; + DCR *dcr; if (dev->num_parts == 0) { /* If there is only one part, simply call lseek. */ return lseek(dev->fd, offset, whence); } + dcr = (DCR *)dev->attached_dcrs->first(); /* any dcr will do */ switch(whence) { case SEEK_SET: Dmsg1(100, "lseek_dev SEEK_SET called %d\n", offset); @@ -566,7 +579,7 @@ off_t lseek_dev(DEVICE *dev, off_t offset, int whence) } } else { /* Load next part, and start again */ - if (open_next_part(dev) < 0) { + if (open_next_part(dcr) < 0) { Dmsg0(100, "lseek_dev failed while trying to open the next part\n"); return -1; } @@ -577,7 +590,7 @@ off_t lseek_dev(DEVICE *dev, off_t offset, int whence) * We need to access a previous part, * so just load the first one, and seek again * until the right one is loaded */ - if (open_first_part(dev, dev->openmode) < 0) { + if (open_first_part(dcr, dev->openmode) < 0) { Dmsg0(100, "lseek_dev failed while trying to open the first part\n"); return -1; } @@ -618,18 +631,18 @@ off_t lseek_dev(DEVICE *dev, off_t offset, int whence) openmode = dev->openmode; /* Works because num_parts > 0. */ - if (open_first_part(dev, OPEN_READ_ONLY) < 0) { + if (open_first_part(dcr, OPEN_READ_ONLY) < 0) { Dmsg0(100, "lseek_dev failed while trying to open the first part\n"); return -1; } while (dev->part < (dev->num_parts-1)) { - if (open_next_part(dev) < 0) { + if (open_next_part(dcr) < 0) { Dmsg0(100, "lseek_dev failed while trying to open the next part\n"); return -1; } } dev->openmode = openmode; - if (open_next_part(dev) < 0) { + if (open_next_part(dcr) < 0) { Dmsg0(100, "lseek_dev failed while trying to open the next part\n"); return -1; } @@ -661,7 +674,7 @@ bool dvd_close_job(DCR *dcr) ok = false; } - if (ok && (open_next_part(dev) < 0)) { + if (ok && (open_next_part(dcr) < 0)) { Jmsg2(jcr, M_FATAL, 0, _("Unable to open device next part %s: ERR=%s\n"), dev->print_name(), strerror_dev(dev)); dev->dev_errno = EIO; @@ -692,7 +705,6 @@ static char *edit_device_codes_dev(DEVICE* dev, char *omsg, const char *imsg) char add[20]; POOL_MEM archive_name(PM_FNAME); - get_filename(dev, dev->VolCatInfo.VolCatName, archive_name); *omsg = 0; Dmsg1(800, "edit_device_codes: %s\n", imsg); @@ -713,6 +725,7 @@ static char *edit_device_codes_dev(DEVICE* dev, char *omsg, const char *imsg) str = dev->device->mount_point; break; case 'v': + make_dvd_filename(dev, archive_name); str = archive_name.c_str(); break; default: diff --git a/bacula/src/stored/label.c b/bacula/src/stored/label.c index ac0dd6bab5..9ea663715d 100644 --- a/bacula/src/stored/label.c +++ b/bacula/src/stored/label.c @@ -230,106 +230,6 @@ int read_dev_volume_label(DCR *dcr) return VOL_OK; } -/* Read the volume label by guessing the volume name. (only for DVD devices) - * write is true if we are reading the label before writing to the device. - * - * If the volume name cannot be guessed : - * Writing : returns the label of the current file (on the harddisk). - * Reading : returns an error - */ -int read_dvd_volume_label(DCR *dcr, bool write) -{ - int vol_label_status; - DEVICE *dev = dcr->dev; - JCR *jcr = dcr->jcr; - Dmsg3(100, "Enter: dvd_volume_label device=%s vol=%s dev_Vol=%s\n", - dev->print_name(), dcr->VolumeName, dev->VolHdr.VolumeName); - - if (!dev->is_dvd()) { - Jmsg1(jcr, M_ABORT, 0, _("Device %s is not a DVD.\n"), dev->print_name()); - return -1; /* for compiler, won't get here */ - } - - if (!write && (dcr->VolCatInfo.VolCatParts == 0)) { - Dmsg0(100, "Leave read_dvd_volume_label !writing, and VolCatParts == 0\n"); - return read_dev_volume_label(dcr); - } - - /* - * For mounted devices, try to guess the Volume name - * and read the label if possible. - */ - if (!can_open_mounted_dev(dev)) { - if (!write || dcr->VolCatInfo.VolCatParts > 0) { - Mmsg2(jcr->errmsg, _("Requested Volume \"%s\" on %s is not a Bacula labeled Volume."), - dev->print_name(), dcr->VolumeName); - Dmsg0(100, "Leave read_dvd_volume_label VOL_NO_LABEL (!open_mounted_dev)\n"); - return VOL_NO_LABEL; - } - - /* At this point, we are writing */ - if (dev->free_space_errno < 0) { - Dmsg0(100, "Exit: read_dvd_volume_label !free_space VOL_NO_MEDIA\n"); - Mmsg2(jcr->errmsg, _("free_space error on %s. The current medium is probably not writable: ERR=%s.\n"), - dev->print_name(), dev->errmsg); - return VOL_NO_MEDIA; - } - - /* - * If we can't guess the name, and we are writing, - * just reopen the right file with open_first_part. - */ - if (open_first_part(dev, OPEN_READ_WRITE) < 0) { - berrno be; - Mmsg2(jcr->errmsg, _("open_first_part error on %s: ERR=%s.\n"), - dev->print_name(), be.strerror()); - Dmsg0(100, "Leave read_dvd_volume_label VOL_IO_ERROR (!open_mounted_dev && !open_first_part)\n"); - return VOL_IO_ERROR; - } - - Dmsg0(100, "Leave read_dvd_volume_label !open_mounted_dev\n"); - return read_dev_volume_label(dcr); - - } else { - /* - * If we get here, we can open the mounted device - */ - if (write && dcr->dev->free_space_errno < 0) { - Dmsg0(100, "Leave read_dvd_volume_label !free_space VOL_NO_MEDIA\n"); - Mmsg2(jcr->errmsg, _("free_space error on %s. The current medium is probably not writable: ERR=%s.\n"), - dev->print_name(), dev->errmsg); - return VOL_NO_MEDIA; - } - - if (!write || dcr->VolCatInfo.VolCatParts > 0) { - Dmsg0(100, "Exit: read_dvd_volume_label (open_mounted_dev && (!write || dcr->VolCatInfo.VolCatParts > 0))\n"); - return read_dev_volume_label(dcr); - } - - /* At this point, we are writing */ - if (open_first_part(dcr->dev, OPEN_READ_WRITE) < 0) { - berrno be; - Mmsg2(jcr->errmsg, _("open_first_part error on %s: ERR=%s.\n"), - dev->print_name(), be.strerror()); - Dmsg0(100, "Leave read_dvd_volume_label VOL_IO_ERROR (open_mounted_dev && !open_first_part)\n"); - return VOL_IO_ERROR; - } - vol_label_status = read_dev_volume_label(dcr); - - /* When writing, if the guessed volume name is not the right volume name, - * report the error, otherwise, just continue with the right file. - */ - if (vol_label_status != VOL_NAME_ERROR) { - Dmsg0(100, "Leave read_dvd_volume_label (open_mounted_dev && !VOL_NAME_ERROR)\n"); - dev->clear_labeled(); - return read_dev_volume_label(dcr); - } else { - Dmsg0(100, "Leave read_dvd_volume_label (open_mounted_dev && VOL_NAME_ERROR)\n"); - return vol_label_status; - } - } -} - /* * Put a volume label into the block * diff --git a/bacula/src/stored/mount.c b/bacula/src/stored/mount.c index 9ecbf991f8..67b748f498 100644 --- a/bacula/src/stored/mount.c +++ b/bacula/src/stored/mount.c @@ -97,8 +97,6 @@ mount_next_vol: Dmsg3(100, "After find_next_append. Vol=%s Slot=%d Parts=%d\n", dcr->VolCatInfo.VolCatName, dcr->VolCatInfo.Slot, dcr->VolCatInfo.VolCatParts); - dev->num_parts = dcr->VolCatInfo.VolCatParts; - /* * Get next volume and ready it for append * This code ensures that the device is ready for @@ -181,8 +179,6 @@ read_volume: vol_label_status = VOL_OK; create_volume_label(dev, dcr->VolumeName, "Default"); dev->VolHdr.LabelType = PRE_LABEL; - } else if (dev->is_dvd()) { - vol_label_status = read_dvd_volume_label(dcr, /*write*/true); } else { vol_label_status = read_dev_volume_label(dcr); } diff --git a/bacula/src/stored/protos.h b/bacula/src/stored/protos.h index 3cac3a8c31..618ae64cb7 100644 --- a/bacula/src/stored/protos.h +++ b/bacula/src/stored/protos.h @@ -80,8 +80,8 @@ void display_tape_error_status(JCR *jcr, DEVICE *dev); /* From dev.c */ DEVICE *init_dev(JCR *jcr, DEVRES *device); off_t lseek_dev(DEVICE *dev, off_t offset, int whence); -int open_first_part(DEVICE *dev, int mode); -int open_next_part(DEVICE *dev); +int open_first_part(DCR *dcr, int mode); +int open_next_part(DCR *dcr); bool can_open_mounted_dev(DEVICE *dev); bool truncate_dev(DEVICE *dev); void term_dev(DEVICE *dev); @@ -118,13 +118,13 @@ bool dvd_close_job(DCR *dcr); bool mount_dev(DEVICE* dev, int timeout); bool unmount_dev(DEVICE* dev, int timeout); void update_free_space_dev(DEVICE *dev); -void get_filename(DEVICE *dev, char *VolName, POOL_MEM& archive_name); +void make_dvd_filename(DEVICE *dev, POOL_MEM &archive_name); /* From device.c */ bool open_device(DCR *dcr); void close_device(DEVICE *dev); void force_close_device(DEVICE *dev); -bool first_open_device(DEVICE *dev); +bool first_open_device(DCR *dcr); bool fixup_device_block_write_error(DCR *dcr); void _lock_device(const char *file, int line, DEVICE *dev); void _unlock_device(const char *file, int line, DEVICE *dev); diff --git a/bacula/src/stored/status.c b/bacula/src/stored/status.c index d7b2321e8f..eb48d3bc54 100644 --- a/bacula/src/stored/status.c +++ b/bacula/src/stored/status.c @@ -91,7 +91,6 @@ bool status_cmd(JCR *jcr) * List devices */ bnet_fsend(user, _("\nDevice status:\n")); -// LockRes(); foreach_res(changer, R_AUTOCHANGER) { bnet_fsend(user, _("Autochanger \"%s\" with devices:\n"), changer->hdr.name); @@ -148,7 +147,6 @@ bool status_cmd(JCR *jcr) send_blocked_status(jcr, dev); } } -// UnlockRes(); bnet_fsend(user, "====\n\n"); bnet_fsend(user, "Volume status:\n"); list_volumes(user); @@ -174,6 +172,7 @@ static void send_blocked_status(JCR *jcr, DEVICE *dev) DCR *dcr = jcr->dcr; if (!dev) { + bnet_fsend(user, "No DEVICE structure.\n\n"); return; } switch (dev->dev_blocked) { @@ -216,7 +215,7 @@ static void send_blocked_status(JCR *jcr, DEVICE *dev) bnet_fsend(user, "%sALWAYSOPEN ", dev->capabilities & CAP_ALWAYSOPEN ? "" : "!"); bnet_fsend(user, "\n"); - bnet_fsend(user, _("Device status:\n")); + bnet_fsend(user, _("Device state:\n")); bnet_fsend(user, "%sOPENED ", dev->is_open() ? "" : "!"); bnet_fsend(user, "%sTAPE ", dev->is_tape() ? "" : "!"); bnet_fsend(user, "%sLABEL ", dev->is_labeled() ? "" : "!"); @@ -230,7 +229,7 @@ static void send_blocked_status(JCR *jcr, DEVICE *dev) bnet_fsend(user, "%sSHORT ", dev->state & ST_SHORT ? "" : "!"); bnet_fsend(user, "%sMOUNTED ", dev->state & ST_MOUNTED ? "" : "!"); bnet_fsend(user, "\n"); - bnet_fsend(user, "num_writers=%d JobStatus=%c block=%d\nn", dev->num_writers, + bnet_fsend(user, "num_writers=%d JobStatus=%c block=%d\n\n", dev->num_writers, jcr->JobStatus, dev->dev_blocked); bnet_fsend(user, _("Device parameters:\n")); diff --git a/bacula/src/stored/stored.c b/bacula/src/stored/stored.c index 42ec7a7803..a4a0f7fa32 100644 --- a/bacula/src/stored/stored.c +++ b/bacula/src/stored/stored.c @@ -263,7 +263,6 @@ static int check_resources() bool OK = true; AUTOCHANGER *changer; -// LockRes(); me = (STORES *)GetNextRes(R_STORAGE, NULL); if (!me) { @@ -461,48 +460,56 @@ extern "C" void *device_initialization(void *arg) { DEVRES *device; + DCR *dcr; + JCR *jcr; + DEVICE *dev; LockRes(); + pthread_detach(pthread_self()); + jcr = new_jcr(sizeof(JCR), stored_free_jcr); + jcr->JobType = JT_SYSTEM; + /* Initialize FD start condition variable */ + int errstat = pthread_cond_init(&jcr->job_start_wait, NULL); + if (errstat != 0) { + Jmsg1(jcr, M_ABORT, 0, _("Unable to init job cond variable: ERR=%s\n"), strerror(errstat)); + } foreach_res(device, R_DEVICE) { Dmsg1(90, "calling init_dev %s\n", device->device_name); - device->dev = init_dev(NULL, device); + device->dev = dev = init_dev(NULL, device); Dmsg1(10, "SD init done %s\n", device->device_name); - if (!device->dev) { + if (!dev) { Jmsg1(NULL, M_ERROR, 0, _("Could not initialize %s\n"), device->device_name); continue; } + dcr = new_dcr(jcr, dev); + if (device->cap_bits & CAP_ALWAYSOPEN) { - Dmsg1(20, "calling first_open_device %s\n", device->device_name); - if (!first_open_device(device->dev)) { - Jmsg1(NULL, M_ERROR, 0, _("Could not open device %s\n"), device->device_name); + Dmsg1(20, "calling first_open_device %s\n", dev->print_name()); + if (!first_open_device(dcr)) { + Jmsg1(NULL, M_ERROR, 0, _("Could not open device %s\n"), dev->print_name()); + Dmsg1(20, "Could not open device %s\n", dev->print_name()); + term_dev(dev); + device->dev = NULL; + free_dcr(dcr); + continue; } } - if (device->cap_bits & CAP_AUTOMOUNT && device->dev && - device->dev->is_open()) { - JCR *jcr; - DCR *dcr; - jcr = new_jcr(sizeof(JCR), stored_free_jcr); - jcr->JobType = JT_SYSTEM; - /* Initialize FD start condition variable */ - int errstat = pthread_cond_init(&jcr->job_start_wait, NULL); - if (errstat != 0) { - Jmsg1(jcr, M_ABORT, 0, _("Unable to init job cond variable: ERR=%s\n"), strerror(errstat)); - } - dcr = new_dcr(jcr, device->dev); + if (device->cap_bits & CAP_AUTOMOUNT && dev->is_open()) { switch (read_dev_volume_label(dcr)) { case VOL_OK: - memcpy(&dcr->dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dcr->dev->VolCatInfo)); + memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo)); break; default: - Jmsg1(NULL, M_WARNING, 0, _("Could not mount device %s\n"), device->device_name); + Jmsg1(NULL, M_WARNING, 0, _("Could not mount device %s\n"), dev->print_name()); break; } - free_jcr(jcr); } + free_dcr(dcr); } + free_jcr(jcr); UnlockRes(); return NULL; } @@ -557,9 +564,12 @@ void terminate_stored(int sig) Dmsg1(200, "In terminate_stored() sig=%d\n", sig); foreach_res(device, R_DEVICE) { + Dmsg1(10, "Term device %s\n", device->device_name); if (device->dev) { free_volume(device->dev); term_dev(device->dev); + } else { + Dmsg1(10, "No dev structure %s\n", device->device_name); } } diff --git a/bacula/src/stored/stored_conf.c b/bacula/src/stored/stored_conf.c index 876bf8470b..87a9ca8c10 100644 --- a/bacula/src/stored/stored_conf.c +++ b/bacula/src/stored/stored_conf.c @@ -115,6 +115,8 @@ static RES_ITEM dev_items[] = { {"blockpositioning", store_yesno, ITEM(res_dev.cap_bits), CAP_POSITIONBLOCKS, ITEM_DEFAULT, 1}, {"usemtiocget", store_yesno, ITEM(res_dev.cap_bits), CAP_MTIOCGET, ITEM_DEFAULT, 1}, {"checklabels", store_yesno, ITEM(res_dev.cap_bits), CAP_CHECKLABELS, ITEM_DEFAULT, 0}, + {"requiresmount", store_yesno, ITEM(res_dev.cap_bits), CAP_REQMOUNT, ITEM_DEFAULT, 0}, + {"offlineonunmount", store_yesno, ITEM(res_dev.cap_bits), CAP_OFFLINEUNMOUNT, ITEM_DEFAULT, 0}, {"autoselect", store_yesno, ITEM(res_dev.autoselect), 1, ITEM_DEFAULT, 1}, {"changerdevice", store_strname,ITEM(res_dev.changer_name), 0, 0, 0}, {"changercommand", store_strname,ITEM(res_dev.changer_command), 0, 0, 0}, @@ -124,7 +126,6 @@ static RES_ITEM dev_items[] = { {"maximumopenvolumes", store_pint, ITEM(res_dev.max_open_vols), 0, ITEM_DEFAULT, 1}, {"maximumnetworkbuffersize", store_pint, ITEM(res_dev.max_network_buffer_size), 0, 0, 0}, {"volumepollinterval", store_time, ITEM(res_dev.vol_poll_interval), 0, 0, 0}, - {"offlineonunmount", store_yesno, ITEM(res_dev.cap_bits), CAP_OFFLINEUNMOUNT, ITEM_DEFAULT, 0}, {"maximumrewindwait", store_pint, ITEM(res_dev.max_rewind_wait), 0, ITEM_DEFAULT, 5 * 60}, {"minimumblocksize", store_pint, ITEM(res_dev.min_block_size), 0, 0, 0}, {"maximumblocksize", store_pint, ITEM(res_dev.max_block_size), 0, 0, 0}, @@ -136,7 +137,6 @@ static RES_ITEM dev_items[] = { {"maximumjobspoolsize", store_size, ITEM(res_dev.max_job_spool_size), 0, 0, 0}, {"driveindex", store_pint, ITEM(res_dev.drive_index), 0, 0, 0}, {"maximumpartsize", store_size, ITEM(res_dev.max_part_size), 0, ITEM_DEFAULT, 0}, - {"requiresmount", store_yesno, ITEM(res_dev.cap_bits), CAP_REQMOUNT, ITEM_DEFAULT, 0}, {"mountpoint", store_strname,ITEM(res_dev.mount_point), 0, 0, 0}, {"mountcommand", store_strname,ITEM(res_dev.mount_command), 0, 0, 0}, {"unmountcommand", store_strname,ITEM(res_dev.unmount_command), 0, 0, 0}, @@ -181,7 +181,7 @@ RES_TABLE resources[] = { void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fmt, ...), void *sock) { URES *res = (URES *)reshdr; - char buf[MAXSTRING]; + char buf[1000]; int recurse = 1; IPADDR *p; if (res == NULL) { @@ -276,6 +276,12 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm if (res->res_dev.cap_bits & CAP_CHECKLABELS) { bstrncat(buf, "CAP_CHECKLABELS ", sizeof(buf)); } + if (res->res_dev.cap_bits & CAP_REQMOUNT) { + bstrncat(buf, "CAP_REQMOUNT ", sizeof(buf)); + } + if (res->res_dev.cap_bits & CAP_OFFLINEUNMOUNT) { + bstrncat(buf, "CAP_OFFLINEUNMOUNT ", sizeof(buf)); + } bstrncat(buf, "\n", sizeof(buf)); sendit(sock, buf); break; diff --git a/bacula/src/version.h b/bacula/src/version.h index 063590e2a9..0ca77f7e05 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -1,8 +1,8 @@ /* */ #undef VERSION -#define VERSION "1.37.26" -#define BDATE "26 June 2005" -#define LSMDATE "26Jun05" +#define VERSION "1.37.28" +#define BDATE "29 June 2005" +#define LSMDATE "29Jun05" /* Debug flags */ #undef DEBUG -- 2.39.5