Finish flush.c

This commit is contained in:
toninov 2025-10-03 22:44:25 +02:00
parent e1e1d4b9ec
commit 3e231d0cd7
No known key found for this signature in database

View file

@ -247,6 +247,7 @@ static int mark_posmap_blocks_clean(struct sflite_volume *svol)
*/
int sflite_flush_posmap(struct sflite_volume *svol, struct bio *orig_bio, gfp_t gfp)
{
unsigned nblocks = svol->sdev->posmap_size_blocks;
int err;
/* To prepare the CWBs (encrypt all the `dirty` blocks from `entries`
@ -261,7 +262,7 @@ int sflite_flush_posmap(struct sflite_volume *svol, struct bio *orig_bio, gfp_t
if (err) {
// Clean up flush_pending: give up the FLUSH operation altogether
DMWARN("FLUSH: could not prepare_cwbs(): error %d", err);
bitmap_clear(svol->posmap.flush_pending, 0, svol->sdev->posmap_size_blocks);
bitmap_clear(svol->posmap.flush_pending, 0, nblocks);
}
up_write(&svol->posmap.flush_lock);
if (err)
@ -282,10 +283,10 @@ int sflite_flush_posmap(struct sflite_volume *svol, struct bio *orig_bio, gfp_t
// Clean up and abort FLUSH operation.
DMWARN("FLUSH: could not send_cwbs(): error %d", err);
// All CWB callbacks have finished now, no locking needed
bitmap_clear(svol->posmap.cwb_error, 0, svol->sdev->posmap_size_blocks);
bitmap_clear(svol->posmap.cwb_error, 0, nblocks);
// Need to clear this one under rwsem
down_write(&svol->posmap.flush_lock); // Not killable, for simplicity
bitmap_clear(svol->posmap.flush_pending, 0, svol->sdev->posmap_size_blocks);
bitmap_clear(svol->posmap.flush_pending, 0, nblocks);
up_write(&svol->posmap.flush_lock);
goto out;
}
@ -299,10 +300,10 @@ int sflite_flush_posmap(struct sflite_volume *svol, struct bio *orig_bio, gfp_t
// Bummer, we got so far then the FLUSH failed. Clean up and abort.
DMWARN("FLUSH: could not issue_lowlevel_flush(): error %d", err);
// All CWB callbacks have finished now, no locking needed
bitmap_clear(svol->posmap.cwb_error, 0, svol->sdev->posmap_size_blocks);
bitmap_clear(svol->posmap.cwb_error, 0, nblocks);
// Need to clear this one under rwsem
down_write(&svol->posmap.flush_lock); // Not killable, for simplicity
bitmap_clear(svol->posmap.flush_pending, 0, svol->sdev->posmap_size_blocks);
bitmap_clear(svol->posmap.flush_pending, 0, nblocks);
up_write(&svol->posmap.flush_lock);
goto out;
}
@ -312,7 +313,13 @@ int sflite_flush_posmap(struct sflite_volume *svol, struct bio *orig_bio, gfp_t
* did not change while we were not holding the locks.
* If some CWBs failed, we return an error (then failing the upper-layer
* bio in the caller, if there is one), but that doesn't mean aborting
* entirely, because we can still mark some blocks as clean. */
* entirely, because we can still mark some blocks as clean.
* Here, we need to lock. */
down_write(&svol->posmap.flush_lock); // Not killable, for simplicity
err = mark_posmap_blocks_clean(svol);
bitmap_clear(svol->posmap.cwb_error, 0, nblocks);
bitmap_clear(svol->posmap.flush_pending, 0, nblocks);
up_write(&svol->posmap.flush_lock);
out:
if (orig_bio) {
@ -327,28 +334,16 @@ out:
void sflite_flush_work_fn(struct work_struct *work)
{
struct sflite_io *io = container_of(work, struct sflite_io, work);
struct sflite_volume *svol = io->svol;
struct bio *orig_bio = io->orig_bio;
blk_status_t bi_status = BLK_STS_OK;
int err;
// Mutual exclusion with WRITEs, not with READs
if (down_write_killable(&svol->posmap.flush_lock)) {
bi_status = BLK_STS_IOERR;
goto endio;
}
// Just flush the position map: this function sleeps.
err = sflite_flush_posmap(svol, GFP_NOIO);
if (err) {
DMERR("Could not flush position map; error %d", err);
bi_status = BLK_STS_IOERR;
}
up_write(&svol->posmap.flush_lock);
endio:
// Signal FLUSH completion
orig_bio->bi_status = bi_status;
bio_endio(orig_bio);
/* Everything is implemented in flush_posmap().
* As for non-reentrancy: the block layer guarantees that at most one
* FLUSH request is in-flight at any given time. The only other caller
* of flush_posmap is the volume dtr(), which cannot be invoked if the
* target is busy (e.g. I/O in flight) TODO double check */
err = sflite_flush_posmap(io->svol, io->orig_bio, GFP_NOIO);
io->orig_bio->bi_status = errno_to_blk_status(err);
bio_endio(io->orig_bio);
return;