From 76d8a1dc23e77b2b9051989e91c353fe04e7bfea Mon Sep 17 00:00:00 2001 From: Michal Rakowski Date: Thu, 23 Dec 2021 16:27:32 +0100 Subject: [PATCH] Fix #8566 About problem with reusing Immutable volume --- bacula/src/stored/dircmd.c | 29 ++++--------------------- bacula/src/stored/file_dev.c | 41 +++++++++++++++++++++++++++++------- bacula/src/stored/vol_mgr.c | 8 +++++++ 3 files changed, 45 insertions(+), 33 deletions(-) diff --git a/bacula/src/stored/dircmd.c b/bacula/src/stored/dircmd.c index 8f01a3509..b548da82b 100644 --- a/bacula/src/stored/dircmd.c +++ b/bacula/src/stored/dircmd.c @@ -1040,33 +1040,12 @@ static void label_volume_if_ok(DCR *dcr, char *oldname, mode = CREATE_READ_WRITE; } - if (dev->check_volume_protection_time(volname)) { - if (!dev->open_device(dcr, mode)) { - /* Open with 'READ_WRITE' fails if immutable flag is set, check if that's the case */ - if (dev->check_for_immutable(volname)) { - Dmsg1(DT_VOLUME|50, "Volume %s has the 'Immutable' flag set, need to clear it\n", volname); - /* Volume has immutable flag set, we need to clear it */ - if (dev->clear_immutable(volname)) { - /* It should be now possible to open the device with desired mode */ - if (dev->open_device(dcr, mode)) { - opened = true; - } - } else { - dir->fsend(_("3929 Unable to clear immutable flag for device: \"%s\". ERR=%s\n"), - dev->print_name(), dev->bstrerror()); - } - } - } else { - opened = true; - } + if (!dev->open_device(dcr, mode)) { + dir->fsend(_("3929 Unable to open device \"%s\": ERR=%s\n"), + dev->print_name(), dev->bstrerror()); + goto bail_out; } - if (!opened) { - dir->fsend(_("3929 Unable to open device \"%s\": ERR=%s\n"), - dev->print_name(), dev->bstrerror()); - goto bail_out; - } - /* See what we have for a Volume */ label_status = dev->read_dev_volume_label(dcr); diff --git a/bacula/src/stored/file_dev.c b/bacula/src/stored/file_dev.c index c4b7314ec..450c2af2b 100644 --- a/bacula/src/stored/file_dev.c +++ b/bacula/src/stored/file_dev.c @@ -192,17 +192,42 @@ bool file_dev::open_device(DCR *dcr, int omode) archive_name.c_str(), mode); /* Use system open() */ if ((m_fd = ::open(archive_name.c_str(), mode|O_CLOEXEC|append, 0640)) < 0) { - berrno be; - dev_errno = errno; - Mmsg3(errmsg, _("Could not open(%s,%s,0640): ERR=%s\n"), - archive_name.c_str(), mode_to_str(omode), be.bstrerror()); - Dmsg1(40, "open failed: %s", errmsg); - } else { + /* Open may fail if we want to write to the Immutable volume */ + if (errno == EPERM && check_for_immutable(getVolCatName())) { + /* Volume has immutable flag set, we need to clear it */ + if (!check_volume_protection_time(getVolCatName())) { + /* Volume cannot be reused yet */ + MmsgD1(dbglvl, errmsg, _("Cannot open Volume %s for writing/truncating, " + "because Minimum Volume Protection Time hasn't expired yet\n"), + getVolCatName()); + } else { + /* Flag can be cleared, volume can probably be reused */ + if (clear_immutable(getVolCatName())) { + /* It should be now possible to open the device with desired mode */ + if ((m_fd = ::open(archive_name.c_str(), mode|O_CLOEXEC|append, 0640)) < 0) { + berrno be; + dev_errno = errno; + Mmsg3(errmsg, _("Could not open(%s,%s,0640): ERR=%s\n"), + archive_name.c_str(), mode_to_str(omode), be.bstrerror()); + Dmsg1(40, "open failed: %s", errmsg); + } + } + } + } else { + /* Volume is not immutable, that should succeed */ + berrno be; + dev_errno = errno; + Mmsg3(errmsg, _("Could not open(%s,%s,0640): ERR=%s\n"), + archive_name.c_str(), mode_to_str(omode), be.bstrerror()); + Dmsg1(40, "open failed: %s", errmsg); + } + } + + if (m_fd >= 0) { /* Open is OK, now let device get control */ Dmsg2(40, "Did open(%s,%s,0640)\n", archive_name.c_str(), mode_to_str(omode)); device_specific_open(dcr); - } - if (m_fd >= 0) { + dev_errno = 0; file = 0; file_addr = 0; diff --git a/bacula/src/stored/vol_mgr.c b/bacula/src/stored/vol_mgr.c index 0bff7e6c2..766780b08 100644 --- a/bacula/src/stored/vol_mgr.c +++ b/bacula/src/stored/vol_mgr.c @@ -834,6 +834,14 @@ bool DCR::can_i_write_volume() Dmsg1(100, "Found in read list; cannot write vol=%s\n", VolumeName); return false; } + + if (dev->check_for_immutable(VolumeName)) { + MmsgD1(dbglvl, jcr->errmsg, _("Skipping writing onto Volume %s, " + "because Volume's Protection Period has not expired yet\n"), + VolumeName); + return false; + } + return can_i_use_volume(); } -- 2.47.3