From 4e4c9c7de494925690cbb2da7518b77458bd0de3 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Sun, 7 Mar 2004 10:20:24 +0000 Subject: [PATCH] Implement first cut DCR in SD git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1113 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/kernstodo | 17 +- bacula/src/cats/postgresql.c | 354 +++++++++++++++++----------------- bacula/src/cats/sql_get.c | 2 +- bacula/src/dird/ua_tree.c | 23 ++- bacula/src/findlib/find_one.c | 249 ++++++++++++------------ bacula/src/jcr.h | 20 +- bacula/src/lib/bsys.c | 2 +- bacula/src/lib/edit.c | 10 +- bacula/src/lib/message.c | 4 +- bacula/src/stored/acquire.c | 73 +++++-- bacula/src/stored/append.c | 119 +++++++++--- bacula/src/stored/askdir.c | 15 +- bacula/src/stored/bcopy.c | 7 +- bacula/src/stored/bextract.c | 2 +- bacula/src/stored/block.c | 42 ++-- bacula/src/stored/bls.c | 2 +- bacula/src/stored/bscan.c | 81 ++++---- bacula/src/stored/btape.c | 22 ++- bacula/src/stored/butil.c | 11 +- bacula/src/stored/dev.c | 7 + bacula/src/stored/dev.h | 253 +++++++++++++----------- bacula/src/stored/device.c | 42 ++-- bacula/src/stored/dircmd.c | 3 + bacula/src/stored/job.c | 6 +- bacula/src/stored/label.c | 26 +-- bacula/src/stored/mount.c | 4 +- bacula/src/stored/protos.h | 220 ++++++++++----------- bacula/src/stored/read.c | 20 +- bacula/src/stored/stored.c | 9 +- bacula/src/version.h | 4 +- 30 files changed, 934 insertions(+), 715 deletions(-) diff --git a/bacula/kernstodo b/bacula/kernstodo index 5bc288d7c1..29290c4bc8 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -106,9 +106,20 @@ For 1.33 Do both a long and short form. - Later: -- Add a regression test for dbcheck. -- Add disk seeking on restore. -- Allow for optional cancelling of SD and FD in case DIR +- Add John's appended files: + Appended = { /files/server/logs/http/*log } + and such files would be treated as follows.On a FULL backup, they would + be backed up like any other file.On an INCREMENTAL backup, where a + previous INCREMENTAL or FULL was already in thecatalogue and the length + of the file wasgreater than the length of the last backup, only thedata + added since the last backup will be dumped.On an INCREMENTAL backup, if + the length of the file is less than thelength of the file with the same + name last backed up, the completefile is dumped.On Windows systems, with + creation date of files, we can be evensmarter about this and not count + entirely upon the length.On a restore, the full and all incrementals + since it will beapplied in sequence to restore the file. - Add a + regression test for dbcheck. - Add disk seeking on restore. - Allow + for optional cancelling of SD and FD in case DIR gets a fatal error. Requested by Jesse Guardiani - Bizarre message: Error: Could not open WriteBootstrap file: - Build console in client only build. diff --git a/bacula/src/cats/postgresql.c b/bacula/src/cats/postgresql.c index 91b4493743..611ad53a19 100644 --- a/bacula/src/cats/postgresql.c +++ b/bacula/src/cats/postgresql.c @@ -117,6 +117,7 @@ int db_open_database(JCR *jcr, B_DB *mdb) { int errstat; + char port[10]; P(mutex); if (mdb->connected) { @@ -132,12 +133,13 @@ db_open_database(JCR *jcr, B_DB *mdb) return 0; } + bsnprintf(port, sizeof(port), "%d", mdb->db_port); /* connect to the database */ mdb->db = PQsetdbLogin( mdb->db_address, /* default = localhost */ - (char *) mdb->db_port, /* default port */ - NULL, /* pg options */ - NULL, /* tty, ignored */ + port, /* default port */ + NULL, /* pg options */ + NULL, /* tty, ignored */ mdb->db_name, /* database name */ mdb->db_user, /* login name */ mdb->db_password); /* password */ @@ -146,9 +148,9 @@ db_open_database(JCR *jcr, B_DB *mdb) if (PQstatus(mdb->db) != CONNECTION_OK) { mdb->db = PQsetdbLogin( mdb->db_address, /* default = localhost */ - (char *) mdb->db_port, /* default port */ - NULL, /* pg options */ - NULL, /* tty, ignored */ + port, /* default port */ + NULL, /* pg options */ + NULL, /* tty, ignored */ mdb->db_name, /* database name */ mdb->db_user, /* login name */ mdb->db_password); /* password */ @@ -290,214 +292,212 @@ int db_sql_query(B_DB *mdb, char *query, DB_RESULT_HANDLER *result_handler, void POSTGRESQL_ROW my_postgresql_fetch_row(B_DB *mdb) { - int j; - POSTGRESQL_ROW row = NULL; // by default, return NULL + int j; + POSTGRESQL_ROW row = NULL; // by default, return NULL - Dmsg0(50, "my_postgresql_fetch_row start\n"); + Dmsg0(50, "my_postgresql_fetch_row start\n"); - if (mdb->row_number == -1 || mdb->row == NULL) { + if (mdb->row_number == -1 || mdb->row == NULL) { + Dmsg1(50, "we have need space of %d bytes\n", sizeof(char *) * mdb->num_fields); - Dmsg1(50, "we have need space of %d bytes\n", sizeof(char *) * mdb->num_fields); - - if (mdb->row != NULL) { - Dmsg0(50, "my_postgresql_fetch_row freeing space\n"); - free(mdb->row); - mdb->row = NULL; - } + if (mdb->row != NULL) { + Dmsg0(50, "my_postgresql_fetch_row freeing space\n"); + free(mdb->row); + mdb->row = NULL; + } - mdb->row = (POSTGRESQL_ROW) malloc(sizeof(char *) * mdb->num_fields); + mdb->row = (POSTGRESQL_ROW) malloc(sizeof(char *) * mdb->num_fields); - // now reset the row_number now that we have the space allocated - mdb->row_number = 0; - } + // now reset the row_number now that we have the space allocated + mdb->row_number = 0; + } - // if still within the result set - if (mdb->row_number < mdb->num_rows) { - Dmsg2(50, "my_postgresql_fetch_row row number '%d' is acceptable (0..%d)\n", mdb->row_number, mdb->num_rows); - // get each value from this row - for (j = 0; j < mdb->num_fields; j++) { - mdb->row[j] = PQgetvalue(mdb->result, mdb->row_number, j); - Dmsg2(50, "my_postgresql_fetch_row field '%d' has value '%s'\n", j, mdb->row[j]); - } - // increment the row number for the next call - mdb->row_number++; + // if still within the result set + if (mdb->row_number < mdb->num_rows) { + Dmsg2(50, "my_postgresql_fetch_row row number '%d' is acceptable (0..%d)\n", mdb->row_number, mdb->num_rows); + // get each value from this row + for (j = 0; j < mdb->num_fields; j++) { + mdb->row[j] = PQgetvalue(mdb->result, mdb->row_number, j); + Dmsg2(50, "my_postgresql_fetch_row field '%d' has value '%s'\n", j, mdb->row[j]); + } + // increment the row number for the next call + mdb->row_number++; - row = mdb->row; - } else { - Dmsg2(50, "my_postgresql_fetch_row row number '%d' is NOT acceptable (0..%d)\n", mdb->row_number, mdb->num_rows); - } + row = mdb->row; + } else { + Dmsg2(50, "my_postgresql_fetch_row row number '%d' is NOT acceptable (0..%d)\n", mdb->row_number, mdb->num_rows); + } - Dmsg1(50, "my_postgresql_fetch_row finishes returning %x\n", row); + Dmsg1(50, "my_postgresql_fetch_row finishes returning %x\n", row); - return row; + return row; } int my_postgresql_max_length(B_DB *mdb, int field_num) { - // - // for a given column, find the max length - // - int max_length; - int i; - int this_length; - - max_length = 0; - for (i = 0; i < mdb->num_rows; i++) { - if (PQgetisnull(mdb->result, i, field_num)) { - this_length = 4; // "NULL" - } else { - this_length = strlen(PQgetvalue(mdb->result, i, field_num)); - } - - if (max_length < this_length) { - max_length = this_length; - } - } - - return max_length; + // + // for a given column, find the max length + // + int max_length; + int i; + int this_length; + + max_length = 0; + for (i = 0; i < mdb->num_rows; i++) { + if (PQgetisnull(mdb->result, i, field_num)) { + this_length = 4; // "NULL" + } else { + this_length = strlen(PQgetvalue(mdb->result, i, field_num)); + } + + if (max_length < this_length) { + max_length = this_length; + } + } + + return max_length; } POSTGRESQL_FIELD * my_postgresql_fetch_field(B_DB *mdb) { - int i; - - Dmsg0(50, "my_postgresql_fetch_field starts\n"); - if (mdb->fields == NULL) { - Dmsg1(50, "allocating space for %d fields\n", mdb->num_fields); - mdb->fields = (POSTGRESQL_FIELD *) - malloc(sizeof(POSTGRESQL_FIELD) * mdb->num_fields); - - for (i = 0; i < mdb->num_fields; i++) { - Dmsg1(50, "filling field %d\n", i); - mdb->fields[i].name = PQfname(mdb->result, i); - mdb->fields[i].max_length = my_postgresql_max_length(mdb, i); - mdb->fields[i].type = PQftype(mdb->result, i); - mdb->fields[i].flags = 0; - - Dmsg4(50, "my_postgresql_fetch_field finds field '%s' has length='%d' type='%d' and IsNull=%d\n", - mdb->fields[i].name, mdb->fields[i].max_length, mdb->fields[i].type, - mdb->fields[i].flags); - } // end for - } // end if - - // increment field number for the next time around - - Dmsg0(50, "my_postgresql_fetch_field finishes\n"); - return &mdb->fields[mdb->field_number++]; + int i; + + Dmsg0(50, "my_postgresql_fetch_field starts\n"); + if (mdb->fields == NULL) { + Dmsg1(50, "allocating space for %d fields\n", mdb->num_fields); + mdb->fields = (POSTGRESQL_FIELD *)malloc(sizeof(POSTGRESQL_FIELD) * mdb->num_fields); + + for (i = 0; i < mdb->num_fields; i++) { + Dmsg1(50, "filling field %d\n", i); + mdb->fields[i].name = PQfname(mdb->result, i); + mdb->fields[i].max_length = my_postgresql_max_length(mdb, i); + mdb->fields[i].type = PQftype(mdb->result, i); + mdb->fields[i].flags = 0; + + Dmsg4(50, "my_postgresql_fetch_field finds field '%s' has length='%d' type='%d' and IsNull=%d\n", + mdb->fields[i].name, mdb->fields[i].max_length, mdb->fields[i].type, + mdb->fields[i].flags); + } // end for + } // end if + + // increment field number for the next time around + + Dmsg0(50, "my_postgresql_fetch_field finishes\n"); + return &mdb->fields[mdb->field_number++]; } void my_postgresql_data_seek(B_DB *mdb, int row) { - // set the row number to be returned on the next call - // to my_postgresql_fetch_row - mdb->row_number = row; + // set the row number to be returned on the next call + // to my_postgresql_fetch_row + mdb->row_number = row; } void my_postgresql_field_seek(B_DB *mdb, int field) { - mdb->field_number = field; + mdb->field_number = field; } int my_postgresql_query(B_DB *mdb, char *query) { - Dmsg0(50, "my_postgresql_query started\n"); - // We are starting a new query. reset everything. - mdb->num_rows = -1; - mdb->row_number = -1; - mdb->field_number = -1; - - - Dmsg1(50, "my_postgresql_query starts with '%s'\n", query); - mdb->result = PQexec(mdb->db, query); - mdb->status = PQresultStatus(mdb->result); - if (mdb->status == PGRES_TUPLES_OK || mdb->status == PGRES_COMMAND_OK) { - Dmsg1(50, "we have a result\n", query); - - // how many fields in the set? - mdb->num_fields = (int) PQnfields(mdb->result); - Dmsg1(50, "we have %d fields\n", mdb->num_fields); - - mdb->num_rows = PQntuples(mdb->result); - Dmsg1(50, "we have %d rows\n", mdb->num_rows); - - mdb->status = 0; - } else { - Dmsg1(50, "we failed\n", query); - mdb->status = 1; - } + Dmsg0(50, "my_postgresql_query started\n"); + // We are starting a new query. reset everything. + mdb->num_rows = -1; + mdb->row_number = -1; + mdb->field_number = -1; + + + Dmsg1(50, "my_postgresql_query starts with '%s'\n", query); + mdb->result = PQexec(mdb->db, query); + mdb->status = PQresultStatus(mdb->result); + if (mdb->status == PGRES_TUPLES_OK || mdb->status == PGRES_COMMAND_OK) { + Dmsg1(50, "we have a result\n", query); + + // how many fields in the set? + mdb->num_fields = (int) PQnfields(mdb->result); + Dmsg1(50, "we have %d fields\n", mdb->num_fields); + + mdb->num_rows = PQntuples(mdb->result); + Dmsg1(50, "we have %d rows\n", mdb->num_rows); + + mdb->status = 0; + } else { + Dmsg1(50, "we failed\n", query); + mdb->status = 1; + } - Dmsg0(50, "my_postgresql_query finishing\n"); + Dmsg0(50, "my_postgresql_query finishing\n"); - return mdb->status; + return mdb->status; } void my_postgresql_free_result (B_DB *mdb) { - if (mdb->result) { - PQclear(mdb->result); - } - - if (mdb->row) { - free(mdb->row); - mdb->row = NULL; - } - - if (mdb->fields) { - free(mdb->fields); - mdb->fields = NULL; - } + if (mdb->result) { + PQclear(mdb->result); + } + + if (mdb->row) { + free(mdb->row); + mdb->row = NULL; + } + + if (mdb->fields) { + free(mdb->fields); + mdb->fields = NULL; + } } int my_postgresql_currval(B_DB *mdb, char *table_name) { - // Obtain the current value of the sequence that - // provides the serial value for primary key of the table. - - // currval is local to our session. It is not affected by - // other transactions. - - // Determine the name of the sequence. - // PostgreSQL automatically creates a sequence using - // __seq. - // At the time of writing, all tables used this format for - // for their primary key:
id - // Except for basefiles which has a primary key on baseid. - // Therefore, we need to special case that one table. - - // everything else can use the PostgreSQL formula. - - char sequence[NAMEDATALEN-1]; - char query [NAMEDATALEN+50]; - PGresult *result; - int id = 0; - - if (strcasecmp(table_name, "basefiles") == 0) { - bstrncpy(sequence, "basefiles_baseid", sizeof(sequence)); - } else { - bstrncpy(sequence, table_name, sizeof(sequence)); - bstrncat(sequence, "_", sizeof(sequence)); - bstrncat(sequence, table_name, sizeof(sequence)); - bstrncat(sequence, "id", sizeof(sequence)); - } - - bstrncat(sequence, "_seq", sizeof(sequence)); - bsnprintf(query, sizeof(query), "SELECT currval('%s')", sequence); - -// Mmsg(&query, "SELECT currval('%s')", sequence); - Dmsg1(50, "my_postgresql_currval invoked with '%s'\n", query); - result = PQexec(mdb->db, query); - - Dmsg0(50, "exec done"); - - if (PQresultStatus(result) == PGRES_TUPLES_OK) { - Dmsg0(50, "getting value"); - id = atoi(PQgetvalue(result, 0, 0)); - Dmsg2(50, "got value '%s' which became %d\n", PQgetvalue(result, 0, 0), id); - } else { - Mmsg1(&mdb->errmsg, _("error fetching currval: %s\n"), PQerrorMessage(mdb->db)); - } - - PQclear(result); - - return id; + // Obtain the current value of the sequence that + // provides the serial value for primary key of the table. + + // currval is local to our session. It is not affected by + // other transactions. + + // Determine the name of the sequence. + // PostgreSQL automatically creates a sequence using + //
__seq. + // At the time of writing, all tables used this format for + // for their primary key:
id + // Except for basefiles which has a primary key on baseid. + // Therefore, we need to special case that one table. + + // everything else can use the PostgreSQL formula. + + char sequence[NAMEDATALEN-1]; + char query [NAMEDATALEN+50]; + PGresult *result; + int id = 0; + + if (strcasecmp(table_name, "basefiles") == 0) { + bstrncpy(sequence, "basefiles_baseid", sizeof(sequence)); + } else { + bstrncpy(sequence, table_name, sizeof(sequence)); + bstrncat(sequence, "_", sizeof(sequence)); + bstrncat(sequence, table_name, sizeof(sequence)); + bstrncat(sequence, "id", sizeof(sequence)); + } + + bstrncat(sequence, "_seq", sizeof(sequence)); + bsnprintf(query, sizeof(query), "SELECT currval('%s')", sequence); + +// Mmsg(&query, "SELECT currval('%s')", sequence); + Dmsg1(50, "my_postgresql_currval invoked with '%s'\n", query); + result = PQexec(mdb->db, query); + + Dmsg0(50, "exec done"); + + if (PQresultStatus(result) == PGRES_TUPLES_OK) { + Dmsg0(50, "getting value"); + id = atoi(PQgetvalue(result, 0, 0)); + Dmsg2(50, "got value '%s' which became %d\n", PQgetvalue(result, 0, 0), id); + } else { + Mmsg1(&mdb->errmsg, _("error fetching currval: %s\n"), PQerrorMessage(mdb->db)); + } + + PQclear(result); + + return id; } diff --git a/bacula/src/cats/sql_get.c b/bacula/src/cats/sql_get.c index 34dcb299f0..6d9cad59fc 100644 --- a/bacula/src/cats/sql_get.c +++ b/bacula/src/cats/sql_get.c @@ -296,7 +296,7 @@ int db_get_job_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr) jr->JobStatus = (int)*row[9]; jr->Type = (int)*row[10]; jr->Level = (int)*row[11]; - jr->ClientId = str_to_uint64(row[12]); + jr->ClientId = str_to_uint64(row[12]!=NULL?row[12]:(char *)""); sql_free_result(mdb); db_unlock(mdb); diff --git a/bacula/src/dird/ua_tree.c b/bacula/src/dird/ua_tree.c index 7bc68576cf..7af685a6c1 100644 --- a/bacula/src/dird/ua_tree.c +++ b/bacula/src/dird/ua_tree.c @@ -183,14 +183,21 @@ int insert_tree_handler(void *ctx, int num_fields, char **row) } else { tree->avail_node = NULL; /* added node to tree */ } - new_node->FileIndex = atoi(row[2]); - new_node->JobId = (JobId_t)str_to_int64(row[3]); - new_node->type = type; - new_node->extract = true; /* extract all by default */ - new_node->hard_link = hard_link; - new_node->soft_link = S_ISLNK(statp.st_mode) != 0; - if (type == TN_DIR || type == TN_DIR_NLS) { - new_node->extract_dir = true; /* if dir, extract it */ + /* + * If the user has backed up a hard linked file twice, the + * second copy will be a pointer (i.e. hard link will be set), + * so we do not overwrite the original file with a pointer file. + */ + if (!new_node->hard_link || hard_link) { + new_node->hard_link = hard_link; + new_node->FileIndex = atoi(row[2]); + new_node->JobId = (JobId_t)str_to_int64(row[3]); + new_node->type = type; + new_node->extract = true; /* extract all by default */ + new_node->soft_link = S_ISLNK(statp.st_mode) != 0; + if (type == TN_DIR || type == TN_DIR_NLS) { + new_node->extract_dir = true; /* if dir, extract it */ + } } tree->cnt++; return 0; diff --git a/bacula/src/findlib/find_one.c b/bacula/src/findlib/find_one.c index cc3f5be47c..226bc89e44 100755 --- a/bacula/src/findlib/find_one.c +++ b/bacula/src/findlib/find_one.c @@ -28,8 +28,8 @@ #include "bacula.h" #include "find.h" -extern int32_t name_max; /* filename max length */ -extern int32_t path_max; /* path name max length */ +extern int32_t name_max; /* filename max length */ +extern int32_t path_max; /* path name max length */ /* * Structure for keeping track of hard linked files, we @@ -40,11 +40,11 @@ extern int32_t path_max; /* path name max length */ */ struct f_link { struct f_link *next; - dev_t dev; /* device */ - ino_t ino; /* inode with device is unique */ + dev_t dev; /* device */ + ino_t ino; /* inode with device is unique */ short linkcount; - uint32_t FileIndex; /* Bacula FileIndex of this file */ - char name[1]; /* The name */ + uint32_t FileIndex; /* Bacula FileIndex of this file */ + char name[1]; /* The name */ }; static void free_dir_ff_pkt(FF_PKT *dir_ff_pkt) @@ -56,7 +56,7 @@ static void free_dir_ff_pkt(FF_PKT *dir_ff_pkt) } /* - * Find a single file. + * Find a single file. * handle_file is the callback for handling the file. * p is the filename * parent_device is the device we are currently on @@ -65,7 +65,7 @@ static void free_dir_ff_pkt(FF_PKT *dir_ff_pkt) */ int find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), - void *pkt, char *fname, dev_t parent_device, int top_level) + void *pkt, char *fname, dev_t parent_device, int top_level) { struct utimbuf restore_times; int rtn_stat; @@ -97,11 +97,11 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), Dmsg1(300, "Non-directory incremental: %s\n", ff_pkt->fname); /* Not a directory */ if (ff_pkt->statp.st_mtime < ff_pkt->save_time - && ((ff_pkt->flags & FO_MTIMEONLY) || - ff_pkt->statp.st_ctime < ff_pkt->save_time)) { - /* Incremental option, file not changed */ - ff_pkt->type = FT_NOCHG; - return handle_file(ff_pkt, pkt); + && ((ff_pkt->flags & FO_MTIMEONLY) || + ff_pkt->statp.st_ctime < ff_pkt->save_time)) { + /* Incremental option, file not changed */ + ff_pkt->type = FT_NOCHG; + return handle_file(ff_pkt, pkt); } } @@ -123,21 +123,26 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), */ if (ff_pkt->statp.st_nlink > 1 && (S_ISREG(ff_pkt->statp.st_mode) - || S_ISCHR(ff_pkt->statp.st_mode) - || S_ISBLK(ff_pkt->statp.st_mode) - || S_ISFIFO(ff_pkt->statp.st_mode) - || S_ISSOCK(ff_pkt->statp.st_mode))) { + || S_ISCHR(ff_pkt->statp.st_mode) + || S_ISBLK(ff_pkt->statp.st_mode) + || S_ISFIFO(ff_pkt->statp.st_mode) + || S_ISSOCK(ff_pkt->statp.st_mode))) { struct f_link *lp; /* Search link list of hard linked files */ for (lp = ff_pkt->linklist; lp; lp = lp->next) - if (lp->ino == ff_pkt->statp.st_ino && lp->dev == ff_pkt->statp.st_dev) { - ff_pkt->link = lp->name; - ff_pkt->type = FT_LNKSAVED; /* Handle link, file already saved */ - ff_pkt->LinkFI = lp->FileIndex; - return handle_file(ff_pkt, pkt); - } + if (lp->ino == ff_pkt->statp.st_ino && lp->dev == ff_pkt->statp.st_dev) { + /* If we have already backed up the hard linked file don't do it again */ + if (strcmp(lp->name, fname) == 0) { + Jmsg0(jcr, M_WARNING, 0, _("Attempt to backup hard linked file %s twice ignored.\n")); + return 1; /* ignore */ + } + ff_pkt->link = lp->name; + ff_pkt->type = FT_LNKSAVED; /* Handle link, file already saved */ + ff_pkt->LinkFI = lp->FileIndex; + return handle_file(ff_pkt, pkt); + } /* File not previously dumped. Chain it into our list. */ lp = (struct f_link *)bmalloc(sizeof(struct f_link) + strlen(fname) +1); @@ -146,7 +151,7 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), strcpy(lp->name, fname); lp->next = ff_pkt->linklist; ff_pkt->linklist = lp; - ff_pkt->linked = lp; /* mark saved link */ + ff_pkt->linked = lp; /* mark saved link */ } else { ff_pkt->linked = NULL; } @@ -158,16 +163,16 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), sizeleft = ff_pkt->statp.st_size; /* Don't bother opening empty, world readable files. Also do not open - files when archive is meant for /dev/null. */ + files when archive is meant for /dev/null. */ if (ff_pkt->null_output_device || (sizeleft == 0 - && MODE_RALL == (MODE_RALL & ff_pkt->statp.st_mode))) { - ff_pkt->type = FT_REGE; + && MODE_RALL == (MODE_RALL & ff_pkt->statp.st_mode))) { + ff_pkt->type = FT_REGE; } else { - ff_pkt->type = FT_REG; + ff_pkt->type = FT_REG; } rtn_stat = handle_file(ff_pkt, pkt); if (ff_pkt->linked) { - ff_pkt->linked->FileIndex = ff_pkt->FileIndex; + ff_pkt->linked->FileIndex = ff_pkt->FileIndex; } return rtn_stat; @@ -178,21 +183,21 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), size = readlink(fname, buffer, path_max + name_max + 101); if (size < 0) { - /* Could not follow link */ - ff_pkt->type = FT_NOFOLLOW; - ff_pkt->ff_errno = errno; - rtn_stat = handle_file(ff_pkt, pkt); - if (ff_pkt->linked) { - ff_pkt->linked->FileIndex = ff_pkt->FileIndex; - } - return rtn_stat; + /* Could not follow link */ + ff_pkt->type = FT_NOFOLLOW; + ff_pkt->ff_errno = errno; + rtn_stat = handle_file(ff_pkt, pkt); + if (ff_pkt->linked) { + ff_pkt->linked->FileIndex = ff_pkt->FileIndex; + } + return rtn_stat; } buffer[size] = 0; - ff_pkt->link = buffer; /* point to link */ - ff_pkt->type = FT_LNK; /* got a real link */ + ff_pkt->link = buffer; /* point to link */ + ff_pkt->type = FT_LNK; /* got a real link */ rtn_stat = handle_file(ff_pkt, pkt); if (ff_pkt->linked) { - ff_pkt->linked->FileIndex = ff_pkt->FileIndex; + ff_pkt->linked->FileIndex = ff_pkt->FileIndex; } return rtn_stat; @@ -201,7 +206,7 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), struct dirent *entry, *result; char *link; int link_len; - int len; + int len; int status; dev_t our_device = ff_pkt->statp.st_dev; @@ -211,16 +216,16 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), * in principle, we should be able to access everything. */ if (!have_win32_api() || (ff_pkt->flags & FO_PORTABLE)) { - if (access(fname, R_OK) == -1 && geteuid() != 0) { - /* Could not access() directory */ - ff_pkt->type = FT_NOACCESS; - ff_pkt->ff_errno = errno; - rtn_stat = handle_file(ff_pkt, pkt); - if (ff_pkt->linked) { - ff_pkt->linked->FileIndex = ff_pkt->FileIndex; - } - return rtn_stat; - } + if (access(fname, R_OK) == -1 && geteuid() != 0) { + /* Could not access() directory */ + ff_pkt->type = FT_NOACCESS; + ff_pkt->ff_errno = errno; + rtn_stat = handle_file(ff_pkt, pkt); + if (ff_pkt->linked) { + ff_pkt->linked->FileIndex = ff_pkt->FileIndex; + } + return rtn_stat; + } } /* Build a canonical directory name with a trailing slash in link var */ @@ -230,18 +235,18 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), bstrncpy(link, fname, link_len); /* Strip all trailing slashes */ while (len >= 1 && link[len - 1] == '/') - len--; + len--; link[len++] = '/'; /* add back one */ link[len] = 0; ff_pkt->link = link; if (ff_pkt->incremental && - (ff_pkt->statp.st_mtime < ff_pkt->save_time && - ff_pkt->statp.st_ctime < ff_pkt->save_time)) { - /* Incremental option, directory entry not changed */ - ff_pkt->type = FT_DIRNOCHG; + (ff_pkt->statp.st_mtime < ff_pkt->save_time && + ff_pkt->statp.st_ctime < ff_pkt->save_time)) { + /* Incremental option, directory entry not changed */ + ff_pkt->type = FT_DIRNOCHG; } else { - ff_pkt->type = FT_DIR; + ff_pkt->type = FT_DIR; } /* @@ -262,7 +267,7 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), dir_ff_pkt->excluded_files_list = NULL; dir_ff_pkt->excluded_paths_list = NULL; dir_ff_pkt->linklist = NULL; - + ff_pkt->link = ff_pkt->fname; /* reset "link" */ /* @@ -270,15 +275,15 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), * user has turned it off for this directory. */ if (ff_pkt->flags & FO_NO_RECURSION) { - /* No recursion into this directory */ - ff_pkt->type = FT_NORECURSE; - rtn_stat = handle_file(ff_pkt, pkt); - if (ff_pkt->linked) { - ff_pkt->linked->FileIndex = ff_pkt->FileIndex; - } - free(link); - free_dir_ff_pkt(dir_ff_pkt); - return rtn_stat; + /* No recursion into this directory */ + ff_pkt->type = FT_NORECURSE; + rtn_stat = handle_file(ff_pkt, pkt); + if (ff_pkt->linked) { + ff_pkt->linked->FileIndex = ff_pkt->FileIndex; + } + free(link); + free_dir_ff_pkt(dir_ff_pkt); + return rtn_stat; } /* @@ -286,16 +291,16 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), * avoid doing so if the user only wants to dump one file system. */ if (!top_level && !(ff_pkt->flags & FO_MULTIFS) && - parent_device != ff_pkt->statp.st_dev) { - /* returning here means we do not handle this directory */ - ff_pkt->type = FT_NOFSCHG; - rtn_stat = handle_file(ff_pkt, pkt); - if (ff_pkt->linked) { - ff_pkt->linked->FileIndex = ff_pkt->FileIndex; - } - free(link); - free_dir_ff_pkt(dir_ff_pkt); - return rtn_stat; + parent_device != ff_pkt->statp.st_dev) { + /* returning here means we do not handle this directory */ + ff_pkt->type = FT_NOFSCHG; + rtn_stat = handle_file(ff_pkt, pkt); + if (ff_pkt->linked) { + ff_pkt->linked->FileIndex = ff_pkt->FileIndex; + } + free(link); + free_dir_ff_pkt(dir_ff_pkt); + return rtn_stat; } /* * Decend into or "recurse" into the directory to read @@ -303,15 +308,15 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), */ errno = 0; if ((directory = opendir(fname)) == NULL) { - ff_pkt->type = FT_NOOPEN; - ff_pkt->ff_errno = errno; - rtn_stat = handle_file(ff_pkt, pkt); - if (ff_pkt->linked) { - ff_pkt->linked->FileIndex = ff_pkt->FileIndex; - } - free(link); - free_dir_ff_pkt(dir_ff_pkt); - return rtn_stat; + ff_pkt->type = FT_NOOPEN; + ff_pkt->ff_errno = errno; + rtn_stat = handle_file(ff_pkt, pkt); + if (ff_pkt->linked) { + ff_pkt->linked->FileIndex = ff_pkt->FileIndex; + } + free(link); + free_dir_ff_pkt(dir_ff_pkt); + return rtn_stat; } /* @@ -322,38 +327,38 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), rtn_stat = 1; entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 100); for ( ; !job_canceled(jcr); ) { - char *p, *q; - int i; + char *p, *q; + int i; - status = readdir_r(directory, entry, &result); - if (status != 0 || result == NULL) { + status = readdir_r(directory, entry, &result); + if (status != 0 || result == NULL) { // Dmsg2(99, "readdir returned stat=%d result=0x%x\n", -// status, (long)result); - break; - } - ASSERT(name_max+1 > (int)sizeof(struct dirent) + (int)NAMELEN(entry)); - p = entry->d_name; +// status, (long)result); + break; + } + ASSERT(name_max+1 > (int)sizeof(struct dirent) + (int)NAMELEN(entry)); + p = entry->d_name; /* Skip `.', `..', and excluded file names. */ if (p[0] == '\0' || (p[0] == '.' && (p[1] == '\0' || (p[1] == '.' && p[2] == '\0')))) { - continue; - } - - if ((int)NAMELEN(entry) + len >= link_len) { - link_len = len + NAMELEN(entry) + 1; - link = (char *)brealloc(link, link_len + 1); - } - q = link + len; - for (i=0; i < (int)NAMELEN(entry); i++) { - *q++ = *p++; - } - *q = 0; - if (!file_is_excluded(ff_pkt, link)) { - rtn_stat = find_one_file(jcr, ff_pkt, handle_file, pkt, link, our_device, 0); - if (ff_pkt->linked) { - ff_pkt->linked->FileIndex = ff_pkt->FileIndex; - } - } + continue; + } + + if ((int)NAMELEN(entry) + len >= link_len) { + link_len = len + NAMELEN(entry) + 1; + link = (char *)brealloc(link, link_len + 1); + } + q = link + len; + for (i=0; i < (int)NAMELEN(entry); i++) { + *q++ = *p++; + } + *q = 0; + if (!file_is_excluded(ff_pkt, link)) { + rtn_stat = find_one_file(jcr, ff_pkt, handle_file, pkt, link, our_device, 0); + if (ff_pkt->linked) { + ff_pkt->linked->FileIndex = ff_pkt->FileIndex; + } + } } closedir(directory); free(link); @@ -366,14 +371,14 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), * the directory modes and dates. Temp directory values * were used without this record. */ - handle_file(dir_ff_pkt, pkt); /* handle directory entry */ + handle_file(dir_ff_pkt, pkt); /* handle directory entry */ if (ff_pkt->linked) { - ff_pkt->linked->FileIndex = dir_ff_pkt->FileIndex; + ff_pkt->linked->FileIndex = dir_ff_pkt->FileIndex; } free_dir_ff_pkt(dir_ff_pkt); if (ff_pkt->flags & FO_KEEPATIME) { - utime(fname, &restore_times); + utime(fname, &restore_times); } return rtn_stat; } /* end check for directory */ @@ -386,8 +391,8 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), #ifdef HAVE_FREEBSD_OS /* * On FreeBSD, all block devices are character devices, so - * to be able to read a raw disk, we need the check for - * a character device. + * to be able to read a raw disk, we need the check for + * a character device.     * crw-r-----  1 root  operator  - 116, 0x00040002 Jun  9 19:32 /dev/ad0s3     * crw-r-----  1 root  operator  - 116, 0x00040002 Jun  9 19:32 /dev/rad0s3 */ @@ -395,9 +400,9 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), #else if (top_level && S_ISBLK(ff_pkt->statp.st_mode)) { #endif - ff_pkt->type = FT_RAW; /* raw partition */ + ff_pkt->type = FT_RAW; /* raw partition */ } else if (top_level && S_ISFIFO(ff_pkt->statp.st_mode) && - ff_pkt->flags & FO_READFIFO) { + ff_pkt->flags & FO_READFIFO) { ff_pkt->type = FT_FIFO; } else { /* The only remaining types are special (character, ...) files */ @@ -420,8 +425,8 @@ int term_find_one(FF_PKT *ff) lc = lp; lp = lp->next; if (lc) { - free(lc); - count++; + free(lc); + count++; } } return count; diff --git a/bacula/src/jcr.h b/bacula/src/jcr.h index a9641222f3..b9924fe74e 100644 --- a/bacula/src/jcr.h +++ b/bacula/src/jcr.h @@ -212,7 +212,8 @@ struct JCR { JCR *prev_dev; /* previous JCR attached to device */ pthread_cond_t job_start_wait; /* Wait for FD to start Job */ int type; - DEVRES *device; /* device to use */ + DCR *dcr; /* device context record */ + DEVRES *device; /* device resource to use */ VOLUME_CAT_INFO VolCatInfo; /* Catalog info for desired volume */ POOLMEM *job_name; /* base Job name (not unique) */ POOLMEM *fileset_name; /* FileSet */ @@ -224,24 +225,13 @@ struct JCR { VOL_LIST *VolList; /* list to read */ int32_t NumVolumes; /* number of volumes used */ int32_t CurVolume; /* current volume number */ - int spool_attributes; /* set if spooling attributes */ - int no_attributes; /* set if no attributes wanted */ int label_status; /* device volume label status */ int label_errors; /* count of label errors */ - int session_opened; - DEV_RECORD rec; /* Read/Write record */ + bool session_opened; long Ticket; /* ticket for this job */ - uint32_t VolFirstIndex; /* First file index this Volume */ - uint32_t VolLastIndex; /* Last file index this Volume */ - uint32_t FileIndex; /* Current File Index */ - uint32_t EndFile; /* End file written */ - uint32_t StartFile; /* Start write file */ - uint32_t StartBlock; /* Start write block */ - uint32_t EndBlock; /* Ending block written */ - bool NewVol; /* set when new Volume mounted */ - bool WroteVol; /* set when Volume written */ - bool NewFile; /* set when EOF written */ bool ignore_label_errors; /* ignore Volume label errors */ + bool spool_attributes; /* set if spooling attributes */ + bool no_attributes; /* set if no attributes wanted */ int CurVol; /* Current Volume count */ uint32_t FileId; /* Last file id inserted */ diff --git a/bacula/src/lib/bsys.c b/bacula/src/lib/bsys.c index 4ddb3f4c00..7251ac9a1f 100644 --- a/bacula/src/lib/bsys.c +++ b/bacula/src/lib/bsys.c @@ -317,7 +317,7 @@ void create_pid_file(char *dir, const char *progname, int port) unlink(mp_chr(fname)); /* remove stale pid file */ } /* Create new pid file */ - if ((pidfd = open(mp_chr(fname), O_CREAT|O_TRUNC|O_WRONLY|O_BINARY, 0644)) >= 0) { + if ((pidfd = open(mp_chr(fname), O_CREAT|O_TRUNC|O_WRONLY|O_BINARY, 0640)) >= 0) { len = sprintf(pidbuf, "%d\n", (int)getpid()); write(pidfd, pidbuf, len); close(pidfd); diff --git a/bacula/src/lib/edit.c b/bacula/src/lib/edit.c index 99184336cd..9647fdf4b3 100644 --- a/bacula/src/lib/edit.c +++ b/bacula/src/lib/edit.c @@ -35,6 +35,9 @@ uint64_t str_to_uint64(char *str) register char *p = str; register uint64_t value = 0; + if (!p) { + return 0; + } while (B_ISSPACE(*p)) { p++; } @@ -52,15 +55,18 @@ int64_t str_to_int64(char *str) { register char *p = str; register int64_t value; - int negative = FALSE; + bool negative = false; + if (!p) { + return 0; + } while (B_ISSPACE(*p)) { p++; } if (*p == '+') { p++; } else if (*p == '-') { - negative = TRUE; + negative = true; p++; } value = str_to_uint64(p); diff --git a/bacula/src/lib/message.c b/bacula/src/lib/message.c index 08ba4dd835..77de72c4e9 100755 --- a/bacula/src/lib/message.c +++ b/bacula/src/lib/message.c @@ -380,10 +380,10 @@ static void make_unique_mail_filename(JCR *jcr, POOLMEM **name, DEST *d) { if (jcr) { Mmsg(name, "%s/%s.mail.%s.%d", working_directory, my_name, - jcr->Job, (int)d); + jcr->Job, (int)(long)d); } else { Mmsg(name, "%s/%s.mail.%s.%d", working_directory, my_name, - my_name, (int)d); + my_name, (int)(long)d); } Dmsg1(200, "mailname=%s\n", *name); } diff --git a/bacula/src/stored/acquire.c b/bacula/src/stored/acquire.c index f926559065..c44fd8e3bf 100644 --- a/bacula/src/stored/acquire.c +++ b/bacula/src/stored/acquire.c @@ -30,6 +30,32 @@ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +DCR *new_dcr(JCR *jcr, DEVICE *dev) +{ + DCR *dcr = (DCR *)malloc(sizeof(DCR)); + memset(dcr, 0, sizeof(DCR)); + jcr->dcr = dcr; + dcr->jcr = jcr; + dcr->dev = dev; + dcr->block = new_block(dev); + dcr->record = new_record(); + dcr->spool_fd = -1; + return dcr; +} + +void free_dcr(DCR *dcr) +{ + if (dcr->block) { + free_block(dcr->block); + } + if (dcr->record) { + free_record(dcr->record); + } + dcr->jcr->dcr = NULL; + free(dcr); +} + + /********************************************************************* * Acquire device for reading. We permit (for the moment) * only one reader. We read the Volume label from the block and @@ -38,7 +64,7 @@ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; * Returns: 0 if failed for any reason * 1 if successful */ -int acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) +DCR *acquire_device_for_read(JCR *jcr) { bool vol_ok = false; bool tape_previously_mounted; @@ -46,7 +72,14 @@ int acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) VOL_LIST *vol; int autochanger = 0; int i; - + DCR *dcr = jcr->dcr; + DEVICE *dev; + + /* Called for each volume */ + if (!dcr) { + dcr = new_dcr(jcr, jcr->device->dev); + } + dev = dcr->dev; if (device_is_unmounted(dev)) { Jmsg(jcr, M_WARNING, 0, _("device %s is BLOCKED due to user unmount.\n"), dev_name(dev)); @@ -77,6 +110,7 @@ int acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) vol = vol->next; } pm_strcpy(&jcr->VolumeName, vol->VolumeName); + bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName)); for (i=0; i<5; i++) { if (job_canceled(jcr)) { @@ -90,9 +124,9 @@ int acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) */ for ( ; !(dev->state & ST_OPENED); ) { Dmsg1(120, "bstored: open vol=%s\n", jcr->VolumeName); - if (open_dev(dev, jcr->VolumeName, READ_ONLY) < 0) { + if (open_dev(dev, dcr->VolumeName, READ_ONLY) < 0) { Jmsg(jcr, M_FATAL, 0, _("Open device %s volume %s failed, ERR=%s\n"), - dev_name(dev), jcr->VolumeName, strerror_dev(dev)); + dev_name(dev), dcr->VolumeName, strerror_dev(dev)); goto get_out; } Dmsg1(129, "open_dev %s OK\n", dev_name(dev)); @@ -101,9 +135,9 @@ int acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) * correctly possitioned. Possibly have way user can turn * this optimization (to be implemented) off. */ - dev->state &= ~ST_LABEL; /* force reread of label */ + dcr->dev->state &= ~ST_LABEL; /* force reread of label */ Dmsg0(200, "calling read-vol-label\n"); - switch (read_dev_volume_label(jcr, dev, block)) { + switch (read_dev_volume_label(jcr, dev, dcr->block)) { case VOL_OK: vol_ok = true; break; /* got it */ @@ -165,7 +199,11 @@ get_out: P(dev->mutex); unblock_device(dev); V(dev->mutex); - return vol_ok; + if (!vol_ok) { + free_dcr(dcr); + dcr = NULL; + } + return dcr; } /* @@ -178,13 +216,15 @@ get_out: * multiple devices (for files), thus we have our own mutex * on top of the device mutex. */ -DEVICE *acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) +DCR *acquire_device_for_append(JCR *jcr) { int release = 0; bool recycle = false; bool do_mount = false; - DEVICE *rtn_dev = NULL; + DCR *dcr; + DEVICE *dev = jcr->device->dev; + dcr = new_dcr(jcr, dev); if (device_is_unmounted(dev)) { Jmsg(jcr, M_WARNING, 0, _("device %s is BLOCKED due to user unmount.\n"), dev_name(dev)); @@ -207,6 +247,7 @@ DEVICE *acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) * dir_find_next_appendable_volume */ pm_strcpy(&jcr->VolumeName, dev->VolHdr.VolName); + bstrncpy(dcr->VolumeName, dev->VolHdr.VolName, sizeof(dcr->VolumeName)); if (!dir_get_volume_info(jcr, GET_VOL_INFO_FOR_WRITE) && !(dir_find_next_appendable_volume(jcr) && strcmp(dev->VolHdr.VolName, jcr->VolumeName) == 0)) { /* wrong tape mounted */ @@ -262,7 +303,7 @@ DEVICE *acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) } if (do_mount || recycle) { - if (!mount_next_write_volume(jcr, dev, block, release)) { + if (!mount_next_write_volume(jcr, dev, dcr->block, release)) { if (!job_canceled(jcr)) { /* Reduce "noise" -- don't print if job canceled */ Jmsg(jcr, M_FATAL, 0, _("Could not ready device \"%s\" for append.\n"), @@ -277,18 +318,21 @@ DEVICE *acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) jcr->NumVolumes = 1; } attach_jcr_to_device(dev, jcr); /* attach jcr to device */ - rtn_dev = dev; /* return device */ + goto ok_out; /* * If we jump here, it is an error return because * rtn_dev will still be NULL */ get_out: + free_dcr(dcr); + dcr = NULL; +ok_out: P(dev->mutex); unblock_device(dev); V(dev->mutex); V(mutex); /* unlock other threads */ - return rtn_dev; + return dcr; } /* @@ -296,8 +340,9 @@ get_out: * the device remains open. * */ -int release_device(JCR *jcr, DEVICE *dev) +int release_device(JCR *jcr) { + DEVICE *dev = jcr->dcr->dev; lock_device(dev); Dmsg1(100, "release_device device is %s\n", dev_is_tape(dev)?"tape":"disk"); if (dev_state(dev, ST_READ)) { @@ -346,5 +391,7 @@ int release_device(JCR *jcr, DEVICE *dev) } else { unlock_device(dev); } + free_dcr(jcr->dcr); + jcr->dcr = NULL; return 1; } diff --git a/bacula/src/stored/append.c b/bacula/src/stored/append.c index 6d42130636..0f755ff493 100644 --- a/bacula/src/stored/append.c +++ b/bacula/src/stored/append.c @@ -36,6 +36,12 @@ static bool are_attributes_spooled(JCR *jcr); static int begin_attribute_spool(JCR *jcr); static int discard_attribute_spool(JCR *jcr); static int commit_attribute_spool(JCR *jcr); +static int open_data_spool_file(JCR *jcr); +static int close_data_spool_file(JCR *jcr); +static int begin_data_spool(JCR *jcr); +static int discard_data_spool(JCR *jcr); +static int commit_data_spool(JCR *jcr); + /* * Append Data sent from File daemon @@ -48,43 +54,39 @@ int do_append_data(JCR *jcr) BSOCK *ds; BSOCK *fd_sock = jcr->file_bsock; bool ok = true; - DEVICE *dev = jcr->device->dev; + DEVICE *dev; DEV_RECORD rec; DEV_BLOCK *block; + DCR *dcr; Dmsg0(10, "Start append data.\n"); - /* Tell File daemon to send data */ - bnet_fsend(fd_sock, OK_data); - - begin_attribute_spool(jcr); - ds = fd_sock; - if (!bnet_set_buffer_size(ds, dev->device->max_network_buffer_size, BNET_SETBUF_WRITE)) { + if (!bnet_set_buffer_size(ds, jcr->device->max_network_buffer_size, BNET_SETBUF_WRITE)) { set_jcr_job_status(jcr, JS_ErrorTerminated); Jmsg(jcr, M_FATAL, 0, _("Unable to set network buffer size.\n")); - discard_attribute_spool(jcr); return 0; } - Dmsg1(20, "Begin append device=%s\n", dev_name(dev)); - - block = new_block(dev); - memset(&rec, 0, sizeof(rec)); - /* * Acquire output device for writing. Note, after acquiring a * device, we MUST release it, which is done at the end of this * subroutine. */ Dmsg0(100, "just before acquire_device\n"); - if (!(dev=acquire_device_for_append(jcr, dev, block))) { + if (!(dcr=acquire_device_for_append(jcr))) { set_jcr_job_status(jcr, JS_ErrorTerminated); - free_block(block); - discard_attribute_spool(jcr); return 0; } + dev = dcr->dev; + block = dcr->block; + + Dmsg1(20, "Begin append device=%s\n", dev_name(dev)); + + begin_data_spool(jcr); + begin_attribute_spool(jcr); + Dmsg0(100, "Just after acquire_device_for_append\n"); /* * Write Begin Session Record @@ -96,6 +98,8 @@ int do_append_data(JCR *jcr) ok = false; } + /* Tell File daemon to send data */ + bnet_fsend(fd_sock, OK_data); /* * Get Data from File daemon, write to device. To clarify what is @@ -114,7 +118,7 @@ int do_append_data(JCR *jcr) * file. 1. for the Attributes, 2. for the file data if any, * and 3. for the MD5 if any. */ - jcr->VolFirstIndex = jcr->VolLastIndex = 0; + dcr->VolFirstIndex = dcr->VolLastIndex = 0; jcr->run_time = time(NULL); /* start counting time for rates */ for (last_file_index = 0; ok && !job_canceled(jcr); ) { @@ -174,7 +178,6 @@ int do_append_data(JCR *jcr) * The data stream is just raw bytes */ while ((n=bget_msg(ds)) > 0 && !job_canceled(jcr)) { - rec.VolSessionId = jcr->VolSessionId; rec.VolSessionTime = jcr->VolSessionTime; rec.FileIndex = file_index; @@ -259,17 +262,25 @@ int do_append_data(JCR *jcr) } } + if (!ok) { + discard_data_spool(jcr); + } else { + commit_data_spool(jcr); + } + Dmsg1(200, "calling release device JobStatus=%d\n", jcr->JobStatus); /* Release the device */ - if (!release_device(jcr, dev)) { + if (!release_device(jcr)) { Pmsg0(000, _("Error in release_device\n")); set_jcr_job_status(jcr, JS_ErrorTerminated); ok = false; } - free_block(block); - - commit_attribute_spool(jcr); + if (!ok) { + discard_attribute_spool(jcr); + } else { + commit_attribute_spool(jcr); + } dir_send_job_status(jcr); /* update director */ @@ -277,6 +288,70 @@ int do_append_data(JCR *jcr) return ok ? 1 : 0; } + +static int begin_data_spool(JCR *jcr) +{ + if (jcr->dcr->spool_data) { + return open_data_spool_file(jcr); + } + return 1; +} + +static int discard_data_spool(JCR *jcr) +{ + if (jcr->dcr->spool_data && jcr->dcr->spool_fd >= 0) { + return close_data_spool_file(jcr); + } + return 1; +} + +static int commit_data_spool(JCR *jcr) +{ + if (jcr->dcr->spool_data && jcr->dcr->spool_fd >= 0) { +// despool_data(jcr); + return close_data_spool_file(jcr); + } + return 1; +} + +static void make_unique_data_spool_filename(JCR *jcr, POOLMEM **name) +{ + Mmsg(name, "%s/%s.data.spool.%s.%s", working_directory, my_name, + jcr->Job, jcr->device->hdr.name); +} + + +static int open_data_spool_file(JCR *jcr) +{ + POOLMEM *name = get_pool_memory(PM_MESSAGE); + int spool_fd; + + make_unique_data_spool_filename(jcr, &name); + if ((spool_fd = open(name, O_CREAT|O_TRUNC|O_RDWR|O_BINARY, 0640)) >= 0) { + jcr->dcr->spool_fd = spool_fd; + jcr->spool_attributes = true; + } else { + Jmsg(jcr, M_ERROR, 0, "open data spool file %s failed: ERR=%s\n", name, strerror(errno)); + free_pool_memory(name); + return 0; + } + free_pool_memory(name); + return 1; +} + +static int close_data_spool_file(JCR *jcr) +{ + POOLMEM *name = get_pool_memory(PM_MESSAGE); + + make_unique_data_spool_filename(jcr, &name); + close(jcr->dcr->spool_fd); + jcr->dcr->spool_fd = -1; + unlink(name); + free_pool_memory(name); + return 1; +} + + static bool are_attributes_spooled(JCR *jcr) { return jcr->spool_attributes && jcr->dir_bsock->spool_fd; diff --git a/bacula/src/stored/askdir.c b/bacula/src/stored/askdir.c index 7573f56a93..ca692e7636 100644 --- a/bacula/src/stored/askdir.c +++ b/bacula/src/stored/askdir.c @@ -76,10 +76,12 @@ int dir_send_job_status(JCR *jcr) static int do_get_volume_info(JCR *jcr) { BSOCK *dir = jcr->dir_bsock; + DCR *dcr = jcr->dcr; VOLUME_CAT_INFO vol; int n; jcr->VolumeName[0] = 0; /* No volume */ + dcr->VolumeName[0] = 0; /* No volume */ if (bnet_recv(dir) <= 0) { Dmsg0(200, "getvolname error bnet_recv\n"); Mmsg(&jcr->errmsg, _("Network error on bnet_recv in req_vol_info.\n")); @@ -102,7 +104,9 @@ static int do_get_volume_info(JCR *jcr) } unbash_spaces(vol.VolCatName); pm_strcpy(&jcr->VolumeName, vol.VolCatName); /* set desired VolumeName */ + bstrncpy(dcr->VolumeName, vol.VolCatName, sizeof(dcr->VolumeName)); memcpy(&jcr->VolCatInfo, &vol, sizeof(jcr->VolCatInfo)); + memcpy(&dcr->VolCatInfo, &vol, sizeof(dcr->VolCatInfo)); Dmsg2(200, "do_reqest_vol_info got slot=%d Volume=%s\n", vol.Slot, vol.VolCatName); @@ -212,16 +216,17 @@ int dir_update_volume_info(JCR *jcr, DEVICE *dev, int label) int dir_create_jobmedia_record(JCR *jcr) { BSOCK *dir = jcr->dir_bsock; + DCR *dcr = jcr->dcr; - if (!jcr->WroteVol) { + if (!dcr->WroteVol) { return 1; /* nothing written to tape */ } - jcr->WroteVol = false; + dcr->WroteVol = false; bnet_fsend(dir, Create_job_media, jcr->Job, - jcr->VolFirstIndex, jcr->VolLastIndex, - jcr->StartFile, jcr->EndFile, - jcr->StartBlock, jcr->EndBlock); + dcr->VolFirstIndex, dcr->VolLastIndex, + dcr->StartFile, dcr->EndFile, + dcr->StartBlock, dcr->EndBlock); Dmsg1(100, "create_jobmedia(): %s", dir->msg); if (bnet_recv(dir) <= 0) { Dmsg0(190, "create_jobmedia error bnet_recv\n"); diff --git a/bacula/src/stored/bcopy.c b/bacula/src/stored/bcopy.c index 761a7d2d7f..73e79945a1 100644 --- a/bacula/src/stored/bcopy.c +++ b/bacula/src/stored/bcopy.c @@ -153,20 +153,18 @@ int main (int argc, char *argv[]) exit(1); } /* For we must now acquire the device for writing */ - out_block = new_block(out_dev); lock_device(out_dev); if (open_dev(out_dev, out_jcr->VolumeName, READ_WRITE) < 0) { Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), out_dev->errmsg); unlock_device(out_dev); - free_block(out_block); exit(1); } unlock_device(out_dev); - if (!(out_dev=acquire_device_for_append(out_jcr, out_dev, out_block))) { - free_block(out_block); + if (!acquire_device_for_append(out_jcr)) { free_jcr(in_jcr); exit(1); } + out_block = out_jcr->dcr->block; read_records(in_jcr, in_dev, record_cb, mount_next_read_volume); if (!write_block_to_device(out_jcr, out_dev, out_block)) { @@ -175,7 +173,6 @@ int main (int argc, char *argv[]) Pmsg2(000, _("%u Jobs copied. %u records copied.\n"), jobs, records); - free_block(out_block); term_dev(in_dev); term_dev(out_dev); free_jcr(in_jcr); diff --git a/bacula/src/stored/bextract.c b/bacula/src/stored/bextract.c index cbf6e513fe..dac87a7880 100644 --- a/bacula/src/stored/bextract.c +++ b/bacula/src/stored/bextract.c @@ -222,7 +222,7 @@ static void do_extract(char *devname) if (is_bopen(&bfd)) { set_attributes(jcr, attr, &bfd); } - release_device(jcr, dev); + release_device(jcr); free_attr(attr); term_dev(dev); diff --git a/bacula/src/stored/block.c b/bacula/src/stored/block.c index bc9c09b62b..5a3edc52ee 100644 --- a/bacula/src/stored/block.c +++ b/bacula/src/stored/block.c @@ -313,6 +313,8 @@ static int unser_block_header(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) int write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) { int stat = 1; + DCR *dcr = jcr->dcr; + lock_device(dev); /* @@ -321,7 +323,7 @@ int write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) * and set new parameters to write this volume * The same applies for if we are in a new file. */ - if (jcr->NewVol || jcr->NewFile) { + if (dcr->NewVol || dcr->NewFile) { /* Create a jobmedia record for this job */ if (!dir_create_jobmedia_record(jcr)) { Jmsg(jcr, M_ERROR, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"), @@ -330,10 +332,10 @@ int write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) unlock_device(dev); return 0; } - if (jcr->NewVol) { + if (dcr->NewVol) { /* Note, setting a new volume also handles any pending new file */ set_new_volume_parameters(jcr, dev); - jcr->NewFile = false; /* this handled for new file too */ + dcr->NewFile = false; /* this handled for new file too */ } else { set_new_file_parameters(jcr, dev); } @@ -359,6 +361,7 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) uint32_t wlen; /* length to write */ int hit_max1, hit_max2; bool ok; + DCR *dcr = jcr->dcr; #ifdef NO_TAPE_WRITE_TEST empty_block(block); @@ -459,7 +462,7 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) dir_update_volume_info(jcr, dev, 0); if (!dir_create_jobmedia_record(jcr)) { Jmsg(jcr, M_ERROR, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"), - jcr->VolCatInfo.VolCatName, jcr->Job); + dcr->VolCatInfo.VolCatName, jcr->Job); return 0; } dev->file_size = 0; /* reset file size */ @@ -471,7 +474,7 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) if (mjcr->JobId == 0) { continue; /* ignore console */ } - mjcr->NewFile = true; /* set reminder to do set_new_file_params */ + mjcr->dcr->NewFile = true; /* set reminder to do set_new_file_params */ } set_new_file_parameters(jcr, dev); } @@ -591,20 +594,20 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) /* Update jcr values */ if (dev_state(dev, ST_TAPE)) { - jcr->EndBlock = dev->EndBlock; - jcr->EndFile = dev->EndFile; + dcr->EndBlock = dev->EndBlock; + dcr->EndFile = dev->EndFile; } else { /* Save address of start of block just written */ - jcr->EndBlock = (uint32_t)dev->file_addr; - jcr->EndFile = (uint32_t)(dev->file_addr >> 32); + dcr->EndBlock = (uint32_t)dev->file_addr; + dcr->EndFile = (uint32_t)(dev->file_addr >> 32); } - if (jcr->VolFirstIndex == 0 && block->FirstIndex > 0) { - jcr->VolFirstIndex = block->FirstIndex; + if (dcr->VolFirstIndex == 0 && block->FirstIndex > 0) { + dcr->VolFirstIndex = block->FirstIndex; } if (block->LastIndex > 0) { - jcr->VolLastIndex = block->LastIndex; + dcr->VolLastIndex = block->LastIndex; } - jcr->WroteVol = true; + dcr->WroteVol = true; dev->file_addr += wlen; /* update file address */ dev->file_size += wlen; @@ -640,6 +643,7 @@ int read_block_from_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, bool check_bloc int looping; uint32_t BlockNumber; int retry; + DCR *dcr = jcr->dcr; if (dev_state(dev, ST_EOT)) { return 0; @@ -765,13 +769,13 @@ reread: /* Update jcr values */ if (dev->state & ST_TAPE) { - jcr->EndBlock = dev->EndBlock; - jcr->EndFile = dev->EndFile; + dcr->EndBlock = dev->EndBlock; + dcr->EndFile = dev->EndFile; } else { - jcr->EndBlock = (uint32_t)dev->file_addr; - jcr->EndFile = (uint32_t)(dev->file_addr >> 32); - dev->block_num = jcr->EndBlock; - dev->file = jcr->EndFile; + dcr->EndBlock = (uint32_t)dev->file_addr; + dcr->EndFile = (uint32_t)(dev->file_addr >> 32); + dev->block_num = dcr->EndBlock; + dev->file = dcr->EndFile; } dev->file_addr += block->block_len; dev->file_size += block->block_len; diff --git a/bacula/src/stored/bls.c b/bacula/src/stored/bls.c index f019c41eef..29f96f0ee3 100644 --- a/bacula/src/stored/bls.c +++ b/bacula/src/stored/bls.c @@ -234,7 +234,7 @@ Warning, this Volume is a continuation of Volume %s\n", static void do_close(JCR *jcr) { - release_device(jcr, dev); + release_device(jcr); free_attr(attr); term_dev(dev); free_record(rec); diff --git a/bacula/src/stored/bscan.c b/bacula/src/stored/bscan.c index 4939581eff..840aad4772 100644 --- a/bacula/src/stored/bscan.c +++ b/bacula/src/stored/bscan.c @@ -265,15 +265,16 @@ static int bscan_mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) { Dmsg1(100, "Walk attached jcrs. Volume=%s\n", dev->VolCatInfo.VolCatName); for (JCR *mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) { + DCR *dcr = mjcr->dcr; if (verbose) { Pmsg1(000, _("Create JobMedia for Job %s\n"), mjcr->Job); } if (dev->state & ST_TAPE) { - mjcr->EndBlock = dev->EndBlock; - mjcr->EndFile = dev->EndFile; + dcr->EndBlock = dev->EndBlock; + dcr->EndFile = dev->EndFile; } else { - mjcr->EndBlock = (uint32_t)dev->file_addr; - mjcr->StartBlock = (uint32_t)(dev->file_addr >> 32); + dcr->EndBlock = (uint32_t)dev->file_addr; + dcr->StartBlock = (uint32_t)(dev->file_addr >> 32); } if (!create_jobmedia_record(db, mjcr)) { Pmsg2(000, _("Could not create JobMedia record for Volume=%s Job=%s\n"), @@ -305,7 +306,7 @@ static void do_scan() detach_jcr_from_device(dev, bjcr); read_records(bjcr, dev, record_cb, bscan_mount_next_read_volume); - release_device(bjcr, dev); + release_device(bjcr); free_attr(attr); term_dev(dev); @@ -314,6 +315,7 @@ static void do_scan() static int record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) { JCR *mjcr; + DCR *dcr; char ec1[30]; if (rec->data_len > 0) { @@ -392,9 +394,10 @@ static int record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) } /* Reset some JCR variables */ for (mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) { - mjcr->VolFirstIndex = mjcr->FileIndex = 0; - mjcr->StartBlock = mjcr->EndBlock = 0; - mjcr->StartFile = mjcr->EndFile = 0; + dcr = mjcr->dcr; + dcr->VolFirstIndex = dcr->FileIndex = 0; + dcr->StartBlock = dcr->EndBlock = 0; + dcr->StartFile = dcr->EndFile = 0; } Pmsg1(000, _("VOL_LABEL: OK for Volume: %s\n"), mr.VolumeName); @@ -430,16 +433,17 @@ static int record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) /* process label, if Job record exists don't update db */ mjcr = create_job_record(db, &jr, &label, rec); + dcr = mjcr->dcr; update_db = save_update_db; jr.PoolId = pr.PoolId; /* Set start positions into JCR */ if (dev->state & ST_TAPE) { - mjcr->StartBlock = dev->block_num; - mjcr->StartFile = dev->file; + dcr->StartBlock = dev->block_num; + dcr->StartFile = dev->file; } else { - mjcr->StartBlock = (uint32_t)dev->file_addr; - mjcr->StartFile = (uint32_t)(dev->file_addr >> 32); + dcr->StartBlock = (uint32_t)dev->file_addr; + dcr->StartFile = (uint32_t)(dev->file_addr >> 32); } mjcr->start_time = jr.StartTime; mjcr->JobLevel = jr.Level; @@ -511,7 +515,9 @@ static int record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) * them. */ if (update_db) { - for (mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) { + mjcr=next_attached_jcr(dev, NULL); + for ( ; mjcr; ) { + JCR *njcr; jr.JobId = mjcr->JobId; jr.JobStatus = JS_ErrorTerminated; jr.JobFiles = mjcr->JobFiles; @@ -520,10 +526,12 @@ static int record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) jr.VolSessionTime = mjcr->VolSessionTime; jr.JobTDate = (utime_t)mjcr->start_time; jr.ClientId = mjcr->ClientId; - free_jcr(mjcr); if (!db_update_job_end_record(bjcr, db, &jr)) { Pmsg1(0, _("Could not update job record. ERR=%s\n"), db_strerror(db)); } + njcr = mjcr->next_dev; + free_jcr(mjcr); + mjcr = njcr; } } mr.VolFiles = rec->File; @@ -550,8 +558,9 @@ static int record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) } return 1; } - if (mjcr->VolFirstIndex == 0) { - mjcr->VolFirstIndex = block->FirstIndex; + dcr = mjcr->dcr; + if (dcr->VolFirstIndex == 0) { + dcr->VolFirstIndex = block->FirstIndex; } /* File Attributes stream */ @@ -656,7 +665,7 @@ static int record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) * Called from main free_jcr() routine in src/lib/jcr.c so * that we can do our Director specific cleanup of the jcr. */ -static void dird_free_jcr(JCR *jcr) +static void bscan_free_jcr(JCR *jcr) { Dmsg0(200, "Start dird free_jcr\n"); @@ -671,6 +680,10 @@ static void dird_free_jcr(JCR *jcr) if (jcr->RestoreBootstrap) { free(jcr->RestoreBootstrap); } + if (jcr->dcr) { + free_dcr(jcr->dcr); + jcr->dcr = NULL; + } Dmsg0(200, "End dird free_jcr\n"); } @@ -682,7 +695,7 @@ static int create_file_attributes_record(B_DB *db, JCR *mjcr, char *fname, char *lname, int type, char *ap, DEV_RECORD *rec) { - + DCR *dcr = mjcr->dcr; ar.fname = fname; ar.link = lname; ar.ClientId = mjcr->ClientId; @@ -690,10 +703,10 @@ static int create_file_attributes_record(B_DB *db, JCR *mjcr, ar.Stream = rec->Stream; ar.FileIndex = rec->FileIndex; ar.attr = ap; - if (mjcr->VolFirstIndex == 0) { - mjcr->VolFirstIndex = rec->FileIndex; + if (dcr->VolFirstIndex == 0) { + dcr->VolFirstIndex = rec->FileIndex; } - mjcr->FileIndex = rec->FileIndex; + dcr->FileIndex = rec->FileIndex; mjcr->JobFiles++; if (!update_db) { @@ -1013,24 +1026,25 @@ Termination: %s\n\n"), static int create_jobmedia_record(B_DB *db, JCR *mjcr) { JOBMEDIA_DBR jmr; + DCR *dcr = mjcr->dcr; if (dev->state & ST_TAPE) { - mjcr->EndBlock = dev->EndBlock; - mjcr->EndFile = dev->EndFile; + dcr->EndBlock = dev->EndBlock; + dcr->EndFile = dev->EndFile; } else { - mjcr->EndBlock = (uint32_t)dev->file_addr; - mjcr->EndFile = (uint32_t)(dev->file_addr >> 32); + dcr->EndBlock = (uint32_t)dev->file_addr; + dcr->EndFile = (uint32_t)(dev->file_addr >> 32); } memset(&jmr, 0, sizeof(jmr)); jmr.JobId = mjcr->JobId; jmr.MediaId = mr.MediaId; - jmr.FirstIndex = mjcr->VolFirstIndex; - jmr.LastIndex = mjcr->FileIndex; - jmr.StartFile = mjcr->StartFile; - jmr.EndFile = mjcr->EndFile; - jmr.StartBlock = mjcr->StartBlock; - jmr.EndBlock = mjcr->EndBlock; + jmr.FirstIndex = dcr->VolFirstIndex; + jmr.LastIndex = dcr->FileIndex; + jmr.StartFile = dcr->StartFile; + jmr.EndFile = dcr->EndFile; + jmr.StartBlock = dcr->StartBlock; + jmr.EndBlock = dcr->EndBlock; if (!update_db) { @@ -1094,7 +1108,7 @@ static JCR *create_jcr(JOB_DBR *jr, DEV_RECORD *rec, uint32_t JobId) * Transfer as much as possible to the Job JCR. Most important is * the JobId and the ClientId. */ - jobjcr = new_jcr(sizeof(JCR), dird_free_jcr); + jobjcr = new_jcr(sizeof(JCR), bscan_free_jcr); jobjcr->JobType = jr->Type; jobjcr->JobLevel = jr->Level; jobjcr->JobStatus = jr->JobStatus; @@ -1106,6 +1120,7 @@ static JCR *create_jcr(JOB_DBR *jr, DEV_RECORD *rec, uint32_t JobId) jobjcr->VolSessionTime = rec->VolSessionTime; jobjcr->ClientId = jr->ClientId; attach_jcr_to_device(dev, jobjcr); + new_dcr(jobjcr, dev); return jobjcr; } @@ -1121,7 +1136,7 @@ int dir_send_job_status(JCR *jcr) {return 1;} int dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev) { - fprintf(stderr, _("Mount Volume %s on device %s and press return when ready: "), + fprintf(stderr, _("Mount Volume \"%s\" on device \"%s\" and press return when ready: "), jcr->VolumeName, dev_name(dev)); getchar(); return 1; diff --git a/bacula/src/stored/btape.c b/bacula/src/stored/btape.c index 075e82f571..62f19c87de 100644 --- a/bacula/src/stored/btape.c +++ b/bacula/src/stored/btape.c @@ -1692,7 +1692,6 @@ This may take a long time -- hours! ...\n\n"); /* Use fixed block size to simplify read back */ min_block_size = dev->min_block_size; dev->min_block_size = dev->max_block_size; - block = new_block(dev); /* * Acquire output device for writing. Note, after acquiring a @@ -1700,11 +1699,11 @@ This may take a long time -- hours! ...\n\n"); * subroutine. */ Dmsg0(100, "just before acquire_device\n"); - if (!(dev=acquire_device_for_append(jcr, dev, block))) { + if (!acquire_device_for_append(jcr)) { set_jcr_job_status(jcr, JS_ErrorTerminated); - free_block(block); return; } + block = jcr->dcr->block; Dmsg0(100, "Just after acquire_device_for_append\n"); /* @@ -1742,7 +1741,7 @@ This may take a long time -- hours! ...\n\n"); /* * Generate data as if from File daemon, write to device */ - jcr->VolFirstIndex = 0; + jcr->dcr->VolFirstIndex = 0; time(&jcr->run_time); /* start counting time for rates */ if (simple) { Pmsg0(-1, "Begin writing Bacula records to tape ...\n"); @@ -1868,7 +1867,7 @@ This may take a long time -- hours! ...\n\n"); } /* Release the device */ - if (!release_device(jcr, dev)) { + if (!release_device(jcr)) { Pmsg0(-1, _("Error in release_device\n")); ok = FALSE; } @@ -1880,7 +1879,6 @@ This may take a long time -- hours! ...\n\n"); do_unfill(); dev->min_block_size = min_block_size; - free_block(block); free_memory(rec.data); } @@ -1969,7 +1967,7 @@ static void do_unfill() create_vol_list(jcr); close_dev(dev); dev->state &= ~ST_READ; - if (!acquire_device_for_read(jcr, dev, block)) { + if (!acquire_device_for_read(jcr)) { Pmsg1(-1, "%s", dev->errmsg); goto bail_out; } @@ -2026,7 +2024,7 @@ static void do_unfill() } dev->state &= ~ST_READ; - if (!acquire_device_for_read(jcr, dev, block)) { + if (!acquire_device_for_read(jcr)) { Pmsg1(-1, "%s", dev->errmsg); goto bail_out; } @@ -2506,7 +2504,7 @@ int dir_get_volume_info(JCR *jcr, enum get_vol_info_rw writing) int dir_create_jobmedia_record(JCR *jcr) { - jcr->WroteVol = false; + jcr->dcr->WroteVol = false; return 1; } @@ -2598,7 +2596,7 @@ static int my_mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) create_vol_list(jcr); close_dev(dev); dev->state &= ~ST_READ; - if (!acquire_device_for_read(jcr, dev, block)) { + if (!acquire_device_for_read(jcr)) { Pmsg2(0, "Cannot open Dev=%s, Vol=%s\n", dev_name(dev), jcr->VolumeName); return 0; } @@ -2607,12 +2605,16 @@ static int my_mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) static void set_volume_name(char *VolName, int volnum) { + DCR *dcr = jcr->dcr; VolumeName = VolName; vol_num = volnum; pm_strcpy(&jcr->VolumeName, VolName); bstrncpy(dev->VolCatInfo.VolCatName, VolName, sizeof(dev->VolCatInfo.VolCatName)); bstrncpy(jcr->VolCatInfo.VolCatName, VolName, sizeof(jcr->VolCatInfo.VolCatName)); + bstrncpy(dcr->VolCatInfo.VolCatName, VolName, sizeof(dcr->VolCatInfo.VolCatName)); + bstrncpy(dcr->VolumeName, VolName, sizeof(dcr->VolumeName)); jcr->VolCatInfo.Slot = volnum; + dcr->VolCatInfo.Slot = volnum; } /* diff --git a/bacula/src/stored/butil.c b/bacula/src/stored/butil.c index 4c51c407ed..1e1387cf4b 100644 --- a/bacula/src/stored/butil.c +++ b/bacula/src/stored/butil.c @@ -71,7 +71,6 @@ char *rec_state_to_str(DEV_RECORD *rec) DEVICE *setup_to_access_device(JCR *jcr, int read_access) { DEVICE *dev; - DEV_BLOCK *block; char *p; DEVRES *device; @@ -107,17 +106,13 @@ DEVICE *setup_to_access_device(JCR *jcr, int read_access) } Dmsg0(90, "Device opened for read.\n"); - block = new_block(dev); - create_vol_list(jcr); if (read_access) { - if (!acquire_device_for_read(jcr, dev, block)) { - free_block(block); + if (!acquire_device_for_read(jcr)) { return NULL; } } - free_block(block); return dev; } @@ -191,6 +186,10 @@ static void my_free_jcr(JCR *jcr) if (jcr->VolList) { free_vol_list(jcr); } + if (jcr->dcr) { + free_dcr(jcr->dcr); + jcr->dcr = NULL; + } return; } diff --git a/bacula/src/stored/dev.c b/bacula/src/stored/dev.c index c0d85f23b2..8b2a69937a 100644 --- a/bacula/src/stored/dev.c +++ b/bacula/src/stored/dev.c @@ -101,6 +101,7 @@ init_dev(DEVICE *dev, DEVRES *device) struct stat statp; int tape, fifo; int errstat; + DCR *dcr = NULL; /* Check that device is available */ if (stat(device->device_name, &statp) < 0) { @@ -192,7 +193,9 @@ init_dev(DEVICE *dev, DEVRES *device) Emsg0(M_FATAL, 0, dev->errmsg); } dev->fd = -1; + dev->attached_dcrs = new dlist(dcr, &dcr->dev_link); Dmsg2(29, "init_dev: tape=%d dev_name=%s\n", dev_is_tape(dev), dev->dev_name); + return dev; } @@ -1388,6 +1391,10 @@ term_dev(DEVICE *dev) pthread_mutex_destroy(&dev->mutex); pthread_cond_destroy(&dev->wait); pthread_cond_destroy(&dev->wait_next_vol); + if (dev->attached_dcrs) { + delete dev->attached_dcrs; + dev->attached_dcrs = NULL; + } if (dev->state & ST_MALLOC) { free_pool_memory((POOLMEM *)dev); } diff --git a/bacula/src/stored/dev.h b/bacula/src/stored/dev.h index 50e0325733..941b5112ca 100644 --- a/bacula/src/stored/dev.h +++ b/bacula/src/stored/dev.h @@ -31,9 +31,9 @@ /* #define NEW_LOCK 1 */ -#define new_lock_device(dev) _new_lock_device(__FILE__, __LINE__, (dev)) +#define new_lock_device(dev) _new_lock_device(__FILE__, __LINE__, (dev)) #define new_lock_device_state(dev,state) _new_lock_device(__FILE__, __LINE__, (dev), (state)) -#define new_unlock_device(dev) _new_unlock_device(__FILE__, __LINE__, (dev)) +#define new_unlock_device(dev) _new_unlock_device(__FILE__, __LINE__, (dev)) #define lock_device(d) _lock_device(__FILE__, __LINE__, (d)) #define unlock_device(d) _unlock_device(__FILE__, __LINE__, (d)) @@ -43,157 +43,162 @@ #define give_back_device_lock(d, p) _give_back_device_lock(__FILE__, __LINE__, (d), (p)) /* Arguments to open_dev() */ -#define READ_WRITE 0 -#define READ_ONLY 1 +#define READ_WRITE 0 +#define READ_ONLY 1 #define OPEN_READ_WRITE 0 -#define OPEN_READ_ONLY 1 +#define OPEN_READ_ONLY 1 #define OPEN_WRITE_ONLY 2 /* Generic status bits returned from status_dev() */ -#define BMT_TAPE (1<<0) /* is tape device */ -#define BMT_EOF (1<<1) /* just read EOF */ -#define BMT_BOT (1<<2) /* at beginning of tape */ -#define BMT_EOT (1<<3) /* end of tape reached */ -#define BMT_SM (1<<4) /* DDS setmark */ -#define BMT_EOD (1<<5) /* DDS at end of data */ -#define BMT_WR_PROT (1<<6) /* tape write protected */ -#define BMT_ONLINE (1<<7) /* tape online */ -#define BMT_DR_OPEN (1<<8) /* tape door open */ -#define BMT_IM_REP_EN (1<<9) /* immediate report enabled */ +#define BMT_TAPE (1<<0) /* is tape device */ +#define BMT_EOF (1<<1) /* just read EOF */ +#define BMT_BOT (1<<2) /* at beginning of tape */ +#define BMT_EOT (1<<3) /* end of tape reached */ +#define BMT_SM (1<<4) /* DDS setmark */ +#define BMT_EOD (1<<5) /* DDS at end of data */ +#define BMT_WR_PROT (1<<6) /* tape write protected */ +#define BMT_ONLINE (1<<7) /* tape online */ +#define BMT_DR_OPEN (1<<8) /* tape door open */ +#define BMT_IM_REP_EN (1<<9) /* immediate report enabled */ /* Test capabilities */ #define dev_cap(dev, cap) ((dev)->capabilities & (cap)) /* Bits for device capabilities */ -#define CAP_EOF (1<<0) /* has MTWEOF */ -#define CAP_BSR (1<<1) /* has MTBSR */ -#define CAP_BSF (1<<2) /* has MTBSF */ -#define CAP_FSR (1<<3) /* has MTFSR */ -#define CAP_FSF (1<<4) /* has MTFSF */ -#define CAP_EOM (1<<5) /* has MTEOM */ -#define CAP_REM (1<<6) /* is removable media */ -#define CAP_RACCESS (1<<7) /* is random access device */ -#define CAP_AUTOMOUNT (1<<8) /* Read device at start to see what is there */ -#define CAP_LABEL (1<<9) /* Label blank tapes */ -#define CAP_ANONVOLS (1<<10) /* Mount without knowing volume name */ -#define CAP_ALWAYSOPEN (1<<11) /* always keep device open */ +#define CAP_EOF (1<<0) /* has MTWEOF */ +#define CAP_BSR (1<<1) /* has MTBSR */ +#define CAP_BSF (1<<2) /* has MTBSF */ +#define CAP_FSR (1<<3) /* has MTFSR */ +#define CAP_FSF (1<<4) /* has MTFSF */ +#define CAP_EOM (1<<5) /* has MTEOM */ +#define CAP_REM (1<<6) /* is removable media */ +#define CAP_RACCESS (1<<7) /* is random access device */ +#define CAP_AUTOMOUNT (1<<8) /* Read device at start to see what is there */ +#define CAP_LABEL (1<<9) /* Label blank tapes */ +#define CAP_ANONVOLS (1<<10) /* Mount without knowing volume name */ +#define CAP_ALWAYSOPEN (1<<11) /* always keep device open */ #define CAP_AUTOCHANGER (1<<12) /* AutoChanger */ #define CAP_OFFLINEUNMOUNT (1<<13) /* Offline before unmount */ -#define CAP_STREAM (1<<14) /* Stream device */ -#define CAP_BSFATEOM (1<<15) /* Backspace file at EOM */ -#define CAP_FASTFSF (1<<16) /* Fast forward space file */ -#define CAP_TWOEOF (1<<17) /* Write two eofs for EOM */ +#define CAP_STREAM (1<<14) /* Stream device */ +#define CAP_BSFATEOM (1<<15) /* Backspace file at EOM */ +#define CAP_FASTFSF (1<<16) /* Fast forward space file */ +#define CAP_TWOEOF (1<<17) /* Write two eofs for EOM */ #define CAP_CLOSEONPOLL (1<<18) /* Close device on polling */ /* Test state */ #define dev_state(dev, st_state) ((dev)->state & (st_state)) /* Device state bits */ -#define ST_OPENED (1<<0) /* set when device opened */ -#define ST_TAPE (1<<1) /* is a tape device */ -#define ST_FILE (1<<2) /* is a file device */ -#define ST_FIFO (1<<3) /* is a fifo device */ -#define ST_PROG (1<<4) /* is a program device */ -#define ST_LABEL (1<<5) /* label found */ +#define ST_OPENED (1<<0) /* set when device opened */ +#define ST_TAPE (1<<1) /* is a tape device */ +#define ST_FILE (1<<2) /* is a file device */ +#define ST_FIFO (1<<3) /* is a fifo device */ +#define ST_PROG (1<<4) /* is a program device */ +#define ST_LABEL (1<<5) /* label found */ #define ST_MALLOC (1<<6) /* dev packet malloc'ed in init_dev() */ -#define ST_APPEND (1<<7) /* ready for Bacula append */ -#define ST_READ (1<<8) /* ready for Bacula read */ -#define ST_EOT (1<<9) /* at end of tape */ -#define ST_WEOT (1<<10) /* Got EOT on write */ -#define ST_EOF (1<<11) /* Read EOF i.e. zero bytes */ -#define ST_NEXTVOL (1<<12) /* Start writing on next volume */ -#define ST_SHORT (1<<13) /* Short block read */ +#define ST_APPEND (1<<7) /* ready for Bacula append */ +#define ST_READ (1<<8) /* ready for Bacula read */ +#define ST_EOT (1<<9) /* at end of tape */ +#define ST_WEOT (1<<10) /* Got EOT on write */ +#define ST_EOF (1<<11) /* Read EOF i.e. zero bytes */ +#define ST_NEXTVOL (1<<12) /* Start writing on next volume */ +#define ST_SHORT (1<<13) /* Short block read */ /* dev_blocked states (mutually exclusive) */ #define BST_NOT_BLOCKED 0 /* not blocked */ -#define BST_UNMOUNTED 1 /* User unmounted device */ +#define BST_UNMOUNTED 1 /* User unmounted device */ #define BST_WAITING_FOR_SYSOP 2 /* Waiting for operator to mount tape */ #define BST_DOING_ACQUIRE 3 /* Opening/validating/moving tape */ #define BST_WRITING_LABEL 4 /* Labeling a tape */ #define BST_UNMOUNTED_WAITING_FOR_SYSOP 5 /* Closed by user during mount request */ -#define BST_MOUNT 6 /* Mount request */ +#define BST_MOUNT 6 /* Mount request */ /* Volume Catalog Information structure definition */ struct VOLUME_CAT_INFO { /* Media info for the current Volume */ - uint32_t VolCatJobs; /* number of jobs on this Volume */ - uint32_t VolCatFiles; /* Number of files */ - uint32_t VolCatBlocks; /* Number of blocks */ - uint64_t VolCatBytes; /* Number of bytes written */ - uint32_t VolCatMounts; /* Number of mounts this volume */ - uint32_t VolCatErrors; /* Number of errors this volume */ - uint32_t VolCatWrites; /* Number of writes this volume */ - uint32_t VolCatReads; /* Number of reads this volume */ - uint64_t VolCatRBytes; /* Number of bytes read */ - uint32_t VolCatRecycles; /* Number of recycles this volume */ - int32_t Slot; /* Slot in changer */ - bool InChanger; /* Set if vol in current magazine */ - uint32_t VolCatMaxJobs; /* Maximum Jobs to write to volume */ - uint32_t VolCatMaxFiles; /* Maximum files to write to volume */ - uint64_t VolCatMaxBytes; /* Max bytes to write to volume */ + uint32_t VolCatJobs; /* number of jobs on this Volume */ + uint32_t VolCatFiles; /* Number of files */ + uint32_t VolCatBlocks; /* Number of blocks */ + uint64_t VolCatBytes; /* Number of bytes written */ + uint32_t VolCatMounts; /* Number of mounts this volume */ + uint32_t VolCatErrors; /* Number of errors this volume */ + uint32_t VolCatWrites; /* Number of writes this volume */ + uint32_t VolCatReads; /* Number of reads this volume */ + uint64_t VolCatRBytes; /* Number of bytes read */ + uint32_t VolCatRecycles; /* Number of recycles this volume */ + int32_t Slot; /* Slot in changer */ + bool InChanger; /* Set if vol in current magazine */ + uint32_t VolCatMaxJobs; /* Maximum Jobs to write to volume */ + uint32_t VolCatMaxFiles; /* Maximum files to write to volume */ + uint64_t VolCatMaxBytes; /* Max bytes to write to volume */ uint64_t VolCatCapacityBytes; /* capacity estimate */ - uint64_t VolReadTime; /* time spent reading */ - uint64_t VolWriteTime; /* time spent writing this Volume */ - char VolCatStatus[20]; /* Volume status */ + uint64_t VolReadTime; /* time spent reading */ + uint64_t VolWriteTime; /* time spent writing this Volume */ + char VolCatStatus[20]; /* Volume status */ char VolCatName[MAX_NAME_LENGTH]; /* Desired volume to mount */ -}; +}; typedef struct s_steal_lock { - pthread_t no_wait_id; /* id of no wait thread */ - int dev_blocked; /* state */ - int dev_prev_blocked; /* previous blocked state */ + pthread_t no_wait_id; /* id of no wait thread */ + int dev_blocked; /* state */ + int dev_prev_blocked; /* previous blocked state */ } bsteal_lock_t; -struct DEVRES; /* Device resource defined in stored_conf.h */ +struct DEVRES; /* Device resource defined in stored_conf.h */ -/* Device structure definition */ +/* + * Device structure definition. There is one of these for + * each physical device. Everything here is "global" to + * that device and effects all jobs using the device. + */ struct DEVICE { public: - DEVICE *next; /* pointer to next open device */ - DEVICE *prev; /* pointer to prev open device */ - JCR *attached_jcrs; /* attached JCR list */ - pthread_mutex_t mutex; /* access control */ - pthread_cond_t wait; /* thread wait variable */ + DEVICE *next; /* pointer to next open device */ + DEVICE *prev; /* pointer to prev open device */ + JCR *attached_jcrs; /* attached JCR list */ + dlist *attached_dcrs; /* attached DCR list */ + pthread_mutex_t mutex; /* access control */ + pthread_cond_t wait; /* thread wait variable */ pthread_cond_t wait_next_vol; /* wait for tape to be mounted */ - pthread_t no_wait_id; /* this thread must not wait */ - int dev_blocked; /* set if we must wait (i.e. change tape) */ - int dev_prev_blocked; /* previous blocked state */ - int num_waiting; /* number of threads waiting */ - int num_writers; /* number of writing threads */ - int use_count; /* usage count on this device */ - int fd; /* file descriptor */ - int capabilities; /* capabilities mask */ - int state; /* state mask */ - int dev_errno; /* Our own errno */ - int mode; /* read/write modes */ - char *dev_name; /* device name */ - char *errmsg; /* nicely edited error message */ - uint32_t block_num; /* current block number base 0 */ - uint32_t file; /* current file number base 0 */ - uint64_t file_addr; /* Current file read/write address */ - 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 */ - 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 */ - uint64_t volume_capacity; /* advisory capacity */ - uint32_t max_rewind_wait; /* max secs to allow for rewind */ - uint32_t max_open_wait; /* max secs to allow for open */ - uint32_t max_open_vols; /* max simultaneous open volumes */ - utime_t vol_poll_interval; /* interval between polling Vol mount */ - DEVRES *device; /* pointer to Device Resource */ - btimer_t *tid; /* timer id */ - - VOLUME_CAT_INFO VolCatInfo; /* Volume Catalog Information */ - VOLUME_LABEL VolHdr; /* Actual volume label */ + pthread_t no_wait_id; /* this thread must not wait */ + int dev_blocked; /* set if we must wait (i.e. change tape) */ + int dev_prev_blocked; /* previous blocked state */ + int num_waiting; /* number of threads waiting */ + int num_writers; /* number of writing threads */ + int use_count; /* usage count on this device */ + int fd; /* file descriptor */ + int capabilities; /* capabilities mask */ + int state; /* state mask */ + int dev_errno; /* Our own errno */ + int mode; /* read/write modes */ + char *dev_name; /* device name */ + char *errmsg; /* nicely edited error message */ + uint32_t block_num; /* current block number base 0 */ + uint32_t file; /* current file number base 0 */ + uint64_t file_addr; /* Current file read/write address */ + 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 */ + 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 */ + uint64_t volume_capacity; /* advisory capacity */ + uint32_t max_rewind_wait; /* max secs to allow for rewind */ + uint32_t max_open_wait; /* max secs to allow for open */ + uint32_t max_open_vols; /* max simultaneous open volumes */ + utime_t vol_poll_interval; /* interval between polling Vol mount */ + DEVRES *device; /* pointer to Device Resource */ + btimer_t *tid; /* timer id */ + + VOLUME_CAT_INFO VolCatInfo; /* Volume Catalog Information */ + VOLUME_LABEL VolHdr; /* Actual volume label */ /* Device wait times ***FIXME*** look at durations */ char BadVolName[MAX_NAME_LENGTH]; /* Last wrong Volume mounted */ - bool poll; /* set to poll Volume */ + bool poll; /* set to poll Volume */ int min_wait; int max_wait; int max_num_wait; @@ -202,13 +207,41 @@ public: int num_wait; }; +/* + * Device Context (or Control) Record. + * There is one of these records for each Job that is using + * the device. Items in this record are "local" to the Job and + * do not affect other Jobs. + */ +struct DCR { + dlink dev_link; /* link to attach to dev */ + JCR *jcr; /* pointer to JCR */ + DEVICE *dev; /* pointer to device */ + DEV_BLOCK *block; /* pointer to block */ + DEV_RECORD *record; /* pointer to record */ + bool spool_data; /* set to spool data */ + int spool_fd; /* fd if spooling */ + bool NewVol; /* set if new Volume mounted */ + bool WroteVol; /* set if Volume written */ + bool NewFile; /* set when EOF written */ + uint32_t VolFirstIndex; /* First file index this Volume */ + uint32_t VolLastIndex; /* Last file index this Volume */ + uint32_t FileIndex; /* Current File Index */ + uint32_t EndFile; /* End file written */ + uint32_t StartFile; /* Start write file */ + uint32_t StartBlock; /* Start write block */ + uint32_t EndBlock; /* Ending block written */ + char VolumeName[MAX_NAME_LENGTH]; /* Volume name */ + VOLUME_CAT_INFO VolCatInfo; /* Catalog info for desired volume */ +}; + /* Get some definition of function to position * to the end of the medium in MTEOM. System * dependent. Arrgggg! */ #ifndef MTEOM -#ifdef MTSEOD +#ifdef MTSEOD #define MTEOM MTSEOD #endif #ifdef MTEOD diff --git a/bacula/src/stored/device.c b/bacula/src/stored/device.c index 51267b4e13..3351c87ecb 100644 --- a/bacula/src/stored/device.c +++ b/bacula/src/stored/device.c @@ -164,14 +164,15 @@ int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) if (mjcr->JobId == 0) { continue; /* ignore console */ } - mjcr->NewVol = true; + mjcr->dcr->NewVol = true; if (jcr != mjcr) { pm_strcpy(&mjcr->VolumeName, jcr->VolumeName); /* get a copy of the new volume */ + bstrncpy(mjcr->dcr->VolumeName, jcr->VolumeName, sizeof(mjcr->dcr->VolumeName)); } } /* Clear NewVol now because dir_get_volume_info() already done */ - jcr->NewVol = false; + jcr->dcr->NewVol = false; set_new_volume_parameters(jcr, dev); jcr->run_time += time(NULL) - wait_time; /* correct run time for mount wait */ @@ -196,23 +197,24 @@ int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) */ void set_new_volume_parameters(JCR *jcr, DEVICE *dev) { - if (jcr->NewVol && !dir_get_volume_info(jcr, GET_VOL_INFO_FOR_WRITE)) { + DCR *dcr = jcr->dcr; + if (dcr->NewVol && !dir_get_volume_info(jcr, GET_VOL_INFO_FOR_WRITE)) { Jmsg1(jcr, M_ERROR, 0, "%s", jcr->errmsg); } /* Set new start/end positions */ if (dev_state(dev, ST_TAPE)) { - jcr->StartBlock = dev->block_num; - jcr->StartFile = dev->file; + dcr->StartBlock = dev->block_num; + dcr->StartFile = dev->file; } else { - jcr->StartBlock = (uint32_t)dev->file_addr; - jcr->StartFile = (uint32_t)(dev->file_addr >> 32); + dcr->StartBlock = (uint32_t)dev->file_addr; + dcr->StartFile = (uint32_t)(dev->file_addr >> 32); } /* Reset indicies */ - jcr->VolFirstIndex = 0; - jcr->VolLastIndex = 0; + dcr->VolFirstIndex = 0; + dcr->VolLastIndex = 0; jcr->NumVolumes++; - jcr->NewVol = false; - jcr->WroteVol = false; + dcr->NewVol = false; + dcr->WroteVol = false; } /* @@ -222,19 +224,21 @@ void set_new_volume_parameters(JCR *jcr, DEVICE *dev) */ void set_new_file_parameters(JCR *jcr, DEVICE *dev) { + DCR *dcr = jcr->dcr; + /* Set new start/end positions */ if (dev_state(dev, ST_TAPE)) { - jcr->StartBlock = dev->block_num; - jcr->StartFile = dev->file; + dcr->StartBlock = dev->block_num; + dcr->StartFile = dev->file; } else { - jcr->StartBlock = (uint32_t)dev->file_addr; - jcr->StartFile = (uint32_t)(dev->file_addr >> 32); + dcr->StartBlock = (uint32_t)dev->file_addr; + dcr->StartFile = (uint32_t)(dev->file_addr >> 32); } /* Reset indicies */ - jcr->VolFirstIndex = 0; - jcr->VolLastIndex = 0; - jcr->NewFile = false; - jcr->WroteVol = false; + dcr->VolFirstIndex = 0; + dcr->VolLastIndex = 0; + dcr->NewFile = false; + dcr->WroteVol = false; } diff --git a/bacula/src/stored/dircmd.c b/bacula/src/stored/dircmd.c index f0b891e95b..bd309d5694 100644 --- a/bacula/src/stored/dircmd.c +++ b/bacula/src/stored/dircmd.c @@ -462,6 +462,9 @@ static bool find_device(JCR *jcr, char *dname) break; } } + if (found) { + jcr->dcr = new_dcr(jcr, device->dev); + } UnlockRes(); return found; } diff --git a/bacula/src/stored/job.c b/bacula/src/stored/job.c index 6c54e6d835..7a9ffa02dc 100644 --- a/bacula/src/stored/job.c +++ b/bacula/src/stored/job.c @@ -103,7 +103,7 @@ int job_cmd(JCR *jcr) */ ojcr = get_jcr_by_full_name(job); if (ojcr && !ojcr->authenticated) { - Dmsg2(100, "Found ojcr=0x%x Job %s\n", (unsigned)ojcr, job); + Dmsg2(100, "Found ojcr=0x%x Job %s\n", (unsigned)(long)ojcr, job); free_jcr(ojcr); } jcr->JobId = JobId; @@ -362,5 +362,9 @@ void stored_free_jcr(JCR *jcr) Emsg0(M_FATAL, 0, _("In free_jcr(), but still attached to device!!!!\n")); } pthread_cond_destroy(&jcr->job_start_wait); + if (jcr->dcr) { + free_dcr(jcr->dcr); + jcr->dcr = NULL; + } return; } diff --git a/bacula/src/stored/label.c b/bacula/src/stored/label.c index 559bb7c2ae..e1d5aa609f 100644 --- a/bacula/src/stored/label.c +++ b/bacula/src/stored/label.c @@ -443,6 +443,7 @@ int write_volume_label_to_dev(JCR *jcr, DEVRES *device, char *VolName, char *Poo */ void create_session_label(JCR *jcr, DEV_RECORD *rec, int label) { + DCR *dcr = jcr->dcr; ser_declare; rec->VolSessionId = jcr->VolSessionId; @@ -476,10 +477,10 @@ void create_session_label(JCR *jcr, DEV_RECORD *rec, int label) if (label == EOS_LABEL) { ser_uint32(jcr->JobFiles); ser_uint64(jcr->JobBytes); - ser_uint32(jcr->StartBlock); - ser_uint32(jcr->EndBlock); - ser_uint32(jcr->StartFile); - ser_uint32(jcr->EndFile); + ser_uint32(dcr->StartBlock); + ser_uint32(dcr->EndBlock); + ser_uint32(dcr->StartFile); + ser_uint32(dcr->EndFile); ser_uint32(jcr->JobErrors); /* Added in VerNum 11 */ @@ -496,6 +497,7 @@ void create_session_label(JCR *jcr, DEV_RECORD *rec, int label) int write_session_label(JCR *jcr, DEV_BLOCK *block, int label) { DEVICE *dev = jcr->device->dev; + DCR *dcr = jcr->dcr; DEV_RECORD *rec; rec = new_record(); @@ -503,20 +505,20 @@ int write_session_label(JCR *jcr, DEV_BLOCK *block, int label) switch (label) { case SOS_LABEL: if (dev->state & ST_TAPE) { - jcr->StartBlock = dev->block_num; - jcr->StartFile = dev->file; + dcr->StartBlock = dev->block_num; + dcr->StartFile = dev->file; } else { - jcr->StartBlock = (uint32_t)dev->file_addr; - jcr->StartFile = (uint32_t)(dev->file_addr >> 32); + dcr->StartBlock = (uint32_t)dev->file_addr; + dcr->StartFile = (uint32_t)(dev->file_addr >> 32); } break; case EOS_LABEL: if (dev->state & ST_TAPE) { - jcr->EndBlock = dev->EndBlock; - jcr->EndFile = dev->EndFile; + dcr->EndBlock = dev->EndBlock; + dcr->EndFile = dev->EndFile; } else { - jcr->EndBlock = (uint32_t)dev->file_addr; - jcr->EndFile = (uint32_t)(dev->file_addr >> 32); + dcr->EndBlock = (uint32_t)dev->file_addr; + dcr->EndFile = (uint32_t)(dev->file_addr >> 32); } break; default: diff --git a/bacula/src/stored/mount.c b/bacula/src/stored/mount.c index 78f689932d..ced3c8ea71 100644 --- a/bacula/src/stored/mount.c +++ b/bacula/src/stored/mount.c @@ -406,7 +406,7 @@ int mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) if (jcr->NumVolumes > 1 && jcr->CurVolume < jcr->NumVolumes) { close_dev(dev); dev->state &= ~ST_READ; - if (!acquire_device_for_read(jcr, dev, block)) { + if (!acquire_device_for_read(jcr)) { Jmsg2(jcr, M_FATAL, 0, "Cannot open Dev=%s, Vol=%s\n", dev_name(dev), jcr->VolumeName); return 0; @@ -423,7 +423,7 @@ int mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) */ void release_volume(JCR *jcr, DEVICE *dev) { - if (jcr->WroteVol) { + if (jcr->dcr->WroteVol) { Jmsg0(jcr, M_ERROR, 0, "Hey!!!!! WroteVol non-zero !!!!!\n"); } /* diff --git a/bacula/src/stored/protos.h b/bacula/src/stored/protos.h index 33025556ea..f4c3776047 100644 --- a/bacula/src/stored/protos.h +++ b/bacula/src/stored/protos.h @@ -28,168 +28,170 @@ uint32_t new_VolSessionId(); /* From acquire.c */ -DEVICE *acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -int acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -int release_device(JCR *jcr, DEVICE *dev); +DCR *acquire_device_for_append(JCR *jcr); +DCR *acquire_device_for_read(JCR *jcr); +int release_device(JCR *jcr); +DCR *new_dcr(JCR *jcr, DEVICE *dev); +void free_dcr(DCR *dcr); /* From askdir.c */ enum get_vol_info_rw { GET_VOL_INFO_FOR_WRITE, GET_VOL_INFO_FOR_READ }; -int dir_get_volume_info(JCR *jcr, enum get_vol_info_rw); -int dir_find_next_appendable_volume(JCR *jcr); -int dir_update_volume_info(JCR *jcr, DEVICE *dev, int label); -int dir_ask_sysop_to_create_appendable_volume(JCR *jcr, DEVICE *dev); -int dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev); -int dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec); -int dir_send_job_status(JCR *jcr); -int dir_create_jobmedia_record(JCR *jcr); +int dir_get_volume_info(JCR *jcr, enum get_vol_info_rw); +int dir_find_next_appendable_volume(JCR *jcr); +int dir_update_volume_info(JCR *jcr, DEVICE *dev, int label); +int dir_ask_sysop_to_create_appendable_volume(JCR *jcr, DEVICE *dev); +int dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev); +int dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec); +int dir_send_job_status(JCR *jcr); +int dir_create_jobmedia_record(JCR *jcr); /* authenticate.c */ -int authenticate_director(JCR *jcr); -int authenticate_filed(JCR *jcr); +int authenticate_director(JCR *jcr); +int authenticate_filed(JCR *jcr); /* From block.c */ -void dump_block(DEV_BLOCK *b, char *msg); +void dump_block(DEV_BLOCK *b, char *msg); DEV_BLOCK *new_block(DEVICE *dev); DEV_BLOCK *dup_block(DEV_BLOCK *eblock); -void init_block_write(DEV_BLOCK *block); -void empty_block(DEV_BLOCK *block); -void free_block(DEV_BLOCK *block); -int write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -void print_block_read_errors(JCR *jcr, DEV_BLOCK *block); +void init_block_write(DEV_BLOCK *block); +void empty_block(DEV_BLOCK *block); +void free_block(DEV_BLOCK *block); +int write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +void print_block_read_errors(JCR *jcr, DEV_BLOCK *block); #define CHECK_BLOCK_NUMBERS true #define NO_BLOCK_NUMBER_CHECK false -int read_block_from_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, bool check_block_numbers); -int read_block_from_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, bool check_block_numbers); +int read_block_from_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, bool check_block_numbers); +int read_block_from_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, bool check_block_numbers); /* From butil.c -- utilities for SD tool programs */ -void print_ls_output(char *fname, char *link, int type, struct stat *statp); +void print_ls_output(char *fname, char *link, int type, struct stat *statp); JCR *setup_jcr(char *name, char *device, BSR *bsr, char *VolumeName); DEVICE *setup_to_access_device(JCR *jcr, int read_access); -void display_tape_error_status(JCR *jcr, DEVICE *dev); +void display_tape_error_status(JCR *jcr, DEVICE *dev); DEVRES *find_device_res(char *device_name, int read_access); /* From dev.c */ -DEVICE *init_dev(DEVICE *dev, DEVRES *device); -int open_dev(DEVICE *dev, char *VolName, int mode); -void close_dev(DEVICE *dev); -void force_close_dev(DEVICE *dev); -int truncate_dev(DEVICE *dev); -void term_dev(DEVICE *dev); -char * strerror_dev(DEVICE *dev); -void clrerror_dev(DEVICE *dev, int func); -int update_pos_dev(DEVICE *dev); -int rewind_dev(DEVICE *dev); -int load_dev(DEVICE *dev); -int offline_dev(DEVICE *dev); -int flush_dev(DEVICE *dev); -int weof_dev(DEVICE *dev, int num); -int write_block(DEVICE *dev); -int write_dev(DEVICE *dev, char *buf, size_t len); -int read_dev(DEVICE *dev, char *buf, size_t len); +DEVICE *init_dev(DEVICE *dev, DEVRES *device); +int open_dev(DEVICE *dev, char *VolName, int mode); +void close_dev(DEVICE *dev); +void force_close_dev(DEVICE *dev); +int truncate_dev(DEVICE *dev); +void term_dev(DEVICE *dev); +char * strerror_dev(DEVICE *dev); +void clrerror_dev(DEVICE *dev, int func); +int update_pos_dev(DEVICE *dev); +int rewind_dev(DEVICE *dev); +int load_dev(DEVICE *dev); +int offline_dev(DEVICE *dev); +int flush_dev(DEVICE *dev); +int weof_dev(DEVICE *dev, int num); +int write_block(DEVICE *dev); +int write_dev(DEVICE *dev, char *buf, size_t len); +int read_dev(DEVICE *dev, char *buf, size_t len); uint32_t status_dev(DEVICE *dev); -int eod_dev(DEVICE *dev); -int fsf_dev(DEVICE *dev, int num); -int fsr_dev(DEVICE *dev, int num); -int bsf_dev(DEVICE *dev, int num); -int bsr_dev(DEVICE *dev, int num); -void attach_jcr_to_device(DEVICE *dev, JCR *jcr); -void detach_jcr_from_device(DEVICE *dev, JCR *jcr); -JCR *next_attached_jcr(DEVICE *dev, JCR *jcr); -int dev_can_write(DEVICE *dev); -int offline_or_rewind_dev(DEVICE *dev); -int reposition_dev(DEVICE *dev, uint32_t file, uint32_t block); -void init_dev_wait_timers(DEVICE *dev); -bool double_dev_wait_time(DEVICE *dev); +int eod_dev(DEVICE *dev); +int fsf_dev(DEVICE *dev, int num); +int fsr_dev(DEVICE *dev, int num); +int bsf_dev(DEVICE *dev, int num); +int bsr_dev(DEVICE *dev, int num); +void attach_jcr_to_device(DEVICE *dev, JCR *jcr); +void detach_jcr_from_device(DEVICE *dev, JCR *jcr); +JCR *next_attached_jcr(DEVICE *dev, JCR *jcr); +int dev_can_write(DEVICE *dev); +int offline_or_rewind_dev(DEVICE *dev); +int reposition_dev(DEVICE *dev, uint32_t file, uint32_t block); +void init_dev_wait_timers(DEVICE *dev); +bool double_dev_wait_time(DEVICE *dev); /* Get info about device */ -char * dev_name(DEVICE *dev); -char * dev_vol_name(DEVICE *dev); +char * dev_name(DEVICE *dev); +char * dev_vol_name(DEVICE *dev); uint32_t dev_block(DEVICE *dev); uint32_t dev_file(DEVICE *dev); -int dev_is_tape(DEVICE *dev); +int dev_is_tape(DEVICE *dev); /* From device.c */ -int open_device(JCR *jcr, DEVICE *dev); -int first_open_device(DEVICE *dev); -int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -void _lock_device(char *file, int line, DEVICE *dev); -void _unlock_device(char *file, int line, DEVICE *dev); -void _block_device(char *file, int line, DEVICE *dev, int state); -void _unblock_device(char *file, int line, DEVICE *dev); -void _steal_device_lock(char *file, int line, DEVICE *dev, bsteal_lock_t *hold, int state); -void _give_back_device_lock(char *file, int line, DEVICE *dev, bsteal_lock_t *hold); -void set_new_volume_parameters(JCR *jcr, DEVICE *dev); -void set_new_file_parameters(JCR *jcr, DEVICE *dev); -int device_is_unmounted(DEVICE *dev); +int open_device(JCR *jcr, DEVICE *dev); +int first_open_device(DEVICE *dev); +int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +void _lock_device(char *file, int line, DEVICE *dev); +void _unlock_device(char *file, int line, DEVICE *dev); +void _block_device(char *file, int line, DEVICE *dev, int state); +void _unblock_device(char *file, int line, DEVICE *dev); +void _steal_device_lock(char *file, int line, DEVICE *dev, bsteal_lock_t *hold, int state); +void _give_back_device_lock(char *file, int line, DEVICE *dev, bsteal_lock_t *hold); +void set_new_volume_parameters(JCR *jcr, DEVICE *dev); +void set_new_file_parameters(JCR *jcr, DEVICE *dev); +int device_is_unmounted(DEVICE *dev); /* From dircmd.c */ -void *connection_request(void *arg); +void *connection_request(void *arg); /* From fd_cmds.c */ -void run_job(JCR *jcr); +void run_job(JCR *jcr); /* From job.c */ -void stored_free_jcr(JCR *jcr); -void connection_from_filed(void *arg); -void handle_filed_connection(BSOCK *fd, char *job_name); +void stored_free_jcr(JCR *jcr); +void connection_from_filed(void *arg); +void handle_filed_connection(BSOCK *fd, char *job_name); /* From label.c */ -int read_dev_volume_label(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -void create_session_label(JCR *jcr, DEV_RECORD *rec, int label); -void create_volume_label(DEVICE *dev, char *VolName, char *PoolName); -int write_volume_label_to_dev(JCR *jcr, DEVRES *device, char *VolName, char *PoolName); -int write_session_label(JCR *jcr, DEV_BLOCK *block, int label); -int write_volume_label_to_block(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -void dump_volume_label(DEVICE *dev); -void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose); -int unser_volume_label(DEVICE *dev, DEV_RECORD *rec); -int unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec); +int read_dev_volume_label(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +void create_session_label(JCR *jcr, DEV_RECORD *rec, int label); +void create_volume_label(DEVICE *dev, char *VolName, char *PoolName); +int write_volume_label_to_dev(JCR *jcr, DEVRES *device, char *VolName, char *PoolName); +int write_session_label(JCR *jcr, DEV_BLOCK *block, int label); +int write_volume_label_to_block(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +void dump_volume_label(DEVICE *dev); +void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose); +int unser_volume_label(DEVICE *dev, DEV_RECORD *rec); +int unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec); /* From match_bsr.c */ -int match_bsr(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec, - SESSION_LABEL *sesrec); -int match_bsr_block(BSR *bsr, DEV_BLOCK *block); -void position_bsr_block(BSR *bsr, DEV_BLOCK *block); -BSR *find_next_bsr(BSR *root_bsr, DEVICE *dev); -bool match_set_eof(BSR *bsr, DEV_RECORD *rec); +int match_bsr(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec, + SESSION_LABEL *sesrec); +int match_bsr_block(BSR *bsr, DEV_BLOCK *block); +void position_bsr_block(BSR *bsr, DEV_BLOCK *block); +BSR *find_next_bsr(BSR *root_bsr, DEVICE *dev); +bool match_set_eof(BSR *bsr, DEV_RECORD *rec); /* From mount.c */ -int mount_next_write_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, int release); -int mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -void release_volume(JCR *jcr, DEVICE *dev); -void mark_volume_in_error(JCR *jcr, DEVICE *dev); +int mount_next_write_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, int release); +int mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +void release_volume(JCR *jcr, DEVICE *dev); +void mark_volume_in_error(JCR *jcr, DEVICE *dev); /* From autochanger.c */ -int autoload_device(JCR *jcr, DEVICE *dev, int writing, BSOCK *dir); -int autochanger_list(JCR *jcr, DEVICE *dev, BSOCK *dir); -void invalidate_slot_in_catalog(JCR *jcr, DEVICE *dev); +int autoload_device(JCR *jcr, DEVICE *dev, int writing, BSOCK *dir); +int autochanger_list(JCR *jcr, DEVICE *dev, BSOCK *dir); +void invalidate_slot_in_catalog(JCR *jcr, DEVICE *dev); /* From parse_bsr.c */ -BSR *parse_bsr(JCR *jcr, char *lf); -void dump_bsr(BSR *bsr, bool recurse); -void free_bsr(BSR *bsr); +BSR *parse_bsr(JCR *jcr, char *lf); +void dump_bsr(BSR *bsr, bool recurse); +void free_bsr(BSR *bsr); VOL_LIST *new_vol(); -int add_vol(JCR *jcr, VOL_LIST *vol); -void free_vol_list(JCR *jcr); -void create_vol_list(JCR *jcr); +int add_vol(JCR *jcr, VOL_LIST *vol); +void free_vol_list(JCR *jcr); +void create_vol_list(JCR *jcr); /* From record.c */ -char *FI_to_ascii(int fi); -char *stream_to_ascii(int stream, int fi); -int write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); -int can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); -int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec); +char *FI_to_ascii(int fi); +char *stream_to_ascii(int stream, int fi); +int write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); +int can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); +int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec); DEV_RECORD *new_record(); -void free_record(DEV_RECORD *rec); +void free_record(DEV_RECORD *rec); /* From read_record.c */ int read_records(JCR *jcr, DEVICE *dev, diff --git a/bacula/src/stored/read.c b/bacula/src/stored/read.c index 1285e5a0d7..0e7dbeb8ca 100644 --- a/bacula/src/stored/read.c +++ b/bacula/src/stored/read.c @@ -34,6 +34,7 @@ static int record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec); /* Responses sent to the File daemon */ static char OK_data[] = "3000 OK data\n"; +static char FD_error[] = "3000 error\n"; static char rec_header[] = "rechdr %ld %ld %ld %ld %ld"; /* @@ -47,29 +48,26 @@ int do_read_data(JCR *jcr) int ok = TRUE; DEVICE *dev; DEV_BLOCK *block; + DCR *dcr; Dmsg0(20, "Start read data.\n"); dev = jcr->device->dev; - /* Tell File daemon we will send data */ - bnet_fsend(fd, OK_data); Dmsg1(10, "bstored>filed: %s\n", fd->msg); - if (!bnet_set_buffer_size(fd, dev->device->max_network_buffer_size, BNET_SETBUF_WRITE)) { + if (!bnet_set_buffer_size(fd, jcr->device->max_network_buffer_size, BNET_SETBUF_WRITE)) { return 0; } Dmsg1(20, "Begin read device=%s\n", dev_name(dev)); - block = new_block(dev); - create_vol_list(jcr); if (jcr->NumVolumes == 0) { Jmsg(jcr, M_FATAL, 0, _("No Volume names found for restore.\n")); - free_block(block); free_vol_list(jcr); + bnet_fsend(fd, FD_error); return 0; } @@ -81,22 +79,24 @@ int do_read_data(JCR *jcr) /* * Ready device for reading, and read records */ - if (!acquire_device_for_read(jcr, dev, block)) { - free_block(block); + if (!acquire_device_for_read(jcr)) { free_vol_list(jcr); return 0; } + block = dcr->block; + + /* Tell File daemon we will send data */ + bnet_fsend(fd, OK_data); ok = read_records(jcr, dev, record_cb, mount_next_read_volume); /* Send end of data to FD */ bnet_sig(fd, BNET_EOD); - if (!release_device(jcr, dev)) { + if (!release_device(jcr)) { ok = FALSE; } - free_block(block); free_vol_list(jcr); Dmsg0(30, "Done reading.\n"); return ok ? 1 : 0; diff --git a/bacula/src/stored/stored.c b/bacula/src/stored/stored.c index 54d8e2524d..ae82a14028 100644 --- a/bacula/src/stored/stored.c +++ b/bacula/src/stored/stored.c @@ -304,6 +304,7 @@ static void *device_allocation(void *arg) Emsg1(M_ERROR, 0, _("Could not initialize %s\n"), device->device_name); continue; } + if (device->cap_bits & CAP_ALWAYSOPEN) { Dmsg1(20, "calling first_open_device %s\n", device->device_name); if (!first_open_device(device->dev)) { @@ -312,11 +313,12 @@ static void *device_allocation(void *arg) } if (device->cap_bits & CAP_AUTOMOUNT && device->dev && device->dev->state & ST_OPENED) { - DEV_BLOCK *block; JCR *jcr; - block = new_block(device->dev); + DCR *dcr; jcr = new_jcr(sizeof(JCR), stored_free_jcr); - switch (read_dev_volume_label(jcr, device->dev, block)) { + jcr->device = device; + dcr = new_dcr(jcr, device->dev); + switch (read_dev_volume_label(jcr, device->dev, dcr->block)) { case VOL_OK: break; default: @@ -324,7 +326,6 @@ static void *device_allocation(void *arg) break; } free_jcr(jcr); - free_block(block); } } UnlockRes(); diff --git a/bacula/src/version.h b/bacula/src/version.h index f50e7891df..0ab3d658f2 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -2,8 +2,8 @@ #undef VERSION #define VERSION "1.33.4" #define VSTRING "1" -#define BDATE "02 Mar 2004" -#define LSMDATE "02Mar04" +#define BDATE "06 Mar 2004" +#define LSMDATE "06Mar04" /* Debug flags */ #undef DEBUG -- 2.39.2