Author: mav
Date: Fri Oct 14 11:49:36 2016
New Revision: 307315
URL: https://svnweb.freebsd.org/changeset/base/307315

Log:
  7301 zpool export -f should be able to interrupt file freeing
  
  Reviewed by: Matthew Ahrens <mahr...@delphix.com>
  Reviewed by: Sanjay Nadkarni <sanjay.nadka...@nexenta.com>
  Reviewed by: Saso Kiselkov <saso.kisel...@nexenta.com>
  Reviewed by: John Kennedy <john.kenn...@delphix.com>
  Author: Alek Pinchuk <a...@nexenta.com>
  
  Closes #175

Modified:
  vendor-sys/illumos/dist/uts/common/fs/zfs/dmu.c
  vendor-sys/illumos/dist/uts/common/fs/zfs/sys/zfs_znode.h
  vendor-sys/illumos/dist/uts/common/fs/zfs/zfs_dir.c
  vendor-sys/illumos/dist/uts/common/fs/zfs/zfs_vfsops.c

Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/dmu.c
==============================================================================
--- vendor-sys/illumos/dist/uts/common/fs/zfs/dmu.c     Fri Oct 14 11:46:17 
2016        (r307314)
+++ vendor-sys/illumos/dist/uts/common/fs/zfs/dmu.c     Fri Oct 14 11:49:36 
2016        (r307315)
@@ -24,7 +24,7 @@
  */
 /* Copyright (c) 2013 by Saso Kiselkov. All rights reserved. */
 /* Copyright (c) 2013, Joyent, Inc. All rights reserved. */
-/* Copyright (c) 2014, Nexenta Systems, Inc. All rights reserved. */
+/* Copyright 2016 Nexenta Systems, Inc. All rights reserved. */
 
 #include <sys/dmu.h>
 #include <sys/dmu_impl.h>
@@ -695,6 +695,22 @@ get_next_chunk(dnode_t *dn, uint64_t *st
        return (0);
 }
 
+/*
+ * If this objset is of type OST_ZFS return true if vfs's unmounted flag is 
set,
+ * otherwise return false.
+ * Used below in dmu_free_long_range_impl() to enable abort when unmounting
+ */
+/*ARGSUSED*/
+static boolean_t
+dmu_objset_zfs_unmounting(objset_t *os)
+{
+#ifdef _KERNEL
+       if (dmu_objset_type(os) == DMU_OST_ZFS)
+               return (zfs_get_vfs_flag_unmounted(os));
+#endif
+       return (B_FALSE);
+}
+
 static int
 dmu_free_long_range_impl(objset_t *os, dnode_t *dn, uint64_t offset,
     uint64_t length)
@@ -711,6 +727,9 @@ dmu_free_long_range_impl(objset_t *os, d
        while (length != 0) {
                uint64_t chunk_end, chunk_begin;
 
+               if (dmu_objset_zfs_unmounting(dn->dn_objset))
+                       return (SET_ERROR(EINTR));
+
                chunk_end = chunk_begin = offset + length;
 
                /* move chunk_begin backwards to the beginning of this chunk */

Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/sys/zfs_znode.h
==============================================================================
--- vendor-sys/illumos/dist/uts/common/fs/zfs/sys/zfs_znode.h   Fri Oct 14 
11:46:17 2016        (r307314)
+++ vendor-sys/illumos/dist/uts/common/fs/zfs/sys/zfs_znode.h   Fri Oct 14 
11:49:36 2016        (r307315)
@@ -22,6 +22,7 @@
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2012, 2015 by Delphix. All rights reserved.
  * Copyright (c) 2014 Integros [integros.com]
+ * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
  */
 
 #ifndef        _SYS_FS_ZFS_ZNODE_H
@@ -302,6 +303,7 @@ extern int  zfs_sync(vfs_t *vfsp, short f
 extern dev_t   zfs_cmpldev(uint64_t);
 extern int     zfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value);
 extern int     zfs_get_stats(objset_t *os, nvlist_t *nv);
+extern boolean_t zfs_get_vfs_flag_unmounted(objset_t *os);
 extern void    zfs_znode_dmu_fini(znode_t *);
 
 extern void zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,

Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/zfs_dir.c
==============================================================================
--- vendor-sys/illumos/dist/uts/common/fs/zfs/zfs_dir.c Fri Oct 14 11:46:17 
2016        (r307314)
+++ vendor-sys/illumos/dist/uts/common/fs/zfs/zfs_dir.c Fri Oct 14 11:49:36 
2016        (r307315)
@@ -618,8 +618,8 @@ zfs_rmnode(znode_t *zp)
                error = dmu_free_long_range(os, zp->z_id, 0, DMU_OBJECT_END);
                if (error) {
                        /*
-                        * Not enough space.  Leave the file in the unlinked
-                        * set.
+                        * Not enough space or we were interrupted by unmount.
+                        * Leave the file in the unlinked set.
                         */
                        zfs_znode_dmu_fini(zp);
                        zfs_znode_free(zp);

Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/zfs_vfsops.c
==============================================================================
--- vendor-sys/illumos/dist/uts/common/fs/zfs/zfs_vfsops.c      Fri Oct 14 
11:46:17 2016        (r307314)
+++ vendor-sys/illumos/dist/uts/common/fs/zfs/zfs_vfsops.c      Fri Oct 14 
11:49:36 2016        (r307315)
@@ -22,6 +22,7 @@
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2012, 2015 by Delphix. All rights reserved.
  * Copyright (c) 2014 Integros [integros.com]
+ * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
  */
 
 /* Portions Copyright 2010 Robert Milkowski */
@@ -1728,7 +1729,7 @@ zfs_root(vfs_t *vfsp, vnode_t **vpp)
 /*
  * Teardown the zfsvfs::z_os.
  *
- * Note, if 'unmounting' if FALSE, we return with the 'z_teardown_lock'
+ * Note, if 'unmounting' is FALSE, we return with the 'z_teardown_lock'
  * and 'z_teardown_inactive_lock' held.
  */
 static int
@@ -1793,8 +1794,8 @@ zfsvfs_teardown(zfsvfs_t *zfsvfs, boolea
         */
        if (unmounting) {
                zfsvfs->z_unmounted = B_TRUE;
-               rrm_exit(&zfsvfs->z_teardown_lock, FTAG);
                rw_exit(&zfsvfs->z_teardown_inactive_lock);
+               rrm_exit(&zfsvfs->z_teardown_lock, FTAG);
        }
 
        /*
@@ -2272,6 +2273,29 @@ zfs_get_zplprop(objset_t *os, zfs_prop_t
        return (error);
 }
 
+/*
+ * Return true if the coresponding vfs's unmounted flag is set.
+ * Otherwise return false.
+ * If this function returns true we know VFS unmount has been initiated.
+ */
+boolean_t
+zfs_get_vfs_flag_unmounted(objset_t *os)
+{
+       zfsvfs_t *zfvp;
+       boolean_t unmounted = B_FALSE;
+
+       ASSERT(dmu_objset_type(os) == DMU_OST_ZFS);
+
+       mutex_enter(&os->os_user_ptr_lock);
+       zfvp = dmu_objset_get_user(os);
+       if (zfvp != NULL && zfvp->z_vfs != NULL &&
+           (zfvp->z_vfs->vfs_flag & VFS_UNMOUNTED))
+               unmounted = B_TRUE;
+       mutex_exit(&os->os_user_ptr_lock);
+
+       return (unmounted);
+}
+
 static vfsdef_t vfw = {
        VFSDEF_VERSION,
        MNTTYPE_ZFS,
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to