add support for obtaining sense status and source slot of a media
authorrobert <robert@openbsd.org>
Tue, 31 Aug 2021 05:29:55 +0000 (05:29 +0000)
committerrobert <robert@openbsd.org>
Tue, 31 Aug 2021 05:29:55 +0000 (05:29 +0000)
this fixes a bug in bacula where the catalog was not properly kept
up-to-date if a tape was in a drive becuse its source slot was
unknown

based on code from FreeBSD; ok krw@

picker 0:  sense: <0x00/0x00> voltag: <:0> avoltag: <:0> source: <>
slot 0: <ACCESS,FULL> sense: <0x00/0x00> voltag: <XX1168L1:0> avoltag: <:0> source: <slot 0>
slot 1: <ACCESS,FULL> sense: <0x00/0x00> voltag: <XX1187L1:0> avoltag: <:0> source: <slot 1>
slot 2: <ACCESS,FULL> sense: <0x00/0x00> voltag: <XX1184L1:0> avoltag: <:0> source: <slot 2>
slot 3: <ACCESS,FULL> sense: <0x00/0x00> voltag: <XX1195L1:0> avoltag: <:0> source: <slot 3>
slot 4: <ACCESS,FULL> sense: <0x00/0x00> voltag: <XX1037L1:0> avoltag: <:0> source: <slot 4>
slot 5: <ACCESS,FULL> sense: <0x00/0x00> voltag: <XX1038L1:0> avoltag: <:0> source: <slot 5>
slot 6: <ACCESS,FULL> sense: <0x00/0x00> voltag: <XX1166L1:0> avoltag: <:0> source: <slot 6>
slot 7: <ACCESS,FULL> sense: <0x00/0x00> voltag: <XX1167L1:0> avoltag: <:0> source: <slot 7>
slot 8: <ACCESS,FULL> sense: <0x00/0x00> voltag: <XX1180L1:0> avoltag: <:0> source: <slot 8>
slot 9: <ACCESS,FULL> sense: <0x00/0x00> voltag: <XX1186L1:0> avoltag: <:0> source: <slot 9>
slot 10: <ACCESS> sense: <0x00/0x00> voltag: <:0> avoltag: <:0> source: <picker 0>
slot 11: <ACCESS,FULL> sense: <0x00/0x00> voltag: <XX1182L1:0> avoltag: <:0> source: <slot 11>
slot 12: <ACCESS,FULL> sense: <0x00/0x00> voltag: <XX1181L1:0> avoltag: <:0> source: <slot 12>
slot 13: <ACCESS,FULL> sense: <0x00/0x00> voltag: <XX1196L1:0> avoltag: <:0> source: <slot 13>
slot 14: <ACCESS,FULL> sense: <0x00/0x00> voltag: <XX1169L1:0> avoltag: <:0> source: <slot 14>
slot 15: <ACCESS,FULL> sense: <0x00/0x00> voltag: <XX1197L1:0> avoltag: <:0> source: <slot 15>
slot 16: <ACCESS,FULL> sense: <0x00/0x00> voltag: <XX1165L1:0> avoltag: <:0> source: <slot 16>
slot 17: <ACCESS,FULL> sense: <0x00/0x00> voltag: <XX1199L1:0> avoltag: <:0> source: <slot 17>
slot 18: <ACCESS,FULL> sense: <0x00/0x00> voltag: <XX1189L1:0> avoltag: <:0> source: <slot 18>
slot 19: <ACCESS,FULL> sense: <0x00/0x00> voltag: <XX1185L1:0> avoltag: <:0> source: <slot 19>
slot 20: <ACCESS,FULL> sense: <0x00/0x00> voltag: <XX1198L1:0> avoltag: <:0> source: <slot 20>
slot 21: <ACCESS,FULL> sense: <0x00/0x00> voltag: <XX1039L1:0> avoltag: <:0> source: <slot 21>
slot 22: <ACCESS,FULL> sense: <0x00/0x00> voltag: <XX1035L1:0> avoltag: <:0> source: <slot 22>
slot 23: <ACCESS,FULL> sense: <0x00/0x00> voltag: <XX1188L1:0> avoltag: <:0> source: <slot 23>
drive 0: <ACCESS,FULL> sense: <0x00/0x00> voltag: <XX1183L1:0> avoltag: <:0> source: <slot 10>

