From 339dfeb1016cb4f9a079046a6bf1b1ce3e84b71b Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Thu, 28 Jun 2007 11:57:03 +0000 Subject: [PATCH] kes Move lock structures into new file lock.h kes Use jcr lock for locking reservations messages rather than the reservations lock. kes Rename a number of locking functions to make their sense a bit more logical (more to be done), also rename a few other methods in the DEVICE structure. kes Add a good bit of documentation of the SD locking mechanisms to src/stored/lock.c kes Convert a number of bnet_xx calls to use the new bsock class. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@5112 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/src/stored/acquire.c | 17 +++--- bacula/src/stored/append.c | 26 ++++----- bacula/src/stored/block.c | 20 +++---- bacula/src/stored/dev.c | 6 -- bacula/src/stored/dev.h | 79 ++++++++------------------ bacula/src/stored/label.c | 2 +- bacula/src/stored/lock.c | 109 +++++++++++++++++++++++++++++++++--- bacula/src/stored/lock.h | 79 ++++++++++++++++++++++++++ bacula/src/stored/protos.h | 2 +- bacula/src/stored/reserve.c | 32 ++++++++--- bacula/src/stored/stored.h | 1 + bacula/src/version.h | 4 +- 12 files changed, 260 insertions(+), 117 deletions(-) create mode 100644 bacula/src/stored/lock.h diff --git a/bacula/src/stored/acquire.c b/bacula/src/stored/acquire.c index 0f6a89017a..57e359da84 100644 --- a/bacula/src/stored/acquire.c +++ b/bacula/src/stored/acquire.c @@ -63,7 +63,7 @@ bool acquire_device_for_read(DCR *dcr) int retry = 0; Dmsg1(50, "jcr->dcr=%p\n", jcr->dcr); - dev->block(BST_DOING_ACQUIRE); + dev->dblock(BST_DOING_ACQUIRE); if (dev->num_writers > 0) { Jmsg2(jcr, M_FATAL, 0, _("Acquire read: num_writers=%d not zero. Job %d canceled.\n"), @@ -129,11 +129,11 @@ bool acquire_device_for_read(DCR *dcr) * which we do not use except for the dev info. */ stat = search_res_for_device(rctx); - release_msgs(jcr); /* release queued messages */ + release_reserve_messages(jcr); /* release queued messages */ unlock_reservations(); if (stat == 1) { DCR *ndcr = jcr->read_dcr; - dev->unblock(dev_unlocked); + dev->dunblock(dev_unlocked); detach_dcr_from_dev(dcr); /* release old device */ /* Copy important info from the new dcr */ dev = dcr->dev = ndcr->dev; @@ -143,7 +143,7 @@ bool acquire_device_for_read(DCR *dcr) attach_dcr_to_dev(dcr); ndcr->VolumeName[0] = 0; free_dcr(ndcr); - dev->block(BST_DOING_ACQUIRE); + dev->dblock(BST_DOING_ACQUIRE); Jmsg(jcr, M_INFO, 0, _("Media Type change. New device %s chosen.\n"), dev->print_name()); bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName)); @@ -290,7 +290,7 @@ get_out: Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name()); dcr->reserved_device = false; } - dev->unblock(dev_locked); + dev->dunblock(dev_locked); Dmsg1(50, "jcr->dcr=%p\n", jcr->dcr); return ok; } @@ -315,7 +315,7 @@ DCR *acquire_device_for_append(DCR *dcr) init_device_wait_timers(dcr); - dev->block(BST_DOING_ACQUIRE); + dev->dblock(BST_DOING_ACQUIRE); Dmsg1(190, "acquire_append device is %s\n", dev->is_tape()?"tape": (dev->is_dvd()?"DVD":"disk")); @@ -439,7 +439,7 @@ DCR *acquire_device_for_append(DCR *dcr) Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name()); dcr->reserved_device = false; } - dev->unblock(dev_locked); + dev->dunblock(dev_locked); return dcr; /* @@ -452,7 +452,7 @@ get_out: Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name()); dcr->reserved_device = false; } - dev->unblock(dev_locked); + dev->dunblock(dev_locked); return NULL; } @@ -560,7 +560,6 @@ bool release_device(DCR *dcr) pthread_cond_broadcast(&dev->wait_next_vol); Dmsg1(100, "JobId=%u broadcast wait_device_release\n", (uint32_t)jcr->JobId); pthread_cond_broadcast(&wait_device_release); - dcr->dev_locked = false; /* set no longer locked */ dev->dunlock(); if (jcr->read_dcr == dcr) { jcr->read_dcr = NULL; diff --git a/bacula/src/stored/append.c b/bacula/src/stored/append.c index 1bda34c632..6519c70123 100644 --- a/bacula/src/stored/append.c +++ b/bacula/src/stored/append.c @@ -1,9 +1,3 @@ -/* - * Append code for Storage daemon - * Kern Sibbald, May MM - * - * Version $Id$ - */ /* Bacula® - The Network Backup Solution @@ -31,6 +25,12 @@ (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, Switzerland, email:ftf@fsfeurope.org. */ +/* + * Append code for Storage daemon + * Kern Sibbald, May MM + * + * Version $Id$ + */ #include "bacula.h" #include "stored.h" @@ -76,7 +76,7 @@ bool do_append_data(JCR *jcr) ds = fd_sock; - if (!bnet_set_buffer_size(ds, dcr->device->max_network_buffer_size, BNET_SETBUF_WRITE)) { + if (!ds->set_buffer_size(dcr->device->max_network_buffer_size, BNET_SETBUF_WRITE)) { set_jcr_job_status(jcr, JS_ErrorTerminated); Jmsg0(jcr, M_FATAL, 0, _("Unable to set network buffer size.\n")); return false; @@ -116,7 +116,7 @@ bool do_append_data(JCR *jcr) } /* Tell File daemon to send data */ - if (!bnet_fsend(fd_sock, OK_data)) { + if (!fd_sock->fsend(OK_data)) { berrno be; Jmsg1(jcr, M_FATAL, 0, _("Network send error to FD. ERR=%s\n"), be.bstrerror(fd_sock->b_errno)); @@ -156,7 +156,7 @@ bool do_append_data(JCR *jcr) break; /* end of data */ } Jmsg1(jcr, M_FATAL, 0, _("Error reading data header from FD. ERR=%s\n"), - bnet_strerror(ds)); + ds->bstrerror()); ok = false; break; } @@ -242,7 +242,7 @@ bool do_append_data(JCR *jcr) if (!dir_update_file_attributes(dcr, &rec)) { jcr->dir_bsock->clear_spooling(); Jmsg(jcr, M_FATAL, 0, _("Error updating file attributes. ERR=%s\n"), - bnet_strerror(jcr->dir_bsock)); + jcr->dir_bsock->bstrerror()); ok = false; break; } @@ -254,9 +254,9 @@ bool do_append_data(JCR *jcr) Dmsg1(650, "End read loop with FD. Stat=%d\n", n); if (is_bnet_error(ds)) { - Dmsg1(350, "Network read error from FD. ERR=%s\n", bnet_strerror(ds)); + Dmsg1(350, "Network read error from FD. ERR=%s\n", ds->bstrerror()); Jmsg1(jcr, M_FATAL, 0, _("Network error on data channel. ERR=%s\n"), - bnet_strerror(ds)); + ds->bstrerror()); ok = false; break; } @@ -266,7 +266,7 @@ bool do_append_data(JCR *jcr) set_jcr_job_status(jcr, ok?JS_Terminated:JS_ErrorTerminated); /* Terminate connection with FD */ - bnet_fsend(ds, OK_append); + ds->fsend(OK_append); do_fd_commands(jcr); /* finish dialog with FD */ diff --git a/bacula/src/stored/block.c b/bacula/src/stored/block.c index 0ab2c033b8..db28aed9ed 100644 --- a/bacula/src/stored/block.c +++ b/bacula/src/stored/block.c @@ -1,13 +1,3 @@ -/* - * - * block.c -- tape block handling functions - * - * Kern Sibbald, March MMI - * added BB02 format October MMII - * - * Version $Id$ - * - */ /* Bacula® - The Network Backup Solution @@ -35,6 +25,16 @@ (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, Switzerland, email:ftf@fsfeurope.org. */ +/* + * + * block.c -- tape block handling functions + * + * Kern Sibbald, March MMI + * added BB02 format October MMII + * + * Version $Id$ + * + */ #include "bacula.h" diff --git a/bacula/src/stored/dev.c b/bacula/src/stored/dev.c index 08dc97f67a..2e2f39088b 100644 --- a/bacula/src/stored/dev.c +++ b/bacula/src/stored/dev.c @@ -47,12 +47,6 @@ * daemon. More complicated coding (double buffering, writer * thread, ...) is left for a later version. * - * Unfortunately, I have had to add more and more complication - * to this code. This was not foreseen as noted above, and as - * a consequence has lead to something more contorted than is - * really necessary -- KES. Note, this contortion has been - * corrected to a large extent by a rewrite (Apr MMI). - * * Version $Id$ */ diff --git a/bacula/src/stored/dev.h b/bacula/src/stored/dev.h index bb8d33ed7d..5cc3f7ba16 100644 --- a/bacula/src/stored/dev.h +++ b/bacula/src/stored/dev.h @@ -39,20 +39,8 @@ #ifndef __DEV_H #define __DEV_H 1 -#ifdef SD_DEBUG_LOCK -#define r_dlock() _r_dlock(__FILE__, __LINE__); /* in device.c */ -#define r_dunlock() _r_dunlock(__FILE__, __LINE__); /* in device.c */ -#define dlock() _dlock(__FILE__, __LINE__); /* in device.c */ -#define dunlock() _dunlock(__FILE__, __LINE__); /* in device.c */ -#endif - #undef DCR /* used by Bacula */ -#define block_device(d, s) _block_device(__FILE__, __LINE__, (d), s) -#define unblock_device(d) _unblock_device(__FILE__, __LINE__, (d)) -#define steal_device_lock(d, p, s) _steal_device_lock(__FILE__, __LINE__, (d), (p), s) -#define give_back_device_lock(d, p) _give_back_device_lock(__FILE__, __LINE__, (d), (p)) - /* Return values from wait_for_sysop() */ enum { W_ERROR = 1, @@ -143,16 +131,6 @@ enum { #define ST_PART_SPOOLED (1<<18) /* spooling part */ #define ST_FREESPACE_OK (1<<19) /* Have valid freespace for DVD */ -/* m_blocked states (mutually exclusive) */ -enum { - BST_NOT_BLOCKED = 0, /* not blocked */ - BST_UNMOUNTED, /* User unmounted device */ - BST_WAITING_FOR_SYSOP, /* Waiting for operator to mount tape */ - BST_DOING_ACQUIRE, /* Opening/validating/moving tape */ - BST_WRITING_LABEL, /* Labeling a tape */ - BST_UNMOUNTED_WAITING_FOR_SYSOP, /* User unmounted during wait for op */ - BST_MOUNT /* Mount request */ -}; /* Volume Catalog Information structure definition */ struct VOLUME_CAT_INFO { @@ -186,24 +164,11 @@ struct VOLUME_CAT_INFO { }; -typedef struct s_steal_lock { - pthread_t no_wait_id; /* id of no wait thread */ - int dev_blocked; /* state */ - int dev_prev_blocked; /* previous blocked state */ -} bsteal_lock_t; - class DEVRES; /* Device resource defined in stored_conf.h */ class DCR; /* forward reference */ class VOLRES; /* forward reference */ -/* - * Used in unblock() call - */ -enum { - dev_locked = true, - dev_unlocked = false -}; /* * Device structure definition. There is one of these for @@ -227,10 +192,6 @@ public: int num_waiting; /* number of threads waiting */ int num_writers; /* number of writing threads */ int reserved_device; /* number of device reservations */ - - /* New access control in process of being implemented */ -// brwlock_t xlock; /* New mutual exclusion lock */ - int capabilities; /* capabilities mask */ int state; /* state mask */ int dev_errno; /* Our own errno */ @@ -380,21 +341,8 @@ public: char *bstrerror(void) { return errmsg; }; char *print_errmsg() { return errmsg; }; -#ifdef SD_DEBUG_LOCK - void _r_dlock(const char *, int); /* in device.c */ - void _r_dunlock(const char *, int); /* in device.c */ - void _dlock(const char *, int); /* in device.c */ - void _dunlock(const char *, int); /* in device.c */ -#else - void r_dlock(); /* in device.c */ - void r_dunlock() { dunlock(); } - void dlock() { P(m_mutex); } - void dunlock() { V(m_mutex); } -#endif void clear_volhdr(); /* in dev.c */ - void block(int why); /* in locks.c */ - void unblock(bool locked=false); /* in locks.c */ void close(); /* in dev.c */ void close_part(DCR *dcr); /* in dev.c */ bool truncate(DCR *dcr); /* in dev.c */ @@ -424,14 +372,31 @@ public: bool update_pos(DCR *dcr); /* in dev.c */ bool update_freespace(); /* in dvd.c */ - void set_blocked(int block) { m_blocked = block; }; - int blocked() const { return m_blocked; }; uint32_t get_file() const { return file; }; - uint32_t get_block() const { return block_num; }; - const char *print_blocked() const; /* in dev.c */ - bool is_blocked() const { return m_blocked != BST_NOT_BLOCKED; }; + uint32_t get_block_num() const { return block_num; }; int fd() const { return m_fd; }; + /* + * Locking and blocking calls + */ +#ifdef SD_DEBUG_LOCK + void _r_dlock(const char *, int); /* in lock.c */ + void _r_dunlock(const char *, int); /* in lock.c */ + void _dlock(const char *, int); /* in lock.c */ + void _dunlock(const char *, int); /* in lock.c */ +#else + void r_dlock(); /* in lock.c */ + void r_dunlock() { dunlock(); } + void dlock() { P(m_mutex); } + void dunlock() { V(m_mutex); } +#endif + void dblock(int why); /* in lock.c */ + void dunblock(bool locked=false); /* in lock.c */ + void set_blocked(int block) { m_blocked = block; }; + int blocked() const { return m_blocked; }; + bool is_blocked() const { return m_blocked != BST_NOT_BLOCKED; }; + const char *print_blocked() const; /* in dev.c */ + private: bool do_mount(int mount, int timeout); /* in dev.c */ void set_mode(int omode); /* in dev.c */ diff --git a/bacula/src/stored/label.c b/bacula/src/stored/label.c index b52d77318a..19ca8badcd 100644 --- a/bacula/src/stored/label.c +++ b/bacula/src/stored/label.c @@ -755,7 +755,7 @@ bool write_session_label(DCR *dcr, int label) free_record(rec); Dmsg2(150, "Leave write_session_label Block=%ud File=%ud\n", - dev->get_block(), dev->get_file()); + dev->get_block_num(), dev->get_file()); return true; } diff --git a/bacula/src/stored/lock.c b/bacula/src/stored/lock.c index c57559dbf4..9b2a4ca1f8 100644 --- a/bacula/src/stored/lock.c +++ b/bacula/src/stored/lock.c @@ -43,14 +43,107 @@ const int dbglvl = 500; #endif -void DEVICE::block(int why) +/* + * + * The Storage daemon has three locking concepts that must be + * understood: + * + * 1. dblock blocking the device, which means that the device + * is "marked" in use. When setting and removing the + block, the device is locked, but after dblock is + called the device is unlocked. + * 2. dlock() simple mutex that locks the device structure. A dlock + * can be acquired while a device is blocked if it is not + * locked. + * 3. r_dlock "recursive" dlock, when means that a dlock (mutex) + * will be acquired on the device if it is not blocked + * by some other thread. If the device was blocked by + * the current thread, it will acquire the lock. + * If some other thread has set a block on the device, + * this call will wait until the device is unblocked. + * + * A lock is normally set when modifying the device structure. + * A r_lock is normally acquired when you want to block the device + * i.e. it will wait until the device is not blocked. + * A block is normally set during long operations like writing to + * the device. + * If you are writing the device, you will normally block and + * lock it. + * A lock cannot be violated. No other thread can touch the + * device while a lock is set. + * When a block is set, every thread accept the thread that set + * the block will block if r_dlock is called. + * A device can be blocked for multiple reasons, labeling, writing, + * acquiring (opening) the device, waiting for the operator, unmounted, + * ... + * Under certain conditions the block that is set on a device can be + * stolen and the device can be used by another thread. For example, + * a device is blocked because it is waiting for the operator to + * mount a tape. The operator can then unmount the device, and label + * a tape, re-mount it, give back the block, and the job will continue. + * + * + * Functions: + * + * DEVICE::dlock() does P(m_mutex) (in dev.h) + * DEVICE::dunlock() does V(m_mutex) + * + * DEVICE::dblock(why) does + * r_dlock(); (recursive device lock) + * block_device(this, why) + * r_dunlock() + * + * DEVICE::dunblock does + * dlock() + * unblock_device() + * dunlock() + * + * DEVICE::r_dlock() does recursive locking + * dlock() + * if blocked and not same thread that locked + * pthread_cond_wait + * leaves device locked + * + * DEVICE::r_dunlock() + * same as dunlock(); + * + * block_device() does (must be locked and not blocked at entry) + * set blocked status + * set our pid + * + * unblock_device() does (must be blocked at entry) + * (locked on entry) + * (locked on exit) + * set unblocked status + * clear pid + * if waiting threads + * pthread_cond_broadcast + * + * steal_device_lock() does (must be locked and blocked at entry) + * save status + * set new blocked status + * set new pid + * unlock() + * + * give_back_device_lock() does (must be blocked but not locked) + * dlock() + * reset blocked status + * save previous blocked + * reset pid + * if waiting threads + * pthread_cond_broadcast + * + */ + + +void DEVICE::dblock(int why) { r_dlock(); /* need recursive lock to block */ block_device(this, why); r_dunlock(); } -void DEVICE::unblock(bool locked) +void DEVICE::dunblock(bool locked) { if (!locked) { dlock(); @@ -103,17 +196,14 @@ void DEVICE::_r_dunlock(const char *file, int line) */ #ifdef SD_DEBUG_LOCK void DEVICE::_r_dlock(const char *file, int line) -#else -void DEVICE::r_dlock() -#endif { - int stat; -#ifdef SD_DEBUG_LOCK Dmsg4(sd_dbglvl+1, "r_dlock blked=%s from %s:%d JobId=%u\n", this->print_blocked(), file, line, get_jobid_from_tid()); #else - Dmsg1(sd_dbglvl, "reclock blked=%s\n", this->print_blocked()); +void DEVICE::r_dlock() +{ #endif + int stat; this->dlock(); if (this->blocked() && !pthread_equal(this->no_wait_id, pthread_self())) { this->num_waiting++; /* indicate that I am waiting */ @@ -216,6 +306,8 @@ const char *DEVICE::print_blocked() const return "BST_UNMOUNTED_WAITING_FOR_SYSOP"; case BST_MOUNT: return "BST_MOUNT"; + case BST_DESPOOLING: + return "BST_DESPOOLING"; default: return _("unknown blocked code"); } @@ -233,4 +325,3 @@ bool is_device_unmounted(DEVICE *dev) (blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP); return stat; } - diff --git a/bacula/src/stored/lock.h b/bacula/src/stored/lock.h new file mode 100644 index 0000000000..c49a24292b --- /dev/null +++ b/bacula/src/stored/lock.h @@ -0,0 +1,79 @@ +/* + Bacula® - The Network Backup Solution + + Copyright (C) 2000-2007 Free Software Foundation Europe e.V. + + The main author of Bacula is Kern Sibbald, with contributions from + many others, a complete list can be found in the file AUTHORS. + This program is Free Software; you can redistribute it and/or + modify it under the terms of version two of the GNU General Public + License as published by the Free Software Foundation and included + in the file LICENSE. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. + + Bacula® is a registered trademark of John Walker. + The licensor of Bacula is the Free Software Foundation Europe + (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, + Switzerland, email:ftf@fsfeurope.org. +*/ +/* + * Definitions for locking and blocking functions in the SD + * + * Kern Sibbald, pulled out of dev.h June 2007 + * + * Version $Id$ + * + */ + + +#ifndef __LOCK_H +#define __LOCK_H 1 + +#ifdef SD_DEBUG_LOCK +#define r_dlock() _r_dlock(__FILE__, __LINE__); /* in lock.c */ +#define r_dunlock() _r_dunlock(__FILE__, __LINE__); /* in lock.c */ +#define dlock() _dlock(__FILE__, __LINE__); /* in lock.c */ +#define dunlock() _dunlock(__FILE__, __LINE__); /* in lock.c */ +#endif + +#define block_device(d, s) _block_device(__FILE__, __LINE__, (d), s) +#define unblock_device(d) _unblock_device(__FILE__, __LINE__, (d)) +#define steal_device_lock(d, p, s) _steal_device_lock(__FILE__, __LINE__, (d), (p), s) +#define give_back_device_lock(d, p) _give_back_device_lock(__FILE__, __LINE__, (d), (p)) + +/* m_blocked states (mutually exclusive) */ +enum { + BST_NOT_BLOCKED = 0, /* not blocked */ + BST_UNMOUNTED, /* User unmounted device */ + BST_WAITING_FOR_SYSOP, /* Waiting for operator to mount tape */ + BST_DOING_ACQUIRE, /* Opening/validating/moving tape */ + BST_WRITING_LABEL, /* Labeling a tape */ + BST_UNMOUNTED_WAITING_FOR_SYSOP, /* User unmounted during wait for op */ + BST_MOUNT, /* Mount request */ + BST_DESPOOLING /* Despooling -- i.e. multiple writes */ +}; + +typedef struct s_steal_lock { + pthread_t no_wait_id; /* id of no wait thread */ + int dev_blocked; /* state */ + int dev_prev_blocked; /* previous blocked state */ +} bsteal_lock_t; + +/* + * Used in unblock() call + */ +enum { + dev_locked = true, + dev_unlocked = false +}; + +#endif diff --git a/bacula/src/stored/protos.h b/bacula/src/stored/protos.h index bbdf17b536..783241d30b 100644 --- a/bacula/src/stored/protos.h +++ b/bacula/src/stored/protos.h @@ -230,7 +230,7 @@ bool is_volume_in_use(DCR *dcr); void send_drive_reserve_messages(JCR *jcr, void sendit(const char *msg, int len, void *sarg), void *arg); bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx); int search_res_for_device(RCTX &rctx); -void release_msgs(JCR *jcr); +void release_reserve_messages(JCR *jcr); extern int reservations_lock_count; extern int vol_list_lock_count; diff --git a/bacula/src/stored/reserve.c b/bacula/src/stored/reserve.c index 1485111ca8..797a85c263 100644 --- a/bacula/src/stored/reserve.c +++ b/bacula/src/stored/reserve.c @@ -54,6 +54,7 @@ static bool reserve_device_for_read(DCR *dcr); static bool reserve_device_for_append(DCR *dcr, RCTX &rctx); static bool use_storage_cmd(JCR *jcr); static void queue_reserve_message(JCR *jcr); +static void pop_reserve_messages(JCR *jcr); /* Requests from the Director daemon */ static char use_storage[] = "use storage=%127s media_type=%127s " @@ -573,8 +574,6 @@ static bool use_storage_cmd(JCR *jcr) int Copy, Stripe; DIRSTORE *store; RCTX rctx; - char *msg; - alist *msgs; alist *dirstore; memset(&rctx, 0, sizeof(RCTX)); @@ -584,7 +583,7 @@ static bool use_storage_cmd(JCR *jcr) * use_device for each device that it wants to use. */ dirstore = New(alist(10, not_owned_by_alist)); - msgs = jcr->reserve_msgs = New(alist(10, not_owned_by_alist)); + jcr->reserve_msgs = New(alist(10, not_owned_by_alist)); do { Dmsg2(dbglvl, "jid=%u msg); ok = sscanf(dir->msg, use_storage, store_name.c_str(), @@ -664,9 +663,7 @@ static bool use_storage_cmd(JCR *jcr) lock_reservations(); for ( ; !fail && !job_canceled(jcr); ) { - while ((msg = (char *)msgs->pop())) { - free(msg); - } + pop_reserve_messages(jcr); rctx.suitable_device = false; rctx.have_volume = false; rctx.VolumeName[0] = 0; @@ -784,7 +781,7 @@ static bool use_storage_cmd(JCR *jcr) Dmsg2(dbglvl, "jid=%u >dird: %s", jid(), dir->msg); } - release_msgs(jcr); + release_reserve_messages(jcr); return ok; } @@ -1522,7 +1519,10 @@ bail_out: jcr->unlock(); } -void release_msgs(JCR *jcr) +/* + * Pop and release any reservations messages + */ +static void pop_reserve_messages(JCR *jcr) { alist *msgs; char *msg; @@ -1535,7 +1535,21 @@ void release_msgs(JCR *jcr) while ((msg = (char *)msgs->pop())) { free(msg); } - delete msgs; +bail_out: + jcr->unlock(); +} + +/* + * Also called from acquire.c + */ +void release_reserve_messages(JCR *jcr) +{ + pop_reserve_messages(jcr); + jcr->lock(); + if (!jcr->reserve_msgs) { + goto bail_out; + } + delete jcr->reserve_msgs; jcr->reserve_msgs = NULL; bail_out: diff --git a/bacula/src/stored/stored.h b/bacula/src/stored/stored.h index 03e067d0fe..d29f34cd5e 100644 --- a/bacula/src/stored/stored.h +++ b/bacula/src/stored/stored.h @@ -51,6 +51,7 @@ const int sd_dbglvl = 300; # endif # endif #endif +#include "lock.h" #include "block.h" #include "record.h" #include "dev.h" diff --git a/bacula/src/version.h b/bacula/src/version.h index 4a72952153..077c2ead8b 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -4,8 +4,8 @@ #undef VERSION #define VERSION "2.1.23" -#define BDATE "26 June 2007" -#define LSMDATE "26Jun07" +#define BDATE "28 June 2007" +#define LSMDATE "28Jun07" #define PROG_COPYRIGHT "Copyright (C) %d-2007 Free Software Foundation Europe e.V.\n" #define BYEAR "2007" /* year for copyright messages in progs */ -- 2.39.5