aboutsummaryrefslogtreecommitdiffstats
path: root/uts
diff options
context:
space:
mode:
authorAlexander Motin <mav@FreeBSD.org>2019-06-03 17:01:16 +0000
committerAlexander Motin <mav@FreeBSD.org>2019-06-03 17:01:16 +0000
commit86a6a20c48b548859f3498d8e18c64c64a733152 (patch)
tree3d16ef0e6413f8a1c64a5d475743469bce5ef27e /uts
parent380d790f2b00f30813940e0535cd6b83e8cc7d96 (diff)
downloadsrc-86a6a20c48b548859f3498d8e18c64c64a733152.tar.gz
src-86a6a20c48b548859f3498d8e18c64c64a733152.zip
1700 Add SCSI UNMAP support
illumos/illumos-gate@047c81d31d0f571d6652e97143cd15281de61e84 Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com> Reviewed by: Garrett D'Amore <garrett@damore.org> Reviewed by: Igor Kozhukhov <igor@dilos.org> Approved by: Dan McDonald <danmcd@joyent.com> Author: Saso Kiselkov <saso.kiselkov@nexenta.com>
Notes
Notes: svn path=/vendor-sys/illumos/dist/; revision=348550
Diffstat (limited to 'uts')
-rw-r--r--uts/common/fs/zfs/zvol.c82
1 files changed, 53 insertions, 29 deletions
diff --git a/uts/common/fs/zfs/zvol.c b/uts/common/fs/zfs/zvol.c
index 9f8700cba865..e44423dee78a 100644
--- a/uts/common/fs/zfs/zvol.c
+++ b/uts/common/fs/zfs/zvol.c
@@ -23,7 +23,7 @@
*
* Portions Copyright 2010 Robert Milkowski
*
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2012, 2017 by Delphix. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
@@ -89,6 +89,7 @@
#include <sys/zfeature.h>
#include <sys/zio_checksum.h>
#include <sys/zil_impl.h>
+#include <sys/dkioc_free_util.h>
#include "zfs_namecheck.h"
@@ -1778,43 +1779,63 @@ zvol_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp)
case DKIOCFREE:
{
- dkioc_free_t df;
+ dkioc_free_list_t *dfl;
dmu_tx_t *tx;
if (!zvol_unmap_enabled)
break;
- if (ddi_copyin((void *)arg, &df, sizeof (df), flag)) {
- error = SET_ERROR(EFAULT);
- break;
+ if (!(flag & FKIOCTL)) {
+ error = dfl_copyin((void *)arg, &dfl, flag, KM_SLEEP);
+ if (error != 0)
+ break;
+ } else {
+ dfl = (dkioc_free_list_t *)arg;
+ ASSERT3U(dfl->dfl_num_exts, <=, DFL_COPYIN_MAX_EXTS);
+ if (dfl->dfl_num_exts > DFL_COPYIN_MAX_EXTS) {
+ error = SET_ERROR(EINVAL);
+ break;
+ }
}
- /*
- * Apply Postel's Law to length-checking. If they overshoot,
- * just blank out until the end, if there's a need to blank
- * out anything.
- */
- if (df.df_start >= zv->zv_volsize)
- break; /* No need to do anything... */
-
mutex_exit(&zfsdev_state_lock);
- rl = zfs_range_lock(&zv->zv_znode, df.df_start, df.df_length,
- RL_WRITER);
- tx = dmu_tx_create(zv->zv_objset);
- dmu_tx_mark_netfree(tx);
- error = dmu_tx_assign(tx, TXG_WAIT);
- if (error != 0) {
- dmu_tx_abort(tx);
- } else {
- zvol_log_truncate(zv, tx, df.df_start,
- df.df_length, B_TRUE);
- dmu_tx_commit(tx);
- error = dmu_free_long_range(zv->zv_objset, ZVOL_OBJ,
- df.df_start, df.df_length);
- }
+ for (int i = 0; i < dfl->dfl_num_exts; i++) {
+ uint64_t start = dfl->dfl_exts[i].dfle_start,
+ length = dfl->dfl_exts[i].dfle_length,
+ end = start + length;
+
+ /*
+ * Apply Postel's Law to length-checking. If they
+ * overshoot, just blank out until the end, if there's
+ * a need to blank out anything.
+ */
+ if (start >= zv->zv_volsize)
+ continue; /* No need to do anything... */
+ if (end > zv->zv_volsize) {
+ end = DMU_OBJECT_END;
+ length = end - start;
+ }
- zfs_range_unlock(rl);
+ rl = zfs_range_lock(&zv->zv_znode, start, length,
+ RL_WRITER);
+ tx = dmu_tx_create(zv->zv_objset);
+ error = dmu_tx_assign(tx, TXG_WAIT);
+ if (error != 0) {
+ dmu_tx_abort(tx);
+ } else {
+ zvol_log_truncate(zv, tx, start, length,
+ B_TRUE);
+ dmu_tx_commit(tx);
+ error = dmu_free_long_range(zv->zv_objset,
+ ZVOL_OBJ, start, length);
+ }
+
+ zfs_range_unlock(rl);
+
+ if (error != 0)
+ break;
+ }
/*
* If the write-cache is disabled, 'sync' property
@@ -1827,10 +1848,13 @@ zvol_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp)
if ((error == 0) && zvol_unmap_sync_enabled &&
(!(zv->zv_flags & ZVOL_WCE) ||
(zv->zv_objset->os_sync == ZFS_SYNC_ALWAYS) ||
- (df.df_flags & DF_WAIT_SYNC))) {
+ (dfl->dfl_flags & DF_WAIT_SYNC))) {
zil_commit(zv->zv_zilog, ZVOL_OBJ);
}
+ if (!(flag & FKIOCTL))
+ dfl_free(dfl);
+
return (error);
}