<feed xmlns='http://www.w3.org/2005/Atom'>
<title>linux-toradex.git/fs/ntfs, branch master</title>
<subtitle>Linux kernel for Apalis and Colibri modules</subtitle>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/'/>
<entry>
<title>Merge tag 'ntfs-for-7.3-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/ntfs</title>
<updated>2026-09-18T18:02:08+00:00</updated>
<author>
<name>Linus Torvalds</name>
<email>torvalds@linux-foundation.org</email>
</author>
<published>2026-09-18T18:02:08+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=bfda5a01aa99c5c363ac9967b81cbd5902d6c940'/>
<id>bfda5a01aa99c5c363ac9967b81cbd5902d6c940</id>
<content type='text'>
Pull ntfs fixes from Namjae Jeon:

 - Make MFT extension work on existing Windows-created volumes by
   dynamically reserving MFT tail records, accounting for records added
   during allocation, and avoiding false -ENOSPC failures

 - Repack non-resident $MFT/$ATTRIBUTE_LIST when its mapping pairs no
   longer fit in the base MFT record, while propagating allocation and
   writeback errors

 - Serialize runlist updates with the runlist lock and restore both the
   in-memory runlist and on-disk mapping pairs when allocation rollback
   is required

 - Propagate folio errors and harden inode failure handling by treating
   interrupted reads as transient failures and discarding and unhashing
   inodes whose initialization fails

 - Fix the $MFTMirr write offset when mirror records span multiple
   folios, preventing mirror records from overwriting the first record
   with large MFT record sizes

* tag 'ntfs-for-7.3-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/ntfs:
  ntfs: fix $MFTMirr write offset when it spans multiple folios
  ntfs: unhash failed inode reads
  ntfs: discard inodes that fail initialization
  ntfs: ignore interrupted inode reads as corruption
  ntfs: propagate folio errors
  ntfs: protect runlist updates with the runlist lock
  ntfs: account for MFT records added during allocation
  ntfs: repack $MFT/$ATTRIBUTE LIST
  ntfs: use dynamic MFT tail reservation
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Pull ntfs fixes from Namjae Jeon:

 - Make MFT extension work on existing Windows-created volumes by
   dynamically reserving MFT tail records, accounting for records added
   during allocation, and avoiding false -ENOSPC failures

 - Repack non-resident $MFT/$ATTRIBUTE_LIST when its mapping pairs no
   longer fit in the base MFT record, while propagating allocation and
   writeback errors

 - Serialize runlist updates with the runlist lock and restore both the
   in-memory runlist and on-disk mapping pairs when allocation rollback
   is required

 - Propagate folio errors and harden inode failure handling by treating
   interrupted reads as transient failures and discarding and unhashing
   inodes whose initialization fails

 - Fix the $MFTMirr write offset when mirror records span multiple
   folios, preventing mirror records from overwriting the first record
   with large MFT record sizes

* tag 'ntfs-for-7.3-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/ntfs:
  ntfs: fix $MFTMirr write offset when it spans multiple folios
  ntfs: unhash failed inode reads
  ntfs: discard inodes that fail initialization
  ntfs: ignore interrupted inode reads as corruption
  ntfs: propagate folio errors
  ntfs: protect runlist updates with the runlist lock
  ntfs: account for MFT records added during allocation
  ntfs: repack $MFT/$ATTRIBUTE LIST
  ntfs: use dynamic MFT tail reservation
</pre>
</div>
</content>
</entry>
<entry>
<title>ntfs: fix $MFTMirr write offset when it spans multiple folios</title>
<updated>2026-09-13T02:41:58+00:00</updated>
<author>
<name>Zhu Tianhao</name>
<email>zhutianhao75@hotmail.com</email>
</author>
<published>2026-09-07T20:41:00+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=229e8188307b9724cc676a49e9600c4acd24b571'/>
<id>229e8188307b9724cc676a49e9600c4acd24b571</id>
<content type='text'>
When commit 115380f9a2f9 ("ntfs: update mft operations") refactored the
MFT code to use folios, it assumed $MFTMirr is allocated contiguously,
which is indeed what mkfs arranges.  However, the folio rewrite kept a
leftover from the old buffer-head/runlist based implementation:
vol-&gt;cluster_size_mask is still applied to the mirror write offset.
In fact it is no longer needed -- and in some configurations it is
actively wrong.

