X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvppinfra%2Fmaplog.c;h=689133651307b58586422853ad0180e88671fc34;hb=c2c1bfd9b72aec88526c06479b128725eb525866;hp=41ee0757897c74d795401a7a64ff0bb1c47944bd;hpb=04fee31f265b1d8b602bf336ef1df6c917cf18b2;p=vpp.git diff --git a/src/vppinfra/maplog.c b/src/vppinfra/maplog.c index 41ee0757897..68913365130 100644 --- a/src/vppinfra/maplog.c +++ b/src/vppinfra/maplog.c @@ -27,7 +27,7 @@ int clib_maplog_init (clib_maplog_init_args_t * a) { - int i, fd; + int i, fd, limit; int rv = 0; u8 zero = 0; u32 record_size_in_cache_lines; @@ -42,7 +42,7 @@ clib_maplog_init (clib_maplog_init_args_t * a) if (mm->flags & CLIB_MAPLOG_FLAG_INIT) return (-2); - memset (mm, 0, sizeof (*mm)); + clib_memset (mm, 0, sizeof (*mm)); record_size_in_cache_lines = (a->record_size_in_bytes + CLIB_CACHE_LINE_BYTES - @@ -54,7 +54,6 @@ clib_maplog_init (clib_maplog_init_args_t * a) /* Round up file size in records to a power of 2, for speed... */ mm->log2_file_size_in_records = max_log2 (file_size_in_records); file_size_in_records = 1ULL << (mm->log2_file_size_in_records); - a->file_size_in_bytes = file_size_in_records * record_size_in_cache_lines * CLIB_CACHE_LINE_BYTES; @@ -68,9 +67,19 @@ clib_maplog_init (clib_maplog_init_args_t * a) mm->file_size_in_records = file_size_in_records; mm->flags |= CLIB_MAPLOG_FLAG_INIT; mm->record_size_in_cachelines = record_size_in_cache_lines; + limit = 2; + if (a->maplog_is_circular) + { + mm->log2_file_size_in_records = 63; + mm->flags |= CLIB_MAPLOG_FLAG_CIRCULAR; + limit = 1; + } - /* Map two files */ - for (i = 0; i < 2; i++) + /* + * Map the one and only file for a circular log, + * two files for a normal log. + */ + for (i = 0; i < limit; i++) { mm->filenames[i] = format (0, "%v_%d", mm->file_basename, mm->current_file_index++); @@ -104,7 +113,7 @@ clib_maplog_init (clib_maplog_init_args_t * a) (void) close (fd); } - memset (h, 0, sizeof (*h)); + clib_memset (h, 0, sizeof (*h)); h->maplog_major_version = MAPLOG_MAJOR_VERSION; h->maplog_minor_version = MAPLOG_MINOR_VERSION; h->maplog_patch_version = MAPLOG_PATCH_VERSION; @@ -117,6 +126,7 @@ clib_maplog_init (clib_maplog_init_args_t * a) h->file_size_in_records = file_size_in_records; h->number_of_records = ~0ULL; h->number_of_files = ~0ULL; + h->maplog_flag_circular = a->maplog_is_circular; memcpy (h->file_basename, mm->file_basename, vec_len (mm->file_basename)); mm->header_filename = format (0, "%v_header", mm->file_basename); @@ -143,7 +153,7 @@ fail: if (fd >= 0) (void) close (fd); - for (i = 0; i < 2; i++) + for (i = 0; i < limit; i++) { if (mm->file_baseva[i]) (void) munmap ((u8 *) mm->file_baseva[i], a->file_size_in_bytes); @@ -171,6 +181,9 @@ _clib_maplog_get_entry_slowpath (clib_maplog_main_t * mm, u64 my_record_index) u64 file_size_in_bytes = mm->file_size_in_records * mm->record_size_in_cachelines * CLIB_CACHE_LINE_BYTES; + /* This should never happen */ + ASSERT ((mm->flags & CLIB_MAPLOG_FLAG_CIRCULAR) == 0); + /* * Kill some time by calling format before we make the previous log * segment disappear. Obviously it won't do to call clib_maplog_get_entry(), @@ -224,35 +237,20 @@ _clib_maplog_get_entry_slowpath (clib_maplog_main_t * mm, u64 my_record_index) } /** - * @brief Close a mapped log, and update the log header file + * @brief Update a mapped log header file * - * Unmap the current log segments. * Read the log header. Update the number of records, and number of files - * * @param[in/out] mm mapped log object */ void -clib_maplog_close (clib_maplog_main_t * mm) +clib_maplog_update_header (clib_maplog_main_t * mm) { - int i, rv; - u64 file_size_in_bytes; - int fd; + int fd, rv; clib_maplog_header_t _h, *h = &_h; if (!(mm->flags & CLIB_MAPLOG_FLAG_INIT)) return; - file_size_in_bytes = - mm->file_size_in_records * mm->record_size_in_cachelines * - CLIB_CACHE_LINE_BYTES; - - /* unmap current + next segments */ - for (i = 0; i < 2; i++) - { - (void) munmap ((u8 *) mm->file_baseva[i], file_size_in_bytes); - vec_free (mm->filenames[i]); - } - /* Open the log header */ fd = open ((char *) mm->header_filename, O_RDWR, 0600); if (fd < 0) @@ -271,6 +269,7 @@ clib_maplog_close (clib_maplog_main_t * mm) /* Fix the header... */ h->number_of_records = mm->next_record_index; h->number_of_files = mm->current_file_index; + h->maplog_flag_wrapped = (mm->flags & CLIB_MAPLOG_FLAG_WRAPPED) ? 1 : 0; /* Back to the beginning of the log header... */ if (lseek (fd, 0, SEEK_SET) < 0) @@ -286,10 +285,43 @@ clib_maplog_close (clib_maplog_main_t * mm) out: if (fd >= 0) (void) close (fd); +} + +/** + * @brief Close a mapped log, and update the log header file + * + * Unmap the current log segments. + * Read the log header. Update the number of records, and number of files + * + * @param[in/out] mm mapped log object + */ +void +clib_maplog_close (clib_maplog_main_t * mm) +{ + int i, limit; + u64 file_size_in_bytes; + + if (!(mm->flags & CLIB_MAPLOG_FLAG_INIT)) + return; + + clib_maplog_update_header (mm); + + file_size_in_bytes = + mm->file_size_in_records * mm->record_size_in_cachelines * + CLIB_CACHE_LINE_BYTES; + + limit = (mm->flags & CLIB_MAPLOG_FLAG_CIRCULAR) ? 1 : 2; + + /* unmap current + next segments */ + for (i = 0; i < limit; i++) + { + (void) munmap ((u8 *) mm->file_baseva[i], file_size_in_bytes); + vec_free (mm->filenames[i]); + } vec_free (mm->file_basename); vec_free (mm->header_filename); - memset (mm, 0, sizeof (*mm)); + clib_memset (mm, 0, sizeof (*mm)); } /** @@ -308,13 +340,15 @@ format_maplog_header (u8 * s, va_list * args) if (!verbose) goto brief; s = format (s, "basename %s ", h->file_basename); - s = format (s, "log ver %d.%d.%d app id %u ver %d.%d.%d\n", + s = format (s, "log ver %d.%d.%d app id %u ver %d.%d.%d %s %s\n", h->maplog_major_version, h->maplog_minor_version, h->maplog_patch_version, h->application_id, h->application_major_version, - h->application_minor_version, h->application_patch_version); + h->application_minor_version, h->application_patch_version, + h->maplog_flag_circular ? "circular" : "linear", + h->maplog_flag_wrapped ? "wrapped" : "not wrapped"); s = format (s, " records are %d %d-byte cachelines\n", h->record_size_in_cachelines, h->cacheline_size); s = format (s, " files are %lld records long, %lld files\n", @@ -335,6 +369,14 @@ brief: * Reads the maplog header. Map and process all log segments in order. * Calls the callback function once per file with a record count. * + * Note: if the file header isn't updated by calling + * clib_maplog_close(), it will appear to have an infinite + * number of records in an infinite number of files. + * + * So long as the callback function understands that possibility + * - by simply ignoring NULL records - the scheme still + * works... + * * @param [in] file_basename Same basename supplied to clib_maplog_init * @param [in] fp_arg Callback function pointer */ @@ -347,7 +389,7 @@ clib_maplog_process (char *file_basename, void *fp_arg) u64 file_size_in_bytes; u8 *header_filename, *this_filename = 0; u8 *file_baseva; - void (*fp) (clib_maplog_header_t *, void *data, u64 count); + int (*fp) (clib_maplog_header_t *, void *data, u64 count); u64 records_this_file, records_left; ASSERT (fp_arg); @@ -370,6 +412,7 @@ clib_maplog_process (char *file_basename, void *fp_arg) goto out; } (void) close (fd); + fd = -1; file_size_in_bytes = h->file_size_in_records * h->record_size_in_cachelines * CLIB_CACHE_LINE_BYTES; @@ -384,7 +427,6 @@ clib_maplog_process (char *file_basename, void *fp_arg) fd = open ((char *) this_filename, O_RDONLY, 0600); if (fd < 0) { - clib_unix_warning ("open maplog file"); rv = -3; goto out; } @@ -392,6 +434,7 @@ clib_maplog_process (char *file_basename, void *fp_arg) file_baseva = mmap (0, file_size_in_bytes, PROT_READ, MAP_SHARED, fd, 0); (void) close (fd); + fd = -1; if (file_baseva == (u8 *) MAP_FAILED) { clib_unix_warning ("mmap"); @@ -402,7 +445,27 @@ clib_maplog_process (char *file_basename, void *fp_arg) records_this_file = (records_left > h->file_size_in_records) ? h->file_size_in_records : records_left; - (*fp) (h, file_baseva, records_this_file); + /* + * Normal log, or a circular non-wrapped log, or a circular + * wrapped log which happens to be exactly linear + */ + if (h->maplog_flag_circular == 0 || h->maplog_flag_wrapped == 0 || + ((h->number_of_records % h->file_size_in_records) == 0)) + (*fp) (h, file_baseva, records_this_file); + else + { + /* "Normal" wrapped circular log */ + u64 first_chunk_record_index = h->number_of_records & + (h->file_size_in_records - 1); + u64 first_chunk_number_of_records = records_this_file - + first_chunk_record_index; + u8 *chunk_baseva = file_baseva + + first_chunk_record_index * h->record_size_in_cachelines * + h->cacheline_size; + (*fp) (h, chunk_baseva, first_chunk_number_of_records); + (*fp) (h, file_baseva, + records_this_file - first_chunk_number_of_records); + } if (munmap (file_baseva, file_size_in_bytes) < 0) { @@ -416,7 +479,7 @@ clib_maplog_process (char *file_basename, void *fp_arg) } out: - if (fd > 0) + if (fd >= 0) (void) close (fd); vec_free (this_filename);