xref: /linux/fs/ntfs/volume.h (revision bba2c3615bd6cfee7456d1130f2e6b01b3f4e9ba)
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_zone_start: First cluster of the mft zone.
59  * @mft_zone_end: First cluster beyond the mft zone.
60  * @mft_zone_pos: Current position in the mft zone.
61  * @data1_zone_pos: Current position in the first data zone.
62  * @data2_zone_pos: Current position in the second data zone.
63  * @mft_ino: The VFS inode of $MFT.
64  * @mftbmp_ino: Attribute inode for $MFT/$BITMAP.
65  * @mftbmp_lock: Lock for serializing accesses to the mft record bitmap.
66  * @mftmirr_ino: The VFS inode of $MFTMirr.
67  * @mftmirr_size: Size of mft mirror in mft records.
68  * @logfile_ino: The VFS inode of LogFile.
69  * @lcnbmp_ino: The VFS inode of $Bitmap.
70  * @lcnbmp_lock: Lock for serializing accesses to the cluster bitmap
71  * @vol_ino: The VFS inode of $Volume.
72  * @vol_flags: Volume flags.
73  * @major_ver: Ntfs major version of volume.
74  * @minor_ver: Ntfs minor version of volume.
75  * @volume_label_lock: protects @volume_label.
76  * @volume_label: volume label.
77  * @root_ino: The VFS inode of the root directory.
78  * @secure_ino: The VFS inode of $Secure (NTFS3.0+ only, otherwise NULL).
79  * @extend_ino: The VFS inode of $Extend (NTFS3.0+ only, otherwise NULL).
80  * @nls_map: NLS (National Language Support) table.
81  * @nls_utf8: NLS table for UTF-8.
82  * @free_waitq: Wait queue for threads waiting for free clusters or MFT records.
83  * @free_clusters: Track the number of free clusters.
84  * @free_mft_records: Track the free mft records.
85  * @dirty_clusters: Number of clusters that are dirty.
86  * @sparse_compression_unit: Size of compression/sparse unit in clusters.
87  * @lcn_empty_bits_per_page: Number of empty bits per page in the LCN bitmap.
88  * @precalc_work: Work structure for background pre-calculation tasks.
89  * @preallocated_size: reallocation size (in bytes).
90  */
91 struct ntfs_volume {
92 	struct super_block *sb;
93 	s64 nr_blocks;
94 	unsigned long flags;
95 	kuid_t uid;
96 	kgid_t gid;
97 	umode_t fmask;
98 	umode_t dmask;
99 	u8 mft_zone_multiplier;
100 	u8 on_errors;
101 	errseq_t wb_err;
102 	u16 sector_size;
103 	u8 sector_size_bits;
104 	u32 cluster_size;
105 	u32 cluster_size_mask;
106 	u8 cluster_size_bits;
107 	u32 mft_record_size;
108 	u32 mft_record_size_mask;
109 	u8 mft_record_size_bits;
110 	u32 index_record_size;
111 	u32 index_record_size_mask;
112 	u8 index_record_size_bits;
113 	s64 nr_clusters;
114 	s64 mft_lcn;
115 	s64 mftmirr_lcn;
116 	u64 serial_no;
117 	u32 upcase_len;
118 	__le16 *upcase;
119 	s32 attrdef_size;
120 	struct attr_def *attrdef;
121 	s64 mft_data_pos;
122 	s64 mft_zone_start;
123 	s64 mft_zone_end;
124 	s64 mft_zone_pos;
125 	s64 data1_zone_pos;
126 	s64 data2_zone_pos;
127 	struct inode *mft_ino;
128 	struct inode *mftbmp_ino;
129 	struct rw_semaphore mftbmp_lock;
130 	struct inode *mftmirr_ino;
131 	int mftmirr_size;
132 	struct inode *logfile_ino;
133 	struct inode *lcnbmp_ino;
134 	struct rw_semaphore lcnbmp_lock;
135 	struct mutex volume_label_lock;
136 	struct inode *vol_ino;
137 	__le16 vol_flags;
138 	u8 major_ver;
139 	u8 minor_ver;
140 	unsigned char *volume_label;
141 	struct inode *root_ino;
142 	struct inode *secure_ino;
143 	struct inode *extend_ino;
144 	struct nls_table *nls_map;
145 	bool nls_utf8;
146 	wait_queue_head_t free_waitq;
147 	atomic64_t free_clusters;
148 	atomic64_t free_mft_records;
149 	atomic64_t dirty_clusters;
150 	u8 sparse_compression_unit;
151 	unsigned int *lcn_empty_bits_per_page;
152 	struct work_struct precalc_work;
153 	loff_t preallocated_size;
154 };
155 
156 /*
157  * Defined bits for the flags field in the ntfs_volume structure.
158  *
159  * NV_Errors			Volume has errors, prevent remount rw.
160  * NV_ShowSystemFiles		Return system files in ntfs_readdir().
161  * NV_CaseSensitive		Treat file names as case sensitive and
162  *				create filenames in the POSIX namespace.
163  *				Otherwise be case insensitive but still
164  *				create file names in POSIX namespace.
165  * NV_LogFileEmpty		LogFile journal is empty.
166  * NV_UsnJrnlStamped		UsnJrnl has been stamped.
167  * NV_ReadOnly			Volume is mounted read-only.
168  * NV_Compression		Volume supports compression.
169  * NV_FreeClusterKnown		Free cluster count is known and up-to-date.
170  * NV_Shutdown			Volume is in shutdown state
171  * NV_SysImmutable		Protect system files from deletion.
172  * NV_ShowHiddenFiles		Return hidden files in ntfs_readdir().
173  * NV_HideDotFiles		Hide names beginning with a dot (".").
174  * NV_CheckWindowsNames		Refuse creation/rename of files with
175  *				Windows-reserved names (CON, AUX, NUL, COM1,
176  *				LPT1, etc.) or invalid characters.
177  *
178  * NV_Discard			Issue discard/TRIM commands for freed clusters.
179  * NV_DisableSparse		Disable creation of sparse regions.
180  * NV_NativeSymlinkRel		Translate absolute Windows reparse targets (native_symlink=rel).
181  */
182 enum {
183 	NV_Errors,
184 	NV_ShowSystemFiles,
185 	NV_CaseSensitive,
186 	NV_LogFileEmpty,
187 	NV_UsnJrnlStamped,
188 	NV_ReadOnly,
189 	NV_Compression,
190 	NV_FreeClusterKnown,
191 	NV_Shutdown,
192 	NV_SysImmutable,
193 	NV_ShowHiddenFiles,
194 	NV_HideDotFiles,
195 	NV_CheckWindowsNames,
196 	NV_Discard,
197 	NV_DisableSparse,
198 	NV_NativeSymlinkRel,
199 	NV_SymlinkNative,
200 };
201 
202 /*
203  * Macro tricks to expand the NVolFoo(), NVolSetFoo(), and NVolClearFoo()
204  * functions.
205  */
206 #define DEFINE_NVOL_BIT_OPS(flag)					\
207 static inline int NVol##flag(struct ntfs_volume *vol)		\
208 {								\
209 	return test_bit(NV_##flag, &(vol)->flags);		\
210 }								\
211 static inline void NVolSet##flag(struct ntfs_volume *vol)	\
212 {								\
213 	set_bit(NV_##flag, &(vol)->flags);			\
214 }								\
215 static inline void NVolClear##flag(struct ntfs_volume *vol)	\
216 {								\
217 	clear_bit(NV_##flag, &(vol)->flags);			\
218 }
219 
220 /* Emit the ntfs volume bitops functions. */
221 DEFINE_NVOL_BIT_OPS(Errors)
222 DEFINE_NVOL_BIT_OPS(ShowSystemFiles)
223 DEFINE_NVOL_BIT_OPS(CaseSensitive)
224 DEFINE_NVOL_BIT_OPS(LogFileEmpty)
225 DEFINE_NVOL_BIT_OPS(UsnJrnlStamped)
226 DEFINE_NVOL_BIT_OPS(ReadOnly)
227 DEFINE_NVOL_BIT_OPS(Compression)
228 DEFINE_NVOL_BIT_OPS(FreeClusterKnown)
229 DEFINE_NVOL_BIT_OPS(Shutdown)
230 DEFINE_NVOL_BIT_OPS(SysImmutable)
231 DEFINE_NVOL_BIT_OPS(ShowHiddenFiles)
232 DEFINE_NVOL_BIT_OPS(HideDotFiles)
233 DEFINE_NVOL_BIT_OPS(CheckWindowsNames)
234 DEFINE_NVOL_BIT_OPS(Discard)
235 DEFINE_NVOL_BIT_OPS(DisableSparse)
236 DEFINE_NVOL_BIT_OPS(NativeSymlinkRel)
237 DEFINE_NVOL_BIT_OPS(SymlinkNative)
238 
239 static inline void ntfs_inc_free_clusters(struct ntfs_volume *vol, s64 nr)
240 {
241 	if (!NVolFreeClusterKnown(vol))
242 		wait_event(vol->free_waitq, NVolFreeClusterKnown(vol));
243 	atomic64_add(nr, &vol->free_clusters);
244 }
245 
246 static inline void ntfs_dec_free_clusters(struct ntfs_volume *vol, s64 nr)
247 {
248 	if (!NVolFreeClusterKnown(vol))
249 		wait_event(vol->free_waitq, NVolFreeClusterKnown(vol));
250 	atomic64_sub(nr, &vol->free_clusters);
251 }
252 
253 static inline void ntfs_inc_free_mft_records(struct ntfs_volume *vol, s64 nr)
254 {
255 	if (!NVolFreeClusterKnown(vol))
256 		return;
257 
258 	atomic64_add(nr, &vol->free_mft_records);
259 }
260 
261 static inline void ntfs_dec_free_mft_records(struct ntfs_volume *vol, s64 nr)
262 {
263 	if (!NVolFreeClusterKnown(vol))
264 		return;
265 
266 	atomic64_sub(nr, &vol->free_mft_records);
267 }
268 
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 
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 
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