The bug triggers whenever the four mirror records do not fit in a
single folio, i.e. when mft_record_size exceeds PAGE_SIZE / 4 (for
example mft_record_size &gt; 1KiB on 4KiB pages).

For example, on the built-in 4Kn SSD (Apple SSD AP0256J) of a
MacBookPro14,1 with 4096-byte MFT records, mirror record 3 is still
written to the location of record 0.  $MFTMirr therefore gets out of
sync with $MFT and the following warning is printed on remount:

        ntfs: (device nvme0n1p3): check_mft_mirror(): $MFT and $MFTMirr
              record 0 do not match.  Run chkdsk.

Fix it by always adding the folio offset (folio-&gt;index &lt;&lt; PAGE_SHIFT)
to the base LCN address instead of applying the cluster_size_mask
truncation.  This is the standard file-offset calculation and is
correct for every combination of cluster size, page size and MFT
record size, provided $MFTMirr data is contiguous from mftmirr_lcn
(which mkfs always arranges).

Tested on the volume above: before the change mirror records 1-3 are
all written to record 0's sector; after the change the write-back
probe reports:

        ntfs: NTFSDBG pre mft_no=0x3 folio_idx=0x3 ofs=0x0 mftmirr_lcn=0x2540c5 clu_bits=12 rec_bits=12 PAGE_SHIFT=12 sect=0x12a0640
        ntfs: NTFSDBG pre mft_no=0x0 folio_idx=0x0 ofs=0x0 mftmirr_lcn=0x2540c5 clu_bits=12 rec_bits=12 PAGE_SHIFT=12 sect=0x12a0628

which matches the expected sectors computed as:

        (NTFS_CLU_TO_B(mftmirr_lcn) + (folio-&gt;index &lt;&lt; PAGE_SHIFT)) &gt;&gt; SECTOR_SHIFT

        record 0: (0x2540c5 &lt;&lt; 12) + 0x0000 = 0x2540c5000 &gt;&gt; 9 = 0x12a0628
        record 3: (0x2540c5 &lt;&lt; 12) + 0x3000 = 0x2540c8000 &gt;&gt; 9 = 0x12a0640

A 13 MB file write succeeds on this volume and the file is byte-for-byte
identical after a umount/mount cycle.

Fixes: 115380f9a2f9 ("ntfs: update mft operations")
Assisted-by: UOS-AI
Assisted-by: CodeBuddy:Hy4 preview
Signed-off-by: Zhu Tianhao &lt;zhutianhao75@hotmail.com&gt;
Reviewed-by: Baolin Liu &lt;liubaolin@kylinos.cn&gt;
Signed-off-by: Namjae Jeon &lt;linkinjeon@kernel.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
When commit 115380f9a2f9 ("ntfs: update mft operations") refactored the
MFT code to use folios, it assumed $MFTMirr is allocated contiguously,
which is indeed what mkfs arranges.  However, the folio rewrite kept a
leftover from the old buffer-head/runlist based implementation:
vol-&gt;cluster_size_mask is still applied to the mirror write offset.
In fact it is no longer needed -- and in some configurations it is
actively wrong.

The bug triggers whenever the four mirror records do not fit in a
single folio, i.e. when mft_record_size exceeds PAGE_SIZE / 4 (for
example mft_record_size &gt; 1KiB on 4KiB pages).

For example, on the built-in 4Kn SSD (Apple SSD AP0256J) of a
MacBookPro14,1 with 4096-byte MFT records, mirror record 3 is still
written to the location of record 0.  $MFTMirr therefore gets out of
sync with $MFT and the following warning is printed on remount:

        ntfs: (device nvme0n1p3): check_mft_mirror(): $MFT and $MFTMirr
              record 0 do not match.  Run chkdsk.

