/* * Copyright (C) 2018 Red Hat, Inc. All rights reserved. * * This file is part of LVM2. * * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions * of the GNU Lesser General Public License v.2.1. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "lib/misc/lib.h" #include "lib/device/dev-type.h" #include "lib/mm/xlate.h" /* * These lvm1 structs just used NAME_LEN in the previous format1 lvm2 code, but * NAME_LEN was defined as 128 in generic lvm2 code that was not lvm1-specific * and not disk-format-specific. */ #define LVM1_NAME_LEN 128 struct data_area { uint32_t base; uint32_t size; } __attribute__ ((packed)); struct pv_disk { int8_t id[2]; uint16_t version; /* lvm version */ struct data_area pv_on_disk; struct data_area vg_on_disk; struct data_area pv_uuidlist_on_disk; struct data_area lv_on_disk; struct data_area pe_on_disk; int8_t pv_uuid[LVM1_NAME_LEN]; int8_t vg_name[LVM1_NAME_LEN]; int8_t system_id[LVM1_NAME_LEN]; /* for vgexport/vgimport */ uint32_t pv_major; uint32_t pv_number; uint32_t pv_status; uint32_t pv_allocatable; uint32_t pv_size; uint32_t lv_cur; uint32_t pe_size; uint32_t pe_total; uint32_t pe_allocated; /* only present on version == 2 pv's */ uint32_t pe_start; } __attribute__ ((packed)); int dev_is_lvm1(struct device *dev, char *buf, int buflen) { struct pv_disk *pvd = (struct pv_disk *) buf; uint32_t version; int ret; version = xlate16(pvd->version); if (pvd->id[0] == 'H' && pvd->id[1] == 'M' && (version == 1 || version == 2)) ret = 1; else ret = 0; return ret; } #define POOL_MAGIC 0x011670 #define POOL_NAME_SIZE 256 #define NSPMajorVersion 4 #define NSPMinorVersion 1 #define NSPUpdateLevel 3 /* When checking for version matching, the first two numbers ** ** are important for metadata formats, a.k.a pool labels. ** ** All the numbers are important when checking if the user ** ** space tools match up with the kernel module............. */ #define POOL_VERSION (NSPMajorVersion << 16 | \ NSPMinorVersion << 8 | \ NSPUpdateLevel) struct pool_disk { uint64_t pl_magic; /* Pool magic number */ uint64_t pl_pool_id; /* Unique pool identifier */ char pl_pool_name[POOL_NAME_SIZE]; /* Name of pool */ uint32_t pl_version; /* Pool version */ uint32_t pl_subpools; /* Number of subpools in this pool */ uint32_t pl_sp_id; /* Subpool number within pool */ uint32_t pl_sp_devs; /* Number of data partitions in this subpool */ uint32_t pl_sp_devid; /* Partition number within subpool */ uint32_t pl_sp_type; /* Partition type */ uint64_t pl_blocks; /* Number of blocks in this partition */ uint32_t pl_striping; /* Striping size within subpool */ /* * If the number of DMEP devices is zero, then the next field ** * ** (pl_sp_dmepid) becomes the subpool ID for redirection. In ** * ** other words, if this subpool does not have the capability ** * ** to do DMEP, then it must specify which subpool will do it ** * ** in it's place */ /* * While the next 3 field are no longer used, they must stay to keep ** * ** backward compatibility........................................... */ uint32_t pl_sp_dmepdevs;/* Number of dmep devices in this subpool */ uint32_t pl_sp_dmepid; /* Dmep device number within subpool */ uint32_t pl_sp_weight; /* if dmep dev, pref to using it */ uint32_t pl_minor; /* the pool minor number */ uint32_t pl_padding; /* reminder - think about alignment */ /* * Even though we're zeroing out 8k at the front of the disk before * writing the label, putting this in */ char pl_reserve[184]; /* bump the structure size out to 512 bytes */ }; #define CPIN_8(x, y, z) {memcpy((x), (y), (z));} #define CPIN_16(x, y) {(x) = xlate16_be((y));} #define CPIN_32(x, y) {(x) = xlate32_be((y));} #define CPIN_64(x, y) {(x) = xlate64_be((y));} static void pool_label_in(struct pool_disk *pl, void *buf) { struct pool_disk *bufpl = (struct pool_disk *) buf; CPIN_64(pl->pl_magic, bufpl->pl_magic); CPIN_64(pl->pl_pool_id, bufpl->pl_pool_id); CPIN_8(pl->pl_pool_name, bufpl->pl_pool_name, POOL_NAME_SIZE); CPIN_32(pl->pl_version, bufpl->pl_version); CPIN_32(pl->pl_subpools, bufpl->pl_subpools); CPIN_32(pl->pl_sp_id, bufpl->pl_sp_id); CPIN_32(pl->pl_sp_devs, bufpl->pl_sp_devs); CPIN_32(pl->pl_sp_devid, bufpl->pl_sp_devid); CPIN_32(pl->pl_sp_type, bufpl->pl_sp_type); CPIN_64(pl->pl_blocks, bufpl->pl_blocks); CPIN_32(pl->pl_striping, bufpl->pl_striping); CPIN_32(pl->pl_sp_dmepdevs, bufpl->pl_sp_dmepdevs); CPIN_32(pl->pl_sp_dmepid, bufpl->pl_sp_dmepid); CPIN_32(pl->pl_sp_weight, bufpl->pl_sp_weight); CPIN_32(pl->pl_minor, bufpl->pl_minor); CPIN_32(pl->pl_padding, bufpl->pl_padding); CPIN_8(pl->pl_reserve, bufpl->pl_reserve, 184); } int dev_is_pool(struct device *dev, char *buf, int buflen) { struct pool_disk pd; int ret; pool_label_in(&pd, buf); /* can ignore 8 rightmost bits for ondisk format check */ if ((pd.pl_magic == POOL_MAGIC) && (pd.pl_version >> 8 == POOL_VERSION >> 8)) ret = 1; else ret = 0; return ret; }