git: 3703c1888334 - main - md: Add MD_MUSTDEALLOC support

Ka Ho Ng khng at FreeBSD.org
Sat Sep 11 12:05:08 UTC 2021


The branch main has been updated by khng:

URL: https://cgit.FreeBSD.org/src/commit/?id=3703c18883341f3ff09c42d7f3b36ab80e4a071b

commit 3703c18883341f3ff09c42d7f3b36ab80e4a071b
Author:     Ka Ho Ng <khng at FreeBSD.org>
AuthorDate: 2021-09-11 12:03:38 +0000
Commit:     Ka Ho Ng <khng at FreeBSD.org>
CommitDate: 2021-09-11 12:04:52 +0000

    md: Add MD_MUSTDEALLOC support
    
    This adds an option to detect if hole-punching is implemented by the
    underlying file system.  If this flag is set, and if the underlying file
    system does not support hole-punching, md(4) fails BIO_DELETE requests
    with EOPNOTSUPP.
    
    Sponsored by:   The FreeBSD Foundation
    Reviewed by:    markj
    Differential Revision:  https://reviews.freebsd.org/D31883
---
 sbin/mdconfig/mdconfig.8 | 35 +++++++++++++++++++++++++++++++++--
 sbin/mdconfig/mdconfig.c |  7 ++++++-
 sys/dev/md/md.c          | 18 ++++++++++++++++--
 sys/sys/mdioctl.h        |  1 +
 4 files changed, 56 insertions(+), 5 deletions(-)

diff --git a/sbin/mdconfig/mdconfig.8 b/sbin/mdconfig/mdconfig.8
index 6d9da8159723..775823fd0bc7 100644
--- a/sbin/mdconfig/mdconfig.8
+++ b/sbin/mdconfig/mdconfig.8
@@ -37,7 +37,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd November 6, 2020
+.Dd August 27, 2021
 .Dt MDCONFIG 8
 .Os
 .Sh NAME
@@ -246,6 +246,34 @@ This can be used with the
 flag to forcibly destroy an
 .Xr md 4
 disk that is still in use.
+.It Oo Cm no Oc Ns Cm mustdealloc
+For
+.Cm vnode
+backed devices: detect whether hole-punching is supported by the underlying file
+system.
+If the file system supports hole-punching, then to handle a
+.Dv BIO_DELETE
+request, some or all of the request's operation range may be turned into a hole
+in the file used for backing store.
+Any parts which are not turned into holes are zero-filled in
+the file.
+If the file system does not support
+hole-punching,
+.Dv BIO_DELETE
+requests to the device are not handled and will fail with
+.Er EOPNOTSUPP .
+.Pp
+When
+.Cm mustdealloc
+is not specified or
+.Oo Cm no Oc Ns Cm mustdealloc
+is specified, for a
+.Dv BIO_DELETE
+request, if the file system supports hole-punching, some or all of the request's
+operation range may be turned into a hole in the file used for backing store.
+Any parts which are not turned into holes are zero-filled in the file.
+If the file system of the vnode type memory disk does not support hole-punching,
+the request's operation range is zero-filled in the file.
 .It Oo Cm no Oc Ns Cm readonly
 Enable/disable readonly mode.
 .It Oo Cm no Oc Ns Cm verify
@@ -339,12 +367,15 @@ gnop create -o 512K md1
 mount /dev/md1.nop /mnt
 .Ed
 .Sh SEE ALSO
+.Xr fpathconf 2 ,
+.Xr fspacectl 2 ,
 .Xr open 2 ,
 .Xr md 4 ,
 .Xr ffs 7 ,
 .Xr gpart 8 ,
 .Xr mdmfs 8 ,
-.Xr malloc 9
+.Xr malloc 9 ,
+.Xr vn_deallocate 9
 .Sh HISTORY
 The
 .Nm
diff --git a/sbin/mdconfig/mdconfig.c b/sbin/mdconfig/mdconfig.c
index 0f76ca6149f1..9f4f3fc3a392 100644
--- a/sbin/mdconfig/mdconfig.c
+++ b/sbin/mdconfig/mdconfig.c
@@ -89,7 +89,8 @@ usage(void)
 "       mdconfig file\n");
 	fprintf(stderr, "\t\ttype = {malloc, vnode, swap}\n");
 	fprintf(stderr, "\t\toption = {cache, cluster, compress, force,\n");
-	fprintf(stderr, "\t\t          readonly, reserve, ro, verify}\n");
+	fprintf(stderr, "\t\t          mustdealloc, readonly, reserve, ro,\n");
+	fprintf(stderr, "\t\t          verify}\n");
 	fprintf(stderr, "\t\tsize = %%d (512 byte blocks), %%db (B),\n");
 	fprintf(stderr, "\t\t       %%dk (kB), %%dm (MB), %%dg (GB), \n");
 	fprintf(stderr, "\t\t       %%dt (TB), or %%dp (PB)\n");
