OpenZFS 7301 - zpool export -f should be able to interrupt file freeing
Authored by: Alek Pinchuk <alek@nexenta.com> Reviewed by: Matthew Ahrens <mahrens@delphix.com> Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com> Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com> Reviewed by: John Kennedy <john.kennedy@delphix.com> Approved by: Gordon Ross <gordon.ross@nexenta.com> Reviewed-by: Tim Chase <tim@chase2k.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Ported-by: George Melikov <mail@gmelikov.ru> OpenZFS-issue: https://www.illumos.org/issues/7301 OpenZFS-commit: https://github.com/openzfs/openzfs/commit/eb72182 Closes #5680
This commit is contained in:
parent
cc9bb3e58e
commit
a08abc1bb3
|
@ -21,6 +21,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012, 2015 by Delphix. All rights reserved.
|
* Copyright (c) 2012, 2015 by Delphix. All rights reserved.
|
||||||
|
* Copyright 2016 Nexenta Systems, Inc. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _SYS_FS_ZFS_ZNODE_H
|
#ifndef _SYS_FS_ZFS_ZNODE_H
|
||||||
|
@ -311,6 +312,7 @@ extern int zfs_sync(struct super_block *, int, cred_t *);
|
||||||
extern dev_t zfs_cmpldev(uint64_t);
|
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_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value);
|
||||||
extern int zfs_get_stats(objset_t *os, nvlist_t *nv);
|
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_znode_dmu_fini(znode_t *);
|
||||||
extern int zfs_inode_alloc(struct super_block *, struct inode **ip);
|
extern int zfs_inode_alloc(struct super_block *, struct inode **ip);
|
||||||
extern void zfs_inode_destroy(struct inode *);
|
extern void zfs_inode_destroy(struct inode *);
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
* Copyright (c) 2011, 2016 by Delphix. All rights reserved.
|
* Copyright (c) 2011, 2016 by Delphix. All rights reserved.
|
||||||
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
|
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
|
||||||
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
|
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
|
||||||
* Copyright (c) 2014, Nexenta Systems, Inc. All rights reserved.
|
* Copyright (c) 2016, Nexenta Systems, Inc. All rights reserved.
|
||||||
* Copyright (c) 2015 by Chunwei Chen. All rights reserved.
|
* Copyright (c) 2015 by Chunwei Chen. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -705,6 +705,22 @@ get_next_chunk(dnode_t *dn, uint64_t *start, uint64_t minimum)
|
||||||
return (0);
|
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
|
static int
|
||||||
dmu_free_long_range_impl(objset_t *os, dnode_t *dn, uint64_t offset,
|
dmu_free_long_range_impl(objset_t *os, dnode_t *dn, uint64_t offset,
|
||||||
uint64_t length)
|
uint64_t length)
|
||||||
|
@ -726,6 +742,9 @@ dmu_free_long_range_impl(objset_t *os, dnode_t *dn, uint64_t offset,
|
||||||
uint64_t chunk_end, chunk_begin;
|
uint64_t chunk_end, chunk_begin;
|
||||||
dmu_tx_t *tx;
|
dmu_tx_t *tx;
|
||||||
|
|
||||||
|
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 */
|
/* move chunk_begin backwards to the beginning of this chunk */
|
||||||
|
|
|
@ -644,8 +644,8 @@ zfs_rmnode(znode_t *zp)
|
||||||
error = dmu_free_long_range(os, zp->z_id, 0, DMU_OBJECT_END);
|
error = dmu_free_long_range(os, zp->z_id, 0, DMU_OBJECT_END);
|
||||||
if (error) {
|
if (error) {
|
||||||
/*
|
/*
|
||||||
* Not enough space. Leave the file in the unlinked
|
* Not enough space or we were interrupted by unmount.
|
||||||
* set.
|
* Leave the file in the unlinked set.
|
||||||
*/
|
*/
|
||||||
zfs_znode_dmu_fini(zp);
|
zfs_znode_dmu_fini(zp);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1263,7 +1263,7 @@ EXPORT_SYMBOL(zfs_sb_prune);
|
||||||
/*
|
/*
|
||||||
* Teardown the zfs_sb_t.
|
* Teardown the zfs_sb_t.
|
||||||
*
|
*
|
||||||
* 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.
|
* and 'z_teardown_inactive_lock' held.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
|
@ -1358,8 +1358,8 @@ zfs_sb_teardown(zfs_sb_t *zsb, boolean_t unmounting)
|
||||||
*/
|
*/
|
||||||
if (unmounting) {
|
if (unmounting) {
|
||||||
zsb->z_unmounted = B_TRUE;
|
zsb->z_unmounted = B_TRUE;
|
||||||
rrm_exit(&zsb->z_teardown_lock, FTAG);
|
|
||||||
rw_exit(&zsb->z_teardown_inactive_lock);
|
rw_exit(&zsb->z_teardown_inactive_lock);
|
||||||
|
rrm_exit(&zsb->z_teardown_lock, FTAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1906,6 +1906,28 @@ zfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(zfs_get_zplprop);
|
EXPORT_SYMBOL(zfs_get_zplprop);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
zfs_sb_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_unmounted)
|
||||||
|
unmounted = B_TRUE;
|
||||||
|
mutex_exit(&os->os_user_ptr_lock);
|
||||||
|
|
||||||
|
return (unmounted);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
zfs_init(void)
|
zfs_init(void)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue