/** * Create a logpack. * * @logh_sectdp pointer to sector data pointer * for logpack header (will be set). * @logd_sect_aryp pointer to sector data array pointer * for logpack data (will be set). * @pbs physical block size [byte]. * @bufsize buffer size for log data [byte]. * * RETURN: * allocated logpack in success, or NULL. */ struct logpack *alloc_logpack( unsigned int pbs, unsigned int n_sectors) { struct logpack *pack; ASSERT(is_valid_pbs(pbs)); ASSERT(0 < n_sectors); pack = (struct logpack *)malloc(sizeof(*pack)); if (!pack) { goto error1; } memset(pack, 0, sizeof(*pack)); /* Buffer for logpack header. */ pack->sectd = sector_alloc(pbs); if (!pack->sectd) { goto error1; } pack->header = get_logpack_header(pack->sectd); /* Buffer for logpack data. */ pack->sectd_ary = sector_array_alloc(pbs, n_sectors); if (!pack->sectd_ary) { goto error1; } return pack; error1: LOGe("Memory allocation failure.\n"); free_logpack(pack); return NULL; }
/** * 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; }
/** * 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; }
/** * Write an end logpack header block. */ bool write_end_logpack_header(int fd, unsigned int pbs, u32 salt) { bool ret = false; struct walb_logpack_header *h; struct sector_data *sect = sector_alloc(pbs); if (!sect) { LOGe("sector_alloc failed.\n"); return false; } h = get_logpack_header(sect); memset(h, 0, pbs); h->sector_type = SECTOR_TYPE_LOGPACK; h->n_records = 0; h->logpack_lsid = (u64)(-1); h->checksum = 0; h->checksum = checksum((const u8 *)h, pbs, salt); ret = write_data(fd, (const u8 *)h, pbs); if (!ret) LOGe("write_data failed.\n"); sector_free(sect); return ret; }