mirror of https://github.com/schoebel/mars
lib_log: better data safety, rework error handling
This commit is contained in:
parent
bcf323c254
commit
44f45025f8
70
lib_log.c
70
lib_log.c
|
@ -381,7 +381,7 @@ int log_scan(void *buf, int len, loff_t file_pos, int file_offset, struct log_he
|
||||||
*payload = NULL;
|
*payload = NULL;
|
||||||
*payload_len = 0;
|
*payload_len = 0;
|
||||||
|
|
||||||
for (i = 0; i < len; i += sizeof(long)) {
|
for (i = 0; i < len && i <= len - OVERHEAD; i += sizeof(long)) {
|
||||||
long long start_magic;
|
long long start_magic;
|
||||||
char format_version;
|
char format_version;
|
||||||
char valid_flag;
|
char valid_flag;
|
||||||
|
@ -394,32 +394,32 @@ int log_scan(void *buf, int len, loff_t file_pos, int file_offset, struct log_he
|
||||||
|
|
||||||
offset = i;
|
offset = i;
|
||||||
DATA_GET(buf, offset, start_magic);
|
DATA_GET(buf, offset, start_magic);
|
||||||
if (start_magic != START_MAGIC) {
|
if (unlikely(start_magic != START_MAGIC)) {
|
||||||
if (start_magic != 0)
|
if (start_magic != 0)
|
||||||
dirty = true;
|
dirty = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
restlen = len - i;
|
restlen = len - i;
|
||||||
if (restlen < START_OVERHEAD) {
|
if (unlikely(restlen < START_OVERHEAD)) {
|
||||||
MARS_ERR(SCAN_TXT "magic found, but restlen is too small\n", SCAN_PAR);
|
MARS_WRN(SCAN_TXT "magic found, but restlen is too small\n", SCAN_PAR);
|
||||||
return -EBADMSG;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
DATA_GET(buf, offset, format_version);
|
DATA_GET(buf, offset, format_version);
|
||||||
if (format_version != FORMAT_VERSION) {
|
if (unlikely(format_version != FORMAT_VERSION)) {
|
||||||
MARS_ERR(SCAN_TXT "found unknown data format %d\n", SCAN_PAR, (int)format_version);
|
MARS_ERR(SCAN_TXT "found unknown data format %d\n", SCAN_PAR, (int)format_version);
|
||||||
return -EBADMSG;
|
return -EBADMSG;
|
||||||
}
|
}
|
||||||
DATA_GET(buf, offset, valid_flag);
|
DATA_GET(buf, offset, valid_flag);
|
||||||
if (!valid_flag) {
|
if (unlikely(!valid_flag)) {
|
||||||
MARS_WRN(SCAN_TXT "data is marked invalid (was there a short write?)\n", SCAN_PAR);
|
MARS_WRN(SCAN_TXT "data is explicitly marked invalid (was there a short write?)\n", SCAN_PAR);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
DATA_GET(buf, offset, total_len);
|
DATA_GET(buf, offset, total_len);
|
||||||
if (total_len > restlen) {
|
if (unlikely(total_len > restlen)) {
|
||||||
MARS_ERR(SCAN_TXT "data is longer than expected, total_len = %d restlen = %d\n", SCAN_PAR, total_len, restlen);
|
MARS_WRN(SCAN_TXT "total_len = %d but available data restlen = %d. Was the logfile truncated?\n", SCAN_PAR, total_len, restlen);
|
||||||
return -EBADMSG;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(lh, 0, sizeof(struct log_header));
|
memset(lh, 0, sizeof(struct log_header));
|
||||||
|
@ -436,21 +436,22 @@ int log_scan(void *buf, int len, loff_t file_pos, int file_offset, struct log_he
|
||||||
offset += lh->l_len;
|
offset += lh->l_len;
|
||||||
|
|
||||||
restlen = len - offset;
|
restlen = len - offset;
|
||||||
if (restlen < END_OVERHEAD) {
|
if (unlikely(restlen < END_OVERHEAD)) {
|
||||||
MARS_WRN(SCAN_TXT "magic found, but restlen %d is too small\n", SCAN_PAR, restlen);
|
MARS_WRN(SCAN_TXT "restlen %d is too small\n", SCAN_PAR, restlen);
|
||||||
continue;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
DATA_GET(buf, offset, end_magic);
|
DATA_GET(buf, offset, end_magic);
|
||||||
if (end_magic != END_MAGIC) {
|
if (unlikely(end_magic != END_MAGIC)) {
|
||||||
MARS_WRN(SCAN_TXT "bad end_magic 0x%llx\n", SCAN_PAR, end_magic);
|
MARS_WRN(SCAN_TXT "bad end_magic 0x%llx, is the logfile truncated?\n", SCAN_PAR, end_magic);
|
||||||
continue;
|
return -EBADMSG;
|
||||||
}
|
}
|
||||||
DATA_GET(buf, offset, lh->l_crc);
|
DATA_GET(buf, offset, lh->l_crc);
|
||||||
DATA_GET(buf, offset, valid_copy);
|
DATA_GET(buf, offset, valid_copy);
|
||||||
if (valid_copy != 1) {
|
|
||||||
MARS_WRN(SCAN_TXT "found uncompleted / invalid data, len = %d, valid_flag = %d\n", SCAN_PAR, lh->l_len, (int)valid_copy);
|
if (unlikely(valid_copy != 1)) {
|
||||||
continue;
|
MARS_WRN(SCAN_TXT "found data marked as uncompleted / invalid, len = %d, valid_flag = %d\n", SCAN_PAR, lh->l_len, (int)valid_copy);
|
||||||
|
return -EBADMSG;
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip spares
|
// skip spares
|
||||||
|
@ -461,7 +462,7 @@ int log_scan(void *buf, int len, loff_t file_pos, int file_offset, struct log_he
|
||||||
DATA_GET(buf, offset, lh->l_written.tv_nsec);
|
DATA_GET(buf, offset, lh->l_written.tv_nsec);
|
||||||
|
|
||||||
if (unlikely(lh->l_seq_nr != *seq_nr + 1 && lh->l_seq_nr && *seq_nr)) {
|
if (unlikely(lh->l_seq_nr != *seq_nr + 1 && lh->l_seq_nr && *seq_nr)) {
|
||||||
MARS_ERR("log sequence number %u mismatch, expected was %u\n", lh->l_seq_nr, *seq_nr + 1);
|
MARS_ERR(SCAN_TXT "log sequence number %u mismatch, expected was %u\n", SCAN_PAR, lh->l_seq_nr, *seq_nr + 1);
|
||||||
return -EBADMSG;
|
return -EBADMSG;
|
||||||
}
|
}
|
||||||
*seq_nr = lh->l_seq_nr;
|
*seq_nr = lh->l_seq_nr;
|
||||||
|
@ -470,30 +471,31 @@ int log_scan(void *buf, int len, loff_t file_pos, int file_offset, struct log_he
|
||||||
unsigned char checksum[mars_digest_size];
|
unsigned char checksum[mars_digest_size];
|
||||||
mars_digest(checksum, buf + found_offset, lh->l_len);
|
mars_digest(checksum, buf + found_offset, lh->l_len);
|
||||||
if (unlikely(*(int*)checksum != lh->l_crc)) {
|
if (unlikely(*(int*)checksum != lh->l_crc)) {
|
||||||
MARS_ERR("data checksumming mismatch, length = %d\n", lh->l_len);
|
MARS_ERR(SCAN_TXT "data checksumming mismatch, length = %d\n", SCAN_PAR, lh->l_len);
|
||||||
return -EBADMSG;
|
return -EBADMSG;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// last check
|
// last check
|
||||||
if (total_len != offset - i) {
|
if (unlikely(total_len != offset - i)) {
|
||||||
MARS_WRN(SCAN_TXT "size mismatch: %d != %d\n", SCAN_PAR, total_len, offset - i);
|
MARS_ERR(SCAN_TXT "internal size mismatch: %d != %d\n", SCAN_PAR, total_len, offset - i);
|
||||||
// just warn, but no consequences: better use the data, it has been checked by lots of magics
|
return -EBADMSG;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Success...
|
// Success...
|
||||||
*payload = buf + found_offset;
|
*payload = buf + found_offset;
|
||||||
*payload_len = lh->l_len;
|
*payload_len = lh->l_len;
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
offset = i;
|
|
||||||
|
|
||||||
done:
|
|
||||||
// don't cry when nullbytes have been skipped
|
// don't cry when nullbytes have been skipped
|
||||||
if (i > 0 && dirty) {
|
if (i > 0 && dirty) {
|
||||||
MARS_WRN("skipped %d dirty bytes at offset %d to find valid data\n", i, offset);
|
MARS_WRN(SCAN_TXT "skipped %d dirty bytes to find valid data\n", SCAN_PAR, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
return offset;
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
MARS_ERR("could not find any useful data within len=%d bytes\n", len);
|
||||||
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
|
@ -551,6 +553,10 @@ restart:
|
||||||
}
|
}
|
||||||
goto done_free;
|
goto done_free;
|
||||||
}
|
}
|
||||||
|
if (unlikely(mref->ref_len <= OVERHEAD)) { // EOF
|
||||||
|
status = 0;
|
||||||
|
goto done_put;
|
||||||
|
}
|
||||||
|
|
||||||
SETUP_CALLBACK(mref, log_read_endio, logst);
|
SETUP_CALLBACK(mref, log_read_endio, logst);
|
||||||
mref->ref_rw = READ;
|
mref->ref_rw = READ;
|
||||||
|
@ -587,9 +593,9 @@ restart:
|
||||||
goto done_put;
|
goto done_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
// memorize success
|
// memoize success
|
||||||
logst->offset += status;
|
logst->offset += status;
|
||||||
if (logst->offset > mref->ref_len - logst->chunk_size) {
|
if (logst->offset + (logst->max_size + OVERHEAD) * 2 >= mref->ref_len) {
|
||||||
logst->do_free = true;
|
logst->do_free = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue