fdisk, gpt - Support trim on recent kernels
authorMatthew Dillon <dillon@apollo.backplane.com>
Wed, 1 Aug 2018 21:38:34 +0000 (14:38 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Wed, 1 Aug 2018 21:46:21 +0000 (14:46 -0700)
* Recent kernels removed the 'trim' sysctls.  Devices now allow trim by
  default.

* Fix the fdisk -E option to no longer try to use the sysctls.

* Add trim support to gpt init (-E).

* Fix swapon -e, change option to -E to match gpt and fdisk
  (-e still supported and does the same thing).

sbin/fdisk/fdisk.c
sbin/gpt/create.c
sbin/gpt/gpt.8
sbin/swapon/swapon.8
sbin/swapon/swapon.c
sys/bus/cam/scsi/scsi_da.c

index 056b5e0..57a52db 100644 (file)
@@ -778,12 +778,14 @@ erase_partition(int i)
        struct    dos_partition *partp;
        off_t ioarg[2];
 
-       char sysctl_name[64];
-       int trim_enabled = 0;
-       size_t olen = sizeof(trim_enabled);
        char *dev_name = strdup(disk);
 
        dev_name = strtok(dev_name + strlen("/dev/da"),"s");
+#if 0
+       int trim_enabled = 0;
+       char sysctl_name[64];
+       size_t olen = sizeof(trim_enabled);
+
        sprintf(sysctl_name, "kern.cam.da.%s.trim_enabled", dev_name);
        if (sysctlbyname(sysctl_name, &trim_enabled, &olen, NULL, 0) < 0) {
                printf("Device:%s does not support the TRIM command\n", disk);
@@ -794,6 +796,7 @@ erase_partition(int i)
                    "is not enabled\n",sysctl_name);
                usage();
        }
