MFV r348550: 1700 Add SCSI UNMAP support

illumos/illumos-gate@047c81d31d

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>

This is irrelevant to FreeBSD, just a diff reduction.
This commit is contained in:
Alexander Motin 2019-06-03 17:43:32 +00:00
commit bd2ae688a4
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=348562

View File

@ -26,7 +26,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]
@ -2259,43 +2259,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;
zfs_range_unlock(rl);
/*
* 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;
}
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
@ -2308,10 +2328,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);
}