mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
ntfs: use sync flag for direct MFT writes
Use the supplied sync flag for direct MFT writes instead of forcing
containing-unit writes to complete synchronously.
Pass sync=1 from ntfs_mft_record_free() so the MFT bitmap entry is not
released until the record write completes. Other direct-write callers keep
the completion mode requested by their caller.
The folio lock serializes write preparation, and PG_writeback keeps the
whole unit stable until all chained BIOs complete, so asynchronous
containing-unit writes remain safe.
Fixes: 115380f9a2 ("ntfs: update mft operations")
Cc: stable@vger.kernel.org
Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
This commit is contained in:
parent
4437d9d787
commit
43e2fff9f4
|
|
@ -671,9 +671,13 @@ static int ntfs_prepare_mft_record_io_units(struct ntfs_inode *ni,
|
|||
*
|
||||
* We only write the mft record if the ntfs inode @ni is dirty.
|
||||
*
|
||||
* On success, clean the mft record and return 0.
|
||||
* On error (specifically ENOMEM), we redirty the record so it can be retried.
|
||||
* For other errors, we mark the volume with errors.
|
||||
* On success, clean the mft record and return 0. On ENOMEM, redirty the
|
||||
* record so it can be retried. Asynchronous callers return success after
|
||||
* redirtying while synchronous callers receive the error. For other errors,
|
||||
* mark the volume with errors.
|
||||
*
|
||||
* If @sync is false, PG_writeback keeps the folio stable and serializes later
|
||||
* writers until the I/O completes.
|
||||
*/
|
||||
int write_mft_record_nolock(struct ntfs_inode *ni, struct mft_record *m, int sync)
|
||||
{
|
||||
|
|
@ -693,8 +697,6 @@ int write_mft_record_nolock(struct ntfs_inode *ni, struct mft_record *m, int syn
|
|||
WARN_ON(NInoAttr(ni));
|
||||
WARN_ON(!folio_test_locked(folio));
|
||||
|
||||
if (vol->mft_io_unit_size > vol->mft_record_size)
|
||||
sync = 1;
|
||||
if (folio_test_writeback(folio))
|
||||
folio_wait_writeback(folio);
|
||||
|
||||
|
|
@ -804,7 +806,8 @@ int write_mft_record_nolock(struct ntfs_inode *ni, struct mft_record *m, int syn
|
|||
ntfs_error(vol->sb,
|
||||
"Not enough memory to write mft record. Redirtying so the write is retried later.");
|
||||
mark_mft_record_dirty(ni);
|
||||
err = 0;
|
||||
if (!sync)
|
||||
err = 0;
|
||||
} else
|
||||
NVolSetErrors(vol);
|
||||
return err;
|
||||
|
|
@ -2959,7 +2962,7 @@ int ntfs_mft_record_free(struct ntfs_volume *vol, struct ntfs_inode *ni)
|
|||
* record to be freed is guaranteed to do it already.
|
||||
*/
|
||||
NInoSetDirty(ni);
|
||||
err = write_mft_record(ni, ni_mrec, 0);
|
||||
err = write_mft_record(ni, ni_mrec, 1);
|
||||
if (err)
|
||||
goto sync_rollback;
|
||||
|
||||
|
|
|
|||
|
|
@ -53,17 +53,19 @@ int write_mft_record_nolock(struct ntfs_inode *ni, struct mft_record *m, int syn
|
|||
* @sync: if true, wait for i/o completion
|
||||
*
|
||||
* This is just a wrapper for write_mft_record_nolock() (see mft.c), which
|
||||
* locks the folio for the duration of the write. The folio lock prevents
|
||||
* races between writing the mft record via the dirty inode code paths and via
|
||||
* page cache writeback or between neighbouring mft records residing in the
|
||||
* same folio.
|
||||
* locks the folio while preparing the write. write_mft_record_nolock() waits
|
||||
* for prior folio writeback before modifying the folio and keeps PG_writeback
|
||||
* set until the submitted I/O completes. Together these serialize dirty
|
||||
* inode writes, page cache writeback, and neighbouring mft record writes in
|
||||
* the same folio.
|
||||
*
|
||||
* Locking the page also serializes us against ->read_folio() if the page is not
|
||||
* uptodate.
|
||||
*
|
||||
* On success, clean the mft record and return 0. On allocation failure,
|
||||
* redirty the record for retry and return 0. On other errors, return -errno
|
||||
* and mark the volume with errors.
|
||||
* redirty the record for retry. Asynchronous callers return 0 after
|
||||
* redirtying, while synchronous callers receive -ENOMEM. On other errors,
|
||||
* return -errno and mark the volume with errors.
|
||||
*/
|
||||
static inline int write_mft_record(struct ntfs_inode *ni, struct mft_record *m, int sync)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user