Index: sbin/mdconfig/mdconfig.8 =================================================================== --- sbin/mdconfig/mdconfig.8 +++ sbin/mdconfig/mdconfig.8 @@ -37,7 +37,7 @@ .\" .\" $FreeBSD$ .\" -.Dd November 6, 2020 +.Dd August 27, 2021 .Dt MDCONFIG 8 .Os .Sh NAME @@ -256,6 +256,12 @@ The type of verification depends on which security features are available. One example of verification is testing file integrity with checksums or cryptographic signatures. +.It Oo Cm no Oc Ns Cm autounmap +Detect if hole-punching is supported by the underlying file system. +If the underlying file system of the vnode type memory disk does not support +hole-punching, +.Dv BIO_DELETE +requests are returned unsupported. .El .It Fl u Ar unit Request a specific unit number or device name for the Index: sbin/mdconfig/mdconfig.c =================================================================== --- sbin/mdconfig/mdconfig.c +++ sbin/mdconfig/mdconfig.c @@ -88,8 +88,8 @@ " mdconfig -l [-v] [-n] [-f file] [-u unit]\n" " 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\toption = {autounmap, cache, cluster, compress,\n"); + fprintf(stderr, "\t\t force, readonly, reserve, ro, 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"); @@ -210,6 +210,10 @@ mdio.md_options |= MD_VERIFY; else if (!strcmp(optarg, "noverify")) mdio.md_options &= ~MD_VERIFY; + else if (!strcmp(optarg, "autounmap")) + mdio.md_options |= MD_AUTOUNMAP; + else if (!strcmp(optarg, "noautounmap")) + mdio.md_options &= ~MD_AUTOUNMAP; else errx(1, "unknown option: %s", optarg); break; Index: sys/dev/md/md.c =================================================================== --- sys/dev/md/md.c +++ sys/dev/md/md.c @@ -90,6 +90,7 @@ #include #include #include +#include #include #include @@ -259,6 +260,7 @@ 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 @@ 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 @@ (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 @@ 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 @@ error = VOP_GETATTR(nd.ni_vp, &vattr, td->td_ucred); if (error != 0) goto bad; + if ((mdr->md_options & MD_AUTOUNMAP) != 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 @@ mdr->md_unit = sc->unit; sc->mediasize = mdr->md_mediasize; sc->sectorsize = sectsize; + sc->candelete = true; error = EDOOFUS; switch (sc->type) { case MD_MALLOC: Index: sys/sys/mdioctl.h =================================================================== --- sys/sys/mdioctl.h +++ sys/sys/mdioctl.h @@ -92,5 +92,6 @@ #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_AUTOUNMAP 0x200 /* Detect if hole-punching is available */ #endif /* _SYS_MDIOCTL_H_*/