|
@@ -477,8 +477,6 @@ _xfs_buf_find(
|
|
|
|
|
|
/* No match found */
|
|
|
if (new_bp) {
|
|
|
- _xfs_buf_initialize(new_bp, btp, range_base,
|
|
|
- range_length, flags);
|
|
|
rb_link_node(&new_bp->b_rbnode, parent, rbp);
|
|
|
rb_insert_color(&new_bp->b_rbnode, &pag->pag_buf_tree);
|
|
|
/* the buffer keeps the perag reference until it is freed */
|
|
@@ -521,35 +519,53 @@ found:
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * Assembles a buffer covering the specified range.
|
|
|
- * Storage in memory for all portions of the buffer will be allocated,
|
|
|
- * although backing storage may not be.
|
|
|
+ * Assembles a buffer covering the specified range. The code is optimised for
|
|
|
+ * cache hits, as metadata intensive workloads will see 3 orders of magnitude
|
|
|
+ * more hits than misses.
|
|
|
*/
|
|
|
-xfs_buf_t *
|
|
|
+struct xfs_buf *
|
|
|
xfs_buf_get(
|
|
|
xfs_buftarg_t *target,/* target for buffer */
|
|
|
xfs_off_t ioff, /* starting offset of range */
|
|
|
size_t isize, /* length of range */
|
|
|
xfs_buf_flags_t flags)
|
|
|
{
|
|
|
- xfs_buf_t *bp, *new_bp;
|
|
|
+ struct xfs_buf *bp;
|
|
|
+ struct xfs_buf *new_bp;
|
|
|
int error = 0;
|
|
|
|
|
|
+ bp = _xfs_buf_find(target, ioff, isize, flags, NULL);
|
|
|
+ if (likely(bp))
|
|
|
+ goto found;
|
|
|
+
|
|
|
new_bp = xfs_buf_allocate(flags);
|
|
|
if (unlikely(!new_bp))
|
|
|
return NULL;
|
|
|
|
|
|
+ _xfs_buf_initialize(new_bp, target,
|
|
|
+ ioff << BBSHIFT, isize << BBSHIFT, flags);
|
|
|
+
|
|
|
bp = _xfs_buf_find(target, ioff, isize, flags, new_bp);
|
|
|
+ if (!bp) {
|
|
|
+ xfs_buf_deallocate(new_bp);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
if (bp == new_bp) {
|
|
|
error = xfs_buf_allocate_memory(bp, flags);
|
|
|
if (error)
|
|
|
goto no_buffer;
|
|
|
- } else {
|
|
|
+ } else
|
|
|
xfs_buf_deallocate(new_bp);
|
|
|
- if (unlikely(bp == NULL))
|
|
|
- return NULL;
|
|
|
- }
|
|
|
|
|
|
+ /*
|
|
|
+ * Now we have a workable buffer, fill in the block number so
|
|
|
+ * that we can do IO on it.
|
|
|
+ */
|
|
|
+ bp->b_bn = ioff;
|
|
|
+ bp->b_count_desired = bp->b_buffer_length;
|
|
|
+
|
|
|
+found:
|
|
|
if (!(bp->b_flags & XBF_MAPPED)) {
|
|
|
error = _xfs_buf_map_pages(bp, flags);
|
|
|
if (unlikely(error)) {
|
|
@@ -560,18 +576,10 @@ xfs_buf_get(
|
|
|
}
|
|
|
|
|
|
XFS_STATS_INC(xb_get);
|
|
|
-
|
|
|
- /*
|
|
|
- * Always fill in the block number now, the mapped cases can do
|
|
|
- * their own overlay of this later.
|
|
|
- */
|
|
|
- bp->b_bn = ioff;
|
|
|
- bp->b_count_desired = bp->b_buffer_length;
|
|
|
-
|
|
|
trace_xfs_buf_get(bp, flags, _RET_IP_);
|
|
|
return bp;
|
|
|
|
|
|
- no_buffer:
|
|
|
+no_buffer:
|
|
|
if (flags & (XBF_LOCK | XBF_TRYLOCK))
|
|
|
xfs_buf_unlock(bp);
|
|
|
xfs_buf_rele(bp);
|