Priority:
+- Fix prog copyright (SD) all other files.
 - Migration Volume span bug
 - Rescue release
 - Bug reports
 
       goto bail_out;
    }
 
-
    if (!send_runscripts_commands(jcr)) {
       goto bail_out;
    }
         jcr->client->name(), cr.Uname,
         jcr->fileset->name(), jcr->FSCreateTime,
         jcr->pool->name(), jcr->pool_source,
-        jcr->wstore->name(), jcr->storage_source,
+        jcr->wstore->name(), jcr->wstore_source,
         schedt,
         sdt,
         edt,
 
 
 inline char *STORE::name() const { return hdr.name; }
 
+/*
+ * This is a sort of "unified" store that has both the
+ *  storage pointer and the text of where the pointer was
+ *  found.
+ */
+class USTORE {
+public:
+   STORE *store;
+   POOLMEM *store_source;
+
+   /* Methods */
+   USTORE() { store = NULL; store_source = get_pool_memory(PM_MESSAGE); }
+   ~USTORE() { destroy(); }   
+   void set_source(const char *where);
+   void destroy();
+};
+
+inline void USTORE::destroy()
+{
+   if (store_source) {
+      free_pool_memory(store_source);
+      store_source = NULL;
+   }
+}
+
+
+inline void USTORE::set_source(const char *where)
+{
+   if (!store_source) {
+      store_source = get_pool_memory(PM_MESSAGE);
+   }
+   pm_strcpy(store_source, where);
+}
+
 
 /*
  *   Job Resource
 
 {
    int stat;
    if (setup_job(jcr)) {
+      Dmsg0(200, "Add jrc to work queue\n");
       /* Queue the job to be run */
       if ((stat = jobq_add(&job_queue, jcr)) != 0) {
          berrno be;
       jcr->pool_source = get_pool_memory(PM_MESSAGE);
       pm_strcpy(jcr->pool_source, _("unknown source"));
    }
-   if (!jcr->storage_source) {
-      jcr->storage_source = get_pool_memory(PM_MESSAGE);
-      pm_strcpy(jcr->storage_source, _("unknown source"));
-   }
 
    /*
     * Create Job record
    Dmsg4(100, "Created job record JobId=%d Name=%s Type=%c Level=%c\n",
        jcr->JobId, jcr->Job, jcr->jr.JobType, jcr->jr.JobLevel);
 
-   generate_daemon_event(jcr, "JobStart");
-
    if (!get_or_create_client_record(jcr)) {
       goto bail_out;
    }
 
+   generate_daemon_event(jcr, "JobStart");
+
    if (job_canceled(jcr)) {
       goto bail_out;
    }
    }
 
    generate_job_event(jcr, "JobInit");
-
-   Dmsg0(200, "Add jrc to work queue\n");
    return true;
 
 bail_out:
                copy_wstorage(ua->jcr, jcr->wstorage, _("Job resource")); 
             }
          } else {
+            USTORE store;
             if (jcr->rstorage) {
-               set_wstorage(ua->jcr, jcr->rstore);
+               store.store = jcr->rstore;
+               pm_strcpy(store.store_source, jcr->rstore_source);
             } else {
-               set_wstorage(ua->jcr, jcr->wstore);
+               store.store = jcr->wstore;
+               pm_strcpy(store.store_source, jcr->wstore_source);
             }
+            set_wstorage(ua->jcr, &store);
          }
+
          if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
             bsendmsg(ua, _("Failed to connect to Storage daemon.\n"));
             return false;
 void apply_pool_overrides(JCR *jcr)
 {
    if (jcr->run_pool_override) {
-      pm_strcpy(jcr->pool_source, _("Run Pool override"));
+      pm_strcpy(jcr->pool_source, _("run pool override"));
    }
    /*
     * Apply any level related Pool selections
       if (jcr->full_pool) {
          jcr->pool = jcr->full_pool;
          if (jcr->run_full_pool_override) {
-            pm_strcpy(jcr->pool_source, _("Run FullPool override"));
+            pm_strcpy(jcr->pool_source, _("run FullPool override"));
          } else {
-            pm_strcpy(jcr->pool_source, _("Job FullPool override"));
+            pm_strcpy(jcr->pool_source, _("job FullPool override"));
          }
       }
       break;
       if (jcr->inc_pool) {
          jcr->pool = jcr->inc_pool;
          if (jcr->run_inc_pool_override) {
-            pm_strcpy(jcr->pool_source, _("Run IncPool override"));
+            pm_strcpy(jcr->pool_source, _("run IncPool override"));
          } else {
-            pm_strcpy(jcr->pool_source, _("Job IncPool override"));
+            pm_strcpy(jcr->pool_source, _("job IncPool override"));
          }
       }
       break;
       if (jcr->diff_pool) {
          jcr->pool = jcr->diff_pool;
          if (jcr->run_diff_pool_override) {
-            pm_strcpy(jcr->pool_source, _("Run DiffPool override"));
+            pm_strcpy(jcr->pool_source, _("run DiffPool override"));
          } else {
-            pm_strcpy(jcr->pool_source, _("Job DiffPool override"));
+            pm_strcpy(jcr->pool_source, _("job DiffPool override"));
          }
       }
       break;
       free_pool_memory(jcr->pool_source);
       jcr->pool_source = NULL;
    }
-   if (jcr->storage_source) {
-      free_pool_memory(jcr->storage_source);
-      jcr->storage_source = NULL;
+   if (jcr->wstore_source) {
+      free_pool_memory(jcr->wstore_source);
+      jcr->wstore_source = NULL;
+   }
+   if (jcr->rstore_source) {
+      free_pool_memory(jcr->rstore_source);
+      jcr->rstore_source = NULL;
    }
    if (jcr->stime) {
       Dmsg0(200, "Free JCR stime\n");
  *  or in the Pool record.  The Pool record overrides the Job 
  *  record.
  */
