mirror of
https://codeberg.org/shufflecake/shufflecake-c.git
synced 2025-12-27 14:14:57 -05:00
Finish flush.c
This commit is contained in:
parent
e1e1d4b9ec
commit
3e231d0cd7
1 changed files with 21 additions and 26 deletions
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue