This patch should hold jobs in the Director's start queue if more than one simultaneous backup job wants to use the same Storage device with two different Pools (i.e. 2 Volumes). Apply the patch to version 1.36.1 with: cd patch -p0 <1.36.1-pool.patch make make install ... Index: src/dird/jobq.c =================================================================== RCS file: /cvsroot/bacula/bacula/src/dird/jobq.c,v retrieving revision 1.25 retrieving revision 1.26 diff -u -r1.25 -r1.26 --- src/dird/jobq.c 24 Sep 2004 12:30:14 -0000 1.25 +++ src/dird/jobq.c 3 Dec 2004 21:00:18 -0000 1.26 @@ -10,7 +10,7 @@ * * Kern Sibbald, July MMIII * - * Version $Id: 1.36.1-pool.patch 1866 2005-03-06 13:45:35Z kerns $ + * Version $Id: 1.36.1-pool.patch 1866 2005-03-06 13:45:35Z kerns $ * * This code was adapted from the Bacula workq, which was * adapted from "Programming with POSIX Threads", by @@ -40,6 +40,7 @@ #include "bacula.h" #include "dird.h" +extern JCR *jobs; /* Forward referenced functions */ extern "C" void *jobq_server(void *arg); @@ -47,6 +48,8 @@ static int start_server(jobq_t *jq); + + /* * Initialize a job queue * @@ -544,6 +547,7 @@ for ( ; je; ) { /* je is current job item on the queue, jn is the next one */ JCR *jcr = je->jcr; + bool skip_this_jcr = false; jobq_item_t *jn = (jobq_item_t *)jq->waiting_jobs->next(je); Dmsg3(300, "Examining Job=%d JobPri=%d want Pri=%d\n", jcr->JobId, jcr->JobPriority, Priority); @@ -560,14 +564,40 @@ jcr->store->MaxConcurrentJobs = 1; } else { set_jcr_job_status(jcr, JS_WaitStoreRes); - je = jn; + je = jn; /* point to next waiting job */ continue; } + /* We are not doing a Restore or Verify */ + } else if (jcr->store->NumConcurrentJobs == 0 && + jcr->store->NumConcurrentJobs < jcr->store->MaxConcurrentJobs) { + /* Simple case, first job */ + jcr->store->NumConcurrentJobs = 1; } else if (jcr->store->NumConcurrentJobs < jcr->store->MaxConcurrentJobs) { - jcr->store->NumConcurrentJobs++; - } else { + /* + * At this point, we already have at least one Job running + * for this Storage daemon, so we must ensure that there + * is no Volume conflict. In general, it should be OK, if + * all Jobs pull from the same Pool, so we check the Pools. + */ + JCR *njcr; + lock_jcr_chain(); + for (njcr=jobs; njcr; njcr=njcr->next) { + if (njcr->JobId == 0 || njcr == jcr) { + continue; + } + if (njcr->pool != jcr->pool) { + skip_this_jcr = true; + break; + } + } + unlock_jcr_chain(); + if (!skip_this_jcr) { + jcr->store->NumConcurrentJobs++; + } + } + if (skip_this_jcr) { set_jcr_job_status(jcr, JS_WaitStoreRes); - je = jn; + je = jn; /* point to next waiting job */ continue; } @@ -580,7 +610,7 @@ jcr->store->MaxConcurrentJobs = jcr->saveMaxConcurrentJobs; } set_jcr_job_status(jcr, JS_WaitClientRes); - je = jn; + je = jn; /* point to next waiting job */ continue; } if (jcr->job->NumConcurrentJobs < jcr->job->MaxConcurrentJobs) { @@ -593,7 +623,7 @@ } jcr->client->NumConcurrentJobs--; set_jcr_job_status(jcr, JS_WaitJobRes); - je = jn; + je = jn; /* Point to next waiting job */ continue; } /* Got all locks, now remove it from wait queue and append it @@ -603,7 +633,7 @@ jq->waiting_jobs->remove(je); jq->ready_jobs->append(je); Dmsg1(300, "moved JobId=%d from wait to ready queue\n", je->jcr->JobId); - je = jn; + je = jn; /* Point to next waiting job */ } /* end for loop */ break; } /* end while loop */ Index: src/lib/jcr.c =================================================================== RCS file: /cvsroot/bacula/bacula/src/lib/jcr.c,v retrieving revision 1.61 retrieving revision 1.62 diff -u -r1.61 -r1.62 --- src/lib/jcr.c 15 Nov 2004 22:43:33 -0000 1.61 +++ src/lib/jcr.c 3 Dec 2004 21:00:19 -0000 1.62 @@ -3,7 +3,7 @@ * * Kern E. Sibbald, December 2000 * - * Version $Id: 1.36.1-pool.patch 1866 2005-03-06 13:45:35Z kerns $ + * Version $Id: 1.36.1-pool.patch 1866 2005-03-06 13:45:35Z kerns $ * * These routines are thread safe. * @@ -43,7 +43,7 @@ dlist *last_jobs = NULL; const int max_last_jobs = 10; -static JCR *jobs = NULL; /* pointer to JCR chain */ +JCR *jobs = NULL; /* pointer to JCR chain */ static brwlock_t lock; /* lock for last jobs and JCR chain */ void init_last_jobs_list()