From 0be23e5ebcb5713a1dbdd474658a1c880274a8d8 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Sat, 12 Nov 2005 17:31:19 +0000 Subject: [PATCH] - Implement autochanger drives protocol so that Dir knows how many drives an autochanger has. - Do not request drive number in label, ... if only one drive. - Turn off debug code. - Fix update slots to clear slot number of every slot before setting it. This fixes (I believe) bug #471 - Make unmount unload the autochanger slot. - Modify open() on mount to be read-only and non-blocking, otherwise the mount can block for a long time. - Make a few error message numbers unique. - Make a few error messages more correct. - Apply patch from Thorsten to fix Win98 stat() command. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@2575 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/kes-1.38 | 14 ++ bacula/src/dird/dird_conf.h | 1 + bacula/src/dird/protos.h | 1 + bacula/src/dird/ua_cmds.c | 3 +- bacula/src/dird/ua_label.c | 63 ++++-- bacula/src/dird/ua_select.c | 21 +- bacula/src/filed/backup.c | 4 +- bacula/src/lib/smartall.c | 327 ++++++++++++++--------------- bacula/src/lib/smartall.h | 41 ++-- bacula/src/stored/autochanger.c | 12 +- bacula/src/stored/dircmd.c | 101 ++++++--- bacula/src/stored/reserve.c | 2 +- bacula/src/win32/compat/compat.cpp | 26 +-- 13 files changed, 353 insertions(+), 263 deletions(-) diff --git a/bacula/kes-1.38 b/bacula/kes-1.38 index 7569459631..9ef3e1b1b4 100644 --- a/bacula/kes-1.38 +++ b/bacula/kes-1.38 @@ -4,6 +4,20 @@ General: Changes to 1.38.1: +12Oct05 +- Implement "autochanger drives" protocol so that Dir knows + how many drives an autochanger has. +- Do not request drive number in label, ... if only one drive. +- Turn off debug code. +- Fix update slots to clear slot number of every slot before + setting it. This fixes (I believe) bug #471 +- Make unmount unload the autochanger slot. +- Modify open() on mount to be read-only and non-blocking, + otherwise the mount can block for a long time. +- Make a few error message numbers unique. +- Make a few error messages more correct. +- Apply patch from Thorsten to fix Win98 stat() command. +10Oct05 - Remove delete of CVS from all makefiles. - Fix seg fault when clicking on Add button in wx-console restore panel. Bug #470. diff --git a/bacula/src/dird/dird_conf.h b/bacula/src/dird/dird_conf.h index a9291f982b..5d2ef5befc 100644 --- a/bacula/src/dird/dird_conf.h +++ b/bacula/src/dird/dird_conf.h @@ -240,6 +240,7 @@ public: char *media_type; alist *device; /* Alternate devices for this Storage */ int autochanger; /* set if autochanger */ + int drives; /* number of drives in autochanger */ uint32_t MaxConcurrentJobs; /* Maximume concurrent jobs */ uint32_t NumConcurrentJobs; /* number of concurrent jobs running */ int tls_enable; /* Enable TLS */ diff --git a/bacula/src/dird/protos.h b/bacula/src/dird/protos.h index 5938e0e14b..a7aabf4ec2 100644 --- a/bacula/src/dird/protos.h +++ b/bacula/src/dird/protos.h @@ -159,6 +159,7 @@ void parse_ua_args(UAContext *ua); /* ua_label.c */ bool is_volume_name_legal(UAContext *ua, const char *name); +int get_num_drives_from_SD(UAContext *ua); /* ua_output.c */ void prtit(void *ctx, const char *msg); diff --git a/bacula/src/dird/ua_cmds.c b/bacula/src/dird/ua_cmds.c index 2c90337aac..127f5a5299 100644 --- a/bacula/src/dird/ua_cmds.c +++ b/bacula/src/dird/ua_cmds.c @@ -1262,12 +1262,13 @@ static void do_mount_cmd(UAContext *ua, const char *command) if (!store) { return; } + set_storage(jcr, store); + drive = get_storage_drive(ua, store); Dmsg3(120, "Found storage, MediaType=%s DevName=%s drive=%d\n", store->media_type, store->dev_name(), drive); - set_storage(jcr, store); if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) { bsendmsg(ua, _("Failed to connect to Storage daemon.\n")); return; diff --git a/bacula/src/dird/ua_label.c b/bacula/src/dird/ua_label.c index 00889c90ac..88f2794a5b 100644 --- a/bacula/src/dird/ua_label.c +++ b/bacula/src/dird/ua_label.c @@ -135,7 +135,7 @@ static bool get_user_slot_list(UAContext *ua, char *slot_list, int num_slots) Dmsg0(100, "Slots turned on:\n"); for (i=1; i <= num_slots; i++) { if (slot_list[i]) { - Dmsg1(000, "%d\n", i); + Dmsg1(100, "%d\n", i); } } return true; @@ -191,7 +191,7 @@ int update_slots(UAContext *ua) /* Walk through the list updating the media records */ for (vl=vol_list; vl; vl=vl->next) { if (vl->Slot > max_slots) { - bsendmsg(ua, _("Slot %d larger than max %d ignored.\n"), + bsendmsg(ua, _("Slot %d greater than max %d ignored.\n"), vl->Slot, max_slots); continue; } @@ -210,16 +210,16 @@ int update_slots(UAContext *ua) Dmsg2(100, "Got Vol=%s from SD for Slot=%d\n", vl->VolName, vl->Slot); } slot_list[vl->Slot] = 0; /* clear Slot */ + memset(&mr, 0, sizeof(mr)); + mr.Slot = vl->Slot; + mr.InChanger = 1; + mr.StorageId = store->StorageId; + /* Set InChanger to zero for this Slot */ + db_lock(ua->db); + db_make_inchanger_unique(ua->jcr, ua->db, &mr); + db_unlock(ua->db); if (!vl->VolName) { - Dmsg1(100, "No VolName for Slot=%d setting InChanger to zero.\n", vl->Slot); - memset(&mr, 0, sizeof(mr)); - mr.Slot = vl->Slot; - mr.InChanger = 1; - mr.StorageId = store->StorageId; - /* Set InChanger to zero for this Slot */ - db_lock(ua->db); - db_make_inchanger_unique(ua->jcr, ua->db, &mr); - db_unlock(ua->db); + Dmsg1(000, "No VolName for Slot=%d setting InChanger to zero.\n", vl->Slot); bsendmsg(ua, _("No VolName for Slot=%d set InChanger to zero.\n"), vl->Slot); continue; } @@ -245,8 +245,8 @@ int update_slots(UAContext *ua) db_unlock(ua->db); continue; } else { - bsendmsg(ua, _("Record for Volume \"%s\" not found in catalog.\n"), - mr.VolumeName); + bsendmsg(ua, _("Volume \"%s\" not found in catalog. Slot=%d set InChanger to zero.\n"), + mr.VolumeName, vl->Slot); } db_unlock(ua->db); } @@ -878,8 +878,8 @@ static int get_num_slots_from_SD(UAContext *ua) bstrncpy(dev_name, store->dev_name(), sizeof(dev_name)); bash_spaces(dev_name); - /* Ask for autochanger list of volumes */ - bnet_fsend(sd, _("autochanger slots %s \n"), dev_name); + /* Ask for autochanger number of slots */ + bnet_fsend(sd, _("autochanger slots %s\n"), dev_name); while (bnet_recv(sd) >= 0) { if (sscanf(sd->msg, "slots=%d\n", &slots) == 1) { @@ -893,6 +893,39 @@ static int get_num_slots_from_SD(UAContext *ua) return slots; } +/* + * We get the number of drives in the changer from the SD + */ +int get_num_drives_from_SD(UAContext *ua) +{ + STORE *store = ua->jcr->store; + char dev_name[MAX_NAME_LENGTH]; + BSOCK *sd; + int drives = 0; + + + if (!(sd=open_sd_bsock(ua))) { + return 0; + } + + bstrncpy(dev_name, store->dev_name(), sizeof(dev_name)); + bash_spaces(dev_name); + /* Ask for autochanger number of slots */ + bnet_fsend(sd, _("autochanger drives %s\n"), dev_name); + + while (bnet_recv(sd) >= 0) { + if (sscanf(sd->msg, "drives=%d\n", &drives) == 1) { + break; + } else { + bsendmsg(ua, "%s", sd->msg); + } + } + close_sd_bsock(ua); +// bsendmsg(ua, _("Device \"%s\" has %d drives.\n"), store->dev_name(), drives); + return drives; +} + + /* diff --git a/bacula/src/dird/ua_select.c b/bacula/src/dird/ua_select.c index 0e860bd68e..dd529eac4b 100644 --- a/bacula/src/dird/ua_select.c +++ b/bacula/src/dird/ua_select.c @@ -839,6 +839,7 @@ STORE *get_storage_resource(UAContext *ua, bool use_default) return store; } +/* Get drive that we are working with for this storage */ int get_storage_drive(UAContext *ua, STORE *store) { int i, drive = -1; @@ -847,12 +848,22 @@ int get_storage_drive(UAContext *ua, STORE *store) if (i >=0) { drive = atoi(ua->argv[i]); } else if (store && store->autochanger) { - ua->cmd[0] = 0; - if (!get_cmd(ua, _("Enter autochanger drive[0]: "))) { - drive = -1; /* None */ - } else { - drive = atoi(ua->cmd); + /* If our structure is not set ask SD for # drives */ + if (store->drives == 0) { + store->drives = get_num_drives_from_SD(ua); } + /* If only one drive, default = 0 */ + if (store->drives == 1) { + drive = 0; + } else { + /* Ask user to enter drive number */ + ua->cmd[0] = 0; + if (!get_cmd(ua, _("Enter autochanger drive[0]: "))) { + drive = -1; /* None */ + } else { + drive = atoi(ua->cmd); + } + } } return drive; } diff --git a/bacula/src/filed/backup.c b/bacula/src/filed/backup.c index 175634d217..cb489d6114 100644 --- a/bacula/src/filed/backup.c +++ b/bacula/src/filed/backup.c @@ -96,10 +96,10 @@ bool blast_data_to_storage_daemon(JCR *jcr, char *addr) free_pool_memory(jcr->acl_text); - bnet_sig(sd, BNET_EOD); /* end of sending data */ - stop_heartbeat_monitor(jcr); + bnet_sig(sd, BNET_EOD); /* end of sending data */ + if (jcr->big_buf) { free(jcr->big_buf); jcr->big_buf = NULL; diff --git a/bacula/src/lib/smartall.c b/bacula/src/lib/smartall.c index 0f7c00fd5d..32f5fac221 100644 --- a/bacula/src/lib/smartall.c +++ b/bacula/src/lib/smartall.c @@ -1,40 +1,35 @@ /* - S M A R T A L L O C - Smart Memory Allocator + S M A R T A L L O C + Smart Memory Allocator - Evolved over several years, starting with the initial - SMARTALLOC code for AutoSketch in 1986, guided by the Blind - Watchbreaker, John Walker. Isolated in this general-purpose - form in September of 1989. Updated with be more POSIX - compliant and to include Web-friendly HTML documentation in - October of 1998 by the same culprit. For additional - information and the current version visit the Web page: + Evolved over several years, starting with the initial + SMARTALLOC code for AutoSketch in 1986, guided by the Blind + Watchbreaker, John Walker. Isolated in this general-purpose + form in September of 1989. Updated with be more POSIX + compliant and to include Web-friendly HTML documentation in + October of 1998 by the same culprit. For additional + information and the current version visit the Web page: - http://www.fourmilab.ch/smartall/ + http://www.fourmilab.ch/smartall/ - Version $Id$ + Version $Id$ */ /* - Copyright (C) 2000-2004 Kern Sibbald and John Walker + Copyright (C) 2000-2005 Kern Sibbald This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. + modify it under the terms of the GNU General Public License + version 2 as amended with additional clauses defined in the + file LICENSE in the main source directory. 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., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + the file LICENSE for additional details. */ @@ -68,7 +63,7 @@ uint32_t sm_buffers = 0; static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; -extern char my_name[]; /* daemon name */ +extern char my_name[]; /* daemon name */ typedef unsigned short sm_ushort; @@ -80,10 +75,10 @@ typedef unsigned short sm_ushort; /* Memory allocation control structures and storage. */ struct abufhead { - struct b_queue abq; /* Links on allocated queue */ - unsigned ablen; /* Buffer length in bytes */ + struct b_queue abq; /* Links on allocated queue */ + unsigned ablen; /* Buffer length in bytes */ const char *abfname; /* File name pointer */ - sm_ushort ablineno; /* Line number of allocation */ + sm_ushort ablineno; /* Line number of allocation */ }; static struct b_queue abqueue = { /* Allocated buffer queue */ @@ -91,13 +86,13 @@ static struct b_queue abqueue = { /* Allocated buffer queue */ }; -static bool bufimode = false; /* Buffers not tracked when True */ +static bool bufimode = false; /* Buffers not tracked when True */ #define HEAD_SIZE BALIGN(sizeof(struct abufhead)) /* SMALLOC -- Allocate buffer, enqueing on the orphaned buffer - tracking list. */ + tracking list. */ static void *smalloc(const char *fname, int lineno, unsigned int nbytes) { @@ -126,11 +121,11 @@ static void *smalloc(const char *fname, int lineno, unsigned int nbytes) buf[nbytes - 1] = (((long) buf) & 0xFF) ^ 0xC5; buf += HEAD_SIZE; /* Increment to user data start */ if (++sm_buffers > sm_max_buffers) { - sm_max_buffers = sm_buffers; + sm_max_buffers = sm_buffers; } sm_bytes += nbytes; if (sm_bytes > sm_max_bytes) { - sm_max_bytes = sm_bytes; + sm_max_bytes = sm_bytes; } V(mutex); } else { @@ -141,7 +136,7 @@ static void *smalloc(const char *fname, int lineno, unsigned int nbytes) } /* SM_NEW_OWNER -- Update the File and line number for a buffer - This is to accomodate mem_pool. */ + This is to accomodate mem_pool. */ void sm_new_owner(const char *fname, int lineno, char *buf) { @@ -152,9 +147,9 @@ void sm_new_owner(const char *fname, int lineno, char *buf) } /* SM_FREE -- Update free pool availability. FREE is never called - except through this interface or by actuallyfree(). - free(x) is defined to generate a call to this - routine. */ + except through this interface or by actuallyfree(). + free(x) is defined to generate a call to this + routine. */ void sm_free(const char *file, int line, void *fp) { @@ -171,8 +166,8 @@ void sm_free(const char *file, int line, void *fp) P(mutex); Dmsg4(1150, "sm_free %d at %x from %s:%d\n", - head->ablen, fp, - head->abfname, head->ablineno); + head->ablen, fp, + head->abfname, head->ablineno); /* The following assertions will catch virtually every release of an address which isn't an allocated buffer. */ @@ -185,9 +180,9 @@ void sm_free(const char *file, int line, void *fp) Emsg2(M_ABORT, 0, _("qp->qprev->qnext != qp called from %s:%d\n"), file, line); } - /* The following assertion detects storing off the end of the + /* The following assertion detects storing off the end of the allocated space in the buffer by comparing the end of buffer - checksum with the address of the buffer. */ + checksum with the address of the buffer. */ if (((unsigned char *)cp)[head->ablen - 1] != ((((long) cp) & 0xFF) ^ 0xC5)) { V(mutex); @@ -199,7 +194,7 @@ void sm_free(const char *file, int line, void *fp) qdchain(qp); V(mutex); - /* Now we wipe the contents of the just-released buffer with + /* Now we wipe the contents of the just-released buffer with "designer garbage" (Duff Kurland's phrase) of alternating bits. This is intended to ruin the day for any miscreant who attempts to access data through a pointer into storage that's @@ -211,7 +206,7 @@ void sm_free(const char *file, int line, void *fp) } /* SM_MALLOC -- Allocate buffer. NULL is returned if no memory - was available. */ + was available. */ void *sm_malloc(const char *fname, int lineno, unsigned int nbytes) { @@ -220,8 +215,8 @@ void *sm_malloc(const char *fname, int lineno, unsigned int nbytes) if ((buf = smalloc(fname, lineno, nbytes)) != NULL) { /* To catch sloppy code that assumes buffers obtained from - malloc() are zeroed, we preset the buffer contents to - "designer garbage" consisting of alternating bits. */ + malloc() are zeroed, we preset the buffer contents to + "designer garbage" consisting of alternating bits. */ memset(buf, 0x55, (int) nbytes); } else { @@ -233,7 +228,7 @@ void *sm_malloc(const char *fname, int lineno, unsigned int nbytes) /* SM_CALLOC -- Allocate an array and clear it to zero. */ void *sm_calloc(const char *fname, int lineno, - unsigned int nelem, unsigned int elsize) + unsigned int nelem, unsigned int elsize) { void *buf; @@ -245,14 +240,14 @@ void *sm_calloc(const char *fname, int lineno, return buf; } -/* SM_REALLOC -- Adjust the size of a previously allocated buffer. - Note that the trick of "resurrecting" a previously - freed buffer with realloc() is NOT supported by this - function. Further, because of the need to maintain - our control storage, SM_REALLOC must always allocate - a new block and copy the data in the old block. - This may result in programs which make heavy use of - realloc() running much slower than normally. */ +/* SM_REALLOC -- Adjust the size of a previously allocated buffer. + Note that the trick of "resurrecting" a previously + freed buffer with realloc() is NOT supported by this + function. Further, because of the need to maintain + our control storage, SM_REALLOC must always allocate + a new block and copy the data in the old block. + This may result in programs which make heavy use of + realloc() running much slower than normally. */ void *sm_realloc(const char *fname, int lineno, void *ptr, unsigned int size) { @@ -265,7 +260,7 @@ void *sm_realloc(const char *fname, int lineno, void *ptr, unsigned int size) e_msg(fname, lineno, M_ABORT, 0, _("sm_realloc size: %d\n"), size); } - /* If the old block pointer is NULL, treat realloc() as a + /* If the old block pointer is NULL, treat realloc() as a malloc(). SVID is silent on this, but many C libraries permit this. */ @@ -285,7 +280,7 @@ void *sm_realloc(const char *fname, int lineno, void *ptr, unsigned int size) /* Sizes differ. Allocate a new buffer of the requested size. If we can't obtain such a buffer, act as defined in SVID: - return NULL from realloc() and leave the buffer in PTR + return NULL from realloc() and leave the buffer in PTR intact. */ sm_buffers--; @@ -294,9 +289,9 @@ void *sm_realloc(const char *fname, int lineno, void *ptr, unsigned int size) if ((buf = smalloc(fname, lineno, size)) != NULL) { memcpy(buf, ptr, (int) sm_min(size, osize)); /* If the new buffer is larger than the old, fill the balance - of it with "designer garbage". */ + of it with "designer garbage". */ if (size > osize) { - memset(((char *) buf) + osize, 0x55, (int) (size - osize)); + memset(((char *) buf) + osize, 0x55, (int) (size - osize)); } /* All done. Free and dechain the original buffer. */ @@ -307,20 +302,20 @@ void *sm_realloc(const char *fname, int lineno, void *ptr, unsigned int size) return buf; } -/* ACTUALLYMALLOC -- Call the system malloc() function to obtain - storage which will eventually be released - by system or library routines not compiled - using SMARTALLOC. */ +/* ACTUALLYMALLOC -- Call the system malloc() function to obtain + storage which will eventually be released + by system or library routines not compiled + using SMARTALLOC. */ void *actuallymalloc(unsigned int size) { return malloc(size); } -/* ACTUALLYCALLOC -- Call the system calloc() function to obtain - storage which will eventually be released - by system or library routines not compiled - using SMARTALLOC. */ +/* ACTUALLYCALLOC -- Call the system calloc() function to obtain + storage which will eventually be released + by system or library routines not compiled + using SMARTALLOC. */ void *actuallycalloc(unsigned int nelem, unsigned int elsize) { @@ -328,9 +323,9 @@ void *actuallycalloc(unsigned int nelem, unsigned int elsize) } /* ACTUALLYREALLOC -- Call the system realloc() function to obtain - storage which will eventually be released - by system or library routines not compiled - using SMARTALLOC. */ + storage which will eventually be released + by system or library routines not compiled + using SMARTALLOC. */ void *actuallyrealloc(void *ptr, unsigned int size) { @@ -339,7 +334,7 @@ void *actuallyrealloc(void *ptr, unsigned int size) } /* ACTUALLYFREE -- Interface to system free() function to release - buffers allocated by low-level routines. */ + buffers allocated by low-level routines. */ void actuallyfree(void *cp) { @@ -347,7 +342,7 @@ void actuallyfree(void *cp) } /* SM_DUMP -- Print orphaned buffers (and dump them if BUFDUMP is - * True). + * True). * N.B. DO NOT USE any Bacula print routines (Dmsg, Jmsg, Emsg, ...) * as they have all been shut down at this point. */ @@ -362,45 +357,45 @@ void sm_dump(bool bufdump) while (ap != (struct abufhead *) &abqueue) { if ((ap == NULL) || - (ap->abq.qnext->qprev != (struct b_queue *) ap) || - (ap->abq.qprev->qnext != (struct b_queue *) ap)) { - fprintf(stderr, _( - "\nOrphaned buffers exist. Dump terminated following\n" - " discovery of bad links in chain of orphaned buffers.\n" - " Buffer address with bad links: %lx\n"), (long) ap); - break; + (ap->abq.qnext->qprev != (struct b_queue *) ap) || + (ap->abq.qprev->qnext != (struct b_queue *) ap)) { + fprintf(stderr, _( + "\nOrphaned buffers exist. Dump terminated following\n" + " discovery of bad links in chain of orphaned buffers.\n" + " Buffer address with bad links: %lx\n"), (long) ap); + break; } if (ap->abfname != NULL) { - unsigned memsize = ap->ablen - (HEAD_SIZE + 1); - char errmsg[500]; - - bsnprintf(errmsg, sizeof(errmsg), - _("Orphaned buffer: %6u bytes allocated at line %d of %s %s\n"), - memsize, ap->ablineno, my_name, ap->abfname - ); - fprintf(stderr, "%s", errmsg); - if (bufdump) { - char buf[20]; - unsigned llen = 0; - char *cp = ((char *) ap) + HEAD_SIZE; - - errmsg[0] = EOS; - while (memsize) { - if (llen >= 16) { - bstrncat(errmsg, "\n", sizeof(errmsg)); - llen = 0; - fprintf(stderr, "%s", errmsg); - errmsg[0] = EOS; - } - bsnprintf(buf, sizeof(buf), " %02X", - (*cp++) & 0xFF); - bstrncat(errmsg, buf, sizeof(errmsg)); - llen++; - memsize--; - } - fprintf(stderr, "%s\n", errmsg); - } + unsigned memsize = ap->ablen - (HEAD_SIZE + 1); + char errmsg[500]; + + bsnprintf(errmsg, sizeof(errmsg), + _("Orphaned buffer: %6u bytes allocated at line %d of %s %s\n"), + memsize, ap->ablineno, my_name, ap->abfname + ); + fprintf(stderr, "%s", errmsg); + if (bufdump) { + char buf[20]; + unsigned llen = 0; + char *cp = ((char *) ap) + HEAD_SIZE; + + errmsg[0] = EOS; + while (memsize) { + if (llen >= 16) { + bstrncat(errmsg, "\n", sizeof(errmsg)); + llen = 0; + fprintf(stderr, "%s", errmsg); + errmsg[0] = EOS; + } + bsnprintf(buf, sizeof(buf), " %02X", + (*cp++) & 0xFF); + bstrncat(errmsg, buf, sizeof(errmsg)); + llen++; + memsize--; + } + fprintf(stderr, "%s\n", errmsg); + } } ap = (struct abufhead *) ap->abq.qnext; } @@ -411,10 +406,10 @@ void sm_dump(bool bufdump) /* SM_CHECK -- Check the buffers and dump if any damage exists. */ void sm_check(const char *fname, int lineno, bool bufdump) { - if (!sm_check_rtn(fname, lineno, bufdump)) { - Emsg2(M_ABORT, 0, _("Damaged buffer found. Called from %s:%d\n"), - fname, lineno); - } + if (!sm_check_rtn(fname, lineno, bufdump)) { + Emsg2(M_ABORT, 0, _("Damaged buffer found. Called from %s:%d\n"), + fname, lineno); + } } #undef sm_check_rtn @@ -429,66 +424,66 @@ int sm_check_rtn(const char *fname, int lineno, bool bufdump) while (ap != (struct abufhead *) &abqueue) { bad = 0; if ((ap == NULL) || - (ap->abq.qnext->qprev != (struct b_queue *) ap)) { - bad = 0x1; + (ap->abq.qnext->qprev != (struct b_queue *) ap)) { + bad = 0x1; } if (ap->abq.qprev->qnext != (struct b_queue *) ap) { - bad |= 0x2; + bad |= 0x2; } if (((unsigned char *) ap)[((struct abufhead *) ap)->ablen - 1] != - ((((long) ap) & 0xFF) ^ 0xC5)) { - bad |= 0x4; + ((((long) ap) & 0xFF) ^ 0xC5)) { + bad |= 0x4; } badbuf |= bad; if (bad) { - fprintf(stderr, - _("\nDamaged buffers found at %s:%d\n"), fname, lineno); - - if (bad & 0x1) { - fprintf(stderr, _(" discovery of bad prev link.\n")); - } - if (bad & 0x2) { - fprintf(stderr, _(" discovery of bad next link.\n")); - } - if (bad & 0x4) { - fprintf(stderr, _(" discovery of data overrun.\n")); - } - - fprintf(stderr, _(" Buffer address: %lx\n"), (long) ap); - - if (ap->abfname != NULL) { - unsigned memsize = ap->ablen - (HEAD_SIZE + 1); - char errmsg[80]; - - fprintf(stderr, - _("Damaged buffer: %6u bytes allocated at line %d of %s %s\n"), - memsize, ap->ablineno, my_name, ap->abfname - ); - if (bufdump) { - unsigned llen = 0; - char *cp = ((char *) ap) + HEAD_SIZE; - - errmsg[0] = EOS; - while (memsize) { - if (llen >= 16) { - strcat(errmsg, "\n"); - llen = 0; - fprintf(stderr, "%s", errmsg); - errmsg[0] = EOS; - } - if (*cp < 0x20) { - sprintf(errmsg + strlen(errmsg), " %02X", - (*cp++) & 0xFF); - } else { - sprintf(errmsg + strlen(errmsg), " %c ", - (*cp++) & 0xFF); - } - llen++; - memsize--; - } - fprintf(stderr, "%s\n", errmsg); - } - } + fprintf(stderr, + _("\nDamaged buffers found at %s:%d\n"), fname, lineno); + + if (bad & 0x1) { + fprintf(stderr, _(" discovery of bad prev link.\n")); + } + if (bad & 0x2) { + fprintf(stderr, _(" discovery of bad next link.\n")); + } + if (bad & 0x4) { + fprintf(stderr, _(" discovery of data overrun.\n")); + } + + fprintf(stderr, _(" Buffer address: %lx\n"), (long) ap); + + if (ap->abfname != NULL) { + unsigned memsize = ap->ablen - (HEAD_SIZE + 1); + char errmsg[80]; + + fprintf(stderr, + _("Damaged buffer: %6u bytes allocated at line %d of %s %s\n"), + memsize, ap->ablineno, my_name, ap->abfname + ); + if (bufdump) { + unsigned llen = 0; + char *cp = ((char *) ap) + HEAD_SIZE; + + errmsg[0] = EOS; + while (memsize) { + if (llen >= 16) { + strcat(errmsg, "\n"); + llen = 0; + fprintf(stderr, "%s", errmsg); + errmsg[0] = EOS; + } + if (*cp < 0x20) { + sprintf(errmsg + strlen(errmsg), " %02X", + (*cp++) & 0xFF); + } else { + sprintf(errmsg + strlen(errmsg), " %c ", + (*cp++) & 0xFF); + } + llen++; + memsize--; + } + fprintf(stderr, "%s\n", errmsg); + } + } } ap = (struct abufhead *) ap->abq.qnext; } @@ -498,11 +493,11 @@ int sm_check_rtn(const char *fname, int lineno, bool bufdump) /* SM_STATIC -- Orphaned buffer detection can be disabled (for such - items as buffers allocated during initialisation) by - calling sm_static(1). Normal orphaned buffer - detection can be re-enabled with sm_static(0). Note - that all the other safeguards still apply to buffers - allocated when sm_static(1) mode is in effect. */ + items as buffers allocated during initialisation) by + calling sm_static(1). Normal orphaned buffer + detection can be re-enabled with sm_static(0). Note + that all the other safeguards still apply to buffers + allocated when sm_static(1) mode is in effect. */ void sm_static(int mode) { diff --git a/bacula/src/lib/smartall.h b/bacula/src/lib/smartall.h index c646888abe..429549b9d1 100644 --- a/bacula/src/lib/smartall.h +++ b/bacula/src/lib/smartall.h @@ -1,28 +1,23 @@ /* - Definitions for the smart memory allocator + Definitions for the smart memory allocator Version $Id$ */ /* - Copyright (C) 2000-2004 Kern Sibbald and John Walker + Copyright (C) 2000-2005 Kern Sibbald This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. + modify it under the terms of the GNU General Public License + version 2 as amended with additional clauses defined in the + file LICENSE in the main source directory. 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., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + the file LICENSE for additional details. */ @@ -37,15 +32,15 @@ extern uint32_t sm_buffers; extern void *sm_malloc(const char *fname, int lineno, unsigned int nbytes), - *sm_calloc(const char *fname, int lineno, - unsigned int nelem, unsigned int elsize), - *sm_realloc(const char *fname, int lineno, void *ptr, unsigned int size), - *actuallymalloc(unsigned int size), - *actuallycalloc(unsigned int nelem, unsigned int elsize), - *actuallyrealloc(void *ptr, unsigned int size); + *sm_calloc(const char *fname, int lineno, + unsigned int nelem, unsigned int elsize), + *sm_realloc(const char *fname, int lineno, void *ptr, unsigned int size), + *actuallymalloc(unsigned int size), + *actuallycalloc(unsigned int nelem, unsigned int elsize), + *actuallyrealloc(void *ptr, unsigned int size); extern void sm_free(const char *fname, int lineno, void *fp); extern void actuallyfree(void *cp), - sm_dump(bool bufdump), sm_static(int mode); + sm_dump(bool bufdump), sm_static(int mode); extern void sm_new_owner(const char *fname, int lineno, char *buf); #ifdef SMCHECK @@ -142,19 +137,19 @@ class SMARTALLOC public: void *operator new(size_t s) { - return malloc(s); + return malloc(s); } void *operator new[](size_t s) { - return malloc(s); + return malloc(s); } void operator delete(void *ptr) { - free(ptr); + free(ptr); } void operator delete[](void *ptr, size_t i) { - free(ptr); + free(ptr); } }; #endif diff --git a/bacula/src/stored/autochanger.c b/bacula/src/stored/autochanger.c index 5da5ce5c25..008cc228aa 100644 --- a/bacula/src/stored/autochanger.c +++ b/bacula/src/stored/autochanger.c @@ -421,12 +421,18 @@ bool autochanger_cmd(DCR *dcr, BSOCK *dir, const char *cmd) return false; } - changer = get_pool_memory(PM_FNAME); /* List command? */ if (strcmp(cmd, "list") == 0) { unload_autochanger(dcr, -1); } + if (strcmp(cmd, "drives") == 0) { + AUTOCHANGER *changer_res = dcr->device->changer_res; + bnet_fsend(dir, "drives=%d\n", changer_res->device->size()); + Dmsg1(100, "drives=%d\n", changer_res->device->size()); + return true; + } + changer = get_pool_memory(PM_FNAME); lock_changer(dcr); /* Now issue the command */ changer = edit_device_codes(dcr, changer, @@ -444,14 +450,14 @@ bool autochanger_cmd(DCR *dcr, BSOCK *dir, const char *cmd) Dmsg1(100, "msg); bnet_send(dir); } - } else { + } else if (strcmp(cmd, "slots") == 0 ) { /* For slots command, read a single line */ bstrncpy(dir->msg, "slots=", len); fgets(dir->msg+6, len-6, bpipe->rfd); dir->msglen = strlen(dir->msg); Dmsg1(100, "msg); bnet_send(dir); - } + } stat = close_bpipe(bpipe); if (stat != 0) { diff --git a/bacula/src/stored/dircmd.c b/bacula/src/stored/dircmd.c index 398607c3a7..f3fa17f209 100644 --- a/bacula/src/stored/dircmd.c +++ b/bacula/src/stored/dircmd.c @@ -71,7 +71,7 @@ static bool setdebug_cmd(JCR *jcr); static bool cancel_cmd(JCR *cjcr); static bool mount_cmd(JCR *jcr); static bool unmount_cmd(JCR *jcr); -static bool autochanger_cmd(JCR *sjcr); +static bool changer_cmd(JCR *sjcr); static bool do_label(JCR *jcr, int relabel); static DEVICE *find_device(JCR *jcr, POOL_MEM &dev_name, int drive); static void read_volume_label(JCR *jcr, DEVICE *dev, int Slot); @@ -92,7 +92,7 @@ struct s_cmds { */ static struct s_cmds cmds[] = { {"JobId=", job_cmd, 0}, /* start Job */ - {"autochanger", autochanger_cmd, 0}, + {"autochanger", changer_cmd, 0}, {"bootstrap", bootstrap_cmd, 0}, {"cancel", cancel_cmd, 0}, {"label", label_cmd, 0}, /* label a tape */ @@ -353,7 +353,7 @@ static bool do_label(JCR *jcr, int relabel) } V(dev->mutex); } else { - bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), dev_name.c_str()); + bnet_fsend(dir, _("3999 Device \"%s\" not found or could not be opened.\n"), dev_name.c_str()); } } else { /* NB dir->msg gets clobbered in bnet_fsend, so save command */ @@ -520,6 +520,7 @@ static DEVICE *find_device(JCR *jcr, POOL_MEM &devname, int drive) continue; } if (!device->dev->autoselect) { + Dmsg1(100, "Device %s not autoselect skipped.\n", devname.c_str()); continue; /* device is not available */ } if (drive < 0 || drive == (int)device->dev->drive_index) { @@ -527,12 +528,15 @@ static DEVICE *find_device(JCR *jcr, POOL_MEM &devname, int drive) found = true; break; } + Dmsg3(100, "Device %s drive wrong: want=%d got=%d skipping\n", + devname.c_str(), drive, (int)device->dev->drive_index); } break; /* we found it but could not open a device */ } } if (found) { + Dmsg1(100, "Found changer device %s\n", device->hdr.name); jcr->dcr = new_dcr(jcr, device->dev); jcr->dcr->device = device; return jcr->dcr->dev; @@ -555,7 +559,7 @@ static bool mount_cmd(JCR *jcr) if (sscanf(dir->msg, "mount %127s drive=%d", devname.c_str(), &drive) == 2) { dev = find_device(jcr, devname, drive); dcr = jcr->dcr; - if (dev) { + if (dev) { P(dev->mutex); /* Use P to avoid indefinite block */ switch (dev->dev_blocked) { /* device blocked? */ case BST_WAITING_FOR_SYSOP: @@ -572,11 +576,14 @@ static bool mount_cmd(JCR *jcr) case BST_UNMOUNTED_WAITING_FOR_SYSOP: case BST_UNMOUNTED: /* We freed the device, so reopen it and wake any waiting threads */ - if (dev->open(dcr, OPEN_READ_WRITE) < 0) { + dev->open_nowait = true; + if (dev->open(dcr, OPEN_READ_ONLY) < 0) { bnet_fsend(dir, _("3901 open device failed: ERR=%s\n"), strerror_dev(dev)); + dev->open_nowait = false; break; } + dev->open_nowait = false; read_dev_volume_label(dcr); if (dev->dev_blocked == BST_UNMOUNTED) { /* We blocked the device, so unblock it */ @@ -620,11 +627,14 @@ static bool mount_cmd(JCR *jcr) dev->print_name()); } } else if (dev->is_tape()) { - if (dev->open(dcr, OPEN_READ_WRITE) < 0) { + dev->open_nowait = true; + if (dev->open(dcr, OPEN_READ_ONLY) < 0) { bnet_fsend(dir, _("3901 open device failed: ERR=%s\n"), strerror_dev(dev)); + dev->open_nowait = false; break; } + dev->open_nowait = false; read_label(dcr); if (dev->is_labeled()) { bnet_fsend(dir, _("3001 Device %s is already mounted with Volume \"%s\"\n"), @@ -653,7 +663,7 @@ static bool mount_cmd(JCR *jcr) } V(dev->mutex); } else { - bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), devname.c_str()); + bnet_fsend(dir, _("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str()); } } else { pm_strcpy(jcr->errmsg, dir->msg); @@ -678,6 +688,9 @@ static bool unmount_cmd(JCR *jcr) if (dev) { P(dev->mutex); /* Use P to avoid indefinite block */ if (!dev->is_open()) { + if (!dev->is_busy()) { + unload_autochanger(jcr->dcr, -1); + } Dmsg0(90, "Device already unmounted\n"); bnet_fsend(dir, _("3901 Device %s is already unmounted.\n"), dev->print_name()); @@ -685,8 +698,10 @@ static bool unmount_cmd(JCR *jcr) } else if (dev->dev_blocked == BST_WAITING_FOR_SYSOP) { Dmsg2(90, "%d waiter dev_block=%d. doing unmount\n", dev->num_waiting, dev->dev_blocked); - offline_or_rewind_dev(dev); - force_close_device(dev); + if (!unload_autochanger(jcr->dcr, -1)) { + offline_or_rewind_dev(dev); + force_close_device(dev); + } dev->dev_blocked = BST_UNMOUNTED_WAITING_FOR_SYSOP; bnet_fsend(dir, _("3001 Device %s unmounted.\n"), dev->print_name()); @@ -711,14 +726,16 @@ static bool unmount_cmd(JCR *jcr) /* block_device(dev, BST_UNMOUNTED); replace with 2 lines below */ dev->dev_blocked = BST_UNMOUNTED; dev->no_wait_id = 0; - offline_or_rewind_dev(dev); - force_close_device(dev); + if (!unload_autochanger(jcr->dcr, -1)) { + offline_or_rewind_dev(dev); + force_close_device(dev); + } bnet_fsend(dir, _("3002 Device %s unmounted.\n"), dev->print_name()); } V(dev->mutex); } else { - bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), devname.c_str()); + bnet_fsend(dir, _("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str()); } } else { /* NB dir->msg gets clobbered in bnet_fsend, so save command */ @@ -749,18 +766,18 @@ static bool release_cmd(JCR *jcr) P(dev->mutex); /* Use P to avoid indefinite block */ if (!dev->is_open()) { Dmsg0(90, "Device already released\n"); - bnet_fsend(dir, _("3911 Device %s already released.\n"), + bnet_fsend(dir, _("3921 Device %s already released.\n"), dev->print_name()); } else if (dev->dev_blocked == BST_WAITING_FOR_SYSOP || dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP) { Dmsg2(90, "%d waiter dev_block=%d. doing unmount\n", dev->num_waiting, dev->dev_blocked); - bnet_fsend(dir, _("3912 Device %s waiting for mount.\n"), + bnet_fsend(dir, _("3922 Device %s waiting for mount.\n"), dev->print_name()); } else if (dev->dev_blocked == BST_DOING_ACQUIRE) { - bnet_fsend(dir, _("3913 Device %s is busy in acquire.\n"), + bnet_fsend(dir, _("3923 Device %s is busy in acquire.\n"), dev->print_name()); } else if (dev->dev_blocked == BST_WRITING_LABEL) { @@ -772,17 +789,17 @@ static bool release_cmd(JCR *jcr) } else { /* device not being used */ Dmsg0(90, "Device not in use, unmounting\n"); release_volume(jcr->dcr); - bnet_fsend(dir, _("3012 Device %s released.\n"), + bnet_fsend(dir, _("3022 Device %s released.\n"), dev->print_name()); } V(dev->mutex); } else { - bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), devname.c_str()); + bnet_fsend(dir, _("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str()); } } else { /* NB dir->msg gets clobbered in bnet_fsend, so save command */ pm_strcpy(jcr->errmsg, dir->msg); - bnet_fsend(dir, _("3917 Error scanning release command: %s\n"), jcr->errmsg); + bnet_fsend(dir, _("3927 Error scanning release command: %s\n"), jcr->errmsg); } bnet_sig(dir, BNET_EOD); return true; @@ -793,7 +810,7 @@ static bool release_cmd(JCR *jcr) /* * Autochanger command from Director */ -static bool autochanger_cmd(JCR *jcr) +static bool changer_cmd(JCR *jcr) { POOL_MEM devname; BSOCK *dir = jcr->dir_bsock; @@ -802,12 +819,15 @@ static bool autochanger_cmd(JCR *jcr) const char *cmd = NULL; bool ok = false; - if (sscanf(dir->msg, "autochanger list %127s ", devname.c_str()) == 1) { + if (sscanf(dir->msg, "autochanger list %127s", devname.c_str()) == 1) { cmd = "list"; ok = true; - } else if (sscanf(dir->msg, "autochanger slots %127s ", devname.c_str()) == 1) { + } else if (sscanf(dir->msg, "autochanger slots %127s", devname.c_str()) == 1) { cmd = "slots"; ok = true; + } else if (sscanf(dir->msg, "autochanger drives %127s", devname.c_str()) == 1) { + cmd = "drives"; + ok = true; } if (ok) { dev = find_device(jcr, devname, -1); @@ -827,11 +847,11 @@ static bool autochanger_cmd(JCR *jcr) } V(dev->mutex); } else { - bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), devname.c_str()); + bnet_fsend(dir, _("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str()); } } else { /* error on scanf */ pm_strcpy(jcr->errmsg, dir->msg); - bnet_fsend(dir, _("3908 Error scanning autocharger list/slots command: %s\n"), + bnet_fsend(dir, _("3908 Error scanning autocharger drives/list/slots command: %s\n"), jcr->errmsg); } bnet_sig(dir, BNET_EOD); @@ -867,7 +887,7 @@ static bool readlabel_cmd(JCR *jcr) } V(dev->mutex); } else { - bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), devname.c_str()); + bnet_fsend(dir, _("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str()); } } else { pm_strcpy(jcr->errmsg, dir->msg); @@ -937,11 +957,38 @@ static bool try_autoload_device(JCR *jcr, int slot, const char *VolName) static void send_dir_busy_message(BSOCK *dir, DEVICE *dev) { - if (dev->can_read()) { - bnet_fsend(dir, _("3911 Device %s is busy reading.\n"), + if (dev->is_blocked()) { + switch (dev->dev_blocked) { + case BST_UNMOUNTED: + bnet_fsend(dir, _("3931 Device %s is BLOCKED. user unmounted.\n"), + dev->print_name()); + break; + case BST_UNMOUNTED_WAITING_FOR_SYSOP: + bnet_fsend(dir, _("3932 Device %s is BLOCKED. user unmounted during wait for media/mount.\n"), + dev->print_name()); + break; + case BST_WAITING_FOR_SYSOP: + bnet_fsend(dir, _("3933 Device %s is BLOCKED waiting for media.\n"), + dev->print_name()); + break; + case BST_DOING_ACQUIRE: + bnet_fsend(dir, _("3934 Device %s is being initialized.\n"), + dev->print_name()); + break; + case BST_WRITING_LABEL: + bnet_fsend(dir, _("3935 Device %s is blocked labeling a Volume.\n"), + dev->print_name()); + break; + default: + bnet_fsend(dir, _("3935 Device %s is blocked for unknown reason.\n"), + dev->print_name()); + break; + } + } else if (dev->can_read()) { + bnet_fsend(dir, _("3936 Device %s is busy reading.\n"), dev->print_name());; } else { - bnet_fsend(dir, _("3912 Device %s is busy with %d writer(s).\n"), + bnet_fsend(dir, _("3937 Device %s is busy with %d writer(s).\n"), dev->print_name(), dev->num_writers); } } diff --git a/bacula/src/stored/reserve.c b/bacula/src/stored/reserve.c index 50fef64521..ccd8527da6 100644 --- a/bacula/src/stored/reserve.c +++ b/bacula/src/stored/reserve.c @@ -788,7 +788,7 @@ static int can_reserve_drive(DCR *dcr, RCTX &rctx) return 1; } else { /* Changing pool, unload old tape if any in drive */ - Dmsg0(200, "got dev: num_writers=0, reserved, pool change\n"); + Dmsg0(200, "got dev: num_writers=0, not reserved, pool change, unload changer\n"); unload_autochanger(dcr, 0); } } diff --git a/bacula/src/win32/compat/compat.cpp b/bacula/src/win32/compat/compat.cpp index 14c72df9f8..4fc0e6b874 100644 --- a/bacula/src/win32/compat/compat.cpp +++ b/bacula/src/win32/compat/compat.cpp @@ -423,24 +423,12 @@ stat(const char *file, struct stat *sb) memset(sb, 0, sizeof(*sb)); - if (g_platform_id == VER_PLATFORM_WIN32_WINDOWS) { - return stat2(file, sb); - } - - // otherwise we're on NT -#if 0 - WCHAR buf[32767]; - buf[0] = '\\'; - buf[1] = '\\'; - buf[2] = '?'; - buf[3] = '\\'; - - wchar_win32_path(file, buf+4); - - if (!GetFileAttributesExW((WCHAR *)buf, GetFileExInfoStandard, &data)) { - return stat2(file, sb); - } -#else + /* why not allow win 95 to use p_GetFileAttributesExA ? + * this function allows _some_ open files to be stat'ed + * if (g_platform_id == VER_PLATFORM_WIN32_WINDOWS) { + * return stat2(file, sb); + * } + */ if (p_GetFileAttributesExW) { /* dynamically allocate enough space for UCS2 filename */ @@ -461,8 +449,6 @@ stat(const char *file, struct stat *sb) return stat2(file, sb); } -#endif - sb->st_mode = 0777; /* start with everything */ if (data.dwFileAttributes & FILE_ATTRIBUTE_READONLY) { sb->st_mode &= ~(S_IRUSR|S_IRGRP|S_IROTH); -- 2.39.5