Fix it by always adding the folio offset (folio-&gt;index &lt;&lt; PAGE_SHIFT)
to the base LCN address instead of applying the cluster_size_mask
truncation.  This is the standard file-offset calculation and is
correct for every combination of cluster size, page size and MFT
record size, provided $MFTMirr data is contiguous from mftmirr_lcn
(which mkfs always arranges).

Tested on the volume above: before the change mirror records 1-3 are
all written to record 0's sector; after the change the write-back
probe reports:

        ntfs: NTFSDBG pre mft_no=0x3 folio_idx=0x3 ofs=0x0 mftmirr_lcn=0x2540c5 clu_bits=12 rec_bits=12 PAGE_SHIFT=12 sect=0x12a0640
        ntfs: NTFSDBG pre mft_no=0x0 folio_idx=0x0 ofs=0x0 mftmirr_lcn=0x2540c5 clu_bits=12 rec_bits=12 PAGE_SHIFT=12 sect=0x12a0628

which matches the expected sectors computed as:

        (NTFS_CLU_TO_B(mftmirr_lcn) + (folio-&gt;index &lt;&lt; PAGE_SHIFT)) &gt;&gt; SECTOR_SHIFT

        record 0: (0x2540c5 &lt;&lt; 12) + 0x0000 = 0x2540c5000 &gt;&gt; 9 = 0x12a0628
        record 3: (0x2540c5 &lt;&lt; 12) + 0x3000 = 0x2540c8000 &gt;&gt; 9 = 0x12a0640

A 13 MB file write succeeds on this volume and the file is byte-for-byte
identical after a umount/mount cycle.

Fixes: 115380f9a2f9 ("ntfs: update mft operations")
Assisted-by: UOS-AI
Assisted-by: CodeBuddy:Hy4 preview
Signed-off-by: Zhu Tianhao &lt;zhutianhao75@hotmail.com&gt;
Reviewed-by: Baolin Liu &lt;liubaolin@kylinos.cn&gt;
Signed-off-by: Namjae Jeon &lt;linkinjeon@kernel.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>ntfs: unhash failed inode reads</title>
<updated>2026-09-13T02:41:54+00:00</updated>
<author>
<name>Namjae Jeon</name>
<email>linkinjeon@kernel.org</email>
</author>
<published>2026-09-07T04:38:17+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=0c32a42fd96a0e7c06c8a648a6dd8f1ec0bf643b'/>
<id>0c32a42fd96a0e7c06c8a648a6dd8f1ec0bf643b</id>
<content type='text'>
Remove a newly allocated inode from the inode hash before discarding it.
NTFS may set i_nlink before a later initialization step fails, in which
case iput alone can retain the incomplete inode in the cache.

Fixes: bf6be898fbc5 ("ntfs: discard inodes that fail initialization")
Reviewed-by: Hyunchul Lee &lt;hyc.lee@gmail.com&gt;
Signed-off-by: Namjae Jeon &lt;linkinjeon@kernel.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Remove a newly allocated inode from the inode hash before discarding it.
NTFS may set i_nlink before a later initialization step fails, in which
case iput alone can retain the incomplete inode in the cache.

Fixes: bf6be898fbc5 ("ntfs: discard inodes that fail initialization")
Reviewed-by: Hyunchul Lee &lt;hyc.lee@gmail.com&gt;
Signed-off-by: Namjae Jeon &lt;linkinjeon@kernel.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>ntfs: discard inodes that fail initialization</title>
<updated>2026-09-13T02:41:49+00:00</updated>
<author>
<name>Namjae Jeon</name>
<email>linkinjeon@kernel.org</email>
</author>
<published>2026-09-07T04:34:44+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=fc440366c47000b768d013e347f60e81d60328ca'/>
<id>fc440366c47000b768d013e347f60e81d60328ca</id>
<content type='text'>
Discard a newly allocated normal, attribute, or index inode when
initialization fails. Keeping an incompletely initialized inode in the
inode cache can expose stale sequence data to later directory lookups.

