From: Eric Bollengier Date: Thu, 30 Mar 2023 14:44:13 +0000 (+0200) Subject: Fix #10004 Use VolRetention if greater than MinimumVolumeRetention when setting volum... X-Git-Tag: Beta-15.0.0~209 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c9c45e639aa45e0f7b06939eedcafa8c5040c8d9;p=thirdparty%2Fbacula.git Fix #10004 Use VolRetention if greater than MinimumVolumeRetention when setting volume to Read-Only --- diff --git a/bacula/src/dird/catreq.c b/bacula/src/dird/catreq.c index e798f11bb..a2a81f492 100644 --- a/bacula/src/dird/catreq.c +++ b/bacula/src/dird/catreq.c @@ -68,7 +68,7 @@ static char OK_media[] = "1000 OK VolName=%s VolJobs=%u VolFiles=%u" " VolWriteTime=%s EndFile=%u EndBlock=%u VolType=%u LabelType=%d" " MediaId=%s ScratchPoolId=%s VolParts=%d VolCloudParts=%d" " LastPartBytes=%lld Enabled=%d MaxPoolBytes=%s PoolBytes=%s Recycle=%d" - " Protected=%d UseProtect=%d VolEncrypted=%d\n"; + " Protected=%d UseProtect=%d VolEncrypted=%d VolRetention=%u\n"; static char OK_create[] = "1000 OK CreateJobMedia\n"; @@ -121,7 +121,7 @@ static int send_volume_info_to_storage_daemon(JCR *jcr, BSOCK *sd, MEDIA_DBR *mr mr->Enabled, edit_uint64(pr.MaxPoolBytes, ed11), edit_uint64(pr.PoolBytes, ed12), - mr->Recycle, mr->Protected, mr->UseProtect, mr->VolEncrypted); + mr->Recycle, mr->Protected, mr->UseProtect, mr->VolEncrypted, mr->VolRetention); unbash_spaces(mr->VolumeName); Dmsg2(100, "Vol Info for %s: %s", jcr->Job, sd->msg); return stat; diff --git a/bacula/src/dird/ua_update.c b/bacula/src/dird/ua_update.c index 08bea43f2..b942f3757 100644 --- a/bacula/src/dird/ua_update.c +++ b/bacula/src/dird/ua_update.c @@ -1116,6 +1116,7 @@ struct media_protect { char volname[MAX_NAME_LENGTH]; char storage[MAX_NAME_LENGTH]; char mediatype[MAX_NAME_LENGTH]; + uint32_t retention; }; /* @@ -1125,12 +1126,13 @@ static int media_protect_list_handler(void *ctx, int num_fields, char **row) { alist *val = (alist *)ctx; - if (row[0] && row[1] && row[2] && row[3]) { + if (row[0] && row[1] && row[2] && row[3] && row[4]) { struct media_protect *a = (struct media_protect *)malloc(sizeof(struct media_protect)); a->id = str_to_uint64(row[0]); bstrncpy(a->mediatype, row[1], sizeof(a->mediatype)); bstrncpy(a->volname, row[2], sizeof(a->volname)); bstrncpy(a->storage, row[3], sizeof(a->storage)); + a->retention = str_to_uint64(row[4]); val->append(a); } @@ -1194,10 +1196,14 @@ static int update_volumeprotect_cmd(UAContext *ua) return 0; } - Mmsg(tmp, "SELECT Media.MediaId, Media.MediaType, Media.VolumeName, Storage.Name " - "FROM Media JOIN Storage USING (StorageId) JOIN Pool USING (PoolId) " - "WHERE UseProtect=1 AND Protected=0 AND VolStatus IN ('Used', 'Full') %s " - "ORDER BY Storage.Name", filter.c_str()); + db_lock(ua->db); + const char *where_pool = ua->db->get_acls(DB_ACL_BIT(DB_ACL_POOL), false); + /* We use DISTINCT because when looking with JobId, we can get multiple time the same record */ + Mmsg(tmp, "SELECT DISTINCT Media.MediaId, Media.MediaType, Media.VolumeName, Storage.Name, Media.VolRetention " + "FROM Media JOIN Storage USING (StorageId) JOIN Pool USING (PoolId) %s " + "WHERE UseProtect=1 AND Protected=0 AND VolStatus IN ('Used', 'Full') %s %s " + "ORDER BY Storage.Name", join_job, filter.c_str(), where_pool); + db_unlock(ua->db); db_sql_query(ua->db, tmp.c_str(), media_protect_list_handler, &list); @@ -1254,8 +1260,8 @@ static int update_volumeprotect_cmd(UAContext *ua) bash_spaces(selected_dev_name); bash_spaces(elt->volname); - sd->fsend("volumeprotect mediatype=%s device=%s volume=%s drive=%d\n", - elt->mediatype, selected_dev_name, elt->volname, drive); + sd->fsend("volumeprotect mediatype=%s device=%s volume=%s drive=%d retention=%u\n", + elt->mediatype, selected_dev_name, elt->volname, drive, elt->retention); unbash_spaces(elt->mediatype); unbash_spaces(selected_dev_name); diff --git a/bacula/src/stored/askdir.c b/bacula/src/stored/askdir.c index 3476fa0f5..47ee2c4a7 100644 --- a/bacula/src/stored/askdir.c +++ b/bacula/src/stored/askdir.c @@ -51,7 +51,7 @@ static char OK_media[] = "1000 OK VolName=%127s VolJobs=%u VolFiles=%lu" " VolReadTime=%lld VolWriteTime=%lld EndFile=%lu EndBlock=%lu" " VolType=%lu LabelType=%ld MediaId=%lld ScratchPoolId=%lld" " VolParts=%d VolCloudParts=%d LastPartBytes=%lld Enabled=%d MaxPoolBytes=%lld PoolBytes=%lld Recycle=%d" - " Protected=%d UseProtect=%d VolEncrypted=%d\n"; + " Protected=%d UseProtect=%d VolEncrypted=%d VolRetention=%u\n"; static char OK_create[] = "1000 OK CreateJobMedia\n"; @@ -223,9 +223,9 @@ static bool do_get_volume_info(DCR *dcr) &vol.LabelType, &vol.VolMediaId, &vol.VolScratchPoolId, &vol.VolCatParts, &vol.VolCatCloudParts, &vol.VolLastPartBytes, &Enabled, &vol.MaxPoolBytes, - &vol.PoolBytes, &Recycle, &Protected, &UseProtect, &VolEncrypted); + &vol.PoolBytes, &Recycle, &Protected, &UseProtect, &VolEncrypted, &vol.VolRetention); Dmsg2(dbglvl, "msg); - if (n != 36) { + if (n != 37) { Dmsg1(dbglvl, "get_volume_info failed: ERR=%s", dir->msg); /* * Note, we can get an error here either because there is diff --git a/bacula/src/stored/block_util.c b/bacula/src/stored/block_util.c index 378efa2b1..a1fc5eccd 100644 --- a/bacula/src/stored/block_util.c +++ b/bacula/src/stored/block_util.c @@ -683,28 +683,11 @@ bool is_user_volume_size_reached(DCR *dcr, bool quiet) dev->getVolCatName()); } - if (dev->device->set_vol_immutable) { - dev->VolCatInfo.UseProtect = 1; - /* Set volume as immutable */ - if (!dev->set_immutable(dev->getVolCatName(), &dev->errmsg)) { - /* We may proceed with that but warn the user */ - Jmsg(dcr->jcr, M_WARNING, 0, _("Failed to set the volume %s on device %s as immutable, ERR=%s.\n"), - dev->getVolCatName(), dev->print_name(), dev->errmsg); - } else { - if (!quiet) { - Jmsg(dcr->jcr, M_INFO, 0, _("Marking Volume \"%s\" as immutable\n"), - dev->getVolCatName()); - } - events_send_msg(dcr->jcr, "SJ0003", EVENTS_TYPE_VOLUME, me->hdr.name, (intptr_t)dcr->jcr, - "Mark Volume \"%s\" as immutable", dev->getVolCatName());; - dev->VolCatInfo.Protected = 1; - } - } - if (dev->device->set_vol_read_only) { + uint32_t when = MAX(dev->device->min_volume_protection_time, dev->VolCatInfo.VolRetention); dev->VolCatInfo.UseProtect = 1; /* Set volume as immutable/read only */ - if (dev->set_atime(dev->m_fd, dev->getVolCatName(), time(NULL) + dev->device->min_volume_protection_time) < 0) { + if (dev->set_atime(dev->m_fd, dev->getVolCatName(), time(NULL) + when) < 0) { Jmsg(dcr->jcr, M_WARNING, 0, _("Failed to set the volume %s on device %s in atime retention, ERR=%s.\n"), dev->getVolCatName(), dev->print_name(), dev->errmsg); } @@ -714,16 +697,35 @@ bool is_user_volume_size_reached(DCR *dcr, bool quiet) Jmsg(dcr->jcr, M_WARNING, 0, _("Failed to set the volume %s on device %s in read-only, ERR=%s.\n"), dev->getVolCatName(), dev->print_name(), be.bstrerror()); } else { + char buf[128]; + edit_utime(when, buf, sizeof(buf)); if (!quiet) { - Jmsg(dcr->jcr, M_INFO, 0, _("Marking Volume \"%s\" as read-only\n"), + Jmsg(dcr->jcr, M_INFO, 0, _("Marking Volume \"%s\" as read-only. Retention set to %s.\n"), buf, dev->getVolCatName()); } dev->VolCatInfo.Protected = 1; events_send_msg(dcr->jcr, "SJ0003", EVENTS_TYPE_VOLUME, me->hdr.name, (intptr_t)dcr->jcr, - "Mark Volume \"%s\" as read-only", dev->getVolCatName());; + "Mark Volume \"%s\" as read-only. retention %s.", dev->getVolCatName(), buf);; } } + if (dev->device->set_vol_immutable) { + dev->VolCatInfo.UseProtect = 1; + /* Set volume as immutable */ + if (!dev->set_immutable(dev->getVolCatName(), &dev->errmsg)) { + /* We may proceed with that but warn the user */ + Jmsg(dcr->jcr, M_WARNING, 0, _("Failed to set the volume %s on device %s as immutable, ERR=%s.\n"), + dev->getVolCatName(), dev->print_name(), dev->errmsg); + } else { + if (!quiet) { + Jmsg(dcr->jcr, M_INFO, 0, _("Marking Volume \"%s\" as immutable\n"), + dev->getVolCatName()); + } + events_send_msg(dcr->jcr, "SJ0003", EVENTS_TYPE_VOLUME, me->hdr.name, (intptr_t)dcr->jcr, + "Mark Volume \"%s\" as immutable", dev->getVolCatName());; + dev->VolCatInfo.Protected = 1; + } + } Dmsg4(100, "Maximum volume size %s exceeded Vol=%s device=%s.\n" "Marking Volume \"%s\" as Full.\n", edit_uint64_with_commas(max_size, ed1), dev->getVolCatName(), diff --git a/bacula/src/stored/dev.h b/bacula/src/stored/dev.h index 0b5ddadc0..5eab15067 100644 --- a/bacula/src/stored/dev.h +++ b/bacula/src/stored/dev.h @@ -215,7 +215,8 @@ struct VOLUME_CAT_INFO { uint32_t VolCatRecycles; /* Number of recycles this volume */ uint32_t EndFile; /* Last file number */ uint32_t EndBlock; /* Last block number */ - + uint32_t VolRetention; /* Volume Retention */ + int32_t LabelType; /* Bacula/ANSI/IBM */ int32_t Slot; /* >0=Slot loaded, 0=nothing, -1=unknown */ uint32_t VolCatMaxJobs; /* Maximum Jobs to write to volume */ diff --git a/bacula/src/stored/dircmd.c b/bacula/src/stored/dircmd.c index eff14c7f1..cee028dd6 100644 --- a/bacula/src/stored/dircmd.c +++ b/bacula/src/stored/dircmd.c @@ -1340,11 +1340,12 @@ static bool volumeprotect_cmd(JCR *jcr) char mediatype[MAX_NAME_LENGTH]; char volume[MAX_NAME_LENGTH]; POOL_MEM device, tmp; + uint32_t retention; int32_t drive; bool ok; - ok = sscanf(dir->msg, "volumeprotect mediatype=%127s device=%127s volume=%127s drive=%d", - mediatype, device.c_str(), volume, &drive) == 4; + ok = sscanf(dir->msg, "volumeprotect mediatype=%127s device=%127s volume=%127s drive=%d retention=%u", + mediatype, device.c_str(), volume, &drive, &retention) == 5; if (ok) { unbash_spaces(mediatype); unbash_spaces(device.c_str()); @@ -1374,7 +1375,8 @@ static bool volumeprotect_cmd(JCR *jcr) } else if (dev->device->set_vol_read_only) { /* Set volume as immutable/read only */ pm_strcpy(tmp, ""); - if (dev->set_atime(-1, volume, time(NULL) + dev->device->min_volume_protection_time) < 0) { + uint32_t when = MAX(dev->device->min_volume_protection_time, retention); + if (dev->set_atime(-1, volume, time(NULL) + when) < 0) { berrno be; Mmsg(tmp, _(" Failed to set the volume %s on device %s in atime retention, ERR=%s.\n"), volume, dev->print_name(), be.bstrerror()); @@ -1385,9 +1387,11 @@ static bool volumeprotect_cmd(JCR *jcr) dir->fsend(_("3900 Failed to set the volume %s on device %s in read-only, ERR=%s.%s\n"), volume, dev->print_name(), be.bstrerror(), tmp.c_str()); } else { - dir->fsend(_("3000 Marking volume \"%s\" as read-only.\n"), volume); + char buf[128]; + dir->fsend(_("3000 Marking volume \"%s\" as read-only. Retention set to %s.\n"), + volume, edit_utime(when, buf, sizeof(buf))); events_send_msg(jcr, "SJ0003", EVENTS_TYPE_VOLUME, me->hdr.name, (intptr_t)jcr, - "Mark volume \"%s\" as read-only", volume); + "Mark volume \"%s\" as read-only, retention %s", volume, buf); } } else { dir->fsend(_("3900 Device %s not configured for ReadOnly or Immutable\n"), dev->device->hdr.name);