/** * Set bitmap bits for clusters * * @check: Check structure * @offset: Starting offset in bytes * @n: Number of clusters */ static bool qed_set_used_clusters(QEDCheck *check, uint64_t offset, unsigned int n) { uint64_t cluster = qed_bytes_to_clusters(check->s, offset); unsigned int corruptions = 0; while (n-- != 0) { /* Clusters should only be referenced once */ if (qed_test_bit(check->used_clusters, cluster)) { corruptions++; } qed_set_bit(check->used_clusters, cluster); cluster++; } check->result->corruptions += corruptions; return corruptions == 0; }
static void qed_find_cluster_cb(void *opaque, int ret) { QEDFindClusterCB *find_cluster_cb = opaque; BDRVQEDState *s = find_cluster_cb->s; QEDRequest *request = find_cluster_cb->request; uint64_t offset = 0; size_t len = 0; unsigned int index; unsigned int n; if (ret) { goto out; } index = qed_l2_index(s, find_cluster_cb->pos); n = qed_bytes_to_clusters(s, qed_offset_into_cluster(s, find_cluster_cb->pos) + find_cluster_cb->len); n = qed_count_contiguous_clusters(s, request->l2_table->table, index, n, &offset); if (qed_offset_is_unalloc_cluster(offset)) { ret = QED_CLUSTER_L2; } else if (qed_offset_is_zero_cluster(offset)) { ret = QED_CLUSTER_ZERO; } else if (qed_check_cluster_offset(s, offset)) { ret = QED_CLUSTER_FOUND; } else { ret = -EINVAL; } len = MIN(find_cluster_cb->len, n * s->header.cluster_size - qed_offset_into_cluster(s, find_cluster_cb->pos)); out: find_cluster_cb->cb(find_cluster_cb->opaque, ret, offset, len); g_free(find_cluster_cb); }
BDRVQEDState *s = check->s; uint64_t i; for (i = s->header.header_size; i < check->nclusters; i++) { if (!qed_test_bit(check->used_clusters, i)) { check->result->leaks++; } } } int qed_check(BDRVQEDState *s, BdrvCheckResult *result, bool fix) { QEDCheck check = { .s = s, .result = result, .nclusters = qed_bytes_to_clusters(s, s->file_size), .request = { .l2_table = NULL }, .fix = fix, }; int ret; check.used_clusters = g_malloc0(((check.nclusters + 31) / 32) * sizeof(check.used_clusters[0])); ret = qed_check_l1_table(&check, s->l1_table); if (ret == 0) { /* Only check for leaks if entire image was scanned successfully */ qed_check_for_leaks(&check); } g_free(check.used_clusters);