The branch main has been updated by khng:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=8d7cd10ba633309a2fa8c0d6475f85e0266e3d94

commit 8d7cd10ba633309a2fa8c0d6475f85e0266e3d94
Author:     Ka Ho Ng <k...@freebsd.org>
AuthorDate: 2021-08-25 21:34:35 +0000
Commit:     Ka Ho Ng <k...@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,
_______________________________________________
dev-commits-src-main@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-main
To unsubscribe, send any mail to "dev-commits-src-main-unsubscr...@freebsd.org"

Reply via email to