From patchwork Mon Feb 3 09:43:05 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Hellwig X-Patchwork-Id: 13957143 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0262C1FF7AA; Mon, 3 Feb 2025 09:43:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.137.202.133 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738575811; cv=none; b=I/Y16FZNF8rRfuendqpO5C9mo2gj4l+9EtQ+a6QLLO5djS/eFoPTAglZ6lR++YmhBynxtS/PnyeSaverGr+YC9x+ZP5/gdUqOf1ORFivGjNE1QGBDuM3bx1KNMl8q0Li2gUzKA4UfbsZQnDDvXIYbpoaBc+541ScYq93siz/UNQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738575811; c=relaxed/simple; bh=sroJfLq3X/drWey6E3R7XSmSx29NBw8nU6wnqyau4O4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=oRkCJqetLQDw+1gf1JkhcdkGlXZnEtuUFxCTl8pjNV7aqHjElGOx0dL5utuw0KLdpHOBKKt8FDqV0s0FNBMkSOAZH6MzbX64bjfuTVTmthAQGnFAa0opQiw+QHNfnClUG+lqY5i6l/BzNrVxj5E54h6CGsOI//HLJ3SuHVM/rY4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=lst.de; spf=none smtp.mailfrom=bombadil.srs.infradead.org; dkim=pass (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b=yyZIawju; arc=none smtp.client-ip=198.137.202.133 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=lst.de Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=bombadil.srs.infradead.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b="yyZIawju" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20210309; h=Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Sender :Reply-To:Content-Type:Content-ID:Content-Description; bh=bvfQgK+AKz4WUIi388qsNolaDh+rw/fXsHQu/CdS8Ms=; b=yyZIawjuJLJnugwQ79XdR2o2Bh oG7eNLqM40iJABagyAe42Mc3M6M2CU9agZzXHraZ9uSW/prZvfCoKf3nFa+xkSDLtkb1teOOEKQAA q2FUuLbU11n1rS9ygHBj8p41QYHp6dnn22yzFMpkqGSUCtH66DBpJxzdErlmH6yM0sNHjPN3TffGI vtRgDi3Id1OelfpCdXzGpS3OcFyw9pbYGBgEoAALeKdTeHgoh0FtlbXe82f+hQJtucJd7FW4YQ4NE XBlUHMCHQFDE8+Zbqn2G70u+65oBSiYSlGGDcjhbSdJtnOUvdCF+xT/2PC0HCZ+W+QDkCMgZy6ilj 4CoKhXKQ==; Received: from 2a02-8389-2341-5b80-b79f-eb9e-0b40-3aae.cable.dynamic.v6.surfer.at ([2a02:8389:2341:5b80:b79f:eb9e:b40:3aae] helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.98 #2 (Red Hat Linux)) id 1teszH-0000000F1gH-3njw; Mon, 03 Feb 2025 09:43:28 +0000 From: Christoph Hellwig To: Kanchan Joshi , "Martin K . Petersen" Cc: Johannes Thumshirn , Qu Wenruo , Goldwyn Rodrigues , linux-block@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-xfs@vger.kernel.org Subject: [PATCH 1/7] block: support integrity generation and verification from file systems Date: Mon, 3 Feb 2025 10:43:05 +0100 Message-ID: <20250203094322.1809766-2-hch@lst.de> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250203094322.1809766-1-hch@lst.de> References: <20250203094322.1809766-1-hch@lst.de> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html Add a new blk_integrity_verify_all helper that uses the _all iterator to verify the entire bio as built by the file system and doesn't require the extra bvec_iter used by blk_integrity_verify_iter and export blk_integrity_generate which can be used as-is. Signed-off-by: Christoph Hellwig Reviewed-by: Martin K. Petersen --- block/blk.h | 1 - block/t10-pi.c | 90 ++++++++++++++++++++++++----------- include/linux/bio-integrity.h | 12 +++++ 3 files changed, 75 insertions(+), 28 deletions(-) diff --git a/block/blk.h b/block/blk.h index 8f5554a6989e..176b04cdddda 100644 --- a/block/blk.h +++ b/block/blk.h @@ -709,7 +709,6 @@ int bdev_open(struct block_device *bdev, blk_mode_t mode, void *holder, const struct blk_holder_ops *hops, struct file *bdev_file); int bdev_permission(dev_t dev, blk_mode_t mode, void *holder); -void blk_integrity_generate(struct bio *bio); void blk_integrity_verify_iter(struct bio *bio, struct bvec_iter *saved_iter); void blk_integrity_prepare(struct request *rq); void blk_integrity_complete(struct request *rq, unsigned int nr_bytes); diff --git a/block/t10-pi.c b/block/t10-pi.c index de172d56b1f3..b59db61a8104 100644 --- a/block/t10-pi.c +++ b/block/t10-pi.c @@ -403,42 +403,51 @@ void blk_integrity_generate(struct bio *bio) kunmap_local(kaddr); } } +EXPORT_SYMBOL_GPL(blk_integrity_generate); +static blk_status_t blk_integrity_verify_bvec(struct blk_integrity *bi, + struct blk_integrity_iter *iter, struct bio_vec *bv) +{ + void *kaddr = bvec_kmap_local(bv); + blk_status_t ret = BLK_STS_OK; + + iter->data_buf = kaddr; + iter->data_size = bv->bv_len; + switch (bi->csum_type) { + case BLK_INTEGRITY_CSUM_CRC64: + ret = ext_pi_crc64_verify(iter, bi); + break; + case BLK_INTEGRITY_CSUM_CRC: + case BLK_INTEGRITY_CSUM_IP: + ret = t10_pi_verify(iter, bi); + break; + default: + break; + } + kunmap_local(kaddr); + return ret; +} + +/* + * At the moment verify is called, bi_iter could have been advanced by splits + * and completions, thus we have to use the saved copy here. + */ void blk_integrity_verify_iter(struct bio *bio, struct bvec_iter *saved_iter) { struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); struct bio_integrity_payload *bip = bio_integrity(bio); - struct blk_integrity_iter iter; + struct blk_integrity_iter iter = { + .disk_name = bio->bi_bdev->bd_disk->disk_name, + .interval = 1 << bi->interval_exp, + .seed = saved_iter->bi_sector, + .prot_buf = bvec_virt(bip->bip_vec), + }; struct bvec_iter bviter; struct bio_vec bv; + blk_status_t ret; - /* - * At the moment verify is called bi_iter has been advanced during split - * and completion, so use the copy created during submission here. - */ - iter.disk_name = bio->bi_bdev->bd_disk->disk_name; - iter.interval = 1 << bi->interval_exp; - iter.seed = saved_iter->bi_sector; - iter.prot_buf = bvec_virt(bip->bip_vec); __bio_for_each_segment(bv, bio, bviter, *saved_iter) { - void *kaddr = bvec_kmap_local(&bv); - blk_status_t ret = BLK_STS_OK; - - iter.data_buf = kaddr; - iter.data_size = bv.bv_len; - switch (bi->csum_type) { - case BLK_INTEGRITY_CSUM_CRC64: - ret = ext_pi_crc64_verify(&iter, bi); - break; - case BLK_INTEGRITY_CSUM_CRC: - case BLK_INTEGRITY_CSUM_IP: - ret = t10_pi_verify(&iter, bi); - break; - default: - break; - } - kunmap_local(kaddr); - + ret = blk_integrity_verify_bvec(bi, &iter, &bv); if (ret) { bio->bi_status = ret; return; @@ -446,6 +455,33 @@ void blk_integrity_verify_iter(struct bio *bio, struct bvec_iter *saved_iter) } } +/* + * For use by the file system which owns the entire bio. + */ +int blk_integrity_verify_all(struct bio *bio, sector_t seed) +{ + struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); + struct bio_integrity_payload *bip = bio_integrity(bio); + struct blk_integrity_iter iter = { + .disk_name = bio->bi_bdev->bd_disk->disk_name, + .interval = 1 << bi->interval_exp, + .seed = seed, + .prot_buf = bvec_virt(bip->bip_vec), + }; + struct bvec_iter_all bviter; + struct bio_vec *bv; + blk_status_t ret; + + bio_for_each_segment_all(bv, bio, bviter) { + ret = blk_integrity_verify_bvec(bi, &iter, bv); + if (ret) + return blk_status_to_errno(ret); + } + + return 0; +} +EXPORT_SYMBOL_GPL(blk_integrity_verify_all); + void blk_integrity_prepare(struct request *rq) { struct blk_integrity *bi = &rq->q->limits.integrity; diff --git a/include/linux/bio-integrity.h b/include/linux/bio-integrity.h index 0a25716820fe..26419eb5425a 100644 --- a/include/linux/bio-integrity.h +++ b/include/linux/bio-integrity.h @@ -81,6 +81,9 @@ void bio_integrity_advance(struct bio *bio, unsigned int bytes_done); void bio_integrity_trim(struct bio *bio); int bio_integrity_clone(struct bio *bio, struct bio *bio_src, gfp_t gfp_mask); +void blk_integrity_generate(struct bio *bio); +int blk_integrity_verify_all(struct bio *bio, sector_t seed); + #else /* CONFIG_BLK_DEV_INTEGRITY */ static inline struct bio_integrity_payload *bio_integrity(struct bio *bio) @@ -138,5 +141,14 @@ static inline int bio_integrity_add_page(struct bio *bio, struct page *page, { return 0; } + +static inline void blk_integrity_generate(struct bio *bio) +{ +} + +static inline int blk_integrity_verify_all(struct bio *bio, sector_t seed) +{ + return 0; +} #endif /* CONFIG_BLK_DEV_INTEGRITY */ #endif /* _LINUX_BIO_INTEGRITY_H */ From patchwork Mon Feb 3 09:43:06 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Hellwig X-Patchwork-Id: 13957144 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 405D51FFC67; Mon, 3 Feb 2025 09:43:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.137.202.133 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738575813; cv=none; b=evrJD/VE35rOzF3FDwJB0C8iGCkf0tmcIXCxFKlQyoR5/7G+ZD85IPLF1HFMkmklu5BsMC/4DPhKX3FVAk081hC642klzTSYrC6y/n4LgTusVp+yMqoq1mfk8Y4V1jvP0tKo5jjQqw28pHtExNNrF/plUfEsubNLAJiNyvhmC/s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738575813; c=relaxed/simple; bh=v2FHne68+jEpTvz5Rqg+6S/DvY9pyEXy6/nHNsd2irE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WizIJJg03xAD/Jq1d90nGWnk0KzRKVhULpLAJcBLjWVkTWJ1N1glo/Ny0AT/ifCN8FKAsIWliVBEFbFOlL2v1USWVgvwp9Ch9S2vTUsPKemKAkS+PBcKLK5jCOD4qG0oSNOzjEFlzkrBTE5WWVHr7VGU8n3sT0TOT9sLIXDiYQY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=lst.de; spf=none smtp.mailfrom=bombadil.srs.infradead.org; dkim=pass (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b=zSaQmeB5; arc=none smtp.client-ip=198.137.202.133 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=lst.de Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=bombadil.srs.infradead.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b="zSaQmeB5" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20210309; h=Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Sender :Reply-To:Content-Type:Content-ID:Content-Description; bh=VmoVu1qBS/xDcNr5Y2OBKuc12ztCJfDEnl6CgejjiPQ=; b=zSaQmeB5IDRvQFUdClCaEr/+90 J7RakJyZU2ewghkPhz8mpCcZ7jgFQv8DFm40fVgl7QBm6vzoLct+bp12TKAgV/xU94fb0vJqAhNu0 O7NON7HRrvhCe/Q9LvWaAxWTlzIqyQ3XwPS1ttgf26eUmdMJmHOWNd4blPuGpDJ3GRpK2flUPss1O 2Gd2lPN7+4caWI+SJrmJRkYAMOVhTStVW7Zhh10Olgxc8c2p7zKM8WUwXMIMgEkBvz4l2be7AA5GF /Uc3/SJL+awnkYZSxt8jXGKkn71WyRjIQVKw/Rrjg2B6RuPGtRsMOAh/FH+ckA8CQpc/qT2n8yTNP o405fgSQ==; Received: from 2a02-8389-2341-5b80-b79f-eb9e-0b40-3aae.cable.dynamic.v6.surfer.at ([2a02:8389:2341:5b80:b79f:eb9e:b40:3aae] helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.98 #2 (Red Hat Linux)) id 1teszK-0000000F1hF-0hMi; Mon, 03 Feb 2025 09:43:30 +0000 From: Christoph Hellwig To: Kanchan Joshi , "Martin K . Petersen" Cc: Johannes Thumshirn , Qu Wenruo , Goldwyn Rodrigues , linux-block@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-xfs@vger.kernel.org Subject: [PATCH 2/7] iomap: introduce iomap_read_folio_ops Date: Mon, 3 Feb 2025 10:43:06 +0100 Message-ID: <20250203094322.1809766-3-hch@lst.de> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250203094322.1809766-1-hch@lst.de> References: <20250203094322.1809766-1-hch@lst.de> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html From: Goldwyn Rodrigues iomap_read_folio_ops provide additional functions to allocate or submit the bio. Filesystems such as btrfs have additional operations with bios such as verifying data checksums. Creating a bio submission hook allows the filesystem to process and verify the bio. Signed-off-by: Goldwyn Rodrigues [hch: add a helper, pass file offset to ->submit_io] Signed-off-by: Christoph Hellwig --- block/fops.c | 4 ++-- fs/erofs/data.c | 4 ++-- fs/gfs2/aops.c | 4 ++-- fs/iomap/buffered-io.c | 27 ++++++++++++++++++++++----- fs/xfs/xfs_aops.c | 4 ++-- fs/zonefs/file.c | 4 ++-- include/linux/iomap.h | 16 ++++++++++++++-- 7 files changed, 46 insertions(+), 17 deletions(-) diff --git a/block/fops.c b/block/fops.c index be9f1dbea9ce..f4c971311c6c 100644 --- a/block/fops.c +++ b/block/fops.c @@ -505,12 +505,12 @@ const struct address_space_operations def_blk_aops = { #else /* CONFIG_BUFFER_HEAD */ static int blkdev_read_folio(struct file *file, struct folio *folio) { - return iomap_read_folio(folio, &blkdev_iomap_ops); + return iomap_read_folio(folio, &blkdev_iomap_ops, NULL); } static void blkdev_readahead(struct readahead_control *rac) { - iomap_readahead(rac, &blkdev_iomap_ops); + iomap_readahead(rac, &blkdev_iomap_ops, NULL); } static int blkdev_map_blocks(struct iomap_writepage_ctx *wpc, diff --git a/fs/erofs/data.c b/fs/erofs/data.c index 0cd6b5c4df98..b0f0db855971 100644 --- a/fs/erofs/data.c +++ b/fs/erofs/data.c @@ -370,12 +370,12 @@ int erofs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, */ static int erofs_read_folio(struct file *file, struct folio *folio) { - return iomap_read_folio(folio, &erofs_iomap_ops); + return iomap_read_folio(folio, &erofs_iomap_ops, NULL); } static void erofs_readahead(struct readahead_control *rac) { - return iomap_readahead(rac, &erofs_iomap_ops); + return iomap_readahead(rac, &erofs_iomap_ops, NULL); } static sector_t erofs_bmap(struct address_space *mapping, sector_t block) diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index 68fc8af14700..f0debbe048a6 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c @@ -422,7 +422,7 @@ static int gfs2_read_folio(struct file *file, struct folio *folio) if (!gfs2_is_jdata(ip) || (i_blocksize(inode) == PAGE_SIZE && !folio_buffers(folio))) { - error = iomap_read_folio(folio, &gfs2_iomap_ops); + error = iomap_read_folio(folio, &gfs2_iomap_ops, NULL); } else if (gfs2_is_stuffed(ip)) { error = stuffed_read_folio(ip, folio); } else { @@ -497,7 +497,7 @@ static void gfs2_readahead(struct readahead_control *rac) else if (gfs2_is_jdata(ip)) mpage_readahead(rac, gfs2_block_map); else - iomap_readahead(rac, &gfs2_iomap_ops); + iomap_readahead(rac, &gfs2_iomap_ops, NULL); } /** diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c index 4abff64998fe..804527dcc9ba 100644 --- a/fs/iomap/buffered-io.c +++ b/fs/iomap/buffered-io.c @@ -320,7 +320,9 @@ struct iomap_readpage_ctx { struct folio *cur_folio; bool cur_folio_in_bio; struct bio *bio; + loff_t bio_start_pos; struct readahead_control *rac; + const struct iomap_read_folio_ops *ops; }; /** @@ -362,6 +364,15 @@ static inline bool iomap_block_needs_zeroing(const struct iomap_iter *iter, pos >= i_size_read(iter->inode); } +static void iomap_read_submit_bio(const struct iomap_iter *iter, + struct iomap_readpage_ctx *ctx) +{ + if (ctx->ops && ctx->ops->submit_io) + ctx->ops->submit_io(iter->inode, ctx->bio, ctx->bio_start_pos); + else + submit_bio(ctx->bio); +} + static loff_t iomap_readpage_iter(const struct iomap_iter *iter, struct iomap_readpage_ctx *ctx, loff_t offset) { @@ -405,8 +416,9 @@ static loff_t iomap_readpage_iter(const struct iomap_iter *iter, unsigned int nr_vecs = DIV_ROUND_UP(length, PAGE_SIZE); if (ctx->bio) - submit_bio(ctx->bio); + iomap_read_submit_bio(iter, ctx); + ctx->bio_start_pos = offset; if (ctx->rac) /* same as readahead_gfp_mask */ gfp |= __GFP_NORETRY | __GFP_NOWARN; ctx->bio = bio_alloc(iomap->bdev, bio_max_segs(nr_vecs), @@ -455,7 +467,8 @@ static loff_t iomap_read_folio_iter(const struct iomap_iter *iter, return done; } -int iomap_read_folio(struct folio *folio, const struct iomap_ops *ops) +int iomap_read_folio(struct folio *folio, const struct iomap_ops *ops, + const struct iomap_read_folio_ops *read_folio_ops) { struct iomap_iter iter = { .inode = folio->mapping->host, @@ -464,6 +477,7 @@ int iomap_read_folio(struct folio *folio, const struct iomap_ops *ops) }; struct iomap_readpage_ctx ctx = { .cur_folio = folio, + .ops = read_folio_ops, }; int ret; @@ -473,7 +487,7 @@ int iomap_read_folio(struct folio *folio, const struct iomap_ops *ops) iter.processed = iomap_read_folio_iter(&iter, &ctx); if (ctx.bio) { - submit_bio(ctx.bio); + iomap_read_submit_bio(&iter, &ctx); WARN_ON_ONCE(!ctx.cur_folio_in_bio); } else { WARN_ON_ONCE(ctx.cur_folio_in_bio); @@ -518,6 +532,7 @@ static loff_t iomap_readahead_iter(const struct iomap_iter *iter, * iomap_readahead - Attempt to read pages from a file. * @rac: Describes the pages to be read. * @ops: The operations vector for the filesystem. + * @read_folio_ops: Function hooks for filesystems for special bio submissions * * This function is for filesystems to call to implement their readahead * address_space operation. @@ -529,7 +544,8 @@ static loff_t iomap_readahead_iter(const struct iomap_iter *iter, * function is called with memalloc_nofs set, so allocations will not cause * the filesystem to be reentered. */ -void iomap_readahead(struct readahead_control *rac, const struct iomap_ops *ops) +void iomap_readahead(struct readahead_control *rac, const struct iomap_ops *ops, + const struct iomap_read_folio_ops *read_folio_ops) { struct iomap_iter iter = { .inode = rac->mapping->host, @@ -538,6 +554,7 @@ void iomap_readahead(struct readahead_control *rac, const struct iomap_ops *ops) }; struct iomap_readpage_ctx ctx = { .rac = rac, + .ops = read_folio_ops, }; trace_iomap_readahead(rac->mapping->host, readahead_count(rac)); @@ -546,7 +563,7 @@ void iomap_readahead(struct readahead_control *rac, const struct iomap_ops *ops) iter.processed = iomap_readahead_iter(&iter, &ctx); if (ctx.bio) - submit_bio(ctx.bio); + iomap_read_submit_bio(&iter, &ctx); if (ctx.cur_folio) { if (!ctx.cur_folio_in_bio) folio_unlock(ctx.cur_folio); diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 8e60ceeb1520..3e42a684cce1 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -522,14 +522,14 @@ xfs_vm_read_folio( struct file *unused, struct folio *folio) { - return iomap_read_folio(folio, &xfs_read_iomap_ops); + return iomap_read_folio(folio, &xfs_read_iomap_ops, NULL); } STATIC void xfs_vm_readahead( struct readahead_control *rac) { - iomap_readahead(rac, &xfs_read_iomap_ops); + iomap_readahead(rac, &xfs_read_iomap_ops, NULL); } static int diff --git a/fs/zonefs/file.c b/fs/zonefs/file.c index 35166c92420c..a70fa1cecef8 100644 --- a/fs/zonefs/file.c +++ b/fs/zonefs/file.c @@ -112,12 +112,12 @@ static const struct iomap_ops zonefs_write_iomap_ops = { static int zonefs_read_folio(struct file *unused, struct folio *folio) { - return iomap_read_folio(folio, &zonefs_read_iomap_ops); + return iomap_read_folio(folio, &zonefs_read_iomap_ops, NULL); } static void zonefs_readahead(struct readahead_control *rac) { - iomap_readahead(rac, &zonefs_read_iomap_ops); + iomap_readahead(rac, &zonefs_read_iomap_ops, NULL); } /* diff --git a/include/linux/iomap.h b/include/linux/iomap.h index b4be07e8ec94..2930861d1ef1 100644 --- a/include/linux/iomap.h +++ b/include/linux/iomap.h @@ -303,8 +303,20 @@ static inline bool iomap_want_unshare_iter(const struct iomap_iter *iter) ssize_t iomap_file_buffered_write(struct kiocb *iocb, struct iov_iter *from, const struct iomap_ops *ops, void *private); -int iomap_read_folio(struct folio *folio, const struct iomap_ops *ops); -void iomap_readahead(struct readahead_control *, const struct iomap_ops *ops); + +struct iomap_read_folio_ops { + /* + * Optional, allows the filesystem to perform a custom submission of + * bio, such as csum calculations or multi-device bio split + */ + void (*submit_io)(struct inode *inode, struct bio *bio, + loff_t file_offset); +}; + +int iomap_read_folio(struct folio *folio, const struct iomap_ops *ops, + const struct iomap_read_folio_ops *); +void iomap_readahead(struct readahead_control *, const struct iomap_ops *ops, + const struct iomap_read_folio_ops *); bool iomap_is_partially_uptodate(struct folio *, size_t from, size_t count); struct folio *iomap_get_folio(struct iomap_iter *iter, loff_t pos, size_t len); bool iomap_release_folio(struct folio *folio, gfp_t gfp_flags); From patchwork Mon Feb 3 09:43:07 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Hellwig X-Patchwork-Id: 13957145 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A6B311FF619; Mon, 3 Feb 2025 09:43:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.137.202.133 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738575817; cv=none; b=h55CrgQzI/oDS3XvShWHXI7WKUlrMTEBqLgNsM4oSr1yJc2vjkSWktWZQf2q2uaaPlBC1vL41Og6ZTzrC9Q207RoHSravLxFiMyFoftVvPc7hxRLM8HvoVXiQYtgztrUj6XutmduXRfTc3BiOo1T6AE4r0NXtjlSQ+RBEGptub4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738575817; c=relaxed/simple; bh=WbPOZY/3NRfUnKFn1TQ7znkwH2q8Lwcv2m9OLFIL/k8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MNHeuEDzgspJ771ESXd6Dh9Qb/wREmHBngOgH6U/dPw/vYWAttmB/7lOgYk3uiQwxmAWZghqW8EOfViz55kSAGPuA37HOgy9UQePyfX5aM2j8lm3hMmeL8EX22cDt5KzEimlb1asdicYqhDRUjiBQ/HBmkaurSnHSYv6UxNyRfc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=lst.de; spf=none smtp.mailfrom=bombadil.srs.infradead.org; dkim=pass (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b=x+VTF81G; arc=none smtp.client-ip=198.137.202.133 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=lst.de Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=bombadil.srs.infradead.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b="x+VTF81G" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20210309; h=Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Sender :Reply-To:Content-Type:Content-ID:Content-Description; bh=j8azhDW1wfzhNKmZcgt1wCHCrfjnFNGdrafHVpplpj8=; b=x+VTF81GFTJNz7eyf2mP2toROZ SHEpdIriXlpHPjfR2H/lPizBozCUfb47JUEMZYI6xe8RskjjGa6izSkNFGDYFctDd5iJv0eYJ0Acm vIiRA839HuJ3RBflsi7Sw2fldHGeysVYxkUy4UvLa9TdbTNGpxBugQ2YtgzDFGvdrWoAIlOfNUU+2 LDC4fGCPtHfP0Okq5wfskXbXoBlxkpNGxO0cXCUsU4QDmUbq2yfua7DQxjSRIQiWm4ERI8i2IkOM3 uLSdGv8pfbTbbGyIadvaZh/tgCbLNsQPBhm5QcgdIJ0xZ7HQSNTAmRlJOsMAo10ZD71iYzVfpVHEZ MJAodGUQ==; Received: from 2a02-8389-2341-5b80-b79f-eb9e-0b40-3aae.cable.dynamic.v6.surfer.at ([2a02:8389:2341:5b80:b79f:eb9e:b40:3aae] helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.98 #2 (Red Hat Linux)) id 1teszM-0000000F1hg-2CwK; Mon, 03 Feb 2025 09:43:32 +0000 From: Christoph Hellwig To: Kanchan Joshi , "Martin K . Petersen" Cc: Johannes Thumshirn , Qu Wenruo , Goldwyn Rodrigues , linux-block@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-xfs@vger.kernel.org Subject: [PATCH 3/7] iomap: add bioset in iomap_read_folio_ops for filesystems to use own bioset Date: Mon, 3 Feb 2025 10:43:07 +0100 Message-ID: <20250203094322.1809766-4-hch@lst.de> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250203094322.1809766-1-hch@lst.de> References: <20250203094322.1809766-1-hch@lst.de> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html From: Goldwyn Rodrigues Allocate the bio from the bioset provided in iomap_read_folio_ops. If no bioset is provided, fs_bio_set is used which is the standard bioset for filesystems. Signed-off-by: Goldwyn Rodrigues [hch: factor out two helpers] Signed-off-by: Christoph Hellwig --- fs/iomap/buffered-io.c | 51 ++++++++++++++++++++++++++++-------------- include/linux/iomap.h | 6 +++++ 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c index 804527dcc9ba..eaffa23eb8e4 100644 --- a/fs/iomap/buffered-io.c +++ b/fs/iomap/buffered-io.c @@ -364,6 +364,39 @@ static inline bool iomap_block_needs_zeroing(const struct iomap_iter *iter, pos >= i_size_read(iter->inode); } +static struct bio_set *iomap_read_bio_set(struct iomap_readpage_ctx *ctx) +{ + if (ctx->ops && ctx->ops->bio_set) + return ctx->ops->bio_set; + return &fs_bio_set; +} + +static struct bio *iomap_read_alloc_bio(const struct iomap_iter *iter, + struct iomap_readpage_ctx *ctx, loff_t length) +{ + unsigned int nr_vecs = DIV_ROUND_UP(length, PAGE_SIZE); + struct block_device *bdev = iter->iomap.bdev; + struct bio_set *bio_set = iomap_read_bio_set(ctx); + gfp_t gfp = mapping_gfp_constraint(iter->inode->i_mapping, GFP_KERNEL); + gfp_t orig_gfp = gfp; + struct bio *bio; + + if (ctx->rac) /* same as readahead_gfp_mask */ + gfp |= __GFP_NORETRY | __GFP_NOWARN; + + bio = bio_alloc_bioset(bdev, bio_max_segs(nr_vecs), REQ_OP_READ, gfp, + bio_set); + + /* + * If the bio_alloc fails, try it again for a single page to avoid + * having to deal with partial page reads. This emulates what + * do_mpage_read_folio does. + */ + if (!bio) + bio = bio_alloc_bioset(bdev, 1, REQ_OP_READ, orig_gfp, bio_set); + return bio; +} + static void iomap_read_submit_bio(const struct iomap_iter *iter, struct iomap_readpage_ctx *ctx) { @@ -411,27 +444,11 @@ static loff_t iomap_readpage_iter(const struct iomap_iter *iter, if (!ctx->bio || bio_end_sector(ctx->bio) != sector || !bio_add_folio(ctx->bio, folio, plen, poff)) { - gfp_t gfp = mapping_gfp_constraint(folio->mapping, GFP_KERNEL); - gfp_t orig_gfp = gfp; - unsigned int nr_vecs = DIV_ROUND_UP(length, PAGE_SIZE); - if (ctx->bio) iomap_read_submit_bio(iter, ctx); ctx->bio_start_pos = offset; - if (ctx->rac) /* same as readahead_gfp_mask */ - gfp |= __GFP_NORETRY | __GFP_NOWARN; - ctx->bio = bio_alloc(iomap->bdev, bio_max_segs(nr_vecs), - REQ_OP_READ, gfp); - /* - * If the bio_alloc fails, try it again for a single page to - * avoid having to deal with partial page reads. This emulates - * what do_mpage_read_folio does. - */ - if (!ctx->bio) { - ctx->bio = bio_alloc(iomap->bdev, 1, REQ_OP_READ, - orig_gfp); - } + ctx->bio = iomap_read_alloc_bio(iter, ctx, length); if (ctx->rac) ctx->bio->bi_opf |= REQ_RAHEAD; ctx->bio->bi_iter.bi_sector = sector; diff --git a/include/linux/iomap.h b/include/linux/iomap.h index 2930861d1ef1..304be88ecd23 100644 --- a/include/linux/iomap.h +++ b/include/linux/iomap.h @@ -311,6 +311,12 @@ struct iomap_read_folio_ops { */ void (*submit_io)(struct inode *inode, struct bio *bio, loff_t file_offset); + + /* + * Optional, allows filesystem to specify own bio_set, so new bio's + * can be allocated from the provided bio_set. + */ + struct bio_set *bio_set; }; int iomap_read_folio(struct folio *folio, const struct iomap_ops *ops, From patchwork Mon Feb 3 09:43:08 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Hellwig X-Patchwork-Id: 13957146 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 112C21FF7BE; Mon, 3 Feb 2025 09:43:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.137.202.133 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738575817; cv=none; b=rQENm62m9L2XSo1MoF3fwv6I+7uMvCZrqxonD3aQuQdfiUlCum3PnDN6Y56ozJx5XCf/PbqYuRp5dzrbv9rq4655CBarezv0b+LXv4NQF4uB9U9T6+AUKowzJX4XOYDOhaNKXYVG8ArWnJu5epe+ppyS+ZQ7qcVUY0ac2s9bFUE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738575817; c=relaxed/simple; bh=dekFVcIuGm6tnqBZrNBZBrUw3En5mjA9/CX0fzauhWY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DGWn8qVAS7vzcIWxXh21gzN8Ir1kg+T2ZCWFGGNsdvT3LD5uXvtE96XCS2gjbJDZgItbTvT5tDkpi+sL78p98Nv8CNHeYXU2w1CHPzf16/On5ldBnBinnb3ZV3SU3LKQhMuxo/E/unPkgbPDIeBNBkAyx0SEEm2wLlKeGmlRBMQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=lst.de; spf=none smtp.mailfrom=bombadil.srs.infradead.org; dkim=pass (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b=fu1P+0/d; arc=none smtp.client-ip=198.137.202.133 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=lst.de Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=bombadil.srs.infradead.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b="fu1P+0/d" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20210309; h=Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Sender :Reply-To:Content-Type:Content-ID:Content-Description; bh=8NmXlknxBJgQexTpKRVq32zBS3NbysG30WlEU8TZT1s=; b=fu1P+0/dYklKsDHT0RwrOxZMKI cU4SEhbiUKy7xwDGQetFmANPDkwy/BR3OBlQhW6/Xs8UmUo01YJdHwpDQdW+PoYqcioSdkU8c9bel L+/2Ckug55fnorlE8EyU3Cc0ce4YPE33ywOH1AoC7DNBQag0iKWYq25GccOfFs/rf98//9VQXvEMl xRCD8gdS62IJkYNGCyh/myRpR41MTkEocB/ka0hFqvUGf6vvyA88EtBwGcpumzlXwB583DYqaS2U4 SjBs36LKettLZTLjwT3LcGDLoPbZGY0W5r4vnkz7ooikWJXvAuSLjuBX6FjYmO2YKsf7K11b/WREe nEQxo3NQ==; Received: from 2a02-8389-2341-5b80-b79f-eb9e-0b40-3aae.cable.dynamic.v6.surfer.at ([2a02:8389:2341:5b80:b79f:eb9e:b40:3aae] helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.98 #2 (Red Hat Linux)) id 1teszP-0000000F1hy-0P3t; Mon, 03 Feb 2025 09:43:35 +0000 From: Christoph Hellwig To: Kanchan Joshi , "Martin K . Petersen" Cc: Johannes Thumshirn , Qu Wenruo , Goldwyn Rodrigues , linux-block@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-xfs@vger.kernel.org Subject: [PATCH 4/7] iomap: support ioends for reads Date: Mon, 3 Feb 2025 10:43:08 +0100 Message-ID: <20250203094322.1809766-5-hch@lst.de> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250203094322.1809766-1-hch@lst.de> References: <20250203094322.1809766-1-hch@lst.de> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html Support using the ioend structure to defer I/O completion for reads in addition to writes. This requires a check for the operation to not merge reads and writes, and for buffere I/O a call into the buffered read I/O completion handler from iomap_finish_ioend. For direct I/O the existing call into the direct I/O completion handler handles reads just fine already. Signed-off-by: Christoph Hellwig --- fs/iomap/buffered-io.c | 23 ++++++++++++++++++----- fs/iomap/internal.h | 3 ++- fs/iomap/ioend.c | 6 +++++- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c index eaffa23eb8e4..06990e012884 100644 --- a/fs/iomap/buffered-io.c +++ b/fs/iomap/buffered-io.c @@ -306,14 +306,27 @@ static void iomap_finish_folio_read(struct folio *folio, size_t off, folio_end_read(folio, uptodate); } -static void iomap_read_end_io(struct bio *bio) +static u32 __iomap_read_end_io(struct bio *bio, int error) { - int error = blk_status_to_errno(bio->bi_status); struct folio_iter fi; + u32 folio_count = 0; - bio_for_each_folio_all(fi, bio) + bio_for_each_folio_all(fi, bio) { iomap_finish_folio_read(fi.folio, fi.offset, fi.length, error); + folio_count++; + } bio_put(bio); + return folio_count; +} + +static void iomap_read_end_io(struct bio *bio) +{ + __iomap_read_end_io(bio, blk_status_to_errno(bio->bi_status)); +} + +u32 iomap_finish_ioend_buffered_read(struct iomap_ioend *ioend) +{ + return __iomap_read_end_io(&ioend->io_bio, ioend->io_error); } struct iomap_readpage_ctx { @@ -1568,7 +1581,7 @@ static void iomap_finish_folio_write(struct inode *inode, struct folio *folio, * state, release holds on bios, and finally free up memory. Do not use the * ioend after this. */ -u32 iomap_finish_ioend_buffered(struct iomap_ioend *ioend) +u32 iomap_finish_ioend_buffered_write(struct iomap_ioend *ioend) { struct inode *inode = ioend->io_inode; struct bio *bio = &ioend->io_bio; @@ -1600,7 +1613,7 @@ static void iomap_writepage_end_bio(struct bio *bio) struct iomap_ioend *ioend = iomap_ioend_from_bio(bio); ioend->io_error = blk_status_to_errno(bio->bi_status); - iomap_finish_ioend_buffered(ioend); + iomap_finish_ioend_buffered_write(ioend); } /* diff --git a/fs/iomap/internal.h b/fs/iomap/internal.h index f6992a3bf66a..c824e74a3526 100644 --- a/fs/iomap/internal.h +++ b/fs/iomap/internal.h @@ -4,7 +4,8 @@ #define IOEND_BATCH_SIZE 4096 -u32 iomap_finish_ioend_buffered(struct iomap_ioend *ioend); +u32 iomap_finish_ioend_buffered_read(struct iomap_ioend *ioend); +u32 iomap_finish_ioend_buffered_write(struct iomap_ioend *ioend); u32 iomap_finish_ioend_direct(struct iomap_ioend *ioend); #endif /* _IOMAP_INTERNAL_H */ diff --git a/fs/iomap/ioend.c b/fs/iomap/ioend.c index 18894ebba6db..2dd29403dc10 100644 --- a/fs/iomap/ioend.c +++ b/fs/iomap/ioend.c @@ -44,7 +44,9 @@ static u32 iomap_finish_ioend(struct iomap_ioend *ioend, int error) return 0; if (ioend->io_flags & IOMAP_IOEND_DIRECT) return iomap_finish_ioend_direct(ioend); - return iomap_finish_ioend_buffered(ioend); + if (bio_op(&ioend->io_bio) == REQ_OP_READ) + return iomap_finish_ioend_buffered_read(ioend); + return iomap_finish_ioend_buffered_write(ioend); } /* @@ -83,6 +85,8 @@ EXPORT_SYMBOL_GPL(iomap_finish_ioends); static bool iomap_ioend_can_merge(struct iomap_ioend *ioend, struct iomap_ioend *next) { + if (bio_op(&ioend->io_bio) != bio_op(&next->io_bio)) + return false; if (ioend->io_bio.bi_status != next->io_bio.bi_status) return false; if (next->io_flags & IOMAP_IOEND_BOUNDARY) From patchwork Mon Feb 3 09:43:09 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Hellwig X-Patchwork-Id: 13957147 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 813E21FF7D9; Mon, 3 Feb 2025 09:43:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.137.202.133 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738575820; cv=none; b=QHtudFy0EC5W+USluk/+INQplDu/FC/A7kC6GpYOXo/PWkNW47CLfFRiAUZhiJjGGQYgbTB0RjcLHqUpFI1cgfrBuvS9m7zmSsEuIsll16GzjlPtAdtVVY/+Qez985su8fDb6Dw9ODxRLRBXqsrci/jIqWuWhP7rW9p4ZV5/zpQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738575820; c=relaxed/simple; bh=0H7R/32qBR1ABcEaLP7uvDEdcLC7fV1gh8NLN+pNmEY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Fc/q2ygAQXibmEx56qhq9LCRBmjyz5ijbjyH0j7NZ0KHdGUXUouPE4b/Qtgd/WKx4oxowzwwpR4dT5voX5ShaWGoaba/ZgRNU0Lt3y5RJFggwZ8/c+kz+wZb7zlwc7+9Wwene+5sWRmq1bGGq/wCX3DNJ0sjv06++2Mm4pMUPeA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=lst.de; spf=none smtp.mailfrom=bombadil.srs.infradead.org; dkim=pass (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b=YAKFcexV; arc=none smtp.client-ip=198.137.202.133 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=lst.de Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=bombadil.srs.infradead.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b="YAKFcexV" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20210309; h=Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Sender :Reply-To:Content-Type:Content-ID:Content-Description; bh=6K5gePAiaQ8jDiZJyI7dOxfUjMmC+tI4lc9G9PArXnY=; b=YAKFcexVM0Gjs5Y8o3MVjlaJwI K/8jSb5D5y9VzAS4OUBEo5eSLGq+ckNOCiz8BO6ndSpAf+e5hO4DRakhcxMcbXOS7y+dT9Coa2krQ v4SS7XsaQKGvmnIeQdkgLts+8dhLoLH/Ko7lEZQ3lsvvSrgYv0p8qI7sgDt3EI61WeaV01V3l16of dQsg6YKoq/v+7fXKw7tpB2KMjdvdG/Er3KBX2IuhFDlGies7RxJEDOgPWheKUTfJAUDU73CK9y1hV hIw0WBUDhCk5I42YBJ8ApNcJZK5sYH/x1rvHUBkhQgZtbP/ONwEnkyjcmo1oAnPO9JiCPzuSql88P Sf+nDSlw==; Received: from 2a02-8389-2341-5b80-b79f-eb9e-0b40-3aae.cable.dynamic.v6.surfer.at ([2a02:8389:2341:5b80:b79f:eb9e:b40:3aae] helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.98 #2 (Red Hat Linux)) id 1teszS-0000000F1iQ-2hRv; Mon, 03 Feb 2025 09:43:39 +0000 From: Christoph Hellwig To: Kanchan Joshi , "Martin K . Petersen" Cc: Johannes Thumshirn , Qu Wenruo , Goldwyn Rodrigues , linux-block@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-xfs@vger.kernel.org Subject: [PATCH 5/7] iomap: limit buffered I/O size to 128M Date: Mon, 3 Feb 2025 10:43:09 +0100 Message-ID: <20250203094322.1809766-6-hch@lst.de> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250203094322.1809766-1-hch@lst.de> References: <20250203094322.1809766-1-hch@lst.de> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html Currently iomap can build extremely large bios (I've seen sizes up to 480MB). Limit this to a lower bound so that the soon to be added per-ioend integrity buffer doesn't go beyond what the page allocator can support. Signed-off-by: Christoph Hellwig --- fs/iomap/buffered-io.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c index 06990e012884..71bb676d4998 100644 --- a/fs/iomap/buffered-io.c +++ b/fs/iomap/buffered-io.c @@ -456,6 +456,7 @@ static loff_t iomap_readpage_iter(const struct iomap_iter *iter, sector = iomap_sector(iomap, pos); if (!ctx->bio || bio_end_sector(ctx->bio) != sector || + ctx->bio->bi_iter.bi_size > SZ_128M || !bio_add_folio(ctx->bio, folio, plen, poff)) { if (ctx->bio) iomap_read_submit_bio(iter, ctx); @@ -1674,6 +1675,8 @@ static struct iomap_ioend *iomap_alloc_ioend(struct iomap_writepage_ctx *wpc, static bool iomap_can_add_to_ioend(struct iomap_writepage_ctx *wpc, loff_t pos, u16 ioend_flags) { + if (wpc->ioend->io_bio.bi_iter.bi_size > SZ_128M) + return false; if (ioend_flags & IOMAP_IOEND_BOUNDARY) return false; if ((ioend_flags & IOMAP_IOEND_NOMERGE_FLAGS) != From patchwork Mon Feb 3 09:43:10 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Hellwig X-Patchwork-Id: 13957148 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1336F1FFC4C; Mon, 3 Feb 2025 09:43:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.137.202.133 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738575824; cv=none; b=EXUD6x3MNRQbmguhaH7D3RYTgqnb0KS5ol3DyTavYESoL19z0w+V6SwNmochSq0iyXaXXrOyIL+o6uh/u9elP04hAdIfoRNx/UmwOzo1vR4328of3lYdyDAQcIhedOWurZevOeYTG3/TR3m7b0l8vzNfvXVktpTXApy81ZVoXVA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738575824; c=relaxed/simple; bh=eWgMtLSItRFRCilpI5gkDAfvNqJI7R7VVvazggB1HDM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GHo08XA70MyH1D5A/7i2+UP7fSomXOuSIJW+clvcVcvD5A80w6q+aE2LfM005TGokjoKOtPF2H5vFvV8ZdOnhoKb/9e9PXc0ezgMGN78es2DbNj5wUiVZIG8daJESOj6Nph4htlxwsDiXSs63NYpJ8pkYMSt5T0tpR4GiMPmn7A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=lst.de; spf=none smtp.mailfrom=bombadil.srs.infradead.org; dkim=pass (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b=1BJo2zXK; arc=none smtp.client-ip=198.137.202.133 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=lst.de Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=bombadil.srs.infradead.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b="1BJo2zXK" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20210309; h=Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Sender :Reply-To:Content-Type:Content-ID:Content-Description; bh=FcXkIA/5Yfj+mlhdUB2rXIYPv6sZBOXhbPnnA7cZBDk=; b=1BJo2zXK/VRXdBOv4FSllrnv7k /3uZsytlF4JSwnFgawnglAOAX6ZJKJ9xC/MYH8Vj2kwRo81qBmlqu20O1QCC+vEYjIgXcTgbfU2GK DtylnMGp3tdJjzayzrEEdvhkw0u4AiEyE32lB40ikYT9EFDXjsqZavCTQmyjuSDS3Yj0zVn7kfWDT Oj+zab/pKiSoftKUvDbT3n/2r8/EWjIWjDT4gKkQjR65LvVn6+sAIfqxzcVmExhWx1X0V2sXEjKPY Y6DsJQXr65imevvpnGpl1s9V8e15QjDaSaAPSM03xxi6SmGdjvqHWjFbVSYn6XxCvAqZM0PMWfeaz beNq4mPg==; Received: from 2a02-8389-2341-5b80-b79f-eb9e-0b40-3aae.cable.dynamic.v6.surfer.at ([2a02:8389:2341:5b80:b79f:eb9e:b40:3aae] helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.98 #2 (Red Hat Linux)) id 1teszV-0000000F1jm-28pr; Mon, 03 Feb 2025 09:43:41 +0000 From: Christoph Hellwig To: Kanchan Joshi , "Martin K . Petersen" Cc: Johannes Thumshirn , Qu Wenruo , Goldwyn Rodrigues , linux-block@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-xfs@vger.kernel.org Subject: [PATCH 6/7] xfs: support T10 protection information Date: Mon, 3 Feb 2025 10:43:10 +0100 Message-ID: <20250203094322.1809766-7-hch@lst.de> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250203094322.1809766-1-hch@lst.de> References: <20250203094322.1809766-1-hch@lst.de> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html Add support for generating / verifying protection information in the file system. This is done by hooking into the bio submission in iomap and then using the generic PI helpers. Compared to just using the block layer auto PI this extends the protection envelope and also prepares for eventually passing through PI from userspace at least for direct I/O. Right now this is still pretty hacky, e.g. the single PI buffer can get pretty gigantic and has no mempool backing it. The deferring of I/O completions is done unconditionally instead only when needed, and we assume the device can actually handle these huge segments. The latter should be fixed by doing proper splitting based on metadata limits in the block layer, but the rest needs to be addressed here. Signed-off-by: Christoph Hellwig --- fs/xfs/Makefile | 1 + fs/xfs/xfs_aops.c | 29 +++++++++++++++-- fs/xfs/xfs_aops.h | 1 + fs/xfs/xfs_data_csum.c | 73 ++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_data_csum.h | 7 ++++ fs/xfs/xfs_file.c | 27 +++++++++++++++- fs/xfs/xfs_inode.h | 6 ++-- 7 files changed, 136 insertions(+), 8 deletions(-) create mode 100644 fs/xfs/xfs_data_csum.c create mode 100644 fs/xfs/xfs_data_csum.h diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index 7afa51e41427..aa8749d640e7 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -73,6 +73,7 @@ xfs-y += xfs_aops.o \ xfs_bmap_util.o \ xfs_bio_io.o \ xfs_buf.o \ + xfs_data_csum.o \ xfs_dahash_test.o \ xfs_dir2_readdir.o \ xfs_discard.o \ diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 3e42a684cce1..291f5d4dbce6 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -19,6 +19,7 @@ #include "xfs_reflink.h" #include "xfs_errortag.h" #include "xfs_error.h" +#include "xfs_data_csum.h" struct xfs_writepage_ctx { struct iomap_writepage_ctx ctx; @@ -122,6 +123,11 @@ xfs_end_ioend( goto done; } + if (bio_op(&ioend->io_bio) == REQ_OP_READ) { + error = xfs_data_csum_verify(ioend); + goto done; + } + /* * Success: commit the COW or unwritten blocks if needed. */ @@ -175,7 +181,7 @@ xfs_end_io( } } -STATIC void +void xfs_end_bio( struct bio *bio) { @@ -417,6 +423,8 @@ xfs_submit_ioend( memalloc_nofs_restore(nofs_flag); + xfs_data_csum_generate(&ioend->io_bio); + /* send ioends that might require a transaction to the completion wq */ if (xfs_ioend_is_append(ioend) || (ioend->io_flags & (IOMAP_IOEND_UNWRITTEN | IOMAP_IOEND_SHARED))) @@ -517,19 +525,34 @@ xfs_vm_bmap( return iomap_bmap(mapping, block, &xfs_read_iomap_ops); } +static void xfs_buffered_read_submit_io(struct inode *inode, + struct bio *bio, loff_t file_offset) +{ + xfs_data_csum_alloc(bio); + iomap_init_ioend(inode, bio, file_offset, 0); + bio->bi_end_io = xfs_end_bio; + submit_bio(bio); +} + +static const struct iomap_read_folio_ops xfs_iomap_read_ops = { + .bio_set = &iomap_ioend_bioset, + .submit_io = xfs_buffered_read_submit_io, +}; + STATIC int xfs_vm_read_folio( struct file *unused, struct folio *folio) { - return iomap_read_folio(folio, &xfs_read_iomap_ops, NULL); + return iomap_read_folio(folio, &xfs_read_iomap_ops, + &xfs_iomap_read_ops); } STATIC void xfs_vm_readahead( struct readahead_control *rac) { - iomap_readahead(rac, &xfs_read_iomap_ops, NULL); + iomap_readahead(rac, &xfs_read_iomap_ops, &xfs_iomap_read_ops); } static int diff --git a/fs/xfs/xfs_aops.h b/fs/xfs/xfs_aops.h index e0bd68419764..efed1ab59dbf 100644 --- a/fs/xfs/xfs_aops.h +++ b/fs/xfs/xfs_aops.h @@ -10,5 +10,6 @@ extern const struct address_space_operations xfs_address_space_operations; extern const struct address_space_operations xfs_dax_aops; int xfs_setfilesize(struct xfs_inode *ip, xfs_off_t offset, size_t size); +void xfs_end_bio(struct bio *bio); #endif /* __XFS_AOPS_H__ */ diff --git a/fs/xfs/xfs_data_csum.c b/fs/xfs/xfs_data_csum.c new file mode 100644 index 000000000000..d9d3620654b1 --- /dev/null +++ b/fs/xfs/xfs_data_csum.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2022-2025 Christoph Hellwig. + */ +#include "xfs.h" +#include "xfs_format.h" +#include "xfs_shared.h" +#include "xfs_trans_resv.h" +#include "xfs_mount.h" +#include "xfs_inode.h" +#include "xfs_cksum.h" +#include "xfs_data_csum.h" +#include +#include +#include + +void * +xfs_data_csum_alloc( + struct bio *bio) +{ + struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); + struct bio_integrity_payload *bip; + unsigned int buf_size; + void *buf; + + if (!bi) + return NULL; + + buf_size = bio_integrity_bytes(bi, bio_sectors(bio)); + /* XXX: this needs proper mempools */ + /* XXX: needs (partial) zeroing if tuple_size > csum_size */ + buf = kmalloc(buf_size, GFP_NOFS | __GFP_NOFAIL); + bip = bio_integrity_alloc(bio, GFP_NOFS | __GFP_NOFAIL, 1); + if (!bio_integrity_add_page(bio, virt_to_page(buf), buf_size, + offset_in_page(buf))) + WARN_ON_ONCE(1); + + if (bi->csum_type) { + if (bi->csum_type == BLK_INTEGRITY_CSUM_IP) + bip->bip_flags |= BIP_IP_CHECKSUM; + bip->bip_flags |= BIP_CHECK_GUARD; + } + if (bi->flags & BLK_INTEGRITY_REF_TAG) + bip->bip_flags |= BIP_CHECK_REFTAG; + bip_set_seed(bip, bio->bi_iter.bi_sector); + + return buf; +} + +void +xfs_data_csum_generate( + struct bio *bio) +{ + struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); + + if (!bi || !bi->csum_type) + return; + + xfs_data_csum_alloc(bio); + blk_integrity_generate(bio); +} + +int +xfs_data_csum_verify( + struct iomap_ioend *ioend) +{ + struct bio *bio = &ioend->io_bio; + struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); + + if (!bi || !bi->csum_type) + return 0; + return blk_integrity_verify_all(bio, ioend->io_sector); +} diff --git a/fs/xfs/xfs_data_csum.h b/fs/xfs/xfs_data_csum.h new file mode 100644 index 000000000000..f32215e8f46c --- /dev/null +++ b/fs/xfs/xfs_data_csum.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +struct iomap_ioend; + +void *xfs_data_csum_alloc(struct bio *bio); +void xfs_data_csum_generate(struct bio *bio); +int xfs_data_csum_verify(struct iomap_ioend *ioend); diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index f7a7d89c345e..0d64c54017f0 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -25,6 +25,8 @@ #include "xfs_iomap.h" #include "xfs_reflink.h" #include "xfs_file.h" +#include "xfs_data_csum.h" +#include "xfs_aops.h" #include #include @@ -227,6 +229,20 @@ xfs_ilock_iocb_for_write( return 0; } +static void xfs_dio_read_submit_io(const struct iomap_iter *iter, + struct bio *bio, loff_t file_offset) +{ + xfs_data_csum_alloc(bio); + iomap_init_ioend(iter->inode, bio, file_offset, IOMAP_IOEND_DIRECT); + bio->bi_end_io = xfs_end_bio; + submit_bio(bio); +} + +static const struct iomap_dio_ops xfs_dio_read_ops = { + .bio_set = &iomap_ioend_bioset, + .submit_io = xfs_dio_read_submit_io, +}; + STATIC ssize_t xfs_file_dio_read( struct kiocb *iocb, @@ -245,7 +261,8 @@ xfs_file_dio_read( ret = xfs_ilock_iocb(iocb, XFS_IOLOCK_SHARED); if (ret) return ret; - ret = iomap_dio_rw(iocb, to, &xfs_read_iomap_ops, NULL, 0, NULL, 0); + ret = iomap_dio_rw(iocb, to, &xfs_read_iomap_ops, &xfs_dio_read_ops, 0, + NULL, 0); xfs_iunlock(ip, XFS_IOLOCK_SHARED); return ret; @@ -578,8 +595,16 @@ xfs_dio_write_end_io( return error; } +static void xfs_dio_write_submit_io(const struct iomap_iter *iter, + struct bio *bio, loff_t file_offset) +{ + xfs_data_csum_generate(bio); + submit_bio(bio); +} + static const struct iomap_dio_ops xfs_dio_write_ops = { .end_io = xfs_dio_write_end_io, + .submit_io = xfs_dio_write_submit_io, }; /* diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index c08093a65352..ff346bbe454c 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -609,10 +609,8 @@ int xfs_break_layouts(struct inode *inode, uint *iolock, static inline void xfs_update_stable_writes(struct xfs_inode *ip) { - if (bdev_stable_writes(xfs_inode_buftarg(ip)->bt_bdev)) - mapping_set_stable_writes(VFS_I(ip)->i_mapping); - else - mapping_clear_stable_writes(VFS_I(ip)->i_mapping); + /* XXX: unconditional for now */ + mapping_set_stable_writes(VFS_I(ip)->i_mapping); } /* From patchwork Mon Feb 3 09:43:11 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Hellwig X-Patchwork-Id: 13957149 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8DE8B1FFC5F; Mon, 3 Feb 2025 09:43:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.137.202.133 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738575827; cv=none; b=ExeEMWq82VXU3m42rBPLiNlfHyFgKnnm2IeMB7qLsBvVpDBT/4gopVx5og5gtgDXOkEvxSPRHZwnaD2mvIL94O6CqbgY1sZtBo9bnyE281K2eC5fZuFmqa1Op8A5idaFhadPZSWHvyuZt8t8E/FYZj7RPWxoQ9ANE3sVDJ5D4yI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738575827; c=relaxed/simple; bh=dCXeVt8dRfbqbGCPB6sMufQYJnUBcCFfMLj5eq+b8vk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gqCm3qeDWd3nBfgp8VCI/sTD68N/y1a05QszJdh+64p3rCRlvyKUP7SbaHAdUU1xrvGOEQ6FJbGTADSOXYcv0FWdxYejZCG+VcviRjAhJSMNtNzLoDa4r+dSC/Ml7KSn0w1YO9iZxMBe+RS0WkfhsMV5kxvl6N+x4zvIJSZXi50= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=lst.de; spf=none smtp.mailfrom=bombadil.srs.infradead.org; dkim=pass (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b=4Ljqzspb; arc=none smtp.client-ip=198.137.202.133 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=lst.de Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=bombadil.srs.infradead.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b="4Ljqzspb" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20210309; h=Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Sender :Reply-To:Content-Type:Content-ID:Content-Description; bh=8sfW3RXcNW2wYU3qaS4CmyxX4fJw7263JCYLxDjNqIM=; b=4LjqzspbiHr0LX8gKdzlN7Mo7a zH/Ibi9sX70MS7OzjAWWcWtB9xsn0sWWZbi+8SGPIdDDOWrUaIBdoHUnZZPWQLFyHu7ykiai9DSli XDUDR2l+TqLmxWf/9fMe/APmYpXSNtY1ZwFlGzv0BrfV3WWLFq/00Z/FZ/pdqpYzMMZ5+5oxFUvN8 sHt4JSK1jN82koHs1aLfwXIvKpdLUNwDZsXuXHLIXfp0Nn2ABjXp4K62BtalUURngdQs01Mu4zwx4 i5AbIRVEXybAOLbwu25E+hUtXX7e4gBiUqenJOk1Wb+0EZjkaUXi7lze3t2xI/IVEzFO6Y43N89Vs IGzyVxpQ==; Received: from 2a02-8389-2341-5b80-b79f-eb9e-0b40-3aae.cable.dynamic.v6.surfer.at ([2a02:8389:2341:5b80:b79f:eb9e:b40:3aae] helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.98 #2 (Red Hat Linux)) id 1teszY-0000000F1kl-34oe; Mon, 03 Feb 2025 09:43:45 +0000 From: Christoph Hellwig To: Kanchan Joshi , "Martin K . Petersen" Cc: Johannes Thumshirn , Qu Wenruo , Goldwyn Rodrigues , linux-block@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-xfs@vger.kernel.org Subject: [PATCH 7/7] xfs: implement block-metadata based data checksums Date: Mon, 3 Feb 2025 10:43:11 +0100 Message-ID: <20250203094322.1809766-8-hch@lst.de> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250203094322.1809766-1-hch@lst.de> References: <20250203094322.1809766-1-hch@lst.de> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html This is a quick hack to demonstrate how data checksumming can be implemented when it can be stored in the out of line metadata for each logical block. It builds on top of the previous PI infrastructure and instead of generating/verifying protection information it simply generates and verifies a crc32c checksum and stores it in the non-PI metadata. It misses a feature bit in the superblock, checking that enough size is available in the metadata and many other things. Signed-off-by: Christoph Hellwig --- fs/xfs/xfs_data_csum.c | 79 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 76 insertions(+), 3 deletions(-) diff --git a/fs/xfs/xfs_data_csum.c b/fs/xfs/xfs_data_csum.c index d9d3620654b1..862388803398 100644 --- a/fs/xfs/xfs_data_csum.c +++ b/fs/xfs/xfs_data_csum.c @@ -14,6 +14,73 @@ #include #include +static inline void *xfs_csum_buf(struct bio *bio) +{ + return bvec_virt(bio_integrity(bio)->bip_vec); +} + +static inline __le32 +xfs_data_csum( + void *data, + unsigned int len) +{ + return xfs_end_cksum(crc32c(XFS_CRC_SEED, data, len)); +} + +static void +__xfs_data_csum_generate( + struct bio *bio) +{ + unsigned int ssize = bdev_logical_block_size(bio->bi_bdev); + __le32 *csum_buf = xfs_csum_buf(bio); + struct bvec_iter_all iter; + struct bio_vec *bv; + int c = 0; + + bio_for_each_segment_all(bv, bio, iter) { + void *p; + unsigned int off; + + p = bvec_kmap_local(bv); + for (off = 0; off < bv->bv_len; off += ssize) + csum_buf[c++] = xfs_data_csum(p + off, ssize); + kunmap_local(p); + } +} + +static int +__xfs_data_csum_verify( + struct bio *bio, + struct xfs_inode *ip, + xfs_off_t file_offset) +{ + unsigned int ssize = bdev_logical_block_size(bio->bi_bdev); + __le32 *csum_buf = xfs_csum_buf(bio); + int c = 0; + struct bvec_iter_all iter; + struct bio_vec *bv; + + bio_for_each_segment_all(bv, bio, iter) { + void *p; + unsigned int off; + + p = bvec_kmap_local(bv); + for (off = 0; off < bv->bv_len; off += ssize) { + if (xfs_data_csum(p + off, ssize) != csum_buf[c++]) { + kunmap_local(p); + xfs_warn(ip->i_mount, +"checksum mismatch at inode 0x%llx offset %lld", + ip->i_ino, file_offset); + return -EFSBADCRC; + } + file_offset += ssize; + } + kunmap_local(p); + } + + return 0; +} + void * xfs_data_csum_alloc( struct bio *bio) @@ -53,11 +120,14 @@ xfs_data_csum_generate( { struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); - if (!bi || !bi->csum_type) + if (!bi) return; xfs_data_csum_alloc(bio); - blk_integrity_generate(bio); + if (!bi->csum_type) + __xfs_data_csum_generate(bio); + else + blk_integrity_generate(bio); } int @@ -67,7 +137,10 @@ xfs_data_csum_verify( struct bio *bio = &ioend->io_bio; struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); - if (!bi || !bi->csum_type) + if (!bi) return 0; + if (!bi->csum_type) + return __xfs_data_csum_verify(&ioend->io_bio, + XFS_I(ioend->io_inode), ioend->io_offset); return blk_integrity_verify_all(bio, ioend->io_sector); }