diff options
author | Ka Ho Ng <khng@FreeBSD.org> | 2021-09-11 12:03:38 +0000 |
---|---|---|
committer | Ka Ho Ng <khng@FreeBSD.org> | 2021-09-11 12:04:52 +0000 |
commit | 3703c18883341f3ff09c42d7f3b36ab80e4a071b (patch) | |
tree | 2463648a1f0b2dc6446e65cfcac0de59bcc33d66 /sys/dev/md | |
parent | 71a1ae7cebd3791d4d18ac9620a7a4ce8cf15819 (diff) | |
download | src-3703c18883341f3ff09c42d7f3b36ab80e4a071b.tar.gz src-3703c18883341f3ff09c42d7f3b36ab80e4a071b.zip |
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
Diffstat (limited to 'sys/dev/md')
-rw-r--r-- | sys/dev/md/md.c | 18 |
1 files changed, 16 insertions, 2 deletions
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: |