]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/lock.c
Backport from BEE
[bacula/bacula] / bacula / src / stored / lock.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2014 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from many
7    others, a complete list can be found in the file AUTHORS.
8
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.
13
14    Bacula® is a registered trademark of Kern Sibbald.
15 */
16 /*
17  * Collection of Bacula Storage daemon locking software
18  *
19  *  Kern Sibbald, June 2007
20  *
21  */
22
23 #include "bacula.h"                   /* pull in global headers */
24 #include "stored.h"                   /* pull in Storage Deamon headers */
25
26 #ifdef SD_DEBUG_LOCK
27 const int dbglvl = 300;
28 #else
29 const int dbglvl = 500;
30 #endif
31
32
33 /*
34  *
35  * The Storage daemon has three locking concepts that must be
36  *   understood:
37  *
38  *  1. dblock    blocking the device, which means that the device
39  *               is "marked" in use.  When setting and removing the
40                  block, the device is locked, but after dblock is
41                  called the device is unlocked.
42  *  2. Lock()    simple mutex that locks the device structure. A Lock
43  *               can be acquired while a device is blocked if it is not
44  *               locked.
45  *  3. rLock(locked)  "recursive" Lock, when means that a Lock (mutex)
46  *               will be acquired on the device if it is not blocked
47  *               by some other thread. If the device was blocked by
48  *               the current thread, it will acquire the lock.
49  *               If some other thread has set a block on the device,
50  *               this call will wait until the device is unblocked.
51  *               Can be called with locked true, which means the
52  *               Lock is already set
53  *
54  *  A lock is normally set when modifying the device structure.
55  *  A rLock is normally acquired when you want to block the device
56  *    i.e. it will wait until the device is not blocked.
57  *  A block is normally set during long operations like writing to
58  *    the device.
59  *  If you are writing the device, you will normally block and
60  *    lock it.
61  *  A lock cannot be violated. No other thread can touch the
62  *    device while a lock is set.
63  *  When a block is set, every thread accept the thread that set
64  *    the block will block if rLock is called.
65  *  A device can be blocked for multiple reasons, labeling, writing,
66  *    acquiring (opening) the device, waiting for the operator, unmounted,
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  *
75  * Functions:
76  *
77  *   DEVICE::Lock()   does P(m_mutex)     (in dev.h)
78  *   DEVICE::Unlock() does V(m_mutex)
79  *
80  *   DEVICE::rLock(locked) allows locking the device when this thread
81  *                     already has the device blocked.
82  *                    if (!locked)
83  *                       Lock()
84  *                    if blocked and not same thread that locked
85  *                       pthread_cond_wait
86  *                    leaves device locked
87  *
88  *   DEVICE::rUnlock() unlocks but does not unblock
89  *                    same as Unlock();
90  *
91  *   DEVICE::dblock(why)  does
92  *                    rLock();         (recursive device lock)
93  *                    block_device(this, why)
94  *                    rUnlock()
95  *
96  *   DEVICE::dunblock does
97  *                    Lock()
98  *                    unblock_device()
99  *                    Unlock()
100  *
101  *   block_device() does  (must be locked and not blocked at entry)
102  *                    set blocked status
103  *                    set our pid
104  *
105  *   unblock_device() 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  *   steal_device_lock() does (must be locked and blocked at entry)
114  *                    save status
115  *                    set new blocked status
116  *                    set new pid
117  *                    Unlock()
118  *
119  *   give_back_device_lock() 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  *
127  */
128
129 void DEVICE::dblock(int why)
130 {
131    rLock(false);              /* need recursive lock to block */
132    block_device(this, why);
133    rUnlock();
134 }
135
136 void DEVICE::dunblock(bool locked)
137 {
138    if (!locked) {
139       Lock();
140    }
141    unblock_device(this);
142    Unlock();
143 }
144
145
146
147 /*
148  * Debug DEVICE locks  N.B.
149  *
150  */
151
152 #ifdef DEV_DEBUG_LOCK
153
154 void DEVICE::dbg_Lock(const char *file, int line)
155 {
156    Dmsg3(sd_dbglvl, "Lock from %s:%d precnt=%d\n", file, line, m_count);
157    bthread_mutex_lock_p(&m_mutex, file, line);
158    m_pid = pthread_self();
159    m_count++;
160 }
161
162 void DEVICE::dbg_Unlock(const char *file, int line)
163 {
164    m_count--;
165    Dmsg3(sd_dbglvl, "Unlock from %s:%d postcnt=%d\n", file, line, m_count);
166    bthread_mutex_unlock_p(&m_mutex, file, line);
167 }
168
169 void DEVICE::dbg_rUnlock(const char *file, int line)
170 {
171    Dmsg2(sd_dbglvl, "rUnlock from %s:%d\n", file, line);
172    dbg_Unlock(file, line);
173 }
174
175 #else
176
177 /*
178  * DEVICE locks  N.B.
179  *
180  */
181
182
183 void DEVICE::rUnlock()
184 {
185    Unlock();
186 }
187
188 void DEVICE::Lock()
189 {
190    P(m_mutex);
191 }
192
193 void DEVICE::Unlock()
194 {
195    V(m_mutex);
196 }
197
198 #endif /* DEV_DEBUG_LOCK */
199
200 /*
201  * This is a recursive lock that checks if the device is blocked.
202  *
203  * When blocked is set, all threads EXCEPT thread with id no_wait_id
204  * must wait. The no_wait_id thread is out obtaining a new volume
205  * and preparing the label.
206  */
207 #ifdef DEV_DEBUG_LOCK
208 void DEVICE::dbg_rLock(const char *file, int line, bool locked)
209 {
210    Dmsg3(sd_dbglvl, "rLock blked=%s from %s:%d\n", print_blocked(),
211          file, line);
212
213    if (!locked) {
214       /* lockmgr version of P(m_mutex) */
215       bthread_mutex_lock_p(&m_mutex, file, line);
216       m_count++;
217    }
218
219    if (blocked() && !pthread_equal(no_wait_id, pthread_self())) {
220       num_waiting++;             /* indicate that I am waiting */
221       while (blocked()) {
222          int stat;
223 #ifndef HAVE_WIN32
224          /* thread id on Win32 may be a struct */
225          Dmsg3(sd_dbglvl, "rLock blked=%s no_wait=%p me=%p\n", print_blocked(),
226                no_wait_id, pthread_self());
227 #endif
228          if ((stat = bthread_cond_wait_p(&this->wait, &m_mutex, file, line)) != 0) {
229             berrno be;
230             this->dbg_Unlock(file, line);
231             Emsg1(M_ABORT, 0, _("pthread_cond_wait failure. ERR=%s\n"),
232                be.bstrerror(stat));
233          }
234       }
235       num_waiting--;             /* no longer waiting */
236    }
237 }
238 #else /* DEV_DEBUG_LOCK */
239
240 void DEVICE::rLock(bool locked)
241 {
242    if (!locked) {
243       Lock();
244       m_count++;
245    }
246
247    if (blocked() && !pthread_equal(no_wait_id, pthread_self())) {
248       num_waiting++;             /* indicate that I am waiting */
249       while (blocked()) {
250          int stat;
251 #ifndef HAVE_WIN32
252          /* thread id on Win32 may be a struct */
253          Dmsg3(sd_dbglvl, "rLock blked=%s no_wait=%p me=%p\n", print_blocked(),
254                no_wait_id, pthread_self());
255 #endif
256          if ((stat = pthread_cond_wait(&this->wait, &m_mutex)) != 0) {
257             berrno be;
258             this->Unlock();
259             Emsg1(M_ABORT, 0, _("pthread_cond_wait failure. ERR=%s\n"),
260                be.bstrerror(stat));
261          }
262       }
263       num_waiting--;             /* no longer waiting */
264    }
265 }
266
267 #endif  /* DEV_DEBUG_LOCK */
268
269 #ifdef SD_DEBUG_LOCK
270
271 void DEVICE::dbg_Lock_acquire(const char *file, int line)
272 {
273    Dmsg2(sd_dbglvl, "Lock_acquire from %s:%d\n", file, line);
274    bthread_mutex_lock_p(&acquire_mutex, file, line);
275 }
276
277 void DEVICE::dbg_Unlock_acquire(const char *file, int line)
278 {
279    Dmsg2(sd_dbglvl, "Unlock_acquire from %s:%d\n", file, line);
280    bthread_mutex_unlock_p(&acquire_mutex, file, line);
281 }
282
283 void DEVICE::dbg_Lock_read_acquire(const char *file, int line)
284 {
285    Dmsg2(sd_dbglvl, "Lock_read_acquire from %s:%d\n", file, line);
286    bthread_mutex_lock_p(&read_acquire_mutex, file, line);
287 }
288
289 void DEVICE::dbg_Unlock_read_acquire(const char *file, int line)
290 {
291    Dmsg2(sd_dbglvl, "Unlock_read_acquire from %s:%d\n", file, line);
292    bthread_mutex_unlock_p(&read_acquire_mutex, file, line);
293 }
294
295 void DEVICE::dbg_Lock_VolCatInfo(const char *file, int line)
296 {
297    bthread_mutex_lock_p(&volcat_mutex, file, line);
298 }
299
300 void DEVICE::dbg_Unlock_VolCatInfo(const char *file, int line)
301 {
302    bthread_mutex_unlock_p(&volcat_mutex, file, line);
303 }
304
305 #else
306
307 void DEVICE::Lock_acquire()
308 {
309    P(acquire_mutex);
310 }
311
312 void DEVICE::Unlock_acquire()
313 {
314    V(acquire_mutex);
315 }
316
317 void DEVICE::Lock_read_acquire()
318 {
319    P(read_acquire_mutex);
320 }
321
322 void DEVICE::Unlock_read_acquire()
323 {
324    V(read_acquire_mutex);
325 }
326
327 void DEVICE::Lock_VolCatInfo()
328 {
329    P(volcat_mutex);
330 }
331
332 void DEVICE::Unlock_VolCatInfo()
333 {
334    V(volcat_mutex);
335 }
336
337
338
339 #endif
340
341 /* Main device access control */
342 int DEVICE::init_mutex()
343 {
344    return pthread_mutex_init(&m_mutex, NULL);
345 }
346
347 /* Write device acquire mutex */
348 int DEVICE::init_acquire_mutex()
349 {
350    return pthread_mutex_init(&acquire_mutex, NULL);
351 }
352
353 /* Read device acquire mutex */
354 int DEVICE::init_read_acquire_mutex()
355 {
356    return pthread_mutex_init(&read_acquire_mutex, NULL);
357 }
358
359 /* VolCatInfo mutex */
360 int DEVICE::init_volcat_mutex()
361 {
362    return pthread_mutex_init(&volcat_mutex, NULL);
363 }
364
365 /* dcrs mutex */
366 int DEVICE::init_dcrs_mutex()
367 {
368    return pthread_mutex_init(&dcrs_mutex, NULL);
369 }
370
371 /* Set order in which device locks must be acquired */
372 void DEVICE::set_mutex_priorities()
373 {
374    /* Ensure that we respect this order in P/V operations */
375    bthread_mutex_set_priority(&m_mutex,       PRIO_SD_DEV_ACCESS);
376    bthread_mutex_set_priority(&spool_mutex,   PRIO_SD_DEV_SPOOL);
377    bthread_mutex_set_priority(&acquire_mutex, PRIO_SD_DEV_ACQUIRE);
378 }
379
380 int DEVICE::next_vol_timedwait(const struct timespec *timeout)
381 {
382    return pthread_cond_timedwait(&wait_next_vol, &m_mutex, timeout);
383 }
384
385
386 /*
387  * Block all other threads from using the device
388  *  Device must already be locked.  After this call,
389  *  the device is blocked to any thread calling dev->rLock(),
390  *  but the device is not locked (i.e. no P on device).  Also,
391  *  the current thread can do slip through the dev->rLock()
392  *  calls without blocking.
393  */
394 void _block_device(const char *file, int line, DEVICE *dev, int state)
395 {
396    ASSERT2(dev->blocked() == BST_NOT_BLOCKED, "Block request of device already blocked");
397    dev->set_blocked(state);           /* make other threads wait */
398    dev->no_wait_id = pthread_self();  /* allow us to continue */
399    Dmsg3(sd_dbglvl, "set blocked=%s from %s:%d\n", dev->print_blocked(), file, line);
400 }
401
402 /*
403  * Unblock the device, and wake up anyone who went to sleep.
404  * Enter: device locked
405  * Exit:  device locked
406  */
407 void _unblock_device(const char *file, int line, DEVICE *dev)
408 {
409    Dmsg3(sd_dbglvl, "unblock %s from %s:%d\n", dev->print_blocked(), file, line);
410    ASSERT2(dev->blocked(), "Unblock request of device not blocked");
411    dev->set_blocked(BST_NOT_BLOCKED);
412    clear_thread_id(dev->no_wait_id);
413    if (dev->num_waiting > 0) {
414       pthread_cond_broadcast(&dev->wait); /* wake them up */
415    }
416 }
417
418 /*
419  * Enter with device locked and blocked
420  * Exit with device unlocked and blocked by us.
421  */
422 void _steal_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold, int state)
423 {
424    Dmsg3(sd_dbglvl, "steal lock. old=%s from %s:%d\n", dev->print_blocked(),
425       file, line);
426    hold->dev_blocked = dev->blocked();
427    hold->dev_prev_blocked = dev->dev_prev_blocked;
428    hold->no_wait_id = dev->no_wait_id;
429    dev->set_blocked(state);
430    Dmsg1(sd_dbglvl, "steal lock. new=%s\n", dev->print_blocked());
431    dev->no_wait_id = pthread_self();
432    dev->Unlock();
433 }
434
435 /*
436  * Enter with device blocked by us but not locked
437  * Exit with device locked, and blocked by previous owner
438  */
439 void _give_back_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold)
440 {
441    Dmsg3(sd_dbglvl, "return lock. old=%s from %s:%d\n",
442       dev->print_blocked(), file, line);
443    dev->Lock();
444    dev->set_blocked(hold->dev_blocked);
445    dev->dev_prev_blocked = hold->dev_prev_blocked;
446    dev->no_wait_id = hold->no_wait_id;
447    Dmsg1(sd_dbglvl, "return lock. new=%s\n", dev->print_blocked());
448    if (dev->num_waiting > 0) {
449       pthread_cond_broadcast(&dev->wait); /* wake them up */
450    }
451 }
452
453 const char *DEVICE::print_blocked() const
454 {
455    switch (m_blocked) {
456    case BST_NOT_BLOCKED:
457       return "BST_NOT_BLOCKED";
458    case BST_UNMOUNTED:
459       return "BST_UNMOUNTED";
460    case BST_WAITING_FOR_SYSOP:
461       return "BST_WAITING_FOR_SYSOP";
462    case BST_DOING_ACQUIRE:
463       return "BST_DOING_ACQUIRE";
464    case BST_WRITING_LABEL:
465       return "BST_WRITING_LABEL";
466    case BST_UNMOUNTED_WAITING_FOR_SYSOP:
467       return "BST_UNMOUNTED_WAITING_FOR_SYSOP";
468    case BST_MOUNT:
469       return "BST_MOUNT";
470    case BST_DESPOOLING:
471       return "BST_DESPOOLING";
472    case BST_RELEASING:
473       return "BST_RELEASING";
474    default:
475       return _("unknown blocked code");
476    }
477 }
478
479
480 /*
481  * Check if the device is blocked or not
482  */
483 bool DEVICE::is_device_unmounted()
484 {
485    bool stat;
486
487    int blk = blocked();
488    stat = (blk == BST_UNMOUNTED) ||
489           (blk == BST_UNMOUNTED_WAITING_FOR_SYSOP);
490    return stat;
491 }