diff options
author | Alexander Motin <mav@FreeBSD.org> | 2019-06-03 17:01:16 +0000 |
---|---|---|
committer | Alexander Motin <mav@FreeBSD.org> | 2019-06-03 17:01:16 +0000 |
commit | 86a6a20c48b548859f3498d8e18c64c64a733152 (patch) | |
tree | 3d16ef0e6413f8a1c64a5d475743469bce5ef27e /uts | |
parent | 380d790f2b00f30813940e0535cd6b83e8cc7d96 (diff) | |
download | src-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.c | 82 |
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); } |