+ * Encapsulate the entire change (including truncating the link) in
+ * nested transactions if we are modifying a symlink, because we know that its
+ * file length will be at most 4k, and we can fit both the truncation and
+ * any relevant bitmap changes into a single journal transaction. We also want
+ * the kill_block code to execute in the same transaction so that any dirty symlink
+ * blocks will not be written. Otherwise, rely on
+ * hfs_truncate doing its own transactions to ensure that we don't blow up
+ * the journal.
+ */
+ if ((started_tr == 0) && (v_type == VLNK)) {
+ if (hfs_start_transaction(hfsmp) != 0) {
+ error = EINVAL;
+ goto out;
+ }
+ else {
+ started_tr = 1;
+ }
+ }
+
+ /*
+ * At this point, we have decided that this cnode is
+ * suitable for full removal. We are about to deallocate
+ * its blocks and remove its entry from the catalog.
+ * If it was a symlink, then it's possible that the operation
+ * which created it is still in the current transaction group
+ * due to coalescing. Take action here to kill the data blocks
+ * of the symlink out of the journal before moving to
+ * deallocate the blocks. We need to be in the middle of
+ * a transaction before calling buf_iterate like this.
+ *
+ * Note: we have to kill any potential symlink buffers out of
+ * the journal prior to deallocating their blocks. This is so
+ * that we don't race with another thread that may be doing an
+ * an allocation concurrently and pick up these blocks. It could
+ * generate I/O against them which could go out ahead of our journal
+ * transaction.
+ */
+
+ if (hfsmp->jnl && vnode_islnk(vp)) {
+ buf_iterate(vp, hfs_removefile_callback, BUF_SKIP_NONLOCKED, (void *)hfsmp);
+ }
+
+ /*