From d14e039674602515d0dc065db5d856f7aea21d43 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Sat, 7 Feb 2004 17:25:23 +0000 Subject: [PATCH] Fix watchdog deadlog + restore soft link bug git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1030 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/ChangeLog | 19 ++ bacula/examples/backup-every-other-week.txt | 16 -- bacula/examples/backup-to-cdwriter.txt | 156 +------------- bacula/examples/upgrade-win32-client.txt | 68 ++++++ bacula/kernstodo | 4 + bacula/src/dird/job.c | 4 +- bacula/src/dird/ua_cmds.c | 15 +- bacula/src/dird/ua_run.c | 16 +- bacula/src/dird/ua_status.c | 7 +- bacula/src/dird/ua_tree.c | 64 +++--- bacula/src/findlib/attribs.c | 5 +- bacula/src/findlib/protos.h | 2 +- bacula/src/jcr.h | 4 + bacula/src/lib/jcr.c | 54 +++-- bacula/src/lib/mem_pool.c | 2 +- bacula/src/lib/tree.c | 13 +- bacula/src/lib/tree.h | 5 +- bacula/src/lib/watchdog.c | 86 +++++--- bacula/src/stored/block.c | 23 +-- bacula/src/stored/btape.c | 10 +- bacula/src/stored/butil.c | 9 +- bacula/src/stored/dev.c | 9 +- bacula/src/stored/device.c | 4 +- bacula/src/stored/dircmd.c | 8 +- bacula/src/stored/protos.h | 218 ++++++++++---------- bacula/src/version.h | 6 +- 26 files changed, 413 insertions(+), 414 deletions(-) create mode 100644 bacula/examples/upgrade-win32-client.txt diff --git a/bacula/ChangeLog b/bacula/ChangeLog index 42f8e45ae1..4e1851b4aa 100644 --- a/bacula/ChangeLog +++ b/bacula/ChangeLog @@ -1,5 +1,24 @@ +07Feb04 +- Added backup to cdwriter script to examples provided by Johan Decock. +- Fixed a bug where ls really did lsmark (just invert command table + entries). +- Fix bug where a soft linked file and a directory had the same name + by treating the soft link as a directory and putting the entries under + it. This fixes the bug reported by Alexander Mueller. +- Fix a deadlock situation in the new watchdog code where the + watchdog locks its semaphore, and attempts to lock the jcr_chain, + but another thread has locked the jcr_chain and wants to free a + watchdog, which tries to lock the watchdog semaphore -- deadlock! + Used read/write locks to solve the problem. +- Improved the error messages when I/O errors or buffer id errors + are detected, and prevent non-sense errors from being printed. +- Fix some incorrect messages in restore if no name is supplied + on the command line (e.g. pool= ). +- Add the third digit to the release version number. +04Feb04 +- Add -l option to bls that causes it to ignore tape label errors. 03Feb04 - Correct problems with jobs scheduled at a later time by hand. Missing unlock(), backward test on pthread_create status. diff --git a/bacula/examples/backup-every-other-week.txt b/bacula/examples/backup-every-other-week.txt index f2f91730ba..b26a456abc 100644 --- a/bacula/examples/backup-every-other-week.txt +++ b/bacula/examples/backup-every-other-week.txt @@ -1,11 +1,7 @@ -From bacula-users-admin@lists.sourceforge.net Wed Aug 13 19:22:21 2003 From: Robert L Mathews To: -Content-Type: text/plain; charset="US-ASCII" -Message-Id: <20030813170422.E48403FC65F@fry.tigertech.net> Subject: [Bacula-users] Making Backups Run Every Other Week -Sender: bacula-users-admin@lists.sourceforge.net Date: Wed, 13 Aug 2003 10:04:23 -0700 In case anyone is interested, here's a tip I came up with. @@ -78,15 +74,3 @@ while before coming up with this. -- Robert L Mathews, Tiger Technologies - - - -------------------------------------------------------- -This SF.Net email sponsored by: Free pre-built ASP.NET sites including -Data Reports, E-commerce, Portals, and Forums are available now. -Download today and enter to win an XBOX or Visual Studio .NET. -http://aspnet.click-url.com/go/psa00100003ave/direct;at.aspnet_072303_01/01 -_______________________________________________ -Bacula-users mailing list -Bacula-users@lists.sourceforge.net -https://lists.sourceforge.net/lists/listinfo/bacula-users diff --git a/bacula/examples/backup-to-cdwriter.txt b/bacula/examples/backup-to-cdwriter.txt index 5d49b1bd0d..c0f85112d0 100644 --- a/bacula/examples/backup-to-cdwriter.txt +++ b/bacula/examples/backup-to-cdwriter.txt @@ -1,68 +1,15 @@ -From bacula-users-admin@lists.sourceforge.net Sat Jan 31 05:42:42 2004 -Return-Path: -Received: from sc8-sf-list2.sourceforge.net (lists.sourceforge.net - [66.35.250.206]) by matou.sibbald.com (8.12.10/8.12.10) with ESMTP id - i0V4ggtH005859 for ; Sat, 31 Jan 2004 05:42:42 +0100 -Received: from localhost ([127.0.0.1] helo=projects.sourceforge.net) by - sc8-sf-list2.sourceforge.net with esmtp (Exim 4.30) id 1Amms2-0004RT-4e; - Fri, 30 Jan 2004 20:36:38 -0800 -Received: from sc8-sf-mx1-b.sourceforge.net ([10.3.1.11] - helo=sc8-sf-mx1.sourceforge.net) by sc8-sf-list2.sourceforge.net with esmtp - (Exim 4.30) id 1Ammo5-0002Tt-2F for bacula-users@lists.sourceforge.net; - Fri, 30 Jan 2004 20:32:33 -0800 -Received: from www.abis.be ([195.0.32.120] helo=xenophon.abis.be) by - sc8-sf-mx1.sourceforge.net with esmtp (Exim 4.30) id 1AmbFN-0008Hu-99 for - bacula-users@lists.sourceforge.net; Fri, 30 Jan 2004 08:11:57 -0800 -Received: from tosfeb32.abis.be ([194.78.5.1]) by xenophon.abis.be - (8.11.6/8.11.6) with SMTP id i0UGBI715849 for - ; Fri, 30 Jan 2004 17:11:18 +0100 -Received: by tosfeb32.abis.be(Lotus SMTP MTA v4.6.5 (863.2 5-20-1999)) id - C1256E2B.0058F4EE ; Fri, 30 Jan 2004 17:11:38 +0100 -X-Lotus-FromDomain: ABIS From: "Johan Decock" To: bacula-users@lists.sourceforge.net -Message-ID: Subject: Re: [Bacula-users] cdwriter -Mime-Version: 1.0 -Content-type: multipart/mixed; Boundary="0__=dQlRuu8umGKzn67woQcbAbtp1kVJLJuYIqUZPSjcX1GgjEHuWdvHDqOX" -Content-Disposition: inline -X-Spam-Score: 1.1 (+) -X-Spam-Report: Spam Filtering performed by sourceforge.net. See - http://spamassassin.org/tag/ for more details. Report problems to - http://sf.net/tracker/?func=add&group_id=1&atid=200001 1.1 - MIME_BASE64_LATIN RAW: Latin alphabet text using base64 encoding -Sender: bacula-users-admin@lists.sourceforge.net -Errors-To: bacula-users-admin@lists.sourceforge.net -X-BeenThere: bacula-users@lists.sourceforge.net -X-Mailman-Version: 2.0.9-sf.net -Precedence: bulk -List-Unsubscribe: - , - -List-Id: Bacula user's email list for support and discussions - -List-Post: -List-Help: -List-Subscribe: - , - -List-Archive: - Date: Fri, 30 Jan 2004 17:11:34 +0100 +I thought it would be easy to find them in the archives. I'll post them +again. I changed some things in them anyway in the mean time. I also +include the Director config. Then you see how they are to be used in +Runbefore- and RunafterJobs ---0__=dQlRuu8umGKzn67woQcbAbtp1kVJLJuYIqUZPSjcX1GgjEHuWdvHDqOX -Content-type: text/plain; charset=us-ascii -Content-Disposition: inline -Content-Transfer-Encoding: 8bit - - - -Hi Alex, - -I thought it would be easy to find them in the archives. I'll post them again. I changed some things in them anyway in the mean time. I also include the Director config. Then you see how they are to be used in Runbefore- and RunafterJobs - -I'm interested in any remarks or improvements you might have. (I'm still getting started in shell scripting) +I'm interested in any remarks or improvements you might have. (I'm +still getting started in shell scripting) # @@ -859,93 +806,8 @@ else echo "hello" fi -# This is run as a RunAfterJob of the catalog backup. It already had a RunAfterJob, so we execute that here -/etc/bacula/delete_catalog_backup - - - - - - -From: "Alex Federau" on 30/01/2004 15:57 GMT - -To: Johan Decock/Abis@Abis -cc: -Subject: Re: [Bacula-users] cdwriter - - - ---0__=dQlRuu8umGKzn67woQcbAbtp1kVJLJuYIqUZPSjcX1GgjEHuWdvHDqOX -Content-type: text/plain; charset=iso-8859-1 -Content-Disposition: inline -Content-Transfer-Encoding: 8bit - - -Hi Johan, -Could you send me the scripts or tell me where they are located. I am -browsing the mail archive, -and while I can find several of your mails, I am unable to find your -scripts. Probably they would be very useful for us. - -Cheers -Alex - - -> -> -> Hi Alex, -> -> Bacula isn't able to write to CD-R or DVD+/-R directly. This isn't needed -> though. If you look in the mailing list archive, you will find that I have -> implemented a solution where the backup volume files are written to DVD+R -> with some bash scripts. A caveat is that files on an ISO9660 can't be -larger -> than 2 GB (Not on Linux anyway). This has kept me busy for a while, -> looking what was going on and why I wasn't able to read back my DVD's. -> -> I hope my scripts are of help to you. -> -> Johan -> -> -> -> -> From: "Alex Federau" on 30/01/2004 14:29 GMT -> -> To: bacula-users@lists.sourceforge.net -> cc: (bcc: Johan Decock/Abis) -> Subject: [Bacula-users] cdwriter -> -> -> - --- -+++ Mailpower für Multimedia-Begeisterte: http://www.gmx.net/topmail +++ -250 MB Mailbox, 1 GB Online-Festplatte, 100 FreeSMS. Jetzt kostenlos testen! - - - - - - - - --------------------------------------------------------------------------- -ABIS Training & Consulting -website: http://www.abis.be - e-mail: training@abis.be -tel: Belgium: (+32)-16-245610 - The Netherlands: (+31)-348-435570 -fax: Belgium: (+32)-16-245691 - The Netherlands: (+31)-348-432493 --------------------------------------------------------------------------- ---0__=dQlRuu8umGKzn67woQcbAbtp1kVJLJuYIqUZPSjcX1GgjEHuWdvHDqOX-- - +# This is run as a RunAfterJob of the catalog backup. It already had a +# RunAfterJob, so we execute that here +/etc/bacula/delete_catalog_backup -------------------------------------------------------- -The SF.Net email is sponsored by EclipseCon 2004 -Premiere Conference on Open Tools Development and Integration -See the breadth of Eclipse activity. February 3-5 in Anaheim, CA. -http://www.eclipsecon.org/osdn -_______________________________________________ -Bacula-users mailing list -Bacula-users@lists.sourceforge.net -https://lists.sourceforge.net/lists/listinfo/bacula-users diff --git a/bacula/examples/upgrade-win32-client.txt b/bacula/examples/upgrade-win32-client.txt new file mode 100644 index 0000000000..3ffe0eff77 --- /dev/null +++ b/bacula/examples/upgrade-win32-client.txt @@ -0,0 +1,68 @@ +From: "Michel Meyers" +To: "bacula-users" +Subject: [Bacula-users] Script for pushing new clients to Windows boxes +Date: Mon, 2 Feb 2004 16:10:48 +0100 + +Hello, + +Some of you may remember my document on how to remotely push a Win32 bacula +client onto a WinNT/2k/XP box. Well, I've written a script to do it for me +and thought I'd share it with you: +- ---------------------------------------------------------------- +#!/bin/bash +# +# Remote Win32 client upgrade script +# written by Michel Meyers (last update 02/02/04 16:10) +# +# WARNING: Make sure that no bacula-fd.conf exists in the source directory! +# You will destroy/overwrite all your client's configs if you don't +# be careful with this. +# +# The upgrade function does the following: +# - Shutdown Bacula service on remote machine +# - Wait 30 seconds (to allow proper shutdown) +# - Mount C: drive of remote box +# - Copy new client to remote machine +# - Unmount C; +# - Startup the new Bacula service +# +# To upgrade a machine append the following at the bottom of this file: +# +# SERVERNAME= +# USERNAME= +# PASSWORD= +# upgrade + +upgrade() { +rpcclient -S $SERVERNAME -U $USERNAME%"$PASSWORD" -c "service stop bacula" +sleep 30 +smbmount //$SERVERNAME/c$ /mnt -o username=$USERNAME,password="$PASSWORD" +cp /home/michel/winbacula/bin/* /mnt/bacula/bin +umount /mnt +rpcclient -S $SERVERNAME -U $USERNAME%"$PASSWORD" -c "service start bacula" +} + +SERVERNAME=xerxes +USERNAME=administrator +PASSWORD=secret +upgrade + +SERVERNAME=shodan +USERNAME=teh_one +PASSWORD="" +upgrade +- ---------------------------------------------------------------- + +It should be pretty self-explanatory. I'm not good at shell programming and +I don't know whether there's any notion of arrays or 'for' loops that could +make it cleaner so I simply wrote a function which references some variables +and then call that repeatedly (once per machine). You can of course change +the values according to your system and liking (if 30 secs seem to much for +you, just reduce the value after sleep, make sure to check on the paths and +mountpoint /mnt may not be usable on your system, ...) + +Note: The requirements are the same as described in my other document +(Samba-TNG clients among others, otherwise you'll be missing rpcclient). + +Enjoy! + diff --git a/bacula/kernstodo b/bacula/kernstodo index 063e0a9af1..d4c627a5ea 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -70,6 +70,10 @@ For 1.33 Testing/Documentation: http://howtos.linux.com/guides/nag2/x-087-2-nfs.mountd.shtml For 1.33 +- Have each daemon save the last_jobs structure when exiting and + read it back in when starting up. +- "restore jobid=1 select" calls get_storage_xxx, which prints "JobId 1 is + not running." - Add FromClient and ToClient keywords on restore command (or BackupClient RestoreClient). - Automatic "update slots" on user configuration directive when a diff --git a/bacula/src/dird/job.c b/bacula/src/dird/job.c index b0f5467f6c..051a540447 100644 --- a/bacula/src/dird/job.c +++ b/bacula/src/dird/job.c @@ -83,13 +83,13 @@ static void job_monitor_watchdog(watchdog_t *self) { JCR *control_jcr, *jcr; - control_jcr = (JCR *) self->data; + control_jcr = (JCR *)self->data; Dmsg1(400, "job_monitor_watchdog %p called\n", self); lock_jcr_chain(); - for (jcr = NULL; (jcr = get_next_jcr(jcr)); /* nothing */) { + foreach_jcr(jcr) { bool cancel; if (jcr->JobId == 0) { diff --git a/bacula/src/dird/ua_cmds.c b/bacula/src/dird/ua_cmds.c index 954ac237f6..1d89432a78 100644 --- a/bacula/src/dird/ua_cmds.c +++ b/bacula/src/dird/ua_cmds.c @@ -388,13 +388,13 @@ static int cancel_cmd(UAContext *ua, char *cmd) if (!jcr) { /* Count Jobs running */ lock_jcr_chain(); - for (jcr=NULL; (jcr=get_next_jcr(jcr)); njobs++) { + foreach_jcr(jcr) { if (jcr->JobId == 0) { /* this is us */ free_locked_jcr(jcr); - njobs--; continue; } free_locked_jcr(jcr); + njobs++; } unlock_jcr_chain(); @@ -404,7 +404,7 @@ static int cancel_cmd(UAContext *ua, char *cmd) } start_prompt(ua, _("Select Job:\n")); lock_jcr_chain(); - for (jcr=NULL; (jcr=get_next_jcr(jcr)); ) { + foreach_jcr(jcr) { if (jcr->JobId == 0) { /* this is us */ free_locked_jcr(jcr); continue; @@ -1674,13 +1674,14 @@ int quit_cmd(UAContext *ua, char *cmd) */ int wait_cmd(UAContext *ua, char *cmd) { + JCR *jcr; bmicrosleep(0, 200000); /* let job actually start */ - for (int running=1; running; ) { - running = 0; + for (bool running=true; running; ) { + running = false; lock_jcr_chain(); - for (JCR *jcr=NULL; (jcr=get_next_jcr(jcr)); ) { + foreach_jcr(jcr) { if (jcr->JobId != 0) { - running = 1; + running = true; free_locked_jcr(jcr); break; } diff --git a/bacula/src/dird/ua_run.c b/bacula/src/dird/ua_run.c index 2753409556..747b62d276 100644 --- a/bacula/src/dird/ua_run.c +++ b/bacula/src/dird/ua_run.c @@ -258,7 +258,9 @@ int run_cmd(UAContext *ua, char *cmd) /* Find Job */ job = (JOB *)GetResWithName(R_JOB, job_name); if (!job) { - bsendmsg(ua, _("Job \"%s\" not found\n"), job_name); + if (*job_name != 0) { + bsendmsg(ua, _("Job \"%s\" not found\n"), job_name); + } job = select_job_resource(ua); } else { Dmsg1(200, "Found job=%s\n", job_name); @@ -274,7 +276,9 @@ int run_cmd(UAContext *ua, char *cmd) if (store_name) { store = (STORE *)GetResWithName(R_STORAGE, store_name); if (!store) { - bsendmsg(ua, _("Storage \"%s\" not found.\n"), store_name); + if (*store_name != 0) { + bsendmsg(ua, _("Storage \"%s\" not found.\n"), store_name); + } store = select_storage_resource(ua); } } else { @@ -288,7 +292,9 @@ int run_cmd(UAContext *ua, char *cmd) if (pool_name) { pool = (POOL *)GetResWithName(R_POOL, pool_name); if (!pool) { - bsendmsg(ua, _("Pool \"%s\" not found.\n"), pool_name); + if (*pool_name != 0) { + bsendmsg(ua, _("Pool \"%s\" not found.\n"), pool_name); + } pool = select_pool_resource(ua); } } else { @@ -301,7 +307,9 @@ int run_cmd(UAContext *ua, char *cmd) if (client_name) { client = (CLIENT *)GetResWithName(R_CLIENT, client_name); if (!client) { - bsendmsg(ua, _("Client \"%s\" not found.\n"), client_name); + if (*client_name != 0) { + bsendmsg(ua, _("Client \"%s\" not found.\n"), client_name); + } client = select_client_resource(ua); } } else { diff --git a/bacula/src/dird/ua_status.c b/bacula/src/dird/ua_status.c index 754b0199f8..7a8a47d147 100644 --- a/bacula/src/dird/ua_status.c +++ b/bacula/src/dird/ua_status.c @@ -391,7 +391,8 @@ static void list_running_jobs(UAContext *ua) Dmsg0(200, "enter list_run_jobs()\n"); lock_jcr_chain(); - for (jcr=NULL; (jcr=get_next_jcr(jcr)); njobs++) { + foreach_jcr(jcr) { + njobs++; if (jcr->JobId == 0) { /* this is us */ /* this is a console or other control job. We only show console * jobs in the status output. @@ -414,12 +415,12 @@ static void list_running_jobs(UAContext *ua) bsendmsg(ua, _("\nRunning Jobs:\n")); bsendmsg(ua, _("Level JobId Job Status\n")); bsendmsg(ua, _("====================================================================\n")); - for (jcr=NULL; (jcr=get_next_jcr(jcr)); njobs++) { + foreach_jcr(jcr) { if (jcr->JobId == 0 || !acl_access_ok(ua, Job_ACL, jcr->job->hdr.name)) { - njobs--; free_locked_jcr(jcr); continue; } + njobs++; switch (jcr->JobStatus) { case JS_Created: msg = _("is waiting execution"); diff --git a/bacula/src/dird/ua_tree.c b/bacula/src/dird/ua_tree.c index b7641f9b3c..7bc68576cf 100644 --- a/bacula/src/dird/ua_tree.c +++ b/bacula/src/dird/ua_tree.c @@ -64,8 +64,8 @@ static struct cmdstruct commands[] = { { N_("exit"), donecmd, _("exit = done")}, { N_("find"), findcmd, _("find files -- wildcards allowed")}, { N_("help"), helpcmd, _("print help")}, - { N_("lsmark"), lsmarkcmd, _("list the marked files in and below the cd")}, { N_("ls"), lscmd, _("list current directory -- wildcards allowed")}, + { N_("lsmark"), lsmarkcmd, _("list the marked files in and below the cd")}, { N_("mark"), markcmd, _("mark file to be restored")}, { N_("markdir"), markdircmd, _("mark directory entry to be restored -- nonrecursive")}, { N_("pwd"), pwdcmd, _("print current working directory")}, @@ -149,10 +149,12 @@ bool user_select_files_from_tree(TREE_CTX *tree) */ int insert_tree_handler(void *ctx, int num_fields, char **row) { + struct stat statp; TREE_CTX *tree = (TREE_CTX *)ctx; char fname[5000]; TREE_NODE *node, *new_node; int type; + bool hard_link; strip_trailing_junk(row[1]); if (*row[1] == 0) { /* no filename => directory */ @@ -164,29 +166,32 @@ int insert_tree_handler(void *ctx, int num_fields, char **row) } else { type = TN_FILE; } - bsnprintf(fname, sizeof(fname), "%s%s", row[0], row[1]); if (tree->avail_node) { - node = tree->avail_node; + node = tree->avail_node; /* if prev node avail use it */ } else { - node = new_tree_node(tree->root, type); + node = new_tree_node(tree->root, type); /* get new node */ tree->avail_node = node; } + hard_link = (decode_LinkFI(row[4], &statp) != 0); + bsnprintf(fname, sizeof(fname), "%s%s%s", row[0], row[1], ""); +// S_ISLNK(statp.st_mode)?" ->":""); Dmsg3(200, "FI=%d type=%d fname=%s\n", node->FileIndex, type, fname); new_node = insert_tree_node(fname, node, tree->root, NULL); /* Note, if node already exists, save new one for next time */ if (new_node != node) { - tree->avail_node = node; + tree->avail_node = node; /* node already exists */ } else { - tree->avail_node = NULL; + 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 */ } - new_node->have_link = (decode_LinkFI(row[4]) != 0); tree->cnt++; return 0; } @@ -212,7 +217,7 @@ static int set_extract(UAContext *ua, TREE_NODE *node, TREE_CTX *tree, bool extr count++; } /* For a non-file (i.e. directory), we see all the children */ - if (node->type != TN_FILE) { + if (node->type != TN_FILE || (node->soft_link && node->child)) { /* Recursive set children within directory */ for (n=node->child; n; n=n->sibling) { count += set_extract(ua, n, tree, extract); @@ -237,7 +242,7 @@ static int set_extract(UAContext *ua, TREE_NODE *node, TREE_CTX *tree, bool extr tree_getpath(node, cwd, sizeof(cwd)); fdbr.FileId = 0; fdbr.JobId = node->JobId; - if (node->have_link && db_get_file_attributes_record(ua->jcr, ua->db, cwd, NULL, &fdbr)) { + if (node->hard_link && db_get_file_attributes_record(ua->jcr, ua->db, cwd, NULL, &fdbr)) { int32_t LinkFI; decode_stat(fdbr.LStat, &statp, &LinkFI); /* decode stat pkt */ /* @@ -379,10 +384,9 @@ static int lscmd(UAContext *ua, TREE_CTX *tree) } else if (node->extract_dir) { tag = "+"; } else { - tag = ""; + tag = ""; } - bsendmsg(ua, "%s%s%s\n", tag, node->fname, - (node->type==TN_DIR||node->type==TN_NEWDIR)?"/":""); + bsendmsg(ua, "%s%s%s\n", tag, node->fname, node->child?"/":""); } } return 1; @@ -409,8 +413,7 @@ static int lsmarkcmd(UAContext *ua, TREE_CTX *tree) } else { tag = ""; } - bsendmsg(ua, "%s%s%s\n", tag, node->fname, - (node->type==TN_DIR||node->type==TN_NEWDIR)?"/":""); + bsendmsg(ua, "%s%s%s\n", tag, node->fname, node->child?"/":""); } } return 1; @@ -454,8 +457,8 @@ static int dircmd(UAContext *ua, TREE_CTX *tree) TREE_NODE *node; FILE_DBR fdbr; struct stat statp; - char buf[1000]; - char cwd[1100]; + char buf[1100]; + char cwd[1100], *pcwd; if (!tree->node->child) { return 1; @@ -473,19 +476,32 @@ static int dircmd(UAContext *ua, TREE_CTX *tree) tree_getpath(node, cwd, sizeof(cwd)); fdbr.FileId = 0; fdbr.JobId = node->JobId; - if (db_get_file_attributes_record(ua->jcr, ua->db, cwd, NULL, &fdbr)) { + /* + * Strip / from soft links to directories. + * This is because soft links to files have a trailing slash + * when returned from tree_getpath, but db_get_file_attr... + * treats soft links as files, so they do not have a trailing + * slash like directory names. + */ + if (node->type == TN_FILE && node->child) { + bstrncpy(buf, cwd, sizeof(buf)); + pcwd = buf; + int len = strlen(buf); + if (len > 1) { + buf[len-1] = 0; /* strip trailing / */ + } + } else { + pcwd = cwd; + } + if (db_get_file_attributes_record(ua->jcr, ua->db, pcwd, NULL, &fdbr)) { int32_t LinkFI; decode_stat(fdbr.LStat, &statp, &LinkFI); /* decode stat pkt */ - ls_output(buf, cwd, tag, &statp); - bsendmsg(ua, "%s\n", buf); } else { /* Something went wrong getting attributes -- print name */ - if (*tag == ' ') { - tag = ""; - } - bsendmsg(ua, "%s%s%s\n", tag, node->fname, - (node->type==TN_DIR||node->type==TN_NEWDIR)?"/":""); + memset(&statp, 0, sizeof(statp)); } + ls_output(buf, cwd, tag, &statp); + bsendmsg(ua, "%s\n", buf); } } return 1; diff --git a/bacula/src/findlib/attribs.c b/bacula/src/findlib/attribs.c index d16c3ec964..87514c67c0 100755 --- a/bacula/src/findlib/attribs.c +++ b/bacula/src/findlib/attribs.c @@ -221,7 +221,7 @@ int decode_stat(char *buf, struct stat *statp, int32_t *LinkFI) } /* Decode a LinkFI field of encoded stat packet */ -int32_t decode_LinkFI(char *buf) +int32_t decode_LinkFI(char *buf, struct stat *statp) { char *p = buf; int64_t val; @@ -230,7 +230,8 @@ int32_t decode_LinkFI(char *buf) p++; /* skip space */ skip_nonspaces(&p); /* st_ino */ p++; - skip_nonspaces(&p); /* st_mode */ + p += from_base64(&val, p); + statp->st_mode = val; /* st_mode */ p++; skip_nonspaces(&p); /* st_nlink */ p++; diff --git a/bacula/src/findlib/protos.h b/bacula/src/findlib/protos.h index 618b0f0d64..4355b12607 100644 --- a/bacula/src/findlib/protos.h +++ b/bacula/src/findlib/protos.h @@ -26,7 +26,7 @@ /* from attribs.c */ void encode_stat (char *buf, FF_PKT *ff_pkt, int data_stream); int decode_stat (char *buf, struct stat *statp, int32_t *LinkFI); -int32_t decode_LinkFI (char *buf); +int32_t decode_LinkFI (char *buf, struct stat *statp); int encode_attribsEx (JCR *jcr, char *attribsEx, FF_PKT *ff_pkt); int set_attributes (JCR *jcr, ATTR *attr, BFILE *ofd); int select_data_stream(FF_PKT *ff_pkt); diff --git a/bacula/src/jcr.h b/bacula/src/jcr.h index 3dba8948d4..2844d6da36 100644 --- a/bacula/src/jcr.h +++ b/bacula/src/jcr.h @@ -81,6 +81,10 @@ jcr->JobStatus == JS_ErrorTerminated || \ jcr->JobStatus == JS_FatalError) +#define foreach_jcr(jcr) \ + for ((jcr)=NULL; ((jcr)=get_next_jcr(jcr)); ) + + struct JCR; typedef void (JCR_free_HANDLER)(JCR *jcr); diff --git a/bacula/src/lib/jcr.c b/bacula/src/lib/jcr.c index f3710da003..aaff694372 100755 --- a/bacula/src/lib/jcr.c +++ b/bacula/src/lib/jcr.c @@ -44,16 +44,21 @@ dlist *last_jobs = NULL; static JCR *jobs = NULL; /* pointer to JCR chain */ -/* Mutex for locking various jcr chains while updating */ -static pthread_mutex_t jcr_chain_mutex = PTHREAD_MUTEX_INITIALIZER; +static brwlock_t lock; /* lock for last jobs and JCR chain */ void init_last_jobs_list() { + int errstat; struct s_last_job *job_entry; if (!last_jobs) { last_jobs = new dlist(job_entry, &job_entry->link); memset(&last_job, 0, sizeof(last_job)); } + if ((errstat=rwl_init(&lock)) != 0) { + Emsg1(M_ABORT, 0, _("Unable to initialize jcr_chain lock. ERR=%s\n"), + strerror(errstat)); + } + } void term_last_jobs_list() @@ -66,18 +71,19 @@ void term_last_jobs_list() delete last_jobs; last_jobs = NULL; } + rwl_destroy(&lock); } void lock_last_jobs_list() { /* Use jcr chain mutex */ - P(jcr_chain_mutex); + lock_jcr_chain(); } void unlock_last_jobs_list() { /* Use jcr chain mutex */ - V(jcr_chain_mutex); + unlock_jcr_chain(); } /* @@ -111,14 +117,14 @@ JCR *new_jcr(int size, JCR_free_HANDLER *daemon_free_jcr) sigfillset(&sigtimer.sa_mask); sigaction(TIMEOUT_SIGNAL, &sigtimer, NULL); - P(jcr_chain_mutex); + lock_jcr_chain(); jcr->prev = NULL; jcr->next = jobs; if (jobs) { jobs->prev = jcr; } jobs = jcr; - V(jcr_chain_mutex); + unlock_jcr_chain(); return jcr; } @@ -232,11 +238,11 @@ void free_jcr(JCR *jcr) #endif struct s_last_job *je; - P(jcr_chain_mutex); + lock_jcr_chain(); jcr->use_count--; /* decrement use count */ Dmsg3(200, "Dec free_jcr 0x%x use_count=%d jobid=%d\n", jcr, jcr->use_count, jcr->JobId); if (jcr->use_count > 0) { /* if in use */ - V(jcr_chain_mutex); + unlock_jcr_chain(); Dmsg2(200, "free_jcr 0x%x use_count=%d\n", jcr, jcr->use_count); return; } @@ -263,7 +269,7 @@ void free_jcr(JCR *jcr) last_job.JobId = 0; /* zap last job */ } close_msg(NULL); /* flush any daemon messages */ - V(jcr_chain_mutex); + unlock_jcr_chain(); Dmsg0(200, "Exit free_jcr\n"); } @@ -296,7 +302,7 @@ JCR *get_jcr_by_id(uint32_t JobId) { JCR *jcr; - P(jcr_chain_mutex); /* lock chain */ + lock_jcr_chain(); /* lock chain */ for (jcr = jobs; jcr; jcr=jcr->next) { if (jcr->JobId == JobId) { P(jcr->mutex); @@ -306,7 +312,7 @@ JCR *get_jcr_by_id(uint32_t JobId) break; } } - V(jcr_chain_mutex); + unlock_jcr_chain(); return jcr; } @@ -319,7 +325,7 @@ JCR *get_jcr_by_session(uint32_t SessionId, uint32_t SessionTime) { JCR *jcr; - P(jcr_chain_mutex); + lock_jcr_chain(); for (jcr = jobs; jcr; jcr=jcr->next) { if (jcr->VolSessionId == SessionId && jcr->VolSessionTime == SessionTime) { @@ -330,7 +336,7 @@ JCR *get_jcr_by_session(uint32_t SessionId, uint32_t SessionTime) break; } } - V(jcr_chain_mutex); + unlock_jcr_chain(); return jcr; } @@ -350,7 +356,7 @@ JCR *get_jcr_by_partial_name(char *Job) if (!Job) { return NULL; } - P(jcr_chain_mutex); + lock_jcr_chain(); len = strlen(Job); for (jcr = jobs; jcr; jcr=jcr->next) { if (strncmp(Job, jcr->Job, len) == 0) { @@ -361,7 +367,7 @@ JCR *get_jcr_by_partial_name(char *Job) break; } } - V(jcr_chain_mutex); + unlock_jcr_chain(); return jcr; } @@ -379,7 +385,7 @@ JCR *get_jcr_by_full_name(char *Job) if (!Job) { return NULL; } - P(jcr_chain_mutex); + lock_jcr_chain(); for (jcr = jobs; jcr; jcr=jcr->next) { if (strcmp(jcr->Job, Job) == 0) { P(jcr->mutex); @@ -389,7 +395,7 @@ JCR *get_jcr_by_full_name(char *Job) break; } } - V(jcr_chain_mutex); + unlock_jcr_chain(); return jcr; } @@ -416,7 +422,11 @@ void set_jcr_job_status(JCR *jcr, int JobStatus) */ void lock_jcr_chain() { - P(jcr_chain_mutex); + int errstat; + if ((errstat=rwl_writelock(&lock)) != 0) { + Emsg1(M_ABORT, 0, "rwl_writelock failure. ERR=%s\n", + strerror(errstat)); + } } /* @@ -424,7 +434,11 @@ void lock_jcr_chain() */ void unlock_jcr_chain() { - V(jcr_chain_mutex); + int errstat; + if ((errstat=rwl_writeunlock(&lock)) != 0) { + Emsg1(M_ABORT, 0, "rwl_writeunlock failure. ERR=%s\n", + strerror(errstat)); + } } @@ -472,7 +486,7 @@ static void jcr_timeout_check(watchdog_t *self) * blocked for more than specified max time. */ lock_jcr_chain(); - for (jcr=NULL; (jcr=get_next_jcr(jcr)); ) { + foreach_jcr(jcr) { free_locked_jcr(jcr); /* OK to free now cuz chain is locked */ if (jcr->JobId == 0) { continue; diff --git a/bacula/src/lib/mem_pool.c b/bacula/src/lib/mem_pool.c index ff8b048092..74fb59bf73 100644 --- a/bacula/src/lib/mem_pool.c +++ b/bacula/src/lib/mem_pool.c @@ -134,7 +134,7 @@ POOLMEM *sm_get_memory(char *fname, int lineno, int32_t size) struct abufhead *buf; int pool = 0; - if ((buf = (struct abufhead *) sm_malloc(fname, lineno, size+HEAD_SIZE)) == NULL) { + if ((buf = (struct abufhead *)sm_malloc(fname, lineno, size+HEAD_SIZE)) == NULL) { Emsg1(M_ABORT, 0, "Out of memory requesting %d bytes\n", size); } buf->ablen = size; diff --git a/bacula/src/lib/tree.c b/bacula/src/lib/tree.c index de1e7f25e9..e13ae8c33b 100755 --- a/bacula/src/lib/tree.c +++ b/bacula/src/lib/tree.c @@ -32,6 +32,9 @@ #define MAXPATHLEN 1000 #endif +/* + * NOTE !!!!! we turn off Debug messages for performance reasons. + */ #undef Dmsg0 #undef Dmsg1 #undef Dmsg2 @@ -347,7 +350,6 @@ void print_tree(char *path, TREE_NODE *tree) Dmsg3(-1, "%s/%s%s\n", path, tree->fname, termchr); switch (tree->type) { case TN_FILE: - break; case TN_NEWDIR: case TN_DIR: case TN_DIR_NLS: @@ -380,7 +382,12 @@ int tree_getpath(TREE_NODE *node, char *buf, int buf_size) buf[0] = 0; } bstrncat(buf, node->fname, buf_size); - if (node->type != TN_FILE) { + /* Add a slash for all directories unless we are at the root, + * also add a slash to a soft linked file if it has children + * i.e. it is linked to a directory. + */ + if ((node->type != TN_FILE && !(buf[0] == '/' && buf[1] == 0)) || + (node->soft_link && node->child)) { bstrncat(buf, "/", buf_size); } return 1; @@ -437,7 +444,7 @@ TREE_NODE *tree_relcwd(char *path, TREE_ROOT *root, TREE_NODE *node) break; } } - if (!cd || cd->type == TN_FILE) { + if (!cd || (cd->type == TN_FILE && !cd->child)) { return NULL; } if (!p) { diff --git a/bacula/src/lib/tree.h b/bacula/src/lib/tree.h index 838f920966..e398e546cd 100644 --- a/bacula/src/lib/tree.h +++ b/bacula/src/lib/tree.h @@ -40,10 +40,11 @@ struct s_tree_node { int32_t FileIndex; /* file index */ uint32_t JobId; /* JobId */ uint16_t fname_len; /* filename length */ - unsigned int type: 8; /* node type */ + int type: 8; /* node type */ unsigned int extract: 1; /* extract item */ unsigned int extract_dir: 1; /* extract dir entry only */ - unsigned int have_link: 1; /* set if have hard link */ + unsigned int hard_link: 1; /* set if have hard link */ + unsigned int soft_link: 1; /* set if is soft link */ struct s_tree_node *parent; struct s_tree_node *sibling; struct s_tree_node *child; diff --git a/bacula/src/lib/watchdog.c b/bacula/src/lib/watchdog.c index ff0c865883..708554a908 100755 --- a/bacula/src/lib/watchdog.c +++ b/bacula/src/lib/watchdog.c @@ -37,17 +37,15 @@ time_t watchdog_time = 0; /* this has granularity of SLEEP_TIME */ /* Forward referenced functions */ static void *watchdog_thread(void *arg); +static void wd_lock(); +static void wd_unlock(); /* Static globals */ -static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t timer = PTHREAD_COND_INITIALIZER; -static bool quit; +static bool quit = false;; static bool wd_is_init = false; +static brwlock_t lock; /* watchdog lock */ -/* Forward referenced callback functions */ static pthread_t wd_tid; - -/* Static globals */ static dlist *wd_queue; static dlist *wd_inactive; @@ -61,14 +59,18 @@ int start_watchdog(void) { int stat; watchdog_t *dummy = NULL; + int errstat; if (wd_is_init) { return 0; } Dmsg0(200, "Initialising NicB-hacked watchdog thread\n"); watchdog_time = time(NULL); - quit = false; + if ((errstat=rwl_init(&lock)) != 0) { + Emsg1(M_ABORT, 0, _("Unable to initialize watchdog lock. ERR=%s\n"), + strerror(errstat)); + } wd_queue = new dlist(wd_queue, &dummy->link); wd_inactive = new dlist(wd_inactive, &dummy->link); @@ -94,12 +96,7 @@ int stop_watchdog(void) return 0; } - Dmsg0(200, "Sending stop signal to NicB-hacked watchdog thread\n"); - P(mutex); - quit = true; - stat = pthread_cond_signal(&timer); - V(mutex); - + quit = true; /* notify watchdog thread to stop */ wd_is_init = false; stat = pthread_join(wd_tid, NULL); @@ -119,8 +116,10 @@ int stop_watchdog(void) } free(p); } + delete wd_inactive; wd_inactive = NULL; + rwl_destroy(&lock); return stat; } @@ -131,9 +130,6 @@ watchdog_t *new_watchdog(void) if (!wd_is_init) { start_watchdog(); - if (!wd_is_init) { - Emsg0(M_ABORT, 0, "BUG! new_watchdog called before start_watchdog\n"); - } } if (wd == NULL) { @@ -160,12 +156,12 @@ bool register_watchdog(watchdog_t *wd) Emsg1(M_ABORT, 0, "BUG! Watchdog %p has zero interval\n", wd); } - P(mutex); + wd_lock(); wd->next_fire = watchdog_time + wd->interval; wd_queue->append(wd); Dmsg3(200, "Registered watchdog %p, interval %d%s\n", wd, wd->interval, wd->one_shot ? " one shot" : ""); - V(mutex); + wd_unlock(); return false; } @@ -206,9 +202,9 @@ bool unregister_watchdog(watchdog_t *wd) Emsg0(M_ABORT, 0, "BUG! unregister_watchdog called before start_watchdog\n"); } - P(mutex); + wd_lock(); ret = unregister_watchdog_unlocked(wd); - V(mutex); + wd_unlock(); return ret; } @@ -217,15 +213,20 @@ static void *watchdog_thread(void *arg) { Dmsg0(200, "NicB-reworked watchdog thread entered\n"); - while (true) { + while (!quit) { watchdog_t *p; - P(mutex); - if (quit) { - V(mutex); - break; - } - + /* + * We lock the jcr chain here because a good number of the + * callback routines lock the jcr chain. We need to lock + * it here *before* the watchdog lock because the SD message + * thread first locks the jcr chain, then when closing the + * job locks the watchdog chain. If the two thread do not + * lock in the same order, we get a deadlock -- each holds + * the other's needed lock. + */ + lock_jcr_chain(); + wd_lock(); watchdog_time = time(NULL); foreach_dlist(p, wd_queue) { @@ -242,10 +243,39 @@ static void *watchdog_thread(void *arg) } } } - V(mutex); + wd_unlock(); + unlock_jcr_chain(); bmicrosleep(SLEEP_TIME, 0); } Dmsg0(200, "NicB-reworked watchdog thread exited\n"); return NULL; } + +/* + * Watchdog lock, this can be called multiple times by the same + * thread without blocking, but must be unlocked the number of + * times it was locked. + */ +static void wd_lock() +{ + int errstat; + if ((errstat=rwl_writelock(&lock)) != 0) { + Emsg1(M_ABORT, 0, "rwl_writelock failure. ERR=%s\n", + strerror(errstat)); + } +} + +/* + * Unlock the watchdog. This can be called multiple times by the + * same thread up to the number of times that thread called + * wd_ lock()/ + */ +static void wd_unlock() +{ + int errstat; + if ((errstat=rwl_writeunlock(&lock)) != 0) { + Emsg1(M_ABORT, 0, "rwl_writeunlock failure. ERR=%s\n", + strerror(errstat)); + } +} diff --git a/bacula/src/stored/block.c b/bacula/src/stored/block.c index 5a3028403e..58fa67ef5e 100644 --- a/bacula/src/stored/block.c +++ b/bacula/src/stored/block.c @@ -116,11 +116,6 @@ DEV_BLOCK *new_block(DEVICE *dev) block->dev = dev; block->block_len = block->buf_len; /* default block size */ block->buf = get_memory(block->buf_len); - if (block->buf == NULL) { - Mmsg0(&dev->errmsg, _("Unable to malloc block buffer.\n")); - Emsg0(M_FATAL, 0, dev->errmsg); - return NULL; - } empty_block(block); block->BlockVer = BLOCK_VER; /* default write version */ Dmsg1(90, "Returning new block=%x\n", block); @@ -134,7 +129,7 @@ DEV_BLOCK *new_block(DEVICE *dev) void print_block_read_errors(JCR *jcr, DEV_BLOCK *block) { if (block->read_errors > 1) { - Jmsg(jcr, M_ERROR, 0, _("%d block read errors ignored.\n"), + Jmsg(jcr, M_ERROR, 0, _("%d block read errors not printed.\n"), block->read_errors); } } @@ -221,7 +216,7 @@ static int unser_block_header(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) block->BlockVer = 1; block->bufp = block->buf + bhl; if (strncmp(Id, BLKHDR1_ID, BLKHDR_ID_LENGTH) != 0) { - Mmsg2(&dev->errmsg, _("Buffer ID error. Wanted: %s, got %s. Buffer discarded.\n"), + Mmsg2(&dev->errmsg, _("Volume data error! Wanted ID: %s, got %s. Buffer discarded.\n"), BLKHDR1_ID, Id); if (block->read_errors == 0 || verbose >= 2) { Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); @@ -236,7 +231,7 @@ static int unser_block_header(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) block->BlockVer = 2; block->bufp = block->buf + bhl; if (strncmp(Id, BLKHDR2_ID, BLKHDR_ID_LENGTH) != 0) { - Mmsg2(&dev->errmsg, _("Buffer ID error. Wanted: %s, got %s. Buffer discarded.\n"), + Mmsg2(&dev->errmsg, _("Volume data error! Wanted ID: %s, got %s. Buffer discarded.\n"), BLKHDR2_ID, Id); if (block->read_errors == 0 || verbose >= 2) { Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); @@ -245,7 +240,7 @@ static int unser_block_header(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) return 0; } } else { - Mmsg1(&dev->errmsg, _("Expected block-id BB01 or BB02, got %s. Buffer discarded.\n"), Id); + Mmsg1(&dev->errmsg, _("Volume data error! Wanted block-id BB02, got %s. Buffer discarded.\n"), Id); if (block->read_errors == 0 || verbose >= 2) { Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); } @@ -255,7 +250,7 @@ static int unser_block_header(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) /* Sanity check */ if (block_len > MAX_BLOCK_LENGTH) { - Mmsg1(&dev->errmsg, _("Block length %u is insane (too large), probably due to a bad archive.\n"), + Mmsg1(&dev->errmsg, _("Volume data error! Block length %u is insane (too large), probably due to a bad archive.\n"), block_len); if (block->read_errors == 0 || verbose >= 2) { Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); @@ -280,7 +275,7 @@ static int unser_block_header(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) BlockCheckSum = bcrc32((uint8_t *)block->buf+BLKHDR_CS_LENGTH, block_len-BLKHDR_CS_LENGTH); if (BlockCheckSum != CheckSum) { - Mmsg3(&dev->errmsg, _("Block checksum mismatch in block %u: calc=%x blk=%x\n"), + Mmsg3(&dev->errmsg, _("Volume data error! Block checksum mismatch in block %u: calc=%x blk=%x\n"), (unsigned)BlockNumber, BlockCheckSum, CheckSum); if (block->read_errors == 0 || verbose >= 2) { Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); @@ -308,7 +303,7 @@ int write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) * If a new volume has been mounted since our last write * Create a JobMedia record for the previous volume written, * and set new parameters to write this volume - * The saem applies for if we are in a new file. + * The same applies for if we are in a new file. */ if (jcr->NewVol || jcr->NewFile) { /* Create a jobmedia record for this job */ @@ -680,7 +675,7 @@ reread: /* Continue here for successful read */ block->read_len = stat; /* save length read */ if (block->read_len < BLKHDR2_LENGTH) { - Mmsg2(&dev->errmsg, _("Very short block of %d bytes on device %s discarded.\n"), + Mmsg2(&dev->errmsg, _("Volume data error! Very short block of %d bytes on device %s discarded.\n"), block->read_len, dev->dev_name); Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); dev->state |= ST_SHORT; /* set short block */ @@ -732,7 +727,7 @@ reread: } if (block->block_len > block->read_len) { - Mmsg3(&dev->errmsg, _("Short block at %u of %d bytes on device %s discarded.\n"), + Mmsg3(&dev->errmsg, _("Volume data error! Short block at %u of %d bytes on device %s discarded.\n"), dev->block_num, block->read_len, dev->dev_name); Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); dev->state |= ST_SHORT; /* set short block */ diff --git a/bacula/src/stored/btape.c b/bacula/src/stored/btape.c index 1a812d5efa..ca18e1d802 100644 --- a/bacula/src/stored/btape.c +++ b/bacula/src/stored/btape.c @@ -1352,15 +1352,9 @@ bail_out: static void statcmd() { - int stat = 0; - int debug; - uint32_t status; - - debug = debug_level; + int debug = debug_level; debug_level = 30; - if (!status_dev(dev, &status)) { - Pmsg2(0, "Bad status from status %d. ERR=%s\n", stat, strerror_dev(dev)); - } + Pmsg2(0, "Device status: %u. ERR=%s\n", status_dev(dev), strerror_dev(dev)); #ifdef xxxx dump_volume_label(dev); #endif diff --git a/bacula/src/stored/butil.c b/bacula/src/stored/butil.c index 249a503c5c..5586309d82 100644 --- a/bacula/src/stored/butil.c +++ b/bacula/src/stored/butil.c @@ -1,7 +1,7 @@ /* * * Utility routines for "tool" programs such as bscan, bls, - * bextract, ... + * bextract, ... Some routines also used by Bacula. * * Normally nothing in this file is called by the Storage * daemon because we interact more directly with the user @@ -240,12 +240,11 @@ void display_tape_error_status(JCR *jcr, DEVICE *dev) { uint32_t status; - Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); - status_dev(dev, &status); + status = status_dev(dev); Dmsg1(20, "Device status: %x\n", status); if (status & BMT_EOD) Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Data\n")); - else if (status & BMT_EOT) + else if (status & BMT_EOT) Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Tape\n")); else if (status & BMT_EOF) Jmsg(jcr, M_ERROR, 0, _("Unexpected End of File\n")); @@ -253,6 +252,4 @@ void display_tape_error_status(JCR *jcr, DEVICE *dev) Jmsg(jcr, M_ERROR, 0, _("Tape Door is Open\n")); else if (!(status & BMT_ONLINE)) Jmsg(jcr, M_ERROR, 0, _("Unexpected Tape is Off-line\n")); - else - Jmsg(jcr, M_ERROR, 0, _("Read error on Record Header %s: %s\n"), dev_name(dev), strerror(errno)); } diff --git a/bacula/src/stored/dev.c b/bacula/src/stored/dev.c index 1664f9ca20..146be78624 100644 --- a/bacula/src/stored/dev.c +++ b/bacula/src/stored/dev.c @@ -555,11 +555,9 @@ int update_pos_dev(DEVICE *dev) * currently), which means that for the moment, this * routine has very little value. * - * Returns: 1 on success - * 0 on error + * Returns: status */ -int -status_dev(DEVICE *dev, uint32_t *status) +uint32_t status_dev(DEVICE *dev) { struct mtget mt_stat; uint32_t stat = 0; @@ -626,8 +624,7 @@ status_dev(DEVICE *dev, uint32_t *status) } else { stat |= BMT_ONLINE | BMT_BOT; } - *status = stat; - return 1; + return stat; } diff --git a/bacula/src/stored/device.c b/bacula/src/stored/device.c index 115a9d5ae2..51f5d3a831 100644 --- a/bacula/src/stored/device.c +++ b/bacula/src/stored/device.c @@ -78,7 +78,7 @@ extern int debug_level; */ int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) { - uint32_t stat = 0; + uint32_t stat; char PrevVolName[MAX_NAME_LENGTH]; DEV_BLOCK *label_blk; char b1[30], b2[30]; @@ -86,7 +86,7 @@ int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) char dt[MAX_TIME_LENGTH]; wait_time = time(NULL); - status_dev(dev, &stat); + stat = status_dev(dev); if (!(stat & BMT_EOD)) { return 0; /* this really shouldn't happen */ } diff --git a/bacula/src/stored/dircmd.c b/bacula/src/stored/dircmd.c index 6cd627f03b..5cef5693e4 100644 --- a/bacula/src/stored/dircmd.c +++ b/bacula/src/stored/dircmd.c @@ -781,12 +781,8 @@ static int readlabel_cmd(JCR *jcr) P(dev->mutex); /* Use P to avoid indefinite block */ if (!dev_state(dev, ST_OPENED)) { - if (open_dev(dev, NULL, READ_WRITE) < 0) { - bnet_fsend(dir, _("3994 Connot open device: %s\n"), strerror_dev(dev)); - } else { - read_volume_label(jcr, dev, Slot); - force_close_dev(dev); - } + read_volume_label(jcr, dev, Slot); + force_close_dev(dev); /* Under certain "safe" conditions, we can steal the lock */ } else if (dev->dev_blocked && (dev->dev_blocked == BST_UNMOUNTED || diff --git a/bacula/src/stored/protos.h b/bacula/src/stored/protos.h index 10b4122db9..c46d9ad22f 100644 --- a/bacula/src/stored/protos.h +++ b/bacula/src/stored/protos.h @@ -28,166 +28,166 @@ 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); +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); /* 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); -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); -int status_dev(DEVICE *dev, uint32_t *status); -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); +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); /* 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(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(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/version.h b/bacula/src/version.h index 492893a380..2dde19f717 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -1,9 +1,9 @@ /* */ #undef VERSION -#define VERSION "1.33" +#define VERSION "1.33.3" #define VSTRING "1" -#define BDATE "04 Feb 2004" -#define LSMDATE "04Feb04" +#define BDATE "07 Feb 2004" +#define LSMDATE "07Feb04" /* Debug flags */ #undef DEBUG -- 2.39.2