Coverity warning be gone
[vpp.git] / src / vppinfra / maplog.c
1 /*
2  * Copyright (c) 2017 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include <vppinfra/maplog.h>
17
18 int
19 clib_maplog_init (clib_maplog_main_t * mm, char *file_basename,
20                   u64 file_size_in_bytes, u32 record_size_in_bytes)
21 {
22   int i, fd;
23   int rv = 0;
24   u8 zero = 0;
25   u32 record_size_in_cache_lines;
26   u64 file_size_in_records;
27
28   /* Already initialized? */
29   if (mm->flags & CLIB_MAPLOG_FLAG_INIT)
30     return (-2);
31
32   memset (mm, 0, sizeof (*mm));
33
34   record_size_in_cache_lines =
35     (record_size_in_bytes + CLIB_CACHE_LINE_BYTES -
36      1) / CLIB_CACHE_LINE_BYTES;
37
38   file_size_in_records = file_size_in_bytes
39     / (record_size_in_cache_lines * CLIB_CACHE_LINE_BYTES);
40
41   /* Round up file size in records to a power of 2, for speed... */
42   mm->log2_file_size_in_records = max_log2 (file_size_in_records);
43   file_size_in_records = 1ULL << (mm->log2_file_size_in_records);
44
45   file_size_in_bytes = file_size_in_records * record_size_in_cache_lines
46     * CLIB_CACHE_LINE_BYTES;
47
48   mm->file_basename = format (0, "%s", file_basename);
49   mm->file_size_in_records = file_size_in_records;
50   mm->flags |= CLIB_MAPLOG_FLAG_INIT;
51   mm->record_size_in_cachelines = record_size_in_cache_lines;
52
53   /* Map two files */
54   for (i = 0; i < 2; i++)
55     {
56       mm->filenames[i] = format (0, "%v_%d", mm->file_basename,
57                                  mm->current_file_index++);
58
59       fd = open ((char *) mm->filenames[i], O_CREAT | O_RDWR | O_TRUNC, 0600);
60       if (fd < 0)
61         {
62           rv = -3;
63           goto fail;
64         }
65
66       if (lseek (fd, file_size_in_bytes - 1, SEEK_SET) == (off_t) - 1)
67         {
68           rv = -4;
69           goto fail;
70         }
71       if (write (fd, &zero, 1) != 1)
72         {
73           rv = -5;
74           goto fail;
75         }
76
77       mm->file_baseva[i] = mmap (0, file_size_in_bytes,
78                                  PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
79       if (mm->file_baseva[i] == (u8 *) MAP_FAILED)
80         {
81           clib_unix_warning ("mmap");
82           goto fail;
83         }
84       (void) close (fd);
85     }
86   return rv;
87
88 fail:
89   if (fd >= 0)
90     (void) close (fd);
91
92   for (i = 0; i < 2; i++)
93     {
94       if (mm->file_baseva[i])
95         (void) munmap ((u8 *) mm->file_baseva[i], file_size_in_bytes);
96     }
97   return rv;
98 }
99
100 u8 *
101 _clib_maplog_get_entry_slowpath (clib_maplog_main_t * mm, u64 my_record_index)
102 {
103   int fd;
104   u8 *rv;
105   u8 zero = 0;
106   u32 unmap_index = (mm->current_file_index) & 1;
107   u64 file_size_in_bytes = mm->file_size_in_records
108     * mm->record_size_in_cachelines * CLIB_CACHE_LINE_BYTES;
109
110   (void) munmap ((u8 *) mm->file_baseva[unmap_index], file_size_in_bytes);
111   vec_reset_length (mm->filenames[unmap_index]);
112
113   mm->filenames[unmap_index] = format (mm->filenames[unmap_index],
114                                        "%v_%d", mm->file_basename,
115                                        mm->current_file_index++);
116
117   fd = open ((char *) mm->filenames[unmap_index],
118              O_CREAT | O_RDWR | O_TRUNC, 0600);
119   /* $$$ this is not real error recovery... */
120   if (fd < 0)
121     {
122       clib_unix_warning ("creat");
123       abort ();
124     }
125
126   if (lseek (fd, file_size_in_bytes - 1, SEEK_SET) == (off_t) - 1)
127     {
128       clib_unix_warning ("lseek");
129       abort ();
130     }
131   if (write (fd, &zero, 1) != 1)
132     {
133       clib_unix_warning ("set-size write");
134       abort ();
135     }
136
137   mm->file_baseva[unmap_index] =
138     mmap (0, file_size_in_bytes, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
139   if (mm->file_baseva[unmap_index] == (u8 *) MAP_FAILED)
140     {
141       clib_unix_warning ("mmap");
142       abort ();
143     }
144   (void) close (fd);
145
146   rv = (u8 *)
147     mm->file_baseva[(my_record_index >> mm->log2_file_size_in_records) & 1] +
148     (my_record_index & (mm->file_size_in_records - 1))
149     * mm->record_size_in_cachelines * CLIB_CACHE_LINE_BYTES;
150
151   return rv;
152 }
153
154 void
155 clib_maplog_close (clib_maplog_main_t * mm)
156 {
157   int i;
158   u64 file_size_in_bytes;
159
160   if (!(mm->flags & CLIB_MAPLOG_FLAG_INIT))
161     return;
162
163   file_size_in_bytes =
164     mm->file_size_in_records * mm->record_size_in_cachelines *
165     CLIB_CACHE_LINE_BYTES;
166
167   for (i = 0; i < 2; i++)
168     {
169       (void) munmap ((u8 *) mm->file_baseva[i], file_size_in_bytes);
170       vec_free (mm->filenames[i]);
171     }
172
173   vec_free (mm->file_basename);
174   memset (mm, 0, sizeof (*mm));
175 }
176
177 /*
178  * fd.io coding-style-patch-verification: ON
179  *
180  * Local Variables:
181  * eval: (c-set-style "gnu")
182  * End:
183  */