/* * We're now finished for good with this ioend structure. Update the folio * state, release holds on bios, and finally free up memory. Do not use the * ioend after this.
*/ static u32 iomap_finish_ioend_buffered(struct iomap_ioend *ioend)
{ struct inode *inode = ioend->io_inode; struct bio *bio = &ioend->io_bio; struct folio_iter fi;
u32 folio_count = 0;
if (ioend->io_error) {
mapping_set_error(inode->i_mapping, ioend->io_error); if (!bio_flagged(bio, BIO_QUIET)) {
pr_err_ratelimited( "%s: writeback error on inode %lu, offset %lld, sector %llu",
inode->i_sb->s_id, inode->i_ino,
ioend->io_offset, ioend->io_sector);
}
}
/* walk all folios in bio, ending page IO on them */
bio_for_each_folio_all(fi, bio) {
iomap_finish_folio_write(inode, fi.folio, fi.length);
folio_count++;
}
bio_put(bio); /* frees the ioend */ return folio_count;
}
staticvoid ioend_writeback_end_bio(struct bio *bio)
{ struct iomap_ioend *ioend = iomap_ioend_from_bio(bio);
/* * We cannot cancel the ioend directly in case of an error, so call the bio end * I/O handler with the error status here to run the normal I/O completion * handler.
*/ int iomap_ioend_writeback_submit(struct iomap_writepage_ctx *wpc, int error)
{ struct iomap_ioend *ioend = wpc->wb_ctx;
if (!ioend->io_bio.bi_end_io)
ioend->io_bio.bi_end_io = ioend_writeback_end_bio;
if (WARN_ON_ONCE(wpc->iomap.flags & IOMAP_F_ANON_WRITE))
error = -EIO;
if (error) {
ioend->io_bio.bi_status = errno_to_blk_status(error);
bio_endio(&ioend->io_bio); return error;
}
if (ioend_flags & IOMAP_IOEND_BOUNDARY) returnfalse; if ((ioend_flags & IOMAP_IOEND_NOMERGE_FLAGS) !=
(ioend->io_flags & IOMAP_IOEND_NOMERGE_FLAGS)) returnfalse; if (pos != ioend->io_offset + ioend->io_size) returnfalse; if (!(wpc->iomap.flags & IOMAP_F_ANON_WRITE) &&
iomap_sector(&wpc->iomap, pos) != bio_end_sector(&ioend->io_bio)) returnfalse; /* * Limit ioend bio chain lengths to minimise IO completion latency. This * also prevents long tight loops ending page writeback on all the * folios in the ioend.
*/ if (wpc->nr_folios >= IOEND_BATCH_SIZE) returnfalse; returntrue;
}
/* * Test to see if we have an existing ioend structure that we could append to * first; otherwise finish off the current ioend and start another. * * If a new ioend is created and cached, the old ioend is submitted to the block * layer instantly. Batching optimisations are provided by higher level block * plugging. * * At the end of a writeback pass, there will be a cached ioend remaining on the * writepage context that the caller will need to submit.
*/
ssize_t iomap_add_to_ioend(struct iomap_writepage_ctx *wpc, struct folio *folio,
loff_t pos, loff_t end_pos, unsignedint dirty_len)
{ struct iomap_ioend *ioend = wpc->wb_ctx;
size_t poff = offset_in_folio(folio, pos); unsignedint ioend_flags = 0; unsignedint map_len = min_t(u64, dirty_len,
wpc->iomap.offset + wpc->iomap.length - pos); int error;
/* * Clamp io_offset and io_size to the incore EOF so that ondisk * file size updates in the ioend completion are byte-accurate. * This avoids recovering files with zeroed tail regions when * writeback races with appending writes: * * Thread 1: Thread 2: * ------------ ----------- * write [A, A+B] * update inode size to A+B * submit I/O [A, A+BS] * write [A+B, A+B+C] * update inode size to A+B+C * <I/O completes, updates disk size to min(A+B+C, A+BS)> * <power failure> * * After reboot: * 1) with A+B+C < A+BS, the file has zero padding in range * [A+B, A+B+C] * * |< Block Size (BS) >| * |DDDDDDDDDDDD0000000000000| * ^ ^ ^ * A A+B A+B+C * (EOF) * * 2) with A+B+C > A+BS, the file has zero padding in range * [A+B, A+BS] * * |< Block Size (BS) >|< Block Size (BS) >| * |DDDDDDDDDDDD0000000000000|00000000000000000000000000| * ^ ^ ^ ^ * A A+B A+BS A+B+C * (EOF) * * D = Valid Data * 0 = Zero Padding * * Note that this defeats the ability to chain the ioends of * appending writes.
*/
ioend->io_size += map_len; if (ioend->io_offset + ioend->io_size > end_pos)
ioend->io_size = end_pos - ioend->io_offset;
static u32 iomap_finish_ioend(struct iomap_ioend *ioend, int error)
{ if (ioend->io_parent) { struct bio *bio = &ioend->io_bio;
ioend = ioend->io_parent;
bio_put(bio);
}
if (error)
cmpxchg(&ioend->io_error, 0, error);
if (!atomic_dec_and_test(&ioend->io_remaining)) return 0; if (ioend->io_flags & IOMAP_IOEND_DIRECT) return iomap_finish_ioend_direct(ioend); return iomap_finish_ioend_buffered(ioend);
}
/* * Ioend completion routine for merged bios. This can only be called from task * contexts as merged ioends can be of unbound length. Hence we have to break up * the writeback completions into manageable chunks to avoid long scheduler * holdoffs. We aim to keep scheduler holdoffs down below 10ms so that we get * good batch processing throughput without creating adverse scheduler latency * conditions.
*/ void iomap_finish_ioends(struct iomap_ioend *ioend, int error)
{ struct list_head tmp;
u32 completions;
/* * We can merge two adjacent ioends if they have the same set of work to do.
*/ staticbool iomap_ioend_can_merge(struct iomap_ioend *ioend, struct iomap_ioend *next)
{ if (ioend->io_bio.bi_status != next->io_bio.bi_status) returnfalse; if (next->io_flags & IOMAP_IOEND_BOUNDARY) returnfalse; if ((ioend->io_flags & IOMAP_IOEND_NOMERGE_FLAGS) !=
(next->io_flags & IOMAP_IOEND_NOMERGE_FLAGS)) returnfalse; if (ioend->io_offset + ioend->io_size != next->io_offset) returnfalse; /* * Do not merge physically discontiguous ioends. The filesystem * completion functions will have to iterate the physical * discontiguities even if we merge the ioends at a logical level, so * we don't gain anything by merging physical discontiguities here. * * We cannot use bio->bi_iter.bi_sector here as it is modified during * submission so does not point to the start sector of the bio at * completion.
*/ if (ioend->io_sector + (ioend->io_size >> SECTOR_SHIFT) !=
next->io_sector) returnfalse; returntrue;
}
/* * Split up to the first @max_len bytes from @ioend if the ioend covers more * than @max_len bytes. * * If @is_append is set, the split will be based on the hardware limits for * REQ_OP_ZONE_APPEND commands and can be less than @max_len if the hardware * limits don't allow the entire @max_len length. * * The bio embedded into @ioend must be a REQ_OP_WRITE because the block layer * does not allow splitting REQ_OP_ZONE_APPEND bios. The file systems has to * switch the operation after this call, but before submitting the bio.
*/ struct iomap_ioend *iomap_split_ioend(struct iomap_ioend *ioend, unsignedint max_len, bool is_append)
{ struct bio *bio = &ioend->io_bio; struct iomap_ioend *split_ioend; unsignedint nr_segs; int sector_offset; struct bio *split;
if (is_append) { struct queue_limits *lim = bdev_limits(bio->bi_bdev);
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.10Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.