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 #include "lib/util.h"
34 #include "lib/berrno.h"
35 
36 namespace storagedaemon {
37 
38 /**
39  * The Storage daemon has three locking concepts that must be understood:
40  *
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
47  *              locked.
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
55  *                  Lock is already set
56  *
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 the device.
61  * - If you are writing the device, you will normally block and lock it.
62  * - A lock cannot be violated. No other thread can touch the
63  *   device while a lock is set.
64  * - When a block is set, every thread accept the thread that set
65  *   the block will block if rLock is called.
66  * - A device can be blocked for multiple reasons, labeling, writing,
67  *   acquiring (opening) the device, waiting for the operator, unmounted,
68  *   ...
69  *
70  * Under certain conditions the block that is set on a device can be
71  * stolen and the device can be used by another thread. For example,
72  * a device is blocked because it is waiting for the operator to
73  * mount a tape.  The operator can then unmount the device, and label
74  * a tape, re-mount it, give back the block, and the job will continue.
75  *
76  * Functions:
77  *
78  * Device::Lock()   does P(mutex_)     (in dev.h)
79  * Device::Unlock() does V(mutex_)
80  *
81  * Device::rLock(locked) allows locking the device when this thread
82  *                       already has the device blocked.
83  * - if (!locked)
84  *   Lock()
85  * - if blocked and not same thread that locked
86  *   pthread_cond_wait
87  * - leaves device locked
88  *
89  * Device::rUnlock() Unlocks but does not unblock same as Unlock();
90  *
91  * Device::dblock(why) does
92  * - rLock();         (recursive device lock)
93  * - BlockDevice(this, why)
94  * - rUnlock()
95  *
96  * Device::dunblock does
97  * - Lock()
98  * - UnblockDevice()
99  * - Unlock()
100  *
101  * BlockDevice() does (must be locked and not blocked at entry)
102  * - set blocked status
103  * - set our pid
104  *
105  * UnblockDevice() does (must be blocked at entry)
106  * - (locked on entry)
107  * - (locked on exit)
108  * - set unblocked status
109  * - clear pid
110  * - if waiting threads
111  *   pthread_cond_broadcast
112  *
113  * StealDeviceLock() does (must be locked and blocked at entry)
114  * - save status
115  * - set new blocked status
116  * - set new pid
117  * - Unlock()
118  *
119  * GiveBackDeviceLock() does (must be blocked but not locked)
120  * - Lock()
121  * - reset blocked status
122  * - save previous blocked
123  * - reset pid
124  * - if waiting threads
125  *   pthread_cond_broadcast
126  */
dblock(int why)127 void Device::dblock(int why)
128 {
129   rLock(false); /* need recursive lock to block */
130   BlockDevice(this, why);
131   rUnlock();
132 }
133 
dunblock(bool locked)134 void Device::dunblock(bool locked)
135 {
136   if (!locked) { Lock(); }
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()) { dev->dbg_rUnlock(file, line); }
172   real_V(r_mutex);
173   return;
174 }
175 
dbg_Unlock(const char * file,int line)176 void Device::dbg_Unlock(const char* file, int line)
177 {
178   count_--;
179   Dmsg3(sd_debuglevel, "Unlock from %s:%d postcnt=%d\n", file, line, count_);
180   pthread_mutex_unlock(&mutex_);
181 }
182 
dbg_rUnlock(const char * file,int line)183 void Device::dbg_rUnlock(const char* file, int line)
184 {
185   Dmsg2(sd_debuglevel, "rUnlock from %s:%d\n", file, line);
186   dbg_Unlock(file, line);
187 }
188 
dbg_Lock_acquire(const char * file,int line)189 void Device::dbg_Lock_acquire(const char* file, int line)
190 {
191   Dmsg2(sd_debuglevel, "Lock_acquire from %s:%d\n", file, line);
192   pthread_mutex_lock(&acquire_mutex);
193 }
194 
dbg_Unlock_acquire(const char * file,int line)195 void Device::dbg_Unlock_acquire(const char* file, int line)
196 {
197   Dmsg2(sd_debuglevel, "Unlock_acquire from %s:%d\n", file, line);
198   pthread_mutex_unlock(&acquire_mutex);
199 }
200 
dbg_Lock_read_acquire(const char * file,int line)201 void Device::dbg_Lock_read_acquire(const char* file, int line)
202 {
203   Dmsg2(sd_debuglevel, "Lock_read_acquire from %s:%d\n", file, line);
204   pthread_mutex_lock(&read_acquire_mutex);
205 }
206 
dbg_Unlock_read_acquire(const char * file,int line)207 void Device::dbg_Unlock_read_acquire(const char* file, int line)
208 {
209   Dmsg2(sd_debuglevel, "Unlock_read_acquire from %s:%d\n", file, line);
210   pthread_mutex_unlock(&read_acquire_mutex);
211 }
212 
213 #else
214 
215 /**
216  * DeviceControlRecord locks N.B.
217  */
218 /**
219  * Multiple rLock implementation
220  */
mLock(bool locked)221 void DeviceControlRecord::mLock(bool locked)
222 {
223   P(r_mutex);
224   if (IsDevLocked()) {
225     V(r_mutex);
226     return;
227   }
228   dev->rLock(locked);
229   IncDevLock();
230   V(r_mutex);
231   return;
232 }
233 
234 /**
235  * Multiple rUnlock implementation
236  */
mUnlock()237 void DeviceControlRecord::mUnlock()
238 {
239   P(r_mutex);
240   if (!IsDevLocked()) {
241     V(r_mutex);
242     ASSERT2(0, "Call on dcr mUnlock when not locked");
243     return;
244   }
245   DecDevLock();
246   /*
247    * When the count goes to zero, unlock it
248    */
249   if (!IsDevLocked()) { dev->rUnlock(); }
250   V(r_mutex);
251   return;
252 }
253 
254 /**
255  * Device locks N.B.
256  */
rUnlock()257 void Device::rUnlock() { Unlock(); }
258 
Lock()259 void Device::Lock() { P(mutex_); }
260 
Unlock()261 void Device::Unlock() { V(mutex_); }
262 
Lock_acquire()263 void Device::Lock_acquire() { P(acquire_mutex); }
264 
Unlock_acquire()265 void Device::Unlock_acquire() { V(acquire_mutex); }
266 
Lock_read_acquire()267 void Device::Lock_read_acquire() { P(read_acquire_mutex); }
268 
Unlock_read_acquire()269 void Device::Unlock_read_acquire() { V(read_acquire_mutex); }
270 
271 #endif
272 
273 /**
274  * Main device access control
275  */
InitMutex()276 int Device::InitMutex() { return pthread_mutex_init(&mutex_, NULL); }
277 
278 /**
279  * Write device acquire mutex
280  */
InitAcquireMutex()281 int Device::InitAcquireMutex()
282 {
283   return pthread_mutex_init(&acquire_mutex, NULL);
284 }
285 
286 /**
287  * Read device acquire mutex
288  */
InitReadAcquireMutex()289 int Device::InitReadAcquireMutex()
290 {
291   return pthread_mutex_init(&read_acquire_mutex, NULL);
292 }
293 
NextVolTimedwait(const struct timespec * timeout)294 int Device::NextVolTimedwait(const struct timespec* timeout)
295 {
296   return pthread_cond_timedwait(&wait_next_vol, &mutex_, timeout);
297 }
298 
299 /**
300  * This is a recursive lock that checks if the device is blocked.
301  *
302  * When blocked is set, all threads EXCEPT thread with id no_wait_id
303  * must wait. The no_wait_id thread is out obtaining a new volume
304  * and preparing the label.
305  */
306 #ifdef SD_DEBUG_LOCK
dbg_rLock(const char * file,int line,bool locked)307 void Device::dbg_rLock(const char* file, int line, bool locked)
308 {
309   Dmsg3(sd_debuglevel, "rLock blked=%s from %s:%d\n", print_blocked(), file,
310         line);
311   if (!locked) {
312     pthread_mutex_lock(&mutex);
313     count_++;
314   }
315 #else
316 void Device::rLock(bool locked)
317 {
318   if (!locked) {
319     Lock();
320     count_++;
321   }
322 #endif
323 
324   if (blocked() && !pthread_equal(no_wait_id, pthread_self())) {
325     num_waiting++; /* indicate that I am waiting */
326     while (blocked()) {
327       int status;
328       char ed1[50], ed2[50];
329 
330       Dmsg3(sd_debuglevel, "rLock blked=%s no_wait=%s me=%s\n", print_blocked(),
331             edit_pthread(no_wait_id, ed1, sizeof(ed1)),
332             edit_pthread(pthread_self(), ed2, sizeof(ed2)));
333       if ((status = pthread_cond_wait(&wait, &mutex_)) != 0) {
334         BErrNo be;
335         this->Unlock();
336         Emsg1(M_ABORT, 0, _("pthread_cond_wait failure. ERR=%s\n"),
337               be.bstrerror(status));
338       }
339     }
340     num_waiting--; /* no longer waiting */
341   }
342 }
343 
344 /**
345  * Block all other threads from using the device
346  *
347  * Device must already be locked.  After this call,
348  * the device is blocked to any thread calling dev->rLock(),
349  * but the device is not locked (i.e. no P on device).  Also,
350  * the current thread can do slip through the dev->rLock()
351  * calls without blocking.
352  */
353 void _blockDevice(const char* file, int line, Device* dev, int state)
354 {
355   ASSERT(dev->blocked() == BST_NOT_BLOCKED);
356   dev->SetBlocked(state);           /* make other threads wait */
357   dev->no_wait_id = pthread_self(); /* allow us to continue */
358   Dmsg3(sd_debuglevel, "set blocked=%s from %s:%d\n", dev->print_blocked(),
359         file, line);
360 }
361 
362 /**
363  * Unblock the device, and wake up anyone who went to sleep.
364  * Enter: device locked
365  * Exit:  device locked
366  */
367 void _unBlockDevice(const char* file, int line, Device* dev)
368 {
369   Dmsg3(sd_debuglevel, "unblock %s from %s:%d\n", dev->print_blocked(), file,
370         line);
371   ASSERT(dev->blocked());
372   dev->SetBlocked(BST_NOT_BLOCKED);
373   ClearThreadId(dev->no_wait_id);
374   if (dev->num_waiting > 0) {
375     pthread_cond_broadcast(&dev->wait); /* wake them up */
376   }
377 }
378 
379 /**
380  * Enter with device locked and blocked
381  * Exit with device unlocked and blocked by us.
382  */
383 void _stealDeviceLock(const char* file,
384                       int line,
385                       Device* dev,
386                       bsteal_lock_t* hold,
387                       int state)
388 {
389   Dmsg3(sd_debuglevel, "steal lock. old=%s from %s:%d\n", dev->print_blocked(),
390         file, line);
391   hold->dev_blocked = dev->blocked();
392   hold->dev_prev_blocked = dev->dev_prev_blocked;
393   hold->no_wait_id = dev->no_wait_id;
394   dev->SetBlocked(state);
395   Dmsg1(sd_debuglevel, "steal lock. new=%s\n", dev->print_blocked());
396   dev->no_wait_id = pthread_self();
397   dev->Unlock();
398 }
399 
400 /**
401  * Enter with device blocked by us but not locked
402  * Exit with device locked, and blocked by previous owner
403  */
404 void _giveBackDeviceLock(const char* file,
405                          int line,
406                          Device* dev,
407                          bsteal_lock_t* hold)
408 {
409   Dmsg3(sd_debuglevel, "return lock. old=%s from %s:%d\n", dev->print_blocked(),
410         file, line);
411   dev->Lock();
412   dev->SetBlocked(hold->dev_blocked);
413   dev->dev_prev_blocked = hold->dev_prev_blocked;
414   dev->no_wait_id = hold->no_wait_id;
415   Dmsg1(sd_debuglevel, "return lock. new=%s\n", dev->print_blocked());
416   if (dev->num_waiting > 0) {
417     pthread_cond_broadcast(&dev->wait); /* wake them up */
418   }
419 }
420 
421 const char* Device::print_blocked() const
422 {
423   switch (blocked_) {
424     case BST_NOT_BLOCKED:
425       return "BST_NOT_BLOCKED";
426     case BST_UNMOUNTED:
427       return "BST_UNMOUNTED";
428     case BST_WAITING_FOR_SYSOP:
429       return "BST_WAITING_FOR_SYSOP";
430     case BST_DOING_ACQUIRE:
431       return "BST_DOING_ACQUIRE";
432     case BST_WRITING_LABEL:
433       return "BST_WRITING_LABEL";
434     case BST_UNMOUNTED_WAITING_FOR_SYSOP:
435       return "BST_UNMOUNTED_WAITING_FOR_SYSOP";
436     case BST_MOUNT:
437       return "BST_MOUNT";
438     case BST_DESPOOLING:
439       return "BST_DESPOOLING";
440     case BST_RELEASING:
441       return "BST_RELEASING";
442     default:
443       return _("unknown blocked code");
444   }
445 }
446 
447 /**
448  * Check if the device is blocked or not
449  */
450 bool Device::IsDeviceUnmounted()
451 {
452   bool status;
453   int blk = blocked();
454 
455   status = (blk == BST_UNMOUNTED) || (blk == BST_UNMOUNTED_WAITING_FOR_SYSOP);
456 
457   return status;
458 }
459 
460 } /* namespace storagedaemon */
461