-STORE *get_job_storage(JOB *job)
+void get_job_storage(USTORE *store, JOB *job, RUN *run) 
 {
+   if (run && run->pool && run->pool->storage) {
+      store->store = (STORE *)run->pool->storage->first();
+      pm_strcpy(store->store_source, _("run pool override"));
+      return;
+   }
+   if (run && run->storage) {
+      store->store = run->storage;
+      pm_strcpy(store->store_source, _("run storage override"));
+      return;
+   }
    if (job->pool->storage) {
-      return (STORE *)job->pool->storage->first();
+      store->store = (STORE *)job->pool->storage->first();
+      pm_strcpy(store->store_source, _("job pool storage"));
    } else {
-      return (STORE *)job->storage->first();
+      store->store = (STORE *)job->storage->first();
+      pm_strcpy(store->store_source, _("job storage"));
    }
 }
 
       jcr->pool_source = get_pool_memory(PM_MESSAGE);
       pm_strcpy(jcr->pool_source, _("unknown source"));
    }
-   if (!jcr->storage_source) {
-      jcr->storage_source = get_pool_memory(PM_MESSAGE);
-      pm_strcpy(jcr->storage_source, _("unknown source"));
-   }
    jcr->JobPriority = job->Priority;
    /* Copy storage definitions -- deleted in dir_free_jcr above */
    if (job->storage) {
       copy_rwstorage(jcr, job->storage, _("Job resource"));
    } else {
-      copy_rwstorage(jcr, job->pool->storage, _("Job resource"));
+      copy_rwstorage(jcr, job->pool->storage, _("Pool resource"));
    }
    jcr->client = job->client;
    if (!jcr->client_name) {
          jcr->JobLevel = L_NONE;
          break;
       default:
+         jcr->JobLevel = L_FULL;
          break;
       }
    }
  */
 void copy_rwstorage(JCR *jcr, alist *storage, const char *where)
 {
-   copy_rstorage(jcr, storage, where);
-   copy_wstorage(jcr, storage, where);
+   switch(jcr->JobType) {
+   case JT_RESTORE:
+   case JT_VERIFY:
+   case JT_MIGRATE:
+      copy_rstorage(jcr, storage, where);
+      break;
+   default:
+      copy_wstorage(jcr, storage, where);
+      break;
+   }
 }
 
 
 /* Set storage override */
-void set_rwstorage(JCR *jcr, STORE *store)
+void set_rwstorage(JCR *jcr, USTORE *store)
 {
    if (!store) {
       Jmsg(jcr, M_FATAL, 0, _("No storage specified.\n"));
       return;
    }
-   set_rstorage(jcr, store);
-   set_wstorage(jcr, store);
+   switch(jcr->JobType) {
+   case JT_RESTORE:
+   case JT_VERIFY:
+   case JT_MIGRATE:
+      set_rstorage(jcr, store);
+      break;
+   default:
+      set_wstorage(jcr, store);
+      break;
+   }
 }
 
 void free_rwstorage(JCR *jcr)
       foreach_alist(st, storage) {
          jcr->rstorage->append(st);
       }
