162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * mft.h - Defines for mft record handling in NTFS Linux kernel driver.
462306a36Sopenharmony_ci *	   Part of the Linux-NTFS project.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Copyright (c) 2001-2004 Anton Altaparmakov
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#ifndef _LINUX_NTFS_MFT_H
1062306a36Sopenharmony_ci#define _LINUX_NTFS_MFT_H
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <linux/fs.h>
1362306a36Sopenharmony_ci#include <linux/highmem.h>
1462306a36Sopenharmony_ci#include <linux/pagemap.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#include "inode.h"
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ciextern MFT_RECORD *map_mft_record(ntfs_inode *ni);
1962306a36Sopenharmony_ciextern void unmap_mft_record(ntfs_inode *ni);
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ciextern MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
2262306a36Sopenharmony_ci		ntfs_inode **ntfs_ino);
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_cistatic inline void unmap_extent_mft_record(ntfs_inode *ni)
2562306a36Sopenharmony_ci{
2662306a36Sopenharmony_ci	unmap_mft_record(ni);
2762306a36Sopenharmony_ci	return;
2862306a36Sopenharmony_ci}
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci#ifdef NTFS_RW
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci/**
3362306a36Sopenharmony_ci * flush_dcache_mft_record_page - flush_dcache_page() for mft records
3462306a36Sopenharmony_ci * @ni:		ntfs inode structure of mft record
3562306a36Sopenharmony_ci *
3662306a36Sopenharmony_ci * Call flush_dcache_page() for the page in which an mft record resides.
3762306a36Sopenharmony_ci *
3862306a36Sopenharmony_ci * This must be called every time an mft record is modified, just after the
3962306a36Sopenharmony_ci * modification.
4062306a36Sopenharmony_ci */
4162306a36Sopenharmony_cistatic inline void flush_dcache_mft_record_page(ntfs_inode *ni)
4262306a36Sopenharmony_ci{
4362306a36Sopenharmony_ci	flush_dcache_page(ni->page);
4462306a36Sopenharmony_ci}
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ciextern void __mark_mft_record_dirty(ntfs_inode *ni);
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci/**
4962306a36Sopenharmony_ci * mark_mft_record_dirty - set the mft record and the page containing it dirty
5062306a36Sopenharmony_ci * @ni:		ntfs inode describing the mapped mft record
5162306a36Sopenharmony_ci *
5262306a36Sopenharmony_ci * Set the mapped (extent) mft record of the (base or extent) ntfs inode @ni,
5362306a36Sopenharmony_ci * as well as the page containing the mft record, dirty.  Also, mark the base
5462306a36Sopenharmony_ci * vfs inode dirty.  This ensures that any changes to the mft record are
5562306a36Sopenharmony_ci * written out to disk.
5662306a36Sopenharmony_ci *
5762306a36Sopenharmony_ci * NOTE:  Do not do anything if the mft record is already marked dirty.
5862306a36Sopenharmony_ci */
5962306a36Sopenharmony_cistatic inline void mark_mft_record_dirty(ntfs_inode *ni)
6062306a36Sopenharmony_ci{
6162306a36Sopenharmony_ci	if (!NInoTestSetDirty(ni))
6262306a36Sopenharmony_ci		__mark_mft_record_dirty(ni);
6362306a36Sopenharmony_ci}
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ciextern int ntfs_sync_mft_mirror(ntfs_volume *vol, const unsigned long mft_no,
6662306a36Sopenharmony_ci		MFT_RECORD *m, int sync);
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ciextern int write_mft_record_nolock(ntfs_inode *ni, MFT_RECORD *m, int sync);
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci/**
7162306a36Sopenharmony_ci * write_mft_record - write out a mapped (extent) mft record
7262306a36Sopenharmony_ci * @ni:		ntfs inode describing the mapped (extent) mft record
7362306a36Sopenharmony_ci * @m:		mapped (extent) mft record to write
7462306a36Sopenharmony_ci * @sync:	if true, wait for i/o completion
7562306a36Sopenharmony_ci *
7662306a36Sopenharmony_ci * This is just a wrapper for write_mft_record_nolock() (see mft.c), which
7762306a36Sopenharmony_ci * locks the page for the duration of the write.  This ensures that there are
7862306a36Sopenharmony_ci * no race conditions between writing the mft record via the dirty inode code
7962306a36Sopenharmony_ci * paths and via the page cache write back code paths or between writing
8062306a36Sopenharmony_ci * neighbouring mft records residing in the same page.
8162306a36Sopenharmony_ci *
8262306a36Sopenharmony_ci * Locking the page also serializes us against ->read_folio() if the page is not
8362306a36Sopenharmony_ci * uptodate.
8462306a36Sopenharmony_ci *
8562306a36Sopenharmony_ci * On success, clean the mft record and return 0.  On error, leave the mft
8662306a36Sopenharmony_ci * record dirty and return -errno.
8762306a36Sopenharmony_ci */
8862306a36Sopenharmony_cistatic inline int write_mft_record(ntfs_inode *ni, MFT_RECORD *m, int sync)
8962306a36Sopenharmony_ci{
9062306a36Sopenharmony_ci	struct page *page = ni->page;
9162306a36Sopenharmony_ci	int err;
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	BUG_ON(!page);
9462306a36Sopenharmony_ci	lock_page(page);
9562306a36Sopenharmony_ci	err = write_mft_record_nolock(ni, m, sync);
9662306a36Sopenharmony_ci	unlock_page(page);
9762306a36Sopenharmony_ci	return err;
9862306a36Sopenharmony_ci}
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ciextern bool ntfs_may_write_mft_record(ntfs_volume *vol,
10162306a36Sopenharmony_ci		const unsigned long mft_no, const MFT_RECORD *m,
10262306a36Sopenharmony_ci		ntfs_inode **locked_ni);
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ciextern ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, const int mode,
10562306a36Sopenharmony_ci		ntfs_inode *base_ni, MFT_RECORD **mrec);
10662306a36Sopenharmony_ciextern int ntfs_extent_mft_record_free(ntfs_inode *ni, MFT_RECORD *m);
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci#endif /* NTFS_RW */
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci#endif /* _LINUX_NTFS_MFT_H */
111