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"

Reply via email to