[BTRFS]
[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 #define MAX_EXTENT_SIZE 0x8000000 // 128 MB
77
78 #ifdef _MSC_VER
79 #define try __try
80 #define except __except
81 #define finally __finally
82 #else
83 #define try if (1)
84 #define except(x) if (0 && (x))
85 #define finally if (1)
86 #endif
87
88 // #pragma pack(push, 1)
89
90 struct device_extension;
91
92 typedef struct {
93 BTRFS_UUID fsuuid;
94 BTRFS_UUID devuuid;
95 UINT64 devnum;
96 UNICODE_STRING devpath;
97 UINT64 length;
98 UINT64 gen1, gen2;
99 BOOL processed;
100 LIST_ENTRY list_entry;
101 } volume;
102
103 typedef struct _fcb_nonpaged {
104 FAST_MUTEX HeaderMutex;
105 SECTION_OBJECT_POINTERS segment_object;
106 ERESOURCE resource;
107 ERESOURCE paging_resource;
108 ERESOURCE index_lock;
109 } fcb_nonpaged;
110
111 struct _root;
112
113 typedef struct {
114 UINT64 offset;
115 EXTENT_DATA* data;
116 ULONG datalen;
117 BOOL unique;
118 BOOL ignore;
119
120 LIST_ENTRY list_entry;
121 } extent;
122
123 typedef struct {
124 UINT32 hash;
125 KEY key;
126 UINT8 type;
127 UINT64 index;
128 ANSI_STRING utf8;
129 UNICODE_STRING filepart_uc;
130
131 LIST_ENTRY list_entry;
132 } index_entry;
133
134 typedef struct {
135 UINT64 parent;
136 UINT64 index;
137 UNICODE_STRING name;
138 ANSI_STRING utf8;
139 LIST_ENTRY list_entry;
140 } hardlink;
141
142 struct _file_ref;
143
144 typedef struct _fcb {
145 FSRTL_ADVANCED_FCB_HEADER Header;
146 struct _fcb_nonpaged* nonpaged;
147 LONG refcount;
148 LONG open_count;
149 struct _device_extension* Vcb;
150 struct _root* subvol;
151 UINT64 inode;
152 UINT8 type;
153 INODE_ITEM inode_item;
154 SECURITY_DESCRIPTOR* sd;
155 FILE_LOCK lock;
156 BOOL deleted;
157 PKTHREAD lazy_writer_thread;
158 ULONG atts;
159 SHARE_ACCESS share_access;
160 WCHAR* debug_desc;
161 LIST_ENTRY extents;
162 UINT64 last_dir_index;
163 ANSI_STRING reparse_xattr;
164 LIST_ENTRY hardlinks;
165 struct _file_ref* fileref;
166
167 BOOL index_loaded;
168 LIST_ENTRY index_list;
169
170 BOOL dirty;
171 BOOL sd_dirty;
172 BOOL atts_changed, atts_deleted;
173 BOOL extents_changed;
174 BOOL reparse_xattr_changed;
175 BOOL created;
176
177 BOOL ads;
178 UINT32 adshash;
179 ANSI_STRING adsxattr;
180 ANSI_STRING adsdata;
181
182 LIST_ENTRY list_entry;
183 LIST_ENTRY list_entry_all;
184 } fcb;
185
186 typedef struct {
187 fcb* fcb;
188 LIST_ENTRY list_entry;
189 } dirty_fcb;
190
191 typedef struct {
192 ERESOURCE children_lock;
193 } file_ref_nonpaged;
194
195 typedef struct _file_ref {
196 fcb* fcb;
197 UNICODE_STRING filepart;
198 UNICODE_STRING filepart_uc;
199 ANSI_STRING utf8;
200 ANSI_STRING oldutf8;
201 UINT64 index;
202 BOOL delete_on_close;
203 BOOL deleted;
204 BOOL created;
205 file_ref_nonpaged* nonpaged;
206 LIST_ENTRY children;
207 LONG refcount;
208 struct _file_ref* parent;
209 WCHAR* debug_desc;
210
211 BOOL dirty;
212
213 LIST_ENTRY list_entry;
214 } file_ref;
215
216 typedef struct {
217 file_ref* fileref;
218 LIST_ENTRY list_entry;
219 } dirty_fileref;
220
221 typedef struct _ccb {
222 USHORT NodeType;
223 CSHORT NodeSize;
224 ULONG disposition;
225 ULONG options;
226 UINT64 query_dir_offset;
227 // char* query_string;
228 UNICODE_STRING query_string;
229 BOOL has_wildcard;
230 BOOL specific_file;
231 ACCESS_MASK access;
232 file_ref* fileref;
233 UNICODE_STRING filename;
234 } ccb;
235
236 // typedef struct _log_to_phys {
237 // UINT64 address;
238 // UINT64 size;
239 // UINT64 physaddr;
240 // UINT32 sector_size;
241 // struct _log_to_phys* next;
242 // } log_to_phys;
243
244 struct _device_extension;
245
246 // enum tree_holder_status {
247 // tree_holder_unloaded,
248 // tree_holder_loading,
249 // tree_holder_loaded,
250 // tree_holder_unloading
251 // };
252
253 // typedef struct {
254 // enum tree_holder_status status;
255 // KSPIN_LOCK spin_lock;
256 // ERESOURCE lock;
257 // } tree_holder_nonpaged;
258
259 typedef struct {
260 UINT64 address;
261 UINT64 generation;
262 struct _tree* tree;
263 // tree_holder_nonpaged* nonpaged;
264 } tree_holder;
265
266 typedef struct _tree_data {
267 KEY key;
268 LIST_ENTRY list_entry;
269 BOOL ignore;
270 BOOL inserted;
271
272 union {
273 tree_holder treeholder;
274
275 struct {
276 UINT32 size;
277 UINT8* data;
278 };
279 };
280 } tree_data;
281
282 // typedef struct _tree_nonpaged {
283 // ERESOURCE load_tree_lock;
284 // } tree_nonpaged;
285
286 typedef struct _tree {
287 // UINT64 address;
288 // UINT8 level;
289 tree_header header;
290 BOOL has_address;
291 UINT32 size;
292 struct _device_extension* Vcb;
293 struct _tree* parent;
294 tree_data* paritem;
295 struct _root* root;
296 // tree_nonpaged* nonpaged;
297 LIST_ENTRY itemlist;
298 LIST_ENTRY list_entry;
299 UINT64 new_address;
300 BOOL has_new_address;
301 UINT64 flags;
302 BOOL write;
303 } tree;
304
305 typedef struct {
306 // KSPIN_LOCK load_tree_lock;
307 ERESOURCE load_tree_lock;
308 } root_nonpaged;
309
310 typedef struct _root {
311 UINT64 id;
312 tree_holder treeholder;
313 root_nonpaged* nonpaged;
314 UINT64 lastinode;
315 ROOT_ITEM root_item;
316 UNICODE_STRING path;
317 LIST_ENTRY fcbs;
318 LIST_ENTRY list_entry;
319 } root;
320
321 typedef struct {
322 tree* tree;
323 tree_data* item;
324 } traverse_ptr;
325
326 typedef struct _root_cache {
327 root* root;
328 struct _root_cache* next;
329 } root_cache;
330
331 typedef struct {
332 UINT64 address;
333 UINT64 size;
334 LIST_ENTRY list_entry;
335 LIST_ENTRY list_entry_size;
336 } space;
337
338 typedef struct {
339 PDEVICE_OBJECT devobj;
340 DEV_ITEM devitem;
341 BOOL removable;
342 ULONG change_count;
343 UINT64 length;
344 LIST_ENTRY space;
345 } device;
346
347 typedef struct {
348 ERESOURCE lock;
349 ERESOURCE changed_extents_lock;
350 } chunk_nonpaged;
351
352 typedef struct {
353 CHUNK_ITEM* chunk_item;
354 UINT32 size;
355 UINT64 offset;
356 UINT64 used;
357 UINT32 oldused;
358 device** devices;
359 fcb* cache;
360 LIST_ENTRY space;
361 LIST_ENTRY space_size;
362 LIST_ENTRY deleting;
363 LIST_ENTRY changed_extents;
364 chunk_nonpaged* nonpaged;
365 BOOL created;
366
367 LIST_ENTRY list_entry;
368 LIST_ENTRY list_entry_changed;
369 } chunk;
370
371 typedef struct {
372 UINT64 address;
373 UINT64 size;
374 UINT64 old_size;
375 UINT64 count;
376 UINT64 old_count;
377 BOOL no_csum;
378 LIST_ENTRY refs;
379 LIST_ENTRY old_refs;
380 LIST_ENTRY list_entry;
381 } changed_extent;
382
383 typedef struct {
384 EXTENT_DATA_REF edr;
385 LIST_ENTRY list_entry;
386 } changed_extent_ref;
387
388 typedef struct {
389 UINT64 address;
390 UINT64 size;
391 EXTENT_DATA_REF edr;
392 LIST_ENTRY list_entry;
393 } shared_data_entry;
394
395 typedef struct {
396 UINT64 address;
397 UINT64 parent;
398 LIST_ENTRY entries;
399 LIST_ENTRY list_entry;
400 } shared_data;
401
402 typedef struct {
403 KEY key;
404 void* data;
405 USHORT size;
406 LIST_ENTRY list_entry;
407 } sys_chunk;
408
409 typedef struct {
410 PIRP Irp;
411 LIST_ENTRY list_entry;
412 } thread_job;
413
414 typedef struct {
415 PDEVICE_OBJECT DeviceObject;
416 HANDLE handle;
417 KEVENT event, finished;
418 BOOL quit;
419 LIST_ENTRY jobs;
420 KSPIN_LOCK spin_lock;
421 } drv_thread;
422
423 typedef struct {
424 ULONG num_threads;
425 LONG next_thread;
426 drv_thread* threads;
427 } drv_threads;
428
429 typedef struct {
430 BOOL ignore;
431 } mount_options;
432
433 #define VCB_TYPE_VOLUME 1
434 #define VCB_TYPE_PARTITION0 2
435
436 typedef struct _device_extension {
437 UINT32 type;
438 mount_options options;
439 PVPB Vpb;
440 device* devices;
441 UINT64 devices_loaded;
442 // DISK_GEOMETRY geometry;
443 superblock superblock;
444 // WCHAR label[MAX_LABEL_SIZE];
445 BOOL readonly;
446 BOOL removing;
447 BOOL locked;
448 PFILE_OBJECT locked_fileobj;
449 fcb* volume_fcb;
450 file_ref* root_fileref;
451 ERESOURCE DirResource;
452 KSPIN_LOCK FcbListLock;
453 ERESOURCE fcb_lock;
454 ERESOURCE load_lock;
455 ERESOURCE tree_lock;
456 PNOTIFY_SYNC NotifySync;
457 LIST_ENTRY DirNotifyList;
458 LONG open_trees;
459 BOOL need_write;
460 // ERESOURCE LogToPhysLock;
461 // UINT64 chunk_root_phys_addr;
462 UINT64 root_tree_phys_addr;
463 UINT64 data_flags;
464 // log_to_phys* log_to_phys;
465 LIST_ENTRY roots;
466 LIST_ENTRY drop_roots;
467 root* chunk_root;
468 root* root_root;
469 root* extent_root;
470 root* checksum_root;
471 root* dev_root;
472 root* uuid_root;
473 BOOL log_to_phys_loaded;
474 UINT32 max_inline;
475 LIST_ENTRY sys_chunks;
476 LIST_ENTRY chunks;
477 LIST_ENTRY chunks_changed;
478 LIST_ENTRY trees;
479 LIST_ENTRY all_fcbs;
480 LIST_ENTRY dirty_fcbs;
481 KSPIN_LOCK dirty_fcbs_lock;
482 LIST_ENTRY dirty_filerefs;
483 KSPIN_LOCK dirty_filerefs_lock;
484 ERESOURCE checksum_lock;
485 ERESOURCE chunk_lock;
486 LIST_ENTRY sector_checksums;
487 LIST_ENTRY shared_extents;
488 KSPIN_LOCK shared_extents_lock;
489 HANDLE flush_thread_handle;
490 KTIMER flush_thread_timer;
491 KEVENT flush_thread_finished;
492 drv_threads threads;
493 PFILE_OBJECT root_file;
494 LIST_ENTRY list_entry;
495 } device_extension;
496
497 typedef struct {
498 UINT32 type;
499 PDEVICE_OBJECT devobj;
500 BTRFS_UUID uuid;
501 UNICODE_STRING name;
502 } part0_device_extension;
503
504 typedef struct {
505 LIST_ENTRY listentry;
506 PSID sid;
507 UINT32 uid;
508 } uid_map;
509
510 typedef struct {
511 LIST_ENTRY list_entry;
512 UINT64 key;
513 } ordered_list;
514
515 typedef struct {
516 ordered_list ol;
517 ULONG length;
518 UINT32* checksums;
519 BOOL deleted;
520 } changed_sector;
521
522 enum write_data_status {
523 WriteDataStatus_Pending,
524 WriteDataStatus_Success,
525 WriteDataStatus_Error,
526 WriteDataStatus_Cancelling,
527 WriteDataStatus_Cancelled,
528 WriteDataStatus_Ignore
529 };
530
531 struct write_data_context;
532
533 typedef struct {
534 struct write_data_context* context;
535 UINT8* buf;
536 BOOL need_free;
537 device* device;
538 PIRP Irp;
539 IO_STATUS_BLOCK iosb;
540 enum write_data_status status;
541 LIST_ENTRY list_entry;
542 } write_data_stripe;
543
544 typedef struct {
545 KEVENT Event;
546 LIST_ENTRY stripes;
547 LONG stripes_left;
548 BOOL tree;
549 } write_data_context;
550
551 // #pragma pack(pop)
552
553 static __inline void* map_user_buffer(PIRP Irp) {
554 if (!Irp->MdlAddress) {
555 return Irp->UserBuffer;
556 } else {
557 return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
558 }
559 }
560
561 static __inline UINT64 unix_time_to_win(BTRFS_TIME* t) {
562 return (t->seconds * 10000000) + (t->nanoseconds / 100) + 116444736000000000;
563 }
564
565 static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME* out) {
566 ULONGLONG l = t.QuadPart - 116444736000000000;
567
568 out->seconds = l / 10000000;
569 out->nanoseconds = (l % 10000000) * 100;
570 }
571
572 static __inline void insert_into_ordered_list(LIST_ENTRY* list, ordered_list* ins) {
573 LIST_ENTRY* le = list->Flink;
574 ordered_list* ol;
575
576 while (le != list) {
577 ol = (ordered_list*)le;
578
579 if (ol->key > ins->key) {
580 le->Blink->Flink = &ins->list_entry;
581 ins->list_entry.Blink = le->Blink;
582 le->Blink = &ins->list_entry;
583 ins->list_entry.Flink = le;
584 return;
585 }
586
587 le = le->Flink;
588 }
589
590 InsertTailList(list, &ins->list_entry);
591 }
592
593 static __inline void get_raid0_offset(UINT64 off, UINT64 stripe_length, UINT16 num_stripes, UINT64* stripeoff, UINT16* stripe) {
594 UINT64 initoff, startoff;
595
596 startoff = off % (num_stripes * stripe_length);
597 initoff = (off / (num_stripes * stripe_length)) * stripe_length;
598
599 *stripe = startoff / stripe_length;
600 *stripeoff = initoff + startoff - (*stripe * stripe_length);
601 }
602
603 // in btrfs.c
604 device* find_device_from_uuid(device_extension* Vcb, BTRFS_UUID* uuid);
605 UINT64 sector_align( UINT64 NumberToBeAligned, UINT64 Alignment );
606 int keycmp(const KEY* key1, const KEY* key2);
607 ULONG STDCALL get_file_attributes(device_extension* Vcb, INODE_ITEM* ii, root* r, UINT64 inode, UINT8 type, BOOL dotfile, BOOL ignore_xa);
608 BOOL STDCALL get_xattr(device_extension* Vcb, root* subvol, UINT64 inode, char* name, UINT32 crc32, UINT8** data, UINT16* datalen);
609 void _free_fcb(fcb* fcb, const char* func, const char* file, unsigned int line);
610 void _free_fileref(file_ref* fr, const char* func, const char* file, unsigned int line);
611 BOOL STDCALL get_last_inode(device_extension* Vcb, root* r);
612 NTSTATUS add_dir_item(device_extension* Vcb, root* subvol, UINT64 inode, UINT32 crc32, DIR_ITEM* di, ULONG disize, LIST_ENTRY* rollback);
613 NTSTATUS delete_dir_item(device_extension* Vcb, root* subvol, UINT64 parinode, UINT32 crc32, PANSI_STRING utf8, LIST_ENTRY* rollback);
614 NTSTATUS delete_inode_ref(device_extension* Vcb, root* subvol, UINT64 inode, UINT64 parinode, PANSI_STRING utf8, LIST_ENTRY* rollback);
615 fcb* create_fcb();
616 file_ref* create_fileref();
617 void protect_superblocks(device_extension* Vcb, chunk* c);
618 BOOL is_top_level(PIRP Irp);
619 NTSTATUS create_root(device_extension* Vcb, UINT64 id, root** rootptr, BOOL no_tree, UINT64 offset, LIST_ENTRY* rollback);
620 void STDCALL uninit(device_extension* Vcb, BOOL flush);
621 NTSTATUS STDCALL dev_ioctl(PDEVICE_OBJECT DeviceObject, ULONG ControlCode, PVOID InputBuffer,
622 ULONG InputBufferSize, PVOID OutputBuffer, ULONG OutputBufferSize, BOOLEAN Override, IO_STATUS_BLOCK* iosb);
623 BOOL is_file_name_valid(PUNICODE_STRING us);
624 void send_notification_fileref(file_ref* fileref, ULONG filter_match, ULONG action);
625 void send_notification_fcb(file_ref* fileref, ULONG filter_match, ULONG action);
626 WCHAR* file_desc(PFILE_OBJECT FileObject);
627 WCHAR* file_desc_fileref(file_ref* fileref);
628 BOOL add_thread_job(device_extension* Vcb, PIRP Irp);
629 NTSTATUS part0_passthrough(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
630 void mark_fcb_dirty(fcb* fcb);
631 void mark_fileref_dirty(file_ref* fileref);
632 NTSTATUS delete_fileref(file_ref* fileref, PFILE_OBJECT FileObject, LIST_ENTRY* rollback);
633
634 #ifdef _MSC_VER
635 #define funcname __FUNCTION__
636 #else
637 #define funcname __func__
638 #endif
639
640 // FIXME - we probably shouldn't be moving funcname etc. around if we're not printing debug messages
641 #define free_fcb(fcb) _free_fcb(fcb, funcname, __FILE__, __LINE__)
642 #define free_fileref(fileref) _free_fileref(fileref, funcname, __FILE__, __LINE__)
643
644 #ifdef _DEBUG
645
646 extern BOOL log_started;
647 extern UINT32 debug_log_level;
648
649 #ifdef DEBUG_LONG_MESSAGES
650
651 #define MSG(fn, file, line, s, level, ...) (!log_started || level <= debug_log_level) ? _debug_message(fn, file, line, s, ##__VA_ARGS__) : 0
652
653 #define TRACE(s, ...) MSG(funcname, __FILE__, __LINE__, s, 3, ##__VA_ARGS__)
654 #define WARN(s, ...) MSG(funcname, __FILE__, __LINE__, s, 2, ##__VA_ARGS__)
655 #define FIXME(s, ...) MSG(funcname, __FILE__, __LINE__, s, 1, ##__VA_ARGS__)
656 #define ERR(s, ...) MSG(funcname, __FILE__, __LINE__, s, 1, ##__VA_ARGS__)
657
658 void STDCALL _debug_message(const char* func, const char* file, unsigned int line, char* s, ...);
659
660 #else
661
662 #define MSG(fn, s, level, ...) (!log_started || level <= debug_log_level) ? _debug_message(fn, s, ##__VA_ARGS__) : 0
663
664 #define TRACE(s, ...) MSG(funcname, s, 3, ##__VA_ARGS__)
665 #define WARN(s, ...) MSG(funcname, s, 2, ##__VA_ARGS__)
666 #define FIXME(s, ...) MSG(funcname, s, 1, ##__VA_ARGS__)
667 #define ERR(s, ...) MSG(funcname, s, 1, ##__VA_ARGS__)
668
669 void STDCALL _debug_message(const char* func, char* s, ...);
670
671 #endif
672
673 #else
674
675 #define TRACE(s, ...)
676 #define WARN(s, ...)
677 #ifndef __REACTOS__
678 #define FIXME(s, ...) DbgPrint("Btrfs FIXME : " funcname " : " s, ##__VA_ARGS__)
679 #define ERR(s, ...) DbgPrint("Btrfs ERR : " funcname " : " s, ##__VA_ARGS__)
680 #else
681 #define FIXME(s, ...) DbgPrint("Btrfs FIXME : %s : " s, funcname, ##__VA_ARGS__)
682 #define ERR(s, ...) DbgPrint("Btrfs ERR : %s : " s, funcname, ##__VA_ARGS__)
683 #endif
684
685 #endif
686
687 static __inline void increase_chunk_usage(chunk* c, UINT64 delta) {
688 c->used += delta;
689
690 TRACE("increasing size of chunk %llx by %llx\n", c->offset, delta);
691 }
692
693 // in fastio.c
694 void STDCALL init_fast_io_dispatch(FAST_IO_DISPATCH** fiod);
695
696 // in crc32c.c
697 UINT32 STDCALL calc_crc32c(UINT32 seed, UINT8* msg, ULONG msglen);
698
699 enum rollback_type {
700 ROLLBACK_INSERT_ITEM,
701 ROLLBACK_DELETE_ITEM,
702 ROLLBACK_INSERT_EXTENT,
703 ROLLBACK_DELETE_EXTENT
704 };
705
706 // in treefuncs.c
707 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);
708 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);
709 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);
710 void STDCALL free_trees(device_extension* Vcb);
711 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);
712 void STDCALL delete_tree_item(device_extension* Vcb, traverse_ptr* tp, LIST_ENTRY* rollback);
713 tree* STDCALL _free_tree(tree* t, const char* func, const char* file, unsigned int line);
714 NTSTATUS STDCALL _load_tree(device_extension* Vcb, UINT64 addr, root* r, tree** pt, tree* parent, const char* func, const char* file, unsigned int line);
715 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);
716 void clear_rollback(LIST_ENTRY* rollback);
717 void do_rollback(device_extension* Vcb, LIST_ENTRY* rollback);
718 void free_trees_root(device_extension* Vcb, root* r);
719 void add_rollback(LIST_ENTRY* rollback, enum rollback_type type, void* ptr);
720
721 #define find_item(Vcb, r, tp, searchkey, ignore) _find_item(Vcb, r, tp, searchkey, ignore, funcname, __FILE__, __LINE__)
722 #define find_next_item(Vcb, tp, next_tp, ignore) _find_next_item(Vcb, tp, next_tp, ignore, funcname, __FILE__, __LINE__)
723 #define find_prev_item(Vcb, tp, prev_tp, ignore) _find_prev_item(Vcb, tp, prev_tp, ignore, funcname, __FILE__, __LINE__)
724 #define free_tree(t) _free_tree(t, funcname, __FILE__, __LINE__)
725 #define load_tree(t, addr, r, pt, parent) _load_tree(t, addr, r, pt, parent, funcname, __FILE__, __LINE__)
726 #define do_load_tree(Vcb, th, r, t, td, loaded) _do_load_tree(Vcb, th, r, t, td, loaded, funcname, __FILE__, __LINE__)
727
728 // in search.c
729 void STDCALL look_for_vols(PDRIVER_OBJECT DriverObject, LIST_ENTRY* volumes);
730
731 // in cache.c
732 NTSTATUS STDCALL init_cache();
733 void STDCALL free_cache();
734 extern CACHE_MANAGER_CALLBACKS* cache_callbacks;
735
736 // in write.c
737 NTSTATUS STDCALL do_write(device_extension* Vcb, LIST_ENTRY* rollback);
738 NTSTATUS write_file(device_extension* Vcb, PIRP Irp, BOOL wait, BOOL deferred_write);
739 NTSTATUS write_file2(device_extension* Vcb, PIRP Irp, LARGE_INTEGER offset, void* buf, ULONG* length, BOOL paging_io, BOOL no_cache,
740 BOOL wait, BOOL deferred_write, LIST_ENTRY* rollback);
741 NTSTATUS truncate_file(fcb* fcb, UINT64 end, LIST_ENTRY* rollback);
742 NTSTATUS extend_file(fcb* fcb, file_ref* fileref, UINT64 end, BOOL prealloc, PIRP Irp, LIST_ENTRY* rollback);
743 NTSTATUS excise_extents(device_extension* Vcb, fcb* fcb, UINT64 start_data, UINT64 end_data, LIST_ENTRY* rollback);
744 void commit_checksum_changes(device_extension* Vcb, LIST_ENTRY* changed_sector_list);
745 NTSTATUS insert_sparse_extent(fcb* fcb, UINT64 start, UINT64 length, LIST_ENTRY* rollback);
746 chunk* get_chunk_from_address(device_extension* Vcb, UINT64 address);
747 chunk* alloc_chunk(device_extension* Vcb, UINT64 flags, LIST_ENTRY* rollback);
748 NTSTATUS STDCALL write_data(device_extension* Vcb, UINT64 address, void* data, BOOL need_free, UINT32 length, write_data_context* wtc, PIRP Irp);
749 NTSTATUS STDCALL write_data_complete(device_extension* Vcb, UINT64 address, void* data, UINT32 length, PIRP Irp);
750 void free_write_data_stripes(write_data_context* wtc);
751 NTSTATUS get_tree_new_address(device_extension* Vcb, tree* t, LIST_ENTRY* rollback);
752 NTSTATUS STDCALL drv_write(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
753 void flush_fcb(fcb* fcb, BOOL cache, LIST_ENTRY* rollback);
754 BOOL insert_extent_chunk(device_extension* Vcb, fcb* fcb, chunk* c, UINT64 start_data, UINT64 length, BOOL prealloc, void* data, LIST_ENTRY* changed_sector_list,
755 PIRP Irp, LIST_ENTRY* rollback);
756 NTSTATUS do_nocow_write(device_extension* Vcb, fcb* fcb, UINT64 start_data, UINT64 end_data, void* data, LIST_ENTRY* changed_sector_list, PIRP Irp, LIST_ENTRY* rollback);
757 NTSTATUS insert_extent(device_extension* Vcb, fcb* fcb, UINT64 start_data, UINT64 length, void* data, LIST_ENTRY* changed_sector_list, PIRP Irp, LIST_ENTRY* rollback);
758 void remove_fcb_extent(extent* ext, LIST_ENTRY* rollback);
759 NTSTATUS update_changed_extent_ref(device_extension* Vcb, chunk* c, UINT64 address, UINT64 size, UINT64 root, UINT64 objid, UINT64 offset,
760 signed long long count, BOOL no_csum, UINT64 new_size);
761
762 // in dirctrl.c
763 NTSTATUS STDCALL drv_directory_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
764
765 // in security.c
766 NTSTATUS STDCALL drv_query_security(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
767 NTSTATUS STDCALL drv_set_security(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
768 void fcb_get_sd(fcb* fcb, struct _fcb* parent);
769 // UINT32 STDCALL get_uid();
770 void add_user_mapping(WCHAR* sidstring, ULONG sidstringlength, UINT32 uid);
771 UINT32 sid_to_uid(PSID sid);
772 NTSTATUS fcb_get_new_sd(fcb* fcb, file_ref* parfileref, ACCESS_STATE* as);
773
774 // in fileinfo.c
775 NTSTATUS STDCALL drv_set_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
776 NTSTATUS STDCALL drv_query_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
777 NTSTATUS add_inode_ref(device_extension* Vcb, root* subvol, UINT64 inode, UINT64 parinode, UINT64 index, PANSI_STRING utf8, LIST_ENTRY* rollback);
778 BOOL has_open_children(file_ref* fileref);
779 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);
780 NTSTATUS fileref_get_filename(file_ref* fileref, PUNICODE_STRING fn, USHORT* name_offset);
781 NTSTATUS open_fileref_by_inode(device_extension* Vcb, root* subvol, UINT64 inode, file_ref** pfr);
782
783 // in reparse.c
784 NTSTATUS get_reparse_point(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject, void* buffer, DWORD buflen, DWORD* retlen);
785 NTSTATUS set_reparse_point(PDEVICE_OBJECT DeviceObject, PIRP Irp);
786 NTSTATUS delete_reparse_point(PDEVICE_OBJECT DeviceObject, PIRP Irp);
787
788 // in create.c
789 NTSTATUS STDCALL drv_create(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
790 NTSTATUS STDCALL find_file_in_dir_with_crc32(device_extension* Vcb, PUNICODE_STRING filename, UINT32 crc32, file_ref* fr, root** subvol,
791 UINT64* inode, UINT8* type, UINT64* index, PANSI_STRING utf8);
792 NTSTATUS STDCALL find_file_in_dir(device_extension* Vcb, PUNICODE_STRING filename, file_ref* fr,
793 root** subvol, UINT64* inode, UINT8* type, UINT64* index, PANSI_STRING utf8);
794 NTSTATUS open_fileref(device_extension* Vcb, file_ref** pfr, PUNICODE_STRING fnus, file_ref* related, BOOL parent, USHORT* unparsed);
795 NTSTATUS open_fcb(device_extension* Vcb, root* subvol, UINT64 inode, UINT8 type, PANSI_STRING utf8, fcb* parent, fcb** pfcb);
796 NTSTATUS open_fcb_stream(device_extension* Vcb, root* subvol, UINT64 inode, ANSI_STRING* xattr, UINT32 streamhash, fcb* parent, fcb** pfcb);
797 void insert_fileref_child(file_ref* parent, file_ref* child, BOOL do_lock);
798 NTSTATUS fcb_get_last_dir_index(fcb* fcb, UINT64* index);
799
800 // in fsctl.c
801 NTSTATUS fsctl_request(PDEVICE_OBJECT DeviceObject, PIRP Irp, UINT32 type, BOOL user);
802 void do_unlock_volume(device_extension* Vcb);
803
804 // in flushthread.c
805 void STDCALL flush_thread(void* context);
806
807 // in read.c
808 NTSTATUS STDCALL drv_read(PDEVICE_OBJECT DeviceObject, PIRP Irp);
809 NTSTATUS STDCALL read_data(device_extension* Vcb, UINT64 addr, UINT32 length, UINT32* csum, BOOL is_tree, UINT8* buf, chunk** pc, PIRP Irp);
810 NTSTATUS STDCALL read_file(fcb* fcb, UINT8* data, UINT64 start, UINT64 length, ULONG* pbr, PIRP Irp);
811 NTSTATUS do_read(PIRP Irp, BOOL wait, ULONG* bytes_read);
812
813 // in pnp.c
814 NTSTATUS STDCALL drv_pnp(PDEVICE_OBJECT DeviceObject, PIRP Irp);
815
816 // in free-space.c
817 NTSTATUS load_free_space_cache(device_extension* Vcb, chunk* c);
818 NTSTATUS clear_free_space_cache(device_extension* Vcb);
819 NTSTATUS allocate_cache(device_extension* Vcb, BOOL* changed, LIST_ENTRY* rollback);
820 NTSTATUS update_chunk_caches(device_extension* Vcb, LIST_ENTRY* rollback);
821 NTSTATUS add_space_entry(LIST_ENTRY* list, LIST_ENTRY* list_size, UINT64 offset, UINT64 size);
822 void _space_list_add(device_extension* Vcb, chunk* c, BOOL deleting, UINT64 address, UINT64 length, LIST_ENTRY* rollback, const char* func);
823 void _space_list_add2(LIST_ENTRY* list, LIST_ENTRY* list_size, UINT64 address, UINT64 length, LIST_ENTRY* rollback, const char* func);
824 void _space_list_subtract(device_extension* Vcb, chunk* c, BOOL deleting, UINT64 address, UINT64 length, LIST_ENTRY* rollback, const char* func);
825 void _space_list_subtract2(LIST_ENTRY* list, LIST_ENTRY* list_size, UINT64 address, UINT64 length, LIST_ENTRY* rollback, const char* func);
826
827 #define space_list_add(Vcb, c, deleting, address, length, rollback) _space_list_add(Vcb, c, deleting, address, length, rollback, funcname)
828 #define space_list_add2(list, list_size, address, length, rollback) _space_list_add2(list, list_size, address, length, rollback, funcname)
829 #define space_list_subtract(Vcb, c, deleting, address, length, rollback) _space_list_subtract(Vcb, c, deleting, address, length, rollback, funcname)
830 #define space_list_subtract2(list, list_size, address, length, rollback) _space_list_subtract2(list, list_size, address, length, rollback, funcname)
831
832 // in extent-tree.c
833 NTSTATUS increase_extent_refcount_data(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 root, UINT64 inode, UINT64 offset, UINT32 refcount, LIST_ENTRY* rollback);
834 NTSTATUS decrease_extent_refcount_data(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 root, UINT64 inode, UINT64 offset, UINT32 refcount, LIST_ENTRY* rollback);
835 NTSTATUS decrease_extent_refcount_shared_data(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 treeaddr, UINT64 parent, LIST_ENTRY* rollback);
836 NTSTATUS decrease_extent_refcount_old(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 treeaddr, LIST_ENTRY* rollback);
837 void decrease_chunk_usage(chunk* c, UINT64 delta);
838 NTSTATUS convert_old_data_extent(device_extension* Vcb, UINT64 address, UINT64 size, LIST_ENTRY* rollback);
839 UINT64 find_extent_data_refcount(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 root, UINT64 objid, UINT64 offset);
840
841 // in worker-thread.c
842 void STDCALL worker_thread(void* context);
843 void do_read_job(PIRP Irp);
844 void do_write_job(device_extension* Vcb, PIRP Irp);
845
846 // in registry.c
847 void STDCALL read_registry(PUNICODE_STRING regpath);
848 NTSTATUS registry_mark_volume_mounted(BTRFS_UUID* uuid);
849 NTSTATUS registry_mark_volume_unmounted(BTRFS_UUID* uuid);
850 NTSTATUS registry_load_volume_options(BTRFS_UUID* uuid, mount_options* options);
851
852 #define fast_io_possible(fcb) (!FsRtlAreThereCurrentFileLocks(&fcb->lock) && !fcb->Vcb->readonly ? FastIoIsPossible : FastIoIsQuestionable)
853
854 static __inline void print_open_trees(device_extension* Vcb) {
855 LIST_ENTRY* le = Vcb->trees.Flink;
856 while (le != &Vcb->trees) {
857 tree* t = CONTAINING_RECORD(le, tree, list_entry);
858 tree_data* td = CONTAINING_RECORD(t->itemlist.Flink, tree_data, list_entry);
859 ERR("tree %p: root %llx, level %u, first key (%llx,%x,%llx)\n",
860 t, t->root->id, t->header.level, td->key.obj_id, td->key.obj_type, td->key.offset);
861
862 le = le->Flink;
863 }
864 }
865
866 static __inline void InsertAfter(LIST_ENTRY* head, LIST_ENTRY* item, LIST_ENTRY* before) {
867 item->Flink = before->Flink;
868 before->Flink = item;
869 item->Blink = before;
870
871 if (item->Flink != head)
872 item->Flink->Blink = item;
873 else
874 head->Blink = item;
875 }
876
877 #ifdef DEBUG_FCB_REFCOUNTS
878 #ifdef DEBUG_LONG_MESSAGES
879 #define increase_fileref_refcount(fileref) {\
880 LONG rc = InterlockedIncrement(&fileref->refcount);\
881 MSG(funcname, __FILE__, __LINE__, "fileref %p: refcount now %i\n", 1, fileref, rc);\
882 }
883 #else
884 #define increase_fileref_refcount(fileref) {\
885 LONG rc = InterlockedIncrement(&fileref->refcount);\
886 MSG(funcname, "fileref %p: refcount now %i\n", 1, fileref, rc);\
887 }
888 #endif
889 #else
890 #define increase_fileref_refcount(fileref) InterlockedIncrement(&fileref->refcount)
891 #endif
892
893 #ifdef _MSC_VER
894 // #define int3 __asm { int 3 }
895 #define int3 __debugbreak()
896 #else
897 #define int3 asm("int3;")
898 #endif
899
900 // if (Vcb->open_trees > 0) { ERR("open tree count = %i\n", Vcb->open_trees); print_open_trees(Vcb); int3; }
901 // else TRACE("open tree count = %i\n", Vcb->open_trees);
902
903 // FIXME - find a way to catch unfreed trees again
904
905 // from sys/stat.h
906 #define __S_IFMT 0170000 /* These bits determine file type. */
907 #define __S_IFDIR 0040000 /* Directory. */
908 #define __S_IFCHR 0020000 /* Character device. */
909 #define __S_IFBLK 0060000 /* Block device. */
910 #define __S_IFREG 0100000 /* Regular file. */
911 #define __S_IFIFO 0010000 /* FIFO. */
912 #define __S_IFLNK 0120000 /* Symbolic link. */
913 #define __S_IFSOCK 0140000 /* Socket. */
914 #define __S_ISTYPE(mode, mask) (((mode) & __S_IFMT) == (mask))
915
916 #ifndef S_ISDIR
917 #define S_ISDIR(mode) __S_ISTYPE((mode), __S_IFDIR)
918 #endif
919
920 #ifndef S_IRUSR
921 #define S_IRUSR 0000400
922 #endif
923
924 #ifndef S_IWUSR
925 #define S_IWUSR 0000200
926 #endif
927
928 #ifndef S_IXUSR
929 #define S_IXUSR 0000100
930 #endif
931
932 #ifdef __REACTOS__
933 #define S_IFDIR __S_IFDIR
934 #define S_IFREG __S_IFREG
935 #endif /* __REACTOS__ */
936
937 #ifndef S_IRGRP
938 #define S_IRGRP (S_IRUSR >> 3)
939 #endif
940
941 #ifndef S_IWGRP
942 #define S_IWGRP (S_IWUSR >> 3)
943 #endif
944
945 #ifndef S_IXGRP
946 #define S_IXGRP (S_IXUSR >> 3)
947 #endif
948
949 #ifndef S_IROTH
950 #define S_IROTH (S_IRGRP >> 3)
951 #endif
952
953 #ifndef S_IWOTH
954 #define S_IWOTH (S_IWGRP >> 3)
955 #endif
956
957 #ifndef S_IXOTH
958 #define S_IXOTH (S_IXGRP >> 3)
959 #endif
960
961 #if defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_WIN7)
962 NTSTATUS WINAPI RtlUnicodeToUTF8N(CHAR *utf8_dest, ULONG utf8_bytes_max,
963 ULONG *utf8_bytes_written,
964 const WCHAR *uni_src, ULONG uni_bytes);
965 NTSTATUS WINAPI RtlUTF8ToUnicodeN(WCHAR *uni_dest, ULONG uni_bytes_max,
966 ULONG *uni_bytes_written,
967 const CHAR *utf8_src, ULONG utf8_bytes);
968 #endif /* defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_WIN7) */
969 #if defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_VISTA)
970 NTSTATUS NTAPI FsRtlRemoveDotsFromPath(PWSTR OriginalString,
971 USHORT PathLength, USHORT *NewLength);
972 NTSTATUS NTAPI FsRtlValidateReparsePointBuffer(ULONG BufferLength,
973 PREPARSE_DATA_BUFFER ReparseBuffer);
974 ULONG NTAPI KeQueryActiveProcessorCount(PKAFFINITY ActiveProcessors);
975 #endif /* defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_VISTA) */
976
977 #endif