git: 8d7cd10ba633 - main - tmpfs: Implement VOP_DEALLOCATE
Ka Ho Ng
khng at FreeBSD.org
Wed Aug 25 21:35:14 UTC 2021
The branch main has been updated by khng:
URL: https://cgit.FreeBSD.org/src/commit/?id=8d7cd10ba633309a2fa8c0d6475f85e0266e3d94
commit 8d7cd10ba633309a2fa8c0d6475f85e0266e3d94
Author: Ka Ho Ng <khng at FreeBSD.org>
AuthorDate: 2021-08-25 21:34:35 +0000
Commit: Ka Ho Ng <khng at FreeBSD.org>
CommitDate: 2021-08-25 21:34:54 +0000
tmpfs: Implement VOP_DEALLOCATE
Implementing VOP_DEALLOCATE to allow hole-punching in the same manner as
POSIX shared memory's fspacectl(SPACECTL_DEALLOC) support.
Sponsored by: The FreeBSD Foundation
Reviewed by: kib
Differential Revision: https://reviews.freebsd.org/D31684
---
sys/fs/tmpfs/tmpfs.h | 1 +
sys/fs/tmpfs/tmpfs_subr.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++
sys/fs/tmpfs/tmpfs_vnops.c | 7 ++++
3 files changed, 93 insertions(+)
diff --git a/sys/fs/tmpfs/tmpfs.h b/sys/fs/tmpfs/tmpfs.h
index 99368d67aaaa..bfa12b0382bc 100644
--- a/sys/fs/tmpfs/tmpfs.h
+++ b/sys/fs/tmpfs/tmpfs.h
@@ -459,6 +459,7 @@ int tmpfs_dir_getdents(struct tmpfs_mount *, struct tmpfs_node *,
int tmpfs_dir_whiteout_add(struct vnode *, struct componentname *);
void tmpfs_dir_whiteout_remove(struct vnode *, struct componentname *);
int tmpfs_reg_resize(struct vnode *, off_t, boolean_t);
+int tmpfs_reg_punch_hole(struct vnode *vp, off_t *, off_t *);
int tmpfs_chflags(struct vnode *, u_long, struct ucred *, struct thread *);
int tmpfs_chmod(struct vnode *, mode_t, struct ucred *, struct thread *);
int tmpfs_chown(struct vnode *, uid_t, gid_t, struct ucred *,
diff --git a/sys/fs/tmpfs/tmpfs_subr.c b/sys/fs/tmpfs/tmpfs_subr.c
index e746a7455860..1b7521cf0b0d 100644
--- a/sys/fs/tmpfs/tmpfs_subr.c
+++ b/sys/fs/tmpfs/tmpfs_subr.c
@@ -1775,6 +1775,91 @@ tmpfs_reg_resize(struct vnode *vp, off_t newsize, boolean_t ignerr)
return (0);
}
+/*
+ * Punch hole in the aobj associated with the regular file pointed to by 'vp'.
+ * Requests completely beyond the end-of-file are converted to no-op.
+ *
+ * Returns 0 on success or error code from tmpfs_partial_page_invalidate() on
+ * failure.
+ */
+int
+tmpfs_reg_punch_hole(struct vnode *vp, off_t *offset, off_t *length)
+{
+ struct tmpfs_mount *tmp;
+ struct tmpfs_node *node;
+ vm_object_t object;
+ vm_pindex_t pistart, pi, piend;
+ int startofs, endofs, end;
+ off_t off, len;
+ int error;
+
+ KASSERT(*length <= OFF_MAX - *offset, ("%s: offset + length overflows",
+ __func__));
+ node = VP_TO_TMPFS_NODE(vp);
+ KASSERT(node->tn_type == VREG, ("%s: node is not regular file",
+ __func__));
+ object = node->tn_reg.tn_aobj;
+ tmp = VFS_TO_TMPFS(vp->v_mount);
+ off = *offset;
+ len = omin(node->tn_size - off, *length);
+ startofs = off & PAGE_MASK;
+ endofs = (off + len) & PAGE_MASK;
+ pistart = OFF_TO_IDX(off);
+ piend = OFF_TO_IDX(off + len);
+ pi = OFF_TO_IDX((vm_ooffset_t)off + PAGE_MASK);
+ error = 0;
+
+ /* Handle the case when offset is on or beyond file size. */
+ if (len <= 0) {
+ *length = 0;
+ return (0);
+ }
+
+ VM_OBJECT_WLOCK(object);
+
+ /*
+ * If there is a partial page at the beginning of the hole-punching
+ * request, fill the partial page with zeroes.
+ */
+ if (startofs != 0) {
+ end = pistart != piend ? PAGE_SIZE : endofs;
+ error = tmpfs_partial_page_invalidate(object, pistart, startofs,
+ end, FALSE);
+ if (error != 0)
+ goto out;
+ off += end - startofs;
+ len -= end - startofs;
+ }
+
+ /*
+ * Toss away the full pages in the affected area.
+ */
+ if (pi < piend) {
+ vm_object_page_remove(object, pi, piend, 0);
+ off += IDX_TO_OFF(piend - pi);
+ len -= IDX_TO_OFF(piend - pi);
+ }
+
+ /*
+ * If there is a partial page at the end of the hole-punching request,
+ * fill the partial page with zeroes.
+ */
+ if (endofs != 0 && pistart != piend) {
+ error = tmpfs_partial_page_invalidate(object, piend, 0, endofs,
+ FALSE);
+ if (error != 0)
+ goto out;
+ off += endofs;
+ len -= endofs;
+ }
+
+out:
+ VM_OBJECT_WUNLOCK(object);
+ *offset = off;
+ *length = len;
+ return (error);
+}
+
void
tmpfs_check_mtime(struct vnode *vp)
{
diff --git a/sys/fs/tmpfs/tmpfs_vnops.c b/sys/fs/tmpfs/tmpfs_vnops.c
index 326a5132990d..d8c74cecdfe4 100644
--- a/sys/fs/tmpfs/tmpfs_vnops.c
+++ b/sys/fs/tmpfs/tmpfs_vnops.c
@@ -695,6 +695,12 @@ out:
return (error);
}
+static int
+tmpfs_deallocate(struct vop_deallocate_args *v)
+{
+ return (tmpfs_reg_punch_hole(v->a_vp, v->a_offset, v->a_len));
+}
+
static int
tmpfs_fsync(struct vop_fsync_args *v)
{
@@ -1840,6 +1846,7 @@ struct vop_vector tmpfs_vnodeop_entries = {
.vop_read = tmpfs_read,
.vop_read_pgcache = tmpfs_read_pgcache,
.vop_write = tmpfs_write,
+ .vop_deallocate = tmpfs_deallocate,
.vop_fsync = tmpfs_fsync,
.vop_remove = tmpfs_remove,
.vop_link = tmpfs_link,
More information about the dev-commits-src-main
mailing list