Fixes: d7aa04984f12 ("ntfs: return errors from inode initialization")
Reviewed-by: Hyunchul Lee &lt;hyc.lee@gmail.com&gt;
Signed-off-by: Namjae Jeon &lt;linkinjeon@kernel.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Discard a newly allocated normal, attribute, or index inode when
initialization fails. Keeping an incompletely initialized inode in the
inode cache can expose stale sequence data to later directory lookups.

Fixes: d7aa04984f12 ("ntfs: return errors from inode initialization")
Reviewed-by: Hyunchul Lee &lt;hyc.lee@gmail.com&gt;
Signed-off-by: Namjae Jeon &lt;linkinjeon@kernel.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>ntfs: ignore interrupted inode reads as corruption</title>
<updated>2026-09-13T02:41:47+00:00</updated>
<author>
<name>Namjae Jeon</name>
<email>linkinjeon@kernel.org</email>
</author>
<published>2026-09-07T04:34:25+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=8c5dc7587fdd45f957af81a9adc1e16863f300fc'/>
<id>8c5dc7587fdd45f957af81a9adc1e16863f300fc</id>
<content type='text'>
Do not mark the volume in error or report an inode as corrupt when
reading it was interrupted by a signal. -EINTR and -ERESTARTSYS indicate
a transient read failure rather than on-disk NTFS corruption.

Fixes: 115380f9a2f9 ("ntfs: update mft operations")
Reviewed-by: Hyunchul Lee &lt;hyc.lee@gmail.com&gt;
Signed-off-by: Namjae Jeon &lt;linkinjeon@kernel.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Do not mark the volume in error or report an inode as corrupt when
reading it was interrupted by a signal. -EINTR and -ERESTARTSYS indicate
a transient read failure rather than on-disk NTFS corruption.

Fixes: 115380f9a2f9 ("ntfs: update mft operations")
Reviewed-by: Hyunchul Lee &lt;hyc.lee@gmail.com&gt;
Signed-off-by: Namjae Jeon &lt;linkinjeon@kernel.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>ntfs: propagate folio errors</title>
<updated>2026-09-13T02:41:44+00:00</updated>
<author>
<name>Namjae Jeon</name>
<email>linkinjeon@kernel.org</email>
</author>
<published>2026-09-07T04:34:01+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=1923eeffa63edeff427d76fc302bc5eb835771ce'/>
<id>1923eeffa63edeff427d76fc302bc5eb835771ce</id>
<content type='text'>
Return the error from __filemap_get_folio() instead of replacing it
with -ENOMEM.

Fixes: af0db57d4293 ("ntfs: update inode operations")
Reviewed-by: Hyunchul Lee &lt;hyc.lee@gmail.com&gt;
Signed-off-by: Namjae Jeon &lt;linkinjeon@kernel.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Return the error from __filemap_get_folio() instead of replacing it
with -ENOMEM.

Fixes: af0db57d4293 ("ntfs: update inode operations")
Reviewed-by: Hyunchul Lee &lt;hyc.lee@gmail.com&gt;
Signed-off-by: Namjae Jeon &lt;linkinjeon@kernel.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>ntfs: protect runlist updates with the runlist lock</title>
<updated>2026-09-13T02:41:42+00:00</updated>
<author>
<name>Namjae Jeon</name>
<email>linkinjeon@kernel.org</email>
</author>
<published>2026-09-06T12:37:28+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=91709ba5d6d709b2b663287b7e871e2c6b480502'/>
<id>91709ba5d6d709b2b663287b7e871e2c6b480502</id>
<content type='text'>
ntfs_non_resident_attr_shrink() calls runlist helpers that require the
runlist write lock, but did not hold it while freeing clusters and
truncating the runlist. Serialize those operations and the resident
conversion with the runlist lock.

