Author: jimharris
Date: Wed Jun 26 23:00:42 2013
New Revision: 252266
URL: http://svnweb.freebsd.org/changeset/base/252266

Log:
  Break out code related to the identify command into a separate source file.
  
  Sponsored by: Intel
  MFC after:    3 days

Added:
  head/sbin/nvmecontrol/identify.c   (contents, props changed)
Modified:
  head/sbin/nvmecontrol/Makefile
  head/sbin/nvmecontrol/nvmecontrol.c
  head/sbin/nvmecontrol/nvmecontrol.h

Modified: head/sbin/nvmecontrol/Makefile
==============================================================================
--- head/sbin/nvmecontrol/Makefile      Wed Jun 26 22:58:59 2013        
(r252265)
+++ head/sbin/nvmecontrol/Makefile      Wed Jun 26 23:00:42 2013        
(r252266)
@@ -1,7 +1,7 @@
 # $FreeBSD$
 
 PROG=  nvmecontrol
-SRCS=  nvmecontrol.c devlist.c
+SRCS=  nvmecontrol.c devlist.c identify.c
 MAN=   nvmecontrol.8
 
 .include <bsd.prog.mk>

Added: head/sbin/nvmecontrol/identify.c
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sbin/nvmecontrol/identify.c    Wed Jun 26 23:00:42 2013        
(r252266)
@@ -0,0 +1,321 @@
+/*-
+ * Copyright (C) 2012-2013 Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#include "nvmecontrol.h"
+
+static void
+print_controller_hex(struct nvme_controller_data *cdata, uint32_t length)
+{
+       uint32_t        *p;
+       uint32_t        i, j;
+
+       p = (uint32_t *)cdata;
+       length /= sizeof(uint32_t);
+
+       for (i = 0; i < length; i+=8) {
+               printf("%03x: ", i*4);
+               for (j = 0; j < 8; j++)
+                       printf("%08x ", p[i+j]);
+               printf("\n");
+       }
+
+       printf("\n");
+}
+
+static void
+print_controller(struct nvme_controller_data *cdata)
+{
+       printf("Controller Capabilities/Features\n");
+       printf("================================\n");
+       printf("Vendor ID:                  %04x\n", cdata->vid);
+       printf("Subsystem Vendor ID:        %04x\n", cdata->ssvid);
+       printf("Serial Number:              %s\n", cdata->sn);
+       printf("Model Number:               %s\n", cdata->mn);
+       printf("Firmware Version:           %s\n", cdata->fr);
+       printf("Recommended Arb Burst:      %d\n", cdata->rab);
+       printf("IEEE OUI Identifier:        %02x %02x %02x\n",
+               cdata->ieee[0], cdata->ieee[1], cdata->ieee[2]);
+       printf("Multi-Interface Cap:        %02x\n", cdata->mic);
+       /* TODO: Use CAP.MPSMIN to determine true memory page size. */
+       printf("Max Data Transfer Size:     ");
+       if (cdata->mdts == 0)
+               printf("Unlimited\n");
+       else
+               printf("%d\n", PAGE_SIZE * (1 << cdata->mdts));
+       printf("\n");
+
+       printf("Admin Command Set Attributes\n");
+       printf("============================\n");
+       printf("Security Send/Receive:       %s\n",
+               cdata->oacs.security ? "Supported" : "Not Supported");
+       printf("Format NVM:                  %s\n",
+               cdata->oacs.format ? "Supported" : "Not Supported");
+       printf("Firmware Activate/Download:  %s\n",
+               cdata->oacs.firmware ? "Supported" : "Not Supported");
+       printf("Abort Command Limit:         %d\n", cdata->acl+1);
+       printf("Async Event Request Limit:   %d\n", cdata->aerl+1);
+       printf("Number of Firmware Slots:    ");
+       if (cdata->oacs.firmware != 0)
+               printf("%d\n", cdata->frmw.num_slots);
+       else
+               printf("N/A\n");
+       printf("Firmware Slot 1 Read-Only:   ");
+       if (cdata->oacs.firmware != 0)
+               printf("%s\n", cdata->frmw.slot1_ro ? "Yes" : "No");
+       else
+               printf("N/A\n");
+       printf("Per-Namespace SMART Log:     %s\n",
+               cdata->lpa.ns_smart ? "Yes" : "No");
+       printf("Error Log Page Entries:      %d\n", cdata->elpe+1);
+       printf("Number of Power States:      %d\n", cdata->npss+1);
+       printf("\n");
+
+       printf("NVM Command Set Attributes\n");
+       printf("==========================\n");
+       printf("Submission Queue Entry Size\n");
+       printf("  Max:                       %d\n", 1 << cdata->sqes.max);
+       printf("  Min:                       %d\n", 1 << cdata->sqes.min);
+       printf("Completion Queue Entry Size\n");
+       printf("  Max:                       %d\n", 1 << cdata->cqes.max);
+       printf("  Min:                       %d\n", 1 << cdata->cqes.min);
+       printf("Number of Namespaces:        %d\n", cdata->nn);
+       printf("Compare Command:             %s\n",
+               cdata->oncs.compare ? "Supported" : "Not Supported");
+       printf("Write Uncorrectable Command: %s\n",
+               cdata->oncs.write_unc ? "Supported" : "Not Supported");
+       printf("Dataset Management Command:  %s\n",
+               cdata->oncs.dsm ? "Supported" : "Not Supported");
+       printf("Volatile Write Cache:        %s\n",
+               cdata->vwc.present ? "Present" : "Not Present");
+}
+
+static void
+print_namespace_hex(struct nvme_namespace_data *nsdata, uint32_t length)
+{
+       uint32_t        *p;
+       uint32_t        i, j;
+
+       p = (uint32_t *)nsdata;
+       length /= sizeof(uint32_t);
+
+       for (i = 0; i < length; i+=8) {
+               printf("%03x: ", i*4);
+               for (j = 0; j < 8; j++)
+                       printf("%08x ", p[i+j]);
+               printf("\n");
+       }
+
+       printf("\n");
+}
+
+static void
+print_namespace(struct nvme_namespace_data *nsdata)
+{
+       uint32_t        i;
+
+       printf("Size (in LBAs):              %lld (%lldM)\n",
+               (long long)nsdata->nsze,
+               (long long)nsdata->nsze / 1024 / 1024);
+       printf("Capacity (in LBAs):          %lld (%lldM)\n",
+               (long long)nsdata->ncap,
+               (long long)nsdata->ncap / 1024 / 1024);
+       printf("Utilization (in LBAs):       %lld (%lldM)\n",
+               (long long)nsdata->nuse,
+               (long long)nsdata->nuse / 1024 / 1024);
+       printf("Thin Provisioning:           %s\n",
+               nsdata->nsfeat.thin_prov ? "Supported" : "Not Supported");
+       printf("Number of LBA Formats:       %d\n", nsdata->nlbaf+1);
+       printf("Current LBA Format:          LBA Format #%d\n",
+               nsdata->flbas.format);
+       for (i = 0; i <= nsdata->nlbaf; i++) {
+               printf("LBA Format #%d:\n", i);
+               printf("  LBA Data Size:             %d\n",
+                       1 << nsdata->lbaf[i].lbads);
+       }
+}
+
+static void
+identify_usage(void)
+{
+       fprintf(stderr, "usage:\n");
+       fprintf(stderr, IDENTIFY_USAGE);
+       exit(EX_USAGE);
+}
+
+static void
+identify_ctrlr(int argc, char *argv[])
+{
+       struct nvme_controller_data     cdata;
+       int                             ch, fd, hexflag = 0, hexlength;
+       int                             verboseflag = 0;
+
+       while ((ch = getopt(argc, argv, "vx")) != -1) {
+               switch ((char)ch) {
+               case 'v':
+                       verboseflag = 1;
+                       break;
+               case 'x':
+                       hexflag = 1;
+                       break;
+               default:
+                       identify_usage();
+               }
+       }
+
+       open_dev(argv[optind], &fd, 1, 1);
+       read_controller_data(fd, &cdata);
+       close(fd);
+
+       if (hexflag == 1) {
+               if (verboseflag == 1)
+                       hexlength = sizeof(struct nvme_controller_data);
+               else
+                       hexlength = offsetof(struct nvme_controller_data,
+                           reserved5);
+               print_controller_hex(&cdata, hexlength);
+               exit(EX_OK);
+       }
+
+       if (verboseflag == 1) {
+               printf("-v not currently supported without -x.\n");
+               identify_usage();
+       }
+
+       print_controller(&cdata);
+       exit(EX_OK);
+}
+
+static void
+identify_ns(int argc, char *argv[])
+{
+       struct nvme_namespace_data      nsdata;
+       char                            path[64];
+       char                            *nsloc;
+       int                             ch, fd, hexflag = 0, hexlength, nsid;
+       int                             verboseflag = 0;
+
+       while ((ch = getopt(argc, argv, "vx")) != -1) {
+               switch ((char)ch) {
+               case 'v':
+                       verboseflag = 1;
+                       break;
+               case 'x':
+                       hexflag = 1;
+                       break;
+               default:
+                       identify_usage();
+               }
+       }
+
+       /*
+        * Check if the specified device node exists before continuing.
+        *  This is a cleaner check for cases where the correct controller
+        *  is specified, but an invalid namespace on that controller.
+        */
+       open_dev(argv[optind], &fd, 1, 1);
+       close(fd);
+
+       /*
+        * Pull the namespace id from the string. +2 skips past the "ns" part
+        *  of the string.  Don't search past 10 characters into the string,
+        *  otherwise we know it is malformed.
+        */
+       nsloc = strnstr(argv[optind], "ns", 10);
+       if (nsloc != NULL)
+               nsid = strtol(nsloc + 2, NULL, 10);
+       if (nsloc == NULL || (nsid == 0 && errno != 0)) {
+               printf("Invalid namespace ID %s.\n", argv[optind]);
+               exit(EX_IOERR);
+       }
+
+       /*
+        * We send IDENTIFY commands to the controller, not the namespace,
+        *  since it is an admin cmd.  So the path should only include the
+        *  nvmeX part of the nvmeXnsY string.
+        */
+       snprintf(path, nsloc - argv[optind] + 1, "%s", argv[optind]);
+       open_dev(path, &fd, 1, 1);
+       read_namespace_data(fd, nsid, &nsdata);
+       close(fd);
+
+       if (hexflag == 1) {
+               if (verboseflag == 1)
+                       hexlength = sizeof(struct nvme_namespace_data);
+               else
+                       hexlength = offsetof(struct nvme_namespace_data,
+                           reserved6);
+               print_namespace_hex(&nsdata, hexlength);
+               exit(EX_OK);
+       }
+
+       if (verboseflag == 1) {
+               printf("-v not currently supported without -x.\n");
+               identify_usage();
+       }
+
+       print_namespace(&nsdata);
+       exit(EX_OK);
+}
+
+void
+identify(int argc, char *argv[])
+{
+       char    *target;
+
+       if (argc < 2)
+               identify_usage();
+
+       while (getopt(argc, argv, "vx") != -1) ;
+
+       target = argv[optind];
+
+       optreset = 1;
+       optind = 1;
+
+       /*
+        * If device node contains "ns", we consider it a namespace,
+        *  otherwise, consider it a controller.
+        */
+       if (strstr(target, "ns") == NULL)
+               identify_ctrlr(argc, argv);
+       else
+               identify_ns(argc, argv);
+}

