From: Kern Sibbald Date: Mon, 11 Sep 2006 21:11:03 +0000 (+0000) Subject: kes Modify disk changer to simulate some of the error conditions X-Git-Tag: Release-2.0.0~460 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=0df1b05ab644fac295d2ea6f2e2f1c977fa19a87;p=bacula%2Fbacula kes Modify disk changer to simulate some of the error conditions of mtx-changer. kes Make sure the close() call in the SD tools is just before the getchar() call. kes Implement dir_get_volume_info() in bls using the patch from Richard Mortimer but call find_num_dvd_parts(). kes Implement find_num_dvd_parts() that mounts and scans a DVD and counts the parts. kes Move the omode code in open_dvd() up so that the cannot write on blank disk can check can be bypassed for read mode. Not yet implemented. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@3457 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/scripts/disk-changer.in b/bacula/scripts/disk-changer.in index 94c5682f4d..85de7bf1de 100644 --- a/bacula/scripts/disk-changer.in +++ b/bacula/scripts/disk-changer.in @@ -164,23 +164,39 @@ case $cmd in unload) debug "Doing disk -f $ctl unload $slot $device $drive" get_dir - echo "0" >$dir/loaded${drive} - unlink $device 2>/dev/null >/dev/null - rm -f $device + ld=`cat $dir/loaded${drive}` + if [ $slot -eq $ld ]; then + echo "0" >$dir/loaded${drive} + unlink $device 2>/dev/null >/dev/null + rm -f $device + else + echo "Storage Element $slot is Already Full" + exit 1 + fi ;; load) debug "Doing disk $ctl load $slot $device $drive" get_dir - echo "0" >$dir/loaded${drive} - unlink $device 2>/dev/null >/dev/null - rm -f $device - ln -s $dir/slot${slot} $device - rtn=$? - if [ $rtn -eq 0 ]; then - echo $slot >$dir/loaded${drive} + if [ -f $dir/loaded${drive} ]; then + ld=`cat $dir/loaded${drive}` + else + ld=0 + fi + if [ $ld -eq 0 ]; then + echo "0" >$dir/loaded${drive} + unlink $device 2>/dev/null >/dev/null + rm -f $device + ln -s $dir/slot${slot} $device + rtn=$? + if [ $rtn -eq 0 ]; then + echo $slot >$dir/loaded${drive} + fi + exit $rtn + else + echo "Drive ${drive} Full (Storage element ${ld} loaded)" + exit 1 fi - exit $rtn ;; list) diff --git a/bacula/src/stored/bextract.c b/bacula/src/stored/bextract.c index 8251f90e61..e64fe47136 100644 --- a/bacula/src/stored/bextract.c +++ b/bacula/src/stored/bextract.c @@ -472,6 +472,7 @@ bool dir_ask_sysop_to_mount_volume(DCR *dcr) DEVICE *dev = dcr->dev; fprintf(stderr, _("Mount Volume \"%s\" on device %s and press return when ready: "), dcr->VolumeName, dev->print_name()); + dev->close(); getchar(); return true; } diff --git a/bacula/src/stored/bls.c b/bacula/src/stored/bls.c index 5d671f232d..bdc20604dc 100644 --- a/bacula/src/stored/bls.c +++ b/bacula/src/stored/bls.c @@ -421,7 +421,6 @@ static void get_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sess /* Dummies to replace askdir.c */ -bool dir_get_volume_info(DCR *dcr, enum get_vol_info_rw writing) { return 1;} bool dir_find_next_appendable_volume(DCR *dcr) { return 1;} bool dir_update_volume_info(DCR *dcr, bool relabel) { return 1; } bool dir_create_jobmedia_record(DCR *dcr) { return 1; } @@ -436,6 +435,16 @@ bool dir_ask_sysop_to_mount_volume(DCR *dcr) DEVICE *dev = dcr->dev; fprintf(stderr, _("Mount Volume \"%s\" on device %s and press return when ready: "), dcr->VolumeName, dev->print_name()); + dev->close(); getchar(); return true; } + +bool dir_get_volume_info(DCR *dcr, enum get_vol_info_rw writing) +{ + Dmsg0(100, "Fake dir_get_volume_info\n"); + bstrncpy(dcr->VolCatInfo.VolCatName, dcr->VolumeName, sizeof(dcr->VolCatInfo.VolCatName)); + dcr->VolCatInfo.VolCatParts = find_num_dvd_parts(dcr); + Dmsg2(500, "Vol=%s num_parts=%d\n", dcr->VolCatInfo.VolCatName, dcr->VolCatInfo.VolCatParts); + return 1; +} diff --git a/bacula/src/stored/bscan.c b/bacula/src/stored/bscan.c index 735ddc11c9..7b4061554a 100644 --- a/bacula/src/stored/bscan.c +++ b/bacula/src/stored/bscan.c @@ -1263,9 +1263,9 @@ bool dir_ask_sysop_to_mount_volume(DCR *dcr) DEVICE *dev = dcr->dev; Dmsg0(20, "Enter dir_ask_sysop_to_mount_volume\n"); /* Close device so user can use autochanger if desired */ - dev->close(); fprintf(stderr, _("Mount Volume \"%s\" on device %s and press return when ready: "), dcr->VolumeName, dev->print_name()); + dev->close(); getchar(); return true; } diff --git a/bacula/src/stored/btape.c b/bacula/src/stored/btape.c index f3c4b4d55e..10b64c4377 100644 --- a/bacula/src/stored/btape.c +++ b/bacula/src/stored/btape.c @@ -2687,7 +2687,6 @@ bool dir_ask_sysop_to_mount_volume(DCR *dcr) if (dcr->VolumeName[0] == 0) { return dir_ask_sysop_to_create_appendable_volume(dcr); } - dev->close(); Pmsg1(-1, "%s", dev->errmsg); /* print reason */ if (dcr->VolumeName[0] == 0 || strcmp(dcr->VolumeName, "TestVolume2") == 0) { fprintf(stderr, _("Mount second Volume on device %s and press return when ready: "), @@ -2696,6 +2695,7 @@ bool dir_ask_sysop_to_mount_volume(DCR *dcr) fprintf(stderr, _("Mount Volume \"%s\" on device %s and press return when ready: "), dcr->VolumeName, dev->print_name()); } + dev->close(); getchar(); return true; } @@ -2716,9 +2716,9 @@ bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) } autochanger = autoload_device(dcr, 1, NULL); if (!autochanger) { - dev->close(); fprintf(stderr, _("Mount blank Volume on device %s and press return when ready: "), dev->print_name()); + dev->close(); getchar(); } open_device(dcr); diff --git a/bacula/src/stored/dev.c b/bacula/src/stored/dev.c index a4dc847733..331e7a5faa 100644 --- a/bacula/src/stored/dev.c +++ b/bacula/src/stored/dev.c @@ -518,6 +518,23 @@ void DEVICE::open_dvd_device(DCR *dcr, int omode) if (num_dvd_parts != VolCatInfo.VolCatParts) { num_dvd_parts = VolCatInfo.VolCatParts; } + + /* + * If we are not trying to access the last part, set mode to + * OPEN_READ_ONLY as writing would be an error. + */ + Dmsg2(29, "open DVD part=%d num_dvd_parts=%d\n", part, num_dvd_parts); + if (part <= num_dvd_parts) { + omode = OPEN_READ_ONLY; + make_mounted_dvd_filename(this, archive_name); + set_part_spooled(false); + } else { + omode = OPEN_READ_WRITE; + make_spooled_dvd_filename(this, archive_name); + set_part_spooled(true); + } + set_mode(omode); + // Clear any previous truncated_dvd status - we will recalculate it here truncated_dvd = false; @@ -574,21 +591,6 @@ void DEVICE::open_dvd_device(DCR *dcr, int omode) openmode = omode; Dmsg2(100, "openmode=%d %s\n", openmode, mode_to_str(openmode)); - /* - * If we are not trying to access the last part, set mode to - * OPEN_READ_ONLY as writing would be an error. - */ - Dmsg2(29, "open DVD part=%d num_dvd_parts=%d\n", part, num_dvd_parts); - if (part <= num_dvd_parts) { - omode = OPEN_READ_ONLY; - make_mounted_dvd_filename(this, archive_name); - set_part_spooled(false); - } else { - omode = OPEN_READ_WRITE; - make_spooled_dvd_filename(this, archive_name); - set_part_spooled(true); - } - set_mode(omode); /* If creating file, give 0640 permissions */ Dmsg3(29, "mode=%s open(%s, 0x%x, 0640)\n", mode_to_str(omode), diff --git a/bacula/src/stored/dvd.c b/bacula/src/stored/dvd.c index 96eca5b32d..beb9c7de71 100644 --- a/bacula/src/stored/dvd.c +++ b/bacula/src/stored/dvd.c @@ -904,3 +904,76 @@ bool check_can_write_on_non_blank_dvd(DCR *dcr) Dmsg2(29, "OK can_write_on_non_blank_dvd: got %d files in the mount point (matched=%d)\n", count, matched); return matched; } + +/* + * Mount a DVD device, then scan to find out how many parts + * there are. + */ +int find_num_dvd_parts(DCR *dcr) +{ + DEVICE *dev = dcr->dev; + int num_parts = 0; + + if (!dev->is_dvd()) { + return 0; + } + + if (dev->mount(1)) { + DIR* dp; + struct dirent *entry, *result; + int name_max; + int len = strlen(dcr->VolCatInfo.VolCatName); + + /* Now count the number of parts */ + name_max = pathconf(".", _PC_NAME_MAX); + if (name_max < 1024) { + name_max = 1024; + } + + if (!(dp = opendir(dev->device->mount_point))) { + berrno be; + dev->dev_errno = errno; + Dmsg3(29, "find_num_dvd_parts: failed to open dir %s (dev=%s), ERR=%s\n", + dev->device->mount_point, dev->print_name(), be.strerror()); + goto get_out; + } + + entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 1000); + + Dmsg1(100, "Looking for Vol=%s\n", dcr->VolCatInfo.VolCatName); + for ( ;; ) { + int flen; + bool ignore; + if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) { + dev->dev_errno = EIO; + Dmsg2(129, "find_num_dvd_parts: failed to find suitable file in dir %s (dev=%s)\n", + dev->device->mount_point, dev->print_name()); + break; + } + flen = strlen(result->d_name); + ignore = true; + if (flen >= len) { + result->d_name[len] = 0; + if (strcmp(dcr->VolCatInfo.VolCatName, result->d_name) == 0) { + num_parts++; + Dmsg1(100, "find_num_dvd_parts: found part: %s\n", result->d_name); + ignore = false; + } + } + if (ignore) { + Dmsg2(129, "find_num_dvd_parts: ignoring %s in %s\n", + result->d_name, dev->device->mount_point); + } + } + free(entry); + closedir(dp); + Dmsg1(29, "find_num_dvd_parts = %d\n", num_parts); + } + +get_out: + dev->set_freespace_ok(); + if (dev->is_mounted()) { + dev->unmount(0); + } + return num_parts; +} diff --git a/bacula/src/stored/protos.h b/bacula/src/stored/protos.h index 1b9cf9d078..10b82cf1d8 100644 --- a/bacula/src/stored/protos.h +++ b/bacula/src/stored/protos.h @@ -119,6 +119,7 @@ void make_mounted_dvd_filename(DEVICE *dev, POOL_MEM &archive_name); void make_spooled_dvd_filename(DEVICE *dev, POOL_MEM &archive_name); bool truncate_dvd(DCR *dcr); bool check_can_write_on_non_blank_dvd(DCR *dcr); +int find_num_dvd_parts(DCR *dcr); /* From device.c */ bool open_device(DCR *dcr); diff --git a/bacula/technotes-1.39 b/bacula/technotes-1.39 index 2a0712a7a8..811d2e2bdd 100644 --- a/bacula/technotes-1.39 +++ b/bacula/technotes-1.39 @@ -1,6 +1,18 @@ Technical notes on version 1.39 General: +11Sep06 +kes Modify disk changer to simulate some of the error conditions + of mtx-changer. +kes Make sure the close() call in the SD tools is just before the + getchar() call. +kes Implement dir_get_volume_info() in bls using the patch from + Richard Mortimer but call find_num_dvd_parts(). +kes Implement find_num_dvd_parts() that mounts and scans a DVD + and counts the parts. +kes Move the omode code in open_dvd() up so that the cannot + write on blank disk can check can be bypassed for read mode. + Not yet implemented. 10Sep06 kes Disable normal data spooling for DVD writing which uses a different spooling mechanism.