1 /*
2 BAREOS® - Backup Archiving REcovery Open Sourced
3
4 Copyright (C) 2000-2012 Free Software Foundation Europe e.V.
5 Copyright (C) 2016-2016 Bareos GmbH & Co. KG
6
7 This program is Free Software; you can redistribute it and/or
8 modify it under the terms of version three of the GNU Affero General Public
9 License as published by the Free Software Foundation and included
10 in the file LICENSE.
11
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Affero General Public License for more details.
16
17 You should have received a copy of the GNU Affero General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 02110-1301, USA.
21 */
22 /*
23 * Kern Sibbald, June 2007
24 */
25 /*+
26 * @file
27 * Collection of Bacula Storage daemon locking software
28 */
29
30 #include "include/bareos.h" /* pull in global headers */
31 #include "stored/stored.h" /* pull in Storage Daemon headers */
32 #include "lib/edit.h"
33
34 namespace storagedaemon {
35
36 /**
37 * The Storage daemon has three locking concepts that must be understood:
38 *
39 * 1. dblock blocking the device, which means that the device
40 * is "marked" in use. When setting and removing the
41 * block, the device is locked, but after dblock is
42 * called the device is unlocked.
43 * 2. Lock() simple mutex that locks the device structure. A Lock
44 * can be acquired while a device is blocked if it is not
45 * locked.
46 * 3. rLock(locked) "recursive" Lock, when means that a Lock (mutex)
47 * will be acquired on the device if it is not blocked
48 * by some other thread. If the device was blocked by
49 * the current thread, it will acquire the lock.
50 * If some other thread has set a block on the device,
51 * this call will wait until the device is unblocked.
52 * Can be called with locked true, which means the
53 * Lock is already set
54 *
55 * - A lock is normally set when modifying the device structure.
56 * - A rLock is normally acquired when you want to block the device
57 * i.e. it will wait until the device is not blocked.
58 * - A block is normally set during long operations like writing to the device.
59 * - If you are writing the device, you will normally block and lock it.
60 * - A lock cannot be violated. No other thread can touch the
61 * device while a lock is set.
62 * - When a block is set, every thread accept the thread that set
63 * the block will block if rLock is called.
64 * - A device can be blocked for multiple reasons, labeling, writing,
65 * acquiring (opening) the device, waiting for the operator, unmounted,
66 * ...
67 *
68 * Under certain conditions the block that is set on a device can be
69 * stolen and the device can be used by another thread. For example,
70 * a device is blocked because it is waiting for the operator to
71 * mount a tape. The operator can then unmount the device, and label
72 * a tape, re-mount it, give back the block, and the job will continue.
73 *
74 * Functions:
75 *
76 * Device::Lock() does P(mutex_) (in dev.h)
77 * Device::Unlock() does V(mutex_)
78 *
79 * Device::rLock(locked) allows locking the device when this thread
80 * already has the device blocked.
81 * - if (!locked)
82 * Lock()
83 * - if blocked and not same thread that locked
84 * pthread_cond_wait
85 * - leaves device locked
86 *
87 * Device::rUnlock() Unlocks but does not unblock same as Unlock();
88 *
89 * Device::dblock(why) does
90 * - rLock(); (recursive device lock)
91 * - BlockDevice(this, why)
92 * - rUnlock()
93 *
94 * Device::dunblock does
95 * - Lock()
96 * - UnblockDevice()
97 * - Unlock()
98 *
99 * BlockDevice() does (must be locked and not blocked at entry)
100 * - set blocked status
101 * - set our pid
102 *
103 * UnblockDevice() does (must be blocked at entry)
104 * - (locked on entry)
105 * - (locked on exit)
106 * - set unblocked status
107 * - clear pid
108 * - if waiting threads
109 * pthread_cond_broadcast
110 *
111 * StealDeviceLock() does (must be locked and blocked at entry)
112 * - save status
113 * - set new blocked status
114 * - set new pid
115 * - Unlock()
116 *
117 * GiveBackDeviceLock() does (must be blocked but not locked)
118 * - Lock()
119 * - reset blocked status
120 * - save previous blocked
121 * - reset pid
122 * - if waiting threads
123 * pthread_cond_broadcast
124 */
dblock(int why)125 void Device::dblock(int why)
126 {
127 rLock(false); /* need recursive lock to block */
128 BlockDevice(this, why);
129 rUnlock();
130 }
131
dunblock(bool locked)132 void Device::dunblock(bool locked)
133 {
134 if (!locked) {
135 Lock();
136 }
137 UnblockDevice(this);
138 Unlock();
139 }
140
141 #ifdef SD_DEBUG_LOCK
142 /**
143 * Debug DeviceControlRecord locks N.B.
144 *
145 */
dbg_mLock(const char * file,int line,bool locked)146 void DeviceControlRecord::dbg_mLock(const char *file, int line, bool locked)
147 {
148 real_P(r_mutex);
149 if (IsDevLocked()) {
150 real_V(r_mutex);
151 return;
152 }
153 Dmsg3(sd_debuglevel, "mLock %d from %s:%d\n", locked, file, line);
154 dev->dbg_rLock(file,line,locked);
155 IncDevLock();
156 real_V(r_mutex);
157 return;
158 }
159
dbg_mUnlock(const char * file,int line)160 void DeviceControlRecord::dbg_mUnlock(const char *file, int line)
161 {
162 Dmsg2(sd_debuglevel, "mUnlock from %s:%d\n", file, line);
163 real_P(r_mutex);
164 if (!IsDevLocked()) {
165 real_P(r_mutex);
166 ASSERT2(0, "Call on dcr mUnlock when not locked");
167 return;
168 }
169 DecDevLock();
170 /* When the count goes to zero, unlock it */
171 if (!IsDevLocked()) {
172 dev->dbg_rUnlock(file,line);
173 }
174 real_V(r_mutex);
175 return;
176 }
177
178 /**
179 * Debug Device locks N.B.
180 *
181 */
dbg_Lock(const char * file,int line)182 void Device::dbg_Lock(const char *file, int line)
183 {
184 Dmsg3(sd_debuglevel, "Lock from %s:%d precnt=%d\n", file, line, count_);
185 /* Note, this *really* should be protected by a mutex, but
186 * since it is only debug code we don't worry too much.
187 */
188 if (count_ > 0 && pthread_equal(pid_, pthread_self())) {
189 Dmsg4(sd_debuglevel, "Possible DEADLOCK!! lock held by JobId=%u from %s:%d count_=%d\n",
190 GetJobidFromTid(pid_),
191 file, line, count_);
192 }
193 BthreadMutexLock_p(&mutex_, file, line);
194 pid_ = pthread_self();
195 count_++;
196 }
197
dbg_Unlock(const char * file,int line)198 void Device::dbg_Unlock(const char *file, int line)
199 {
200 count_--;
201 Dmsg3(sd_debuglevel, "Unlock from %s:%d postcnt=%d\n", file, line, count_);
202 BthreadMutexUnlock_p(&mutex_, file, line);
203 }
204
dbg_rUnlock(const char * file,int line)205 void Device::dbg_rUnlock(const char *file, int line)
206 {
207 Dmsg2(sd_debuglevel, "rUnlock from %s:%d\n", file, line);
208 dbg_Unlock(file, line);
209 }
210
dbg_Lock_acquire(const char * file,int line)211 void Device::dbg_Lock_acquire(const char *file, int line)
212 {
213 Dmsg2(sd_debuglevel, "Lock_acquire from %s:%d\n", file, line);
214 BthreadMutexLock_p(&acquire_mutex, file, line);
215 }
216
dbg_Unlock_acquire(const char * file,int line)217 void Device::dbg_Unlock_acquire(const char *file, int line)
218 {
219 Dmsg2(sd_debuglevel, "Unlock_acquire from %s:%d\n", file, line);
220 BthreadMutexUnlock_p(&acquire_mutex, file, line);
221 }
222
dbg_Lock_read_acquire(const char * file,int line)223 void Device::dbg_Lock_read_acquire(const char *file, int line)
224 {
225 Dmsg2(sd_debuglevel, "Lock_read_acquire from %s:%d\n", file, line);
226 BthreadMutexLock_p(&read_acquire_mutex, file, line);
227 }
228
dbg_Unlock_read_acquire(const char * file,int line)229 void Device::dbg_Unlock_read_acquire(const char *file, int line)
230 {
231 Dmsg2(sd_debuglevel, "Unlock_read_acquire from %s:%d\n", file, line);
232 BthreadMutexUnlock_p(&read_acquire_mutex, file, line);
233 }
234
235 #else
236
237 /**
238 * DeviceControlRecord locks N.B.
239 */
240 /**
241 * Multiple rLock implementation
242 */
mLock(bool locked)243 void DeviceControlRecord::mLock(bool locked)
244 {
245 P(r_mutex);
246 if (IsDevLocked()) {
247 V(r_mutex);
248 return;
249 }
250 dev->rLock(locked);
251 IncDevLock();
252 V(r_mutex);
253 return;
254 }
255
256 /**
257 * Multiple rUnlock implementation
258 */
mUnlock()259 void DeviceControlRecord::mUnlock()
260 {
261 P(r_mutex);
262 if (!IsDevLocked()) {
263 V(r_mutex);
264 ASSERT2(0, "Call on dcr mUnlock when not locked");
265 return;
266 }
267 DecDevLock();
268 /*
269 * When the count goes to zero, unlock it
270 */
271 if (!IsDevLocked()) {
272 dev->rUnlock();
273 }
274 V(r_mutex);
275 return;
276 }
277
278 /**
279 * Device locks N.B.
280 */
rUnlock()281 void Device::rUnlock()
282 {
283 Unlock();
284 }
285
Lock()286 void Device::Lock()
287 {
288 P(mutex_);
289 }
290
Unlock()291 void Device::Unlock()
292 {
293 V(mutex_);
294 }
295
Lock_acquire()296 void Device::Lock_acquire()
297 {
298 P(acquire_mutex);
299 }
300
Unlock_acquire()301 void Device::Unlock_acquire()
302 {
303 V(acquire_mutex);
304 }
305
Lock_read_acquire()306 void Device::Lock_read_acquire()
307 {
308 P(read_acquire_mutex);
309 }
310
Unlock_read_acquire()311 void Device::Unlock_read_acquire()
312 {
313 V(read_acquire_mutex);
314 }
315
316 #endif
317
318 /**
319 * Main device access control
320 */
InitMutex()321 int Device::InitMutex()
322 {
323 return pthread_mutex_init(&mutex_, NULL);
324 }
325
326 /**
327 * Write device acquire mutex
328 */
InitAcquireMutex()329 int Device::InitAcquireMutex()
330 {
331 return pthread_mutex_init(&acquire_mutex, NULL);
332 }
333
334 /**
335 * Read device acquire mutex
336 */
InitReadAcquireMutex()337 int Device::InitReadAcquireMutex()
338 {
339 return pthread_mutex_init(&read_acquire_mutex, NULL);
340 }
341
342 /**
343 * Set order in which device locks must be acquired
344 */
SetMutexPriorities()345 void Device::SetMutexPriorities()
346 {
347 /*
348 * Ensure that we respect this order in P/V operations
349 */
350 BthreadMutexSetPriority(&mutex_, PRIO_SD_DEV_ACCESS);
351 BthreadMutexSetPriority(&spool_mutex, PRIO_SD_DEV_SPOOL);
352 BthreadMutexSetPriority(&acquire_mutex, PRIO_SD_DEV_ACQUIRE);
353 }
354
NextVolTimedwait(const struct timespec * timeout)355 int Device::NextVolTimedwait(const struct timespec *timeout)
356 {
357 return pthread_cond_timedwait(&wait_next_vol, &mutex_, timeout);
358 }
359
360 /**
361 * This is a recursive lock that checks if the device is blocked.
362 *
363 * When blocked is set, all threads EXCEPT thread with id no_wait_id
364 * must wait. The no_wait_id thread is out obtaining a new volume
365 * and preparing the label.
366 */
367 #ifdef SD_DEBUG_LOCK
dbg_rLock(const char * file,int line,bool locked)368 void Device::dbg_rLock(const char *file, int line, bool locked)
369 {
370 Dmsg3(sd_debuglevel, "rLock blked=%s from %s:%d\n", print_blocked(),
371 file, line);
372 if (!locked) {
373 /*
374 * lockmgr version of P(mutex_)
375 */
376 BthreadMutexLock_p(&mutex_, file, line);
377 count_++;
378 }
379 #else
380 void Device::rLock(bool locked)
381 {
382 if (!locked) {
383 Lock();
384 count_++;
385 }
386 #endif
387
388 if (blocked() && !pthread_equal(no_wait_id, pthread_self())) {
389 num_waiting++; /* indicate that I am waiting */
390 while (blocked()) {
391 int status;
392 char ed1[50], ed2[50];
393
394 Dmsg3(sd_debuglevel, "rLock blked=%s no_wait=%s me=%s\n",
395 print_blocked(),
396 edit_pthread(no_wait_id, ed1, sizeof(ed1)),
397 edit_pthread(pthread_self(), ed2, sizeof(ed2)));
398 if ((status = pthread_cond_wait(&wait, &mutex_)) != 0) {
399 BErrNo be;
400 this->Unlock();
401 Emsg1(M_ABORT, 0, _("pthread_cond_wait failure. ERR=%s\n"),
402 be.bstrerror(status));
403 }
404 }
405 num_waiting--; /* no longer waiting */
406 }
407 }
408
409 /**
410 * Block all other threads from using the device
411 *
412 * Device must already be locked. After this call,
413 * the device is blocked to any thread calling dev->rLock(),
414 * but the device is not locked (i.e. no P on device). Also,
415 * the current thread can do slip through the dev->rLock()
416 * calls without blocking.
417 */
418 void _blockDevice(const char *file, int line, Device *dev, int state)
419 {
420 // ASSERT(LmgrMutexIsLocked(&dev->mutex_) == 1);
421 ASSERT(dev->blocked() == BST_NOT_BLOCKED);
422 dev->SetBlocked(state); /* make other threads wait */
423 dev->no_wait_id = pthread_self(); /* allow us to continue */
424 Dmsg3(sd_debuglevel, "set blocked=%s from %s:%d\n", dev->print_blocked(), file, line);
425 }
426
427 /**
428 * Unblock the device, and wake up anyone who went to sleep.
429 * Enter: device locked
430 * Exit: device locked
431 */
432 void _unBlockDevice(const char *file, int line, Device *dev)
433 {
434 Dmsg3(sd_debuglevel, "unblock %s from %s:%d\n", dev->print_blocked(), file, line);
435 // ASSERT(LmgrMutexIsLocked(&dev->mutex_) == 1);
436 ASSERT(dev->blocked());
437 dev->SetBlocked(BST_NOT_BLOCKED);
438 ClearThreadId(dev->no_wait_id);
439 if (dev->num_waiting > 0) {
440 pthread_cond_broadcast(&dev->wait); /* wake them up */
441 }
442 }
443
444 /**
445 * Enter with device locked and blocked
446 * Exit with device unlocked and blocked by us.
447 */
448 void _stealDeviceLock(const char *file, int line, Device *dev, bsteal_lock_t *hold, int state)
449 {
450 Dmsg3(sd_debuglevel, "steal lock. old=%s from %s:%d\n", dev->print_blocked(),
451 file, line);
452 hold->dev_blocked = dev->blocked();
453 hold->dev_prev_blocked = dev->dev_prev_blocked;
454 hold->no_wait_id = dev->no_wait_id;
455 dev->SetBlocked(state);
456 Dmsg1(sd_debuglevel, "steal lock. new=%s\n", dev->print_blocked());
457 dev->no_wait_id = pthread_self();
458 dev->Unlock();
459 }
460
461 /**
462 * Enter with device blocked by us but not locked
463 * Exit with device locked, and blocked by previous owner
464 */
465 void _giveBackDeviceLock(const char *file, int line, Device *dev, bsteal_lock_t *hold)
466 {
467 Dmsg3(sd_debuglevel, "return lock. old=%s from %s:%d\n",
468 dev->print_blocked(), file, line);
469 dev->Lock();
470 dev->SetBlocked(hold->dev_blocked);
471 dev->dev_prev_blocked = hold->dev_prev_blocked;
472 dev->no_wait_id = hold->no_wait_id;
473 Dmsg1(sd_debuglevel, "return lock. new=%s\n", dev->print_blocked());
474 if (dev->num_waiting > 0) {
475 pthread_cond_broadcast(&dev->wait); /* wake them up */
476 }
477 }
478
479 const char *Device::print_blocked() const
480 {
481 switch (blocked_) {
482 case BST_NOT_BLOCKED:
483 return "BST_NOT_BLOCKED";
484 case BST_UNMOUNTED:
485 return "BST_UNMOUNTED";
486 case BST_WAITING_FOR_SYSOP:
487 return "BST_WAITING_FOR_SYSOP";
488 case BST_DOING_ACQUIRE:
489 return "BST_DOING_ACQUIRE";
490 case BST_WRITING_LABEL:
491 return "BST_WRITING_LABEL";
492 case BST_UNMOUNTED_WAITING_FOR_SYSOP:
493 return "BST_UNMOUNTED_WAITING_FOR_SYSOP";
494 case BST_MOUNT:
495 return "BST_MOUNT";
496 case BST_DESPOOLING:
497 return "BST_DESPOOLING";
498 case BST_RELEASING:
499 return "BST_RELEASING";
500 default:
501 return _("unknown blocked code");
502 }
503 }
504
505 /**
506 * Check if the device is blocked or not
507 */
508 bool Device::IsDeviceUnmounted()
509 {
510 bool status;
511 int blk = blocked();
512
513 status = (blk == BST_UNMOUNTED) ||
514 (blk == BST_UNMOUNTED_WAITING_FOR_SYSOP);
515
516 return status;
517 }
518
519 } /* namespace storagedaemon */
520