xref: /openbmc/linux/fs/ntfs3/ntfs_fs.h (revision 0ad9dfcb)
14534a70bSKonstantin Komarov /* SPDX-License-Identifier: GPL-2.0 */
24534a70bSKonstantin Komarov /*
34534a70bSKonstantin Komarov  *
44534a70bSKonstantin Komarov  * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
54534a70bSKonstantin Komarov  *
64534a70bSKonstantin Komarov  */
74534a70bSKonstantin Komarov 
84534a70bSKonstantin Komarov // clang-format off
987790b65SKari Argillander #ifndef _LINUX_NTFS3_NTFS_FS_H
1087790b65SKari Argillander #define _LINUX_NTFS3_NTFS_FS_H
1187790b65SKari Argillander 
12f239b3a9SKari Argillander #include <linux/blkdev.h>
13f239b3a9SKari Argillander #include <linux/buffer_head.h>
14f239b3a9SKari Argillander #include <linux/fs.h>
15f239b3a9SKari Argillander #include <linux/highmem.h>
16f239b3a9SKari Argillander #include <linux/kernel.h>
17f239b3a9SKari Argillander #include <linux/mm.h>
18f239b3a9SKari Argillander #include <linux/mutex.h>
19f239b3a9SKari Argillander #include <linux/page-flags.h>
20f239b3a9SKari Argillander #include <linux/pagemap.h>
21f239b3a9SKari Argillander #include <linux/rbtree.h>
22f239b3a9SKari Argillander #include <linux/rwsem.h>
23f239b3a9SKari Argillander #include <linux/slab.h>
24f239b3a9SKari Argillander #include <linux/string.h>
25f239b3a9SKari Argillander #include <linux/time64.h>
26f239b3a9SKari Argillander #include <linux/types.h>
27f239b3a9SKari Argillander #include <linux/uidgid.h>
28f239b3a9SKari Argillander #include <asm/div64.h>
29f239b3a9SKari Argillander #include <asm/page.h>
30f239b3a9SKari Argillander 
31f239b3a9SKari Argillander #include "debug.h"
32f239b3a9SKari Argillander #include "ntfs.h"
33f239b3a9SKari Argillander 
34f239b3a9SKari Argillander struct dentry;
35f239b3a9SKari Argillander struct fiemap_extent_info;
36f239b3a9SKari Argillander struct user_namespace;
37f239b3a9SKari Argillander struct page;
38f239b3a9SKari Argillander struct writeback_control;
39f239b3a9SKari Argillander enum utf16_endian;
40f239b3a9SKari Argillander 
41f239b3a9SKari Argillander 
424534a70bSKonstantin Komarov #define MINUS_ONE_T			((size_t)(-1))
434534a70bSKonstantin Komarov /* Biggest MFT / smallest cluster */
444534a70bSKonstantin Komarov #define MAXIMUM_BYTES_PER_MFT		4096
454534a70bSKonstantin Komarov #define NTFS_BLOCKS_PER_MFT_RECORD	(MAXIMUM_BYTES_PER_MFT / 512)
464534a70bSKonstantin Komarov 
474534a70bSKonstantin Komarov #define MAXIMUM_BYTES_PER_INDEX		4096
484534a70bSKonstantin Komarov #define NTFS_BLOCKS_PER_INODE		(MAXIMUM_BYTES_PER_INDEX / 512)
494534a70bSKonstantin Komarov 
50e8b8e97fSKari Argillander /* NTFS specific error code when fixup failed. */
514534a70bSKonstantin Komarov #define E_NTFS_FIXUP			555
52e8b8e97fSKari Argillander /* NTFS specific error code about resident->nonresident. */
534534a70bSKonstantin Komarov #define E_NTFS_NONRESIDENT		556
54e8b8e97fSKari Argillander /* NTFS specific error code about punch hole. */
554534a70bSKonstantin Komarov #define E_NTFS_NOTALIGNED		557
564534a70bSKonstantin Komarov 
574534a70bSKonstantin Komarov 
584534a70bSKonstantin Komarov /* sbi->flags */
594534a70bSKonstantin Komarov #define NTFS_FLAGS_NODISCARD		0x00000001
60e8b8e97fSKari Argillander /* Set when LogFile is replaying. */
614534a70bSKonstantin Komarov #define NTFS_FLAGS_LOG_REPLAYING	0x00000008
62e8b8e97fSKari Argillander /* Set when we changed first MFT's which copy must be updated in $MftMirr. */
634534a70bSKonstantin Komarov #define NTFS_FLAGS_MFTMIRR		0x00001000
644534a70bSKonstantin Komarov #define NTFS_FLAGS_NEED_REPLAY		0x04000000
654534a70bSKonstantin Komarov 
664534a70bSKonstantin Komarov 
674534a70bSKonstantin Komarov /* ni->ni_flags */
684534a70bSKonstantin Komarov /*
69e8b8e97fSKari Argillander  * Data attribute is external compressed (LZX/Xpress)
704534a70bSKonstantin Komarov  * 1 - WOF_COMPRESSION_XPRESS4K
714534a70bSKonstantin Komarov  * 2 - WOF_COMPRESSION_XPRESS8K
724534a70bSKonstantin Komarov  * 3 - WOF_COMPRESSION_XPRESS16K
734534a70bSKonstantin Komarov  * 4 - WOF_COMPRESSION_LZX32K
744534a70bSKonstantin Komarov  */
754534a70bSKonstantin Komarov #define NI_FLAG_COMPRESSED_MASK		0x0000000f
76e8b8e97fSKari Argillander /* Data attribute is deduplicated. */
774534a70bSKonstantin Komarov #define NI_FLAG_DEDUPLICATED		0x00000010
784534a70bSKonstantin Komarov #define NI_FLAG_EA			0x00000020
794534a70bSKonstantin Komarov #define NI_FLAG_DIR			0x00000040
804534a70bSKonstantin Komarov #define NI_FLAG_RESIDENT		0x00000080
814534a70bSKonstantin Komarov #define NI_FLAG_UPDATE_PARENT		0x00000100
824534a70bSKonstantin Komarov // clang-format on
834534a70bSKonstantin Komarov 
844534a70bSKonstantin Komarov struct ntfs_mount_options {
85610f8f5aSKari Argillander 	char *nls_name;
864534a70bSKonstantin Komarov 	struct nls_table *nls;
874534a70bSKonstantin Komarov 
884534a70bSKonstantin Komarov 	kuid_t fs_uid;
894534a70bSKonstantin Komarov 	kgid_t fs_gid;
904534a70bSKonstantin Komarov 	u16 fs_fmask_inv;
914534a70bSKonstantin Komarov 	u16 fs_dmask_inv;
924534a70bSKonstantin Komarov 
9315b2ae77SKari Argillander 	unsigned fmask : 1; /* fmask was set. */
9415b2ae77SKari Argillander 	unsigned dmask : 1; /*dmask was set. */
9515b2ae77SKari Argillander 	unsigned sys_immutable : 1; /* Immutable system files. */
9615b2ae77SKari Argillander 	unsigned discard : 1; /* Issue discard requests on deletions. */
9715b2ae77SKari Argillander 	unsigned sparse : 1; /* Create sparse files. */
9815b2ae77SKari Argillander 	unsigned showmeta : 1; /* Show meta files. */
9915b2ae77SKari Argillander 	unsigned nohidden : 1; /* Do not show hidden files. */
100098250dbSKonstantin Komarov 	unsigned hide_dot_files : 1; /* Set hidden flag on dot files. */
1011d07a9dfSDaniel Pinto 	unsigned windows_names : 1; /* Disallow names forbidden by Windows. */
10215b2ae77SKari Argillander 	unsigned force : 1; /* RW mount dirty volume. */
10315b2ae77SKari Argillander 	unsigned noacsrules : 1; /* Exclude acs rules. */
10415b2ae77SKari Argillander 	unsigned prealloc : 1; /* Preallocate space when file is growing. */
105a3a956c7SKonstantin Komarov 	unsigned nocase : 1; /* case insensitive. */
1064534a70bSKonstantin Komarov };
1074534a70bSKonstantin Komarov 
108e8b8e97fSKari Argillander /* Special value to unpack and deallocate. */
1094534a70bSKonstantin Komarov #define RUN_DEALLOCATE ((struct runs_tree *)(size_t)1)
1104534a70bSKonstantin Komarov 
111e8b8e97fSKari Argillander /* TODO: Use rb tree instead of array. */
1124534a70bSKonstantin Komarov struct runs_tree {
1134534a70bSKonstantin Komarov 	struct ntfs_run *runs;
114e8b8e97fSKari Argillander 	size_t count; /* Currently used size a ntfs_run storage. */
115e8b8e97fSKari Argillander 	size_t allocated; /* Currently allocated ntfs_run storage size. */
1164534a70bSKonstantin Komarov };
1174534a70bSKonstantin Komarov 
1184534a70bSKonstantin Komarov struct ntfs_buffers {
1194534a70bSKonstantin Komarov 	/* Biggest MFT / smallest cluster = 4096 / 512 = 8 */
1204534a70bSKonstantin Komarov 	/* Biggest index / smallest cluster = 4096 / 512 = 8 */
1214534a70bSKonstantin Komarov 	struct buffer_head *bh[PAGE_SIZE >> SECTOR_SHIFT];
1224534a70bSKonstantin Komarov 	u32 bytes;
1234534a70bSKonstantin Komarov 	u32 nbufs;
1244534a70bSKonstantin Komarov 	u32 off;
1254534a70bSKonstantin Komarov };
1264534a70bSKonstantin Komarov 
1274534a70bSKonstantin Komarov enum ALLOCATE_OPT {
128e8b8e97fSKari Argillander 	ALLOCATE_DEF = 0, // Allocate all clusters.
129e8b8e97fSKari Argillander 	ALLOCATE_MFT = 1, // Allocate for MFT.
130c380b52fSKonstantin Komarov 	ALLOCATE_ZERO = 2, // Zeroout new allocated clusters
1314534a70bSKonstantin Komarov };
1324534a70bSKonstantin Komarov 
1334534a70bSKonstantin Komarov enum bitmap_mutex_classes {
1344534a70bSKonstantin Komarov 	BITMAP_MUTEX_CLUSTERS = 0,
1354534a70bSKonstantin Komarov 	BITMAP_MUTEX_MFT = 1,
1364534a70bSKonstantin Komarov };
1374534a70bSKonstantin Komarov 
1384534a70bSKonstantin Komarov struct wnd_bitmap {
1394534a70bSKonstantin Komarov 	struct super_block *sb;
1404534a70bSKonstantin Komarov 	struct rw_semaphore rw_lock;
1414534a70bSKonstantin Komarov 
1424534a70bSKonstantin Komarov 	struct runs_tree run;
1434534a70bSKonstantin Komarov 	size_t nbits;
1444534a70bSKonstantin Komarov 
145e8b8e97fSKari Argillander 	size_t total_zeroes; // Total number of free bits.
146e8b8e97fSKari Argillander 	u16 *free_bits; // Free bits in each window.
1474534a70bSKonstantin Komarov 	size_t nwnd;
148e8b8e97fSKari Argillander 	u32 bits_last; // Bits in last window.
1494534a70bSKonstantin Komarov 
150e8b8e97fSKari Argillander 	struct rb_root start_tree; // Extents, sorted by 'start'.
151e8b8e97fSKari Argillander 	struct rb_root count_tree; // Extents, sorted by 'count + start'.
152e8b8e97fSKari Argillander 	size_t count; // Extents count.
1534534a70bSKonstantin Komarov 
1544534a70bSKonstantin Komarov 	/*
155e8b8e97fSKari Argillander 	 * -1 Tree is activated but not updated (too many fragments).
156e8b8e97fSKari Argillander 	 * 0 - Tree is not activated.
157e8b8e97fSKari Argillander 	 * 1 - Tree is activated and updated.
1584534a70bSKonstantin Komarov 	 */
1594534a70bSKonstantin Komarov 	int uptodated;
160e8b8e97fSKari Argillander 	size_t extent_min; // Minimal extent used while building.
161e8b8e97fSKari Argillander 	size_t extent_max; // Upper estimate of biggest free block.
1624534a70bSKonstantin Komarov 
1634534a70bSKonstantin Komarov 	/* Zone [bit, end) */
1644534a70bSKonstantin Komarov 	size_t zone_bit;
1654534a70bSKonstantin Komarov 	size_t zone_end;
1664534a70bSKonstantin Komarov 
167e8b8e97fSKari Argillander 	bool set_tail; // Not necessary in driver.
1684534a70bSKonstantin Komarov 	bool inited;
1694534a70bSKonstantin Komarov };
1704534a70bSKonstantin Komarov 
1714534a70bSKonstantin Komarov typedef int (*NTFS_CMP_FUNC)(const void *key1, size_t len1, const void *key2,
1724534a70bSKonstantin Komarov 			     size_t len2, const void *param);
1734534a70bSKonstantin Komarov 
1744534a70bSKonstantin Komarov enum index_mutex_classed {
1754534a70bSKonstantin Komarov 	INDEX_MUTEX_I30 = 0,
1764534a70bSKonstantin Komarov 	INDEX_MUTEX_SII = 1,
1774534a70bSKonstantin Komarov 	INDEX_MUTEX_SDH = 2,
1784534a70bSKonstantin Komarov 	INDEX_MUTEX_SO = 3,
1794534a70bSKonstantin Komarov 	INDEX_MUTEX_SQ = 4,
1804534a70bSKonstantin Komarov 	INDEX_MUTEX_SR = 5,
1814534a70bSKonstantin Komarov 	INDEX_MUTEX_TOTAL
1824534a70bSKonstantin Komarov };
1834534a70bSKonstantin Komarov 
184e8b8e97fSKari Argillander /* ntfs_index - Allocation unit inside directory. */
1854534a70bSKonstantin Komarov struct ntfs_index {
1864534a70bSKonstantin Komarov 	struct runs_tree bitmap_run;
1874534a70bSKonstantin Komarov 	struct runs_tree alloc_run;
1884534a70bSKonstantin Komarov 	/* read/write access to 'bitmap_run'/'alloc_run' while ntfs_readdir */
1894534a70bSKonstantin Komarov 	struct rw_semaphore run_lock;
1904534a70bSKonstantin Komarov 
191e8b8e97fSKari Argillander 	/*TODO: Remove 'cmp'. */
1924534a70bSKonstantin Komarov 	NTFS_CMP_FUNC cmp;
1934534a70bSKonstantin Komarov 
1944534a70bSKonstantin Komarov 	u8 index_bits; // log2(root->index_block_size)
1954534a70bSKonstantin Komarov 	u8 idx2vbn_bits; // log2(root->index_block_clst)
1964534a70bSKonstantin Komarov 	u8 vbn2vbo_bits; // index_block_size < cluster? 9 : cluster_bits
1974534a70bSKonstantin Komarov 	u8 type; // index_mutex_classed
1984534a70bSKonstantin Komarov };
1994534a70bSKonstantin Komarov 
200e8b8e97fSKari Argillander /* Minimum MFT zone. */
2014534a70bSKonstantin Komarov #define NTFS_MIN_MFT_ZONE 100
2024534a70bSKonstantin Komarov 
203e8b8e97fSKari Argillander /* Ntfs file system in-core superblock data. */
2044534a70bSKonstantin Komarov struct ntfs_sb_info {
2054534a70bSKonstantin Komarov 	struct super_block *sb;
2064534a70bSKonstantin Komarov 
2074534a70bSKonstantin Komarov 	u32 discard_granularity;
2084534a70bSKonstantin Komarov 	u64 discard_granularity_mask_inv; // ~(discard_granularity_mask_inv-1)
2094534a70bSKonstantin Komarov 
2104534a70bSKonstantin Komarov 	u32 cluster_size; // bytes per cluster
2114534a70bSKonstantin Komarov 	u32 cluster_mask; // == cluster_size - 1
2124534a70bSKonstantin Komarov 	u64 cluster_mask_inv; // ~(cluster_size - 1)
2134534a70bSKonstantin Komarov 	u32 block_mask; // sb->s_blocksize - 1
2144534a70bSKonstantin Komarov 	u32 blocks_per_cluster; // cluster_size / sb->s_blocksize
2154534a70bSKonstantin Komarov 
2164534a70bSKonstantin Komarov 	u32 record_size;
2174534a70bSKonstantin Komarov 	u32 index_size;
2184534a70bSKonstantin Komarov 
2194534a70bSKonstantin Komarov 	u8 cluster_bits;
2204534a70bSKonstantin Komarov 	u8 record_bits;
2214534a70bSKonstantin Komarov 
222e8b8e97fSKari Argillander 	u64 maxbytes; // Maximum size for normal files.
223e8b8e97fSKari Argillander 	u64 maxbytes_sparse; // Maximum size for sparse file.
2244534a70bSKonstantin Komarov 
225e8b8e97fSKari Argillander 	u32 flags; // See NTFS_FLAGS_XXX.
2264534a70bSKonstantin Komarov 
2278335ebe1SKonstantin Komarov 	CLST zone_max; // Maximum MFT zone length in clusters
228e8b8e97fSKari Argillander 	CLST bad_clusters; // The count of marked bad clusters.
2294534a70bSKonstantin Komarov 
230e8b8e97fSKari Argillander 	u16 max_bytes_per_attr; // Maximum attribute size in record.
231e8b8e97fSKari Argillander 	u16 attr_size_tr; // Attribute size threshold (320 bytes).
2324534a70bSKonstantin Komarov 
233e8b8e97fSKari Argillander 	/* Records in $Extend. */
2344534a70bSKonstantin Komarov 	CLST objid_no;
2354534a70bSKonstantin Komarov 	CLST quota_no;
2364534a70bSKonstantin Komarov 	CLST reparse_no;
2374534a70bSKonstantin Komarov 	CLST usn_jrnl_no;
2384534a70bSKonstantin Komarov 
239e8b8e97fSKari Argillander 	struct ATTR_DEF_ENTRY *def_table; // Attribute definition table.
2404534a70bSKonstantin Komarov 	u32 def_entries;
2414534a70bSKonstantin Komarov 	u32 ea_max_size;
2424534a70bSKonstantin Komarov 
2434534a70bSKonstantin Komarov 	struct MFT_REC *new_rec;
2444534a70bSKonstantin Komarov 
2454534a70bSKonstantin Komarov 	u16 *upcase;
2464534a70bSKonstantin Komarov 
2474534a70bSKonstantin Komarov 	struct {
2484534a70bSKonstantin Komarov 		u64 lbo, lbo2;
2494534a70bSKonstantin Komarov 		struct ntfs_inode *ni;
2504534a70bSKonstantin Komarov 		struct wnd_bitmap bitmap; // $MFT::Bitmap
2514534a70bSKonstantin Komarov 		/*
252e8b8e97fSKari Argillander 		 * MFT records [11-24) used to expand MFT itself.
2534534a70bSKonstantin Komarov 		 * They always marked as used in $MFT::Bitmap
254e8b8e97fSKari Argillander 		 * 'reserved_bitmap' contains real bitmap of these records.
2554534a70bSKonstantin Komarov 		 */
256e8b8e97fSKari Argillander 		ulong reserved_bitmap; // Bitmap of used records [11 - 24)
2574534a70bSKonstantin Komarov 		size_t next_free; // The next record to allocate from
258e8b8e97fSKari Argillander 		size_t used; // MFT valid size in records.
2594534a70bSKonstantin Komarov 		u32 recs_mirr; // Number of records in MFTMirr
2604534a70bSKonstantin Komarov 		u8 next_reserved;
2614534a70bSKonstantin Komarov 		u8 reserved_bitmap_inited;
2624534a70bSKonstantin Komarov 	} mft;
2634534a70bSKonstantin Komarov 
2644534a70bSKonstantin Komarov 	struct {
2654534a70bSKonstantin Komarov 		struct wnd_bitmap bitmap; // $Bitmap::Data
2664534a70bSKonstantin Komarov 		CLST next_free_lcn;
2674534a70bSKonstantin Komarov 	} used;
2684534a70bSKonstantin Komarov 
2694534a70bSKonstantin Komarov 	struct {
270e8b8e97fSKari Argillander 		u64 size; // In bytes.
271e8b8e97fSKari Argillander 		u64 blocks; // In blocks.
2724534a70bSKonstantin Komarov 		u64 ser_num;
2734534a70bSKonstantin Komarov 		struct ntfs_inode *ni;
274e8b8e97fSKari Argillander 		__le16 flags; // Cached current VOLUME_INFO::flags, VOLUME_FLAG_DIRTY.
2754534a70bSKonstantin Komarov 		u8 major_ver;
2764534a70bSKonstantin Komarov 		u8 minor_ver;
2774534a70bSKonstantin Komarov 		char label[65];
278e8b8e97fSKari Argillander 		bool real_dirty; // Real fs state.
2794534a70bSKonstantin Komarov 	} volume;
2804534a70bSKonstantin Komarov 
2814534a70bSKonstantin Komarov 	struct {
2824534a70bSKonstantin Komarov 		struct ntfs_index index_sii;
2834534a70bSKonstantin Komarov 		struct ntfs_index index_sdh;
2844534a70bSKonstantin Komarov 		struct ntfs_inode *ni;
2854534a70bSKonstantin Komarov 		u32 next_id;
2864534a70bSKonstantin Komarov 		u64 next_off;
2874534a70bSKonstantin Komarov 
2884534a70bSKonstantin Komarov 		__le32 def_security_id;
2894534a70bSKonstantin Komarov 	} security;
2904534a70bSKonstantin Komarov 
2914534a70bSKonstantin Komarov 	struct {
2924534a70bSKonstantin Komarov 		struct ntfs_index index_r;
2934534a70bSKonstantin Komarov 		struct ntfs_inode *ni;
2944534a70bSKonstantin Komarov 		u64 max_size; // 16K
2954534a70bSKonstantin Komarov 	} reparse;
2964534a70bSKonstantin Komarov 
2974534a70bSKonstantin Komarov 	struct {
2984534a70bSKonstantin Komarov 		struct ntfs_index index_o;
2994534a70bSKonstantin Komarov 		struct ntfs_inode *ni;
3004534a70bSKonstantin Komarov 	} objid;
3014534a70bSKonstantin Komarov 
3024534a70bSKonstantin Komarov 	struct {
3034534a70bSKonstantin Komarov 		struct mutex mtx_lznt;
3044534a70bSKonstantin Komarov 		struct lznt *lznt;
3054534a70bSKonstantin Komarov #ifdef CONFIG_NTFS3_LZX_XPRESS
3064534a70bSKonstantin Komarov 		struct mutex mtx_xpress;
3074534a70bSKonstantin Komarov 		struct xpress_decompressor *xpress;
3084534a70bSKonstantin Komarov 		struct mutex mtx_lzx;
3094534a70bSKonstantin Komarov 		struct lzx_decompressor *lzx;
3104534a70bSKonstantin Komarov #endif
3114534a70bSKonstantin Komarov 	} compress;
3124534a70bSKonstantin Komarov 
313564c97bdSKari Argillander 	struct ntfs_mount_options *options;
3144534a70bSKonstantin Komarov 	struct ratelimit_state msg_ratelimit;
3154534a70bSKonstantin Komarov };
3164534a70bSKonstantin Komarov 
317e8b8e97fSKari Argillander /* One MFT record(usually 1024 bytes), consists of attributes. */
3184534a70bSKonstantin Komarov struct mft_inode {
3194534a70bSKonstantin Komarov 	struct rb_node node;
3204534a70bSKonstantin Komarov 	struct ntfs_sb_info *sbi;
3214534a70bSKonstantin Komarov 
3224534a70bSKonstantin Komarov 	struct MFT_REC *mrec;
3234534a70bSKonstantin Komarov 	struct ntfs_buffers nb;
3244534a70bSKonstantin Komarov 
3254534a70bSKonstantin Komarov 	CLST rno;
3264534a70bSKonstantin Komarov 	bool dirty;
3274534a70bSKonstantin Komarov };
3284534a70bSKonstantin Komarov 
329e8b8e97fSKari Argillander /* Nested class for ntfs_inode::ni_lock. */
3304534a70bSKonstantin Komarov enum ntfs_inode_mutex_lock_class {
3314534a70bSKonstantin Komarov 	NTFS_INODE_MUTEX_DIRTY,
3324534a70bSKonstantin Komarov 	NTFS_INODE_MUTEX_SECURITY,
3334534a70bSKonstantin Komarov 	NTFS_INODE_MUTEX_OBJID,
3344534a70bSKonstantin Komarov 	NTFS_INODE_MUTEX_REPARSE,
3354534a70bSKonstantin Komarov 	NTFS_INODE_MUTEX_NORMAL,
3364534a70bSKonstantin Komarov 	NTFS_INODE_MUTEX_PARENT,
337*0ad9dfcbSKonstantin Komarov 	NTFS_INODE_MUTEX_PARENT2,
3384534a70bSKonstantin Komarov };
3394534a70bSKonstantin Komarov 
3404534a70bSKonstantin Komarov /*
341e8b8e97fSKari Argillander  * sturct ntfs_inode
342e8b8e97fSKari Argillander  *
343e8b8e97fSKari Argillander  * Ntfs inode - extends linux inode. consists of one or more MFT inodes.
3444534a70bSKonstantin Komarov  */
3454534a70bSKonstantin Komarov struct ntfs_inode {
3464534a70bSKonstantin Komarov 	struct mft_inode mi; // base record
3474534a70bSKonstantin Komarov 
3484534a70bSKonstantin Komarov 	/*
349e8b8e97fSKari Argillander 	 * Valid size: [0 - i_valid) - these range in file contains valid data.
350e8b8e97fSKari Argillander 	 * Range [i_valid - inode->i_size) - contains 0.
351e8b8e97fSKari Argillander 	 * Usually i_valid <= inode->i_size.
3524534a70bSKonstantin Komarov 	 */
3534534a70bSKonstantin Komarov 	u64 i_valid;
3544534a70bSKonstantin Komarov 	struct timespec64 i_crtime;
3554534a70bSKonstantin Komarov 
3564534a70bSKonstantin Komarov 	struct mutex ni_lock;
3574534a70bSKonstantin Komarov 
358e8b8e97fSKari Argillander 	/* File attributes from std. */
3594534a70bSKonstantin Komarov 	enum FILE_ATTRIBUTE std_fa;
3604534a70bSKonstantin Komarov 	__le32 std_security_id;
3614534a70bSKonstantin Komarov 
3624534a70bSKonstantin Komarov 	/*
363e8b8e97fSKari Argillander 	 * Tree of mft_inode.
364e8b8e97fSKari Argillander 	 * Not empty when primary MFT record (usually 1024 bytes) can't save all attributes
365e8b8e97fSKari Argillander 	 * e.g. file becomes too fragmented or contains a lot of names.
3664534a70bSKonstantin Komarov 	 */
3674534a70bSKonstantin Komarov 	struct rb_root mi_tree;
3684534a70bSKonstantin Komarov 
3694534a70bSKonstantin Komarov 	/*
3704534a70bSKonstantin Komarov 	 * This member is used in ntfs_readdir to ensure that all subrecords are loaded
3714534a70bSKonstantin Komarov 	 */
3724534a70bSKonstantin Komarov 	u8 mi_loaded;
3734534a70bSKonstantin Komarov 
3744534a70bSKonstantin Komarov 	union {
3754534a70bSKonstantin Komarov 		struct ntfs_index dir;
3764534a70bSKonstantin Komarov 		struct {
3774534a70bSKonstantin Komarov 			struct rw_semaphore run_lock;
3784534a70bSKonstantin Komarov 			struct runs_tree run;
3794534a70bSKonstantin Komarov #ifdef CONFIG_NTFS3_LZX_XPRESS
3804534a70bSKonstantin Komarov 			struct page *offs_page;
3814534a70bSKonstantin Komarov #endif
3824534a70bSKonstantin Komarov 		} file;
3834534a70bSKonstantin Komarov 	};
3844534a70bSKonstantin Komarov 
3854534a70bSKonstantin Komarov 	struct {
3864534a70bSKonstantin Komarov 		struct runs_tree run;
387e8b8e97fSKari Argillander 		struct ATTR_LIST_ENTRY *le; // 1K aligned memory.
3884534a70bSKonstantin Komarov 		size_t size;
3894534a70bSKonstantin Komarov 		bool dirty;
3904534a70bSKonstantin Komarov 	} attr_list;
3914534a70bSKonstantin Komarov 
3924534a70bSKonstantin Komarov 	size_t ni_flags; // NI_FLAG_XXX
3934534a70bSKonstantin Komarov 
3944534a70bSKonstantin Komarov 	struct inode vfs_inode;
3954534a70bSKonstantin Komarov };
3964534a70bSKonstantin Komarov 
3974534a70bSKonstantin Komarov struct indx_node {
3984534a70bSKonstantin Komarov 	struct ntfs_buffers nb;
3994534a70bSKonstantin Komarov 	struct INDEX_BUFFER *index;
4004534a70bSKonstantin Komarov };
4014534a70bSKonstantin Komarov 
4024534a70bSKonstantin Komarov struct ntfs_fnd {
4034534a70bSKonstantin Komarov 	int level;
4044534a70bSKonstantin Komarov 	struct indx_node *nodes[20];
4054534a70bSKonstantin Komarov 	struct NTFS_DE *de[20];
4064534a70bSKonstantin Komarov 	struct NTFS_DE *root_de;
4074534a70bSKonstantin Komarov };
4084534a70bSKonstantin Komarov 
4094534a70bSKonstantin Komarov enum REPARSE_SIGN {
4104534a70bSKonstantin Komarov 	REPARSE_NONE = 0,
4114534a70bSKonstantin Komarov 	REPARSE_COMPRESSED = 1,
4124534a70bSKonstantin Komarov 	REPARSE_DEDUPLICATED = 2,
4134534a70bSKonstantin Komarov 	REPARSE_LINK = 3
4144534a70bSKonstantin Komarov };
4154534a70bSKonstantin Komarov 
416e8b8e97fSKari Argillander /* Functions from attrib.c */
4174534a70bSKonstantin Komarov int attr_allocate_clusters(struct ntfs_sb_info *sbi, struct runs_tree *run,
4184534a70bSKonstantin Komarov 			   CLST vcn, CLST lcn, CLST len, CLST *pre_alloc,
4194534a70bSKonstantin Komarov 			   enum ALLOCATE_OPT opt, CLST *alen, const size_t fr,
420c380b52fSKonstantin Komarov 			   CLST *new_lcn, CLST *new_len);
4214534a70bSKonstantin Komarov int attr_make_nonresident(struct ntfs_inode *ni, struct ATTRIB *attr,
4224534a70bSKonstantin Komarov 			  struct ATTR_LIST_ENTRY *le, struct mft_inode *mi,
4234534a70bSKonstantin Komarov 			  u64 new_size, struct runs_tree *run,
4244534a70bSKonstantin Komarov 			  struct ATTRIB **ins_attr, struct page *page);
4254534a70bSKonstantin Komarov int attr_set_size(struct ntfs_inode *ni, enum ATTR_TYPE type,
4264534a70bSKonstantin Komarov 		  const __le16 *name, u8 name_len, struct runs_tree *run,
4274534a70bSKonstantin Komarov 		  u64 new_size, const u64 *new_valid, bool keep_prealloc,
4284534a70bSKonstantin Komarov 		  struct ATTRIB **ret);
4294534a70bSKonstantin Komarov int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
430c380b52fSKonstantin Komarov 			CLST *len, bool *new, bool zero);
4314534a70bSKonstantin Komarov int attr_data_read_resident(struct ntfs_inode *ni, struct page *page);
4324534a70bSKonstantin Komarov int attr_data_write_resident(struct ntfs_inode *ni, struct page *page);
4334534a70bSKonstantin Komarov int attr_load_runs_vcn(struct ntfs_inode *ni, enum ATTR_TYPE type,
4344534a70bSKonstantin Komarov 		       const __le16 *name, u8 name_len, struct runs_tree *run,
4354534a70bSKonstantin Komarov 		       CLST vcn);
4364534a70bSKonstantin Komarov int attr_load_runs_range(struct ntfs_inode *ni, enum ATTR_TYPE type,
4374534a70bSKonstantin Komarov 			 const __le16 *name, u8 name_len, struct runs_tree *run,
4384534a70bSKonstantin Komarov 			 u64 from, u64 to);
4394534a70bSKonstantin Komarov int attr_wof_frame_info(struct ntfs_inode *ni, struct ATTRIB *attr,
4404534a70bSKonstantin Komarov 			struct runs_tree *run, u64 frame, u64 frames,
4414534a70bSKonstantin Komarov 			u8 frame_bits, u32 *ondisk_size, u64 *vbo_data);
4424534a70bSKonstantin Komarov int attr_is_frame_compressed(struct ntfs_inode *ni, struct ATTRIB *attr,
4434534a70bSKonstantin Komarov 			     CLST frame, CLST *clst_data);
4444534a70bSKonstantin Komarov int attr_allocate_frame(struct ntfs_inode *ni, CLST frame, size_t compr_size,
4454534a70bSKonstantin Komarov 			u64 new_valid);
4464534a70bSKonstantin Komarov int attr_collapse_range(struct ntfs_inode *ni, u64 vbo, u64 bytes);
447aa30eccbSKonstantin Komarov int attr_insert_range(struct ntfs_inode *ni, u64 vbo, u64 bytes);
4484534a70bSKonstantin Komarov int attr_punch_hole(struct ntfs_inode *ni, u64 vbo, u64 bytes, u32 *frame_size);
4494534a70bSKonstantin Komarov 
450e8b8e97fSKari Argillander /* Functions from attrlist.c */
4514534a70bSKonstantin Komarov void al_destroy(struct ntfs_inode *ni);
4524534a70bSKonstantin Komarov bool al_verify(struct ntfs_inode *ni);
4534534a70bSKonstantin Komarov int ntfs_load_attr_list(struct ntfs_inode *ni, struct ATTRIB *attr);
4544534a70bSKonstantin Komarov struct ATTR_LIST_ENTRY *al_enumerate(struct ntfs_inode *ni,
4554534a70bSKonstantin Komarov 				     struct ATTR_LIST_ENTRY *le);
4564534a70bSKonstantin Komarov struct ATTR_LIST_ENTRY *al_find_le(struct ntfs_inode *ni,
4574534a70bSKonstantin Komarov 				   struct ATTR_LIST_ENTRY *le,
4584534a70bSKonstantin Komarov 				   const struct ATTRIB *attr);
4594534a70bSKonstantin Komarov struct ATTR_LIST_ENTRY *al_find_ex(struct ntfs_inode *ni,
4604534a70bSKonstantin Komarov 				   struct ATTR_LIST_ENTRY *le,
4614534a70bSKonstantin Komarov 				   enum ATTR_TYPE type, const __le16 *name,
4624534a70bSKonstantin Komarov 				   u8 name_len, const CLST *vcn);
4634534a70bSKonstantin Komarov int al_add_le(struct ntfs_inode *ni, enum ATTR_TYPE type, const __le16 *name,
4644534a70bSKonstantin Komarov 	      u8 name_len, CLST svcn, __le16 id, const struct MFT_REF *ref,
4654534a70bSKonstantin Komarov 	      struct ATTR_LIST_ENTRY **new_le);
4664534a70bSKonstantin Komarov bool al_remove_le(struct ntfs_inode *ni, struct ATTR_LIST_ENTRY *le);
4674534a70bSKonstantin Komarov bool al_delete_le(struct ntfs_inode *ni, enum ATTR_TYPE type, CLST vcn,
4684534a70bSKonstantin Komarov 		  const __le16 *name, size_t name_len,
4694534a70bSKonstantin Komarov 		  const struct MFT_REF *ref);
47063544672SKonstantin Komarov int al_update(struct ntfs_inode *ni, int sync);
4714534a70bSKonstantin Komarov static inline size_t al_aligned(size_t size)
4724534a70bSKonstantin Komarov {
4734534a70bSKonstantin Komarov 	return (size + 1023) & ~(size_t)1023;
4744534a70bSKonstantin Komarov }
4754534a70bSKonstantin Komarov 
476e8b8e97fSKari Argillander /* Globals from bitfunc.c */
47708811ba5SKonstantin Komarov bool are_bits_clear(const void *map, size_t bit, size_t nbits);
47808811ba5SKonstantin Komarov bool are_bits_set(const void *map, size_t bit, size_t nbits);
47908811ba5SKonstantin Komarov size_t get_set_bits_ex(const void *map, size_t bit, size_t nbits);
4804534a70bSKonstantin Komarov 
481e8b8e97fSKari Argillander /* Globals from dir.c */
4822c690788SKonstantin Komarov int ntfs_utf16_to_nls(struct ntfs_sb_info *sbi, const __le16 *name, u32 len,
4834534a70bSKonstantin Komarov 		      u8 *buf, int buf_len);
4844534a70bSKonstantin Komarov int ntfs_nls_to_utf16(struct ntfs_sb_info *sbi, const u8 *name, u32 name_len,
4854534a70bSKonstantin Komarov 		      struct cpu_str *uni, u32 max_ulen,
4864534a70bSKonstantin Komarov 		      enum utf16_endian endian);
4874534a70bSKonstantin Komarov struct inode *dir_search_u(struct inode *dir, const struct cpu_str *uni,
4884534a70bSKonstantin Komarov 			   struct ntfs_fnd *fnd);
4894534a70bSKonstantin Komarov bool dir_is_empty(struct inode *dir);
4904534a70bSKonstantin Komarov extern const struct file_operations ntfs_dir_operations;
4914534a70bSKonstantin Komarov 
492e8b8e97fSKari Argillander /* Globals from file.c */
4934534a70bSKonstantin Komarov int ntfs_getattr(struct user_namespace *mnt_userns, const struct path *path,
4944534a70bSKonstantin Komarov 		 struct kstat *stat, u32 request_mask, u32 flags);
4954534a70bSKonstantin Komarov int ntfs3_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
4964534a70bSKonstantin Komarov 		  struct iattr *attr);
4974534a70bSKonstantin Komarov int ntfs_file_open(struct inode *inode, struct file *file);
4984534a70bSKonstantin Komarov int ntfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
4994534a70bSKonstantin Komarov 		__u64 start, __u64 len);
5004534a70bSKonstantin Komarov extern const struct inode_operations ntfs_special_inode_operations;
5014534a70bSKonstantin Komarov extern const struct inode_operations ntfs_file_inode_operations;
5024534a70bSKonstantin Komarov extern const struct file_operations ntfs_file_operations;
5034534a70bSKonstantin Komarov 
504e8b8e97fSKari Argillander /* Globals from frecord.c */
5054534a70bSKonstantin Komarov void ni_remove_mi(struct ntfs_inode *ni, struct mft_inode *mi);
5064534a70bSKonstantin Komarov struct ATTR_STD_INFO *ni_std(struct ntfs_inode *ni);
5074534a70bSKonstantin Komarov struct ATTR_STD_INFO5 *ni_std5(struct ntfs_inode *ni);
5084534a70bSKonstantin Komarov void ni_clear(struct ntfs_inode *ni);
5094534a70bSKonstantin Komarov int ni_load_mi_ex(struct ntfs_inode *ni, CLST rno, struct mft_inode **mi);
51078ab59feSKonstantin Komarov int ni_load_mi(struct ntfs_inode *ni, const struct ATTR_LIST_ENTRY *le,
5114534a70bSKonstantin Komarov 	       struct mft_inode **mi);
5124534a70bSKonstantin Komarov struct ATTRIB *ni_find_attr(struct ntfs_inode *ni, struct ATTRIB *attr,
5134534a70bSKonstantin Komarov 			    struct ATTR_LIST_ENTRY **entry_o,
5144534a70bSKonstantin Komarov 			    enum ATTR_TYPE type, const __le16 *name,
5154534a70bSKonstantin Komarov 			    u8 name_len, const CLST *vcn,
5164534a70bSKonstantin Komarov 			    struct mft_inode **mi);
5174534a70bSKonstantin Komarov struct ATTRIB *ni_enum_attr_ex(struct ntfs_inode *ni, struct ATTRIB *attr,
5184534a70bSKonstantin Komarov 			       struct ATTR_LIST_ENTRY **le,
5194534a70bSKonstantin Komarov 			       struct mft_inode **mi);
5204534a70bSKonstantin Komarov struct ATTRIB *ni_load_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
5214534a70bSKonstantin Komarov 			    const __le16 *name, u8 name_len, CLST vcn,
5224534a70bSKonstantin Komarov 			    struct mft_inode **pmi);
5234534a70bSKonstantin Komarov int ni_load_all_mi(struct ntfs_inode *ni);
5244534a70bSKonstantin Komarov bool ni_add_subrecord(struct ntfs_inode *ni, CLST rno, struct mft_inode **mi);
5254534a70bSKonstantin Komarov int ni_remove_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
5264534a70bSKonstantin Komarov 		   const __le16 *name, size_t name_len, bool base_only,
5274534a70bSKonstantin Komarov 		   const __le16 *id);
5284534a70bSKonstantin Komarov int ni_create_attr_list(struct ntfs_inode *ni);
5294534a70bSKonstantin Komarov int ni_expand_list(struct ntfs_inode *ni);
5304534a70bSKonstantin Komarov int ni_insert_nonresident(struct ntfs_inode *ni, enum ATTR_TYPE type,
5314534a70bSKonstantin Komarov 			  const __le16 *name, u8 name_len,
5324534a70bSKonstantin Komarov 			  const struct runs_tree *run, CLST svcn, CLST len,
5334534a70bSKonstantin Komarov 			  __le16 flags, struct ATTRIB **new_attr,
534c1e0ab37SKonstantin Komarov 			  struct mft_inode **mi, struct ATTR_LIST_ENTRY **le);
5354534a70bSKonstantin Komarov int ni_insert_resident(struct ntfs_inode *ni, u32 data_size,
5364534a70bSKonstantin Komarov 		       enum ATTR_TYPE type, const __le16 *name, u8 name_len,
53778ab59feSKonstantin Komarov 		       struct ATTRIB **new_attr, struct mft_inode **mi,
53878ab59feSKonstantin Komarov 		       struct ATTR_LIST_ENTRY **le);
53978ab59feSKonstantin Komarov void ni_remove_attr_le(struct ntfs_inode *ni, struct ATTRIB *attr,
54078ab59feSKonstantin Komarov 		       struct mft_inode *mi, struct ATTR_LIST_ENTRY *le);
5414534a70bSKonstantin Komarov int ni_delete_all(struct ntfs_inode *ni);
5424534a70bSKonstantin Komarov struct ATTR_FILE_NAME *ni_fname_name(struct ntfs_inode *ni,
5434534a70bSKonstantin Komarov 				     const struct cpu_str *uni,
5444534a70bSKonstantin Komarov 				     const struct MFT_REF *home,
54578ab59feSKonstantin Komarov 				     struct mft_inode **mi,
5464534a70bSKonstantin Komarov 				     struct ATTR_LIST_ENTRY **entry);
5474534a70bSKonstantin Komarov struct ATTR_FILE_NAME *ni_fname_type(struct ntfs_inode *ni, u8 name_type,
54878ab59feSKonstantin Komarov 				     struct mft_inode **mi,
5494534a70bSKonstantin Komarov 				     struct ATTR_LIST_ENTRY **entry);
5504534a70bSKonstantin Komarov int ni_new_attr_flags(struct ntfs_inode *ni, enum FILE_ATTRIBUTE new_fa);
5514534a70bSKonstantin Komarov enum REPARSE_SIGN ni_parse_reparse(struct ntfs_inode *ni, struct ATTRIB *attr,
552cd4c76ffSKonstantin Komarov 				   struct REPARSE_DATA_BUFFER *buffer);
5534534a70bSKonstantin Komarov int ni_write_inode(struct inode *inode, int sync, const char *hint);
5544534a70bSKonstantin Komarov #define _ni_write_inode(i, w) ni_write_inode(i, w, __func__)
5554534a70bSKonstantin Komarov int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo,
5564534a70bSKonstantin Komarov 	      __u64 vbo, __u64 len);
5574534a70bSKonstantin Komarov int ni_readpage_cmpr(struct ntfs_inode *ni, struct page *page);
5584534a70bSKonstantin Komarov int ni_decompress_file(struct ntfs_inode *ni);
5594534a70bSKonstantin Komarov int ni_read_frame(struct ntfs_inode *ni, u64 frame_vbo, struct page **pages,
5604534a70bSKonstantin Komarov 		  u32 pages_per_frame);
5614534a70bSKonstantin Komarov int ni_write_frame(struct ntfs_inode *ni, struct page **pages,
5624534a70bSKonstantin Komarov 		   u32 pages_per_frame);
56378ab59feSKonstantin Komarov int ni_remove_name(struct ntfs_inode *dir_ni, struct ntfs_inode *ni,
56478ab59feSKonstantin Komarov 		   struct NTFS_DE *de, struct NTFS_DE **de2, int *undo_step);
56578ab59feSKonstantin Komarov 
56678ab59feSKonstantin Komarov bool ni_remove_name_undo(struct ntfs_inode *dir_ni, struct ntfs_inode *ni,
56778ab59feSKonstantin Komarov 			 struct NTFS_DE *de, struct NTFS_DE *de2,
56878ab59feSKonstantin Komarov 			 int undo_step);
56978ab59feSKonstantin Komarov 
57078ab59feSKonstantin Komarov int ni_add_name(struct ntfs_inode *dir_ni, struct ntfs_inode *ni,
57178ab59feSKonstantin Komarov 		struct NTFS_DE *de);
57278ab59feSKonstantin Komarov 
57378ab59feSKonstantin Komarov int ni_rename(struct ntfs_inode *dir_ni, struct ntfs_inode *new_dir_ni,
57478ab59feSKonstantin Komarov 	      struct ntfs_inode *ni, struct NTFS_DE *de, struct NTFS_DE *new_de,
57578ab59feSKonstantin Komarov 	      bool *is_bad);
57678ab59feSKonstantin Komarov 
57778ab59feSKonstantin Komarov bool ni_is_dirty(struct inode *inode);
5784534a70bSKonstantin Komarov 
579e8b8e97fSKari Argillander /* Globals from fslog.c */
5804534a70bSKonstantin Komarov int log_replay(struct ntfs_inode *ni, bool *initialized);
5814534a70bSKonstantin Komarov 
582e8b8e97fSKari Argillander /* Globals from fsntfs.c */
5834534a70bSKonstantin Komarov bool ntfs_fix_pre_write(struct NTFS_RECORD_HEADER *rhdr, size_t bytes);
5844534a70bSKonstantin Komarov int ntfs_fix_post_read(struct NTFS_RECORD_HEADER *rhdr, size_t bytes,
5854534a70bSKonstantin Komarov 		       bool simple);
5864534a70bSKonstantin Komarov int ntfs_extend_init(struct ntfs_sb_info *sbi);
5874534a70bSKonstantin Komarov int ntfs_loadlog_and_replay(struct ntfs_inode *ni, struct ntfs_sb_info *sbi);
5884534a70bSKonstantin Komarov int ntfs_look_for_free_space(struct ntfs_sb_info *sbi, CLST lcn, CLST len,
5894534a70bSKonstantin Komarov 			     CLST *new_lcn, CLST *new_len,
5904534a70bSKonstantin Komarov 			     enum ALLOCATE_OPT opt);
5914534a70bSKonstantin Komarov int ntfs_look_free_mft(struct ntfs_sb_info *sbi, CLST *rno, bool mft,
5924534a70bSKonstantin Komarov 		       struct ntfs_inode *ni, struct mft_inode **mi);
593071100eaSKonstantin Komarov void ntfs_mark_rec_free(struct ntfs_sb_info *sbi, CLST rno, bool is_mft);
5944534a70bSKonstantin Komarov int ntfs_clear_mft_tail(struct ntfs_sb_info *sbi, size_t from, size_t to);
5954534a70bSKonstantin Komarov int ntfs_refresh_zone(struct ntfs_sb_info *sbi);
596e66af07cSPavel Skripkin void ntfs_update_mftmirr(struct ntfs_sb_info *sbi, int wait);
597c12df45eSKonstantin Komarov void ntfs_bad_inode(struct inode *inode, const char *hint);
598c12df45eSKonstantin Komarov #define _ntfs_bad_inode(i) ntfs_bad_inode(i, __func__)
5994534a70bSKonstantin Komarov enum NTFS_DIRTY_FLAGS {
6004534a70bSKonstantin Komarov 	NTFS_DIRTY_CLEAR = 0,
6014534a70bSKonstantin Komarov 	NTFS_DIRTY_DIRTY = 1,
6024534a70bSKonstantin Komarov 	NTFS_DIRTY_ERROR = 2,
6034534a70bSKonstantin Komarov };
6044534a70bSKonstantin Komarov int ntfs_set_state(struct ntfs_sb_info *sbi, enum NTFS_DIRTY_FLAGS dirty);
6054534a70bSKonstantin Komarov int ntfs_sb_read(struct super_block *sb, u64 lbo, size_t bytes, void *buffer);
6064534a70bSKonstantin Komarov int ntfs_sb_write(struct super_block *sb, u64 lbo, size_t bytes,
6074534a70bSKonstantin Komarov 		  const void *buffer, int wait);
6084534a70bSKonstantin Komarov int ntfs_sb_write_run(struct ntfs_sb_info *sbi, const struct runs_tree *run,
60963544672SKonstantin Komarov 		      u64 vbo, const void *buf, size_t bytes, int sync);
6104534a70bSKonstantin Komarov struct buffer_head *ntfs_bread_run(struct ntfs_sb_info *sbi,
6114534a70bSKonstantin Komarov 				   const struct runs_tree *run, u64 vbo);
6124534a70bSKonstantin Komarov int ntfs_read_run_nb(struct ntfs_sb_info *sbi, const struct runs_tree *run,
6134534a70bSKonstantin Komarov 		     u64 vbo, void *buf, u32 bytes, struct ntfs_buffers *nb);
6144534a70bSKonstantin Komarov int ntfs_read_bh(struct ntfs_sb_info *sbi, const struct runs_tree *run, u64 vbo,
6154534a70bSKonstantin Komarov 		 struct NTFS_RECORD_HEADER *rhdr, u32 bytes,
6164534a70bSKonstantin Komarov 		 struct ntfs_buffers *nb);
6174534a70bSKonstantin Komarov int ntfs_get_bh(struct ntfs_sb_info *sbi, const struct runs_tree *run, u64 vbo,
6184534a70bSKonstantin Komarov 		u32 bytes, struct ntfs_buffers *nb);
6194534a70bSKonstantin Komarov int ntfs_write_bh(struct ntfs_sb_info *sbi, struct NTFS_RECORD_HEADER *rhdr,
6204534a70bSKonstantin Komarov 		  struct ntfs_buffers *nb, int sync);
6214534a70bSKonstantin Komarov int ntfs_bio_pages(struct ntfs_sb_info *sbi, const struct runs_tree *run,
6224534a70bSKonstantin Komarov 		   struct page **pages, u32 nr_pages, u64 vbo, u32 bytes,
623ce6b5315SBart Van Assche 		   enum req_op op);
6244534a70bSKonstantin Komarov int ntfs_bio_fill_1(struct ntfs_sb_info *sbi, const struct runs_tree *run);
6254534a70bSKonstantin Komarov int ntfs_vbo_to_lbo(struct ntfs_sb_info *sbi, const struct runs_tree *run,
6264534a70bSKonstantin Komarov 		    u64 vbo, u64 *lbo, u64 *bytes);
6274534a70bSKonstantin Komarov struct ntfs_inode *ntfs_new_inode(struct ntfs_sb_info *sbi, CLST nRec,
6284534a70bSKonstantin Komarov 				  bool dir);
6294534a70bSKonstantin Komarov extern const u8 s_default_security[0x50];
6304534a70bSKonstantin Komarov bool is_sd_valid(const struct SECURITY_DESCRIPTOR_RELATIVE *sd, u32 len);
6314534a70bSKonstantin Komarov int ntfs_security_init(struct ntfs_sb_info *sbi);
6324534a70bSKonstantin Komarov int ntfs_get_security_by_id(struct ntfs_sb_info *sbi, __le32 security_id,
6334534a70bSKonstantin Komarov 			    struct SECURITY_DESCRIPTOR_RELATIVE **sd,
6344534a70bSKonstantin Komarov 			    size_t *size);
6354534a70bSKonstantin Komarov int ntfs_insert_security(struct ntfs_sb_info *sbi,
6364534a70bSKonstantin Komarov 			 const struct SECURITY_DESCRIPTOR_RELATIVE *sd,
6374534a70bSKonstantin Komarov 			 u32 size, __le32 *security_id, bool *inserted);
6384534a70bSKonstantin Komarov int ntfs_reparse_init(struct ntfs_sb_info *sbi);
6394534a70bSKonstantin Komarov int ntfs_objid_init(struct ntfs_sb_info *sbi);
6404534a70bSKonstantin Komarov int ntfs_objid_remove(struct ntfs_sb_info *sbi, struct GUID *guid);
6414534a70bSKonstantin Komarov int ntfs_insert_reparse(struct ntfs_sb_info *sbi, __le32 rtag,
6424534a70bSKonstantin Komarov 			const struct MFT_REF *ref);
6434534a70bSKonstantin Komarov int ntfs_remove_reparse(struct ntfs_sb_info *sbi, __le32 rtag,
6444534a70bSKonstantin Komarov 			const struct MFT_REF *ref);
6454534a70bSKonstantin Komarov void mark_as_free_ex(struct ntfs_sb_info *sbi, CLST lcn, CLST len, bool trim);
6464534a70bSKonstantin Komarov int run_deallocate(struct ntfs_sb_info *sbi, struct runs_tree *run, bool trim);
6471d07a9dfSDaniel Pinto bool valid_windows_name(struct ntfs_sb_info *sbi, const struct le_str *name);
6484534a70bSKonstantin Komarov 
649e8b8e97fSKari Argillander /* Globals from index.c */
6504534a70bSKonstantin Komarov int indx_used_bit(struct ntfs_index *indx, struct ntfs_inode *ni, size_t *bit);
6514534a70bSKonstantin Komarov void fnd_clear(struct ntfs_fnd *fnd);
6524534a70bSKonstantin Komarov static inline struct ntfs_fnd *fnd_get(void)
6534534a70bSKonstantin Komarov {
654195c52bdSKari Argillander 	return kzalloc(sizeof(struct ntfs_fnd), GFP_NOFS);
6554534a70bSKonstantin Komarov }
6564534a70bSKonstantin Komarov static inline void fnd_put(struct ntfs_fnd *fnd)
6574534a70bSKonstantin Komarov {
6584534a70bSKonstantin Komarov 	if (fnd) {
6594534a70bSKonstantin Komarov 		fnd_clear(fnd);
660195c52bdSKari Argillander 		kfree(fnd);
6614534a70bSKonstantin Komarov 	}
6624534a70bSKonstantin Komarov }
6634534a70bSKonstantin Komarov void indx_clear(struct ntfs_index *idx);
6644534a70bSKonstantin Komarov int indx_init(struct ntfs_index *indx, struct ntfs_sb_info *sbi,
6654534a70bSKonstantin Komarov 	      const struct ATTRIB *attr, enum index_mutex_classed type);
6664534a70bSKonstantin Komarov struct INDEX_ROOT *indx_get_root(struct ntfs_index *indx, struct ntfs_inode *ni,
6674534a70bSKonstantin Komarov 				 struct ATTRIB **attr, struct mft_inode **mi);
6684534a70bSKonstantin Komarov int indx_read(struct ntfs_index *idx, struct ntfs_inode *ni, CLST vbn,
6694534a70bSKonstantin Komarov 	      struct indx_node **node);
6704534a70bSKonstantin Komarov int indx_find(struct ntfs_index *indx, struct ntfs_inode *dir,
6714534a70bSKonstantin Komarov 	      const struct INDEX_ROOT *root, const void *Key, size_t KeyLen,
6724534a70bSKonstantin Komarov 	      const void *param, int *diff, struct NTFS_DE **entry,
6734534a70bSKonstantin Komarov 	      struct ntfs_fnd *fnd);
6744534a70bSKonstantin Komarov int indx_find_sort(struct ntfs_index *indx, struct ntfs_inode *ni,
6754534a70bSKonstantin Komarov 		   const struct INDEX_ROOT *root, struct NTFS_DE **entry,
6764534a70bSKonstantin Komarov 		   struct ntfs_fnd *fnd);
6774534a70bSKonstantin Komarov int indx_find_raw(struct ntfs_index *indx, struct ntfs_inode *ni,
6784534a70bSKonstantin Komarov 		  const struct INDEX_ROOT *root, struct NTFS_DE **entry,
6794534a70bSKonstantin Komarov 		  size_t *off, struct ntfs_fnd *fnd);
6804534a70bSKonstantin Komarov int indx_insert_entry(struct ntfs_index *indx, struct ntfs_inode *ni,
6814534a70bSKonstantin Komarov 		      const struct NTFS_DE *new_de, const void *param,
68278ab59feSKonstantin Komarov 		      struct ntfs_fnd *fnd, bool undo);
6834534a70bSKonstantin Komarov int indx_delete_entry(struct ntfs_index *indx, struct ntfs_inode *ni,
6844534a70bSKonstantin Komarov 		      const void *key, u32 key_len, const void *param);
6854534a70bSKonstantin Komarov int indx_update_dup(struct ntfs_inode *ni, struct ntfs_sb_info *sbi,
6864534a70bSKonstantin Komarov 		    const struct ATTR_FILE_NAME *fname,
6874534a70bSKonstantin Komarov 		    const struct NTFS_DUP_INFO *dup, int sync);
6884534a70bSKonstantin Komarov 
689e8b8e97fSKari Argillander /* Globals from inode.c */
6904534a70bSKonstantin Komarov struct inode *ntfs_iget5(struct super_block *sb, const struct MFT_REF *ref,
6914534a70bSKonstantin Komarov 			 const struct cpu_str *name);
6924534a70bSKonstantin Komarov int ntfs_set_size(struct inode *inode, u64 new_size);
6934534a70bSKonstantin Komarov int reset_log_file(struct inode *inode);
6944534a70bSKonstantin Komarov int ntfs_get_block(struct inode *inode, sector_t vbn,
6954534a70bSKonstantin Komarov 		   struct buffer_head *bh_result, int create);
69644ab23b9SMatthew Wilcox (Oracle) int ntfs_write_begin(struct file *file, struct address_space *mapping,
69744ab23b9SMatthew Wilcox (Oracle) 		     loff_t pos, u32 len, struct page **pagep, void **fsdata);
69844ab23b9SMatthew Wilcox (Oracle) int ntfs_write_end(struct file *file, struct address_space *mapping,
69944ab23b9SMatthew Wilcox (Oracle) 		   loff_t pos, u32 len, u32 copied, struct page *page,
70044ab23b9SMatthew Wilcox (Oracle) 		   void *fsdata);
7014534a70bSKonstantin Komarov int ntfs3_write_inode(struct inode *inode, struct writeback_control *wbc);
7024534a70bSKonstantin Komarov int ntfs_sync_inode(struct inode *inode);
7034534a70bSKonstantin Komarov int ntfs_flush_inodes(struct super_block *sb, struct inode *i1,
7044534a70bSKonstantin Komarov 		      struct inode *i2);
7054534a70bSKonstantin Komarov int inode_write_data(struct inode *inode, const void *data, size_t bytes);
7064534a70bSKonstantin Komarov struct inode *ntfs_create_inode(struct user_namespace *mnt_userns,
7074534a70bSKonstantin Komarov 				struct inode *dir, struct dentry *dentry,
7084534a70bSKonstantin Komarov 				const struct cpu_str *uni, umode_t mode,
7094534a70bSKonstantin Komarov 				dev_t dev, const char *symname, u32 size,
7104534a70bSKonstantin Komarov 				struct ntfs_fnd *fnd);
7114534a70bSKonstantin Komarov int ntfs_link_inode(struct inode *inode, struct dentry *dentry);
7124534a70bSKonstantin Komarov int ntfs_unlink_inode(struct inode *dir, const struct dentry *dentry);
7134534a70bSKonstantin Komarov void ntfs_evict_inode(struct inode *inode);
7144534a70bSKonstantin Komarov extern const struct inode_operations ntfs_link_inode_operations;
7154534a70bSKonstantin Komarov extern const struct address_space_operations ntfs_aops;
7164534a70bSKonstantin Komarov extern const struct address_space_operations ntfs_aops_cmpr;
7174534a70bSKonstantin Komarov 
718e8b8e97fSKari Argillander /* Globals from name_i.c */
7194534a70bSKonstantin Komarov int fill_name_de(struct ntfs_sb_info *sbi, void *buf, const struct qstr *name,
7204534a70bSKonstantin Komarov 		 const struct cpu_str *uni);
7214534a70bSKonstantin Komarov struct dentry *ntfs3_get_parent(struct dentry *child);
7224534a70bSKonstantin Komarov 
7234534a70bSKonstantin Komarov extern const struct inode_operations ntfs_dir_inode_operations;
7244534a70bSKonstantin Komarov extern const struct inode_operations ntfs_special_inode_operations;
725a3a956c7SKonstantin Komarov extern const struct dentry_operations ntfs_dentry_ops;
7264534a70bSKonstantin Komarov 
727e8b8e97fSKari Argillander /* Globals from record.c */
7284534a70bSKonstantin Komarov int mi_get(struct ntfs_sb_info *sbi, CLST rno, struct mft_inode **mi);
7294534a70bSKonstantin Komarov void mi_put(struct mft_inode *mi);
7304534a70bSKonstantin Komarov int mi_init(struct mft_inode *mi, struct ntfs_sb_info *sbi, CLST rno);
7314534a70bSKonstantin Komarov int mi_read(struct mft_inode *mi, bool is_mft);
7324534a70bSKonstantin Komarov struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr);
7334534a70bSKonstantin Komarov // TODO: id?
7344534a70bSKonstantin Komarov struct ATTRIB *mi_find_attr(struct mft_inode *mi, struct ATTRIB *attr,
7354534a70bSKonstantin Komarov 			    enum ATTR_TYPE type, const __le16 *name,
7364534a70bSKonstantin Komarov 			    size_t name_len, const __le16 *id);
7374534a70bSKonstantin Komarov static inline struct ATTRIB *rec_find_attr_le(struct mft_inode *rec,
7384534a70bSKonstantin Komarov 					      struct ATTR_LIST_ENTRY *le)
7394534a70bSKonstantin Komarov {
7404534a70bSKonstantin Komarov 	return mi_find_attr(rec, NULL, le->type, le_name(le), le->name_len,
7414534a70bSKonstantin Komarov 			    &le->id);
7424534a70bSKonstantin Komarov }
7434534a70bSKonstantin Komarov int mi_write(struct mft_inode *mi, int wait);
7444534a70bSKonstantin Komarov int mi_format_new(struct mft_inode *mi, struct ntfs_sb_info *sbi, CLST rno,
7454534a70bSKonstantin Komarov 		  __le16 flags, bool is_mft);
7464534a70bSKonstantin Komarov struct ATTRIB *mi_insert_attr(struct mft_inode *mi, enum ATTR_TYPE type,
7474534a70bSKonstantin Komarov 			      const __le16 *name, u8 name_len, u32 asize,
7484534a70bSKonstantin Komarov 			      u16 name_off);
7494534a70bSKonstantin Komarov 
75078ab59feSKonstantin Komarov bool mi_remove_attr(struct ntfs_inode *ni, struct mft_inode *mi,
75178ab59feSKonstantin Komarov 		    struct ATTRIB *attr);
7524534a70bSKonstantin Komarov bool mi_resize_attr(struct mft_inode *mi, struct ATTRIB *attr, int bytes);
7534534a70bSKonstantin Komarov int mi_pack_runs(struct mft_inode *mi, struct ATTRIB *attr,
7544534a70bSKonstantin Komarov 		 struct runs_tree *run, CLST len);
7554534a70bSKonstantin Komarov static inline bool mi_is_ref(const struct mft_inode *mi,
7564534a70bSKonstantin Komarov 			     const struct MFT_REF *ref)
7574534a70bSKonstantin Komarov {
7584534a70bSKonstantin Komarov 	if (le32_to_cpu(ref->low) != mi->rno)
7594534a70bSKonstantin Komarov 		return false;
7604534a70bSKonstantin Komarov 	if (ref->seq != mi->mrec->seq)
7614534a70bSKonstantin Komarov 		return false;
7624534a70bSKonstantin Komarov 
7634534a70bSKonstantin Komarov #ifdef CONFIG_NTFS3_64BIT_CLUSTER
7644534a70bSKonstantin Komarov 	return le16_to_cpu(ref->high) == (mi->rno >> 32);
7654534a70bSKonstantin Komarov #else
7664534a70bSKonstantin Komarov 	return !ref->high;
7674534a70bSKonstantin Komarov #endif
7684534a70bSKonstantin Komarov }
7694534a70bSKonstantin Komarov 
7704534a70bSKonstantin Komarov static inline void mi_get_ref(const struct mft_inode *mi, struct MFT_REF *ref)
7714534a70bSKonstantin Komarov {
7724534a70bSKonstantin Komarov 	ref->low = cpu_to_le32(mi->rno);
7734534a70bSKonstantin Komarov #ifdef CONFIG_NTFS3_64BIT_CLUSTER
7744534a70bSKonstantin Komarov 	ref->high = cpu_to_le16(mi->rno >> 32);
7754534a70bSKonstantin Komarov #else
7764534a70bSKonstantin Komarov 	ref->high = 0;
7774534a70bSKonstantin Komarov #endif
7784534a70bSKonstantin Komarov 	ref->seq = mi->mrec->seq;
7794534a70bSKonstantin Komarov }
7804534a70bSKonstantin Komarov 
781e8b8e97fSKari Argillander /* Globals from run.c */
7824534a70bSKonstantin Komarov bool run_lookup_entry(const struct runs_tree *run, CLST vcn, CLST *lcn,
7834534a70bSKonstantin Komarov 		      CLST *len, size_t *index);
7844534a70bSKonstantin Komarov void run_truncate(struct runs_tree *run, CLST vcn);
7854534a70bSKonstantin Komarov void run_truncate_head(struct runs_tree *run, CLST vcn);
7864534a70bSKonstantin Komarov void run_truncate_around(struct runs_tree *run, CLST vcn);
7874534a70bSKonstantin Komarov bool run_add_entry(struct runs_tree *run, CLST vcn, CLST lcn, CLST len,
7884534a70bSKonstantin Komarov 		   bool is_mft);
7894534a70bSKonstantin Komarov bool run_collapse_range(struct runs_tree *run, CLST vcn, CLST len);
790aa30eccbSKonstantin Komarov bool run_insert_range(struct runs_tree *run, CLST vcn, CLST len);
7914534a70bSKonstantin Komarov bool run_get_entry(const struct runs_tree *run, size_t index, CLST *vcn,
7924534a70bSKonstantin Komarov 		   CLST *lcn, CLST *len);
7934534a70bSKonstantin Komarov bool run_is_mapped_full(const struct runs_tree *run, CLST svcn, CLST evcn);
7944534a70bSKonstantin Komarov 
7954534a70bSKonstantin Komarov int run_pack(const struct runs_tree *run, CLST svcn, CLST len, u8 *run_buf,
7964534a70bSKonstantin Komarov 	     u32 run_buf_size, CLST *packed_vcns);
7974534a70bSKonstantin Komarov int run_unpack(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino,
7984534a70bSKonstantin Komarov 	       CLST svcn, CLST evcn, CLST vcn, const u8 *run_buf,
7994534a70bSKonstantin Komarov 	       u32 run_buf_size);
8004534a70bSKonstantin Komarov 
8014534a70bSKonstantin Komarov #ifdef NTFS3_CHECK_FREE_CLST
8024534a70bSKonstantin Komarov int run_unpack_ex(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino,
8034534a70bSKonstantin Komarov 		  CLST svcn, CLST evcn, CLST vcn, const u8 *run_buf,
8044534a70bSKonstantin Komarov 		  u32 run_buf_size);
8054534a70bSKonstantin Komarov #else
8064534a70bSKonstantin Komarov #define run_unpack_ex run_unpack
8074534a70bSKonstantin Komarov #endif
8084534a70bSKonstantin Komarov int run_get_highest_vcn(CLST vcn, const u8 *run_buf, u64 *highest_vcn);
80920abc64fSKonstantin Komarov int run_clone(const struct runs_tree *run, struct runs_tree *new_run);
8104534a70bSKonstantin Komarov 
811e8b8e97fSKari Argillander /* Globals from super.c */
8124534a70bSKonstantin Komarov void *ntfs_set_shared(void *ptr, u32 bytes);
8134534a70bSKonstantin Komarov void *ntfs_put_shared(void *ptr);
8144534a70bSKonstantin Komarov void ntfs_unmap_meta(struct super_block *sb, CLST lcn, CLST len);
8154534a70bSKonstantin Komarov int ntfs_discard(struct ntfs_sb_info *sbi, CLST Lcn, CLST Len);
8164534a70bSKonstantin Komarov 
817e8b8e97fSKari Argillander /* Globals from bitmap.c*/
8184534a70bSKonstantin Komarov int __init ntfs3_init_bitmap(void);
8194534a70bSKonstantin Komarov void ntfs3_exit_bitmap(void);
8204534a70bSKonstantin Komarov void wnd_close(struct wnd_bitmap *wnd);
8214534a70bSKonstantin Komarov static inline size_t wnd_zeroes(const struct wnd_bitmap *wnd)
8224534a70bSKonstantin Komarov {
8234534a70bSKonstantin Komarov 	return wnd->total_zeroes;
8244534a70bSKonstantin Komarov }
8254534a70bSKonstantin Komarov int wnd_init(struct wnd_bitmap *wnd, struct super_block *sb, size_t nbits);
8264534a70bSKonstantin Komarov int wnd_set_free(struct wnd_bitmap *wnd, size_t bit, size_t bits);
8274534a70bSKonstantin Komarov int wnd_set_used(struct wnd_bitmap *wnd, size_t bit, size_t bits);
8284534a70bSKonstantin Komarov bool wnd_is_free(struct wnd_bitmap *wnd, size_t bit, size_t bits);
8294534a70bSKonstantin Komarov bool wnd_is_used(struct wnd_bitmap *wnd, size_t bit, size_t bits);
8304534a70bSKonstantin Komarov 
831e8b8e97fSKari Argillander /* Possible values for 'flags' 'wnd_find'. */
8324534a70bSKonstantin Komarov #define BITMAP_FIND_MARK_AS_USED 0x01
8334534a70bSKonstantin Komarov #define BITMAP_FIND_FULL 0x02
8344534a70bSKonstantin Komarov size_t wnd_find(struct wnd_bitmap *wnd, size_t to_alloc, size_t hint,
8354534a70bSKonstantin Komarov 		size_t flags, size_t *allocated);
8364534a70bSKonstantin Komarov int wnd_extend(struct wnd_bitmap *wnd, size_t new_bits);
8374534a70bSKonstantin Komarov void wnd_zone_set(struct wnd_bitmap *wnd, size_t Lcn, size_t Len);
8384534a70bSKonstantin Komarov int ntfs_trim_fs(struct ntfs_sb_info *sbi, struct fstrim_range *range);
8394534a70bSKonstantin Komarov 
84008811ba5SKonstantin Komarov void ntfs_bitmap_set_le(void *map, unsigned int start, int len);
84108811ba5SKonstantin Komarov void ntfs_bitmap_clear_le(void *map, unsigned int start, int len);
84208811ba5SKonstantin Komarov unsigned int ntfs_bitmap_weight_le(const void *bitmap, int bits);
84388a8d0d2SThomas Kühnel 
844e8b8e97fSKari Argillander /* Globals from upcase.c */
8454534a70bSKonstantin Komarov int ntfs_cmp_names(const __le16 *s1, size_t l1, const __le16 *s2, size_t l2,
8464534a70bSKonstantin Komarov 		   const u16 *upcase, bool bothcase);
8474534a70bSKonstantin Komarov int ntfs_cmp_names_cpu(const struct cpu_str *uni1, const struct le_str *uni2,
8484534a70bSKonstantin Komarov 		       const u16 *upcase, bool bothcase);
849a3a956c7SKonstantin Komarov unsigned long ntfs_names_hash(const u16 *name, size_t len, const u16 *upcase,
850a3a956c7SKonstantin Komarov 			      unsigned long hash);
8514534a70bSKonstantin Komarov 
8524534a70bSKonstantin Komarov /* globals from xattr.c */
8534534a70bSKonstantin Komarov #ifdef CONFIG_NTFS3_FS_POSIX_ACL
854f7464060SLinus Torvalds struct posix_acl *ntfs_get_acl(struct inode *inode, int type, bool rcu);
8554534a70bSKonstantin Komarov int ntfs_set_acl(struct user_namespace *mnt_userns, struct inode *inode,
8564534a70bSKonstantin Komarov 		 struct posix_acl *acl, int type);
8574534a70bSKonstantin Komarov int ntfs_init_acl(struct user_namespace *mnt_userns, struct inode *inode,
8584534a70bSKonstantin Komarov 		  struct inode *dir);
8594534a70bSKonstantin Komarov #else
8604534a70bSKonstantin Komarov #define ntfs_get_acl NULL
8614534a70bSKonstantin Komarov #define ntfs_set_acl NULL
8624534a70bSKonstantin Komarov #endif
8634534a70bSKonstantin Komarov 
8644534a70bSKonstantin Komarov int ntfs_acl_chmod(struct user_namespace *mnt_userns, struct inode *inode);
8654534a70bSKonstantin Komarov int ntfs_permission(struct user_namespace *mnt_userns, struct inode *inode,
8664534a70bSKonstantin Komarov 		    int mask);
8674534a70bSKonstantin Komarov ssize_t ntfs_listxattr(struct dentry *dentry, char *buffer, size_t size);
8684534a70bSKonstantin Komarov extern const struct xattr_handler *ntfs_xattr_handlers[];
8694534a70bSKonstantin Komarov 
8704534a70bSKonstantin Komarov int ntfs_save_wsl_perm(struct inode *inode);
8714534a70bSKonstantin Komarov void ntfs_get_wsl_perm(struct inode *inode);
8724534a70bSKonstantin Komarov 
8734534a70bSKonstantin Komarov /* globals from lznt.c */
8744534a70bSKonstantin Komarov struct lznt *get_lznt_ctx(int level);
8754534a70bSKonstantin Komarov size_t compress_lznt(const void *uncompressed, size_t uncompressed_size,
8764534a70bSKonstantin Komarov 		     void *compressed, size_t compressed_size,
8774534a70bSKonstantin Komarov 		     struct lznt *ctx);
8784534a70bSKonstantin Komarov ssize_t decompress_lznt(const void *compressed, size_t compressed_size,
8794534a70bSKonstantin Komarov 			void *uncompressed, size_t uncompressed_size);
8804534a70bSKonstantin Komarov 
8814534a70bSKonstantin Komarov static inline bool is_ntfs3(struct ntfs_sb_info *sbi)
8824534a70bSKonstantin Komarov {
8834534a70bSKonstantin Komarov 	return sbi->volume.major_ver >= 3;
8844534a70bSKonstantin Komarov }
8854534a70bSKonstantin Komarov 
8864534a70bSKonstantin Komarov /* (sb->s_flags & SB_ACTIVE) */
8874534a70bSKonstantin Komarov static inline bool is_mounted(struct ntfs_sb_info *sbi)
8884534a70bSKonstantin Komarov {
8894534a70bSKonstantin Komarov 	return !!sbi->sb->s_root;
8904534a70bSKonstantin Komarov }
8914534a70bSKonstantin Komarov 
8924534a70bSKonstantin Komarov static inline bool ntfs_is_meta_file(struct ntfs_sb_info *sbi, CLST rno)
8934534a70bSKonstantin Komarov {
8944534a70bSKonstantin Komarov 	return rno < MFT_REC_FREE || rno == sbi->objid_no ||
8954534a70bSKonstantin Komarov 	       rno == sbi->quota_no || rno == sbi->reparse_no ||
8964534a70bSKonstantin Komarov 	       rno == sbi->usn_jrnl_no;
8974534a70bSKonstantin Komarov }
8984534a70bSKonstantin Komarov 
8994534a70bSKonstantin Komarov static inline void ntfs_unmap_page(struct page *page)
9004534a70bSKonstantin Komarov {
9014534a70bSKonstantin Komarov 	kunmap(page);
9024534a70bSKonstantin Komarov 	put_page(page);
9034534a70bSKonstantin Komarov }
9044534a70bSKonstantin Komarov 
9054534a70bSKonstantin Komarov static inline struct page *ntfs_map_page(struct address_space *mapping,
9064534a70bSKonstantin Komarov 					 unsigned long index)
9074534a70bSKonstantin Komarov {
9084534a70bSKonstantin Komarov 	struct page *page = read_mapping_page(mapping, index, NULL);
9094534a70bSKonstantin Komarov 
91019cb4273SMatthew Wilcox (Oracle) 	if (!IS_ERR(page))
9114534a70bSKonstantin Komarov 		kmap(page);
9124534a70bSKonstantin Komarov 	return page;
9134534a70bSKonstantin Komarov }
9144534a70bSKonstantin Komarov 
9154534a70bSKonstantin Komarov static inline size_t wnd_zone_bit(const struct wnd_bitmap *wnd)
9164534a70bSKonstantin Komarov {
9174534a70bSKonstantin Komarov 	return wnd->zone_bit;
9184534a70bSKonstantin Komarov }
9194534a70bSKonstantin Komarov 
9204534a70bSKonstantin Komarov static inline size_t wnd_zone_len(const struct wnd_bitmap *wnd)
9214534a70bSKonstantin Komarov {
9224534a70bSKonstantin Komarov 	return wnd->zone_end - wnd->zone_bit;
9234534a70bSKonstantin Komarov }
9244534a70bSKonstantin Komarov 
9254534a70bSKonstantin Komarov static inline void run_init(struct runs_tree *run)
9264534a70bSKonstantin Komarov {
9274534a70bSKonstantin Komarov 	run->runs = NULL;
9284534a70bSKonstantin Komarov 	run->count = 0;
9294534a70bSKonstantin Komarov 	run->allocated = 0;
9304534a70bSKonstantin Komarov }
9314534a70bSKonstantin Komarov 
9324534a70bSKonstantin Komarov static inline struct runs_tree *run_alloc(void)
9334534a70bSKonstantin Komarov {
934195c52bdSKari Argillander 	return kzalloc(sizeof(struct runs_tree), GFP_NOFS);
9354534a70bSKonstantin Komarov }
9364534a70bSKonstantin Komarov 
9374534a70bSKonstantin Komarov static inline void run_close(struct runs_tree *run)
9384534a70bSKonstantin Komarov {
939195c52bdSKari Argillander 	kvfree(run->runs);
9404534a70bSKonstantin Komarov 	memset(run, 0, sizeof(*run));
9414534a70bSKonstantin Komarov }
9424534a70bSKonstantin Komarov 
9434534a70bSKonstantin Komarov static inline void run_free(struct runs_tree *run)
9444534a70bSKonstantin Komarov {
9454534a70bSKonstantin Komarov 	if (run) {
946195c52bdSKari Argillander 		kvfree(run->runs);
947195c52bdSKari Argillander 		kfree(run);
9484534a70bSKonstantin Komarov 	}
9494534a70bSKonstantin Komarov }
9504534a70bSKonstantin Komarov 
9514534a70bSKonstantin Komarov static inline bool run_is_empty(struct runs_tree *run)
9524534a70bSKonstantin Komarov {
9534534a70bSKonstantin Komarov 	return !run->count;
9544534a70bSKonstantin Komarov }
9554534a70bSKonstantin Komarov 
956e8b8e97fSKari Argillander /* NTFS uses quad aligned bitmaps. */
9574534a70bSKonstantin Komarov static inline size_t bitmap_size(size_t bits)
9584534a70bSKonstantin Komarov {
959fa3cacf5SKari Argillander 	return ALIGN((bits + 7) >> 3, 8);
9604534a70bSKonstantin Komarov }
9614534a70bSKonstantin Komarov 
9624534a70bSKonstantin Komarov #define _100ns2seconds 10000000
9634534a70bSKonstantin Komarov #define SecondsToStartOf1970 0x00000002B6109100
9644534a70bSKonstantin Komarov 
9654534a70bSKonstantin Komarov #define NTFS_TIME_GRAN 100
9664534a70bSKonstantin Komarov 
9674534a70bSKonstantin Komarov /*
968e8b8e97fSKari Argillander  * kernel2nt - Converts in-memory kernel timestamp into nt time.
9694534a70bSKonstantin Komarov  */
9704534a70bSKonstantin Komarov static inline __le64 kernel2nt(const struct timespec64 *ts)
9714534a70bSKonstantin Komarov {
9724534a70bSKonstantin Komarov 	// 10^7 units of 100 nanoseconds one second
9734534a70bSKonstantin Komarov 	return cpu_to_le64(_100ns2seconds *
9744534a70bSKonstantin Komarov 				   (ts->tv_sec + SecondsToStartOf1970) +
9754534a70bSKonstantin Komarov 			   ts->tv_nsec / NTFS_TIME_GRAN);
9764534a70bSKonstantin Komarov }
9774534a70bSKonstantin Komarov 
9784534a70bSKonstantin Komarov /*
979e8b8e97fSKari Argillander  * nt2kernel - Converts on-disk nt time into kernel timestamp.
9804534a70bSKonstantin Komarov  */
9814534a70bSKonstantin Komarov static inline void nt2kernel(const __le64 tm, struct timespec64 *ts)
9824534a70bSKonstantin Komarov {
9834534a70bSKonstantin Komarov 	u64 t = le64_to_cpu(tm) - _100ns2seconds * SecondsToStartOf1970;
9844534a70bSKonstantin Komarov 
9854534a70bSKonstantin Komarov 	// WARNING: do_div changes its first argument(!)
9864534a70bSKonstantin Komarov 	ts->tv_nsec = do_div(t, _100ns2seconds) * 100;
9874534a70bSKonstantin Komarov 	ts->tv_sec = t;
9884534a70bSKonstantin Komarov }
9894534a70bSKonstantin Komarov 
9904534a70bSKonstantin Komarov static inline struct ntfs_sb_info *ntfs_sb(struct super_block *sb)
9914534a70bSKonstantin Komarov {
9924534a70bSKonstantin Komarov 	return sb->s_fs_info;
9934534a70bSKonstantin Komarov }
9944534a70bSKonstantin Komarov 
995e8b8e97fSKari Argillander /*
996e8b8e97fSKari Argillander  * ntfs_up_cluster - Align up on cluster boundary.
997e8b8e97fSKari Argillander  */
9984534a70bSKonstantin Komarov static inline u64 ntfs_up_cluster(const struct ntfs_sb_info *sbi, u64 size)
9994534a70bSKonstantin Komarov {
10004534a70bSKonstantin Komarov 	return (size + sbi->cluster_mask) & sbi->cluster_mask_inv;
10014534a70bSKonstantin Komarov }
10024534a70bSKonstantin Komarov 
1003e8b8e97fSKari Argillander /*
1004e8b8e97fSKari Argillander  * ntfs_up_block - Align up on cluster boundary.
1005e8b8e97fSKari Argillander  */
10064534a70bSKonstantin Komarov static inline u64 ntfs_up_block(const struct super_block *sb, u64 size)
10074534a70bSKonstantin Komarov {
10084534a70bSKonstantin Komarov 	return (size + sb->s_blocksize - 1) & ~(u64)(sb->s_blocksize - 1);
10094534a70bSKonstantin Komarov }
10104534a70bSKonstantin Komarov 
10114534a70bSKonstantin Komarov static inline CLST bytes_to_cluster(const struct ntfs_sb_info *sbi, u64 size)
10124534a70bSKonstantin Komarov {
10134534a70bSKonstantin Komarov 	return (size + sbi->cluster_mask) >> sbi->cluster_bits;
10144534a70bSKonstantin Komarov }
10154534a70bSKonstantin Komarov 
10164534a70bSKonstantin Komarov static inline u64 bytes_to_block(const struct super_block *sb, u64 size)
10174534a70bSKonstantin Komarov {
10184534a70bSKonstantin Komarov 	return (size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
10194534a70bSKonstantin Komarov }
10204534a70bSKonstantin Komarov 
10214534a70bSKonstantin Komarov static inline struct buffer_head *ntfs_bread(struct super_block *sb,
10224534a70bSKonstantin Komarov 					     sector_t block)
10234534a70bSKonstantin Komarov {
10244534a70bSKonstantin Komarov 	struct buffer_head *bh = sb_bread(sb, block);
10254534a70bSKonstantin Komarov 
10264534a70bSKonstantin Komarov 	if (bh)
10274534a70bSKonstantin Komarov 		return bh;
10284534a70bSKonstantin Komarov 
10294534a70bSKonstantin Komarov 	ntfs_err(sb, "failed to read volume at offset 0x%llx",
10304534a70bSKonstantin Komarov 		 (u64)block << sb->s_blocksize_bits);
10314534a70bSKonstantin Komarov 	return NULL;
10324534a70bSKonstantin Komarov }
10334534a70bSKonstantin Komarov 
10344534a70bSKonstantin Komarov static inline struct ntfs_inode *ntfs_i(struct inode *inode)
10354534a70bSKonstantin Komarov {
10364534a70bSKonstantin Komarov 	return container_of(inode, struct ntfs_inode, vfs_inode);
10374534a70bSKonstantin Komarov }
10384534a70bSKonstantin Komarov 
10394534a70bSKonstantin Komarov static inline bool is_compressed(const struct ntfs_inode *ni)
10404534a70bSKonstantin Komarov {
10414534a70bSKonstantin Komarov 	return (ni->std_fa & FILE_ATTRIBUTE_COMPRESSED) ||
10424534a70bSKonstantin Komarov 	       (ni->ni_flags & NI_FLAG_COMPRESSED_MASK);
10434534a70bSKonstantin Komarov }
10444534a70bSKonstantin Komarov 
10454534a70bSKonstantin Komarov static inline int ni_ext_compress_bits(const struct ntfs_inode *ni)
10464534a70bSKonstantin Komarov {
10474534a70bSKonstantin Komarov 	return 0xb + (ni->ni_flags & NI_FLAG_COMPRESSED_MASK);
10484534a70bSKonstantin Komarov }
10494534a70bSKonstantin Komarov 
1050e8b8e97fSKari Argillander /* Bits - 0xc, 0xd, 0xe, 0xf, 0x10 */
10514534a70bSKonstantin Komarov static inline void ni_set_ext_compress_bits(struct ntfs_inode *ni, u8 bits)
10524534a70bSKonstantin Komarov {
10534534a70bSKonstantin Komarov 	ni->ni_flags |= (bits - 0xb) & NI_FLAG_COMPRESSED_MASK;
10544534a70bSKonstantin Komarov }
10554534a70bSKonstantin Komarov 
10564534a70bSKonstantin Komarov static inline bool is_dedup(const struct ntfs_inode *ni)
10574534a70bSKonstantin Komarov {
10584534a70bSKonstantin Komarov 	return ni->ni_flags & NI_FLAG_DEDUPLICATED;
10594534a70bSKonstantin Komarov }
10604534a70bSKonstantin Komarov 
10614534a70bSKonstantin Komarov static inline bool is_encrypted(const struct ntfs_inode *ni)
10624534a70bSKonstantin Komarov {
10634534a70bSKonstantin Komarov 	return ni->std_fa & FILE_ATTRIBUTE_ENCRYPTED;
10644534a70bSKonstantin Komarov }
10654534a70bSKonstantin Komarov 
10664534a70bSKonstantin Komarov static inline bool is_sparsed(const struct ntfs_inode *ni)
10674534a70bSKonstantin Komarov {
10684534a70bSKonstantin Komarov 	return ni->std_fa & FILE_ATTRIBUTE_SPARSE_FILE;
10694534a70bSKonstantin Komarov }
10704534a70bSKonstantin Komarov 
10714534a70bSKonstantin Komarov static inline int is_resident(struct ntfs_inode *ni)
10724534a70bSKonstantin Komarov {
10734534a70bSKonstantin Komarov 	return ni->ni_flags & NI_FLAG_RESIDENT;
10744534a70bSKonstantin Komarov }
10754534a70bSKonstantin Komarov 
10764534a70bSKonstantin Komarov static inline void le16_sub_cpu(__le16 *var, u16 val)
10774534a70bSKonstantin Komarov {
10784534a70bSKonstantin Komarov 	*var = cpu_to_le16(le16_to_cpu(*var) - val);
10794534a70bSKonstantin Komarov }
10804534a70bSKonstantin Komarov 
10814534a70bSKonstantin Komarov static inline void le32_sub_cpu(__le32 *var, u32 val)
10824534a70bSKonstantin Komarov {
10834534a70bSKonstantin Komarov 	*var = cpu_to_le32(le32_to_cpu(*var) - val);
10844534a70bSKonstantin Komarov }
10854534a70bSKonstantin Komarov 
10864534a70bSKonstantin Komarov static inline void nb_put(struct ntfs_buffers *nb)
10874534a70bSKonstantin Komarov {
10884534a70bSKonstantin Komarov 	u32 i, nbufs = nb->nbufs;
10894534a70bSKonstantin Komarov 
10904534a70bSKonstantin Komarov 	if (!nbufs)
10914534a70bSKonstantin Komarov 		return;
10924534a70bSKonstantin Komarov 
10934534a70bSKonstantin Komarov 	for (i = 0; i < nbufs; i++)
10944534a70bSKonstantin Komarov 		put_bh(nb->bh[i]);
10954534a70bSKonstantin Komarov 	nb->nbufs = 0;
10964534a70bSKonstantin Komarov }
10974534a70bSKonstantin Komarov 
10984534a70bSKonstantin Komarov static inline void put_indx_node(struct indx_node *in)
10994534a70bSKonstantin Komarov {
11004534a70bSKonstantin Komarov 	if (!in)
11014534a70bSKonstantin Komarov 		return;
11024534a70bSKonstantin Komarov 
1103195c52bdSKari Argillander 	kfree(in->index);
11044534a70bSKonstantin Komarov 	nb_put(&in->nb);
1105195c52bdSKari Argillander 	kfree(in);
11064534a70bSKonstantin Komarov }
11074534a70bSKonstantin Komarov 
11084534a70bSKonstantin Komarov static inline void mi_clear(struct mft_inode *mi)
11094534a70bSKonstantin Komarov {
11104534a70bSKonstantin Komarov 	nb_put(&mi->nb);
1111195c52bdSKari Argillander 	kfree(mi->mrec);
11124534a70bSKonstantin Komarov 	mi->mrec = NULL;
11134534a70bSKonstantin Komarov }
11144534a70bSKonstantin Komarov 
11154534a70bSKonstantin Komarov static inline void ni_lock(struct ntfs_inode *ni)
11164534a70bSKonstantin Komarov {
11174534a70bSKonstantin Komarov 	mutex_lock_nested(&ni->ni_lock, NTFS_INODE_MUTEX_NORMAL);
11184534a70bSKonstantin Komarov }
11194534a70bSKonstantin Komarov 
11204534a70bSKonstantin Komarov static inline void ni_lock_dir(struct ntfs_inode *ni)
11214534a70bSKonstantin Komarov {
11224534a70bSKonstantin Komarov 	mutex_lock_nested(&ni->ni_lock, NTFS_INODE_MUTEX_PARENT);
11234534a70bSKonstantin Komarov }
11244534a70bSKonstantin Komarov 
1125*0ad9dfcbSKonstantin Komarov static inline void ni_lock_dir2(struct ntfs_inode *ni)
1126*0ad9dfcbSKonstantin Komarov {
1127*0ad9dfcbSKonstantin Komarov 	mutex_lock_nested(&ni->ni_lock, NTFS_INODE_MUTEX_PARENT2);
1128*0ad9dfcbSKonstantin Komarov }
1129*0ad9dfcbSKonstantin Komarov 
11304534a70bSKonstantin Komarov static inline void ni_unlock(struct ntfs_inode *ni)
11314534a70bSKonstantin Komarov {
11324534a70bSKonstantin Komarov 	mutex_unlock(&ni->ni_lock);
11334534a70bSKonstantin Komarov }
11344534a70bSKonstantin Komarov 
11354534a70bSKonstantin Komarov static inline int ni_trylock(struct ntfs_inode *ni)
11364534a70bSKonstantin Komarov {
11374534a70bSKonstantin Komarov 	return mutex_trylock(&ni->ni_lock);
11384534a70bSKonstantin Komarov }
11394534a70bSKonstantin Komarov 
11404534a70bSKonstantin Komarov static inline int attr_load_runs_attr(struct ntfs_inode *ni,
11414534a70bSKonstantin Komarov 				      struct ATTRIB *attr,
11424534a70bSKonstantin Komarov 				      struct runs_tree *run, CLST vcn)
11434534a70bSKonstantin Komarov {
11444534a70bSKonstantin Komarov 	return attr_load_runs_vcn(ni, attr->type, attr_name(attr),
11454534a70bSKonstantin Komarov 				  attr->name_len, run, vcn);
11464534a70bSKonstantin Komarov }
11474534a70bSKonstantin Komarov 
11484534a70bSKonstantin Komarov static inline void le64_sub_cpu(__le64 *var, u64 val)
11494534a70bSKonstantin Komarov {
11504534a70bSKonstantin Komarov 	*var = cpu_to_le64(le64_to_cpu(*var) - val);
11514534a70bSKonstantin Komarov }
115287790b65SKari Argillander 
115387790b65SKari Argillander #endif /* _LINUX_NTFS3_NTFS_FS_H */
1154