diff --git a/src/cats/cats.h b/src/cats/cats.h index cb77d4abc27..9f782ffb167 100644 --- a/src/cats/cats.h +++ b/src/cats/cats.h @@ -247,6 +247,8 @@ struct POOL_DBR { DBId_t ScratchPoolId; /* ScratchPool source when media is needed */ char PoolType[MAX_NAME_LENGTH]; char LabelFormat[MAX_NAME_LENGTH]; + uint32_t MinBlocksize; /* Minimum Block Size */ + uint32_t MaxBlocksize; /* Maximum Block Size */ /* Extra stuff not in DB */ faddr_t rec_addr; }; @@ -330,6 +332,8 @@ class MEDIA_DBR { uint32_t EndFile; /* Last file on volume */ uint32_t EndBlock; /* Last block on volume */ uint32_t RecycleCount; /* Number of times recycled */ + uint32_t MinBlocksize; /* Minimum Block Size */ + uint32_t MaxBlocksize; /* Maximum Block Size */ char VolStatus[20]; /* Volume status */ DBId_t DeviceId; /* Device where Vol last written */ DBId_t LocationId; /* Where Volume is -- user defined */ diff --git a/src/cats/sql_create.c b/src/cats/sql_create.c index fe0851334d6..ea211779e44 100644 --- a/src/cats/sql_create.c +++ b/src/cats/sql_create.c @@ -198,8 +198,8 @@ bool db_create_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr) "INSERT INTO Pool (Name,NumVols,MaxVols,UseOnce,UseCatalog," "AcceptAnyVolume,AutoPrune,Recycle,VolRetention,VolUseDuration," "MaxVolJobs,MaxVolFiles,MaxVolBytes,PoolType,LabelType,LabelFormat," -"RecyclePoolId,ScratchPoolId,ActionOnPurge) " -"VALUES ('%s',%u,%u,%d,%d,%d,%d,%d,%s,%s,%u,%u,%s,'%s',%d,'%s',%s,%s,%d)", +"RecyclePoolId,ScratchPoolId,ActionOnPurge,MinBlocksize,MaxBlocksize) " +"VALUES ('%s',%u,%u,%d,%d,%d,%d,%d,%s,%s,%u,%u,%s,'%s',%d,'%s',%s,%s,%d,%d,%d)", esc_name, pr->NumVols, pr->MaxVols, pr->UseOnce, pr->UseCatalog, @@ -212,8 +212,9 @@ bool db_create_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr) pr->PoolType, pr->LabelType, esc_lf, edit_int64(pr->RecyclePoolId,ed4), edit_int64(pr->ScratchPoolId,ed5), - pr->ActionOnPurge - ); + pr->ActionOnPurge, + pr->MinBlocksize, + pr->MaxBlocksize); Dmsg1(200, "Create Pool: %s\n", mdb->cmd); pr->PoolId = sql_insert_autokey_record(mdb, mdb->cmd, NT_("Pool")); if (pr->PoolId == 0) { @@ -438,9 +439,10 @@ bool db_create_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) "VolCapacityBytes,Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles," "VolStatus,Slot,VolBytes,InChanger,VolReadTime,VolWriteTime," "EndFile,EndBlock,LabelType,StorageId,DeviceId,LocationId," -"ScratchPoolId,RecyclePoolId,Enabled,ActionOnPurge,EncryptionKey)" +"ScratchPoolId,RecyclePoolId,Enabled,ActionOnPurge,EncryptionKey," +"MinBlocksize,MaxBlocksize) " "VALUES ('%s','%s',0,%u,%s,%s,%d,%s,%s,%u,%u,'%s',%d,%s,%d,%s,%s,0,0,%d,%s," -"%s,%s,%s,%s,%d,%d,'%s')", +"%s,%s,%s,%s,%d,%d,'%s',%d,%d)", esc_name, esc_mtype, mr->PoolId, edit_uint64(mr->MaxVolBytes,ed1), @@ -463,7 +465,8 @@ bool db_create_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) edit_int64(mr->ScratchPoolId, ed11), edit_int64(mr->RecyclePoolId, ed12), mr->Enabled, mr->ActionOnPurge, - mr->EncrKey); + mr->EncrKey, mr->MinBlocksize, + mr->MaxBlocksize); Dmsg1(500, "Create Volume: %s\n", mdb->cmd); mr->MediaId = sql_insert_autokey_record(mdb, mdb->cmd, NT_("Media")); diff --git a/src/cats/sql_find.c b/src/cats/sql_find.c index b48e4f46af4..0f6a75a7b6f 100644 --- a/src/cats/sql_find.c +++ b/src/cats/sql_find.c @@ -337,7 +337,7 @@ int db_find_next_volume(JCR *jcr, B_DB *mdb, int item, bool InChanger, MEDIA_DBR "EndFile,EndBlock,LabelType,LabelDate,StorageId," "Enabled,LocationId,RecycleCount,InitialWrite," "ScratchPoolId,RecyclePoolId,VolReadTime,VolWriteTime," - "ActionOnPurge,EncryptionKey " + "ActionOnPurge,EncryptionKey,MinBlocksize,MaxBlocksize " "FROM Media WHERE PoolId=%s AND MediaType='%s' AND VolStatus IN ('Full'," "'Recycle','Purged','Used','Append') AND Enabled=1 " "ORDER BY LastWritten LIMIT 1", @@ -363,7 +363,7 @@ int db_find_next_volume(JCR *jcr, B_DB *mdb, int item, bool InChanger, MEDIA_DBR "EndFile,EndBlock,LabelType,LabelDate,StorageId," "Enabled,LocationId,RecycleCount,InitialWrite," "ScratchPoolId,RecyclePoolId,VolReadTime,VolWriteTime," - "ActionOnPurge,EncryptionKey " + "ActionOnPurge,EncryptionKey,MinBlocksize,MaxBlocksize " "FROM Media WHERE PoolId=%s AND MediaType='%s' AND Enabled=1 " "AND VolStatus='%s' " "%s " @@ -443,6 +443,8 @@ int db_find_next_volume(JCR *jcr, B_DB *mdb, int item, bool InChanger, MEDIA_DBR mr->VolWriteTime = str_to_int64(row[35]); mr->ActionOnPurge = str_to_int64(row[36]); bstrncpy(mr->EncrKey, (row[37] != NULL) ? row[37] : "", sizeof(mr->EncrKey)); + mr->MinBlocksize = str_to_int32(row[38]); + mr->MaxBlocksize = str_to_int32(row[39]); sql_free_result(mdb); diff --git a/src/cats/sql_get.c b/src/cats/sql_get.c index 9ac207fe5de..057e5f2dcbd 100644 --- a/src/cats/sql_get.c +++ b/src/cats/sql_get.c @@ -608,7 +608,7 @@ bool db_get_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pdbr) "SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,AcceptAnyVolume," "AutoPrune,Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles," "MaxVolBytes,PoolType,LabelType,LabelFormat,RecyclePoolId,ScratchPoolId," -"ActionOnPurge FROM Pool WHERE Pool.PoolId=%s", +"ActionOnPurge,MinBlocksize,MaxBlocksize FROM Pool WHERE Pool.PoolId=%s", edit_int64(pdbr->PoolId, ed1)); } else { /* find by name */ mdb->db_escape_string(jcr, esc, pdbr->Name, strlen(pdbr->Name)); @@ -616,7 +616,7 @@ bool db_get_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pdbr) "SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,AcceptAnyVolume," "AutoPrune,Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles," "MaxVolBytes,PoolType,LabelType,LabelFormat,RecyclePoolId,ScratchPoolId," -"ActionOnPurge FROM Pool WHERE Pool.Name='%s'", esc); +"ActionOnPurge,MinBlocksize,MaxBlocksize FROM Pool WHERE Pool.Name='%s'", esc); } if (QUERY_DB(jcr, mdb, mdb->cmd)) { num_rows = sql_num_rows(mdb); @@ -650,6 +650,8 @@ bool db_get_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pdbr) pdbr->RecyclePoolId = str_to_int64(row[17]); pdbr->ScratchPoolId = str_to_int64(row[18]); pdbr->ActionOnPurge = str_to_int32(row[19]); + pdbr->MinBlocksize = str_to_int32(row[20]); + pdbr->MaxBlocksize = str_to_int32(row[21]); ok = true; } } @@ -1004,7 +1006,7 @@ bool db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) "EndFile,EndBlock,LabelType,LabelDate,StorageId," "Enabled,LocationId,RecycleCount,InitialWrite," "ScratchPoolId,RecyclePoolId,VolReadTime,VolWriteTime," - "ActionOnPurge,EncryptionKey " + "ActionOnPurge,EncryptionKey,MinBlocksize,MaxBlocksize " "FROM Media WHERE MediaId=%s", edit_int64(mr->MediaId, ed1)); } else { /* find by name */ @@ -1016,7 +1018,7 @@ bool db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) "EndFile,EndBlock,LabelType,LabelDate,StorageId," "Enabled,LocationId,RecycleCount,InitialWrite," "ScratchPoolId,RecyclePoolId,VolReadTime,VolWriteTime," - "ActionOnPurge,EncryptionKey " + "ActionOnPurge,EncryptionKey,MinBlocksize,MaxBlocksize " "FROM Media WHERE VolumeName='%s'", esc); } @@ -1075,7 +1077,8 @@ bool db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) mr->VolWriteTime = str_to_int64(row[35]); mr->ActionOnPurge = str_to_int32(row[36]); bstrncpy(mr->EncrKey, (row[37] != NULL) ? row[37] : "", sizeof(mr->EncrKey)); - + mr->MinBlocksize = str_to_int32(row[38]); + mr->MaxBlocksize = str_to_int32(row[39]); retval = true; } } else { diff --git a/src/cats/sql_update.c b/src/cats/sql_update.c index 44bc8f82f5d..18b9c880af8 100644 --- a/src/cats/sql_update.c +++ b/src/cats/sql_update.c @@ -272,7 +272,7 @@ bool db_update_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr) "AcceptAnyVolume=%d,VolRetention='%s',VolUseDuration='%s'," "MaxVolJobs=%u,MaxVolFiles=%u,MaxVolBytes=%s,Recycle=%d," "AutoPrune=%d,LabelType=%d,LabelFormat='%s',RecyclePoolId=%s," -"ScratchPoolId=%s,ActionOnPurge=%d WHERE PoolId=%s", +"ScratchPoolId=%s,ActionOnPurge=%d,MinBlockSize=%d,MaxBlockSize=%d WHERE PoolId=%s", pr->NumVols, pr->MaxVols, pr->UseOnce, pr->UseCatalog, pr->AcceptAnyVolume, edit_uint64(pr->VolRetention, ed1), edit_uint64(pr->VolUseDuration, ed2), @@ -282,6 +282,8 @@ bool db_update_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr) esc, edit_int64(pr->RecyclePoolId,ed5), edit_int64(pr->ScratchPoolId,ed6), pr->ActionOnPurge, + pr->MinBlocksize, + pr->MaxBlocksize, ed4); retval = UPDATE_DB(jcr, mdb, mdb->cmd); db_unlock(mdb); @@ -373,7 +375,8 @@ bool db_update_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) "Slot=%d,InChanger=%d,VolReadTime=%s,VolWriteTime=%s," "LabelType=%d,StorageId=%s,PoolId=%s,VolRetention=%s,VolUseDuration=%s," "MaxVolJobs=%d,MaxVolFiles=%d,Enabled=%d,LocationId=%s," - "ScratchPoolId=%s,RecyclePoolId=%s,RecycleCount=%d,Recycle=%d,ActionOnPurge=%d" + "ScratchPoolId=%s,RecyclePoolId=%s,RecycleCount=%d,Recycle=%d,ActionOnPurge=%d," + "MinBlocksize=%u,MaxBlocksize=%u" " WHERE VolumeName='%s'", mr->VolJobs, mr->VolFiles, mr->VolBlocks, edit_uint64(mr->VolBytes, ed1), mr->VolMounts, mr->VolErrors, mr->VolWrites, @@ -390,7 +393,8 @@ bool db_update_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) mr->Enabled, edit_uint64(mr->LocationId, ed9), edit_uint64(mr->ScratchPoolId, ed10), edit_uint64(mr->RecyclePoolId, ed11), - mr->RecycleCount,mr->Recycle, mr->ActionOnPurge, + mr->RecycleCount, mr->Recycle, mr->ActionOnPurge, + mr->MinBlocksize, mr->MaxBlocksize, esc_name); Dmsg1(400, "%s\n", mdb->cmd); @@ -420,25 +424,31 @@ bool db_update_media_defaults(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) if (mr->VolumeName[0]) { mdb->db_escape_string(jcr, esc, mr->VolumeName, strlen(mr->VolumeName)); Mmsg(mdb->cmd, "UPDATE Media SET " - "ActionOnPurge=%d, Recycle=%d,VolRetention=%s,VolUseDuration=%s," - "MaxVolJobs=%u,MaxVolFiles=%u,MaxVolBytes=%s,RecyclePoolId=%s" + "ActionOnPurge=%d,Recycle=%d,VolRetention=%s,VolUseDuration=%s," + "MaxVolJobs=%u,MaxVolFiles=%u,MaxVolBytes=%s,RecyclePoolId=%s," + "MinBlocksize=%d,MaxBlocksize=%d" " WHERE VolumeName='%s'", mr->ActionOnPurge, mr->Recycle,edit_uint64(mr->VolRetention, ed1), edit_uint64(mr->VolUseDuration, ed2), mr->MaxVolJobs, mr->MaxVolFiles, edit_uint64(mr->MaxVolBytes, ed3), edit_uint64(mr->RecyclePoolId, ed4), + mr->MinBlocksize, + mr->MaxBlocksize, esc); } else { Mmsg(mdb->cmd, "UPDATE Media SET " - "ActionOnPurge=%d, Recycle=%d,VolRetention=%s,VolUseDuration=%s," - "MaxVolJobs=%u,MaxVolFiles=%u,MaxVolBytes=%s,RecyclePoolId=%s" + "ActionOnPurge=%d,Recycle=%d,VolRetention=%s,VolUseDuration=%s," + "MaxVolJobs=%u,MaxVolFiles=%u,MaxVolBytes=%s,RecyclePoolId=%s," + "MinBlocksize=%d,MaxBlocksize=%d" " WHERE PoolId=%s", mr->ActionOnPurge, mr->Recycle,edit_uint64(mr->VolRetention, ed1), edit_uint64(mr->VolUseDuration, ed2), mr->MaxVolJobs, mr->MaxVolFiles, edit_uint64(mr->MaxVolBytes, ed3), edit_int64(mr->RecyclePoolId, ed4), + mr->MinBlocksize, + mr->MaxBlocksize, edit_int64(mr->PoolId, ed5)); } diff --git a/src/dird/catreq.c b/src/dird/catreq.c index cfa9123652f..ec6269831cb 100644 --- a/src/dird/catreq.c +++ b/src/dird/catreq.c @@ -68,7 +68,7 @@ static char OK_media[] = " MaxVolBytes=%s VolCapacityBytes=%s VolStatus=%s Slot=%d" " MaxVolJobs=%u MaxVolFiles=%u InChanger=%d VolReadTime=%s" " VolWriteTime=%s EndFile=%u EndBlock=%u LabelType=%d" - " MediaId=%s EncryptionKey=%s\n"; + " MediaId=%s EncryptionKey=%s MinBlocksize=%d MaxBlocksize=%d\n"; static char OK_create[] = "1000 OK CreateJobMedia\n"; @@ -92,7 +92,7 @@ static int send_volume_info_to_storage_daemon(JCR *jcr, BSOCK *sd, MEDIA_DBR *mr mr->EndFile, mr->EndBlock, mr->LabelType, edit_uint64(mr->MediaId, ed6), - mr->EncrKey); + mr->EncrKey, mr->MinBlocksize, mr->MaxBlocksize); unbash_spaces(mr->VolumeName); Dmsg2(100, "Vol Info for %s: %s", jcr->Job, sd->msg); return status; diff --git a/src/dird/dird_conf.c b/src/dird/dird_conf.c index 80f3a4fd851..97120df5a33 100644 --- a/src/dird/dird_conf.c +++ b/src/dird/dird_conf.c @@ -455,6 +455,8 @@ static RES_ITEM pool_items[] = { { "catalog", store_res, ITEM(res_pool.catalog), R_CATALOG, 0, NULL }, { "fileretention", store_time, ITEM(res_pool.FileRetention), 0, 0, NULL }, { "jobretention", store_time, ITEM(res_pool.JobRetention), 0, 0, NULL }, + { "minimumblocksize", store_pint32, ITEM(res_pool.MinBlocksize), 0, 0, NULL }, + { "maximumblocksize", store_pint32, ITEM(res_pool.MaxBlocksize), 0, 0, NULL }, { NULL, NULL, { 0 }, 0, 0, NULL } }; @@ -1136,6 +1138,8 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm sendit(sock, _(" max_vols=%d auto_prune=%d VolRetention=%s\n"), res->res_pool.max_volumes, res->res_pool.AutoPrune, edit_utime(res->res_pool.VolRetention, ed1, sizeof(ed1))); + sendit(sock, _(" minblocksize=%d maxblocksize=%d\n"), + res->res_pool.MinBlocksize, res->res_pool.MaxBlocksize); sendit(sock, _(" VolUse=%s recycle=%d LabelFormat=%s\n"), edit_utime(res->res_pool.VolUseDuration, ed1, sizeof(ed1)), res->res_pool.Recycle, diff --git a/src/dird/dird_conf.h b/src/dird/dird_conf.h index fa7b870accc..99e7898a71a 100644 --- a/src/dird/dird_conf.h +++ b/src/dird/dird_conf.h @@ -607,6 +607,8 @@ class POOLRES { CATRES *catalog; /* Catalog to be used */ utime_t FileRetention; /* file retention period in seconds */ utime_t JobRetention; /* job retention period in seconds */ + uint32_t MinBlocksize; /* Minimum Blocksize */ + uint32_t MaxBlocksize; /* Maximum Blocksize */ /* Methods */ char *name() const; diff --git a/src/dird/ua_cmds.c b/src/dird/ua_cmds.c index 0d5182bb199..75753403bab 100644 --- a/src/dird/ua_cmds.c +++ b/src/dird/ua_cmds.c @@ -309,6 +309,8 @@ void set_pool_dbr_defaults_in_media_dbr(MEDIA_DBR *mr, POOL_DBR *pr) mr->MaxVolFiles = pr->MaxVolFiles; mr->MaxVolBytes = pr->MaxVolBytes; mr->LabelType = pr->LabelType; + mr->MinBlocksize = pr->MinBlocksize; + mr->MaxBlocksize = pr->MaxBlocksize; mr->Enabled = 1; } @@ -555,7 +557,7 @@ static int cancel_cmd(UAContext *ua, const char *cmd) * Pool DB base record from a Pool Resource. We handle * the setting of MaxVols and NumVols slightly differently * depending on if we are creating the Pool or we are - * simply bringing it into agreement with the resource (updage). + * simply bringing it into agreement with the resource (update). * * Caution : RecyclePoolId isn't setup in this function. * You can use set_pooldbr_recyclepoolid(); @@ -585,6 +587,9 @@ void set_pooldbr_from_poolres(POOL_DBR *pr, POOLRES *pool, e_pool_op op) pr->MaxVolBytes = pool->MaxVolBytes; pr->AutoPrune = pool->AutoPrune; pr->ActionOnPurge = pool->action_on_purge; + pr->ActionOnPurge = pool->action_on_purge; + pr->MinBlocksize = pool->MinBlocksize; + pr->MaxBlocksize = pool->MaxBlocksize; pr->Recycle = pool->Recycle; if (pool->label_format) { bstrncpy(pr->LabelFormat, pool->label_format, sizeof(pr->LabelFormat)); diff --git a/src/dird/ua_label.c b/src/dird/ua_label.c index 941efdc5489..c968e20485a 100644 --- a/src/dird/ua_label.c +++ b/src/dird/ua_label.c @@ -412,8 +412,7 @@ static void label_from_barcodes(UAContext *ua, int drive, bool label_encrypt) set_storageid_in_mr(store, &mr); /* - * Deal with creating cleaning tape here. Normal tapes created in - * send_label_request() below + * Deal with creating cleaning tape here. Normal tapes created in send_label_request() below */ if (is_cleaning_tape(ua, &mr, &pr)) { if (media_record_exists) { /* we update it */ @@ -458,7 +457,7 @@ static void label_from_barcodes(UAContext *ua, int drive, bool label_encrypt) } mr.Slot = vl->Slot; - send_label_request(ua, &mr, &omr, &pr, 0, media_record_exists, drive); + send_label_request(ua, &mr, &omr, &pr, false, media_record_exists, drive); } bail_out: @@ -555,20 +554,30 @@ static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr, if (relabel) { bash_spaces(omr->VolumeName); sd->fsend("relabel %s OldName=%s NewName=%s PoolName=%s " - "MediaType=%s Slot=%d drive=%d", + "MediaType=%s Slot=%d drive=%d MinBlocksize=%d MaxBlocksize=%d", dev_name, omr->VolumeName, mr->VolumeName, pr->Name, - mr->MediaType, mr->Slot, drive); + mr->MediaType, mr->Slot, drive, + /* + * if relabeling, keep blocksize settings + */ + omr->MinBlocksize, omr->MaxBlocksize); ua->send_msg(_("Sending relabel command from \"%s\" to \"%s\" ...\n"), omr->VolumeName, mr->VolumeName); } else { sd->fsend("label %s VolumeName=%s PoolName=%s MediaType=%s " - "Slot=%d drive=%d", + "Slot=%d drive=%d MinBlocksize=%d MaxBlocksize=%d", dev_name, mr->VolumeName, pr->Name, mr->MediaType, - mr->Slot, drive); + mr->Slot, drive, + /* + * if labeling, use blocksize defined in pool + */ + pr->MinBlocksize, pr->MaxBlocksize); ua->send_msg(_("Sending label command for Volume \"%s\" Slot %d ...\n"), mr->VolumeName, mr->Slot); - Dmsg6(100, "label %s VolumeName=%s PoolName=%s MediaType=%s Slot=%d drive=%d\n", - dev_name, mr->VolumeName, pr->Name, mr->MediaType, mr->Slot, drive); + Dmsg8(100, "label %s VolumeName=%s PoolName=%s MediaType=%s " + "Slot=%d drive=%d MinBlocksize=%d MaxBlocksize=%d\n", + dev_name, mr->VolumeName, pr->Name, mr->MediaType, mr->Slot, drive, + pr->MinBlocksize, pr->MaxBlocksize); } /* diff --git a/src/lib/scan.c b/src/lib/scan.c index cf194421b39..6ab48dadb1f 100644 --- a/src/lib/scan.c +++ b/src/lib/scan.c @@ -544,6 +544,8 @@ struct VOLUME_CAT_INFO { uint64_t VolCatCapacityBytes; /* capacity estimate */ uint64_t VolReadTime; /* time spent reading */ uint64_t VolWriteTime; /* time spent writing this Volume */ + uint32_t MinBlocksize; /* Minimum block size */ + uint32_t MaxBlocksize; /* Maximum block size */ char VolCatStatus[20]; /* Volume status */ char VolCatName[MAX_NAME_LENGTH]; /* Desired volume to mount */ }; @@ -569,7 +571,8 @@ struct VOLUME_CAT_INFO { &vol.VolCatWrites, &vol.VolCatMaxBytes, &vol.VolCatCapacityBytes, vol.VolCatStatus, &vol.Slot, &vol.VolCatMaxJobs, &vol.VolCatMaxFiles, - &vol.InChanger, &vol.VolReadTime, &vol.VolWriteTime); + &vol.InChanger, &vol.VolReadTime, &vol.VolWriteTime, + &vol.MaxBlocksize, &vol.MinBocksize); printf("cnt=%d Vol=%s\n", cnt, vol.VolCatName); } diff --git a/src/stored/acquire.c b/src/stored/acquire.c index e38434dadf1..84a66671eb7 100644 --- a/src/stored/acquire.c +++ b/src/stored/acquire.c @@ -338,7 +338,9 @@ bool acquire_device_for_read(DCR *dcr) } Dmsg2(rdbglvl, "dcr=%p dev=%p\n", dcr, dcr->dev); Dmsg2(rdbglvl, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type); + dev->Unlock_read_acquire(); + Leave(rdbglvl); return ok; } @@ -606,7 +608,7 @@ bool clean_device(DCR *dcr) * this dcr in the right place * */ -DCR *new_dcr(JCR *jcr, DCR *dcr, DEVICE *dev) +DCR *new_dcr(JCR *jcr, DCR *dcr, DEVICE *dev, BLOCKSIZES *blocksizes) { if (!dcr) { int errstat; @@ -633,6 +635,14 @@ DCR *new_dcr(JCR *jcr, DCR *dcr, DEVICE *dev) * Set device information, possibly change device */ if (dev) { + /* + * Set wanted blocksizes + */ + if (blocksizes) { + dev->min_block_size = blocksizes->min_block_size; + dev->max_block_size = blocksizes->max_block_size; + } + if (dcr->block) { free_block(dcr->block); } diff --git a/src/stored/askdir.c b/src/stored/askdir.c index b65ff7e2ad9..148130181e6 100644 --- a/src/stored/askdir.c +++ b/src/stored/askdir.c @@ -59,7 +59,8 @@ static char OK_media[] = " MaxVolBytes=%lld VolCapacityBytes=%lld VolStatus=%20s" " Slot=%ld MaxVolJobs=%lu MaxVolFiles=%lu InChanger=%ld" " VolReadTime=%lld VolWriteTime=%lld EndFile=%lu EndBlock=%lu" - " LabelType=%ld MediaId=%lld EncryptionKey=%127s\n"; + " LabelType=%ld MediaId=%lld EncryptionKey=%127s" + " MinBlocksize=%lu MaxBlocksize=%lu\n"; static char OK_create[] = "1000 OK CreateJobMedia\n"; @@ -181,8 +182,9 @@ static bool do_get_volume_info(DCR *dcr) &vol.Slot, &vol.VolCatMaxJobs, &vol.VolCatMaxFiles, &InChanger, &vol.VolReadTime, &vol.VolWriteTime, &vol.EndFile, &vol.EndBlock, &vol.LabelType, - &vol.VolMediaId, vol.VolEncrKey); - if (n != 22) { + &vol.VolMediaId, vol.VolEncrKey, + &vol.VolMinBlocksize, &vol.VolMaxBlocksize); + if (n != 24) { Dmsg3(dbglvl, "Bad response from Dir fields=%d, len=%d: %s", n, dir->msglen, dir->msg); Mmsg(jcr->errmsg, _("Error getting Volume info: %s"), dir->msg); @@ -195,8 +197,7 @@ static bool do_get_volume_info(DCR *dcr) dcr->VolCatInfo = vol; /* structure assignment */ /* - * If we received a new crypto key update the cache and write - * out the new cache on a change. + * If we received a new crypto key update the cache and write out the new cache on a change. */ if (*vol.VolEncrKey) { if (update_crypto_cache(vol.VolCatName, vol.VolEncrKey)) { @@ -205,12 +206,23 @@ static bool do_get_volume_info(DCR *dcr) } } - Dmsg2(dbglvl, "do_get_volume_info return true slot=%d Volume=%s\n", - vol.Slot, vol.VolCatName); + Dmsg4(dbglvl, "do_get_volume_info return true slot=%d Volume=%s, " + "VolminBlocksize=%u VolMaxBlocksize=%u\n", + vol.Slot, vol.VolCatName, vol.VolMinBlocksize, vol.VolMaxBlocksize); + Dmsg2(dbglvl, "setting dcr->VolMinBlocksize(%u) to vol.VolMinBlocksize(%u)\n", + dcr->VolMinBlocksize, vol.VolMinBlocksize); + Dmsg2(dbglvl, "setting dcr->VolMaxBlocksize(%u) to vol.VolMaxBlocksize(%u)\n", + dcr->VolMaxBlocksize, vol.VolMaxBlocksize); + + /* + * Assign the volcatinfo to the dcr. + */ + dcr->VolMinBlocksize = vol.VolMinBlocksize; + dcr->VolMaxBlocksize = vol.VolMaxBlocksize; + return true; } - /** * Get Volume info for a specific volume from the Director's Database * @@ -238,8 +250,6 @@ bool dir_get_volume_info(DCR *dcr, enum get_vol_info_rw writing) return ok; } - - /** * Get info on the next appendable volume in the Director's database * @@ -316,7 +326,6 @@ bool dir_find_next_appendable_volume(DCR *dcr) return rtn; } - /** * After writing a Volume, send the updated statistics * back to the director. The information comes from the @@ -443,7 +452,6 @@ bool dir_create_jobmedia_record(DCR *dcr, bool zero) return true; } - /** * Update File Attribute data * We do the following: @@ -486,7 +494,6 @@ bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) return dir->send(); } - /** * Request the sysop to create an appendable volume * diff --git a/src/stored/block.c b/src/stored/block.c index 979f226c08c..6462bf5766a 100644 --- a/src/stored/block.c +++ b/src/stored/block.c @@ -42,7 +42,6 @@ static const bool no_tape_write_test = true; static const bool no_tape_write_test = false; #endif - static bool terminate_writing_volume(DCR *dcr); static bool do_new_file_bookkeeping(DCR *dcr); static void reread_last_block(DCR *dcr); @@ -121,13 +120,12 @@ DEV_BLOCK *new_block(DEVICE *dev) memset(block, 0, sizeof(DEV_BLOCK)); - /* - * If the user has specified a max_block_size, use it as the default - */ if (dev->max_block_size == 0) { - block->buf_len = DEFAULT_BLOCK_SIZE; + block->buf_len = dev->device->label_block_size; + Dmsg1(100, "created new block of blocksize %d (dev->device->label_block_size) as dev->max_block_size is zero\n", block->buf_len); } else { block->buf_len = dev->max_block_size; + Dmsg1(100, "created new block of blocksize %d (dev->max_block_size)\n", block->buf_len); } block->dev = dev; block->block_len = block->buf_len; /* default block size */ @@ -502,11 +500,19 @@ bool DCR::write_block_to_dev() wlen = ((wlen + TAPE_BSIZE - 1) / TAPE_BSIZE) * TAPE_BSIZE; } } + + Dmsg4(100, "writing block of size %d to dev=%s with max_block_size %d and min_block_size %d\n", + wlen, dev->print_name(), dev->max_block_size, dev->min_block_size); + if (wlen-blen > 0) { memset(block->bufp, 0, wlen-blen); /* clear garbage */ } } + Dmsg4(100, "writing block of size %d to dev=%s with max_block_size %d and min_block_size %d\n", + wlen, dev->print_name(), dev->max_block_size, dev->min_block_size); + + checksum = ser_block_header(block, dev->do_checksum()); /* diff --git a/src/stored/block.h b/src/stored/block.h index d2ab3f459d6..cc69e25b034 100644 --- a/src/stored/block.h +++ b/src/stored/block.h @@ -28,7 +28,9 @@ #define __BLOCK_H 1 #define MAX_BLOCK_LENGTH 20000000 /* this is a sort of sanity check */ -#define DEFAULT_BLOCK_SIZE (512 * 126) /* 64,512 N.B. do not use 65,636 here */ +#define DEFAULT_BLOCK_SIZE (512 * 126) /* 64,512 N.B. do not use 65,536 here + the POSIX standard defaults the size of a + tape record to 126 blocks (63k). */ /* Block Header definitions. */ #define BLKHDR1_ID "BB01" diff --git a/src/stored/bscan.c b/src/stored/bscan.c index 00041273fe7..94f3de4184b 100644 --- a/src/stored/bscan.c +++ b/src/stored/bscan.c @@ -1391,7 +1391,7 @@ static JCR *create_jcr(JOB_DBR *jr, DEV_RECORD *rec, uint32_t JobId) jobjcr->VolSessionId = rec->VolSessionId; jobjcr->VolSessionTime = rec->VolSessionTime; jobjcr->ClientId = jr->ClientId; - jobjcr->dcr = jobjcr->read_dcr = new_dcr(jobjcr, NULL, dev); + jobjcr->dcr = jobjcr->read_dcr = new_dcr(jobjcr, NULL, dev, NULL); return jobjcr; } diff --git a/src/stored/butil.c b/src/stored/butil.c index deb1abbe172..24d5d35d556 100644 --- a/src/stored/butil.c +++ b/src/stored/butil.c @@ -171,7 +171,7 @@ static DCR *setup_to_access_device(JCR *jcr, char *dev_name, return NULL; } device->dev = dev; - jcr->dcr = dcr = new_dcr(jcr, NULL, dev); + jcr->dcr = dcr = new_dcr(jcr, NULL, dev, NULL); if (VolName[0]) { bstrncpy(dcr->VolumeName, VolName, sizeof(dcr->VolumeName)); } diff --git a/src/stored/dev.c b/src/stored/dev.c index a6670d59366..82f0fb14d29 100644 --- a/src/stored/dev.c +++ b/src/stored/dev.c @@ -118,6 +118,8 @@ m_init_dev(JCR *jcr, DEVRES *device, bool new_init) DEVICE *dev; uint32_t max_bs; + Dmsg1(400, "max_block_size in device res is %u\n", device->max_block_size); + /* If no device type specified, try to guess */ if (!device->dev_type) { /* Check that device is available */ @@ -172,14 +174,23 @@ m_init_dev(JCR *jcr, DEVRES *device, bool new_init) } dev->clear_slot(); /* unknown */ - /* Copy user supplied device parameters from Resource */ + /* + * Copy user supplied device parameters from Resource + */ dev->dev_name = get_memory(strlen(device->device_name)+1); pm_strcpy(dev->dev_name, device->device_name); dev->prt_name = get_memory(strlen(device->device_name) + strlen(device->hdr.name) + 20); - /* We edit "Resource-name" (physical-name) */ + + /* + * We edit "Resource-name" (physical-name) + */ Mmsg(dev->prt_name, "\"%s\" (%s)", device->hdr.name, device->device_name); Dmsg1(400, "Allocate dev=%s\n", dev->print_name()); dev->capabilities = device->cap_bits; + + /* + * current block sizes + */ dev->min_block_size = device->min_block_size; dev->max_block_size = device->max_block_size; dev->max_volume_size = device->max_volume_size; @@ -196,7 +207,10 @@ m_init_dev(JCR *jcr, DEVRES *device, bool new_init) dev->norewindonclose = device->norewindonclose; dev->dev_type = device->dev_type; dev->device = device; - /* Sanity check */ + + /* + * Sanity check + */ if (dev->vol_poll_interval && dev->vol_poll_interval < 60) { dev->vol_poll_interval = 60; } @@ -206,7 +220,8 @@ m_init_dev(JCR *jcr, DEVRES *device, bool new_init) dev->capabilities |= CAP_STREAM; /* set stream device */ } - /* If the device requires mount : + /* + * If the device requires mount : * - Check that the mount point is available * - Check that (un)mount commands are defined */ @@ -223,7 +238,9 @@ m_init_dev(JCR *jcr, DEVRES *device, bool new_init) } } - /* Sanity check */ + /* + * Sanity check + */ if (dev->max_block_size == 0) { max_bs = DEFAULT_BLOCK_SIZE; } else { @@ -289,7 +306,6 @@ m_init_dev(JCR *jcr, DEVRES *device, bool new_init) dev->set_mutex_priorities(); - #ifdef xxx if ((errstat = rwl_init(&dev->lock)) != 0) { berrno be; @@ -303,10 +319,113 @@ m_init_dev(JCR *jcr, DEVRES *device, bool new_init) dev->attached_dcrs = New(dlist(dcr, &dcr->dev_link)); Dmsg2(100, "init_dev: tape=%d dev_name=%s\n", dev->is_tape(), dev->dev_name); dev->initiated = true; + Dmsg3(100, "dev=%s dev_max_bs=%u max_bs=%u\n", dev->dev_name, dev->device->max_block_size, dev->max_block_size); return dev; } +/* + * Set the block size of the device. + * If the volume block size is zero, we set the max block size to what is + * configured in the device resource i.e. dev->device->max_block_size. + */ +void DEVICE::set_blocksizes(DCR *dcr) { + + DEVICE* dev = this; + JCR* jcr = dcr->jcr; + uint32_t max_bs; + + Dmsg3(100, "Device %s has dev_max_block_size of %u and max_block_size of %u\n", + dev->print_name(), dev->device->max_block_size, dev->max_block_size); + + if (dcr->VolMaxBlocksize == 0) { + Dmsg2(100, "setting dev->max_block_size to dev_max_block_size=%u " + "on device %s because dcr->VolMaxBlocksize is 0\n", + dev->device->max_block_size, dev->print_name()); + dev->min_block_size = dev->device->min_block_size; + dev->max_block_size = dev->device->max_block_size; + } else { + dev->min_block_size = dcr->VolMinBlocksize; + dev->max_block_size = dcr->VolMaxBlocksize; + } + + /* + * Sanity check + */ + if (dev->max_block_size == 0) { + max_bs = DEFAULT_BLOCK_SIZE; + } else { + max_bs = dev->max_block_size; + } + + if (dev->min_block_size > max_bs) { + Jmsg(jcr, M_ERROR_TERM, 0, _("Min block size > max on device %s\n"), dev->print_name()); + } + + if (dev->max_block_size > MAX_BLOCK_LENGTH) { + Jmsg3(jcr, M_ERROR, 0, _("Block size %u on device %s is too large, using default %u\n"), + dev->max_block_size, dev->print_name(), DEFAULT_BLOCK_SIZE); + dev->max_block_size = 0; + } + + if (dev->max_block_size % TAPE_BSIZE != 0) { + Jmsg3(jcr, M_WARNING, 0, _("Max block size %u not multiple of device %s block size=%d.\n"), + dev->max_block_size, dev->print_name(), TAPE_BSIZE); + } + + if (dev->max_volume_size != 0 && dev->max_volume_size < (dev->max_block_size << 4)) { + Jmsg(jcr, M_ERROR_TERM, 0, _("Max Vol Size < 8 * Max Block Size for device %s\n"), dev->print_name()); + } + + Dmsg3(100, "set minblocksize to %d, maxblocksize to %d on device %s\n", + dev->min_block_size, dev->max_block_size, dev->print_name()); + + /* + * If blocklen is not dev->max_block_size create a new block with the right size. + * (as header is always dev->label_block_size which is preset with DEFAULT_BLOCK_SIZE) + */ + if (dcr->block) { + if (dcr->block->buf_len != dev->max_block_size) { + Dmsg2(100, "created new block of buf_len: %u on device %s\n", + dev->max_block_size, dev->print_name()); + free_block(dcr->block); + dcr->block = new_block(dev); + Dmsg2(100, "created new block of buf_len: %u on device %s, freeing block\n", + dcr->block->buf_len, dev->print_name()); + } + } +} + +/* + * Set the block size of the device to the label_block_size + * to read labels as we want to always use that blocksize when + * writing volume labels + */ +void DEVICE::set_label_blocksize(DCR *dcr) +{ + DEVICE *dev = this; + + Dmsg3(100, "setting minblocksize to %u, " + "maxblocksize to label_block_size=%u, on device %s\n", + 0, dev->device->label_block_size, dev->print_name()); + + dev->min_block_size = 0; + + dev->max_block_size = dev->device->label_block_size; + /* + * If blocklen is not dev->max_block_size create a new block with the right size + * (as header is always label_block_size) + */ + if (dcr->block) { + if (dcr->block->buf_len != dev->max_block_size) { + free_block(dcr->block); + dcr->block = new_block(dev); + Dmsg2(100, "created new block of buf_len: %u on device %s\n", + dcr->block->buf_len, dev->print_name()); + } + } +} + /* * Open the device with the operating system and * initialize buffer pointers. diff --git a/src/stored/dev.h b/src/stored/dev.h index b499c71e79f..fa2061397da 100644 --- a/src/stored/dev.h +++ b/src/stored/dev.h @@ -192,6 +192,13 @@ struct VOLUME_CAT_INFO { char VolCatStatus[20]; /* Volume status */ char VolCatName[MAX_NAME_LENGTH]; /* Desired volume to mount */ char VolEncrKey[MAX_NAME_LENGTH]; /* Encryption Key needed to read the media */ + uint32_t VolMinBlocksize; /* Volume Minimum Blocksize */ + uint32_t VolMaxBlocksize; /* Volume Maximum Blocksize */ +}; + +struct BLOCKSIZES { + uint32_t max_block_size; + uint32_t min_block_size; }; class DEVRES; /* Device resource defined in stored_conf.h */ @@ -251,8 +258,8 @@ class DEVICE: public SMARTALLOC { uint64_t file_size; /* Current file size */ uint32_t EndBlock; /* last block written */ uint32_t EndFile; /* last file written */ - uint32_t min_block_size; /* min block size */ - uint32_t max_block_size; /* max block size */ + uint32_t min_block_size; /* min block size currently set */ + uint32_t max_block_size; /* max block size currently set */ uint32_t max_concurrent_jobs; /* maximum simultaneous jobs this drive */ uint64_t max_volume_size; /* max bytes to put on one volume */ uint64_t max_file_size; /* max file size to put in one file on volume */ @@ -415,6 +422,9 @@ class DEVICE: public SMARTALLOC { void set_slot(int32_t slot); /* in dev.c */ void clear_slot(); /* in dev.c */ + void set_blocksizes(DCR* dcr); /* in dev.c */ + void set_label_blocksize(DCR* dcr); /* in dev.c */ + uint32_t get_file() const { return file; }; uint32_t get_block_num() const { return block_num; }; int fd() const { return m_fd; }; @@ -538,6 +548,8 @@ class DCR { int64_t VolMediaId; /* MediaId */ int64_t job_spool_size; /* Current job spool size */ int64_t max_job_spool_size; /* Max job spool size */ + uint32_t VolMinBlocksize; /* Minimum Blocksize */ + uint32_t VolMaxBlocksize; /* Maximum Blocksize */ char VolumeName[MAX_NAME_LENGTH]; /* Volume name */ char pool_name[MAX_NAME_LENGTH]; /* Pool name */ char pool_type[MAX_NAME_LENGTH]; /* Pool type */ @@ -610,7 +622,6 @@ class DCR { /* Methods in label.c */ bool rewrite_volume_label(bool recycle); - }; /* Get some definition of function to position diff --git a/src/stored/dir_cmd.c b/src/stored/dir_cmd.c index 0a7babcb48d..50a16cfdca8 100644 --- a/src/stored/dir_cmd.c +++ b/src/stored/dir_cmd.c @@ -58,10 +58,10 @@ static char cancelcmd[] = "cancel Job=%127s"; static char relabelcmd[] = "relabel %127s OldName=%127s NewName=%127s PoolName=%127s " - "MediaType=%127s Slot=%d drive=%d"; + "MediaType=%127s Slot=%d drive=%d MinBlocksize=%d MaxBlocksize=%d"; static char labelcmd[] = "label %127s VolumeName=%127s PoolName=%127s " - "MediaType=%127s Slot=%d drive=%d"; + "MediaType=%127s Slot=%d drive=%d MinBlocksize=%d MaxBlocksize=%d"; static char mountslotcmd[] = "mount %127s drive=%d slot=%d"; static char mountcmd[] = @@ -136,7 +136,7 @@ static bool setbandwidth_cmd(JCR *jcr); static bool setdebug_cmd(JCR *jcr); static bool unmount_cmd(JCR *jcr); -static DCR *find_device(JCR *jcr, POOL_MEM &dev_name, int drive); +static DCR *find_device(JCR *jcr, POOL_MEM &dev_name, int drive, BLOCKSIZES *blocksizes); static void read_volume_label(JCR *jcr, DCR *dcr, DEVICE *dev, int Slot); static void label_volume_if_ok(DCR *dcr, char *oldname, char *newname, char *poolname, @@ -578,8 +578,10 @@ static bool do_label(JCR *jcr, bool relabel) BSOCK *dir = jcr->dir_bsock; DCR *dcr; DEVICE *dev; + BLOCKSIZES blocksizes; bool ok = false; int32_t slot, drive; + //, max_block_size, min_block_size; /* * Determine the length of the temporary buffers. @@ -600,25 +602,35 @@ static bool do_label(JCR *jcr, bool relabel) mediatype = get_memory(len); if (relabel) { if (sscanf(dir->msg, relabelcmd, dev_name.c_str(), oldname, - newname, poolname, mediatype, &slot, &drive) == 7) { + newname, poolname, mediatype, &slot, &drive, + &blocksizes.min_block_size, &blocksizes.max_block_size) == 9) { ok = true; } } else { *oldname = 0; if (sscanf(dir->msg, labelcmd, dev_name.c_str(), newname, - poolname, mediatype, &slot, &drive) == 6) { + poolname, mediatype, &slot, &drive, + &blocksizes.min_block_size, &blocksizes.max_block_size) == 8) { ok = true; } } + if (ok) { unbash_spaces(newname); unbash_spaces(oldname); unbash_spaces(poolname); unbash_spaces(mediatype); - dcr = find_device(jcr, dev_name, drive); + + dcr = find_device(jcr, dev_name, drive, &blocksizes); if (dcr) { dev = dcr->dev; + + dev->Lock(); /* Use P to avoid indefinite block */ + dcr->VolMinBlocksize = blocksizes.min_block_size; + dcr->VolMaxBlocksize = blocksizes.max_block_size; + dev->set_blocksizes(dcr); /* apply blocksizes from dcr to dev */ + if (!dev->is_open() && !dev->is_busy()) { Dmsg1(400, "Can %slabel. Device is not open\n", relabel ? "re" : ""); label_volume_if_ok(dcr, oldname, newname, poolname, slot, relabel); @@ -801,7 +813,7 @@ static bool read_label(DCR *dcr) /* * Searches for device by name, and if found, creates a dcr and returns it. */ -static DCR *find_device(JCR *jcr, POOL_MEM &devname, int drive) +static DCR *find_device(JCR *jcr, POOL_MEM &devname, int drive, BLOCKSIZES *blocksizes) { DEVRES *device; AUTOCHANGERRES *changer; @@ -862,7 +874,7 @@ static DCR *find_device(JCR *jcr, POOL_MEM &devname, int drive) if (found) { Dmsg1(100, "Found device %s\n", device->hdr.name); - dcr = new_dcr(jcr, NULL, device->dev); + dcr = new_dcr(jcr, NULL, device->dev, blocksizes); dcr->device = device; } return dcr; @@ -888,7 +900,7 @@ static bool mount_cmd(JCR *jcr) Dmsg3(100, "ok=%d drive=%d slot=%d\n", ok, drive, slot); if (ok) { - dcr = find_device(jcr, devname, drive); + dcr = find_device(jcr, devname, drive, NULL); if (dcr) { dev = dcr->dev; dev->Lock(); /* Use P to avoid indefinite block */ @@ -1038,7 +1050,7 @@ static bool unmount_cmd(JCR *jcr) int32_t drive; if (sscanf(dir->msg, unmountcmd, devname.c_str(), &drive) == 2) { - dcr = find_device(jcr, devname, drive); + dcr = find_device(jcr, devname, drive, NULL); if (dcr) { dev = dcr->dev; dev->Lock(); /* Use P to avoid indefinite block */ @@ -1173,7 +1185,7 @@ static bool release_cmd(JCR *jcr) int32_t drive; if (sscanf(dir->msg, releasecmd, devname.c_str(), &drive) == 2) { - dcr = find_device(jcr, devname, drive); + dcr = find_device(jcr, devname, drive, NULL); if (dcr) { dev = dcr->dev; dev->Lock(); /* Use P to avoid indefinite block */ @@ -1328,7 +1340,7 @@ static bool changer_cmd(JCR *jcr) is_transfer = true; } if (ok) { - dcr = find_device(jcr, devname, -1); + dcr = find_device(jcr, devname, -1, NULL); if (dcr) { dev = dcr->dev; dev->Lock(); /* Use P to avoid indefinite block */ @@ -1378,7 +1390,7 @@ static bool readlabel_cmd(JCR *jcr) if (sscanf(dir->msg, readlabelcmd, devname.c_str(), &Slot, &drive) == 3) { - dcr = find_device(jcr, devname, drive); + dcr = find_device(jcr, devname, drive, NULL); if (dcr) { dev = dcr->dev; dev->Lock(); /* Use P to avoid indefinite block */ diff --git a/src/stored/label.c b/src/stored/label.c index 90a6feba4c6..cb95cfca28b 100644 --- a/src/stored/label.c +++ b/src/stored/label.c @@ -67,9 +67,19 @@ int read_dev_volume_label(DCR *dcr) bool want_ansi_label; bool have_ansi_label = false; - Dmsg4(100, "Enter read_volume_label res=%d device=%s vol=%s dev_Vol=%s\n", + /* + * We always write the label in an 64512 byte / 63k block. + * so we never have problems reading the volume label. + */ + + /* + * Set the default blocksize to read the label + */ + dev->set_label_blocksize(dcr); + + Dmsg5(100, "Enter read_volume_label res=%d device=%s vol=%s dev_Vol=%s max_blocksize=%u\n", dev->num_reserved(), dev->print_name(), VolName, - dev->VolHdr.VolumeName[0]?dev->VolHdr.VolumeName:"*NULL*"); + dev->VolHdr.VolumeName[0]?dev->VolHdr.VolumeName:"*NULL*", dev->max_block_size); if (!dev->is_open()) { if (!dev->open(dcr, OPEN_READ_ONLY)) { @@ -259,7 +269,7 @@ int read_dev_volume_label(DCR *dcr) * the return value e.g. although we think the volume label is ok the plugin * has reasons to override that. So when the plugin returns something else * then bRC_OK it want to tell us the volume is not OK to use and as - * such we return VOL_NAME_ERROR as error although it might not be te + * such we return VOL_NAME_ERROR as error although it might not be the * best error it should be sufficient. */ if (generate_plugin_event(jcr, bsdEventLabelVerified, dcr) != bRC_OK) { @@ -268,6 +278,13 @@ int read_dev_volume_label(DCR *dcr) goto bail_out; } empty_block(block); + + /* + * reset blocksizes from volinfo to device as we set blocksize to + * DEFAULT_BLOCK_SIZE to read the label + */ + dev->set_blocksizes(dcr); + return VOL_OK; bail_out: @@ -328,12 +345,16 @@ bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, DEVICE *dev = dcr->dev; DEV_BLOCK *block = dcr->block; + /* + * Set the default blocksize to read the label + */ + dev->set_label_blocksize(dcr); + Dmsg0(150, "write_volume_label()\n"); if (*VolName == 0) { Pmsg0(0, "=== ERROR: write_new_volume_label_to_dev called with NULL VolName\n"); goto bail_out; } - if (relabel) { volume_unused(dcr); /* mark current volume unused */ /* Truncate device */ @@ -349,6 +370,8 @@ bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, dev->setVolCatName(VolName); dcr->setVolCatName(VolName); Dmsg1(150, "New VolName=%s\n", VolName); + + if (!dev->open(dcr, OPEN_READ_WRITE)) { /* If device is not tape, attempt to create it */ if (dev->is_tape() || !dev->open(dcr, CREATE_READ_WRITE)) { @@ -379,6 +402,7 @@ bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, /* Temporarily mark in append state to enable writing */ dev->set_append(); + /* Create PRE_LABEL */ create_volume_label(dev, VolName, PoolName); @@ -400,6 +424,11 @@ bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, dcr->rec->Stream = 0; dcr->rec->maskedStream = 0; + /* + * Set the label blocksize to read the label + */ + dev->set_label_blocksize(dcr); + if (!write_record_to_block(dcr, dcr->rec)) { Dmsg2(130, "Bad Label write on %s: ERR=%s\n", dev->print_name(), dev->print_errmsg()); goto bail_out; @@ -436,6 +465,12 @@ bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, dev = dcr->dev; /* may have changed in reserve_volume */ dev->clear_append(); /* remove append since this is PRE_LABEL */ + + /* + * Reset blocksizes from volinfo to device as we set blocksize to DEFAULT_BLOCK_SIZE to read the label. + */ + dev->set_blocksizes(dcr); + return true; bail_out: @@ -456,6 +491,11 @@ bool DCR::rewrite_volume_label(bool recycle) { DCR *dcr = this; + /* + * Set the label blocksize to write the label + */ + dev->set_label_blocksize(dcr); + if (!dev->open(dcr, OPEN_READ_WRITE)) { Jmsg3(jcr, M_WARNING, 0, _("Open device %s Volume \"%s\" failed: ERR=%s\n"), dev->print_name(), dcr->VolumeName, dev->bstrerror()); @@ -572,6 +612,12 @@ bool DCR::rewrite_volume_label(bool recycle) */ Dmsg1(150, "OK from rewrite vol label. Vol=%s\n", dcr->VolumeName); + /* + * reset blocksizes from volinfo to device as we set blocksize to + * DEFAULT_BLOCK_SIZE to write the label + */ + dev->set_blocksizes(dcr); + /* * Let any stored plugin know the label was rewritten and as such is verified . */ diff --git a/src/stored/mount.c b/src/stored/mount.c index fea6178a3a3..ff376564d04 100644 --- a/src/stored/mount.c +++ b/src/stored/mount.c @@ -237,7 +237,21 @@ bool DCR::mount_next_write_volume() if (!find_a_volume()) { goto mount_next_vol; } + dev->VolCatInfo = VolCatInfo; /* structure assignment */ + + /* + * Apply the Volume Blocksizes to device + */ + dcr->VolMinBlocksize = VolCatInfo.VolMinBlocksize; + dcr->VolMaxBlocksize = VolCatInfo.VolMaxBlocksize; + Dmsg3(200, "applying vol block sizes to device %s: dcr->VolMinBlocksize set to %u, dcr->VolMaxBlocksize set to %u\n", + dev->print_name(), dcr->VolMinBlocksize, dcr->VolMaxBlocksize); + + /* + * Set the block sizes of the dcr in the device. + */ + dev->set_blocksizes(dcr); } /* diff --git a/src/stored/protos.h b/src/stored/protos.h index dafdf0af0c6..29f4b5917f9 100644 --- a/src/stored/protos.h +++ b/src/stored/protos.h @@ -32,7 +32,7 @@ DCR *acquire_device_for_append(DCR *dcr); bool acquire_device_for_read(DCR *dcr); bool release_device(DCR *dcr); bool clean_device(DCR *dcr); -DCR *new_dcr(JCR *jcr, DCR *dcr, DEVICE *dev); +DCR *new_dcr(JCR *jcr, DCR *dcr, DEVICE *dev, BLOCKSIZES *blocksizes); void free_dcr(DCR *dcr); /* append.c */ diff --git a/src/stored/reserve.c b/src/stored/reserve.c index dfac4eb2ed7..eb6ea1e925b 100644 --- a/src/stored/reserve.c +++ b/src/stored/reserve.c @@ -247,7 +247,7 @@ static bool use_device_cmd(JCR *jcr) #endif init_jcr_device_wait_timers(jcr); - jcr->dcr = new_dcr(jcr, NULL, NULL); /* get a dcr */ + jcr->dcr = new_dcr(jcr, NULL, NULL, NULL); /* get a dcr */ if (!jcr->dcr) { BSOCK *dir = jcr->dir_bsock; dir->fsend(_("3939 Could not get dcr\n")); @@ -645,9 +645,9 @@ static int reserve_device(RCTX &rctx) rctx.suitable_device = true; Dmsg1(dbglvl, "try reserve %s\n", rctx.device->hdr.name); if (rctx.store->append) { - dcr = new_dcr(rctx.jcr, rctx.jcr->dcr, rctx.device->dev); + dcr = new_dcr(rctx.jcr, rctx.jcr->dcr, rctx.device->dev, NULL); } else { - dcr = new_dcr(rctx.jcr, rctx.jcr->read_dcr, rctx.device->dev); + dcr = new_dcr(rctx.jcr, rctx.jcr->read_dcr, rctx.device->dev, NULL); } if (!dcr) { BSOCK *dir = rctx.jcr->dir_bsock; diff --git a/src/stored/sd_plugins.c b/src/stored/sd_plugins.c index 4de52080bee..55d27758ca1 100644 --- a/src/stored/sd_plugins.c +++ b/src/stored/sd_plugins.c @@ -30,7 +30,7 @@ #include "sd_plugins.h" #include "lib/crypto_cache.h" -const int dbglvl = 150; +const int dbglvl = 250; const char *plugin_type = "-sd.so"; static alist *sd_plugin_list = NULL; diff --git a/src/stored/spool.c b/src/stored/spool.c index 4b28468dd40..840dec345eb 100644 --- a/src/stored/spool.c +++ b/src/stored/spool.c @@ -262,7 +262,7 @@ static bool despool_data(DCR *dcr, bool commit) rdev->max_block_size = dcr->dev->max_block_size; rdev->min_block_size = dcr->dev->min_block_size; rdev->device = dcr->dev->device; - rdcr = new_dcr(jcr, NULL, rdev); + rdcr = new_dcr(jcr, NULL, rdev, NULL); rdcr->spool_fd = dcr->spool_fd; block = dcr->block; /* save block */ dcr->block = rdcr->block; /* make read and write block the same */ diff --git a/src/stored/stored.c b/src/stored/stored.c index 202c1f2fed6..039419eed8f 100644 --- a/src/stored/stored.c +++ b/src/stored/stored.c @@ -629,7 +629,7 @@ void *device_initialization(void *arg) continue; } - jcr->dcr = dcr = new_dcr(jcr, NULL, dev); + jcr->dcr = dcr = new_dcr(jcr, NULL, dev, NULL); generate_plugin_event(jcr, bsdEventDeviceInit, dcr); if (dev->is_autochanger()) { /* If autochanger set slot in dev structure */ diff --git a/src/stored/stored.h b/src/stored/stored.h index 9d3b6395115..eff5c969d5e 100644 --- a/src/stored/stored.h +++ b/src/stored/stored.h @@ -62,6 +62,7 @@ const int sd_dbglvl = 300; #include "jcr.h" #include "vol_mgr.h" #include "reserve.h" + #include "protos.h" #ifdef HAVE_FNMATCH #include diff --git a/src/stored/stored_conf.c b/src/stored/stored_conf.c index 9bd13b0f0d2..91436bfcc61 100644 --- a/src/stored/stored_conf.c +++ b/src/stored/stored_conf.c @@ -196,6 +196,7 @@ static RES_ITEM dev_items[] = { { "maximumnetworkbuffersize", store_pint32, ITEM(res_dev.max_network_buffer_size), 0, 0, NULL }, { "volumepollinterval", store_time, ITEM(res_dev.vol_poll_interval), 0, ITEM_DEFAULT, "300" /* 5 minutes */ }, { "maximumrewindwait", store_time, ITEM(res_dev.max_rewind_wait), 0, ITEM_DEFAULT, "300" /* 5 minutes */ }, + { "labelblocksize", store_pint32, ITEM(res_dev.label_block_size), 0, ITEM_DEFAULT, "64512"/* DEFAULT_BLOCK_SIZE */ }, { "minimumblocksize", store_pint32, ITEM(res_dev.min_block_size), 0, 0, NULL }, { "maximumblocksize", store_maxblocksize, ITEM(res_dev.max_block_size), 0, 0, NULL }, { "maximumvolumesize", store_size64, ITEM(res_dev.max_volume_size), 0, ITEM_DEPRECATED, NULL }, diff --git a/src/stored/stored_conf.h b/src/stored/stored_conf.h index 04dea0f9901..a134be47bad 100644 --- a/src/stored/stored_conf.h +++ b/src/stored/stored_conf.h @@ -157,8 +157,9 @@ class DEVRES { utime_t max_rewind_wait; /* Maximum secs to wait for rewind */ utime_t max_open_wait; /* Maximum secs to wait for open */ uint32_t max_open_vols; /* Maximum simultaneous open volumes */ - uint32_t min_block_size; /* Min block size */ - uint32_t max_block_size; /* Max block size */ + uint32_t label_block_size; /* block size of the label block*/ + uint32_t min_block_size; /* Current Minimum block size */ + uint32_t max_block_size; /* Current Maximum block size */ uint32_t max_volume_jobs; /* Max jobs to put on one volume */ uint32_t max_network_buffer_size; /* Max network buf size */ uint32_t max_concurrent_jobs; /* Maximum concurrent jobs this drive */