2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2015 Kern Sibbald
5 Copyright (C) 2000-2014 Free Software Foundation Europe e.V.
7 The original author of Bacula is Kern Sibbald, with contributions
8 from many others, a complete list can be found in the file AUTHORS.
10 You may use this file and others of this release according to the
11 license defined in the LICENSE file, which includes the Affero General
12 Public License, v3.0 ("AGPLv3") and some additional permissions and
13 terms pursuant to its AGPLv3 Section 7.
15 This notice must be preserved when any source code is
16 conveyed and/or propagated.
18 Bacula(R) is a registered trademark of Kern Sibbald.
21 * Collection of Bacula Storage daemon locking software
23 * Kern Sibbald, June 2007
27 #include "bacula.h" /* pull in global headers */
28 #include "stored.h" /* pull in Storage Deamon headers */
31 const int dbglvl = 300;
33 const int dbglvl = 500;
39 * The Storage daemon has three locking concepts that must be
42 * 1. dblock blocking the device, which means that the device
43 * is "marked" in use. When setting and removing the
44 block, the device is locked, but after dblock is
45 called the device is unlocked.
46 * 2. Lock() simple mutex that locks the device structure. A Lock
47 * can be acquired while a device is blocked if it is not
49 * 3. rLock(locked) "recursive" Lock, when means that a Lock (mutex)
50 * will be acquired on the device if it is not blocked
51 * by some other thread. If the device was blocked by
52 * the current thread, it will acquire the lock.
53 * If some other thread has set a block on the device,
54 * this call will wait until the device is unblocked.
55 * Can be called with locked true, which means the
58 * A lock is normally set when modifying the device structure.
59 * A rLock is normally acquired when you want to block the device
60 * i.e. it will wait until the device is not blocked.
61 * A block is normally set during long operations like writing to
63 * If you are writing the device, you will normally block and
65 * A lock cannot be violated. No other thread can touch the
66 * device while a lock is set.
67 * When a block is set, every thread accept the thread that set
68 * the block will block if rLock is called.
69 * A device can be blocked for multiple reasons, labeling, writing,
70 * acquiring (opening) the device, waiting for the operator, unmounted,
72 * Under certain conditions the block that is set on a device can be
73 * stolen and the device can be used by another thread. For example,
74 * a device is blocked because it is waiting for the operator to
75 * mount a tape. The operator can then unmount the device, and label
76 * a tape, re-mount it, give back the block, and the job will continue.
81 * DEVICE::Lock() does P(m_mutex) (in dev.h)
82 * DEVICE::Unlock() does V(m_mutex)
84 * DEVICE::rLock(locked) allows locking the device when this thread
85 * already has the device blocked.
88 * if blocked and not same thread that locked
90 * leaves device locked
92 * DEVICE::rUnlock() unlocks but does not unblock
95 * DEVICE::dblock(why) does
96 * rLock(); (recursive device lock)
97 * block_device(this, why)
100 * DEVICE::dunblock does
105 * block_device() does (must be locked and not blocked at entry)
109 * unblock_device() does (must be blocked at entry)
112 * set unblocked status
115 * pthread_cond_broadcast
117 * steal_device_lock() does (must be locked and blocked at entry)
119 * set new blocked status
123 * give_back_device_lock() does (must be blocked but not locked)
125 * reset blocked status
126 * save previous blocked
129 * pthread_cond_broadcast
133 void DEVICE::dblock(int why)
135 rLock(false); /* need recursive lock to block */
136 block_device(this, why);
140 void DEVICE::dunblock(bool locked)
145 unblock_device(this);
152 * Debug DEVICE locks N.B.
156 #ifdef DEV_DEBUG_LOCK
158 void DEVICE::dbg_Lock(const char *file, int line)
160 Dmsg3(sd_dbglvl, "Lock from %s:%d precnt=%d\n", file, line, m_count);
161 bthread_mutex_lock_p(&m_mutex, file, line);
162 m_pid = pthread_self();
166 void DEVICE::dbg_Unlock(const char *file, int line)
169 Dmsg3(sd_dbglvl, "Unlock from %s:%d postcnt=%d\n", file, line, m_count);
170 bthread_mutex_unlock_p(&m_mutex, file, line);
173 void DEVICE::dbg_rUnlock(const char *file, int line)
175 Dmsg2(sd_dbglvl, "rUnlock from %s:%d\n", file, line);
176 dbg_Unlock(file, line);
187 void DEVICE::rUnlock()
197 void DEVICE::Unlock()
202 #endif /* DEV_DEBUG_LOCK */
205 * This is a recursive lock that checks if the device is blocked.
207 * When blocked is set, all threads EXCEPT thread with id no_wait_id
208 * must wait. The no_wait_id thread is out obtaining a new volume
209 * and preparing the label.
211 #ifdef DEV_DEBUG_LOCK
212 void DEVICE::dbg_rLock(const char *file, int line, bool locked)
214 Dmsg3(sd_dbglvl, "rLock blked=%s from %s:%d\n", print_blocked(),
218 /* lockmgr version of P(m_mutex) */
219 bthread_mutex_lock_p(&m_mutex, file, line);
223 if (blocked() && !pthread_equal(no_wait_id, pthread_self())) {
224 num_waiting++; /* indicate that I am waiting */
228 /* thread id on Win32 may be a struct */
229 Dmsg3(sd_dbglvl, "rLock blked=%s no_wait=%p me=%p\n", print_blocked(),
230 no_wait_id, pthread_self());
232 if ((stat = bthread_cond_wait_p(&this->wait, &m_mutex, file, line)) != 0) {
234 this->dbg_Unlock(file, line);
235 Emsg1(M_ABORT, 0, _("pthread_cond_wait failure. ERR=%s\n"),
239 num_waiting--; /* no longer waiting */
242 #else /* DEV_DEBUG_LOCK */
244 void DEVICE::rLock(bool locked)
252 if (blocked() && !pthread_equal(no_wait_id, pthread_self())) {
253 num_waiting++; /* indicate that I am waiting */
257 /* thread id on Win32 may be a struct */
258 Dmsg3(sd_dbglvl, "rLock blked=%s no_wait=%p me=%p\n", print_blocked(),
259 no_wait_id, pthread_self());
261 if ((stat = pthread_cond_wait(&this->wait, &m_mutex)) != 0) {
264 Emsg1(M_ABORT, 0, _("pthread_cond_wait failure. ERR=%s\n"),
268 num_waiting--; /* no longer waiting */
272 #endif /* DEV_DEBUG_LOCK */
276 void DEVICE::dbg_Lock_acquire(const char *file, int line)
278 Dmsg2(sd_dbglvl, "Lock_acquire from %s:%d\n", file, line);
279 bthread_mutex_lock_p(&acquire_mutex, file, line);
282 void DEVICE::dbg_Unlock_acquire(const char *file, int line)
284 Dmsg2(sd_dbglvl, "Unlock_acquire from %s:%d\n", file, line);
285 bthread_mutex_unlock_p(&acquire_mutex, file, line);
288 void DEVICE::dbg_Lock_read_acquire(const char *file, int line)
290 Dmsg2(sd_dbglvl, "Lock_read_acquire from %s:%d\n", file, line);
291 bthread_mutex_lock_p(&read_acquire_mutex, file, line);
294 void DEVICE::dbg_Unlock_read_acquire(const char *file, int line)
296 Dmsg2(sd_dbglvl, "Unlock_read_acquire from %s:%d\n", file, line);
297 bthread_mutex_unlock_p(&read_acquire_mutex, file, line);
300 void DEVICE::dbg_Lock_VolCatInfo(const char *file, int line)
302 bthread_mutex_lock_p(&volcat_mutex, file, line);
305 void DEVICE::dbg_Unlock_VolCatInfo(const char *file, int line)
307 bthread_mutex_unlock_p(&volcat_mutex, file, line);
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);
332 void DEVICE::Lock_VolCatInfo()
337 void DEVICE::Unlock_VolCatInfo()
346 /* Main device access control */
347 int DEVICE::init_mutex()
349 return pthread_mutex_init(&m_mutex, NULL);
352 /* Mutex around the freespace command */
353 int DEVICE::init_freespace_mutex()
355 return pthread_mutex_init(&freespace_mutex, NULL);
358 /* Write device acquire mutex */
359 int DEVICE::init_acquire_mutex()
361 return pthread_mutex_init(&acquire_mutex, NULL);
364 /* Read device acquire mutex */
365 int DEVICE::init_read_acquire_mutex()
367 return pthread_mutex_init(&read_acquire_mutex, NULL);
370 /* VolCatInfo mutex */
371 int DEVICE::init_volcat_mutex()
373 return pthread_mutex_init(&volcat_mutex, NULL);
377 int DEVICE::init_dcrs_mutex()
379 return pthread_mutex_init(&dcrs_mutex, NULL);
382 /* Set order in which device locks must be acquired */
383 void DEVICE::set_mutex_priorities()
385 /* Ensure that we respect this order in P/V operations */
386 bthread_mutex_set_priority(&m_mutex, PRIO_SD_DEV_ACCESS);
387 bthread_mutex_set_priority(&spool_mutex, PRIO_SD_DEV_SPOOL);
388 bthread_mutex_set_priority(&acquire_mutex, PRIO_SD_DEV_ACQUIRE);
391 int DEVICE::next_vol_timedwait(const struct timespec *timeout)
393 return pthread_cond_timedwait(&wait_next_vol, &m_mutex, timeout);
398 * Block all other threads from using the device
399 * Device must already be locked. After this call,
400 * the device is blocked to any thread calling dev->rLock(),
401 * but the device is not locked (i.e. no P on device). Also,
402 * the current thread can do slip through the dev->rLock()
403 * calls without blocking.
405 void _block_device(const char *file, int line, DEVICE *dev, int state)
407 ASSERT2(dev->blocked() == BST_NOT_BLOCKED, "Block request of device already blocked");
408 dev->set_blocked(state); /* make other threads wait */
409 dev->no_wait_id = pthread_self(); /* allow us to continue */
410 Dmsg3(sd_dbglvl, "set blocked=%s from %s:%d\n", dev->print_blocked(), file, line);
414 * Unblock the device, and wake up anyone who went to sleep.
415 * Enter: device locked
416 * Exit: device locked
418 void _unblock_device(const char *file, int line, DEVICE *dev)
420 Dmsg3(sd_dbglvl, "unblock %s from %s:%d\n", dev->print_blocked(), file, line);
421 ASSERT2(dev->blocked(), "Unblock request of device not blocked");
422 dev->set_blocked(BST_NOT_BLOCKED);
423 clear_thread_id(dev->no_wait_id);
424 if (dev->num_waiting > 0) {
425 pthread_cond_broadcast(&dev->wait); /* wake them up */
430 * Enter with device locked and blocked
431 * Exit with device unlocked and blocked by us.
433 void _steal_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold, int state)
435 Dmsg3(sd_dbglvl, "steal lock. old=%s from %s:%d\n", dev->print_blocked(),
437 hold->dev_blocked = dev->blocked();
438 hold->dev_prev_blocked = dev->dev_prev_blocked;
439 hold->no_wait_id = dev->no_wait_id;
440 dev->set_blocked(state);
441 Dmsg1(sd_dbglvl, "steal lock. new=%s\n", dev->print_blocked());
442 dev->no_wait_id = pthread_self();
447 * Enter with device blocked by us but not locked
448 * Exit with device locked, and blocked by previous owner
450 void _give_back_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold)
452 Dmsg3(sd_dbglvl, "return lock. old=%s from %s:%d\n",
453 dev->print_blocked(), file, line);
455 dev->set_blocked(hold->dev_blocked);
456 dev->dev_prev_blocked = hold->dev_prev_blocked;
457 dev->no_wait_id = hold->no_wait_id;
458 Dmsg1(sd_dbglvl, "return lock. new=%s\n", dev->print_blocked());
459 if (dev->num_waiting > 0) {
460 pthread_cond_broadcast(&dev->wait); /* wake them up */
464 const char *DEVICE::print_blocked() const
467 case BST_NOT_BLOCKED:
468 return "BST_NOT_BLOCKED";
470 return "BST_UNMOUNTED";
471 case BST_WAITING_FOR_SYSOP:
472 return "BST_WAITING_FOR_SYSOP";
473 case BST_DOING_ACQUIRE:
474 return "BST_DOING_ACQUIRE";
475 case BST_WRITING_LABEL:
476 return "BST_WRITING_LABEL";
477 case BST_UNMOUNTED_WAITING_FOR_SYSOP:
478 return "BST_UNMOUNTED_WAITING_FOR_SYSOP";
482 return "BST_DESPOOLING";
484 return "BST_RELEASING";
486 return _("unknown blocked code");
492 * Check if the device is blocked or not
494 bool DEVICE::is_device_unmounted()
499 stat = (blk == BST_UNMOUNTED) ||
500 (blk == BST_UNMOUNTED_WAITING_FOR_SYSOP);