ntfs_attr_map_cluster() can merge a newly allocated run before updating
mapping pairs. If the update fails, free the clusters and restore both
the in-memory runlist and on-disk mapping pairs from a saved runlist.
Mark the volume in error if either rollback step fails.

Fixes: 495e90fa3348 ("ntfs: update attrib operations")
Reviewed-by: Hyunchul Lee &lt;hyc.lee@gmail.com&gt;
Signed-off-by: Namjae Jeon &lt;linkinjeon@kernel.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
ntfs_non_resident_attr_shrink() calls runlist helpers that require the
runlist write lock, but did not hold it while freeing clusters and
truncating the runlist. Serialize those operations and the resident
conversion with the runlist lock.

ntfs_attr_map_cluster() can merge a newly allocated run before updating
mapping pairs. If the update fails, free the clusters and restore both
the in-memory runlist and on-disk mapping pairs from a saved runlist.
Mark the volume in error if either rollback step fails.

Fixes: 495e90fa3348 ("ntfs: update attrib operations")
Reviewed-by: Hyunchul Lee &lt;hyc.lee@gmail.com&gt;
Signed-off-by: Namjae Jeon &lt;linkinjeon@kernel.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>ntfs: account for MFT records added during allocation</title>
<updated>2026-09-13T02:41:40+00:00</updated>
<author>
<name>Namjae Jeon</name>
<email>linkinjeon@kernel.org</email>
</author>
<published>2026-09-04T05:46:38+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=631946431ddc66a472c5cc629cd654e62dfa1f88'/>
<id>631946431ddc66a472c5cc629cd654e62dfa1f88</id>
<content type='text'>
When no free MFT record is available in the initialized $MFT/$BITMAP,
ntfs_mft_record_alloc() extends $MFT/$DATA and formats the requested record
together with a dynamically sized tail reserve. Those records become
visible through the $MFT file size before charging the requested record to
the free-record counter.

Account for all newly visible records before releasing the MFT allocation
lock, then subtract the one record being allocated. Keep MFT counter
updates independent of the asynchronous free-cluster scan and update the
counter when a record is successfully cleared in the MFT bitmap.

Store the clamped result of the MFT bitmap scan and keep statfs from
exposing an invalid cached count if an accounting error occurs.

Fixes: 115380f9a2f9 ("ntfs: update mft operations")
Reviewed-by: Hyunchul Lee &lt;hyc.lee@gmail.com&gt;
Signed-off-by: Namjae Jeon &lt;linkinjeon@kernel.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
When no free MFT record is available in the initialized $MFT/$BITMAP,
ntfs_mft_record_alloc() extends $MFT/$DATA and formats the requested record
together with a dynamically sized tail reserve. Those records become
visible through the $MFT file size before charging the requested record to
the free-record counter.

Account for all newly visible records before releasing the MFT allocation
lock, then subtract the one record being allocated. Keep MFT counter
updates independent of the asynchronous free-cluster scan and update the
counter when a record is successfully cleared in the MFT bitmap.

Store the clamped result of the MFT bitmap scan and keep statfs from
exposing an invalid cached count if an accounting error occurs.

Fixes: 115380f9a2f9 ("ntfs: update mft operations")
Reviewed-by: Hyunchul Lee &lt;hyc.lee@gmail.com&gt;
Signed-off-by: Namjae Jeon &lt;linkinjeon@kernel.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>ntfs: repack $MFT/$ATTRIBUTE LIST</title>
<updated>2026-09-13T02:41:38+00:00</updated>
<author>
<name>Namjae Jeon</name>
<email>linkinjeon@kernel.org</email>
</author>
<published>2026-09-06T02:12:47+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=b1d732e62a5b3942546e4edaab8976258e779287'/>
<id>b1d732e62a5b3942546e4edaab8976258e779287</id>
<content type='text'>
Repack the non-resident $MFT/$ATTRIBUTE_LIST into a contiguous run
when its mapping pairs no longer fit in the base MFT record. Propagate
allocation and writeback errors, and check synchronous replacement writes.

