| .. | .. |
|---|
| 10 | 10 | #include "xfs_log_format.h" |
|---|
| 11 | 11 | #include "xfs_trans_resv.h" |
|---|
| 12 | 12 | #include "xfs_mount.h" |
|---|
| 13 | | -#include "xfs_inode.h" |
|---|
| 14 | 13 | #include "xfs_trans.h" |
|---|
| 15 | 14 | #include "xfs_buf_item.h" |
|---|
| 16 | 15 | #include "xfs_trans_priv.h" |
|---|
| 17 | | -#include "xfs_error.h" |
|---|
| 18 | 16 | #include "xfs_trace.h" |
|---|
| 19 | 17 | |
|---|
| 20 | 18 | /* |
|---|
| .. | .. |
|---|
| 114 | 112 | * If the transaction pointer is NULL, make this just a normal |
|---|
| 115 | 113 | * get_buf() call. |
|---|
| 116 | 114 | */ |
|---|
| 117 | | -struct xfs_buf * |
|---|
| 115 | +int |
|---|
| 118 | 116 | xfs_trans_get_buf_map( |
|---|
| 119 | 117 | struct xfs_trans *tp, |
|---|
| 120 | 118 | struct xfs_buftarg *target, |
|---|
| 121 | 119 | struct xfs_buf_map *map, |
|---|
| 122 | 120 | int nmaps, |
|---|
| 123 | | - xfs_buf_flags_t flags) |
|---|
| 121 | + xfs_buf_flags_t flags, |
|---|
| 122 | + struct xfs_buf **bpp) |
|---|
| 124 | 123 | { |
|---|
| 125 | 124 | xfs_buf_t *bp; |
|---|
| 126 | 125 | struct xfs_buf_log_item *bip; |
|---|
| 126 | + int error; |
|---|
| 127 | 127 | |
|---|
| 128 | + *bpp = NULL; |
|---|
| 128 | 129 | if (!tp) |
|---|
| 129 | | - return xfs_buf_get_map(target, map, nmaps, flags); |
|---|
| 130 | + return xfs_buf_get_map(target, map, nmaps, flags, bpp); |
|---|
| 130 | 131 | |
|---|
| 131 | 132 | /* |
|---|
| 132 | 133 | * If we find the buffer in the cache with this transaction |
|---|
| .. | .. |
|---|
| 148 | 149 | ASSERT(atomic_read(&bip->bli_refcount) > 0); |
|---|
| 149 | 150 | bip->bli_recur++; |
|---|
| 150 | 151 | trace_xfs_trans_get_buf_recur(bip); |
|---|
| 151 | | - return bp; |
|---|
| 152 | + *bpp = bp; |
|---|
| 153 | + return 0; |
|---|
| 152 | 154 | } |
|---|
| 153 | 155 | |
|---|
| 154 | | - bp = xfs_buf_get_map(target, map, nmaps, flags); |
|---|
| 155 | | - if (bp == NULL) { |
|---|
| 156 | | - return NULL; |
|---|
| 157 | | - } |
|---|
| 156 | + error = xfs_buf_get_map(target, map, nmaps, flags, &bp); |
|---|
| 157 | + if (error) |
|---|
| 158 | + return error; |
|---|
| 158 | 159 | |
|---|
| 159 | 160 | ASSERT(!bp->b_error); |
|---|
| 160 | 161 | |
|---|
| 161 | 162 | _xfs_trans_bjoin(tp, bp, 1); |
|---|
| 162 | 163 | trace_xfs_trans_get_buf(bp->b_log_item); |
|---|
| 163 | | - return bp; |
|---|
| 164 | + *bpp = bp; |
|---|
| 165 | + return 0; |
|---|
| 164 | 166 | } |
|---|
| 165 | 167 | |
|---|
| 166 | 168 | /* |
|---|
| 167 | | - * Get and lock the superblock buffer of this file system for the |
|---|
| 168 | | - * given transaction. |
|---|
| 169 | | - * |
|---|
| 170 | | - * We don't need to use incore_match() here, because the superblock |
|---|
| 171 | | - * buffer is a private buffer which we keep a pointer to in the |
|---|
| 172 | | - * mount structure. |
|---|
| 169 | + * Get and lock the superblock buffer for the given transaction. |
|---|
| 173 | 170 | */ |
|---|
| 174 | | -xfs_buf_t * |
|---|
| 171 | +struct xfs_buf * |
|---|
| 175 | 172 | xfs_trans_getsb( |
|---|
| 176 | | - xfs_trans_t *tp, |
|---|
| 177 | | - struct xfs_mount *mp, |
|---|
| 178 | | - int flags) |
|---|
| 173 | + struct xfs_trans *tp) |
|---|
| 179 | 174 | { |
|---|
| 180 | | - xfs_buf_t *bp; |
|---|
| 181 | | - struct xfs_buf_log_item *bip; |
|---|
| 175 | + struct xfs_buf *bp = tp->t_mountp->m_sb_bp; |
|---|
| 182 | 176 | |
|---|
| 183 | 177 | /* |
|---|
| 184 | | - * Default to just trying to lock the superblock buffer |
|---|
| 185 | | - * if tp is NULL. |
|---|
| 178 | + * Just increment the lock recursion count if the buffer is already |
|---|
| 179 | + * attached to this transaction. |
|---|
| 186 | 180 | */ |
|---|
| 187 | | - if (tp == NULL) |
|---|
| 188 | | - return xfs_getsb(mp, flags); |
|---|
| 189 | | - |
|---|
| 190 | | - /* |
|---|
| 191 | | - * If the superblock buffer already has this transaction |
|---|
| 192 | | - * pointer in its b_fsprivate2 field, then we know we already |
|---|
| 193 | | - * have it locked. In this case we just increment the lock |
|---|
| 194 | | - * recursion count and return the buffer to the caller. |
|---|
| 195 | | - */ |
|---|
| 196 | | - bp = mp->m_sb_bp; |
|---|
| 197 | 181 | if (bp->b_transp == tp) { |
|---|
| 198 | | - bip = bp->b_log_item; |
|---|
| 182 | + struct xfs_buf_log_item *bip = bp->b_log_item; |
|---|
| 183 | + |
|---|
| 199 | 184 | ASSERT(bip != NULL); |
|---|
| 200 | 185 | ASSERT(atomic_read(&bip->bli_refcount) > 0); |
|---|
| 201 | 186 | bip->bli_recur++; |
|---|
| 187 | + |
|---|
| 202 | 188 | trace_xfs_trans_getsb_recur(bip); |
|---|
| 203 | | - return bp; |
|---|
| 189 | + } else { |
|---|
| 190 | + xfs_buf_lock(bp); |
|---|
| 191 | + xfs_buf_hold(bp); |
|---|
| 192 | + _xfs_trans_bjoin(tp, bp, 1); |
|---|
| 193 | + |
|---|
| 194 | + trace_xfs_trans_getsb(bp->b_log_item); |
|---|
| 204 | 195 | } |
|---|
| 205 | 196 | |
|---|
| 206 | | - bp = xfs_getsb(mp, flags); |
|---|
| 207 | | - if (bp == NULL) |
|---|
| 208 | | - return NULL; |
|---|
| 209 | | - |
|---|
| 210 | | - _xfs_trans_bjoin(tp, bp, 1); |
|---|
| 211 | | - trace_xfs_trans_getsb(bp->b_log_item); |
|---|
| 212 | 197 | return bp; |
|---|
| 213 | 198 | } |
|---|
| 214 | 199 | |
|---|
| .. | .. |
|---|
| 264 | 249 | return -EIO; |
|---|
| 265 | 250 | } |
|---|
| 266 | 251 | |
|---|
| 252 | + /* |
|---|
| 253 | + * Check if the caller is trying to read a buffer that is |
|---|
| 254 | + * already attached to the transaction yet has no buffer ops |
|---|
| 255 | + * assigned. Ops are usually attached when the buffer is |
|---|
| 256 | + * attached to the transaction, or by the read caller if |
|---|
| 257 | + * special circumstances. That didn't happen, which is not |
|---|
| 258 | + * how this is supposed to go. |
|---|
| 259 | + * |
|---|
| 260 | + * If the buffer passes verification we'll let this go, but if |
|---|
| 261 | + * not we have to shut down. Let the transaction cleanup code |
|---|
| 262 | + * release this buffer when it kills the tranaction. |
|---|
| 263 | + */ |
|---|
| 264 | + ASSERT(bp->b_ops != NULL); |
|---|
| 265 | + error = xfs_buf_reverify(bp, ops); |
|---|
| 266 | + if (error) { |
|---|
| 267 | + xfs_buf_ioerror_alert(bp, __return_address); |
|---|
| 268 | + |
|---|
| 269 | + if (tp->t_flags & XFS_TRANS_DIRTY) |
|---|
| 270 | + xfs_force_shutdown(tp->t_mountp, |
|---|
| 271 | + SHUTDOWN_META_IO_ERROR); |
|---|
| 272 | + |
|---|
| 273 | + /* bad CRC means corrupted metadata */ |
|---|
| 274 | + if (error == -EFSBADCRC) |
|---|
| 275 | + error = -EFSCORRUPTED; |
|---|
| 276 | + return error; |
|---|
| 277 | + } |
|---|
| 278 | + |
|---|
| 267 | 279 | bip = bp->b_log_item; |
|---|
| 268 | 280 | bip->bli_recur++; |
|---|
| 269 | 281 | |
|---|
| 270 | 282 | ASSERT(atomic_read(&bip->bli_refcount) > 0); |
|---|
| 271 | 283 | trace_xfs_trans_read_buf_recur(bip); |
|---|
| 284 | + ASSERT(bp->b_ops != NULL || ops == NULL); |
|---|
| 272 | 285 | *bpp = bp; |
|---|
| 273 | 286 | return 0; |
|---|
| 274 | 287 | } |
|---|
| 275 | 288 | |
|---|
| 276 | | - bp = xfs_buf_read_map(target, map, nmaps, flags, ops); |
|---|
| 277 | | - if (!bp) { |
|---|
| 278 | | - if (!(flags & XBF_TRYLOCK)) |
|---|
| 279 | | - return -ENOMEM; |
|---|
| 280 | | - return tp ? 0 : -EAGAIN; |
|---|
| 281 | | - } |
|---|
| 282 | | - |
|---|
| 283 | | - /* |
|---|
| 284 | | - * If we've had a read error, then the contents of the buffer are |
|---|
| 285 | | - * invalid and should not be used. To ensure that a followup read tries |
|---|
| 286 | | - * to pull the buffer from disk again, we clear the XBF_DONE flag and |
|---|
| 287 | | - * mark the buffer stale. This ensures that anyone who has a current |
|---|
| 288 | | - * reference to the buffer will interpret it's contents correctly and |
|---|
| 289 | | - * future cache lookups will also treat it as an empty, uninitialised |
|---|
| 290 | | - * buffer. |
|---|
| 291 | | - */ |
|---|
| 292 | | - if (bp->b_error) { |
|---|
| 293 | | - error = bp->b_error; |
|---|
| 294 | | - if (!XFS_FORCED_SHUTDOWN(mp)) |
|---|
| 295 | | - xfs_buf_ioerror_alert(bp, __func__); |
|---|
| 296 | | - bp->b_flags &= ~XBF_DONE; |
|---|
| 297 | | - xfs_buf_stale(bp); |
|---|
| 298 | | - |
|---|
| 289 | + error = xfs_buf_read_map(target, map, nmaps, flags, &bp, ops, |
|---|
| 290 | + __return_address); |
|---|
| 291 | + switch (error) { |
|---|
| 292 | + case 0: |
|---|
| 293 | + break; |
|---|
| 294 | + default: |
|---|
| 299 | 295 | if (tp && (tp->t_flags & XFS_TRANS_DIRTY)) |
|---|
| 300 | 296 | xfs_force_shutdown(tp->t_mountp, SHUTDOWN_META_IO_ERROR); |
|---|
| 301 | | - xfs_buf_relse(bp); |
|---|
| 302 | | - |
|---|
| 303 | | - /* bad CRC means corrupted metadata */ |
|---|
| 304 | | - if (error == -EFSBADCRC) |
|---|
| 305 | | - error = -EFSCORRUPTED; |
|---|
| 297 | + /* fall through */ |
|---|
| 298 | + case -ENOMEM: |
|---|
| 299 | + case -EAGAIN: |
|---|
| 306 | 300 | return error; |
|---|
| 307 | 301 | } |
|---|
| 308 | 302 | |
|---|
| .. | .. |
|---|
| 316 | 310 | _xfs_trans_bjoin(tp, bp, 1); |
|---|
| 317 | 311 | trace_xfs_trans_read_buf(bp->b_log_item); |
|---|
| 318 | 312 | } |
|---|
| 313 | + ASSERT(bp->b_ops != NULL || ops == NULL); |
|---|
| 319 | 314 | *bpp = bp; |
|---|
| 320 | 315 | return 0; |
|---|
| 321 | 316 | |
|---|
| 317 | +} |
|---|
| 318 | + |
|---|
| 319 | +/* Has this buffer been dirtied by anyone? */ |
|---|
| 320 | +bool |
|---|
| 321 | +xfs_trans_buf_is_dirty( |
|---|
| 322 | + struct xfs_buf *bp) |
|---|
| 323 | +{ |
|---|
| 324 | + struct xfs_buf_log_item *bip = bp->b_log_item; |
|---|
| 325 | + |
|---|
| 326 | + if (!bip) |
|---|
| 327 | + return false; |
|---|
| 328 | + ASSERT(bip->bli_item.li_type == XFS_LI_BUF); |
|---|
| 329 | + return test_bit(XFS_LI_DIRTY, &bip->bli_item.li_flags); |
|---|
| 322 | 330 | } |
|---|
| 323 | 331 | |
|---|
| 324 | 332 | /* |
|---|
| .. | .. |
|---|
| 386 | 394 | |
|---|
| 387 | 395 | /* |
|---|
| 388 | 396 | * Mark the buffer as not needing to be unlocked when the buf item's |
|---|
| 389 | | - * iop_unlock() routine is called. The buffer must already be locked |
|---|
| 397 | + * iop_committing() routine is called. The buffer must already be locked |
|---|
| 390 | 398 | * and associated with the given transaction. |
|---|
| 391 | 399 | */ |
|---|
| 392 | 400 | /* ARGSUSED */ |
|---|
| .. | .. |
|---|
| 441 | 449 | |
|---|
| 442 | 450 | ASSERT(bp->b_transp == tp); |
|---|
| 443 | 451 | ASSERT(bip != NULL); |
|---|
| 444 | | - ASSERT(bp->b_iodone == NULL || |
|---|
| 445 | | - bp->b_iodone == xfs_buf_iodone_callbacks); |
|---|
| 446 | 452 | |
|---|
| 447 | 453 | /* |
|---|
| 448 | 454 | * Mark the buffer as needing to be written out eventually, |
|---|
| 449 | 455 | * and set its iodone function to remove the buffer's buf log |
|---|
| 450 | 456 | * item from the AIL and free it when the buffer is flushed |
|---|
| 451 | | - * to disk. See xfs_buf_attach_iodone() for more details |
|---|
| 452 | | - * on li_cb and xfs_buf_iodone_callbacks(). |
|---|
| 453 | | - * If we end up aborting this transaction, we trap this buffer |
|---|
| 454 | | - * inside the b_bdstrat callback so that this won't get written to |
|---|
| 455 | | - * disk. |
|---|
| 457 | + * to disk. |
|---|
| 456 | 458 | */ |
|---|
| 457 | 459 | bp->b_flags |= XBF_DONE; |
|---|
| 458 | 460 | |
|---|
| 459 | 461 | ASSERT(atomic_read(&bip->bli_refcount) > 0); |
|---|
| 460 | | - bp->b_iodone = xfs_buf_iodone_callbacks; |
|---|
| 461 | | - bip->bli_item.li_cb = xfs_buf_iodone; |
|---|
| 462 | 462 | |
|---|
| 463 | 463 | /* |
|---|
| 464 | 464 | * If we invalidated the buffer within this transaction, then |
|---|
| .. | .. |
|---|
| 602 | 602 | ASSERT(atomic_read(&bip->bli_refcount) > 0); |
|---|
| 603 | 603 | |
|---|
| 604 | 604 | bip->bli_flags |= XFS_BLI_INODE_BUF; |
|---|
| 605 | + bp->b_flags |= _XBF_INODES; |
|---|
| 605 | 606 | xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DINO_BUF); |
|---|
| 606 | 607 | } |
|---|
| 607 | 608 | |
|---|
| .. | .. |
|---|
| 626 | 627 | ASSERT(atomic_read(&bip->bli_refcount) > 0); |
|---|
| 627 | 628 | |
|---|
| 628 | 629 | bip->bli_flags |= XFS_BLI_STALE_INODE; |
|---|
| 629 | | - bip->bli_item.li_cb = xfs_buf_iodone; |
|---|
| 630 | + bp->b_flags |= _XBF_INODES; |
|---|
| 630 | 631 | xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DINO_BUF); |
|---|
| 631 | 632 | } |
|---|
| 632 | 633 | |
|---|
| .. | .. |
|---|
| 651 | 652 | ASSERT(atomic_read(&bip->bli_refcount) > 0); |
|---|
| 652 | 653 | |
|---|
| 653 | 654 | bip->bli_flags |= XFS_BLI_INODE_ALLOC_BUF; |
|---|
| 655 | + bp->b_flags |= _XBF_INODES; |
|---|
| 654 | 656 | xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DINO_BUF); |
|---|
| 655 | 657 | } |
|---|
| 656 | 658 | |
|---|
| .. | .. |
|---|
| 761 | 763 | break; |
|---|
| 762 | 764 | } |
|---|
| 763 | 765 | |
|---|
| 766 | + bp->b_flags |= _XBF_DQUOTS; |
|---|
| 764 | 767 | xfs_trans_buf_set_type(tp, bp, type); |
|---|
| 765 | 768 | } |
|---|