Emulex Logo
OneCoreā„¢ Storage SDK Release 11.2
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ocs_ramlog.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-2015, Emulex
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors
16  * may be used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  *
31  */
32 
33 /**
34  * @file
35  * RAM buffer logging code
36  *
37  */
38 
39 #include "ocs.h"
40 
41 struct ocs_ramlog_s {
42  uint32_t initialized;
43  uint32_t textbuf_count;
44  uint32_t textbuf_base;
46  uint32_t cur_textbuf_idx;
48  ocs_lock_t lock;
49 };
50 
51 static uint32_t ocs_ramlog_next_idx(ocs_ramlog_t *ramlog, uint32_t idx);
52 
53 /**
54  * @brief Allocate a ramlog buffer.
55  *
56  * Initialize a RAM logging buffer with text buffers totalling buffer_len.
57  *
58  * @param ocs Pointer to driver structure.
59  * @param buffer_len Total length of RAM log buffers.
60  * @param buffer_count Number of text buffers to allocate (totalling buffer-len).
61  *
62  * @return Returns pointer to ocs_ramlog_t instance, or NULL.
63  */
64 ocs_ramlog_t *
65 ocs_ramlog_init(ocs_t *ocs, uint32_t buffer_len, uint32_t buffer_count)
66 {
67  uint32_t i;
68  uint32_t rc;
69  ocs_ramlog_t *ramlog;
70 
71  ramlog = ocs_malloc(ocs, sizeof(*ramlog), OCS_M_ZERO | OCS_M_NOWAIT);
72  if (ramlog == NULL) {
73  ocs_log_err(ocs, "ocs_malloc ramlog failed\n");
74  return NULL;
75  }
76 
77  ramlog->textbuf_count = buffer_count;
78 
79  ramlog->textbufs = ocs_malloc(ocs, sizeof(*ramlog->textbufs)*buffer_count,
80  OCS_M_ZERO | OCS_M_NOWAIT | OCS_M_NONUMA);
81  if (ramlog->textbufs == NULL) {
82  ocs_log_err(ocs, "ocs_malloc textbufs failed\n");
83  ocs_ramlog_free(ocs, ramlog);
84  return NULL;
85  }
86 
87  for (i = 0; i < buffer_count; i ++) {
88  rc = ocs_textbuf_alloc(ocs, &ramlog->textbufs[i], buffer_len);
89  if (rc) {
90  ocs_log_err(ocs, "ocs_textbuf_alloc failed\n");
91  ocs_ramlog_free(ocs, ramlog);
92  return NULL;
93  }
94  }
95 
96  ramlog->cur_textbuf_idx = 0;
97  ramlog->textbuf_base = 1;
98  ramlog->cur_textbuf = &ramlog->textbufs[0];
99  ramlog->initialized = TRUE;
100  ocs_lock_init(ocs, &ramlog->lock, "ramlog_lock[%d]", ocs_instance(ocs));
101  return ramlog;
102 }
103 
104 /**
105  * @brief Free a ramlog buffer.
106  *
107  * A previously allocated RAM logging buffer is freed.
108  *
109  * @param ocs Pointer to driver structure.
110  * @param ramlog Pointer to RAM logging buffer structure.
111  *
112  * @return None.
113  */
114 
115 void
116 ocs_ramlog_free(ocs_t *ocs, ocs_ramlog_t *ramlog)
117 {
118  uint32_t i;
119 
120  if (ramlog != NULL) {
121  ocs_lock_free(&ramlog->lock);
122  if (ramlog->textbufs) {
123  for (i = 0; i < ramlog->textbuf_count; i ++) {
124  ocs_textbuf_free(ocs, &ramlog->textbufs[i]);
125  }
126 
127  ocs_free(ocs, ramlog->textbufs, ramlog->textbuf_count*sizeof(*ramlog->textbufs));
128  ramlog->textbufs = NULL;
129  }
130  ocs_free(ocs, ramlog, sizeof(*ramlog));
131  }
132 }
133 
134 /**
135  * @brief Clear a ramlog buffer.
136  *
137  * The text in the start of day and/or recent ramlog text buffers is cleared.
138  *
139  * @param ocs Pointer to driver structure.
140  * @param ramlog Pointer to RAM logging buffer structure.
141  * @param clear_start_of_day Clear the start of day (driver init) portion of the ramlog.
142  * @param clear_recent Clear the recent messages portion of the ramlog.
143  *
144  * @return None.
145  */
146 
147 void
148 ocs_ramlog_clear(ocs_t *ocs, ocs_ramlog_t *ramlog, int clear_start_of_day, int clear_recent)
149 {
150  uint32_t i;
151 
152  if (clear_recent) {
153  for (i = ramlog->textbuf_base; i < ramlog->textbuf_count; i ++) {
154  ocs_textbuf_reset(&ramlog->textbufs[i]);
155  }
156  ramlog->cur_textbuf_idx = 1;
157  }
158  if (clear_start_of_day && ramlog->textbuf_base) {
159  ocs_textbuf_reset(&ramlog->textbufs[0]);
160  /* Set textbuf_base to 0, so that all buffers are available for
161  * recent logs
162  */
163  ramlog->textbuf_base = 0;
164  }
165 }
166 
167 /**
168  * @brief Append formatted printf data to a ramlog buffer.
169  *
170  * Formatted data is appended to a RAM logging buffer.
171  *
172  * @param os Pointer to driver structure.
173  * @param fmt Pointer to printf style format specifier.
174  *
175  * @return Returns 0 on success, or a negative error code value on failure.
176  */
177 
178 int32_t
179 ocs_ramlog_printf(void *os, const char *fmt, ...)
180 {
181  ocs_t *ocs = os;
182  va_list ap;
183  int32_t res;
184 
185  if (ocs == NULL || ocs->ramlog == NULL) {
186  return -1;
187  }
188 
189  va_start(ap, fmt);
190  res = ocs_ramlog_vprintf(ocs->ramlog, fmt, ap);
191  va_end(ap);
192 
193  return res;
194 }
195 
196 /**
197  * @brief Append formatted text to a ramlog using variable arguments.
198  *
199  * Formatted data is appended to the RAM logging buffer, using variable arguments.
200  *
201  * @param ramlog Pointer to RAM logging buffer.
202  * @param fmt Pointer to printf style formatting string.
203  * @param ap Variable argument pointer.
204  *
205  * @return Returns 0 on success, or a negative error code value on failure.
206  */
207 
208 int32_t
209 ocs_ramlog_vprintf(ocs_ramlog_t *ramlog, const char *fmt, va_list ap)
210 {
211  if (ramlog == NULL || !ramlog->initialized) {
212  return -1;
213  }
214 
215  /* check the current text buffer, if it is almost full (less than 120 characaters), then
216  * roll to the next one.
217  */
218  ocs_lock(&ramlog->lock);
219  if (ocs_textbuf_remaining(ramlog->cur_textbuf) < 120) {
220  ramlog->cur_textbuf_idx = ocs_ramlog_next_idx(ramlog, ramlog->cur_textbuf_idx);
221  ramlog->cur_textbuf = &ramlog->textbufs[ramlog->cur_textbuf_idx];
222  ocs_textbuf_reset(ramlog->cur_textbuf);
223  }
224 
225  ocs_textbuf_vprintf(ramlog->cur_textbuf, fmt, ap);
226  ocs_unlock(&ramlog->lock);
227 
228  return 0;
229 }
230 
231 /**
232  * @brief Return next ramlog buffer index.
233  *
234  * Given a RAM logging buffer index, return the next index.
235  *
236  * @param ramlog Pointer to RAM logging buffer.
237  * @param idx Index value.
238  *
239  * @return Returns next index value.
240  */
241 
242 static uint32_t
243 ocs_ramlog_next_idx(ocs_ramlog_t *ramlog, uint32_t idx)
244 {
245  idx = idx + 1;
246 
247  if (idx >= ramlog->textbuf_count) {
248  idx = ramlog->textbuf_base;
249  }
250 
251  return idx;
252 }
253 
254 /**
255  * @brief Perform ramlog buffer driver dump.
256  *
257  * The RAM logging buffer is appended to the driver dump data.
258  *
259  * @param textbuf Pointer to the driver dump text buffer.
260  * @param ramlog Pointer to the RAM logging buffer.
261  *
262  * @return Returns 0 on success, or a negative error code value on failure.
263  */
264 
265 int32_t
266 ocs_ddump_ramlog(ocs_textbuf_t *textbuf, ocs_ramlog_t *ramlog)
267 {
268  uint32_t i;
269  ocs_textbuf_t *rltextbuf;
270  int idx;
271 
272  if ((ramlog == NULL) || (ramlog->textbufs == NULL)) {
273  return -1;
274  }
275 
276  ocs_ddump_section(textbuf, "driver-log", 0);
277 
278  /* Dump the start of day buffer */
279  ocs_ddump_section(textbuf, "startofday", 0);
280  /* If textbuf_base is 0, then all buffers are used for recent */
281  if (ramlog->textbuf_base) {
282  rltextbuf = &ramlog->textbufs[0];
283  ocs_textbuf_buffer(textbuf, ocs_textbuf_get_buffer(rltextbuf), ocs_textbuf_get_written(rltextbuf));
284  }
285  ocs_ddump_endsection(textbuf, "startofday", 0);
286 
287  /* Dump the most recent buffers */
288  ocs_ddump_section(textbuf, "recent", 0);
289 
290  /* start with the next textbuf */
291  idx = ocs_ramlog_next_idx(ramlog, ramlog->textbuf_count);
292 
293  for (i = ramlog->textbuf_base; i < ramlog->textbuf_count; i ++) {
294  rltextbuf = &ramlog->textbufs[idx];
295  ocs_textbuf_buffer(textbuf, ocs_textbuf_get_buffer(rltextbuf), ocs_textbuf_get_written(rltextbuf));
296  idx = ocs_ramlog_next_idx(ramlog, idx);
297  }
298  ocs_ddump_endsection(textbuf, "recent", 0);
299  ocs_ddump_endsection(textbuf, "driver-log", 0);
300 
301  return 0;
302 }
static uint32_t ocs_ramlog_next_idx(ocs_ramlog_t *ramlog, uint32_t idx)
Return next ramlog buffer index.
Definition: ocs_ramlog.c:243
uint32_t cur_textbuf_idx
Definition: ocs_ramlog.c:46
int32_t ocs_ramlog_printf(void *os, const char *fmt,...)
Append formatted printf data to a ramlog buffer.
Definition: ocs_ramlog.c:179
int32_t ocs_textbuf_remaining(ocs_textbuf_t *textbuf)
Definition: ocs_textbuf.c:386
ocs_lock_t lock
Definition: ocs_ramlog.c:48
int32_t ocs_textbuf_get_written(ocs_textbuf_t *textbuf)
Definition: ocs_textbuf.c:54
uint8_t * ocs_textbuf_get_buffer(ocs_textbuf_t *textbuf)
Definition: ocs_textbuf.c:42
int32_t ocs_ddump_ramlog(ocs_textbuf_t *textbuf, ocs_ramlog_t *ramlog)
Perform ramlog buffer driver dump.
Definition: ocs_ramlog.c:266
void ocs_ddump_section(ocs_textbuf_t *textbuf, const char *name, uint32_t instance)
Generate driver dump section start data.
Definition: ocs_ddumplib.c:90
void ocs_textbuf_free(ocs_t *ocs, ocs_textbuf_t *textbuf)
Definition: ocs_textbuf.c:213
int32_t ocs_ramlog_vprintf(ocs_ramlog_t *ramlog, const char *fmt, va_list ap)
Append formatted text to a ramlog using variable arguments.
Definition: ocs_ramlog.c:209
void ocs_ramlog_free(ocs_t *ocs, ocs_ramlog_t *ramlog)
Free a ramlog buffer.
Definition: ocs_ramlog.c:116
uint32_t initialized
Definition: ocs_ramlog.c:42
ocs_textbuf_t * cur_textbuf
Definition: ocs_ramlog.c:47
const char const char va_list ap
Definition: ocs_ramlog.h:54
uint32_t textbuf_count
Definition: ocs_ramlog.c:43
uint32_t ocs_instance(void *os)
Return the instance index of an opaque ocs structure.
Definition: ocs_driver.c:160
void ocs_ddump_endsection(ocs_textbuf_t *textbuf, const char *name, uint32_t instance)
Generate driver dump section end data.
Definition: ocs_ddumplib.c:108
ocs_textbuf_t * textbufs
Definition: ocs_ramlog.c:45
void ocs_textbuf_vprintf(ocs_textbuf_t *textbuf, const char *fmt, va_list ap)
Definition: ocs_textbuf.c:254
uint32_t textbuf_base
Definition: ocs_ramlog.c:44
void ocs_textbuf_buffer(ocs_textbuf_t *textbuf, uint8_t *buffer, uint32_t buffer_length)
Definition: ocs_textbuf.c:335
void ocs_textbuf_reset(ocs_textbuf_t *textbuf)
Definition: ocs_textbuf.c:406
int32_t ocs_textbuf_alloc(ocs_t *ocs, ocs_textbuf_t *textbuf, uint32_t length)
Definition: ocs_textbuf.c:105
void ocs_ramlog_clear(ocs_t *ocs, ocs_ramlog_t *ramlog, int clear_start_of_day, int clear_recent)
Clear a ramlog buffer.
Definition: ocs_ramlog.c:148
const char const char * fmt
Definition: ocs_ddump.h:54
ocs_ramlog_t * ocs_ramlog_init(ocs_t *ocs, uint32_t buffer_len, uint32_t buffer_count)
Allocate a ramlog buffer.
Definition: ocs_ramlog.c:65