@@ -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
@@ -125,6 +125,7 @@ static int write_intent_writeback(struct btrfs_fs_info *fs_info)
struct write_intent_super *wis;
struct btrfs_device *dev;
SHASH_DESC_ON_STACK(shash, fs_info->csum_shash);
+ unsigned long flags;
int total_errors = 0;
int ret;
@@ -132,13 +133,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;
}
@@ -155,7 +156,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);
/*
* Go through all the writeable devices, copy the bitmap page into the
@@ -179,11 +180,11 @@ static int write_intent_writeback(struct btrfs_fs_info *fs_info)
total_errors++;
}
- 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 > btrfs_super_num_devices(fs_info->super_copy) - 1) {
@@ -707,6 +708,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;
@@ -717,7 +719,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;
@@ -733,7 +735,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;
@@ -742,12 +744,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;
@@ -755,14 +774,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;
}
@@ -772,7 +791,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;
@@ -785,7 +804,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;
@@ -796,7 +815,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);
@@ -267,4 +267,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(-)