Page MenuHomeFreeBSD

D28834.diff
No OneTemporary

D28834.diff

Index: sys/contrib/openzfs/include/sys/dmu.h
===================================================================
--- sys/contrib/openzfs/include/sys/dmu.h
+++ sys/contrib/openzfs/include/sys/dmu.h
@@ -820,6 +820,8 @@
*/
int dmu_free_range(objset_t *os, uint64_t object, uint64_t offset,
uint64_t size, dmu_tx_t *tx);
+int dmu_free_long_range_ofs(objset_t *os, uint64_t object, uint64_t *offset,
+ uint64_t *length);
int dmu_free_long_range(objset_t *os, uint64_t object, uint64_t offset,
uint64_t size);
int dmu_free_long_object(objset_t *os, uint64_t object);
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
@@ -5222,6 +5222,9 @@
case _PC_NAME_MAX:
*ap->a_retval = NAME_MAX;
return (0);
+ case _PC_DEALLOC_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;
@@ -6057,6 +6060,80 @@
return (error);
}
+static int
+zfs_deallocate(struct vop_deallocate_args *ap)
+{
+ dmu_tx_t *tx;
+ vnode_t *vp;
+ znode_t *zp;
+ zfsvfs_t *zfsvfs;
+ zilog_t *zilog;
+ zfs_locked_range_t *lr;
+ uint64_t mtime[2], ctime[2];
+ sa_bulk_attr_t bulk[3];
+ off_t off, len;
+ int count = 0;
+ int error;
+
+ vp = ap->a_vp;
+ zp = VTOZ(vp);
+ zfsvfs = ZTOZSB(zp);
+ zilog = zfsvfs->z_log;
+ off = *ap->a_offset;
+ len = *ap->a_len;
+
+ ZFS_ENTER(zfsvfs);
+ ZFS_VERIFY_ZP(zp);
+
+ lr = zfs_rangelock_enter(&zp->z_rangelock, off, len, RL_WRITER);
+
+ if (off >= zp->z_size) {
+ *ap->a_len = 0;
+ error = 0;
+ goto out;
+ }
+
+ if (len > zp->z_size - off)
+ len = *ap->a_len = zp->z_size - off;
+ error = dmu_free_long_range_ofs(zfsvfs->z_os, zp->z_id, ap->a_offset,
+ ap->a_len);
+ if (error != 0)
+ goto out;
+
+ vnode_pager_purge_range(vp, off, off + len);
+
+ tx = dmu_tx_create(zfsvfs->z_os);
+ dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE);
+ zfs_sa_upgrade_txholds(tx, zp);
+ error = dmu_tx_assign(tx, TXG_WAIT);
+ if (error) {
+ dmu_tx_abort(tx);
+ goto out;
+ }
+
+ SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zfsvfs), NULL, mtime, 16);
+ SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL, ctime, 16);
+ SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs),
+ NULL, &zp->z_pflags, 8);
+ zfs_tstamp_update_setup(zp, CONTENT_MODIFIED, mtime, ctime);
+ error = sa_bulk_update(zp->z_sa_hdl, bulk, count, tx);
+ ASSERT(error == 0);
+
+ /*
+ * The log record is TX_TRUNCATE during replay. off + len has been
+ * truncated to fit within znode size to make sure the file size is not
+ * expanded.
+ */
+ zfs_log_truncate(zilog, tx, TX_TRUNCATE, zp, off, len);
+
+ dmu_tx_commit(tx);
+out:
+ zfs_rangelock_exit(lr);
+
+ ZFS_EXIT(zfsvfs);
+ return (error);
+}
+
struct vop_vector zfs_vnodeops;
struct vop_vector zfs_fifoops;
struct vop_vector zfs_shareops;
@@ -6076,6 +6153,7 @@
#endif
.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
@@ -1480,14 +1480,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);
Index: sys/contrib/openzfs/module/zfs/dmu.c
===================================================================
--- sys/contrib/openzfs/module/zfs/dmu.c
+++ sys/contrib/openzfs/module/zfs/dmu.c
@@ -824,8 +824,8 @@
}
static int
-dmu_free_long_range_impl(objset_t *os, dnode_t *dn, uint64_t offset,
- uint64_t length)
+dmu_free_long_range_impl(objset_t *os, dnode_t *dn, uint64_t * const offset,
+ uint64_t * const length)
{
uint64_t object_size;
int err;
@@ -836,7 +836,7 @@
return (SET_ERROR(EINVAL));
object_size = (dn->dn_maxblkid + 1) * dn->dn_datablksz;
- if (offset >= object_size)
+ if (*offset >= object_size)
return (0);
if (zfs_per_txg_dirty_frees_percent <= 100)
@@ -845,10 +845,10 @@
else
dirty_frees_threshold = zfs_dirty_data_max / 20;
- if (length == DMU_OBJECT_END || offset + length > object_size)
- length = object_size - offset;
+ if (*length == DMU_OBJECT_END || *offset + *length > object_size)
+ *length = object_size - *offset;
- while (length != 0) {
+ while (*length != 0) {
uint64_t chunk_end, chunk_begin, chunk_len;
uint64_t l1blks;
dmu_tx_t *tx;
@@ -856,13 +856,13 @@
if (dmu_objset_zfs_unmounting(dn->dn_objset))
return (SET_ERROR(EINTR));
- chunk_end = chunk_begin = offset + length;
+ chunk_end = chunk_begin = *offset + *length;
/* move chunk_begin backwards to the beginning of this chunk */
- err = get_next_chunk(dn, &chunk_begin, offset, &l1blks);
+ err = get_next_chunk(dn, &chunk_begin, *offset, &l1blks);
if (err)
return (err);
- ASSERT3U(chunk_begin, >=, offset);
+ ASSERT3U(chunk_begin, >=, *offset);
ASSERT3U(chunk_begin, <=, chunk_end);
chunk_len = chunk_end - chunk_begin;
@@ -922,22 +922,25 @@
dmu_tx_commit(tx);
- length -= chunk_len;
+ *length -= chunk_len;
}
return (0);
}
int
-dmu_free_long_range(objset_t *os, uint64_t object,
- uint64_t offset, uint64_t length)
+dmu_free_long_range_ofs(objset_t *os, uint64_t object,
+ uint64_t *offset, uint64_t *length)
{
dnode_t *dn;
+ uint64_t off, len;
int err;
err = dnode_hold(os, object, FTAG, &dn);
if (err != 0)
return (err);
- err = dmu_free_long_range_impl(os, dn, offset, length);
+ off = *offset;
+ len = *length;
+ err = dmu_free_long_range_impl(os, dn, &off, &len);
/*
* It is important to zero out the maxblkid when freeing the entire
@@ -945,13 +948,22 @@
* will take the fast path, and (b) dnode_reallocate() can verify
* that the entire file has been freed.
*/
- if (err == 0 && offset == 0 && length == DMU_OBJECT_END)
+ if (err == 0 && *offset == 0 && *length == DMU_OBJECT_END)
dn->dn_maxblkid = 0;
dnode_rele(dn, FTAG);
+ *offset = off;
+ *length = len;
return (err);
}
+int
+dmu_free_long_range(objset_t *os, uint64_t object,
+ uint64_t offset, uint64_t length)
+{
+ return (dmu_free_long_range_ofs(os, object, &offset, &length));
+}
+
int
dmu_free_long_object(objset_t *os, uint64_t object)
{

File Metadata

Mime Type
text/plain
Expires
Sun, Nov 17, 7:58 AM (32 m, 11 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14672897
Default Alt Text
D28834.diff (6 KB)

Event Timeline