| 532 | long zfs_immediate_write_sz = 32768; |
| 533 | |
| 534 | void |
| 535 | zfs_log_write(zilog_t *zilog, dmu_tx_t *tx, int txtype, |
| 536 | znode_t *zp, offset_t off, ssize_t resid, int ioflag, |
| 537 | zil_callback_t callback, void *callback_data) |
| 538 | { |
| 539 | dmu_buf_impl_t *db = (dmu_buf_impl_t *)sa_get_db(zp->z_sa_hdl); |
| 540 | uint32_t blocksize = zp->z_blksz; |
| 541 | itx_wr_state_t write_state; |
| 542 | uintptr_t fsync_cnt; |
| 543 | |
| 544 | if (zil_replaying(zilog, tx) || zp->z_unlinked || |
| 545 | zfs_xattr_owner_unlinked(zp)) { |
| 546 | if (callback != NULL) |
| 547 | callback(callback_data); |
| 548 | return; |
| 549 | } |
| 550 | |
| 551 | if (zilog->zl_logbias == ZFS_LOGBIAS_THROUGHPUT) |
| 552 | write_state = WR_INDIRECT; |
| 553 | else if (!spa_has_slogs(zilog->zl_spa) && |
| 554 | resid >= zfs_immediate_write_sz) |
| 555 | write_state = WR_INDIRECT; |
| 556 | else if (ioflag & (O_SYNC | O_DSYNC)) |
| 557 | write_state = WR_COPIED; |
| 558 | else |
| 559 | write_state = WR_NEED_COPY; |
| 560 | |
| 561 | if ((fsync_cnt = (uintptr_t)tsd_get(zfs_fsyncer_key)) != 0) { |
| 562 | (void) tsd_set(zfs_fsyncer_key, (void *)(fsync_cnt - 1)); |
| 563 | } |
| 564 | |
| 565 | while (resid) { |
| 566 | itx_t *itx; |
| 567 | lr_write_t *lr; |
| 568 | itx_wr_state_t wr_state = write_state; |
| 569 | ssize_t len = resid; |
| 570 | |
| 571 | /* |
| 572 | * A WR_COPIED record must fit entirely in one log block. |
| 573 | * Large writes can use WR_NEED_COPY, which the ZIL will |
| 574 | * split into multiple records across several log blocks |
| 575 | * if necessary. |
| 576 | */ |
| 577 | if (wr_state == WR_COPIED && |
| 578 | resid > zil_max_copied_data(zilog)) |
| 579 | wr_state = WR_NEED_COPY; |
| 580 | else if (wr_state == WR_INDIRECT) |
| 581 | len = MIN(blocksize - P2PHASE(off, blocksize), resid); |
| 582 | |
| 583 | itx = zil_itx_create(txtype, sizeof (*lr) + |
| 584 | (wr_state == WR_COPIED ? len : 0)); |
| 585 | lr = (lr_write_t *)&itx->itx_lr; |
| 586 | |
| 587 | /* |
| 588 | * For WR_COPIED records, copy the data into the lr_write_t. |
| 589 | */ |
| 590 | if (wr_state == WR_COPIED) { |
| 591 | int err; |
no test coverage detected