/** * Shrink logpack header. * * @logh logpack header to shrink. * @invalid_idx new logpack header's n_records must be invalid_idx. * @pbs physical block size [byte]. * @salt checksum salt. */ void shrink_logpack_header( struct walb_logpack_header *logh, unsigned int invalid_idx, unsigned int pbs, u32 salt) { unsigned int i; /* Invalidate records. */ ASSERT(invalid_idx < logh->n_records); for (i = invalid_idx; i < logh->n_records; i++) { log_record_init(&logh->record[i]); } /* Set n_records, n_padding, and total_io_size. */ logh->n_records = invalid_idx; logh->n_padding = 0; logh->total_io_size = 0; for (i = 0; i < invalid_idx; i++) { const struct walb_log_record *rec = &logh->record[i]; if (!test_bit_u32(LOG_RECORD_DISCARD, &rec->flags)) { logh->total_io_size += capacity_pb(pbs, rec->io_size); } if (test_bit_u32(LOG_RECORD_PADDING, &rec->flags)) { logh->n_padding++; } } /* Calculate checksum. */ logh->checksum = 0; logh->checksum = checksum((const u8 *)logh, pbs, salt); ASSERT(is_valid_logpack_header_with_checksum(logh, pbs, salt)); }
/** * Read logpack header sector from log device. * * @fd log device fd opened. * @super_sectp super sector. * @lsid logpack lsid to read. * @logh_sect buffer to store logpack header data. * This allocated size must be sector size. * @salt log checksum salt. * * RETURN: * ture in success, or false. */ bool read_logpack_header_from_wldev( int fd, const struct walb_super_sector* super_sectp, u64 lsid, u32 salt, struct sector_data *logh_sect) { /* calc offset in the ring buffer */ u64 ring_buffer_offset = get_ring_buffer_offset_2(super_sectp); u64 ring_buffer_size = super_sectp->ring_buffer_size; u64 off = ring_buffer_offset + lsid % ring_buffer_size; struct walb_logpack_header *logh = get_logpack_header(logh_sect); /* read sector */ if (!sector_read(fd, off, logh_sect)) { LOGe("read logpack header (lsid %"PRIu64") failed.\n", lsid); return false; } /* check lsid */ if (lsid != logh->logpack_lsid) { LOGe("lsid (given %"PRIu64" read %"PRIu64") is invalid.\n", lsid, logh->logpack_lsid); return false; } if (!is_valid_logpack_header_with_checksum( logh, super_sectp->physical_bs, salt)) { LOGe("check logpack header failed.\n"); return false; } return true; }
/** * Read logpack header from fd. * * @fd file descriptor (opened, seeked) * @pbs physical block size [byte]. * @salt checksum salt. * @logpack logpack to be filled. (allocated size must be physical_bs). * * RETURN: * true in success, or false. */ bool read_logpack_header( int fd, unsigned int pbs, u32 salt, struct walb_logpack_header* logh) { /* Read */ if (!read_data(fd, (u8 *)logh, pbs)) { return false; } /* Check */ if (!is_valid_logpack_header_with_checksum(logh, pbs, salt)) { return false; } return true; }
/** * Check logpack of the given lsid exists. * * @lsid lsid to check. * * @return Non-zero if valid, or 0. */ int walb_check_lsid_valid(struct walb_dev *wdev, u64 lsid) { struct sector_data *sect; struct walb_logpack_header *logh; u64 off; ASSERT(wdev); sect = sector_alloc(wdev->physical_bs, GFP_NOIO); if (!sect) { LOGe("walb_check_lsid_valid: alloc sector failed.\n"); goto error0; } ASSERT(is_same_size_sector(sect, wdev->lsuper0)); logh = get_logpack_header(sect); spin_lock(&wdev->lsuper0_lock); off = get_offset_of_lsid_2(get_super_sector(wdev->lsuper0), lsid); spin_unlock(&wdev->lsuper0_lock); if (!sector_io(READ, wdev->ldev, off, sect)) { LOGe("walb_check_lsid_valid: read sector failed.\n"); goto error1; } /* Check valid logpack header. */ if (!is_valid_logpack_header_with_checksum( logh, wdev->physical_bs, wdev->log_checksum_salt)) { goto error1; } /* Check lsid. */ if (logh->logpack_lsid != lsid) { goto error1; } sector_free(sect); return 1; error1: sector_free(sect); error0: return 0; }