Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *  fs/partitions/aix.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *  Copyright (C) 2012-2013 Philippe De Muyter <phdm@macqel.be>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include "check.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) struct lvm_rec {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) 	char lvm_id[4]; /* "_LVM" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 	char reserved4[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) 	__be32 lvmarea_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 	__be32 vgda_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 	__be32 vgda_psn[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 	char reserved36[10];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 	__be16 pp_size; /* log2(pp_size) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 	char reserved46[12];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 	__be16 version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) struct vgda {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 	__be32 secs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	__be32 usec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	char reserved8[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	__be16 numlvs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	__be16 maxlvs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	__be16 pp_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	__be16 numpvs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	__be16 total_vgdas;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	__be16 vgda_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) struct lvd {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	__be16 lv_ix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	__be16 res2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	__be16 res4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	__be16 maxsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	__be16 lv_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	__be16 mirror;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	__be16 mirror_policy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	__be16 num_lps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	__be16 res10[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) struct lvname {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	char name[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) struct ppe {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	__be16 lv_ix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	unsigned short res2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	unsigned short res4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	__be16 lp_ix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	unsigned short res8[12];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) struct pvd {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	char reserved0[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	__be16 pp_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	char reserved18[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	__be32 psn_part1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	char reserved24[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	struct ppe ppe[1016];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) #define LVM_MAXLVS 256
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70)  * last_lba(): return number of last logical block of device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71)  * @bdev: block device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73)  * Description: Returns last LBA value on success, 0 on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74)  * This is stored (by sd and ide-geometry) in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75)  *  the part[0] entry for this disk, and is the number of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76)  *  physical sectors available on the disk.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) static u64 last_lba(struct block_device *bdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	if (!bdev || !bdev->bd_inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	return (bdev->bd_inode->i_size >> 9) - 1ULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86)  * read_lba(): Read bytes from disk, starting at given LBA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87)  * @state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88)  * @lba
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89)  * @buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90)  * @count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92)  * Description:  Reads @count bytes from @state->bdev into @buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93)  * Returns number of bytes read on success, 0 on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) static size_t read_lba(struct parsed_partitions *state, u64 lba, u8 *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 			size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	size_t totalreadcount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	if (!buffer || lba + count / 512 > last_lba(state->bdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	while (count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 		int copied = 512;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 		Sector sect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 		unsigned char *data = read_part_sector(state, lba++, &sect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 		if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		if (copied > count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 			copied = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 		memcpy(buffer, data, copied);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 		put_dev_sector(sect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 		buffer += copied;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 		totalreadcount += copied;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 		count -= copied;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	return totalreadcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)  * alloc_pvd(): reads physical volume descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)  * @state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)  * @lba
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)  * Description: Returns pvd on success,  NULL on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)  * Allocates space for pvd and fill it with disk blocks at @lba
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)  * Notes: remember to free pvd when you're done!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static struct pvd *alloc_pvd(struct parsed_partitions *state, u32 lba)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	size_t count = sizeof(struct pvd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	struct pvd *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	p = kmalloc(count, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	if (read_lba(state, lba, (u8 *) p, count) < count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 		kfree(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	return p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)  * alloc_lvn(): reads logical volume names
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)  * @state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)  * @lba
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)  * Description: Returns lvn on success,  NULL on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)  * Allocates space for lvn and fill it with disk blocks at @lba
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)  * Notes: remember to free lvn when you're done!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static struct lvname *alloc_lvn(struct parsed_partitions *state, u32 lba)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	size_t count = sizeof(struct lvname) * LVM_MAXLVS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	struct lvname *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	p = kmalloc(count, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	if (read_lba(state, lba, (u8 *) p, count) < count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 		kfree(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	return p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) int aix_partition(struct parsed_partitions *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	Sector sect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	unsigned char *d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	u32 pp_bytes_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	u32 pp_blocks_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	u32 vgda_sector = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	u32 vgda_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	int numlvs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	struct pvd *pvd = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	struct lv_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 		unsigned short pps_per_lv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 		unsigned short pps_found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 		unsigned char lv_is_contiguous;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	} *lvip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	struct lvname *n = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	d = read_part_sector(state, 7, &sect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	if (d) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		struct lvm_rec *p = (struct lvm_rec *)d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		u16 lvm_version = be16_to_cpu(p->version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		char tmp[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 		if (lvm_version == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 			int pp_size_log2 = be16_to_cpu(p->pp_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 			pp_bytes_size = 1 << pp_size_log2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 			pp_blocks_size = pp_bytes_size / 512;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 			snprintf(tmp, sizeof(tmp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 				" AIX LVM header version %u found\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 				lvm_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 			vgda_len = be32_to_cpu(p->vgda_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 			vgda_sector = be32_to_cpu(p->vgda_psn[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 			snprintf(tmp, sizeof(tmp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 				" unsupported AIX LVM version %d found\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 				lvm_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 		strlcat(state->pp_buf, tmp, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 		put_dev_sector(sect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	if (vgda_sector && (d = read_part_sector(state, vgda_sector, &sect))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 		struct vgda *p = (struct vgda *)d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 		numlvs = be16_to_cpu(p->numlvs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 		put_dev_sector(sect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	lvip = kcalloc(state->limit, sizeof(struct lv_info), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	if (!lvip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	if (numlvs && (d = read_part_sector(state, vgda_sector + 1, &sect))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 		struct lvd *p = (struct lvd *)d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 		int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 		n = alloc_lvn(state, vgda_sector + vgda_len - 33);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 		if (n) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 			int foundlvs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 			for (i = 0; foundlvs < numlvs && i < state->limit; i += 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 				lvip[i].pps_per_lv = be16_to_cpu(p[i].num_lps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 				if (lvip[i].pps_per_lv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 					foundlvs += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 			/* pvd loops depend on n[].name and lvip[].pps_per_lv */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 			pvd = alloc_pvd(state, vgda_sector + 17);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 		put_dev_sector(sect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	if (pvd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 		int numpps = be16_to_cpu(pvd->pp_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		int psn_part1 = be32_to_cpu(pvd->psn_part1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 		int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 		int cur_lv_ix = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 		int next_lp_ix = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 		int lp_ix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 		for (i = 0; i < numpps; i += 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 			struct ppe *p = pvd->ppe + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 			unsigned int lv_ix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 			lp_ix = be16_to_cpu(p->lp_ix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 			if (!lp_ix) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 				next_lp_ix = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 			lv_ix = be16_to_cpu(p->lv_ix) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 			if (lv_ix >= state->limit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 				cur_lv_ix = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 			lvip[lv_ix].pps_found += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 			if (lp_ix == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 				cur_lv_ix = lv_ix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 				next_lp_ix = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 			} else if (lv_ix != cur_lv_ix || lp_ix != next_lp_ix) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 				next_lp_ix = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 			if (lp_ix == lvip[lv_ix].pps_per_lv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 				char tmp[70];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 				put_partition(state, lv_ix + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 				  (i + 1 - lp_ix) * pp_blocks_size + psn_part1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 				  lvip[lv_ix].pps_per_lv * pp_blocks_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 				snprintf(tmp, sizeof(tmp), " <%s>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 					 n[lv_ix].name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 				strlcat(state->pp_buf, tmp, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 				lvip[lv_ix].lv_is_contiguous = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 				ret = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 				next_lp_ix = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 			} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 				next_lp_ix += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		for (i = 0; i < state->limit; i += 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 			if (lvip[i].pps_found && !lvip[i].lv_is_contiguous) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 				char tmp[sizeof(n[i].name) + 1]; // null char
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 				snprintf(tmp, sizeof(tmp), "%s", n[i].name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 				pr_warn("partition %s (%u pp's found) is "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 					"not contiguous\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 					tmp, lvip[i].pps_found);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 		kfree(pvd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	kfree(n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	kfree(lvip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }