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