-
Notifications
You must be signed in to change notification settings - Fork 12
/
antfs.h
334 lines (289 loc) · 8.52 KB
/
antfs.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
#ifndef _FS_NTFSAVM_H
#define _FS_NTFSAVM_H
#include <linux/version.h>
#include <linux/err.h>
#ifdef CONFIG_AVM_ENHANCED
#include <linux/avm_debug.h>
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)
static inline long IS_ERR_OR_NULL(const void *ptr)
{
return !ptr || IS_ERR_VALUE((unsigned long)ptr);
}
#endif
#define ANTFS_LOGLEVEL_EMER 0
#define ANTFS_LOGLEVEL_CRIT 1
#define ANTFS_LOGLEVEL_ERR 2
#define ANTFS_LOGLEVEL_ERR_EXT 3
#define ANTFS_LOGLEVEL_WARN 4
#define ANTFS_LOGLEVEL_INFO 5
#define ANTFS_LOGLEVEL_DBG 6
#ifndef CONFIG_AVM_ENHANCED
#define avm_logger_printk_ratelimited(logger, fmt, ...)
#endif
/**
* Make sure to set loglevel to at least 'ANTFS_LOGLEVEL_CRIT' if you want to
* have debug information in a specific file.
*/
#ifndef ANTFS_LOGLEVEL
# define ANTFS_LOGLEVEL ANTFS_LOGLEVEL_DEFAULT
#endif
#if (ANTFS_LOGLEVEL >= ANTFS_LOGLEVEL_ERR_EXT)
#define antfs_pr_err(fmt, ...) pr_err(fmt, ##__VA_ARGS__)
#define antfs_pr_warn(fmt, ...) pr_warn(fmt, ##__VA_ARGS__)
#define antfs_pr_info(fmt, ...) pr_info(fmt, ##__VA_ARGS__)
#else
#ifdef pr_err_ratelimited
#include <linux/ratelimit.h>
#define antfs_pr_err(fmt, ...) \
pr_err_ratelimited(fmt, ##__VA_ARGS__)
#define antfs_pr_warn(fmt, ...) \
pr_warn_ratelimited(fmt, ##__VA_ARGS__)
#define antfs_pr_info(fmt, ...) \
pr_info_ratelimited(fmt, ##__VA_ARGS__)
#else
#define antfs_pr_err(fmt, ...) \
do { \
if (printk_ratelimit()) \
pr_err(fmt, ##__VA_ARGS__); \
} while (0)
#define antfs_pr_warn(fmt, ...) \
do { \
if (printk_ratelimit()) \
pr_warn(fmt, ##__VA_ARGS__); \
} while (0)
#define antfs_pr_info(fmt, ...) \
do { \
if (printk_ratelimit()) \
pr_info(fmt, ##__VA_ARGS__); \
} while (0)
#define antfs_pr_debug(fmt, ...) \
do { \
if (printk_ratelimit()) \
pr_debug(fmt, ##__VA_ARGS__); \
} while (0)
#endif
#endif
#if (ANTFS_LOGLEVEL >= ANTFS_LOGLEVEL_CRIT)
#define antfs_log_critical(fmt, ...) \
pr_err("[%s] <CRITICAL> " fmt "\n", __func__, ##__VA_ARGS__)
#else
#define antfs_log_critical(fmt, ...)
#endif
#if (ANTFS_LOGLEVEL >= ANTFS_LOGLEVEL_ERR_EXT)
#define antfs_log_error_ext(fmt, ...) \
do { \
pr_err("[%s] <ERROR> " fmt "\n", __func__, \
##__VA_ARGS__); \
dump_stack(); \
} while (0)
#elif (ANTFS_LOGLEVEL == ANTFS_LOGLEVEL_ERR)
#define antfs_log_error_ext(fmt, ...) \
antfs_pr_err("[%s] <ERROR> " fmt "\n", __func__, \
##__VA_ARGS__)
#else
#define antfs_log_error_ext(fmt, ...)
#endif
#if (ANTFS_LOGLEVEL >= ANTFS_LOGLEVEL_ERR)
#define antfs_log_error(fmt, ...) \
antfs_pr_err("[%s] <ERROR> " fmt "\n", __func__, \
##__VA_ARGS__)
#else
#define antfs_log_error(fmt, ...)
#endif
#if (ANTFS_LOGLEVEL >= ANTFS_LOGLEVEL_WARN)
#define antfs_log_warning(fmt, ...) \
antfs_pr_warn("[%s] <WARNING> " fmt "\n", __func__, \
##__VA_ARGS__)
#else
#define antfs_log_warning(fmt, ...)
#endif
#if (ANTFS_LOGLEVEL >= ANTFS_LOGLEVEL_INFO)
#define antfs_log_info(fmt, ...) \
pr_info("[%s] <INFO> " fmt "\n", __func__, ##__VA_ARGS__)
#else
#define antfs_log_info(fmt, ...)
#endif
#if (ANTFS_LOGLEVEL >= ANTFS_LOGLEVEL_DBG)
#define antfs_log_debug(fmt, ...) \
pr_debug("[%s] <DEBUG> " fmt "\n", __func__, ##__VA_ARGS__)
#define antfs_debug(fmt, ...) \
pr_debug("[%s] <DEBUG> " fmt "\n", __func__, ##__VA_ARGS__)
#else
#define antfs_log_debug(fmt, ...)
#define antfs_debug(fmt, ...)
#endif
#if (ANTFS_LOGLEVEL >= ANTFS_LOGLEVEL_DBG)
#define antfs_log_enter(fmt, ...) \
pr_debug("[%s] (%pS) --> " fmt "\n", __func__,\
__builtin_return_address(0), ##__VA_ARGS__)
#else
#define antfs_log_enter(fmt, ...)
#endif
#if (ANTFS_LOGLEVEL >= ANTFS_LOGLEVEL_DBG)
#define antfs_log_leave(fmt, ...) \
pr_debug("[%s] (%pS) <-- " fmt "\n\n", __func__,\
__builtin_return_address(0), ##__VA_ARGS__)
#else
#define antfs_log_leave(fmt, ...)
#endif
/* macro that calls avm_logger_printk_ratelimited and antfs_log_critical */
#define antfs_logger(logger, fmt, ...) \
do { \
avm_logger_printk_ratelimited(logger, "[%s] " fmt "\n", \
__func__, ##__VA_ARGS__); \
antfs_log_critical(fmt, ##__VA_ARGS__); \
} while (0)
/*--- #define ANTFS_EARLY_BLALLOC ---*/
#include <linux/fs.h>
#include <linux/mount.h>
#include <linux/wait.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/mm.h>
#include <linux/backing-dev.h>
#include <linux/mutex.h>
#include <linux/rwsem.h>
#include <linux/rbtree.h>
#include <linux/poll.h>
#include <linux/workqueue.h>
#include <linux/spinlock.h>
#include <linux/buffer_head.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)
#include <linux/kernel.h>
#else
#include <linux/printk.h>
#endif
#include "inode.h"
#include "lcnalloc.h"
/** Do not allocate MFT records smaller than 24. They are special... */
#define RESERVED_MFT_RECORDS 24
/** If we need to extend MFT $DATA, allocate 1 << this number of MFT records at
* once. This is to reduce MFT fragmentation.
*
* Note: ntfs-3g hardcoded 1 << 4 for this purpose in
* @ntfs_mft_data_extend_allocation.
*/
#define MFT_DATA_BURST_ALLOC_SHIFT 7
#define IN_KERNEL_VERSION(a, b) ( \
(LINUX_VERSION_CODE >= KERNEL_VERSION(a, b, 0)) && \
(LINUX_VERSION_CODE < KERNEL_VERSION(a, b, 256)))
#define ANTFS_DIRENT_ALIGN(x) (((x) + sizeof(__u64) - 1) & ~(sizeof(__u64) - 1))
enum {
ATIME_ENABLED,
ATIME_DISABLED,
ATIME_RELATIVE
};
enum antfs_bh_state_bits {
/** Marks a block that replaces a hole. */
BH_Zeronew = BH_PrivateStart,
};
BUFFER_FNS(Zeronew, zeronew)
TAS_BUFFER_FNS(Zeronew, zeronew)
struct antfs_dirent {
unsigned long ino;
unsigned int type;
unsigned long name_len;
unsigned long offset;
char *name[0];
};
/**
* ni->ni_lock mutex nesting subclasses for the lock validator:
*
* 0: Target of current operation
* 1: parent inode
* 2: another parent inode (e.g. for antfs_rename)
*
* Locking order is normal -> parent -> parent2
*/
enum antfs_inode_mutex_lock_class {
NI_MUTEX_NORMAL,
NI_MUTEX_PARENT,
NI_MUTEX_PARENT2
};
struct antfs_filler {
int (*filldir) (void *buf, const char *name, int name_len,
loff_t offset, u64 ino, unsigned int d_type);
struct dir_context *ctx;
struct file *file;
void *buffer;
};
struct antfs_sb_info {
struct ntfs_volume *vol; /* NTFS volume structure */
struct super_block *sb; /* Super block */
const char *dev; /* Device name */
/* Mount flags */
unsigned int atime; /* 0:ENABLED, 1:DISABLED, 2:RELATIVE */
unsigned char silent;
unsigned char recover;
unsigned char blkdev;
unsigned char ro;
unsigned char hiberfile;
unsigned char utf8;
unsigned short umask;
unsigned int uid;
unsigned int gid;
unsigned char inherit; /* for permission checking */
struct SECURITY_CONTEXT *security;
char *usermap_path;
#ifdef CONFIG_AVM_ENHANCED
struct _logger_priv *logger;
#endif
};
struct antfs_inode_info {
struct inode inode;
struct ntfs_inode ni;
struct ntfs_attr na;
};
static inline struct antfs_sb_info *ANTFS_SB(struct super_block *sb)
{
return (struct antfs_sb_info *)sb->s_fs_info;
}
static inline struct ntfs_inode *ANTFS_NI(struct inode *inode)
{
return &(container_of(inode, struct antfs_inode_info, inode)->ni);
}
static inline struct inode *ANTFS_I(struct ntfs_inode *ni)
{
return &(container_of(ni, struct antfs_inode_info, ni)->inode);
}
static inline struct ntfs_attr *ANTFS_NA(struct ntfs_inode *ni)
{
return &(container_of(ni, struct antfs_inode_info, ni)->na);
}
/**
* Initialize ANTFS
*/
extern struct kmem_cache *antfs_inode_cachep;
/**
* ANTFS functions
*/
void antfs_fill_super_operations(struct super_block *sb);
void antfs_fill_dentry_operations(struct super_block *sb);
int antfs_inode_setup_root(struct super_block *sb);
void antfs_inode_init_common(struct inode *inode);
void antfs_inode_init_dir(struct inode *inode);
void antfs_inode_init_file(struct inode *inode);
void antfs_inode_init_symlink(struct inode *inode);
void antfs_parse_options(struct antfs_sb_info *sbi, char *data);
int antfs_inode_init(struct inode *inode);
void antfs_sbi_destroy(struct antfs_sb_info *sbi);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
int antfs_fsync(struct file *filp, struct dentry *dentry, int datasync);
#elif LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
int antfs_fsync(struct file *filp, int datasync);
#else
int antfs_fsync(struct file *filp, loff_t start, loff_t end, int datasync);
#endif
int antfs_get_block(struct inode *inode, sector_t iblock,
struct buffer_head *bh_result, int create);
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0)
#define file_inode(file) ((file)->f_path.dentry->d_inode)
#endif
#if KERNEL_VERSION(3, 2, 0) > LINUX_VERSION_CODE
static inline void set_nlink(struct inode *inode, unsigned int nlink)
{
inode->i_nlink = nlink;
}
#endif
#endif /* _FS_NTFSAVM_H */