/** * Redo logpack. * * @fd file descriptor of data device (opened). * @logpack logpack header to be redo. * @buf logpack data. * (data size: logh->total_io_size * physical_bs) * * RETURN: * true in success, or false. */ bool redo_logpack( int fd, const struct walb_logpack_header* logh, const struct sector_data_array *sect_ary) { int i, n_req; ASSERT(logh); ASSERT_SECTOR_DATA_ARRAY(sect_ary); n_req = logh->n_records; for (i = 0; i < n_req; i++) { unsigned int idx_lb, n_lb; u64 off_lb; const struct walb_log_record *rec = &logh->record[i]; if (test_bit_u32(LOG_RECORD_PADDING, &rec->flags)) { continue; } off_lb = rec->offset; idx_lb = addr_lb(sect_ary->sector_size, rec->lsid_local - 1); n_lb = rec->io_size; if (test_bit_u32(LOG_RECORD_DISCARD, &rec->flags)) { /* If the data device supports discard request, you must issue discard requests. */ /* now editing */ continue; } if (!sector_array_pwrite_lb(fd, off_lb, sect_ary, idx_lb, n_lb)) { LOGe("write sectors failed.\n"); return false; } } return true; }
/** * Write multiple logical sectors at an offset. * Logical block size is 512 bytes. * * @fd file descriptor of the target storage device. * @offset_lb storage offset [logical block]. * @sect_ary input sector data array. * @idx_lb start offset in sect_ary [logical block]. * @n_lb number of sectors to write [logical block]. * * RETURN: * true in success, or false. */ bool sector_array_pwrite_lb( int fd, u64 offset_lb, const struct sector_data_array *sect_ary, unsigned int idx_lb, unsigned int n_lb) { const unsigned int pbs = sect_ary->sector_size; unsigned int w_lb = 0; ASSERT(fd > 0); ASSERT_SECTOR_DATA_ARRAY(sect_ary); ASSERT(n_lb > 0); while (w_lb < n_lb) { unsigned int idx = addr_pb(pbs, idx_lb + w_lb); unsigned int off_lb = off_in_pb(pbs, idx_lb + w_lb); unsigned int tmp_lb = get_min_value(n_lb_in_pb(pbs) - off_lb, n_lb - w_lb); if (!sector_write_lb( fd, offset_lb + w_lb, sect_ary->array[idx], off_lb, tmp_lb)) { return false; } w_lb += tmp_lb; } ASSERT(w_lb == n_lb); return true; }
/** * Read a logpack data from a stream. * * @fd file descriptor (opened, seeked) * @logh corresponding logpack header. * @salt checksum salt. * @sect_ary sector data array to be store data. * * RETURN: * true in success, or false. */ bool read_logpack_data( int fd, const struct walb_logpack_header* logh, u32 salt, struct sector_data_array *sect_ary) { unsigned int pbs; u32 total_pb; int i; int n_req; ASSERT(fd >= 0); ASSERT(logh); n_req = logh->n_records; ASSERT_SECTOR_DATA_ARRAY(sect_ary); pbs = sect_ary->sector_size; ASSERT_PBS(pbs); if (logh->total_io_size > sect_ary->size) { LOGe("sect_ary size is not enough.\n"); return false; } total_pb = 0; for (i = 0; i < n_req; i++) { unsigned int idx_pb, log_lb, log_pb; u32 csum; const struct walb_log_record *rec = &logh->record[i]; if (test_bit_u32(LOG_RECORD_DISCARD, &rec->flags)) { continue; } idx_pb = rec->lsid_local - 1; log_lb = rec->io_size; log_pb = capacity_pb(pbs, log_lb); /* Read data of the log record. */ if (!sector_array_read(fd, sect_ary, idx_pb, log_pb)) { LOGe("read log data failed.\n"); return false; } if (test_bit_u32(LOG_RECORD_PADDING, &rec->flags)) { total_pb += log_pb; continue; } /* Confirm checksum. */ csum = sector_array_checksum( sect_ary, idx_pb * pbs, log_lb * LOGICAL_BLOCK_SIZE, salt); if (csum != rec->checksum) { LOGe("log record[%d] checksum is invalid. %08x %08x\n", i, csum, rec->checksum); return false; } total_pb += log_pb; } ASSERT(total_pb == logh->total_io_size); return true; }
/** * Read multiple sectors data at an offset. * * RETURN: * true in success, or false. */ bool sector_array_pread( int fd, u64 offset, struct sector_data_array *sect_ary, unsigned int start_idx, unsigned int n_sectors) { unsigned int i; ASSERT(fd > 0); ASSERT_SECTOR_DATA_ARRAY(sect_ary); ASSERT(start_idx + n_sectors <= sect_ary->size); for (i = 0; i < n_sectors; i++) { unsigned int idx = start_idx + i; u64 off = offset + i; bool ret = sector_read(fd, off, get_sector_data_in_array(sect_ary, idx)); if (!ret) { LOGe("read failed.\n"); return false; } } return true; }
/** * Write multiple sectors. * * @fd file descriptor of the target storage device. * @sect_ary sector data array. * @start_idx start offset in sect_ary [sectors]. * @n_sectors number of sectors to write [sectors]. * * RETURN: * true in success, or false. */ bool sector_array_write( int fd, const struct sector_data_array *sect_ary, unsigned int start_idx, unsigned int n_sectors) { unsigned int i; ASSERT(fd >= 0); ASSERT_SECTOR_DATA_ARRAY(sect_ary); ASSERT(start_idx + n_sectors <= sect_ary->size); for (i = 0; i < n_sectors; i++) { unsigned int idx = start_idx + i; bool ret = write_data( fd, (u8 *)sect_ary->array[idx]->data, sect_ary->sector_size); if (!ret) { LOGe("read failed.\n"); return false; } } return true; }