* more integrity cleanups
@ 2024-06-28 13:27 Christoph Hellwig
2024-06-28 13:27 ` [PATCH 1/3] block: split integrity support out of bio.h Christoph Hellwig
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Christoph Hellwig @ 2024-06-28 13:27 UTC (permalink / raw)
To: Jens Axboe; +Cc: Martin K . Petersen, Anuj Gupta, Kanchan Joshi, linux-block
Hi Jens and Martin,
this series has more cleanups to the block layer integrity code.
It splits the bio integrity APIs into their own header as they are
only used by very few source files, cleans up their stubs a little
bit, and then in the last patch change when the bio_integrity_payload
is freed when it is not owned by the block layer. This avoids having
to know the submitter in the core code and will simplify adding other
consuer of the API like file systems or the io_uring non-passthrough
PI support.
It sits on top of the previously sumitted "integrity cleanups" series.
Diffstat:
block/bio-integrity.c | 56 ++++++---------
block/bio.c | 2
block/blk-map.c | 3
block/blk.h | 5 +
block/bounce.c | 2
drivers/md/dm.c | 1
drivers/nvme/host/ioctl.c | 1
drivers/scsi/sd.c | 3
include/linux/bio-integrity.h | 153 ++++++++++++++++++++++++++++++++++++++++++
include/linux/bio.h | 152 -----------------------------------------
include/linux/blk-integrity.h | 1
11 files changed, 192 insertions(+), 187 deletions(-)
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/3] block: split integrity support out of bio.h
2024-06-28 13:27 more integrity cleanups Christoph Hellwig
@ 2024-06-28 13:27 ` Christoph Hellwig
2024-06-28 13:27 ` [PATCH 2/3] block: also return bio_integrity_payload * from stubs Christoph Hellwig
2024-06-28 13:27 ` [PATCH 3/3] block: don't free submitter owned integrity payload on I/O completion Christoph Hellwig
2 siblings, 0 replies; 6+ messages in thread
From: Christoph Hellwig @ 2024-06-28 13:27 UTC (permalink / raw)
To: Jens Axboe; +Cc: Martin K . Petersen, Anuj Gupta, Kanchan Joshi, linux-block
Split struct bio_integrity_payload and the related prototypes out of
bio.h into a separate bio-integrity.h header so that it is only pulled
in by the few places that need it.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
block/bio.c | 2 +-
block/blk.h | 1 +
block/bounce.c | 2 +-
drivers/md/dm.c | 1 +
drivers/nvme/host/ioctl.c | 1 +
drivers/scsi/sd.c | 3 +-
include/linux/bio-integrity.h | 149 +++++++++++++++++++++++++++++++++
include/linux/bio.h | 152 ----------------------------------
include/linux/blk-integrity.h | 1 +
9 files changed, 157 insertions(+), 155 deletions(-)
create mode 100644 include/linux/bio-integrity.h
diff --git a/block/bio.c b/block/bio.c
index e9e809a63c5975..4ca3f31ce45fb5 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -4,7 +4,7 @@
*/
#include <linux/mm.h>
#include <linux/swap.h>
-#include <linux/bio.h>
+#include <linux/bio-integrity.h>
#include <linux/blkdev.h>
#include <linux/uio.h>
#include <linux/iocontext.h>
diff --git a/block/blk.h b/block/blk.h
index 47dadd2439b1ca..401e604f35d2cf 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -2,6 +2,7 @@
#ifndef BLK_INTERNAL_H
#define BLK_INTERNAL_H
+#include <linux/bio-integrity.h>
#include <linux/blk-crypto.h>
#include <linux/memblock.h> /* for max_pfn/max_low_pfn */
#include <linux/sched/sysctl.h>
diff --git a/block/bounce.c b/block/bounce.c
index d6a5219f29dd53..0d898cd5ec497f 100644
--- a/block/bounce.c
+++ b/block/bounce.c
@@ -10,7 +10,7 @@
#include <linux/export.h>
#include <linux/swap.h>
#include <linux/gfp.h>
-#include <linux/bio.h>
+#include <linux/bio-integrity.h>
#include <linux/pagemap.h>
#include <linux/mempool.h>
#include <linux/blkdev.h>
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 7d107ae06e1ae1..92d6eeb0a59327 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -11,6 +11,7 @@
#include "dm-uevent.h"
#include "dm-ima.h"
+#include <linux/bio-integrity.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mutex.h>
diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c
index 9d9d2a127c4ec2..f1d58e70933f54 100644
--- a/drivers/nvme/host/ioctl.c
+++ b/drivers/nvme/host/ioctl.c
@@ -3,6 +3,7 @@
* Copyright (c) 2011-2014, Intel Corporation.
* Copyright (c) 2017-2021 Christoph Hellwig.
*/
+#include <linux/bio-integrity.h>
#include <linux/ptrace.h> /* for force_successful_syscall_return */
#include <linux/nvme_ioctl.h>
#include <linux/io_uring/cmd.h>
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 525f48c97f5e15..977f761714d575 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -33,11 +33,12 @@
* than the level indicated above to trigger output.
*/
+#include <linux/bio-integrity.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/mm.h>
-#include <linux/bio.h>
+#include <linux/bio-integrity.h>
#include <linux/hdreg.h>
#include <linux/errno.h>
#include <linux/idr.h>
diff --git a/include/linux/bio-integrity.h b/include/linux/bio-integrity.h
new file mode 100644
index 00000000000000..0912f47f1d1eea
--- /dev/null
+++ b/include/linux/bio-integrity.h
@@ -0,0 +1,149 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_BIO_INTEGRITY_H
+#define _LINUX_BIO_INTEGRITY_H
+
+#include <linux/bio.h>
+
+enum bip_flags {
+ BIP_BLOCK_INTEGRITY = 1 << 0, /* block layer owns integrity data */
+ BIP_MAPPED_INTEGRITY = 1 << 1, /* ref tag has been remapped */
+ BIP_CTRL_NOCHECK = 1 << 2, /* disable HBA integrity checking */
+ BIP_DISK_NOCHECK = 1 << 3, /* disable disk integrity checking */
+ BIP_IP_CHECKSUM = 1 << 4, /* IP checksum */
+ BIP_INTEGRITY_USER = 1 << 5, /* Integrity payload is user address */
+ BIP_COPY_USER = 1 << 6, /* Kernel bounce buffer in use */
+};
+
+struct bio_integrity_payload {
+ struct bio *bip_bio; /* parent bio */
+
+ struct bvec_iter bip_iter;
+
+ unsigned short bip_vcnt; /* # of integrity bio_vecs */
+ unsigned short bip_max_vcnt; /* integrity bio_vec slots */
+ unsigned short bip_flags; /* control flags */
+
+ struct bvec_iter bio_iter; /* for rewinding parent bio */
+
+ struct work_struct bip_work; /* I/O completion */
+
+ struct bio_vec *bip_vec;
+ struct bio_vec bip_inline_vecs[];/* embedded bvec array */
+};
+
+#ifdef CONFIG_BLK_DEV_INTEGRITY
+
+#define bip_for_each_vec(bvl, bip, iter) \
+ for_each_bvec(bvl, (bip)->bip_vec, iter, (bip)->bip_iter)
+
+#define bio_for_each_integrity_vec(_bvl, _bio, _iter) \
+ for_each_bio(_bio) \
+ bip_for_each_vec(_bvl, _bio->bi_integrity, _iter)
+
+static inline struct bio_integrity_payload *bio_integrity(struct bio *bio)
+{
+ if (bio->bi_opf & REQ_INTEGRITY)
+ return bio->bi_integrity;
+
+ return NULL;
+}
+
+static inline bool bio_integrity_flagged(struct bio *bio, enum bip_flags flag)
+{
+ struct bio_integrity_payload *bip = bio_integrity(bio);
+
+ if (bip)
+ return bip->bip_flags & flag;
+
+ return false;
+}
+
+static inline sector_t bip_get_seed(struct bio_integrity_payload *bip)
+{
+ return bip->bip_iter.bi_sector;
+}
+
+static inline void bip_set_seed(struct bio_integrity_payload *bip,
+ sector_t seed)
+{
+ bip->bip_iter.bi_sector = seed;
+}
+
+struct bio_integrity_payload *bio_integrity_alloc(struct bio *bio, gfp_t gfp,
+ unsigned int nr);
+int bio_integrity_add_page(struct bio *bio, struct page *page, unsigned int len,
+ unsigned int offset);
+int bio_integrity_map_user(struct bio *bio, void __user *ubuf, ssize_t len, u32 seed);
+bool bio_integrity_prep(struct bio *bio);
+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);
+int bioset_integrity_create(struct bio_set *bs, int pool_size);
+void bioset_integrity_free(struct bio_set *bs);
+void bio_integrity_init(void);
+
+#else /* CONFIG_BLK_DEV_INTEGRITY */
+
+static inline void *bio_integrity(struct bio *bio)
+{
+ return NULL;
+}
+
+static inline int bioset_integrity_create(struct bio_set *bs, int pool_size)
+{
+ return 0;
+}
+
+static inline void bioset_integrity_free (struct bio_set *bs)
+{
+ return;
+}
+
+static inline int bio_integrity_map_user(struct bio *bio, void __user *ubuf,
+ ssize_t len, u32 seed)
+{
+ return -EINVAL;
+}
+
+static inline bool bio_integrity_prep(struct bio *bio)
+{
+ return true;
+}
+
+static inline int bio_integrity_clone(struct bio *bio, struct bio *bio_src,
+ gfp_t gfp_mask)
+{
+ return 0;
+}
+
+static inline void bio_integrity_advance(struct bio *bio,
+ unsigned int bytes_done)
+{
+}
+
+static inline void bio_integrity_trim(struct bio *bio)
+{
+}
+
+static inline void bio_integrity_init(void)
+{
+}
+
+static inline bool bio_integrity_flagged(struct bio *bio, enum bip_flags flag)
+{
+ return false;
+}
+
+static inline void *bio_integrity_alloc(struct bio * bio, gfp_t gfp,
+ unsigned int nr)
+{
+ return ERR_PTR(-EINVAL);
+}
+
+static inline int bio_integrity_add_page(struct bio *bio, struct page *page,
+ unsigned int len, unsigned int offset)
+{
+ return 0;
+}
+#endif /* CONFIG_BLK_DEV_INTEGRITY */
+#endif /* _LINUX_BIO_INTEGRITY_H */
diff --git a/include/linux/bio.h b/include/linux/bio.h
index d5379548d684e1..a46e2047bea4d2 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -321,69 +321,6 @@ static inline void bio_next_folio(struct folio_iter *fi, struct bio *bio)
#define bio_for_each_folio_all(fi, bio) \
for (bio_first_folio(&fi, bio, 0); fi.folio; bio_next_folio(&fi, bio))
-enum bip_flags {
- BIP_BLOCK_INTEGRITY = 1 << 0, /* block layer owns integrity data */
- BIP_MAPPED_INTEGRITY = 1 << 1, /* ref tag has been remapped */
- BIP_CTRL_NOCHECK = 1 << 2, /* disable HBA integrity checking */
- BIP_DISK_NOCHECK = 1 << 3, /* disable disk integrity checking */
- BIP_IP_CHECKSUM = 1 << 4, /* IP checksum */
- BIP_INTEGRITY_USER = 1 << 5, /* Integrity payload is user address */
- BIP_COPY_USER = 1 << 6, /* Kernel bounce buffer in use */
-};
-
-/*
- * bio integrity payload
- */
-struct bio_integrity_payload {
- struct bio *bip_bio; /* parent bio */
-
- struct bvec_iter bip_iter;
-
- unsigned short bip_vcnt; /* # of integrity bio_vecs */
- unsigned short bip_max_vcnt; /* integrity bio_vec slots */
- unsigned short bip_flags; /* control flags */
-
- struct bvec_iter bio_iter; /* for rewinding parent bio */
-
- struct work_struct bip_work; /* I/O completion */
-
- struct bio_vec *bip_vec;
- struct bio_vec bip_inline_vecs[];/* embedded bvec array */
-};
-
-#if defined(CONFIG_BLK_DEV_INTEGRITY)
-
-static inline struct bio_integrity_payload *bio_integrity(struct bio *bio)
-{
- if (bio->bi_opf & REQ_INTEGRITY)
- return bio->bi_integrity;
-
- return NULL;
-}
-
-static inline bool bio_integrity_flagged(struct bio *bio, enum bip_flags flag)
-{
- struct bio_integrity_payload *bip = bio_integrity(bio);
-
- if (bip)
- return bip->bip_flags & flag;
-
- return false;
-}
-
-static inline sector_t bip_get_seed(struct bio_integrity_payload *bip)
-{
- return bip->bip_iter.bi_sector;
-}
-
-static inline void bip_set_seed(struct bio_integrity_payload *bip,
- sector_t seed)
-{
- bip->bip_iter.bi_sector = seed;
-}
-
-#endif /* CONFIG_BLK_DEV_INTEGRITY */
-
void bio_trim(struct bio *bio, sector_t offset, sector_t size);
extern struct bio *bio_split(struct bio *bio, int sectors,
gfp_t gfp, struct bio_set *bs);
@@ -721,95 +658,6 @@ static inline bool bioset_initialized(struct bio_set *bs)
return bs->bio_slab != NULL;
}
-#if defined(CONFIG_BLK_DEV_INTEGRITY)
-
-#define bip_for_each_vec(bvl, bip, iter) \
- for_each_bvec(bvl, (bip)->bip_vec, iter, (bip)->bip_iter)
-
-#define bio_for_each_integrity_vec(_bvl, _bio, _iter) \
- for_each_bio(_bio) \
- bip_for_each_vec(_bvl, _bio->bi_integrity, _iter)
-
-int bio_integrity_map_user(struct bio *bio, void __user *ubuf, ssize_t len, u32 seed);
-extern struct bio_integrity_payload *bio_integrity_alloc(struct bio *, gfp_t, unsigned int);
-extern int bio_integrity_add_page(struct bio *, struct page *, unsigned int, unsigned int);
-extern bool bio_integrity_prep(struct bio *);
-extern void bio_integrity_advance(struct bio *, unsigned int);
-extern void bio_integrity_trim(struct bio *);
-extern int bio_integrity_clone(struct bio *, struct bio *, gfp_t);
-extern int bioset_integrity_create(struct bio_set *, int);
-extern void bioset_integrity_free(struct bio_set *);
-extern void bio_integrity_init(void);
-
-#else /* CONFIG_BLK_DEV_INTEGRITY */
-
-static inline void *bio_integrity(struct bio *bio)
-{
- return NULL;
-}
-
-static inline int bioset_integrity_create(struct bio_set *bs, int pool_size)
-{
- return 0;
-}
-
-static inline void bioset_integrity_free (struct bio_set *bs)
-{
- return;
-}
-
-static inline bool bio_integrity_prep(struct bio *bio)
-{
- return true;
-}
-
-static inline int bio_integrity_clone(struct bio *bio, struct bio *bio_src,
- gfp_t gfp_mask)
-{
- return 0;
-}
-
-static inline void bio_integrity_advance(struct bio *bio,
- unsigned int bytes_done)
-{
- return;
-}
-
-static inline void bio_integrity_trim(struct bio *bio)
-{
- return;
-}
-
-static inline void bio_integrity_init(void)
-{
- return;
-}
-
-static inline bool bio_integrity_flagged(struct bio *bio, enum bip_flags flag)
-{
- return false;
-}
-
-static inline void *bio_integrity_alloc(struct bio * bio, gfp_t gfp,
- unsigned int nr)
-{
- return ERR_PTR(-EINVAL);
-}
-
-static inline int bio_integrity_add_page(struct bio *bio, struct page *page,
- unsigned int len, unsigned int offset)
-{
- return 0;
-}
-
-static inline int bio_integrity_map_user(struct bio *bio, void __user *ubuf,
- ssize_t len, u32 seed)
-{
- return -EINVAL;
-}
-
-#endif /* CONFIG_BLK_DEV_INTEGRITY */
-
/*
* Mark a bio as polled. Note that for async polled IO, the caller must
* expect -EWOULDBLOCK if we cannot allocate a request (or other resources).
diff --git a/include/linux/blk-integrity.h b/include/linux/blk-integrity.h
index 804f856ed3e571..de98049b7ded91 100644
--- a/include/linux/blk-integrity.h
+++ b/include/linux/blk-integrity.h
@@ -3,6 +3,7 @@
#define _LINUX_BLK_INTEGRITY_H
#include <linux/blk-mq.h>
+#include <linux/bio-integrity.h>
struct request;
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/3] block: also return bio_integrity_payload * from stubs
2024-06-28 13:27 more integrity cleanups Christoph Hellwig
2024-06-28 13:27 ` [PATCH 1/3] block: split integrity support out of bio.h Christoph Hellwig
@ 2024-06-28 13:27 ` Christoph Hellwig
2024-06-28 13:27 ` [PATCH 3/3] block: don't free submitter owned integrity payload on I/O completion Christoph Hellwig
2 siblings, 0 replies; 6+ messages in thread
From: Christoph Hellwig @ 2024-06-28 13:27 UTC (permalink / raw)
To: Jens Axboe; +Cc: Martin K . Petersen, Anuj Gupta, Kanchan Joshi, linux-block
struct bio_integrity_payload is defined unconditionally. No need to
return void * from bio_integrity() and bio_integrity_alloc().
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
include/linux/bio-integrity.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/include/linux/bio-integrity.h b/include/linux/bio-integrity.h
index 0912f47f1d1eea..7b6e687d436de2 100644
--- a/include/linux/bio-integrity.h
+++ b/include/linux/bio-integrity.h
@@ -84,7 +84,7 @@ void bio_integrity_init(void);
#else /* CONFIG_BLK_DEV_INTEGRITY */
-static inline void *bio_integrity(struct bio *bio)
+static inline struct bio_integrity_payload *bio_integrity(struct bio *bio)
{
return NULL;
}
@@ -134,8 +134,8 @@ static inline bool bio_integrity_flagged(struct bio *bio, enum bip_flags flag)
return false;
}
-static inline void *bio_integrity_alloc(struct bio * bio, gfp_t gfp,
- unsigned int nr)
+static inline struct bio_integrity_payload *
+bio_integrity_alloc(struct bio * bio, gfp_t gfp, unsigned int nr)
{
return ERR_PTR(-EINVAL);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 3/3] block: don't free submitter owned integrity payload on I/O completion
2024-06-28 13:27 more integrity cleanups Christoph Hellwig
2024-06-28 13:27 ` [PATCH 1/3] block: split integrity support out of bio.h Christoph Hellwig
2024-06-28 13:27 ` [PATCH 2/3] block: also return bio_integrity_payload * from stubs Christoph Hellwig
@ 2024-06-28 13:27 ` Christoph Hellwig
2024-06-28 16:16 ` Kanchan Joshi
2 siblings, 1 reply; 6+ messages in thread
From: Christoph Hellwig @ 2024-06-28 13:27 UTC (permalink / raw)
To: Jens Axboe; +Cc: Martin K . Petersen, Anuj Gupta, Kanchan Joshi, linux-block
Currently __bio_integrity_endio unconditionally frees the integrity
payload. While this works really well for block-layer generated
integrity payloads, it is a bad idea for those passed in by the
submitter, as it can't access the integrity data from the I/O completion
handler.
Change bio_integrity_endio to only call __bio_integrity_endio for
block layer generated integrity data, and leave freeing of submitter
allocated integrity data to bio_uninit which also gets called from
the final bio_put. This requires that unmapping user mapped or copied
integrity data is done by the caller now.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
block/bio-integrity.c | 56 ++++++++++++++++-------------------
block/blk-map.c | 3 ++
block/blk.h | 4 ++-
include/linux/bio-integrity.h | 8 +++--
4 files changed, 37 insertions(+), 34 deletions(-)
diff --git a/block/bio-integrity.c b/block/bio-integrity.c
index ad296849aa2a9a..8c6447bcddede2 100644
--- a/block/bio-integrity.c
+++ b/block/bio-integrity.c
@@ -22,9 +22,17 @@ void blk_flush_integrity(void)
flush_workqueue(kintegrityd_wq);
}
-static void __bio_integrity_free(struct bio_set *bs,
- struct bio_integrity_payload *bip)
+/**
+ * bio_integrity_free - Free bio integrity payload
+ * @bio: bio containing bip to be freed
+ *
+ * Description: Free the integrity portion of a bio.
+ */
+void bio_integrity_free(struct bio *bio)
{
+ struct bio_integrity_payload *bip = bio_integrity(bio);
+ struct bio_set *bs = bio->bi_pool;
+
if (bs && mempool_initialized(&bs->bio_integrity_pool)) {
if (bip->bip_vec)
bvec_free(&bs->bvec_integrity_pool, bip->bip_vec,
@@ -33,6 +41,8 @@ static void __bio_integrity_free(struct bio_set *bs,
} else {
kfree(bip);
}
+ bio->bi_integrity = NULL;
+ bio->bi_opf &= ~REQ_INTEGRITY;
}
/**
@@ -86,7 +96,10 @@ struct bio_integrity_payload *bio_integrity_alloc(struct bio *bio,
return bip;
err:
- __bio_integrity_free(bs, bip);
+ if (bs && mempool_initialized(&bs->bio_integrity_pool))
+ mempool_free(bip, &bs->bio_integrity_pool);
+ else
+ kfree(bip);
return ERR_PTR(-ENOMEM);
}
EXPORT_SYMBOL(bio_integrity_alloc);
@@ -118,9 +131,10 @@ static void bio_integrity_uncopy_user(struct bio_integrity_payload *bip)
bio_integrity_unpin_bvec(copy, nr_vecs, true);
}
-static void bio_integrity_unmap_user(struct bio_integrity_payload *bip)
+void bio_integrity_unmap_user(struct bio *bio)
{
- bool dirty = bio_data_dir(bip->bip_bio) == READ;
+ struct bio_integrity_payload *bip = bio_integrity(bio);
+ bool dirty = bio_data_dir(bio) == READ;
if (bip->bip_flags & BIP_COPY_USER) {
if (dirty)
@@ -131,28 +145,7 @@ static void bio_integrity_unmap_user(struct bio_integrity_payload *bip)
bio_integrity_unpin_bvec(bip->bip_vec, bip->bip_max_vcnt, dirty);
}
-
-/**
- * bio_integrity_free - Free bio integrity payload
- * @bio: bio containing bip to be freed
- *
- * Description: Used to free the integrity portion of a bio. Usually
- * called from bio_free().
- */
-void bio_integrity_free(struct bio *bio)
-{
- struct bio_integrity_payload *bip = bio_integrity(bio);
- struct bio_set *bs = bio->bi_pool;
-
- if (bip->bip_flags & BIP_BLOCK_INTEGRITY)
- kfree(bvec_virt(bip->bip_vec));
- else if (bip->bip_flags & BIP_INTEGRITY_USER)
- bio_integrity_unmap_user(bip);
-
- __bio_integrity_free(bs, bip);
- bio->bi_integrity = NULL;
- bio->bi_opf &= ~REQ_INTEGRITY;
-}
+EXPORT_SYMBOL_GPL(bio_integrity_unmap_user);
/**
* bio_integrity_add_page - Attach integrity metadata
@@ -252,7 +245,7 @@ static int bio_integrity_copy_user(struct bio *bio, struct bio_vec *bvec,
goto free_bip;
}
- bip->bip_flags |= BIP_INTEGRITY_USER | BIP_COPY_USER;
+ bip->bip_flags |= BIP_COPY_USER;
bip->bip_iter.bi_sector = seed;
return 0;
free_bip:
@@ -272,7 +265,6 @@ static int bio_integrity_init_user(struct bio *bio, struct bio_vec *bvec,
return PTR_ERR(bip);
memcpy(bip->bip_vec, bvec, nr_vecs * sizeof(*bvec));
- bip->bip_flags |= BIP_INTEGRITY_USER;
bip->bip_iter.bi_sector = seed;
bip->bip_iter.bi_size = len;
return 0;
@@ -479,6 +471,8 @@ static void bio_integrity_verify_fn(struct work_struct *work)
struct bio *bio = bip->bip_bio;
blk_integrity_verify(bio);
+
+ kfree(bvec_virt(bip->bip_vec));
bio_integrity_free(bio);
bio_endio(bio);
}
@@ -499,13 +493,13 @@ bool __bio_integrity_endio(struct bio *bio)
struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
struct bio_integrity_payload *bip = bio_integrity(bio);
- if (bio_op(bio) == REQ_OP_READ && !bio->bi_status &&
- (bip->bip_flags & BIP_BLOCK_INTEGRITY) && bi->csum_type) {
+ if (bio_op(bio) == REQ_OP_READ && !bio->bi_status && bi->csum_type) {
INIT_WORK(&bip->bip_work, bio_integrity_verify_fn);
queue_work(kintegrityd_wq, &bip->bip_work);
return false;
}
+ kfree(bvec_virt(bip->bip_vec));
bio_integrity_free(bio);
return true;
}
diff --git a/block/blk-map.c b/block/blk-map.c
index bce144091128f6..0e1167b239342f 100644
--- a/block/blk-map.c
+++ b/block/blk-map.c
@@ -757,6 +757,9 @@ int blk_rq_unmap_user(struct bio *bio)
bio_release_pages(bio, bio_data_dir(bio) == READ);
}
+ if (bio_integrity(bio))
+ bio_integrity_unmap_user(bio);
+
next_bio = bio;
bio = bio->bi_next;
blk_mq_map_bio_put(next_bio);
diff --git a/block/blk.h b/block/blk.h
index 401e604f35d2cf..e8a6e7497c8d36 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -206,7 +206,9 @@ bool __bio_integrity_endio(struct bio *);
void bio_integrity_free(struct bio *bio);
static inline bool bio_integrity_endio(struct bio *bio)
{
- if (bio_integrity(bio))
+ struct bio_integrity_payload *bip = bio_integrity(bio);
+
+ if (bip && (bip->bip_flags & BIP_BLOCK_INTEGRITY))
return __bio_integrity_endio(bio);
return true;
}
diff --git a/include/linux/bio-integrity.h b/include/linux/bio-integrity.h
index 7b6e687d436de2..a5a8b44e9b118f 100644
--- a/include/linux/bio-integrity.h
+++ b/include/linux/bio-integrity.h
@@ -10,8 +10,7 @@ enum bip_flags {
BIP_CTRL_NOCHECK = 1 << 2, /* disable HBA integrity checking */
BIP_DISK_NOCHECK = 1 << 3, /* disable disk integrity checking */
BIP_IP_CHECKSUM = 1 << 4, /* IP checksum */
- BIP_INTEGRITY_USER = 1 << 5, /* Integrity payload is user address */
- BIP_COPY_USER = 1 << 6, /* Kernel bounce buffer in use */
+ BIP_COPY_USER = 1 << 5, /* Kernel bounce buffer in use */
};
struct bio_integrity_payload {
@@ -74,6 +73,7 @@ struct bio_integrity_payload *bio_integrity_alloc(struct bio *bio, gfp_t gfp,
int bio_integrity_add_page(struct bio *bio, struct page *page, unsigned int len,
unsigned int offset);
int bio_integrity_map_user(struct bio *bio, void __user *ubuf, ssize_t len, u32 seed);
+void bio_integrity_unmap_user(struct bio *bio);
bool bio_integrity_prep(struct bio *bio);
void bio_integrity_advance(struct bio *bio, unsigned int bytes_done);
void bio_integrity_trim(struct bio *bio);
@@ -105,6 +105,10 @@ static inline int bio_integrity_map_user(struct bio *bio, void __user *ubuf,
return -EINVAL;
}
+static inline void bio_integrity_unmap_user(struct bio *bio)
+{
+}
+
static inline bool bio_integrity_prep(struct bio *bio)
{
return true;
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 3/3] block: don't free submitter owned integrity payload on I/O completion
2024-06-28 13:27 ` [PATCH 3/3] block: don't free submitter owned integrity payload on I/O completion Christoph Hellwig
@ 2024-06-28 16:16 ` Kanchan Joshi
2024-06-29 5:02 ` Christoph Hellwig
0 siblings, 1 reply; 6+ messages in thread
From: Kanchan Joshi @ 2024-06-28 16:16 UTC (permalink / raw)
To: Christoph Hellwig, Jens Axboe
Cc: Martin K . Petersen, Anuj Gupta, linux-block
On 6/28/2024 6:57 PM, Christoph Hellwig wrote:
Thanks for streamlining this. Few comments below.
> static inline bool bio_integrity_endio(struct bio *bio)
> {
> - if (bio_integrity(bio))
> + struct bio_integrity_payload *bip = bio_integrity(bio);
> +
> + if (bip && (bip->bip_flags & BIP_BLOCK_INTEGRITY))
> return __bio_integrity_endio(bio);
Seems we will need similar BIP_BLOCK_INTEGRITY check inside bio_uninit
too. At line 221 in below snippet [1].
As that also frees integrity by calling bio_integrity_free. Earlier that
free was skipped due to BIP_INTEGRITY_USER flag. Now that flag has gone,
integrity will get freed and after that control may go back to
nvme-passthrough where it will try to unmap (and potentially copy back)
integrity.
> return true;
> }
> diff --git a/include/linux/bio-integrity.h b/include/linux/bio-integrity.h
> index 7b6e687d436de2..a5a8b44e9b118f 100644
> --- a/include/linux/bio-integrity.h
> +++ b/include/linux/bio-integrity.h
> @@ -10,8 +10,7 @@ enum bip_flags {
> BIP_CTRL_NOCHECK = 1 << 2, /* disable HBA integrity checking */
> BIP_DISK_NOCHECK = 1 << 3, /* disable disk integrity checking */
> BIP_IP_CHECKSUM = 1 << 4, /* IP checksum */
> - BIP_INTEGRITY_USER = 1 << 5, /* Integrity payload is user address */
Seems this patch is with "for-6.11/block".
But with "for-next" you will see more places where this flag has been
used. And there will be conflicts because we have this patch there [1].
Parts of this patch need changes to work with it. I can look more and
test next week.
[1]
commit e038ee6189842e9662d2fc59d09dbcf48350cf99
Author: Anuj Gupta <anuj20.g@samsung.com>
Date: Mon Jun 10 16:41:44 2024 +0530
block: unmap and free user mapped integrity via submitter
The user mapped intergity is copied back and unpinned by
bio_integrity_free which is a low-level routine. Do it via the
submitter
rather than doing it in the low-level block layer code, to split the
submitter side from the consumer side of the bio.
[2]
213 void bio_uninit(struct bio *bio)
214 {
215 #ifdef CONFIG_BLK_CGROUP
216 if (bio->bi_blkg) {
217 blkg_put(bio->bi_blkg);
218 bio->bi_blkg = NULL;
219 }
220 #endif
221 if (bio_integrity(bio))
222 bio_integrity_free(bio);
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 3/3] block: don't free submitter owned integrity payload on I/O completion
2024-06-28 16:16 ` Kanchan Joshi
@ 2024-06-29 5:02 ` Christoph Hellwig
0 siblings, 0 replies; 6+ messages in thread
From: Christoph Hellwig @ 2024-06-29 5:02 UTC (permalink / raw)
To: Kanchan Joshi
Cc: Christoph Hellwig, Jens Axboe, Martin K . Petersen, Anuj Gupta,
linux-block
On Fri, Jun 28, 2024 at 09:46:21PM +0530, Kanchan Joshi wrote:
> > static inline bool bio_integrity_endio(struct bio *bio)
> > {
> > - if (bio_integrity(bio))
> > + struct bio_integrity_payload *bip = bio_integrity(bio);
> > +
> > + if (bip && (bip->bip_flags & BIP_BLOCK_INTEGRITY))
> > return __bio_integrity_endio(bio);
>
> Seems we will need similar BIP_BLOCK_INTEGRITY check inside bio_uninit
> too. At line 221 in below snippet [1].
> As that also frees integrity by calling bio_integrity_free. Earlier that
> free was skipped due to BIP_INTEGRITY_USER flag. Now that flag has gone,
> integrity will get freed and after that control may go back to
> nvme-passthrough where it will try to unmap (and potentially copy back)
> integrity.
bio_integrity_free clears the REQ_INTEGRITY flag and the bi_integrity
pointer, and bio_uninit checks for those using bio_integrity() first.
The check is alredy required for the existing code and that doesn't
change.
> Seems this patch is with "for-6.11/block".
> But with "for-next" you will see more places where this flag has been
> used. And there will be conflicts because we have this patch there [1].
> Parts of this patch need changes to work with it. I can look more and
> test next week.
Oh, the patch actually does part of what this one does, _and_ I've
reviewed it. Jens, maybe just skip the patch we are replying to
(my one) for now, and I'll resend it for the next merge window
as the conflicts vs the 6.10 tree would be too annoying.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2024-06-29 5:02 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-06-28 13:27 more integrity cleanups Christoph Hellwig
2024-06-28 13:27 ` [PATCH 1/3] block: split integrity support out of bio.h Christoph Hellwig
2024-06-28 13:27 ` [PATCH 2/3] block: also return bio_integrity_payload * from stubs Christoph Hellwig
2024-06-28 13:27 ` [PATCH 3/3] block: don't free submitter owned integrity payload on I/O completion Christoph Hellwig
2024-06-28 16:16 ` Kanchan Joshi
2024-06-29 5:02 ` Christoph Hellwig
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.