-      pm_strcpy(jcr->storage_source, where);
-   }               
-   if (jcr->rstorage) {
-      jcr->rstore = (STORE *)jcr->rstorage->first();
+      if (!jcr->rstore_source) {
+         jcr->rstore_source = get_pool_memory(PM_MESSAGE);
+      }
+      pm_strcpy(jcr->rstore_source, where);
+      if (jcr->rstorage) {
+         jcr->rstore = (STORE *)jcr->rstorage->first();
+      }
    }
 }
 
 
 /* Set storage override */
-void set_rstorage(JCR *jcr, STORE *store)
+void set_rstorage(JCR *jcr, USTORE *store)
 {
    STORE *storage;
 
-   if (!store) {
+   if (!store->store) {
       return;
    }
    if (!jcr->rstorage) {
       jcr->rstorage = New(alist(10, not_owned_by_alist));
    }
-   jcr->rstore = store;
+   jcr->rstore = store->store;
+   if (!jcr->rstore_source) {
+      jcr->rstore_source = get_pool_memory(PM_MESSAGE);
+   }
+   pm_strcpy(jcr->rstore_source, store->store_source);
    foreach_alist(storage, jcr->rstorage) {
-      if (store == storage) {
+      if (store->store == storage) {
          return;
       }
    }
    /* Store not in list, so add it */
-   jcr->rstorage->prepend(store);
+   jcr->rstorage->prepend(store->store);
 }
 
 void free_rstorage(JCR *jcr)
       }
       jcr->wstorage = New(alist(10, not_owned_by_alist));
       foreach_alist(st, storage) {
+         Dmsg1(50, "storage=%s\n", st->name());
          jcr->wstorage->append(st);
       }
-      pm_strcpy(jcr->storage_source, where);
-   }               
-   if (jcr->wstorage) {
-      jcr->wstore = (STORE *)jcr->wstorage->first();
+      if (!jcr->wstore_source) {
+         jcr->wstore_source = get_pool_memory(PM_MESSAGE);
+      }
+      pm_strcpy(jcr->wstore_source, where);
+      if (jcr->wstorage) {
+         jcr->wstore = (STORE *)jcr->wstorage->first();
+         Dmsg2(100, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
+      }
    }
 }
 
 
 /* Set storage override */
