Module Name:    src
Committed By:   mrg
Date:           Mon Feb  7 09:33:26 UTC 2022

Added Files:
        src/sbin/blkdiscard: Makefile blkdiscard.8 blkdiscard.c

Log Message:
convert my fdiscard-stuff.c into blkdiscard.c and give it a UI
that matches the linux-util version.

comes in two forms:  blkdiscard equivalent, and the (almost)
original interface i used (the "-s" option is conflicting and
i've switched to only the not yet implemented secure erase
option.)  the only real difference is that "fdiscard" mode
requires the -R flag to do something, vs blkdiscard needs the
-n flag to not do anything.

not yet hooked into the build or sets.  would like more testing
on it to be performed before doing that (but soon.)


To generate a diff of this commit:
cvs rdiff -u -r0 -r1.1 src/sbin/blkdiscard/Makefile \
    src/sbin/blkdiscard/blkdiscard.8 src/sbin/blkdiscard/blkdiscard.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Added files:

Index: src/sbin/blkdiscard/Makefile
diff -u /dev/null src/sbin/blkdiscard/Makefile:1.1
--- /dev/null	Mon Feb  7 09:33:26 2022
+++ src/sbin/blkdiscard/Makefile	Mon Feb  7 09:33:26 2022
@@ -0,0 +1,9 @@
+#	$NetBSD: Makefile,v 1.1 2022/02/07 09:33:26 mrg Exp $
+
+PROG=	blkdiscard
+MAN=	blkdiscard.8
+
+LINKS=	${BINDIR}/blkdiscard ${BINDIR}/fdiscard
+MLINKS=	blkdiscard.8 fdiscard.8
+
+.include <bsd.prog.mk>
Index: src/sbin/blkdiscard/blkdiscard.8
diff -u /dev/null src/sbin/blkdiscard/blkdiscard.8:1.1
--- /dev/null	Mon Feb  7 09:33:26 2022
+++ src/sbin/blkdiscard/blkdiscard.8	Mon Feb  7 09:33:26 2022
@@ -0,0 +1,163 @@
+.\"	$NetBSD: blkdiscard.8,v 1.1 2022/02/07 09:33:26 mrg Exp $
+.\"
+.\" Copyright (c) 2022 Matthew R. Green
+.\" 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 ``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 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.
+.\"
+.Dd February 6, 2022
+.Dt BLKDISCARD 8
+.Os
+.Sh NAME
+.Nm blkdiscard
+.Nd tool to discard portions of a device or file
+.Sh SYNOPSIS
+.Nm
+.Op Fl h
+.Op Fl l Ar length
+.Op Fl p Ar chunksize
+.Op Fl n
+.Op Fl o Ar firstbyte
+.Op Fl R
+.Op Fl s
+.Op Fl V
+.Op Fl v
+.Op Fl z
+.Ar file
+.Nm fdiscard
+.Op Fl f Ar firstbyte
+.Op Fl h
+.Op Fl l Ar length
+.Op Fl m Ar chunksize
+.Op Fl n
+.Op Fl R
+.Op Fl s
+.Op Fl V
+.Op Fl v
+.Op Fl z
+.Ar file
+.Sh DESCRIPTION
+The
+.Nm
+program can be used to discard portions of storage, and works on either
+device files directly or upon files inside of a mounted file-system.
+It provides access to the
+.Xr fdiscard 2
+system call, and relies upon the
+backing device to have support in both the
+.Nm
+driver and in the hardware itself.
+.Pp
+The
+.Nm fdiscard
+interface defaults to the
+.Dq no-run
+mode and requires the
+.Fl R
+option to perform any actions.
+.Pp
+.Sh OPTIONS
+Available options:
+.Bl -tag -width chunksize123
+.It Fl f Ar firstbyte
+Set the first byte to be discarded.
+The default is 0.
+.It Fl h
+Display built-in help.
+.It Fl l Ar length
+Limit the length to be discarded.
+The default is the full device or file size, or the rest of the device
+or file when the start offset has been set.
+.It Fl m Ar chunksize
+Set the per-operation chunksize.
+The default is 32 MiB.
+.It Fl n
+Set the
+.Dq no-run
+option, and do not actually call
+.Xr fdiscard 2 ,
+secure erase, or write zeroes to the file.
+.It Fl o Ar firstbyte
+This flag is an alias for the
+.Fl f
+flag.
+.It Fl p Ar chunksize
+This flag is an alias for the
+.Fl m
+flag.
+.It Fl R
+Turn off the
+.Dq no-run mode.
+.It Fl s
+Use secure erase operation.
+This requires specific hardware support and is not currently supported.
+.It Fl V
+Display the program version and exit.
+.It Fl v
+Set the verbose flag.
+.It Fl z
+Write zeroes instead of calling
+.Xr fdiscard 2 .
+.Sh EXAMPLES
+To have a dry-run cleaning of any particular file or device:
+.Bd -literal -offset indent
+# blkdiscard -n -v filename
+# blkdiscard -n -v /dev/rwd0b
+.Ed
+.Pp
+To discard all the blocks on a swap device:
+.Bd -literal -offset indent
+# blkdiscard -v /dev/rwd0b
+.Ed
+.Pp
+To discard all but the first 256MiB of a device, using 128MiB increments:
+.Bd -literal -offset indent
+# blkdiscard -v -f 256m -m 128m /dev/rwd0c
+.Ed
+.Pp
+To zero out the contents of a file or device:
+.Bd -literal -offset indent
+# blkdiscard -v -z filename
+# blkdiscard -v -z /dev/device
+.Ed
+.Sh SEE ALSO
+.Xr fdiscard 2
+.Sh HISTORY
+The
+.Nm
+command first appeared linux-util.
+This implementation was originally called fdiscard-stuff and has been
+converted to be
+.Lx
+.Xr blkdiscard 8
+compatible and appeared in
+.Nx 10.0 .
+.Sh AUTHORS
+The
+.Nm
+command was written by
+.An Matthew R. Green
+.Aq m...@eterna.com.au .
+.Sh BUGS
+The secure erase funtionality of the
+.Fl s
+option is not yet implemented.
Index: src/sbin/blkdiscard/blkdiscard.c
diff -u /dev/null src/sbin/blkdiscard/blkdiscard.c:1.1
--- /dev/null	Mon Feb  7 09:33:26 2022
+++ src/sbin/blkdiscard/blkdiscard.c	Mon Feb  7 09:33:26 2022
@@ -0,0 +1,264 @@
+/*	$NetBSD: blkdiscard.c,v 1.1 2022/02/07 09:33:26 mrg Exp $	*/
+
+/*
+ * Copyright (c) 2019, 2020, 2022 Matthew R. Green
+ * 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.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+ */
+
+/* from: $eterna: fdiscard-stuff.c,v 1.3 2020/12/25 23:40:19 mrg Exp $	*/
+
+/* fdiscard(2) front-end -- TRIM support. */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/disk.h>
+#include <sys/disklabel.h>
+#include <sys/ioctl.h>
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <err.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+
+static bool secure = false;
+static bool zeroout = false;
+static char *zeros = NULL;
+
+#define FDISCARD_VERSION	20220206u
+
+static void __dead
+usage(const char* msg)
+{
+	FILE *out = stdout;
+	int rv = 0;
+
+	if (msg) {
+		out = stderr;
+		rv = 1;
+		fprintf(out, "%s", msg);
+	}
+	fprintf(out, "Usage: blkdiscard [-hnRsVvz] [-l length] "
+		     "[-m chunk_bytes]\n"
+		     "                  [-o first_byte] <file>\n");
+	exit(rv);
+}
+
+static void __dead
+version(void)
+{
+
+	printf("NetBSD blkdiscard %u\n", FDISCARD_VERSION);
+	exit(0);
+}
+
+static void
+write_one(int fd, off_t discard_size, off_t first_byte)
+{
+
+	if (secure)
+		/* not yet */;
+	else if (zeroout) {
+		if (pwrite(fd, zeros, discard_size, first_byte) != discard_size)
+			err(1, "pwrite");
+	} else if (fdiscard(fd, first_byte, discard_size) != 0)
+		err(1, "fdiscard");
+}
+
+int
+main(int argc, char *argv[])
+{
+	off_t first_byte = 0, end_offset = 0;
+	/* doing a terabyte at a time leads to ATA timeout issues */
+	off_t max_per_call = 32 * 1024 * 1024;
+	off_t discard_size;
+	off_t size = 0;
+	off_t length = 0;
+	int64_t val;
+	int i;
+	bool verbose = false;
+
+	/* Default /sbin/blkdiscard to be "run" */
+	bool norun = strcmp(getprogname(), "blkdiscard") != 0;
+
+	while ((i = getopt(argc, argv, "f:hl:m:no:p:RsvVz")) != -1) {
+		switch (i) {
+		case 'l':
+			if (dehumanize_number(optarg, &val) == -1 || val < 0)
+				usage("bad -s\n");
+			length = val;
+			break;
+		case 'm':
+		case 'p':
+			if (dehumanize_number(optarg, &val) == -1 || val < 0)
+				usage("bad -m\n");
+			max_per_call = val;
+			break;
+		case 'f':
+		case 'o':
+			if (dehumanize_number(optarg, &val) == -1 || val < 0)
+				usage("bad -f\n");
+			first_byte = val;
+			break;
+		case 'n':
+			norun = true;
+			break;
+		case 'R':
+			norun = false;
+			break;
+		case 's':
+			secure = true;
+			break;
+		case 'V':
+			version();
+		case 'v':
+			verbose = true;
+			break;
+		case 'z':
+			zeroout = true;
+			break;
+		case 'h':
+			usage(NULL);
+		default:
+			usage("bad options\n");
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	if (secure)
+		usage("blkdiscard: secure erase not yet implemnted\n");
+	if (zeroout) {
+		zeros = calloc(1, max_per_call);
+		if (!zeros)
+			errx(1, "Unable to allocate %lld bytes for zeros",
+			    (long long)max_per_call);
+	}
+	
+	if (length)
+		end_offset = first_byte + length;
+
+	if (argc != 1)
+		usage("not one arg left\n");
+
+	char *name = argv[0];
+	int fd = open(name, O_RDWR);
+	if (fd < 0)
+		err(1, "open on %s", name);
+
+	if (size == 0) {
+		struct dkwedge_info dkw;
+		if (ioctl(fd, DIOCGWEDGEINFO, &dkw) == 0) {
+			size = dkw.dkw_size * DEV_BSIZE;
+			if (verbose)
+				printf("%s: wedge size is %lld\n", name,
+				    (long long)size);
+		}
+	}
+
+	if (size == 0) {
+		struct disklabel dl;
+		if (ioctl(fd, DIOCGDINFO, &dl) != -1) {
+			char partchar = name[strlen(name)-1];
+			assert(partchar >= 'a' && partchar <= 'p');
+			int part = partchar - 'a';
+
+			size = (uint64_t)dl.d_partitions[part].p_size *
+			    dl.d_secsize;
+			if (verbose)
+				printf("%s: disklabel size is %lld\n", name,
+				    (long long)size);
+		}
+	}
+
+	if (size == 0) {
+		struct stat sb;
+		if (fstat(fd, &sb) != -1) {
+			size = sb.st_size;
+			if (verbose)
+				printf("%s: stat size is %lld\n", name,
+				    (long long)size);
+		}
+	}
+
+	if (size == 0) {
+		fprintf(stderr, "unable to determine size.\n");
+		exit(1);
+	}
+
+	size -= first_byte;
+
+	if (end_offset) {
+		if (end_offset > size) {
+			fprintf(stderr, "end_offset %lld > size %lld\n",
+			    (long long)end_offset, (long long)size);
+			usage("");
+		}
+		size = end_offset;
+	}
+
+	if (verbose)
+		printf("%sgoing to %s on %s from byte %lld for "
+		       "%lld bytes, %lld at a time\n",
+		       norun ? "not " : "",
+		       secure ? "secure erase" :
+		       zeroout ? "zero out" : "fdiscard(2)",
+		       name, (long long)first_byte, (long long)size,
+		       (long long)max_per_call);
+
+	int loop = 0;
+	while (size > 0) {
+		if (size > max_per_call)
+			discard_size = max_per_call;
+		else
+			discard_size = size;
+
+		if (!norun)
+			write_one(fd, discard_size, first_byte);
+
+		first_byte += discard_size;
+		size -= discard_size;
+		if (verbose) {
+			printf(".");
+			fflush(stdout);
+			if (loop++ > 100) {
+				loop = 0;
+				printf("\n");
+			}
+		}
+	}
+	if (loop != 0)
+		printf("\n");
+
+	if (close(fd) != 0)
+		warnx("close failed: %s", strerror(errno));
+
+	return 0;
+}

Reply via email to