]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/lock.c
0fea98821be636a48b8f5975203f5590ec9b4f20
[bacula/bacula] / bacula / src / stored / lock.c
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2015 Kern Sibbald
5    Copyright (C) 2000-2014 Free Software Foundation Europe e.V.
6
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.
9
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.
14
15    This notice must be preserved when any source code is 
16    conveyed and/or propagated.
17
18    Bacula(R) is a registered trademark of Kern Sibbald.
19 */
20 /*
21  * Collection of Bacula Storage daemon locking software
22  *
23  *  Kern Sibbald, June 2007
24  *
25  */
26
27 #include "bacula.h"                   /* pull in global headers */
28 #include "stored.h"                   /* pull in Storage Deamon headers */
29
30 #ifdef SD_DEBUG_LOCK
31 const int dbglvl = 300;
32 #else
33 const int dbglvl = 500;
34 #endif
35
36
37 /*
38  *
39  * The Storage daemon has three locking concepts that must be
40  *   understood:
41  *
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
48  *               locked.
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
56  *               Lock is already set
57  *
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
62  *    the device.
63  *  If you are writing the device, you will normally block and
64  *    lock it.
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,
71  *    ...
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.
77  *
78  *
79  * Functions:
80  *
81  *   DEVICE::Lock()   does P(m_mutex)     (in dev.h)
82  *   DEVICE::Unlock() does V(m_mutex)
83  *
84  *   DEVICE::rLock(locked) allows locking the device when this thread
85  *                     already has the device blocked.
86  *                    if (!locked)
87  *                       Lock()
88  *                    if blocked and not same thread that locked
89  *                       pthread_cond_wait
90  *                    leaves device locked
91  *
92  *   DEVICE::rUnlock() unlocks but does not unblock
93  *                    same as Unlock();
94  *
95  *   DEVICE::dblock(why)  does
96  *                    rLock();         (recursive device lock)
97  *                    block_device(this, why)
98  *                    rUnlock()
99  *
100  *   DEVICE::dunblock does
101  *                    Lock()
102  *                    unblock_device()
103  *                    Unlock()
104  *
105  *   block_device() does  (must be locked and not blocked at entry)
106  *                    set blocked status
107  *                    set our pid
108  *
109  *   unblock_device() does (must be blocked at entry)
110  *                        (locked on entry)
111  *                        (locked on exit)
112  *                    set unblocked status
113  *                    clear pid
114  *                    if waiting threads
115  *                       pthread_cond_broadcast
116  *
117  *   steal_device_lock() does (must be locked and blocked at entry)
118  *                    save status
119  *                    set new blocked status
120  *                    set new pid
121  *                    Unlock()
122  *
123  *   give_back_device_lock() does (must be blocked but not locked)
124  *                    Lock()
125  *                    reset blocked status
126  *                    save previous blocked
127  *                    reset pid
128  *                    if waiting threads
129  *                       pthread_cond_broadcast
130  *
131  */
132
133 void DEVICE::dblock(int why)
134 {
135    rLock(false);              /* need recursive lock to block */
136    block_device(this, why);
137    rUnlock();
138 }
139
140 void DEVICE::dunblock(bool locked)
141 {
142    if (!locked) {
143       Lock();
144    }
145    unblock_device(this);
146    Unlock();
147 }
148
149
150
151 /*
152  * Debug DEVICE locks  N.B.
153  *
154  */
155
156 #ifdef DEV_DEBUG_LOCK
157
158 void DEVICE::dbg_Lock(const char *file, int line)
159 {
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();
163    m_count++;
164 }
165
166 void DEVICE::dbg_Unlock(const char *file, int line)
167 {
168    m_count--;
169    Dmsg3(sd_dbglvl, "Unlock from %s:%d postcnt=%d\n", file, line, m_count);
170    bthread_mutex_unlock_p(&m_mutex, file, line);
171 }
172
173 void DEVICE::dbg_rUnlock(const char *file, int line)
174 {
175    Dmsg2(sd_dbglvl, "rUnlock from %s:%d\n", file, line);
176    dbg_Unlock(file, line);
177 }
178
179 #else
180
181 /*
182  * DEVICE locks  N.B.
183  *
184  */
185
186
187 void DEVICE::rUnlock()
188 {
189    Unlock();
190 }
191
192 void DEVICE::Lock()
193 {
194    P(m_mutex);
195 }
196
197 void DEVICE::Unlock()
198 {
199    V(m_mutex);
200 }
201
202 #endif /* DEV_DEBUG_LOCK */
203
204 /*
205  * This is a recursive lock that checks if the device is blocked.
206  *
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.
210  */
211 #ifdef DEV_DEBUG_LOCK
212 void DEVICE::dbg_rLock(const char *file, int line, bool locked)
213 {
214    Dmsg3(sd_dbglvl, "rLock blked=%s from %s:%d\n", print_blocked(),
215          file, line);
216
217    if (!locked) {
218       /* lockmgr version of P(m_mutex) */
219       bthread_mutex_lock_p(&m_mutex, file, line);
220       m_count++;
221    }
222
223    if (blocked() && !pthread_equal(no_wait_id, pthread_self())) {
224       num_waiting++;             /* indicate that I am waiting */
225       while (blocked()) {
226          int stat;
227 #ifndef HAVE_WIN32
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());
231 #endif
232          if ((stat = bthread_cond_wait_p(&this->wait, &m_mutex, file, line)) != 0) {
233             berrno be;
234             this->dbg_Unlock(file, line);
235             Emsg1(M_ABORT, 0, _("pthread_cond_wait failure. ERR=%s\n"),
236                be.bstrerror(stat));
237          }
238       }
239       num_waiting--;             /* no longer waiting */
240    }
241 }
242 #else /* DEV_DEBUG_LOCK */
243
244 void DEVICE::rLock(bool locked)
245 {
246
247    if (!locked) {
248       Lock();
249       m_count++;
250    }
251
252    if (blocked() && !pthread_equal(no_wait_id, pthread_self())) {
253       num_waiting++;             /* indicate that I am waiting */
254       while (blocked()) {
255          int stat;
256 #ifndef HAVE_WIN32
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());
260 #endif
261          if ((stat = pthread_cond_wait(&this->wait, &m_mutex)) != 0) {
262             berrno be;
263             this->Unlock();
264             Emsg1(M_ABORT, 0, _("pthread_cond_wait failure. ERR=%s\n"),
265                be.bstrerror(stat));
266          }
267       }
268       num_waiting--;             /* no longer waiting */
269    }
270 }
271
272 #endif  /* DEV_DEBUG_LOCK */
273
274 #ifdef SD_DEBUG_LOCK
275
276 void DEVICE::dbg_Lock_acquire(const char *file, int line)
277 {
278    Dmsg2(sd_dbglvl, "Lock_acquire from %s:%d\n", file, line);
279    bthread_mutex_lock_p(&acquire_mutex, file, line);
280 }
281
282 void DEVICE::dbg_Unlock_acquire(const char *file, int line)
283 {
284    Dmsg2(sd_dbglvl, "Unlock_acquire from %s:%d\n", file, line);
285    bthread_mutex_unlock_p(&acquire_mutex, file, line);
286 }
287
288 void DEVICE::dbg_Lock_read_acquire(const char *file, int line)
289 {
290    Dmsg2(sd_dbglvl, "Lock_read_acquire from %s:%d\n", file, line);
291    bthread_mutex_lock_p(&read_acquire_mutex, file, line);
292 }
293
294 void DEVICE::dbg_Unlock_read_acquire(const char *file, int line)
295 {
296    Dmsg2(sd_dbglvl, "Unlock_read_acquire from %s:%d\n", file, line);
297    bthread_mutex_unlock_p(&read_acquire_mutex, file, line);
298 }
299
300 void DEVICE::dbg_Lock_VolCatInfo(const char *file, int line)
301 {
302    bthread_mutex_lock_p(&volcat_mutex, file, line);
303 }
304
305 void DEVICE::dbg_Unlock_VolCatInfo(const char *file, int line)
306 {
307    bthread_mutex_unlock_p(&volcat_mutex, file, line);
308 }
309
310 #else
311
312 void DEVICE::Lock_acquire()
313 {
314    P(acquire_mutex);
315 }
316
317 void DEVICE::Unlock_acquire()
318 {
319    V(acquire_mutex);
320 }
321
322 void DEVICE::Lock_read_acquire()
323 {
324    P(read_acquire_mutex);
325 }
326
327 void DEVICE::Unlock_read_acquire()
328 {
329    V(read_acquire_mutex);
330 }
331
332 void DEVICE::Lock_VolCatInfo()
333 {
334    P(volcat_mutex);
335 }
336
337 void DEVICE::Unlock_VolCatInfo()
338 {
339    V(volcat_mutex);
340 }
341
342
343
344 #endif
345
346 /* Main device access control */
347 int DEVICE::init_mutex()
348 {
349    return pthread_mutex_init(&m_mutex, NULL);
350 }
351
352 /* Mutex around the freespace command */
353 int DEVICE::init_freespace_mutex()
354 {
355    return pthread_mutex_init(&freespace_mutex, NULL);
356 }
357
358 /* Write device acquire mutex */
359 int DEVICE::init_acquire_mutex()
360 {
361    return pthread_mutex_init(&acquire_mutex, NULL);
362 }
363
364 /* Read device acquire mutex */
365 int DEVICE::init_read_acquire_mutex()
366 {
367    return pthread_mutex_init(&read_acquire_mutex, NULL);
368 }
369
370 /* VolCatInfo mutex */
371 int DEVICE::init_volcat_mutex()
372 {
373    return pthread_mutex_init(&volcat_mutex, NULL);
374 }
375
376 /* dcrs mutex */
377 int DEVICE::init_dcrs_mutex()
378 {
379    return pthread_mutex_init(&dcrs_mutex, NULL);
380 }
381
382 /* Set order in which device locks must be acquired */
383 void DEVICE::set_mutex_priorities()
384 {
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);
389 }
390
391 int DEVICE::next_vol_timedwait(const struct timespec *timeout)
392 {
393    return pthread_cond_timedwait(&wait_next_vol, &m_mutex, timeout);
394 }
395
396
397 /*
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.
404  */
405 void _block_device(const char *file, int line, DEVICE *dev, int state)
406 {
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);
411 }
412
413 /*
414  * Unblock the device, and wake up anyone who went to sleep.
415  * Enter: device locked
416  * Exit:  device locked
417  */
418 void _unblock_device(const char *file, int line, DEVICE *dev)
419 {
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 */
426    }
427 }
428
429 /*
430  * Enter with device locked and blocked
431  * Exit with device unlocked and blocked by us.
432  */
433 void _steal_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold, int state)
434 {
435    Dmsg3(sd_dbglvl, "steal lock. old=%s from %s:%d\n", dev->print_blocked(),
436       file, line);
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();
443    dev->Unlock();
444 }
445
446 /*
447  * Enter with device blocked by us but not locked
448  * Exit with device locked, and blocked by previous owner
449  */
450 void _give_back_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold)
451 {
452    Dmsg3(sd_dbglvl, "return lock. old=%s from %s:%d\n",
453       dev->print_blocked(), file, line);
454    dev->Lock();
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 */
461    }
462 }
463
464 const char *DEVICE::print_blocked() const
465 {
466    switch (m_blocked) {
467    case BST_NOT_BLOCKED:
468       return "BST_NOT_BLOCKED";
469    case BST_UNMOUNTED:
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";
479    case BST_MOUNT:
480       return "BST_MOUNT";
481    case BST_DESPOOLING:
482       return "BST_DESPOOLING";
483    case BST_RELEASING:
484       return "BST_RELEASING";
485    default:
486       return _("unknown blocked code");
487    }
488 }
489
490
491 /*
492  * Check if the device is blocked or not
493  */
494 bool DEVICE::is_device_unmounted()
495 {
496    bool stat;
497
498    int blk = blocked();
499    stat = (blk == BST_UNMOUNTED) ||
500           (blk == BST_UNMOUNTED_WAITING_FOR_SYSOP);
501    return stat;
502 }