/* * This returns the number of log iovecs needed to log the given buf log item. * * It calculates this as 1 iovec for the buf log format structure and 1 for each * stretch of non-contiguous chunks to be logged. Contiguous chunks are logged * in a single iovec. * * Discontiguous buffers need a format structure per region that that is being * logged. This makes the changes in the buffer appear to log recovery as though * they came from separate buffers, just like would occur if multiple buffers * were used instead of a single discontiguous buffer. This enables * discontiguous buffers to be in-memory constructs, completely transparent to * what ends up on disk. * * If the XFS_BLI_STALE flag has been set, then log nothing but the buf log * format structures. */ STATIC void xfs_buf_item_size( struct xfs_log_item *lip, int *nvecs, int *nbytes) { struct xfs_buf_log_item *bip = BUF_ITEM(lip); int i; ASSERT(atomic_read(&bip->bli_refcount) > 0); if (bip->bli_flags & XFS_BLI_STALE) { /* * The buffer is stale, so all we need to log * is the buf log format structure with the * cancel flag in it. */ trace_xfs_buf_item_size_stale(bip); ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL); *nvecs += bip->bli_format_count; for (i = 0; i < bip->bli_format_count; i++) { *nbytes += xfs_buf_log_format_size(&bip->bli_formats[i]); } return; } ASSERT(bip->bli_flags & XFS_BLI_LOGGED); if (bip->bli_flags & XFS_BLI_ORDERED) { /* * The buffer has been logged just to order it. * It is not being included in the transaction * commit, so no vectors are used at all. */ trace_xfs_buf_item_size_ordered(bip); *nvecs = XFS_LOG_VEC_ORDERED; return; } /* * the vector count is based on the number of buffer vectors we have * dirty bits in. This will only be greater than one when we have a * compound buffer with more than one segment dirty. Hence for compound * buffers we need to track which segment the dirty bits correspond to, * and when we move from one segment to the next increment the vector * count for the extra buf log format structure that will need to be * written. */ for (i = 0; i < bip->bli_format_count; i++) { xfs_buf_item_size_segment(bip, &bip->bli_formats[i], nvecs, nbytes); } trace_xfs_buf_item_size(bip); }
/* * This returns the number of log iovecs needed to log the given buf log item. * * It calculates this as 1 iovec for the buf log format structure and 1 for each * stretch of non-contiguous chunks to be logged. Contiguous chunks are logged * in a single iovec. * * Discontiguous buffers need a format structure per region that that is being * logged. This makes the changes in the buffer appear to log recovery as though * they came from separate buffers, just like would occur if multiple buffers * were used instead of a single discontiguous buffer. This enables * discontiguous buffers to be in-memory constructs, completely transparent to * what ends up on disk. * * If the XFS_BLI_STALE flag has been set, then log nothing but the buf log * format structures. */ STATIC uint xfs_buf_item_size( struct xfs_log_item *lip) { struct xfs_buf_log_item *bip = BUF_ITEM(lip); uint nvecs; int i; ASSERT(atomic_read(&bip->bli_refcount) > 0); if (bip->bli_flags & XFS_BLI_STALE) { /* * The buffer is stale, so all we need to log * is the buf log format structure with the * cancel flag in it. */ trace_xfs_buf_item_size_stale(bip); ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL); return bip->bli_format_count; } ASSERT(bip->bli_flags & XFS_BLI_LOGGED); /* * the vector count is based on the number of buffer vectors we have * dirty bits in. This will only be greater than one when we have a * compound buffer with more than one segment dirty. Hence for compound * buffers we need to track which segment the dirty bits correspond to, * and when we move from one segment to the next increment the vector * count for the extra buf log format structure that will need to be * written. */ nvecs = 0; for (i = 0; i < bip->bli_format_count; i++) { nvecs += xfs_buf_item_size_segment(bip, &bip->bli_formats[i]); } trace_xfs_buf_item_size(bip); return nvecs; }
/* * This returns the number of log iovecs needed to log the * given buf log item. * * It calculates this as 1 iovec for the buf log format structure * and 1 for each stretch of non-contiguous chunks to be logged. * Contiguous chunks are logged in a single iovec. * * If the XFS_BLI_STALE flag has been set, then log nothing. */ STATIC uint xfs_buf_item_size( struct xfs_log_item *lip) { struct xfs_buf_log_item *bip = BUF_ITEM(lip); struct xfs_buf *bp = bip->bli_buf; uint nvecs; int next_bit; int last_bit; ASSERT(atomic_read(&bip->bli_refcount) > 0); if (bip->bli_flags & XFS_BLI_STALE) { /* * The buffer is stale, so all we need to log * is the buf log format structure with the * cancel flag in it. */ trace_xfs_buf_item_size_stale(bip); ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL); return 1; } ASSERT(bip->bli_flags & XFS_BLI_LOGGED); nvecs = 1; last_bit = xfs_next_bit(bip->bli_format.blf_data_map, bip->bli_format.blf_map_size, 0); ASSERT(last_bit != -1); nvecs++; while (last_bit != -1) { /* * This takes the bit number to start looking from and * returns the next set bit from there. It returns -1 * if there are no more bits set or the start bit is * beyond the end of the bitmap. */ next_bit = xfs_next_bit(bip->bli_format.blf_data_map, bip->bli_format.blf_map_size, last_bit + 1); /* * If we run out of bits, leave the loop, * else if we find a new set of bits bump the number of vecs, * else keep scanning the current set of bits. */ if (next_bit == -1) { last_bit = -1; } else if (next_bit != last_bit + 1) { last_bit = next_bit; nvecs++; } else if (xfs_buf_offset(bp, next_bit * XFS_BLF_CHUNK) != (xfs_buf_offset(bp, last_bit * XFS_BLF_CHUNK) + XFS_BLF_CHUNK)) { last_bit = next_bit; nvecs++; } else { last_bit++; } } trace_xfs_buf_item_size(bip); return nvecs; }