Author: mav Date: Sat Oct 3 11:21:50 2015 New Revision: 288590 URL: https://svnweb.freebsd.org/changeset/base/288590
Log: MFC r287103 (by avg): 5692 expose the number of hole blocks in a file FreeBSD porting notes: - only kernel-side changes are merged - the new ioctl is not actually implemented yet - thus, the goal is to synchronize DMU code illumos/illumos-gate@2bcf0248e992f292c7b814458bcdce2f004925d6 https://www.illumos.org/issues/5692 we would like to expose the number of hole (sparse) blocks in a file. this can be useful to for example if you want to fill in the holes with some data; knowing the number of holes in advances allows you to report progress on hole filling. We could use SEEK_HOLE to do that but it would be O(n) where n is the number of holes present in the file. Author: Max Grossman <max.gross...@delphix.com> Reviewed by: Adam Leventhal <a...@delphix.com> Reviewed by: Matthew Ahrens <mahr...@delphix.com> Reviewed by: Boris Protopopov <bprotopo...@hotmail.com> Approved by: Richard Lowe <richl...@richlowe.net> Modified: stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c ============================================================================== --- stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c Sat Oct 3 11:19:32 2015 (r288589) +++ stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c Sat Oct 3 11:21:50 2015 (r288590) @@ -1902,25 +1902,20 @@ int dmu_offset_next(objset_t *os, uint64_t object, boolean_t hole, uint64_t *off) { dnode_t *dn; - int i, err; + int err; - err = dnode_hold(os, object, FTAG, &dn); - if (err) - return (err); /* * Sync any current changes before * we go trundling through the block pointers. */ - for (i = 0; i < TXG_SIZE; i++) { - if (list_link_active(&dn->dn_dirty_link[i])) - break; + err = dmu_object_wait_synced(os, object); + if (err) { + return (err); } - if (i != TXG_SIZE) { - dnode_rele(dn, FTAG); - txg_wait_synced(dmu_objset_pool(os), 0); - err = dnode_hold(os, object, FTAG, &dn); - if (err) - return (err); + + err = dnode_hold(os, object, FTAG, &dn); + if (err) { + return (err); } err = dnode_next_offset(dn, (hole ? DNODE_FIND_HOLE : 0), off, 1, 1, 0); @@ -1929,6 +1924,36 @@ dmu_offset_next(objset_t *os, uint64_t o return (err); } +/* + * Given the ZFS object, if it contains any dirty nodes + * this function flushes all dirty blocks to disk. This + * ensures the DMU object info is updated. A more efficient + * future version might just find the TXG with the maximum + * ID and wait for that to be synced. + */ +int +dmu_object_wait_synced(objset_t *os, uint64_t object) { + dnode_t *dn; + int error, i; + + error = dnode_hold(os, object, FTAG, &dn); + if (error) { + return (error); + } + + for (i = 0; i < TXG_SIZE; i++) { + if (list_link_active(&dn->dn_dirty_link[i])) { + break; + } + } + dnode_rele(dn, FTAG); + if (i != TXG_SIZE) { + txg_wait_synced(dmu_objset_pool(os), 0); + } + + return (0); +} + void dmu_object_info_from_dnode(dnode_t *dn, dmu_object_info_t *doi) { Modified: stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h ============================================================================== --- stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h Sat Oct 3 11:19:32 2015 (r288589) +++ stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h Sat Oct 3 11:21:50 2015 (r288590) @@ -915,6 +915,15 @@ int dmu_offset_next(objset_t *os, uint64 uint64_t *off); /* + * Check if a DMU object has any dirty blocks. If so, sync out + * all pending transaction groups. Otherwise, this function + * does not alter DMU state. This could be improved to only sync + * out the necessary transaction groups for this particular + * object. + */ +int dmu_object_wait_synced(objset_t *os, uint64_t object); + +/* * Initial setup and final teardown. */ extern void dmu_init(void); Modified: stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c ============================================================================== --- stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c Sat Oct 3 11:19:32 2015 (r288589) +++ stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c Sat Oct 3 11:21:50 2015 (r288590) @@ -293,25 +293,32 @@ zfs_ioctl(vnode_t *vp, u_long com, intpt int *rvalp, caller_context_t *ct) { offset_t off; + offset_t ndata; + dmu_object_info_t doi; int error; zfsvfs_t *zfsvfs; znode_t *zp; switch (com) { case _FIOFFS: + { return (0); /* * The following two ioctls are used by bfu. Faking out, * necessary to avoid bfu errors. */ + } case _FIOGDIO: case _FIOSDIO: + { return (0); + } case _FIO_SEEK_DATA: case _FIO_SEEK_HOLE: -#ifdef sun + { +#ifdef illumos if (ddi_copyin((void *)data, &off, sizeof (off), flag)) return (SET_ERROR(EFAULT)); #else @@ -335,6 +342,48 @@ zfs_ioctl(vnode_t *vp, u_long com, intpt #endif return (0); } +#ifdef illumos + case _FIO_COUNT_FILLED: + { + /* + * _FIO_COUNT_FILLED adds a new ioctl command which + * exposes the number of filled blocks in a + * ZFS object. + */ + zp = VTOZ(vp); + zfsvfs = zp->z_zfsvfs; + ZFS_ENTER(zfsvfs); + ZFS_VERIFY_ZP(zp); + + /* + * Wait for all dirty blocks for this object + * to get synced out to disk, and the DMU info + * updated. + */ + error = dmu_object_wait_synced(zfsvfs->z_os, zp->z_id); + if (error) { + ZFS_EXIT(zfsvfs); + return (error); + } + + /* + * Retrieve fill count from DMU object. + */ + error = dmu_object_info(zfsvfs->z_os, zp->z_id, &doi); + if (error) { + ZFS_EXIT(zfsvfs); + return (error); + } + + ndata = doi.doi_fill_count; + + ZFS_EXIT(zfsvfs); + if (ddi_copyout(&ndata, (void *)data, sizeof (ndata), flag)) + return (SET_ERROR(EFAULT)); + return (0); + } +#endif + } return (SET_ERROR(ENOTTY)); } _______________________________________________ svn-src-stable-10@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-stable-10 To unsubscribe, send any mail to "svn-src-stable-10-unsubscr...@freebsd.org"