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