18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * mft.h - Defines for mft record handling in NTFS Linux kernel driver.
48c2ecf20Sopenharmony_ci *	   Part of the Linux-NTFS project.
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Copyright (c) 2001-2004 Anton Altaparmakov
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#ifndef _LINUX_NTFS_MFT_H
108c2ecf20Sopenharmony_ci#define _LINUX_NTFS_MFT_H
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <linux/fs.h>
138c2ecf20Sopenharmony_ci#include <linux/highmem.h>
148c2ecf20Sopenharmony_ci#include <linux/pagemap.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#include "inode.h"
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ciextern MFT_RECORD *map_mft_record(ntfs_inode *ni);
198c2ecf20Sopenharmony_ciextern void unmap_mft_record(ntfs_inode *ni);
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ciextern MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
228c2ecf20Sopenharmony_ci		ntfs_inode **ntfs_ino);
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_cistatic inline void unmap_extent_mft_record(ntfs_inode *ni)
258c2ecf20Sopenharmony_ci{
268c2ecf20Sopenharmony_ci	unmap_mft_record(ni);
278c2ecf20Sopenharmony_ci	return;
288c2ecf20Sopenharmony_ci}
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci#ifdef NTFS_RW
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci/**
338c2ecf20Sopenharmony_ci * flush_dcache_mft_record_page - flush_dcache_page() for mft records
348c2ecf20Sopenharmony_ci * @ni:		ntfs inode structure of mft record
358c2ecf20Sopenharmony_ci *
368c2ecf20Sopenharmony_ci * Call flush_dcache_page() for the page in which an mft record resides.
378c2ecf20Sopenharmony_ci *
388c2ecf20Sopenharmony_ci * This must be called every time an mft record is modified, just after the
398c2ecf20Sopenharmony_ci * modification.
408c2ecf20Sopenharmony_ci */
418c2ecf20Sopenharmony_cistatic inline void flush_dcache_mft_record_page(ntfs_inode *ni)
428c2ecf20Sopenharmony_ci{
438c2ecf20Sopenharmony_ci	flush_dcache_page(ni->page);
448c2ecf20Sopenharmony_ci}
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ciextern void __mark_mft_record_dirty(ntfs_inode *ni);
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci/**
498c2ecf20Sopenharmony_ci * mark_mft_record_dirty - set the mft record and the page containing it dirty
508c2ecf20Sopenharmony_ci * @ni:		ntfs inode describing the mapped mft record
518c2ecf20Sopenharmony_ci *
528c2ecf20Sopenharmony_ci * Set the mapped (extent) mft record of the (base or extent) ntfs inode @ni,
538c2ecf20Sopenharmony_ci * as well as the page containing the mft record, dirty.  Also, mark the base
548c2ecf20Sopenharmony_ci * vfs inode dirty.  This ensures that any changes to the mft record are
558c2ecf20Sopenharmony_ci * written out to disk.
568c2ecf20Sopenharmony_ci *
578c2ecf20Sopenharmony_ci * NOTE:  Do not do anything if the mft record is already marked dirty.
588c2ecf20Sopenharmony_ci */
598c2ecf20Sopenharmony_cistatic inline void mark_mft_record_dirty(ntfs_inode *ni)
608c2ecf20Sopenharmony_ci{
618c2ecf20Sopenharmony_ci	if (!NInoTestSetDirty(ni))
628c2ecf20Sopenharmony_ci		__mark_mft_record_dirty(ni);
638c2ecf20Sopenharmony_ci}
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ciextern int ntfs_sync_mft_mirror(ntfs_volume *vol, const unsigned long mft_no,
668c2ecf20Sopenharmony_ci		MFT_RECORD *m, int sync);
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ciextern int write_mft_record_nolock(ntfs_inode *ni, MFT_RECORD *m, int sync);
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci/**
718c2ecf20Sopenharmony_ci * write_mft_record - write out a mapped (extent) mft record
728c2ecf20Sopenharmony_ci * @ni:		ntfs inode describing the mapped (extent) mft record
738c2ecf20Sopenharmony_ci * @m:		mapped (extent) mft record to write
748c2ecf20Sopenharmony_ci * @sync:	if true, wait for i/o completion
758c2ecf20Sopenharmony_ci *
768c2ecf20Sopenharmony_ci * This is just a wrapper for write_mft_record_nolock() (see mft.c), which
778c2ecf20Sopenharmony_ci * locks the page for the duration of the write.  This ensures that there are
788c2ecf20Sopenharmony_ci * no race conditions between writing the mft record via the dirty inode code
798c2ecf20Sopenharmony_ci * paths and via the page cache write back code paths or between writing
808c2ecf20Sopenharmony_ci * neighbouring mft records residing in the same page.
818c2ecf20Sopenharmony_ci *
828c2ecf20Sopenharmony_ci * Locking the page also serializes us against ->readpage() if the page is not
838c2ecf20Sopenharmony_ci * uptodate.
848c2ecf20Sopenharmony_ci *
858c2ecf20Sopenharmony_ci * On success, clean the mft record and return 0.  On error, leave the mft
868c2ecf20Sopenharmony_ci * record dirty and return -errno.
878c2ecf20Sopenharmony_ci */
888c2ecf20Sopenharmony_cistatic inline int write_mft_record(ntfs_inode *ni, MFT_RECORD *m, int sync)
898c2ecf20Sopenharmony_ci{
908c2ecf20Sopenharmony_ci	struct page *page = ni->page;
918c2ecf20Sopenharmony_ci	int err;
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	BUG_ON(!page);
948c2ecf20Sopenharmony_ci	lock_page(page);
958c2ecf20Sopenharmony_ci	err = write_mft_record_nolock(ni, m, sync);
968c2ecf20Sopenharmony_ci	unlock_page(page);
978c2ecf20Sopenharmony_ci	return err;
988c2ecf20Sopenharmony_ci}
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ciextern bool ntfs_may_write_mft_record(ntfs_volume *vol,
1018c2ecf20Sopenharmony_ci		const unsigned long mft_no, const MFT_RECORD *m,
1028c2ecf20Sopenharmony_ci		ntfs_inode **locked_ni);
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ciextern ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, const int mode,
1058c2ecf20Sopenharmony_ci		ntfs_inode *base_ni, MFT_RECORD **mrec);
1068c2ecf20Sopenharmony_ciextern int ntfs_extent_mft_record_free(ntfs_inode *ni, MFT_RECORD *m);
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci#endif /* NTFS_RW */
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci#endif /* _LINUX_NTFS_MFT_H */
111