spin_unlock_irqrestore(&bg->stripe_run_lock, flags);
}
+/*
+ * Range variant of btrfs_open_stripe_write_done() for callers without the
+ * block group at hand (e.g. the prealloc path, which never issues data IO
+ * for its extent and reports it done at insertion).
+ */
+void btrfs_open_stripe_write_done_bytenr(struct btrfs_fs_info *fs_info,
+ u64 start, u64 num_bytes)
+{
+ struct btrfs_block_group *bg;
+
+ if (list_empty_careful(&fs_info->open_stripe_bgs))
+ return;
+ bg = btrfs_lookup_block_group(fs_info, start);
+ if (!bg)
+ return;
+ btrfs_open_stripe_write_done(bg, start, num_bytes);
+ btrfs_put_block_group(bg);
+}
+
+/*
+ * Find the open stripe run whose allocated region contains
+ * [bytenr, bytenr + num_bytes). The caller must own unreported inflight
+ * bytes in that region (i.e. it was allocated from the run and not yet
+ * reported done), which is what keeps the returned pointer valid: a run
+ * with inflight bytes is never freed.
+ */
+struct btrfs_open_stripe_run *btrfs_get_open_stripe_run(
+ struct btrfs_fs_info *fs_info, u64 bytenr, u64 num_bytes)
+{
+ struct btrfs_open_stripe_run *run = NULL;
+ struct btrfs_open_stripe_run *iter;
+ struct btrfs_block_group *bg;
+ unsigned long flags;
+
+ bg = btrfs_lookup_block_group(fs_info, bytenr);
+ if (!bg)
+ return NULL;
+ spin_lock_irqsave(&bg->stripe_run_lock, flags);
+ list_for_each_entry(iter, &bg->open_stripe_runs, list) {
+ if (bytenr >= iter->start && bytenr < iter->offset) {
+ ASSERT(bytenr + num_bytes <= iter->offset);
+ ASSERT(iter->inflight_bytes >= num_bytes);
+ run = iter;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&bg->stripe_run_lock, flags);
+ btrfs_put_block_group(bg);
+ return run;
+}
+
/*
* Pointer-based variant of btrfs_open_stripe_write_done() for callers that
* recorded the run at allocation or ordered extent creation time; safe from
u64 num_bytes);
void btrfs_open_stripe_write_done_run(struct btrfs_open_stripe_run *run,
u64 num_bytes);
+void btrfs_open_stripe_write_done_bytenr(struct btrfs_fs_info *fs_info,
+ u64 start, u64 num_bytes);
+struct btrfs_open_stripe_run *btrfs_get_open_stripe_run(
+ struct btrfs_fs_info *fs_info, u64 bytenr, u64 num_bytes);
void btrfs_close_bg_open_stripes(struct btrfs_block_group *bg);
void btrfs_retire_block_group_stripes(struct btrfs_block_group *bg);
void btrfs_retire_open_stripes(struct btrfs_fs_info *fs_info);
return 0;
}
+/*
+ * Undo a stripe-policy allocation that find_free_extent() is discarding
+ * before it is handed to the caller (allocation would cross the block group
+ * end, or btrfs_add_reserved_bytes() raced and returned -EAGAIN). The bytes
+ * were counted as inflight in the block group's open stripe run at allocation
+ * time; report them done so the run's inflight accounting stays balanced,
+ * otherwise a commit-time stripe drain waits on them forever. The bytes are
+ * returned to the free space cache by the caller's btrfs_add_free_space_unused()
+ * and, being inside a partially filled stripe, stay unclaimable -- exactly
+ * like a hole left by a deleted extent.
+ */
+static void undo_stripe_allocation(struct btrfs_block_group *block_group,
+ struct find_free_extent_ctl *ffe_ctl)
+{
+ if (btrfs_is_stripe_alloc_bg(block_group))
+ btrfs_open_stripe_write_done(block_group, ffe_ctl->found_offset,
+ ffe_ctl->num_bytes);
+}
+
static int do_allocation(struct btrfs_block_group *block_group,
struct find_free_extent_ctl *ffe_ctl,
struct btrfs_block_group **bg_ret)
/* move on to the next group */
if (ffe_ctl->search_start + ffe_ctl->num_bytes >
block_group->start + block_group->length) {
+ undo_stripe_allocation(block_group, ffe_ctl);
btrfs_add_free_space_unused(block_group,
ffe_ctl->found_offset,
ffe_ctl->num_bytes);
ffe_ctl->delalloc,
ffe_ctl->loop >= LOOP_WRONG_SIZE_CLASS);
if (ret == -EAGAIN) {
+ undo_stripe_allocation(block_group, ffe_ctl);
btrfs_add_free_space_unused(block_group,
ffe_ctl->found_offset,
ffe_ctl->num_bytes);
return ret;
}
-int btrfs_free_reserved_extent(struct btrfs_fs_info *fs_info, u64 start, u64 len,
- bool is_delalloc)
+static int __btrfs_free_reserved_extent(struct btrfs_fs_info *fs_info,
+ u64 start, u64 len, bool is_delalloc,
+ bool stripe_reported)
{
struct btrfs_block_group *cache;
return -ENOSPC;
}
+ /*
+ * A freed reservation from a stripe run will never be written; report
+ * it so the run's inflight accounting stays paired with the reserve.
+ * Skipped when an ordered extent owned the range: its IO completion
+ * (or teardown) already reported these bytes.
+ */
+ if (!stripe_reported)
+ btrfs_open_stripe_write_done(cache, start, len);
+
btrfs_add_free_space(cache, start, len);
btrfs_free_reserved_bytes(cache, len, is_delalloc);
trace_btrfs_reserved_extent_free(fs_info, start, len);
return 0;
}
+int btrfs_free_reserved_extent(struct btrfs_fs_info *fs_info, u64 start, u64 len,
+ bool is_delalloc)
+{
+ return __btrfs_free_reserved_extent(fs_info, start, len, is_delalloc,
+ false);
+}
+
+/*
+ * As btrfs_free_reserved_extent(), for ranges whose bytes were already
+ * reported to the stripe allocator: either an ordered extent owned the
+ * range (its lifecycle reports the data IO), or it was a preallocation
+ * (reported immediately after the reserve).
+ */
+int btrfs_free_reserved_extent_reported(struct btrfs_fs_info *fs_info,
+ u64 start, u64 len, bool is_delalloc)
+{
+ return __btrfs_free_reserved_extent(fs_info, start, len, is_delalloc,
+ true);
+}
+
int btrfs_pin_reserved_extent(struct btrfs_trans_handle *trans,
const struct extent_buffer *eb)
{
struct extent_buffer *leaf, int slot);
int btrfs_free_reserved_extent(struct btrfs_fs_info *fs_info, u64 start, u64 len,
bool is_delalloc);
+int btrfs_free_reserved_extent_reported(struct btrfs_fs_info *fs_info,
+ u64 start, u64 len, bool is_delalloc);
int btrfs_pin_reserved_extent(struct btrfs_trans_handle *trans,
const struct extent_buffer *eb);
int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans);
ordered_extent->disk_bytenr,
ordered_extent->disk_num_bytes,
NULL);
- btrfs_free_reserved_extent(fs_info,
+ btrfs_free_reserved_extent_reported(fs_info,
ordered_extent->disk_bytenr,
ordered_extent->disk_num_bytes, true);
/*
min_size, 0, *alloc_hint, &ins, 1, 0);
if (ret)
break;
+ /*
+ * A preallocated extent never issues data IO, so report it to
+ * the stripe allocator right away. This must happen before
+ * anything that can wait for a transaction (the file extent
+ * insertion below starts one): a commit's stripe retirement
+ * waits for unreported bytes, so holding them across a
+ * transaction join would deadlock. The error paths below
+ * must use the _reported variant of the reservation free.
+ */
+ btrfs_open_stripe_write_done_bytenr(fs_info, ins.objectid,
+ ins.offset);
/*
* We've reserved this space, and thus converted it from
btrfs_dec_block_group_reservations(fs_info, ins.objectid);
if (IS_ERR(trans)) {
ret = PTR_ERR(trans);
- btrfs_free_reserved_extent(fs_info, ins.objectid,
- ins.offset, false);
+ btrfs_free_reserved_extent_reported(fs_info,
+ ins.objectid, ins.offset, false);
break;
}
init_waitqueue_head(&entry->wait);
INIT_LIST_HEAD(&entry->list);
INIT_LIST_HEAD(&entry->log_list);
+
+ /*
+ * Attach the open stripe run backing this extent's disk range, if
+ * any, so its data IO can be reported to the stripe allocator. The
+ * list check makes this free when no stripe runs exist; a run's
+ * block group membership is established before the allocation
+ * returns, so an ordered extent for a stripe-run allocation cannot
+ * observe an empty list. NOCOW and PREALLOC ordered extents write
+ * to previously allocated extents, which can never sit inside a
+ * stripe run (runs are claimed from fully-free stripes).
+ */
+ if (!is_nocow &&
+ !list_empty_careful(&inode->root->fs_info->open_stripe_bgs))
+ entry->stripe_run = btrfs_get_open_stripe_run(
+ inode->root->fs_info, disk_bytenr,
+ disk_num_bytes);
INIT_LIST_HEAD(&entry->root_extent_list);
INIT_LIST_HEAD(&entry->work_list);
INIT_LIST_HEAD(&entry->bioc_list);
btrfs_finish_ordered_io(ordered_extent);
}
+/*
+ * Report this ordered extent's data IO to its open stripe run, exactly
+ * once. Called at IO completion, and as a catch-all when an ordered
+ * extent is freed without ever completing its IO (error teardown); either
+ * way the stripe allocator must stop counting these bytes as in flight.
+ */
+static void btrfs_ordered_stripe_write_done(struct btrfs_ordered_extent *ordered)
+{
+ struct btrfs_open_stripe_run *run = ordered->stripe_run;
+
+ if (!run)
+ return;
+ ordered->stripe_run = NULL;
+ btrfs_open_stripe_write_done_run(run, ordered->disk_num_bytes);
+}
+
static bool can_finish_ordered_extent(struct btrfs_ordered_extent *ordered,
u64 file_offset, u64 len, bool uptodate)
{
* the finish_func to be executed.
*/
set_bit(BTRFS_ORDERED_IO_DONE, &ordered->flags);
+ btrfs_ordered_stripe_write_done(ordered);
cond_wake_up(&ordered->wait);
refcount_inc(&ordered->refs);
trace_btrfs_ordered_extent_mark_finished(inode, ordered);
ASSERT(list_empty(&entry->root_extent_list));
ASSERT(list_empty(&entry->log_list));
ASSERT(RB_EMPTY_NODE(&entry->rb_node));
+ /* Catch-all for extents torn down without completing IO. */
+ btrfs_ordered_stripe_write_done(entry);
btrfs_add_delayed_iput(entry->inode);
list_for_each_entry_safe(sum, tmp, &entry->list, list)
kvfree(sum);
struct extent_state;
struct btrfs_block_group;
struct btrfs_inode;
+struct btrfs_open_stripe_run;
struct btrfs_root;
struct btrfs_fs_info;
/* flags (described above) */
unsigned long flags;
+ /*
+ * The open stripe run backing this extent's disk range, if it was
+ * allocated by the raid56 stripe allocation policy; this extent's
+ * data IO is reported to it exactly once (at IO completion, or when
+ * the ordered extent is freed without completing IO).
+ */
+ struct btrfs_open_stripe_run *stripe_run;
+
/* compression algorithm */
int compress_type;