[PATCH] blkcache: include the hardware partition in the cache key
Daniel Golle <[email protected]>
| Newsgroups | gmane.comp.boot-loaders.u-boot.general,gmane.comp.boot-loaders.u-boot |
|---|---|
| Message-ID | <[email protected]> |
The block cache keys its entries on (iftype, devnum, start, blkcnt,
blksz) but not on the block descriptor's hardware partition. Devices
that expose several independent address spaces through blk_desc->hwpart
therefore alias each other in the cache: once a block has been cached
for one hwpart, reads of the same LBA on another hwpart return the data
cached for the first one.
For MMC this is masked because switching hwpart invalidates the cache,
but a UBI block device selects the target volume purely through hwpart
and does not invalidate on switch, so scanning several UBI volumes
returns the first volume's blocks for all of them.
Add hwpart to the cache key so entries for different hardware partitions
(or UBI volumes) are kept distinct.
Fixes: e40cf34a29f1 ("drivers: block: add block device cache")
Signed-off-by: Daniel Golle <[email protected]>
---
drivers/block/blk-uclass.c | 6 +++---
drivers/block/blkcache.c | 13 ++++++++-----
include/blk.h | 14 ++++++++------
3 files changed, 19 insertions(+), 14 deletions(-)
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c
index 73c24fd9176..6d2161cfc7b 100644
--- a/drivers/block/blk-uclass.c
+++ b/drivers/block/blk-uclass.c
@@ -439,7 +439,7 @@ long blk_read(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, void *buf)
return -ENOSYS;
if (blkcache_read(desc->uclass_id, desc->devnum,
- start, blkcnt, desc->blksz, buf))
+ desc->hwpart, start, blkcnt, desc->blksz, buf))
return blkcnt;
if (IS_ENABLED(CONFIG_BOUNCE_BUFFER) && desc->bb) {
@@ -461,8 +461,8 @@ long blk_read(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, void *buf)
}
if (blks_read == blkcnt)
- blkcache_fill(desc->uclass_id, desc->devnum, start, blkcnt,
- desc->blksz, buf);
+ blkcache_fill(desc->uclass_id, desc->devnum, desc->hwpart,
+ start, blkcnt, desc->blksz, buf);
return blks_read;
}
diff --git a/drivers/block/blkcache.c b/drivers/block/blkcache.c
index 0e69160249c..8a895dbe7a2 100644
--- a/drivers/block/blkcache.c
+++ b/drivers/block/blkcache.c
@@ -16,6 +16,7 @@ struct block_cache_node {
struct list_head lh;
int iftype;
int devnum;
+ int hwpart;
lbaint_t start;
lbaint_t blkcnt;
unsigned long blksz;
@@ -29,7 +30,7 @@ static struct block_cache_stats _stats = {
.max_entries = 32
};
-static struct block_cache_node *cache_find(int iftype, int devnum,
+static struct block_cache_node *cache_find(int iftype, int devnum, int hwpart,
lbaint_t start, lbaint_t blkcnt,
unsigned long blksz)
{
@@ -38,6 +39,7 @@ static struct block_cache_node *cache_find(int iftype, int devnum,
list_for_each_entry(node, &block_cache, lh)
if ((node->iftype == iftype) &&
(node->devnum == devnum) &&
+ (node->hwpart == hwpart) &&
(node->blksz == blksz) &&
(node->start <= start) &&
(node->start + node->blkcnt >= start + blkcnt)) {
@@ -51,12 +53,12 @@ static struct block_cache_node *cache_find(int iftype, int devnum,
return 0;
}
-int blkcache_read(int iftype, int devnum,
+int blkcache_read(int iftype, int devnum, int hwpart,
lbaint_t start, lbaint_t blkcnt,
unsigned long blksz, void *buffer)
{
- struct block_cache_node *node = cache_find(iftype, devnum, start,
- blkcnt, blksz);
+ struct block_cache_node *node = cache_find(iftype, devnum, hwpart,
+ start, blkcnt, blksz);
if (node) {
const char *src = node->cache + (start - node->start) * blksz;
memcpy(buffer, src, blksz * blkcnt);
@@ -72,7 +74,7 @@ int blkcache_read(int iftype, int devnum,
return 0;
}
-void blkcache_fill(int iftype, int devnum,
+void blkcache_fill(int iftype, int devnum, int hwpart,
lbaint_t start, lbaint_t blkcnt,
unsigned long blksz, void const *buffer)
{
@@ -118,6 +120,7 @@ void blkcache_fill(int iftype, int devnum,
node->iftype = iftype;
node->devnum = devnum;
+ node->hwpart = hwpart;
node->start = start;
node->blkcnt = blkcnt;
node->blksz = blksz;
diff --git a/include/blk.h b/include/blk.h
index 8d1b70cabd3..2cb9cb31ac2 100644
--- a/include/blk.h
+++ b/include/blk.h
@@ -120,7 +120,7 @@ struct blk_desc {
*
* Return: - 1 if block returned from cache, 0 otherwise.
*/
-int blkcache_read(int iftype, int dev,
+int blkcache_read(int iftype, int dev, int hwpart,
lbaint_t start, lbaint_t blkcnt,
unsigned long blksz, void *buffer);
@@ -136,7 +136,7 @@ int blkcache_read(int iftype, int dev,
* @param buffer - buffer containing data to cache
*
*/
-void blkcache_fill(int iftype, int dev,
+void blkcache_fill(int iftype, int dev, int hwpart,
lbaint_t start, lbaint_t blkcnt,
unsigned long blksz, void const *buffer);
@@ -180,14 +180,14 @@ void blkcache_free(void);
#else
-static inline int blkcache_read(int iftype, int dev,
+static inline int blkcache_read(int iftype, int dev, int hwpart,
lbaint_t start, lbaint_t blkcnt,
unsigned long blksz, void *buffer)
{
return 0;
}
-static inline void blkcache_fill(int iftype, int dev,
+static inline void blkcache_fill(int iftype, int dev, int hwpart,
lbaint_t start, lbaint_t blkcnt,
unsigned long blksz, void const *buffer) {}
@@ -529,7 +529,8 @@ static inline ulong blk_dread(struct blk_desc *block_dev, lbaint_t start,
{
ulong blks_read;
if (blkcache_read(block_dev->uclass_id, block_dev->devnum,
- start, blkcnt, block_dev->blksz, buffer))
+ block_dev->hwpart, start, blkcnt, block_dev->blksz,
+ buffer))
return blkcnt;
/*
@@ -540,7 +541,8 @@ static inline ulong blk_dread(struct blk_desc *block_dev, lbaint_t start,
blks_read = block_dev->block_read(block_dev, start, blkcnt, buffer);
if (blks_read == blkcnt)
blkcache_fill(block_dev->uclass_id, block_dev->devnum,
- start, blkcnt, block_dev->blksz, buffer);
+ block_dev->hwpart, start, blkcnt,
+ block_dev->blksz, buffer);
return blks_read;
}
--
2.55.0