bin/chio/chio.c
sys/scsi/ch.c
sys/sys/chio.h

index bec50cb..8ec01b1 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: chio.c,v 1.27 2021/06/26 15:42:58 deraadt Exp $       */
+/*     $OpenBSD: chio.c,v 1.28 2021/08/31 05:29:55 robert Exp $        */
 /*     $NetBSD: chio.c,v 1.1.1.1 1996/04/03 00:34:38 thorpej Exp $     */
 
 /*
@@ -59,6 +59,7 @@ static        int parse_element_type(char *);
 static int parse_element_unit(char *);
 static int parse_special(char *);
 static int is_special(char *);
+static const char * element_type_name(int et);
 static char *bits_to_string(int, const char *);
 static void find_voltag(char *, int *, int *);
 static void check_source_drive(int);
@@ -104,6 +105,8 @@ static      int changer_fd;
 static char *changer_name;
 static int avoltag;
 static int pvoltag;
+static int sense;
+static int source;
 
 int
 main(int argc, char *argv[])
@@ -486,8 +489,14 @@ do_status(char *cname, int argc, char *argv[])
 
        optreset = 1;
        optind = 1;
-       while ((c = getopt(argc, argv, "vVa")) != -1) {
+       while ((c = getopt(argc, argv, "SsvVa")) != -1) {
                switch (c) {
+               case 's':
+                       sense = 1;
+                       break;
+               case 'S':
+                       source = 1;
+                       break;
                case 'v':
                        pvoltag = 1;
                        break;
@@ -495,7 +504,7 @@ do_status(char *cname, int argc, char *argv[])
                        avoltag = 1;
                        break;
                case 'a':
-                       pvoltag = avoltag = 1;
+                       pvoltag = avoltag = source = sense = 1;
                        break;
                default:
                        goto usage;
@@ -589,6 +598,10 @@ do_status(char *cname, int argc, char *argv[])
                                 &(cmd.cesr_data[i]);
                        printf("%s %d: %s", description, i,
                            bits_to_string(ces->ces_flags, CESTATUS_BITS));
+                       if (sense)
+                               printf(" sense: <0x%02x/0x%02x>",
+                                      ces->ces_sensecode,
+                                      ces->ces_sensequal);
                        if (pvoltag)
                                printf(" voltag: <%s:%d>",
                                       ces->ces_pvoltag.cv_volid,
@@ -597,6 +610,15 @@ do_status(char *cname, int argc, char *argv[])
                                printf(" avoltag: <%s:%d>",
                                       ces->ces_avoltag.cv_volid,
                                       ces->ces_avoltag.cv_serial);
+                       if (source) {
+                               if (ces->ces_flags & CESTATUS_ACCESS)
+                                       printf(" source: <%s %d>",
+                                               element_type_name(
+                                                       ces->ces_source_type),
+                                               ces->ces_source_addr);
+                               else
+                                       printf(" source: <>");
+                       }
                        printf("\n");
                }
 
@@ -765,6 +787,18 @@ parse_element_type(char *cp)
        errx(1, "invalid element type `%s'", cp);
 }
 
+static const char *
+element_type_name(int et)
+{
+       int i;
+
+       for (i = 0; elements[i].et_name != NULL; i++)
+               if (elements[i].et_type == et)
+                       return elements[i].et_name;
+
+       return "unknown";
+}
+
 static int
 parse_element_unit(char *cp)
 {
index 672bd95..7672970 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ch.c,v 1.68 2021/03/12 10:22:46 jsg Exp $     */
+/*     $OpenBSD: ch.c,v 1.69 2021/08/31 05:29:55 robert Exp $  */
 /*     $NetBSD: ch.c,v 1.26 1997/02/21 22:06:52 thorpej Exp $  */
 
 /*
@@ -514,11 +514,53 @@ copy_voltag(struct changer_voltag *uvoltag, struct volume_tag *voltag)
  * changer_element_status structure.
  */
 static void
