Skip to content

[UDFS] Apply PR #283 and PR #339#341

Closed
Copilot wants to merge 44 commits into
udf-devfrom
copilot/apply-pr-283-and-pr-339
Closed

[UDFS] Apply PR #283 and PR #339#341
Copilot wants to merge 44 commits into
udf-devfrom
copilot/apply-pr-283-and-pr-339

Conversation

Copy link
Copy Markdown

Copilot AI commented May 1, 2026

Merges two UDFS improvements: chunked bitmap infrastructure to reduce mount-time NonPagedPool pressure (PR #283), and a set of Driver Verifier–caught double-free / BSOD fixes (PR #339).

PR #283 — Chunked bitmap optimizations

Motivation: Mounting on low-RAM systems (e.g. Windows Server 2003 with 2 GB) failed because FSBM/BSBM/VAT were allocated as single large contiguous NonPagedPool blocks.

  • udf_info.h: New bulk helpers replacing per-bit chunk-pointer lookups:
    • UDFChunkedSetBitRange / UDFChunkedClrBitRange — O(bytes) range ops instead of O(bits)
    • UDFVatGetEntry / UDFVatSetEntry — chunked VAT accessors
    • UDFChunkedCopyMemory, UDFChunkedCompareMemory, UDFChunkedOrMemory
    • UDFReadExtentIntoChunked / UDFWriteExtentFromChunked
    • Updated UDFSetBits/UDFClrBits macros to call bulk helpers
  • alloc.cpp: Fixed UDFGetBitmapLen chunked path (byte-at-a-time scan + null-chunk skip); rewrote UDFMarkBadSpaceAsUsed and UDFGetPartFreeSpace for chunked bitmaps
  • mount.cpp: XSBM buffers allocated via UDFAllocChunked; bitmap read/written sector-by-sector through UDFReadExtentIntoChunked/UDFWriteExtentFromChunked
  • fscntrl.cpp: VCB cleanup uses UDFFreeChunked for Vat, FSBM, BSBM, FSBM_OldBitmap
  • struct.h: Vcb->Vat changed from uint32* to PCHAR for chunked access
  • FSBM bit semantics inverted to bit=1=USED so null (unallocated) chunks implicitly mean all-free, minimizing chunk allocations on mostly-free disks

PR #339 — Double-free / BSOD fixes

  • udf_info/dirtree.cpp (UDFDirIndexFree): moved null check on hDirNdx before FrameList pointer calculation — previously dereferenced a null pointer before returning
  • udf_info/udf_info.cpp (UDFCleanUpFile__): nil-out Dloc->DirIndex before iterating/freeing to prevent use-after-free; introduced tmpDirIndex local
  • dircntrl.cpp (UDFQueryDirectory): null-guard DirectorySearchPattern->Buffer before free; free the descriptor itself on buffer allocation failure to avoid leak
  • struct.h / strucsup.cpp: add CcbListResource ERESOURCE to FCB_NONPAGED; initialize in UDFCreateFcbNonpaged; drain and delete in UDFDeleteFcbNonpaged — fixes Driver Verifier BugCheck 0xC4/0xD2 (pool free with active ERESOURCE)

Merge notes

assorted and others added 30 commits December 25, 2025 18:46
Agent-Logs-Url: https://github.com/Zero3K20/reactos/sessions/ff223f67-8e29-494d-8ec8-faa87755450f

Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com>
Agent-Logs-Url: https://github.com/Zero3K20/reactos/sessions/ff223f67-8e29-494d-8ec8-faa87755450f

Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com>
Agent-Logs-Url: https://github.com/Zero3K20/reactos/sessions/ff223f67-8e29-494d-8ec8-faa87755450f

Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com>
Agent-Logs-Url: https://github.com/Zero3K20/reactos/sessions/ff223f67-8e29-494d-8ec8-faa87755450f

Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com>
…ap buffers

- Add UDFReadExtentIntoChunked and UDFWriteExtentFromChunked inline helpers
  in udf_info.h that walk a chunked bitmap chunk by chunk, calling the flat
  UDFReadExtent/UDFWriteExtent for each contiguous slice.
- UDFPrepareXSpaceBitmap: allocate _XSBM via UDFAllocChunkedBitmap; pass
  chunk-0 pointer to UDFReadTagged, use UDFReadExtentIntoChunked for the full
  read, UDFBitmapFillMemory for zeroing, UDFBitmapGetBytePtr for struct access,
  and UDFFreeChunkedBitmap on error.
- UDFUpdateXSpaceBitmaps: remove flat upart_bm/fpart_bm pointer arithmetic;
  replace with bit-offset constants (sizeof(SPACE_BITMAP_DESC)*8 + j);
  use UDFWriteExtentFromChunked for flushing and UDFFreeChunkedBitmap for
  freeing USBM/FSBM.  Also fix pre-existing bug in recovery path where chunked
  Vcb->FSBM_Bitmap was passed directly to the flat UDFWriteExtent.
- UDFAddXSpaceBitmap: allocate tmp via UDFAllocChunkedBitmap; read header into
  chunk-0 pointer, read full bitmap chunk by chunk via UDFReadData loop; access
  numOfBits through UDFBitmapGetBytePtr; use bit-offset indexing for
  UDFGetBitmapLen/UDFGetFreeBit; free with UDFFreeChunkedBitmap.
- UDFVerifyXSpaceBitmap: same allocation/read pattern; update commented-out
  processing block to use matching offset form.

Agent-Logs-Url: https://github.com/Zero3K20/reactos/sessions/b0226bca-5fc8-436b-9638-bcc54675a10d

Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com>
The chunked-buffer API is now used for bitmaps, VAT entries and generic I/O
buffers, so remove the 'Bitmap' qualifier from every public identifier:

  UDF_BITMAP_CHUNK_{SHIFT,SIZE,MASK} -> UDF_CHUNK_{SHIFT,SIZE,MASK}
  UDF_BITMAP_PTR_TAG                 -> UDF_CHUNKED_PTR_TAG
  UDF_CHUNKED_BITMAP{,_SIGNATURE}    -> UDF_CHUNKED_BUF{,_SIGNATURE}
  PUDF_CHUNKED_BITMAP                -> PUDF_CHUNKED_BUF
  UDFIsChunkedBitmap                 -> UDFIsChunked
  UDFGetChunkedBitmap                -> UDFGetChunked
  UDFTagChunkedBitmap                -> UDFTagChunked
  UDFAllocChunkedBitmap              -> UDFAllocChunked
  UDFFreeChunkedBitmap               -> UDFFreeChunked
  UDFBitmapGetBytePtr                -> UDFChunkedGetBytePtr
  UDFBitmapGetContiguousLength       -> UDFChunkedGetContiguousLength
  UDFBitmapGetByte                   -> UDFChunkedGetByte
  UDFBitmapSetByte                   -> UDFChunkedSetByte
  UDFBitmapSetBit                    -> UDFChunkedSetBit
  UDFBitmapClearBit                  -> UDFChunkedClearBit
  UDFBitmapFillMemory                -> UDFChunkedFillMemory
  UDFBitmapCopyMemory                -> UDFChunkedCopyMemory
  UDFBitmapCompareMemory             -> UDFChunkedCompareMemory
  UDFBitmapAndNotMemory              -> UDFChunkedAndNotMemory

All call sites in udf_info.h, mount.cpp, udf_info.cpp, alloc.cpp and
fscntrl.cpp are updated.

Agent-Logs-Url: https://github.com/Zero3K20/reactos/sessions/d66d281b-5f83-4404-b3d8-638478ae7d6a

Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com>
Agent-Logs-Url: https://github.com/Zero3K20/reactos/sessions/d66d281b-5f83-4404-b3d8-638478ae7d6a
Co-Authored-By: Zero3K20 <258969903+Zero3K20@users.noreply.github.com>
…ory/UDFBitmapCompareMemory aliases

Agent-Logs-Url: https://github.com/Zero3K20/reactos/sessions/357e4e17-140b-4f48-a5cf-8ee571f86649

Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com>
…bugs

UDFAllocChunked now only allocates the header; chunks are lazily
allocated on first write via UDFChunkedGetOrAllocBytePtr. This avoids
committing the full bitmap memory on boot.

Read operations use UDFChunkedGetBytePtr which returns a static
all-zeros chunk for unallocated chunks (0 = 'used' for FSBM bitmaps).

UDFChunkedClearBit returns early when the chunk is NULL since the bit
is already 0. All other write operations (SetBit, SetByte, FillMemory,
CopyMemory, AndNot, ReadExtentIntoChunked, VatSetEntry) now use the
new UDFChunkedGetOrAllocBytePtr write accessor.

Also fix pre-existing direct Vcb->Vat[] byte-indexing bugs (lines
3728, 3736, 3739, 5140) introduced when Vcb->Vat was changed from
uint32* to PCHAR: use proper (uint32*) casts or accessor functions so
the VAT is indexed correctly as a uint32 array.

Agent-Logs-Url: https://github.com/Zero3K20/reactos/sessions/5e1fa1ab-2464-4da2-a139-022bdcf9bd96

Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com>
…at allocation

Both functions previously called DbgAllocatePool(NonPagedPool, max(Length, SectorSize))
where Length is the full on-disk space bitmap size (~64MB for a large disk).  This
allocation failed on systems with limited NonPagedPool, causing UDFProcessSequence
to fail for every anchor location and ultimately printing "No Anchor block found".

UDFAddXSpaceBitmap: rewrite to use a single sector-sized buffer.  Read the first
sector with UDFReadTagged (verifies the tag and obtains numOfBits), then process
bitmap bytes in-place sector by sector, reading each subsequent sector with
UDFReadData.  Free and used bits are copied to FSBM_Bitmap as before.

UDFVerifyXSpaceBitmap: the processing loop was already dead code (commented out).
Reduce the allocation to a single sector (only the tag check is needed) and remove
the now-unnecessary UDFReadData call for the whole bitmap.

Agent-Logs-Url: https://github.com/Zero3K20/reactos/sessions/468e22d7-9f91-48a0-a1af-9ea95334396b

Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com>
…ap byte fast-path

Agent-Logs-Url: https://github.com/Zero3K20/reactos/sessions/791d7ec2-5ba0-4472-a067-4b1312b86426

Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com>
…ostly-free disks

Previously bit=1=FREE, so mounting a mostly-free disk forced chunk allocation
for nearly every sector, exhausting PagedPool on low-memory VMs (64 MB).

With bit=1=USED: null chunks (all-zero) are implicitly all-FREE, so chunks are
only allocated for actually used sectors. A mostly-free large disk now needs
almost no chunk memory at mount time.

Changes:
- udf_info.h: invert UDFGet/SetFree/UsedBit(s) macros; add UDFChunkedOrMemory;
  optimize UDFChunkedFillMemory to skip null chunks on zero-fill
- mount.cpp UDFUpdateXSpaceBitmaps: fix on-disk bitmap output code to use raw
  UDFGetBit/SetBit/ClrBit (FSBM new_bm/old_bm use inverted semantics; output
  upart_bm/fpart_bm use UDF on-disk convention bit=1=free)
- mount.cpp UDFAddXSpaceBitmap: call UDFSetUsedBit for on-disk bit=0 (used);
  skip for bit=1 (free, already default 0 in FSBM); fast path for all-used byte
- alloc.cpp: UDFChunkedAndNotMemory→UDFChunkedOrMemory for bad-block marking;
  fix free-bit count to count zero bits (inverted popcount)

Agent-Logs-Url: https://github.com/Zero3K20/reactos/sessions/e7f24905-cb5d-4ccb-897b-b6b232d89ee0

Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com>
…XSBM buffers

UDFPrepareXSpaceBitmap:
- Allocate *XSBM via UDFAllocChunked instead of a single large flat
  NonPagedPool buffer, reducing peak RAM usage on large volumes.
- Validate the descriptor tag with a small flat sector buffer passed to
  UDFReadTagged; read the full extent directly into the chunked buffer
  via UDFReadExtentIntoChunked.
- Access the SPACE_BITMAP_DESC header through UDFChunkedGetOrAllocBytePtr
  instead of a flat pointer cast; remove the now-redundant RtlZeroMemory
  (chunked chunks are zero-initialised on first allocation).
- Free *XSBM via UDFFreeChunked in all error paths.

UDFUpdateXSpaceBitmaps:
- Remove the flat upart_bm/fpart_bm pointer variables; the bit loop now
  addresses bits in the chunked USBM/FSBM buffers directly using a
  sizeof(SPACE_BITMAP_DESC)*8 header-skip offset with UDFSetBit/UDFClrBit,
  which already dispatch through the chunked path.
- Replace all UDFWriteExtent calls for USBM, FSBM and the recovery-path
  new_bm with UDFWriteExtentFromChunked.
- Free USBM and FSBM via UDFFreeChunked after writing.

Agent-Logs-Url: https://github.com/Zero3K20/reactos/sessions/ebee9663-46f5-4285-8333-99e192cded84

Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com>
Copilot AI and others added 10 commits April 28, 2026 15:17
…BitmapLen

Three changes to eliminate the O(bits) overhead introduced by the chunked
bitmap approach:

1. UDFChunkedGetBytePtr: replace ZeroChunk[UDF_CHUNK_SIZE] with a fixed
   4096-byte array and a C_ASSERT that UDF_CHUNK_SIZE <= 4096.  The old
   definition inflated the driver binary whenever UDF_CHUNK_SHIFT was raised
   because each translation unit embedded its own copy of the array sized to
   UDF_CHUNK_SIZE.  The new definition is always exactly one page regardless
   of UDF_CHUNK_SHIFT.

2. Add UDFChunkedSetBitRange / UDFChunkedClrBitRange inline helpers and use
   them for UDFSetBits / UDFClrBits.  The previous macros called UDFSetBit /
   UDFClrBit in a per-bit loop, so marking N blocks as used/free cost N chunk-
   pointer lookups.  The new helpers handle the leading/trailing partial bytes
   individually and then call UDFChunkedFillMemory for the bulk middle, reducing
   cost to O(chunks) instead of O(bits).

3. Replace the bit-by-bit chunked path in UDFGetBitmapLen with a byte-at-a-
   time scan that skips unallocated (null) chunks in O(1).  On a mostly-free
   disk almost all chunks are null; the old loop visited every bit one at a
   time.  The new path: (a) skips an entire null chunk in one step when
   scanning for free bits, (b) exits immediately on a null chunk when scanning
   for used bits, and (c) uses a full-byte fast path inside allocated chunks.
   This makes UDFFindMinSuitableExtent (called for every file allocation) fast
   again.

Agent-Logs-Url: https://github.com/Zero3K20/reactos/sessions/3ebb2bf5-c977-4e8d-8339-fe15dcc8b381

Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com>
Remove the dead `BS = Vcb->SectorSize` assignment that was left behind
after an earlier refactor; `BS` was never declared as a local variable
in this function, causing a C2065 build error.  `LBS` (the variable
that is actually used) already receives the same value on the next line,
so the dead assignment is simply dropped.

Agent-Logs-Url: https://github.com/Zero3K20/reactos/sessions/9c665003-6edb-442c-889c-087c6ce3dcaa

Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com>
…rySearchPattern->Buffer and cleanup on alloc failure

Agent-Logs-Url: https://github.com/Zero3K20/reactos/sessions/29310a33-9426-4853-8f5d-6d1a33b7d991

Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com>
Copilot AI linked an issue May 1, 2026 that may be closed by this pull request
Copilot AI and others added 4 commits May 1, 2026 03:24
…p optimizations)

Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com>
…PAGED

Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com>
Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com>
…x merge artifacts

Agent-Logs-Url: https://github.com/Zero3K20/reactos/sessions/fd2df4b2-bb62-4535-a8dc-697ac219c316

Co-authored-by: Zero3K20 <258969903+Zero3K20@users.noreply.github.com>
Copilot AI changed the title [WIP] Apply PR #283 and PR #339 [UDFS] Apply PR #283 and PR #339 May 1, 2026
Copilot AI requested a review from Zero3K20 May 1, 2026 03:28
@Zero3K20 Zero3K20 closed this May 1, 2026
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.

[UDFS] Apply PR #283 and PR #339

3 participants