[BTRFS][UBTRFS][SHELLBTRFS] Upgrade to 1.7.2
[reactos.git] / drivers / filesystems / btrfs / btrfs_drv.h
index 24307d9..344223e 100644 (file)
 #include <stddef.h>
 #include <stdint.h>
 #include <stdbool.h>
-#ifndef __REACTOS__
-// Not actually used
-#include <emmintrin.h>
-#endif /* __REACTOS__ */
 #include "btrfs.h"
 #include "btrfsioctl.h"
 
+#if !defined(__REACTOS__) && (defined(_X86_) || defined(_AMD64_))
+#include <emmintrin.h>
+#endif
+
 #ifdef __REACTOS__
 C_ASSERT(sizeof(bool) == 1);
 #endif
@@ -117,12 +117,16 @@ C_ASSERT(sizeof(bool) == 1);
 
 #define READ_AHEAD_GRANULARITY COMPRESSED_EXTENT_SIZE // really ought to be a multiple of COMPRESSED_EXTENT_SIZE
 
-#define IO_REPARSE_TAG_LXSS_SYMLINK 0xa000001d // undocumented?
+#ifndef IO_REPARSE_TAG_LX_SYMLINK
 
-#define IO_REPARSE_TAG_LXSS_SOCKET      0x80000023
-#define IO_REPARSE_TAG_LXSS_FIFO        0x80000024
-#define IO_REPARSE_TAG_LXSS_CHARDEV     0x80000025
-#define IO_REPARSE_TAG_LXSS_BLOCKDEV    0x80000026
+#define IO_REPARSE_TAG_LX_SYMLINK 0xa000001d
+
+#define IO_REPARSE_TAG_AF_UNIX          0x80000023
+#define IO_REPARSE_TAG_LX_FIFO          0x80000024
+#define IO_REPARSE_TAG_LX_CHR           0x80000025
+#define IO_REPARSE_TAG_LX_BLK           0x80000026
+
+#endif
 
 #define BTRFS_VOLUME_PREFIX L"\\Device\\Btrfs{"
 
@@ -140,7 +144,7 @@ C_ASSERT(sizeof(bool) == 1);
 #ifdef __GNUC__
 #define InterlockedIncrement64(a) __sync_add_and_fetch(a, 1)
 #endif
-#endif
+#endif // __REACTOS__
 
 #ifndef FILE_SUPPORTS_BLOCK_REFCOUNTING
 #define FILE_SUPPORTS_BLOCK_REFCOUNTING 0x08000000
@@ -154,10 +158,22 @@ C_ASSERT(sizeof(bool) == 1);
 #define FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL 0x00020000
 #endif
 
+#ifndef __REACTOS__
+#ifndef _MSC_VER
 typedef struct _FILE_ID_128 {
     UCHAR Identifier[16];
 } FILE_ID_128, *PFILE_ID_128;
 
