Skip to content

posix: files that fail to assimilate are re-read in full on every scan, with no backoff #3498

Description

@NickWalters

I ran into this with the posix driver. When a file can't be assimilated for a reason that isn't going to go away, nothing records that it failed. The file stays uncached, so every scan and every directory listing tries to assimilate it again, and each attempt reads the whole file to compute its sha1, md5 and adler32. There's no backoff and no retry limit, so OpenCloud just keeps re-reading the same files as fast as the disk allows.

In my case it was permissions. opencloud.service runs as User=opencloud, but the tree I pointed it at was owned by root:media, so the opencloud user couldn't write to the files. Setting user.* xattrs needs write permission on the file, so every attempt ended with:

xattr.Set .../00001.m2ts user.oc.id: permission denied
-> failed to assimilate node

and the next listing logged record not found in cache. Assimilate. and read the file again.

I know the docs say the tree should be owned by the OpenCloud user and not shared with anything else, and my setup didn't follow that. I'm not asking for that layout to be supported. The problem is that getting it wrong ends up as a read loop that never stops, instead of an error you'd notice.

What it did on my machine:

  • about 117 MB/s of reads for 46 hours, with around 517 assimilation attempts per 24 hours
  • everything else on that array was starved for I/O
  • STORAGE_USERS_POSIX_MAX_CONCURRENCY=2 didn't help, because it limits how many run at once, not how often they repeat
  • it was hard to trace back to OpenCloud: load was 11 but user CPU was only 4% (47% iowait), so anything looking at CPU showed the service as idle

The permission problem is just what triggered it for me. I'd expect any per-file failure that keeps happening to cause the same loop. #1585 (file name too long) looks like the same thing with a different cause, and that one was fixed by handling long names rather than by changing how failures are retried. #3470 might be this too (constant ~100% I/O pressure, low memory, no requests), but I haven't checked whether that reporter has files that keep failing.

The code is in reva, pkg/storage/fs/posix/tree/assimilation.go:

  • workScanQueue logs the error and moves on, and nothing about the failure is kept
  • the _errSkipAlreadyKnown shortcut compares against the mtime stored in the file's xattrs, and those were never written, so a file that failed can't take that path
  • updateFile calls node.CalculateChecksums on every attempt, so every retry is a full read

I've opened opencloud-eu/reva#796 with a fix. It remembers files that failed after the checksums were computed and doesn't read them again until they change or a backoff delay has passed. Two other things that might be worth doing: treating errors like EACCES/EPERM on the xattr write or ENAMETOOLONG as permanent, or checking at startup that the service user can actually write xattrs in the tree and logging a clear error if it can't.

Environment:

  • OpenCloud 7.3.0 (rolling) when I hit it, and the code above is the same on main as of 7.5.0
  • Debian in an unprivileged LXC, native systemd install (no Docker), ZFS storage
  • STORAGE_USERS_DRIVER=posix, STORAGE_USERS_POSIX_WATCH_FS=true, SCAN_FS=true

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions