Commit ffd2cb6b authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'block-6.8-2024-02-22' of git://git.kernel.dk/linux

Pull block fixes from Jens Axboe:
 "Mostly just fixlets for md, but also a sed-opal parsing fix"

* tag 'block-6.8-2024-02-22' of git://git.kernel.dk/linux:
  block: sed-opal: handle empty atoms when parsing response
  md: Don't suspend the array for interrupted reshape
  md: Don't register sync_thread for reshape directly
  md: Make sure md_do_sync() will set MD_RECOVERY_DONE
  md: Don't ignore read-only array in md_check_recovery()
  md: Don't ignore suspended array in md_check_recovery()
  md: Fix missing release of 'active_io' for flush
parents 4c36fbb4 5429c8de
...@@ -71,6 +71,7 @@ enum opal_response_token { ...@@ -71,6 +71,7 @@ enum opal_response_token {
#define SHORT_ATOM_BYTE 0xBF #define SHORT_ATOM_BYTE 0xBF
#define MEDIUM_ATOM_BYTE 0xDF #define MEDIUM_ATOM_BYTE 0xDF
#define LONG_ATOM_BYTE 0xE3 #define LONG_ATOM_BYTE 0xE3
#define EMPTY_ATOM_BYTE 0xFF
#define OPAL_INVAL_PARAM 12 #define OPAL_INVAL_PARAM 12
#define OPAL_MANUFACTURED_INACTIVE 0x08 #define OPAL_MANUFACTURED_INACTIVE 0x08
......
...@@ -1056,16 +1056,20 @@ static int response_parse(const u8 *buf, size_t length, ...@@ -1056,16 +1056,20 @@ static int response_parse(const u8 *buf, size_t length,
token_length = response_parse_medium(iter, pos); token_length = response_parse_medium(iter, pos);
else if (pos[0] <= LONG_ATOM_BYTE) /* long atom */ else if (pos[0] <= LONG_ATOM_BYTE) /* long atom */
token_length = response_parse_long(iter, pos); token_length = response_parse_long(iter, pos);
else if (pos[0] == EMPTY_ATOM_BYTE) /* empty atom */
token_length = 1;
else /* TOKEN */ else /* TOKEN */
token_length = response_parse_token(iter, pos); token_length = response_parse_token(iter, pos);
if (token_length < 0) if (token_length < 0)
return token_length; return token_length;
if (pos[0] != EMPTY_ATOM_BYTE)
num_entries++;
pos += token_length; pos += token_length;
total -= token_length; total -= token_length;
iter++; iter++;
num_entries++;
} }
resp->num = num_entries; resp->num = num_entries;
......
...@@ -579,8 +579,12 @@ static void submit_flushes(struct work_struct *ws) ...@@ -579,8 +579,12 @@ static void submit_flushes(struct work_struct *ws)
rcu_read_lock(); rcu_read_lock();
} }
rcu_read_unlock(); rcu_read_unlock();
if (atomic_dec_and_test(&mddev->flush_pending)) if (atomic_dec_and_test(&mddev->flush_pending)) {
/* The pair is percpu_ref_get() from md_flush_request() */
percpu_ref_put(&mddev->active_io);
queue_work(md_wq, &mddev->flush_work); queue_work(md_wq, &mddev->flush_work);
}
} }
static void md_submit_flush_data(struct work_struct *ws) static void md_submit_flush_data(struct work_struct *ws)
...@@ -8788,12 +8792,16 @@ void md_do_sync(struct md_thread *thread) ...@@ -8788,12 +8792,16 @@ void md_do_sync(struct md_thread *thread)
int ret; int ret;
/* just incase thread restarts... */ /* just incase thread restarts... */
if (test_bit(MD_RECOVERY_DONE, &mddev->recovery) || if (test_bit(MD_RECOVERY_DONE, &mddev->recovery))
test_bit(MD_RECOVERY_WAIT, &mddev->recovery))
return; return;
if (!md_is_rdwr(mddev)) {/* never try to sync a read-only array */
if (test_bit(MD_RECOVERY_INTR, &mddev->recovery))
goto skip;
if (test_bit(MD_RECOVERY_WAIT, &mddev->recovery) ||
!md_is_rdwr(mddev)) {/* never try to sync a read-only array */
set_bit(MD_RECOVERY_INTR, &mddev->recovery); set_bit(MD_RECOVERY_INTR, &mddev->recovery);
return; goto skip;
} }
if (mddev_is_clustered(mddev)) { if (mddev_is_clustered(mddev)) {
...@@ -9368,13 +9376,19 @@ static void md_start_sync(struct work_struct *ws) ...@@ -9368,13 +9376,19 @@ static void md_start_sync(struct work_struct *ws)
struct mddev *mddev = container_of(ws, struct mddev, sync_work); struct mddev *mddev = container_of(ws, struct mddev, sync_work);
int spares = 0; int spares = 0;
bool suspend = false; bool suspend = false;
char *name;
if (md_spares_need_change(mddev)) /*
* If reshape is still in progress, spares won't be added or removed
* from conf until reshape is done.
*/
if (mddev->reshape_position == MaxSector &&
md_spares_need_change(mddev)) {
suspend = true; suspend = true;
mddev_suspend(mddev, false);
}
suspend ? mddev_suspend_and_lock_nointr(mddev) : mddev_lock_nointr(mddev);
mddev_lock_nointr(mddev);
if (!md_is_rdwr(mddev)) { if (!md_is_rdwr(mddev)) {
/* /*
* On a read-only array we can: * On a read-only array we can:
...@@ -9400,8 +9414,10 @@ static void md_start_sync(struct work_struct *ws) ...@@ -9400,8 +9414,10 @@ static void md_start_sync(struct work_struct *ws)
if (spares) if (spares)
md_bitmap_write_all(mddev->bitmap); md_bitmap_write_all(mddev->bitmap);
name = test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) ?
"reshape" : "resync";
rcu_assign_pointer(mddev->sync_thread, rcu_assign_pointer(mddev->sync_thread,
md_register_thread(md_do_sync, mddev, "resync")); md_register_thread(md_do_sync, mddev, name));
if (!mddev->sync_thread) { if (!mddev->sync_thread) {
pr_warn("%s: could not start resync thread...\n", pr_warn("%s: could not start resync thread...\n",
mdname(mddev)); mdname(mddev));
...@@ -9445,6 +9461,20 @@ static void md_start_sync(struct work_struct *ws) ...@@ -9445,6 +9461,20 @@ static void md_start_sync(struct work_struct *ws)
sysfs_notify_dirent_safe(mddev->sysfs_action); sysfs_notify_dirent_safe(mddev->sysfs_action);
} }
static void unregister_sync_thread(struct mddev *mddev)
{
if (!test_bit(MD_RECOVERY_DONE, &mddev->recovery)) {
/* resync/recovery still happening */
clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
return;
}
if (WARN_ON_ONCE(!mddev->sync_thread))
return;
md_reap_sync_thread(mddev);
}
/* /*
* This routine is regularly called by all per-raid-array threads to * This routine is regularly called by all per-raid-array threads to
* deal with generic issues like resync and super-block update. * deal with generic issues like resync and super-block update.
...@@ -9469,9 +9499,6 @@ static void md_start_sync(struct work_struct *ws) ...@@ -9469,9 +9499,6 @@ static void md_start_sync(struct work_struct *ws)
*/ */
void md_check_recovery(struct mddev *mddev) void md_check_recovery(struct mddev *mddev)
{ {
if (READ_ONCE(mddev->suspended))
return;
if (mddev->bitmap) if (mddev->bitmap)
md_bitmap_daemon_work(mddev); md_bitmap_daemon_work(mddev);
...@@ -9485,7 +9512,8 @@ void md_check_recovery(struct mddev *mddev) ...@@ -9485,7 +9512,8 @@ void md_check_recovery(struct mddev *mddev)
} }
if (!md_is_rdwr(mddev) && if (!md_is_rdwr(mddev) &&
!test_bit(MD_RECOVERY_NEEDED, &mddev->recovery)) !test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) &&
!test_bit(MD_RECOVERY_DONE, &mddev->recovery))
return; return;
if ( ! ( if ( ! (
(mddev->sb_flags & ~ (1<<MD_SB_CHANGE_PENDING)) || (mddev->sb_flags & ~ (1<<MD_SB_CHANGE_PENDING)) ||
...@@ -9507,8 +9535,7 @@ void md_check_recovery(struct mddev *mddev) ...@@ -9507,8 +9535,7 @@ void md_check_recovery(struct mddev *mddev)
struct md_rdev *rdev; struct md_rdev *rdev;
if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) { if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) {
/* sync_work already queued. */ unregister_sync_thread(mddev);
clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
goto unlock; goto unlock;
} }
...@@ -9571,16 +9598,7 @@ void md_check_recovery(struct mddev *mddev) ...@@ -9571,16 +9598,7 @@ void md_check_recovery(struct mddev *mddev)
* still set. * still set.
*/ */
if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) { if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) {
if (!test_bit(MD_RECOVERY_DONE, &mddev->recovery)) { unregister_sync_thread(mddev);
/* resync/recovery still happening */
clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
goto unlock;
}
if (WARN_ON_ONCE(!mddev->sync_thread))
goto unlock;
md_reap_sync_thread(mddev);
goto unlock; goto unlock;
} }
......
...@@ -4175,11 +4175,7 @@ static int raid10_run(struct mddev *mddev) ...@@ -4175,11 +4175,7 @@ static int raid10_run(struct mddev *mddev)
clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery); set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
set_bit(MD_RECOVERY_RUNNING, &mddev->recovery); set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
rcu_assign_pointer(mddev->sync_thread,
md_register_thread(md_do_sync, mddev, "reshape"));
if (!mddev->sync_thread)
goto out_free_conf;
} }
return 0; return 0;
...@@ -4573,16 +4569,8 @@ static int raid10_start_reshape(struct mddev *mddev) ...@@ -4573,16 +4569,8 @@ static int raid10_start_reshape(struct mddev *mddev)
clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
clear_bit(MD_RECOVERY_DONE, &mddev->recovery); clear_bit(MD_RECOVERY_DONE, &mddev->recovery);
set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery); set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
set_bit(MD_RECOVERY_RUNNING, &mddev->recovery); set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
rcu_assign_pointer(mddev->sync_thread,
md_register_thread(md_do_sync, mddev, "reshape"));
if (!mddev->sync_thread) {
ret = -EAGAIN;
goto abort;
}
conf->reshape_checkpoint = jiffies; conf->reshape_checkpoint = jiffies;
md_wakeup_thread(mddev->sync_thread);
md_new_event(); md_new_event();
return 0; return 0;
......
...@@ -7936,11 +7936,7 @@ static int raid5_run(struct mddev *mddev) ...@@ -7936,11 +7936,7 @@ static int raid5_run(struct mddev *mddev)
clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery); set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
set_bit(MD_RECOVERY_RUNNING, &mddev->recovery); set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
rcu_assign_pointer(mddev->sync_thread,
md_register_thread(md_do_sync, mddev, "reshape"));
if (!mddev->sync_thread)
goto abort;
} }
/* Ok, everything is just fine now */ /* Ok, everything is just fine now */
...@@ -8506,29 +8502,8 @@ static int raid5_start_reshape(struct mddev *mddev) ...@@ -8506,29 +8502,8 @@ static int raid5_start_reshape(struct mddev *mddev)
clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
clear_bit(MD_RECOVERY_DONE, &mddev->recovery); clear_bit(MD_RECOVERY_DONE, &mddev->recovery);
set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery); set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
set_bit(MD_RECOVERY_RUNNING, &mddev->recovery); set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
rcu_assign_pointer(mddev->sync_thread,
md_register_thread(md_do_sync, mddev, "reshape"));
if (!mddev->sync_thread) {
mddev->recovery = 0;
spin_lock_irq(&conf->device_lock);
write_seqcount_begin(&conf->gen_lock);
mddev->raid_disks = conf->raid_disks = conf->previous_raid_disks;
mddev->new_chunk_sectors =
conf->chunk_sectors = conf->prev_chunk_sectors;
mddev->new_layout = conf->algorithm = conf->prev_algo;
rdev_for_each(rdev, mddev)
rdev->new_data_offset = rdev->data_offset;
smp_wmb();
conf->generation --;
conf->reshape_progress = MaxSector;
mddev->reshape_position = MaxSector;
write_seqcount_end(&conf->gen_lock);
spin_unlock_irq(&conf->device_lock);
return -EAGAIN;
}
conf->reshape_checkpoint = jiffies; conf->reshape_checkpoint = jiffies;
md_wakeup_thread(mddev->sync_thread);
md_new_event(); md_new_event();
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment