/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Defines for volume structures in NTFS Linux kernel driver. * * Copyright (c) 2001-2006 Anton Altaparmakov * Copyright (c) 2002 Richard Russon * Copyright (c) 2025 LG Electronics Co., Ltd. */ #ifndef _LINUX_NTFS_VOLUME_H #define _LINUX_NTFS_VOLUME_H #include #include #include #include #include #include #include "layout.h" #define NTFS_VOL_UID BIT(1) #define NTFS_VOL_GID BIT(2) /* * The NTFS in memory super block structure. * * @sb: Pointer back to the super_block. * @nr_blocks: Number of sb->s_blocksize bytes sized blocks on the device. * @flags: Miscellaneous flags, see below. * @uid: uid that files will be mounted as. * @gid: gid that files will be mounted as. * @fmask: The mask for file permissions. * @dmask: The mask for directory permissions. * @mft_zone_multiplier: Initial mft zone multiplier. * @on_errors: What to do on filesystem errors. * @wb_err: Writeback error tracking. * @sector_size: in bytes * @sector_size_bits: log2(sector_size) * @cluster_size: in bytes * @cluster_size_mask: cluster_size - 1 * @cluster_size_bits: log2(cluster_size) * @mft_record_size: in bytes * @mft_record_size_mask: mft_record_size - 1 * @mft_record_size_bits: log2(mft_record_size) * @index_record_size: in bytes * @index_record_size_mask: index_record_size - 1 * @index_record_size_bits: log2(index_record_size) * @nr_clusters: Volume size in clusters == number of bits in lcn bitmap. * @mft_lcn: Cluster location of mft data. * @mftmirr_lcn: Cluster location of copy of mft. * @serial_no: The volume serial number. * @upcase_len: Number of entries in upcase[]. * @upcase: The upcase table. * @attrdef_size: Size of the attribute definition table in bytes. * @attrdef: Table of attribute definitions. Obtained from FILE_AttrDef. * @mft_data_pos: Mft record number at which to allocate the next mft record. * @mft_zone_start: First cluster of the mft zone. * @mft_zone_end: First cluster beyond the mft zone. * @mft_zone_pos: Current position in the mft zone. * @data1_zone_pos: Current position in the first data zone. * @data2_zone_pos: Current position in the second data zone. * @mft_ino: The VFS inode of $MFT. * @mftbmp_ino: Attribute inode for $MFT/$BITMAP. * @mftbmp_lock: Lock for serializing accesses to the mft record bitmap. * @mftmirr_ino: The VFS inode of $MFTMirr. * @mftmirr_size: Size of mft mirror in mft records. * @logfile_ino: The VFS inode of LogFile. * @lcnbmp_ino: The VFS inode of $Bitmap. * @lcnbmp_lock: Lock for serializing accesses to the cluster bitmap * @vol_ino: The VFS inode of $Volume. * @vol_flags: Volume flags. * @major_ver: Ntfs major version of volume. * @minor_ver: Ntfs minor version of volume. * @volume_label: volume label. * @root_ino: The VFS inode of the root directory. * @secure_ino: The VFS inode of $Secure (NTFS3.0+ only, otherwise NULL). * @extend_ino: The VFS inode of $Extend (NTFS3.0+ only, otherwise NULL). * @quota_ino: The VFS inode of $Quota. * @quota_q_ino: Attribute inode for $Quota/$Q. * @nls_map: NLS (National Language Support) table. * @nls_utf8: NLS table for UTF-8. * @free_waitq: Wait queue for threads waiting for free clusters or MFT records. * @free_clusters: Track the number of free clusters. * @free_mft_records: Track the free mft records. * @dirty_clusters: Number of clusters that are dirty. * @sparse_compression_unit: Size of compression/sparse unit in clusters. * @lcn_empty_bits_per_page: Number of empty bits per page in the LCN bitmap. * @precalc_work: Work structure for background pre-calculation tasks. * @preallocated_size: reallocation size (in bytes). */ struct ntfs_volume { struct super_block *sb; s64 nr_blocks; unsigned long flags; kuid_t uid; kgid_t gid; umode_t fmask; umode_t dmask; u8 mft_zone_multiplier; u8 on_errors; errseq_t wb_err; u16 sector_size; u8 sector_size_bits; u32 cluster_size; u32 cluster_size_mask; u8 cluster_size_bits; u32 mft_record_size; u32 mft_record_size_mask; u8 mft_record_size_bits; u32 index_record_size; u32 index_record_size_mask; u8 index_record_size_bits; s64 nr_clusters; s64 mft_lcn; s64 mftmirr_lcn; u64 serial_no; u32 upcase_len; __le16 *upcase; s32 attrdef_size; struct attr_def *attrdef; s64 mft_data_pos; s64 mft_zone_start; s64 mft_zone_end; s64 mft_zone_pos; s64 data1_zone_pos; s64 data2_zone_pos; struct inode *mft_ino; struct inode *mftbmp_ino; struct rw_semaphore mftbmp_lock; struct inode *mftmirr_ino; int mftmirr_size; struct inode *logfile_ino; struct inode *lcnbmp_ino; struct rw_semaphore lcnbmp_lock; struct inode *vol_ino; __le16 vol_flags; u8 major_ver; u8 minor_ver; unsigned char *volume_label; struct inode *root_ino; struct inode *secure_ino; struct inode *extend_ino; struct inode *quota_ino; struct inode *quota_q_ino; struct nls_table *nls_map; bool nls_utf8; wait_queue_head_t free_waitq; atomic64_t free_clusters; atomic64_t free_mft_records; atomic64_t dirty_clusters; u8 sparse_compression_unit; unsigned int *lcn_empty_bits_per_page; struct work_struct precalc_work; loff_t preallocated_size; }; /* * Defined bits for the flags field in the ntfs_volume structure. * * NV_Errors Volume has errors, prevent remount rw. * NV_ShowSystemFiles Return system files in ntfs_readdir(). * NV_CaseSensitive Treat file names as case sensitive and * create filenames in the POSIX namespace. * Otherwise be case insensitive but still * create file names in POSIX namespace. * NV_LogFileEmpty LogFile journal is empty. * NV_QuotaOutOfDate Quota is out of date. * NV_UsnJrnlStamped UsnJrnl has been stamped. * NV_ReadOnly Volume is mounted read-only. * NV_Compression Volume supports compression. * NV_FreeClusterKnown Free cluster count is known and up-to-date. * NV_Shutdown Volume is in shutdown state * NV_SysImmutable Protect system files from deletion. * NV_ShowHiddenFiles Return hidden files in ntfs_readdir(). * NV_HideDotFiles Hide names beginning with a dot ("."). * NV_CheckWindowsNames Refuse creation/rename of files with * Windows-reserved names (CON, AUX, NUL, COM1, * LPT1, etc.) or invalid characters. * * NV_Discard Issue discard/TRIM commands for freed clusters. * NV_DisableSparse Disable creation of sparse regions. */ enum { NV_Errors, NV_ShowSystemFiles, NV_CaseSensitive, NV_LogFileEmpty, NV_QuotaOutOfDate, NV_UsnJrnlStamped, NV_ReadOnly, NV_Compression, NV_FreeClusterKnown, NV_Shutdown, NV_SysImmutable, NV_ShowHiddenFiles, NV_HideDotFiles, NV_CheckWindowsNames, NV_Discard, NV_DisableSparse, }; /* * Macro tricks to expand the NVolFoo(), NVolSetFoo(), and NVolClearFoo() * functions. */ #define DEFINE_NVOL_BIT_OPS(flag) \ static inline int NVol##flag(struct ntfs_volume *vol) \ { \ return test_bit(NV_##flag, &(vol)->flags); \ } \ static inline void NVolSet##flag(struct ntfs_volume *vol) \ { \ set_bit(NV_##flag, &(vol)->flags); \ } \ static inline void NVolClear##flag(struct ntfs_volume *vol) \ { \ clear_bit(NV_##flag, &(vol)->flags); \ } /* Emit the ntfs volume bitops functions. */ DEFINE_NVOL_BIT_OPS(Errors) DEFINE_NVOL_BIT_OPS(ShowSystemFiles) DEFINE_NVOL_BIT_OPS(CaseSensitive) DEFINE_NVOL_BIT_OPS(LogFileEmpty) DEFINE_NVOL_BIT_OPS(QuotaOutOfDate) DEFINE_NVOL_BIT_OPS(UsnJrnlStamped) DEFINE_NVOL_BIT_OPS(ReadOnly) DEFINE_NVOL_BIT_OPS(Compression) DEFINE_NVOL_BIT_OPS(FreeClusterKnown) DEFINE_NVOL_BIT_OPS(Shutdown) DEFINE_NVOL_BIT_OPS(SysImmutable) DEFINE_NVOL_BIT_OPS(ShowHiddenFiles) DEFINE_NVOL_BIT_OPS(HideDotFiles) DEFINE_NVOL_BIT_OPS(CheckWindowsNames) DEFINE_NVOL_BIT_OPS(Discard) DEFINE_NVOL_BIT_OPS(DisableSparse) static inline void ntfs_inc_free_clusters(struct ntfs_volume *vol, s64 nr) { if (!NVolFreeClusterKnown(vol)) wait_event(vol->free_waitq, NVolFreeClusterKnown(vol)); atomic64_add(nr, &vol->free_clusters); } static inline void ntfs_dec_free_clusters(struct ntfs_volume *vol, s64 nr) { if (!NVolFreeClusterKnown(vol)) wait_event(vol->free_waitq, NVolFreeClusterKnown(vol)); atomic64_sub(nr, &vol->free_clusters); } static inline void ntfs_inc_free_mft_records(struct ntfs_volume *vol, s64 nr) { if (!NVolFreeClusterKnown(vol)) return; atomic64_add(nr, &vol->free_mft_records); } static inline void ntfs_dec_free_mft_records(struct ntfs_volume *vol, s64 nr) { if (!NVolFreeClusterKnown(vol)) return; atomic64_sub(nr, &vol->free_mft_records); } static inline void ntfs_set_lcn_empty_bits(struct ntfs_volume *vol, unsigned long index, u8 val, unsigned int count) { if (!NVolFreeClusterKnown(vol)) wait_event(vol->free_waitq, NVolFreeClusterKnown(vol)); if (val) vol->lcn_empty_bits_per_page[index] -= count; else vol->lcn_empty_bits_per_page[index] += count; } static __always_inline void ntfs_hold_dirty_clusters(struct ntfs_volume *vol, s64 nr_clusters) { atomic64_add(nr_clusters, &vol->dirty_clusters); } static __always_inline void ntfs_release_dirty_clusters(struct ntfs_volume *vol, s64 nr_clusters) { if (atomic64_read(&vol->dirty_clusters) < nr_clusters) atomic64_set(&vol->dirty_clusters, 0); else atomic64_sub(nr_clusters, &vol->dirty_clusters); } s64 ntfs_available_clusters_count(struct ntfs_volume *vol, s64 nr_clusters); s64 get_nr_free_clusters(struct ntfs_volume *vol); #endif /* _LINUX_NTFS_VOLUME_H */