2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2012 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version three of the GNU Affero General Public
10 License as published by the Free Software Foundation and included
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU Affero General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of Kern Sibbald.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
29 * Collection of Bacula Storage daemon locking software
31 * Kern Sibbald, June 2007
35 #include "bacula.h" /* pull in global headers */
36 #include "stored.h" /* pull in Storage Deamon headers */
41 const int dbglvl = 500;
47 * The Storage daemon has three locking concepts that must be
50 * 1. dblock blocking the device, which means that the device
51 * is "marked" in use. When setting and removing the
52 block, the device is locked, but after dblock is
53 called the device is unlocked.
54 * 2. Lock() simple mutex that locks the device structure. A Lock
55 * can be acquired while a device is blocked if it is not
57 * 3. rLock(locked) "recursive" Lock, when means that a Lock (mutex)
58 * will be acquired on the device if it is not blocked
59 * by some other thread. If the device was blocked by
60 * the current thread, it will acquire the lock.
61 * If some other thread has set a block on the device,
62 * this call will wait until the device is unblocked.
63 * Can be called with locked true, which means the
66 * A lock is normally set when modifying the device structure.
67 * A rLock is normally acquired when you want to block the device
68 * i.e. it will wait until the device is not blocked.
69 * A block is normally set during long operations like writing to
71 * If you are writing the device, you will normally block and
73 * A lock cannot be violated. No other thread can touch the
74 * device while a lock is set.
75 * When a block is set, every thread accept the thread that set
76 * the block will block if rLock is called.
77 * A device can be blocked for multiple reasons, labeling, writing,
78 * acquiring (opening) the device, waiting for the operator, unmounted,
80 * Under certain conditions the block that is set on a device can be
81 * stolen and the device can be used by another thread. For example,
82 * a device is blocked because it is waiting for the operator to
83 * mount a tape. The operator can then unmount the device, and label
84 * a tape, re-mount it, give back the block, and the job will continue.
89 * DEVICE::Lock() does P(m_mutex) (in dev.h)
90 * DEVICE::Unlock() does V(m_mutex)
92 * DEVICE::rLock(locked) allows locking the device when this thread
93 * already has the device blocked.
96 * if blocked and not same thread that locked
98 * leaves device locked
100 * DEVICE::rUnlock() unlocks but does not unblock
103 * DEVICE::dblock(why) does
104 * rLock(); (recursive device lock)
105 * block_device(this, why)
108 * DEVICE::dunblock does
113 * block_device() does (must be locked and not blocked at entry)
117 * unblock_device() does (must be blocked at entry)
120 * set unblocked status
123 * pthread_cond_broadcast
125 * steal_device_lock() does (must be locked and blocked at entry)
127 * set new blocked status
131 * give_back_device_lock() does (must be blocked but not locked)
133 * reset blocked status
134 * save previous blocked
137 * pthread_cond_broadcast
141 void DEVICE::dblock(int why)
143 rLock(false); /* need recursive lock to block */
144 block_device(this, why);
148 void DEVICE::dunblock(bool locked)
153 unblock_device(this);
161 * Debug DCR locks N.B.
164 void DCR::dbg_mLock(const char *file, int line, bool locked)
167 if (is_dev_locked()) {
171 Dmsg3(sd_dbglvl, "mLock %d from %s:%d\n", locked, file, line);
172 dev->dbg_rLock(file,line,locked);
178 void DCR::dbg_mUnlock(const char *file, int line)
180 Dmsg2(sd_dbglvl, "mUnlock from %s:%d\n", file, line);
182 if (!is_dev_locked()) {
184 ASSERT2(0, "Call on dcr mUnlock when not locked");
188 /* When the count goes to zero, unlock it */
189 if (!is_dev_locked()) {
190 dev->dbg_rUnlock(file,line);
197 * Debug DEVICE locks N.B.
200 void DEVICE::dbg_Lock(const char *file, int line)
202 Dmsg3(sd_dbglvl, "Lock from %s:%d precnt=%d\n", file, line, m_count);
203 /* Note, this *really* should be protected by a mutex, but
204 * since it is only debug code we don't worry too much.
206 if (m_count > 0 && pthread_equal(m_pid, pthread_self())) {
207 Dmsg4(sd_dbglvl, "Possible DEADLOCK!! lock held by JobId=%u from %s:%d m_count=%d\n",
208 get_jobid_from_tid(m_pid),
209 file, line, m_count);
211 bthread_mutex_lock_p(&m_mutex, file, line);
212 m_pid = pthread_self();
216 void DEVICE::dbg_Unlock(const char *file, int line)
219 Dmsg3(sd_dbglvl, "Unlock from %s:%d postcnt=%d\n", file, line, m_count);
220 bthread_mutex_unlock_p(&m_mutex, file, line);
223 void DEVICE::dbg_rUnlock(const char *file, int line)
225 Dmsg2(sd_dbglvl, "rUnlock from %s:%d\n", file, line);
226 dbg_Unlock(file, line);
229 void DEVICE::dbg_Lock_acquire(const char *file, int line)
231 Dmsg2(sd_dbglvl, "Lock_acquire from %s:%d\n", file, line);
232 bthread_mutex_lock_p(&acquire_mutex, file, line);
235 void DEVICE::dbg_Unlock_acquire(const char *file, int line)
237 Dmsg2(sd_dbglvl, "Unlock_acquire from %s:%d\n", file, line);
238 bthread_mutex_unlock_p(&acquire_mutex, file, line);
241 void DEVICE::dbg_Lock_read_acquire(const char *file, int line)
243 Dmsg2(sd_dbglvl, "Lock_read_acquire from %s:%d\n", file, line);
244 bthread_mutex_lock_p(&read_acquire_mutex, file, line);
247 void DEVICE::dbg_Unlock_read_acquire(const char *file, int line)
249 Dmsg2(sd_dbglvl, "Unlock_read_acquire from %s:%d\n", file, line);
250 bthread_mutex_unlock_p(&read_acquire_mutex, file, line);
260 /* Multiple rLock implementation */
261 void DCR::mLock(bool locked)
264 if (is_dev_locked()) {
274 /* Multiple rUnlock implementation */
278 if (!is_dev_locked()) {
280 ASSERT2(0, "Call on dcr mUnlock when not locked");
284 /* When the count goes to zero, unlock it */
285 if (!is_dev_locked()) {
297 void DEVICE::rUnlock()
307 void DEVICE::Unlock()
312 void DEVICE::Lock_acquire()
317 void DEVICE::Unlock_acquire()
322 void DEVICE::Lock_read_acquire()
324 P(read_acquire_mutex);
327 void DEVICE::Unlock_read_acquire()
329 V(read_acquire_mutex);
334 /* Main device access control */
335 int DEVICE::init_mutex()
337 return pthread_mutex_init(&m_mutex, NULL);
340 /* Write device acquire mutex */
341 int DEVICE::init_acquire_mutex()
343 return pthread_mutex_init(&acquire_mutex, NULL);
346 /* Read device acquire mutex */
347 int DEVICE::init_read_acquire_mutex()
349 return pthread_mutex_init(&read_acquire_mutex, NULL);
352 /* Set order in which device locks must be acquired */
353 void DEVICE::set_mutex_priorities()
355 /* Ensure that we respect this order in P/V operations */
356 bthread_mutex_set_priority(&m_mutex, PRIO_SD_DEV_ACCESS);
357 bthread_mutex_set_priority(&spool_mutex, PRIO_SD_DEV_SPOOL);
358 bthread_mutex_set_priority(&acquire_mutex, PRIO_SD_DEV_ACQUIRE);
361 int DEVICE::next_vol_timedwait(const struct timespec *timeout)
363 return pthread_cond_timedwait(&wait_next_vol, &m_mutex, timeout);
368 * This is a recursive lock that checks if the device is blocked.
370 * When blocked is set, all threads EXCEPT thread with id no_wait_id
371 * must wait. The no_wait_id thread is out obtaining a new volume
372 * and preparing the label.
375 void DEVICE::dbg_rLock(const char *file, int line, bool locked)
377 Dmsg3(sd_dbglvl, "rLock blked=%s from %s:%d\n", print_blocked(),
380 /* lockmgr version of P(m_mutex) */
381 bthread_mutex_lock_p(&m_mutex, file, line);
385 void DEVICE::rLock(bool locked)
393 if (blocked() && !pthread_equal(no_wait_id, pthread_self())) {
394 num_waiting++; /* indicate that I am waiting */
398 /* thread id on Win32 may be a struct */
399 Dmsg3(sd_dbglvl, "rLock blked=%s no_wait=%p me=%p\n", print_blocked(),
400 no_wait_id, pthread_self());
402 if ((stat = pthread_cond_wait(&this->wait, &m_mutex)) != 0) {
405 Emsg1(M_ABORT, 0, _("pthread_cond_wait failure. ERR=%s\n"),
409 num_waiting--; /* no longer waiting */
414 * Block all other threads from using the device
415 * Device must already be locked. After this call,
416 * the device is blocked to any thread calling dev->rLock(),
417 * but the device is not locked (i.e. no P on device). Also,
418 * the current thread can do slip through the dev->rLock()
419 * calls without blocking.
421 void _block_device(const char *file, int line, DEVICE *dev, int state)
423 // ASSERT(lmgr_mutex_is_locked(&dev->m_mutex) == 1);
424 ASSERT(dev->blocked() == BST_NOT_BLOCKED);
425 dev->set_blocked(state); /* make other threads wait */
426 dev->no_wait_id = pthread_self(); /* allow us to continue */
427 Dmsg3(sd_dbglvl, "set blocked=%s from %s:%d\n", dev->print_blocked(), file, line);
431 * Unblock the device, and wake up anyone who went to sleep.
432 * Enter: device locked
433 * Exit: device locked
435 void _unblock_device(const char *file, int line, DEVICE *dev)
437 Dmsg3(sd_dbglvl, "unblock %s from %s:%d\n", dev->print_blocked(), file, line);
438 // ASSERT(lmgr_mutex_is_locked(&dev->m_mutex) == 1);
439 ASSERT(dev->blocked());
440 dev->set_blocked(BST_NOT_BLOCKED);
441 clear_thread_id(dev->no_wait_id);
442 if (dev->num_waiting > 0) {
443 pthread_cond_broadcast(&dev->wait); /* wake them up */
448 * Enter with device locked and blocked
449 * Exit with device unlocked and blocked by us.
451 void _steal_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold, int state)
453 Dmsg3(sd_dbglvl, "steal lock. old=%s from %s:%d\n", dev->print_blocked(),
455 hold->dev_blocked = dev->blocked();
456 hold->dev_prev_blocked = dev->dev_prev_blocked;
457 hold->no_wait_id = dev->no_wait_id;
458 dev->set_blocked(state);
459 Dmsg1(sd_dbglvl, "steal lock. new=%s\n", dev->print_blocked());
460 dev->no_wait_id = pthread_self();
465 * Enter with device blocked by us but not locked
466 * Exit with device locked, and blocked by previous owner
468 void _give_back_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold)
470 Dmsg3(sd_dbglvl, "return lock. old=%s from %s:%d\n",
471 dev->print_blocked(), file, line);
473 dev->set_blocked(hold->dev_blocked);
474 dev->dev_prev_blocked = hold->dev_prev_blocked;
475 dev->no_wait_id = hold->no_wait_id;
476 Dmsg1(sd_dbglvl, "return lock. new=%s\n", dev->print_blocked());
477 if (dev->num_waiting > 0) {
478 pthread_cond_broadcast(&dev->wait); /* wake them up */
482 const char *DEVICE::print_blocked() const
485 case BST_NOT_BLOCKED:
486 return "BST_NOT_BLOCKED";
488 return "BST_UNMOUNTED";
489 case BST_WAITING_FOR_SYSOP:
490 return "BST_WAITING_FOR_SYSOP";
491 case BST_DOING_ACQUIRE:
492 return "BST_DOING_ACQUIRE";
493 case BST_WRITING_LABEL:
494 return "BST_WRITING_LABEL";
495 case BST_UNMOUNTED_WAITING_FOR_SYSOP:
496 return "BST_UNMOUNTED_WAITING_FOR_SYSOP";
500 return "BST_DESPOOLING";
502 return "BST_RELEASING";
504 return _("unknown blocked code");
510 * Check if the device is blocked or not
512 bool DEVICE::is_device_unmounted()
517 stat = (blk == BST_UNMOUNTED) ||
518 (blk == BST_UNMOUNTED_WAITING_FOR_SYSOP);