+#define FILE_CS_FLAG_CASE_SENSITIVE_DIR                 1
+#endif
+#else
+typedef struct _FILE_ID_128 {
+    UCHAR Identifier[16];
+} FILE_ID_128, *PFILE_ID_128;
+
+#define FILE_CS_FLAG_CASE_SENSITIVE_DIR                 1
+#endif // __REACTOS__
+
 typedef struct _DUPLICATE_EXTENTS_DATA {
     HANDLE FileHandle;
     LARGE_INTEGER SourceFileOffset;
@@ -190,9 +206,6 @@ typedef struct _FSCTL_SET_INTEGRITY_INFORMATION_BUFFER {
 #define _Requires_lock_held_(a)
 #define _Requires_exclusive_lock_held_(a)
 #define _Releases_lock_(a)
-#define _Out_writes_bytes_opt_(a)
-#define _Pre_satisfies_(a)
-#define _Post_satisfies_(a)
 #define _Releases_exclusive_lock_(a)
 #define _Dispatch_type_(a)
 #define _Create_lock_level_(a)
@@ -202,12 +215,14 @@ typedef struct _FSCTL_SET_INTEGRITY_INFORMATION_BUFFER {
 #define _Acquires_exclusive_lock_(a)
 #define _Acquires_shared_lock_(a)
 #endif
-#endif
+#endif // __REACTOS__
 
 _Create_lock_level_(tree_lock)
 _Create_lock_level_(fcb_lock)
 _Lock_level_order_(tree_lock, fcb_lock)
 
+#define MAX_HASH_SIZE 32
+
 struct _device_extension;
 
 typedef struct _fcb_nonpaged {
@@ -226,7 +241,7 @@ typedef struct {
     bool unique;
     bool ignore;
     bool inserted;
-    uint32_t* csum;
+    void* csum;
 
     LIST_ENTRY list_entry;
 
@@ -461,6 +476,7 @@ typedef struct _root {
     LONG send_ops;
     uint64_t fcbs_version;
     bool checked_for_orphans;
+    bool dropped;
     LIST_ENTRY fcbs;
     LIST_ENTRY* fcbs_ptrs[256];
     LIST_ENTRY list_entry;
@@ -617,27 +633,42 @@ typedef struct {
     LIST_ENTRY list_entry;
 } sys_chunk;
 
+enum calc_thread_type {
+    calc_thread_crc32c,
+    calc_thread_xxhash,
+    calc_thread_sha256,
+    calc_thread_blake2,
+    calc_thread_decomp_zlib,
+    calc_thread_decomp_lzo,
+    calc_thread_decomp_zstd,
+    calc_thread_comp_zlib,
+    calc_thread_comp_lzo,
+    calc_thread_comp_zstd,
+};
+
 typedef struct {
-    uint8_t* data;
-    uint32_t* csum;
-    uint32_t sectors;
-    LONG pos, done;
-    KEVENT event;
-    LONG refcount;
     LIST_ENTRY list_entry;
+    void* in;
+    void* out;
+    unsigned int inlen, outlen, off, space_left;
+    LONG left, not_started;
+    KEVENT event;
+    enum calc_thread_type type;
+    NTSTATUS Status;
 } calc_job;
 
 typedef struct {
     PDEVICE_OBJECT DeviceObject;
     HANDLE handle;
     KEVENT finished;
+    unsigned int number;
     bool quit;
 } drv_calc_thread;
 
 typedef struct {
     ULONG num_threads;
     LIST_ENTRY job_list;
-    ERESOURCE lock;
+    KSPIN_LOCK spinlock;
     drv_calc_thread* threads;
     KEVENT event;
 } drv_calc_threads;
@@ -744,6 +775,7 @@ typedef struct _device_extension {
 #endif
     uint64_t devices_loaded;
     superblock superblock;
+    unsigned int csum_size;
     bool readonly;
     bool removing;
     bool locked;
@@ -839,6 +871,7 @@ typedef struct {
     void* notification_entry;
     ULONG disk_num;
     ULONG part_num;
+    bool boot_volume;
     LIST_ENTRY list_entry;
 } volume_child;
 
@@ -1134,6 +1167,7 @@ _Ret_maybenull_
 root* find_default_subvol(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension* Vcb, _In_opt_ PIRP Irp);
 
 void do_shutdown(PIRP Irp);
+bool check_superblock_checksum(superblock* sb);
 
 #ifdef _MSC_VER
 #define funcname __FUNCTION__
@@ -1159,6 +1193,10 @@ extern uint32_t mount_readonly;
 extern uint32_t mount_no_root_dir;
 extern uint32_t no_pnp;
 
+#ifndef __GNUC__
+#define __attribute__(x)
+#endif
+
 #ifdef _DEBUG
 
 extern bool log_started;
@@ -1166,25 +1204,25 @@ extern uint32_t debug_log_level;
 
 #ifdef DEBUG_LONG_MESSAGES
 
-#define MSG(fn, file, line, s, level, ...) (!log_started || level <= debug_log_level) ? _debug_message(fn, file, line, s, ##__VA_ARGS__) : 0
+#define MSG(fn, file, line, s, level, ...) (!log_started || level <= debug_log_level) ? _debug_message(fn, file, line, s, ##__VA_ARGS__) : (void)0
 
 #define TRACE(s, ...) MSG(funcname, __FILE__, __LINE__, s, 3, ##__VA_ARGS__)
 #define WARN(s, ...) MSG(funcname, __FILE__, __LINE__, s, 2, ##__VA_ARGS__)
 #define FIXME(s, ...) MSG(funcname, __FILE__, __LINE__, s, 1, ##__VA_ARGS__)
 #define ERR(s, ...) MSG(funcname, __FILE__, __LINE__, s, 1, ##__VA_ARGS__)
 
-void _debug_message(_In_ const char* func, _In_ const char* file, _In_ unsigned int line, _In_ char* s, ...);
+void _debug_message(_In_ const char* func, _In_ const char* file, _In_ unsigned int line, _In_ char* s, ...) __attribute__((format(printf, 4, 5)));
 
 #else
 
-#define MSG(fn, s, level, ...) (!log_started || level <= debug_log_level) ? _debug_message(fn, s, ##__VA_ARGS__) : 0
+#define MSG(fn, s, level, ...) (!log_started || level <= debug_log_level) ? _debug_message(fn, s, ##__VA_ARGS__) : (void)0
 
 #define TRACE(s, ...) MSG(funcname, s, 3, ##__VA_ARGS__)
 #define WARN(s, ...) MSG(funcname, s, 2, ##__VA_ARGS__)
 #define FIXME(s, ...) MSG(funcname, s, 1, ##__VA_ARGS__)
 #define ERR(s, ...) MSG(funcname, s, 1, ##__VA_ARGS__)
 
-void _debug_message(_In_ const char* func, _In_ char* s, ...);
+void _debug_message(_In_ const char* func, _In_ char* s, ...) __attribute__((format(printf, 2, 3)));
 
 #endif
 
@@ -1205,8 +1243,13 @@ void _free_fcb(_Inout_ fcb* fcb, _In_ const char* func);
 // in fastio.c
 void init_fast_io_dispatch(FAST_IO_DISPATCH** fiod);
 
-// in crc32c.c
-uint32_t calc_crc32c(_In_ uint32_t seed, _In_reads_bytes_(msglen) uint8_t* msg, _In_ ULONG msglen);
+// in sha256.c
+void calc_sha256(uint8_t* hash, const void* input, size_t len);
+#define SHA256_HASH_SIZE 32
+
+// in blake2b-ref.c
+void blake2b(void *out, size_t outlen, const void* in, size_t inlen);
+#define BLAKE2_HASH_SIZE 32
 
 typedef struct {
     LIST_ENTRY* list;
@@ -1315,14 +1358,11 @@ bool insert_extent_chunk(_In_ device_extension* Vcb, _In_ fcb* fcb, _In_ chunk*
                          _In_opt_ PIRP Irp, _In_ LIST_ENTRY* rollback, _In_ uint8_t compression, _In_ uint64_t decoded_size, _In_ bool file_write, _In_ uint64_t irp_offset);
 
 NTSTATUS do_write_file(fcb* fcb, uint64_t start_data, uint64_t end_data, void* data, PIRP Irp, bool file_write, uint32_t irp_offset, LIST_ENTRY* rollback);
-NTSTATUS write_compressed(fcb* fcb, uint64_t start_data, uint64_t end_data, void* data, PIRP Irp, LIST_ENTRY* rollback);
 bool find_data_address_in_chunk(device_extension* Vcb, chunk* c, uint64_t length, uint64_t* address);
 void get_raid56_lock_range(chunk* c, uint64_t address, uint64_t length, uint64_t* lockaddr, uint64_t* locklen);
-NTSTATUS calc_csum(_In_ device_extension* Vcb, _In_reads_bytes_(sectors*Vcb->superblock.sector_size) uint8_t* data,
-                   _In_ uint32_t sectors, _Out_writes_bytes_(sectors*sizeof(uint32_t)) uint32_t* csum);
 void add_insert_extent_rollback(LIST_ENTRY* rollback, fcb* fcb, extent* ext);
 NTSTATUS add_extent_to_fcb(_In_ fcb* fcb, _In_ uint64_t offset, _In_reads_bytes_(edsize) EXTENT_DATA* ed, _In_ uint16_t edsize,
-                           _In_ bool unique, _In_opt_ _When_(return >= 0, __drv_aliasesMem) uint32_t* csum, _In_ LIST_ENTRY* rollback);
+                           _In_ bool unique, _In_opt_ _When_(return >= 0, __drv_aliasesMem) void* csum, _In_ LIST_ENTRY* rollback);
 void add_extent(_In_ fcb* fcb, _In_ LIST_ENTRY* prevextle, _In_ __drv_aliasesMem extent* newext);
 
 // in dirctrl.c
@@ -1393,7 +1433,7 @@ NTSTATUS open_fileref(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusiv
                       _In_ bool case_sensitive, _In_opt_ PIRP Irp);
 NTSTATUS open_fcb(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension* Vcb,
                   root* subvol, uint64_t inode, uint8_t type, PANSI_STRING utf8, bool always_add_hl, fcb* parent, fcb** pfcb, POOL_TYPE pooltype, PIRP Irp);
-NTSTATUS load_csum(_Requires_lock_held_(_Curr_->tree_lock) device_extension* Vcb, uint32_t* csum, uint64_t start, uint64_t length, PIRP Irp);
+NTSTATUS load_csum(_Requires_lock_held_(_Curr_->tree_lock) device_extension* Vcb, void* csum, uint64_t start, uint64_t length, PIRP Irp);
 NTSTATUS load_dir_children(_Requires_lock_held_(_Curr_->tree_lock) device_extension* Vcb, fcb* fcb, bool ignore_size, PIRP Irp);
 NTSTATUS add_dir_child(fcb* fcb, uint64_t inode, bool subvol, PANSI_STRING utf8, PUNICODE_STRING name, uint8_t type, dir_child** pdc);
 NTSTATUS open_fileref_child(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension* Vcb,
@@ -1425,13 +1465,14 @@ NTSTATUS write_data_phys(_In_ PDEVICE_OBJECT device, _In_ PFILE_OBJECT fileobj,
                          _In_reads_bytes_(length) void* data, _In_ uint32_t length);
 bool is_tree_unique(device_extension* Vcb, tree* t, PIRP Irp);
 NTSTATUS do_tree_writes(device_extension* Vcb, LIST_ENTRY* tree_writes, bool no_free);
-void add_checksum_entry(device_extension* Vcb, uint64_t address, ULONG length, uint32_t* csum, PIRP Irp);
+void add_checksum_entry(device_extension* Vcb, uint64_t address, ULONG length, void* csum, PIRP Irp);
 bool find_metadata_address_in_chunk(device_extension* Vcb, chunk* c, uint64_t* address);
 void add_trim_entry_avoid_sb(device_extension* Vcb, device* dev, uint64_t address, uint64_t size);
 NTSTATUS insert_tree_item_batch(LIST_ENTRY* batchlist, device_extension* Vcb, root* r, uint64_t objid, uint8_t objtype, uint64_t offset,
                                 _In_opt_ _When_(return >= 0, __drv_aliasesMem) void* data, uint16_t datalen, enum batch_operation operation);
 NTSTATUS flush_partial_stripe(device_extension* Vcb, chunk* c, partial_stripe* ps);
 NTSTATUS update_dev_item(device_extension* Vcb, device* device, PIRP Irp);
+void calc_tree_checksum(device_extension* Vcb, tree_header* th);
 
 // in read.c
 
@@ -1439,14 +1480,18 @@ _Dispatch_type_(IRP_MJ_READ)
 _Function_class_(DRIVER_DISPATCH)
 NTSTATUS __stdcall drv_read(PDEVICE_OBJECT DeviceObject, PIRP Irp);
 
-NTSTATUS read_data(_In_ device_extension* Vcb, _In_ uint64_t addr, _In_ uint32_t length, _In_reads_bytes_opt_(length*sizeof(uint32_t)/Vcb->superblock.sector_size) uint32_t* csum,
+NTSTATUS read_data(_In_ device_extension* Vcb, _In_ uint64_t addr, _In_ uint32_t length, _In_reads_bytes_opt_(length*sizeof(uint32_t)/Vcb->superblock.sector_size) void* csum,
                    _In_ bool is_tree, _Out_writes_bytes_(length) uint8_t* buf, _In_opt_ chunk* c, _Out_opt_ chunk** pc, _In_opt_ PIRP Irp, _In_ uint64_t generation, _In_ bool file_read,
                    _In_ ULONG priority);
 NTSTATUS read_file(fcb* fcb, uint8_t* data, uint64_t start, uint64_t length, ULONG* pbr, PIRP Irp);
 NTSTATUS read_stream(fcb* fcb, uint8_t* data, uint64_t start, ULONG length, ULONG* pbr);
 NTSTATUS do_read(PIRP Irp, bool wait, ULONG* bytes_read);
-NTSTATUS check_csum(device_extension* Vcb, uint8_t* data, uint32_t sectors, uint32_t* csum);
+NTSTATUS check_csum(device_extension* Vcb, uint8_t* data, uint32_t sectors, void* csum);
 void raid6_recover2(uint8_t* sectors, uint16_t num_stripes, ULONG sector_size, uint16_t missing1, uint16_t missing2, uint8_t* out);
+void get_tree_checksum(device_extension* Vcb, tree_header* th, void* csum);
+bool check_tree_checksum(device_extension* Vcb, tree_header* th);
+void get_sector_csum(device_extension* Vcb, void* buf, void* csum);
+bool check_sector_csum(device_extension* Vcb, void* buf, void* csum);
 
 // in pnp.c
 
@@ -1505,7 +1550,10 @@ void watch_registry(HANDLE regh);
 NTSTATUS zlib_decompress(uint8_t* inbuf, uint32_t inlen, uint8_t* outbuf, uint32_t outlen);
 NTSTATUS lzo_decompress(uint8_t* inbuf, uint32_t inlen, uint8_t* outbuf, uint32_t outlen, uint32_t inpageoff);
 NTSTATUS zstd_decompress(uint8_t* inbuf, uint32_t inlen, uint8_t* outbuf, uint32_t outlen);
-NTSTATUS write_compressed_bit(fcb* fcb, uint64_t start_data, uint64_t end_data, void* data, bool* compressed, PIRP Irp, LIST_ENTRY* rollback);
+NTSTATUS write_compressed(fcb* fcb, uint64_t start_data, uint64_t end_data, void* data, PIRP Irp, LIST_ENTRY* rollback);
+NTSTATUS zlib_compress(uint8_t* inbuf, uint32_t inlen, uint8_t* outbuf, uint32_t outlen, unsigned int level, unsigned int* space_left);
+NTSTATUS lzo_compress(uint8_t* inbuf, uint32_t inlen, uint8_t* outbuf, uint32_t outlen, unsigned int* space_left);
+NTSTATUS zstd_compress(uint8_t* inbuf, uint32_t inlen, uint8_t* outbuf, uint32_t outlen, uint32_t level, unsigned int* space_left);
 
 // in galois.c
 void galois_double(uint8_t* data, uint32_t len);
@@ -1525,8 +1573,12 @@ NTSTATUS __stdcall drv_device_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Ir
 _Function_class_(KSTART_ROUTINE)
 void __stdcall calc_thread(void* context);
 
-NTSTATUS add_calc_job(device_extension* Vcb, uint8_t* data, uint32_t sectors, uint32_t* csum, calc_job** pcj);
-void free_calc_job(calc_job* cj);
+void do_calc_job(device_extension* Vcb, uint8_t* data, uint32_t sectors, void* csum);
+NTSTATUS add_calc_job_decomp(device_extension* Vcb, uint8_t compression, void* in, unsigned int inlen,
+                             void* out, unsigned int outlen, unsigned int off, calc_job** pcj);
+NTSTATUS add_calc_job_comp(device_extension* Vcb, uint8_t compression, void* in, unsigned int inlen,
+                           void* out, unsigned int outlen, calc_job** pcj);
+void calc_thread_main(device_extension* Vcb, calc_job* cj);
 
 // in balance.c
 NTSTATUS start_balance(device_extension* Vcb, void* data, ULONG length, KPROCESSOR_MODE processor_mode);
@@ -1584,6 +1636,8 @@ NTSTATUS __stdcall compat_FsRtlValidateReparsePointBuffer(IN ULONG BufferLength,
 
 // in boot.c
 void __stdcall check_system_root(PDRIVER_OBJECT DriverObject, PVOID Context, ULONG Count);
+void boot_add_device(DEVICE_OBJECT* pdo);
+extern BTRFS_UUID boot_uuid;
 
 // based on function in sys/sysmacros.h
 #define makedev(major, minor) (((minor) & 0xFF) | (((major) & 0xFFF) << 8) | (((uint64_t)((minor) & ~0xFF)) << 12) | (((uint64_t)((major) & ~0xFFF)) << 32))
@@ -1624,7 +1678,7 @@ typedef struct {
 } FSRTL_ADVANCED_FCB_HEADER_NEW;
 
 #define FSRTL_FCB_HEADER_V2 2
-#endif
+#endif // __REACTOS__
 
 static __inline POPLOCK fcb_oplock(fcb* fcb) {
     if (fcb->Header.Version >= FSRTL_FCB_HEADER_V2)
@@ -1675,10 +1729,9 @@ static __inline bool write_fcb_compressed(fcb* fcb) {
 static __inline void do_xor(uint8_t* buf1, uint8_t* buf2, uint32_t len) {
     uint32_t j;
 #ifndef __REACTOS__
+#if defined(_X86_) || defined(_AMD64_)
     __m128i x1, x2;
-#endif
 
-#ifndef __REACTOS__
     if (have_sse2 && ((uintptr_t)buf1 & 0xf) == 0 && ((uintptr_t)buf2 & 0xf) == 0) {
         while (len >= 16) {
             x1 = _mm_load_si128((__m128i*)buf1);
@@ -1686,12 +1739,28 @@ static __inline void do_xor(uint8_t* buf1, uint8_t* buf2, uint32_t len) {
             x1 = _mm_xor_si128(x1, x2);
             _mm_store_si128((__m128i*)buf1, x1);
 
+            buf1 += 16;
+            buf2 += 16;
+            len -= 16;
+        }
+    }
+#elif defined(_ARM_) || defined(_ARM64_)
+    uint64x2_t x1, x2;
+
+    if (((uintptr_t)buf1 & 0xf) == 0 && ((uintptr_t)buf2 & 0xf) == 0) {
+        while (len >= 16) {
+            x1 = vld1q_u64((const uint64_t*)buf1);
+            x2 = vld1q_u64((const uint64_t*)buf2);
+            x1 = veorq_u64(x1, x2);
+            vst1q_u64((uint64_t*)buf1, x1);
+
             buf1 += 16;
             buf2 += 16;
             len -= 16;
         }
     }
 #endif
+#endif // __REACTOS__
 
     for (j = 0; j < len; j++) {
         *buf1 ^= *buf2;
@@ -1895,7 +1964,7 @@ typedef struct _PEB {
     PVOID Reserved7[1];
     ULONG SessionId;
 } PEB,*PPEB;
-#endif
+#endif /* __REACTOS__ */
 
 #ifdef _MSC_VER
 __kernel_entry