-void set_wstorage(JCR *jcr, STORE *store)
+void set_wstorage(JCR *jcr, USTORE *store)
 {
    STORE *storage;
 
-   if (!store) {
+   if (!store->store) {
       return;
    }
    if (!jcr->wstorage) {
       jcr->wstorage = New(alist(10, not_owned_by_alist));
    }
-   jcr->wstore = store;
+   jcr->wstore = store->store;
+   if (!jcr->wstore_source) {
+      jcr->wstore_source = get_pool_memory(PM_MESSAGE);
+   }
+   pm_strcpy(jcr->wstore_source, store->store_source);
+   Dmsg2(50, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
    foreach_alist(storage, jcr->wstorage) {
-      if (store == storage) {
+      if (store->store == storage) {
          return;
       }
    }
    /* Store not in list, so add it */
-   jcr->wstorage->prepend(store);
+   jcr->wstorage->prepend(store->store);
 }
 
 void free_wstorage(JCR *jcr)
 
    }
    
    if (jcr->wstore) {
+      Dmsg1(200, "Wstore=%s\n", jcr->wstore->name());
       if (jcr->rstore == jcr->wstore) {           /* deadlock */
          jcr->rstore->NumConcurrentJobs = 0;      /* back out rstore */
-         Jmsg(jcr, M_FATAL, 0, _("Job canceled. Attempt to read and write same device.\n"));
+         Jmsg(jcr, M_FATAL, 0, _("Job canceled. Attempt to read and write same device.\n"
+            "    Read storage \"%s\" (From %s) -- Write storage \"%s\" (From %s)\n"), 
+            jcr->rstore->name(), jcr->rstore_source, jcr->wstore->name(), jcr->wstore_source);
          set_jcr_job_status(jcr, JS_Canceled);
          return false;
       }
 
 
 /* 
  * Called here before the job is run to do the job
- *   specific setup.
+ *   specific setup.  Note, one of the important things to
+ *   complete in this init code is to make the definitive
+ *   choice of input and output storage devices.  This is
+ *   because immediately after the init, the job is queued
+ *   in the jobq.c code, and it checks that all the resources
+ *   (storage resources in particular) are available, so these
+ *   must all be properly defined.
+ *
+ *  previous_jr refers to the job DB record of the Job that is
+ *    going to be migrated.
+ *  prev_job refers to the job resource of the Job that is
+ *    going to be migrated.
+ *  jcr is the jcr for the current "migration" job.  It is a
+ *    control job that is put in the DB as a migration job, which
+ *    means that this job migrated a previous job to a new job.
+ *    No Volume or File data is associated with this control
+ *    job.
+ *  mig_jcr refers to the newly migrated job that is run by
+ *    the current jcr.  It is a backup job that moves (migrates) the
+ *    data written for the previous_jr into the new pool.  This
+ *    job (mig_jcr) becomes the new backup job that replaces
+ *    the original backup job.
  */
 bool do_migration_init(JCR *jcr)
 {
+   POOL_DBR pr;
+   POOL *pool;
+   char ed1[100];
+   JOB *job, *prev_job;
+   JCR *mig_jcr;                   /* newly migrated job */
+
    /* If we find a job or jobs to migrate it is previous_jr.JobId */
    if (!get_job_to_migrate(jcr)) {
       return false;
       return false;
    }
 
-  /* If pool storage specified, use it instead of job storage */
+   /* If pool storage specified, use it instead of job storage */
    copy_wstorage(jcr, jcr->pool->storage, _("Pool resource"));
 
    if (jcr->wstorage->size() == 0) {
    }
 
    create_restore_bootstrap_file(jcr);
-   return true;
-}
-
-/*
- * Do a Migration of a previous job
- *
- *  Returns:  false on failure
- *            true  on success
- */
-bool do_migration(JCR *jcr)
-{
-   POOL_DBR pr;
-   POOL *pool;
-   char ed1[100];
-   BSOCK *sd;
-   JOB *job, *prev_job;
-   JCR *mig_jcr;                   /* newly migrated job */
 
-   /* 
-    *  previous_jr refers to the job DB record of the Job that is
-    *    going to be migrated.
-    *  prev_job refers to the job resource of the Job that is
-    *    going to be migrated.
-    *  jcr is the jcr for the current "migration" job.  It is a
-    *    control job that is put in the DB as a migration job, which
-    *    means that this job migrated a previous job to a new job.
-    *    No Volume or File data is associated with this control
-    *    job.
-    *  mig_jcr refers to the newly migrated job that is run by
-    *    the current jcr.  It is a backup job that moves (migrates) the
-    *    data written for the previous_jr into the new pool.  This
-    *    job (mig_jcr) becomes the new backup job that replaces
-    *    the original backup job.
-    */
    if (jcr->previous_jr.JobId == 0 || jcr->ExpectedFiles == 0) {
       set_jcr_job_status(jcr, JS_Terminated);
       Dmsg1(dbglevel, "JobId=%d expected files == 0\n", (int)jcr->JobId);
       } else {
          Jmsg(jcr, M_INFO, 0, _("Previous Job has no data to migrate.\n"));
       }
-      migration_cleanup(jcr, jcr->JobStatus);
       return true;                    /* no work */
    }
 
    /* If pool storage specified, use it instead of job storage for backup */
    copy_wstorage(jcr, jcr->pool->storage, _("Next pool resource"));
 
+
+   return true;
+}
+
+/*
+ * Do a Migration of a previous job
+ *
+ *  Returns:  false on failure
+ *            true  on success
+ */
+bool do_migration(JCR *jcr)
+{
+   char ed1[100];
+   BSOCK *sd;
+   JCR *mig_jcr = jcr->mig_jcr;    /* newly migrated job */
+
+
    /* Print Job Start message */
    Jmsg(jcr, M_INFO, 0, _("Start Migration JobId %s, Job=%s\n"),
         edit_uint64(jcr->JobId, ed1), jcr->Job);
 "  Client:                 %s\n"
 "  FileSet:                \"%s\" %s\n"
 "  Pool:                   \"%s\" (From %s)\n"
-"  Storage:                \"%s\" (From %s)\n"
+"  Read Storage:           \"%s\" (From %s_\n"
+"  Write Storage:          \"%s\" (From %s)\n"
 "  Start time:             %s\n"
 "  End time:               %s\n"
 "  Elapsed time:           %s\n"
         jcr->client->name(),
         jcr->fileset->name(), jcr->FSCreateTime,
         jcr->pool->name(), jcr->pool_source,
-        jcr->wstore->name(), jcr->storage_source,
+        jcr->rstore->name(), jcr->rstore_source,
+        jcr->wstore->name(), jcr->wstore_source,
         sdt,
         edt,
         edit_utime(RunTime, elapsed, sizeof(elapsed)),
 
    }
 
    /* If there is a write storage use it */
-   if (jcr->wstorage) {
-      store = (STORE *)jcr->wstorage->first();
+   if (jcr->wstore) {
+      store = jcr->wstore;
    } else {
-      store = (STORE *)jcr->rstorage->first();
+      store = jcr->rstore;
    }
 
    /*
    /* Do read side of storage daemon */
    if (ok && rstore) {
       foreach_alist(storage, rstore) {
-         pm_strcpy(store_name, storage->hdr.name);
+         Dmsg1(100, "Rstore=%s\n", storage->name());
+         pm_strcpy(store_name, storage->name());
          bash_spaces(store_name);
          pm_strcpy(media_type, storage->media_type);
          bash_spaces(media_type);
    /* Do write side of storage daemon */
    if (ok && wstore) {
       foreach_alist(storage, wstore) {
-         pm_strcpy(store_name, storage->hdr.name);
+         Dmsg1(100, "Wstore=%s\n", storage->name());
+         pm_strcpy(store_name, storage->name());
          bash_spaces(store_name);
          pm_strcpy(media_type, storage->media_type);
          bash_spaces(media_type);
 
 extern void apply_pool_overrides(JCR *jcr);
 extern JobId_t run_job(JCR *jcr);
 extern bool cancel_job(UAContext *ua, JCR *jcr);
-extern STORE *get_job_storage(JOB *job);
+extern void get_job_storage(USTORE *store, JOB *job, RUN *run);
 extern void init_jcr_job_record(JCR *jcr);
 extern void copy_rwstorage(JCR *jcr, alist *storage, const char *where);
-extern void set_rwstorage(JCR *jcr, STORE *store);
+extern void set_rwstorage(JCR *jcr, USTORE *store);
 extern void free_rwstorage(JCR *jcr);
 extern void copy_wstorage(JCR *jcr, alist *storage, const char *where);
-extern void set_wstorage(JCR *jcr, STORE *store);
+extern void set_wstorage(JCR *jcr, USTORE *store);
 extern void free_wstorage(JCR *jcr);
 extern void copy_rstorage(JCR *jcr, alist *storage, const char *where);
-extern void set_rstorage(JCR *jcr, STORE *store);
+extern void set_rstorage(JCR *jcr, USTORE *store);
 extern void free_rstorage(JCR *jcr);
 extern bool setup_job(JCR *jcr);
 extern void create_clones(JCR *jcr);
 
       jcr->run_diff_pool_override = true;
    }
    if (run->storage) {
-      set_rwstorage(jcr, run->storage); /* override storage */
+      USTORE store;
+      store.store = run->storage;
+      pm_strcpy(store.store_source, _("run override"));
+      set_rwstorage(jcr, &store);     /* override storage */
    }
    if (run->msgs) {
       jcr->messages = run->msgs;      /* override messages */
 
 {
    BSOCK *sd;
    JCR *jcr = ua->jcr;
-
-   set_wstorage(jcr, store);
+   USTORE lstore;
+   
+   lstore.store = store;
+   pm_strcpy(lstore.store_source, _("unknown source"));
+   set_wstorage(jcr, &lstore);
    /* Try connecting for up to 15 seconds */
    bsendmsg(ua, _("Connecting to Storage daemon %s at %s:%d\n"),
       store->name(), store->address, store->SDport);
 
 static void do_mount_cmd(UAContext *ua, const char *command)
 {
-   STORE *store;
+   USTORE store;
    BSOCK *sd;
    JCR *jcr = ua->jcr;
    char dev_name[MAX_NAME_LENGTH];
    }
    Dmsg2(120, "%s: %s\n", command, ua->UA_sock->msg);
 
-   store = get_storage_resource(ua, true/*arg is storage*/);
-   if (!store) {
+   store.store = get_storage_resource(ua, true/*arg is storage*/);
+   pm_strcpy(store.store_source, _("unknown source"));
+   if (!store.store) {
       return;
    }
-   set_wstorage(jcr, store);
-   drive = get_storage_drive(ua, store);
+   set_wstorage(jcr, &store);
+   drive = get_storage_drive(ua, store.store);
    if (strcmp(command, "mount") == 0) {
-      slot = get_storage_slot(ua, store);
+      slot = get_storage_slot(ua, store.store);
    }
 
    Dmsg3(120, "Found storage, MediaType=%s DevName=%s drive=%d\n",
-      store->media_type, store->dev_name(), drive);
+      store.store->media_type, store.store->dev_name(), drive);
 
    if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
       bsendmsg(ua, _("Failed to connect to Storage daemon.\n"));
       return;
    }
    sd = jcr->store_bsock;
-   bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
+   bstrncpy(dev_name, store.store->dev_name(), sizeof(dev_name));
    bash_spaces(dev_name);
    if (slot > 0) {
       bnet_fsend(sd, "%s %s drive=%d slot=%d", command, dev_name, drive, slot);
 
       }
       job = (JOB *)GetResWithName(R_JOB, ua->argv[1]);
       if (job) {
-         STORE *store;
+         USTORE store;
          bsendmsg(ua, "job=%s", job->hdr.name);
          bsendmsg(ua, "pool=%s", job->pool->hdr.name);
          bsendmsg(ua, "messages=%s", job->messages->hdr.name);
          bsendmsg(ua, "client=%s", job->client->hdr.name);
-         store = get_job_storage(job);
-         bsendmsg(ua, "storage=%s", store->hdr.name);
+         get_job_storage(&store, job, NULL);
+         bsendmsg(ua, "storage=%s", store.store->name());
          bsendmsg(ua, "where=%s", job->RestoreWhere?job->RestoreWhere:"");
          bsendmsg(ua, "level=%s", level_to_str(job->JobLevel));
          bsendmsg(ua, "type=%s", job_type_to_str(job->JobType));
 
  */
 void update_slots(UAContext *ua)
 {
-   STORE *store;
+   USTORE store;
    vol_list_t *vl, *vol_list = NULL;
    MEDIA_DBR mr;
    char *slot_list;
    if (!open_db(ua)) {
       return;
    }
-   store = get_storage_resource(ua, true/*arg is storage*/);
-   if (!store) {
+   store.store = get_storage_resource(ua, true/*arg is storage*/);
+   if (!store.store) {
       return;
    }
-   set_wstorage(ua->jcr, store);
-   drive = get_storage_drive(ua, store);
+   pm_strcpy(store.store_source, _("command line"));
+   set_wstorage(ua->jcr, &store);
+   drive = get_storage_drive(ua, store.store);
 
    scan = find_arg(ua, NT_("scan")) >= 0;
    if ((i=find_arg_with_value(ua, NT_("Enabled"))) >= 0) {
       memset(&mr, 0, sizeof(mr));
       mr.Slot = vl->Slot;
       mr.InChanger = 1;
-      mr.StorageId = store->StorageId;
+      mr.StorageId = store.store->StorageId;
       /* Set InChanger to zero for this Slot */
       db_lock(ua->db);
       db_make_inchanger_unique(ua->jcr, ua->db, &mr);
       bstrncpy(mr.VolumeName, vl->VolName, sizeof(mr.VolumeName));
       db_lock(ua->db);
       if (db_get_media_record(ua->jcr, ua->db, &mr)) {
-         if (mr.Slot != vl->Slot || !mr.InChanger || mr.StorageId != store->StorageId) {
+         if (mr.Slot != vl->Slot || !mr.InChanger || mr.StorageId != store.store->StorageId) {
             mr.Slot = vl->Slot;
             mr.InChanger = 1;
-            mr.StorageId = store->StorageId;
+            mr.StorageId = store.store->StorageId;
             if (have_enabled) {
                mr.Enabled = Enabled;
             }
    }
    memset(&mr, 0, sizeof(mr));
    mr.InChanger = 1;
-   mr.StorageId = store->StorageId;
+   mr.StorageId = store.store->StorageId;
    db_lock(ua->db);
    for (int i=1; i <= max_slots; i++) {
       if (slot_list[i]) {
  */
 static int do_label(UAContext *ua, const char *cmd, int relabel)
 {
-   STORE *store;
+   USTORE store;
    BSOCK *sd;
    char dev_name[MAX_NAME_LENGTH];
    MEDIA_DBR mr, omr;
       label_barcodes = true;
    }
 
-   store = get_storage_resource(ua, true/*use default*/);
-   if (!store) {
+   store.store = get_storage_resource(ua, true/*use default*/);
+   if (!store.store) {
       return 1;
    }
-   set_wstorage(ua->jcr, store);
-   drive = get_storage_drive(ua, store);
+   pm_strcpy(store.store_source, _("command line"));
+   set_wstorage(ua->jcr, &store);
+   drive = get_storage_drive(ua, store.store);
 
    if (label_barcodes) {
       label_from_barcodes(ua, drive);
    if (i >= 0) {
       mr.Slot = atoi(ua->argv[i]);
       mr.InChanger = 1;               /* assumed if we are labeling it */
-   } else if (store->autochanger) {
+   } else if (store.store->autochanger) {
       if (!get_pint(ua, _("Enter slot (0 or Enter for none): "))) {
          return 1;
       }
       mr.Slot = ua->pint32_val;
       mr.InChanger = 1;               /* assumed if we are labeling it */
    }
-   mr.StorageId = store->StorageId;
+   mr.StorageId = store.store->StorageId;
 
-   bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType));
+   bstrncpy(mr.MediaType, store.store->media_type, sizeof(mr.MediaType));
 
    /* Must select Pool if not already done */
    if (pr.PoolId == 0) {
          }
       }
       if (ua->automount) {
-         bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
+         bstrncpy(dev_name, store.store->dev_name(), sizeof(dev_name));
          bsendmsg(ua, _("Requesting to mount %s ...\n"), dev_name);
          bash_spaces(dev_name);
          bnet_fsend(sd, "mount %s drive=%d", dev_name, drive);
 
    JOB *job;
    JCR *jcr = ua->jcr;
    POOL *pool;
+   USTORE store;
    RUN *run;
    time_t runtime;
    bool found = false;
          bstrncpy(pr.Name, "*UnknownPool*", sizeof(pr.Name));
       }
       mr.PoolId = jcr->jr.PoolId;
-      if (run->storage) {
-         jcr->wstore = run->storage;
-      } else {
-         jcr->wstore = get_job_storage(job);
-      }
-      mr.StorageId = jcr->wstore->StorageId;
+      get_job_storage(&store, job, run);
+      mr.StorageId = store.store->StorageId;
       if (!find_next_volume_for_append(jcr, &mr, 1, false/*no create*/)) {
          bsendmsg(ua, _("Could not find next Volume for Job %s (%s, %s).\n"),
             job->hdr.name, pr.Name, level_to_str(run->level));
 
    JOB *job = NULL;
    JOB *verify_job = NULL;
    JOB *previous_job = NULL;
-   STORE *store = NULL;
+   USTORE store;
    CLIENT *client = NULL;
    FILESET *fileset = NULL;
    POOL *pool = NULL;
    }
 
    if (store_name) {
-      store = (STORE *)GetResWithName(R_STORAGE, store_name);
-      if (!store) {
+      store.store = (STORE *)GetResWithName(R_STORAGE, store_name);
+      pm_strcpy(store.store_source, _("command line"));
+      if (!store.store) {
          if (*store_name != 0) {
             bsendmsg(ua, _("Storage \"%s\" not found.\n"), store_name);
          }
-         store = select_storage_resource(ua);
+         store.store = select_storage_resource(ua);
+         pm_strcpy(store.store_source, _("user selection"));
       }
    } else {
-      store = get_job_storage(job);            /* use default */
+      get_job_storage(&store, job, NULL);      /* use default */
    }
-   if (!store) {
+   if (!store.store) {
       return 1;
-   } else if (!acl_access_ok(ua, Storage_ACL, store->name())) {
+   } else if (!acl_access_ok(ua, Storage_ACL, store.store->name())) {
       bsendmsg(ua, _("No authorization. Storage \"%s\".\n"),
-               store->name());
+               store.store->name());
       return 0;
    }
-   Dmsg1(800, "Using storage=%s\n", store->name());
+   Dmsg1(800, "Using storage=%s\n", store.store->name());
 
    if (pool_name) {
       pool = (POOL *)GetResWithName(R_POOL, pool_name);
 
    jcr->verify_job = verify_job;
    jcr->previous_job = previous_job;
-   set_rwstorage(jcr, store);
+   set_rwstorage(jcr, &store);
    jcr->client = client;
    jcr->fileset = fileset;
    jcr->pool = pool;
          goto try_again;
       case 1:
          /* Storage */
-         store = select_storage_resource(ua);
-         if (store) {
-            set_rwstorage(jcr, store);
+         store.store = select_storage_resource(ua);
+         if (store.store) {
+            pm_strcpy(store.store_source, _("user selection"));
+            set_rwstorage(jcr, &store);
             goto try_again;
          }
          break;
 
 static void do_storage_status(UAContext *ua, STORE *store)
 {
    BSOCK *sd;
+   USTORE lstore;
 
-   set_wstorage(ua->jcr, store);
+   lstore.store = store;
+   pm_strcpy(lstore.store_source, _("unknown source"));
+   set_wstorage(ua->jcr, &lstore);
    /* Try connecting for up to 15 seconds */
    bsendmsg(ua, _("Connecting to Storage daemon %s at %s:%d\n"),
       store->name(), store->address, store->SDport);
    time_t runtime;
    RUN *run;
    JOB *job;
-   STORE* store;
    int level, num_jobs = 0;
    int priority;
    bool hdr_printed = false;
          continue;
       }
       for (run=NULL; (run = find_next_run(run, job, runtime, days)); ) {
+         USTORE store;
          level = job->JobLevel;
          if (run->level) {
             level = run->level;
          if (run->Priority) {
             priority = run->Priority;
          }
-         if (run->storage) {
-            store = run->storage;
-         } else {
-            store = get_job_storage(job);
-         }
          if (!hdr_printed) {
             prt_runhdr(ua);
             hdr_printed = true;
          sp->priority = priority;
          sp->runtime = runtime;
          sp->pool = run->pool;
-         sp->store = store;
+         get_job_storage(&store, job, run);
+         sp->store = store.store;
          sched.binary_insert_multiple(sp, my_compare);
          num_jobs++;
       }
 
    };
    POOLMEM *client_uname;             /* client uname */
    POOLMEM *pool_source;              /* Where pool came from */
-   POOLMEM *storage_source;           /* Where storage came from */
+   POOLMEM *rstore_source;            /* Where read storage came from */
+   POOLMEM *wstore_source;            /* Where write storage came from */
    int replace;                       /* Replace option */
    int NumVols;                       /* Number of Volume used in pool */
    int reschedule_count;              /* Number of times rescheduled */
 
 static void scan_blocks();
 static void set_volume_name(const char *VolName, int volnum);
 static void rawfill_cmd();
-static void bfill_cmd();
 static bool open_the_device();
 static void autochangercmd();
 static void do_unfill();
 }
 
 
-/*
- * Fill a tape using Bacula block writes
- */
-static void bfill_cmd()
-{
-   DEV_BLOCK *block = dcr->block;
-   uint32_t block_num = 0;
-   uint32_t *p;
-   int my_errno;
-   int fd;
-   uint32_t i;
-
-   fd = open("/dev/urandom", O_RDONLY);
-   if (fd) {
-      read(fd, block->buf, block->buf_len);
-      close(fd);
-   } else {
-      uint32_t *p = (uint32_t *)block->buf;
-      srandom(time(NULL));
-      for (i=0; i<block->buf_len/sizeof(uint32_t); i++) {
-         p[i] = random();
-      }
-   }
-   p = (uint32_t *)block->buf;
-   Pmsg1(0, _("Begin writing Bacula blocks of %u bytes.\n"), block->buf_len);
-   for ( ;; ) {
-      *p = block_num;
-      block->binbuf = block->buf_len;
-      block->bufp = block->buf + block->binbuf;
-      if (!write_block_to_dev(dcr)) {
-         break;
-      }
-      if ((block_num++ % 100) == 0) {
-         printf("+");
-         fflush(stdout);
-      }
-      p[0] += p[13];
-      for (i=1; i<(block->buf_len/sizeof(uint32_t)-1); i++) {
-         p[i] += p[i-1];
-      }
-   }
-   my_errno = errno;
-   printf("\n");
-   printf(_("Write failed at block %u.\n"), block_num);
-   weofcmd();
-}
-
 
 struct cmdstruct { const char *key; void (*func)(); const char *help; };
 static struct cmdstruct commands[] = {
  {NT_("autochanger"),autochangercmd, _("test autochanger")},
  {NT_("bsf"),       bsfcmd,       _("backspace file")},
  {NT_("bsr"),       bsrcmd,       _("backspace record")},
- {NT_("bfill"),     bfill_cmd,    _("fill tape using Bacula writes")},
  {NT_("cap"),       capcmd,       _("list device capabilities")},
  {NT_("clear"),     clearcmd,     _("clear tape errors")},
  {NT_("eod"),       eodcmd,       _("go to end of Bacula data for append")},
 
 
 #undef  VERSION
 #define VERSION "1.39.29"
-#define BDATE   "20 November 2006"
-#define LSMDATE "20Nov06"
+#define BDATE   "24 November 2006"
+#define LSMDATE "24Nov06"
+
 #define PROG_COPYRIGHT "Copyright (C) 2000-%s Free Software Foundation Europe e.V.\n"
 #define BYEAR "2006"       /* year for copyright messages in progs */
 
 
 
 General:
 22Nov06
+kes  Separate read/write source strings to keep track of where
+     storage devices are used in a job.
+kes  Implement a new method of keeping track of which storage 
+     device is used in a Job.  USTORE keeps both a pointer to the
+     resource and to the source string.
+kes  Modify all code to use new storage set subroutines in job.c
+kes  Modify migrate.c so that the definitive selection of the storage
+     resource is done in the do_migration_init() routine prior to
+     the job going into the job queue.  This permits accurate 
+     deadlock detection (same read and write storage resource).
+kes  Remove bfill from btape (I think it was a left over stub).
+22Nov06
 kes  Make sure that the storage for a job is pulled first from
      the Pool and if not from the Job.  
 kes  Ensure that either the Pool or the Job specifies a Storage