dev->device->mount_point, dev->print_name());
break;
}
- count++;
+ if ((strcmp(result->d_name, ".")) && (strcmp(result->d_name, "..")) && (strcmp(result->d_name, ".keep"))) {
+ count++; /* result->d_name != ., .. or .keep (Gentoo-specific) */
+ }
+ else {
+ Dmsg2(129, "open_mounted_dev: ignoring %s in %s\n",
+ result->d_name, dev->device->mount_point);
+ }
}
free(entry);
closedir(dp);
- Dmsg1(29, "open_mounted_dev: got %d files in the mount point\n", count);
+ Dmsg1(29, "open_mounted_dev: got %d files in the mount point (not counting ., .. and .keep)\n", count);
- if (count > 2) {
- mount = 1; /* If we got more than . and .. */
+ if (count > 0) {
+ mount = 1; /* If we got more than ., .. and .keep */
break; /* there must be something mounted */
}
get_out:
dev->set_mounted(mount); /* set/clear mounted flag */
free_pool_memory(results);
- /* Do not check free space when unmounting (otherwise it will mount it again) */
+ /* Do not check free space when unmounting */
if (mount) {
update_free_space_dev(dev);
}
bool dvd_write_part(DCR *dcr)
{
DEVICE *dev = dcr->dev;
+ POOL_MEM archive_name(PM_FNAME);
+
+ /* Don't write empty part files.
+ * This is only useful when growisofs does not support write beyond
+ * the 4GB boundary.
+ * Example :
+ * - 3.9 GB on the volume, dvd-freespace reports 0.4 GB free
+ * - Write 0.2 GB on the volume, Bacula thinks it could still
+ * append data, it creates a new empty part.
+ * - dvd-freespace reports 0 GB free, as the 4GB boundary has
+ * been crossed
+ * - Bacula thinks he must finish to write to the device, so it
+ * tries to write the last part (0-byte), but dvd-writepart fails...
+ *
+ * There is one exception: when recycling a volume, we write a blank part
+ * file, so, then, we need to accept to write it.
+ */
+ if ((dev->part_size == 0) && (dev->part > 0)) {
+ Dmsg2(29, "dvd_write_part: device is %s, won't write blank part %d\n", dev->print_name(), dev->part);
+ /* Delete spool file */
+ make_spooled_dvd_filename(dev, archive_name);
+ unlink(archive_name.c_str());
+ Dmsg1(29, "unlink(%s)\n", archive_name.c_str());
+ sm_check(__FILE__, __LINE__, false);
+ return true;
+ }
+
POOL_MEM ocmd(PM_FNAME);
+ POOL_MEM results(PM_MESSAGE);
char* icmd;
int status;
int timeout;
* I modified this for a longer timeout; pre-formatting, blanking and
* writing can take quite a while
*/
- timeout = dev->max_open_wait + (dev->max_part_size/(1350*1024)*8);
+
+ /* Explanation of the timeout value, when writing the first part,
+ * by Arno Lehmann :
+ * 9 GB, write speed 1x: 6990 seconds (almost 2 hours...)
+ * Overhead: 900 seconds (starting, initializing, finalizing,probably
+ * reloading 15 minutes)
+ * Sum: 15780.
+ * A reasonable last-exit timeout would be 16000 seconds. Quite long -
+ * almost 4.5 hours, but hopefully, that timeout will only ever be needed
+ * in case of a serious emergency.
+ */
+
+ if (dev->part == 0)
+ timeout = 16000;
+ else
+ timeout = dev->max_open_wait + (dev->part_size/(1350*1024/4));
Dmsg2(29, "dvd_write_part: cmd=%s timeout=%d\n", ocmd.c_str(), timeout);
- {
- POOL_MEM results(PM_MESSAGE);
- sm_check(__FILE__, __LINE__, false);
- status = run_program_full_output(ocmd.c_str(), timeout, results.c_str());
- sm_check(__FILE__, __LINE__, false);
- if (status != 0) {
- Mmsg1(dev->errmsg, _("Error while writing current part to the DVD: %s"),
- results.c_str());
- Dmsg1(000, "%s", dev->errmsg);
- dev->dev_errno = EIO;
- mark_volume_in_error(dcr);
- return false;
- }
+ status = run_program_full_output(ocmd.c_str(), timeout, results.c_str());
+ if (status != 0) {
+ Mmsg1(dev->errmsg, _("Error while writing current part to the DVD: %s"),
+ results.c_str());
+ Dmsg1(000, "%s", dev->errmsg);
+ dev->dev_errno = EIO;
+ mark_volume_in_error(dcr);
sm_check(__FILE__, __LINE__, false);
+ return false;
+ } else {
+ dev->num_parts++; /* there is now one more part on DVD */
}
- {
- POOL_MEM archive_name(PM_FNAME);
- /* Delete spool file */
- make_spooled_dvd_filename(dev, archive_name);
- unlink(archive_name.c_str());
- Dmsg1(29, "unlink(%s)\n", archive_name.c_str());
- sm_check(__FILE__, __LINE__, false);
- }
+ /* Delete spool file */
+ make_spooled_dvd_filename(dev, archive_name);
+ unlink(archive_name.c_str());
+ Dmsg1(29, "unlink(%s)\n", archive_name.c_str());
+ sm_check(__FILE__, __LINE__, false);
/* growisofs umounted the device, so remount it (it will update the free space) */
dev->clear_mounted();
*/
if (dev->is_dvd() && (dev->part >= dev->num_parts) && dev->can_append()) {
if (!dvd_write_part(dcr)) {
+ Dmsg0(29, "Error in dvd_write part.\n");
return -1;
}
}
}
}
- Dmsg2(100, "Set npart=%d to part=%d\n", dev->num_parts, dev->part);
- dev->num_parts = dev->part;
+ Dmsg2(100, "num_parts=%d part=%d\n", dev->num_parts, dev->part);
dev->VolCatInfo.VolCatParts = dev->part;
make_spooled_dvd_filename(dev, archive_name); /* makes spool name */
}
}
}
+ /* KES. It seems to me that this if should not be
+ * needed. If num_parts represents what is on the DVD
+ * we should only need to change it when writing a part
+ * to the DVD.
+ */
if (dev->num_parts < dev->part) {
Dmsg2(100, "Set npart=%d to part=%d\n", dev->num_parts, dev->part);
dev->num_parts = dev->part;
{
DEVICE *dev = dcr->dev;
- Dmsg4(29, "Enter: ==== open_first_part dev=%s Vol=%s mode=%d num_parts=%d\n", dev->print_name(),
- dev->VolCatInfo.VolCatName, dev->openmode, dev->num_parts);
+ Dmsg5(29, "Enter: ==== open_first_part dev=%s Vol=%s mode=%d num_parts=%d append=%d\n", dev->print_name(),
+ dev->VolCatInfo.VolCatName, dev->openmode, dev->num_parts, dev->can_append());
if (dev->fd >= 0) {
close(dev->fd);
Dmsg2(50, "Call dev->open(vol=%s, mode=%d)\n", dcr->VolCatInfo.VolCatName,
mode);
+ int append = dev->can_append();
if (dev->open(dcr, mode) < 0) {
Dmsg0(50, "open dev() failed\n");
return -1;
}
- Dmsg1(50, "Leave open_first_part state=%s\n", dev->is_open()?"open":"not open");
+ if (append && (dev->part == dev->num_parts)) { /* If needed, set the append flag back */
+ dev->set_append();
+ }
+ Dmsg2(50, "Leave open_first_part state=%s append=%d\n", dev->is_open()?"open":"not open", dev->can_append());
+
return dev->fd;
}
return false;
}
+ /* Set num_parts to zero (on disk) */
+ dev->num_parts = 0;
+ dcr->VolCatInfo.VolCatParts = 0;
+ dev->VolCatInfo.VolCatParts = 0;
+
if (dvd_open_first_part(dcr, OPEN_READ_WRITE) < 0) {
Dmsg0(100, "truncate_dvd_dev: Error while opening first part (2).\n");
return false;
if (name_max < 1024) {
name_max = 1024;
}
-
+
if (!(dp = opendir(dev->device->mount_point))) {
berrno be;
dev->dev_errno = errno;