From 66716ecf7c18274dc510bf316678f2c802551ead Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Sat, 2 Sep 2006 17:18:08 +0000 Subject: [PATCH] kes When doing a label, pass the VolBytes back to the Director, which puts it in the catalog. kes Print an error message if the user attempts to prune an archived Volume. kes Need to start using %ld when sscanfing 32 bit values. kes Update the free kes Correct the counting of VolCatBytes for DVDs. kes Add code to mount.c to require that VolCatBytes corresponds to what is actually found when doing an append. kes Update freespace only after writing on the DVD. kes Remove code that blows away the current part in the spool file. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@3401 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/kernstodo | 4 ++ bacula/src/dird/ua_label.c | 15 +++--- bacula/src/dird/ua_prune.c | 4 ++ bacula/src/lib/attr.c | 2 +- bacula/src/lib/bpipe.c | 2 +- bacula/src/lib/btime.c | 97 ++++++++++++++++++-------------------- bacula/src/lib/scan.c | 4 +- bacula/src/stored/askdir.c | 15 +++--- bacula/src/stored/block.c | 9 +++- bacula/src/stored/btape.c | 2 +- bacula/src/stored/dev.c | 4 +- bacula/src/stored/dircmd.c | 8 ++-- bacula/src/stored/dvd.c | 44 ++++++++++------- bacula/src/stored/label.c | 6 ++- bacula/src/stored/mount.c | 18 ++++++- bacula/src/version.h | 4 +- bacula/technotes-1.39 | 12 +++++ 17 files changed, 151 insertions(+), 99 deletions(-) diff --git a/bacula/kernstodo b/bacula/kernstodo index 5a30162551..4b5e303f54 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -33,6 +33,8 @@ Document: Priority: For 1.39: +- When reading through parts on the DVD, the DVD is mounted and + unmounted for each part. - Restricted consoles start in the Default catalog even if it is not permitted. - Make sure that the restore options don't permit "seeing" other @@ -1654,4 +1656,6 @@ Block Position: 0 - Fix ClientRunBefore/AfterJob compatibility. - Ensure that connection to daemon failure always indicates what daemon it was trying to connect to. +- Freespace on DVD requested over and over even with no intervening + writes. diff --git a/bacula/src/dird/ua_label.c b/bacula/src/dird/ua_label.c index c7d546f4b5..b60ba3df93 100644 --- a/bacula/src/dird/ua_label.c +++ b/bacula/src/dird/ua_label.c @@ -540,7 +540,7 @@ static void label_from_barcodes(UAContext *ua, int drive) */ if (is_cleaning_tape(ua, &mr, &pr)) { if (media_record_exists) { /* we update it */ - mr.VolBytes = 1; + mr.VolBytes = 1; /* any bytes to indicate it exists */ bstrncpy(mr.VolStatus, "Cleaning", sizeof(mr.VolStatus)); mr.MediaType[0] = 0; mr.StorageId = store->StorageId; @@ -630,6 +630,7 @@ static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr, char dev_name[MAX_NAME_LENGTH]; bool ok = false; bool is_dvd = false; + uint64_t VolBytes = 0; if (!(sd=open_sd_bsock(ua))) { return false; @@ -659,13 +660,13 @@ static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr, } while (bnet_recv(sd) >= 0) { + int dvd; bsendmsg(ua, "%s", sd->msg); - if (strncmp(sd->msg, "3000 OK label.", 14) == 0) { + if (sscanf(sd->msg, "3000 OK label. VolBytes=%llu DVD=%d ", &VolBytes, + &dvd) == 2) { + is_dvd = dvd; ok = true; } - if (strncmp(sd->msg, "3000 OK label. DVD=1 ", 21) == 0) { - is_dvd = true; - } } unbash_spaces(mr->VolumeName); unbash_spaces(mr->MediaType); @@ -679,7 +680,7 @@ static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr, } if (ok) { if (media_record_exists) { /* we update it */ - mr->VolBytes = 1; + mr->VolBytes = VolBytes; mr->InChanger = 1; mr->StorageId = ua->jcr->wstore->StorageId; if (!db_update_media_record(ua->jcr, ua->db, mr)) { @@ -688,7 +689,7 @@ static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr, } } else { /* create the media record */ set_pool_dbr_defaults_in_media_dbr(mr, pr); - mr->VolBytes = 1; /* flag indicating Volume labeled */ + mr->VolBytes = VolBytes; mr->InChanger = 1; mr->StorageId = ua->jcr->wstore->StorageId; mr->Enabled = 1; diff --git a/bacula/src/dird/ua_prune.c b/bacula/src/dird/ua_prune.c index dd0b8aa869..fb530d51c9 100644 --- a/bacula/src/dird/ua_prune.c +++ b/bacula/src/dird/ua_prune.c @@ -174,6 +174,10 @@ int prunecmd(UAContext *ua, const char *cmd) if (!select_pool_and_media_dbr(ua, &pr, &mr)) { return false; } + if (mr.Enabled == 2) { + bsendmsg(ua, _("Cannot prune Volume \"%s\" because it is archived.\n"), + mr.VolumeName); + } if (!confirm_retention(ua, &mr.VolRetention, "Volume")) { return false; } diff --git a/bacula/src/lib/attr.c b/bacula/src/lib/attr.c index 34a0088d94..ac509288cd 100644 --- a/bacula/src/lib/attr.c +++ b/bacula/src/lib/attr.c @@ -59,7 +59,7 @@ int unpack_attributes_record(JCR *jcr, int32_t stream, char *rec, ATTR *attr) */ attr->stream = stream; Dmsg1(400, "Attr: %s\n", rec); - if (sscanf(rec, "%d %d", &attr->file_index, &attr->type) != 2) { + if (sscanf(rec, "%ld %ld", &attr->file_index, &attr->type) != 2) { Jmsg(jcr, M_FATAL, 0, _("Error scanning attributes: %s\n"), rec); Dmsg1(100, "\nError scanning attributes. %s\n", rec); return 0; diff --git a/bacula/src/lib/bpipe.c b/bacula/src/lib/bpipe.c index 7b1535e4b0..e20a3dea73 100644 --- a/bacula/src/lib/bpipe.c +++ b/bacula/src/lib/bpipe.c @@ -247,7 +247,7 @@ int close_bpipe(BPIPE *bpipe) stop_child_timer(bpipe->timer_id); } free(bpipe); - Dmsg2(200, "returning stat=%d,%d\n", stat & ~(b_errno_exit|b_errno_signal), stat); + Dmsg2(800, "returning stat=%d,%d\n", stat & ~(b_errno_exit|b_errno_signal), stat); return stat; } diff --git a/bacula/src/lib/btime.c b/bacula/src/lib/btime.c index 79fc7578f9..7011b74a9d 100644 --- a/bacula/src/lib/btime.c +++ b/bacula/src/lib/btime.c @@ -4,22 +4,17 @@ * Version $Id$ */ /* - Copyright (C) 2000-2004 Kern Sibbald and John Walker + Copyright (C) 2000-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 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 amended 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. */ @@ -34,8 +29,8 @@ * and is 1 Jan 1970 at 0:0 UTC * * The major two times that should be left are: - * btime_t (64 bit integer in microseconds base Epoch) - * utime_t (64 bit integer in seconds base Epoch) + * btime_t (64 bit integer in microseconds base Epoch) + * utime_t (64 bit integer in seconds base Epoch) */ #include "bacula.h" @@ -111,7 +106,7 @@ utime_t str_to_utime(char *str) time_t ttime; if (sscanf(str, "%d-%d-%d %d:%d:%d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, - &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) { + &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) { return 0; } if (tm.tm_mon > 0) { @@ -168,7 +163,7 @@ utime_t btime_to_utime(btime_t bt) */ int tm_wom(int mday, int wday) { - int fs; /* first sunday */ + int fs; /* first sunday */ fs = (mday%7) - wday; if (fs <= 0) { fs += 7; @@ -234,7 +229,7 @@ void get_current_time(struct date_time *dt) } -/* date_encode -- Encode civil date as a Julian day number. */ +/* date_encode -- Encode civil date as a Julian day number. */ /* Deprecated. Do not use. */ fdate_t date_encode(uint32_t year, uint8_t month, uint8_t day) @@ -252,44 +247,44 @@ fdate_t date_encode(uint32_t year, uint8_t month, uint8_t day) y = year; if (m <= 2) { - y--; - m += 12; + y--; + m += 12; } /* Determine whether date is in Julian or Gregorian calendar based on canonical date of calendar reform. */ if ((year < 1582) || ((year == 1582) && ((month < 9) || (month == 9 && day < 5)))) { - b = 0; + b = 0; } else { - a = ((int) (y / 100)); - b = 2 - a + (a / 4); + a = ((int) (y / 100)); + b = 2 - a + (a / 4); } return (((int32_t) (365.25 * (y + 4716))) + ((int) (30.6001 * (m + 1))) + - day + b - 1524.5); + day + b - 1524.5); } /* time_encode -- Encode time from hours, minutes, and seconds - into a fraction of a day. */ + into a fraction of a day. */ /* Deprecated. Do not use. */ ftime_t time_encode(uint8_t hour, uint8_t minute, uint8_t second, - float32_t second_fraction) + float32_t second_fraction) { ASSERT((second_fraction >= 0.0) || (second_fraction < 1.0)); return (ftime_t) (((second + 60L * (minute + 60L * hour)) / 86400.0)) + - second_fraction; + second_fraction; } /* date_time_encode -- Set day number and fraction from date - and time. */ + and time. */ /* Deprecated. Do not use. */ void date_time_encode(struct date_time *dt, - uint32_t year, uint8_t month, uint8_t day, - uint8_t hour, uint8_t minute, uint8_t second, - float32_t second_fraction) + uint32_t year, uint8_t month, uint8_t day, + uint8_t hour, uint8_t minute, uint8_t second, + float32_t second_fraction) { dt->julian_day_number = date_encode(year, month, day); dt->julian_day_fraction = time_encode(hour, minute, second, second_fraction); @@ -299,7 +294,7 @@ void date_time_encode(struct date_time *dt, /* Deprecated. Do not use. */ void date_decode(fdate_t date, uint32_t *year, uint8_t *month, - uint8_t *day) + uint8_t *day) { fdate_t z, f, a, alpha, b, c, d, e; @@ -308,10 +303,10 @@ void date_decode(fdate_t date, uint32_t *year, uint8_t *month, f = date - z; if (z < 2299161.0) { - a = z; + a = z; } else { - alpha = floor((z - 1867216.25) / 36524.25); - a = z + 1 + alpha - floor(alpha / 4); + alpha = floor((z - 1867216.25) / 36524.25); + a = z + 1 + alpha - floor(alpha / 4); } b = a + 1524; @@ -328,7 +323,7 @@ void date_decode(fdate_t date, uint32_t *year, uint8_t *month, /* Deprecated. Do not use. */ void time_decode(ftime_t time, uint8_t *hour, uint8_t *minute, - uint8_t *second, float32_t *second_fraction) + uint8_t *second, float32_t *second_fraction) { uint32_t ij; @@ -337,30 +332,30 @@ void time_decode(ftime_t time, uint8_t *hour, uint8_t *minute, *minute = (uint8_t) ((ij / 60L) % 60L); *second = (uint8_t) (ij % 60L); if (second_fraction != NULL) { - *second_fraction = (float32_t)(time - floor(time)); + *second_fraction = (float32_t)(time - floor(time)); } } /* date_time_decode -- Decode a Julian day and day fraction - into civil date and time. */ + into civil date and time. */ /* Deprecated. Do not use. */ void date_time_decode(struct date_time *dt, - uint32_t *year, uint8_t *month, uint8_t *day, - uint8_t *hour, uint8_t *minute, uint8_t *second, - float32_t *second_fraction) + uint32_t *year, uint8_t *month, uint8_t *day, + uint8_t *hour, uint8_t *minute, uint8_t *second, + float32_t *second_fraction) { date_decode(dt->julian_day_number, year, month, day); time_decode(dt->julian_day_fraction, hour, minute, second, second_fraction); } /* tm_encode -- Encode a civil date and time from a tm structure - * to a Julian day and day fraction. + * to a Julian day and day fraction. */ /* Deprecated. Do not use. */ void tm_encode(struct date_time *dt, - struct tm *tm) + struct tm *tm) { uint32_t year; uint8_t month, day, hour, minute, second; @@ -377,11 +372,11 @@ void tm_encode(struct date_time *dt, /* tm_decode -- Decode a Julian day and day fraction - into civil date and time in tm structure */ + into civil date and time in tm structure */ /* Deprecated. Do not use. */ void tm_decode(struct date_time *dt, - struct tm *tm) + struct tm *tm) { uint32_t year; uint8_t month, day, hour, minute, second; @@ -398,21 +393,21 @@ void tm_decode(struct date_time *dt, /* date_time_compare -- Compare two dates and times and return - the relationship as follows: + the relationship as follows: - -1 dt1 < dt2 - 0 dt1 = dt2 - 1 dt1 > dt2 + -1 dt1 < dt2 + 0 dt1 = dt2 + 1 dt1 > dt2 */ /* Deprecated. Do not use. */ int date_time_compare(struct date_time *dt1, struct date_time *dt2) { if (dt1->julian_day_number == dt2->julian_day_number) { - if (dt1->julian_day_fraction == dt2->julian_day_fraction) { - return 0; - } - return (dt1->julian_day_fraction < dt2->julian_day_fraction) ? -1 : 1; + if (dt1->julian_day_fraction == dt2->julian_day_fraction) { + return 0; + } + return (dt1->julian_day_fraction < dt2->julian_day_fraction) ? -1 : 1; } return (dt1->julian_day_number - dt2->julian_day_number) ? -1 : 1; } diff --git a/bacula/src/lib/scan.c b/bacula/src/lib/scan.c index 53c4024210..5e9403fd54 100644 --- a/bacula/src/lib/scan.c +++ b/bacula/src/lib/scan.c @@ -339,7 +339,9 @@ switch_top: } vp = (void *)va_arg(ap, void *); // Dmsg2(000, "val=%lld at 0x%lx\n", value, (long unsigned)vp); - if (l < 2) { + if (l == 0) { + *((int *)vp) = (int)value; + } else if (l == 1) { *((uint32_t *)vp) = (uint32_t)value; // Dmsg0(000, "Store 32 bit int\n"); } else { diff --git a/bacula/src/stored/askdir.c b/bacula/src/stored/askdir.c index be5411e3cf..54e125d92c 100644 --- a/bacula/src/stored/askdir.c +++ b/bacula/src/stored/askdir.c @@ -41,12 +41,12 @@ static char Job_status[] = "Status Job=%s JobStatus=%d\n"; /* Responses received from the Director */ -static char OK_media[] = "1000 OK VolName=%127s VolJobs=%u VolFiles=%u" - " VolBlocks=%u VolBytes=%" lld " VolMounts=%u VolErrors=%u VolWrites=%u" - " MaxVolBytes=%" lld " VolCapacityBytes=%" lld " VolStatus=%20s" - " Slot=%d MaxVolJobs=%u MaxVolFiles=%u InChanger=%d" - " VolReadTime=%" lld " VolWriteTime=%" lld " EndFile=%u EndBlock=%u" - " VolParts=%u LabelType=%d"; +static char OK_media[] = "1000 OK VolName=%127s VolJobs=%u VolFiles=%lu" + " VolBlocks=%lu VolBytes=%lld VolMounts=%lu VolErrors=%lu VolWrites=%lu" + " MaxVolBytes=%lld VolCapacityBytes=%lld VolStatus=%20s" + " Slot=%ld MaxVolJobs=%lu MaxVolFiles=%lu InChanger=%ld" + " VolReadTime=%lld VolWriteTime=%lld EndFile=%lu EndBlock=%lu" + " VolParts=%lu LabelType=%ld"; static char OK_create[] = "1000 OK CreateJobMedia\n"; @@ -153,7 +153,7 @@ static bool do_get_volume_info(DCR *dcr) BSOCK *dir = jcr->dir_bsock; VOLUME_CAT_INFO vol; int n; - int InChanger; + int32_t InChanger; dcr->VolumeName[0] = 0; /* No volume */ if (bnet_recv(dir) <= 0) { @@ -302,7 +302,6 @@ bool dir_update_volume_info(DCR *dcr, bool label) /* Just labeled or relabeled the tape */ if (label) { bstrncpy(vol->VolCatStatus, "Append", sizeof(vol->VolCatStatus)); - vol->VolCatBytes = 1; /* indicates tape labeled */ } pm_strcpy(VolumeName, vol->VolCatName); bash_spaces(VolumeName); diff --git a/bacula/src/stored/block.c b/bacula/src/stored/block.c index 69f9ab616b..2c5f5c9ff9 100644 --- a/bacula/src/stored/block.c +++ b/bacula/src/stored/block.c @@ -570,8 +570,9 @@ bool write_block_to_dev(DCR *dcr) } /* We successfully wrote the block, now do housekeeping */ - - dev->VolCatInfo.VolCatBytes += block->binbuf; + Dmsg2(400, "VolCatBytes=%d newVolCatBytes=%d\n", (int)dev->VolCatInfo.VolCatBytes, + (int)(dev->VolCatInfo.VolCatBytes+wlen)); + dev->VolCatInfo.VolCatBytes += wlen; dev->VolCatInfo.VolCatBlocks++; dev->EndBlock = dev->block_num; dev->EndFile = dev->file; @@ -836,6 +837,10 @@ static bool do_dvd_size_checks(DCR *dcr) return false; } } + + if (!dev->is_freespace_ok()) { + update_free_space_dev(dev); + } if (!dev->is_freespace_ok()) { /* Error while getting free space */ char ed1[50], ed2[50]; diff --git a/bacula/src/stored/btape.c b/bacula/src/stored/btape.c index 6fe9210bad..f3c4b4d55e 100644 --- a/bacula/src/stored/btape.c +++ b/bacula/src/stored/btape.c @@ -167,7 +167,7 @@ int main(int margc, char *margv[]) } x32 = 123456789; bsnprintf(buf, sizeof(buf), "%u", x32); - i = bsscanf(buf, "%u", &y32); + i = bsscanf(buf, "%lu", &y32); if (i != 1 || x32 != y32) { Pmsg3(-1, _("32 bit printf/scanf problem. i=%d x32=%u y32=%u\n"), i, x32, y32); exit(1); diff --git a/bacula/src/stored/dev.c b/bacula/src/stored/dev.c index 1cdf259efc..2ba6fa455f 100644 --- a/bacula/src/stored/dev.c +++ b/bacula/src/stored/dev.c @@ -1783,12 +1783,12 @@ void DEVICE::close() int status; part = num_dvd_parts; - Dmsg3(100, "Remove empty part in close call make_dvd_filename. part=%d num=%d vol=%s\n", - part, num_dvd_parts, VolCatInfo.VolCatName); make_spooled_dvd_filename(this, archive_name); /* Check that the part file is empty */ status = stat(archive_name.c_str(), &statp); if (status == 0 && statp.st_size == 0) { + Dmsg3(100, "Unlink empty part in close call make_dvd_filename. part=%d num=%d vol=%s\n", + part, num_dvd_parts, VolCatInfo.VolCatName); Dmsg1(100, "unlink(%s)\n", archive_name.c_str()); unlink(archive_name.c_str()); set_part_spooled(false); /* no spooled part left */ diff --git a/bacula/src/stored/dircmd.c b/bacula/src/stored/dircmd.c index 877b4b01b2..eb8fb36718 100644 --- a/bacula/src/stored/dircmd.c +++ b/bacula/src/stored/dircmd.c @@ -391,13 +391,14 @@ static void label_volume_if_ok(DCR *dcr, char *oldname, int label_status; int mode; const char *volname = (relabel == 0) ? newname : oldname; + char ed1[50]; steal_device_lock(dev, &hold, BST_WRITING_LABEL); Dmsg1(100, "Stole device %s lock, writing label.\n", dev->print_name()); Dmsg0(90, "try_autoload_device - looking for volume_info\n"); if (relabel && dev->is_dvd()) { - dcr->VolCatInfo.VolCatParts=1; + dcr->VolCatInfo.VolCatParts=0; } if (!try_autoload_device(dcr->jcr, slot, volname)) { @@ -462,8 +463,9 @@ static void label_volume_if_ok(DCR *dcr, char *oldname, } 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. DVD=%d Volume=\"%s\" Device=\"%s\"\n", - dev->is_dvd()?1:0, newname, dev->print_name()); + bnet_fsend(dir, "3000 OK label. VolBytes=%s DVD=%d Volume=\"%s\" Device=%s\n", + edit_uint64(dev->VolCatInfo.VolCatBytes, ed1), + 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()); diff --git a/bacula/src/stored/dvd.c b/bacula/src/stored/dvd.c index 6c826ba4c3..bfa47a4a0b 100644 --- a/bacula/src/stored/dvd.c +++ b/bacula/src/stored/dvd.c @@ -138,7 +138,7 @@ static bool do_mount_dvd(DEVICE* dev, int mount, int dotimeout) Dmsg1(20, "Run mount prog=%s\n", ocmd.c_str()); while ((status = run_program_full_output(ocmd.c_str(), dev->max_open_wait/2, results)) != 0) { - Dmsg2(99, "Mount status=%d result=%s\n", status, results); + Dmsg2(20, "Mount status=%d result=%s\n", status, results); /* Doesn't work with internationalization (This is not a problem) */ if (mount && fnmatch("*is already mounted on*", results, 0) == 0) { break; @@ -261,6 +261,10 @@ bool update_free_space_dev(DEVICE* dev) char ed1[50]; bool ok = false; int status; + + if (!dev->is_dvd() || dev->is_freespace_ok()) { + return true; + } /* The device must be mounted in order to dvd-freespace to work */ mount_dvd(dev, 1); @@ -271,7 +275,7 @@ bool update_free_space_dev(DEVICE* dev) if (!icmd) { dev->free_space = 0; dev->free_space_errno = 0; - dev->clear_freespace_ok(); /* No valid freespace */ + dev->clear_freespace_ok(); /* No valid freespace */ dev->clear_media(); Dmsg2(29, "ERROR: update_free_space_dev: free_space=%s, free_space_errno=%d (!icmd)\n", edit_uint64(dev->free_space, ed1), dev->free_space_errno); @@ -292,6 +296,7 @@ bool update_free_space_dev(DEVICE* dev) berrno be; Dmsg1(20, "Run freespace prog=%s\n", ocmd.c_str()); status = run_program_full_output(ocmd.c_str(), dev->max_open_wait/2, results); + Dmsg2(20, "Freespace status=%d result=%s\n", status, results); if (status == 0) { free = str_to_int64(results); Dmsg1(400, "Free space program run: Freespace=%s\n", results); @@ -352,6 +357,8 @@ bool dvd_write_part(DCR *dcr) DEVICE *dev = dcr->dev; POOL_MEM archive_name(PM_FNAME); + dev->clear_freespace_ok(); /* need to update freespace */ + /* Don't write empty part files. * This is only useful when growisofs does not support write beyond * the 4GB boundary. @@ -409,14 +416,17 @@ bool dvd_write_part(DCR *dcr) * in case of a serious emergency. */ - if (dev->part == 1) + if (dev->part == 1) { timeout = 16000; - else + } else { timeout = dev->max_open_wait + (dev->part_size/(1350*1024/4)); + } - Dmsg2(20, "dvd_write_part: cmd=%s timeout=%d\n", ocmd.c_str(), timeout); + Dmsg2(20, "Write part: cmd=%s timeout=%d\n", ocmd.c_str(), timeout); status = run_program_full_output(ocmd.c_str(), timeout, results.c_str()); + Dmsg2(20, "Write part status=%d result=%s\n", status, results.c_str()); + dev->truncated_dvd = false; if (status != 0) { Jmsg2(dcr->jcr, M_FATAL, 0, _("Error writing part %d to the DVD: ERR=%s\n"), dev->part, results.c_str()); @@ -426,19 +436,15 @@ bool dvd_write_part(DCR *dcr) dev->dev_errno = EIO; mark_volume_in_error(dcr); sm_check(__FILE__, __LINE__, false); - dev->truncated_dvd = false; return false; } Jmsg(dcr->jcr, M_INFO, 0, _("Part %d written to DVD.\n"), dev->part); Dmsg2(400, "dvd_write_part: Part %d written to DVD\nResults: %s\n", dev->part, results.c_str()); - if (dev->truncated_dvd) { - dev->truncated_dvd = false; /* turn off flag */ - } else { /* DVD part written */ - dev->num_dvd_parts++; /* there is now one more part on DVD */ - dev->VolCatInfo.VolCatParts = dev->num_dvd_parts; - } + dev->num_dvd_parts++; /* there is now one more part on DVD */ + dev->VolCatInfo.VolCatParts = dev->num_dvd_parts; + Dmsg1(000, "Update num_parts=%d\n", dev->num_dvd_parts); /* Delete spool file */ make_spooled_dvd_filename(dev, archive_name); @@ -507,6 +513,7 @@ int dvd_open_next_part(DCR *dcr) dev->part++; Dmsg2(29, "Inc part=%d num_dvd_parts=%d\n", dev->part, dev->num_dvd_parts); + /* Are we working on a part past what is written in the DVD? */ if (dev->num_dvd_parts < dev->part) { POOL_MEM archive_name(PM_FNAME); struct stat buf; @@ -514,7 +521,7 @@ int dvd_open_next_part(DCR *dcr) * First check what is on DVD. If our part is there, we * are in trouble, so bail out. * NB: This is however not a problem if we are writing the first part. - * It simply means that we are overriding an existing volume... + * It simply means that we are over writing an existing volume... */ if (dev->num_dvd_parts > 0) { make_mounted_dvd_filename(dev, archive_name); /* makes dvd name */ @@ -527,13 +534,14 @@ int dvd_open_next_part(DCR *dcr) } } +#ifdef neeeded Dmsg2(400, "num_dvd_parts=%d part=%d\n", dev->num_dvd_parts, dev->part); make_spooled_dvd_filename(dev, archive_name); /* makes spool name */ /* Check if the next part exists in spool directory . */ - Dmsg1(100, "Check if part on spool: $s\n", archive_name.c_str()); + Dmsg1(100, "Check if part on spool: %s\n", archive_name.c_str()); if ((stat(archive_name.c_str(), &buf) == 0) || (errno != ENOENT)) { - Dmsg1(29, "open_next_part %s is in the way, deleting it...\n", archive_name.c_str()); + Dmsg1(29, "======= Part %s is in the way, deleting it...\n", archive_name.c_str()); /* Then try to unlink it */ if (unlink(archive_name.c_str()) < 0) { berrno be; @@ -543,6 +551,7 @@ int dvd_open_next_part(DCR *dcr) return -1; } } +#endif } Dmsg2(400, "Call dev->open(vol=%s, mode=%d)\n", dcr->VolCatInfo.VolCatName, @@ -740,7 +749,8 @@ bool dvd_close_job(DCR *dcr) JCR *jcr = dcr->jcr; bool ok = true; - /* If the device is a dvd and WritePartAfterJob + /* + * If the device is a dvd and WritePartAfterJob * is set to yes, open the next part, so, in case of a device * that requires mount, it will be written to the device. */ @@ -853,7 +863,7 @@ bool check_can_write_on_non_blank_dvd(DCR *dcr) struct dirent *entry, *result; int name_max; int count = 0; - bool matched = false; + bool matched = true; struct stat filestat; name_max = pathconf(".", _PC_NAME_MAX); diff --git a/bacula/src/stored/label.c b/bacula/src/stored/label.c index b51ec45661..0e18e92ea4 100644 --- a/bacula/src/stored/label.c +++ b/bacula/src/stored/label.c @@ -399,6 +399,9 @@ bool rewrite_volume_label(DCR *dcr, bool recycle) Dmsg0(200, "Error from write volume label.\n"); return false; } + + dev->VolCatInfo.VolCatBytes = 0; /* reset byte count */ + /* * If we are not dealing with a streaming device, * write the block now to ensure we have write permission. @@ -446,7 +449,6 @@ bool rewrite_volume_label(DCR *dcr, bool recycle) /* Set or reset Volume statistics */ dev->VolCatInfo.VolCatJobs = 0; dev->VolCatInfo.VolCatFiles = 0; - dev->VolCatInfo.VolCatBytes = 1; dev->VolCatInfo.VolCatErrors = 0; dev->VolCatInfo.VolCatBlocks = 0; dev->VolCatInfo.VolCatRBytes = 0; @@ -558,7 +560,7 @@ void create_volume_label(DEVICE *dev, const char *VolName, bstrncpy(dev->VolHdr.Id, BaculaId, sizeof(dev->VolHdr.Id)); dev->VolHdr.VerNum = BaculaTapeVersion; - if (dev->is_dvd()) { + if (dvdnow) { /* We do not want to re-label a DVD so write VOL_LABEL now */ dev->VolHdr.LabelType = VOL_LABEL; } else { diff --git a/bacula/src/stored/mount.c b/bacula/src/stored/mount.c index 83494eb715..61443a6e7f 100644 --- a/bacula/src/stored/mount.c +++ b/bacula/src/stored/mount.c @@ -339,6 +339,22 @@ read_volume: mark_volume_in_error(dcr); goto mount_next_vol; } + if (dev->is_dvd()) { + char ed1[50], ed2[50]; + if (dev->VolCatInfo.VolCatBytes == dev->part_start + dev->part_size) { + Jmsg(jcr, M_INFO, 0, _("Ready to append to end of Volume \"%s\"" + " part=%d size=%s\n"), dcr->VolumeName, + dev->part, edit_uint64(dev->VolCatInfo.VolCatBytes,ed1)); + } else { + Jmsg(jcr, M_ERROR, 0, _("I cannot write on Volume \"%s\" because: " + "The sizes do not match! Volume=%s Catalog=%s\n"), + dcr->VolumeName, + edit_uint64(dev->part_start + dev->part_size, ed1), + edit_uint64(dev->VolCatInfo.VolCatBytes, ed2)); + mark_volume_in_error(dcr); + goto mount_next_vol; + } + } /* *****FIXME**** we should do some checking for files too */ if (dev->is_tape()) { /* @@ -350,7 +366,7 @@ read_volume: dcr->VolumeName, dev_file(dev)); } else { Jmsg(jcr, M_ERROR, 0, _("I cannot write on Volume \"%s\" because:\n" -"The number of files mismatch! Volume=%u Catalog=%u\n"), + "The number of files mismatch! Volume=%u Catalog=%u\n"), dcr->VolumeName, dev_file(dev), dev->VolCatInfo.VolCatFiles); mark_volume_in_error(dcr); goto mount_next_vol; diff --git a/bacula/src/version.h b/bacula/src/version.h index a4a6aa51df..b15923ae6d 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -4,8 +4,8 @@ #undef VERSION #define VERSION "1.39.21" -#define BDATE "01 Septermber 2006" -#define LSMDATE "01Sep06" +#define BDATE "02 Septermber 2006" +#define LSMDATE "02Sep06" #define BYEAR "2006" /* year for copyright messages in progs */ /* Debug flags */ diff --git a/bacula/technotes-1.39 b/bacula/technotes-1.39 index 76063d427d..c35abe0968 100644 --- a/bacula/technotes-1.39 +++ b/bacula/technotes-1.39 @@ -1,6 +1,18 @@ Technical notes on version 1.39 General: +02Sep06 +kes When doing a label, pass the VolBytes back to the Director, + which puts it in the catalog. +kes Print an error message if the user attempts to prune an + archived Volume. +kes Need to start using %ld when sscanfing 32 bit values. +kes Update the free +kes Correct the counting of VolCatBytes for DVDs. +kes Add code to mount.c to require that VolCatBytes corresponds to + what is actually found when doing an append. +kes Update freespace only after writing on the DVD. +kes Remove code that blows away the current part in the spool file. 01Sep06 kes Apply new dvd-handler patch from Richard Mortimer. kes Tweak so that debug level 20 shows only DVD commands. -- 2.39.5