/* SPDX-License-Identifier: GPL-2.0 */
/*
*
* Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
*
*/
// clang-format off
#ifndef _LINUX_NTFS3_NTFS_FS_H
#define _LINUX_NTFS3_NTFS_FS_H
#include <linux/blkdev.h>
#include <linux/buffer_head.h>
#include <linux/fs.h>
#include <linux/highmem.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/mutex.h>
#include <linux/page-flags.h>
#include <linux/pagemap.h>
#include <linux/rbtree.h>
#include <linux/rwsem.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/time64.h>
#include <linux/types.h>
#include <linux/uidgid.h>
#include <asm/div64.h>
#include <asm/page.h>
#include "debug.h"
#include "ntfs.h"
struct dentry;
struct fiemap_extent_info;
struct user_namespace;
struct page;
struct writeback_control;
enum utf16_endian;
#define MINUS_ONE_T ((size_t)(-1))
/* Biggest MFT / smallest cluster */
#define MAXIMUM_BYTES_PER_MFT 4096
#define NTFS_BLOCKS_PER_MFT_RECORD (MAXIMUM_BYTES_PER_MFT / 512)
#define MAXIMUM_BYTES_PER_INDEX 4096
#define NTFS_BLOCKS_PER_INODE (MAXIMUM_BYTES_PER_INDEX / 512)
/* NTFS specific error code when fixup failed. */
#define E_NTFS_FIXUP 555
/* NTFS specific error code about resident->nonresident. */
#define E_NTFS_NONRESIDENT 556
/* NTFS specific error code about punch hole. */
#define E_NTFS_NOTALIGNED 557
/* NTFS specific error code when on-disk struct is corrupted. */
#define E_NTFS_CORRUPT 558
/* sbi->flags */
#define NTFS_FLAGS_NODISCARD 0x00000001
/* Set when LogFile is replaying. */
#define NTFS_FLAGS_LOG_REPLAYING 0x00000008
/* Set when we changed first MFT's which copy must be updated in $MftMirr. */
#define NTFS_FLAGS_MFTMIRR 0x00001000
#define NTFS_FLAGS_NEED_REPLAY 0x04000000
/* ni->ni_flags */
/*
* Data attribute is external compressed (LZX/Xpress)
* 1 - WOF_COMPRESSION_XPRESS4K
* 2 - WOF_COMPRESSION_XPRESS8K
* 3 - WOF_COMPRESSION_XPRESS16K
* 4 - WOF_COMPRESSION_LZX32K
*/
#define NI_FLAG_COMPRESSED_MASK 0x0000000f
/* Data attribute is deduplicated. */
#define NI_FLAG_DEDUPLICATED 0x00000010
#define NI_FLAG_EA 0x00000020
#define NI_FLAG_DIR 0x00000040
#define NI_FLAG_RESIDENT 0x00000080
#define NI_FLAG_UPDATE_PARENT 0x00000100
// clang-format on
struct ntfs_mount_options {
char *nls_name;
struct nls_table *nls;
kuid_t fs_uid;
kgid_t fs_gid;
u16 fs_fmask_inv;
u16 fs_dmask_inv;
unsigned fmask : 1; /* fmask was set. */
unsigned dmask : 1; /*dmask was set. */
unsigned sys_immutable : 1; /* Immutable system files. */
unsigned discard : 1; /* Issue discard requests on deletions. */
unsigned sparse : 1; /* Create sparse files. */
unsigned showmeta : 1; /* Show meta files. */
unsigned nohidden : 1; /* Do not show hidden files. */
unsigned force : 1; /* RW mount dirty volume. */
unsigned noacsrules : 1; /* Exclude acs rules. */
unsigned prealloc : 1; /* Preallocate space when file is growing. */
};
/* Special value to unpack and deallocate. */
#define RUN_DEALLOCATE ((struct runs_tree *)(size_t)1)
/* TODO: Use rb tree instead of array. */
struct runs_tree {
struct ntfs_run *runs;
size_t count; /* Currently used size a ntfs_run storage. */
size_t allocated; /* Currently allocated ntfs_run storage size. */
};
struct ntfs_buffers {
/* Biggest MFT / smallest cluster = 4096 / 512 = 8 */
/* Biggest index / smallest cluster = 4096 / 512 = 8 */
struct buffer_head *bh[PAGE_SIZE >> SECTOR_SHIFT];
u32 bytes;
u32 nbufs;
u32 off;
};
enum ALLOCATE_OPT {
ALLOCATE_DEF = 0, // Allocate all clusters.
ALLOCATE_MFT = 1, // Allocate for MFT.
};
enum bitmap_mutex_classes {
BITMAP_MUTEX_CLUSTERS = 0,
BITMAP_MUTEX_MFT = 1,
};
struct wnd_bitmap {
struct super_block *sb;
struct rw_semaphore rw_lock;
struct runs_tree run;
size_t nbits;
size_t total_zeroes; // Total number of free bits.
u16 *free_bits; // Free bits in each window.
size_t nwnd;
u32 bits_last; // Bits in last window.
struct rb_root start_tree; // Extents, sorted by 'start'.
struct rb_root count_tree; // Extents, sorted by 'count + start'.
size_t count; // Extents count.
/*
* -1 Tree is activated but not updated (too many fragments).
* 0 - Tree is not activated.
* 1 - Tree is activated and updated.
*/
int uptodated;
size_t extent_min; // Minimal extent used while building.
size_t extent_max; // Upper estimate of biggest free block.
/* Zone [bit, end) */
size_t zone_bit;
size_t zone_end;
bool set_tail; // Not necessary in driver.
bool inited;
};
typedef int (*NTFS_CMP_FUNC)(const void *key1, size_t len1, const void *key2,
size_t len2, const void *param);
enum index_mutex_classed {
INDEX_MUTEX_I30 = 0,
INDEX_MUTEX_SII = 1,
INDEX_MUTEX_SDH = 2,
INDEX_MUTEX_SO = 3,
INDEX_MUTEX_SQ = 4,
INDEX_MUTEX_SR = 5,
INDEX_MUTEX_TOTAL
};
/* ntfs_index - Allocation unit inside directory. */
struct ntfs_index {
struct runs_tree bitmap_run;
struct runs_tree alloc_run;
/* read/write access to 'bitmap_run'/'alloc_run' while ntfs_readdir */
struct rw_semaphore run_lock;
/*TODO: Remove 'cmp'. */
NTFS_CMP_FUNC cmp;
u8 index_bits; // log2(root->index_block_size)
u8 idx2vbn_bits; // log2(root->index_block_clst)
u8 vbn2vbo_bits; // index_block_size < cluster? 9 : cluster_bits
u8 type; // index_mutex_classed
};
/* Minimum MFT zone. */
#define NTFS_MIN_MFT_ZONE 100
/* Ntfs file system in-core superblock data. */
struct ntfs_sb_info {
struct super_block *sb;
u32 discard_granularity;
u64 discard_granularity_mask_inv; // ~(discard_granularity_mask_inv-1)
u32 cluster_size; // bytes per cluster
u32 cluster_mask; // == cluster_size - 1
u64 cluster_mask_inv; // ~(cluster_size - 1)
u32 block_mask; // sb->s_blocksize - 1
u32 blocks_per_cluster; // cluster_size / sb->s_blocksize
u32 record_size;
u32 index_size;
u8 cluster_bits;
u8 record_bits;
u64 maxbytes; // Maximum size for normal files.
u64 maxbytes_sparse; // Maximum size for