^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++, §);
^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, §);
^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, §))) {
^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, §))) {
^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) }