xref: /spdk/lib/env_ocf/ocf_env.h (revision 296e7fba0335252f8c81c63a6c45d34ac054bc75)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 
35 #ifndef __LIBOCF_ENV_H__
36 #define __LIBOCF_ENV_H__
37 
38 #ifndef _GNU_SOURCE
39 #define _GNU_SOURCE
40 #endif
41 #ifndef __USE_GNU
42 #define __USE_GNU
43 #endif
44 
45 #include <linux/limits.h>
46 #include <linux/stddef.h>
47 
48 #include "spdk/stdinc.h"
49 #include "spdk/likely.h"
50 #include "spdk/env.h"
51 #include "spdk/util.h"
52 #include "spdk_internal/log.h"
53 
54 #include "ocf_env_list.h"
55 #include "ocf/ocf_err.h"
56 
57 typedef uint8_t u8;
58 typedef uint16_t u16;
59 typedef uint32_t u32;
60 typedef uint64_t u64;
61 
62 typedef uint64_t sector_t;
63 
64 #define __packed __attribute__((packed))
65 #define __aligned(x) __attribute__((aligned(x)))
66 
67 /* linux sector 512-bytes */
68 #define ENV_SECTOR_SHIFT	9
69 #define ENV_SECTOR_SIZE (1<<ENV_SECTOR_SHIFT)
70 #define BYTES_TO_SECTOR(x)	((x) >> ENV_SECTOR_SHIFT)
71 
72 /* *** MEMORY MANAGEMENT *** */
73 
74 #define ENV_MEM_NORMAL	0
75 #define ENV_MEM_NOIO	0
76 #define ENV_MEM_ATOMIC	0
77 
78 #define likely spdk_likely
79 #define unlikely spdk_unlikely
80 
81 #define min(x, y) MIN(x, y)
82 #ifndef MIN
83 #define MIN(x, y) spdk_min(x, y)
84 #endif
85 
86 #define ARRAY_SIZE(x) SPDK_COUNTOF(x)
87 
88 /* LOGGING */
89 #define ENV_PRIu64 PRIu64
90 
91 #define ENV_WARN(cond, fmt, args...) ({ \
92 		if (spdk_unlikely((uintptr_t)(cond))) \
93 			SPDK_NOTICELOG("WARNING" fmt, ##args); \
94 	})
95 
96 #define ENV_WARN_ON(cond) ({ \
97 	if (spdk_unlikely((uintptr_t)(cond))) \
98 		SPDK_NOTICELOG("WARNING\n"); \
99 	})
100 
101 #define ENV_BUG() ({ \
102 		SPDK_ERRLOG("BUG\n"); \
103 		assert(0); \
104 		abort(); \
105 	})
106 
107 #define ENV_BUG_ON(cond) ({ \
108 		if (spdk_unlikely((uintptr_t)(cond))) { \
109 			SPDK_ERRLOG("BUG\n"); \
110 			assert(0); \
111 			abort(); \
112 		} \
113 	})
114 
115 #define container_of(ptr, type, member) SPDK_CONTAINEROF(ptr, type, member)
116 
117 static inline void *env_malloc(size_t size, int flags)
118 {
119 	return spdk_malloc(size, 0, NULL, SPDK_ENV_LCORE_ID_ANY,
120 			   SPDK_MALLOC_DMA);
121 }
122 
123 static inline void *env_zalloc(size_t size, int flags)
124 {
125 	return spdk_zmalloc(size, 0, NULL, SPDK_ENV_LCORE_ID_ANY,
126 			    SPDK_MALLOC_DMA);
127 }
128 
129 static inline void env_free(const void *ptr)
130 {
131 	return spdk_free((void *)ptr);
132 }
133 
134 static inline void *env_vmalloc(size_t size)
135 {
136 	return spdk_malloc(size, 0, NULL, SPDK_ENV_LCORE_ID_ANY,
137 			   SPDK_MALLOC_DMA);
138 }
139 
140 static inline void *env_vzalloc(size_t size)
141 {
142 	/* TODO: raw_ram init can request huge amount of memory to store
143 	 * hashtable in it. need to ensure that allocation succedds */
144 	return spdk_zmalloc(size, 0, NULL, SPDK_ENV_LCORE_ID_ANY,
145 			    SPDK_MALLOC_DMA);
146 }
147 
148 static inline void *env_secure_alloc(size_t size)
149 {
150 	return spdk_zmalloc(size, 0, NULL, SPDK_ENV_LCORE_ID_ANY,
151 			    SPDK_MALLOC_DMA);
152 }
153 
154 static inline void env_secure_free(const void *ptr, size_t size)
155 {
156 	return spdk_free((void *)ptr);
157 }
158 
159 static inline void env_vfree(const void *ptr)
160 {
161 	return spdk_free((void *)ptr);
162 }
163 
164 static inline uint64_t env_get_free_memory(void)
165 {
166 	/* TODO: do we need implementation for this function? */
167 	return sysconf(_SC_PAGESIZE) * sysconf(_SC_AVPHYS_PAGES);
168 }
169 
170 /* *** ALLOCATOR *** */
171 
172 #define OCF_ALLOCATOR_NAME_MAX 128
173 
174 typedef struct {
175 	struct spdk_mempool *mempool;
176 	size_t element_size;
177 } env_allocator;
178 
179 env_allocator *env_allocator_create(uint32_t size, const char *name);
180 
181 void env_allocator_destroy(env_allocator *allocator);
182 
183 void *env_allocator_new(env_allocator *allocator);
184 
185 void env_allocator_del(env_allocator *allocator, void *item);
186 
187 uint32_t env_allocator_item_count(env_allocator *allocator);
188 
189 /* *** MUTEX *** */
190 
191 typedef struct {
192 	pthread_mutex_t m;
193 } env_mutex;
194 
195 static inline int env_mutex_init(env_mutex *mutex)
196 {
197 	return !!pthread_mutex_init(&mutex->m, NULL);
198 }
199 
200 static inline void env_mutex_lock(env_mutex *mutex)
201 {
202 	ENV_BUG_ON(pthread_mutex_lock(&mutex->m));
203 }
204 
205 static inline int env_mutex_lock_interruptible(env_mutex *mutex)
206 {
207 	env_mutex_lock(mutex);
208 	return 0;
209 }
210 
211 static inline int env_mutex_trylock(env_mutex *mutex)
212 {
213 	return pthread_mutex_trylock(&mutex->m) ? -OCF_ERR_NO_LOCK : 0;
214 }
215 
216 static inline void env_mutex_unlock(env_mutex *mutex)
217 {
218 	ENV_BUG_ON(pthread_mutex_unlock(&mutex->m));
219 }
220 
221 static inline int env_mutex_is_locked(env_mutex *mutex)
222 {
223 	if (env_mutex_trylock(mutex) == 0) {
224 		env_mutex_unlock(mutex);
225 		return 0;
226 	}
227 
228 	return 1;
229 }
230 
231 /* *** RECURSIVE MUTEX *** */
232 
233 typedef env_mutex env_rmutex;
234 
235 static inline int env_rmutex_init(env_rmutex *rmutex)
236 {
237 	return env_mutex_init(rmutex);
238 }
239 
240 static inline void env_rmutex_lock(env_rmutex *rmutex)
241 {
242 	env_mutex_lock(rmutex);
243 }
244 
245 static inline int env_rmutex_lock_interruptible(env_rmutex *rmutex)
246 {
247 	return env_mutex_lock_interruptible(rmutex);
248 }
249 
250 static inline int env_rmutex_trylock(env_rmutex *rmutex)
251 {
252 	return env_mutex_trylock(rmutex);
253 }
254 
255 static inline void env_rmutex_unlock(env_rmutex *rmutex)
256 {
257 	env_mutex_unlock(rmutex);
258 }
259 
260 static inline int env_rmutex_is_locked(env_rmutex *rmutex)
261 {
262 	return env_mutex_is_locked(rmutex);
263 }
264 
265 /* *** RW SEMAPHORE *** */
266 typedef struct {
267 	pthread_rwlock_t lock;
268 } env_rwsem;
269 
270 static inline int env_rwsem_init(env_rwsem *s)
271 {
272 	return !!pthread_rwlock_init(&s->lock, NULL);
273 }
274 
275 static inline void env_rwsem_up_read(env_rwsem *s)
276 {
277 	ENV_BUG_ON(pthread_rwlock_unlock(&s->lock));
278 }
279 
280 static inline void env_rwsem_down_read(env_rwsem *s)
281 {
282 	ENV_BUG_ON(pthread_rwlock_rdlock(&s->lock));
283 }
284 
285 static inline int env_rwsem_down_read_trylock(env_rwsem *s)
286 {
287 	return pthread_rwlock_tryrdlock(&s->lock) ? -OCF_ERR_NO_LOCK : 0;
288 }
289 
290 static inline void env_rwsem_up_write(env_rwsem *s)
291 {
292 	ENV_BUG_ON(pthread_rwlock_unlock(&s->lock));
293 }
294 
295 static inline void env_rwsem_down_write(env_rwsem *s)
296 {
297 	ENV_BUG_ON(pthread_rwlock_wrlock(&s->lock));
298 }
299 
300 static inline int env_rwsem_down_write_trylock(env_rwsem *s)
301 {
302 	return pthread_rwlock_trywrlock(&s->lock) ? -OCF_ERR_NO_LOCK : 0;
303 }
304 
305 static inline int env_rwsem_is_locked(env_rwsem *s)
306 {
307 	if (env_rwsem_down_read_trylock(s) == 0) {
308 		env_rwsem_up_read(s);
309 		return 0;
310 	}
311 
312 	return 1;
313 }
314 
315 static inline int env_rwsem_down_read_interruptible(env_rwsem *s)
316 {
317 	return pthread_rwlock_rdlock(&s->lock);
318 }
319 static inline int env_rwsem_down_write_interruptible(env_rwsem *s)
320 {
321 	return pthread_rwlock_wrlock(&s->lock);
322 }
323 
324 /* *** ATOMIC VARIABLES *** */
325 
326 typedef int env_atomic;
327 
328 typedef long env_atomic64;
329 
330 #ifndef atomic_read
331 #define atomic_read(ptr)       (*(__typeof__(*ptr) *volatile) (ptr))
332 #endif
333 
334 #ifndef atomic_set
335 #define atomic_set(ptr, i)     ((*(__typeof__(*ptr) *volatile) (ptr)) = (i))
336 #endif
337 
338 #define atomic_inc(ptr)        ((void) __sync_fetch_and_add(ptr, 1))
339 #define atomic_dec(ptr)        ((void) __sync_fetch_and_add(ptr, -1))
340 #define atomic_add(ptr, n)     ((void) __sync_fetch_and_add(ptr, n))
341 #define atomic_sub(ptr, n)     ((void) __sync_fetch_and_sub(ptr, n))
342 
343 #define atomic_cmpxchg         __sync_val_compare_and_swap
344 
345 static inline int env_atomic_read(const env_atomic *a)
346 {
347 	return atomic_read(a);
348 }
349 
350 static inline void env_atomic_set(env_atomic *a, int i)
351 {
352 	atomic_set(a, i);
353 }
354 
355 static inline void env_atomic_add(int i, env_atomic *a)
356 {
357 	atomic_add(a, i);
358 }
359 
360 static inline void env_atomic_sub(int i, env_atomic *a)
361 {
362 	atomic_sub(a, i);
363 }
364 
365 static inline bool env_atomic_sub_and_test(int i, env_atomic *a)
366 {
367 	return __sync_sub_and_fetch(a, i) == 0;
368 }
369 
370 static inline void env_atomic_inc(env_atomic *a)
371 {
372 	atomic_inc(a);
373 }
374 
375 static inline void env_atomic_dec(env_atomic *a)
376 {
377 	atomic_dec(a);
378 }
379 
380 static inline bool env_atomic_dec_and_test(env_atomic *a)
381 {
382 	return __sync_sub_and_fetch(a, 1) == 0;
383 }
384 
385 static inline bool env_atomic_inc_and_test(env_atomic *a)
386 {
387 	return __sync_add_and_fetch(a, 1) == 0;
388 }
389 
390 static inline int env_atomic_add_return(int i, env_atomic *a)
391 {
392 	return __sync_add_and_fetch(a, i);
393 }
394 
395 static inline int env_atomic_sub_return(int i, env_atomic *a)
396 {
397 	return __sync_sub_and_fetch(a, i);
398 }
399 
400 static inline int env_atomic_inc_return(env_atomic *a)
401 {
402 	return env_atomic_add_return(1, a);
403 }
404 
405 static inline int env_atomic_dec_return(env_atomic *a)
406 {
407 	return env_atomic_sub_return(1, a);
408 }
409 
410 static inline int env_atomic_cmpxchg(env_atomic *a, int old, int new_value)
411 {
412 	return atomic_cmpxchg(a, old, new_value);
413 }
414 
415 static inline int env_atomic_add_unless(env_atomic *a, int i, int u)
416 {
417 	int c, old;
418 	c = env_atomic_read(a);
419 	for (;;) {
420 		if (spdk_unlikely(c == (u))) {
421 			break;
422 		}
423 		old = env_atomic_cmpxchg((a), c, c + (i));
424 		if (spdk_likely(old == c)) {
425 			break;
426 		}
427 		c = old;
428 	}
429 	return c != (u);
430 }
431 
432 static inline long env_atomic64_read(const env_atomic64 *a)
433 {
434 	return atomic_read(a);
435 }
436 
437 static inline void env_atomic64_set(env_atomic64 *a, long i)
438 {
439 	atomic_set(a, i);
440 }
441 
442 static inline void env_atomic64_add(long i, env_atomic64 *a)
443 {
444 	atomic_add(a, i);
445 }
446 
447 static inline void env_atomic64_sub(long i, env_atomic64 *a)
448 {
449 	atomic_sub(a, i);
450 }
451 
452 static inline void env_atomic64_inc(env_atomic64 *a)
453 {
454 	atomic_inc(a);
455 }
456 
457 static inline void env_atomic64_dec(env_atomic64 *a)
458 {
459 	atomic_dec(a);
460 }
461 
462 static inline int env_atomic64_add_return(int i, env_atomic *a)
463 {
464 	return __sync_add_and_fetch(a, i);
465 }
466 
467 static inline int env_atomic64_sub_return(int i, env_atomic *a)
468 {
469 	return __sync_sub_and_fetch(a, i);
470 }
471 
472 static inline int env_atomic64_inc_return(env_atomic *a)
473 {
474 	return env_atomic64_add_return(1, a);
475 }
476 
477 static inline int env_atomic64_dec_return(env_atomic *a)
478 {
479 	return env_atomic_sub_return(1, a);
480 }
481 
482 static inline long env_atomic64_cmpxchg(env_atomic64 *a, long old, long new)
483 {
484 	return atomic_cmpxchg(a, old, new);
485 }
486 
487 /* *** COMPLETION *** */
488 struct completion {
489 	env_atomic atom;
490 };
491 
492 typedef struct completion env_completion;
493 
494 void env_completion_init(env_completion *completion);
495 void env_completion_wait(env_completion *completion);
496 void env_completion_complete(env_completion *completion);
497 
498 /* *** SPIN LOCKS *** */
499 
500 typedef env_mutex env_spinlock;
501 
502 static inline void env_spinlock_init(env_spinlock *l)
503 {
504 	env_mutex_init(l);
505 }
506 
507 static inline void env_spinlock_lock(env_spinlock *l)
508 {
509 	env_mutex_lock(l);
510 }
511 
512 static inline void env_spinlock_unlock(env_spinlock *l)
513 {
514 	env_mutex_unlock(l);
515 }
516 
517 static inline void env_spinlock_lock_irq(env_spinlock *l)
518 {
519 	env_spinlock_lock(l);
520 }
521 
522 static inline void env_spinlock_unlock_irq(env_spinlock *l)
523 {
524 	env_spinlock_unlock(l);
525 }
526 
527 static inline void env_spinlock_lock_irqsave(env_spinlock *l, int flags)
528 {
529 	env_spinlock_lock(l);
530 	(void)flags;
531 }
532 
533 static inline void env_spinlock_unlock_irqrestore(env_spinlock *l, int flags)
534 {
535 	env_spinlock_unlock(l);
536 	(void)flags;
537 }
538 
539 /* *** RW LOCKS *** */
540 
541 typedef env_rwsem env_rwlock;
542 
543 static inline void env_rwlock_init(env_rwlock *l)
544 {
545 	env_rwsem_init(l);
546 }
547 
548 static inline void env_rwlock_read_lock(env_rwlock *l)
549 {
550 	env_rwsem_down_read(l);
551 }
552 
553 static inline void env_rwlock_read_unlock(env_rwlock *l)
554 {
555 	env_rwsem_up_read(l);
556 }
557 
558 static inline void env_rwlock_write_lock(env_rwlock *l)
559 {
560 	env_rwsem_down_write(l);
561 }
562 
563 static inline void env_rwlock_write_unlock(env_rwlock *l)
564 {
565 	env_rwsem_up_write(l);
566 }
567 
568 static inline void env_bit_set(int nr, volatile void *addr)
569 {
570 	char *byte = (char *)addr + (nr >> 3);
571 	char mask = 1 << (nr & 7);
572 
573 	__sync_or_and_fetch(byte, mask);
574 }
575 
576 static inline void env_bit_clear(int nr, volatile void *addr)
577 {
578 	char *byte = (char *)addr + (nr >> 3);
579 	char mask = 1 << (nr & 7);
580 
581 	mask = ~mask;
582 	__sync_and_and_fetch(byte, mask);
583 }
584 
585 static inline bool env_bit_test(int nr, const volatile unsigned long *addr)
586 {
587 	const char *byte = (char *)addr + (nr >> 3);
588 	char mask = 1 << (nr & 7);
589 
590 	return !!(*byte & mask);
591 }
592 
593 /* *** WAITQUEUE *** */
594 
595 typedef struct {
596 	sem_t sem;
597 } env_waitqueue;
598 
599 static inline void env_waitqueue_init(env_waitqueue *w)
600 {
601 	sem_init(&w->sem, 0, 0);
602 }
603 
604 static inline void env_waitqueue_wake_up(env_waitqueue *w)
605 {
606 	sem_post(&w->sem);
607 }
608 
609 #define env_waitqueue_wait(w, condition)	\
610 ({						\
611 	int __ret = 0;				\
612 	if (!(condition))			\
613 		sem_wait(&w.sem);		\
614 	__ret = __ret;				\
615 })
616 
617 /* *** SCHEDULING *** */
618 
619 /* CAS does not need this while in user-space */
620 static inline void env_schedule(void)
621 {
622 }
623 
624 #define env_cond_resched	env_schedule
625 
626 static inline int env_in_interrupt(void)
627 {
628 	return 0;
629 }
630 
631 static inline uint64_t env_get_tick_count(void)
632 {
633 	return spdk_get_ticks();
634 }
635 
636 static inline uint64_t env_ticks_to_secs(uint64_t j)
637 {
638 	return j / spdk_get_ticks_hz();
639 }
640 
641 static inline uint64_t env_ticks_to_msecs(uint64_t j)
642 {
643 	return env_ticks_to_secs(j) * 1000;
644 }
645 
646 static inline uint64_t env_ticks_to_nsecs(uint64_t j)
647 {
648 	return env_ticks_to_secs(j) * 1000 * 1000;
649 }
650 
651 static inline uint64_t env_ticks_to_usecs(uint64_t j)
652 {
653 	return env_ticks_to_secs(j) * 1000 * 1000 * 1000;
654 }
655 
656 static inline uint64_t env_secs_to_ticks(uint64_t j)
657 {
658 	return j * spdk_get_ticks_hz();
659 }
660 
661 /* *** STRING OPERATIONS *** */
662 
663 /* 512 KB is sufficient amount of memory for OCF operations */
664 #define ENV_MAX_MEM (512 * 1024)
665 
666 static inline int env_memset(void *dest, size_t len, uint8_t value)
667 {
668 	if (dest == NULL || len == 0) {
669 		return 1;
670 	}
671 
672 	memset(dest, value, len);
673 	return 0;
674 }
675 
676 static inline int env_memcpy(void *dest, size_t dmax, const void *src, size_t len)
677 {
678 	if (dest == NULL || src == NULL) {
679 		return 1;
680 	}
681 	if (dmax == 0 || dmax > ENV_MAX_MEM) {
682 		return 1;
683 	}
684 	if (len == 0 || len > dmax) {
685 		return 1;
686 	}
687 
688 	memcpy(dest, src, len);
689 	return 0;
690 }
691 
692 static inline int env_memcmp(const void *aptr, size_t dmax, const void *bptr, size_t len,
693 			     int *diff)
694 {
695 	if (diff == NULL || aptr == NULL || bptr == NULL) {
696 		return 1;
697 	}
698 	if (dmax == 0 || dmax > ENV_MAX_MEM) {
699 		return 1;
700 	}
701 	if (len == 0 || len > dmax) {
702 		return 1;
703 	}
704 
705 	*diff = memcmp(aptr, bptr, len);
706 	return 0;
707 }
708 
709 /* 4096 is sufficient max length for any OCF operation on string */
710 #define ENV_MAX_STR (4 * 1024)
711 
712 static inline size_t env_strnlen(const char *src, size_t dmax)
713 {
714 	return strnlen(src, dmax);
715 }
716 
717 static inline int env_strncpy(char *dest, size_t dmax, const char *src, size_t len)
718 {
719 	if (dest == NULL  || src == NULL) {
720 		return 1;
721 	}
722 	if (dmax == 0 || dmax > ENV_MAX_STR) {
723 		return 1;
724 	}
725 	if (len == 0) {
726 		return 1;
727 	}
728 	/* Just copy as many characters as we can instead of return failure */
729 	len = min(len, dmax);
730 
731 	strncpy(dest, src, len);
732 	return 0;
733 }
734 
735 #define env_strncmp strncmp
736 
737 static inline char *env_strdup(const char *src, int flags)
738 {
739 	int len;
740 	char *ret;
741 
742 	if (src == NULL) {
743 		return NULL;
744 	}
745 
746 	len = env_strnlen(src, ENV_MAX_STR) + 1;
747 	ret = env_malloc(len, flags);
748 
749 	if (env_strncpy(ret, ENV_MAX_STR, src, len)) {
750 		return NULL;
751 	} else {
752 		return ret;
753 	}
754 }
755 
756 /* *** SORTING *** */
757 
758 static inline void env_sort(void *base, size_t num, size_t size,
759 			    int (*cmp_fn)(const void *, const void *),
760 			    void (*swap_fn)(void *, void *, int size))
761 {
762 	qsort(base, num, size, cmp_fn);
763 }
764 
765 static inline void env_msleep(uint64_t n)
766 {
767 	usleep(n * 1000);
768 }
769 
770 static inline void env_touch_softlockup_wd(void)
771 {
772 }
773 
774 /* *** CRC *** */
775 
776 uint32_t env_crc32(uint32_t crc, uint8_t const *data, size_t len);
777 
778 #endif /* __OCF_ENV_H__ */
779