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