Linux 5.6: failed to compile
k0ste opened this issue · comments
Konstantin Shalygin commented
Making all...
ccflags-y= -O2 -Wno-multichar -DDISTRIB_NAME_ARCH -DDISTRIB_VERSION_1=1
make -C /lib/modules/5.6.2-arch1-2/build M=/tmp/veeamsnap/source modules
make[1]: Entering directory '/usr/lib/modules/5.6.2-arch1-2/build'
CC [M] /tmp/veeamsnap/source/log.o
In file included from /tmp/veeamsnap/source/stdafx.h:39,
from /tmp/veeamsnap/source/log.c:1:
/tmp/veeamsnap/source/log.h:25:80: error: unknown type name ‘time_t’
25 | void log_s_sec(const char* section, const unsigned level, const char* s, const time_t totalsecs);
| ^~~~~~
/tmp/veeamsnap/source/log.c:43:21: error: field ‘m_time’ has incomplete type
43 | struct timespec m_time;
| ^~~~~~
/tmp/veeamsnap/source/log.c:68:21: error: field ‘m_modify_time’ has incomplete type
68 | struct timespec m_modify_time;
| ^~~~~~~~~~~~~
/tmp/veeamsnap/source/log.c: In function ‘_logging_filename_create’:
/tmp/veeamsnap/source/log.c:187:9: error: implicit declaration of function ‘getnstimeofday’ [-Werror=implicit-function-declaration]
187 | getnstimeofday(&logging->m_modify_time);
| ^~~~~~~~~~~~~~
/tmp/veeamsnap/source/log.c: In function ‘_logging_check_renew’:
/tmp/veeamsnap/source/log.c:224:21: error: storage size of ‘_time’ isn’t known
224 | struct timespec _time;
| ^~~~~
/tmp/veeamsnap/source/log.c:224:21: warning: unused variable ‘_time’ [-Wunused-variable]
/tmp/veeamsnap/source/log.c: In function ‘logging_init’:
/tmp/veeamsnap/source/log.c:454:49: error: invalid application of ‘sizeof’ to incomplete type ‘struct timespec’
454 | memset( &logging->m_modify_time, 0, sizeof( struct timespec ) );
| ^~~~~~
/tmp/veeamsnap/source/log.c: At top level:
/tmp/veeamsnap/source/log.c:692:80: error: unknown type name ‘time_t’
692 | void log_s_sec(const char* section, const unsigned level, const char* s, const time_t totalsecs)
| ^~~~~~
cc1: some warnings being treated as errors
make[2]: *** [scripts/Makefile.build:268: /tmp/veeamsnap/source/log.o] Error 1
make[1]: *** [Makefile:1683: /tmp/veeamsnap/source] Error 2
make[1]: Leaving directory '/usr/lib/modules/5.6.2-arch1-2/build'
make: *** [Makefile:77: all] Error 2
redrum781 commented
I think it's due to kernel 5.6 resolved time bug.
I got it to compile by basically changing time_t to uint64_t, timespec to timespec64 and getnstimeofday to ktime_get_ts64 in log.h, log.c, cbt_storage.h and cbt_storage.c:
--- Downloads/veeamsnap-master/source/log.h 2020-02-18 12:26:51.000000000 +0100
+++ /usr/src/veeamsnap-4.0.0.1961/log.h 2020-04-08 10:53:55.915475583 +0200
@@ -24,3 +24,3 @@
void log_format( const char* section, const int level, const char* frm, ... );
-void log_s_sec(const char* section, const unsigned level, const char* s, const time_t totalsecs);
+void log_s_sec(const char* section, const unsigned level, const char* s, const uint64_t totalsecs);
///////////////////////////////////////////////////////////////////////////////
--- Downloads/veeamsnap-master/source/log.c 2020-02-18 12:26:51.000000000 +0100
+++ /usr/src/veeamsnap-4.0.0.1961/log.c 2020-04-08 11:09:09.264306329 +0200
@@ -42,3 +42,3 @@
- struct timespec m_time;
+ struct timespec64 m_time;
pid_t m_pid;
@@ -67,3 +67,3 @@
char m_filepath[MAX_FILENAME_SIZE];
- struct timespec m_modify_time;
+ struct timespec64 m_modify_time;
@@ -186,3 +186,3 @@
struct tm modify_time;
- getnstimeofday(&logging->m_modify_time);
+ ktime_get_ts64(&logging->m_modify_time);
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,20,0)
@@ -223,3 +223,3 @@
loff_t sz = 0;
- struct timespec _time;
+ struct timespec64 _time;
struct tm current_time;
@@ -232,3 +232,3 @@
- getnstimeofday( &_time );
+ ktime_get_ts64( &_time );
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,20,0)
@@ -453,3 +453,3 @@
logging->m_filp = NULL;
- memset( &logging->m_modify_time, 0, sizeof( struct timespec ) );
+ memset( &logging->m_modify_time, 0, sizeof( struct timespec64 ) );
logging->m_state = LOGGING_STATE_READY;
@@ -509,3 +509,3 @@
rq->m_pid = get_current( )->pid;
- getnstimeofday( &rq->m_time );
+ ktime_get_ts64( &rq->m_time );
@@ -691,3 +691,3 @@
-void log_s_sec(const char* section, const unsigned level, const char* s, const time_t totalsecs)
+void log_s_sec(const char* section, const unsigned level, const char* s, const uint64_t totalsecs)
{
--- Downloads/veeamsnap-master/source/cbt_storage.h 2020-02-18 12:26:51.000000000 +0100
+++ /usr/src/veeamsnap-4.0.0.1961/cbt_storage.h 2020-04-08 11:10:45.846700785 +0200
@@ -1,49 +1,49 @@
-#pragma once
-#ifdef PERSISTENT_CBT
-
-#define CBT_STORAGE_MAGIC "vcbtdata"
-
-typedef struct cbt_storage_page_s
-{
- char magic[8];
- uint32_t crc;
- uint32_t number;
- uint64_t tv_sec; // seconds
- uint32_t tv_nsec; // nanoseconds
- uint32_t padding0;
- unsigned char data[0];
-} cbt_storage_page_t;
-
-#define CBT_PAGE_DATA_SIZE (PAGE_SIZE - offsetof(cbt_storage_page_t, data))
-
-typedef struct cbt_storage_accessor_s
-{
- struct block_device* device;
- rangevector_t* rangevector;
-
- struct timespec time;//cbt data time marker
-
- struct page* pg;
- cbt_storage_page_t* page;
-
- unsigned long long page_count;
- unsigned long long page_number;
- unsigned long long used_page_count;
- size_t page_offset;
-
-}cbt_storage_accessor_t;
-
-
-int cbt_storage_open(cbt_persistent_parameters_t* params, cbt_storage_accessor_t* accessor);
-void cbt_storage_close(cbt_storage_accessor_t* accessor);
-
-int cbt_storage_check(cbt_storage_accessor_t* accessor);
-
-int cbt_storage_prepare4read(cbt_storage_accessor_t* accessor);
-int cbt_storage_prepare4write(cbt_storage_accessor_t* accessor);
-
-int cbt_storage_read(cbt_storage_accessor_t* accessor, void* dst, size_t sz);
-int cbt_storage_write(cbt_storage_accessor_t* accessor, void* src, size_t sz);
-int cbt_storage_write_finish(cbt_storage_accessor_t* accessor);
-
-#endif//PERSISTENT_CBT
+#pragma once
+#ifdef PERSISTENT_CBT
+
+#define CBT_STORAGE_MAGIC "vcbtdata"
+
+typedef struct cbt_storage_page_s
+{
+ char magic[8];
+ uint32_t crc;
+ uint32_t number;
+ uint64_t tv_sec; // seconds
+ uint32_t tv_nsec; // nanoseconds
+ uint32_t padding0;
+ unsigned char data[0];
+} cbt_storage_page_t;
+
+#define CBT_PAGE_DATA_SIZE (PAGE_SIZE - offsetof(cbt_storage_page_t, data))
+
+typedef struct cbt_storage_accessor_s
+{
+ struct block_device* device;
+ rangevector_t* rangevector;
+
+ struct timespec64 time;//cbt data time marker
+
+ struct page* pg;
+ cbt_storage_page_t* page;
+
+ unsigned long long page_count;
+ unsigned long long page_number;
+ unsigned long long used_page_count;
+ size_t page_offset;
+
+}cbt_storage_accessor_t;
+
+
+int cbt_storage_open(cbt_persistent_parameters_t* params, cbt_storage_accessor_t* accessor);
+void cbt_storage_close(cbt_storage_accessor_t* accessor);
+
+int cbt_storage_check(cbt_storage_accessor_t* accessor);
+
+int cbt_storage_prepare4read(cbt_storage_accessor_t* accessor);
+int cbt_storage_prepare4write(cbt_storage_accessor_t* accessor);
+
+int cbt_storage_read(cbt_storage_accessor_t* accessor, void* dst, size_t sz);
+int cbt_storage_write(cbt_storage_accessor_t* accessor, void* src, size_t sz);
+int cbt_storage_write_finish(cbt_storage_accessor_t* accessor);
+
+#endif//PERSISTENT_CBT
--- Downloads/veeamsnap-master/source/cbt_storage.c 2020-02-18 12:26:51.000000000 +0100
+++ /usr/src/veeamsnap-4.0.0.1961/cbt_storage.c 2020-04-08 11:17:04.156543224 +0200
@@ -1,460 +1,460 @@
-#include "stdafx.h"
-#ifdef PERSISTENT_CBT
-
-#include "rangevector.h"
-#include "cbt_params.h"
-#include "cbt_storage.h"
-#include "sector.h"
-#include "blk_direct.h"
-#include <linux/crc32.h>
-
-#define SECTION "cbt_store "
-#include "log_format.h"
-
-
-static int _cbt_storage_read_page(cbt_storage_accessor_t* accessor)
-{
- int res;
- sector_t phys_offset = 0;
- sector_t phys_length = 0;
- uint32_t crc;
-
- res = rangevector_v2p(accessor->rangevector, accessor->page_number * sector_from_uint(PAGE_SIZE), sector_from_uint(PAGE_SIZE), &phys_offset, &phys_length);
- if (res != SUCCESS){
- log_err("Failed to get real disk offset for persistent CBT data");
- return res;
- }
-
- if (phys_length != sector_from_uint(PAGE_SIZE)){
- log_err_sect("Unordered range size: ", phys_length);
- log_err("Range is not ordered by PAGE_SIZE");
- return -EINVAL;
- }
-
- res = blk_direct_submit_page(accessor->device, READ_SYNC, phys_offset, accessor->pg);
- if (res != SUCCESS){
- log_err("Failed to read device");
- log_err_sect("Real device offset: ", phys_offset);
- return res;
- }
-
- //check magic
- if (0 != memcmp(accessor->page->magic, CBT_STORAGE_MAGIC, 8)){
- log_err("Invalid CBT data header. Magic mismatch.");
- log_err_sect("device offset=", phys_offset);
- log_err_sect("avaliable sectors=", phys_length);
- log_err("Page header:");
- log_err_bytes((unsigned char*)accessor->page, sizeof(cbt_storage_page_t));
- return -EINVAL;
- }
-
- //chech CRC32
- crc = crc32(~0, (void*)(accessor->page) + offsetof(cbt_storage_page_t, number), PAGE_SIZE - offsetof(cbt_storage_page_t, number));
- if (crc != accessor->page->crc){
- log_err_lld("Invalid CRC32 on page #", accessor->page_number);
- log_err_sect("Physical offset on block device: ", phys_offset);
- log_err_lx("Expected crc=", crc);
- log_err_lx("Read crc=", accessor->page->crc);
- return -EINVAL;
- }
-
- if (accessor->page_number != accessor->page->number){
- log_err("Invalid cbt data page number");
- log_err_lld("Expected=", accessor->page_number);
- log_err_lld("Read=", accessor->page->number);
- return -EINVAL;
- }
-
- return SUCCESS;
-}
-
-static int _cbt_storage_write_page(cbt_storage_accessor_t* accessor, struct timespec* optional_time)
-{
- int res;
- sector_t phys_offset = 0;
- sector_t phys_length = 0;
-
- log_tr_d("DEBUG! write page# ", accessor->page_number);
-
- //set magic
- memcpy(accessor->page->magic, CBT_STORAGE_MAGIC, 8);
- //set number
- accessor->page->number = accessor->page_number;
- //set time marker
- if (optional_time){
- accessor->page->tv_sec = optional_time->tv_sec;
- accessor->page->tv_nsec = optional_time->tv_nsec;
- }
- else{
- accessor->page->tv_sec = accessor->time.tv_sec;
- accessor->page->tv_nsec = accessor->time.tv_nsec;
- }
- //calculate CRC32
- accessor->page->crc = crc32(~0, (void*)(accessor->page) + offsetof(cbt_storage_page_t, number), PAGE_SIZE - offsetof(cbt_storage_page_t, number));
-
- res = rangevector_v2p(accessor->rangevector, accessor->page_number * sector_from_uint(PAGE_SIZE), sector_from_uint(PAGE_SIZE), &phys_offset, &phys_length);
- if (res != SUCCESS){
- log_err("Failed to get real disk offset for persistent CBT data");
- return res;
- }
-
- if (phys_length != sector_from_uint(PAGE_SIZE)){
- log_err_sect("Unordered range size: ", phys_length);
- log_err("Range is not ordered by PAGE_SIZE");
- return -EINVAL;
- }
-
- //write page
- log_tr_sect("DEBUG! offset= ", phys_offset);
- res = blk_direct_submit_page(accessor->device, WRITE_SYNC, phys_offset, accessor->pg);
- if (res != SUCCESS){
- log_err("Failed to read device");
- log_err_sect("Real device offset: ", phys_offset);
- return res;
- }
-
- return SUCCESS;
-}
-
-int cbt_storage_open(cbt_persistent_parameters_t* params, cbt_storage_accessor_t* accessor)
-{
- int res = SUCCESS;
- log_tr_dev_t("Open persistent CBT storage device ",params->dev_id);
-
- res = blk_dev_open(params->dev_id, &accessor->device);
- if (res != SUCCESS){
- log_err_dev_t("Failed to open device ", params->dev_id);
- return res;
- }
- do{
- if (0 == rangevector_cnt(¶ms->rangevector)){
- log_err("No range for reading");
- res = -EINVAL;
- break;
- }
-
- //allocate page
- if (NULL == (accessor->pg = alloc_page(GFP_KERNEL))){
- log_err("Failed to allocate page");
- res = -ENOMEM;
- break;
- }
- accessor->page = (cbt_storage_page_t*)page_address(accessor->pg);
-
- accessor->rangevector = ¶ms->rangevector;
- accessor->page_count = rangevector_length(accessor->rangevector) / sector_from_uint(PAGE_SIZE);
- accessor->page_number = 0;
- accessor->used_page_count = accessor->page_count;
- accessor->page_offset = offsetof(cbt_storage_page_t, data);
-
- } while (false);
- if (res != SUCCESS)
- cbt_storage_close(accessor);
- return res;
-}
-
-void cbt_storage_close(cbt_storage_accessor_t* accessor)
-{
- if (accessor->pg != NULL){
- __free_page(accessor->pg);
- accessor->pg = NULL;
- accessor->page = NULL;
- }
- if (accessor->device != NULL){
- log_tr("Close persistent CBT storage device ");
-
- blk_dev_close(accessor->device);
- accessor->device = NULL;
- }
- accessor->rangevector = NULL;
-}
-
-int cbt_storage_check(cbt_storage_accessor_t* accessor)
-{
- int res = SUCCESS;
- //check all pages
-
- //log_tr("[TBD] Checking CRC32 for all pages:");
- accessor->page_number = 0;
- accessor->used_page_count = accessor->page_count;
- res = _cbt_storage_read_page(accessor);
- if (res != SUCCESS){
- log_err("Failed to get first page ");
- return res;
- }
- //get time from first page
- accessor->time.tv_sec = accessor->page->tv_sec;
- accessor->time.tv_nsec = accessor->page->tv_nsec;
-
- if (accessor->time.tv_sec == 0ull){
- log_tr("Persistent CBT data is empty");
- accessor->used_page_count = 0;
- }
-
- for (accessor->page_number = 1; accessor->page_number < accessor->page_count; ++accessor->page_number){
- res = _cbt_storage_read_page(accessor);
- if (res != SUCCESS){
- log_err_lld("Failed to get page #", accessor->page_number);
- break;
- }
- if (accessor->time.tv_sec != 0ull){
- if (accessor->page->tv_sec == 0ull){
- //unused page found
- if (accessor->used_page_count == accessor->page_count){
- accessor->used_page_count = accessor->page_number;
- log_tr_lld("Found first unused page #", accessor->page_number);
- }
- }
- else{
- if ((accessor->time.tv_sec != accessor->page->tv_sec) && (accessor->time.tv_nsec != accessor->page->tv_nsec))
- {
- log_err_lld("Invalid time marker on page #", accessor->page_number);
- log_err_llx("Expected=", accessor->time.tv_sec);
- log_err_llx("Read=", accessor->page->tv_sec);
-
- //cbt data skipped
- accessor->time.tv_sec = 0ull;
- accessor->time.tv_nsec = 0ul;
-
- break;
- }
- }
- }
- }
-
- if (res != SUCCESS){
- log_err("Check failed");
- return res;
- }
-
- if (accessor->time.tv_sec != 0ull){
- //show time
- struct tm modify_time;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(4,20,0)
- time_to_tm(accessor->time.tv_sec, 0, &modify_time);
-#else
- time64_to_tm(accessor->time.tv_sec, 0, &modify_time);
-#endif
- log_tr_format("Persistent CBT data from %04ld.%02d.%02d %02ld:%02d:%02d %d",
- modify_time.tm_year + 1900,
- modify_time.tm_mon + 1,
- modify_time.tm_mday,
- modify_time.tm_hour,
- modify_time.tm_min,
- modify_time.tm_sec,
- accessor->time.tv_nsec);
- }
-
- return res;
-}
-
-
-int cbt_storage_prepare4read(cbt_storage_accessor_t* accessor)
-{
- int res = SUCCESS;
-
- //set position to first page
- accessor->page_number = 0;
- accessor->page_offset = 0;
-
- res = _cbt_storage_read_page(accessor);
- if (res != SUCCESS){
- log_err("Failed to get first page ");
- return res;
- }
- //check time from fisrt page
- accessor->time.tv_sec = accessor->page->tv_sec;
- accessor->time.tv_nsec = accessor->page->tv_nsec;
-
- if (accessor->time.tv_sec == 0ull)
- return ENODATA;
-
- //set CBT data empty
- {
- struct timespec tm = {0}; //
- res = _cbt_storage_write_page(accessor, &tm);
- if (res != SUCCESS){
- log_err("Failed to write first page ");
- return res;
- }
- }
-
- return res;
-}
-
-int cbt_storage_prepare4write(cbt_storage_accessor_t* accessor)
-{
- int res = SUCCESS;
- //set position to first page
- accessor->page_number = 0;
- accessor->page_offset = 0;
-
- res = _cbt_storage_read_page(accessor);
- if (res != SUCCESS){
- log_err("Failed to get first page ");
- return res;
- }
- //get time
- getnstimeofday(&accessor->time);
-
- return res;
-}
-
-int cbt_storage_read(cbt_storage_accessor_t* accessor, void* dst, size_t sz)
-{
- int res = SUCCESS;
- size_t ofs = 0;
- size_t can_be_read;
- if (accessor->page_number == accessor->page_count){
- log_err_lld("EOF reached, page number ", accessor->page_number);
- return -ENODATA;
- }
-
- can_be_read = min(CBT_PAGE_DATA_SIZE - accessor->page_offset, sz - ofs);
- memcpy(dst, accessor->page->data + accessor->page_offset, can_be_read);
- accessor->page_offset += can_be_read;
- ofs += can_be_read;
-
- do{
- if (accessor->page_offset == CBT_PAGE_DATA_SIZE) {
- accessor->page_number++;
- accessor->page_offset = 0;
- }
-
- if (accessor->page_number == accessor->page_count){
- if (ofs < sz){
- log_err_lld("EOF reached, page number= ", accessor->page_number);
- res = -ENODATA;
- }
- else{
- log_tr("Reached EOF");
- res = SUCCESS;
- }
- break;
- }
-
- //read next page
- res = _cbt_storage_read_page(accessor);
- if (res != SUCCESS){
- log_err_lld("Failed to get page #", accessor->page_number);
- return res;
- }
-
- if (ofs == sz)
- break;//reading is complete
-
- can_be_read = min(CBT_PAGE_DATA_SIZE - accessor->page_offset, sz - ofs);
- memcpy(dst, accessor->page->data + accessor->page_offset, can_be_read);
- accessor->page_offset += can_be_read;
- ofs += can_be_read;
-
- } while (true);
- return res;
-}
-
-int cbt_storage_write(cbt_storage_accessor_t* accessor, void* src, size_t sz)
-{
- int res = SUCCESS;
- size_t ofs = 0;
- size_t can_be_write;
-
- if (accessor->page_number == accessor->page_count){
- log_err_lld("Reached EOF, page number= ", accessor->page_number);
- return -ENODATA;
- }
-
- can_be_write = min(CBT_PAGE_DATA_SIZE - accessor->page_offset, sz - ofs);
- log_tr_sz("DEBUG! can_be_write=", can_be_write);
- if (can_be_write == 0){
- log_tr_format("can_be_write is zero. sz=%lu, ofs=%lu page_offset=%lu", (unsigned long)(sz), (unsigned long)(ofs), (unsigned long)(accessor->page_offset));
- return -EFAULT;
- }
-
- memcpy(accessor->page->data + accessor->page_offset, src + ofs, can_be_write);
- accessor->page_offset += can_be_write;
- ofs += can_be_write;
-
- do{
- if (accessor->page_offset == CBT_PAGE_DATA_SIZE){
- //write current page
- res = _cbt_storage_write_page(accessor, NULL);
- if (res != SUCCESS){
- log_err_lld("Failed to get page #", accessor->page_number);
- return res;
- }
-
- accessor->page_number++;
- accessor->page_offset = 0;
- }
-
- if (accessor->page_number == accessor->page_count){
- if (ofs < sz){
- log_err_lld("Reached EOF, page number= ", accessor->page_number);
- res = -ENODATA;
- }
- else{
- log_tr("Reached EOF");
- res = SUCCESS;
- }
- break;
- }
-
- if (ofs == sz)
- break;//writing is complete
-
- can_be_write = min(CBT_PAGE_DATA_SIZE - accessor->page_offset, sz - ofs);
- log_tr_sz("DEBUG! can_be_write=", can_be_write);
- if (can_be_write == 0){
- log_tr_format("can_be_write is zero. sz=%lu, ofs=%lu page_offset=%lu", (unsigned long)sz, (unsigned long)ofs, (unsigned long)accessor->page_offset);
- return -EFAULT;
- }
- memcpy(accessor->page->data + accessor->page_offset, src + ofs, can_be_write);
- accessor->page_offset += can_be_write;
- ofs += can_be_write;
-
- } while (true);
-
- return res;
-}
-
-int cbt_storage_write_finish(cbt_storage_accessor_t* accessor)
-{
- int res = SUCCESS;
-
- if (accessor->page_number == accessor->page_count)
- return SUCCESS;
-
- //write last page
- log_tr_lld("DEBUG! write last page #", accessor->page_number);
-
- res = _cbt_storage_write_page(accessor, NULL);
- if (res != SUCCESS){
- log_err_lld("Failed to get page #", accessor->page_number);
- return res;
- }
-
- accessor->page_number++;
- accessor->page_offset = 0;
-
- {//store empty unused pages
- struct timespec tm = {0};
- memset(accessor->page->data, 0, CBT_PAGE_DATA_SIZE);
-
- while (accessor->page_number < accessor->page_count){
-
- accessor->page->number = accessor->page_number;
-
- //log_tr_lld("DEBUG! write empty page #", accessor->page_number);
- res = _cbt_storage_write_page(accessor, &tm);
- if (res != SUCCESS){
- log_err_lld("Failed to get page #", accessor->page_number);
- break;
- }
- accessor->page_number++;
- }
- }
- return res;
-}
-
-
-#endif//PERSISTENT_CBT
+#include "stdafx.h"
+#ifdef PERSISTENT_CBT
+
+#include "rangevector.h"
+#include "cbt_params.h"
+#include "cbt_storage.h"
+#include "sector.h"
+#include "blk_direct.h"
+#include <linux/crc32.h>
+
+#define SECTION "cbt_store "
+#include "log_format.h"
+
+
+static int _cbt_storage_read_page(cbt_storage_accessor_t* accessor)
+{
+ int res;
+ sector_t phys_offset = 0;
+ sector_t phys_length = 0;
+ uint32_t crc;
+
+ res = rangevector_v2p(accessor->rangevector, accessor->page_number * sector_from_uint(PAGE_SIZE), sector_from_uint(PAGE_SIZE), &phys_offset, &phys_length);
+ if (res != SUCCESS){
+ log_err("Failed to get real disk offset for persistent CBT data");
+ return res;
+ }
+
+ if (phys_length != sector_from_uint(PAGE_SIZE)){
+ log_err_sect("Unordered range size: ", phys_length);
+ log_err("Range is not ordered by PAGE_SIZE");
+ return -EINVAL;
+ }
+
+ res = blk_direct_submit_page(accessor->device, READ_SYNC, phys_offset, accessor->pg);
+ if (res != SUCCESS){
+ log_err("Failed to read device");
+ log_err_sect("Real device offset: ", phys_offset);
+ return res;
+ }
+
+ //check magic
+ if (0 != memcmp(accessor->page->magic, CBT_STORAGE_MAGIC, 8)){
+ log_err("Invalid CBT data header. Magic mismatch.");
+ log_err_sect("device offset=", phys_offset);
+ log_err_sect("avaliable sectors=", phys_length);
+ log_err("Page header:");
+ log_err_bytes((unsigned char*)accessor->page, sizeof(cbt_storage_page_t));
+ return -EINVAL;
+ }
+
+ //chech CRC32
+ crc = crc32(~0, (void*)(accessor->page) + offsetof(cbt_storage_page_t, number), PAGE_SIZE - offsetof(cbt_storage_page_t, number));
+ if (crc != accessor->page->crc){
+ log_err_lld("Invalid CRC32 on page #", accessor->page_number);
+ log_err_sect("Physical offset on block device: ", phys_offset);
+ log_err_lx("Expected crc=", crc);
+ log_err_lx("Read crc=", accessor->page->crc);
+ return -EINVAL;
+ }
+
+ if (accessor->page_number != accessor->page->number){
+ log_err("Invalid cbt data page number");
+ log_err_lld("Expected=", accessor->page_number);
+ log_err_lld("Read=", accessor->page->number);
+ return -EINVAL;
+ }
+
+ return SUCCESS;
+}
+
+static int _cbt_storage_write_page(cbt_storage_accessor_t* accessor, struct timespec64* optional_time)
+{
+ int res;
+ sector_t phys_offset = 0;
+ sector_t phys_length = 0;
+
+ log_tr_d("DEBUG! write page# ", accessor->page_number);
+
+ //set magic
+ memcpy(accessor->page->magic, CBT_STORAGE_MAGIC, 8);
+ //set number
+ accessor->page->number = accessor->page_number;
+ //set time marker
+ if (optional_time){
+ accessor->page->tv_sec = optional_time->tv_sec;
+ accessor->page->tv_nsec = optional_time->tv_nsec;
+ }
+ else{
+ accessor->page->tv_sec = accessor->time.tv_sec;
+ accessor->page->tv_nsec = accessor->time.tv_nsec;
+ }
+ //calculate CRC32
+ accessor->page->crc = crc32(~0, (void*)(accessor->page) + offsetof(cbt_storage_page_t, number), PAGE_SIZE - offsetof(cbt_storage_page_t, number));
+
+ res = rangevector_v2p(accessor->rangevector, accessor->page_number * sector_from_uint(PAGE_SIZE), sector_from_uint(PAGE_SIZE), &phys_offset, &phys_length);
+ if (res != SUCCESS){
+ log_err("Failed to get real disk offset for persistent CBT data");
+ return res;
+ }
+
+ if (phys_length != sector_from_uint(PAGE_SIZE)){
+ log_err_sect("Unordered range size: ", phys_length);
+ log_err("Range is not ordered by PAGE_SIZE");
+ return -EINVAL;
+ }
+
+ //write page
+ log_tr_sect("DEBUG! offset= ", phys_offset);
+ res = blk_direct_submit_page(accessor->device, WRITE_SYNC, phys_offset, accessor->pg);
+ if (res != SUCCESS){
+ log_err("Failed to read device");
+ log_err_sect("Real device offset: ", phys_offset);
+ return res;
+ }
+
+ return SUCCESS;
+}
+
+int cbt_storage_open(cbt_persistent_parameters_t* params, cbt_storage_accessor_t* accessor)
+{
+ int res = SUCCESS;
+ log_tr_dev_t("Open persistent CBT storage device ",params->dev_id);
+
+ res = blk_dev_open(params->dev_id, &accessor->device);
+ if (res != SUCCESS){
+ log_err_dev_t("Failed to open device ", params->dev_id);
+ return res;
+ }
+ do{
+ if (0 == rangevector_cnt(¶ms->rangevector)){
+ log_err("No range for reading");
+ res = -EINVAL;
+ break;
+ }
+
+ //allocate page
+ if (NULL == (accessor->pg = alloc_page(GFP_KERNEL))){
+ log_err("Failed to allocate page");
+ res = -ENOMEM;
+ break;
+ }
+ accessor->page = (cbt_storage_page_t*)page_address(accessor->pg);
+
+ accessor->rangevector = ¶ms->rangevector;
+ accessor->page_count = rangevector_length(accessor->rangevector) / sector_from_uint(PAGE_SIZE);
+ accessor->page_number = 0;
+ accessor->used_page_count = accessor->page_count;
+ accessor->page_offset = offsetof(cbt_storage_page_t, data);
+
+ } while (false);
+ if (res != SUCCESS)
+ cbt_storage_close(accessor);
+ return res;
+}
+
+void cbt_storage_close(cbt_storage_accessor_t* accessor)
+{
+ if (accessor->pg != NULL){
+ __free_page(accessor->pg);
+ accessor->pg = NULL;
+ accessor->page = NULL;
+ }
+ if (accessor->device != NULL){
+ log_tr("Close persistent CBT storage device ");
+
+ blk_dev_close(accessor->device);
+ accessor->device = NULL;
+ }
+ accessor->rangevector = NULL;
+}
+
+int cbt_storage_check(cbt_storage_accessor_t* accessor)
+{
+ int res = SUCCESS;
+ //check all pages
+
+ //log_tr("[TBD] Checking CRC32 for all pages:");
+ accessor->page_number = 0;
+ accessor->used_page_count = accessor->page_count;
+ res = _cbt_storage_read_page(accessor);
+ if (res != SUCCESS){
+ log_err("Failed to get first page ");
+ return res;
+ }
+ //get time from first page
+ accessor->time.tv_sec = accessor->page->tv_sec;
+ accessor->time.tv_nsec = accessor->page->tv_nsec;
+
+ if (accessor->time.tv_sec == 0ull){
+ log_tr("Persistent CBT data is empty");
+ accessor->used_page_count = 0;
+ }
+
+ for (accessor->page_number = 1; accessor->page_number < accessor->page_count; ++accessor->page_number){
+ res = _cbt_storage_read_page(accessor);
+ if (res != SUCCESS){
+ log_err_lld("Failed to get page #", accessor->page_number);
+ break;
+ }
+ if (accessor->time.tv_sec != 0ull){
+ if (accessor->page->tv_sec == 0ull){
+ //unused page found
+ if (accessor->used_page_count == accessor->page_count){
+ accessor->used_page_count = accessor->page_number;
+ log_tr_lld("Found first unused page #", accessor->page_number);
+ }
+ }
+ else{
+ if ((accessor->time.tv_sec != accessor->page->tv_sec) && (accessor->time.tv_nsec != accessor->page->tv_nsec))
+ {
+ log_err_lld("Invalid time marker on page #", accessor->page_number);
+ log_err_llx("Expected=", accessor->time.tv_sec);
+ log_err_llx("Read=", accessor->page->tv_sec);
+
+ //cbt data skipped
+ accessor->time.tv_sec = 0ull;
+ accessor->time.tv_nsec = 0ul;
+
+ break;
+ }
+ }
+ }
+ }
+
+ if (res != SUCCESS){
+ log_err("Check failed");
+ return res;
+ }
+
+ if (accessor->time.tv_sec != 0ull){
+ //show time
+ struct tm modify_time;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,20,0)
+ time_to_tm(accessor->time.tv_sec, 0, &modify_time);
+#else
+ time64_to_tm(accessor->time.tv_sec, 0, &modify_time);
+#endif
+ log_tr_format("Persistent CBT data from %04ld.%02d.%02d %02ld:%02d:%02d %d",
+ modify_time.tm_year + 1900,
+ modify_time.tm_mon + 1,
+ modify_time.tm_mday,
+ modify_time.tm_hour,
+ modify_time.tm_min,
+ modify_time.tm_sec,
+ accessor->time.tv_nsec);
+ }
+
+ return res;
+}
+
+
+int cbt_storage_prepare4read(cbt_storage_accessor_t* accessor)
+{
+ int res = SUCCESS;
+
+ //set position to first page
+ accessor->page_number = 0;
+ accessor->page_offset = 0;
+
+ res = _cbt_storage_read_page(accessor);
+ if (res != SUCCESS){
+ log_err("Failed to get first page ");
+ return res;
+ }
+ //check time from fisrt page
+ accessor->time.tv_sec = accessor->page->tv_sec;
+ accessor->time.tv_nsec = accessor->page->tv_nsec;
+
+ if (accessor->time.tv_sec == 0ull)
+ return ENODATA;
+
+ //set CBT data empty
+ {
+ struct timespec64 tm = {0}; //
+ res = _cbt_storage_write_page(accessor, &tm);
+ if (res != SUCCESS){
+ log_err("Failed to write first page ");
+ return res;
+ }
+ }
+
+ return res;
+}
+
+int cbt_storage_prepare4write(cbt_storage_accessor_t* accessor)
+{
+ int res = SUCCESS;
+ //set position to first page
+ accessor->page_number = 0;
+ accessor->page_offset = 0;
+
+ res = _cbt_storage_read_page(accessor);
+ if (res != SUCCESS){
+ log_err("Failed to get first page ");
+ return res;
+ }
+ //get time
+ ktime_get_ts64(&accessor->time);
+
+ return res;
+}
+
+int cbt_storage_read(cbt_storage_accessor_t* accessor, void* dst, size_t sz)
+{
+ int res = SUCCESS;
+ size_t ofs = 0;
+ size_t can_be_read;
+ if (accessor->page_number == accessor->page_count){
+ log_err_lld("EOF reached, page number ", accessor->page_number);
+ return -ENODATA;
+ }
+
+ can_be_read = min(CBT_PAGE_DATA_SIZE - accessor->page_offset, sz - ofs);
+ memcpy(dst, accessor->page->data + accessor->page_offset, can_be_read);
+ accessor->page_offset += can_be_read;
+ ofs += can_be_read;
+
+ do{
+ if (accessor->page_offset == CBT_PAGE_DATA_SIZE) {
+ accessor->page_number++;
+ accessor->page_offset = 0;
+ }
+
+ if (accessor->page_number == accessor->page_count){
+ if (ofs < sz){
+ log_err_lld("EOF reached, page number= ", accessor->page_number);
+ res = -ENODATA;
+ }
+ else{
+ log_tr("Reached EOF");
+ res = SUCCESS;
+ }
+ break;
+ }
+
+ //read next page
+ res = _cbt_storage_read_page(accessor);
+ if (res != SUCCESS){
+ log_err_lld("Failed to get page #", accessor->page_number);
+ return res;
+ }
+
+ if (ofs == sz)
+ break;//reading is complete
+
+ can_be_read = min(CBT_PAGE_DATA_SIZE - accessor->page_offset, sz - ofs);
+ memcpy(dst, accessor->page->data + accessor->page_offset, can_be_read);
+ accessor->page_offset += can_be_read;
+ ofs += can_be_read;
+
+ } while (true);
+ return res;
+}
+
+int cbt_storage_write(cbt_storage_accessor_t* accessor, void* src, size_t sz)
+{
+ int res = SUCCESS;
+ size_t ofs = 0;
+ size_t can_be_write;
+
+ if (accessor->page_number == accessor->page_count){
+ log_err_lld("Reached EOF, page number= ", accessor->page_number);
+ return -ENODATA;
+ }
+
+ can_be_write = min(CBT_PAGE_DATA_SIZE - accessor->page_offset, sz - ofs);
+ log_tr_sz("DEBUG! can_be_write=", can_be_write);
+ if (can_be_write == 0){
+ log_tr_format("can_be_write is zero. sz=%lu, ofs=%lu page_offset=%lu", (unsigned long)(sz), (unsigned long)(ofs), (unsigned long)(accessor->page_offset));
+ return -EFAULT;
+ }
+
+ memcpy(accessor->page->data + accessor->page_offset, src + ofs, can_be_write);
+ accessor->page_offset += can_be_write;
+ ofs += can_be_write;
+
+ do{
+ if (accessor->page_offset == CBT_PAGE_DATA_SIZE){
+ //write current page
+ res = _cbt_storage_write_page(accessor, NULL);
+ if (res != SUCCESS){
+ log_err_lld("Failed to get page #", accessor->page_number);
+ return res;
+ }
+
+ accessor->page_number++;
+ accessor->page_offset = 0;
+ }
+
+ if (accessor->page_number == accessor->page_count){
+ if (ofs < sz){
+ log_err_lld("Reached EOF, page number= ", accessor->page_number);
+ res = -ENODATA;
+ }
+ else{
+ log_tr("Reached EOF");
+ res = SUCCESS;
+ }
+ break;
+ }
+
+ if (ofs == sz)
+ break;//writing is complete
+
+ can_be_write = min(CBT_PAGE_DATA_SIZE - accessor->page_offset, sz - ofs);
+ log_tr_sz("DEBUG! can_be_write=", can_be_write);
+ if (can_be_write == 0){
+ log_tr_format("can_be_write is zero. sz=%lu, ofs=%lu page_offset=%lu", (unsigned long)sz, (unsigned long)ofs, (unsigned long)accessor->page_offset);
+ return -EFAULT;
+ }
+ memcpy(accessor->page->data + accessor->page_offset, src + ofs, can_be_write);
+ accessor->page_offset += can_be_write;
+ ofs += can_be_write;
+
+ } while (true);
+
+ return res;
+}
+
+int cbt_storage_write_finish(cbt_storage_accessor_t* accessor)
+{
+ int res = SUCCESS;
+
+ if (accessor->page_number == accessor->page_count)
+ return SUCCESS;
+
+ //write last page
+ log_tr_lld("DEBUG! write last page #", accessor->page_number);
+
+ res = _cbt_storage_write_page(accessor, NULL);
+ if (res != SUCCESS){
+ log_err_lld("Failed to get page #", accessor->page_number);
+ return res;
+ }
+
+ accessor->page_number++;
+ accessor->page_offset = 0;
+
+ {//store empty unused pages
+ struct timespec64 tm = {0};
+ memset(accessor->page->data, 0, CBT_PAGE_DATA_SIZE);
+
+ while (accessor->page_number < accessor->page_count){
+
+ accessor->page->number = accessor->page_number;
+
+ //log_tr_lld("DEBUG! write empty page #", accessor->page_number);
+ res = _cbt_storage_write_page(accessor, &tm);
+ if (res != SUCCESS){
+ log_err_lld("Failed to get page #", accessor->page_number);
+ break;
+ }
+ accessor->page_number++;
+ }
+ }
+ return res;
+}
+
+
+#endif//PERSISTENT_CBT
Konstantin Shalygin commented
@redrum781 PR for this patch?
Sergei Shtepa commented
fixed in 4.0.1.2365