vitastor/src/disk_tool_journal.cpp

578 lines
24 KiB
C++
Raw Permalink Normal View History

// Copyright (c) Vitaliy Filippov, 2019+
// License: VNPL-1.1 (see README.md for details)
#include "disk_tool.h"
int disk_tool_t::dump_journal()
{
2022-08-20 14:05:53 +03:00
dump_with_blocks = options["format"] == "blocks";
dump_with_data = options["format"] == "data" || options["format"] == "blocks,data";
if (dsk.journal_block_size < DIRECT_IO_ALIGNMENT || (dsk.journal_block_size % DIRECT_IO_ALIGNMENT) ||
dsk.journal_block_size > 128*1024)
{
fprintf(stderr, "Invalid journal block size\n");
return 1;
}
first_block = true;
if (json)
printf("[\n");
if (all)
{
dsk.journal_fd = open(dsk.journal_device.c_str(), O_DIRECT|O_RDONLY);
if (dsk.journal_fd < 0)
{
fprintf(stderr, "Failed to open journal device %s: %s\n", dsk.journal_device.c_str(), strerror(errno));
return 1;
}
void *journal_buf = memalign_or_die(MEM_ALIGNMENT, dsk.journal_block_size);
journal_pos = 0;
while (journal_pos < dsk.journal_len)
{
int r = pread(dsk.journal_fd, journal_buf, dsk.journal_block_size, dsk.journal_offset+journal_pos);
assert(r == dsk.journal_block_size);
uint64_t s;
for (s = 0; s < dsk.journal_block_size; s += 8)
{
if (*((uint64_t*)((uint8_t*)journal_buf+s)) != 0)
break;
}
if (json)
{
printf("%s{\"offset\":\"0x%jx\"", first_block ? "" : ",\n", journal_pos);
first_block = false;
}
if (s == dsk.journal_block_size)
{
if (json)
printf(",\"type\":\"zero\"}");
else
printf("offset %08jx: zeroes\n", journal_pos);
journal_pos += dsk.journal_block_size;
}
else if (((journal_entry*)journal_buf)->magic == JOURNAL_MAGIC)
{
if (!json)
printf("offset %08jx:\n", journal_pos);
else
printf(",\"entries\":[\n");
if (journal_pos == 0)
{
// Fill journal header to know checksum type & size
journal_entry *je = (journal_entry*)journal_buf;
if (je->magic == JOURNAL_MAGIC && je->type == JE_START &&
(je->start.version == JOURNAL_VERSION_V1 || je->start.version == JOURNAL_VERSION_V2))
{
memcpy(&je_start, je, sizeof(je_start));
if (je_start.size == JE_START_V0_SIZE)
je_start.version = 0;
if (je_start.version < JOURNAL_VERSION_V2)
{
je_start.data_csum_type = 0;
je_start.csum_block_size = 0;
}
}
}
first_entry = true;
process_journal_block(journal_buf, [this](int num, journal_entry *je) { dump_journal_entry(num, je, json); });
if (json)
printf(first_entry ? "]}" : "\n]}");
}
else
{
if (json)
printf(",\"type\":\"data\",\"pattern\":\"%08jx\"}", *((uint64_t*)journal_buf));
else
printf("offset %08jx: no magic in the beginning, looks like random data (pattern=%08jx)\n", journal_pos, *((uint64_t*)journal_buf));
journal_pos += dsk.journal_block_size;
}
}
free(journal_buf);
close(dsk.journal_fd);
dsk.journal_fd = -1;
}
else
{
first_entry = true;
process_journal([this](void *data)
{
if (json && dump_with_blocks)
first_entry = true;
if (!json)
printf("offset %08jx:\n", journal_pos);
auto pos = journal_pos;
int r = process_journal_block(data, [this, pos](int num, journal_entry *je)
{
if (json && dump_with_blocks && first_entry)
printf("%s{\"offset\":\"0x%jx\",\"entries\":[\n", first_block ? "" : ",\n", pos);
dump_journal_entry(num, je, json);
first_block = false;
});
if (json && dump_with_blocks && !first_entry)
printf("\n]}");
else if (!json && r <= 0)
printf("end of the journal\n");
return r;
});
}
if (json)
printf(first_block ? "]\n" : "\n]\n");
return 0;
}
int disk_tool_t::process_journal(std::function<int(void*)> block_fn)
{
dsk.journal_fd = open(dsk.journal_device.c_str(), O_DIRECT|O_RDONLY);
if (dsk.journal_fd < 0)
{
fprintf(stderr, "Failed to open journal device %s: %s\n", dsk.journal_device.c_str(), strerror(errno));
return 1;
}
void *data = memalign_or_die(MEM_ALIGNMENT, dsk.journal_block_size);
journal_pos = 0;
int r = pread(dsk.journal_fd, data, dsk.journal_block_size, dsk.journal_offset+journal_pos);
assert(r == dsk.journal_block_size);
journal_entry *je = (journal_entry*)(data);
if (je->magic != JOURNAL_MAGIC || je->type != JE_START || je_crc32(je) != je->crc32)
{
fprintf(stderr, "offset %08jx: journal superblock is invalid\n", journal_pos);
r = 1;
}
else if (je->start.size != JE_START_V0_SIZE && je->start.version != JOURNAL_VERSION_V1 && je->start.version != JOURNAL_VERSION_V2)
{
fprintf(stderr, "offset %08jx: journal superblock contains version %ju, but I only understand 0, 1 and 2\n",
journal_pos, je->start.size == JE_START_V0_SIZE ? 0 : je->start.version);
r = 1;
}
else
{
memcpy(&je_start, je, sizeof(je_start));
if (je_start.size == JE_START_V0_SIZE)
je_start.version = 0;
if (je_start.version < JOURNAL_VERSION_V2)
{
je_start.data_csum_type = 0;
je_start.csum_block_size = 0;
}
started = false;
crc32_last = 0;
block_fn(data);
started = false;
crc32_last = 0;
journal_pos = je->start.journal_start;
while (1)
{
if (journal_pos >= dsk.journal_len)
journal_pos = dsk.journal_block_size;
r = pread(dsk.journal_fd, data, dsk.journal_block_size, dsk.journal_offset+journal_pos);
assert(r == dsk.journal_block_size);
r = block_fn(data);
if (r <= 0)
break;
}
}
close(dsk.journal_fd);
dsk.journal_fd = -1;
free(data);
return r;
}
int disk_tool_t::process_journal_block(void *buf, std::function<void(int, journal_entry*)> iter_fn)
{
uint32_t pos = 0;
journal_pos += dsk.journal_block_size;
int entry = 0;
bool wrapped = false;
while (pos <= dsk.journal_block_size-JOURNAL_ENTRY_HEADER_SIZE)
{
journal_entry *je = (journal_entry*)((uint8_t*)buf + pos);
if (je->magic != JOURNAL_MAGIC || je->type < JE_MIN || je->type > JE_MAX ||
!all && started && je->crc32_prev != crc32_last || pos > dsk.journal_block_size-je->size)
{
break;
}
bool crc32_valid = je_crc32(je) == je->crc32;
if (!all && !crc32_valid)
{
break;
}
started = true;
crc32_last = je->crc32;
if (je->type == JE_SMALL_WRITE || je->type == JE_SMALL_WRITE_INSTANT)
{
journal_calc_data_pos = journal_pos;
if (journal_pos + je->small_write.len > dsk.journal_len)
{
// data continues from the beginning of the journal
journal_calc_data_pos = journal_pos = dsk.journal_block_size;
wrapped = true;
}
journal_pos += je->small_write.len;
if (journal_pos >= dsk.journal_len)
{
journal_pos = dsk.journal_block_size;
wrapped = true;
}
small_write_data = memalign_or_die(MEM_ALIGNMENT, je->small_write.len);
assert(pread(dsk.journal_fd, small_write_data, je->small_write.len, dsk.journal_offset+je->small_write.data_offset) == je->small_write.len);
data_crc32 = je_start.csum_block_size ? 0 : crc32c(0, small_write_data, je->small_write.len);
data_csum_valid = (data_crc32 == je->small_write.crc32_data);
2023-01-19 02:23:27 +03:00
if (je_start.csum_block_size && je->small_write.len > 0)
{
2023-01-19 02:23:27 +03:00
// like in enqueue_write()
uint32_t start = je->small_write.offset / je_start.csum_block_size;
uint32_t end = (je->small_write.offset+je->small_write.len-1) / je_start.csum_block_size;
uint32_t data_csum_size = (end-start+1) * (je_start.data_csum_type & 0xFF);
if (je->size < sizeof(journal_entry_small_write) + data_csum_size)
{
2023-01-19 02:23:27 +03:00
data_csum_valid = false;
}
else
{
uint32_t calc_csum = 0;
uint32_t *block_csums = (uint32_t*)((uint8_t*)je + je->size - data_csum_size);
if (start == end)
{
calc_csum = crc32c(0, (uint8_t*)small_write_data, je->small_write.len);
data_csum_valid = data_csum_valid && (calc_csum == *block_csums++);
}
else
{
2023-01-19 02:23:27 +03:00
// First block
calc_csum = crc32c(0, (uint8_t*)small_write_data,
je_start.csum_block_size*(start+1)-je->small_write.offset);
data_csum_valid = data_csum_valid && (calc_csum == *block_csums++);
// Intermediate blocks
for (uint32_t i = start+1; i < end; i++)
{
calc_csum = crc32c(0, (uint8_t*)small_write_data +
je_start.csum_block_size*i-je->small_write.offset, je_start.csum_block_size);
data_csum_valid = data_csum_valid && (calc_csum == *block_csums++);
}
// Last block
calc_csum = crc32c(
0, (uint8_t*)small_write_data + end*je_start.csum_block_size - je->small_write.offset,
je->small_write.offset+je->small_write.len - end*je_start.csum_block_size
);
data_csum_valid = data_csum_valid && (calc_csum == *block_csums++);
}
}
}
}
iter_fn(entry, je);
if (je->type == JE_SMALL_WRITE || je->type == JE_SMALL_WRITE_INSTANT)
{
free(small_write_data);
small_write_data = NULL;
}
pos += je->size;
entry++;
}
if (wrapped)
{
journal_pos = dsk.journal_len;
}
return entry;
}
void disk_tool_t::dump_journal_entry(int num, journal_entry *je, bool json)
{
if (json)
{
if (!first_entry)
printf(",\n");
first_entry = false;
printf(
"{\"crc32\":\"%08x\",\"valid\":%s,\"crc32_prev\":\"%08x\"",
je->crc32, (je_crc32(je) == je->crc32 ? "true" : "false"), je->crc32_prev
);
}
else
{
printf(
"entry % 3d: crc32=%08x %s prev=%08x ",
num, je->crc32, (je_crc32(je) == je->crc32 ? "(valid)" : "(invalid)"), je->crc32_prev
);
}
if (je->type == JE_START)
{
printf(
json ? ",\"type\":\"start\",\"start\":\"0x%jx\"" : "je_start start=%08jx",
je->start.journal_start
);
if (je->start.data_csum_type)
{
printf(
json ? ",\"data_csum_type\":\"%s\",\"csum_block_size\":%u" : " data_csum_type=%s csum_block_size=%u",
csum_type_str(je->start.data_csum_type).c_str(), je->start.csum_block_size
);
}
printf(json ? "}" : "\n");
}
else if (je->type == JE_SMALL_WRITE || je->type == JE_SMALL_WRITE_INSTANT)
{
2023-01-19 02:23:27 +03:00
auto & sw = je->small_write;
printf(
json ? ",\"type\":\"small_write%s\",\"inode\":\"0x%jx\",\"stripe\":\"0x%jx\",\"ver\":\"%ju\",\"offset\":%u,\"len\":%u,\"loc\":\"0x%jx\""
: "je_small_write%s oid=%jx:%jx ver=%ju offset=%u len=%u loc=%08jx",
je->type == JE_SMALL_WRITE_INSTANT ? "_instant" : "",
2023-01-19 02:23:27 +03:00
sw.oid.inode, sw.oid.stripe, sw.version, sw.offset, sw.len, sw.data_offset
);
2023-01-19 02:23:27 +03:00
if (journal_calc_data_pos != sw.data_offset)
{
printf(json ? ",\"bad_loc\":true,\"calc_loc\":\"0x%jx\""
: " (mismatched, calculated = %08jx)", journal_pos);
}
2023-01-19 02:23:27 +03:00
uint32_t data_csum_size = (!je_start.csum_block_size
? 0
: ((sw.offset + sw.len - 1)/je_start.csum_block_size - sw.offset/je_start.csum_block_size + 1)
*(je_start.data_csum_type & 0xFF));
if (je->size > sizeof(journal_entry_small_write) + data_csum_size)
2022-08-20 14:05:53 +03:00
{
printf(json ? ",\"bitmap\":\"" : " (bitmap: ");
for (int i = sizeof(journal_entry_small_write); i < je->size - data_csum_size; i++)
2022-08-20 14:05:53 +03:00
{
printf("%02x", ((uint8_t*)je)[i]);
}
printf(json ? "\"" : ")");
}
if (dump_with_data)
{
printf(json ? ",\"data\":\"" : " (data: ");
2023-01-19 02:23:27 +03:00
for (int i = 0; i < sw.len; i++)
2022-08-20 14:05:53 +03:00
{
printf("%02x", ((uint8_t*)small_write_data)[i]);
}
printf(json ? "\"" : ")");
}
2023-01-19 02:23:27 +03:00
if (data_csum_size > 0 && je->size >= sizeof(journal_entry_small_write) + data_csum_size)
{
printf(json ? ",\"block_csums\":\"" : " block_csums=");
uint8_t *block_csums = (uint8_t*)je + je->size - data_csum_size;
for (int i = 0; i < data_csum_size; i++)
printf("%02x", block_csums[i]);
printf(json ? "\"" : "");
}
else
{
2023-01-19 02:23:27 +03:00
printf(json ? ",\"data_crc32\":\"%08x\"" : " data_crc32=%08x", sw.crc32_data);
}
printf(
json ? ",\"data_valid\":%s}" : "%s\n",
(data_csum_valid
2023-01-19 02:23:27 +03:00
? (json ? "true" : " (valid)")
: (json ? "false" : " (invalid)"))
);
}
else if (je->type == JE_BIG_WRITE || je->type == JE_BIG_WRITE_INSTANT)
{
2023-01-19 02:23:27 +03:00
auto & bw = je->big_write;
printf(
json ? ",\"type\":\"big_write%s\",\"inode\":\"0x%jx\",\"stripe\":\"0x%jx\",\"ver\":\"%ju\",\"offset\":%u,\"len\":%u,\"loc\":\"0x%jx\""
: "je_big_write%s oid=%jx:%jx ver=%ju offset=%u len=%u loc=%08jx",
je->type == JE_BIG_WRITE_INSTANT ? "_instant" : "",
2023-01-19 02:23:27 +03:00
bw.oid.inode, bw.oid.stripe, bw.version, bw.offset, bw.len, bw.location
);
2023-01-19 02:23:27 +03:00
uint32_t data_csum_size = (!je_start.csum_block_size
? 0
: ((bw.offset + bw.len - 1)/je_start.csum_block_size - bw.offset/je_start.csum_block_size + 1)
*(je_start.data_csum_type & 0xFF));
if (data_csum_size > 0 && je->size >= sizeof(journal_entry_big_write) + data_csum_size)
{
printf(json ? ",\"block_csums\":\"" : " block_csums=");
uint8_t *block_csums = (uint8_t*)je + je->size - data_csum_size;
for (int i = 0; i < data_csum_size; i++)
printf("%02x", block_csums[i]);
printf(json ? "\"" : "");
}
2023-01-19 02:23:27 +03:00
if (bw.size > sizeof(journal_entry_big_write) + data_csum_size)
2022-08-20 14:05:53 +03:00
{
printf(json ? ",\"bitmap\":\"" : " (bitmap: ");
2023-01-19 02:23:27 +03:00
for (int i = sizeof(journal_entry_big_write); i < bw.size - data_csum_size; i++)
2022-08-20 14:05:53 +03:00
{
printf("%02x", ((uint8_t*)je)[i]);
}
printf(json ? "\"" : ")");
}
printf(json ? "}" : "\n");
}
else if (je->type == JE_STABLE)
{
printf(
json ? ",\"type\":\"stable\",\"inode\":\"0x%jx\",\"stripe\":\"0x%jx\",\"ver\":\"%ju\"}"
: "je_stable oid=%jx:%jx ver=%ju\n",
je->stable.oid.inode, je->stable.oid.stripe, je->stable.version
);
}
else if (je->type == JE_ROLLBACK)
{
printf(
json ? ",\"type\":\"rollback\",\"inode\":\"0x%jx\",\"stripe\":\"0x%jx\",\"ver\":\"%ju\"}"
: "je_rollback oid=%jx:%jx ver=%ju\n",
je->rollback.oid.inode, je->rollback.oid.stripe, je->rollback.version
);
}
else if (je->type == JE_DELETE)
{
printf(
json ? ",\"type\":\"delete\",\"inode\":\"0x%jx\",\"stripe\":\"0x%jx\",\"ver\":\"%ju\"}"
: "je_delete oid=%jx:%jx ver=%ju\n",
je->del.oid.inode, je->del.oid.stripe, je->del.version
);
}
}
2022-08-20 14:05:53 +03:00
int disk_tool_t::write_json_journal(json11::Json entries)
{
new_journal_buf = (uint8_t*)memalign_or_die(MEM_ALIGNMENT, new_journal_len);
new_journal_ptr = new_journal_buf;
new_journal_data = new_journal_ptr + dsk.journal_block_size;
new_journal_in_pos = 0;
memset(new_journal_buf, 0, new_journal_len);
std::map<std::string,uint16_t> type_by_name = {
{ "start", JE_START },
{ "small_write", JE_SMALL_WRITE },
{ "small_write_instant", JE_SMALL_WRITE_INSTANT },
{ "big_write", JE_BIG_WRITE },
{ "big_write_instant", JE_BIG_WRITE_INSTANT },
{ "stable", JE_STABLE },
{ "delete", JE_DELETE },
{ "rollback", JE_ROLLBACK },
};
2022-08-20 15:07:28 +03:00
// Write start entry into the first block
*((journal_entry_start*)new_journal_buf) = (journal_entry_start){
.magic = JOURNAL_MAGIC,
.type = JE_START,
.size = sizeof(journal_entry_start),
.journal_start = dsk.journal_block_size,
.version = JOURNAL_VERSION_V2,
.data_csum_type = dsk.data_csum_type,
.csum_block_size = dsk.csum_block_size,
2022-08-20 15:07:28 +03:00
};
((journal_entry*)new_journal_buf)->crc32 = je_crc32((journal_entry*)new_journal_buf);
new_journal_ptr += dsk.journal_block_size;
new_journal_data = new_journal_ptr+dsk.journal_block_size;
new_journal_in_pos = 0;
2022-08-20 14:05:53 +03:00
for (const auto & rec: entries.array_items())
{
auto t_it = type_by_name.find(rec["type"].string_value());
if (t_it == type_by_name.end())
{
fprintf(stderr, "Unknown journal entry type \"%s\", skipping\n", rec["type"].string_value().c_str());
continue;
}
uint16_t type = t_it->second;
2022-08-20 15:07:28 +03:00
if (type == JE_START)
continue;
2022-08-20 14:05:53 +03:00
uint32_t entry_size = (type == JE_START
? sizeof(journal_entry_start)
: (type == JE_SMALL_WRITE || type == JE_SMALL_WRITE_INSTANT
? sizeof(journal_entry_small_write) + dsk.clean_entry_bitmap_size +
(dsk.data_csum_type ? rec["len"].uint64_value()/dsk.csum_block_size*(dsk.data_csum_type & 0xFF) : 0)
2022-08-20 14:05:53 +03:00
: (type == JE_BIG_WRITE || type == JE_BIG_WRITE_INSTANT
? sizeof(journal_entry_big_write) + dsk.clean_entry_bitmap_size +
(dsk.data_csum_type ? rec["len"].uint64_value()/dsk.csum_block_size*(dsk.data_csum_type & 0xFF) : 0)
2022-08-20 14:05:53 +03:00
: sizeof(journal_entry_del))));
if (dsk.journal_block_size < new_journal_in_pos + entry_size)
{
new_journal_ptr = new_journal_data;
if (new_journal_ptr-new_journal_buf >= new_journal_len)
{
fprintf(stderr, "Error: entries don't fit to the new journal\n");
free(new_journal_buf);
return 1;
}
new_journal_data = new_journal_ptr+dsk.journal_block_size;
new_journal_in_pos = 0;
if (dsk.journal_block_size < entry_size)
{
fprintf(stderr, "Error: journal entry too large (%u bytes)\n", entry_size);
free(new_journal_buf);
return 1;
}
}
journal_entry *ne = (journal_entry*)(new_journal_ptr + new_journal_in_pos);
2022-08-20 15:07:28 +03:00
if (type == JE_SMALL_WRITE || type == JE_SMALL_WRITE_INSTANT)
2022-08-20 14:05:53 +03:00
{
if (new_journal_data - new_journal_buf + ne->small_write.len > new_journal_len)
{
fprintf(stderr, "Error: entries don't fit to the new journal\n");
free(new_journal_buf);
return 1;
}
*((journal_entry_small_write*)ne) = (journal_entry_small_write){
.magic = JOURNAL_MAGIC,
.type = type,
.size = entry_size,
.crc32_prev = new_crc32_prev,
.oid = {
2022-08-20 15:07:28 +03:00
.inode = sscanf_json(NULL, rec["inode"]),
.stripe = sscanf_json(NULL, rec["stripe"]),
2022-08-20 14:05:53 +03:00
},
.version = rec["ver"].uint64_value(),
.offset = (uint32_t)rec["offset"].uint64_value(),
.len = (uint32_t)rec["len"].uint64_value(),
.data_offset = (uint64_t)(new_journal_data-new_journal_buf),
.crc32_data = !dsk.data_csum_type ? 0 : (uint32_t)sscanf_json("%x", rec["data_crc32"]),
2022-08-20 14:05:53 +03:00
};
uint32_t data_csum_size = !dsk.data_csum_type ? 0 : ne->small_write.len/dsk.csum_block_size*(dsk.data_csum_type & 0xFF);
fromhexstr(rec["bitmap"].string_value(), dsk.clean_entry_bitmap_size, ((uint8_t*)ne) + sizeof(journal_entry_small_write) + data_csum_size);
2022-08-20 14:05:53 +03:00
fromhexstr(rec["data"].string_value(), ne->small_write.len, new_journal_data);
if (dsk.data_csum_type)
fromhexstr(rec["block_csums"].string_value(), data_csum_size, ((uint8_t*)ne) + sizeof(journal_entry_small_write));
2022-08-20 14:05:53 +03:00
if (rec["data"].is_string())
{
if (!dsk.data_csum_type)
ne->small_write.crc32_data = crc32c(0, new_journal_data, ne->small_write.len);
else if (dsk.data_csum_type == BLOCKSTORE_CSUM_CRC32C)
{
uint32_t *block_csums = (uint32_t*)(((uint8_t*)ne) + sizeof(journal_entry_small_write));
for (uint32_t i = 0; i < ne->small_write.len; i += dsk.csum_block_size, block_csums++)
*block_csums = crc32c(0, new_journal_data+i, dsk.csum_block_size);
}
}
2022-08-20 14:05:53 +03:00
new_journal_data += ne->small_write.len;
}
else if (type == JE_BIG_WRITE || type == JE_BIG_WRITE_INSTANT)
{
*((journal_entry_big_write*)ne) = (journal_entry_big_write){
.magic = JOURNAL_MAGIC,
.type = type,
.size = entry_size,
.crc32_prev = new_crc32_prev,
.oid = {
2022-08-20 15:07:28 +03:00
.inode = sscanf_json(NULL, rec["inode"]),
.stripe = sscanf_json(NULL, rec["stripe"]),
2022-08-20 14:05:53 +03:00
},
.version = rec["ver"].uint64_value(),
.offset = (uint32_t)rec["offset"].uint64_value(),
.len = (uint32_t)rec["len"].uint64_value(),
2022-08-20 15:07:28 +03:00
.location = sscanf_json(NULL, rec["loc"]),
2022-08-20 14:05:53 +03:00
};
uint32_t data_csum_size = !dsk.data_csum_type ? 0 : ne->big_write.len/dsk.csum_block_size*(dsk.data_csum_type & 0xFF);
fromhexstr(rec["bitmap"].string_value(), dsk.clean_entry_bitmap_size, ((uint8_t*)ne) + sizeof(journal_entry_big_write) + data_csum_size);
if (dsk.data_csum_type)
fromhexstr(rec["block_csums"].string_value(), data_csum_size, ((uint8_t*)ne) + sizeof(journal_entry_big_write));
2022-08-20 14:05:53 +03:00
}
else if (type == JE_STABLE || type == JE_ROLLBACK || type == JE_DELETE)
{
*((journal_entry_del*)ne) = (journal_entry_del){
.magic = JOURNAL_MAGIC,
.type = type,
.size = entry_size,
.crc32_prev = new_crc32_prev,
.oid = {
2022-08-20 15:07:28 +03:00
.inode = sscanf_json(NULL, rec["inode"]),
.stripe = sscanf_json(NULL, rec["stripe"]),
2022-08-20 14:05:53 +03:00
},
.version = rec["ver"].uint64_value(),
};
}
ne->crc32 = je_crc32(ne);
new_crc32_prev = ne->crc32;
new_journal_in_pos += ne->size;
}
int r = resize_write_new_journal();
free(new_journal_buf);
return r;
}