@@ -817,6 +817,13 @@ static void rbio_orig_end_io(struct btrfs_raid_bio *rbio, blk_status_t err)
if (rbio->generic_bio_cnt)
btrfs_bio_counter_sub(rbio->bioc->fs_info, rbio->generic_bio_cnt);
+
+ /* Clear the write-intent bitmap range for write operation. */
+ if (rbio->operation == BTRFS_RBIO_WRITE)
+ btrfs_write_intent_clear_dirty(rbio->bioc->fs_info,
+ rbio->bioc->raid_map[0],
+ rbio->nr_data * BTRFS_STRIPE_LEN);
+
/*
* Clear the data bitmap, as the rbio may be cached for later usage.
* do this before before unlock_stripe() so there will be no new bio
@@ -61,6 +61,7 @@ static int write_intent_writeback(struct btrfs_fs_info *fs_info)
struct bitmap_writeback_contrl wb_ctrl = {0};
SHASH_DESC_ON_STACK(shash, fs_info->csum_shash);
const int nr_devs_max = fs_info->fs_devices->open_devices + 4;
+ unsigned long flags;
int nr_devs = 0;
int total_errors = 0;
int ret;
@@ -75,13 +76,13 @@ static int write_intent_writeback(struct btrfs_fs_info *fs_info)
shash->tfm = fs_info->csum_shash;
- spin_lock(&ctrl->lock);
+ spin_lock_irqsave(&ctrl->lock, flags);
/* No update on the bitmap, just skip this writeback. */
if (!memcmp(page_address(ctrl->page), page_address(ctrl->commit_page),
WRITE_INTENT_BITMAPS_SIZE)) {
ctrl->writing_event = 0;
- spin_unlock(&ctrl->lock);
+ spin_unlock_irqrestore(&ctrl->lock, flags);
wake_up(&ctrl->write_wait);
return 0;
}
@@ -98,7 +99,7 @@ static int write_intent_writeback(struct btrfs_fs_info *fs_info)
atomic64_inc(&ctrl->event);
memcpy_page(ctrl->commit_page, 0, ctrl->page, 0,
WRITE_INTENT_BITMAPS_SIZE);
- spin_unlock(&ctrl->lock);
+ spin_unlock_irqrestore(&ctrl->lock, flags);
init_waitqueue_head(&wb_ctrl.wait);
atomic_set(&wb_ctrl.pending_bios, 0);
@@ -136,11 +137,11 @@ static int write_intent_writeback(struct btrfs_fs_info *fs_info)
}
wait_event(wb_ctrl.wait, atomic_read(&wb_ctrl.pending_bios) == 0);
- spin_lock(&ctrl->lock);
+ spin_lock_irqsave(&ctrl->lock, flags);
if (ctrl->writing_event > ctrl->committed_event)
ctrl->committed_event = ctrl->writing_event;
ctrl->writing_event = 0;
- spin_unlock(&ctrl->lock);
+ spin_unlock_irqrestore(&ctrl->lock, flags);
wake_up(&ctrl->write_wait);
if (total_errors + atomic_read(&wb_ctrl.errors) >
@@ -648,6 +649,7 @@ void btrfs_write_intent_mark_dirty(struct btrfs_fs_info *fs_info, u64 logical,
{
struct write_intent_ctrl *ctrl = fs_info->wi_ctrl;
struct write_intent_super *wis;
+ unsigned long flags;
u32 entry_len;
int nr_entries;
@@ -658,7 +660,7 @@ void btrfs_write_intent_mark_dirty(struct btrfs_fs_info *fs_info, u64 logical,
ASSERT(IS_ALIGNED(len, BTRFS_STRIPE_LEN));
again:
- spin_lock(&ctrl->lock);
+ spin_lock_irqsave(&ctrl->lock, flags);
entry_len = ctrl->blocksize * WRITE_INTENT_BITS_PER_ENTRY;
nr_entries = (round_up(logical + len, entry_len) -
round_down(logical, entry_len)) / entry_len;
@@ -674,7 +676,7 @@ void btrfs_write_intent_mark_dirty(struct btrfs_fs_info *fs_info, u64 logical,
prepare_to_wait_event(&ctrl->overflow_wait, &__wait,
TASK_UNINTERRUPTIBLE);
- spin_unlock(&ctrl->lock);
+ spin_unlock_irqrestore(&ctrl->lock, flags);
schedule();
finish_wait(&ctrl->write_wait, &__wait);
goto again;
@@ -683,12 +685,29 @@ void btrfs_write_intent_mark_dirty(struct btrfs_fs_info *fs_info, u64 logical,
/* Update the bitmap. */
write_intent_set_bits(ctrl, logical, len);
*event_ret = atomic64_read(&ctrl->event);
- spin_unlock(&ctrl->lock);
+ spin_unlock_irqrestore(&ctrl->lock, flags);
+}
+
+void btrfs_write_intent_clear_dirty(struct btrfs_fs_info *fs_info, u64 logical,
+ u32 len)
+{
+ struct write_intent_ctrl *ctrl = fs_info->wi_ctrl;
+ unsigned long flags;
+
+ if (!btrfs_fs_compat_ro(fs_info, WRITE_INTENT_BITMAP))
+ return;
+ ASSERT(ctrl);
+ ASSERT(IS_ALIGNED(len, BTRFS_STRIPE_LEN));
+
+ spin_lock_irqsave(&ctrl->lock, flags);
+ write_intent_clear_bits(ctrl, logical, len);
+ spin_unlock_irqrestore(&ctrl->lock, flags);
}
int btrfs_write_intent_writeback(struct btrfs_fs_info *fs_info, u64 event)
{
struct write_intent_ctrl *ctrl = fs_info->wi_ctrl;
+ unsigned long flags;
if (!btrfs_fs_compat_ro(fs_info, WRITE_INTENT_BITMAP))
return 0;
@@ -696,14 +715,14 @@ int btrfs_write_intent_writeback(struct btrfs_fs_info *fs_info, u64 event)
ASSERT(ctrl);
again:
- spin_lock(&ctrl->lock);
+ spin_lock_irqsave(&ctrl->lock, flags);
/*
* The bitmap has already been written to disk at least once. Our update
* has already reached disk.
*/
if (event && ctrl->committed_event > event) {
- spin_unlock(&ctrl->lock);
+ spin_unlock_irqrestore(&ctrl->lock, flags);
return 0;
}
@@ -713,7 +732,7 @@ int btrfs_write_intent_writeback(struct btrfs_fs_info *fs_info, u64 event)
prepare_to_wait_event(&ctrl->write_wait, &__wait,
TASK_UNINTERRUPTIBLE);
- spin_unlock(&ctrl->lock);
+ spin_unlock_irqrestore(&ctrl->lock, flags);
schedule();
finish_wait(&ctrl->write_wait, &__wait);
goto again;
@@ -726,7 +745,7 @@ int btrfs_write_intent_writeback(struct btrfs_fs_info *fs_info, u64 event)
ASSERT(ctrl->writing_event > event);
prepare_to_wait_event(&ctrl->write_wait, &__wait,
TASK_UNINTERRUPTIBLE);
- spin_unlock(&ctrl->lock);
+ spin_unlock_irqrestore(&ctrl->lock, flags);
schedule();
finish_wait(&ctrl->write_wait, &__wait);
return 0;
@@ -737,7 +756,7 @@ int btrfs_write_intent_writeback(struct btrfs_fs_info *fs_info, u64 event)
* all the other caller will just wait for us.
*/
ctrl->writing_event = atomic64_read(&ctrl->event) + 1;
- spin_unlock(&ctrl->lock);
+ spin_unlock_irqrestore(&ctrl->lock, flags);
/* Slow path, do the submission and wait. */
return write_intent_writeback(fs_info);
@@ -284,4 +284,12 @@ int btrfs_write_intent_writeback(struct btrfs_fs_info *fs_info, u64 event);
void btrfs_write_intent_mark_dirty(struct btrfs_fs_info *fs_info, u64 logical,
u32 len, u64 *event_ret);
+/*
+ * Clear the range dirty in write intent bitmaps.
+ *
+ * This function should not sleep, and no need to wait for the bitmap to be
+ * flushed.
+ */
+void btrfs_write_intent_clear_dirty(struct btrfs_fs_info *fs_info, u64 logical,
+ u32 len);
#endif
Signed-off-by: Qu Wenruo <wqu@suse.com> --- fs/btrfs/raid56.c | 7 +++++++ fs/btrfs/write-intent.c | 45 +++++++++++++++++++++++++++++------------ fs/btrfs/write-intent.h | 8 ++++++++ 3 files changed, 47 insertions(+), 13 deletions(-)