1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3 * Defines for volume structures in NTFS Linux kernel driver.
4 *
5 * Copyright (c) 2001-2006 Anton Altaparmakov
6 * Copyright (c) 2002 Richard Russon
7 * Copyright (c) 2025 LG Electronics Co., Ltd.
8 */
9
10 #ifndef _LINUX_NTFS_VOLUME_H
11 #define _LINUX_NTFS_VOLUME_H
12
13 #include <linux/rwsem.h>
14 #include <linux/sched.h>
15 #include <linux/wait.h>
16 #include <linux/uidgid.h>
17 #include <linux/workqueue.h>
18 #include <linux/errseq.h>
19
20 #include "layout.h"
21
22 #define NTFS_VOL_UID BIT(1)
23 #define NTFS_VOL_GID BIT(2)
24
25 /*
26 * The NTFS in memory super block structure.
27 *
28 * @sb: Pointer back to the super_block.
29 * @nr_blocks: Number of sb->s_blocksize bytes sized blocks on the device.
30 * @flags: Miscellaneous flags, see below.
31 * @uid: uid that files will be mounted as.
32 * @gid: gid that files will be mounted as.
33 * @fmask: The mask for file permissions.
34 * @dmask: The mask for directory permissions.
35 * @mft_zone_multiplier: Initial mft zone multiplier.
36 * @on_errors: What to do on filesystem errors.
37 * @wb_err: Writeback error tracking.
38 * @sector_size: in bytes
39 * @sector_size_bits: log2(sector_size)
40 * @cluster_size: in bytes
41 * @cluster_size_mask: cluster_size - 1
42 * @cluster_size_bits: log2(cluster_size)
43 * @mft_record_size: in bytes
44 * @mft_record_size_mask: mft_record_size - 1
45 * @mft_record_size_bits: log2(mft_record_size)
46 * @index_record_size: in bytes
47 * @index_record_size_mask: index_record_size - 1
48 * @index_record_size_bits: log2(index_record_size)
49 * @nr_clusters: Volume size in clusters == number of bits in lcn bitmap.
50 * @mft_lcn: Cluster location of mft data.
51 * @mftmirr_lcn: Cluster location of copy of mft.
52 * @serial_no: The volume serial number.
53 * @upcase_len: Number of entries in upcase[].
54 * @upcase: The upcase table.
55 * @attrdef_size: Size of the attribute definition table in bytes.
56 * @attrdef: Table of attribute definitions. Obtained from FILE_AttrDef.
57 * @mft_data_pos: Mft record number at which to allocate the next mft record.
58 * @mft_record_reserve_pos: First record in the in-memory MFT metadata reserve
59 * (protected by mftbmp_lock).
60 * @mft_record_reserve_end: First record beyond the MFT metadata reserve
61 * (protected by mftbmp_lock).
62 * @mft_zone_start: First cluster of the mft zone.
63 * @mft_zone_end: First cluster beyond the mft zone.
64 * @mft_zone_pos: Current position in the mft zone.
65 * @data1_zone_pos: Current position in the first data zone.
66 * @data2_zone_pos: Current position in the second data zone.
67 * @mft_ino: The VFS inode of $MFT.
68 * @mftbmp_ino: Attribute inode for $MFT/$BITMAP.
69 * @mftbmp_lock: Lock for serializing accesses to the mft record bitmap.
70 * @mftmirr_ino: The VFS inode of $MFTMirr.
71 * @mftmirr_size: Size of mft mirror in mft records.
72 * @logfile_ino: The VFS inode of LogFile.
73 * @lcnbmp_ino: The VFS inode of $Bitmap.
74 * @lcnbmp_lock: Lock for serializing accesses to the cluster bitmap
75 * @vol_ino: The VFS inode of $Volume.
76 * @vol_flags: Volume flags.
77 * @major_ver: Ntfs major version of volume.
78 * @minor_ver: Ntfs minor version of volume.
79 * @volume_label_lock: protects @volume_label.
80 * @volume_label: volume label.
81 * @root_ino: The VFS inode of the root directory.
82 * @secure_ino: The VFS inode of $Secure (NTFS3.0+ only, otherwise NULL).
83 * @extend_ino: The VFS inode of $Extend (NTFS3.0+ only, otherwise NULL).
84 * @nls_map: NLS (National Language Support) table.
85 * @nls_utf8: NLS table for UTF-8.
86 * @free_waitq: Wait queue for threads waiting for free clusters or MFT records.
87 * @free_clusters: Track the number of free clusters.
88 * @free_mft_records: Track the free mft records.
89 * @dirty_clusters: Number of clusters that are dirty.
90 * @sparse_compression_unit: Size of compression/sparse unit in clusters.
91 * @lcn_empty_bits_per_page: Number of empty bits per page in the LCN bitmap.
92 * @precalc_work: Work structure for background pre-calculation tasks.
93 * @preallocated_size: reallocation size (in bytes).
94 */
95 struct ntfs_volume {
96 struct super_block *sb;
97 s64 nr_blocks;
98 unsigned long flags;
99 kuid_t uid;
100 kgid_t gid;
101 umode_t fmask;
102 umode_t dmask;
103 u8 mft_zone_multiplier;
104 u8 on_errors;
105 errseq_t wb_err;
106 u16 sector_size;
107 u8 sector_size_bits;
108 u32 cluster_size;
109 u32 cluster_size_mask;
110 u8 cluster_size_bits;
111 u32 mft_record_size;
112 u32 mft_record_size_mask;
113 u8 mft_record_size_bits;
114 u32 index_record_size;
115 u32 index_record_size_mask;
116 u8 index_record_size_bits;
117 s64 nr_clusters;
118 s64 mft_lcn;
119 s64 mftmirr_lcn;
120 u64 serial_no;
121 u32 upcase_len;
122 __le16 *upcase;
123 s32 attrdef_size;
124 struct attr_def *attrdef;
125 s64 mft_data_pos;
126 s64 mft_record_reserve_pos;
127 s64 mft_record_reserve_end;
128 s64 mft_zone_start;
129 s64 mft_zone_end;
130 s64 mft_zone_pos;
131 s64 data1_zone_pos;
132 s64 data2_zone_pos;
133 struct inode *mft_ino;
134 struct inode *mftbmp_ino;
135 struct rw_semaphore mftbmp_lock;
136 struct inode *mftmirr_ino;
137 int mftmirr_size;
138 struct inode *logfile_ino;
139 struct inode *lcnbmp_ino;
140 struct rw_semaphore lcnbmp_lock;
141 struct mutex volume_label_lock;
142 struct inode *vol_ino;
143 __le16 vol_flags;
144 u8 major_ver;
145 u8 minor_ver;
146 unsigned char *volume_label;
147 struct inode *root_ino;
148 struct inode *secure_ino;
149 struct inode *extend_ino;
150 struct nls_table *nls_map;
151 bool nls_utf8;
152 wait_queue_head_t free_waitq;
153 atomic64_t free_clusters;
154 atomic64_t free_mft_records;
155 atomic64_t dirty_clusters;
156 u8 sparse_compression_unit;
157 unsigned int *lcn_empty_bits_per_page;
158 struct work_struct precalc_work;
159 loff_t preallocated_size;
160 };
161
162 /*
163 * Defined bits for the flags field in the ntfs_volume structure.
164 *
165 * NV_Errors Volume has errors, prevent remount rw.
166 * NV_ShowSystemFiles Return system files in ntfs_readdir().
167 * NV_CaseSensitive Treat file names as case sensitive and
168 * create filenames in the POSIX namespace.
169 * Otherwise be case insensitive but still
170 * create file names in POSIX namespace.
171 * NV_LogFileEmpty LogFile journal is empty.
172 * NV_UsnJrnlStamped UsnJrnl has been stamped.
173 * NV_ReadOnly Volume is mounted read-only.
174 * NV_Compression Volume supports compression.
175 * NV_FreeClusterKnown Free cluster count is known and up-to-date.
176 * NV_Shutdown Volume is in shutdown state
177 * NV_SysImmutable Protect system files from deletion.
178 * NV_ShowHiddenFiles Return hidden files in ntfs_readdir().
179 * NV_HideDotFiles Hide names beginning with a dot (".").
180 * NV_CheckWindowsNames Refuse creation/rename of files with
181 * Windows-reserved names (CON, AUX, NUL, COM1,
182 * LPT1, etc.) or invalid characters.
183 *
184 * NV_Discard Issue discard/TRIM commands for freed clusters.
185 * NV_DisableSparse Disable creation of sparse regions.
186 * NV_NativeSymlinkRel Translate absolute Windows reparse targets (native_symlink=rel).
187 */
188 enum {
189 NV_Errors,
190 NV_ShowSystemFiles,
191 NV_CaseSensitive,
192 NV_LogFileEmpty,
193 NV_UsnJrnlStamped,
194 NV_ReadOnly,
195 NV_Compression,
196 NV_FreeClusterKnown,
197 NV_Shutdown,
198 NV_SysImmutable,
199 NV_ShowHiddenFiles,
200 NV_HideDotFiles,
201 NV_CheckWindowsNames,
202 NV_Discard,
203 NV_DisableSparse,
204 NV_NativeSymlinkRel,
205 NV_SymlinkNative,
206 };
207
208 /*
209 * Macro tricks to expand the NVolFoo(), NVolSetFoo(), and NVolClearFoo()
210 * functions.
211 */
212 #define DEFINE_NVOL_BIT_OPS(flag) \
213 static inline int NVol##flag(struct ntfs_volume *vol) \
214 { \
215 return test_bit(NV_##flag, &(vol)->flags); \
216 } \
217 static inline void NVolSet##flag(struct ntfs_volume *vol) \
218 { \
219 set_bit(NV_##flag, &(vol)->flags); \
220 } \
221 static inline void NVolClear##flag(struct ntfs_volume *vol) \
222 { \
223 clear_bit(NV_##flag, &(vol)->flags); \
224 }
225
226 /* Emit the ntfs volume bitops functions. */
227 DEFINE_NVOL_BIT_OPS(Errors)
DEFINE_NVOL_BIT_OPS(ShowSystemFiles)228 DEFINE_NVOL_BIT_OPS(ShowSystemFiles)
229 DEFINE_NVOL_BIT_OPS(CaseSensitive)
230 DEFINE_NVOL_BIT_OPS(LogFileEmpty)
231 DEFINE_NVOL_BIT_OPS(UsnJrnlStamped)
232 DEFINE_NVOL_BIT_OPS(ReadOnly)
233 DEFINE_NVOL_BIT_OPS(Compression)
234 DEFINE_NVOL_BIT_OPS(FreeClusterKnown)
235 DEFINE_NVOL_BIT_OPS(Shutdown)
236 DEFINE_NVOL_BIT_OPS(SysImmutable)
237 DEFINE_NVOL_BIT_OPS(ShowHiddenFiles)
238 DEFINE_NVOL_BIT_OPS(HideDotFiles)
239 DEFINE_NVOL_BIT_OPS(CheckWindowsNames)
240 DEFINE_NVOL_BIT_OPS(Discard)
241 DEFINE_NVOL_BIT_OPS(DisableSparse)
242 DEFINE_NVOL_BIT_OPS(NativeSymlinkRel)
243 DEFINE_NVOL_BIT_OPS(SymlinkNative)
244
245 static inline void ntfs_inc_free_clusters(struct ntfs_volume *vol, s64 nr)
246 {
247 if (!NVolFreeClusterKnown(vol))
248 wait_event(vol->free_waitq, NVolFreeClusterKnown(vol));
249 atomic64_add(nr, &vol->free_clusters);
250 }
251
ntfs_dec_free_clusters(struct ntfs_volume * vol,s64 nr)252 static inline void ntfs_dec_free_clusters(struct ntfs_volume *vol, s64 nr)
253 {
254 if (!NVolFreeClusterKnown(vol))
255 wait_event(vol->free_waitq, NVolFreeClusterKnown(vol));
256 atomic64_sub(nr, &vol->free_clusters);
257 }
258
ntfs_inc_free_mft_records(struct ntfs_volume * vol,s64 nr)259 static inline void ntfs_inc_free_mft_records(struct ntfs_volume *vol, s64 nr)
260 {
261 atomic64_add(nr, &vol->free_mft_records);
262 }
263
ntfs_dec_free_mft_records(struct ntfs_volume * vol,s64 nr)264 static inline void ntfs_dec_free_mft_records(struct ntfs_volume *vol, s64 nr)
265 {
266 atomic64_sub(nr, &vol->free_mft_records);
267 }
268
ntfs_set_lcn_empty_bits(struct ntfs_volume * vol,unsigned long index,u8 val,unsigned int count)269 static inline void ntfs_set_lcn_empty_bits(struct ntfs_volume *vol, unsigned long index,
270 u8 val, unsigned int count)
271 {
272 if (!NVolFreeClusterKnown(vol))
273 wait_event(vol->free_waitq, NVolFreeClusterKnown(vol));
274
275 if (val)
276 vol->lcn_empty_bits_per_page[index] -= count;
277 else
278 vol->lcn_empty_bits_per_page[index] += count;
279 }
280
ntfs_hold_dirty_clusters(struct ntfs_volume * vol,s64 nr_clusters)281 static __always_inline void ntfs_hold_dirty_clusters(struct ntfs_volume *vol, s64 nr_clusters)
282 {
283 atomic64_add(nr_clusters, &vol->dirty_clusters);
284 }
285
ntfs_release_dirty_clusters(struct ntfs_volume * vol,s64 nr_clusters)286 static __always_inline void ntfs_release_dirty_clusters(struct ntfs_volume *vol, s64 nr_clusters)
287 {
288 if (atomic64_read(&vol->dirty_clusters) < nr_clusters)
289 atomic64_set(&vol->dirty_clusters, 0);
290 else
291 atomic64_sub(nr_clusters, &vol->dirty_clusters);
292 }
293
294 s64 ntfs_available_clusters_count(struct ntfs_volume *vol, s64 nr_clusters);
295 s64 get_nr_free_clusters(struct ntfs_volume *vol);
296 #endif /* _LINUX_NTFS_VOLUME_H */
297