#7534·juicefs

config: concurrent updates silently overwrite unrelated settings

Author: zhijian-proCreated Sep 14, 2026Updated Sep 15, 2026
Labelspriority/wishlist

What happened:

Two concurrent juicefs config commands can silently overwrite each other's changes, even when they modify different fields and use the same client version. Both commands return success.

A deterministic example is an administrator waiting at the confirmation prompt for --trash-days 0 while another administrator changes the volume capacity. When the first administrator confirms, the capacity change is reverted without a conflict error.

What you expected to happen:

A stale configuration update should either preserve unrelated committed changes or fail with a conflict before writing anything. Two successful updates to different fields should not silently undo one another.

How to reproduce it (as minimally and precisely as possible):

Use the same newly created, empty scratch directory in both terminals and the same JuiceFS binary. No mount is needed.

  1. Initialize an isolated volume:

    bash
    juicefs format sqlite3://meta.db concurrent-config \
      --storage file --bucket ./objects --capacity 1 --trash-days 1
  2. In terminal A, run:

    bash
    juicefs config sqlite3://meta.db --trash-days 0

    Leave it waiting at Proceed anyway? [y/N]: without answering yet. It has already read the configuration with a capacity of 1 GiB.

  3. In terminal B, run:

    bash
    juicefs config sqlite3://meta.db --capacity 2
    juicefs config sqlite3://meta.db

    The update succeeds and the stored Capacity is 2147483648 (2 GiB).

  4. Return to terminal A and answer y. Its update also succeeds. Read the configuration again:

    bash
    juicefs config sqlite3://meta.db

    The stored configuration now contains:

    json
    {
      "Capacity": 1073741824,
      "TrashDays": 0
    }

    TrashDays changed as requested, but terminal B's successful capacity update was lost. Neither command reports a conflict. The reproduction was verified by rereading the raw SQLite jfs_setting record as well as checking both commands' exit status.

Anything else we need to know?

The configuration is read into a complete Format snapshot and later written back as a whole. The confirmation prompt makes the race easy to reproduce, but any delay between load and save can allow the same interleaving.

Source references, pinned to the tested commit:

This is an existing configuration concurrency issue, distinct from the excluded-client/unknown-field problem addressed by #7533. The CLI reproduction above succeeds on that PR's head. A separate two-client Meta.Load/Meta.Init reproduction also demonstrated the lost update on main at c9a67b23e8e08ec23ec331aa6f1675e2319e921c, with force=false.

A possible fix is an atomic compare-and-swap against the originally read configuration or a configuration revision, shared by all format writers and all metadata engine families. On conflict, reject the stale write and let the caller reload and retry. A regression test should deterministically interleave two updates to different fields and verify that a successful change cannot be silently reverted.

Environment:

  • JuiceFS: 1.5.0-dev+2026-09-14.32af8c126 (PR #7533 head 32af8c12626bb9474ac915eaac009177a403140e).
  • OS/architecture: macOS, Darwin arm64.
  • Object storage: isolated local file directory.
  • Metadata engine: isolated local SQLite database.
  • Both processes use the same binary; no mounts, sessions, external services, or user volumes were used.