From b4686a398e5504efa02d9cdd2bbe89ac80ceeccb Mon Sep 17 00:00:00 2001 From: toninov Date: Fri, 3 Oct 2025 23:09:28 +0200 Subject: [PATCH] Advance seqnum in create and destroy local_slice_mapping --- dm-sflc/src/lite/discard.c | 6 +++--- dm-sflc/src/lite/flush.c | 2 +- dm-sflc/src/lite/posmap.c | 20 ++++++++++++++++++-- dm-sflc/src/lite/read.c | 2 +- dm-sflc/src/lite/write.c | 6 +++--- 5 files changed, 26 insertions(+), 10 deletions(-) diff --git a/dm-sflc/src/lite/discard.c b/dm-sflc/src/lite/discard.c index a1d81d1..991174d 100644 --- a/dm-sflc/src/lite/discard.c +++ b/dm-sflc/src/lite/discard.c @@ -31,13 +31,13 @@ void sflite_discard_work_fn(struct work_struct *work) unsigned long flags; u32 lsi = sio->lsi; u32 psi; + int err = 0; /* Mutual exclusion with FLUSHes */ if (down_read_interruptible(&svol->posmap.flush_lock)) { orig_bio->bi_status = BLK_STS_IOERR; goto unlock; } - /* Lock the position map */ spin_lock_irqsave(&svol->posmap.lock, flags); @@ -52,7 +52,7 @@ void sflite_discard_work_fn(struct work_struct *work) } /* Unmap the slice */ - sflite_destroy_local_slice_mapping(svol, lsi); + err = sflite_destroy_local_slice_mapping(svol, lsi); unlock: /* Unlock */ @@ -63,7 +63,7 @@ unlock: /* WARNING: it is crucial that the original bio is terminated here and never reaches the block device, otherwise the effect of a TRIM on the block device would be obvious, and likely to break plausible deniability */ - orig_bio->bi_status = BLK_STS_OK; + orig_bio->bi_status = errno_to_blk_status(err); bio_endio(orig_bio); return; } diff --git a/dm-sflc/src/lite/flush.c b/dm-sflc/src/lite/flush.c index 25a1112..c797b17 100644 --- a/dm-sflc/src/lite/flush.c +++ b/dm-sflc/src/lite/flush.c @@ -314,7 +314,7 @@ int sflite_flush_posmap(struct sflite_volume *svol, struct bio *orig_bio, gfp_t * 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. - * Here, we need to lock. */ + * Here, we need to lock again. */ down_write(&svol->posmap.flush_lock); // Not killable, for simplicity err = mark_posmap_blocks_clean(svol); bitmap_clear(svol->posmap.cwb_error, 0, nblocks); diff --git a/dm-sflc/src/lite/posmap.c b/dm-sflc/src/lite/posmap.c index 2a341aa..201753f 100644 --- a/dm-sflc/src/lite/posmap.c +++ b/dm-sflc/src/lite/posmap.c @@ -64,6 +64,7 @@ static int __peek_next_free_psi(struct sflite_device *sdev, u32 *psi) static void __create_local_slice_mapping(struct sflite_volume *svol, u32 lsi, u32 psi, bool set_dirty) { struct sflite_device *sdev = svol->sdev; + u32 block = lsi/SFLITE_PSIS_PER_BLOCK; /* Grab it from the device (NOCHECK whether PSI is taken already, or OOB) */ __set_bit(psi, sdev->occupation_bitmap); @@ -78,7 +79,8 @@ static void __create_local_slice_mapping(struct sflite_volume *svol, u32 lsi, u3 svol->posmap.entries[lsi] = psi; svol->posmap.nr_mapped_slices++; if (likely(set_dirty)) { - __set_bit(lsi/SFLITE_PSIS_PER_BLOCK, svol->posmap.dirty); + __set_bit(block, svol->posmap.dirty); + svol->posmap.seqnum[block] += 1; // Wrap around, no problem } return; @@ -91,6 +93,7 @@ static void __create_local_slice_mapping(struct sflite_volume *svol, u32 lsi, u3 int sflite_create_local_slice_mapping(struct sflite_volume *svol, u32 lsi, u32 *psi) { struct sflite_device *sdev = svol->sdev; + u32 block = lsi/SFLITE_PSIS_PER_BLOCK; int err; /* Bounds check TODO redundant? */ @@ -99,6 +102,11 @@ int sflite_create_local_slice_mapping(struct sflite_volume *svol, u32 lsi, u32 * /* Check LSI is unmapped TODO redundant? */ if (unlikely(svol->posmap.entries[lsi] != SFLITE_PSI_INVALID)) return -EINVAL; + /* Overwhelmingly unlikely: needs 16384 create/destroy on the same + * posmap block while a FLUSH is pending. */ + if (unlikely(test_bit(block, svol->posmap.flush_pending) && + (svol->posmap.seqnum[block] + 1 == svol->posmap.snap_seqnum[block]))) + return -EAGAIN; /* Create mapping */ err = __peek_next_free_psi(sdev, psi); @@ -115,10 +123,17 @@ int sflite_create_local_slice_mapping(struct sflite_volume *svol, u32 lsi, u32 * */ int sflite_destroy_local_slice_mapping(struct sflite_volume *svol, u32 lsi) { + u32 block = lsi/SFLITE_PSIS_PER_BLOCK; + /* Bounds check */ if (unlikely(lsi >= svol->sdev->tot_slices)) { return -EINVAL; } + /* Overwhelmingly unlikely: needs 16384 create/destroy on the same + * posmap block while a FLUSH is pending. */ + if (unlikely(test_bit(block, svol->posmap.flush_pending) && + (svol->posmap.seqnum[block] + 1 == svol->posmap.snap_seqnum[block]))) + return -EAGAIN; /* Unassign the PSI */ svol->posmap.entries[lsi] = SFLITE_PSI_INVALID; @@ -131,7 +146,8 @@ int sflite_destroy_local_slice_mapping(struct sflite_volume *svol, u32 lsi) requiring reload/close-open? */ /* Set the dirty bit in position map */ - __set_bit(lsi/SFLITE_PSIS_PER_BLOCK, svol->posmap.dirty); + __set_bit(block, svol->posmap.dirty); + svol->posmap.seqnum[block] += 1; // Wrap around, no problem return 0; } diff --git a/dm-sflc/src/lite/read.c b/dm-sflc/src/lite/read.c index b27ffe2..af72883 100644 --- a/dm-sflc/src/lite/read.c +++ b/dm-sflc/src/lite/read.c @@ -107,7 +107,7 @@ static void sflite_decrypt_work_fn(struct work_struct *work) struct bio *orig_bio = io->orig_bio; struct bio *phys_bio = io->phys_bio; struct bio_vec bvl = bio_iovec(orig_bio); - int err; + int err = 0; /* If physical bio failed, then fail-fast */ if (unlikely(phys_bio->bi_status != BLK_STS_OK)) { diff --git a/dm-sflc/src/lite/write.c b/dm-sflc/src/lite/write.c index cd255bc..76a4438 100644 --- a/dm-sflc/src/lite/write.c +++ b/dm-sflc/src/lite/write.c @@ -42,7 +42,7 @@ void sflite_write_work_fn(struct work_struct *work) u32 block_offset = io->block_offset; u32 psi; unsigned long flags; - int err; + int err = 0; // Catch FUA-tagged request early: unsupported TODO improve and support - BUG: this causes a bug, comment out for now //if (orig_bio->bi_opf & REQ_FUA) { @@ -68,12 +68,12 @@ void sflite_write_work_fn(struct work_struct *work) err = sflite_create_local_slice_mapping(svol, lsi, &psi); spin_unlock(&sdev->slices_lock); if (unlikely(err)){ - DMERR("Could not create slice mapping; error %d", err); + DMWARN("Could not create slice mapping; error %d", err); /* Unlock */ spin_unlock_irqrestore(&svol->posmap.lock, flags); up_read(&svol->posmap.flush_lock); /* End of critical section: fail bio */ - orig_bio->bi_status = BLK_STS_IOERR; + orig_bio->bi_status = errno_to_blk_status(err); goto endio; } }