diff options
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_buf.c | 21 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_buf.h | 1 | ||||
-rw-r--r-- | fs/xfs/xfs_log.c | 8 | ||||
-rw-r--r-- | fs/xfs/xfs_log_recover.c | 75 |
4 files changed, 67 insertions, 38 deletions
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index 098890357659..52b2b5da566e 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c | |||
@@ -708,6 +708,27 @@ xfs_buf_get_empty( | |||
708 | return bp; | 708 | return bp; |
709 | } | 709 | } |
710 | 710 | ||
711 | /* | ||
712 | * Return a buffer allocated as an empty buffer and associated to external | ||
713 | * memory via xfs_buf_associate_memory() back to it's empty state. | ||
714 | */ | ||
715 | void | ||
716 | xfs_buf_set_empty( | ||
717 | struct xfs_buf *bp, | ||
718 | size_t len) | ||
719 | { | ||
720 | if (bp->b_pages) | ||
721 | _xfs_buf_free_pages(bp); | ||
722 | |||
723 | bp->b_pages = NULL; | ||
724 | bp->b_page_count = 0; | ||
725 | bp->b_addr = NULL; | ||
726 | bp->b_file_offset = 0; | ||
727 | bp->b_buffer_length = bp->b_count_desired = len; | ||
728 | bp->b_bn = XFS_BUF_DADDR_NULL; | ||
729 | bp->b_flags &= ~XBF_MAPPED; | ||
730 | } | ||
731 | |||
711 | static inline struct page * | 732 | static inline struct page * |
712 | mem_to_page( | 733 | mem_to_page( |
713 | void *addr) | 734 | void *addr) |
diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h index a9a1c4512645..50a7d5fb3b73 100644 --- a/fs/xfs/linux-2.6/xfs_buf.h +++ b/fs/xfs/linux-2.6/xfs_buf.h | |||
@@ -178,6 +178,7 @@ extern xfs_buf_t *xfs_buf_read(xfs_buftarg_t *, xfs_off_t, size_t, | |||
178 | xfs_buf_flags_t); | 178 | xfs_buf_flags_t); |
179 | 179 | ||
180 | extern xfs_buf_t *xfs_buf_get_empty(size_t, xfs_buftarg_t *); | 180 | extern xfs_buf_t *xfs_buf_get_empty(size_t, xfs_buftarg_t *); |
181 | extern void xfs_buf_set_empty(struct xfs_buf *bp, size_t len); | ||
181 | extern xfs_buf_t *xfs_buf_get_uncached(struct xfs_buftarg *, size_t, int); | 182 | extern xfs_buf_t *xfs_buf_get_uncached(struct xfs_buftarg *, size_t, int); |
182 | extern int xfs_buf_associate_memory(xfs_buf_t *, void *, size_t); | 183 | extern int xfs_buf_associate_memory(xfs_buf_t *, void *, size_t); |
183 | extern void xfs_buf_hold(xfs_buf_t *); | 184 | extern void xfs_buf_hold(xfs_buf_t *); |
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 18fd4beffcc3..211930246f20 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c | |||
@@ -1449,6 +1449,13 @@ xlog_dealloc_log(xlog_t *log) | |||
1449 | 1449 | ||
1450 | xlog_cil_destroy(log); | 1450 | xlog_cil_destroy(log); |
1451 | 1451 | ||
1452 | /* | ||
1453 | * always need to ensure that the extra buffer does not point to memory | ||
1454 | * owned by another log buffer before we free it. | ||
1455 | */ | ||
1456 | xfs_buf_set_empty(log->l_xbuf, log->l_iclog_size); | ||
1457 | xfs_buf_free(log->l_xbuf); | ||
1458 | |||
1452 | iclog = log->l_iclog; | 1459 | iclog = log->l_iclog; |
1453 | for (i=0; i<log->l_iclog_bufs; i++) { | 1460 | for (i=0; i<log->l_iclog_bufs; i++) { |
1454 | xfs_buf_free(iclog->ic_bp); | 1461 | xfs_buf_free(iclog->ic_bp); |
@@ -1458,7 +1465,6 @@ xlog_dealloc_log(xlog_t *log) | |||
1458 | } | 1465 | } |
1459 | spinlock_destroy(&log->l_icloglock); | 1466 | spinlock_destroy(&log->l_icloglock); |
1460 | 1467 | ||
1461 | xfs_buf_free(log->l_xbuf); | ||
1462 | log->l_mp->m_log = NULL; | 1468 | log->l_mp->m_log = NULL; |
1463 | kmem_free(log); | 1469 | kmem_free(log); |
1464 | } /* xlog_dealloc_log */ | 1470 | } /* xlog_dealloc_log */ |
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 5cc464a17c93..04142caedb2b 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
@@ -205,6 +205,35 @@ xlog_bread( | |||
205 | } | 205 | } |
206 | 206 | ||
207 | /* | 207 | /* |
208 | * Read at an offset into the buffer. Returns with the buffer in it's original | ||
209 | * state regardless of the result of the read. | ||
210 | */ | ||
211 | STATIC int | ||
212 | xlog_bread_offset( | ||
213 | xlog_t *log, | ||
214 | xfs_daddr_t blk_no, /* block to read from */ | ||
215 | int nbblks, /* blocks to read */ | ||
216 | xfs_buf_t *bp, | ||
217 | xfs_caddr_t offset) | ||
218 | { | ||
219 | xfs_caddr_t orig_offset = XFS_BUF_PTR(bp); | ||
220 | int orig_len = bp->b_buffer_length; | ||
221 | int error, error2; | ||
222 | |||
223 | error = XFS_BUF_SET_PTR(bp, offset, BBTOB(nbblks)); | ||
224 | if (error) | ||
225 | return error; | ||
226 | |||
227 | error = xlog_bread_noalign(log, blk_no, nbblks, bp); | ||
228 | |||
229 | /* must reset buffer pointer even on error */ | ||
230 | error2 = XFS_BUF_SET_PTR(bp, orig_offset, orig_len); | ||
231 | if (error) | ||
232 | return error; | ||
233 | return error2; | ||
234 | } | ||
235 | |||
236 | /* | ||
208 | * Write out the buffer at the given block for the given number of blocks. | 237 | * Write out the buffer at the given block for the given number of blocks. |
209 | * The buffer is kept locked across the write and is returned locked. | 238 | * The buffer is kept locked across the write and is returned locked. |
210 | * This can only be used for synchronous log writes. | 239 | * This can only be used for synchronous log writes. |
@@ -1229,20 +1258,12 @@ xlog_write_log_records( | |||
1229 | */ | 1258 | */ |
1230 | ealign = round_down(end_block, sectbb); | 1259 | ealign = round_down(end_block, sectbb); |
1231 | if (j == 0 && (start_block + endcount > ealign)) { | 1260 | if (j == 0 && (start_block + endcount > ealign)) { |
1232 | offset = XFS_BUF_PTR(bp); | 1261 | offset = XFS_BUF_PTR(bp) + BBTOB(ealign - start_block); |
1233 | balign = BBTOB(ealign - start_block); | 1262 | error = xlog_bread_offset(log, ealign, sectbb, |
1234 | error = XFS_BUF_SET_PTR(bp, offset + balign, | 1263 | bp, offset); |
1235 | BBTOB(sectbb)); | ||
1236 | if (error) | 1264 | if (error) |
1237 | break; | 1265 | break; |
1238 | 1266 | ||
1239 | error = xlog_bread_noalign(log, ealign, sectbb, bp); | ||
1240 | if (error) | ||
1241 | break; | ||
1242 | |||
1243 | error = XFS_BUF_SET_PTR(bp, offset, bufblks); | ||
1244 | if (error) | ||
1245 | break; | ||
1246 | } | 1267 | } |
1247 | 1268 | ||
1248 | offset = xlog_align(log, start_block, endcount, bp); | 1269 | offset = xlog_align(log, start_block, endcount, bp); |
@@ -3448,19 +3469,9 @@ xlog_do_recovery_pass( | |||
3448 | * - order is important. | 3469 | * - order is important. |
3449 | */ | 3470 | */ |
3450 | wrapped_hblks = hblks - split_hblks; | 3471 | wrapped_hblks = hblks - split_hblks; |
3451 | error = XFS_BUF_SET_PTR(hbp, | 3472 | error = xlog_bread_offset(log, 0, |
3452 | offset + BBTOB(split_hblks), | 3473 | wrapped_hblks, hbp, |
3453 | BBTOB(hblks - split_hblks)); | 3474 | offset + BBTOB(split_hblks)); |
3454 | if (error) | ||
3455 | goto bread_err2; | ||
3456 | |||
3457 | error = xlog_bread_noalign(log, 0, | ||
3458 | wrapped_hblks, hbp); | ||
3459 | if (error) | ||
3460 | goto bread_err2; | ||
3461 | |||
3462 | error = XFS_BUF_SET_PTR(hbp, offset, | ||
3463 | BBTOB(hblks)); | ||
3464 | if (error) | 3475 | if (error) |
3465 | goto bread_err2; | 3476 | goto bread_err2; |
3466 | } | 3477 | } |
@@ -3511,19 +3522,9 @@ xlog_do_recovery_pass( | |||
3511 | * _first_, then the log start (LR header end) | 3522 | * _first_, then the log start (LR header end) |
3512 | * - order is important. | 3523 | * - order is important. |
3513 | */ | 3524 | */ |
3514 | error = XFS_BUF_SET_PTR(dbp, | 3525 | error = xlog_bread_offset(log, 0, |
3515 | offset + BBTOB(split_bblks), | 3526 | bblks - split_bblks, hbp, |
3516 | BBTOB(bblks - split_bblks)); | 3527 | offset + BBTOB(split_bblks)); |
3517 | if (error) | ||
3518 | goto bread_err2; | ||
3519 | |||
3520 | error = xlog_bread_noalign(log, wrapped_hblks, | ||
3521 | bblks - split_bblks, | ||
3522 | dbp); | ||
3523 | if (error) | ||
3524 | goto bread_err2; | ||
3525 | |||
3526 | error = XFS_BUF_SET_PTR(dbp, offset, h_size); | ||
3527 | if (error) | 3528 | if (error) |
3528 | goto bread_err2; | 3529 | goto bread_err2; |
3529 | } | 3530 | } |