diff --git a/.github/actions/pmem_benchmark_run/action.yml b/.github/actions/pmem_benchmark_run/action.yml new file mode 100644 index 00000000000..27c989c7ebe --- /dev/null +++ b/.github/actions/pmem_benchmark_run/action.yml @@ -0,0 +1,45 @@ +name: PMEM benchmark procedure +description: PMDK benchmarking procedure for self-hosted runners equipped with PMEM +inputs: + runtime_dir: + description: The root directory of the repository designated as runtime + required: true + reference_LIB_PATH: + description: LD_LIBRARY_PATH where the first version of PMDK is built + required: true + rival_LIB_PATH: + description: LD_LIBRARY_PATH where the second version of PMDK is built + required: true + config: + description: Name of the .cfg file to use + required: true + scenario: + description: Name of the scenario to run + required: true + pmem_path: + description: A PMEM-mounted directory to use + default: /mnt/pmem0 +runs: + using: composite + steps: + - name: Run the benchmark + working-directory: ${{ inputs.runtime_dir }} + shell: bash + run: >- + ./utils/benchmarks/run_and_combine.py + --reference ${{ inputs.reference_LIB_PATH }} --rival ${{ inputs.rival_LIB_PATH }} + --config ${{ inputs.config }} --scenario ${{ inputs.scenario }} + --pmem_path ${{ inputs.pmem_path }} + + - name: Archive logs + if: always() + uses: actions/upload-artifact@v4 + with: + name: ${{ inputs.config }}__${{ inputs.scenario }} + path: '${{ inputs.runtime_dir }}/*.csv' + + - name: Remove logs + if: always() + working-directory: ${{ inputs.runtime_dir }} + shell: bash + run: rm -f *.csv diff --git a/.github/actions/pmem_test_prepare/action.yml b/.github/actions/pmem_test_prepare/action.yml index 8a67800fcf4..e9ca0982590 100644 --- a/.github/actions/pmem_test_prepare/action.yml +++ b/.github/actions/pmem_test_prepare/action.yml @@ -9,6 +9,10 @@ inputs: description: Build with the fault injection capability required: false default: '0' + valgrind: + description: Build with Valgrind support + required: true + runs: using: composite steps: @@ -30,6 +34,9 @@ runs: - env: FAULT_INJECTION: ${{ inputs.fault_injection }} NDCTL_ENABLE: ${{ inputs.ndctl_enable }} + PMEMOBJ_IGNORE_DIRTY_SHUTDOWN: ${{ inputs.ndctl_enable == 'n' && 'y' || 'n' }} + PMEMOBJ_IGNORE_BAD_BLOCKS: ${{ inputs.ndctl_enable == 'n' && 'y' || 'n' }} + VALGRIND: ${{ inputs.valgrind }} run: | echo '::group::Build' $WORKDIR/build-pmdk.sh diff --git a/.github/workflows/docker_rebuild.yml b/.github/workflows/docker_rebuild.yml index 6d0444f2d75..dd740fef3d2 100644 --- a/.github/workflows/docker_rebuild.yml +++ b/.github/workflows/docker_rebuild.yml @@ -37,7 +37,7 @@ jobs: - {OS: ubuntu, OS_VER: 22.04} steps: - name: Clone the git repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Rebuild the image env: diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 09eb864b837..49b378103dc 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -13,12 +13,16 @@ jobs: issues: read steps: - name: Clone the git repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: # required for `make check-license` to work properly fetch-depth: 50 - name: Check changelog + # Skip for pmem/pmdk/master and stable-* branches + if: | + !(github.repository == 'pmem/pmdk' && + (github.ref_name == 'master' || startsWith(github.ref_name, 'stable-'))) uses: Zomzog/changelog-checker@v1.3.0 with: fileName: ChangeLog @@ -32,24 +36,54 @@ jobs: sudo pip install flake8 sudo apt-get install clang-format-14 - - name: Check licenses + - name: Check license + id: check_license + continue-on-error: true env: NDCTL_ENABLE: n # just to speed up the job - run: make -j$(nproc) check-license + PMEMOBJ_IGNORE_DIRTY_SHUTDOWN: y # not recommended for production + PMEMOBJ_IGNORE_BAD_BLOCKS: y # not recommended for production + run: | + make -j$(nproc) check-license || true + git diff > /tmp/check-license.diff + [ $(cat /tmp/check-license.diff | wc -l ) -gt 0 ] && exit 1 + exit 0 + + - name: Upload check license diff + if: steps.check_license.outcome != 'success' + uses: actions/upload-artifact@v4 + with: + name: check-license.diff + path: /tmp/check-license.diff + + - name: Check license - Exit code + run: | + [ "${{steps.check_license.outcome}}" != "success" ] && exit 1 + exit 0 - name: Check style env: CSTYLE_FAIL_IF_CLANG_FORMAT_MISSING: 1 NDCTL_ENABLE: n # just to speed up the job + PMEMOBJ_IGNORE_DIRTY_SHUTDOWN: y # not recommended for production + PMEMOBJ_IGNORE_BAD_BLOCKS: y # not recommended for production run: make -j$(nproc) cstyle basic_build: name: Basic build runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - CC: gcc + CXX: g++ + - CC: clang + CXX: clang++ steps: - name: Clone the git repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install dependencies run: sudo apt-get -y install pandoc @@ -57,6 +91,10 @@ jobs: - name: Build sources env: NDCTL_ENABLE: n # just to speed up the job + PMEMOBJ_IGNORE_DIRTY_SHUTDOWN: y # not recommended for production + PMEMOBJ_IGNORE_BAD_BLOCKS: y # not recommended for production + CC: ${{ matrix.CC }} + CXX: ${{ matrix.CXX }} run: make -j$(nproc) test @@ -66,6 +104,8 @@ jobs: name: Ubuntu coverage_scan: - needs: call-ubuntu + needs: [src_checkers, basic_build] uses: ./.github/workflows/scan_coverage.yml + secrets: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} name: Coverage diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index dc846995648..b2b43cef8b1 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -35,7 +35,7 @@ jobs: TEST_BUILD: [debug, nondebug] steps: - name: Clone the git repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 50 @@ -66,7 +66,7 @@ jobs: ] steps: - name: Clone the git repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 50 diff --git a/.github/workflows/pmem.io_doc_update.yml b/.github/workflows/pmem.io_doc_update.yml index 8dce6d866ad..147bfabd3f2 100644 --- a/.github/workflows/pmem.io_doc_update.yml +++ b/.github/workflows/pmem.io_doc_update.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Clone the git repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install dependencies run: sudo apt-get install libndctl-dev libdaxctl-dev pandoc diff --git a/.github/workflows/pmem_benchmark.yml b/.github/workflows/pmem_benchmark.yml new file mode 100644 index 00000000000..93fcfbb8f1a --- /dev/null +++ b/.github/workflows/pmem_benchmark.yml @@ -0,0 +1,115 @@ +name: PMEM Benchmark + +on: + workflow_dispatch: + inputs: + reference_ref: + type: string + default: stable-2.0 + rival_ref: + type: string + default: master + + +jobs: + prep_runtime: + name: Prepare runtime + runs-on: [self-hosted, benchmark] + permissions: + contents: read + steps: + - name: Clone the git repo + uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Build + run: make -j + + + prep_contesters: + name: Prepare ${{ matrix.ROLE }} (${{ matrix.GITHUB_REF }}) + runs-on: [self-hosted, benchmark] + needs: prep_runtime + strategy: + matrix: + include: + - ROLE: reference + GITHUB_REF: ${{ inputs.reference_ref }} + - ROLE: rival + GITHUB_REF: ${{ inputs.rival_ref }} + permissions: + contents: read + env: + MANIFEST: ${{ matrix.ROLE }}/manifest.txt + steps: + - name: Clone the git repo + uses: actions/checkout@v4 + with: + ref: ${{ matrix.GITHUB_REF }} + fetch-depth: 1 + path: ${{ matrix.ROLE }} + + - name: Build + working-directory: ${{ matrix.ROLE }} + run: make -j + + - name: Write the manifest + run: | + echo "${{ matrix.GITHUB_REF }}" >> $MANIFEST + git -C ${{ matrix.ROLE }} rev-parse HEAD >> $MANIFEST + + - name: Archive the manifest + uses: actions/upload-artifact@v4 + with: + name: manifest_${{ matrix.ROLE }} + path: ${{ env.MANIFEST }} + + + run: + name: Run perf.cfg ${{ matrix.SCENARIO }} + runs-on: [self-hosted, benchmark] + needs: prep_contesters + strategy: + matrix: + SCENARIO: + - obj_tx_alloc_small_v_thread + - obj_pmalloc_small_v_threads + - obj_rbtree_map_insert + - obj_hashmap_tx_map_insert + steps: + - name: Benchmark + uses: ./.github/actions/pmem_benchmark_run + with: + runtime_dir: ./ + reference_LIB_PATH: reference/src/nondebug + rival_LIB_PATH: rival/src/nondebug + config: perf + scenario: ${{ matrix.SCENARIO }} + + + repack: + name: Repack + runs-on: ubuntu-latest + needs: run + steps: + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: csvs + + - name: Combine the manifests + env: + OUTPUT: csvs/manifest.txt + run: | + for competitor in reference rival; do + echo "$competitor:" >> $OUTPUT + cat csvs/manifest_$competitor/manifest.txt >> $OUTPUT + echo >> $OUTPUT + done + + - name: Upload all as a single artifact + uses: actions/upload-artifact@v4 + with: + name: perf__all__${{ github.run_id }} + path: csvs/**/* diff --git a/.github/workflows/pmem_ras.yml b/.github/workflows/pmem_ras.yml index 703f48278b9..9a041e24a54 100644 --- a/.github/workflows/pmem_ras.yml +++ b/.github/workflows/pmem_ras.yml @@ -44,7 +44,7 @@ jobs: steps: - name: Clone the git repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Variables, such as $ras_runner are hidden on the controller platform as environmental variables. # 'sed' command is used to filter out IP addresses from the ansible output, it will show up as the 'ras_runner' instead. diff --git a/.github/workflows/pmem_test_matrix.yml b/.github/workflows/pmem_test_matrix.yml index e4b9d47cbe8..4b62b0c6788 100644 --- a/.github/workflows/pmem_test_matrix.yml +++ b/.github/workflows/pmem_test_matrix.yml @@ -9,6 +9,9 @@ on: force_enable: required: true type: string + valgrind: + required: true + type: string timeout_minutes: required: false type: number @@ -28,11 +31,14 @@ jobs: os: [rhel, opensuse] build: [debug, nondebug] + steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Test prepare uses: ./.github/actions/pmem_test_prepare + with: + valgrind: ${{ inputs.valgrind }} - name: Test run uses: ./.github/actions/pmem_test_run diff --git a/.github/workflows/pmem_tests.yml b/.github/workflows/pmem_tests.yml index 6fb36e89d0f..972e9eebe42 100644 --- a/.github/workflows/pmem_tests.yml +++ b/.github/workflows/pmem_tests.yml @@ -6,17 +6,22 @@ name: PMEM tests on: workflow_dispatch: schedule: - # run this job at 00:00 UTC every day - - cron: '0 0 * * *' + # run this job at 18:00 UTC every day + - cron: '0 18 * * *' jobs: # Test the default build with the basic test suite. Basic: + strategy: + matrix: + VALGRIND: [0, 1] + name: Basic ${{ matrix.VALGRIND == 0 && 'w/o Valgrind' || 'w/ Valgrind' }} uses: ./.github/workflows/pmem_test_matrix.yml with: # Exclude all Valgrind tests. All tests employing Valgrind tooling are run # in the dedicated workflows below. force_enable: '["none"]' + valgrind: ${{ matrix.VALGRIND }} # Test the default build with force-enabled Valgrind tooling for (persistent) @@ -25,6 +30,7 @@ jobs: uses: ./.github/workflows/pmem_test_matrix.yml with: force_enable: '["pmemcheck", "memcheck"]' + valgrind: 1 # Test the default build with force-enabled Valgrind tooling for thread error @@ -33,6 +39,7 @@ jobs: uses: ./.github/workflows/pmem_test_matrix.yml with: force_enable: '["drd", "helgrind"]' + valgrind: 1 # 9h = 7h20m (the longest workflow execution time) + ~20% leeway. timeout_minutes: 540 @@ -48,10 +55,12 @@ jobs: build: [static_debug, static_nondebug] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Test prepare uses: ./.github/actions/pmem_test_prepare + with: + valgrid: 1 - name: Test run uses: ./.github/actions/pmem_test_run @@ -67,12 +76,13 @@ jobs: runs-on: [self-hosted, rhel] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Test prepare uses: ./.github/actions/pmem_test_prepare with: fault_injection: '1' + valgrind: 1 - name: Test run uses: ./.github/actions/pmem_test_run @@ -84,18 +94,21 @@ jobs: # By default, PMDK is built with NDCTL in order to provide RAS features. # This build is only viable as long as DAOS builds PMDK with NDCTL_ENABLE=n # https://github.com/daos-stack/pmdk/pull/12 + # It should be removed as soon as following PR is merged + # https://github.com/daos-stack/pmdk/pull/35 ndctl_enable_n: name: Without ndctl if: github.repository == 'pmem/pmdk' runs-on: [self-hosted, rhel] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Test prepare uses: ./.github/actions/pmem_test_prepare with: ndctl_enable: n + valgrind: 0 - name: Test run uses: ./.github/actions/pmem_test_run diff --git a/.github/workflows/scan_bandit.yml b/.github/workflows/scan_bandit.yml index d803661a766..ead974e30fa 100644 --- a/.github/workflows/scan_bandit.yml +++ b/.github/workflows/scan_bandit.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Clone the git repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install Bandit run: sudo apt-get -y install bandit diff --git a/.github/workflows/scan_codeql.yml b/.github/workflows/scan_codeql.yml index c45a4e70bfa..ce5a625834b 100644 --- a/.github/workflows/scan_codeql.yml +++ b/.github/workflows/scan_codeql.yml @@ -15,7 +15,7 @@ jobs: steps: - name: Clone the git repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install pmem/valgrind (including dependencies) run: | @@ -41,7 +41,7 @@ jobs: languages: cpp, python - name: Build PMDK - run: make EXTRA_CFLAGS=-DUSE_VALGRIND test -j$(nproc) + run: make test -j$(nproc) - name: CodeQL scan uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/scan_coverage.yml b/.github/workflows/scan_coverage.yml index 20de43538b6..6fcef3d30a1 100644 --- a/.github/workflows/scan_coverage.yml +++ b/.github/workflows/scan_coverage.yml @@ -3,6 +3,9 @@ name: Coverage on: workflow_call: + secrets: + CODECOV_TOKEN: + required: true env: # Note: All coverage scans, e.g. on pull requests, should be run in the same @@ -27,10 +30,18 @@ jobs: runs-on: ubuntu-latest steps: - name: Clone the git repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Pull the image run: cd $WORKDIR && ./pull-or-rebuild-image.sh - - name: Measure and upload code coverage + - name: Run the build run: cd $WORKDIR && ./build-CI.sh + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v4 + with: + root_dir: /home/runner/work/pmdk/pmdk/ + directory: /home/runner/work/pmdk/pmdk/ + token: ${{ secrets.CODECOV_TOKEN }} + verbose: true diff --git a/.github/workflows/scan_coverity.yml b/.github/workflows/scan_coverity.yml index c87f5f7076e..4c1c5703046 100644 --- a/.github/workflows/scan_coverity.yml +++ b/.github/workflows/scan_coverity.yml @@ -30,7 +30,7 @@ jobs: CONFIG: ["OS=ubuntu OS_VER=22.04"] steps: - name: Clone the git repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Pull or rebuild the image run: cd $WORKDIR && ${{ matrix.CONFIG }} ./pull-or-rebuild-image.sh diff --git a/.github/workflows/scan_documentation.yml b/.github/workflows/scan_documentation.yml index d35231c489e..16c4993ea4d 100644 --- a/.github/workflows/scan_documentation.yml +++ b/.github/workflows/scan_documentation.yml @@ -13,7 +13,7 @@ jobs: steps: - name: Clone the git repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install required packages run: | diff --git a/.github/workflows/scan_log_calls.yml b/.github/workflows/scan_log_calls.yml new file mode 100644 index 00000000000..406ce1275a5 --- /dev/null +++ b/.github/workflows/scan_log_calls.yml @@ -0,0 +1,41 @@ +# Verify the log calls test is up-to-date +name: Log calls + +on: + workflow_dispatch: + workflow_call: + + +jobs: + log-calls: + name: Log calls + env: + WORKING_DIRECTORY: utils/call_stacks_analysis/ + runs-on: ubuntu-latest + steps: + - name: Clone the git repo + uses: actions/checkout@v4 + + - name: Generate log calls' diff + working-directory: ${{ env.WORKING_DIRECTORY }} + run: | + ./log_call_all_generate.py + git diff > log_calls.diff + echo "length=$(cat log_calls.diff | wc -l)" >> $GITHUB_OUTPUT + id: log_calls_diff + + - name: Non-empty diff + if: steps.log_calls_diff.outputs.length != '0' + run: cat ${{ env.WORKING_DIRECTORY }}/log_calls.diff + + - name: Upload artifacts + if: steps.log_calls_diff.outputs.length != '0' + uses: actions/upload-artifact@v3 + with: + name: log_calls_diff + path: ${{ env.WORKING_DIRECTORY }}/log_calls.diff + + - name: Exit code + run: | + [ "${{steps.log_calls_diff.outputs.length}}" != '0' ] && exit 1 + exit 0 diff --git a/.github/workflows/scan_stack_usage.yml b/.github/workflows/scan_stack_usage.yml index 93f36f59608..a5b1ecc8984 100644 --- a/.github/workflows/scan_stack_usage.yml +++ b/.github/workflows/scan_stack_usage.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Clone the git repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: pmdk @@ -52,13 +52,13 @@ jobs: ./make_extra.py ./make_cflow.sh # The lower limit comes up from the DAOS memory requirements. - # 16kB - 4kB - 1kB = ~11kB + # 16kB - 4kB - 752B = 11536B # 16kB = Stack allocated for a single Argobot's ULT # 4kB = a maximum DAOS' stack usage up to calling a PMDK API calls - # 1kB = safety margin + # 752B = safety margin # ~ = Some OSes, e.g. Ubuntu 22.04, generate call stacks of size # a little bit over the exact limit which is not deemed a problem at the moment. - ./make_call_stacks.py --filter-api-file examples/api_filter.txt --filter-lower-limit 11296 + ./make_call_stacks.py --filter-api-file examples/api_filter.txt --filter-lower-limit 11536 - name: List per-function stack usage for all call stacks of interest working-directory: ${{ env.CALL_STACKS_TOOLS_PATH }} diff --git a/.github/workflows/scan_ubsan.yml b/.github/workflows/scan_ubsan.yml index 2c8427f222b..3693783ca22 100644 --- a/.github/workflows/scan_ubsan.yml +++ b/.github/workflows/scan_ubsan.yml @@ -28,7 +28,7 @@ jobs: build: ['debug', 'nondebug'] steps: - name: Clone the git repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Pull the image run: cd $WORKDIR && ./pull-or-rebuild-image.sh diff --git a/.github/workflows/scans.yml b/.github/workflows/scans.yml index 644d2baf1fc..7bafd77ad01 100644 --- a/.github/workflows/scans.yml +++ b/.github/workflows/scans.yml @@ -22,6 +22,8 @@ jobs: name: Coverity call-coverage: uses: ./.github/workflows/scan_coverage.yml + secrets: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} name: Coverage call-documentation: uses: ./.github/workflows/scan_documentation.yml @@ -32,3 +34,6 @@ jobs: call-stack-usage: uses: ./.github/workflows/scan_stack_usage.yml name: Stack usage + call-log-calls: + uses: ./.github/workflows/scan_log_calls.yml + name: Log calls diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index 3f81c6057de..7874483f567 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -27,7 +27,7 @@ jobs: TEST_BUILD: ['debug', 'nondebug'] steps: - name: Clone the git repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 50 @@ -41,3 +41,17 @@ jobs: env: TEST_BUILD: ${{ matrix.TEST_BUILD }} run: cd $WORKDIR && ./build-CI.sh + continue-on-error: true + id: build + + - name: Archive logs + if: steps.build.outcome != 'success' + uses: actions/upload-artifact@v4.2.0 + with: + name: logs-${{ matrix.TEST_BUILD }} + path: ${{env.HOST_WORKDIR}}/src/test/**/*.log + + - name: Exit code + run: | + [ "${{steps.build.outcome}}" != "success" ] && exit 1 + exit 0 diff --git a/CODING_STYLE.md b/CODING_STYLE.md index 3ca517d5e2a..9b99b7b9df3 100644 --- a/CODING_STYLE.md +++ b/CODING_STYLE.md @@ -76,7 +76,7 @@ for width-based integral types (`uint32_t`, `int64_t`, etc.). - Put `LOG(3, ...)` at the beginning of each function. Consider using higher log level for most frequently called routines. - Make use of `COMPILE_ERROR_ON` and `ASSERT*` macros. -- Use `ERR()` macro to log error messages. +- Use `ERR_W_ERRNO()`/`ERR_WO_ERRNO()` macros to log error messages. ### Unit tests - There **must** be unit tests provided for each new function/module added. diff --git a/ChangeLog b/ChangeLog index 6d3265fe76e..b4e96391a15 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,19 +1,39 @@ +Fri May 10 2024 Oksana Sałyk + + * Version 2.1.0 + + This release: + - Introduces the new logging subsystem in the release build for all libraries. + - Messages by default are printed to syslog and stderr but might be redirected to a user-defined function, see pmem(obj)_log_set_function() for details. + - Log level thresholds are controlled via new API, see pmem(obj)_log_set_treshold() for details. + - These new APIs are not available for LIBPMEM2 and LIBPMEMPOOL at the moment. + - The new logging subsystem is suppressed in the debug build when any of the legacy debug logging environment variables is set: + - PMEM_LOG_LEVEL/_FILE + - PMEM2_LOG_LEVEL/_FILE + - PMEMOBJ_LOG_LEVEL/_FILE + - PMEMPOOL_LOG_LEVEL/_FILE + - The debug logging subsystem becomes DEPRECATED. + - Introduces fuses against ill-considered use of NDCTL_ENABLE=n. + - PMEMOBJ_IGNORE_DIRTY_SHUTDOWN and PMEMOBJ_IGNORE_BAD_BLOCKS are required to acknowledge the understanding of what production-critical functions are missing for the build without NDCTL. + - Does not allow opening PMEMOBJ pool without unsafe shutdown counter (USC) if not explicitly disabled. (#5968) + - use PMEMOBJ_CONF="sds.at_create=0" to disable USC when working without PMem (emulated PMem, Docker, etc.). + - Drops support for building without libpthread (NO_LIBPTHREAD build-time define). + Mon Dec 4 2023 Oksana Sałyk * Version 2.0.1 - This release : + This release: - Significantly reduces the libpmem's stack usage. - Reduces libpmemobj's stack usage below the 11kB threshold. - Fixing minor Coverity issues - Add a new toolset for stack usage analysis (https://github.com/pmem/pmdk/tree/master/utils/call_stacks_analysis) - Tue Aug 8 2023 Oksana Sałyk * Version 2.0.0 - This release : + This release: - Removes libpmemlog, libpmemblk, btt, and their support in (lib)pmempool - Removes Windows support - Removes FreeBSD support @@ -33,7 +53,7 @@ Wed May 31 2023 Oksana Sałyk * Version 1.13.1 - This release : + This release: - Identifies and temporarily disables tests permanently or sporadically failing in some configurations: - ex_libpmem2 (#5593, #5635, #5638, #5641) diff --git a/INSTALL.md b/INSTALL.md index 4d5286d3585..4add4622aa8 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -20,7 +20,7 @@ You will need to install the following required packages on the build system: The following packages are required only by selected PMDK components or features: -PMDK depends on libndctl to support RAS features. It is possible +PMDK depends on libndctl and libdaxctl to support RAS features. It is possible to disable this support by passing `NDCTL_ENABLE=n` to `make`, but we strongly discourage users from doing that. Disabling NDCTL strips PMDK from ability to detect hardware failures, which may lead to silent data corruption. @@ -39,7 +39,7 @@ cd pmdk For a stable version, checkout a [release tag](https://github.com/pmem/pmdk/releases) as follows. Otherwise skip this step to build the latest development release. ```sh -git checkout tags/2.0.1 +git checkout tags/2.1.0 ``` Once all required [dependencies](#dependencies) are installed, PMDK is built using the @@ -108,15 +108,12 @@ Both building and installation scripts are very flexible. To see additional opti ### Memory Management Tools The PMDK libraries support standard Valgrind DRD, Helgrind and Memcheck, as well as a PM-aware version of [Valgrind](https://github.com/pmem/valgrind). -By default, support for all tools is enabled. If you wish to disable it, supply the compiler with `VG_\_ENABLED` flag set to 0, for example: +By default, support for all tools is enabled. If you wish to disable it, supply the compiler with `VALGRIND` flag set to 0: ```sh -make EXTRA_CFLAGS=-DVG_MEMCHECK_ENABLED=0 +make VALGRIND=0 ``` -`VALGRIND_ENABLED` flag, when set to 0, disables all Valgrind tools -(drd, helgrind, memcheck and pmemcheck). - The `SANITIZE` flag allows the libraries to be tested with various sanitizers. For example, to test the libraries with AddressSanitizer and UndefinedBehaviorSanitizer, run: diff --git a/doc/Makefile b/doc/Makefile index 764a1409c03..e7d77f95298 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2014-2023, Intel Corporation +# Copyright 2014-2024, Intel Corporation # # @@ -14,10 +14,12 @@ MANPAGES_7_MD = libpmem/libpmem.7.md libpmemobj/libpmemobj.7.md \ MANPAGES_5_MD = poolset/poolset.5.md pmem_ctl/pmem_ctl.5.md MANPAGES_3_MD = libpmem/pmem_flush.3.md libpmem/pmem_is_pmem.3.md libpmem/pmem_memmove_persist.3.md \ + libpmem/pmem_log_get_threshold.3.md libpmem/pmem_log_set_function.3.md libpmem/pmem_log_set_threshold.3.md \ libpmemobj/oid_is_null.3.md libpmemobj/pmemobj_action.3.md libpmemobj/pmemobj_alloc.3.md libpmemobj/pmemobj_ctl_get.3.md libpmemobj/pmemobj_first.3.md \ libpmemobj/pmemobj_list_insert.3.md libpmemobj/pmemobj_memcpy_persist.3.md libpmemobj/pmemobj_mutex_zero.3.md \ libpmemobj/pmemobj_open.3.md libpmemobj/pmemobj_root.3.md libpmemobj/pmemobj_tx_begin.3.md libpmemobj/pmemobj_tx_add_range.3.md \ libpmemobj/pmemobj_tx_alloc.3.md libpmemobj/pobj_layout_begin.3.md libpmemobj/pobj_list_head.3.md libpmemobj/toid_declare.3.md \ + libpmemobj/pmemobj_log_get_threshold.3.md libpmemobj/pmemobj_log_set_function.3.md libpmemobj/pmemobj_log_set_threshold.3.md \ libpmempool/pmempool_check_init.3.md libpmempool/pmempool_feature_query.3.md libpmempool/pmempool_rm.3.md libpmempool/pmempool_sync.3.md MANPAGES_1_MD = pmempool/pmempool.1.md pmempool/pmempool-info.1.md pmempool/pmempool-create.1.md \ @@ -64,7 +66,8 @@ MANPAGES_3_DUMMY = libpmem/pmem_drain.3 libpmem/pmem_has_hw_drain.3 libpmem/pmem libpmemobj/pmemobj_check_version.3 libpmemobj/pmemobj_check.3 libpmemobj/pmemobj_errormsg.3 libpmemobj/pmemobj_set_funcs.3 \ libpmemobj/pmemobj_reserve.3 libpmemobj/pmemobj_xreserve.3 libpmemobj/pmemobj_defer_free.3 libpmemobj/pmemobj_set_value.3 libpmemobj/pmemobj_publish.3 libpmemobj/pmemobj_tx_publish.3 libpmemobj/pmemobj_tx_xpublish.3 libpmemobj/pmemobj_cancel.3 libpmemobj/pobj_reserve_new.3 libpmemobj/pobj_reserve_alloc.3 libpmemobj/pobj_xreserve_new.3 libpmemobj/pobj_xreserve_alloc.3 \ libpmemobj/tx_xstrdup.3 libpmemobj/tx_xwcsdup.3 libpmemobj/tx_xfree.3 \ - libpmemobj/pmemobj_defrag.3 libpmemobj/pmemobj_get_user_data.3 libpmemobj/pmemobj_set_user_data.3 libpmemobj/pmemobj_tx_get_user_data.3 libpmemobj/pmemobj_tx_set_user_data.3 libpmemobj/pmemobj_tx_get_failure_behavior.3 libpmemobj/pmemobj_tx_set_failure_behavior.3 + libpmemobj/pmemobj_defrag.3 libpmemobj/pmemobj_get_user_data.3 libpmemobj/pmemobj_set_user_data.3 libpmemobj/pmemobj_tx_get_user_data.3 libpmemobj/pmemobj_tx_set_user_data.3 libpmemobj/pmemobj_tx_get_failure_behavior.3 libpmemobj/pmemobj_tx_set_failure_behavior.3 \ + libpmemobj/pmemobj_log_use_default_function.3 MANPAGES_WEBDIR_LINUX = web_linux diff --git a/doc/libpmem/.gitignore b/doc/libpmem/.gitignore index 810bf8b91a4..12f98ffb233 100644 --- a/doc/libpmem/.gitignore +++ b/doc/libpmem/.gitignore @@ -1,4 +1,7 @@ libpmem.7 pmem_flush.3 pmem_is_pmem.3 +pmem_log_get_treshold.3 +pmem_log_set_function.3 +pmem_log_set_treshold.3 pmem_memmove_persist.3 diff --git a/doc/libpmem/libpmem.7.md b/doc/libpmem/libpmem.7.md index b64454422e7..8684d7f8482 100644 --- a/doc/libpmem/libpmem.7.md +++ b/doc/libpmem/libpmem.7.md @@ -19,7 +19,9 @@ header: "pmem API version 1.1" [CAVEATS](#caveats)
[LIBRARY API VERSIONING](#library-api-versioning-1)
[ENVIRONMENT](#environment)
-[DEBUGGING AND ERROR HANDLING](#debugging-and-error-handling)
+[ERROR HANDLING](#error-handling)
+[DEBUGGING](#debugging)
+[LOGGING (DEPRECATED)](#logging-deprecated)
[EXAMPLE](#example)
[ACKNOWLEDGEMENTS](#acknowledgements)
[SEE ALSO](#see-also) @@ -223,7 +225,7 @@ affects all the PMDK libraries,** disabling mapping address randomization and causing the specified address to be used as a hint about where to place the mapping. -# DEBUGGING AND ERROR HANDLING # +# ERROR HANDLING # If an error is detected during the call to a **libpmem** function, the application may retrieve an error message describing the reason of the failure @@ -238,6 +240,14 @@ call to a **libpmem** function indicated an error. The application must not modify or free the error message string. Subsequent calls to other library functions may modify the previous message. +In parallel to the above mechanism, all logging messages are written to +**syslog**(3) and/or **stderr**(3) or passed to the user-provided logging +function. Please see **pmem_log_set_function**(3) for details. +The influx of the reported messages can be controlled by setting a respective +threshold value. Please see **pmem_log_set_threshold**(3) for details. + +# DEBUGGING # + Two versions of **libpmem** are typically available on a development system. The normal version, accessed when a program is linked using the **-lpmem** option, is optimized for performance. That version skips checks @@ -248,13 +258,17 @@ A second version of **libpmem**, accessed when a program uses the libraries under **/usr/lib/pmdk_debug**, contains run-time assertions and trace points. The typical way to access the debug version is to set the environment variable **LD_LIBRARY_PATH** to **/usr/lib/pmdk_debug** or **/usr/lib64/pmdk_debug**, -as appropriate. Debugging output is controlled using the following environment +as appropriate. + +# LOGGING (DEPRECATED) # + +Debugging output is controlled using the following environment variables. These variables have no effect on the non-debug version of the library. + **PMEM_LOG_LEVEL** -The value of **PMEM_LOG_LEVEL** enables trace points in the debug version -of the library, as follows: +The value of the **PMEM_LOG_LEVEL** environment variable enables trace points in +the debug version of the library, as follows: + **0** - This is the default level when **PMEM_LOG_LEVEL** is not set. No log messages are emitted at this level. @@ -271,7 +285,8 @@ library. + **4** - Enables voluminous and fairly obscure tracing information that is likely only useful to the **libpmem** developers. -Unless **PMEM_LOG_FILE** is set, debugging output is written to *stderr*. +Unless the **PMEM_LOG_FILE** environment variable is set, the debugging output +is written to *stderr*. + **PMEM_LOG_FILE** @@ -281,6 +296,11 @@ is "-", the *PID* of the current process will be appended to the file name when the log file is created. If **PMEM_LOG_FILE** is not set, output is written to *stderr*. +Whenever either **PMEM_LOG_LEVEL** or **PMEM_LOG_FILE** environment variable is +set the messages are not passed via the routes described in +the [ERROR HANDLING](#error-handling) section except for the **pmem_errormsg**() +which works unconditionally. + # EXAMPLE # The following example uses **libpmem** to flush changes made to raw, diff --git a/doc/libpmem/pmem_log_get_threshold.3.md b/doc/libpmem/pmem_log_get_threshold.3.md new file mode 100644 index 00000000000..ad4ee139804 --- /dev/null +++ b/doc/libpmem/pmem_log_get_threshold.3.md @@ -0,0 +1,56 @@ +--- +draft: false +slider_enable: true +description: "" +disclaimer: "The contents of this web site and the associated GitHub repositories are BSD-licensed open source." +aliases: ["pmem_log_get_threshold.3.html"] +title: "libpmem | PMDK" +header: "pmem API version 1.1" +--- + +[comment]: <> (SPDX-License-Identifier: BSD-3-Clause) +[comment]: <> (Copyright 2024, Intel Corporation) + +[comment]: <> (pmem_log_get_threshold.3 -- get the logging threshold value) + +[NAME](#name)
+[SYNOPSIS](#synopsis)
+[DESCRIPTION](#description)
+[RETURN VALUE](#return-value)
+[ERRORS](#errors)
+[SEE ALSO](#see-also)
+ +# NAME # + +**pmem_log_get_threshold** - get the logging threshold value + +# SYNOPSIS # + +```c + #include + + int pmem_log_get_threshold(enum pmem_log_threshold threshold, + enum pmem_log_level *value); +``` + +# DESCRIPTION # + +**pmem_log_get_threshold**() gets the current *value* of the *threshold*. +See **pmem_log_set_threshold**(3) for available thresholds and values. + +# RETURN VALUE # + +On success, **pmem_log_get_threshold**() function returns 0 and writes into +*value* the current value of the *threshold*. On failure, it returns +a non-zero value and sets errno. In case of failure, the *value* contents is undefined. + +# ERRORS # + +**pmem_log_get_threshold**() can fail with the following errors: + + - EINVAL - *threshold* is not **PMEM_LOG_THRESHOLD** nor **PMEM_LOG_THRESHOLD_AUX** + - EINVAL - *value* is NULL + +# SEE ALSO # + +**pmem_log_set_function**(3), **pmem_log_set_threshold**(3). diff --git a/doc/libpmem/pmem_log_set_function.3.md b/doc/libpmem/pmem_log_set_function.3.md new file mode 100644 index 00000000000..22f6e3fb203 --- /dev/null +++ b/doc/libpmem/pmem_log_set_function.3.md @@ -0,0 +1,109 @@ +--- +draft: false +slider_enable: true +description: "" +disclaimer: "The contents of this web site and the associated GitHub repositories are BSD-licensed open source." +aliases: ["pmem_log_set_function.3.html"] +title: "libpmem | PMDK" +header: "pmem API version 1.1" +--- + +[comment]: <> (SPDX-License-Identifier: BSD-3-Clause) +[comment]: <> (Copyright 2024, Intel Corporation) + +[comment]: <> (pmem_log_set_function.3 -- set the logging function) + +[NAME](#name)
+[SYNOPSIS](#synopsis)
+[DESCRIPTION](#description)
+[THE DEFAULT LOGGING FUNCTION](#the-default-logging-function)
+[RETURN VALUE](#return-value)
+[ERRORS](#errors)
+[NOTE](#note)
+[SEE ALSO](#see-also)
+ +# NAME # + +**pmem_log_set_function**() - set the logging function + +# SYNOPSIS # + +```c + #include + + typedef void pmem_log_function( + enum pmem_log_level level, + const char *file_name, + unsigned line_no, + const char *function_name, + const char *message); + + int pmem_log_set_function(pmem_log_function *log_function); +``` + +# DESCRIPTION # + +**pmem_log_set_function**() allows choosing the function which will get all +the generated logging messages. The *log_function* can be either +**PMEM_LOG_USE_DEFAULT_FUNCTION** which will use the default logging function +(built into the library) or a pointer to a user-defined function. + +The parameters of a user-defined log function are as follows: + + - *level* - the log level of the message (see **pmem_log_set_threshold**(3) + for available log levels) + - *file_name* - name of the source file where the message is coming from. + It could be set to NULL and in such case, neither *line_no* nor *function_name* + are provided. + - *line_no* - the source file line where the message is coming from + - *function_name* - the function name where the message is coming from + - *message* - the message string + +# THE DEFAULT LOGGING FUNCTION # + +The library provides the default logging function which writes messages to +**syslog**(3) and to **stderr**(3). This function is enabled during library +initialization and can be restored using **PMEM_LOG_USE_DEFAULT_FUNCTION** value +as the *log_function* argument. + +The default logging function sinks all the logging messages into **syslog**(3) +unconditionally. Additionally, it sinks a logging message into **stderr**(3) +if its logging level is not less severe than indicated by +the **PMEM_LOG_THRESHOLD_AUX** threshold's value and it is not of level +**PMEM_LOG_LEVEL_HARK**. + +Note that the **PMEM_LOG_THRESHOLD** threshold's value applies to +the default logging function. Please see the notes below. + +# RETURN VALUE # + +**pmem_log_set_function**() function returns 0 on success or returns +a non-zero value and sets errno on failure. On failure, the logging +function remains unchanged. + +# ERRORS # + +**pmem_log_set_function**() can set the following errno values on fail: + + - EAGAIN - multiple threads attempted to change the logging function concurrently. + A retry may fix the problem. This error is not expected when the function is + called from just one thread at a time. + +# NOTE # + +The logging messages of level less severe than indicated by +the **PMEM_LOG_THRESHOLD** threshold's value won't make it to the logging function +no matter whether the logging function is the default logging function or user-provided. + +The user-defined function must be thread-safe. + +The library will call user defined function before returning from **pmem_log_set_function**() +to deliver basic information about the library: + + - "src version: 2.y.z" + - "compiled with support for shutdown state" + - "compiled with libndctl 63+" + +# SEE ALSO # + +**pmem_log_get_threshold**(3), **pmem_log_set_threshold**(3). diff --git a/doc/libpmem/pmem_log_set_threshold.3.md b/doc/libpmem/pmem_log_set_threshold.3.md new file mode 100644 index 00000000000..890c36e1cf1 --- /dev/null +++ b/doc/libpmem/pmem_log_set_threshold.3.md @@ -0,0 +1,104 @@ +--- +draft: false +slider_enable: true +description: "" +disclaimer: "The contents of this web site and the associated GitHub repositories are BSD-licensed open source." +aliases: ["pmem_log_set_threshold.3.html"] +title: "libpmem | PMDK" +header: "pmem API version 1.1" +--- + +[comment]: <> (SPDX-License-Identifier: BSD-3-Clause) +[comment]: <> (Copyright 2024, Intel Corporation) + +[comment]: <> (pmem_log_set_threshold.3 -- set the logging threshold value) + +[NAME](#name)
+[SYNOPSIS](#synopsis)
+[DESCRIPTION](#description)
+[RETURN VALUE](#return-value)
+[ERRORS](#errors)
+[SEE ALSO](#see-also)
+ +# NAME # + +**pmem_log_set_threshold** - set the logging threshold value + +# SYNOPSIS # + +```c + #include + + enum pmem_log_level { + PMEM_LOG_LEVEL_HARK, + PMEM_LOG_LEVEL_FATAL, + PMEM_LOG_LEVEL_ERROR, + PMEM_LOG_LEVEL_WARNING, + PMEM_LOG_LEVEL_NOTICE, + PMEM_LOG_LEVEL_INFO, + PMEM_LOG_LEVEL_DEBUG + }; + + enum pmem_log_threshold { + PMEM_LOG_THRESHOLD, + PMEM_LOG_THRESHOLD_AUX + }; + + int pmem_log_set_threshold(enum pmem_log_threshold threshold, + enum pmem_log_level value); +``` + +# DESCRIPTION # + +**pmem_log_set_threshold**() sets the logging threshold value. + +Available thresholds are: + + - **PMEM_LOG_THRESHOLD** - the main threshold used to filter out undesired + logging messages. Messages less severe than indicated by this threshold's + value are ignored so they won't make it to the logging function + (please see **pmem_log_set_function**(3)). + The default value is **PMEM_LOG_WARNING**. + - **PMEM_LOG_THRESHOLD_AUX** - the auxiliary threshold intended for use inside + the logging function (please see **pmem_log_get_threshold**(3)). A custom + logging function may or may not take this threshold into consideration depending + on the developer's needs. For the default logging function behaviour please see + **pmem_log_set_function**(3). The initial value of this threshold is + **PMEM_LOG_LEVEL_HARK**. + +Available threshold values are defined by enum *pmem_log_level*. +They are listed in descending order of severity: + + - **PMEM_LOG_LEVEL_HARK** - only basic library info. Shall be used to + effectively suppress the logging since it is used just for a few messages + when the program is started and whenever a new logging function is set. + Please see **pmem_log_set_function**(3). + - **PMEM_LOG_LEVEL_FATAL** - an error that causes the program to stop working + immediately. Sorry. + - **PMEM_LOG_LEVEL_ERROR** - an error that causes the current operation to fail + - **PMEM_LOG_LEVEL_WARNING** - an unexpected situation that does NOT + cause the current operation to fail + - **PMEM_LOG_LEVEL_NOTICE** - non-massive info mainly related to public API + function completions + - **PMEM_LOG_LEVEL_INFO** - massive info e.g. every write operation indication + - **PMEM_LOG_LEVEL_DEBUG** - debug info e.g. write operation dump + +# RETURN VALUE # + +**pmem_log_set_threshold**() function returns 0 on success or returns +a non-zero value and sets errno on failure. On failure, the *threshold* value remains unchanged. + +# ERRORS # + +**pmem_log_set_threshold**() can set the following errno values on fail: + + - EINVAL - *threshold* is not **PMEM_LOG_THRESHOLD** nor + **PMEM_LOG_THRESHOLD_AUX** + - EINVAL - *value* is not defined by enum *pmem_log_level* type + - EAGAIN - multiple threads attempted to change the *threshold* value concurrently. + A retry may fix the problem. This error is not expected when the function is + called from just one thread at a time. + +# SEE ALSO # + +**pmem_log_get_threshold**(3), **pmem_log_set_function**(3). diff --git a/doc/libpmemobj/.gitignore b/doc/libpmemobj/.gitignore index 19523dae4f9..f0e1a6f0f43 100644 --- a/doc/libpmemobj/.gitignore +++ b/doc/libpmemobj/.gitignore @@ -5,6 +5,9 @@ pmemobj_alloc.3 pmemobj_ctl_get.3 pmemobj_first.3 pmemobj_list_insert.3 +pmemobj_log_get_threshold.3 +pmemobj_log_set_function.3 +pmemobj_log_set_threshold.3 pmemobj_memcpy_persist.3 pmemobj_mutex_zero.3 pmemobj_open.3 diff --git a/doc/libpmemobj/libpmemobj.7.md b/doc/libpmemobj/libpmemobj.7.md index 3c089ae708c..8d2135f9bc2 100644 --- a/doc/libpmemobj/libpmemobj.7.md +++ b/doc/libpmemobj/libpmemobj.7.md @@ -18,7 +18,9 @@ header: "pmemobj API version 2.3" [DESCRIPTION](#description)
[LIBRARY API VERSIONING](#library-api-versioning-1)
[MANAGING LIBRARY BEHAVIOR](#managing-library-behavior-1)
-[DEBUGGING AND ERROR HANDLING](#debugging-and-error-handling)
+[ERROR HANDLING](#error-handling)
+[DEBUGGING](#debugging)
+[LOGGING (DEPRECATED)](#logging-deprecated)
[EXAMPLE](#example)
[ACKNOWLEDGEMENTS](#acknowledgements)
[SEE ALSO](#see-also)
@@ -162,7 +164,7 @@ transactions/allocations. For debugging purposes it is possible to decrease this value by setting the **PMEMOBJ_NLANES** environment variable to the desired limit. -# DEBUGGING AND ERROR HANDLING # +# ERROR HANDLING # If an error is detected during the call to a **libpmemobj** function, the application may retrieve an error message describing the reason for the failure @@ -177,6 +179,14 @@ call to a **libpmemobj** function indicated an error, or if *errno* was set. The application must not modify or free the error message string, but it may be modified by subsequent calls to other library functions. +In parallel to the above mechanism, all logging messages are written to +**syslog**(3) and/or **stderr**(3) or passed to the user-provided logging +function. Please see **pmemobj_log_set_function**(3) for details. +The influx of the reported messages can be controlled by setting a respective +threshold value. Please see **pmemobj_log_set_threshold**(3) for details. + +# DEBUGGING # + Two versions of **libpmemobj** are typically available on a development system. The normal version, accessed when a program is linked using the **-lpmemobj** option, is optimized for performance. That version skips checks @@ -187,13 +197,17 @@ A second version of **libpmemobj**, accessed when a program uses the libraries under **/usr/lib/pmdk_debug**, contains run-time assertions and trace points. The typical way to access the debug version is to set the environment variable **LD_LIBRARY_PATH** to **/usr/lib/pmdk_debug** or **/usr/lib64/pmdk_debug**, -as appropriate. Debugging output is controlled using the following environment +as appropriate. + +# LOGGING (DEPRECATED) # + +Debugging output is controlled using the following environment variables. These variables have no effect on the non-debug version of the library. + **PMEMOBJ_LOG_LEVEL** -The value of **PMEMOBJ_LOG_LEVEL** enables trace points in the debug version -of the library, as follows: +The value of the **PMEMOBJ_LOG_LEVEL** environment variable enables trace points +in the debug version of the library, as follows: + **0** - This is the default level when **PMEMOBJ_LOG_LEVEL** is not set. No log messages are emitted at this level. @@ -210,7 +224,8 @@ tracing in the library. + **4** - Enables voluminous and fairly obscure tracing information that is likely only useful to the **libpmemobj** developers. -Unless **PMEMOBJ_LOG_FILE** is set, debugging output is written to *stderr*. +Unless the **PMEMOBJ_LOG_FILE** environment variable is set, the debugging +output is written to *stderr*. + **PMEMOBJ_LOG_FILE** @@ -219,6 +234,11 @@ If the last character in the name is "-", the *PID* of the current process will be appended to the file name when the log file is created. If **PMEMOBJ_LOG_FILE** is not set, logging output is written to *stderr*. +Whenever either **PMEMOBJ_LOG_LEVEL** or **PMEMOBJ_LOG_FILE** environment +variable is set the messages are not passed via the routes described in +the [ERROR HANDLING](#error-handling) section except for +the **pmemobj_errormsg**() which works unconditionally. + See also **libpmem**(7) to get information about other environment variables affecting **libpmemobj** behavior. diff --git a/doc/libpmemobj/pmemobj_log_get_threshold.3.md b/doc/libpmemobj/pmemobj_log_get_threshold.3.md new file mode 100644 index 00000000000..0fafe5c8f4e --- /dev/null +++ b/doc/libpmemobj/pmemobj_log_get_threshold.3.md @@ -0,0 +1,56 @@ +--- +draft: false +slider_enable: true +description: "" +disclaimer: "The contents of this web site and the associated GitHub repositories are BSD-licensed open source." +aliases: ["pmemobj_log_get_threshold.3.html"] +title: "libpmemobj | PMDK" +header: "pmemobj API version 2.3" +--- + +[comment]: <> (SPDX-License-Identifier: BSD-3-Clause) +[comment]: <> (Copyright 2024, Intel Corporation) + +[comment]: <> (pmemobj_log_get_threshold.3 -- get the logging threshold value) + +[NAME](#name)
+[SYNOPSIS](#synopsis)
+[DESCRIPTION](#description)
+[RETURN VALUE](#return-value)
+[ERRORS](#errors)
+[SEE ALSO](#see-also)
+ +# NAME # + +**pmemobj_log_get_threshold** - get the logging threshold value + +# SYNOPSIS # + +```c + #include + + int pmemobj_log_get_threshold(enum pmemobj_log_threshold threshold, + enum pmemobj_log_level *value); +``` + +# DESCRIPTION # + +**pmemobj_log_get_threshold**() gets the current *value* of the *threshold*. +See **pmemobj_log_set_threshold**(3) for available thresholds and values. + +# RETURN VALUE # + +On success, **pmemobj_log_get_threshold**() function returns 0 and writes into +*value* the current value of the *threshold*. On failure, it returns +a non-zero value and sets errno. In case of failure, the *value* contents is undefined. + +# ERRORS # + +**pmemobj_log_get_threshold**() can fail with the following errors: + + - EINVAL - *threshold* is not **PMEMOBJ_LOG_THRESHOLD** nor **PMEMOBJ_LOG_THRESHOLD_AUX** + - EINVAL - *value* is NULL + +# SEE ALSO # + +**pmemobj_log_set_function**(3), **pmemobj_log_set_threshold**(3). diff --git a/doc/libpmemobj/pmemobj_log_set_function.3.md b/doc/libpmemobj/pmemobj_log_set_function.3.md new file mode 100644 index 00000000000..775e436aa1c --- /dev/null +++ b/doc/libpmemobj/pmemobj_log_set_function.3.md @@ -0,0 +1,109 @@ +--- +draft: false +slider_enable: true +description: "" +disclaimer: "The contents of this web site and the associated GitHub repositories are BSD-licensed open source." +aliases: ["pmemobj_log_set_function.3.html"] +title: "libpmemobj | PMDK" +header: "pmemobj API version 2.3" +--- + +[comment]: <> (SPDX-License-Identifier: BSD-3-Clause) +[comment]: <> (Copyright 2024, Intel Corporation) + +[comment]: <> (pmemobj_log_set_function.3 -- set the logging function) + +[NAME](#name)
+[SYNOPSIS](#synopsis)
+[DESCRIPTION](#description)
+[THE DEFAULT LOGGING FUNCTION](#the-default-logging-function)
+[RETURN VALUE](#return-value)
+[ERRORS](#errors)
+[NOTE](#note)
+[SEE ALSO](#see-also)
+ +# NAME # + +**pmemobj_log_set_function**() - set the logging function + +# SYNOPSIS # + +```c + #include + + typedef void pmemobj_log_function( + enum pmemobj_log_level level, + const char *file_name, + unsigned line_no, + const char *function_name, + const char *message); + + int pmemobj_log_set_function(pmemobj_log_function *log_function); +``` + +# DESCRIPTION # + +**pmemobj_log_set_function**() allows choosing the function which will get all +the generated logging messages. The *log_function* can be either +**PMEMOBJ_LOG_USE_DEFAULT_FUNCTION** which will use the default logging function +(built into the library) or a pointer to a user-defined function. + +The parameters of a user-defined log function are as follows: + + - *level* - the log level of the message (see **pmemobj_log_set_threshold**(3) + for available log levels) + - *file_name* - name of the source file where the message is coming from. + It could be set to NULL and in such case, neither *line_no* nor *function_name* + are provided. + - *line_no* - the source file line where the message is coming from + - *function_name* - the function name where the message is coming from + - *message* - the message string + +# THE DEFAULT LOGGING FUNCTION # + +The library provides the default logging function which writes messages to +**syslog**(3) and to **stderr**(3). This function is enabled during library +initialization and can be restored using **PMEMOBJ_LOG_USE_DEFAULT_FUNCTION** value +as the *log_function* argument. + +The default logging function sinks all the logging messages into **syslog**(3) +unconditionally. Additionally, it sinks a logging message into **stderr**(3) +if its logging level is not less severe than indicated by +the **PMEMOBJ_LOG_THRESHOLD_AUX** threshold's value and it is not of level +**PMEMOBJ_LOG_LEVEL_HARK**. + +Note that the **PMEMOBJ_LOG_THRESHOLD** threshold's value applies to +the default logging function. Please see the notes below. + +# RETURN VALUE # + +**pmemobj_log_set_function**() function returns 0 on success or returns +a non-zero value and sets errno on failure. On failure, the logging +function remains unchanged. + +# ERRORS # + +**pmemobj_log_set_function**() can set the following errno values on fail: + + - EAGAIN - multiple threads attempted to change the logging function concurrently. + A retry may fix the problem. This error is not expected when the function is + called from just one thread at a time. + +# NOTE # + +The logging messages of level less severe than indicated by +the **PMEMOBJ_LOG_THRESHOLD** threshold's value won't make it to the logging function +no matter whether the logging function is the default logging function or user-provided. + +The user-defined function must be thread-safe. + +The library will call user defined function before returning from **pmemobj_log_set_function**() +to deliver basic information about the library: + + - "src version: 2.y.z" + - "compiled with support for shutdown state" + - "compiled with libndctl 63+" + +# SEE ALSO # + +**pmemobj_log_get_threshold**(3), **pmemobj_log_set_threshold**(3). diff --git a/doc/libpmemobj/pmemobj_log_set_threshold.3.md b/doc/libpmemobj/pmemobj_log_set_threshold.3.md new file mode 100644 index 00000000000..d174aa780c8 --- /dev/null +++ b/doc/libpmemobj/pmemobj_log_set_threshold.3.md @@ -0,0 +1,104 @@ +--- +draft: false +slider_enable: true +description: "" +disclaimer: "The contents of this web site and the associated GitHub repositories are BSD-licensed open source." +aliases: ["pmemobj_log_set_threshold.3.html"] +title: "libpmemobj | PMDK" +header: "pmemobj API version 2.3" +--- + +[comment]: <> (SPDX-License-Identifier: BSD-3-Clause) +[comment]: <> (Copyright 2024, Intel Corporation) + +[comment]: <> (pmemobj_log_set_threshold.3 -- set the logging threshold value) + +[NAME](#name)
+[SYNOPSIS](#synopsis)
+[DESCRIPTION](#description)
+[RETURN VALUE](#return-value)
+[ERRORS](#errors)
+[SEE ALSO](#see-also)
+ +# NAME # + +**pmemobj_log_set_threshold** - set the logging threshold value + +# SYNOPSIS # + +```c + #include + + enum pmemobj_log_level { + PMEMOBJ_LOG_LEVEL_HARK, + PMEMOBJ_LOG_LEVEL_FATAL, + PMEMOBJ_LOG_LEVEL_ERROR, + PMEMOBJ_LOG_LEVEL_WARNING, + PMEMOBJ_LOG_LEVEL_NOTICE, + PMEMOBJ_LOG_LEVEL_INFO, + PMEMOBJ_LOG_LEVEL_DEBUG + }; + + enum pmemobj_log_threshold { + PMEMOBJ_LOG_THRESHOLD, + PMEMOBJ_LOG_THRESHOLD_AUX + }; + + int pmemobj_log_set_threshold(enum pmemobj_log_threshold threshold, + enum pmemobj_log_level value); +``` + +# DESCRIPTION # + +**pmemobj_log_set_threshold**() sets the logging threshold value. + +Available thresholds are: + + - **PMEMOBJ_LOG_THRESHOLD** - the main threshold used to filter out undesired + logging messages. Messages less severe than indicated by this threshold's + value are ignored so they won't make it to the logging function + (please see **pmemobj_log_set_function**(3)). + The default value is **PMEMOBJ_LOG_WARNING**. + - **PMEMOBJ_LOG_THRESHOLD_AUX** - the auxiliary threshold intended for use inside + the logging function (please see **pmemobj_log_get_threshold**(3)). A custom + logging function may or may not take this threshold into consideration depending + on the developer's needs. For the default logging function behaviour please see + **pmemobj_log_set_function**(3). The initial value of this threshold is + **PMEMOBJ_LOG_LEVEL_HARK**. + +Available threshold values are defined by enum *pmemobj_log_level*. +They are listed in descending order of severity: + + - **PMEMOBJ_LOG_LEVEL_HARK** - only basic library info. Shall be used to + effectively suppress the logging since it is used just for a few messages + when the program is started and whenever a new logging function is set. + Please see **pmemobj_log_set_function**(3). + - **PMEMOBJ_LOG_LEVEL_FATAL** - an error that causes the program to stop working + immediately. Sorry. + - **PMEMOBJ_LOG_LEVEL_ERROR** - an error that causes the current operation or transaction to fail + - **PMEMOBJ_LOG_LEVEL_WARNING** - an unexpected situation that does NOT + cause the current operation to fail + - **PMEMOBJ_LOG_LEVEL_NOTICE** - non-massive info mainly related to public API + function completions + - **PMEMOBJ_LOG_LEVEL_INFO** - massive info e.g. every write operation indication + - **PMEMOBJ_LOG_LEVEL_DEBUG** - debug info e.g. write operation dump + +# RETURN VALUE # + +**pmemobj_log_set_threshold**() function returns 0 on success or returns +a non-zero value and sets errno on failure. On failure, the *threshold* value remains unchanged. + +# ERRORS # + +**pmemobj_log_set_threshold**() can set the following errno values on fail: + + - EINVAL - *threshold* is not **PMEMOBJ_LOG_THRESHOLD** nor + **PMEMOBJ_LOG_THRESHOLD_AUX** + - EINVAL - *value* is not defined by enum *pmemobj_log_level* type + - EAGAIN - multiple threads attempted to change the *threshold* value concurrently. + A retry may fix the problem. This error is not expected when the function is + called from just one thread at a time. + +# SEE ALSO # + +**pmemobj_log_get_threshold**(3), **pmemobj_log_set_function**(3). diff --git a/doc/libpmemobj/pmemobj_log_use_default_function.3 b/doc/libpmemobj/pmemobj_log_use_default_function.3 new file mode 100644 index 00000000000..fef4f379b5a --- /dev/null +++ b/doc/libpmemobj/pmemobj_log_use_default_function.3 @@ -0,0 +1 @@ +.so pmemobj_log_set_function.3 diff --git a/src/benchmarks/Makefile b/src/benchmarks/Makefile index f70c4f17856..81691ccc765 100644 --- a/src/benchmarks/Makefile +++ b/src/benchmarks/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2014-2023, Intel Corporation +# Copyright 2014-2024, Intel Corporation # # src/benchmarks/Makefile -- build all benchmarks @@ -109,6 +109,11 @@ LDFLAGS += $(GCOV_LDFLAGS) LIBS += $(GCOV_LIBS) endif +ifeq ($(VALGRIND),0) +CFLAGS += -DVALGRIND_ENABLED=0 +CXXFLAGS += -DVALGRIND_ENABLED=0 +endif + ifneq ($(SANITIZE),) CXXFLAGS += -fsanitize=$(SANITIZE) LDFLAGS += -fsanitize=$(SANITIZE) diff --git a/src/benchmarks/obj_pmalloc.cpp b/src/benchmarks/obj_pmalloc.cpp index 614bdf074e2..c0efdffd8bf 100644 --- a/src/benchmarks/obj_pmalloc.cpp +++ b/src/benchmarks/obj_pmalloc.cpp @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2015-2020, Intel Corporation */ +/* Copyright 2015-2024, Intel Corporation */ /* * obj_pmalloc.cpp -- pmalloc benchmarks definition @@ -27,7 +27,7 @@ * The factor used for PMEM pool size calculation, accounts for metadata, * fragmentation and etc. */ -#define FACTOR 1.2f +#define FACTOR 1.9f /* The minimum allocation size that pmalloc can perform */ #define ALLOC_MIN_SIZE 64 @@ -236,7 +236,7 @@ pmalloc_op(struct benchmark *bench, struct operation_info *info) int ret = pmalloc(ob->pop, &ob->offs[i], ob->sizes[i], 0, 0); if (ret) { - fprintf(stderr, "pmalloc ret: %d\n", ret); + perror("pmalloc"); return ret; } diff --git a/src/benchmarks/perf.cfg b/src/benchmarks/perf.cfg index 7fa71690e09..ede7ac6536b 100644 --- a/src/benchmarks/perf.cfg +++ b/src/benchmarks/perf.cfg @@ -6,8 +6,8 @@ repeats = 3 [obj_tx_alloc_small_v_thread] bench = obj_tx_alloc group = pmemobj -ops-per-thread = 200000 -threads = 1:+1:32 +ops-per-thread = 6000000 +threads = 1:*2:32 type-number = per-thread data-size = 256 @@ -33,8 +33,8 @@ data-size = 64:*2:32768 [obj_pmalloc_small_v_threads] bench = pmalloc group = pmemobj -ops-per-thread = 200000 -threads = 1:+1:32 +ops-per-thread = 2000000 +threads = 1:*2:32 data-size = 100 # pmalloc (size = 128k) vs threads diff --git a/src/benchmarks/pmemobj_tx.cpp b/src/benchmarks/pmemobj_tx.cpp index 9fca99cefbf..3c4ff0fbf33 100644 --- a/src/benchmarks/pmemobj_tx.cpp +++ b/src/benchmarks/pmemobj_tx.cpp @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2015-2020, Intel Corporation */ +/* Copyright 2015-2024, Intel Corporation */ /* * pmemobj_tx.cpp -- pmemobj_tx_alloc(), pmemobj_tx_free(), @@ -19,7 +19,7 @@ #include "poolset_util.hpp" #define LAYOUT_NAME "benchmark" -#define FACTOR 1.2f +#define FACTOR 1.3f #define ALLOC_OVERHEAD 64 /* * operations number is limited to prevent stack overflow during diff --git a/src/common.inc b/src/common.inc index 43c7914d577..1f42b425718 100644 --- a/src/common.inc +++ b/src/common.inc @@ -332,9 +332,7 @@ NDCTL_ENABLE ?= y ifeq ($(NDCTL_ENABLE),y) ifeq ($(LIBNDCTL_LIBS),) HAS_NDCTL := $(call check_package, libndctl --atleast-version $(NDCTL_MIN_VERSION)) - ifeq ($(HAS_NDCTL),y) - OS_DIMM_CFLAG=-DNDCTL_ENABLED=1 - else + ifeq ($(HAS_NDCTL),n) $(error Please install libndctl-dev/libndctl-devel/ndctl-devel >= $(NDCTL_MIN_VERSION)) endif HAS_DAXCTL := $(call check_package, libdaxctl --atleast-version $(NDCTL_MIN_VERSION)) @@ -348,8 +346,10 @@ ifeq ($(NDCTL_ENABLE),y) LIBNDCTL_LIBS := $(shell $(PKG_CONFIG) --libs $(LIBNDCTL_PKG_CONFIG_DEPS)) endif OS_DIMM := ndctl + OS_DIMM_CFLAG=-DNDCTL_ENABLED=1 else OS_DIMM := none + OS_DIMM_CFLAG=-DNDCTL_ENABLED=0 endif export OS_DIMM export LIBNDCTL_PKG_CONFIG_DEPS diff --git a/src/common/bad_blocks.c b/src/common/bad_blocks.c index 28bf2843a26..54f89d65d17 100644 --- a/src/common/bad_blocks.c +++ b/src/common/bad_blocks.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2018-2020, Intel Corporation */ +/* Copyright 2018-2024, Intel Corporation */ /* * bad_blocks.c - implementation of the bad block API using libpmem2 library @@ -11,6 +11,7 @@ #include "libpmem2.h" #include "badblocks.h" #include "out.h" +#include "core_assert.h" #include "vec.h" #include "os.h" @@ -59,7 +60,7 @@ badblocks_get(const char *file, struct badblocks *bbs) int fd = os_open(file, O_RDONLY); if (fd == -1) { - ERR("!open %s", file); + ERR_W_ERRNO("open %s", file); return -1; } @@ -138,7 +139,7 @@ badblocks_clear(const char *file, struct badblocks *bbs) int fd = os_open(file, O_RDWR); if (fd == -1) { - ERR("!open %s", file); + ERR_W_ERRNO("open %s", file); return -1; } @@ -148,7 +149,7 @@ badblocks_clear(const char *file, struct badblocks *bbs) ret = pmem2_badblock_context_new(&bbctx, src); if (ret) { - LOG(1, "pmem2_badblock_context_new failed -- %s", file); + CORE_LOG_ERROR("pmem2_badblock_context_new failed -- %s", file); goto exit_delete_source; } @@ -157,7 +158,7 @@ badblocks_clear(const char *file, struct badblocks *bbs) bb.length = bbs->bbv[b].length; ret = pmem2_badblock_clear(bbctx, &bb); if (ret) { - LOG(1, "pmem2_badblock_clear -- %s", file); + CORE_LOG_ERROR("pmem2_badblock_clear -- %s", file); goto exit_delete_ctx; } } @@ -196,7 +197,7 @@ badblocks_clear_all(const char *file) int fd = os_open(file, O_RDWR); if (fd == -1) { - ERR("!open %s", file); + ERR_W_ERRNO("open %s", file); return -1; } @@ -206,14 +207,14 @@ badblocks_clear_all(const char *file) ret = pmem2_badblock_context_new(&bbctx, src); if (ret) { - LOG(1, "pmem2_badblock_context_new failed -- %s", file); + CORE_LOG_ERROR("pmem2_badblock_context_new failed -- %s", file); goto exit_delete_source; } while ((pmem2_badblock_next(bbctx, &bb)) == 0) { ret = pmem2_badblock_clear(bbctx, &bb); if (ret) { - LOG(1, "pmem2_badblock_clear -- %s", file); + CORE_LOG_ERROR("pmem2_badblock_clear -- %s", file); goto exit_delete_ctx; } }; @@ -251,12 +252,13 @@ badblocks_check_file(const char *file) long bbsc = badblocks_count(file); if (bbsc < 0) { - LOG(1, "counting bad blocks failed -- '%s'", file); + CORE_LOG_ERROR("counting bad blocks failed -- '%s'", file); return -1; } if (bbsc > 0) { - LOG(1, "pool file '%s' contains %li bad block(s)", file, bbsc); + CORE_LOG_ERROR("pool file '%s' contains %li bad block(s)", file, + bbsc); return 1; } diff --git a/src/common/ctl.c b/src/common/ctl.c index b86690fb814..13d4e94f978 100644 --- a/src/common/ctl.c +++ b/src/common/ctl.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2016-2023, Intel Corporation */ +/* Copyright 2016-2024, Intel Corporation */ /* * ctl.c -- implementation of the interface for examination and modification of @@ -8,12 +8,13 @@ #include "ctl.h" #include "os.h" #include "alloc.h" +#include "core_assert.h" #define CTL_MAX_ENTRIES 100 #define MAX_CONFIG_FILE_LEN (1 << 20) /* 1 megabyte */ -#define CTL_STRING_QUERY_SEPARATOR ";" +#define CTL_STRING_QUERY_SEPARATOR ";:" #define CTL_NAME_VALUE_SEPARATOR "=" #define CTL_QUERY_NODE_SEPARATOR "." #define CTL_VALUE_ARG_SEPARATOR "," @@ -128,7 +129,7 @@ ctl_parse_args(const struct ctl_argument *arg_proto, char *arg) char *dest_arg = Malloc(arg_proto->dest_size); if (dest_arg == NULL) { - ERR("!Malloc"); + ERR_W_ERRNO("Malloc"); return NULL; } @@ -138,7 +139,7 @@ ctl_parse_args(const struct ctl_argument *arg_proto, char *arg) p->parser != NULL; ++p) { ASSERT(p->dest_offset + p->dest_size <= arg_proto->dest_size); if (arg_sep == NULL) { - ERR("!strtok_r"); + ERR_W_ERRNO("strtok_r"); goto error_parsing; } @@ -211,7 +212,7 @@ ctl_exec_query_read(void *ctx, const struct ctl_node *n, enum ctl_query_source source, void *arg, struct ctl_indexes *indexes) { if (arg == NULL) { - ERR("read queries require non-NULL argument"); + ERR_WO_ERRNO("read queries require non-NULL argument"); errno = EINVAL; return -1; } @@ -227,14 +228,14 @@ ctl_exec_query_write(void *ctx, const struct ctl_node *n, enum ctl_query_source source, void *arg, struct ctl_indexes *indexes) { if (arg == NULL) { - ERR("write queries require non-NULL argument"); + ERR_WO_ERRNO("write queries require non-NULL argument"); errno = EINVAL; return -1; } void *real_arg = ctl_query_get_real_args(n, arg, source); if (real_arg == NULL) { - LOG(1, "Invalid arguments"); + CORE_LOG_ERROR("Invalid arguments"); return -1; } @@ -274,7 +275,7 @@ ctl_query(struct ctl *ctl, void *ctx, enum ctl_query_source source, ctl, ctx, source, name, type, arg); if (name == NULL) { - ERR("invalid query"); + ERR_WO_ERRNO("invalid query"); errno = EINVAL; return -1; } @@ -298,7 +299,7 @@ ctl_query(struct ctl *ctl, void *ctx, enum ctl_query_source source, } if (n == NULL || n->type != CTL_NODE_LEAF || n->cb[type] == NULL) { - ERR("invalid query entry point %s", name); + ERR_WO_ERRNO("invalid query entry point %s", name); errno = EINVAL; goto out; } @@ -370,7 +371,7 @@ ctl_load_config(struct ctl *ctl, void *ctx, char *buf) while (qbuf != NULL) { r = ctl_parse_query(qbuf, &name, &value); if (r != 0) { - ERR("failed to parse query %s", qbuf); + ERR_WO_ERRNO("failed to parse query %s", qbuf); return -1; } @@ -396,7 +397,7 @@ ctl_load_config_from_string(struct ctl *ctl, void *ctx, const char *cfg_string) char *buf = Strdup(cfg_string); if (buf == NULL) { - ERR("!Strdup"); + ERR_W_ERRNO("Strdup"); return -1; } @@ -432,7 +433,7 @@ ctl_load_config_from_file(struct ctl *ctl, void *ctx, const char *cfg_file) goto error_file_parse; if (fsize > MAX_CONFIG_FILE_LEN) { - ERR("Config file too large"); + ERR_WO_ERRNO("Config file too large"); goto error_file_parse; } @@ -441,7 +442,7 @@ ctl_load_config_from_file(struct ctl *ctl, void *ctx, const char *cfg_file) char *buf = Zalloc((size_t)fsize + 1); /* +1 for NULL-termination */ if (buf == NULL) { - ERR("!Zalloc"); + ERR_W_ERRNO("Zalloc"); goto error_file_parse; } @@ -475,7 +476,7 @@ ctl_new(void) { struct ctl *c = Zalloc(sizeof(struct ctl)); if (c == NULL) { - ERR("!Zalloc"); + ERR_W_ERRNO("Zalloc"); return NULL; } @@ -558,7 +559,7 @@ ctl_arg_integer(const void *arg, void *dest, size_t dest_size) *(uint8_t *)dest = (uint8_t)val; break; default: - ERR("invalid destination size %zu", dest_size); + ERR_WO_ERRNO("invalid destination size %zu", dest_size); errno = EINVAL; return -1; } diff --git a/src/common/file.c b/src/common/file.c index c378a6f6845..b77c49c9bd2 100644 --- a/src/common/file.c +++ b/src/common/file.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2014-2023, Intel Corporation */ +/* Copyright 2014-2024, Intel Corporation */ /* * file.c -- file utilities @@ -37,7 +37,7 @@ util_file_exists(const char *path) return 1; if (errno != ENOENT) { - ERR("!os_access \"%s\"", path); + ERR_W_ERRNO("os_access \"%s\"", path); return -1; } @@ -91,7 +91,7 @@ util_fd_get_type(int fd) os_stat_t st; if (os_fstat(fd, &st) < 0) { - ERR("!fstat"); + ERR_W_ERRNO("fstat"); return OTHER_ERROR; } @@ -108,7 +108,7 @@ util_file_get_type(const char *path) LOG(3, "path \"%s\"", path); if (path == NULL) { - ERR("invalid (NULL) path"); + ERR_WO_ERRNO("invalid (NULL) path"); errno = EINVAL; return OTHER_ERROR; } @@ -123,7 +123,7 @@ util_file_get_type(const char *path) os_stat_t st; if (os_stat(path, &st) < 0) { - ERR("!stat"); + ERR_W_ERRNO("stat"); return OTHER_ERROR; } @@ -140,7 +140,7 @@ util_file_get_size(const char *path) int fd = os_open(path, O_RDONLY); if (fd < 0) { - ERR("!open"); + ERR_W_ERRNO("open"); return -1; } @@ -179,7 +179,7 @@ util_fd_get_size(int fd) /* size is unsigned, this function returns signed */ if (size >= INT64_MAX) { errno = ERANGE; - ERR( + ERR_WO_ERRNO( "file size (%ld) too big to be represented in 64-bit signed integer", size); return -1; @@ -203,19 +203,19 @@ util_file_map_whole(const char *path) int flags = O_RDWR; if ((fd = os_open(path, flags)) < 0) { - ERR("!open \"%s\"", path); + ERR_W_ERRNO("open \"%s\"", path); return NULL; } ssize_t size = util_fd_get_size(fd); if (size < 0) { - LOG(2, "cannot determine file length \"%s\"", path); + CORE_LOG_ERROR("cannot determine file length \"%s\"", path); goto out; } addr = util_map(fd, 0, (size_t)size, MAP_SHARED, 0, 0, NULL); if (addr == NULL) { - LOG(2, "failed to map entire file \"%s\"", path); + CORE_LOG_ERROR("failed to map entire file \"%s\"", path); goto out; } @@ -241,33 +241,35 @@ util_file_zero(const char *path, os_off_t off, size_t len) int flags = O_RDWR; if ((fd = os_open(path, flags)) < 0) { - ERR("!open \"%s\"", path); + ERR_W_ERRNO("open \"%s\"", path); return -1; } ssize_t size = util_fd_get_size(fd); if (size < 0) { - LOG(2, "cannot determine file length \"%s\"", path); + CORE_LOG_ERROR("cannot determine file length \"%s\"", path); ret = -1; goto out; } if (off > size) { - LOG(2, "offset beyond file length, %ju > %ju", off, size); + CORE_LOG_ERROR("offset beyond file length, %ju > %ju", off, + size); ret = -1; goto out; } if ((size_t)off + len > (size_t)size) { - LOG(2, "requested size of write goes beyond the file length, " - "%zu > %zu", (size_t)off + len, size); + CORE_LOG_WARNING( + "requested size of write goes beyond the file length, %zu > %zu", + (size_t)off + len, size); LOG(4, "adjusting len to %zu", size - off); len = (size_t)(size - off); } void *addr = util_map(fd, 0, (size_t)size, MAP_SHARED, 0, 0, NULL); if (addr == NULL) { - LOG(2, "failed to map entire file \"%s\"", path); + CORE_LOG_ERROR("failed to map entire file \"%s\"", path); ret = -1; goto out; } @@ -302,7 +304,7 @@ util_file_pwrite(const char *path, const void *buffer, size_t size, if (type == TYPE_NORMAL) { int fd = util_file_open(path, NULL, 0, O_RDWR); if (fd < 0) { - LOG(2, "failed to open file \"%s\"", path); + CORE_LOG_ERROR("failed to open file \"%s\"", path); return -1; } @@ -315,21 +317,22 @@ util_file_pwrite(const char *path, const void *buffer, size_t size, ssize_t file_size = util_file_get_size(path); if (file_size < 0) { - LOG(2, "cannot determine file length \"%s\"", path); + CORE_LOG_ERROR("cannot determine file length \"%s\"", path); return -1; } size_t max_size = (size_t)(file_size - offset); if (size > max_size) { - LOG(2, "requested size of write goes beyond the file length, " - "%zu > %zu", size, max_size); + CORE_LOG_WARNING( + "requested size of write goes beyond the file length, %zu > %zu", + size, max_size); LOG(4, "adjusting size to %zu", max_size); size = max_size; } void *addr = util_file_map_whole(path); if (addr == NULL) { - LOG(2, "failed to map entire file \"%s\"", path); + CORE_LOG_ERROR("failed to map entire file \"%s\"", path); return -1; } @@ -355,7 +358,7 @@ util_file_pread(const char *path, void *buffer, size_t size, if (type == TYPE_NORMAL) { int fd = util_file_open(path, NULL, 0, O_RDONLY); if (fd < 0) { - LOG(2, "failed to open file \"%s\"", path); + CORE_LOG_ERROR("failed to open file \"%s\"", path); return -1; } @@ -368,21 +371,22 @@ util_file_pread(const char *path, void *buffer, size_t size, ssize_t file_size = util_file_get_size(path); if (file_size < 0) { - LOG(2, "cannot determine file length \"%s\"", path); + CORE_LOG_ERROR("cannot determine file length \"%s\"", path); return -1; } size_t max_size = (size_t)(file_size - offset); if (size > max_size) { - LOG(2, "requested size of read goes beyond the file length, " - "%zu > %zu", size, max_size); + CORE_LOG_WARNING( + "requested size of read goes beyond the file length, %zu > %zu", + size, max_size); LOG(4, "adjusting size to %zu", max_size); size = max_size; } void *addr = util_file_map_whole(path); if (addr == NULL) { - LOG(2, "failed to map entire file \"%s\"", path); + CORE_LOG_ERROR("failed to map entire file \"%s\"", path); return -1; } @@ -402,13 +406,13 @@ util_file_create(const char *path, size_t size, size_t minsize) ASSERTne(size, 0); if (size < minsize) { - ERR("size %zu smaller than %zu", size, minsize); + ERR_WO_ERRNO("size %zu smaller than %zu", size, minsize); errno = EINVAL; return -1; } if (((os_off_t)size) < 0) { - ERR("invalid size (%zu) for os_off_t", size); + ERR_WO_ERRNO("invalid size (%zu) for os_off_t", size); errno = EFBIG; return -1; } @@ -423,17 +427,17 @@ util_file_create(const char *path, size_t size, size_t minsize) * initialization completes. */ if ((fd = os_open(path, flags, mode)) < 0) { - ERR("!open \"%s\"", path); + ERR_W_ERRNO("open \"%s\"", path); return -1; } if ((errno = os_posix_fallocate(fd, 0, (os_off_t)size)) != 0) { - ERR("!posix_fallocate \"%s\", %zu", path, size); + ERR_W_ERRNO("posix_fallocate \"%s\", %zu", path, size); goto err; } if (os_flock(fd, OS_LOCK_EX | OS_LOCK_NB) < 0) { - ERR("!flock \"%s\"", path); + ERR_W_ERRNO("flock \"%s\"", path); goto err; } @@ -462,12 +466,12 @@ util_file_open(const char *path, size_t *size, size_t minsize, int flags) int fd; if ((fd = os_open(path, flags)) < 0) { - ERR("!open \"%s\"", path); + ERR_W_ERRNO("open \"%s\"", path); return -1; } if (os_flock(fd, OS_LOCK_EX | OS_LOCK_NB) < 0) { - ERR("!flock \"%s\"", path); + ERR_W_ERRNO("flock \"%s\"", path); (void) os_close(fd); return -1; } @@ -478,13 +482,13 @@ util_file_open(const char *path, size_t *size, size_t minsize, int flags) ssize_t actual_size = util_fd_get_size(fd); if (actual_size < 0) { - ERR("stat \"%s\": negative size", path); + ERR_WO_ERRNO("stat \"%s\": negative size", path); errno = EINVAL; goto err; } if ((size_t)actual_size < minsize) { - ERR("size %zu smaller than %zu", + ERR_WO_ERRNO("size %zu smaller than %zu", (size_t)actual_size, minsize); errno = EINVAL; goto err; @@ -500,7 +504,7 @@ util_file_open(const char *path, size_t *size, size_t minsize, int flags) err: oerrno = errno; if (os_flock(fd, OS_LOCK_UN)) - ERR("!flock unlock"); + ERR_W_ERRNO("flock unlock"); (void) os_close(fd); errno = oerrno; return -1; @@ -540,7 +544,7 @@ util_unlink_flock(const char *path) int fd = util_file_open(path, NULL, 0, O_RDONLY); if (fd < 0) { - LOG(2, "failed to open file \"%s\"", path); + CORE_LOG_ERROR("failed to open file \"%s\"", path); return -1; } diff --git a/src/common/file_posix.c b/src/common/file_posix.c index 60dbcfe5976..938722130e9 100644 --- a/src/common/file_posix.c +++ b/src/common/file_posix.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2014-2023, Intel Corporation */ +/* Copyright 2014-2024, Intel Corporation */ /* * file_posix.c -- Posix versions of file APIs @@ -112,7 +112,7 @@ device_dax_alignment(const char *path) int fd = os_open(path, O_RDONLY); if (fd == -1) { - LOG(1, "Cannot open file %s", path); + CORE_LOG_ERROR("Cannot open file %s", path); return size; } @@ -155,7 +155,7 @@ util_ddax_region_find(const char *path, unsigned *region_id) int ret; if (os_stat(path, &st) < 0) { - ERR("!stat \"%s\"", path); + ERR_W_ERRNO("stat \"%s\"", path); return -1; } diff --git a/src/common/mmap.c b/src/common/mmap.c index bfb99565f99..48bb01d1233 100644 --- a/src/common/mmap.c +++ b/src/common/mmap.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2014-2023, Intel Corporation */ +/* Copyright 2014-2024, Intel Corporation */ /* * mmap.c -- mmap utilities @@ -51,9 +51,9 @@ util_mmap_init(void) unsigned long long val = strtoull(e, &endp, 16); if (errno || endp == e) { - LOG(2, "Invalid PMEM_MMAP_HINT"); + CORE_LOG_WARNING("Invalid PMEM_MMAP_HINT"); } else if (os_access(OS_MAPFILE, R_OK)) { - LOG(2, "No /proc, PMEM_MMAP_HINT ignored"); + CORE_LOG_WARNING("No /proc, PMEM_MMAP_HINT ignored"); } else { Mmap_hint = (void *)val; Mmap_no_random = 1; @@ -91,7 +91,7 @@ util_map(int fd, os_off_t off, size_t len, int flags, int rdonly, void *base; void *addr = util_map_hint(len, req_align); if (addr == MAP_FAILED) { - LOG(1, "cannot find a contiguous region of given size"); + CORE_LOG_ERROR("cannot find a contiguous region of given size"); return NULL; } @@ -101,7 +101,7 @@ util_map(int fd, os_off_t off, size_t len, int flags, int rdonly, int proto = rdonly ? PROT_READ : PROT_READ|PROT_WRITE; base = util_map_sync(addr, len, proto, flags, fd, off, map_sync); if (base == MAP_FAILED) { - ERR("!mmap %zu bytes", len); + ERR_W_ERRNO("mmap %zu bytes", len); return NULL; } @@ -123,7 +123,7 @@ util_unmap(void *addr, size_t len) int retval = munmap(addr, len); if (retval < 0) - ERR("!munmap"); + ERR_W_ERRNO("munmap"); return retval; } @@ -152,7 +152,7 @@ util_range_ro(void *addr, size_t len) uptr = (uintptr_t)addr & ~(Pagesize - 1); if ((retval = mprotect((void *)uptr, len, PROT_READ)) < 0) - ERR("!mprotect: PROT_READ"); + ERR_W_ERRNO("mprotect: PROT_READ"); return retval; } @@ -181,7 +181,7 @@ util_range_rw(void *addr, size_t len) uptr = (uintptr_t)addr & ~(Pagesize - 1); if ((retval = mprotect((void *)uptr, len, PROT_READ|PROT_WRITE)) < 0) - ERR("!mprotect: PROT_READ|PROT_WRITE"); + ERR_W_ERRNO("mprotect: PROT_READ|PROT_WRITE"); return retval; } @@ -210,7 +210,7 @@ util_range_none(void *addr, size_t len) uptr = (uintptr_t)addr & ~(Pagesize - 1); if ((retval = mprotect((void *)uptr, len, PROT_NONE)) < 0) - ERR("!mprotect: PROT_NONE"); + ERR_W_ERRNO("mprotect: PROT_NONE"); return retval; } @@ -284,7 +284,7 @@ util_range_register(const void *addr, size_t len, const char *path, /* check if not tracked already */ if (util_range_find((uintptr_t)addr, len) != NULL) { - ERR( + ERR_WO_ERRNO( "duplicated persistent memory range; presumably unmapped with munmap() instead of pmem_unmap(): addr %p len %zu", addr, len); errno = ENOMEM; @@ -294,7 +294,7 @@ util_range_register(const void *addr, size_t len, const char *path, struct map_tracker *mt; mt = Malloc(sizeof(struct map_tracker)); if (mt == NULL) { - ERR("!Malloc"); + ERR_W_ERRNO("Malloc"); return -1; } @@ -305,7 +305,7 @@ util_range_register(const void *addr, size_t len, const char *path, unsigned region_id; int ret = util_ddax_region_find(path, ®ion_id); if (ret < 0) { - ERR("Cannot find DAX device region id"); + ERR_WO_ERRNO("Cannot find DAX device region id"); return -1; } mt->region_id = region_id; @@ -333,7 +333,7 @@ util_range_split(struct map_tracker *mt, const void *addrp, const void *endp) uintptr_t end = (uintptr_t)endp; ASSERTne(mt, NULL); if (addr == end || addr % Mmap_align != 0 || end % Mmap_align != 0) { - ERR( + ERR_WO_ERRNO( "invalid munmap length, must be non-zero and page aligned"); return -1; } @@ -357,7 +357,7 @@ util_range_split(struct map_tracker *mt, const void *addrp, const void *endp) /* new mapping at the beginning */ mtb = Malloc(sizeof(struct map_tracker)); if (mtb == NULL) { - ERR("!Malloc"); + ERR_W_ERRNO("Malloc"); goto err; } @@ -372,7 +372,7 @@ util_range_split(struct map_tracker *mt, const void *addrp, const void *endp) /* new mapping at the end */ mte = Malloc(sizeof(struct map_tracker)); if (mte == NULL) { - ERR("!Malloc"); + ERR_W_ERRNO("Malloc"); goto err; } diff --git a/src/common/mmap_posix.c b/src/common/mmap_posix.c index 29d45a19e41..00a46ec7e33 100644 --- a/src/common/mmap_posix.c +++ b/src/common/mmap_posix.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2014-2023, Intel Corporation */ +/* Copyright 2014-2024, Intel Corporation */ /* * mmap_posix.c -- memory-mapped files for Posix @@ -9,7 +9,7 @@ #include #include #include "mmap.h" -#include "out.h" +#include "core_assert.h" #include "os.h" #define PROCMAXLEN 2048 /* maximum expected line length in /proc files */ @@ -40,7 +40,7 @@ util_map_hint_unused(void *minaddr, size_t len, size_t align) FILE *fp; if ((fp = os_fopen(Mmap_mapfile, "r")) == NULL) { - ERR("!%s", Mmap_mapfile); + ERR_W_ERRNO("%s", Mmap_mapfile); return MAP_FAILED; } @@ -87,7 +87,7 @@ util_map_hint_unused(void *minaddr, size_t len, size_t align) * space, but is not large enough. (very unlikely) */ if ((raddr != NULL) && (UINTPTR_MAX - (uintptr_t)raddr < len)) { - ERR("end of address space reached"); + ERR_WO_ERRNO("end of address space reached"); raddr = MAP_FAILED; } @@ -138,7 +138,7 @@ util_map_hint(size_t len, size_t req_align) char *addr = mmap(NULL, len + align, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); if (addr == MAP_FAILED) { - ERR("!mmap MAP_ANONYMOUS"); + ERR_W_ERRNO("mmap MAP_ANONYMOUS"); } else { LOG(4, "system choice %p", addr); hint_addr = (char *)roundup((uintptr_t)addr, align); diff --git a/src/common/os_deep_linux.c b/src/common/os_deep_linux.c index eec0a3a5ce1..c9185c24467 100644 --- a/src/common/os_deep_linux.c +++ b/src/common/os_deep_linux.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2017-2023, Intel Corporation */ +/* Copyright 2017-2024, Intel Corporation */ /* * os_deep_linux.c -- Linux abstraction layer @@ -35,11 +35,13 @@ os_deep_type(const struct map_tracker *mt, void *addr, size_t len) if (ret < 0) { if (ret == PMEM2_E_NOSUPP) { errno = ENOTSUP; - LOG(1, "!deep_flush not supported"); + CORE_LOG_ERROR_W_ERRNO( + "deep_flush not supported"); } else { errno = pmem2_err_to_errno(ret); - LOG(2, "cannot write to deep_flush" - "in region %u", mt->region_id); + CORE_LOG_ERROR( + "cannot write to deep_flush in region %u", + mt->region_id); } return -1; } @@ -122,7 +124,7 @@ os_part_deep_common(struct pool_replica *rep, unsigned partidx, void *addr, return 0; if (pmem_msync(addr, len)) { - LOG(1, "pmem_msync(%p, %lu)", addr, len); + CORE_LOG_ERROR("pmem_msync(%p, %lu)", addr, len); return -1; } return 0; @@ -151,16 +153,17 @@ os_part_deep_common(struct pool_replica *rep, unsigned partidx, void *addr, if (ret < 0) { if (errno == ENOENT) { errno = ENOTSUP; - LOG(1, "!deep_flush not supported"); + CORE_LOG_ERROR_W_ERRNO( + "deep_flush not supported"); } else { - LOG(1, "invalid dax_region id %u", region_id); + CORE_LOG_ERROR("invalid dax_region id %u", + region_id); } return -1; } if (pmem2_deep_flush_write(region_id)) { - LOG(1, "pmem2_deep_flush_write(%u)", - region_id); + CORE_LOG_ERROR("pmem2_deep_flush_write(%u)", region_id); return -1; } } else { @@ -169,7 +172,7 @@ os_part_deep_common(struct pool_replica *rep, unsigned partidx, void *addr, * call msync on one page. */ if (pmem_msync(addr, MIN(Pagesize, len))) { - LOG(1, "pmem_msync(%p, %lu)", addr, len); + CORE_LOG_ERROR("pmem_msync(%p, %lu)", addr, len); return -1; } } diff --git a/src/common/pool_hdr.c b/src/common/pool_hdr.c index 13486a09b34..47e754eccd8 100644 --- a/src/common/pool_hdr.c +++ b/src/common/pool_hdr.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2014-2021, Intel Corporation */ +/* Copyright 2014-2024, Intel Corporation */ /* * pool_hdr.c -- pool header utilities @@ -11,6 +11,7 @@ #include #include "out.h" +#include "log_internal.h" #include "pool_hdr.h" /* Determine ISA for which PMDK is currently compiled */ @@ -112,27 +113,27 @@ util_check_arch_flags(const struct arch_flags *arch_flags) if (!util_is_zeroed(&arch_flags->reserved, sizeof(arch_flags->reserved))) { - ERR("invalid reserved values"); + ERR_WO_ERRNO("invalid reserved values"); ret = -1; } if (arch_flags->machine != cur_af.machine) { - ERR("invalid machine value"); + ERR_WO_ERRNO("invalid machine value"); ret = -1; } if (arch_flags->data != cur_af.data) { - ERR("invalid data value"); + ERR_WO_ERRNO("invalid data value"); ret = -1; } if (arch_flags->machine_class != cur_af.machine_class) { - ERR("invalid machine_class value"); + ERR_WO_ERRNO("invalid machine_class value"); ret = -1; } if (arch_flags->alignment_desc != cur_af.alignment_desc) { - ERR("invalid alignment_desc value"); + ERR_WO_ERRNO("invalid alignment_desc value"); ret = -1; } @@ -169,16 +170,18 @@ util_feature_check(struct pool_hdr *hdrp, features_t known) /* check incompatible ("must support") features */ if (unknown.incompat) { - ERR("unsafe to continue due to unknown incompat "\ - "features: %#x", unknown.incompat); + ERR_WO_ERRNO( + "unsafe to continue due to unknown incompat features: %#x", + unknown.incompat); errno = EINVAL; return -1; } /* check RO-compatible features (force RO if unsupported) */ if (unknown.ro_compat) { - ERR("switching to read-only mode due to unknown ro_compat "\ - "features: %#x", unknown.ro_compat); + ERR_WO_ERRNO( + "switching to read-only mode due to unknown ro_compat features: %#x", + unknown.ro_compat); return 0; } diff --git a/src/common/set.c b/src/common/set.c index 1cd908eb14c..f82e9fd5141 100644 --- a/src/common/set.c +++ b/src/common/set.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2015-2023, Intel Corporation */ +/* Copyright 2015-2024, Intel Corporation */ /* * Copyright (c) 2016, Microsoft Corporation. All rights reserved. * @@ -180,7 +180,8 @@ util_map_hdr(struct pool_set_part *part, int flags, int rdonly) /* this is required only for Device DAX & memcheck */ addr = util_map_hint(hdrsize, hdrsize); if (addr == MAP_FAILED) { - LOG(1, "cannot find a contiguous region of given size"); + CORE_LOG_ERROR( + "cannot find a contiguous region of given size"); /* there's nothing we can do */ return -1; } @@ -191,7 +192,7 @@ util_map_hdr(struct pool_set_part *part, int flags, int rdonly) void *hdrp = util_map_sync(addr, hdrsize, prot, flags, part->fd, 0, &part->hdr_map_sync); if (hdrp == MAP_FAILED) { - ERR("!mmap: %s", part->path); + ERR_W_ERRNO("mmap: %s", part->path); return -1; } @@ -217,7 +218,7 @@ util_unmap_hdr(struct pool_set_part *part) VALGRIND_REMOVE_PMEM_MAPPING(part->hdr, part->hdrsize); if (munmap(part->hdr, part->hdrsize) != 0) /* this means there's a bug on the caller side */ - FATAL("!munmap: %s", part->path); + CORE_LOG_FATAL_W_ERRNO("munmap: %s", part->path); part->hdr = NULL; part->hdrsize = 0; } @@ -248,12 +249,12 @@ util_map_part(struct pool_set_part *part, void *addr, size_t size, void *addrp = util_map_sync(addr, size, prot, flags, part->fd, (os_off_t)offset, &part->map_sync); if (addrp == MAP_FAILED) { - ERR("!mmap: %s", part->path); + ERR_W_ERRNO("mmap: %s", part->path); return -1; } if (addr != NULL && (flags & MAP_FIXED) && addrp != addr) { - ERR("unable to map at requested address %p", addr); + ERR_WO_ERRNO("unable to map at requested address %p", addr); munmap(addrp, size); return -1; } @@ -279,7 +280,7 @@ util_unmap_part(struct pool_set_part *part) LOG(4, "munmap: addr %p size %zu", part->addr, part->size); VALGRIND_REMOVE_PMEM_MAPPING(part->addr, part->size); if (munmap(part->addr, part->size) != 0) { - ERR("!munmap: %s", part->path); + ERR_W_ERRNO("munmap: %s", part->path); } part->addr = NULL; @@ -339,7 +340,7 @@ util_poolset_open(struct pool_set *set) { for (unsigned r = 0; r < set->nreplicas; ++r) { if (util_replica_open(set, r, MAP_SHARED)) { - LOG(2, "replica open failed: replica %u", r); + CORE_LOG_ERROR("replica open failed: replica %u", r); errno = EINVAL; return -1; } @@ -365,7 +366,8 @@ util_replica_close_local(struct pool_replica *rep, unsigned repn, LOG(4, "unlink %s", rep->part[p].path); int olderrno = errno; if (util_unlink(rep->part[p].path) && errno != ENOENT) { - ERR("!unlink %s failed (part %u, replica %u)", + ERR_W_ERRNO( + "unlink %s failed (part %u, replica %u)", rep->part[p].path, p, repn); return -1; } @@ -417,19 +419,20 @@ util_poolset_chmod(struct pool_set *set, mode_t mode) os_stat_t stbuf; if (os_fstat(part->fd, &stbuf) != 0) { - ERR("!fstat %d %s", part->fd, part->path); + ERR_W_ERRNO("fstat %d %s", part->fd, + part->path); return -1; } if (stbuf.st_mode & ~(unsigned)S_IFMT) { - LOG(1, "file permissions changed during pool " - "initialization, file: %s (%o)", + CORE_LOG_WARNING( + "file permissions changed during pool initialization, file: %s (%o)", part->path, stbuf.st_mode & ~(unsigned)S_IFMT); } if (os_chmod(part->path, mode)) { - ERR("!chmod %u/%u/%s", r, p, part->path); + ERR_W_ERRNO("chmod %u/%u/%s", r, p, part->path); return -1; } } @@ -470,7 +473,8 @@ util_autodetect_size(const char *path) return -1; if (type == TYPE_NORMAL) { - ERR("size autodetection is supported only for device dax"); + ERR_WO_ERRNO( + "size autodetection is supported only for device dax"); return -1; } @@ -511,7 +515,7 @@ parser_read_line(char *line, size_t *size, char **path) *path = Strdup(path_str); if (!(*path)) { - ERR("!Strdup"); + ERR_W_ERRNO("Strdup"); return PARSER_OUT_OF_MEMORY; } @@ -615,7 +619,7 @@ parser_read_replica(char *line, char **node_addr, char **pool_desc) *pool_desc = Strdup(desc_str); if (!(*node_addr) || !(*pool_desc)) { - ERR("!Strdup"); + ERR_W_ERRNO("Strdup"); if (*node_addr) Free(*node_addr); if (*pool_desc) @@ -641,7 +645,7 @@ util_replica_reserve(struct pool_replica **repp, unsigned n) rep = Realloc(rep, sizeof(struct pool_replica) + (n) * sizeof(struct pool_set_part)); if (rep == NULL) { - ERR("!Realloc"); + ERR_W_ERRNO("Realloc"); return -1; } @@ -725,7 +729,7 @@ util_parse_add_part(struct pool_set *set, const char *path, size_t filesize) ASSERTne(set, NULL); if (set->directory_based) { - ERR("cannot mix directories and files in a set"); + ERR_WO_ERRNO("cannot mix directories and files in a set"); errno = EINVAL; return -1; } @@ -751,7 +755,8 @@ util_parse_add_directory(struct pool_set *set, const char *path, if (set->directory_based == 0) { if (rep->nparts > 0 || set->nreplicas > 1) { - ERR("cannot mix directories and files in a set"); + ERR_WO_ERRNO( + "cannot mix directories and files in a set"); errno = EINVAL; return -1; } @@ -760,7 +765,7 @@ util_parse_add_directory(struct pool_set *set, const char *path, char *rpath = util_part_realpath(path); if (rpath == NULL) { - ERR("cannot resolve realpath of new directory"); + ERR_WO_ERRNO("cannot resolve realpath of new directory"); return -1; } @@ -772,7 +777,8 @@ util_parse_add_directory(struct pool_set *set, const char *path, dpath = util_part_realpath(dir->path); ASSERTne(dpath, NULL); /* must have been resolved */ if (strcmp(rpath, dpath) == 0) { - ERR("cannot use the same directory twice"); + ERR_WO_ERRNO( + "cannot use the same directory twice"); errno = EEXIST; free(dpath); free(rpath); @@ -832,7 +838,7 @@ util_parse_add_replica(struct pool_set **setp) set = Realloc(set, sizeof(struct pool_set) + (set->nreplicas + 1) * sizeof(struct pool_replica *)); if (set == NULL) { - ERR("!Realloc"); + ERR_W_ERRNO("Realloc"); return -1; } *setp = set; @@ -840,7 +846,7 @@ util_parse_add_replica(struct pool_set **setp) struct pool_replica *rep; rep = Zalloc(sizeof(struct pool_replica)); if (rep == NULL) { - ERR("!Zalloc"); + ERR_W_ERRNO("Zalloc"); return -1; } @@ -868,7 +874,8 @@ util_replica_check_map_sync(struct pool_set *set, unsigned repidx, for (unsigned p = 1; p < rep->nparts; p++) { if (map_sync != rep->part[p].map_sync) { - ERR("replica #%u part %u %smapped with MAP_SYNC", + ERR_WO_ERRNO( + "replica #%u part %u %smapped with MAP_SYNC", repidx, p, rep->part[p].map_sync ? "" : "not"); return -1; } @@ -877,9 +884,9 @@ util_replica_check_map_sync(struct pool_set *set, unsigned repidx, if (check_hdr) { for (unsigned p = 0; p < rep->nhdrs; p++) { if (map_sync != rep->part[p].hdr_map_sync) { - ERR("replica #%u part %u header %smapped " - "with MAP_SYNC", repidx, p, - rep->part[p].hdr_map_sync ? + ERR_WO_ERRNO( + "replica #%u part %u header %smapped with MAP_SYNC", + repidx, p, rep->part[p].hdr_map_sync ? "" : "not"); return -1; } @@ -906,7 +913,7 @@ util_poolset_check_devdax(struct pool_set *set) for (unsigned p = 0; p < rep->nparts; p++) { if (rep->part[p].is_dev_dax != is_dev_dax) { - ERR( + ERR_WO_ERRNO( "either all the parts must be Device DAX or none"); return -1; } @@ -916,7 +923,7 @@ util_poolset_check_devdax(struct pool_set *set) OPTION_NOHDRS)) == 0 && util_file_device_dax_alignment(rep->part[p].path) != Pagesize) { - ERR( + ERR_WO_ERRNO( "Multiple DAX devices with alignment other than 4KB. Use the SINGLEHDR poolset option."); return -1; } @@ -935,8 +942,8 @@ util_poolset_check_options(struct pool_set *set) LOG(3, "set %p", set); if ((set->options & OPTION_SINGLEHDR) && (set->options & OPTION_NOHDRS)) { - ERR( - "both SINGLEHDR and NOHDR poolset options used at the same time"); + ERR_WO_ERRNO( + "both SINGLEHDR and NOHDR poolset options used at the same time"); return -1; } return 0; @@ -1017,7 +1024,7 @@ util_poolset_directory_load(struct pool_replica **repp, const char *directory) struct fs *f = fs_new(directory); if (f == NULL) { - ERR("!fs_new: \"%s\"", directory); + ERR_W_ERRNO("fs_new: \"%s\"", directory); return -1; } @@ -1043,20 +1050,20 @@ util_poolset_directory_load(struct pool_replica **repp, const char *directory) ssize_t size = util_file_get_size(entry->path); if (size < 0) { - LOG(2, - "cannot read size of file (%s) in a poolset directory", - entry->path); + CORE_LOG_ERROR( + "cannot read size of file (%s) in a poolset directory", + entry->path); goto err; } if ((path = Strdup(entry->path)) == NULL) { - ERR("!Strdup"); + ERR_W_ERRNO("Strdup"); goto err; } if (util_replica_add_part_by_idx(repp, path, (size_t)size, (unsigned)part_idx) != 0) { - ERR("unable to load part %s", entry->path); + ERR_WO_ERRNO("unable to load part %s", entry->path); goto err; } nparts++; @@ -1095,7 +1102,8 @@ util_poolset_directories_load(struct pool_set *set) nparts = util_poolset_directory_load(&set->replica[r], d->path); if (nparts < 0) { - ERR("failed to load parts from directory %s", + ERR_WO_ERRNO( + "failed to load parts from directory %s", d->path); return -1; } @@ -1128,7 +1136,7 @@ util_poolset_directories_load(struct pool_set *set) if (VEC_SIZE(&set->replica[r]->directory) == 0) { errno = ENOENT; - ERR("!no directories in replica"); + ERR_W_ERRNO("no directories in replica"); return -1; } @@ -1145,7 +1153,7 @@ util_poolset_directories_load(struct pool_set *set) size_t path_len = strlen(d->path) + PMEM_FILE_MAX_LEN; if ((p->path = Malloc(path_len)) == NULL) { - ERR("!Malloc"); + ERR_W_ERRNO("Malloc"); return -1; } @@ -1185,19 +1193,19 @@ util_poolset_parse(struct pool_set **setp, const char *path, int fd) int oerrno; if (os_lseek(fd, 0, SEEK_SET) != 0) { - ERR("!lseek %d", fd); + ERR_W_ERRNO("lseek %d", fd); return -1; } fd = dup(fd); if (fd < 0) { - ERR("!dup"); + ERR_W_ERRNO("dup"); return -1; } /* associate a stream with the file descriptor */ if ((fs = os_fdopen(fd, "r")) == NULL) { - ERR("!fdopen %d", fd); + ERR_W_ERRNO("fdopen %d", fd); os_close(fd); return -1; } @@ -1208,20 +1216,20 @@ util_poolset_parse(struct pool_set **setp, const char *path, int fd) /* read the first line */ line = util_readline(fs); if (line == NULL) { - ERR("!Reading poolset file"); + ERR_W_ERRNO("Reading poolset file"); goto err; } nlines++; set = Zalloc(sizeof(struct pool_set)); if (set == NULL) { - ERR("!Malloc for pool set"); + ERR_W_ERRNO("Malloc for pool set"); goto err; } set->path = Strdup(path); if (set->path == NULL) { - ERR("!Strdup"); + ERR_W_ERRNO("Strdup"); goto err; } @@ -1291,9 +1299,8 @@ util_poolset_parse(struct pool_set **setp, const char *path, int fd) &node_addr, &pool_desc); if (result == PARSER_CONTINUE) { /* remote REPLICA */ - ERR( - "Remote replicas are no longer supported. " - "This functionality is deprecated."); + ERR_WO_ERRNO( + "Remote replicas are no longer supported. This functionality is deprecated."); goto err; } } else if (nparts >= 1) { @@ -1329,7 +1336,7 @@ util_poolset_parse(struct pool_set **setp, const char *path, int fd) } if (result != PARSER_FORMAT_OK) { - ERR("%s [%s:%d]", path, parser_errstr[result], nlines); + ERR_WO_ERRNO("%s [%s:%d]", path, parser_errstr[result], nlines); switch (result) { case PARSER_CANNOT_READ_SIZE: case PARSER_OUT_OF_MEMORY: @@ -1347,7 +1354,7 @@ util_poolset_parse(struct pool_set **setp, const char *path, int fd) } if (util_poolset_directories_load(set) != 0) { - ERR("cannot load part files from directories"); + ERR_WO_ERRNO("cannot load part files from directories"); goto err; } @@ -1394,13 +1401,13 @@ util_poolset_single(const char *path, size_t filesize, int create, set = Zalloc(sizeof(struct pool_set) + sizeof(struct pool_replica *)); if (set == NULL) { - ERR("!Malloc for pool set"); + ERR_W_ERRNO("Malloc for pool set"); return NULL; } set->path = Strdup(path); if (set->path == NULL) { - ERR("!Strdup"); + ERR_W_ERRNO("Strdup"); Free(set); return NULL; } @@ -1409,7 +1416,7 @@ util_poolset_single(const char *path, size_t filesize, int create, rep = Zalloc(sizeof(struct pool_replica) + sizeof(struct pool_set_part)); if (rep == NULL) { - ERR("!Malloc for pool set replica"); + ERR_W_ERRNO("Malloc for pool set replica"); Free(set->path); Free(set); return NULL; @@ -1474,7 +1481,8 @@ util_part_open(struct pool_set_part *part, size_t minsize, int create_part) part->fd = util_file_create(part->path, part->filesize, minsize); if (part->fd == -1) { - LOG(2, "failed to create file: %s", part->path); + CORE_LOG_ERROR("failed to create file: %s", + part->path); return -1; } part->created = 1; @@ -1483,7 +1491,7 @@ util_part_open(struct pool_set_part *part, size_t minsize, int create_part) int flags = O_RDWR; part->fd = util_file_open(part->path, &size, minsize, flags); if (part->fd == -1) { - LOG(2, "failed to open file: %s", part->path); + CORE_LOG_ERROR("failed to open file: %s", part->path); return -1; } @@ -1492,15 +1500,16 @@ util_part_open(struct pool_set_part *part, size_t minsize, int create_part) (os_off_t)size); if (ret != 0) { errno = ret; - ERR("!posix_fallocate \"%s\", %zu", part->path, - size); + ERR_W_ERRNO("posix_fallocate \"%s\", %zu", + part->path, size); return -1; } } /* check if filesize matches */ if (part->filesize != size) { - ERR("file size does not match config: %s, %zu != %zu", + ERR_WO_ERRNO( + "file size does not match config: %s, %zu != %zu", part->path, size, part->filesize); errno = EINVAL; return -1; @@ -1561,7 +1570,7 @@ util_poolset_read(struct pool_set **setp, const char *path) int fd; if ((fd = os_open(path, O_RDONLY)) < 0) { - ERR("!open: path \"%s\"", path); + ERR_W_ERRNO("open: path \"%s\"", path); return -1; } @@ -1597,7 +1606,7 @@ util_poolset_create_set(struct pool_set **setp, const char *path, if (poolsize != 0) { if (type == TYPE_DEVDAX) { - ERR("size must be zero for device dax"); + ERR_WO_ERRNO("size must be zero for device dax"); return -1; } *setp = util_poolset_single(path, poolsize, 1, ignore_sds); @@ -1620,7 +1629,7 @@ util_poolset_create_set(struct pool_set **setp, const char *path, */ ret = (int)read(fd, signature, POOLSET_HDR_SIG_LEN); if (ret < 0) { - ERR("!read %d", fd); + ERR_W_ERRNO("read %d", fd); goto err; } } @@ -1631,8 +1640,9 @@ util_poolset_create_set(struct pool_set **setp, const char *path, (void) os_close(fd); if (size < minsize) { - ERR("file is not a poolset file and its size (%zu)" - " is smaller than %zu", size, minsize); + ERR_WO_ERRNO( + "file is not a poolset file and its size (%zu) is smaller than %zu", + size, minsize); errno = EINVAL; return -1; } @@ -1667,7 +1677,7 @@ util_poolset_check_header_options(struct pool_set *set, uint32_t incompat) if (((set->options & OPTION_SINGLEHDR) == 0) != ((incompat & POOL_FEAT_SINGLEHDR) == 0)) { - ERR( + ERR_WO_ERRNO( "poolset file options (%u) do not match incompat feature flags (%#x)", set->options, incompat); errno = EINVAL; @@ -1695,7 +1705,7 @@ util_header_create(struct pool_set *set, unsigned repidx, unsigned partidx, /* check if the pool header is all zeros */ if (!util_is_zeroed(hdrp, sizeof(*hdrp)) && !overwrite) { - ERR("Non-empty file detected"); + ERR_WO_ERRNO("Non-empty file detected"); errno = EEXIST; return -1; } @@ -1743,7 +1753,7 @@ util_header_create(struct pool_set *set, unsigned repidx, unsigned partidx, os_stat_t stbuf; if (os_fstat(rep->part[partidx].fd, &stbuf) != 0) { - ERR("!fstat"); + ERR_W_ERRNO("fstat"); return -1; } ASSERT(stbuf.st_ctime); @@ -1803,24 +1813,24 @@ util_header_check(struct pool_set *set, unsigned repidx, unsigned partidx, /* to be valid, a header must have a major version of at least 1 */ if (hdr.major == 0) { - ERR("invalid major version (0)"); + ERR_WO_ERRNO("invalid major version (0)"); errno = EINVAL; return -1; } /* check signature */ if (memcmp(hdr.signature, attr->signature, POOL_HDR_SIG_LEN)) { - ERR("wrong pool type: \"%.8s\"", hdr.signature); + ERR_WO_ERRNO("wrong pool type: \"%.8s\"", hdr.signature); errno = EINVAL; return -1; } /* check format version number */ if (hdr.major != attr->major) { - ERR("pool version %d (library expects %d)", hdr.major, + ERR_WO_ERRNO("pool version %d (library expects %d)", hdr.major, attr->major); if (hdr.major < attr->major) - ERR( + ERR_WO_ERRNO( "Please run the pmdk-convert utility to upgrade the pool."); errno = EINVAL; return -1; @@ -1845,7 +1855,7 @@ util_header_check(struct pool_set *set, unsigned repidx, unsigned partidx, */ if (!util_checksum(&hdr, sizeof(hdr), &hdr.checksum, 0, POOL_HDR_CSUM_END_OFF(&hdr))) { - ERR("invalid checksum of pool header"); + ERR_WO_ERRNO("invalid checksum of pool header"); errno = EINVAL; return -1; } @@ -1853,7 +1863,7 @@ util_header_check(struct pool_set *set, unsigned repidx, unsigned partidx, LOG(3, "valid header, signature \"%.8s\"", hdr.signature); if (util_check_arch_flags(&hdr.arch_flags)) { - ERR("wrong architecture flags"); + ERR_WO_ERRNO("wrong architecture flags"); errno = EINVAL; return -1; } @@ -1861,7 +1871,7 @@ util_header_check(struct pool_set *set, unsigned repidx, unsigned partidx, /* check pool set UUID */ if (memcmp(HDR(REP(set, 0), 0)->poolset_uuid, hdr.poolset_uuid, POOL_HDR_UUID_LEN)) { - ERR("wrong pool set UUID"); + ERR_WO_ERRNO("wrong pool set UUID"); errno = EINVAL; return -1; } @@ -1871,14 +1881,14 @@ util_header_check(struct pool_set *set, unsigned repidx, unsigned partidx, POOL_HDR_UUID_LEN) || memcmp(HDRN(rep, partidx)->uuid, hdr.next_part_uuid, POOL_HDR_UUID_LEN)) { - ERR("wrong part UUID"); + ERR_WO_ERRNO("wrong part UUID"); errno = EINVAL; return -1; } /* check format version */ if (HDR(rep, 0)->major != hdrp->major) { - ERR("incompatible pool format"); + ERR_WO_ERRNO("incompatible pool format"); errno = EINVAL; return -1; } @@ -1887,7 +1897,7 @@ util_header_check(struct pool_set *set, unsigned repidx, unsigned partidx, if (HDR(rep, 0)->features.compat != hdrp->features.compat || HDR(rep, 0)->features.incompat != hdrp->features.incompat || HDR(rep, 0)->features.ro_compat != hdrp->features.ro_compat) { - ERR("incompatible feature flags"); + ERR_WO_ERRNO("incompatible feature flags"); errno = EINVAL; return -1; } @@ -1951,14 +1961,16 @@ util_replica_map_local(struct pool_set *set, unsigned repidx, int flags) /* determine a hint address for mmap() */ addr = util_map_hint(rep->resvsize, 0); if (addr == MAP_FAILED) { - LOG(1, "cannot find a contiguous region of given size"); + CORE_LOG_ERROR( + "cannot find a contiguous region of given size"); return -1; } /* map the first part and reserve space for remaining parts */ if (util_map_part(&rep->part[0], addr, rep->resvsize, 0, flags, 0) != 0) { - LOG(2, "pool mapping failed - replica #%u part #0", + CORE_LOG_ERROR( + "pool mapping failed - replica #%u part #0", repidx); return -1; } @@ -1987,8 +1999,9 @@ util_replica_map_local(struct pool_set *set, unsigned repidx, int flags) */ if ((errno == EINVAL) && (remaining_retries > 0)) { - LOG(2, "usable space mapping failed - " - "part #%d - retrying", p); + CORE_LOG_WARNING( + "usable space mapping failed - part #%d - retrying", + p); retry_for_contiguous_addr = 1; remaining_retries--; @@ -2000,7 +2013,8 @@ util_replica_map_local(struct pool_set *set, unsigned repidx, int flags) munmap(addr, rep->resvsize - mapsize); break; } - LOG(2, "usable space mapping failed - part #%d", + CORE_LOG_ERROR( + "usable space mapping failed - part #%d", p); goto err; } @@ -2068,7 +2082,7 @@ util_replica_init_headers_local(struct pool_set *set, unsigned repidx, /* map all headers - don't care about the address */ for (unsigned p = 0; p < rep->nhdrs; p++) { if (util_map_hdr(&rep->part[p], flags, 0) != 0) { - LOG(2, "header mapping failed - part #%d", p); + CORE_LOG_ERROR("header mapping failed - part #%d", p); goto err; } } @@ -2076,7 +2090,8 @@ util_replica_init_headers_local(struct pool_set *set, unsigned repidx, /* create headers, set UUID's */ for (unsigned p = 0; p < rep->nhdrs; p++) { if (util_header_create(set, repidx, p, attr, 0) != 0) { - LOG(2, "header creation failed - part #%d", p); + CORE_LOG_ERROR("header creation failed - part #%d", + p); goto err; } } @@ -2112,7 +2127,7 @@ util_replica_create_local(struct pool_set *set, unsigned repidx, int flags, */ if (PART(REP(set, repidx), 0)->addr == NULL) { if (util_replica_map_local(set, repidx, flags) != 0) { - LOG(2, "replica #%u map failed", repidx); + CORE_LOG_ERROR("replica #%u map failed", repidx); return -1; } } @@ -2121,7 +2136,8 @@ util_replica_create_local(struct pool_set *set, unsigned repidx, int flags, return 0; if (util_replica_init_headers_local(set, repidx, flags, attr) != 0) { - LOG(2, "replica #%u headers initialization failed", repidx); + CORE_LOG_ERROR("replica #%u headers initialization failed", + repidx); return -1; } return 0; @@ -2193,7 +2209,7 @@ util_poolset_append_new_part(struct pool_set *set, size_t size) path_len = strlen(d->path) + PMEM_FILE_MAX_LEN; if ((path = Malloc(path_len)) == NULL) { - ERR("!Malloc"); + ERR_W_ERRNO("Malloc"); goto err_part_init; } @@ -2201,7 +2217,8 @@ util_poolset_append_new_part(struct pool_set *set, size_t size) d->path, PMEM_FILE_PADDING, set->next_id, PMEM_EXT); if (util_replica_add_part(&set->replica[r], path, size) != 0) - FATAL("cannot add a new part to the replica info"); + CORE_LOG_FATAL( + "cannot add a new part to the replica info"); } set->next_directory_id += 1; @@ -2233,20 +2250,20 @@ util_pool_extend(struct pool_set *set, size_t *size, size_t minpartsize) LOG(3, "set %p size %zu minpartsize %zu", set, *size, minpartsize); if (*size == 0) { - ERR("cannot extend pool by 0 bytes"); + ERR_WO_ERRNO("cannot extend pool by 0 bytes"); return NULL; } if ((set->options & OPTION_SINGLEHDR) == 0) { - ERR( - "extending the pool by appending parts with headers is not supported!"); + ERR_WO_ERRNO( + "extending the pool by appending parts with headers is not supported!"); return NULL; } if (set->poolsize + *size > set->resvsize) { *size = set->resvsize - set->poolsize; if (*size < minpartsize) { - ERR("exceeded reservation size"); + ERR_WO_ERRNO("exceeded reservation size"); return NULL; } LOG(4, "extend size adjusted to not exceed reservation size"); @@ -2255,7 +2272,7 @@ util_pool_extend(struct pool_set *set, size_t *size, size_t minpartsize) size_t old_poolsize = set->poolsize; if (util_poolset_append_new_part(set, *size) != 0) { - ERR("unable to append a new part to the pool"); + ERR_WO_ERRNO("unable to append a new part to the pool"); return NULL; } @@ -2270,7 +2287,7 @@ util_pool_extend(struct pool_set *set, size_t *size, size_t minpartsize) struct pool_set_part *p = &rep->part[pidx]; if (util_part_open(p, 0, 1 /* create */) != 0) { - ERR("cannot open the new part"); + ERR_WO_ERRNO("cannot open the new part"); goto err; } @@ -2280,7 +2297,7 @@ util_pool_extend(struct pool_set *set, size_t *size, size_t minpartsize) if (util_map_part(p, addr, 0, hdrsize, MAP_SHARED | MAP_FIXED, 0) != 0) { - ERR("cannot map the new part"); + ERR_WO_ERRNO("cannot map the new part"); goto err; } @@ -2290,9 +2307,10 @@ util_pool_extend(struct pool_set *set, size_t *size, size_t minpartsize) */ if (p->map_sync != rep->part[0].map_sync) { if (p->map_sync) - ERR("new part cannot be mapped with MAP_SYNC"); + ERR_WO_ERRNO( + "new part cannot be mapped with MAP_SYNC"); else - ERR("new part mapped with MAP_SYNC"); + ERR_WO_ERRNO("new part mapped with MAP_SYNC"); goto err; } } @@ -2335,7 +2353,8 @@ util_print_bad_files_cb(struct part_file *pf, void *arg) SUPPRESS_UNUSED(arg); if (pf->part && pf->part->has_bad_blocks) - ERR("file contains bad blocks -- '%s'", pf->part->path); + ERR_WO_ERRNO("file contains bad blocks -- '%s'", + pf->part->path); return 0; } @@ -2368,7 +2387,7 @@ util_pool_create_uuids(struct pool_set **setp, const char *path, /* check if file exists */ if (poolsize > 0 && exists) { - ERR("file %s already exists", path); + ERR_WO_ERRNO("file %s already exists", path); errno = EEXIST; return -1; } @@ -2376,7 +2395,7 @@ util_pool_create_uuids(struct pool_set **setp, const char *path, int ret = util_poolset_create_set(setp, path, poolsize, minsize, IGNORE_SDS(attr)); if (ret < 0) { - LOG(2, "cannot create pool set -- '%s'", path); + CORE_LOG_ERROR("cannot create pool set -- '%s'", path); return -1; } @@ -2385,28 +2404,28 @@ util_pool_create_uuids(struct pool_set **setp, const char *path, ASSERT(set->nreplicas > 0); if (set->options & OPTION_NOHDRS) { - ERR( + ERR_WO_ERRNO( "the NOHDRS poolset option is not supported for local poolsets"); errno = EINVAL; goto err_poolset_free; } if ((attr == NULL) != ((set->options & OPTION_NOHDRS) != 0)) { - ERR( + ERR_WO_ERRNO( "pool attributes are not supported for poolsets without headers (with the NOHDRS option)"); errno = EINVAL; goto err_poolset_free; } if (set->directory_based && ((set->options & OPTION_SINGLEHDR) == 0)) { - ERR( + ERR_WO_ERRNO( "directory based pools are not supported for poolsets with headers (without SINGLEHDR option)"); errno = EINVAL; goto err_poolset_free; } if (set->resvsize < minsize) { - ERR("reservation pool size %zu smaller than %zu", + ERR_WO_ERRNO("reservation pool size %zu smaller than %zu", set->resvsize, minsize); errno = EINVAL; goto err_poolset_free; @@ -2414,7 +2433,8 @@ util_pool_create_uuids(struct pool_set **setp, const char *path, if (set->directory_based && set->poolsize == 0 && util_poolset_append_new_part(set, minsize) != 0) { - ERR("cannot create a new part in provided directories"); + ERR_WO_ERRNO( + "cannot create a new part in provided directories"); goto err_poolset_free; } @@ -2422,7 +2442,7 @@ util_pool_create_uuids(struct pool_set **setp, const char *path, (attr->features.compat & POOL_FEAT_CHECK_BAD_BLOCKS)) { int bbs = badblocks_check_poolset(set, 1 /* create */); if (bbs < 0) { - LOG(1, + CORE_LOG_ERROR( "failed to check pool set for bad blocks -- '%s'", path); goto err_poolset_free; @@ -2432,7 +2452,7 @@ util_pool_create_uuids(struct pool_set **setp, const char *path, util_poolset_foreach_part_struct(set, util_print_bad_files_cb, NULL); - ERR( + ERR_WO_ERRNO( "pool set contains bad blocks and cannot be created, run 'pmempool create --clear-bad-blocks' utility to clear bad blocks and create a pool"); errno = EIO; goto err_poolset_free; @@ -2440,14 +2460,14 @@ util_pool_create_uuids(struct pool_set **setp, const char *path, } if (set->poolsize < minsize) { - ERR("net pool size %zu smaller than %zu", + ERR_WO_ERRNO("net pool size %zu smaller than %zu", set->poolsize, minsize); errno = EINVAL; goto err_poolset_free; } if (!can_have_rep && set->nreplicas > 1) { - ERR("replication not supported"); + ERR_WO_ERRNO("replication not supported"); errno = ENOTSUP; goto err_poolset_free; } @@ -2462,7 +2482,8 @@ util_pool_create_uuids(struct pool_set **setp, const char *path, /* generate pool set UUID */ ret = util_uuid_generate(set->uuid); if (ret < 0) { - LOG(2, "cannot generate pool set UUID"); + CORE_LOG_ERROR( + "cannot generate pool set UUID"); goto err_poolset; } } @@ -2473,8 +2494,8 @@ util_pool_create_uuids(struct pool_set **setp, const char *path, for (unsigned i = 0; i < rep->nhdrs; i++) { ret = util_uuid_generate(rep->part[i].uuid); if (ret < 0) { - LOG(2, - "cannot generate pool set part UUID"); + CORE_LOG_ERROR( + "cannot generate pool set part UUID"); goto err_poolset; } } @@ -2500,7 +2521,7 @@ util_pool_create_uuids(struct pool_set **setp, const char *path, for (unsigned r = 0; r < set->nreplicas; r++) { if (util_replica_create_local(set, r, flags, attr) != 0) { - LOG(2, "replica #%u creation failed", r); + CORE_LOG_ERROR("replica #%u creation failed", r); goto err_create; } } @@ -2567,7 +2588,8 @@ util_replica_open_local(struct pool_set *set, unsigned repidx, int flags) if (addr == NULL) addr = util_map_hint(rep->resvsize, 0); if (addr == MAP_FAILED) { - LOG(1, "cannot find a contiguous region of given size"); + CORE_LOG_ERROR( + "cannot find a contiguous region of given size"); return -1; } @@ -2576,7 +2598,8 @@ util_replica_open_local(struct pool_set *set, unsigned repidx, int flags) /* map the first part and reserve space for remaining parts */ if (util_map_part(&rep->part[0], addr, rep->resvsize, 0, flags, 0) != 0) { - LOG(2, "pool mapping failed - replica #%u part #0", + CORE_LOG_ERROR( + "pool mapping failed - replica #%u part #0", repidx); return -1; } @@ -2589,7 +2612,8 @@ util_replica_open_local(struct pool_set *set, unsigned repidx, int flags) /* map all headers - don't care about the address */ for (unsigned p = 0; p < rep->nhdrs; p++) { if (util_map_hdr(&rep->part[p], flags, 0) != 0) { - LOG(2, "header mapping failed - part #%d", p); + CORE_LOG_ERROR( + "header mapping failed - part #%d", p); goto err; } } @@ -2606,7 +2630,7 @@ util_replica_open_local(struct pool_set *set, unsigned repidx, int flags) ALIGN_DOWN(part->filesize - hdrsize, part->alignment); if (targetsize > rep->resvsize) { - ERR( + ERR_WO_ERRNO( "pool mapping failed - address space reservation too small"); errno = EINVAL; goto err; @@ -2622,8 +2646,9 @@ util_replica_open_local(struct pool_set *set, unsigned repidx, int flags) */ if ((errno == EINVAL) && (remaining_retries > 0)) { - LOG(2, "usable space mapping failed - " - "part #%d - retrying", p); + CORE_LOG_WARNING( + "usable space mapping failed - part #%d - retrying", + p); retry_for_contiguous_addr = 1; remaining_retries--; @@ -2634,7 +2659,8 @@ util_replica_open_local(struct pool_set *set, unsigned repidx, int flags) rep->resvsize); break; } - LOG(2, "usable space mapping failed - part #%d", + CORE_LOG_ERROR( + "usable space mapping failed - part #%d", p); goto err; } @@ -2758,13 +2784,25 @@ util_replica_check(struct pool_set *set, const struct pool_attr *attr) LOG(3, "set %p attr %p", set, attr); /* read shutdown state toggle from header */ - set->ignore_sds |= IGNORE_SDS(HDR(REP(set, 0), 0)); + int pool_ignore_sds = IGNORE_SDS(HDR(REP(set, 0), 0)); + if (pool_ignore_sds && (attr->features.incompat & POOL_E_FEAT_SDS)) { + /* + * In case, the user has a pool with the SDS feature turned off + * despite the PMEMOBJ can support it. It is the last call to + * turn on this crucial feature if possible. + */ + CORE_LOG_WARNING( + "Possible silent data corruption. The unsafe shutdown detection (SDS) is not supported in the pool: %s", + set->path); + } + set->ignore_sds |= pool_ignore_sds; for (unsigned r = 0; r < set->nreplicas; r++) { struct pool_replica *rep = set->replica[r]; for (unsigned p = 0; p < rep->nhdrs; p++) { if (util_header_check(set, r, p, attr) != 0) { - LOG(2, "header check failed - part #%d", p); + CORE_LOG_ERROR( + "header check failed - part #%d", p); return -1; } set->rdonly |= rep->part[p].rdonly; @@ -2776,7 +2814,7 @@ util_replica_check(struct pool_set *set, const struct pool_attr *attr) memcmp(HDR(REPN(set, r), 0)->uuid, HDR(REP(set, r), 0)->next_repl_uuid, POOL_HDR_UUID_LEN)) { - ERR("wrong replica UUID"); + ERR_WO_ERRNO("wrong replica UUID"); errno = EINVAL; return -1; } @@ -2793,7 +2831,7 @@ util_replica_check(struct pool_set *set, const struct pool_attr *attr) ASSERTne(rep->nparts, 0); if (shutdown_state_check(&sds, &HDR(rep, 0)->sds, rep)) { - LOG(2, "ADR failure detected"); + CORE_LOG_ERROR("ADR failure detected"); errno = EINVAL; return -1; } @@ -2832,7 +2870,7 @@ util_pool_open_nocheck(struct pool_set *set, unsigned flags) int cow = flags & POOL_OPEN_COW; if (cow && util_pool_has_device_dax(set)) { - ERR("device dax cannot be mapped privately"); + ERR_WO_ERRNO("device dax cannot be mapped privately"); errno = ENOTSUP; return -1; } @@ -2847,29 +2885,30 @@ util_pool_open_nocheck(struct pool_set *set, unsigned flags) /* check if any bad block recovery file exists */ int bfe = badblocks_recovery_file_exists(set); if (bfe > 0) { - ERR( + ERR_WO_ERRNO( "error: a bad block recovery file exists, run 'pmempool sync --bad-blocks' utility to try to recover the pool"); errno = EINVAL; return -1; } if (bfe < 0) { - LOG(1, + CORE_LOG_ERROR( "an error occurred when checking whether recovery file exists."); return -1; } int bbs = badblocks_check_poolset(set, 0 /* not create */); if (bbs < 0) { - LOG(1, "failed to check pool set for bad blocks"); + CORE_LOG_ERROR( + "failed to check pool set for bad blocks"); return -1; } if (bbs > 0) { if (flags & POOL_OPEN_IGNORE_BAD_BLOCKS) { - LOG(1, - "WARNING: pool set contains bad blocks, ignoring"); + CORE_LOG_WARNING( + "pool set contains bad blocks, ignoring"); } else { - ERR( + ERR_WO_ERRNO( "pool set contains bad blocks and cannot be opened, run 'pmempool sync --bad-blocks' utility to try to recover the pool"); errno = EIO; return -1; @@ -2885,7 +2924,7 @@ util_pool_open_nocheck(struct pool_set *set, unsigned flags) for (unsigned r = 0; r < set->nreplicas; r++) { if (util_replica_open(set, r, mmap_flags) != 0) { - LOG(2, "replica #%u open failed", r); + CORE_LOG_ERROR("replica #%u open failed", r); goto err_replica; } } @@ -2924,14 +2963,16 @@ util_read_compat_features(struct pool_set *set, uint32_t *compat_features) struct pool_set_part *part = &rep->part[p]; if (util_part_open(part, 0, 0 /* create */)) { - LOG(1, "!cannot open the part -- \"%s\"", + CORE_LOG_WARNING_W_ERRNO( + "cannot open the part -- \"%s\"", part->path); /* try to open the next part */ continue; } if (util_map_hdr(part, MAP_SHARED, 0) != 0) { - LOG(1, "header mapping failed -- \"%s\"", + CORE_LOG_ERROR( + "header mapping failed -- \"%s\"", part->path); util_part_fdclose(part); return -1; @@ -2974,18 +3015,18 @@ util_pool_open(struct pool_set **setp, const char *path, size_t minpartsize, int ret = util_poolset_create_set(setp, path, 0, 0, flags & POOL_OPEN_IGNORE_SDS); if (ret < 0) { - LOG(2, "cannot open pool set -- '%s'", path); + CORE_LOG_ERROR("cannot open pool set -- '%s'", path); return -1; } if ((*setp)->replica[0]->nparts == 0) { errno = ENOENT; - ERR("!no parts in replicas"); + ERR_W_ERRNO("no parts in replicas"); goto err_poolset_free; } if (cow && (*setp)->replica[0]->part[0].is_dev_dax) { - ERR("device dax cannot be mapped privately"); + ERR_WO_ERRNO("device dax cannot be mapped privately"); errno = ENOTSUP; goto err_poolset_free; } @@ -2997,7 +3038,7 @@ util_pool_open(struct pool_set **setp, const char *path, size_t minpartsize, uint32_t compat_features; if (util_read_compat_features(set, &compat_features)) { - LOG(1, "reading compat features failed"); + CORE_LOG_ERROR("reading compat features failed"); goto err_poolset_free; } @@ -3005,21 +3046,21 @@ util_pool_open(struct pool_set **setp, const char *path, size_t minpartsize, /* check if any bad block recovery file exists */ int bfe = badblocks_recovery_file_exists(set); if (bfe > 0) { - ERR( + ERR_WO_ERRNO( "error: a bad block recovery file exists, run 'pmempool sync --bad-blocks' utility to try to recover the pool"); errno = EINVAL; goto err_poolset_free; } if (bfe < 0) { - LOG(1, + CORE_LOG_ERROR( "an error occurred when checking whether recovery file exists."); goto err_poolset_free; } int bbs = badblocks_check_poolset(set, 0 /* not create */); if (bbs < 0) { - LOG(1, + CORE_LOG_ERROR( "failed to check pool set for bad blocks -- '%s'", path); goto err_poolset_free; @@ -3027,11 +3068,11 @@ util_pool_open(struct pool_set **setp, const char *path, size_t minpartsize, if (bbs > 0) { if (flags & POOL_OPEN_IGNORE_BAD_BLOCKS) { - LOG(1, - "WARNING: pool set contains bad blocks, ignoring -- '%s'", + CORE_LOG_WARNING( + "pool set contains bad blocks, ignoring -- '%s'", path); } else { - ERR( + ERR_WO_ERRNO( "pool set contains bad blocks and cannot be opened, run 'pmempool sync --bad-blocks' utility to try to recover the pool -- '%s'", path); errno = EIO; @@ -3046,7 +3087,7 @@ util_pool_open(struct pool_set **setp, const char *path, size_t minpartsize, for (unsigned r = 0; r < set->nreplicas; r++) { if (util_replica_open(set, r, mmap_flags) != 0) { - LOG(2, "replica #%u open failed", r); + CORE_LOG_ERROR("replica #%u open failed", r); goto err_replica; } } @@ -3111,7 +3152,7 @@ util_is_poolset_file(const char *path) rd += (size_t)sret; } while (sret > 0); if (sret < 0) { - ERR("!read"); + ERR_W_ERRNO("read"); ret = -1; goto out; } else if (rd != sizeof(signature)) { @@ -3175,14 +3216,14 @@ util_poolset_foreach_part(const char *path, int fd = os_open(path, O_RDONLY); if (fd < 0) { - ERR("!open: path \"%s\"", path); + ERR_W_ERRNO("open: path \"%s\"", path); return -1; } struct pool_set *set; int ret = util_poolset_parse(&set, path, fd); if (ret) { - ERR("util_poolset_parse failed -- '%s'", path); + ERR_WO_ERRNO("util_poolset_parse failed -- '%s'", path); ret = -1; goto err_close; } @@ -3251,8 +3292,10 @@ util_replica_deep_common(const void *addr, size_t len, struct pool_set *set, addr, len, set, replica_id, flush); struct pool_replica *rep = set->replica[replica_id]; +#ifdef DEBUG /* variables required for ASSERTs below */ uintptr_t rep_start = (uintptr_t)rep->part[0].addr; uintptr_t rep_end = rep_start + rep->repsize; +#endif uintptr_t start = (uintptr_t)addr; uintptr_t end = start + len; @@ -3281,7 +3324,7 @@ util_replica_deep_common(const void *addr, size_t len, struct pool_set *set, replica_id, part, (void *)range_start, range_len); if (os_part_deep_common(rep, p, (void *)range_start, range_len, flush)) { - LOG(1, "os_part_deep_common(%p, %p, %lu)", + CORE_LOG_ERROR("os_part_deep_common(%p, %p, %lu)", part, (void *)range_start, range_len); return -1; } diff --git a/src/common/set.h b/src/common/set.h index 8e691e880c7..b34c9928387 100644 --- a/src/common/set.h +++ b/src/common/set.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause */ -/* Copyright 2014-2022, Intel Corporation */ +/* Copyright 2014-2024, Intel Corporation */ /* * Copyright (c) 2016, Microsoft Corporation. All rights reserved. * @@ -45,7 +45,7 @@ #include -#include "out.h" +#include "core_assert.h" #include "vec.h" #include "pool_hdr.h" diff --git a/src/common/set_badblocks.c b/src/common/set_badblocks.c index f2bfac805da..f39ac85966f 100644 --- a/src/common/set_badblocks.c +++ b/src/common/set_badblocks.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2018-2023, Intel Corporation */ +/* Copyright 2018-2024, Intel Corporation */ /* * set_badblocks.c - common part of implementation of bad blocks API @@ -43,13 +43,15 @@ badblocks_check_file_cb(struct part_file *pf, void *arg) int ret = badblocks_check_file(pf->part->path); if (ret < 0) { - ERR("checking the pool file for bad blocks failed -- '%s'", + ERR_WO_ERRNO( + "checking the pool file for bad blocks failed -- '%s'", pf->part->path); return -1; } if (ret > 0) { - ERR("part file contains bad blocks -- '%s'", pf->part->path); + ERR_WO_ERRNO("part file contains bad blocks -- '%s'", + pf->part->path); pcfcb->n_files_bbs++; pf->part->has_bad_blocks = 1; } @@ -81,7 +83,8 @@ badblocks_check_poolset(struct pool_set *set, int create) } if (cfcb.n_files_bbs) { - LOG(1, "%i pool file(s) contain bad blocks", cfcb.n_files_bbs); + CORE_LOG_ERROR("%i pool file(s) contain bad blocks", + cfcb.n_files_bbs); set->has_bad_blocks = 1; } @@ -114,7 +117,8 @@ badblocks_clear_poolset_cb(struct part_file *pf, void *arg) int ret = badblocks_clear_all(pf->part->path); if (ret < 0) { - ERR("clearing bad blocks in the pool file failed -- '%s'", + ERR_WO_ERRNO( + "clearing bad blocks in the pool file failed -- '%s'", pf->part->path); errno = EIO; return -1; @@ -164,7 +168,7 @@ badblocks_recovery_file_alloc(const char *file, unsigned rep, unsigned part) path = Malloc(len_path + 1); if (path == NULL) { - ERR("!Malloc"); + ERR_W_ERRNO("Malloc"); return NULL; } @@ -206,7 +210,7 @@ badblocks_recovery_file_exists(struct pool_set *set) char *rec_file = badblocks_recovery_file_alloc(set->path, r, p); if (rec_file == NULL) { - LOG(1, + CORE_LOG_ERROR( "allocating name of bad block recovery file failed"); return -1; } diff --git a/src/common/shutdown_state.c b/src/common/shutdown_state.c index 3a2bb11fa2e..fb101d38e56 100644 --- a/src/common/shutdown_state.c +++ b/src/common/shutdown_state.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2017-2020, Intel Corporation */ +/* Copyright 2017-2024, Intel Corporation */ /* * shutdown_state.c -- unsafe shudown detection @@ -71,21 +71,20 @@ shutdown_state_add_part(struct shutdown_state *sds, int fd, int ret = pmem2_source_device_usc(src, &usc); - if (ret == PMEM2_E_NOSUPP) { - usc = 0; - } else if (ret != 0) { + if (ret != 0) { if (ret == -EPERM) { /* overwrite error message */ - ERR( + ERR_WO_ERRNO( "Cannot read unsafe shutdown count. For more information please check https://github.com/pmem/pmdk/issues/4207"); } - LOG(2, "cannot read unsafe shutdown count for %d", fd); + CORE_LOG_ERROR("cannot read unsafe shutdown count for %d", + fd); goto err; } ret = pmem2_source_device_id(src, NULL, &len); - if (ret != PMEM2_E_NOSUPP && ret != 0) { - ERR("cannot read uuid of %d", fd); + if (ret != 0) { + ERR_WO_ERRNO("cannot read uuid of %d", fd); goto err; } @@ -93,13 +92,13 @@ shutdown_state_add_part(struct shutdown_state *sds, int fd, uid = Zalloc(len); if (uid == NULL) { - ERR("!Zalloc"); + ERR_W_ERRNO("Zalloc"); goto err; } ret = pmem2_source_device_id(src, uid, &len); - if (ret != PMEM2_E_NOSUPP && ret != 0) { - ERR("cannot read uuid of %d", fd); + if (ret != 0) { + ERR_WO_ERRNO("cannot read uuid of %d", fd); Free(uid); goto err; } @@ -204,7 +203,8 @@ shutdown_state_check(struct shutdown_state *curr_sds, if (!is_checksum_correct) { /* the program was killed during opening or closing the pool */ - LOG(2, "incorrect checksum - SDS will be reinitialized"); + CORE_LOG_WARNING( + "incorrect checksum - SDS will be reinitialized"); shutdown_state_reinit(curr_sds, pool_sds, rep); return 0; } @@ -216,19 +216,20 @@ shutdown_state_check(struct shutdown_state *curr_sds, * the program was killed when the pool was opened * but there wasn't an ADR failure */ - LOG(2, + CORE_LOG_WARNING( "the pool was not closed - SDS will be reinitialized"); shutdown_state_reinit(curr_sds, pool_sds, rep); return 0; } if (dirty == 0) { /* an ADR failure but the pool was closed */ - LOG(2, + CORE_LOG_WARNING( "an ADR failure was detected but the pool was closed - SDS will be reinitialized"); shutdown_state_reinit(curr_sds, pool_sds, rep); return 0; } /* an ADR failure - the pool might be corrupted */ - ERR("an ADR failure was detected, the pool might be corrupted"); + ERR_WO_ERRNO( + "an ADR failure was detected, the pool might be corrupted"); return 1; } diff --git a/src/common/util_pmem.h b/src/common/util_pmem.h index a31b6b8f7e9..720d1d78d76 100644 --- a/src/common/util_pmem.h +++ b/src/common/util_pmem.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause */ -/* Copyright 2017-2020, Intel Corporation */ +/* Copyright 2017-2024, Intel Corporation */ /* * util_pmem.h -- internal definitions for pmem utils @@ -10,6 +10,7 @@ #include "libpmem.h" #include "out.h" +#include "log_internal.h" #ifdef __cplusplus extern "C" { @@ -26,7 +27,7 @@ util_persist(int is_pmem, const void *addr, size_t len) if (is_pmem) pmem_persist(addr, len); else if (pmem_msync(addr, len)) - FATAL("!pmem_msync"); + CORE_LOG_FATAL_W_ERRNO("pmem_msync"); } /* diff --git a/src/common/uuid.c b/src/common/uuid.c index 0b16d7f7c58..66cc1c1ae18 100644 --- a/src/common/uuid.c +++ b/src/common/uuid.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2014-2021, Intel Corporation */ +/* Copyright 2014-2024, Intel Corporation */ /* * uuid.c -- uuid utilities @@ -8,8 +8,9 @@ #include #include #include + #include "uuid.h" -#include "out.h" +#include "log_internal.h" /* * util_uuid_to_string -- generate a string form of the uuid @@ -20,12 +21,12 @@ util_uuid_to_string(const uuid_t u, char *buf) int len; /* size that is returned from sprintf call */ if (buf == NULL) { - LOG(2, "invalid buffer for uuid string"); + CORE_LOG_ERROR("invalid buffer for uuid string"); return -1; } if (u == NULL) { - LOG(2, "invalid uuid structure"); + CORE_LOG_ERROR("invalid uuid structure"); return -1; } @@ -38,7 +39,7 @@ util_uuid_to_string(const uuid_t u, char *buf) uuid->node[5]); if (len != POOL_HDR_UUID_STR_LEN - 1) { - LOG(2, "snprintf(uuid): %d", len); + CORE_LOG_ERROR("snprintf(uuid): %d", len); return -1; } @@ -56,13 +57,13 @@ int util_uuid_from_string(const char uuid[POOL_HDR_UUID_STR_LEN], struct uuid *ud) { if (strlen(uuid) != 36) { - LOG(2, "invalid uuid string"); + CORE_LOG_ERROR("invalid uuid string"); return -1; } if (uuid[8] != '-' || uuid[13] != '-' || uuid[18] != '-' || uuid[23] != '-') { - LOG(2, "invalid uuid string"); + CORE_LOG_ERROR("invalid uuid string"); return -1; } @@ -75,7 +76,7 @@ util_uuid_from_string(const char uuid[POOL_HDR_UUID_STR_LEN], struct uuid *ud) &ud->node[5]); if (n != 11) { - LOG(2, "sscanf(uuid)"); + CORE_LOG_ERROR("sscanf(uuid)"); return -1; } diff --git a/src/common/uuid_linux.c b/src/common/uuid_linux.c index 979e0ad52ba..3ec2abd64ba 100644 --- a/src/common/uuid_linux.c +++ b/src/common/uuid_linux.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2015-2017, Intel Corporation */ +/* Copyright 2015-2024, Intel Corporation */ /* * uuid_linux.c -- pool set utilities with OS-specific implementation @@ -11,7 +11,7 @@ #include "uuid.h" #include "os.h" -#include "out.h" +#include "log_internal.h" /* * util_uuid_generate -- generate a uuid @@ -28,13 +28,13 @@ util_uuid_generate(uuid_t uuid) int fd = os_open(POOL_HDR_UUID_GEN_FILE, O_RDONLY); if (fd < 0) { /* Fatal error */ - LOG(2, "!open(uuid)"); + CORE_LOG_ERROR_W_ERRNO("open(uuid)"); return -1; } ssize_t num = read(fd, uu, POOL_HDR_UUID_STR_LEN); if (num < POOL_HDR_UUID_STR_LEN) { /* Fatal error */ - LOG(2, "!read(uuid)"); + CORE_LOG_ERROR_W_ERRNO("read(uuid)"); os_close(fd); return -1; } diff --git a/src/common/vec.h b/src/common/vec.h index c1ba60c9539..5d7cfbb6fd6 100644 --- a/src/common/vec.h +++ b/src/common/vec.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause */ -/* Copyright 2017-2020, Intel Corporation */ +/* Copyright 2017-2024, Intel Corporation */ /* * vec.h -- vector interface @@ -11,7 +11,7 @@ #include #include "valgrind_internal.h" #include "util.h" -#include "out.h" +#include "log_internal.h" #include "alloc.h" #ifdef __cplusplus @@ -59,7 +59,7 @@ vec_reserve(void *vec, size_t ncapacity, size_t s) VEC(vvec, void) *vecp = (struct vvec *)vec; void *tbuf = Realloc(vecp->buffer, s * ncap); if (tbuf == NULL) { - ERR("!Realloc"); + ERR_W_ERRNO("Realloc"); return -1; } vecp->buffer = tbuf; diff --git a/src/common/vecq.h b/src/common/vecq.h index 98c77b615ff..cface8ba93d 100644 --- a/src/common/vecq.h +++ b/src/common/vecq.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause */ -/* Copyright 2018-2020, Intel Corporation */ +/* Copyright 2018-2024, Intel Corporation */ /* * vecq.h -- vector queue (FIFO) interface @@ -65,7 +65,7 @@ realloc_set(void **buf, size_t s) { void *tbuf = Realloc(*buf, s); if (tbuf == NULL) { - ERR("!Realloc"); + ERR_W_ERRNO("Realloc"); return -1; } *buf = tbuf; diff --git a/src/core/alloc.c b/src/core/alloc.c index e267e4e6291..e50426b2b46 100644 --- a/src/core/alloc.c +++ b/src/core/alloc.c @@ -1,16 +1,17 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2019-2020, Intel Corporation */ +/* Copyright 2019-2024, Intel Corporation */ #include #include "alloc.h" #include "fault_injection.h" -#include "out.h" Malloc_func fn_malloc = malloc; Realloc_func fn_realloc = realloc; #if FAULT_INJECTION +#include "log_internal.h" + static __thread int malloc_num; static __thread int fail_malloc_num; static __thread const char *fail_malloc_from; @@ -58,7 +59,7 @@ core_inject_fault_at(enum pmem_allocation_type type, int nth, const char *at) fail_realloc_from = at; break; default: - FATAL("unknown allocation type"); + CORE_LOG_FATAL("unknown allocation type"); } } diff --git a/src/core/core_assert.h b/src/core/core_assert.h new file mode 100644 index 00000000000..fdcfeaafc14 --- /dev/null +++ b/src/core/core_assert.h @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright 2014-2024, Intel Corporation */ + +/* + * core_assert.h -- definitions for the "core_assert" module + */ + +#ifndef CORE_ASSERT_H +#define CORE_ASSERT_H + +#include "log_internal.h" +#include "util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__KLOCWORK__) +#define TEST_ALWAYS_TRUE_EXPR(cnd) +#define TEST_ALWAYS_EQ_EXPR(cnd) +#define TEST_ALWAYS_NE_EXPR(cnd) +#else +#define TEST_ALWAYS_TRUE_EXPR(cnd)\ + if (__builtin_constant_p(cnd))\ + ASSERT_COMPILE_ERROR_ON(cnd); +#define TEST_ALWAYS_EQ_EXPR(lhs, rhs)\ + if (__builtin_constant_p(lhs) && __builtin_constant_p(rhs))\ + ASSERT_COMPILE_ERROR_ON((lhs) == (rhs)); +#define TEST_ALWAYS_NE_EXPR(lhs, rhs)\ + if (__builtin_constant_p(lhs) && __builtin_constant_p(rhs))\ + ASSERT_COMPILE_ERROR_ON((lhs) != (rhs)); +#endif + +/* assert a condition is true at runtime */ +#if defined(DEBUG) || defined(__clang_analyzer__) || defined(__COVERITY__) ||\ + defined(__KLOCWORK__) +#define ASSERT_rt(cnd) do { \ + if ((cnd)) break; \ + CORE_LOG_FATAL("assertion failure: %s", #cnd);\ +} while (0) + +/* assertion with extra info printed if assertion fails at runtime */ +#define ASSERTinfo_rt(cnd, info) do { \ + if ((cnd)) break; \ + CORE_LOG_FATAL("assertion failure: %s (%s = %s)", #cnd, #info, info);\ +} while (0) + +/* assert two integer values are equal at runtime */ +#define ASSERTeq_rt(lhs, rhs) do { \ + if ((lhs) == (rhs)) break; \ + CORE_LOG_FATAL( \ + "assertion failure: %s (0x%llx) == %s (0x%llx)", #lhs, \ + (unsigned long long)(lhs), #rhs, (unsigned long long)(rhs)); \ +} while (0) + +/* assert two integer values are not equal at runtime */ +#define ASSERTne_rt(lhs, rhs) do { \ + if ((lhs) != (rhs)) break; \ + CORE_LOG_FATAL("assertion failure: %s (0x%llx) != %s (0x%llx)", #lhs,\ + (unsigned long long)(lhs), #rhs, (unsigned long long)(rhs)); \ +} while (0) + +/* assert a condition is true */ +#define ASSERT(cnd)\ + do {\ + /*\ + * Detect useless asserts on always true expression. Please use\ + * COMPILE_ERROR_ON(!cnd) or ASSERT_rt(cnd) in such cases.\ + */\ + TEST_ALWAYS_TRUE_EXPR(cnd);\ + ASSERT_rt(cnd);\ + } while (0) + +/* assertion with extra info printed if assertion fails */ +#define ASSERTinfo(cnd, info)\ + do {\ + /* See comment in ASSERT. */\ + TEST_ALWAYS_TRUE_EXPR(cnd);\ + ASSERTinfo_rt(cnd, info);\ + } while (0) + +/* assert two integer values are equal */ +#define ASSERTeq(lhs, rhs)\ + do {\ + /* See comment in ASSERT. */\ + TEST_ALWAYS_EQ_EXPR(lhs, rhs);\ + ASSERTeq_rt(lhs, rhs);\ + } while (0) + +/* assert two integer values are not equal */ +#define ASSERTne(lhs, rhs)\ + do {\ + /* See comment in ASSERT. */\ + TEST_ALWAYS_NE_EXPR(lhs, rhs);\ + ASSERTne_rt(lhs, rhs);\ + } while (0) +#else +#define ASSERT_rt(cnd) +#define ASSERTinfo_rt(cnd, info) +#define ASSERTeq_rt(lhs, rhs) +#define ASSERTne_rt(lhs, rhs) +#define ASSERT(cnd) +#define ASSERTinfo(cnd, info) +#define ASSERTeq(lhs, rhs) +#define ASSERTne(lhs, rhs) +#endif /* DEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif /* CORE_ASSERT_H */ diff --git a/src/core/last_error_msg.c b/src/core/last_error_msg.c new file mode 100644 index 00000000000..799e11cff41 --- /dev/null +++ b/src/core/last_error_msg.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* Copyright 2014-2024, Intel Corporation */ + +/* + * last_error_msg.c -- maintain TLS buffers to store the last error message + * + * The last error message is a hand-picked error message believed to convey + * the critical piece of information which will be available to the user via + * the *_errormsg() API calls. + */ + +#include +#include +#include +#include +#include +#include + +#include "last_error_msg.h" +#include "os_thread.h" +#include "log_internal.h" +#include "valgrind_internal.h" + +struct lasterrormsg +{ + char msg[CORE_LAST_ERROR_MSG_MAXPRINT]; +}; + +static os_once_t Last_errormsg_key_once = OS_ONCE_INIT; +static os_tls_key_t Last_errormsg_key; + +static void +last_error_msg_key_alloc(void) +{ + int pth_ret = os_tls_key_create(&Last_errormsg_key, free); + if (pth_ret) + CORE_LOG_FATAL_W_ERRNO("os_thread_key_create"); + + VALGRIND_ANNOTATE_HAPPENS_BEFORE(&Last_errormsg_key_once); +} + +void +last_error_msg_init(void) +{ + os_once(&Last_errormsg_key_once, last_error_msg_key_alloc); + /* + * Workaround Helgrind's bug: + * https://bugs.kde.org/show_bug.cgi?id=337735 + */ + VALGRIND_ANNOTATE_HAPPENS_AFTER(&Last_errormsg_key_once); +} + +void +last_error_msg_fini(void) +{ + void *p = os_tls_get(Last_errormsg_key); + if (p) { + free(p); + (void) os_tls_set(Last_errormsg_key, NULL); + } + (void) os_tls_key_delete(Last_errormsg_key); +} + +static inline struct lasterrormsg * +last_error_msg_get_internal(void) +{ + last_error_msg_init(); + + struct lasterrormsg *last = os_tls_get(Last_errormsg_key); + if (last == NULL) { + last = malloc(sizeof(struct lasterrormsg)); + if (last == NULL) + return NULL; + /* make sure it contains empty string initially */ + last->msg[0] = '\0'; + int ret = os_tls_set(Last_errormsg_key, last); + if (ret) + CORE_LOG_FATAL_W_ERRNO("os_tls_set"); + } + return last; +} + +/* + * last_error_msg_get -- get the last error message + */ +const char * +last_error_msg_get(void) +{ + const struct lasterrormsg *last = last_error_msg_get_internal(); + return &last->msg[0]; +} diff --git a/src/core/last_error_msg.h b/src/core/last_error_msg.h new file mode 100644 index 00000000000..f43821b2c13 --- /dev/null +++ b/src/core/last_error_msg.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright 2014-2024, Intel Corporation */ + +/* + * last_error_msg.h -- definitions for the "last_error_msg" module + */ + +#ifndef CORE_LAST_ERROR_MSG_H +#define CORE_LAST_ERROR_MSG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define CORE_LAST_ERROR_MSG_MAXPRINT 301 /* maximum expected log line */ + +void last_error_msg_init(void); +void last_error_msg_fini(void); + +const char *last_error_msg_get(void); + +#ifdef __cplusplus +} +#endif + +#endif /* CORE_LAST_ERROR_MSG_H */ diff --git a/src/core/log.c b/src/core/log.c new file mode 100644 index 00000000000..529d2a8b043 --- /dev/null +++ b/src/core/log.c @@ -0,0 +1,237 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* Copyright 2020-2024, Intel Corporation */ + +/* + * log.c -- support for logging output to either syslog or stderr or + * via user defined function + */ + +/* + * Note: The undef below is critical to use the XSI-compliant version of + * the strerror_r(3) instead of the GNU-specific. Otherwise, the produced + * error string may not end up in the log buffer. + */ +#undef _GNU_SOURCE +#include + +#include +#include +#include +#include +#include + +#include "log_internal.h" +#include "log_default.h" +#include "last_error_msg.h" +#include "core_assert.h" + +/* + * Default levels of the logging thresholds + */ +#ifdef DEBUG +#define CORE_LOG_THRESHOLD_DEFAULT CORE_LOG_LEVEL_DEBUG +#define CORE_LOG_THRESHOLD_AUX_DEFAULT CORE_LOG_LEVEL_WARNING +#else +#define CORE_LOG_THRESHOLD_DEFAULT CORE_LOG_LEVEL_WARNING +#define CORE_LOG_THRESHOLD_AUX_DEFAULT CORE_LOG_LEVEL_HARK +#endif + +/* + * Core_log_function -- pointer to the logging function. By default it is + * core_log_default_function(), but could be a user-defined logging function + * provided via core_log_set_function(). + */ +static core_log_function *Core_log_function = NULL; + +/* threshold levels */ +static enum core_log_level Core_log_threshold[] = { + CORE_LOG_THRESHOLD_DEFAULT, + CORE_LOG_THRESHOLD_AUX_DEFAULT +}; + +/* + * core_log_init -- initialize and set the default logging function + */ +void +core_log_init() +{ + /* + * The core log might be already initialized. + * It might happen in the case of some unit tests. + */ + if (Core_log_function != 0) + return; + + /* enable the default logging function */ + core_log_default_init(); + while (EAGAIN == + core_log_set_function(CORE_LOG_USE_DEFAULT_FUNCTION)) + ; +} + +/* + * core_log_fini -- disable logging and cleanup the default logging function + */ +void +core_log_fini() +{ + /* + * NULL-ed function pointer turns off the logging. No matter if + * the previous value was the default logging function or a user + * logging function. + */ + Core_log_function = NULL; + + /* cleanup the default logging function */ + core_log_default_fini(); +} + +static void +core_log_lib_info(void) +{ + CORE_LOG_HARK("src version: " SRCVERSION); +#if SDS_ENABLED + CORE_LOG_HARK("compiled with support for shutdown state"); +#endif +#if NDCTL_ENABLED + CORE_LOG_HARK("compiled with libndctl 63+"); +#endif +} + +/* + * core_log_set_function -- set the log function pointer either to + * a user-provided function pointer or to the default logging function. + */ +int +core_log_set_function(core_log_function *log_function) +{ + + if (log_function == CORE_LOG_USE_DEFAULT_FUNCTION) + log_function = core_log_default_function; + + core_log_function *core_log_function_old = Core_log_function; + if (__sync_bool_compare_and_swap(&Core_log_function, + core_log_function_old, log_function)) { + core_log_lib_info(); + return 0; + } + return EAGAIN; +} + +/* + * core_log_set_threshold -- set the log level threshold + */ +int +core_log_set_threshold(enum core_log_threshold threshold, + enum core_log_level level) +{ + if (threshold != CORE_LOG_THRESHOLD && + threshold != CORE_LOG_THRESHOLD_AUX) + return EINVAL; + + if (level < CORE_LOG_LEVEL_HARK || level > CORE_LOG_LEVEL_DEBUG) + return EINVAL; + + enum core_log_level level_old; + /* fed with already validated arguments it can't fail */ + (void) core_log_get_threshold(threshold, &level_old); + + if (!__sync_bool_compare_and_swap(&Core_log_threshold[threshold], + level_old, level)) { + return EAGAIN; + } + + return 0; +} + +/* + * core_log_get_threshold -- get the log level threshold + */ +int +core_log_get_threshold(enum core_log_threshold threshold, + enum core_log_level *level) +{ + if (threshold != CORE_LOG_THRESHOLD && + threshold != CORE_LOG_THRESHOLD_AUX) + return EINVAL; + + if (level == NULL) + return EINVAL; + + *level = Core_log_threshold[threshold]; + + return 0; +} + +/* + * _core_log_get_threshold_internal -- a core_log_get_threshold variant + * optimized for performance and not affecting the stack size of all + * the functions using the CORE_LOG_* macros. + */ +volatile enum core_log_level +_core_log_get_threshold_internal() +{ + return Core_log_threshold[CORE_LOG_THRESHOLD]; +} + +static void inline +core_log_va(char *buf, size_t buf_len, enum core_log_level level, + int errnum, const char *file_name, unsigned line_no, + const char *function_name, const char *message_format, va_list arg) +{ + int msg_len = vsnprintf(buf, buf_len, message_format, arg); + if (msg_len < 0) + goto end; + + if ((size_t)msg_len < buf_len - 1 && errnum != NO_ERRNO) { + /* + * Ask for the error string right after the already printed + * message. + */ + char *msg_ptr = buf + msg_len; + size_t buf_len_left = buf_len - (size_t)msg_len; + /* + * If it fails, the best thing to do is to at least pass + * the log message as is. + */ + (void) strerror_r(errnum, msg_ptr, buf_len_left); + } + + /* + * Despite this check is already done when the function is called from + * the CORE_LOG() macro it has to be done here again since it is not + * performed in the case of the CORE_LOG_TO_LAST macro. Sorry. + */ + if (level > _core_log_get_threshold_internal()) + goto end; + + if (NULL == Core_log_function) + goto end; + + Core_log_function(level, file_name, line_no, function_name, buf); + +end: + if (errnum != NO_ERRNO) + errno = errnum; +} + +void +core_log(enum core_log_level level, int errnum, const char *file_name, + unsigned line_no, const char *function_name, const char *message_format, + ...) +{ + char message[_CORE_LOG_MSG_MAXPRINT] = ""; + char *buf = message; + size_t buf_len = sizeof(message); + if (level == CORE_LOG_LEVEL_ERROR_LAST) { + level = CORE_LOG_LEVEL_ERROR; + buf = (char *)last_error_msg_get(); + buf_len = CORE_LAST_ERROR_MSG_MAXPRINT; + } + + va_list arg; + va_start(arg, message_format); + core_log_va(buf, buf_len, level, errnum, file_name, line_no, + function_name, message_format, arg); + va_end(arg); +} diff --git a/src/core/log_default.c b/src/core/log_default.c new file mode 100644 index 00000000000..bdb165dd097 --- /dev/null +++ b/src/core/log_default.c @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* Copyright 2020-2024, Intel Corporation */ + +/* + * log_default.c -- the default logging function with support for logging either + * to syslog or to stderr + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "log_internal.h" +#include "log_default.h" +#include "os.h" +#include "util.h" + +static const char log_level_names[CORE_LOG_LEVEL_MAX][9] = { + [CORE_LOG_LEVEL_HARK] = "*HARK* ", + [CORE_LOG_LEVEL_FATAL] = "*FATAL* ", + [CORE_LOG_LEVEL_ERROR] = "*ERROR* ", + [CORE_LOG_LEVEL_WARNING] = "*WARN* ", + [CORE_LOG_LEVEL_NOTICE] = "*NOTE* ", + [CORE_LOG_LEVEL_INFO] = "*INFO* ", + [CORE_LOG_LEVEL_DEBUG] = "*DEBUG* ", +}; + +static const int log_level_syslog_severity[] = { + [CORE_LOG_LEVEL_HARK] = LOG_NOTICE, + [CORE_LOG_LEVEL_FATAL] = LOG_CRIT, + [CORE_LOG_LEVEL_ERROR] = LOG_ERR, + [CORE_LOG_LEVEL_WARNING] = LOG_WARNING, + [CORE_LOG_LEVEL_NOTICE] = LOG_NOTICE, + [CORE_LOG_LEVEL_INFO] = LOG_INFO, + [CORE_LOG_LEVEL_DEBUG] = LOG_DEBUG, +}; + +/* + * get_timestamp_prefix -- provide actual time in a readable string + * + * NOTE + * This function is static now, so we know all possible calls of snprintf() + * and we conclude it can not fail. + * + * ASSUMPTIONS: + * - buf != NULL && buf_size >= 16 + */ +static void +get_timestamp_prefix(char *buf, size_t buf_size) +{ + struct tm info; + char date[24]; + struct timespec ts; + long usec; + + const char error_message[] = "[time error] "; + + if (os_clock_gettime(CLOCK_REALTIME, &ts)) + goto err_message; + + if (NULL == localtime_r(&ts.tv_sec, &info)) + goto err_message; + + usec = ts.tv_nsec / 1000; + if (!strftime(date, sizeof(date), "%b %d %H:%M:%S", &info)) + goto err_message; + + /* it cannot fail - please see the note above */ + (void) snprintf(buf, buf_size, "%s.%06ld ", date, usec); + if (strnlen(buf, buf_size) == buf_size) + goto err_message; + + return; + +err_message: + memcpy(buf, error_message, sizeof(error_message)); +} + +/* + * core_log_default_function -- default logging function used to log a message + * to syslog and/or stderr + * + * The message is started with prefix composed from file, line, func parameters + * followed by string pointed by format. If format includes format specifiers + * (subsequences beginning with %), the additional arguments following format + * are formatted and inserted in the message. + * + * ASSUMPTIONS: + * - level >= CORE_LOG_LEVEL_HARK && level <= CORE_LOG_LEVEL_DEBUG + * - level <= Core_log_threshold[LOG_THRESHOLD] + * - file == NULL || (file != NULL && function != NULL) + */ +void +core_log_default_function(enum core_log_level level, const char *file_name, + unsigned line_no, const char *function_name, const char *message) +{ + char file_info_buffer[256] = ""; + const char *file_info = file_info_buffer; + const char file_info_error[] = "[file info error]: "; + enum core_log_level threshold_aux; + + if (file_name) { + /* extract base_file_name */ + const char *base_file_name = strrchr(file_name, '/'); + if (!base_file_name) + base_file_name = file_name; + else + /* skip '/' */ + base_file_name++; + + if (snprintf(file_info_buffer, sizeof(file_info_buffer), + "%s: %3u: %s: ", base_file_name, line_no, + function_name) < 0) { + file_info = file_info_error; + } + } + + /* primary logging destination (CORE_LOG_THRESHOLD) */ + syslog(log_level_syslog_severity[level], "%s%s%s", + log_level_names[level], file_info, message); + + /* + * Since the CORE_LOG_LEVEL_HARK level messages convey pretty mundane + * information regarding the libraries versions etc. it has been decided + * to print them out to the syslog and under no circumstances to stderr + * to keep it clean for potentially more critical information. + */ + if (level == CORE_LOG_LEVEL_HARK) { + return; + } + + /* secondary logging destination (CORE_LOG_THRESHOLD_AUX) */ + (void) core_log_get_threshold(CORE_LOG_THRESHOLD_AUX, &threshold_aux); + if (level <= threshold_aux) { + char times_tamp[45] = ""; + get_timestamp_prefix(times_tamp, sizeof(times_tamp)); + (void) fprintf(stderr, "%s[%ld] %s%s%s\n", times_tamp, + syscall(SYS_gettid), log_level_names[level], file_info, + message); + } +} + +/* + * core_log_default_init -- explain why not calling openlog(3) + */ +void +core_log_default_init() +{ + /* + * Despite the default logging function prints to the syslog it is + * undesirable to call openlog(3) here since other software components + * might already configured the syslog. It is also unnecessary since + * the first syslog(3) call will call it. + */ +} + +/* + * core_log_default_fini -- explain why not calling closelog(3) + */ +void +core_log_default_fini(void) +{ + /* + * Since the PMDK libraries might not be the only software components + * making use of the syslog it is undesirable to call closelog(3) + * explicitly. Note its use is optional. + */ +} diff --git a/src/core/log_default.h b/src/core/log_default.h new file mode 100644 index 00000000000..2a00d388799 --- /dev/null +++ b/src/core/log_default.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright 2020-2024, Intel Corporation */ + +/* + * log_default.h -- the default logging function definitions + */ + +#ifndef CORE_LOG_DEFAULT_H +#define CORE_LOG_DEFAULT_H + +void core_log_default_function(enum core_log_level level, const char *file_name, + unsigned line_no, const char *function_name, const char *message); + +void core_log_default_init(void); + +void core_log_default_fini(void); + +#endif /* CORE_LOG_DEFAULT_H */ diff --git a/src/core/log_internal.h b/src/core/log_internal.h new file mode 100644 index 00000000000..dd9d775fdb7 --- /dev/null +++ b/src/core/log_internal.h @@ -0,0 +1,209 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright 2020-2024, Intel Corporation */ + +/* + * log_internal.h -- internal logging interfaces + */ + +#ifndef CORE_LOG_INTERNAL_H +#define CORE_LOG_INTERNAL_H + +#include +#include +#include + +#ifdef ATOMIC_OPERATIONS_SUPPORTED +#include +#endif /* ATOMIC_OPERATIONS_SUPPORTED */ + +/* Required to work properly with pmembench. */ +#ifdef __cplusplus +extern "C" { +#endif + +enum core_log_level { + /* only basic library info */ + CORE_LOG_LEVEL_HARK, + /* an error that causes the library to stop working immediately */ + CORE_LOG_LEVEL_FATAL, + /* an error that causes the library to stop working properly */ + CORE_LOG_LEVEL_ERROR, + /* an errors that could be handled in the upper level */ + CORE_LOG_LEVEL_WARNING, + /* non-massive info mainly related to public API function completions */ + CORE_LOG_LEVEL_NOTICE, + /* massive info e.g. every write operation indication */ + CORE_LOG_LEVEL_INFO, + /* debug info e.g. write operation dump */ + CORE_LOG_LEVEL_DEBUG, + CORE_LOG_LEVEL_MAX +}; + +#define CORE_LOG_LEVEL_ERROR_LAST ((enum core_log_level) \ + (CORE_LOG_LEVEL_ERROR + CORE_LOG_LEVEL_MAX)) + +enum core_log_threshold { + /* + * the main threshold level - the logging messages above this level + * won't trigger the logging functions + */ + CORE_LOG_THRESHOLD, + /* + * the auxiliary threshold level - may or may not be used by the logging + * function + */ + CORE_LOG_THRESHOLD_AUX, + CORE_LOG_THRESHOLD_MAX +}; + +int core_log_set_threshold(enum core_log_threshold threshold, + enum core_log_level level); + +int core_log_get_threshold(enum core_log_threshold threshold, + enum core_log_level *level); + +volatile enum core_log_level _core_log_get_threshold_internal(void); + +/* + * the type used for defining logging functions + */ +typedef void core_log_function( + /* the log level of the message */ + enum core_log_level level, + /* name of the source file where the message coming from */ + const char *file_name, + /* the source file line where the message coming from */ + unsigned line_no, + /* the function name where the message coming from */ + const char *function_name, + /* message */ + const char *message); + +#define CORE_LOG_USE_DEFAULT_FUNCTION (NULL) + +int core_log_set_function(core_log_function *log_function); + +void core_log_init(void); + +void core_log_fini(void); + +/* + * The actual maximum expected log line is 407. + * An additional byte is used to detect buffer overflow in core_log tests. + * If the actual max message length is equal to 408, it means we have a buffer + * overflow. + */ +#define _CORE_LOG_MSG_MAXPRINT 408 /* maximum expected log line + 1 */ + +static inline int +core_log_error_translate(int ret) +{ + if (ret != 0) { + errno = ret; + return 1; + } + + return 0; +} + +#define NO_ERRNO (-1) + +void core_log(enum core_log_level level, int errnum, const char *file_name, + unsigned line_no, const char *function_name, const char *message_format, + ...); + +#define _CORE_LOG(level, errnum, format, ...) \ + do { \ + if (level <= \ + _core_log_get_threshold_internal()) { \ + core_log(level, errnum, __FILE__, __LINE__, \ + __func__, format, ##__VA_ARGS__); \ + } \ + } while (0) + +/* + * Can't check the logging level here when logging to the last error message. + * Since the log message has to be generated anyway. + */ +#define CORE_LOG_TO_LAST(errnum, format, ...) \ + core_log(CORE_LOG_LEVEL_ERROR_LAST, errnum, __FILE__, __LINE__, \ + __func__, format, ##__VA_ARGS__) + +/* The value fine-tuned to accommodate all possible errno message strings. */ +#define _CORE_LOG_MAX_ERRNO_MSG 50 + +#define _CORE_LOG_W_ERRNO(level, format, ...) \ + _CORE_LOG(level, errno, format ": ", ##__VA_ARGS__) + +/* + * Set of macros that should be used as the primary API for logging. + * Direct call to log shall be used only in exceptional, corner cases. + */ +#define CORE_LOG_DEBUG(format, ...) \ + _CORE_LOG(CORE_LOG_LEVEL_DEBUG, NO_ERRNO, format, ##__VA_ARGS__) + +#define CORE_LOG_INFO(format, ...) \ + _CORE_LOG(CORE_LOG_LEVEL_INFO, NO_ERRNO, format, ##__VA_ARGS__) + +#define CORE_LOG_NOTICE(format, ...) \ + _CORE_LOG(CORE_LOG_LEVEL_NOTICE, NO_ERRNO, format, ##__VA_ARGS__) + +#define CORE_LOG_WARNING(format, ...) \ + _CORE_LOG(CORE_LOG_LEVEL_WARNING, NO_ERRNO, format, ##__VA_ARGS__) + +#define CORE_LOG_ERROR(format, ...) \ + _CORE_LOG(CORE_LOG_LEVEL_ERROR, NO_ERRNO, format, ##__VA_ARGS__) + +#define CORE_LOG_FATAL(format, ...) \ + do { \ + _CORE_LOG(CORE_LOG_LEVEL_FATAL, NO_ERRNO, \ + format, ##__VA_ARGS__); \ + abort(); \ + } while (0) + +#define CORE_LOG_HARK(format, ...) \ + _CORE_LOG(CORE_LOG_LEVEL_HARK, NO_ERRNO, format, ##__VA_ARGS__) + +/* + * 'With errno' macros' flavours. Append string describing the current errno + * value. + */ + +#define CORE_LOG_WARNING_W_ERRNO(format, ...) \ + _CORE_LOG_W_ERRNO(CORE_LOG_LEVEL_WARNING, format, ##__VA_ARGS__) + +#define CORE_LOG_ERROR_W_ERRNO(format, ...) \ + _CORE_LOG_W_ERRNO(CORE_LOG_LEVEL_ERROR, format, ##__VA_ARGS__) + +#define CORE_LOG_FATAL_W_ERRNO(format, ...) \ + do { \ + _CORE_LOG_W_ERRNO(CORE_LOG_LEVEL_FATAL, \ + format, ##__VA_ARGS__); \ + abort(); \ + } while (0) + +/* + * 'Last' macros' flavours. Additionally writes the produced error message + * to the last error message's TLS buffer making it available to the end user + * via the *_errormsg() API calls. + */ + +#define CORE_LOG_ERROR_LAST(format, ...) \ + CORE_LOG_TO_LAST(NO_ERRNO, format, ##__VA_ARGS__) + +#define CORE_LOG_ERROR_W_ERRNO_LAST(format, ...) \ + CORE_LOG_TO_LAST(errno, format ": ", ##__VA_ARGS__); + +/* Aliases */ + +#define ERR_W_ERRNO(f, ...)\ + CORE_LOG_ERROR_W_ERRNO_LAST(f, ##__VA_ARGS__) + +#define ERR_WO_ERRNO(f, ...)\ + CORE_LOG_ERROR_LAST(f, ##__VA_ARGS__) + +#ifdef __cplusplus +} +#endif + +#endif /* CORE_LOG_INTERNAL_H */ diff --git a/src/core/out.c b/src/core/out.c index a7f5f6eb340..37a17d8855d 100644 --- a/src/core/out.c +++ b/src/core/out.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2014-2023, Intel Corporation */ +/* Copyright 2014-2024, Intel Corporation */ /* * out.c -- support for logging, tracing, and assertion output @@ -17,112 +17,48 @@ #include "out.h" #include "os.h" -#include "os_thread.h" #include "valgrind_internal.h" #include "util.h" +#include "log_internal.h" +#include "last_error_msg.h" + +#ifdef DEBUG + +#define MAXPRINT 8192 static const char *Log_prefix; static int Log_level; static FILE *Out_fp; static unsigned Log_alignment; -#ifndef NO_LIBPTHREAD -#define MAXPRINT 8192 /* maximum expected log line */ -#else -#define MAXPRINT 256 /* maximum expected log line for libpmem */ -#endif - -struct errormsg -{ - char msg[MAXPRINT]; +static const enum core_log_level level_to_core_log_level[5] = { + [0] = CORE_LOG_LEVEL_HARK, + [1] = CORE_LOG_LEVEL_ERROR, + [2] = CORE_LOG_LEVEL_NOTICE, + [3] = CORE_LOG_LEVEL_INFO, + [4] = CORE_LOG_LEVEL_DEBUG, }; -#ifndef NO_LIBPTHREAD - -static os_once_t Last_errormsg_key_once = OS_ONCE_INIT; -static os_tls_key_t Last_errormsg_key; - -static void -_Last_errormsg_key_alloc(void) -{ - int pth_ret = os_tls_key_create(&Last_errormsg_key, free); - if (pth_ret) - FATAL("!os_thread_key_create"); +static const int core_log_level_to_level[CORE_LOG_LEVEL_MAX] = { + [CORE_LOG_LEVEL_HARK] = 1, + [CORE_LOG_LEVEL_FATAL] = 1, + [CORE_LOG_LEVEL_ERROR] = 1, + [CORE_LOG_LEVEL_WARNING] = 2, + [CORE_LOG_LEVEL_NOTICE] = 2, + [CORE_LOG_LEVEL_INFO] = 3, + [CORE_LOG_LEVEL_DEBUG] = 4, +}; - VALGRIND_ANNOTATE_HAPPENS_BEFORE(&Last_errormsg_key_once); -} +#define OUT_MAX_LEVEL 4 static void -Last_errormsg_key_alloc(void) -{ - os_once(&Last_errormsg_key_once, _Last_errormsg_key_alloc); - /* - * Workaround Helgrind's bug: - * https://bugs.kde.org/show_bug.cgi?id=337735 - */ - VALGRIND_ANNOTATE_HAPPENS_AFTER(&Last_errormsg_key_once); -} - -static inline void -Last_errormsg_fini(void) +out_legacy(enum core_log_level core_level, const char *file_name, + unsigned line_no, const char *function_name, const char *message) { - void *p = os_tls_get(Last_errormsg_key); - if (p) { - free(p); - (void) os_tls_set(Last_errormsg_key, NULL); - } - (void) os_tls_key_delete(Last_errormsg_key); + int level = core_log_level_to_level[core_level]; + out_log(file_name, line_no, function_name, level, "%s", message); } - -static inline struct errormsg * -Last_errormsg_get(void) -{ - Last_errormsg_key_alloc(); - - struct errormsg *errormsg = os_tls_get(Last_errormsg_key); - if (errormsg == NULL) { - errormsg = malloc(sizeof(struct errormsg)); - if (errormsg == NULL) - return NULL; - /* make sure it contains empty string initially */ - errormsg->msg[0] = '\0'; - int ret = os_tls_set(Last_errormsg_key, errormsg); - if (ret) - FATAL("!os_tls_set"); - } - return errormsg; -} - -#else - -/* - * We don't want libpmem to depend on libpthread. Instead of using pthread - * API to dynamically allocate thread-specific error message buffer, we put - * it into TLS. However, keeping a pretty large static buffer (8K) in TLS - * may lead to some issues, so the maximum message length is reduced. - * Fortunately, it looks like the longest error message in libpmem should - * not be longer than about 90 chars (in case of pmem_check_version()). - */ - -static __thread struct errormsg Last_errormsg; - -static inline void -Last_errormsg_key_alloc(void) -{ -} - -static inline void -Last_errormsg_fini(void) -{ -} - -static inline const struct errormsg * -Last_errormsg_get(void) -{ - return &Last_errormsg; -} - -#endif /* NO_LIBPTHREAD */ +#endif /* DEBUG */ /* * out_init -- initialize the log @@ -135,7 +71,8 @@ out_init(const char *log_prefix, const char *log_level_var, int minor_version) { /* suppress unused-parameter errors */ - SUPPRESS_UNUSED(log_level_var, log_file_var); + SUPPRESS_UNUSED(log_prefix, log_level_var, log_file_var, major_version, + minor_version); static int once; @@ -144,19 +81,17 @@ out_init(const char *log_prefix, const char *log_level_var, return; once++; - Log_prefix = log_prefix; - #ifdef DEBUG - char *log_level; - char *log_file; + Log_prefix = log_prefix; - if ((log_level = os_getenv(log_level_var)) != NULL) { - Log_level = atoi(log_level); - if (Log_level < 0) { - Log_level = 0; - } + char *log_alignment = os_getenv("PMDK_LOG_ALIGN"); + if (log_alignment) { + int align = atoi(log_alignment); + if (align > 0) + Log_alignment = (unsigned)align; } + char *log_file; if ((log_file = os_getenv(log_file_var)) != NULL && log_file[0] != '\0') { @@ -166,7 +101,7 @@ out_init(const char *log_prefix, const char *log_level_var, if (len > 0 && log_file[len - 1] == '-') { if (util_snprintf(log_file_pid, PATH_MAX, "%s%d", log_file, getpid()) < 0) { - ERR("snprintf: %d", errno); + ERR_W_ERRNO("snprintf"); abort(); } log_file = log_file_pid; @@ -181,30 +116,52 @@ out_init(const char *log_prefix, const char *log_level_var, abort(); } } -#endif /* DEBUG */ - - char *log_alignment = os_getenv("PMDK_LOG_ALIGN"); - if (log_alignment) { - int align = atoi(log_alignment); - if (align > 0) - Log_alignment = (unsigned)align; - } if (Out_fp == NULL) Out_fp = stderr; else setlinebuf(Out_fp); -#ifdef DEBUG + char *log_level; + int log_level_cropped = 0; + int ret; + + if ((log_level = os_getenv(log_level_var)) != NULL) { + Log_level = atoi(log_level); + if (Log_level < 0) { + Log_level = 0; + } + if (Log_level <= OUT_MAX_LEVEL) { + log_level_cropped = Log_level; + } else { + log_level_cropped = OUT_MAX_LEVEL; + } + } + + if (log_level != NULL) { + ret = core_log_set_threshold(CORE_LOG_THRESHOLD, + level_to_core_log_level[log_level_cropped]); + if (ret) { + CORE_LOG_FATAL("Cannot set log threshold"); + } + } + + if (log_level != NULL || log_file != NULL) { + ret = core_log_set_function(out_legacy); + if (ret) { + CORE_LOG_FATAL("Cannot set legacy log function"); + } + } +/* + * Print library info + */ static char namepath[PATH_MAX]; - LOG(1, "pid %d: program: %s", getpid(), + CORE_LOG_HARK("pid %d: program: %s", getpid(), util_getexecname(namepath, PATH_MAX)); -#endif - LOG(1, "%s version %d.%d", log_prefix, major_version, minor_version); - static __attribute__((used)) const char *version_msg = - "src version: " SRCVERSION; - LOG(1, "%s", version_msg); + CORE_LOG_HARK("%s version %d.%d", log_prefix, major_version, + minor_version); + #if VG_PMEMCHECK_ENABLED /* * Attribute "used" to prevent compiler from optimizing out the variable @@ -212,35 +169,25 @@ out_init(const char *log_prefix, const char *log_level_var, */ static __attribute__((used)) const char *pmemcheck_msg = "compiled with support for Valgrind pmemcheck"; - LOG(1, "%s", pmemcheck_msg); + CORE_LOG_HARK("%s", pmemcheck_msg); #endif /* VG_PMEMCHECK_ENABLED */ #if VG_HELGRIND_ENABLED static __attribute__((used)) const char *helgrind_msg = "compiled with support for Valgrind helgrind"; - LOG(1, "%s", helgrind_msg); + CORE_LOG_HARK("%s", helgrind_msg); #endif /* VG_HELGRIND_ENABLED */ #if VG_MEMCHECK_ENABLED static __attribute__((used)) const char *memcheck_msg = "compiled with support for Valgrind memcheck"; - LOG(1, "%s", memcheck_msg); + CORE_LOG_HARK("%s", memcheck_msg); #endif /* VG_MEMCHECK_ENABLED */ #if VG_DRD_ENABLED static __attribute__((used)) const char *drd_msg = "compiled with support for Valgrind drd"; - LOG(1, "%s", drd_msg); + CORE_LOG_HARK("%s", drd_msg); #endif /* VG_DRD_ENABLED */ -#if SDS_ENABLED - static __attribute__((used)) const char *shutdown_state_msg = - "compiled with support for shutdown state"; - LOG(1, "%s", shutdown_state_msg); -#endif -#if NDCTL_ENABLED - static __attribute__((used)) const char *ndctl_ge_63_msg = - "compiled with libndctl 63+"; - LOG(1, "%s", ndctl_ge_63_msg); -#endif - - Last_errormsg_key_alloc(); +#endif /* DEBUG */ + last_error_msg_init(); } /* @@ -251,16 +198,17 @@ out_init(const char *log_prefix, const char *log_level_var, void out_fini(void) { +#ifdef DEBUG if (Out_fp != NULL && Out_fp != stderr) { fclose(Out_fp); Out_fp = stderr; } - - Last_errormsg_fini(); +#endif } +#ifdef DEBUG /* - * out_print_func -- default print_func, goes to stderr or Out_fp + * out_print_func -- print function, goes to Out_fp (stderr by default) */ static void out_print_func(const char *s) @@ -278,38 +226,6 @@ out_print_func(const char *s) #endif } -/* - * calling Print(s) calls the current print_func... - */ -typedef void (*Print_func)(const char *s); -typedef int (*Vsnprintf_func)(char *str, size_t size, const char *format, - va_list ap); -static Print_func Print = out_print_func; -static Vsnprintf_func Vsnprintf = vsnprintf; - -/* - * out_set_print_func -- allow override of print_func used by out module - */ -void -out_set_print_func(void (*print_func)(const char *s)) -{ - LOG(3, "print %p", print_func); - - Print = (print_func == NULL) ? out_print_func : print_func; -} - -/* - * out_set_vsnprintf_func -- allow override of vsnprintf_func used by out module - */ -void -out_set_vsnprintf_func(int (*vsnprintf_func)(char *str, size_t size, - const char *format, va_list ap)) -{ - LOG(3, "vsnprintf %p", vsnprintf_func); - - Vsnprintf = (vsnprintf_func == NULL) ? vsnprintf : vsnprintf_func; -} - /* * out_snprintf -- (internal) custom snprintf implementation */ @@ -321,7 +237,7 @@ out_snprintf(char *str, size_t size, const char *format, ...) va_list ap; va_start(ap, format); - ret = Vsnprintf(str, size, format, ap); + ret = vsnprintf(str, size, format, ap); va_end(ap); return (ret); @@ -331,7 +247,7 @@ out_snprintf(char *str, size_t size, const char *format, ...) * out_common -- common output code, all output goes through here */ static void -out_common(const char *file, int line, const char *func, int level, +out_common(const char *file, unsigned line, const char *func, int level, const char *suffix, const char *fmt, va_list ap) { int oerrno = errno; @@ -341,17 +257,15 @@ out_common(const char *file, int line, const char *func, int level, const char *sep = ""; char errstr[UTIL_MAX_ERR_MSG] = ""; - unsigned long olast_error = 0; - if (file) { char *f = strrchr(file, OS_DIR_SEPARATOR); if (f) file = f + 1; ret = out_snprintf(&buf[cc], MAXPRINT - cc, - "<%s>: <%d> [%s:%d %s] ", + "<%s>: <%d> [%s:%u %s] ", Log_prefix, level, file, line, func); if (ret < 0) { - Print("out_snprintf failed"); + out_print_func("out_snprintf failed"); goto end; } cc += (unsigned)ret; @@ -365,19 +279,11 @@ out_common(const char *file, int line, const char *func, int level, if (*fmt == '!') { sep = ": "; fmt++; - if (*fmt == '!') { - fmt++; - /* it will abort on non Windows OS */ - util_strwinerror(olast_error, errstr, - UTIL_MAX_ERR_MSG); - } else { - util_strerror(oerrno, errstr, UTIL_MAX_ERR_MSG); - } - + util_strerror(oerrno, errstr, UTIL_MAX_ERR_MSG); } - ret = Vsnprintf(&buf[cc], MAXPRINT - cc, fmt, ap); + ret = vsnprintf(&buf[cc], MAXPRINT - cc, fmt, ap); if (ret < 0) { - Print("Vsnprintf failed"); + out_print_func("vsnprintf failed"); goto end; } cc += (unsigned)ret; @@ -385,181 +291,33 @@ out_common(const char *file, int line, const char *func, int level, out_snprintf(&buf[cc], MAXPRINT - cc, "%s%s%s", sep, errstr, suffix); - Print(buf); + out_print_func(buf); end: errno = oerrno; } /* - * out_error -- common error output code, all error messages go through here + * out_log_va/out_log -- output a log line if Log_level >= level */ static void -out_error(const char *file, int line, const char *func, - const char *suffix, const char *fmt, va_list ap) -{ - int oerrno = errno; - unsigned long olast_error = 0; - unsigned cc = 0; - int ret; - const char *sep = ""; - char errstr[UTIL_MAX_ERR_MSG] = ""; - - char *errormsg = (char *)out_get_errormsg(); - - if (errormsg == NULL) { - Print("There's no memory to properly format error strings."); - return; - } - - if (fmt) { - if (*fmt == '!') { - sep = ": "; - fmt++; - if (*fmt == '!') { - fmt++; - /* it will abort on non Windows OS */ - util_strwinerror(olast_error, errstr, - UTIL_MAX_ERR_MSG); - } else { - util_strerror(oerrno, errstr, UTIL_MAX_ERR_MSG); - } - } - - ret = Vsnprintf(&errormsg[cc], MAXPRINT, fmt, ap); - if (ret < 0) { - strcpy(errormsg, "Vsnprintf failed"); - goto end; - } - cc += (unsigned)ret; - out_snprintf(&errormsg[cc], MAXPRINT - cc, "%s%s", - sep, errstr); - } - -#ifdef DEBUG - if (Log_level >= 1) { - char buf[MAXPRINT]; - cc = 0; - - if (file) { - char *f = strrchr(file, OS_DIR_SEPARATOR); - if (f) - file = f + 1; - ret = out_snprintf(&buf[cc], MAXPRINT, - "<%s>: <1> [%s:%d %s] ", - Log_prefix, file, line, func); - if (ret < 0) { - Print("out_snprintf failed"); - goto end; - } - cc += (unsigned)ret; - if (cc < Log_alignment) { - memset(buf + cc, ' ', Log_alignment - cc); - cc = Log_alignment; - } - } - - out_snprintf(&buf[cc], MAXPRINT - cc, "%s%s", errormsg, - suffix); - - Print(buf); - } -#else - /* suppress unused-parameter errors */ - SUPPRESS_UNUSED(file, line, func, suffix); -#endif - -end: - errno = oerrno; -} - -/* - * out -- output a line, newline added automatically - */ -void -out(const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - - out_common(NULL, 0, NULL, 0, "\n", fmt, ap); - - va_end(ap); -} - -/* - * out_nonl -- output a line, no newline added automatically - */ -void -out_nonl(int level, const char *fmt, ...) +out_log_va(const char *file, unsigned line, const char *func, int level, + const char *fmt, va_list ap) { - va_list ap; - - if (Log_level < level) - return; - - va_start(ap, fmt); - out_common(NULL, 0, NULL, level, "", fmt, ap); - - va_end(ap); -} - -/* - * out_log -- output a log line if Log_level >= level - */ -void -out_log(const char *file, int line, const char *func, int level, - const char *fmt, ...) -{ - va_list ap; - if (Log_level < level) return; - - va_start(ap, fmt); out_common(file, line, func, level, "\n", fmt, ap); - - va_end(ap); } -/* - * out_fatal -- output a fatal error & die (i.e. assertion failure) - */ void -out_fatal(const char *file, int line, const char *func, +out_log(const char *file, unsigned line, const char *func, int level, const char *fmt, ...) { va_list ap; - va_start(ap, fmt); - - out_common(file, line, func, 1, "\n", fmt, ap); - - va_end(ap); - - abort(); -} -/* - * out_err -- output an error message - */ -void -out_err(const char *file, int line, const char *func, - const char *fmt, ...) -{ - va_list ap; va_start(ap, fmt); - - out_error(file, line, func, "\n", fmt, ap); + out_log_va(file, line, func, level, fmt, ap); va_end(ap); } - -/* - * out_get_errormsg -- get the last error message - */ -const char * -out_get_errormsg(void) -{ - const struct errormsg *errormsg = Last_errormsg_get(); - return &errormsg->msg[0]; -} +#endif /* DEBUG */ diff --git a/src/core/out.h b/src/core/out.h index d44c9ca06a6..5fe86565eaa 100644 --- a/src/core/out.h +++ b/src/core/out.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause */ -/* Copyright 2014-2023, Intel Corporation */ +/* Copyright 2014-2024, Intel Corporation */ /* * out.h -- definitions for "out" module @@ -8,10 +8,6 @@ #ifndef PMDK_OUT_H #define PMDK_OUT_H 1 -#include -#include -#include - #include "util.h" #ifdef __cplusplus @@ -19,15 +15,9 @@ extern "C" { #endif /* - * Suppress errors which are after appropriate ASSERT* macro for nondebug + * Suppress errors messages (LOG()) in non-debug version * builds. */ -#if !defined(DEBUG) && (defined(__clang_analyzer__) || defined(__COVERITY__)) -#define OUT_FATAL_DISCARD_NORETURN __attribute__((noreturn)) -#else -#define OUT_FATAL_DISCARD_NORETURN -#endif - #ifndef EVALUATE_DBG_EXPRESSIONS #if defined(DEBUG) || defined(__clang_analyzer__) || defined(__COVERITY__) ||\ defined(__KLOCWORK__) @@ -39,69 +29,22 @@ extern "C" { /* klocwork does not seem to respect __attribute__((noreturn)) */ #if defined(DEBUG) || defined(__KLOCWORK__) - #define OUT_LOG out_log -#define OUT_NONL out_nonl -#define OUT_FATAL out_fatal -#define OUT_FATAL_ABORT out_fatal - #else static __attribute__((always_inline)) inline void -out_log_discard(const char *file, int line, const char *func, int level, +out_log_discard(const char *file, unsigned line, const char *func, int level, const char *fmt, ...) { /* suppress unused-parameter errors */ SUPPRESS_UNUSED(file, line, func, level, fmt); } -static __attribute__((always_inline)) inline void -out_nonl_discard(int level, const char *fmt, ...) -{ - /* suppress unused-parameter errors */ - SUPPRESS_UNUSED(level, fmt); -} - -static __attribute__((always_inline)) OUT_FATAL_DISCARD_NORETURN inline void -out_fatal_discard(const char *file, int line, const char *func, - const char *fmt, ...) -{ - /* suppress unused-parameter errors */ - SUPPRESS_UNUSED(file, line, func, fmt); -} - -static __attribute__((always_inline)) NORETURN inline void -out_fatal_abort(const char *file, int line, const char *func, - const char *fmt, ...) -{ - /* suppress unused-parameter errors */ - SUPPRESS_UNUSED(file, line, func, fmt); - - abort(); -} - #define OUT_LOG out_log_discard -#define OUT_NONL out_nonl_discard -#define OUT_FATAL out_fatal_discard -#define OUT_FATAL_ABORT out_fatal_abort #endif -#if defined(__KLOCWORK__) -#define TEST_ALWAYS_TRUE_EXPR(cnd) -#define TEST_ALWAYS_EQ_EXPR(cnd) -#define TEST_ALWAYS_NE_EXPR(cnd) -#else -#define TEST_ALWAYS_TRUE_EXPR(cnd)\ - if (__builtin_constant_p(cnd))\ - ASSERT_COMPILE_ERROR_ON(cnd); -#define TEST_ALWAYS_EQ_EXPR(lhs, rhs)\ - if (__builtin_constant_p(lhs) && __builtin_constant_p(rhs))\ - ASSERT_COMPILE_ERROR_ON((lhs) == (rhs)); -#define TEST_ALWAYS_NE_EXPR(lhs, rhs)\ - if (__builtin_constant_p(lhs) && __builtin_constant_p(rhs))\ - ASSERT_COMPILE_ERROR_ON((lhs) != (rhs)); -#endif +#if defined(DEBUG) || defined(__KLOCWORK__) /* produce debug/trace output */ #define LOG(level, ...) do { \ @@ -109,100 +52,27 @@ out_fatal_abort(const char *file, int line, const char *func, OUT_LOG(__FILE__, __LINE__, __func__, level, __VA_ARGS__);\ } while (0) -/* produce debug/trace output without prefix and new line */ -#define LOG_NONL(level, ...) do { \ - if (!EVALUATE_DBG_EXPRESSIONS) break; \ - OUT_NONL(level, __VA_ARGS__); \ -} while (0) - -/* produce output and exit */ -#define FATAL(...)\ - OUT_FATAL_ABORT(__FILE__, __LINE__, __func__, __VA_ARGS__) - -/* assert a condition is true at runtime */ -#define ASSERT_rt(cnd) do { \ - if (!EVALUATE_DBG_EXPRESSIONS || (cnd)) break; \ - OUT_FATAL(__FILE__, __LINE__, __func__, "assertion failure: %s", #cnd);\ -} while (0) - -/* assertion with extra info printed if assertion fails at runtime */ -#define ASSERTinfo_rt(cnd, info) do { \ - if (!EVALUATE_DBG_EXPRESSIONS || (cnd)) break; \ - OUT_FATAL(__FILE__, __LINE__, __func__, \ - "assertion failure: %s (%s = %s)", #cnd, #info, info);\ -} while (0) - -/* assert two integer values are equal at runtime */ -#define ASSERTeq_rt(lhs, rhs) do { \ - if (!EVALUATE_DBG_EXPRESSIONS || ((lhs) == (rhs))) break; \ - OUT_FATAL(__FILE__, __LINE__, __func__,\ - "assertion failure: %s (0x%llx) == %s (0x%llx)", #lhs,\ - (unsigned long long)(lhs), #rhs, (unsigned long long)(rhs)); \ -} while (0) - -/* assert two integer values are not equal at runtime */ -#define ASSERTne_rt(lhs, rhs) do { \ - if (!EVALUATE_DBG_EXPRESSIONS || ((lhs) != (rhs))) break; \ - OUT_FATAL(__FILE__, __LINE__, __func__,\ - "assertion failure: %s (0x%llx) != %s (0x%llx)", #lhs,\ - (unsigned long long)(lhs), #rhs, (unsigned long long)(rhs)); \ -} while (0) - -/* assert a condition is true */ -#define ASSERT(cnd)\ - do {\ - /*\ - * Detect useless asserts on always true expression. Please use\ - * COMPILE_ERROR_ON(!cnd) or ASSERT_rt(cnd) in such cases.\ - */\ - TEST_ALWAYS_TRUE_EXPR(cnd);\ - ASSERT_rt(cnd);\ - } while (0) - -/* assertion with extra info printed if assertion fails */ -#define ASSERTinfo(cnd, info)\ - do {\ - /* See comment in ASSERT. */\ - TEST_ALWAYS_TRUE_EXPR(cnd);\ - ASSERTinfo_rt(cnd, info);\ - } while (0) - -/* assert two integer values are equal */ -#define ASSERTeq(lhs, rhs)\ - do {\ - /* See comment in ASSERT. */\ - TEST_ALWAYS_EQ_EXPR(lhs, rhs);\ - ASSERTeq_rt(lhs, rhs);\ - } while (0) - -/* assert two integer values are not equal */ -#define ASSERTne(lhs, rhs)\ - do {\ - /* See comment in ASSERT. */\ - TEST_ALWAYS_NE_EXPR(lhs, rhs);\ - ASSERTne_rt(lhs, rhs);\ +#else +/* + * 'do { ... } while()' is required for a proper interpretation of + * SUPPRESS_UNUSED(__VA_ARGS__) in the context of if() statement + * without brackets {}, especially in the situation when '...' expands + * to more than one argument in '__VA_ARGS__' list + */ +#define LOG(level, ...) do { \ + SUPPRESS_UNUSED(__VA_ARGS__); \ } while (0) - -#define ERR(...)\ - out_err(__FILE__, __LINE__, __func__, __VA_ARGS__) +#endif void out_init(const char *log_prefix, const char *log_level_var, const char *log_file_var, int major_version, int minor_version); void out_fini(void); -void out(const char *fmt, ...) FORMAT_PRINTF(1, 2); -void out_nonl(int level, const char *fmt, ...) FORMAT_PRINTF(2, 3); -void out_log(const char *file, int line, const char *func, int level, - const char *fmt, ...) FORMAT_PRINTF(5, 6); -void out_err(const char *file, int line, const char *func, - const char *fmt, ...) FORMAT_PRINTF(4, 5); -void NORETURN out_fatal(const char *file, int line, const char *func, - const char *fmt, ...) FORMAT_PRINTF(4, 5); -void out_set_print_func(void (*print_func)(const char *s)); -void out_set_vsnprintf_func(int (*vsnprintf_func)(char *str, size_t size, - const char *format, va_list ap)); - -const char *out_get_errormsg(void); + +#ifdef DEBUG +void out_log(const char *file, unsigned line, const char *func, + int level, const char *fmt, ...) FORMAT_PRINTF(5, 6); +#endif #ifdef __cplusplus } diff --git a/src/core/pmemcore.h b/src/core/pmemcore.h index 8291ad1a35e..5f68c308db4 100644 --- a/src/core/pmemcore.h +++ b/src/core/pmemcore.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause */ -/* Copyright 2020, Intel Corporation */ +/* Copyright 2020-2024, Intel Corporation */ /* * pmemcore.h -- definitions for "core" module @@ -10,6 +10,8 @@ #include "util.h" #include "out.h" +#include "last_error_msg.h" +#include "log_internal.h" #ifdef __cplusplus extern "C" { @@ -24,6 +26,7 @@ core_init(const char *log_prefix, const char *log_level_var, int minor_version) { util_init(); + core_log_init(); out_init(log_prefix, log_level_var, log_file_var, major_version, minor_version); } @@ -35,6 +38,8 @@ static inline void core_fini(void) { out_fini(); + core_log_fini(); + last_error_msg_fini(); } #ifdef __cplusplus diff --git a/src/core/pmemcore.inc b/src/core/pmemcore.inc index d701ab0cb97..4b7f36c0f16 100644 --- a/src/core/pmemcore.inc +++ b/src/core/pmemcore.inc @@ -1,4 +1,4 @@ -# Copyright 2020, Intel Corporation +# Copyright 2020-2024, Intel Corporation # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -40,4 +40,8 @@ SOURCE +=\ $(CORE)/ravl.c\ $(CORE)/ravl_interval.c\ $(CORE)/util.c\ - $(CORE)/util_posix.c + $(CORE)/util_posix.c \ + $(CORE)/last_error_msg.c\ + $(CORE)/log.c \ + $(CORE)/log_default.c + diff --git a/src/core/ravl.c b/src/core/ravl.c index a316a60310d..3352a384973 100644 --- a/src/core/ravl.c +++ b/src/core/ravl.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2018-2021, Intel Corporation */ +/* Copyright 2018-2024, Intel Corporation */ /* * ravl.c -- implementation of a RAVL tree @@ -9,7 +9,9 @@ #include #include #include + #include "out.h" +#include "core_assert.h" #include "ravl.h" #include "alloc.h" @@ -46,7 +48,7 @@ ravl_new_sized(ravl_compare *compare, size_t data_size) { struct ravl *r = Malloc(sizeof(*r)); if (r == NULL) { - ERR("!Malloc"); + ERR_W_ERRNO("Malloc"); return r; } @@ -162,7 +164,7 @@ ravl_new_node(struct ravl *ravl, ravl_constr constr, const void *arg) { struct ravl_node *n = Malloc(sizeof(*n) + ravl->data_size); if (n == NULL) { - ERR("!Malloc"); + ERR_W_ERRNO("Malloc"); return n; } diff --git a/src/core/sys_util.h b/src/core/sys_util.h index fbe0c10d632..357ae7b669d 100644 --- a/src/core/sys_util.h +++ b/src/core/sys_util.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause */ -/* Copyright 2016-2020, Intel Corporation */ +/* Copyright 2016-2024, Intel Corporation */ /* * sys_util.h -- internal utility wrappers around system functions @@ -11,7 +11,7 @@ #include #include "os_thread.h" -#include "out.h" +#include "core_assert.h" #ifdef __cplusplus extern "C" { @@ -28,7 +28,7 @@ util_mutex_init(os_mutex_t *m) int tmp = os_mutex_init(m); if (tmp) { errno = tmp; - FATAL("!os_mutex_init"); + CORE_LOG_FATAL_W_ERRNO("os_mutex_init"); } } @@ -43,7 +43,7 @@ util_mutex_destroy(os_mutex_t *m) int tmp = os_mutex_destroy(m); if (tmp) { errno = tmp; - FATAL("!os_mutex_destroy"); + CORE_LOG_FATAL_W_ERRNO("os_mutex_destroy"); } } @@ -58,7 +58,7 @@ util_mutex_lock(os_mutex_t *m) int tmp = os_mutex_lock(m); if (tmp) { errno = tmp; - FATAL("!os_mutex_lock"); + CORE_LOG_FATAL_W_ERRNO("os_mutex_lock"); } } @@ -74,7 +74,7 @@ util_mutex_trylock(os_mutex_t *m) int tmp = os_mutex_trylock(m); if (tmp && tmp != EBUSY) { errno = tmp; - FATAL("!os_mutex_trylock"); + CORE_LOG_FATAL_W_ERRNO("os_mutex_trylock"); } return tmp; } @@ -90,7 +90,7 @@ util_mutex_unlock(os_mutex_t *m) int tmp = os_mutex_unlock(m); if (tmp) { errno = tmp; - FATAL("!os_mutex_unlock"); + CORE_LOG_FATAL_W_ERRNO("os_mutex_unlock"); } } @@ -105,7 +105,7 @@ util_rwlock_init(os_rwlock_t *m) int tmp = os_rwlock_init(m); if (tmp) { errno = tmp; - FATAL("!os_rwlock_init"); + CORE_LOG_FATAL_W_ERRNO("os_rwlock_init"); } } @@ -120,7 +120,7 @@ util_rwlock_rdlock(os_rwlock_t *m) int tmp = os_rwlock_rdlock(m); if (tmp) { errno = tmp; - FATAL("!os_rwlock_rdlock"); + CORE_LOG_FATAL_W_ERRNO("os_rwlock_rdlock"); } } @@ -135,7 +135,7 @@ util_rwlock_wrlock(os_rwlock_t *m) int tmp = os_rwlock_wrlock(m); if (tmp) { errno = tmp; - FATAL("!os_rwlock_wrlock"); + CORE_LOG_FATAL_W_ERRNO("os_rwlock_wrlock"); } } @@ -150,7 +150,7 @@ util_rwlock_unlock(os_rwlock_t *m) int tmp = os_rwlock_unlock(m); if (tmp) { errno = tmp; - FATAL("!os_rwlock_unlock"); + CORE_LOG_FATAL_W_ERRNO("os_rwlock_unlock"); } } @@ -165,7 +165,7 @@ util_rwlock_destroy(os_rwlock_t *m) int tmp = os_rwlock_destroy(m); if (tmp) { errno = tmp; - FATAL("!os_rwlock_destroy"); + CORE_LOG_FATAL_W_ERRNO("os_rwlock_destroy"); } } @@ -178,7 +178,7 @@ util_spin_init(os_spinlock_t *lock, int pshared) int tmp = os_spin_init(lock, pshared); if (tmp) { errno = tmp; - ERR("!os_spin_init"); + ERR_W_ERRNO("os_spin_init"); } return tmp; } @@ -194,7 +194,7 @@ util_spin_destroy(os_spinlock_t *lock) int tmp = os_spin_destroy(lock); if (tmp) { errno = tmp; - FATAL("!os_spin_destroy"); + CORE_LOG_FATAL_W_ERRNO("os_spin_destroy"); } } @@ -208,7 +208,7 @@ util_spin_lock(os_spinlock_t *lock) int tmp = os_spin_lock(lock); if (tmp) { errno = tmp; - FATAL("!os_spin_lock"); + CORE_LOG_FATAL_W_ERRNO("os_spin_lock"); } } @@ -223,7 +223,7 @@ util_spin_unlock(os_spinlock_t *lock) int tmp = os_spin_unlock(lock); if (tmp) { errno = tmp; - FATAL("!os_spin_unlock"); + CORE_LOG_FATAL_W_ERRNO("os_spin_unlock"); } } @@ -236,7 +236,7 @@ static inline void util_semaphore_init(os_semaphore_t *sem, unsigned value) { if (os_semaphore_init(sem, value)) - FATAL("!os_semaphore_init"); + CORE_LOG_FATAL_W_ERRNO("os_semaphore_init"); } /* @@ -246,7 +246,7 @@ static inline void util_semaphore_destroy(os_semaphore_t *sem) { if (os_semaphore_destroy(sem) != 0) - FATAL("!os_semaphore_destroy"); + CORE_LOG_FATAL_W_ERRNO("os_semaphore_destroy"); } /* @@ -263,7 +263,7 @@ util_semaphore_wait(os_semaphore_t *sem) } while (errno == EINTR); /* signal interrupt */ if (ret != 0) - FATAL("!os_semaphore_wait"); + CORE_LOG_FATAL_W_ERRNO("os_semaphore_wait"); } /* @@ -279,7 +279,7 @@ util_semaphore_trywait(os_semaphore_t *sem) } while (errno == EINTR); /* signal interrupt */ if (ret != 0 && errno != EAGAIN) - FATAL("!os_semaphore_trywait"); + CORE_LOG_FATAL_W_ERRNO("os_semaphore_trywait"); return ret; } @@ -291,21 +291,21 @@ static inline void util_semaphore_post(os_semaphore_t *sem) { if (os_semaphore_post(sem) != 0) - FATAL("!os_semaphore_post"); + CORE_LOG_FATAL_W_ERRNO("os_semaphore_post"); } static inline void util_cond_init(os_cond_t *__restrict cond) { if (os_cond_init(cond)) - FATAL("!os_cond_init"); + CORE_LOG_FATAL_W_ERRNO("os_cond_init"); } static inline void util_cond_destroy(os_cond_t *__restrict cond) { if (os_cond_destroy(cond)) - FATAL("!os_cond_destroy"); + CORE_LOG_FATAL_W_ERRNO("os_cond_destroy"); } #ifdef __cplusplus diff --git a/src/core/util.h b/src/core/util.h index 0224aaa774d..179fc9a3f35 100644 --- a/src/core/util.h +++ b/src/core/util.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause */ -/* Copyright 2014-2023, Intel Corporation */ +/* Copyright 2014-2024, Intel Corporation */ /* * Copyright (c) 2016-2020, Microsoft Corporation. All rights reserved. * @@ -101,7 +101,6 @@ int util_snprintf(char *str, size_t size, #define UTIL_MAX_ERR_MSG 128 void util_strerror(int errnum, char *buff, size_t bufflen); -void util_strwinerror(unsigned long err, char *buff, size_t bufflen); void util_set_alloc_funcs( void *(*malloc_func)(size_t size), @@ -320,9 +319,9 @@ char *util_concat_str(const char *s1, const char *s2); #define GLUE_I(A, B) A##B /* macro for suppresing errors from unused variables (up to 9) */ -#define SUPPRESS_UNUSED(...)\ +#define SUPPRESS_UNUSED(...) \ GLUE(SUPPRESS_ARG_, COUNT(__VA_ARGS__))(__VA_ARGS__) -#define SUPPRESS_ARG_1(X) (void) X +#define SUPPRESS_ARG_1(X) (void) (X) #define SUPPRESS_ARG_2(X, ...) SUPPRESS_ARG_1(X); SUPPRESS_ARG_1(__VA_ARGS__) #define SUPPRESS_ARG_3(X, ...) SUPPRESS_ARG_1(X); SUPPRESS_ARG_2(__VA_ARGS__) #define SUPPRESS_ARG_4(X, ...) SUPPRESS_ARG_1(X); SUPPRESS_ARG_3(__VA_ARGS__) diff --git a/src/core/util_posix.c b/src/core/util_posix.c index 4b23400c178..79ab2c63357 100644 --- a/src/core/util_posix.c +++ b/src/core/util_posix.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2015-2023, Intel Corporation */ +/* Copyright 2015-2024, Intel Corporation */ /* * util_posix.c -- Abstraction layer for misc utilities (Posix implementation) @@ -14,6 +14,7 @@ #include #include "os.h" #include "out.h" +#include "core_assert.h" #include "util.h" /* pass through for Posix */ @@ -23,17 +24,6 @@ util_strerror(int errnum, char *buff, size_t bufflen) strerror_r(errnum, buff, bufflen); } -/* - * util_strwinerror -- should never be called on posix OS - abort() - */ -void -util_strwinerror(unsigned long err, char *buff, size_t bufflen) -{ - /* suppress unused-parameter errors */ - SUPPRESS_UNUSED(err, buff, bufflen); - abort(); -} - /* * util_part_realpath -- get canonicalized absolute pathname * @@ -56,20 +46,20 @@ util_compare_file_inodes(const char *path1, const char *path2) struct stat sb1, sb2; if (os_stat(path1, &sb1)) { if (errno != ENOENT) { - ERR("!stat failed for %s", path1); + ERR_W_ERRNO("stat failed for %s", path1); return -1; } - LOG(1, "stat failed for %s", path1); + CORE_LOG_ERROR("stat failed for %s", path1); errno = 0; return strcmp(path1, path2) != 0; } if (os_stat(path2, &sb2)) { if (errno != ENOENT) { - ERR("!stat failed for %s", path2); + ERR_W_ERRNO("stat failed for %s", path2); return -1; } - LOG(1, "stat failed for %s", path2); + CORE_LOG_ERROR("stat failed for %s", path2); errno = 0; return strcmp(path1, path2) != 0; } @@ -106,7 +96,7 @@ util_tmpfile_mkstemp(const char *dir, const char *templ) umask(prev_umask); if (fd < 0) { - ERR("!mkstemp"); + ERR_W_ERRNO("mkstemp"); goto err; } @@ -145,7 +135,7 @@ util_tmpfile(const char *dir, const char *templ, int flags) if (fd >= 0) return fd; if (errno != EOPNOTSUPP) { - ERR("!open"); + ERR_W_ERRNO("open"); return -1; } #endif diff --git a/src/core/valgrind_internal.h b/src/core/valgrind_internal.h index 5e203bb823a..99dc553664a 100644 --- a/src/core/valgrind_internal.h +++ b/src/core/valgrind_internal.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause */ -/* Copyright 2015-2023, Intel Corporation */ +/* Copyright 2015-2024, Intel Corporation */ /* * valgrind_internal.h -- internal definitions for valgrind macros @@ -8,7 +8,7 @@ #ifndef PMDK_VALGRIND_INTERNAL_H #define PMDK_VALGRIND_INTERNAL_H 1 -#if !defined(__FreeBSD__) && !defined(__riscv) && !defined(__loongarch64) +#if !defined(__riscv) && !defined(__loongarch64) #ifndef VALGRIND_ENABLED #define VALGRIND_ENABLED 1 #endif @@ -19,6 +19,11 @@ #define VG_HELGRIND_ENABLED 1 #define VG_MEMCHECK_ENABLED 1 #define VG_DRD_ENABLED 1 +#else +#define VG_PMEMCHECK_ENABLED 0 +#define VG_HELGRIND_ENABLED 0 +#define VG_MEMCHECK_ENABLED 0 +#define VG_DRD_ENABLED 0 #endif #if VG_PMEMCHECK_ENABLED || VG_HELGRIND_ENABLED || VG_MEMCHECK_ENABLED || \ diff --git a/src/examples/Makefile.inc b/src/examples/Makefile.inc index 3481e348a4e..ec9ca1a2e06 100644 --- a/src/examples/Makefile.inc +++ b/src/examples/Makefile.inc @@ -1,5 +1,5 @@ # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2015-2020, Intel Corporation +# Copyright 2015-2024, Intel Corporation # # examples/Makefile.inc -- build the Persistent Memory Development Kit examples @@ -23,6 +23,10 @@ CFLAGS += -fsanitize=$(SANITIZE) CXXFLAGS += -fsanitize=$(SANITIZE) LDFLAGS += -fsanitize=$(SANITIZE) endif +ifeq ($(VALGRIND),0) +CFLAGS += -DVALGRIND_ENABLED=0 +CXXFLAGS += -DVALGRIND_ENABLED=0 +endif INCS = -I$(INCDIR) -I. -I$(TOP_SRC)/examples $(OS_INCS) LIBS += $(OS_LIBS) $(LIBUUID) diff --git a/src/include/libpmem.h b/src/include/libpmem.h index a1201889644..5f075c449c8 100644 --- a/src/include/libpmem.h +++ b/src/include/libpmem.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause */ -/* Copyright 2014-2023, Intel Corporation */ +/* Copyright 2014-2024, Intel Corporation */ /* * libpmem.h -- definitions of libpmem entry points @@ -91,6 +91,79 @@ const char *pmem_check_version(unsigned major_required, const char *pmem_errormsg(void); +/* + * Available log levels. Log levels are used in the logging API calls + * to indicate logging message severity. Log levels are also used + * to define thresholds for the logging. + */ +enum pmem_log_level { + /* only basic library info */ + PMEM_LOG_LEVEL_HARK, + /* an error that causes the program to stop working immediately */ + PMEM_LOG_LEVEL_FATAL, + /* an error that causes the current operation to fail */ + PMEM_LOG_LEVEL_ERROR, + /* + * an unexpected situation that does NOT cause + * the current operation to fail + */ + PMEM_LOG_LEVEL_WARNING, + /* non-massive info mainly related to public API function completions */ + PMEM_LOG_LEVEL_NOTICE, + /* massive info e.g. every write operation indication */ + PMEM_LOG_LEVEL_INFO, + /* debug info e.g. write operation dump */ + PMEM_LOG_LEVEL_DEBUG, +}; + +enum pmem_log_threshold { + /* + * the main threshold level - the logging messages less severe than + * indicated by this threshold's value won't trigger the logging + * functions + */ + PMEM_LOG_THRESHOLD, + /* + * the auxiliary threshold level - may or may not be used by the logging + * function + */ + PMEM_LOG_THRESHOLD_AUX, +}; + +/* + * pmem_log_set_threshold - set the logging threshold value + */ +int pmem_log_set_threshold(enum pmem_log_threshold threshold, + enum pmem_log_level value); + +/* + * pmem_log_get_threshold - get the logging threshold value + */ +int pmem_log_get_threshold(enum pmem_log_threshold threshold, + enum pmem_log_level *value); + +/* + * the type used for defining logging functions + */ +typedef void pmem_log_function( + /* the log level of the message */ + enum pmem_log_level level, + /* name of the source file where the message coming from */ + const char *file_name, + /* the source file line where the message coming from */ + unsigned line_no, + /* the function name where the message coming from */ + const char *function_name, + /* message */ + const char *message); + +#define PMEM_LOG_USE_DEFAULT_FUNCTION (NULL) + +/* + * pmem_log_set_function - set the logging function + */ +int pmem_log_set_function(pmem_log_function *log_function); + #ifdef __cplusplus } #endif diff --git a/src/include/libpmemobj.h b/src/include/libpmemobj.h index e1fd75aa634..d4a5becbb48 100644 --- a/src/include/libpmemobj.h +++ b/src/include/libpmemobj.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause */ -/* Copyright 2014-2020, Intel Corporation */ +/* Copyright 2014-2024, Intel Corporation */ /* * libpmemobj.h -- definitions of libpmemobj entry points @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include diff --git a/src/include/libpmemobj/log.h b/src/include/libpmemobj/log.h new file mode 100644 index 00000000000..96651ccea07 --- /dev/null +++ b/src/include/libpmemobj/log.h @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright 2024, Intel Corporation */ + +/* + * libpmemobj/log.h -- the controls for the libpmemobj's logging output + */ + +#ifndef LIBPMEMOBJ_LOG_H +#define LIBPMEMOBJ_LOG_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Available log levels. Log levels are used in the logging API calls + * to indicate logging message severity. Log levels are also used + * to define thresholds for the logging. + */ +enum pmemobj_log_level { + /* only basic library info */ + PMEMOBJ_LOG_LEVEL_HARK, + /* an error that causes the program to stop working immediately */ + PMEMOBJ_LOG_LEVEL_FATAL, + /* an error that causes the current operation or transaction to fail */ + PMEMOBJ_LOG_LEVEL_ERROR, + /* + * an unexpected situation that does NOT cause + * the current operation to fail + */ + PMEMOBJ_LOG_LEVEL_WARNING, + /* non-massive info mainly related to public API function completions */ + PMEMOBJ_LOG_LEVEL_NOTICE, + /* massive info e.g. every write operation indication */ + PMEMOBJ_LOG_LEVEL_INFO, + /* debug info e.g. write operation dump */ + PMEMOBJ_LOG_LEVEL_DEBUG, +}; + +enum pmemobj_log_threshold { + /* + * the main threshold level - the logging messages less severe than + * indicated by this threshold's value won't trigger the logging + * functions + */ + PMEMOBJ_LOG_THRESHOLD, + /* + * the auxiliary threshold level - may or may not be used by the logging + * function + */ + PMEMOBJ_LOG_THRESHOLD_AUX, +}; + +/* + * pmemobj_log_set_threshold - set the logging threshold value + */ +int pmemobj_log_set_threshold(enum pmemobj_log_threshold threshold, + enum pmemobj_log_level value); + +/* + * pmemobj_log_get_threshold - get the logging threshold value + */ +int pmemobj_log_get_threshold(enum pmemobj_log_threshold threshold, + enum pmemobj_log_level *value); + +/* + * the type used for defining logging functions + */ +typedef void pmemobj_log_function( + /* the log level of the message */ + enum pmemobj_log_level level, + /* name of the source file where the message coming from */ + const char *file_name, + /* the source file line where the message coming from */ + unsigned line_no, + /* the function name where the message coming from */ + const char *function_name, + /* message */ + const char *message); + +#define PMEMOBJ_LOG_USE_DEFAULT_FUNCTION (NULL) + +/* + * pmemobj_log_set_function - set the logging function + */ +int pmemobj_log_set_function(pmemobj_log_function *log_function); + +#ifdef __cplusplus +} +#endif + +#endif /* libpmemobj/log.h */ diff --git a/src/libpmem/Makefile b/src/libpmem/Makefile index 54eda860469..1e0a567128e 100644 --- a/src/libpmem/Makefile +++ b/src/libpmem/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2014-2023, Intel Corporation +# Copyright 2014-2024, Intel Corporation # # src/libpmem/Makefile -- Makefile for libpmem @@ -18,6 +18,9 @@ SOURCE =\ $(CORE)/out.c\ $(CORE)/util.c\ $(CORE)/util_posix.c\ + $(CORE)/last_error_msg.c\ + $(CORE)/log.c\ + $(CORE)/log_default.c\ $(COMMON)/file.c\ $(COMMON)/file_posix.c\ $(COMMON)/mmap.c\ diff --git a/src/libpmem/libpmem.c b/src/libpmem/libpmem.c index e6733fea3c3..865deedf28f 100644 --- a/src/libpmem/libpmem.c +++ b/src/libpmem/libpmem.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2014-2023, Intel Corporation */ +/* Copyright 2014-2024, Intel Corporation */ /* * libpmem.c -- pmem entry points for libpmem @@ -53,15 +53,17 @@ pmem_check_versionU(unsigned major_required, unsigned minor_required) major_required, minor_required); if (major_required != PMEM_MAJOR_VERSION) { - ERR("libpmem major version mismatch (need %u, found %u)", + ERR_WO_ERRNO( + "libpmem major version mismatch (need %u, found %u)", major_required, PMEM_MAJOR_VERSION); - return out_get_errormsg(); + return last_error_msg_get(); } if (minor_required > PMEM_MINOR_VERSION) { - ERR("libpmem minor version mismatch (need %u, found %u)", + ERR_WO_ERRNO( + "libpmem minor version mismatch (need %u, found %u)", minor_required, PMEM_MINOR_VERSION); - return out_get_errormsg(); + return last_error_msg_get(); } return NULL; @@ -77,20 +79,55 @@ pmem_check_version(unsigned major_required, unsigned minor_required) } /* - * pmem_errormsgU -- return last error message + * pmem_errormsgU -- return the last error message */ static inline const char * pmem_errormsgU(void) { - return out_get_errormsg(); + return last_error_msg_get(); } /* - * pmem_errormsg -- return last error message + * pmem_errormsg -- return the last error message */ const char * pmem_errormsg(void) { return pmem_errormsgU(); } + +/* + * pmem_log_set_threshold -- set the logging threshold value + */ +int +pmem_log_set_threshold(enum pmem_log_threshold threshold, + enum pmem_log_level value) +{ + int ret = core_log_set_threshold((enum core_log_threshold)threshold, + (enum core_log_level)value); + return core_log_error_translate(ret); +} + +/* + * pmem_log_get_threshold -- get the logging level threshold value + */ +int +pmem_log_get_threshold(enum pmem_log_threshold threshold, + enum pmem_log_level *value) +{ + int ret = core_log_get_threshold((enum core_log_threshold)threshold, + (enum core_log_level *)value); + return core_log_error_translate(ret); +} + +/* + * pmem_log_set_function -- set the log function pointer either to + * a user-provided function pointer or to the default logging function. + */ +int +pmem_log_set_function(pmem_log_function *log_function) +{ + int ret = core_log_set_function((core_log_function *)log_function); + return core_log_error_translate(ret); +} diff --git a/src/libpmem/libpmem.link.in b/src/libpmem/libpmem.link.in index 16673da952a..7dea4b1a6b8 100644 --- a/src/libpmem/libpmem.link.in +++ b/src/libpmem/libpmem.link.in @@ -1,5 +1,5 @@ # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2014-2019, Intel Corporation +# Copyright 2014-2024, Intel Corporation # # # src/libpmem.link -- linker link file for libpmem @@ -20,6 +20,9 @@ LIBPMEM_1.0 { pmem_has_hw_drain; pmem_check_version; pmem_errormsg; + pmem_log_get_threshold; + pmem_log_set_function; + pmem_log_set_threshold; pmem_memmove_persist; pmem_memcpy_persist; pmem_memset_persist; diff --git a/src/libpmem/pmem.c b/src/libpmem/pmem.c index 9257e9f8d7d..1078d14eec1 100644 --- a/src/libpmem/pmem.c +++ b/src/libpmem/pmem.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2014-2023, Intel Corporation */ +/* Copyright 2014-2024, Intel Corporation */ /* * pmem.c -- pmem entry points for libpmem @@ -277,7 +277,7 @@ pmem_msync(const void *addr, size_t len) int ret; if ((ret = msync((void *)uptr, len, MS_SYNC)) < 0) - ERR("!msync"); + ERR_W_ERRNO("msync"); VALGRIND_DO_ENABLE_ERROR_REPORTING; @@ -359,7 +359,7 @@ pmem_is_pmem_init(void) Is_pmem = is_pmem_never; if (!util_bool_compare_and_swap32(&init, 1, 2)) - FATAL("util_bool_compare_and_swap32"); + CORE_LOG_FATAL("util_bool_compare_and_swap32"); } } @@ -410,14 +410,15 @@ pmem_map_fileU(const char *path, size_t len, int flags, return NULL; if (flags & ~(PMEM_FILE_ALL_FLAGS)) { - ERR("invalid flag specified %x", flags); + ERR_WO_ERRNO("invalid flag specified %x", flags); errno = EINVAL; return NULL; } if (file_type == TYPE_DEVDAX) { if (flags & ~(PMEM_DAX_VALID_FLAGS)) { - ERR("flag unsupported for Device DAX %x", flags); + ERR_WO_ERRNO( + "flag unsupported for Device DAX %x", flags); errno = EINVAL; return NULL; } else { @@ -425,13 +426,13 @@ pmem_map_fileU(const char *path, size_t len, int flags, flags = 0; ssize_t actual_len = util_file_get_size(path); if (actual_len < 0) { - ERR("unable to read Device DAX size"); + ERR_WO_ERRNO("unable to read Device DAX size"); errno = EINVAL; return NULL; } if (len != 0 && len != (size_t)actual_len) { - ERR("Device DAX length must be either 0 or " - "the exact size of the device: %zu", + ERR_WO_ERRNO( + "Device DAX length must be either 0 or the exact size of the device: %zu", actual_len); errno = EINVAL; return NULL; @@ -442,7 +443,7 @@ pmem_map_fileU(const char *path, size_t len, int flags, if (flags & PMEM_FILE_CREATE) { if ((os_off_t)len < 0) { - ERR("invalid file length %zu", len); + ERR_WO_ERRNO("invalid file length %zu", len); errno = EINVAL; return NULL; } @@ -453,19 +454,21 @@ pmem_map_fileU(const char *path, size_t len, int flags, open_flags |= O_EXCL; if ((len != 0) && !(flags & PMEM_FILE_CREATE)) { - ERR("non-zero 'len' not allowed without PMEM_FILE_CREATE"); + ERR_WO_ERRNO( + "non-zero 'len' not allowed without PMEM_FILE_CREATE"); errno = EINVAL; return NULL; } if ((len == 0) && (flags & PMEM_FILE_CREATE)) { - ERR("zero 'len' not allowed with PMEM_FILE_CREATE"); + ERR_WO_ERRNO("zero 'len' not allowed with PMEM_FILE_CREATE"); errno = EINVAL; return NULL; } if ((flags & PMEM_FILE_TMPFILE) && !(flags & PMEM_FILE_CREATE)) { - ERR("PMEM_FILE_TMPFILE not allowed without PMEM_FILE_CREATE"); + ERR_WO_ERRNO( + "PMEM_FILE_TMPFILE not allowed without PMEM_FILE_CREATE"); errno = EINVAL; return NULL; } @@ -474,13 +477,14 @@ pmem_map_fileU(const char *path, size_t len, int flags, if ((fd = util_tmpfile(path, OS_DIR_SEP_STR"pmem.XXXXXX", open_flags & O_EXCL)) < 0) { - LOG(2, "failed to create temporary file at \"%s\"", + CORE_LOG_ERROR( + "failed to create temporary file at \"%s\"", path); return NULL; } } else { if ((fd = os_open(path, open_flags, mode)) < 0) { - ERR("!open %s", path); + ERR_W_ERRNO("open %s", path); return NULL; } if ((flags & PMEM_FILE_CREATE) && (flags & PMEM_FILE_EXCL)) @@ -493,20 +497,20 @@ pmem_map_fileU(const char *path, size_t len, int flags, * (May either extend or truncate existing file.) */ if (os_ftruncate(fd, (os_off_t)len) != 0) { - ERR("!ftruncate"); + ERR_W_ERRNO("ftruncate"); goto err; } if ((flags & PMEM_FILE_SPARSE) == 0) { if ((errno = os_posix_fallocate(fd, 0, (os_off_t)len)) != 0) { - ERR("!posix_fallocate"); + ERR_W_ERRNO("posix_fallocate"); goto err; } } } else { ssize_t actual_size = util_fd_get_size(fd); if (actual_size < 0) { - ERR("stat %s: negative size", path); + ERR_WO_ERRNO("stat %s: negative size", path); errno = EINVAL; goto err; } @@ -573,10 +577,18 @@ pmem_memmove(void *pmemdest, const void *src, size_t len, unsigned flags) LOG(15, "pmemdest %p src %p len %zu flags 0x%x", pmemdest, src, len, flags); +/* + * XXX + * Disable this warning until #5979 is fixed + * https://github.com/pmem/pmdk/issues/5979 + */ +#if 0 #ifdef DEBUG if (flags & ~PMEM_F_MEM_VALID_FLAGS) - ERR("invalid flags 0x%x", flags); + ERR_WO_ERRNO("invalid flags 0x%x", flags); +#endif #endif + PMEM_API_START(); Funcs.memmove_nodrain(pmemdest, src, len, flags & ~PMEM_F_MEM_NODRAIN, Funcs.flush, &Funcs.memmove_funcs); @@ -597,10 +609,17 @@ pmem_memcpy(void *pmemdest, const void *src, size_t len, unsigned flags) LOG(15, "pmemdest %p src %p len %zu flags 0x%x", pmemdest, src, len, flags); +/* + * Disable this warning until #5979 is fixed + * https://github.com/pmem/pmdk/issues/5979 + */ +#if 0 #ifdef DEBUG if (flags & ~PMEM_F_MEM_VALID_FLAGS) - ERR("invalid flags 0x%x", flags); + ERR_WO_ERRNO("invalid flags 0x%x", flags); #endif +#endif + PMEM_API_START(); Funcs.memmove_nodrain(pmemdest, src, len, flags & ~PMEM_F_MEM_NODRAIN, Funcs.flush, &Funcs.memmove_funcs); @@ -621,9 +640,16 @@ pmem_memset(void *pmemdest, int c, size_t len, unsigned flags) LOG(15, "pmemdest %p c 0x%x len %zu flags 0x%x", pmemdest, c, len, flags); +/* + * XXX + * Disable this warning until #5979 is fixed + * https://github.com/pmem/pmdk/issues/5979 + */ +#if 0 #ifdef DEBUG if (flags & ~PMEM_F_MEM_VALID_FLAGS) - ERR("invalid flags 0x%x", flags); + ERR_WO_ERRNO("invalid flags 0x%x", flags); +#endif #endif PMEM_API_START(); @@ -886,7 +912,7 @@ pmem_init(void) if (Funcs.flush == flush_empty) LOG(3, "not flushing CPU cache"); else if (Funcs.flush != Funcs.deep_flush) - FATAL("invalid flush function address"); + CORE_LOG_FATAL("invalid flush function address"); pmem_os_init(&Is_pmem); } diff --git a/src/libpmem/pmem_posix.c b/src/libpmem/pmem_posix.c index d295b13c732..c8c802699de 100644 --- a/src/libpmem/pmem_posix.c +++ b/src/libpmem/pmem_posix.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2014-2019, Intel Corporation */ +/* Copyright 2014-2024, Intel Corporation */ /* * pmem_posix.c -- pmem utilities with Posix implementation @@ -9,7 +9,7 @@ #include #include "pmem.h" -#include "out.h" +#include "log_internal.h" #include "mmap.h" /* @@ -58,7 +58,7 @@ pmem_map_register(int fd, size_t len, const char *path, int is_dev_dax) if (type != MAX_PMEM_TYPE) { if (util_range_register(addr, len, path, type)) { - LOG(1, "can't track mapped region"); + CORE_LOG_ERROR("can't track mapped region"); goto err_unmap; } } diff --git a/src/libpmem2/aarch64/init.c b/src/libpmem2/aarch64/init.c index 6540b0bf70e..d4dd8812b21 100644 --- a/src/libpmem2/aarch64/init.c +++ b/src/libpmem2/aarch64/init.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2014-2021, Intel Corporation */ +/* Copyright 2014-2024, Intel Corporation */ #include #include @@ -85,5 +85,5 @@ pmem2_arch_init(struct pmem2_arch_info *info) else if (info->flush == flush_pop) LOG(3, "Synchronize VA to pop for ARM"); else - FATAL("invalid deep flush function address"); + CORE_LOG_FATAL("invalid deep flush function address"); } diff --git a/src/libpmem2/auto_flush_linux.c b/src/libpmem2/auto_flush_linux.c index ca12e348b4e..738f02742f9 100644 --- a/src/libpmem2/auto_flush_linux.c +++ b/src/libpmem2/auto_flush_linux.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2018-2020, Intel Corporation */ +/* Copyright 2018-2024, Intel Corporation */ /* * auto_flush_linux.c -- Linux auto flush detection @@ -13,6 +13,7 @@ #include #include #include "out.h" +#include "core_assert.h" #include "os.h" #include "fs.h" #include "auto_flush.h" @@ -34,26 +35,26 @@ check_cpu_cache(const char *domain_path) int cpu_cache = 0; if ((domain_fd = os_open(domain_path, O_RDONLY)) < 0) { - LOG(1, "!open(\"%s\", O_RDONLY)", domain_path); + CORE_LOG_ERROR_W_ERRNO("open(\"%s\", O_RDONLY)", + domain_path); goto end; } ssize_t len = read(domain_fd, domain_value, DOMAIN_VALUE_LEN); if (len < 0) { - ERR("!read(%d, %p, %d)", domain_fd, + ERR_W_ERRNO("read(%d, %p, %d)", domain_fd, domain_value, DOMAIN_VALUE_LEN); cpu_cache = -1; goto end; } else if (len == 0) { errno = EIO; - ERR("read(%d, %p, %d) empty string", - domain_fd, domain_value, - DOMAIN_VALUE_LEN); + ERR_WO_ERRNO("read(%d, %p, %d) empty string", + domain_fd, domain_value, DOMAIN_VALUE_LEN); cpu_cache = -1; goto end; } else if (domain_value[len - 1] != '\n') { - ERR("!read(%d, %p, %d) invalid format", + ERR_W_ERRNO("read(%d, %p, %d) invalid format", domain_fd, domain_value, DOMAIN_VALUE_LEN); cpu_cache = -1; @@ -92,7 +93,7 @@ check_domain_in_region(const char *region_path) reg = fs_new(region_path); if (reg == NULL) { - ERR("!fs_new: \"%s\"", region_path); + ERR_W_ERRNO("fs_new: \"%s\"", region_path); cpu_cache = -1; goto end; } @@ -112,7 +113,7 @@ check_domain_in_region(const char *region_path) int ret = util_snprintf(domain_path, PATH_MAX, "%s/"PERSISTENCE_DOMAIN, region_path); if (ret < 0) { - ERR("!snprintf"); + ERR_W_ERRNO("snprintf"); cpu_cache = -1; goto end; } @@ -153,7 +154,7 @@ pmem2_auto_flush(void) struct fs *dev = fs_new(device_path); if (dev == NULL) { - ERR("!fs_new: \"%s\"", device_path); + ERR_W_ERRNO("fs_new: \"%s\"", device_path); return -1; } diff --git a/src/libpmem2/badblocks.c b/src/libpmem2/badblocks.c index e126f3e2955..e39304b2959 100644 --- a/src/libpmem2/badblocks.c +++ b/src/libpmem2/badblocks.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2018-2020, Intel Corporation */ +/* Copyright 2018-2024, Intel Corporation */ /* * badblocks.c -- implementation of common bad blocks API @@ -8,6 +8,7 @@ #include "badblocks.h" #include "alloc.h" #include "out.h" +#include "log_internal.h" /* * badblocks_new -- zalloc bad blocks structure @@ -19,7 +20,7 @@ badblocks_new(void) struct badblocks *bbs = Zalloc(sizeof(struct badblocks)); if (bbs == NULL) { - ERR("!Zalloc"); + ERR_W_ERRNO("Zalloc"); } return bbs; diff --git a/src/libpmem2/badblocks_ndctl.c b/src/libpmem2/badblocks_ndctl.c index d9e988d46a2..c7a8b4dd582 100644 --- a/src/libpmem2/badblocks_ndctl.c +++ b/src/libpmem2/badblocks_ndctl.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2017-2022, Intel Corporation */ +/* Copyright 2017-2024, Intel Corporation */ /* * badblocks_ndctl.c -- implementation of DIMMs API based on the ndctl library @@ -16,7 +16,6 @@ #include #include #include -#include #include "libpmem2.h" #include "pmem2_utils.h" @@ -115,13 +114,14 @@ badblocks_get_namespace_bounds(struct ndctl_region *region, if (pfn) { *ns_offset = ndctl_pfn_get_resource(pfn); if (*ns_offset == ULLONG_MAX) { - ERR("(pfn) cannot read offset of the namespace"); + ERR_WO_ERRNO( + "(pfn) cannot read offset of the namespace"); return PMEM2_E_CANNOT_READ_BOUNDS; } *ns_size = ndctl_pfn_get_size(pfn); if (*ns_size == ULLONG_MAX) { - ERR("(pfn) cannot read size of the namespace"); + ERR_WO_ERRNO("(pfn) cannot read size of the namespace"); return PMEM2_E_CANNOT_READ_BOUNDS; } @@ -130,13 +130,14 @@ badblocks_get_namespace_bounds(struct ndctl_region *region, } else if (dax) { *ns_offset = ndctl_dax_get_resource(dax); if (*ns_offset == ULLONG_MAX) { - ERR("(dax) cannot read offset of the namespace"); + ERR_WO_ERRNO( + "(dax) cannot read offset of the namespace"); return PMEM2_E_CANNOT_READ_BOUNDS; } *ns_size = ndctl_dax_get_size(dax); if (*ns_size == ULLONG_MAX) { - ERR("(dax) cannot read size of the namespace"); + ERR_WO_ERRNO("(dax) cannot read size of the namespace"); return PMEM2_E_CANNOT_READ_BOUNDS; } @@ -145,13 +146,15 @@ badblocks_get_namespace_bounds(struct ndctl_region *region, } else { /* raw or btt */ *ns_offset = ndctl_namespace_get_resource(ndns); if (*ns_offset == ULLONG_MAX) { - ERR("(raw/btt) cannot read offset of the namespace"); + ERR_WO_ERRNO( + "(raw/btt) cannot read offset of the namespace"); return PMEM2_E_CANNOT_READ_BOUNDS; } *ns_size = ndctl_namespace_get_size(ndns); if (*ns_size == ULLONG_MAX) { - ERR("(raw/btt) cannot read size of the namespace"); + ERR_WO_ERRNO( + "(raw/btt) cannot read size of the namespace"); return PMEM2_E_CANNOT_READ_BOUNDS; } @@ -161,7 +164,7 @@ badblocks_get_namespace_bounds(struct ndctl_region *region, unsigned long long region_offset = ndctl_region_get_resource(region); if (region_offset == ULLONG_MAX) { - ERR("!cannot read offset of the region"); + ERR_W_ERRNO("cannot read offset of the region"); return PMEM2_E_ERRNO; } @@ -188,14 +191,14 @@ badblocks_devdax_clear_one_badblock(struct ndctl_bus *bus, struct ndctl_cmd *cmd_ars_cap = ndctl_bus_cmd_new_ars_cap(bus, address, length); if (cmd_ars_cap == NULL) { - ERR("ndctl_bus_cmd_new_ars_cap() failed (bus '%s')", + ERR_WO_ERRNO("ndctl_bus_cmd_new_ars_cap() failed (bus '%s')", ndctl_bus_get_provider(bus)); return PMEM2_E_ERRNO; } ret = ndctl_cmd_submit(cmd_ars_cap); if (ret) { - ERR("ndctl_cmd_submit() failed (bus '%s')", + ERR_WO_ERRNO("ndctl_cmd_submit() failed (bus '%s')", ndctl_bus_get_provider(bus)); /* ndctl_cmd_submit() returns -errno */ goto out_ars_cap; @@ -204,7 +207,7 @@ badblocks_devdax_clear_one_badblock(struct ndctl_bus *bus, struct ndctl_range range; ret = ndctl_cmd_ars_cap_get_range(cmd_ars_cap, &range); if (ret) { - ERR("ndctl_cmd_ars_cap_get_range() failed"); + ERR_WO_ERRNO("ndctl_cmd_ars_cap_get_range() failed"); /* ndctl_cmd_ars_cap_get_range() returns -errno */ goto out_ars_cap; } @@ -214,7 +217,7 @@ badblocks_devdax_clear_one_badblock(struct ndctl_bus *bus, ret = ndctl_cmd_submit(cmd_clear_error); if (ret) { - ERR("ndctl_cmd_submit() failed (bus '%s')", + ERR_WO_ERRNO("ndctl_cmd_submit() failed (bus '%s')", ndctl_bus_get_provider(bus)); /* ndctl_cmd_submit() returns -errno */ goto out_clear_error; @@ -227,7 +230,7 @@ badblocks_devdax_clear_one_badblock(struct ndctl_bus *bus, ASSERT(cleared <= length); if (cleared < length) { - ERR("failed to clear %llu out of %llu bad blocks", + ERR_WO_ERRNO("failed to clear %llu out of %llu bad blocks", length - cleared, length); errno = ENXIO; /* ndctl handles such error in this way */ ret = PMEM2_E_ERRNO; @@ -256,7 +259,7 @@ pmem2_badblock_context_new(struct pmem2_badblock_context **bbctx, ASSERTne(bbctx, NULL); if (src->type == PMEM2_SOURCE_ANON) { - ERR("Anonymous source does not support bad blocks"); + ERR_WO_ERRNO("Anonymous source does not support bad blocks"); return PMEM2_E_NOSUPP; } @@ -272,7 +275,7 @@ pmem2_badblock_context_new(struct pmem2_badblock_context **bbctx, errno = ndctl_new(&ctx) * (-1); if (errno) { - ERR("!ndctl_new"); + ERR_W_ERRNO("ndctl_new"); return PMEM2_E_ERRNO; } @@ -280,7 +283,7 @@ pmem2_badblock_context_new(struct pmem2_badblock_context **bbctx, ret = pmem2_region_namespace(ctx, src, ®ion, &ndns); if (ret) { - LOG(1, "getting region and namespace failed"); + CORE_LOG_ERROR("getting region and namespace failed"); goto exit_ndctl_unref; } @@ -310,7 +313,7 @@ pmem2_badblock_context_new(struct pmem2_badblock_context **bbctx, region, ndns, &ns_beg, &ns_size); if (ret) { - LOG(1, "cannot read namespace's bounds"); + CORE_LOG_ERROR("cannot read namespace's bounds"); goto error_free_all; } @@ -335,7 +338,7 @@ pmem2_badblock_context_new(struct pmem2_badblock_context **bbctx, /* only regular files have extents */ ret = pmem2_extents_create_get(src->value.fd, &tbbctx->exts); if (ret) { - LOG(1, "getting extents of fd %i failed", + CORE_LOG_ERROR("getting extents of fd %i failed", src->value.fd); goto error_free_all; } @@ -547,7 +550,8 @@ pmem2_badblock_next(struct pmem2_badblock_context *bbctx, int ret; if (bbctx->rgn.region == NULL && bbctx->ndns == NULL) { - ERR("Cannot find any matching device, no bad blocks found"); + ERR_WO_ERRNO( + "Cannot find any matching device, no bad blocks found"); return PMEM2_E_NO_BAD_BLOCK_FOUND; } @@ -687,13 +691,13 @@ pmem2_badblock_clear_fsdax(int fd, const struct pmem2_badblock *bb) /* fallocate() takes offset as the off_t type */ if (bb->offset > (size_t)INT64_MAX) { - ERR("bad block's offset is greater than INT64_MAX"); + ERR_WO_ERRNO("bad block's offset is greater than INT64_MAX"); return PMEM2_E_OFFSET_OUT_OF_RANGE; } /* fallocate() takes length as the off_t type */ if (bb->length > (size_t)INT64_MAX) { - ERR("bad block's length is greater than INT64_MAX"); + ERR_WO_ERRNO("bad block's length is greater than INT64_MAX"); return PMEM2_E_LENGTH_OUT_OF_RANGE; } @@ -703,13 +707,13 @@ pmem2_badblock_clear_fsdax(int fd, const struct pmem2_badblock *bb) /* deallocate bad blocks */ if (fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, offset, length)) { - ERR("!fallocate"); + ERR_W_ERRNO("fallocate"); return PMEM2_E_ERRNO; } /* allocate new blocks */ if (fallocate(fd, FALLOC_FL_KEEP_SIZE, offset, length)) { - ERR("!fallocate"); + ERR_W_ERRNO("fallocate"); return PMEM2_E_ERRNO; } @@ -739,7 +743,7 @@ pmem2_badblock_clear_devdax(const struct pmem2_badblock_context *bbctx, bb->offset + bbctx->rgn.ns_res, bb->length); if (ret) { - LOG(1, + CORE_LOG_ERROR( "failed to clear a bad block: offset %zu length %zu (in 512B sectors)", B2SEC(bb->offset), B2SEC(bb->length)); diff --git a/src/libpmem2/config.c b/src/libpmem2/config.c index 3795b3e3959..959c3644d90 100644 --- a/src/libpmem2/config.c +++ b/src/libpmem2/config.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2019-2023, Intel Corporation */ +/* Copyright 2019-2024, Intel Corporation */ /* * config.c -- pmem2_config implementation @@ -77,7 +77,7 @@ pmem2_config_set_required_store_granularity(struct pmem2_config *cfg, case PMEM2_GRANULARITY_PAGE: break; default: - ERR("unknown granularity value %d", g); + ERR_WO_ERRNO("unknown granularity value %d", g); return PMEM2_E_GRANULARITY_NOT_SUPPORTED; } @@ -96,7 +96,7 @@ pmem2_config_set_offset(struct pmem2_config *cfg, size_t offset) /* mmap func takes offset as a type of off_t */ if (offset > (size_t)INT64_MAX) { - ERR("offset is greater than INT64_MAX"); + ERR_WO_ERRNO("offset is greater than INT64_MAX"); return PMEM2_E_OFFSET_OUT_OF_RANGE; } @@ -129,19 +129,19 @@ pmem2_config_validate_length(const struct pmem2_config *cfg, ASSERTne(alignment, 0); if (file_len == 0) { - ERR("file length is equal 0"); + ERR_WO_ERRNO("file length is equal 0"); return PMEM2_E_SOURCE_EMPTY; } if (cfg->length % alignment) { - ERR("length is not a multiple of %lu", alignment); + ERR_WO_ERRNO("length is not a multiple of %lu", alignment); return PMEM2_E_LENGTH_UNALIGNED; } /* overflow check */ const size_t end = cfg->offset + cfg->length; if (end < cfg->offset) { - ERR("overflow of offset and length"); + ERR_WO_ERRNO("overflow of offset and length"); return PMEM2_E_MAP_RANGE; } @@ -149,7 +149,7 @@ pmem2_config_validate_length(const struct pmem2_config *cfg, * Validate the file size to be sure the mapping will fit in the file. */ if (end > file_len) { - ERR("mapping larger than file size"); + ERR_WO_ERRNO("mapping larger than file size"); return PMEM2_E_MAP_RANGE; } @@ -170,7 +170,7 @@ pmem2_config_set_sharing(struct pmem2_config *cfg, enum pmem2_sharing_type type) cfg->sharing = type; break; default: - ERR("unknown sharing value %d", type); + ERR_WO_ERRNO("unknown sharing value %d", type); return PMEM2_E_INVALID_SHARING_VALUE; } @@ -206,7 +206,7 @@ pmem2_config_set_protection(struct pmem2_config *cfg, unsigned unknown_prot = prot & ~(PMEM2_PROT_READ | PMEM2_PROT_WRITE | PMEM2_PROT_EXEC | PMEM2_PROT_NONE); if (unknown_prot) { - ERR("invalid flag %u", prot); + ERR_WO_ERRNO("invalid flag %u", prot); return PMEM2_E_INVALID_PROT_FLAG; } diff --git a/src/libpmem2/deep_flush.c b/src/libpmem2/deep_flush.c index 585772ae1e1..f31aa7b8ec1 100644 --- a/src/libpmem2/deep_flush.c +++ b/src/libpmem2/deep_flush.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2020, Intel Corporation */ +/* Copyright 2024, Intel Corporation */ /* * deep_flush.c -- pmem2_deep_flush implementation @@ -27,14 +27,16 @@ pmem2_deep_flush(struct pmem2_map *map, void *ptr, size_t size) uintptr_t flush_end = flush_addr + size; if (flush_addr < map_addr || flush_end > map_end) { - ERR("requested deep flush rage ptr %p size %zu" - "exceeds map range %p", ptr, size, map); + ERR_WO_ERRNO( + "requested deep flush rage ptr %p size %zu exceeds map range %p", + ptr, size, map); return PMEM2_E_DEEP_FLUSH_RANGE; } int ret = map->deep_flush_fn(map, ptr, size); if (ret) { - LOG(1, "cannot perform deep flush operation for map %p", map); + CORE_LOG_ERROR( + "cannot perform deep flush operation for map %p", map); return ret; } diff --git a/src/libpmem2/deep_flush_linux.c b/src/libpmem2/deep_flush_linux.c index 567174b4253..df625db08cf 100644 --- a/src/libpmem2/deep_flush_linux.c +++ b/src/libpmem2/deep_flush_linux.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2020, Intel Corporation */ +/* Copyright 2020-2024, Intel Corporation */ /* * deep_flush_linux.c -- deep_flush functionality @@ -34,17 +34,18 @@ pmem2_deep_flush_write(unsigned region_id) if (util_snprintf(deep_flush_path, PATH_MAX, "/sys/bus/nd/devices/region%u/deep_flush", region_id) < 0) { - ERR("!snprintf"); + ERR_W_ERRNO("snprintf"); return PMEM2_E_ERRNO; } if ((deep_flush_fd = os_open(deep_flush_path, O_RDONLY)) < 0) { - LOG(1, "!os_open(\"%s\", O_RDONLY)", deep_flush_path); + CORE_LOG_ERROR_W_ERRNO("os_open(\"%s\", O_RDONLY)", + deep_flush_path); return 0; } if (read(deep_flush_fd, rbuf, sizeof(rbuf)) != 2) { - LOG(1, "!read(%d)", deep_flush_fd); + CORE_LOG_ERROR_W_ERRNO("read(%d)", deep_flush_fd); goto end; } @@ -56,13 +57,14 @@ pmem2_deep_flush_write(unsigned region_id) os_close(deep_flush_fd); if ((deep_flush_fd = os_open(deep_flush_path, O_WRONLY)) < 0) { - LOG(1, "Cannot open deep_flush file %s to write", + CORE_LOG_ERROR("Cannot open deep_flush file %s to write", deep_flush_path); return 0; } if (write(deep_flush_fd, "1", 1) != 1) { - LOG(1, "Cannot write to deep_flush file %d", deep_flush_fd); + CORE_LOG_ERROR("Cannot write to deep_flush file %d", + deep_flush_fd); goto end; } @@ -98,7 +100,7 @@ pmem2_deep_flush_dax(struct pmem2_map *map, void *ptr, size_t size) ret = pmem2_flush_file_buffers_os(map, ptr, size, 0); if (ret) { - LOG(1, "cannot flush buffers addr %p len %zu", + CORE_LOG_ERROR("cannot flush buffers addr %p len %zu", ptr, size); return ret; } @@ -106,13 +108,14 @@ pmem2_deep_flush_dax(struct pmem2_map *map, void *ptr, size_t size) unsigned region_id; int ret = pmem2_get_region_id(&map->source, ®ion_id); if (ret < 0) { - LOG(1, "cannot find region id for dev %lu", + CORE_LOG_ERROR("cannot find region id for dev %lu", map->source.value.st_rdev); return ret; } ret = pmem2_deep_flush_write(region_id); if (ret) { - LOG(1, "cannot write to deep_flush file for region %d", + CORE_LOG_ERROR( + "cannot write to deep_flush file for region %d", region_id); return ret; } diff --git a/src/libpmem2/deep_flush_other.c b/src/libpmem2/deep_flush_other.c index ec5067c2819..b1aaa5a2ee5 100644 --- a/src/libpmem2/deep_flush_other.c +++ b/src/libpmem2/deep_flush_other.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2020-2021, Intel Corporation */ +/* Copyright 2020-2024, Intel Corporation */ /* * deep_flush_other.c -- deep_flush functionality @@ -23,7 +23,8 @@ pmem2_deep_flush_dax(struct pmem2_map *map, void *ptr, size_t size) { int ret = pmem2_flush_file_buffers_os(map, ptr, size, 0); if (ret) { - LOG(1, "cannot flush buffers addr %p len %zu", ptr, size); + CORE_LOG_ERROR("cannot flush buffers addr %p len %zu", ptr, + size); return ret; } @@ -40,7 +41,7 @@ pmem2_deep_flush_write(unsigned region_id) SUPPRESS_UNUSED(region_id); const char *err = "BUG: pmem2_deep_flush_write should never be called on this OS"; - ERR("%s", err); + ERR_WO_ERRNO("%s", err); ASSERTinfo(0, err); /* not supported */ diff --git a/src/libpmem2/errormsg.c b/src/libpmem2/errormsg.c index ba1ac8f9136..48303b43adf 100644 --- a/src/libpmem2/errormsg.c +++ b/src/libpmem2/errormsg.c @@ -1,26 +1,28 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2019-2023, Intel Corporation */ +/* Copyright 2019-2024, Intel Corporation */ /* * errormsg.c -- pmem2_errormsg* implementation */ +#include + #include "libpmem2.h" #include "out.h" #include "pmem2_utils.h" /* - * pmem2_errormsgU -- return last error message + * pmem2_errormsgU -- return the last error message */ static inline const char * pmem2_errormsgU(void) { - return out_get_errormsg(); + return last_error_msg_get(); } /* - * pmem2_errormsg -- return last error message + * pmem2_errormsg -- return the last error message */ const char * pmem2_errormsg(void) diff --git a/src/libpmem2/extent_linux.c b/src/libpmem2/extent_linux.c index 6491e67b6fb..3202b614e58 100644 --- a/src/libpmem2/extent_linux.c +++ b/src/libpmem2/extent_linux.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2018-2020, Intel Corporation */ +/* Copyright 2018-2024, Intel Corporation */ /* * extent_linux.c - implementation of the linux fs extent query API @@ -37,7 +37,7 @@ pmem2_extents_create_get(int fd, struct extents **exts) os_stat_t st; if (os_fstat(fd, &st) < 0) { - ERR("!fstat %d", fd); + ERR_W_ERRNO("fstat %d", fd); return PMEM2_E_ERRNO; } @@ -47,7 +47,7 @@ pmem2_extents_create_get(int fd, struct extents **exts) /* directories do not have any extents */ if (pmem2_type == PMEM2_FTYPE_DIR) { - ERR( + ERR_WO_ERRNO( "checking extents does not make sense in case of directories"); return PMEM2_E_INVALID_FILE_TYPE; } @@ -80,7 +80,7 @@ pmem2_extents_create_get(int fd, struct extents **exts) fmap->fm_mapped_extents = 0; if (ioctl(fd, FS_IOC_FIEMAP, fmap) != 0) { - ERR("!fiemap ioctl() for fd=%d failed", fd); + ERR_W_ERRNO("fiemap ioctl() for fd=%d failed", fd); ret = PMEM2_E_ERRNO; goto error_free; } @@ -99,7 +99,7 @@ pmem2_extents_create_get(int fd, struct extents **exts) fmap->fm_mapped_extents = 0; if (ioctl(fd, FS_IOC_FIEMAP, fmap) != 0) { - ERR("!fiemap ioctl() for fd=%d failed", fd); + ERR_W_ERRNO("fiemap ioctl() for fd=%d failed", fd); ret = PMEM2_E_ERRNO; goto error_free; } diff --git a/src/libpmem2/map.c b/src/libpmem2/map.c index 1e02ee1f753..de729b58a9c 100644 --- a/src/libpmem2/map.c +++ b/src/libpmem2/map.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2019-2023, Intel Corporation */ +/* Copyright 2019-2024, Intel Corporation */ /* * map.c -- pmem2_map (common) @@ -70,7 +70,8 @@ parse_force_granularity() char str[11]; /* strlen("CACHE_LINE") + 1 */ if (util_safe_strcpy(str, ptr, sizeof(str))) { - LOG(1, "Invalid value of PMEM2_FORCE_GRANULARITY"); + CORE_LOG_ERROR( + "Invalid value of PMEM2_FORCE_GRANULARITY"); return PMEM2_GRANULARITY_INVALID; } @@ -90,7 +91,7 @@ parse_force_granularity() return PMEM2_GRANULARITY_PAGE; } - LOG(1, "Invalid value of PMEM2_FORCE_GRANULARITY"); + CORE_LOG_ERROR("Invalid value of PMEM2_FORCE_GRANULARITY"); } return PMEM2_GRANULARITY_INVALID; } @@ -125,7 +126,7 @@ pmem2_validate_offset(const struct pmem2_config *cfg, size_t *offset, { ASSERTne(alignment, 0); if (cfg->offset % alignment) { - ERR("offset is not a multiple of %lu", alignment); + ERR_WO_ERRNO("offset is not a multiple of %lu", alignment); return PMEM2_E_OFFSET_UNALIGNED; } @@ -213,7 +214,7 @@ pmem2_unregister_mapping(struct pmem2_map *map) util_rwlock_wrlock(&State.range_map_lock); node = ravl_interval_find_equal(State.range_map, map); if (!(node && !ravl_interval_remove(State.range_map, node))) { - ERR("Cannot find mapping %p to delete", map); + ERR_WO_ERRNO("Cannot find mapping %p to delete", map); ret = PMEM2_E_MAPPING_NOT_FOUND; } @@ -274,7 +275,7 @@ pmem2_map_from_existing(struct pmem2_map **map_ptr, ret = pmem2_register_mapping(map); if (ret) { if (ret == -EEXIST) { - ERR( + ERR_WO_ERRNO( "Provided mapping(addr %p len %zu) is already registered by libpmem2", addr, len); ret = PMEM2_E_MAP_EXISTS; diff --git a/src/libpmem2/map_posix.c b/src/libpmem2/map_posix.c index 9e232fc2614..afaf1c1f549 100644 --- a/src/libpmem2/map_posix.c +++ b/src/libpmem2/map_posix.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2019-2023, Intel Corporation */ +/* Copyright 2019-2024, Intel Corporation */ /* * map_posix.c -- pmem2_map (POSIX) @@ -129,10 +129,10 @@ map_reserve(size_t len, size_t alignment, void **reserv, size_t *reslen, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (daddr == MAP_FAILED) { if (errno == EEXIST) { - ERR("!mmap MAP_FIXED_NOREPLACE"); + ERR_W_ERRNO("mmap MAP_FIXED_NOREPLACE"); return PMEM2_E_MAPPING_EXISTS; } - ERR("!mmap MAP_ANONYMOUS"); + ERR_W_ERRNO("mmap MAP_ANONYMOUS"); return PMEM2_E_ERRNO; } @@ -170,7 +170,7 @@ map_reserve(size_t len, size_t alignment, void **reserv, size_t *reslen, const size_t before = (uintptr_t)(*reserv) - (uintptr_t)daddr; if (before) { if (munmap(daddr, before)) { - ERR("!munmap"); + ERR_W_ERRNO("munmap"); return PMEM2_E_ERRNO; } } @@ -180,7 +180,7 @@ map_reserve(size_t len, size_t alignment, void **reserv, size_t *reslen, void *end = (void *)((uintptr_t)(*reserv) + (uintptr_t)*reslen); if (after) if (munmap(end, after)) { - ERR("!munmap"); + ERR_W_ERRNO("munmap"); return PMEM2_E_ERRNO; } @@ -212,7 +212,7 @@ file_map(void *reserv, size_t len, int proto, int flags, if (flags & MAP_PRIVATE) { *base = mmap(reserv, len, proto, flags, fd, offset); if (*base == MAP_FAILED) { - ERR("!mmap"); + ERR_W_ERRNO("mmap"); return PMEM2_E_ERRNO; } LOG(4, "mmap with MAP_PRIVATE succeeded"); @@ -240,7 +240,7 @@ file_map(void *reserv, size_t len, int proto, int flags, } } - ERR("!mmap"); + ERR_W_ERRNO("mmap"); return PMEM2_E_ERRNO; } @@ -252,7 +252,7 @@ unmap(void *addr, size_t len) { int retval = munmap(addr, len); if (retval < 0) { - ERR("!munmap"); + ERR_W_ERRNO("munmap"); return PMEM2_E_ERRNO; } @@ -266,16 +266,19 @@ unmap(void *addr, size_t len) static int vm_reservation_mend(struct pmem2_vm_reservation *rsv, void *addr, size_t size) { +#ifdef DEBUG /* variables required for ASSERTs below */ void *rsv_addr = pmem2_vm_reservation_get_address(rsv); size_t rsv_size = pmem2_vm_reservation_get_size(rsv); - +#else + SUPPRESS_UNUSED(rsv); +#endif ASSERT((char *)addr >= (char *)rsv_addr && (char *)addr + size <= (char *)rsv_addr + rsv_size); char *daddr = mmap(addr, size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); if (daddr == MAP_FAILED) { - ERR("!mmap MAP_ANONYMOUS"); + ERR_W_ERRNO("mmap MAP_ANONYMOUS"); return PMEM2_E_ERRNO; } @@ -298,7 +301,7 @@ pmem2_map_new(struct pmem2_map **map_ptr, const struct pmem2_config *cfg, *map_ptr = NULL; if (cfg->requested_max_granularity == PMEM2_GRANULARITY_INVALID) { - ERR( + ERR_WO_ERRNO( "please define the max granularity requested for the mapping"); return PMEM2_E_GRANULARITY_NOT_SET; @@ -348,7 +351,8 @@ pmem2_map_new(struct pmem2_map **map_ptr, const struct pmem2_config *cfg, if (src->type == PMEM2_SOURCE_FD) { if (src->value.ftype == PMEM2_FTYPE_DIR) { - ERR("the directory is not a supported file type"); + ERR_WO_ERRNO( + "the directory is not a supported file type"); return PMEM2_E_INVALID_FILE_TYPE; } @@ -357,8 +361,8 @@ pmem2_map_new(struct pmem2_map **map_ptr, const struct pmem2_config *cfg, if (cfg->sharing == PMEM2_PRIVATE && src->value.ftype == PMEM2_FTYPE_DEVDAX) { - ERR( - "device DAX does not support mapping with MAP_PRIVATE"); + ERR_WO_ERRNO( + "device DAX does not support mapping with MAP_PRIVATE"); return PMEM2_E_SRC_DEVDAX_PRIVATE; } } @@ -387,27 +391,26 @@ pmem2_map_new(struct pmem2_map **map_ptr, const struct pmem2_config *cfg, if (rsv_offset % Mmap_align) { ret = PMEM2_E_OFFSET_UNALIGNED; - ERR( + ERR_WO_ERRNO( "virtual memory reservation offset %zu is not a multiple of %llu", - rsv_offset, Mmap_align); + rsv_offset, Mmap_align); return ret; } if (rsv_offset + reserved_length > rsv_size) { ret = PMEM2_E_LENGTH_OUT_OF_RANGE; - ERR( + ERR_WO_ERRNO( "Reservation %p has not enough space for the intended content", - rsv); + rsv); return ret; } reserv_region = (char *)rsv_addr + rsv_offset; if ((size_t)reserv_region % alignment) { ret = PMEM2_E_ADDRESS_UNALIGNED; - ERR( - "base mapping address %p (virtual memory reservation address + offset)" \ - " is not a multiple of %zu required by device DAX", - reserv_region, alignment); + ERR_WO_ERRNO( + "base mapping address %p (virtual memory reservation address + offset) is not a multiple of %zu required by device DAX", + reserv_region, alignment); return ret; } @@ -415,9 +418,8 @@ pmem2_map_new(struct pmem2_map **map_ptr, const struct pmem2_config *cfg, if (vm_reservation_map_find_acquire(rsv, rsv_offset, reserved_length)) { ret = PMEM2_E_MAPPING_EXISTS; - ERR( - "region of the reservation %p at the offset %zu and " - "length %zu is at least partly occupied by other mapping", + ERR_WO_ERRNO( + "region of the reservation %p at the offset %zu and length %zu is at least partly occupied by other mapping", rsv, rsv_offset, reserved_length); goto err_reservation_release; } @@ -430,10 +432,10 @@ pmem2_map_new(struct pmem2_map **map_ptr, const struct pmem2_config *cfg, &reserved_length, cfg); if (ret != 0) { if (ret == PMEM2_E_MAPPING_EXISTS) - LOG(1, + CORE_LOG_ERROR( "given mapping region is already occupied"); else - LOG(1, + CORE_LOG_ERROR( "cannot find a contiguous region of given size"); return ret; } @@ -485,12 +487,12 @@ pmem2_map_new(struct pmem2_map **map_ptr, const struct pmem2_config *cfg, [cfg->requested_max_granularity] [available_min_granularity]; if (strcmp(err, GRAN_IMPOSSIBLE) == 0) - FATAL( + CORE_LOG_FATAL( "unhandled granularity error: available_min_granularity: %d" \ "requested_max_granularity: %d", available_min_granularity, cfg->requested_max_granularity); - ERR("%s", err); + ERR_WO_ERRNO("%s", err); ret = PMEM2_E_GRANULARITY_NOT_SUPPORTED; goto err_undo_mapping; } diff --git a/src/libpmem2/mcsafe_ops_posix.c b/src/libpmem2/mcsafe_ops_posix.c index 4fe76d7cca8..72a913ba3e8 100644 --- a/src/libpmem2/mcsafe_ops_posix.c +++ b/src/libpmem2/mcsafe_ops_posix.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2021-2022, Intel Corporation */ +/* Copyright 2021-2024, Intel Corporation */ #include #include @@ -46,12 +46,12 @@ mcsafe_op_reg_read(struct pmem2_source *src, void *buf, size_t size, ssize_t retsize = pread(fd, buf, size, (off_t)offset); if (retsize == -1) { if (errno == EIO) { - ERR("physical I/O error occurred on read operation, " - "possible bad block"); + ERR_WO_ERRNO( + "physical I/O error occurred on read operation, possible bad block"); return PMEM2_E_IO_FAIL; } - ERR("!pread"); + ERR_W_ERRNO("pread"); return PMEM2_E_ERRNO; } @@ -72,12 +72,12 @@ mcsafe_op_reg_write(struct pmem2_source *src, void *buf, size_t size, ssize_t retsize = pwrite(fd, buf, size, (off_t)offset); if (retsize == -1) { if (errno == EIO) { - ERR("physical I/O error occurred on write operation, " - "possible bad block"); + ERR_WO_ERRNO( + "physical I/O error occurred on write operation, possible bad block"); return PMEM2_E_IO_FAIL; } - ERR("!pwrite"); + ERR_W_ERRNO("pwrite"); return PMEM2_E_ERRNO; } @@ -126,7 +126,7 @@ handle_sigbus_execute_mcsafe_op(struct pmem2_source *src, void *buf, struct sigaction old_act; /* register a custom signal handler */ if (sigaction(SIGBUS, &custom_act, &old_act) == -1) { - ERR("!sigaction"); + ERR_W_ERRNO("sigaction"); return PMEM2_E_ERRNO; } @@ -134,7 +134,7 @@ handle_sigbus_execute_mcsafe_op(struct pmem2_source *src, void *buf, /* sigsetjmp returns nonzero only when returning from siglongjmp */ if (sigsetjmp(mcsafe_jmp_buf, 1)) { - ERR("physical I/O error occurred, possible bad block"); + ERR_WO_ERRNO("physical I/O error occurred, possible bad block"); ret = PMEM2_E_IO_FAIL; goto clnup_null_global_jmp; } @@ -149,7 +149,7 @@ handle_sigbus_execute_mcsafe_op(struct pmem2_source *src, void *buf, /* restore the previous signal handler */ if (sigaction(SIGBUS, &old_act, NULL) == -1) { - ERR("!sigaction"); + ERR_W_ERRNO("sigaction"); return PMEM2_E_ERRNO; } @@ -163,7 +163,6 @@ static int devdax_read(struct pmem2_source *src, void *buf, size_t size, size_t offset) { int ret; - int clnup_ret; struct pmem2_config *cfg; struct pmem2_map *map; @@ -186,11 +185,13 @@ devdax_read(struct pmem2_source *src, void *buf, size_t size, size_t offset) memcpy_fn(buf, ADDR_SUM(addr, offset), size, 0); - clnup_ret = pmem2_map_delete(&map); +#ifdef DEBUG /* variables required for ASSERTs below */ + int clnup_ret = +#endif + pmem2_map_delete(&map); ASSERTeq(clnup_ret, 0); clnup_cfg_delete: - clnup_ret = pmem2_config_delete(&cfg); - ASSERTeq(clnup_ret, 0); + pmem2_config_delete(&cfg); return ret; } @@ -202,7 +203,6 @@ static int devdax_write(struct pmem2_source *src, void *buf, size_t size, size_t offset) { int ret; - int clnup_ret; struct pmem2_config *cfg; struct pmem2_map *map; @@ -225,11 +225,13 @@ devdax_write(struct pmem2_source *src, void *buf, size_t size, size_t offset) memcpy_fn(ADDR_SUM(addr, offset), buf, size, 0); - clnup_ret = pmem2_map_delete(&map); +#ifdef DEBUG /* variables required for ASSERTs below */ + int clnup_ret = +#endif + pmem2_map_delete(&map); ASSERTeq(clnup_ret, 0); clnup_cfg_delete: - clnup_ret = pmem2_config_delete(&cfg); - ASSERTeq(clnup_ret, 0); + pmem2_config_delete(&cfg); return ret; } @@ -274,9 +276,8 @@ static int pmem2_source_type_check_mcsafe_supp(struct pmem2_source *src) { if (src->type != PMEM2_SOURCE_FD && src->type != PMEM2_SOURCE_HANDLE) { - ERR("operation doesn't support provided source type, only "\ - "sources created from file descriptor or file handle "\ - "are supported"); + ERR_WO_ERRNO( + "operation doesn't support provided source type, only sources created from file descriptor or file handle are supported"); return PMEM2_E_SOURCE_TYPE_NOT_SUPPORTED; } @@ -297,8 +298,9 @@ pmem2_source_check_op_size(struct pmem2_source *src, size_t size, size_t offset) size_t max_size = (size_t)(src_size - offset); if (size > max_size) { - ERR("size of read %zu from offset %zu goes beyond the file " - "length %zu", size, offset, max_size); + ERR_WO_ERRNO( + "size of read %zu from offset %zu goes beyond the file length %zu", + size, offset, max_size); return PMEM2_E_LENGTH_OUT_OF_RANGE; } diff --git a/src/libpmem2/numa_ndctl.c b/src/libpmem2/numa_ndctl.c index 80d3f508008..9359a531342 100644 --- a/src/libpmem2/numa_ndctl.c +++ b/src/libpmem2/numa_ndctl.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2020, Intel Corporation */ +/* Copyright 2024, Intel Corporation */ #include #include @@ -25,7 +25,7 @@ pmem2_source_numa_node(const struct pmem2_source *src, int *numa_node) struct ndctl_region *region = NULL; if (src->type == PMEM2_SOURCE_ANON) { - ERR("Anonymous sources are not bound to numa nodes."); + ERR_WO_ERRNO("Anonymous sources are not bound to numa nodes."); return PMEM2_E_NOSUPP; } @@ -33,18 +33,18 @@ pmem2_source_numa_node(const struct pmem2_source *src, int *numa_node) errno = ndctl_new(&ctx) * (-1); if (errno) { - ERR("!ndctl_new"); + ERR_W_ERRNO("ndctl_new"); return PMEM2_E_ERRNO; } int ret = pmem2_region_namespace(ctx, src, ®ion, NULL); if (ret < 0) { - LOG(1, "getting region failed"); + CORE_LOG_ERROR("getting region failed"); goto end; } if (region == NULL) { - ERR("unknown region"); + ERR_WO_ERRNO("unknown region"); ret = PMEM2_E_DAX_REGION_NOT_FOUND; goto end; } diff --git a/src/libpmem2/numa_none.c b/src/libpmem2/numa_none.c index 941d696ed1e..fed528dda23 100644 --- a/src/libpmem2/numa_none.c +++ b/src/libpmem2/numa_none.c @@ -1,8 +1,9 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2020-2021, Intel Corporation */ +/* Copyright 2020-2024, Intel Corporation */ #include "libpmem2.h" -#include "out.h" +#include "util.h" +#include "log_internal.h" #include "source.h" /* @@ -13,7 +14,8 @@ int pmem2_source_numa_node(const struct pmem2_source *src, int *numa_node) { SUPPRESS_UNUSED(src, numa_node); - ERR("Cannot get numa node from source - ndctl is not available"); + ERR_WO_ERRNO( + "Cannot get numa node from source - ndctl is not available"); return PMEM2_E_NOSUPP; } diff --git a/src/libpmem2/persist.c b/src/libpmem2/persist.c index d54d69b61ec..b9281089958 100644 --- a/src/libpmem2/persist.c +++ b/src/libpmem2/persist.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2019-2022, Intel Corporation */ +/* Copyright 2019-2024, Intel Corporation */ /* * persist.c -- pmem2_get_[persist|flush|drain]_fn @@ -31,7 +31,7 @@ memmove_nodrain_libc(void *pmemdest, const void *src, size_t len, { #ifdef DEBUG if (flags & ~PMEM2_F_MEM_VALID_FLAGS) - ERR("invalid flags 0x%x", flags); + ERR_WO_ERRNO("invalid flags 0x%x", flags); #endif LOG(15, "pmemdest %p src %p len %zu flags 0x%x", pmemdest, src, len, flags); @@ -55,7 +55,7 @@ memset_nodrain_libc(void *pmemdest, int c, size_t len, unsigned flags, { #ifdef DEBUG if (flags & ~PMEM2_F_MEM_VALID_FLAGS) - ERR("invalid flags 0x%x", flags); + ERR_WO_ERRNO("invalid flags 0x%x", flags); #endif LOG(15, "pmemdest %p c 0x%x len %zu flags 0x%x", pmemdest, c, len, flags); @@ -322,7 +322,8 @@ pmem2_deep_flush_cache(struct pmem2_map *map, void *ptr, size_t size) int ret = pmem2_deep_flush_dax(map, ptr, size); if (ret < 0) { - LOG(1, "cannot perform deep flush cache for map %p", map); + CORE_LOG_ERROR( + "cannot perform deep flush cache for map %p", map); return ret; } @@ -338,7 +339,7 @@ pmem2_deep_flush_byte(struct pmem2_map *map, void *ptr, size_t size) LOG(3, "map %p ptr %p size %zu", map, ptr, size); if (map->source.type == PMEM2_SOURCE_ANON) { - ERR("Anonymous source does not support deep flush"); + ERR_WO_ERRNO("Anonymous source does not support deep flush"); return PMEM2_E_NOSUPP; } @@ -356,7 +357,8 @@ pmem2_deep_flush_byte(struct pmem2_map *map, void *ptr, size_t size) int ret = pmem2_deep_flush_dax(map, ptr, size); if (ret < 0) { - LOG(1, "cannot perform deep flush byte for map %p", map); + CORE_LOG_ERROR("cannot perform deep flush byte for map %p", + map); return ret; } @@ -436,7 +438,7 @@ pmem2_memmove_nonpmem(void *pmemdest, const void *src, size_t len, { #ifdef DEBUG if (flags & ~PMEM2_F_MEM_VALID_FLAGS) - ERR("invalid flags 0x%x", flags); + ERR_WO_ERRNO("invalid flags 0x%x", flags); #endif PMEM2_API_START("pmem2_memmove"); Info.memmove_nodrain(pmemdest, src, len, @@ -458,7 +460,7 @@ pmem2_memset_nonpmem(void *pmemdest, int c, size_t len, unsigned flags) { #ifdef DEBUG if (flags & ~PMEM2_F_MEM_VALID_FLAGS) - ERR("invalid flags 0x%x", flags); + ERR_WO_ERRNO("invalid flags 0x%x", flags); #endif PMEM2_API_START("pmem2_memset"); Info.memset_nodrain(pmemdest, c, len, @@ -481,7 +483,7 @@ pmem2_memmove(void *pmemdest, const void *src, size_t len, { #ifdef DEBUG if (flags & ~PMEM2_F_MEM_VALID_FLAGS) - ERR("invalid flags 0x%x", flags); + ERR_WO_ERRNO("invalid flags 0x%x", flags); #endif PMEM2_API_START("pmem2_memmove"); Info.memmove_nodrain(pmemdest, src, len, flags, Info.flush, @@ -501,7 +503,7 @@ pmem2_memset(void *pmemdest, int c, size_t len, unsigned flags) { #ifdef DEBUG if (flags & ~PMEM2_F_MEM_VALID_FLAGS) - ERR("invalid flags 0x%x", flags); + ERR_WO_ERRNO("invalid flags 0x%x", flags); #endif PMEM2_API_START("pmem2_memset"); Info.memset_nodrain(pmemdest, c, len, flags, Info.flush, @@ -522,7 +524,7 @@ pmem2_memmove_eadr(void *pmemdest, const void *src, size_t len, { #ifdef DEBUG if (flags & ~PMEM2_F_MEM_VALID_FLAGS) - ERR("invalid flags 0x%x", flags); + ERR_WO_ERRNO("invalid flags 0x%x", flags); #endif PMEM2_API_START("pmem2_memmove"); Info.memmove_nodrain_eadr(pmemdest, src, len, flags, Info.flush, @@ -542,7 +544,7 @@ pmem2_memset_eadr(void *pmemdest, int c, size_t len, unsigned flags) { #ifdef DEBUG if (flags & ~PMEM2_F_MEM_VALID_FLAGS) - ERR("invalid flags 0x%x", flags); + ERR_WO_ERRNO("invalid flags 0x%x", flags); #endif PMEM2_API_START("pmem2_memset"); Info.memset_nodrain_eadr(pmemdest, c, len, flags, Info.flush, diff --git a/src/libpmem2/persist_posix.c b/src/libpmem2/persist_posix.c index d36f0969ce4..52938a482d4 100644 --- a/src/libpmem2/persist_posix.c +++ b/src/libpmem2/persist_posix.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2019-2021, Intel Corporation */ +/* Copyright 2019-2024, Intel Corporation */ /* * persist_posix.c -- POSIX-specific part of persist implementation @@ -37,7 +37,7 @@ pmem2_flush_file_buffers_os(struct pmem2_map *map, const void *addr, size_t len, ret = msync((void *)addr, len, MS_SYNC); if (ret < 0) { - ERR("!msync"); + ERR_W_ERRNO("msync"); } else { /* full flush */ VALGRIND_DO_PERSIST((uintptr_t)addr, len); diff --git a/src/libpmem2/pmem2_arch.h b/src/libpmem2/pmem2_arch.h index e14dec4598e..f0bf232d80e 100644 --- a/src/libpmem2/pmem2_arch.h +++ b/src/libpmem2/pmem2_arch.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause */ -/* Copyright 2014-2022, Intel Corporation */ +/* Copyright 2014-2024, Intel Corporation */ /* * pmem2_arch.h -- core-arch interface @@ -8,9 +8,11 @@ #define PMEM2_ARCH_H #include + #include "libpmem2.h" #include "util.h" #include "valgrind_internal.h" +#include "out.h" #ifdef __cplusplus extern "C" { diff --git a/src/libpmem2/pmem2_utils.c b/src/libpmem2/pmem2_utils.c index 6f06b1b6236..19cfc5c9c56 100644 --- a/src/libpmem2/pmem2_utils.c +++ b/src/libpmem2/pmem2_utils.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2019-2023, Intel Corporation */ +/* Copyright 2019-2024, Intel Corporation */ /* * pmem2_utils.c -- libpmem2 utilities functions @@ -22,7 +22,7 @@ pmem2_malloc(size_t size, int *err) *err = 0; if (ptr == NULL) { - ERR("!malloc(%zu)", size); + ERR_W_ERRNO("malloc(%zu)", size); *err = PMEM2_E_ERRNO; } @@ -39,7 +39,7 @@ pmem2_zalloc(size_t size, int *err) *err = 0; if (ptr == NULL) { - ERR("!malloc(%zu)", size); + ERR_W_ERRNO("malloc(%zu)", size); *err = PMEM2_E_ERRNO; } @@ -56,7 +56,7 @@ pmem2_realloc(void *ptr, size_t size, int *err) *err = 0; if (newptr == NULL) { - ERR("!realloc(%zu)", size); + ERR_W_ERRNO("realloc(%zu)", size); *err = PMEM2_E_ERRNO; } @@ -67,7 +67,7 @@ int pmem2_err_to_errno(int err) { if (err > 0) - FATAL("positive error code is a bug in libpmem2"); + CORE_LOG_FATAL("positive error code is a bug in libpmem2"); if (err == PMEM2_E_NOSUPP) return ENOTSUP; diff --git a/src/libpmem2/pmem2_utils.h b/src/libpmem2/pmem2_utils.h index 39654d1adf4..43f7b211615 100644 --- a/src/libpmem2/pmem2_utils.h +++ b/src/libpmem2/pmem2_utils.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause */ -/* Copyright 2019-2023, Intel Corporation */ +/* Copyright 2019-2024, Intel Corporation */ /* * pmem2_utils.h -- libpmem2 utilities functions @@ -11,14 +11,15 @@ #include #include "os.h" -#include "out.h" +#include "core_assert.h" +#include "last_error_msg.h" #include "source.h" static inline int pmem2_assert_errno(void) { if (!errno) { - ERR("errno is not set"); + ERR_WO_ERRNO("errno is not set"); ASSERTinfo(0, "errno is not set"); return -EINVAL; } @@ -32,7 +33,7 @@ pmem2_assert_errno(void) #define PMEM2_ERR_CLR() \ {\ errno = 0;\ - char *errormsg = (char *)out_get_errormsg();\ + char *errormsg = (char *)last_error_msg_get();\ strcpy(errormsg, "\0");\ } #else diff --git a/src/libpmem2/pmem2_utils_linux.c b/src/libpmem2/pmem2_utils_linux.c index 9352ea51f69..94a63fb4ccb 100644 --- a/src/libpmem2/pmem2_utils_linux.c +++ b/src/libpmem2/pmem2_utils_linux.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2014-2023, Intel Corporation */ +/* Copyright 2014-2024, Intel Corporation */ #include #include @@ -40,7 +40,8 @@ pmem2_get_type_from_stat(const os_stat_t *st, enum pmem2_file_type *type) } if (!S_ISCHR(st->st_mode)) { - ERR("file type 0%o not supported", st->st_mode & S_IFMT); + ERR_WO_ERRNO("file type 0%o not supported", + st->st_mode & S_IFMT); return PMEM2_E_INVALID_FILE_TYPE; } @@ -50,7 +51,7 @@ pmem2_get_type_from_stat(const os_stat_t *st, enum pmem2_file_type *type) os_minor(st->st_rdev)); if (ret < 0) { /* impossible */ - ERR("!snprintf"); + ERR_W_ERRNO("snprintf"); ASSERTinfo(0, "snprintf failed"); return PMEM2_E_ERRNO; } @@ -60,7 +61,7 @@ pmem2_get_type_from_stat(const os_stat_t *st, enum pmem2_file_type *type) char npath[PATH_MAX]; char *rpath = realpath(spath, npath); if (rpath == NULL) { - ERR("!realpath \"%s\"", spath); + ERR_W_ERRNO("realpath \"%s\"", spath); return PMEM2_E_ERRNO; } diff --git a/src/libpmem2/pmem2_utils_ndctl.c b/src/libpmem2/pmem2_utils_ndctl.c index fed82306378..b51aeedff95 100644 --- a/src/libpmem2/pmem2_utils_ndctl.c +++ b/src/libpmem2/pmem2_utils_ndctl.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2020, Intel Corporation */ +/* Copyright 2020-2024, Intel Corporation */ #include #include @@ -24,13 +24,13 @@ pmem2_device_dax_alignment(const struct pmem2_source *src, size_t *alignment) errno = ndctl_new(&ctx) * (-1); if (errno) { - ERR("!ndctl_new"); + ERR_W_ERRNO("ndctl_new"); return PMEM2_E_ERRNO; } ret = pmem2_region_namespace(ctx, src, NULL, &ndns); if (ret) { - LOG(1, "getting region and namespace failed"); + CORE_LOG_ERROR("getting region and namespace failed"); goto end; } @@ -63,13 +63,13 @@ pmem2_device_dax_size(const struct pmem2_source *src, size_t *size) errno = ndctl_new(&ctx) * (-1); if (errno) { - ERR("!ndctl_new"); + ERR_W_ERRNO("ndctl_new"); return PMEM2_E_ERRNO; } ret = pmem2_region_namespace(ctx, src, NULL, &ndns); if (ret) { - LOG(1, "getting region and namespace failed"); + CORE_LOG_ERROR("getting region and namespace failed"); goto end; } @@ -79,8 +79,8 @@ pmem2_device_dax_size(const struct pmem2_source *src, size_t *size) *size = ndctl_dax_get_size(dax); } else { ret = PMEM2_E_DAX_REGION_NOT_FOUND; - ERR("Issue while reading Device Dax size - cannot " - "find dax region"); + ERR_WO_ERRNO( + "Issue while reading Device Dax size - cannot find dax region"); } end: diff --git a/src/libpmem2/pmem2_utils_none.c b/src/libpmem2/pmem2_utils_none.c index 0863c7dbe11..5dac1801184 100644 --- a/src/libpmem2/pmem2_utils_none.c +++ b/src/libpmem2/pmem2_utils_none.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2020-2022, Intel Corporation */ +/* Copyright 2020-2024, Intel Corporation */ #include @@ -17,7 +17,8 @@ pmem2_device_dax_alignment(const struct pmem2_source *src, size_t *alignment) { SUPPRESS_UNUSED(src, alignment); - ERR("Cannot read Device Dax alignment - ndctl is not available"); + ERR_WO_ERRNO( + "Cannot read Device Dax alignment - ndctl is not available"); return PMEM2_E_NOSUPP; } @@ -31,7 +32,7 @@ pmem2_device_dax_size(const struct pmem2_source *src, size_t *size) { SUPPRESS_UNUSED(src, size); - ERR("Cannot read Device Dax size - ndctl is not available"); + ERR_WO_ERRNO("Cannot read Device Dax size - ndctl is not available"); return PMEM2_E_NOSUPP; } diff --git a/src/libpmem2/pmem2_utils_other.c b/src/libpmem2/pmem2_utils_other.c index 6b2c140187a..efbc7b65cd2 100644 --- a/src/libpmem2/pmem2_utils_other.c +++ b/src/libpmem2/pmem2_utils_other.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2014-2023, Intel Corporation */ +/* Copyright 2014-2024, Intel Corporation */ #include #include @@ -21,7 +21,7 @@ pmem2_get_type_from_stat(const os_stat_t *st, enum pmem2_file_type *type) return 0; } - ERR("file type 0%o not supported", st->st_mode & S_IFMT); + ERR_WO_ERRNO("file type 0%o not supported", st->st_mode & S_IFMT); return PMEM2_E_INVALID_FILE_TYPE; } @@ -35,7 +35,7 @@ pmem2_device_dax_size(const struct pmem2_source *src, size_t *size) SUPPRESS_UNUSED(src, size); const char *err = "BUG: pmem2_device_dax_size should never be called on this OS"; - ERR("%s", err); + ERR_WO_ERRNO("%s", err); ASSERTinfo(0, err); return PMEM2_E_NOSUPP; } @@ -50,7 +50,7 @@ pmem2_device_dax_alignment(const struct pmem2_source *src, size_t *alignment) SUPPRESS_UNUSED(src, alignment); const char *err = "BUG: pmem2_device_dax_alignment should never be called on this OS"; - ERR("%s", err); + ERR_WO_ERRNO("%s", err); ASSERTinfo(0, err); return PMEM2_E_NOSUPP; } diff --git a/src/libpmem2/region_namespace_ndctl.c b/src/libpmem2/region_namespace_ndctl.c index 675f82d61cd..03aa85a214b 100644 --- a/src/libpmem2/region_namespace_ndctl.c +++ b/src/libpmem2/region_namespace_ndctl.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2020-2023, Intel Corporation */ +/* Copyright 2020-2024, Intel Corporation */ /* * region_namespace_ndctl.c -- common ndctl functions @@ -39,12 +39,12 @@ pmem2_devdax_match(dev_t st_rdev, const char *devname) os_stat_t stat; if (util_snprintf(path, PATH_MAX, "/dev/%s", devname) < 0) { - ERR("!snprintf"); + ERR_W_ERRNO("snprintf"); return PMEM2_E_ERRNO; } if (os_stat(path, &stat)) { - ERR("!stat %s", path); + ERR_W_ERRNO("stat %s", path); return PMEM2_E_ERRNO; } @@ -77,26 +77,26 @@ pmem2_fsdax_match(dev_t st_dev, const char *devname) char dev_id[BUFF_LENGTH]; if (util_snprintf(path, PATH_MAX, "/sys/block/%s/dev", devname) < 0) { - ERR("!snprintf"); + ERR_W_ERRNO("snprintf"); return PMEM2_E_ERRNO; } if (util_snprintf(dev_id, BUFF_LENGTH, "%d:%d", major(st_dev), minor(st_dev)) < 0) { - ERR("!snprintf"); + ERR_W_ERRNO("snprintf"); return PMEM2_E_ERRNO; } int fd = os_open(path, O_RDONLY); if (fd < 0) { - ERR("!open \"%s\"", path); + ERR_W_ERRNO("open \"%s\"", path); return PMEM2_E_ERRNO; } char buff[BUFF_LENGTH]; ssize_t nread = read(fd, buff, BUFF_LENGTH); if (nread < 0) { - ERR("!read"); + ERR_W_ERRNO("read"); int oerrno = errno; /* save the errno */ os_close(fd); errno = oerrno; @@ -106,12 +106,12 @@ pmem2_fsdax_match(dev_t st_dev, const char *devname) os_close(fd); if (nread == 0) { - ERR("%s is empty", path); + ERR_WO_ERRNO("%s is empty", path); return PMEM2_E_INVALID_DEV_FORMAT; } if (buff[nread - 1] != '\n') { - ERR("%s doesn't end with new line", path); + ERR_WO_ERRNO("%s doesn't end with new line", path); return PMEM2_E_INVALID_DEV_FORMAT; } @@ -152,7 +152,7 @@ pmem2_region_namespace(struct ndctl_ctx *ctx, *pndns = NULL; if (src->value.ftype == PMEM2_FTYPE_DIR) { - ERR("cannot check region or namespace of a directory"); + ERR_WO_ERRNO("cannot check region or namespace of a directory"); return PMEM2_E_INVALID_FILE_TYPE; } @@ -170,7 +170,7 @@ pmem2_region_namespace(struct ndctl_ctx *ctx, struct daxctl_region *dax_region; dax_region = ndctl_dax_get_daxctl_region(dax); if (!dax_region) { - ERR("!cannot find dax region"); + ERR_W_ERRNO("cannot find dax region"); return PMEM2_E_DAX_REGION_NOT_FOUND; } struct daxctl_dev *dev; @@ -239,18 +239,18 @@ pmem2_get_region_id(const struct pmem2_source *src, unsigned *region_id) errno = ndctl_new(&ctx) * (-1); if (errno) { - ERR("!ndctl_new"); + ERR_W_ERRNO("ndctl_new"); return PMEM2_E_ERRNO; } int rv = pmem2_region_namespace(ctx, src, ®ion, &ndns); if (rv) { - LOG(1, "getting region and namespace failed"); + CORE_LOG_ERROR("getting region and namespace failed"); goto end; } if (!region) { - ERR("unknown region"); + ERR_WO_ERRNO("unknown region"); rv = PMEM2_E_DAX_REGION_NOT_FOUND; goto end; } diff --git a/src/libpmem2/source_posix.c b/src/libpmem2/source_posix.c index 92f61860977..346623d770d 100644 --- a/src/libpmem2/source_posix.c +++ b/src/libpmem2/source_posix.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2019-2020, Intel Corporation */ +/* Copyright 2019-2024, Intel Corporation */ #include #include @@ -28,14 +28,14 @@ pmem2_source_from_fd(struct pmem2_source **src, int fd) int flags = fcntl(fd, F_GETFL); if (flags == -1) { - ERR("!fcntl"); + ERR_W_ERRNO("fcntl"); if (errno == EBADF) return PMEM2_E_INVALID_FILE_HANDLE; return PMEM2_E_ERRNO; } if ((flags & O_ACCMODE) == O_WRONLY) { - ERR("fd must be open with O_RDONLY or O_RDWR"); + ERR_WO_ERRNO("fd must be open with O_RDONLY or O_RDWR"); return PMEM2_E_INVALID_FILE_HANDLE; } @@ -50,7 +50,7 @@ pmem2_source_from_fd(struct pmem2_source **src, int fd) os_stat_t st; if (os_fstat(fd, &st) < 0) { - ERR("!fstat"); + ERR_W_ERRNO("fstat"); if (errno == EBADF) return PMEM2_E_INVALID_FILE_HANDLE; return PMEM2_E_ERRNO; @@ -62,7 +62,8 @@ pmem2_source_from_fd(struct pmem2_source **src, int fd) return ret; if (ftype == PMEM2_FTYPE_DIR) { - ERR("cannot set fd to directory in pmem2_source_from_fd"); + ERR_WO_ERRNO( + "cannot set fd to directory in pmem2_source_from_fd"); return PMEM2_E_INVALID_FILE_TYPE; } @@ -102,7 +103,7 @@ pmem2_source_size(const struct pmem2_source *src, size_t *size) os_stat_t st; if (os_fstat(src->value.fd, &st) < 0) { - ERR("!fstat"); + ERR_W_ERRNO("fstat"); if (errno == EBADF) return PMEM2_E_INVALID_FILE_HANDLE; return PMEM2_E_ERRNO; @@ -117,7 +118,7 @@ pmem2_source_size(const struct pmem2_source *src, size_t *size) } case PMEM2_FTYPE_REG: if (st.st_size < 0) { - ERR( + ERR_WO_ERRNO( "kernel says size of regular file is negative (%ld)", st.st_size); return PMEM2_E_INVALID_FILE_HANDLE; @@ -125,7 +126,7 @@ pmem2_source_size(const struct pmem2_source *src, size_t *size) *size = (size_t)st.st_size; break; default: - FATAL( + CORE_LOG_FATAL( "BUG: unhandled file type in pmem2_source_size"); } @@ -161,12 +162,13 @@ pmem2_source_alignment(const struct pmem2_source *src, size_t *alignment) *alignment = Pagesize; break; default: - FATAL( + CORE_LOG_FATAL( "BUG: unhandled file type in pmem2_source_alignment"); } if (!util_is_pow2(*alignment)) { - ERR("alignment (%zu) has to be a power of two", *alignment); + ERR_WO_ERRNO( + "alignment (%zu) has to be a power of two", *alignment); return PMEM2_E_INVALID_ALIGNMENT_VALUE; } @@ -187,7 +189,7 @@ pmem2_source_get_fd(const struct pmem2_source *src, int *fd) if (src->type == PMEM2_SOURCE_FD) { *fd = src->value.fd; } else { - ERR( + ERR_WO_ERRNO( "File descriptor is not set, source type does not support fd"); return PMEM2_E_FILE_DESCRIPTOR_NOT_SET; } diff --git a/src/libpmem2/usc_ndctl.c b/src/libpmem2/usc_ndctl.c index db658c7e10f..72cf9df3c02 100644 --- a/src/libpmem2/usc_ndctl.c +++ b/src/libpmem2/usc_ndctl.c @@ -1,11 +1,10 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2020-2022, Intel Corporation */ +/* Copyright 2020-2024, Intel Corporation */ /* * usc_ndctl.c -- pmem2 usc function for platforms using ndctl */ #include -#include #include #include #include @@ -26,7 +25,8 @@ pmem2_source_device_usc(const struct pmem2_source *src, uint64_t *usc) PMEM2_ERR_CLR(); if (src->type == PMEM2_SOURCE_ANON) { - ERR("Anonymous source does not support unsafe shutdown count"); + ERR_WO_ERRNO( + "Anonymous source does not support unsafe shutdown count"); return PMEM2_E_NOSUPP; } @@ -38,7 +38,7 @@ pmem2_source_device_usc(const struct pmem2_source *src, uint64_t *usc) errno = ndctl_new(&ctx) * (-1); if (errno) { - ERR("!ndctl_new"); + ERR_W_ERRNO("ndctl_new"); return PMEM2_E_ERRNO; } @@ -51,7 +51,7 @@ pmem2_source_device_usc(const struct pmem2_source *src, uint64_t *usc) ret = PMEM2_E_NOSUPP; if (region == NULL) { - ERR( + ERR_WO_ERRNO( "Unsafe shutdown count is not supported for this source"); goto err; } @@ -62,7 +62,7 @@ pmem2_source_device_usc(const struct pmem2_source *src, uint64_t *usc) long long dimm_usc = ndctl_dimm_get_dirty_shutdown(dimm); if (dimm_usc < 0) { ret = PMEM2_E_NOSUPP; - ERR( + ERR_WO_ERRNO( "Unsafe shutdown count is not supported for this source"); goto err; } @@ -88,7 +88,7 @@ pmem2_source_device_id(const struct pmem2_source *src, char *id, size_t *len) const char *dimm_uid; if (src->type == PMEM2_SOURCE_ANON) { - ERR("Anonymous source does not have device id"); + ERR_WO_ERRNO("Anonymous source does not have device id"); return PMEM2_E_NOSUPP; } @@ -96,7 +96,7 @@ pmem2_source_device_id(const struct pmem2_source *src, char *id, size_t *len) errno = ndctl_new(&ctx) * (-1); if (errno) { - ERR("!ndctl_new"); + ERR_W_ERRNO("ndctl_new"); return PMEM2_E_ERRNO; } diff --git a/src/libpmem2/usc_none.c b/src/libpmem2/usc_none.c index db559525648..9c1652d5a9d 100644 --- a/src/libpmem2/usc_none.c +++ b/src/libpmem2/usc_none.c @@ -1,19 +1,20 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2020-2022, Intel Corporation */ +/* Copyright 2020-2024, Intel Corporation */ /* * usc_none.c -- pmem2 usc function for non supported platform */ #include "libpmem2.h" -#include "out.h" +#include "log_internal.h" +#include "util.h" int pmem2_source_device_id(const struct pmem2_source *src, char *id, size_t *len) { SUPPRESS_UNUSED(src, id, len); - ERR("Cannot read device id - ndctl is not available"); + ERR_WO_ERRNO("Cannot read device id - ndctl is not available"); return PMEM2_E_NOSUPP; } @@ -23,7 +24,7 @@ pmem2_source_device_usc(const struct pmem2_source *src, uint64_t *usc) { SUPPRESS_UNUSED(src, usc); - ERR("Cannot read device usc - ndctl is not available"); + ERR_WO_ERRNO("Cannot read device usc - ndctl is not available"); return PMEM2_E_NOSUPP; } diff --git a/src/libpmem2/vm_reservation.c b/src/libpmem2/vm_reservation.c index 982d14c7d3e..473b5c1e2e1 100644 --- a/src/libpmem2/vm_reservation.c +++ b/src/libpmem2/vm_reservation.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2020-2023, Intel Corporation */ +/* Copyright 2020-2024, Intel Corporation */ /* * vm_reservation.c -- implementation of virtual memory allocation API @@ -113,13 +113,13 @@ pmem2_vm_reservation_new(struct pmem2_vm_reservation **rsv_ptr, * on Windows and to the 'page size' otherwise */ if (addr && (unsigned long long)addr % Mmap_align) { - ERR("address %p is not a multiple of 0x%llx", addr, + ERR_WO_ERRNO("address %p is not a multiple of 0x%llx", addr, Mmap_align); return PMEM2_E_ADDRESS_UNALIGNED; } if (size % Mmap_align) { - ERR("reservation size %zu is not a multiple of %llu", + ERR_WO_ERRNO("reservation size %zu is not a multiple of %llu", size, Mmap_align); return PMEM2_E_LENGTH_UNALIGNED; } @@ -187,7 +187,7 @@ pmem2_vm_reservation_delete(struct pmem2_vm_reservation **rsv_ptr) struct pmem2_map *any_map; /* check if reservation contains any mapping */ if (!pmem2_vm_reservation_map_find(rsv, 0, rsv->size, &any_map)) { - ERR("vm reservation %p isn't empty", rsv); + ERR_WO_ERRNO("vm reservation %p isn't empty", rsv); return PMEM2_E_VM_RESERVATION_NOT_EMPTY; } @@ -223,8 +223,9 @@ pmem2_vm_reservation_map_find(struct pmem2_vm_reservation *rsv, struct ravl_interval_node *node; node = ravl_interval_find(rsv->itree, &dummy_map); if (!node) { - ERR("mapping not found at the range (offset %zu, size %zu) in" \ - " reservation %p", reserv_offset, len, rsv); + ERR_WO_ERRNO( + "mapping not found at the range (offset %zu, size %zu) in reservation %p", + reserv_offset, len, rsv); return PMEM2_E_MAPPING_NOT_FOUND; } @@ -249,7 +250,7 @@ pmem2_vm_reservation_map_find_prev(struct pmem2_vm_reservation *rsv, struct ravl_interval_node *node; node = ravl_interval_find_prev(rsv->itree, map); if (!node) { - ERR("mapping previous to mapping %p not found", map); + ERR_WO_ERRNO("mapping previous to mapping %p not found", map); return PMEM2_E_MAPPING_NOT_FOUND; } @@ -274,7 +275,7 @@ pmem2_vm_reservation_map_find_next(struct pmem2_vm_reservation *rsv, struct ravl_interval_node *node; node = ravl_interval_find_next(rsv->itree, map); if (!node) { - ERR("mapping next to mapping %p not found", map); + ERR_WO_ERRNO("mapping next to mapping %p not found", map); return PMEM2_E_MAPPING_NOT_FOUND; } @@ -299,7 +300,7 @@ pmem2_vm_reservation_map_find_first(struct pmem2_vm_reservation *rsv, struct ravl_interval_node *node; node = ravl_interval_find_first(rsv->itree); if (!node) { - ERR("reservation %p stores no mapping", rsv); + ERR_WO_ERRNO("reservation %p stores no mapping", rsv); return PMEM2_E_MAPPING_NOT_FOUND; } @@ -324,7 +325,7 @@ pmem2_vm_reservation_map_find_last(struct pmem2_vm_reservation *rsv, struct ravl_interval_node *node; node = ravl_interval_find_last(rsv->itree); if (!node) { - ERR("reservation %p stores no mapping", rsv); + ERR_WO_ERRNO("reservation %p stores no mapping", rsv); return PMEM2_E_MAPPING_NOT_FOUND; } @@ -344,7 +345,7 @@ vm_reservation_map_register_release(struct pmem2_vm_reservation *rsv, { int ret = ravl_interval_insert(rsv->itree, map); if (ret == -EEXIST) { - ERR( + ERR_WO_ERRNO( "mapping at the given region of the reservation already exists"); ret = PMEM2_E_MAPPING_EXISTS; } @@ -368,8 +369,8 @@ vm_reservation_map_unregister_release(struct pmem2_vm_reservation *rsv, node = ravl_interval_find_equal(rsv->itree, map); if (!(node && !ravl_interval_remove(rsv->itree, node))) { - ERR("Cannot find mapping %p in the reservation %p", - map, rsv); + ERR_WO_ERRNO("Cannot find mapping %p in the reservation %p", + map, rsv); ret = PMEM2_E_MAPPING_NOT_FOUND; } @@ -431,7 +432,8 @@ pmem2_vm_reservation_extend(struct pmem2_vm_reservation *rsv, size_t size) PMEM2_ERR_CLR(); if (size % Mmap_align) { - ERR("reservation extension size %zu is not a multiple of %llu", + ERR_WO_ERRNO( + "reservation extension size %zu is not a multiple of %llu", size, Pagesize); return PMEM2_E_LENGTH_UNALIGNED; } @@ -483,49 +485,53 @@ pmem2_vm_reservation_shrink(struct pmem2_vm_reservation *rsv, size_t offset, PMEM2_ERR_CLR(); if (offset % Mmap_align) { - ERR("reservation shrink offset %zu is not a multiple of %llu", + ERR_WO_ERRNO( + "reservation shrink offset %zu is not a multiple of %llu", offset, Mmap_align); return PMEM2_E_OFFSET_UNALIGNED; } if (size % Mmap_align) { - ERR("reservation shrink size %zu is not a multiple of %llu", + ERR_WO_ERRNO( + "reservation shrink size %zu is not a multiple of %llu", size, Mmap_align); return PMEM2_E_LENGTH_UNALIGNED; } if (offset >= rsv->size) { - ERR("reservation shrink offset %zu is out of reservation range", + ERR_WO_ERRNO( + "reservation shrink offset %zu is out of reservation range", offset); return PMEM2_E_OFFSET_OUT_OF_RANGE; } if (size == 0) { - ERR("reservation shrink size %zu cannot be zero", + ERR_WO_ERRNO("reservation shrink size %zu cannot be zero", size); return PMEM2_E_LENGTH_OUT_OF_RANGE; } if ((offset + size) > rsv->size) { - ERR( + ERR_WO_ERRNO( "reservation shrink size %zu stands out of reservation range", size); return PMEM2_E_LENGTH_OUT_OF_RANGE; } if (offset != 0 && (offset + size) != rsv->size) { - ERR("shrinking reservation from the middle is not supported"); + ERR_WO_ERRNO( + "shrinking reservation from the middle is not supported"); return PMEM2_E_NOSUPP; } if (offset == 0 && size == rsv->size) { - ERR("shrinking whole reservation is not supported"); + ERR_WO_ERRNO("shrinking whole reservation is not supported"); return PMEM2_E_NOSUPP; } struct pmem2_map *any_map; if (!pmem2_vm_reservation_map_find(rsv, offset, size, &any_map)) { - ERR( + ERR_WO_ERRNO( "reservation region (offset %zu, size %zu) to be shrunk is occupied by a mapping", offset, size); return PMEM2_E_VM_RESERVATION_NOT_EMPTY; diff --git a/src/libpmem2/vm_reservation_posix.c b/src/libpmem2/vm_reservation_posix.c index 1a59c52eced..bd87a845b5e 100644 --- a/src/libpmem2/vm_reservation_posix.c +++ b/src/libpmem2/vm_reservation_posix.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2020-2021, Intel Corporation */ +/* Copyright 2020-2024, Intel Corporation */ /* * vm_reservation_posix.c -- implementation of virtual memory @@ -75,10 +75,10 @@ vm_reservation_reserve_memory(void *addr, size_t size, void **raddr, MAP_PRIVATE | MAP_ANONYMOUS | mmap_flag, -1, 0); if (mmap_addr == MAP_FAILED) { if (errno == EEXIST) { - ERR("!mmap MAP_FIXED_NOREPLACE"); + ERR_W_ERRNO("mmap MAP_FIXED_NOREPLACE"); return PMEM2_E_MAPPING_EXISTS; } - ERR("!mmap MAP_ANONYMOUS"); + ERR_W_ERRNO("mmap MAP_ANONYMOUS"); return PMEM2_E_ERRNO; } @@ -91,7 +91,7 @@ vm_reservation_reserve_memory(void *addr, size_t size, void **raddr, */ if (addr && mmap_addr != addr) { munmap(mmap_addr, mmap_size); - ERR("mapping exists in the given address"); + ERR_WO_ERRNO("mapping exists in the given address"); return PMEM2_E_MAPPING_EXISTS; } @@ -109,7 +109,7 @@ int vm_reservation_release_memory(void *addr, size_t size) { if (munmap(addr, size)) { - ERR("!munmap"); + ERR_W_ERRNO("munmap"); return PMEM2_E_ERRNO; } diff --git a/src/libpmem2/x86_64/init.c b/src/libpmem2/x86_64/init.c index bc21183301c..e46be1a7610 100644 --- a/src/libpmem2/x86_64/init.c +++ b/src/libpmem2/x86_64/init.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2014-2022, Intel Corporation */ +/* Copyright 2014-2024, Intel Corporation */ #include #include @@ -10,6 +10,7 @@ #include "memcpy_memset.h" #include "os.h" #include "out.h" +#include "core_assert.h" #include "pmem2_arch.h" #include "valgrind_internal.h" @@ -64,7 +65,7 @@ flush_clwb(const void *addr, size_t len) #define PMEM2_F_MEM_MOV (PMEM2_F_MEM_WB | PMEM2_F_MEM_TEMPORAL) static void * -pmem_memmove_nodrain(void *dest, const void *src, size_t len, unsigned flags, +pmem2_memmove_nodrain(void *dest, const void *src, size_t len, unsigned flags, flush_func flushf, const struct memmove_nodrain *memmove_funcs) { /* suppress unused-parameter errors */ @@ -88,7 +89,7 @@ pmem_memmove_nodrain(void *dest, const void *src, size_t len, unsigned flags, } static void * -pmem_memmove_nodrain_eadr(void *dest, const void *src, size_t len, +pmem2_memmove_nodrain_eadr(void *dest, const void *src, size_t len, unsigned flags, flush_func flushf, const struct memmove_nodrain *memmove_funcs) { @@ -109,7 +110,7 @@ pmem_memmove_nodrain_eadr(void *dest, const void *src, size_t len, } static void * -pmem_memset_nodrain(void *dest, int c, size_t len, unsigned flags, +pmem2_memset_nodrain(void *dest, int c, size_t len, unsigned flags, flush_func flushf, const struct memset_nodrain *memset_funcs) { /* suppress unused-parameter errors */ @@ -133,7 +134,7 @@ pmem_memset_nodrain(void *dest, int c, size_t len, unsigned flags, } static void * -pmem_memset_nodrain_eadr(void *dest, int c, size_t len, unsigned flags, +pmem2_memset_nodrain_eadr(void *dest, int c, size_t len, unsigned flags, flush_func flushf, const struct memset_nodrain *memset_funcs) { /* suppress unused-parameter errors */ @@ -155,10 +156,10 @@ pmem_memset_nodrain_eadr(void *dest, int c, size_t len, unsigned flags, static void pmem_set_mem_funcs(struct pmem2_arch_info *info) { - info->memmove_nodrain = pmem_memmove_nodrain; - info->memmove_nodrain_eadr = pmem_memmove_nodrain_eadr; - info->memset_nodrain = pmem_memset_nodrain; - info->memset_nodrain_eadr = pmem_memset_nodrain_eadr; + info->memmove_nodrain = pmem2_memmove_nodrain; + info->memmove_nodrain_eadr = pmem2_memmove_nodrain_eadr; + info->memset_nodrain = pmem2_memset_nodrain; + info->memset_nodrain_eadr = pmem2_memset_nodrain_eadr; } enum memcpy_impl { @@ -585,7 +586,7 @@ pmem2_arch_init(struct pmem2_arch_info *info) else if (info->flush == flush_clflush) LOG(3, "using clflush"); else - FATAL("invalid deep flush function address"); + CORE_LOG_FATAL("invalid deep flush function address"); if (impl == MEMCPY_MOVDIR64B) LOG(3, "using movnt MOVDIR64B"); diff --git a/src/libpmem2/x86_64/memcpy/memcpy_avx.h b/src/libpmem2/x86_64/memcpy/memcpy_avx.h index 2a01739bf41..6cb3c8fb88e 100644 --- a/src/libpmem2/x86_64/memcpy/memcpy_avx.h +++ b/src/libpmem2/x86_64/memcpy/memcpy_avx.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause */ -/* Copyright 2017-2022, Intel Corporation */ +/* Copyright 2017-2024, Intel Corporation */ #ifndef PMEM2_MEMCPY_AVX_H #define PMEM2_MEMCPY_AVX_H @@ -8,7 +8,7 @@ #include #include -#include "out.h" +#include "core_assert.h" static force_inline void memmove_small_avx_noflush(char *dest, const char *src, size_t len) @@ -87,10 +87,13 @@ memmove_small_avx(char *dest, const char *src, size_t len, flush_fn flush) * path) in the optimized version. * libc's memcpy also does that, so we can't use it here. */ +#if VG_PMEMCHECK_ENABLED if (On_pmemcheck) { memmove_nodrain_generic(dest, src, len, PMEM2_F_MEM_NOFLUSH, NULL, NULL); - } else { + } else +#endif + { memmove_small_avx_noflush(dest, src, len); } diff --git a/src/libpmem2/x86_64/memcpy/memcpy_sse2.h b/src/libpmem2/x86_64/memcpy/memcpy_sse2.h index dc0d8351dc8..4012f33b712 100644 --- a/src/libpmem2/x86_64/memcpy/memcpy_sse2.h +++ b/src/libpmem2/x86_64/memcpy/memcpy_sse2.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause */ -/* Copyright 2017-2022, Intel Corporation */ +/* Copyright 2017-2024, Intel Corporation */ #ifndef PMEM2_MEMCPY_SSE2_H #define PMEM2_MEMCPY_SSE2_H @@ -8,7 +8,7 @@ #include #include -#include "out.h" +#include "core_assert.h" static force_inline void memmove_small_sse2_noflush(char *dest, const char *src, size_t len) @@ -103,10 +103,13 @@ memmove_small_sse2(char *dest, const char *src, size_t len, flush_fn flush) * path) in the optimized version. * libc's memcpy also does that, so we can't use it here. */ +#if VG_PMEMCHECK_ENABLED if (On_pmemcheck) { memmove_nodrain_generic(dest, src, len, PMEM2_F_MEM_NOFLUSH, NULL, NULL); - } else { + } else +#endif + { memmove_small_sse2_noflush(dest, src, len); } diff --git a/src/libpmem2/x86_64/memset/memset_avx.h b/src/libpmem2/x86_64/memset/memset_avx.h index db43691176d..1a5df0facc4 100644 --- a/src/libpmem2/x86_64/memset/memset_avx.h +++ b/src/libpmem2/x86_64/memset/memset_avx.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause */ -/* Copyright 2017-2022, Intel Corporation */ +/* Copyright 2017-2024, Intel Corporation */ #ifndef PMEM2_MEMSET_AVX_H #define PMEM2_MEMSET_AVX_H @@ -10,7 +10,7 @@ #include #include "avx.h" -#include "out.h" +#include "core_assert.h" static force_inline void memset_small_avx_noflush(char *dest, __m256i ymm, size_t len) @@ -84,11 +84,15 @@ memset_small_avx(char *dest, __m256i ymm, size_t len, flush_fn flush) * path) in the optimized version. * libc's memset also does that, so we can't use it here. */ +#if VG_PMEMCHECK_ENABLED if (On_pmemcheck) { memset_nodrain_generic(dest, (uint8_t)m256_get2b(ymm), len, PMEM2_F_MEM_NOFLUSH, NULL, NULL); - } else { + } + else +#endif + { memset_small_avx_noflush(dest, ymm, len); } diff --git a/src/libpmem2/x86_64/memset/memset_sse2.h b/src/libpmem2/x86_64/memset/memset_sse2.h index 83a67f148b3..a160683fc45 100644 --- a/src/libpmem2/x86_64/memset/memset_sse2.h +++ b/src/libpmem2/x86_64/memset/memset_sse2.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause */ -/* Copyright 2017-2022, Intel Corporation */ +/* Copyright 2017-2024, Intel Corporation */ #ifndef PMEM2_MEMSET_SSE2_H #define PMEM2_MEMSET_SSE2_H @@ -9,7 +9,7 @@ #include #include -#include "out.h" +#include "core_assert.h" static force_inline void memset_small_sse2_noflush(char *dest, __m128i xmm, size_t len) @@ -91,10 +91,13 @@ memset_small_sse2(char *dest, __m128i xmm, size_t len, flush_fn flush) * path) in the optimized version. * libc's memset also does that, so we can't use it here. */ +#if VG_PMEMCHECK_ENABLED if (On_pmemcheck) { memset_nodrain_generic(dest, (uint8_t)_mm_cvtsi128_si32(xmm), len, PMEM2_F_MEM_NOFLUSH, NULL, NULL); - } else { + } else +#endif + { memset_small_sse2_noflush(dest, xmm, len); } diff --git a/src/libpmemobj/Makefile b/src/libpmemobj/Makefile index af013dd3cc8..62c242b4c4d 100644 --- a/src/libpmemobj/Makefile +++ b/src/libpmemobj/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2014-2023, Intel Corporation +# Copyright 2014-2024, Intel Corporation # # src/libpmemobj/Makefile -- Makefile for libpmemobj @@ -26,6 +26,7 @@ SOURCE +=\ memblock.c\ memops.c\ obj.c\ + obj_log.c\ palloc.c\ pmalloc.c\ recycler.c\ @@ -36,6 +37,28 @@ SOURCE +=\ include ../Makefile.inc +ifeq ($(OS_DIMM),none) + NOT_RECOMMENDED = Continuing the build without NDCTL is highly NOT recommended for production quality systems. + RAS_SUFFIX = Please see https://www.intel.com/content/www/us/en/developer/articles/technical/build-pmem-apps-with-ras.html for more info on RAS features. + PMEMOBJ_IGNORE_DIRTY_SHUTDOWN ?= n + ifneq ($(PMEMOBJ_IGNORE_DIRTY_SHUTDOWN),y) + $(info Libpmemobj without NDCTL cannot detect dirty shutdowns. This may result in silent data corruption.) + $(info $(NOT_RECOMMENDED)) + $(info If you understand the consequences for consistency of your data please set PMEMOBJ_IGNORE_DIRTY_SHUTDOWN=y to silence this error.) + $(info $(RAS_SUFFIX)) + $(error ) + endif + + PMEMOBJ_IGNORE_BAD_BLOCKS ?= n + ifneq ($(PMEMOBJ_IGNORE_BAD_BLOCKS),y) + $(info Libpmemobj without NDCTL cannot detect bad blocks up front. This may result in SIGBUS at runtime.) + $(info $(NOT_RECOMMENDED)) + $(info If you understand the consequences for the behaviour of your application at runtime please set PMEMOBJ_IGNORE_BAD_BLOCKS=y to silence this error.) + $(info $(RAS_SUFFIX)) + $(error ) + endif +endif + CFLAGS += -DUSE_LIBDL -D_PMEMOBJ_INTRNL $(LIBNDCTL_CFLAGS) LIBS += -pthread -lpmem $(LIBDL) $(LIBNDCTL_LIBS) diff --git a/src/libpmemobj/alloc_class.c b/src/libpmemobj/alloc_class.c index 6b2b80bc301..52702ff1050 100644 --- a/src/libpmemobj/alloc_class.c +++ b/src/libpmemobj/alloc_class.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2016-2023, Intel Corporation */ +/* Copyright 2016-2024, Intel Corporation */ /* * alloc_class.c -- implementation of allocation classes @@ -11,7 +11,7 @@ #include "alloc_class.h" #include "heap_layout.h" #include "util.h" -#include "out.h" +#include "core_assert.h" #include "bucket.h" #include "critnib.h" @@ -167,8 +167,10 @@ alloc_class_reservation_clear(struct alloc_class_collection *ac, int id) { LOG(10, NULL); - int ret = util_bool_compare_and_swap64(&ac->aclasses[id], - ACLASS_RESERVED, NULL); +#ifdef DEBUG /* variables required for ASSERTs below */ + int ret = +#endif + util_bool_compare_and_swap64(&ac->aclasses[id], ACLASS_RESERVED, NULL); ASSERT(ret); } @@ -226,7 +228,8 @@ alloc_class_new(int id, struct alloc_class_collection *ac, flags_s, size_idx_s); if (critnib_insert(ac->class_map_by_unit_size, k, c) != 0) { - ERR("unable to register allocation class"); + ERR_WO_ERRNO( + "unable to register allocation class"); goto error_map_insert; } diff --git a/src/libpmemobj/critnib.c b/src/libpmemobj/critnib.c index ff13479c90f..601ae0a5c8e 100644 --- a/src/libpmemobj/critnib.c +++ b/src/libpmemobj/critnib.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2018-2021, Intel Corporation */ +/* Copyright 2018-2024, Intel Corporation */ /* * critnib.c -- implementation of critnib tree @@ -276,7 +276,7 @@ alloc_node(struct critnib *__restrict c) if (!c->deleted_node) { struct critnib_node *n = Malloc(sizeof(struct critnib_node)); if (n == NULL) - ERR("!Malloc"); + ERR_W_ERRNO("Malloc"); return n; } @@ -313,7 +313,7 @@ alloc_leaf(struct critnib *__restrict c) if (!c->deleted_leaf) { struct critnib_leaf *k = Malloc(sizeof(struct critnib_leaf)); if (k == NULL) - ERR("!Malloc"); + ERR_W_ERRNO("Malloc"); return k; } diff --git a/src/libpmemobj/heap.c b/src/libpmemobj/heap.c index 926fb77e8d2..64cc19f42d7 100644 --- a/src/libpmemobj/heap.c +++ b/src/libpmemobj/heap.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2015-2023, Intel Corporation */ +/* Copyright 2015-2024, Intel Corporation */ /* * heap.c -- heap implementation @@ -184,7 +184,7 @@ heap_arena_new(struct palloc_heap *heap, int automatic) struct arena *arena = Zalloc(sizeof(struct arena)); if (arena == NULL) { - ERR("!heap: arena malloc error"); + ERR_W_ERRNO("heap: arena malloc error"); return NULL; } arena->nthreads = 0; @@ -741,7 +741,9 @@ heap_reclaim_run(struct palloc_heap *heap, struct memory_block *m, int startup) struct recycler_element e = recycler_element_new(heap, m); if (c == NULL) { +#ifdef DEBUG uint32_t size_idx = m->size_idx; +#endif struct run_bitmap b; m->m_ops->get_bitmap(m, &b); @@ -763,7 +765,9 @@ heap_reclaim_run(struct palloc_heap *heap, struct memory_block *m, int startup) c->rdsc.nallocs); if (recycler == NULL || recycler_put(recycler, e) < 0) - ERR("lost runtime tracking info of %u run due to OOM", c->id); + ERR_WO_ERRNO( + "lost runtime tracking info of %u run due to OOM", + c->id); return 0; } @@ -825,7 +829,9 @@ heap_ensure_zone_reclaimed(struct palloc_heap *heap, uint32_t zone_id) DEFAULT_ALLOC_CLASS_ID, HEAP_ARENA_PER_THREAD); +#ifdef DEBUG /* variables required for ASSERTs below */ struct zone *z = ZID_TO_ZONE(heap->layout, zone_id); +#endif ASSERTeq(z->header.magic, ZONE_HEADER_MAGIC); /* check a second time just to make sure no other thread was first */ @@ -1042,7 +1048,7 @@ heap_reuse_from_recycler(struct palloc_heap *heap, struct recycler *recycler = heap_get_recycler(heap, aclass->id, aclass->rdsc.nallocs); if (recycler == NULL) { - ERR("lost runtime tracking info of %u run due to OOM", + ERR_WO_ERRNO("lost runtime tracking info of %u run due to OOM", aclass->id); return 0; } @@ -1158,7 +1164,7 @@ heap_memblock_on_free(struct palloc_heap *heap, const struct memory_block *m) struct recycler *recycler = heap_get_recycler(heap, c->id, c->rdsc.nallocs); if (recycler == NULL) { - ERR("lost runtime tracking info of %u run due to OOM", + ERR_WO_ERRNO("lost runtime tracking info of %u run due to OOM", c->id); } else { recycler_inc_unaccounted(recycler, m); @@ -1183,7 +1189,7 @@ heap_split_block(struct palloc_heap *heap, struct bucket *b, NULL, NULL, 0, 0, NULL}; memblock_rebuild_state(heap, &r); if (bucket_insert_block(b, &r) != 0) - LOG(2, + CORE_LOG_WARNING( "failed to allocate memory block runtime tracking info"); } else { uint32_t new_chunk_id = m->chunk_id + units; @@ -1195,7 +1201,7 @@ heap_split_block(struct palloc_heap *heap, struct bucket *b, *m = memblock_huge_init(heap, m->chunk_id, m->zone_id, units); if (bucket_insert_block(b, &n) != 0) - LOG(2, + CORE_LOG_WARNING( "failed to allocate memory block runtime tracking info"); } @@ -1234,6 +1240,7 @@ heap_get_bestfit_block(struct palloc_heap *heap, struct bucket *b, return 0; } +#if VG_MEMCHECK_ENABLED /* * heap_end -- returns first address after heap */ @@ -1246,6 +1253,7 @@ heap_end(struct palloc_heap *h) return &last_zone->chunks[last_zone->header.size_idx]; } +#endif /* VG_MEMCHECK_ENABLED */ /* * heap_arena_create -- create a new arena, push it to the vector @@ -1318,7 +1326,7 @@ heap_set_narenas_max(struct palloc_heap *heap, unsigned size) util_mutex_lock(&h->arenas.lock); unsigned capacity = (unsigned)VEC_CAPACITY(&h->arenas.vec); if (size < capacity) { - LOG(2, "cannot decrease max number of arenas"); + CORE_LOG_ERROR("cannot decrease max number of arenas"); goto out; } else if (size == capacity) { ret = 0; @@ -1401,7 +1409,7 @@ heap_set_arena_auto(struct palloc_heap *heap, unsigned arena_id, a = VEC_ARR(&heap->rt->arenas.vec)[arena_id - 1]; if (!automatic && nautomatic <= 1 && a->automatic) { - ERR("at least one automatic arena must exist"); + ERR_WO_ERRNO("at least one automatic arena must exist"); ret = -1; goto out; } @@ -1596,7 +1604,7 @@ heap_boot(struct palloc_heap *heap, void *heap_start, uint64_t heap_size, } if (heap_size < *sizep) { - ERR("mapped region smaller than the heap size"); + ERR_WO_ERRNO("mapped region smaller than the heap size"); return EINVAL; } @@ -1778,12 +1786,12 @@ static int heap_verify_header(struct heap_header *hdr) { if (util_checksum(hdr, sizeof(*hdr), &hdr->checksum, 0, 0) != 1) { - ERR("heap: invalid header's checksum"); + ERR_WO_ERRNO("heap: invalid header's checksum"); return -1; } if (memcmp(hdr->signature, HEAP_SIGNATURE, HEAP_SIGNATURE_LEN) != 0) { - ERR("heap: invalid signature"); + ERR_WO_ERRNO("heap: invalid signature"); return -1; } @@ -1801,7 +1809,7 @@ heap_verify_zone_header(struct zone_header *hdr) return 0; if (hdr->size_idx == 0) { - ERR("heap: invalid zone size"); + ERR_WO_ERRNO("heap: invalid zone size"); return -1; } @@ -1816,17 +1824,17 @@ static int heap_verify_chunk_header(struct chunk_header *hdr) { if (hdr->type == CHUNK_TYPE_UNKNOWN) { - ERR("heap: invalid chunk type"); + ERR_WO_ERRNO("heap: invalid chunk type"); return -1; } if (hdr->type >= MAX_CHUNK_TYPE) { - ERR("heap: unknown chunk type"); + ERR_WO_ERRNO("heap: unknown chunk type"); return -1; } if (hdr->flags & ~CHUNK_FLAGS_ALL_VALID) { - ERR("heap: invalid chunk flags"); + ERR_WO_ERRNO("heap: invalid chunk flags"); return -1; } @@ -1843,7 +1851,7 @@ heap_verify_zone(struct zone *zone) return 0; /* not initialized, and that is OK */ if (zone->header.magic != ZONE_HEADER_MAGIC) { - ERR("heap: invalid zone magic"); + ERR_WO_ERRNO("heap: invalid zone magic"); return -1; } @@ -1859,7 +1867,7 @@ heap_verify_zone(struct zone *zone) } if (i != zone->header.size_idx) { - ERR("heap: chunk sizes mismatch"); + ERR_WO_ERRNO("heap: chunk sizes mismatch"); return -1; } @@ -1875,7 +1883,7 @@ int heap_check(void *heap_start, uint64_t heap_size) { if (heap_size < HEAP_MIN_SIZE) { - ERR("heap: invalid heap size"); + ERR_WO_ERRNO("heap: invalid heap size"); return -1; } diff --git a/src/libpmemobj/heap.h b/src/libpmemobj/heap.h index 455669aef9b..09278bad69e 100644 --- a/src/libpmemobj/heap.h +++ b/src/libpmemobj/heap.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause */ -/* Copyright 2015-2022, Intel Corporation */ +/* Copyright 2015-2024, Intel Corporation */ /* * heap.h -- internal definitions for heap @@ -83,7 +83,9 @@ void heap_foreach_object(struct palloc_heap *heap, object_callback cb, struct alloc_class_collection *heap_alloc_classes(struct palloc_heap *heap); +#if VG_MEMCHECK_ENABLED void *heap_end(struct palloc_heap *heap); +#endif /* VG_MEMCHECK_ENABLED */ unsigned heap_get_narenas_total(struct palloc_heap *heap); diff --git a/src/libpmemobj/lane.c b/src/libpmemobj/lane.c index 9d98649262a..f5c1b478172 100644 --- a/src/libpmemobj/lane.c +++ b/src/libpmemobj/lane.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2015-2023, Intel Corporation */ +/* Copyright 2015-2024, Intel Corporation */ /* * lane.c -- lane implementation @@ -17,7 +17,7 @@ #include "libpmemobj.h" #include "critnib.h" #include "lane.h" -#include "out.h" +#include "core_assert.h" #include "util.h" #include "obj.h" #include "os_thread.h" @@ -40,7 +40,7 @@ lane_info_create(void) { Lane_info_ht = critnib_new(); if (Lane_info_ht == NULL) - FATAL("critnib_new"); + CORE_LOG_FATAL("critnib_new"); } /* @@ -77,7 +77,7 @@ lane_info_ht_boot(void) int result = os_tls_set(Lane_info_key, Lane_info_ht); if (result != 0) { errno = result; - FATAL("!os_tls_set"); + CORE_LOG_FATAL_W_ERRNO("os_tls_set"); } } @@ -102,7 +102,7 @@ lane_info_boot(void) int result = os_tls_key_create(&Lane_info_key, lane_info_ht_destroy); if (result != 0) { errno = result; - FATAL("!os_tls_key_create"); + CORE_LOG_FATAL_W_ERRNO("os_tls_key_create"); } } @@ -264,7 +264,7 @@ lane_boot(PMEMobjpool *pop) pop->lanes_desc.lane = Malloc(sizeof(struct lane) * pop->nlanes); if (pop->lanes_desc.lane == NULL) { err = ENOMEM; - ERR("!Malloc of volatile lanes"); + ERR_W_ERRNO("Malloc of volatile lanes"); goto error_lanes_malloc; } @@ -273,7 +273,7 @@ lane_boot(PMEMobjpool *pop) pop->lanes_desc.lane_locks = Zalloc(sizeof(*pop->lanes_desc.lane_locks) * pop->nlanes); if (pop->lanes_desc.lane_locks == NULL) { - ERR("!Malloc for lane locks"); + ERR_W_ERRNO("Malloc for lane locks"); goto error_locks_malloc; } @@ -286,7 +286,7 @@ lane_boot(PMEMobjpool *pop) struct lane_layout *layout = lane_get_layout(pop, i); if ((err = lane_init(pop, &pop->lanes_desc.lane[i], layout))) { - ERR("!lane_init"); + ERR_W_ERRNO("lane_init"); goto error_lane_init; } } @@ -414,7 +414,8 @@ lane_check(PMEMobjpool *pop) layout = lane_get_layout(pop, j); if (ulog_check((struct ulog *)&layout->internal, OBJ_OFF_IS_VALID_FROM_CTX, &pop->p_ops) != 0) { - LOG(2, "lane %" PRIu64 " internal redo failed: %d", + CORE_LOG_ERROR( + "lane %" PRIu64 " internal redo failed: %d", j, err); return err; } @@ -479,7 +480,7 @@ get_lane_info_record(PMEMobjpool *pop) if (unlikely(info == NULL)) { info = Malloc(sizeof(struct lane_info)); if (unlikely(info == NULL)) { - FATAL("Malloc"); + CORE_LOG_FATAL("Malloc"); } info->pop_uuid_lo = pop->uuid_lo; info->lane_idx = UINT64_MAX; @@ -495,7 +496,7 @@ get_lane_info_record(PMEMobjpool *pop) if (unlikely(critnib_insert( Lane_info_ht, pop->uuid_lo, info) != 0)) { - FATAL("critnib_insert"); + CORE_LOG_FATAL("critnib_insert"); } } @@ -551,12 +552,12 @@ lane_release(PMEMobjpool *pop) ASSERTne(lane->lane_idx, UINT64_MAX); if (unlikely(lane->nest_count == 0)) { - FATAL("lane_release"); + CORE_LOG_FATAL("lane_release"); } else if (--(lane->nest_count) == 0) { if (unlikely(!util_bool_compare_and_swap64( &pop->lanes_desc.lane_locks[lane->lane_idx], 1, 0))) { - FATAL("util_bool_compare_and_swap64"); + CORE_LOG_FATAL("util_bool_compare_and_swap64"); } } } diff --git a/src/libpmemobj/libpmemobj.c b/src/libpmemobj/libpmemobj.c index 824b9973f76..b289671c0e3 100644 --- a/src/libpmemobj/libpmemobj.c +++ b/src/libpmemobj/libpmemobj.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2014-2023, Intel Corporation */ +/* Copyright 2014-2024, Intel Corporation */ /* * libpmemobj.c -- pmem entry points for libpmemobj @@ -49,15 +49,17 @@ pmemobj_check_versionU(unsigned major_required, unsigned minor_required) major_required, minor_required); if (major_required != PMEMOBJ_MAJOR_VERSION) { - ERR("libpmemobj major version mismatch (need %u, found %u)", + ERR_WO_ERRNO( + "libpmemobj major version mismatch (need %u, found %u)", major_required, PMEMOBJ_MAJOR_VERSION); - return out_get_errormsg(); + return last_error_msg_get(); } if (minor_required > PMEMOBJ_MINOR_VERSION) { - ERR("libpmemobj minor version mismatch (need %u, found %u)", + ERR_WO_ERRNO( + "libpmemobj minor version mismatch (need %u, found %u)", minor_required, PMEMOBJ_MINOR_VERSION); - return out_get_errormsg(); + return last_error_msg_get(); } return NULL; @@ -88,17 +90,17 @@ pmemobj_set_funcs( } /* - * pmemobj_errormsgU -- return last error message + * pmemobj_errormsgU -- return the last error message */ static inline const char * pmemobj_errormsgU(void) { - return out_get_errormsg(); + return last_error_msg_get(); } /* - * pmemobj_errormsg -- return last error message + * pmemobj_errormsg -- return the last error message */ const char * pmemobj_errormsg(void) diff --git a/src/libpmemobj/libpmemobj.link.in b/src/libpmemobj/libpmemobj.link.in index 5b730caa6b0..da9db4b9d57 100644 --- a/src/libpmemobj/libpmemobj.link.in +++ b/src/libpmemobj/libpmemobj.link.in @@ -1,5 +1,5 @@ # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2014-2020, Intel Corporation +# Copyright 2014-2024, Intel Corporation # # # src/libpmemobj.link -- linker link file for libpmemobj @@ -56,6 +56,9 @@ LIBPMEMOBJ_1.0 { pmemobj_list_insert_new; pmemobj_list_remove; pmemobj_list_move; + pmemobj_log_get_threshold; + pmemobj_log_set_function; + pmemobj_log_set_threshold; pmemobj_tx_begin; pmemobj_tx_stage; pmemobj_tx_abort; diff --git a/src/libpmemobj/list.c b/src/libpmemobj/list.c index 9eb1b7070f6..108ed9814b5 100644 --- a/src/libpmemobj/list.c +++ b/src/libpmemobj/list.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2015-2019, Intel Corporation */ +/* Copyright 2015-2024, Intel Corporation */ /* * list.c -- implementation of persistent atomic lists module @@ -9,7 +9,7 @@ #include "list.h" #include "obj.h" #include "os_thread.h" -#include "out.h" +#include "core_assert.h" #include "sync.h" #include "valgrind_internal.h" #include "memops.h" @@ -202,7 +202,9 @@ list_update_head(PMEMobjpool *pop, static void u64_add_offset(uint64_t *value, ssize_t off) { +#ifdef DEBUG /* variables required for ASSERTs below */ uint64_t prev = *value; +#endif if (off >= 0) { *value += (size_t)off; ASSERT(*value >= prev); /* detect overflow */ @@ -468,7 +470,7 @@ list_insert_new(PMEMobjpool *pop, struct pobj_action reserved; if (palloc_reserve(&pop->heap, size, constructor, arg, type_num, 0, 0, 0, &reserved) != 0) { - ERR("!palloc_reserve"); + ERR_W_ERRNO("palloc_reserve"); ret = -1; goto err_pmalloc; } @@ -559,7 +561,7 @@ list_insert_new_user(PMEMobjpool *pop, int ret; if ((ret = pmemobj_mutex_lock(pop, &user_head->lock))) { errno = ret; - LOG(2, "pmemobj_mutex_lock failed"); + CORE_LOG_ERROR("pmemobj_mutex_lock failed"); return -1; } @@ -598,7 +600,7 @@ list_insert(PMEMobjpool *pop, if ((ret = pmemobj_mutex_lock(pop, &head->lock))) { errno = ret; - LOG(2, "pmemobj_mutex_lock failed"); + CORE_LOG_ERROR("pmemobj_mutex_lock failed"); ret = -1; goto err; } @@ -726,7 +728,7 @@ list_remove_free_user(PMEMobjpool *pop, size_t pe_offset, int ret; if ((ret = pmemobj_mutex_lock(pop, &user_head->lock))) { errno = ret; - LOG(2, "pmemobj_mutex_lock failed"); + CORE_LOG_ERROR("pmemobj_mutex_lock failed"); return -1; } @@ -760,7 +762,7 @@ list_remove(PMEMobjpool *pop, if ((ret = pmemobj_mutex_lock(pop, &head->lock))) { errno = ret; - LOG(2, "pmemobj_mutex_lock failed"); + CORE_LOG_ERROR("pmemobj_mutex_lock failed"); ret = -1; goto err; } @@ -837,7 +839,7 @@ list_move(PMEMobjpool *pop, */ if ((ret = list_mutexes_lock(pop, head_new, head_old))) { errno = ret; - LOG(2, "list_mutexes_lock failed"); + CORE_LOG_ERROR("list_mutexes_lock failed"); ret = -1; goto err; } diff --git a/src/libpmemobj/memblock.c b/src/libpmemobj/memblock.c index 9ad6c2dc063..0276ad80baf 100644 --- a/src/libpmemobj/memblock.c +++ b/src/libpmemobj/memblock.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2016-2021, Intel Corporation */ +/* Copyright 2016-2024, Intel Corporation */ /* * memblock.c -- implementation of memory block @@ -21,7 +21,7 @@ #include "obj.h" #include "heap.h" #include "memblock.h" -#include "out.h" +#include "core_assert.h" #include "valgrind_internal.h" #include "alloc_class.h" @@ -1103,7 +1103,7 @@ huge_vg_init(const struct memory_block *m, int objects, if (objects && huge_get_state(m) == MEMBLOCK_ALLOCATED) { if (cb(m, arg) != 0) - FATAL("failed to initialize valgrind state"); + CORE_LOG_FATAL("failed to initialize valgrind state"); } } @@ -1143,7 +1143,7 @@ run_vg_init(const struct memory_block *m, int objects, if (objects) { if (run_iterate_used(m, cb, arg) != 0) - FATAL("failed to initialize valgrind state"); + CORE_LOG_FATAL("failed to initialize valgrind state"); } } @@ -1463,7 +1463,8 @@ memblock_detect_type(struct palloc_heap *heap, const struct memory_block *m) break; default: /* unreachable */ - FATAL("possible zone chunks metadata corruption"); + CORE_LOG_FATAL( + "possible zone chunks metadata corruption"); } return ret; } diff --git a/src/libpmemobj/memops.c b/src/libpmemobj/memops.c index fc5fe7d227a..7d86c41a32f 100644 --- a/src/libpmemobj/memops.c +++ b/src/libpmemobj/memops.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2016-2022, Intel Corporation */ +/* Copyright 2016-2024, Intel Corporation */ /* * memops.c -- aggregated memory operations helper implementation @@ -87,7 +87,7 @@ operation_log_transient_init(struct operation_log *log) struct ulog *src = Zalloc(sizeof(struct ulog) + ULOG_BASE_SIZE); if (src == NULL) { - ERR("!Zalloc"); + ERR_W_ERRNO("Zalloc"); return -1; } @@ -113,7 +113,7 @@ operation_log_persistent_init(struct operation_log *log, struct ulog *src = Zalloc(sizeof(struct ulog) + ULOG_BASE_SIZE); if (src == NULL) { - ERR("!Zalloc"); + ERR_W_ERRNO("Zalloc"); return -1; } @@ -174,7 +174,7 @@ operation_new(struct ulog *ulog, size_t ulog_base_nbytes, { struct operation_context *ctx = Zalloc(sizeof(*ctx)); if (ctx == NULL) { - ERR("!Zalloc"); + ERR_W_ERRNO("Zalloc"); goto error_ctx_alloc; } @@ -349,7 +349,7 @@ operation_merge_entry_add(struct operation_context *ctx, if (VECQ_ENQUEUE(&ctx->merge_entries, entry) != 0) { /* this is fine, only runtime perf will get slower */ - LOG(2, "out of memory - unable to track entries"); + CORE_LOG_WARNING("out of memory - unable to track entries"); } } @@ -466,7 +466,10 @@ operation_add_buffer(struct operation_context *ctx, ulog_clobber_entry(next_entry, ctx->p_ops); /* create a persistent log entry */ - struct ulog_entry_buf *e = ulog_entry_buf_create(ctx->ulog_curr, +#ifdef DEBUG /* variables required for ASSERTs below */ + struct ulog_entry_buf *e = +#endif + ulog_entry_buf_create(ctx->ulog_curr, ctx->ulog_curr_offset, ctx->ulog_curr_gen_num, dest, src, data_size, @@ -569,7 +572,7 @@ operation_user_buffer_verify_align(struct operation_context *ctx, ssize_t capacity_unaligned = (ssize_t)userbuf->size - size_diff - (ssize_t)sizeof(struct ulog); if (capacity_unaligned < (ssize_t)CACHELINE_SIZE) { - ERR("Capacity insufficient"); + ERR_WO_ERRNO("Capacity insufficient"); return -1; } @@ -580,7 +583,7 @@ operation_user_buffer_verify_align(struct operation_context *ctx, userbuf->size = capacity_aligned + sizeof(struct ulog); if (operation_user_buffer_try_insert(ctx->p_ops->base, userbuf)) { - ERR("Buffer currently used"); + ERR_WO_ERRNO("Buffer currently used"); return -1; } @@ -685,7 +688,7 @@ operation_reserve(struct operation_context *ctx, size_t new_capacity) { if (new_capacity > ctx->ulog_capacity) { if (ctx->extend == NULL) { - ERR("no extend function present"); + ERR_WO_ERRNO("no extend function present"); return -1; } diff --git a/src/libpmemobj/obj.c b/src/libpmemobj/obj.c index 8b23a54db1c..886e3f16cee 100644 --- a/src/libpmemobj/obj.c +++ b/src/libpmemobj/obj.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2014-2023, Intel Corporation */ +/* Copyright 2014-2024, Intel Corporation */ /* * obj.c -- transactional object store implementation @@ -87,7 +87,7 @@ obj_ctl_init_and_load(PMEMobjpool *pop) LOG(3, "pop %p", pop); if (pop != NULL && (pop->ctl = ctl_new()) == NULL) { - LOG(2, "!ctl_new"); + CORE_LOG_ERROR_W_ERRNO("ctl_new"); return -1; } @@ -102,8 +102,8 @@ obj_ctl_init_and_load(PMEMobjpool *pop) if (env_config != NULL) { if (ctl_load_config_from_string(pop ? pop->ctl : NULL, pop, env_config) != 0) { - LOG(2, "unable to parse config stored in %s " - "environment variable", + CORE_LOG_ERROR( + "unable to parse config stored in %s environment variable", OBJ_CONFIG_ENV_VARIABLE); goto err; } @@ -113,10 +113,9 @@ obj_ctl_init_and_load(PMEMobjpool *pop) if (env_config_file != NULL && env_config_file[0] != '\0') { if (ctl_load_config_from_file(pop ? pop->ctl : NULL, pop, env_config_file) != 0) { - LOG(2, "unable to parse config stored in %s " - "file (from %s environment variable)", - env_config_file, - OBJ_CONFIG_FILE_ENV_VARIABLE); + CORE_LOG_ERROR( + "unable to parse config stored in %s file (from %s environment variable)", + env_config_file, OBJ_CONFIG_FILE_ENV_VARIABLE); goto err; } } @@ -146,7 +145,7 @@ obj_pool_init(void) if (pools_ht == NULL) { c = critnib_new(); if (c == NULL) - FATAL("!critnib_new for pools_ht"); + CORE_LOG_FATAL_W_ERRNO("critnib_new for pools_ht"); if (!util_bool_compare_and_swap64(&pools_ht, NULL, c)) critnib_delete(c); } @@ -154,7 +153,7 @@ obj_pool_init(void) if (pools_tree == NULL) { c = critnib_new(); if (c == NULL) - FATAL("!critnib_new for pools_tree"); + CORE_LOG_FATAL_W_ERRNO("critnib_new for pools_tree"); if (!util_bool_compare_and_swap64(&pools_tree, NULL, c)) critnib_delete(c); } @@ -209,7 +208,7 @@ obj_init(void) pmalloc_global_ctl_register(); if (obj_ctl_init_and_load(NULL)) - FATAL("error: %s", pmemobj_errormsg()); + CORE_LOG_FATAL("error: %s", pmemobj_errormsg()); lane_info_boot(); } @@ -250,7 +249,7 @@ static void obj_msync_nofail(const void *addr, size_t size) { if (pmem_msync(addr, size)) - FATAL("!pmem_msync"); + CORE_LOG_FATAL_W_ERRNO("pmem_msync"); } /* @@ -660,12 +659,12 @@ obj_runtime_init_common(PMEMobjpool *pop) LOG(3, "pop %p", pop); if ((errno = lane_boot(pop)) != 0) { - ERR("!lane_boot"); + ERR_W_ERRNO("lane_boot"); return errno; } if ((errno = lane_recover_and_section_boot(pop)) != 0) { - ERR("!lane_recover_and_section_boot"); + ERR_W_ERRNO("lane_recover_and_section_boot"); return errno; } @@ -723,7 +722,7 @@ obj_descr_create(PMEMobjpool *pop, const char *layout, size_t poolsize) errno = palloc_init((char *)pop + pop->heap_offset, heap_size, &pop->heap_size, p_ops); if (errno != 0) { - ERR("!palloc_init"); + ERR_W_ERRNO("palloc_init"); return -1; } @@ -771,22 +770,22 @@ obj_descr_check(PMEMobjpool *pop, const char *layout, size_t poolsize) void *dscp = (void *)((uintptr_t)pop + sizeof(struct pool_hdr)); if (!util_checksum(dscp, OBJ_DSC_P_SIZE, &pop->checksum, 0, 0)) { - ERR("invalid checksum of pool descriptor"); + ERR_WO_ERRNO("invalid checksum of pool descriptor"); errno = EINVAL; return -1; } if (layout && strncmp(pop->layout, layout, PMEMOBJ_MAX_LAYOUT)) { - ERR("wrong layout (\"%s\"), " - "pool created with layout \"%s\"", + ERR_WO_ERRNO( + "wrong layout (\"%s\"), pool created with layout \"%s\"", layout, pop->layout); errno = EINVAL; return -1; } if (pop->heap_offset % Pagesize) { - ERR("unaligned heap: off %" PRIu64, pop->heap_offset); + ERR_WO_ERRNO("unaligned heap: off %" PRIu64, pop->heap_offset); errno = EINVAL; return -1; } @@ -957,17 +956,17 @@ obj_runtime_init(PMEMobjpool *pop, int rdonly, int boot, unsigned nlanes) VALGRIND_DO_MAKE_MEM_NOACCESS(end, (char *)pop + pop->set->poolsize - (char *)end); } -#endif +#endif /* VG_MEMCHECK_ENABLED */ obj_pool_init(); if ((errno = critnib_insert(pools_ht, pop->uuid_lo, pop))) { - ERR("!critnib_insert to pools_ht"); + ERR_W_ERRNO("critnib_insert to pools_ht"); goto err_critnib_insert; } if ((errno = critnib_insert(pools_tree, (uint64_t)pop, pop))) { - ERR("!critnib_insert to pools_tree"); + ERR_W_ERRNO("critnib_insert to pools_tree"); goto err_tree_insert; } } @@ -982,7 +981,7 @@ obj_runtime_init(PMEMobjpool *pop, int rdonly, int boot, unsigned nlanes) operation_user_buffer_range_cmp, sizeof(struct user_buffer_def)); if (pop->ulog_user_buffers.map == NULL) { - ERR("!ravl_new_sized"); + ERR_W_ERRNO("ravl_new_sized"); goto err_user_buffers_map; } pop->ulog_user_buffers.verify = 0; @@ -1001,7 +1000,10 @@ obj_runtime_init(PMEMobjpool *pop, int rdonly, int boot, unsigned nlanes) util_mutex_destroy(&pop->ulog_user_buffers.lock); ctl_delete(pop->ctl); err_ctl:; - void *n = critnib_remove(pools_tree, (uint64_t)pop); +#ifdef DEBUG /* variables required for ASSERTs below */ + void *n = +#endif + critnib_remove(pools_tree, (uint64_t)pop); ASSERTne(n, NULL); err_tree_insert: critnib_remove(pools_ht, pop->uuid_lo); @@ -1031,8 +1033,8 @@ obj_get_nlanes(void) if (env_nlanes) { int nlanes = atoi(env_nlanes); if (nlanes <= 0) { - ERR("%s variable must be a positive integer", - OBJ_NLANES_ENV_VARIABLE); + ERR_WO_ERRNO("%s variable must be a positive integer", + OBJ_NLANES_ENV_VARIABLE); errno = EINVAL; goto no_valid_env; } @@ -1060,7 +1062,7 @@ pmemobj_createU(const char *path, const char *layout, /* check length of layout */ if (layout && (strlen(layout) >= PMEMOBJ_MAX_LAYOUT)) { - ERR("Layout too long"); + ERR_WO_ERRNO("Layout too long"); errno = EINVAL; return NULL; } @@ -1085,7 +1087,7 @@ pmemobj_createU(const char *path, const char *layout, if (util_pool_create(&set, path, poolsize, PMEMOBJ_MIN_POOL, PMEMOBJ_MIN_PART, &adj_pool_attr, &runtime_nlanes, REPLICAS_ENABLED) != 0) { - LOG(2, "cannot create pool or pool set"); + CORE_LOG_ERROR("cannot create pool or pool set"); os_mutex_unlock(&pools_mutex); return NULL; } @@ -1109,7 +1111,7 @@ pmemobj_createU(const char *path, const char *layout, /* initialize replica runtime - is_pmem, funcs, ... */ if (obj_replica_init(rep, set, r) != 0) { - ERR("initialization of replica #%u failed", r); + ERR_WO_ERRNO("initialization of replica #%u failed", r); goto err; } @@ -1122,14 +1124,14 @@ pmemobj_createU(const char *path, const char *layout, /* create pool descriptor */ if (obj_descr_create(pop, layout, set->poolsize) != 0) { - LOG(2, "creation of pool descriptor failed"); + CORE_LOG_ERROR("creation of pool descriptor failed"); goto err; } /* initialize runtime parts - lanes, obj stores, ... */ if (obj_runtime_init(pop, 0, 1 /* boot */, runtime_nlanes) != 0) { - ERR("pool initialization failed"); + ERR_WO_ERRNO("pool initialization failed"); goto err; } @@ -1179,12 +1181,12 @@ obj_check_basic_local(PMEMobjpool *pop, size_t mapped_size) int consistent = 1; if (pop->run_id % 2) { - ERR("invalid run_id %" PRIu64, pop->run_id); + ERR_WO_ERRNO("invalid run_id %" PRIu64, pop->run_id); consistent = 0; } if ((errno = lane_check(pop)) != 0) { - LOG(2, "!lane_check"); + CORE_LOG_ERROR_W_ERRNO("lane_check"); consistent = 0; } @@ -1193,7 +1195,7 @@ obj_check_basic_local(PMEMobjpool *pop, size_t mapped_size) errno = palloc_heap_check((char *)pop + pop->heap_offset, heap_size); if (errno != 0) { - LOG(2, "!heap_check"); + CORE_LOG_ERROR_W_ERRNO("heap_check"); consistent = 0; } @@ -1233,7 +1235,7 @@ obj_pool_open(struct pool_set **set, const char *path, unsigned flags, { if (util_pool_open(set, path, PMEMOBJ_MIN_PART, &Obj_open_attr, nlanes, NULL, flags) != 0) { - LOG(2, "cannot open pool or pool set"); + CORE_LOG_ERROR("cannot open pool or pool set"); return -1; } @@ -1241,7 +1243,7 @@ obj_pool_open(struct pool_set **set, const char *path, unsigned flags, /* read-only mode is not supported in libpmemobj */ if ((*set)->rdonly) { - ERR("read-only mode is not supported"); + ERR_WO_ERRNO("read-only mode is not supported"); errno = EINVAL; goto err_rdonly; } @@ -1274,7 +1276,7 @@ obj_replicas_init(struct pool_set *set) /* initialize replica runtime - is_pmem, funcs, ... */ if (obj_replica_init(rep, set, r) != 0) { - ERR("initialization of replica #%u failed", r); + ERR_WO_ERRNO("initialization of replica #%u failed", r); goto err; } @@ -1314,7 +1316,7 @@ obj_replicas_check_basic(PMEMobjpool *pop) for (unsigned r = 0; r < pop->set->nreplicas; r++) { rep = pop->set->replica[r]->part[0].addr; if (obj_check_basic(rep, pop->set->poolsize) == 0) { - ERR("inconsistent replica #%u", r); + ERR_WO_ERRNO("inconsistent replica #%u", r); return -1; } } @@ -1370,7 +1372,8 @@ obj_open_common(const char *path, const char *layout, unsigned flags, int boot) PMEMobjpool *rep = repset->part[0].addr; /* check descriptor */ if (obj_descr_check(rep, layout, set->poolsize) != 0) { - LOG(2, "descriptor check of replica #%u failed", r); + CORE_LOG_ERROR( + "descriptor check of replica #%u failed", r); goto err_descr_check; } } @@ -1399,7 +1402,7 @@ obj_open_common(const char *path, const char *layout, unsigned flags, int boot) #endif /* initialize runtime parts - lanes, obj stores, ... */ if (obj_runtime_init(pop, 0, boot, runtime_nlanes) != 0) { - ERR("pool initialization failed"); + ERR_WO_ERRNO("pool initialization failed"); goto err_runtime_init; } @@ -1531,11 +1534,11 @@ pmemobj_close(PMEMobjpool *pop) os_mutex_lock(&pools_mutex); if (critnib_remove(pools_ht, pop->uuid_lo) != pop) { - ERR("critnib_remove for pools_ht"); + ERR_WO_ERRNO("critnib_remove for pools_ht"); } if (critnib_remove(pools_tree, (uint64_t)pop) != pop) - ERR("critnib_remove for pools_tree"); + ERR_WO_ERRNO("critnib_remove for pools_tree"); if (_pobj_cached_pool.pop == pop) { _pobj_cached_pool.pop = NULL; @@ -1718,7 +1721,7 @@ obj_alloc_construct(PMEMobjpool *pop, PMEMoid *oidp, size_t size, pmemobj_constr constructor, void *arg) { if (size > PMEMOBJ_MAX_ALLOC_SIZE) { - ERR("requested size too large"); + ERR_WO_ERRNO("requested size too large"); errno = ENOMEM; return -1; } @@ -1761,7 +1764,7 @@ pmemobj_alloc(PMEMobjpool *pop, PMEMoid *oidp, size_t size, _POBJ_DEBUG_NOTICE_IN_TX(); if (size == 0) { - ERR("allocation with size 0"); + ERR_WO_ERRNO("allocation with size 0"); errno = EINVAL; return -1; } @@ -1792,13 +1795,13 @@ pmemobj_xalloc(PMEMobjpool *pop, PMEMoid *oidp, size_t size, _POBJ_DEBUG_NOTICE_IN_TX(); if (size == 0) { - ERR("allocation with size 0"); + ERR_WO_ERRNO("allocation with size 0"); errno = EINVAL; return -1; } if (flags & ~POBJ_TX_XALLOC_VALID_FLAGS) { - ERR("unknown flags 0x%" PRIx64, + ERR_WO_ERRNO("unknown flags 0x%" PRIx64, flags & ~POBJ_TX_XALLOC_VALID_FLAGS); errno = EINVAL; return -1; @@ -1837,7 +1840,7 @@ pmemobj_zalloc(PMEMobjpool *pop, PMEMoid *oidp, size_t size, _POBJ_DEBUG_NOTICE_IN_TX(); if (size == 0) { - ERR("allocation with size 0"); + ERR_WO_ERRNO("allocation with size 0"); errno = EINVAL; return -1; } @@ -1915,7 +1918,7 @@ obj_realloc_common(PMEMobjpool *pop, } if (size > PMEMOBJ_MAX_ALLOC_SIZE) { - ERR("requested size too large"); + ERR_WO_ERRNO("requested size too large"); errno = ENOMEM; return -1; } @@ -2292,7 +2295,7 @@ pmemobj_xpersist(PMEMobjpool *pop, const void *addr, size_t len, unsigned flags) if (flags & ~OBJ_X_VALID_FLAGS) { errno = EINVAL; - ERR("invalid flags 0x%x", flags); + ERR_WO_ERRNO("invalid flags 0x%x", flags); return -1; } @@ -2310,7 +2313,7 @@ pmemobj_xflush(PMEMobjpool *pop, const void *addr, size_t len, unsigned flags) if (flags & ~OBJ_X_VALID_FLAGS) { errno = EINVAL; - ERR("invalid flags 0x%x", flags); + ERR_WO_ERRNO("invalid flags 0x%x", flags); return -1; } @@ -2412,13 +2415,13 @@ pmemobj_root_construct(PMEMobjpool *pop, size_t size, arg); if (size > PMEMOBJ_MAX_ALLOC_SIZE) { - ERR("requested size too large"); + ERR_WO_ERRNO("requested size too large"); errno = ENOMEM; return OID_NULL; } if (size == 0 && pop->root_offset == 0) { - ERR("requested size cannot equals zero"); + ERR_WO_ERRNO("requested size cannot equals zero"); errno = EINVAL; return OID_NULL; } @@ -2432,7 +2435,7 @@ pmemobj_root_construct(PMEMobjpool *pop, size_t size, if (size > pop->root_size && obj_alloc_root(pop, size, constructor, arg)) { pmemobj_mutex_unlock_nofail(pop, &pop->rootlock); - LOG(2, "obj_realloc_root failed"); + CORE_LOG_ERROR("obj_realloc_root failed"); PMEMOBJ_API_END(); return OID_NULL; } @@ -2554,7 +2557,7 @@ pmemobj_xreserve(PMEMobjpool *pop, struct pobj_action *act, PMEMoid oid = OID_NULL; if (flags & ~POBJ_ACTION_XRESERVE_VALID_FLAGS) { - ERR("unknown flags 0x%" PRIx64, + ERR_WO_ERRNO("unknown flags 0x%" PRIx64, flags & ~POBJ_ACTION_XRESERVE_VALID_FLAGS); errno = EINVAL; return oid; @@ -2663,7 +2666,8 @@ pmemobj_defrag(PMEMobjpool *pop, PMEMoid **oidv, size_t oidcnt, continue; if (oidv[i]->pool_uuid_lo != pop->uuid_lo) { ret = -1; - ERR("Not all PMEMoids belong to the provided pool"); + ERR_WO_ERRNO( + "Not all PMEMoids belong to the provided pool"); goto out; } objv[j++] = &oidv[i]->off; @@ -2732,7 +2736,7 @@ pmemobj_list_insert_new(PMEMobjpool *pop, size_t pe_offset, void *head, ASSERT(pe_offset <= size - sizeof(struct list_entry)); if (size > PMEMOBJ_MAX_ALLOC_SIZE) { - ERR("requested size too large"); + ERR_WO_ERRNO("requested size too large"); errno = ENOMEM; return OID_NULL; } diff --git a/src/libpmemobj/obj_log.c b/src/libpmemobj/obj_log.c new file mode 100644 index 00000000000..ad3791c1844 --- /dev/null +++ b/src/libpmemobj/obj_log.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* Copyright 2024, Intel Corporation */ + +/* + * obj_log.c -- the public interface to control the logging output + */ +#include + +#include "log_internal.h" +#include "util.h" + +/* + * pmemobj_log_set_threshold -- set the logging threshold value + */ +int +pmemobj_log_set_threshold(enum pmemobj_log_threshold threshold, + enum pmemobj_log_level value) +{ + int ret = core_log_set_threshold((enum core_log_threshold)threshold, + (enum core_log_level)value); + return core_log_error_translate(ret); +} + +/* + * pmemobj_log_get_threshold -- get the logging value threshold value + */ +int +pmemobj_log_get_threshold(enum pmemobj_log_threshold threshold, + enum pmemobj_log_level *value) +{ + int ret = core_log_get_threshold((enum core_log_threshold)threshold, + (enum core_log_level *)value); + return core_log_error_translate(ret); +} + +/* + * pmemobj_log_set_function -- set the log function pointer either to + * a user-provided function pointer or to the default logging function. + */ +int +pmemobj_log_set_function(pmemobj_log_function *log_function) +{ + int ret = core_log_set_function((core_log_function *)log_function); + return core_log_error_translate(ret); +} diff --git a/src/libpmemobj/palloc.c b/src/libpmemobj/palloc.c index 9420440277d..852deca50e3 100644 --- a/src/libpmemobj/palloc.c +++ b/src/libpmemobj/palloc.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2015-2022, Intel Corporation */ +/* Copyright 2015-2024, Intel Corporation */ /* * palloc.c -- implementation of pmalloc POSIX-like API @@ -193,7 +193,7 @@ palloc_reservation_create(struct palloc_heap *heap, size_t size, (uint8_t)class_id); if (c == NULL) { - ERR("no allocation class for size %lu bytes", size); + ERR_WO_ERRNO("no allocation class for size %lu bytes", size); errno = EINVAL; return -1; } @@ -208,7 +208,7 @@ palloc_reservation_create(struct palloc_heap *heap, size_t size, */ ssize_t size_idx = alloc_class_calc_size_idx(c, size); if (size_idx < 0) { - ERR("allocation class not suitable for size %lu bytes", + ERR_WO_ERRNO("allocation class not suitable for size %lu bytes", size); errno = EINVAL; return -1; @@ -272,7 +272,7 @@ palloc_heap_action_exec(struct palloc_heap *heap, #ifdef DEBUG enum memblock_state s = act->m.m_ops->get_state(&act->m); if (s == act->new_state || s == MEMBLOCK_STATE_UNKNOWN) { - ERR("invalid operation or heap corruption"); + ERR_WO_ERRNO("invalid operation or heap corruption"); ASSERT(0); } #endif /* DEBUG */ @@ -301,10 +301,11 @@ palloc_restore_free_chunk_state(struct palloc_heap *heap, HEAP_ARENA_PER_THREAD); if (heap_free_chunk_reuse(heap, b, m) != 0) { if (errno == EEXIST) { - FATAL( + CORE_LOG_FATAL( "duplicate runtime chunk state, possible double free"); } else { - LOG(2, "unable to track runtime chunk state"); + CORE_LOG_WARNING( + "unable to track runtime chunk state"); } } heap_bucket_release(b); @@ -397,10 +398,14 @@ palloc_heap_action_on_process(struct palloc_heap *heap, act->m.m_ops->get_real_size(&act->m)); } } else if (act->new_state == MEMBLOCK_FREE) { +#if VG_MEMCHECK_ENABLED if (On_memcheck) { void *ptr = act->m.m_ops->get_user_data(&act->m); VALGRIND_DO_MEMPOOL_FREE(heap->layout, ptr); - } else if (On_pmemcheck) { + } +#endif /* VG_MEMCHECK_ENABLED */ +#if VG_PMEMCHECK_ENABLED + if (On_pmemcheck) { /* * The sync module, responsible for implementations of * persistent memory resident volatile variables, @@ -417,7 +422,7 @@ palloc_heap_action_on_process(struct palloc_heap *heap, size_t size = act->m.m_ops->get_real_size(&act->m); VALGRIND_REGISTER_PMEM_MAPPING(ptr, size); } - +#endif /* VG_PMEMCHECK_ENABLED */ STATS_SUB(heap->stats, persistent, heap_curr_allocated, act->m.m_ops->get_real_size(&act->m)); if (act->m.type == MEMORY_BLOCK_RUN) { @@ -1274,6 +1279,7 @@ palloc_init(void *heap_start, uint64_t heap_size, uint64_t *sizep, return heap_init(heap_start, heap_size, sizep, p_ops); } +#if VG_MEMCHECK_ENABLED /* * palloc_heap_end -- returns first address after heap */ @@ -1282,6 +1288,7 @@ palloc_heap_end(struct palloc_heap *h) { return heap_end(h); } +#endif /* VG_MEMCHECK_ENABLED */ /* * palloc_heap_check -- verifies heap state diff --git a/src/libpmemobj/palloc.h b/src/libpmemobj/palloc.h index 52a1f533d3f..31ddecd5595 100644 --- a/src/libpmemobj/palloc.h +++ b/src/libpmemobj/palloc.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause */ -/* Copyright 2015-2022, Intel Corporation */ +/* Copyright 2015-2024, Intel Corporation */ /* * palloc.h -- internal definitions for persistent allocator @@ -89,7 +89,9 @@ int palloc_buckets_init(struct palloc_heap *heap); int palloc_init(void *heap_start, uint64_t heap_size, uint64_t *sizep, struct pmem_ops *p_ops); +#if VG_MEMCHECK_ENABLED void *palloc_heap_end(struct palloc_heap *h); +#endif /* VG_MEMCHECK_ENABLED */ int palloc_heap_check(void *heap_start, uint64_t heap_size); void palloc_heap_cleanup(struct palloc_heap *heap); size_t palloc_heap(void *heap_start); diff --git a/src/libpmemobj/pmalloc.c b/src/libpmemobj/pmalloc.c index 95b49bcc407..e0c0e236772 100644 --- a/src/libpmemobj/pmalloc.c +++ b/src/libpmemobj/pmalloc.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2015-2021, Intel Corporation */ +/* Copyright 2015-2024, Intel Corporation */ /* * pmalloc.c -- implementation of pmalloc POSIX-like API @@ -166,7 +166,10 @@ pfree(PMEMobjpool *pop, uint64_t *off) struct operation_context *ctx = pmalloc_operation_hold_type(pop, OPERATION_INTERNAL, 1); - int ret = palloc_operation(&pop->heap, *off, off, 0, NULL, NULL, +#ifdef DEBUG /* variables required for ASSERTs below */ + int ret = +#endif + palloc_operation(&pop->heap, *off, off, 0, NULL, NULL, 0, 0, 0, 0, ctx); ASSERTeq(ret, 0); @@ -231,13 +234,13 @@ CTL_WRITE_HANDLER(desc)(void *ctx, } if (p->alignment != 0 && p->unit_size % p->alignment != 0) { - ERR("unit size must be evenly divisible by alignment"); + ERR_WO_ERRNO("unit size must be evenly divisible by alignment"); errno = EINVAL; return -1; } if (p->alignment > (MEGABYTE * 2)) { - ERR("alignment cannot be larger than 2 megabytes"); + ERR_WO_ERRNO("alignment cannot be larger than 2 megabytes"); errno = EINVAL; return -1; } @@ -255,14 +258,15 @@ CTL_WRITE_HANDLER(desc)(void *ctx, break; case MAX_POBJ_HEADER_TYPES: default: - ERR("invalid header type"); + ERR_WO_ERRNO("invalid header type"); errno = EINVAL; return -1; } if (PMDK_SLIST_EMPTY(indexes)) { if (alloc_class_find_first_free_slot(ac, &id) != 0) { - ERR("no available free allocation class identifier"); + ERR_WO_ERRNO( + "no available free allocation class identifier"); errno = EINVAL; return -1; } @@ -271,7 +275,7 @@ CTL_WRITE_HANDLER(desc)(void *ctx, ASSERTeq(strcmp(idx->name, "class_id"), 0); if (idx->value < 0 || idx->value >= MAX_ALLOCATION_CLASSES) { - ERR("class id outside of the allowed range"); + ERR_WO_ERRNO("class id outside of the allowed range"); errno = ERANGE; return -1; } @@ -279,7 +283,8 @@ CTL_WRITE_HANDLER(desc)(void *ctx, id = (uint8_t)idx->value; if (alloc_class_reserve(ac, id) != 0) { - ERR("attempted to overwrite an allocation class"); + ERR_WO_ERRNO( + "attempted to overwrite an allocation class"); errno = EEXIST; return -1; } @@ -324,6 +329,9 @@ pmalloc_header_type_parser(const void *arg, void *dest, size_t dest_size) { const char *vstr = arg; enum pobj_header_type *htype = dest; +#ifndef DEBUG + SUPPRESS_UNUSED(dest_size); +#endif ASSERTeq(dest_size, sizeof(enum pobj_header_type)); if (strcmp(vstr, "none") == 0) { @@ -333,7 +341,7 @@ pmalloc_header_type_parser(const void *arg, void *dest, size_t dest_size) } else if (strcmp(vstr, "legacy") == 0) { *htype = POBJ_HEADER_LEGACY; } else { - ERR("invalid header type"); + ERR_WO_ERRNO("invalid header type"); errno = EINVAL; return -1; } @@ -358,7 +366,7 @@ CTL_READ_HANDLER(desc)(void *ctx, ASSERTeq(strcmp(idx->name, "class_id"), 0); if (idx->value < 0 || idx->value >= MAX_ALLOCATION_CLASSES) { - ERR("class id outside of the allowed range"); + ERR_WO_ERRNO("class id outside of the allowed range"); errno = ERANGE; return -1; } @@ -369,7 +377,7 @@ CTL_READ_HANDLER(desc)(void *ctx, heap_alloc_classes(&pop->heap), id); if (c == NULL) { - ERR("class with the given id does not exist"); + ERR_WO_ERRNO("class with the given id does not exist"); errno = ENOENT; return -1; } @@ -448,7 +456,9 @@ CTL_RUNNABLE_HANDLER(extend)(void *ctx, ssize_t arg_in = *(ssize_t *)arg; if (arg_in < (ssize_t)PMEMOBJ_MIN_PART) { - ERR("incorrect size for extend, must be larger than %" PRIu64, + ERR_WO_ERRNO( + "incorrect size for extend, must be larger than %" + PRIu64, PMEMOBJ_MIN_PART); return -1; } @@ -498,7 +508,9 @@ CTL_WRITE_HANDLER(granularity)(void *ctx, ssize_t arg_in = *(int *)arg; if (arg_in != 0 && arg_in < (ssize_t)PMEMOBJ_MIN_PART) { - ERR("incorrect grow size, must be 0 or larger than %" PRIu64, + ERR_WO_ERRNO( + "incorrect grow size, must be 0 or larger than %" + PRIu64, PMEMOBJ_MIN_PART); return -1; } @@ -561,7 +573,7 @@ CTL_WRITE_HANDLER(max)(void *ctx, int ret = heap_set_narenas_max(&pop->heap, size); if (ret) { - LOG(1, "cannot change max arena number"); + ERR_WO_ERRNO("cannot change max arena number"); return -1; } @@ -627,7 +639,7 @@ CTL_WRITE_HANDLER(arena_id)(void *ctx, * or if it is not equal zero */ if (arena_id < 1 || arena_id > narenas) { - LOG(1, "arena id outside of the allowed range: <1,%u>", + ERR_WO_ERRNO("arena id outside of the allowed range: <1,%u>", narenas); errno = ERANGE; return -1; @@ -665,14 +677,14 @@ CTL_WRITE_HANDLER(automatic)(void *ctx, enum ctl_query_source source, * or if it is not equal zero */ if (arena_id < 1 || arena_id > narenas) { - LOG(1, "arena id outside of the allowed range: <1,%u>", + ERR_WO_ERRNO("arena id outside of the allowed range: <1,%u>", narenas); errno = ERANGE; return -1; } if (arg_in != 0 && arg_in != 1) { - LOG(1, "incorrect arena state, must be 0 or 1"); + ERR_WO_ERRNO("incorrect arena state, must be 0 or 1"); return -1; } @@ -704,7 +716,7 @@ CTL_READ_HANDLER(automatic)(void *ctx, * or if it is not equal zero */ if (arena_id < 1 || arena_id > narenas) { - LOG(1, "arena id outside of the allowed range: <1,%u>", + ERR_WO_ERRNO("arena id outside of the allowed range: <1,%u>", narenas); errno = ERANGE; return -1; @@ -752,7 +764,7 @@ CTL_READ_HANDLER(size)(void *ctx, * or if it is not equal zero */ if (arena_id < 1 || arena_id > narenas) { - LOG(1, "arena id outside of the allowed range: <1,%u>", + ERR_WO_ERRNO("arena id outside of the allowed range: <1,%u>", narenas); errno = ERANGE; return -1; @@ -894,6 +906,9 @@ arenas_assignment_type_parser(const void *arg, void *dest, size_t dest_size) { const char *vstr = arg; enum pobj_arenas_assignment_type *atype = dest; +#ifndef DEBUG + SUPPRESS_UNUSED(dest_size); +#endif ASSERTeq(dest_size, sizeof(enum pobj_header_type)); if (strcmp(vstr, "global") == 0) { @@ -901,7 +916,7 @@ arenas_assignment_type_parser(const void *arg, void *dest, size_t dest_size) } else if (strcmp(vstr, "thread") == 0) { *atype = POBJ_ARENAS_ASSIGNMENT_THREAD_KEY; } else { - ERR("invalid arena assignment type"); + ERR_WO_ERRNO("invalid arena assignment type"); errno = EINVAL; return -1; } @@ -951,7 +966,7 @@ CTL_WRITE_HANDLER(arenas_default_max)(void *ctx, unsigned size = *(unsigned *)arg; if (size == 0) { - LOG(1, "number of default arenas can't be 0"); + ERR_WO_ERRNO("number of default arenas can't be 0"); return -1; } diff --git a/src/libpmemobj/stats.c b/src/libpmemobj/stats.c index 423c94ee31a..2f3e23e302e 100644 --- a/src/libpmemobj/stats.c +++ b/src/libpmemobj/stats.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2017-2021, Intel Corporation */ +/* Copyright 2017-2024, Intel Corporation */ /* * stats.c -- implementation of statistics @@ -7,6 +7,7 @@ #include "obj.h" #include "stats.h" +#include "core_assert.h" STATS_CTL_HANDLER(persistent, curr_allocated, heap_curr_allocated); @@ -49,6 +50,9 @@ stats_enabled_parser(const void *arg, void *dest, size_t dest_size) { const char *vstr = arg; enum pobj_stats_enabled *enabled = dest; +#ifndef DEBUG + SUPPRESS_UNUSED(dest_size); +#endif ASSERTeq(dest_size, sizeof(enum pobj_stats_enabled)); int bool_out; @@ -67,7 +71,7 @@ stats_enabled_parser(const void *arg, void *dest, size_t dest_size) } else if (strcmp(vstr, "transient") == 0) { *enabled = POBJ_STATS_ENABLED_TRANSIENT; } else { - ERR("invalid enable type"); + ERR_WO_ERRNO("invalid enable type"); errno = EINVAL; return -1; } @@ -117,7 +121,7 @@ stats_new(PMEMobjpool *pop) { struct stats *s = Malloc(sizeof(*s)); if (s == NULL) { - ERR("!Malloc"); + ERR_W_ERRNO("Malloc"); return NULL; } diff --git a/src/libpmemobj/sync.c b/src/libpmemobj/sync.c index ee7b7198ab3..c8c4428d44e 100644 --- a/src/libpmemobj/sync.c +++ b/src/libpmemobj/sync.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2015-2023, Intel Corporation */ +/* Copyright 2015-2024, Intel Corporation */ /* * sync.c -- persistent memory resident synchronization primitives @@ -40,14 +40,14 @@ _get_value(uint64_t pop_runid, volatile uint64_t *runid, void *value, void *arg, initializer = 1; if (init_value(value, arg)) { - ERR("error initializing lock"); + ERR_WO_ERRNO("error initializing lock"); util_fetch_and_and64(runid, 0); return -1; } if (util_bool_compare_and_swap64(runid, pop_runid - 1, pop_runid) == 0) { - ERR("error setting lock runid"); + ERR_WO_ERRNO("error setting lock runid"); return -1; } } diff --git a/src/libpmemobj/sync.h b/src/libpmemobj/sync.h index 46aa1bb221c..bc206826c16 100644 --- a/src/libpmemobj/sync.h +++ b/src/libpmemobj/sync.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause */ -/* Copyright 2016-2020, Intel Corporation */ +/* Copyright 2016-2024, Intel Corporation */ /* * sync.h -- internal to obj synchronization API @@ -84,7 +84,7 @@ pmemobj_mutex_lock_nofail(PMEMobjpool *pop, PMEMmutex *mutexp) int ret = pmemobj_mutex_lock(pop, mutexp); if (ret) { errno = ret; - FATAL("!pmemobj_mutex_lock"); + CORE_LOG_FATAL_W_ERRNO("pmemobj_mutex_lock"); } } @@ -99,7 +99,7 @@ pmemobj_mutex_unlock_nofail(PMEMobjpool *pop, PMEMmutex *mutexp) int ret = pmemobj_mutex_unlock(pop, mutexp); if (ret) { errno = ret; - FATAL("!pmemobj_mutex_unlock"); + CORE_LOG_FATAL_W_ERRNO("pmemobj_mutex_unlock"); } } diff --git a/src/libpmemobj/tx.c b/src/libpmemobj/tx.c index b119230dac9..bdb9f18b075 100644 --- a/src/libpmemobj/tx.c +++ b/src/libpmemobj/tx.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2015-2021, Intel Corporation */ +/* Copyright 2015-2024, Intel Corporation */ /* * tx.c -- transactions implementation @@ -7,11 +7,12 @@ #include #include +#include #include "queue.h" #include "ravl.h" #include "obj.h" -#include "out.h" +#include "core_assert.h" #include "pmalloc.h" #include "tx.h" #include "valgrind_internal.h" @@ -158,13 +159,14 @@ obj_tx_fail_null(int errnum, uint64_t flags) /* ASSERT_IN_TX -- checks whether there's open transaction */ #define ASSERT_IN_TX(tx) do {\ if ((tx)->stage == TX_STAGE_NONE)\ - FATAL("%s called outside of transaction", __func__);\ + CORE_LOG_FATAL("%s called outside of transaction", __func__);\ } while (0) /* ASSERT_TX_STAGE_WORK -- checks whether current transaction stage is WORK */ #define ASSERT_TX_STAGE_WORK(tx) do {\ if ((tx)->stage != TX_STAGE_WORK)\ - FATAL("%s called in invalid stage %d", __func__, (tx)->stage);\ + CORE_LOG_FATAL("%s called in invalid stage %d",\ + __func__, (tx)->stage);\ } while (0) /* @@ -268,7 +270,7 @@ tx_remove_range(struct txr *tx_ranges, void *begin, void *end) struct tx_range_data *txrn = Malloc(sizeof(*txrn)); if (txrn == NULL) /* we can't do it any other way */ - FATAL("!Malloc"); + CORE_LOG_FATAL_W_ERRNO("Malloc"); txrn->begin = txr->begin; txrn->end = begin; @@ -280,7 +282,7 @@ tx_remove_range(struct txr *tx_ranges, void *begin, void *end) struct tx_range_data *txrn = Malloc(sizeof(*txrn)); if (txrn == NULL) /* we can't do it any other way */ - FATAL("!Malloc"); + CORE_LOG_FATAL_W_ERRNO("Malloc"); txrn->begin = end; txrn->end = txr->end; @@ -317,7 +319,7 @@ tx_restore_range(PMEMobjpool *pop, struct tx *tx, struct ulog_entry_buf *range) txr = Malloc(sizeof(*txr)); if (txr == NULL) { /* we can't do it any other way */ - FATAL("!Malloc"); + CORE_LOG_FATAL_W_ERRNO("Malloc"); } uint64_t range_offset = ulog_entry_offset(&range->base); @@ -495,7 +497,7 @@ add_to_tx_and_lock(struct tx *tx, enum pobj_tx_param type, void *lock) retval = pmemobj_mutex_lock(tx->pop, txl->lock.mutex); if (retval) { - ERR("!pmemobj_mutex_lock"); + ERR_W_ERRNO("pmemobj_mutex_lock"); goto err; } break; @@ -504,12 +506,12 @@ add_to_tx_and_lock(struct tx *tx, enum pobj_tx_param type, void *lock) retval = pmemobj_rwlock_wrlock(tx->pop, txl->lock.rwlock); if (retval) { - ERR("!pmemobj_rwlock_wrlock"); + ERR_W_ERRNO("pmemobj_rwlock_wrlock"); goto err; } break; default: - ERR("Unrecognized lock type"); + ERR_WO_ERRNO("Unrecognized lock type"); ASSERT(0); break; } @@ -546,7 +548,7 @@ release_and_free_tx_locks(struct tx *tx) tx_lock->lock.rwlock); break; default: - ERR("Unrecognized lock type"); + ERR_WO_ERRNO("Unrecognized lock type"); ASSERT(0); break; } @@ -570,7 +572,7 @@ tx_lane_ranges_insert_def(PMEMobjpool *pop, struct tx *tx, int ret = ravl_emplace_copy(tx->ranges, rdef); if (ret && errno == EEXIST) - FATAL("invalid state of ranges tree"); + CORE_LOG_FATAL("invalid state of ranges tree"); return ret; } @@ -584,7 +586,7 @@ tx_alloc_common(struct tx *tx, size_t size, type_num_t type_num, LOG(3, NULL); if (size > PMEMOBJ_MAX_ALLOC_SIZE) { - ERR("requested size too large"); + ERR_WO_ERRNO("requested size too large"); return obj_tx_fail_null(ENOMEM, args.flags); } @@ -613,7 +615,7 @@ tx_alloc_common(struct tx *tx, size_t size, type_num_t type_num, err_oom: tx_action_remove(tx); - ERR("out of memory"); + ERR_WO_ERRNO("out of memory"); return obj_tx_fail_null(ENOMEM, args.flags); } @@ -629,7 +631,7 @@ tx_realloc_common(struct tx *tx, PMEMoid oid, size_t size, uint64_t type_num, LOG(3, NULL); if (size > PMEMOBJ_MAX_ALLOC_SIZE) { - ERR("requested size too large"); + ERR_WO_ERRNO("requested size too large"); return obj_tx_fail_null(ENOMEM, flags); } @@ -643,7 +645,7 @@ tx_realloc_common(struct tx *tx, PMEMoid oid, size_t size, uint64_t type_num, /* if size is 0 just free */ if (size == 0) { if (pmemobj_tx_free(oid)) { - ERR("pmemobj_tx_free failed"); + ERR_WO_ERRNO("pmemobj_tx_free failed"); return oid; } else { return OID_NULL; @@ -661,7 +663,7 @@ tx_realloc_common(struct tx *tx, PMEMoid oid, size_t size, uint64_t type_num, if (!OBJ_OID_IS_NULL(new_obj)) { if (pmemobj_tx_free(oid)) { - ERR("pmemobj_tx_free failed"); + ERR_WO_ERRNO("pmemobj_tx_free failed"); VEC_POP_BACK(&tx->actions); return OID_NULL; } @@ -678,7 +680,7 @@ tx_construct_user_buffer(struct tx *tx, void *addr, size_t size, enum pobj_log_type type, int outer_tx, uint64_t flags) { if (tx->pop != pmemobj_pool_by_ptr(addr)) { - ERR("Buffer from a different pool"); + ERR_WO_ERRNO("Buffer from a different pool"); goto err; } @@ -735,7 +737,7 @@ pmemobj_tx_begin(PMEMobjpool *pop, jmp_buf env, ...) if (tx->stage == TX_STAGE_WORK) { ASSERTne(tx->lane, NULL); if (tx->pop != pop) { - ERR("nested transaction for different pool"); + ERR_WO_ERRNO("nested transaction for different pool"); return obj_tx_fail_err(EINVAL, 0); } @@ -765,13 +767,14 @@ pmemobj_tx_begin(PMEMobjpool *pop, jmp_buf env, ...) tx->user_data = NULL; } else { - FATAL("Invalid stage %d to begin new transaction", tx->stage); + CORE_LOG_FATAL("Invalid stage %d to begin new transaction", + tx->stage); } struct tx_data *txd = Malloc(sizeof(*txd)); if (txd == NULL) { err = errno; - ERR("!Malloc"); + ERR_W_ERRNO("Malloc"); goto err_abort; } @@ -802,8 +805,8 @@ pmemobj_tx_begin(PMEMobjpool *pop, jmp_buf env, ...) if (tx->stage_callback && (tx->stage_callback != cb || tx->stage_callback_arg != arg)) { - FATAL("transaction callback is already set, " - "old %p new %p old_arg %p new_arg %p", + CORE_LOG_FATAL( + "transaction callback is already set, old %p new %p old_arg %p new_arg %p", tx->stage_callback, cb, tx->stage_callback_arg, arg); } @@ -860,7 +863,7 @@ pmemobj_tx_xlock(enum pobj_tx_param type, void *lockp, uint64_t flags) flags |= tx_abort_on_failure_flag(tx); if (flags & ~POBJ_XLOCK_VALID_FLAGS) { - ERR("unknown flags 0x%" PRIx64, + ERR_WO_ERRNO("unknown flags 0x%" PRIx64, flags & ~POBJ_XLOCK_VALID_FLAGS); return obj_tx_fail_err(EINVAL, flags); } @@ -940,7 +943,7 @@ obj_tx_abort(int errnum, int user) tx->last_errnum = errnum; errno = errnum; if (user) - ERR("!explicit transaction abort"); + ERR_W_ERRNO("explicit transaction abort"); /* ONABORT */ obj_tx_callback(tx); @@ -1044,10 +1047,12 @@ pmemobj_tx_end(void) struct tx *tx = get_tx(); if (tx->stage == TX_STAGE_WORK) - FATAL("pmemobj_tx_end called without pmemobj_tx_commit"); + CORE_LOG_FATAL( + "pmemobj_tx_end called without pmemobj_tx_commit"); if (tx->pop == NULL) - FATAL("pmemobj_tx_end called without pmemobj_tx_begin"); + CORE_LOG_FATAL( + "pmemobj_tx_end called without pmemobj_tx_begin"); if (tx->stage_callback && (tx->stage == TX_STAGE_ONCOMMIT || @@ -1229,14 +1234,14 @@ pmemobj_tx_add_common(struct tx *tx, struct tx_range_def *args) LOG(15, NULL); if (args->size > PMEMOBJ_MAX_ALLOC_SIZE) { - ERR("snapshot size too large"); + ERR_WO_ERRNO("snapshot size too large"); return obj_tx_fail_err(EINVAL, args->flags); } if (args->offset < tx->pop->heap_offset || (args->offset + args->size) > (tx->pop->heap_offset + tx->pop->heap_size)) { - ERR("object outside of heap"); + ERR_WO_ERRNO("object outside of heap"); return obj_tx_fail_err(EINVAL, args->flags); } @@ -1376,7 +1381,7 @@ pmemobj_tx_add_common(struct tx *tx, struct tx_range_def *args) } if (ret != 0) { - ERR("out of memory"); + ERR_WO_ERRNO("out of memory"); return obj_tx_fail_err(ENOMEM, args->flags); } @@ -1403,7 +1408,7 @@ pmemobj_tx_add_range_direct(const void *ptr, size_t size) uint64_t flags = tx_abort_on_failure_flag(tx); if (!OBJ_PTR_FROM_POOL(tx->pop, ptr)) { - ERR("object outside of pool"); + ERR_WO_ERRNO("object outside of pool"); ret = obj_tx_fail_err(EINVAL, flags); PMEMOBJ_API_END(); return ret; @@ -1441,7 +1446,7 @@ pmemobj_tx_xadd_range_direct(const void *ptr, size_t size, uint64_t flags) flags |= tx_abort_on_failure_flag(tx); if (flags & ~POBJ_XADD_VALID_FLAGS) { - ERR("unknown flags 0x%" PRIx64, flags + ERR_WO_ERRNO("unknown flags 0x%" PRIx64, flags & ~POBJ_XADD_VALID_FLAGS); ret = obj_tx_fail_err(EINVAL, flags); PMEMOBJ_API_END(); @@ -1449,7 +1454,7 @@ pmemobj_tx_xadd_range_direct(const void *ptr, size_t size, uint64_t flags) } if (!OBJ_PTR_FROM_POOL(tx->pop, ptr)) { - ERR("object outside of pool"); + ERR_WO_ERRNO("object outside of pool"); ret = obj_tx_fail_err(EINVAL, flags); PMEMOBJ_API_END(); return ret; @@ -1486,7 +1491,7 @@ pmemobj_tx_add_range(PMEMoid oid, uint64_t hoff, size_t size) uint64_t flags = tx_abort_on_failure_flag(tx); if (oid.pool_uuid_lo != tx->pop->uuid_lo) { - ERR("invalid pool uuid"); + ERR_WO_ERRNO("invalid pool uuid"); ret = obj_tx_fail_err(EINVAL, flags); PMEMOBJ_API_END(); return ret; @@ -1524,7 +1529,7 @@ pmemobj_tx_xadd_range(PMEMoid oid, uint64_t hoff, size_t size, uint64_t flags) flags |= tx_abort_on_failure_flag(tx); if (flags & ~POBJ_XADD_VALID_FLAGS) { - ERR("unknown flags 0x%" PRIx64, flags + ERR_WO_ERRNO("unknown flags 0x%" PRIx64, flags & ~POBJ_XADD_VALID_FLAGS); ret = obj_tx_fail_err(EINVAL, flags); PMEMOBJ_API_END(); @@ -1532,7 +1537,7 @@ pmemobj_tx_xadd_range(PMEMoid oid, uint64_t hoff, size_t size, uint64_t flags) } if (oid.pool_uuid_lo != tx->pop->uuid_lo) { - ERR("invalid pool uuid"); + ERR_WO_ERRNO("invalid pool uuid"); ret = obj_tx_fail_err(EINVAL, flags); PMEMOBJ_API_END(); return ret; @@ -1569,7 +1574,7 @@ pmemobj_tx_alloc(size_t size, uint64_t type_num) PMEMoid oid; if (size == 0) { - ERR("allocation with size 0"); + ERR_WO_ERRNO("allocation with size 0"); oid = obj_tx_fail_null(EINVAL, flags); PMEMOBJ_API_END(); return oid; @@ -1600,7 +1605,7 @@ pmemobj_tx_zalloc(size_t size, uint64_t type_num) PMEMOBJ_API_START(); PMEMoid oid; if (size == 0) { - ERR("allocation with size 0"); + ERR_WO_ERRNO("allocation with size 0"); oid = obj_tx_fail_null(EINVAL, flags); PMEMOBJ_API_END(); return oid; @@ -1631,14 +1636,14 @@ pmemobj_tx_xalloc(size_t size, uint64_t type_num, uint64_t flags) PMEMoid oid; if (size == 0) { - ERR("allocation with size 0"); + ERR_WO_ERRNO("allocation with size 0"); oid = obj_tx_fail_null(EINVAL, flags); PMEMOBJ_API_END(); return oid; } if (flags & ~POBJ_TX_XALLOC_VALID_FLAGS) { - ERR("unknown flags 0x%" PRIx64, flags + ERR_WO_ERRNO("unknown flags 0x%" PRIx64, flags & ~(POBJ_TX_XALLOC_VALID_FLAGS)); oid = obj_tx_fail_null(EINVAL, flags); PMEMOBJ_API_END(); @@ -1707,7 +1712,7 @@ pmemobj_tx_xstrdup(const char *s, uint64_t type_num, uint64_t flags) flags |= tx_abort_on_failure_flag(tx); if (flags & ~POBJ_TX_XALLOC_VALID_FLAGS) { - ERR("unknown flags 0x%" PRIx64, + ERR_WO_ERRNO("unknown flags 0x%" PRIx64, flags & ~POBJ_TX_XALLOC_VALID_FLAGS); return obj_tx_fail_null(EINVAL, flags); } @@ -1715,7 +1720,7 @@ pmemobj_tx_xstrdup(const char *s, uint64_t type_num, uint64_t flags) PMEMOBJ_API_START(); PMEMoid oid; if (NULL == s) { - ERR("cannot duplicate NULL string"); + ERR_WO_ERRNO("cannot duplicate NULL string"); oid = obj_tx_fail_null(EINVAL, flags); PMEMOBJ_API_END(); return oid; @@ -1765,7 +1770,7 @@ pmemobj_tx_xwcsdup(const wchar_t *s, uint64_t type_num, uint64_t flags) flags |= tx_abort_on_failure_flag(tx); if (flags & ~POBJ_TX_XALLOC_VALID_FLAGS) { - ERR("unknown flags 0x%" PRIx64, + ERR_WO_ERRNO("unknown flags 0x%" PRIx64, flags & ~POBJ_TX_XALLOC_VALID_FLAGS); return obj_tx_fail_null(EINVAL, flags); } @@ -1773,7 +1778,7 @@ pmemobj_tx_xwcsdup(const wchar_t *s, uint64_t type_num, uint64_t flags) PMEMOBJ_API_START(); PMEMoid oid; if (NULL == s) { - ERR("cannot duplicate NULL string"); + ERR_WO_ERRNO("cannot duplicate NULL string"); oid = obj_tx_fail_null(EINVAL, flags); PMEMOBJ_API_END(); return oid; @@ -1824,7 +1829,7 @@ pmemobj_tx_xfree(PMEMoid oid, uint64_t flags) flags |= tx_abort_on_failure_flag(tx); if (flags & ~POBJ_XFREE_VALID_FLAGS) { - ERR("unknown flags 0x%" PRIx64, + ERR_WO_ERRNO("unknown flags 0x%" PRIx64, flags & ~POBJ_XFREE_VALID_FLAGS); return obj_tx_fail_err(EINVAL, flags); } @@ -1835,7 +1840,7 @@ pmemobj_tx_xfree(PMEMoid oid, uint64_t flags) PMEMobjpool *pop = tx->pop; if (pop->uuid_lo != oid.pool_uuid_lo) { - ERR("invalid pool uuid"); + ERR_WO_ERRNO("invalid pool uuid"); return obj_tx_fail_err(EINVAL, flags); } @@ -1907,7 +1912,7 @@ pmemobj_tx_xpublish(struct pobj_action *actv, size_t actvcnt, uint64_t flags) flags |= tx_abort_on_failure_flag(tx); if (flags & ~POBJ_XPUBLISH_VALID_FLAGS) { - ERR("unknown flags 0x%" PRIx64, + ERR_WO_ERRNO("unknown flags 0x%" PRIx64, flags & ~POBJ_XPUBLISH_VALID_FLAGS); return obj_tx_fail_err(EINVAL, flags); } @@ -1952,7 +1957,7 @@ pmemobj_tx_xlog_append_buffer(enum pobj_log_type type, void *addr, size_t size, flags |= tx_abort_on_failure_flag(tx); if (flags & ~POBJ_XLOG_APPEND_BUFFER_VALID_FLAGS) { - ERR("unknown flags 0x%" PRIx64, + ERR_WO_ERRNO("unknown flags 0x%" PRIx64, flags & ~POBJ_XLOG_APPEND_BUFFER_VALID_FLAGS); return obj_tx_fail_err(EINVAL, flags); } @@ -2201,7 +2206,8 @@ CTL_WRITE_HANDLER(size)(void *ctx, if (arg_in < 0 || arg_in > (ssize_t)PMEMOBJ_MAX_ALLOC_SIZE) { errno = EINVAL; - ERR("invalid cache size, must be between 0 and max alloc size"); + ERR_WO_ERRNO( + "invalid cache size, must be between 0 and max alloc size"); return -1; } @@ -2224,9 +2230,9 @@ CTL_READ_HANDLER(threshold)(void *ctx, /* suppress unused-parameter errors */ SUPPRESS_UNUSED(ctx, source, arg, indexes); - LOG(1, "tx.cache.threshold parameter is deprecated"); + ERR_WO_ERRNO("tx.cache.threshold parameter is deprecated"); - return 0; + return -1; } /* @@ -2239,9 +2245,9 @@ CTL_WRITE_HANDLER(threshold)(void *ctx, /* suppress unused-parameter errors */ SUPPRESS_UNUSED(ctx, source, arg, indexes); - LOG(1, "tx.cache.threshold parameter is deprecated"); + ERR_WO_ERRNO("tx.cache.threshold parameter is deprecated"); - return 0; + return -1; } static const struct ctl_argument CTL_ARG(threshold) = CTL_ARG_LONG_LONG; diff --git a/src/libpmemobj/ulog.c b/src/libpmemobj/ulog.c index 80569373d85..81289c283cf 100644 --- a/src/libpmemobj/ulog.c +++ b/src/libpmemobj/ulog.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2015-2021, Intel Corporation */ +/* Copyright 2015-2024, Intel Corporation */ /* * ulog.c -- unified log implementation @@ -12,7 +12,7 @@ #include "pmemops.h" #include "ulog.h" #include "obj.h" -#include "out.h" +#include "core_assert.h" #include "util.h" #include "valgrind_internal.h" @@ -26,8 +26,10 @@ #define ULOG_OFFSET_MASK (~(ULOG_OPERATION_MASK)) #define CACHELINE_ALIGN(size) ALIGN_UP(size, CACHELINE_SIZE) +#ifdef DEBUG /* variables required for ASSERTs below */ #define IS_CACHELINE_ALIGNED(ptr)\ (((uintptr_t)(ptr) & (CACHELINE_SIZE - 1)) == 0) +#endif /* * ulog_by_offset -- calculates the ulog pointer @@ -240,7 +242,7 @@ ulog_reserve(struct ulog *ulog, const struct pmem_ops *p_ops) { if (!auto_reserve) { - LOG(1, "cannot auto reserve next ulog"); + ERR_WO_ERRNO("cannot auto reserve next ulog"); return -1; } @@ -669,7 +671,8 @@ ulog_free_next(struct ulog *u, const struct pmem_ops *p_ops, if (VEC_PUSH_BACK(&ulogs_internal_except_first, &u->next) != 0) { /* this is fine, it will just use more pmem */ - LOG(1, "unable to free transaction logs memory"); + CORE_LOG_NOTICE( + "unable to free transaction logs memory"); goto out; } u = ulog_by_offset(u->next, p_ops); diff --git a/src/libpmempool/check_backup.c b/src/libpmempool/check_backup.c index de1e4dee1a7..01900df0f09 100644 --- a/src/libpmempool/check_backup.c +++ b/src/libpmempool/check_backup.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2016-2021, Intel Corporation */ +/* Copyright 2016-2024, Intel Corporation */ /* * check_backup.c -- pre-check backup @@ -100,7 +100,7 @@ backup_nonpoolset_overwrite(PMEMpoolcheck *ppc, location *loc, loc->step = CHECK_STEP_COMPLETE; return 0; default: - ERR("not implemented question id: %u", question); + ERR_WO_ERRNO("not implemented question id: %u", question); } return 0; @@ -265,7 +265,7 @@ backup_poolset_overwrite(PMEMpoolcheck *ppc, location *loc, loc->step = CHECK_STEP_COMPLETE; return 0; default: - ERR("not implemented question id: %u", question); + ERR_WO_ERRNO("not implemented question id: %u", question); } return 0; diff --git a/src/libpmempool/check_pool_hdr.c b/src/libpmempool/check_pool_hdr.c index ca9236726c4..7a5500570d9 100644 --- a/src/libpmempool/check_pool_hdr.c +++ b/src/libpmempool/check_pool_hdr.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2016-2023, Intel Corporation */ +/* Copyright 2016-2024, Intel Corporation */ /* * check_pool_hdr.c -- pool header check @@ -216,7 +216,7 @@ pool_hdr_default_fix(PMEMpoolcheck *ppc, location *loc, uint32_t question, memset(loc->hdr.unused, 0, sizeof(loc->hdr.unused)); break; default: - ERR("not implemented question id: %u", question); + ERR_WO_ERRNO("not implemented question id: %u", question); } return 0; @@ -315,7 +315,7 @@ pool_hdr_nondefault_fix(PMEMpoolcheck *ppc, location *loc, uint32_t question, util_convert2le_hdr(&loc->hdr); break; default: - ERR("not implemented question id: %u", question); + ERR_WO_ERRNO("not implemented question id: %u", question); } return 0; @@ -458,7 +458,7 @@ pool_hdr_poolset_uuid_fix(PMEMpoolcheck *ppc, location *loc, uint32_t question, check_get_uuid_str(loc->hdr.poolset_uuid)); break; default: - ERR("not implemented question id: %u", question); + ERR_WO_ERRNO("not implemented question id: %u", question); } return 0; @@ -581,7 +581,7 @@ pool_hdr_uuid_fix(PMEMpoolcheck *ppc, location *loc, uint32_t question, check_get_uuid_str(loc->hdr.uuid)); break; default: - ERR("not implemented question id: %u", question); + ERR_WO_ERRNO("not implemented question id: %u", question); } return 0; @@ -683,7 +683,7 @@ pool_hdr_uuid_links_fix(PMEMpoolcheck *ppc, location *loc, uint32_t question, POOL_HDR_UUID_LEN); break; default: - ERR("not implemented question id: %u", question); + ERR_WO_ERRNO("not implemented question id: %u", question); } return 0; @@ -736,7 +736,7 @@ pool_hdr_checksum_fix(PMEMpoolcheck *ppc, location *loc, uint32_t question, loc->prefix, le64toh(loc->hdr.checksum)); break; default: - ERR("not implemented question id: %u", question); + ERR_WO_ERRNO("not implemented question id: %u", question); } return 0; @@ -852,7 +852,7 @@ init_location_data(PMEMpoolcheck *ppc, location *loc) "replica %u part %u: ", loc->replica, loc->part); if (ret < 0) - FATAL("!snprintf"); + CORE_LOG_FATAL_W_ERRNO("snprintf"); } else loc->prefix[0] = '\0'; loc->step = 0; diff --git a/src/libpmempool/check_sds.c b/src/libpmempool/check_sds.c index 1869ee08a9a..3ffc87bb985 100644 --- a/src/libpmempool/check_sds.c +++ b/src/libpmempool/check_sds.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2018-2022, Intel Corporation */ +/* Copyright 2018-2024, Intel Corporation */ /* * check_shutdown_state.c -- shutdown state check @@ -126,7 +126,7 @@ sds_fix(PMEMpoolcheck *ppc, location *loc, uint32_t question, ++loc->healthy_replicas; break; default: - ERR("not implemented question id: %u", question); + ERR_WO_ERRNO("not implemented question id: %u", question); } return 0; } @@ -187,7 +187,7 @@ init_prefix(location *loc) "replica %u: ", loc->replica); if (ret < 0) - FATAL("!snprintf"); + CORE_LOG_FATAL_W_ERRNO("snprintf"); } else loc->prefix[0] = '\0'; loc->step = 0; diff --git a/src/libpmempool/check_util.c b/src/libpmempool/check_util.c index 0715d6f5acb..9688194a0f7 100644 --- a/src/libpmempool/check_util.c +++ b/src/libpmempool/check_util.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2016-2023, Intel Corporation */ +/* Copyright 2016-2024, Intel Corporation */ /* * check_util.c -- check utility functions @@ -7,6 +7,7 @@ #include #include +#include #include "out.h" #include "libpmempool.h" @@ -20,7 +21,9 @@ #define MSG_SEPARATOR '|' /* error part of message must have '.' at the end */ +#ifdef DEBUG /* variables required for ASSERTs below */ #define MSG_PLACE_OF_SEPARATION '.' +#endif #define MAX_MSG_STR_SIZE 8192 #define CHECK_ANSWER_YES "yes" @@ -72,7 +75,7 @@ check_data_alloc(void) struct check_data *data = calloc(1, sizeof(*data)); if (data == NULL) { - ERR("!calloc"); + ERR_W_ERRNO("calloc"); return NULL; } @@ -181,11 +184,11 @@ status_alloc(void) { struct check_status *status = malloc(sizeof(*status)); if (!status) - FATAL("!malloc"); + CORE_LOG_FATAL_W_ERRNO("malloc"); status->msg = malloc(sizeof(char) * MAX_MSG_STR_SIZE); if (!status->msg) { free(status); - FATAL("!malloc"); + CORE_LOG_FATAL_W_ERRNO("malloc"); } status->status.str.msg = status->msg; status->answer = PMEMPOOL_CHECK_ANSWER_EMPTY; @@ -262,7 +265,7 @@ status_push(PMEMpoolcheck *ppc, struct check_status *st, uint32_t question) if (CHECK_IS_NOT(ppc, REPAIR)) { /* error status */ if (status_msg_info_only(st->msg)) { - ERR("no error message for the user"); + ERR_WO_ERRNO("no error message for the user"); st->msg[0] = '\0'; } st->status.type = PMEMPOOL_CHECK_MSG_TYPE_ERROR; @@ -329,7 +332,7 @@ check_status_create(PMEMpoolcheck *ppc, enum pmempool_check_msg_type type, int ret = util_snprintf(st->msg + p, MAX_MSG_STR_SIZE - (size_t)p, ": %s", buff); if (ret < 0) { - ERR("!snprintf"); + ERR_W_ERRNO("snprintf"); status_release(st); return -1; } @@ -603,7 +606,7 @@ check_get_time_str(time_t time) else { int ret = util_snprintf(str_buff, STR_MAX, "unknown"); if (ret < 0) { - ERR("!snprintf"); + ERR_W_ERRNO("snprintf"); return ""; } } @@ -620,7 +623,7 @@ check_get_uuid_str(uuid_t uuid) int ret = util_uuid_to_string(uuid, uuid_str); if (ret != 0) { - ERR("failed to convert uuid to string"); + ERR_WO_ERRNO("failed to convert uuid to string"); return ""; } return uuid_str; diff --git a/src/libpmempool/feature.c b/src/libpmempool/feature.c index 83600057e07..3716b0cb262 100644 --- a/src/libpmempool/feature.c +++ b/src/libpmempool/feature.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2018-2023, Intel Corporation */ +/* Copyright 2018-2024, Intel Corporation */ /* * feature.c -- implementation of pmempool_feature_(enable|disable|query)() @@ -10,6 +10,7 @@ #include #include #include +#include #include "libpmempool.h" #include "util_pmem.h" @@ -47,12 +48,12 @@ buff_concat(char *buff, size_t *pos, const char *fmt, ...) va_end(ap); if (ret < 0) { - ERR("vsprintf"); + ERR_WO_ERRNO("vsprintf"); return ret; } if ((size_t)ret >= size) { - ERR("buffer truncated %d >= %zu", ret, size); + ERR_WO_ERRNO("buffer truncated %d >= %zu", ret, size); return -1; } @@ -110,7 +111,7 @@ features_check(features_t *f, struct pool_hdr *hdrp) goto err; if (buff_concat_features(msg, &pos, *f)) goto err; - ERR("features mismatch detected: %s", msg); + ERR_WO_ERRNO("features mismatch detected: %s", msg); return -1; } else { return 0; @@ -130,7 +131,7 @@ features_check(features_t *f, struct pool_hdr *hdrp) size_t pos = 0; if (buff_concat_features(msg, &pos, unknown)) goto err; - ERR("invalid features detected: %s", msg); + ERR_WO_ERRNO("invalid features detected: %s", msg); err: return -1; } @@ -172,7 +173,7 @@ poolset_open(const char *path, int rdonly) /* read poolset */ int ret = util_poolset_create_set(&set, path, 0, 0, true); if (ret < 0) { - ERR("cannot open pool set -- '%s'", path); + ERR_WO_ERRNO("cannot open pool set -- '%s'", path); goto err_poolset; } @@ -196,7 +197,7 @@ poolset_open(const char *path, int rdonly) } if (features_check(&f, HDR(rep, p))) { - ERR( + ERR_WO_ERRNO( "invalid features - replica #%d part #%d", r, p); goto err_open; @@ -261,8 +262,10 @@ typedef enum { ENABLED } fstate_t; +#ifdef DEBUG #define FEATURE_IS_ENABLED_STR "feature already enabled: %s" #define FEATURE_IS_DISABLED_STR "feature already disabled: %s" +#endif /* * require_feature_is -- (internal) check if required feature is enabled @@ -277,9 +280,11 @@ require_feature_is(struct pool_set *set, features_t feature, fstate_t req_state) if (state == req_state) return 1; +#ifdef DEBUG const char *msg = (state == ENABLED) ? FEATURE_IS_ENABLED_STR : FEATURE_IS_DISABLED_STR; LOG(3, msg, util_feature2str(feature, NULL)); +#endif return 0; } @@ -301,11 +306,14 @@ require_other_feature_is(struct pool_set *set, features_t other, if (state == req_state) return 1; - const char *msg = (req_state == ENABLED) - ? FEATURE_IS_NOT_ENABLED_PRIOR_STR - : FEATURE_IS_NOT_DISABLED_PRIOR_STR; - ERR(msg, util_feature2str(other, NULL), - cause, util_feature2str(feature, NULL)); + if (req_state == ENABLED) + ERR_WO_ERRNO(FEATURE_IS_NOT_ENABLED_PRIOR_STR, + util_feature2str(other, NULL), cause, + util_feature2str(feature, NULL)); + else + ERR_WO_ERRNO(FEATURE_IS_NOT_DISABLED_PRIOR_STR, + util_feature2str(other, NULL), cause, + util_feature2str(feature, NULL)); return 0; } @@ -354,7 +362,8 @@ query_feature(const char *path, features_t feature) static inline int unsupported_feature(features_t feature) { - ERR("unsupported feature: %s", util_feature2str(feature, NULL)); + ERR_WO_ERRNO("unsupported feature: %s", + util_feature2str(feature, NULL)); errno = EINVAL; return -1; } @@ -600,7 +609,7 @@ static inline int are_flags_valid(unsigned flags) { if (flags != 0) { - ERR("invalid flags: 0x%x", flags); + ERR_WO_ERRNO("invalid flags: 0x%x", flags); errno = EINVAL; return 0; } @@ -614,7 +623,7 @@ static inline int is_feature_valid(uint32_t feature) { if (feature >= FEATURE_FUNCS_MAX) { - ERR("invalid feature: 0x%x", feature); + ERR_WO_ERRNO("invalid feature: 0x%x", feature); errno = EINVAL; return 0; } diff --git a/src/libpmempool/libpmempool.c b/src/libpmempool/libpmempool.c index e8031a2a164..73413c8329a 100644 --- a/src/libpmempool/libpmempool.c +++ b/src/libpmempool/libpmempool.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2016-2023, Intel Corporation */ +/* Copyright 2016-2024, Intel Corporation */ /* * libpmempool.c -- entry points for libpmempool @@ -56,15 +56,17 @@ pmempool_check_versionU(unsigned major_required, unsigned minor_required) major_required, minor_required); if (major_required != PMEMPOOL_MAJOR_VERSION) { - ERR("libpmempool major version mismatch (need %u, found %u)", + ERR_WO_ERRNO( + "libpmempool major version mismatch (need %u, found %u)", major_required, PMEMPOOL_MAJOR_VERSION); - return out_get_errormsg(); + return last_error_msg_get(); } if (minor_required > PMEMPOOL_MINOR_VERSION) { - ERR("libpmempool minor version mismatch (need %u, found %u)", + ERR_WO_ERRNO( + "libpmempool minor version mismatch (need %u, found %u)", minor_required, PMEMPOOL_MINOR_VERSION); - return out_get_errormsg(); + return last_error_msg_get(); } return NULL; @@ -80,17 +82,17 @@ pmempool_check_version(unsigned major_required, unsigned minor_required) } /* - * pmempool_errormsgU -- return last error message + * pmempool_errormsgU -- return the last error message */ static inline const char * pmempool_errormsgU(void) { - return out_get_errormsg(); + return last_error_msg_get(); } /* - * pmempool_errormsg -- return last error message + * pmempool_errormsg -- return the last error message */ const char * pmempool_errormsg(void) @@ -130,7 +132,7 @@ pmempool_check_initU(struct pmempool_check_argsU *args, size_t args_size) * args_size. */ if (args_size < sizeof(struct pmempool_check_args)) { - ERR("provided args_size is not supported"); + ERR_WO_ERRNO("provided args_size is not supported"); errno = EINVAL; return NULL; } @@ -144,8 +146,9 @@ pmempool_check_initU(struct pmempool_check_argsU *args, size_t args_size) if (util_flag_isclr(args->flags, PMEMPOOL_CHECK_REPAIR) && util_flag_isset(args->flags, PMEMPOOL_CHECK_DRY_RUN | PMEMPOOL_CHECK_ADVANCED | PMEMPOOL_CHECK_ALWAYS_YES)) { - ERR("dry_run, advanced and always_yes are applicable only if " - "repair is set"); + ERR_WO_ERRNO( + "dry_run, advanced and always_yes are applicable " + "only if repair is set"); errno = EINVAL; return NULL; } @@ -155,7 +158,7 @@ pmempool_check_initU(struct pmempool_check_argsU *args, size_t args_size) */ if (util_flag_isset(args->flags, PMEMPOOL_CHECK_DRY_RUN) && args->backup_path != NULL) { - ERR("dry run does not allow one to perform backup"); + ERR_WO_ERRNO("dry run does not allow one to perform backup"); errno = EINVAL; return NULL; } @@ -164,14 +167,14 @@ pmempool_check_initU(struct pmempool_check_argsU *args, size_t args_size) * libpmempool uses str format of communication so it must be set */ if (util_flag_isclr(args->flags, PMEMPOOL_CHECK_FORMAT_STR)) { - ERR("PMEMPOOL_CHECK_FORMAT_STR flag must be set"); + ERR_WO_ERRNO("PMEMPOOL_CHECK_FORMAT_STR flag must be set"); errno = EINVAL; return NULL; } PMEMpoolcheck *ppc = calloc(1, sizeof(*ppc)); if (ppc == NULL) { - ERR("!calloc"); + ERR_W_ERRNO("calloc"); return NULL; } @@ -179,7 +182,7 @@ pmempool_check_initU(struct pmempool_check_argsU *args, size_t args_size) memcpy(&ppc->args, args, sizeof(ppc->args)); ppc->path = strdup(args->path); if (!ppc->path) { - ERR("!strdup"); + ERR_W_ERRNO("strdup"); goto error_path_malloc; } ppc->args.path = ppc->path; @@ -187,7 +190,7 @@ pmempool_check_initU(struct pmempool_check_argsU *args, size_t args_size) if (args->backup_path != NULL) { ppc->backup_path = strdup(args->backup_path); if (!ppc->backup_path) { - ERR("!strdup"); + ERR_W_ERRNO("strdup"); goto error_backup_path_malloc; } ppc->args.backup_path = ppc->backup_path; diff --git a/src/libpmempool/pool.c b/src/libpmempool/pool.c index b96d659a5ad..9ccc432ee86 100644 --- a/src/libpmempool/pool.c +++ b/src/libpmempool/pool.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2016-2023, Intel Corporation */ +/* Copyright 2016-2024, Intel Corporation */ /* * pool.c -- pool processing functions @@ -46,14 +46,14 @@ pool_set_read_header(const char *fname, struct pool_hdr *hdr) const struct pool_set_part *part = PART(REP(set, 0), 0); int fdp = util_file_open(part->path, NULL, 0, O_RDONLY); if (fdp < 0) { - ERR("cannot open poolset part file"); + ERR_WO_ERRNO("cannot open poolset part file"); ret = -1; goto err_pool_set; } /* read the pool header from first pool set file */ if (pread(fdp, hdr, sizeof(*hdr), 0) != sizeof(*hdr)) { - ERR("cannot read pool header from poolset"); + ERR_WO_ERRNO("cannot read pool header from poolset"); ret = -1; goto err_close_part; } @@ -83,7 +83,7 @@ pool_set_map(const char *fname, struct pool_set **poolset, unsigned flags) /* parse pool type from first pool set file */ enum pool_type type = pool_hdr_get_type(&hdr); if (type == POOL_TYPE_UNKNOWN) { - ERR("cannot determine pool type from poolset"); + ERR_WO_ERRNO("cannot determine pool type from poolset"); return -1; } @@ -97,7 +97,7 @@ pool_set_map(const char *fname, struct pool_set **poolset, unsigned flags) if (util_pool_open(poolset, fname, 0 /* minpartsize */, &attr, NULL, NULL, flags | POOL_OPEN_IGNORE_SDS | POOL_OPEN_IGNORE_BAD_BLOCKS)) { - ERR("opening poolset failed"); + ERR_WO_ERRNO("opening poolset failed"); return -1; } @@ -136,7 +136,8 @@ pool_check_type_to_pool_type(enum pmempool_pool_type check_pool_type) case PMEMPOOL_POOL_TYPE_OBJ: return POOL_TYPE_OBJ; default: - ERR("can not convert pmempool_pool_type %u to pool_type", + ERR_WO_ERRNO( + "can not convert pmempool_pool_type %u to pool_type", check_pool_type); return POOL_TYPE_UNKNOWN; } @@ -186,7 +187,7 @@ pool_params_parse(const PMEMpoolcheck *ppc, struct pool_params *params, ret = util_poolset_create_set(&set, ppc->path, 0, 0, true); if (ret < 0) { - LOG(2, "cannot open pool set -- '%s'", + CORE_LOG_ERROR("cannot open pool set -- '%s'", ppc->path); return -1; } @@ -206,7 +207,7 @@ pool_params_parse(const PMEMpoolcheck *ppc, struct pool_params *params, */ if (mprotect(addr, set->replica[0]->repsize, PROT_READ) < 0) { - ERR("!mprotect"); + ERR_W_ERRNO("mprotect"); goto out_unmap; } params->is_dev_dax = set->replica[0]->part[0].is_dev_dax; @@ -245,7 +246,7 @@ pool_params_parse(const PMEMpoolcheck *ppc, struct pool_params *params, enum pool_type declared_type = pool_check_type_to_pool_type(ppc->args.pool_type); if ((params->type & ~declared_type) != 0) { - ERR("declared pool type does not match"); + ERR_WO_ERRNO("declared pool type does not match"); errno = EINVAL; ret = 1; goto out_unmap; @@ -295,7 +296,7 @@ pool_set_file_open(const char *fname, int rdonly) int ret = util_poolset_create_set(&file->poolset, path, 0, 0, true); if (ret < 0) { - LOG(2, "cannot open pool set -- '%s'", path); + CORE_LOG_ERROR("cannot open pool set -- '%s'", path); goto err_free_fname; } unsigned flags = (rdonly ? POOL_OPEN_COW : 0) | @@ -311,7 +312,7 @@ pool_set_file_open(const char *fname, int rdonly) os_stat_t buf; if (os_stat(path, &buf)) { - ERR("%s", path); + ERR_WO_ERRNO("%s", path); goto err_close_poolset; } @@ -362,7 +363,7 @@ pool_data_alloc(PMEMpoolcheck *ppc) struct pool_data *pool = calloc(1, sizeof(*pool)); if (!pool) { - ERR("!calloc"); + ERR_W_ERRNO("calloc"); return NULL; } @@ -374,7 +375,7 @@ pool_data_alloc(PMEMpoolcheck *ppc) if (prv && pool->params.is_dev_dax) { errno = ENOTSUP; - ERR("!cannot perform a dry run on dax device"); + ERR_W_ERRNO("cannot perform a dry run on dax device"); goto error; } @@ -554,7 +555,7 @@ pool_set_part_copy(struct pool_set_part *dpart, struct pool_set_part *spart, os_stat_t stat_buf; if (os_fstat(spart->fd, &stat_buf)) { - ERR("!util_stat"); + ERR_W_ERRNO("util_stat"); return -1; } @@ -596,7 +597,8 @@ pool_set_part_copy(struct pool_set_part *dpart, struct pool_set_part *spart, #ifdef DEBUG /* provide extra logging in case of wrong dmapped/smapped value */ if (dmapped < smapped) { - LOG(1, "dmapped < smapped: dmapped = %lu, smapped = %lu", + CORE_LOG_ERROR( + "dmapped < smapped: dmapped = %lu, smapped = %lu", dmapped, smapped); ASSERT(0); } @@ -750,7 +752,7 @@ pool_set_type(struct pool_set *set) if (util_file_pread(part->path, &hdr, sizeof(hdr), 0) != sizeof(hdr)) { - ERR("cannot read pool header from poolset"); + ERR_WO_ERRNO("cannot read pool header from poolset"); return POOL_TYPE_UNKNOWN; } @@ -769,7 +771,7 @@ pool_get_min_size(enum pool_type type) case POOL_TYPE_OBJ: return PMEMOBJ_MIN_POOL; default: - ERR("unknown type of a pool"); + ERR_WO_ERRNO("unknown type of a pool"); return SIZE_MAX; } } diff --git a/src/libpmempool/replica.c b/src/libpmempool/replica.c index 6b51c3dd66d..1a90bb6cbbf 100644 --- a/src/libpmempool/replica.c +++ b/src/libpmempool/replica.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2016-2023, Intel Corporation */ +/* Copyright 2016-2024, Intel Corporation */ /* * replica.c -- groups all commands for replica manipulation @@ -132,14 +132,14 @@ replica_remove_part(struct pool_set *set, unsigned repn, unsigned partn, /* if the part is a device dax, clear its bad blocks */ if (type == TYPE_DEVDAX && fix_bad_blocks && badblocks_clear_all(part->path)) { - ERR("clearing bad blocks in device dax failed -- '%s'", + ERR_WO_ERRNO("clearing bad blocks in device dax failed -- '%s'", part->path); errno = EIO; return -1; } if (type == TYPE_NORMAL && util_unlink(part->path)) { - ERR("!removing part %u from replica %u failed", + ERR_W_ERRNO("removing part %u from replica %u failed", partn, repn); return -1; } @@ -165,7 +165,7 @@ create_replica_health_status(struct pool_set *set, unsigned repn) replica_hs = Zalloc(sizeof(struct replica_health_status) + nparts * sizeof(struct part_health_status)); if (replica_hs == NULL) { - ERR("!Zalloc for replica health status"); + ERR_W_ERRNO("Zalloc for replica health status"); return NULL; } @@ -187,7 +187,8 @@ replica_part_remove_recovery_file(struct part_health_status *phs) return 0; if (os_unlink(phs->recovery_file_name) < 0) { - ERR("!removing the bad block recovery file failed -- '%s'", + ERR_W_ERRNO( + "removing the bad block recovery file failed -- '%s'", phs->recovery_file_name); return -1; } @@ -256,7 +257,7 @@ replica_create_poolset_health_status(struct pool_set *set, set_hs = Zalloc(sizeof(struct poolset_health_status) + nreplicas * sizeof(struct replica_health_status *)); if (set_hs == NULL) { - ERR("!Zalloc for poolset health state"); + ERR_W_ERRNO("Zalloc for poolset health state"); return -1; } set_hs->nreplicas = nreplicas; @@ -545,7 +546,8 @@ check_and_open_poolset_part_files(struct pool_set *set, enum file_type type = util_file_get_type(path); if (type < 0 || os_access(path, R_OK|W_OK) != 0) { - LOG(1, "part file %s is not accessible", path); + CORE_LOG_ERROR("part file %s is not accessible", + path); errno = 0; rep_hs->part[p].flags |= IS_BROKEN; if (is_dry_run(flags)) @@ -554,12 +556,12 @@ check_and_open_poolset_part_files(struct pool_set *set, if (util_part_open(&rep->part[p], 0, 0)) { if (type == TYPE_DEVDAX) { - LOG(1, + CORE_LOG_ERROR( "opening part on Device DAX %s failed", path); return -1; } - LOG(1, "opening part %s failed", path); + CORE_LOG_ERROR("opening part %s failed", path); errno = 0; rep_hs->part[p].flags |= IS_BROKEN; } @@ -589,7 +591,8 @@ map_all_unbroken_headers(struct pool_set *set, LOG(4, "mapping header for part %u, replica %u", p, r); if (util_map_hdr(&rep->part[p], MAP_SHARED, 0) != 0) { - LOG(1, "header mapping failed - part #%d", p); + CORE_LOG_ERROR( + "header mapping failed - part #%d", p); rep_hs->part[p].flags |= IS_BROKEN; } } @@ -639,7 +642,7 @@ check_checksums_and_signatures(struct pool_set *set, if (!util_checksum(hdr, sizeof(*hdr), &hdr->checksum, 0, POOL_HDR_CSUM_END_OFF(hdr))) { - ERR("invalid checksum of pool header"); + ERR_WO_ERRNO("invalid checksum of pool header"); rep_hs->part[p].flags |= IS_BROKEN; } else if (util_is_zeroed(hdr, sizeof(*hdr))) { rep_hs->part[p].flags |= IS_BROKEN; @@ -647,7 +650,7 @@ check_checksums_and_signatures(struct pool_set *set, enum pool_type type = pool_hdr_get_type(hdr); if (type == POOL_TYPE_UNKNOWN) { - ERR("invalid signature"); + ERR_WO_ERRNO("invalid signature"); rep_hs->part[p].flags |= IS_BROKEN; } } @@ -673,14 +676,16 @@ replica_badblocks_recovery_file_save(struct part_health_status *part_hs) int fd = os_open(path, O_WRONLY | O_TRUNC); if (fd < 0) { - ERR("!opening bad block recovery file failed -- '%s'", path); + ERR_W_ERRNO( + "opening bad block recovery file failed -- '%s'", + path); return -1; } FILE *recovery_file_name = os_fdopen(fd, "w"); if (recovery_file_name == NULL) { - ERR( - "!opening a file stream for bad block recovery file failed -- '%s'", + ERR_W_ERRNO( + "opening a file stream for bad block recovery file failed -- '%s'", path); os_close(fd); return -1; @@ -694,12 +699,16 @@ replica_badblocks_recovery_file_save(struct part_health_status *part_hs) } if (fflush(recovery_file_name) == EOF) { - ERR("!flushing bad block recovery file failed -- '%s'", path); + ERR_W_ERRNO( + "flushing bad block recovery file failed -- '%s'", + path); goto exit_error; } if (os_fsync(fd) < 0) { - ERR("!syncing bad block recovery file failed -- '%s'", path); + ERR_W_ERRNO( + "syncing bad block recovery file failed -- '%s'", + path); goto exit_error; } @@ -707,12 +716,16 @@ replica_badblocks_recovery_file_save(struct part_health_status *part_hs) fprintf(recovery_file_name, "0 0\n"); if (fflush(recovery_file_name) == EOF) { - ERR("!flushing bad block recovery file failed -- '%s'", path); + ERR_W_ERRNO( + "flushing bad block recovery file failed -- '%s'", + path); goto exit_error; } if (os_fsync(fd) < 0) { - ERR("!syncing bad block recovery file failed -- '%s'", path); + ERR_W_ERRNO( + "syncing bad block recovery file failed -- '%s'", + path); goto exit_error; } @@ -745,7 +758,8 @@ replica_part_badblocks_recovery_file_read(struct part_health_status *part_hs) FILE *recovery_file = os_fopen(path, "r"); if (!recovery_file) { - ERR("!opening the recovery file for reading failed -- '%s'", + ERR_W_ERRNO( + "opening the recovery file for reading failed -- '%s'", path); return -1; } @@ -755,7 +769,8 @@ replica_part_badblocks_recovery_file_read(struct part_health_status *part_hs) do { if (fscanf(recovery_file, "%zu %zu\n", &bb.offset, &bb.length) < 2) { - LOG(1, "incomplete bad block recovery file -- '%s'", + CORE_LOG_ERROR( + "incomplete bad block recovery file -- '%s'", path); ret = 1; goto error_exit; @@ -768,7 +783,7 @@ replica_part_badblocks_recovery_file_read(struct part_health_status *part_hs) /* check if bad blocks build an increasing sequence */ if (bb.offset < min_offset) { - ERR( + ERR_WO_ERRNO( "wrong format of bad block recovery file (bad blocks are not sorted by the offset in ascending order) -- '%s'", path); errno = EINVAL; @@ -791,7 +806,7 @@ replica_part_badblocks_recovery_file_read(struct part_health_status *part_hs) os_fclose(recovery_file); - LOG(1, "bad blocks read from the recovery file -- '%s'", path); + CORE_LOG_HARK("bad blocks read from the recovery file -- '%s'", path); return 0; @@ -843,7 +858,7 @@ replica_badblocks_recovery_files_check(struct pool_set *set, badblocks_recovery_file_alloc(set->path, r, p); if (part_hs->recovery_file_name == NULL) { - LOG(1, + CORE_LOG_ERROR( "allocating name of bad block recovery file failed"); return RECOVERY_FILES_ERROR; } @@ -913,21 +928,21 @@ replica_badblocks_recovery_files_read(struct pool_set *set, continue; } - LOG(1, + CORE_LOG_HARK( "reading bad blocks from the recovery file -- '%s'", part_hs->recovery_file_name); ret = replica_part_badblocks_recovery_file_read( part_hs); if (ret < 0) { - LOG(1, + CORE_LOG_ERROR( "reading bad blocks from the recovery file failed -- '%s'", part_hs->recovery_file_name); return -1; } if (ret > 0) { - LOG(1, + CORE_LOG_WARNING( "incomplete bad block recovery file detected -- '%s'", part_hs->recovery_file_name); return 1; @@ -973,8 +988,8 @@ replica_badblocks_recovery_files_create_empty(struct pool_set *set, O_RDWR | O_CREAT | O_EXCL, 0600); if (fd < 0) { - ERR( - "!creating an empty bad block recovery file failed -- '%s' (part file '%s')", + ERR_W_ERRNO( + "creating an empty bad block recovery file failed -- '%s' (part file '%s')", part_hs->recovery_file_name, path); return -1; } @@ -983,7 +998,7 @@ replica_badblocks_recovery_files_create_empty(struct pool_set *set, char *file_name = Strdup(part_hs->recovery_file_name); if (file_name == NULL) { - ERR("!Strdup"); + ERR_W_ERRNO("Strdup"); return -1; } @@ -991,8 +1006,8 @@ replica_badblocks_recovery_files_create_empty(struct pool_set *set, /* fsync the file's directory */ if (os_fsync_dir(dir_name) < 0) { - ERR( - "!syncing the directory of the bad block recovery file failed -- '%s' (part file '%s')", + ERR_W_ERRNO( + "syncing the directory of the bad block recovery file failed -- '%s' (part file '%s')", dir_name, path); Free(file_name); return -1; @@ -1029,7 +1044,7 @@ replica_badblocks_recovery_files_save(struct pool_set *set, int ret = replica_badblocks_recovery_file_save(part_hs); if (ret < 0) { - LOG(1, + CORE_LOG_ERROR( "opening bad block recovery file failed -- '%s'", part_hs->recovery_file_name); return -1; @@ -1070,8 +1085,8 @@ replica_badblocks_get(struct pool_set *set, int ret = badblocks_get(path, &part_hs->bbs); if (ret < 0) { - ERR( - "!checking the pool part for bad blocks failed -- '%s'", + ERR_W_ERRNO( + "checking the pool part for bad blocks failed -- '%s'", path); return -1; } @@ -1147,7 +1162,7 @@ replica_badblocks_clear(struct pool_set *set, ret = badblocks_clear(path, &part_hs->bbs); if (ret < 0) { - LOG(1, + CORE_LOG_ERROR( "clearing bad blocks in replica failed -- '%s'", path); return -1; @@ -1188,19 +1203,19 @@ replica_badblocks_check_or_clear(struct pool_set *set, /* phase #1 - error handling */ switch (status) { case RECOVERY_FILES_ERROR: - LOG(1, "checking bad block recovery files failed"); + CORE_LOG_ERROR("checking bad block recovery files failed"); return -1; case RECOVERY_FILES_EXIST_ALL: case RECOVERY_FILES_NOT_ALL_EXIST: if (!called_from_sync) { - ERR( + ERR_WO_ERRNO( "error: a bad block recovery file exists, run 'pmempool sync --bad-blocks' to fix bad blocks first"); return -1; } if (!fix_bad_blocks) { - ERR( + ERR_WO_ERRNO( "error: a bad block recovery file exists, but the '--bad-blocks' option is not set\n" ERR_MSG_BB); return -1; @@ -1231,16 +1246,17 @@ replica_badblocks_check_or_clear(struct pool_set *set, /* read all bad block recovery files */ ret = replica_badblocks_recovery_files_read(set, set_hs); if (ret < 0) { - LOG(1, "checking bad block recovery files failed"); + CORE_LOG_ERROR( + "checking bad block recovery files failed"); return -1; } if (ret > 0) { /* incomplete bad block recovery file was detected */ - LOG(1, - "warning: incomplete bad block recovery file detected\n" - " - all recovery files will be removed"); + CORE_LOG_WARNING( + "incomplete bad block recovery file detected\n" + "- all recovery files will be removed"); /* changing status to RECOVERY_FILES_NOT_ALL_EXIST */ status = RECOVERY_FILES_NOT_ALL_EXIST; @@ -1248,9 +1264,8 @@ replica_badblocks_check_or_clear(struct pool_set *set, break; case RECOVERY_FILES_NOT_ALL_EXIST: - LOG(1, - "warning: one of bad block recovery files does not exist\n" - " - all recovery files will be removed"); + CORE_LOG_WARNING( + "one of bad block recovery files does not exist - all recovery files will be removed"); break; default: @@ -1265,15 +1280,17 @@ replica_badblocks_check_or_clear(struct pool_set *set, */ if (!dry_run) { - LOG(1, "removing all bad block recovery files..."); + CORE_LOG_HARK( + "removing all bad block recovery files..."); ret = replica_remove_all_recovery_files(set_hs); if (ret < 0) { - LOG(1, + CORE_LOG_ERROR( "removing bad block recovery files failed"); return -1; } } else { - LOG(1, "all bad block recovery files would be removed"); + CORE_LOG_HARK( + "all bad block recovery files would be removed"); } /* changing status to RECOVERY_FILES_DO_NOT_EXIST */ @@ -1289,11 +1306,11 @@ replica_badblocks_check_or_clear(struct pool_set *set, int bad_blocks_found = replica_badblocks_get(set, set_hs); if (bad_blocks_found < 0) { if (errno == ENOTSUP) { - LOG(1, BB_NOT_SUPP); + CORE_LOG_ERROR(BB_NOT_SUPP); return -1; } - LOG(1, "checking bad blocks failed"); + CORE_LOG_ERROR("checking bad blocks failed"); return -1; } @@ -1305,13 +1322,13 @@ replica_badblocks_check_or_clear(struct pool_set *set, /* bad blocks were found */ if (!called_from_sync) { - ERR( + ERR_WO_ERRNO( "error: bad blocks found, run 'pmempool sync --bad-blocks' to fix bad blocks first"); return -1; } if (!fix_bad_blocks) { - ERR( + ERR_WO_ERRNO( "error: bad blocks found, but the '--bad-blocks' option is not set\n" ERR_MSG_BB); return -1; @@ -1319,7 +1336,7 @@ replica_badblocks_check_or_clear(struct pool_set *set, if (dry_run) { /* dry-run - do nothing */ - LOG(1, "warning: bad blocks were found"); + CORE_LOG_WARNING("bad blocks were found"); return 0; } @@ -1327,7 +1344,7 @@ replica_badblocks_check_or_clear(struct pool_set *set, ret = replica_badblocks_recovery_files_create_empty(set, set_hs); if (ret < 0) { - LOG(1, + CORE_LOG_ERROR( "creating empty bad block recovery files failed"); return -1; } @@ -1335,20 +1352,21 @@ replica_badblocks_check_or_clear(struct pool_set *set, /* save bad blocks in recovery files */ ret = replica_badblocks_recovery_files_save(set, set_hs); if (ret < 0) { - LOG(1, "saving bad block recovery files failed"); + CORE_LOG_ERROR( + "saving bad block recovery files failed"); return -1; } } if (dry_run) { /* dry-run - do nothing */ - LOG(1, "bad blocks would be cleared"); + CORE_LOG_HARK("bad blocks would be cleared"); return 0; } ret = replica_badblocks_clear(set, set_hs); if (ret < 0) { - ERR("clearing bad blocks failed"); + ERR_WO_ERRNO("clearing bad blocks failed"); return -1; } @@ -1431,7 +1449,7 @@ check_uuids_between_parts(struct pool_set *set, unsigned repn, } if (uuidcmp(HDR(rep, p)->poolset_uuid, poolset_uuid)) { - ERR( + ERR_WO_ERRNO( "different poolset uuids in parts from the same replica (repn %u, parts %u and %u) - cannot synchronize", repn, part_stored, p); errno = EINVAL; @@ -1460,7 +1478,7 @@ check_uuids_between_parts(struct pool_set *set, unsigned repn, hdrp->next_repl_uuid); if (prev_differ || next_differ) { - ERR( + ERR_WO_ERRNO( "different adjacent replica UUID between parts (repn %u, parts %u and %u) - cannot synchronize", repn, unbroken_p, p); errno = EINVAL; @@ -1486,7 +1504,7 @@ check_uuids_between_parts(struct pool_set *set, unsigned repn, hdrp->uuid) || uuidcmp(hdrp->next_part_uuid, next_hdrp->uuid); if (next_decoupled) { - ERR( + ERR_WO_ERRNO( "two consecutive unbroken parts are not linked to each other (repn %u, parts %u and %u) - cannot synchronize", repn, p, p + 1); errno = EINVAL; @@ -1532,7 +1550,7 @@ check_replica_options(struct pool_set *set, unsigned repn, struct pool_hdr *hdr = HDR(rep, p); if (((hdr->features.incompat & POOL_FEAT_SINGLEHDR) == 0) != ((set->options & OPTION_SINGLEHDR) == 0)) { - LOG(1, + CORE_LOG_ERROR( "improper options are set in part %u's header in replica %u", p, repn); rep_hs->part[p].flags |= IS_BROKEN; @@ -1603,7 +1621,7 @@ check_poolset_uuids(struct pool_set *set, /* find a replica with healthy header */ unsigned r_h = replica_find_replica_healthy_header(set_hs); if (r_h == UNDEF_REPLICA) { - ERR("no healthy replica found"); + ERR_WO_ERRNO("no healthy replica found"); return -1; } @@ -1617,7 +1635,7 @@ check_poolset_uuids(struct pool_set *set, continue; if (check_replica_poolset_uuids(set, r, poolset_uuid, set_hs)) { - ERR( + ERR_WO_ERRNO( "inconsistent poolset uuids between replicas %u and %u - cannot synchronize", r_h, r); return -1; @@ -1676,9 +1694,11 @@ check_uuids_between_replicas(struct pool_set *set, uuid_t *rep_n_uuidp = NULL; unsigned r_n = REPN_HEALTHidx(set_hs, r); if (get_replica_uuid(rep, r, set_hs, &rep_uuidp)) - LOG(2, "cannot get replica uuid, replica %u", r); + CORE_LOG_WARNING("cannot get replica uuid, replica %u", + r); if (get_replica_uuid(rep_n, r_n, set_hs, &rep_n_uuidp)) - LOG(2, "cannot get replica uuid, replica %u", r_n); + CORE_LOG_WARNING("cannot get replica uuid, replica %u", + r_n); /* * check if replica uuids are consistent between two adjacent @@ -1689,7 +1709,7 @@ check_uuids_between_replicas(struct pool_set *set, if (p_n != UNDEF_PART && rep_uuidp != NULL && uuidcmp(*rep_uuidp, HDR(rep_n, p_n)->prev_repl_uuid)) { - ERR( + ERR_WO_ERRNO( "inconsistent replica uuids between replicas %u and %u", r, r_n); return -1; @@ -1697,7 +1717,7 @@ check_uuids_between_replicas(struct pool_set *set, if (p != UNDEF_PART && rep_n_uuidp != NULL && uuidcmp(*rep_n_uuidp, HDR(rep, p)->next_repl_uuid)) { - ERR( + ERR_WO_ERRNO( "inconsistent replica uuids between replicas %u and %u", r, r_n); return -1; @@ -1714,7 +1734,7 @@ check_uuids_between_replicas(struct pool_set *set, unsigned p_nn = replica_find_unbroken_part(r_nn, set_hs); if (p_nn == UNDEF_PART) { - LOG(2, + CORE_LOG_WARNING( "cannot compare uuids on borders of replica %u", r); continue; @@ -1722,7 +1742,7 @@ check_uuids_between_replicas(struct pool_set *set, struct pool_replica *rep_nn = REP(set, r_nn); if (uuidcmp(HDR(rep, p)->next_repl_uuid, HDR(rep_nn, p_nn)->prev_repl_uuid)) { - ERR( + ERR_WO_ERRNO( "inconsistent replica uuids on borders of replica %u", r); return -1; @@ -1763,7 +1783,7 @@ check_replica_cycles(struct pool_set *set, * the number of all replicas; for the user it * means that: */ - ERR( + ERR_WO_ERRNO( "alien replica found (probably coming from a different poolset)"); return -1; } @@ -1790,7 +1810,9 @@ check_replica_sizes(struct pool_set *set, struct poolset_health_status *set_hs) replica_pool_size = replica_get_pool_size(set, r); if (replica_pool_size < 0) { - LOG(1, "getting pool size from replica %u failed", r); + CORE_LOG_ERROR( + "getting pool size from replica %u failed", + r); set_hs->replica[r]->flags |= IS_BROKEN; continue; } @@ -1798,7 +1820,7 @@ check_replica_sizes(struct pool_set *set, struct poolset_health_status *set_hs) /* check if the pool is bigger than minimum size */ enum pool_type type = pool_hdr_get_type(HDR(REP(set, r), 0)); if ((size_t)replica_pool_size < pool_get_min_size(type)) { - LOG(1, + CORE_LOG_ERROR( "pool size from replica %u is smaller than the minimum size allowed for the pool", r); set_hs->replica[r]->flags |= IS_BROKEN; @@ -1807,7 +1829,7 @@ check_replica_sizes(struct pool_set *set, struct poolset_health_status *set_hs) /* check if each replica is big enough to hold the pool data */ if (set->poolsize < (size_t)replica_pool_size) { - ERR( + ERR_WO_ERRNO( "some replicas are too small to hold synchronized data"); return -1; } @@ -1819,7 +1841,8 @@ check_replica_sizes(struct pool_set *set, struct poolset_health_status *set_hs) /* check if pools in all healthy replicas are of equal size */ if (pool_size != replica_pool_size) { - ERR("pool sizes from different replicas differ"); + ERR_WO_ERRNO( + "pool sizes from different replicas differ"); return -1; } } @@ -1848,7 +1871,7 @@ replica_read_features(struct pool_set *set, continue; if (util_map_hdr(part, MAP_SHARED, 0) != 0) { - LOG(1, "header mapping failed"); + CORE_LOG_ERROR("header mapping failed"); return -1; } @@ -1878,7 +1901,7 @@ replica_check_poolset_health(struct pool_set *set, set, set_hsp, called_from_sync, flags); if (replica_create_poolset_health_status(set, set_hsp)) { - LOG(1, "creating poolset health status failed"); + CORE_LOG_ERROR("creating poolset health status failed"); return -1; } @@ -1886,7 +1909,7 @@ replica_check_poolset_health(struct pool_set *set, /* check if part files exist and are accessible */ if (check_and_open_poolset_part_files(set, set_hs, flags)) { - LOG(1, "poolset part files check failed"); + CORE_LOG_ERROR("poolset part files check failed"); goto err; } @@ -1908,7 +1931,7 @@ replica_check_poolset_health(struct pool_set *set, * We will not fix bad blocks, so we have to read features here. */ if (replica_read_features(set, set_hs, &features)) { - LOG(1, "reading features failed"); + CORE_LOG_ERROR("reading features failed"); goto err; } check_bad_blks = features.compat & POOL_FEAT_CHECK_BAD_BLOCKS; @@ -1917,13 +1940,13 @@ replica_check_poolset_health(struct pool_set *set, /* check for bad blocks when in dry run or clear them otherwise */ if (replica_badblocks_check_or_clear(set, set_hs, is_dry_run(flags), called_from_sync, check_bad_blks, fix_bad_blks)) { - LOG(1, "replica bad_blocks check failed"); + CORE_LOG_ERROR("replica bad_blocks check failed"); goto err; } /* read features after fixing bad blocks */ if (fix_bad_blks && replica_read_features(set, set_hs, &features)) { - LOG(1, "reading features failed"); + CORE_LOG_ERROR("reading features failed"); goto err; } @@ -1941,47 +1964,47 @@ replica_check_poolset_health(struct pool_set *set, /* check if option flags are consistent */ if (check_options(set, set_hs)) { - LOG(1, "flags check failed"); + CORE_LOG_ERROR("flags check failed"); goto err; } if (!set->ignore_sds && check_shutdown_state(set, set_hs)) { - LOG(1, "replica shutdown_state check failed"); + CORE_LOG_ERROR("replica shutdown_state check failed"); goto err; } /* check if uuids in parts across each replica are consistent */ if (check_replicas_consistency(set, set_hs)) { - LOG(1, "replica consistency check failed"); + CORE_LOG_ERROR("replica consistency check failed"); goto err; } /* check poolset_uuid values between replicas */ if (check_poolset_uuids(set, set_hs)) { - LOG(1, "poolset uuids check failed"); + CORE_LOG_ERROR("poolset uuids check failed"); goto err; } /* check if uuids for adjacent replicas are consistent */ if (check_uuids_between_replicas(set, set_hs)) { - LOG(1, "replica uuids check failed"); + CORE_LOG_ERROR("replica uuids check failed"); goto err; } /* check if healthy replicas make up another poolset */ if (check_replica_cycles(set, set_hs)) { - LOG(1, "replica cycles check failed"); + CORE_LOG_ERROR("replica cycles check failed"); goto err; } /* check if replicas are large enough */ if (check_replica_sizes(set, set_hs)) { - LOG(1, "replica sizes check failed"); + CORE_LOG_ERROR("replica sizes check failed"); goto err; } if (check_store_all_sizes(set, set_hs)) { - LOG(1, "reading pool sizes failed"); + CORE_LOG_ERROR("reading pool sizes failed"); goto err; } @@ -2048,8 +2071,9 @@ replica_check_part_sizes(struct pool_set *set, size_t min_size) for (unsigned p = 0; p < rep->nparts; ++p) { if (PART(rep, p)->filesize < min_size) { - ERR("replica %u, part %u: file is too small", - r, p); + ERR_WO_ERRNO( + "replica %u, part %u: file is too small", + r, p); errno = EINVAL; return -1; } @@ -2071,7 +2095,7 @@ replica_check_local_part_dir(struct pool_set *set, unsigned repn, const char *dir = dirname(path); os_stat_t sb; if (os_stat(dir, &sb) != 0 || !(sb.st_mode & S_IFDIR)) { - ERR( + ERR_WO_ERRNO( "directory %s for part %u in replica %u does not exist or is not accessible", path, partn, repn); Free(path); @@ -2114,8 +2138,9 @@ replica_open_replica_part_files(struct pool_set *set, unsigned repn) continue; if (util_part_open(&rep->part[p], 0, 0)) { - LOG(1, "part files open failed for replica %u, part %u", - repn, p); + CORE_LOG_ERROR( + "part files open failed for replica %u, part %u", + repn, p); errno = EINVAL; goto err; } @@ -2136,7 +2161,8 @@ replica_open_poolset_part_files(struct pool_set *set) LOG(3, "set %p", set); for (unsigned r = 0; r < set->nreplicas; ++r) { if (replica_open_replica_part_files(set, r)) { - LOG(1, "opening replica %u, part files failed", r); + CORE_LOG_ERROR("opening replica %u, part files failed", + r); goto err; } } @@ -2160,13 +2186,13 @@ pmempool_syncU(const char *poolset, unsigned flags) /* check if poolset has correct signature */ if (util_is_poolset_file(poolset) != 1) { - ERR("file is not a poolset file"); + ERR_WO_ERRNO("file is not a poolset file"); goto err; } /* check if flags are supported */ if (check_flags_sync(flags)) { - ERR("unsupported flags"); + ERR_WO_ERRNO("unsupported flags"); errno = EINVAL; goto err; } @@ -2174,26 +2200,26 @@ pmempool_syncU(const char *poolset, unsigned flags) /* open poolset file */ int fd = util_file_open(poolset, NULL, 0, O_RDONLY); if (fd < 0) { - ERR("cannot open a poolset file"); + ERR_WO_ERRNO("cannot open a poolset file"); goto err; } /* fill up pool_set structure */ struct pool_set *set = NULL; if (util_poolset_parse(&set, poolset, fd)) { - ERR("parsing input poolset failed"); + ERR_WO_ERRNO("parsing input poolset failed"); goto err_close_file; } if (set->nreplicas == 1) { - ERR("no replica(s) found in the pool set"); + ERR_WO_ERRNO("no replica(s) found in the pool set"); errno = EINVAL; goto err_close_all; } /* sync all replicas */ if (replica_sync(set, NULL, flags)) { - LOG(1, "synchronization failed"); + CORE_LOG_ERROR("synchronization failed"); goto err_close_all; } @@ -2238,19 +2264,19 @@ pmempool_transformU(const char *poolset_src, /* check if the source poolset has correct signature */ if (util_is_poolset_file(poolset_src) != 1) { - ERR("source file is not a poolset file"); + ERR_WO_ERRNO("source file is not a poolset file"); goto err; } /* check if the destination poolset has correct signature */ if (util_is_poolset_file(poolset_dst) != 1) { - ERR("destination file is not a poolset file"); + ERR_WO_ERRNO("destination file is not a poolset file"); goto err; } /* check if flags are supported */ if (check_flags_transform(flags)) { - ERR("unsupported flags"); + ERR_WO_ERRNO("unsupported flags"); errno = EINVAL; goto err; } @@ -2258,14 +2284,14 @@ pmempool_transformU(const char *poolset_src, /* open the source poolset file */ int fd_in = util_file_open(poolset_src, NULL, 0, O_RDONLY); if (fd_in < 0) { - ERR("cannot open source poolset file"); + ERR_WO_ERRNO("cannot open source poolset file"); goto err; } /* parse the source poolset file */ struct pool_set *set_in = NULL; if (util_poolset_parse(&set_in, poolset_src, fd_in)) { - ERR("parsing source poolset failed"); + ERR_WO_ERRNO("parsing source poolset failed"); os_close(fd_in); goto err; } @@ -2274,7 +2300,7 @@ pmempool_transformU(const char *poolset_src, /* open the destination poolset file */ int fd_out = util_file_open(poolset_dst, NULL, 0, O_RDONLY); if (fd_out < 0) { - ERR("cannot open destination poolset file"); + ERR_WO_ERRNO("cannot open destination poolset file"); goto err_free_poolin; } @@ -2283,7 +2309,7 @@ pmempool_transformU(const char *poolset_src, /* parse the destination poolset file */ struct pool_set *set_out = NULL; if (util_poolset_parse(&set_out, poolset_dst, fd_out)) { - ERR("parsing destination poolset failed"); + ERR_WO_ERRNO("parsing destination poolset failed"); os_close(fd_out); goto err_free_poolin; } @@ -2293,8 +2319,9 @@ pmempool_transformU(const char *poolset_src, enum pool_type ptype = pool_set_type(set_in); if (ptype != POOL_TYPE_OBJ) { errno = EINVAL; - ERR("transform is not supported for given pool type: %s", - pool_get_pool_type_str(ptype)); + ERR_WO_ERRNO( + "transform is not supported for given pool type: %s", + pool_get_pool_type_str(ptype)); goto err_free_poolout; } @@ -2302,7 +2329,7 @@ pmempool_transformU(const char *poolset_src, /* transform poolset */ if (replica_transform(set_in, set_out, flags)) { - LOG(1, "transformation failed"); + CORE_LOG_ERROR("transformation failed"); goto err_free_poolout; } diff --git a/src/libpmempool/rm.c b/src/libpmempool/rm.c index 2978ae15cb1..480b3fa79cb 100644 --- a/src/libpmempool/rm.c +++ b/src/libpmempool/rm.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2016-2023, Intel Corporation */ +/* Copyright 2016-2024, Intel Corporation */ /* * rm.c -- implementation of pmempool_rm() function @@ -20,9 +20,9 @@ #define ERR_F(f, ...) do {\ if (CHECK_FLAG((f), FORCE))\ - LOG(2, "!(ignored) " __VA_ARGS__);\ + CORE_LOG_WARNING_W_ERRNO("(ignored) " __VA_ARGS__);\ else\ - ERR(__VA_ARGS__);\ + ERR_WO_ERRNO(__VA_ARGS__);\ } while (0) #define CHECK_FLAG(f, i) ((f) & PMEMPOOL_RM_##i) @@ -51,9 +51,9 @@ rm_local(const char *path, unsigned flags, int is_part_file) if (S_ISDIR(buff.st_mode)) { errno = EISDIR; if (is_part_file) - ERR("%s: removing file failed", path); + ERR_WO_ERRNO("%s: removing file failed", path); else - ERR("removing file failed"); + ERR_WO_ERRNO("removing file failed"); return -1; } } @@ -98,7 +98,7 @@ pmempool_rmU(const char *path, unsigned flags) int ret; if (flags & ~PMEMPOOL_RM_ALL_FLAGS) { - ERR("invalid flags specified"); + ERR_WO_ERRNO("invalid flags specified"); errno = EINVAL; return -1; } @@ -110,7 +110,7 @@ pmempool_rmU(const char *path, unsigned flags) if (!ret) { if (S_ISDIR(buff.st_mode)) { errno = EISDIR; - ERR("removing file failed"); + ERR_WO_ERRNO("removing file failed"); return -1; } } @@ -122,11 +122,11 @@ pmempool_rmU(const char *path, unsigned flags) } if (!is_poolset) { - LOG(2, "%s: not a poolset file", path); + CORE_LOG_ERROR("%s: not a poolset file", path); return rm_local(path, flags, 0); } - LOG(2, "%s: poolset file", path); + CORE_LOG_ERROR("%s: poolset file", path); /* fill up pool_set structure */ struct pool_set *set = NULL; diff --git a/src/libpmempool/sync.c b/src/libpmempool/sync.c index 3f04f74e984..6379d13e26d 100644 --- a/src/libpmempool/sync.c +++ b/src/libpmempool/sync.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2016-2022, Intel Corporation */ +/* Copyright 2016-2024, Intel Corporation */ /* * sync.c -- a module for poolset synchronizing @@ -41,7 +41,7 @@ validate_args(struct pool_set *set) * (now replication works only for pmemobj pools) */ if (replica_check_part_sizes(set, PMEMOBJ_MIN_POOL)) { - LOG(2, "part sizes check failed"); + CORE_LOG_ERROR("part sizes check failed"); goto err; } @@ -49,7 +49,7 @@ validate_args(struct pool_set *set) * check if all directories for part files exist */ if (replica_check_part_dirs(set)) { - LOG(2, "part directories check failed"); + CORE_LOG_ERROR("part directories check failed"); goto err; } @@ -98,7 +98,8 @@ sync_recreate_header(struct pool_set *set, unsigned r, unsigned p, util_pool_hdr2attr(&attr, src_hdr); if (util_header_create(set, r, p, &attr, 1) != 0) { - LOG(1, "part headers create failed for replica %u part %u", + CORE_LOG_ERROR( + "part headers create failed for replica %u part %u", r, p); errno = EINVAL; return -1; @@ -532,7 +533,9 @@ sync_badblocks_assign_healthy_replica(struct part_health_status *phs, struct bb_vec bbv_new = VEC_INITIALIZER; +#ifdef DEBUG /* variables required for ASSERTs below */ size_t size_all = VEC_SIZE(pbbv_all); +#endif pbb_all = VEC_GET(pbbv_all, *i_all); for (unsigned i = 0; i < phs->bbs.bb_cnt; i++) { @@ -711,7 +714,7 @@ sync_check_bad_blocks_overlap(struct pool_set *set, if (pbb_all->nhealthy == NO_HEALTHY_REPLICA) { ret = 1; /* this bad block cannot be fixed */ - LOG(1, + CORE_LOG_ERROR( "uncorrectable bad block found: offset 0x%zx, length 0x%zx", pbb_all->offset, pbb_all->length); @@ -816,10 +819,10 @@ sync_badblocks_data(struct pool_set *set, struct poolset_health_status *set_hs) sync_mark_replica_no_badblocks(r, set_hs); } - LOG(1, "all bad blocks have been fixed"); + CORE_LOG_HARK("all bad blocks have been fixed"); if (replica_remove_all_recovery_files(set_hs)) { - LOG(1, "removing bad block recovery files failed"); + CORE_LOG_ERROR("removing bad block recovery files failed"); return -1; } @@ -848,14 +851,14 @@ recreate_broken_parts(struct pool_set *set, /* remove parts from broken replica */ if (replica_remove_part(set, r, p, fix_bad_blocks)) { - LOG(2, "cannot remove part"); + CORE_LOG_ERROR("cannot remove part"); return -1; } /* create removed part and open it */ if (util_part_open(&broken_r->part[p], 0, 1 /* create */)) { - LOG(2, "cannot open/create parts"); + CORE_LOG_ERROR("cannot open/create parts"); return -1; } @@ -921,7 +924,8 @@ fill_struct_broken_part_uuids(struct pool_set *set, unsigned repn, if (replica_is_poolset_transformed(flags)) { /* generate new uuid for this part */ if (util_uuid_generate(rep->part[p].uuid) < 0) { - ERR("cannot generate pool set part UUID"); + ERR_WO_ERRNO( + "cannot generate pool set part UUID"); errno = EINVAL; return -1; } @@ -946,7 +950,7 @@ fill_struct_broken_part_uuids(struct pool_set *set, unsigned repn, hdrp = HDR(REPP(set, repn), 0); if (is_uuid_already_used(hdrp->next_repl_uuid, set, repn)) { - ERR( + ERR_WO_ERRNO( "repeated uuid - some replicas were created with a different poolset file"); errno = EINVAL; return -1; @@ -959,7 +963,7 @@ fill_struct_broken_part_uuids(struct pool_set *set, unsigned repn, hdrp = HDR(REPN(set, repn), 0); if (is_uuid_already_used(hdrp->prev_repl_uuid, set, repn)) { - ERR( + ERR_WO_ERRNO( "repeated uuid - some replicas were created with a different poolset file"); errno = EINVAL; return -1; @@ -969,7 +973,8 @@ fill_struct_broken_part_uuids(struct pool_set *set, unsigned repn, } else { /* generate new uuid for this part */ if (util_uuid_generate(rep->part[p].uuid) < 0) { - ERR("cannot generate pool set part UUID"); + ERR_WO_ERRNO( + "cannot generate pool set part UUID"); errno = EINVAL; return -1; } @@ -1110,7 +1115,8 @@ grant_created_parts_perm(struct pool_set *set, unsigned src_repn, mode_t src_mode; os_stat_t sb; if (os_stat(PART(REP(set, src_repn), 0)->path, &sb) != 0) { - ERR("cannot check file permissions of %s (replica %u, part %u)", + ERR_WO_ERRNO( + "cannot check file permissions of %s (replica %u, part %u)", PART(REP(set, src_repn), 0)->path, src_repn, 0); src_mode = def_mode; } else { @@ -1133,7 +1139,7 @@ grant_created_parts_perm(struct pool_set *set, unsigned src_repn, /* set rights to those of existing part files */ if (os_chmod(PART(REP(set, r), p)->path, src_mode)) { - ERR( + ERR_WO_ERRNO( "cannot set permission rights for created parts: replica %u, part %u", r, p); errno = EPERM; @@ -1314,13 +1320,13 @@ replica_sync(struct pool_set *set, struct poolset_health_status *s_hs, if (replica_check_poolset_health(set, &set_hs, 1 /* called from sync */, flags)) { - LOG(1, "poolset health check failed"); + CORE_LOG_ERROR("poolset health check failed"); return -1; } /* check if poolset is broken; if not, nothing to do */ if (replica_is_poolset_healthy(set_hs)) { - LOG(1, "poolset is healthy"); + CORE_LOG_HARK("poolset is healthy"); goto out; } } else { @@ -1333,7 +1339,7 @@ replica_sync(struct pool_set *set, struct poolset_health_status *s_hs, if (healthy_header == UNDEF_REPLICA) { healthy_header = replica_find_replica_healthy_header(set_hs); if (healthy_header == UNDEF_REPLICA) { - ERR("no healthy replica found"); + ERR_WO_ERRNO("no healthy replica found"); errno = EINVAL; ret = -1; goto out; @@ -1342,27 +1348,27 @@ replica_sync(struct pool_set *set, struct poolset_health_status *s_hs, /* in dry-run mode we can stop here */ if (is_dry_run(flags)) { - LOG(1, "Sync in dry-run mode finished successfully"); + CORE_LOG_HARK("Sync in dry-run mode finished successfully"); goto out; } /* recreate broken parts */ if (recreate_broken_parts(set, set_hs, fix_bad_blocks(flags))) { - ERR("recreating broken parts failed"); + ERR_WO_ERRNO("recreating broken parts failed"); ret = -1; goto out; } /* open all part files */ if (replica_open_poolset_part_files(set)) { - ERR("opening poolset part files failed"); + ERR_WO_ERRNO("opening poolset part files failed"); ret = -1; goto out; } /* map all replicas */ if (util_poolset_open(set)) { - ERR("opening poolset failed"); + ERR_WO_ERRNO("opening poolset failed"); ret = -1; goto out; } @@ -1373,7 +1379,7 @@ replica_sync(struct pool_set *set, struct poolset_health_status *s_hs, /* recalculate offset and length of bad blocks */ if (sync_recalc_badblocks(set, set_hs)) { - LOG(1, "syncing bad blocks data failed"); + CORE_LOG_ERROR("syncing bad blocks data failed"); ret = -1; goto out; } @@ -1384,13 +1390,13 @@ replica_sync(struct pool_set *set, struct poolset_health_status *s_hs, */ int status = sync_check_bad_blocks_overlap(set, set_hs); if (status == -1) { - LOG(1, "checking bad blocks failed"); + CORE_LOG_ERROR("checking bad blocks failed"); ret = -1; goto out; } if (status == 1) { - ERR( + ERR_WO_ERRNO( "a part of the pool has uncorrectable errors in all replicas"); errno = EINVAL; ret = -1; @@ -1401,7 +1407,7 @@ replica_sync(struct pool_set *set, struct poolset_health_status *s_hs, /* sync data in bad blocks */ if (sync_badblocks_data(set, set_hs)) { - LOG(1, "syncing bad blocks data failed"); + CORE_LOG_ERROR("syncing bad blocks data failed"); ret = -1; goto out; } @@ -1409,7 +1415,7 @@ replica_sync(struct pool_set *set, struct poolset_health_status *s_hs, /* find one good replica; it will be the source of data */ healthy_replica = replica_find_healthy_replica(set_hs); if (healthy_replica == UNDEF_REPLICA) { - ERR("no healthy replica found"); + ERR_WO_ERRNO("no healthy replica found"); errno = EINVAL; ret = -1; goto out; @@ -1417,14 +1423,14 @@ replica_sync(struct pool_set *set, struct poolset_health_status *s_hs, /* update uuid fields in the set structure with part headers */ if (fill_struct_uuids(set, healthy_replica, set_hs, flags)) { - ERR("gathering uuids failed"); + ERR_WO_ERRNO("gathering uuids failed"); ret = -1; goto out; } /* create headers for broken parts */ if (create_headers_for_broken_parts(set, healthy_replica, set_hs)) { - ERR("creating headers for broken parts failed"); + ERR_WO_ERRNO("creating headers for broken parts failed"); ret = -1; goto out; } @@ -1432,21 +1438,21 @@ replica_sync(struct pool_set *set, struct poolset_health_status *s_hs, /* check and copy data if possible */ if (copy_data_to_broken_parts(set, healthy_replica, flags, set_hs)) { - ERR("copying data to broken parts failed"); + ERR_WO_ERRNO("copying data to broken parts failed"); ret = -1; goto out; } /* update uuids of replicas and parts */ if (update_uuids(set, set_hs)) { - ERR("updating uuids failed"); + ERR_WO_ERRNO("updating uuids failed"); ret = -1; goto out; } /* grant permissions to all created parts */ if (grant_created_parts_perm(set, healthy_replica, set_hs)) { - ERR("granting permissions to created parts failed"); + ERR_WO_ERRNO("granting permissions to created parts failed"); ret = -1; } diff --git a/src/libpmempool/transform.c b/src/libpmempool/transform.c index 32a5fe7ab2b..be9f9fad81d 100644 --- a/src/libpmempool/transform.c +++ b/src/libpmempool/transform.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2016-2022, Intel Corporation */ +/* Copyright 2016-2024, Intel Corporation */ /* * transform.c -- a module for poolset transforming @@ -55,12 +55,13 @@ check_if_part_used_once(struct pool_set *set, unsigned repn, unsigned partn) struct pool_replica *rep = REP(set, repn); char *path = util_part_realpath(PART(rep, partn)->path); if (path == NULL) { - LOG(1, "cannot get absolute path for %s, replica %u, part %u", - PART(rep, partn)->path, repn, partn); + CORE_LOG_WARNING( + "cannot get absolute path for %s, replica %u, part %u", + PART(rep, partn)->path, repn, partn); errno = 0; path = strdup(PART(rep, partn)->path); if (path == NULL) { - ERR("!strdup"); + ERR_W_ERRNO("strdup"); return -1; } } @@ -74,30 +75,31 @@ check_if_part_used_once(struct pool_set *set, unsigned repn, unsigned partn) char *pathp = util_part_realpath(PART(repr, p)->path); if (pathp == NULL) { if (errno != ENOENT) { - ERR("realpath failed for %s, errno %d", + ERR_WO_ERRNO( + "realpath failed for %s, errno %d", PART(repr, p)->path, errno); ret = -1; goto out; } - LOG(1, "cannot get absolute path for %s," - " replica %u, part %u", - PART(rep, partn)->path, repn, - partn); + CORE_LOG_WARNING( + "cannot get absolute path for %s, replica %u, part %u", + PART(rep, partn)->path, repn, partn); pathp = strdup(PART(repr, p)->path); errno = 0; } int result = util_compare_file_inodes(path, pathp); if (result == 0) { /* same file used multiple times */ - ERR("some part file's path is" - " used multiple times"); + ERR_WO_ERRNO( + "some part file's path is used multiple times"); ret = -1; errno = EINVAL; free(pathp); goto out; } else if (result < 0) { - ERR("comparing file inodes failed for %s and" - " %s", path, pathp); + ERR_WO_ERRNO( + "comparing file inodes failed for %s and %s", + path, pathp); ret = -1; free(pathp); goto out; @@ -140,7 +142,8 @@ validate_args(struct pool_set *set_in, struct pool_set *set_out) LOG(3, "set_in %p, set_out %p", set_in, set_out); if (set_in->directory_based) { - ERR("transform of directory poolsets is not supported"); + ERR_WO_ERRNO( + "transform of directory poolsets is not supported"); errno = EINVAL; return -1; } @@ -150,7 +153,7 @@ validate_args(struct pool_set *set_in, struct pool_set *set_out) * (now replication works only for pmemobj pools) */ if (replica_check_part_sizes(set_out, PMEMOBJ_MIN_POOL)) { - ERR("part sizes check failed"); + ERR_WO_ERRNO("part sizes check failed"); return -1; } @@ -168,12 +171,12 @@ validate_args(struct pool_set *set_in, struct pool_set *set_out) */ ssize_t master_pool_size = replica_get_pool_size(set_in, 0); if (master_pool_size < 0) { - ERR("getting pool size from master replica failed"); + ERR_WO_ERRNO("getting pool size from master replica failed"); return -1; } if (set_out->poolsize < (size_t)master_pool_size) { - ERR("target poolset is too small"); + ERR_WO_ERRNO("target poolset is too small"); errno = EINVAL; return -1; } @@ -194,7 +197,7 @@ create_poolset_compare_status(struct pool_set *set, set_s = Zalloc(sizeof(struct poolset_compare_status) + set->nreplicas * sizeof(unsigned)); if (set_s == NULL) { - ERR("!Zalloc for poolset status"); + ERR_W_ERRNO("Zalloc for poolset status"); return -1; } for (unsigned r = 0; r < set->nreplicas; ++r) @@ -256,7 +259,8 @@ check_compare_poolsets_status(struct pool_set *set_in, struct pool_replica *rep_in = REP(set_in, ri); for (unsigned ro = 0; ro < set_out->nreplicas; ++ro) { struct pool_replica *rep_out = REP(set_out, ro); - LOG(1, "comparing rep_in %u with rep_out %u", ri, ro); + CORE_LOG_DEBUG("comparing rep_in %u with rep_out %u", + ri, ro); /* skip different replicas */ if (compare_replicas(rep_in, rep_out)) continue; @@ -265,8 +269,8 @@ check_compare_poolsets_status(struct pool_set *set_in, set_out_s->replica[ro] != UNDEF_REPLICA) { /* there are more than one counterparts */ - ERR("there are more then one corresponding" - " replicas; cannot transform"); + ERR_WO_ERRNO( + "there are more then one corresponding replicas; cannot transform"); errno = EINVAL; return -1; } @@ -296,8 +300,8 @@ check_compare_poolsets_options(struct pool_set *set_in, if ((set_in->options & OPTION_NOHDRS) || (set_out->options & OPTION_NOHDRS)) { errno = EINVAL; - ERR( - "the NOHDRS poolset option is not supported in local poolset files"); + ERR_WO_ERRNO( + "the NOHDRS poolset option is not supported in local poolset files"); return -1; } @@ -370,30 +374,31 @@ identify_transform_operation(struct poolset_compare_status *set_in_s, for (unsigned r = 0; r < set_in_s->nreplicas; ++r) { unsigned c = replica_counterpart(r, set_in_s); if (c != UNDEF_REPLICA) { - LOG(2, "replica %u has a counterpart %u", r, + CORE_LOG_DEBUG("replica %u has a counterpart %u", r, set_in_s->replica[r]); has_replica_to_keep = 1; REP_HEALTH(set_out_hs, c)->pool_size = REP_HEALTH(set_in_hs, r)->pool_size; } else { - LOG(2, "replica %u has no counterpart", r); + CORE_LOG_NOTICE("replica %u has no counterpart", r); is_removing_replicas = 1; } } /* make sure we have at least one replica to keep */ if (!has_replica_to_keep) { - ERR("there must be at least one replica left"); + ERR_WO_ERRNO("there must be at least one replica left"); return NOT_TRANSFORMABLE; } /* check if there are replicas to be added */ for (unsigned r = 0; r < set_out_s->nreplicas; ++r) { if (replica_counterpart(r, set_out_s) == UNDEF_REPLICA) { - LOG(2, "Replica %u from output set has no counterpart", + CORE_LOG_NOTICE( + "Replica %u from output set has no counterpart", r); if (is_removing_replicas) { - ERR( + ERR_WO_ERRNO( "adding and removing replicas at the same time is not allowed"); return NOT_TRANSFORMABLE; } @@ -407,7 +412,7 @@ identify_transform_operation(struct poolset_compare_status *set_in_s, if (!is_removing_replicas && !is_adding_replicas && (set_in_s->flags & OPTION_SINGLEHDR) == (set_out_s->flags & OPTION_SINGLEHDR)) { - ERR("both poolsets are equal"); + ERR_WO_ERRNO("both poolsets are equal"); return NOT_TRANSFORMABLE; } @@ -415,7 +420,7 @@ identify_transform_operation(struct poolset_compare_status *set_in_s, if ((is_removing_replicas || is_adding_replicas) && (set_in_s->flags & OPTION_SINGLEHDR) != (set_out_s->flags & OPTION_SINGLEHDR)) { - ERR( + ERR_WO_ERRNO( "cannot add/remove replicas and change the SINGLEHDR option at the same time"); return NOT_TRANSFORMABLE; } @@ -459,8 +464,8 @@ do_added_parts_exist(struct pool_set *set, return -1; if (exists && !rep->part[p].is_dev_dax) { - LOG(1, "part file %s exists", - rep->part[p].path); + CORE_LOG_ERROR("part file %s exists", + rep->part[p].path); return 1; } errno = oerrno; @@ -500,7 +505,8 @@ copy_replica_data_fw(struct pool_set *set_dst, struct pool_set *set_src, LOG(3, "set_in %p, set_out %p, repn %u", set_src, set_dst, repn); ssize_t pool_size = replica_get_pool_size(set_src, repn); if (pool_size < 0) { - LOG(1, "getting pool size from replica %u failed", repn); + CORE_LOG_WARNING("getting pool size from replica %u failed", + repn); pool_size = (ssize_t)set_src->poolsize; } @@ -527,7 +533,8 @@ copy_replica_data_bw(struct pool_set *set_dst, struct pool_set *set_src, LOG(3, "set_in %p, set_out %p, repn %u", set_src, set_dst, repn); ssize_t pool_size = replica_get_pool_size(set_src, repn); if (pool_size < 0) { - LOG(1, "getting pool size from replica %u failed", repn); + CORE_LOG_WARNING("getting pool size from replica %u failed", + repn); pool_size = (ssize_t)set_src->poolsize; } @@ -557,8 +564,9 @@ create_missing_headers(struct pool_set *set, unsigned repn) util_pool_hdr2attr(&attr, src_hdr); attr.features.incompat &= (uint32_t)(~POOL_FEAT_SINGLEHDR); if (util_header_create(set, repn, p, &attr, 1) != 0) { - LOG(1, "part headers create failed for" - " replica %u part %u", repn, p); + CORE_LOG_ERROR( + "part headers create failed for replica %u part %u", + repn, p); errno = EINVAL; return -1; } @@ -602,7 +610,7 @@ fill_replica_struct_uuids(struct pool_set *set, unsigned repn) memcpy(PART(rep, 0)->uuid, HDR(rep, 0)->uuid, POOL_HDR_UUID_LEN); for (unsigned p = 1; p < rep->nhdrs; ++p) { if (util_uuid_generate(rep->part[p].uuid) < 0) { - ERR("cannot generate part UUID"); + ERR_WO_ERRNO("cannot generate part UUID"); errno = EINVAL; return -1; } @@ -672,7 +680,7 @@ remove_hdrs_replica(struct pool_set *set_in, struct pool_set *set_out, /* open all part files of the input replica */ if (replica_open_replica_part_files(set_in, repn)) { - LOG(1, "opening replica %u, part files failed", repn); + CORE_LOG_ERROR("opening replica %u, part files failed", repn); ret = -1; goto out; } @@ -682,14 +690,16 @@ remove_hdrs_replica(struct pool_set *set_in, struct pool_set *set_out, /* map the whole input replica */ if (util_replica_open(set_in, repn, MAP_SHARED)) { - LOG(1, "opening input replica failed: replica %u", repn); + CORE_LOG_ERROR("opening input replica failed: replica %u", + repn); ret = -1; goto out_close; } /* map the whole output replica */ if (util_replica_open(set_out, repn, MAP_SHARED)) { - LOG(1, "opening output replica failed: replica %u", repn); + CORE_LOG_ERROR("opening output replica failed: replica %u", + repn); ret = -1; goto out_unmap_in; } @@ -724,7 +734,8 @@ add_hdrs_replica(struct pool_set *set_in, struct pool_set *set_out, /* open all part files of the input replica */ if (replica_open_replica_part_files(set_in, repn)) { - LOG(1, "opening replica %u, part files failed", repn); + CORE_LOG_ERROR("opening replica %u, part files failed", + repn); ret = -1; goto out; } @@ -734,22 +745,25 @@ add_hdrs_replica(struct pool_set *set_in, struct pool_set *set_out, /* map the whole input replica */ if (util_replica_open(set_in, repn, MAP_SHARED)) { - LOG(1, "opening input replica failed: replica %u", repn); + CORE_LOG_ERROR("opening input replica failed: replica %u", + repn); ret = -1; goto out_close; } /* map the whole output replica */ if (util_replica_open(set_out, repn, MAP_SHARED)) { - LOG(1, "opening output replica failed: replica %u", repn); + CORE_LOG_ERROR("opening output replica failed: replica %u", + repn); ret = -1; goto out_unmap_in; } /* generate new uuids for lacking headers */ if (fill_replica_struct_uuids(set_out, repn)) { - LOG(1, "generating lacking uuids for parts failed: replica %u", - repn); + CORE_LOG_ERROR( + "generating lacking uuids for parts failed: replica %u", + repn); ret = -1; goto out_unmap_out; } @@ -760,7 +774,8 @@ add_hdrs_replica(struct pool_set *set_in, struct pool_set *set_out, /* create the missing headers */ if (create_missing_headers(set_out, repn)) { - LOG(1, "creating lacking headers failed: replica %u", repn); + CORE_LOG_ERROR("creating lacking headers failed: replica %u", + repn); /* * copy the data back, so we could fall back to the original * state @@ -800,7 +815,8 @@ remove_hdrs(struct pool_set *set_in, struct pool_set *set_out, set_in, set_out, set_in_hs, flags); for (unsigned r = 0; r < set_in->nreplicas; ++r) { if (remove_hdrs_replica(set_in, set_out, r)) { - LOG(1, "removing headers from replica %u failed", r); + CORE_LOG_ERROR( + "removing headers from replica %u failed", r); /* mark all previous replicas as damaged */ while (--r < set_in->nreplicas) REP_HEALTH(set_in_hs, r)->flags |= IS_BROKEN; @@ -824,7 +840,8 @@ add_hdrs(struct pool_set *set_in, struct pool_set *set_out, set_in, set_out, set_in_hs, flags); for (unsigned r = 0; r < set_in->nreplicas; ++r) { if (add_hdrs_replica(set_in, set_out, r)) { - LOG(1, "adding headers to replica %u failed", r); + CORE_LOG_ERROR("adding headers to replica %u failed", + r); /* mark all previous replicas as damaged */ while (--r < set_in->nreplicas) REP_HEALTH(set_in_hs, r)->flags |= IS_BROKEN; @@ -852,12 +869,12 @@ replica_transform(struct pool_set *set_in, struct pool_set *set_out, struct poolset_health_status *set_in_hs = NULL; if (replica_check_poolset_health(set_in, &set_in_hs, 0 /* called from transform */, flags)) { - ERR("source poolset health check failed"); + ERR_WO_ERRNO("source poolset health check failed"); return -1; } if (!replica_is_poolset_healthy(set_in_hs)) { - ERR("source poolset is broken"); + ERR_WO_ERRNO("source poolset is broken"); ret = -1; errno = EINVAL; goto free_hs_in; @@ -868,7 +885,7 @@ replica_transform(struct pool_set *set_in, struct pool_set *set_out, struct poolset_health_status *set_out_hs = NULL; if (replica_create_poolset_health_status(set_out, &set_out_hs)) { - ERR("creating poolset health status failed"); + ERR_WO_ERRNO("creating poolset health status failed"); ret = -1; goto free_hs_in; } @@ -877,7 +894,7 @@ replica_transform(struct pool_set *set_in, struct pool_set *set_out, struct poolset_compare_status *set_in_cs = NULL; struct poolset_compare_status *set_out_cs = NULL; if (compare_poolsets(set_in, set_out, &set_in_cs, &set_out_cs)) { - ERR("comparing poolsets failed"); + ERR_WO_ERRNO("comparing poolsets failed"); ret = -1; goto free_hs_out; } @@ -886,7 +903,7 @@ replica_transform(struct pool_set *set_in, struct pool_set *set_out, set_out_cs, set_in_hs, set_out_hs); if (operation == NOT_TRANSFORMABLE) { - LOG(1, "poolsets are not transformable"); + CORE_LOG_ERROR("poolsets are not transformable"); ret = -1; errno = EINVAL; goto free_cs; @@ -896,15 +913,15 @@ replica_transform(struct pool_set *set_in, struct pool_set *set_out, if (!is_dry_run(flags) && remove_hdrs(set_in, set_out, set_in_hs, flags)) { - ERR("removing headers failed; falling back to the " - "input poolset"); + ERR_WO_ERRNO( + "removing headers failed; falling back to the input poolset"); if (replica_sync(set_in, set_in_hs, flags | IS_TRANSFORMED)) { - LOG(1, "falling back to the input poolset " - "failed"); + CORE_LOG_ERROR( + "falling back to the input poolset failed"); } else { - LOG(1, "falling back to the input poolset " - "succeeded"); + CORE_LOG_HARK( + "falling back to the input poolset succeeded"); } ret = -1; } @@ -914,15 +931,15 @@ replica_transform(struct pool_set *set_in, struct pool_set *set_out, if (operation == ADD_HDRS) { if (!is_dry_run(flags) && add_hdrs(set_in, set_out, set_in_hs, flags)) { - ERR("adding headers failed; falling back to the " - "input poolset"); + ERR_WO_ERRNO( + "adding headers failed; falling back to the input poolset"); if (replica_sync(set_in, set_in_hs, flags | IS_TRANSFORMED)) { - LOG(1, "falling back to the input poolset " - "failed"); + CORE_LOG_ERROR( + "falling back to the input poolset failed"); } else { - LOG(1, "falling back to the input poolset " - "succeeded"); + CORE_LOG_HARK( + "falling back to the input poolset succeeded"); } ret = -1; } @@ -934,7 +951,7 @@ replica_transform(struct pool_set *set_in, struct pool_set *set_out, * check if any of the parts that are to be added already exists */ if (do_added_parts_exist(set_out, set_out_hs)) { - ERR("some parts being added already exist"); + ERR_WO_ERRNO("some parts being added already exist"); ret = -1; errno = EINVAL; goto free_cs; diff --git a/src/test/Makefile b/src/test/Makefile index 761cfa73f1f..e7a9c78a889 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2014-2023, Intel Corporation +# Copyright 2014-2024, Intel Corporation # # @@ -23,7 +23,6 @@ OBJ_TESTS = \ obj_many_size_allocs\ obj_realloc\ obj_sync\ - \ obj_action\ obj_alloc\ obj_badblock\ @@ -63,6 +62,9 @@ OBJ_TESTS = \ obj_list_valgrind\ obj_list_macro\ obj_locks\ + obj_log_get_treshold\ + obj_log_set_function\ + obj_log_set_treshold\ obj_mem\ obj_memblock\ obj_memcheck\ @@ -108,6 +110,13 @@ OBJ_TESTS = \ OTHER_TESTS = \ arch_flags\ + core_log\ + core_log_default_function\ + core_log_function_mt\ + core_log_internal\ + core_log_max\ + core_log_no_func\ + core_log_threshold_mt\ checksum\ compat_incompat_features\ ctl_prefault\ @@ -120,8 +129,6 @@ OTHER_TESTS = \ scope\ set_funcs\ traces\ - traces_custom_function\ - traces_pmem\ unicode_match_script\ util_badblock\ util_ctl\ @@ -142,7 +149,9 @@ OTHER_TESTS = \ util_sds\ util_uuid_generate\ util_vec\ - util_vecq + util_vecq\ + log_errno\ + valgrind_check ifeq ($(ARCH), x86_64) OTHER_TESTS += \ @@ -153,6 +162,9 @@ PMEM_TESTS = \ pmem_include\ pmem_is_pmem\ pmem_is_pmem_posix\ + pmem_log_get_treshold\ + pmem_log_set_function\ + pmem_log_set_treshold\ pmem_map_file\ pmem_has_auto_flush\ pmem_deep_persist\ diff --git a/src/test/Makefile.inc b/src/test/Makefile.inc index 2d893b96618..103a89ca715 100644 --- a/src/test/Makefile.inc +++ b/src/test/Makefile.inc @@ -1,5 +1,5 @@ # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2014-2023, Intel Corporation +# Copyright 2014-2024, Intel Corporation # # @@ -47,6 +47,7 @@ endif ifeq ($(LIBPMEMOBJ), y) LIBPMEM=y +USE_LOG_PMEMOBJ=y DYNAMIC_LIBS += -lpmemobj STATIC_DEBUG_LIBS += $(LIBS_DIR)/debug/libpmemobj.a STATIC_NONDEBUG_LIBS += $(LIBS_DIR)/nondebug/libpmemobj.a @@ -54,6 +55,7 @@ endif ifeq ($(LIBPMEMOBJ), internal-debug) LIBPMEM=y +USE_LOG_PMEMOBJ=y LIBPMEMCOMMON=internal-debug OBJS += $(TOP)/src/debug/libpmemobj/alloc_class.o\ $(TOP)/src/debug/libpmemobj/bucket.o\ @@ -74,13 +76,15 @@ OBJS += $(TOP)/src/debug/libpmemobj/alloc_class.o\ $(TOP)/src/debug/libpmemobj/ulog.o\ $(TOP)/src/debug/libpmemobj/sync.o\ $(TOP)/src/debug/libpmemobj/tx.o\ - $(TOP)/src/debug/libpmemobj/stats.o + $(TOP)/src/debug/libpmemobj/stats.o\ + $(TOP)/src/debug/libpmemobj/obj_log.o INCS += -I$(TOP)/src/libpmemobj endif ifeq ($(LIBPMEMOBJ), internal-nondebug) LIBPMEM=y +USE_LOG_PMEMOBJ=y LIBPMEMCOMMON=internal-nondebug OBJS += $(TOP)/src/nondebug/libpmemobj/alloc_class.o\ $(TOP)/src/nondebug/libpmemobj/bucket.o\ @@ -101,7 +105,8 @@ OBJS += $(TOP)/src/nondebug/libpmemobj/alloc_class.o\ $(TOP)/src/nondebug/libpmemobj/ulog.o\ $(TOP)/src/nondebug/libpmemobj/sync.o\ $(TOP)/src/nondebug/libpmemobj/tx.o\ - $(TOP)/src/nondebug/libpmemobj/stats.o + $(TOP)/src/nondebug/libpmemobj/stats.o\ + $(TOP)/src/nondebug/libpmemobj/obj_log.o INCS += -I$(TOP)/src/libpmemobj endif @@ -388,6 +393,9 @@ ifeq ($(LIBPMEMCORE), internal-nondebug) OBJS +=\ $(TOP)/src/nondebug/core/alloc.o\ $(TOP)/src/nondebug/core/fs_posix.o\ + $(TOP)/src/nondebug/core/last_error_msg.o\ + $(TOP)/src/nondebug/core/log.o\ + $(TOP)/src/nondebug/core/log_default.o\ $(TOP)/src/nondebug/core/os_posix.o\ $(TOP)/src/nondebug/core/os_thread_posix.o\ $(TOP)/src/nondebug/core/out.o\ @@ -403,6 +411,9 @@ ifeq ($(LIBPMEMCORE), internal-debug) OBJS +=\ $(TOP)/src/debug/core/alloc.o\ $(TOP)/src/debug/core/fs_posix.o\ + $(TOP)/src/debug/core/last_error_msg.o\ + $(TOP)/src/debug/core/log.o\ + $(TOP)/src/debug/core/log_default.o\ $(TOP)/src/debug/core/os_posix.o\ $(TOP)/src/debug/core/os_thread_posix.o\ $(TOP)/src/debug/core/out.o\ @@ -441,7 +452,7 @@ endif PAREN=( extract_funcs = $(shell \ awk -F '[$(PAREN),]' \ - '/(FUNC_MOCK_RET_ALWAYS|FUNC_MOCK_RET_ALWAYS_VOID|FUNC_MOCK)\$(PAREN)[^,]/ \ + '/(FUNC_MOCK_RET_ALWAYS|FUNC_MOCK_RET_ALWAYS_VOID|FUNC_MOCK|FUNC_MOCK_NONSTATIC)\$(PAREN)[^,]/ \ { \ print "-Wl,--wrap=" $$2 \ }' $(1) ) @@ -517,6 +528,20 @@ CFLAGS += -DFAULT_INJECTION=1 CXXFLAGS += -DFAULT_INJECTION=1 endif +ifeq ($(USE_LOG_PMEMOBJ),y) +CFLAGS += -DUSE_LOG_PMEMOBJ +endif + +# LIBPMEMCORE == '' means the binary is built without directly linking with +# core units which are required whenever test makes use of core utils. +ifeq ($(LIBPMEMCORE),) +OBJS += $(TOP)/src/debug/core/out.o +OBJS += $(TOP)/src/debug/core/last_error_msg.o +OBJS += $(TOP)/src/debug/core/log.o +OBJS += $(TOP)/src/debug/core/log_default.o +OBJS += $(TOP)/src/debug/core/util_posix.o +endif + ifneq ($(SANITIZE),) CFLAGS += -fsanitize=$(SANITIZE) CXXFLAGS += -fsanitize=$(SANITIZE) diff --git a/src/test/RUNTESTS.py b/src/test/RUNTESTS.py index da27e155918..ccf4355f9aa 100755 --- a/src/test/RUNTESTS.py +++ b/src/test/RUNTESTS.py @@ -121,7 +121,9 @@ def run_tests(self): continue except futils.Skip as s: - self.msg.print('{}: SKIP: {}'.format(t, s)) + self.msg.print('{}: {}SKIP{}: {}'. + format(t, futils.Color.YELLOW, + futils.Color.END, s)) except futils.Fail as f: self._test_failed(t, c, f) @@ -130,7 +132,9 @@ def run_tests(self): self._test_passed(t) except futils.Skip as s: - self.msg.print('{}: SKIP: {}'.format(tc, s)) + self.msg.print('{}: {}SKIP{}: {}'. + format(tc, futils.Color.YELLOW, + futils.Color.END, s)) except futils.Fail as f: self._test_failed(tc, c, f) ret = 1 diff --git a/src/test/arch_flags/log0.log.match b/src/test/arch_flags/log0.log.match index 6328efe7c15..f55300c8a02 100644 --- a/src/test/arch_flags/log0.log.match +++ b/src/test/arch_flags/log0.log.match @@ -1,12 +1,12 @@ -: <1> [$(nW) out_init]$(W)pid $(nW): program: $(nW) -: <1> [$(nW) out_init]$(W)arch_flags version 0.0 -: <1> [$(nW) out_init]$(W)src version: $(nW) -$(OPT): <1> [$(nW) out_init]$(W)compiled with support for Valgrind pmemcheck -$(OPT): <1> [$(nW) out_init]$(W)compiled with support for Valgrind helgrind -$(OPT): <1> [$(nW) out_init]$(W)compiled with support for Valgrind memcheck -$(OPT): <1> [$(nW) out_init]$(W)compiled with support for Valgrind drd -$(OPT): <1> [$(nW) out_init]$(W)compiled with support for shutdown state -$(OPT): <1> [$(nW) out_init]$(W)compiled with libndctl 63+ +: <1> [$(*)]$(W)src version: $(nW) +$(OPT): <1> [$(*)]$(W)compiled with support for shutdown state +$(OPT): <1> [$(*)]$(W)compiled with libndctl 63+ +: <1> [$(*)]$(W)pid $(nW): program: $(nW) +: <1> [$(*)]$(W)arch_flags version 0.0 +$(OPT): <1> [$(*)]$(W)compiled with support for Valgrind pmemcheck +$(OPT): <1> [$(*)]$(W)compiled with support for Valgrind helgrind +$(OPT): <1> [$(*)]$(W)compiled with support for Valgrind memcheck +$(OPT): <1> [$(*)]$(W)compiled with support for Valgrind drd : <3> [$(nW) util_mmap_init] : <1> [$(nW) util_check_arch_flags]$(W)invalid machine value : <1> [$(nW) util_check_arch_flags]$(W)invalid machine_class value diff --git a/src/test/core_log/.gitignore b/src/test/core_log/.gitignore new file mode 100644 index 00000000000..077e6928a11 --- /dev/null +++ b/src/test/core_log/.gitignore @@ -0,0 +1 @@ +core_log diff --git a/src/test/core_log/Makefile b/src/test/core_log/Makefile new file mode 100644 index 00000000000..0067f595c8d --- /dev/null +++ b/src/test/core_log/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation + +TARGET = core_log +OBJS = core_log.o core_log_common.o + +include ./Makefile.inc diff --git a/src/test/core_log/Makefile.inc b/src/test/core_log/Makefile.inc new file mode 100644 index 00000000000..1e2ecb614bb --- /dev/null +++ b/src/test/core_log/Makefile.inc @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation + +BUILD_STATIC_DEBUG=n +BUILD_STATIC_NONDEBUG=n + +# required for proper mock integration +LIBPMEMCORE=internal-debug + +include ../Makefile.inc +LDFLAGS += $(call extract_funcs, ../core_log/core_log_common.c) diff --git a/src/test/core_log/TESTS.py b/src/test/core_log/TESTS.py new file mode 100755 index 00000000000..c84ad1578e3 --- /dev/null +++ b/src/test/core_log/TESTS.py @@ -0,0 +1,52 @@ +#!../env.py +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation +# + + +import testframework as t +from testframework import granularity as g + + +@g.require_granularity(g.ANY) +@t.require_valgrind_disabled('pmemcheck') +# The 'nondebug' build is chosen arbitrarily to ensure these tests are run only +# once. No dynamic libraries are used nor .static_* builds are available. +@t.require_build('nondebug') +class CORE_LOG(t.BaseTest): + test_type = t.Short + + def run(self, ctx): + ctx.exec('core_log', self.test_case) + + +class TEST0(CORE_LOG): + test_case = 'test_CORE_LOG_LEVEL_ERROR_LAST' + + +class TEST1(CORE_LOG): + test_case = 'test_vsnprintf_fail' + + +class TEST2(CORE_LOG): + test_case = 'test_NO_ERRNO' + + +class TEST3(CORE_LOG): + test_case = 'test_no_space_for_strerror_r' + + +class TEST4(CORE_LOG): + test_case = 'test_strerror_r_fail' + + +class TEST5(CORE_LOG): + test_case = 'test_level_gt_threshold' + + +class TEST6(CORE_LOG): + test_case = 'test_happy_day' + + +class TEST7(CORE_LOG): + test_case = 'test_set_custom_function' diff --git a/src/test/core_log/core_log.c b/src/test/core_log/core_log.c new file mode 100644 index 00000000000..5801f02ef0c --- /dev/null +++ b/src/test/core_log/core_log.c @@ -0,0 +1,259 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* Copyright 2024, Intel Corporation */ + +/* + * core_log.c -- unit test for core_log(), core_log_va() and + * core_log_set_function() + */ + +#include + +#include "last_error_msg.h" +#include "unittest.h" + +#include "core_log_common.h" + +/* tests */ + +/* + * Check: + * - CORE_LOG_LEVEL_ERROR_LAST -> CORE_LOG_LEVEL_ERROR + * - buf == last_error_msg_get(); + * - buf_len == CORE_LAST_ERROR_MSG_MAXPRINT + */ +static int +test_CORE_LOG_LEVEL_ERROR_LAST(const struct test_case *tc, int argc, + char *argv[]) +{ + /* Pass the message all the way to the logging function. */ + core_log_set_threshold(CORE_LOG_THRESHOLD, CORE_LOG_LEVEL_ERROR); + + reset_mocks(); + + /* set the expectations */ + Common.use_last_error_msg = true; + Vsnprintf_.ret = 0; /* empty but successful */ + Log_function_.exp_level = CORE_LOG_LEVEL_ERROR; + + core_log(CORE_LOG_LEVEL_ERROR_LAST, NO_ERRNO, FILE_NAME, LINE_NO, + FUNC_NAME, MSG_FORMAT); + + /* check the call counters */ + UT_ASSERTeq(RCOUNTER(last_error_msg_get), CALLED); + UT_ASSERTeq(RCOUNTER(vsnprintf), CALLED); + UT_ASSERTeq(RCOUNTER(__xpg_strerror_r), NOT_CALLED); + UT_ASSERTeq(RCOUNTER(core_log_default_function), CALLED); + return NO_ARGS_CONSUMED; +} + +/* + * Check: + * - The log preparation stops after the failed vsnprintf() call. + * - The log function is not called. + */ +static int +test_vsnprintf_fail(const struct test_case *tc, int argc, char *argv[]) +{ + /* Pass the message all the way to the logging function. */ + core_log_set_threshold(CORE_LOG_THRESHOLD, CORE_LOG_LEVEL_ERROR); + + reset_mocks(); + + /* set the expectations */ + Vsnprintf_.ret = -1; /* negative value if an output error */ + Log_function_.exp_level = CORE_LOG_LEVEL_ERROR; + Common.use_last_error_msg = false; + + core_log(CORE_LOG_LEVEL_ERROR, NO_ERRNO, FILE_NAME, LINE_NO, + FUNC_NAME, MSG_FORMAT); + + /* check the call counters */ + UT_ASSERTeq(RCOUNTER(last_error_msg_get), NOT_CALLED); + UT_ASSERTeq(RCOUNTER(vsnprintf), CALLED); + UT_ASSERTeq(RCOUNTER(__xpg_strerror_r), NOT_CALLED); + UT_ASSERTeq(RCOUNTER(core_log_default_function), NOT_CALLED); + return NO_ARGS_CONSUMED; +} + +/* + * Check: + * - NO_ERRNO means no strerror_r() call. + * - The produced log message is passed to the log function. + */ +static int +test_NO_ERRNO(const struct test_case *tc, int argc, char *argv[]) +{ + /* Pass the message all the way to the logging function. */ + core_log_set_threshold(CORE_LOG_THRESHOLD, CORE_LOG_LEVEL_ERROR); + + reset_mocks(); + + /* set the expectations */ + Vsnprintf_.ret = 0; /* leave a lot of space for the error string */ + Log_function_.exp_level = CORE_LOG_LEVEL_ERROR; + Common.use_last_error_msg = false; + + core_log(CORE_LOG_LEVEL_ERROR, NO_ERRNO, FILE_NAME, LINE_NO, + FUNC_NAME, MSG_FORMAT); + + /* check the call counters */ + UT_ASSERTeq(RCOUNTER(last_error_msg_get), NOT_CALLED); + UT_ASSERTeq(RCOUNTER(vsnprintf), CALLED); + UT_ASSERTeq(RCOUNTER(__xpg_strerror_r), NOT_CALLED); + UT_ASSERTeq(RCOUNTER(core_log_default_function), CALLED); + return NO_ARGS_CONSUMED; +} + +/* + * Check: + * - fully fill the provided buffer in three ways: + * (1) exactly (`- 1` for the terminating null-byte) + * (2) one character too many (the null-byte would end up just after + * the actual buffer space) + * (3) two characters too many (no space for one character of the message and + * for the null-byte) + * - the strerror_r() is not called despite an errno is provided. + */ +static int +test_no_space_for_strerror_r(const struct test_case *tc, int argc, char *argv[]) +{ + /* Pass the message all the way to the logging function. */ + core_log_set_threshold(CORE_LOG_THRESHOLD, CORE_LOG_LEVEL_ERROR); + + for (int i = _CORE_LOG_MSG_MAXPRINT - 1; + i <= _CORE_LOG_MSG_MAXPRINT + 1; ++i) { + test_no_space_for_strerror_r_helper(i); + } + + return NO_ARGS_CONSUMED; +} + +/* + * Check: + * - strerror_r() fails in two ways: + * (1) before glibc 2.13 + * (2) since glibc 2.13 + * - The produced log message is passed to the log function. + */ +static int +test_strerror_r_fail(const struct test_case *tc, int argc, char *argv[]) +{ + /* Pass the message all the way to the logging function. */ + core_log_set_threshold(CORE_LOG_THRESHOLD, CORE_LOG_LEVEL_ERROR); + + test_strerror_r_fail_helper(true); + test_strerror_r_fail_helper(false); + + return NO_ARGS_CONSUMED; +} + +/* + * Check: + * - if level <= threshold: + * - the log function is called + * - else: + * - the log function is not called + */ +static int +test_level_gt_threshold(const struct test_case *tc, int argc, char *argv[]) +{ + for (enum core_log_level threshold = CORE_LOG_LEVEL_HARK; + threshold < CORE_LOG_LEVEL_MAX; ++threshold) { + core_log_set_threshold(CORE_LOG_THRESHOLD, threshold); + + for (enum core_log_level level = CORE_LOG_LEVEL_HARK; + level < CORE_LOG_LEVEL_MAX; ++level) { + bool log_function_called = (level <= threshold); + test_log_function_call_helper(level, + log_function_called); + } + } + + return NO_ARGS_CONSUMED; +} + +static int +test_happy_day_helper(core_log_function *log_function) +{ + /* Pass the message all the way to the logging function. */ + core_log_set_threshold(CORE_LOG_THRESHOLD, CORE_LOG_LEVEL_ERROR); + + /* + * Disable the validation as custom_log_function() may be called from + * core_log_set_function(). + */ + if (log_function == CORE_LOG_USE_DEFAULT_FUNCTION) { + FUNC_MOCK_RCOUNTER_SET(core_log_default_function, + NOT_VALIDATED_CALL); + } else { + FUNC_MOCK_RCOUNTER_SET(custom_log_function, + NOT_VALIDATED_CALL); + } + + core_log_set_function(log_function); + + reset_mocks(); + + /* set the expectations */ + Vsnprintf_.ret = BASIC_MESSAGE_LEN; + Log_function_.exp_level = CORE_LOG_LEVEL_ERROR; + Common.use_last_error_msg = true; + Strerror_r.exp__buf = LAST_ERROR_MSG_MOCK + Vsnprintf_.ret; + Strerror_r.exp__buflen = CORE_LAST_ERROR_MSG_MAXPRINT - + (size_t)Vsnprintf_.ret; + Strerror_r.error = EXIT_SUCCESS; + + core_log(CORE_LOG_LEVEL_ERROR_LAST, DUMMY_ERRNO1, FILE_NAME, LINE_NO, + FUNC_NAME, MSG_FORMAT); + + /* check the call counters */ + UT_ASSERTeq(RCOUNTER(last_error_msg_get), CALLED); + UT_ASSERTeq(RCOUNTER(vsnprintf), CALLED); + UT_ASSERTeq(RCOUNTER(__xpg_strerror_r), CALLED); + if (log_function == CORE_LOG_USE_DEFAULT_FUNCTION) { + UT_ASSERTeq(RCOUNTER(core_log_default_function), CALLED); + UT_ASSERTeq(RCOUNTER(custom_log_function), NOT_CALLED); + } else { + UT_ASSERTeq(RCOUNTER(core_log_default_function), NOT_CALLED); + UT_ASSERTeq(RCOUNTER(custom_log_function), CALLED); + } + + return NO_ARGS_CONSUMED; +} + +static int +test_happy_day(const struct test_case *tc, int argc, char *argv[]) +{ + return test_happy_day_helper(CORE_LOG_USE_DEFAULT_FUNCTION); +} + +/* Happy day scenario with custom logging function */ +static int +test_set_custom_function(const struct test_case *tc, int argc, char *argv[]) +{ + return test_happy_day_helper(custom_log_function); +} + +static struct test_case test_cases[] = { + TEST_CASE(test_CORE_LOG_LEVEL_ERROR_LAST), + TEST_CASE(test_vsnprintf_fail), + TEST_CASE(test_NO_ERRNO), + TEST_CASE(test_no_space_for_strerror_r), + TEST_CASE(test_strerror_r_fail), + TEST_CASE(test_level_gt_threshold), + TEST_CASE(test_happy_day), + TEST_CASE(test_set_custom_function), +}; + +#define NTESTS ARRAY_SIZE(test_cases) + +int +main(int argc, char *argv[]) +{ + START(argc, argv, "core_log"); + core_log_set_function(CORE_LOG_USE_DEFAULT_FUNCTION); + openlog(NULL, LOG_NDELAY, LOG_USER); + TEST_CASE_PROCESS(argc, argv, test_cases, NTESTS); + closelog(); + DONE(NULL); +} diff --git a/src/test/core_log/core_log_common.c b/src/test/core_log/core_log_common.c new file mode 100644 index 00000000000..e5104e60fe3 --- /dev/null +++ b/src/test/core_log/core_log_common.c @@ -0,0 +1,192 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* Copyright 2024, Intel Corporation */ + +/* + * core_log_common.c -- mocks and helpers common for core_log(_no_func) + */ + +#include "last_error_msg.h" +#include "unittest.h" + +#include "core_log_common.h" + +/* mocks */ + +struct common_ctx Common; +struct vsnprintf_ctx Vsnprintf_; +struct strerror_r_ctx Strerror_r; +struct log_function_ctx Log_function_; + +FUNC_MOCK_NONSTATIC(last_error_msg_get, const char *, void) +FUNC_MOCK_RUN_DEFAULT { + return LAST_ERROR_MSG_MOCK; +} +FUNC_MOCK_END + +FUNC_MOCK_NONSTATIC(vsnprintf, int, char *__restrict __s, size_t __maxlen, + const char *__restrict __format, va_list __arg) + FUNC_MOCK_RUN(VALIDATED_CALL) { + if (Common.use_last_error_msg) { + UT_ASSERTeq(__s, LAST_ERROR_MSG_MOCK); + UT_ASSERTeq(__maxlen, CORE_LAST_ERROR_MSG_MAXPRINT); + } else { + UT_ASSERTne(__s, LAST_ERROR_MSG_MOCK); + UT_ASSERTeq(__maxlen, _CORE_LOG_MSG_MAXPRINT); + } + UT_ASSERT(__format == MSG_FORMAT); + (void) __arg; + + return Vsnprintf_.ret; + } +FUNC_MOCK_RUN_DEFAULT { + return _FUNC_REAL(vsnprintf)(__s, __maxlen, __format, __arg); +} +FUNC_MOCK_END + +FUNC_MOCK_NONSTATIC(__xpg_strerror_r, int, int __errnum, char *__buf, + size_t __buflen) +FUNC_MOCK_RUN_DEFAULT { + UT_ASSERTeq(__errnum, DUMMY_ERRNO1); + UT_ASSERTeq(__buf, Strerror_r.exp__buf); + UT_ASSERTeq(__buflen, Strerror_r.exp__buflen); + + if (Strerror_r.error == EXIT_SUCCESS) { + return 0; + } + + if (Strerror_r.before_glibc_2_13) { + errno = Strerror_r.error; + return -1; + } else { + return Strerror_r.error; + } +} +FUNC_MOCK_END + +FUNC_MOCK_NONSTATIC(core_log_default_function, void, enum core_log_level level, + const char *file_name, unsigned line_no, const char *function_name, + const char *message) + FUNC_MOCK_RUN(VALIDATED_CALL) { + UT_ASSERTeq(level, Log_function_.exp_level); + UT_ASSERTstreq(file_name, FILE_NAME); + UT_ASSERTeq(line_no, LINE_NO); + UT_ASSERTstreq(function_name, FUNC_NAME); + if (Common.use_last_error_msg) { + UT_ASSERTeq(message, LAST_ERROR_MSG_MOCK); + } else { + UT_ASSERTne(message, LAST_ERROR_MSG_MOCK); + } + return; + } +FUNC_MOCK_RUN_DEFAULT { + _FUNC_REAL(core_log_default_function)(level, file_name, line_no, + function_name, message); +} +FUNC_MOCK_END + +FUNC_MOCK_NONSTATIC(custom_log_function, void, enum core_log_level level, + const char *file_name, unsigned line_no, const char *function_name, + const char *message) + FUNC_MOCK_RUN(VALIDATED_CALL) { + UT_ASSERTeq(level, Log_function_.exp_level); + UT_ASSERTstreq(file_name, FILE_NAME); + UT_ASSERTeq(line_no, LINE_NO); + UT_ASSERTstreq(function_name, FUNC_NAME); + if (Common.use_last_error_msg) { + UT_ASSERTeq(message, LAST_ERROR_MSG_MOCK); + } else { + UT_ASSERTne(message, LAST_ERROR_MSG_MOCK); + } + return; + } +FUNC_MOCK_RUN_DEFAULT { + _FUNC_REAL(custom_log_function)(level, file_name, line_no, + function_name, message); +} +FUNC_MOCK_END + +void +custom_log_function(enum core_log_level level, const char *file_name, + unsigned line_no, const char *function_name, const char *message) +{ + SUPPRESS_UNUSED(level, file_name, line_no, function_name, message); +} + +/* helpers */ + +void +reset_mocks(void) +{ + FUNC_MOCK_RCOUNTER_SET(last_error_msg_get, VALIDATED_CALL); + FUNC_MOCK_RCOUNTER_SET(vsnprintf, VALIDATED_CALL); + FUNC_MOCK_RCOUNTER_SET(__xpg_strerror_r, VALIDATED_CALL); + FUNC_MOCK_RCOUNTER_SET(core_log_default_function, VALIDATED_CALL); + FUNC_MOCK_RCOUNTER_SET(custom_log_function, VALIDATED_CALL); +} + +void +test_no_space_for_strerror_r_helper(int core_message_length) +{ + reset_mocks(); + + /* set the expectations */ + Vsnprintf_.ret = core_message_length; + Log_function_.exp_level = CORE_LOG_LEVEL_ERROR; + Common.use_last_error_msg = false; + + core_log(CORE_LOG_LEVEL_ERROR, DUMMY_ERRNO1, FILE_NAME, LINE_NO, + FUNC_NAME, MSG_FORMAT); + + /* check the call counters */ + UT_ASSERTeq(RCOUNTER(last_error_msg_get), NOT_CALLED); + UT_ASSERTeq(RCOUNTER(vsnprintf), CALLED); + UT_ASSERTeq(RCOUNTER(__xpg_strerror_r), NOT_CALLED); + UT_ASSERTeq(RCOUNTER(core_log_default_function), CALLED); +} + +void +test_strerror_r_fail_helper(bool before_glibc_2_13) +{ + reset_mocks(); + + /* set the expectations */ + Vsnprintf_.ret = BASIC_MESSAGE_LEN; + Log_function_.exp_level = CORE_LOG_LEVEL_ERROR; + Common.use_last_error_msg = true; + Strerror_r.exp__buf = LAST_ERROR_MSG_MOCK + Vsnprintf_.ret; + Strerror_r.exp__buflen = CORE_LAST_ERROR_MSG_MAXPRINT - + (size_t)Vsnprintf_.ret; + Strerror_r.error = DUMMY_ERRNO2; + Strerror_r.before_glibc_2_13 = before_glibc_2_13; + + core_log(CORE_LOG_LEVEL_ERROR_LAST, DUMMY_ERRNO1, FILE_NAME, LINE_NO, + FUNC_NAME, MSG_FORMAT); + + /* check the call counters */ + UT_ASSERTeq(RCOUNTER(last_error_msg_get), CALLED); + UT_ASSERTeq(RCOUNTER(vsnprintf), CALLED); + UT_ASSERTeq(RCOUNTER(__xpg_strerror_r), CALLED); + UT_ASSERTeq(RCOUNTER(core_log_default_function), CALLED); +} + +void +test_log_function_call_helper(enum core_log_level level, + bool log_function_called) +{ + reset_mocks(); + + /* set the expectations */ + Vsnprintf_.ret = BASIC_MESSAGE_LEN; + Log_function_.exp_level = level; + Common.use_last_error_msg = (level == CORE_LOG_LEVEL_ERROR_LAST); + + core_log(level, NO_ERRNO, FILE_NAME, LINE_NO, FUNC_NAME, MSG_FORMAT); + + /* check the call counters */ + UT_ASSERTeq(RCOUNTER(last_error_msg_get), + Common.use_last_error_msg ? CALLED : NOT_CALLED); + UT_ASSERTeq(RCOUNTER(vsnprintf), CALLED); + UT_ASSERTeq(RCOUNTER(__xpg_strerror_r), NOT_CALLED); + UT_ASSERTeq(RCOUNTER(core_log_default_function), + log_function_called ? CALLED : NOT_CALLED); +} diff --git a/src/test/core_log/core_log_common.h b/src/test/core_log/core_log_common.h new file mode 100644 index 00000000000..28f0f854c5e --- /dev/null +++ b/src/test/core_log/core_log_common.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright 2024, Intel Corporation */ + +/* + * core_log.c -- definitions for mocks and helpers common for core_log(_no_func) + */ + +#include + +#include "unittest.h" + +#define NO_ARGS_CONSUMED 0 + +#define FILE_NAME "dummy.c" +#define LINE_NO 1234 +#define FUNC_NAME "dummy_func" +#define MSG_FORMAT ((char *)0x0458f044) +#define LAST_ERROR_MSG_MOCK ((char *)0x1a547e58) +#define DUMMY_ERRNO1 500 +#define DUMMY_ERRNO2 (DUMMY_ERRNO1 + 1) +#define BASIC_MESSAGE_LEN 131 + +#define VALIDATED_CALL 127 +#define NOT_CALLED VALIDATED_CALL +#define CALLED (VALIDATED_CALL + 1) +#define NOT_VALIDATED_CALL 0 + +extern struct common_ctx { + bool use_last_error_msg; +} Common; + +extern struct vsnprintf_ctx { + int ret; +} Vsnprintf_; + +extern struct strerror_r_ctx { + char *exp__buf; + size_t exp__buflen; + bool before_glibc_2_13; + int error; +} Strerror_r; + +extern struct log_function_ctx { + enum core_log_level exp_level; +} Log_function_; + +/* mocks */ + +FUNC_MOCK_EXTERN(last_error_msg_get); +FUNC_MOCK_EXTERN(vsnprintf); +FUNC_MOCK_EXTERN(__xpg_strerror_r); +FUNC_MOCK_EXTERN(core_log_default_function); +FUNC_MOCK_EXTERN(custom_log_function); + +/* helpers */ + +void reset_mocks(void); + +void test_no_space_for_strerror_r_helper(int core_message_length); + +void test_strerror_r_fail_helper(bool before_glibc_2_13); + +void test_log_function_call_helper(enum core_log_level level, + bool call_log_function); + +void custom_log_function(enum core_log_level level, const char *file_name, + unsigned line_no, const char *function_name, const char *message); diff --git a/src/test/core_log_default_function/.gitignore b/src/test/core_log_default_function/.gitignore new file mode 100644 index 00000000000..5c484fc37a8 --- /dev/null +++ b/src/test/core_log_default_function/.gitignore @@ -0,0 +1 @@ +core_log_default_function diff --git a/src/test/core_log_default_function/Makefile b/src/test/core_log_default_function/Makefile new file mode 100644 index 00000000000..6857d30cb99 --- /dev/null +++ b/src/test/core_log_default_function/Makefile @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation + +TARGET = core_log_default_function +OBJS = core_log_default_function.o + +BUILD_STATIC_DEBUG=n +BUILD_STATIC_NONDEBUG=n + +# required for proper mock integration +LIBPMEMCORE=internal-debug + +include ../Makefile.inc +LDFLAGS += $(call extract_funcs, core_log_default_function.c) diff --git a/src/test/core_log_default_function/TESTS.py b/src/test/core_log_default_function/TESTS.py new file mode 100755 index 00000000000..5121a713337 --- /dev/null +++ b/src/test/core_log_default_function/TESTS.py @@ -0,0 +1,44 @@ +#!../env.py +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation +# + + +import testframework as t +from testframework import granularity as g + + +@g.require_granularity(g.ANY) +@t.require_valgrind_disabled('pmemcheck') +# The 'debug' build is chosen arbitrarily to ensure these tests are run only +# once. No dynamic libraries are used nor .static_* builds are available. +@t.require_build('debug') +class CORE_LOG(t.BaseTest): + test_type = t.Short + + def run(self, ctx): + ctx.exec('core_log_default_function', self.test_case) + + +class TEST0(CORE_LOG): + test_case = 'test_default_function' + + +class TEST1(CORE_LOG): + test_case = 'test_default_function_bad_file_name' + + +class TEST2(CORE_LOG): + test_case = 'test_default_function_short_file_name' + + +class TEST3(CORE_LOG): + test_case = 'test_default_function_no_file_name' + + +class TEST4(CORE_LOG): + test_case = 'test_default_function_no_function_name' + + +class TEST5(CORE_LOG): + test_case = 'test_default_function_bad_timestamp' diff --git a/src/test/core_log_default_function/core_log_default_function.c b/src/test/core_log_default_function/core_log_default_function.c new file mode 100644 index 00000000000..f3d089b39f2 --- /dev/null +++ b/src/test/core_log_default_function/core_log_default_function.c @@ -0,0 +1,300 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* Copyright 2024, Intel Corporation */ + +/* + * core_log_default_function.c -- unit test for core_log_default_function + */ + +#undef _GNU_SOURCE +#include +#include +#include + +#include "unittest.h" +#include "log_internal.h" +#include "log_default.h" + +#define NO_ARGS_CONSUMED 0 + +#define MESSAGE_MOCK ((char *)0x24689753) +#define TIMESTAMP "DUMMY TIMESTAMP" +#define FILE_NAME "dummy.c" +#define FILE_NAME_W_PATH "dummy_path/dummy_path/" FILE_NAME +#define FILE_INFO_ERROR "[file info error]: " +#define FUNCTION_NAME "dummy_func()" +#define FILE_INFO FILE_NAME ": 123: " FUNCTION_NAME ": " +#define LINE_NO 1357 + +static const char log_level_names[CORE_LOG_LEVEL_MAX][9] = { + [CORE_LOG_LEVEL_HARK] = "*HARK* ", + [CORE_LOG_LEVEL_FATAL] = "*FATAL* ", + [CORE_LOG_LEVEL_ERROR] = "*ERROR* ", + [CORE_LOG_LEVEL_WARNING] = "*WARN* ", + [CORE_LOG_LEVEL_NOTICE] = "*NOTE* ", + [CORE_LOG_LEVEL_INFO] = "*INFO* ", + [CORE_LOG_LEVEL_DEBUG] = "*DEBUG* ", +}; + +static const int log_level_syslog_severity[] = { + [CORE_LOG_LEVEL_HARK] = LOG_NOTICE, + [CORE_LOG_LEVEL_FATAL] = LOG_CRIT, + [CORE_LOG_LEVEL_ERROR] = LOG_ERR, + [CORE_LOG_LEVEL_WARNING] = LOG_WARNING, + [CORE_LOG_LEVEL_NOTICE] = LOG_NOTICE, + [CORE_LOG_LEVEL_INFO] = LOG_INFO, + [CORE_LOG_LEVEL_DEBUG] = LOG_DEBUG, +}; + +static struct { + const char *exp_log_level_name; + const char *exp_file_info; +} Common; + +static char *Strchr_ret; + +FUNC_MOCK(strrchr, char *, const char *__s, int __c) +FUNC_MOCK_RUN_DEFAULT { + UT_ASSERTeq(__c, '/'); + return Strchr_ret; +} +FUNC_MOCK_END + +static bool Os_clock_gettime_force_error; + +FUNC_MOCK(clock_gettime, int, clockid_t __clock_id, struct timespec *__tp) +FUNC_MOCK_RUN_DEFAULT { + if (Os_clock_gettime_force_error) + return -1; + return _FUNC_REAL(clock_gettime)(__clock_id, __tp); +} +FUNC_MOCK_END + +static struct { + const char *exp_file_name; + int ret; +} Snprintf; + +FUNC_MOCK(snprintf, int, char *__restrict __s, size_t __maxlen, + const char *__restrict __format, ...) +/* file info */ + FUNC_MOCK_RUN(0) { + va_list arg; + va_start(arg, __format); + UT_ASSERTstreq(__format, "%s: %3u: %s: "); + char *file_name = va_arg(arg, char *); + UT_ASSERTstreq(file_name, Snprintf.exp_file_name); + unsigned line_no = va_arg(arg, unsigned); + UT_ASSERTeq(line_no, LINE_NO); + char *function_name = va_arg(arg, char *); + UT_ASSERTstreq(function_name, FUNCTION_NAME); + /* Can we access the whole given buffer (*__s) */ + *(__s + __maxlen - 1) = '\0'; + va_end(arg); + + if (Snprintf.ret != 0) + return Snprintf.ret; + UT_ASSERT(sizeof(FILE_INFO) <= __maxlen); + strncpy(__s, FILE_INFO, __maxlen); + return sizeof(FILE_INFO) - 1; + } +/* get time prefix */ + FUNC_MOCK_RUN(1) { + UT_ASSERTstreq(__format, "%s.%06ld "); + UT_ASSERT(sizeof(TIMESTAMP) <= __maxlen); + strncpy(__s, TIMESTAMP, __maxlen); + return sizeof(TIMESTAMP) - 1; + } +FUNC_MOCK_RUN_DEFAULT { + UT_FATAL("Unexpected #%d sprintf: %s", RCOUNTER(snprintf), __format); +} +FUNC_MOCK_END + +static struct { + int exp__pri; +} Syslog; + +FUNC_MOCK(syslog, void, int __pri, const char *__fmt, ...) +FUNC_MOCK_RUN_DEFAULT { + UT_ASSERTeq(__pri, Syslog.exp__pri); + UT_ASSERTstreq(__fmt, "%s%s%s"); + va_list arg; + va_start(arg, __fmt); + char *log_level_name = va_arg(arg, char *); + UT_ASSERTstreq(log_level_name, Common.exp_log_level_name); + char *file_info = va_arg(arg, char *); + UT_ASSERTstreq(file_info, Common.exp_file_info); + char *message = va_arg(arg, char *); + UT_ASSERTeq(message, MESSAGE_MOCK); + va_end(arg); +} +FUNC_MOCK_END + +static struct { + char *exp_times_stamp; +} Fprintf; + +FUNC_MOCK(fprintf, int, FILE *__restrict __stream, const char *__restrict __fmt, + ...) +FUNC_MOCK_RUN_DEFAULT { + UT_ASSERTeq(__stream, stderr); + UT_ASSERTstreq(__fmt, "%s[%ld] %s%s%s\n"); + va_list arg; + va_start(arg, __fmt); + char *times_tamp = va_arg(arg, char *); + UT_ASSERTstreq(times_tamp, Fprintf.exp_times_stamp); + va_arg(arg, int); /* skip syscall(SYS_gettid) */ + char *log_level_name = va_arg(arg, char *); + UT_ASSERTstreq(log_level_name, Common.exp_log_level_name); + char *file_info = va_arg(arg, char *); + UT_ASSERTstreq(file_info, Common.exp_file_info); + char *message = va_arg(arg, char *); + UT_ASSERTeq(message, MESSAGE_MOCK); + va_end(arg); + return 0; +} +FUNC_MOCK_END + +/* Tests' helpers */ +#define TEST_SETUP() core_log_set_threshold(CORE_LOG_THRESHOLD_AUX, \ + CORE_LOG_LEVEL_DEBUG) + +#define TEST_STEP_SETUP(_LEVEL, _FILE_NAME_SHORT) \ + do { \ + FUNC_MOCK_RCOUNTER_SET(snprintf, 0); \ + FUNC_MOCK_RCOUNTER_SET(syslog, 0); \ + FUNC_MOCK_RCOUNTER_SET(fprintf, 0); \ + Strchr_ret = "/"_FILE_NAME_SHORT; \ + Common.exp_log_level_name = log_level_names[_LEVEL]; \ + Common.exp_file_info = FILE_INFO; \ + Snprintf.exp_file_name = _FILE_NAME_SHORT; \ + Snprintf.ret = 0; \ + Syslog.exp__pri = log_level_syslog_severity[_LEVEL]; \ + Fprintf.exp_times_stamp = TIMESTAMP; \ + } while (0) + +#define TEST_STEP_CHECK(_SNPRINTF, _FPRINTF) \ + do { \ + UT_ASSERTeq(RCOUNTER(syslog), 1); \ + UT_ASSERTeq(RCOUNTER(snprintf), _SNPRINTF); \ + UT_ASSERTeq(RCOUNTER(fprintf), _FPRINTF); \ + } while (0) + +/* basic test with a normal message pass through */ +static int +test_default_function(const struct test_case *tc, int argc, char *argv[]) +{ + TEST_SETUP(); + for (enum core_log_level treshold = CORE_LOG_LEVEL_HARK; + treshold < CORE_LOG_LEVEL_MAX; treshold++) { + core_log_set_threshold(CORE_LOG_THRESHOLD_AUX, treshold); + for (enum core_log_level level = CORE_LOG_LEVEL_HARK; + level < CORE_LOG_LEVEL_MAX; level++) { + TEST_STEP_SETUP(level, FILE_NAME); + core_log_default_function(level, FILE_NAME_W_PATH, + LINE_NO, FUNCTION_NAME, MESSAGE_MOCK); + if (level == CORE_LOG_LEVEL_HARK || level > treshold) + TEST_STEP_CHECK(1, 0); + else + TEST_STEP_CHECK(2, 1); + } + } + + return NO_ARGS_CONSUMED; +} + +/* test to check that information about a bad file is printed */ +static int +test_default_function_bad_file_name(const struct test_case *tc, int argc, + char *argv[]) +{ + TEST_SETUP(); + TEST_STEP_SETUP(CORE_LOG_LEVEL_DEBUG, FILE_INFO_ERROR); + Snprintf.ret = -1; + Common.exp_file_info = FILE_INFO_ERROR; + core_log_default_function(CORE_LOG_LEVEL_DEBUG, FILE_NAME_W_PATH, + LINE_NO, FUNCTION_NAME, MESSAGE_MOCK); + TEST_STEP_CHECK(2, 1); + + return NO_ARGS_CONSUMED; +} + +/* test to check that short file name (w/o path) is properly printed */ +static int +test_default_function_short_file_name(const struct test_case *tc, int argc, + char *argv[]) +{ + core_log_set_threshold(CORE_LOG_THRESHOLD_AUX, CORE_LOG_LEVEL_DEBUG); + TEST_SETUP(); + TEST_STEP_SETUP(CORE_LOG_LEVEL_DEBUG, FILE_NAME); + Strchr_ret = NULL; + core_log_default_function(CORE_LOG_LEVEL_DEBUG, FILE_NAME, + LINE_NO, FUNCTION_NAME, MESSAGE_MOCK); + TEST_STEP_CHECK(2, 1); + + return NO_ARGS_CONSUMED; +} + +/* test to check no fileinfo when file_name is NULL */ +static int +test_default_function_no_file_name(const struct test_case *tc, int argc, + char *argv[]) +{ + TEST_SETUP(); + TEST_STEP_SETUP(CORE_LOG_LEVEL_DEBUG, ""); + FUNC_MOCK_RCOUNTER_SET(snprintf, 1); /* skip file_info snprintf() */ + Common.exp_file_info = ""; + core_log_default_function(CORE_LOG_LEVEL_DEBUG, NULL, + LINE_NO, FUNCTION_NAME, MESSAGE_MOCK); + TEST_STEP_CHECK(2, 1); + + return NO_ARGS_CONSUMED; +} + +/* test to check no fileinfo when file_name and function_name are NULL */ +static int +test_default_function_no_function_name(const struct test_case *tc, int argc, + char *argv[]) +{ + TEST_SETUP(); + TEST_STEP_SETUP(CORE_LOG_LEVEL_DEBUG, ""); + FUNC_MOCK_RCOUNTER_SET(snprintf, 1); /* skip file_info snprintf() */ + Common.exp_file_info = ""; + core_log_default_function(CORE_LOG_LEVEL_DEBUG, NULL, LINE_NO, NULL, + MESSAGE_MOCK); + TEST_STEP_CHECK(2, 1); + + return NO_ARGS_CONSUMED; +} + +/* test to check timestamp error */ +static int +test_default_function_bad_timestamp(const struct test_case *tc, int argc, + char *argv[]) +{ + TEST_SETUP(); + TEST_STEP_SETUP(CORE_LOG_LEVEL_DEBUG, FILE_NAME); + Os_clock_gettime_force_error = true; /* fail the file_info snprintf() */ + Fprintf.exp_times_stamp = "[time error] "; + core_log_default_function(CORE_LOG_LEVEL_DEBUG, FILE_NAME, LINE_NO, + FUNCTION_NAME, MESSAGE_MOCK); + TEST_STEP_CHECK(1, 1); + + return NO_ARGS_CONSUMED; +} + +static struct test_case test_cases[] = { + TEST_CASE(test_default_function), + TEST_CASE(test_default_function_bad_file_name), + TEST_CASE(test_default_function_short_file_name), + TEST_CASE(test_default_function_no_file_name), + TEST_CASE(test_default_function_no_function_name), + TEST_CASE(test_default_function_bad_timestamp), +}; + +int +main(int argc, char *argv[]) +{ + START(argc, argv, "core_log_default_function"); + TEST_CASE_PROCESS(argc, argv, test_cases, ARRAY_SIZE(test_cases)); + DONE(NULL); +} diff --git a/src/test/core_log_function_mt/.gitignore b/src/test/core_log_function_mt/.gitignore new file mode 100644 index 00000000000..b61c703b86f --- /dev/null +++ b/src/test/core_log_function_mt/.gitignore @@ -0,0 +1 @@ +core_log_function_mt diff --git a/src/test/core_log_function_mt/Makefile b/src/test/core_log_function_mt/Makefile new file mode 100644 index 00000000000..4029f83a0ac --- /dev/null +++ b/src/test/core_log_function_mt/Makefile @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation + +TARGET = core_log_function_mt +OBJS = core_log_function_mt.o + +BUILD_STATIC_DEBUG=n +BUILD_STATIC_NONDEBUG=n + +LIBPMEMCORE=y + +include ../Makefile.inc diff --git a/src/test/core_log_function_mt/TESTS.py b/src/test/core_log_function_mt/TESTS.py new file mode 100755 index 00000000000..56c93227f9f --- /dev/null +++ b/src/test/core_log_function_mt/TESTS.py @@ -0,0 +1,31 @@ +#!../env.py +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation +# + + +import testframework as t +from testframework import granularity as g + + +@g.require_granularity(g.ANY) +@t.require_valgrind_disabled('pmemcheck', 'memcheck') +# The 'nondebug' build is chosen arbitrarily to ensure these tests are run only +# once. No dynamic libraries are used nor .static_* builds are available. +@t.require_build('nondebug') +class TEST0(t.BaseTest): + test_type = t.Short + test_case = 'test_function_set_call' + + def run(self, ctx): + ctx.exec('core_log_function_mt', self.test_case) + + +@t.require_valgrind_enabled('helgrind') +class TEST1(TEST0): + pass + + +@t.require_valgrind_enabled('drd') +class TEST2(TEST0): + pass diff --git a/src/test/core_log_function_mt/core_log_function_mt.c b/src/test/core_log_function_mt/core_log_function_mt.c new file mode 100644 index 00000000000..0384907bde5 --- /dev/null +++ b/src/test/core_log_function_mt/core_log_function_mt.c @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* Copyright 2024, Intel Corporation */ + +/* + * core_log_function_mt.c -- unit test for core_log_set_function() and + * core_log() since both of them may write/read the log function pointer in + * parallel. + */ + +#include "unittest.h" +#include "log_internal.h" + +#define NO_ARGS_CONSUMED 0 + +#define THREADS_IN_GROUP 10 +#define THREADS_SET_MIN 0 +#define THREADS_SET_MAX (THREADS_SET_MIN + THREADS_IN_GROUP) +#define THREADS_CALL_MIN THREADS_SET_MAX +#define THREADS_CALL_MAX (THREADS_CALL_MIN + THREADS_IN_GROUP) +#define TOTAL_THREADS THREADS_CALL_MAX + +#define OP_REDO 4096 + +#define LOG_FUNC(FUNC_NAME) \ +static void \ +FUNC_NAME(enum core_log_level level, const char *file_name, unsigned line_no, \ + const char *function_name, const char *message) \ +{ \ + SUPPRESS_UNUSED(level, file_name, line_no, function_name, message); \ +} + +LOG_FUNC(log_func0) +LOG_FUNC(log_func1) +LOG_FUNC(log_func2) +LOG_FUNC(log_func3) +LOG_FUNC(log_func4) +LOG_FUNC(log_func5) +LOG_FUNC(log_func6) +LOG_FUNC(log_func7) +LOG_FUNC(log_func8) +LOG_FUNC(log_func9) + +static core_log_function *log_funcs[] = { + log_func0, + log_func1, + log_func2, + log_func3, + log_func4, + log_func5, + log_func6, + log_func7, + log_func8, + log_func9, +}; + +#define N_LOG_FUNCS ARRAY_SIZE(log_funcs) + +static os_mutex_t mutex; +static os_cond_t cond; +static unsigned threads_waiting; + +static void * +helper_set(void *arg) +{ + uint64_t idx = (uint64_t)arg; + os_mutex_lock(&mutex); + ++threads_waiting; + os_cond_wait(&cond, &mutex); + os_mutex_unlock(&mutex); + for (uint64_t i = 0; i < OP_REDO; ++i) { + core_log_function *log_func = + log_funcs[(i * (idx + 1)) % N_LOG_FUNCS]; + int ret = core_log_set_function(log_func); + UT_ASSERT(ret == 0 || ret == EAGAIN); + if (ret == EAGAIN) { + UT_OUT("ret == EAGAIN"); /* just out of curiosity */ + } + } + return NULL; +} + +static void * +helper_call(void *arg) +{ + SUPPRESS_UNUSED(arg); + + os_mutex_lock(&mutex); + ++threads_waiting; + os_cond_wait(&cond, &mutex); + os_mutex_unlock(&mutex); + for (uint64_t i = 0; i < OP_REDO; ++i) { + core_log(CORE_LOG_LEVEL_ERROR, NO_ERRNO, "", 0, "", ""); + } + return NULL; +} + +/* tests */ + +/* Run core_log_set_function() and core_log() in parallel. */ +static int +test_function_set_call(const struct test_case *tc, int argc, char *argv[]) +{ + os_thread_t threads[TOTAL_THREADS]; + + os_mutex_init(&mutex); + os_cond_init(&cond); + threads_waiting = 0; + + /* core_log_set_function() threads */ + for (uint64_t idx = THREADS_SET_MIN; idx < THREADS_SET_MAX; idx++) { + THREAD_CREATE(&threads[idx], 0, helper_set, (void *)idx); + } + + /* core_log() threads */ + for (uint64_t idx = THREADS_CALL_MIN; idx < THREADS_CALL_MAX; idx++) { + THREAD_CREATE(&threads[idx], 0, helper_call, NULL); + } + + do { + os_mutex_lock(&mutex); + if (threads_waiting == TOTAL_THREADS) { + os_cond_broadcast(&cond); + os_mutex_unlock(&mutex); + break; + } + os_mutex_unlock(&mutex); + } while (1); + + for (uint64_t idx = 0; idx < TOTAL_THREADS; idx++) { + void *retval; + THREAD_JOIN(&threads[idx], &retval); + } + + os_cond_destroy(&cond); + os_mutex_destroy(&mutex); + return NO_ARGS_CONSUMED; +} + +/* + * A Valgrind tool external to the test binary is assumed to monitor + * the execution and assess synchronisation correctness. + */ +static struct test_case test_cases[] = { + TEST_CASE(test_function_set_call), +}; + +#define NTESTS ARRAY_SIZE(test_cases) + +int +main(int argc, char *argv[]) +{ + START(argc, argv, "core_log_function_mt"); + TEST_CASE_PROCESS(argc, argv, test_cases, NTESTS); + DONE(NULL); +} diff --git a/src/test/core_log_internal/.gitignore b/src/test/core_log_internal/.gitignore new file mode 100644 index 00000000000..69ac3b5a5ea --- /dev/null +++ b/src/test/core_log_internal/.gitignore @@ -0,0 +1 @@ +core_log_internal diff --git a/src/test/core_log_internal/Makefile b/src/test/core_log_internal/Makefile new file mode 100644 index 00000000000..1fe8a911bd3 --- /dev/null +++ b/src/test/core_log_internal/Makefile @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation + +TARGET = core_log_internal +OBJS = core_log_internal.o + +BUILD_STATIC_DEBUG=n +BUILD_STATIC_NONDEBUG=n + +# 'internal' is required for proper mock integration +# 'nondebug' is required for proper execution of test_CORE_LOG_TRESHOLD_DEFAULT +# (use nondebug version of core/log.o) +LIBPMEMCORE=internal-nondebug + +include ../Makefile.inc +LDFLAGS += $(call extract_funcs, core_log_internal.c) diff --git a/src/test/core_log_internal/TESTS.py b/src/test/core_log_internal/TESTS.py new file mode 100755 index 00000000000..4db34d21f22 --- /dev/null +++ b/src/test/core_log_internal/TESTS.py @@ -0,0 +1,42 @@ +#!../env.py +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation +# + + +import testframework as t +from testframework import granularity as g + + +@g.require_granularity(g.ANY) +@t.require_build('nondebug') +@t.require_valgrind_disabled('pmemcheck') +class CORE_LOG(t.BaseTest): + test_type = t.Short + + def run(self, ctx): + ctx.exec('core_log_internal', self.test_case) + + +class TEST0(CORE_LOG): + test_case = 'test_CORE_LOG' + + +class TEST1(CORE_LOG): + test_case = 'test_CORE_LOG_ERROR_LAST' + + +class TEST2(CORE_LOG): + test_case = 'test_CORE_LOG_ERROR_W_ERRNO_LAST' + + +class TEST3(CORE_LOG): + test_case = 'test_CORE_LOG_W_ERRNO' + + +class TEST4(CORE_LOG): + test_case = 'test_CORE_LOG_TRESHOLD' + + +class TEST5(CORE_LOG): + test_case = 'test_CORE_LOG_TRESHOLD_DEFAULT' diff --git a/src/test/core_log_internal/core_log_internal.c b/src/test/core_log_internal/core_log_internal.c new file mode 100644 index 00000000000..1016480ad86 --- /dev/null +++ b/src/test/core_log_internal/core_log_internal.c @@ -0,0 +1,257 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* Copyright 2024, Intel Corporation */ + +/* + * core_log_internal.c -- unit test to CORE_LOG_... + */ + +#undef _GNU_SOURCE +#include +#include + +#include "unittest.h" +#include "log_internal.h" +#include "last_error_msg.h" + +#define NO_ARGS_CONSUMED 0 + +/* + * Prevent abort() from CORE_LOG_FATAL() + * Use mock_abort() instead. + * Use mock_abort() mock to monitor usage of abort() function + * inside CORE_LOG_FATAL(); + */ +#define abort() mock_abort() +void mock_abort(void); + +/* mock_abort() - mock for abort() function in CORE_LOG_FATAL() */ +static int Mock_abort_no_of_calls = 0; + +void +mock_abort(void) +{ + Mock_abort_no_of_calls++; +} + +/* core_log() - mock */ +static int Core_log_no_of_calls = 0; +static struct { + int initialized; + enum core_log_level level; + int errnum; + const char *file_name; + unsigned line_no; + const char *function_name; + const char *message_format; +} Core_log_context; + +FUNC_MOCK(core_log, void, enum core_log_level level, int errnum, + const char *file_name, unsigned line_no, const char *function_name, + const char *message_format, ...) +FUNC_MOCK_RUN_DEFAULT { + Core_log_no_of_calls++; + if (Core_log_context.initialized) { + UT_ASSERTeq(Core_log_context.level, level); + UT_ASSERTeq(Core_log_context.errnum, errnum); + UT_ASSERTeq(strcmp(Core_log_context.file_name, file_name), 0); + UT_ASSERTeq(Core_log_context.line_no, line_no); + UT_ASSERTeq(strcmp(Core_log_context.function_name, + function_name), 0); + UT_ASSERTeq(strcmp(Core_log_context.message_format, + message_format), 0); + } +} +FUNC_MOCK_END + +static enum core_log_level Core_log_default_threshold; + +#define CORE_LOG_UT_MESSAGE "Test message long 20Test message long 40" \ + "Test message long 60Test message long 80Test message long100" \ + "Test message long120Test message long140Test message long160" \ + "Test message long180Test message long200Test message long220" \ + "Test message long240Test message long260Test message long280" \ + "Test message long300Test message long320Test message long340" \ + "Test message long360Test message long380Test message long400 407" + +#define TEST_SETUP(MESSAGE_TO_TEST) \ + core_log_set_threshold(CORE_LOG_THRESHOLD, \ + Core_log_default_threshold); \ + Mock_abort_no_of_calls = 0; \ + Core_log_context.file_name = __FILE__; \ + Core_log_context.function_name = __func__; \ + Core_log_context.message_format = MESSAGE_TO_TEST; \ + Core_log_context.errnum = NO_ERRNO; \ + Core_log_context.initialized = 1 + +#define CORE_LOG_(LEVEL) CORE_LOG_##LEVEL +#define CORE_LOG_W_ERRNO_(LEVEL) CORE_LOG_##LEVEL##_W_ERRNO + +#define TEST_STEP_SETUP(LEVEL) \ + Core_log_context.level = CORE_LOG_LEVEL_##LEVEL; \ + Core_log_no_of_calls = 0; \ + Core_log_context.line_no = __LINE__ + +#define TEST_STEP(LEVEL, PASS) \ + TEST_STEP_SETUP(LEVEL); \ + CORE_LOG_(LEVEL)(CORE_LOG_UT_MESSAGE); \ + UT_ASSERTeq(Core_log_no_of_calls, PASS) + +#define TEST_STEP_W_ERRNO(LEVEL, ERRNUM) \ + TEST_STEP_SETUP(LEVEL); \ + Core_log_context.errnum = ERRNUM; \ + CORE_LOG_W_ERRNO_(LEVEL) (CORE_LOG_UT_MESSAGE) + +/* tests CORE_LOG_... with default threshold */ +static int +test_CORE_LOG(const struct test_case *tc, int argc, char *argv[]) +{ + TEST_SETUP(CORE_LOG_UT_MESSAGE); + TEST_STEP(HARK, 1); + UT_ASSERTeq(Mock_abort_no_of_calls, 0); + TEST_STEP(FATAL, 1); + UT_ASSERTeq(Mock_abort_no_of_calls, 1); + Mock_abort_no_of_calls = 0; + TEST_STEP(ERROR, 1); + TEST_STEP(WARNING, 1); + TEST_STEP(NOTICE, 0); + TEST_STEP(INFO, 0); + TEST_STEP(DEBUG, 0); + UT_ASSERTeq(Mock_abort_no_of_calls, 0); + return NO_ARGS_CONSUMED; +} + +/* Test for CORE_LOG_ERROR_LAST() */ +static int +test_CORE_LOG_ERROR_LAST(const struct test_case *tc, int argc, + char *argv[]) +{ + TEST_SETUP(CORE_LOG_UT_MESSAGE); + Core_log_no_of_calls = 0; + Core_log_context.level = CORE_LOG_LEVEL_ERROR_LAST; + Core_log_context.line_no = __LINE__ + 1; + CORE_LOG_ERROR_LAST(CORE_LOG_UT_MESSAGE); + UT_ASSERTeq(Core_log_no_of_calls, 1); + return NO_ARGS_CONSUMED; +} + +#define DUMMY_ERRNO 0xf00d + +/* Test for CORE_LOG_ERROR_W_ERRNO_LAST() w/ errno */ +static int +test_CORE_LOG_ERROR_W_ERRNO_LAST(const struct test_case *tc, int argc, \ + char *argv[]) +{ + TEST_SETUP(CORE_LOG_UT_MESSAGE ": "); + errno = DUMMY_ERRNO; + Core_log_no_of_calls = 0; + Core_log_context.errnum = DUMMY_ERRNO; + Core_log_context.level = CORE_LOG_LEVEL_ERROR_LAST; + Core_log_context.line_no = __LINE__ + 1; + CORE_LOG_ERROR_W_ERRNO_LAST(CORE_LOG_UT_MESSAGE); + UT_ASSERTeq(errno, DUMMY_ERRNO); + UT_ASSERTeq(Core_log_no_of_calls, 1); + errno = 0; + return NO_ARGS_CONSUMED; +} + +/* Test all macros that pass errno */ +static int +test_CORE_LOG_W_ERRNO(const struct test_case *tc, + int argc, char *argv[]) +{ + int errnum = DUMMY_ERRNO; + TEST_SETUP(CORE_LOG_UT_MESSAGE ": "); + Mock_abort_no_of_calls = 0; + errno = errnum; + TEST_STEP_W_ERRNO(FATAL, errnum); + UT_ASSERTeq(Mock_abort_no_of_calls, 1); + UT_ASSERTeq(errno, errnum); + errno = ++errnum; + TEST_STEP_W_ERRNO(ERROR, errnum); + UT_ASSERTeq(errno, errnum); + errno = ++errnum; + TEST_STEP_W_ERRNO(WARNING, errnum); + UT_ASSERTeq(errno, errnum); + UT_ASSERTeq(Mock_abort_no_of_calls, 1); + errno = 0; + return NO_ARGS_CONSUMED; +} + +#define CORE_LOG_TRESHOLD_STEP(LEVEL, ABORT_NO_OF_CALL, CORE_LOG_NO_OF_CALL) \ + do { \ + TEST_STEP_SETUP(LEVEL); \ + Mock_abort_no_of_calls = 0; \ + CORE_LOG_(LEVEL)(CORE_LOG_UT_MESSAGE); \ + UT_ASSERTeq(Mock_abort_no_of_calls, ABORT_NO_OF_CALL); \ + UT_ASSERTeq(Core_log_no_of_calls, CORE_LOG_NO_OF_CALL); \ + } while (0) + +#define CORE_LOG_TRESHOLD_STEP_ALL(HARK_PASS, FATAL_PASS, ERROR_PASS, \ + WARNING_PASS, NOTICE_PASS, INFO_PASS, DEBUG_PASS) \ + Mock_abort_no_of_calls = 0; \ + CORE_LOG_TRESHOLD_STEP(HARK, 0, HARK_PASS); \ + CORE_LOG_TRESHOLD_STEP(FATAL, 1, FATAL_PASS); \ + Mock_abort_no_of_calls = 0; \ + CORE_LOG_TRESHOLD_STEP(ERROR, 0, ERROR_PASS); \ + CORE_LOG_TRESHOLD_STEP(WARNING, 0, WARNING_PASS); \ + CORE_LOG_TRESHOLD_STEP(NOTICE, 0, NOTICE_PASS); \ + CORE_LOG_TRESHOLD_STEP(INFO, 0, INFO_PASS); \ + CORE_LOG_TRESHOLD_STEP(DEBUG, 0, DEBUG_PASS) + +/* Test all possible tresholds */ +static int +test_CORE_LOG_TRESHOLD(const struct test_case *tc, int argc, char *argv[]) +{ + TEST_SETUP(CORE_LOG_UT_MESSAGE); + Mock_abort_no_of_calls = 0; + core_log_set_threshold(CORE_LOG_THRESHOLD, CORE_LOG_LEVEL_HARK); + CORE_LOG_TRESHOLD_STEP_ALL(1, 0, 0, 0, 0, 0, 0); + core_log_set_threshold(CORE_LOG_THRESHOLD, CORE_LOG_LEVEL_FATAL); + CORE_LOG_TRESHOLD_STEP_ALL(1, 1, 0, 0, 0, 0, 0); + core_log_set_threshold(CORE_LOG_THRESHOLD, CORE_LOG_LEVEL_ERROR); + CORE_LOG_TRESHOLD_STEP_ALL(1, 1, 1, 0, 0, 0, 0); + core_log_set_threshold(CORE_LOG_THRESHOLD, CORE_LOG_LEVEL_WARNING); + CORE_LOG_TRESHOLD_STEP_ALL(1, 1, 1, 1, 0, 0, 0); + core_log_set_threshold(CORE_LOG_THRESHOLD, CORE_LOG_LEVEL_NOTICE); + CORE_LOG_TRESHOLD_STEP_ALL(1, 1, 1, 1, 1, 0, 0); + core_log_set_threshold(CORE_LOG_THRESHOLD, CORE_LOG_LEVEL_INFO); + CORE_LOG_TRESHOLD_STEP_ALL(1, 1, 1, 1, 1, 1, 0); + core_log_set_threshold(CORE_LOG_THRESHOLD, CORE_LOG_LEVEL_DEBUG); + CORE_LOG_TRESHOLD_STEP_ALL(1, 1, 1, 1, 1, 1, 1); + return NO_ARGS_CONSUMED; +} + +/* Validate the default threshold of the release build (no DEBUG set). */ +static int +test_CORE_LOG_TRESHOLD_DEFAULT(const struct test_case *tc, int argc, + char *argv[]) +{ + UT_ASSERTeq(Core_log_default_threshold, CORE_LOG_LEVEL_WARNING); + return NO_ARGS_CONSUMED; +} + +static struct test_case test_cases[] = { + TEST_CASE(test_CORE_LOG), + TEST_CASE(test_CORE_LOG_ERROR_LAST), + TEST_CASE(test_CORE_LOG_ERROR_W_ERRNO_LAST), + TEST_CASE(test_CORE_LOG_W_ERRNO), + TEST_CASE(test_CORE_LOG_TRESHOLD), + TEST_CASE(test_CORE_LOG_TRESHOLD_DEFAULT), +}; + +#define NTESTS ARRAY_SIZE(test_cases) + +/* Restore original abort() definition as it is defined in stdlib.h */ +#undef abort +extern void abort(void) __THROW __attribute__((__noreturn__)); + +int +main(int argc, char *argv[]) +{ + core_log_get_threshold(CORE_LOG_THRESHOLD, &Core_log_default_threshold); + core_log_set_function(CORE_LOG_USE_DEFAULT_FUNCTION); + + START(argc, argv, "core_log_internal"); + TEST_CASE_PROCESS(argc, argv, test_cases, NTESTS); + DONE(NULL); +} diff --git a/src/test/core_log_max/.gitignore b/src/test/core_log_max/.gitignore new file mode 100644 index 00000000000..94e5728aea0 --- /dev/null +++ b/src/test/core_log_max/.gitignore @@ -0,0 +1 @@ +core_log_max diff --git a/src/test/core_log_max/Makefile b/src/test/core_log_max/Makefile new file mode 100644 index 00000000000..d4196489148 --- /dev/null +++ b/src/test/core_log_max/Makefile @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation + +TARGET = core_log_max +OBJS = core_log_max.o call_all.o + +BUILD_STATIC_DEBUG=n +BUILD_STATIC_NONDEBUG=n + +LIBPMEMCORE=y +include ../Makefile.inc +LDFLAGS += $(call extract_funcs, core_log_max.c) diff --git a/src/test/core_log_max/TESTS.py b/src/test/core_log_max/TESTS.py new file mode 100755 index 00000000000..c09cc5fc4da --- /dev/null +++ b/src/test/core_log_max/TESTS.py @@ -0,0 +1,30 @@ +#!../env.py +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation +# + + +import testframework as t +from testframework import granularity as g + + +@g.require_granularity(g.ANY) +@t.require_build('nondebug') +@t.require_valgrind_disabled('pmemcheck') +class CORE_LOG(t.BaseTest): + test_type = t.Short + + def run(self, ctx): + ctx.exec('core_log_max', self.test_case) + + +class TEST0(CORE_LOG): + test_case = 'test_CORE_LOG_MAX_ERRNO_MSG' + + +class TEST1(CORE_LOG): + test_case = 'test_ERR_W_ERRNO' + + +class TEST2(CORE_LOG): + test_case = 'test_CORE_LOG' diff --git a/src/test/core_log_max/call_all.c b/src/test/core_log_max/call_all.c new file mode 100644 index 00000000000..e8978a97736 --- /dev/null +++ b/src/test/core_log_max/call_all.c @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* Copyright 2024, Intel Corporation */ + +#include +#include +#include + +#include "call_all.h" +#include "unittest.h" + +static char *_s = PATH; +static char _8s[8] = "Posuere"; +static unsigned _u = UINT_MAX; +static unsigned long _lu = ULONG_MAX; +static int _d = INT_MAX; +static long _ld = LONG_MAX; +static size_t _zu = SIZE_MAX; +static void *_p = (void *)UINT64_MAX; +static uintmax_t _ju = UINTMAX_MAX; + +/* + * Prevent abort() from CORE_LOG_FATAL() + */ +#define abort() do {; } while (0) + +#include "call_all.c.generated" diff --git a/src/test/core_log_max/call_all.c.generated b/src/test/core_log_max/call_all.c.generated new file mode 100644 index 00000000000..1ef0385ab22 --- /dev/null +++ b/src/test/core_log_max/call_all.c.generated @@ -0,0 +1,1248 @@ +/* + * This file is automatically generated by utils/call_stack_analysis/log_call_all_generate.py. + * Please do not modify manually. + */ +void +call_all_CORE_LOG_ERROR_LAST(void) +{ +} + +void +call_all_ERR_WO_ERRNO(void) +{ + // src/common/ctl.c + ERR_WO_ERRNO("read queries require non-NULL argument"); + // src/common/ctl.c + ERR_WO_ERRNO("write queries require non-NULL argument"); + // src/common/ctl.c + ERR_WO_ERRNO("invalid query"); + // src/common/ctl.c + ERR_WO_ERRNO("invalid query entry point %s", _s); + // src/common/ctl.c + ERR_WO_ERRNO("failed to parse query %s", _s); + // src/common/ctl.c + ERR_WO_ERRNO("Config file too large"); + // src/common/ctl.c + ERR_WO_ERRNO("invalid destination size %zu", _zu); + // src/common/file.c + ERR_WO_ERRNO("invalid (NULL) path"); + // src/common/file.c + ERR_WO_ERRNO("file size (%ld) too big to be represented in 64-bit signed integer", _ld); + // src/common/file.c + ERR_WO_ERRNO("size %zu smaller than %zu", _zu, _zu); + // src/common/file.c + ERR_WO_ERRNO("invalid size (%zu) for os_off_t", _zu); + // src/common/file.c + ERR_WO_ERRNO("stat \"%s\": negative size", _s); + // src/common/file.c + ERR_WO_ERRNO("size %zu smaller than %zu", _zu, _zu); + // src/common/mmap.c + ERR_WO_ERRNO("duplicated persistent memory range; presumably unmapped with munmap() instead of pmem_unmap(): addr %p len %zu", _p, _zu); + // src/common/mmap.c + ERR_WO_ERRNO("Cannot find DAX device region id"); + // src/common/mmap.c + ERR_WO_ERRNO("invalid munmap length, must be non-zero and page aligned"); + // src/common/mmap_posix.c + ERR_WO_ERRNO("end of address space reached"); + // src/common/pool_hdr.c + ERR_WO_ERRNO("invalid reserved values"); + // src/common/pool_hdr.c + ERR_WO_ERRNO("invalid machine value"); + // src/common/pool_hdr.c + ERR_WO_ERRNO("invalid data value"); + // src/common/pool_hdr.c + ERR_WO_ERRNO("invalid machine_class value"); + // src/common/pool_hdr.c + ERR_WO_ERRNO("invalid alignment_desc value"); + // src/common/pool_hdr.c + ERR_WO_ERRNO("unsafe to continue due to unknown incompat features: %#x", _u); + // src/common/pool_hdr.c + ERR_WO_ERRNO("switching to read-only mode due to unknown ro_compat features: %#x", _u); + // src/common/set.c + ERR_WO_ERRNO("unable to load part %s", _s); + // src/common/set.c + ERR_WO_ERRNO("failed to load parts from directory %s", _s); + // src/common/set.c + ERR_WO_ERRNO("Remote replicas are no longer supported. This functionality is deprecated."); + // src/common/set.c + ERR_WO_ERRNO("%s [%s:%d]", _s, _s, _d); + // src/common/set.c + ERR_WO_ERRNO("cannot load part files from directories"); + // src/common/set.c + ERR_WO_ERRNO("file size does not match config: %s, %zu != %zu", _s, _zu, _zu); + // src/common/set.c + ERR_WO_ERRNO("size must be zero for device dax"); + // src/common/set.c + ERR_WO_ERRNO("file is not a poolset file and its size (%zu) is smaller than %zu", _zu, _zu); + // src/common/set.c + ERR_WO_ERRNO("poolset file options (%u) do not match incompat feature flags (%#x)", _u, _u); + // src/common/set.c + ERR_WO_ERRNO("Non-empty file detected"); + // src/common/set.c + ERR_WO_ERRNO("invalid major version (0)"); + // src/common/set.c + ERR_WO_ERRNO("wrong pool type: \"%.8s\"", _8s); + // src/common/set.c + ERR_WO_ERRNO("pool version %d (library expects %d)", _d, _d); + // src/common/set.c + ERR_WO_ERRNO("Please run the pmdk-convert utility to upgrade the pool."); + // src/common/set.c + ERR_WO_ERRNO("invalid checksum of pool header"); + // src/common/set.c + ERR_WO_ERRNO("wrong architecture flags"); + // src/common/set.c + ERR_WO_ERRNO("wrong pool set UUID"); + // src/common/set.c + ERR_WO_ERRNO("wrong part UUID"); + // src/common/set.c + ERR_WO_ERRNO("incompatible pool format"); + // src/common/set.c + ERR_WO_ERRNO("incompatible feature flags"); + // src/common/set.c + ERR_WO_ERRNO("cannot extend pool by 0 bytes"); + // src/common/set.c + ERR_WO_ERRNO("extending the pool by appending parts with headers is not supported!"); + // src/common/set.c + ERR_WO_ERRNO("exceeded reservation size"); + // src/common/set.c + ERR_WO_ERRNO("unable to append a new part to the pool"); + // src/common/set.c + ERR_WO_ERRNO("cannot open the new part"); + // src/common/set.c + ERR_WO_ERRNO("cannot map the new part"); + // src/common/set.c + ERR_WO_ERRNO("new part cannot be mapped with MAP_SYNC"); + // src/common/set.c + ERR_WO_ERRNO("new part mapped with MAP_SYNC"); + // src/common/set.c + ERR_WO_ERRNO("file contains bad blocks -- '%s'", _s); + // src/common/set.c + ERR_WO_ERRNO("file %s already exists", _s); + // src/common/set.c + ERR_WO_ERRNO("the NOHDRS poolset option is not supported for local poolsets"); + // src/common/set.c + ERR_WO_ERRNO("pool attributes are not supported for poolsets without headers (with the NOHDRS option)"); + // src/common/set.c + ERR_WO_ERRNO("directory based pools are not supported for poolsets with headers (without SINGLEHDR option)"); + // src/common/set.c + ERR_WO_ERRNO("reservation pool size %zu smaller than %zu", _zu, _zu); + // src/common/set.c + ERR_WO_ERRNO("cannot create a new part in provided directories"); + // src/common/set.c + ERR_WO_ERRNO("pool set contains bad blocks and cannot be created, run 'pmempool create --clear-bad-blocks' utility to clear bad blocks and create a pool"); + // src/common/set.c + ERR_WO_ERRNO("net pool size %zu smaller than %zu", _zu, _zu); + // src/common/set.c + ERR_WO_ERRNO("replication not supported"); + // src/common/set.c + ERR_WO_ERRNO("unable to map at requested address %p", _p); + // src/common/set.c + ERR_WO_ERRNO("pool mapping failed - address space reservation too small"); + // src/common/set.c + ERR_WO_ERRNO("wrong replica UUID"); + // src/common/set.c + ERR_WO_ERRNO("device dax cannot be mapped privately"); + // src/common/set.c + ERR_WO_ERRNO("error: a bad block recovery file exists, run 'pmempool sync --bad-blocks' utility to try to recover the pool"); + // src/common/set.c + ERR_WO_ERRNO("pool set contains bad blocks and cannot be opened, run 'pmempool sync --bad-blocks' utility to try to recover the pool"); + // src/common/set.c + ERR_WO_ERRNO("device dax cannot be mapped privately"); + // src/common/set.c + ERR_WO_ERRNO("error: a bad block recovery file exists, run 'pmempool sync --bad-blocks' utility to try to recover the pool"); + // src/common/set.c + ERR_WO_ERRNO("pool set contains bad blocks and cannot be opened, run 'pmempool sync --bad-blocks' utility to try to recover the pool -- '%s'", _s); + // src/common/set.c + ERR_WO_ERRNO("util_poolset_parse failed -- '%s'", _s); + // src/common/set.c + ERR_WO_ERRNO("size autodetection is supported only for device dax"); + // src/common/set.c + ERR_WO_ERRNO("cannot mix directories and files in a set"); + // src/common/set.c + ERR_WO_ERRNO("cannot mix directories and files in a set"); + // src/common/set.c + ERR_WO_ERRNO("cannot resolve realpath of new directory"); + // src/common/set.c + ERR_WO_ERRNO("cannot use the same directory twice"); + // src/common/set.c + ERR_WO_ERRNO("replica #%u part %u %smapped with MAP_SYNC", _u, _u, _s); + // src/common/set.c + ERR_WO_ERRNO("replica #%u part %u header %smapped with MAP_SYNC", _u, _u, _s); + // src/common/set.c + ERR_WO_ERRNO("either all the parts must be Device DAX or none"); + // src/common/set.c + ERR_WO_ERRNO("Multiple DAX devices with alignment other than 4KB. Use the SINGLEHDR poolset option."); + // src/common/set.c + ERR_WO_ERRNO("both SINGLEHDR and NOHDR poolset options used at the same time"); + // src/common/set_badblocks.c + ERR_WO_ERRNO("clearing bad blocks in the pool file failed -- '%s'", _s); + // src/common/set_badblocks.c + ERR_WO_ERRNO("checking the pool file for bad blocks failed -- '%s'", _s); + // src/common/set_badblocks.c + ERR_WO_ERRNO("part file contains bad blocks -- '%s'", _s); + // src/common/shutdown_state.c + ERR_WO_ERRNO("cannot read uuid of %d", _d); + // src/common/shutdown_state.c + ERR_WO_ERRNO("an ADR failure was detected, the pool might be corrupted"); + // src/common/shutdown_state.c + ERR_WO_ERRNO("Cannot read unsafe shutdown count. For more information please check https://github.com/pmem/pmdk/issues/4207"); + // src/common/shutdown_state.c + ERR_WO_ERRNO("cannot read uuid of %d", _d); + // src/libpmem/libpmem.c + ERR_WO_ERRNO("libpmem major version mismatch (need %u, found %u)", _u, _u); + // src/libpmem/libpmem.c + ERR_WO_ERRNO("libpmem minor version mismatch (need %u, found %u)", _u, _u); + // src/libpmem/pmem.c + ERR_WO_ERRNO("invalid flag specified %x", _u); + // src/libpmem/pmem.c + ERR_WO_ERRNO("flag unsupported for Device DAX %x", _u); + // src/libpmem/pmem.c + ERR_WO_ERRNO("unable to read Device DAX size"); + // src/libpmem/pmem.c + ERR_WO_ERRNO("Device DAX length must be either 0 or the exact size of the device: %zu", _zu); + // src/libpmem/pmem.c + ERR_WO_ERRNO("invalid file length %zu", _zu); + // src/libpmem/pmem.c + ERR_WO_ERRNO("non-zero 'len' not allowed without PMEM_FILE_CREATE"); + // src/libpmem/pmem.c + ERR_WO_ERRNO("zero 'len' not allowed with PMEM_FILE_CREATE"); + // src/libpmem/pmem.c + ERR_WO_ERRNO("PMEM_FILE_TMPFILE not allowed without PMEM_FILE_CREATE"); + // src/libpmem/pmem.c + ERR_WO_ERRNO("stat %s: negative size", _s); + // src/libpmem/pmem.c + ERR_WO_ERRNO("invalid flags 0x%x", _u); + // src/libpmem/pmem.c + ERR_WO_ERRNO("invalid flags 0x%x", _u); + // src/libpmem/pmem.c + ERR_WO_ERRNO("invalid flags 0x%x", _u); + // src/libpmemobj/alloc_class.c + ERR_WO_ERRNO("unable to register allocation class"); + // src/libpmemobj/heap.c + ERR_WO_ERRNO("lost runtime tracking info of %u run due to OOM", _u); + // src/libpmemobj/heap.c + ERR_WO_ERRNO("lost runtime tracking info of %u run due to OOM", _u); + // src/libpmemobj/heap.c + ERR_WO_ERRNO("at least one automatic arena must exist"); + // src/libpmemobj/heap.c + ERR_WO_ERRNO("mapped region smaller than the heap size"); + // src/libpmemobj/heap.c + ERR_WO_ERRNO("heap: invalid header's checksum"); + // src/libpmemobj/heap.c + ERR_WO_ERRNO("heap: invalid signature"); + // src/libpmemobj/heap.c + ERR_WO_ERRNO("heap: invalid zone size"); + // src/libpmemobj/heap.c + ERR_WO_ERRNO("heap: invalid chunk type"); + // src/libpmemobj/heap.c + ERR_WO_ERRNO("heap: unknown chunk type"); + // src/libpmemobj/heap.c + ERR_WO_ERRNO("heap: invalid chunk flags"); + // src/libpmemobj/heap.c + ERR_WO_ERRNO("heap: invalid zone magic"); + // src/libpmemobj/heap.c + ERR_WO_ERRNO("heap: chunk sizes mismatch"); + // src/libpmemobj/heap.c + ERR_WO_ERRNO("heap: invalid heap size"); + // src/libpmemobj/heap.c + ERR_WO_ERRNO("lost runtime tracking info of %u run due to OOM", _u); + // src/libpmemobj/libpmemobj.c + ERR_WO_ERRNO("libpmemobj major version mismatch (need %u, found %u)", _u, _u); + // src/libpmemobj/libpmemobj.c + ERR_WO_ERRNO("libpmemobj minor version mismatch (need %u, found %u)", _u, _u); + // src/libpmemobj/memops.c + ERR_WO_ERRNO("Capacity insufficient"); + // src/libpmemobj/memops.c + ERR_WO_ERRNO("Buffer currently used"); + // src/libpmemobj/memops.c + ERR_WO_ERRNO("no extend function present"); + // src/libpmemobj/obj.c + ERR_WO_ERRNO("%s variable must be a positive integer", _s); + // src/libpmemobj/obj.c + ERR_WO_ERRNO("Layout too long"); + // src/libpmemobj/obj.c + ERR_WO_ERRNO("initialization of replica #%u failed", _u); + // src/libpmemobj/obj.c + ERR_WO_ERRNO("pool initialization failed"); + // src/libpmemobj/obj.c + ERR_WO_ERRNO("invalid run_id %lu", _lu); + // src/libpmemobj/obj.c + ERR_WO_ERRNO("read-only mode is not supported"); + // src/libpmemobj/obj.c + ERR_WO_ERRNO("initialization of replica #%u failed", _u); + // src/libpmemobj/obj.c + ERR_WO_ERRNO("inconsistent replica #%u", _u); + // src/libpmemobj/obj.c + ERR_WO_ERRNO("pool initialization failed"); + // src/libpmemobj/obj.c + ERR_WO_ERRNO("critnib_remove for pools_ht"); + // src/libpmemobj/obj.c + ERR_WO_ERRNO("critnib_remove for pools_tree"); + // src/libpmemobj/obj.c + ERR_WO_ERRNO("requested size too large"); + // src/libpmemobj/obj.c + ERR_WO_ERRNO("allocation with size 0"); + // src/libpmemobj/obj.c + ERR_WO_ERRNO("allocation with size 0"); + // src/libpmemobj/obj.c + ERR_WO_ERRNO("unknown flags 0x%lx", _lu); + // src/libpmemobj/obj.c + ERR_WO_ERRNO("allocation with size 0"); + // src/libpmemobj/obj.c + ERR_WO_ERRNO("requested size too large"); + // src/libpmemobj/obj.c + ERR_WO_ERRNO("invalid flags 0x%x", _u); + // src/libpmemobj/obj.c + ERR_WO_ERRNO("invalid flags 0x%x", _u); + // src/libpmemobj/obj.c + ERR_WO_ERRNO("requested size too large"); + // src/libpmemobj/obj.c + ERR_WO_ERRNO("requested size cannot equals zero"); + // src/libpmemobj/obj.c + ERR_WO_ERRNO("unknown flags 0x%lx", _lu); + // src/libpmemobj/obj.c + ERR_WO_ERRNO("Not all PMEMoids belong to the provided pool"); + // src/libpmemobj/obj.c + ERR_WO_ERRNO("requested size too large"); + // src/libpmemobj/obj.c + ERR_WO_ERRNO("invalid checksum of pool descriptor"); + // src/libpmemobj/obj.c + ERR_WO_ERRNO("wrong layout (\"%s\"), pool created with layout \"%s\"", _s, _s); + // src/libpmemobj/obj.c + ERR_WO_ERRNO("unaligned heap: off %lu", _lu); + // src/libpmemobj/palloc.c + ERR_WO_ERRNO("no allocation class for size %lu bytes", _lu); + // src/libpmemobj/palloc.c + ERR_WO_ERRNO("allocation class not suitable for size %lu bytes", _lu); + // src/libpmemobj/palloc.c + ERR_WO_ERRNO("invalid operation or heap corruption"); + // src/libpmemobj/pmalloc.c + ERR_WO_ERRNO("unit size must be evenly divisible by alignment"); + // src/libpmemobj/pmalloc.c + ERR_WO_ERRNO("alignment cannot be larger than 2 megabytes"); + // src/libpmemobj/pmalloc.c + ERR_WO_ERRNO("invalid header type"); + // src/libpmemobj/pmalloc.c + ERR_WO_ERRNO("no available free allocation class identifier"); + // src/libpmemobj/pmalloc.c + ERR_WO_ERRNO("class id outside of the allowed range"); + // src/libpmemobj/pmalloc.c + ERR_WO_ERRNO("attempted to overwrite an allocation class"); + // src/libpmemobj/pmalloc.c + ERR_WO_ERRNO("invalid header type"); + // src/libpmemobj/pmalloc.c + ERR_WO_ERRNO("class id outside of the allowed range"); + // src/libpmemobj/pmalloc.c + ERR_WO_ERRNO("class with the given id does not exist"); + // src/libpmemobj/pmalloc.c + ERR_WO_ERRNO("incorrect size for extend, must be larger than %lu", _lu); + // src/libpmemobj/pmalloc.c + ERR_WO_ERRNO("incorrect grow size, must be 0 or larger than %lu", _lu); + // src/libpmemobj/pmalloc.c + ERR_WO_ERRNO("cannot change max arena number"); + // src/libpmemobj/pmalloc.c + ERR_WO_ERRNO("arena id outside of the allowed range: <1,%u>", _u); + // src/libpmemobj/pmalloc.c + ERR_WO_ERRNO("arena id outside of the allowed range: <1,%u>", _u); + // src/libpmemobj/pmalloc.c + ERR_WO_ERRNO("incorrect arena state, must be 0 or 1"); + // src/libpmemobj/pmalloc.c + ERR_WO_ERRNO("arena id outside of the allowed range: <1,%u>", _u); + // src/libpmemobj/pmalloc.c + ERR_WO_ERRNO("arena id outside of the allowed range: <1,%u>", _u); + // src/libpmemobj/pmalloc.c + ERR_WO_ERRNO("invalid arena assignment type"); + // src/libpmemobj/pmalloc.c + ERR_WO_ERRNO("number of default arenas can't be 0"); + // src/libpmemobj/stats.c + ERR_WO_ERRNO("invalid enable type"); + // src/libpmemobj/sync.c + ERR_WO_ERRNO("error initializing lock"); + // src/libpmemobj/sync.c + ERR_WO_ERRNO("error setting lock runid"); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("snapshot size too large"); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("object outside of heap"); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("out of memory"); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("object outside of pool"); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("unknown flags 0x%lx", _lu); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("object outside of pool"); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("invalid pool uuid"); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("unknown flags 0x%lx", _lu); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("invalid pool uuid"); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("allocation with size 0"); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("allocation with size 0"); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("allocation with size 0"); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("unknown flags 0x%lx", _lu); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("unknown flags 0x%lx", _lu); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("cannot duplicate NULL string"); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("unknown flags 0x%lx", _lu); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("cannot duplicate NULL string"); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("unknown flags 0x%lx", _lu); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("invalid pool uuid"); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("unknown flags 0x%lx", _lu); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("unknown flags 0x%lx", _lu); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("invalid cache size, must be between 0 and max alloc size"); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("tx.cache.threshold parameter is deprecated"); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("tx.cache.threshold parameter is deprecated"); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("Unrecognized lock type"); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("Unrecognized lock type"); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("requested size too large"); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("out of memory"); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("requested size too large"); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("pmemobj_tx_free failed"); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("pmemobj_tx_free failed"); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("Buffer from a different pool"); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("nested transaction for different pool"); + // src/libpmemobj/tx.c + ERR_WO_ERRNO("unknown flags 0x%lx", _lu); + // src/libpmemobj/ulog.c + ERR_WO_ERRNO("cannot auto reserve next ulog"); + // src/tools/pmempool/output.c + ERR_WO_ERRNO("snprintf for incompat features: %d", _d); +} + +void +call_all_CORE_LOG_WARNING(void) +{ + // src/common/file.c + CORE_LOG_WARNING("requested size of write goes beyond the file length, %zu > %zu", _zu, _zu); + // src/common/file.c + CORE_LOG_WARNING("requested size of write goes beyond the file length, %zu > %zu", _zu, _zu); + // src/common/file.c + CORE_LOG_WARNING("requested size of read goes beyond the file length, %zu > %zu", _zu, _zu); + // src/common/mmap.c + CORE_LOG_WARNING("Invalid PMEM_MMAP_HINT"); + // src/common/mmap.c + CORE_LOG_WARNING("No /proc, PMEM_MMAP_HINT ignored"); + // src/common/set.c + CORE_LOG_WARNING("usable space mapping failed - part #%d - retrying", _d); + // src/common/set.c + CORE_LOG_WARNING("usable space mapping failed - part #%d - retrying", _d); + // src/common/set.c + CORE_LOG_WARNING("Possible silent data corruption. The unsafe shutdown detection (SDS) is not supported in the pool: %s", _s); + // src/common/set.c + CORE_LOG_WARNING("pool set contains bad blocks, ignoring"); + // src/common/set.c + CORE_LOG_WARNING("cannot open the part -- \"%s\"", _s); + // src/common/set.c + CORE_LOG_WARNING("pool set contains bad blocks, ignoring -- '%s'", _s); + // src/common/set.c + CORE_LOG_WARNING("file permissions changed during pool initialization, file: %s (%o)", _s, _u); + // src/common/shutdown_state.c + CORE_LOG_WARNING("incorrect checksum - SDS will be reinitialized"); + // src/common/shutdown_state.c + CORE_LOG_WARNING("the pool was not closed - SDS will be reinitialized"); + // src/common/shutdown_state.c + CORE_LOG_WARNING("an ADR failure was detected but the pool was closed - SDS will be reinitialized"); + // src/libpmemobj/heap.c + CORE_LOG_WARNING("failed to allocate memory block runtime tracking info"); + // src/libpmemobj/heap.c + CORE_LOG_WARNING("failed to allocate memory block runtime tracking info"); + // src/libpmemobj/memops.c + CORE_LOG_WARNING("out of memory - unable to track entries"); + // src/libpmemobj/palloc.c + CORE_LOG_WARNING("unable to track runtime chunk state"); +} + +void +call_all_CORE_LOG_ERROR(void) +{ + // src/common/bad_blocks.c + CORE_LOG_ERROR("pmem2_badblock_context_new failed -- %s", _s); + // src/common/bad_blocks.c + CORE_LOG_ERROR("pmem2_badblock_clear -- %s", _s); + // src/common/bad_blocks.c + CORE_LOG_ERROR("pmem2_badblock_context_new failed -- %s", _s); + // src/common/bad_blocks.c + CORE_LOG_ERROR("pmem2_badblock_clear -- %s", _s); + // src/common/bad_blocks.c + CORE_LOG_ERROR("counting bad blocks failed -- '%s'", _s); + // src/common/bad_blocks.c + CORE_LOG_ERROR("pool file '%s' contains %li bad block(s)", _s, _d); + // src/common/ctl.c + CORE_LOG_ERROR("Invalid arguments"); + // src/common/file.c + CORE_LOG_ERROR("cannot determine file length \"%s\"", _s); + // src/common/file.c + CORE_LOG_ERROR("failed to map entire file \"%s\"", _s); + // src/common/file.c + CORE_LOG_ERROR("cannot determine file length \"%s\"", _s); + // src/common/file.c + CORE_LOG_ERROR("offset beyond file length, %ju > %ju", _ju, _ju); + // src/common/file.c + CORE_LOG_ERROR("failed to map entire file \"%s\"", _s); + // src/common/file.c + CORE_LOG_ERROR("failed to open file \"%s\"", _s); + // src/common/file.c + CORE_LOG_ERROR("cannot determine file length \"%s\"", _s); + // src/common/file.c + CORE_LOG_ERROR("failed to map entire file \"%s\"", _s); + // src/common/file.c + CORE_LOG_ERROR("failed to open file \"%s\"", _s); + // src/common/file.c + CORE_LOG_ERROR("cannot determine file length \"%s\"", _s); + // src/common/file.c + CORE_LOG_ERROR("failed to map entire file \"%s\"", _s); + // src/common/file.c + CORE_LOG_ERROR("failed to open file \"%s\"", _s); + // src/common/file_posix.c + CORE_LOG_ERROR("Cannot open file %s", _s); + // src/common/mmap.c + CORE_LOG_ERROR("cannot find a contiguous region of given size"); + // src/common/os_deep_linux.c + CORE_LOG_ERROR("pmem_msync(%p, %lu)", _p, _lu); + // src/common/os_deep_linux.c + CORE_LOG_ERROR("deep_flush not supported"); + // src/common/os_deep_linux.c + CORE_LOG_ERROR("invalid dax_region id %u", _u); + // src/common/os_deep_linux.c + CORE_LOG_ERROR("pmem2_deep_flush_write(%u)", _u); + // src/common/os_deep_linux.c + CORE_LOG_ERROR("pmem_msync(%p, %lu)", _p, _lu); + // src/common/os_deep_linux.c + CORE_LOG_ERROR("deep_flush not supported"); + // src/common/os_deep_linux.c + CORE_LOG_ERROR("cannot write to deep_flush in region %u", _u); + // src/common/set.c + CORE_LOG_ERROR("cannot read size of file (%s) in a poolset directory", _s); + // src/common/set.c + CORE_LOG_ERROR("failed to create file: %s", _s); + // src/common/set.c + CORE_LOG_ERROR("failed to open file: %s", _s); + // src/common/set.c + CORE_LOG_ERROR("cannot find a contiguous region of given size"); + // src/common/set.c + CORE_LOG_ERROR("cannot find a contiguous region of given size"); + // src/common/set.c + CORE_LOG_ERROR("pool mapping failed - replica #%u part #0", _u); + // src/common/set.c + CORE_LOG_ERROR("usable space mapping failed - part #%d", _d); + // src/common/set.c + CORE_LOG_ERROR("header mapping failed - part #%d", _d); + // src/common/set.c + CORE_LOG_ERROR("header creation failed - part #%d", _d); + // src/common/set.c + CORE_LOG_ERROR("replica #%u map failed", _u); + // src/common/set.c + CORE_LOG_ERROR("replica #%u headers initialization failed", _u); + // src/common/set.c + CORE_LOG_ERROR("cannot create pool set -- '%s'", _s); + // src/common/set.c + CORE_LOG_ERROR("failed to check pool set for bad blocks -- '%s'", _s); + // src/common/set.c + CORE_LOG_ERROR("cannot generate pool set UUID"); + // src/common/set.c + CORE_LOG_ERROR("cannot generate pool set part UUID"); + // src/common/set.c + CORE_LOG_ERROR("replica #%u creation failed", _u); + // src/common/set.c + CORE_LOG_ERROR("cannot find a contiguous region of given size"); + // src/common/set.c + CORE_LOG_ERROR("pool mapping failed - replica #%u part #0", _u); + // src/common/set.c + CORE_LOG_ERROR("header mapping failed - part #%d", _d); + // src/common/set.c + CORE_LOG_ERROR("usable space mapping failed - part #%d", _d); + // src/common/set.c + CORE_LOG_ERROR("header check failed - part #%d", _d); + // src/common/set.c + CORE_LOG_ERROR("ADR failure detected"); + // src/common/set.c + CORE_LOG_ERROR("an error occurred when checking whether recovery file exists."); + // src/common/set.c + CORE_LOG_ERROR("failed to check pool set for bad blocks"); + // src/common/set.c + CORE_LOG_ERROR("replica #%u open failed", _u); + // src/common/set.c + CORE_LOG_ERROR("header mapping failed -- \"%s\"", _s); + // src/common/set.c + CORE_LOG_ERROR("cannot open pool set -- '%s'", _s); + // src/common/set.c + CORE_LOG_ERROR("reading compat features failed"); + // src/common/set.c + CORE_LOG_ERROR("an error occurred when checking whether recovery file exists."); + // src/common/set.c + CORE_LOG_ERROR("failed to check pool set for bad blocks -- '%s'", _s); + // src/common/set.c + CORE_LOG_ERROR("replica #%u open failed", _u); + // src/common/set.c + CORE_LOG_ERROR("os_part_deep_common(%p, %p, %lu)", _p, _p, _lu); + // src/common/set.c + CORE_LOG_ERROR("replica open failed: replica %u", _u); + // src/common/set_badblocks.c + CORE_LOG_ERROR("allocating name of bad block recovery file failed"); + // src/common/set_badblocks.c + CORE_LOG_ERROR("%i pool file(s) contain bad blocks", _d); + // src/common/shutdown_state.c + CORE_LOG_ERROR("cannot read unsafe shutdown count for %d", _d); + // src/common/uuid.c + CORE_LOG_ERROR("invalid buffer for uuid string"); + // src/common/uuid.c + CORE_LOG_ERROR("invalid uuid structure"); + // src/common/uuid.c + CORE_LOG_ERROR("snprintf(uuid): %d", _d); + // src/common/uuid.c + CORE_LOG_ERROR("invalid uuid string"); + // src/common/uuid.c + CORE_LOG_ERROR("invalid uuid string"); + // src/common/uuid.c + CORE_LOG_ERROR("sscanf(uuid)"); + // src/common/uuid_linux.c + CORE_LOG_ERROR("open(uuid)"); + // src/common/uuid_linux.c + CORE_LOG_ERROR("read(uuid)"); + // src/core/util_posix.c + CORE_LOG_ERROR("stat failed for %s", _s); + // src/core/util_posix.c + CORE_LOG_ERROR("stat failed for %s", _s); + // src/libpmem/pmem.c + CORE_LOG_ERROR("failed to create temporary file at \"%s\"", _s); + // src/libpmem/pmem_posix.c + CORE_LOG_ERROR("can't track mapped region"); + // src/libpmemobj/heap.c + CORE_LOG_ERROR("cannot decrease max number of arenas"); + // src/libpmemobj/lane.c + CORE_LOG_ERROR("lane %lu internal redo failed: %d", _lu, _d); + // src/libpmemobj/list.c + CORE_LOG_ERROR("pmemobj_mutex_lock failed"); + // src/libpmemobj/list.c + CORE_LOG_ERROR("pmemobj_mutex_lock failed"); + // src/libpmemobj/list.c + CORE_LOG_ERROR("pmemobj_mutex_lock failed"); + // src/libpmemobj/list.c + CORE_LOG_ERROR("pmemobj_mutex_lock failed"); + // src/libpmemobj/list.c + CORE_LOG_ERROR("list_mutexes_lock failed"); + // src/libpmemobj/obj.c + CORE_LOG_ERROR("unable to parse config stored in %s environment variable", _s); + // src/libpmemobj/obj.c + CORE_LOG_ERROR("cannot create pool or pool set"); + // src/libpmemobj/obj.c + CORE_LOG_ERROR("creation of pool descriptor failed"); + // src/libpmemobj/obj.c + CORE_LOG_ERROR("unable to parse config stored in %s file (from %s environment variable)", _s, _s); + // src/libpmemobj/obj.c + CORE_LOG_ERROR("lane_check"); + // src/libpmemobj/obj.c + CORE_LOG_ERROR("heap_check"); + // src/libpmemobj/obj.c + CORE_LOG_ERROR("cannot open pool or pool set"); + // src/libpmemobj/obj.c + CORE_LOG_ERROR("descriptor check of replica #%u failed", _u); + // src/libpmemobj/obj.c + CORE_LOG_ERROR("obj_realloc_root failed"); + // src/libpmemobj/obj.c + CORE_LOG_ERROR("ctl_new"); + // src/tools/pmempool/common.c + CORE_LOG_ERROR("cannot open pool set -- '%s'", _s); +} + +void +call_all_CORE_LOG_FATAL(void) +{ + // src/common/set.c + CORE_LOG_FATAL("munmap: %s", _s); + // src/common/set.c + CORE_LOG_FATAL("cannot add a new part to the replica info"); + // src/common/util_pmem.h + CORE_LOG_FATAL("pmem_msync"); + // src/core/alloc.c + CORE_LOG_FATAL("unknown allocation type"); + // src/core/core_assert.h + CORE_LOG_FATAL("assertion failure: %s", _s); + // src/core/core_assert.h + CORE_LOG_FATAL("assertion failure: %s (%s = %s)", _s, _s, _s); + // src/core/last_error_msg.c + CORE_LOG_FATAL("os_thread_key_create"); + // src/core/last_error_msg.c + CORE_LOG_FATAL("os_tls_set"); + // src/core/out.c + CORE_LOG_FATAL("Cannot set log threshold"); + // src/core/out.c + CORE_LOG_FATAL("Cannot set legacy log function"); + // src/core/sys_util.h + CORE_LOG_FATAL("os_rwlock_init"); + // src/core/sys_util.h + CORE_LOG_FATAL("os_rwlock_rdlock"); + // src/core/sys_util.h + CORE_LOG_FATAL("os_rwlock_wrlock"); + // src/core/sys_util.h + CORE_LOG_FATAL("os_rwlock_unlock"); + // src/core/sys_util.h + CORE_LOG_FATAL("os_rwlock_destroy"); + // src/core/sys_util.h + CORE_LOG_FATAL("os_spin_destroy"); + // src/core/sys_util.h + CORE_LOG_FATAL("os_spin_lock"); + // src/core/sys_util.h + CORE_LOG_FATAL("os_spin_unlock"); + // src/core/sys_util.h + CORE_LOG_FATAL("os_semaphore_init"); + // src/core/sys_util.h + CORE_LOG_FATAL("os_semaphore_destroy"); + // src/core/sys_util.h + CORE_LOG_FATAL("os_semaphore_wait"); + // src/core/sys_util.h + CORE_LOG_FATAL("os_semaphore_trywait"); + // src/core/sys_util.h + CORE_LOG_FATAL("os_semaphore_post"); + // src/core/sys_util.h + CORE_LOG_FATAL("os_cond_init"); + // src/core/sys_util.h + CORE_LOG_FATAL("os_cond_destroy"); + // src/core/sys_util.h + CORE_LOG_FATAL("os_mutex_init"); + // src/core/sys_util.h + CORE_LOG_FATAL("os_mutex_destroy"); + // src/core/sys_util.h + CORE_LOG_FATAL("os_mutex_lock"); + // src/core/sys_util.h + CORE_LOG_FATAL("os_mutex_trylock"); + // src/core/sys_util.h + CORE_LOG_FATAL("os_mutex_unlock"); + // src/libpmem/pmem.c + CORE_LOG_FATAL("util_bool_compare_and_swap32"); + // src/libpmem/pmem.c + CORE_LOG_FATAL("invalid flush function address"); + // src/libpmemobj/lane.c + CORE_LOG_FATAL("os_tls_key_create"); + // src/libpmemobj/lane.c + CORE_LOG_FATAL("critnib_new"); + // src/libpmemobj/lane.c + CORE_LOG_FATAL("Malloc"); + // src/libpmemobj/lane.c + CORE_LOG_FATAL("critnib_insert"); + // src/libpmemobj/lane.c + CORE_LOG_FATAL("lane_release"); + // src/libpmemobj/lane.c + CORE_LOG_FATAL("util_bool_compare_and_swap64"); + // src/libpmemobj/lane.c + CORE_LOG_FATAL("os_tls_set"); + // src/libpmemobj/memblock.c + CORE_LOG_FATAL("failed to initialize valgrind state"); + // src/libpmemobj/memblock.c + CORE_LOG_FATAL("failed to initialize valgrind state"); + // src/libpmemobj/memblock.c + CORE_LOG_FATAL("possible zone chunks metadata corruption"); + // src/libpmemobj/obj.c + CORE_LOG_FATAL("critnib_new for pools_ht"); + // src/libpmemobj/obj.c + CORE_LOG_FATAL("critnib_new for pools_tree"); + // src/libpmemobj/obj.c + CORE_LOG_FATAL("error: %s", _s); + // src/libpmemobj/obj.c + CORE_LOG_FATAL("pmem_msync"); + // src/libpmemobj/palloc.c + CORE_LOG_FATAL("duplicate runtime chunk state, possible double free"); + // src/libpmemobj/sync.h + CORE_LOG_FATAL("pmemobj_mutex_unlock"); + // src/libpmemobj/sync.h + CORE_LOG_FATAL("pmemobj_mutex_lock"); + // src/libpmemobj/tx.c + CORE_LOG_FATAL("pmemobj_tx_end called without pmemobj_tx_commit"); + // src/libpmemobj/tx.c + CORE_LOG_FATAL("pmemobj_tx_end called without pmemobj_tx_begin"); + // src/libpmemobj/tx.c + CORE_LOG_FATAL("%s called outside of transaction", _s); + // src/libpmemobj/tx.c + CORE_LOG_FATAL("Malloc"); + // src/libpmemobj/tx.c + CORE_LOG_FATAL("Malloc"); + // src/libpmemobj/tx.c + CORE_LOG_FATAL("Malloc"); + // src/libpmemobj/tx.c + CORE_LOG_FATAL("invalid state of ranges tree"); + // src/libpmemobj/tx.c + CORE_LOG_FATAL("Invalid stage %d to begin new transaction", _d); + // src/libpmemobj/tx.c + CORE_LOG_FATAL("transaction callback is already set, old %p new %p old_arg %p new_arg %p", _p, _p, _p, _p); +} + +void +call_all_CORE_LOG_ERROR_W_ERRNO_LAST(int errnum) +{ + errno = errnum; +} + +void +call_all_ERR_W_ERRNO(int errnum) +{ + errno = errnum; + // src/common/bad_blocks.c + ERR_W_ERRNO("open %s", _s); + UT_ASSERTeq(errno, errnum); + // src/common/bad_blocks.c + ERR_W_ERRNO("open %s", _s); + UT_ASSERTeq(errno, errnum); + // src/common/bad_blocks.c + ERR_W_ERRNO("open %s", _s); + UT_ASSERTeq(errno, errnum); + // src/common/ctl.c + ERR_W_ERRNO("Malloc"); + UT_ASSERTeq(errno, errnum); + // src/common/ctl.c + ERR_W_ERRNO("strtok_r"); + UT_ASSERTeq(errno, errnum); + // src/common/ctl.c + ERR_W_ERRNO("Strdup"); + UT_ASSERTeq(errno, errnum); + // src/common/ctl.c + ERR_W_ERRNO("Zalloc"); + UT_ASSERTeq(errno, errnum); + // src/common/ctl.c + ERR_W_ERRNO("Zalloc"); + UT_ASSERTeq(errno, errnum); + // src/common/file.c + ERR_W_ERRNO("stat"); + UT_ASSERTeq(errno, errnum); + // src/common/file.c + ERR_W_ERRNO("open"); + UT_ASSERTeq(errno, errnum); + // src/common/file.c + ERR_W_ERRNO("open \"%s\"", _s); + UT_ASSERTeq(errno, errnum); + // src/common/file.c + ERR_W_ERRNO("open \"%s\"", _s); + UT_ASSERTeq(errno, errnum); + // src/common/file.c + ERR_W_ERRNO("os_access \"%s\"", _s); + UT_ASSERTeq(errno, errnum); + // src/common/file.c + ERR_W_ERRNO("open \"%s\"", _s); + UT_ASSERTeq(errno, errnum); + // src/common/file.c + ERR_W_ERRNO("posix_fallocate \"%s\", %zu", _s, _zu); + UT_ASSERTeq(errno, errnum); + // src/common/file.c + ERR_W_ERRNO("flock \"%s\"", _s); + UT_ASSERTeq(errno, errnum); + // src/common/file.c + ERR_W_ERRNO("open \"%s\"", _s); + UT_ASSERTeq(errno, errnum); + // src/common/file.c + ERR_W_ERRNO("flock \"%s\"", _s); + UT_ASSERTeq(errno, errnum); + // src/common/file.c + ERR_W_ERRNO("flock unlock"); + UT_ASSERTeq(errno, errnum); + // src/common/file.c + ERR_W_ERRNO("fstat"); + UT_ASSERTeq(errno, errnum); + // src/common/file_posix.c + ERR_W_ERRNO("stat \"%s\"", _s); + UT_ASSERTeq(errno, errnum); + // src/common/mmap.c + ERR_W_ERRNO("mmap %zu bytes", _zu); + UT_ASSERTeq(errno, errnum); + // src/common/mmap.c + ERR_W_ERRNO("munmap"); + UT_ASSERTeq(errno, errnum); + // src/common/mmap.c + ERR_W_ERRNO("mprotect: PROT_READ"); + UT_ASSERTeq(errno, errnum); + // src/common/mmap.c + ERR_W_ERRNO("mprotect: PROT_READ|PROT_WRITE"); + UT_ASSERTeq(errno, errnum); + // src/common/mmap.c + ERR_W_ERRNO("mprotect: PROT_NONE"); + UT_ASSERTeq(errno, errnum); + // src/common/mmap.c + ERR_W_ERRNO("Malloc"); + UT_ASSERTeq(errno, errnum); + // src/common/mmap.c + ERR_W_ERRNO("Malloc"); + UT_ASSERTeq(errno, errnum); + // src/common/mmap.c + ERR_W_ERRNO("Malloc"); + UT_ASSERTeq(errno, errnum); + // src/common/mmap_posix.c + ERR_W_ERRNO("mmap MAP_ANONYMOUS"); + UT_ASSERTeq(errno, errnum); + // src/common/mmap_posix.c + ERR_W_ERRNO("%s", _s); + UT_ASSERTeq(errno, errnum); + // src/common/set.c + ERR_W_ERRNO("fs_new: \"%s\"", _s); + UT_ASSERTeq(errno, errnum); + // src/common/set.c + ERR_W_ERRNO("Strdup"); + UT_ASSERTeq(errno, errnum); + // src/common/set.c + ERR_W_ERRNO("no directories in replica"); + UT_ASSERTeq(errno, errnum); + // src/common/set.c + ERR_W_ERRNO("Malloc"); + UT_ASSERTeq(errno, errnum); + // src/common/set.c + ERR_W_ERRNO("lseek %d", _d); + UT_ASSERTeq(errno, errnum); + // src/common/set.c + ERR_W_ERRNO("dup"); + UT_ASSERTeq(errno, errnum); + // src/common/set.c + ERR_W_ERRNO("fdopen %d", _d); + UT_ASSERTeq(errno, errnum); + // src/common/set.c + ERR_W_ERRNO("Reading poolset file"); + UT_ASSERTeq(errno, errnum); + // src/common/set.c + ERR_W_ERRNO("Malloc for pool set"); + UT_ASSERTeq(errno, errnum); + // src/common/set.c + ERR_W_ERRNO("Strdup"); + UT_ASSERTeq(errno, errnum); + // src/common/set.c + ERR_W_ERRNO("Malloc for pool set"); + UT_ASSERTeq(errno, errnum); + // src/common/set.c + ERR_W_ERRNO("Strdup"); + UT_ASSERTeq(errno, errnum); + // src/common/set.c + ERR_W_ERRNO("Malloc for pool set replica"); + UT_ASSERTeq(errno, errnum); + // src/common/set.c + ERR_W_ERRNO("posix_fallocate \"%s\", %zu", _s, _zu); + UT_ASSERTeq(errno, errnum); + // src/common/set.c + ERR_W_ERRNO("open: path \"%s\"", _s); + UT_ASSERTeq(errno, errnum); + // src/common/set.c + ERR_W_ERRNO("read %d", _d); + UT_ASSERTeq(errno, errnum); + // src/common/set.c + ERR_W_ERRNO("fstat"); + UT_ASSERTeq(errno, errnum); + // src/common/set.c + ERR_W_ERRNO("mmap: %s", _s); + UT_ASSERTeq(errno, errnum); + // src/common/set.c + ERR_W_ERRNO("Malloc"); + UT_ASSERTeq(errno, errnum); + // src/common/set.c + ERR_W_ERRNO("mmap: %s", _s); + UT_ASSERTeq(errno, errnum); + // src/common/set.c + ERR_W_ERRNO("munmap: %s", _s); + UT_ASSERTeq(errno, errnum); + // src/common/set.c + ERR_W_ERRNO("no parts in replicas"); + UT_ASSERTeq(errno, errnum); + // src/common/set.c + ERR_W_ERRNO("read"); + UT_ASSERTeq(errno, errnum); + // src/common/set.c + ERR_W_ERRNO("open: path \"%s\"", _s); + UT_ASSERTeq(errno, errnum); + // src/common/set.c + ERR_W_ERRNO("unlink %s failed (part %u, replica %u)", _s, _u, _u); + UT_ASSERTeq(errno, errnum); + // src/common/set.c + ERR_W_ERRNO("fstat %d %s", _d, _s); + UT_ASSERTeq(errno, errnum); + // src/common/set.c + ERR_W_ERRNO("chmod %u/%u/%s", _u, _u, _s); + UT_ASSERTeq(errno, errnum); + // src/common/set.c + ERR_W_ERRNO("Strdup"); + UT_ASSERTeq(errno, errnum); + // src/common/set.c + ERR_W_ERRNO("Strdup"); + UT_ASSERTeq(errno, errnum); + // src/common/set.c + ERR_W_ERRNO("Realloc"); + UT_ASSERTeq(errno, errnum); + // src/common/set.c + ERR_W_ERRNO("Realloc"); + UT_ASSERTeq(errno, errnum); + // src/common/set.c + ERR_W_ERRNO("Zalloc"); + UT_ASSERTeq(errno, errnum); + // src/common/set_badblocks.c + ERR_W_ERRNO("Malloc"); + UT_ASSERTeq(errno, errnum); + // src/common/shutdown_state.c + ERR_W_ERRNO("Zalloc"); + UT_ASSERTeq(errno, errnum); + // src/common/vec.h + ERR_W_ERRNO("Realloc"); + UT_ASSERTeq(errno, errnum); + // src/common/vecq.h + ERR_W_ERRNO("Realloc"); + UT_ASSERTeq(errno, errnum); + // src/core/out.c + ERR_W_ERRNO("snprintf"); + UT_ASSERTeq(errno, errnum); + // src/core/ravl.c + ERR_W_ERRNO("Malloc"); + UT_ASSERTeq(errno, errnum); + // src/core/ravl.c + ERR_W_ERRNO("Malloc"); + UT_ASSERTeq(errno, errnum); + // src/core/sys_util.h + ERR_W_ERRNO("os_spin_init"); + UT_ASSERTeq(errno, errnum); + // src/core/util_posix.c + ERR_W_ERRNO("open"); + UT_ASSERTeq(errno, errnum); + // src/core/util_posix.c + ERR_W_ERRNO("stat failed for %s", _s); + UT_ASSERTeq(errno, errnum); + // src/core/util_posix.c + ERR_W_ERRNO("stat failed for %s", _s); + UT_ASSERTeq(errno, errnum); + // src/core/util_posix.c + ERR_W_ERRNO("mkstemp"); + UT_ASSERTeq(errno, errnum); + // src/libpmem/pmem.c + ERR_W_ERRNO("msync"); + UT_ASSERTeq(errno, errnum); + // src/libpmem/pmem.c + ERR_W_ERRNO("open %s", _s); + UT_ASSERTeq(errno, errnum); + // src/libpmem/pmem.c + ERR_W_ERRNO("ftruncate"); + UT_ASSERTeq(errno, errnum); + // src/libpmem/pmem.c + ERR_W_ERRNO("posix_fallocate"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/critnib.c + ERR_W_ERRNO("Malloc"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/critnib.c + ERR_W_ERRNO("Malloc"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/heap.c + ERR_W_ERRNO("heap: arena malloc error"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/lane.c + ERR_W_ERRNO("Malloc of volatile lanes"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/lane.c + ERR_W_ERRNO("Malloc for lane locks"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/lane.c + ERR_W_ERRNO("lane_init"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/list.c + ERR_W_ERRNO("palloc_reserve"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/memops.c + ERR_W_ERRNO("Zalloc"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/memops.c + ERR_W_ERRNO("Zalloc"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/memops.c + ERR_W_ERRNO("Zalloc"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/obj.c + ERR_W_ERRNO("lane_boot"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/obj.c + ERR_W_ERRNO("lane_recover_and_section_boot"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/obj.c + ERR_W_ERRNO("palloc_init"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/obj.c + ERR_W_ERRNO("critnib_insert to pools_ht"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/obj.c + ERR_W_ERRNO("critnib_insert to pools_tree"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/obj.c + ERR_W_ERRNO("ravl_new_sized"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/stats.c + ERR_W_ERRNO("Malloc"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/tx.c + ERR_W_ERRNO("pmemobj_mutex_lock"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/tx.c + ERR_W_ERRNO("pmemobj_rwlock_wrlock"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/tx.c + ERR_W_ERRNO("Malloc"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/tx.c + ERR_W_ERRNO("explicit transaction abort"); + UT_ASSERTeq(errno, errnum); +} + +void +call_all_CORE_LOG_WARNING_W_ERRNO(int errnum) +{ + errno = errnum; + // src/common/set.c + CORE_LOG_WARNING_W_ERRNO("cannot open the part -- \"%s\"", _s); + UT_ASSERTeq(errno, errnum); +} + +void +call_all_CORE_LOG_ERROR_W_ERRNO(int errnum) +{ + errno = errnum; + // src/common/os_deep_linux.c + CORE_LOG_ERROR_W_ERRNO("deep_flush not supported"); + UT_ASSERTeq(errno, errnum); + // src/common/os_deep_linux.c + CORE_LOG_ERROR_W_ERRNO("deep_flush not supported"); + UT_ASSERTeq(errno, errnum); + // src/common/uuid_linux.c + CORE_LOG_ERROR_W_ERRNO("open(uuid)"); + UT_ASSERTeq(errno, errnum); + // src/common/uuid_linux.c + CORE_LOG_ERROR_W_ERRNO("read(uuid)"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/obj.c + CORE_LOG_ERROR_W_ERRNO("lane_check"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/obj.c + CORE_LOG_ERROR_W_ERRNO("heap_check"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/obj.c + CORE_LOG_ERROR_W_ERRNO("ctl_new"); + UT_ASSERTeq(errno, errnum); +} + +void +call_all_CORE_LOG_FATAL_W_ERRNO(int errnum) +{ + errno = errnum; + // src/common/set.c + CORE_LOG_FATAL_W_ERRNO("munmap: %s", _s); + UT_ASSERTeq(errno, errnum); + // src/common/util_pmem.h + CORE_LOG_FATAL_W_ERRNO("pmem_msync"); + UT_ASSERTeq(errno, errnum); + // src/core/last_error_msg.c + CORE_LOG_FATAL_W_ERRNO("os_thread_key_create"); + UT_ASSERTeq(errno, errnum); + // src/core/last_error_msg.c + CORE_LOG_FATAL_W_ERRNO("os_tls_set"); + UT_ASSERTeq(errno, errnum); + // src/core/sys_util.h + CORE_LOG_FATAL_W_ERRNO("os_rwlock_init"); + UT_ASSERTeq(errno, errnum); + // src/core/sys_util.h + CORE_LOG_FATAL_W_ERRNO("os_rwlock_rdlock"); + UT_ASSERTeq(errno, errnum); + // src/core/sys_util.h + CORE_LOG_FATAL_W_ERRNO("os_rwlock_wrlock"); + UT_ASSERTeq(errno, errnum); + // src/core/sys_util.h + CORE_LOG_FATAL_W_ERRNO("os_rwlock_unlock"); + UT_ASSERTeq(errno, errnum); + // src/core/sys_util.h + CORE_LOG_FATAL_W_ERRNO("os_rwlock_destroy"); + UT_ASSERTeq(errno, errnum); + // src/core/sys_util.h + CORE_LOG_FATAL_W_ERRNO("os_spin_destroy"); + UT_ASSERTeq(errno, errnum); + // src/core/sys_util.h + CORE_LOG_FATAL_W_ERRNO("os_spin_lock"); + UT_ASSERTeq(errno, errnum); + // src/core/sys_util.h + CORE_LOG_FATAL_W_ERRNO("os_spin_unlock"); + UT_ASSERTeq(errno, errnum); + // src/core/sys_util.h + CORE_LOG_FATAL_W_ERRNO("os_semaphore_init"); + UT_ASSERTeq(errno, errnum); + // src/core/sys_util.h + CORE_LOG_FATAL_W_ERRNO("os_semaphore_destroy"); + UT_ASSERTeq(errno, errnum); + // src/core/sys_util.h + CORE_LOG_FATAL_W_ERRNO("os_semaphore_wait"); + UT_ASSERTeq(errno, errnum); + // src/core/sys_util.h + CORE_LOG_FATAL_W_ERRNO("os_semaphore_trywait"); + UT_ASSERTeq(errno, errnum); + // src/core/sys_util.h + CORE_LOG_FATAL_W_ERRNO("os_semaphore_post"); + UT_ASSERTeq(errno, errnum); + // src/core/sys_util.h + CORE_LOG_FATAL_W_ERRNO("os_cond_init"); + UT_ASSERTeq(errno, errnum); + // src/core/sys_util.h + CORE_LOG_FATAL_W_ERRNO("os_cond_destroy"); + UT_ASSERTeq(errno, errnum); + // src/core/sys_util.h + CORE_LOG_FATAL_W_ERRNO("os_mutex_init"); + UT_ASSERTeq(errno, errnum); + // src/core/sys_util.h + CORE_LOG_FATAL_W_ERRNO("os_mutex_destroy"); + UT_ASSERTeq(errno, errnum); + // src/core/sys_util.h + CORE_LOG_FATAL_W_ERRNO("os_mutex_lock"); + UT_ASSERTeq(errno, errnum); + // src/core/sys_util.h + CORE_LOG_FATAL_W_ERRNO("os_mutex_trylock"); + UT_ASSERTeq(errno, errnum); + // src/core/sys_util.h + CORE_LOG_FATAL_W_ERRNO("os_mutex_unlock"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/lane.c + CORE_LOG_FATAL_W_ERRNO("os_tls_key_create"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/lane.c + CORE_LOG_FATAL_W_ERRNO("os_tls_set"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/obj.c + CORE_LOG_FATAL_W_ERRNO("critnib_new for pools_ht"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/obj.c + CORE_LOG_FATAL_W_ERRNO("critnib_new for pools_tree"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/obj.c + CORE_LOG_FATAL_W_ERRNO("pmem_msync"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/sync.h + CORE_LOG_FATAL_W_ERRNO("pmemobj_mutex_unlock"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/sync.h + CORE_LOG_FATAL_W_ERRNO("pmemobj_mutex_lock"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/tx.c + CORE_LOG_FATAL_W_ERRNO("Malloc"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/tx.c + CORE_LOG_FATAL_W_ERRNO("Malloc"); + UT_ASSERTeq(errno, errnum); + // src/libpmemobj/tx.c + CORE_LOG_FATAL_W_ERRNO("Malloc"); + UT_ASSERTeq(errno, errnum); +} diff --git a/src/test/core_log_max/call_all.h b/src/test/core_log_max/call_all.h new file mode 100644 index 00000000000..c188e7518c8 --- /dev/null +++ b/src/test/core_log_max/call_all.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright 2024, Intel Corporation */ + +/* + * call_all.h -- + */ + +#ifndef CALL_ALL_H +#define CALL_ALL_H + +/* + * In general, a path in Linux can be as long as PATH_MAX (4096). However, + * because of the memory constraints, it is undesirable to allocate log buffers + * just in case the system is tested to its limits. Hence, we assumed a rational + * path length is 128 bytes. + * + * Note: If the assumption won't be met and no limitation on the path string + * will be introduced by the string format, the log buffer might be in great + * part consumed to store the path whereas the latter part of the log message + * would be lost. + */ +#define PATH \ + "Ut/imperdiet/dictum/dui/in/posuere/augue/accumsan/ut/Cras/et/neque/id/elit/porta/malesuada/Class/aptent/taciti/sociosqu//litora" + +/* Basic log APIs */ +void call_all_CORE_LOG_WARNING(void); +void call_all_CORE_LOG_ERROR(void); +void call_all_CORE_LOG_FATAL(void); + +/* Log APIs appending an error string */ +void call_all_CORE_LOG_WARNING_W_ERRNO(int errnum); +void call_all_CORE_LOG_ERROR_W_ERRNO(int errnum); +void call_all_CORE_LOG_FATAL_W_ERRNO(int errnum); + +/* Log APIs that also store the error message for later use via TLS */ +void call_all_CORE_LOG_ERROR_LAST(void); +void call_all_CORE_LOG_ERROR_W_ERRNO_LAST(int errnum); +void call_all_ERR_WO_ERRNO(void); +void call_all_ERR_W_ERRNO(int errnum); + +#endif /* CALL_ALL_H */ diff --git a/src/test/core_log_max/core_log_max.c b/src/test/core_log_max/core_log_max.c new file mode 100644 index 00000000000..57cb19b6960 --- /dev/null +++ b/src/test/core_log_max/core_log_max.c @@ -0,0 +1,200 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* Copyright 2024, Intel Corporation */ + +/* + * core_log_max.c -- unit test to verify max size of log buffers + */ + +#undef _GNU_SOURCE +#include +#include +#include + +#include "log_internal.h" +#include "last_error_msg.h" +#include "unittest.h" +#include "call_all.h" + +#define NO_ARGS_CONSUMED 0 + +#define BIG_BUF_SIZE 4096 + +#define MAX_STRERROR_NUM 0x54 + +static void +call_all_strerror_r(int *max_strerror_len, int *max_streerror_num) +{ + char buf[BIG_BUF_SIZE]; + int correct_strerror_calls = 0; + + *max_strerror_len = 0; + *max_streerror_num = 0; + + /* + * In general, valid errno values are all positive values of type int, + * but at the time of writing only the first 134 values are allocated. + * Out of which, 2 are not implemented hence 132 ought to be available. + * If not as expected please review the assumptions. + */ + for (int errnum = 0; errnum < 256; ++errnum) { + int ret = strerror_r(errnum, buf, BIG_BUF_SIZE); + + /* + * It is not forced on strerror_r(3) to end up correctly to + * accommodate not-implemented errno values already existing in + * Linux and to freely go over the biggest errno value known at + * the time of writing this comment and potentially discover + * newly introduced values. + */ + if (ret != 0) { + continue; + } + + ++correct_strerror_calls; + + int len = strlen(buf); + if (len > *max_strerror_len) { + *max_strerror_len = len; + *max_streerror_num = errnum; + } + } + UT_ASSERT(correct_strerror_calls == 132); +} + +/* tests */ + +/* + * test_CORE_LOG_MAX_ERRNO_MSG -- + * _CORE_LOG_MAX_ERRNO_MSG >= max(strlen(strerror(errnnum))) + * for errnum in errnums + */ +static int +test_CORE_LOG_MAX_ERRNO_MSG(const struct test_case *tc, int argc, char *argv[]) +{ + int max_strerror_len = 0; + int max_streerror_num = 0; + + call_all_strerror_r(&max_strerror_len, &max_streerror_num); + + /* + * The assumed errno message buffer size is big enough no matter + * the errno value. + */ + UT_ASSERT(max_strerror_len + 1 <= _CORE_LOG_MAX_ERRNO_MSG); + + /* + * Other tests in this group makes use of this value so just make sure + * the generated strerror will be as long as it is possible. + */ + UT_ASSERTeq(max_streerror_num, MAX_STRERROR_NUM); + + return NO_ARGS_CONSUMED; +} + +static int Max_TLS_message_len; +static char The_longest_TLS_message[BIG_BUF_SIZE]; +static int Total_TLS_message_num; + +/* + * A hard-coded value as obtained when the call_all_*() source code was + * generated. + */ +#define TOTAL_TLS_MESSAGE_NUM_EXPECTED 311 + +static int +test_ERR_W_ERRNO(const struct test_case *tc, int argc, char *argv[]) +{ + Max_TLS_message_len = 0; + Total_TLS_message_num = 0; + + call_all_CORE_LOG_ERROR_LAST(); + call_all_ERR_WO_ERRNO(); + call_all_CORE_LOG_ERROR_W_ERRNO_LAST(MAX_STRERROR_NUM); + call_all_ERR_W_ERRNO(MAX_STRERROR_NUM); + + UT_OUT("The_longest_TLS_message: %s", The_longest_TLS_message); + UT_ASSERTeq(Total_TLS_message_num, TOTAL_TLS_MESSAGE_NUM_EXPECTED); + UT_ASSERTeq(Max_TLS_message_len + 1, CORE_LAST_ERROR_MSG_MAXPRINT); + + return NO_ARGS_CONSUMED; +} + +#define TOTAL_MESSAGE_NUM_EXPECTED 213 +static int Max_message_len = 0; +static int Total_message_num = 0; +static char The_longest_message[BIG_BUF_SIZE]; + +FUNC_MOCK(core_log, void, enum core_log_level level, int errnum, + const char *file_name, unsigned line_no, const char *function_name, + const char *message_format, ...) + FUNC_MOCK_RUN_DEFAULT { + char buf[BIG_BUF_SIZE] = ""; + va_list arg; + va_start(arg, message_format); + int ret = vsnprintf(buf, BIG_BUF_SIZE, message_format, arg); + UT_ASSERT(ret > 0); + UT_ASSERTeq(ret, strlen(buf)); + if (errnum != NO_ERRNO) + ret += _CORE_LOG_MAX_ERRNO_MSG; + + if (level == CORE_LOG_LEVEL_ERROR_LAST) { + if (ret > Max_TLS_message_len) { + Max_TLS_message_len = ret; + strncpy(The_longest_TLS_message, buf, + BIG_BUF_SIZE); + } + ++Total_TLS_message_num; + } else { + if (ret > Max_message_len) { + Max_message_len = ret; + strncpy(The_longest_message, buf, BIG_BUF_SIZE); + } + ++Total_message_num; + } + return; + } +FUNC_MOCK_END + +static int +test_CORE_LOG(const struct test_case *tc, int argc, char *argv[]) +{ + Max_message_len = 0; + Total_message_num = 0; + + call_all_CORE_LOG_WARNING(); + call_all_CORE_LOG_WARNING_W_ERRNO(MAX_STRERROR_NUM); + call_all_CORE_LOG_ERROR(); + call_all_CORE_LOG_ERROR_W_ERRNO(MAX_STRERROR_NUM); + call_all_CORE_LOG_FATAL(); + call_all_CORE_LOG_FATAL_W_ERRNO(MAX_STRERROR_NUM); + + UT_OUT("The_longest_message: %s", The_longest_message); +/* + * + 1 for '\0' and another + * + 1 as a means for detecting too-long log messages. + * Please see _CORE_LOG_MSG_MAXPRINT for details. + */ + UT_ASSERTeq(Max_message_len + 2, _CORE_LOG_MSG_MAXPRINT); + UT_ASSERTeq(Total_message_num, TOTAL_MESSAGE_NUM_EXPECTED); + + return NO_ARGS_CONSUMED; +} + +static struct test_case test_cases[] = { + TEST_CASE(test_CORE_LOG_MAX_ERRNO_MSG), + TEST_CASE(test_ERR_W_ERRNO), + TEST_CASE(test_CORE_LOG), +}; + +#define NTESTS ARRAY_SIZE(test_cases) + +int +main(int argc, char *argv[]) +{ + START(argc, argv, "core_log_max"); + + UT_COMPILE_ERROR_ON(sizeof(PATH) != 128); + + TEST_CASE_PROCESS(argc, argv, test_cases, NTESTS); + DONE(NULL); +} diff --git a/src/test/core_log_no_func/.gitignore b/src/test/core_log_no_func/.gitignore new file mode 100644 index 00000000000..18f74694106 --- /dev/null +++ b/src/test/core_log_no_func/.gitignore @@ -0,0 +1 @@ +core_log_no_func diff --git a/src/test/core_log_no_func/Makefile b/src/test/core_log_no_func/Makefile new file mode 100644 index 00000000000..cfa23ac02f5 --- /dev/null +++ b/src/test/core_log_no_func/Makefile @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation + +vpath %.c ../core_log + +TARGET = core_log_no_func +OBJS = core_log_no_func.o core_log_common.o + +include ../core_log/Makefile.inc +INCS += -I../core_log diff --git a/src/test/core_log_no_func/TESTS.py b/src/test/core_log_no_func/TESTS.py new file mode 100755 index 00000000000..b058118966c --- /dev/null +++ b/src/test/core_log_no_func/TESTS.py @@ -0,0 +1,28 @@ +#!../env.py +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation +# + + +import testframework as t +from testframework import granularity as g + + +@g.require_granularity(g.ANY) +@t.require_valgrind_disabled('pmemcheck') +# The 'nondebug' build is chosen arbitrarily to ensure these tests are run only +# once. No dynamic libraries are used nor .static_* builds are available. +@t.require_build('nondebug') +class CORE_LOG(t.BaseTest): + test_type = t.Short + + def run(self, ctx): + ctx.exec('core_log_no_func', self.test_case) + + +class TEST0(CORE_LOG): + test_case = 'test_no_log_function' + + +class TEST1(CORE_LOG): + test_case = 'test_no_log_function_CORE_LOG_LEVEL_ERROR_LAST' diff --git a/src/test/core_log_no_func/core_log_no_func.c b/src/test/core_log_no_func/core_log_no_func.c new file mode 100644 index 00000000000..d3672c3ca70 --- /dev/null +++ b/src/test/core_log_no_func/core_log_no_func.c @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* Copyright 2024, Intel Corporation */ + +/* + * core_log_no_func.c -- unit test for core_log() and core_log_va() when + * no logging function is attached. + */ + +#include + +#include "unittest.h" +#include "core_log_common.h" + +/* tests */ + +/* + * Check: + * - if Core_log_function == 0: + * - the log function is not called + */ +static int +test_no_log_function(const struct test_case *tc, int argc, char *argv[]) +{ + /* Pass the message all the way to the logging function. */ + core_log_set_threshold(CORE_LOG_THRESHOLD, CORE_LOG_LEVEL_ERROR); + + test_log_function_call_helper(CORE_LOG_LEVEL_ERROR, + false /* log_function_called */); + + return NO_ARGS_CONSUMED; +} + +/* + * Check: + * - if Core_log_function == 0 and level == CORE_LOG_LEVEL_ERROR_LAST: + * - the log function is not called + */ +static int +test_no_log_function_CORE_LOG_LEVEL_ERROR_LAST(const struct test_case *tc, + int argc, char *argv[]) +{ + /* Pass the message all the way to the logging function. */ + core_log_set_threshold(CORE_LOG_THRESHOLD, CORE_LOG_LEVEL_ERROR); + + test_log_function_call_helper(CORE_LOG_LEVEL_ERROR_LAST, + false /* log_function_called */); + + return NO_ARGS_CONSUMED; +} + +static struct test_case test_cases[] = { + TEST_CASE(test_no_log_function), + TEST_CASE(test_no_log_function_CORE_LOG_LEVEL_ERROR_LAST), +}; + +#define NTESTS ARRAY_SIZE(test_cases) + +int +main(int argc, char *argv[]) +{ + START(argc, argv, "core_log_no_func"); + TEST_CASE_PROCESS(argc, argv, test_cases, NTESTS); + DONE(NULL); +} diff --git a/src/test/core_log_threshold_mt/.gitignore b/src/test/core_log_threshold_mt/.gitignore new file mode 100644 index 00000000000..c949af1fe1d --- /dev/null +++ b/src/test/core_log_threshold_mt/.gitignore @@ -0,0 +1 @@ +core_log_threshold_mt diff --git a/src/test/core_log_threshold_mt/Makefile b/src/test/core_log_threshold_mt/Makefile new file mode 100644 index 00000000000..545331e97fc --- /dev/null +++ b/src/test/core_log_threshold_mt/Makefile @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation + +TARGET = core_log_threshold_mt +OBJS = core_log_threshold_mt.o + +BUILD_STATIC_DEBUG=n +BUILD_STATIC_NONDEBUG=n + +LIBPMEMCORE=y + +include ../Makefile.inc diff --git a/src/test/core_log_threshold_mt/TESTS.py b/src/test/core_log_threshold_mt/TESTS.py new file mode 100755 index 00000000000..fffa0d7faf9 --- /dev/null +++ b/src/test/core_log_threshold_mt/TESTS.py @@ -0,0 +1,46 @@ +#!../env.py +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation +# + + +import testframework as t +from testframework import granularity as g + + +@g.require_granularity(g.ANY) +@t.require_build('nondebug') +@t.require_valgrind_disabled('pmemcheck', 'memcheck') +class CORE_LOG_MT(t.BaseTest): + test_type = t.Short + + def run(self, ctx): + ctx.exec('core_log_threshold_mt', self.test_case) + + +class TEST0(CORE_LOG_MT): + test_case = 'test_threshold_set_get' + + +@t.require_valgrind_enabled('helgrind') +class TEST1(TEST0): + pass + + +@t.require_valgrind_enabled('drd') +class TEST2(TEST0): + pass + + +class TEST3(CORE_LOG_MT): + test_case = 'test_threshold_aux_set_get' + + +@t.require_valgrind_enabled('helgrind') +class TEST4(TEST3): + pass + + +@t.require_valgrind_enabled('drd') +class TEST5(TEST3): + pass diff --git a/src/test/core_log_threshold_mt/core_log_threshold_mt.c b/src/test/core_log_threshold_mt/core_log_threshold_mt.c new file mode 100644 index 00000000000..eb854e968c5 --- /dev/null +++ b/src/test/core_log_threshold_mt/core_log_threshold_mt.c @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* Copyright 2024, Intel Corporation */ + +/* + * core_log_threshold_mt.c -- unit test for core_log_set/get_threshold() and + * CORE_LOG_X() since all of them may write/read thresholds in parallel. + */ + +#include "unittest.h" +#include "log_internal.h" + +#define NO_ARGS_CONSUMED 0 + +#define THREADS_IN_GROUP 10 +#define THREADS_SET_MIN 0 +#define THREADS_SET_MAX (THREADS_SET_MIN + THREADS_IN_GROUP) +#define THREADS_GET_MIN THREADS_SET_MAX +#define THREADS_GET_MAX (THREADS_GET_MIN + THREADS_IN_GROUP) +#define TOTAL_THREADS THREADS_GET_MAX + +#define OP_REDO 4096 + +static struct helper_ctx { + enum core_log_threshold threshold; + int idx; +} helper_ctx_ [TOTAL_THREADS]; + +static os_mutex_t mutex; +static os_cond_t cond; +static unsigned threads_waiting; + +static void * +helper_set(void *arg) +{ + struct helper_ctx *ctx = (struct helper_ctx *)arg; + os_mutex_lock(&mutex); + ++threads_waiting; + os_cond_wait(&cond, &mutex); + os_mutex_unlock(&mutex); + for (int i = 0; i < OP_REDO; ++i) { + /* + * a simple attempt to generate a different sequence of values + * for each of the threads + */ + enum core_log_level level = + (enum core_log_level)((i * (ctx->idx + 1)) % + CORE_LOG_LEVEL_MAX); + int ret = core_log_set_threshold(ctx->threshold, level); + UT_ASSERT(ret == 0 || ret == EAGAIN); + if (ret == EAGAIN) { + UT_OUT("ret == EAGAIN"); /* just out of curiosity */ + } + } + return NULL; +} + +static void * +helper_get(void *arg) +{ + struct helper_ctx *ctx = (struct helper_ctx *)arg; + os_mutex_lock(&mutex); + ++threads_waiting; + os_cond_wait(&cond, &mutex); + os_mutex_unlock(&mutex); + for (int i = 0; i < OP_REDO; ++i) { + enum core_log_level level; + int ret = core_log_get_threshold(ctx->threshold, &level); + UT_ASSERTeq(ret, 0); + level = _core_log_get_threshold_internal(); + } + return NULL; +} + +static void +helper(enum core_log_threshold threshold) +{ + os_thread_t threads[TOTAL_THREADS]; + + os_mutex_init(&mutex); + os_cond_init(&cond); + threads_waiting = 0; + + /* core_log_set_threshold() threads */ + for (int idx = THREADS_SET_MIN; idx < THREADS_SET_MAX; idx++) { + helper_ctx_[idx].threshold = threshold; + helper_ctx_[idx].idx = idx; + THREAD_CREATE(&threads[idx], 0, helper_set, + (void *)&helper_ctx_[idx]); + } + + /* core_log_get_threshold/_core_log_get_threshold_internal() threads */ + for (int idx = THREADS_GET_MIN; idx < THREADS_GET_MAX; idx++) { + helper_ctx_[idx].threshold = threshold; + THREAD_CREATE(&threads[idx], 0, helper_get, + (void *)&helper_ctx_[idx]); + } + + do { + os_mutex_lock(&mutex); + if (threads_waiting == TOTAL_THREADS) { + os_cond_broadcast(&cond); + os_mutex_unlock(&mutex); + break; + } + os_mutex_unlock(&mutex); + } while (1); + + for (int idx = 0; idx < TOTAL_THREADS; idx++) { + void *retval; + THREAD_JOIN(&threads[idx], &retval); + } + + os_cond_destroy(&cond); + os_mutex_destroy(&mutex); +} + +/* tests */ + +/* + * Run core_log_set/get_threshold(CORE_LOG_THRESHOLD, ...) and CORE_LOG_X() + * in parallel. + */ +static int +test_threshold_set_get(const struct test_case *tc, int argc, char *argv[]) +{ + helper(CORE_LOG_THRESHOLD); + return NO_ARGS_CONSUMED; +} + +/* + * Run core_log_set/get_threshold(CORE_LOG_THRESHOLD_AUX, ...) and CORE_LOG_X() + * in parallel. + */ +static int +test_threshold_aux_set_get(const struct test_case *tc, int argc, char *argv[]) +{ + helper(CORE_LOG_THRESHOLD_AUX); + return NO_ARGS_CONSUMED; +} + +/* + * A Valgrind tool external to the test binary is assumed to monitor + * the execution and assess synchronisation correctness. + */ +static struct test_case test_cases[] = { + TEST_CASE(test_threshold_set_get), + TEST_CASE(test_threshold_aux_set_get), +}; + +#define NTESTS ARRAY_SIZE(test_cases) + +int +main(int argc, char *argv[]) +{ + START(argc, argv, "core_log_threshold_mt"); + TEST_CASE_PROCESS(argc, argv, test_cases, NTESTS); + DONE(NULL); +} diff --git a/src/test/ctl_cow/TEST0 b/src/test/ctl_cow/TEST0 index 589e1831889..f1b2649fcc3 100755 --- a/src/test/ctl_cow/TEST0 +++ b/src/test/ctl_cow/TEST0 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2019, Intel Corporation +# Copyright 2019-2024, Intel Corporation # # src/test/ctl_cow/TEST0 -- unit test which checks copy on write feature @@ -26,7 +26,7 @@ expect_normal_exit $PMEMPOOL$EXESUFFIX create obj $DIR/$POOLSET POOL_BEFORE=`md5sum -b $DIR/$POOL` REPLICA_BEFORE=`md5sum -b $DIR/$REPLICA` -PMEMOBJ_CONF="${PMEMOBJ_CONF}copy_on_write.at_open=1" +PMEMOBJ_CONF="${PMEMOBJ_CONF};copy_on_write.at_open=1" expect_normal_exit ./ctl_cow$EXESUFFIX $DIR/$POOLSET obj diff --git a/src/test/ctl_cow/TEST3 b/src/test/ctl_cow/TEST3 index ab658fb282a..d673a2ca9b4 100755 --- a/src/test/ctl_cow/TEST3 +++ b/src/test/ctl_cow/TEST3 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2019, Intel Corporation +# Copyright 2019-2024, Intel Corporation # # src/test/ctl_cow/TEST3 -- unit test which checks if opening pool located @@ -24,7 +24,7 @@ expect_normal_exit $PMEMPOOL$EXESUFFIX create obj $POOLSET_DAX expect_normal_exit $PMEMPOOL$EXESUFFIX create -s 32MB obj $POOL -PMEMOBJ_CONF="copy_on_write.at_open=1;" +PMEMOBJ_CONF="${PMEMOBJ_CONF};copy_on_write.at_open=1;" # check if opening non-dax pool does not fail expect_normal_exit ./ctl_cow$EXESUFFIX $POOL dax diff --git a/src/test/drd-log.supp b/src/test/drd-log.supp index d99f69bfe26..5d9db8c9650 100644 --- a/src/test/drd-log.supp +++ b/src/test/drd-log.supp @@ -7,6 +7,7 @@ ... fun:out_print_func fun:out_common + fun:out_log_va fun:out_log } { @@ -18,6 +19,7 @@ ... fun:out_print_func fun:out_common + fun:out_log_va fun:out_log } { diff --git a/src/test/ex_libpmemobj/TEST0 b/src/test/ex_libpmemobj/TEST0 index f3cd5149176..fa1ec47b245 100755 --- a/src/test/ex_libpmemobj/TEST0 +++ b/src/test/ex_libpmemobj/TEST0 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2015-2019, Intel Corporation +# Copyright 2015-2024, Intel Corporation # # src/test/ex_libpmemobj/TEST0 -- unit test for libpmemobj examples @@ -17,8 +17,12 @@ setup EX_PATH=../../examples/libpmemobj -expect_normal_exit $EX_PATH/pi $DIR/testfile1 c 2 20 > out$UNITTEST_NUM.log 2>&1 -expect_normal_exit $EX_PATH/pi $DIR/testfile1 p >> out$UNITTEST_NUM.log 2>&1 +. ./common.sh + +expect_normal_exit $EX_PATH/pi $DIR/testfile1 c 2 20 > $LOG_TEMP 2>&1 +expect_normal_exit $EX_PATH/pi $DIR/testfile1 p >> $LOG_TEMP 2>&1 + +mv $LOG_TEMP $LOG check diff --git a/src/test/ex_libpmemobj/TEST1 b/src/test/ex_libpmemobj/TEST1 index 86f751c47f3..82fc2e98cf3 100755 --- a/src/test/ex_libpmemobj/TEST1 +++ b/src/test/ex_libpmemobj/TEST1 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2015-2019, Intel Corporation +# Copyright 2015-2024, Intel Corporation # # src/test/ex_libpmemobj/TEST1 -- unit test for libpmemobj examples @@ -14,14 +14,18 @@ require_build_type debug nondebug setup +. ./common.sh + EX_PATH=../../examples/libpmemobj -expect_normal_exit $EX_PATH/btree $DIR/testfile1 i 1234 foo > out$UNITTEST_NUM.log 2>&1 -expect_normal_exit $EX_PATH/btree $DIR/testfile1 i 4321 bar >> out$UNITTEST_NUM.log 2>&1 -expect_normal_exit $EX_PATH/btree $DIR/testfile1 i 1 Hello >> out$UNITTEST_NUM.log 2>&1 -expect_normal_exit $EX_PATH/btree $DIR/testfile1 i 2 World! >> out$UNITTEST_NUM.log 2>&1 -expect_normal_exit $EX_PATH/btree $DIR/testfile1 p >> out$UNITTEST_NUM.log 2>&1 -expect_normal_exit $EX_PATH/btree $DIR/testfile1 f 4321 >> out$UNITTEST_NUM.log 2>&1 +expect_normal_exit $EX_PATH/btree $DIR/testfile1 i 1234 foo > $LOG_TEMP 2>&1 +expect_normal_exit $EX_PATH/btree $DIR/testfile1 i 4321 bar >> $LOG_TEMP 2>&1 +expect_normal_exit $EX_PATH/btree $DIR/testfile1 i 1 Hello >> $LOG_TEMP 2>&1 +expect_normal_exit $EX_PATH/btree $DIR/testfile1 i 2 World! >> $LOG_TEMP 2>&1 +expect_normal_exit $EX_PATH/btree $DIR/testfile1 p >> $LOG_TEMP 2>&1 +expect_normal_exit $EX_PATH/btree $DIR/testfile1 f 4321 >> $LOG_TEMP 2>&1 + +mv $LOG_TEMP $LOG check diff --git a/src/test/ex_libpmemobj/TEST17 b/src/test/ex_libpmemobj/TEST17 index ccbca8f96cd..3ef613d42cc 100755 --- a/src/test/ex_libpmemobj/TEST17 +++ b/src/test/ex_libpmemobj/TEST17 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2015-2019, Intel Corporation +# Copyright 2015-2024, Intel Corporation # # src/test/ex_libpmemobj/TEST17 -- unit test for libpmemobj examples @@ -13,16 +13,20 @@ require_test_type medium setup +. ./common.sh + EX_PATH=../../examples/libpmemobj -expect_normal_exit $EX_PATH/lists $DIR/testfile1 1 foo 100 > out$UNITTEST_NUM.log 2>&1 -expect_normal_exit $EX_PATH/lists $DIR/testfile1 2 bar 200 >> out$UNITTEST_NUM.log 2>&1 -expect_normal_exit $EX_PATH/lists $DIR/testfile1 3 foo 300 >> out$UNITTEST_NUM.log 2>&1 -expect_normal_exit $EX_PATH/lists $DIR/testfile1 1 bar 400 >> out$UNITTEST_NUM.log 2>&1 -expect_normal_exit $EX_PATH/lists $DIR/testfile1 1 foo print >> out$UNITTEST_NUM.log 2>&1 -expect_normal_exit $EX_PATH/lists $DIR/testfile1 2 bar print >> out$UNITTEST_NUM.log 2>&1 -expect_normal_exit $EX_PATH/lists $DIR/testfile1 3 foo print >> out$UNITTEST_NUM.log 2>&1 -expect_normal_exit $EX_PATH/lists $DIR/testfile1 1 bar print >> out$UNITTEST_NUM.log 2>&1 +expect_normal_exit $EX_PATH/lists $DIR/testfile1 1 foo 100 > $LOG_TEMP 2>&1 +expect_normal_exit $EX_PATH/lists $DIR/testfile1 2 bar 200 >> $LOG_TEMP 2>&1 +expect_normal_exit $EX_PATH/lists $DIR/testfile1 3 foo 300 >> $LOG_TEMP 2>&1 +expect_normal_exit $EX_PATH/lists $DIR/testfile1 1 bar 400 >> $LOG_TEMP 2>&1 +expect_normal_exit $EX_PATH/lists $DIR/testfile1 1 foo print >> $LOG_TEMP 2>&1 +expect_normal_exit $EX_PATH/lists $DIR/testfile1 2 bar print >> $LOG_TEMP 2>&1 +expect_normal_exit $EX_PATH/lists $DIR/testfile1 3 foo print >> $LOG_TEMP 2>&1 +expect_normal_exit $EX_PATH/lists $DIR/testfile1 1 bar print >> $LOG_TEMP 2>&1 + +mv $LOG_TEMP $LOG check diff --git a/src/test/ex_libpmemobj/TEST7 b/src/test/ex_libpmemobj/TEST7 index 6f58a41172f..c5c968e5faf 100755 --- a/src/test/ex_libpmemobj/TEST7 +++ b/src/test/ex_libpmemobj/TEST7 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2015-2019, Intel Corporation +# Copyright 2015-2024, Intel Corporation # # src/test/ex_libpmemobj/TEST7 -- unit test for libpmemobj examples @@ -14,13 +14,17 @@ require_build_type debug nondebug setup +. ./common.sh + EX_PATH=../../examples/libpmemobj/string_store -expect_normal_exit $EX_PATH/writer $DIR/testfile1 > out$UNITTEST_NUM.log 2>&1 << EOF +expect_normal_exit $EX_PATH/writer $DIR/testfile1 > $LOG_TEMP 2>&1 << EOF Hello! EOF -expect_normal_exit $EX_PATH/reader $DIR/testfile1 >> out$UNITTEST_NUM.log 2>&1 +expect_normal_exit $EX_PATH/reader $DIR/testfile1 >> $LOG_TEMP 2>&1 + +mv $LOG_TEMP $LOG check diff --git a/src/test/ex_libpmemobj/TEST8 b/src/test/ex_libpmemobj/TEST8 index a8f949c9657..8d7b7a1494e 100755 --- a/src/test/ex_libpmemobj/TEST8 +++ b/src/test/ex_libpmemobj/TEST8 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2015-2019, Intel Corporation +# Copyright 2015-2024, Intel Corporation # # src/test/ex_libpmemobj/TEST8 -- unit test for libpmemobj examples @@ -14,13 +14,17 @@ require_build_type debug nondebug setup +. ./common.sh + EX_PATH=../../examples/libpmemobj/string_store_tx -expect_normal_exit $EX_PATH/writer $DIR/testfile1 > out$UNITTEST_NUM.log 2>&1 << EOF +expect_normal_exit $EX_PATH/writer $DIR/testfile1 > $LOG_TEMP 2>&1 << EOF Hello! EOF -expect_normal_exit $EX_PATH/reader $DIR/testfile1 >> out$UNITTEST_NUM.log 2>&1 +expect_normal_exit $EX_PATH/reader $DIR/testfile1 >> $LOG_TEMP 2>&1 + +mv $LOG_TEMP $LOG check diff --git a/src/test/ex_libpmemobj/TEST9 b/src/test/ex_libpmemobj/TEST9 index 5f109791b2d..f42a527129a 100755 --- a/src/test/ex_libpmemobj/TEST9 +++ b/src/test/ex_libpmemobj/TEST9 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2015-2019, Intel Corporation +# Copyright 2015-2024, Intel Corporation # # src/test/ex_libpmemobj/TEST9 -- unit test for libpmemobj examples @@ -14,13 +14,16 @@ require_build_type debug nondebug setup +. ./common.sh EX_PATH=../../examples/libpmemobj/string_store_tx_type -expect_normal_exit $EX_PATH/writer $DIR/testfile1 > out$UNITTEST_NUM.log 2>&1 << EOF +expect_normal_exit $EX_PATH/writer $DIR/testfile1 > $LOG_TEMP 2>&1 << EOF Hello! EOF -expect_normal_exit $EX_PATH/reader $DIR/testfile1 >> out$UNITTEST_NUM.log 2>&1 +expect_normal_exit $EX_PATH/reader $DIR/testfile1 >> $LOG_TEMP 2>&1 + +mv $LOG_TEMP $LOG check diff --git a/src/test/ex_libpmemobj/common.sh b/src/test/ex_libpmemobj/common.sh new file mode 100644 index 00000000000..262a90d362c --- /dev/null +++ b/src/test/ex_libpmemobj/common.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation + +# +# src/test/ex_libpmemobj/common.sh -- common setup of unit test +# for libpmemobj examples +# + +LOG=out$UNITTEST_NUM.log + +LOG_TEMP=out${UNITTEST_NUM}_part.log +rm -f $LOG_TEMP && touch $LOG_TEMP diff --git a/src/test/helgrind-log.supp b/src/test/helgrind-log.supp index 95f90df3623..eac51a6ada5 100644 --- a/src/test/helgrind-log.supp +++ b/src/test/helgrind-log.supp @@ -7,6 +7,7 @@ ... fun:out_print_func fun:out_common + fun:out_log_va fun:out_log } { @@ -17,19 +18,9 @@ fun:fputs fun:out_print_func fun:out_common + fun:out_log_va fun:out_log } -{ - - Helgrind:Race - fun:*mem*cpy - ... - fun:_IO_file_xsputn@@GLIBC* - ... - fun:out_print_func - fun:out_error - fun:out_err -} { diff --git a/src/test/libpmempool_feature/common.sh b/src/test/libpmempool_feature/common.sh index ce9992a880e..8b4741a6415 100644 --- a/src/test/libpmempool_feature/common.sh +++ b/src/test/libpmempool_feature/common.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2018-2019, Intel Corporation +# Copyright 2018-2024, Intel Corporation # # src/test/libpmempool_feature/common.sh -- common part of libpmempool_feature tests diff --git a/src/test/libpmempool_feature/grep3.log.match b/src/test/libpmempool_feature/grep3.log.match index bf37883bdc5..dd007438b30 100644 --- a/src/test/libpmempool_feature/grep3.log.match +++ b/src/test/libpmempool_feature/grep3.log.match @@ -1,13 +1,18 @@ $(*)pool.obj: spoil: pool_hdr.features.compat=0xfe $(*)pool.obj: spoil: pool_hdr.f:checksum_gen -: <1> [feature.c:$(N) features_check] invalid features detected: {compat 0xfe, incompat 0x0, ro_compat 0x0} -: <1> [feature.c:$(N) poolset_open] invalid features - replica #0 part #0 +$(OPT)XXX Next line to be restored (no OPT) when #5981 is fixed +$(OPT): <1> [feature.c:$(N) features_check] invalid features detected: {compat 0xfe, incompat 0x0, ro_compat 0x0} +$(OPT)XXX Next line to be restored (no OPT) when #5981 is fixed +$(OPT): <1> [feature.c:$(N) poolset_open] invalid features - replica #0 part #0 $(*)testfile23: spoil: pool_hdr.features.incompat=0xfe $(*)testfile23: spoil: pool_hdr.f:checksum_gen $(OPT): <1> [feature.c:$(N) features_check] features mismatch detected: {compat 0x0, incompat 0xfe, ro_compat 0x0} != {compat 0x0, incompat 0x$(N), ro_compat 0x0} $(OPT): <1> [feature.c:$(N) features_check] features mismatch detected: {compat 0x1, incompat 0xfe, ro_compat 0x0} != {compat 0x1, incompat 0x$(N), ro_compat 0x0} -: <1> [feature.c:$(N) poolset_open] invalid features - replica #1 part #2 +$(OPT)XXX Next line to be restored (no OPT) when #5981 is fixed +$(OPT): <1> [feature.c:$(N) poolset_open] invalid features - replica #1 part #2 $(*)testfile11: spoil: pool_hdr.features.ro_compat=0xfe $(*)testfile11: spoil: pool_hdr.f:checksum_gen -: <1> [feature.c:$(N) features_check] invalid features detected: {compat 0x0, incompat 0x0, ro_compat 0xfe} -: <1> [feature.c:$(N) poolset_open] invalid features - replica #0 part #0 +$(OPT)XXX Next line to be restored (no OPT) when #5981 is fixed +$(OPT): <1> [feature.c:$(N) features_check] invalid features detected: {compat 0x0, incompat 0x0, ro_compat 0xfe} +$(OPT)XXX Next line to be restored (no OPT) when #5981 is fixed +$(OPT): <1> [feature.c:$(N) poolset_open] invalid features - replica #0 part #0 diff --git a/src/test/log_errno/.gitignore b/src/test/log_errno/.gitignore new file mode 100644 index 00000000000..1c6ea52f0aa --- /dev/null +++ b/src/test/log_errno/.gitignore @@ -0,0 +1 @@ +log_errno diff --git a/src/test/log_errno/Makefile b/src/test/log_errno/Makefile new file mode 100644 index 00000000000..98cb6888878 --- /dev/null +++ b/src/test/log_errno/Makefile @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation + +# +# src/test/log_errno/Makefile -- build unit test for log_errno +# +TARGET = log_errno +OBJS = log_errno.o + +BUILD_STATIC_DEBUG=n +BUILD_STATIC_NONDEBUG=n + +include ../Makefile.inc diff --git a/src/test/log_errno/TEST0 b/src/test/log_errno/TEST0 new file mode 100755 index 00000000000..8e873718163 --- /dev/null +++ b/src/test/log_errno/TEST0 @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation + +# +# src/test/log_errno/TEST0 -- unit test for CORE_LOG_ERROR_W_ERRNO macro +# + +. ../unittest/unittest.sh + +require_test_type short + +require_fs_type none +setup + +expect_normal_exit ./log_errno$EXESUFFIX 2>$ERR_LOG_FILE + +check + +pass diff --git a/src/test/log_errno/err0.log.match b/src/test/log_errno/err0.log.match new file mode 100644 index 00000000000..846f021cffd --- /dev/null +++ b/src/test/log_errno/err0.log.match @@ -0,0 +1 @@ +$(*) [$(*)] *ERROR* log_errno.c: $(N): main: open file lolek: Success diff --git a/src/test/log_errno/log_errno.c b/src/test/log_errno/log_errno.c new file mode 100644 index 00000000000..251e7cdd264 --- /dev/null +++ b/src/test/log_errno/log_errno.c @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* Copyright 2024, Intel Corporation */ + +/* + * log_errno.c -- unit test for CORE_LOG_ERROR_W_ERRNO macro + */ +#include + +#include "unittest.h" +#include "log_internal.h" + +int +main(int argc, char *argv[]) +{ + START(argc, argv, "log_errno"); + + core_log_init(); + CORE_LOG_ERROR_W_ERRNO("open file %s", "lolek"); + core_log_fini(); + /* + * The fini function above intentionally does not close the syslog + * socket. It has to be closed separately so it won't be accounted as + * an unclosed file descriptor. + */ + closelog(); + + DONE(NULL); +} diff --git a/src/test/obj_ctl_arenas/TEST8 b/src/test/obj_ctl_arenas/TEST8 index 8db2691513a..c913bbe760b 100755 --- a/src/test/obj_ctl_arenas/TEST8 +++ b/src/test/obj_ctl_arenas/TEST8 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2021, Intel Corporation +# Copyright 2021-2024, Intel Corporation # # src/test/obj_ctl_arenas/TEST8 -- test for global arena type assignment @@ -13,7 +13,7 @@ require_fs_type any setup -PMEMOBJ_CONF="heap.arenas_assignment_type=global"\ +PMEMOBJ_CONF="${PMEMOBJ_CONF};heap.arenas_assignment_type=global"\ expect_normal_exit ./obj_ctl_arenas$EXESUFFIX $DIR/testset1 p pass diff --git a/src/test/obj_ctl_arenas/TEST9 b/src/test/obj_ctl_arenas/TEST9 index 82900cb6de2..534ed084a61 100755 --- a/src/test/obj_ctl_arenas/TEST9 +++ b/src/test/obj_ctl_arenas/TEST9 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2021, Intel Corporation +# Copyright 2021-2024, Intel Corporation # # src/test/obj_ctl_arenas/TEST9 -- test for global arena type assignment @@ -13,7 +13,7 @@ require_fs_type any setup -PMEMOBJ_CONF="heap.arenas_assignment_type=thread"\ +PMEMOBJ_CONF="${PMEMOBJ_CONF};heap.arenas_assignment_type=thread"\ expect_normal_exit ./obj_ctl_arenas$EXESUFFIX $DIR/testset1 d pass diff --git a/src/test/obj_ctl_arenas/obj_ctl_arenas.c b/src/test/obj_ctl_arenas/obj_ctl_arenas.c index ff11bf975bc..7f5cff2d0b8 100644 --- a/src/test/obj_ctl_arenas/obj_ctl_arenas.c +++ b/src/test/obj_ctl_arenas/obj_ctl_arenas.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2019-2021, Intel Corporation */ +/* Copyright 2019-2024, Intel Corporation */ /* * obj_ctl_arenas.c -- tests for the ctl entry points @@ -215,7 +215,6 @@ worker_arena_threads(void *arg) UT_ASSERTeq(ret, 0); PMEMoid oid[NOBJECT_THREAD]; - unsigned d; for (int i = 0; i < NOBJECT_THREAD; i++) { ret = pmemobj_xalloc(pop, &oid[i], @@ -224,10 +223,9 @@ worker_arena_threads(void *arg) NULL, NULL); UT_ASSERTeq(ret, 0); - d = labs((long)ref->oid.off - (long)oid[i].off); - /* objects are in the same block as the first one */ - ASSERT(d <= alloc_class[ALLOC_CLASS_ARENA].unit_size * + ASSERT(labs((long)ref->oid.off - (long)oid[i].off) <= + alloc_class[ALLOC_CLASS_ARENA].unit_size * (alloc_class[ALLOC_CLASS_ARENA].units_per_block - 1)); } diff --git a/src/test/obj_defrag/TESTS.py b/src/test/obj_defrag/TESTS.py index 42b6a8b23a4..2c7ca30dd38 100755 --- a/src/test/obj_defrag/TESTS.py +++ b/src/test/obj_defrag/TESTS.py @@ -1,13 +1,13 @@ #!../env.py # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2019-2020, Intel Corporation +# Copyright 2019-2024, Intel Corporation # from os import path import testframework as t -class BASE(t.BaseTest): +class BASE(t.Test): test_type = t.Medium def run(self, ctx): diff --git a/src/test/obj_defrag_advanced/TESTS.py b/src/test/obj_defrag_advanced/TESTS.py index a33200c44dd..1ad4885e588 100755 --- a/src/test/obj_defrag_advanced/TESTS.py +++ b/src/test/obj_defrag_advanced/TESTS.py @@ -1,6 +1,6 @@ #!../env.py # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2020-2023, Intel Corporation +# Copyright 2020-2024, Intel Corporation # import testframework as t @@ -11,7 +11,7 @@ # These tests last too long under drd # Exceptions: test no. 2 @t.require_valgrind_disabled('drd') -class ObjDefragAdvanced(t.BaseTest): +class ObjDefragAdvanced(t.Test): test_type = t.Short max_nodes = 50 diff --git a/src/test/obj_extend/TEST1 b/src/test/obj_extend/TEST1 index 91815017da8..c5543002e47 100755 --- a/src/test/obj_extend/TEST1 +++ b/src/test/obj_extend/TEST1 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2018-2019, Intel Corporation +# Copyright 2018-2024, Intel Corporation # # src/test/obj_extend/TEST1 -- unit test for extending the pool @@ -22,7 +22,7 @@ create_poolset $DIR/testset2\ $RESVSIZE:$DIR/testdir21:d\ O SINGLEHDR -PMEMOBJ_CONF="heap.size.granularity=$GRANULARITY"\ +PMEMOBJ_CONF="${PMEMOBJ_CONF};heap.size.granularity=$GRANULARITY"\ expect_normal_exit ./obj_extend$EXESUFFIX $DIR/testset2 check diff --git a/src/test/obj_log_get_treshold/.gitignore b/src/test/obj_log_get_treshold/.gitignore new file mode 100644 index 00000000000..72cb85ece1c --- /dev/null +++ b/src/test/obj_log_get_treshold/.gitignore @@ -0,0 +1 @@ +obj_log_get_treshold diff --git a/src/test/obj_log_get_treshold/Makefile b/src/test/obj_log_get_treshold/Makefile new file mode 100644 index 00000000000..8629483392b --- /dev/null +++ b/src/test/obj_log_get_treshold/Makefile @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation + +TARGET = obj_log_get_treshold +OBJS = obj_log_get_treshold.o + +BUILD_STATIC_DEBUG=n +BUILD_STATIC_NONDEBUG=n + +# required for proper mock integration +LIBPMEMOBJ=internal-debug + +include ../Makefile.inc +LDFLAGS += $(call extract_funcs, obj_log_get_treshold.c) diff --git a/src/test/obj_log_get_treshold/TESTS.py b/src/test/obj_log_get_treshold/TESTS.py new file mode 100755 index 00000000000..47094061bf6 --- /dev/null +++ b/src/test/obj_log_get_treshold/TESTS.py @@ -0,0 +1,27 @@ +#!../env.py +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation +# + + +import testframework as t +from testframework import granularity as g + + +@g.require_granularity(g.ANY) +# The 'debug' build is chosen arbitrarily to ensure these tests are run only +# once. No dynamic libraries are used nor .static_* builds are available. +@t.require_build('debug') +class OBJ_LOG(t.BaseTest): + test_type = t.Short + + def run(self, ctx): + ctx.exec('obj_log_get_treshold', self.test_case) + + +class TEST0(OBJ_LOG): + test_case = 'test_log_get_treshold' + + +class TEST1(OBJ_LOG): + test_case = 'test_log_get_treshold_EAGAIN' diff --git a/src/test/obj_log_get_treshold/obj_log_get_treshold.c b/src/test/obj_log_get_treshold/obj_log_get_treshold.c new file mode 100644 index 00000000000..3dcf79707f5 --- /dev/null +++ b/src/test/obj_log_get_treshold/obj_log_get_treshold.c @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* Copyright 2024, Intel Corporation */ + +/* + * obj_log_get_treshold.c -- unit test for pmemobj_log_get_treshold + */ + +#include "unittest.h" +#include "log_internal.h" +#include "libpmemobj/log.h" + +#define NO_ARGS_CONSUMED 0 + +#define VALIDATED_CALL 127 +#define CALLED (VALIDATED_CALL + 1) + +static enum core_log_threshold core_tresholds[] = { + CORE_LOG_THRESHOLD, + CORE_LOG_THRESHOLD_AUX +}; + +static enum core_log_level core_levels[] = { + CORE_LOG_LEVEL_HARK, + CORE_LOG_LEVEL_FATAL, + CORE_LOG_LEVEL_ERROR, + CORE_LOG_LEVEL_WARNING, + CORE_LOG_LEVEL_NOTICE, + CORE_LOG_LEVEL_INFO, + CORE_LOG_LEVEL_DEBUG +}; + +/* Mock */ +static struct { + enum core_log_threshold exp_threshold; + enum core_log_level level; + int ret; +} Core_log_get_treshold; + +FUNC_MOCK(core_log_get_threshold, int, enum core_log_threshold threshold, + enum core_log_level *level) + FUNC_MOCK_RUN(VALIDATED_CALL) { + UT_ASSERTeq(threshold, Core_log_get_treshold.exp_threshold); + if (Core_log_get_treshold.ret == 0) + *level = Core_log_get_treshold.level; + return Core_log_get_treshold.ret; + } +FUNC_MOCK_RUN_DEFAULT { + return _FUNC_REAL(core_log_get_threshold)(threshold, level); +} +FUNC_MOCK_END + +/* Helper */ +static int +test_log_get_treshold_helper(int error) +{ + errno = 0; + Core_log_get_treshold.ret = error == NO_ERRNO ? 0 : error; + for (enum pmemobj_log_threshold treshold = PMEMOBJ_LOG_THRESHOLD; + treshold <= PMEMOBJ_LOG_THRESHOLD_AUX; treshold++) { + Core_log_get_treshold.exp_threshold = core_tresholds[treshold]; + for (enum pmemobj_log_level exp_level = PMEMOBJ_LOG_LEVEL_HARK; + exp_level <= PMEMOBJ_LOG_LEVEL_DEBUG; exp_level++) { + enum pmemobj_log_level level; + Core_log_get_treshold.level = core_levels[exp_level]; + FUNC_MOCK_RCOUNTER_SET(core_log_get_threshold, + VALIDATED_CALL); + int ret = pmemobj_log_get_threshold(treshold, &level); + if (error == NO_ERRNO) { + UT_ASSERTeq(ret, 0); + UT_ASSERTeq(level, exp_level); + } else { + UT_ASSERTeq(ret, 1); + UT_ASSERTeq(errno, error); + } + UT_ASSERTeq(RCOUNTER(core_log_get_threshold), CALLED); + /* no need to test the error path for all values */ + if (error != NO_ERRNO) + return NO_ARGS_CONSUMED; + } + } + return NO_ARGS_CONSUMED; +} + +/* Tests */ +/* + * Check: + * - if core_log_get_treshold is called with proper arguments + * - if pmemobj_log_get_treshold return 0 (no error) + * - if each PMEMOBJ_LOG_LEVEL corespond to relevant CORE_LOG_LEVEL + * - no errno is set + */ +static int +test_log_get_treshold(const struct test_case *tc, int argc, char *argv[]) +{ + return test_log_get_treshold_helper(NO_ERRNO); +} + +/* Check pmemobj_log_get_threshold EAGAIN error handling. */ +static int +test_log_get_treshold_EAGAIN(const struct test_case *tc, int argc, char *argv[]) +{ + return test_log_get_treshold_helper(EAGAIN); +} + +static struct test_case test_cases[] = { + TEST_CASE(test_log_get_treshold), + TEST_CASE(test_log_get_treshold_EAGAIN), +}; + +int +main(int argc, char *argv[]) +{ + START(argc, argv, "obj_log_get_treshold"); + TEST_CASE_PROCESS(argc, argv, test_cases, ARRAY_SIZE(test_cases)); + DONE(NULL); +} diff --git a/src/test/obj_log_set_function/.gitignore b/src/test/obj_log_set_function/.gitignore new file mode 100644 index 00000000000..4d9074233de --- /dev/null +++ b/src/test/obj_log_set_function/.gitignore @@ -0,0 +1 @@ +obj_log_set_function diff --git a/src/test/obj_log_set_function/Makefile b/src/test/obj_log_set_function/Makefile new file mode 100644 index 00000000000..f3a26da93da --- /dev/null +++ b/src/test/obj_log_set_function/Makefile @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation + +TARGET = obj_log_set_function +OBJS = obj_log_set_function.o + +BUILD_STATIC_DEBUG=n +BUILD_STATIC_NONDEBUG=n + +# required for proper mock integration +LIBPMEMOBJ=internal-debug + +include ../Makefile.inc +LDFLAGS += $(call extract_funcs, obj_log_set_function.c) diff --git a/src/test/obj_log_set_function/TESTS.py b/src/test/obj_log_set_function/TESTS.py new file mode 100755 index 00000000000..7d59355dd63 --- /dev/null +++ b/src/test/obj_log_set_function/TESTS.py @@ -0,0 +1,27 @@ +#!../env.py +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation +# + + +import testframework as t +from testframework import granularity as g + + +@g.require_granularity(g.ANY) +# The 'debug' build is chosen arbitrarily to ensure these tests are run only +# once. No dynamic libraries are used nor .static_* builds are available. +@t.require_build('debug') +class OBJ_LOG(t.BaseTest): + test_type = t.Short + + def run(self, ctx): + ctx.exec('obj_log_set_function', self.test_case) + + +class TEST0(OBJ_LOG): + test_case = 'test_log_set_function' + + +class TEST1(OBJ_LOG): + test_case = 'test_log_set_function_EAGAIN' diff --git a/src/test/obj_log_set_function/obj_log_set_function.c b/src/test/obj_log_set_function/obj_log_set_function.c new file mode 100644 index 00000000000..bf95b03f690 --- /dev/null +++ b/src/test/obj_log_set_function/obj_log_set_function.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* Copyright 2024, Intel Corporation */ + +/* + * obj_log_set_function.c -- unit test for pmemobj_log_set_function + */ + +#include "unittest.h" +#include "log_internal.h" +#include "libpmemobj/log.h" + +#define NO_ARGS_CONSUMED 0 + +#define VALIDATED_CALL 127 +#define CALLED (VALIDATED_CALL + 1) + +#define PMEMOBJ_LOG_CUSTOM_FUNCTION_MOCK ((pmemobj_log_function *) 0xA1C5D68F) + +/* Mock */ +static struct { + int ret; +} Core_log_set_function; + +FUNC_MOCK(core_log_set_function, int, core_log_function *log_function) + FUNC_MOCK_RUN(VALIDATED_CALL) { + UT_ASSERTeq((void *)log_function, + (void *)PMEMOBJ_LOG_CUSTOM_FUNCTION_MOCK); + return Core_log_set_function.ret; + } +FUNC_MOCK_RUN_DEFAULT { + return _FUNC_REAL(core_log_set_function)(log_function); +} +FUNC_MOCK_END + +/* Helper */ +static int +test_log_set_function_helper(int error) +{ + errno = 0; + Core_log_set_function.ret = error == NO_ERRNO ? 0 : error; + FUNC_MOCK_RCOUNTER_SET(core_log_set_function, VALIDATED_CALL); + int ret = pmemobj_log_set_function(PMEMOBJ_LOG_CUSTOM_FUNCTION_MOCK); + if (error == NO_ERRNO) { + UT_ASSERTeq(ret, 0); + } else { + UT_ASSERTeq(ret, 1); + UT_ASSERTeq(errno, error); + } + UT_ASSERTeq(RCOUNTER(core_log_set_function), CALLED); + + return NO_ARGS_CONSUMED; +} + +/* Tests */ +/* + * Check: + * - if core_log_set_function is called with proper argument + * - if pmemobj_log_set_function return 0 (no error) + * - no errno is set + */ +static int +test_log_set_function(const struct test_case *tc, int argc, char *argv[]) +{ + return test_log_set_function_helper(NO_ERRNO); +} + +/* + * core_log_set_function() with EAGAIN error + * Check: + * - if core_log_set_function is called with proper argument + * - if pmemobj_log_set_function return 1 (error via errno) + * - errno is set to EAGAIN + */ +static int +test_log_set_function_EAGAIN(const struct test_case *tc, int argc, char *argv[]) +{ + return test_log_set_function_helper(EAGAIN); +} + +static struct test_case test_cases[] = { + TEST_CASE(test_log_set_function), + TEST_CASE(test_log_set_function_EAGAIN), +}; + +int +main(int argc, char *argv[]) +{ + START(argc, argv, "obj_log_set_function"); + TEST_CASE_PROCESS(argc, argv, test_cases, ARRAY_SIZE(test_cases)); + DONE(NULL); +} diff --git a/src/test/obj_log_set_treshold/.gitignore b/src/test/obj_log_set_treshold/.gitignore new file mode 100644 index 00000000000..bc77b806407 --- /dev/null +++ b/src/test/obj_log_set_treshold/.gitignore @@ -0,0 +1 @@ +obj_log_set_treshold diff --git a/src/test/obj_log_set_treshold/Makefile b/src/test/obj_log_set_treshold/Makefile new file mode 100644 index 00000000000..d36f662524a --- /dev/null +++ b/src/test/obj_log_set_treshold/Makefile @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation + +TARGET = obj_log_set_treshold +OBJS = obj_log_set_treshold.o + +BUILD_STATIC_DEBUG=n +BUILD_STATIC_NONDEBUG=n + +# required for proper mock integration +LIBPMEMOBJ=internal-debug + +include ../Makefile.inc +LDFLAGS += $(call extract_funcs, obj_log_set_treshold.c) diff --git a/src/test/obj_log_set_treshold/TESTS.py b/src/test/obj_log_set_treshold/TESTS.py new file mode 100755 index 00000000000..5d9b2416f83 --- /dev/null +++ b/src/test/obj_log_set_treshold/TESTS.py @@ -0,0 +1,31 @@ +#!../env.py +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation +# + + +import testframework as t +from testframework import granularity as g + + +@g.require_granularity(g.ANY) +# The 'debug' build is chosen arbitrarily to ensure these tests are run only +# once. No dynamic libraries are used nor .static_* builds are available. +@t.require_build('debug') +class OBJ_LOG(t.BaseTest): + test_type = t.Short + + def run(self, ctx): + ctx.exec('obj_log_set_treshold', self.test_case) + + +class TEST0(OBJ_LOG): + test_case = 'test_log_set_treshold' + + +class TEST1(OBJ_LOG): + test_case = 'test_log_set_treshold_EAGAIN' + + +class TEST2(OBJ_LOG): + test_case = 'test_log_set_treshold_EINVAL' diff --git a/src/test/obj_log_set_treshold/obj_log_set_treshold.c b/src/test/obj_log_set_treshold/obj_log_set_treshold.c new file mode 100644 index 00000000000..4f9aeec3ed3 --- /dev/null +++ b/src/test/obj_log_set_treshold/obj_log_set_treshold.c @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* Copyright 2024, Intel Corporation */ + +/* + * obj_log_set_treshold.c -- unit test for pmemobj_log_set_treshold + */ + +#include "unittest.h" +#include "log_internal.h" +#include "libpmemobj/log.h" + +#define NO_ARGS_CONSUMED 0 + +#define VALIDATED_CALL 127 +#define CALLED (VALIDATED_CALL + 1) + +static enum core_log_threshold core_tresholds[] = { + CORE_LOG_THRESHOLD, + CORE_LOG_THRESHOLD_AUX +}; + +static enum core_log_level core_levels[] = { + CORE_LOG_LEVEL_HARK, + CORE_LOG_LEVEL_FATAL, + CORE_LOG_LEVEL_ERROR, + CORE_LOG_LEVEL_WARNING, + CORE_LOG_LEVEL_NOTICE, + CORE_LOG_LEVEL_INFO, + CORE_LOG_LEVEL_DEBUG +}; + +/* Mock */ +static struct { + enum core_log_threshold exp_threshold; + enum core_log_level exp_level; + int ret; +} Core_log_set_treshold; + +FUNC_MOCK(core_log_set_threshold, int, enum core_log_threshold threshold, + enum core_log_level level) + FUNC_MOCK_RUN(VALIDATED_CALL) { + UT_ASSERTeq(threshold, Core_log_set_treshold.exp_threshold); + UT_ASSERTeq(level, Core_log_set_treshold.exp_level); + return Core_log_set_treshold.ret; + } +FUNC_MOCK_RUN_DEFAULT { + return _FUNC_REAL(core_log_set_threshold)(threshold, level); +} +FUNC_MOCK_END + +/* Helper */ +static int +test_log_set_treshold_helper(int error) +{ + errno = 0; + Core_log_set_treshold.ret = error == NO_ERRNO ? 0 : error; + for (enum pmemobj_log_threshold treshold = PMEMOBJ_LOG_THRESHOLD; + treshold <= PMEMOBJ_LOG_THRESHOLD_AUX; treshold++) { + Core_log_set_treshold.exp_threshold = core_tresholds[treshold]; + for (enum pmemobj_log_level level = PMEMOBJ_LOG_LEVEL_HARK; + level <= PMEMOBJ_LOG_LEVEL_DEBUG; level++) { + Core_log_set_treshold.exp_level = core_levels[level]; + FUNC_MOCK_RCOUNTER_SET(core_log_set_threshold, + VALIDATED_CALL); + int ret = pmemobj_log_set_threshold(treshold, level); + if (error == NO_ERRNO) { + UT_ASSERTeq(ret, 0); + } else { + UT_ASSERTeq(ret, 1); + UT_ASSERTeq(errno, error); + } + UT_ASSERTeq(RCOUNTER(core_log_set_threshold), CALLED); + /* no need to test the error path for all values */ + if (error != NO_ERRNO) + return NO_ARGS_CONSUMED; + } + } + return NO_ARGS_CONSUMED; +} + +/* Tests */ +/* + * Check: + * - if core_log_set_treshold is called with proper arguments + * - if pmemobj_log_set_treshold return 0 (no error) + * - if each PMEMOBJ_LOG_LEVEL corespond to relevant CORE_LOG_LEVEL + * - no errno is set + */ +static int +test_log_set_treshold(const struct test_case *tc, int argc, char *argv[]) +{ + return test_log_set_treshold_helper(NO_ERRNO); +} + +/* Check pmemobj_log_set_threshold EAGAIN error handling. */ +static int +test_log_set_treshold_EAGAIN(const struct test_case *tc, int argc, char *argv[]) +{ + return test_log_set_treshold_helper(EAGAIN); +} + +/* Check pmemobj_log_set_threshold EINVAL error handling. */ +static int +test_log_set_treshold_EINVAL(const struct test_case *tc, int argc, char *argv[]) +{ + return test_log_set_treshold_helper(EINVAL); +} + +static struct test_case test_cases[] = { + TEST_CASE(test_log_set_treshold), + TEST_CASE(test_log_set_treshold_EAGAIN), + TEST_CASE(test_log_set_treshold_EINVAL), +}; + +int +main(int argc, char *argv[]) +{ + START(argc, argv, "obj_log_set_treshold"); + TEST_CASE_PROCESS(argc, argv, test_cases, ARRAY_SIZE(test_cases)); + DONE(NULL); +} diff --git a/src/test/obj_pool_open_mt/TESTS.py b/src/test/obj_pool_open_mt/TESTS.py index 64a73239695..e0670c69d80 100644 --- a/src/test/obj_pool_open_mt/TESTS.py +++ b/src/test/obj_pool_open_mt/TESTS.py @@ -1,12 +1,12 @@ #!../env.py # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2021, Intel Corporation +# Copyright 2021-2024, Intel Corporation # import testframework as t -class BASE(t.BaseTest): +class BASE(t.Test): test_type = t.Medium niter = 2 diff --git a/src/test/obj_tx_add_range/TESTS.py b/src/test/obj_tx_add_range/TESTS.py index 9c8ce14f339..4a22c3220a8 100755 --- a/src/test/obj_tx_add_range/TESTS.py +++ b/src/test/obj_tx_add_range/TESTS.py @@ -1,6 +1,6 @@ #!../env.py # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2019-2020, Intel Corporation +# Copyright 2019-2024, Intel Corporation """unit tests for pmemobj_tx_add_range and pmemobj_tx_xadd_range""" diff --git a/src/test/obj_tx_add_range_direct/TESTS.py b/src/test/obj_tx_add_range_direct/TESTS.py index f1482d9bf97..b16aeb4127e 100755 --- a/src/test/obj_tx_add_range_direct/TESTS.py +++ b/src/test/obj_tx_add_range_direct/TESTS.py @@ -1,6 +1,6 @@ #!../env.py # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2019-2020, Intel Corporation +# Copyright 2019-2024, Intel Corporation """ unit tests for pmemobj_tx_add_range_direct diff --git a/src/test/obj_tx_locks/TEST1 b/src/test/obj_tx_locks/TEST1 index 517832d1bb5..f0bbae0dedc 100755 --- a/src/test/obj_tx_locks/TEST1 +++ b/src/test/obj_tx_locks/TEST1 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2015-2019, Intel Corporation +# Copyright 2015-2024, Intel Corporation # # src/test/obj_tx_locks/TEST1 -- unit test for transaction locks @@ -21,6 +21,6 @@ require_valgrind 3.10 configure_valgrind drd force-enable setup -expect_normal_exit ./obj_tx_locks$EXESUFFIX $DIR/testfile1 m +expect_normal_exit ./obj_tx_locks$EXESUFFIX $DIR/testfile1 m 2>/dev/null pass diff --git a/src/test/obj_tx_user_data/TESTS.py b/src/test/obj_tx_user_data/TESTS.py index 3c2e11d2d88..c9c4fc6bd77 100755 --- a/src/test/obj_tx_user_data/TESTS.py +++ b/src/test/obj_tx_user_data/TESTS.py @@ -1,13 +1,13 @@ #!../env.py # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2019-2020, Intel Corporation +# Copyright 2019-2024, Intel Corporation # import testframework as t -class TEST0(t.BaseTest): +class TEST0(t.Test): test_type = t.Short def run(self, ctx): diff --git a/src/test/out_err/out0.log.match b/src/test/out_err/out0.log.match index 506ea5d3997..7da50af156a 100644 --- a/src/test/out_err/out0.log.match +++ b/src/test/out_err/out0.log.match @@ -4,6 +4,4 @@ ERR #1 $(OPT)ERR #2: Success $(OPX)ERR #2: No error: 0 ERR #3: Invalid argument -ERR1: Bad file descriptor:1234 -ERR2: Bad file descriptor:1234 out_err$(nW)TEST0: DONE diff --git a/src/test/out_err/out_err.c b/src/test/out_err/out_err.c index f97ed7ff9ef..d1b91a4e607 100644 --- a/src/test/out_err/out_err.c +++ b/src/test/out_err/out_err.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2014-2023, Intel Corporation */ +/* Copyright 2014-2024, Intel Corporation */ /* * traces.c -- unit test for traces @@ -19,7 +19,6 @@ int main(int argc, char *argv[]) { - char buff[UT_MAX_ERR_MSG]; START(argc, argv, "out_err"); @@ -28,28 +27,16 @@ main(int argc, char *argv[]) MAJOR_VERSION, MINOR_VERSION); errno = 0; - ERR("ERR #%d", 1); - UT_OUT("%s", out_get_errormsg()); + ERR_WO_ERRNO("ERR #%d", 1); + UT_OUT("%s", last_error_msg_get()); errno = 0; - ERR("!ERR #%d", 2); - UT_OUT("%s", out_get_errormsg()); + ERR_W_ERRNO("ERR #%d", 2); + UT_OUT("%s", last_error_msg_get()); errno = EINVAL; - ERR("!ERR #%d", 3); - UT_OUT("%s", out_get_errormsg()); - - errno = EBADF; - strerror_r(errno, buff, UT_MAX_ERR_MSG); - out_err(__FILE__, 100, __func__, - "ERR1: %s:%d", buff, 1234); - UT_OUT("%s", out_get_errormsg()); - - errno = EBADF; - strerror_r(errno, buff, UT_MAX_ERR_MSG); - out_err(NULL, 0, NULL, - "ERR2: %s:%d", buff, 1234); - UT_OUT("%s", out_get_errormsg()); + ERR_W_ERRNO("ERR #%d", 3); + UT_OUT("%s", last_error_msg_get()); /* Cleanup */ common_fini(); diff --git a/src/test/out_err/traces0.log.match b/src/test/out_err/traces0.log.match index e49c59d1fd7..b9b09809d4f 100644 --- a/src/test/out_err/traces0.log.match +++ b/src/test/out_err/traces0.log.match @@ -1,15 +1,13 @@ +: <1> [$(*)]$(W)src version: $(nW) +$(OPT): <1> [$(*)]$(W)compiled with support for shutdown state +$(OPT): <1> [$(*)]$(W)compiled with libndctl 63+ : <1> [out.c:$(N) out_init]$(W)pid $(N): program: $(nW) : <1> [out.c:$(N) out_init]$(W)trace version 1.0 -: <1> [out.c:$(N) out_init]$(W)src version: $(nW) $(OPT): <1> [out.c:$(N) out_init]$(W)compiled with support for Valgrind pmemcheck $(OPT): <1> [out.c:$(N) out_init]$(W)compiled with support for Valgrind helgrind $(OPT): <1> [out.c:$(N) out_init]$(W)compiled with support for Valgrind memcheck $(OPT): <1> [out.c:$(N) out_init]$(W)compiled with support for Valgrind drd -$(OPT): <1> [out.c:$(N) out_init]$(W)compiled with support for shutdown state -$(OPT): <1> [out.c:$(N) out_init]$(W)compiled with libndctl 63+ : <1> [out_err$(nW).c:$(N) $(nW)main]$(W)ERR #1 $(OPT): <1> [out_err$(nW).c:$(N) $(nW)main]$(W)ERR #2: Success $(OPX): <1> [out_err$(nW).c:$(N) $(nW)main]$(W)ERR #2: No error: 0 : <1> [out_err$(nW).c:$(N) $(nW)main]$(W)ERR #3: Invalid argument -: <1> [out_err$(nW).c:$(N) $(nW)main]$(W)ERR1: Bad file descriptor:1234 -ERR2: Bad file descriptor:1234 diff --git a/src/test/out_err_mt/TEST1 b/src/test/out_err_mt/TEST1 index f1f557f211b..81f09de12c9 100755 --- a/src/test/out_err_mt/TEST1 +++ b/src/test/out_err_mt/TEST1 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2015-2023, Intel Corporation +# Copyright 2015-2024, Intel Corporation # # @@ -26,7 +26,7 @@ unset PMEM_LOG_FILE unset PMEMOBJ_LOG_FILE unset PMEMPOOL_LOG_FILE -expect_normal_exit ./out_err_mt$EXESUFFIX $DIR/testfile1 +expect_normal_exit ./out_err_mt$EXESUFFIX $DIR/testfile1 2>/dev/null check diff --git a/src/test/out_err_mt/TEST2 b/src/test/out_err_mt/TEST2 index 83bac1d3e38..fca512776bc 100755 --- a/src/test/out_err_mt/TEST2 +++ b/src/test/out_err_mt/TEST2 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2015-2023, Intel Corporation +# Copyright 2015-2024, Intel Corporation # # @@ -24,7 +24,7 @@ unset PMEMOBJ_LOG_LEVEL unset PMEM_LOG_FILE unset PMEMOBJ_LOG_FILE -expect_normal_exit ./out_err_mt$EXESUFFIX $DIR/testfile1 +expect_normal_exit ./out_err_mt$EXESUFFIX $DIR/testfile1 2>/dev/null check diff --git a/src/test/pmem2_granularity_detection/TESTS.py b/src/test/pmem2_granularity_detection/TESTS.py index e446154c5d2..453880ae434 100755 --- a/src/test/pmem2_granularity_detection/TESTS.py +++ b/src/test/pmem2_granularity_detection/TESTS.py @@ -1,6 +1,6 @@ #!../env.py # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2019-2020, Intel Corporation +# Copyright 2019-2024, Intel Corporation # @@ -10,7 +10,7 @@ @g.require_granularity(g.ANY) -class PMEM2_CONFIG(t.BaseTest): +class PMEM2_CONFIG(t.Test): test_type = t.Short diff --git a/src/test/pmem2_perror/pmem2_perror.c b/src/test/pmem2_perror/pmem2_perror.c index b21f53c3c47..45cb08b3a9d 100644 --- a/src/test/pmem2_perror/pmem2_perror.c +++ b/src/test/pmem2_perror/pmem2_perror.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2020-2023, Intel Corporation */ +/* Copyright 2020-2024, Intel Corporation */ /* * pmem2_perror.c -- pmem2_perror unittests @@ -59,7 +59,7 @@ test_fail_system_func_simple(const struct test_case *tc, int argc, char *argv[]) /* "randomly" chosen function to be failed */ int ret = os_open("XXX", O_RDONLY); UT_ASSERTeq(ret, -1); - ERR("!open"); + ERR_W_ERRNO("open"); pmem2_perror("test"); @@ -76,7 +76,7 @@ test_fail_system_func_format(const struct test_case *tc, int argc, char *argv[]) /* "randomly" chosen function to be failed */ int ret = os_open("XXX", O_RDONLY); UT_ASSERTeq(ret, -1); - ERR("!open"); + ERR_W_ERRNO("open"); pmem2_perror("test %d", 123); @@ -98,7 +98,10 @@ test_fail_pmem2_syscall_simple(const struct test_case *tc, src.value.fd = -1; /* "randomly" chosen function to be failed */ - int ret = pmem2_source_size(&src, &size); +#ifdef DEBUG /* variables required for ASSERTs below */ + int ret = +#endif + pmem2_source_size(&src, &size); ASSERTne(ret, 0); pmem2_perror("test"); @@ -121,7 +124,10 @@ test_fail_pmem2_syscall_format(const struct test_case *tc, src.value.fd = -1; /* "randomly" chosen function to be failed */ - int ret = pmem2_source_size(&src, &size); +#ifdef DEBUG /* variables required for ASSERTs below */ + int ret = +#endif + pmem2_source_size(&src, &size); ASSERTne(ret, 0); pmem2_perror("test %d", 123); diff --git a/src/test/pmem2_persist_valgrind/Makefile b/src/test/pmem2_persist_valgrind/Makefile index fff52176d4c..7afa7521e22 100644 --- a/src/test/pmem2_persist_valgrind/Makefile +++ b/src/test/pmem2_persist_valgrind/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2020, Intel Corporation +# Copyright 2020-2024, Intel Corporation # # src/test/pmem2_persist_valgrind/Makefile -- build pmem2_persist_valgrind test @@ -10,11 +10,7 @@ vpath %.c $(TOP)/src/core vpath %.c $(TOP)/src/test/unittest TARGET = pmem2_persist_valgrind -OBJS = alloc.o\ - out.o\ - pmem2_persist_valgrind.o\ - util.o\ - util_posix.o\ +OBJS = pmem2_persist_valgrind.o\ ut_pmem2_utils.o LIBPMEM2=y diff --git a/src/test/pmem2_persist_valgrind/pmem2_persist_valgrind.c b/src/test/pmem2_persist_valgrind/pmem2_persist_valgrind.c index 02d21f4f0f0..9a21e74533a 100644 --- a/src/test/pmem2_persist_valgrind/pmem2_persist_valgrind.c +++ b/src/test/pmem2_persist_valgrind/pmem2_persist_valgrind.c @@ -1,11 +1,10 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2020, Intel Corporation */ +/* Copyright 2020-2024, Intel Corporation */ /* * pmem2_persist_valgrind.c -- pmem2_persist_valgrind tests */ -#include "out.h" #include "unittest.h" #include "ut_pmem2_utils.h" @@ -208,9 +207,6 @@ int main(int argc, char *argv[]) { START(argc, argv, "pmem2_persist_valgrind"); - out_init("pmem2_persist_valgrind", "TEST_LOG_LEVEL", "TEST_LOG_FILE", 0, - 0); TEST_CASE_PROCESS(argc, argv, test_cases, NTESTS); - out_fini(); DONE(NULL); } diff --git a/src/test/pmem_is_pmem_posix/pmem_is_pmem_posix.c b/src/test/pmem_is_pmem_posix/pmem_is_pmem_posix.c index ffef2686eb7..fae84bbc5cb 100644 --- a/src/test/pmem_is_pmem_posix/pmem_is_pmem_posix.c +++ b/src/test/pmem_is_pmem_posix/pmem_is_pmem_posix.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2016-2020, Intel Corporation */ +/* Copyright 2016-2024, Intel Corporation */ /* * pmem_is_pmem_posix.c -- Posix specific unit test for pmem_is_pmem() @@ -24,7 +24,7 @@ str2type(char *str) if (strcmp(str, "MAP_SYNC") == 0) return PMEM_MAP_SYNC; - FATAL("unknown type '%s'", str); + CORE_LOG_FATAL("unknown type '%s'", str); } static int @@ -145,7 +145,7 @@ main(int argc, char *argv[]) i += do_fault_injection_split(addr, len); break; default: - FATAL("invalid op '%c'", argv[i][0]); + CORE_LOG_FATAL("invalid op '%c'", argv[i][0]); } } diff --git a/src/test/pmem_log_get_treshold/.gitignore b/src/test/pmem_log_get_treshold/.gitignore new file mode 100644 index 00000000000..39976e5d27f --- /dev/null +++ b/src/test/pmem_log_get_treshold/.gitignore @@ -0,0 +1 @@ +pmem_log_get_treshold diff --git a/src/test/pmem_log_get_treshold/Makefile b/src/test/pmem_log_get_treshold/Makefile new file mode 100644 index 00000000000..5db71427838 --- /dev/null +++ b/src/test/pmem_log_get_treshold/Makefile @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation +# + +# +# src/test/pmem_log_get_treshold/Makefile -- build pmem_log_get_treshold unit test +# + +TARGET = pmem_log_get_treshold +OBJS = pmem_log_get_treshold.o + +BUILD_STATIC_DEBUG=n +BUILD_STATIC_NONDEBUG=n + +# required for proper mock integration +LIBPMEMCOMMON=internal-debug +LIBPMEM=internal-debug + +include ../Makefile.inc +LDFLAGS += $(call extract_funcs, pmem_log_get_treshold.c) diff --git a/src/test/pmem_log_get_treshold/TESTS.py b/src/test/pmem_log_get_treshold/TESTS.py new file mode 100755 index 00000000000..c01d1556353 --- /dev/null +++ b/src/test/pmem_log_get_treshold/TESTS.py @@ -0,0 +1,27 @@ +#!../env.py +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation +# + + +import testframework as t +from testframework import granularity as g + + +@g.require_granularity(g.ANY) +# The 'debug' build is chosen arbitrarily to ensure these tests are run only +# once. No dynamic libraries are used nor .static_* builds are available. +@t.require_build('debug') +class PMEM_LOG(t.BaseTest): + test_type = t.Short + + def run(self, ctx): + ctx.exec('pmem_log_get_treshold', self.test_case) + + +class TEST0(PMEM_LOG): + test_case = 'test_log_get_treshold' + + +class TEST1(PMEM_LOG): + test_case = 'test_log_get_treshold_EAGAIN' diff --git a/src/test/pmem_log_get_treshold/pmem_log_get_treshold.c b/src/test/pmem_log_get_treshold/pmem_log_get_treshold.c new file mode 100644 index 00000000000..1f96a71359f --- /dev/null +++ b/src/test/pmem_log_get_treshold/pmem_log_get_treshold.c @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* Copyright 2024, Intel Corporation */ + +/* + * pmem_log_get_treshold.c -- unit test for pmem_log_get_treshold + */ + +#include "unittest.h" +#include "log_internal.h" +#include "libpmem.h" + +#define NO_ARGS_CONSUMED 0 + +#define VALIDATED_CALL 127 +#define CALLED (VALIDATED_CALL + 1) + +static enum core_log_threshold core_tresholds[] = { + [PMEM_LOG_THRESHOLD] = CORE_LOG_THRESHOLD, + [PMEM_LOG_THRESHOLD_AUX] = CORE_LOG_THRESHOLD_AUX +}; + +static enum core_log_level core_levels[] = { + [PMEM_LOG_LEVEL_HARK] = CORE_LOG_LEVEL_HARK, + [PMEM_LOG_LEVEL_FATAL] = CORE_LOG_LEVEL_FATAL, + [PMEM_LOG_LEVEL_ERROR] = CORE_LOG_LEVEL_ERROR, + [PMEM_LOG_LEVEL_WARNING] = CORE_LOG_LEVEL_WARNING, + [PMEM_LOG_LEVEL_NOTICE] = CORE_LOG_LEVEL_NOTICE, + [PMEM_LOG_LEVEL_INFO] = CORE_LOG_LEVEL_INFO, + [PMEM_LOG_LEVEL_DEBUG] = CORE_LOG_LEVEL_DEBUG +}; + +/* Mock */ +static struct { + enum core_log_threshold exp_threshold; + enum core_log_level level; + int ret; +} Core_log_get_treshold; + +FUNC_MOCK(core_log_get_threshold, int, enum core_log_threshold threshold, + enum core_log_level *level) + FUNC_MOCK_RUN(VALIDATED_CALL) { + UT_ASSERTeq(threshold, Core_log_get_treshold.exp_threshold); + if (Core_log_get_treshold.ret == 0) + *level = Core_log_get_treshold.level; + return Core_log_get_treshold.ret; + } +FUNC_MOCK_RUN_DEFAULT { + return _FUNC_REAL(core_log_get_threshold)(threshold, level); +} +FUNC_MOCK_END + +/* Helper */ +static int +test_log_get_treshold_helper(int error) +{ + errno = 0; + Core_log_get_treshold.ret = error == NO_ERRNO ? 0 : error; + for (enum pmem_log_threshold treshold = PMEM_LOG_THRESHOLD; + treshold <= PMEM_LOG_THRESHOLD_AUX; treshold++) { + Core_log_get_treshold.exp_threshold = core_tresholds[treshold]; + for (enum pmem_log_level exp_level = PMEM_LOG_LEVEL_HARK; + exp_level <= PMEM_LOG_LEVEL_DEBUG; exp_level++) { + enum pmem_log_level level; + Core_log_get_treshold.level = core_levels[exp_level]; + FUNC_MOCK_RCOUNTER_SET(core_log_get_threshold, + VALIDATED_CALL); + int ret = pmem_log_get_threshold(treshold, &level); + if (error == NO_ERRNO) { + UT_ASSERTeq(ret, 0); + UT_ASSERTeq(level, exp_level); + } else { + UT_ASSERTeq(ret, 1); + UT_ASSERTeq(errno, error); + } + UT_ASSERTeq(RCOUNTER(core_log_get_threshold), CALLED); + /* no need to test the error path for all values */ + if (error != NO_ERRNO) + return NO_ARGS_CONSUMED; + } + } + return NO_ARGS_CONSUMED; +} + +/* Tests */ +/* + * Check: + * - if core_log_get_treshold is called with proper arguments + * - if pmem_log_get_treshold return 0 (no error) + * - if each PMEM_LOG_LEVEL corespond to relevant CORE_LOG_LEVEL + * - no errno is set + */ +static int +test_log_get_treshold(const struct test_case *tc, int argc, char *argv[]) +{ + return test_log_get_treshold_helper(NO_ERRNO); +} + +/* Check pmem_log_get_threshold EAGAIN error handling. */ +static int +test_log_get_treshold_EAGAIN(const struct test_case *tc, int argc, char *argv[]) +{ + return test_log_get_treshold_helper(EAGAIN); +} + +static struct test_case test_cases[] = { + TEST_CASE(test_log_get_treshold), + TEST_CASE(test_log_get_treshold_EAGAIN), +}; + +int +main(int argc, char *argv[]) +{ + START(argc, argv, "pmem_log_get_treshold"); + TEST_CASE_PROCESS(argc, argv, test_cases, ARRAY_SIZE(test_cases)); + DONE(NULL); +} diff --git a/src/test/pmem_log_set_function/.gitignore b/src/test/pmem_log_set_function/.gitignore new file mode 100644 index 00000000000..ee9f2a39097 --- /dev/null +++ b/src/test/pmem_log_set_function/.gitignore @@ -0,0 +1 @@ +pmem_log_set_function diff --git a/src/test/pmem_log_set_function/Makefile b/src/test/pmem_log_set_function/Makefile new file mode 100644 index 00000000000..ac703e1e285 --- /dev/null +++ b/src/test/pmem_log_set_function/Makefile @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation + +TARGET = pmem_log_set_function +OBJS = pmem_log_set_function.o + +BUILD_STATIC_DEBUG=n +BUILD_STATIC_NONDEBUG=n + +# required for proper mock integration +LIBPMEMCOMMON=internal-debug +LIBPMEM=internal-debug + +include ../Makefile.inc +LDFLAGS += $(call extract_funcs, pmem_log_set_function.c) diff --git a/src/test/pmem_log_set_function/TESTS.py b/src/test/pmem_log_set_function/TESTS.py new file mode 100755 index 00000000000..0058a101a1a --- /dev/null +++ b/src/test/pmem_log_set_function/TESTS.py @@ -0,0 +1,27 @@ +#!../env.py +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation +# + + +import testframework as t +from testframework import granularity as g + + +@g.require_granularity(g.ANY) +# The 'debug' build is chosen arbitrarily to ensure these tests are run only +# once. No dynamic libraries are used nor .static_* builds are available. +@t.require_build('debug') +class PMEM_LOG(t.BaseTest): + test_type = t.Short + + def run(self, ctx): + ctx.exec('pmem_log_set_function', self.test_case) + + +class TEST0(PMEM_LOG): + test_case = 'test_log_set_function' + + +class TEST1(PMEM_LOG): + test_case = 'test_log_set_function_EAGAIN' diff --git a/src/test/pmem_log_set_function/pmem_log_set_function.c b/src/test/pmem_log_set_function/pmem_log_set_function.c new file mode 100644 index 00000000000..9f92d9cbd15 --- /dev/null +++ b/src/test/pmem_log_set_function/pmem_log_set_function.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* Copyright 2024, Intel Corporation */ + +/* + * pmem_log_set_function.c -- unit test for pmem_log_set_function + */ + +#include "unittest.h" +#include "log_internal.h" +#include "libpmem.h" + +#define NO_ARGS_CONSUMED 0 + +#define VALIDATED_CALL 127 +#define CALLED (VALIDATED_CALL + 1) + +#define PMEM_LOG_CUSTOM_FUNCTION_MOCK ((pmem_log_function *) 0xA1C5D68F) + +/* Mock */ +static struct { + int ret; +} Core_log_set_function; + +FUNC_MOCK(core_log_set_function, int, core_log_function *log_function) + FUNC_MOCK_RUN(VALIDATED_CALL) { + UT_ASSERTeq((void *)log_function, + (void *)PMEM_LOG_CUSTOM_FUNCTION_MOCK); + return Core_log_set_function.ret; + } +FUNC_MOCK_RUN_DEFAULT { + return _FUNC_REAL(core_log_set_function)(log_function); +} +FUNC_MOCK_END + +/* Helper */ +static int +test_log_set_function_helper(int error) +{ + errno = 0; + Core_log_set_function.ret = error == NO_ERRNO ? 0 : error; + FUNC_MOCK_RCOUNTER_SET(core_log_set_function, VALIDATED_CALL); + int ret = pmem_log_set_function(PMEM_LOG_CUSTOM_FUNCTION_MOCK); + if (error == NO_ERRNO) { + UT_ASSERTeq(ret, 0); + } else { + UT_ASSERTeq(ret, 1); + UT_ASSERTeq(errno, error); + } + UT_ASSERTeq(RCOUNTER(core_log_set_function), CALLED); + + return NO_ARGS_CONSUMED; +} + +/* Tests */ +/* + * Check: + * - if core_log_set_function is called with proper argument + * - if pmem_log_set_function return 0 (no error) + * - no errno is set + */ +static int +test_log_set_function(const struct test_case *tc, int argc, char *argv[]) +{ + return test_log_set_function_helper(NO_ERRNO); +} + +/* + * core_log_set_function() with EAGAIN error + * Check: + * - if core_log_set_function is called with proper argument + * - if pmem_log_set_function return 1 (error via errno) + * - errno is set to EAGAIN + */ +static int +test_log_set_function_EAGAIN(const struct test_case *tc, int argc, char *argv[]) +{ + return test_log_set_function_helper(EAGAIN); +} + +static struct test_case test_cases[] = { + TEST_CASE(test_log_set_function), + TEST_CASE(test_log_set_function_EAGAIN), +}; + +int +main(int argc, char *argv[]) +{ + START(argc, argv, "pmem_log_set_function"); + TEST_CASE_PROCESS(argc, argv, test_cases, ARRAY_SIZE(test_cases)); + DONE(NULL); +} diff --git a/src/test/pmem_log_set_treshold/.gitignore b/src/test/pmem_log_set_treshold/.gitignore new file mode 100644 index 00000000000..c56248dfa65 --- /dev/null +++ b/src/test/pmem_log_set_treshold/.gitignore @@ -0,0 +1 @@ +pmem_log_set_treshold diff --git a/src/test/pmem_log_set_treshold/Makefile b/src/test/pmem_log_set_treshold/Makefile new file mode 100644 index 00000000000..5e13b3cc238 --- /dev/null +++ b/src/test/pmem_log_set_treshold/Makefile @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation + +TARGET = pmem_log_set_treshold +OBJS = pmem_log_set_treshold.o + +BUILD_STATIC_DEBUG=n +BUILD_STATIC_NONDEBUG=n + +# required for proper mock integration +LIBPMEMCOMMON=internal-debug +LIBPMEM=internal-debug + +include ../Makefile.inc +LDFLAGS += $(call extract_funcs, pmem_log_set_treshold.c) diff --git a/src/test/pmem_log_set_treshold/TESTS.py b/src/test/pmem_log_set_treshold/TESTS.py new file mode 100755 index 00000000000..781acaa44a2 --- /dev/null +++ b/src/test/pmem_log_set_treshold/TESTS.py @@ -0,0 +1,31 @@ +#!../env.py +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation +# + + +import testframework as t +from testframework import granularity as g + + +@g.require_granularity(g.ANY) +# The 'debug' build is chosen arbitrarily to ensure these tests are run only +# once. No dynamic libraries are used nor .static_* builds are available. +@t.require_build('debug') +class PMEM_LOG(t.BaseTest): + test_type = t.Short + + def run(self, ctx): + ctx.exec('pmem_log_set_treshold', self.test_case) + + +class TEST0(PMEM_LOG): + test_case = 'test_log_set_treshold' + + +class TEST1(PMEM_LOG): + test_case = 'test_log_set_treshold_EAGAIN' + + +class TEST2(PMEM_LOG): + test_case = 'test_log_set_treshold_EINVAL' diff --git a/src/test/pmem_log_set_treshold/pmem_log_set_treshold.c b/src/test/pmem_log_set_treshold/pmem_log_set_treshold.c new file mode 100644 index 00000000000..887ac02289a --- /dev/null +++ b/src/test/pmem_log_set_treshold/pmem_log_set_treshold.c @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* Copyright 2024, Intel Corporation */ + +/* + * pmem_log_set_treshold.c -- unit test for pmem_log_set_treshold + */ + +#include "unittest.h" +#include "log_internal.h" +#include "libpmem.h" + +#define NO_ARGS_CONSUMED 0 + +#define VALIDATED_CALL 127 +#define CALLED (VALIDATED_CALL + 1) + +static enum core_log_threshold core_tresholds[] = { + [PMEM_LOG_THRESHOLD] = CORE_LOG_THRESHOLD, + [PMEM_LOG_THRESHOLD_AUX] = CORE_LOG_THRESHOLD_AUX +}; + +static enum core_log_level core_levels[] = { + [PMEM_LOG_LEVEL_HARK] = CORE_LOG_LEVEL_HARK, + [PMEM_LOG_LEVEL_FATAL] = CORE_LOG_LEVEL_FATAL, + [PMEM_LOG_LEVEL_ERROR] = CORE_LOG_LEVEL_ERROR, + [PMEM_LOG_LEVEL_WARNING] = CORE_LOG_LEVEL_WARNING, + [PMEM_LOG_LEVEL_NOTICE] = CORE_LOG_LEVEL_NOTICE, + [PMEM_LOG_LEVEL_INFO] = CORE_LOG_LEVEL_INFO, + [PMEM_LOG_LEVEL_DEBUG] = CORE_LOG_LEVEL_DEBUG +}; + +/* Mock */ +static struct { + enum core_log_threshold exp_threshold; + enum core_log_level exp_level; + int ret; +} Core_log_set_treshold; + +FUNC_MOCK(core_log_set_threshold, int, enum core_log_threshold threshold, + enum core_log_level level) + FUNC_MOCK_RUN(VALIDATED_CALL) { + UT_ASSERTeq(threshold, Core_log_set_treshold.exp_threshold); + UT_ASSERTeq(level, Core_log_set_treshold.exp_level); + return Core_log_set_treshold.ret; + } +FUNC_MOCK_RUN_DEFAULT { + return _FUNC_REAL(core_log_set_threshold)(threshold, level); +} +FUNC_MOCK_END + +/* Helper */ +static int +test_log_set_treshold_helper(int error) +{ + errno = 0; + Core_log_set_treshold.ret = error == NO_ERRNO ? 0 : error; + for (enum pmem_log_threshold treshold = PMEM_LOG_THRESHOLD; + treshold <= PMEM_LOG_THRESHOLD_AUX; treshold++) { + Core_log_set_treshold.exp_threshold = core_tresholds[treshold]; + for (enum pmem_log_level level = PMEM_LOG_LEVEL_HARK; + level <= PMEM_LOG_LEVEL_DEBUG; level++) { + Core_log_set_treshold.exp_level = core_levels[level]; + FUNC_MOCK_RCOUNTER_SET(core_log_set_threshold, + VALIDATED_CALL); + int ret = pmem_log_set_threshold(treshold, level); + if (error == NO_ERRNO) { + UT_ASSERTeq(ret, 0); + } else { + UT_ASSERTeq(ret, 1); + UT_ASSERTeq(errno, error); + } + UT_ASSERTeq(RCOUNTER(core_log_set_threshold), CALLED); + /* no need to test the error path for all values */ + if (error != NO_ERRNO) + return NO_ARGS_CONSUMED; + } + } + return NO_ARGS_CONSUMED; +} + +/* Tests */ +/* + * Check: + * - if core_log_set_treshold is called with proper arguments + * - if pmempmem_log_set_treshold return 0 (no error) + * - if each PMEM_LOG_LEVEL corespond to relevant CORE_LOG_LEVEL + * - no errno is set + */ +static int +test_log_set_treshold(const struct test_case *tc, int argc, char *argv[]) +{ + return test_log_set_treshold_helper(NO_ERRNO); +} + +/* Check pmem_log_set_threshold EAGAIN error handling. */ +static int +test_log_set_treshold_EAGAIN(const struct test_case *tc, int argc, char *argv[]) +{ + return test_log_set_treshold_helper(EAGAIN); +} + +/* Check pmem_log_set_threshold EINVAL error handling. */ +static int +test_log_set_treshold_EINVAL(const struct test_case *tc, int argc, char *argv[]) +{ + return test_log_set_treshold_helper(EINVAL); +} + +static struct test_case test_cases[] = { + TEST_CASE(test_log_set_treshold), + TEST_CASE(test_log_set_treshold_EAGAIN), + TEST_CASE(test_log_set_treshold_EINVAL), +}; + +int +main(int argc, char *argv[]) +{ + START(argc, argv, "pmem_log_set_treshold"); + TEST_CASE_PROCESS(argc, argv, test_cases, ARRAY_SIZE(test_cases)); + DONE(NULL); +} diff --git a/src/test/pmempool_check/common.sh b/src/test/pmempool_check/common.sh index f6ead577006..38e91d1d3da 100644 --- a/src/test/pmempool_check/common.sh +++ b/src/test/pmempool_check/common.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2018-2020, Intel Corporation +# Copyright 2018-2024, Intel Corporation # # # pmempool_check/common.sh -- checking pools helpers @@ -37,7 +37,7 @@ function pmempool_check_sds_init() { local conf="sds.at_create=1" fi - PMEMOBJ_CONF="${PMEMOBJ_CONF}$conf;" + PMEMOBJ_CONF="${PMEMOBJ_CONF};$conf;" expect_normal_exit $PMEMPOOL$EXESUFFIX create --layout=$LAYOUT obj $POOLSET } diff --git a/src/test/pmempool_feature/TEST14 b/src/test/pmempool_feature/TEST14 index 2dbcf0c5cd0..c96bb490d4e 100755 --- a/src/test/pmempool_feature/TEST14 +++ b/src/test/pmempool_feature/TEST14 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2018-2019, Intel Corporation +# Copyright 2018-2024, Intel Corporation # # # pmempool_feature/TEST14 -- unit test for SHUTDOWN_STATE + ctl @@ -15,7 +15,7 @@ require_sds $PMEMPOOL$EXESUFFIX setup . ./common.sh -PMEMOBJ_CONF="${PMEMOBJ_CONF}sds.at_create=0" +PMEMOBJ_CONF="${PMEMOBJ_CONF};sds.at_create=0" pmempool_feature_create_poolset "no_dax_device" pmempool_feature_query SHUTDOWN_STATE normal diff --git a/src/test/pmempool_feature/TEST15 b/src/test/pmempool_feature/TEST15 index 61b8e490b91..01aa8d10dba 100755 --- a/src/test/pmempool_feature/TEST15 +++ b/src/test/pmempool_feature/TEST15 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2018-2019, Intel Corporation +# Copyright 2018-2024, Intel Corporation # # # pmempool_feature/TEST15 -- unit test for SHUTDOWN_STATE + ctl @@ -17,7 +17,7 @@ setup require_usc_permission $DIR -PMEMOBJ_CONF="${PMEMOBJ_CONF}sds.at_create=1" +PMEMOBJ_CONF="${PMEMOBJ_CONF};sds.at_create=1" pmempool_feature_create_poolset "no_dax_device" pmempool_feature_query SHUTDOWN_STATE normal diff --git a/src/test/pmempool_feature/grep0.log.match b/src/test/pmempool_feature/grep0.log.match index 2d1f606a373..8db2004f0e0 100644 --- a/src/test/pmempool_feature/grep0.log.match +++ b/src/test/pmempool_feature/grep0.log.match @@ -1 +1,3 @@ +$(OPT)$(*)*ERROR* feature.c: $(N): unsupported_feature: unsupported feature: SINGLEHDR +$(OPT)$(*)*ERROR* feature.c: $(N): unsupported_feature: unsupported feature: SINGLEHDR query SINGLEHDR result is 0 diff --git a/src/test/pmempool_feature/grep1.log.match b/src/test/pmempool_feature/grep1.log.match index 7a755266bd1..9f10940c5b3 100644 --- a/src/test/pmempool_feature/grep1.log.match +++ b/src/test/pmempool_feature/grep1.log.match @@ -1,4 +1,5 @@ query CKSUM_2K result is 1 +$(OPT)$(*) *ERROR* feature.c: $(N): require_other_feature_is: disable SHUTDOWN_STATE prior to disabling CKSUM_2K query CKSUM_2K result is 1 query SHUTDOWN_STATE result is 0 query CKSUM_2K result is 0 diff --git a/src/test/pmempool_feature/grep2.log.match b/src/test/pmempool_feature/grep2.log.match index 9a6fc81ec1a..b8a8a1d489a 100644 --- a/src/test/pmempool_feature/grep2.log.match +++ b/src/test/pmempool_feature/grep2.log.match @@ -1,6 +1,7 @@ $(OPT)query SHUTDOWN_STATE result is 1 query SHUTDOWN_STATE result is 0 query CKSUM_2K result is 0 +$(OPT)$(*) *ERROR* feature.c: $(N): require_other_feature_is: enable CKSUM_2K prior to enabling SHUTDOWN_STATE query SHUTDOWN_STATE result is 0 query CKSUM_2K result is 1 query SHUTDOWN_STATE result is 1 diff --git a/src/test/pmempool_info/TEST10 b/src/test/pmempool_info/TEST0 similarity index 81% rename from src/test/pmempool_info/TEST10 rename to src/test/pmempool_info/TEST0 index 07181c78f55..6d489073701 100755 --- a/src/test/pmempool_info/TEST10 +++ b/src/test/pmempool_info/TEST0 @@ -1,9 +1,9 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2014-2018, Intel Corporation +# Copyright 2014-2024, Intel Corporation # # -# pmempool_info/TEST10 -- test for info command +# pmempool_info/TEST0 -- test for info command # . ../unittest/unittest.sh diff --git a/src/test/pmempool_info/out10.log.match b/src/test/pmempool_info/out0.log.match similarity index 100% rename from src/test/pmempool_info/out10.log.match rename to src/test/pmempool_info/out0.log.match diff --git a/src/test/pmempool_info/out27.log.match b/src/test/pmempool_info/out27.log.match index 5029eeed9b3..68781c7e77a 100644 --- a/src/test/pmempool_info/out27.log.match +++ b/src/test/pmempool_info/out27.log.match @@ -23,11 +23,13 @@ $(OPT)Machine : AMD X86-64 $(OPT)Machine : Aarch64 $(OPT)Machine : RISCV $(OPX)Machine : PPC64 -Last shutdown : dirty +$(OPT)Last shutdown : dirty +$(OPX)Last shutdown : clean Checksum : $(*) [OK] PMEM OBJ Header: -Layout : pmempool$(*) +$(OPT)Layout : pmempool$(*) +$(OPX)Layout : (null) Lanes offset : $(*) Number of lanes : $(*) Heap offset : $(*) diff --git a/src/test/pmempool_sync/TEST10 b/src/test/pmempool_sync/TEST10 index 95975d11a0c..fabdba79d1d 100755 --- a/src/test/pmempool_sync/TEST10 +++ b/src/test/pmempool_sync/TEST10 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2016-2018, Intel Corporation +# Copyright 2016-2024, Intel Corporation # # # pmempool_sync/TEST10 -- test for checking pmempool sync; @@ -52,6 +52,7 @@ expect_abnormal_exit $PMEMPOOL$EXESUFFIX sync $POOLSET2 >> $LOG_TEMP 2>&1 dump_pool_info $POOLSET1 >> $LOG_TEMP mv $LOG_TEMP $LOG + check pass diff --git a/src/test/pmempool_sync/TEST11 b/src/test/pmempool_sync/TEST11 index aaa6f6e9787..890c2ae850b 100755 --- a/src/test/pmempool_sync/TEST11 +++ b/src/test/pmempool_sync/TEST11 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2016-2018, Intel Corporation +# Copyright 2016-2024, Intel Corporation # # # pmempool_sync/TEST11 -- test for checking pmempool sync @@ -62,6 +62,7 @@ expect_normal_exit $DDMAP$EXESUFFIX -o $DIR/part20 -n 10 -b 1 expect_abnormal_exit $PMEMPOOL$EXESUFFIX sync $POOLSET3 &>> $LOG_TEMP mv $LOG_TEMP $LOG + check pass diff --git a/src/test/pmempool_sync/TEST12 b/src/test/pmempool_sync/TEST12 index ab0e177442b..1b517aa2654 100755 --- a/src/test/pmempool_sync/TEST12 +++ b/src/test/pmempool_sync/TEST12 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2017-2019, Intel Corporation +# Copyright 2017-2024, Intel Corporation # # # pmempool_sync/TEST12 -- test for checking pmempool sync; @@ -45,6 +45,7 @@ expect_normal_exit $PMEMSPOIL $DIR/testfile1 pool_hdr.uuid=0000000000000000\ expect_abnormal_exit $PMEMPOOL$EXESUFFIX sync $POOLSET &>> $LOG_TEMP mv $LOG_TEMP $LOG + check pass diff --git a/src/test/pmempool_sync/TEST23 b/src/test/pmempool_sync/TEST23 index e56c748547b..a087d0d80f0 100755 --- a/src/test/pmempool_sync/TEST23 +++ b/src/test/pmempool_sync/TEST23 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2018, Intel Corporation +# Copyright 2018-2024, Intel Corporation # # # pmempool_sync/TEST23 -- test for pmempool sync @@ -64,5 +64,6 @@ expect_normal_exit $PMEMPOOL$EXESUFFIX sync $POOLSET1 >> $LOG_TEMP dump_pool_info $POOLSET1 >> $LOG_TEMP mv $LOG_TEMP $LOG + check pass diff --git a/src/test/pmempool_sync/TEST24 b/src/test/pmempool_sync/TEST24 index 4dd1e6e52c8..21fb8a3b613 100755 --- a/src/test/pmempool_sync/TEST24 +++ b/src/test/pmempool_sync/TEST24 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2018, Intel Corporation +# Copyright 2018-2024, Intel Corporation # # # pmempool_sync/TEST24 -- test for checking pmempool sync @@ -61,6 +61,7 @@ expect_normal_exit $PMEMPOOL$EXESUFFIX sync $POOLSET1 >> $LOG_TEMP dump_pool_info $POOLSET1 >> $LOG_TEMP mv $LOG_TEMP $LOG + check pass diff --git a/src/test/pmempool_sync/TEST25 b/src/test/pmempool_sync/TEST25 index e6d4d99aa53..d197bc04b71 100755 --- a/src/test/pmempool_sync/TEST25 +++ b/src/test/pmempool_sync/TEST25 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2018-2019, Intel Corporation +# Copyright 2018-2024, Intel Corporation # # # pmempool_sync/TEST25 -- test for checking pmempool sync @@ -63,6 +63,7 @@ expect_normal_exit $PMEMPOOL$EXESUFFIX sync $POOLSET1 >> $LOG_TEMP dump_pool_info $POOLSET1 >> $LOG_TEMP mv $LOG_TEMP $LOG + check pass diff --git a/src/test/pmempool_sync/TEST26 b/src/test/pmempool_sync/TEST26 index ebd4b88e26c..172f720010c 100755 --- a/src/test/pmempool_sync/TEST26 +++ b/src/test/pmempool_sync/TEST26 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2018-2023, Intel Corporation +# Copyright 2018-2024, Intel Corporation # # # pmempool_sync/TEST26 -- test for checking pmempool sync; @@ -48,6 +48,7 @@ expect_abnormal_exit $PMEMPOOL$EXESUFFIX sync $POOLSET >> $LOG_TEMP 2>&1 expect_normal_exit $PMEMPOOL$EXESUFFIX rm $POOLSET mv $LOG_TEMP $LOG + check pass diff --git a/src/test/pmempool_sync/TEST29 b/src/test/pmempool_sync/TEST29 index b2c25a46bcf..ed17b57d6c8 100755 --- a/src/test/pmempool_sync/TEST29 +++ b/src/test/pmempool_sync/TEST29 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2018-2019, Intel Corporation +# Copyright 2018-2024, Intel Corporation # # # pmempool_sync/TEST29 -- test for sync using the 'obj_verify' tool diff --git a/src/test/pmempool_sync/TEST32 b/src/test/pmempool_sync/TEST32 index ef47a4fb40f..3f00abadecc 100755 --- a/src/test/pmempool_sync/TEST32 +++ b/src/test/pmempool_sync/TEST32 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2018-2019, Intel Corporation +# Copyright 2018-2024, Intel Corporation # # # pmempool_sync/TEST32 -- test for sync command diff --git a/src/test/pmempool_sync/TEST33 b/src/test/pmempool_sync/TEST33 index 6367f92bec5..d6ec59271a5 100755 --- a/src/test/pmempool_sync/TEST33 +++ b/src/test/pmempool_sync/TEST33 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2018-2019, Intel Corporation +# Copyright 2018-2024, Intel Corporation # # # pmempool_sync/TEST33 -- test for sync command diff --git a/src/test/pmempool_sync/TEST34 b/src/test/pmempool_sync/TEST34 index d0ff494588e..72e18b4aabc 100755 --- a/src/test/pmempool_sync/TEST34 +++ b/src/test/pmempool_sync/TEST34 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2018-2019, Intel Corporation +# Copyright 2018-2024, Intel Corporation # # # pmempool_sync/TEST34 -- test for sync command diff --git a/src/test/pmempool_sync/TEST35 b/src/test/pmempool_sync/TEST35 index 2aa32823043..5a4368fea6c 100755 --- a/src/test/pmempool_sync/TEST35 +++ b/src/test/pmempool_sync/TEST35 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2018-2019, Intel Corporation +# Copyright 2018-2024, Intel Corporation # # # pmempool_sync/TEST35 -- test for sync command diff --git a/src/test/pmempool_sync/TEST36 b/src/test/pmempool_sync/TEST36 index 20e5e8ad151..3eac293e51a 100755 --- a/src/test/pmempool_sync/TEST36 +++ b/src/test/pmempool_sync/TEST36 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2018-2019, Intel Corporation +# Copyright 2018-2024, Intel Corporation # # # pmempool_sync/TEST36 -- test for sync command diff --git a/src/test/pmempool_sync/TEST37 b/src/test/pmempool_sync/TEST37 index aecdac74063..9f87982184d 100755 --- a/src/test/pmempool_sync/TEST37 +++ b/src/test/pmempool_sync/TEST37 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2018-2019, Intel Corporation +# Copyright 2018-2024, Intel Corporation # # # pmempool_sync/TEST37 -- test for sync command diff --git a/src/test/pmempool_sync/TEST42 b/src/test/pmempool_sync/TEST42 index 943fdfccac7..32272d0ee17 100755 --- a/src/test/pmempool_sync/TEST42 +++ b/src/test/pmempool_sync/TEST42 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2018-2019, Intel Corporation +# Copyright 2018-2024, Intel Corporation # # # pmempool_sync/TEST42 -- test for sync command with badblocks diff --git a/src/test/pmempool_sync/TEST43 b/src/test/pmempool_sync/TEST43 index cf095a22cf7..d46eeda96f2 100755 --- a/src/test/pmempool_sync/TEST43 +++ b/src/test/pmempool_sync/TEST43 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2018-2019, Intel Corporation +# Copyright 2018-2024, Intel Corporation # # # pmempool_sync/TEST43 -- test for sync command with badblocks diff --git a/src/test/pmempool_sync/TEST44 b/src/test/pmempool_sync/TEST44 index b3993498094..da8b2a07f17 100755 --- a/src/test/pmempool_sync/TEST44 +++ b/src/test/pmempool_sync/TEST44 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2018-2019, Intel Corporation +# Copyright 2018-2024, Intel Corporation # # # pmempool_sync/TEST44 -- test for sync command with badblocks diff --git a/src/test/pmempool_sync/TEST45 b/src/test/pmempool_sync/TEST45 index 16060d83fd6..b28b086a7e7 100755 --- a/src/test/pmempool_sync/TEST45 +++ b/src/test/pmempool_sync/TEST45 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2018-2019, Intel Corporation +# Copyright 2018-2024, Intel Corporation # # # pmempool_sync/TEST45 -- test for sync command with badblocks diff --git a/src/test/pmempool_sync/TEST46 b/src/test/pmempool_sync/TEST46 index 09f4026d4d8..6758b2e95be 100755 --- a/src/test/pmempool_sync/TEST46 +++ b/src/test/pmempool_sync/TEST46 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2018-2019, Intel Corporation +# Copyright 2018-2024, Intel Corporation # # # pmempool_sync/TEST46 -- test for sync command with badblocks diff --git a/src/test/pmempool_sync/TEST47 b/src/test/pmempool_sync/TEST47 index 05406ee4725..19f769567a6 100755 --- a/src/test/pmempool_sync/TEST47 +++ b/src/test/pmempool_sync/TEST47 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2018-2019, Intel Corporation +# Copyright 2018-2024, Intel Corporation # # # pmempool_sync/TEST47 -- test for sync command with badblocks diff --git a/src/test/pmempool_sync/TEST48 b/src/test/pmempool_sync/TEST48 index a65ae25abef..27d85005bbd 100755 --- a/src/test/pmempool_sync/TEST48 +++ b/src/test/pmempool_sync/TEST48 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2018-2019, Intel Corporation +# Copyright 2018-2024, Intel Corporation # # # pmempool_sync/TEST48 -- test for sync command with badblocks diff --git a/src/test/pmempool_sync/TEST49 b/src/test/pmempool_sync/TEST49 index d00e4b4693f..4db82bf4c2d 100755 --- a/src/test/pmempool_sync/TEST49 +++ b/src/test/pmempool_sync/TEST49 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2011-2019, Intel Corporation +# Copyright 2011-2024, Intel Corporation # # # pmempool_sync/TEST49 -- test for sync command with badblocks diff --git a/src/test/pmempool_sync/TEST50 b/src/test/pmempool_sync/TEST50 index 6735f1bc90e..963cf1cf25d 100755 --- a/src/test/pmempool_sync/TEST50 +++ b/src/test/pmempool_sync/TEST50 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2018-2019, Intel Corporation +# Copyright 2018-2024, Intel Corporation # # # pmempool_sync/TEST50 -- test for sync command with badblocks diff --git a/src/test/pmempool_sync/TEST51 b/src/test/pmempool_sync/TEST51 index 86d4225a061..5902a68634c 100755 --- a/src/test/pmempool_sync/TEST51 +++ b/src/test/pmempool_sync/TEST51 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2018-2019, Intel Corporation +# Copyright 2018-2024, Intel Corporation # # # pmempool_sync/TEST51 -- test for sync command with badblocks diff --git a/src/test/pmempool_sync/TEST52 b/src/test/pmempool_sync/TEST52 index 50cb9f48325..721eeb53487 100755 --- a/src/test/pmempool_sync/TEST52 +++ b/src/test/pmempool_sync/TEST52 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2018-2019, Intel Corporation +# Copyright 2018-2024, Intel Corporation # # # pmempool_sync/TEST52 -- test for sync command with badblocks diff --git a/src/test/pmempool_sync/TEST53 b/src/test/pmempool_sync/TEST53 index e3e87f6acad..abd2e08eb28 100755 --- a/src/test/pmempool_sync/TEST53 +++ b/src/test/pmempool_sync/TEST53 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2011-2019, Intel Corporation +# Copyright 2011-2024, Intel Corporation # # # pmempool_sync/TEST53 -- test for sync command with badblocks diff --git a/src/test/pmempool_sync/TEST8 b/src/test/pmempool_sync/TEST8 index 7ca05a9ed87..dc0f668fac0 100755 --- a/src/test/pmempool_sync/TEST8 +++ b/src/test/pmempool_sync/TEST8 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2016-2018, Intel Corporation +# Copyright 2016-2024, Intel Corporation # # # pmempool_sync/TEST8 -- test for checking pmempool sync; @@ -56,6 +56,7 @@ rm -f $DIR/part11 expect_abnormal_exit $PMEMPOOL$EXESUFFIX sync $POOLSET2 >> $LOG_TEMP 2>&1 mv $LOG_TEMP $LOG + check pass diff --git a/src/test/pmempool_sync/TEST9 b/src/test/pmempool_sync/TEST9 index df59e4db997..3186f5fef7b 100755 --- a/src/test/pmempool_sync/TEST9 +++ b/src/test/pmempool_sync/TEST9 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2016-2018, Intel Corporation +# Copyright 2016-2024, Intel Corporation # # # pmempool_sync/TEST9 -- test for checking pmempool sync; @@ -59,6 +59,7 @@ rm -f $DIR/part01 expect_abnormal_exit $PMEMPOOL$EXESUFFIX sync $POOLSET2 >> $LOG_TEMP 2>&1 mv $LOG_TEMP $LOG + check pass diff --git a/src/test/pmempool_transform/TEST10 b/src/test/pmempool_transform/TEST10 index 23791430713..63388f80030 100755 --- a/src/test/pmempool_transform/TEST10 +++ b/src/test/pmempool_transform/TEST10 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2016-2018, Intel Corporation +# Copyright 2016-2024, Intel Corporation # # # pmempool_transform/TEST10 -- test for checking pmempool transform; @@ -57,6 +57,7 @@ expect_abnormal_exit $PMEMPOOL$EXESUFFIX transform \ dump_pool_info $POOLSET_IN >> $LOG_TEMP mv $LOG_TEMP $LOG + check pass diff --git a/src/test/pmempool_transform/TEST12 b/src/test/pmempool_transform/TEST12 index 679924ad0dd..92b4c9ade85 100755 --- a/src/test/pmempool_transform/TEST12 +++ b/src/test/pmempool_transform/TEST12 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2016-2019, Intel Corporation +# Copyright 2016-2024, Intel Corporation # # # pmempool_transform/TEST12 -- test for transform with SINGLEHDR option @@ -31,6 +31,7 @@ dax_device_zero LOG=out${UNITTEST_NUM}.log ERR_LOG=err${UNITTEST_NUM}.log LOG_TEMP=out${UNITTEST_NUM}_part.log +ERR_TEMP=err${UNITTEST_NUM}_temp.log rm -f $LOG && touch $LOG rm -f $LOG_TEMP && touch $LOG_TEMP @@ -104,6 +105,7 @@ dump_pool_info $POOLSET_2 >> $LOG_TEMP dump_pool_info ${DEVICE_DAX_PATH[0]} >> $LOG_TEMP mv $LOG_TEMP $LOG + check pass diff --git a/src/test/pmempool_transform/TEST3 b/src/test/pmempool_transform/TEST3 index 4eb59fa3ab5..f67ed2b94a4 100755 --- a/src/test/pmempool_transform/TEST3 +++ b/src/test/pmempool_transform/TEST3 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2016-2018, Intel Corporation +# Copyright 2016-2024, Intel Corporation # # # pmempool_transform/TEST3 -- test for checking pmempool transform; @@ -84,6 +84,7 @@ dump_pool_info $DIR/testfile00 >> $LOG_TEMP check_no_files $DIR/testfile10 $DIR/testfile11 mv $LOG_TEMP $LOG + check pass diff --git a/src/test/pmempool_transform/TEST5 b/src/test/pmempool_transform/TEST5 index 6cbc430e4a3..81fee2d215f 100755 --- a/src/test/pmempool_transform/TEST5 +++ b/src/test/pmempool_transform/TEST5 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2016-2018, Intel Corporation +# Copyright 2016-2024, Intel Corporation # # # pmempool_transform/TEST5 -- test for checking pmempool transform; @@ -93,6 +93,7 @@ dump_pool_info $DIR/testfile02 >> $LOG_TEMP dump_pool_info $DIR/testfile10 >> $LOG_TEMP mv $LOG_TEMP $LOG + check pass diff --git a/src/test/pmempool_transform/TEST6 b/src/test/pmempool_transform/TEST6 index 2639d8e9fe2..394ab5fbda4 100755 --- a/src/test/pmempool_transform/TEST6 +++ b/src/test/pmempool_transform/TEST6 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2016-2018, Intel Corporation +# Copyright 2016-2024, Intel Corporation # # # pmempool_transform/TEST6 -- test for checking pmempool transform; @@ -72,6 +72,7 @@ expect_abnormal_exit $PMEMPOOL$EXESUFFIX transform \ dump_pool_info $POOLSET_OUT1 >> $LOG_TEMP mv $LOG_TEMP $LOG + check pass diff --git a/src/test/pmempool_transform/TEST9 b/src/test/pmempool_transform/TEST9 index 2e1bd178305..b3089e9f058 100755 --- a/src/test/pmempool_transform/TEST9 +++ b/src/test/pmempool_transform/TEST9 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2016-2018, Intel Corporation +# Copyright 2016-2024, Intel Corporation # # # pmempool_transform/TEST9 -- test for checking pmempool transform; @@ -86,6 +86,7 @@ dump_pool_info ${DEVICE_DAX_PATH[1]} >> $LOG_TEMP expect_normal_exit $CMPMAP$EXESUFFIX -z -l $HDR_LEN ${DEVICE_DAX_PATH[0]} mv $LOG_TEMP $LOG + check pass diff --git a/src/test/pmempool_transform/out10.log.match b/src/test/pmempool_transform/out10.log.match index 1476db59f19..5152de98020 100644 --- a/src/test/pmempool_transform/out10.log.match +++ b/src/test/pmempool_transform/out10.log.match @@ -11,6 +11,10 @@ REPLICA 20M $(nW)testfile01 20M $(nW)testfile21 +$(OPT)$(*) *ERROR* transform.c: $(N): check_if_part_used_once: cannot get absolute path for $(*)/test_pmempool_transform10/testfile00, replica 0, part 0 +$(OPT)$(*) *ERROR* util_posix.c: $(N): util_compare_file_inodes: stat failed for $(*)/test_pmempool_transform10/testfile21 +$(OPT)$(*) *ERROR* transform.c: $(N): check_if_part_used_once: some part file's path is used multiple times +$(OPT)$(*) *ERROR* replica.c: $(N): pmempool_transformU: transformation failed error: Invalid argument error: failed to transform $(nW)poolset.in -> $(nW)poolset.out: some part file's path is used multiple times Poolset structure: diff --git a/src/test/scope/out2.log.match b/src/test/scope/out2.log.match index 50225a08d30..20e7dda9247 100644 --- a/src/test/scope/out2.log.match +++ b/src/test/scope/out2.log.match @@ -10,6 +10,9 @@ pmem_has_auto_flush$(nW) pmem_has_hw_drain$(nW) $(OPT)pmem_inject_fault_at$(nW) pmem_is_pmem$(nW) +pmem_log_get_threshold$(nW) +pmem_log_set_function$(nW) +pmem_log_set_threshold$(nW) pmem_map_file$(nW) pmem_memcpy$(nW) pmem_memcpy_nodrain$(nW) diff --git a/src/test/scope/out5.log.match b/src/test/scope/out5.log.match index 3ad10d14459..d88824a39f1 100644 --- a/src/test/scope/out5.log.match +++ b/src/test/scope/out5.log.match @@ -31,6 +31,9 @@ pmemobj_list_insert$(nW) pmemobj_list_insert_new$(nW) pmemobj_list_move$(nW) pmemobj_list_remove$(nW) +pmemobj_log_get_threshold$(nW) +pmemobj_log_set_function$(nW) +pmemobj_log_set_threshold$(nW) pmemobj_memcpy$(nW) pmemobj_memcpy_persist$(nW) pmemobj_memmove$(nW) diff --git a/src/test/tools/anonymous_mmap/anonymous_mmap.c b/src/test/tools/anonymous_mmap/anonymous_mmap.c index 2fc6e5e085b..87f945120cd 100644 --- a/src/test/tools/anonymous_mmap/anonymous_mmap.c +++ b/src/test/tools/anonymous_mmap/anonymous_mmap.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2018, Intel Corporation */ +/* Copyright 2018-2024, Intel Corporation */ /* * anonymous_mmap.c -- tool for verifying if given memory length can be @@ -18,7 +18,7 @@ main(int argc, char *argv[]) out_init("ANONYMOUS_MMAP", "ANONYMOUS_MMAP", "", 1, 0); if (argc != 2) { - out("Usage: %s ", argv[0]); + printf("Usage: %s \n", argv[0]); return -1; } @@ -26,8 +26,9 @@ main(int argc, char *argv[]) char *addr = mmap(NULL, length, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); if (addr == MAP_FAILED) { - out("anonymous_mmap.c: Failed to mmap length=%lu of memory, " - "errno=%d", length, errno); + printf( + "anonymous_mmap.c: Failed to mmap length=%lu of memory, errno=%d\n", + length, errno); return errno; } diff --git a/src/test/tools/obj_verify/obj_verify.c b/src/test/tools/obj_verify/obj_verify.c index d9b1bb842a4..ab02182e9f8 100644 --- a/src/test/tools/obj_verify/obj_verify.c +++ b/src/test/tools/obj_verify/obj_verify.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2018-2020, Intel Corporation */ +/* Copyright 2018-2024, Intel Corporation */ /* * obj_verify.c -- tool for creating and verifying a pmemobj pool @@ -12,6 +12,7 @@ #include "libpmemobj.h" #include "set.h" #include "os.h" +#include "out.h" #define SIGNATURE_LEN 10 #define NUMBER_LEN 10 @@ -93,13 +94,13 @@ do_create(const char *path, const char *layout) if ((pop = pmemobj_create(path, layout, 0, S_IWUSR | S_IRUSR)) == NULL) { if (errno != EEXIST) { - out("!%s: pmemobj_create: %s", + printf("!%s: pmemobj_create: %s\n", path, pmemobj_errormsg()); exit(-1); } if ((pop = pmemobj_open(path, layout)) == NULL) { - out("!%s: pmemobj_open: %s", + printf("!%s: pmemobj_open: %s\n", path, pmemobj_errormsg()); exit(-1); } @@ -114,11 +115,11 @@ do_create(const char *path, const char *layout) if (pmemobj_ctl_set(pop, "heap.alloc_class.new.desc", &class) != 0) { pmemobj_close(pop); - out("!pmemobj_ctl_set: %s", path); + printf("!pmemobj_ctl_set: %s\n", path); exit(-1); } - out("create(%s): allocating records in the pool ...", path); + printf("create(%s): allocating records in the pool ...\n", path); count = D_RO(root)->count; @@ -128,10 +129,10 @@ do_create(const char *path, const char *layout) count = D_RO(root)->count - count; if (count) { - out("create(%s): allocated %lu records (of size %zu)", + printf("create(%s): allocated %lu records (of size %zu)\n", path, count, sizeof(struct data_s)); } else { - out("create(%s): pool is full", path); + printf("create(%s): pool is full\n", path); } pmemobj_close(pop); @@ -147,10 +148,12 @@ do_verify(const char *path, const char *layout) PMEMoid oid; uint64_t count = 0; int error = 0; + char buff[128]; if ((pop = pmemobj_open(path, layout)) == NULL) { - out("!%s: pmemobj_open: %s", - path, pmemobj_errormsg()); + strerror_r(errno, buff, 128); + printf("%s: pmemobj_open: %s: %s\n", + path, pmemobj_errormsg(), buff); exit(-1); } @@ -162,7 +165,7 @@ do_verify(const char *path, const char *layout) if (!util_checksum(D_RW(rec), sizeof(*D_RW(rec)), &D_RW(rec)->checksum, 0 /* verify */, SKIP_OFFSET)) { - out("verify(%s): incorrect record: %s (#%lu)", + printf("verify(%s): incorrect record: %s (#%lu)\n", path, D_RW(rec)->signature, count); error = 1; break; @@ -172,8 +175,8 @@ do_verify(const char *path, const char *layout) } if (D_RO(root)->count != count) { - out( - "verify(%s): incorrect number of records (is: %lu, should be: %lu)", + printf( + "verify(%s): incorrect number of records (is: %lu, should be: %lu)\n", path, count, D_RO(root)->count); error = 1; } @@ -181,12 +184,12 @@ do_verify(const char *path, const char *layout) pmemobj_close(pop); if (error) { - out("verify(%s): pool file contains error", path); + printf("verify(%s): pool file contains error\n", path); exit(-1); } - out( - "verify(%s): pool file successfully verified (%lu records of size %zu)", + printf( + "verify(%s): pool file successfully verified (%lu records of size %zu)\n", path, count, sizeof(struct data_s)); } @@ -197,7 +200,7 @@ main(int argc, char *argv[]) out_init("OBJ_VERIFY", "OBJ_VERIFY", "", 1, 0); if (argc < 4) { - out("Usage: %s \n" + printf("Usage: %s \n" "Options:\n" " c - create\n" " v - verify\n", @@ -221,7 +224,7 @@ main(int argc, char *argv[]) op = argv[arg]; if (op[1] != '\0') { - out("op must be c or v (c=create, v=verify)"); + printf("op must be c or v (c=create, v=verify)\n"); exit(-1); } @@ -235,7 +238,7 @@ main(int argc, char *argv[]) break; default: - out("op must be c or v (c=create, v=verify)"); + printf("op must be c or v (c=create, v=verify)\n"); exit(-1); break; } diff --git a/src/test/traces/TEST6 b/src/test/traces/TEST6 deleted file mode 100755 index 05da8876e43..00000000000 --- a/src/test/traces/TEST6 +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash -# SPDX-License-Identifier: BSD-3-Clause -# Copyright 2014-2019, Intel Corporation - -# -# src/test/traces/TEST6 -- unit test for traces -# - -. ../unittest/unittest.sh - -require_test_type medium - -require_fs_type none -require_build_type debug - -setup - -export UT_LOG_LEVEL=4 -expect_normal_exit ./traces$EXESUFFIX 2>redir_stderr$UNITTEST_NUM.log - -check - -pass diff --git a/src/test/traces/custom_file0.log.match b/src/test/traces/custom_file0.log.match index 9209b0590f2..e04efd9f8c0 100644 --- a/src/test/traces/custom_file0.log.match +++ b/src/test/traces/custom_file0.log.match @@ -1,16 +1,16 @@ -$(*) -$(*) -$(*) -$(OPT)$(*) compiled with support for Valgrind pmemcheck -$(OPT)$(*) compiled with support for Valgrind helgrind -$(OPT)$(*) compiled with support for Valgrind memcheck -$(OPT)$(*) compiled with support for Valgrind drd -$(OPT)$(*) compiled with support for shutdown state -$(OPT)$(*) compiled with libndctl 63+ -$(*) -$(*)Log level NONE -$(*)Log level ERROR -$(*)Log level WARNING -$(*)Log level INFO -$(*)Log level DEBUG -$(*) +$(nW) <1> $(nW) $(nW) src version: $(nW) +$(OPT)$(nW) <1> $(nW) $(nW) compiled with support for shutdown state +$(OPT)$(nW) <1> $(nW) $(nW) compiled with libndctl 63+ +$(nW) <1> $(nW) $(nW) pid $(N): program: $(nW) +$(nW) <1> $(nW) $(nW) ut version 1.0 +$(OPT)$(nW) <1> $(nW) $(nW) compiled with support for Valgrind pmemcheck +$(OPT)$(nW) <1> $(nW) $(nW) compiled with support for Valgrind helgrind +$(OPT)$(nW) <1> $(nW) $(nW) compiled with support for Valgrind memcheck +$(OPT)$(nW) <1> $(nW) $(nW) compiled with support for Valgrind drd +$(nW) <3> $(nW) $(nW) +$(nW) <1> $(nW) $(nW) Log level HARK +$(nW) <1> $(nW) $(nW) Log level ERROR +$(nW) <2> $(nW) $(nW) Log level WARNING +$(nW) <3> $(nW) $(nW) Log level INFO +$(nW) <4> $(nW) $(nW) Log level DEBUG +$(nW) <3> $(nW) $(nW) diff --git a/src/test/traces/redir_stderr1.log.match b/src/test/traces/redir_stderr1.log.match index 3d739c871d8..e69de29bb2d 100644 --- a/src/test/traces/redir_stderr1.log.match +++ b/src/test/traces/redir_stderr1.log.match @@ -1 +0,0 @@ -$(*)Log level NONE diff --git a/src/test/traces/redir_stderr2.log.match b/src/test/traces/redir_stderr2.log.match index 0ff6e699564..1de6b64ad75 100644 --- a/src/test/traces/redir_stderr2.log.match +++ b/src/test/traces/redir_stderr2.log.match @@ -1,11 +1,11 @@ -$(*) -$(*) -$(*) -$(OPT)$(*) compiled with support for Valgrind pmemcheck -$(OPT)$(*) compiled with support for Valgrind helgrind -$(OPT)$(*) compiled with support for Valgrind memcheck -$(OPT)$(*) compiled with support for Valgrind drd -$(OPT)$(*) compiled with support for shutdown state -$(OPT)$(*) compiled with libndctl 63+ -$(*)Log level NONE -$(*)Log level ERROR +$(nW) <1> $(nW) $(nW) src version: $(nW) +$(OPT)$(nW) <1> $(nW) $(nW) compiled with support for shutdown state +$(OPT)$(nW) <1> $(nW) $(nW) compiled with libndctl 63+ +$(nW) <1> $(nW) $(nW) pid $(N): program: $(nW) +$(nW) <1> $(nW) $(nW) ut version 1.0 +$(OPT)$(nW) <1> $(nW) $(nW) compiled with support for Valgrind pmemcheck +$(OPT)$(nW) <1> $(nW) $(nW) compiled with support for Valgrind helgrind +$(OPT)$(nW) <1> $(nW) $(nW) compiled with support for Valgrind memcheck +$(OPT)$(nW) <1> $(nW) $(nW) compiled with support for Valgrind drd +$(nW) <1> $(nW) $(nW) Log level HARK +$(nW) <1> $(nW) $(nW) Log level ERROR diff --git a/src/test/traces/redir_stderr3.log.match b/src/test/traces/redir_stderr3.log.match index 1f4b14419a3..a2d55384538 100644 --- a/src/test/traces/redir_stderr3.log.match +++ b/src/test/traces/redir_stderr3.log.match @@ -1,12 +1,12 @@ -$(*) -$(*) -$(*) -$(OPT)$(*) compiled with support for Valgrind pmemcheck -$(OPT)$(*) compiled with support for Valgrind helgrind -$(OPT)$(*) compiled with support for Valgrind memcheck -$(OPT)$(*) compiled with support for Valgrind drd -$(OPT)$(*) compiled with support for shutdown state -$(OPT)$(*) compiled with libndctl 63+ -$(*)Log level NONE -$(*)Log level ERROR -$(*)Log level WARNING +$(nW) <1> $(nW) $(nW) src version: $(nW) +$(OPT)$(nW) <1> $(nW) $(nW) compiled with support for shutdown state +$(OPT)$(nW) <1> $(nW) $(nW) compiled with libndctl 63+ +$(nW) <1> $(nW) $(nW) pid $(N): program: $(nW) +$(nW) <1> $(nW) $(nW) ut version 1.0 +$(OPT)$(nW) <1> $(nW) $(nW) compiled with support for Valgrind pmemcheck +$(OPT)$(nW) <1> $(nW) $(nW) compiled with support for Valgrind helgrind +$(OPT)$(nW) <1> $(nW) $(nW) compiled with support for Valgrind memcheck +$(OPT)$(nW) <1> $(nW) $(nW) compiled with support for Valgrind drd +$(nW) <1> $(nW) $(nW) Log level HARK +$(nW) <1> $(nW) $(nW) Log level ERROR +$(nW) <2> $(nW) $(nW) Log level WARNING diff --git a/src/test/traces/redir_stderr4.log.match b/src/test/traces/redir_stderr4.log.match index 97f9f09bf48..140b9d37046 100644 --- a/src/test/traces/redir_stderr4.log.match +++ b/src/test/traces/redir_stderr4.log.match @@ -1,15 +1,15 @@ -$(*) -$(*) -$(*) -$(OPT)$(*) compiled with support for Valgrind pmemcheck -$(OPT)$(*) compiled with support for Valgrind helgrind -$(OPT)$(*) compiled with support for Valgrind memcheck -$(OPT)$(*) compiled with support for Valgrind drd -$(OPT)$(*) compiled with support for shutdown state -$(OPT)$(*) compiled with libndctl 63+ -$(*) -$(*)Log level NONE -$(*)Log level ERROR -$(*)Log level WARNING -$(*)Log level INFO -$(*) +$(nW) <1> $(nW) $(nW) src version: $(nW) +$(OPT)$(nW) <1> $(nW) $(nW) compiled with support for shutdown state +$(OPT)$(nW) <1> $(nW) $(nW) compiled with libndctl 63+ +$(nW) <1> $(nW) $(nW) pid $(N): program: $(nW) +$(nW) <1> $(nW) $(nW) ut version 1.0 +$(OPT)$(nW) <1> $(nW) $(nW) compiled with support for Valgrind pmemcheck +$(OPT)$(nW) <1> $(nW) $(nW) compiled with support for Valgrind helgrind +$(OPT)$(nW) <1> $(nW) $(nW) compiled with support for Valgrind memcheck +$(OPT)$(nW) <1> $(nW) $(nW) compiled with support for Valgrind drd +$(nW) <3> $(nW) $(nW) +$(nW) <1> $(nW) $(nW) Log level HARK +$(nW) <1> $(nW) $(nW) Log level ERROR +$(nW) <2> $(nW) $(nW) Log level WARNING +$(nW) <3> $(nW) $(nW) Log level INFO +$(nW) <3> $(nW) $(nW) diff --git a/src/test/traces/redir_stderr5.log.match b/src/test/traces/redir_stderr5.log.match index 9209b0590f2..e04efd9f8c0 100644 --- a/src/test/traces/redir_stderr5.log.match +++ b/src/test/traces/redir_stderr5.log.match @@ -1,16 +1,16 @@ -$(*) -$(*) -$(*) -$(OPT)$(*) compiled with support for Valgrind pmemcheck -$(OPT)$(*) compiled with support for Valgrind helgrind -$(OPT)$(*) compiled with support for Valgrind memcheck -$(OPT)$(*) compiled with support for Valgrind drd -$(OPT)$(*) compiled with support for shutdown state -$(OPT)$(*) compiled with libndctl 63+ -$(*) -$(*)Log level NONE -$(*)Log level ERROR -$(*)Log level WARNING -$(*)Log level INFO -$(*)Log level DEBUG -$(*) +$(nW) <1> $(nW) $(nW) src version: $(nW) +$(OPT)$(nW) <1> $(nW) $(nW) compiled with support for shutdown state +$(OPT)$(nW) <1> $(nW) $(nW) compiled with libndctl 63+ +$(nW) <1> $(nW) $(nW) pid $(N): program: $(nW) +$(nW) <1> $(nW) $(nW) ut version 1.0 +$(OPT)$(nW) <1> $(nW) $(nW) compiled with support for Valgrind pmemcheck +$(OPT)$(nW) <1> $(nW) $(nW) compiled with support for Valgrind helgrind +$(OPT)$(nW) <1> $(nW) $(nW) compiled with support for Valgrind memcheck +$(OPT)$(nW) <1> $(nW) $(nW) compiled with support for Valgrind drd +$(nW) <3> $(nW) $(nW) +$(nW) <1> $(nW) $(nW) Log level HARK +$(nW) <1> $(nW) $(nW) Log level ERROR +$(nW) <2> $(nW) $(nW) Log level WARNING +$(nW) <3> $(nW) $(nW) Log level INFO +$(nW) <4> $(nW) $(nW) Log level DEBUG +$(nW) <3> $(nW) $(nW) diff --git a/src/test/traces/redir_stderr6.log.match b/src/test/traces/redir_stderr6.log.match deleted file mode 100644 index c96567c6243..00000000000 --- a/src/test/traces/redir_stderr6.log.match +++ /dev/null @@ -1,16 +0,0 @@ -$(*) -$(*) -$(*) -$(OPT)$(*) compiled with support for Valgrind pmemcheck -$(OPT)$(*) compiled with support for Valgrind helgrind -$(OPT)$(*) compiled with support for Valgrind memcheck -$(OPT)$(*) compiled with support for Valgrind drd -$(OPT)$(*) compiled with support for shutdown state -$(OPT)$(*) compiled with libndctl 63+ -$(*) -: <0> [traces.c:$(*) main]$(W)Log level NONE -: <1> [traces.c:$(*) main]$(W)Log level ERROR -: <2> [traces.c:$(*) main]$(W)Log level WARNING -: <3> [traces.c:$(*) main]$(W)Log level INFO -: <4> [traces.c:$(*) main]$(W)Log level DEBUG -$(*) diff --git a/src/test/traces/traces.c b/src/test/traces/traces.c index 317ceb53f9a..c2286260e2d 100644 --- a/src/test/traces/traces.c +++ b/src/test/traces/traces.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2014-2017, Intel Corporation */ +/* Copyright 2014-2024, Intel Corporation */ /* * traces.c -- unit test for traces @@ -24,9 +24,9 @@ main(int argc, char *argv[]) /* Execute test */ common_init(LOG_PREFIX, LOG_LEVEL_VAR, LOG_FILE_VAR, MAJOR_VERSION, MINOR_VERSION); - LOG(0, "Log level NONE"); - LOG(1, "Log level ERROR"); - LOG(2, "Log level WARNING"); + CORE_LOG_HARK("Log level HARK"); + CORE_LOG_ERROR("Log level ERROR"); + CORE_LOG_WARNING("Log level WARNING"); LOG(3, "Log level INFO"); LOG(4, "Log level DEBUG"); diff --git a/src/test/traces_custom_function/.gitignore b/src/test/traces_custom_function/.gitignore deleted file mode 100644 index 47a458e4892..00000000000 --- a/src/test/traces_custom_function/.gitignore +++ /dev/null @@ -1 +0,0 @@ -traces_custom_function diff --git a/src/test/traces_custom_function/Makefile b/src/test/traces_custom_function/Makefile deleted file mode 100644 index e84a1d46a99..00000000000 --- a/src/test/traces_custom_function/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause -# Copyright 2014-2016, Intel Corporation - -# -# src/test/traces_custom_function/Makefile -- build traces unit test -# -TARGET = traces_custom_function -OBJS = traces_custom_function.o - -BUILD_STATIC_DEBUG=n -BUILD_STATIC_NONDEBUG=n - -LIBPMEMCOMMON=y -include ../Makefile.inc -CFLAGS += -DDEBUG diff --git a/src/test/traces_custom_function/TEST0 b/src/test/traces_custom_function/TEST0 deleted file mode 100755 index 8c3d74c5c5f..00000000000 --- a/src/test/traces_custom_function/TEST0 +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env bash -# SPDX-License-Identifier: BSD-3-Clause -# Copyright 2014-2019, Intel Corporation - -# -# src/test/traces_custom_function/TEST0 -- unit test for traces custom -# print function -# - -. ../unittest/unittest.sh - -require_test_type medium - -require_fs_type none -require_build_type debug - -setup - -export TRACE_LOG_LEVEL=4 -expect_normal_exit ./traces_custom_function$EXESUFFIX p - -check - -pass diff --git a/src/test/traces_custom_function/TEST1 b/src/test/traces_custom_function/TEST1 deleted file mode 100755 index b3cdc35ca48..00000000000 --- a/src/test/traces_custom_function/TEST1 +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env bash -# SPDX-License-Identifier: BSD-3-Clause -# Copyright 2014-2019, Intel Corporation - -# -# src/test/traces_custom_function/TEST1 -- unit test for traces custom -# vsnprintf function -# - -. ../unittest/unittest.sh - -require_test_type medium - -require_fs_type none -require_build_type debug - -setup - -export TRACE_LOG_LEVEL=4 -expect_normal_exit ./traces_custom_function$EXESUFFIX v - -check - -pass diff --git a/src/test/traces_custom_function/out0.log.match b/src/test/traces_custom_function/out0.log.match deleted file mode 100644 index dbac0022d18..00000000000 --- a/src/test/traces_custom_function/out0.log.match +++ /dev/null @@ -1,35 +0,0 @@ -traces_custom_function$(nW)TEST0: START: traces_custom_function - $(nW)traces_custom_function$(nW) p -CUSTOM_PRINT: : <1> [$(nW):$(N) out_init]$(W)pid $(N): program: $(nW) - -CUSTOM_PRINT: : <1> [$(nW):$(N) out_init]$(W)trace_func version $(S) - -CUSTOM_PRINT: : <1> [$(nW):$(N) out_init]$(W)src version: $(nW) - -$(OPT)CUSTOM_PRINT: : <1> [$(nW):$(N) out_init]$(W)compiled with support for Valgrind pmemcheck -$(OPT) -$(OPT)CUSTOM_PRINT: : <1> [$(nW):$(N) out_init]$(W)compiled with support for Valgrind helgrind -$(OPT) -$(OPT)CUSTOM_PRINT: : <1> [$(nW):$(N) out_init]$(W)compiled with support for Valgrind memcheck -$(OPT) -$(OPT)CUSTOM_PRINT: : <1> [$(nW):$(N) out_init]$(W)compiled with support for Valgrind drd -$(OPT) -$(OPT)CUSTOM_PRINT: : <1> [$(nW):$(N) out_init]$(W)compiled with support for shutdown state -$(OPT) -$(OPT)CUSTOM_PRINT: : <1> [$(nW):$(N) out_init]$(W)compiled with libndctl 63+ -$(OPT) -CUSTOM_PRINT: : <3> [$(nW):$(N) util_mmap_init]$(W) - -CUSTOM_PRINT: : <0> [$(nW):$(N) main]$(W)Log level NONE - -CUSTOM_PRINT: : <1> [$(nW):$(N) main]$(W)Log level ERROR - -CUSTOM_PRINT: : <2> [$(nW):$(N) main]$(W)Log level WARNING - -CUSTOM_PRINT: : <3> [$(nW):$(N) main]$(W)Log level INFO - -CUSTOM_PRINT: : <4> [$(nW):$(N) main]$(W)Log level DEBUG - -CUSTOM_PRINT: : <3> [$(nW):$(N) util_mmap_fini]$(W) - -traces_custom_function$(nW)TEST0: DONE diff --git a/src/test/traces_custom_function/out1.log.match b/src/test/traces_custom_function/out1.log.match deleted file mode 100644 index 4c739a5c40c..00000000000 --- a/src/test/traces_custom_function/out1.log.match +++ /dev/null @@ -1,37 +0,0 @@ -traces_custom_function$(nW)TEST1: START: traces_custom_function - $(nW)traces_custom_function$(nW) v -CUSTOM_PRINT: : <1> [$(nW):$(N) out_init]$(W)pid $(N): program: $(nW) - -CUSTOM_PRINT: : <1> [$(nW):$(N) out_init]$(W)trace_func version $(S) - -CUSTOM_PRINT: : <1> [$(nW):$(N) out_init]$(W)src version: $(nW) - -$(OPT)CUSTOM_PRINT: : <1> [$(nW):$(N) out_init]$(W)compiled with support for Valgrind pmemcheck -$(OPT) -$(OPT)CUSTOM_PRINT: : <1> [$(nW):$(N) out_init]$(W)compiled with support for Valgrind helgrind -$(OPT) -$(OPT)CUSTOM_PRINT: : <1> [$(nW):$(N) out_init]$(W)compiled with support for Valgrind memcheck -$(OPT) -$(OPT)CUSTOM_PRINT: : <1> [$(nW):$(N) out_init]$(W)compiled with support for Valgrind drd -$(OPT) -$(OPT)CUSTOM_PRINT: : <1> [$(nW):$(N) out_init]$(W)compiled with support for shutdown state -$(OPT) -$(OPT)CUSTOM_PRINT: : <1> [$(nW):$(N) out_init]$(W)compiled with libndctl 63+ -$(OPT) -CUSTOM_PRINT: : <3> [$(nW):$(N) util_mmap_init]$(W) - -CUSTOM_PRINT: : <3> [$(nW):$(N) out_set_vsnprintf_func]$(W)vsnprintf $(nW)$(X) - -CUSTOM_PRINT: <@@trace_func>: <@@0> [@@$(nW):@@$(N) @@main]$(W)no format@@@@@@ - -CUSTOM_PRINT: <@@trace_func>: <@@0> [@@$(nW):@@$(N) @@main]$(W)pointer: @@$(nW)12345678@@@@@@ - -CUSTOM_PRINT: <@@trace_func>: <@@0> [@@$(nW):@@$(N) @@main]$(W)string: @@Hello world!@@@@@@ - -CUSTOM_PRINT: <@@trace_func>: <@@0> [@@$(nW):@@$(N) @@main]$(W)number: @@12345678@@@@@@ - -CUSTOM_PRINT: <@@trace_func>: <@@0> [@@$(nW):@@$(N) @@main]$(W)error@@: @@Invalid argument@@ - -CUSTOM_PRINT: <@@trace_func>: <@@3> [@@$(nW):@@$(N) @@util_mmap_fini] @@@@@@ - -traces_custom_function$(nW)TEST1: DONE diff --git a/src/test/traces_custom_function/traces_custom_function.c b/src/test/traces_custom_function/traces_custom_function.c deleted file mode 100644 index 19168a84811..00000000000 --- a/src/test/traces_custom_function/traces_custom_function.c +++ /dev/null @@ -1,106 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2014-2017, Intel Corporation */ - -/* - * traces_custom_function.c -- unit test for traces with custom print or - * vsnprintf functions - * - * usage: traces_custom_function [v|p] - * - */ - -#define LOG_PREFIX "trace_func" -#define LOG_LEVEL_VAR "TRACE_LOG_LEVEL" -#define LOG_FILE_VAR "TRACE_LOG_FILE" -#define MAJOR_VERSION 1 -#define MINOR_VERSION 0 - -#include -#include -#include "pmemcommon.h" -#include "unittest.h" - -/* - * print_custom_function -- Custom function to handle output - * - * This is called from the library to print text instead of output to stderr. - */ -static void -print_custom_function(const char *s) -{ - if (s) { - UT_OUT("CUSTOM_PRINT: %s", s); - } else { - UT_OUT("CUSTOM_PRINT(NULL)"); - } -} - -/* - * vsnprintf_custom_function -- Custom vsnprintf implementation - * - * It modifies format by adding @@ in front of each conversion specification. - */ -static int -vsnprintf_custom_function(char *str, size_t size, const char *format, - va_list ap) -{ - char *format2 = MALLOC(strlen(format) * 3); - int i = 0; - int ret_val; - - while (*format != '\0') { - if (*format == '%') { - format2[i++] = '@'; - format2[i++] = '@'; - } - format2[i++] = *format++; - } - format2[i++] = '\0'; - - ret_val = vsnprintf(str, size, format2, ap); - FREE(format2); - - return ret_val; -} - -int -main(int argc, char *argv[]) -{ - START(argc, argv, "traces_custom_function"); - - if (argc != 2) - UT_FATAL("usage: %s [v|p]", argv[0]); - - out_set_print_func(print_custom_function); - - common_init(LOG_PREFIX, LOG_LEVEL_VAR, LOG_FILE_VAR, - MAJOR_VERSION, MINOR_VERSION); - - switch (argv[1][0]) { - case 'p': { - LOG(0, "Log level NONE"); - LOG(1, "Log level ERROR"); - LOG(2, "Log level WARNING"); - LOG(3, "Log level INFO"); - LOG(4, "Log level DEBUG"); - } - break; - case 'v': - out_set_vsnprintf_func(vsnprintf_custom_function); - - LOG(0, "no format"); - LOG(0, "pointer: %p", (void *)0x12345678); - LOG(0, "string: %s", "Hello world!"); - LOG(0, "number: %u", 12345678); - errno = EINVAL; - LOG(0, "!error"); - break; - default: - UT_FATAL("usage: %s [v|p]", argv[0]); - } - - /* Cleanup */ - common_fini(); - - DONE(NULL); -} diff --git a/src/test/traces_pmem/.gitignore b/src/test/traces_pmem/.gitignore deleted file mode 100644 index fb2885648e8..00000000000 --- a/src/test/traces_pmem/.gitignore +++ /dev/null @@ -1 +0,0 @@ -traces_pmem diff --git a/src/test/traces_pmem/Makefile b/src/test/traces_pmem/Makefile deleted file mode 100644 index 662a1bb3a48..00000000000 --- a/src/test/traces_pmem/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause -# Copyright 2014-2023, Intel Corporation - -# -# src/test/traces_pmem/Makefile -- build traces for library pmem -# -TARGET = traces_pmem -OBJS = traces_pmem.o - -LIBPMEM=y -LIBPMEMOBJ=y - -include ../Makefile.inc diff --git a/src/test/traces_pmem/TEST0 b/src/test/traces_pmem/TEST0 deleted file mode 100755 index 4b299d1d54e..00000000000 --- a/src/test/traces_pmem/TEST0 +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env bash -# SPDX-License-Identifier: BSD-3-Clause -# Copyright 2014-2023, Intel Corporation - -# -# src/test/traces_pmem/TEST0 -- unit test traces for libraries pmem -# - -. ../unittest/unittest.sh - -require_test_type medium - -require_fs_type none -require_build_type debug static_debug - -setup - -export PMEM_LOG_LEVEL=4 -export PMEM_LOG_FILE=./trace_pmem$UNITTEST_NUM.log -export PMEMOBJ_LOG_LEVEL=4 -export PMEMOBJ_LOG_FILE=./trace_pmemobj$UNITTEST_NUM.log - -expect_normal_exit ./traces_pmem$EXESUFFIX - -# We want to check if traces are enabled and correctness of printed -# string format. We can't rely on full output (because of different -# machines configurations), hence comparison of only first 3 lines. -head -n 3 $PMEM_LOG_FILE > ./trace_pmem_head$UNITTEST_NUM.log -head -n 3 $PMEMOBJ_LOG_FILE > ./trace_pmemobj_head$UNITTEST_NUM.log - -check - -pass diff --git a/src/test/traces_pmem/trace_pmem_head0.log.match b/src/test/traces_pmem/trace_pmem_head0.log.match deleted file mode 100644 index 709ecb2df74..00000000000 --- a/src/test/traces_pmem/trace_pmem_head0.log.match +++ /dev/null @@ -1,3 +0,0 @@ -: <$(N)> [out.c:$(N) $(*)] pid $(N): program: $(*) -: <$(N)> [out.c:$(N) $(*)] libpmem version $(N).$(N) -: <$(N)> [out.c:$(N) $(*)] src version: $(*) diff --git a/src/test/traces_pmem/trace_pmemobj_head0.log.match b/src/test/traces_pmem/trace_pmemobj_head0.log.match deleted file mode 100644 index a7d81a0b690..00000000000 --- a/src/test/traces_pmem/trace_pmemobj_head0.log.match +++ /dev/null @@ -1,3 +0,0 @@ -: <$(N)> [out.c:$(N) $(*)] pid $(N): program: $(*) -: <$(N)> [out.c:$(N) $(*)] libpmemobj version $(N).$(N) -: <$(N)> [out.c:$(N) $(*)] src version: $(*) diff --git a/src/test/traces_pmem/traces_pmem.c b/src/test/traces_pmem/traces_pmem.c deleted file mode 100644 index d88fd047913..00000000000 --- a/src/test/traces_pmem/traces_pmem.c +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2014-2023, Intel Corporation */ - -/* - * traces_pmem.c -- unit test traces for libraries pmem - */ - -#include "unittest.h" - -int -main(int argc, char *argv[]) -{ - START(argc, argv, "traces_pmem"); - - UT_ASSERT(!pmem_check_version(PMEM_MAJOR_VERSION, - PMEM_MINOR_VERSION)); - UT_ASSERT(!pmemobj_check_version(PMEMOBJ_MAJOR_VERSION, - PMEMOBJ_MINOR_VERSION)); - - DONE(NULL); -} diff --git a/src/test/unittest/Makefile b/src/test/unittest/Makefile index acbeeb55a42..75242382d6c 100644 --- a/src/test/unittest/Makefile +++ b/src/test/unittest/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2014-2023, Intel Corporation +# Copyright 2014-2024, Intel Corporation # # src/test/unittest/Makefile -- build unittest support library @@ -18,9 +18,6 @@ TARGET_UT = libut.a OBJS_UT = ut.o ut_alloc.o ut_file.o ut_pthread.o ut_signal.o ut_backtrace.o\ os_posix.o os_thread_posix.o util.o alloc.o rand.o ut_fh.o ut_mt.o -TARGET_UT_PMEM2 = ut_pmem2.a -OBJS_UT_PMEM2 = ut_pmem2_config.o ut_pmem2_utils.o - CFLAGS = -I$(TOP)/src/include CFLAGS += -I$(TOP)/src/common CFLAGS += -I$(TOP)/src/core @@ -75,18 +72,20 @@ LDFLAGS += $(GCOV_LDFLAGS) LIBS += $(GCOV_LIBS) endif +ifeq ($(VALGRIND),0) +CFLAGS += -DVALGRIND_ENABLED=0 +CXXFLAGS += -DVALGRIND_ENABLED=0 +endif + CFLAGS += $(EXTRA_CFLAGS) LIBS += $(LIBUTIL) -all test: $(TARGET_UT) $(TARGET_UT_PMEM2) +all test: $(TARGET_UT) $(TARGET_UT): $(OBJS_UT) $(AR) rv $@ $(OBJS_UT) -$(TARGET_UT_PMEM2): $(OBJS_UT_PMEM2) - $(AR) rv $@ $(OBJS_UT_PMEM2) - ifneq ($(CSTYLEON),0) $(TARGET): unittest.htmp endif @@ -106,7 +105,7 @@ clean: $(RM) *.o core a.out unittest.htmp clobber: clean - $(RM) $(TARGET_UT) $(TARGET_UT_PMEM2) + $(RM) $(TARGET_UT) $(RM) -r .deps test check pcheck pycheck: all diff --git a/src/test/unittest/README b/src/test/unittest/README index c5c8fb9c6c6..ea50a92f6f6 100644 --- a/src/test/unittest/README +++ b/src/test/unittest/README @@ -6,7 +6,8 @@ This directory contains the unit test framework used by the Persistent Memory Development Kit unit tests. This framework provides a support for mock objects. To mock an interface use -FUNC_MOCK_RET_ALWAYS or FUNC_MOCK macros in the test code. +FUNC_MOCK_RET_ALWAYS, FUNC_MOCK_RET_ALWAYS_VOID, FUNC_MOCK or +FUNC_MOCK_NONSTATIC macros in the test code. The FUNC_MOCK_RET_ALWAYS is quite straightforward, it simply takes a function name and a value that the given function has to return. For example: diff --git a/src/test/unittest/basetest.py b/src/test/unittest/basetest.py index da514e73abd..560aa8bb8fa 100644 --- a/src/test/unittest/basetest.py +++ b/src/test/unittest/basetest.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2019-2023, Intel Corporation +# Copyright 2019-2024, Intel Corporation """Base tests class and its functionalities. @@ -66,6 +66,7 @@ def clean(self, ctx): from configurator import Configurator from consts import LIBS_LIST, ROOTDIR +import granularity as g import futils import test_types import shutil @@ -339,6 +340,13 @@ def setup(self, ctx): self.env.update(self._get_utenv()) self.env.update(self._debug_log_env()) self.ctx.add_env(self.env) + # disable shutdown state control for non-pmem (Page granularity) + if isinstance(ctx.granularity, g.Page): + pmemobj_conf = os.getenv('PMEMOBJ_CONF', default='') + if 'sds.at_create=0' not in pmemobj_conf: + env = dict() + env['PMEMOBJ_CONF'] = 'sds.at_create=0' + self.ctx.add_env(env) self.remove_log_files() diff --git a/src/test/unittest/unittest.h b/src/test/unittest/unittest.h index 13a47ffb91f..f0e1b19c9f5 100644 --- a/src/test/unittest/unittest.h +++ b/src/test/unittest/unittest.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause */ -/* Copyright 2014-2023, Intel Corporation */ +/* Copyright 2014-2024, Intel Corporation */ /* * unittest.h -- the mundane stuff shared by all unit tests @@ -87,6 +87,12 @@ extern "C" { #include "os.h" #include "os_thread.h" #include "util.h" +#include "log_internal.h" +#include "core_assert.h" + +#ifdef USE_LOG_PMEMOBJ +#include "libpmemobj/log.h" +#endif int ut_get_uuid_str(char *); #define UT_MAX_ERR_MSG 128 @@ -117,7 +123,7 @@ void ut_err(const char *file, int line, const char *func, /* indicate the start of the test */ #define START(argc, argv, ...)\ - ut_start(__FILE__, __LINE__, __func__, argc, argv, __VA_ARGS__) + ut_start(__FILE__, __LINE__, __func__, argc, argv, __VA_ARGS__) /* normal exit from test */ #define DONE(...)\ @@ -144,29 +150,35 @@ void ut_err(const char *file, int line, const char *func, /* * assertions... */ +#define UT_ASSERT_MSG(FORMAT, ...) \ + UT_FATAL("assertion failure: " FORMAT, ##__VA_ARGS__) /* assert a condition is true at runtime */ #define UT_ASSERT_rt(cnd)\ - ((void)((cnd) || (ut_fatal(__FILE__, __LINE__, __func__,\ - "assertion failure: %s", #cnd), 0))) + ((void)((cnd) || (UT_ASSERT_MSG("%s", #cnd), 0))) /* assertion with extra info printed if assertion fails at runtime */ #define UT_ASSERTinfo_rt(cnd, info) \ - ((void)((cnd) || (ut_fatal(__FILE__, __LINE__, __func__,\ - "assertion failure: %s (%s)", #cnd, info), 0))) + ((void)((cnd) || (UT_ASSERT_MSG("%s (%s)", #cnd, info), 0))) /* assert two integer values are equal at runtime */ -#define UT_ASSERTeq_rt(lhs, rhs)\ - ((void)(((lhs) == (rhs)) || (ut_fatal(__FILE__, __LINE__, __func__,\ - "assertion failure: %s (0x%llx) == %s (0x%llx)", #lhs,\ +#define UT_ASSERTeq_rt(lhs, rhs) \ + ((void)(((lhs) == (rhs)) || \ + (UT_ASSERT_MSG("%s (0x%llx) == %s (0x%llx)", #lhs, \ (unsigned long long)(lhs), #rhs, (unsigned long long)(rhs)), 0))) /* assert two integer values are not equal at runtime */ -#define UT_ASSERTne_rt(lhs, rhs)\ - ((void)(((lhs) != (rhs)) || (ut_fatal(__FILE__, __LINE__, __func__,\ - "assertion failure: %s (0x%llx) != %s (0x%llx)", #lhs,\ +#define UT_ASSERTne_rt(lhs, rhs) \ + ((void)(((lhs) != (rhs)) || \ + (UT_ASSERT_MSG("%s (0x%llx) != %s (0x%llx)", #lhs, \ (unsigned long long)(lhs), #rhs, (unsigned long long)(rhs)), 0))) +/* assert two strings are equal at runtime */ +#define UT_ASSERTstreq_rt(__s1, __s2) \ + ((void)((__s1 == NULL && __s2 == NULL) || \ + (strcmp(__s1, __s2) == 0) || \ + (UT_ASSERT_MSG("%s: \"%s\" != %s", #__s1, __s1, __s2), 0))) + #if defined(__CHECKER__) #define UT_COMPILE_ERROR_ON(cond) #define UT_ASSERT_COMPILE_ERROR_ON(cond) @@ -226,11 +238,18 @@ void ut_err(const char *file, int line, const char *func, #define UT_ASSERTrange(ptr, start, size)\ ((void)(((uintptr_t)(ptr) >= (uintptr_t)(start) &&\ (uintptr_t)(ptr) < (uintptr_t)(start) + (uintptr_t)(size)) ||\ - (ut_fatal(__FILE__, __LINE__, __func__,\ - "assert failure: %s (%p) is outside range [%s (%p), %s (%p))", #ptr,\ + (UT_ASSERT_MSG("%s (%p) is outside range [%s (%p), %s (%p))", #ptr,\ (void *)(ptr), #start, (void *)(start), #start"+"#size,\ (void *)((uintptr_t)(start) + (uintptr_t)(size))), 0))) +/* assert strings are equal */ +#define UT_ASSERTstreq(__s1, __s2) \ + do { \ + if (__builtin_constant_p(__s1)) \ + UT_FATAL("UT_ASSERTstreq the first param must not be " \ + "const"); \ + UT_ASSERTstreq_rt(__s1, __s2); \ + } while (0) /* * memory allocation... */ @@ -515,13 +534,22 @@ int ut_thread_join(const char *file, int line, const char *func, #define FUNC_MOCK_RCOUNTER_SET(name, val)\ RCOUNTER(name) = val; -#define FUNC_MOCK(name, ret_type, ...)\ +#define _FUNC_MOCK(type, name, ret_type, ...)\ _FUNC_REAL_DECL(name, ret_type, ##__VA_ARGS__)\ - static unsigned RCOUNTER(name);\ + type unsigned RCOUNTER(name);\ ret_type __wrap_##name(__VA_ARGS__);\ ret_type __wrap_##name(__VA_ARGS__) {\ switch (util_fetch_and_add32(&RCOUNTER(name), 1)) { +#define FUNC_MOCK(name, ret_type, ...) \ + _FUNC_MOCK(static, name, ret_type, ##__VA_ARGS__) + +#define FUNC_MOCK_NONSTATIC(name, ret_type, ...) \ + _FUNC_MOCK(, name, ret_type, ##__VA_ARGS__) + +#define FUNC_MOCK_EXTERN(name) \ + extern unsigned RCOUNTER(name) + #define FUNC_MOCK_DLLIMPORT(name, ret_type, ...)\ __declspec(dllimport) _FUNC_REAL_DECL(name, ret_type, ##__VA_ARGS__)\ static unsigned RCOUNTER(name);\ @@ -595,6 +623,16 @@ TEST_CASE_PROCESS(int argc, char *argv[], if (argc < 2) UT_FATAL("usage: %s []", argv[0]); + if (strcmp("ALL", argv[1]) == 0) { + for (size_t i = 0; i < ntests; i++) { + int ret = test_cases[i].func(&test_cases[i], 0, NULL); + if (ret < 0) + UT_FATAL("Test %s return negative result", + test_cases[i].name); + } + return; + } + for (int i = 1; i < argc; i++) { char *str_test = argv[i]; const int args_off = i + 1; diff --git a/src/test/unittest/unittest.sh b/src/test/unittest/unittest.sh index 00cef128631..6208c044e4e 100644 --- a/src/test/unittest/unittest.sh +++ b/src/test/unittest/unittest.sh @@ -1,6 +1,6 @@ # # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2014-2023, Intel Corporation +# Copyright 2014-2024, Intel Corporation # # Copyright (c) 2016, Microsoft Corporation. All rights reserved. # @@ -126,7 +126,7 @@ fi [ "$CHECK_POOL" ] || CHECK_POOL=0 [ "$VERBOSE" ] || VERBOSE=0 [ "$TEST_LABEL" ] || TEST_LABEL= -[ -n "${SUFFIX+x}" ] || SUFFIX="😘⠏⠍⠙⠅ɗPMDKӜ⥺🙋" +[ -n "${SUFFIX+x}" ] || SUFFIX="" export UNITTEST_LOG_LEVEL GREP TEST FS BUILD CHECK_TYPE CHECK_POOL VERBOSE SUFFIX @@ -1268,8 +1268,10 @@ function require_native_fallocate() { # function require_usc_permission() { set +e - $USC_PERMISSION $1 2> $DIR/usc_permission.txt + touch $1/test.tmp + $USC_PERMISSION $1/test.tmp 2> $DIR/usc_permission.txt status=$? + rm -rf $1/test.tmp set -e # check if there were any messages printed to stderr, skip test if there were @@ -1473,6 +1475,17 @@ function require_valgrind() { exit 0 fi fi + + # Check if Valgrind is enabled in the test build + disable_exit_on_error + ../valgrind_check/valgrind_check + ret=$? + restore_exit_on_error + if [ $ret -ne 0 ]; then + msg=$(interactive_yellow STDOUT "SKIP:") + echo -e "$UNITTEST_NAME: $msg Valgrind is required but the Valgrind support has been disabled at compile time" + exit 0 + fi } # @@ -1650,6 +1663,10 @@ function require_sds() { msg "$UNITTEST_NAME: SKIP not compiled with support for shutdown state" exit 0 fi + if [[ $PMEMOBJ_CONF = *'sds.at_create=0'* ]]; then + msg "$UNITTEST_NAME: SKIP the shutdown state has been disabled by the PMEMOBJ_CONF environment variable" + exit 0 + fi return 0 } @@ -1859,7 +1876,12 @@ function setup() { lock_devdax fi - export PMEMOBJ_CONF="fallocate.at_create=0;" + export PMEMOBJ_CONF="${PMEMOBJ_CONF};fallocate.at_create=0" + + # disable SDS for non-pmem tests + if [ "$REAL_FS" = "non-pmem" ]; then + export PMEMOBJ_CONF="${PMEMOBJ_CONF};sds.at_create=0" + fi } # diff --git a/src/test/unittest/valgrind.py b/src/test/unittest/valgrind.py index abbc9723727..1af65357555 100644 --- a/src/test/unittest/valgrind.py +++ b/src/test/unittest/valgrind.py @@ -200,6 +200,14 @@ def _get_valgrind_exe(self, force_enable): else: raise futils.Skip('Valgrind not found') + try: + _ = sp.check_output('./valgrind_check/valgrind_check', + shell=True, universal_newlines=True, + stderr=sp.STDOUT) + except sp.CalledProcessError: + raise futils.Skip( + 'Valgrind is required but the Valgrind support has been disabled at compile time') # noqa: E501 + valgrind_bin = path.join(path.dirname(out), 'valgrind.bin') if path.isfile(valgrind_bin): return valgrind_bin diff --git a/src/test/util_ctl/TEST0 b/src/test/util_ctl/TEST0 index f721eea18ce..15784dd7eb4 100755 --- a/src/test/util_ctl/TEST0 +++ b/src/test/util_ctl/TEST0 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2016-2023, Intel Corporation +# Copyright 2016-2024, Intel Corporation . ../unittest/unittest.sh @@ -10,6 +10,6 @@ set_test_labels fault_injection setup expect_normal_exit\ - ./util_ctl$EXESUFFIX $DIR/testconfig + ./util_ctl$EXESUFFIX $DIR/testconfig 2>/dev/null pass diff --git a/src/test/util_ctl/TEST1 b/src/test/util_ctl/TEST1 index 9df1d2a6bda..981e27f1ea1 100755 --- a/src/test/util_ctl/TEST1 +++ b/src/test/util_ctl/TEST1 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2016-2023, Intel Corporation +# Copyright 2016-2024, Intel Corporation . ../unittest/unittest.sh @@ -12,6 +12,6 @@ configure_valgrind memcheck force-enable setup expect_normal_exit\ - ./util_ctl$EXESUFFIX $DIR/testconfig + ./util_ctl$EXESUFFIX $DIR/testconfig 2>/dev/null pass diff --git a/src/test/util_poolset/grep0.log.match b/src/test/util_poolset/grep0.log.match index 65444a345ac..441bee9364a 100644 --- a/src/test/util_poolset/grep0.log.match +++ b/src/test/util_poolset/grep0.log.match @@ -1,13 +1,14 @@ +src version: $(nW) +$(OPT)compiled with support for shutdown state +$(OPT)compiled with libndctl 63+ pid $(N): program: $(nW)/util_poolset$(nW) ut version 1.0 -src version: $(nW) $(OPT)compiled with support for Valgrind pmemcheck $(OPT)compiled with support for Valgrind helgrind $(OPT)compiled with support for Valgrind memcheck $(OPT)compiled with support for Valgrind drd -$(OPT)compiled with support for shutdown state -$(OPT)compiled with libndctl 63+ open "$(nW)/testset0": No such file or directory +cannot create pool set -- '$(nW)/testset0' $(OPT)Cannot read device usc - ndctl is not available $(OPT)Unsafe shutdown count is not supported for this source $(OPT)Cannot read device usc - ndctl is not available @@ -19,17 +20,32 @@ $(OPT)Unsafe shutdown count is not supported for this source $(OPT)Cannot read device usc - ndctl is not available $(OPT)Unsafe shutdown count is not supported for this source size 1000000 smaller than 2097152 +failed to create file: $(nW)/testfile41 size 1000000 smaller than 2097152 +failed to create file: $(nW)/testfile52 open "$(nW)/nodir/testfile62": No such file or directory +failed to create file: $(nW)/testfile62 open "/proc/testfile72": Permission denied +failed to create file: /proc/testfile72 posix_fallocate "$(nW)/testfile82", 1073741824: No space left on device +failed to create file: $(nW)/testfile82 open "$(nW)/testfile102": Permission denied +failed to open file: $(nW)/testfile102 file size does not match config: $(nW)testfile113, 4194304 != 1048576 size 12288 smaller than 2097152 +failed to open file: $(nW)/testfile122 size 12288 smaller than 2097152 +failed to open file: $(nW)/testfile131 file size does not match config: $(nW)testfile142, 4194304 != 8388608 file size does not match config: $(nW)testfile152, 3145728 != 4194304 Non-empty file detected +header creation failed - part #1 +replica #0 headers initialization failed +replica #0 creation failed Non-empty file detected +header creation failed - part #0 +replica #0 headers initialization failed +replica #0 creation failed open "$(nW)/testset23": Permission denied +cannot create pool set -- '$(nW)/testset23' reservation pool size 1048576 smaller than 4194304 diff --git a/src/test/util_poolset/grep1.log.match b/src/test/util_poolset/grep1.log.match index 20a69f0e9c7..370ed3dee53 100644 --- a/src/test/util_poolset/grep1.log.match +++ b/src/test/util_poolset/grep1.log.match @@ -1,25 +1,35 @@ +src version: $(nW) +$(OPT)compiled with support for shutdown state +$(OPT)compiled with libndctl 63+ pid $(N): program: $(nW)/util_poolset$(nW) ut version 1.0 -src version: $(nW) $(OPT)compiled with support for Valgrind pmemcheck $(OPT)compiled with support for Valgrind helgrind $(OPT)compiled with support for Valgrind memcheck $(OPT)compiled with support for Valgrind drd -$(OPT)compiled with support for shutdown state -$(OPT)compiled with libndctl 63+ open "$(nW)/testset0": No such file or directory +cannot open pool set -- '$(nW)/testset0' invalid major version (0) +header check failed - part #0 open "$(nW)/testset2": Permission denied +cannot open pool set -- '$(nW)/testset2' open "$(nW)/testfile31": No such file or directory -cannot open the part -- "$(nW)/testfile31": No such file or directory +failed to open file: $(nW)/testfile31 open "$(nW)/testfile32": No such file or directory -cannot open the part -- "$(nW)/testfile32": No such file or directory +failed to open file: $(nW)/testfile32 open "$(nW)/testfile31": No such file or directory +failed to open file: $(nW)/testfile31 open "$(nW)/testfile42": No such file or directory +failed to open file: $(nW)/testfile42 size 1048576 smaller than 2097152 +failed to open file: $(nW)/testfile51 size 1048576 smaller than 2097152 +failed to open file: $(nW)/testfile62 size 2097151 smaller than 2097152 +failed to open file: $(nW)/testfile71 open "$(nW)/testfile82": Permission denied +failed to open file: $(nW)/testfile82 file size does not match config: $(nW)testfile92, 4194304 != 65536 file size does not match config: $(nW)testfile102, 4194303 != 4194304 invalid major version (0) +header check failed - part #0 diff --git a/src/test/util_poolset/grep10.log.match b/src/test/util_poolset/grep10.log.match index f7d99cc936f..091561cbf37 100644 --- a/src/test/util_poolset/grep10.log.match +++ b/src/test/util_poolset/grep10.log.match @@ -1,12 +1,12 @@ +src version: $(nW) +$(OPT)compiled with support for shutdown state +$(OPT)compiled with libndctl 63+ pid $(N): program: $(nW)/util_poolset$(nW) ut version 1.0 -src version: $(nW) $(OPT)compiled with support for Valgrind pmemcheck $(OPT)compiled with support for Valgrind helgrind $(OPT)compiled with support for Valgrind memcheck $(OPT)compiled with support for Valgrind drd -$(OPT)compiled with support for shutdown state -$(OPT)compiled with libndctl 63+ invalid checksum of pool header wrong pool type: "ERRORXX" pool version 99 (library expects 1) diff --git a/src/test/util_poolset/grep2.log.match b/src/test/util_poolset/grep2.log.match index f7d99cc936f..63958613a09 100644 --- a/src/test/util_poolset/grep2.log.match +++ b/src/test/util_poolset/grep2.log.match @@ -1,25 +1,35 @@ +src version: $(nW) +$(OPT)compiled with support for shutdown state +$(OPT)compiled with libndctl 63+ pid $(N): program: $(nW)/util_poolset$(nW) ut version 1.0 -src version: $(nW) $(OPT)compiled with support for Valgrind pmemcheck $(OPT)compiled with support for Valgrind helgrind $(OPT)compiled with support for Valgrind memcheck $(OPT)compiled with support for Valgrind drd -$(OPT)compiled with support for shutdown state -$(OPT)compiled with libndctl 63+ invalid checksum of pool header +header check failed - part #1 wrong pool type: "ERRORXX" +header check failed - part #1 pool version 99 (library expects 1) +header check failed - part #1 invalid reserved values invalid machine value invalid data value invalid machine_class value invalid alignment_desc value wrong architecture flags +header check failed - part #1 incompatible feature flags +header check failed - part #1 incompatible feature flags +header check failed - part #1 incompatible feature flags +header check failed - part #1 wrong pool set UUID +header check failed - part #1 wrong part UUID +header check failed - part #0 wrong part UUID +header check failed - part #0 wrong replica UUID diff --git a/src/test/util_poolset/grep3.log.match b/src/test/util_poolset/grep3.log.match index 96b81b9b3b7..4849bc225db 100644 --- a/src/test/util_poolset/grep3.log.match +++ b/src/test/util_poolset/grep3.log.match @@ -1,9 +1,9 @@ +src version: $(nW) +$(OPT)compiled with support for shutdown state +$(OPT)compiled with libndctl 63+ pid $(N): program: $(nW)util_poolset$(nW) ut version 1.0 -src version: $(nW) $(OPT)compiled with support for Valgrind pmemcheck $(OPT)compiled with support for Valgrind helgrind $(OPT)compiled with support for Valgrind memcheck $(OPT)compiled with support for Valgrind drd -$(OPT)compiled with support for shutdown state -$(OPT)compiled with libndctl 63+ diff --git a/src/test/util_poolset/grep4.log.match b/src/test/util_poolset/grep4.log.match index 96b81b9b3b7..4849bc225db 100644 --- a/src/test/util_poolset/grep4.log.match +++ b/src/test/util_poolset/grep4.log.match @@ -1,9 +1,9 @@ +src version: $(nW) +$(OPT)compiled with support for shutdown state +$(OPT)compiled with libndctl 63+ pid $(N): program: $(nW)util_poolset$(nW) ut version 1.0 -src version: $(nW) $(OPT)compiled with support for Valgrind pmemcheck $(OPT)compiled with support for Valgrind helgrind $(OPT)compiled with support for Valgrind memcheck $(OPT)compiled with support for Valgrind drd -$(OPT)compiled with support for shutdown state -$(OPT)compiled with libndctl 63+ diff --git a/src/test/util_poolset/grep5.log.match b/src/test/util_poolset/grep5.log.match index 96b81b9b3b7..4849bc225db 100644 --- a/src/test/util_poolset/grep5.log.match +++ b/src/test/util_poolset/grep5.log.match @@ -1,9 +1,9 @@ +src version: $(nW) +$(OPT)compiled with support for shutdown state +$(OPT)compiled with libndctl 63+ pid $(N): program: $(nW)util_poolset$(nW) ut version 1.0 -src version: $(nW) $(OPT)compiled with support for Valgrind pmemcheck $(OPT)compiled with support for Valgrind helgrind $(OPT)compiled with support for Valgrind memcheck $(OPT)compiled with support for Valgrind drd -$(OPT)compiled with support for shutdown state -$(OPT)compiled with libndctl 63+ diff --git a/src/test/util_poolset/grep6.log.match b/src/test/util_poolset/grep6.log.match index 08bd647a7e5..dd61ea30a0d 100644 --- a/src/test/util_poolset/grep6.log.match +++ b/src/test/util_poolset/grep6.log.match @@ -1,16 +1,23 @@ +src version: $(nW) +$(OPT)compiled with support for shutdown state +$(OPT)compiled with libndctl 63+ pid $(N): program: $(nW)util_poolset$(nW) ut version 1.0 -src version: $(nW) $(OPT)compiled with support for Valgrind pmemcheck $(OPT)compiled with support for Valgrind helgrind $(OPT)compiled with support for Valgrind memcheck $(OPT)compiled with support for Valgrind drd -$(OPT)compiled with support for shutdown state -$(OPT)compiled with libndctl 63+ cannot mix directories and files in a set +cannot create pool set -- '$(nW)/testset2' cannot mix directories and files in a set +cannot create pool set -- '$(nW)/testset3' cannot mix directories and files in a set +cannot create pool set -- '$(nW)/testset4' cannot mix directories and files in a set +cannot create pool set -- '$(nW)/testset6' cannot mix directories and files in a set +cannot create pool set -- '$(nW)/testset7' cannot mix directories and files in a set +cannot create pool set -- '$(nW)/testset8' cannot mix directories and files in a set +cannot create pool set -- '$(nW)/testset9' diff --git a/src/test/util_poolset/grep7.log.match b/src/test/util_poolset/grep7.log.match index 712b6a897dd..c6a96c6a44f 100644 --- a/src/test/util_poolset/grep7.log.match +++ b/src/test/util_poolset/grep7.log.match @@ -1,8 +1,8 @@ -pid $(N): program: $(nW)util_poolset$(nW) -ut version 1.0 src version: $(nW) $(OPT)compiled with support for shutdown state $(OPT)compiled with libndctl 63+ +pid $(N): program: $(nW)util_poolset$(nW) +ut version 1.0 the NOHDRS poolset option is not supported for local poolsets the NOHDRS poolset option is not supported for local poolsets the NOHDRS poolset option is not supported for local poolsets diff --git a/src/test/util_ravl/Makefile b/src/test/util_ravl/Makefile index d5be4c0e747..f7cfc19f936 100644 --- a/src/test/util_ravl/Makefile +++ b/src/test/util_ravl/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2018-2020, Intel Corporation +# Copyright 2018-2024, Intel Corporation # # @@ -7,7 +7,8 @@ # TARGET = util_ravl -OBJS = util_ravl.o alloc.o ravl.o out.o util_posix.o util.o +OBJS = util_ravl.o +LIBPMEMCORE = y INCS += -I$(TOP)/src/common include ../Makefile.inc diff --git a/src/test/valgrind_check/.gitignore b/src/test/valgrind_check/.gitignore new file mode 100644 index 00000000000..15bae9bd64e --- /dev/null +++ b/src/test/valgrind_check/.gitignore @@ -0,0 +1 @@ +valgrind_check diff --git a/src/test/valgrind_check/Makefile b/src/test/valgrind_check/Makefile new file mode 100644 index 00000000000..b6d2a7129e8 --- /dev/null +++ b/src/test/valgrind_check/Makefile @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation + +# +# src/test/valgrind_check/Makefile -- build valgrind_check unit test +# +TARGET = valgrind_check +OBJS = valgrind_check.o + +include ../Makefile.inc diff --git a/src/test/valgrind_check/README b/src/test/valgrind_check/README new file mode 100644 index 00000000000..ba3ee397cd5 --- /dev/null +++ b/src/test/valgrind_check/README @@ -0,0 +1,7 @@ +Persistent Memory Development Kit + +This is src/test/valgrind_check/README. + +This directory contains a unit test for Valgrind enabling. + +The program in valgrind_check.c verifies if Valgrind was enabled during build. diff --git a/src/test/valgrind_check/TEST0 b/src/test/valgrind_check/TEST0 new file mode 100755 index 00000000000..d7ffd137f8c --- /dev/null +++ b/src/test/valgrind_check/TEST0 @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation + +# +# src/test/valgrind_check/TEST0 -- unit test for valgrind_check +# + +. ../unittest/unittest.sh + +require_test_type short +require_valgrind + +setup + +expect_normal_exit ./valgrind_check$EXESUFFIX + +pass diff --git a/src/test/valgrind_check/valgrind_check.c b/src/test/valgrind_check/valgrind_check.c new file mode 100644 index 00000000000..b719be9a0b1 --- /dev/null +++ b/src/test/valgrind_check/valgrind_check.c @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* Copyright 2024, Intel Corporation */ + +/* + * valgrind_check.c -- unit test Valgrind enabled during build + * + * usage: valgrind_check + * + */ + +#include "valgrind_internal.h" + +#ifndef VALGRIND_ENABLED +#error Valgrind tools not properly configured +#endif + +int +main(int argc, char *argv[]) +{ +#if VALGRIND_ENABLED + return 0; +#else + return 1; +#endif +} diff --git a/src/tools/pmempool/common.c b/src/tools/pmempool/common.c index 4fac0ca94a4..c814380599f 100644 --- a/src/tools/pmempool/common.c +++ b/src/tools/pmempool/common.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2014-2023, Intel Corporation */ +/* Copyright 2014-2024, Intel Corporation */ /* * common.c -- definitions of common functions @@ -1304,7 +1304,7 @@ util_pool_clear_badblocks(const char *path, int create) int ret = util_poolset_create_set(&setp, path, 0, 0, POOL_OPEN_IGNORE_SDS); if (ret < 0) { - LOG(2, "cannot open pool set -- '%s'", path); + CORE_LOG_ERROR("cannot open pool set -- '%s'", path); return -1; } diff --git a/src/tools/pmempool/output.c b/src/tools/pmempool/output.c index 63df4f5244b..cf5e929d3ac 100644 --- a/src/tools/pmempool/output.c +++ b/src/tools/pmempool/output.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2014-2023, Intel Corporation */ +/* Copyright 2014-2024, Intel Corporation */ /* * output.c -- definitions of output printing related functions @@ -16,9 +16,11 @@ #include #include #include + #include "feature.h" #include "common.h" #include "output.h" +#include "core_assert.h" #define _STR(s) #s #define STR(s) _STR(s) @@ -774,7 +776,7 @@ out_get_incompat_features_str(uint32_t incompat) /* print the value and the left square bracket */ ret = util_snprintf(str_buff, STR_MAX, "0x%x [", incompat); if (ret < 0) { - ERR("snprintf for incompat features: %d", ret); + ERR_WO_ERRNO("snprintf for incompat features: %d", ret); return ""; } diff --git a/src/tools/pmempool/output.h b/src/tools/pmempool/output.h index 80922f2ec0a..28b57aeebb1 100644 --- a/src/tools/pmempool/output.h +++ b/src/tools/pmempool/output.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause */ -/* Copyright 2014-2023, Intel Corporation */ +/* Copyright 2014-2024, Intel Corporation */ /* * output.h -- declarations of output printing related functions @@ -14,8 +14,6 @@ void out_set_stream(FILE *stream); void out_set_prefix(const char *prefix); void out_set_col_width(unsigned col_width); void outv_err(const char *fmt, ...) FORMAT_PRINTF(1, 2); -void out_err(const char *file, int line, const char *func, - const char *fmt, ...) FORMAT_PRINTF(4, 5); void outv_err_vargs(const char *fmt, va_list ap); void outv_indent(int vlevel, int i); void outv(int vlevel, const char *fmt, ...) FORMAT_PRINTF(2, 3); diff --git a/src/tools/pmempool/rm.c b/src/tools/pmempool/rm.c index d142da15dc1..aa106dd8c25 100644 --- a/src/tools/pmempool/rm.c +++ b/src/tools/pmempool/rm.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2014-2022, Intel Corporation */ +/* Copyright 2014-2024, Intel Corporation */ /* * rm.c -- pmempool rm command main source file @@ -14,6 +14,7 @@ #include "os.h" #include "out.h" +#include "last_error_msg.h" #include "common.h" #include "output.h" #include "file.h" @@ -169,7 +170,7 @@ rm_poolset(const char *file) int ret = util_poolset_foreach_part(file, rm_poolset_cb, &error); if (ret == -1) { outv_err("parsing poolset failed: %s\n", - out_get_errormsg()); + last_error_msg_get()); return ret; } diff --git a/utils/ansible/README.md b/utils/ansible/README.md index 2da277aa391..28db8397a7e 100644 --- a/utils/ansible/README.md +++ b/utils/ansible/README.md @@ -56,10 +56,10 @@ Use the below command to configure persistent memory on Intel servers to be used for PMDK libraries tests execution. ```sh export TARGET_IP= # ip of the target -export ROOT_PASSWORD= # a password of root on the target +export USER_PASSWORD= # a password on the target ansible-playbook -i $TARGET_IP, configure-pmem.yml \ - --extra-vars "host=all ansible_user=root ansible_password=$ROOT_PASSWORD \ - newRegions=true testUser=pmdkuser" + --extra-vars "host=all ansible_user=pmdkuser ansible_password=$USER_PASSWORD \ + newRegions=true" ``` The script creates a new region and set of namespaces regardless of the configuration already available on the target platform. @@ -81,10 +81,9 @@ the test environment. parameter in this case. ```sh export TARGET_IP= # ip of the target -export ROOT_PASSWORD= # a password of root on the target +export USER_PASSWORD= # a password on the target ansible-playbook -i $TARGET_IP, configure-pmem.yml \ - --extra-vars "host=all ansible_user=root ansible_password=$ROOT_PASSWORD \ - testUser=pmdkuser" + --extra-vars "host=all ansible_user=pmdkuser ansible_password=$USER_PASSWORD" ``` # Installing a GitHub Action self-hosted runner using Ansible palybook @@ -94,16 +93,16 @@ the pmem/pmdk repository. ```sh export TARGET_IP= # ip of the target -export ROOT_PASSWORD= # a password of root on the target +export USER_PASSWORD= # a password on the target export GHA_TOKEN= # GitHub token generated for a new self-hosted runner export HOST_NAME= # host's name that will be visible on GitHub export LABELS= # rhel or opensuse export VARS_GHA= # e.g. proxy settings: http_proxy=http://proxy-dmz.{XXX}.com:911,https_proxy=http://proxy-dmz.{XXX}.com:912 ansible-playbook -i $TARGET_IP, configure-self-hosted-runner.yml --extra-vars - "host=all ansible_user=root ansible_password=$ROOT_PASSWORD testUser=pmdkuser \ + "host=all ansible_user=pmdkuser ansible_password=$USER_PASSWORD \ runner_name=$HOST_NAME labels=$LABELS token=$GHA_TOKEN vars_gha=$VARS_GHA" ``` -**Note**: To obtain a token for a new self hosted runer visit +**Note**: To obtain a token for a new self-hosted runer visit [Create self-hosted runner](https://gib.com/pmem/pmdk/settings/actions/runners/new) . @@ -127,15 +126,15 @@ export SETUP_SCRIPT= # opensuse-setup.yml or rockylinux-setup.yml sudo ansible-playbook $SETUP_SCRIPT --extra-vars "testUser=pmdkuser" ``` **Note**: If a reboot is necessary, as described above, perform it manually and -rerun the playbook withot in question. +rerun the playbook without in question. -And next: +And next log in as `pmdkuser`: ```sh -sudo ansible-playbook ./configure-pmem.yml --extra-vars "testUser=pmdkuser newRegions=true" +ansible-playbook configure-pmem.yml --extra-vars "newRegions=true" # you will have to perform a reboot manually -reboot +sudo reboot # and re-run the playbook without newRegions=true to finalize the setup -sudo ansible-playbook ./configure-pmem.yml --extra-vars "testUser=pmdkuser" +ansible-playbook configure-pmem.yml ``` # Example - GitHub self-hosted runner setup @@ -163,19 +162,24 @@ reboot # ... cd pmdk/utils/ansible ansible-playbook rockylinux-setup.yml --extra-vars "testUser=pmdkuser testUserPass=pmdkpass" +``` +Log in as `pmdkuser` and execute: +```sh +# as pmdkuser +cd pmdk/utils/ansible ansible-playbook configure-pmem.yml --extra-vars "newRegions=true" -reboot +sudo reboot # ... cd pmdk/utils/ansible # note - no newRegions=true when running the playbook after the reboot -ansible-playbook configure-pmem.yml --extra-vars "testUser=pmdkuser" +ansible-playbook configure-pmem.yml export GHA_TOKEN= # GitHub token generated for a new self-hosted runner export HOST_NAME=`hostname` -export LABELS= rhel +export LABELS=rhel export VARS_GHA=http_proxy=http://proxy-dmz.{XXX}.com:911,https_proxy=http://proxy-dmz.{XXX}.com:912 ansible-playbook configure-self-hosted-runner.yml -extra-vars \ -"testUser=pmdkuser runner_name=$HOST_NAME labels=$LABELS token=$GHA_TOKEN vars_gha=$VARS_GHA" +"runner_name=$HOST_NAME labels=$LABELS token=$GHA_TOKEN vars_gha=$VARS_GHA" cd rm -rf pmdk ``` @@ -192,25 +196,30 @@ Update playbooks to be used directly on the target as described [above](#provisi and execute: ```sh # as root: -ansible-playbook ./opensuse-setup.yml --extra-vars "testUser=pmdkuser testUserPass=pmdkpass" +ansible-playbook opensuse-setup.yml --extra-vars "testUser=pmdkuser testUserPass=pmdkpass" # reboot shall be performed only if the playbook requests to do it. reboot # ... cd pmdk/utils/ansible -ansible-playbook ./opensuse-setup.yml --extra-vars "testUser=pmdkuser testUserPass=pmdkpass" -ansible-playbook ./configure-pmem.yml --extra-vars "newRegions=true" -reboot +ansible-playbook opensuse-setup.yml --extra-vars "testUser=pmdkuser testUserPass=pmdkpass" +``` +Log in as `pmdkuser` and execute: +```sh +# as pmdkuser: +cd pmdk/utils/ansible +ansible-playbook configure-pmem.yml --extra-vars "newRegions=true" +sudo reboot # ... cd pmdk/utils/ansible # note - no newRegions=true when running the playbook after the reboot -ansible-playbook ./configure-pmem.yml --extra-vars "testUser=pmdkuser" +ansible-playbook configure-pmem.yml export GHA_TOKEN= # GitHub token generated for a new self-hosted runner export HOST_NAME=`hostname` -export LABELS= opensuse +export LABELS=opensuse export VARS_GHA=http_proxy=http://proxy-dmz.{XXX}.com:911,https_proxy=http://proxy-dmz.{XXX}.com:912 ansible-playbook configure-self-hosted-runner.yml -extra-vars \ -"testUser=pmdkuser runner_name=$HOST_NAME labels=$LABELS token=$GHA_TOKEN vars_gha=$VARS_GHA" +"runner_name=$HOST_NAME labels=$LABELS token=$GHA_TOKEN vars_gha=$VARS_GHA" cd rm -rf pmdk ``` diff --git a/utils/ansible/configure-pmem.yml b/utils/ansible/configure-pmem.yml index 6390487ec20..4d78003132a 100644 --- a/utils/ansible/configure-pmem.yml +++ b/utils/ansible/configure-pmem.yml @@ -16,11 +16,26 @@ # # Below are examples of how to use this file: # -# 1) setup PMem for the first time (establish regions): -# sudo ansible-playbook ./configure-pmem.yml --extra-vars "testUser=pmdkuser newRegions='true'" +# 1) remotely +# export TARGET_IP= # ip of the target +# export USER_PASSWORD= # a password on the target +# a) setup PMem for the first time (establish regions): +# ansible-playbook -i $TARGET_IP, configure-pmem.yml --extra-vars \ +# "host=all ansible_user=pmdkuser ansible_password=$USER_PASSWORD newRegions=true" +# b) setup PMem if it already has been initialized before: +# ansible-playbook -i $TARGET_IP, configure-pmem.yml --extra-vars \ +# "host=all ansible_user=pmdkuser ansible_password=$USER_PASSWORD" # -# 2) setup PMem if it already has been initialized before: -# sudo ansible-playbook ./configure-pmem.yml --extra-vars "testUser=pmdkuser" +# 2) locally +# For a playbook to be used on a local server please log in as pmdkuser: +# a) comment out the first command: # -hosts: "{{ host }}" +# b) uncomment the next two lines: +# - hosts: localhost +# connection: local +# c) setup PMem for the first time (establish regions): +# ansible-playbook configure-pmem.yml --extra-vars "newRegions=true" +# d) setup PMem if it already has been initialized before: +# ansible-playbook configure-pmem.yml # - hosts: "{{ host }}" @@ -28,45 +43,50 @@ # connection: local vars: newRegions: false - testUser: pmdkuser mountPoint: /mnt/pmem0 tasks: - - name: "Test if ndctl is installed" + - name: Test if ndctl is installed shell: which ndctl - - name: "Remove fstab entry if it exist" + - name: Remove fstab entry if it exist ansible.posix.mount: path: "{{ mountPoint }}" state: absent_from_fstab backup: true + become: true - - name: "Unmount namespaces if they exist" - shell: sudo umount /dev/pmem* || true + - name: Unmount namespaces if they exist + shell: umount /dev/pmem* || true + become: true - - name: "Disable current namespaces" - shell: sudo ndctl disable-namespace all || true + - name: Disable current namespaces + shell: ndctl disable-namespace all || true register: namespaces + become: true - - name: "Destroy current namespaces" - shell: sudo ndctl destroy-namespace all || true + - name: Destroy current namespaces + shell: ndctl destroy-namespace all || true register: namespaces + become: true - debug: var=namespaces - - name: "Create new regions" + - name: Create new regions block: - - name: "Test if ipmctl is installed" + - name: Test if ipmctl is installed shell: which ipmctl - - name: "Create goal in AppDirectInterleaved mode" + - name: Create goal in AppDirectInterleaved mode shell: ipmctl create -f -goal + become: true - - name: "Reboot machine in order to apply new AppDirectInterleaved goal" + - name: Reboot machine in order to apply new AppDirectInterleaved goal reboot: when: newRegions == 'true' + become: true - - name: "Create new namespace configuration" + - name: Create new namespace configuration shell: | #!/usr/bin/env bash DEV_DAX_R=0x0000 @@ -74,7 +94,7 @@ function check_alignment() { local size=$1 - local interleave_width=$(sudo ipmctl show -dimm -socket 1 | grep "0x1" | wc -l) + local interleave_width=$(ipmctl show -dimm -socket 1 | grep "0x1" | wc -l) local size_alignment=$(expr $size % $interleave_width) if [ "$size_alignment" -gt "0" ]; then @@ -93,7 +113,7 @@ size_option="" fi - local cmd="sudo ndctl create-namespace --mode devdax -a ${align} ${size_option} -r ${DEV_DAX_R} -f" + local cmd="ndctl create-namespace --mode devdax -a ${align} ${size_option} -r ${DEV_DAX_R} -f" result=$(${cmd}) if [ $? -ne 0 ]; then exit 1; @@ -101,7 +121,7 @@ } function create_fsdax() { - local cmd="sudo ndctl create-namespace --mode fsdax -r ${FS_DAX_R} -f" + local cmd="ndctl create-namespace --mode fsdax -r ${FS_DAX_R} -f" result=$(${cmd}) if [ $? -ne 0 ]; then exit 1; @@ -125,27 +145,28 @@ pmem_name=$(create_fsdax) if [ ! -d "{{ mountPoint }}" ]; then - sudo mkdir {{ mountPoint }} + mkdir {{ mountPoint }} fi - sudo mkfs.ext4 -F /dev/${pmem_name} - sudo mount -o dax=always /dev/${pmem_name} {{ mountPoint }} - sudo chown -R {{ testUser }} {{ mountPoint }} + mkfs.ext4 -F /dev/${pmem_name} + mount -o dax=always /dev/${pmem_name} {{ mountPoint }} + chown -R $(id -u {{ ansible_user }}):$(id -g {{ ansible_user }}) {{ mountPoint }} - sudo chmod 777 /dev/dax* || true - sudo chmod a+rw /sys/bus/nd/devices/region*/deep_flush - sudo chmod +r /sys/bus/nd/devices/ndbus*/region*/resource - sudo chmod +r /sys/bus/nd/devices/ndbus*/region*/dax*/resource + chmod 777 /dev/dax* + chmod +rw /sys/bus/nd/devices/region*/deep_flush + chmod +r /sys/bus/nd/devices/ndbus*/region*/resource + chmod +r /sys/bus/nd/devices/ndbus*/region*/dax*/resource register: script + become: true - debug: var=script - - name: "Get PMEM device name for {{ mountPoint }} mount point" + - name: Get PMEM device name for {{ mountPoint }} mount point shell: | - mount | sed -nr "s/^.*(\/dev\/\S+) on \/mnt\/pmem0.*$/\1/p" + mount | sed -nr 's/^.*(\/dev\/\S+) on \/mnt\/pmem0.*$/\1/p' register: pmem_name - - name: "Add /etc/fstab entry for PMEM" + - name: Add /etc/fstab entry for PMEM ansible.posix.mount: path: "{{ mountPoint }}" src: "{{ pmem_name.stdout }}" @@ -153,3 +174,4 @@ opts: rw,relatime,dax=always state: present backup: true + become: true diff --git a/utils/ansible/configure-self-hosted-runner.yml b/utils/ansible/configure-self-hosted-runner.yml index b2b8f28b1a8..1b2c6020d2f 100644 --- a/utils/ansible/configure-self-hosted-runner.yml +++ b/utils/ansible/configure-self-hosted-runner.yml @@ -5,17 +5,17 @@ # Examples below show how to use this file: # 1) remotely # export TARGET_IP= # ip of the target -# export ROOT_PASSWORD= # a password of root on the target +# export USER_PASSWORD= # a password on the target # export GHA_TOKEN= # a GitHub token generated for a new self-hosted runner # export HOST_NAME= # host's name that will be visible on GitHub # export LABELS= # rhel or opensuse # export VARS_GHA=http_proxy=http://proxy-dmz.{XXX}.com:911,https_proxy=http://proxy-dmz.{XXX}.com:912 # ansible-playbook -i $TARGET_IP, configure-self-hosted-runner.yml --extra-vars \ -# "host=all ansible_user=root ansible_password=$ROOT_PASSWORD testUser=pmdkuser \ +# "host=all ansible_user=pmdkuser ansible_password=$USER_PASSWORD \ # runner_name=$HOST_NAME labels=$LABELS token=$GHA_TOKEN vars_gha=$VARS_GHA" # # 2) locally -# For a playbook to be used on a local server please: +# For a playbook to be used on a local server please log in as pmdkuser: # a) comment out the first command: # -hosts: "{{ host }}" # b) uncomment the next two lines: # - hosts: localhost @@ -36,9 +36,8 @@ #- hosts: localhost # connection: local vars: - testUser: pmdkuser - package_url: https://github.com/actions/runner/releases/download/v2.306.0/actions-runner-linux-x64-2.306.0.tar.gz - runner_folder: /home/{{ testUser }}/actions-runner + package_url: https://github.com/actions/runner/releases/download/v2.311.0/actions-runner-linux-x64-2.311.0.tar.gz + runner_folder: /home/{{ ansible_user }}/actions-runner repo_url: https://github.com/pmem/pmdk vars_list: "{{ vars_gha.split(',') }}" # token: # a GitHub token generated for a new self-hosted runner @@ -46,24 +45,21 @@ # runner_name: # Host name that will be visible on GitHub tasks: - - name: "Create a runner folder" + - name: Create a runner folder file: - path: '{{ runner_folder }}' + path: "{{ runner_folder }}" state: directory force: yes - - name: "Download and extract the installer" + - name: Download and extract the installer unarchive: - src: '{{ package_url }}' - dest: '{{ runner_folder }}' + src: "{{ package_url }}" + dest: "{{ runner_folder }}" remote_src: yes - - name: "Change owner to {{ testUser }}" - shell: chown -R $(id -u {{ testUser }}):$(id -g {{ testUser }}) {{ runner_folder }} - # Make sure the following environment variables are present in the env # to ensure propagation to the actions-runner's environment. - - name: "Add env variables into env.sh checklist" + - name: Add env variables into env.sh checklist lineinfile: path: "{{ runner_folder }}/env.sh" line: " '{{ item.line }}'" @@ -72,30 +68,29 @@ - line: PKG_CONFIG_PATH - line: HOME - - name: "Add runner to GHA" + - name: Add runner to GHA shell: | cd {{ runner_folder }} ./config.sh --url {{ repo_url }} --token {{ token }} --name {{ runner_name }} --labels {{ labels }} --runnergroup Default --work _work - become: yes - become_user: '{{ testUser }}' - - name: "Install runner service" - shell: | - cd {{ runner_folder }} - ./svc.sh install {{ testUser }} + - name: Install runner service + shell: ./svc.sh install {{ ansible_user }} + args: + chdir: "{{ runner_folder }}" become: true - become_user: root - - name: "Insert variables into runsvc.sh file" + - name: Insert variables into runsvc.sh file lineinfile: path: "{{ runner_folder }}/runsvc.sh" line: "export {{ item }}" insertbefore: "insert anything to setup env when running as a service" loop: "{{ vars_list }}" - - name: "Enable and restart runner service" + - name: Enable and restart runner service + # Note: The service name must match the repo_url. + # repo_url: https://github.com/{OWNER}/{REPO} + # service: actions.runner.{OWNER}-{REPO}.{{ runner_name }}.service shell: | systemctl enable actions.runner.pmem-pmdk.{{ runner_name }}.service systemctl restart actions.runner.pmem-pmdk.{{ runner_name }}.service become: true - become_user: root diff --git a/utils/ansible/opensuse-setup.yml b/utils/ansible/opensuse-setup.yml index b6dcd9a1b47..57406392f3e 100644 --- a/utils/ansible/opensuse-setup.yml +++ b/utils/ansible/opensuse-setup.yml @@ -14,41 +14,40 @@ testUserPass: pmdkpass tasks: - - - name: "Update kernel packages" + - name: Update kernel packages package: name: "kernel-default" state: latest register: isUpdated - - name: "Update OS packages" + - name: Update OS packages package: name: "*" state: latest - - name: "Reboot platform to apply updates" + - name: Reboot platform to apply updates reboot: when: isUpdated.changed - - name: "Add permanent pkg config variable to the system" + - name: Add permanent pkg config variable to the system env: state: present name: PKG_CONFIG_PATH value: /usr/local/lib64/pkgconfig:/usr/local/lib/pkgconfig - - name: "Add permanent ld library path to the system" + - name: Add permanent ld library path to the system env: state: present name: LD_LIBRARY_PATH value: /usr/lib64:/usr/lib - - name: "Add openSUSE Leap 15.4 Oss repo" + - name: Add openSUSE Leap 15.4 Oss repo zypper_repository: name: oss - repo: 'http://download.opensuse.org/distribution/leap/15.4/repo/oss' + repo: "http://download.opensuse.org/distribution/leap/15.4/repo/oss" state: present - - name: "Install Valgrind dependencies" + - name: Install Valgrind dependencies package: state: present name: @@ -58,7 +57,7 @@ - findutils - git - - name: "Install PMDK base dependencies" + - name: Install PMDK base dependencies package: state: present name: @@ -70,13 +69,15 @@ - systemd - libndctl-devel - - name: "Install benchmarks dependencies (optional)" + - name: Install benchmarks dependencies (optional) package: state: present name: - glib2-devel + - numactl + - python3-pandas - - name: "Install examples dependencies (optional)" + - name: Install examples dependencies (optional) package: state: present name: @@ -85,13 +86,13 @@ - ncurses-devel - libuv-devel - - name: "Install documentation dependencies (optional)" + - name: Install documentation dependencies (optional) package: state: present name: - pandoc - - name: "Install tests dependencies" + - name: Install tests dependencies package: state: present name: @@ -100,14 +101,14 @@ - libunwind-devel - strace - - name: "Install packaging dependencies" + - name: Install packaging dependencies package: state: present name: - rpm-build - rpmdevtools - - name: "Install miscellaneous dependencies" + - name: Install miscellaneous dependencies package: state: present name: @@ -123,7 +124,7 @@ - xmlto - jq - - name: "Install ndctl dependencies" + - name: Install ndctl dependencies package: state: present name: @@ -136,13 +137,13 @@ - libuuid-devel - systemd-devel - - name: "Install ipmctl" + - name: Install ipmctl package: state: present name: - ipmctl - - name: "Install valgrind from source" + - name: Install valgrind from source script: ../docker/images/install-valgrind.sh # Disable AppArmor. @@ -157,7 +158,7 @@ ignore_errors: yes when: ansible_facts['os_family'] == 'Suse' - - name: "Add new user" + - name: Add new user shell: | #!/usr/bin/env bash export USER={{ testUser }} @@ -173,26 +174,26 @@ gpasswd wheel -a $USER when: testUser != None - - name: "Set variable OS" + - name: Set variable OS env: state: present - name: 'OS' - value: 'opensuse/leap' + name: "OS" + value: "opensuse/leap" - - name: "Set variable OS_VER" + - name: Set variable OS_VER env: state: present - name: 'OS_VER' - value: '15' + name: "OS_VER" + value: "15" - - name: "Set variable PACKAGE_MANAGER" + - name: Set variable PACKAGE_MANAGER env: state: present - name: 'PACKAGE_MANAGER' - value: 'rpm' + name: "PACKAGE_MANAGER" + value: "rpm" - - name: "Set variable NOTTY" + - name: Set variable NOTTY env: state: present - name: 'NOTTY' - value: '1' + name: "NOTTY" + value: "1" diff --git a/utils/ansible/rockylinux-setup.yml b/utils/ansible/rockylinux-setup.yml index a5c0771e15c..dcdee1c870b 100644 --- a/utils/ansible/rockylinux-setup.yml +++ b/utils/ansible/rockylinux-setup.yml @@ -14,22 +14,22 @@ testUserPass: pmdkpass tasks: - - name: "Update kernel packages" + - name: Update kernel packages package: name: "kernel.x86_64" state: latest register: isUpdated - - name: "Update OS packages" + - name: Update OS packages package: name: "*" state: latest - - name: "Reboot platform to apply updates" + - name: Reboot platform to apply updates reboot: when: isUpdated.changed - - name: "Add permanent pkg config variable to the system" + - name: Add permanent pkg config variable to the system env: state: present name: PKG_CONFIG_PATH @@ -37,20 +37,20 @@ # For `ansible_distribution_*` variables see: # https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_conditionals.html#commonly-used-facts - - name: "Rocky - adding additional repositories" + - name: Rocky - adding additional repositories block: - - name: "Rocky - adding epel repository" + - name: Rocky - adding epel repository shell: yum install epel-release -y - - name: "Rocky 9 - enabling Power Tools" + - name: Rocky 9 - enabling Power Tools shell: dnf config-manager --enable crb when: ansible_distribution_major_version == "9" - - name: "Rocky 8 - enabling Power Tools" + - name: Rocky 8 - enabling Power Tools shell: dnf config-manager --enable powertools when: ansible_distribution_major_version == "8" - - name: "Install Valgrind dependencies" + - name: Install Valgrind dependencies package: state: present name: @@ -60,7 +60,7 @@ - findutils - git - - name: "Install PMDK base dependencies" + - name: Install PMDK base dependencies package: state: present name: @@ -71,13 +71,19 @@ - passwd - pkgconfig - - name: "Install benchmarks dependencies (optional)" + - name: Install benchmarks dependencies (optional) package: state: present name: - glib2-devel + - numactl + - python3-pip - - name: "Install examples dependencies (optional)" + - name: Install benchmarks dependencies part 2 (optional) + ansible.builtin.pip: + name: pandas + + - name: Install examples dependencies (optional) package: state: present name: @@ -86,13 +92,13 @@ - ncurses-devel - libuv-devel - - name: "Install documentation dependencies (optional)" + - name: Install documentation dependencies (optional) package: state: present name: - pandoc - - name: "Install tests dependencies" + - name: Install tests dependencies package: state: present name: @@ -103,7 +109,7 @@ - openssh-server - strace - - name: "Install packaging dependencies" + - name: Install packaging dependencies package: state: present name: @@ -111,7 +117,7 @@ - rpm-build-libs - rpmdevtools - - name: "Install miscellaneous dependencies" + - name: Install miscellaneous dependencies package: state: present name: @@ -128,13 +134,13 @@ - xmlto - jq - - name: "Install ipmctl" + - name: Install ipmctl package: state: present name: - ipmctl - - name: "Install valgrind from source" + - name: Install valgrind from source script: ../docker/images/install-valgrind.sh # Disable SELinux. @@ -145,9 +151,9 @@ selinux: state: disabled ignore_errors: yes - when: ansible_facts['os_family'] != 'Debian' + when: ansible_facts["os_family"] != "Debian" - - name: "Add new user" + - name: Add new user shell: | #!/usr/bin/env bash export USER={{ testUser }} @@ -158,34 +164,34 @@ echo "%wheel ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers when: testUser != none - - name: "Set variable OS" + - name: Set variable OS env: state: present - name: 'OS' - value: 'rockylinux/rockylinux' + name: "OS" + value: "rockylinux/rockylinux" - - name: "Set variable OS_VER (9)" + - name: Set variable OS_VER (9) env: state: present - name: 'OS_VER' - value: '9' + name: "OS_VER" + value: "9" when: ansible_distribution_major_version == "9" - - name: "Set variable OS_VER (8)" + - name: Set variable OS_VER (8) env: state: present - name: 'OS_VER' - value: '8' + name: "OS_VER" + value: "8" when: ansible_distribution_major_version == "8" - - name: "Set variable PACKAGE_MANAGER" + - name: Set variable PACKAGE_MANAGER env: state: present - name: 'PACKAGE_MANAGER' - value: 'rpm' + name: "PACKAGE_MANAGER" + value: "rpm" - - name: "Set variable NOTTY" + - name: Set variable NOTTY env: state: present - name: 'NOTTY' - value: '1' + name: "NOTTY" + value: "1" diff --git a/utils/benchmarks/run_and_combine.py b/utils/benchmarks/run_and_combine.py new file mode 100755 index 00000000000..c48fd342832 --- /dev/null +++ b/utils/benchmarks/run_and_combine.py @@ -0,0 +1,176 @@ +#!/usr/bin/env python3 + +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation + +import argparse +import json +import pandas as pd +import subprocess + + +PARSER = argparse.ArgumentParser() +PARSER.add_argument('--reference', metavar='LD_LIBRARY_PATH', required=True, + help='LD_LIBRARY_PATH where the first version of PMDK is built') +PARSER.add_argument('--rival', metavar='LD_LIBRARY_PATH', required=True, + help='LD_LIBRARY_PATH where the second version of PMDK is built') +PARSER.add_argument('-c', '--config', required=True, + help='Name of the .cfg file to use') +PARSER.add_argument('-s', '--scenario', required=True, + help='Name of the scenario to run') +PARSER.add_argument('-p', '--pmem_path', required=True, + help='PMEM-mounted directory to use') + + +COLUMNS_COMBINE = [ + 'ops-per-second[1/sec]', + 'total-avg[sec]', + 'total-max[sec]', + 'total-min[sec]', + 'total-median[sec]', + 'total-std-dev[sec]', + 'latency-avg[nsec]', + 'latency-min[nsec]', + 'latency-max[nsec]', + 'latency-std-dev[nsec]', + 'latency-pctl-50.0%[nsec]', + 'latency-pctl-99.0%[nsec]', + 'latency-pctl-99.9%[nsec]', +] + + +COLUMNS_COPY = [ + 'threads', + 'ops-per-thread', + 'data-size', + 'seed', + 'repeats', + 'thread-affinity', + 'main-affinity', + 'min-exe-time', + 'random', + 'min-size', + 'type-number', + 'operation', + 'lib', + 'nestings', + 'type', + 'max-key', + 'external-tx', + 'alloc', +] + + +def get_numa_node(pmem_path: str) -> int: + """Find the NUMA node of the device mounted at the specified path""" + # no slash at the end of the path + if pmem_path[-1] == '/': + pmem_path = pmem_path[0:-1] + # find the line describing the mount point + mount = subprocess.getoutput('mount') + mount_line = None + for line in mount.splitlines(): + if pmem_path in line: + mount_line = line + break + if mount_line is None: + print(mount) + raise Exception(f'Can not find the mounted PMEM device for: {pmem_path}') + # Extract blockdev from the found line e.g. + # /dev/pmem1 on /mnt/pmem1 type ext4 (rw,noatime,seclabel,nodelalloc,dax=always) + # - Linux device is the first part of the line e.g. /dev/pmem1 + # - blockdev is the name of the device file e.g. pmem1 + blockdev = mount_line.split(' ')[0].split('/')[2] + # Find the NDCTL namespace of the blockdev and extract its NUMA node + numa_node = None + namespaces = json.loads(subprocess.getoutput('ndctl list -v')) + for namespace in namespaces: + if namespace['mode'] == 'fsdax' and namespace['blockdev'] == blockdev: + numa_node = namespace['numa_node'] + break + if numa_node is None: + print(namespaces) + raise Exception(f'Can not find the namespace: mode == "fsdax" and blockdev == "{blockdev}"') + return numa_node + + +IDX_TO_NAME = ['ref', 'riv'] + + +def output_name(args: argparse.Namespace, idx: int) -> str: + """Generate a file name for an output ref or riv""" + return f'{args.config}__{args.scenario}_{IDX_TO_NAME[idx]}.csv' + + +def run(numa_node: int, args: argparse.Namespace, idx: int, ld_library_path: str) -> None: + """Run PMEMBENCH according to the provided parameters""" + config = f'src/benchmarks/{args.config}.cfg' + file = f'{args.pmem_path}/testfile.obj' + cmd = f'numactl --cpunodebind {numa_node} --localalloc ./src/benchmarks/pmembench {config} {args.scenario} --file {file}' + env = {'LD_LIBRARY_PATH': ld_library_path} + result = subprocess.run(cmd, env=env, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, encoding='utf-8', shell=True) + # generate the file with the output + if result.returncode == 0: + # drop the first line e.g. obj_rbtree_map_insert: map_insert [1] + out = ''.join(result.stdout.splitlines(keepends=True)[1:]) + else: + out = result.stdout + with open(output_name(args, idx), 'w') as output: + output.write(out) + # validate the run + if result.returncode != 0: + print(result.stdout) + print(result.stderr) + exit(result.returncode) + + +def column_name(column: str, idx: int) -> str: + """Generate a column name with ref or rev infix""" + return f'-{IDX_TO_NAME[idx]}['.join(column.split('[')) + + +def combine(args: argparse.Namespace) -> None: + """" + Combine outputs from the reference and rival runs. + + Output data files: + - combined - contains data from ref and riv together with a normalized + difference between them. + - diff - just a normalized difference between ref and riv + """ + dfs = [pd.read_csv(output_name(args, idx), sep=';') for idx in range(2)] + combined = pd.DataFrame() + diff = pd.DataFrame() + for column in COLUMNS_COMBINE: + # Copy columns to combine from both ref and riv + for idx in range(2): + combined[column_name(column, idx)] = dfs[idx][column] + diff_column = f'{column}-diff' + # Normalized difference between ref and riv: + # diff = (riv - ref) / ref + # Both output data frames contains diff columns. + combined[diff_column] = (dfs[1][column] / dfs[0][column] - 1) + diff[diff_column] = combined[diff_column] + for column in COLUMNS_COPY: + if column in dfs[0].columns: + # These columns are identical in both data frames + # so they can be copied from either data frame ref or riv. + combined[column] = dfs[0][column] + diff[column] = dfs[0][column] + # Write the generated data frames to CSV files. + prefix = f'{args.config}__{args.scenario}' + combined.to_csv(f'{prefix}_combined.csv', index=False, float_format='%.3f') + diff.to_csv(f'{prefix}_diff.csv', index=False, float_format='%.3f') + + +def main(): + args = PARSER.parse_args() + numa_node = get_numa_node(args.pmem_path) + for idx, ld_library_path in enumerate([args.reference, args.rival]): + run(numa_node, args, idx, ld_library_path) + combine(args) + + +if __name__ == '__main__': + main() diff --git a/utils/build-dpkg.sh b/utils/build-dpkg.sh index a895c85a0f8..00304c4154f 100755 --- a/utils/build-dpkg.sh +++ b/utils/build-dpkg.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2014-2023, Intel Corporation +# Copyright 2014-2024, Intel Corporation # # build-dpkg.sh - Script for building deb packages @@ -610,13 +610,17 @@ echo "" >> debian/changelog tail -n1 $CHANGELOG_TMP >> debian/changelog rm $CHANGELOG_TMP -# This is our first release but we do +# Required for PMEMOBJ tests to not attempt creating an SDS which will fail +# in the simulated test environment. +PMEMOBJ_CONF='sds.at_create=0' + debuild --preserve-envvar=EXTRA_CFLAGS_RELEASE \ --preserve-envvar=EXTRA_CFLAGS_DEBUG \ --preserve-envvar=EXTRA_CFLAGS \ --preserve-envvar=EXTRA_CXXFLAGS \ --preserve-envvar=EXTRA_LDFLAGS \ --preserve-envvar=NDCTL_ENABLE \ + --preserve-envvar=PMEMOBJ_CONF \ -us -uc -b cd $OLD_DIR diff --git a/utils/build-rpm.sh b/utils/build-rpm.sh index 6a878a4244b..c0c4fbeed61 100755 --- a/utils/build-rpm.sh +++ b/utils/build-rpm.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2014-2023, Intel Corporation +# Copyright 2014-2024, Intel Corporation # # build-rpm.sh - Script for building rpm packages @@ -238,6 +238,10 @@ mkdir -v BUILD SPECS echo "opts: ${RPMBUILD_OPTS[@]}" +# Required for PMEMOBJ tests to not attempt creating an SDS which will fail +# in the simulated test environment. +PMEMOBJ_CONF='sds.at_create=0' + rpmbuild --define "_topdir `pwd`"\ --define "_rpmdir ${OUT_DIR}"\ --define "_srcrpmdir ${OUT_DIR}"\ diff --git a/utils/call_stacks_analysis/README.md b/utils/call_stacks_analysis/README.md index c47af9a7e7d..40a21cfc15e 100644 --- a/utils/call_stacks_analysis/README.md +++ b/utils/call_stacks_analysis/README.md @@ -15,7 +15,7 @@ ./make_extra.py && \ ./make_cflow.sh && \ ./make_call_stacks.py --filter-api-file examples/api_filter.txt \ - --filter-lower-limit 8192 --dump-all-stacks + --filter-lower-limit 11536 --dump-all-stacks ``` If succesfull, it produces: diff --git a/utils/call_stacks_analysis/log_call_all_generate.py b/utils/call_stacks_analysis/log_call_all_generate.py new file mode 100755 index 00000000000..d4a2b7924d1 --- /dev/null +++ b/utils/call_stacks_analysis/log_call_all_generate.py @@ -0,0 +1,428 @@ +#!/usr/bin/env python3 + +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024, Intel Corporation + +import subprocess # nosec B304 +import json +import re + +from typing import List, Dict, Any + +DEBUG = False +PARSER_DEBUG = False + +TOP = '../../src/' +OUTPUT_PATH = TOP + 'test/core_log_max/' +OUTPUT_C = OUTPUT_PATH + 'call_all.c.generated' + +NOTICE = """/* + * This file is automatically generated by utils/call_stack_analysis/log_call_all_generate.py. + * Please do not modify manually. + */""" + +C_FUNCTION_W_ERRNUM_PREFIX = """ +void +call_all_{}(int errnum) +{{ + errno = errnum; +""" + +C_FUNCTION_PREFIX = """ +void +call_all_{}(void) +{{ +""" + +C_FUNCTION_SUFFIX = """} +""" + +def dump(var: Any, name: str) -> None: + with open(f'{name}.json', 'w') as outfile: + json.dump(var, outfile, indent = 4) + +def bad_line(reason: str, line: str) -> None: + print(f'{reason}: {line}') + exit(1) + +# Extract all calls from the code base + +def extract_append_code(file_name: str, start_line: int, code: str) -> str: + if not re.search(f'\.[ch]$', file_name): + print(f'Unsupported file type: {file_name}') + exit(1) + + with open(TOP + file_name, 'r') as file: + # skip to the line + for _ in range(0, start_line): + file.readline() + # look up for the end of the statement + while True: + line = file.readline() + line = line.strip() + code += " " + line + if code[-1] == ';': + break + if re.search(f'(//|/\*)', code): + bad_line('Comment found', code) + return code + +IGNORE_FILES = [ + 'core/log_internal.h', + 'libpmem2/', + 'libpmempool/', + 'test/', +] + +def file_should_be_ignored(file: str) -> bool: + for ignore in IGNORE_FILES: + if file.startswith(ignore): + return True + return False + +def extract_all_calls(func: str) -> List[Dict]: + # XXX The grep call could be replaced by os.walk() call + for loops over + # all lines of all files + re.search(). + # In the meantime: + # B607: Starting a process with a partial executable path - ignored since it + # is normal way of accessing system utilities. + # B603: subprocess call - check for execution of untrusted input - there is + # no way around it. Theoretically, some bad actor could inject faulty grep + # in the head of the PATH which will lead to us parsing whatever they could + # benefit from. So, do not commit the produced code automatically. + returned_output = subprocess.check_output(['grep', '-Irn', func], cwd=TOP) # nosec B607, B603 + string = returned_output.decode("utf-8") + calls = [] + total = 0 + for line in string.splitlines(): + found = re.search(f'([a-zA-Z0-9_/.-]+):([0-9]+):[ \t]*(.+)', line) + if found: + total += 1 + file = found.group(1) + line_no = found.group(2) + code = found.group(3) + # Filter out known odd occurrences. + if file_should_be_ignored(file): + continue + if not code.startswith(func): + bad_line(f'Does not start with "{func}"', line) + if code[-1] == '\\': # template's type of ending a line + if code[-2] == ';': # a single line call can be extracted + code = code[:-1] + else: + print(f'SKIP call: Multiline calls in templates are not supported: {line}') + continue + elif code[-1] != ';': + code = extract_append_code(file, int(line_no), code) + call = { + 'file': file, + 'line_no': line_no, + 'code': code + } + calls.append(call) + else: + bad_line('An unexpected line format', line) + # sort calls by file and line + def key_func(a: Dict) -> str: + return a['file'] + a['line_no'] + calls.sort(key=key_func) + print(f'[{func}] total: {total}, included: {len(calls)}') + return calls + +# Parse a single call's code and tokenize the format string + +def parse_token_start(state: Dict, type: str) -> Dict: + if PARSER_DEBUG: + print('parse_token_start') + state['token_start'] = state['pos'] + state['in_' + type] = True + return state + +def parse_token_end(state: Dict) -> Dict: + if PARSER_DEBUG: + print('parse_token_end') + + plus = 0 + if state['in_string'] and state['in_literal']: + bad_line("Both string and literal tokens detected at the same time", state['code']) + elif state['in_string']: + _type = 'string' + plus = 1 # the character ending a string literal belongs to it + elif state['in_literal']: + _type = 'literal' + else: + bad_line("End of an unknown token detected", state['code']) + + if state['token_start'] is None: + bad_line("End of a {_type} without the beginning", state['code']) + state['tokens'].append(state['code'][state['token_start']:(state['pos'] + plus)]) + state['token_start'] = None + state['in_' + _type] = False + return state + +def parse_call_quote(state: Dict) -> Dict: + if PARSER_DEBUG: + print('parse_call_quote') + if state['in_string']: + if state['code'][state['pos'] - 1] == '\\': # escaped + pass + else: + state = parse_token_end(state) # string token ends here + elif state['in_literal']: + state = parse_token_end(state) # a literal token ends here + state = parse_token_start(state, 'string') # a string token starts here... + else: + state = parse_token_start(state, 'string') # ... and here as well. + return state + +def parse_call_comma_or_rbracket(state: Dict) -> Dict: + if PARSER_DEBUG: + print('parse_call_comma_or_rbracket') + if state['in_string']: + pass + elif state['in_literal']: + state = parse_token_end(state) # a literal token ends here + state['end'] = True # the format ends here... + else: + state['end'] = True # ... and here + return state + +def parse_call_AZaz09(state: Dict) -> Dict: + if PARSER_DEBUG: + print('parse_call_AZaz09') + if state['in_string']: + pass + elif state['in_literal']: + pass + else: + state = parse_token_start(state, 'literal') + return state + +def parse_call_space_or_minus(state: Dict) -> Dict: + if PARSER_DEBUG: + print('parse_call_space_or_minus') + if state['in_string']: + pass + elif state['in_literal']: + state = parse_token_end(state) # a literal token ends here + return state + +def parse_call_odd(state: Dict) -> Dict: + if PARSER_DEBUG: + print('parse_call_odd') + if state['in_string']: + pass + else: + ch = state['code'][state['pos']] + bad_line('Unexpected "{ch}"', state['code']) + return state + +PARSER_CHAR_ACTION = { + '"': parse_call_quote, + ',': parse_call_comma_or_rbracket, + ')': parse_call_comma_or_rbracket, + ' ': parse_call_space_or_minus, + '-': parse_call_space_or_minus, + '(': parse_call_odd, + '#': parse_call_odd, + '%': parse_call_odd, + ':': parse_call_odd, + '+': parse_call_odd, + '\'': parse_call_odd, + '/': parse_call_odd, + '.': parse_call_odd, + '\\': parse_call_odd, + '<': parse_call_odd, + '>': parse_call_odd, + '=': parse_call_odd, + ';': parse_call_odd, + '[': parse_call_odd, + ']': parse_call_odd, + '!': parse_call_odd, + '|': parse_call_odd, + 'A-Za-z0-9_': parse_call_AZaz09, +} + +def call_get_format_tokens(call): + code = call['code'] + start = code.find('(') + state = { + 'code': code, + 'pos': None, + 'end': False, + 'in_string': False, + 'in_literal': False, + 'token_start': None, + 'tokens': [] + } + for i in range(start + 1, len(code)): + state['pos'] = i + ch = code[i] + if ch in PARSER_CHAR_ACTION.keys(): + state = PARSER_CHAR_ACTION[ch](state) + elif ch.isalpha() or ch.isdecimal() or ch == '_': + state = PARSER_CHAR_ACTION['A-Za-z0-9_'](state) + else: + bad_line(f'Unsupported character \'{ch}\'', code) + if state['end']: + break + if not state['end']: + bad_line('Cannot find the end of the format string', code) + return state['tokens'] + +# Generate a complete format string + +LITERAL_TO_STRING = { + 'PRIx64': 'lx', + 'PRIu64': 'lu' +} + +def token_stringify(token: str) -> str: + if token[0] == '"' and token[-1] == '"': + return token[1:-1] # strip quotes + if token in LITERAL_TO_STRING.keys(): + return LITERAL_TO_STRING[token] + else: + print(f'Unknown token: "{token}"') + exit(1) + +def format_stringify(tokens: List) -> str: + tokens_str = [token_stringify(token) for token in tokens] + return ''.join(tokens_str) + +# Identify required arguments + +SPECIFIERS = [ + 'd', + 'x', + 'u', + 's', + 'p', + 'o', + 'i', +] + +FORMAT_SPECIFIER_ARGS = { + '%s': '_s', + '%.8s': '_8s', + '%x': '_u', + '%lx': '_lu', + '%#x': '_u', + '%d': '_d', + '%ld': '_ld', + '%u': '_u', + '%lu': '_lu', + '%zu': '_zu', + '%ju': '_ju', + '%p': '_p', + '%o': '_u', + '%i': '_d', + '%li': '_d', +} + +def arg_identify(format: str, pos: int): + format_spec = None + end_pos = None + for i in range(pos + 1, len(format)): + ch = format[i] + if ch in SPECIFIERS: + format_spec = format[pos:i + 1] + end_pos = i + 1 + break + if format_spec is None: + visited = format[pos:] + print(f'Unrecognized specifier: "{visited}"') + exit(1) + if format_spec not in FORMAT_SPECIFIER_ARGS.keys(): + print(f'Unrecognized format specifier: "{format_spec}"') + exit(1) + return FORMAT_SPECIFIER_ARGS[format_spec], end_pos + +def args_parse(format: str) -> List: + pos = 0 + args = [] + while True: + pos = format.find('%', pos) + if pos == -1: + break + arg, pos = arg_identify(format, pos) + args.append(arg) + return args + +# Process raw source code: generate the complete format string and list of args + +def calls_process(calls: List) -> List: + for call in calls: + call['format_tokens'] = call_get_format_tokens(call) + call['format_string'] = format_stringify(call['format_tokens']) + call['args'] = args_parse(call['format_string']) + return calls + +# Generate the call all source file + +def init_source_file(): + with open(OUTPUT_C, 'w') as file: + file.write(NOTICE) + +def generate_call(file, func: str, call: Dict) -> str: + if len(call['args']) > 0: + args = ', ' + ', '.join(call['args']) + else: + args = '' + file.write(f'\t// src/{call["file"]}\n') + file.write(f'\t{func}("{call["format_string"]}"{args});\n') + +def generate_func_with_errno(func: str, calls: List[Dict]) -> None: + with open(OUTPUT_C, 'a') as file: + file.write(C_FUNCTION_W_ERRNUM_PREFIX.format(func)) + for call in calls: + generate_call(file, func, call) + file.write('\tUT_ASSERTeq(errno, errnum);\n') + file.write(C_FUNCTION_SUFFIX) + +def generate_func(func: str, calls: List[Dict]) -> None: + with open(OUTPUT_C, 'a') as file: + file.write(C_FUNCTION_PREFIX.format(func)) + for call in calls: + generate_call(file, func, call) + file.write(C_FUNCTION_SUFFIX) + +# Main + +API = { + 'void': [ + 'CORE_LOG_ERROR_LAST', + 'ERR_WO_ERRNO', + 'CORE_LOG_WARNING', + 'CORE_LOG_ERROR', + 'CORE_LOG_FATAL', + ], + 'errno': [ + 'CORE_LOG_ERROR_W_ERRNO_LAST', + 'ERR_W_ERRNO', + 'CORE_LOG_WARNING_W_ERRNO', + 'CORE_LOG_ERROR_W_ERRNO', + 'CORE_LOG_FATAL_W_ERRNO' + ] +} + +def main(): + global_total = 0 + init_source_file() + + for func in API['void']: + calls = extract_all_calls(func) + global_total += len(calls) + calls = calls_process(calls) + generate_func(func, calls) + + for func in API['errno']: + calls = extract_all_calls(func) + global_total += len(calls) + calls = calls_process(calls) + generate_func_with_errno(func, calls) + + print(f'Total: {global_total}') + +if __name__ == '__main__': + main() diff --git a/utils/call_stacks_analysis/make_call_stacks.py b/utils/call_stacks_analysis/make_call_stacks.py index 63adf22e7bc..5dacbf8c57b 100755 --- a/utils/call_stacks_analysis/make_call_stacks.py +++ b/utils/call_stacks_analysis/make_call_stacks.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2023, Intel Corporation +# Copyright 2023-2024, Intel Corporation import argparse import json @@ -101,7 +101,15 @@ def parse_stack_usage(stack_usage_file: str) -> StackUsage: # 112 ctl_find_node.isra.5 : src/nondebug/common/ctl.su:ctl.c static found = re.search('([0-9]+) ([a-zA-Z0-9_]+)(.[a-zA-Z0-9.]+)* : ([a-zA-Z0-9.:/_-]+) ([a-z,]+)', line) if found: - funcs[found.group(2)] = {'size': int(found.group(1)), 'type': found.group(5)} + func = found.group(2) + size = int(found.group(1)) + if func in funcs.keys(): + curr_size = funcs[func]['size'] + if size != curr_size: + print(f'Warning: Incompatible function records [{func}].size: {size} != {curr_size}. Continue with the biggest reported size.') + if curr_size > size: + size = curr_size + funcs[func] = {'size': size, 'type': found.group(5)} else: print(f'An unexpected line format: {line}') exit(1) diff --git a/utils/call_stacks_analysis/make_extra.py b/utils/call_stacks_analysis/make_extra.py index ade4d321961..e1aade25630 100755 --- a/utils/call_stacks_analysis/make_extra.py +++ b/utils/call_stacks_analysis/make_extra.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2023, Intel Corporation +# Copyright 2023-2024, Intel Corporation import json from typing import Dict, List @@ -21,15 +21,11 @@ def dict_extend(dict_, key, values): def inlines(calls: Calls) -> Calls: # common - calls['core_init'] = ['util_init', 'out_init'] - calls['core_fini'] = ['out_fini'] - calls['ERR'] = ['out_err'] - calls['Print'] = ['out_print_func'] + calls['core_init'] = ['util_init', 'core_log_init', 'out_init'] + calls['core_fini'] = ['out_fini', 'core_log_fini', 'last_error_msg_fini'] calls['common_init'] = ['core_init', 'util_mmap_init'] calls['common_fini'] = ['util_mmap_fini', 'core_fini'] - calls['Last_errormsg_key_alloc'] = ['_Last_errormsg_key_alloc'] - calls['_Last_errormsg_key_alloc'] = ['os_once', 'os_tls_key_create'] - calls['out_common'] = ['out_snprintf'] + calls['core_log_init'] = ['core_log_default_init', 'core_log_set_function'] # libpmem calls['flush_empty'] = ['flush_empty_nolog'] @@ -43,6 +39,10 @@ def inlines(calls: Calls) -> Calls: return calls +def core_function_pointers(calls: Calls) -> Calls: + calls['core_log_va'] = ['core_log_default_function'] + return calls + def pmem_function_pointers(calls: Calls) -> Calls: calls['pmem_drain'] = ['fence_empty', 'memory_barrier'] @@ -51,7 +51,7 @@ def pmem_function_pointers(calls: Calls) -> Calls: calls['pmem_flush'] = flush_all # '.static' suffix added to differentiate between libpmem API function and a static helper. - memmove_nodrain_all = ['memmove_nodrain_libc', 'memmove_nodrain_generic', 'pmem_memmove_nodrain.static', 'pmem_memmove_nodrain_eadr.static'] + memmove_nodrain_all = ['memmove_nodrain_libc', 'memmove_nodrain_generic', 'pmem2_memmove_nodrain', 'pmem2_memmove_nodrain_eadr'] calls['pmem_memmove'] = memmove_nodrain_all calls['pmem_memcpy'] = memmove_nodrain_all calls['pmem_memmove_nodrain'] = memmove_nodrain_all @@ -59,7 +59,7 @@ def pmem_function_pointers(calls: Calls) -> Calls: calls['pmem_memmove_persist'] = memmove_nodrain_all calls['pmem_memcpy_persist'] = memmove_nodrain_all - memset_nodrain_all = ['memset_nodrain_libc', 'memset_nodrain_generic', 'pmem_memset_nodrain.static', 'pmem_memset_nodrain_eadr.static'] + memset_nodrain_all = ['memset_nodrain_libc', 'memset_nodrain_generic', 'pmem2_memset_nodrain', 'pmem2_memset_nodrain_eadr'] calls['pmem_memset'] = memset_nodrain_all calls['pmem_memset_nodrain'] = memset_nodrain_all calls['pmem_memset_persist'] = memset_nodrain_all @@ -103,12 +103,12 @@ def pmem_function_pointers(calls: Calls) -> Calls: memmove_funcs['nt']['empty'].extend(memmove_funcs_extras['nt']['empty']) memmove_funcs['nt']['flush'].extend(memmove_funcs_extras['nt']['flush']) - calls['pmem_memmove_nodrain.static'] = \ + calls['pmem2_memmove_nodrain'] = \ memmove_funcs['t']['noflush'] + \ memmove_funcs['nt']['flush'] + \ memmove_funcs['t']['flush'] - calls['pmem_memmove_nodrain_eadr.static'] = \ + calls['pmem2_memmove_nodrain_eadr'] = \ memmove_funcs['t']['noflush'] + \ memmove_funcs['nt']['empty'] + \ memmove_funcs['t']['empty'] @@ -152,12 +152,12 @@ def pmem_function_pointers(calls: Calls) -> Calls: memsetfuncs['nt']['empty'].extend(memsetfuncs_extras['nt']['empty']) memsetfuncs['nt']['flush'].extend(memsetfuncs_extras['nt']['flush']) - calls['pmem_memset_nodrain.static'] = \ + calls['pmem2_memset_nodrain'] = \ memsetfuncs['t']['noflush'] + \ memsetfuncs['nt']['flush'] + \ memsetfuncs['t']['flush'] - calls['pmem_memset_nodrain_eadr.static'] = \ + calls['pmem2_memset_nodrain_eadr'] = \ memsetfuncs['t']['noflush'] + \ memsetfuncs['nt']['empty'] + \ memsetfuncs['t']['empty'] @@ -424,13 +424,17 @@ def get_callees(calls): callees.extend(v) return list(set(callees)) +# XXX +# The way how inlines() function is used shall be changed according to: +# https://github.com/pmem/pmdk/issues/6070 def main(): - extra_calls = inlines({}) + extra_calls = core_function_pointers({}) extra_calls = pmem_function_pointers(extra_calls) extra_calls = pmemobj_function_pointers(extra_calls) with open("extra_calls.json", "w") as outfile: json.dump(extra_calls, outfile, indent = 4) + extra_calls = inlines(extra_calls) # All functions accessed via function pointers have to be provided # on top of regular API calls for cflow to process their call stacks. extra_entry_points = get_callees(extra_calls) diff --git a/utils/call_stacks_analysis/white_list.json b/utils/call_stacks_analysis/white_list.json index 331951beca6..a53696ca786 100644 --- a/utils/call_stacks_analysis/white_list.json +++ b/utils/call_stacks_analysis/white_list.json @@ -125,11 +125,10 @@ "os_thread_setaffinity_np", "os_unsetenv", "os_writev", - "out_fatal", "out_log", - "out_nonl", - "out_set_print_func", - "out_set_vsnprintf_func", + "out_log_va", + "out_common", + "out_snprintf", "pmalloc_operation_hold_no_start", "pmalloc", "pmem2_badblock_clear", @@ -180,6 +179,7 @@ "util_safe_strcpy", "util_str2feature", "util_str2pmempool_feature", + "util_strerror", "util_unlink_flock", "util_uuid_to_string", "util_write_all" diff --git a/utils/check_docs/exceptions.txt b/utils/check_docs/exceptions.txt index f7c93fae46c..0b10129bdb7 100644 --- a/utils/check_docs/exceptions.txt +++ b/utils/check_docs/exceptions.txt @@ -27,6 +27,7 @@ libpmemobj_atomic_base_h pobj_xalloc_valid_flags libpmemobj_atomic_h libpmemobj_iterator_base_h +libpmemobj_log_h libpmemobj_pool_base_h pmemobj_min_pool pmemobj_min_part diff --git a/utils/check_license/check-headers.sh b/utils/check_license/check-headers.sh index c3fd36a9bed..e53f1baa4ce 100755 --- a/utils/check_license/check-headers.sh +++ b/utils/check_license/check-headers.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2016-2023, Intel Corporation +# Copyright 2016-2024, Intel Corporation # check-headers.sh - check copyright and license in source files @@ -26,7 +26,6 @@ shift PATTERN=`mktemp` TMP=`mktemp` TMP2=`mktemp` -TEMPFILE=`mktemp` rm -f $PATTERN $TMP $TMP2 if [ "$1" == "-h" -o "$1" == "--help" ]; then @@ -47,6 +46,12 @@ else SHALLOW_CLONE=0 fi +if [ $($GIT diff | wc -l) -gt 0 ]; then + DIRTY_SOURCE=1 +else + DIRTY_SOURCE=0 +fi + VERBOSE=0 CHECK_ALL=0 while [ "$1" != "" ]; do @@ -99,9 +104,6 @@ for file in $FILES ; do # git is called with -C flag so filepaths should be relative to SOURCE_ROOT src_path="${SOURCE_ROOT}/$file" [ ! -f $src_path ] && continue - # ensure that file is UTF-8 encoded - ENCODING=`file -b --mime-encoding $src_path` - iconv -f $ENCODING -t "UTF-8" $src_path > $TEMPFILE if ! grep -q "SPDX-License-Identifier: $LICENSE" $src_path; then echo "$src_path:1: no $LICENSE SPDX tag found " >&2 @@ -150,7 +152,7 @@ for file in $FILES ; do s/.*Copyright \([0-9]\+\)-\([0-9]\+\),.*/\1-\2/ s/.*Copyright \([0-9]\+\),.*/\1-\1/' $src_path` if [ -z "$YEARS" ]; then - echo >&2 "$src_path:1: No copyright years found" + echo >&2 "$src_path:2: No copyright years found" RV=1 continue fi @@ -171,7 +173,13 @@ s/.*Copyright \([0-9]\+\),.*/\1-\1/' $src_path` else NEW=$COMMIT_FIRST-$COMMIT_LAST fi - echo "$file:1: error: wrong copyright date: (is: $YEARS, should be: $NEW)" >&2 + if [ $HEADER_FIRST == $HEADER_LAST ]; then + YEARS=$HEADER_LAST + fi + echo "$file:2: error: wrong copyright date: (is: $YEARS, should be: $NEW)" >&2 + if [ $DIRTY_SOURCE -eq 0 ]; then + sed -i "s/\(Copyright\) $YEARS\(, Intel Corporation\)/\1 $NEW\2/" $src_path + fi RV=1 fi else @@ -179,7 +187,7 @@ s/.*Copyright \([0-9]\+\),.*/\1-\1/' $src_path` RV=1 fi done -rm -f $TMP $TMP2 $TEMPFILE +rm -f $TMP $TMP2 $(dirname "$0")/check-ms-license.pl $FILES @@ -188,5 +196,10 @@ if [ $RV -eq 0 ]; then echo "Copyright headers are OK." else echo "Error(s) in copyright headers found!" >&2 + if [ $DIRTY_SOURCE -eq 0 ]; then + echo "Please see the proposed changes to fix the found issues." >&2 + else + echo "Since the source is dirty no changes have been proposed." >&2 + fi fi exit $RV diff --git a/utils/docker/build-CI.sh b/utils/docker/build-CI.sh index 670411fd61c..e253f2f8dda 100755 --- a/utils/docker/build-CI.sh +++ b/utils/docker/build-CI.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2016-2023, Intel Corporation +# Copyright 2016-2024, Intel Corporation # # build-CI.sh - runs a Docker container from a Docker image with environment @@ -100,6 +100,7 @@ docker run --rm --name=$containerName -i \ --env CI_RUN=$CI_RUN \ --env SRC_CHECKERS=$SRC_CHECKERS \ --env BLACKLIST_FILE=$BLACKLIST_FILE \ + --env PMEMOBJ_CONF="sds.at_create=0" \ $ndctl_enable \ --tmpfs /tmp:rw,relatime,suid,dev,exec,size=6G \ -v $HOST_WORKDIR:$WORKDIR \ diff --git a/utils/docker/images/Dockerfile.ubuntu-22.04 b/utils/docker/images/Dockerfile.ubuntu-22.04 index 25ae8a0f62b..41dbb7af646 100644 --- a/utils/docker/images/Dockerfile.ubuntu-22.04 +++ b/utils/docker/images/Dockerfile.ubuntu-22.04 @@ -1,5 +1,5 @@ # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2016-2023, Intel Corporation +# Copyright 2016-2024, Intel Corporation # # Dockerfile - a 'recipe' for Docker to build an image of ubuntu-based @@ -83,9 +83,6 @@ ENV PYTHON_DEPS "\ # Copy install valgrind script COPY install-valgrind.sh install-valgrind.sh -# Copy script to download codecov script required in run-coverage.sh -COPY download-scripts.sh download-scripts.sh - # Update the Apt cache and install basic tools RUN apt-get update && apt-get dist-upgrade -y \ && apt-get install -y --no-install-recommends \ @@ -100,7 +97,6 @@ RUN apt-get update && apt-get dist-upgrade -y \ $COVERITY_DEPS \ $MISC_DEPS \ && ./install-valgrind.sh ubuntu \ - && ./download-scripts.sh \ && rm -rf /var/lib/apt/lists/* RUN pip3 install $PYTHON_DEPS diff --git a/utils/docker/images/download-scripts.sh b/utils/docker/images/download-scripts.sh deleted file mode 100755 index 448e38c8f26..00000000000 --- a/utils/docker/images/download-scripts.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env bash -# SPDX-License-Identifier: BSD-3-Clause -# Copyright 2020-2023, Intel Corporation - -# -# download-scripts.sh - downloads latest version of -# codecov's uploader to generate and upload reports. -# - -set -e - -if [ "${SKIP_SCRIPTS_DOWNLOAD}" ]; then - echo "Variable 'SKIP_SCRIPTS_DOWNLOAD' is set; skipping scripts' download" - exit -fi - -mkdir -p /opt/scripts - -if ! [ -x "$(command -v curl)" ]; then - echo "Error: curl is not installed." - return 1 -fi - -# Download codecov and check integrity -mkdir -p codecov-tmp -pushd codecov-tmp - -curl https://keybase.io/codecovsecurity/pgp_keys.asc | gpg --no-default-keyring --keyring trustedkeys.gpg --import -curl -Os https://uploader.codecov.io/latest/linux/codecov -curl -Os https://uploader.codecov.io/latest/linux/codecov.SHA256SUM -curl -Os https://uploader.codecov.io/latest/linux/codecov.SHA256SUM.sig -gpgv codecov.SHA256SUM.sig codecov.SHA256SUM -shasum -a 256 -c codecov.SHA256SUM -chmod +x codecov - -mv -v codecov /opt/scripts/codecov - -popd -rm -rf codecov-tmp diff --git a/utils/docker/images/set-images-version.sh b/utils/docker/images/set-images-version.sh index d1a937ce672..44b7b08813a 100755 --- a/utils/docker/images/set-images-version.sh +++ b/utils/docker/images/set-images-version.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2020-2023, Intel Corporation +# Copyright 2020-2024, Intel Corporation # # @@ -13,4 +13,4 @@ # has to trigger the rebuild of all Docker images. # -export IMG_VER=2.0 +export IMG_VER=2.1 diff --git a/utils/docker/run-coverage.sh b/utils/docker/run-coverage.sh index 823414c4563..afba8e67fa5 100755 --- a/utils/docker/run-coverage.sh +++ b/utils/docker/run-coverage.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2017-2023, Intel Corporation +# Copyright 2017-2024, Intel Corporation # # run-coverage.sh - is called inside a Docker container; runs tests @@ -31,21 +31,3 @@ make -kj2 pcheck-local-quiet TEST_BUILD=debug || true # do not change -j2 to -j$(nproc) in case of tests (make check/pycheck) make -kj2 pycheck TEST_BUILD=debug || true popd - -# prepare flag for codecov report to differentiate builds -flag=tests -[ -n "${GITHUB_ACTIONS}" ] && flag=GHA - -# validate codecov.yaml file -cat "${WORKDIR}/.codecov.yml" | curl --data-binary @- https://codecov.io/validate - -# run codecov's uploader in current dir (WORKDIR), with gcov executable -# (clean parsed coverage files, set flag and exit 1 if not successful) -/opt/scripts/codecov --rootDir . --gcov --clean --flags ${flag} --nonZero --verbose -echo "Check for any leftover gcov files" -leftover_files=$(find . -name "*.gcov") -if [[ -n "${leftover_files}" ]]; then - # display found files and exit with error (they all should be parsed) - echo "${leftover_files}" - return 1 -fi diff --git a/utils/gha-runners/build-pmdk.sh b/utils/gha-runners/build-pmdk.sh index 467acbff43a..84e2d4d5252 100755 --- a/utils/gha-runners/build-pmdk.sh +++ b/utils/gha-runners/build-pmdk.sh @@ -17,7 +17,7 @@ set -eo pipefail function build_pmdk { echo "********** make pmdk **********" cd ${PMDK_PATH} && make -j$(nproc) clean - cd ${PMDK_PATH} && make -j$(nproc) EXTRA_CFLAGS=-DUSE_VALGRIND + cd ${PMDK_PATH} && make -j$(nproc) echo "********** make pmdk test **********" cd ${PMDK_PATH}/ && make -j$(nproc) test } diff --git a/utils/gha-runners/get-system-info.sh b/utils/gha-runners/get-system-info.sh index 9a41e1c6427..c8e68df60c5 100755 --- a/utils/gha-runners/get-system-info.sh +++ b/utils/gha-runners/get-system-info.sh @@ -13,8 +13,8 @@ function system_info { echo "libndctl: $(pkg-config --modversion libndctl || echo 'libndctl not found')" echo "valgrind: $(pkg-config --modversion valgrind || echo 'valgrind not found')" echo "******************** memory-info *******************" - ipmctl show -dimm || true - ipmctl show -topology || true + sudo ipmctl show -dimm || true + sudo ipmctl show -topology || true echo "*************** list-existing-namespaces ***************" ndctl list -M -N echo "*************** installed-packages ***************" @@ -45,6 +45,7 @@ function system_info { echo "**********list-avaialble-pmem-devices**********" ls -la /dev/dax* ls -la /dev/pmem* + ls -la /mnt/pmem* echo "**********list-nd-resources**********" ls -la /sys/bus/nd/devices/ndbus*/region*/resource ls -la /sys/bus/nd/devices/ndbus*/region*/dax*/resource