+#endif
        partp = ((struct dos_partition *) &mboot.parts) + i;
        printf("erase sectors:%u %u\n",
            partp->dp_start,
index f9fd586..ce58e68 100644 (file)
@@ -31,6 +31,9 @@
 
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/errno.h>
+#include <sys/param.h>
+#include <bus/cam/scsi/scsi_daio.h>
 
 #include <err.h>
 #include <stddef.h>
@@ -46,6 +49,8 @@
 static int force;
 static int primary_only;
 
+static void do_erase(int fd);
+
 static void
 usage_create(void)
 {
@@ -56,7 +61,7 @@ usage_create(void)
 static void
 usage_init(void)
 {
-       fprintf(stderr, "usage: %s -f [-B] device ...\n", getprogname());
+       fprintf(stderr, "usage: %s -f [-B] [-E] device ...\n", getprogname());
        fprintf(stderr, "\tnote: -f is mandatory for this command\n");
        exit(1);
 }
@@ -284,8 +289,9 @@ cmd_init(int argc, char *argv[])
 {
        int ch, fd;
        int with_boot = 0;
+       int with_trim = 0;
 
-       while ((ch = getopt(argc, argv, "fIB")) != -1) {
+       while ((ch = getopt(argc, argv, "fBEI")) != -1) {
                switch(ch) {
                case 'f':
                        force = 1;
@@ -297,6 +303,9 @@ cmd_init(int argc, char *argv[])
                        usage_init();
                        /* NOT REACHED */
                        break;
+               case 'E':
+                       with_trim = 1;
+                       break;
                case 'B':
                        with_boot = 1;
                        break;
@@ -322,11 +331,22 @@ cmd_init(int argc, char *argv[])
                 */
                fd = gpt_open(path);
                if (fd == -1) {
-                       warn("unable to open device '%s'", device_name);
+                       warn("unable to open device '%s'", path);
                        continue;
                }
+               if (with_trim) {
+                       do_erase(fd);
+                       gpt_close(fd);
+                       sleep(1);
+                       fd = gpt_open(path);
+                       if (fd == -1) {
+                               warn("unable to reopen device '%s'", path);
+                               continue;
+                       }
+               }
                do_destroy(fd);
                gpt_close(fd);
+               sleep(1);
 
                fd = gpt_open(path);
                if (fd == -1) {
@@ -336,6 +356,7 @@ cmd_init(int argc, char *argv[])
                create(fd);
                add_defaults(fd);
                gpt_close(fd);
+               sleep(1);
 
                /*
                 * Setup slices
@@ -353,10 +374,10 @@ cmd_init(int argc, char *argv[])
                /*
                 * Label slice1
                 */
-               sleep(1);
                dosys("disklabel -r -w %s %s auto",
                      (with_boot ? "-B" : ""),
                      slice1);
+               sleep(1);
 
                /*
                 * newfs_msdos slice0
@@ -393,3 +414,19 @@ cmd_init(int argc, char *argv[])
 
        return (0);
 }
+
+static void
+do_erase(int fd)
+{
+       off_t ioarg[2];
+
+       ioarg[0] = 0;
+       ioarg[1] = mediasz;
+
+       if (ioctl(fd, DAIOCTRIM, ioarg) < 0) {
+               printf("Trim error %s\n", strerror(errno));
+               printf("Continuing\n");
+       } else {
+               printf("Trim completed ok\n");
+       }
+}
index 6e691c4..3c94b31 100644 (file)
@@ -237,7 +237,7 @@ option instructs
 .Nm
 to destroy the table in a way that it can be recovered.
 .\" ==== init ====
-.It Nm Ic init Fl f Oo Fl B Oc Ar device ...
+.It Nm Ic init Fl f Oo Fl B Oc Oo Fl E Oc Ar device ...
 The
 .Ic init
 command allows the user to create a new GPT similar
@@ -257,6 +257,13 @@ If the
 option is specified, /boot/bootx64.efi will be copied into
 the msdos slice (s0), and the disklabel will be initialized
 with -B in addition to the normal -r -w.
+.Pp
+If the
+.Fl E
+option is specified, the drive is TRIMed prior to the installation
+of the new label, if supported.  The operation will continue if not
+supported.  Note that this will complete destroy the contents of the
+drive.
 .\" ==== label ====
 .It Xo
 .Nm
index a32cf64..87a8304 100644 (file)
@@ -35,7 +35,7 @@
 .Nm swapon , swapoff , swapctl
 .Nd "specify devices for paging and swapping"
 .Sh SYNOPSIS
-.Nm swapon Fl aceiq | Ar
+.Nm swapon Fl acEiq | Ar
 .Nm swapoff Fl aq | Ar
 .Nm swapctl
 .Op Fl AeghklmsU
@@ -90,7 +90,7 @@ If the
 option is used, the device will be encrypted with a random
 key.
 If the
-.Fl e
+.Fl E
 option is used, the device will be trimmed if
 it supports trim and the trim_enabled sysctl is on.
 The
@@ -183,7 +183,9 @@ Print a summary line for system swap.
 .If Fl c
 The swap is or should be crypted.
 .It Fl e
-Attempts to Trim the device if -[Aa] is used.
+.It Fl E
+Attempts to Trim the device if -[Aa] is used.  The lower-case version
+of this option is deprecated.
 .It Fl i
 Asks user confirmation when -a is used.
 .It Fl q
index 2f9e843..3c7fdd7 100644 (file)
@@ -77,7 +77,7 @@ main(int argc, char **argv)
        orig_prog = which_prog;
 
        sflag = lflag = hflag = doall = eflag = cflag = iflag = 0;
-       while ((ch = getopt(argc, argv, "AacdeghiklmqsU")) != -1) {
+       while ((ch = getopt(argc, argv, "acdeghiklmqsAEU")) != -1) {
                switch((char)ch) {
                case 'A':
                        if (which_prog == SWAPCTL) {
@@ -102,6 +102,7 @@ main(int argc, char **argv)
                case 'c':
                        cflag = 1;
                        break;
+               case 'E':
                case 'e':
                        eflag = 1;
                        break;
@@ -340,9 +341,8 @@ trim_volume(char * name)
        /*Trim the Device*/     
        ioarg[0] = pinfo.media_offset;
        ioarg[1] = pinfo.media_size;
-       printf("Trimming Device:%s, sectors (%llu -%llu)\n",name,
-            (unsigned long long)ioarg[0]/512,
-            (unsigned long long)ioarg[1]/512);
+       printf("Trimming Device:%s, start=%jd bytes=%jd)\n",
+            name, (intmax_t)ioarg[0], (intmax_t)ioarg[1]);
        if (ioctl(fd, DAIOCTRIM, ioarg) < 0) {
                printf("Device trim failed\n");
                usage ();
@@ -365,28 +365,7 @@ swap_on_off(char *name, int doingall, int trim, int ask)
 
        }
        if (which_prog == SWAPON && trim) {
-               char sysctl_name[64];
-               int trim_enabled = 0;
-               size_t olen = sizeof(trim_enabled);
-               char *dev_name = strdup(name);
-               dev_name = strtok(dev_name + strlen("/dev/da"),"s");
-               sprintf(sysctl_name, "kern.cam.da.%s.trim_enabled", dev_name);
-               if (sysctlbyname(sysctl_name, &trim_enabled, &olen, NULL, 0) < 0) {
-                       if (qflag == 0) {
-                               printf("TRIM not supported on %s, "
-                                      "ignoring\n",
-                                      name);
-                       }
-                       errno = 0;
-               } else if (!trim_enabled) {
-                       if (qflag == 0) {
-                               printf("TRIM not enabled on %s (%s), "
-                                      "ignoring\n",
-                                      name, sysctl_name);
-                       }
-               } else {
-                       trim_volume(name);
-               }
+               trim_volume(name);
        }
        if ((which_prog == SWAPOFF ? swapoff(name) : swapon(name)) == -1) {
                switch(errno) {
index c696530..e8d0d98 100644 (file)
@@ -1309,11 +1309,6 @@ dastart(struct cam_periph *periph, union ccb *start_ccb)
                                count = bp->b_bcount / softc->params.secsize;
                                lba = bio1->bio_offset/softc->params.secsize;
 
-                               kprintf("trim lba:%llu boff:%llu count:%d\n",
-                                   (unsigned long long) lba,
-                                   (unsigned long long) bio1->bio_offset,
-                                   count);
-
                                bioq_remove(&softc->bio_queue_trim, bio1);
                                while (count > 0) {
                                        int c = min(count, 0xffff);