X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fstored%2Fdircmd.c;h=210f30b8b9606f0be89ba1eb3f92be11e9229cc0;hb=28346ad7fe97a74998f04157c8c63b39e4717ac8;hp=7713d9626f5a7e483bc6ae208caa2c305d1e2933;hpb=48d6e0f64731f3e81f84a687e4cc4320c71e901e;p=bacula%2Fbacula diff --git a/bacula/src/stored/dircmd.c b/bacula/src/stored/dircmd.c index 7713d9626f..210f30b8b9 100644 --- a/bacula/src/stored/dircmd.c +++ b/bacula/src/stored/dircmd.c @@ -6,9 +6,16 @@ * subcommands that are handled * in job.c. * + * N.B. in this file, in general we must use P(dev->mutex) rather + * than lock_device(dev) so that we can examine the blocked + * state rather than blocking ourselves. In some "safe" cases, + * we can do things to a blocked device. CAREFUL!!!! + * * File daemon commands are handled in fdcmd.c * * Kern Sibbald, May MMI + * + * Version $Id$ * */ /* @@ -60,7 +67,9 @@ static int cancel_cmd(JCR *cjcr); static int mount_cmd(JCR *jcr); static int unmount_cmd(JCR *jcr); static int status_cmd(JCR *sjcr); -static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *vname, char *poolname); +static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *vname, char *poolname, + int Slot); +static void send_blocked_status(JCR *jcr, DEVICE *dev); struct s_cmds { char *cmd; @@ -102,7 +111,7 @@ void connection_request(void *arg) BSOCK *bs = (BSOCK *)arg; JCR *jcr; int i, found, quit; - int bnet_stat; + int bnet_stat = 0; char name[MAX_NAME_LENGTH]; if (bnet_recv(bs) <= 0) { @@ -127,7 +136,7 @@ void connection_request(void *arg) * Authenticate the Director */ if (!authenticate_director(jcr)) { - Emsg0(M_FATAL, 0, _("Unable to authenticate Director\n")); + Jmsg(jcr, M_FATAL, 0, _("Unable to authenticate Director\n")); free_jcr(jcr); return; } @@ -214,7 +223,7 @@ static int cancel_cmd(JCR *cjcr) } else { bnet_fsend(dir, _("3993 Error scanning cancel command.\n")); } - bnet_sig(dir, BNET_EOF); + bnet_sig(dir, BNET_EOD); return 1; } @@ -224,18 +233,19 @@ static int cancel_cmd(JCR *cjcr) */ static int label_cmd(JCR *jcr) { - char *dname, *volname, *poolname, *mtype; + POOLMEM *dname, *volname, *poolname, *mtype; BSOCK *dir = jcr->dir_bsock; DEVRES *device; DEVICE *dev; int found = 0; - - dname = (char *) get_memory(dir->msglen+1); - volname = (char *) get_memory(dir->msglen+1); - poolname = (char *) get_memory(dir->msglen+1); - mtype = (char *) get_memory(dir->msglen+1); - if (sscanf(dir->msg, "label %s VolumeName=%s PoolName=%s MediaType=%s", - dname, volname, poolname, mtype) == 4) { + int slot; + + dname = get_memory(dir->msglen+1); + volname = get_memory(dir->msglen+1); + poolname = get_memory(dir->msglen+1); + mtype = get_memory(dir->msglen+1); + if (sscanf(dir->msg, "label %s VolumeName=%s PoolName=%s MediaType=%s Slot=%d", + dname, volname, poolname, mtype, &slot) == 5) { unbash_spaces(dname); unbash_spaces(volname); unbash_spaces(poolname); @@ -255,17 +265,21 @@ static int label_cmd(JCR *jcr) /******FIXME**** compare MediaTypes */ jcr->device = device; dev = device->dev; - P(dev->mutex); + + P(dev->mutex); /* Use P to avoid indefinite block */ if (!(dev->state & ST_OPENED)) { if (open_dev(dev, volname, READ_WRITE) < 0) { bnet_fsend(dir, _("3994 Connot open device: %s\n"), strerror_dev(dev)); } else { - label_volume_if_ok(jcr, dev, volname, poolname); + label_volume_if_ok(jcr, dev, volname, poolname, slot); force_close_dev(dev); } + /* Under certain "safe" conditions, we can steal the lock */ } else if (dev->dev_blocked && - dev->dev_blocked != BST_DOING_ACQUIRE) { /* device blocked? */ - label_volume_if_ok(jcr, dev, volname, poolname); + (dev->dev_blocked == BST_UNMOUNTED || + dev->dev_blocked == BST_WAITING_FOR_SYSOP || + dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP)) { + label_volume_if_ok(jcr, dev, volname, poolname, slot); } else if (dev->state & ST_READ || dev->num_writers) { if (dev->state & ST_READ) { bnet_fsend(dir, _("3901 Device %s is busy with 1 reader.\n"), @@ -275,7 +289,7 @@ static int label_cmd(JCR *jcr) dev_name(dev), dev->num_writers); } } else { /* device not being used */ - label_volume_if_ok(jcr, dev, volname, poolname); + label_volume_if_ok(jcr, dev, volname, poolname, slot); } V(dev->mutex); } else { @@ -290,7 +304,7 @@ static int label_cmd(JCR *jcr) free_memory(volname); free_memory(poolname); free_memory(mtype); - bnet_sig(dir, BNET_EOF); + bnet_sig(dir, BNET_EOD); return 1; } @@ -300,21 +314,33 @@ static int label_cmd(JCR *jcr) * * Enter with the mutex set */ -static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *vname, char *poolname) +static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *vname, char *poolname, + int slot) { BSOCK *dir = jcr->dir_bsock; DEV_BLOCK *block; - int blocked; - pthread_t no_wait_id; + bsteal_lock_t hold; - blocked = dev->dev_blocked; /* save any prev blocked state */ - no_wait_id = dev->no_wait_id; - dev->dev_blocked = BST_WRITING_LABEL; - dev->no_wait_id = pthread_self(); /* let us use the tape */ - V(dev->mutex); /* release lock */ + steal_device_lock(dev, &hold, BST_WRITING_LABEL); strcpy(jcr->VolumeName, vname); + jcr->VolCatInfo.Slot = slot; + autoload_device(jcr, dev, 0, dir); /* autoload if possible */ block = new_block(dev); + + /* Ensure that the device is open -- not autoload_device() closes it */ + for ( ; !(dev->state & ST_OPENED); ) { + if (open_dev(dev, jcr->VolumeName, READ_WRITE) < 0) { + if (dev->dev_errno == EAGAIN || dev->dev_errno == EBUSY) { + sleep(30); + } + bnet_fsend(dir, _("3903 Unable to open device %s. ERR=%s\n"), + dev_name(dev), strerror_dev(dev)); + goto bail_out; + } + } + + /* See what we have for a Volume */ switch (read_dev_volume_label(jcr, dev, block)) { case VOL_NAME_ERROR: case VOL_VERSION_ERROR: @@ -325,7 +351,10 @@ already labeled: %s\n"), dev->VolHdr.VolName); break; case VOL_IO_ERROR: case VOL_NO_LABEL: - write_volume_label_to_dev(jcr, jcr->device, vname, poolname); + if (!write_volume_label_to_dev(jcr, jcr->device, vname, poolname)) { + bnet_fsend(dir, _("3903 Failed to label Volume: ERR=%s\n"), strerror_dev(dev)); + break; + } strcpy(jcr->VolumeName, vname); bnet_fsend(dir, _("3000 OK label. Volume=%s Device=%s\n"), vname, dev->dev_name); @@ -335,10 +364,9 @@ already labeled: %s\n"), dev->VolHdr.VolName); Unknown status %d from read_volume_label()\n"), jcr->label_status); break; } +bail_out: free_block(block); - P(dev->mutex); - dev->dev_blocked = blocked; /* reset blocked state */ - dev->no_wait_id = no_wait_id; /* reset blocking thread id */ + return_device_lock(dev, &hold); } @@ -349,17 +377,14 @@ Unknown status %d from read_volume_label()\n"), jcr->label_status); */ static int read_label(JCR *jcr, DEVICE *dev) { + int stat; BSOCK *dir = jcr->dir_bsock; DEV_BLOCK *block; - int blocked; - pthread_t no_wait_id; - int stat; +#ifndef NEW_LOCK + bsteal_lock_t hold; - blocked = dev->dev_blocked; /* save any prev blocked state */ - no_wait_id = dev->no_wait_id; - dev->dev_blocked = BST_DOING_ACQUIRE; - dev->no_wait_id = pthread_self(); /* let us use the tape */ - V(dev->mutex); /* release lock */ + steal_device_lock(dev, &hold, BST_DOING_ACQUIRE); +#endif jcr->VolumeName[0] = 0; block = new_block(dev); @@ -376,9 +401,9 @@ static int read_label(JCR *jcr, DEVICE *dev) break; } free_block(block); - P(dev->mutex); - dev->dev_blocked = blocked; /* reset blocked state */ - dev->no_wait_id = no_wait_id; /* reset blocking thread id */ +#ifndef NEW_LOCK + return_device_lock(dev, &hold); +#endif return stat; } @@ -410,7 +435,7 @@ static int mount_cmd(JCR *jcr) if (found) { jcr->device = device; dev = device->dev; - P(dev->mutex); + P(dev->mutex); /* Use P to avoid indefinite block */ switch (dev->dev_blocked) { /* device blocked? */ DEV_BLOCK *block; case BST_WAITING_FOR_SYSOP: @@ -501,7 +526,7 @@ static int mount_cmd(JCR *jcr) bnet_fsend(dir, _("3906 Error scanning mount command: %s\n"), dev_name); } free_memory(dev_name); - bnet_sig(dir, BNET_EOF); + bnet_sig(dir, BNET_EOD); return 1; } @@ -533,7 +558,7 @@ static int unmount_cmd(JCR *jcr) if (found) { jcr->device = device; dev = device->dev; - P(dev->mutex); + P(dev->mutex); /* Use P to avoid indefinite block */ if (!(dev->state & ST_OPENED)) { Dmsg0(90, "Device already unmounted\n"); bnet_fsend(dir, _("3901 Device %s is already unmounted.\n"), dev_name(dev)); @@ -541,6 +566,9 @@ static int unmount_cmd(JCR *jcr) } else if (dev->dev_blocked == BST_WAITING_FOR_SYSOP) { Dmsg2(90, "%d waiter dev_block=%d. doing unmount\n", dev->num_waiting, dev->dev_blocked); + if (dev->capabilities & CAP_OFFLINEUNMOUNT) { + offline_dev(dev); + } force_close_dev(dev); dev->dev_blocked = BST_UNMOUNTED_WAITING_FOR_SYSOP; bnet_fsend(dir, _("3001 Device %s unmounted.\n"), dev_name(dev)); @@ -567,6 +595,9 @@ static int unmount_cmd(JCR *jcr) } else { /* device not being used */ Dmsg0(90, "Device not in use, unmounting\n"); block_device(dev, BST_UNMOUNTED); + if (dev->capabilities & CAP_OFFLINEUNMOUNT) { + offline_dev(dev); + } force_close_dev(dev); bnet_fsend(dir, _("3002 Device %s unmounted.\n"), dev_name(dev)); } @@ -580,7 +611,7 @@ static int unmount_cmd(JCR *jcr) bnet_fsend(dir, _("3907 Error scanning unmount command: %s\n"), dname); } free_memory(dname); - bnet_sig(dir, BNET_EOF); + bnet_sig(dir, BNET_EOD); return 1; } @@ -601,27 +632,15 @@ static int status_cmd(JCR *jcr) bnet_fsend(user, _("Daemon started %s, %d Job%s run.\n"), dt, last_job.NumJobs, last_job.NumJobs == 1 ? "" : "s"); if (last_job.NumJobs > 0) { - char *termstat, jstat[2]; + char termstat[30]; bstrftime(dt, sizeof(dt), last_job.end_time); bnet_fsend(user, _("Last Job %s finished at %s\n"), last_job.Job, dt); - switch (last_job.JobStatus) { - case JS_Terminated: - termstat = _("OK"); - break; - case JS_ErrorTerminated: - termstat = _("Error"); - break; - default: - jstat[0] = last_job.JobStatus; - jstat[1] = 0; - termstat = jstat; - break; - } - + + jobstatus_to_ascii(last_job.JobStatus, termstat, sizeof(termstat)); bnet_fsend(user, _(" Files=%s Bytes=%s Termination Status=%s\n"), - edit_uint_with_commas(last_job.JobFiles, b1), - edit_uint_with_commas(last_job.JobBytes, b2), + edit_uint64_with_commas(last_job.JobFiles, b1), + edit_uint64_with_commas(last_job.JobBytes, b2), termstat); } @@ -636,44 +655,23 @@ static int status_cmd(JCR *jcr) } else { bnet_fsend(user, _("Device %s open but no Bacula volume is mounted.\n"), dev_name(dev)); } - switch (dev->dev_blocked) { - case BST_UNMOUNTED: - bnet_fsend(user, _(" Deviced is blocked. User unmounted.\n")); - break; - case BST_UNMOUNTED_WAITING_FOR_SYSOP: - bnet_fsend(user, _(" Deviced is blocked. User unmounted during wait for media/mount.\n")); - break; - case BST_WAITING_FOR_SYSOP: - if (jcr->JobStatus == JS_WaitMount) { - bnet_fsend(user, _(" Device is blocked waiting for mount.\n")); - } else { - bnet_fsend(user, _(" Device is blocked waiting for appendable media.\n")); - } - break; - case BST_DOING_ACQUIRE: - bnet_fsend(user, _(" Device is being initialized.\n")); - break; - case BST_WRITING_LABEL: - bnet_fsend(user, _(" Device is blocked labeling a Volume.\n")); - break; - default: - break; - } + send_blocked_status(jcr, dev); bpb = dev->VolCatInfo.VolCatBlocks; if (bpb <= 0) { bpb = 1; } bpb = dev->VolCatInfo.VolCatBytes / bpb; bnet_fsend(user, _(" Total Bytes=%s Blocks=%s Bytes/block=%s\n"), - edit_uint_with_commas(dev->VolCatInfo.VolCatBytes, b1), - edit_uint_with_commas(dev->VolCatInfo.VolCatBlocks, b2), - edit_uint_with_commas(bpb, b3)); + edit_uint64_with_commas(dev->VolCatInfo.VolCatBytes, b1), + edit_uint64_with_commas(dev->VolCatInfo.VolCatBlocks, b2), + edit_uint64_with_commas(bpb, b3)); bnet_fsend(user, _(" Positioned at File=%s Block=%s\n"), - edit_uint_with_commas(dev->file, b1), - edit_uint_with_commas(dev->block_num, b2)); + edit_uint64_with_commas(dev->file, b1), + edit_uint64_with_commas(dev->block_num, b2)); } else { bnet_fsend(user, _("Device %s is not open.\n"), dev_name(dev)); + send_blocked_status(jcr, dev); } } } @@ -684,11 +682,13 @@ static int status_cmd(JCR *jcr) /* NOTE, we reuse a calling argument jcr. Be warned! */ for (jcr=NULL; (jcr=get_next_jcr(jcr)); ) { if (jcr->JobStatus == JS_WaitFD) { - bnet_fsend(user, _("Job %s is waiting for the Client connection.\n"), - jcr->Job); + bnet_fsend(user, _("%s Job %s waiting for Client connection.\n"), + job_type_to_str(jcr->JobType), jcr->Job); } if (jcr->device) { - bnet_fsend(user, _("Job %s is using device %s\n"), + bnet_fsend(user, _("%s %s job %s is using device %s\n"), + job_level_to_str(jcr->JobLevel), + job_type_to_str(jcr->JobType), jcr->Job, jcr->device->device_name); sec = time(NULL) - jcr->run_time; if (sec <= 0) { @@ -696,9 +696,9 @@ static int status_cmd(JCR *jcr) } bps = jcr->JobBytes / sec; bnet_fsend(user, _(" Files=%s Bytes=%s Bytes/sec=%s\n"), - edit_uint_with_commas(jcr->JobFiles, b1), - edit_uint_with_commas(jcr->JobBytes, b2), - edit_uint_with_commas(bps, b3)); + edit_uint64_with_commas(jcr->JobFiles, b1), + edit_uint64_with_commas(jcr->JobBytes, b2), + edit_uint64_with_commas(bps, b3)); found = 1; #ifdef DEBUG if (jcr->file_bsock) { @@ -722,6 +722,35 @@ static int status_cmd(JCR *jcr) #endif bnet_fsend(user, "====\n"); - bnet_sig(user, BNET_EOF); + bnet_sig(user, BNET_EOD); return 1; } + +static void send_blocked_status(JCR *jcr, DEVICE *dev) +{ + BSOCK *user = jcr->dir_bsock; + + switch (dev->dev_blocked) { + case BST_UNMOUNTED: + bnet_fsend(user, _(" Device is BLOCKED. User unmounted.\n")); + break; + case BST_UNMOUNTED_WAITING_FOR_SYSOP: + bnet_fsend(user, _(" Device is BLOCKED. User unmounted during wait for media/mount.\n")); + break; + case BST_WAITING_FOR_SYSOP: + if (jcr->JobStatus == JS_WaitMount) { + bnet_fsend(user, _(" Device is BLOCKED waiting for mount.\n")); + } else { + bnet_fsend(user, _(" Device is BLOCKED waiting for appendable media.\n")); + } + break; + case BST_DOING_ACQUIRE: + bnet_fsend(user, _(" Device is being initialized.\n")); + break; + case BST_WRITING_LABEL: + bnet_fsend(user, _(" Device is blocked labeling a Volume.\n")); + break; + default: + break; + } +}