return 0;
 }
 
+/*
+ * Read at an offset into the buffer. Returns with the buffer in it's original
+ * state regardless of the result of the read.
+ */
+STATIC int
+xlog_bread_offset(
+       xlog_t          *log,
+       xfs_daddr_t     blk_no,         /* block to read from */
+       int             nbblks,         /* blocks to read */
+       xfs_buf_t       *bp,
+       xfs_caddr_t     offset)
+{
+       xfs_caddr_t     orig_offset = XFS_BUF_PTR(bp);
+       int             orig_len = bp->b_buffer_length;
+       int             error, error2;
+
+       error = XFS_BUF_SET_PTR(bp, offset, BBTOB(nbblks));
+       if (error)
+               return error;
+
+       error = xlog_bread_noalign(log, blk_no, nbblks, bp);
+
+       /* must reset buffer pointer even on error */
+       error2 = XFS_BUF_SET_PTR(bp, orig_offset, orig_len);
+       if (error)
+               return error;
+       return error2;
+}
+
 /*
  * Write out the buffer at the given block for the given number of blocks.
  * The buffer is kept locked across the write and is returned locked.
                 */
                ealign = round_down(end_block, sectbb);
                if (j == 0 && (start_block + endcount > ealign)) {
-                       offset = XFS_BUF_PTR(bp);
-                       balign = BBTOB(ealign - start_block);
-                       error = XFS_BUF_SET_PTR(bp, offset + balign,
-                                               BBTOB(sectbb));
+                       offset = XFS_BUF_PTR(bp) + BBTOB(ealign - start_block);
+                       error = xlog_bread_offset(log, ealign, sectbb,
+                                                       bp, offset);
                        if (error)
                                break;
 
-                       error = xlog_bread_noalign(log, ealign, sectbb, bp);
-                       if (error)
-                               break;
-
-                       error = XFS_BUF_SET_PTR(bp, offset, bufblks);
-                       if (error)
-                               break;
                }
 
                offset = xlog_align(log, start_block, endcount, bp);
                                 *   - order is important.
                                 */
                                wrapped_hblks = hblks - split_hblks;
-                               error = XFS_BUF_SET_PTR(hbp,
-                                               offset + BBTOB(split_hblks),
-                                               BBTOB(hblks - split_hblks));
-                               if (error)
-                                       goto bread_err2;
-
-                               error = xlog_bread_noalign(log, 0,
-                                                          wrapped_hblks, hbp);
-                               if (error)
-                                       goto bread_err2;
-
-                               error = XFS_BUF_SET_PTR(hbp, offset,
-                                                       BBTOB(hblks));
+                               error = xlog_bread_offset(log, 0,
+                                               wrapped_hblks, hbp,
+                                               offset + BBTOB(split_hblks));
                                if (error)
                                        goto bread_err2;
                        }
                                 *   _first_, then the log start (LR header end)
                                 *   - order is important.
                                 */
-                               error = XFS_BUF_SET_PTR(dbp,
-                                               offset + BBTOB(split_bblks),
-                                               BBTOB(bblks - split_bblks));
-                               if (error)
-                                       goto bread_err2;
-
-                               error = xlog_bread_noalign(log, wrapped_hblks,
-                                               bblks - split_bblks,
-                                               dbp);
-                               if (error)
-                                       goto bread_err2;
-
-                               error = XFS_BUF_SET_PTR(dbp, offset, h_size);
+                               error = xlog_bread_offset(log, 0,
+                                               bblks - split_bblks, hbp,
+                                               offset + BBTOB(split_bblks));
                                if (error)
                                        goto bread_err2;
                        }