Merge branch 'xfs-4.8-misc-fixes-4' into for-next
[cascardo/linux.git] / fs / xfs / xfs_buf_item.c
index 4561b1e..e455f90 100644 (file)
@@ -359,7 +359,7 @@ xfs_buf_item_format(
        for (i = 0; i < bip->bli_format_count; i++) {
                xfs_buf_item_format_segment(bip, lv, &vecp, offset,
                                            &bip->bli_formats[i]);
-               offset += bp->b_maps[i].bm_len;
+               offset += BBTOB(bp->b_maps[i].bm_len);
        }
 
        /*
@@ -915,20 +915,28 @@ xfs_buf_item_log(
        for (i = 0; i < bip->bli_format_count; i++) {
                if (start > last)
                        break;
-               end = start + BBTOB(bp->b_maps[i].bm_len);
+               end = start + BBTOB(bp->b_maps[i].bm_len) - 1;
+
+               /* skip to the map that includes the first byte to log */
                if (first > end) {
                        start += BBTOB(bp->b_maps[i].bm_len);
                        continue;
                }
+
+               /*
+                * Trim the range to this segment and mark it in the bitmap.
+                * Note that we must convert buffer offsets to segment relative
+                * offsets (e.g., the first byte of each segment is byte 0 of
+                * that segment).
+                */
                if (first < start)
                        first = start;
                if (end > last)
                        end = last;
-
-               xfs_buf_item_log_segment(first, end,
+               xfs_buf_item_log_segment(first - start, end - start,
                                         &bip->bli_formats[i].blf_data_map[0]);
 
-               start += bp->b_maps[i].bm_len;
+               start += BBTOB(bp->b_maps[i].bm_len);
        }
 }
 
@@ -1074,6 +1082,8 @@ xfs_buf_iodone_callback_error(
        trace_xfs_buf_item_iodone_async(bp, _RET_IP_);
        ASSERT(bp->b_iodone != NULL);
 
+       cfg = xfs_error_get_cfg(mp, XFS_ERR_METADATA, bp->b_error);
+
        /*
         * If the write was asynchronous then no one will be looking for the
         * error.  If this is the first failure of this type, clear the error
@@ -1081,13 +1091,12 @@ xfs_buf_iodone_callback_error(
         * async write failure at least once, but we also need to set the buffer
         * up to behave correctly now for repeated failures.
         */
-       if (!(bp->b_flags & (XBF_STALE|XBF_WRITE_FAIL)) ||
+       if (!(bp->b_flags & (XBF_STALE | XBF_WRITE_FAIL)) ||
             bp->b_last_error != bp->b_error) {
-               bp->b_flags |= (XBF_WRITE | XBF_ASYNC |
-                               XBF_DONE | XBF_WRITE_FAIL);
+               bp->b_flags |= (XBF_WRITE | XBF_DONE | XBF_WRITE_FAIL);
                bp->b_last_error = bp->b_error;
-               bp->b_retries = 0;
-               bp->b_first_retry_time = jiffies;
+               if (cfg->retry_timeout && !bp->b_first_retry_time)
+                       bp->b_first_retry_time = jiffies;
 
                xfs_buf_ioerror(bp, 0);
                xfs_buf_submit(bp);
@@ -1098,7 +1107,6 @@ xfs_buf_iodone_callback_error(
         * Repeated failure on an async write. Take action according to the
         * error configuration we have been set up to use.
         */
-       cfg = xfs_error_get_cfg(mp, XFS_ERR_METADATA, bp->b_error);
 
        if (cfg->max_retries != XFS_ERR_RETRY_FOREVER &&
            ++bp->b_retries > cfg->max_retries)