Commit 0fd22b45 authored by Shaohua Li's avatar Shaohua Li Committed by NeilBrown

raid5-cache: fix a user-after-free bug

r5l_compress_stripe_end_list() can free an io_unit. This breaks the
assumption only reclaimer can free io_unit. We can add a reference count
based io_unit free, but since only reclaim can wait io_unit becoming to
STRIPE_END state, we use a simple global wait queue here.
Signed-off-by: default avatarShaohua Li <shli@fb.com>
Signed-off-by: default avatarNeilBrown <neilb@suse.com>
parent a8c34f91
...@@ -79,6 +79,7 @@ struct r5l_log { ...@@ -79,6 +79,7 @@ struct r5l_log {
* dones't wait for specific io_unit * dones't wait for specific io_unit
* switching to IO_UNIT_STRIPE_END * switching to IO_UNIT_STRIPE_END
* state) */ * state) */
wait_queue_head_t iounit_wait;
struct list_head no_space_stripes; /* pending stripes, log has no space */ struct list_head no_space_stripes; /* pending stripes, log has no space */
spinlock_t no_space_stripes_lock; spinlock_t no_space_stripes_lock;
...@@ -109,7 +110,6 @@ struct r5l_io_unit { ...@@ -109,7 +110,6 @@ struct r5l_io_unit {
struct list_head stripe_list; /* stripes added to the io_unit */ struct list_head stripe_list; /* stripes added to the io_unit */
int state; int state;
wait_queue_head_t wait_state;
}; };
/* r5l_io_unit state */ /* r5l_io_unit state */
...@@ -162,7 +162,6 @@ static struct r5l_io_unit *r5l_alloc_io_unit(struct r5l_log *log) ...@@ -162,7 +162,6 @@ static struct r5l_io_unit *r5l_alloc_io_unit(struct r5l_log *log)
INIT_LIST_HEAD(&io->log_sibling); INIT_LIST_HEAD(&io->log_sibling);
INIT_LIST_HEAD(&io->stripe_list); INIT_LIST_HEAD(&io->stripe_list);
io->state = IO_UNIT_RUNNING; io->state = IO_UNIT_RUNNING;
init_waitqueue_head(&io->wait_state);
return io; return io;
} }
...@@ -243,8 +242,8 @@ static void __r5l_set_io_unit_state(struct r5l_io_unit *io, ...@@ -243,8 +242,8 @@ static void __r5l_set_io_unit_state(struct r5l_io_unit *io,
r5l_wake_reclaim(log, 0); r5l_wake_reclaim(log, 0);
r5l_compress_stripe_end_list(log); r5l_compress_stripe_end_list(log);
wake_up(&log->iounit_wait);
} }
wake_up(&io->wait_state);
} }
static void r5l_set_io_unit_state(struct r5l_io_unit *io, static void r5l_set_io_unit_state(struct r5l_io_unit *io,
...@@ -622,10 +621,11 @@ void r5l_flush_stripe_to_raid(struct r5l_log *log) ...@@ -622,10 +621,11 @@ void r5l_flush_stripe_to_raid(struct r5l_log *log)
submit_bio(WRITE_FLUSH, &log->flush_bio); submit_bio(WRITE_FLUSH, &log->flush_bio);
} }
static void r5l_kick_io_unit(struct r5l_log *log, struct r5l_io_unit *io) static void r5l_kick_io_unit(struct r5l_log *log)
{ {
md_wakeup_thread(log->rdev->mddev->thread); md_wakeup_thread(log->rdev->mddev->thread);
wait_event(io->wait_state, io->state >= IO_UNIT_STRIPE_END); wait_event_lock_irq(log->iounit_wait, !list_empty(&log->stripe_end_ios),
log->io_list_lock);
} }
static void r5l_write_super(struct r5l_log *log, sector_t cp); static void r5l_write_super(struct r5l_log *log, sector_t cp);
...@@ -670,12 +670,7 @@ static void r5l_do_reclaim(struct r5l_log *log) ...@@ -670,12 +670,7 @@ static void r5l_do_reclaim(struct r5l_log *log)
else if (!list_empty(&log->running_ios)) else if (!list_empty(&log->running_ios))
target_list = &log->running_ios; target_list = &log->running_ios;
io = list_first_entry(target_list, r5l_kick_io_unit(log);
struct r5l_io_unit, log_sibling);
spin_unlock_irq(&log->io_list_lock);
/* nobody else can delete the io, we are safe */
r5l_kick_io_unit(log, io);
spin_lock_irq(&log->io_list_lock);
} }
spin_unlock_irq(&log->io_list_lock); spin_unlock_irq(&log->io_list_lock);
...@@ -1079,6 +1074,7 @@ int r5l_init_log(struct r5conf *conf, struct md_rdev *rdev) ...@@ -1079,6 +1074,7 @@ int r5l_init_log(struct r5conf *conf, struct md_rdev *rdev)
log->rdev->mddev, "reclaim"); log->rdev->mddev, "reclaim");
if (!log->reclaim_thread) if (!log->reclaim_thread)
goto reclaim_thread; goto reclaim_thread;
init_waitqueue_head(&log->iounit_wait);
INIT_LIST_HEAD(&log->no_space_stripes); INIT_LIST_HEAD(&log->no_space_stripes);
spin_lock_init(&log->no_space_stripes_lock); spin_lock_init(&log->no_space_stripes_lock);
......
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