Page MenuHomeFreeBSD

D31684.diff
No OneTemporary

D31684.diff

diff --git a/sys/fs/tmpfs/tmpfs.h b/sys/fs/tmpfs/tmpfs.h
--- a/sys/fs/tmpfs/tmpfs.h
+++ b/sys/fs/tmpfs/tmpfs.h
@@ -459,6 +459,7 @@
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
--- a/sys/fs/tmpfs/tmpfs_subr.c
+++ b/sys/fs/tmpfs/tmpfs_subr.c
@@ -1775,6 +1775,91 @@
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
--- a/sys/fs/tmpfs/tmpfs_vnops.c
+++ b/sys/fs/tmpfs/tmpfs_vnops.c
@@ -695,6 +695,12 @@
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 @@
.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,

File Metadata

Mime Type
text/plain
Expires
Tue, Oct 1, 5:29 PM (22 h, 2 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
13267781
Default Alt Text
D31684.diff (3 KB)

Event Timeline