Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2903381f authored by Kent Overstreet's avatar Kent Overstreet
Browse files

bcache: Take data offset from the bdev superblock.



Add a new superblock version, and consolidate related defines.

Signed-off-by: default avatarGabriel de Perthuis <g2p.code+bcache@gmail.com>
Signed-off-by: default avatarKent Overstreet <koverstreet@google.com>
parent cef52797
Loading
Loading
Loading
Loading
+37 −10
Original line number Diff line number Diff line
@@ -223,11 +223,17 @@ struct bkey {
#define BKEY_PADDED(key)					\
	union { struct bkey key; uint64_t key ## _pad[BKEY_PAD]; }

/* Version 1: Backing device
/* Version 0: Cache device
 * Version 1: Backing device
 * Version 2: Seed pointer into btree node checksum
 * Version 3: New UUID format
 * Version 3: Cache device with new UUID format
 * Version 4: Backing device with data offset
 */
#define BCACHE_SB_VERSION	3
#define BCACHE_SB_VERSION_CDEV			0
#define BCACHE_SB_VERSION_BDEV			1
#define BCACHE_SB_VERSION_CDEV_WITH_UUID	3
#define BCACHE_SB_VERSION_BDEV_WITH_OFFSET	4
#define BCACHE_SB_MAX_VERSION			4

#define SB_SECTOR		8
#define SB_SIZE			4096
@@ -236,13 +242,12 @@ struct bkey {
/* SB_JOURNAL_BUCKETS must be divisible by BITS_PER_LONG */
#define MAX_CACHES_PER_SET	8

#define BDEV_DATA_START		16	/* sectors */
#define BDEV_DATA_START_DEFAULT	16	/* sectors */

struct cache_sb {
	uint64_t		csum;
	uint64_t		offset;	/* sector where this sb was written */
	uint64_t		version;
#define CACHE_BACKING_DEV	1

	uint8_t			magic[16];

@@ -257,12 +262,28 @@ struct cache_sb {
	uint64_t		seq;
	uint64_t		pad[8];

	union {
	struct {
		/* Cache devices */
		uint64_t	nbuckets;	/* device size */

		uint16_t	block_size;	/* sectors */
		uint16_t	bucket_size;	/* sectors */

		uint16_t	nr_in_set;
		uint16_t	nr_this_dev;
	};
	struct {
		/* Backing devices */
		uint64_t	data_offset;

		/*
		 * block_size from the cache device section is still used by
		 * backing devices, so don't add anything here until we fix
		 * things to not need it for backing devices anymore
		 */
	};
	};

	uint32_t		last_mount;	/* time_t */

@@ -861,6 +882,12 @@ static inline bool key_merging_disabled(struct cache_set *c)
#endif
}

static inline bool SB_IS_BDEV(const struct cache_sb *sb)
{
	return sb->version == BCACHE_SB_VERSION_BDEV
		|| sb->version == BCACHE_SB_VERSION_BDEV_WITH_OFFSET;
}

struct bbio {
	unsigned		submit_time_us;
	union {
+1 −1
Original line number Diff line number Diff line
@@ -1220,7 +1220,7 @@ static void cached_dev_make_request(struct request_queue *q, struct bio *bio)
	part_stat_unlock();

	bio->bi_bdev = dc->bdev;
	bio->bi_sector += BDEV_DATA_START;
	bio->bi_sector += dc->sb.data_offset;

	if (cached_dev_get(dc)) {
		s = search_alloc(bio, d);
+62 −46
Original line number Diff line number Diff line
@@ -110,15 +110,7 @@ static const char *read_super(struct cache_sb *sb, struct block_device *bdev,

	sb->flags		= le64_to_cpu(s->flags);
	sb->seq			= le64_to_cpu(s->seq);

	sb->nbuckets		= le64_to_cpu(s->nbuckets);
	sb->block_size		= le16_to_cpu(s->block_size);
	sb->bucket_size		= le16_to_cpu(s->bucket_size);

	sb->nr_in_set		= le16_to_cpu(s->nr_in_set);
	sb->nr_this_dev		= le16_to_cpu(s->nr_this_dev);
	sb->last_mount		= le32_to_cpu(s->last_mount);

	sb->first_bucket	= le16_to_cpu(s->first_bucket);
	sb->keys		= le16_to_cpu(s->keys);

@@ -147,15 +139,29 @@ static const char *read_super(struct cache_sb *sb, struct block_device *bdev,
	if (bch_is_zero(sb->uuid, 16))
		goto err;

	err = "Unsupported superblock version";
	if (sb->version > BCACHE_SB_VERSION)
		goto err;
	switch (sb->version) {
	case BCACHE_SB_VERSION_BDEV:
		sb->block_size	= le16_to_cpu(s->block_size);
		sb->data_offset	= BDEV_DATA_START_DEFAULT;
		break;
	case BCACHE_SB_VERSION_BDEV_WITH_OFFSET:
		sb->block_size	= le16_to_cpu(s->block_size);
		sb->data_offset	= le64_to_cpu(s->data_offset);

	err = "Bad block/bucket size";
	if (!is_power_of_2(sb->block_size) || sb->block_size > PAGE_SECTORS ||
	    !is_power_of_2(sb->bucket_size) || sb->bucket_size < PAGE_SECTORS)
		err = "Bad data offset";
		if (sb->data_offset < BDEV_DATA_START_DEFAULT)
			goto err;

		break;
	case BCACHE_SB_VERSION_CDEV:
	case BCACHE_SB_VERSION_CDEV_WITH_UUID:
		sb->nbuckets	= le64_to_cpu(s->nbuckets);
		sb->block_size	= le16_to_cpu(s->block_size);
		sb->bucket_size	= le16_to_cpu(s->bucket_size);

		sb->nr_in_set	= le16_to_cpu(s->nr_in_set);
		sb->nr_this_dev	= le16_to_cpu(s->nr_this_dev);

		err = "Too many buckets";
		if (sb->nbuckets > LONG_MAX)
			goto err;
@@ -164,13 +170,17 @@ static const char *read_super(struct cache_sb *sb, struct block_device *bdev,
		if (sb->nbuckets < 1 << 7)
			goto err;

		err = "Bad block/bucket size";
		if (!is_power_of_2(sb->block_size) ||
		    sb->block_size > PAGE_SECTORS ||
		    !is_power_of_2(sb->bucket_size) ||
		    sb->bucket_size < PAGE_SECTORS)
			goto err;

		err = "Invalid superblock: device too small";
		if (get_capacity(bdev->bd_disk) < sb->bucket_size * sb->nbuckets)
			goto err;

	if (sb->version == CACHE_BACKING_DEV)
		goto out;

		err = "Bad UUID";
		if (bch_is_zero(sb->set_uuid, 16))
			goto err;
@@ -193,7 +203,13 @@ static const char *read_super(struct cache_sb *sb, struct block_device *bdev,
		err = "Invalid superblock: first bucket comes before end of super";
		if (sb->first_bucket * sb->bucket_size < 16)
			goto err;
out:

		break;
	default:
		err = "Unsupported superblock version";
		goto err;
	}

	sb->last_mount = get_seconds();
	err = NULL;

@@ -286,7 +302,7 @@ void bcache_write_super(struct cache_set *c)
	for_each_cache(ca, c, i) {
		struct bio *bio = &ca->sb_bio;

		ca->sb.version		= BCACHE_SB_VERSION;
		ca->sb.version		= BCACHE_SB_VERSION_CDEV_WITH_UUID;
		ca->sb.seq		= c->sb.seq;
		ca->sb.last_mount	= c->sb.last_mount;

@@ -1049,7 +1065,7 @@ static const char *register_bdev(struct cache_sb *sb, struct page *sb_page,

	g = dc->disk.disk;

	set_capacity(g, dc->bdev->bd_part->nr_sects - 16);
	set_capacity(g, dc->bdev->bd_part->nr_sects - dc->sb.data_offset);

	bch_cached_dev_request_init(dc);

@@ -1802,7 +1818,7 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr,
	if (err)
		goto err_close;

	if (sb->version == CACHE_BACKING_DEV) {
	if (SB_IS_BDEV(sb)) {
		struct cached_dev *dc = kzalloc(sizeof(*dc), GFP_KERNEL);

		err = register_bdev(sb, sb_page, bdev, dc);