Modified: head/sbin/nvmecontrol/nvmecontrol.c
==============================================================================
--- head/sbin/nvmecontrol/nvmecontrol.c Wed Jun 26 22:58:59 2013        
(r252265)
+++ head/sbin/nvmecontrol/nvmecontrol.c Wed Jun 26 23:00:42 2013        
(r252266)
@@ -57,137 +57,6 @@ usage(void)
        exit(EX_USAGE);
 }
 
-static void
-print_controller_hex(struct nvme_controller_data *cdata, uint32_t length)
-{
-       uint32_t        *p;
-       uint32_t        i, j;
-
-       p = (uint32_t *)cdata;
-       length /= sizeof(uint32_t);
-
-       for (i = 0; i < length; i+=8) {
-               printf("%03x: ", i*4);
-               for (j = 0; j < 8; j++)
-                       printf("%08x ", p[i+j]);
-               printf("\n");
-       }
-
-       printf("\n");
-}
-
-static void
-print_controller(struct nvme_controller_data *cdata)
-{
-       printf("Controller Capabilities/Features\n");
-       printf("================================\n");
-       printf("Vendor ID:                  %04x\n", cdata->vid);
-       printf("Subsystem Vendor ID:        %04x\n", cdata->ssvid);
-       printf("Serial Number:              %s\n", cdata->sn);
-       printf("Model Number:               %s\n", cdata->mn);
-       printf("Firmware Version:           %s\n", cdata->fr);
-       printf("Recommended Arb Burst:      %d\n", cdata->rab);
-       printf("IEEE OUI Identifier:        %02x %02x %02x\n",
-               cdata->ieee[0], cdata->ieee[1], cdata->ieee[2]);
-       printf("Multi-Interface Cap:        %02x\n", cdata->mic);
-       /* TODO: Use CAP.MPSMIN to determine true memory page size. */
-       printf("Max Data Transfer Size:     ");
-       if (cdata->mdts == 0)
-               printf("Unlimited\n");
-       else
-               printf("%d\n", PAGE_SIZE * (1 << cdata->mdts));
-       printf("\n");
-
-       printf("Admin Command Set Attributes\n");
-       printf("============================\n");
-       printf("Security Send/Receive:       %s\n",
-               cdata->oacs.security ? "Supported" : "Not Supported");
-       printf("Format NVM:                  %s\n",
-               cdata->oacs.format ? "Supported" : "Not Supported");
-       printf("Firmware Activate/Download:  %s\n",
-               cdata->oacs.firmware ? "Supported" : "Not Supported");
-       printf("Abort Command Limit:         %d\n", cdata->acl+1);
-       printf("Async Event Request Limit:   %d\n", cdata->aerl+1);
-       printf("Number of Firmware Slots:    ");
-       if (cdata->oacs.firmware != 0)
-               printf("%d\n", cdata->frmw.num_slots);
-       else
-               printf("N/A\n");
-       printf("Firmware Slot 1 Read-Only:   ");
-       if (cdata->oacs.firmware != 0)
-               printf("%s\n", cdata->frmw.slot1_ro ? "Yes" : "No");
-       else
-               printf("N/A\n");
-       printf("Per-Namespace SMART Log:     %s\n",
-               cdata->lpa.ns_smart ? "Yes" : "No");
-       printf("Error Log Page Entries:      %d\n", cdata->elpe+1);
-       printf("Number of Power States:      %d\n", cdata->npss+1);
-       printf("\n");
-
-       printf("NVM Command Set Attributes\n");
-       printf("==========================\n");
-       printf("Submission Queue Entry Size\n");
-       printf("  Max:                       %d\n", 1 << cdata->sqes.max);
-       printf("  Min:                       %d\n", 1 << cdata->sqes.min);
-       printf("Completion Queue Entry Size\n");
-       printf("  Max:                       %d\n", 1 << cdata->cqes.max);
-       printf("  Min:                       %d\n", 1 << cdata->cqes.min);
-       printf("Number of Namespaces:        %d\n", cdata->nn);
-       printf("Compare Command:             %s\n",
-               cdata->oncs.compare ? "Supported" : "Not Supported");
-       printf("Write Uncorrectable Command: %s\n",
-               cdata->oncs.write_unc ? "Supported" : "Not Supported");
-       printf("Dataset Management Command:  %s\n",
-               cdata->oncs.dsm ? "Supported" : "Not Supported");
-       printf("Volatile Write Cache:        %s\n",
-               cdata->vwc.present ? "Present" : "Not Present");
-}
-
-static void
-print_namespace_hex(struct nvme_namespace_data *nsdata, uint32_t length)
-{
-       uint32_t        *p;
-       uint32_t        i, j;
-
-       p = (uint32_t *)nsdata;
-       length /= sizeof(uint32_t);
-
-       for (i = 0; i < length; i+=8) {
-               printf("%03x: ", i*4);
-               for (j = 0; j < 8; j++)
-                       printf("%08x ", p[i+j]);
-               printf("\n");
-       }
-
-       printf("\n");
-}
-
-static void
-print_namespace(struct nvme_namespace_data *nsdata)
-{
-       uint32_t        i;
-
-       printf("Size (in LBAs):              %lld (%lldM)\n",
-               (long long)nsdata->nsze,
-               (long long)nsdata->nsze / 1024 / 1024);
-       printf("Capacity (in LBAs):          %lld (%lldM)\n",
-               (long long)nsdata->ncap,
-               (long long)nsdata->ncap / 1024 / 1024);
-       printf("Utilization (in LBAs):       %lld (%lldM)\n",
-               (long long)nsdata->nuse,
-               (long long)nsdata->nuse / 1024 / 1024);
-       printf("Thin Provisioning:           %s\n",
-               nsdata->nsfeat.thin_prov ? "Supported" : "Not Supported");
-       printf("Number of LBA Formats:       %d\n", nsdata->nlbaf+1);
-       printf("Current LBA Format:          LBA Format #%d\n",
-               nsdata->flbas.format);
-       for (i = 0; i <= nsdata->nlbaf; i++) {
-               printf("LBA Format #%d:\n", i);
-               printf("  LBA Data Size:             %d\n",
-                       1 << nsdata->lbaf[i].lbads);
-       }
-}
-
 void
 read_controller_data(int fd, struct nvme_controller_data *cdata)
 {
@@ -267,154 +136,6 @@ open_dev(const char *str, int *fd, int s
 }
 
 static void
-identify_usage(void)
-{
-       fprintf(stderr, "usage:\n");
-       fprintf(stderr, IDENTIFY_USAGE);
-       exit(EX_USAGE);
-}
-
-static void
-identify_ctrlr(int argc, char *argv[])
-{
-       struct nvme_controller_data     cdata;
-       int                             ch, fd, hexflag = 0, hexlength;
-       int                             verboseflag = 0;
-
-       while ((ch = getopt(argc, argv, "vx")) != -1) {
-               switch ((char)ch) {
-               case 'v':
-                       verboseflag = 1;
-                       break;
-               case 'x':
-                       hexflag = 1;
-                       break;
-               default:
-                       identify_usage();
-               }
-       }
-
-       open_dev(argv[optind], &fd, 1, 1);
-       read_controller_data(fd, &cdata);
-       close(fd);
-
-       if (hexflag == 1) {
-               if (verboseflag == 1)
-                       hexlength = sizeof(struct nvme_controller_data);
-               else
-                       hexlength = offsetof(struct nvme_controller_data,
-                           reserved5);
-               print_controller_hex(&cdata, hexlength);
-               exit(EX_OK);
-       }
-
-       if (verboseflag == 1) {
-               printf("-v not currently supported without -x.\n");
-               identify_usage();
-       }
-
-       print_controller(&cdata);
-       exit(EX_OK);
-}
-
-static void
-identify_ns(int argc, char *argv[])
-{
-       struct nvme_namespace_data      nsdata;
-       char                            path[64];
-       char                            *nsloc;
-       int                             ch, fd, hexflag = 0, hexlength, nsid;
-       int                             verboseflag = 0;
-
-       while ((ch = getopt(argc, argv, "vx")) != -1) {
-               switch ((char)ch) {
-               case 'v':
-                       verboseflag = 1;
-                       break;
-               case 'x':
-                       hexflag = 1;
-                       break;
-               default:
-                       identify_usage();
-               }
-       }
-
-       /*
-        * Check if the specified device node exists before continuing.
-        *  This is a cleaner check for cases where the correct controller
-        *  is specified, but an invalid namespace on that controller.
-        */
-       open_dev(argv[optind], &fd, 1, 1);
-       close(fd);
-
-       /*
-        * Pull the namespace id from the string. +2 skips past the "ns" part
-        *  of the string.  Don't search past 10 characters into the string,
-        *  otherwise we know it is malformed.
-        */
-       nsloc = strnstr(argv[optind], "ns", 10);
-       if (nsloc != NULL)
-               nsid = strtol(nsloc + 2, NULL, 10);
-       if (nsloc == NULL || (nsid == 0 && errno != 0)) {
-               printf("Invalid namespace ID %s.\n", argv[optind]);
-               exit(EX_IOERR);
-       }
-
-       /*
-        * We send IDENTIFY commands to the controller, not the namespace,
-        *  since it is an admin cmd.  So the path should only include the
-        *  nvmeX part of the nvmeXnsY string.
-        */
-       snprintf(path, nsloc - argv[optind] + 1, "%s", argv[optind]);
-       open_dev(path, &fd, 1, 1);
-       read_namespace_data(fd, nsid, &nsdata);
-       close(fd);
-
-       if (hexflag == 1) {
-               if (verboseflag == 1)
-                       hexlength = sizeof(struct nvme_namespace_data);
-               else
-                       hexlength = offsetof(struct nvme_namespace_data,
-                           reserved6);
-               print_namespace_hex(&nsdata, hexlength);
-               exit(EX_OK);
-       }
-
-       if (verboseflag == 1) {
-               printf("-v not currently supported without -x.\n");
-               identify_usage();
-       }
-
-       print_namespace(&nsdata);
-       exit(EX_OK);
-}
-
-static void
-identify(int argc, char *argv[])
-{
-       char    *target;
-
-       if (argc < 2)
-               identify_usage();
-
-       while (getopt(argc, argv, "vx") != -1) ;
-
-       target = argv[optind];
-
-       optreset = 1;
-       optind = 1;
-
-       /*
-        * If device node contains "ns", we consider it a namespace,
-        *  otherwise, consider it a controller.
-        */
-       if (strstr(target, "ns") == NULL)
-               identify_ctrlr(argc, argv);
-       else
-               identify_ns(argc, argv);
-}
-
-static void
 print_perftest(struct nvme_io_test *io_test, bool perthread)
 {
        uint32_t i, io_completed = 0, iops, mbps;

Modified: head/sbin/nvmecontrol/nvmecontrol.h
==============================================================================
--- head/sbin/nvmecontrol/nvmecontrol.h Wed Jun 26 22:58:59 2013        
(r252265)
+++ head/sbin/nvmecontrol/nvmecontrol.h Wed Jun 26 23:00:42 2013        
(r252266)
@@ -51,6 +51,7 @@ void read_controller_data(int fd, struct
 void read_namespace_data(int fd, int nsid, struct nvme_namespace_data *nsdata);
 
 void devlist(int argc, char *argv[]);
+void identify(int argc, char *argv[]);
 
 #endif
 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to