-copy_element_status(int flags, struct read_element_status_descriptor *desc,
+copy_element_status(struct ch_softc *sc, int flags,
+    struct read_element_status_descriptor *desc,
     struct changer_element_status *ces)
 {
+       u_int16_t eaddr = _2btol(desc->eaddr);
+       u_int16_t et;
+
+       for (et = CHET_MT; et <= CHET_DT; et++) {
+               if ((sc->sc_firsts[et] <= eaddr)
+                   && ((sc->sc_firsts[et] + sc->sc_counts[et])
+                   > eaddr)) {
+                       ces->ces_addr = eaddr - sc->sc_firsts[et];
+                       ces->ces_type = et;
+                       break;
+               }
+       }
+
        ces->ces_flags = desc->flags1;
 
+       ces->ces_sensecode = desc->sense_code;
+       ces->ces_sensequal = desc->sense_qual;
+
+       if (desc->flags2 & READ_ELEMENT_STATUS_INVERT)
+               ces->ces_flags |= READ_ELEMENT_STATUS_EXCEPT;
+
+       if (desc->flags2 & READ_ELEMENT_STATUS_SVALID) {
+               eaddr = _2btol(desc->ssea);
+
+               /* convert source address to logical format */
+               for (et = CHET_MT; et <= CHET_DT; et++) {
+                       if ((sc->sc_firsts[et] <= eaddr)
+                           && ((sc->sc_firsts[et] + sc->sc_counts[et])
+                               > eaddr)) {
+                               ces->ces_source_addr =
+                                       eaddr - sc->sc_firsts[et];
+                               ces->ces_source_type = et;
+                               ces->ces_flags |= READ_ELEMENT_STATUS_ACCESS;
+                               break;
+                       }
+               }
+
+               if (!(ces->ces_flags & READ_ELEMENT_STATUS_ACCESS))
+                       printf("ch: warning: could not map element source "
+                              "address %ud to a valid element type\n",
+                              eaddr);
+       }
+
        if (ISSET(flags, READ_ELEMENT_STATUS_PVOLTAG))
                copy_voltag(&ces->ces_pvoltag, &desc->pvoltag);
        if (ISSET(flags, READ_ELEMENT_STATUS_AVOLTAG))
@@ -604,7 +646,7 @@ ch_usergetelemstatus(struct ch_softc *sc,
        desc = (caddr_t)(pg_hdr + 1);
        for (i = 0; i < avail; ++i) {
                struct changer_element_status *ces = &(user_data[i]);
-               copy_element_status(pg_hdr->flags,
+               copy_element_status(sc, pg_hdr->flags,
                    (struct read_element_status_descriptor *)desc, ces);
                desc += desclen;
        }
index 88afaa9..a6cb8b1 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: chio.h,v 1.7 2006/05/31 03:01:44 beck Exp $   */
+/*     $OpenBSD: chio.h,v 1.8 2021/08/31 05:29:55 robert Exp $ */
 /*     $NetBSD: chio.h,v 1.8 1996/04/03 00:25:21 thorpej Exp $ */
 
 /*
@@ -127,6 +127,11 @@ struct changer_voltag {
 struct changer_element_status {
        int                     ces_type;               /* element type */
        u_int8_t                ces_flags;              /* flags */
+       u_int16_t               ces_addr;               /* logical element address */
+       u_int8_t                ces_sensecode;          /* additional sense code for element */
+       u_int8_t                ces_sensequal;          /* additional sense code qualifier */
+       u_int8_t                ces_source_type;        /*  element type of source address */
+       u_int16_t               ces_source_addr;        /*  source address of medium */
        struct changer_voltag   ces_pvoltag;            /* primary voltag */
        struct changer_voltag   ces_avoltag;            /* alternate voltag */
 };