0aae32065b34310dc565a826a4f493bd7ff8a391
[reactos.git] / reactos / drivers / filesystems / btrfs / btrfs_drv.h
1 /* Copyright (c) Mark Harmstone 2016
2 *
3 * This file is part of WinBtrfs.
4 *
5 * WinBtrfs is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public Licence as published by
7 * the Free Software Foundation, either version 3 of the Licence, or
8 * (at your option) any later version.
9 *
10 * WinBtrfs is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public Licence for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public Licence
16 * along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
17
18 #ifndef BTRFS_DRV_H_DEFINED
19 #define BTRFS_DRV_H_DEFINED
20
21 #ifndef __REACTOS__
22 #undef _WIN32_WINNT
23 #undef NTDDI_VERSION
24
25 #define _WIN32_WINNT 0x0600
26 #define NTDDI_VERSION 0x06010000 // Win 7
27 #define _CRT_SECURE_NO_WARNINGS
28 #endif /* __REACTOS__ */
29
30 #include <ntifs.h>
31 #include <ntddk.h>
32 #ifdef __REACTOS__
33 #include <ntdddisk.h>
34 #endif /* __REACTOS__ */
35 #include <mountmgr.h>
36 #ifdef __REACTOS__
37 #include <rtlfuncs.h>
38 #include <iotypes.h>
39 #include <pseh/pseh2.h>
40 #endif /* __REACTOS__ */
41 //#include <windows.h>
42 #include <windef.h>
43 #include <wdm.h>
44 #include <stdio.h>
45 #include <stdarg.h>
46 #include <stddef.h>
47 #include "btrfs.h"
48
49 #ifdef _DEBUG
50 // #define DEBUG_FCB_REFCOUNTS
51 // #define DEBUG_LONG_MESSAGES
52 #define DEBUG_PARANOID
53 #endif
54
55 #define BTRFS_NODE_TYPE_CCB 0x2295
56 #define BTRFS_NODE_TYPE_FCB 0x2296
57
58 #define ALLOC_TAG 0x7442484D //'MHBt'
59
60 #define STDCALL __stdcall
61
62 #define UID_NOBODY 65534
63 #define GID_NOBODY 65534
64
65 #define EA_NTACL "security.NTACL"
66 #define EA_NTACL_HASH 0x45922146
67
68 #define EA_DOSATTRIB "user.DOSATTRIB"
69 #define EA_DOSATTRIB_HASH 0x914f9939
70
71 #define EA_REPARSE "system.reparse"
72 #define EA_REPARSE_HASH 0x786f6167
73
74 #define READ_AHEAD_GRANULARITY 0x10000 // 64 KB
75
76 #ifdef _MSC_VER
77 #define try __try
78 #define except __except
79 #define finally __finally
80 #else
81 #define try if (1)
82 #define except(x) if (0 && (x))
83 #define finally if (1)
84 #endif
85
86 // #pragma pack(push, 1)
87
88 struct device_extension;
89
90 typedef struct {
91 PDEVICE_OBJECT devobj;
92 BTRFS_UUID fsuuid;
93 BTRFS_UUID devuuid;
94 UINT64 devnum;
95 UNICODE_STRING devpath;
96 BOOL processed;
97 LIST_ENTRY list_entry;
98 } volume;
99
100 typedef struct _fcb_nonpaged {
101 FAST_MUTEX HeaderMutex;
102 SECTION_OBJECT_POINTERS segment_object;
103 ERESOURCE resource;
104 ERESOURCE paging_resource;
105 } fcb_nonpaged;
106
107 struct _root;
108
109 typedef struct _fcb {
110 FSRTL_ADVANCED_FCB_HEADER Header;
111 struct _fcb_nonpaged* nonpaged;
112 LONG refcount;
113 LONG open_count;
114 struct _device_extension* Vcb;
115 struct _root* subvol;
116 UINT64 inode;
117 UINT8 type;
118 INODE_ITEM inode_item;
119 SECURITY_DESCRIPTOR* sd;
120 FILE_LOCK lock;
121 BOOL deleted;
122 PKTHREAD lazy_writer_thread;
123 ULONG atts;
124 SHARE_ACCESS share_access;
125 WCHAR* debug_desc;
126
127 BOOL ads;
128 UINT32 adssize;
129 UINT32 adshash;
130 ANSI_STRING adsxattr;
131
132 LIST_ENTRY list_entry;
133 } fcb;
134
135 struct _file_ref;
136
137 typedef struct _file_ref {
138 fcb* fcb;
139 UNICODE_STRING filepart;
140 ANSI_STRING utf8;
141 UNICODE_STRING full_filename;
142 ULONG name_offset;
143 BOOL delete_on_close;
144 BOOL deleted;
145 LIST_ENTRY children;
146 LONG refcount;
147 struct _file_ref* parent;
148 WCHAR* debug_desc;
149
150 LIST_ENTRY list_entry;
151 } file_ref;
152
153 typedef struct _ccb {
154 USHORT NodeType;
155 CSHORT NodeSize;
156 ULONG disposition;
157 ULONG options;
158 UINT64 query_dir_offset;
159 // char* query_string;
160 UNICODE_STRING query_string;
161 BOOL has_wildcard;
162 BOOL specific_file;
163 ACCESS_MASK access;
164 file_ref* fileref;
165 } ccb;
166
167 // typedef struct _log_to_phys {
168 // UINT64 address;
169 // UINT64 size;
170 // UINT64 physaddr;
171 // UINT32 sector_size;
172 // struct _log_to_phys* next;
173 // } log_to_phys;
174
175 struct _device_extension;
176
177 // enum tree_holder_status {
178 // tree_holder_unloaded,
179 // tree_holder_loading,
180 // tree_holder_loaded,
181 // tree_holder_unloading
182 // };
183
184 // typedef struct {
185 // enum tree_holder_status status;
186 // KSPIN_LOCK spin_lock;
187 // ERESOURCE lock;
188 // } tree_holder_nonpaged;
189
190 typedef struct {
191 UINT64 address;
192 UINT64 generation;
193 struct _tree* tree;
194 // tree_holder_nonpaged* nonpaged;
195 } tree_holder;
196
197 typedef struct _tree_data {
198 KEY key;
199 LIST_ENTRY list_entry;
200 BOOL ignore;
201 BOOL inserted;
202
203 union {
204 tree_holder treeholder;
205
206 struct {
207 UINT32 size;
208 UINT8* data;
209 };
210 };
211 } tree_data;
212
213 // typedef struct _tree_nonpaged {
214 // ERESOURCE load_tree_lock;
215 // } tree_nonpaged;
216
217 typedef struct _tree {
218 // UINT64 address;
219 // UINT8 level;
220 tree_header header;
221 BOOL has_address;
222 UINT32 size;
223 struct _device_extension* Vcb;
224 struct _tree* parent;
225 tree_data* paritem;
226 struct _root* root;
227 // tree_nonpaged* nonpaged;
228 LIST_ENTRY itemlist;
229 LIST_ENTRY list_entry;
230 UINT64 new_address;
231 BOOL has_new_address;
232 UINT64 flags;
233 BOOL write;
234 } tree;
235
236 typedef struct {
237 // KSPIN_LOCK load_tree_lock;
238 ERESOURCE load_tree_lock;
239 } root_nonpaged;
240
241 typedef struct _root {
242 UINT64 id;
243 tree_holder treeholder;
244 root_nonpaged* nonpaged;
245 UINT64 lastinode;
246 ROOT_ITEM root_item;
247 UNICODE_STRING path;
248 LIST_ENTRY fcbs;
249 LIST_ENTRY list_entry;
250 } root;
251
252 typedef struct {
253 tree* tree;
254 tree_data* item;
255 } traverse_ptr;
256
257 typedef struct _root_cache {
258 root* root;
259 struct _root_cache* next;
260 } root_cache;
261
262 #define SPACE_TYPE_FREE 0
263 #define SPACE_TYPE_USED 1
264 #define SPACE_TYPE_DELETING 2
265 #define SPACE_TYPE_WRITING 3
266
267 typedef struct {
268 UINT64 offset;
269 UINT64 size;
270 UINT8 type;
271 LIST_ENTRY list_entry;
272 } space;
273
274 typedef struct {
275 UINT64 address;
276 UINT64 size;
277 BOOL provisional;
278 LIST_ENTRY listentry;
279 } disk_hole;
280
281 typedef struct {
282 PDEVICE_OBJECT devobj;
283 DEV_ITEM devitem;
284 BOOL removable;
285 ULONG change_count;
286 LIST_ENTRY disk_holes;
287 } device;
288
289 typedef struct {
290 CHUNK_ITEM* chunk_item;
291 UINT32 size;
292 UINT64 offset;
293 UINT64 used;
294 UINT32 oldused;
295 BOOL space_changed;
296 device** devices;
297 UINT64 cache_size;
298 UINT64 cache_inode;
299 LIST_ENTRY space;
300 LIST_ENTRY list_entry;
301 } chunk;
302
303 typedef struct {
304 KEY key;
305 void* data;
306 USHORT size;
307 LIST_ENTRY list_entry;
308 } sys_chunk;
309
310 typedef struct _device_extension {
311 device* devices;
312 // DISK_GEOMETRY geometry;
313 UINT64 length;
314 superblock superblock;
315 // WCHAR label[MAX_LABEL_SIZE];
316 BOOL readonly;
317 BOOL removing;
318 fcb* volume_fcb;
319 file_ref* root_fileref;
320 ERESOURCE DirResource;
321 KSPIN_LOCK FcbListLock;
322 ERESOURCE fcb_lock;
323 ERESOURCE load_lock;
324 ERESOURCE tree_lock;
325 PNOTIFY_SYNC NotifySync;
326 LIST_ENTRY DirNotifyList;
327 LONG tree_lock_counter;
328 LONG open_trees;
329 ULONG write_trees;
330 // ERESOURCE LogToPhysLock;
331 // UINT64 chunk_root_phys_addr;
332 UINT64 root_tree_phys_addr;
333 // log_to_phys* log_to_phys;
334 LIST_ENTRY roots;
335 LIST_ENTRY drop_roots;
336 root* chunk_root;
337 root* root_root;
338 root* extent_root;
339 root* checksum_root;
340 root* dev_root;
341 root* uuid_root;
342 BOOL log_to_phys_loaded;
343 UINT32 max_inline;
344 LIST_ENTRY sys_chunks;
345 LIST_ENTRY chunks;
346 LIST_ENTRY trees;
347 HANDLE flush_thread_handle;
348 LIST_ENTRY list_entry;
349 } device_extension;
350
351 typedef struct {
352 LIST_ENTRY listentry;
353 PSID sid;
354 UINT32 uid;
355 } uid_map;
356
357 typedef struct {
358 LIST_ENTRY list_entry;
359 UINT64 key;
360 } ordered_list;
361
362 typedef struct {
363 ordered_list ol;
364 ULONG length;
365 UINT32* checksums;
366 BOOL deleted;
367 } changed_sector;
368
369 enum write_tree_status {
370 WriteTreeStatus_Pending,
371 WriteTreeStatus_Success,
372 WriteTreeStatus_Error,
373 WriteTreeStatus_Cancelling,
374 WriteTreeStatus_Cancelled
375 };
376
377 struct write_tree_context;
378
379 typedef struct {
380 struct write_tree_context* context;
381 UINT8* buf;
382 device* device;
383 PIRP Irp;
384 IO_STATUS_BLOCK iosb;
385 enum write_tree_status status;
386 LIST_ENTRY list_entry;
387 } write_tree_stripe;
388
389 typedef struct {
390 KEVENT Event;
391 LIST_ENTRY stripes;
392 } write_tree_context;
393
394 // #pragma pack(pop)
395
396 static __inline void init_tree_holder(tree_holder* th) {
397 // th->nonpaged = ExAllocatePoolWithTag(NonPagedPool, sizeof(tree_holder_nonpaged), ALLOC_TAG);
398 // KeInitializeSpinLock(&th->nonpaged->spin_lock);
399 // ExInitializeResourceLite(&th->nonpaged->lock); // FIXME - delete this later
400 }
401
402 static __inline void* map_user_buffer(PIRP Irp) {
403 if (!Irp->MdlAddress) {
404 return Irp->UserBuffer;
405 } else {
406 return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
407 }
408 }
409
410 static __inline UINT64 unix_time_to_win(BTRFS_TIME* t) {
411 return (t->seconds * 10000000) + (t->nanoseconds / 100) + 116444736000000000;
412 }
413
414 static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME* out) {
415 ULONGLONG l = t.QuadPart - 116444736000000000;
416
417 out->seconds = l / 10000000;
418 out->nanoseconds = (l % 10000000) * 100;
419 }
420
421 static __inline void insert_into_ordered_list(LIST_ENTRY* list, ordered_list* ins) {
422 LIST_ENTRY* le = list->Flink;
423 ordered_list* ol;
424
425 while (le != list) {
426 ol = (ordered_list*)le;
427
428 if (ol->key > ins->key) {
429 le->Blink->Flink = &ins->list_entry;
430 ins->list_entry.Blink = le->Blink;
431 le->Blink = &ins->list_entry;
432 ins->list_entry.Flink = le;
433 return;
434 }
435
436 le = le->Flink;
437 }
438
439 InsertTailList(list, &ins->list_entry);
440 }
441
442 // in btrfs.c
443 device* find_device_from_uuid(device_extension* Vcb, BTRFS_UUID* uuid);
444 ULONG sector_align( ULONG NumberToBeAligned, ULONG Alignment );
445 int keycmp(const KEY* key1, const KEY* key2);
446 ULONG STDCALL get_file_attributes(device_extension* Vcb, INODE_ITEM* ii, root* r, UINT64 inode, UINT8 type, BOOL dotfile, BOOL ignore_xa);
447 BOOL STDCALL get_xattr(device_extension* Vcb, root* subvol, UINT64 inode, char* name, UINT32 crc32, UINT8** data, UINT16* datalen);
448 NTSTATUS STDCALL set_xattr(device_extension* Vcb, root* subvol, UINT64 inode, char* name, UINT32 crc32, UINT8* data, UINT16 datalen, LIST_ENTRY* rollback);
449 BOOL STDCALL delete_xattr(device_extension* Vcb, root* subvol, UINT64 inode, char* name, UINT32 crc32, LIST_ENTRY* rollback);
450 void _free_fcb(fcb* fcb, const char* func, const char* file, unsigned int line);
451 void _free_fileref(file_ref* fr, const char* func, const char* file, unsigned int line);
452 BOOL STDCALL get_last_inode(device_extension* Vcb, root* r);
453 NTSTATUS add_dir_item(device_extension* Vcb, root* subvol, UINT64 inode, UINT32 crc32, DIR_ITEM* di, ULONG disize, LIST_ENTRY* rollback);
454 NTSTATUS delete_dir_item(device_extension* Vcb, root* subvol, UINT64 parinode, UINT32 crc32, PANSI_STRING utf8, LIST_ENTRY* rollback);
455 UINT64 find_next_dir_index(device_extension* Vcb, root* subvol, UINT64 inode);
456 NTSTATUS delete_inode_ref(device_extension* Vcb, root* subvol, UINT64 inode, UINT64 parinode, PANSI_STRING utf8, UINT64* index, LIST_ENTRY* rollback);
457 NTSTATUS delete_fileref(file_ref* fileref, PFILE_OBJECT FileObject, LIST_ENTRY* rollback);
458 fcb* create_fcb();
459 file_ref* create_fileref();
460 void protect_superblocks(device_extension* Vcb, chunk* c);
461 BOOL is_top_level(PIRP Irp);
462 NTSTATUS create_root(device_extension* Vcb, UINT64 id, root** rootptr, BOOL no_tree, UINT64 offset, LIST_ENTRY* rollback);
463 void STDCALL uninit(device_extension* Vcb, BOOL flush);
464 NTSTATUS STDCALL dev_ioctl(PDEVICE_OBJECT DeviceObject, ULONG ControlCode, PVOID InputBuffer,
465 ULONG InputBufferSize, PVOID OutputBuffer, ULONG OutputBufferSize, BOOLEAN Override, IO_STATUS_BLOCK* iosb);
466 BOOL is_file_name_valid(PUNICODE_STRING us);
467 void send_notification_fileref(file_ref* fileref, ULONG filter_match, ULONG action);
468 WCHAR* file_desc(PFILE_OBJECT FileObject);
469 WCHAR* file_desc_fileref(file_ref* fileref);
470
471 #ifdef _MSC_VER
472 #define funcname __FUNCTION__
473 #else
474 #define funcname __func__
475 #endif
476
477 // FIXME - we probably shouldn't be moving funcname etc. around if we're not printing debug messages
478 #define free_fcb(fcb) _free_fcb(fcb, funcname, __FILE__, __LINE__)
479 #define free_fileref(fileref) _free_fileref(fileref, funcname, __FILE__, __LINE__)
480
481 #ifdef _DEBUG
482
483 extern BOOL log_started;
484 extern UINT32 debug_log_level;
485
486 #ifdef DEBUG_LONG_MESSAGES
487
488 #define MSG(fn, file, line, s, level, ...) (!log_started || level <= debug_log_level) ? _debug_message(fn, file, line, s, ##__VA_ARGS__) : 0
489
490 #define TRACE(s, ...) MSG(funcname, __FILE__, __LINE__, s, 3, ##__VA_ARGS__)
491 #define WARN(s, ...) MSG(funcname, __FILE__, __LINE__, s, 2, ##__VA_ARGS__)
492 #define FIXME(s, ...) MSG(funcname, __FILE__, __LINE__, s, 1, ##__VA_ARGS__)
493 #define ERR(s, ...) MSG(funcname, __FILE__, __LINE__, s, 1, ##__VA_ARGS__)
494
495 void STDCALL _debug_message(const char* func, const char* file, unsigned int line, char* s, ...);
496
497 #else
498
499 #define MSG(fn, s, level, ...) (!log_started || level <= debug_log_level) ? _debug_message(fn, s, ##__VA_ARGS__) : 0
500
501 #define TRACE(s, ...) MSG(funcname, s, 3, ##__VA_ARGS__)
502 #define WARN(s, ...) MSG(funcname, s, 2, ##__VA_ARGS__)
503 #define FIXME(s, ...) MSG(funcname, s, 1, ##__VA_ARGS__)
504 #define ERR(s, ...) MSG(funcname, s, 1, ##__VA_ARGS__)
505
506 void STDCALL _debug_message(const char* func, char* s, ...);
507
508 #endif
509
510 #else
511
512 #define TRACE(s, ...)
513 #define WARN(s, ...)
514 #ifndef __REACTOS__
515 #define FIXME(s, ...) DbgPrint("Btrfs FIXME : " funcname " : " s, ##__VA_ARGS__)
516 #define ERR(s, ...) DbgPrint("Btrfs ERR : " funcname " : " s, ##__VA_ARGS__)
517 #else
518 #define FIXME(s, ...) DbgPrint("Btrfs FIXME : %s : " s, funcname, ##__VA_ARGS__)
519 #define ERR(s, ...) DbgPrint("Btrfs ERR : %s : " s, funcname, ##__VA_ARGS__)
520 #endif
521
522 #endif
523
524 static __inline void increase_chunk_usage(chunk* c, UINT64 delta) {
525 c->used += delta;
526
527 TRACE("increasing size of chunk %llx by %llx\n", c->offset, delta);
528 }
529
530 // in fastio.c
531 void STDCALL init_fast_io_dispatch(FAST_IO_DISPATCH** fiod);
532
533 // in crc32c.c
534 UINT32 STDCALL calc_crc32c(UINT32 seed, UINT8* msg, ULONG msglen);
535
536 // in treefuncs.c
537 NTSTATUS STDCALL _find_item(device_extension* Vcb, root* r, traverse_ptr* tp, const KEY* searchkey, BOOL ignore, const char* func, const char* file, unsigned int line);
538 BOOL STDCALL _find_next_item(device_extension* Vcb, const traverse_ptr* tp, traverse_ptr* next_tp, BOOL ignore, const char* func, const char* file, unsigned int line);
539 BOOL STDCALL _find_prev_item(device_extension* Vcb, const traverse_ptr* tp, traverse_ptr* prev_tp, BOOL ignore, const char* func, const char* file, unsigned int line);
540 void STDCALL free_trees(device_extension* Vcb);
541 BOOL STDCALL insert_tree_item(device_extension* Vcb, root* r, UINT64 obj_id, UINT8 obj_type, UINT64 offset, void* data, UINT32 size, traverse_ptr* ptp, LIST_ENTRY* rollback);
542 void STDCALL delete_tree_item(device_extension* Vcb, traverse_ptr* tp, LIST_ENTRY* rollback);
543 tree* STDCALL _free_tree(tree* t, const char* func, const char* file, unsigned int line);
544 NTSTATUS STDCALL _load_tree(device_extension* Vcb, UINT64 addr, root* r, tree** pt, const char* func, const char* file, unsigned int line);
545 NTSTATUS STDCALL _do_load_tree(device_extension* Vcb, tree_holder* th, root* r, tree* t, tree_data* td, BOOL* loaded, const char* func, const char* file, unsigned int line);
546 void clear_rollback(LIST_ENTRY* rollback);
547 void do_rollback(device_extension* Vcb, LIST_ENTRY* rollback);
548 void free_trees_root(device_extension* Vcb, root* r);
549 NTSTATUS STDCALL read_tree(device_extension* Vcb, UINT64 addr, UINT8* buf);
550
551 #define find_item(Vcb, r, tp, searchkey, ignore) _find_item(Vcb, r, tp, searchkey, ignore, funcname, __FILE__, __LINE__)
552 #define find_next_item(Vcb, tp, next_tp, ignore) _find_next_item(Vcb, tp, next_tp, ignore, funcname, __FILE__, __LINE__)
553 #define find_prev_item(Vcb, tp, prev_tp, ignore) _find_prev_item(Vcb, tp, prev_tp, ignore, funcname, __FILE__, __LINE__)
554 #define free_tree(t) _free_tree(t, funcname, __FILE__, __LINE__)
555 #define load_tree(t, addr, r, pt) _load_tree(t, addr, r, pt, funcname, __FILE__, __LINE__)
556 #define do_load_tree(Vcb, th, r, t, td, loaded) _do_load_tree(Vcb, th, r, t, td, loaded, funcname, __FILE__, __LINE__)
557
558 // in search.c
559 void STDCALL look_for_vols(LIST_ENTRY* volumes);
560
561 // in cache.c
562 NTSTATUS STDCALL init_cache();
563 void STDCALL free_cache();
564 extern CACHE_MANAGER_CALLBACKS* cache_callbacks;
565
566 // in write.c
567 NTSTATUS STDCALL do_write(device_extension* Vcb, LIST_ENTRY* rollback);
568 NTSTATUS write_file(PDEVICE_OBJECT DeviceObject, PIRP Irp);
569 NTSTATUS write_file2(device_extension* Vcb, PIRP Irp, LARGE_INTEGER offset, void* buf, ULONG* length, BOOL paging_io, BOOL no_cache, LIST_ENTRY* rollback);
570 NTSTATUS truncate_file(fcb* fcb, UINT64 end, LIST_ENTRY* rollback);
571 NTSTATUS extend_file(fcb* fcb, file_ref* fileref, UINT64 end, BOOL prealloc, LIST_ENTRY* rollback);
572 NTSTATUS excise_extents_inode(device_extension* Vcb, root* subvol, UINT64 inode, INODE_ITEM* ii, UINT64 start_data, UINT64 end_data, LIST_ENTRY* changed_sector_list, LIST_ENTRY* rollback);
573 NTSTATUS excise_extents(device_extension* Vcb, fcb* fcb, UINT64 start_data, UINT64 end_data, LIST_ENTRY* changed_sector_list, LIST_ENTRY* rollback);
574 void update_checksum_tree(device_extension* Vcb, LIST_ENTRY* changed_sector_list, LIST_ENTRY* rollback);
575 NTSTATUS insert_sparse_extent(device_extension* Vcb, root* r, UINT64 inode, UINT64 start, UINT64 length, LIST_ENTRY* rollback);
576 chunk* get_chunk_from_address(device_extension* Vcb, UINT64 address);
577 void add_to_space_list(chunk* c, UINT64 offset, UINT64 size, UINT8 type);
578 NTSTATUS consider_write(device_extension* Vcb);
579 BOOL insert_extent_chunk_inode(device_extension* Vcb, root* subvol, UINT64 inode, INODE_ITEM* inode_item, chunk* c, UINT64 start_data,
580 UINT64 length, BOOL prealloc, void* data, LIST_ENTRY* changed_sector_list, LIST_ENTRY* rollback);
581 chunk* alloc_chunk(device_extension* Vcb, UINT64 flags, LIST_ENTRY* rollback);
582 NTSTATUS STDCALL write_data(device_extension* Vcb, UINT64 address, void* data, UINT32 length);
583 NTSTATUS write_tree(device_extension* Vcb, UINT64 addr, UINT8* data, write_tree_context* wtc);
584 void free_write_tree_stripes(write_tree_context* wtc);
585 NTSTATUS get_tree_new_address(device_extension* Vcb, tree* t, LIST_ENTRY* rollback);
586
587 // in dirctrl.c
588 NTSTATUS STDCALL drv_directory_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
589 ULONG STDCALL get_reparse_tag(device_extension* Vcb, root* subvol, UINT64 inode, UINT8 type);
590
591 // in security.c
592 NTSTATUS STDCALL drv_query_security(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
593 NTSTATUS STDCALL drv_set_security(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
594 void fcb_get_sd(fcb* fcb, struct _fcb* parent);
595 // UINT32 STDCALL get_uid();
596 void add_user_mapping(WCHAR* sidstring, ULONG sidstringlength, UINT32 uid);
597 UINT32 sid_to_uid(PSID sid);
598 NTSTATUS fcb_get_new_sd(fcb* fcb, file_ref* fileref, ACCESS_STATE* as);
599
600 // in fileinfo.c
601 NTSTATUS STDCALL drv_set_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
602 NTSTATUS STDCALL drv_query_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
603 NTSTATUS add_inode_ref(device_extension* Vcb, root* subvol, UINT64 inode, UINT64 parinode, UINT64 index, PANSI_STRING utf8, LIST_ENTRY* rollback);
604 NTSTATUS delete_root_ref(device_extension* Vcb, UINT64 subvolid, UINT64 parsubvolid, UINT64 parinode, PANSI_STRING utf8, UINT64* index, LIST_ENTRY* rollback);
605 NTSTATUS STDCALL update_root_backref(device_extension* Vcb, UINT64 subvolid, UINT64 parsubvolid, LIST_ENTRY* rollback);
606 BOOL has_open_children(file_ref* fileref);
607 NTSTATUS STDCALL stream_set_end_of_file_information(device_extension* Vcb, UINT64 end, fcb* fcb, file_ref* fileref, PFILE_OBJECT FileObject, BOOL advance_only, LIST_ENTRY* rollback);
608
609 // in reparse.c
610 NTSTATUS get_reparse_point(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject, void* buffer, DWORD buflen, DWORD* retlen);
611 NTSTATUS set_reparse_point(PDEVICE_OBJECT DeviceObject, PIRP Irp);
612 NTSTATUS delete_reparse_point(PDEVICE_OBJECT DeviceObject, PIRP Irp);
613
614 // in create.c
615 NTSTATUS STDCALL drv_create(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
616 BOOL STDCALL find_file_in_dir_with_crc32(device_extension* Vcb, PUNICODE_STRING filename, UINT32 crc32, root* r, UINT64 parinode, root** subvol,
617 UINT64* inode, UINT8* type, PANSI_STRING utf8);
618 NTSTATUS update_inode_item(device_extension* Vcb, root* subvol, UINT64 inode, INODE_ITEM* ii, LIST_ENTRY* rollback);
619 NTSTATUS open_fileref(device_extension* Vcb, file_ref** pfr, PUNICODE_STRING fnus, file_ref* related, BOOL parent, USHORT* unparsed);
620
621 // in fsctl.c
622 NTSTATUS fsctl_request(PDEVICE_OBJECT DeviceObject, PIRP Irp, UINT32 type, BOOL user);
623
624 // in flushthread.c
625 void STDCALL flush_thread(void* context);
626
627 // in read.c
628 NTSTATUS STDCALL drv_read(PDEVICE_OBJECT DeviceObject, PIRP Irp);
629 NTSTATUS STDCALL read_file(device_extension* Vcb, root* subvol, UINT64 inode, UINT8* data, UINT64 start, UINT64 length, ULONG* pbr);
630
631 // in pnp.c
632 NTSTATUS STDCALL drv_pnp(PDEVICE_OBJECT DeviceObject, PIRP Irp);
633
634 // in free-space.c
635 NTSTATUS load_free_space_cache(device_extension* Vcb, chunk* c);
636 NTSTATUS clear_free_space_cache(device_extension* Vcb);
637 NTSTATUS allocate_cache(device_extension* Vcb, BOOL* changed, LIST_ENTRY* rollback);
638 NTSTATUS update_chunk_caches(device_extension* Vcb, LIST_ENTRY* rollback);
639
640 // in extent-tree.c
641 NTSTATUS increase_extent_refcount_data(device_extension* Vcb, UINT64 address, UINT64 size, root* subvol, UINT64 inode, UINT64 offset, UINT32 refcount, LIST_ENTRY* rollback);
642 NTSTATUS decrease_extent_refcount_data(device_extension* Vcb, UINT64 address, UINT64 size, root* subvol, UINT64 inode, UINT64 offset, UINT32 refcount, LIST_ENTRY* changed_sector_list, LIST_ENTRY* rollback);
643 void decrease_chunk_usage(chunk* c, UINT64 delta);
644 NTSTATUS convert_shared_data_extent(device_extension* Vcb, UINT64 address, UINT64 size, LIST_ENTRY* rollback);
645 NTSTATUS convert_old_data_extent(device_extension* Vcb, UINT64 address, UINT64 size, LIST_ENTRY* rollback);
646
647 #define fast_io_possible(fcb) (!FsRtlAreThereCurrentFileLocks(&fcb->lock) && !fcb->Vcb->readonly ? FastIoIsPossible : FastIoIsQuestionable)
648
649 static __inline void print_open_trees(device_extension* Vcb) {
650 LIST_ENTRY* le = Vcb->trees.Flink;
651 while (le != &Vcb->trees) {
652 tree* t = CONTAINING_RECORD(le, tree, list_entry);
653 tree_data* td = CONTAINING_RECORD(t->itemlist.Flink, tree_data, list_entry);
654 ERR("tree %p: root %llx, level %u, first key (%llx,%x,%llx)\n",
655 t, t->root->id, t->header.level, td->key.obj_id, td->key.obj_type, td->key.offset);
656
657 le = le->Flink;
658 }
659 }
660
661 static __inline void InsertAfter(LIST_ENTRY* head, LIST_ENTRY* item, LIST_ENTRY* before) {
662 item->Flink = before->Flink;
663 before->Flink = item;
664 item->Blink = before;
665
666 if (item->Flink != head)
667 item->Flink->Blink = item;
668 else
669 head->Blink = item;
670 }
671
672 #ifdef _MSC_VER
673 // #define int3 __asm { int 3 }
674 #define int3 __debugbreak()
675 #else
676 #define int3 asm("int3;")
677 #endif
678
679 #define acquire_tree_lock(Vcb, exclusive) {\
680 LONG ref = InterlockedIncrement(&Vcb->tree_lock_counter); \
681 ref = ref; \
682 if (exclusive) { \
683 TRACE("getting tree_lock (exclusive) %u->%u\n", ref-1, ref); \
684 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, TRUE); \
685 TRACE("open tree count = %i\n", Vcb->open_trees); \
686 } else { \
687 TRACE("getting tree_lock %u->%u\n", ref-1, ref); \
688 ExAcquireResourceSharedLite(&Vcb->tree_lock, TRUE); \
689 } \
690 }
691
692 // if (Vcb->open_trees > 0) { ERR("open tree count = %i\n", Vcb->open_trees); print_open_trees(Vcb); int3; }
693 // else TRACE("open tree count = %i\n", Vcb->open_trees);
694
695 // FIXME - find a way to catch unfreed trees again
696
697 #define release_tree_lock(Vcb, exclusive) {\
698 LONG ref = InterlockedDecrement(&Vcb->tree_lock_counter); \
699 ref = ref; \
700 TRACE("releasing tree_lock %u->%u\n", ref+1, ref); \
701 if (exclusive) {\
702 TRACE("open tree count = %i\n", Vcb->open_trees); \
703 } \
704 ExReleaseResourceLite(&Vcb->tree_lock); \
705 }
706
707 // from sys/stat.h
708 #define __S_IFMT 0170000 /* These bits determine file type. */
709 #define __S_IFDIR 0040000 /* Directory. */
710 #define __S_IFCHR 0020000 /* Character device. */
711 #define __S_IFBLK 0060000 /* Block device. */
712 #define __S_IFREG 0100000 /* Regular file. */
713 #define __S_IFIFO 0010000 /* FIFO. */
714 #define __S_IFLNK 0120000 /* Symbolic link. */
715 #define __S_IFSOCK 0140000 /* Socket. */
716 #define __S_ISTYPE(mode, mask) (((mode) & __S_IFMT) == (mask))
717
718 #ifndef S_ISDIR
719 #define S_ISDIR(mode) __S_ISTYPE((mode), __S_IFDIR)
720 #endif
721
722 #ifndef S_IRUSR
723 #define S_IRUSR 0000400
724 #endif
725
726 #ifndef S_IWUSR
727 #define S_IWUSR 0000200
728 #endif
729
730 #ifndef S_IXUSR
731 #define S_IXUSR 0000100
732 #endif
733
734 #ifdef __REACTOS__
735 #define S_IFDIR __S_IFDIR
736 #define S_IFREG __S_IFREG
737 #endif /* __REACTOS__ */
738
739 #ifndef S_IRGRP
740 #define S_IRGRP (S_IRUSR >> 3)
741 #endif
742
743 #ifndef S_IWGRP
744 #define S_IWGRP (S_IWUSR >> 3)
745 #endif
746
747 #ifndef S_IXGRP
748 #define S_IXGRP (S_IXUSR >> 3)
749 #endif
750
751 #ifndef S_IROTH
752 #define S_IROTH (S_IRGRP >> 3)
753 #endif
754
755 #ifndef S_IWOTH
756 #define S_IWOTH (S_IWGRP >> 3)
757 #endif
758
759 #ifndef S_IXOTH
760 #define S_IXOTH (S_IXGRP >> 3)
761 #endif
762
763 #if defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_WIN7)
764 NTSTATUS WINAPI RtlUnicodeToUTF8N(CHAR *utf8_dest, ULONG utf8_bytes_max,
765 ULONG *utf8_bytes_written,
766 const WCHAR *uni_src, ULONG uni_bytes);
767 NTSTATUS WINAPI RtlUTF8ToUnicodeN(WCHAR *uni_dest, ULONG uni_bytes_max,
768 ULONG *uni_bytes_written,
769 const CHAR *utf8_src, ULONG utf8_bytes);
770 #endif /* defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_WIN7) */
771 #if defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_VISTA)
772 NTSTATUS NTAPI FsRtlRemoveDotsFromPath(PWSTR OriginalString,
773 USHORT PathLength, USHORT *NewLength);
774 NTSTATUS NTAPI FsRtlValidateReparsePointBuffer(ULONG BufferLength,
775 PREPARSE_DATA_BUFFER ReparseBuffer);
776 #endif /* defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_WIN7) */
777
778 #endif