Fixes: 495e90fa3348 ("ntfs: update attrib operations")
Reviewed-by: Hyunchul Lee &lt;hyc.lee@gmail.com&gt;
Signed-off-by: Namjae Jeon &lt;linkinjeon@kernel.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Repack the non-resident $MFT/$ATTRIBUTE_LIST into a contiguous run
when its mapping pairs no longer fit in the base MFT record. Propagate
allocation and writeback errors, and check synchronous replacement writes.

Fixes: 495e90fa3348 ("ntfs: update attrib operations")
Reviewed-by: Hyunchul Lee &lt;hyc.lee@gmail.com&gt;
Signed-off-by: Namjae Jeon &lt;linkinjeon@kernel.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>ntfs: use dynamic MFT tail reservation</title>
<updated>2026-09-13T02:41:34+00:00</updated>
<author>
<name>Namjae Jeon</name>
<email>linkinjeon@kernel.org</email>
</author>
<published>2026-09-08T06:52:46+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=6d8c197c9992659a65525a07de4368c8401fdda7'/>
<id>6d8c197c9992659a65525a07de4368c8401fdda7</id>
<content type='text'>
The ntfs MFT allocator historically treated records below 64 as a
permanent extension area and stopped searching for $MFT extent records
after record 400. Windows and ntfs3 do not maintain that on-disk
layout, so an NTFS volume can have free MFT records while ntfs returns
-ENOSPC when $MFT:$DATA needs another mapping-pairs extent.

Use record 24 as the first normal record and maintain an in-memory tail
reserve of up to four initialized records. Normal allocations skip the
reserve, while $MFT metadata extent allocations consume it. When a new
tail is initialized, allocate at least two records and reserve the
following records to avoid recursive allocation during MFT extension.
Existing free runs can seed the reserve on volumes mounted without one.

For $MFT/$DATA, constrain an extent record to a record whose byte offset
is below the new extent lowest VCN byte offset. This preserves bootstrap
reachability without an arbitrary record 400 limit. If no safe record is
available, validate and use reserved records 15, 12, 13, and 14 as
bootstrap candidates while keeping their MFT bitmap entries in use.

This allows existing Windows volumes to extend $MFT using their actual
free records and prevents normal file allocation from consuming
the metadata reserve.

Fixes: 115380f9a2f9 ("ntfs: update mft operations")
Reviewed-by: Hyunchul Lee &lt;hyc.lee@gmail.com&gt;
Signed-off-by: Namjae Jeon &lt;linkinjeon@kernel.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The ntfs MFT allocator historically treated records below 64 as a
permanent extension area and stopped searching for $MFT extent records
after record 400. Windows and ntfs3 do not maintain that on-disk
layout, so an NTFS volume can have free MFT records while ntfs returns
-ENOSPC when $MFT:$DATA needs another mapping-pairs extent.

Use record 24 as the first normal record and maintain an in-memory tail
reserve of up to four initialized records. Normal allocations skip the
reserve, while $MFT metadata extent allocations consume it. When a new
tail is initialized, allocate at least two records and reserve the
following records to avoid recursive allocation during MFT extension.
Existing free runs can seed the reserve on volumes mounted without one.

For $MFT/$DATA, constrain an extent record to a record whose byte offset
is below the new extent lowest VCN byte offset. This preserves bootstrap
reachability without an arbitrary record 400 limit. If no safe record is
available, validate and use reserved records 15, 12, 13, and 14 as
bootstrap candidates while keeping their MFT bitmap entries in use.

This allows existing Windows volumes to extend $MFT using their actual
free records and prevents normal file allocation from consuming
the metadata reserve.

Fixes: 115380f9a2f9 ("ntfs: update mft operations")
Reviewed-by: Hyunchul Lee &lt;hyc.lee@gmail.com&gt;
Signed-off-by: Namjae Jeon &lt;linkinjeon@kernel.org&gt;
</pre>
</div>
</content>
</entry>
</feed>
