2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2017 Kern Sibbald
6 The original author of Bacula is Kern Sibbald, with contributions
7 from many others, a complete list can be found in the file AUTHORS.
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
17 Bacula(R) is a registered trademark of Kern Sibbald.
20 * Collection of Bacula Storage daemon locking software
22 * Kern Sibbald, June 2007
26 #include "bacula.h" /* pull in global headers */
27 #include "stored.h" /* pull in Storage Deamon headers */
30 const int dbglvl = 300;
32 const int dbglvl = 500;
38 * The Storage daemon has three locking concepts that must be
41 * 1. dblock blocking the device, which means that the device
42 * is "marked" in use. When setting and removing the
43 block, the device is locked, but after dblock is
44 called the device is unlocked.
45 * 2. Lock() simple mutex that locks the device structure. A Lock
46 * can be acquired while a device is blocked if it is not
48 * 3. rLock(locked) "recursive" Lock, when means that a Lock (mutex)
49 * will be acquired on the device if it is not blocked
50 * by some other thread. If the device was blocked by
51 * the current thread, it will acquire the lock.
52 * If some other thread has set a block on the device,
53 * this call will wait until the device is unblocked.
54 * Can be called with locked true, which means the
57 * A lock is normally set when modifying the device structure.
58 * A rLock is normally acquired when you want to block the device
59 * i.e. it will wait until the device is not blocked.
60 * A block is normally set during long operations like writing to
62 * If you are writing the device, you will normally block and
64 * A lock cannot be violated. No other thread can touch the
65 * device while a lock is set.
66 * When a block is set, every thread accept the thread that set
67 * the block will block if rLock is called.
68 * A device can be blocked for multiple reasons, labeling, writing,
69 * acquiring (opening) the device, waiting for the operator, unmounted,
71 * Under certain conditions the block that is set on a device can be
72 * stolen and the device can be used by another thread. For example,
73 * a device is blocked because it is waiting for the operator to
74 * mount a tape. The operator can then unmount the device, and label
75 * a tape, re-mount it, give back the block, and the job will continue.
80 * DEVICE::Lock() does P(m_mutex) (in dev.h)
81 * DEVICE::Unlock() does V(m_mutex)
83 * DEVICE::rLock(locked) allows locking the device when this thread
84 * already has the device blocked.
87 * if blocked and not same thread that locked
89 * leaves device locked
91 * DEVICE::rUnlock() unlocks but does not unblock
94 * DEVICE::dblock(why) does
95 * rLock(); (recursive device lock)
96 * block_device(this, why)
99 * DEVICE::dunblock does
104 * block_device() does (must be locked and not blocked at entry)
108 * unblock_device() does (must be blocked at entry)
111 * set unblocked status
114 * pthread_cond_broadcast
116 * steal_device_lock() does (must be locked and blocked at entry)
118 * set new blocked status
122 * give_back_device_lock() does (must be blocked but not locked)
124 * reset blocked status
125 * save previous blocked
128 * pthread_cond_broadcast
132 void DEVICE::dblock(int why)
134 rLock(false); /* need recursive lock to block */
135 block_device(this, why);
139 void DEVICE::dunblock(bool locked)
144 unblock_device(this);
151 * Debug DEVICE locks N.B.
155 #ifdef DEV_DEBUG_LOCK
157 void DEVICE::dbg_Lock(const char *file, int line)
159 Dmsg4(sd_dbglvl, "Lock %s from %s:%d precnt=%d\n", device->hdr.name, file, line, m_count);
160 bthread_mutex_lock_p(&m_mutex, file, line);
161 m_pid = pthread_self();
165 void DEVICE::dbg_Unlock(const char *file, int line)
168 clear_thread_id(m_pid);
169 Dmsg4(sd_dbglvl, "Unlock %s from %s:%d postcnt=%d\n", device->hdr.name, 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, "Enter rLock blked=%s from %s:%d\n", print_blocked(),
217 /* lockmgr version of P(m_mutex) */
218 Dmsg4(sd_dbglvl, "Lock %s in rLock %s from %s:%d\n",
219 device->hdr.name, print_blocked(), file, line);
220 bthread_mutex_lock_p(&m_mutex, file, line);
224 if (blocked() && !pthread_equal(no_wait_id, pthread_self())) {
225 num_waiting++; /* indicate that I am waiting */
229 /* thread id on Win32 may be a struct */
230 Dmsg5(sd_dbglvl, "Blocked by %d %s in rLock blked=%s no_wait=%p me=%p\n",
231 blocked_by, device->hdr.name, print_blocked(), no_wait_id, pthread_self());
233 if ((stat = bthread_cond_wait_p(&this->wait, &m_mutex, file, line)) != 0) {
235 this->dbg_Unlock(file, line);
236 Emsg1(M_ABORT, 0, _("pthread_cond_wait failure. ERR=%s\n"),
240 num_waiting--; /* no longer waiting */
243 #else /* DEV_DEBUG_LOCK */
245 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 Dmsg5(sd_dbglvl, "Blocked by %d rLock %s blked=%s no_wait=%p me=%p\n",
259 blocked_by, device->hdr.name, print_blocked(), 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 dev->blocked_by = get_jobid_from_tsd();
411 Dmsg4(sd_dbglvl, "Blocked %s %s from %s:%d\n",
412 dev->device->hdr.name, dev->print_blocked(), file, line);
416 * Unblock the device, and wake up anyone who went to sleep.
417 * Enter: device locked
418 * Exit: device locked
420 void _unblock_device(const char *file, int line, DEVICE *dev)
422 Dmsg4(sd_dbglvl, "Unblocked %s %s from %s:%d\n", dev->device->hdr.name,
423 dev->print_blocked(), file, line);
424 ASSERT2(dev->blocked(), "Unblock request of device not blocked");
425 dev->set_blocked(BST_NOT_BLOCKED);
427 clear_thread_id(dev->no_wait_id);
428 if (dev->num_waiting > 0) {
429 pthread_cond_broadcast(&dev->wait); /* wake them up */
434 * Enter with device locked and blocked
435 * Exit with device unlocked and blocked by us.
437 void _steal_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold, int state)
439 Dmsg4(sd_dbglvl, "Steal lock %s old=%s from %s:%d\n",
440 dev->device->hdr.name, dev->print_blocked(), file, line);
441 hold->dev_blocked = dev->blocked();
442 hold->dev_prev_blocked = dev->dev_prev_blocked;
443 hold->no_wait_id = dev->no_wait_id;
444 hold->blocked_by = dev->blocked_by;
445 dev->set_blocked(state);
446 Dmsg1(sd_dbglvl, "steal lock. new=%s\n", dev->print_blocked());
447 dev->no_wait_id = pthread_self();
448 dev->blocked_by = get_jobid_from_tsd();
453 * Enter with device blocked by us but not locked
454 * Exit with device locked, and blocked by previous owner
456 void _give_back_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold)
458 Dmsg4(sd_dbglvl, "Return lock %s old=%s from %s:%d\n",
459 dev->device->hdr.name, dev->print_blocked(), file, line);
461 dev->set_blocked(hold->dev_blocked);
462 dev->dev_prev_blocked = hold->dev_prev_blocked;
463 dev->no_wait_id = hold->no_wait_id;
464 dev->blocked_by = hold->blocked_by;
465 Dmsg1(sd_dbglvl, "return lock. new=%s\n", dev->print_blocked());
466 if (dev->num_waiting > 0) {
467 pthread_cond_broadcast(&dev->wait); /* wake them up */
471 const char *DEVICE::print_blocked() const
474 case BST_NOT_BLOCKED:
475 return "BST_NOT_BLOCKED";
477 return "BST_UNMOUNTED";
478 case BST_WAITING_FOR_SYSOP:
479 return "BST_WAITING_FOR_SYSOP";
480 case BST_DOING_ACQUIRE:
481 return "BST_DOING_ACQUIRE";
482 case BST_WRITING_LABEL:
483 return "BST_WRITING_LABEL";
484 case BST_UNMOUNTED_WAITING_FOR_SYSOP:
485 return "BST_UNMOUNTED_WAITING_FOR_SYSOP";
489 return "BST_DESPOOLING";
491 return "BST_RELEASING";
493 return _("unknown blocked code");
499 * Check if the device is blocked or not
501 bool DEVICE::is_device_unmounted()
506 stat = (blk == BST_UNMOUNTED) ||
507 (blk == BST_UNMOUNTED_WAITING_FOR_SYSOP);