/* * pool_set_map -- (internal) map poolset */ static int pool_set_map(const char *fname, struct pool_set **poolset, int rdonly) { ASSERTeq(util_is_poolset_file(fname), 1); struct pool_hdr hdr; if (pool_set_read_header(fname, &hdr)) return -1; util_convert2h_hdr_nocheck(&hdr); /* parse pool type from first pool set file */ enum pool_type type = pool_hdr_get_type(&hdr); if (type == POOL_TYPE_UNKNOWN) { ERR("cannot determine pool type from poolset"); return -1; } /* get minimum size based on pool type for util_pool_open */ size_t minsize = pool_get_min_size(type); /* * Open the poolset, the values passed to util_pool_open are read * from the first poolset file, these values are then compared with * the values from all headers of poolset files. */ if (util_pool_open(poolset, fname, rdonly, minsize, hdr.signature, hdr.major, hdr.compat_features, hdr.incompat_features, hdr.ro_compat_features, NULL)) { ERR("opening poolset failed"); return -1; } return 0; }
/* * pool_set_map -- (internal) map poolset */ static int pool_set_map(const char *fname, struct pool_set **poolset, unsigned flags) { ASSERTeq(util_is_poolset_file(fname), 1); struct pool_hdr hdr; if (pool_set_read_header(fname, &hdr)) return -1; util_convert2h_hdr_nocheck(&hdr); /* parse pool type from first pool set file */ enum pool_type type = pool_hdr_get_type(&hdr); if (type == POOL_TYPE_UNKNOWN) { ERR("cannot determine pool type from poolset"); return -1; } /* * Open the poolset, the values passed to util_pool_open are read * from the first poolset file, these values are then compared with * the values from all headers of poolset files. */ struct pool_attr attr; util_pool_hdr2attr(&attr, &hdr); if (util_pool_open(poolset, fname, 0 /* minpartsize */, &attr, NULL, NULL, flags | POOL_OPEN_IGNORE_SDS | POOL_OPEN_IGNORE_BAD_BLOCKS)) { ERR("opening poolset failed"); return -1; } return 0; }
/* * pool_set_type -- get pool type of a poolset */ enum pool_type pool_set_type(struct pool_set *set) { struct pool_hdr hdr; /* open the first part file to read the pool header values */ const struct pool_set_part *part = &PART(REP(set, 0), 0); int fdp = util_file_open(part->path, NULL, 0, O_RDONLY); if (fdp < 0) { ERR("cannot open poolset part file"); return POOL_TYPE_UNKNOWN; } /* read the pool header from first pool set file */ if (read(fdp, &hdr, sizeof(hdr)) != sizeof(hdr)) { ERR("cannot read pool header from poolset"); close(fdp); return POOL_TYPE_UNKNOWN; } close(fdp); util_convert2h_hdr_nocheck(&hdr); enum pool_type type = pool_hdr_get_type(&hdr); return type; }
/* * pool_hdr_preliminary_check -- (internal) check pool header checksum and pool * parameters */ static int pool_hdr_preliminary_check(PMEMpoolcheck *ppc, location *loc) { LOG(3, NULL); CHECK_INFO(ppc, "%schecking pool header", loc->prefix); if (util_is_zeroed((void *)&loc->hdr, sizeof(loc->hdr))) { if (CHECK_IS_NOT(ppc, REPAIR)) { check_end(ppc->data); ppc->result = CHECK_RESULT_NOT_CONSISTENT; return CHECK_ERR(ppc, "%sempty pool hdr", loc->prefix); } } else if (loc->hdr_valid) { enum pool_type type = pool_hdr_get_type(&loc->hdr); if (type == POOL_TYPE_UNKNOWN) { if (CHECK_IS_NOT(ppc, REPAIR)) { check_end(ppc->data); ppc->result = CHECK_RESULT_NOT_CONSISTENT; return CHECK_ERR(ppc, "%sinvalid signature", loc->prefix); } CHECK_INFO(ppc, "%sinvalid signature", loc->prefix); } else { /* valid check sum */ CHECK_INFO(ppc, "%spool header correct", loc->prefix); loc->step = CHECK_STEP_COMPLETE; return 0; } } else if (CHECK_IS_NOT(ppc, REPAIR)) { check_end(ppc->data); ppc->result = CHECK_RESULT_NOT_CONSISTENT; return CHECK_ERR(ppc, "%sincorrect pool header", loc->prefix); } else { CHECK_INFO(ppc, "%sincorrect pool header", loc->prefix); } ASSERT(CHECK_IS(ppc, REPAIR)); if (ppc->pool->params.type == POOL_TYPE_UNKNOWN) { ppc->pool->params.type = pool_hdr_possible_type(ppc); if (ppc->pool->params.type == POOL_TYPE_UNKNOWN) { ppc->result = CHECK_RESULT_CANNOT_REPAIR; return CHECK_ERR(ppc, "cannot determine pool type"); } } if (!pool_supported(ppc->pool->params.type)) { ppc->result = CHECK_RESULT_CANNOT_REPAIR; return CHECK_ERR(ppc, "the repair of %s pools is not supported", pool_get_pool_type_str(ppc->pool->params.type)); } return 0; }
/* * check_replica_sizes -- (internal) check if all replicas are large * enough to hold data from a healthy replica */ static int check_replica_sizes(struct pool_set *set, struct poolset_health_status *set_hs) { LOG(3, "set %p, set_hs %p", set, set_hs); ssize_t pool_size = -1; for (unsigned r = 0; r < set->nreplicas; ++r) { /* skip broken replicas */ if (!replica_is_replica_healthy(r, set_hs)) continue; /* get the size of a pool in the replica */ ssize_t replica_pool_size; if (REP(set, r)->remote) /* XXX: no way to get the size of a remote pool yet */ replica_pool_size = (ssize_t)set->poolsize; else replica_pool_size = replica_get_pool_size(set, r); if (replica_pool_size < 0) { LOG(1, "getting pool size from replica %u failed", r); set_hs->replica[r]->flags |= IS_BROKEN; continue; } /* check if the pool is bigger than minimum size */ enum pool_type type = pool_hdr_get_type(HDR(REP(set, r), 0)); if ((size_t)replica_pool_size < pool_get_min_size(type)) { LOG(1, "pool size from replica %u is smaller than the minimum size allowed for the pool", r); set_hs->replica[r]->flags |= IS_BROKEN; continue; } /* check if each replica is big enough to hold the pool data */ if (set->poolsize < (size_t)replica_pool_size) { ERR( "some replicas are too small to hold synchronized data"); return -1; } if (pool_size < 0) { pool_size = replica_pool_size; continue; } /* check if pools in all healthy replicas are of equal size */ if (pool_size != replica_pool_size) { ERR("pool sizes from different replicas differ"); return -1; } } return 0; }
/* * pool_params_from_header -- parse pool params from pool header */ void pool_params_from_header(struct pool_params *params, const struct pool_hdr *hdr) { memcpy(params->signature, hdr->signature, sizeof(params->signature)); /* * Check if file is a part of pool set by comparing the UUID with the * next part UUID. If it is the same it means the pool consist of a * single file. */ int uuid_eq_next = uuidcmp(hdr->uuid, hdr->next_part_uuid); int uuid_eq_prev = uuidcmp(hdr->uuid, hdr->prev_part_uuid); params->is_part = !params->is_poolset && (uuid_eq_next || uuid_eq_prev); params->type = pool_hdr_get_type(hdr); }
/* * pool_set_type -- get pool type of a poolset */ enum pool_type pool_set_type(struct pool_set *set) { struct pool_hdr hdr; /* open the first part file to read the pool header values */ const struct pool_set_part *part = &PART(REP(set, 0), 0); if (util_file_pread(part->path, &hdr, sizeof(hdr), 0) != sizeof(hdr)) { ERR("cannot read pool header from poolset"); return POOL_TYPE_UNKNOWN; } util_convert2h_hdr_nocheck(&hdr); enum pool_type type = pool_hdr_get_type(&hdr); return type; }