From: Kern Sibbald Date: Tue, 15 Aug 2006 20:43:54 +0000 (+0000) Subject: kes If doing a mount, look for a slot, and if specified pass it to X-Git-Tag: Release-2.0.0~619 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=94f9c56ee2efd4baae985ab0a4dfbf5a099ef2c3;p=bacula%2Fbacula kes If doing a mount, look for a slot, and if specified pass it to the SD so that it can load the autochanger. kes Return DVD=1 flag if a label command is done to a DVD. This permits setting VolParts to 1. kes Apply DVD patch from Richard Mortimer , but rework ua_label code based on DVD media type to use DVD flag returned. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@3286 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/kernstodo b/bacula/kernstodo index 6258919c07..c8774d6921 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -1,5 +1,5 @@ Kern's ToDo List - 30 July 2006 + 16 August 2006 Major development: Project Developer @@ -1647,3 +1647,5 @@ Block Position: 0 - Fix auth compatibility with 1.38 - Update dbcheck to include Log table - Update llist to include new fields. +- Make unmount unload autochanger. Make mount load slot. + diff --git a/bacula/scripts/dvd-handler.in b/bacula/scripts/dvd-handler.in index b90108156e..1aa05e842d 100644 --- a/bacula/scripts/dvd-handler.in +++ b/bacula/scripts/dvd-handler.in @@ -267,6 +267,9 @@ class disk: cmd = self.growcmd + self.growparams if newvol: cmd += " -Z " + // Ignore any existing iso9660 filesystem - used for truncate + if newvol == 2: + cmd += "-use-the-force-luke=tty " else: cmd += " -M " cmd += self.device + " " + str(partfile) @@ -397,8 +400,9 @@ test Scan the device and report the information found. free Scan the device and report the available space. write Write a part file to disk. This operation needs two additional arguments. - The first indicates to append (0) or restart the - disk (1). The second is the file to write. + The first indicates to append (0), restart the + disk (1) or restart existing disk (2). The second + is the file to write. prepare Prepare a DVD+/-RW for being used by Bacula. Note: This is only useful if you already have some non-Bacula data on a medium, and you want to use diff --git a/bacula/src/cats/bdb_find.c b/bacula/src/cats/bdb_find.c index f63a5354dc..a6cce18e9d 100644 --- a/bacula/src/cats/bdb_find.c +++ b/bacula/src/cats/bdb_find.c @@ -174,7 +174,7 @@ db_find_next_volume(JCR *jcr, B_DB *mdb, int item, bool InChanger, MEDIA_DBR *mr bool db_find_last_jobid(JCR *jcr, B_DB *mdb, const char *Name, JOB_DBR *jr) -{ return 0; } +{ return false; } bool db_find_failed_job_since(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM *stime, int &JobLevel) diff --git a/bacula/src/dird/protos.h b/bacula/src/dird/protos.h index 16a361df71..d7c040fbb2 100644 --- a/bacula/src/dird/protos.h +++ b/bacula/src/dird/protos.h @@ -208,6 +208,7 @@ int do_prompt(UAContext *ua, const char *automsg, const char *msg, char *pro CAT *get_catalog_resource(UAContext *ua); STORE *get_storage_resource(UAContext *ua, bool use_default); int get_storage_drive(UAContext *ua, STORE *store); +int get_storage_slot(UAContext *ua, STORE *store); int get_media_type(UAContext *ua, char *MediaType, int max_media); bool get_pool_dbr(UAContext *ua, POOL_DBR *pr); int get_client_dbr(UAContext *ua, CLIENT_DBR *cr); diff --git a/bacula/src/dird/ua_cmds.c b/bacula/src/dird/ua_cmds.c index 9869bb281e..24828f4a25 100644 --- a/bacula/src/dird/ua_cmds.c +++ b/bacula/src/dird/ua_cmds.c @@ -1301,6 +1301,7 @@ static void do_mount_cmd(UAContext *ua, const char *command) JCR *jcr = ua->jcr; char dev_name[MAX_NAME_LENGTH]; int drive; + int slot = -1; if (!open_db(ua)) { return; @@ -1313,6 +1314,9 @@ static void do_mount_cmd(UAContext *ua, const char *command) } set_wstorage(jcr, store); drive = get_storage_drive(ua, store); + if (strcmp(command, "mount") == 0) { + slot = get_storage_slot(ua, store); + } Dmsg3(120, "Found storage, MediaType=%s DevName=%s drive=%d\n", store->media_type, store->dev_name(), drive); @@ -1324,7 +1328,11 @@ static void do_mount_cmd(UAContext *ua, const char *command) sd = jcr->store_bsock; bstrncpy(dev_name, store->dev_name(), sizeof(dev_name)); bash_spaces(dev_name); - bnet_fsend(sd, "%s %s drive=%d", command, dev_name, drive); + if (slot > 0) { + bnet_fsend(sd, "%s %s drive=%d slot=%d", command, dev_name, drive, slot); + } else { + bnet_fsend(sd, "%s %s drive=%d", command, dev_name, drive); + } while (bnet_recv(sd) >= 0) { bsendmsg(ua, "%s", sd->msg); } @@ -1334,7 +1342,7 @@ static void do_mount_cmd(UAContext *ua, const char *command) } /* - * mount [storage=] [drive=nn] + * mount [storage=] [drive=nn] [slot=mm] */ static int mount_cmd(UAContext *ua, const char *cmd) { diff --git a/bacula/src/dird/ua_label.c b/bacula/src/dird/ua_label.c index 86a5b02843..c7d546f4b5 100644 --- a/bacula/src/dird/ua_label.c +++ b/bacula/src/dird/ua_label.c @@ -629,6 +629,7 @@ static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr, BSOCK *sd; char dev_name[MAX_NAME_LENGTH]; bool ok = false; + bool is_dvd = false; if (!(sd=open_sd_bsock(ua))) { return false; @@ -662,12 +663,20 @@ static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr, if (strncmp(sd->msg, "3000 OK label.", 14) == 0) { ok = true; } + if (strncmp(sd->msg, "3000 OK label. DVD=1 ", 21) == 0) { + is_dvd = true; + } } unbash_spaces(mr->VolumeName); unbash_spaces(mr->MediaType); unbash_spaces(pr->Name); mr->LabelDate = time(NULL); mr->set_label_date = true; + if (is_dvd) { + /* We know that a freshly labelled DVD has 1 VolParts */ + /* This does not apply to auto-labelled DVDs. */ + mr->VolParts = 1; + } if (ok) { if (media_record_exists) { /* we update it */ mr->VolBytes = 1; diff --git a/bacula/src/dird/ua_select.c b/bacula/src/dird/ua_select.c index 6fbfb84d03..b12517f4f9 100644 --- a/bacula/src/dird/ua_select.c +++ b/bacula/src/dird/ua_select.c @@ -907,6 +907,27 @@ int get_storage_drive(UAContext *ua, STORE *store) return drive; } +/* Get slot that we are working with for this storage */ +int get_storage_slot(UAContext *ua, STORE *store) +{ + int i, slot = -1; + /* Get slot for autochanger if possible */ + i = find_arg_with_value(ua, "slot"); + if (i >=0) { + slot = atoi(ua->argv[i]); + } else if (store && store->autochanger) { + /* Ask user to enter slot number */ + ua->cmd[0] = 0; + if (!get_cmd(ua, _("Enter autochanger slot: "))) { + slot = -1; /* None */ + } else { + slot = atoi(ua->cmd); + } + } + return slot; +} + + /* * Scan looking for mediatype= diff --git a/bacula/src/lib/edit.c b/bacula/src/lib/edit.c index c0e5d0523d..bc07ad74ee 100644 --- a/bacula/src/lib/edit.c +++ b/bacula/src/lib/edit.c @@ -6,7 +6,7 @@ * Version $Id$ */ /* - Copyright (C) 2002-2005 Kern Sibbald + Copyright (C) 2002-2006 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/bacula/src/stored/btape.c b/bacula/src/stored/btape.c index 9eabe54198..6fe9210bad 100644 --- a/bacula/src/stored/btape.c +++ b/bacula/src/stored/btape.c @@ -373,7 +373,7 @@ static void labelcmd() } } dev->rewind(dcr); - write_new_volume_label_to_dev(dcr, cmd, "Default"); + write_new_volume_label_to_dev(dcr, cmd, "Default", true /* label dvd now */); Pmsg1(-1, _("Wrote Volume label for volume \"%s\".\n"), cmd); } diff --git a/bacula/src/stored/dev.c b/bacula/src/stored/dev.c index f394db043d..9dfaa307d0 100644 --- a/bacula/src/stored/dev.c +++ b/bacula/src/stored/dev.c @@ -504,6 +504,8 @@ void DEVICE::open_dvd_device(DCR *dcr, int omode) file_size = 0; } part_size = 0; + // Clear any previous truncated_dvd status - we will recalculate it here + truncated_dvd = false; Dmsg2(99, "open_dvd_device: num_parts=%d, VolCatInfo.VolCatParts=%d\n", dcr->dev->num_parts, dcr->VolCatInfo.VolCatParts); @@ -525,6 +527,7 @@ void DEVICE::open_dvd_device(DCR *dcr, int omode) clear_opened(); return; } + truncated_dvd = true; } } else { /* We cannot mount the device */ @@ -576,16 +579,21 @@ void DEVICE::open_dvd_device(DCR *dcr, int omode) berrno be; Mmsg2(errmsg, _("Could not open: %s, ERR=%s\n"), archive_name.c_str(), be.strerror()); + // Should this be set if we try the create/open below dev_errno = EIO; /* Interpreted as no device present by acquire.c:acquire_device_for_read(). */ Dmsg1(29, "open failed: %s", errmsg); - if ((omode == OPEN_READ_ONLY) && (part == num_parts)) { - /* If the last part (on spool), doesn't exists when reading, create it and read from it - * (it will report immediately an EOF): + if ((omode == OPEN_READ_ONLY || omode == OPEN_READ_WRITE) && + (part == num_parts)) { + /* If the last part (on spool), doesn't exists when accessing, + * create it. In read/write mode a write will be allowed (higher + * level software thinks that we are extending a pre-existing + * media. Reads for READ_ONLY will report immediately an EOF * Sometimes it is better to finish with an EOF than with an error. */ - set_mode(OPEN_READ_WRITE); + Dmsg0(29, "Creating last part on spool to make our caller happy\n"); + set_mode(CREATE_READ_WRITE); fd = ::open(archive_name.c_str(), mode, 0640); - set_mode(OPEN_READ_ONLY); + set_mode(omode); } /* We don't need it. Only the last part is on spool */ @@ -2002,7 +2010,11 @@ void DEVICE::edit_mount_codes(POOL_MEM &omsg, const char *imsg) break; case 'e': if (num_parts == 0) { - str = "1"; + if (truncating || truncated_dvd) { + str = "2"; + } else { + str = "1"; + } } else { str = "0"; } diff --git a/bacula/src/stored/dev.h b/bacula/src/stored/dev.h index 929726b7b8..4f2068ee15 100644 --- a/bacula/src/stored/dev.h +++ b/bacula/src/stored/dev.h @@ -246,6 +246,7 @@ public: uint64_t free_space; /* current free space on medium (without the current part) */ int free_space_errno; /* indicates errno getting freespace */ bool truncating; /* if set, we are currently truncating the DVD */ + bool truncated_dvd; /* if set, we have a truncated DVD in the drive */ utime_t vol_poll_interval; /* interval between polling Vol mount */ diff --git a/bacula/src/stored/dircmd.c b/bacula/src/stored/dircmd.c index 1243e24eea..7a22f56521 100644 --- a/bacula/src/stored/dircmd.c +++ b/bacula/src/stored/dircmd.c @@ -209,7 +209,7 @@ void *handle_connection_request(void *arg) Dmsg1(200, "Do command: %s\n", cmds[i].cmd); if (!cmds[i].func(jcr)) { /* do command */ quit = true; /* error, get out */ - Dmsg1(190, "Command %s requsts quit\n", cmds[i].cmd); + Dmsg1(190, "Command %s reqeusts quit\n", cmds[i].cmd); } found = true; /* indicate command found */ break; @@ -396,7 +396,12 @@ static void label_volume_if_ok(DCR *dcr, char *oldname, steal_device_lock(dev, &hold, BST_WRITING_LABEL); Dmsg1(100, "Stole device %s lock, writing label.\n", dev->print_name()); - if (!try_autoload_device(dcr->jcr, slot, newname)) { + Dmsg0(90, "try_autoload_device - looking for volume_info\n"); + if (relabel && dev->is_dvd()) { + dcr->VolCatInfo.VolCatParts=1; + } + + if (!try_autoload_device(dcr->jcr, slot, (relabel == 0) ? newname : oldname)) { goto bail_out; /* error */ } @@ -409,7 +414,7 @@ static void label_volume_if_ok(DCR *dcr, char *oldname, if (dev->open(dcr, mode) < 0) { bnet_fsend(dir, _("3910 Unable to open device %s: ERR=%s\n"), dev->print_name(), dev->strerror()); - return; + goto bail_out; } /* See what we have for a Volume */ @@ -436,18 +441,26 @@ static void label_volume_if_ok(DCR *dcr, char *oldname, bnet_fsend(dir, _("3922 Cannot relabel an ANSI/IBM labeled Volume.\n")); break; } + if (relabel && dev->is_dvd()) { + /* Change the partition file name */ + bstrncpy(dcr->VolumeName, newname, sizeof(dcr->VolumeName)); + if (!dev->truncate(dcr)) { + bnet_fsend(dir, _("3912 Failed to truncate previous DVD volume.\n")); + break; + } + } free_volume(dev); /* release old volume name */ /* Fall through wanted! */ case VOL_IO_ERROR: case VOL_NO_LABEL: - if (!write_new_volume_label_to_dev(dcr, newname, poolname)) { + if (!write_new_volume_label_to_dev(dcr, newname, poolname, true /* write dvd now */)) { bnet_fsend(dir, _("3912 Failed to label Volume: ERR=%s\n"), dev->bstrerror()); break; } bstrncpy(dcr->VolumeName, newname, sizeof(dcr->VolumeName)); /* The following 3000 OK label. string is scanned in ua_label.c */ - bnet_fsend(dir, "3000 OK label. Volume=%s Device=%s\n", - newname, dev->print_name()); + bnet_fsend(dir, "3000 OK label. DVD=%d Volume=\"%s\" Device=\"%s\"\n", + dev->is_dvd()?1:0, newname, dev->print_name()); break; case VOL_NO_MEDIA: bnet_fsend(dir, _("3912 Failed to label Volume: ERR=%s\n"), dev->bstrerror()); @@ -582,8 +595,15 @@ static bool mount_cmd(JCR *jcr) DEVICE *dev; DCR *dcr; int drive; + int slot = 0; + bool ok; - if (sscanf(dir->msg, "mount %127s drive=%d", devname.c_str(), &drive) == 2) { + ok = sscanf(dir->msg, "mount %127s drive=%d slot=%d", devname.c_str(), + &drive, &slot) == 3; + if (!ok) { + ok = sscanf(dir->msg, "mount %127s drive=%d", devname.c_str(), &drive) == 2; + } + if (ok) { dcr = find_device(jcr, devname, drive); if (dcr) { dev = dcr->dev; @@ -603,6 +623,9 @@ static bool mount_cmd(JCR *jcr) /* In both of these two cases, we (the user) unmounted the Volume */ case BST_UNMOUNTED_WAITING_FOR_SYSOP: case BST_UNMOUNTED: + if (dev->is_autochanger() && slot > 0) { + try_autoload_device(jcr, slot, ""); + } /* We freed the device, so reopen it and wake any waiting threads */ if (dev->open(dcr, OPEN_READ_ONLY) < 0) { bnet_fsend(dir, _("3901 open device failed: ERR=%s\n"), @@ -647,6 +670,9 @@ static bool mount_cmd(JCR *jcr) break; case BST_NOT_BLOCKED: + if (dev->is_autochanger() && slot > 0) { + try_autoload_device(jcr, slot, ""); + } if (dev->is_open()) { if (dev->is_labeled()) { bnet_fsend(dir, _("3001 Device %s is mounted with Volume \"%s\"\n"), @@ -722,19 +748,31 @@ static bool unmount_cmd(JCR *jcr) if (!dev->is_busy()) { unload_autochanger(jcr->dcr, -1); } - Dmsg0(90, "Device already unmounted\n"); - bnet_fsend(dir, _("3901 Device %s is already unmounted.\n"), - dev->print_name()); - + if (dev->is_dvd()) { + if (unmount_dvd(dev, 0)) { + bnet_fsend(dir, _("3002 Device %s unmounted.\n"), + dev->print_name()); + } else { + bnet_fsend(dir, _("3907 %s"), dev->bstrerror()); + } + } else { + Dmsg0(90, "Device already unmounted\n"); + bnet_fsend(dir, _("3901 Device %s is already unmounted.\n"), + dev->print_name()); + } } else if (dev->dev_blocked == BST_WAITING_FOR_SYSOP) { Dmsg2(90, "%d waiter dev_block=%d. doing unmount\n", dev->num_waiting, dev->dev_blocked); if (!unload_autochanger(jcr->dcr, -1)) { dev->close(); } - dev->dev_blocked = BST_UNMOUNTED_WAITING_FOR_SYSOP; - bnet_fsend(dir, _("3001 Device %s unmounted.\n"), - dev->print_name()); + if (dev->is_dvd() && !unmount_dvd(dev, 0)) { + bnet_fsend(dir, _("3907 %s"), dev->bstrerror()); + } else { + dev->dev_blocked = BST_UNMOUNTED_WAITING_FOR_SYSOP; + bnet_fsend(dir, _("3001 Device %s unmounted.\n"), + dev->print_name()); + } } else if (dev->dev_blocked == BST_DOING_ACQUIRE) { bnet_fsend(dir, _("3902 Device %s is busy in acquire.\n"), @@ -759,8 +797,12 @@ static bool unmount_cmd(JCR *jcr) if (!unload_autochanger(jcr->dcr, -1)) { dev->close(); } - bnet_fsend(dir, _("3002 Device %s unmounted.\n"), - dev->print_name()); + if (dev->is_dvd() && !unmount_dvd(dev, 0)) { + bnet_fsend(dir, _("3907 %s"), dev->bstrerror()); + } else { + bnet_fsend(dir, _("3002 Device %s unmounted.\n"), + dev->print_name()); + } } V(dev->mutex); free_dcr(dcr); diff --git a/bacula/src/stored/dvd.c b/bacula/src/stored/dvd.c index 8284256911..bc50a59a24 100644 --- a/bacula/src/stored/dvd.c +++ b/bacula/src/stored/dvd.c @@ -138,7 +138,10 @@ static bool do_mount_dvd(DEVICE* dev, int mount, int dotimeout) while ((status = run_program_full_output(ocmd.c_str(), dev->max_open_wait/2, results)) != 0) { /* Doesn't work with internationalisation (This is not a problem) */ - if (fnmatch("*is already mounted on", results, 0) == 0) { + if (mount && fnmatch("*is already mounted on*", results, 0) == 0) { + break; + } + if (!mount && fnmatch("* not mounted*", results, 0) == 0) { break; } if (timeout-- > 0) { @@ -151,9 +154,10 @@ static bool do_mount_dvd(DEVICE* dev, int mount, int dotimeout) bmicrosleep(1, 0); continue; } - Dmsg2(40, "Device %s cannot be mounted. ERR=%s\n", dev->print_name(), results); - Mmsg(dev->errmsg, _("Device %s cannot be mounted. ERR=%s\n"), - dev->print_name(), results); + Dmsg3(40, "Device %s cannot be %smounted. ERR=%s\n", dev->print_name(), + (mount ? "" : "un"), results); + Mmsg(dev->errmsg, _("Device %s cannot be %smounted. ERR=%s\n"), + dev->print_name(), (mount ? "" : "un"), results); /* * Now, just to be sure it is not mounted, try to read the * filesystem. @@ -201,8 +205,17 @@ static bool do_mount_dvd(DEVICE* dev, int mount, int dotimeout) Dmsg1(29, "do_mount_dvd: got %d files in the mount point (not counting ., .. and .keep)\n", count); if (count > 0) { - mount = 1; /* If we got more than ., .. and .keep */ - break; /* there must be something mounted */ + /* If we got more than ., .. and .keep */ + /* there must be something mounted */ + if (mount) { + break; + } else { + /* An unmount request. We failed to unmount - report an error */ + dev->set_mounted(true); + free_pool_memory(results); + Dmsg0(200, "============ DVD mount=1\n"); + return false; + } } get_out: dev->set_mounted(false); @@ -375,10 +388,11 @@ bool dvd_write_part(DCR *dcr) Dmsg2(29, "dvd_write_part: cmd=%s timeout=%d\n", ocmd.c_str(), timeout); status = run_program_full_output(ocmd.c_str(), timeout, results.c_str()); + dev->truncated_dvd = false; // Clear this status now write has finished if (status != 0) { Mmsg1(dev->errmsg, _("Error while writing current part to the DVD: %s"), results.c_str()); - Dmsg1(000, "%s", dev->errmsg); + Dmsg1(000, "%s\n", dev->errmsg); dev->dev_errno = EIO; mark_volume_in_error(dcr); sm_check(__FILE__, __LINE__, false); @@ -716,6 +730,17 @@ bool dvd_close_job(DCR *dcr) bool truncate_dvd(DCR *dcr) { DEVICE* dev = dcr->dev; + if (dev->fd >= 0) { + close(dev->fd); + } + dev->fd = -1; + dev->clear_opened(); + + if (!unmount_dvd(dev, 1)) { + Dmsg0(400, "truncate_dvd: Failed to unmount DVD\n"); + return false; + } + /* Set num_parts to zero (on disk) */ dev->num_parts = 0; dcr->VolCatInfo.VolCatParts = 0; @@ -724,12 +749,11 @@ bool truncate_dvd(DCR *dcr) { Dmsg0(400, "truncate_dvd: Opening first part (1)...\n"); dev->truncating = true; - if (dvd_open_first_part(dcr, OPEN_READ_WRITE) < 0) { + if (dvd_open_first_part(dcr, CREATE_READ_WRITE) < 0) { Dmsg0(400, "truncate_dvd: Error while opening first part (1).\n"); dev->truncating = false; return false; } - dev->truncating = false; Dmsg0(400, "truncate_dvd: Truncating...\n"); @@ -738,6 +762,7 @@ bool truncate_dvd(DCR *dcr) { berrno be; Mmsg2(dev->errmsg, _("Unable to truncate device %s. ERR=%s\n"), dev->print_name(), be.strerror()); + dev->truncating = false; return false; } @@ -749,8 +774,10 @@ bool truncate_dvd(DCR *dcr) { if (!dvd_write_part(dcr)) { Dmsg0(400, "truncate_dvd: Error while writing to DVD.\n"); + dev->truncating = false; return false; } + dev->truncating = false; /* Set num_parts to zero (on disk) */ dev->num_parts = 0; diff --git a/bacula/src/stored/label.c b/bacula/src/stored/label.c index 030a7ca2c2..4959d55268 100644 --- a/bacula/src/stored/label.c +++ b/bacula/src/stored/label.c @@ -163,6 +163,7 @@ int read_dev_volume_label(DCR *dcr) empty_block(block); return VOL_OK; } + Dmsg0(100, "No volume label - bailing out\n"); stat = VOL_NO_LABEL; goto bail_out; } @@ -288,7 +289,8 @@ bool write_volume_label_to_block(DCR *dcr) * * This routine should be used only when labeling a blank tape. */ -bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, const char *PoolName) +bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, + const char *PoolName, bool dvdnow) { DEVICE *dev = dcr->dev; @@ -312,8 +314,8 @@ bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, const char *Po } } - /* Create PRE_LABEL */ - create_volume_label(dev, VolName, PoolName); + /* Create PRE_LABEL or VOL_LABEL if DVD */ + create_volume_label(dev, VolName, PoolName, dvdnow); /* * If we have already detected an ANSI label, re-read it @@ -346,6 +348,15 @@ bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, const char *Po Dmsg2(30, "Bad Label write on %s: ERR=%s\n", dev->print_name(), dev->bstrerror()); goto bail_out; } + + /* Now commit block to DVD if we should write now */ + if (dev->is_dvd() && dvdnow) { + if (!dvd_write_part(dcr)) { + Dmsg2(30, "Bad DVD write on %s: ERR=%s\n", dev->print_name(), dev->bstrerror()); + goto bail_out; + } + } + Dmsg0(99, " Wrote block to device\n"); if (dev->weof(1)) { @@ -541,7 +552,8 @@ static void create_volume_label_record(DCR *dcr, DEV_RECORD *rec) /* * Create a volume label in memory */ -void create_volume_label(DEVICE *dev, const char *VolName, const char *PoolName) +void create_volume_label(DEVICE *dev, const char *VolName, + const char *PoolName, bool dvdnow) { DEVRES *device = (DEVRES *)dev->device; @@ -554,7 +566,12 @@ void create_volume_label(DEVICE *dev, const char *VolName, const char *PoolName) bstrncpy(dev->VolHdr.Id, BaculaId, sizeof(dev->VolHdr.Id)); dev->VolHdr.VerNum = BaculaTapeVersion; - dev->VolHdr.LabelType = PRE_LABEL; /* Mark tape as unused */ + if (dev->is_dvd() && dvdnow) { + /* We do not want to re-label a DVD so write VOL_LABEL now */ + dev->VolHdr.LabelType = VOL_LABEL; + } else { + dev->VolHdr.LabelType = PRE_LABEL; /* Mark tape as unused */ + } bstrncpy(dev->VolHdr.VolumeName, VolName, sizeof(dev->VolHdr.VolumeName)); bstrncpy(dev->VolHdr.PoolName, PoolName, sizeof(dev->VolHdr.PoolName)); bstrncpy(dev->VolHdr.MediaType, device->media_type, sizeof(dev->VolHdr.MediaType)); diff --git a/bacula/src/stored/mount.c b/bacula/src/stored/mount.c index 8b86db484b..83494eb715 100644 --- a/bacula/src/stored/mount.c +++ b/bacula/src/stored/mount.c @@ -194,7 +194,7 @@ read_volume: */ if (dev->has_cap(CAP_STREAM)) { vol_label_status = VOL_OK; - create_volume_label(dev, dcr->VolumeName, "Default"); + create_volume_label(dev, dcr->VolumeName, "Default", false /* not DVD */); dev->VolHdr.LabelType = PRE_LABEL; } else { vol_label_status = read_dev_volume_label(dcr); @@ -421,7 +421,7 @@ static int try_autolabel(DCR *dcr) Dmsg0(150, "Create volume label\n"); /* Create a new Volume label and write it to the device */ if (!write_new_volume_label_to_dev(dcr, dcr->VolumeName, - dcr->pool_name)) { + dcr->pool_name, false /* defer DVD label */)) { Dmsg0(150, "!write_vol_label\n"); mark_volume_in_error(dcr); return try_next_vol; diff --git a/bacula/src/stored/protos.h b/bacula/src/stored/protos.h index 1b92dc0e94..269ba46011 100644 --- a/bacula/src/stored/protos.h +++ b/bacula/src/stored/protos.h @@ -153,8 +153,8 @@ void handle_filed_connection(BSOCK *fd, char *job_name); int read_dev_volume_label(DCR *dcr); int read_dvd_volume_label(DCR *dcr, bool write); void create_session_label(DCR *dcr, DEV_RECORD *rec, int label); -void create_volume_label(DEVICE *dev, const char *VolName, const char *PoolName); -bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, const char *PoolName); +void create_volume_label(DEVICE *dev, const char *VolName, const char *PoolName, bool dvdnow); +bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, const char *PoolName, bool dvdnow); #define ANSI_VOL_LABEL 0 #define ANSI_EOF_LABEL 1 #define ANSI_EOV_LABEL 2 diff --git a/bacula/src/version.h b/bacula/src/version.h index e29b19d39e..e929806785 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -3,9 +3,9 @@ */ #undef VERSION -#define VERSION "1.39.19" -#define BDATE "15 August 2006" -#define LSMDATE "15Aug06" +#define VERSION "1.39.20" +#define BDATE "16 August 2006" +#define LSMDATE "16Aug06" #define BYEAR "2006" /* year for copyright messages in progs */ /* Debug flags */ diff --git a/bacula/technotes-1.39 b/bacula/technotes-1.39 index a81bb4f30b..117310cf7f 100644 --- a/bacula/technotes-1.39 +++ b/bacula/technotes-1.39 @@ -1,6 +1,13 @@ Technical notes on version 1.39 General: +16Aug06 +kes If doing a mount, look for a slot, and if specified pass it to + the SD so that it can load the autochanger. +kes Return DVD=1 flag if a label command is done to a DVD. This + permits setting VolParts to 1. +kes Apply DVD patch from Richard Mortimer , but + rework ua_label code based on DVD media type to use DVD flag returned. 15Aug06 kes Eliminate some compile warnings in dird_conf.c kes Format the bytes field in the terminated jobs part of the status