Skip to content

* preserve GFS2 inode metadata during rebuilds - #422

Merged
Hawkynt merged 3 commits into
mainfrom
feat/gfs2-metadata-preservation
Sep 30, 2026
Merged

Hawkynt merged 3 commits into
mainfrom
feat/gfs2-metadata-preservation

Conversation

@Hawkynt

@Hawkynt Hawkynt commented Sep 29, 2026 •

Copy link
Copy Markdown
Owner

What changed

  • Expose GFS2 inode ownership, mode, flags, and second/nanosecond timestamps through Gfs2Entry.
  • Let buffered and streaming writer inputs retain those inode attributes.
  • Preserve file dinode metadata and the filesystem UUID through add/remove rebuilds, including the large-volume streaming path and defragment rebuilds.
  • Validate metadata type and nanosecond ranges before writing.
  • Add regression coverage for metadata and UUID preservation after an add operation.

The existing GFS2 implementation already provides image creation, nested directories, streaming reads/writes, defragmentation, and unused-space wiping. This change closes a metadata-loss path in rebuild operations. Extended-attribute trees and directory inode attributes are not preserved yet.

Validation

  • git diff --check passed.
  • Attempted dotnet test Compression.Tests/Compression.Tests.csproj --filter FullyQualifiedName~Gfs2ModifyTests --no-restore; unable to run because the environment has no dotnet executable.
  • On-disk inode fields were checked against the public Linux gfs2_ondisk.h layout. The change is original code based on that published structure; no GPL implementation code was copied.

Review update

  • Rebased onto main.
  • di_flags was copied verbatim. A source file flagged JDATA (data blocks behind a meta header) or EA_INDIRECT (an extended-attribute tree) was rebuilt with plain data blocks and no attribute tree, yet still claimed both. The writer now accepts only the access-policy bits (DIRECTIO, IMMUTABLE, APPENDONLY, NOATIME, SYNC, per gfs2_ondisk.h) on a regular file and refuses the rest. The rebuild profile narrows a source file's flags to that set, skips directories, and does not throw on a repeated name.
  • Tests: default attributes, each policy flag, each refused layout flag, non-regular modes, the 999999999/1000000000 nanosecond boundary, Remove preservation, JDATA stripping on rebuild, and the Uuid create option (valid, non-hex, 15 and 17 bytes).
  • External: new AttributedFile_SurvivesRebuild_AndGfs2EditDecodesItsDinode. fsck.gfs2 -n accepts the volume before and after a rebuild, and gfs2_edit decodes mode, uid, gid, atime/mtime/ctime and di_flags from the rebuilt dinode. gfs2_edit does not print the *_nsec fields, so the internal tests cover those.
  • The package README and generated API reference are updated. The earlier CI failure was the stale reference.
  • Local: all Compression.Tests.Gfs2 tests, WSL external gates included: 67 passed, 1 skipped.

@Hawkynt
Hawkynt force-pushed the feat/gfs2-metadata-preservation branch from 4094512 to de166df Compare September 30, 2026 12:02
@Hawkynt Hawkynt changed the title Preserve GFS2 inode metadata during rebuilds * preserve GFS2 inode metadata during rebuilds Sep 30, 2026
@Hawkynt
Hawkynt force-pushed the feat/gfs2-metadata-preservation branch 2 times, most recently from f02ffaa to 6586955 Compare September 30, 2026 16:09
Rebuild based edits retained only the image size and lock table, replacing file ownership, permissions, flags, timestamp precision, and UUID. Capture those dinode attributes and feed them back into buffered and streaming writer paths. The GFS2 inode layout follows the public Linux gfs2_ondisk.h definition; extended-attribute trees remain outside this change. Add a regression covering file metadata and UUID preservation across add.
…an have

Symptom: the metadata-preserving rebuild copied di_flags verbatim. A source
file flagged JDATA (data blocks behind a meta header, bsize - 24 bytes each)
or EA_INDIRECT (an extended-attribute tree) was rewritten with plain data
blocks and no attribute tree while still claiming both, and the writer
accepted any flag word from a caller.

Root cause: di_flags mixes access policy with layout, directory-only and
transient bits (gfs2_ondisk.h), and the writer did not distinguish them.

Fix: the writer accepts only DIRECTIO, IMMUTABLE, APPENDONLY, NOATIME and SYNC
on a regular file and refuses the rest; the edit profile narrows a source
file's flags to that set, skips directories, keeps the first entry of a
repeated name instead of throwing, and zeroes out-of-range nanoseconds.

Tests cover the default attributes, every policy flag, each refused layout
flag, non-regular modes, the 999999999/1000000000 nanosecond boundary, Remove
preservation, JDATA stripping on rebuild and the Uuid create option. A new
external test has fsck.gfs2 accept the volume before and after a rebuild and
gfs2_edit decode mode, uid, gid, the three timestamps and di_flags from the
rebuilt dinode.
The support matrix and limitations now say which attributes a rebuild keeps
and which it drops; the generated API sections were stale for the new
Gfs2InodeMetadata type and writer overloads, which failed the package-README
gate.
@Hawkynt
Hawkynt force-pushed the feat/gfs2-metadata-preservation branch from 16801ef to a2c407d Compare September 30, 2026 18:06
@Hawkynt
Hawkynt merged commit ecfc712 into main Sep 30, 2026
5 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant