From 2a077f08e469e03b56576196f351faba15761b9f Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Sun, 18 Mar 2007 20:10:58 +0000 Subject: [PATCH] kes Move the checking of the database in initializion of the Director to after we drop privileges. This avoids the need for both root and bacula access to the DB. kes Correct a misplaced variable definition in src/filed/backup.c kes Correct how the new batch insert db_create_attributes_record() uses the arguments. Caused a seg fault in bscan. kes Implement lock() and unlock() methods in DEVICE class. Implement block() and set_block(xx) methods in DEVICE class. kes Modify bnet_connect() so that it uses time() to check for the wait time expiring (on some OSes, some system calls may not return immediately). kes Modify Verify to obtain the previous JobId when it is actually running rather than at schedule time (as it was in 1.38.x). kes Fix src/job.c to handle MaxWaitTime correctly. This should fix bug #802. kes When checking pid in pid file, continue running if the pid is the same as ours. This occurs on IRIX after a system crash. Fixes bug #797. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@4358 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/src/cats/sql_create.c | 34 ++--- bacula/src/cats/sqlite.c | 16 +-- bacula/src/dird/dird.c | 233 +++++++++++++++++--------------- bacula/src/dird/job.c | 90 +----------- bacula/src/filed/backup.c | 2 +- bacula/src/lib/bnet.c | 8 +- bacula/src/lib/bsock.h | 1 - bacula/src/lib/bsys.c | 14 +- bacula/src/lib/protos.h | 2 +- bacula/src/stored/acquire.c | 12 +- bacula/src/stored/askdir.c | 8 +- bacula/src/stored/autochanger.c | 6 +- bacula/src/stored/dev.c | 16 ++- bacula/src/stored/dev.h | 50 +++---- bacula/src/stored/device.c | 90 ++++++------ bacula/src/stored/dircmd.c | 97 +++++++------ bacula/src/stored/protos.h | 2 - bacula/src/stored/reserve.c | 34 ++--- bacula/src/stored/status.c | 20 +-- bacula/src/stored/stored.c | 32 ++--- bacula/src/stored/wait.c | 32 ++--- bacula/src/version.h | 6 +- bacula/technotes-2.1 | 19 +++ 23 files changed, 405 insertions(+), 419 deletions(-) diff --git a/bacula/src/cats/sql_create.c b/bacula/src/cats/sql_create.c index 47ea132ca1..282aede043 100644 --- a/bacula/src/cats/sql_create.c +++ b/bacula/src/cats/sql_create.c @@ -53,9 +53,11 @@ static const int dbglevel = 500; */ /* Forward referenced subroutines */ +#ifndef HAVE_BATCH_FILE_INSERT static int db_create_file_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar); static int db_create_filename_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar); static int db_create_path_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar); +#endif /* HAVE_BATCH_FILE_INSERT */ /* Create a new record for the Job @@ -810,20 +812,19 @@ int db_create_batch_file_record(JCR *jcr) * how many times it occurs. This is this subroutine, we separate * the file and the path and fill temporary tables with this three records. */ -int db_create_file_attributes_record(JCR *jcr, B_DB *_mdb, ATTR_DBR *ar) +int db_create_file_attributes_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar) { - Dmsg1(dbglevel, "Fname=%s\n", ar->fname); Dmsg0(dbglevel, "put_file_into_catalog\n"); if (!jcr->db_batch) { jcr->db_batch = db_init_database(jcr, - jcr->db->db_name, - jcr->db->db_user, - jcr->db->db_password, - jcr->db->db_address, - jcr->db->db_port, - jcr->db->db_socket, + mdb->db_name, + mdb->db_user, + mdb->db_password, + mdb->db_address, + mdb->db_port, + mdb->db_socket, 1 /* multi_db = true */); if (!jcr->db_batch || !db_open_database(jcr, jcr->db_batch)) { @@ -838,31 +839,31 @@ int db_create_file_attributes_record(JCR *jcr, B_DB *_mdb, ATTR_DBR *ar) sql_batch_start(jcr->db_batch); } - B_DB *mdb = jcr->db_batch; + B_DB *bdb = jcr->db_batch; /* * Make sure we have an acceptable attributes record. */ if (!(ar->Stream == STREAM_UNIX_ATTRIBUTES || ar->Stream == STREAM_UNIX_ATTRIBUTES_EX)) { - Mmsg1(&mdb->errmsg, _("Attempt to put non-attributes into catalog. Stream=%d\n"), + Mmsg1(&bdb->errmsg, _("Attempt to put non-attributes into catalog. Stream=%d\n"), ar->Stream); - Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); + Jmsg(jcr, M_ERROR, 0, "%s", bdb->errmsg); return 0; } - split_path_and_file(jcr, mdb, ar->fname); + split_path_and_file(jcr, bdb, ar->fname); /* if (jcr->changes > 100000) { - sql_batch_end(mdb, NULL); - sql_batch_start(mdb); + sql_batch_end(bdb, NULL); + sql_batch_start(bdb); jcr->changes = 0; } */ - return (sql_batch_insert(mdb, ar) == 0); + return (sql_batch_insert(bdb, ar) == 0); } #else /* ! HAVE_BATCH_FILE_INSERT */ @@ -922,7 +923,6 @@ bail_out: return 0; } -#endif /* ! HAVE_BATCH_FILE_INSERT */ /* * This is the master File entry containing the attributes. @@ -1081,4 +1081,6 @@ static int db_create_filename_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar) return ar->FilenameId > 0; } +#endif /* ! HAVE_BATCH_FILE_INSERT */ + #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL */ diff --git a/bacula/src/cats/sqlite.c b/bacula/src/cats/sqlite.c index 6c9b7f498a..32dd34853d 100644 --- a/bacula/src/cats/sqlite.c +++ b/bacula/src/cats/sqlite.c @@ -1,14 +1,7 @@ -/* - * Bacula Catalog Database routines specific to SQLite - * - * Kern Sibbald, January 2002 - * - * Version $Id$ - */ /* Bacula® - The Network Backup Solution - Copyright (C) 2000-2006 Free Software Foundation Europe e.V. + Copyright (C) 2000-2007 Free Software Foundation Europe e.V. The main author of Bacula is Kern Sibbald, with contributions from many others, a complete list can be found in the file AUTHORS. @@ -32,6 +25,13 @@ (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, Switzerland, email:ftf@fsfeurope.org. */ +/* + * Bacula Catalog Database routines specific to SQLite + * + * Kern Sibbald, January 2002 + * + * Version $Id$ + */ diff --git a/bacula/src/dird/dird.c b/bacula/src/dird/dird.c index 62c38dee31..733b8dcfc1 100644 --- a/bacula/src/dird/dird.c +++ b/bacula/src/dird/dird.c @@ -1,15 +1,7 @@ -/* - * - * Bacula Director daemon -- this is the main program - * - * Kern Sibbald, March MM - * - * Version $Id$ - */ /* Bacula® - The Network Backup Solution - Copyright (C) 2000-2006 Free Software Foundation Europe e.V. + Copyright (C) 2000-2007 Free Software Foundation Europe e.V. The main author of Bacula is Kern Sibbald, with contributions from many others, a complete list can be found in the file AUTHORS. @@ -33,13 +25,22 @@ (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, Switzerland, email:ftf@fsfeurope.org. */ +/* + * + * Bacula Director daemon -- this is the main program + * + * Kern Sibbald, March MM + * + * Version $Id$ + */ #include "bacula.h" #include "dird.h" /* Forward referenced subroutines */ void terminate_dird(int sig); -static int check_resources(); +static bool check_resources(); +static bool check_catalog(); static void dir_sql_query(JCR *jcr, const char *cmd); /* Exported subroutines */ @@ -113,6 +114,7 @@ PROG_COPYRIGHT * */ #if defined(HAVE_WIN32) +/* For Win32 main() is in src/win32 code ... */ #define main BaculaMain #endif @@ -246,7 +248,11 @@ int main (int argc, char *argv[]) create_pid_file(director->pid_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs)); read_state_file(director->working_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs)); - drop(uid, gid); /* reduce priveleges if requested */ + drop(uid, gid); /* reduce privileges if requested */ + + if (!check_catalog()) { + Jmsg((JCR *)NULL, M_ERROR_TERM, 0, _("Please correct configuration file: %s\n"), configfile); + } #if !defined(HAVE_WIN32) signal(SIGHUP, reload_config); @@ -511,7 +517,7 @@ bail_out: * **** FIXME **** this routine could be a lot more * intelligent and comprehensive. */ -static int check_resources() +static bool check_resources() { bool OK = true; JOB *job; @@ -735,6 +741,110 @@ static int check_resources() } } /* End loop over Job res */ + + /* Loop over Consoles */ + CONRES *cons; + foreach_res(cons, R_CONSOLE) { + /* tls_require implies tls_enable */ + if (cons->tls_require) { + if (have_tls) { + cons->tls_enable = true; + } else { + Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n")); + OK = false; + continue; + } + } + + if (!cons->tls_certfile && cons->tls_enable) { + Jmsg(NULL, M_FATAL, 0, _("\"TLS Certificate\" file not defined for Console \"%s\" in %s.\n"), + cons->name(), configfile); + OK = false; + } + + if (!cons->tls_keyfile && cons->tls_enable) { + Jmsg(NULL, M_FATAL, 0, _("\"TLS Key\" file not defined for Console \"%s\" in %s.\n"), + cons->name(), configfile); + OK = false; + } + + if ((!cons->tls_ca_certfile && !cons->tls_ca_certdir) && cons->tls_enable && cons->tls_verify_peer) { + Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\" or \"TLS CA" + " Certificate Dir\" are defined for Console \"%s\" in %s." + " At least one CA certificate store is required" + " when using \"TLS Verify Peer\".\n"), + cons->name(), configfile); + OK = false; + } + /* If everything is well, attempt to initialize our per-resource TLS context */ + if (OK && (cons->tls_enable || cons->tls_require)) { + /* Initialize TLS context: + * Args: CA certfile, CA certdir, Certfile, Keyfile, + * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */ + cons->tls_ctx = new_tls_context(cons->tls_ca_certfile, + cons->tls_ca_certdir, cons->tls_certfile, + cons->tls_keyfile, NULL, NULL, cons->tls_dhfile, cons->tls_verify_peer); + + if (!cons->tls_ctx) { + Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for File daemon \"%s\" in %s.\n"), + cons->name(), configfile); + OK = false; + } + } + + } + + /* Loop over Clients */ + CLIENT *client; + foreach_res(client, R_CLIENT) { + /* tls_require implies tls_enable */ + if (client->tls_require) { + if (have_tls) { + client->tls_enable = true; + } else { + Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n")); + OK = false; + continue; + } + } + + if ((!client->tls_ca_certfile && !client->tls_ca_certdir) && client->tls_enable) { + Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\"" + " or \"TLS CA Certificate Dir\" are defined for File daemon \"%s\" in %s.\n"), + client->name(), configfile); + OK = false; + } + + /* If everything is well, attempt to initialize our per-resource TLS context */ + if (OK && (client->tls_enable || client->tls_require)) { + /* Initialize TLS context: + * Args: CA certfile, CA certdir, Certfile, Keyfile, + * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */ + client->tls_ctx = new_tls_context(client->tls_ca_certfile, + client->tls_ca_certdir, client->tls_certfile, + client->tls_keyfile, NULL, NULL, NULL, + true); + + if (!client->tls_ctx) { + Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for File daemon \"%s\" in %s.\n"), + client->name(), configfile); + OK = false; + } + } + } + + UnlockRes(); + if (OK) { + close_msg(NULL); /* close temp message handler */ + init_msg(NULL, director->messages); /* open daemon message handler */ + } + return OK; +} + +static bool check_catalog() +{ + bool OK = true; + /* Loop over databases */ CAT *catalog; foreach_res(catalog, R_CATALOG) { @@ -765,7 +875,7 @@ static int check_resources() /* Loop over all pools for updating RecyclePool */ foreach_res(pool, R_POOL) { - update_pool_recyclepool(NULL, db, pool); + update_pool_recyclepool(NULL, db, pool); } STORE *store; @@ -849,102 +959,5 @@ static int check_resources() } db_close_database(NULL, db); } - - /* Loop over Consoles */ - CONRES *cons; - foreach_res(cons, R_CONSOLE) { - /* tls_require implies tls_enable */ - if (cons->tls_require) { - if (have_tls) { - cons->tls_enable = true; - } else { - Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n")); - OK = false; - continue; - } - } - - if (!cons->tls_certfile && cons->tls_enable) { - Jmsg(NULL, M_FATAL, 0, _("\"TLS Certificate\" file not defined for Console \"%s\" in %s.\n"), - cons->name(), configfile); - OK = false; - } - - if (!cons->tls_keyfile && cons->tls_enable) { - Jmsg(NULL, M_FATAL, 0, _("\"TLS Key\" file not defined for Console \"%s\" in %s.\n"), - cons->name(), configfile); - OK = false; - } - - if ((!cons->tls_ca_certfile && !cons->tls_ca_certdir) && cons->tls_enable && cons->tls_verify_peer) { - Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\" or \"TLS CA" - " Certificate Dir\" are defined for Console \"%s\" in %s." - " At least one CA certificate store is required" - " when using \"TLS Verify Peer\".\n"), - cons->name(), configfile); - OK = false; - } - /* If everything is well, attempt to initialize our per-resource TLS context */ - if (OK && (cons->tls_enable || cons->tls_require)) { - /* Initialize TLS context: - * Args: CA certfile, CA certdir, Certfile, Keyfile, - * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */ - cons->tls_ctx = new_tls_context(cons->tls_ca_certfile, - cons->tls_ca_certdir, cons->tls_certfile, - cons->tls_keyfile, NULL, NULL, cons->tls_dhfile, cons->tls_verify_peer); - - if (!cons->tls_ctx) { - Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for File daemon \"%s\" in %s.\n"), - cons->name(), configfile); - OK = false; - } - } - - } - - /* Loop over Clients */ - CLIENT *client; - foreach_res(client, R_CLIENT) { - /* tls_require implies tls_enable */ - if (client->tls_require) { - if (have_tls) { - client->tls_enable = true; - } else { - Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n")); - OK = false; - continue; - } - } - - if ((!client->tls_ca_certfile && !client->tls_ca_certdir) && client->tls_enable) { - Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\"" - " or \"TLS CA Certificate Dir\" are defined for File daemon \"%s\" in %s.\n"), - client->name(), configfile); - OK = false; - } - - /* If everything is well, attempt to initialize our per-resource TLS context */ - if (OK && (client->tls_enable || client->tls_require)) { - /* Initialize TLS context: - * Args: CA certfile, CA certdir, Certfile, Keyfile, - * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */ - client->tls_ctx = new_tls_context(client->tls_ca_certfile, - client->tls_ca_certdir, client->tls_certfile, - client->tls_keyfile, NULL, NULL, NULL, - true); - - if (!client->tls_ctx) { - Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for File daemon \"%s\" in %s.\n"), - client->name(), configfile); - OK = false; - } - } - } - - UnlockRes(); - if (OK) { - close_msg(NULL); /* close temp message handler */ - init_msg(NULL, director->messages); /* open daemon message handler */ - } return OK; } diff --git a/bacula/src/dird/job.c b/bacula/src/dird/job.c index b158ce2d1f..0df9407104 100644 --- a/bacula/src/dird/job.c +++ b/bacula/src/dird/job.c @@ -481,7 +481,6 @@ static void job_monitor_watchdog(watchdog_t *self) static bool job_check_maxwaittime(JCR *control_jcr, JCR *jcr) { bool cancel = false; - bool ok_to_cancel = false; JOB *job = jcr->job; if (job_canceled(jcr)) { @@ -493,69 +492,18 @@ static bool job_check_maxwaittime(JCR *control_jcr, JCR *jcr) } if (jcr->JobLevel == L_FULL && job->FullMaxWaitTime != 0 && (watchdog_time - jcr->start_time) >= job->FullMaxWaitTime) { - ok_to_cancel = true; + cancel = true; } else if (jcr->JobLevel == L_DIFFERENTIAL && job->DiffMaxWaitTime != 0 && (watchdog_time - jcr->start_time) >= job->DiffMaxWaitTime) { - ok_to_cancel = true; + cancel = true; } else if (jcr->JobLevel == L_INCREMENTAL && job->IncMaxWaitTime != 0 && (watchdog_time - jcr->start_time) >= job->IncMaxWaitTime) { - ok_to_cancel = true; + cancel = true; } else if (job->MaxWaitTime != 0 && (watchdog_time - jcr->start_time) >= job->MaxWaitTime) { - ok_to_cancel = true; - } - if (!ok_to_cancel) { - return false; - } - -/* - * I don't see the need for all this -- kes 17Dec06 - */ -#ifdef xxx - Dmsg3(800, "Job %d (%s): MaxWaitTime of %d seconds exceeded, " - "checking status\n", - jcr->JobId, jcr->Job, job->MaxWaitTime); - switch (jcr->JobStatus) { - case JS_Created: - case JS_Blocked: - case JS_WaitFD: - case JS_WaitSD: - case JS_WaitStoreRes: - case JS_WaitClientRes: - case JS_WaitJobRes: - case JS_WaitPriority: - case JS_WaitMaxJobs: - case JS_WaitStartTime: cancel = true; - Dmsg0(200, "JCR blocked in #1\n"); - break; - case JS_Running: - Dmsg0(800, "JCR running, checking SD status\n"); - switch (jcr->SDJobStatus) { - case JS_WaitMount: - case JS_WaitMedia: - case JS_WaitFD: - cancel = true; - Dmsg0(800, "JCR blocked in #2\n"); - break; - default: - Dmsg0(800, "JCR not blocked in #2\n"); - break; - } - break; - case JS_Terminated: - case JS_ErrorTerminated: - case JS_Canceled: - case JS_FatalError: - Dmsg0(800, "JCR already dead in #3\n"); - break; - default: - Jmsg1(jcr, M_ERROR, 0, _("Unhandled job status code %d\n"), - jcr->JobStatus); } - Dmsg3(800, "MaxWaitTime result: %scancel JCR %p (%s)\n", - cancel ? "" : "do not ", jcr, jcr->Job); -#endif + return cancel; } @@ -574,36 +522,6 @@ static bool job_check_maxruntime(JCR *control_jcr, JCR *jcr) return false; } -#ifdef xxx - switch (jcr->JobStatus) { - case JS_Created: - case JS_Running: - case JS_Blocked: - case JS_WaitFD: - case JS_WaitSD: - case JS_WaitStoreRes: - case JS_WaitClientRes: - case JS_WaitJobRes: - case JS_WaitPriority: - case JS_WaitMaxJobs: - case JS_WaitStartTime: - case JS_Differences: - cancel = true; - break; - case JS_Terminated: - case JS_ErrorTerminated: - case JS_Canceled: - case JS_FatalError: - cancel = false; - break; - default: - Jmsg1(jcr, M_ERROR, 0, _("Unhandled job status code %d\n"), - jcr->JobStatus); - } - - Dmsg3(200, "MaxRunTime result: %scancel JCR %p (%s)\n", - cancel ? "" : "do not ", jcr, jcr->Job); -#endif return true; } diff --git a/bacula/src/filed/backup.c b/bacula/src/filed/backup.c index a4b9d74d4b..f218f52f15 100644 --- a/bacula/src/filed/backup.c +++ b/bacula/src/filed/backup.c @@ -211,6 +211,7 @@ bool blast_data_to_storage_daemon(JCR *jcr, char *addr) */ static int save_file(FF_PKT *ff_pkt, void *vjcr, bool top_level) { + bool do_read = false; int stat, data_stream; int rtnstat = 0; DIGEST *digest = NULL; @@ -406,7 +407,6 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr, bool top_level) * Note, if is_win32_backup, we must open the Directory so that * the BackupRead will save its permissions and ownership streams. */ - bool do_read = false; if (ff_pkt->type != FT_LNKSAVED && S_ISREG(ff_pkt->statp.st_mode)) { #ifdef HAVE_WIN32 diff --git a/bacula/src/lib/bnet.c b/bacula/src/lib/bnet.c index 7dc1f143fb..2fc92200f5 100644 --- a/bacula/src/lib/bnet.c +++ b/bacula/src/lib/bnet.c @@ -751,13 +751,15 @@ static BSOCK *bnet_open(JCR * jcr, const char *name, char *host, char *service, /* * Try to connect to host for max_retry_time at retry_time intervals. */ -BSOCK *bnet_connect(JCR * jcr, int retry_interval, int max_retry_time, +BSOCK *bnet_connect(JCR * jcr, int retry_interval, utime_t max_retry_time, const char *name, char *host, char *service, int port, int verbose) { int i; BSOCK *bsock; int fatal = 0; + time_t begin_time = time(NULL); + time_t now; for (i = 0; (bsock = bnet_open(jcr, name, host, service, port, &fatal)) == NULL; i -= retry_interval) { @@ -775,8 +777,8 @@ BSOCK *bnet_connect(JCR * jcr, int retry_interval, int max_retry_time, "Retrying ...\n"), name, host, port, be.strerror()); } bmicrosleep(retry_interval, 0); - max_retry_time -= retry_interval; - if (max_retry_time <= 0) { + now = time(NULL); + if (begin_time + max_retry_time <= now) { Qmsg4(jcr, M_FATAL, 0, _("Unable to connect to %s on %s:%d. ERR=%s\n"), name, host, port, be.strerror()); return NULL; diff --git a/bacula/src/lib/bsock.h b/bacula/src/lib/bsock.h index 2168ffa5d1..addace2b72 100644 --- a/bacula/src/lib/bsock.h +++ b/bacula/src/lib/bsock.h @@ -87,7 +87,6 @@ public: char *host() { return m_host; }; int port() { return m_port; }; JCR *jcr() { return m_jcr; }; - }; /* diff --git a/bacula/src/lib/bsys.c b/bacula/src/lib/bsys.c index 975811ad73..b869d51d1c 100644 --- a/bacula/src/lib/bsys.c +++ b/bacula/src/lib/bsys.c @@ -467,8 +467,18 @@ void create_pid_file(char *dir, const char *progname, int port) sscanf(pidbuf, "%d", &oldpid) != 1) { Emsg2(M_ERROR_TERM, 0, _("Cannot open pid file. %s ERR=%s\n"), fname, strerror(errno)); } - /* See if other Bacula is still alive */ - if (kill(oldpid, 0) != -1 || errno != ESRCH) { + /* Some OSes (IRIX) don't bother to clean out the old pid files after a crash, and + * since they use a deterministic algorithm for assigning PIDs, we can have + * pid conflicts with the old PID file after a reboot. + * The intent the following code is to check if the oldpid read from the pid + * file is the same as the currently executing process's pid, + * and if oldpid == getpid(), skip the attempt to + * kill(oldpid,0), since the attempt is guaranteed to succeed, + * but the success won't actually mean that there is an + * another Bacula process already running. + * For more details see bug #797. + */ + if ((oldpid != (int)getpid()) && (kill(oldpid, 0) != -1 || errno != ESRCH)) { Emsg3(M_ERROR_TERM, 0, _("%s is already running. pid=%d\nCheck file %s\n"), progname, oldpid, fname); } diff --git a/bacula/src/lib/protos.h b/bacula/src/lib/protos.h index 863b8539e0..7dab6cb52b 100644 --- a/bacula/src/lib/protos.h +++ b/bacula/src/lib/protos.h @@ -87,7 +87,7 @@ bool bnet_tls_server (TLS_CONTEXT *ctx, BSOCK *bsock, alist *verify_list); bool bnet_tls_client (TLS_CONTEXT *ctx, BSOCK *bsock); BSOCK * bnet_connect (JCR *jcr, int retry_interval, - int max_retry_time, const char *name, char *host, char *service, + utime_t max_retry_time, const char *name, char *host, char *service, int port, int verbose); void bnet_close (BSOCK *bsock); BSOCK * init_bsock (JCR *jcr, int sockfd, const char *who, const char *ip, diff --git a/bacula/src/stored/acquire.c b/bacula/src/stored/acquire.c index ab6f6f20c4..c1b791ee3d 100644 --- a/bacula/src/stored/acquire.c +++ b/bacula/src/stored/acquire.c @@ -281,13 +281,13 @@ default_path: dcr->VolumeName, dev->print_name()); get_out: - P(dev->mutex); + dev->lock(); if (dcr->reserved_device) { dev->reserved_device--; Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name()); dcr->reserved_device = false; } - V(dev->mutex); + dev->unlock(); dev->unblock(); Dmsg1(50, "jcr->dcr=%p\n", jcr->dcr); return ok; @@ -408,13 +408,13 @@ DCR *acquire_device_for_append(DCR *dcr) } dev->VolCatInfo.VolCatJobs++; /* increment number of jobs on vol */ dir_update_volume_info(dcr, false); /* send Volume info to Director */ - P(dev->mutex); + dev->lock(); if (dcr->reserved_device) { dev->reserved_device--; Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name()); dcr->reserved_device = false; } - V(dev->mutex); + dev->unlock(); dev->unblock(); return dcr; @@ -422,13 +422,13 @@ DCR *acquire_device_for_append(DCR *dcr) * Error return */ get_out: - P(dev->mutex); + dev->lock(); if (dcr->reserved_device) { dev->reserved_device--; Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name()); dcr->reserved_device = false; } - V(dev->mutex); + dev->unlock(); dev->unblock(); return NULL; } diff --git a/bacula/src/stored/askdir.c b/bacula/src/stored/askdir.c index e28c7b3bfa..dbc2b8fe2e 100644 --- a/bacula/src/stored/askdir.c +++ b/bacula/src/stored/askdir.c @@ -459,7 +459,7 @@ bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) bool got_vol = false; Dmsg0(400, "enter dir_ask_sysop_to_create_appendable_volume\n"); - ASSERT(dev->dev_blocked); + ASSERT(dev->blocked()); for ( ;; ) { if (job_canceled(jcr)) { Mmsg(dev->errmsg, @@ -468,9 +468,9 @@ bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) Jmsg(jcr, M_INFO, 0, "%s", dev->errmsg); return false; } - P(dev->mutex); + dev->lock(); got_vol = dir_find_next_appendable_volume(dcr); /* get suggested volume */ - V(dev->mutex); + dev->unlock(); if (got_vol) { return true; } else { @@ -545,7 +545,7 @@ bool dir_ask_sysop_to_mount_volume(DCR *dcr) Mmsg0(dev->errmsg, _("Cannot request another volume: no volume name given.\n")); return false; } - ASSERT(dev->dev_blocked); + ASSERT(dev->blocked()); for ( ;; ) { if (job_canceled(jcr)) { Mmsg(dev->errmsg, _("Job %s canceled while waiting for mount on Storage Device %s.\n"), diff --git a/bacula/src/stored/autochanger.c b/bacula/src/stored/autochanger.c index afa7ed8464..977ff5706c 100644 --- a/bacula/src/stored/autochanger.c +++ b/bacula/src/stored/autochanger.c @@ -414,14 +414,14 @@ static bool unload_other_drive(DCR *dcr, int slot) } break; } - P(dev->mutex); + dev->lock(); if (dev->is_busy()) { Jmsg(jcr, M_WARNING, 0, _("Volume \"%s\" is in use by device %s\n"), dcr->VolumeName, dev->print_name()); Dmsg4(100, "Vol %s for dev=%s is busy dev=%s slot=%d\n", dcr->VolumeName, dcr->dev->print_name(), dev->print_name(), slot); Dmsg2(100, "num_writ=%d reserv=%d\n", dev->num_writers, dev->reserved_device); - V(dev->mutex); + dev->unlock(); return false; } @@ -463,7 +463,7 @@ static bool unload_other_drive(DCR *dcr, int slot) Dmsg0(100, "Slot unloaded\n"); } unlock_changer(dcr); - V(dev->mutex); + dev->unlock(); free_pool_memory(changer_cmd); return ok; } diff --git a/bacula/src/stored/dev.c b/bacula/src/stored/dev.c index 7a57709b5b..47d8e6741f 100644 --- a/bacula/src/stored/dev.c +++ b/bacula/src/stored/dev.c @@ -218,7 +218,7 @@ init_dev(JCR *jcr, DEVRES *device) dev->errmsg = get_pool_memory(PM_EMSG); *dev->errmsg = 0; - if ((errstat = pthread_mutex_init(&dev->mutex, NULL)) != 0) { + if ((errstat = pthread_mutex_init(&dev->m_mutex, NULL)) != 0) { berrno be; dev->dev_errno = errstat; Mmsg1(dev->errmsg, _("Unable to init mutex: ERR=%s\n"), be.strerror(errstat)); @@ -242,12 +242,14 @@ init_dev(JCR *jcr, DEVRES *device) Mmsg1(dev->errmsg, _("Unable to init mutex: ERR=%s\n"), be.strerror(errstat)); Jmsg0(jcr, M_ERROR_TERM, 0, dev->errmsg); } +#ifdef xxx if ((errstat = rwl_init(&dev->lock)) != 0) { berrno be; dev->dev_errno = errstat; Mmsg1(dev->errmsg, _("Unable to init mutex: ERR=%s\n"), be.strerror(errstat)); Jmsg0(jcr, M_ERROR_TERM, 0, dev->errmsg); } +#endif dev->clear_opened(); dev->attached_dcrs = New(dlist(dcr, &dcr->dev_link)); @@ -782,19 +784,19 @@ void DEVICE::block(int why) { lock_device(this); block_device(this, why); - V(mutex); + unlock(); } void DEVICE::unblock() { - P(mutex); + lock(); unblock_device(this); - V(mutex); + unlock(); } const char *DEVICE::print_blocked() const { - switch (dev_blocked) { + switch (m_blocked) { case BST_NOT_BLOCKED: return "BST_NOT_BLOCKED"; case BST_UNMOUNTED: @@ -2283,11 +2285,11 @@ void DEVICE::term(void) free_pool_memory(errmsg); errmsg = NULL; } - pthread_mutex_destroy(&mutex); + pthread_mutex_destroy(&m_mutex); pthread_cond_destroy(&wait); pthread_cond_destroy(&wait_next_vol); pthread_mutex_destroy(&spool_mutex); - rwl_destroy(&lock); +// rwl_destroy(&lock); if (attached_dcrs) { delete attached_dcrs; attached_dcrs = NULL; diff --git a/bacula/src/stored/dev.h b/bacula/src/stored/dev.h index 0638e55a1c..37a9418f18 100644 --- a/bacula/src/stored/dev.h +++ b/bacula/src/stored/dev.h @@ -1,16 +1,7 @@ -/* - * Definitions for using the Device functions in Bacula - * Tape and File storage access - * - * Kern Sibbald, MM - * - * Version $Id$ - * - */ /* Bacula® - The Network Backup Solution - Copyright (C) 2000-2006 Free Software Foundation Europe e.V. + Copyright (C) 2000-2007 Free Software Foundation Europe e.V. The main author of Bacula is Kern Sibbald, with contributions from many others, a complete list can be found in the file AUTHORS. @@ -34,6 +25,15 @@ (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, Switzerland, email:ftf@fsfeurope.org. */ +/* + * Definitions for using the Device functions in Bacula + * Tape and File storage access + * + * Kern Sibbald, MM + * + * Version $Id$ + * + */ #ifndef __DEV_H @@ -144,7 +144,7 @@ enum { #define ST_PART_SPOOLED (1<<18) /* spooling part */ #define ST_FREESPACE_OK (1<<19) /* Have valid freespace for DVD */ -/* dev_blocked states (mutually exclusive) */ +/* m_blocked states (mutually exclusive) */ enum { BST_NOT_BLOCKED = 0, /* not blocked */ BST_UNMOUNTED, /* User unmounted device */ @@ -204,21 +204,21 @@ class DCR; /* forward reference */ class DEVICE { private: int m_fd; /* file descriptor */ + int m_blocked; /* set if we must wait (i.e. change tape) */ public: dlist *attached_dcrs; /* attached DCR list */ - pthread_mutex_t mutex; /* access control */ + pthread_mutex_t m_mutex; /* access control */ pthread_mutex_t spool_mutex; /* mutex for updating spool_size */ 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 reserved_device; /* number of device reservations */ /* New access control in process of being implemented */ - brwlock_t lock; /* New mutual exclusion lock */ +// brwlock_t xlock; /* New mutual exclusion lock */ int capabilities; /* capabilities mask */ int state; /* state mask */ @@ -324,14 +324,14 @@ public: int can_write() const { return is_open() && can_append() && is_labeled() && !at_weot(); } int can_read() const { return state & ST_READ; } - bool can_steal_lock() const { return dev_blocked && - (dev_blocked == BST_UNMOUNTED || - dev_blocked == BST_WAITING_FOR_SYSOP || - dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP); }; + bool can_steal_lock() const { return m_blocked && + (m_blocked == BST_UNMOUNTED || + m_blocked == BST_WAITING_FOR_SYSOP || + m_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP); }; bool waiting_for_mount() const { return - (dev_blocked == BST_UNMOUNTED || - dev_blocked == BST_WAITING_FOR_SYSOP || - dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP); }; + (m_blocked == BST_UNMOUNTED || + m_blocked == BST_WAITING_FOR_SYSOP || + m_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP); }; const char *strerror() const; const char *archive_name() const; const char *name() const; @@ -366,6 +366,8 @@ public: void clear_freespace_ok() { state &= ~ST_FREESPACE_OK; }; char *bstrerror(void) { return errmsg; }; char *print_errmsg() { return errmsg; }; + void lock() { P(m_mutex); } + void unlock() { V(m_mutex); } void block(int why); /* in dev.c */ void unblock(); /* in dev.c */ @@ -397,12 +399,12 @@ public: bool update_pos(DCR *dcr); /* in dev.c */ bool update_freespace(); /* in dvd.c */ - void set_blocked(int block) { dev_blocked = block; }; - int get_blocked() const { return dev_blocked; }; + void set_blocked(int block) { m_blocked = block; }; + int blocked() const { return m_blocked; }; uint32_t get_file() const { return file; }; uint32_t get_block() const { return block_num; }; const char *print_blocked() const; /* in dev.c */ - bool is_blocked() const { return dev_blocked != BST_NOT_BLOCKED; }; + bool is_blocked() const { return m_blocked != BST_NOT_BLOCKED; }; int fd() const { return m_fd; }; private: diff --git a/bacula/src/stored/device.c b/bacula/src/stored/device.c index b70902ef00..810b3da170 100644 --- a/bacula/src/stored/device.c +++ b/bacula/src/stored/device.c @@ -1,3 +1,30 @@ +/* + Bacula® - The Network Backup Solution + + Copyright (C) 2000-2007 Free Software Foundation Europe e.V. + + The main author of Bacula is Kern Sibbald, with contributions from + many others, a complete list can be found in the file AUTHORS. + This program is Free Software; you can redistribute it and/or + modify it under the terms of version two of the GNU General Public + License as published by the Free Software Foundation plus additions + that are listed in the file LICENSE. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. + + Bacula® is a registered trademark of John Walker. + The licensor of Bacula is the Free Software Foundation Europe + (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, + Switzerland, email:ftf@fsfeurope.org. +*/ /* * * Higher Level Device routines. @@ -28,33 +55,6 @@ * * Version $Id$ */ -/* - Bacula® - The Network Backup Solution - - Copyright (C) 2000-2006 Free Software Foundation Europe e.V. - - The main author of Bacula is Kern Sibbald, with contributions from - many others, a complete list can be found in the file AUTHORS. - This program is Free Software; you can redistribute it and/or - modify it under the terms of version two of the GNU General Public - License as published by the Free Software Foundation plus additions - that are listed in the file LICENSE. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. - - Bacula® is a registered trademark of John Walker. - The licensor of Bacula is the Free Software Foundation Europe - (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, - Switzerland, email:ftf@fsfeurope.org. -*/ #include "bacula.h" /* pull in global headers */ #include "stored.h" /* pull in Storage Deamon headers */ @@ -116,11 +116,11 @@ bool fixup_device_block_write_error(DCR *dcr) if (!mount_next_write_volume(dcr, 1)) { free_block(label_blk); dcr->block = block; - P(dev->mutex); + dev->lock(); unblock_device(dev); return false; /* device locked */ } - P(dev->mutex); /* lock again */ + dev->lock(); /* lock again */ dev->VolCatInfo.VolCatJobs++; /* increment number of jobs on vol */ dir_update_volume_info(dcr, false); /* send Volume info to Director */ @@ -318,6 +318,7 @@ bool open_device(DCR *dcr) +#ifdef xxx void dev_lock(DEVICE *dev) { int errstat; @@ -333,6 +334,7 @@ void dev_unlock(DEVICE *dev) Emsg1(M_ABORT, 0, _("Device write unlock failure. ERR=%s\n"), strerror(errstat)); } } +#endif /* * When dev_blocked is set, all threads EXCEPT thread with id no_wait_id @@ -342,13 +344,13 @@ void dev_unlock(DEVICE *dev) void _lock_device(const char *file, int line, DEVICE *dev) { int stat; - Dmsg3(500, "lock %d from %s:%d\n", dev->dev_blocked, file, line); - P(dev->mutex); - if (dev->dev_blocked && !pthread_equal(dev->no_wait_id, pthread_self())) { + Dmsg3(500, "lock %d from %s:%d\n", dev->blocked(), file, line); + dev->lock(); + if (dev->blocked() && !pthread_equal(dev->no_wait_id, pthread_self())) { dev->num_waiting++; /* indicate that I am waiting */ - while (dev->dev_blocked) { - if ((stat = pthread_cond_wait(&dev->wait, &dev->mutex)) != 0) { - V(dev->mutex); + while (dev->blocked()) { + if ((stat = pthread_cond_wait(&dev->wait, &dev->m_mutex)) != 0) { + dev->unlock(); Emsg1(M_ABORT, 0, _("pthread_cond_wait failure. ERR=%s\n"), strerror(stat)); } @@ -363,7 +365,7 @@ void _lock_device(const char *file, int line, DEVICE *dev) bool is_device_unmounted(DEVICE *dev) { bool stat; - int blocked = dev->dev_blocked; + int blocked = dev->blocked(); stat = (blocked == BST_UNMOUNTED) || (blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP); return stat; @@ -372,7 +374,7 @@ bool is_device_unmounted(DEVICE *dev) void _unlock_device(const char *file, int line, DEVICE *dev) { Dmsg2(500, "unlock from %s:%d\n", file, line); - V(dev->mutex); + dev->unlock(); } /* @@ -386,20 +388,18 @@ void _unlock_device(const char *file, int line, DEVICE *dev) void _block_device(const char *file, int line, DEVICE *dev, int state) { Dmsg3(500, "block set %d from %s:%d\n", state, file, line); - ASSERT(dev->get_blocked() == BST_NOT_BLOCKED); + ASSERT(dev->blocked() == BST_NOT_BLOCKED); dev->set_blocked(state); /* make other threads wait */ dev->no_wait_id = pthread_self(); /* allow us to continue */ } - - /* * Unblock the device, and wake up anyone who went to sleep. */ void _unblock_device(const char *file, int line, DEVICE *dev) { Dmsg3(500, "unblock %s from %s:%d\n", dev->print_blocked(), file, line); - ASSERT(dev->dev_blocked); + ASSERT(dev->blocked()); dev->set_blocked(BST_NOT_BLOCKED); dev->no_wait_id = 0; if (dev->num_waiting > 0) { @@ -416,13 +416,13 @@ void _steal_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t * Dmsg3(400, "steal lock. old=%s from %s:%d\n", dev->print_blocked(), file, line); - hold->dev_blocked = dev->get_blocked(); + hold->dev_blocked = dev->blocked(); hold->dev_prev_blocked = dev->dev_prev_blocked; hold->no_wait_id = dev->no_wait_id; dev->set_blocked(state); Dmsg1(400, "steal lock. new=%s\n", dev->print_blocked()); dev->no_wait_id = pthread_self(); - V(dev->mutex); + dev->unlock(); } /* @@ -433,8 +433,8 @@ void _give_back_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock { Dmsg3(400, "return lock. old=%s from %s:%d\n", dev->print_blocked(), file, line); - P(dev->mutex); - dev->dev_blocked = hold->dev_blocked; + dev->lock(); + dev->set_blocked(hold->dev_blocked); dev->dev_prev_blocked = hold->dev_prev_blocked; dev->no_wait_id = hold->no_wait_id; Dmsg1(400, "return lock. new=%s\n", dev->print_blocked()); diff --git a/bacula/src/stored/dircmd.c b/bacula/src/stored/dircmd.c index 639b2148c8..72e239049e 100644 --- a/bacula/src/stored/dircmd.c +++ b/bacula/src/stored/dircmd.c @@ -22,7 +22,7 @@ /* Bacula® - The Network Backup Solution - Copyright (C) 2001-2006 Free Software Foundation Europe e.V. + Copyright (C) 2001-2007 Free Software Foundation Europe e.V. The main author of Bacula is Kern Sibbald, with contributions from many others, a complete list can be found in the file AUTHORS. @@ -46,6 +46,27 @@ (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, Switzerland, email:ftf@fsfeurope.org. */ +/* + * This file handles accepting Director Commands + * + * Most Director commands are handled here, with the + * exception of the Job command command and subsequent + * subcommands that are handled + * in job.c. + * + * N.B. in this file, in general we must use P(dev->mutex) rather + * than lock_device(dev) so that we can examine the blocked + * state rather than blocking ourselves because a Job + * thread has the device blocked. In some "safe" cases, + * we can do things to a blocked device. CAREFUL!!!! + * + * File daemon commands are handled in fdcmd.c + * + * Kern Sibbald, May MMI + * + * Version $Id$ + * + */ #include "bacula.h" #include "stored.h" @@ -148,7 +169,7 @@ void *handle_connection_request(void *arg) int bnet_stat = 0; char name[MAX_NAME_LENGTH]; - if (bnet_recv(bs) <= 0) { + if (bs->recv() <= 0) { Emsg0(M_ERROR, 0, _("Connection request failed.\n")); bnet_close(bs); return NULL; @@ -200,7 +221,7 @@ void *handle_connection_request(void *arg) for (quit=false; !quit;) { /* Read command */ - if ((bnet_stat = bnet_recv(bs)) <= 0) { + if ((bnet_stat = bs->recv()) <= 0) { break; /* connection terminated */ } Dmsg1(199, "msg); @@ -214,7 +235,7 @@ void *handle_connection_request(void *arg) if ((!cmds[i].monitoraccess) && (jcr->director->monitor)) { Dmsg1(100, "Command \"%s\" is invalid.\n", cmds[i].cmd); bnet_fsend(bs, invalid_cmd); - bnet_sig(bs, BNET_EOD); + bs->signal(BNET_EOD); break; } Dmsg1(200, "Do command: %s\n", cmds[i].cmd); @@ -355,7 +376,7 @@ static bool do_label(JCR *jcr, int relabel) dcr = find_device(jcr, dev_name, drive); if (dcr) { dev = dcr->dev; - P(dev->mutex); /* Use P to avoid indefinite block */ + dev->lock(); /* Use P to avoid indefinite block */ if (!dev->is_open()) { Dmsg1(400, "Can %slabel. Device is not open\n", relabel?"re":""); label_volume_if_ok(dcr, oldname, newname, poolname, slot, relabel); @@ -370,7 +391,7 @@ static bool do_label(JCR *jcr, int relabel) Dmsg0(400, "Can relabel. device not used\n"); label_volume_if_ok(dcr, oldname, newname, poolname, slot, relabel); } - V(dev->mutex); + dev->unlock(); free_dcr(dcr); jcr->dcr = NULL; } else { @@ -619,13 +640,13 @@ static bool mount_cmd(JCR *jcr) dcr = find_device(jcr, devname, drive); if (dcr) { dev = dcr->dev; - P(dev->mutex); /* Use P to avoid indefinite block */ - Dmsg1(100, "mount cmd blocked=%d\n", dev->dev_blocked); - switch (dev->dev_blocked) { /* device blocked? */ + dev->lock(); /* Use P to avoid indefinite block */ + Dmsg1(100, "mount cmd blocked=%d\n", dev->blocked()); + switch (dev->blocked()) { /* device blocked? */ case BST_WAITING_FOR_SYSOP: /* Someone is waiting, wake him */ Dmsg0(100, "Waiting for mount. Attempting to wake thread\n"); - dev->dev_blocked = BST_MOUNT; + dev->set_blocked(BST_MOUNT); bnet_fsend(dir, "3001 OK mount. Device=%s\n", dev->print_name()); pthread_cond_broadcast(&dev->wait_next_vol); @@ -642,7 +663,7 @@ static bool mount_cmd(JCR *jcr) if (dev->open(dcr, OPEN_READ_ONLY) < 0) { bnet_fsend(dir, _("3901 open device failed: ERR=%s\n"), dev->bstrerror()); - if (dev->dev_blocked == BST_UNMOUNTED) { + if (dev->blocked() == BST_UNMOUNTED) { /* We blocked the device, so unblock it */ Dmsg0(100, "Unmounted. Unblocking device\n"); unblock_device(dev); @@ -650,14 +671,14 @@ static bool mount_cmd(JCR *jcr) break; } read_dev_volume_label(dcr); - if (dev->dev_blocked == BST_UNMOUNTED) { + if (dev->blocked() == BST_UNMOUNTED) { /* We blocked the device, so unblock it */ Dmsg0(100, "Unmounted. Unblocking device\n"); read_label(dcr); /* this should not be necessary */ unblock_device(dev); } else { Dmsg0(100, "Unmounted waiting for mount. Attempting to wake thread\n"); - dev->dev_blocked = BST_MOUNT; + dev->set_blocked(BST_MOUNT); } if (dev->is_labeled()) { bnet_fsend(dir, _("3001 Device %s is mounted with Volume \"%s\"\n"), @@ -723,10 +744,10 @@ static bool mount_cmd(JCR *jcr) break; default: - bnet_fsend(dir, _("3905 Bizarre wait state %d\n"), dev->dev_blocked); + bnet_fsend(dir, _("3905 Bizarre wait state %d\n"), dev->blocked()); break; } - V(dev->mutex); + dev->unlock(); free_dcr(dcr); jcr->dcr = NULL; } else { @@ -755,7 +776,7 @@ static bool unmount_cmd(JCR *jcr) dcr = find_device(jcr, devname, drive); if (dcr) { dev = dcr->dev; - P(dev->mutex); /* Use P to avoid indefinite block */ + dev->lock(); /* Use P to avoid indefinite block */ if (!dev->is_open()) { if (!dev->is_busy()) { unload_autochanger(dcr, -1); @@ -772,9 +793,9 @@ static bool unmount_cmd(JCR *jcr) bnet_fsend(dir, _("3901 Device %s is already unmounted.\n"), dev->print_name()); } - } else if (dev->dev_blocked == BST_WAITING_FOR_SYSOP) { + } else if (dev->blocked() == BST_WAITING_FOR_SYSOP) { Dmsg2(90, "%d waiter dev_block=%d. doing unmount\n", dev->num_waiting, - dev->dev_blocked); + dev->blocked()); if (!unload_autochanger(dcr, -1)) { /* ***FIXME**** what is this ???? */ dev->close(); @@ -782,16 +803,16 @@ static bool unmount_cmd(JCR *jcr) if (dev->is_dvd() && !dev->unmount(0)) { bnet_fsend(dir, _("3907 %s"), dev->bstrerror()); } else { - dev->dev_blocked = BST_UNMOUNTED_WAITING_FOR_SYSOP; + dev->set_blocked(BST_UNMOUNTED_WAITING_FOR_SYSOP); bnet_fsend(dir, _("3001 Device %s unmounted.\n"), dev->print_name()); } - } else if (dev->dev_blocked == BST_DOING_ACQUIRE) { + } else if (dev->blocked() == BST_DOING_ACQUIRE) { bnet_fsend(dir, _("3902 Device %s is busy in acquire.\n"), dev->print_name()); - } else if (dev->dev_blocked == BST_WRITING_LABEL) { + } else if (dev->blocked() == BST_WRITING_LABEL) { bnet_fsend(dir, _("3903 Device %s is being labeled.\n"), dev->print_name()); @@ -805,7 +826,7 @@ static bool unmount_cmd(JCR *jcr) * we simply do it by hand. Gross, but a solution. */ /* block_device(dev, BST_UNMOUNTED); replace with 2 lines below */ - dev->dev_blocked = BST_UNMOUNTED; + dev->set_blocked(BST_UNMOUNTED); dev->no_wait_id = 0; if (!unload_autochanger(dcr, -1)) { dev->close(); @@ -817,7 +838,7 @@ static bool unmount_cmd(JCR *jcr) dev->print_name()); } } - V(dev->mutex); + dev->unlock(); free_dcr(dcr); jcr->dcr = NULL; } else { @@ -851,7 +872,7 @@ static bool release_cmd(JCR *jcr) dcr = find_device(jcr, devname, drive); if (dcr) { dev = dcr->dev; - P(dev->mutex); /* Use P to avoid indefinite block */ + dev->lock(); /* Use P to avoid indefinite block */ if (!dev->is_open()) { if (!dev->is_busy()) { unload_autochanger(dcr, -1); @@ -860,24 +881,24 @@ static bool release_cmd(JCR *jcr) bnet_fsend(dir, _("3921 Device %s already released.\n"), dev->print_name()); - } else if (dev->dev_blocked == BST_WAITING_FOR_SYSOP) { + } else if (dev->blocked() == BST_WAITING_FOR_SYSOP) { Dmsg2(90, "%d waiter dev_block=%d.\n", dev->num_waiting, - dev->dev_blocked); + dev->blocked()); unload_autochanger(dcr, -1); bnet_fsend(dir, _("3922 Device %s waiting for sysop.\n"), dev->print_name()); - } else if (dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP) { + } else if (dev->blocked() == BST_UNMOUNTED_WAITING_FOR_SYSOP) { Dmsg2(90, "%d waiter dev_block=%d. doing unmount\n", dev->num_waiting, - dev->dev_blocked); + dev->blocked()); bnet_fsend(dir, _("3922 Device %s waiting for mount.\n"), dev->print_name()); - } else if (dev->dev_blocked == BST_DOING_ACQUIRE) { + } else if (dev->blocked() == BST_DOING_ACQUIRE) { bnet_fsend(dir, _("3923 Device %s is busy in acquire.\n"), dev->print_name()); - } else if (dev->dev_blocked == BST_WRITING_LABEL) { + } else if (dev->blocked() == BST_WRITING_LABEL) { bnet_fsend(dir, _("3914 Device %s is being labeled.\n"), dev->print_name()); @@ -890,7 +911,7 @@ static bool release_cmd(JCR *jcr) bnet_fsend(dir, _("3022 Device %s released.\n"), dev->print_name()); } - V(dev->mutex); + dev->unlock(); free_dcr(dcr); jcr->dcr = NULL; } else { @@ -942,7 +963,7 @@ static bool changer_cmd(JCR *jcr) dcr = find_device(jcr, devname, -1); if (dcr) { dev = dcr->dev; - P(dev->mutex); /* Use P to avoid indefinite block */ + dev->lock(); /* Use P to avoid indefinite block */ if (!dev->device->changer_res) { bnet_fsend(dir, _("3995 Device %s is not an autochanger.\n"), dev->print_name()); @@ -954,7 +975,7 @@ static bool changer_cmd(JCR *jcr) } else { /* device not being used */ autochanger_cmd(dcr, dir, cmd); } - V(dev->mutex); + dev->unlock(); free_dcr(dcr); jcr->dcr = NULL; } else { @@ -965,7 +986,7 @@ static bool changer_cmd(JCR *jcr) bnet_fsend(dir, _("3908 Error scanning autocharger drives/list/slots command: %s\n"), jcr->errmsg); } - bnet_sig(dir, BNET_EOD); + dir->signal(BNET_EOD); return true; } @@ -986,7 +1007,7 @@ static bool readlabel_cmd(JCR *jcr) dcr = find_device(jcr, devname, drive); if (dcr) { dev = dcr->dev; - P(dev->mutex); /* Use P to avoid indefinite block */ + dev->lock(); /* Use P to avoid indefinite block */ if (!dev->is_open()) { read_volume_label(jcr, dev, Slot); dev->close(); @@ -998,7 +1019,7 @@ static bool readlabel_cmd(JCR *jcr) } else { /* device not being used */ read_volume_label(jcr, dev, Slot); } - V(dev->mutex); + dev->unlock(); free_dcr(dcr); jcr->dcr = NULL; } else { @@ -1008,7 +1029,7 @@ static bool readlabel_cmd(JCR *jcr) pm_strcpy(jcr->errmsg, dir->msg); bnet_fsend(dir, _("3909 Error scanning readlabel command: %s\n"), jcr->errmsg); } - bnet_sig(dir, BNET_EOD); + dir->signal(BNET_EOD); return true; } @@ -1066,7 +1087,7 @@ static bool try_autoload_device(JCR *jcr, int slot, const char *VolName) static void send_dir_busy_message(BSOCK *dir, DEVICE *dev) { if (dev->is_blocked()) { - switch (dev->dev_blocked) { + switch (dev->blocked()) { case BST_UNMOUNTED: bnet_fsend(dir, _("3931 Device %s is BLOCKED. user unmounted.\n"), dev->print_name()); diff --git a/bacula/src/stored/protos.h b/bacula/src/stored/protos.h index 3b8388e7a5..fdeeada249 100644 --- a/bacula/src/stored/protos.h +++ b/bacula/src/stored/protos.h @@ -135,8 +135,6 @@ void _give_back_device_lock(const char *file, int line, DEVICE *dev, bsteal_ void set_new_volume_parameters(DCR *dcr); void set_new_file_parameters(DCR *dcr); bool is_device_unmounted(DEVICE *dev); -void dev_lock(DEVICE *dev); -void dev_unlock(DEVICE *dev); /* From dircmd.c */ void *handle_connection_request(void *arg); diff --git a/bacula/src/stored/reserve.c b/bacula/src/stored/reserve.c index bf1bf3dfe7..866524fb50 100644 --- a/bacula/src/stored/reserve.c +++ b/bacula/src/stored/reserve.c @@ -1,17 +1,7 @@ -/* - * Drive reservation functions for Storage Daemon - * - * Kern Sibbald, MM - * - * Split from job.c and acquire.c June 2005 - * - * Version $Id$ - * - */ /* Bacula® - The Network Backup Solution - Copyright (C) 2000-2006 Free Software Foundation Europe e.V. + Copyright (C) 2000-2007 Free Software Foundation Europe e.V. The main author of Bacula is Kern Sibbald, with contributions from many others, a complete list can be found in the file AUTHORS. @@ -35,6 +25,16 @@ (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, Switzerland, email:ftf@fsfeurope.org. */ +/* + * Drive reservation functions for Storage Daemon + * + * Kern Sibbald, MM + * + * Split from job.c and acquire.c June 2005 + * + * Version $Id$ + * + */ #include "bacula.h" #include "stored.h" @@ -402,7 +402,7 @@ static bool use_storage_cmd(JCR *jcr) store->append = append; /* Now get all devices */ - while (bnet_recv(dir) >= 0) { + while (dir->recv() >= 0) { Dmsg1(100, "msg); ok = sscanf(dir->msg, use_device, dev_name.c_str()) == 1; if (!ok) { @@ -411,7 +411,7 @@ static bool use_storage_cmd(JCR *jcr) unbash_spaces(dev_name); store->device->append(bstrdup(dev_name.c_str())); } - } while (ok && bnet_recv(dir) >= 0); + } while (ok && dir->recv() >= 0); #ifdef DEVELOPER /* This loop is debug code and can be removed */ @@ -779,7 +779,7 @@ static bool reserve_device_for_read(DCR *dcr) /* Get locks in correct order */ unlock_reservations(); - P(dev->mutex); + dev->lock(); lock_reservations(); if (is_device_unmounted(dev)) { @@ -808,7 +808,7 @@ static bool reserve_device_for_read(DCR *dcr) dcr->reserved_device = true; bail_out: - V(dev->mutex); + dev->unlock(); return ok; } @@ -838,7 +838,7 @@ static bool reserve_device_for_append(DCR *dcr, RCTX &rctx) /* Get locks in correct order */ unlock_reservations(); - P(dev->mutex); + dev->lock(); lock_reservations(); /* If device is being read, we cannot write it */ @@ -874,7 +874,7 @@ static bool reserve_device_for_append(DCR *dcr, RCTX &rctx) ok = true; bail_out: - V(dev->mutex); + dev->unlock(); return ok; } diff --git a/bacula/src/stored/status.c b/bacula/src/stored/status.c index 4744840ce6..b671936270 100644 --- a/bacula/src/stored/status.c +++ b/bacula/src/stored/status.c @@ -1,11 +1,3 @@ -/* - * This file handles the status command - * - * Kern Sibbald, May MMIII - * - * Version $Id$ - * - */ /* Bacula® - The Network Backup Solution @@ -33,6 +25,14 @@ (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, Switzerland, email:ftf@fsfeurope.org. */ +/* + * This file handles the status command + * + * Kern Sibbald, May MMIII + * + * Version $Id$ + * + */ #include "bacula.h" #include "stored.h" @@ -217,7 +217,7 @@ static void send_blocked_status(DEVICE *dev, void sendit(const char *msg, int le free_pool_memory(msg); return; } - switch (dev->dev_blocked) { + switch (dev->blocked()) { case BST_UNMOUNTED: len = Mmsg(msg, _(" Device is BLOCKED. User unmounted.\n")); sendit(msg, len, arg); @@ -312,7 +312,7 @@ static void send_blocked_status(DEVICE *dev, void sendit(const char *msg, int le dev->state & ST_MOUNTED ? "" : "!"); sendit(msg, len, arg); - len = Mmsg(msg, _("num_writers=%d block=%d\n\n"), dev->num_writers, dev->dev_blocked); + len = Mmsg(msg, _("num_writers=%d block=%d\n\n"), dev->num_writers, dev->blocked()); sendit(msg, len, arg); len = Mmsg(msg, _("Device parameters:\n")); diff --git a/bacula/src/stored/stored.c b/bacula/src/stored/stored.c index caa53f8a80..290dca1b5b 100644 --- a/bacula/src/stored/stored.c +++ b/bacula/src/stored/stored.c @@ -1,20 +1,7 @@ -/* - * Second generation Storage daemon. - * - * Kern Sibbald, MM - * - * It accepts a number of simple commands from the File daemon - * and acts on them. When a request to append data is made, - * it opens a data channel and accepts data from the - * File daemon. - * - * Version $Id$ - * - */ /* Bacula® - The Network Backup Solution - Copyright (C) 2000-2006 Free Software Foundation Europe e.V. + Copyright (C) 2000-2007 Free Software Foundation Europe e.V. The main author of Bacula is Kern Sibbald, with contributions from many others, a complete list can be found in the file AUTHORS. @@ -38,6 +25,19 @@ (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, Switzerland, email:ftf@fsfeurope.org. */ +/* + * Second generation Storage daemon. + * + * Kern Sibbald, MM + * + * It accepts a number of simple commands from the File daemon + * and acts on them. When a request to append data is made, + * it opens a data channel and accepts data from the + * File daemon. + * + * Version $Id$ + * + */ #include "bacula.h" #include "stored.h" @@ -556,11 +556,11 @@ void terminate_stored(int sig) Dmsg1(100, "term_stored killing JobId=%d\n", jcr->JobId); pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL); /* ***FIXME*** wiffle through all dcrs */ - if (jcr->dcr && jcr->dcr->dev && jcr->dcr->dev->dev_blocked) { + if (jcr->dcr && jcr->dcr->dev && jcr->dcr->dev->blocked()) { pthread_cond_broadcast(&jcr->dcr->dev->wait_next_vol); pthread_cond_broadcast(&wait_device_release); } - if (jcr->read_dcr && jcr->read_dcr->dev && jcr->read_dcr->dev->dev_blocked) { + if (jcr->read_dcr && jcr->read_dcr->dev && jcr->read_dcr->dev->blocked()) { pthread_cond_broadcast(&jcr->read_dcr->dev->wait_next_vol); pthread_cond_broadcast(&wait_device_release); } diff --git a/bacula/src/stored/wait.c b/bacula/src/stored/wait.c index c7563c4959..6251a9b4ab 100644 --- a/bacula/src/stored/wait.c +++ b/bacula/src/stored/wait.c @@ -1,17 +1,7 @@ -/* - * Subroutines to handle waiting for operator intervention - * or waiting for a Device to be released - * - * Code for wait_for_sysop() pulled from askdir.c - * - * Kern Sibbald, March 2005 - * - * Version $Id$ - */ /* Bacula® - The Network Backup Solution - Copyright (C) 2000-2006 Free Software Foundation Europe e.V. + Copyright (C) 2000-2007 Free Software Foundation Europe e.V. The main author of Bacula is Kern Sibbald, with contributions from many others, a complete list can be found in the file AUTHORS. @@ -35,6 +25,16 @@ (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, Switzerland, email:ftf@fsfeurope.org. */ +/* + * Subroutines to handle waiting for operator intervention + * or waiting for a Device to be released + * + * Code for wait_for_sysop() pulled from askdir.c + * + * Kern Sibbald, March 2005 + * + * Version $Id$ + */ #include "bacula.h" /* pull in global headers */ @@ -61,7 +61,7 @@ int wait_for_sysop(DCR *dcr) DEVICE *dev = dcr->dev; JCR *jcr = dcr->jcr; - P(dev->mutex); + dev->lock(); Dmsg1(100, "Enter blocked=%s\n", dev->print_blocked()); unmounted = is_device_unmounted(dev); @@ -85,7 +85,7 @@ int wait_for_sysop(DCR *dcr) if (!unmounted) { Dmsg1(400, "blocked=%s\n", dev->print_blocked()); - dev->dev_prev_blocked = dev->dev_blocked; + dev->dev_prev_blocked = dev->blocked(); dev->set_blocked(BST_WAITING_FOR_SYSOP); /* indicate waiting for mount */ } @@ -100,7 +100,7 @@ int wait_for_sysop(DCR *dcr) dev->print_name(), (int)me->heartbeat_interval, dev->wait_sec, add_wait); start = time(NULL); /* Wait required time */ - stat = pthread_cond_timedwait(&dev->wait_next_vol, &dev->mutex, &timeout); + stat = pthread_cond_timedwait(&dev->wait_next_vol, &dev->m_mutex, &timeout); Dmsg2(400, "Wokeup from sleep on device stat=%d blocked=%s\n", stat, dev->print_blocked()); @@ -151,7 +151,7 @@ int wait_for_sysop(DCR *dcr) /* * Check if user mounted the device while we were waiting */ - if (dev->get_blocked() == BST_MOUNT) { /* mount request ? */ + if (dev->blocked() == BST_MOUNT) { /* mount request ? */ stat = W_MOUNT; break; } @@ -184,7 +184,7 @@ int wait_for_sysop(DCR *dcr) Dmsg1(400, "set %s\n", dev->print_blocked()); } Dmsg1(400, "Exit blocked=%s\n", dev->print_blocked()); - V(dev->mutex); + dev->unlock(); return stat; } diff --git a/bacula/src/version.h b/bacula/src/version.h index 4c37357735..206995b9b5 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -4,8 +4,8 @@ #undef VERSION #define VERSION "2.1.5" -#define BDATE "16 March 2007" -#define LSMDATE "16Mar07" +#define BDATE "18 March 2007" +#define LSMDATE "18Mar07" #define PROG_COPYRIGHT "Copyright (C) %d-2007 Free Software Foundation Europe e.V.\n" #define BYEAR "2007" /* year for copyright messages in progs */ @@ -56,7 +56,7 @@ /* Turn on the following flag to enable batch attribute inserts * in the catalog. This gives a large speedup. */ -/* #define HAVE_BATCH_FILE_INSERT 1 */ +#define HAVE_BATCH_FILE_INSERT 1 /* Debug flags not normally turned on */ diff --git a/bacula/technotes-2.1 b/bacula/technotes-2.1 index 366f4675d5..fa94860a6b 100644 --- a/bacula/technotes-2.1 +++ b/bacula/technotes-2.1 @@ -1,6 +1,25 @@ Technical notes on version 2.1 General: +18Mar07 +kes Move the checking of the database in initializion of the Director + to after we drop privileges. This avoids the need for both root + and bacula access to the DB. +kes Correct a misplaced variable definition in src/filed/backup.c +kes Correct how the new batch insert db_create_attributes_record() + uses the arguments. Caused a seg fault in bscan. +kes Implement lock() and unlock() methods in DEVICE class. + Implement block() and set_block(xx) methods in DEVICE class. +kes Modify bnet_connect() so that it uses time() to check for the + wait time expiring (on some OSes, some system calls may not + return immediately). +kes Modify Verify to obtain the previous JobId when it is actually + running rather than at schedule time (as it was in 1.38.x). +kes Fix src/job.c to handle MaxWaitTime correctly. This should + fix bug #802. +kes When checking pid in pid file, continue running if the pid is + the same as ours. This occurs on IRIX after a system crash. + Fixes bug #797. 10Mar07 kes Extend new GUI API. kes Make the ua structure a class, and implement send_msg(), -- 2.39.5