Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F139444916
D28834.id85983.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D28834.id85983.diff
View Options
Index: sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c
===================================================================
--- sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c
+++ sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c
@@ -3800,6 +3800,49 @@
return (error);
}
+/*
+ * common code for zfs_space-related operations
+ *
+ * This function is called from zfs_space and zfs_deallocate.
+ */
+static int
+zfs_space_common(znode_t *zp, int cmd, off_t off, off_t len, int flag,
+ cred_t *cr)
+{
+ zfsvfs_t *zfsvfs = ZTOZSB(zp);
+ uint64_t uoff, ulen;
+ int error;
+
+ if (cmd != F_FREESP)
+ return (EINVAL);
+
+ /*
+ * Callers might not be able to detect properly that we are read-only,
+ * so check it explicitly here.
+ */
+ if (zfs_is_readonly(zfsvfs))
+ return (EROFS);
+
+ if (len < 0)
+ return (EINVAL);
+
+ /*
+ * Permissions aren't checked on Solaris because on this OS
+ * zfs_space() can only be called with an opened file handle.
+ * On Linux we can get here through truncate_range() which
+ * operates directly on inodes, so we need to check access rights.
+ */
+ if ((error = zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr)))
+ return (error);
+
+ uoff = off;
+ ulen = len;
+
+ error = zfs_freesp(zp, uoff, ulen, flag, TRUE);
+
+ return (error);
+}
+
/*
* Free or allocate space in a file. Currently, this function only
* supports the `F_FREESP' command. However, this command is somewhat
@@ -3824,47 +3867,16 @@
offset_t offset, cred_t *cr)
{
zfsvfs_t *zfsvfs = ZTOZSB(zp);
- uint64_t off, len;
+ off_t off, len;
int error;
ZFS_ENTER(zfsvfs);
ZFS_VERIFY_ZP(zp);
- if (cmd != F_FREESP) {
- ZFS_EXIT(zfsvfs);
- return (SET_ERROR(EINVAL));
- }
-
- /*
- * Callers might not be able to detect properly that we are read-only,
- * so check it explicitly here.
- */
- if (zfs_is_readonly(zfsvfs)) {
- ZFS_EXIT(zfsvfs);
- return (SET_ERROR(EROFS));
- }
-
- if (bfp->l_len < 0) {
- ZFS_EXIT(zfsvfs);
- return (SET_ERROR(EINVAL));
- }
-
- /*
- * Permissions aren't checked on Solaris because on this OS
- * zfs_space() can only be called with an opened file handle.
- * On Linux we can get here through truncate_range() which
- * operates directly on inodes, so we need to check access rights.
- */
- if ((error = zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr))) {
- ZFS_EXIT(zfsvfs);
- return (error);
- }
-
off = bfp->l_start;
len = bfp->l_len; /* 0 means from off to end of file */
- error = zfs_freesp(zp, off, len, flag, TRUE);
-
+ error = zfs_space_common(zp, cmd, off, len, flag, cr);
ZFS_EXIT(zfsvfs);
return (error);
}
@@ -5196,6 +5208,9 @@
case _PC_NAME_MAX:
*ap->a_retval = NAME_MAX;
return (0);
+ case _PC_FDEALLOC_PRESENT:
+ *ap->a_retval = 1;
+ return (0);
case _PC_PIPE_BUF:
if (ap->a_vp->v_type == VDIR || ap->a_vp->v_type == VFIFO) {
*ap->a_retval = PIPE_BUF;
@@ -5792,6 +5807,43 @@
return (error);
}
+/*
+ * This is mostly the same as zfs_space except it also limits the range of
+ * operation to zp->z_size. The log
+ * record of zfs_space during replay would be the same as ordinary zfs_space.
+ */
+static int
+zfs_deallocate(struct vop_deallocate_args *ap)
+{
+ vnode_t *vp;
+ znode_t *zp;
+ zfsvfs_t *zfsvfs;
+ off_t offset, len;
+ int error;
+
+ vp = ap->a_vp;
+ zp = VTOZ(vp);
+ zfsvfs = ZTOZSB(zp);
+
+ ZFS_ENTER(zfsvfs);
+ ZFS_VERIFY_ZP(zp);
+
+ offset = *ap->a_offset;
+ len = *ap->a_len;
+
+ len = omin(len, zp->z_size - offset);
+ if (len == 0) {
+ error = 0;
+ goto out;
+ }
+ error = zfs_space_common(zp, F_FREESP, offset, len, O_RDWR, ap->a_cred);
+out:
+ if (__predict_true(error == 0))
+ *ap->a_len = 0;
+ ZFS_EXIT(zfsvfs);
+ return (error);
+}
+
struct vop_vector zfs_vnodeops;
struct vop_vector zfs_fifoops;
struct vop_vector zfs_shareops;
@@ -5809,6 +5861,7 @@
.vop_fplookup_symlink = zfs_freebsd_fplookup_symlink,
.vop_access = zfs_freebsd_access,
.vop_allocate = VOP_EINVAL,
+ .vop_deallocate = zfs_deallocate,
.vop_lookup = zfs_cache_lookup,
.vop_cachedlookup = zfs_freebsd_cachedlookup,
.vop_getattr = zfs_freebsd_getattr,
Index: sys/contrib/openzfs/module/os/freebsd/zfs/zfs_znode.c
===================================================================
--- sys/contrib/openzfs/module/os/freebsd/zfs/zfs_znode.c
+++ sys/contrib/openzfs/module/os/freebsd/zfs/zfs_znode.c
@@ -1449,14 +1449,8 @@
error = dmu_free_long_range(zfsvfs->z_os, zp->z_id, off, len);
- if (error == 0) {
- /*
- * In FreeBSD we cannot free block in the middle of a file,
- * but only at the end of a file, so this code path should
- * never happen.
- */
- vnode_pager_setsize(ZTOV(zp), off);
- }
+ if (error == 0)
+ vnode_pager_purge_range(ZTOV(zp), off, off + len);
zfs_rangelock_exit(lr);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Dec 13, 4:17 AM (11 h, 53 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
26920936
Default Alt Text
D28834.id85983.diff (4 KB)
Attached To
Mode
D28834: Wire up OpenZFS with VOP_DEALLOCATE(9)
Attached
Detach File
Event Timeline
Log In to Comment