Print this page
4347 ZPL can use dmu_tx_assign(TXG_WAIT)
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Adam Leventhal <ahl@delphix.com>
*** 109,123 ****
* If you must call VN_RELE() within a tx then use VN_RELE_ASYNC().
*
* (3) All range locks must be grabbed before calling dmu_tx_assign(),
* as they can span dmu_tx_assign() calls.
*
! * (4) Always pass TXG_NOWAIT as the second argument to dmu_tx_assign().
! * This is critical because we don't want to block while holding locks.
* Note, in particular, that if a lock is sometimes acquired before
! * the tx assigns, and sometimes after (e.g. z_lock), then failing to
! * use a non-blocking assign can deadlock the system. The scenario:
*
* Thread A has grabbed a lock before calling dmu_tx_assign().
* Thread B is in an already-assigned tx, and blocks for this lock.
* Thread A calls dmu_tx_assign(TXG_WAIT) and blocks in txg_wait_open()
* forever, because the previous txg can't quiesce until B's tx commits.
--- 109,130 ----
* If you must call VN_RELE() within a tx then use VN_RELE_ASYNC().
*
* (3) All range locks must be grabbed before calling dmu_tx_assign(),
* as they can span dmu_tx_assign() calls.
*
! * (4) If ZPL locks are held, pass TXG_NOWAIT as the second argument to
! * dmu_tx_assign(). This is critical because we don't want to block
! * while holding locks.
! *
! * If no ZPL locks are held (aside from ZFS_ENTER()), use TXG_WAIT. This
! * reduces lock contention and CPU usage when we must wait (note that if
! * throughput is constrained by the storage, nearly every transaction
! * must wait).
! *
* Note, in particular, that if a lock is sometimes acquired before
! * the tx assigns, and sometimes after (e.g. z_lock), then failing
! * to use a non-blocking assign can deadlock the system. The scenario:
*
* Thread A has grabbed a lock before calling dmu_tx_assign().
* Thread B is in an already-assigned tx, and blocks for this lock.
* Thread A calls dmu_tx_assign(TXG_WAIT) and blocks in txg_wait_open()
* forever, because the previous txg can't quiesce until B's tx commits.
*** 726,736 ****
* and allows us to do more fine-grained space accounting.
*/
while (n > 0) {
abuf = NULL;
woff = uio->uio_loffset;
- again:
if (zfs_owner_overquota(zfsvfs, zp, B_FALSE) ||
zfs_owner_overquota(zfsvfs, zp, B_TRUE)) {
if (abuf != NULL)
dmu_return_arcbuf(abuf);
error = SET_ERROR(EDQUOT);
--- 733,742 ----
*** 778,795 ****
*/
tx = dmu_tx_create(zfsvfs->z_os);
dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE);
dmu_tx_hold_write(tx, zp->z_id, woff, MIN(n, max_blksz));
zfs_sa_upgrade_txholds(tx, zp);
! error = dmu_tx_assign(tx, TXG_NOWAIT);
if (error) {
- if (error == ERESTART) {
- dmu_tx_wait(tx);
dmu_tx_abort(tx);
- goto again;
- }
- dmu_tx_abort(tx);
if (abuf != NULL)
dmu_return_arcbuf(abuf);
break;
}
--- 784,796 ----
*/
tx = dmu_tx_create(zfsvfs->z_os);
dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE);
dmu_tx_hold_write(tx, zp->z_id, woff, MIN(n, max_blksz));
zfs_sa_upgrade_txholds(tx, zp);
! error = dmu_tx_assign(tx, TXG_WAIT);
if (error) {
dmu_tx_abort(tx);
if (abuf != NULL)
dmu_return_arcbuf(abuf);
break;
}
*** 3041,3056 ****
if (fuid_dirtied)
zfs_fuid_txhold(zfsvfs, tx);
zfs_sa_upgrade_txholds(tx, zp);
! err = dmu_tx_assign(tx, TXG_NOWAIT);
! if (err) {
! if (err == ERESTART)
! dmu_tx_wait(tx);
goto out;
- }
count = 0;
/*
* Set each attribute requested.
* We group settings according to the locks they need to acquire.
--- 3042,3054 ----
if (fuid_dirtied)
zfs_fuid_txhold(zfsvfs, tx);
zfs_sa_upgrade_txholds(tx, zp);
! err = dmu_tx_assign(tx, TXG_WAIT);
! if (err)
goto out;
count = 0;
/*
* Set each attribute requested.
* We group settings according to the locks they need to acquire.
*** 4138,4161 ****
if (zfs_owner_overquota(zfsvfs, zp, B_FALSE) ||
zfs_owner_overquota(zfsvfs, zp, B_TRUE)) {
err = SET_ERROR(EDQUOT);
goto out;
}
- top:
tx = dmu_tx_create(zfsvfs->z_os);
dmu_tx_hold_write(tx, zp->z_id, off, len);
dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE);
zfs_sa_upgrade_txholds(tx, zp);
! err = dmu_tx_assign(tx, TXG_NOWAIT);
if (err != 0) {
- if (err == ERESTART) {
- dmu_tx_wait(tx);
dmu_tx_abort(tx);
- goto top;
- }
- dmu_tx_abort(tx);
goto out;
}
if (zp->z_blksz <= PAGESIZE) {
caddr_t va = zfs_map_page(pp, S_READ);
--- 4136,4153 ----
if (zfs_owner_overquota(zfsvfs, zp, B_FALSE) ||
zfs_owner_overquota(zfsvfs, zp, B_TRUE)) {
err = SET_ERROR(EDQUOT);
goto out;
}
tx = dmu_tx_create(zfsvfs->z_os);
dmu_tx_hold_write(tx, zp->z_id, off, len);
dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE);
zfs_sa_upgrade_txholds(tx, zp);
! err = dmu_tx_assign(tx, TXG_WAIT);
if (err != 0) {
dmu_tx_abort(tx);
goto out;
}
if (zp->z_blksz <= PAGESIZE) {
caddr_t va = zfs_map_page(pp, S_READ);