loader: calculate physical vdev psize from asize
Since physical device asize is calculated from psize and the asize is stored in pool label, we can use asize to set the value of psize, which is used to calculate the location of the pool labels. MFC after: 1 week
This commit is contained in:
parent
bcbb1e60a1
commit
abca0bd501
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=354279
@ -1102,7 +1102,7 @@ vdev_init_from_nvlist(const unsigned char *nvlist, vdev_t *pvdev,
|
|||||||
vdev_t **vdevp, int is_newer)
|
vdev_t **vdevp, int is_newer)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
uint64_t guid, id, ashift, nparity;
|
uint64_t guid, id, ashift, asize, nparity;
|
||||||
const char *type;
|
const char *type;
|
||||||
const char *path;
|
const char *path;
|
||||||
vdev_t *vdev, *kid;
|
vdev_t *vdev, *kid;
|
||||||
@ -1181,6 +1181,11 @@ vdev_init_from_nvlist(const unsigned char *nvlist, vdev_t *pvdev,
|
|||||||
} else {
|
} else {
|
||||||
vdev->v_ashift = 0;
|
vdev->v_ashift = 0;
|
||||||
}
|
}
|
||||||
|
if (nvlist_find(nvlist, ZPOOL_CONFIG_ASIZE,
|
||||||
|
DATA_TYPE_UINT64, NULL, &asize) == 0) {
|
||||||
|
vdev->v_psize = asize +
|
||||||
|
VDEV_LABEL_START_SIZE + VDEV_LABEL_END_SIZE;
|
||||||
|
}
|
||||||
if (nvlist_find(nvlist, ZPOOL_CONFIG_NPARITY,
|
if (nvlist_find(nvlist, ZPOOL_CONFIG_NPARITY,
|
||||||
DATA_TYPE_UINT64, NULL, &nparity) == 0) {
|
DATA_TYPE_UINT64, NULL, &nparity) == 0) {
|
||||||
vdev->v_nparity = nparity;
|
vdev->v_nparity = nparity;
|
||||||
@ -1547,7 +1552,6 @@ vdev_probe(vdev_phys_read_t *_read, void *read_priv, spa_t **spap)
|
|||||||
uint64_t guid;
|
uint64_t guid;
|
||||||
uint64_t best_txg = 0;
|
uint64_t best_txg = 0;
|
||||||
uint64_t pool_txg, pool_guid;
|
uint64_t pool_txg, pool_guid;
|
||||||
uint64_t psize;
|
|
||||||
const char *pool_name;
|
const char *pool_name;
|
||||||
const unsigned char *vdevs;
|
const unsigned char *vdevs;
|
||||||
const unsigned char *features;
|
const unsigned char *features;
|
||||||
@ -1562,17 +1566,17 @@ vdev_probe(vdev_phys_read_t *_read, void *read_priv, spa_t **spap)
|
|||||||
memset(&vtmp, 0, sizeof(vtmp));
|
memset(&vtmp, 0, sizeof(vtmp));
|
||||||
vtmp.v_phys_read = _read;
|
vtmp.v_phys_read = _read;
|
||||||
vtmp.v_read_priv = read_priv;
|
vtmp.v_read_priv = read_priv;
|
||||||
psize = P2ALIGN(ldi_get_size(read_priv),
|
vtmp.v_psize = P2ALIGN(ldi_get_size(read_priv),
|
||||||
(uint64_t)sizeof (vdev_label_t));
|
(uint64_t)sizeof (vdev_label_t));
|
||||||
|
|
||||||
/* Test for minimum pool size. */
|
/* Test for minimum pool size. */
|
||||||
if (psize < SPA_MINDEVSIZE)
|
if (vtmp.v_psize < SPA_MINDEVSIZE)
|
||||||
return (EIO);
|
return (EIO);
|
||||||
|
|
||||||
tmp_label = zfs_alloc(sizeof(vdev_phys_t));
|
tmp_label = zfs_alloc(sizeof(vdev_phys_t));
|
||||||
|
|
||||||
for (l = 0; l < VDEV_LABELS; l++) {
|
for (l = 0; l < VDEV_LABELS; l++) {
|
||||||
off = vdev_label_offset(psize, l,
|
off = vdev_label_offset(vtmp.v_psize, l,
|
||||||
offsetof(vdev_label_t, vl_vdev_phys));
|
offsetof(vdev_label_t, vl_vdev_phys));
|
||||||
|
|
||||||
BP_ZERO(&bp);
|
BP_ZERO(&bp);
|
||||||
@ -1595,8 +1599,20 @@ vdev_probe(vdev_phys_read_t *_read, void *read_priv, spa_t **spap)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (best_txg <= pool_txg) {
|
if (best_txg <= pool_txg) {
|
||||||
|
uint64_t asize;
|
||||||
|
|
||||||
best_txg = pool_txg;
|
best_txg = pool_txg;
|
||||||
memcpy(vdev_label, tmp_label, sizeof (vdev_phys_t));
|
memcpy(vdev_label, tmp_label, sizeof (vdev_phys_t));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use asize from pool config. We need this
|
||||||
|
* because we can get bad value from BIOS.
|
||||||
|
*/
|
||||||
|
if (nvlist_find(nvlist, ZPOOL_CONFIG_ASIZE,
|
||||||
|
DATA_TYPE_UINT64, NULL, &asize) == 0) {
|
||||||
|
vtmp.v_psize = asize +
|
||||||
|
VDEV_LABEL_START_SIZE + VDEV_LABEL_END_SIZE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1716,6 +1732,7 @@ vdev_probe(vdev_phys_read_t *_read, void *read_priv, spa_t **spap)
|
|||||||
vdev->v_phys_read = _read;
|
vdev->v_phys_read = _read;
|
||||||
vdev->v_read_priv = read_priv;
|
vdev->v_read_priv = read_priv;
|
||||||
vdev->v_state = VDEV_STATE_HEALTHY;
|
vdev->v_state = VDEV_STATE_HEALTHY;
|
||||||
|
vdev->v_psize = vtmp.v_psize;
|
||||||
} else {
|
} else {
|
||||||
printf("ZFS: inconsistent nvlist contents\n");
|
printf("ZFS: inconsistent nvlist contents\n");
|
||||||
return (EIO);
|
return (EIO);
|
||||||
@ -1735,7 +1752,7 @@ vdev_probe(vdev_phys_read_t *_read, void *read_priv, spa_t **spap)
|
|||||||
up = (const struct uberblock *)upbuf;
|
up = (const struct uberblock *)upbuf;
|
||||||
for (l = 0; l < VDEV_LABELS; l++) {
|
for (l = 0; l < VDEV_LABELS; l++) {
|
||||||
for (i = 0; i < VDEV_UBERBLOCK_COUNT(vdev); i++) {
|
for (i = 0; i < VDEV_UBERBLOCK_COUNT(vdev); i++) {
|
||||||
off = vdev_label_offset(psize, l,
|
off = vdev_label_offset(vdev->v_psize, l,
|
||||||
VDEV_UBERBLOCK_OFFSET(vdev, i));
|
VDEV_UBERBLOCK_OFFSET(vdev, i));
|
||||||
BP_ZERO(&bp);
|
BP_ZERO(&bp);
|
||||||
DVA_SET_OFFSET(&bp.blk_dva[0], off);
|
DVA_SET_OFFSET(&bp.blk_dva[0], off);
|
||||||
|
@ -1660,7 +1660,8 @@ typedef struct vdev {
|
|||||||
vdev_list_t v_children; /* children of this vdev */
|
vdev_list_t v_children; /* children of this vdev */
|
||||||
const char *v_name; /* vdev name */
|
const char *v_name; /* vdev name */
|
||||||
uint64_t v_guid; /* vdev guid */
|
uint64_t v_guid; /* vdev guid */
|
||||||
int v_id; /* index in parent */
|
uint64_t v_id; /* index in parent */
|
||||||
|
uint64_t v_psize; /* physical device capacity */
|
||||||
int v_ashift; /* offset to block shift */
|
int v_ashift; /* offset to block shift */
|
||||||
int v_nparity; /* # parity for raidz */
|
int v_nparity; /* # parity for raidz */
|
||||||
struct vdev *v_top; /* parent vdev */
|
struct vdev *v_top; /* parent vdev */
|
||||||
|
Loading…
Reference in New Issue
Block a user