@@ -194,6 +195,10 @@ main(int argc, char **argv)
 				mdio.md_options |= MD_FORCE;
 			else if (!strcmp(optarg, "noforce"))
 				mdio.md_options &= ~MD_FORCE;
+			else if (!strcmp(optarg, "mustdealloc"))
+				mdio.md_options |= MD_MUSTDEALLOC;
+			else if (!strcmp(optarg, "nomustdealloc"))
+				mdio.md_options &= ~MD_MUSTDEALLOC;
 			else if (!strcmp(optarg, "readonly"))
 				mdio.md_options |= MD_READONLY;
 			else if (!strcmp(optarg, "noreadonly"))
diff --git a/sys/dev/md/md.c b/sys/dev/md/md.c
index 08fb4b0c6574..92d93f0f0f1d 100644
--- a/sys/dev/md/md.c
+++ b/sys/dev/md/md.c
@@ -90,6 +90,7 @@
 #include <sys/sf_buf.h>
 #include <sys/sysctl.h>
 #include <sys/uio.h>
+#include <sys/unistd.h>
 #include <sys/vnode.h>
 #include <sys/disk.h>
 
@@ -259,6 +260,7 @@ struct md_s {
 	struct g_provider *pp;
 	int (*start)(struct md_s *sc, struct bio *bp);
 	struct devstat *devstat;
+	bool candelete;
 
 	/* MD_MALLOC related fields */
 	struct indir *indir;
@@ -885,9 +887,12 @@ mdstart_vnode(struct md_s *sc, struct bio *bp)
 	case BIO_WRITE:
 		auio.uio_rw = UIO_WRITE;
 		break;
-	case BIO_DELETE:
 	case BIO_FLUSH:
 		break;
+	case BIO_DELETE:
+		if (sc->candelete)
+			break;
+		/* FALLTHROUGH */
 	default:
 		return (EOPNOTSUPP);
 	}
@@ -1176,7 +1181,7 @@ md_handleattr(struct md_s *sc, struct bio *bp)
 	    (g_handleattr_int(bp, "GEOM::fwsectors", sc->fwsectors) != 0 ||
 	    g_handleattr_int(bp, "GEOM::fwheads", sc->fwheads) != 0))
 		return;
-	if (g_handleattr_int(bp, "GEOM::candelete", 1) != 0)
+	if (g_handleattr_int(bp, "GEOM::candelete", sc->candelete) != 0)
 		return;
 	if (sc->ident[0] != '\0' &&
 	    g_handleattr_str(bp, "GEOM::ident", sc->ident) != 0)
@@ -1405,6 +1410,7 @@ mdcreate_vnode(struct md_s *sc, struct md_req *mdr, struct thread *td)
 	struct nameidata nd;
 	char *fname;
 	int error, flags;
+	long v;
 
 	fname = mdr->md_file;
 	if (mdr->md_file_seg == UIO_USERSPACE) {
@@ -1434,6 +1440,13 @@ mdcreate_vnode(struct md_s *sc, struct md_req *mdr, struct thread *td)
 	error = VOP_GETATTR(nd.ni_vp, &vattr, td->td_ucred);
 	if (error != 0)
 		goto bad;
+	if ((mdr->md_options & MD_MUSTDEALLOC) != 0) {
+		error = VOP_PATHCONF(nd.ni_vp, _PC_DEALLOC_PRESENT, &v);
+		if (error != 0)
+			goto bad;
+		if (v == 0)
+			sc->candelete = false;
+	}
 	if (VOP_ISLOCKED(nd.ni_vp) != LK_EXCLUSIVE) {
 		vn_lock(nd.ni_vp, LK_UPGRADE | LK_RETRY);
 		if (VN_IS_DOOMED(nd.ni_vp)) {
@@ -1690,6 +1703,7 @@ kern_mdattach_locked(struct thread *td, struct md_req *mdr)
 		mdr->md_unit = sc->unit;
 	sc->mediasize = mdr->md_mediasize;
 	sc->sectorsize = sectsize;
+	sc->candelete = true;
 	error = EDOOFUS;
 	switch (sc->type) {
 	case MD_MALLOC:
diff --git a/sys/sys/mdioctl.h b/sys/sys/mdioctl.h
index 9e0b0c995341..97464c11149b 100644
--- a/sys/sys/mdioctl.h
+++ b/sys/sys/mdioctl.h
@@ -92,5 +92,6 @@ struct md_ioctl {
 #define MD_ASYNC	0x40	/* Asynchronous mode */
 #define MD_VERIFY	0x80	/* Open file with O_VERIFY (vnode only) */
 #define	MD_CACHE	0x100	/* Cache vnode data */
+#define	MD_MUSTDEALLOC	0x200	/* BIO_DELETE only if dealloc is available */
 
 #endif	/* _SYS_MDIOCTL_H_*/


More information about the dev-commits-src-main mailing list