ReactOS 0.4.15-dev-7788-g1ad9096
btrfs_drv.h File Reference
#include <ntifs.h>
#include <ntddk.h>
#include <mountmgr.h>
#include <windef.h>
#include <wdm.h>
#include <stdio.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include "btrfs.h"
#include "btrfsioctl.h"
Include dependency graph for btrfs_drv.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  _FILE_ID_128
 
struct  _DUPLICATE_EXTENTS_DATA
 
struct  _FSCTL_GET_INTEGRITY_INFORMATION_BUFFER
 
struct  _FSCTL_SET_INTEGRITY_INFORMATION_BUFFER
 
struct  _fcb_nonpaged
 
struct  extent
 
struct  hardlink
 
struct  dir_child
 
struct  xattr
 
struct  _fcb
 
struct  _file_ref
 
struct  send_info
 
struct  _ccb
 
struct  tree_holder
 
struct  _tree_data
 
struct  tree_nonpaged
 
struct  _tree
 
struct  root_nonpaged
 
struct  _root
 
struct  batch_item
 
struct  batch_item_ind
 
struct  batch_root
 
struct  traverse_ptr
 
struct  _root_cache
 
struct  space
 
struct  device
 
struct  range_lock
 
struct  partial_stripe
 
struct  chunk
 
struct  changed_extent
 
struct  changed_extent_ref
 
struct  sys_chunk
 
struct  calc_job
 
struct  drv_calc_thread
 
struct  drv_calc_threads
 
struct  mount_options
 
struct  balance_info
 
struct  scrub_error
 
struct  scrub_info
 
struct  _device_extension
 
struct  control_device_extension
 
struct  bus_device_extension
 
struct  volume_child
 
struct  _volume_device_extension
 
struct  pdo_device_extension
 
struct  uid_map
 
struct  gid_map
 
struct  write_data_stripe
 
struct  _write_data_context
 
struct  tree_write
 
struct  name_bit
 
struct  rollback_space
 
struct  rollback_extent
 
struct  rollback_item
 
struct  ea_item
 
struct  FSRTL_ADVANCED_FCB_HEADER_NEW
 
struct  _LDR_DATA_TABLE_ENTRY
 
struct  _PEB_LDR_DATA
 
struct  _RTL_USER_PROCESS_PARAMETERS
 
struct  _PEB
 

Macros

#define _WIN32_WINNT   0x0601
 
#define NTDDI_VERSION   0x06020000
 
#define _CRT_SECURE_NO_WARNINGS
 
#define _NO_CRT_STDIO_INLINE
 
#define UNUSED(x)   (void)(x)
 
#define BTRFS_NODE_TYPE_CCB   0x2295
 
#define BTRFS_NODE_TYPE_FCB   0x2296
 
#define ALLOC_TAG   0x7442484D
 
#define ALLOC_TAG_ZLIB   0x7A42484D
 
#define UID_NOBODY   65534
 
#define GID_NOBODY   65534
 
#define EA_NTACL   "security.NTACL"
 
#define EA_NTACL_HASH   0x45922146
 
#define EA_DOSATTRIB   "user.DOSATTRIB"
 
#define EA_DOSATTRIB_HASH   0x914f9939
 
#define EA_REPARSE   "user.reparse"
 
#define EA_REPARSE_HASH   0xfabad1fe
 
#define EA_EA   "user.EA"
 
#define EA_EA_HASH   0x8270dd43
 
#define EA_CASE_SENSITIVE   "user.casesensitive"
 
#define EA_CASE_SENSITIVE_HASH   0x1a9d97d4
 
#define EA_PROP_COMPRESSION   "btrfs.compression"
 
#define EA_PROP_COMPRESSION_HASH   0x20ccdf69
 
#define MAX_EXTENT_SIZE   0x8000000
 
#define COMPRESSED_EXTENT_SIZE   0x20000
 
#define READ_AHEAD_GRANULARITY   COMPRESSED_EXTENT_SIZE
 
#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
 
#define BTRFS_VOLUME_PREFIX   L"\\Device\\Btrfs{"
 
#define try   if (1)
 
#define except(x)   if (0 && (x))
 
#define finally   if (1)
 
#define leave
 
#define InterlockedIncrement64(a)   __sync_add_and_fetch(a, 1)
 
#define FILE_SUPPORTS_BLOCK_REFCOUNTING   0x08000000
 
#define FILE_SUPPORTS_POSIX_UNLINK_RENAME   0x00000400
 
#define FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL   0x00020000
 
#define FILE_CS_FLAG_CASE_SENSITIVE_DIR   1
 
#define FSCTL_DUPLICATE_EXTENTS_TO_FILE   CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 209, METHOD_BUFFERED, FILE_WRITE_ACCESS)
 
#define FSCTL_GET_INTEGRITY_INFORMATION   CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 159, METHOD_BUFFERED, FILE_ANY_ACCESS)
 
#define FSCTL_SET_INTEGRITY_INFORMATION   CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 160, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
 
#define __drv_aliasesMem
 
#define _Dispatch_type_(a)
 
#define _Lock_level_order_(a, b)
 
#define MAX_HASH_SIZE   32
 
#define VCB_TYPE_FS   1
 
#define VCB_TYPE_CONTROL   2
 
#define VCB_TYPE_VOLUME   3
 
#define VCB_TYPE_PDO   4
 
#define VCB_TYPE_BUS   5
 
#define BALANCE_OPTS_DATA   0
 
#define BALANCE_OPTS_METADATA   1
 
#define BALANCE_OPTS_SYSTEM   2
 
#define keycmp(key1, key2)
 
#define acquire_chunk_lock(c, Vcb)   ExAcquireResourceExclusiveLite(&(c)->lock, true)
 
#define release_chunk_lock(c, Vcb)   ExReleaseResourceLite(&(c)->lock)
 
#define funcname   __func__
 
#define __attribute__(x)
 
#define TRACE(s, ...)   do { } while(0)
 
#define WARN(s, ...)   do { } while(0)
 
#define FIXME(s, ...)   DbgPrint("Btrfs FIXME : %s : " s, funcname, ##__VA_ARGS__)
 
#define ERR(s, ...)   DbgPrint("Btrfs ERR : %s : " s, funcname, ##__VA_ARGS__)
 
#define SHA256_HASH_SIZE   32
 
#define BLAKE2_HASH_SIZE   32
 
#define makedev(major, minor)   (((minor) & 0xFF) | (((major) & 0xFFF) << 8) | (((uint64_t)((minor) & ~0xFF)) << 12) | (((uint64_t)((major) & ~0xFFF)) << 32))
 
#define FSRTL_FCB_HEADER_V2   2
 
#define increase_fileref_refcount(fileref)   InterlockedIncrement(&fileref->refcount)
 
#define int3   asm("int3;")
 
#define hex_digit(c)   ((c) <= 9) ? ((c) + '0') : ((c) - 10 + 'a')
 
#define __S_IFMT   0170000 /* These bits determine file type. */
 
#define __S_IFDIR   0040000 /* Directory. */
 
#define __S_IFCHR   0020000 /* Character device. */
 
#define __S_IFBLK   0060000 /* Block device. */
 
#define __S_IFREG   0100000 /* Regular file. */
 
#define __S_IFIFO   0010000 /* FIFO. */
 
#define __S_IFLNK   0120000 /* Symbolic link. */
 
#define __S_IFSOCK   0140000 /* Socket. */
 
#define __S_ISTYPE(mode, mask)   (((mode) & __S_IFMT) == (mask))
 
#define S_ISDIR(mode)   __S_ISTYPE((mode), __S_IFDIR)
 
#define S_IRUSR   0000400
 
#define S_IWUSR   0000200
 
#define S_IXUSR   0000100
 
#define S_IRGRP   (S_IRUSR >> 3)
 
#define S_IWGRP   (S_IWUSR >> 3)
 
#define S_IXGRP   (S_IXUSR >> 3)
 
#define S_IROTH   (S_IRGRP >> 3)
 
#define S_IWOTH   (S_IWGRP >> 3)
 
#define S_IXOTH   (S_IXGRP >> 3)
 
#define S_ISUID   0004000
 
#define S_ISGID   0002000
 
#define S_ISVTX   0001000
 
#define major(rdev)   ((((rdev) >> 8) & 0xFFF) | ((uint32_t)((rdev) >> 32) & ~0xFFF))
 
#define minor(rdev)   (((rdev) & 0xFF) | ((uint32_t)((rdev) >> 12) & ~0xFF))
 
#define CC_ENABLE_DISK_IO_ACCOUNTING   0x00000010
 

Typedefs

typedef struct _FILE_ID_128 FILE_ID_128
 
typedef struct _FILE_ID_128PFILE_ID_128
 
typedef struct _DUPLICATE_EXTENTS_DATA DUPLICATE_EXTENTS_DATA
 
typedef struct _DUPLICATE_EXTENTS_DATAPDUPLICATE_EXTENTS_DATA
 
typedef struct _FSCTL_GET_INTEGRITY_INFORMATION_BUFFER FSCTL_GET_INTEGRITY_INFORMATION_BUFFER
 
typedef struct _FSCTL_GET_INTEGRITY_INFORMATION_BUFFERPFSCTL_GET_INTEGRITY_INFORMATION_BUFFER
 
typedef struct _FSCTL_SET_INTEGRITY_INFORMATION_BUFFER FSCTL_SET_INTEGRITY_INFORMATION_BUFFER
 
typedef struct _FSCTL_SET_INTEGRITY_INFORMATION_BUFFERPFSCTL_SET_INTEGRITY_INFORMATION_BUFFER
 
typedef struct _fcb_nonpaged fcb_nonpaged
 
typedef struct _fcb fcb
 
typedef struct _file_ref file_ref
 
typedef struct _ccb ccb
 
typedef struct _tree_data tree_data
 
typedef struct _tree tree
 
typedef struct _root root
 
typedef struct _root_cache root_cache
 
typedef struct _device_extension device_extension
 
typedef struct _volume_device_extension volume_device_extension
 
typedef struct pdo_device_extension pdo_device_extension
 
typedef struct _write_data_context write_data_context
 
typedef void(__stdcallxor_func) (uint8_t *buf1, uint8_t *buf2, uint32_t len)
 
typedef BOOLEAN(__stdcalltPsIsDiskCountersEnabled) ()
 
typedef VOID(__stdcalltPsUpdateDiskCounters) (PEPROCESS Process, ULONG64 BytesRead, ULONG64 BytesWritten, ULONG ReadOperationCount, ULONG WriteOperationCount, ULONG FlushOperationCount)
 
typedef BOOLEAN(__stdcalltCcCopyWriteEx) (PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, BOOLEAN Wait, PVOID Buffer, PETHREAD IoIssuerThread)
 
typedef BOOLEAN(__stdcalltCcCopyReadEx) (PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, BOOLEAN Wait, PVOID Buffer, PIO_STATUS_BLOCK IoStatus, PETHREAD IoIssuerThread)
 
typedef VOID(__stdcalltCcSetAdditionalCacheAttributesEx) (PFILE_OBJECT FileObject, ULONG Flags)
 
typedef VOID(__stdcalltFsRtlUpdateDiskCounters) (ULONG64 BytesRead, ULONG64 BytesWritten)
 
typedef NTSTATUS(__stdcalltIoUnregisterPlugPlayNotificationEx) (PVOID NotificationEntry)
 
typedef NTSTATUS(__stdcalltFsRtlGetEcpListFromIrp) (PIRP Irp, PECP_LIST *EcpList)
 
typedef NTSTATUS(__stdcalltFsRtlGetNextExtraCreateParameter) (PECP_LIST EcpList, PVOID CurrentEcpContext, LPGUID NextEcpType, PVOID *NextEcpContext, ULONG *NextEcpContextSize)
 
typedef NTSTATUS(__stdcalltFsRtlValidateReparsePointBuffer) (ULONG BufferLength, PREPARSE_DATA_BUFFER ReparseBuffer)
 
typedef BOOLEAN(__stdcalltFsRtlCheckLockForOplockRequest) (PFILE_LOCK FileLock, PLARGE_INTEGER AllocationSize)
 
typedef BOOLEAN(__stdcalltFsRtlAreThereCurrentOrInProgressFileLocks) (PFILE_LOCK FileLock)
 
typedef struct _LDR_DATA_TABLE_ENTRY LDR_DATA_TABLE_ENTRY
 
typedef struct _LDR_DATA_TABLE_ENTRYPLDR_DATA_TABLE_ENTRY
 
typedef struct _PEB_LDR_DATA PEB_LDR_DATA
 
typedef struct _PEB_LDR_DATAPPEB_LDR_DATA
 
typedef struct _RTL_USER_PROCESS_PARAMETERS RTL_USER_PROCESS_PARAMETERS
 
typedef struct _RTL_USER_PROCESS_PARAMETERSPRTL_USER_PROCESS_PARAMETERS
 
typedef VOID(NTAPIPPS_POST_PROCESS_INIT_ROUTINE) (VOID)
 
typedef struct _PEB PEB
 
typedef struct _PEBPPEB
 

Enumerations

enum  prop_compression_type { PropCompression_None , PropCompression_Zlib , PropCompression_LZO , PropCompression_ZSTD }
 
enum  batch_operation {
  Batch_Delete , Batch_DeleteInode , Batch_DeleteDirItem , Batch_DeleteInodeRef ,
  Batch_DeleteInodeExtRef , Batch_DeleteXattr , Batch_DeleteExtentData , Batch_DeleteFreeSpace ,
  Batch_Insert , Batch_SetXattr , Batch_DirItem , Batch_InodeRef ,
  Batch_InodeExtRef
}
 
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
}
 
enum  write_data_status {
  WriteDataStatus_Pending , WriteDataStatus_Success , WriteDataStatus_Error , WriteDataStatus_Cancelling ,
  WriteDataStatus_Cancelled , WriteDataStatus_Ignore
}
 
enum  rollback_type { ROLLBACK_INSERT_EXTENT , ROLLBACK_DELETE_EXTENT , ROLLBACK_ADD_SPACE , ROLLBACK_SUBTRACT_SPACE }
 

Functions

 _Create_lock_level_ (tree_lock) _Create_lock_level_(fcb_lock) _Lock_level_order_(tree_lock
 
 _Requires_lock_not_held_ (Vcb->fcb_lock) _Acquires_shared_lock_(Vcb -> fcb_lock) static __inline void acquire_fcb_lock_shared(device_extension *Vcb)
 
 _Requires_lock_held_ (Vcb->fcb_lock) _Releases_lock_(Vcb -> fcb_lock) static __inline void release_fcb_lock(device_extension *Vcb)
 
static __inline voidmap_user_buffer (PIRP Irp, ULONG priority)
 
static __inline uint64_t unix_time_to_win (BTRFS_TIME *t)
 
static __inline void win_time_to_unix (LARGE_INTEGER t, BTRFS_TIME *out)
 
_Post_satisfies_ static stripe __inline void get_raid0_offset (_In_ uint64_t off, _In_ uint64_t stripe_length, _In_ uint16_t num_stripes, _Out_ uint64_t *stripeoff, _Out_ uint16_t *stripe)
 
static __inline uint64_t make_file_id (root *r, uint64_t inode)
 
 _Post_satisfies_ (return >=n) __inline static uint64_t sector_align(_In_ uint64_t n
 
static __inline bool is_subvol_readonly (root *r, PIRP Irp)
 
static __inline uint16_t get_extent_data_len (uint8_t type)
 
static __inline uint32_t get_extent_data_refcount (uint8_t type, void *data)
 
_Ret_maybenull_ devicefind_device_from_uuid (_In_ device_extension *Vcb, _In_ BTRFS_UUID *uuid)
 
 _Success_ (return) bool get_file_attributes_from_xattr(_In_reads_bytes_(len) char *val
 
ULONG get_file_attributes (_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_ uint64_t inode, _In_ uint8_t type, _In_ bool dotfile, _In_ bool ignore_xa, _In_opt_ PIRP Irp)
 
void free_fcb (_Inout_ fcb *fcb)
 
void free_fileref (_Inout_ file_ref *fr)
 
void protect_superblocks (_Inout_ chunk *c)
 
bool is_top_level (_In_ PIRP Irp)
 
NTSTATUS create_root (_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ uint64_t id, _Out_ root **rootptr, _In_ bool no_tree, _In_ uint64_t offset, _In_opt_ PIRP Irp)
 
void uninit (_In_ device_extension *Vcb)
 
NTSTATUS dev_ioctl (_In_ PDEVICE_OBJECT DeviceObject, _In_ ULONG ControlCode, _In_reads_bytes_opt_(InputBufferSize) PVOID InputBuffer, _In_ ULONG InputBufferSize, _Out_writes_bytes_opt_(OutputBufferSize) PVOID OutputBuffer, _In_ ULONG OutputBufferSize, _In_ bool Override, _Out_opt_ IO_STATUS_BLOCK *iosb)
 
NTSTATUS check_file_name_valid (_In_ PUNICODE_STRING us, _In_ bool posix, _In_ bool stream)
 
void send_notification_fileref (_In_ file_ref *fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream)
 
void queue_notification_fcb (_In_ file_ref *fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream)
 
void mark_fcb_dirty (_In_ fcb *fcb)
 
void mark_fileref_dirty (_In_ file_ref *fileref)
 
NTSTATUS delete_fileref (_In_ file_ref *fileref, _In_opt_ PFILE_OBJECT FileObject, _In_ bool make_orphan, _In_opt_ PIRP Irp, _In_ LIST_ENTRY *rollback)
 
void chunk_lock_range (_In_ device_extension *Vcb, _In_ chunk *c, _In_ uint64_t start, _In_ uint64_t length)
 
void chunk_unlock_range (_In_ device_extension *Vcb, _In_ chunk *c, _In_ uint64_t start, _In_ uint64_t length)
 
void init_device (_In_ device_extension *Vcb, _Inout_ device *dev, _In_ bool get_nums)
 
void init_file_cache (_In_ PFILE_OBJECT FileObject, _In_ CC_FILE_SIZES *ccfs)
 
NTSTATUS sync_read_phys (_In_ PDEVICE_OBJECT DeviceObject, _In_ PFILE_OBJECT FileObject, _In_ uint64_t StartingOffset, _In_ ULONG Length, _Out_writes_bytes_(Length) PUCHAR Buffer, _In_ bool override)
 
NTSTATUS get_device_pnp_name (_In_ PDEVICE_OBJECT DeviceObject, _Out_ PUNICODE_STRING pnp_name, _Out_ const GUID **guid)
 
void log_device_error (_In_ device_extension *Vcb, _Inout_ device *dev, _In_ int error)
 
NTSTATUS find_chunk_usage (_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_opt_ PIRP Irp)
 
 _Function_class_ (DRIVER_ADD_DEVICE) NTSTATUS __stdcall AddDevice(PDRIVER_OBJECT DriverObject
 
void reap_fcb (fcb *fcb)
 
void reap_fcbs (device_extension *Vcb)
 
void reap_fileref (device_extension *Vcb, file_ref *fr)
 
void reap_filerefs (device_extension *Vcb, file_ref *fr)
 
NTSTATUS utf8_to_utf16 (WCHAR *dest, ULONG dest_max, ULONG *dest_len, char *src, ULONG src_len)
 
NTSTATUS utf16_to_utf8 (char *dest, ULONG dest_max, ULONG *dest_len, WCHAR *src, ULONG src_len)
 
uint32_t get_num_of_processors ()
 
_Ret_maybenull_ rootfind_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)
 
void init_fast_io_dispatch (FAST_IO_DISPATCH **fiod)
 
void calc_sha256 (uint8_t *hash, const void *input, size_t len)
 
void blake2b (void *out, size_t outlen, const void *in, size_t inlen)
 
NTSTATUS find_item (_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _Out_ traverse_ptr *tp, _In_ const KEY *searchkey, _In_ bool ignore, _In_opt_ PIRP Irp) __attribute__((nonnull(1
 
NTSTATUS NTSTATUS find_item_to_level (device_extension *Vcb, root *r, traverse_ptr *tp, const KEY *searchkey, bool ignore, uint8_t level, PIRP Irp) __attribute__((nonnull(1
 
NTSTATUS NTSTATUS bool find_next_item (_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, const traverse_ptr *tp, traverse_ptr *next_tp, bool ignore, PIRP Irp) __attribute__((nonnull(1
 
NTSTATUS NTSTATUS bool bool find_prev_item (_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, const traverse_ptr *tp, traverse_ptr *prev_tp, PIRP Irp) __attribute__((nonnull(1
 
NTSTATUS NTSTATUS bool bool void free_trees (device_extension *Vcb) __attribute__((nonnull(1)))
 
NTSTATUS insert_tree_item (_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_ uint64_t obj_id, _In_ uint8_t obj_type, _In_ uint64_t offset, _In_reads_bytes_opt_(size) _When_(return >=0, __drv_aliasesMem) void *data, _In_ uint16_t size, _Out_opt_ traverse_ptr *ptp, _In_opt_ PIRP Irp) __attribute__((nonnull(1
 
NTSTATUS NTSTATUS delete_tree_item (_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp) __attribute__((nonnull(1
 
NTSTATUS NTSTATUS void free_tree (tree *t) __attribute__((nonnull(1)))
 
NTSTATUS load_tree (device_extension *Vcb, uint64_t addr, uint8_t *buf, root *r, tree **pt) __attribute__((nonnull(1
 
NTSTATUS NTSTATUS do_load_tree (device_extension *Vcb, tree_holder *th, root *r, tree *t, tree_data *td, PIRP Irp) __attribute__((nonnull(1
 
NTSTATUS NTSTATUS void clear_rollback (LIST_ENTRY *rollback) __attribute__((nonnull(1)))
 
void do_rollback (device_extension *Vcb, LIST_ENTRY *rollback) __attribute__((nonnull(1
 
void void free_trees_root (device_extension *Vcb, root *r) __attribute__((nonnull(1
 
void void void add_rollback (_In_ LIST_ENTRY *rollback, _In_ enum rollback_type type, _In_ __drv_aliasesMem void *ptr) __attribute__((nonnull(1
 
void void void NTSTATUS commit_batch_list (_Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, LIST_ENTRY *batchlist, PIRP Irp) __attribute__((nonnull(1
 
void void void NTSTATUS void clear_batch_list (device_extension *Vcb, LIST_ENTRY *batchlist) __attribute__((nonnull(1
 
void void void NTSTATUS void NTSTATUS skip_to_difference (device_extension *Vcb, traverse_ptr *tp, traverse_ptr *tp2, bool *ended1, bool *ended2) __attribute__((nonnull(1
 
void void void NTSTATUS void NTSTATUS NTSTATUS remove_drive_letter (PDEVICE_OBJECT mountmgr, PUNICODE_STRING devpath)
 
 _Function_class_ (KSTART_ROUTINE) void __stdcall mountmgr_thread(_In_ void *context)
 
 _Function_class_ (DRIVER_NOTIFICATION_CALLBACK_ROUTINE) NTSTATUS __stdcall pnp_notification(PVOID NotificationStructure
 
void disk_arrival (PUNICODE_STRING devpath)
 
bool volume_arrival (PUNICODE_STRING devpath, bool fve_callback)
 
void volume_removal (PUNICODE_STRING devpath)
 
void remove_volume_child (_Inout_ _Requires_exclusive_lock_held_(_Curr_->child_lock) _Releases_exclusive_lock_(_Curr_->child_lock) _In_ volume_device_extension *vde, _In_ volume_child *vc, _In_ bool skip_dev)
 
void init_cache ()
 
NTSTATUS write_file (device_extension *Vcb, PIRP Irp, bool wait, bool deferred_write) __attribute__((nonnull(1
 
NTSTATUS NTSTATUS write_file2 (device_extension *Vcb, PIRP Irp, LARGE_INTEGER offset, void *buf, ULONG *length, bool paging_io, bool no_cache, bool wait, bool deferred_write, bool write_irp, LIST_ENTRY *rollback) __attribute__((nonnull(1
 
NTSTATUS NTSTATUS NTSTATUS truncate_file (fcb *fcb, uint64_t end, PIRP Irp, LIST_ENTRY *rollback) __attribute__((nonnull(1
 
NTSTATUS NTSTATUS NTSTATUS NTSTATUS extend_file (fcb *fcb, file_ref *fileref, uint64_t end, bool prealloc, PIRP Irp, LIST_ENTRY *rollback) __attribute__((nonnull(1
 
NTSTATUS NTSTATUS NTSTATUS NTSTATUS NTSTATUS excise_extents (device_extension *Vcb, fcb *fcb, uint64_t start_data, uint64_t end_data, PIRP Irp, LIST_ENTRY *rollback) __attribute__((nonnull(1
 
NTSTATUS NTSTATUS NTSTATUS NTSTATUS NTSTATUS chunkget_chunk_from_address (device_extension *Vcb, uint64_t address) __attribute__((nonnull(1)))
 
NTSTATUS alloc_chunk (device_extension *Vcb, uint64_t flags, chunk **pc, bool full_size) __attribute__((nonnull(1
 
NTSTATUS NTSTATUS write_data (_In_ device_extension *Vcb, _In_ uint64_t address, _In_reads_bytes_(length) void *data, _In_ uint32_t length, _In_ write_data_context *wtc, _In_opt_ PIRP Irp, _In_opt_ chunk *c, _In_ bool file_write, _In_ uint64_t irp_offset, _In_ ULONG priority) __attribute__((nonnull(1
 
NTSTATUS NTSTATUS NTSTATUS write_data_complete (device_extension *Vcb, uint64_t address, void *data, uint32_t length, PIRP Irp, chunk *c, bool file_write, uint64_t irp_offset, ULONG priority) __attribute__((nonnull(1
 
NTSTATUS NTSTATUS NTSTATUS void free_write_data_stripes (write_data_context *wtc) __attribute__((nonnull(1)))
 
 _Dispatch_type_ (IRP_MJ_WRITE) _Function_class_(DRIVER_DISPATCH) NTSTATUS __stdcall drv_write(IN PDEVICE_OBJECT DeviceObject
 
IN PIRP Irp __attribute__ ((nonnull(1, 2)))
 
 _Requires_lock_held_ (c->lock) _When_(return !=0
 
 _Releases_lock_ (c->lock)) bool insert_extent_chunk(_In_ device_extension *Vcb
 
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t _In_ uint64_t _In_ bool _In_ uint64_t irp_offset __attribute__ ((nonnull(1, 2, 3, 9)))
 
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) __attribute__((nonnull(1
 
NTSTATUS bool find_data_address_in_chunk (device_extension *Vcb, chunk *c, uint64_t length, uint64_t *address) __attribute__((nonnull(1
 
NTSTATUS bool void get_raid56_lock_range (chunk *c, uint64_t address, uint64_t length, uint64_t *lockaddr, uint64_t *locklen) __attribute__((nonnull(1
 
NTSTATUS bool void 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) void *csum, _In_ LIST_ENTRY *rollback) __attribute__((nonnull(1
 
NTSTATUS bool void NTSTATUS void add_extent (_In_ fcb *fcb, _In_ LIST_ENTRY *prevextle, _In_ __drv_aliasesMem extent *newext) __attribute__((nonnull(1
 
NTSTATUS bool void NTSTATUS void _Dispatch_type_ (IRP_MJ_DIRECTORY_CONTROL) _Function_class_(DRIVER_DISPATCH) NTSTATUS __stdcall drv_directory_control(IN PDEVICE_OBJECT DeviceObject
 
ULONG get_reparse_tag (device_extension *Vcb, root *subvol, uint64_t inode, uint8_t type, ULONG atts, bool lxss, PIRP Irp)
 
ULONG get_reparse_tag_fcb (fcb *fcb)
 
 _Dispatch_type_ (IRP_MJ_QUERY_SECURITY) _Function_class_(DRIVER_DISPATCH) NTSTATUS __stdcall drv_query_security(IN PDEVICE_OBJECT DeviceObject
 
 _Dispatch_type_ (IRP_MJ_SET_SECURITY) _Function_class_(DRIVER_DISPATCH) NTSTATUS __stdcall drv_set_security(IN PDEVICE_OBJECT DeviceObject
 
void fcb_get_sd (fcb *fcb, struct _fcb *parent, bool look_for_xattr, PIRP Irp)
 
void add_user_mapping (WCHAR *sidstring, ULONG sidstringlength, uint32_t uid)
 
void add_group_mapping (WCHAR *sidstring, ULONG sidstringlength, uint32_t gid)
 
uint32_t sid_to_uid (PSID sid)
 
NTSTATUS uid_to_sid (uint32_t uid, PSID *sid)
 
NTSTATUS fcb_get_new_sd (fcb *fcb, file_ref *parfileref, ACCESS_STATE *as)
 
void find_gid (struct _fcb *fcb, struct _fcb *parfcb, PSECURITY_SUBJECT_CONTEXT subjcont)
 
 _Dispatch_type_ (IRP_MJ_SET_INFORMATION) _Function_class_(DRIVER_DISPATCH) NTSTATUS __stdcall drv_set_information(IN PDEVICE_OBJECT DeviceObject
 
 _Dispatch_type_ (IRP_MJ_QUERY_INFORMATION) _Function_class_(DRIVER_DISPATCH) NTSTATUS __stdcall drv_query_information(IN PDEVICE_OBJECT DeviceObject
 
 _Dispatch_type_ (IRP_MJ_QUERY_EA) _Function_class_(DRIVER_DISPATCH) NTSTATUS __stdcall drv_query_ea(IN PDEVICE_OBJECT DeviceObject
 
 _Dispatch_type_ (IRP_MJ_SET_EA) _Function_class_(DRIVER_DISPATCH) NTSTATUS __stdcall drv_set_ea(IN PDEVICE_OBJECT DeviceObject
 
bool has_open_children (file_ref *fileref)
 
NTSTATUS stream_set_end_of_file_information (device_extension *Vcb, uint16_t end, fcb *fcb, file_ref *fileref, bool advance_only)
 
NTSTATUS fileref_get_filename (file_ref *fileref, PUNICODE_STRING fn, USHORT *name_offset, ULONG *preqlen)
 
void insert_dir_child_into_hash_lists (fcb *fcb, dir_child *dc)
 
void remove_dir_child_from_hash_lists (fcb *fcb, dir_child *dc)
 
void add_fcb_to_subvol (_In_ _Requires_exclusive_lock_held_(_Curr_->Vcb->fcb_lock) fcb *fcb)
 
void remove_fcb_from_subvol (_In_ _Requires_exclusive_lock_held_(_Curr_->Vcb->fcb_lock) fcb *fcb)
 
NTSTATUS get_reparse_point (PFILE_OBJECT FileObject, void *buffer, DWORD buflen, ULONG_PTR *retlen)
 
NTSTATUS set_reparse_point2 (fcb *fcb, REPARSE_DATA_BUFFER *rdb, ULONG buflen, ccb *ccb, file_ref *fileref, PIRP Irp, LIST_ENTRY *rollback)
 
NTSTATUS set_reparse_point (PIRP Irp)
 
NTSTATUS delete_reparse_point (PIRP Irp)
 
 _Dispatch_type_ (IRP_MJ_CREATE) _Function_class_(DRIVER_DISPATCH) NTSTATUS __stdcall drv_create(IN PDEVICE_OBJECT DeviceObject
 
NTSTATUS open_fileref (_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension *Vcb, _Out_ file_ref **pfr, _In_ PUNICODE_STRING fnus, _In_opt_ file_ref *related, _In_ bool parent, _Out_opt_ USHORT *parsed, _Out_opt_ ULONG *fn_offset, _In_ POOL_TYPE pooltype, _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, 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, _In_ file_ref *sf, _In_ PUNICODE_STRING name, _In_ bool case_sensitive, _In_ bool lastpart, _In_ bool streampart, _In_ POOL_TYPE pooltype, _Out_ file_ref **psf2, _In_opt_ PIRP Irp)
 
fcbcreate_fcb (device_extension *Vcb, POOL_TYPE pool_type)
 
NTSTATUS find_file_in_dir (PUNICODE_STRING filename, fcb *fcb, root **subvol, uint64_t *inode, dir_child **pdc, bool case_sensitive)
 
uint32_t inherit_mode (fcb *parfcb, bool is_dir)
 
file_refcreate_fileref (device_extension *Vcb)
 
NTSTATUS open_fileref_by_inode (_Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension *Vcb, root *subvol, uint64_t inode, file_ref **pfr, PIRP Irp)
 
NTSTATUS fsctl_request (PDEVICE_OBJECT DeviceObject, PIRP *Pirp, uint32_t type)
 
void do_unlock_volume (device_extension *Vcb)
 
void trim_whole_device (device *dev)
 
void flush_subvol_fcbs (root *subvol)
 
bool fcb_is_inline (fcb *fcb)
 
NTSTATUS dismount_volume (device_extension *Vcb, bool shutdown, PIRP Irp)
 
NTSTATUS do_write (device_extension *Vcb, PIRP Irp)
 
NTSTATUS get_tree_new_address (device_extension *Vcb, tree *t, PIRP Irp, LIST_ENTRY *rollback)
 
NTSTATUS flush_fcb (fcb *fcb, bool cache, LIST_ENTRY *batchlist, PIRP Irp)
 
NTSTATUS write_data_phys (_In_ PDEVICE_OBJECT device, _In_ PFILE_OBJECT fileobj, _In_ uint64_t address, _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, 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 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)
 
 _Dispatch_type_ (IRP_MJ_READ) _Function_class_(DRIVER_DISPATCH) NTSTATUS __stdcall drv_read(PDEVICE_OBJECT DeviceObject
 
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) __attribute__((nonnull(1
 
NTSTATUS NTSTATUS read_stream (fcb *fcb, uint8_t *data, uint64_t start, ULONG length, ULONG *pbr) __attribute__((nonnull(1
 
NTSTATUS NTSTATUS NTSTATUS do_read (PIRP Irp, bool wait, ULONG *bytes_read)
 
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)
 
 _Dispatch_type_ (IRP_MJ_PNP) _Function_class_(DRIVER_DISPATCH) NTSTATUS __stdcall drv_pnp(PDEVICE_OBJECT DeviceObject
 
NTSTATUS pnp_surprise_removal (PDEVICE_OBJECT DeviceObject, PIRP Irp)
 
NTSTATUS pnp_query_remove_device (PDEVICE_OBJECT DeviceObject, PIRP Irp)
 
NTSTATUS load_cache_chunk (device_extension *Vcb, chunk *c, PIRP Irp)
 
NTSTATUS clear_free_space_cache (device_extension *Vcb, LIST_ENTRY *batchlist, PIRP Irp)
 
NTSTATUS allocate_cache (device_extension *Vcb, bool *changed, PIRP Irp, LIST_ENTRY *rollback)
 
NTSTATUS update_chunk_caches (device_extension *Vcb, PIRP Irp, LIST_ENTRY *rollback)
 
NTSTATUS update_chunk_caches_tree (device_extension *Vcb, PIRP Irp)
 
NTSTATUS add_space_entry (LIST_ENTRY *list, LIST_ENTRY *list_size, uint64_t offset, uint64_t size)
 
void space_list_add (chunk *c, uint64_t address, uint64_t length, LIST_ENTRY *rollback)
 
void space_list_add2 (LIST_ENTRY *list, LIST_ENTRY *list_size, uint64_t address, uint64_t length, chunk *c, LIST_ENTRY *rollback)
 
void space_list_subtract (chunk *c, uint64_t address, uint64_t length, LIST_ENTRY *rollback)
 
void space_list_subtract2 (LIST_ENTRY *list, LIST_ENTRY *list_size, uint64_t address, uint64_t length, chunk *c, LIST_ENTRY *rollback)
 
void space_list_merge (LIST_ENTRY *spacelist, LIST_ENTRY *spacelist_size, LIST_ENTRY *deleting)
 
NTSTATUS load_stored_free_space_cache (device_extension *Vcb, chunk *c, bool load_only, PIRP Irp)
 
NTSTATUS increase_extent_refcount_data (device_extension *Vcb, uint64_t address, uint64_t size, uint64_t root, uint64_t inode, uint64_t offset, uint32_t refcount, PIRP Irp)
 
NTSTATUS decrease_extent_refcount_data (device_extension *Vcb, uint64_t address, uint64_t size, uint64_t root, uint64_t inode, uint64_t offset, uint32_t refcount, bool superseded, PIRP Irp)
 
NTSTATUS decrease_extent_refcount_tree (device_extension *Vcb, uint64_t address, uint64_t size, uint64_t root, uint8_t level, PIRP Irp)
 
uint64_t get_extent_refcount (device_extension *Vcb, uint64_t address, uint64_t size, PIRP Irp)
 
bool is_extent_unique (device_extension *Vcb, uint64_t address, uint64_t size, PIRP Irp)
 
NTSTATUS increase_extent_refcount (device_extension *Vcb, uint64_t address, uint64_t size, uint8_t type, void *data, KEY *firstitem, uint8_t level, PIRP Irp)
 
uint64_t get_extent_flags (device_extension *Vcb, uint64_t address, PIRP Irp)
 
void update_extent_flags (device_extension *Vcb, uint64_t address, uint64_t flags, PIRP Irp)
 
NTSTATUS update_changed_extent_ref (device_extension *Vcb, chunk *c, uint64_t address, uint64_t size, uint64_t root, uint64_t objid, uint64_t offset, int32_t count, bool no_csum, bool superseded, PIRP Irp)
 
void add_changed_extent_ref (chunk *c, uint64_t address, uint64_t size, uint64_t root, uint64_t objid, uint64_t offset, uint32_t count, bool no_csum)
 
uint64_t find_extent_shared_tree_refcount (device_extension *Vcb, uint64_t address, uint64_t parent, PIRP Irp)
 
uint32_t find_extent_shared_data_refcount (device_extension *Vcb, uint64_t address, uint64_t parent, PIRP Irp)
 
NTSTATUS decrease_extent_refcount (device_extension *Vcb, uint64_t address, uint64_t size, uint8_t type, void *data, KEY *firstitem, uint8_t level, uint64_t parent, bool superseded, PIRP Irp)
 
uint64_t get_extent_data_ref_hash2 (uint64_t root, uint64_t objid, uint64_t offset)
 
NTSTATUS do_read_job (PIRP Irp)
 
NTSTATUS do_write_job (device_extension *Vcb, PIRP Irp)
 
bool add_thread_job (device_extension *Vcb, PIRP Irp)
 
void read_registry (PUNICODE_STRING regpath, bool refresh)
 
NTSTATUS registry_mark_volume_mounted (BTRFS_UUID *uuid)
 
NTSTATUS registry_mark_volume_unmounted (BTRFS_UUID *uuid)
 
NTSTATUS registry_load_volume_options (device_extension *Vcb)
 
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 (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)
 
void galois_double (uint8_t *data, uint32_t len)
 
void galois_divpower (uint8_t *data, uint8_t div, uint32_t readlen)
 
uint8_t gpow2 (uint8_t e)
 
uint8_t gmul (uint8_t a, uint8_t b)
 
uint8_t gdiv (uint8_t a, uint8_t b)
 
 _Dispatch_type_ (IRP_MJ_DEVICE_CONTROL) _Function_class_(DRIVER_DISPATCH) NTSTATUS __stdcall drv_device_control(IN PDEVICE_OBJECT DeviceObject
 
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)
 
NTSTATUS start_balance (device_extension *Vcb, void *data, ULONG length, KPROCESSOR_MODE processor_mode)
 
NTSTATUS query_balance (device_extension *Vcb, void *data, ULONG length)
 
NTSTATUS pause_balance (device_extension *Vcb, KPROCESSOR_MODE processor_mode)
 
NTSTATUS resume_balance (device_extension *Vcb, KPROCESSOR_MODE processor_mode)
 
NTSTATUS stop_balance (device_extension *Vcb, KPROCESSOR_MODE processor_mode)
 
NTSTATUS look_for_balance_item (_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb)
 
NTSTATUS remove_device (device_extension *Vcb, void *data, ULONG length, KPROCESSOR_MODE processor_mode)
 
NTSTATUS vol_create (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
 
NTSTATUS vol_close (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
 
NTSTATUS vol_read (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
 
NTSTATUS vol_write (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
 
NTSTATUS vol_device_control (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
 
void add_volume_device (superblock *sb, PUNICODE_STRING devpath, uint64_t length, ULONG disk_num, ULONG part_num)
 
NTSTATUS mountmgr_add_drive_letter (PDEVICE_OBJECT mountmgr, PUNICODE_STRING devpath)
 
void free_vol (volume_device_extension *vde)
 
NTSTATUS start_scrub (device_extension *Vcb, KPROCESSOR_MODE processor_mode)
 
NTSTATUS query_scrub (device_extension *Vcb, KPROCESSOR_MODE processor_mode, void *data, ULONG length)
 
NTSTATUS pause_scrub (device_extension *Vcb, KPROCESSOR_MODE processor_mode)
 
NTSTATUS resume_scrub (device_extension *Vcb, KPROCESSOR_MODE processor_mode)
 
NTSTATUS stop_scrub (device_extension *Vcb, KPROCESSOR_MODE processor_mode)
 
NTSTATUS send_subvol (device_extension *Vcb, void *data, ULONG datalen, PFILE_OBJECT FileObject, PIRP Irp)
 
NTSTATUS read_send_buffer (device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG datalen, ULONG_PTR *retlen, KPROCESSOR_MODE processor_mode)
 
NTSTATUS __stdcall compat_FsRtlValidateReparsePointBuffer (IN ULONG BufferLength, IN PREPARSE_DATA_BUFFER ReparseBuffer)
 
void check_system_root ()
 
void boot_add_device (DEVICE_OBJECT *pdo)
 
static __inline POPLOCK fcb_oplock (fcb *fcb)
 
static __inline FAST_IO_POSSIBLE fast_io_possible (fcb *fcb)
 
static __inline void print_open_trees (device_extension *Vcb)
 
static __inline bool write_fcb_compressed (fcb *fcb)
 
static __inline uint64_t fcb_alloc_size (fcb *fcb)
 
PEPROCESS __stdcall PsGetThreadProcess (_In_ PETHREAD Thread)
 

Variables

_In_ uint64_t a
 
return n
 
_In_ uint16_t len
 
_In_ uint16_t _Out_ ULONGatts
 
xor_func do_xor
 
PDEVICE_OBJECT PhysicalDeviceObject
 
uint32_t mount_compress
 
uint32_t mount_compress_force
 
uint32_t mount_compress_type
 
uint32_t mount_zlib_level
 
uint32_t mount_zstd_level
 
uint32_t mount_flush_interval
 
uint32_t mount_max_inline
 
uint32_t mount_skip_balance
 
uint32_t mount_no_barrier
 
uint32_t mount_no_trim
 
uint32_t mount_clear_cache
 
uint32_t mount_allow_degraded
 
uint32_t mount_readonly
 
uint32_t mount_no_root_dir
 
uint32_t mount_nodatacow
 
uint32_t no_pnp
 
static const char lxuid [] = "$LXUID"
 
static const char lxgid [] = "$LXGID"
 
static const char lxmod [] = "$LXMOD"
 
static const char lxdev [] = "$LXDEV"
 
PVOID Context
 
KSPIN_LOCK fve_data_lock
 
CACHE_MANAGER_CALLBACKS cache_callbacks
 
_In_ fcb _In_ chunkc
 
_In_ fcb _In_ chunk _In_ uint64_t start_data
 
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t length
 
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool prealloc
 
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ voiddata
 
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP Irp
 
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRYrollback
 
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t compression
 
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t _In_ uint64_t decoded_size
 
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t _In_ uint64_t _In_ bool file_write
 
BTRFS_UUID boot_uuid
 

Macro Definition Documentation

◆ __attribute__

Definition at line 1197 of file btrfs_drv.h.

◆ __drv_aliasesMem

#define __drv_aliasesMem

Definition at line 203 of file btrfs_drv.h.

◆ __S_IFBLK

#define __S_IFBLK   0060000 /* Block device. */

Definition at line 1756 of file btrfs_drv.h.

◆ __S_IFCHR

#define __S_IFCHR   0020000 /* Character device. */

Definition at line 1755 of file btrfs_drv.h.

◆ __S_IFDIR

#define __S_IFDIR   0040000 /* Directory. */

Definition at line 1754 of file btrfs_drv.h.

◆ __S_IFIFO

#define __S_IFIFO   0010000 /* FIFO. */

Definition at line 1758 of file btrfs_drv.h.

◆ __S_IFLNK

#define __S_IFLNK   0120000 /* Symbolic link. */

Definition at line 1759 of file btrfs_drv.h.

◆ __S_IFMT

#define __S_IFMT   0170000 /* These bits determine file type. */

Definition at line 1753 of file btrfs_drv.h.

◆ __S_IFREG

#define __S_IFREG   0100000 /* Regular file. */

Definition at line 1757 of file btrfs_drv.h.

◆ __S_IFSOCK

#define __S_IFSOCK   0140000 /* Socket. */

Definition at line 1760 of file btrfs_drv.h.

◆ __S_ISTYPE

#define __S_ISTYPE (   mode,
  mask 
)    (((mode) & __S_IFMT) == (mask))

Definition at line 1761 of file btrfs_drv.h.

◆ _CRT_SECURE_NO_WARNINGS

#define _CRT_SECURE_NO_WARNINGS

Definition at line 26 of file btrfs_drv.h.

◆ _Dispatch_type_

#define _Dispatch_type_ (   a)

Definition at line 204 of file btrfs_drv.h.

◆ _Lock_level_order_

#define _Lock_level_order_ (   a,
  b 
)

Definition at line 205 of file btrfs_drv.h.

◆ _NO_CRT_STDIO_INLINE

#define _NO_CRT_STDIO_INLINE

Definition at line 27 of file btrfs_drv.h.

◆ _WIN32_WINNT

#define _WIN32_WINNT   0x0601

Definition at line 24 of file btrfs_drv.h.

◆ acquire_chunk_lock

#define acquire_chunk_lock (   c,
  Vcb 
)    ExAcquireResourceExclusiveLite(&(c)->lock, true)

Definition at line 1139 of file btrfs_drv.h.

◆ ALLOC_TAG

#define ALLOC_TAG   0x7442484D

Definition at line 87 of file btrfs_drv.h.

◆ ALLOC_TAG_ZLIB

#define ALLOC_TAG_ZLIB   0x7A42484D

Definition at line 88 of file btrfs_drv.h.

◆ BALANCE_OPTS_DATA

#define BALANCE_OPTS_DATA   0

Definition at line 693 of file btrfs_drv.h.

◆ BALANCE_OPTS_METADATA

#define BALANCE_OPTS_METADATA   1

Definition at line 694 of file btrfs_drv.h.

◆ BALANCE_OPTS_SYSTEM

#define BALANCE_OPTS_SYSTEM   2

Definition at line 695 of file btrfs_drv.h.

◆ BLAKE2_HASH_SIZE

#define BLAKE2_HASH_SIZE   32

Definition at line 1252 of file btrfs_drv.h.

◆ BTRFS_NODE_TYPE_CCB

#define BTRFS_NODE_TYPE_CCB   0x2295

Definition at line 84 of file btrfs_drv.h.

◆ BTRFS_NODE_TYPE_FCB

#define BTRFS_NODE_TYPE_FCB   0x2296

Definition at line 85 of file btrfs_drv.h.

◆ BTRFS_VOLUME_PREFIX

#define BTRFS_VOLUME_PREFIX   L"\\Device\\Btrfs{"

Definition at line 127 of file btrfs_drv.h.

◆ CC_ENABLE_DISK_IO_ACCOUNTING

#define CC_ENABLE_DISK_IO_ACCOUNTING   0x00000010

Definition at line 1845 of file btrfs_drv.h.

◆ COMPRESSED_EXTENT_SIZE

#define COMPRESSED_EXTENT_SIZE   0x20000

Definition at line 112 of file btrfs_drv.h.

◆ EA_CASE_SENSITIVE

#define EA_CASE_SENSITIVE   "user.casesensitive"

Definition at line 105 of file btrfs_drv.h.

◆ EA_CASE_SENSITIVE_HASH

#define EA_CASE_SENSITIVE_HASH   0x1a9d97d4

Definition at line 106 of file btrfs_drv.h.

◆ EA_DOSATTRIB

#define EA_DOSATTRIB   "user.DOSATTRIB"

Definition at line 96 of file btrfs_drv.h.

◆ EA_DOSATTRIB_HASH

#define EA_DOSATTRIB_HASH   0x914f9939

Definition at line 97 of file btrfs_drv.h.

◆ EA_EA

#define EA_EA   "user.EA"

Definition at line 102 of file btrfs_drv.h.

◆ EA_EA_HASH

#define EA_EA_HASH   0x8270dd43

Definition at line 103 of file btrfs_drv.h.

◆ EA_NTACL

#define EA_NTACL   "security.NTACL"

Definition at line 93 of file btrfs_drv.h.

◆ EA_NTACL_HASH

#define EA_NTACL_HASH   0x45922146

Definition at line 94 of file btrfs_drv.h.

◆ EA_PROP_COMPRESSION

#define EA_PROP_COMPRESSION   "btrfs.compression"

Definition at line 108 of file btrfs_drv.h.

◆ EA_PROP_COMPRESSION_HASH

#define EA_PROP_COMPRESSION_HASH   0x20ccdf69

Definition at line 109 of file btrfs_drv.h.

◆ EA_REPARSE

#define EA_REPARSE   "user.reparse"

Definition at line 99 of file btrfs_drv.h.

◆ EA_REPARSE_HASH

#define EA_REPARSE_HASH   0xfabad1fe

Definition at line 100 of file btrfs_drv.h.

◆ ERR

#define ERR (   s,
  ... 
)    DbgPrint("Btrfs ERR : %s : " s, funcname, ##__VA_ARGS__)

Definition at line 1234 of file btrfs_drv.h.

◆ except

#define except (   x)    if (0 && (x))

Definition at line 136 of file btrfs_drv.h.

◆ FILE_CS_FLAG_CASE_SENSITIVE_DIR

#define FILE_CS_FLAG_CASE_SENSITIVE_DIR   1

Definition at line 165 of file btrfs_drv.h.

◆ FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL

#define FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL   0x00020000

Definition at line 156 of file btrfs_drv.h.

◆ FILE_SUPPORTS_BLOCK_REFCOUNTING

#define FILE_SUPPORTS_BLOCK_REFCOUNTING   0x08000000

Definition at line 148 of file btrfs_drv.h.

◆ FILE_SUPPORTS_POSIX_UNLINK_RENAME

#define FILE_SUPPORTS_POSIX_UNLINK_RENAME   0x00000400

Definition at line 152 of file btrfs_drv.h.

◆ finally

#define finally   if (1)

Definition at line 137 of file btrfs_drv.h.

◆ FIXME

#define FIXME (   s,
  ... 
)    DbgPrint("Btrfs FIXME : %s : " s, funcname, ##__VA_ARGS__)

Definition at line 1233 of file btrfs_drv.h.

◆ FSCTL_DUPLICATE_EXTENTS_TO_FILE

#define FSCTL_DUPLICATE_EXTENTS_TO_FILE   CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 209, METHOD_BUFFERED, FILE_WRITE_ACCESS)

Definition at line 182 of file btrfs_drv.h.

◆ FSCTL_GET_INTEGRITY_INFORMATION

#define FSCTL_GET_INTEGRITY_INFORMATION   CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 159, METHOD_BUFFERED, FILE_ANY_ACCESS)

Definition at line 198 of file btrfs_drv.h.

◆ FSCTL_SET_INTEGRITY_INFORMATION

#define FSCTL_SET_INTEGRITY_INFORMATION   CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 160, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)

Definition at line 199 of file btrfs_drv.h.

◆ FSRTL_FCB_HEADER_V2

#define FSRTL_FCB_HEADER_V2   2

Definition at line 1655 of file btrfs_drv.h.

◆ funcname

#define funcname   __func__

Definition at line 1176 of file btrfs_drv.h.

◆ GID_NOBODY

#define GID_NOBODY   65534

Definition at line 91 of file btrfs_drv.h.

◆ hex_digit

#define hex_digit (   c)    ((c) <= 9) ? ((c) + '0') : ((c) - 10 + 'a')

Definition at line 1748 of file btrfs_drv.h.

◆ increase_fileref_refcount

#define increase_fileref_refcount (   fileref)    InterlockedIncrement(&fileref->refcount)

Definition at line 1739 of file btrfs_drv.h.

◆ int3

#define int3   asm("int3;")

Definition at line 1745 of file btrfs_drv.h.

◆ InterlockedIncrement64

#define InterlockedIncrement64 (   a)    __sync_add_and_fetch(a, 1)

Definition at line 143 of file btrfs_drv.h.

◆ IO_REPARSE_TAG_AF_UNIX

#define IO_REPARSE_TAG_AF_UNIX   0x80000023

Definition at line 120 of file btrfs_drv.h.

◆ IO_REPARSE_TAG_LX_BLK

#define IO_REPARSE_TAG_LX_BLK   0x80000026

Definition at line 123 of file btrfs_drv.h.

◆ IO_REPARSE_TAG_LX_CHR

#define IO_REPARSE_TAG_LX_CHR   0x80000025

Definition at line 122 of file btrfs_drv.h.

◆ IO_REPARSE_TAG_LX_FIFO

#define IO_REPARSE_TAG_LX_FIFO   0x80000024

Definition at line 121 of file btrfs_drv.h.

◆ IO_REPARSE_TAG_LX_SYMLINK

#define IO_REPARSE_TAG_LX_SYMLINK   0xa000001d

Definition at line 118 of file btrfs_drv.h.

◆ keycmp

#define keycmp (   key1,
  key2 
)
Value:
((key1.obj_id < key2.obj_id) ? -1 :\
((key1.obj_id > key2.obj_id) ? 1 :\
((key1.obj_type < key2.obj_type) ? -1 :\
((key1.obj_type > key2.obj_type) ? 1 :\
((key1.offset < key2.offset) ? -1 :\
((key1.offset > key2.offset) ? 1 :\
0))))))
GLuint64EXT GLuint GLuint GLenum GLenum GLuint GLuint GLenum GLuint GLuint key1
Definition: glext.h:10608

Definition at line 1016 of file btrfs_drv.h.

◆ leave

#define leave

Definition at line 138 of file btrfs_drv.h.

◆ major

#define major (   rdev)    ((((rdev) >> 8) & 0xFFF) | ((uint32_t)((rdev) >> 32) & ~0xFFF))

Definition at line 1821 of file btrfs_drv.h.

◆ makedev

#define makedev (   major,
  minor 
)    (((minor) & 0xFF) | (((major) & 0xFFF) << 8) | (((uint64_t)((minor) & ~0xFF)) << 12) | (((uint64_t)((major) & ~0xFFF)) << 32))

Definition at line 1637 of file btrfs_drv.h.

◆ MAX_EXTENT_SIZE

#define MAX_EXTENT_SIZE   0x8000000

Definition at line 111 of file btrfs_drv.h.

◆ MAX_HASH_SIZE

#define MAX_HASH_SIZE   32

Definition at line 213 of file btrfs_drv.h.

◆ minor

#define minor (   rdev)    (((rdev) & 0xFF) | ((uint32_t)((rdev) >> 12) & ~0xFF))

Definition at line 1822 of file btrfs_drv.h.

◆ NTDDI_VERSION

#define NTDDI_VERSION   0x06020000

Definition at line 25 of file btrfs_drv.h.

◆ READ_AHEAD_GRANULARITY

#define READ_AHEAD_GRANULARITY   COMPRESSED_EXTENT_SIZE

Definition at line 114 of file btrfs_drv.h.

◆ release_chunk_lock

#define release_chunk_lock (   c,
  Vcb 
)    ExReleaseResourceLite(&(c)->lock)

Definition at line 1140 of file btrfs_drv.h.

◆ S_IRGRP

#define S_IRGRP   (S_IRUSR >> 3)

Definition at line 1785 of file btrfs_drv.h.

◆ S_IROTH

#define S_IROTH   (S_IRGRP >> 3)

Definition at line 1797 of file btrfs_drv.h.

◆ S_IRUSR

#define S_IRUSR   0000400

Definition at line 1768 of file btrfs_drv.h.

◆ S_ISDIR

#define S_ISDIR (   mode)    __S_ISTYPE((mode), __S_IFDIR)

Definition at line 1764 of file btrfs_drv.h.

◆ S_ISGID

#define S_ISGID   0002000

Definition at line 1813 of file btrfs_drv.h.

◆ S_ISUID

#define S_ISUID   0004000

Definition at line 1809 of file btrfs_drv.h.

◆ S_ISVTX

#define S_ISVTX   0001000

Definition at line 1817 of file btrfs_drv.h.

◆ S_IWGRP

#define S_IWGRP   (S_IWUSR >> 3)

Definition at line 1789 of file btrfs_drv.h.

◆ S_IWOTH

#define S_IWOTH   (S_IWGRP >> 3)

Definition at line 1801 of file btrfs_drv.h.

◆ S_IWUSR

#define S_IWUSR   0000200

Definition at line 1772 of file btrfs_drv.h.

◆ S_IXGRP

#define S_IXGRP   (S_IXUSR >> 3)

Definition at line 1793 of file btrfs_drv.h.

◆ S_IXOTH

#define S_IXOTH   (S_IXGRP >> 3)

Definition at line 1805 of file btrfs_drv.h.

◆ S_IXUSR

#define S_IXUSR   0000100

Definition at line 1776 of file btrfs_drv.h.

◆ SHA256_HASH_SIZE

#define SHA256_HASH_SIZE   32

Definition at line 1248 of file btrfs_drv.h.

◆ TRACE

#define TRACE (   s,
  ... 
)    do { } while(0)

Definition at line 1231 of file btrfs_drv.h.

◆ try

#define try   if (1)

Definition at line 135 of file btrfs_drv.h.

◆ UID_NOBODY

#define UID_NOBODY   65534

Definition at line 90 of file btrfs_drv.h.

◆ UNUSED

#define UNUSED (   x)    (void)(x)

Definition at line 82 of file btrfs_drv.h.

◆ VCB_TYPE_BUS

#define VCB_TYPE_BUS   5

Definition at line 691 of file btrfs_drv.h.

◆ VCB_TYPE_CONTROL

#define VCB_TYPE_CONTROL   2

Definition at line 688 of file btrfs_drv.h.

◆ VCB_TYPE_FS

#define VCB_TYPE_FS   1

Definition at line 687 of file btrfs_drv.h.

◆ VCB_TYPE_PDO

#define VCB_TYPE_PDO   4

Definition at line 690 of file btrfs_drv.h.

◆ VCB_TYPE_VOLUME

#define VCB_TYPE_VOLUME   3

Definition at line 689 of file btrfs_drv.h.

◆ WARN

#define WARN (   s,
  ... 
)    do { } while(0)

Definition at line 1232 of file btrfs_drv.h.

Typedef Documentation

◆ ccb

typedef struct _ccb ccb

◆ device_extension

◆ DUPLICATE_EXTENTS_DATA

◆ fcb

Definition at line 1364 of file btrfs_drv.h.

◆ fcb_nonpaged

◆ FILE_ID_128

◆ file_ref

◆ FSCTL_GET_INTEGRITY_INFORMATION_BUFFER

◆ FSCTL_SET_INTEGRITY_INFORMATION_BUFFER

◆ LDR_DATA_TABLE_ENTRY

◆ pdo_device_extension

◆ PDUPLICATE_EXTENTS_DATA

◆ PEB

typedef struct _PEB PEB

◆ PEB_LDR_DATA

◆ PFILE_ID_128

◆ PFSCTL_GET_INTEGRITY_INFORMATION_BUFFER

◆ PFSCTL_SET_INTEGRITY_INFORMATION_BUFFER

◆ PLDR_DATA_TABLE_ENTRY

◆ PPEB

typedef struct _PEB* PPEB

◆ PPEB_LDR_DATA

◆ PPS_POST_PROCESS_INIT_ROUTINE

typedef VOID(NTAPI * PPS_POST_PROCESS_INIT_ROUTINE) (VOID)

Definition at line 1905 of file btrfs_drv.h.

◆ PRTL_USER_PROCESS_PARAMETERS

◆ root

typedef struct _root root

◆ root_cache

◆ RTL_USER_PROCESS_PARAMETERS

◆ tCcCopyReadEx

◆ tCcCopyWriteEx

Definition at line 1838 of file btrfs_drv.h.

◆ tCcSetAdditionalCacheAttributesEx

typedef VOID(__stdcall * tCcSetAdditionalCacheAttributesEx) (PFILE_OBJECT FileObject, ULONG Flags)

Definition at line 1853 of file btrfs_drv.h.

◆ tFsRtlAreThereCurrentOrInProgressFileLocks

typedef BOOLEAN(__stdcall * tFsRtlAreThereCurrentOrInProgressFileLocks) (PFILE_LOCK FileLock)

Definition at line 1868 of file btrfs_drv.h.

◆ tFsRtlCheckLockForOplockRequest

typedef BOOLEAN(__stdcall * tFsRtlCheckLockForOplockRequest) (PFILE_LOCK FileLock, PLARGE_INTEGER AllocationSize)

Definition at line 1866 of file btrfs_drv.h.

◆ tFsRtlGetEcpListFromIrp

typedef NTSTATUS(__stdcall * tFsRtlGetEcpListFromIrp) (PIRP Irp, PECP_LIST *EcpList)

Definition at line 1859 of file btrfs_drv.h.

◆ tFsRtlGetNextExtraCreateParameter

Definition at line 1861 of file btrfs_drv.h.

◆ tFsRtlUpdateDiskCounters

typedef VOID(__stdcall * tFsRtlUpdateDiskCounters) (ULONG64 BytesRead, ULONG64 BytesWritten)

Definition at line 1855 of file btrfs_drv.h.

◆ tFsRtlValidateReparsePointBuffer

typedef NTSTATUS(__stdcall * tFsRtlValidateReparsePointBuffer) (ULONG BufferLength, PREPARSE_DATA_BUFFER ReparseBuffer)

Definition at line 1864 of file btrfs_drv.h.

◆ tIoUnregisterPlugPlayNotificationEx

typedef NTSTATUS(__stdcall * tIoUnregisterPlugPlayNotificationEx) (PVOID NotificationEntry)

Definition at line 1857 of file btrfs_drv.h.

◆ tPsIsDiskCountersEnabled

typedef BOOLEAN(__stdcall * tPsIsDiskCountersEnabled) ()

Definition at line 1833 of file btrfs_drv.h.

◆ tPsUpdateDiskCounters

typedef VOID(__stdcall * tPsUpdateDiskCounters) (PEPROCESS Process, ULONG64 BytesRead, ULONG64 BytesWritten, ULONG ReadOperationCount, ULONG WriteOperationCount, ULONG FlushOperationCount)

Definition at line 1835 of file btrfs_drv.h.

◆ tree

typedef struct _tree tree

◆ tree_data

◆ volume_device_extension

◆ write_data_context

◆ xor_func

typedef void(__stdcall * xor_func) (uint8_t *buf1, uint8_t *buf2, uint32_t len)

Definition at line 1131 of file btrfs_drv.h.

Enumeration Type Documentation

◆ batch_operation

Enumerator
Batch_Delete 
Batch_DeleteInode 
Batch_DeleteDirItem 
Batch_DeleteInodeRef 
Batch_DeleteInodeExtRef 
Batch_DeleteXattr 
Batch_DeleteExtentData 
Batch_DeleteFreeSpace 
Batch_Insert 
Batch_SetXattr 
Batch_DirItem 
Batch_InodeRef 
Batch_InodeExtRef 

Definition at line 470 of file btrfs_drv.h.

470 {
484};
@ Batch_InodeExtRef
Definition: btrfs_drv.h:483
@ Batch_DeleteExtentData
Definition: btrfs_drv.h:477
@ Batch_DeleteDirItem
Definition: btrfs_drv.h:473
@ Batch_DeleteXattr
Definition: btrfs_drv.h:476
@ Batch_SetXattr
Definition: btrfs_drv.h:480
@ Batch_DeleteFreeSpace
Definition: btrfs_drv.h:478
@ Batch_InodeRef
Definition: btrfs_drv.h:482
@ Batch_DeleteInode
Definition: btrfs_drv.h:472
@ Batch_DeleteInodeRef
Definition: btrfs_drv.h:474
@ Batch_Insert
Definition: btrfs_drv.h:479
@ Batch_DeleteInodeExtRef
Definition: btrfs_drv.h:475
@ Batch_DirItem
Definition: btrfs_drv.h:481
@ Batch_Delete
Definition: btrfs_drv.h:471

◆ calc_thread_type

Enumerator
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 

Definition at line 627 of file btrfs_drv.h.

627 {
638};
@ calc_thread_comp_lzo
Definition: btrfs_drv.h:636
@ calc_thread_sha256
Definition: btrfs_drv.h:630
@ calc_thread_decomp_zlib
Definition: btrfs_drv.h:632
@ calc_thread_crc32c
Definition: btrfs_drv.h:628
@ calc_thread_blake2
Definition: btrfs_drv.h:631
@ calc_thread_xxhash
Definition: btrfs_drv.h:629
@ calc_thread_decomp_zstd
Definition: btrfs_drv.h:634
@ calc_thread_comp_zstd
Definition: btrfs_drv.h:637
@ calc_thread_comp_zlib
Definition: btrfs_drv.h:635
@ calc_thread_decomp_lzo
Definition: btrfs_drv.h:633

◆ prop_compression_type

Enumerator
PropCompression_None 
PropCompression_Zlib 
PropCompression_LZO 
PropCompression_ZSTD 

Definition at line 267 of file btrfs_drv.h.

267 {
272};
@ PropCompression_None
Definition: btrfs_drv.h:268
@ PropCompression_LZO
Definition: btrfs_drv.h:270
@ PropCompression_Zlib
Definition: btrfs_drv.h:269
@ PropCompression_ZSTD
Definition: btrfs_drv.h:271

◆ rollback_type

Enumerator
ROLLBACK_INSERT_EXTENT 
ROLLBACK_DELETE_EXTENT 
ROLLBACK_ADD_SPACE 
ROLLBACK_SUBTRACT_SPACE 

Definition at line 1267 of file btrfs_drv.h.

1267 {
1272};
@ ROLLBACK_DELETE_EXTENT
Definition: btrfs_drv.h:1269
@ ROLLBACK_ADD_SPACE
Definition: btrfs_drv.h:1270
@ ROLLBACK_SUBTRACT_SPACE
Definition: btrfs_drv.h:1271
@ ROLLBACK_INSERT_EXTENT
Definition: btrfs_drv.h:1268

◆ write_data_status

Enumerator
WriteDataStatus_Pending 
WriteDataStatus_Success 
WriteDataStatus_Error 
WriteDataStatus_Cancelling 
WriteDataStatus_Cancelled 
WriteDataStatus_Ignore 

Definition at line 914 of file btrfs_drv.h.

914 {
921};
@ WriteDataStatus_Pending
Definition: btrfs_drv.h:915
@ WriteDataStatus_Ignore
Definition: btrfs_drv.h:920
@ WriteDataStatus_Cancelled
Definition: btrfs_drv.h:919
@ WriteDataStatus_Error
Definition: btrfs_drv.h:917
@ WriteDataStatus_Cancelling
Definition: btrfs_drv.h:918
@ WriteDataStatus_Success
Definition: btrfs_drv.h:916

Function Documentation

◆ __attribute__() [1/2]

IN PIRP Irp __attribute__ ( (nonnull(1, 2))  )

Definition at line 2730 of file read.c.

2731 {
2732 ULONG readlen;
2733
2734 TRACE("(%p, %p, %I64x, %lx, %p)\n", fcb, data, start, length, pbr);
2735
2736 if (pbr) *pbr = 0;
2737
2738 if (start >= fcb->adsdata.Length) {
2739 TRACE("tried to read beyond end of stream\n");
2740 return STATUS_END_OF_FILE;
2741 }
2742
2743 if (length == 0) {
2744 WARN("tried to read zero bytes\n");
2745 return STATUS_SUCCESS;
2746 }
2747
2748 if (start + length < fcb->adsdata.Length)
2749 readlen = length;
2750 else
2751 readlen = fcb->adsdata.Length - (ULONG)start;
2752
2753 if (readlen > 0)
2754 RtlCopyMemory(data, fcb->adsdata.Buffer + start, readlen);
2755
2756 if (pbr) *pbr = readlen;
2757
2758 return STATUS_SUCCESS;
2759}
#define WARN(fmt,...)
Definition: debug.h:112
GLuint start
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
#define STATUS_END_OF_FILE
Definition: shellext.h:67
#define STATUS_SUCCESS
Definition: shellext.h:65
#define TRACE(s)
Definition: solgame.cpp:4
ANSI_STRING adsdata
Definition: btrfs_drv.h:334
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG
Definition: typedefs.h:59

◆ __attribute__() [2/2]

◆ _Create_lock_level_()

_Create_lock_level_ ( tree_lock  )

◆ _Dispatch_type_() [1/12]

_Dispatch_type_ ( IRP_MJ_CREATE  )

Definition at line 297 of file isapnp.c.

995{
996 PAGED_CODE();
997
998 Irp->IoStatus.Status = STATUS_SUCCESS;
999
1000 DPRINT("%s(%p, %p)\n", __FUNCTION__, DeviceObject, Irp);
1001
1003
1004 return STATUS_SUCCESS;
1005}
#define PAGED_CODE()
_In_ PIRP Irp
Definition: csq.h:116
#define __FUNCTION__
Definition: types.h:116
#define IoCompleteRequest
Definition: irp.c:1240
#define DPRINT
Definition: sndvol32.h:71
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
#define IO_NO_INCREMENT
Definition: iotypes.h:598

◆ _Dispatch_type_() [2/12]

_Dispatch_type_ ( IRP_MJ_DEVICE_CONTROL  )

Definition at line 1385 of file isapnp.c.

1018{
1019 PISAPNP_COMMON_EXTENSION CommonExt = DeviceObject->DeviceExtension;
1020
1021 PAGED_CODE();
1022
1023 DPRINT("%s(%p, %p) Minor - %X\n", __FUNCTION__, DeviceObject, Irp,
1025
1026 if (CommonExt->Signature == IsaPnpBus)
1027 {
1029 return IoCallDriver(((PISAPNP_FDO_EXTENSION)CommonExt)->Ldo, Irp);
1030 }
1031 else
1032 {
1033 NTSTATUS Status = Irp->IoStatus.Status;
1034
1036 return Status;
1037 }
1038}
LONG NTSTATUS
Definition: precomp.h:26
Status
Definition: gdiplustypes.h:25
@ IsaPnpBus
Definition: isapnp.h:143
#define IoSkipCurrentIrpStackLocation(Irp)
Definition: ntifs_ex.h:421
#define IoCallDriver
Definition: irp.c:1225
ISAPNP_SIGNATURE Signature
Definition: isapnp.h:150
_In_ UCHAR _In_ UCHAR MinorFunction
Definition: wdfdevice.h:1699
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793

◆ _Dispatch_type_() [3/12]

◆ _Dispatch_type_() [4/12]

_Dispatch_type_ ( IRP_MJ_PNP  )

Definition at line 377 of file isapnp.c.

1591{
1593 PISAPNP_COMMON_EXTENSION DevExt = DeviceObject->DeviceExtension;
1594
1595 PAGED_CODE();
1596
1597 if (DevExt->Signature == IsaPnpBus)
1598 return IsaFdoPnp((PISAPNP_FDO_EXTENSION)DevExt, Irp, IrpSp);
1599 else
1600 return IsaPdoPnp((PISAPNP_PDO_EXTENSION)DevExt, Irp, IrpSp);
1601}
NTSTATUS IsaFdoPnp(_In_ PISAPNP_FDO_EXTENSION FdoExt, _Inout_ PIRP Irp, _In_ PIO_STACK_LOCATION IrpSp)
Definition: fdo.c:123
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
NTSTATUS IsaPdoPnp(_In_ PISAPNP_PDO_EXTENSION PdoDeviceExtension, _Inout_ PIRP Irp, _In_ PIO_STACK_LOCATION IrpSp)
Definition: pdo.c:864

◆ _Dispatch_type_() [5/12]

_Dispatch_type_ ( IRP_MJ_QUERY_EA  )

◆ _Dispatch_type_() [6/12]

_Dispatch_type_ ( IRP_MJ_QUERY_INFORMATION  )

◆ _Dispatch_type_() [7/12]

_Dispatch_type_ ( IRP_MJ_QUERY_SECURITY  )

◆ _Dispatch_type_() [8/12]

_Dispatch_type_ ( IRP_MJ_READ  )

◆ _Dispatch_type_() [9/12]

_Dispatch_type_ ( IRP_MJ_SET_EA  )

◆ _Dispatch_type_() [10/12]

_Dispatch_type_ ( IRP_MJ_SET_INFORMATION  )

◆ _Dispatch_type_() [11/12]

_Dispatch_type_ ( IRP_MJ_SET_SECURITY  )

◆ _Dispatch_type_() [12/12]

_Dispatch_type_ ( IRP_MJ_WRITE  )

◆ _Function_class_() [1/3]

_Function_class_ ( DRIVER_ADD_DEVICE  )

◆ _Function_class_() [2/3]

_Function_class_ ( DRIVER_NOTIFICATION_CALLBACK_ROUTINE  )

◆ _Function_class_() [3/3]

_Function_class_ ( KSTART_ROUTINE  )

Definition at line 3047 of file balance.c.

3048 {
3050 LIST_ENTRY chunks;
3051 LIST_ENTRY* le;
3052 uint64_t num_chunks[3], okay_metadata_chunks = 0, okay_data_chunks = 0, okay_system_chunks = 0;
3053 uint64_t old_data_flags = 0, old_metadata_flags = 0, old_system_flags = 0;
3055
3056 Vcb->balance.balance_num++;
3057
3058 Vcb->balance.stopping = false;
3059 KeInitializeEvent(&Vcb->balance.finished, NotificationEvent, false);
3060
3061 if (Vcb->balance.opts[BALANCE_OPTS_DATA].flags & BTRFS_BALANCE_OPTS_ENABLED && Vcb->balance.opts[BALANCE_OPTS_DATA].flags & BTRFS_BALANCE_OPTS_CONVERT) {
3062 old_data_flags = Vcb->data_flags;
3063 Vcb->data_flags = BLOCK_FLAG_DATA | (Vcb->balance.opts[BALANCE_OPTS_DATA].convert == BLOCK_FLAG_SINGLE ? 0 : Vcb->balance.opts[BALANCE_OPTS_DATA].convert);
3064
3066 }
3067
3068 if (Vcb->balance.opts[BALANCE_OPTS_METADATA].flags & BTRFS_BALANCE_OPTS_ENABLED && Vcb->balance.opts[BALANCE_OPTS_METADATA].flags & BTRFS_BALANCE_OPTS_CONVERT) {
3069 old_metadata_flags = Vcb->metadata_flags;
3070 Vcb->metadata_flags = BLOCK_FLAG_METADATA | (Vcb->balance.opts[BALANCE_OPTS_METADATA].convert == BLOCK_FLAG_SINGLE ? 0 : Vcb->balance.opts[BALANCE_OPTS_METADATA].convert);
3071 }
3072
3073 if (Vcb->balance.opts[BALANCE_OPTS_SYSTEM].flags & BTRFS_BALANCE_OPTS_ENABLED && Vcb->balance.opts[BALANCE_OPTS_SYSTEM].flags & BTRFS_BALANCE_OPTS_CONVERT) {
3074 old_system_flags = Vcb->system_flags;
3075 Vcb->system_flags = BLOCK_FLAG_SYSTEM | (Vcb->balance.opts[BALANCE_OPTS_SYSTEM].convert == BLOCK_FLAG_SINGLE ? 0 : Vcb->balance.opts[BALANCE_OPTS_SYSTEM].convert);
3076 }
3077
3078 if (Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_MIXED_GROUPS) {
3079 if (Vcb->balance.opts[BALANCE_OPTS_DATA].flags & BTRFS_BALANCE_OPTS_ENABLED)
3080 RtlCopyMemory(&Vcb->balance.opts[BALANCE_OPTS_METADATA], &Vcb->balance.opts[BALANCE_OPTS_DATA], sizeof(btrfs_balance_opts));
3081 else if (Vcb->balance.opts[BALANCE_OPTS_METADATA].flags & BTRFS_BALANCE_OPTS_ENABLED)
3082 RtlCopyMemory(&Vcb->balance.opts[BALANCE_OPTS_DATA], &Vcb->balance.opts[BALANCE_OPTS_METADATA], sizeof(btrfs_balance_opts));
3083 }
3084
3085 num_chunks[0] = num_chunks[1] = num_chunks[2] = 0;
3086 Vcb->balance.total_chunks = Vcb->balance.chunks_left = 0;
3087
3088 InitializeListHead(&chunks);
3089
3090 // FIXME - what are we supposed to do with limit_start?
3091
3092 if (!Vcb->readonly) {
3093 if (!Vcb->balance.removing && !Vcb->balance.shrinking) {
3095 if (!NT_SUCCESS(Status)) {
3096 ERR("add_balance_item returned %08lx\n", Status);
3097 Vcb->balance.status = Status;
3098 goto end;
3099 }
3100 } else {
3101 if (Vcb->need_write) {
3102 Status = do_write(Vcb, NULL);
3103
3104 free_trees(Vcb);
3105
3106 if (!NT_SUCCESS(Status)) {
3107 ERR("do_write returned %08lx\n", Status);
3108 Vcb->balance.status = Status;
3109 goto end;
3110 }
3111 }
3112 }
3113 }
3114
3115 KeWaitForSingleObject(&Vcb->balance.event, Executive, KernelMode, false, NULL);
3116
3117 if (Vcb->balance.stopping)
3118 goto end;
3119
3120 ExAcquireResourceSharedLite(&Vcb->chunk_lock, true);
3121
3122 le = Vcb->chunks.Flink;
3123 while (le != &Vcb->chunks) {
3125 uint8_t sort;
3126
3128
3129 if (c->chunk_item->type & BLOCK_FLAG_DATA)
3131 else if (c->chunk_item->type & BLOCK_FLAG_METADATA)
3133 else if (c->chunk_item->type & BLOCK_FLAG_SYSTEM)
3135 else {
3136 ERR("unexpected chunk type %I64x\n", c->chunk_item->type);
3138 break;
3139 }
3140
3141 if ((!(Vcb->balance.opts[sort].flags & BTRFS_BALANCE_OPTS_LIMIT) || num_chunks[sort] < Vcb->balance.opts[sort].limit_end) &&
3143 InsertTailList(&chunks, &c->list_entry_balance);
3144
3145 num_chunks[sort]++;
3146 Vcb->balance.total_chunks++;
3147 Vcb->balance.chunks_left++;
3148 } else if (sort == BALANCE_OPTS_METADATA)
3149 okay_metadata_chunks++;
3150 else if (sort == BALANCE_OPTS_DATA)
3151 okay_data_chunks++;
3152 else if (sort == BALANCE_OPTS_SYSTEM)
3153 okay_system_chunks++;
3154
3155 if (!c->cache_loaded) {
3157
3158 if (!NT_SUCCESS(Status)) {
3159 ERR("load_cache_chunk returned %08lx\n", Status);
3160 Vcb->balance.status = Status;
3162 ExReleaseResourceLite(&Vcb->chunk_lock);
3163 goto end;
3164 }
3165 }
3166
3168
3169 le = le->Flink;
3170 }
3171
3172 ExReleaseResourceLite(&Vcb->chunk_lock);
3173
3174 // If we're doing a full balance, try and allocate a new chunk now, before we mess things up
3175 if (okay_metadata_chunks == 0 || okay_data_chunks == 0 || okay_system_chunks == 0) {
3176 bool consolidated = false;
3177 chunk* c;
3178
3179 if (okay_metadata_chunks == 0) {
3180 ExAcquireResourceExclusiveLite(&Vcb->chunk_lock, true);
3181
3182 Status = alloc_chunk(Vcb, Vcb->metadata_flags, &c, true);
3183 if (NT_SUCCESS(Status))
3184 c->balance_num = Vcb->balance.balance_num;
3185 else if (Status != STATUS_DISK_FULL || consolidated) {
3186 ERR("alloc_chunk returned %08lx\n", Status);
3187 ExReleaseResourceLite(&Vcb->chunk_lock);
3188 Vcb->balance.status = Status;
3189 goto end;
3190 }
3191
3192 ExReleaseResourceLite(&Vcb->chunk_lock);
3193
3194 if (Status == STATUS_DISK_FULL) {
3195 Status = try_consolidation(Vcb, Vcb->metadata_flags, &c);
3196 if (!NT_SUCCESS(Status)) {
3197 ERR("try_consolidation returned %08lx\n", Status);
3198 Vcb->balance.status = Status;
3199 goto end;
3200 } else
3201 c->balance_num = Vcb->balance.balance_num;
3202
3203 consolidated = true;
3204
3205 if (Vcb->balance.stopping)
3206 goto end;
3207 }
3208 }
3209
3210 if (okay_data_chunks == 0) {
3211 ExAcquireResourceExclusiveLite(&Vcb->chunk_lock, true);
3212
3213 Status = alloc_chunk(Vcb, Vcb->data_flags, &c, true);
3214 if (NT_SUCCESS(Status))
3215 c->balance_num = Vcb->balance.balance_num;
3216 else if (Status != STATUS_DISK_FULL || consolidated) {
3217 ERR("alloc_chunk returned %08lx\n", Status);
3218 ExReleaseResourceLite(&Vcb->chunk_lock);
3219 Vcb->balance.status = Status;
3220 goto end;
3221 }
3222
3223 ExReleaseResourceLite(&Vcb->chunk_lock);
3224
3225 if (Status == STATUS_DISK_FULL) {
3226 Status = try_consolidation(Vcb, Vcb->data_flags, &c);
3227 if (!NT_SUCCESS(Status)) {
3228 ERR("try_consolidation returned %08lx\n", Status);
3229 Vcb->balance.status = Status;
3230 goto end;
3231 } else
3232 c->balance_num = Vcb->balance.balance_num;
3233
3234 consolidated = true;
3235
3236 if (Vcb->balance.stopping)
3237 goto end;
3238 }
3239 }
3240
3241 if (okay_system_chunks == 0) {
3242 ExAcquireResourceExclusiveLite(&Vcb->chunk_lock, true);
3243
3244 Status = alloc_chunk(Vcb, Vcb->system_flags, &c, true);
3245 if (NT_SUCCESS(Status))
3246 c->balance_num = Vcb->balance.balance_num;
3247 else if (Status != STATUS_DISK_FULL || consolidated) {
3248 ERR("alloc_chunk returned %08lx\n", Status);
3249 ExReleaseResourceLite(&Vcb->chunk_lock);
3250 Vcb->balance.status = Status;
3251 goto end;
3252 }
3253
3254 ExReleaseResourceLite(&Vcb->chunk_lock);
3255
3256 if (Status == STATUS_DISK_FULL) {
3257 Status = try_consolidation(Vcb, Vcb->system_flags, &c);
3258 if (!NT_SUCCESS(Status)) {
3259 ERR("try_consolidation returned %08lx\n", Status);
3260 Vcb->balance.status = Status;
3261 goto end;
3262 } else
3263 c->balance_num = Vcb->balance.balance_num;
3264
3265 consolidated = true;
3266
3267 if (Vcb->balance.stopping)
3268 goto end;
3269 }
3270 }
3271 }
3272
3273 ExAcquireResourceSharedLite(&Vcb->chunk_lock, true);
3274
3275 le = chunks.Flink;
3276 while (le != &chunks) {
3277 chunk* c = CONTAINING_RECORD(le, chunk, list_entry_balance);
3278
3279 c->reloc = true;
3280
3281 le = le->Flink;
3282 }
3283
3284 ExReleaseResourceLite(&Vcb->chunk_lock);
3285
3286 // do data chunks before metadata
3287 le = chunks.Flink;
3288 while (le != &chunks) {
3289 chunk* c = CONTAINING_RECORD(le, chunk, list_entry_balance);
3290 LIST_ENTRY* le2 = le->Flink;
3291
3292 if (c->chunk_item->type & BLOCK_FLAG_DATA) {
3293 bool changed;
3294
3295 do {
3296 changed = false;
3297
3298 Status = balance_data_chunk(Vcb, c, &changed);
3299 if (!NT_SUCCESS(Status)) {
3300 ERR("balance_data_chunk returned %08lx\n", Status);
3301 Vcb->balance.status = Status;
3302 goto end;
3303 }
3304
3305 KeWaitForSingleObject(&Vcb->balance.event, Executive, KernelMode, false, NULL);
3306
3307 if (Vcb->readonly)
3308 Vcb->balance.stopping = true;
3309
3310 if (Vcb->balance.stopping)
3311 break;
3312 } while (changed);
3313
3314 c->changed = true;
3315 c->space_changed = true;
3316 }
3317
3318 if (Vcb->balance.stopping)
3319 goto end;
3320
3321 if (c->chunk_item->type & BLOCK_FLAG_DATA &&
3322 (!(Vcb->balance.opts[BALANCE_OPTS_METADATA].flags & BTRFS_BALANCE_OPTS_ENABLED) || !(c->chunk_item->type & BLOCK_FLAG_METADATA))) {
3323 RemoveEntryList(&c->list_entry_balance);
3324 c->list_entry_balance.Flink = NULL;
3325
3326 Vcb->balance.chunks_left--;
3327 }
3328
3329 le = le2;
3330 }
3331
3332 // do metadata chunks
3333 while (!IsListEmpty(&chunks)) {
3334 chunk* c;
3335 bool changed;
3336
3337 le = RemoveHeadList(&chunks);
3338 c = CONTAINING_RECORD(le, chunk, list_entry_balance);
3339
3340 if (c->chunk_item->type & BLOCK_FLAG_METADATA || c->chunk_item->type & BLOCK_FLAG_SYSTEM) {
3341 do {
3342 Status = balance_metadata_chunk(Vcb, c, &changed);
3343 if (!NT_SUCCESS(Status)) {
3344 ERR("balance_metadata_chunk returned %08lx\n", Status);
3345 Vcb->balance.status = Status;
3346 goto end;
3347 }
3348
3349 KeWaitForSingleObject(&Vcb->balance.event, Executive, KernelMode, false, NULL);
3350
3351 if (Vcb->readonly)
3352 Vcb->balance.stopping = true;
3353
3354 if (Vcb->balance.stopping)
3355 break;
3356 } while (changed);
3357
3358 c->changed = true;
3359 c->space_changed = true;
3360 }
3361
3362 if (Vcb->balance.stopping)
3363 break;
3364
3365 c->list_entry_balance.Flink = NULL;
3366
3367 Vcb->balance.chunks_left--;
3368 }
3369
3370end:
3371 if (!Vcb->readonly) {
3372 if (Vcb->balance.stopping || !NT_SUCCESS(Vcb->balance.status)) {
3373 le = chunks.Flink;
3374 while (le != &chunks) {
3375 chunk* c = CONTAINING_RECORD(le, chunk, list_entry_balance);
3376 c->reloc = false;
3377
3378 le = le->Flink;
3379 c->list_entry_balance.Flink = NULL;
3380 }
3381
3382 if (old_data_flags != 0)
3383 Vcb->data_flags = old_data_flags;
3384
3385 if (old_metadata_flags != 0)
3386 Vcb->metadata_flags = old_metadata_flags;
3387
3388 if (old_system_flags != 0)
3389 Vcb->system_flags = old_system_flags;
3390 }
3391
3392 if (Vcb->balance.removing) {
3393 device* dev = NULL;
3394
3395 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
3396
3397 le = Vcb->devices.Flink;
3398 while (le != &Vcb->devices) {
3400
3401 if (dev2->devitem.dev_id == Vcb->balance.opts[0].devid) {
3402 dev = dev2;
3403 break;
3404 }
3405
3406 le = le->Flink;
3407 }
3408
3409 if (dev) {
3410 if (Vcb->balance.chunks_left == 0) {
3412
3413 if (!NT_SUCCESS(Status)) {
3414 ERR("finish_removing_device returned %08lx\n", Status);
3415 dev->reloc = false;
3416 }
3417 } else
3418 dev->reloc = false;
3419 }
3420
3421 ExReleaseResourceLite(&Vcb->tree_lock);
3422 } else if (Vcb->balance.shrinking) {
3423 device* dev = NULL;
3424
3425 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
3426
3427 le = Vcb->devices.Flink;
3428 while (le != &Vcb->devices) {
3430
3431 if (dev2->devitem.dev_id == Vcb->balance.opts[0].devid) {
3432 dev = dev2;
3433 break;
3434 }
3435
3436 le = le->Flink;
3437 }
3438
3439 if (!dev) {
3440 ERR("could not find device %I64x\n", Vcb->balance.opts[0].devid);
3441 Vcb->balance.status = STATUS_INTERNAL_ERROR;
3442 }
3443
3444 if (Vcb->balance.stopping || !NT_SUCCESS(Vcb->balance.status)) {
3445 if (dev) {
3447 if (!NT_SUCCESS(Status))
3448 WARN("regenerate_space_list returned %08lx\n", Status);
3449 }
3450 } else {
3451 uint64_t old_size;
3452
3453 old_size = dev->devitem.num_bytes;
3454 dev->devitem.num_bytes = Vcb->balance.opts[0].drange_start;
3455
3457 if (!NT_SUCCESS(Status)) {
3458 ERR("update_dev_item returned %08lx\n", Status);
3459 dev->devitem.num_bytes = old_size;
3460 Vcb->balance.status = Status;
3461
3463 if (!NT_SUCCESS(Status))
3464 WARN("regenerate_space_list returned %08lx\n", Status);
3465 } else {
3466 Vcb->superblock.total_bytes -= old_size - dev->devitem.num_bytes;
3467
3468 Status = do_write(Vcb, NULL);
3469 if (!NT_SUCCESS(Status))
3470 ERR("do_write returned %08lx\n", Status);
3471
3472 free_trees(Vcb);
3473 }
3474 }
3475
3476 ExReleaseResourceLite(&Vcb->tree_lock);
3477
3478 if (!Vcb->balance.stopping && NT_SUCCESS(Vcb->balance.status))
3480 } else {
3482 if (!NT_SUCCESS(Status)) {
3483 ERR("remove_balance_item returned %08lx\n", Status);
3484 goto end;
3485 }
3486 }
3487
3488 if (Vcb->trim && !Vcb->options.no_trim) {
3489 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
3490
3491 le = Vcb->devices.Flink;
3492 while (le != &Vcb->devices) {
3494
3495 if (dev2->devobj && !dev2->readonly && dev2->trim)
3496 trim_unalloc_space(Vcb, dev2);
3497
3498 le = le->Flink;
3499 }
3500
3501 ExReleaseResourceLite(&Vcb->tree_lock);
3502 }
3503 }
3504
3505 ZwClose(Vcb->balance.thread);
3506 Vcb->balance.thread = NULL;
3507
3508 KeSetEvent(&Vcb->balance.finished, 0, false);
3509}
_STLP_MOVE_TO_STD_NAMESPACE void sort(_RandomAccessIter __first, _RandomAccessIter __last)
Definition: _algo.c:993
#define ERR(fmt,...)
Definition: debug.h:110
#define acquire_chunk_lock(c, Vcb)
Definition: btrfs_drv.h:1139
NTSTATUS load_cache_chunk(device_extension *Vcb, chunk *c, PIRP Irp)
Definition: free-space.c:980
NTSTATUS alloc_chunk(device_extension *Vcb, uint64_t flags, chunk **pc, bool full_size) __attribute__((nonnull(1
NTSTATUS update_dev_item(device_extension *Vcb, device *device, PIRP Irp)
Definition: flushthread.c:4093
#define BALANCE_OPTS_METADATA
Definition: btrfs_drv.h:694
NTSTATUS do_write(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7877
#define BALANCE_OPTS_DATA
Definition: btrfs_drv.h:693
NTSTATUS NTSTATUS bool bool void free_trees(device_extension *Vcb) __attribute__((nonnull(1)))
#define BALANCE_OPTS_SYSTEM
Definition: btrfs_drv.h:695
#define release_chunk_lock(c, Vcb)
Definition: btrfs_drv.h:1140
#define BTRFS_BALANCE_OPTS_ENABLED
Definition: btrfsioctl.h:130
#define BTRFS_BALANCE_OPTS_CONVERT
Definition: btrfsioctl.h:138
#define BLOCK_FLAG_SINGLE
Definition: btrfsioctl.h:141
#define BTRFS_BALANCE_OPTS_LIMIT
Definition: btrfsioctl.h:135
#define NULL
Definition: types.h:112
UINT64 uint64_t
Definition: types.h:77
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static NTSTATUS remove_balance_item(device_extension *Vcb)
Definition: balance.c:2451
static NTSTATUS finish_removing_device(_Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, device *dev)
Definition: balance.c:2586
static void trim_unalloc_space(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, device *dev)
Definition: balance.c:2802
static bool should_balance_chunk(device_extension *Vcb, uint8_t sort, chunk *c)
Definition: balance.c:2225
static NTSTATUS try_consolidation(device_extension *Vcb, uint64_t flags, chunk **newchunk)
Definition: balance.c:2902
static NTSTATUS balance_data_chunk(device_extension *Vcb, chunk *c, bool *changed)
Definition: balance.c:1671
static NTSTATUS balance_metadata_chunk(device_extension *Vcb, chunk *c, bool *changed)
Definition: balance.c:1100
static NTSTATUS add_balance_item(device_extension *Vcb)
Definition: balance.c:2378
static NTSTATUS regenerate_space_list(device_extension *Vcb, device *dev)
Definition: balance.c:2997
#define BTRFS_INCOMPAT_FLAGS_MIXED_GROUPS
Definition: btrfs.h:117
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define ExAcquireResourceExclusiveLite(res, wait)
Definition: env_spec_w32.h:615
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define ExAcquireResourceSharedLite(res, wait)
Definition: env_spec_w32.h:621
#define FSRTL_VOLUME_CHANGE_SIZE
Definition: fsrtltypes.h:101
GLuint GLuint end
Definition: gl.h:1545
const GLubyte * c
Definition: glext.h:8905
#define c
Definition: ke_i.h:80
BYTE uint8_t
Definition: msvideo1.c:66
#define KernelMode
Definition: asm.h:34
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
@ NotificationEvent
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1822
NTSTATUS NTAPI FsRtlNotifyVolumeEvent(IN PFILE_OBJECT FileObject, IN ULONG EventCode)
Definition: pnp.c:38
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define Vcb
Definition: cdprocs.h:1415
#define BLOCK_FLAG_DATA
Definition: shellext.h:75
#define BLOCK_FLAG_SYSTEM
Definition: shellext.h:76
#define BLOCK_FLAG_METADATA
Definition: shellext.h:77
uint64_t dev_id
Definition: btrfs.h:178
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
Definition: http.c:7252
Definition: devices.h:37
DEV_ITEM devitem
Definition: btrfs_drv.h:527
bool readonly
Definition: btrfs_drv.h:530
bool trim
Definition: btrfs_drv.h:532
PDEVICE_OBJECT devobj
Definition: btrfs_drv.h:525
Definition: list.h:27
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
#define STATUS_DISK_FULL
Definition: udferr_usr.h:155
@ Executive
Definition: ketypes.h:415

◆ _Post_satisfies_()

_Post_satisfies_ ( return >=  n)

◆ _Releases_lock_()

_Releases_lock_ ( c->  lock)

◆ _Requires_lock_held_() [1/2]

_Requires_lock_held_ ( c->  lock)
pure virtual

◆ _Requires_lock_held_() [2/2]

_Requires_lock_held_ ( Vcb->  fcb_lock) -> fcb_lock) static __inline void release_fcb_lock(device_extension* Vcb)

Definition at line 971 of file btrfs_drv.h.

973 {
974 ExReleaseResourceLite(&Vcb->fcb_lock);
975}

◆ _Requires_lock_not_held_()

_Requires_lock_not_held_ ( Vcb->  fcb_lock) -> fcb_lock) static __inline void acquire_fcb_lock_shared(device_extension* Vcb)

Definition at line 959 of file btrfs_drv.h.

961 {
962 ExAcquireResourceSharedLite(&Vcb->fcb_lock, true);
963}

◆ _Success_()

_Success_ ( return  )

◆ add_calc_job_comp()

NTSTATUS add_calc_job_comp ( device_extension Vcb,
uint8_t  compression,
void in,
unsigned int  inlen,
void out,
unsigned int  outlen,
calc_job **  pcj 
)

Definition at line 237 of file calcthread.c.

238 {
239 calc_job* cj;
240 KIRQL irql;
241
243 if (!cj) {
244 ERR("out of memory\n");
246 }
247
248 cj->in = in;
249 cj->inlen = inlen;
250 cj->out = out;
251 cj->outlen = outlen;
252 cj->left = cj->not_started = 1;
253 cj->Status = STATUS_SUCCESS;
254
255 switch (compression) {
258 break;
259
261 cj->type = calc_thread_comp_lzo;
262 break;
263
266 break;
267
268 default:
269 ERR("unexpected compression type %x\n", compression);
270 ExFreePool(cj);
272 }
273
274 KeInitializeEvent(&cj->event, NotificationEvent, false);
275
276 KeAcquireSpinLock(&Vcb->calcthreads.spinlock, &irql);
277
278 InsertTailList(&Vcb->calcthreads.job_list, &cj->list_entry);
279
280 KeSetEvent(&Vcb->calcthreads.event, 0, false);
281 KeClearEvent(&Vcb->calcthreads.event);
282
283 KeReleaseSpinLock(&Vcb->calcthreads.spinlock, irql);
284
285 *pcj = cj;
286
287 return STATUS_SUCCESS;
288}
#define ALLOC_TAG
Definition: btrfs_drv.h:87
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t compression
Definition: btrfs_drv.h:1365
#define BTRFS_COMPRESSION_LZO
Definition: btrfs.h:67
#define BTRFS_COMPRESSION_ZLIB
Definition: btrfs.h:66
#define BTRFS_COMPRESSION_ZSTD
Definition: btrfs.h:68
KIRQL irql
Definition: wave.h:1
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define NonPagedPool
Definition: env_spec_w32.h:307
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
GLuint in
Definition: glext.h:9616
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
static FILE * out
Definition: regtests2xml.c:44
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ ULONG * pcj
Definition: winddi.h:3642
_In_ ULONG cj
Definition: winddi.h:3540

Referenced by write_compressed().

◆ add_calc_job_decomp()

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 
)

Definition at line 183 of file calcthread.c.

184 {
185 calc_job* cj;
186 KIRQL irql;
187
189 if (!cj) {
190 ERR("out of memory\n");
192 }
193
194 cj->in = in;
195 cj->inlen = inlen;
196 cj->out = out;
197 cj->outlen = outlen;
198 cj->off = off;
199 cj->left = cj->not_started = 1;
200 cj->Status = STATUS_SUCCESS;
201
202 switch (compression) {
205 break;
206
209 break;
210
213 break;
214
215 default:
216 ERR("unexpected compression type %x\n", compression);
217 ExFreePool(cj);
219 }
220
221 KeInitializeEvent(&cj->event, NotificationEvent, false);
222
223 KeAcquireSpinLock(&Vcb->calcthreads.spinlock, &irql);
224
225 InsertTailList(&Vcb->calcthreads.job_list, &cj->list_entry);
226
227 KeSetEvent(&Vcb->calcthreads.event, 0, false);
228 KeClearEvent(&Vcb->calcthreads.event);
229
230 KeReleaseSpinLock(&Vcb->calcthreads.spinlock, irql);
231
232 *pcj = cj;
233
234 return STATUS_SUCCESS;
235}

◆ add_changed_extent_ref()

void add_changed_extent_ref ( chunk c,
uint64_t  address,
uint64_t  size,
uint64_t  root,
uint64_t  objid,
uint64_t  offset,
uint32_t  count,
bool  no_csum 
)

Definition at line 2076 of file extent-tree.c.

2076 {
2077 changed_extent* ce;
2078 changed_extent_ref* cer;
2079 LIST_ENTRY* le;
2080
2081 ce = get_changed_extent_item(c, address, size, no_csum);
2082
2083 if (!ce) {
2084 ERR("get_changed_extent_item failed\n");
2085 return;
2086 }
2087
2088 le = ce->refs.Flink;
2089 while (le != &ce->refs) {
2091
2092 if (cer->type == TYPE_EXTENT_DATA_REF && cer->edr.root == root && cer->edr.objid == objid && cer->edr.offset == offset) {
2093 ce->count += count;
2094 cer->edr.count += count;
2095 return;
2096 }
2097
2098 le = le->Flink;
2099 }
2100
2102
2103 if (!cer) {
2104 ERR("out of memory\n");
2105 return;
2106 }
2107
2109 cer->edr.root = root;
2110 cer->edr.objid = objid;
2111 cer->edr.offset = offset;
2112 cer->edr.count = count;
2113
2114 InsertTailList(&ce->refs, &cer->list_entry);
2115
2116 ce->count += count;
2117}
struct _root root
#define TYPE_EXTENT_DATA_REF
Definition: btrfs.h:38
#define PagedPool
Definition: env_spec_w32.h:308
static changed_extent * get_changed_extent_item(chunk *c, uint64_t address, uint64_t size, bool no_csum)
Definition: extent-tree.c:1916
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLsizeiptr size
Definition: glext.h:5919
GLuint address
Definition: glext.h:9393
GLintptr offset
Definition: glext.h:5920
uint64_t offset
Definition: btrfs.h:419
uint64_t root
Definition: btrfs.h:417
uint64_t objid
Definition: btrfs.h:418
uint32_t count
Definition: btrfs.h:420
LIST_ENTRY list_entry
Definition: btrfs_drv.h:617
EXTENT_DATA_REF edr
Definition: btrfs_drv.h:613
uint64_t count
Definition: btrfs_drv.h:600
LIST_ENTRY refs
Definition: btrfs_drv.h:604

Referenced by insert_extent_chunk(), rationalize_extents(), and write_compressed().

◆ add_checksum_entry()

void add_checksum_entry ( device_extension Vcb,
uint64_t  address,
ULONG  length,
void csum,
PIRP  Irp 
)

Definition at line 2602 of file flushthread.c.

2602 {
2603 KEY searchkey;
2604 traverse_ptr tp, next_tp;
2606 uint64_t startaddr, endaddr;
2607 ULONG len;
2609 ULONG* bmparr;
2610 ULONG runlength, index;
2611
2612 TRACE("(%p, %I64x, %lx, %p, %p)\n", Vcb, address, length, csum, Irp);
2613
2614 searchkey.obj_id = EXTENT_CSUM_ID;
2615 searchkey.obj_type = TYPE_EXTENT_CSUM;
2616 searchkey.offset = address;
2617
2618 // FIXME - create checksum_root if it doesn't exist at all
2619
2620 Status = find_item(Vcb, Vcb->checksum_root, &tp, &searchkey, false, Irp);
2621 if (Status == STATUS_NOT_FOUND) { // tree is completely empty
2622 if (csum) { // not deleted
2623 ULONG length2 = length;
2624 uint64_t off = address;
2625 void* data = csum;
2626
2627 do {
2628 uint16_t il = (uint16_t)min(length2, MAX_CSUM_SIZE / Vcb->csum_size);
2629
2630 void* checksums = ExAllocatePoolWithTag(PagedPool, il * Vcb->csum_size, ALLOC_TAG);
2631 if (!checksums) {
2632 ERR("out of memory\n");
2633 return;
2634 }
2635
2636 RtlCopyMemory(checksums, data, il * Vcb->csum_size);
2637
2638 Status = insert_tree_item(Vcb, Vcb->checksum_root, EXTENT_CSUM_ID, TYPE_EXTENT_CSUM, off, checksums,
2639 il * Vcb->csum_size, NULL, Irp);
2640 if (!NT_SUCCESS(Status)) {
2641 ERR("insert_tree_item returned %08lx\n", Status);
2642 ExFreePool(checksums);
2643 return;
2644 }
2645
2646 length2 -= il;
2647
2648 if (length2 > 0) {
2649 off += (uint64_t)il << Vcb->sector_shift;
2650 data = (uint8_t*)data + (il * Vcb->csum_size);
2651 }
2652 } while (length2 > 0);
2653 }
2654 } else if (!NT_SUCCESS(Status)) {
2655 ERR("find_item returned %08lx\n", Status);
2656 return;
2657 } else {
2658 uint32_t tplen;
2659 void* checksums;
2660
2661 // FIXME - check entry is TYPE_EXTENT_CSUM?
2662
2663 if (tp.item->key.offset < address && tp.item->key.offset + (((uint64_t)tp.item->size << Vcb->sector_shift) / Vcb->csum_size) >= address)
2665 else
2667
2668 searchkey.obj_id = EXTENT_CSUM_ID;
2669 searchkey.obj_type = TYPE_EXTENT_CSUM;
2670 searchkey.offset = address + (length << Vcb->sector_shift);
2671
2672 Status = find_item(Vcb, Vcb->checksum_root, &tp, &searchkey, false, Irp);
2673 if (!NT_SUCCESS(Status)) {
2674 ERR("find_item returned %08lx\n", Status);
2675 return;
2676 }
2677
2678 tplen = tp.item->size / Vcb->csum_size;
2679
2680 if (tp.item->key.offset + (tplen << Vcb->sector_shift) >= address + (length << Vcb->sector_shift))
2681 endaddr = tp.item->key.offset + (tplen << Vcb->sector_shift);
2682 else
2683 endaddr = address + (length << Vcb->sector_shift);
2684
2685 TRACE("cs starts at %I64x (%lx sectors)\n", address, length);
2686 TRACE("startaddr = %I64x\n", startaddr);
2687 TRACE("endaddr = %I64x\n", endaddr);
2688
2689 len = (ULONG)((endaddr - startaddr) >> Vcb->sector_shift);
2690
2691 checksums = ExAllocatePoolWithTag(PagedPool, Vcb->csum_size * len, ALLOC_TAG);
2692 if (!checksums) {
2693 ERR("out of memory\n");
2694 return;
2695 }
2696
2697 bmparr = ExAllocatePoolWithTag(PagedPool, sizeof(ULONG) * ((len/8)+1), ALLOC_TAG);
2698 if (!bmparr) {
2699 ERR("out of memory\n");
2700 ExFreePool(checksums);
2701 return;
2702 }
2703
2704 RtlInitializeBitMap(&bmp, bmparr, len);
2706
2707 searchkey.obj_id = EXTENT_CSUM_ID;
2708 searchkey.obj_type = TYPE_EXTENT_CSUM;
2709 searchkey.offset = address;
2710
2711 Status = find_item(Vcb, Vcb->checksum_root, &tp, &searchkey, false, Irp);
2712 if (!NT_SUCCESS(Status)) {
2713 ERR("find_item returned %08lx\n", Status);
2714 ExFreePool(checksums);
2715 ExFreePool(bmparr);
2716 return;
2717 }
2718
2719 // set bit = free space, cleared bit = allocated sector
2720
2721 while (tp.item->key.offset < endaddr) {
2722 if (tp.item->key.offset >= startaddr) {
2723 if (tp.item->size > 0) {
2724 ULONG itemlen = (ULONG)min((len - ((tp.item->key.offset - startaddr) >> Vcb->sector_shift)) * Vcb->csum_size, tp.item->size);
2725
2726 RtlCopyMemory((uint8_t*)checksums + (((tp.item->key.offset - startaddr) * Vcb->csum_size) >> Vcb->sector_shift),
2727 tp.item->data, itemlen);
2728 RtlClearBits(&bmp, (ULONG)((tp.item->key.offset - startaddr) >> Vcb->sector_shift), itemlen / Vcb->csum_size);
2729 }
2730
2732 if (!NT_SUCCESS(Status)) {
2733 ERR("delete_tree_item returned %08lx\n", Status);
2734 ExFreePool(checksums);
2735 ExFreePool(bmparr);
2736 return;
2737 }
2738 }
2739
2740 if (find_next_item(Vcb, &tp, &next_tp, false, Irp)) {
2741 tp = next_tp;
2742 } else
2743 break;
2744 }
2745
2746 if (!csum) { // deleted
2747 RtlSetBits(&bmp, (ULONG)((address - startaddr) >> Vcb->sector_shift), length);
2748 } else {
2749 RtlCopyMemory((uint8_t*)checksums + (((address - startaddr) * Vcb->csum_size) >> Vcb->sector_shift),
2750 csum, length * Vcb->csum_size);
2751 RtlClearBits(&bmp, (ULONG)((address - startaddr) >> Vcb->sector_shift), length);
2752 }
2753
2754 runlength = RtlFindFirstRunClear(&bmp, &index);
2755
2756 while (runlength != 0) {
2757 if (index >= len)
2758 break;
2759
2760 if (index + runlength >= len) {
2761 runlength = len - index;
2762
2763 if (runlength == 0)
2764 break;
2765 }
2766
2767 do {
2768 uint16_t rl;
2769 uint64_t off;
2770 void* data;
2771
2772 if (runlength * Vcb->csum_size > MAX_CSUM_SIZE)
2773 rl = (uint16_t)(MAX_CSUM_SIZE / Vcb->csum_size);
2774 else
2775 rl = (uint16_t)runlength;
2776
2777 data = ExAllocatePoolWithTag(PagedPool, Vcb->csum_size * rl, ALLOC_TAG);
2778 if (!data) {
2779 ERR("out of memory\n");
2780 ExFreePool(bmparr);
2781 ExFreePool(checksums);
2782 return;
2783 }
2784
2785 RtlCopyMemory(data, (uint8_t*)checksums + (Vcb->csum_size * index), Vcb->csum_size * rl);
2786
2787 off = startaddr + ((uint64_t)index << Vcb->sector_shift);
2788
2789 Status = insert_tree_item(Vcb, Vcb->checksum_root, EXTENT_CSUM_ID, TYPE_EXTENT_CSUM, off, data, Vcb->csum_size * rl, NULL, Irp);
2790 if (!NT_SUCCESS(Status)) {
2791 ERR("insert_tree_item returned %08lx\n", Status);
2793 ExFreePool(bmparr);
2794 ExFreePool(checksums);
2795 return;
2796 }
2797
2798 runlength -= rl;
2799 index += rl;
2800 } while (runlength > 0);
2801
2802 runlength = RtlFindNextForwardRunClear(&bmp, index, &index);
2803 }
2804
2805 ExFreePool(bmparr);
2806 ExFreePool(checksums);
2807 }
2808}
unsigned short int uint16_t
Definition: acefiex.h:54
static void startaddr(void)
#define index(s, c)
Definition: various.h:29
NTSTATUS insert_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_ uint64_t obj_id, _In_ uint8_t obj_type, _In_ uint64_t offset, _In_reads_bytes_opt_(size) _When_(return >=0, __drv_aliasesMem) void *data, _In_ uint16_t size, _Out_opt_ traverse_ptr *ptp, _In_opt_ PIRP Irp) __attribute__((nonnull(1
NTSTATUS NTSTATUS bool find_next_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, const traverse_ptr *tp, traverse_ptr *next_tp, bool ignore, PIRP Irp) __attribute__((nonnull(1
NTSTATUS NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp) __attribute__((nonnull(1
UINT32 uint32_t
Definition: types.h:75
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2996
#define EXTENT_CSUM_ID
Definition: btrfs.h:91
#define TYPE_EXTENT_CSUM
Definition: btrfs.h:31
#define MAX_CSUM_SIZE
Definition: flushthread.c:28
GLuint index
Definition: glext.h:6031
GLenum GLsizei len
Definition: glext.h:6722
NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG)
NTSYSAPI void WINAPI RtlSetAllBits(PRTL_BITMAP)
NTSYSAPI void WINAPI RtlClearBits(PRTL_BITMAP, ULONG, ULONG)
NTSYSAPI void WINAPI RtlSetBits(PRTL_BITMAP, ULONG, ULONG)
NTSYSAPI ULONG WINAPI RtlFindNextForwardRunClear(PCRTL_BITMAP, ULONG, PULONG)
BITMAP bmp
Definition: alphablend.c:62
#define min(a, b)
Definition: monoChain.cc:55
#define uint64_t
Definition: nsiface.idl:62
#define uint16_t
Definition: nsiface.idl:60
#define STATUS_NOT_FOUND
Definition: shellext.h:72
Definition: btrfs.h:143
uint8_t obj_type
Definition: btrfs.h:145
uint64_t obj_id
Definition: btrfs.h:144
uint64_t offset
Definition: btrfs.h:146
uint8_t * data
Definition: btrfs_drv.h:415
uint16_t size
Definition: btrfs_drv.h:414
Definition: ffs.h:52
tree_data * item
Definition: btrfs_drv.h:509
NTSYSAPI ULONG NTAPI RtlFindFirstRunClear(_In_ PRTL_BITMAP BitMapHeader, _Out_ PULONG StartingIndex)

Referenced by balance_data_chunk(), decrease_extent_refcount(), flush_fcb(), and rationalize_extents().

◆ add_dir_child()

NTSTATUS add_dir_child ( fcb fcb,
uint64_t  inode,
bool  subvol,
PANSI_STRING  utf8,
PUNICODE_STRING  name,
uint8_t  type,
dir_child **  pdc 
)

Definition at line 1871 of file create.c.

1871 {
1873 dir_child* dc;
1874 bool locked;
1875
1877 if (!dc) {
1878 ERR("out of memory\n");
1880 }
1881
1882 RtlZeroMemory(dc, sizeof(dir_child));
1883
1884 dc->utf8.Buffer = ExAllocatePoolWithTag(PagedPool, utf8->Length, ALLOC_TAG);
1885 if (!dc->utf8.Buffer) {
1886 ERR("out of memory\n");
1887 ExFreePool(dc);
1889 }
1890
1891 dc->name.Buffer = ExAllocatePoolWithTag(PagedPool, name->Length, ALLOC_TAG);
1892 if (!dc->name.Buffer) {
1893 ERR("out of memory\n");
1894 ExFreePool(dc->utf8.Buffer);
1895 ExFreePool(dc);
1897 }
1898
1899 dc->key.obj_id = inode;
1900 dc->key.obj_type = subvol ? TYPE_ROOT_ITEM : TYPE_INODE_ITEM;
1901 dc->key.offset = subvol ? 0xffffffffffffffff : 0;
1902 dc->type = type;
1903 dc->fileref = NULL;
1904
1905 dc->utf8.Length = dc->utf8.MaximumLength = utf8->Length;
1906 RtlCopyMemory(dc->utf8.Buffer, utf8->Buffer, utf8->Length);
1907
1908 dc->name.Length = dc->name.MaximumLength = name->Length;
1909 RtlCopyMemory(dc->name.Buffer, name->Buffer, name->Length);
1910
1911 Status = RtlUpcaseUnicodeString(&dc->name_uc, name, true);
1912 if (!NT_SUCCESS(Status)) {
1913 ERR("RtlUpcaseUnicodeString returned %08lx\n", Status);
1914 ExFreePool(dc->utf8.Buffer);
1915 ExFreePool(dc->name.Buffer);
1916 ExFreePool(dc);
1917 return Status;
1918 }
1919
1920 dc->hash = calc_crc32c(0xffffffff, (uint8_t*)dc->name.Buffer, dc->name.Length);
1921 dc->hash_uc = calc_crc32c(0xffffffff, (uint8_t*)dc->name_uc.Buffer, dc->name_uc.Length);
1922
1923 locked = ExIsResourceAcquiredExclusive(&fcb->nonpaged->dir_children_lock);
1924
1925 if (!locked)
1926 ExAcquireResourceExclusiveLite(&fcb->nonpaged->dir_children_lock, true);
1927
1929 dc->index = 2;
1930 else {
1932
1933 dc->index = max(2, dc2->index + 1);
1934 }
1935
1936 InsertTailList(&fcb->dir_children_index, &dc->list_entry_index);
1937
1939
1940 if (!locked)
1941 ExReleaseResourceLite(&fcb->nonpaged->dir_children_lock);
1942
1943 *pdc = dc;
1944
1945 return STATUS_SUCCESS;
1946}
void insert_dir_child_into_hash_lists(fcb *fcb, dir_child *dc)
Definition: fileinfo.c:1470
crc_func calc_crc32c
Definition: crc32c.c:23
#define TYPE_ROOT_ITEM
Definition: btrfs.h:32
#define TYPE_INODE_ITEM
Definition: btrfs.h:23
NTSTATUS RtlUpcaseUnicodeString(PUNICODE_STRING dst, PUNICODE_STRING src, BOOLEAN Alloc)
Definition: string_lib.cpp:46
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
static const WCHAR dc[]
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
LIST_ENTRY dir_children_index
Definition: btrfs_drv.h:314
struct _fcb_nonpaged * nonpaged
Definition: btrfs_drv.h:284
uint64_t index
Definition: btrfs_drv.h:252
Definition: fs.h:78
Definition: name.c:39
#define max(a, b)
Definition: svc.c:63
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define ExIsResourceAcquiredExclusive
Definition: exfuncs.h:347

Referenced by create_subvol(), do_create_snapshot(), file_create2(), mknod(), and set_link_information().

◆ add_extent()

NTSTATUS bool void NTSTATUS void add_extent ( _In_ fcb fcb,
_In_ LIST_ENTRY prevextle,
_In_ __drv_aliasesMem extent newext 
)

Referenced by __attribute__(), and duplicate_extents().

◆ add_extent_to_fcb()

◆ add_fcb_to_subvol()

void add_fcb_to_subvol ( _In_ _Requires_exclusive_lock_held_(_Curr_->Vcb->fcb_lock) fcb fcb)

Definition at line 888 of file fileinfo.c.

888 {
889 LIST_ENTRY* lastle = NULL;
891
892 if (fcb->subvol->fcbs_ptrs[hash >> 24]) {
893 LIST_ENTRY* le = fcb->subvol->fcbs_ptrs[hash >> 24];
894
895 while (le != &fcb->subvol->fcbs) {
896 struct _fcb* fcb2 = CONTAINING_RECORD(le, struct _fcb, list_entry);
897
898 if (fcb2->hash > hash) {
899 lastle = le->Blink;
900 break;
901 }
902
903 le = le->Flink;
904 }
905 }
906
907 if (!lastle) {
908 uint8_t c = hash >> 24;
909
910 if (c != 0xff) {
911 uint8_t d = c + 1;
912
913 do {
914 if (fcb->subvol->fcbs_ptrs[d]) {
915 lastle = fcb->subvol->fcbs_ptrs[d]->Blink;
916 break;
917 }
918
919 d++;
920 } while (d != 0);
921 }
922 }
923
924 if (lastle) {
925 InsertHeadList(lastle, &fcb->list_entry);
926
927 if (lastle == &fcb->subvol->fcbs || (CONTAINING_RECORD(lastle, struct _fcb, list_entry)->hash >> 24) != (hash >> 24))
928 fcb->subvol->fcbs_ptrs[hash >> 24] = &fcb->list_entry;
929 } else {
931
932 if (fcb->list_entry.Blink == &fcb->subvol->fcbs || (CONTAINING_RECORD(fcb->list_entry.Blink, struct _fcb, list_entry)->hash >> 24) != (hash >> 24))
933 fcb->subvol->fcbs_ptrs[hash >> 24] = &fcb->list_entry;
934 }
935}
#define InsertHeadList(ListHead, Entry)
#define d
Definition: ke_i.h:81
struct _root * subvol
Definition: btrfs_drv.h:288
LIST_ENTRY list_entry
Definition: btrfs_drv.h:336
uint32_t hash
Definition: btrfs_drv.h:290
Definition: _hash_fun.h:40

Referenced by allocate_cache_chunk(), create_directory_fcb(), create_subvol(), mknod(), move_across_subvols(), rename_stream(), and rename_stream_to_file().

◆ add_group_mapping()

void add_group_mapping ( WCHAR sidstring,
ULONG  sidstringlength,
uint32_t  gid 
)

Definition at line 145 of file security.c.

145 {
146 unsigned int i, np;
147 uint8_t numdashes;
149 ULONG sidsize;
151 gid_map* gm;
152
153 if (sidstringlength < 4 || sidstring[0] != 'S' || sidstring[1] != '-' || sidstring[2] != '1' || sidstring[3] != '-') {
154 ERR("invalid SID\n");
155 return;
156 }
157
158 sidstring = &sidstring[4];
159 sidstringlength -= 4;
160
161 numdashes = 0;
162 for (i = 0; i < sidstringlength; i++) {
163 if (sidstring[i] == '-') {
164 numdashes++;
165 sidstring[i] = 0;
166 }
167 }
168
169 sidsize = 8 + (numdashes * 4);
171 if (!sid) {
172 ERR("out of memory\n");
173 return;
174 }
175
176 sid->revision = 0x01;
177 sid->elements = numdashes;
178
179 np = 0;
180 while (sidstringlength > 0) {
181 val = 0;
182 i = 0;
183 while (i < sidstringlength && sidstring[i] != '-') {
184 if (sidstring[i] >= '0' && sidstring[i] <= '9') {
185 val *= 10;
186 val += sidstring[i] - '0';
187 } else
188 break;
189
190 i++;
191 }
192
193 i++;
194 TRACE("val = %u, i = %u, ssl = %lu\n", (uint32_t)val, i, sidstringlength);
195
196 if (np == 0) {
197 sid->auth[0] = (uint8_t)((val & 0xff0000000000) >> 40);
198 sid->auth[1] = (uint8_t)((val & 0xff00000000) >> 32);
199 sid->auth[2] = (uint8_t)((val & 0xff000000) >> 24);
200 sid->auth[3] = (uint8_t)((val & 0xff0000) >> 16);
201 sid->auth[4] = (uint8_t)((val & 0xff00) >> 8);
202 sid->auth[5] = val & 0xff;
203 } else
204 sid->nums[np-1] = (uint32_t)val;
205
206 np++;
207
208 if (sidstringlength > i) {
209 sidstringlength -= i;
210
211 sidstring = &sidstring[i];
212 } else
213 break;
214 }
215
217 if (!gm) {
218 ERR("out of memory\n");
220 return;
221 }
222
223 gm->sid = sid;
224 gm->gid = gid;
225
227}
FT_UInt sid
Definition: cffcmap.c:139
LIST_ENTRY gid_map_list
Definition: security.c:53
GLuint GLfloat * val
Definition: glext.h:7180
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define uint32_t
Definition: nsiface.idl:61
#define uint8_t
Definition: nsiface.idl:59
uint32_t gid
Definition: btrfs_drv.h:911
PSID sid
Definition: btrfs_drv.h:910
LIST_ENTRY listentry
Definition: btrfs_drv.h:909

Referenced by read_group_mappings().

◆ add_rollback()

void void void add_rollback ( _In_ LIST_ENTRY rollback,
_In_ enum rollback_type  type,
_In_ __drv_aliasesMem void ptr 
)

Referenced by add_rollback_space().

◆ add_space_entry()

NTSTATUS add_space_entry ( LIST_ENTRY list,
LIST_ENTRY list_size,
uint64_t  offset,
uint64_t  size 
)

Definition at line 190 of file free-space.c.

190 {
191 space* s;
192
194
195 if (!s) {
196 ERR("out of memory\n");
198 }
199
200 s->address = offset;
201 s->size = size;
202
203 if (IsListEmpty(list))
204 InsertTailList(list, &s->list_entry);
205 else {
207
208 if (s2->address < offset)
209 InsertTailList(list, &s->list_entry);
210 else {
211 LIST_ENTRY* le;
212
213 le = list->Flink;
214 while (le != list) {
216
217 if (s2->address > offset) {
218 InsertTailList(le, &s->list_entry);
219 goto size;
220 }
221
222 le = le->Flink;
223 }
224 }
225 }
226
227size:
228 if (!list_size)
229 return STATUS_SUCCESS;
230
231 if (IsListEmpty(list_size))
232 InsertTailList(list_size, &s->list_entry_size);
233 else {
234 space* s2 = CONTAINING_RECORD(list_size->Blink, space, list_entry_size);
235
236 if (s2->size >= size)
237 InsertTailList(list_size, &s->list_entry_size);
238 else {
239 LIST_ENTRY* le;
240
241 le = list_size->Flink;
242 while (le != list_size) {
243 s2 = CONTAINING_RECORD(le, space, list_entry_size);
244
245 if (s2->size <= size) {
246 InsertHeadList(le->Blink, &s->list_entry_size);
247 return STATUS_SUCCESS;
248 }
249
250 le = le->Flink;
251 }
252 }
253 }
254
255 return STATUS_SUCCESS;
256}
Definition: list.h:37
GLdouble s
Definition: gl.h:2039
struct S2 s2

Referenced by add_device(), find_disk_holes(), load_free_space_bitmap(), load_stored_free_space_cache(), and load_stored_free_space_tree().

◆ add_thread_job()

bool add_thread_job ( device_extension Vcb,
PIRP  Irp 
)

Definition at line 109 of file worker-thread.c.

109 {
110 job_info* ji;
111
113 if (!ji) {
114 ERR("out of memory\n");
115 return false;
116 }
117
118 ji->Vcb = Vcb;
119 ji->Irp = Irp;
120
121 if (!Irp->MdlAddress) {
122 PMDL Mdl;
124 ULONG len;
126
129 len = IrpSp->Parameters.Read.Length;
130 } else if (IrpSp->MajorFunction == IRP_MJ_WRITE) {
132 len = IrpSp->Parameters.Write.Length;
133 } else {
134 ERR("unexpected major function %u\n", IrpSp->MajorFunction);
135 ExFreePool(ji);
136 return false;
137 }
138
139 Mdl = IoAllocateMdl(Irp->UserBuffer, len, false, false, Irp);
140
141 if (!Mdl) {
142 ERR("out of memory\n");
143 ExFreePool(ji);
144 return false;
145 }
146
147 _SEH2_TRY {
148 MmProbeAndLockPages(Mdl, Irp->RequestorMode, op);
150 ERR("MmProbeAndLockPages raised status %08lx\n", _SEH2_GetExceptionCode());
151
152 IoFreeMdl(Mdl);
153 Irp->MdlAddress = NULL;
154 ExFreePool(ji);
155
156 _SEH2_YIELD(return FALSE);
157 } _SEH2_END;
158 }
159
160 ExInitializeWorkItem(&ji->item, do_job, ji);
162
163 return true;
164}
#define FALSE
Definition: types.h:117
UINT op
Definition: effect.c:236
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
#define IoFreeMdl
Definition: fxmdl.h:89
#define IoAllocateMdl
Definition: fxmdl.h:88
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
VOID NTAPI MmProbeAndLockPages(IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode, IN LOCK_OPERATION Operation)
Definition: mdlsup.c:931
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:162
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3128
device_extension * Vcb
Definition: worker-thread.c:21
WORK_QUEUE_ITEM item
Definition: worker-thread.c:23
_In_ WDFDEVICE _In_ PVOID _In_opt_ PMDL Mdl
VOID NTAPI ExQueueWorkItem(IN PWORK_QUEUE_ITEM WorkItem, IN WORK_QUEUE_TYPE QueueType)
Definition: work.c:723
#define ExInitializeWorkItem(Item, Routine, Context)
Definition: exfuncs.h:265
@ DelayedWorkQueue
Definition: extypes.h:190
enum _LOCK_OPERATION LOCK_OPERATION
@ IoReadAccess
Definition: ketypes.h:863
@ IoWriteAccess
Definition: ketypes.h:864

Referenced by _Dispatch_type_().

◆ add_trim_entry_avoid_sb()

void add_trim_entry_avoid_sb ( device_extension Vcb,
device dev,
uint64_t  address,
uint64_t  size 
)

Definition at line 5507 of file flushthread.c.

5507 {
5508 int i;
5509 ULONG sblen = (ULONG)sector_align(sizeof(superblock), Vcb->superblock.sector_size);
5510
5511 i = 0;
5512 while (superblock_addrs[i] != 0) {
5513 if (superblock_addrs[i] + sblen >= address && superblock_addrs[i] < address + size) {
5514 if (superblock_addrs[i] > address)
5516
5517 if (size <= superblock_addrs[i] + sblen - address)
5518 return;
5519
5520 size -= superblock_addrs[i] + sblen - address;
5521 address = superblock_addrs[i] + sblen;
5522 } else if (superblock_addrs[i] > address + size)
5523 break;
5524
5525 i++;
5526 }
5527
5529}
static uint64_t __inline sector_align(uint64_t n, uint64_t a)
static const uint64_t superblock_addrs[]
Definition: btrfs.h:16
static void add_trim_entry(device *dev, uint64_t address, uint64_t size)
Definition: flushthread.c:157

Referenced by drop_chunk(), and trim_unalloc_space().

◆ add_user_mapping()

void add_user_mapping ( WCHAR sidstring,
ULONG  sidstringlength,
uint32_t  uid 
)

Definition at line 56 of file security.c.

56 {
57 unsigned int i, np;
58 uint8_t numdashes;
60 ULONG sidsize;
62 uid_map* um;
63
64 if (sidstringlength < 4 ||
65 sidstring[0] != 'S' ||
66 sidstring[1] != '-' ||
67 sidstring[2] != '1' ||
68 sidstring[3] != '-') {
69 ERR("invalid SID\n");
70 return;
71 }
72
73 sidstring = &sidstring[4];
74 sidstringlength -= 4;
75
76 numdashes = 0;
77 for (i = 0; i < sidstringlength; i++) {
78 if (sidstring[i] == '-') {
79 numdashes++;
80 sidstring[i] = 0;
81 }
82 }
83
84 sidsize = 8 + (numdashes * 4);
86 if (!sid) {
87 ERR("out of memory\n");
88 return;
89 }
90
91 sid->revision = 0x01;
92 sid->elements = numdashes;
93
94 np = 0;
95 while (sidstringlength > 0) {
96 val = 0;
97 i = 0;
98 while (sidstring[i] != '-' && i < sidstringlength) {
99 if (sidstring[i] >= '0' && sidstring[i] <= '9') {
100 val *= 10;
101 val += sidstring[i] - '0';
102 } else
103 break;
104
105 i++;
106 }
107
108 i++;
109 TRACE("val = %u, i = %u, ssl = %lu\n", (uint32_t)val, i, sidstringlength);
110
111 if (np == 0) {
112 sid->auth[0] = (uint8_t)((val & 0xff0000000000) >> 40);
113 sid->auth[1] = (uint8_t)((val & 0xff00000000) >> 32);
114 sid->auth[2] = (uint8_t)((val & 0xff000000) >> 24);
115 sid->auth[3] = (uint8_t)((val & 0xff0000) >> 16);
116 sid->auth[4] = (uint8_t)((val & 0xff00) >> 8);
117 sid->auth[5] = val & 0xff;
118 } else {
119 sid->nums[np-1] = (uint32_t)val;
120 }
121
122 np++;
123
124 if (sidstringlength > i) {
125 sidstringlength -= i;
126
127 sidstring = &sidstring[i];
128 } else
129 break;
130 }
131
133 if (!um) {
134 ERR("out of memory\n");
136 return;
137 }
138
139 um->sid = sid;
140 um->uid = uid;
141
143}
LIST_ENTRY uid_map_list
Definition: btrfs.c:68
LIST_ENTRY listentry
Definition: btrfs_drv.h:903
PSID sid
Definition: btrfs_drv.h:904
uint32_t uid
Definition: btrfs_drv.h:905

Referenced by read_mappings().

◆ add_volume_device()

void add_volume_device ( superblock sb,
PUNICODE_STRING  devpath,
uint64_t  length,
ULONG  disk_num,
ULONG  part_num 
)

Definition at line 1077 of file volume.c.

1077 {
1079 LIST_ENTRY* le;
1081 volume_child* vc;
1083 UNICODE_STRING devpath2;
1084 bool inserted = false, new_pdo = false;
1085 pdo_device_extension* pdode = NULL;
1086 PDEVICE_OBJECT pdo = NULL;
1087 bool process_drive_letters = false;
1088
1089 if (devpath->Length == 0)
1090 return;
1091
1093
1094 le = pdo_list.Flink;
1095 while (le != &pdo_list) {
1097
1098 if (RtlCompareMemory(&pdode2->uuid, &sb->uuid, sizeof(BTRFS_UUID)) == sizeof(BTRFS_UUID)) {
1099 pdode = pdode2;
1100 break;
1101 }
1102
1103 le = le->Flink;
1104 }
1105
1107 if (!NT_SUCCESS(Status)) {
1108 ERR("IoGetDeviceObjectPointer returned %08lx\n", Status);
1110 return;
1111 }
1112
1113 if (!pdode) {
1114 if (no_pnp) {
1115 Status = IoReportDetectedDevice(drvobj, InterfaceTypeUndefined, 0xFFFFFFFF, 0xFFFFFFFF, NULL, NULL, 0, &pdo);
1116
1117 if (!NT_SUCCESS(Status)) {
1118 ERR("IoReportDetectedDevice returned %08lx\n", Status);
1120 return;
1121 }
1122
1124
1125 if (!pdode) {
1126 ERR("out of memory\n");
1128 return;
1129 }
1130 } else {
1133 if (!NT_SUCCESS(Status)) {
1134 ERR("IoCreateDevice returned %08lx\n", Status);
1136 goto fail;
1137 }
1138
1140
1141 pdode = pdo->DeviceExtension;
1142 }
1143
1144 RtlZeroMemory(pdode, sizeof(pdo_device_extension));
1145
1146 pdode->type = VCB_TYPE_PDO;
1147 pdode->pdo = pdo;
1148 pdode->uuid = sb->uuid;
1149
1152 pdode->num_children = sb->num_devices;
1153 pdode->children_loaded = 0;
1154
1155 pdo->Flags &= ~DO_DEVICE_INITIALIZING;
1156 pdo->SectorSize = (USHORT)sb->sector_size;
1157
1159
1160 new_pdo = true;
1161 } else {
1164
1165 le = pdode->children.Flink;
1166 while (le != &pdode->children) {
1168
1169 if (RtlCompareMemory(&vc2->uuid, &sb->dev_item.device_uuid, sizeof(BTRFS_UUID)) == sizeof(BTRFS_UUID)) {
1170 // duplicate, ignore
1173 goto fail;
1174 }
1175
1176 le = le->Flink;
1177 }
1178 }
1179
1181 if (!vc) {
1182 ERR("out of memory\n");
1183
1186
1187 goto fail;
1188 }
1189
1190 vc->uuid = sb->dev_item.device_uuid;
1191 vc->devid = sb->dev_item.dev_id;
1192 vc->generation = sb->generation;
1194 vc->boot_volume = false;
1195
1197 drvobj, pnp_removal, pdode, &vc->notification_entry);
1198 if (!NT_SUCCESS(Status))
1199 WARN("IoRegisterPlugPlayNotification returned %08lx\n", Status);
1200
1201 vc->devobj = DeviceObject;
1202 vc->fileobj = FileObject;
1203
1204 devpath2 = *devpath;
1205
1206 // The PNP path sometimes begins \\?\ and sometimes \??\. We need to remove this prefix
1207 // so we can compare properly if the device is removed.
1208 if (devpath->Length > 4 * sizeof(WCHAR) && devpath->Buffer[0] == '\\' && (devpath->Buffer[1] == '\\' || devpath->Buffer[1] == '?') &&
1209 devpath->Buffer[2] == '?' && devpath->Buffer[3] == '\\') {
1210 devpath2.Buffer = &devpath2.Buffer[3];
1211 devpath2.Length -= 3 * sizeof(WCHAR);
1212 devpath2.MaximumLength -= 3 * sizeof(WCHAR);
1213 }
1214
1215 vc->pnp_name.Length = vc->pnp_name.MaximumLength = devpath2.Length;
1217
1218 if (vc->pnp_name.Buffer)
1219 RtlCopyMemory(vc->pnp_name.Buffer, devpath2.Buffer, devpath2.Length);
1220 else {
1221 ERR("out of memory\n");
1222 vc->pnp_name.Length = vc->pnp_name.MaximumLength = 0;
1223 }
1224
1225 vc->size = length;
1227 vc->disk_num = disk_num;
1228 vc->part_num = part_num;
1229 vc->had_drive_letter = false;
1230
1231 le = pdode->children.Flink;
1232 while (le != &pdode->children) {
1234
1235 if (vc2->generation < vc->generation) {
1236 if (le == pdode->children.Flink)
1237 pdode->num_children = sb->num_devices;
1238
1240 inserted = true;
1241 break;
1242 }
1243
1244 le = le->Flink;
1245 }
1246
1247 if (!inserted)
1248 InsertTailList(&pdode->children, &vc->list_entry);
1249
1250 pdode->children_loaded++;
1251
1252 if (pdode->vde && pdode->vde->mounted_device) {
1254
1255 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
1256
1257 le = Vcb->devices.Flink;
1258 while (le != &Vcb->devices) {
1260
1261 if (!dev->devobj && RtlCompareMemory(&dev->devitem.device_uuid, &sb->dev_item.device_uuid, sizeof(BTRFS_UUID)) == sizeof(BTRFS_UUID)) {
1262 dev->devobj = DeviceObject;
1263 dev->disk_num = disk_num;
1264 dev->part_num = part_num;
1265 init_device(Vcb, dev, false);
1266 break;
1267 }
1268
1269 le = le->Flink;
1270 }
1271
1272 ExReleaseResourceLite(&Vcb->tree_lock);
1273 }
1274
1275 if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {
1276 pdode->removable = true;
1277
1278 if (pdode->vde && pdode->vde->device)
1279 pdode->vde->device->Characteristics |= FILE_REMOVABLE_MEDIA;
1280 }
1281
1282 if (pdode->num_children == pdode->children_loaded || (pdode->children_loaded == 1 && allow_degraded_mount(&sb->uuid))) {
1283 if ((!new_pdo || !no_pnp) && pdode->vde) {
1284 Status = IoSetDeviceInterfaceState(&pdode->vde->bus_name, true);
1285 if (!NT_SUCCESS(Status))
1286 WARN("IoSetDeviceInterfaceState returned %08lx\n", Status);
1287 }
1288
1289 process_drive_letters = true;
1290 }
1291
1293
1294 if (new_pdo)
1296
1298
1299 if (process_drive_letters)
1300 drive_letter_callback(pdode);
1301
1302 if (new_pdo) {
1303 if (RtlCompareMemory(&sb->uuid, &boot_uuid, sizeof(BTRFS_UUID)) == sizeof(BTRFS_UUID))
1304 boot_add_device(pdo);
1305 else if (no_pnp)
1306 AddDevice(drvobj, pdo);
1307 else {
1310 }
1311 }
1312
1313 return;
1314
1315fail:
1317}
#define VCB_TYPE_PDO
Definition: btrfs_drv.h:690
#define FILE_DEVICE_SECURE_OPEN
Definition: cdrw_usr.h:46
BTRFS_UUID boot_uuid
Definition: boot.c:33
void boot_add_device(DEVICE_OBJECT *pdo)
Definition: boot.c:318
superblock * sb
Definition: btrfs.c:4261
void init_device(_In_ device_extension *Vcb, _Inout_ device *dev, _In_ bool get_nums)
Definition: btrfs.c:3416
uint32_t no_pnp
Definition: btrfs.c:87
#define BTRFS_SUPERBLOCK_FLAGS_SEEDING
Definition: btrfs.h:128
static bool allow_degraded_mount(BTRFS_UUID *uuid)
Definition: volume.c:877
PDRIVER_OBJECT drvobj
Definition: btrfs.c:65
LIST_ENTRY pdo_list
Definition: btrfs.c:104
ERESOURCE pdo_list_lock
Definition: btrfs.c:103
PDEVICE_OBJECT busobj
Definition: btrfs.c:66
NTSTATUS ExInitializeResourceLite(PULONG res)
Definition: env_spec_w32.h:641
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
#define ExConvertExclusiveToSharedLite(res)
Definition: env_spec_w32.h:652
@ InterfaceTypeUndefined
Definition: hwresource.cpp:136
#define FILE_AUTOGENERATED_DEVICE_NAME
Definition: iotypes.h:138
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
NTSTATUS NTAPI IoCreateDevice(IN PDRIVER_OBJECT DriverObject, IN ULONG DeviceExtensionSize, IN PUNICODE_STRING DeviceName, IN DEVICE_TYPE DeviceType, IN ULONG DeviceCharacteristics, IN BOOLEAN Exclusive, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1031
NTSTATUS NTAPI IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName, IN ACCESS_MASK DesiredAccess, OUT PFILE_OBJECT *FileObject, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1435
NTSTATUS NTAPI IoSetDeviceInterfaceState(IN PUNICODE_STRING SymbolicLinkName, IN BOOLEAN Enable)
Definition: deviface.c:1311
DRIVER_ADD_DEVICE AddDevice
Definition: parport.h:72
unsigned short USHORT
Definition: pedump.c:61
VOID NTAPI IoInvalidateDeviceRelations(IN PDEVICE_OBJECT DeviceObject, IN DEVICE_RELATION_TYPE Type)
Definition: pnpmgr.c:1772
NTSTATUS NTAPI IoRegisterPlugPlayNotification(_In_ IO_NOTIFICATION_EVENT_CATEGORY EventCategory, _In_ ULONG EventCategoryFlags, _In_opt_ PVOID EventCategoryData, _In_ PDRIVER_OBJECT DriverObject, _In_ PDRIVER_NOTIFICATION_CALLBACK_ROUTINE CallbackRoutine, _Inout_opt_ PVOID Context, _Out_ PVOID *NotificationEntry)
Definition: pnpnotify.c:345
NTSTATUS NTAPI IoReportDetectedDevice(_In_ PDRIVER_OBJECT DriverObject, _In_ INTERFACE_TYPE LegacyBusType, _In_ ULONG BusNumber, _In_ ULONG SlotNumber, _In_opt_ PCM_RESOURCE_LIST ResourceList, _In_opt_ PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirements, _In_ BOOLEAN ResourceAssigned, _Inout_ PDEVICE_OBJECT *DeviceObject)
Definition: pnpreport.c:148
#define FILE_DEVICE_DISK
Definition: winioctl.h:113
#define true
Definition: stdbool.h:36
BTRFS_UUID device_uuid
Definition: btrfs.h:190
PVOID DeviceExtension
Definition: env_spec_w32.h:418
USHORT MaximumLength
Definition: env_spec_w32.h:370
PDEVICE_OBJECT device
Definition: btrfs_drv.h:875
UNICODE_STRING bus_name
Definition: btrfs_drv.h:879
PDEVICE_OBJECT mounted_device
Definition: btrfs_drv.h:876
PDEVICE_OBJECT buspdo
Definition: btrfs_drv.h:848
ERESOURCE child_lock
Definition: btrfs_drv.h:896
PDEVICE_OBJECT pdo
Definition: btrfs_drv.h:890
uint64_t children_loaded
Definition: btrfs_drv.h:895
LIST_ENTRY children
Definition: btrfs_drv.h:897
volume_device_extension * vde
Definition: btrfs_drv.h:889
uint64_t num_children
Definition: btrfs_drv.h:894
LIST_ENTRY list_entry
Definition: btrfs_drv.h:899
uint64_t flags
Definition: btrfs.h:227
uint32_t sector_size
Definition: btrfs.h:238
BTRFS_UUID uuid
Definition: btrfs.h:225
uint64_t generation
Definition: btrfs.h:229
uint64_t num_devices
Definition: btrfs.h:237
DEV_ITEM dev_item
Definition: btrfs.h:251
LIST_ENTRY list_entry
Definition: btrfs_drv.h:867
PFILE_OBJECT fileobj
Definition: btrfs_drv.h:858
uint64_t size
Definition: btrfs_drv.h:860
uint64_t devid
Definition: btrfs_drv.h:855
ULONG part_num
Definition: btrfs_drv.h:865
ULONG disk_num
Definition: btrfs_drv.h:864
void * notification_entry
Definition: btrfs_drv.h:863
bool seeding
Definition: btrfs_drv.h:861
bool boot_volume
Definition: btrfs_drv.h:866
UNICODE_STRING pnp_name
Definition: btrfs_drv.h:859
PDEVICE_OBJECT devobj
Definition: btrfs_drv.h:857
bool had_drive_letter
Definition: btrfs_drv.h:862
uint64_t generation
Definition: btrfs_drv.h:856
BTRFS_UUID uuid
Definition: btrfs_drv.h:854
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
@ BusRelations
Definition: iotypes.h:2152
#define DO_BUS_ENUMERATED_DEVICE
@ EventCategoryTargetDeviceChange
Definition: iotypes.h:1227
* PFILE_OBJECT
Definition: iotypes.h:1998
#define ObDereferenceObject
Definition: obfuncs.h:203
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by test_vol().

◆ alloc_chunk()

◆ allocate_cache()

NTSTATUS allocate_cache ( device_extension Vcb,
bool changed,
PIRP  Irp,
LIST_ENTRY rollback 
)

Definition at line 1382 of file free-space.c.

1382 {
1383 LIST_ENTRY *le, batchlist;
1385
1386 *changed = false;
1387
1388 InitializeListHead(&batchlist);
1389
1390 ExAcquireResourceExclusiveLite(&Vcb->chunk_lock, true);
1391
1392 le = Vcb->chunks.Flink;
1393 while (le != &Vcb->chunks) {
1395
1396 if (c->space_changed && c->chunk_item->size >= 0x6400000) { // 100MB
1397 bool b;
1398
1400 Status = allocate_cache_chunk(Vcb, c, &b, &batchlist, Irp, rollback);
1402
1403 if (b)
1404 *changed = true;
1405
1406 if (!NT_SUCCESS(Status)) {
1407 ERR("allocate_cache_chunk(%I64x) returned %08lx\n", c->offset, Status);
1408 ExReleaseResourceLite(&Vcb->chunk_lock);
1409 clear_batch_list(Vcb, &batchlist);
1410 return Status;
1411 }
1412 }
1413
1414 le = le->Flink;
1415 }
1416
1417 ExReleaseResourceLite(&Vcb->chunk_lock);
1418
1419 Status = commit_batch_list(Vcb, &batchlist, Irp);
1420 if (!NT_SUCCESS(Status)) {
1421 ERR("commit_batch_list returned %08lx\n", Status);
1422 return Status;
1423 }
1424
1425 return STATUS_SUCCESS;
1426}
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: btrfs_drv.h:1365
void void void NTSTATUS commit_batch_list(_Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, LIST_ENTRY *batchlist, PIRP Irp) __attribute__((nonnull(1
void void void NTSTATUS void clear_batch_list(device_extension *Vcb, LIST_ENTRY *batchlist) __attribute__((nonnull(1
static NTSTATUS allocate_cache_chunk(device_extension *Vcb, chunk *c, bool *changed, LIST_ENTRY *batchlist, PIRP Irp, LIST_ENTRY *rollback)
Definition: free-space.c:1043
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
#define b
Definition: ke_i.h:79

Referenced by do_write2().

◆ blake2b()

void blake2b ( void out,
size_t  outlen,
const void in,
size_t  inlen 
)

Definition at line 237 of file blake2b-ref.c.

238{
239 blake2b_state S[1];
240
241 blake2b_init( S, outlen );
242
243 blake2b_update( S, ( const uint8_t * )in, inlen );
244 blake2b_final( S, out, outlen );
245}
static int blake2b_final(blake2b_state *S, void *out, size_t outlen)
Definition: blake2b-ref.c:212
static void blake2b_init(blake2b_state *S, size_t outlen)
Definition: blake2b-ref.c:97
static int blake2b_update(blake2b_state *S, const void *in, size_t inlen)
Definition: blake2b-ref.c:185
Definition: movable.cpp:9

◆ boot_add_device()

void boot_add_device ( DEVICE_OBJECT pdo)

Definition at line 318 of file boot.c.

318 {
320
321 AddDevice(drvobj, pdo);
322
323 // To stop Windows sneakily setting DOE_START_PENDING
324 pdode->dont_report = true;
325
326 if (pdo->DeviceObjectExtension) {
327 ((DEVOBJ_EXTENSION2*)pdo->DeviceObjectExtension)->ExtensionFlags &= ~DOE_START_PENDING;
328
329 if (pdode && pdode->vde && pdode->vde->device)
330 ((DEVOBJ_EXTENSION2*)pdode->vde->device->DeviceObjectExtension)->ExtensionFlags &= ~DOE_START_PENDING;
331 }
332
334}
PDRIVER_OBJECT drvobj
Definition: btrfs.c:65
static void mountmgr_notification(BTRFS_UUID *uuid)
Definition: boot.c:180

Referenced by add_volume_device(), and check_system_root().

◆ calc_sha256()

void calc_sha256 ( uint8_t hash,
const void input,
size_t  len 
)

Definition at line 126 of file sha256.c.

127{
128 /*
129 * Note 1: All integers (expect indexes) are 32-bit unsigned integers and addition is calculated modulo 2^32.
130 * Note 2: For each round, there is one round constant k[i] and one entry in the message schedule array w[i], 0 = i = 63
131 * Note 3: The compression function uses 8 working variables, a through h
132 * Note 4: Big-endian convention is used when expressing the constants in this pseudocode,
133 * and when parsing message block data from bytes to words, for example,
134 * the first word of the input message "abc" after padding is 0x61626380
135 */
136
137 /*
138 * Initialize hash values:
139 * (first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19):
140 */
141 uint32_t h[] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 };
142 unsigned i, j;
143
144 /* 512-bit chunks is what we will operate on. */
145 uint8_t chunk[64];
146
147 struct buffer_state state;
148
150
151 while (calc_chunk(chunk, &state)) {
152 uint32_t ah[8];
153
154 const uint8_t *p = chunk;
155
156 /* Initialize working variables to current hash value: */
157 for (i = 0; i < 8; i++)
158 ah[i] = h[i];
159
160 /* Compression function main loop: */
161 for (i = 0; i < 4; i++) {
162 /*
163 * The w-array is really w[64], but since we only need
164 * 16 of them at a time, we save stack by calculating
165 * 16 at a time.
166 *
167 * This optimization was not there initially and the
168 * rest of the comments about w[64] are kept in their
169 * initial state.
170 */
171
172 /*
173 * create a 64-entry message schedule array w[0..63] of 32-bit words
174 * (The initial values in w[0..63] don't matter, so many implementations zero them here)
175 * copy chunk into first 16 words w[0..15] of the message schedule array
176 */
177 uint32_t w[16];
178
179 for (j = 0; j < 16; j++) {
180 if (i == 0) {
181 w[j] = (uint32_t) p[0] << 24 | (uint32_t) p[1] << 16 |
182 (uint32_t) p[2] << 8 | (uint32_t) p[3];
183 p += 4;
184 } else {
185 /* Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array: */
186 const uint32_t s0 = right_rot(w[(j + 1) & 0xf], 7) ^ right_rot(w[(j + 1) & 0xf], 18) ^ (w[(j + 1) & 0xf] >> 3);
187 const uint32_t s1 = right_rot(w[(j + 14) & 0xf], 17) ^ right_rot(w[(j + 14) & 0xf], 19) ^ (w[(j + 14) & 0xf] >> 10);
188 w[j] = w[j] + s0 + w[(j + 9) & 0xf] + s1;
189 }
190 {
191 const uint32_t s1 = right_rot(ah[4], 6) ^ right_rot(ah[4], 11) ^ right_rot(ah[4], 25);
192 const uint32_t ch = (ah[4] & ah[5]) ^ (~ah[4] & ah[6]);
193 const uint32_t temp1 = ah[7] + s1 + ch + k[i << 4 | j] + w[j];
194 const uint32_t s0 = right_rot(ah[0], 2) ^ right_rot(ah[0], 13) ^ right_rot(ah[0], 22);
195 const uint32_t maj = (ah[0] & ah[1]) ^ (ah[0] & ah[2]) ^ (ah[1] & ah[2]);
196 const uint32_t temp2 = s0 + maj;
197
198 ah[7] = ah[6];
199 ah[6] = ah[5];
200 ah[5] = ah[4];
201 ah[4] = ah[3] + temp1;
202 ah[3] = ah[2];
203 ah[2] = ah[1];
204 ah[1] = ah[0];
205 ah[0] = temp1 + temp2;
206 }
207 }
208 }
209
210 /* Add the compressed chunk to the current hash value: */
211 for (i = 0; i < 8; i++)
212 h[i] += ah[i];
213 }
214
215 /* Produce the final hash value (big-endian): */
216 for (i = 0, j = 0; i < 8; i++)
217 {
218 hash[j++] = (uint8_t) (h[i] >> 24);
219 hash[j++] = (uint8_t) (h[i] >> 16);
220 hash[j++] = (uint8_t) (h[i] >> 8);
221 hash[j++] = (uint8_t) h[i];
222 }
223}
static int state
Definition: maze.c:121
static uint32_t right_rot(uint32_t value, unsigned int count)
Definition: sha256.c:43
static void init_buf_state(struct buffer_state *state, const void *input, size_t len)
Definition: sha256.c:52
static const uint32_t k[]
Definition: sha256.c:24
static int calc_chunk(uint8_t chunk[CHUNK_SIZE], struct buffer_state *state)
Definition: sha256.c:62
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLenum GLenum input
Definition: glext.h:9031
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:6102
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
struct S1 s1

Referenced by calc_superblock_checksum(), calc_thread_main(), calc_tree_checksum(), check_sector_csum(), check_superblock_checksum(), check_tree_checksum(), get_sector_csum(), and get_tree_checksum().

◆ calc_thread_main()

void calc_thread_main ( device_extension Vcb,
calc_job cj 
)

Definition at line 22 of file calcthread.c.

22 {
23 while (true) {
24 KIRQL irql;
25 calc_job* cj2;
26 uint8_t* src;
27 void* dest;
28 bool last_one = false;
29
30 KeAcquireSpinLock(&Vcb->calcthreads.spinlock, &irql);
31
32 if (cj && cj->not_started == 0) {
33 KeReleaseSpinLock(&Vcb->calcthreads.spinlock, irql);
34 break;
35 }
36
37 if (cj)
38 cj2 = cj;
39 else {
40 if (IsListEmpty(&Vcb->calcthreads.job_list)) {
41 KeReleaseSpinLock(&Vcb->calcthreads.spinlock, irql);
42 break;
43 }
44
45 cj2 = CONTAINING_RECORD(Vcb->calcthreads.job_list.Flink, calc_job, list_entry);
46 }
47
48 src = cj2->in;
49 dest = cj2->out;
50
51 switch (cj2->type) {
56 cj2->in = (uint8_t*)cj2->in + Vcb->superblock.sector_size;
57 cj2->out = (uint8_t*)cj2->out + Vcb->csum_size;
58 break;
59
60 default:
61 break;
62 }
63
64 cj2->not_started--;
65
66 if (cj2->not_started == 0) {
68 last_one = true;
69 }
70
71 KeReleaseSpinLock(&Vcb->calcthreads.spinlock, irql);
72
73 switch (cj2->type) {
75 *(uint32_t*)dest = ~calc_crc32c(0xffffffff, src, Vcb->superblock.sector_size);
76 break;
77
79 *(uint64_t*)dest = XXH64(src, Vcb->superblock.sector_size, 0);
80 break;
81
83 calc_sha256(dest, src, Vcb->superblock.sector_size);
84 break;
85
87 blake2b(dest, BLAKE2_HASH_SIZE, src, Vcb->superblock.sector_size);
88 break;
89
91 cj2->Status = zlib_decompress(src, cj2->inlen, dest, cj2->outlen);
92
93 if (!NT_SUCCESS(cj2->Status))
94 ERR("zlib_decompress returned %08lx\n", cj2->Status);
95 break;
96
98 cj2->Status = lzo_decompress(src, cj2->inlen, dest, cj2->outlen, cj2->off);
99
100 if (!NT_SUCCESS(cj2->Status))
101 ERR("lzo_decompress returned %08lx\n", cj2->Status);
102 break;
103
105 cj2->Status = zstd_decompress(src, cj2->inlen, dest, cj2->outlen);
106
107 if (!NT_SUCCESS(cj2->Status))
108 ERR("zstd_decompress returned %08lx\n", cj2->Status);
109 break;
110
112 cj2->Status = zlib_compress(src, cj2->inlen, dest, cj2->outlen, Vcb->options.zlib_level, &cj2->space_left);
113
114 if (!NT_SUCCESS(cj2->Status))
115 ERR("zlib_compress returned %08lx\n", cj2->Status);
116 break;
117
119 cj2->Status = lzo_compress(src, cj2->inlen, dest, cj2->outlen, &cj2->space_left);
120
121 if (!NT_SUCCESS(cj2->Status))
122 ERR("lzo_compress returned %08lx\n", cj2->Status);
123 break;
124
126 cj2->Status = zstd_compress(src, cj2->inlen, dest, cj2->outlen, Vcb->options.zstd_level, &cj2->space_left);
127
128 if (!NT_SUCCESS(cj2->Status))
129 ERR("zstd_compress returned %08lx\n", cj2->Status);
130 break;
131 }
132
133 if (InterlockedDecrement(&cj2->left) == 0)
134 KeSetEvent(&cj2->event, 0, false);
135
136 if (last_one)
137 break;
138 }
139}
#define InterlockedDecrement
Definition: armddk.h:52
void blake2b(void *out, size_t outlen, const void *in, size_t inlen)
Definition: blake2b-ref.c:237
NTSTATUS zlib_compress(uint8_t *inbuf, uint32_t inlen, uint8_t *outbuf, uint32_t outlen, unsigned int level, unsigned int *space_left)
Definition: compress.c:336
NTSTATUS zlib_decompress(uint8_t *inbuf, uint32_t inlen, uint8_t *outbuf, uint32_t outlen)
Definition: compress.c:377
NTSTATUS zstd_decompress(uint8_t *inbuf, uint32_t inlen, uint8_t *outbuf, uint32_t outlen)
Definition: compress.c:676
NTSTATUS lzo_decompress(uint8_t *inbuf, uint32_t inlen, uint8_t *outbuf, uint32_t outlen, uint32_t inpageoff)
Definition: compress.c:278
#define BLAKE2_HASH_SIZE
Definition: btrfs_drv.h:1252
void calc_sha256(uint8_t *hash, const void *input, size_t len)
Definition: sha256.c:126
NTSTATUS lzo_compress(uint8_t *inbuf, uint32_t inlen, uint8_t *outbuf, uint32_t outlen, unsigned int *space_left)
Definition: compress.c:727
NTSTATUS zstd_compress(uint8_t *inbuf, uint32_t inlen, uint8_t *outbuf, uint32_t outlen, uint32_t level, unsigned int *space_left)
Definition: compress.c:805
GLenum src
Definition: glext.h:6340
static char * dest
Definition: rtl.c:135
NTSTATUS Status
Definition: btrfs_drv.h:648
unsigned int space_left
Definition: btrfs_drv.h:644
void * in
Definition: btrfs_drv.h:642
LONG not_started
Definition: btrfs_drv.h:645
void * out
Definition: btrfs_drv.h:643
unsigned int inlen
Definition: btrfs_drv.h:644
LIST_ENTRY list_entry
Definition: btrfs_drv.h:641
unsigned int off
Definition: btrfs_drv.h:644
unsigned int outlen
Definition: btrfs_drv.h:644
KEVENT event
Definition: btrfs_drv.h:646
LONG left
Definition: btrfs_drv.h:645
enum calc_thread_type type
Definition: btrfs_drv.h:647
XXH_PUBLIC_API unsigned long long XXH64(const void *input, size_t len, unsigned long long seed)
Definition: xxhash.c:555

Referenced by _Function_class_(), do_calc_job(), and write_compressed().

◆ calc_tree_checksum()

void calc_tree_checksum ( device_extension Vcb,
tree_header th 
)

Definition at line 1806 of file flushthread.c.

1806 {
1807 switch (Vcb->superblock.csum_type) {
1808 case CSUM_TYPE_CRC32C:
1809 *((uint32_t*)th) = ~calc_crc32c(0xffffffff, (uint8_t*)&th->fs_uuid, Vcb->superblock.node_size - sizeof(th->csum));
1810 break;
1811
1812 case CSUM_TYPE_XXHASH:
1813 *((uint64_t*)th) = XXH64((uint8_t*)&th->fs_uuid, Vcb->superblock.node_size - sizeof(th->csum), 0);
1814 break;
1815
1816 case CSUM_TYPE_SHA256:
1817 calc_sha256((uint8_t*)th, &th->fs_uuid, Vcb->superblock.node_size - sizeof(th->csum));
1818 break;
1819
1820 case CSUM_TYPE_BLAKE2:
1821 blake2b((uint8_t*)th, BLAKE2_HASH_SIZE, &th->fs_uuid, Vcb->superblock.node_size - sizeof(th->csum));
1822 break;
1823 }
1824}
#define CSUM_TYPE_SHA256
Definition: btrfs.h:134
#define CSUM_TYPE_XXHASH
Definition: btrfs.h:133
#define CSUM_TYPE_BLAKE2
Definition: btrfs.h:135
#define CSUM_TYPE_CRC32C
Definition: btrfs.h:132
uint8_t csum[32]
Definition: btrfs.h:154
BTRFS_UUID fs_uuid
Definition: btrfs.h:155

Referenced by snapshot_tree_copy(), write_metadata_items(), and write_trees().

◆ check_csum()

NTSTATUS check_csum ( device_extension Vcb,
uint8_t data,
uint32_t  sectors,
void csum 
)

Definition at line 87 of file read.c.

87 {
88 void* csum2;
89
90 csum2 = ExAllocatePoolWithTag(PagedPool, Vcb->csum_size * sectors, ALLOC_TAG);
91 if (!csum2) {
92 ERR("out of memory\n");
94 }
95
96 do_calc_job(Vcb, data, sectors, csum2);
97
98 if (RtlCompareMemory(csum2, csum, sectors * Vcb->csum_size) != sectors * Vcb->csum_size) {
99 ExFreePool(csum2);
100 return STATUS_CRC_ERROR;
101 }
102
103 ExFreePool(csum2);
104
105 return STATUS_SUCCESS;
106}
void do_calc_job(device_extension *Vcb, uint8_t *data, uint32_t sectors, void *csum)
Definition: calcthread.c:141
__u8 sectors[2]
Definition: mkdosfs.c:8
#define STATUS_CRC_ERROR
Definition: udferr_usr.h:153

Referenced by read_data_dup(), read_data_raid0(), read_data_raid10(), read_data_raid5(), and read_data_raid6().

◆ check_file_name_valid()

NTSTATUS check_file_name_valid ( _In_ PUNICODE_STRING  us,
_In_ bool  posix,
_In_ bool  stream 
)

Definition at line 5797 of file btrfs.c.

5797 {
5798 ULONG i;
5799
5800 if (us->Length < sizeof(WCHAR))
5802
5803 if (us->Length > 255 * sizeof(WCHAR))
5805
5806 for (i = 0; i < us->Length / sizeof(WCHAR); i++) {
5807 if (us->Buffer[i] == '/' || us->Buffer[i] == 0 ||
5808 (!posix && (us->Buffer[i] == '/' || us->Buffer[i] == ':')) ||
5809 (!posix && !stream && (us->Buffer[i] == '<' || us->Buffer[i] == '>' || us->Buffer[i] == '"' ||
5810 us->Buffer[i] == '|' || us->Buffer[i] == '?' || us->Buffer[i] == '*' || (us->Buffer[i] >= 1 && us->Buffer[i] <= 31))))
5812
5813 /* Don't allow unpaired surrogates ("WTF-16") */
5814
5815 if ((us->Buffer[i] & 0xfc00) == 0xdc00 && (i == 0 || ((us->Buffer[i-1] & 0xfc00) != 0xd800)))
5817
5818 if ((us->Buffer[i] & 0xfc00) == 0xd800 && (i == (us->Length / sizeof(WCHAR)) - 1 || ((us->Buffer[i+1] & 0xfc00) != 0xdc00)))
5820 }
5821
5822 if (us->Buffer[0] == '.' && (us->Length == sizeof(WCHAR) || (us->Length == 2 * sizeof(WCHAR) && us->Buffer[1] == '.')))
5824
5825 /* The Linux driver expects filenames with a maximum length of 255 bytes - make sure
5826 * that our UTF-8 length won't be longer than that. */
5827 if (us->Length >= 85 * sizeof(WCHAR)) {
5829 ULONG utf8len;
5830
5831 Status = utf16_to_utf8(NULL, 0, &utf8len, us->Buffer, us->Length);
5832 if (!NT_SUCCESS(Status))
5833 return Status;
5834
5835 if (utf8len > 255)
5837 else if (stream && utf8len > 250) // minus five bytes for "user."
5839 }
5840
5841 return STATUS_SUCCESS;
5842}
NTSTATUS utf16_to_utf8(char *dest, ULONG dest_max, ULONG *dest_len, WCHAR *src, ULONG src_len)
Definition: btrfs.c:894
return STATUS_SUCCESS
Definition: btrfs.c:3080
static const BYTE us[]
Definition: encode.c:689
Definition: parse.h:23
#define STATUS_OBJECT_NAME_INVALID
Definition: udferr_usr.h:148

Referenced by create_snapshot(), create_stream(), create_subvol(), file_create(), find_file_in_dir(), rename_file_to_stream(), rename_stream(), set_link_information(), and set_rename_information().

◆ check_sector_csum()

bool check_sector_csum ( device_extension Vcb,
void buf,
void csum 
)

Definition at line 202 of file read.c.

202 {
203 switch (Vcb->superblock.csum_type) {
204 case CSUM_TYPE_CRC32C: {
205 uint32_t crc32 = ~calc_crc32c(0xffffffff, buf, Vcb->superblock.sector_size);
206
207 return *(uint32_t*)csum == crc32;
208 }
209
210 case CSUM_TYPE_XXHASH: {
211 uint64_t hash = XXH64(buf, Vcb->superblock.sector_size, 0);
212
213 return *(uint64_t*)csum == hash;
214 }
215
216 case CSUM_TYPE_SHA256: {
218
219 calc_sha256(hash, buf, Vcb->superblock.sector_size);
220
222 }
223
224 case CSUM_TYPE_BLAKE2: {
226
227 blake2b(hash, sizeof(hash), buf, Vcb->superblock.sector_size);
228
230 }
231 }
232
233 return false;
234}
#define SHA256_HASH_SIZE
Definition: btrfs_drv.h:1248
#define crc32(crc, buf, len)
Definition: inflate.c:1081
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751

Referenced by read_data_dup(), read_data_raid0(), read_data_raid10(), read_data_raid5(), read_data_raid6(), scrub_extent_raid0(), scrub_extent_raid10(), scrub_raid5_stripe(), and scrub_raid6_stripe().

◆ check_superblock_checksum()

bool check_superblock_checksum ( superblock sb)

Definition at line 2825 of file btrfs.c.

2825 {
2826 switch (sb->csum_type) {
2827 case CSUM_TYPE_CRC32C: {
2828 uint32_t crc32 = ~calc_crc32c(0xffffffff, (uint8_t*)&sb->uuid, (ULONG)sizeof(superblock) - sizeof(sb->checksum));
2829
2830 if (crc32 == *((uint32_t*)sb->checksum))
2831 return true;
2832
2833 WARN("crc32 was %08x, expected %08x\n", crc32, *((uint32_t*)sb->checksum));
2834
2835 break;
2836 }
2837
2838 case CSUM_TYPE_XXHASH: {
2839 uint64_t hash = XXH64(&sb->uuid, sizeof(superblock) - sizeof(sb->checksum), 0);
2840
2841 if (hash == *((uint64_t*)sb->checksum))
2842 return true;
2843
2844 WARN("superblock hash was %I64x, expected %I64x\n", hash, *((uint64_t*)sb->checksum));
2845
2846 break;
2847 }
2848
2849 case CSUM_TYPE_SHA256: {
2851
2852 calc_sha256(hash, &sb->uuid, sizeof(superblock) - sizeof(sb->checksum));
2853
2855 return true;
2856
2857 WARN("superblock hash was invalid\n");
2858
2859 break;
2860 }
2861
2862 case CSUM_TYPE_BLAKE2: {
2864
2865 blake2b(hash, sizeof(hash), &sb->uuid, sizeof(superblock) - sizeof(sb->checksum));
2866
2868 return true;
2869
2870 WARN("superblock hash was invalid\n");
2871
2872 break;
2873 }
2874
2875 default:
2876 WARN("unrecognized csum type %x\n", sb->csum_type);
2877 }
2878
2879 return false;
2880}
uint16_t csum_type
Definition: btrfs.h:247
uint8_t checksum[32]
Definition: btrfs.h:224

Referenced by device_still_valid(), is_device_part_of_mounted_btrfs_raid(), read_superblock(), still_has_superblock(), test_vol(), and verify_device().

◆ check_system_root()

void check_system_root ( )

Definition at line 336 of file boot.c.

336 {
337 LIST_ENTRY* le;
338 PDEVICE_OBJECT pdo_to_add = NULL;
339
340 TRACE("()\n");
341
342 // wait for any PNP notifications in progress to finish
345
346 if (!get_system_root())
347 return;
348
350
351 le = pdo_list.Flink;
352 while (le != &pdo_list) {
354
355 if (RtlCompareMemory(&pdode->uuid, &boot_uuid, sizeof(BTRFS_UUID)) == sizeof(BTRFS_UUID)) {
356 if (!pdode->vde)
357 pdo_to_add = pdode->pdo;
358 else if (pdode->vde->device && !(pdode->vde->device->Flags & DO_SYSTEM_BOOT_PARTITION)) { // AddDevice has beaten us to it
360
363
364 Status = IoSetDeviceInterfaceState(&pdode->vde->bus_name, false);
365 if (!NT_SUCCESS(Status))
366 ERR("IoSetDeviceInterfaceState returned %08lx\n", Status);
367
369 if (!NT_SUCCESS(Status))
370 ERR("IoSetDeviceInterfaceState returned %08lx\n", Status);
371 }
372
373 break;
374 }
375
376 le = le->Flink;
377 }
378
380
382
383 // If our FS depends on volumes that aren't there when we do our IoRegisterPlugPlayNotification calls
384 // in DriverEntry, bus_query_device_relations won't get called until it's too late. We need to do our
385 // own call to AddDevice here as a result. We need to clear the DOE_START_PENDING bits, or NtOpenFile
386 // will return STATUS_NO_SUCH_DEVICE.
387 if (pdo_to_add)
388 boot_add_device(pdo_to_add);
389}
#define TRUE
Definition: types.h:120
static bool get_system_root()
Definition: boot.c:49
LIST_ENTRY pdo_list
Definition: btrfs.c:104
ERESOURCE pdo_list_lock
Definition: btrfs.c:103
static void check_boot_options()
Definition: boot.c:232
ERESOURCE boot_lock
Definition: btrfs.c:110
#define DO_SYSTEM_BOOT_PARTITION
Definition: env_spec_w32.h:400

Referenced by _Function_class_().

◆ check_tree_checksum()

bool check_tree_checksum ( device_extension Vcb,
tree_header th 
)

Definition at line 128 of file read.c.

128 {
129 switch (Vcb->superblock.csum_type) {
130 case CSUM_TYPE_CRC32C: {
131 uint32_t crc32 = ~calc_crc32c(0xffffffff, (uint8_t*)&th->fs_uuid, Vcb->superblock.node_size - sizeof(th->csum));
132
133 if (crc32 == *((uint32_t*)th->csum))
134 return true;
135
136 WARN("hash was %08x, expected %08x\n", crc32, *((uint32_t*)th->csum));
137
138 break;
139 }
140
141 case CSUM_TYPE_XXHASH: {
142 uint64_t hash = XXH64((uint8_t*)&th->fs_uuid, Vcb->superblock.node_size - sizeof(th->csum), 0);
143
144 if (hash == *((uint64_t*)th->csum))
145 return true;
146
147 WARN("hash was %I64x, expected %I64x\n", hash, *((uint64_t*)th->csum));
148
149 break;
150 }
151
152 case CSUM_TYPE_SHA256: {
154
155 calc_sha256(hash, (uint8_t*)&th->fs_uuid, Vcb->superblock.node_size - sizeof(th->csum));
156
158 return true;
159
160 WARN("hash was invalid\n");
161
162 break;
163 }
164
165 case CSUM_TYPE_BLAKE2: {
167
168 blake2b(hash, sizeof(hash), (uint8_t*)&th->fs_uuid, Vcb->superblock.node_size - sizeof(th->csum));
169
171 return true;
172
173 WARN("hash was invalid\n");
174
175 break;
176 }
177 }
178
179 return false;
180}

Referenced by read_data_dup(), read_data_raid0(), read_data_raid10(), read_data_raid5(), read_data_raid6(), scrub_extent_dup(), scrub_extent_raid0(), scrub_extent_raid10(), scrub_raid5_stripe(), and scrub_raid6_stripe().

◆ chunk_lock_range()

void chunk_lock_range ( _In_ device_extension Vcb,
_In_ chunk c,
_In_ uint64_t  start,
_In_ uint64_t  length 
)

Definition at line 5844 of file btrfs.c.

5844 {
5845 LIST_ENTRY* le;
5846 bool locked;
5847 range_lock* rl;
5848
5849 rl = ExAllocateFromNPagedLookasideList(&Vcb->range_lock_lookaside);
5850 if (!rl) {
5851 ERR("out of memory\n");
5852 return;
5853 }
5854
5855 rl->start = start;
5856 rl->length = length;
5857 rl->thread = PsGetCurrentThread();
5858
5859 while (true) {
5860 locked = false;
5861
5862 ExAcquireResourceExclusiveLite(&c->range_locks_lock, true);
5863
5864 le = c->range_locks.Flink;
5865 while (le != &c->range_locks) {
5867
5868 if (rl2->start < start + length && rl2->start + rl2->length > start && rl2->thread != PsGetCurrentThread()) {
5869 locked = true;
5870 break;
5871 }
5872
5873 le = le->Flink;
5874 }
5875
5876 if (!locked) {
5877 InsertTailList(&c->range_locks, &rl->list_entry);
5878
5879 ExReleaseResourceLite(&c->range_locks_lock);
5880 return;
5881 }
5882
5883 KeClearEvent(&c->range_locks_event);
5884
5885 ExReleaseResourceLite(&c->range_locks_lock);
5886
5887 KeWaitForSingleObject(&c->range_locks_event, UserRequest, KernelMode, false, NULL);
5888 }
5889}
InsertTailList & Vcb
Definition: btrfs.c:3044
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
uint64_t start
Definition: btrfs_drv.h:546
uint64_t length
Definition: btrfs_drv.h:547
PETHREAD thread
Definition: btrfs_drv.h:548
LIST_ENTRY list_entry
Definition: btrfs_drv.h:549
@ UserRequest
Definition: ketypes.h:421

Referenced by read_data(), and scrub_chunk_raid56_stripe_run().

◆ chunk_unlock_range()

void chunk_unlock_range ( _In_ device_extension Vcb,
_In_ chunk c,
_In_ uint64_t  start,
_In_ uint64_t  length 
)

Definition at line 5891 of file btrfs.c.

5891 {
5892 LIST_ENTRY* le;
5893
5894 ExAcquireResourceExclusiveLite(&c->range_locks_lock, true);
5895
5896 le = c->range_locks.Flink;
5897 while (le != &c->range_locks) {
5899
5900 if (rl->start == start && rl->length == length) {
5902 ExFreeToNPagedLookasideList(&Vcb->range_lock_lookaside, rl);
5903 break;
5904 }
5905
5906 le = le->Flink;
5907 }
5908
5909 KeSetEvent(&c->range_locks_event, 0, false);
5910
5911 ExReleaseResourceLite(&c->range_locks_lock);
5912}

Referenced by read_data(), and scrub_chunk_raid56_stripe_run().

◆ clear_batch_list()

◆ clear_free_space_cache()

NTSTATUS clear_free_space_cache ( device_extension Vcb,
LIST_ENTRY batchlist,
PIRP  Irp 
)

Definition at line 59 of file free-space.c.

59 {
60 KEY searchkey;
61 traverse_ptr tp, next_tp;
63 bool b;
65
67
68 searchkey.obj_id = FREE_SPACE_CACHE_ID;
69 searchkey.obj_type = 0;
70 searchkey.offset = 0;
71
72 Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
73 if (!NT_SUCCESS(Status)) {
74 ERR("error - find_item returned %08lx\n", Status);
75 return Status;
76 }
77
78 do {
79 if (tp.item->key.obj_id > searchkey.obj_id || (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type > searchkey.obj_type))
80 break;
81
82 if (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == searchkey.obj_type) {
84 if (!NT_SUCCESS(Status)) {
85 ERR("delete_tree_item returned %08lx\n", Status);
86 return Status;
87 }
88
89 if (tp.item->size >= sizeof(FREE_SPACE_ITEM)) {
91
93 WARN("key (%I64x,%x,%I64x) does not point to an INODE_ITEM\n", fsi->key.obj_id, fsi->key.obj_type, fsi->key.offset);
94 else {
95 LIST_ENTRY* le;
96
98
99 if (!NT_SUCCESS(Status))
100 ERR("remove_free_space_inode for (%I64x,%x,%I64x) returned %08lx\n", fsi->key.obj_id, fsi->key.obj_type, fsi->key.offset, Status);
101
102 le = Vcb->chunks.Flink;
103 while (le != &Vcb->chunks) {
105
106 if (c->offset == tp.item->key.offset && c->cache) {
107 reap_fcb(c->cache);
108 c->cache = NULL;
109 }
110
111 le = le->Flink;
112 }
113 }
114 } else
115 WARN("(%I64x,%x,%I64x) was %u bytes, expected %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(FREE_SPACE_ITEM));
116 }
117
118 b = find_next_item(Vcb, &tp, &next_tp, false, Irp);
119 if (b)
120 tp = next_tp;
121 } while (b);
122
124
125 if (NT_SUCCESS(Status))
127 else
129
130 if (Vcb->space_root) {
131 searchkey.obj_id = 0;
132 searchkey.obj_type = 0;
133 searchkey.offset = 0;
134
135 Status = find_item(Vcb, Vcb->space_root, &tp, &searchkey, false, Irp);
136 if (!NT_SUCCESS(Status)) {
137 ERR("find_item returned %08lx\n", Status);
138 return Status;
139 }
140
141 do {
143 if (!NT_SUCCESS(Status)) {
144 ERR("delete_tree_item returned %08lx\n", Status);
145 return Status;
146 }
147
148 b = find_next_item(Vcb, &tp, &next_tp, false, Irp);
149 if (b)
150 tp = next_tp;
151 } while (b);
152 }
153
154 // regenerate free space tree
155 if (Vcb->superblock.compat_ro_flags & BTRFS_COMPAT_RO_FLAGS_FREE_SPACE_CACHE) {
156 LIST_ENTRY* le;
157
158 ExAcquireResourceSharedLite(&Vcb->chunk_lock, true);
159
160 le = Vcb->chunks.Flink;
161 while (le != &Vcb->chunks) {
163
164 if (!c->cache_loaded) {
166
168 if (!NT_SUCCESS(Status)) {
169 ERR("load_cache_chunk(%I64x) returned %08lx\n", c->offset, Status);
171 ExReleaseResourceLite(&Vcb->chunk_lock);
172 return Status;
173 }
174
175 c->changed = true;
176 c->space_changed = true;
177
179 }
180
181 le = le->Flink;
182 }
183
184 ExReleaseResourceLite(&Vcb->chunk_lock);
185 }
186
187 return Status;
188}
void do_rollback(device_extension *Vcb, LIST_ENTRY *rollback) __attribute__((nonnull(1
NTSTATUS NTSTATUS void clear_rollback(LIST_ENTRY *rollback) __attribute__((nonnull(1)))
void reap_fcb(fcb *fcb)
Definition: btrfs.c:1743
#define FREE_SPACE_CACHE_ID
Definition: btrfs.h:90
#define BTRFS_COMPAT_RO_FLAGS_FREE_SPACE_CACHE
Definition: btrfs.h:111
NTSTATUS load_cache_chunk(device_extension *Vcb, chunk *c, PIRP Irp)
Definition: free-space.c:980
static NTSTATUS remove_free_space_inode(device_extension *Vcb, uint64_t inode, LIST_ENTRY *batchlist, PIRP Irp, LIST_ENTRY *rollback)
Definition: free-space.c:25
if(dx< 0)
Definition: linetemp.h:194

Referenced by mount_vol().

◆ clear_rollback()

◆ commit_batch_list()

void void void NTSTATUS commit_batch_list ( _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension Vcb,
LIST_ENTRY batchlist,
PIRP  Irp 
)

◆ compat_FsRtlValidateReparsePointBuffer()

NTSTATUS __stdcall compat_FsRtlValidateReparsePointBuffer ( IN ULONG  BufferLength,
IN PREPARSE_DATA_BUFFER  ReparseBuffer 
)

Definition at line 32 of file fsrtl.c.

33{
35 ULONG ReparseTag;
37
38 /* Validate data size range */
39 if (BufferLength < REPARSE_DATA_BUFFER_HEADER_SIZE || BufferLength > MAXIMUM_REPARSE_DATA_BUFFER_SIZE)
40 {
42 }
43
44 GuidBuffer = (PREPARSE_GUID_DATA_BUFFER)ReparseBuffer;
45 DataLength = ReparseBuffer->ReparseDataLength;
46 ReparseTag = ReparseBuffer->ReparseTag;
47
48 /* Validate size consistency */
50 {
52 }
53
54 /* REPARSE_DATA_BUFFER is reserved for MS tags */
56 {
58 }
59
60 /* If that a GUID data buffer, its GUID cannot be null, and it cannot contain a MS tag */
62 && IsNullGuid(&GuidBuffer->ReparseGuid)) || (ReparseTag == IO_REPARSE_TAG_MOUNT_POINT || ReparseTag == IO_REPARSE_TAG_SYMLINK)))
63 {
65 }
66
67 /* Check the data for MS non reserved tags */
68 if (!(ReparseTag & 0xFFF0000) && ReparseTag != IO_REPARSE_TAG_RESERVED_ZERO && ReparseTag != IO_REPARSE_TAG_RESERVED_ONE)
69 {
70 /* If that's a mount point, validate the MountPointReparseBuffer branch */
71 if (ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
72 {
73 /* We need information */
75 {
76 /* Substitue must be the first in row */
77 if (!ReparseBuffer->MountPointReparseBuffer.SubstituteNameOffset)
78 {
79 /* Substitude must be null-terminated */
80 if (ReparseBuffer->MountPointReparseBuffer.PrintNameOffset == ReparseBuffer->MountPointReparseBuffer.SubstituteNameLength + sizeof(UNICODE_NULL))
81 {
82 /* There must just be the Offset/Length fields + buffer + 2 null chars */
83 if (DataLength == ReparseBuffer->MountPointReparseBuffer.PrintNameLength + ReparseBuffer->MountPointReparseBuffer.SubstituteNameLength + (FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) - FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.SubstituteNameOffset)) + 2 * sizeof(UNICODE_NULL))
84 {
85 return STATUS_SUCCESS;
86 }
87 }
88 }
89 }
90 }
91 else
92 {
93#define FIELDS_SIZE (FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) - FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.SubstituteNameOffset))
94
95 /* If that's not a symlink, accept the MS tag as it */
96 if (ReparseTag != IO_REPARSE_TAG_SYMLINK)
97 {
98 return STATUS_SUCCESS;
99 }
100
101 /* We need information */
102 if (DataLength >= FIELDS_SIZE)
103 {
104 /* Validate lengths */
105 if (ReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength && ReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength)
106 {
107 /* Validate unicode strings */
108 if (IsEven(ReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength) && IsEven(ReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength) &&
109 IsEven(ReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset) && IsEven(ReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset))
110 {
111 if ((DataLength + REPARSE_DATA_BUFFER_HEADER_SIZE >= ReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset + ReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength + FIELDS_SIZE + REPARSE_DATA_BUFFER_HEADER_SIZE)
112 && (DataLength + REPARSE_DATA_BUFFER_HEADER_SIZE >= ReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength + ReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset + FIELDS_SIZE + REPARSE_DATA_BUFFER_HEADER_SIZE))
113 {
114 return STATUS_SUCCESS;
115 }
116 }
117 }
118 }
119#undef FIELDS_SIZE
120 }
121
123 }
124
126}
_In_ ULONG _In_opt_ WDFREQUEST _In_opt_ PVOID _In_ size_t _In_ PVOID _In_ size_t _Out_ size_t * DataLength
Definition: cdrom.h:1444
#define IsEven(n)
Definition: render.c:183
#define FIELDS_SIZE
FORCEINLINE BOOLEAN IsNullGuid(IN PGUID Guid)
Definition: fsrtl.c:14
#define REPARSE_DATA_BUFFER_HEADER_SIZE
Definition: vista.c:17
#define UNICODE_NULL
#define STATUS_IO_REPARSE_TAG_INVALID
Definition: ntstatus.h:754
#define STATUS_IO_REPARSE_DATA_INVALID
Definition: ntstatus.h:756
WCHAR PathBuffer[1]
Definition: shellext.h:176
USHORT SubstituteNameOffset
Definition: shellext.h:171
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3771
#define IO_REPARSE_TAG_RESERVED_ONE
Definition: iotypes.h:7217
struct _REPARSE_GUID_DATA_BUFFER * PREPARSE_GUID_DATA_BUFFER
#define MAXIMUM_REPARSE_DATA_BUFFER_SIZE
Definition: iotypes.h:7213
#define REPARSE_GUID_DATA_BUFFER_HEADER_SIZE
Definition: iotypes.h:7211
#define IO_REPARSE_TAG_SYMLINK
Definition: iotypes.h:7240
#define IO_REPARSE_TAG_MOUNT_POINT
Definition: iotypes.h:7231
#define IO_REPARSE_TAG_RESERVED_ZERO
Definition: iotypes.h:7216
#define IsReparseTagMicrosoft(_tag)
Definition: iotypes.h:7220

Referenced by _Function_class_().

◆ create_fcb()

fcb * create_fcb ( device_extension Vcb,
POOL_TYPE  pool_type 
)

Definition at line 91 of file create.c.

91 {
92 fcb* fcb;
93
94 if (pool_type == NonPagedPool) {
95 fcb = ExAllocatePoolWithTag(pool_type, sizeof(struct _fcb), ALLOC_TAG);
96 if (!fcb) {
97 ERR("out of memory\n");
98 return NULL;
99 }
100 } else {
101 fcb = ExAllocateFromPagedLookasideList(&Vcb->fcb_lookaside);
102 if (!fcb) {
103 ERR("out of memory\n");
104 return NULL;
105 }
106 }
107
108#ifdef DEBUG_FCB_REFCOUNTS
109 WARN("allocating fcb %p\n", fcb);
110#endif
111 RtlZeroMemory(fcb, sizeof(struct _fcb));
112 fcb->pool_type = pool_type;
113
114 fcb->Header.NodeTypeCode = BTRFS_NODE_TYPE_FCB;
115 fcb->Header.NodeByteSize = sizeof(struct _fcb);
116
117 fcb->nonpaged = ExAllocateFromNPagedLookasideList(&Vcb->fcb_np_lookaside);
118 if (!fcb->nonpaged) {
119 ERR("out of memory\n");
120
121 if (pool_type == NonPagedPool)
123 else
124 ExFreeToPagedLookasideList(&Vcb->fcb_lookaside, fcb);
125
126 return NULL;
127 }
128 RtlZeroMemory(fcb->nonpaged, sizeof(struct _fcb_nonpaged));
129
130 ExInitializeResourceLite(&fcb->nonpaged->paging_resource);
131 fcb->Header.PagingIoResource = &fcb->nonpaged->paging_resource;
132
133 ExInitializeFastMutex(&fcb->nonpaged->HeaderMutex);
134 FsRtlSetupAdvancedHeader(&fcb->Header, &fcb->nonpaged->HeaderMutex);
135
136 fcb->refcount = 1;
137#ifdef DEBUG_FCB_REFCOUNTS
138 WARN("fcb %p: refcount now %i\n", fcb, fcb->refcount);
139#endif
140
142 fcb->Header.Resource = &fcb->nonpaged->resource;
143
144 ExInitializeResourceLite(&fcb->nonpaged->dir_children_lock);
145
148
152
156
157 return fcb;
158}
#define BTRFS_NODE_TYPE_FCB
Definition: btrfs_drv.h:85
struct _fcb fcb
Definition: btrfs_drv.h:1364
static __inline POPLOCK fcb_oplock(fcb *fcb)
Definition: btrfs_drv.h:1677
VOID NTAPI FsRtlInitializeFileLock(IN PFILE_LOCK FileLock, IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine OPTIONAL, IN PUNLOCK_ROUTINE UnlockRoutine OPTIONAL)
Definition: filelock.c:1262
VOID NTAPI FsRtlInitializeOplock(IN OUT POPLOCK Oplock)
Definition: oplock.c:1400
LIST_ENTRY xattrs
Definition: btrfs_drv.h:308
LIST_ENTRY hardlinks
Definition: btrfs_drv.h:304
FILE_LOCK lock
Definition: btrfs_drv.h:294
POOL_TYPE pool_type
Definition: btrfs_drv.h:286
LIST_ENTRY extents
Definition: btrfs_drv.h:300
LIST_ENTRY dir_children_hash
Definition: btrfs_drv.h:315
LIST_ENTRY dir_children_hash_uc
Definition: btrfs_drv.h:316
LONG refcount
Definition: btrfs_drv.h:285
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:283
FORCEINLINE VOID ExInitializeFastMutex(_Out_ PFAST_MUTEX FastMutex)
Definition: exfuncs.h:274

Referenced by allocate_cache_chunk(), create_directory_fcb(), create_stream(), create_subvol(), duplicate_fcb(), file_create2(), mknod(), mount_vol(), open_fcb(), open_fcb_stream(), rename_stream(), and rename_stream_to_file().

◆ create_fileref()

file_ref * create_fileref ( device_extension Vcb)

Definition at line 160 of file create.c.

160 {
161 file_ref* fr;
162
163 fr = ExAllocateFromPagedLookasideList(&Vcb->fileref_lookaside);
164 if (!fr) {
165 ERR("out of memory\n");
166 return NULL;
167 }
168
169 RtlZeroMemory(fr, sizeof(file_ref));
170
171 fr->refcount = 1;
172
173#ifdef DEBUG_FCB_REFCOUNTS
174 WARN("fileref %p: refcount now 1\n", fr);
175#endif
176
178
179 return fr;
180}
LONG refcount
Definition: btrfs_drv.h:350
LIST_ENTRY children
Definition: btrfs_drv.h:349

Referenced by create_stream(), create_subvol(), do_create_snapshot(), file_create2(), mknod(), mount_vol(), move_across_subvols(), open_fileref_child(), rename_file_to_stream(), set_link_information(), and set_rename_information().

◆ create_root()

NTSTATUS create_root ( _In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension Vcb,
_In_ uint64_t  id,
_Out_ root **  rootptr,
_In_ bool  no_tree,
_In_ uint64_t  offset,
_In_opt_ PIRP  Irp 
)

Definition at line 1271 of file btrfs.c.

1272 {
1274 root* r;
1275 ROOT_ITEM* ri;
1277
1279 if (!r) {
1280 ERR("out of memory\n");
1282 }
1283
1285 if (!r->nonpaged) {
1286 ERR("out of memory\n");
1287 ExFreePool(r);
1289 }
1290
1292 if (!ri) {
1293 ERR("out of memory\n");
1294
1295 ExFreePool(r->nonpaged);
1296 ExFreePool(r);
1298 }
1299
1300 r->id = id;
1301 r->treeholder.address = 0;
1302 r->treeholder.generation = Vcb->superblock.generation;
1303 r->treeholder.tree = NULL;
1304 r->lastinode = 0;
1305 r->dirty = false;
1306 r->received = false;
1307 r->reserved = NULL;
1308 r->parent = 0;
1309 r->send_ops = 0;
1310 RtlZeroMemory(&r->root_item, sizeof(ROOT_ITEM));
1311 r->root_item.num_references = 1;
1312 r->fcbs_version = 0;
1313 r->checked_for_orphans = true;
1314 r->dropped = false;
1315 InitializeListHead(&r->fcbs);
1316 RtlZeroMemory(r->fcbs_ptrs, sizeof(LIST_ENTRY*) * 256);
1317
1318 RtlCopyMemory(ri, &r->root_item, sizeof(ROOT_ITEM));
1319
1320 // We ask here for a traverse_ptr to the item we're inserting, so we can
1321 // copy some of the tree's variables
1322
1323 Status = insert_tree_item(Vcb, Vcb->root_root, id, TYPE_ROOT_ITEM, offset, ri, sizeof(ROOT_ITEM), &tp, Irp);
1324 if (!NT_SUCCESS(Status)) {
1325 ERR("insert_tree_item returned %08lx\n", Status);
1326 ExFreePool(ri);
1327 ExFreePool(r->nonpaged);
1328 ExFreePool(r);
1329 return Status;
1330 }
1331
1332 ExInitializeResourceLite(&r->nonpaged->load_tree_lock);
1333
1334 InsertTailList(&Vcb->roots, &r->list_entry);
1335
1336 if (!no_tree) {
1338 if (!t) {
1339 ERR("out of memory\n");
1340
1342
1343 ExFreePool(r->nonpaged);
1344 ExFreePool(r);
1345 ExFreePool(ri);
1347 }
1348
1349 t->nonpaged = NULL;
1350
1351 t->is_unique = true;
1352 t->uniqueness_determined = true;
1353 t->buf = NULL;
1354
1355 r->treeholder.tree = t;
1356
1357 RtlZeroMemory(&t->header, sizeof(tree_header));
1358 t->header.fs_uuid = tp.tree->header.fs_uuid;
1359 t->header.address = 0;
1360 t->header.flags = HEADER_FLAG_MIXED_BACKREF | 1; // 1 == "written"? Why does the Linux driver record this?
1361 t->header.chunk_tree_uuid = tp.tree->header.chunk_tree_uuid;
1362 t->header.generation = Vcb->superblock.generation;
1363 t->header.tree_id = id;
1364 t->header.num_items = 0;
1365 t->header.level = 0;
1366
1367 t->has_address = false;
1368 t->size = 0;
1369 t->Vcb = Vcb;
1370 t->parent = NULL;
1371 t->paritem = NULL;
1372 t->root = r;
1373
1374 InitializeListHead(&t->itemlist);
1375
1376 t->new_address = 0;
1377 t->has_new_address = false;
1378 t->updated_extents = false;
1379
1380 InsertTailList(&Vcb->trees, &t->list_entry);
1381 t->list_entry_hash.Flink = NULL;
1382
1383 t->write = true;
1384 Vcb->need_write = true;
1385 }
1386
1387 *rootptr = r;
1388
1389 return STATUS_SUCCESS;
1390}
InitializeListHead & r
Definition: btrfs.c:3015
_In_ uint64_t id
Definition: btrfs.c:2995
#define HEADER_FLAG_MIXED_BACKREF
Definition: btrfs.h:151
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLdouble GLdouble t
Definition: gl.h:2047
tree_header header
Definition: btrfs_drv.h:426
tree * tree
Definition: btrfs_drv.h:508
BTRFS_UUID chunk_tree_uuid
Definition: btrfs.h:158

Referenced by create_subvol(), do_create_snapshot(), flush_subvol(), and look_for_roots().

◆ decrease_extent_refcount()

NTSTATUS decrease_extent_refcount ( device_extension Vcb,
uint64_t  address,
uint64_t  size,
uint8_t  type,
void data,
KEY firstitem,
uint8_t  level,
uint64_t  parent,
bool  superseded,
PIRP  Irp 
)

Definition at line 903 of file extent-tree.c.

904 {
905 KEY searchkey;
907 traverse_ptr tp, tp2;
908 EXTENT_ITEM* ei;
909 ULONG len;
910 uint64_t inline_rc;
911 uint8_t* ptr;
914 bool is_tree = (type == TYPE_TREE_BLOCK_REF || type == TYPE_SHARED_BLOCK_REF), skinny = false;
915
916 if (is_tree && Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA) {
917 searchkey.obj_id = address;
918 searchkey.obj_type = TYPE_METADATA_ITEM;
919 searchkey.offset = 0xffffffffffffffff;
920
921 Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, Irp);
922 if (!NT_SUCCESS(Status)) {
923 ERR("error - find_item returned %08lx\n", Status);
924 return Status;
925 }
926
927 if (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == searchkey.obj_type)
928 skinny = true;
929 }
930
931 if (!skinny) {
932 searchkey.obj_id = address;
933 searchkey.obj_type = TYPE_EXTENT_ITEM;
934 searchkey.offset = 0xffffffffffffffff;
935
936 Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, Irp);
937 if (!NT_SUCCESS(Status)) {
938 ERR("error - find_item returned %08lx\n", Status);
939 return Status;
940 }
941
942 if (tp.item->key.obj_id != searchkey.obj_id || tp.item->key.obj_type != searchkey.obj_type) {
943 ERR("could not find EXTENT_ITEM for address %I64x\n", address);
945 }
946
947 if (tp.item->key.offset != size) {
948 ERR("extent %I64x had length %I64x, not %I64x as expected\n", address, tp.item->key.offset, size);
950 }
951
952 if (tp.item->size == sizeof(EXTENT_ITEM_V0)) {
953 Status = convert_old_extent(Vcb, address, is_tree, firstitem, level, Irp);
954
955 if (!NT_SUCCESS(Status)) {
956 ERR("convert_old_extent returned %08lx\n", Status);
957 return Status;
958 }
959
961 }
962 }
963
964 if (tp.item->size < sizeof(EXTENT_ITEM)) {
965 ERR("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(EXTENT_ITEM));
967 }
968
969 ei = (EXTENT_ITEM*)tp.item->data;
970
971 len = tp.item->size - sizeof(EXTENT_ITEM);
972 ptr = (uint8_t*)&ei[1];
973
974 if (ei->flags & EXTENT_ITEM_TREE_BLOCK && !skinny) {
975 if (tp.item->size < sizeof(EXTENT_ITEM) + sizeof(EXTENT_ITEM2)) {
976 ERR("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(EXTENT_ITEM) + sizeof(EXTENT_ITEM2));
978 }
979
980 len -= sizeof(EXTENT_ITEM2);
981 ptr += sizeof(EXTENT_ITEM2);
982 }
983
984 if (ei->refcount < rc) {
985 ERR("error - extent has refcount %I64x, trying to reduce by %x\n", ei->refcount, rc);
987 }
988
989 inline_rc = 0;
990
991 // Loop through inline extent entries
992
993 while (len > 0) {
994 uint8_t secttype = *ptr;
995 uint16_t sectlen = get_extent_data_len(secttype);
996 uint64_t sectcount = get_extent_data_refcount(secttype, ptr + sizeof(uint8_t));
997
998 len--;
999
1000 if (sectlen > len) {
1001 ERR("(%I64x,%x,%I64x): %lx bytes left, expecting at least %x\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, len, sectlen);
1002 return STATUS_INTERNAL_ERROR;
1003 }
1004
1005 if (sectlen == 0) {
1006 ERR("(%I64x,%x,%I64x): unrecognized extent type %x\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, secttype);
1007 return STATUS_INTERNAL_ERROR;
1008 }
1009
1010 if (secttype == type) {
1011 if (type == TYPE_EXTENT_DATA_REF) {
1012 EXTENT_DATA_REF* sectedr = (EXTENT_DATA_REF*)(ptr + sizeof(uint8_t));
1014
1015 if (sectedr->root == edr->root && sectedr->objid == edr->objid && sectedr->offset == edr->offset) {
1016 uint16_t neweilen;
1017 EXTENT_ITEM* newei;
1018
1019 if (ei->refcount == edr->count) {
1021 if (!NT_SUCCESS(Status)) {
1022 ERR("delete_tree_item returned %08lx\n", Status);
1023 return Status;
1024 }
1025
1026 if (!superseded)
1027 add_checksum_entry(Vcb, address, (ULONG)(size >> Vcb->sector_shift), NULL, Irp);
1028
1029 return STATUS_SUCCESS;
1030 }
1031
1032 if (sectedr->count < edr->count) {
1033 ERR("error - extent section has refcount %x, trying to reduce by %x\n", sectedr->count, edr->count);
1034 return STATUS_INTERNAL_ERROR;
1035 }
1036
1037 if (sectedr->count > edr->count) // reduce section refcount
1038 neweilen = tp.item->size;
1039 else // remove section entirely
1040 neweilen = tp.item->size - sizeof(uint8_t) - sectlen;
1041
1042 newei = ExAllocatePoolWithTag(PagedPool, neweilen, ALLOC_TAG);
1043 if (!newei) {
1044 ERR("out of memory\n");
1046 }
1047
1048 if (sectedr->count > edr->count) {
1049 EXTENT_DATA_REF* newedr = (EXTENT_DATA_REF*)((uint8_t*)newei + ((uint8_t*)sectedr - tp.item->data));
1050
1051 RtlCopyMemory(newei, ei, neweilen);
1052
1053 newedr->count -= rc;
1054 } else {
1055 RtlCopyMemory(newei, ei, ptr - tp.item->data);
1056
1057 if (len > sectlen)
1058 RtlCopyMemory((uint8_t*)newei + (ptr - tp.item->data), ptr + sectlen + sizeof(uint8_t), len - sectlen);
1059 }
1060
1061 newei->refcount -= rc;
1062
1064 if (!NT_SUCCESS(Status)) {
1065 ERR("delete_tree_item returned %08lx\n", Status);
1066 return Status;
1067 }
1068
1069 Status = insert_tree_item(Vcb, Vcb->extent_root, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, newei, neweilen, NULL, Irp);
1070 if (!NT_SUCCESS(Status)) {
1071 ERR("insert_tree_item returned %08lx\n", Status);
1072 return Status;
1073 }
1074
1075 return STATUS_SUCCESS;
1076 }
1077 } else if (type == TYPE_SHARED_DATA_REF) {
1078 SHARED_DATA_REF* sectsdr = (SHARED_DATA_REF*)(ptr + sizeof(uint8_t));
1080
1081 if (sectsdr->offset == sdr->offset) {
1082 EXTENT_ITEM* newei;
1083 uint16_t neweilen;
1084
1085 if (ei->refcount == sectsdr->count) {
1087 if (!NT_SUCCESS(Status)) {
1088 ERR("delete_tree_item returned %08lx\n", Status);
1089 return Status;
1090 }
1091
1092 if (!superseded)
1093 add_checksum_entry(Vcb, address, (ULONG)(size >> Vcb->sector_shift), NULL, Irp);
1094
1095 return STATUS_SUCCESS;
1096 }
1097
1098 if (sectsdr->count < sdr->count) {
1099 ERR("error - SHARED_DATA_REF has refcount %x, trying to reduce by %x\n", sectsdr->count, sdr->count);
1100 return STATUS_INTERNAL_ERROR;
1101 }
1102
1103 if (sectsdr->count > sdr->count) // reduce section refcount
1104 neweilen = tp.item->size;
1105 else // remove section entirely
1106 neweilen = tp.item->size - sizeof(uint8_t) - sectlen;
1107
1108 newei = ExAllocatePoolWithTag(PagedPool, neweilen, ALLOC_TAG);
1109 if (!newei) {
1110 ERR("out of memory\n");
1112 }
1113
1114 if (sectsdr->count > sdr->count) {
1115 SHARED_DATA_REF* newsdr = (SHARED_DATA_REF*)((uint8_t*)newei + ((uint8_t*)sectsdr - tp.item->data));
1116
1117 RtlCopyMemory(newei, ei, neweilen);
1118
1119 newsdr->count -= rc;
1120 } else {
1121 RtlCopyMemory(newei, ei, ptr - tp.item->data);
1122
1123 if (len > sectlen)
1124 RtlCopyMemory((uint8_t*)newei + (ptr - tp.item->data), ptr + sectlen + sizeof(uint8_t), len - sectlen);
1125 }
1126
1127 newei->refcount -= rc;
1128
1130 if (!NT_SUCCESS(Status)) {
1131 ERR("delete_tree_item returned %08lx\n", Status);
1132 return Status;
1133 }
1134
1135 Status = insert_tree_item(Vcb, Vcb->extent_root, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, newei, neweilen, NULL, Irp);
1136 if (!NT_SUCCESS(Status)) {
1137 ERR("insert_tree_item returned %08lx\n", Status);
1138 return Status;
1139 }
1140
1141 return STATUS_SUCCESS;
1142 }
1143 } else if (type == TYPE_TREE_BLOCK_REF) {
1144 TREE_BLOCK_REF* secttbr = (TREE_BLOCK_REF*)(ptr + sizeof(uint8_t));
1146
1147 if (secttbr->offset == tbr->offset) {
1148 EXTENT_ITEM* newei;
1149 uint16_t neweilen;
1150
1151 if (ei->refcount == 1) {
1153 if (!NT_SUCCESS(Status)) {
1154 ERR("delete_tree_item returned %08lx\n", Status);
1155 return Status;
1156 }
1157
1158 return STATUS_SUCCESS;
1159 }
1160
1161 neweilen = tp.item->size - sizeof(uint8_t) - sectlen;
1162
1163 newei = ExAllocatePoolWithTag(PagedPool, neweilen, ALLOC_TAG);
1164 if (!newei) {
1165 ERR("out of memory\n");
1167 }
1168
1169 RtlCopyMemory(newei, ei, ptr - tp.item->data);
1170
1171 if (len > sectlen)
1172 RtlCopyMemory((uint8_t*)newei + (ptr - tp.item->data), ptr + sectlen + sizeof(uint8_t), len - sectlen);
1173
1174 newei->refcount--;
1175
1177 if (!NT_SUCCESS(Status)) {
1178 ERR("delete_tree_item returned %08lx\n", Status);
1179 return Status;
1180 }
1181
1182 Status = insert_tree_item(Vcb, Vcb->extent_root, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, newei, neweilen, NULL, Irp);
1183 if (!NT_SUCCESS(Status)) {
1184 ERR("insert_tree_item returned %08lx\n", Status);
1185 return Status;
1186 }
1187
1188 return STATUS_SUCCESS;
1189 }
1190 } else if (type == TYPE_SHARED_BLOCK_REF) {
1191 SHARED_BLOCK_REF* sectsbr = (SHARED_BLOCK_REF*)(ptr + sizeof(uint8_t));
1193
1194 if (sectsbr->offset == sbr->offset) {
1195 EXTENT_ITEM* newei;
1196 uint16_t neweilen;
1197
1198 if (ei->refcount == 1) {
1200 if (!NT_SUCCESS(Status)) {
1201 ERR("delete_tree_item returned %08lx\n", Status);
1202 return Status;
1203 }
1204
1205 return STATUS_SUCCESS;
1206 }
1207
1208 neweilen = tp.item->size - sizeof(uint8_t) - sectlen;
1209
1210 newei = ExAllocatePoolWithTag(PagedPool, neweilen, ALLOC_TAG);
1211 if (!newei) {
1212 ERR("out of memory\n");
1214 }
1215
1216 RtlCopyMemory(newei, ei, ptr - tp.item->data);
1217
1218 if (len > sectlen)
1219 RtlCopyMemory((uint8_t*)newei + (ptr - tp.item->data), ptr + sectlen + sizeof(uint8_t), len - sectlen);
1220
1221 newei->refcount--;
1222
1224 if (!NT_SUCCESS(Status)) {
1225 ERR("delete_tree_item returned %08lx\n", Status);
1226 return Status;
1227 }
1228
1229 Status = insert_tree_item(Vcb, Vcb->extent_root, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, newei, neweilen, NULL, Irp);
1230 if (!NT_SUCCESS(Status)) {
1231 ERR("insert_tree_item returned %08lx\n", Status);
1232 return Status;
1233 }
1234
1235 return STATUS_SUCCESS;
1236 }
1237 } else {
1238 ERR("unhandled extent type %x\n", type);
1239 return STATUS_INTERNAL_ERROR;
1240 }
1241 }
1242
1243 len -= sectlen;
1244 ptr += sizeof(uint8_t) + sectlen;
1245 inline_rc += sectcount;
1246 }
1247
1248 if (inline_rc == ei->refcount) {
1249 ERR("entry not found in inline extent item for address %I64x\n", address);
1250 return STATUS_INTERNAL_ERROR;
1251 }
1252
1254 datalen = sizeof(uint32_t);
1256 datalen = 0;
1257
1258 searchkey.obj_id = address;
1259 searchkey.obj_type = type;
1261
1262 Status = find_item(Vcb, Vcb->extent_root, &tp2, &searchkey, false, Irp);
1263 if (!NT_SUCCESS(Status)) {
1264 ERR("error - find_item returned %08lx\n", Status);
1265 return Status;
1266 }
1267
1268 if (keycmp(tp2.item->key, searchkey)) {
1269 ERR("(%I64x,%x,%I64x) not found\n", tp2.item->key.obj_id, tp2.item->key.obj_type, tp2.item->key.offset);
1270 return STATUS_INTERNAL_ERROR;
1271 }
1272
1273 if (tp2.item->size < datalen) {
1274 ERR("(%I64x,%x,%I64x) was %u bytes, expected at least %lu\n", tp2.item->key.obj_id, tp2.item->key.obj_type, tp2.item->key.offset, tp2.item->size, datalen);
1275 return STATUS_INTERNAL_ERROR;
1276 }
1277
1278 if (type == TYPE_EXTENT_DATA_REF) {
1279 EXTENT_DATA_REF* sectedr = (EXTENT_DATA_REF*)tp2.item->data;
1281
1282 if (sectedr->root == edr->root && sectedr->objid == edr->objid && sectedr->offset == edr->offset) {
1283 EXTENT_ITEM* newei;
1284
1285 if (ei->refcount == edr->count) {
1287 if (!NT_SUCCESS(Status)) {
1288 ERR("delete_tree_item returned %08lx\n", Status);
1289 return Status;
1290 }
1291
1292 Status = delete_tree_item(Vcb, &tp2);
1293 if (!NT_SUCCESS(Status)) {
1294 ERR("delete_tree_item returned %08lx\n", Status);
1295 return Status;
1296 }
1297
1298 if (!superseded)
1299 add_checksum_entry(Vcb, address, (ULONG)(size >> Vcb->sector_shift), NULL, Irp);
1300
1301 return STATUS_SUCCESS;
1302 }
1303
1304 if (sectedr->count < edr->count) {
1305 ERR("error - extent section has refcount %x, trying to reduce by %x\n", sectedr->count, edr->count);
1306 return STATUS_INTERNAL_ERROR;
1307 }
1308
1309 Status = delete_tree_item(Vcb, &tp2);
1310 if (!NT_SUCCESS(Status)) {
1311 ERR("delete_tree_item returned %08lx\n", Status);
1312 return Status;
1313 }
1314
1315 if (sectedr->count > edr->count) {
1317
1318 if (!newedr) {
1319 ERR("out of memory\n");
1321 }
1322
1323 RtlCopyMemory(newedr, sectedr, tp2.item->size);
1324
1325 newedr->count -= edr->count;
1326
1327 Status = insert_tree_item(Vcb, Vcb->extent_root, tp2.item->key.obj_id, tp2.item->key.obj_type, tp2.item->key.offset, newedr, tp2.item->size, NULL, Irp);
1328 if (!NT_SUCCESS(Status)) {
1329 ERR("insert_tree_item returned %08lx\n", Status);
1330 return Status;
1331 }
1332 }
1333
1335 if (!newei) {
1336 ERR("out of memory\n");
1338 }
1339
1340 RtlCopyMemory(newei, tp.item->data, tp.item->size);
1341
1342 newei->refcount -= rc;
1343
1345 if (!NT_SUCCESS(Status)) {
1346 ERR("delete_tree_item returned %08lx\n", Status);
1347 return Status;
1348 }
1349
1351 if (!NT_SUCCESS(Status)) {
1352 ERR("insert_tree_item returned %08lx\n", Status);
1353 return Status;
1354 }
1355
1356 return STATUS_SUCCESS;
1357 } else {
1358 ERR("error - hash collision?\n");
1359 return STATUS_INTERNAL_ERROR;
1360 }
1361 } else if (type == TYPE_SHARED_DATA_REF) {
1363
1364 if (tp2.item->key.offset == sdr->offset) {
1365 uint32_t* sectsdrcount = (uint32_t*)tp2.item->data;
1366 EXTENT_ITEM* newei;
1367
1368 if (ei->refcount == sdr->count) {
1370 if (!NT_SUCCESS(Status)) {
1371 ERR("delete_tree_item returned %08lx\n", Status);
1372 return Status;
1373 }
1374
1375 Status = delete_tree_item(Vcb, &tp2);
1376 if (!NT_SUCCESS(Status)) {
1377 ERR("delete_tree_item returned %08lx\n", Status);
1378 return Status;
1379 }
1380
1381 if (!superseded)
1382 add_checksum_entry(Vcb, address, (ULONG)(size >> Vcb->sector_shift), NULL, Irp);
1383
1384 return STATUS_SUCCESS;
1385 }
1386
1387 if (*sectsdrcount < sdr->count) {
1388 ERR("error - extent section has refcount %x, trying to reduce by %x\n", *sectsdrcount, sdr->count);
1389 return STATUS_INTERNAL_ERROR;
1390 }
1391
1392 Status = delete_tree_item(Vcb, &tp2);
1393 if (!NT_SUCCESS(Status)) {
1394 ERR("delete_tree_item returned %08lx\n", Status);
1395 return Status;
1396 }
1397
1398 if (*sectsdrcount > sdr->count) {
1400
1401 if (!newsdr) {
1402 ERR("out of memory\n");
1404 }
1405
1406 *newsdr = *sectsdrcount - sdr->count;
1407
1408 Status = insert_tree_item(Vcb, Vcb->extent_root, tp2.item->key.obj_id, tp2.item->key.obj_type, tp2.item->key.offset, newsdr, tp2.item->size, NULL, Irp);
1409 if (!NT_SUCCESS(Status)) {
1410 ERR("insert_tree_item returned %08lx\n", Status);
1411 return Status;
1412 }
1413 }
1414
1416 if (!newei) {
1417 ERR("out of memory\n");
1419 }
1420
1421 RtlCopyMemory(newei, tp.item->data, tp.item->size);
1422
1423 newei->refcount -= rc;
1424
1426 if (!NT_SUCCESS(Status)) {
1427 ERR("delete_tree_item returned %08lx\n", Status);
1428 return Status;
1429 }
1430
1432 if (!NT_SUCCESS(Status)) {
1433 ERR("insert_tree_item returned %08lx\n", Status);
1434 return Status;
1435 }
1436
1437 return STATUS_SUCCESS;
1438 } else {
1439 ERR("error - collision?\n");
1440 return STATUS_INTERNAL_ERROR;
1441 }
1442 } else if (type == TYPE_TREE_BLOCK_REF || type == TYPE_SHARED_BLOCK_REF) {
1443 EXTENT_ITEM* newei;
1444
1445 if (ei->refcount == 1) {
1447 if (!NT_SUCCESS(Status)) {
1448 ERR("delete_tree_item returned %08lx\n", Status);
1449 return Status;
1450 }
1451
1452 Status = delete_tree_item(Vcb, &tp2);
1453 if (!NT_SUCCESS(Status)) {
1454 ERR("delete_tree_item returned %08lx\n", Status);
1455 return Status;
1456 }
1457
1458 return STATUS_SUCCESS;
1459 }
1460
1461 Status = delete_tree_item(Vcb, &tp2);
1462 if (!NT_SUCCESS(Status)) {
1463 ERR("delete_tree_item returned %08lx\n", Status);
1464 return Status;
1465 }
1466
1468 if (!newei) {
1469 ERR("out of memory\n");
1471 }
1472
1473 RtlCopyMemory(newei, tp.item->data, tp.item->size);
1474
1475 newei->refcount -= rc;
1476
1478 if (!NT_SUCCESS(Status)) {
1479 ERR("delete_tree_item returned %08lx\n", Status);
1480 return Status;
1481 }
1482
1484 if (!NT_SUCCESS(Status)) {
1485 ERR("insert_tree_item returned %08lx\n", Status);
1486 return Status;
1487 }
1488
1489 return STATUS_SUCCESS;
1490 } else if (type == TYPE_EXTENT_REF_V0) {
1491 EXTENT_REF_V0* erv0 = (EXTENT_REF_V0*)tp2.item->data;
1492 EXTENT_ITEM* newei;
1493
1494 if (ei->refcount == erv0->count) {
1496 if (!NT_SUCCESS(Status)) {
1497 ERR("delete_tree_item returned %08lx\n", Status);
1498 return Status;
1499 }
1500
1501 Status = delete_tree_item(Vcb, &tp2);
1502 if (!NT_SUCCESS(Status)) {
1503 ERR("delete_tree_item returned %08lx\n", Status);
1504 return Status;
1505 }
1506
1507 if (!superseded)
1508 add_checksum_entry(Vcb, address, (ULONG)(size >> Vcb->sector_shift), NULL, Irp);
1509
1510 return STATUS_SUCCESS;
1511 }
1512
1513 Status = delete_tree_item(Vcb, &tp2);
1514 if (!NT_SUCCESS(Status)) {
1515 ERR("delete_tree_item returned %08lx\n", Status);
1516 return Status;
1517 }
1518
1520 if (!newei) {
1521 ERR("out of memory\n");
1523 }
1524
1525 RtlCopyMemory(newei, tp.item->data, tp.item->size);
1526
1527 newei->refcount -= rc;
1528
1530 if (!NT_SUCCESS(Status)) {
1531 ERR("delete_tree_item returned %08lx\n", Status);
1532 return Status;
1533 }
1534
1536 if (!NT_SUCCESS(Status)) {
1537 ERR("insert_tree_item returned %08lx\n", Status);
1538 return Status;
1539 }
1540
1541 return STATUS_SUCCESS;
1542 } else {
1543 ERR("unhandled extent type %x\n", type);
1544 return STATUS_INTERNAL_ERROR;
1545 }
1546}
static __inline uint32_t get_extent_data_refcount(uint8_t type, void *data)
Definition: btrfs_drv.h:1065
#define keycmp(key1, key2)
Definition: btrfs_drv.h:1016
static __inline uint16_t get_extent_data_len(uint8_t type)
Definition: btrfs_drv.h:1043
void add_checksum_entry(device_extension *Vcb, uint64_t address, ULONG length, void *csum, PIRP Irp)
Definition: flushthread.c:2602
static WCHAR superseded[MAX_STRING_RESOURCE_LEN]
Definition: object.c:1817
r parent
Definition: btrfs.c:3010
#define BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA
Definition: btrfs.h:123
#define TYPE_SHARED_BLOCK_REF
Definition: btrfs.h:40
#define TYPE_EXTENT_ITEM
Definition: btrfs.h:35
#define EXTENT_ITEM_TREE_BLOCK
Definition: btrfs.h:388
#define TYPE_SHARED_DATA_REF
Definition: btrfs.h:41
#define TYPE_TREE_BLOCK_REF
Definition: btrfs.h:37
#define TYPE_METADATA_ITEM
Definition: btrfs.h:36
#define TYPE_EXTENT_REF_V0
Definition: btrfs.h:39
static NTSTATUS convert_old_extent(device_extension *Vcb, uint64_t address, bool tree, KEY *firstitem, uint8_t level, PIRP Irp)
Definition: extent-tree.c:372
NTSTATUS decrease_extent_refcount(device_extension *Vcb, uint64_t address, uint64_t size, uint8_t type, void *data, KEY *firstitem, uint8_t level, uint64_t parent, bool superseded, PIRP Irp)
Definition: extent-tree.c:903
static uint64_t get_extent_hash(uint8_t type, void *data)
Definition: extent-tree.c:49
GLint level
Definition: gl.h:1546
int const JOCTET unsigned int datalen
Definition: jpeglib.h:1031
static PVOID ptr
Definition: dispmode.c:27
uint64_t flags
Definition: btrfs.h:394
uint64_t refcount
Definition: btrfs.h:392
uint32_t count
Definition: btrfs.h:433
uint64_t offset
Definition: btrfs.h:437
uint32_t count
Definition: btrfs.h:442
uint64_t offset
Definition: btrfs.h:441
uint64_t offset
Definition: btrfs.h:413

Referenced by add_metadata_reloc_extent_item(), decrease_extent_refcount(), decrease_extent_refcount_data(), decrease_extent_refcount_tree(), and update_tree_extents().

◆ decrease_extent_refcount_data()

NTSTATUS decrease_extent_refcount_data ( device_extension Vcb,
uint64_t  address,
uint64_t  size,
uint64_t  root,
uint64_t  inode,
uint64_t  offset,
uint32_t  refcount,
bool  superseded,
PIRP  Irp 
)

Definition at line 1548 of file extent-tree.c.

1549 {
1550 EXTENT_DATA_REF edr;
1551
1552 edr.root = root;
1553 edr.objid = inode;
1554 edr.offset = offset;
1555 edr.count = refcount;
1556
1558}

Referenced by flush_changed_extent().

◆ decrease_extent_refcount_tree()

NTSTATUS decrease_extent_refcount_tree ( device_extension Vcb,
uint64_t  address,
uint64_t  size,
uint64_t  root,
uint8_t  level,
PIRP  Irp 
)

Definition at line 1560 of file extent-tree.c.

1561 {
1562 TREE_BLOCK_REF tbr;
1563
1564 tbr.offset = root;
1565
1566 return decrease_extent_refcount(Vcb, address, size, TYPE_TREE_BLOCK_REF, &tbr, NULL/*FIXME*/, level, 0, false, Irp);
1567}

Referenced by reduce_tree_extent().

◆ delete_fileref()

NTSTATUS delete_fileref ( _In_ file_ref fileref,
_In_opt_ PFILE_OBJECT  FileObject,
_In_ bool  make_orphan,
_In_opt_ PIRP  Irp,
_In_ LIST_ENTRY rollback 
)

Definition at line 2270 of file btrfs.c.

2270 {
2271 LARGE_INTEGER newlength, time;
2274 ULONG utf8len = 0;
2275
2278
2279 ExAcquireResourceExclusiveLite(fileref->fcb->Header.Resource, true);
2280
2281 if (fileref->deleted) {
2282 ExReleaseResourceLite(fileref->fcb->Header.Resource);
2283 return STATUS_SUCCESS;
2284 }
2285
2286 if (fileref->fcb->subvol->send_ops > 0) {
2287 ExReleaseResourceLite(fileref->fcb->Header.Resource);
2288 return STATUS_ACCESS_DENIED;
2289 }
2290
2291 fileref->deleted = true;
2292 mark_fileref_dirty(fileref);
2293
2294 // delete INODE_ITEM (0x1)
2295
2296 TRACE("nlink = %u\n", fileref->fcb->inode_item.st_nlink);
2297
2298 if (!fileref->fcb->ads) {
2299 if (fileref->parent->fcb->subvol == fileref->fcb->subvol) {
2300 LIST_ENTRY* le;
2301
2302 mark_fcb_dirty(fileref->fcb);
2303
2304 fileref->fcb->inode_item_changed = true;
2305
2306 if (fileref->fcb->inode_item.st_nlink > 1 || make_orphan) {
2307 fileref->fcb->inode_item.st_nlink--;
2308 fileref->fcb->inode_item.transid = fileref->fcb->Vcb->superblock.generation;
2309 fileref->fcb->inode_item.sequence++;
2310 fileref->fcb->inode_item.st_ctime = now;
2311 } else {
2313 if (!NT_SUCCESS(Status)) {
2314 ERR("delete_fileref_fcb returned %08lx\n", Status);
2315 ExReleaseResourceLite(fileref->fcb->Header.Resource);
2316 return Status;
2317 }
2318 }
2319
2320 if (fileref->dc) {
2321 le = fileref->fcb->hardlinks.Flink;
2322 while (le != &fileref->fcb->hardlinks) {
2324
2325 if (hl->parent == fileref->parent->fcb->inode && hl->index == fileref->dc->index) {
2327
2328 if (hl->name.Buffer)
2329 ExFreePool(hl->name.Buffer);
2330
2331 if (hl->utf8.Buffer)
2332 ExFreePool(hl->utf8.Buffer);
2333
2334 ExFreePool(hl);
2335 break;
2336 }
2337
2338 le = le->Flink;
2339 }
2340 }
2341 } else if (fileref->fcb->subvol->parent == fileref->parent->fcb->subvol->id) { // valid subvolume
2342 if (fileref->fcb->subvol->root_item.num_references > 1) {
2343 fileref->fcb->subvol->root_item.num_references--;
2344
2345 mark_fcb_dirty(fileref->fcb); // so ROOT_ITEM gets updated
2346 } else {
2347 LIST_ENTRY* le;
2348
2349 // FIXME - we need a lock here
2350
2351 RemoveEntryList(&fileref->fcb->subvol->list_entry);
2352
2353 InsertTailList(&fileref->fcb->Vcb->drop_roots, &fileref->fcb->subvol->list_entry);
2354
2355 le = fileref->children.Flink;
2356 while (le != &fileref->children) {
2358
2359 if (fr2->fcb->ads) {
2360 fr2->fcb->deleted = true;
2361 mark_fcb_dirty(fr2->fcb);
2362 }
2363
2364 le = le->Flink;
2365 }
2366 }
2367 }
2368 } else {
2369 fileref->fcb->deleted = true;
2370 mark_fcb_dirty(fileref->fcb);
2371 }
2372
2373 // remove dir_child from parent
2374
2375 if (fileref->dc) {
2376 TRACE("delete file %.*S\n", (int)(fileref->dc->name.Length / sizeof(WCHAR)), fileref->dc->name.Buffer);
2377
2378 ExAcquireResourceExclusiveLite(&fileref->parent->fcb->nonpaged->dir_children_lock, true);
2379 RemoveEntryList(&fileref->dc->list_entry_index);
2380
2381 if (!fileref->fcb->ads)
2382 remove_dir_child_from_hash_lists(fileref->parent->fcb, fileref->dc);
2383
2384 ExReleaseResourceLite(&fileref->parent->fcb->nonpaged->dir_children_lock);
2385
2386 if (!fileref->oldutf8.Buffer)
2387 fileref->oldutf8 = fileref->dc->utf8;
2388 else
2389 ExFreePool(fileref->dc->utf8.Buffer);
2390
2391 utf8len = fileref->dc->utf8.Length;
2392
2393 fileref->oldindex = fileref->dc->index;
2394
2395 ExFreePool(fileref->dc->name.Buffer);
2396 ExFreePool(fileref->dc->name_uc.Buffer);
2397 ExFreePool(fileref->dc);
2398
2399 fileref->dc = NULL;
2400 }
2401
2402 // update INODE_ITEM of parent
2403
2404 ExAcquireResourceExclusiveLite(fileref->parent->fcb->Header.Resource, true);
2405
2406 fileref->parent->fcb->inode_item.transid = fileref->fcb->Vcb->superblock.generation;
2407 fileref->parent->fcb->inode_item.sequence++;
2408 fileref->parent->fcb->inode_item.st_ctime = now;
2409
2410 if (!fileref->fcb->ads) {
2411 TRACE("fileref->parent->fcb->inode_item.st_size (inode %I64x) was %I64x\n", fileref->parent->fcb->inode, fileref->parent->fcb->inode_item.st_size);
2412 fileref->parent->fcb->inode_item.st_size -= utf8len * 2;
2413 TRACE("fileref->parent->fcb->inode_item.st_size (inode %I64x) now %I64x\n", fileref->parent->fcb->inode, fileref->parent->fcb->inode_item.st_size);
2414 fileref->parent->fcb->inode_item.st_mtime = now;
2415 }
2416
2417 fileref->parent->fcb->inode_item_changed = true;
2418 ExReleaseResourceLite(fileref->parent->fcb->Header.Resource);
2419
2420 if (!fileref->fcb->ads && fileref->parent->dc)
2422
2423 mark_fcb_dirty(fileref->parent->fcb);
2424
2425 fileref->fcb->subvol->root_item.ctransid = fileref->fcb->Vcb->superblock.generation;
2426 fileref->fcb->subvol->root_item.ctime = now;
2427
2428 newlength.QuadPart = 0;
2429
2430 if (FileObject && !CcUninitializeCacheMap(FileObject, &newlength, NULL))
2431 TRACE("CcUninitializeCacheMap failed\n");
2432
2433 ExReleaseResourceLite(fileref->fcb->Header.Resource);
2434
2435 return STATUS_SUCCESS;
2436}
static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME *out)
Definition: btrfs_drv.h:989
void remove_dir_child_from_hash_lists(fcb *fcb, dir_child *dc)
Definition: fileinfo.c:744
void mark_fcb_dirty(_In_ fcb *fcb)
Definition: btrfs.c:1695
void mark_fileref_dirty(_In_ file_ref *fileref)
Definition: btrfs.c:1717
static NTSTATUS delete_fileref_fcb(_In_ file_ref *fileref, _In_opt_ PFILE_OBJECT FileObject, _In_opt_ PIRP Irp, _In_ LIST_ENTRY *rollback)
Definition: btrfs.c:2214
static void send_notification_fcb(_In_ file_ref *fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream)
Definition: btrfs.c:1557
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
time_t now
Definition: finger.c:65
BOOLEAN NTAPI CcUninitializeCacheMap(IN PFILE_OBJECT FileObject, IN OPTIONAL PLARGE_INTEGER TruncateSize, IN OPTIONAL PCACHE_UNINITIALIZE_EVENT UninitializeEvent)
Definition: fssup.c:286
__u16 time
Definition: mkdosfs.c:8
bool ads
Definition: btrfs_drv.h:330
bool deleted
Definition: btrfs_drv.h:295
fcb * fcb
Definition: btrfs_drv.h:342
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
LONGLONG QuadPart
Definition: typedefs.h:114
#define FILE_ACTION_MODIFIED
#define FILE_NOTIFY_CHANGE_LAST_WRITE

Referenced by _Dispatch_type_(), move_across_subvols(), open_file3(), rename_file_to_stream(), rename_stream(), set_link_information(), and set_rename_information().

◆ delete_reparse_point()

NTSTATUS delete_reparse_point ( PIRP  Irp)

Definition at line 482 of file reparse.c.

482 {
485 REPARSE_DATA_BUFFER* rdb = Irp->AssociatedIrp.SystemBuffer;
486 DWORD buflen = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
488 fcb* fcb;
489 ccb* ccb;
490 file_ref* fileref;
492
493 TRACE("(%p)\n", Irp);
494
496
497 if (!FileObject) {
498 ERR("FileObject was NULL\n");
500 }
501
502 fcb = FileObject->FsContext;
503
504 if (!fcb) {
505 ERR("fcb was NULL\n");
507 }
508
509 ccb = FileObject->FsContext2;
510
511 if (!ccb) {
512 ERR("ccb was NULL\n");
514 }
515
516 if (Irp->RequestorMode == UserMode && !(ccb->access & FILE_WRITE_ATTRIBUTES)) {
517 WARN("insufficient privileges\n");
519 }
520
521 fileref = ccb->fileref;
522
523 if (!fileref) {
524 ERR("fileref was NULL\n");
526 }
527
528 ExAcquireResourceSharedLite(&fcb->Vcb->tree_lock, true);
530
531 if (buflen < offsetof(REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer)) {
532 ERR("buffer was too short\n");
534 goto end;
535 }
536
537 if (rdb->ReparseDataLength > 0) {
538 WARN("rdb->ReparseDataLength was not zero\n");
540 goto end;
541 }
542
543 if (fcb->ads) {
544 WARN("tried to delete reparse point on ADS\n");
546 goto end;
547 }
548
549 if (fcb->type == BTRFS_TYPE_SYMLINK) {
552
554 WARN("reparse tag was not IO_REPARSE_TAG_SYMLINK\n");
556 goto end;
557 }
558
561
562 fileref->fcb->type = BTRFS_TYPE_FILE;
563 fileref->fcb->inode_item.st_mode &= ~__S_IFLNK;
564 fileref->fcb->inode_item.st_mode |= __S_IFREG;
565 fileref->fcb->inode_item.generation = fileref->fcb->Vcb->superblock.generation; // so we don't confuse btrfs send on Linux
566 fileref->fcb->inode_item.transid = fileref->fcb->Vcb->superblock.generation;
567 fileref->fcb->inode_item.sequence++;
568
570 fileref->fcb->inode_item.st_ctime = now;
571
573 fileref->fcb->inode_item.st_mtime = now;
574
575 fileref->fcb->atts &= ~FILE_ATTRIBUTE_REPARSE_POINT;
576
577 if (fileref->dc)
578 fileref->dc->type = fileref->fcb->type;
579
580 mark_fileref_dirty(fileref);
581
582 fileref->fcb->inode_item_changed = true;
583 mark_fcb_dirty(fileref->fcb);
584
585 fileref->fcb->subvol->root_item.ctransid = fcb->Vcb->superblock.generation;
586 fileref->fcb->subvol->root_item.ctime = now;
587 } else if (fcb->type == BTRFS_TYPE_FILE) {
590
591 // FIXME - do we need to check that the reparse tags match?
592
594 if (!NT_SUCCESS(Status)) {
595 ERR("truncate_file returned %08lx\n", Status);
596 goto end;
597 }
598
599 fcb->atts &= ~FILE_ATTRIBUTE_REPARSE_POINT;
600 fcb->atts_changed = true;
601
604
605 fcb->inode_item.transid = fcb->Vcb->superblock.generation;
607
610
613
614 fcb->inode_item_changed = true;
616
617 fcb->subvol->root_item.ctransid = fcb->Vcb->superblock.generation;
618 fcb->subvol->root_item.ctime = now;
619 } else if (fcb->type == BTRFS_TYPE_DIRECTORY) {
622
623 // FIXME - do we need to check that the reparse tags match?
624
625 fcb->atts &= ~FILE_ATTRIBUTE_REPARSE_POINT;
626 fcb->atts_changed = true;
627
628 if (fcb->reparse_xattr.Buffer) {
631 }
632
634
637
638 fcb->inode_item.transid = fcb->Vcb->superblock.generation;
640
643
646
647 fcb->inode_item_changed = true;
649
650 fcb->subvol->root_item.ctransid = fcb->Vcb->superblock.generation;
651 fcb->subvol->root_item.ctime = now;
652 } else {
653 ERR("unsupported file type %u\n", fcb->type);
655 goto end;
656 }
657
659
661
662end:
663 if (NT_SUCCESS(Status))
665 else
667
669 ExReleaseResourceLite(&fcb->Vcb->tree_lock);
670
671 return Status;
672}
#define __S_IFREG
Definition: btrfs_drv.h:1757
NTSTATUS NTSTATUS NTSTATUS truncate_file(fcb *fcb, uint64_t end, PIRP Irp, LIST_ENTRY *rollback) __attribute__((nonnull(1
struct _ccb ccb
void queue_notification_fcb(_In_ file_ref *fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream)
Definition: btrfs.c:1667
unsigned long DWORD
Definition: ntddk_ex.h:95
#define UserMode
Definition: asm.h:35
#define FILE_WRITE_ATTRIBUTES
Definition: nt_native.h:649
#define offsetof(TYPE, MEMBER)
#define BTRFS_TYPE_FILE
Definition: shellext.h:85
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:86
#define BTRFS_TYPE_SYMLINK
Definition: shellext.h:91
uint32_t st_mode
Definition: btrfs.h:295
BTRFS_TIME st_mtime
Definition: btrfs.h:303
uint64_t sequence
Definition: btrfs.h:299
BTRFS_TIME st_ctime
Definition: btrfs.h:302
uint64_t transid
Definition: btrfs.h:288
uint64_t generation
Definition: btrfs.h:287
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
USHORT ReparseDataLength
Definition: shellext.h:166
UCHAR DataBuffer[1]
Definition: shellext.h:188
bool user_set_change_time
Definition: btrfs_drv.h:390
ACCESS_MASK access
Definition: btrfs_drv.h:382
bool user_set_write_time
Definition: btrfs_drv.h:389
file_ref * fileref
Definition: btrfs_drv.h:383
ULONG atts
Definition: btrfs_drv.h:297
INODE_ITEM inode_item
Definition: btrfs_drv.h:292
uint8_t type
Definition: btrfs_drv.h:291
struct _device_extension * Vcb
Definition: btrfs_drv.h:287
ANSI_STRING reparse_xattr
Definition: btrfs_drv.h:301
bool reparse_xattr_changed
Definition: btrfs_drv.h:324
bool atts_changed
Definition: btrfs_drv.h:322
bool inode_item_changed
Definition: btrfs_drv.h:306
dir_child * dc
Definition: btrfs_drv.h:353
uint8_t type
Definition: btrfs_drv.h:253
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define FILE_NOTIFY_CHANGE_ATTRIBUTES

Referenced by fsctl_request().

◆ delete_tree_item()

◆ dev_ioctl()

NTSTATUS dev_ioctl ( _In_ PDEVICE_OBJECT  DeviceObject,
_In_ ULONG  ControlCode,
_In_reads_bytes_opt_(InputBufferSize) PVOID  InputBuffer,
_In_ ULONG  InputBufferSize,
_Out_writes_bytes_opt_(OutputBufferSize) PVOID  OutputBuffer,
_In_ ULONG  OutputBufferSize,
_In_ bool  Override,
_Out_opt_ IO_STATUS_BLOCK iosb 
)

Definition at line 2954 of file btrfs.c.

2955 {
2956 PIRP Irp;
2957 KEVENT Event;
2961
2963
2967 InputBufferSize,
2969 OutputBufferSize,
2970 false,
2971 &Event,
2972 &IoStatus);
2973
2975
2976 if (Override) {
2979 }
2980
2982
2983 if (Status == STATUS_PENDING) {
2985 Status = IoStatus.Status;
2986 }
2987
2988 if (iosb)
2989 *iosb = IoStatus;
2990
2991 return Status;
2992}
static PIO_STATUS_BLOCK iosb
Definition: file.c:98
__in UCHAR __in POWER_STATE __in_opt PVOID __in PIO_STATUS_BLOCK IoStatus
Definition: mxum.h:159
PIRP NTAPI IoBuildDeviceIoControlRequest(IN ULONG IoControlCode, IN PDEVICE_OBJECT DeviceObject, IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PVOID OutputBuffer, IN ULONG OutputBufferLength, IN BOOLEAN InternalDeviceIoControl, IN PKEVENT Event, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:881
#define STATUS_PENDING
Definition: ntstatus.h:82
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR OutputBuffer
Definition: wdfiotarget.h:863
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR InputBuffer
Definition: wdfiotarget.h:953
_IRQL_requires_same_ typedef _In_ ULONG ControlCode
Definition: wmitypes.h:55
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1823

Referenced by _Function_class_(), add_device(), disk_arrival(), finish_removing_device(), get_device_change_count(), get_devices(), init_device(), is_btrfs_volume(), is_device_removable(), is_volume_mounted(), mount_vol(), mountmgr_add_drive_letter(), mountmgr_notification(), mountmgr_process_drive(), probe_volume(), query_filesystems(), remove_drive_letter(), remove_volume_child(), resize_device(), test_vol(), trim_unalloc_space(), trim_whole_device(), verify_device(), verify_vcb(), vol_check_verify(), vol_get_disk_extents(), vol_is_writable(), and volume_arrival().

◆ disk_arrival()

void disk_arrival ( PUNICODE_STRING  devpath)

Definition at line 460 of file search.c.

460 {
461 PFILE_OBJECT fileobj;
462 PDEVICE_OBJECT devobj;
465 ULONG dlisize;
466 DRIVE_LAYOUT_INFORMATION_EX* dli = NULL;
469
471
472 Status = IoGetDeviceObjectPointer(devpath, FILE_READ_ATTRIBUTES, &fileobj, &devobj);
473 if (!NT_SUCCESS(Status)) {
475 ERR("IoGetDeviceObjectPointer returned %08lx\n", Status);
476 return;
477 }
478
479 dlisize = 0;
480
481 do {
482 dlisize += 1024;
483
484 if (dli)
485 ExFreePool(dli);
486
488 if (!dli) {
489 ERR("out of memory\n");
490 goto end;
491 }
492
494 dli, dlisize, true, &iosb);
495 } while (Status == STATUS_BUFFER_TOO_SMALL);
496
497 // only consider disk as a potential filesystem if it has no partitions
498 if (NT_SUCCESS(Status) && dli->PartitionCount > 0) {
499 ExFreePool(dli);
500 goto end;
501 }
502
503 ExFreePool(dli);
504
506 &gli, sizeof(gli), true, NULL);
507
508 if (!NT_SUCCESS(Status)) {
509 ERR("error reading length information: %08lx\n", Status);
510 goto end;
511 }
512
514 &sdn, sizeof(STORAGE_DEVICE_NUMBER), true, NULL);
515 if (!NT_SUCCESS(Status)) {
516 TRACE("IOCTL_STORAGE_GET_DEVICE_NUMBER returned %08lx\n", Status);
517 sdn.DeviceNumber = 0xffffffff;
518 sdn.PartitionNumber = 0;
519 } else
520 TRACE("DeviceType = %lu, DeviceNumber = %lu, PartitionNumber = %lu\n", sdn.DeviceType, sdn.DeviceNumber, sdn.PartitionNumber);
521
522 test_vol(devobj, fileobj, devpath, sdn.DeviceNumber, sdn.PartitionNumber,
523 gli.Length.QuadPart, false);
524
525end:
526 ObDereferenceObject(fileobj);
527
529}
NTSTATUS dev_ioctl(_In_ PDEVICE_OBJECT DeviceObject, _In_ ULONG ControlCode, _In_reads_bytes_opt_(InputBufferSize) PVOID InputBuffer, _In_ ULONG InputBufferSize, _Out_writes_bytes_opt_(OutputBufferSize) PVOID OutputBuffer, _In_ ULONG OutputBufferSize, _In_ bool Override, _Out_opt_ IO_STATUS_BLOCK *iosb)
Definition: btrfs.c:2954
static bool test_vol(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject, PUNICODE_STRING devpath, DWORD disk_num, DWORD part_num, uint64_t length, bool fve_callback)
Definition: search.c:311
ERESOURCE boot_lock
Definition: btrfs.c:110
#define IOCTL_DISK_GET_DRIVE_LAYOUT_EX
Definition: ntddk_ex.h:207
#define IOCTL_DISK_GET_LENGTH_INFO
Definition: imports.h:192
#define IOCTL_STORAGE_GET_DEVICE_NUMBER
Definition: ntddstor.h:143
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
LARGE_INTEGER Length
Definition: winioctl.h:560
DEVICE_TYPE DeviceType
Definition: ntddstor.h:324

Referenced by probe_volume().

◆ dismount_volume()

NTSTATUS dismount_volume ( device_extension Vcb,
bool  shutdown,
PIRP  Irp 
)

Definition at line 2584 of file fsctl.c.

2584 {
2586 bool open_files;
2587
2588 TRACE("FSCTL_DISMOUNT_VOLUME\n");
2589
2590 if (!(Vcb->Vpb->Flags & VPB_MOUNTED))
2591 return STATUS_SUCCESS;
2592
2593 if (!shutdown) {
2594 if (Vcb->disallow_dismount || Vcb->page_file_count != 0) {
2595 WARN("attempting to dismount boot volume or one containing a pagefile\n");
2596 return STATUS_ACCESS_DENIED;
2597 }
2598
2600 if (!NT_SUCCESS(Status)) {
2601 WARN("FsRtlNotifyVolumeEvent returned %08lx\n", Status);
2602 }
2603 }
2604
2605 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
2606
2607 if (!Vcb->locked) {
2609
2610 if (Vcb->need_write && !Vcb->readonly) {
2611 Status = do_write(Vcb, Irp);
2612
2613 if (!NT_SUCCESS(Status))
2614 ERR("do_write returned %08lx\n", Status);
2615 }
2616 }
2617
2618 free_trees(Vcb);
2619
2620 Vcb->removing = true;
2621
2622 open_files = Vcb->open_files > 0;
2623
2624 if (Vcb->vde) {
2626 Vcb->vde->mounted_device = NULL;
2627 }
2628
2629 ExReleaseResourceLite(&Vcb->tree_lock);
2630
2631 if (!open_files)
2632 uninit(Vcb);
2633
2634 return STATUS_SUCCESS;
2635}
static void flush_fcb_caches(device_extension *Vcb)
Definition: fsctl.c:2222
static void update_volumes(device_extension *Vcb)
Definition: fsctl.c:2561
void uninit(_In_ device_extension *Vcb)
Definition: btrfs.c:2001
#define FSRTL_VOLUME_DISMOUNT
Definition: ntifs_ex.h:439
INT WSAAPI shutdown(IN SOCKET s, IN INT how)
Definition: sockctrl.c:506
#define VPB_MOUNTED
Definition: iotypes.h:1807

Referenced by do_shutdown(), and fsctl_request().

◆ do_calc_job()

void do_calc_job ( device_extension Vcb,
uint8_t data,
uint32_t  sectors,
void csum 
)

Definition at line 141 of file calcthread.c.

141 {
142 KIRQL irql;
143 calc_job cj;
144
145 cj.in = data;
146 cj.out = csum;
147 cj.left = cj.not_started = sectors;
148
149 switch (Vcb->superblock.csum_type) {
150 case CSUM_TYPE_CRC32C:
151 cj.type = calc_thread_crc32c;
152 break;
153
154 case CSUM_TYPE_XXHASH:
155 cj.type = calc_thread_xxhash;
156 break;
157
158 case CSUM_TYPE_SHA256:
159 cj.type = calc_thread_sha256;
160 break;
161
162 case CSUM_TYPE_BLAKE2:
163 cj.type = calc_thread_blake2;
164 break;
165 }
166
167 KeInitializeEvent(&cj.event, NotificationEvent, false);
168
169 KeAcquireSpinLock(&Vcb->calcthreads.spinlock, &irql);
170
171 InsertTailList(&Vcb->calcthreads.job_list, &cj.list_entry);
172
173 KeSetEvent(&Vcb->calcthreads.event, 0, false);
174 KeClearEvent(&Vcb->calcthreads.event);
175
176 KeReleaseSpinLock(&Vcb->calcthreads.spinlock, irql);
177
179
181}
void calc_thread_main(device_extension *Vcb, calc_job *cj)
Definition: calcthread.c:22

Referenced by __attribute__(), check_csum(), insert_extent_chunk(), scrub_extent_dup(), scrub_extent_raid10(), and write_compressed().

◆ do_load_tree()

NTSTATUS NTSTATUS do_load_tree ( device_extension Vcb,
tree_holder th,
root r,
tree t,
tree_data td,
PIRP  Irp 
)

Referenced by try_tree_amalgamate().

◆ do_read()

NTSTATUS NTSTATUS NTSTATUS do_read ( PIRP  Irp,
bool  wait,
ULONG bytes_read 
)

Definition at line 3328 of file read.c.

3328 {
3331 fcb* fcb = FileObject->FsContext;
3332 uint8_t* data = NULL;
3333 ULONG length = IrpSp->Parameters.Read.Length, addon = 0;
3334 uint64_t start = IrpSp->Parameters.Read.ByteOffset.QuadPart;
3335
3336 *bytes_read = 0;
3337
3338 if (!fcb || !fcb->Vcb || !fcb->subvol)
3339 return STATUS_INTERNAL_ERROR;
3340
3341 TRACE("fcb = %p\n", fcb);
3342 TRACE("offset = %I64x, length = %lx\n", start, length);
3343 TRACE("paging_io = %s, no cache = %s\n", Irp->Flags & IRP_PAGING_IO ? "true" : "false", Irp->Flags & IRP_NOCACHE ? "true" : "false");
3344
3345 if (!fcb->ads && fcb->type == BTRFS_TYPE_DIRECTORY)
3347
3348 if (!(Irp->Flags & IRP_PAGING_IO) && !FsRtlCheckLockForReadAccess(&fcb->lock, Irp)) {
3349 WARN("tried to read locked region\n");
3351 }
3352
3353 if (length == 0) {
3354 TRACE("tried to read zero bytes\n");
3355 return STATUS_SUCCESS;
3356 }
3357
3358 if (start >= (uint64_t)fcb->Header.FileSize.QuadPart) {
3359 TRACE("tried to read with offset after file end (%I64x >= %I64x)\n", start, fcb->Header.FileSize.QuadPart);
3360 return STATUS_END_OF_FILE;
3361 }
3362
3363 TRACE("FileObject %p fcb %p FileSize = %I64x st_size = %I64x (%p)\n", FileObject, fcb, fcb->Header.FileSize.QuadPart, fcb->inode_item.st_size, &fcb->inode_item.st_size);
3364
3365 if (!(Irp->Flags & IRP_NOCACHE) && IrpSp->MinorFunction & IRP_MN_MDL) {
3367
3368 _SEH2_TRY {
3369 if (!FileObject->PrivateCacheMap) {
3370 CC_FILE_SIZES ccfs;
3371
3372 ccfs.AllocationSize = fcb->Header.AllocationSize;
3373 ccfs.FileSize = fcb->Header.FileSize;
3374 ccfs.ValidDataLength = fcb->Header.ValidDataLength;
3375
3377 }
3378
3379 CcMdlRead(FileObject, &IrpSp->Parameters.Read.ByteOffset, length, &Irp->MdlAddress, &Irp->IoStatus);
3382 } _SEH2_END;
3383
3384 if (NT_SUCCESS(Status)) {
3385 Status = Irp->IoStatus.Status;
3386 Irp->IoStatus.Information += addon;
3387 *bytes_read = (ULONG)Irp->IoStatus.Information;
3388 } else
3389 ERR("EXCEPTION - %08lx\n", Status);
3390
3391 return Status;
3392 }
3393
3395
3396 if (Irp->MdlAddress && !data) {
3397 ERR("MmGetSystemAddressForMdlSafe returned NULL\n");
3399 }
3400
3401 if (start >= (uint64_t)fcb->Header.ValidDataLength.QuadPart) {
3402 length = (ULONG)min(length, min(start + length, (uint64_t)fcb->Header.FileSize.QuadPart) - fcb->Header.ValidDataLength.QuadPart);
3404 Irp->IoStatus.Information = *bytes_read = length;
3405 return STATUS_SUCCESS;
3406 }
3407
3408 if (length + start > (uint64_t)fcb->Header.ValidDataLength.QuadPart) {
3409 addon = (ULONG)(min(start + length, (uint64_t)fcb->Header.FileSize.QuadPart) - fcb->Header.ValidDataLength.QuadPart);
3410 RtlZeroMemory(data + (fcb->Header.ValidDataLength.QuadPart - start), addon);
3411 length = (ULONG)(fcb->Header.ValidDataLength.QuadPart - start);
3412 }
3413
3414 if (!(Irp->Flags & IRP_NOCACHE)) {
3416
3417 _SEH2_TRY {
3418 if (!FileObject->PrivateCacheMap) {
3419 CC_FILE_SIZES ccfs;
3420
3421 ccfs.AllocationSize = fcb->Header.AllocationSize;
3422 ccfs.FileSize = fcb->Header.FileSize;
3423 ccfs.ValidDataLength = fcb->Header.ValidDataLength;
3424
3426 }
3427
3428 if (fCcCopyReadEx) {
3429 TRACE("CcCopyReadEx(%p, %I64x, %lx, %u, %p, %p, %p)\n", FileObject, IrpSp->Parameters.Read.ByteOffset.QuadPart,
3430 length, wait, data, &Irp->IoStatus, Irp->Tail.Overlay.Thread);
3431 TRACE("sizes = %I64x, %I64x, %I64x\n", fcb->Header.AllocationSize.QuadPart, fcb->Header.FileSize.QuadPart, fcb->Header.ValidDataLength.QuadPart);
3432 if (!fCcCopyReadEx(FileObject, &IrpSp->Parameters.Read.ByteOffset, length, wait, data, &Irp->IoStatus, Irp->Tail.Overlay.Thread)) {
3433 TRACE("CcCopyReadEx could not wait\n");
3434
3436 return STATUS_PENDING;
3437 }
3438 TRACE("CcCopyReadEx finished\n");
3439 } else {
3440 TRACE("CcCopyRead(%p, %I64x, %lx, %u, %p, %p)\n", FileObject, IrpSp->Parameters.Read.ByteOffset.QuadPart, length, wait, data, &Irp->IoStatus);
3441 TRACE("sizes = %I64x, %I64x, %I64x\n", fcb->Header.AllocationSize.QuadPart, fcb->Header.FileSize.QuadPart, fcb->Header.ValidDataLength.QuadPart);
3442 if (!CcCopyRead(FileObject, &IrpSp->Parameters.Read.ByteOffset, length, wait, data, &Irp->IoStatus)) {
3443 TRACE("CcCopyRead could not wait\n");
3444
3446 return STATUS_PENDING;
3447 }
3448 TRACE("CcCopyRead finished\n");
3449 }
3452 } _SEH2_END;
3453
3454 if (NT_SUCCESS(Status)) {
3455 Status = Irp->IoStatus.Status;
3456 Irp->IoStatus.Information += addon;
3457 *bytes_read = (ULONG)Irp->IoStatus.Information;
3458 } else
3459 ERR("EXCEPTION - %08lx\n", Status);
3460
3461 return Status;
3462 } else {
3464
3465 if (!wait) {
3467 return STATUS_PENDING;
3468 }
3469
3470 if (fcb->ads) {
3471 Status = read_stream(fcb, data, start, length, bytes_read);
3472
3473 if (!NT_SUCCESS(Status))
3474 ERR("read_stream returned %08lx\n", Status);
3475 } else {
3476 Status = read_file(fcb, data, start, length, bytes_read, Irp);
3477
3478 if (!NT_SUCCESS(Status))
3479 ERR("read_file returned %08lx\n", Status);
3480 }
3481
3482 *bytes_read += addon;
3483 TRACE("read %lu bytes\n", *bytes_read);
3484
3485 Irp->IoStatus.Information = *bytes_read;
3486
3487 if (diskacc && Status != STATUS_PENDING) {
3489
3490 if (Irp->Tail.Overlay.Thread && !IoIsSystemThread(Irp->Tail.Overlay.Thread))
3491 thread = Irp->Tail.Overlay.Thread;
3496
3497 if (thread)
3498 fPsUpdateDiskCounters(PsGetThreadProcess(thread), *bytes_read, 0, 1, 0, 0);
3499 }
3500
3501 return Status;
3502 }
3503}
static const addon_info_t * addon
Definition: addons.c:59
static HANDLE thread
Definition: service.c:33
HRESULT read_stream(BSCallback *, IStream *, void *, DWORD, DWORD *) DECLSPEC_HIDDEN
Definition: navigate.c:602
NTSTATUS read_file(fcb *fcb, uint8_t *data, uint64_t start, uint64_t length, ULONG *pbr, PIRP Irp) __attribute__((nonnull(1
PEPROCESS __stdcall PsGetThreadProcess(_In_ PETHREAD Thread)
static __inline void * map_user_buffer(PIRP Irp, ULONG priority)
Definition: btrfs_drv.h:977
VOID NTAPI CcMdlRead(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, OUT PMDL *MdlChain, OUT PIO_STATUS_BLOCK IoStatus)
Definition: mdlsup.c:64
void init_file_cache(_In_ PFILE_OBJECT FileObject, _In_ CC_FILE_SIZES *ccfs)
Definition: btrfs.c:4069
BOOLEAN NTAPI FsRtlCheckLockForReadAccess(IN PFILE_LOCK FileLock, IN PIRP Irp)
Definition: filelock.c:672
tCcCopyReadEx fCcCopyReadEx
Definition: btrfs.c:91
bool diskacc
Definition: btrfs.c:101
tPsUpdateDiskCounters fPsUpdateDiskCounters
Definition: btrfs.c:90
#define FSRTL_FLAG2_IS_PAGING_FILE
Definition: fsrtltypes.h:57
IoMarkIrpPending(Irp)
@ NormalPagePriority
Definition: imports.h:56
@ HighPagePriority
Definition: imports.h:57
BOOLEAN NTAPI CcCopyRead(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, OUT PVOID Buffer, OUT PIO_STATUS_BLOCK IoStatus)
Definition: copysup.c:43
PIRP NTAPI IoGetTopLevelIrp(VOID)
Definition: irp.c:1843
BOOLEAN NTAPI IoIsSystemThread(IN PETHREAD Thread)
Definition: util.c:115
#define STATUS_FILE_LOCK_CONFLICT
Definition: ntstatus.h:320
uint64_t st_size
Definition: btrfs.h:289
LARGE_INTEGER FileSize
Definition: cctypes.h:16
LARGE_INTEGER ValidDataLength
Definition: cctypes.h:17
LARGE_INTEGER AllocationSize
Definition: cctypes.h:15
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define IRP_PAGING_IO
#define IRP_MN_MDL
Definition: iotypes.h:4419
#define IRP_NOCACHE

Referenced by _Dispatch_type_(), and do_read_job().

◆ do_read_job()

NTSTATUS do_read_job ( PIRP  Irp)

Definition at line 26 of file worker-thread.c.

26 {
28 ULONG bytes_read;
29 bool top_level = is_top_level(Irp);
32 fcb* fcb = FileObject->FsContext;
33 bool acquired_fcb_lock = false;
34
35 Irp->IoStatus.Information = 0;
36
38 ExAcquireResourceSharedLite(fcb->Header.Resource, true);
39 acquired_fcb_lock = true;
40 }
41
42 _SEH2_TRY {
43 Status = do_read(Irp, true, &bytes_read);
46 } _SEH2_END;
47
48 if (acquired_fcb_lock)
50
51 if (!NT_SUCCESS(Status))
52 ERR("do_read returned %08lx\n", Status);
53
54 Irp->IoStatus.Status = Status;
55
56 TRACE("read %Iu bytes\n", Irp->IoStatus.Information);
57
59
60 if (top_level)
62
63 TRACE("returning %08lx\n", Status);
64
65 return Status;
66}
NTSTATUS NTSTATUS NTSTATUS do_read(PIRP Irp, bool wait, ULONG *bytes_read)
Definition: read.c:3328
bool is_top_level(_In_ PIRP Irp)
Definition: btrfs.c:278
ULONG NTAPI ExIsResourceAcquiredSharedLite(IN PERESOURCE Resource)
Definition: resource.c:1663
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000

Referenced by _Dispatch_type_(), and _Function_class_().

◆ do_rollback()

◆ do_shutdown()

void do_shutdown ( PIRP  Irp)

Definition at line 5392 of file btrfs.c.

5392 {
5393 LIST_ENTRY* le;
5395
5396 shutting_down = true;
5398
5399 le = VcbList.Flink;
5400 while (le != &VcbList) {
5401 LIST_ENTRY* le2 = le->Flink;
5402
5404 volume_device_extension* vde = Vcb->vde;
5405 PDEVICE_OBJECT devobj = vde ? vde->device : NULL;
5406
5407 TRACE("shutting down Vcb %p\n", Vcb);
5408
5409 if (vde)
5411
5412 if (devobj)
5413 ObReferenceObject(devobj);
5414
5415 dismount_volume(Vcb, true, Irp);
5416
5417 if (vde) {
5419 UNICODE_STRING mmdevpath;
5421 PFILE_OBJECT mountmgrfo;
5422 KIRQL irql;
5423 PVPB newvpb;
5424
5426 Status = IoGetDeviceObjectPointer(&mmdevpath, FILE_READ_ATTRIBUTES, &mountmgrfo, &mountmgr);
5427 if (!NT_SUCCESS(Status))
5428 ERR("IoGetDeviceObjectPointer returned %08lx\n", Status);
5429 else {
5431
5432 ObDereferenceObject(mountmgrfo);
5433 }
5434
5435 vde->removing = true;
5436
5437 newvpb = ExAllocatePoolWithTag(NonPagedPool, sizeof(VPB), ALLOC_TAG);
5438 if (!newvpb) {
5439 ERR("out of memory\n");
5440 return;
5441 }
5442
5443 RtlZeroMemory(newvpb, sizeof(VPB));
5444
5445 newvpb->Type = IO_TYPE_VPB;
5446 newvpb->Size = sizeof(VPB);
5447 newvpb->RealDevice = newvpb->DeviceObject = vde->device;
5449
5451 vde->device->Vpb = newvpb;
5453
5454 if (InterlockedDecrement(&vde->open_count) == 0)
5455 free_vol(vde);
5456 }
5457
5458 if (devobj)
5459 ObDereferenceObject(devobj);
5460
5461 le = le2;
5462 }
5463
5464#ifdef _DEBUG
5465 if (comfo) {
5466 ObDereferenceObject(comfo);
5467 comdo = NULL;
5468 comfo = NULL;
5469 }
5470#endif
5471
5473
5474 if (notification_entry2) {
5477 else
5479
5481 }
5482
5483 if (notification_entry3) {
5486 else
5488
5490 }
5491
5492 if (notification_entry) {
5495 else
5497
5499 }
5500
5501 bde = busobj->DeviceExtension;
5502
5503 if (bde->attached_device)
5505
5508}
#define InterlockedIncrement
Definition: armddk.h:53
void void void NTSTATUS void NTSTATUS NTSTATUS remove_drive_letter(PDEVICE_OBJECT mountmgr, PUNICODE_STRING devpath)
Definition: search.c:407
void free_vol(volume_device_extension *vde)
Definition: volume.c:50
NTSTATUS dismount_volume(device_extension *Vcb, bool shutdown, PIRP Irp)
Definition: fsctl.c:2584
bool shutting_down
Definition: btrfs.c:109
LIST_ENTRY VcbList
Definition: btrfs.c:69
KEVENT mountmgr_thread_event
Definition: btrfs.c:108
PDEVICE_OBJECT master_devobj
Definition: btrfs.c:66
void * notification_entry3
Definition: btrfs.c:102
tIoUnregisterPlugPlayNotificationEx fIoUnregisterPlugPlayNotificationEx
Definition: btrfs.c:95
PDEVICE_OBJECT busobj
Definition: btrfs.c:66
void * notification_entry2
Definition: btrfs.c:102
void * notification_entry
Definition: btrfs.c:102
#define MOUNTMGR_DEVICE_NAME
Definition: imports.h:76
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
VOID NTAPI IoDetachDevice(IN PDEVICE_OBJECT TargetDevice)
Definition: device.c:1296
VOID NTAPI IoDeleteDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: device.c:1251
VOID NTAPI IoUnregisterFileSystem(IN PDEVICE_OBJECT DeviceObject)
Definition: volume.c:1056
VOID NTAPI IoReleaseVpbSpinLock(IN KIRQL Irql)
Definition: volume.c:1215
VOID NTAPI IoAcquireVpbSpinLock(OUT PKIRQL Irql)
Definition: volume.c:1204
NTSTATUS NTAPI IoUnregisterPlugPlayNotification(_In_ PVOID NotificationEntry)
Definition: pnpnotify.c:479
Definition: iotypes.h:189
CSHORT Type
Definition: iotypes.h:190
CSHORT Size
Definition: iotypes.h:191
struct _DEVICE_OBJECT * DeviceObject
Definition: iotypes.h:194
USHORT Flags
Definition: iotypes.h:192
struct _DEVICE_OBJECT * RealDevice
Definition: iotypes.h:195
UNICODE_STRING name
Definition: btrfs_drv.h:874
PDEVICE_OBJECT attached_device
Definition: btrfs_drv.h:849
#define IO_TYPE_VPB
struct _VPB VPB
#define VPB_DIRECT_WRITES_ALLOWED
Definition: iotypes.h:1812
#define ObReferenceObject
Definition: obfuncs.h:204

Referenced by _Dispatch_type_(), and ioctl_unload().

◆ do_tree_writes()

NTSTATUS do_tree_writes ( device_extension Vcb,
LIST_ENTRY tree_writes,
bool  no_free 
)

Definition at line 1620 of file flushthread.c.

1620 {
1621 chunk* c;
1622 LIST_ENTRY* le;
1623 tree_write* tw;
1625 ULONG i, num_bits;
1626 write_data_context* wtc;
1627 ULONG bit_num = 0;
1628 bool raid56 = false;
1629
1630 // merge together runs
1631 c = NULL;
1632 le = tree_writes->Flink;
1633 while (le != tree_writes) {
1635
1636 if (!c || tw->address < c->offset || tw->address >= c->offset + c->chunk_item->size)
1638 else {
1640
1641 if (tw->address == tw2->address + tw2->length) {
1643
1644 if (!data) {
1645 ERR("out of memory\n");
1647 }
1648
1649 RtlCopyMemory(data, tw2->data, tw2->length);
1650 RtlCopyMemory(&data[tw2->length], tw->data, tw->length);
1651
1652 if (!no_free || tw2->allocated)
1653 ExFreePool(tw2->data);
1654
1655 tw2->data = data;
1656 tw2->length += tw->length;
1657 tw2->allocated = true;
1658
1659 if (!no_free || tw->allocated)
1660 ExFreePool(tw->data);
1661
1663 ExFreePool(tw);
1664
1665 le = tw2->list_entry.Flink;
1666 continue;
1667 }
1668 }
1669
1670 tw->c = c;
1671
1672 if (c->chunk_item->type & (BLOCK_FLAG_RAID5 | BLOCK_FLAG_RAID6))
1673 raid56 = true;
1674
1675 le = le->Flink;
1676 }
1677
1678 num_bits = 0;
1679
1680 le = tree_writes->Flink;
1681 while (le != tree_writes) {
1683
1684 num_bits++;
1685
1686 le = le->Flink;
1687 }
1688
1690 if (!wtc) {
1691 ERR("out of memory\n");
1693 }
1694
1695 le = tree_writes->Flink;
1696
1697 while (le != tree_writes) {
1699
1700 TRACE("address: %I64x, size: %x\n", tw->address, tw->length);
1701
1702 KeInitializeEvent(&wtc[bit_num].Event, NotificationEvent, false);
1703 InitializeListHead(&wtc[bit_num].stripes);
1704 wtc[bit_num].need_wait = false;
1705 wtc[bit_num].stripes_left = 0;
1706 wtc[bit_num].parity1 = wtc[bit_num].parity2 = wtc[bit_num].scratch = NULL;
1707 wtc[bit_num].mdl = wtc[bit_num].parity1_mdl = wtc[bit_num].parity2_mdl = NULL;
1708
1709 Status = write_data(Vcb, tw->address, tw->data, tw->length, &wtc[bit_num], NULL, NULL, false, 0, HighPagePriority);
1710 if (!NT_SUCCESS(Status)) {
1711 ERR("write_data returned %08lx\n", Status);
1712
1713 for (i = 0; i < num_bits; i++) {
1715 }
1716 ExFreePool(wtc);
1717
1718 return Status;
1719 }
1720
1721 bit_num++;
1722
1723 le = le->Flink;
1724 }
1725
1726 for (i = 0; i < num_bits; i++) {
1727 if (wtc[i].stripes.Flink != &wtc[i].stripes) {
1728 // launch writes and wait
1729 le = wtc[i].stripes.Flink;
1730 while (le != &wtc[i].stripes) {
1732
1733 if (stripe->status != WriteDataStatus_Ignore) {
1734 wtc[i].need_wait = true;
1736 }
1737
1738 le = le->Flink;
1739 }
1740 }
1741 }
1742
1743 for (i = 0; i < num_bits; i++) {
1744 if (wtc[i].need_wait)
1746 }
1747
1748 for (i = 0; i < num_bits; i++) {
1749 le = wtc[i].stripes.Flink;
1750 while (le != &wtc[i].stripes) {
1752
1753 if (stripe->status != WriteDataStatus_Ignore && !NT_SUCCESS(stripe->iosb.Status)) {
1754 Status = stripe->iosb.Status;
1756 break;
1757 }
1758
1759 le = le->Flink;
1760 }
1761
1763 }
1764
1765 ExFreePool(wtc);
1766
1767 if (raid56) {
1768 c = NULL;
1769
1770 le = tree_writes->Flink;
1771 while (le != tree_writes) {
1773
1774 if (tw->c != c) {
1775 c = tw->c;
1776
1777 ExAcquireResourceExclusiveLite(&c->partial_stripes_lock, true);
1778
1779 while (!IsListEmpty(&c->partial_stripes)) {
1781
1783
1784 if (ps->bmparr)
1785 ExFreePool(ps->bmparr);
1786
1787 ExFreePool(ps);
1788
1789 if (!NT_SUCCESS(Status)) {
1790 ERR("flush_partial_stripe returned %08lx\n", Status);
1791 ExReleaseResourceLite(&c->partial_stripes_lock);
1792 return Status;
1793 }
1794 }
1795
1796 ExReleaseResourceLite(&c->partial_stripes_lock);
1797 }
1798
1799 le = le->Flink;
1800 }
1801 }
1802
1803 return STATUS_SUCCESS;
1804}
NTSTATUS NTSTATUS NTSTATUS void free_write_data_stripes(write_data_context *wtc) __attribute__((nonnull(1)))
NTSTATUS NTSTATUS NTSTATUS NTSTATUS NTSTATUS chunk * get_chunk_from_address(device_extension *Vcb, uint64_t address) __attribute__((nonnull(1)))
void log_device_error(_In_ device_extension *Vcb, _Inout_ device *dev, _In_ int error)
Definition: btrfs.c:5914
#define BTRFS_DEV_STAT_WRITE_ERRORS
Definition: btrfs.h:539
NTSTATUS flush_partial_stripe(device_extension *Vcb, chunk *c, partial_stripe *ps)
Definition: flushthread.c:5958
#define BLOCK_FLAG_RAID5
Definition: shellext.h:82
#define BLOCK_FLAG_RAID6
Definition: shellext.h:83
LIST_ENTRY stripes
Definition: btrfs_drv.h:938
uint8_t * parity1
Definition: btrfs_drv.h:941
uint8_t * parity2
Definition: btrfs_drv.h:941
uint8_t * scratch
Definition: btrfs_drv.h:941
ULONG * bmparr
Definition: btrfs_drv.h:554
Definition: write.c:113
device * device
Definition: write.c:115
uint32_t length
Definition: btrfs_drv.h:947
uint64_t address
Definition: btrfs_drv.h:946
uint8_t * data
Definition: btrfs_drv.h:948
LIST_ENTRY list_entry
Definition: btrfs_drv.h:951
bool allocated
Definition: btrfs_drv.h:950
chunk * c
Definition: btrfs_drv.h:949

Referenced by write_metadata_items(), and write_trees().

◆ do_unlock_volume()

void do_unlock_volume ( device_extension Vcb)

Definition at line 2326 of file fsctl.c.

2326 {
2327 KIRQL irql;
2328
2330
2331 Vcb->locked = false;
2332 Vcb->Vpb->Flags &= ~VPB_LOCKED;
2333 Vcb->locked_fileobj = NULL;
2334
2336
2337 if (Vcb->lock_paused_balance)
2338 KeSetEvent(&Vcb->balance.event, 0, false);
2339}

Referenced by _Dispatch_type_(), and unlock_volume().

◆ do_write()

NTSTATUS do_write ( device_extension Vcb,
PIRP  Irp 
)

Definition at line 7877 of file flushthread.c.

7877 {
7880
7882
7884
7885 if (!NT_SUCCESS(Status)) {
7886 ERR("do_write2 returned %08lx, dropping into readonly mode\n", Status);
7887 Vcb->readonly = true;
7890 } else
7892
7893 return Status;
7894}
static NTSTATUS do_write2(device_extension *Vcb, PIRP Irp, LIST_ENTRY *rollback)
Definition: flushthread.c:7477
#define FSRTL_VOLUME_FORCED_CLOSED
Definition: fsrtltypes.h:98

Referenced by _Dispatch_type_(), _Function_class_(), add_balance_item(), add_device(), balance_data_chunk(), balance_metadata_chunk(), dismount_volume(), do_create_snapshot(), do_flush(), finish_removing_device(), invalidate_volumes(), lock_volume(), pnp_query_remove_device(), remove_balance_item(), and try_consolidation().

◆ do_write_file()

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 
)

◆ do_write_job()

NTSTATUS do_write_job ( device_extension Vcb,
PIRP  Irp 
)

Definition at line 68 of file worker-thread.c.

68 {
69 bool top_level = is_top_level(Irp);
71
72 _SEH2_TRY {
73 Status = write_file(Vcb, Irp, true, true);
76 } _SEH2_END;
77
78 if (!NT_SUCCESS(Status))
79 ERR("write_file returned %08lx\n", Status);
80
81 Irp->IoStatus.Status = Status;
82
83 TRACE("wrote %Iu bytes\n", Irp->IoStatus.Information);
84
86
87 if (top_level)
89
90 TRACE("returning %08lx\n", Status);
91
92 return Status;
93}
static void write_file(HANDLE hFile, const WCHAR *str)
Definition: export.c:22

Referenced by _Dispatch_type_(), and _Function_class_().

◆ excise_extents()

◆ extend_file()

NTSTATUS NTSTATUS NTSTATUS NTSTATUS extend_file ( fcb fcb,
file_ref fileref,
uint64_t  end,
bool  prealloc,
PIRP  Irp,
LIST_ENTRY rollback 
)

◆ fast_io_possible()

static __inline FAST_IO_POSSIBLE fast_io_possible ( fcb fcb)
static

Definition at line 1684 of file btrfs_drv.h.

1684 {
1686 return FastIoIsNotPossible;
1687
1688 if (!FsRtlAreThereCurrentFileLocks(&fcb->lock) && !fcb->Vcb->readonly)
1689 return FastIoIsPossible;
1690
1691 return FastIoIsQuestionable;
1692}
#define FsRtlAreThereCurrentFileLocks(FL)
Definition: fsrtlfuncs.h:1584
@ FastIoIsQuestionable
Definition: fsrtltypes.h:242
@ FastIoIsNotPossible
Definition: fsrtltypes.h:240
@ FastIoIsPossible
Definition: fsrtltypes.h:241
BOOLEAN NTAPI FsRtlOplockIsFastIoPossible(IN POPLOCK Oplock)
Definition: oplock.c:1564

Referenced by _Dispatch_type_(), _Function_class_(), allocate_cache_chunk(), create_directory_fcb(), create_stream(), create_subvol(), duplicate_fcb(), file_create2(), fsctl_oplock(), mknod(), and open_fcb_stream().

◆ fcb_alloc_size()

static __inline uint64_t fcb_alloc_size ( fcb fcb)
static

Definition at line 1824 of file btrfs_drv.h.

1824 {
1826 return 0;
1828 return fcb->inode_item.st_blocks;
1829 else
1830 return sector_align(fcb->inode_item.st_size, fcb->Vcb->superblock.sector_size);
1831}
#define S_ISDIR(mode)
Definition: btrfs_drv.h:1764
#define FILE_ATTRIBUTE_SPARSE_FILE
Definition: ntifs_ex.h:380
uint64_t st_blocks
Definition: btrfs.h:290

Referenced by _Function_class_(), fill_in_file_network_open_information(), fill_in_file_standard_information(), fill_in_file_stat_information(), fill_in_file_stat_lx_information(), and fill_in_file_stream_information().

◆ fcb_get_new_sd()

NTSTATUS fcb_get_new_sd ( fcb fcb,
file_ref parfileref,
ACCESS_STATE as 
)

Definition at line 988 of file security.c.

988 {
990 PSID owner;
991 BOOLEAN defaulted;
992
993 Status = SeAssignSecurityEx(parfileref ? parfileref->fcb->sd : NULL, as->SecurityDescriptor, (void**)&fcb->sd, NULL, fcb->type == BTRFS_TYPE_DIRECTORY,
995
996 if (!NT_SUCCESS(Status)) {
997 ERR("SeAssignSecurityEx returned %08lx\n", Status);
998 return Status;
999 }
1000
1001 Status = RtlGetOwnerSecurityDescriptor(fcb->sd, &owner, &defaulted);
1002 if (!NT_SUCCESS(Status)) {
1003 ERR("RtlGetOwnerSecurityDescriptor returned %08lx\n", Status);
1005 } else {
1006 fcb->inode_item.st_uid = sid_to_uid(owner);
1007 }
1008
1009 find_gid(fcb, parfileref ? parfileref->fcb : NULL, &as->SubjectSecurityContext);
1010
1011 return STATUS_SUCCESS;
1012}
unsigned char BOOLEAN
#define UID_NOBODY
Definition: btrfs_drv.h:90
uint32_t sid_to_uid(PSID sid)
Definition: security.c:310
void find_gid(struct _fcb *fcb, struct _fcb *parfcb, PSECURITY_SUBJECT_CONTEXT subjcont)
Definition: security.c:924
#define SEF_SACL_AUTO_INHERIT
Definition: security.c:21
NTSYSAPI NTSTATUS NTAPI RtlGetOwnerSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, OUT PSID *Owner, OUT PBOOLEAN OwnerDefaulted)
Definition: sd.c:257
PGENERIC_MAPPING NTAPI IoGetFileObjectGenericMapping(VOID)
Definition: file.c:3267
uint32_t st_uid
Definition: btrfs.h:293
PSECURITY_DESCRIPTOR SecurityDescriptor
Definition: setypes.h:235
SECURITY_SUBJECT_CONTEXT SubjectSecurityContext
Definition: setypes.h:234
SECURITY_DESCRIPTOR * sd
Definition: btrfs_drv.h:293
NTKERNELAPI NTSTATUS NTAPI SeAssignSecurityEx(_In_opt_ PSECURITY_DESCRIPTOR ParentDescriptor, _In_opt_ PSECURITY_DESCRIPTOR ExplicitDescriptor, _Out_ PSECURITY_DESCRIPTOR *NewDescriptor, _In_opt_ GUID *ObjectType, _In_ BOOLEAN IsDirectoryObject, _In_ ULONG AutoInheritFlags, _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext, _In_ PGENERIC_MAPPING GenericMapping, _In_ POOL_TYPE PoolType)

Referenced by file_create2().

◆ fcb_get_sd()

void fcb_get_sd ( fcb fcb,
struct _fcb parent,
bool  look_for_xattr,
PIRP  Irp 
)

Definition at line 511 of file security.c.

511 {
513 PSID usersid = NULL, groupsid = NULL;
515 ULONG buflen;
518 PACL dacl, sacl;
519 PSID owner, group;
520 ULONG abssdlen = 0, dacllen = 0, sacllen = 0, ownerlen = 0, grouplen = 0;
521 uint8_t* buf;
522
523 if (look_for_xattr && get_xattr(fcb->Vcb, fcb->subvol, fcb->inode, EA_NTACL, EA_NTACL_HASH, (uint8_t**)&fcb->sd, (uint16_t*)&buflen, Irp))
524 return;
525
526 if (!parent) {
528 return;
529 }
530
531 SeCaptureSubjectContext(&subjcont);
532
535 if (!NT_SUCCESS(Status)) {
536 ERR("SeAssignSecurityEx returned %08lx\n", Status);
537 return;
538 }
539
540 Status = RtlSelfRelativeToAbsoluteSD(fcb->sd, NULL, &abssdlen, NULL, &dacllen, NULL, &sacllen, NULL, &ownerlen,
541 NULL, &grouplen);
543 ERR("RtlSelfRelativeToAbsoluteSD returned %08lx\n", Status);
544 return;
545 }
546
547 if (abssdlen + dacllen + sacllen + ownerlen + grouplen == 0) {
548 ERR("RtlSelfRelativeToAbsoluteSD returned zero lengths\n");
549 return;
550 }
551
552 buf = (uint8_t*)ExAllocatePoolWithTag(PagedPool, abssdlen + dacllen + sacllen + ownerlen + grouplen, ALLOC_TAG);
553 if (!buf) {
554 ERR("out of memory\n");
555 return;
556 }
557
558 abssd = (PSECURITY_DESCRIPTOR)buf;
559 dacl = (PACL)(buf + abssdlen);
560 sacl = (PACL)(buf + abssdlen + dacllen);
561 owner = (PSID)(buf + abssdlen + dacllen + sacllen);
562 group = (PSID)(buf + abssdlen + dacllen + sacllen + ownerlen);
563
564 Status = RtlSelfRelativeToAbsoluteSD(fcb->sd, abssd, &abssdlen, dacl, &dacllen, sacl, &sacllen, owner, &ownerlen,
565 group, &grouplen);
567 ERR("RtlSelfRelativeToAbsoluteSD returned %08lx\n", Status);
569 return;
570 }
571
572 Status = uid_to_sid(fcb->inode_item.st_uid, &usersid);
573 if (!NT_SUCCESS(Status)) {
574 ERR("uid_to_sid returned %08lx\n", Status);
576 return;
577 }
578
579 RtlSetOwnerSecurityDescriptor(abssd, usersid, false);
580
581 gid_to_sid(fcb->inode_item.st_gid, &groupsid);
582 if (!groupsid) {
583 ERR("out of memory\n");
584 ExFreePool(usersid);
586 return;
587 }
588
589 RtlSetGroupSecurityDescriptor(abssd, groupsid, false);
590
591 buflen = 0;
592
593 Status = RtlAbsoluteToSelfRelativeSD(abssd, NULL, &buflen);
595 ERR("RtlAbsoluteToSelfRelativeSD returned %08lx\n", Status);
596 ExFreePool(usersid);
597 ExFreePool(groupsid);
599 return;
600 }
601
602 if (buflen == 0) {
603 ERR("RtlAbsoluteToSelfRelativeSD returned a buffer size of 0\n");
604 ExFreePool(usersid);
605 ExFreePool(groupsid);
607 return;
608 }
609
610 newsd = ExAllocatePoolWithTag(PagedPool, buflen, ALLOC_TAG);
611 if (!newsd) {
612 ERR("out of memory\n");
613 ExFreePool(usersid);
614 ExFreePool(groupsid);
616 return;
617 }
618
619 Status = RtlAbsoluteToSelfRelativeSD(abssd, newsd, &buflen);
620 if (!NT_SUCCESS(Status)) {
621 ERR("RtlAbsoluteToSelfRelativeSD returned %08lx\n", Status);
622 ExFreePool(usersid);
623 ExFreePool(groupsid);
625 return;
626 }
627
628 ExFreePool(fcb->sd);
629 fcb->sd = newsd;
630
631 ExFreePool(usersid);
632 ExFreePool(groupsid);
634}
#define EA_NTACL_HASH
Definition: btrfs_drv.h:94
#define EA_NTACL
Definition: btrfs_drv.h:93
NTSTATUS uid_to_sid(uint32_t uid, PSID *sid)
Definition: security.c:229
#define SEF_DACL_AUTO_INHERIT
Definition: security.c:20
static void get_top_level_sd(fcb *fcb)
Definition: security.c:415
static void gid_to_sid(uint32_t gid, PSID *sid)
Definition: security.c:341
GLboolean GLuint group
Definition: glext.h:11120
NTSYSAPI NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(PSECURITY_DESCRIPTOR, PSID, BOOLEAN)
NTSYSAPI NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(PSECURITY_DESCRIPTOR, PSECURITY_DESCRIPTOR, PDWORD, PACL, PDWORD, PACL, PDWORD, PSID, PDWORD, PSID, PDWORD)
struct _SID * PSID
Definition: eventlog.c:35
struct _SECURITY_DESCRIPTOR * PSECURITY_DESCRIPTOR
Definition: security.c:98
struct _ACL * PACL
Definition: security.c:105
NTSYSAPI NTSTATUS NTAPI RtlSetGroupSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor, IN PSID Group, IN BOOLEAN GroupDefaulted)
Definition: sd.c:410
NTSYSAPI NTSTATUS NTAPI RtlAbsoluteToSelfRelativeSD(IN PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor, IN OUT PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor, IN PULONG BufferLength)
Definition: sd.c:626
uint32_t st_gid
Definition: btrfs.h:294
uint64_t inode
Definition: btrfs_drv.h:289
Definition: security.c:35
VOID NTAPI SeCaptureSubjectContext(_Out_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
Captures the security subject context of the calling thread and calling process.
Definition: subject.c:85

Referenced by fsctl_set_xattr(), and mount_vol().

◆ fcb_is_inline()

bool fcb_is_inline ( fcb fcb)

Definition at line 3246 of file fsctl.c.

3246 {
3247 LIST_ENTRY* le;
3248
3249 le = fcb->extents.Flink;
3250 while (le != &fcb->extents) {
3252
3253 if (!ext->ignore)
3254 return ext->extent_data.type == EXTENT_TYPE_INLINE;
3255
3256 le = le->Flink;
3257 }
3258
3259 return false;
3260}
static const WCHAR *const ext[]
Definition: module.c:53
#define EXTENT_TYPE_INLINE
Definition: btrfs.h:74

Referenced by __attribute__(), duplicate_extents(), and zero_data().

◆ fcb_oplock()

static __inline POPLOCK fcb_oplock ( fcb fcb)
static

Definition at line 1677 of file btrfs_drv.h.

1677 {
1678 if (fcb->Header.Version >= FSRTL_FCB_HEADER_V2)
1679 return &((FSRTL_ADVANCED_FCB_HEADER_NEW*)&fcb->Header)->Oplock;
1680 else
1681 return &fcb->oplock;
1682}
#define FSRTL_FCB_HEADER_V2
Definition: btrfs_drv.h:1655
OPLOCK oplock
Definition: btrfs_drv.h:312

Referenced by _Dispatch_type_(), create_fcb(), fast_io_possible(), fsctl_oplock(), fsctl_request(), open_file2(), and reap_fcb().

◆ fileref_get_filename()

NTSTATUS fileref_get_filename ( file_ref fileref,
PUNICODE_STRING  fn,
USHORT name_offset,
ULONG preqlen 
)

Definition at line 4245 of file fileinfo.c.

4245 {
4246 file_ref* fr;
4248 ULONG reqlen = 0;
4249 USHORT offset;
4250 bool overflow = false;
4251
4252 // FIXME - we need a lock on filerefs' filepart
4253
4254 if (fileref == fileref->fcb->Vcb->root_fileref) {
4255 if (fn->MaximumLength >= sizeof(WCHAR)) {
4256 fn->Buffer[0] = '\\';
4257 fn->Length = sizeof(WCHAR);
4258
4259 if (name_offset)
4260 *name_offset = 0;
4261
4262 return STATUS_SUCCESS;
4263 } else {
4264 if (preqlen)
4265 *preqlen = sizeof(WCHAR);
4266 fn->Length = 0;
4267
4269 }
4270 }
4271
4272 fr = fileref;
4273 offset = 0;
4274
4275 while (fr->parent) {
4276 USHORT movelen;
4277
4278 if (!fr->dc)
4279 return STATUS_INTERNAL_ERROR;
4280
4281 if (!overflow) {
4282 if (fr->dc->name.Length + sizeof(WCHAR) + fn->Length > fn->MaximumLength)
4283 overflow = true;
4284 }
4285
4286 if (overflow)
4287 movelen = fn->MaximumLength - fr->dc->name.Length - sizeof(WCHAR);
4288 else
4289 movelen = fn->Length;
4290
4291 if ((!overflow || fn->MaximumLength > fr->dc->name.Length + sizeof(WCHAR)) && movelen > 0) {
4292 RtlMoveMemory(&fn->Buffer[(fr->dc->name.Length / sizeof(WCHAR)) + 1], fn->Buffer, movelen);
4293 offset += fr->dc->name.Length + sizeof(WCHAR);
4294 }
4295
4296 if (fn->MaximumLength >= sizeof(WCHAR)) {
4297 fn->Buffer[0] = fr->fcb->ads ? ':' : '\\';
4298 fn->Length += sizeof(WCHAR);
4299
4300 if (fn->MaximumLength > sizeof(WCHAR)) {
4301 RtlCopyMemory(&fn->Buffer[1], fr->dc->name.Buffer, min(fr->dc->name.Length, fn->MaximumLength - sizeof(WCHAR)));
4302 fn->Length += fr->dc->name.Length;
4303 }
4304
4305 if (fn->Length > fn->MaximumLength) {
4306 fn->Length = fn->MaximumLength;
4307 overflow = true;
4308 }
4309 }
4310
4311 reqlen += sizeof(WCHAR) + fr->dc->name.Length;
4312
4313 fr = fr->parent;
4314 }
4315
4316 offset += sizeof(WCHAR);
4317
4318 if (overflow) {
4319 if (preqlen)
4320 *preqlen = reqlen;
4322 } else {
4323 if (name_offset)
4324 *name_offset = offset;
4325
4327 }
4328
4329 return Status;
4330}
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
struct _file_ref * parent
Definition: btrfs_drv.h:352
UNICODE_STRING name
Definition: btrfs_drv.h:256
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
static GLenum _GLUfuncptr fn
Definition: wgl_font.c:159

Referenced by fill_in_file_name_information(), get_subvol_path(), notify_change_directory(), send_notification_fcb(), send_notification_fileref(), and set_rename_information().

◆ find_chunk_usage()

NTSTATUS find_chunk_usage ( _In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension Vcb,
_In_opt_ PIRP  Irp 
)

Definition at line 3876 of file btrfs.c.

3876 {
3877 LIST_ENTRY* le = Vcb->chunks.Flink;
3878 chunk* c;
3879 KEY searchkey;
3881 BLOCK_GROUP_ITEM* bgi;
3883
3884 searchkey.obj_type = TYPE_BLOCK_GROUP_ITEM;
3885
3886 Vcb->superblock.bytes_used = 0;
3887
3888 while (le != &Vcb->chunks) {
3890
3891 searchkey.obj_id = c->offset;
3892 searchkey.offset = c->chunk_item->size;
3893
3894 Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, Irp);
3895 if (!NT_SUCCESS(Status)) {
3896 ERR("error - find_item returned %08lx\n", Status);
3897 return Status;
3898 }
3899
3900 if (!keycmp(searchkey, tp.item->key)) {
3901 if (tp.item->size >= sizeof(BLOCK_GROUP_ITEM)) {
3902 bgi = (BLOCK_GROUP_ITEM*)tp.item->data;
3903
3904 c->used = c->oldused = bgi->used;
3905
3906 TRACE("chunk %I64x has %I64x bytes used\n", c->offset, c->used);
3907
3908 Vcb->superblock.bytes_used += bgi->used;
3909 } else {
3910 ERR("(%I64x;%I64x,%x,%I64x) is %u bytes, expected %Iu\n",
3911 Vcb->extent_root->id, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(BLOCK_GROUP_ITEM));
3912 }
3913 }
3914
3915 le = le->Flink;
3916 }
3917
3918 Vcb->chunk_usage_found = true;
3919
3920 return STATUS_SUCCESS;
3921}
#define TYPE_BLOCK_GROUP_ITEM
Definition: btrfs.h:42
uint64_t used
Definition: btrfs.h:424

Referenced by get_usage(), and mount_vol().

◆ find_data_address_in_chunk()

NTSTATUS bool find_data_address_in_chunk ( device_extension Vcb,
chunk c,
uint64_t  length,
uint64_t address 
)

◆ find_default_subvol()

_Ret_maybenull_ root * find_default_subvol ( _In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension Vcb,
_In_opt_ PIRP  Irp 
)

Definition at line 3981 of file btrfs.c.

3981 {
3982 LIST_ENTRY* le;
3983
3984 static const char fn[] = "default";
3985 static uint32_t crc32 = 0x8dbfc2d2;
3986
3987 if (Vcb->options.subvol_id != 0) {
3988 le = Vcb->roots.Flink;
3989 while (le != &Vcb->roots) {
3991
3992 if (r->id == Vcb->options.subvol_id)
3993 return r;
3994
3995 le = le->Flink;
3996 }
3997 }
3998
3999 if (Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_DEFAULT_SUBVOL) {
4001 KEY searchkey;
4003 DIR_ITEM* di;
4004
4005 searchkey.obj_id = Vcb->superblock.root_dir_objectid;
4006 searchkey.obj_type = TYPE_DIR_ITEM;
4007 searchkey.offset = crc32;
4008
4009 Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
4010 if (!NT_SUCCESS(Status)) {
4011 ERR("error - find_item returned %08lx\n", Status);
4012 goto end;
4013 }
4014
4015 if (keycmp(tp.item->key, searchkey)) {
4016 ERR("could not find (%I64x,%x,%I64x) in root tree\n", searchkey.obj_id, searchkey.obj_type, searchkey.offset);
4017 goto end;
4018 }
4019
4020 if (tp.item->size < sizeof(DIR_ITEM)) {
4021 ERR("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(DIR_ITEM));
4022 goto end;
4023 }
4024
4025 di = (DIR_ITEM*)tp.item->data;
4026
4027 if (tp.item->size < sizeof(DIR_ITEM) - 1 + di->n) {
4028 ERR("(%I64x,%x,%I64x) was %u bytes, expected %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(DIR_ITEM) - 1 + di->n);
4029 goto end;
4030 }
4031
4032 if (di->n != strlen(fn) || RtlCompareMemory(di->name, fn, di->n) != di->n) {
4033 ERR("root DIR_ITEM had same CRC32, but was not \"default\"\n");
4034 goto end;
4035 }
4036
4037 if (di->key.obj_type != TYPE_ROOT_ITEM) {
4038 ERR("default root has key (%I64x,%x,%I64x), expected subvolume\n", di->key.obj_id, di->key.obj_type, di->key.offset);
4039 goto end;
4040 }
4041
4042 le = Vcb->roots.Flink;
4043 while (le != &Vcb->roots) {
4045
4046 if (r->id == di->key.obj_id)
4047 return r;
4048
4049 le = le->Flink;
4050 }
4051
4052 ERR("could not find root %I64x, using default instead\n", di->key.obj_id);
4053 }
4054
4055end:
4056 le = Vcb->roots.Flink;
4057 while (le != &Vcb->roots) {
4059
4060 if (r->id == BTRFS_ROOT_FSTREE)
4061 return r;
4062
4063 le = le->Flink;
4064 }
4065
4066 return NULL;
4067}
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define BTRFS_INCOMPAT_FLAGS_DEFAULT_SUBVOL
Definition: btrfs.h:116
#define BTRFS_ROOT_FSTREE
Definition: btrfs.h:58
#define TYPE_DIR_ITEM
Definition: btrfs.h:28
char name[1]
Definition: btrfs.h:278
uint16_t n
Definition: btrfs.h:276
KEY key
Definition: btrfs.h:273

Referenced by load_dir_children(), and mount_vol().

◆ find_device_from_uuid()

_Ret_maybenull_ device * find_device_from_uuid ( _In_ device_extension Vcb,
_In_ BTRFS_UUID uuid 
)

Definition at line 3299 of file btrfs.c.

3299 {
3301 pdo_device_extension* pdode;
3302 LIST_ENTRY* le;
3303
3304 le = Vcb->devices.Flink;
3305 while (le != &Vcb->devices) {
3307
3308 TRACE("device %I64x, uuid %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n", dev->devitem.dev_id,
3309 dev->devitem.device_uuid.uuid[0], dev->devitem.device_uuid.uuid[1], dev->devitem.device_uuid.uuid[2], dev->devitem.device_uuid.uuid[3], dev->devitem.device_uuid.uuid[4], dev->devitem.device_uuid.uuid[5], dev->devitem.device_uuid.uuid[6], dev->devitem.device_uuid.uuid[7],
3310 dev->devitem.device_uuid.uuid[8], dev->devitem.device_uuid.uuid[9], dev->devitem.device_uuid.uuid[10], dev->devitem.device_uuid.uuid[11], dev->devitem.device_uuid.uuid[12], dev->devitem.device_uuid.uuid[13], dev->devitem.device_uuid.uuid[14], dev->devitem.device_uuid.uuid[15]);
3311
3312 if (RtlCompareMemory(&dev->devitem.device_uuid, uuid, sizeof(BTRFS_UUID)) == sizeof(BTRFS_UUID)) {
3313 TRACE("returning device %I64x\n", dev->devitem.dev_id);
3314 return dev;
3315 }
3316
3317 le = le->Flink;
3318 }
3319
3320 vde = Vcb->vde;
3321
3322 if (!vde)
3323 goto end;
3324
3325 pdode = vde->pdode;
3326
3328
3329 if (Vcb->devices_loaded < Vcb->superblock.num_devices) {
3330 le = pdode->children.Flink;
3331
3332 while (le != &pdode->children) {
3334
3335 if (RtlCompareMemory(uuid, &vc->uuid, sizeof(BTRFS_UUID)) == sizeof(BTRFS_UUID)) {
3336 device* dev;
3337
3339 if (!dev) {
3341 ERR("out of memory\n");
3342 return NULL;
3343 }
3344
3345 RtlZeroMemory(dev, sizeof(device));
3346 dev->devobj = vc->devobj;
3347 dev->fileobj = vc->fileobj;
3348 dev->devitem.device_uuid = *uuid;
3349 dev->devitem.dev_id = vc->devid;
3350 dev->devitem.num_bytes = vc->size;
3351 dev->seeding = vc->seeding;
3352 dev->readonly = dev->seeding;
3353 dev->reloc = false;
3354 dev->removable = false;
3355 dev->disk_num = vc->disk_num;
3356 dev->part_num = vc->part_num;
3357 dev->num_trim_entries = 0;
3358 InitializeListHead(&dev->trim_list);
3359
3361 Vcb->devices_loaded++;
3362
3364
3365 return dev;
3366 }
3367
3368 le = le->Flink;
3369 }
3370 }
3371
3373
3374end:
3375 WARN("could not find device with uuid %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
3376 uuid->uuid[0], uuid->uuid[1], uuid->uuid[2], uuid->uuid[3], uuid->uuid[4], uuid->uuid[5], uuid->uuid[6], uuid->uuid[7],
3377 uuid->uuid[8], uuid->uuid[9], uuid->uuid[10], uuid->uuid[11], uuid->uuid[12], uuid->uuid[13], uuid->uuid[14], uuid->uuid[15]);
3378
3379 return NULL;
3380}
static void add_device_to_list(_In_ device_extension *Vcb, _In_ device *dev)
Definition: btrfs.c:3279
Definition: msctf.idl:550
struct pdo_device_extension * pdode
Definition: btrfs_drv.h:878
uint64_t dev_id

Referenced by load_chunk_root(), and read_data().

◆ find_extent_shared_data_refcount()

uint32_t find_extent_shared_data_refcount ( device_extension Vcb,
uint64_t  address,
uint64_t  parent,
PIRP  Irp 
)

Definition at line 2220 of file extent-tree.c.

2220 {
2222 KEY searchkey;
2224 uint64_t inline_rc;
2225 EXTENT_ITEM* ei;
2226 uint32_t len;
2227 uint8_t* ptr;
2228
2229 searchkey.obj_id = address;
2230 searchkey.obj_type = Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA ? TYPE_METADATA_ITEM : TYPE_EXTENT_ITEM;
2231 searchkey.offset = 0xffffffffffffffff;
2232
2233 Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, Irp);
2234 if (!NT_SUCCESS(Status)) {
2235 ERR("error - find_item returned %08lx\n", Status);
2236 return 0;
2237 }
2238
2240 TRACE("could not find address %I64x in extent tree\n", address);
2241 return 0;
2242 }
2243
2244 if (tp.item->size < sizeof(EXTENT_ITEM)) {
2245 ERR("(%I64x,%x,%I64x): size was %u, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(EXTENT_ITEM));
2246 return 0;
2247 }
2248
2249 ei = (EXTENT_ITEM*)tp.item->data;
2250 inline_rc = 0;
2251
2252 len = tp.item->size - sizeof(EXTENT_ITEM);
2253 ptr = (uint8_t*)&ei[1];
2254
2255 while (len > 0) {
2256 uint8_t secttype = *ptr;
2257 ULONG sectlen = get_extent_data_len(secttype);
2258 uint64_t sectcount = get_extent_data_refcount(secttype, ptr + sizeof(uint8_t));
2259
2260 len--;
2261
2262 if (sectlen > len) {
2263 ERR("(%I64x,%x,%I64x): %x bytes left, expecting at least %lx\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, len, sectlen);
2264 return 0;
2265 }
2266
2267 if (sectlen == 0) {
2268 ERR("(%I64x,%x,%I64x): unrecognized extent type %x\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, secttype);
2269 return 0;
2270 }
2271
2272 if (secttype == TYPE_SHARED_DATA_REF) {
2273 SHARED_DATA_REF* sectsdr = (SHARED_DATA_REF*)(ptr + sizeof(uint8_t));
2274
2275 if (sectsdr->offset == parent)
2276 return sectsdr->count;
2277 }
2278
2279 len -= sectlen;
2280 ptr += sizeof(uint8_t) + sectlen;
2281 inline_rc += sectcount;
2282 }
2283
2284 // FIXME - what if old?
2285
2286 if (inline_rc == ei->refcount)
2287 return 0;
2288
2289 searchkey.obj_id = address;
2290 searchkey.obj_type = TYPE_SHARED_DATA_REF;
2291 searchkey.offset = parent;
2292
2293 Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, Irp);
2294 if (!NT_SUCCESS(Status)) {
2295 ERR("error - find_item returned %08lx\n", Status);
2296 return 0;
2297 }
2298
2299 if (!keycmp(searchkey, tp.item->key)) {
2300 if (tp.item->size < sizeof(uint32_t))
2301 ERR("(%I64x,%x,%I64x) has size %u, not %Iu as expected\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(uint32_t));
2302 else {
2304 return *count;
2305 }
2306 }
2307
2308 return 0;
2309}

Referenced by add_metadata_reloc_extent_item(), and update_tree_extents().

◆ find_extent_shared_tree_refcount()

uint64_t find_extent_shared_tree_refcount ( device_extension Vcb,
uint64_t  address,
uint64_t  parent,
PIRP  Irp 
)

Definition at line 2119 of file extent-tree.c.

2119 {
2121 KEY searchkey;
2123 uint64_t inline_rc;
2124 EXTENT_ITEM* ei;
2125 uint32_t len;
2126 uint8_t* ptr;
2127
2128 searchkey.obj_id = address;
2129 searchkey.obj_type = Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA ? TYPE_METADATA_ITEM : TYPE_EXTENT_ITEM;
2130 searchkey.offset = 0xffffffffffffffff;
2131
2132 Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, Irp);
2133 if (!NT_SUCCESS(Status)) {
2134 ERR("error - find_item returned %08lx\n", Status);
2135 return 0;
2136 }
2137
2139 TRACE("could not find address %I64x in extent tree\n", address);
2140 return 0;
2141 }
2142
2143 if (tp.item->key.obj_type == TYPE_EXTENT_ITEM && tp.item->key.offset != Vcb->superblock.node_size) {
2144 ERR("extent %I64x had size %I64x, not %x as expected\n", address, tp.item->key.offset, Vcb->superblock.node_size);
2145 return 0;
2146 }
2147
2148 if (tp.item->size < sizeof(EXTENT_ITEM)) {
2149 ERR("(%I64x,%x,%I64x): size was %u, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(EXTENT_ITEM));
2150 return 0;
2151 }
2152
2153 ei = (EXTENT_ITEM*)tp.item->data;
2154 inline_rc = 0;
2155
2156 len = tp.item->size - sizeof(EXTENT_ITEM);
2157 ptr = (uint8_t*)&ei[1];
2158
2159 if (searchkey.obj_type == TYPE_EXTENT_ITEM && ei->flags & EXTENT_ITEM_TREE_BLOCK) {
2160 if (tp.item->size < sizeof(EXTENT_ITEM) + sizeof(EXTENT_ITEM2)) {
2161 ERR("(%I64x,%x,%I64x): size was %u, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset,
2162 tp.item->size, sizeof(EXTENT_ITEM) + sizeof(EXTENT_ITEM2));
2163 return 0;
2164 }
2165
2166 len -= sizeof(EXTENT_ITEM2);
2167 ptr += sizeof(EXTENT_ITEM2);
2168 }
2169
2170 while (len > 0) {
2171 uint8_t secttype = *ptr;
2172 ULONG sectlen = get_extent_data_len(secttype);
2173 uint64_t sectcount = get_extent_data_refcount(secttype, ptr + sizeof(uint8_t));
2174
2175 len--;
2176
2177 if (sectlen > len) {
2178 ERR("(%I64x,%x,%I64x): %x bytes left, expecting at least %lx\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, len, sectlen);
2179 return 0;
2180 }
2181
2182 if (sectlen == 0) {
2183 ERR("(%I64x,%x,%I64x): unrecognized extent type %x\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, secttype);
2184 return 0;
2185 }
2186
2187 if (secttype == TYPE_SHARED_BLOCK_REF) {
2188 SHARED_BLOCK_REF* sectsbr = (SHARED_BLOCK_REF*)(ptr + sizeof(uint8_t));
2189
2190 if (sectsbr->offset == parent)
2191 return 1;
2192 }
2193
2194 len -= sectlen;
2195 ptr += sizeof(uint8_t) + sectlen;
2196 inline_rc += sectcount;
2197 }
2198
2199 // FIXME - what if old?
2200
2201 if (inline_rc == ei->refcount)
2202 return 0;
2203
2204 searchkey.obj_id = address;
2205 searchkey.obj_type = TYPE_SHARED_BLOCK_REF;
2206 searchkey.offset = parent;
2207
2208 Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, Irp);
2209 if (!NT_SUCCESS(Status)) {
2210 ERR("error - find_item returned %08lx\n", Status);
2211 return 0;
2212 }
2213
2214 if (!keycmp(searchkey, tp.item->key))
2215 return 1;
2216
2217 return 0;
2218}

Referenced by add_metadata_reloc_extent_item(), and update_tree_extents().

◆ find_file_in_dir()

NTSTATUS find_file_in_dir ( PUNICODE_STRING  filename,
fcb fcb,
root **  subvol,
uint64_t inode,
dir_child **  pdc,
bool  case_sensitive 
)

Definition at line 182 of file create.c.

182 {
184 UNICODE_STRING fnus;
186 LIST_ENTRY* le;
187 uint8_t c;
188 bool locked = false;
189
190 if (!case_sensitive) {
191 Status = RtlUpcaseUnicodeString(&fnus, filename, true);
192
193 if (!NT_SUCCESS(Status)) {
194 ERR("RtlUpcaseUnicodeString returned %08lx\n", Status);
195 return Status;
196 }
197 } else
198 fnus = *filename;
199
200 Status = check_file_name_valid(filename, false, false);
201 if (!NT_SUCCESS(Status))
202 return Status;
203
204 hash = calc_crc32c(0xffffffff, (uint8_t*)fnus.Buffer, fnus.Length);
205
206 c = hash >> 24;
207
208 if (!ExIsResourceAcquiredSharedLite(&fcb->nonpaged->dir_children_lock)) {
209 ExAcquireResourceSharedLite(&fcb->nonpaged->dir_children_lock, true);
210 locked = true;
211 }
212
213 if (case_sensitive) {
214 if (!fcb->hash_ptrs[c]) {
216 goto end;
217 }
218
219 le = fcb->hash_ptrs[c];
220 while (le != &fcb->dir_children_hash) {
221 dir_child* dc = CONTAINING_RECORD(le, dir_child, list_entry_hash);
222
223 if (dc->hash == hash) {
224 if (dc->name.Length == fnus.Length && RtlCompareMemory(dc->name.Buffer, fnus.Buffer, fnus.Length) == fnus.Length) {
225 if (dc->key.obj_type == TYPE_ROOT_ITEM) {
226 LIST_ENTRY* le2;
227
228 *subvol = NULL;
229
230 le2 = fcb->Vcb->roots.Flink;
231 while (le2 != &fcb->Vcb->roots) {
233
234 if (r2->id == dc->key.obj_id) {
235 *subvol = r2;
236 break;
237 }
238
239 le2 = le2->Flink;
240 }
241
243 } else {
244 *subvol = fcb->subvol;
245 *inode = dc->key.obj_id;
246 }
247
248 *pdc = dc;
249
251 goto end;
252 }
253 } else if (dc->hash > hash) {
255 goto end;
256 }
257
258 le = le->Flink;
259 }
260 } else {
261 if (!fcb->hash_ptrs_uc[c]) {
263 goto end;
264 }
265
266 le = fcb->hash_ptrs_uc[c];
267 while (le != &fcb->dir_children_hash_uc) {
268 dir_child* dc = CONTAINING_RECORD(le, dir_child, list_entry_hash_uc);
269
270 if (dc->hash_uc == hash) {
271 if (dc->name_uc.Length == fnus.Length && RtlCompareMemory(dc->name_uc.Buffer, fnus.Buffer, fnus.Length) == fnus.Length) {
272 if (dc->key.obj_type == TYPE_ROOT_ITEM) {
273 LIST_ENTRY* le2;
274
275 *subvol = NULL;
276
277 le2 = fcb->Vcb->roots.Flink;
278 while (le2 != &fcb->Vcb->roots) {
280
281 if (r2->id == dc->key.obj_id) {
282 *subvol = r2;
283 break;
284 }
285
286 le2 = le2->Flink;
287 }
288
290 } else {
291 *subvol = fcb->subvol;
292 *inode = dc->key.obj_id;
293 }
294
295 *pdc = dc;
296
298 goto end;
299 }
300 } else if (dc->hash_uc > hash) {
302 goto end;
303 }
304
305 le = le->Flink;
306 }
307 }
308
310
311end:
312 if (locked)
313 ExReleaseResourceLite(&fcb->nonpaged->dir_children_lock);
314
315 if (!case_sensitive)
316 ExFreePool(fnus.Buffer);
317
318 return Status;
319}
NTSTATUS check_file_name_valid(_In_ PUNICODE_STRING us, _In_ bool posix, _In_ bool stream)
Definition: btrfs.c:5797
const char * filename
Definition: ioapi.h:137
static DNS_RECORDW r2
Definition: record.c:38
#define SUBVOL_ROOT_INODE
Definition: propsheet.cpp:42
LIST_ENTRY ** hash_ptrs_uc
Definition: btrfs_drv.h:318
LIST_ENTRY ** hash_ptrs
Definition: btrfs_drv.h:317
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149

Referenced by mknod(), and open_fileref_child().

◆ find_gid()

void find_gid ( struct _fcb fcb,
struct _fcb parfcb,
PSECURITY_SUBJECT_CONTEXT  subjcont 
)

Definition at line 924 of file security.c.

924 {
926 TOKEN_OWNER* to;
928 TOKEN_GROUPS* tg;
929
930 if (parfcb && parfcb->inode_item.st_mode & S_ISGID) {
932 return;
933 }
934
936
937 if (!subjcont || !subjcont->PrimaryToken || IsListEmpty(&gid_map_list)) {
939 return;
940 }
941
942 Status = SeQueryInformationToken(subjcont->PrimaryToken, TokenOwner, (void**)&to);
943 if (!NT_SUCCESS(Status))
944 ERR("SeQueryInformationToken returned %08lx\n", Status);
945 else {
946 if (search_for_gid(fcb, to->Owner)) {
948 ExFreePool(to);
949 return;
950 }
951
952 ExFreePool(to);
953 }
954
956 if (!NT_SUCCESS(Status))
957 ERR("SeQueryInformationToken returned %08lx\n", Status);
958 else {
959 if (search_for_gid(fcb, tpg->PrimaryGroup)) {
961 ExFreePool(tpg);
962 return;
963 }
964
965 ExFreePool(tpg);
966 }
967
968 Status = SeQueryInformationToken(subjcont->PrimaryToken, TokenGroups, (void**)&tg);
969 if (!NT_SUCCESS(Status))
970 ERR("SeQueryInformationToken returned %08lx\n", Status);
971 else {
972 ULONG i;
973
974 for (i = 0; i < tg->GroupCount; i++) {
975 if (search_for_gid(fcb, tg->Groups[i].Sid)) {
977 ExFreePool(tg);
978 return;
979 }
980 }
981
982 ExFreePool(tg);
983 }
984
986}
static bool search_for_gid(fcb *fcb, PSID sid)
Definition: security.c:906
ERESOURCE mapping_lock
Definition: btrfs.c:103
#define S_ISGID
Definition: propsheet.h:69
PACCESS_TOKEN PrimaryToken
Definition: setypes.h:220
SID_AND_ATTRIBUTES Groups[ANYSIZE_ARRAY]
Definition: setypes.h:1018
$ULONG GroupCount
Definition: setypes.h:1014
PSID Owner
Definition: setypes.h:1028
NTSTATUS NTAPI SeQueryInformationToken(_In_ PACCESS_TOKEN AccessToken, _In_ TOKEN_INFORMATION_CLASS TokenInformationClass, _Outptr_result_buffer_(_Inexpressible_(token-dependent)) PVOID *TokenInformation)
Queries information details about the given token to the call. The difference between NtQueryInformat...
Definition: tokencls.c:95
@ TokenGroups
Definition: setypes.h:967
@ TokenPrimaryGroup
Definition: setypes.h:970
@ TokenOwner
Definition: setypes.h:969

Referenced by create_directory_fcb(), create_subvol(), fcb_get_new_sd(), and mknod().

◆ find_item()

NTSTATUS find_item ( _In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension Vcb,
_In_ root r,
_Out_ traverse_ptr tp,
_In_ const KEY searchkey,
_In_ bool  ignore,
_In_opt_ PIRP  Irp 
)

◆ find_item_to_level()

NTSTATUS NTSTATUS find_item_to_level ( device_extension Vcb,
root r,
traverse_ptr tp,
const KEY searchkey,
bool  ignore,
uint8_t  level,
PIRP  Irp 
)

Referenced by write_metadata_items().

◆ find_metadata_address_in_chunk()

bool find_metadata_address_in_chunk ( device_extension Vcb,
chunk c,
uint64_t address 
)

Definition at line 744 of file flushthread.c.

744 {
745 LIST_ENTRY* le;
746 space* s;
747
748 TRACE("(%p, %I64x, %p)\n", Vcb, c->offset, address);
749
750 if (Vcb->superblock.node_size > c->chunk_item->size - c->used)
751 return false;
752
753 if (!c->cache_loaded) {
755
756 if (!NT_SUCCESS(Status)) {
757 ERR("load_cache_chunk returned %08lx\n", Status);
758 return false;
759 }
760 }
761
762 if (IsListEmpty(&c->space_size))
763 return false;
764
765 if (!c->last_alloc_set) {
766 s = CONTAINING_RECORD(c->space.Blink, space, list_entry);
767
768 c->last_alloc = s->address;
769 c->last_alloc_set = true;
770
771 if (s->size >= Vcb->superblock.node_size) {
772 *address = s->address;
773 c->last_alloc += Vcb->superblock.node_size;
774 return true;
775 }
776 }
777
778 le = c->space.Flink;
779 while (le != &c->space) {
781
782 if (s->address <= c->last_alloc && s->address + s->size >= c->last_alloc + Vcb->superblock.node_size) {
783 *address = c->last_alloc;
784 c->last_alloc += Vcb->superblock.node_size;
785 return true;
786 }
787
788 le = le->Flink;
789 }
790
791 le = c->space_size.Flink;
792 while (le != &c->space_size) {
793 s = CONTAINING_RECORD(le, space, list_entry_size);
794
795 if (s->size == Vcb->superblock.node_size) {
796 *address = s->address;
797 c->last_alloc = s->address + Vcb->superblock.node_size;
798 return true;
799 } else if (s->size < Vcb->superblock.node_size) {
800 if (le == c->space_size.Flink)
801 return false;
802
803 s = CONTAINING_RECORD(le->Blink, space, list_entry_size);
804
805 *address = s->address;
806 c->last_alloc = s->address + Vcb->superblock.node_size;
807
808 return true;
809 }
810
811 le = le->Flink;
812 }
813
814 s = CONTAINING_RECORD(c->space_size.Blink, space, list_entry_size);
815
816 if (s->size > Vcb->superblock.node_size) {
817 *address = s->address;
818 c->last_alloc = s->address + Vcb->superblock.node_size;
819 return true;
820 }
821
822 return false;
823}

Referenced by insert_tree_extent(), and write_metadata_items().

◆ find_next_item()

◆ find_prev_item()

NTSTATUS NTSTATUS bool bool find_prev_item ( _Requires_lock_held_(_Curr_->tree_lock) device_extension Vcb,
const traverse_ptr tp,
traverse_ptr prev_tp,
PIRP  Irp 
)

Referenced by get_last_inode().

◆ flush_fcb()

NTSTATUS flush_fcb ( fcb fcb,
bool  cache,
LIST_ENTRY batchlist,
PIRP  Irp 
)

Definition at line 4924 of file flushthread.c.

4924 {
4926 KEY searchkey;
4928 INODE_ITEM* ii;
4929 uint64_t ii_offset;
4930#ifdef DEBUG_PARANOID
4931 uint64_t old_size = 0;
4932 bool extents_changed;
4933#endif
4934
4935 if (fcb->ads) {
4936 if (fcb->deleted) {
4938 if (!NT_SUCCESS(Status)) {
4939 ERR("delete_xattr returned %08lx\n", Status);
4940 goto end;
4941 }
4942 } else {
4945 if (!NT_SUCCESS(Status)) {
4946 ERR("set_xattr returned %08lx\n", Status);
4947 goto end;
4948 }
4949 }
4950
4952 goto end;
4953 }
4954
4955 if (fcb->deleted) {
4956 Status = insert_tree_item_batch(batchlist, fcb->Vcb, fcb->subvol, fcb->inode, TYPE_INODE_ITEM, 0xffffffffffffffff, NULL, 0, Batch_DeleteInode);
4957 if (!NT_SUCCESS(Status)) {
4958 ERR("insert_tree_item_batch returned %08lx\n", Status);
4959 goto end;
4960 }
4961
4962 if (fcb->marked_as_orphan) {
4964 fcb->inode, NULL, 0, Batch_Delete);
4965 if (!NT_SUCCESS(Status)) {
4966 ERR("insert_tree_item_batch returned %08lx\n", Status);
4967 goto end;
4968 }
4969 }
4970
4972 goto end;
4973 }
4974
4975#ifdef DEBUG_PARANOID
4976 extents_changed = fcb->extents_changed;
4977#endif
4978
4979 if (fcb->extents_changed) {
4980 LIST_ENTRY* le;
4981 bool prealloc = false, extents_inline = false;
4982 uint64_t last_end;
4983
4984 // delete ignored extent items
4985 le = fcb->extents.Flink;
4986 while (le != &fcb->extents) {
4987 LIST_ENTRY* le2 = le->Flink;
4989
4990 if (ext->ignore) {
4991 RemoveEntryList(&ext->list_entry);
4992
4993 if (ext->csum)
4994 ExFreePool(ext->csum);
4995
4996 ExFreePool(ext);
4997 }
4998
4999 le = le2;
5000 }
5001
5002 le = fcb->extents.Flink;
5003 while (le != &fcb->extents) {
5005
5006 if (ext->inserted && ext->csum && ext->extent_data.type == EXTENT_TYPE_REGULAR) {
5007 EXTENT_DATA2* ed2 = (EXTENT_DATA2*)ext->extent_data.data;
5008
5009 if (ed2->size > 0) { // not sparse
5010 if (ext->extent_data.compression == BTRFS_COMPRESSION_NONE)
5011 add_checksum_entry(fcb->Vcb, ed2->address + ed2->offset, (ULONG)(ed2->num_bytes >> fcb->Vcb->sector_shift), ext->csum, Irp);
5012 else
5013 add_checksum_entry(fcb->Vcb, ed2->address, (ULONG)(ed2->size >> fcb->Vcb->sector_shift), ext->csum, Irp);
5014 }
5015 }
5016
5017 le = le->Flink;
5018 }
5019
5020 if (!IsListEmpty(&fcb->extents)) {
5022
5023 // merge together adjacent EXTENT_DATAs pointing to same extent
5024
5025 le = fcb->extents.Flink;
5026 while (le != &fcb->extents) {
5027 LIST_ENTRY* le2 = le->Flink;
5029
5030 if ((ext->extent_data.type == EXTENT_TYPE_REGULAR || ext->extent_data.type == EXTENT_TYPE_PREALLOC) && le->Flink != &fcb->extents) {
5032
5033 if (ext->extent_data.type == nextext->extent_data.type) {
5034 EXTENT_DATA2* ed2 = (EXTENT_DATA2*)ext->extent_data.data;
5035 EXTENT_DATA2* ned2 = (EXTENT_DATA2*)nextext->extent_data.data;
5036
5037 if (ed2->size != 0 && ed2->address == ned2->address && ed2->size == ned2->size &&
5038 nextext->offset == ext->offset + ed2->num_bytes && ned2->offset == ed2->offset + ed2->num_bytes) {
5039 chunk* c;
5040
5041 if (ext->extent_data.compression == BTRFS_COMPRESSION_NONE && ext->csum) {
5042 ULONG len = (ULONG)((ed2->num_bytes + ned2->num_bytes) >> fcb->Vcb->sector_shift);
5043 void* csum;
5044
5046 if (!csum) {
5047 ERR("out of memory\n");
5049 goto end;
5050 }
5051
5052 RtlCopyMemory(csum, ext->csum, (ULONG)((ed2->num_bytes * fcb->Vcb->csum_size) >> fcb->Vcb->sector_shift));
5053 RtlCopyMemory((uint8_t*)csum + ((ed2->num_bytes * fcb->Vcb->csum_size) >> fcb->Vcb->sector_shift), nextext->csum,
5054 (ULONG)((ned2->num_bytes * fcb->Vcb->csum_size) >> fcb->Vcb->sector_shift));
5055
5056 ExFreePool(ext->csum);
5057 ext->csum = csum;
5058 }
5059
5060 ext->extent_data.generation = fcb->Vcb->superblock.generation;
5061 ed2->num_bytes += ned2->num_bytes;
5062
5063 RemoveEntryList(&nextext->list_entry);
5064
5065 if (nextext->csum)
5066 ExFreePool(nextext->csum);
5067
5068 ExFreePool(nextext);
5069
5071
5072 if (!c) {
5073 ERR("get_chunk_from_address(%I64x) failed\n", ed2->address);
5074 } else {
5075 Status = update_changed_extent_ref(fcb->Vcb, c, ed2->address, ed2->size, fcb->subvol->id, fcb->inode, ext->offset - ed2->offset, -1,
5077 if (!NT_SUCCESS(Status)) {
5078 ERR("update_changed_extent_ref returned %08lx\n", Status);
5079 goto end;
5080 }
5081 }
5082
5083 le2 = le;
5084 }
5085 }
5086 }
5087
5088 le = le2;
5089 }
5090 }
5091
5092 if (!fcb->created) {
5093 // delete existing EXTENT_DATA items
5094
5096 if (!NT_SUCCESS(Status)) {
5097 ERR("insert_tree_item_batch returned %08lx\n", Status);
5098 goto end;
5099 }
5100 }
5101
5102 // add new EXTENT_DATAs
5103
5104 last_end = 0;
5105
5106 le = fcb->extents.Flink;
5107 while (le != &fcb->extents) {
5109 EXTENT_DATA* ed;
5110
5111 ext->inserted = false;
5112
5113 if (!(fcb->Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_NO_HOLES) && ext->offset > last_end) {
5114 Status = insert_sparse_extent(fcb, batchlist, last_end, ext->offset - last_end);
5115 if (!NT_SUCCESS(Status)) {
5116 ERR("insert_sparse_extent returned %08lx\n", Status);
5117 goto end;
5118 }
5119 }
5120
5122 if (!ed) {
5123 ERR("out of memory\n");
5125 goto end;
5126 }
5127
5128 RtlCopyMemory(ed, &ext->extent_data, ext->datalen);
5129
5131 ed, ext->datalen, Batch_Insert);
5132 if (!NT_SUCCESS(Status)) {
5133 ERR("insert_tree_item_batch returned %08lx\n", Status);
5134 goto end;
5135 }
5136
5137 if (ed->type == EXTENT_TYPE_PREALLOC)
5138 prealloc = true;
5139
5140 if (ed->type == EXTENT_TYPE_INLINE)
5141 extents_inline = true;
5142
5143 if (!(fcb->Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_NO_HOLES)) {
5144 if (ed->type == EXTENT_TYPE_INLINE)
5145 last_end = ext->offset + ed->decoded_size;
5146 else {
5147 EXTENT_DATA2* ed2 = (EXTENT_DATA2*)ed->data;
5148
5149 last_end = ext->offset + ed2->num_bytes;
5150 }
5151 }
5152
5153 le = le->Flink;
5154 }
5155
5156 if (!(fcb->Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_NO_HOLES) && !extents_inline &&
5157 sector_align(fcb->inode_item.st_size, fcb->Vcb->superblock.sector_size) > last_end) {
5158 Status = insert_sparse_extent(fcb, batchlist, last_end, sector_align(fcb->inode_item.st_size, fcb->Vcb->superblock.sector_size) - last_end);
5159 if (!NT_SUCCESS(Status)) {
5160 ERR("insert_sparse_extent returned %08lx\n", Status);
5161 goto end;
5162 }
5163 }
5164
5165 // update prealloc flag in INODE_ITEM
5166
5167 if (!prealloc)
5168 fcb->inode_item.flags &= ~BTRFS_INODE_PREALLOC;
5169 else
5171
5172 fcb->inode_item_changed = true;
5173
5174 fcb->extents_changed = false;
5175 }
5176
5177 if ((!fcb->created && fcb->inode_item_changed) || cache) {
5178 searchkey.obj_id = fcb->inode;
5179 searchkey.obj_type = TYPE_INODE_ITEM;
5180 searchkey.offset = 0xffffffffffffffff;
5181
5182 Status = find_item(fcb->Vcb, fcb->subvol, &tp, &searchkey, false, Irp);
5183 if (!NT_SUCCESS(Status)) {
5184 ERR("error - find_item returned %08lx\n", Status);
5185 goto end;
5186 }
5187
5188 if (tp.item->key.obj_id != searchkey.obj_id || tp.item->key.obj_type != searchkey.obj_type) {
5189 if (cache) {
5191 if (!ii) {
5192 ERR("out of memory\n");
5194 goto end;
5195 }
5196
5197 RtlCopyMemory(ii, &fcb->inode_item, sizeof(INODE_ITEM));
5198
5200 if (!NT_SUCCESS(Status)) {
5201 ERR("insert_tree_item returned %08lx\n", Status);
5202 goto end;
5203 }
5204
5205 ii_offset = 0;
5206 } else {
5207 ERR("could not find INODE_ITEM for inode %I64x in subvol %I64x\n", fcb->inode, fcb->subvol->id);
5209 goto end;
5210 }
5211 } else {
5212#ifdef DEBUG_PARANOID
5213 INODE_ITEM* ii2 = (INODE_ITEM*)tp.item->data;
5214
5215 old_size = ii2->st_size;
5216#endif
5217
5218 ii_offset = tp.item->key.offset;
5219 }
5220
5221 if (!cache) {
5223 if (!NT_SUCCESS(Status)) {
5224 ERR("delete_tree_item returned %08lx\n", Status);
5225 goto end;
5226 }
5227 } else {
5228 searchkey.obj_id = fcb->inode;
5229 searchkey.obj_type = TYPE_INODE_ITEM;
5230 searchkey.offset = ii_offset;
5231
5232 Status = find_item(fcb->Vcb, fcb->subvol, &tp, &searchkey, false, Irp);
5233 if (!NT_SUCCESS(Status)) {
5234 ERR("error - find_item returned %08lx\n", Status);
5235 goto end;
5236 }
5237
5238 if (keycmp(tp.item->key, searchkey)) {
5239 ERR("could not find INODE_ITEM for inode %I64x in subvol %I64x\n", fcb->inode, fcb->subvol->id);
5241 goto end;
5242 } else
5244 }
5245
5246#ifdef DEBUG_PARANOID
5247 if (!extents_changed && fcb->type != BTRFS_TYPE_DIRECTORY && old_size != fcb->inode_item.st_size) {
5248 ERR("error - size has changed but extents not marked as changed\n");
5249 int3;
5250 }
5251#endif
5252 } else
5253 ii_offset = 0;
5254
5255 fcb->created = false;
5256
5257 if (!cache && fcb->inode_item_changed) {
5259 if (!ii) {
5260 ERR("out of memory\n");
5262 goto end;
5263 }
5264
5265 RtlCopyMemory(ii, &fcb->inode_item, sizeof(INODE_ITEM));
5266
5267 Status = insert_tree_item_batch(batchlist, fcb->Vcb, fcb->subvol, fcb->inode, TYPE_INODE_ITEM, ii_offset, ii, sizeof(INODE_ITEM),
5268 Batch_Insert);
5269 if (!NT_SUCCESS(Status)) {
5270 ERR("insert_tree_item_batch returned %08lx\n", Status);
5271 goto end;
5272 }
5273
5274 fcb->inode_item_changed = false;
5275 }
5276
5277 if (fcb->sd_dirty) {
5278 if (!fcb->sd_deleted) {
5279 Status = set_xattr(fcb->Vcb, batchlist, fcb->subvol, fcb->inode, EA_NTACL, sizeof(EA_NTACL) - 1,
5281 if (!NT_SUCCESS(Status)) {
5282 ERR("set_xattr returned %08lx\n", Status);
5283 goto end;
5284 }
5285 } else {
5286 Status = delete_xattr(fcb->Vcb, batchlist, fcb->subvol, fcb->inode, EA_NTACL, sizeof(EA_NTACL) - 1, EA_NTACL_HASH);
5287 if (!NT_SUCCESS(Status)) {
5288 ERR("delete_xattr returned %08lx\n", Status);
5289 goto end;
5290 }
5291 }
5292
5293 fcb->sd_deleted = false;
5294 fcb->sd_dirty = false;
5295 }
5296
5297 if (fcb->atts_changed) {
5298 if (!fcb->atts_deleted) {
5299 uint8_t val[16], *val2;
5300 ULONG atts = fcb->atts;
5301
5302 TRACE("inserting new DOSATTRIB xattr\n");
5303
5304 if (fcb->inode == SUBVOL_ROOT_INODE)
5305 atts &= ~FILE_ATTRIBUTE_READONLY;
5306
5307 val2 = &val[sizeof(val) - 1];
5308
5309 do {
5310 uint8_t c = atts % 16;
5311 *val2 = c <= 9 ? (c + '0') : (c - 0xa + 'a');
5312
5313 val2--;
5314 atts >>= 4;
5315 } while (atts != 0);
5316
5317 *val2 = 'x';
5318 val2--;
5319 *val2 = '0';
5320
5321 Status = set_xattr(fcb->Vcb, batchlist, fcb->subvol, fcb->inode, EA_DOSATTRIB, sizeof(EA_DOSATTRIB) - 1,
5322 EA_DOSATTRIB_HASH, val2, (uint16_t)(val + sizeof(val) - val2));
5323 if (!NT_SUCCESS(Status)) {
5324 ERR("set_xattr returned %08lx\n", Status);
5325 goto end;
5326 }
5327 } else {
5329 if (!NT_SUCCESS(Status)) {
5330 ERR("delete_xattr returned %08lx\n", Status);
5331 goto end;
5332 }
5333 }
5334
5335 fcb->atts_changed = false;
5336 fcb->atts_deleted = false;
5337 }
5338
5341 Status = set_xattr(fcb->Vcb, batchlist, fcb->subvol, fcb->inode, EA_REPARSE, sizeof(EA_REPARSE) - 1,
5343 if (!NT_SUCCESS(Status)) {
5344 ERR("set_xattr returned %08lx\n", Status);
5345 goto end;
5346 }
5347 } else {
5348 Status = delete_xattr(fcb->Vcb, batchlist, fcb->subvol, fcb->inode, EA_REPARSE, sizeof(EA_REPARSE) - 1, EA_REPARSE_HASH);
5349 if (!NT_SUCCESS(Status)) {
5350 ERR("delete_xattr returned %08lx\n", Status);
5351 goto end;
5352 }
5353 }
5354
5355 fcb->reparse_xattr_changed = false;
5356 }
5357
5358 if (fcb->ea_changed) {
5359 if (fcb->ea_xattr.Buffer && fcb->ea_xattr.Length > 0) {
5360 Status = set_xattr(fcb->Vcb, batchlist, fcb->subvol, fcb->inode, EA_EA, sizeof(EA_EA) - 1,
5362 if (!NT_SUCCESS(Status)) {
5363 ERR("set_xattr returned %08lx\n", Status);
5364 goto end;
5365 }
5366 } else {
5367 Status = delete_xattr(fcb->Vcb, batchlist, fcb->subvol, fcb->inode, EA_EA, sizeof(EA_EA) - 1, EA_EA_HASH);
5368 if (!NT_SUCCESS(Status)) {
5369 ERR("delete_xattr returned %08lx\n", Status);
5370 goto end;
5371 }
5372 }
5373
5374 fcb->ea_changed = false;
5375 }
5376
5380 if (!NT_SUCCESS(Status)) {
5381 ERR("delete_xattr returned %08lx\n", Status);
5382 goto end;
5383 }
5384 } else if (fcb->prop_compression == PropCompression_Zlib) {
5385 static const char zlib[] = "zlib";
5386
5388 EA_PROP_COMPRESSION_HASH, (uint8_t*)zlib, sizeof(zlib) - 1);
5389 if (!NT_SUCCESS(Status)) {
5390 ERR("set_xattr returned %08lx\n", Status);
5391 goto end;
5392 }
5393 } else if (fcb->prop_compression == PropCompression_LZO) {
5394 static const char lzo[] = "lzo";
5395
5397 EA_PROP_COMPRESSION_HASH, (uint8_t*)lzo, sizeof(lzo) - 1);
5398 if (!NT_SUCCESS(Status)) {
5399 ERR("set_xattr returned %08lx\n", Status);
5400 goto end;
5401 }
5402 } else if (fcb->prop_compression == PropCompression_ZSTD) {
5403 static const char zstd[] = "zstd";
5404
5406 EA_PROP_COMPRESSION_HASH, (uint8_t*)zstd, sizeof(zstd) - 1);
5407 if (!NT_SUCCESS(Status)) {
5408 ERR("set_xattr returned %08lx\n", Status);
5409 goto end;
5410 }
5411 }
5412
5414 }
5415
5416 if (fcb->xattrs_changed) {
5417 LIST_ENTRY* le;
5418
5419 le = fcb->xattrs.Flink;
5420 while (le != &fcb->xattrs) {
5422 LIST_ENTRY* le2 = le->Flink;
5423
5424 if (xa->dirty) {
5425 uint32_t hash = calc_crc32c(0xfffffffe, (uint8_t*)xa->data, xa->namelen);
5426
5427 if (xa->valuelen == 0) {
5428 Status = delete_xattr(fcb->Vcb, batchlist, fcb->subvol, fcb->inode, xa->data, xa->namelen, hash);
5429 if (!NT_SUCCESS(Status)) {
5430 ERR("delete_xattr returned %08lx\n", Status);
5431 goto end;
5432 }
5433
5435 ExFreePool(xa);
5436 } else {
5437 Status = set_xattr(fcb->Vcb, batchlist, fcb->subvol, fcb->inode, xa->data, xa->namelen,
5438 hash, (uint8_t*)&xa->data[xa->namelen], xa->valuelen);
5439 if (!NT_SUCCESS(Status)) {
5440 ERR("set_xattr returned %08lx\n", Status);
5441 goto end;
5442 }
5443
5444 xa->dirty = false;
5445 }
5446 }
5447
5448 le = le2;
5449 }
5450
5451 fcb->xattrs_changed = false;
5452 }
5453
5457 if (!NT_SUCCESS(Status)) {
5458 ERR("delete_xattr returned %08lx\n", Status);
5459 goto end;
5460 }
5461
5462 fcb->case_sensitive_set = false;
5463 } else if ((!fcb->case_sensitive_set && fcb->case_sensitive)) {
5465 sizeof(EA_CASE_SENSITIVE) - 1, EA_CASE_SENSITIVE_HASH, (uint8_t*)"1", 1);
5466 if (!NT_SUCCESS(Status)) {
5467 ERR("set_xattr returned %08lx\n", Status);
5468 goto end;
5469 }
5470
5471 fcb->case_sensitive_set = true;
5472 }
5473
5474 if (fcb->inode_item.st_nlink == 0 && !fcb->marked_as_orphan) { // mark as orphan
5476 fcb->inode, NULL, 0, Batch_Insert);
5477 if (!NT_SUCCESS(Status)) {
5478 ERR("insert_tree_item_batch returned %08lx\n", Status);
5479 goto end;
5480 }
5481
5482 fcb->marked_as_orphan = true;
5483 }
5484
5486
5487end:
5488 if (fcb->dirty) {
5489 bool lock = false;
5490
5491 fcb->dirty = false;
5492
5493 if (!ExIsResourceAcquiredExclusiveLite(&fcb->Vcb->dirty_fcbs_lock)) {
5494 ExAcquireResourceExclusiveLite(&fcb->Vcb->dirty_fcbs_lock, true);
5495 lock = true;
5496 }
5497
5499
5500 if (lock)
5501 ExReleaseResourceLite(&fcb->Vcb->dirty_fcbs_lock);
5502 }
5503
5504 return Status;
5505}
#define EA_CASE_SENSITIVE
Definition: btrfs_drv.h:105
#define EA_EA
Definition: btrfs_drv.h:102
#define EA_EA_HASH
Definition: btrfs_drv.h:103
#define EA_PROP_COMPRESSION_HASH
Definition: btrfs_drv.h:109
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool prealloc
Definition: btrfs_drv.h:1364
#define EA_DOSATTRIB_HASH
Definition: btrfs_drv.h:97
#define EA_REPARSE_HASH
Definition: btrfs_drv.h:100
_In_ uint16_t _Out_ ULONG * atts
Definition: btrfs_drv.h:1107
#define EA_REPARSE
Definition: btrfs_drv.h:99
#define EA_PROP_COMPRESSION
Definition: btrfs_drv.h:108
#define EA_DOSATTRIB
Definition: btrfs_drv.h:96
#define EA_CASE_SENSITIVE_HASH
Definition: btrfs_drv.h:106
NTSTATUS update_changed_extent_ref(device_extension *Vcb, chunk *c, uint64_t address, uint64_t size, uint64_t root, uint64_t objid, uint64_t offset, int32_t count, bool no_csum, bool superseded, PIRP Irp)
Definition: extent-tree.c:1951
#define int3
Definition: btrfs_drv.h:1745
#define TYPE_EXTENT_DATA
Definition: btrfs.h:30
#define EXTENT_TYPE_PREALLOC
Definition: btrfs.h:76
#define TYPE_ORPHAN_INODE
Definition: btrfs.h:27
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:75
#define BTRFS_COMPRESSION_NONE
Definition: btrfs.h:65
#define BTRFS_INCOMPAT_FLAGS_NO_HOLES
Definition: btrfs.h:124
#define BTRFS_ORPHAN_INODE_OBJID
Definition: btrfs.h:130
static NTSTATUS insert_sparse_extent(fcb *fcb, LIST_ENTRY *batchlist, uint64_t start, uint64_t length)
Definition: flushthread.c:4402
static void rationalize_extents(fcb *fcb, PIRP Irp)
Definition: flushthread.c:4629
static 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)
Definition: flushthread.c:4517
static NTSTATUS set_xattr(device_extension *Vcb, LIST_ENTRY *batchlist, root *subvol, uint64_t inode, char *name, uint16_t namelen, uint32_t crc32, uint8_t *data, uint16_t datalen)
Definition: flushthread.c:4331
static NTSTATUS delete_xattr(device_extension *Vcb, LIST_ENTRY *batchlist, root *subvol, uint64_t inode, char *name, uint16_t namelen, uint32_t crc32)
Definition: flushthread.c:4367
void add_checksum_entry(device_extension *Vcb, uint64_t address, ULONG length, void *csum, PIRP Irp)
Definition: flushthread.c:2602
NTSYSAPI ULONG WINAPI RtlLengthSecurityDescriptor(PSECURITY_DESCRIPTOR)
BOOLEAN NTAPI ExIsResourceAcquiredExclusiveLite(IN PERESOURCE Resource)
Definition: resource.c:1624
#define BTRFS_INODE_PREALLOC
Definition: propsheet.h:80
#define BTRFS_INODE_NODATASUM
Definition: propsheet.h:76
uint64_t num_bytes
Definition: btrfs.h:371
uint64_t address
Definition: btrfs.h:368
uint64_t size
Definition: btrfs.h:369
uint64_t offset
Definition: btrfs.h:370
uint8_t data[1]
Definition: btrfs.h:364
uint8_t type
Definition: btrfs.h:363
uint64_t decoded_size
Definition: btrfs.h:359
uint32_t st_nlink
Definition: btrfs.h:292
uint32_t flags
Definition: btrfs.h:297
bool marked_as_orphan
Definition: btrfs_drv.h:309
bool case_sensitive_set
Definition: btrfs_drv.h:311
bool atts_deleted
Definition: btrfs_drv.h:322
bool sd_dirty
Definition: btrfs_drv.h:321
bool case_sensitive
Definition: btrfs_drv.h:310
ANSI_STRING adsxattr
Definition: btrfs_drv.h:333
bool created
Definition: btrfs_drv.h:328
bool dirty
Definition: btrfs_drv.h:320
bool xattrs_changed
Definition: btrfs_drv.h:327
bool sd_deleted
Definition: btrfs_drv.h:321
uint32_t adshash
Definition: btrfs_drv.h:331
bool extents_changed
Definition: btrfs_drv.h:323
enum prop_compression_type prop_compression
Definition: btrfs_drv.h:307
bool ea_changed
Definition: btrfs_drv.h:325
LIST_ENTRY list_entry_dirty
Definition: btrfs_drv.h:338
ANSI_STRING ea_xattr
Definition: btrfs_drv.h:302
bool prop_compression_changed
Definition: btrfs_drv.h:326
Definition: cache.c:49
LIST_ENTRY list_entry
Definition: btrfs_drv.h:235
EXTENT_DATA extent_data
Definition: btrfs_drv.h:237
uint64_t offset
Definition: btrfs_drv.h:228
void * csum
Definition: btrfs_drv.h:233
bool dirty
Definition: btrfs_drv.h:278
USHORT namelen
Definition: btrfs_drv.h:276
char data[1]
Definition: btrfs_drv.h:279
USHORT valuelen
Definition: btrfs_drv.h:277
LIST_ENTRY list_entry
Definition: btrfs_drv.h:275
rwlock_t lock
Definition: tcpcore.h:0

Referenced by allocate_cache_chunk(), do_write2(), drop_chunk(), remove_free_space_inode(), update_chunk_cache(), and update_chunk_usage().

◆ flush_partial_stripe()

NTSTATUS flush_partial_stripe ( device_extension Vcb,
chunk c,
partial_stripe ps 
)

Definition at line 5958 of file flushthread.c.

5958 {
5960 uint16_t parity2, stripe, startoffstripe;
5961 uint8_t* data;
5962 uint64_t startoff;
5963 ULONG runlength, index, last1;
5964 CHUNK_ITEM_STRIPE* cis = (CHUNK_ITEM_STRIPE*)&c->chunk_item[1];
5965 LIST_ENTRY* le;
5966 uint16_t k, num_data_stripes = c->chunk_item->num_stripes - (c->chunk_item->type & BLOCK_FLAG_RAID5 ? 1 : 2);
5967 uint64_t ps_length = num_data_stripes * c->chunk_item->stripe_length;
5968 ULONG stripe_length = (ULONG)c->chunk_item->stripe_length;
5969
5970 // FIXME - do writes asynchronously?
5971
5972 get_raid0_offset(ps->address - c->offset, stripe_length, num_data_stripes, &startoff, &startoffstripe);
5973
5974 parity2 = (((ps->address - c->offset) / ps_length) + c->chunk_item->num_stripes - 1) % c->chunk_item->num_stripes;
5975
5976 // read data (or reconstruct if degraded)
5977
5978 runlength = RtlFindFirstRunClear(&ps->bmp, &index);
5979 last1 = 0;
5980
5981 while (runlength != 0) {
5982 if (index >= ps->bmplen)
5983 break;
5984
5985 if (index + runlength >= ps->bmplen) {
5986 runlength = ps->bmplen - index;
5987
5988 if (runlength == 0)
5989 break;
5990 }
5991
5992 if (index > last1) {
5993 Status = partial_stripe_read(Vcb, c, ps, startoff, parity2, last1, index - last1);
5994 if (!NT_SUCCESS(Status)) {
5995 ERR("partial_stripe_read returned %08lx\n", Status);
5996 return Status;
5997 }
5998 }
5999
6000 last1 = index + runlength;
6001
6002 runlength = RtlFindNextForwardRunClear(&ps->bmp, index + runlength, &index);
6003 }
6004
6005 if (last1 < ps_length >> Vcb->sector_shift) {
6006 Status = partial_stripe_read(Vcb, c, ps, startoff, parity2, last1, (ULONG)((ps_length >> Vcb->sector_shift) - last1));
6007 if (!NT_SUCCESS(Status)) {
6008 ERR("partial_stripe_read returned %08lx\n", Status);
6009 return Status;
6010 }
6011 }
6012
6013 // set unallocated data to 0
6014 le = c->space.Flink;
6015 while (le != &c->space) {
6017
6018 if (s->address + s->size > ps->address && s->address < ps->address + ps_length) {
6019 uint64_t start = max(ps->address, s->address);
6020 uint64_t end = min(ps->address + ps_length, s->address + s->size);
6021
6022 RtlZeroMemory(ps->data + start - ps->address, (ULONG)(end - start));
6023 } else if (s->address >= ps->address + ps_length)
6024 break;
6025
6026 le = le->Flink;
6027 }
6028
6029 le = c->deleting.Flink;
6030 while (le != &c->deleting) {
6032
6033 if (s->address + s->size > ps->address && s->address < ps->address + ps_length) {
6034 uint64_t start = max(ps->address, s->address);
6035 uint64_t end = min(ps->address + ps_length, s->address + s->size);
6036
6037 RtlZeroMemory(ps->data + start - ps->address, (ULONG)(end - start));
6038 } else if (s->address >= ps->address + ps_length)
6039 break;
6040
6041 le = le->Flink;
6042 }
6043
6044 stripe = (parity2 + 1) % c->chunk_item->num_stripes;
6045
6046 data = ps->data;
6047 for (k = 0; k < num_data_stripes; k++) {
6048 if (c->devices[stripe]->devobj) {
6049 Status = write_data_phys(c->devices[stripe]->devobj, c->devices[stripe]->fileobj, cis[stripe].offset + startoff, data, stripe_length);
6050 if (!NT_SUCCESS(Status)) {
6051 ERR("write_data_phys returned %08lx\n", Status);
6052 return Status;
6053 }
6054 }
6055
6056 data += stripe_length;
6057 stripe = (stripe + 1) % c->chunk_item->num_stripes;
6058 }
6059
6060 // write parity
6061 if (c->chunk_item->type & BLOCK_FLAG_RAID5) {
6062 if (c->devices[parity2]->devobj) {
6063 uint16_t i;
6064
6065 for (i = 1; i < c->chunk_item->num_stripes - 1; i++) {
6066 do_xor(ps->data, ps->data + (i * stripe_length), stripe_length);
6067 }
6068
6069 Status = write_data_phys(c->devices[parity2]->devobj, c->devices[parity2]->fileobj, cis[parity2].offset + startoff, ps->data, stripe_length);
6070 if (!NT_SUCCESS(Status)) {
6071 ERR("write_data_phys returned %08lx\n", Status);
6072 return Status;
6073 }
6074 }
6075 } else {
6076 uint16_t parity1 = (parity2 + c->chunk_item->num_stripes - 1) % c->chunk_item->num_stripes;
6077
6078 if (c->devices[parity1]->devobj || c->devices[parity2]->devobj) {
6079 uint8_t* scratch;
6080 uint16_t i;
6081
6082 scratch = ExAllocatePoolWithTag(NonPagedPool, stripe_length * 2, ALLOC_TAG);
6083 if (!scratch) {
6084 ERR("out of memory\n");
6086 }
6087
6088 i = c->chunk_item->num_stripes - 3;
6089
6090 while (true) {
6091 if (i == c->chunk_item->num_stripes - 3) {
6092 RtlCopyMemory(scratch, ps->data + (i * stripe_length), stripe_length);
6093 RtlCopyMemory(scratch + stripe_length, ps->data + (i * stripe_length), stripe_length);
6094 } else {
6095 do_xor(scratch, ps->data + (i * stripe_length), stripe_length);
6096
6097 galois_double(scratch + stripe_length, stripe_length);
6098 do_xor(scratch + stripe_length, ps->data + (i * stripe_length), stripe_length);
6099 }
6100
6101 if (i == 0)
6102 break;
6103
6104 i--;
6105 }
6106
6107 if (c->devices[parity1]->devobj) {
6108 Status = write_data_phys(c->devices[parity1]->devobj, c->devices[parity1]->fileobj, cis[parity1].offset + startoff, scratch, stripe_length);
6109 if (!NT_SUCCESS(Status)) {
6110 ERR("write_data_phys returned %08lx\n", Status);
6111 ExFreePool(scratch);
6112 return Status;
6113 }
6114 }
6115
6116 if (c->devices[parity2]->devobj) {
6117 Status = write_data_phys(c->devices[parity2]->devobj, c->devices[parity2]->fileobj, cis[parity2].offset + startoff,
6118 scratch + stripe_length, stripe_length);
6119 if (!NT_SUCCESS(Status)) {
6120 ERR("write_data_phys returned %08lx\n", Status);
6121 ExFreePool(scratch);
6122 return Status;
6123 }
6124 }
6125
6126 ExFreePool(scratch);
6127 }
6128 }
6129
6130 return STATUS_SUCCESS;
6131}
_Post_satisfies_ static stripe __inline void get_raid0_offset(_In_ uint64_t off, _In_ uint64_t stripe_length, _In_ uint16_t num_stripes, _Out_ uint64_t *stripeoff, _Out_ uint16_t *stripe)
Definition: btrfs_drv.h:997
void galois_double(uint8_t *data, uint32_t len)
Definition: galois.c:109
xor_func do_xor
Definition: btrfs.c:127
NTSTATUS write_data_phys(_In_ PDEVICE_OBJECT device, _In_ PFILE_OBJECT fileobj, _In_ uint64_t address, _In_reads_bytes_(length) void *data, _In_ uint32_t length)
Definition: flushthread.c:70
static NTSTATUS partial_stripe_read(device_extension *Vcb, chunk *c, partial_stripe *ps, uint64_t startoff, uint16_t parity, ULONG offset, ULONG len)
Definition: flushthread.c:5833
#define for
Definition: utility.h:88
int k
Definition: mpi.c:3369
uint64_t address
Definition: btrfs_drv.h:553
uint8_t data[1]
Definition: btrfs_drv.h:558
RTL_BITMAP bmp
Definition: btrfs_drv.h:556

Referenced by __attribute__(), do_tree_writes(), update_chunk_caches(), and update_chunks().

◆ flush_subvol_fcbs()

void flush_subvol_fcbs ( root subvol)

Definition at line 243 of file fsctl.c.

243 {
244 LIST_ENTRY* le = subvol->fcbs.Flink;
245
246 if (IsListEmpty(&subvol->fcbs))
247 return;
248
249 while (le != &subvol->fcbs) {
250 struct _fcb* fcb = CONTAINING_RECORD(le, struct _fcb, list_entry);
252
254 CcFlushCache(&fcb->nonpaged->segment_object, NULL, 0, &iosb);
255
256 le = le->Flink;
257 }
258}
VOID NTAPI CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, OUT OPTIONAL PIO_STATUS_BLOCK IoStatus)
Definition: cachesub.c:222
LIST_ENTRY fcbs
Definition: btrfs_drv.h:464

Referenced by _Function_class_(), and do_create_snapshot().

◆ free_fcb()

void free_fcb ( _Inout_ fcb fcb)

Definition at line 1734 of file btrfs.c.

1734 {
1736#endif
1737
1738#ifdef DEBUG_FCB_REFCOUNTS
1739 ERR("fcb %p (%s): refcount now %i (subvol %I64x, inode %I64x)\n", fcb, func, rc, fcb->subvol ? fcb->subvol->id : 0, fcb->inode);
1740#endif
1741}
GLenum func
Definition: glext.h:6028

Referenced by allocate_cache_chunk(), check_for_orphans_root(), close_file(), create_stream(), do_write2(), drop_chunk(), duplicate_fcb(), file_create2(), get_reparse_tag(), load_stored_free_space_cache(), mount_vol(), move_across_subvols(), open_fileref_by_inode(), open_fileref_child(), reap_fileref(), remove_free_space_inode(), rename_stream(), rename_stream_to_file(), and update_chunk_usage().

◆ free_fileref()

void free_fileref ( _Inout_ file_ref fr)

Definition at line 1856 of file btrfs.c.

1856 {
1857#if defined(_DEBUG) || defined(DEBUG_FCB_REFCOUNTS)
1858 LONG rc = InterlockedDecrement(&fr->refcount);
1859
1860#ifdef DEBUG_FCB_REFCOUNTS
1861 ERR("fileref %p: refcount now %i\n", fr, rc);
1862#endif
1863
1864#ifdef _DEBUG
1865 if (rc < 0) {
1866 ERR("fileref %p: refcount now %li\n", fr, rc);
1867 int3;
1868 }
1869#endif
1870#else
1871 InterlockedDecrement(&fr->refcount);
1872#endif
1873}
long LONG
Definition: pedump.c:60

Referenced by _Function_class_(), close_file(), create_snapshot(), create_stream(), create_subvol(), do_create_snapshot(), do_write2(), file_create(), fill_in_hard_link_full_id_information(), fill_in_hard_link_information(), get_subvol_path(), mknod(), mount_vol(), move_across_subvols(), open_file(), open_file2(), open_fileref(), open_fileref_by_inode(), oplock_complete(), reap_fileref(), rename_file_to_stream(), rename_stream(), rename_stream_to_file(), send_notification_fcb(), set_link_information(), and set_rename_information().

◆ free_tree()

NTSTATUS NTSTATUS void free_tree ( tree t)

◆ free_trees()

◆ free_trees_root()

void void free_trees_root ( device_extension Vcb,
root r 
)

Referenced by drop_root().

◆ free_vol()

void free_vol ( volume_device_extension vde)

Definition at line 50 of file volume.c.

50 {
52
53 vde->dead = true;
54
55 if (vde->mounted_device) {
57
58 Vcb->vde = NULL;
59 }
60
61 if (vde->name.Buffer)
63
64 ExDeleteResourceLite(&vde->pdode->child_lock);
65
66 if (vde->pdo->AttachedDevice)
67 IoDetachDevice(vde->pdo);
68
69 while (!IsListEmpty(&vde->pdode->children)) {
71
72 if (vc->notification_entry) {
75 else
77 }
78
79 if (vc->pnp_name.Buffer)
81
82 ExFreePool(vc);
83 }
84
85 if (no_pnp)
86 ExFreePool(vde->pdode);
87
88 pdo = vde->pdo;
90
91 if (!no_pnp)
92 IoDeleteDevice(pdo);
93}
tIoUnregisterPlugPlayNotificationEx fIoUnregisterPlugPlayNotificationEx
Definition: btrfs.c:95
#define ExDeleteResourceLite(res)
Definition: env_spec_w32.h:647
PDEVICE_OBJECT pdo
Definition: btrfs_drv.h:877

Referenced by do_shutdown(), and vol_close().

◆ free_write_data_stripes()

NTSTATUS NTSTATUS NTSTATUS void free_write_data_stripes ( write_data_context wtc)

◆ fsctl_request()

NTSTATUS fsctl_request ( PDEVICE_OBJECT  DeviceObject,
PIRP Pirp,
uint32_t  type 
)

Definition at line 5345 of file fsctl.c.

5345 {
5346 PIRP Irp = *Pirp;
5349
5350 if (IrpSp->FileObject && IrpSp->FileObject->FsContext) {
5351 device_extension* Vcb = DeviceObject->DeviceExtension;
5352
5353 if (Vcb->type == VCB_TYPE_FS)
5355 }
5356
5357 switch (type) {
5366#if (NTDDI_VERSION >= NTDDI_WIN7)
5367 case FSCTL_REQUEST_OPLOCK:
5368#endif
5369 Status = fsctl_oplock(DeviceObject->DeviceExtension, Pirp);
5370 break;
5371
5372 case FSCTL_LOCK_VOLUME:
5373 Status = lock_volume(DeviceObject->DeviceExtension, Irp);
5374 break;
5375
5377 Status = unlock_volume(DeviceObject->DeviceExtension, Irp);
5378 break;
5379
5381 Status = dismount_volume(DeviceObject->DeviceExtension, false, Irp);
5382 break;
5383
5385 Status = is_volume_mounted(DeviceObject->DeviceExtension, Irp);
5386 break;
5387
5389 WARN("STUB: FSCTL_IS_PATHNAME_VALID\n");
5391 break;
5392
5394 WARN("STUB: FSCTL_MARK_VOLUME_DIRTY\n");
5396 break;
5397
5399 WARN("STUB: FSCTL_QUERY_RETRIEVAL_POINTERS\n");
5401 break;
5402
5405 break;
5406
5409 break;
5410
5412 WARN("STUB: FSCTL_SET_BOOTLOADER_ACCESSED\n");
5414 break;
5415
5418 break;
5419
5421 WARN("STUB: FSCTL_QUERY_FAT_BPB\n");
5423 break;
5424
5426 Status = fs_get_statistics(Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.FileSystemControl.OutputBufferLength, &Irp->IoStatus.Information);
5427 break;
5428
5430 WARN("STUB: FSCTL_GET_NTFS_VOLUME_DATA\n");
5432 break;
5433
5435 WARN("STUB: FSCTL_GET_NTFS_FILE_RECORD\n");
5437 break;
5438
5440 WARN("STUB: FSCTL_GET_VOLUME_BITMAP\n");
5442 break;
5443
5446 IrpSp->Parameters.FileSystemControl.Type3InputBuffer,
5447 IrpSp->Parameters.FileSystemControl.InputBufferLength,
5448 Irp->UserBuffer, IrpSp->Parameters.FileSystemControl.OutputBufferLength,
5449 &Irp->IoStatus.Information);
5450 break;
5451
5452 case FSCTL_MOVE_FILE:
5453 WARN("STUB: FSCTL_MOVE_FILE\n");
5455 break;
5456
5458 Status = is_volume_dirty(DeviceObject->DeviceExtension, Irp);
5459 break;
5460
5463 break;
5464
5466 WARN("STUB: FSCTL_FIND_FILES_BY_SID\n");
5468 break;
5469
5471 WARN("STUB: FSCTL_SET_OBJECT_ID\n");
5473 break;
5474
5476 Status = get_object_id(IrpSp->FileObject, Irp->UserBuffer, IrpSp->Parameters.FileSystemControl.OutputBufferLength,
5477 &Irp->IoStatus.Information);
5478 break;
5479
5481 WARN("STUB: FSCTL_DELETE_OBJECT_ID\n");
5483 break;
5484
5487 break;
5488
5490 Status = get_reparse_point(IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer,
5491 IrpSp->Parameters.FileSystemControl.OutputBufferLength, &Irp->IoStatus.Information);
5492 break;
5493
5496 break;
5497
5499 WARN("STUB: FSCTL_ENUM_USN_DATA\n");
5501 break;
5502
5504 WARN("STUB: FSCTL_SECURITY_ID_CHECK\n");
5506 break;
5507
5509 WARN("STUB: FSCTL_READ_USN_JOURNAL\n");
5511 break;
5512
5514 WARN("STUB: FSCTL_SET_OBJECT_ID_EXTENDED\n");
5516 break;
5517
5519 Status = get_object_id(IrpSp->FileObject, Irp->UserBuffer, IrpSp->Parameters.FileSystemControl.OutputBufferLength,
5520 &Irp->IoStatus.Information);
5521 break;
5522
5523 case FSCTL_SET_SPARSE:
5524 Status = set_sparse(DeviceObject->DeviceExtension, IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer,
5525 IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp);
5526 break;
5527
5529 Status = set_zero_data(DeviceObject->DeviceExtension, IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer,
5530 IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp);
5531 break;
5532
5534 Status = query_ranges(IrpSp->FileObject, IrpSp->Parameters.FileSystemControl.Type3InputBuffer,
5535 IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp->UserBuffer,
5536 IrpSp->Parameters.FileSystemControl.OutputBufferLength, &Irp->IoStatus.Information);
5537 break;
5538
5540 WARN("STUB: FSCTL_ENABLE_UPGRADE\n");
5542 break;
5543
5545 WARN("STUB: FSCTL_SET_ENCRYPTION\n");
5547 break;
5548
5550 WARN("STUB: FSCTL_ENCRYPTION_FSCTL_IO\n");
5552 break;
5553
5555 WARN("STUB: FSCTL_WRITE_RAW_ENCRYPTED\n");
5557 break;
5558
5560 WARN("STUB: FSCTL_READ_RAW_ENCRYPTED\n");
5562 break;
5563
5565 WARN("STUB: FSCTL_CREATE_USN_JOURNAL\n");
5567 break;
5568
5570 WARN("STUB: FSCTL_READ_FILE_USN_DATA\n");
5572 break;
5573
5575 WARN("STUB: FSCTL_WRITE_USN_CLOSE_RECORD\n");
5577 break;
5578
5580 WARN("STUB: FSCTL_EXTEND_VOLUME\n");
5582 break;
5583
5585 WARN("STUB: FSCTL_QUERY_USN_JOURNAL\n");
5587 break;
5588
5590 WARN("STUB: FSCTL_DELETE_USN_JOURNAL\n");
5592 break;
5593
5594 case FSCTL_MARK_HANDLE:
5595 WARN("STUB: FSCTL_MARK_HANDLE\n");
5597 break;
5598
5599 case FSCTL_SIS_COPYFILE:
5600 WARN("STUB: FSCTL_SIS_COPYFILE\n");
5602 break;
5603
5605 WARN("STUB: FSCTL_SIS_LINK_FILES\n");
5607 break;
5608
5609 case FSCTL_RECALL_FILE:
5610 WARN("STUB: FSCTL_RECALL_FILE\n");
5612 break;
5613
5615 WARN("STUB: FSCTL_READ_FROM_PLEX\n");
5617 break;
5618
5620 WARN("STUB: FSCTL_FILE_PREFETCH\n");
5622 break;
5623
5624#if _WIN32_WINNT >= 0x0600
5626 WARN("STUB: FSCTL_MAKE_MEDIA_COMPATIBLE\n");
5628 break;
5629
5631 WARN("STUB: FSCTL_SET_DEFECT_MANAGEMENT\n");
5633 break;
5634
5636 WARN("STUB: FSCTL_QUERY_SPARING_INFO\n");
5638 break;
5639
5641 WARN("STUB: FSCTL_QUERY_ON_DISK_VOLUME_INFO\n");
5643 break;
5644
5646 WARN("STUB: FSCTL_SET_VOLUME_COMPRESSION_STATE\n");
5648 break;
5649
5651 WARN("STUB: FSCTL_TXFS_MODIFY_RM\n");
5653 break;
5654
5656 WARN("STUB: FSCTL_TXFS_QUERY_RM_INFORMATION\n");
5658 break;
5659
5661 WARN("STUB: FSCTL_TXFS_ROLLFORWARD_REDO\n");
5663 break;
5664
5666 WARN("STUB: FSCTL_TXFS_ROLLFORWARD_UNDO\n");
5668 break;
5669
5671 WARN("STUB: FSCTL_TXFS_START_RM\n");
5673 break;
5674
5676 WARN("STUB: FSCTL_TXFS_SHUTDOWN_RM\n");
5678 break;
5679
5681 WARN("STUB: FSCTL_TXFS_READ_BACKUP_INFORMATION\n");
5683 break;
5684
5686 WARN("STUB: FSCTL_TXFS_WRITE_BACKUP_INFORMATION\n");
5688 break;
5689
5691 WARN("STUB: FSCTL_TXFS_CREATE_SECONDARY_RM\n");
5693 break;
5694
5696 WARN("STUB: FSCTL_TXFS_GET_METADATA_INFO\n");
5698 break;
5699
5701 WARN("STUB: FSCTL_TXFS_GET_TRANSACTED_VERSION\n");
5703 break;
5704
5705 case FSCTL_TXFS_SAVEPOINT_INFORMATION:
5706 WARN("STUB: FSCTL_TXFS_SAVEPOINT_INFORMATION\n");
5708 break;
5709
5711 WARN("STUB: FSCTL_TXFS_CREATE_MINIVERSION\n");
5713 break;
5714
5716 WARN("STUB: FSCTL_TXFS_TRANSACTION_ACTIVE\n");
5718 break;
5719
5721 WARN("STUB: FSCTL_SET_ZERO_ON_DEALLOCATION\n");
5723 break;
5724
5725 case FSCTL_SET_REPAIR:
5726 WARN("STUB: FSCTL_SET_REPAIR\n");
5728 break;
5729
5730 case FSCTL_GET_REPAIR:
5731 WARN("STUB: FSCTL_GET_REPAIR\n");
5733 break;
5734
5736 WARN("STUB: FSCTL_WAIT_FOR_REPAIR\n");
5738 break;
5739
5741 WARN("STUB: FSCTL_INITIATE_REPAIR\n");
5743 break;
5744
5745 case FSCTL_CSC_INTERNAL:
5746 WARN("STUB: FSCTL_CSC_INTERNAL\n");
5748 break;
5749
5751 WARN("STUB: FSCTL_SHRINK_VOLUME\n");
5753 break;
5754
5756 WARN("STUB: FSCTL_SET_SHORT_NAME_BEHAVIOR\n");
5758 break;
5759
5761 WARN("STUB: FSCTL_DFSR_SET_GHOST_HANDLE_STATE\n");
5763 break;
5764
5766 WARN("STUB: FSCTL_TXFS_LIST_TRANSACTION_LOCKED_FILES\n");
5768 break;
5769
5771 WARN("STUB: FSCTL_TXFS_LIST_TRANSACTIONS\n");
5773 break;
5774
5776 WARN("STUB: FSCTL_QUERY_PAGEFILE_ENCRYPTION\n");
5778 break;
5779
5780 case FSCTL_RESET_VOLUME_ALLOCATION_HINTS:
5781 WARN("STUB: FSCTL_RESET_VOLUME_ALLOCATION_HINTS\n");
5783 break;
5784
5785 case FSCTL_TXFS_READ_BACKUP_INFORMATION2:
5786 WARN("STUB: FSCTL_TXFS_READ_BACKUP_INFORMATION2\n");
5788 break;
5789
5790 case FSCTL_CSV_CONTROL:
5791 WARN("STUB: FSCTL_CSV_CONTROL\n");
5793 break;
5794#endif
5795 // TRACE rather than WARN because Windows 10 spams this undocumented fsctl
5797 TRACE("STUB: FSCTL_QUERY_VOLUME_CONTAINER_STATE\n");
5799 break;
5800
5803 IrpSp->Parameters.FileSystemControl.OutputBufferLength);
5804 break;
5805
5807 Status = set_integrity_information(IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.FileSystemControl.InputBufferLength);
5808 break;
5809
5811 Status = duplicate_extents(DeviceObject->DeviceExtension, IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer,
5812 IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp);
5813 break;
5814
5816 Status = get_file_ids(IrpSp->FileObject, map_user_buffer(Irp, NormalPagePriority), IrpSp->Parameters.FileSystemControl.OutputBufferLength);
5817 break;
5818
5820 Status = create_subvol(DeviceObject->DeviceExtension, IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp);
5821 break;
5822
5824 Status = create_snapshot(DeviceObject->DeviceExtension, IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp);
5825 break;
5826
5828 Status = get_inode_info(IrpSp->FileObject, map_user_buffer(Irp, NormalPagePriority), IrpSp->Parameters.FileSystemControl.OutputBufferLength);
5829 break;
5830
5832 Status = set_inode_info(IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp);
5833 break;
5834
5836 Status = get_devices(DeviceObject->DeviceExtension, map_user_buffer(Irp, NormalPagePriority), IrpSp->Parameters.FileSystemControl.OutputBufferLength);
5837 break;
5838
5840 Status = get_usage(DeviceObject->DeviceExtension, map_user_buffer(Irp, NormalPagePriority), IrpSp->Parameters.FileSystemControl.OutputBufferLength, Irp);
5841 break;
5842
5844 Status = start_balance(DeviceObject->DeviceExtension, Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp->RequestorMode);
5845 break;
5846
5848 Status = query_balance(DeviceObject->DeviceExtension, map_user_buffer(Irp, NormalPagePriority), IrpSp->Parameters.FileSystemControl.OutputBufferLength);
5849 break;
5850
5852 Status = pause_balance(DeviceObject->DeviceExtension, Irp->RequestorMode);
5853 break;
5854
5856 Status = resume_balance(DeviceObject->DeviceExtension, Irp->RequestorMode);
5857 break;
5858
5860 Status = stop_balance(DeviceObject->DeviceExtension, Irp->RequestorMode);
5861 break;
5862
5864 Status = add_device(DeviceObject->DeviceExtension, Irp, Irp->RequestorMode);
5865 break;
5866
5868 Status = remove_device(DeviceObject->DeviceExtension, Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp->RequestorMode);
5869 break;
5870
5872 Status = query_uuid(DeviceObject->DeviceExtension, map_user_buffer(Irp, NormalPagePriority), IrpSp->Parameters.FileSystemControl.OutputBufferLength);
5873 break;
5874
5876 Status = start_scrub(DeviceObject->DeviceExtension, Irp->RequestorMode);
5877 break;
5878
5880 Status = query_scrub(DeviceObject->DeviceExtension, Irp->RequestorMode, map_user_buffer(Irp, NormalPagePriority), IrpSp->Parameters.FileSystemControl.OutputBufferLength);
5881 break;
5882
5884 Status = pause_scrub(DeviceObject->DeviceExtension, Irp->RequestorMode);
5885 break;
5886
5888 Status = resume_scrub(DeviceObject->DeviceExtension, Irp->RequestorMode);
5889 break;
5890
5892 Status = stop_scrub(DeviceObject->DeviceExtension, Irp->RequestorMode);
5893 break;
5894
5896 Status = reset_stats(DeviceObject->DeviceExtension, Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp->RequestorMode);
5897 break;
5898
5899 case FSCTL_BTRFS_MKNOD:
5900 Status = mknod(DeviceObject->DeviceExtension, IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp);
5901 break;
5902
5904 Status = recvd_subvol(DeviceObject->DeviceExtension, IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer,
5905 IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp->RequestorMode);
5906 break;
5907
5909 Status = fsctl_get_xattrs(DeviceObject->DeviceExtension, IrpSp->FileObject, Irp->UserBuffer, IrpSp->Parameters.FileSystemControl.OutputBufferLength, Irp->RequestorMode);
5910 break;
5911
5913 Status = fsctl_set_xattr(DeviceObject->DeviceExtension, IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer,
5914 IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp);
5915 break;
5916
5918 Status = reserve_subvol(DeviceObject->DeviceExtension, IrpSp->FileObject, Irp);
5919 break;
5920
5922 Status = find_subvol(DeviceObject->DeviceExtension, Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.FileSystemControl.InputBufferLength,
5923 Irp->UserBuffer, IrpSp->Parameters.FileSystemControl.OutputBufferLength, Irp);
5924 break;
5925
5927 Status = send_subvol(DeviceObject->DeviceExtension, Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.FileSystemControl.InputBufferLength,
5928 IrpSp->FileObject, Irp);
5929 break;
5930
5932 Status = read_send_buffer(DeviceObject->DeviceExtension, IrpSp->FileObject, map_user_buffer(Irp, NormalPagePriority), IrpSp->Parameters.FileSystemControl.OutputBufferLength,
5933 &Irp->IoStatus.Information, Irp->RequestorMode);
5934 break;
5935
5936 case FSCTL_BTRFS_RESIZE:
5937 Status = resize_device(DeviceObject->DeviceExtension, Irp->AssociatedIrp.SystemBuffer,
5938 IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp);
5939 break;
5940
5942 Status = get_csum_info(DeviceObject->DeviceExtension, IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer,
5943 IrpSp->Parameters.FileSystemControl.OutputBufferLength, &Irp->IoStatus.Information,
5944 Irp->RequestorMode);
5945 break;
5946
5947 default:
5948 WARN("unknown control code %lx (DeviceType = %lx, Access = %lx, Function = %lx, Method = %lx)\n",
5949 IrpSp->Parameters.FileSystemControl.FsControlCode, (IrpSp->Parameters.FileSystemControl.FsControlCode & 0xff0000) >> 16,
5950 (IrpSp->Parameters.FileSystemControl.FsControlCode & 0xc000) >> 14, (IrpSp->Parameters.FileSystemControl.FsControlCode & 0x3ffc) >> 2,
5951 IrpSp->Parameters.FileSystemControl.FsControlCode & 0x3);
5953 break;
5954 }
5955
5956 return Status;
5957}
static NTSTATUS lock_volume(device_extension *Vcb, PIRP Irp)
Definition: fsctl.c:2237
static NTSTATUS get_compression(PIRP Irp)
Definition: fsctl.c:2518
static NTSTATUS get_csum_info(device_extension *Vcb, PFILE_OBJECT FileObject, btrfs_csum_info *buf, ULONG buflen, ULONG_PTR *retlen, KPROCESSOR_MODE processor_mode)
Definition: fsctl.c:5209
static NTSTATUS mknod(device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG datalen, PIRP Irp)
Definition: fsctl.c:3739
static NTSTATUS set_sparse(device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG length, PIRP Irp)
Definition: fsctl.c:1727
static NTSTATUS unlock_volume(device_extension *Vcb, PIRP Irp)
Definition: fsctl.c:2341
static NTSTATUS fs_get_statistics(void *buffer, DWORD buflen, ULONG_PTR *retlen)
Definition: fsctl.c:1705
static NTSTATUS set_zero_data(device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG length, PIRP Irp)
Definition: fsctl.c:1911
static NTSTATUS get_file_ids(PFILE_OBJECT FileObject, void *data, ULONG length)
Definition: fsctl.c:49
static NTSTATUS create_subvol(device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG datalen, PIRP Irp)
Definition: fsctl.c:746
static NTSTATUS find_subvol(device_extension *Vcb, void *in, ULONG inlen, void *out, ULONG outlen, PIRP Irp)
Definition: fsctl.c:4586
static NTSTATUS recvd_subvol(device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG datalen, KPROCESSOR_MODE processor_mode)
Definition: fsctl.c:4120
static NTSTATUS get_retrieval_pointers(device_extension *Vcb, PFILE_OBJECT FileObject, STARTING_VCN_INPUT_BUFFER *in, ULONG inlen, RETRIEVAL_POINTERS_BUFFER *out, ULONG outlen, ULONG_PTR *retlen)
Definition: fsctl.c:5008
static NTSTATUS reserve_subvol(device_extension *Vcb, PFILE_OBJECT FileObject, PIRP Irp)
Definition: fsctl.c:4506
static NTSTATUS get_integrity_information(device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG datalen)
Definition: fsctl.c:3210
static NTSTATUS query_uuid(device_extension *Vcb, void *data, ULONG length)
Definition: fsctl.c:3157
static NTSTATUS get_inode_info(PFILE_OBJECT FileObject, void *data, ULONG length)
Definition: fsctl.c:1162
static NTSTATUS invalidate_volumes(PIRP Irp)
Definition: fsctl.c:2358
static NTSTATUS get_object_id(PFILE_OBJECT FileObject, FILE_OBJECTID_BUFFER *buf, ULONG buflen, ULONG_PTR *retlen)
Definition: fsctl.c:2188
NTSTATUS dismount_volume(device_extension *Vcb, bool shutdown, PIRP Irp)
Definition: fsctl.c:2584
static NTSTATUS fsctl_get_xattrs(device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG datalen, KPROCESSOR_MODE processor_mode)
Definition: fsctl.c:4170
static NTSTATUS get_usage(device_extension *Vcb, void *data, ULONG length, PIRP Irp)
Definition: fsctl.c:1512
static NTSTATUS duplicate_extents(device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG datalen, PIRP Irp)
Definition: fsctl.c:3262
static NTSTATUS resize_device(device_extension *Vcb, void *data, ULONG len, PIRP Irp)
Definition: fsctl.c:4710
static NTSTATUS add_device(device_extension *Vcb, PIRP Irp, KPROCESSOR_MODE processor_mode)
Definition: fsctl.c:2735
#define FSCTL_QUERY_VOLUME_CONTAINER_STATE
Definition: fsctl.c:32
static NTSTATUS is_volume_dirty(device_extension *Vcb, PIRP Irp)
Definition: fsctl.c:2491
static NTSTATUS allow_extended_dasd_io(device_extension *Vcb, PFILE_OBJECT FileObject)
Definition: fsctl.c:3131
static NTSTATUS fsctl_oplock(device_extension *Vcb, PIRP *Pirp)
Definition: fsctl.c:4895
static NTSTATUS create_snapshot(device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG length, PIRP Irp)
Definition: fsctl.c:521
static NTSTATUS get_devices(device_extension *Vcb, void *data, ULONG length)
Definition: fsctl.c:1444
static NTSTATUS set_inode_info(PFILE_OBJECT FileObject, void *data, ULONG length, PIRP Irp)
Definition: fsctl.c:1323
static NTSTATUS set_integrity_information(PFILE_OBJECT FileObject, void *data, ULONG datalen)
Definition: fsctl.c:3232
static NTSTATUS is_volume_mounted(device_extension *Vcb, PIRP Irp)
Definition: fsctl.c:1662
static NTSTATUS query_ranges(PFILE_OBJECT FileObject, FILE_ALLOCATED_RANGE_BUFFER *inbuf, ULONG inbuflen, void *outbuf, ULONG outbuflen, ULONG_PTR *retlen)
Definition: fsctl.c:2089
static NTSTATUS set_compression(PIRP Irp)
Definition: fsctl.c:2544
#define FSCTL_CSV_CONTROL
Definition: fsctl.c:28
static NTSTATUS reset_stats(device_extension *Vcb, void *data, ULONG length, KPROCESSOR_MODE processor_mode)
Definition: fsctl.c:3166
static NTSTATUS fsctl_set_xattr(device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG datalen, PIRP Irp)
Definition: fsctl.c:4235
NTSTATUS stop_scrub(device_extension *Vcb, KPROCESSOR_MODE processor_mode)
Definition: scrub.c:3440
NTSTATUS pause_scrub(device_extension *Vcb, KPROCESSOR_MODE processor_mode)
Definition: scrub.c:3401
NTSTATUS get_reparse_point(PFILE_OBJECT FileObject, void *buffer, DWORD buflen, ULONG_PTR *retlen)
Definition: reparse.c:27
#define VCB_TYPE_FS
Definition: btrfs_drv.h:687
NTSTATUS query_scrub(device_extension *Vcb, KPROCESSOR_MODE processor_mode, void *data, ULONG length)
Definition: scrub.c:3301
NTSTATUS set_reparse_point(PIRP Irp)
Definition: reparse.c:409
NTSTATUS read_send_buffer(device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG datalen, ULONG_PTR *retlen, KPROCESSOR_MODE processor_mode)
Definition: send.c:3839
NTSTATUS delete_reparse_point(PIRP Irp)
Definition: reparse.c:482
NTSTATUS start_scrub(device_extension *Vcb, KPROCESSOR_MODE processor_mode)
Definition: scrub.c:3260
NTSTATUS resume_scrub(device_extension *Vcb, KPROCESSOR_MODE processor_mode)
Definition: scrub.c:3422
#define FSCTL_BTRFS_QUERY_SCRUB
Definition: btrfsioctl.h:24
#define FSCTL_BTRFS_CREATE_SNAPSHOT
Definition: btrfsioctl.h:9
#define FSCTL_BTRFS_SET_INODE_INFO
Definition: btrfsioctl.h:11
#define FSCTL_BTRFS_STOP_SCRUB
Definition: btrfsioctl.h:27
#define FSCTL_BTRFS_ADD_DEVICE
Definition: btrfsioctl.h:19
#define FSCTL_BTRFS_PAUSE_SCRUB
Definition: btrfsioctl.h:25
#define FSCTL_BTRFS_PAUSE_BALANCE
Definition: btrfsioctl.h:16
#define FSCTL_BTRFS_SEND_SUBVOL
Definition: btrfsioctl.h:36
#define FSCTL_BTRFS_SET_XATTR
Definition: btrfsioctl.h:33
#define FSCTL_BTRFS_RESERVE_SUBVOL
Definition: btrfsioctl.h:34
#define FSCTL_BTRFS_QUERY_BALANCE
Definition: btrfsioctl.h:15
#define FSCTL_BTRFS_GET_UUID
Definition: btrfsioctl.h:22
#define FSCTL_BTRFS_GET_XATTRS
Definition: btrfsioctl.h:32
#define FSCTL_BTRFS_RESUME_SCRUB
Definition: btrfsioctl.h:26
#define FSCTL_BTRFS_START_SCRUB
Definition: btrfsioctl.h:23
#define FSCTL_BTRFS_START_BALANCE
Definition: btrfsioctl.h:14
#define FSCTL_BTRFS_MKNOD
Definition: btrfsioctl.h:30
#define FSCTL_BTRFS_FIND_SUBVOL
Definition: btrfsioctl.h:35
#define FSCTL_BTRFS_RESIZE
Definition: btrfsioctl.h:38
#define FSCTL_BTRFS_RECEIVED_SUBVOL
Definition: btrfsioctl.h:31
#define FSCTL_BTRFS_RESUME_BALANCE
Definition: btrfsioctl.h:17
#define FSCTL_BTRFS_GET_INODE_INFO
Definition: btrfsioctl.h:10
#define FSCTL_BTRFS_REMOVE_DEVICE
Definition: btrfsioctl.h:20
#define FSCTL_BTRFS_GET_CSUM_INFO
Definition: btrfsioctl.h:40
#define FSCTL_BTRFS_GET_USAGE
Definition: btrfsioctl.h:13
#define FSCTL_BTRFS_STOP_BALANCE
Definition: btrfsioctl.h:18
#define FSCTL_BTRFS_GET_DEVICES
Definition: btrfsioctl.h:12
#define FSCTL_BTRFS_CREATE_SUBVOL
Definition: btrfsioctl.h:8
#define FSCTL_BTRFS_GET_FILE_IDS
Definition: btrfsioctl.h:7
#define FSCTL_BTRFS_RESET_STATS
Definition: btrfsioctl.h:29
#define FSCTL_BTRFS_READ_SEND_BUFFER
Definition: btrfsioctl.h:37
NTSTATUS query_balance(device_extension *Vcb, void *data, ULONG length)
Definition: balance.c:3711
NTSTATUS resume_balance(device_extension *Vcb, KPROCESSOR_MODE processor_mode)
Definition: balance.c:3765
NTSTATUS pause_balance(device_extension *Vcb, KPROCESSOR_MODE processor_mode)
Definition: balance.c:3749
NTSTATUS remove_device(device_extension *Vcb, void *data, ULONG length, KPROCESSOR_MODE processor_mode)
Definition: balance.c:3799
NTSTATUS stop_balance(device_extension *Vcb, KPROCESSOR_MODE processor_mode)
Definition: balance.c:3784
NTSTATUS start_balance(device_extension *Vcb, void *data, ULONG length, KPROCESSOR_MODE processor_mode)
Definition: balance.c:3511
#define FSCTL_QUERY_RETRIEVAL_POINTERS
Definition: nt_native.h:840
#define FSCTL_OPLOCK_BREAK_NOTIFY
Definition: nt_native.h:831
#define FSCTL_LOCK_VOLUME
Definition: nt_native.h:832
#define FSCTL_OPLOCK_BREAK_ACKNOWLEDGE
Definition: nt_native.h:829
#define FSCTL_REQUEST_OPLOCK_LEVEL_1
Definition: nt_native.h:826
#define FSCTL_REQUEST_FILTER_OPLOCK
Definition: nt_native.h:849
#define FSCTL_MARK_VOLUME_DIRTY
Definition: nt_native.h:838
#define FSCTL_INVALIDATE_VOLUMES
Definition: nt_native.h:847
#define FSCTL_IS_PATHNAME_VALID
Definition: nt_native.h:837
#define FSCTL_UNLOCK_VOLUME
Definition: nt_native.h:833
#define FSCTL_REQUEST_BATCH_OPLOCK
Definition: nt_native.h:828
#define FSCTL_QUERY_FAT_BPB
Definition: nt_native.h:848
#define FSCTL_FILESYSTEM_GET_STATISTICS
Definition: nt_native.h:850
#define FSCTL_OPBATCH_ACK_CLOSE_PENDING
Definition: nt_native.h:830
#define FSCTL_OPLOCK_BREAK_ACK_NO_2
Definition: nt_native.h:846
#define FSCTL_IS_VOLUME_MOUNTED
Definition: nt_native.h:836
#define FSCTL_GET_COMPRESSION
Definition: nt_native.h:841
#define FSCTL_REQUEST_OPLOCK_LEVEL_2
Definition: nt_native.h:827
#define FSCTL_DISMOUNT_VOLUME
Definition: nt_native.h:834
#define FSCTL_SET_COMPRESSION
Definition: nt_native.h:842
#define FSCTL_GET_NTFS_VOLUME_DATA
Definition: ntifs_ex.h:261
#define FSCTL_GET_NTFS_FILE_RECORD
Definition: ntifs_ex.h:262
NTSTATUS NTAPI FsRtlCheckOplock(IN POPLOCK Oplock, IN PIRP Irp, IN PVOID Context, IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL, IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine OPTIONAL)
Definition: oplock.c:1170
#define FSCTL_GET_REPARSE_POINT
Definition: winioctl.h:97
#define FSCTL_SET_REPARSE_POINT
Definition: winioctl.h:98
#define FSCTL_SET_SPARSE
Definition: winioctl.h:100
#define FSCTL_IS_VOLUME_DIRTY
Definition: winioctl.h:714
#define FSCTL_GET_RETRIEVAL_POINTERS
Definition: winioctl.h:95
#define FSCTL_DELETE_REPARSE_POINT
Definition: winioctl.h:99
#define FSCTL_GET_VOLUME_BITMAP
Definition: winioctl.h:94
#define FSCTL_MOVE_FILE
Definition: winioctl.h:96
#define FSCTL_CSC_INTERNAL
Definition: winioctl.h:185
#define FSCTL_READ_RAW_ENCRYPTED
Definition: winioctl.h:147
#define FSCTL_TXFS_SHUTDOWN_RM
Definition: winioctl.h:172
#define FSCTL_SET_VOLUME_COMPRESSION_STATE
Definition: winioctl.h:166
#define FSCTL_QUERY_ALLOCATED_RANGES
Definition: winioctl.h:142
#define FSCTL_GET_REPAIR
Definition: winioctl.h:182
#define FSCTL_SET_OBJECT_ID
Definition: winioctl.h:129
#define FSCTL_SET_DEFECT_MANAGEMENT
Definition: winioctl.h:163
#define FSCTL_SET_REPAIR
Definition: winioctl.h:181
#define FSCTL_TXFS_LIST_TRANSACTION_LOCKED_FILES
Definition: winioctl.h:189
#define FSCTL_TXFS_ROLLFORWARD_REDO
Definition: winioctl.h:169
#define FSCTL_WRITE_USN_CLOSE_RECORD
Definition: winioctl.h:150
#define FSCTL_QUERY_SPARING_INFO
Definition: winioctl.h:164
#define FSCTL_SHRINK_VOLUME
Definition: winioctl.h:186
#define FSCTL_READ_USN_JOURNAL
Definition: winioctl.h:137
#define FSCTL_TXFS_WRITE_BACKUP_INFORMATION
Definition: winioctl.h:174
#define FSCTL_WRITE_RAW_ENCRYPTED
Definition: winioctl.h:146
#define FSCTL_FIND_FILES_BY_SID
Definition: winioctl.h:127
#define FSCTL_DELETE_USN_JOURNAL
Definition: winioctl.h:153
#define FSCTL_SET_ZERO_DATA
Definition: winioctl.h:141
#define FSCTL_ENCRYPTION_FSCTL_IO
Definition: winioctl.h:145
#define FSCTL_TXFS_QUERY_RM_INFORMATION
Definition: winioctl.h:168
#define FSCTL_TXFS_READ_BACKUP_INFORMATION
Definition: winioctl.h:173
#define FSCTL_QUERY_ON_DISK_VOLUME_INFO
Definition: winioctl.h:165
#define FSCTL_SIS_LINK_FILES
Definition: winioctl.h:156
#define FSCTL_RECALL_FILE
Definition: winioctl.h:159
#define FSCTL_SIS_COPYFILE
Definition: winioctl.h:155
#define FSCTL_TXFS_MODIFY_RM
Definition: winioctl.h:167
#define FSCTL_SET_ENCRYPTION
Definition: winioctl.h:144
#define FSCTL_MARK_HANDLE
Definition: winioctl.h:154
#define FSCTL_QUERY_USN_JOURNAL
Definition: winioctl.h:152
#define FSCTL_FILE_PREFETCH
Definition: winioctl.h:161
#define FSCTL_CREATE_OR_GET_OBJECT_ID
Definition: winioctl.h:139
#define FSCTL_CREATE_USN_JOURNAL
Definition: winioctl.h:148
#define FSCTL_SET_OBJECT_ID_EXTENDED
Definition: winioctl.h:138
#define FSCTL_SET_ZERO_ON_DEALLOCATION
Definition: winioctl.h:180
#define FSCTL_ALLOW_EXTENDED_DASD_IO
Definition: winioctl.h:124
#define FSCTL_ENUM_USN_DATA
Definition: winioctl.h:135
#define FSCTL_MAKE_MEDIA_COMPATIBLE
Definition: winioctl.h:162
#define FSCTL_INITIATE_REPAIR
Definition: winioctl.h:184
#define FSCTL_TXFS_START_RM
Definition: winioctl.h:171
#define FSCTL_TXFS_ROLLFORWARD_UNDO
Definition: winioctl.h:170
#define FSCTL_TXFS_LIST_TRANSACTIONS
Definition: winioctl.h:190
#define FSCTL_TXFS_GET_METADATA_INFO
Definition: winioctl.h:176
#define FSCTL_GET_OBJECT_ID
Definition: winioctl.h:130
#define FSCTL_SECURITY_ID_CHECK
Definition: winioctl.h:136
#define FSCTL_TXFS_CREATE_SECONDARY_RM
Definition: winioctl.h:175
#define FSCTL_WAIT_FOR_REPAIR
Definition: winioctl.h:183
#define FSCTL_TXFS_CREATE_MINIVERSION
Definition: winioctl.h:178
#define FSCTL_EXTEND_VOLUME
Definition: winioctl.h:151
#define FSCTL_QUERY_PAGEFILE_ENCRYPTION
Definition: winioctl.h:191
#define FSCTL_TXFS_GET_TRANSACTED_VERSION
Definition: winioctl.h:177
#define FSCTL_ENABLE_UPGRADE
Definition: winioctl.h:143
#define FSCTL_READ_FILE_USN_DATA
Definition: winioctl.h:149
#define FSCTL_SET_SHORT_NAME_BEHAVIOR
Definition: winioctl.h:187
#define FSCTL_DELETE_OBJECT_ID
Definition: winioctl.h:131
#define FSCTL_DFSR_SET_GHOST_HANDLE_STATE
Definition: winioctl.h:188
#define FSCTL_TXFS_TRANSACTION_ACTIVE
Definition: winioctl.h:179
#define FSCTL_READ_FROM_PLEX
Definition: winioctl.h:160
static void send_subvol(const wstring &subvol, const wstring &file, const wstring &parent, const vector< wstring > &clones)
Definition: send.cpp:564
#define FSCTL_SET_INTEGRITY_INFORMATION
Definition: shellext.h:222
#define FSCTL_GET_INTEGRITY_INFORMATION
Definition: shellext.h:221
#define FSCTL_DUPLICATE_EXTENTS_TO_FILE
Definition: shellext.h:205
#define FSCTL_SET_BOOTLOADER_ACCESSED
Definition: iotypes.h:6061

Referenced by _Dispatch_type_().

◆ galois_divpower()

void galois_divpower ( uint8_t data,
uint8_t  div,
uint32_t  readlen 
)

Definition at line 55 of file galois.c.

55 {
56 while (len > 0) {
57 if (data[0] != 0) {
58 if (gilog[data[0]] <= div)
59 data[0] = glog[(gilog[data[0]] + (255 - div)) % 255];
60 else
61 data[0] = glog[(gilog[data[0]] - div) % 255];
62 }
63
64 data++;
65 len--;
66 }
67}
_STLP_VENDOR_CSTD::ldiv_t div(long __x, long __y)
Definition: _cstdlib.h:137
static const uint8_t glog[]
Definition: galois.c:20
static const uint8_t gilog[]
Definition: galois.c:37

Referenced by raid6_recover2(), and scrub_raid6_stripe().

◆ galois_double()

void galois_double ( uint8_t data,
uint32_t  len 
)

Definition at line 109 of file galois.c.

109 {
110 // FIXME - SIMD?
111
112#if defined(_AMD64_) || defined(_ARM64_)
113 while (len > sizeof(uint64_t)) {
114 uint64_t v = *((uint64_t*)data), vv;
115
116 vv = (v << 1) & 0xfefefefefefefefe;
117 vv ^= galois_double_mask64(v) & 0x1d1d1d1d1d1d1d1d;
118 *((uint64_t*)data) = vv;
119
120 data += sizeof(uint64_t);
121 len -= sizeof(uint64_t);
122 }
123#else
124 while (len > sizeof(uint32_t)) {
125 uint32_t v = *((uint32_t*)data), vv;
126
127 vv = (v << 1) & 0xfefefefe;
128 vv ^= galois_double_mask32(v) & 0x1d1d1d1d;
129 *((uint32_t*)data) = vv;
130
131 data += sizeof(uint32_t);
132 len -= sizeof(uint32_t);
133 }
134#endif
135
136 while (len > 0) {
137 data[0] = (data[0] << 1) ^ ((data[0] & 0x80) ? 0x1d : 0);
138 data++;
139 len--;
140 }
141}
static __inline uint32_t galois_double_mask32(uint32_t v)
Definition: galois.c:103
const GLdouble * v
Definition: gl.h:2040

Referenced by flush_partial_stripe(), raid6_recover2(), and scrub_raid6_stripe().

◆ gdiv()

uint8_t gdiv ( uint8_t  a,
uint8_t  b 
)

Definition at line 80 of file galois.c.

80 {
81 if (b == 0) {
82 return 0xff; // shouldn't happen
83 } else if (a == 0) {
84 return 0;
85 } else {
86 if (gilog[a] >= gilog[b])
87 return glog[(gilog[a] - gilog[b]) % 255];
88 else
89 return glog[255-((gilog[b] - gilog[a]) % 255)];
90 }
91}
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
#define a
Definition: ke_i.h:78

Referenced by raid6_recover2(), and scrub_raid6_stripe().

◆ get_chunk_from_address()

◆ get_device_pnp_name()

NTSTATUS get_device_pnp_name ( _In_ PDEVICE_OBJECT  DeviceObject,
_Out_ PUNICODE_STRING  pnp_name,
_Out_ const GUID **  guid 
)

Definition at line 4233 of file btrfs.c.

4233 {
4235
4236 Status = get_device_pnp_name_guid(DeviceObject, pnp_name, &GUID_DEVINTERFACE_VOLUME);
4237 if (NT_SUCCESS(Status)) {
4238 *guid = &GUID_DEVINTERFACE_VOLUME;
4239 return Status;
4240 }
4241
4242 Status = get_device_pnp_name_guid(DeviceObject, pnp_name, &GUID_DEVINTERFACE_HIDDEN_VOLUME);
4243 if (NT_SUCCESS(Status)) {
4244 *guid = &GUID_DEVINTERFACE_HIDDEN_VOLUME;
4245 return Status;
4246 }
4247
4248 Status = get_device_pnp_name_guid(DeviceObject, pnp_name, &GUID_DEVINTERFACE_DISK);
4249 if (NT_SUCCESS(Status)) {
4250 *guid = &GUID_DEVINTERFACE_DISK;
4251 return Status;
4252 }
4253
4254 return STATUS_NOT_FOUND;
4255}
static NTSTATUS get_device_pnp_name_guid(_In_ PDEVICE_OBJECT DeviceObject, _Out_ PUNICODE_STRING pnp_name, _In_ const GUID *guid)
Definition: btrfs.c:4178
const GUID * guid

Referenced by add_device(), and probe_volume().

◆ get_extent_data_len()

static __inline uint16_t get_extent_data_len ( uint8_t  type)
static

Definition at line 1043 of file btrfs_drv.h.

1043 {
1044 switch (type) {
1046 return sizeof(TREE_BLOCK_REF);
1047
1049 return sizeof(EXTENT_DATA_REF);
1050
1051 case TYPE_EXTENT_REF_V0:
1052 return sizeof(EXTENT_REF_V0);
1053
1055 return sizeof(SHARED_BLOCK_REF);
1056
1058 return sizeof(SHARED_DATA_REF);
1059
1060 default:
1061 return 0;
1062 }
1063}

Referenced by construct_extent_item(), decrease_extent_refcount(), find_extent_data_refcount(), find_extent_shared_data_refcount(), find_extent_shared_tree_refcount(), increase_extent_refcount(), is_extent_unique(), and try_clone().

◆ get_extent_data_ref_hash2()

uint64_t get_extent_data_ref_hash2 ( uint64_t  root,
uint64_t  objid,
uint64_t  offset 
)

Definition at line 35 of file extent-tree.c.

35 {
36 uint32_t high_crc = 0xffffffff, low_crc = 0xffffffff;
37
38 high_crc = calc_crc32c(high_crc, (uint8_t*)&root, sizeof(uint64_t));
39 low_crc = calc_crc32c(low_crc, (uint8_t*)&objid, sizeof(uint64_t));
40 low_crc = calc_crc32c(low_crc, (uint8_t*)&offset, sizeof(uint64_t));
41
42 return ((uint64_t)high_crc << 31) ^ (uint64_t)low_crc;
43}

Referenced by find_extent_data_refcount(), get_extent_data_ref_hash(), and sort_data_reloc_refs().

◆ get_extent_data_refcount()

static __inline uint32_t get_extent_data_refcount ( uint8_t  type,
void data 
)
static

Definition at line 1065 of file btrfs_drv.h.

1065 {
1066 switch (type) {
1068 return 1;
1069
1071 {
1073 return edr->count;
1074 }
1075
1076 case TYPE_EXTENT_REF_V0:
1077 {
1079 return erv0->count;
1080 }
1081
1083 return 1;
1084
1086 {
1088 return sdr->count;
1089 }
1090
1091 default:
1092 return 0;
1093 }
1094}

Referenced by construct_extent_item(), decrease_extent_refcount(), find_extent_data_refcount(), find_extent_shared_data_refcount(), find_extent_shared_tree_refcount(), increase_extent_refcount(), is_extent_unique(), and try_clone().

◆ get_extent_flags()

uint64_t get_extent_flags ( device_extension Vcb,
uint64_t  address,
PIRP  Irp 
)

Definition at line 1835 of file extent-tree.c.

1835 {
1836 KEY searchkey;
1839 EXTENT_ITEM* ei;
1840
1841 searchkey.obj_id = address;
1842 searchkey.obj_type = Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA ? TYPE_METADATA_ITEM : TYPE_EXTENT_ITEM;
1843 searchkey.offset = 0xffffffffffffffff;
1844
1845 Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, Irp);
1846 if (!NT_SUCCESS(Status)) {
1847 ERR("error - find_item returned %08lx\n", Status);
1848 return 0;
1849 }
1850
1851 if (Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA && tp.item->key.obj_id == address &&
1853 ei = (EXTENT_ITEM*)tp.item->data;
1854
1855 return ei->flags;
1856 }
1857
1859 ERR("couldn't find %I64x in extent tree\n", address);
1860 return 0;
1861 }
1862
1863 if (tp.item->size == sizeof(EXTENT_ITEM_V0))
1864 return 0;
1865 else if (tp.item->size < sizeof(EXTENT_ITEM)) {
1866 ERR("(%I64x,%x,%I64x) was %x bytes, expected at least %Ix\n", tp.item->key.obj_id, tp.item->key.obj_type,
1867 tp.item->key.offset, tp.item->size, sizeof(EXTENT_ITEM));
1868 return 0;
1869 }
1870
1871 ei = (EXTENT_ITEM*)tp.item->data;
1872
1873 return ei->flags;
1874}

Referenced by update_tree_extents().

◆ get_extent_refcount()

uint64_t get_extent_refcount ( device_extension Vcb,
uint64_t  address,
uint64_t  size,
PIRP  Irp 
)

Definition at line 1651 of file extent-tree.c.

1651 {
1652 KEY searchkey;
1655 EXTENT_ITEM* ei;
1656
1657 searchkey.obj_id = address;
1658 searchkey.obj_type = Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA ? TYPE_METADATA_ITEM : TYPE_EXTENT_ITEM;
1659 searchkey.offset = 0xffffffffffffffff;
1660
1661 Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, Irp);
1662 if (!NT_SUCCESS(Status)) {
1663 ERR("error - find_item returned %08lx\n", Status);
1664 return 0;
1665 }
1666
1667 if (Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA && tp.item->key.obj_id == address &&
1669 ei = (EXTENT_ITEM*)tp.item->data;
1670
1671 return ei->refcount;
1672 }
1673
1675 ERR("couldn't find (%I64x,%x,%I64x) in extent tree\n", address, TYPE_EXTENT_ITEM, size);
1676 return 0;
1677 } else if (tp.item->key.offset != size) {
1678 ERR("extent %I64x had size %I64x, not %I64x as expected\n", address, tp.item->key.offset, size);
1679 return 0;
1680 }
1681
1682 if (tp.item->size == sizeof(EXTENT_ITEM_V0)) {
1684
1685 return eiv0->refcount;
1686 } else if (tp.item->size < sizeof(EXTENT_ITEM)) {
1687 ERR("(%I64x,%x,%I64x) was %x bytes, expected at least %Ix\n", tp.item->key.obj_id, tp.item->key.obj_type,
1688 tp.item->key.offset, tp.item->size, sizeof(EXTENT_ITEM));
1689 return 0;
1690 }
1691
1692 ei = (EXTENT_ITEM*)tp.item->data;
1693
1694 return ei->refcount;
1695}
uint32_t refcount
Definition: btrfs.h:403

Referenced by is_extent_unique(), reduce_tree_extent(), and update_tree_extents().

◆ get_file_attributes()

ULONG get_file_attributes ( _In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension Vcb,
_In_ root r,
_In_ uint64_t  inode,
_In_ uint8_t  type,
_In_ bool  dotfile,
_In_ bool  ignore_xa,
_In_opt_ PIRP  Irp 
)

Definition at line 2664 of file btrfs.c.

2665 {
2666 ULONG att;
2667 char* eaval;
2668 uint16_t ealen;
2669
2670 if (!ignore_xa && get_xattr(Vcb, r, inode, EA_DOSATTRIB, EA_DOSATTRIB_HASH, (uint8_t**)&eaval, &ealen, Irp)) {
2671 ULONG dosnum = 0;
2672
2673 if (get_file_attributes_from_xattr(eaval, ealen, &dosnum)) {
2674 ExFreePool(eaval);
2675
2677 dosnum |= FILE_ATTRIBUTE_DIRECTORY;
2678 else if (type == BTRFS_TYPE_SYMLINK)
2680
2682 dosnum &= ~FILE_ATTRIBUTE_DIRECTORY;
2683
2684 if (inode == SUBVOL_ROOT_INODE) {
2685 if (r->root_item.flags & BTRFS_SUBVOL_READONLY)
2686 dosnum |= FILE_ATTRIBUTE_READONLY;
2687 else
2688 dosnum &= ~FILE_ATTRIBUTE_READONLY;
2689 }
2690
2691 return dosnum;
2692 }
2693
2694 ExFreePool(eaval);
2695 }
2696
2697 switch (type) {
2700 break;
2701
2702 case BTRFS_TYPE_SYMLINK:
2704 break;
2705
2706 default:
2707 att = 0;
2708 break;
2709 }
2710
2711 if (dotfile || (r->id == BTRFS_ROOT_FSTREE && inode == SUBVOL_ROOT_INODE))
2712 att |= FILE_ATTRIBUTE_HIDDEN;
2713
2715
2716 if (inode == SUBVOL_ROOT_INODE) {
2717 if (r->root_item.flags & BTRFS_SUBVOL_READONLY)
2719 else
2720 att &= ~FILE_ATTRIBUTE_READONLY;
2721 }
2722
2723 // FIXME - get READONLY from ii->st_mode
2724 // FIXME - return SYSTEM for block/char devices?
2725
2726 if (att == 0)
2728
2729 return att;
2730}
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define BTRFS_SUBVOL_READONLY
Definition: btrfs.h:109
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
#define FILE_ATTRIBUTE_HIDDEN
Definition: nt_native.h:703
#define FILE_ATTRIBUTE_ARCHIVE
Definition: nt_native.h:706
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
#define FILE_ATTRIBUTE_REPARSE_POINT
Definition: ntifs_ex.h:381

Referenced by create_directory_fcb(), create_subvol(), fsctl_set_xattr(), mount_vol(), move_across_subvols(), open_file3(), query_dir_item(), set_basic_information(), and set_sparse().

◆ get_num_of_processors()

uint32_t get_num_of_processors ( )

Definition at line 4080 of file btrfs.c.

4080 {
4082 uint32_t r = 0;
4083
4084 while (p != 0) {
4085 if (p & 1)
4086 r++;
4087
4088 p >>= 1;
4089 }
4090
4091 return r;
4092}
ULONG_PTR KAFFINITY
Definition: compat.h:85
KAFFINITY NTAPI KeQueryActiveProcessors(VOID)
Definition: cpu.c:637

Referenced by create_calc_threads().

◆ get_raid0_offset()

_Post_satisfies_ static stripe __inline void get_raid0_offset ( _In_ uint64_t  off,
_In_ uint64_t  stripe_length,
_In_ uint16_t  num_stripes,
_Out_ uint64_t stripeoff,
_Out_ uint16_t stripe 
)
static

Definition at line 997 of file btrfs_drv.h.

997 {
998 uint64_t initoff, startoff;
999
1000 startoff = off % (num_stripes * stripe_length);
1001 initoff = (off / (num_stripes * stripe_length)) * stripe_length;
1002
1003 *stripe = (uint16_t)(startoff / stripe_length);
1004 *stripeoff = initoff + startoff - (*stripe * stripe_length);
1005}

Referenced by __attribute__(), clean_space_cache_chunk(), flush_partial_stripe(), protect_superblocks(), read_data(), read_data_raid0(), read_data_raid10(), read_data_raid5(), read_data_raid6(), and scrub_extent().

◆ get_raid56_lock_range()

NTSTATUS bool void get_raid56_lock_range ( chunk c,
uint64_t  address,
uint64_t  length,
uint64_t lockaddr,
uint64_t locklen 
)

Referenced by read_data().

◆ get_reparse_point()

NTSTATUS get_reparse_point ( PFILE_OBJECT  FileObject,
void buffer,
DWORD  buflen,
ULONG_PTR retlen 
)

Definition at line 27 of file reparse.c.

27 {
28 USHORT subnamelen, printnamelen, i;
30 DWORD reqlen;
32 fcb* fcb = FileObject->FsContext;
33 ccb* ccb = FileObject->FsContext2;
35
36 TRACE("(%p, %p, %lx, %p)\n", FileObject, buffer, buflen, retlen);
37
38 if (!ccb)
40
41 ExAcquireResourceSharedLite(&fcb->Vcb->tree_lock, true);
42 ExAcquireResourceSharedLite(fcb->Header.Resource, true);
43
44 if (fcb->type == BTRFS_TYPE_SYMLINK) {
45 if (ccb->lxss) {
46 reqlen = offsetof(REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + sizeof(uint32_t);
47
48 if (buflen < reqlen) {
50 goto end;
51 }
52
54 rdb->ReparseDataLength = offsetof(REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + sizeof(uint32_t);
55 rdb->Reserved = 0;
56
57 *((uint32_t*)rdb->GenericReparseBuffer.DataBuffer) = 1;
58
59 *retlen = reqlen;
60 } else {
61 char* data;
62
63 if (fcb->inode_item.st_size == 0 || fcb->inode_item.st_size > 0xffff) {
65 goto end;
66 }
67
69 if (!data) {
70 ERR("out of memory\n");
72 goto end;
73 }
74
75 TRACE("data = %p, size = %I64x\n", data, fcb->inode_item.st_size);
77
78 if (!NT_SUCCESS(Status)) {
79 ERR("read_file returned %08lx\n", Status);
81 goto end;
82 }
83
85 if (!NT_SUCCESS(Status)) {
86 ERR("utf8_to_utf16 1 returned %08lx\n", Status);
88 goto end;
89 }
90
91 subnamelen = (uint16_t)stringlen;
92 printnamelen = (uint16_t)stringlen;
93
94 reqlen = offsetof(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + subnamelen + printnamelen;
95
96 if (buflen >= offsetof(REPARSE_DATA_BUFFER, ReparseDataLength))
98
100 rdb->ReparseDataLength = (USHORT)(reqlen - offsetof(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer));
101
102 if (buflen >= offsetof(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.SubstituteNameOffset))
103 rdb->Reserved = 0;
104
105 if (buflen < reqlen) {
108 *retlen = min(buflen, offsetof(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.SubstituteNameOffset));
109 goto end;
110 }
111
112 rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0;
113 rdb->SymbolicLinkReparseBuffer.SubstituteNameLength = subnamelen;
114 rdb->SymbolicLinkReparseBuffer.PrintNameOffset = subnamelen;
115 rdb->SymbolicLinkReparseBuffer.PrintNameLength = printnamelen;
117
118 Status = utf8_to_utf16(&rdb->SymbolicLinkReparseBuffer.PathBuffer[rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)],
120
121 if (!NT_SUCCESS(Status)) {
122 ERR("utf8_to_utf16 2 returned %08lx\n", Status);
124 goto end;
125 }
126
127 for (i = 0; i < stringlen / sizeof(WCHAR); i++) {
128 if (rdb->SymbolicLinkReparseBuffer.PathBuffer[(rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)) + i] == '/')
129 rdb->SymbolicLinkReparseBuffer.PathBuffer[(rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)) + i] = '\\';
130 }
131
132 RtlCopyMemory(&rdb->SymbolicLinkReparseBuffer.PathBuffer[rdb->SymbolicLinkReparseBuffer.PrintNameOffset / sizeof(WCHAR)],
133 &rdb->SymbolicLinkReparseBuffer.PathBuffer[rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)],
134 rdb->SymbolicLinkReparseBuffer.SubstituteNameLength);
135
136 *retlen = reqlen;
137
139 }
140
142 } else if (fcb->atts & FILE_ATTRIBUTE_REPARSE_POINT) {
143 if (fcb->type == BTRFS_TYPE_FILE) {
144 ULONG len;
145
146 Status = read_file(fcb, buffer, 0, buflen, &len, NULL);
147
148 if (!NT_SUCCESS(Status)) {
149 ERR("read_file returned %08lx\n", Status);
150 }
151
152 *retlen = len;
153 } else if (fcb->type == BTRFS_TYPE_DIRECTORY) {
154 if (!fcb->reparse_xattr.Buffer || fcb->reparse_xattr.Length < sizeof(ULONG)) {
156 goto end;
157 }
158
159 if (buflen > 0) {
160 *retlen = min(buflen, fcb->reparse_xattr.Length);
162 } else
163 *retlen = 0;
164
166 } else
168 } else {
170 }
171
172end:
174 ExReleaseResourceLite(&fcb->Vcb->tree_lock);
175
176 return Status;
177}
#define IO_REPARSE_TAG_LX_SYMLINK
Definition: btrfs_drv.h:118
wstring utf8_to_utf16(const string_view &utf8)
Definition: main.cpp:734
GLint const GLchar GLint stringlen
Definition: glext.h:7232
GLuint buffer
Definition: glext.h:5915
#define STATUS_NOT_A_REPARSE_POINT
Definition: ntstatus.h:753
#define SYMLINK_FLAG_RELATIVE
Definition: shellext.h:193
struct _REPARSE_DATA_BUFFER::@318::@320 SymbolicLinkReparseBuffer
struct _REPARSE_DATA_BUFFER::@318::@322 GenericReparseBuffer
bool lxss
Definition: btrfs_drv.h:391
_Reserved_ PVOID Reserved
Definition: winddi.h:3974

Referenced by fsctl_request().

◆ get_reparse_tag()

ULONG get_reparse_tag ( device_extension Vcb,
root subvol,
uint64_t  inode,
uint8_t  type,
ULONG  atts,
bool  lxss,
PIRP  Irp 
)

Definition at line 107 of file dirctrl.c.

107 {
108 fcb* fcb;
109 ULONG tag = 0;
111
114 else if (lxss) {
115 if (type == BTRFS_TYPE_SOCKET)
117 else if (type == BTRFS_TYPE_FIFO)
119 else if (type == BTRFS_TYPE_CHARDEV)
121 else if (type == BTRFS_TYPE_BLOCKDEV)
123 }
124
126 return 0;
127
129 return 0;
130
131 Status = open_fcb(Vcb, subvol, inode, type, NULL, false, NULL, &fcb, PagedPool, Irp);
132 if (!NT_SUCCESS(Status)) {
133 ERR("open_fcb returned %08lx\n", Status);
134 return 0;
135 }
136
137 ExAcquireResourceSharedLite(fcb->Header.Resource, true);
138
140
142
143 free_fcb(fcb);
144
145 return tag;
146}
ULONG get_reparse_tag_fcb(fcb *fcb)
Definition: dirctrl.c:83
#define IO_REPARSE_TAG_AF_UNIX
Definition: btrfs_drv.h:120
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)
Definition: create.c:706
#define IO_REPARSE_TAG_LX_CHR
Definition: btrfs_drv.h:122
#define IO_REPARSE_TAG_LX_BLK
Definition: btrfs_drv.h:123
#define IO_REPARSE_TAG_LX_FIFO
Definition: btrfs_drv.h:121
void free_fcb(_Inout_ fcb *fcb)
Definition: btrfs.c:1734
#define BTRFS_TYPE_SOCKET
Definition: shellext.h:90
#define BTRFS_TYPE_FIFO
Definition: shellext.h:89
#define BTRFS_TYPE_CHARDEV
Definition: shellext.h:87
#define BTRFS_TYPE_BLOCKDEV
Definition: shellext.h:88
Definition: ecma_167.h:138

Referenced by query_dir_item().

◆ get_reparse_tag_fcb()

ULONG get_reparse_tag_fcb ( fcb fcb)

Definition at line 83 of file dirctrl.c.

83 {
84 ULONG tag;
85
88 else if (fcb->type == BTRFS_TYPE_DIRECTORY) {
90 return 0;
91
93 } else {
95 ULONG br;
96
97 Status = read_file(fcb, (uint8_t*)&tag, 0, sizeof(ULONG), &br, NULL);
98 if (!NT_SUCCESS(Status)) {
99 ERR("read_file returned %08lx\n", Status);
100 return 0;
101 }
102 }
103
104 return tag;
105}

Referenced by fill_in_file_attribute_information(), fill_in_file_stat_information(), fill_in_file_stat_lx_information(), and get_reparse_tag().

◆ get_sector_csum()

void get_sector_csum ( device_extension Vcb,
void buf,
void csum 
)

Definition at line 182 of file read.c.

182 {
183 switch (Vcb->superblock.csum_type) {
184 case CSUM_TYPE_CRC32C:
185 *(uint32_t*)csum = ~calc_crc32c(0xffffffff, buf, Vcb->superblock.sector_size);
186 break;
187
188 case CSUM_TYPE_XXHASH:
189 *(uint64_t*)csum = XXH64(buf, Vcb->superblock.sector_size, 0);
190 break;
191
192 case CSUM_TYPE_SHA256:
193 calc_sha256(csum, buf, Vcb->superblock.sector_size);
194 break;
195
196 case CSUM_TYPE_BLAKE2:
197 blake2b(csum, BLAKE2_HASH_SIZE, buf, Vcb->superblock.sector_size);
198 break;
199 }
200}

Referenced by add_csum_sparse_extents(), scrub_raid5_stripe(), and scrub_raid6_stripe().

◆ get_tree_checksum()

void get_tree_checksum ( device_extension Vcb,
tree_header th,
void csum 
)

Definition at line 108 of file read.c.

108 {
109 switch (Vcb->superblock.csum_type) {
110 case CSUM_TYPE_CRC32C:
111 *(uint32_t*)csum = ~calc_crc32c(0xffffffff, (uint8_t*)&th->fs_uuid, Vcb->superblock.node_size - sizeof(th->csum));
112 break;
113
114 case CSUM_TYPE_XXHASH:
115 *(uint64_t*)csum = XXH64((uint8_t*)&th->fs_uuid, Vcb->superblock.node_size - sizeof(th->csum), 0);
116 break;
117
118 case CSUM_TYPE_SHA256:
119 calc_sha256(csum, &th->fs_uuid, Vcb->superblock.node_size - sizeof(th->csum));
120 break;
121
122 case CSUM_TYPE_BLAKE2:
123 blake2b(csum, BLAKE2_HASH_SIZE, (uint8_t*)&th->fs_uuid, Vcb->superblock.node_size - sizeof(th->csum));
124 break;
125 }
126}

Referenced by scrub_extent_dup(), scrub_extent_raid10(), and scrub_raid6_stripe().

◆ get_tree_new_address()

NTSTATUS get_tree_new_address ( device_extension Vcb,
tree t,
PIRP  Irp,
LIST_ENTRY rollback 
)

Definition at line 878 of file flushthread.c.

878 {
880 chunk *origchunk = NULL, *c;
881 LIST_ENTRY* le;
883
884 if (t->root->id == BTRFS_ROOT_CHUNK)
885 flags = Vcb->system_flags;
886 else
887 flags = Vcb->metadata_flags;
888
889 if (t->has_address) {
890 origchunk = get_chunk_from_address(Vcb, t->header.address);
891
892 if (origchunk && !origchunk->readonly && !origchunk->reloc && origchunk->chunk_item->type == flags &&
893 insert_tree_extent(Vcb, t->header.level, t->root->id, origchunk, &addr, Irp, rollback)) {
894 t->new_address = addr;
895 t->has_new_address = true;
896 return STATUS_SUCCESS;
897 }
898 }
899
900 ExAcquireResourceExclusiveLite(&Vcb->chunk_lock, true);
901
902 le = Vcb->chunks.Flink;
903 while (le != &Vcb->chunks) {
905
906 if (!c->readonly && !c->reloc) {
908
909 if (c != origchunk && c->chunk_item->type == flags && (c->chunk_item->size - c->used) >= Vcb->superblock.node_size) {
910 if (insert_tree_extent(Vcb, t->header.level, t->root->id, c, &addr, Irp, rollback)) {
912 ExReleaseResourceLite(&Vcb->chunk_lock);
913 t->new_address = addr;
914 t->has_new_address = true;
915 return STATUS_SUCCESS;
916 }
917 }
918
920 }
921
922 le = le->Flink;
923 }
924
925 // allocate new chunk if necessary
926
927 Status = alloc_chunk(Vcb, flags, &c, false);
928
929 if (!NT_SUCCESS(Status)) {
930 ERR("alloc_chunk returned %08lx\n", Status);
931 ExReleaseResourceLite(&Vcb->chunk_lock);
932 return Status;
933 }
934
936
937 if ((c->chunk_item->size - c->used) >= Vcb->superblock.node_size) {
938 if (insert_tree_extent(Vcb, t->header.level, t->root->id, c, &addr, Irp, rollback)) {
940 ExReleaseResourceLite(&Vcb->chunk_lock);
941 t->new_address = addr;
942 t->has_new_address = true;
943 return STATUS_SUCCESS;
944 }
945 }
946
948
949 ExReleaseResourceLite(&Vcb->chunk_lock);
950
951 ERR("couldn't find any metadata chunks with %x bytes free\n", Vcb->superblock.node_size);
952
953 return STATUS_DISK_FULL;
954}
#define BTRFS_ROOT_CHUNK
Definition: btrfs.h:56
static bool insert_tree_extent(device_extension *Vcb, uint8_t level, uint64_t root_id, chunk *c, uint64_t *new_address, PIRP Irp, LIST_ENTRY *rollback)
Definition: flushthread.c:825
GLbitfield flags
Definition: glext.h:7161
GLenum const GLvoid * addr
Definition: glext.h:9621
uint64_t type
Definition: btrfs.h:343
bool readonly
Definition: btrfs_drv.h:580
bool reloc
Definition: btrfs_drv.h:581
CHUNK_ITEM * chunk_item
Definition: btrfs_drv.h:562

Referenced by allocate_tree_extents(), and snapshot_tree_copy().

◆ gmul()

uint8_t gmul ( uint8_t  a,
uint8_t  b 
)

Definition at line 73 of file galois.c.

73 {
74 if (a == 0 || b == 0)
75 return 0;
76 else
77 return glog[(gilog[a] + gilog[b]) % 255];
78}

Referenced by raid6_recover2(), and scrub_raid6_stripe().

◆ gpow2()

uint8_t gpow2 ( uint8_t  e)

Definition at line 69 of file galois.c.

69 {
70 return glog[e%255];
71}
#define e
Definition: ke_i.h:82

Referenced by raid6_recover2(), and scrub_raid6_stripe().

◆ has_open_children()

bool has_open_children ( file_ref fileref)

Definition at line 442 of file fileinfo.c.

442 {
443 LIST_ENTRY* le = fileref->children.Flink;
444
445 if (IsListEmpty(&fileref->children))
446 return false;
447
448 while (le != &fileref->children) {
450
451 if (c->open_count > 0)
452 return true;
453
454 if (has_open_children(c))
455 return true;
456
457 le = le->Flink;
458 }
459
460 return false;
461}
bool has_open_children(file_ref *fileref)
Definition: fileinfo.c:442

Referenced by has_open_children(), lock_volume(), pnp_query_remove_device(), set_link_information(), and set_rename_information().

◆ increase_extent_refcount()

NTSTATUS increase_extent_refcount ( device_extension Vcb,
uint64_t  address,
uint64_t  size,
uint8_t  type,
void data,
KEY firstitem,
uint8_t  level,
PIRP  Irp 
)

Definition at line 454 of file extent-tree.c.

454 {
456 KEY searchkey;
458 ULONG len, max_extent_item_size;
460 EXTENT_ITEM* ei;
461 uint8_t* ptr;
462 uint64_t inline_rc, offset;
463 uint8_t* data2;
464 EXTENT_ITEM* newei;
465 bool skinny;
466 bool is_tree = type == TYPE_TREE_BLOCK_REF || type == TYPE_SHARED_BLOCK_REF;
467
468 if (datalen == 0) {
469 ERR("unrecognized extent type %x\n", type);
471 }
472
473 searchkey.obj_id = address;
474 searchkey.obj_type = Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA ? TYPE_METADATA_ITEM : TYPE_EXTENT_ITEM;
475 searchkey.offset = 0xffffffffffffffff;
476
477 Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, Irp);
478 if (!NT_SUCCESS(Status)) {
479 ERR("error - find_item returned %08lx\n", Status);
480 return Status;
481 }
482
483 // If entry doesn't exist yet, create new inline extent item
484
486 uint16_t eisize;
487
488 eisize = sizeof(EXTENT_ITEM);
489 if (is_tree && !(Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA)) eisize += sizeof(EXTENT_ITEM2);
490 eisize += sizeof(uint8_t);
491 eisize += datalen;
492
494 if (!ei) {
495 ERR("out of memory\n");
497 }
498
500 ei->generation = Vcb->superblock.generation;
502 ptr = (uint8_t*)&ei[1];
503
504 if (is_tree && !(Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA)) {
506 ei2->firstitem = *firstitem;
507 ei2->level = level;
508 ptr = (uint8_t*)&ei2[1];
509 }
510
511 *ptr = type;
513
514 if (Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA && is_tree)
515 Status = insert_tree_item(Vcb, Vcb->extent_root, address, TYPE_METADATA_ITEM, level, ei, eisize, NULL, Irp);
516 else
517 Status = insert_tree_item(Vcb, Vcb->extent_root, address, TYPE_EXTENT_ITEM, size, ei, eisize, NULL, Irp);
518
519 if (!NT_SUCCESS(Status)) {
520 ERR("insert_tree_item returned %08lx\n", Status);
521 return Status;
522 }
523
524 return STATUS_SUCCESS;
525 } else if (tp.item->key.obj_id == address && tp.item->key.obj_type == TYPE_EXTENT_ITEM && tp.item->key.offset != size) {
526 ERR("extent %I64x exists, but with size %I64x rather than %I64x expected\n", tp.item->key.obj_id, tp.item->key.offset, size);
528 }
529
531
532 if (tp.item->size == sizeof(EXTENT_ITEM_V0) && !skinny) {
533 Status = convert_old_extent(Vcb, address, is_tree, firstitem, level, Irp);
534
535 if (!NT_SUCCESS(Status)) {
536 ERR("convert_old_extent returned %08lx\n", Status);
537 return Status;
538 }
539
540 return increase_extent_refcount(Vcb, address, size, type, data, firstitem, level, Irp);
541 }
542
543 if (tp.item->size < sizeof(EXTENT_ITEM)) {
544 ERR("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(EXTENT_ITEM));
546 }
547
548 ei = (EXTENT_ITEM*)tp.item->data;
549
550 len = tp.item->size - sizeof(EXTENT_ITEM);
551 ptr = (uint8_t*)&ei[1];
552
553 if (ei->flags & EXTENT_ITEM_TREE_BLOCK && !skinny) {
554 if (tp.item->size < sizeof(EXTENT_ITEM) + sizeof(EXTENT_ITEM2)) {
555 ERR("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(EXTENT_ITEM) + sizeof(EXTENT_ITEM2));
557 }
558
559 len -= sizeof(EXTENT_ITEM2);
560 ptr += sizeof(EXTENT_ITEM2);
561 }
562
563 inline_rc = 0;
564
565 // Loop through existing inline extent entries
566
567 while (len > 0) {
568 uint8_t secttype = *ptr;
569 ULONG sectlen = get_extent_data_len(secttype);
570 uint64_t sectcount = get_extent_data_refcount(secttype, ptr + sizeof(uint8_t));
571
572 len--;
573
574 if (sectlen > len) {
575 ERR("(%I64x,%x,%I64x): %lx bytes left, expecting at least %lx\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, len, sectlen);
577 }
578
579 if (sectlen == 0) {
580 ERR("(%I64x,%x,%I64x): unrecognized extent type %x\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, secttype);
582 }
583
584 // If inline extent already present, increase refcount and return
585
586 if (secttype == type) {
587 if (type == TYPE_EXTENT_DATA_REF) {
588 EXTENT_DATA_REF* sectedr = (EXTENT_DATA_REF*)(ptr + sizeof(uint8_t));
590
591 if (sectedr->root == edr->root && sectedr->objid == edr->objid && sectedr->offset == edr->offset) {
593 EXTENT_DATA_REF* sectedr2;
594
596 if (!newei) {
597 ERR("out of memory\n");
599 }
600
601 RtlCopyMemory(newei, tp.item->data, tp.item->size);
602
603 newei->refcount += rc;
604
605 sectedr2 = (EXTENT_DATA_REF*)((uint8_t*)newei + ((uint8_t*)sectedr - tp.item->data));
606 sectedr2->count += rc;
607
609 if (!NT_SUCCESS(Status)) {
610 ERR("delete_tree_item returned %08lx\n", Status);
611 return Status;
612 }
613
615 if (!NT_SUCCESS(Status)) {
616 ERR("insert_tree_item returned %08lx\n", Status);
617 return Status;
618 }
619
620 return STATUS_SUCCESS;
621 }
622 } else if (type == TYPE_TREE_BLOCK_REF) {
623 TREE_BLOCK_REF* secttbr = (TREE_BLOCK_REF*)(ptr + sizeof(uint8_t));
625
626 if (secttbr->offset == tbr->offset) {
627 TRACE("trying to increase refcount of non-shared tree extent\n");
628 return STATUS_SUCCESS;
629 }
630 } else if (type == TYPE_SHARED_BLOCK_REF) {
631 SHARED_BLOCK_REF* sectsbr = (SHARED_BLOCK_REF*)(ptr + sizeof(uint8_t));
633
634 if (sectsbr->offset == sbr->offset)
635 return STATUS_SUCCESS;
636 } else if (type == TYPE_SHARED_DATA_REF) {
637 SHARED_DATA_REF* sectsdr = (SHARED_DATA_REF*)(ptr + sizeof(uint8_t));
639
640 if (sectsdr->offset == sdr->offset) {
642 SHARED_DATA_REF* sectsdr2;
643
645 if (!newei) {
646 ERR("out of memory\n");
648 }
649
650 RtlCopyMemory(newei, tp.item->data, tp.item->size);
651
652 newei->refcount += rc;
653
654 sectsdr2 = (SHARED_DATA_REF*)((uint8_t*)newei + ((uint8_t*)sectsdr - tp.item->data));
655 sectsdr2->count += rc;
656
658 if (!NT_SUCCESS(Status)) {
659 ERR("delete_tree_item returned %08lx\n", Status);
660 return Status;
661 }
662
664 if (!NT_SUCCESS(Status)) {
665 ERR("insert_tree_item returned %08lx\n", Status);
666 return Status;
667 }
668
669 return STATUS_SUCCESS;
670 }
671 } else {
672 ERR("unhandled extent type %x\n", type);
674 }
675 }
676
677 len -= sectlen;
678 ptr += sizeof(uint8_t) + sectlen;
679 inline_rc += sectcount;
680 }
681
683
684 max_extent_item_size = (Vcb->superblock.node_size >> 4) - sizeof(leaf_node);
685
686 // If we can, add entry as inline extent item
687
688 if (inline_rc == ei->refcount && tp.item->size + sizeof(uint8_t) + datalen < max_extent_item_size) {
689 len = tp.item->size - sizeof(EXTENT_ITEM);
690 ptr = (uint8_t*)&ei[1];
691
692 if (ei->flags & EXTENT_ITEM_TREE_BLOCK && !skinny) {
693 len -= sizeof(EXTENT_ITEM2);
694 ptr += sizeof(EXTENT_ITEM2);
695 }
696
697 // Confusingly, it appears that references are sorted forward by type (i.e. EXTENT_DATA_REFs before
698 // SHARED_DATA_REFs), but then backwards by hash...
699
700 while (len > 0) {
701 uint8_t secttype = *ptr;
702 ULONG sectlen = get_extent_data_len(secttype);
703
704 if (secttype > type)
705 break;
706
707 if (secttype == type) {
708 uint64_t sectoff = get_extent_hash(secttype, ptr + 1);
709
710 if (sectoff < offset)
711 break;
712 }
713
714 len -= sectlen + sizeof(uint8_t);
715 ptr += sizeof(uint8_t) + sectlen;
716 }
717
719 RtlCopyMemory(newei, tp.item->data, ptr - tp.item->data);
720
722
723 if (len > 0)
724 RtlCopyMemory((uint8_t*)newei + (ptr - tp.item->data) + sizeof(uint8_t) + datalen, ptr, len);
725
726 ptr = (ptr - tp.item->data) + (uint8_t*)newei;
727
728 *ptr = type;
730
732 if (!NT_SUCCESS(Status)) {
733 ERR("delete_tree_item returned %08lx\n", Status);
734 return Status;
735 }
736
737 Status = insert_tree_item(Vcb, Vcb->extent_root, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, newei, tp.item->size + sizeof(uint8_t) + datalen, NULL, Irp);
738 if (!NT_SUCCESS(Status)) {
739 ERR("insert_tree_item returned %08lx\n", Status);
740 return Status;
741 }
742
743 return STATUS_SUCCESS;
744 }
745
746 // Look for existing non-inline entry, and increase refcount if found
747
748 if (inline_rc != ei->refcount) {
749 traverse_ptr tp2;
750
751 searchkey.obj_id = address;
752 searchkey.obj_type = type;
753 searchkey.offset = offset;
754
755 Status = find_item(Vcb, Vcb->extent_root, &tp2, &searchkey, false, Irp);
756 if (!NT_SUCCESS(Status)) {
757 ERR("error - find_item returned %08lx\n", Status);
758 return Status;
759 }
760
761 if (!keycmp(tp2.item->key, searchkey)) {
762 if (type == TYPE_SHARED_DATA_REF && tp2.item->size < sizeof(uint32_t)) {
763 ERR("(%I64x,%x,%I64x) was %x bytes, expecting %Ix\n", tp2.item->key.obj_id, tp2.item->key.obj_type, tp2.item->key.offset, tp2.item->size, sizeof(uint32_t));
765 } else if (type != TYPE_SHARED_DATA_REF && tp2.item->size < datalen) {
766 ERR("(%I64x,%x,%I64x) was %x bytes, expecting %x\n", tp2.item->key.obj_id, tp2.item->key.obj_type, tp2.item->key.offset, tp2.item->size, datalen);
768 }
769
771 if (!data2) {
772 ERR("out of memory\n");
774 }
775
776 RtlCopyMemory(data2, tp2.item->data, tp2.item->size);
777
778 if (type == TYPE_EXTENT_DATA_REF) {
780
782 } else if (type == TYPE_TREE_BLOCK_REF) {
783 TRACE("trying to increase refcount of non-shared tree extent\n");
784 return STATUS_SUCCESS;
785 } else if (type == TYPE_SHARED_BLOCK_REF)
786 return STATUS_SUCCESS;
787 else if (type == TYPE_SHARED_DATA_REF) {
788 uint32_t* sdr = (uint32_t*)data2;
789
791 } else {
792 ERR("unhandled extent type %x\n", type);
794 }
795
796 Status = delete_tree_item(Vcb, &tp2);
797 if (!NT_SUCCESS(Status)) {
798 ERR("delete_tree_item returned %08lx\n", Status);
799 return Status;
800 }
801
802 Status = insert_tree_item(Vcb, Vcb->extent_root, tp2.item->key.obj_id, tp2.item->key.obj_type, tp2.item->key.offset, data2, tp2.item->size, NULL, Irp);
803 if (!NT_SUCCESS(Status)) {
804 ERR("insert_tree_item returned %08lx\n", Status);
805 return Status;
806 }
807
809 if (!newei) {
810 ERR("out of memory\n");
812 }
813
814 RtlCopyMemory(newei, tp.item->data, tp.item->size);
815
817
819 if (!NT_SUCCESS(Status)) {
820 ERR("delete_tree_item returned %08lx\n", Status);
821 return Status;
822 }
823
825 if (!NT_SUCCESS(Status)) {
826 ERR("insert_tree_item returned %08lx\n", Status);
827 return Status;
828 }
829
830 return STATUS_SUCCESS;
831 }
832 }
833
834 // Otherwise, add new non-inline entry
835
836 if (type == TYPE_SHARED_DATA_REF) {
838
840 if (!data2) {
841 ERR("out of memory\n");
843 }
844
845 datalen = sizeof(uint32_t);
846
847 *((uint32_t*)data2) = sdr->count;
849 data2 = NULL;
850 datalen = 0;
851 } else {
853 if (!data2) {
854 ERR("out of memory\n");
856 }
857
859 }
860
862 if (!NT_SUCCESS(Status)) {
863 ERR("insert_tree_item returned %08lx\n", Status);
864 return Status;
865 }
866
868 if (!newei) {
869 ERR("out of memory\n");
871 }
872
873 RtlCopyMemory(newei, tp.item->data, tp.item->size);
874
876
878 if (!NT_SUCCESS(Status)) {
879 ERR("delete_tree_item returned %08lx\n", Status);
880 return Status;
881 }
882
884 if (!NT_SUCCESS(Status)) {
885 ERR("insert_tree_item returned %08lx\n", Status);
886 return Status;
887 }
888
889 return STATUS_SUCCESS;
890}
#define EXTENT_ITEM_DATA
Definition: btrfs.h:387
NTSTATUS increase_extent_refcount(device_extension *Vcb, uint64_t address, uint64_t size, uint8_t type, void *data, KEY *firstitem, uint8_t level, PIRP Irp)
Definition: extent-tree.c:454
KEY firstitem
Definition: btrfs.h:398
uint8_t level
Definition: btrfs.h:399
uint64_t generation
Definition: btrfs.h:393
Definition: tftpd.h:138

Referenced by add_metadata_reloc_extent_item(), increase_extent_refcount(), increase_extent_refcount_data(), snapshot_tree_copy(), and update_tree_extents().

◆ increase_extent_refcount_data()

NTSTATUS increase_extent_refcount_data ( device_extension Vcb,
uint64_t  address,
uint64_t  size,
uint64_t  root,
uint64_t  inode,
uint64_t  offset,
uint32_t  refcount,
PIRP  Irp 
)

Definition at line 892 of file extent-tree.c.

892 {
893 EXTENT_DATA_REF edr;
894
895 edr.root = root;
896 edr.objid = inode;
897 edr.offset = offset;
898 edr.count = refcount;
899
901}

Referenced by flush_changed_extent(), and snapshot_tree_copy().

◆ inherit_mode()

uint32_t inherit_mode ( fcb parfcb,
bool  is_dir 
)

Definition at line 1948 of file create.c.

1948 {
1949 uint32_t mode;
1950
1951 if (!parfcb)
1952 return 0755;
1953
1954 mode = parfcb->inode_item.st_mode & ~S_IFDIR;
1955 mode &= ~S_ISVTX; // clear sticky bit
1956 mode &= ~S_ISUID; // clear setuid bit
1957
1958 if (!is_dir)
1959 mode &= ~S_ISGID; // if not directory, clear setgid bit
1960
1961 return mode;
1962}
GLenum mode
Definition: glext.h:6217

Referenced by create_directory_fcb(), create_subvol(), file_create2(), and mknod().

◆ init_cache()

void init_cache ( )

Definition at line 85 of file cache.c.

85 {
90}
static BOOLEAN __stdcall acquire_for_read_ahead(PVOID Context, BOOLEAN Wait)
Definition: cache.c:59
CACHE_MANAGER_CALLBACKS cache_callbacks
Definition: cache.c:20
static BOOLEAN __stdcall acquire_for_lazy_write(PVOID Context, BOOLEAN Wait)
Definition: cache.c:22
static void __stdcall release_from_read_ahead(PVOID Context)
Definition: cache.c:73
static void __stdcall release_from_lazy_write(PVOID Context)
Definition: cache.c:43
PACQUIRE_FOR_LAZY_WRITE AcquireForLazyWrite
Definition: cctypes.h:39
PRELEASE_FROM_LAZY_WRITE ReleaseFromLazyWrite
Definition: cctypes.h:40
PACQUIRE_FOR_READ_AHEAD AcquireForReadAhead
Definition: cctypes.h:41
PRELEASE_FROM_READ_AHEAD ReleaseFromReadAhead
Definition: cctypes.h:42

Referenced by _Function_class_().

◆ init_device()

void init_device ( _In_ device_extension Vcb,
_Inout_ device dev,
_In_ bool  get_nums 
)

Definition at line 3416 of file btrfs.c.

3416 {
3418 ULONG aptelen;
3419 ATA_PASS_THROUGH_EX* apte;
3422
3423 dev->removable = is_device_removable(dev->devobj);
3424 dev->change_count = dev->removable ? get_device_change_count(dev->devobj) : 0;
3425
3426 if (get_nums) {
3428
3430 &sdn, sizeof(STORAGE_DEVICE_NUMBER), true, NULL);
3431
3432 if (!NT_SUCCESS(Status)) {
3433 WARN("IOCTL_STORAGE_GET_DEVICE_NUMBER returned %08lx\n", Status);
3434 dev->disk_num = 0xffffffff;
3435 dev->part_num = 0xffffffff;
3436 } else {
3437 dev->disk_num = sdn.DeviceNumber;
3438 dev->part_num = sdn.PartitionNumber;
3439 }
3440 }
3441
3442 dev->trim = false;
3443 dev->readonly = dev->seeding;
3444 dev->reloc = false;
3445 dev->num_trim_entries = 0;
3446 dev->stats_changed = false;
3447 InitializeListHead(&dev->trim_list);
3448
3449 if (!dev->readonly) {
3451 NULL, 0, true, NULL);
3453 dev->readonly = true;
3454 }
3455
3456 aptelen = sizeof(ATA_PASS_THROUGH_EX) + 512;
3458 if (!apte) {
3459 ERR("out of memory\n");
3460 return;
3461 }
3462
3463 RtlZeroMemory(apte, aptelen);
3464
3465 apte->Length = sizeof(ATA_PASS_THROUGH_EX);
3467 apte->DataTransferLength = aptelen - sizeof(ATA_PASS_THROUGH_EX);
3468 apte->TimeOutValue = 3;
3469 apte->DataBufferOffset = apte->Length;
3471
3472 Status = dev_ioctl(dev->devobj, IOCTL_ATA_PASS_THROUGH, apte, aptelen,
3473 apte, aptelen, true, NULL);
3474
3475 if (!NT_SUCCESS(Status))
3476 TRACE("IOCTL_ATA_PASS_THROUGH returned %08lx for IDENTIFY DEVICE\n", Status);
3477 else {
3479
3480 if (idd->CommandSetSupport.FlushCache) {
3481 dev->can_flush = true;
3482 TRACE("FLUSH CACHE supported\n");
3483 } else
3484 TRACE("FLUSH CACHE not supported\n");
3485 }
3486
3487 ExFreePool(apte);
3488
3489#ifdef DEBUG_TRIM_EMULATION
3490 dev->trim = true;
3491 Vcb->trim = true;
3492#else
3495 spq.AdditionalParameters[0] = 0;
3496
3498 &dtd, sizeof(DEVICE_TRIM_DESCRIPTOR), true, NULL);
3499
3500 if (NT_SUCCESS(Status)) {
3501 if (dtd.TrimEnabled) {
3502 dev->trim = true;
3503 Vcb->trim = true;
3504 TRACE("TRIM supported\n");
3505 } else
3506 TRACE("TRIM not supported\n");
3507 }
3508#endif
3509
3510 RtlZeroMemory(dev->stats, sizeof(uint64_t) * 5);
3511}
#define IDE_COMMAND_IDENTIFY
Definition: atapi.h:118
#define IOCTL_DISK_IS_WRITABLE
Definition: cdrw_usr.h:172
static ULONG get_device_change_count(_In_ PDEVICE_OBJECT devobj)
Definition: btrfs.c:3396
static bool is_device_removable(_In_ PDEVICE_OBJECT devobj)
Definition: btrfs.c:3382
#define IOCTL_STORAGE_QUERY_PROPERTY
Definition: ntddstor.h:178
@ StorageDeviceTrimProperty
Definition: ntddstor.h:520
@ PropertyStandardQuery
Definition: ntddstor.h:505
#define IOCTL_ATA_PASS_THROUGH
Definition: ntddscsi.h:40
struct _ATA_PASS_THROUGH_EX ATA_PASS_THROUGH_EX
ULONG DataTransferLength
Definition: ntddscsi.h:198
UCHAR CurrentTaskFile[8]
Definition: ntddscsi.h:203
ULONG_PTR DataBufferOffset
Definition: ntddscsi.h:201
struct _IDENTIFY_DEVICE_DATA::@1888 CommandSetSupport
STORAGE_QUERY_TYPE QueryType
Definition: ntddstor.h:553
UCHAR AdditionalParameters[1]
Definition: ntddstor.h:554
STORAGE_PROPERTY_ID PropertyId
Definition: ntddstor.h:552
#define ATA_FLAGS_DATA_IN
Definition: uata_ctl.h:222
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161

Referenced by add_device(), add_volume_device(), load_chunk_root(), and mount_vol().

◆ init_fast_io_dispatch()

void init_fast_io_dispatch ( FAST_IO_DISPATCH **  fiod)

Definition at line 535 of file fastio.c.

535 {
537
539
540 FastIoDispatch.FastIoCheckIfPossible = fast_io_check_if_possible;
542 FastIoDispatch.FastIoWrite = fast_io_write;
543 FastIoDispatch.FastIoQueryBasicInfo = fast_query_basic_info;
544 FastIoDispatch.FastIoQueryStandardInfo = fast_query_standard_info;
545 FastIoDispatch.FastIoLock = fast_io_lock;
546 FastIoDispatch.FastIoUnlockSingle = fast_io_unlock_single;
547 FastIoDispatch.FastIoUnlockAll = fast_io_unlock_all;
548 FastIoDispatch.FastIoUnlockAllByKey = fast_io_unlock_all_by_key;
551 FastIoDispatch.FastIoQueryNetworkOpenInfo = fast_io_query_network_open_info;
552 FastIoDispatch.AcquireForModWrite = fast_io_acquire_for_mod_write;
557 FastIoDispatch.ReleaseForModWrite = fast_io_release_for_mod_write;
558 FastIoDispatch.AcquireForCcFlush = fast_io_acquire_for_ccflush;
559 FastIoDispatch.ReleaseForCcFlush = fast_io_release_for_ccflush;
560
561 *fiod = &FastIoDispatch;
562}
static void __stdcall fast_io_release_for_create_section(_In_ PFILE_OBJECT FileObject)
Definition: fastio.c:518
FAST_IO_DISPATCH FastIoDispatch
Definition: fastio.c:20
static void __stdcall fast_io_acquire_for_create_section(_In_ PFILE_OBJECT FileObject)
Definition: fastio.c:498
BOOLEAN NTAPI FsRtlMdlWriteCompleteDev(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PMDL MdlChain, IN PDEVICE_OBJECT DeviceObject)
Definition: fastio.c:1198
BOOLEAN NTAPI FsRtlMdlReadCompleteDev(IN PFILE_OBJECT FileObject, IN PMDL MemoryDescriptorList, IN PDEVICE_OBJECT DeviceObject)
Definition: fastio.c:1011
BOOLEAN NTAPI FsRtlCopyRead(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, IN ULONG LockKey, OUT PVOID Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject)
Definition: fastio.c:64
BOOLEAN NTAPI FsRtlPrepareMdlWriteDev(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG LockKey, OUT PMDL *MdlChain, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject)
Definition: fastio.c:1272
BOOLEAN NTAPI FsRtlMdlReadDev(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG LockKey, OUT PMDL *MdlChain, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject)
Definition: fastio.c:1025
PFAST_IO_ACQUIRE_FOR_MOD_WRITE AcquireForModWrite
Definition: iotypes.h:1748
PFAST_IO_QUERY_STANDARD_INFO FastIoQueryStandardInfo
Definition: iotypes.h:1738
PFAST_IO_UNLOCK_ALL_BY_KEY FastIoUnlockAllByKey
Definition: iotypes.h:1742
PFAST_IO_RELEASE_FOR_CCFLUSH ReleaseForCcFlush
Definition: iotypes.h:1760
PFAST_IO_MDL_READ_COMPLETE MdlReadComplete
Definition: iotypes.h:1750
PFAST_IO_MDL_READ MdlRead
Definition: iotypes.h:1749
PFAST_IO_WRITE FastIoWrite
Definition: iotypes.h:1736
PFAST_IO_UNLOCK_ALL FastIoUnlockAll
Definition: iotypes.h:1741
PFAST_IO_QUERY_NETWORK_OPEN_INFO FastIoQueryNetworkOpenInfo
Definition: iotypes.h:1747
PFAST_IO_ACQUIRE_FOR_CCFLUSH AcquireForCcFlush
Definition: iotypes.h:1759
PFAST_IO_MDL_WRITE_COMPLETE MdlWriteComplete
Definition: iotypes.h:1752
ULONG SizeOfFastIoDispatch
Definition: iotypes.h:1733
PFAST_IO_ACQUIRE_FILE AcquireFileForNtCreateSection
Definition: iotypes.h:1744
PFAST_IO_READ FastIoRead
Definition: iotypes.h:1735
PFAST_IO_QUERY_BASIC_INFO FastIoQueryBasicInfo
Definition: iotypes.h:1737
PFAST_IO_LOCK FastIoLock
Definition: iotypes.h:1739
PFAST_IO_UNLOCK_SINGLE FastIoUnlockSingle
Definition: iotypes.h:1740
PFAST_IO_RELEASE_FILE ReleaseFileForNtCreateSection
Definition: iotypes.h:1745
PFAST_IO_PREPARE_MDL_WRITE PrepareMdlWrite
Definition: iotypes.h:1751
PFAST_IO_RELEASE_FOR_MOD_WRITE ReleaseForModWrite
Definition: iotypes.h:1758
PFAST_IO_CHECK_IF_POSSIBLE FastIoCheckIfPossible
Definition: iotypes.h:1734
struct _FAST_IO_DISPATCH FAST_IO_DISPATCH

Referenced by _Function_class_().

◆ init_file_cache()

void init_file_cache ( _In_ PFILE_OBJECT  FileObject,
_In_ CC_FILE_SIZES ccfs 
)

Definition at line 4069 of file btrfs.c.

4069 {
4070 TRACE("(%p, %p)\n", FileObject, ccfs);
4071
4073
4074 if (diskacc)
4076
4078}
CACHE_MANAGER_CALLBACKS cache_callbacks
Definition: cache.c:20
#define READ_AHEAD_GRANULARITY
Definition: btrfs_drv.h:114
#define CC_ENABLE_DISK_IO_ACCOUNTING
Definition: btrfs_drv.h:1845
VOID NTAPI CcSetReadAheadGranularity(IN PFILE_OBJECT FileObject, IN ULONG Granularity)
Definition: cachesub.c:36
bool diskacc
Definition: btrfs.c:101
tCcSetAdditionalCacheAttributesEx fCcSetAdditionalCacheAttributesEx
Definition: btrfs.c:93
VOID NTAPI CcInitializeCacheMap(IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSizes, IN BOOLEAN PinAccess, IN PCACHE_MANAGER_CALLBACKS Callbacks, IN PVOID LazyWriteContext)
Definition: fssup.c:195

Referenced by __attribute__(), and do_read().

◆ insert_dir_child_into_hash_lists()

void insert_dir_child_into_hash_lists ( fcb fcb,
dir_child dc 
)

Definition at line 1470 of file fileinfo.c.

1470 {
1471 bool inserted;
1472 LIST_ENTRY* le;
1473 uint8_t c, d;
1474
1475 c = dc->hash >> 24;
1476
1477 inserted = false;
1478
1479 d = c;
1480 do {
1481 le = fcb->hash_ptrs[d];
1482
1483 if (d == 0)
1484 break;
1485
1486 d--;
1487 } while (!le);
1488
1489 if (!le)
1491
1492 while (le != &fcb->dir_children_hash) {
1493 dir_child* dc2 = CONTAINING_RECORD(le, dir_child, list_entry_hash);
1494
1495 if (dc2->hash > dc->hash) {
1496 InsertHeadList(le->Blink, &dc->list_entry_hash);
1497 inserted = true;
1498 break;
1499 }
1500
1501 le = le->Flink;
1502 }
1503
1504 if (!inserted)
1505 InsertTailList(&fcb->dir_children_hash, &dc->list_entry_hash);
1506
1507 if (!fcb->hash_ptrs[c])
1508 fcb->hash_ptrs[c] = &dc->list_entry_hash;
1509 else {
1510 dir_child* dc2 = CONTAINING_RECORD(fcb->hash_ptrs[c], dir_child, list_entry_hash);
1511
1512 if (dc2->hash > dc->hash)
1513 fcb->hash_ptrs[c] = &dc->list_entry_hash;
1514 }
1515
1516 c = dc->hash_uc >> 24;
1517
1518 inserted = false;
1519
1520 d = c;
1521 do {
1522 le = fcb->hash_ptrs_uc[d];
1523
1524 if (d == 0)
1525 break;
1526
1527 d--;
1528 } while (!le);
1529
1530 if (!le)
1532
1533 while (le != &fcb->dir_children_hash_uc) {
1534 dir_child* dc2 = CONTAINING_RECORD(le, dir_child, list_entry_hash_uc);
1535
1536 if (dc2->hash_uc > dc->hash_uc) {
1537 InsertHeadList(le->Blink, &dc->list_entry_hash_uc);
1538 inserted = true;
1539 break;
1540 }
1541
1542 le = le->Flink;
1543 }
1544
1545 if (!inserted)
1546 InsertTailList(&fcb->dir_children_hash_uc, &dc->list_entry_hash_uc);
1547
1548 if (!fcb->hash_ptrs_uc[c])
1549 fcb->hash_ptrs_uc[c] = &dc->list_entry_hash_uc;
1550 else {
1551 dir_child* dc2 = CONTAINING_RECORD(fcb->hash_ptrs_uc[c], dir_child, list_entry_hash_uc);
1552
1553 if (dc2->hash_uc > dc->hash_uc)
1554 fcb->hash_ptrs_uc[c] = &dc->list_entry_hash_uc;
1555 }
1556}
uint32_t hash
Definition: btrfs_drv.h:255
uint32_t hash_uc
Definition: btrfs_drv.h:257

Referenced by add_dir_child(), load_dir_children(), move_across_subvols(), and set_rename_information().

◆ insert_tree_item()

◆ is_extent_unique()

bool is_extent_unique ( device_extension Vcb,
uint64_t  address,
uint64_t  size,
PIRP  Irp 
)

Definition at line 1697 of file extent-tree.c.

1697 {
1698 KEY searchkey;
1699 traverse_ptr tp, next_tp;
1701 uint64_t rc, rcrun, root = 0, inode = 0, offset = 0;
1702 uint32_t len;
1703 EXTENT_ITEM* ei;
1704 uint8_t* ptr;
1705 bool b;
1706
1708
1709 if (rc == 1)
1710 return true;
1711
1712 if (rc == 0)
1713 return false;
1714
1715 searchkey.obj_id = address;
1716 searchkey.obj_type = TYPE_EXTENT_ITEM;
1717 searchkey.offset = size;
1718
1719 Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, Irp);
1720 if (!NT_SUCCESS(Status)) {
1721 WARN("error - find_item returned %08lx\n", Status);
1722 return false;
1723 }
1724
1725 if (keycmp(tp.item->key, searchkey)) {
1726 WARN("could not find (%I64x,%x,%I64x)\n", searchkey.obj_id, searchkey.obj_type, searchkey.offset);
1727 return false;
1728 }
1729
1730 if (tp.item->size == sizeof(EXTENT_ITEM_V0))
1731 return false;
1732
1733 if (tp.item->size < sizeof(EXTENT_ITEM)) {
1734 WARN("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(EXTENT_ITEM));
1735 return false;
1736 }
1737
1738 ei = (EXTENT_ITEM*)tp.item->data;
1739
1740 len = tp.item->size - sizeof(EXTENT_ITEM);
1741 ptr = (uint8_t*)&ei[1];
1742
1743 if (ei->flags & EXTENT_ITEM_TREE_BLOCK) {
1744 if (tp.item->size < sizeof(EXTENT_ITEM) + sizeof(EXTENT_ITEM2)) {
1745 WARN("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(EXTENT_ITEM) + sizeof(EXTENT_ITEM2));
1746 return false;
1747 }
1748
1749 len -= sizeof(EXTENT_ITEM2);
1750 ptr += sizeof(EXTENT_ITEM2);
1751 }
1752
1753 rcrun = 0;
1754
1755 // Loop through inline extent entries
1756
1757 while (len > 0) {
1758 uint8_t secttype = *ptr;
1759 ULONG sectlen = get_extent_data_len(secttype);
1760 uint64_t sectcount = get_extent_data_refcount(secttype, ptr + sizeof(uint8_t));
1761
1762 len--;
1763
1764 if (sectlen > len) {
1765 WARN("(%I64x,%x,%I64x): %x bytes left, expecting at least %lx\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, len, sectlen);
1766 return false;
1767 }
1768
1769 if (sectlen == 0) {
1770 WARN("(%I64x,%x,%I64x): unrecognized extent type %x\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, secttype);
1771 return false;
1772 }
1773
1774 if (secttype == TYPE_EXTENT_DATA_REF) {
1775 EXTENT_DATA_REF* sectedr = (EXTENT_DATA_REF*)(ptr + sizeof(uint8_t));
1776
1777 if (root == 0 && inode == 0) {
1778 root = sectedr->root;
1779 inode = sectedr->objid;
1780 offset = sectedr->offset;
1781 } else if (root != sectedr->root || inode != sectedr->objid || offset != sectedr->offset)
1782 return false;
1783 } else
1784 return false;
1785
1786 len -= sectlen;
1787 ptr += sizeof(uint8_t) + sectlen;
1788 rcrun += sectcount;
1789 }
1790
1791 if (rcrun == rc)
1792 return true;
1793
1794 // Loop through non-inlines if some refs still unaccounted for
1795
1796 do {
1797 b = find_next_item(Vcb, &tp, &next_tp, false, Irp);
1798
1799 if (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == TYPE_EXTENT_DATA_REF) {
1801
1802 if (tp.item->size < sizeof(EXTENT_DATA_REF)) {
1803 WARN("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset,
1804 tp.item->size, sizeof(EXTENT_ITEM) + sizeof(EXTENT_ITEM2));
1805 return false;
1806 }
1807
1808 if (root == 0 && inode == 0) {
1809 root = edr->root;
1810 inode = edr->objid;
1811 offset = edr->offset;
1812 } else if (root != edr->root || inode != edr->objid || offset != edr->offset)
1813 return false;
1814
1815 rcrun += edr->count;
1816 }
1817
1818 if (rcrun == rc)
1819 return true;
1820
1821 if (b) {
1822 tp = next_tp;
1823
1824 if (tp.item->key.obj_id > searchkey.obj_id)
1825 break;
1826 }
1827 } while (b);
1828
1829 // If we reach this point, there's still some refs unaccounted for somewhere.
1830 // Return false in case we mess things up elsewhere.
1831
1832 return false;
1833}
uint64_t get_extent_refcount(device_extension *Vcb, uint64_t address, uint64_t size, PIRP Irp)
Definition: extent-tree.c:1651

◆ is_subvol_readonly()

static __inline bool is_subvol_readonly ( root r,
PIRP  Irp 
)
static

Definition at line 1033 of file btrfs_drv.h.

1033 {
1034 if (!(r->root_item.flags & BTRFS_SUBVOL_READONLY))
1035 return false;
1036
1037 if (!r->reserved)
1038 return true;
1039
1040 return (!Irp || Irp->RequestorMode == UserMode) && PsGetCurrentProcess() != r->reserved ? true : false;
1041}
#define PsGetCurrentProcess
Definition: psfuncs.h:17

Referenced by _Dispatch_type_(), _Function_class_(), create_snapshot(), create_subvol(), duplicate_extents(), file_create(), fsctl_set_xattr(), mknod(), open_file2(), set_basic_information(), set_file_security(), set_inode_info(), and set_rename_information().

◆ is_top_level()

bool is_top_level ( _In_ PIRP  Irp)

Definition at line 278 of file btrfs.c.

278 {
279 if (!IoGetTopLevelIrp()) {
281 return true;
282 }
283
284 return false;
285}

Referenced by _Dispatch_type_(), do_read_job(), and do_write_job().

◆ is_tree_unique()

bool is_tree_unique ( device_extension Vcb,
tree t,
PIRP  Irp 
)

Definition at line 3243 of file flushthread.c.

3243 {
3244 KEY searchkey;
3247 bool ret = false;
3248 EXTENT_ITEM* ei;
3249 uint8_t* type;
3250
3251 if (t->uniqueness_determined)
3252 return t->is_unique;
3253
3254 if (t->parent && !is_tree_unique(Vcb, t->parent, Irp))
3255 goto end;
3256
3257 if (t->has_address) {
3258 searchkey.obj_id = t->header.address;
3259 searchkey.obj_type = Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA ? TYPE_METADATA_ITEM : TYPE_EXTENT_ITEM;
3260 searchkey.offset = 0xffffffffffffffff;
3261
3262 Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, Irp);
3263 if (!NT_SUCCESS(Status)) {
3264 ERR("error - find_item returned %08lx\n", Status);
3265 goto end;
3266 }
3267
3268 if (tp.item->key.obj_id != t->header.address || (tp.item->key.obj_type != TYPE_METADATA_ITEM && tp.item->key.obj_type != TYPE_EXTENT_ITEM))
3269 goto end;
3270
3271 if (tp.item->key.obj_type == TYPE_EXTENT_ITEM && tp.item->size == sizeof(EXTENT_ITEM_V0))
3272 goto end;
3273
3274 if (tp.item->size < sizeof(EXTENT_ITEM))
3275 goto end;
3276
3277 ei = (EXTENT_ITEM*)tp.item->data;
3278
3279 if (ei->refcount > 1)
3280 goto end;
3281
3283 EXTENT_ITEM2* ei2;
3284
3285 if (tp.item->size < sizeof(EXTENT_ITEM) + sizeof(EXTENT_ITEM2))
3286 goto end;
3287
3288 ei2 = (EXTENT_ITEM2*)&ei[1];
3289 type = (uint8_t*)&ei2[1];
3290 } else
3291 type = (uint8_t*)&ei[1];
3292
3293 if (type >= tp.item->data + tp.item->size || *type != TYPE_TREE_BLOCK_REF)
3294 goto end;
3295 }
3296
3297 ret = true;
3298
3299end:
3300 t->is_unique = ret;
3301 t->uniqueness_determined = true;
3302
3303 return ret;
3304}
bool is_tree_unique(device_extension *Vcb, tree *t, PIRP Irp)
Definition: flushthread.c:3243
int ret

Referenced by do_splits(), is_tree_unique(), and try_tree_amalgamate().

◆ load_cache_chunk()

NTSTATUS load_cache_chunk ( device_extension Vcb,
chunk c,
PIRP  Irp 
)

Definition at line 980 of file free-space.c.

980 {
982
983 if (c->cache_loaded)
984 return STATUS_SUCCESS;
985
987 if (!NT_SUCCESS(Status)) {
988 ERR("load_free_space_cache returned %08lx\n", Status);
989 return Status;
990 }
991
993
994 c->cache_loaded = true;
995
996 return STATUS_SUCCESS;
997}
void protect_superblocks(_Inout_ chunk *c)
Definition: btrfs.c:3777
static NTSTATUS load_free_space_cache(device_extension *Vcb, chunk *c, PIRP Irp)
Definition: free-space.c:886

Referenced by __attribute__(), _Function_class_(), allocate_tree_extents(), clear_free_space_cache(), find_metadata_address_in_chunk(), rationalize_extents(), reduce_tree_extent(), and update_chunk_usage().

◆ load_csum()

NTSTATUS load_csum ( _Requires_lock_held_(_Curr_->tree_lock) device_extension Vcb,
void csum,
uint64_t  start,
uint64_t  length,
PIRP  Irp 
)

Definition at line 453 of file create.c.

453 {
455 KEY searchkey;
456 traverse_ptr tp, next_tp;
457 uint64_t i, j;
458 bool b;
459 void* ptr = csum;
460
461 searchkey.obj_id = EXTENT_CSUM_ID;
462 searchkey.obj_type = TYPE_EXTENT_CSUM;
463 searchkey.offset = start;
464
465 Status = find_item(Vcb, Vcb->checksum_root, &tp, &searchkey, false, Irp);
466 if (!NT_SUCCESS(Status)) {
467 ERR("error - find_item returned %08lx\n", Status);
468 return Status;
469 }
470
471 i = 0;
472 do {
473 if (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == searchkey.obj_type) {
474 ULONG readlen;
475
476 if (start < tp.item->key.offset)
477 j = 0;
478 else
479 j = ((start - tp.item->key.offset) >> Vcb->sector_shift) + i;
480
481 if (j * Vcb->csum_size > tp.item->size || tp.item->key.offset > start + (i << Vcb->sector_shift)) {
482 ERR("checksum not found for %I64x\n", start + (i << Vcb->sector_shift));
484 }
485
486 readlen = (ULONG)min((tp.item->size / Vcb->csum_size) - j, length - i);
487 RtlCopyMemory(ptr, tp.item->data + (j * Vcb->csum_size), readlen * Vcb->csum_size);
488
489 ptr = (uint8_t*)ptr + (readlen * Vcb->csum_size);
490 i += readlen;
491
492 if (i == length)
493 break;
494 }
495
496 b = find_next_item(Vcb, &tp, &next_tp, false, Irp);
497
498 if (b)
499 tp = next_tp;
500 } while (b);
501
502 if (i < length) {
503 ERR("could not read checksums: offset %I64x, length %I64x sectors\n", start, length);
505 }
506
507 return STATUS_SUCCESS;
508}
Definition: copy.c:22

Referenced by fcb_load_csums(), and flush_extents().

◆ load_dir_children()

NTSTATUS load_dir_children ( _Requires_lock_held_(_Curr_->tree_lock) device_extension Vcb,
fcb fcb,
bool  ignore_size,
PIRP  Irp 
)

Definition at line 510 of file create.c.

510 {
511 KEY searchkey;
512 traverse_ptr tp, next_tp;
514 ULONG num_children = 0;
515 uint64_t max_index = 2;
516
518 if (!fcb->hash_ptrs) {
519 ERR("out of memory\n");
521 }
522
523 RtlZeroMemory(fcb->hash_ptrs, sizeof(LIST_ENTRY*) * 256);
524
526 if (!fcb->hash_ptrs_uc) {
527 ERR("out of memory\n");
529 }
530
531 RtlZeroMemory(fcb->hash_ptrs_uc, sizeof(LIST_ENTRY*) * 256);
532
533 if (!ignore_size && fcb->inode_item.st_size == 0)
534 return STATUS_SUCCESS;
535
536 searchkey.obj_id = fcb->inode;
537 searchkey.obj_type = TYPE_DIR_INDEX;
538 searchkey.offset = 2;
539
540 Status = find_item(Vcb, fcb->subvol, &tp, &searchkey, false, Irp);
541 if (!NT_SUCCESS(Status)) {
542 ERR("find_item returned %08lx\n", Status);
543 return Status;
544 }
545
546 if (keycmp(tp.item->key, searchkey) == -1) {
547 if (find_next_item(Vcb, &tp, &next_tp, false, Irp)) {
548 tp = next_tp;
549 TRACE("moving on to %I64x,%x,%I64x\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset);
550 }
551 }
552
553 while (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == searchkey.obj_type) {
554 DIR_ITEM* di = (DIR_ITEM*)tp.item->data;
555 dir_child* dc;
556 ULONG utf16len;
557
558 if (tp.item->size < sizeof(DIR_ITEM)) {
559 WARN("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(DIR_ITEM));
560 goto cont;
561 }
562
563 if (di->n == 0) {
564 WARN("(%I64x,%x,%I64x): DIR_ITEM name length is zero\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset);
565 goto cont;
566 }
567
568 Status = utf8_to_utf16(NULL, 0, &utf16len, di->name, di->n);
569 if (!NT_SUCCESS(Status)) {
570 ERR("utf8_to_utf16 1 returned %08lx\n", Status);
571 goto cont;
572 }
573
575 if (!dc) {
576 ERR("out of memory\n");
578 }
579
580 dc->key = di->key;
581 dc->index = tp.item->key.offset;
582 dc->type = di->type;
583 dc->fileref = NULL;
584 dc->root_dir = false;
585
586 max_index = dc->index;
587
588 dc->utf8.MaximumLength = dc->utf8.Length = di->n;
589 dc->utf8.Buffer = ExAllocatePoolWithTag(PagedPool, di->n, ALLOC_TAG);
590 if (!dc->utf8.Buffer) {
591 ERR("out of memory\n");
592 ExFreePool(dc);
594 }
595
596 RtlCopyMemory(dc->utf8.Buffer, di->name, di->n);
597
598 dc->name.MaximumLength = dc->name.Length = (uint16_t)utf16len;
599 dc->name.Buffer = ExAllocatePoolWithTag(PagedPool, dc->name.MaximumLength, ALLOC_TAG);
600 if (!dc->name.Buffer) {
601 ERR("out of memory\n");
602 ExFreePool(dc->utf8.Buffer);
603 ExFreePool(dc);
605 }
606
607 Status = utf8_to_utf16(dc->name.Buffer, utf16len, &utf16len, di->name, di->n);
608 if (!NT_SUCCESS(Status)) {
609 ERR("utf8_to_utf16 2 returned %08lx\n", Status);
610 ExFreePool(dc->utf8.Buffer);
611 ExFreePool(dc->name.Buffer);
612 ExFreePool(dc);
613 goto cont;
614 }
615
616 Status = RtlUpcaseUnicodeString(&dc->name_uc, &dc->name, true);
617 if (!NT_SUCCESS(Status)) {
618 ERR("RtlUpcaseUnicodeString returned %08lx\n", Status);
619 ExFreePool(dc->utf8.Buffer);
620 ExFreePool(dc->name.Buffer);
621 ExFreePool(dc);
622 goto cont;
623 }
624
625 dc->hash = calc_crc32c(0xffffffff, (uint8_t*)dc->name.Buffer, dc->name.Length);
626 dc->hash_uc = calc_crc32c(0xffffffff, (uint8_t*)dc->name_uc.Buffer, dc->name_uc.Length);
627
628 InsertTailList(&fcb->dir_children_index, &dc->list_entry_index);
629
631
632 num_children++;
633
634cont:
635 if (find_next_item(Vcb, &tp, &next_tp, false, Irp))
636 tp = next_tp;
637 else
638 break;
639 }
640
641 if (!Vcb->options.no_root_dir && fcb->inode == SUBVOL_ROOT_INODE) {
642 root* top_subvol;
643
644 if (Vcb->root_fileref && Vcb->root_fileref->fcb)
645 top_subvol = Vcb->root_fileref->fcb->subvol;
646 else
647 top_subvol = find_default_subvol(Vcb, NULL);
648
649 if (fcb->subvol == top_subvol && top_subvol->id != BTRFS_ROOT_FSTREE) {
651 if (!dc) {
652 ERR("out of memory\n");
654 }
655
656 dc->key.obj_id = BTRFS_ROOT_FSTREE;
657 dc->key.obj_type = TYPE_ROOT_ITEM;
658 dc->key.offset = 0;
659 dc->index = max_index + 1;
660 dc->type = BTRFS_TYPE_DIRECTORY;
661 dc->fileref = NULL;
662 dc->root_dir = true;
663
664 dc->utf8.MaximumLength = dc->utf8.Length = sizeof(root_dir) - sizeof(char);
665 dc->utf8.Buffer = ExAllocatePoolWithTag(PagedPool, sizeof(root_dir) - sizeof(char), ALLOC_TAG);
666 if (!dc->utf8.Buffer) {
667 ERR("out of memory\n");
668 ExFreePool(dc);
670 }
671
672 RtlCopyMemory(dc->utf8.Buffer, root_dir, sizeof(root_dir) - sizeof(char));
673
674 dc->name.MaximumLength = dc->name.Length = sizeof(root_dir_utf16) - sizeof(WCHAR);
675 dc->name.Buffer = ExAllocatePoolWithTag(PagedPool, sizeof(root_dir_utf16) - sizeof(WCHAR), ALLOC_TAG);
676 if (!dc->name.Buffer) {
677 ERR("out of memory\n");
678 ExFreePool(dc->utf8.Buffer);
679 ExFreePool(dc);
681 }
682
683 RtlCopyMemory(dc->name.Buffer, root_dir_utf16, sizeof(root_dir_utf16) - sizeof(WCHAR));
684
685 Status = RtlUpcaseUnicodeString(&dc->name_uc, &dc->name, true);
686 if (!NT_SUCCESS(Status)) {
687 ERR("RtlUpcaseUnicodeString returned %08lx\n", Status);
688 ExFreePool(dc->utf8.Buffer);
689 ExFreePool(dc->name.Buffer);
690 ExFreePool(dc);
691 goto cont;
692 }
693
694 dc->hash = calc_crc32c(0xffffffff, (uint8_t*)dc->name.Buffer, dc->name.Length);
695 dc->hash_uc = calc_crc32c(0xffffffff, (uint8_t*)dc->name_uc.Buffer, dc->name_uc.Length);
696
697 InsertTailList(&fcb->dir_children_index, &dc->list_entry_index);
698
700 }
701 }
702
703 return STATUS_SUCCESS;
704}
_Ret_maybenull_ root * find_default_subvol(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_opt_ PIRP Irp)
Definition: btrfs.c:3981
#define TYPE_DIR_INDEX
Definition: btrfs.h:29
static const char root_dir[]
Definition: create.c:32
static const WCHAR root_dir_utf16[]
Definition: create.c:33
uint8_t type
Definition: btrfs.h:277
uint64_t id
Definition: btrfs_drv.h:451

Referenced by mount_vol().

◆ load_stored_free_space_cache()

NTSTATUS load_stored_free_space_cache ( device_extension Vcb,
chunk c,
bool  load_only,
PIRP  Irp 
)

Definition at line 466 of file free-space.c.

466 {
467 KEY searchkey;
469 FREE_SPACE_ITEM* fsi;
471 uint8_t* data;
473 uint32_t *checksums, crc32, num_sectors, num_valid_sectors, size;
474 FREE_SPACE_ENTRY* fse;
475 uint64_t num_entries, num_bitmaps, extent_length, bmpnum, off, total_space = 0, superblock_size;
476 LIST_ENTRY *le, rollback;
477
478 // FIXME - does this break if Vcb->superblock.sector_size is not 4096?
479
480 TRACE("(%p, %I64x)\n", Vcb, c->offset);
481
482 searchkey.obj_id = FREE_SPACE_CACHE_ID;
483 searchkey.obj_type = 0;
484 searchkey.offset = c->offset;
485
486 Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
487 if (!NT_SUCCESS(Status)) {
488 ERR("error - find_item returned %08lx\n", Status);
489 return Status;
490 }
491
492 if (keycmp(tp.item->key, searchkey)) {
493 TRACE("(%I64x,%x,%I64x) not found\n", searchkey.obj_id, searchkey.obj_type, searchkey.offset);
494 return STATUS_NOT_FOUND;
495 }
496
497 if (tp.item->size < sizeof(FREE_SPACE_ITEM)) {
498 WARN("(%I64x,%x,%I64x) was %u bytes, expected %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(FREE_SPACE_ITEM));
499 return STATUS_NOT_FOUND;
500 }
501
502 fsi = (FREE_SPACE_ITEM*)tp.item->data;
503
504 if (fsi->key.obj_type != TYPE_INODE_ITEM) {
505 WARN("cache pointed to something other than an INODE_ITEM\n");
506 return STATUS_NOT_FOUND;
507 }
508
509 inode = fsi->key.obj_id;
510 num_entries = fsi->num_entries;
511 num_bitmaps = fsi->num_bitmaps;
512
513 Status = open_fcb(Vcb, Vcb->root_root, inode, BTRFS_TYPE_FILE, NULL, false, NULL, &c->cache, PagedPool, Irp);
514 if (!NT_SUCCESS(Status)) {
515 ERR("open_fcb returned %08lx\n", Status);
516 return STATUS_NOT_FOUND;
517 }
518
519 if (load_only)
520 return STATUS_SUCCESS;
521
522 if (c->cache->inode_item.st_size == 0) {
523 WARN("cache had zero length\n");
524 free_fcb(c->cache);
525 c->cache = NULL;
526 return STATUS_NOT_FOUND;
527 }
528
529 c->cache->inode_item.flags |= BTRFS_INODE_NODATACOW;
530
531 if (num_entries == 0 && num_bitmaps == 0)
532 return STATUS_SUCCESS;
533
534 size = (uint32_t)sector_align(c->cache->inode_item.st_size, Vcb->superblock.sector_size);
535
537
538 if (!data) {
539 ERR("out of memory\n");
540 free_fcb(c->cache);
541 c->cache = NULL;
543 }
544
545 if (c->chunk_item->size < 0x6400000) { // 100 MB
546 WARN("deleting free space cache for chunk smaller than 100MB\n");
547 goto clearcache;
548 }
549
550 Status = read_file(c->cache, data, 0, c->cache->inode_item.st_size, NULL, NULL);
551 if (!NT_SUCCESS(Status)) {
552 ERR("read_file returned %08lx\n", Status);
554
555 c->cache->deleted = true;
556 mark_fcb_dirty(c->cache);
557
558 free_fcb(c->cache);
559 c->cache = NULL;
560 return STATUS_NOT_FOUND;
561 }
562
563 if (size > c->cache->inode_item.st_size)
564 RtlZeroMemory(&data[c->cache->inode_item.st_size], (ULONG)(size - c->cache->inode_item.st_size));
565
566 num_sectors = size >> Vcb->sector_shift;
567
568 generation = (uint64_t*)(data + (num_sectors * sizeof(uint32_t)));
569
570 if (*generation != fsi->generation) {
571 WARN("free space cache generation for %I64x was %I64x, expected %I64x\n", c->offset, *generation, fsi->generation);
572 goto clearcache;
573 }
574
575 extent_length = (num_sectors * sizeof(uint32_t)) + sizeof(uint64_t) + (num_entries * sizeof(FREE_SPACE_ENTRY));
576
577 num_valid_sectors = (ULONG)((sector_align(extent_length, Vcb->superblock.sector_size) >> Vcb->sector_shift) + num_bitmaps);
578
579 if (num_valid_sectors > num_sectors) {
580 ERR("free space cache for %I64x was %u sectors, expected at least %u\n", c->offset, num_sectors, num_valid_sectors);
581 goto clearcache;
582 }
583
584 checksums = (uint32_t*)data;
585
586 for (uint32_t i = 0; i < num_valid_sectors; i++) {
587 if (i << Vcb->sector_shift > sizeof(uint32_t) * num_sectors)
588 crc32 = ~calc_crc32c(0xffffffff, &data[i << Vcb->sector_shift], Vcb->superblock.sector_size);
589 else if ((i + 1) << Vcb->sector_shift < sizeof(uint32_t) * num_sectors)
590 crc32 = 0; // FIXME - test this
591 else
592 crc32 = ~calc_crc32c(0xffffffff, &data[sizeof(uint32_t) * num_sectors], ((i + 1) << Vcb->sector_shift) - (sizeof(uint32_t) * num_sectors));
593
594 if (crc32 != checksums[i]) {
595 WARN("checksum %u was %08x, expected %08x\n", i, crc32, checksums[i]);
596 goto clearcache;
597 }
598 }
599
600 off = (sizeof(uint32_t) * num_sectors) + sizeof(uint64_t);
601
602 bmpnum = 0;
603 for (uint32_t i = 0; i < num_entries; i++) {
604 if ((off + sizeof(FREE_SPACE_ENTRY)) >> Vcb->sector_shift != off >> Vcb->sector_shift)
605 off = sector_align(off, Vcb->superblock.sector_size);
606
607 fse = (FREE_SPACE_ENTRY*)&data[off];
608
609 if (fse->type == FREE_SPACE_EXTENT) {
610 Status = add_space_entry(&c->space, &c->space_size, fse->offset, fse->size);
611 if (!NT_SUCCESS(Status)) {
612 ERR("add_space_entry returned %08lx\n", Status);
614 return Status;
615 }
616
617 total_space += fse->size;
618 } else if (fse->type != FREE_SPACE_BITMAP) {
619 ERR("unknown free-space type %x\n", fse->type);
620 }
621
622 off += sizeof(FREE_SPACE_ENTRY);
623 }
624
625 if (num_bitmaps > 0) {
626 bmpnum = sector_align(off, Vcb->superblock.sector_size) >> Vcb->sector_shift;
627 off = (sizeof(uint32_t) * num_sectors) + sizeof(uint64_t);
628
629 for (uint32_t i = 0; i < num_entries; i++) {
630 if ((off + sizeof(FREE_SPACE_ENTRY)) >> Vcb->sector_shift != off >> Vcb->sector_shift)
631 off = sector_align(off, Vcb->superblock.sector_size);
632
633 fse = (FREE_SPACE_ENTRY*)&data[off];
634
635 if (fse->type == FREE_SPACE_BITMAP) {
636 // FIXME - make sure we don't overflow the buffer here
637 load_free_space_bitmap(Vcb, c, fse->offset, &data[bmpnum << Vcb->sector_shift], &total_space);
638 bmpnum++;
639 }
640
641 off += sizeof(FREE_SPACE_ENTRY);
642 }
643 }
644
645 // do sanity check
646
647 Status = get_superblock_size(c, &superblock_size);
648 if (!NT_SUCCESS(Status)) {
649 ERR("get_superblock_size returned %08lx\n", Status);
651 return Status;
652 }
653
654 if (c->chunk_item->size - c->used != total_space + superblock_size) {
655 WARN("invalidating cache for chunk %I64x: space was %I64x, expected %I64x\n", c->offset, total_space + superblock_size, c->chunk_item->size - c->used);
656 goto clearcache;
657 }
658
659 le = c->space.Flink;
660 while (le != &c->space) {
662 LIST_ENTRY* le2 = le->Flink;
663
664 if (le2 != &c->space) {
666
667 if (s2->address == s->address + s->size) {
668 s->size += s2->size;
669
670 RemoveEntryList(&s2->list_entry);
671 RemoveEntryList(&s2->list_entry_size);
672 ExFreePool(s2);
673
674 RemoveEntryList(&s->list_entry_size);
675 order_space_entry(s, &c->space_size);
676
677 le2 = le;
678 }
679 }
680
681 le = le2;
682 }
683
685
686 return STATUS_SUCCESS;
687
688clearcache:
690
692
694 if (!NT_SUCCESS(Status)) {
695 ERR("delete_tree_item returned %08lx\n", Status);
696 return Status;
697 }
698
699 Status = excise_extents(Vcb, c->cache, 0, c->cache->inode_item.st_size, Irp, &rollback);
700 if (!NT_SUCCESS(Status)) {
701 ERR("excise_extents returned %08lx\n", Status);
703 return Status;
704 }
705
707
708 c->cache->deleted = true;
709 mark_fcb_dirty(c->cache);
710
711 c->old_cache = c->cache;
712 c->cache = NULL;
713
714 le = c->space.Flink;
715 while (le != &c->space) {
717 LIST_ENTRY* le2 = le->Flink;
718
719 RemoveEntryList(&s->list_entry);
720 RemoveEntryList(&s->list_entry_size);
721 ExFreePool(s);
722
723 le = le2;
724 }
725
726 return STATUS_NOT_FOUND;
727}
NTSTATUS NTSTATUS NTSTATUS NTSTATUS NTSTATUS excise_extents(device_extension *Vcb, fcb *fcb, uint64_t start_data, uint64_t end_data, PIRP Irp, LIST_ENTRY *rollback) __attribute__((nonnull(1
_In_ uint64_t _In_ uint64_t _In_ uint64_t generation
Definition: btrfs.c:2996
#define FREE_SPACE_EXTENT
Definition: btrfs.h:445
#define FREE_SPACE_BITMAP
Definition: btrfs.h:446
static NTSTATUS get_superblock_size(chunk *c, uint64_t *size)
Definition: free-space.c:364
NTSTATUS add_space_entry(LIST_ENTRY *list, LIST_ENTRY *list_size, uint64_t offset, uint64_t size)
Definition: free-space.c:190
static void load_free_space_bitmap(device_extension *Vcb, chunk *c, uint64_t offset, void *data, uint64_t *total_space)
Definition: free-space.c:258
static void order_space_entry(space *s, LIST_ENTRY *list_size)
Definition: free-space.c:299
#define BTRFS_INODE_NODATACOW
Definition: propsheet.h:77
Definition: btrfs.h:448
uint64_t size
Definition: btrfs.h:450
uint64_t offset
Definition: btrfs.h:449
uint8_t type
Definition: btrfs.h:451
uint64_t num_entries
Definition: btrfs.h:457
uint64_t generation
Definition: btrfs.h:456
uint64_t num_bitmaps
Definition: btrfs.h:458

Referenced by drop_chunk(), and load_free_space_cache().

◆ load_tree()

NTSTATUS load_tree ( device_extension Vcb,
uint64_t  addr,
uint8_t buf,
root r,
tree **  pt 
)

◆ log_device_error()

void log_device_error ( _In_ device_extension Vcb,
_Inout_ device dev,
_In_ int  error 
)

◆ look_for_balance_item()

NTSTATUS look_for_balance_item ( _Requires_lock_held_(_Curr_->tree_lock) device_extension Vcb)

Definition at line 3628 of file balance.c.

3628 {
3629 KEY searchkey;
3632 BALANCE_ITEM* bi;
3634 int i;
3635
3636 searchkey.obj_id = BALANCE_ITEM_ID;
3637 searchkey.obj_type = TYPE_TEMP_ITEM;
3638 searchkey.offset = 0;
3639
3640 Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, NULL);
3641 if (!NT_SUCCESS(Status)) {
3642 ERR("find_item returned %08lx\n", Status);
3643 return Status;
3644 }
3645
3646 if (keycmp(tp.item->key, searchkey)) {
3647 TRACE("no balance item found\n");
3648 return STATUS_NOT_FOUND;
3649 }
3650
3651 if (tp.item->size < sizeof(BALANCE_ITEM)) {
3652 WARN("(%I64x,%x,%I64x) was %u bytes, expected %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset,
3653 tp.item->size, sizeof(BALANCE_ITEM));
3654 return STATUS_INTERNAL_ERROR;
3655 }
3656
3657 bi = (BALANCE_ITEM*)tp.item->data;
3658
3660 load_balance_args(&Vcb->balance.opts[BALANCE_OPTS_DATA], &bi->data);
3661
3662 if (bi->flags & BALANCE_FLAGS_METADATA)
3663 load_balance_args(&Vcb->balance.opts[BALANCE_OPTS_METADATA], &bi->metadata);
3664
3665 if (bi->flags & BALANCE_FLAGS_SYSTEM)
3666 load_balance_args(&Vcb->balance.opts[BALANCE_OPTS_SYSTEM], &bi->system);
3667
3668 // do the heuristics that Linux driver does
3669
3670 for (i = 0; i < 3; i++) {
3671 if (Vcb->balance.opts[i].flags & BTRFS_BALANCE_OPTS_ENABLED) {
3672 // if converting, don't redo chunks already done
3673
3674 if (Vcb->balance.opts[i].flags & BTRFS_BALANCE_OPTS_CONVERT)
3675 Vcb->balance.opts[i].flags |= BTRFS_BALANCE_OPTS_SOFT;
3676
3677 // don't balance chunks more than 90% filled - presumably these
3678 // have already been done
3679
3680 if (!(Vcb->balance.opts[i].flags & BTRFS_BALANCE_OPTS_USAGE) &&
3681 !(Vcb->balance.opts[i].flags & BTRFS_BALANCE_OPTS_CONVERT)
3682 ) {
3683 Vcb->balance.opts[i].flags |= BTRFS_BALANCE_OPTS_USAGE;
3684 Vcb->balance.opts[i].usage_start = 0;
3685 Vcb->balance.opts[i].usage_end = 90;
3686 }
3687 }
3688 }
3689
3690 if (Vcb->readonly || Vcb->options.skip_balance)
3691 Vcb->balance.paused = true;
3692 else
3693 Vcb->balance.paused = false;
3694
3695 Vcb->balance.removing = false;
3696 Vcb->balance.shrinking = false;
3697 Vcb->balance.status = STATUS_SUCCESS;
3698 KeInitializeEvent(&Vcb->balance.event, NotificationEvent, !Vcb->balance.paused);
3699
3701
3702 Status = PsCreateSystemThread(&Vcb->balance.thread, 0, &oa, NULL, NULL, balance_thread, Vcb);
3703 if (!NT_SUCCESS(Status)) {
3704 ERR("PsCreateSystemThread returned %08lx\n", Status);
3705 return Status;
3706 }
3707
3708 return STATUS_SUCCESS;
3709}
#define BTRFS_BALANCE_OPTS_SOFT
Definition: btrfsioctl.h:139
#define BTRFS_BALANCE_OPTS_USAGE
Definition: btrfsioctl.h:137
static void load_balance_args(btrfs_balance_opts *opts, BALANCE_ARGS *args)
Definition: balance.c:2492
#define TYPE_TEMP_ITEM
Definition: btrfs.h:49
#define BALANCE_FLAGS_METADATA
Definition: btrfs.h:478
#define BALANCE_FLAGS_SYSTEM
Definition: btrfs.h:477
#define BALANCE_ITEM_ID
Definition: btrfs.h:92
#define BALANCE_FLAGS_DATA
Definition: btrfs.h:476
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
NTSTATUS NTAPI PsCreateSystemThread(OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN HANDLE ProcessHandle, IN PCLIENT_ID ClientId, IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext)
Definition: thread.c:602
BALANCE_ARGS metadata
Definition: btrfs.h:527
BALANCE_ARGS system
Definition: btrfs.h:528
uint64_t flags
Definition: btrfs.h:525
BALANCE_ARGS data
Definition: btrfs.h:526

Referenced by mount_vol().

◆ lzo_compress()

NTSTATUS lzo_compress ( uint8_t inbuf,
uint32_t  inlen,
uint8_t outbuf,
uint32_t  outlen,
unsigned int space_left 
)

Definition at line 727 of file compress.c.

727 {
729 unsigned int num_pages;
730 unsigned int comp_data_len;
731 uint8_t* comp_data;
734
735 num_pages = (unsigned int)sector_align(inlen, LZO_PAGE_SIZE) / LZO_PAGE_SIZE;
736
737 // Four-byte overall header
738 // Another four-byte header page
739 // Each page has a maximum size of lzo_max_outlen(LZO_PAGE_SIZE)
740 // Plus another four bytes for possible padding
741 comp_data_len = sizeof(uint32_t) + ((lzo_max_outlen(LZO_PAGE_SIZE) + (2 * sizeof(uint32_t))) * num_pages);
742
743 // FIXME - can we write this so comp_data isn't necessary?
744
745 comp_data = ExAllocatePoolWithTag(PagedPool, comp_data_len, ALLOC_TAG);
746 if (!comp_data) {
747 ERR("out of memory\n");
749 }
750
752 if (!stream.wrkmem) {
753 ERR("out of memory\n");
754 ExFreePool(comp_data);
756 }
757
758 out_size = (uint32_t*)comp_data;
759 *out_size = sizeof(uint32_t);
760
761 stream.in = inbuf;
762 stream.out = comp_data + (2 * sizeof(uint32_t));
763
764 for (unsigned int i = 0; i < num_pages; i++) {
765 uint32_t* pagelen = (uint32_t*)(stream.out - sizeof(uint32_t));
766
767 stream.inlen = (uint32_t)min(LZO_PAGE_SIZE, outlen - (i * LZO_PAGE_SIZE));
768
770 if (!NT_SUCCESS(Status)) {
771 ERR("lzo1x_1_compress returned %08lx\n", Status);
772 ExFreePool(comp_data);
773 return Status;
774 }
775
776 *pagelen = stream.outlen;
777 *out_size += stream.outlen + sizeof(uint32_t);
778
779 stream.in += LZO_PAGE_SIZE;
780 stream.out += stream.outlen + sizeof(uint32_t);
781
782 // new page needs to start at a 32-bit boundary
783 if (LZO_PAGE_SIZE - (*out_size % LZO_PAGE_SIZE) < sizeof(uint32_t)) {
787 }
788 }
789
790 ExFreePool(stream.wrkmem);
791
792 if (*out_size >= outlen)
793 *space_left = 0;
794 else {
795 *space_left = outlen - *out_size;
796
797 RtlCopyMemory(outbuf, comp_data, *out_size);
798 }
799
800 ExFreePool(comp_data);
801
802 return STATUS_SUCCESS;
803}
static int inbuf
Definition: adnsresfilter.c:73
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
static __inline uint32_t lzo_max_outlen(uint32_t inlen)
Definition: compress.c:660
#define LZO1X_MEM_COMPRESS
Definition: compress.c:59
#define LZO_PAGE_SIZE
Definition: compress.c:46
static NTSTATUS lzo1x_1_compress(lzo_stream *stream)
Definition: compress.c:631
static HANDLE PIO_APC_ROUTINE PVOID PIO_STATUS_BLOCK ULONG PVOID ULONG PVOID ULONG out_size
Definition: file.c:100

Referenced by calc_thread_main().

◆ lzo_decompress()

NTSTATUS lzo_decompress ( uint8_t inbuf,
uint32_t  inlen,
uint8_t outbuf,
uint32_t  outlen,
uint32_t  inpageoff 
)

Definition at line 278 of file compress.c.

278 {
280 uint32_t partlen, inoff, outoff;
282
283 inoff = 0;
284 outoff = 0;
285
286 do {
287 partlen = *(uint32_t*)&inbuf[inoff];
288
289 if (partlen + inoff > inlen) {
290 ERR("overflow: %x + %x > %x\n", partlen, inoff, inlen);
292 }
293
294 inoff += sizeof(uint32_t);
295
296 stream.in = &inbuf[inoff];
297 stream.inlen = partlen;
298 stream.inpos = 0;
299 stream.out = &outbuf[outoff];
300 stream.outlen = min(outlen, LZO_PAGE_SIZE);
301 stream.outpos = 0;
302
304 if (!NT_SUCCESS(Status)) {
305 ERR("do_lzo_decompress returned %08lx\n", Status);
306 return Status;
307 }
308
309 if (stream.outpos < stream.outlen)
310 RtlZeroMemory(&stream.out[stream.outpos], stream.outlen - stream.outpos);
311
312 inoff += partlen;
313 outoff += stream.outlen;
314
315 if (LZO_PAGE_SIZE - ((inpageoff + inoff) % LZO_PAGE_SIZE) < sizeof(uint32_t))
316 inoff = ((((inpageoff + inoff) / LZO_PAGE_SIZE) + 1) * LZO_PAGE_SIZE) - inpageoff;
317
318 outlen -= stream.outlen;
319 } while (inoff < inlen && outlen > 0);
320
321 return STATUS_SUCCESS;
322}
static NTSTATUS do_lzo_decompress(lzo_stream *stream)
Definition: compress.c:170

Referenced by calc_thread_main(), and flush_extents().

◆ make_file_id()

static __inline uint64_t make_file_id ( root r,
uint64_t  inode 
)
static

Definition at line 1012 of file btrfs_drv.h.

1012 {
1013 return (r->id << 40) | (inode & 0xffffffffff);
1014}

Referenced by fill_in_file_internal_information(), fill_in_file_stat_information(), fill_in_file_stat_lx_information(), and query_dir_item().

◆ map_user_buffer()

static __inline void * map_user_buffer ( PIRP  Irp,
ULONG  priority 
)
static

Definition at line 977 of file btrfs_drv.h.

977 {
978 if (!Irp->MdlAddress) {
979 return Irp->UserBuffer;
980 } else {
981 return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, priority);
982 }
983}
static int priority
Definition: timer.c:163
#define MmGetSystemAddressForMdlSafe(_Mdl, _Priority)

Referenced by _Dispatch_type_(), control_ioctl(), do_read(), fsctl_request(), and query_directory().

◆ mark_fcb_dirty()

◆ mark_fileref_dirty()

void mark_fileref_dirty ( _In_ file_ref fileref)

Definition at line 1717 of file btrfs.c.

1717 {
1718 if (!fileref->dirty) {
1719 fileref->dirty = true;
1721
1722 ExAcquireResourceExclusiveLite(&fileref->fcb->Vcb->dirty_filerefs_lock, true);
1723 InsertTailList(&fileref->fcb->Vcb->dirty_filerefs, &fileref->list_entry_dirty);
1724 ExReleaseResourceLite(&fileref->fcb->Vcb->dirty_filerefs_lock);
1725 }
1726
1727 fileref->fcb->Vcb->need_write = true;
1728}
#define increase_fileref_refcount(fileref)
Definition: btrfs_drv.h:1739

Referenced by __attribute__(), create_stream(), create_subvol(), delete_fileref(), delete_reparse_point(), do_create_snapshot(), file_create2(), mknod(), move_across_subvols(), rename_file_to_stream(), rename_stream_to_file(), set_link_information(), set_rename_information(), and set_symlink().

◆ mountmgr_add_drive_letter()

NTSTATUS mountmgr_add_drive_letter ( PDEVICE_OBJECT  mountmgr,
PUNICODE_STRING  devpath 
)

Definition at line 832 of file volume.c.

832 {
834 ULONG mmdltsize;
837
838 mmdltsize = (ULONG)offsetof(MOUNTMGR_DRIVE_LETTER_TARGET, DeviceName[0]) + devpath->Length;
839
840 mmdlt = ExAllocatePoolWithTag(NonPagedPool, mmdltsize, ALLOC_TAG);
841 if (!mmdlt) {
842 ERR("out of memory\n");
844 }
845
846 mmdlt->DeviceNameLength = devpath->Length;
847 RtlCopyMemory(&mmdlt->DeviceName, devpath->Buffer, devpath->Length);
848 TRACE("mmdlt = %.*S\n", (int)(mmdlt->DeviceNameLength / sizeof(WCHAR)), mmdlt->DeviceName);
849
851
852 if (!NT_SUCCESS(Status))
853 ERR("IOCTL_MOUNTMGR_NEXT_DRIVE_LETTER returned %08lx\n", Status);
854 else
855 TRACE("DriveLetterWasAssigned = %u, CurrentDriveLetter = %c\n", mmdli.DriveLetterWasAssigned, mmdli.CurrentDriveLetter);
856
857 ExFreePool(mmdlt);
858
859 return Status;
860}
#define IOCTL_MOUNTMGR_NEXT_DRIVE_LETTER
Definition: mountmgr.h:34
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_opt_ PCUNICODE_STRING DeviceName
Definition: wdfdevice.h:3275

Referenced by finish_removing_device(), and remove_volume_child().

◆ open_fcb()

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 
)

Definition at line 706 of file create.c.

707 {
708 KEY searchkey;
709 traverse_ptr tp, next_tp;
711 fcb *fcb, *deleted_fcb = NULL;
712 bool atts_set = false, sd_set = false, no_data;
713 LIST_ENTRY* lastle = NULL;
714 EXTENT_DATA* ed = NULL;
717
718 hash = calc_crc32c(0xffffffff, (uint8_t*)&inode, sizeof(uint64_t));
719
720 acquire_fcb_lock_shared(Vcb);
721
722 if (subvol->fcbs_ptrs[hash >> 24]) {
723 LIST_ENTRY* le = subvol->fcbs_ptrs[hash >> 24];
724
725 while (le != &subvol->fcbs) {
726 fcb = CONTAINING_RECORD(le, struct _fcb, list_entry);
727
728 if (fcb->inode == inode) {
729 if (!fcb->ads) {
730 if (fcb->deleted)
731 deleted_fcb = fcb;
732 else {
733#ifdef DEBUG_FCB_REFCOUNTS
735
736 WARN("fcb %p: refcount now %i (subvol %I64x, inode %I64x)\n", fcb, rc, fcb->subvol->id, fcb->inode);
737#else
739#endif
740
741 *pfcb = fcb;
742 release_fcb_lock(Vcb);
743 return STATUS_SUCCESS;
744 }
745 }
746 } else if (fcb->hash > hash) {
747 if (deleted_fcb) {
748 InterlockedIncrement(&deleted_fcb->refcount);
749 *pfcb = deleted_fcb;
750 release_fcb_lock(Vcb);
751 return STATUS_SUCCESS;
752 }
753
754 lastle = le->Blink;
755 fcbs_version = subvol->fcbs_version;
756
757 break;
758 }
759
760 le = le->Flink;
761 }
762 }
763
764 release_fcb_lock(Vcb);
765
766 if (deleted_fcb) {
767 InterlockedIncrement(&deleted_fcb->refcount);
768 *pfcb = deleted_fcb;
769 return STATUS_SUCCESS;
770 }
771
772 fcb = create_fcb(Vcb, pooltype);
773 if (!fcb) {
774 ERR("out of memory\n");
776 }
777
778 fcb->Vcb = Vcb;
779
780 fcb->subvol = subvol;
781 fcb->inode = inode;
782 fcb->hash = hash;
783 fcb->type = type;
784
785 searchkey.obj_id = inode;
786 searchkey.obj_type = TYPE_INODE_ITEM;
787 searchkey.offset = 0xffffffffffffffff;
788
789 Status = find_item(Vcb, subvol, &tp, &searchkey, false, Irp);
790 if (!NT_SUCCESS(Status)) {
791 ERR("error - find_item returned %08lx\n", Status);
792 reap_fcb(fcb);
793 return Status;
794 }
795
796 if (tp.item->key.obj_id != searchkey.obj_id || tp.item->key.obj_type != searchkey.obj_type) {
797 WARN("couldn't find INODE_ITEM for inode %I64x in subvol %I64x\n", inode, subvol->id);
798 reap_fcb(fcb);
800 }
801
802 if (tp.item->size > 0)
804
805 if (fcb->type == 0) { // guess the type from the inode mode, if the caller doesn't know already
808 else if ((fcb->inode_item.st_mode & __S_IFCHR) == __S_IFCHR)
810 else if ((fcb->inode_item.st_mode & __S_IFBLK) == __S_IFBLK)
812 else if ((fcb->inode_item.st_mode & __S_IFIFO) == __S_IFIFO)
814 else if ((fcb->inode_item.st_mode & __S_IFLNK) == __S_IFLNK)
816 else if ((fcb->inode_item.st_mode & __S_IFSOCK) == __S_IFSOCK)
818 else
820 }
821
822 no_data = fcb->inode_item.st_size == 0 || (fcb->type != BTRFS_TYPE_FILE && fcb->type != BTRFS_TYPE_SYMLINK);
823
824 while (find_next_item(Vcb, &tp, &next_tp, false, Irp)) {
825 tp = next_tp;
826
827 if (tp.item->key.obj_id > inode)
828 break;
829
831 break;
832
833 if ((always_add_hl || fcb->inode_item.st_nlink > 1) && tp.item->key.obj_type == TYPE_INODE_REF) {
834 ULONG len;
835 INODE_REF* ir;
836
837 len = tp.item->size;
838 ir = (INODE_REF*)tp.item->data;
839
840 while (len >= sizeof(INODE_REF) - 1) {
841 hardlink* hl;
843
844 hl = ExAllocatePoolWithTag(pooltype, sizeof(hardlink), ALLOC_TAG);
845 if (!hl) {
846 ERR("out of memory\n");
847 reap_fcb(fcb);
849 }
850
851 hl->parent = tp.item->key.offset;
852 hl->index = ir->index;
853
854 hl->utf8.Length = hl->utf8.MaximumLength = ir->n;
855
856 if (hl->utf8.Length > 0) {
858 RtlCopyMemory(hl->utf8.Buffer, ir->name, ir->n);
859 }
860
861 Status = utf8_to_utf16(NULL, 0, &stringlen, ir->name, ir->n);
862 if (!NT_SUCCESS(Status)) {
863 ERR("utf8_to_utf16 1 returned %08lx\n", Status);
864 ExFreePool(hl);
865 reap_fcb(fcb);
866 return Status;
867 }
868
870
871 if (stringlen == 0)
872 hl->name.Buffer = NULL;
873 else {
875
876 if (!hl->name.Buffer) {
877 ERR("out of memory\n");
878 ExFreePool(hl);
879 reap_fcb(fcb);
881 }
882
884 if (!NT_SUCCESS(Status)) {
885 ERR("utf8_to_utf16 2 returned %08lx\n", Status);
887 ExFreePool(hl);
888 reap_fcb(fcb);
889 return Status;
890 }
891 }
892
894
895 len -= sizeof(INODE_REF) - 1 + ir->n;
896 ir = (INODE_REF*)&ir->name[ir->n];
897 }
898 } else if ((always_add_hl || fcb->inode_item.st_nlink > 1) && tp.item->key.obj_type == TYPE_INODE_EXTREF) {
899 ULONG len;
900 INODE_EXTREF* ier;
901
902 len = tp.item->size;
903 ier = (INODE_EXTREF*)tp.item->data;
904
905 while (len >= sizeof(INODE_EXTREF) - 1) {
906 hardlink* hl;
908
909 hl = ExAllocatePoolWithTag(pooltype, sizeof(hardlink), ALLOC_TAG);
910 if (!hl) {
911 ERR("out of memory\n");
912 reap_fcb(fcb);
914 }
915
916 hl->parent = ier->dir;
917 hl->index = ier->index;
918
919 hl->utf8.Length = hl->utf8.MaximumLength = ier->n;
920
921 if (hl->utf8.Length > 0) {
923 RtlCopyMemory(hl->utf8.Buffer, ier->name, ier->n);
924 }
925
926 Status = utf8_to_utf16(NULL, 0, &stringlen, ier->name, ier->n);
927 if (!NT_SUCCESS(Status)) {
928 ERR("utf8_to_utf16 1 returned %08lx\n", Status);
929 ExFreePool(hl);
930 reap_fcb(fcb);
931 return Status;
932 }
933
935
936 if (stringlen == 0)
937 hl->name.Buffer = NULL;
938 else {
940
941 if (!hl->name.Buffer) {
942 ERR("out of memory\n");
943 ExFreePool(hl);
944 reap_fcb(fcb);
946 }
947
948 Status = utf8_to_utf16(hl->name.Buffer, stringlen, &stringlen, ier->name, ier->n);
949 if (!NT_SUCCESS(Status)) {
950 ERR("utf8_to_utf16 2 returned %08lx\n", Status);
952 ExFreePool(hl);
953 reap_fcb(fcb);
954 return Status;
955 }
956 }
957
959
960 len -= sizeof(INODE_EXTREF) - 1 + ier->n;
961 ier = (INODE_EXTREF*)&ier->name[ier->n];
962 }
963 } else if (tp.item->key.obj_type == TYPE_XATTR_ITEM) {
964 ULONG len;
965 DIR_ITEM* di;
966
967 static const char xapref[] = "user.";
968
969 if (tp.item->size < offsetof(DIR_ITEM, name[0])) {
970 ERR("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, offsetof(DIR_ITEM, name[0]));
971 continue;
972 }
973
974 len = tp.item->size;
975 di = (DIR_ITEM*)tp.item->data;
976
977 do {
978 if (len < offsetof(DIR_ITEM, name[0]) + di->m + di->n)
979 break;
980
981 if (tp.item->key.offset == EA_REPARSE_HASH && di->n == sizeof(EA_REPARSE) - 1 && RtlCompareMemory(EA_REPARSE, di->name, di->n) == di->n) {
982 if (di->m > 0) {
984 if (!fcb->reparse_xattr.Buffer) {
985 ERR("out of memory\n");
986 reap_fcb(fcb);
988 }
989
990 RtlCopyMemory(fcb->reparse_xattr.Buffer, &di->name[di->n], di->m);
991 } else
993
995 } else if (tp.item->key.offset == EA_EA_HASH && di->n == sizeof(EA_EA) - 1 && RtlCompareMemory(EA_EA, di->name, di->n) == di->n) {
996 if (di->m > 0) {
998
1000
1001 if (!NT_SUCCESS(Status))
1002 WARN("IoCheckEaBufferValidity returned %08lx (error at offset %lu)\n", Status, offset);
1003 else {
1005
1007 if (!fcb->ea_xattr.Buffer) {
1008 ERR("out of memory\n");
1009 reap_fcb(fcb);
1011 }
1012
1013 RtlCopyMemory(fcb->ea_xattr.Buffer, &di->name[di->n], di->m);
1014
1016
1017 fcb->ealen = 4;
1018
1019 // calculate ealen
1020 eainfo = (FILE_FULL_EA_INFORMATION*)&di->name[di->n];
1021 do {
1022 fcb->ealen += 5 + eainfo->EaNameLength + eainfo->EaValueLength;
1023
1024 if (eainfo->NextEntryOffset == 0)
1025 break;
1026
1027 eainfo = (FILE_FULL_EA_INFORMATION*)(((uint8_t*)eainfo) + eainfo->NextEntryOffset);
1028 } while (true);
1029 }
1030 }
1031 } else if (tp.item->key.offset == EA_DOSATTRIB_HASH && di->n == sizeof(EA_DOSATTRIB) - 1 && RtlCompareMemory(EA_DOSATTRIB, di->name, di->n) == di->n) {
1032 if (di->m > 0) {
1033 if (get_file_attributes_from_xattr(&di->name[di->n], di->m, &fcb->atts)) {
1034 atts_set = true;
1035
1038 else if (fcb->type == BTRFS_TYPE_SYMLINK)
1040
1042 fcb->atts &= ~FILE_ATTRIBUTE_DIRECTORY;
1043
1044 if (inode == SUBVOL_ROOT_INODE) {
1047 else
1048 fcb->atts &= ~FILE_ATTRIBUTE_READONLY;
1049 }
1050 }
1051 }
1052 } else if (tp.item->key.offset == EA_NTACL_HASH && di->n == sizeof(EA_NTACL) - 1 && RtlCompareMemory(EA_NTACL, di->name, di->n) == di->n) {
1053 if (di->m > 0) {
1055 if (!fcb->sd) {
1056 ERR("out of memory\n");
1057 reap_fcb(fcb);
1059 }
1060
1061 RtlCopyMemory(fcb->sd, &di->name[di->n], di->m);
1062
1063 // We have to test against our copy rather than the source, as RtlValidRelativeSecurityDescriptor
1064 // will fail if the ACLs aren't 32-bit aligned.
1066 ExFreePool(fcb->sd);
1067 else
1068 sd_set = true;
1069 }
1070 } else if (tp.item->key.offset == EA_PROP_COMPRESSION_HASH && di->n == sizeof(EA_PROP_COMPRESSION) - 1 && RtlCompareMemory(EA_PROP_COMPRESSION, di->name, di->n) == di->n) {
1071 if (di->m > 0) {
1072 static const char lzo[] = "lzo";
1073 static const char zlib[] = "zlib";
1074 static const char zstd[] = "zstd";
1075
1076 if (di->m == sizeof(lzo) - 1 && RtlCompareMemory(&di->name[di->n], lzo, di->m) == di->m)
1078 else if (di->m == sizeof(zlib) - 1 && RtlCompareMemory(&di->name[di->n], zlib, di->m) == di->m)
1080 else if (di->m == sizeof(zstd) - 1 && RtlCompareMemory(&di->name[di->n], zstd, di->m) == di->m)
1082 else
1084 }
1085 } else if (tp.item->key.offset == EA_CASE_SENSITIVE_HASH && di->n == sizeof(EA_CASE_SENSITIVE) - 1 && RtlCompareMemory(EA_CASE_SENSITIVE, di->name, di->n) == di->n) {
1086 if (di->m > 0) {
1087 fcb->case_sensitive = di->m == 1 && di->name[di->n] == '1';
1088 fcb->case_sensitive_set = true;
1089 }
1090 } else if (di->n > sizeof(xapref) - 1 && RtlCompareMemory(xapref, di->name, sizeof(xapref) - 1) == sizeof(xapref) - 1) {
1091 dir_child* dc;
1092 ULONG utf16len;
1093
1094 Status = utf8_to_utf16(NULL, 0, &utf16len, &di->name[sizeof(xapref) - 1], di->n + 1 - sizeof(xapref));
1095 if (!NT_SUCCESS(Status)) {
1096 ERR("utf8_to_utf16 1 returned %08lx\n", Status);
1097 reap_fcb(fcb);
1098 return Status;
1099 }
1100
1102 if (!dc) {
1103 ERR("out of memory\n");
1104 reap_fcb(fcb);
1106 }
1107
1108 RtlZeroMemory(dc, sizeof(dir_child));
1109
1110 dc->utf8.MaximumLength = dc->utf8.Length = di->n + 1 - sizeof(xapref);
1111 dc->utf8.Buffer = ExAllocatePoolWithTag(PagedPool, dc->utf8.MaximumLength, ALLOC_TAG);
1112 if (!dc->utf8.Buffer) {
1113 ERR("out of memory\n");
1114 ExFreePool(dc);
1115 reap_fcb(fcb);
1117 }
1118
1119 RtlCopyMemory(dc->utf8.Buffer, &di->name[sizeof(xapref) - 1], dc->utf8.Length);
1120
1121 dc->name.MaximumLength = dc->name.Length = (uint16_t)utf16len;
1122 dc->name.Buffer = ExAllocatePoolWithTag(PagedPool, dc->name.MaximumLength, ALLOC_TAG);
1123 if (!dc->name.Buffer) {
1124 ERR("out of memory\n");
1125 ExFreePool(dc->utf8.Buffer);
1126 ExFreePool(dc);
1127 reap_fcb(fcb);
1129 }
1130
1131 Status = utf8_to_utf16(dc->name.Buffer, utf16len, &utf16len, dc->utf8.Buffer, dc->utf8.Length);
1132 if (!NT_SUCCESS(Status)) {
1133 ERR("utf8_to_utf16 2 returned %08lx\n", Status);
1134 ExFreePool(dc->utf8.Buffer);
1135 ExFreePool(dc->name.Buffer);
1136 ExFreePool(dc);
1137 reap_fcb(fcb);
1138 return Status;
1139 }
1140
1141 Status = RtlUpcaseUnicodeString(&dc->name_uc, &dc->name, true);
1142 if (!NT_SUCCESS(Status)) {
1143 ERR("RtlUpcaseUnicodeString returned %08lx\n", Status);
1144 ExFreePool(dc->utf8.Buffer);
1145 ExFreePool(dc->name.Buffer);
1146 ExFreePool(dc);
1147 reap_fcb(fcb);
1148 return Status;
1149 }
1150
1151 dc->size = di->m;
1152
1153 InsertTailList(&fcb->dir_children_index, &dc->list_entry_index);
1154 } else {
1155 xattr* xa;
1156
1157 xa = ExAllocatePoolWithTag(PagedPool, offsetof(xattr, data[0]) + di->m + di->n, ALLOC_TAG);
1158 if (!xa) {
1159 ERR("out of memory\n");
1160 reap_fcb(fcb);
1162 }
1163
1164 xa->namelen = di->n;
1165 xa->valuelen = di->m;
1166 xa->dirty = false;
1167 RtlCopyMemory(xa->data, di->name, di->m + di->n);
1168
1170 }
1171
1172 len -= (ULONG)offsetof(DIR_ITEM, name[0]) + di->m + di->n;
1173
1174 if (len < offsetof(DIR_ITEM, name[0]))
1175 break;
1176
1177 di = (DIR_ITEM*)&di->name[di->m + di->n];
1178 } while (true);
1179 } else if (tp.item->key.obj_type == TYPE_EXTENT_DATA) {
1180 extent* ext;
1181 bool unique = false;
1182
1183 ed = (EXTENT_DATA*)tp.item->data;
1184
1185 if (tp.item->size < sizeof(EXTENT_DATA)) {
1186 ERR("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset,
1187 tp.item->size, sizeof(EXTENT_DATA));
1188
1189 reap_fcb(fcb);
1190 return STATUS_INTERNAL_ERROR;
1191 }
1192
1193 if (ed->type == EXTENT_TYPE_REGULAR || ed->type == EXTENT_TYPE_PREALLOC) {
1194 EXTENT_DATA2* ed2 = (EXTENT_DATA2*)&ed->data[0];
1195
1196 if (tp.item->size < sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2)) {
1197 ERR("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset,
1198 tp.item->size, sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2));
1199
1200 reap_fcb(fcb);
1201 return STATUS_INTERNAL_ERROR;
1202 }
1203
1204 if (ed2->address == 0 || ed2->size == 0) // sparse
1205 continue;
1206
1207 if (ed2->size != 0 && is_tree_unique(Vcb, tp.tree, Irp))
1208 unique = is_extent_unique(Vcb, ed2->address, ed2->size, Irp);
1209 }
1210
1211 ext = ExAllocatePoolWithTag(pooltype, offsetof(extent, extent_data) + tp.item->size, ALLOC_TAG);
1212 if (!ext) {
1213 ERR("out of memory\n");
1214 reap_fcb(fcb);
1216 }
1217
1218 ext->offset = tp.item->key.offset;
1219 RtlCopyMemory(&ext->extent_data, tp.item->data, tp.item->size);
1220 ext->datalen = tp.item->size;
1221 ext->unique = unique;
1222 ext->ignore = false;
1223 ext->inserted = false;
1224 ext->csum = NULL;
1225
1226 InsertTailList(&fcb->extents, &ext->list_entry);
1227 }
1228 }
1229
1230 if (fcb->type == BTRFS_TYPE_DIRECTORY) {
1231 Status = load_dir_children(Vcb, fcb, false, Irp);
1232 if (!NT_SUCCESS(Status)) {
1233 ERR("load_dir_children returned %08lx\n", Status);
1234 reap_fcb(fcb);
1235 return Status;
1236 }
1237 }
1238
1239 if (no_data) {
1240 fcb->Header.AllocationSize.QuadPart = 0;
1241 fcb->Header.FileSize.QuadPart = 0;
1242 fcb->Header.ValidDataLength.QuadPart = 0;
1243 } else {
1244 if (ed && ed->type == EXTENT_TYPE_INLINE)
1245 fcb->Header.AllocationSize.QuadPart = fcb->inode_item.st_size;
1246 else
1247 fcb->Header.AllocationSize.QuadPart = sector_align(fcb->inode_item.st_size, fcb->Vcb->superblock.sector_size);
1248
1249 fcb->Header.FileSize.QuadPart = fcb->inode_item.st_size;
1250 fcb->Header.ValidDataLength.QuadPart = fcb->inode_item.st_size;
1251 }
1252
1253 if (!atts_set)
1254 fcb->atts = get_file_attributes(Vcb, fcb->subvol, fcb->inode, fcb->type, utf8 && utf8->Buffer[0] == '.', true, Irp);
1255
1256 if (!sd_set)
1257 fcb_get_sd(fcb, parent, false, Irp);
1258
1259 acquire_fcb_lock_exclusive(Vcb);
1260
1261 if (lastle && subvol->fcbs_version == fcbs_version) {
1262 InsertHeadList(lastle, &fcb->list_entry);
1263
1264 if (!subvol->fcbs_ptrs[hash >> 24] || CONTAINING_RECORD(subvol->fcbs_ptrs[hash >> 24], struct _fcb, list_entry)->hash > hash)
1265 subvol->fcbs_ptrs[hash >> 24] = &fcb->list_entry;
1266 } else {
1267 lastle = NULL;
1268
1269 if (subvol->fcbs_ptrs[hash >> 24]) {
1270 LIST_ENTRY* le = subvol->fcbs_ptrs[hash >> 24];
1271
1272 while (le != &subvol->fcbs) {
1273 struct _fcb* fcb2 = CONTAINING_RECORD(le, struct _fcb, list_entry);
1274
1275 if (fcb2->inode == inode) {
1276 if (!fcb2->ads) {
1277 if (fcb2->deleted)
1278 deleted_fcb = fcb2;
1279 else {
1280#ifdef DEBUG_FCB_REFCOUNTS
1281 LONG rc = InterlockedIncrement(&fcb2->refcount);
1282
1283 WARN("fcb %p: refcount now %i (subvol %I64x, inode %I64x)\n", fcb2, rc, fcb2->subvol->id, fcb2->inode);
1284#else
1286#endif
1287
1288 *pfcb = fcb2;
1289 reap_fcb(fcb);
1290 release_fcb_lock(Vcb);
1291 return STATUS_SUCCESS;
1292 }
1293 }
1294 } else if (fcb2->hash > hash) {
1295 if (deleted_fcb) {
1296 InterlockedIncrement(&deleted_fcb->refcount);
1297 *pfcb = deleted_fcb;
1298 reap_fcb(fcb);
1299 release_fcb_lock(Vcb);
1300 return STATUS_SUCCESS;
1301 }
1302
1303 lastle = le->Blink;
1304 break;
1305 }
1306
1307 le = le->Flink;
1308 }
1309 }
1310
1312 fcb->atts &= ~FILE_ATTRIBUTE_REPARSE_POINT;
1313
1314 if (!Vcb->readonly && !is_subvol_readonly(subvol, Irp)) {
1315 fcb->atts_changed = true;
1317 }
1318 }
1319
1320 if (!lastle) {
1321 uint8_t c = hash >> 24;
1322
1323 if (c != 0xff) {
1324 uint8_t d = c + 1;
1325
1326 do {
1327 if (subvol->fcbs_ptrs[d]) {
1328 lastle = subvol->fcbs_ptrs[d]->Blink;
1329 break;
1330 }
1331
1332 d++;
1333 } while (d != 0);
1334 }
1335 }
1336
1337 if (lastle) {
1338 InsertHeadList(lastle, &fcb->list_entry);
1339
1340 if (lastle == &subvol->fcbs || (CONTAINING_RECORD(lastle, struct _fcb, list_entry)->hash >> 24) != (hash >> 24))
1341 subvol->fcbs_ptrs[hash >> 24] = &fcb->list_entry;
1342 } else {
1344
1345 if (fcb->list_entry.Blink == &subvol->fcbs || (CONTAINING_RECORD(fcb->list_entry.Blink, struct _fcb, list_entry)->hash >> 24) != (hash >> 24))
1346 subvol->fcbs_ptrs[hash >> 24] = &fcb->list_entry;
1347 }
1348 }
1349
1350 if (fcb->inode == SUBVOL_ROOT_INODE && fcb->subvol->id == BTRFS_ROOT_FSTREE && fcb->subvol != Vcb->root_fileref->fcb->subvol)
1352
1353 subvol->fcbs_version++;
1354
1355 InsertTailList(&Vcb->all_fcbs, &fcb->list_entry_all);
1356
1357 release_fcb_lock(Vcb);
1358
1359 fcb->Header.IsFastIoPossible = fast_io_possible(fcb);
1360
1361 *pfcb = fcb;
1362
1363 return STATUS_SUCCESS;
1364}
static __inline FAST_IO_POSSIBLE fast_io_possible(fcb *fcb)
Definition: btrfs_drv.h:1684
#define __S_IFDIR
Definition: btrfs_drv.h:1754
void fcb_get_sd(fcb *fcb, struct _fcb *parent, bool look_for_xattr, PIRP Irp)
Definition: security.c:511
#define __S_IFSOCK
Definition: btrfs_drv.h:1760
#define __S_IFLNK
Definition: btrfs_drv.h:1759
#define __S_IFIFO
Definition: btrfs_drv.h:1758
bool is_extent_unique(device_extension *Vcb, uint64_t address, uint64_t size, PIRP Irp)
Definition: extent-tree.c:1697
#define __S_IFBLK
Definition: btrfs_drv.h:1756
static __inline bool is_subvol_readonly(root *r, PIRP Irp)
Definition: btrfs_drv.h:1033
bool is_tree_unique(device_extension *Vcb, tree *t, PIRP Irp)
Definition: flushthread.c:3243
#define __S_IFCHR
Definition: btrfs_drv.h:1755
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
ULONG get_file_attributes(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_ uint64_t inode, _In_ uint8_t type, _In_ bool dotfile, _In_ bool ignore_xa, _In_opt_ PIRP Irp)
Definition: btrfs.c:2664
r fcbs_version
Definition: btrfs.c:3012
#define TYPE_INODE_EXTREF
Definition: btrfs.h:25
#define TYPE_XATTR_ITEM
Definition: btrfs.h:26
#define TYPE_INODE_REF
Definition: btrfs.h:24
fcb * create_fcb(device_extension *Vcb, POOL_TYPE pool_type)
Definition: create.c:91
NTSTATUS load_dir_children(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, fcb *fcb, bool ignore_size, PIRP Irp)
Definition: create.c:510
NTSYSAPI BOOLEAN WINAPI RtlValidRelativeSecurityDescriptor(PSECURITY_DESCRIPTOR, ULONG, SECURITY_INFORMATION)
NTSTATUS NTAPI IoCheckEaBufferValidity(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: util.c:191
uint16_t m
Definition: btrfs.h:275
uint64_t dir
Definition: btrfs.h:381
uint64_t index
Definition: btrfs.h:382
char name[1]
Definition: btrfs.h:384
uint16_t n
Definition: btrfs.h:383
uint64_t index
Definition: btrfs.h:375
char name[1]
Definition: btrfs.h:377
uint16_t n
Definition: btrfs.h:376
uint64_t flags
Definition: btrfs.h:319
USHORT MaximumLength
Definition: env_spec_w32.h:377
LIST_ENTRY list_entry_all
Definition: btrfs_drv.h:337
ULONG ealen
Definition: btrfs_drv.h:303
LIST_ENTRY * fcbs_ptrs[256]
Definition: btrfs_drv.h:465
ROOT_ITEM root_item
Definition: btrfs_drv.h:455
uint64_t fcbs_version
Definition: btrfs_drv.h:461

Referenced by check_for_orphans_root(), do_create_snapshot(), get_reparse_tag(), load_stored_free_space_cache(), open_fileref_by_inode(), open_fileref_child(), and remove_free_space_inode().

◆ open_fileref()

NTSTATUS open_fileref ( _Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension Vcb,
_Out_ file_ref **  pfr,
_In_ PUNICODE_STRING  fnus,
_In_opt_ file_ref related,
_In_ bool  parent,
_Out_opt_ USHORT parsed,
_Out_opt_ ULONG fn_offset,
_In_ POOL_TYPE  pooltype,
_In_ bool  case_sensitive,
_In_opt_ PIRP  Irp 
)

Definition at line 1690 of file create.c.

1692 {
1693 UNICODE_STRING fnus2;
1694 file_ref *dir, *sf, *sf2;
1696 bool has_stream = false;
1698 LIST_ENTRY* le;
1699
1700 TRACE("(%p, %p, %p, %u, %p)\n", Vcb, pfr, related, parent, parsed);
1701
1702 if (Vcb->removing || Vcb->locked)
1703 return STATUS_ACCESS_DENIED;
1704
1705 fnus2 = *fnus;
1706
1707 if (fnus2.Length < sizeof(WCHAR) && !related) {
1708 ERR("error - fnus was too short\n");
1709 return STATUS_INTERNAL_ERROR;
1710 }
1711
1712 if (related && fnus->Length == 0) {
1714
1715 *pfr = related;
1716 return STATUS_SUCCESS;
1717 }
1718
1719 if (related) {
1720 dir = related;
1721 } else {
1722 if (fnus2.Buffer[0] != '\\') {
1723 ERR("error - filename %.*S did not begin with \\\n", (int)(fnus2.Length / sizeof(WCHAR)), fnus2.Buffer);
1725 }
1726
1727 // if path starts with two backslashes, ignore one of them
1728 if (fnus2.Length >= 2 * sizeof(WCHAR) && fnus2.Buffer[1] == '\\') {
1729 fnus2.Buffer++;
1730 fnus2.Length -= sizeof(WCHAR);
1731 fnus2.MaximumLength -= sizeof(WCHAR);
1732 }
1733
1734 if (fnus2.Length == sizeof(WCHAR)) {
1735 if (Vcb->root_fileref->open_count == 0 && !(Vcb->Vpb->Flags & VPB_MOUNTED)) // don't allow root to be opened on unmounted FS
1737
1738 increase_fileref_refcount(Vcb->root_fileref);
1739 *pfr = Vcb->root_fileref;
1740
1741 if (fn_offset)
1742 *fn_offset = 0;
1743
1744 return STATUS_SUCCESS;
1745 } else if (fnus2.Length >= 2 * sizeof(WCHAR) && fnus2.Buffer[1] == '\\')
1747
1748 dir = Vcb->root_fileref;
1749
1750 fnus2.Buffer++;
1751 fnus2.Length -= sizeof(WCHAR);
1752 fnus2.MaximumLength -= sizeof(WCHAR);
1753 }
1754
1755 if (dir->fcb->type != BTRFS_TYPE_DIRECTORY && (fnus->Length < sizeof(WCHAR) || fnus->Buffer[0] != ':')) {
1756 WARN("passed related fileref which isn't a directory (fnus = %.*S)\n",
1757 (int)(fnus->Length / sizeof(WCHAR)), fnus->Buffer);
1759 }
1760
1762
1763 if (fnus->Length != 0 &&
1764 (fnus->Length != sizeof(datastring) - sizeof(WCHAR) || RtlCompareMemory(fnus->Buffer, datastring, sizeof(datastring) - sizeof(WCHAR)) != sizeof(datastring) - sizeof(WCHAR))) {
1765 Status = split_path(Vcb, &fnus2, &parts, &has_stream);
1766 if (!NT_SUCCESS(Status)) {
1767 ERR("split_path returned %08lx\n", Status);
1768 return Status;
1769 }
1770 }
1771
1772 sf = dir;
1774
1775 if (parent && !IsListEmpty(&parts)) {
1776 name_bit* nb;
1777
1779 ExFreeToPagedLookasideList(&Vcb->name_bit_lookaside, nb);
1780
1781 if (has_stream && !IsListEmpty(&parts)) {
1783 ExFreeToPagedLookasideList(&Vcb->name_bit_lookaside, nb);
1784
1785 has_stream = false;
1786 }
1787 }
1788
1789 if (IsListEmpty(&parts)) {
1791 *pfr = dir;
1792
1793 if (fn_offset)
1794 *fn_offset = 0;
1795
1796 goto end2;
1797 }
1798
1799 le = parts.Flink;
1800 do {
1802 bool lastpart = le->Flink == &parts || (has_stream && le->Flink->Flink == &parts);
1803 bool streampart = has_stream && le->Flink == &parts;
1804 bool cs = case_sensitive;
1805
1806 if (!cs) {
1807 if (streampart && sf->parent)
1808 cs = sf->parent->fcb->case_sensitive;
1809 else
1810 cs = sf->fcb->case_sensitive;
1811 }
1812
1813 Status = open_fileref_child(Vcb, sf, &nb->us, cs, lastpart, streampart, pooltype, &sf2, Irp);
1814
1815 if (!NT_SUCCESS(Status)) {
1817 TRACE("open_fileref_child returned %08lx\n", Status);
1818 else
1819 ERR("open_fileref_child returned %08lx\n", Status);
1820
1821 goto end;
1822 }
1823
1824 if (le->Flink == &parts) { // last entry
1825 if (fn_offset) {
1826 if (has_stream)
1828
1829 *fn_offset = (ULONG)(nb->us.Buffer - fnus->Buffer);
1830 }
1831
1832 break;
1833 }
1834
1837
1838 if (parsed) {
1840
1841 *parsed = (USHORT)(nb2->us.Buffer - fnus->Buffer - 1) * sizeof(WCHAR);
1842 }
1843
1844 break;
1845 }
1846
1847 free_fileref(sf);
1848 sf = sf2;
1849
1850 le = le->Flink;
1851 } while (le != &parts);
1852
1853 if (Status != STATUS_REPARSE)
1855 *pfr = sf2;
1856
1857end:
1858 free_fileref(sf);
1859
1860 while (!IsListEmpty(&parts)) {
1862 ExFreeToPagedLookasideList(&Vcb->name_bit_lookaside, nb);
1863 }
1864
1865end2:
1866 TRACE("returning %08lx\n", Status);
1867
1868 return Status;
1869}
unsigned int dir
Definition: maze.c:112
void free_fileref(_Inout_ file_ref *fr)
Definition: btrfs.c:1856
static const WCHAR datastring[]
Definition: create.c:30
NTSTATUS open_fileref_child(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension *Vcb, _In_ file_ref *sf, _In_ PUNICODE_STRING name, _In_ bool case_sensitive, _In_ bool lastpart, _In_ bool streampart, _In_ POOL_TYPE pooltype, _Out_ file_ref **psf2, _In_opt_ PIRP Irp)
Definition: create.c:1459
static NTSTATUS split_path(device_extension *Vcb, PUNICODE_STRING path, LIST_ENTRY *parts, bool *stream)
Definition: create.c:321
#define RemoveTailList(ListHead)
Definition: env_spec_w32.h:975
#define cs
Definition: i386-dis.c:442
static const D3D_BLOB_PART parts[]
Definition: blob.c:76
#define STATUS_REPARSE
Definition: ntstatus.h:83
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70
UNICODE_STRING us
Definition: btrfs_drv.h:955
#define STATUS_OBJECT_PATH_NOT_FOUND
Definition: udferr_usr.h:151

Referenced by create_snapshot(), create_stream(), create_subvol(), file_create(), open_file(), set_link_information(), and set_rename_information().

◆ open_fileref_by_inode()

NTSTATUS open_fileref_by_inode ( _Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension Vcb,
root subvol,
uint64_t  inode,
file_ref **  pfr,
PIRP  Irp 
)

Definition at line 4136 of file create.c.

4137 {
4139 fcb* fcb;
4140 uint64_t parent = 0;
4142 bool hl_alloc = false;
4143 file_ref *parfr, *fr;
4144
4145 Status = open_fcb(Vcb, subvol, inode, 0, NULL, true, NULL, &fcb, PagedPool, Irp);
4146 if (!NT_SUCCESS(Status)) {
4147 ERR("open_fcb returned %08lx\n", Status);
4148 return Status;
4149 }
4150
4151 ExAcquireResourceSharedLite(fcb->Header.Resource, true);
4152
4153 if (fcb->inode_item.st_nlink == 0 || fcb->deleted) {
4154 ExReleaseResourceLite(fcb->Header.Resource);
4155 free_fcb(fcb);
4157 }
4158
4159 if (fcb->fileref) {
4160 *pfr = fcb->fileref;
4162 free_fcb(fcb);
4163 ExReleaseResourceLite(fcb->Header.Resource);
4164 return STATUS_SUCCESS;
4165 }
4166
4167 if (IsListEmpty(&fcb->hardlinks)) {
4168 ExReleaseResourceLite(fcb->Header.Resource);
4169
4170 ExAcquireResourceSharedLite(&Vcb->dirty_filerefs_lock, true);
4171
4172 if (!IsListEmpty(&Vcb->dirty_filerefs)) {
4173 LIST_ENTRY* le = Vcb->dirty_filerefs.Flink;
4174 while (le != &Vcb->dirty_filerefs) {
4175 fr = CONTAINING_RECORD(le, file_ref, list_entry_dirty);
4176
4177 if (fr->fcb == fcb) {
4178 ExReleaseResourceLite(&Vcb->dirty_filerefs_lock);
4180 free_fcb(fcb);
4181 *pfr = fr;
4182 return STATUS_SUCCESS;
4183 }
4184
4185 le = le->Flink;
4186 }
4187 }
4188
4189 ExReleaseResourceLite(&Vcb->dirty_filerefs_lock);
4190
4191 {
4192 KEY searchkey;
4194
4195 searchkey.obj_id = fcb->inode;
4196 searchkey.obj_type = TYPE_INODE_REF;
4197 searchkey.offset = 0;
4198
4199 Status = find_item(Vcb, subvol, &tp, &searchkey, false, Irp);
4200 if (!NT_SUCCESS(Status)) {
4201 ERR("find_item returned %08lx\n", Status);
4202 free_fcb(fcb);
4203 return Status;
4204 }
4205
4206 do {
4207 traverse_ptr next_tp;
4208
4210 break;
4211
4212 if (tp.item->key.obj_id == fcb->inode) {
4213 if (tp.item->key.obj_type == TYPE_INODE_REF) {
4214 INODE_REF* ir = (INODE_REF*)tp.item->data;
4215
4216 if (tp.item->size < offsetof(INODE_REF, name[0]) || tp.item->size < offsetof(INODE_REF, name[0]) + ir->n) {
4217 ERR("INODE_REF was too short\n");
4218 free_fcb(fcb);
4219 return STATUS_INTERNAL_ERROR;
4220 }
4221
4223
4224 Status = utf8_to_utf16(NULL, 0, &stringlen, ir->name, ir->n);
4225 if (!NT_SUCCESS(Status)) {
4226 ERR("utf8_to_utf16 1 returned %08lx\n", Status);
4227 free_fcb(fcb);
4228 return Status;
4229 }
4230
4231 name.Length = name.MaximumLength = (uint16_t)stringlen;
4232
4233 if (stringlen == 0)
4234 name.Buffer = NULL;
4235 else {
4236 name.Buffer = ExAllocatePoolWithTag(PagedPool, name.MaximumLength, ALLOC_TAG);
4237
4238 if (!name.Buffer) {
4239 ERR("out of memory\n");
4240 free_fcb(fcb);
4242 }
4243
4244 Status = utf8_to_utf16(name.Buffer, stringlen, &stringlen, ir->name, ir->n);
4245 if (!NT_SUCCESS(Status)) {
4246 ERR("utf8_to_utf16 2 returned %08lx\n", Status);
4247 ExFreePool(name.Buffer);
4248 free_fcb(fcb);
4249 return Status;
4250 }
4251
4252 hl_alloc = true;
4253 }
4254
4255 parent = tp.item->key.offset;
4256
4257 break;
4258 } else if (tp.item->key.obj_type == TYPE_INODE_EXTREF) {
4260
4261 if (tp.item->size < offsetof(INODE_EXTREF, name[0]) || tp.item->size < offsetof(INODE_EXTREF, name[0]) + ier->n) {
4262 ERR("INODE_EXTREF was too short\n");
4263 free_fcb(fcb);
4264 return STATUS_INTERNAL_ERROR;
4265 }
4266
4268
4269 Status = utf8_to_utf16(NULL, 0, &stringlen, ier->name, ier->n);
4270 if (!NT_SUCCESS(Status)) {
4271 ERR("utf8_to_utf16 1 returned %08lx\n", Status);
4272 free_fcb(fcb);
4273 return Status;
4274 }
4275
4276 name.Length = name.MaximumLength = (uint16_t)stringlen;
4277
4278 if (stringlen == 0)
4279 name.Buffer = NULL;
4280 else {
4281 name.Buffer = ExAllocatePoolWithTag(PagedPool, name.MaximumLength, ALLOC_TAG);
4282
4283 if (!name.Buffer) {
4284 ERR("out of memory\n");
4285 free_fcb(fcb);
4287 }
4288
4289 Status = utf8_to_utf16(name.Buffer, stringlen, &stringlen, ier->name, ier->n);
4290 if (!NT_SUCCESS(Status)) {
4291 ERR("utf8_to_utf16 2 returned %08lx\n", Status);
4292 ExFreePool(name.Buffer);
4293 free_fcb(fcb);
4294 return Status;
4295 }
4296
4297 hl_alloc = true;
4298 }
4299
4300 parent = ier->dir;
4301
4302 break;
4303 }
4304 }
4305
4306 if (find_next_item(Vcb, &tp, &next_tp, false, Irp))
4307 tp = next_tp;
4308 else
4309 break;
4310 } while (true);
4311 }
4312
4313 if (parent == 0) {
4314 WARN("trying to open inode with no references\n");
4315 free_fcb(fcb);
4317 }
4318 } else {
4320
4321 name = hl->name;
4322 parent = hl->parent;
4323
4324 ExReleaseResourceLite(fcb->Header.Resource);
4325 }
4326
4327 if (parent == inode) { // subvolume root
4328 KEY searchkey;
4330
4331 searchkey.obj_id = subvol->id;
4332 searchkey.obj_type = TYPE_ROOT_BACKREF;
4333 searchkey.offset = 0xffffffffffffffff;
4334
4335 Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
4336 if (!NT_SUCCESS(Status)) {
4337 ERR("find_item returned %08lx\n", Status);
4338 free_fcb(fcb);
4339 return Status;
4340 }
4341
4342 if (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == searchkey.obj_type) {
4343 ROOT_REF* rr = (ROOT_REF*)tp.item->data;
4344 LIST_ENTRY* le;
4345 root* r = NULL;
4347
4348 if (tp.item->size < sizeof(ROOT_REF)) {
4349 ERR("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(ROOT_REF));
4350 free_fcb(fcb);
4351 return STATUS_INTERNAL_ERROR;
4352 }
4353
4354 if (tp.item->size < offsetof(ROOT_REF, name[0]) + rr->n) {
4355 ERR("(%I64x,%x,%I64x) was %u bytes, expected %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, offsetof(ROOT_REF, name[0]) + rr->n);
4356 free_fcb(fcb);
4357 return STATUS_INTERNAL_ERROR;
4358 }
4359
4360 le = Vcb->roots.Flink;
4361 while (le != &Vcb->roots) {
4363
4364 if (r2->id == tp.item->key.offset) {
4365 r = r2;
4366 break;
4367 }
4368
4369 le = le->Flink;
4370 }
4371
4372 if (!r) {
4373 ERR("couldn't find subvol %I64x\n", tp.item->key.offset);
4374 free_fcb(fcb);
4375 return STATUS_INTERNAL_ERROR;
4376 }
4377
4378 Status = open_fileref_by_inode(Vcb, r, rr->dir, &parfr, Irp);
4379 if (!NT_SUCCESS(Status)) {
4380 ERR("open_fileref_by_inode returned %08lx\n", Status);
4381 free_fcb(fcb);
4382 return Status;
4383 }
4384
4385 Status = utf8_to_utf16(NULL, 0, &stringlen, rr->name, rr->n);
4386 if (!NT_SUCCESS(Status)) {
4387 ERR("utf8_to_utf16 1 returned %08lx\n", Status);
4388 free_fcb(fcb);
4389 return Status;
4390 }
4391
4392 name.Length = name.MaximumLength = (uint16_t)stringlen;
4393
4394 if (stringlen == 0)
4395 name.Buffer = NULL;
4396 else {
4397 if (hl_alloc)
4398 ExFreePool(name.Buffer);
4399
4400 name.Buffer = ExAllocatePoolWithTag(PagedPool, name.MaximumLength, ALLOC_TAG);
4401
4402 if (!name.Buffer) {
4403 ERR("out of memory\n");
4404 free_fcb(fcb);
4406 }
4407
4408 Status = utf8_to_utf16(name.Buffer, stringlen, &stringlen, rr->name, rr->n);
4409 if (!NT_SUCCESS(Status)) {
4410 ERR("utf8_to_utf16 2 returned %08lx\n", Status);
4411 ExFreePool(name.Buffer);
4412 free_fcb(fcb);
4413 return Status;
4414 }
4415
4416 hl_alloc = true;
4417 }
4418 } else {
4419 if (!Vcb->options.no_root_dir && subvol->id == BTRFS_ROOT_FSTREE && Vcb->root_fileref->fcb->subvol != subvol) {
4420 Status = open_fileref_by_inode(Vcb, Vcb->root_fileref->fcb->subvol, SUBVOL_ROOT_INODE, &parfr, Irp);
4421 if (!NT_SUCCESS(Status)) {
4422 ERR("open_fileref_by_inode returned %08lx\n", Status);
4423 free_fcb(fcb);
4424 return Status;
4425 }
4426
4427 name.Length = name.MaximumLength = sizeof(root_dir_utf16) - sizeof(WCHAR);
4428 name.Buffer = (WCHAR*)root_dir_utf16;
4429 } else {
4430 ERR("couldn't find parent for subvol %I64x\n", subvol->id);
4431 free_fcb(fcb);
4432 return STATUS_INTERNAL_ERROR;
4433 }
4434 }
4435 } else {
4436 Status = open_fileref_by_inode(Vcb, subvol, parent, &parfr, Irp);
4437 if (!NT_SUCCESS(Status)) {
4438 ERR("open_fileref_by_inode returned %08lx\n", Status);
4439 free_fcb(fcb);
4440 return Status;
4441 }
4442 }
4443
4444 Status = open_fileref_child(Vcb, parfr, &name, true, true, false, PagedPool, &fr, Irp);
4445
4446 if (hl_alloc)
4447 ExFreePool(name.Buffer);
4448
4449 if (!NT_SUCCESS(Status)) {
4450 ERR("open_fileref_child returned %08lx\n", Status);
4451
4452 free_fcb(fcb);
4453 free_fileref(parfr);
4454
4455 return Status;
4456 }
4457
4458 *pfr = fr;
4459
4460 free_fcb(fcb);
4461 free_fileref(parfr);
4462
4463 return STATUS_SUCCESS;
4464}
#define TYPE_ROOT_BACKREF
Definition: btrfs.h:33
NTSTATUS open_fileref_by_inode(_Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension *Vcb, root *subvol, uint64_t inode, file_ref **pfr, PIRP Irp)
Definition: create.c:4136
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)
Definition: create.c:706
uint64_t dir
Definition: btrfs.h:462
char name[1]
Definition: btrfs.h:465
uint16_t n
Definition: btrfs.h:464
struct _file_ref * fileref
Definition: btrfs_drv.h:305

Referenced by fill_in_hard_link_full_id_information(), fill_in_hard_link_information(), get_subvol_path(), open_file(), open_fileref_by_inode(), and send_notification_fcb().

◆ open_fileref_child()

NTSTATUS open_fileref_child ( _Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension Vcb,
_In_ file_ref sf,
_In_ PUNICODE_STRING  name,
_In_ bool  case_sensitive,
_In_ bool  lastpart,
_In_ bool  streampart,
_In_ POOL_TYPE  pooltype,
_Out_ file_ref **  psf2,
_In_opt_ PIRP  Irp 
)

Definition at line 1459 of file create.c.

1461 {
1463 file_ref* sf2;
1464
1465 if (sf->fcb == Vcb->dummy_fcb)
1467
1468 if (streampart) {
1469 bool locked = false;
1470 LIST_ENTRY* le;
1471 UNICODE_STRING name_uc;
1472 dir_child* dc = NULL;
1473 fcb* fcb;
1474 struct _fcb* duff_fcb = NULL;
1475 file_ref* duff_fr = NULL;
1476
1477 if (!case_sensitive) {
1478 Status = RtlUpcaseUnicodeString(&name_uc, name, true);
1479 if (!NT_SUCCESS(Status)) {
1480 ERR("RtlUpcaseUnicodeString returned %08lx\n", Status);
1481 return Status;
1482 }
1483 }
1484
1485 if (!ExIsResourceAcquiredSharedLite(&sf->fcb->nonpaged->dir_children_lock)) {
1486 ExAcquireResourceSharedLite(&sf->fcb->nonpaged->dir_children_lock, true);
1487 locked = true;
1488 }
1489
1490 le = sf->fcb->dir_children_index.Flink;
1491 while (le != &sf->fcb->dir_children_index) {
1492 dir_child* dc2 = CONTAINING_RECORD(le, dir_child, list_entry_index);
1493
1494 if (dc2->index == 0) {
1495 if ((case_sensitive && dc2->name.Length == name->Length && RtlCompareMemory(dc2->name.Buffer, name->Buffer, dc2->name.Length) == dc2->name.Length) ||
1496 (!case_sensitive && dc2->name_uc.Length == name_uc.Length && RtlCompareMemory(dc2->name_uc.Buffer, name_uc.Buffer, dc2->name_uc.Length) == dc2->name_uc.Length)
1497 ) {
1498 dc = dc2;
1499 break;
1500 }
1501 } else
1502 break;
1503
1504 le = le->Flink;
1505 }
1506
1507 if (!dc) {
1508 if (locked)
1509 ExReleaseResourceLite(&sf->fcb->nonpaged->dir_children_lock);
1510
1511 if (!case_sensitive)
1512 ExFreePool(name_uc.Buffer);
1513
1515 }
1516
1517 if (dc->fileref) {
1518 if (locked)
1519 ExReleaseResourceLite(&sf->fcb->nonpaged->dir_children_lock);
1520
1521 if (!case_sensitive)
1522 ExFreePool(name_uc.Buffer);
1523
1524 increase_fileref_refcount(dc->fileref);
1525 *psf2 = dc->fileref;
1526 return STATUS_SUCCESS;
1527 }
1528
1529 if (locked)
1530 ExReleaseResourceLite(&sf->fcb->nonpaged->dir_children_lock);
1531
1532 if (!case_sensitive)
1533 ExFreePool(name_uc.Buffer);
1534
1535 Status = open_fcb_stream(Vcb, dc, sf->fcb, &fcb, Irp);
1536 if (!NT_SUCCESS(Status)) {
1537 ERR("open_fcb_stream returned %08lx\n", Status);
1538 return Status;
1539 }
1540
1541 fcb->hash = sf->fcb->hash;
1542
1543 acquire_fcb_lock_exclusive(Vcb);
1544
1545 if (sf->fcb->subvol->fcbs_ptrs[fcb->hash >> 24]) {
1546 le = sf->fcb->subvol->fcbs_ptrs[fcb->hash >> 24];
1547
1548 while (le != &sf->fcb->subvol->fcbs) {
1549 struct _fcb* fcb2 = CONTAINING_RECORD(le, struct _fcb, list_entry);
1550
1551 if (fcb2->inode == fcb->inode) {
1552 if (fcb2->ads && fcb2->adshash == fcb->adshash) { // FIXME - handle hash collisions
1553 duff_fcb = fcb;
1554 fcb = fcb2;
1555 break;
1556 }
1557 } else if (fcb2->hash > fcb->hash)
1558 break;
1559
1560 le = le->Flink;
1561 }
1562 }
1563
1564 if (!duff_fcb) {
1565 InsertHeadList(&sf->fcb->list_entry, &fcb->list_entry);
1566 InsertTailList(&Vcb->all_fcbs, &fcb->list_entry_all);
1567 fcb->subvol->fcbs_version++;
1568 }
1569
1570 release_fcb_lock(Vcb);
1571
1572 if (duff_fcb) {
1573 reap_fcb(duff_fcb);
1575 }
1576
1577 sf2 = create_fileref(Vcb);
1578 if (!sf2) {
1579 ERR("out of memory\n");
1580 free_fcb(fcb);
1582 }
1583
1584 ExAcquireResourceExclusiveLite(&sf->fcb->nonpaged->dir_children_lock, true);
1585
1586 if (dc->fileref) {
1587 duff_fr = sf2;
1588 sf2 = dc->fileref;
1590 } else {
1591 sf2->fcb = fcb;
1592 sf2->parent = (struct _file_ref*)sf;
1593 sf2->dc = dc;
1594 dc->fileref = sf2;
1596 InsertTailList(&sf->children, &sf2->list_entry);
1597 }
1598
1599 ExReleaseResourceLite(&sf->fcb->nonpaged->dir_children_lock);
1600
1601 if (duff_fr)
1602 ExFreeToPagedLookasideList(&Vcb->fileref_lookaside, duff_fr);
1603 } else {
1604 root* subvol;
1606 dir_child* dc;
1607
1608 Status = find_file_in_dir(name, sf->fcb, &subvol, &inode, &dc, case_sensitive);
1610 TRACE("could not find %.*S\n", (int)(name->Length / sizeof(WCHAR)), name->Buffer);
1611
1613 } else if (Status == STATUS_OBJECT_NAME_INVALID) {
1614 TRACE("invalid filename: %.*S\n", (int)(name->Length / sizeof(WCHAR)), name->Buffer);
1615 return Status;
1616 } else if (!NT_SUCCESS(Status)) {
1617 ERR("find_file_in_dir returned %08lx\n", Status);
1618 return Status;
1619 } else {
1620 fcb* fcb;
1621 file_ref* duff_fr = NULL;
1622
1623 if (dc->fileref) {
1624 if (!lastpart && dc->type != BTRFS_TYPE_DIRECTORY) {
1625 TRACE("passed path including file as subdirectory\n");
1627 }
1628
1629 InterlockedIncrement(&dc->fileref->refcount);
1630 *psf2 = dc->fileref;
1631 return STATUS_SUCCESS;
1632 }
1633
1634 if (!subvol || (subvol != Vcb->root_fileref->fcb->subvol && inode == SUBVOL_ROOT_INODE && subvol->parent != sf->fcb->subvol->id && !dc->root_dir)) {
1635 fcb = Vcb->dummy_fcb;
1637 } else {
1638 Status = open_fcb(Vcb, subvol, inode, dc->type, &dc->utf8, false, sf->fcb, &fcb, pooltype, Irp);
1639
1640 if (!NT_SUCCESS(Status)) {
1641 ERR("open_fcb returned %08lx\n", Status);
1642 return Status;
1643 }
1644 }
1645
1646 if (dc->type != BTRFS_TYPE_DIRECTORY && !lastpart && !(fcb->atts & FILE_ATTRIBUTE_REPARSE_POINT)) {
1647 TRACE("passed path including file as subdirectory\n");
1648 free_fcb(fcb);
1650 }
1651
1652 sf2 = create_fileref(Vcb);
1653 if (!sf2) {
1654 ERR("out of memory\n");
1655 free_fcb(fcb);
1657 }
1658
1659 sf2->fcb = fcb;
1660
1661 ExAcquireResourceExclusiveLite(&sf->fcb->nonpaged->dir_children_lock, true);
1662
1663 if (!dc->fileref) {
1664 sf2->parent = (struct _file_ref*)sf;
1665 sf2->dc = dc;
1666 dc->fileref = sf2;
1667 InsertTailList(&sf->children, &sf2->list_entry);
1669
1670 if (dc->type == BTRFS_TYPE_DIRECTORY)
1671 fcb->fileref = sf2;
1672 } else {
1673 duff_fr = sf2;
1674 sf2 = dc->fileref;
1676 }
1677
1678 ExReleaseResourceLite(&sf->fcb->nonpaged->dir_children_lock);
1679
1680 if (duff_fr)
1681 reap_fileref(Vcb, duff_fr);
1682 }
1683 }
1684
1685 *psf2 = sf2;
1686
1687 return STATUS_SUCCESS;
1688}
void reap_fileref(device_extension *Vcb, file_ref *fr)
Definition: btrfs.c:1875
static NTSTATUS open_fcb_stream(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension *Vcb, dir_child *dc, fcb *parent, fcb **pfcb, PIRP Irp)
Definition: create.c:1366
file_ref * create_fileref(device_extension *Vcb)
Definition: create.c:160
NTSTATUS find_file_in_dir(PUNICODE_STRING filename, fcb *fcb, root **subvol, uint64_t *inode, dir_child **pdc, bool case_sensitive)
Definition: create.c:182
LIST_ENTRY list_entry
Definition: btrfs_drv.h:357
uint64_t parent
Definition: btrfs_drv.h:459
UNICODE_STRING name_uc
Definition: btrfs_drv.h:258

Referenced by add_children_to_move_list(), open_file3(), open_fileref(), open_fileref_by_inode(), rename_file_to_stream(), and rename_stream().

◆ pause_balance()

NTSTATUS pause_balance ( device_extension Vcb,
KPROCESSOR_MODE  processor_mode 
)

Definition at line 3749 of file balance.c.

3749 {
3750 if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), processor_mode))
3752
3753 if (!Vcb->balance.thread)
3755
3756 if (Vcb->balance.paused)
3758
3759 Vcb->balance.paused = true;
3760 KeClearEvent(&Vcb->balance.event);
3761
3762 return STATUS_SUCCESS;
3763}
#define STATUS_PRIVILEGE_NOT_HELD
Definition: DriverTester.h:9
#define SE_MANAGE_VOLUME_PRIVILEGE
Definition: security.c:682
BOOLEAN NTAPI SeSinglePrivilegeCheck(_In_ LUID PrivilegeValue, _In_ KPROCESSOR_MODE PreviousMode)
Checks if a single privilege is present in the context of the calling thread.
Definition: priv.c:744

Referenced by fsctl_request().

◆ pause_scrub()

NTSTATUS pause_scrub ( device_extension Vcb,
KPROCESSOR_MODE  processor_mode 
)

Definition at line 3401 of file scrub.c.

3401 {
3403
3404 if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), processor_mode))
3406
3407 if (!Vcb->scrub.thread)
3409
3410 if (Vcb->scrub.paused)
3412
3413 Vcb->scrub.paused = true;
3414 KeClearEvent(&Vcb->scrub.event);
3415
3417 Vcb->scrub.duration.QuadPart += time.QuadPart - Vcb->scrub.resume_time.QuadPart;
3418
3419 return STATUS_SUCCESS;
3420}

Referenced by fsctl_request().

◆ pnp_query_remove_device()

NTSTATUS pnp_query_remove_device ( PDEVICE_OBJECT  DeviceObject,
PIRP  Irp 
)

Definition at line 23 of file pnp.c.

23 {
24 device_extension* Vcb = DeviceObject->DeviceExtension;
26
27 // We might be going away imminently - do a flush so we're not caught out
28
29 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
30
31 if (Vcb->root_fileref && Vcb->root_fileref->fcb && (Vcb->root_fileref->open_count > 0 || has_open_children(Vcb->root_fileref))) {
32 ExReleaseResourceLite(&Vcb->tree_lock);
34 }
35
36 if (Vcb->need_write && !Vcb->readonly) {
38
40
41 if (!NT_SUCCESS(Status)) {
42 ERR("do_write returned %08lx\n", Status);
43 ExReleaseResourceLite(&Vcb->tree_lock);
44 return Status;
45 }
46 }
47
48 ExReleaseResourceLite(&Vcb->tree_lock);
49
51}
bool has_open_children(file_ref *fileref)
Definition: fileinfo.c:442
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132

Referenced by _Dispatch_type_(), and _Function_class_().

◆ pnp_surprise_removal()

NTSTATUS pnp_surprise_removal ( PDEVICE_OBJECT  DeviceObject,
PIRP  Irp 
)

Definition at line 77 of file pnp.c.

77 {
78 device_extension* Vcb = DeviceObject->DeviceExtension;
79
80 TRACE("(%p, %p)\n", DeviceObject, Irp);
81
82 UNUSED(Irp);
83
84 if (DeviceObject->Vpb->Flags & VPB_MOUNTED) {
85 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
86
87 if (Vcb->vde)
88 Vcb->vde->mounted_device = NULL;
89
90 Vcb->removing = true;
91
92 ExReleaseResourceLite(&Vcb->tree_lock);
93
94 if (Vcb->open_files == 0)
95 uninit(Vcb);
96 }
97
98 return STATUS_SUCCESS;
99}
#define UNUSED(x)
Definition: btrfs_drv.h:82

Referenced by _Dispatch_type_(), and remove_volume_child().

◆ print_open_trees()

static __inline void print_open_trees ( device_extension Vcb)
static

Definition at line 1694 of file btrfs_drv.h.

1694 {
1695 LIST_ENTRY* le = Vcb->trees.Flink;
1696 while (le != &Vcb->trees) {
1698 tree_data* td = CONTAINING_RECORD(t->itemlist.Flink, tree_data, list_entry);
1699 ERR("tree %p: root %I64x, level %u, first key (%I64x,%x,%I64x)\n",
1700 t, t->root->id, t->header.level, td->key.obj_id, td->key.obj_type, td->key.offset);
1701
1702 le = le->Flink;
1703 }
1704}
#define ERR(s,...)
Definition: btrfs_drv.h:1234

◆ protect_superblocks()

void protect_superblocks ( _Inout_ chunk c)

Definition at line 3777 of file btrfs.c.

3777 {
3778 uint16_t i = 0, j;
3779 uint64_t off_start, off_end;
3780
3781 // The Linux driver also protects all the space before the first superblock.
3782 // I realize this confuses physical and logical addresses, but this is what btrfs-progs does -
3783 // evidently Linux assumes the chunk at 0 is always SINGLE.
3784 if (c->offset < superblock_addrs[0])
3785 space_list_subtract(c, c->offset, superblock_addrs[0] - c->offset, NULL);
3786
3787 while (superblock_addrs[i] != 0) {
3788 CHUNK_ITEM* ci = c->chunk_item;
3789 CHUNK_ITEM_STRIPE* cis = (CHUNK_ITEM_STRIPE*)&ci[1];
3790
3791 if (ci->type & BLOCK_FLAG_RAID0 || ci->type & BLOCK_FLAG_RAID10) {
3792 for (j = 0; j < ci->num_stripes; j++) {
3793 uint16_t sub_stripes = max(ci->sub_stripes, 1);
3794
3795 if (cis[j].offset + (ci->size * ci->num_stripes / sub_stripes) > superblock_addrs[i] && cis[j].offset <= superblock_addrs[i] + sizeof(superblock)) {
3796#ifdef _DEBUG
3797 uint64_t startoff;
3798 uint16_t startoffstripe;
3799#endif
3800
3801 TRACE("cut out superblock in chunk %I64x\n", c->offset);
3802
3803 off_start = superblock_addrs[i] - cis[j].offset;
3804 off_start -= off_start % ci->stripe_length;
3805 off_start *= ci->num_stripes / sub_stripes;
3806 off_start += (j / sub_stripes) * ci->stripe_length;
3807
3808 off_end = off_start + ci->stripe_length;
3809
3810#ifdef _DEBUG
3811 get_raid0_offset(off_start, ci->stripe_length, ci->num_stripes / sub_stripes, &startoff, &startoffstripe);
3812 TRACE("j = %u, startoffstripe = %u\n", j, startoffstripe);
3813 TRACE("startoff = %I64x, superblock = %I64x\n", startoff + cis[j].offset, superblock_addrs[i]);
3814#endif
3815
3816 space_list_subtract(c, c->offset + off_start, off_end - off_start, NULL);
3817 }
3818 }
3819 } else if (ci->type & BLOCK_FLAG_RAID5) {
3820 uint64_t stripe_size = ci->size / (ci->num_stripes - 1);
3821
3822 for (j = 0; j < ci->num_stripes; j++) {
3823 if (cis[j].offset + stripe_size > superblock_addrs[i] && cis[j].offset <= superblock_addrs[i] + sizeof(superblock)) {
3824 TRACE("cut out superblock in chunk %I64x\n", c->offset);
3825
3826 off_start = superblock_addrs[i] - cis[j].offset;
3827 off_start -= off_start % ci->stripe_length;
3828 off_start *= ci->num_stripes - 1;
3829
3830 off_end = sector_align(superblock_addrs[i] - cis[j].offset + sizeof(superblock), ci->stripe_length);
3831 off_end *= ci->num_stripes - 1;
3832
3833 TRACE("cutting out %I64x, size %I64x\n", c->offset + off_start, off_end - off_start);
3834
3835 space_list_subtract(c, c->offset + off_start, off_end - off_start, NULL);
3836 }
3837 }
3838 } else if (ci->type & BLOCK_FLAG_RAID6) {
3839 uint64_t stripe_size = ci->size / (ci->num_stripes - 2);
3840
3841 for (j = 0; j < ci->num_stripes; j++) {
3842 if (cis[j].offset + stripe_size > superblock_addrs[i] && cis[j].offset <= superblock_addrs[i] + sizeof(superblock)) {
3843 TRACE("cut out superblock in chunk %I64x\n", c->offset);
3844
3845 off_start = superblock_addrs[i] - cis[j].offset;
3846 off_start -= off_start % ci->stripe_length;
3847 off_start *= ci->num_stripes - 2;
3848
3849 off_end = sector_align(superblock_addrs[i] - cis[j].offset + sizeof(superblock), ci->stripe_length);
3850 off_end *= ci->num_stripes - 2;
3851
3852 TRACE("cutting out %I64x, size %I64x\n", c->offset + off_start, off_end - off_start);
3853
3854 space_list_subtract(c, c->offset + off_start, off_end - off_start, NULL);
3855 }
3856 }
3857 } else { // SINGLE, DUPLICATE, RAID1, RAID1C3, RAID1C4
3858 for (j = 0; j < ci->num_stripes; j++) {
3859 if (cis[j].offset + ci->size > superblock_addrs[i] && cis[j].offset <= superblock_addrs[i] + sizeof(superblock)) {
3860 TRACE("cut out superblock in chunk %I64x\n", c->offset);
3861
3862 // The Linux driver protects the whole stripe in which the superblock lives
3863
3864 off_start = ((superblock_addrs[i] - cis[j].offset) / c->chunk_item->stripe_length) * c->chunk_item->stripe_length;
3865 off_end = sector_align(superblock_addrs[i] - cis[j].offset + sizeof(superblock), c->chunk_item->stripe_length);
3866
3867 space_list_subtract(c, c->offset + off_start, off_end - off_start, NULL);
3868 }
3869 }
3870 }
3871
3872 i++;
3873 }
3874}
void space_list_subtract(chunk *c, uint64_t address, uint64_t length, LIST_ENTRY *rollback)
Definition: free-space.c:2234
#define BLOCK_FLAG_RAID10
Definition: shellext.h:81
#define BLOCK_FLAG_RAID0
Definition: shellext.h:78
uint64_t offset
Definition: btrfs.h:353
uint16_t num_stripes
Definition: btrfs.h:347
uint64_t stripe_length
Definition: btrfs.h:342
uint16_t sub_stripes
Definition: btrfs.h:348
uint64_t size
Definition: btrfs.h:340

Referenced by __attribute__(), and load_cache_chunk().

◆ PsGetThreadProcess()

◆ query_balance()

NTSTATUS query_balance ( device_extension Vcb,
void data,
ULONG  length 
)

Definition at line 3711 of file balance.c.

3711 {
3713
3714 if (length < sizeof(btrfs_query_balance) || !data)
3716
3717 if (!Vcb->balance.thread) {
3719
3720 if (!NT_SUCCESS(Vcb->balance.status)) {
3722 bqb->error = Vcb->balance.status;
3723 }
3724
3725 return STATUS_SUCCESS;
3726 }
3727
3728 bqb->status = Vcb->balance.paused ? BTRFS_BALANCE_PAUSED : BTRFS_BALANCE_RUNNING;
3729
3730 if (Vcb->balance.removing)
3732
3733 if (Vcb->balance.shrinking)
3735
3736 if (!NT_SUCCESS(Vcb->balance.status))
3738
3739 bqb->chunks_left = Vcb->balance.chunks_left;
3740 bqb->total_chunks = Vcb->balance.total_chunks;
3741 bqb->error = Vcb->balance.status;
3742 RtlCopyMemory(&bqb->data_opts, &Vcb->balance.opts[BALANCE_OPTS_DATA], sizeof(btrfs_balance_opts));
3744 RtlCopyMemory(&bqb->system_opts, &Vcb->balance.opts[BALANCE_OPTS_SYSTEM], sizeof(btrfs_balance_opts));
3745
3746 return STATUS_SUCCESS;
3747}
#define BTRFS_BALANCE_STOPPED
Definition: btrfsioctl.h:160
#define BTRFS_BALANCE_ERROR
Definition: btrfsioctl.h:164
#define BTRFS_BALANCE_SHRINKING
Definition: btrfsioctl.h:165
#define BTRFS_BALANCE_RUNNING
Definition: btrfsioctl.h:161
#define BTRFS_BALANCE_PAUSED
Definition: btrfsioctl.h:162
#define BTRFS_BALANCE_REMOVAL
Definition: btrfsioctl.h:163
btrfs_balance_opts data_opts
Definition: btrfsioctl.h:172
uint64_t total_chunks
Definition: btrfsioctl.h:170
btrfs_balance_opts metadata_opts
Definition: btrfsioctl.h:173
uint64_t chunks_left
Definition: btrfsioctl.h:169
btrfs_balance_opts system_opts
Definition: btrfsioctl.h:174

Referenced by fsctl_request().

◆ query_scrub()

NTSTATUS query_scrub ( device_extension Vcb,
KPROCESSOR_MODE  processor_mode,
void data,
ULONG  length 
)

Definition at line 3301 of file scrub.c.

3301 {
3303 ULONG len;
3305 LIST_ENTRY* le;
3306 btrfs_scrub_error* bse = NULL;
3307
3308 if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), processor_mode))
3310
3311 if (length < offsetof(btrfs_query_scrub, errors))
3313
3314 ExAcquireResourceSharedLite(&Vcb->scrub.stats_lock, true);
3315
3316 if (Vcb->scrub.thread && Vcb->scrub.chunks_left > 0)
3317 bqs->status = Vcb->scrub.paused ? BTRFS_SCRUB_PAUSED : BTRFS_SCRUB_RUNNING;
3318 else
3320
3321 bqs->start_time.QuadPart = Vcb->scrub.start_time.QuadPart;
3322 bqs->finish_time.QuadPart = Vcb->scrub.finish_time.QuadPart;
3323 bqs->chunks_left = Vcb->scrub.chunks_left;
3324 bqs->total_chunks = Vcb->scrub.total_chunks;
3325 bqs->data_scrubbed = Vcb->scrub.data_scrubbed;
3326
3327 bqs->duration = Vcb->scrub.duration.QuadPart;
3328
3329 if (bqs->status == BTRFS_SCRUB_RUNNING) {
3331
3333 bqs->duration += time.QuadPart - Vcb->scrub.resume_time.QuadPart;
3334 }
3335
3336 bqs->error = Vcb->scrub.error;
3337
3338 bqs->num_errors = Vcb->scrub.num_errors;
3339
3340 len = length - offsetof(btrfs_query_scrub, errors);
3341
3342 le = Vcb->scrub.errors.Flink;
3343 while (le != &Vcb->scrub.errors) {
3345 ULONG errlen;
3346
3347 if (err->is_metadata)
3348 errlen = offsetof(btrfs_scrub_error, metadata.firstitem) + sizeof(KEY);
3349 else
3350 errlen = offsetof(btrfs_scrub_error, data.filename) + err->data.filename_length;
3351
3352 if (len < errlen) {
3354 goto end;
3355 }
3356
3357 if (!bse)
3358 bse = &bqs->errors;
3359 else {
3360 ULONG lastlen;
3361
3362 if (bse->is_metadata)
3363 lastlen = offsetof(btrfs_scrub_error, metadata.firstitem) + sizeof(KEY);
3364 else
3365 lastlen = offsetof(btrfs_scrub_error, data.filename) + bse->data.filename_length;
3366
3367 bse->next_entry = lastlen;
3368 bse = (btrfs_scrub_error*)(((uint8_t*)bse) + lastlen);
3369 }
3370
3371 bse->next_entry = 0;
3372 bse->address = err->address;
3373 bse->device = err->device;
3374 bse->recovered = err->recovered;
3375 bse->is_metadata = err->is_metadata;
3376 bse->parity = err->parity;
3377
3378 if (err->is_metadata) {
3379 bse->metadata.root = err->metadata.root;
3380 bse->metadata.level = err->metadata.level;
3381 bse->metadata.firstitem = err->metadata.firstitem;
3382 } else {
3383 bse->data.subvol = err->data.subvol;
3384 bse->data.offset = err->data.offset;
3385 bse->data.filename_length = err->data.filename_length;
3386 RtlCopyMemory(bse->data.filename, err->data.filename, err->data.filename_length);
3387 }
3388
3389 len -= errlen;
3390 le = le->Flink;
3391 }
3392
3394
3395end:
3396 ExReleaseResourceLite(&Vcb->scrub.stats_lock);
3397
3398 return Status;
3399}
#define BTRFS_SCRUB_PAUSED
Definition: btrfsioctl.h:197
#define BTRFS_SCRUB_STOPPED
Definition: btrfsioctl.h:195
#define BTRFS_SCRUB_RUNNING
Definition: btrfsioctl.h:196
#define KEY
Definition: profile.c:30
#define err(...)
LARGE_INTEGER start_time
Definition: btrfsioctl.h:225
uint64_t chunks_left
Definition: btrfsioctl.h:227
uint32_t num_errors
Definition: btrfsioctl.h:232
LARGE_INTEGER finish_time
Definition: btrfsioctl.h:226
uint64_t duration
Definition: btrfsioctl.h:230
uint64_t data_scrubbed
Definition: btrfsioctl.h:229
uint64_t total_chunks
Definition: btrfsioctl.h:228
btrfs_scrub_error errors
Definition: btrfsioctl.h:233
WCHAR filename[1]
Definition: btrfsioctl.h:212
uint64_t address
Definition: btrfsioctl.h:201
uint32_t next_entry
Definition: btrfsioctl.h:200
struct btrfs_scrub_error::@656::@658 data
struct btrfs_scrub_error::@656::@659 metadata

Referenced by fsctl_request().

◆ queue_notification_fcb()

void queue_notification_fcb ( _In_ file_ref fileref,
_In_ ULONG  filter_match,
_In_ ULONG  action,
_In_opt_ PUNICODE_STRING  stream 
)

Definition at line 1667 of file btrfs.c.

1667 {
1668 notification_fcb* nf;
1669 PIO_WORKITEM work_item;
1670
1672 if (!nf) {
1673 ERR("out of memory\n");
1674 return;
1675 }
1676
1677 work_item = IoAllocateWorkItem(master_devobj);
1678 if (!work_item) {
1679 ERR("out of memory\n");
1680 ExFreePool(nf);
1681 return;
1682 }
1683
1684 InterlockedIncrement(&fileref->refcount);
1685
1686 nf->fileref = fileref;
1687 nf->filter_match = filter_match;
1688 nf->action = action;
1689 nf->stream = stream;
1690 nf->work_item = work_item;
1691
1692 IoQueueWorkItem(work_item, notification_work_item, DelayedWorkQueue, nf);
1693}
const WCHAR * action
Definition: action.c:7479
VOID NTAPI IoQueueWorkItem(IN PIO_WORKITEM IoWorkItem, IN PIO_WORKITEM_ROUTINE WorkerRoutine, IN WORK_QUEUE_TYPE QueueType, IN PVOID Context)
Definition: iowork.c:40
PIO_WORKITEM NTAPI IoAllocateWorkItem(IN PDEVICE_OBJECT DeviceObject)
Definition: iowork.c:75
ULONG filter_match
Definition: btrfs.c:1642
ULONG action
Definition: btrfs.c:1643
PUNICODE_STRING stream
Definition: btrfs.c:1644
file_ref * fileref
Definition: btrfs.c:1641
PIO_WORKITEM work_item
Definition: btrfs.c:1645

Referenced by __attribute__(), create_stream(), delete_reparse_point(), duplicate_extents(), file_create(), mknod(), open_file3(), set_basic_information(), set_end_of_file_information(), set_file_security(), set_reparse_point(), set_sparse(), set_valid_data_length_information(), and set_zero_data().

◆ raid6_recover2()

void raid6_recover2 ( uint8_t sectors,
uint16_t  num_stripes,
ULONG  sector_size,
uint16_t  missing1,
uint16_t  missing2,
uint8_t out 
)

Definition at line 918 of file read.c.

918 {
919 if (missing1 == num_stripes - 2 || missing2 == num_stripes - 2) { // reconstruct from q and data
920 uint16_t missing = missing1 == (num_stripes - 2) ? missing2 : missing1;
922
923 stripe = num_stripes - 3;
924
925 if (stripe == missing)
927 else
929
930 do {
931 stripe--;
932
934
935 if (stripe != missing)
937 } while (stripe > 0);
938
939 do_xor(out, sectors + ((num_stripes - 1) * sector_size), sector_size);
940
941 if (missing != 0)
943 } else { // reconstruct from p and q
944 uint16_t x = missing1, y = missing2, stripe;
945 uint8_t gyx, gx, denom, a, b, *p, *q, *pxy, *qxy;
946 uint32_t j;
947
948 stripe = num_stripes - 3;
949
950 pxy = out + sector_size;
951 qxy = out;
952
953 if (stripe == missing1 || stripe == missing2) {
956 } else {
959 }
960
961 do {
962 stripe--;
963
965
966 if (stripe != missing1 && stripe != missing2) {
969 }
970 } while (stripe > 0);
971
972 gyx = gpow2(y > x ? (y-x) : (255-x+y));
973 gx = gpow2(255-x);
974
975 denom = gdiv(1, gyx ^ 1);
976 a = gmul(gyx, denom);
977 b = gmul(gx, denom);
978
979 p = sectors + ((num_stripes - 2) * sector_size);
980 q = sectors + ((num_stripes - 1) * sector_size);
981
982 for (j = 0; j < sector_size; j++) {
983 *qxy = gmul(a, *p ^ *pxy) ^ gmul(b, *q ^ *qxy);
984
985 p++;
986 q++;
987 pxy++;
988 qxy++;
989 }
990
992 do_xor(out + sector_size, sectors + ((num_stripes - 2) * sector_size), sector_size);
993 }
994}
uint8_t gdiv(uint8_t a, uint8_t b)
Definition: galois.c:80
uint8_t gmul(uint8_t a, uint8_t b)
Definition: galois.c:73
void galois_divpower(uint8_t *data, uint8_t div, uint32_t readlen)
Definition: galois.c:55
uint8_t gpow2(uint8_t e)
Definition: galois.c:69
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
__u8 sector_size[2]
Definition: mkdosfs.c:3

Referenced by partial_stripe_read(), and read_data_raid6().

◆ read_data()

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 
)

Definition at line 1478 of file read.c.

1480 {
1481 CHUNK_ITEM* ci;
1482 CHUNK_ITEM_STRIPE* cis;
1484 uint64_t type, offset, total_reading = 0;
1486 device** devices = NULL;
1487 uint16_t i, startoffstripe, allowed_missing, missing_devices = 0;
1488 uint8_t* dummypage = NULL;
1489 PMDL dummy_mdl = NULL;
1490 bool need_to_wait;
1491 uint64_t lockaddr, locklen;
1492
1493 if (Vcb->log_to_phys_loaded) {
1494 if (!c) {
1496
1497 if (!c) {
1498 ERR("get_chunk_from_address failed\n");
1499 return STATUS_INTERNAL_ERROR;
1500 }
1501 }
1502
1503 ci = c->chunk_item;
1504 offset = c->offset;
1505 devices = c->devices;
1506
1507 if (pc)
1508 *pc = c;
1509 } else {
1510 LIST_ENTRY* le = Vcb->sys_chunks.Flink;
1511
1512 ci = NULL;
1513
1514 c = NULL;
1515 while (le != &Vcb->sys_chunks) {
1517
1518 if (sc->key.obj_id == 0x100 && sc->key.obj_type == TYPE_CHUNK_ITEM && sc->key.offset <= addr) {
1519 CHUNK_ITEM* chunk_item = sc->data;
1520
1521 if ((addr - sc->key.offset) < chunk_item->size && chunk_item->num_stripes > 0) {
1522 ci = chunk_item;
1523 offset = sc->key.offset;
1524 cis = (CHUNK_ITEM_STRIPE*)&chunk_item[1];
1525
1527 if (!devices) {
1528 ERR("out of memory\n");
1530 }
1531
1532 for (i = 0; i < ci->num_stripes; i++) {
1533 devices[i] = find_device_from_uuid(Vcb, &cis[i].dev_uuid);
1534 }
1535
1536 break;
1537 }
1538 }
1539
1540 le = le->Flink;
1541 }
1542
1543 if (!ci) {
1544 ERR("could not find chunk for %I64x in bootstrap\n", addr);
1545 return STATUS_INTERNAL_ERROR;
1546 }
1547
1548 if (pc)
1549 *pc = NULL;
1550 }
1551
1552 if (ci->type & BLOCK_FLAG_DUPLICATE) {
1554 allowed_missing = ci->num_stripes - 1;
1555 } else if (ci->type & BLOCK_FLAG_RAID0) {
1557 allowed_missing = 0;
1558 } else if (ci->type & BLOCK_FLAG_RAID1) {
1560 allowed_missing = 1;
1561 } else if (ci->type & BLOCK_FLAG_RAID10) {
1563 allowed_missing = 1;
1564 } else if (ci->type & BLOCK_FLAG_RAID5) {
1566 allowed_missing = 1;
1567 } else if (ci->type & BLOCK_FLAG_RAID6) {
1569 allowed_missing = 2;
1570 } else if (ci->type & BLOCK_FLAG_RAID1C3) {
1572 allowed_missing = 2;
1573 } else if (ci->type & BLOCK_FLAG_RAID1C4) {
1575 allowed_missing = 3;
1576 } else { // SINGLE
1578 allowed_missing = 0;
1579 }
1580
1581 cis = (CHUNK_ITEM_STRIPE*)&ci[1];
1582
1585
1587 if (!context.stripes) {
1588 ERR("out of memory\n");
1590 }
1591
1592 if (c && (type == BLOCK_FLAG_RAID5 || type == BLOCK_FLAG_RAID6)) {
1593 get_raid56_lock_range(c, addr, length, &lockaddr, &locklen);
1594 chunk_lock_range(Vcb, c, lockaddr, locklen);
1595 }
1596
1597 RtlZeroMemory(context.stripes, sizeof(read_data_stripe) * ci->num_stripes);
1598
1599 context.buflen = length;
1600 context.num_stripes = ci->num_stripes;
1601 context.stripes_left = context.num_stripes;
1602 context.sector_size = Vcb->superblock.sector_size;
1603 context.csum = csum;
1604 context.tree = is_tree;
1605 context.type = type;
1606
1607 if (type == BLOCK_FLAG_RAID0) {
1608 uint64_t startoff, endoff;
1609 uint16_t endoffstripe, stripe;
1610 uint32_t *stripeoff, pos;
1611 PMDL master_mdl;
1612 PFN_NUMBER* pfns;
1613
1614 // FIXME - test this still works if page size isn't the same as sector size
1615
1616 // This relies on the fact that MDLs are followed in memory by the page file numbers,
1617 // so with a bit of jiggery-pokery you can trick your disks into deinterlacing your RAID0
1618 // data for you without doing a memcpy yourself.
1619 // MDLs are officially opaque, so this might very well break in future versions of Windows.
1620
1621 get_raid0_offset(addr - offset, ci->stripe_length, ci->num_stripes, &startoff, &startoffstripe);
1622 get_raid0_offset(addr + length - offset - 1, ci->stripe_length, ci->num_stripes, &endoff, &endoffstripe);
1623
1624 if (file_read) {
1625 // Unfortunately we can't avoid doing at least one memcpy, as Windows can give us an MDL
1626 // with duplicated dummy PFNs, which confuse check_csum. Ah well.
1627 // See https://msdn.microsoft.com/en-us/library/windows/hardware/Dn614012.aspx if you're interested.
1628
1630
1631 if (!context.va) {
1632 ERR("out of memory\n");
1634 goto exit;
1635 }
1636 } else
1637 context.va = buf;
1638
1639 master_mdl = IoAllocateMdl(context.va, length, false, false, NULL);
1640 if (!master_mdl) {
1641 ERR("out of memory\n");
1643 goto exit;
1644 }
1645
1647
1648 _SEH2_TRY {
1652 } _SEH2_END;
1653
1654 if (!NT_SUCCESS(Status)) {
1655 ERR("MmProbeAndLockPages threw exception %08lx\n", Status);
1656 IoFreeMdl(master_mdl);
1657 goto exit;
1658 }
1659
1660 pfns = (PFN_NUMBER*)(master_mdl + 1);
1661
1662 for (i = 0; i < ci->num_stripes; i++) {
1663 if (startoffstripe > i)
1664 context.stripes[i].stripestart = startoff - (startoff % ci->stripe_length) + ci->stripe_length;
1665 else if (startoffstripe == i)
1666 context.stripes[i].stripestart = startoff;
1667 else
1668 context.stripes[i].stripestart = startoff - (startoff % ci->stripe_length);
1669
1670 if (endoffstripe > i)
1671 context.stripes[i].stripeend = endoff - (endoff % ci->stripe_length) + ci->stripe_length;
1672 else if (endoffstripe == i)
1673 context.stripes[i].stripeend = endoff + 1;
1674 else
1675 context.stripes[i].stripeend = endoff - (endoff % ci->stripe_length);
1676
1677 if (context.stripes[i].stripestart != context.stripes[i].stripeend) {
1678 context.stripes[i].mdl = IoAllocateMdl(context.va, (ULONG)(context.stripes[i].stripeend - context.stripes[i].stripestart), false, false, NULL);
1679
1680 if (!context.stripes[i].mdl) {
1681 ERR("IoAllocateMdl failed\n");
1682 MmUnlockPages(master_mdl);
1683 IoFreeMdl(master_mdl);
1685 goto exit;
1686 }
1687 }
1688 }
1689
1691 if (!stripeoff) {
1692 ERR("out of memory\n");
1693 MmUnlockPages(master_mdl);
1694 IoFreeMdl(master_mdl);
1696 goto exit;
1697 }
1698
1699 RtlZeroMemory(stripeoff, sizeof(uint32_t) * ci->num_stripes);
1700
1701 pos = 0;
1702 stripe = startoffstripe;
1703 while (pos < length) {
1704 PFN_NUMBER* stripe_pfns = (PFN_NUMBER*)(context.stripes[stripe].mdl + 1);
1705
1706 if (pos == 0) {
1707 uint32_t readlen = (uint32_t)min(context.stripes[stripe].stripeend - context.stripes[stripe].stripestart, ci->stripe_length - (context.stripes[stripe].stripestart % ci->stripe_length));
1708
1709 RtlCopyMemory(stripe_pfns, pfns, readlen * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
1710
1711 stripeoff[stripe] += readlen;
1712 pos += readlen;
1713 } else if (length - pos < ci->stripe_length) {
1714 RtlCopyMemory(&stripe_pfns[stripeoff[stripe] >> PAGE_SHIFT], &pfns[pos >> PAGE_SHIFT], (length - pos) * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
1715
1716 pos = length;
1717 } else {
1718 RtlCopyMemory(&stripe_pfns[stripeoff[stripe] >> PAGE_SHIFT], &pfns[pos >> PAGE_SHIFT], (ULONG)(ci->stripe_length * sizeof(PFN_NUMBER) >> PAGE_SHIFT));
1719
1720 stripeoff[stripe] += (uint32_t)ci->stripe_length;
1721 pos += (uint32_t)ci->stripe_length;
1722 }
1723
1724 stripe = (stripe + 1) % ci->num_stripes;
1725 }
1726
1727 MmUnlockPages(master_mdl);
1728 IoFreeMdl(master_mdl);
1729
1730 ExFreePool(stripeoff);
1731 } else if (type == BLOCK_FLAG_RAID10) {
1732 uint64_t startoff, endoff;
1733 uint16_t endoffstripe, j, stripe;
1734 ULONG orig_ls;
1735 PMDL master_mdl;
1736 PFN_NUMBER* pfns;
1737 uint32_t* stripeoff, pos;
1738 read_data_stripe** stripes;
1739
1740 if (c)
1741 orig_ls = c->last_stripe;
1742 else
1743 orig_ls = 0;
1744
1745 get_raid0_offset(addr - offset, ci->stripe_length, ci->num_stripes / ci->sub_stripes, &startoff, &startoffstripe);
1746 get_raid0_offset(addr + length - offset - 1, ci->stripe_length, ci->num_stripes / ci->sub_stripes, &endoff, &endoffstripe);
1747
1748 if ((ci->num_stripes % ci->sub_stripes) != 0) {
1749 ERR("chunk %I64x: num_stripes %x was not a multiple of sub_stripes %x!\n", offset, ci->num_stripes, ci->sub_stripes);
1751 goto exit;
1752 }
1753
1754 if (file_read) {
1756
1757 if (!context.va) {
1758 ERR("out of memory\n");
1760 goto exit;
1761 }
1762 } else
1763 context.va = buf;
1764
1765 context.firstoff = (uint16_t)((startoff % ci->stripe_length) >> Vcb->sector_shift);
1766 context.startoffstripe = startoffstripe;
1767 context.sectors_per_stripe = (uint16_t)(ci->stripe_length >> Vcb->sector_shift);
1768
1769 startoffstripe *= ci->sub_stripes;
1770 endoffstripe *= ci->sub_stripes;
1771
1772 if (c)
1773 c->last_stripe = (orig_ls + 1) % ci->sub_stripes;
1774
1775 master_mdl = IoAllocateMdl(context.va, length, false, false, NULL);
1776 if (!master_mdl) {
1777 ERR("out of memory\n");
1779 goto exit;
1780 }
1781
1783
1784 _SEH2_TRY {
1788 } _SEH2_END;
1789
1790 if (!NT_SUCCESS(Status)) {
1791 ERR("MmProbeAndLockPages threw exception %08lx\n", Status);
1792 IoFreeMdl(master_mdl);
1793 goto exit;
1794 }
1795
1796 pfns = (PFN_NUMBER*)(master_mdl + 1);
1797
1799 if (!stripes) {
1800 ERR("out of memory\n");
1801 MmUnlockPages(master_mdl);
1802 IoFreeMdl(master_mdl);
1804 goto exit;
1805 }
1806
1807 RtlZeroMemory(stripes, sizeof(read_data_stripe*) * ci->num_stripes / ci->sub_stripes);
1808
1809 for (i = 0; i < ci->num_stripes; i += ci->sub_stripes) {
1810 uint64_t sstart, send;
1811 bool stripeset = false;
1812
1813 if (startoffstripe > i)
1814 sstart = startoff - (startoff % ci->stripe_length) + ci->stripe_length;
1815 else if (startoffstripe == i)
1816 sstart = startoff;
1817 else
1818 sstart = startoff - (startoff % ci->stripe_length);
1819
1820 if (endoffstripe > i)
1821 send = endoff - (endoff % ci->stripe_length) + ci->stripe_length;
1822 else if (endoffstripe == i)
1823 send = endoff + 1;
1824 else
1825 send = endoff - (endoff % ci->stripe_length);
1826
1827 for (j = 0; j < ci->sub_stripes; j++) {
1828 if (j == orig_ls && devices[i+j] && devices[i+j]->devobj) {
1829 context.stripes[i+j].stripestart = sstart;
1830 context.stripes[i+j].stripeend = send;
1831 stripes[i / ci->sub_stripes] = &context.stripes[i+j];
1832
1833 if (sstart != send) {
1834 context.stripes[i+j].mdl = IoAllocateMdl(context.va, (ULONG)(send - sstart), false, false, NULL);
1835
1836 if (!context.stripes[i+j].mdl) {
1837 ERR("IoAllocateMdl failed\n");
1838 MmUnlockPages(master_mdl);
1839 IoFreeMdl(master_mdl);
1841 goto exit;
1842 }
1843 }
1844
1845 stripeset = true;
1846 } else
1847 context.stripes[i+j].status = ReadDataStatus_Skip;
1848 }
1849
1850 if (!stripeset) {
1851 for (j = 0; j < ci->sub_stripes; j++) {
1852 if (devices[i+j] && devices[i+j]->devobj) {
1853 context.stripes[i+j].stripestart = sstart;
1854 context.stripes[i+j].stripeend = send;
1855 context.stripes[i+j].status = ReadDataStatus_Pending;
1856 stripes[i / ci->sub_stripes] = &context.stripes[i+j];
1857
1858 if (sstart != send) {
1859 context.stripes[i+j].mdl = IoAllocateMdl(context.va, (ULONG)(send - sstart), false, false, NULL);
1860
1861 if (!context.stripes[i+j].mdl) {
1862 ERR("IoAllocateMdl failed\n");
1863 MmUnlockPages(master_mdl);
1864 IoFreeMdl(master_mdl);
1866 goto exit;
1867 }
1868 }
1869
1870 stripeset = true;
1871 break;
1872 }
1873 }
1874
1875 if (!stripeset) {
1876 ERR("could not find stripe to read\n");
1878 goto exit;
1879 }
1880 }
1881 }
1882
1884 if (!stripeoff) {
1885 ERR("out of memory\n");
1886 MmUnlockPages(master_mdl);
1887 IoFreeMdl(master_mdl);
1889 goto exit;
1890 }
1891
1892 RtlZeroMemory(stripeoff, sizeof(uint32_t) * ci->num_stripes / ci->sub_stripes);
1893
1894 pos = 0;
1895 stripe = startoffstripe / ci->sub_stripes;
1896 while (pos < length) {
1897 PFN_NUMBER* stripe_pfns = (PFN_NUMBER*)(stripes[stripe]->mdl + 1);
1898
1899 if (pos == 0) {
1900 uint32_t readlen = (uint32_t)min(stripes[stripe]->stripeend - stripes[stripe]->stripestart,
1901 ci->stripe_length - (stripes[stripe]->stripestart % ci->stripe_length));
1902
1903 RtlCopyMemory(stripe_pfns, pfns, readlen * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
1904
1905 stripeoff[stripe] += readlen;
1906 pos += readlen;
1907 } else if (length - pos < ci->stripe_length) {
1908 RtlCopyMemory(&stripe_pfns[stripeoff[stripe] >> PAGE_SHIFT], &pfns[pos >> PAGE_SHIFT], (length - pos) * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
1909
1910 pos = length;
1911 } else {
1912 RtlCopyMemory(&stripe_pfns[stripeoff[stripe] >> PAGE_SHIFT], &pfns[pos >> PAGE_SHIFT], (ULONG)(ci->stripe_length * sizeof(PFN_NUMBER) >> PAGE_SHIFT));
1913
1914 stripeoff[stripe] += (ULONG)ci->stripe_length;
1915 pos += (ULONG)ci->stripe_length;
1916 }
1917
1918 stripe = (stripe + 1) % (ci->num_stripes / ci->sub_stripes);
1919 }
1920
1921 MmUnlockPages(master_mdl);
1922 IoFreeMdl(master_mdl);
1923
1924 ExFreePool(stripeoff);
1925 ExFreePool(stripes);
1926 } else if (type == BLOCK_FLAG_DUPLICATE) {
1927 uint64_t orig_ls;
1928
1929 if (c)
1930 orig_ls = i = c->last_stripe;
1931 else
1932 orig_ls = i = 0;
1933
1934 while (!devices[i] || !devices[i]->devobj) {
1935 i = (i + 1) % ci->num_stripes;
1936
1937 if (i == orig_ls) {
1938 ERR("no devices available to service request\n");
1940 goto exit;
1941 }
1942 }
1943
1944 if (c)
1945 c->last_stripe = (i + 1) % ci->num_stripes;
1946
1947 context.stripes[i].stripestart = addr - offset;
1948 context.stripes[i].stripeend = context.stripes[i].stripestart + length;
1949
1950 if (file_read) {
1952
1953 if (!context.va) {
1954 ERR("out of memory\n");
1956 goto exit;
1957 }
1958
1959 context.stripes[i].mdl = IoAllocateMdl(context.va, length, false, false, NULL);
1960 if (!context.stripes[i].mdl) {
1961 ERR("IoAllocateMdl failed\n");
1963 goto exit;
1964 }
1965
1966 MmBuildMdlForNonPagedPool(context.stripes[i].mdl);
1967 } else {
1968 context.stripes[i].mdl = IoAllocateMdl(buf, length, false, false, NULL);
1969
1970 if (!context.stripes[i].mdl) {
1971 ERR("IoAllocateMdl failed\n");
1973 goto exit;
1974 }
1975
1977
1978 _SEH2_TRY {
1982 } _SEH2_END;
1983
1984 if (!NT_SUCCESS(Status)) {
1985 ERR("MmProbeAndLockPages threw exception %08lx\n", Status);
1986 goto exit;
1987 }
1988 }
1989 } else if (type == BLOCK_FLAG_RAID5) {
1990 uint64_t startoff, endoff;
1991 uint16_t endoffstripe, parity;
1992 uint32_t *stripeoff, pos;
1993 PMDL master_mdl;
1994 PFN_NUMBER *pfns, dummy = 0;
1995 bool need_dummy = false;
1996
1997 get_raid0_offset(addr - offset, ci->stripe_length, ci->num_stripes - 1, &startoff, &startoffstripe);
1998 get_raid0_offset(addr + length - offset - 1, ci->stripe_length, ci->num_stripes - 1, &endoff, &endoffstripe);
1999
2000 if (file_read) {
2002
2003 if (!context.va) {
2004 ERR("out of memory\n");
2006 goto exit;
2007 }
2008 } else
2009 context.va = buf;
2010
2011 master_mdl = IoAllocateMdl(context.va, length, false, false, NULL);
2012 if (!master_mdl) {
2013 ERR("out of memory\n");
2015 goto exit;
2016 }
2017
2019
2020 _SEH2_TRY {
2024 } _SEH2_END;
2025
2026 if (!NT_SUCCESS(Status)) {
2027 ERR("MmProbeAndLockPages threw exception %08lx\n", Status);
2028 IoFreeMdl(master_mdl);
2029 goto exit;
2030 }
2031
2032 pfns = (PFN_NUMBER*)(master_mdl + 1);
2033
2034 pos = 0;
2035 while (pos < length) {
2036 parity = (((addr - offset + pos) / ((ci->num_stripes - 1) * ci->stripe_length)) + ci->num_stripes - 1) % ci->num_stripes;
2037
2038 if (pos == 0) {
2039 uint16_t stripe = (parity + startoffstripe + 1) % ci->num_stripes;
2040 ULONG skip, readlen;
2041
2042 i = startoffstripe;
2043 while (stripe != parity) {
2044 if (i == startoffstripe) {
2045 readlen = min(length, (ULONG)(ci->stripe_length - (startoff % ci->stripe_length)));
2046
2047 context.stripes[stripe].stripestart = startoff;
2048 context.stripes[stripe].stripeend = startoff + readlen;
2049
2050 pos += readlen;
2051
2052 if (pos == length)
2053 break;
2054 } else {
2055 readlen = min(length - pos, (ULONG)ci->stripe_length);
2056
2057 context.stripes[stripe].stripestart = startoff - (startoff % ci->stripe_length);
2058 context.stripes[stripe].stripeend = context.stripes[stripe].stripestart + readlen;
2059
2060 pos += readlen;
2061
2062 if (pos == length)
2063 break;
2064 }
2065
2066 i++;
2067 stripe = (stripe + 1) % ci->num_stripes;
2068 }
2069
2070 if (pos == length)
2071 break;
2072
2073 for (i = 0; i < startoffstripe; i++) {
2074 uint16_t stripe2 = (parity + i + 1) % ci->num_stripes;
2075
2076 context.stripes[stripe2].stripestart = context.stripes[stripe2].stripeend = startoff - (startoff % ci->stripe_length) + ci->stripe_length;
2077 }
2078
2079 context.stripes[parity].stripestart = context.stripes[parity].stripeend = startoff - (startoff % ci->stripe_length) + ci->stripe_length;
2080
2081 if (length - pos > ci->num_stripes * (ci->num_stripes - 1) * ci->stripe_length) {
2082 skip = (ULONG)(((length - pos) / (ci->num_stripes * (ci->num_stripes - 1) * ci->stripe_length)) - 1);
2083
2084 for (i = 0; i < ci->num_stripes; i++) {
2085 context.stripes[i].stripeend += skip * ci->num_stripes * ci->stripe_length;
2086 }
2087
2088 pos += (uint32_t)(skip * (ci->num_stripes - 1) * ci->num_stripes * ci->stripe_length);
2089 need_dummy = true;
2090 }
2091 } else if (length - pos >= ci->stripe_length * (ci->num_stripes - 1)) {
2092 for (i = 0; i < ci->num_stripes; i++) {
2093 context.stripes[i].stripeend += ci->stripe_length;
2094 }
2095
2096 pos += (uint32_t)(ci->stripe_length * (ci->num_stripes - 1));
2097 need_dummy = true;
2098 } else {
2099 uint16_t stripe = (parity + 1) % ci->num_stripes;
2100
2101 i = 0;
2102 while (stripe != parity) {
2103 if (endoffstripe == i) {
2104 context.stripes[stripe].stripeend = endoff + 1;
2105 break;
2106 } else if (endoffstripe > i)
2107 context.stripes[stripe].stripeend = endoff - (endoff % ci->stripe_length) + ci->stripe_length;
2108
2109 i++;
2110 stripe = (stripe + 1) % ci->num_stripes;
2111 }
2112
2113 break;
2114 }
2115 }
2116
2117 for (i = 0; i < ci->num_stripes; i++) {
2118 if (context.stripes[i].stripestart != context.stripes[i].stripeend) {
2119 context.stripes[i].mdl = IoAllocateMdl(context.va, (ULONG)(context.stripes[i].stripeend - context.stripes[i].stripestart),
2120 false, false, NULL);
2121
2122 if (!context.stripes[i].mdl) {
2123 ERR("IoAllocateMdl failed\n");
2124 MmUnlockPages(master_mdl);
2125 IoFreeMdl(master_mdl);
2127 goto exit;
2128 }
2129 }
2130 }
2131
2132 if (need_dummy) {
2134 if (!dummypage) {
2135 ERR("out of memory\n");
2136 MmUnlockPages(master_mdl);
2137 IoFreeMdl(master_mdl);
2139 goto exit;
2140 }
2141
2142 dummy_mdl = IoAllocateMdl(dummypage, PAGE_SIZE, false, false, NULL);
2143 if (!dummy_mdl) {
2144 ERR("IoAllocateMdl failed\n");
2145 MmUnlockPages(master_mdl);
2146 IoFreeMdl(master_mdl);
2148 goto exit;
2149 }
2150
2151 MmBuildMdlForNonPagedPool(dummy_mdl);
2152
2153 dummy = *(PFN_NUMBER*)(dummy_mdl + 1);
2154 }
2155
2157 if (!stripeoff) {
2158 ERR("out of memory\n");
2159 MmUnlockPages(master_mdl);
2160 IoFreeMdl(master_mdl);
2162 goto exit;
2163 }
2164
2165 RtlZeroMemory(stripeoff, sizeof(uint32_t) * ci->num_stripes);
2166
2167 pos = 0;
2168
2169 while (pos < length) {
2170 PFN_NUMBER* stripe_pfns;
2171
2172 parity = (((addr - offset + pos) / ((ci->num_stripes - 1) * ci->stripe_length)) + ci->num_stripes - 1) % ci->num_stripes;
2173
2174 if (pos == 0) {
2175 uint16_t stripe = (parity + startoffstripe + 1) % ci->num_stripes;
2176 uint32_t readlen = min(length - pos, (uint32_t)min(context.stripes[stripe].stripeend - context.stripes[stripe].stripestart,
2177 ci->stripe_length - (context.stripes[stripe].stripestart % ci->stripe_length)));
2178
2179 stripe_pfns = (PFN_NUMBER*)(context.stripes[stripe].mdl + 1);
2180
2181 RtlCopyMemory(stripe_pfns, pfns, readlen * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
2182
2183 stripeoff[stripe] = readlen;
2184 pos += readlen;
2185
2186 stripe = (stripe + 1) % ci->num_stripes;
2187
2188 while (stripe != parity) {
2189 stripe_pfns = (PFN_NUMBER*)(context.stripes[stripe].mdl + 1);
2190 readlen = min(length - pos, (uint32_t)min(context.stripes[stripe].stripeend - context.stripes[stripe].stripestart, ci->stripe_length));
2191
2192 if (readlen == 0)
2193 break;
2194
2195 RtlCopyMemory(stripe_pfns, &pfns[pos >> PAGE_SHIFT], readlen * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
2196
2197 stripeoff[stripe] = readlen;
2198 pos += readlen;
2199
2200 stripe = (stripe + 1) % ci->num_stripes;
2201 }
2202 } else if (length - pos >= ci->stripe_length * (ci->num_stripes - 1)) {
2203 uint16_t stripe = (parity + 1) % ci->num_stripes;
2204 ULONG k;
2205
2206 while (stripe != parity) {
2207 stripe_pfns = (PFN_NUMBER*)(context.stripes[stripe].mdl + 1);
2208
2209 RtlCopyMemory(&stripe_pfns[stripeoff[stripe] >> PAGE_SHIFT], &pfns[pos >> PAGE_SHIFT], (ULONG)(ci->stripe_length * sizeof(PFN_NUMBER) >> PAGE_SHIFT));
2210
2211 stripeoff[stripe] += (uint32_t)ci->stripe_length;
2212 pos += (uint32_t)ci->stripe_length;
2213
2214 stripe = (stripe + 1) % ci->num_stripes;
2215 }
2216
2217 stripe_pfns = (PFN_NUMBER*)(context.stripes[parity].mdl + 1);
2218
2219 for (k = 0; k < ci->stripe_length >> PAGE_SHIFT; k++) {
2220 stripe_pfns[stripeoff[parity] >> PAGE_SHIFT] = dummy;
2221 stripeoff[parity] += PAGE_SIZE;
2222 }
2223 } else {
2224 uint16_t stripe = (parity + 1) % ci->num_stripes;
2225 uint32_t readlen;
2226
2227 while (pos < length) {
2228 stripe_pfns = (PFN_NUMBER*)(context.stripes[stripe].mdl + 1);
2229 readlen = min(length - pos, (ULONG)min(context.stripes[stripe].stripeend - context.stripes[stripe].stripestart, ci->stripe_length));
2230
2231 if (readlen == 0)
2232 break;
2233
2234 RtlCopyMemory(&stripe_pfns[stripeoff[stripe] >> PAGE_SHIFT], &pfns[pos >> PAGE_SHIFT], readlen * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
2235
2236 stripeoff[stripe] += readlen;
2237 pos += readlen;
2238
2239 stripe = (stripe + 1) % ci->num_stripes;
2240 }
2241 }
2242 }
2243
2244 MmUnlockPages(master_mdl);
2245 IoFreeMdl(master_mdl);
2246
2247 ExFreePool(stripeoff);
2248 } else if (type == BLOCK_FLAG_RAID6) {
2249 uint64_t startoff, endoff;
2250 uint16_t endoffstripe, parity1;
2251 uint32_t *stripeoff, pos;
2252 PMDL master_mdl;
2253 PFN_NUMBER *pfns, dummy = 0;
2254 bool need_dummy = false;
2255
2256 get_raid0_offset(addr - offset, ci->stripe_length, ci->num_stripes - 2, &startoff, &startoffstripe);
2257 get_raid0_offset(addr + length - offset - 1, ci->stripe_length, ci->num_stripes - 2, &endoff, &endoffstripe);
2258
2259 if (file_read) {
2261
2262 if (!context.va) {
2263 ERR("out of memory\n");
2265 goto exit;
2266 }
2267 } else
2268 context.va = buf;
2269
2270 master_mdl = IoAllocateMdl(context.va, length, false, false, NULL);
2271 if (!master_mdl) {
2272 ERR("out of memory\n");
2274 goto exit;
2275 }
2276
2278
2279 _SEH2_TRY {
2283 } _SEH2_END;
2284
2285 if (!NT_SUCCESS(Status)) {
2286 ERR("MmProbeAndLockPages threw exception %08lx\n", Status);
2287 IoFreeMdl(master_mdl);
2288 goto exit;
2289 }
2290
2291 pfns = (PFN_NUMBER*)(master_mdl + 1);
2292
2293 pos = 0;
2294 while (pos < length) {
2295 parity1 = (((addr - offset + pos) / ((ci->num_stripes - 2) * ci->stripe_length)) + ci->num_stripes - 2) % ci->num_stripes;
2296
2297 if (pos == 0) {
2298 uint16_t stripe = (parity1 + startoffstripe + 2) % ci->num_stripes, parity2;
2299 ULONG skip, readlen;
2300
2301 i = startoffstripe;
2302 while (stripe != parity1) {
2303 if (i == startoffstripe) {
2304 readlen = (ULONG)min(length, ci->stripe_length - (startoff % ci->stripe_length));
2305
2306 context.stripes[stripe].stripestart = startoff;
2307 context.stripes[stripe].stripeend = startoff + readlen;
2308
2309 pos += readlen;
2310
2311 if (pos == length)
2312 break;
2313 } else {
2314 readlen = min(length - pos, (ULONG)ci->stripe_length);
2315
2316 context.stripes[stripe].stripestart = startoff - (startoff % ci->stripe_length);
2317 context.stripes[stripe].stripeend = context.stripes[stripe].stripestart + readlen;
2318
2319 pos += readlen;
2320
2321 if (pos == length)
2322 break;
2323 }
2324
2325 i++;
2326 stripe = (stripe + 1) % ci->num_stripes;
2327 }
2328
2329 if (pos == length)
2330 break;
2331
2332 for (i = 0; i < startoffstripe; i++) {
2333 uint16_t stripe2 = (parity1 + i + 2) % ci->num_stripes;
2334
2335 context.stripes[stripe2].stripestart = context.stripes[stripe2].stripeend = startoff - (startoff % ci->stripe_length) + ci->stripe_length;
2336 }
2337
2338 context.stripes[parity1].stripestart = context.stripes[parity1].stripeend = startoff - (startoff % ci->stripe_length) + ci->stripe_length;
2339
2340 parity2 = (parity1 + 1) % ci->num_stripes;
2341 context.stripes[parity2].stripestart = context.stripes[parity2].stripeend = startoff - (startoff % ci->stripe_length) + ci->stripe_length;
2342
2343 if (length - pos > ci->num_stripes * (ci->num_stripes - 2) * ci->stripe_length) {
2344 skip = (ULONG)(((length - pos) / (ci->num_stripes * (ci->num_stripes - 2) * ci->stripe_length)) - 1);
2345
2346 for (i = 0; i < ci->num_stripes; i++) {
2347 context.stripes[i].stripeend += skip * ci->num_stripes * ci->stripe_length;
2348 }
2349
2350 pos += (uint32_t)(skip * (ci->num_stripes - 2) * ci->num_stripes * ci->stripe_length);
2351 need_dummy = true;
2352 }
2353 } else if (length - pos >= ci->stripe_length * (ci->num_stripes - 2)) {
2354 for (i = 0; i < ci->num_stripes; i++) {
2355 context.stripes[i].stripeend += ci->stripe_length;
2356 }
2357
2358 pos += (uint32_t)(ci->stripe_length * (ci->num_stripes - 2));
2359 need_dummy = true;
2360 } else {
2361 uint16_t stripe = (parity1 + 2) % ci->num_stripes;
2362
2363 i = 0;
2364 while (stripe != parity1) {
2365 if (endoffstripe == i) {
2366 context.stripes[stripe].stripeend = endoff + 1;
2367 break;
2368 } else if (endoffstripe > i)
2369 context.stripes[stripe].stripeend = endoff - (endoff % ci->stripe_length) + ci->stripe_length;
2370
2371 i++;
2372 stripe = (stripe + 1) % ci->num_stripes;
2373 }
2374
2375 break;
2376 }
2377 }
2378
2379 for (i = 0; i < ci->num_stripes; i++) {
2380 if (context.stripes[i].stripestart != context.stripes[i].stripeend) {
2381 context.stripes[i].mdl = IoAllocateMdl(context.va, (ULONG)(context.stripes[i].stripeend - context.stripes[i].stripestart), false, false, NULL);
2382
2383 if (!context.stripes[i].mdl) {
2384 ERR("IoAllocateMdl failed\n");
2385 MmUnlockPages(master_mdl);
2386 IoFreeMdl(master_mdl);
2388 goto exit;
2389 }
2390 }
2391 }
2392
2393 if (need_dummy) {
2395 if (!dummypage) {
2396 ERR("out of memory\n");
2397 MmUnlockPages(master_mdl);
2398 IoFreeMdl(master_mdl);
2400 goto exit;
2401 }
2402
2403 dummy_mdl = IoAllocateMdl(dummypage, PAGE_SIZE, false, false, NULL);
2404 if (!dummy_mdl) {
2405 ERR("IoAllocateMdl failed\n");
2406 MmUnlockPages(master_mdl);
2407 IoFreeMdl(master_mdl);
2409 goto exit;
2410 }
2411
2412 MmBuildMdlForNonPagedPool(dummy_mdl);
2413
2414 dummy = *(PFN_NUMBER*)(dummy_mdl + 1);
2415 }
2416
2418 if (!stripeoff) {
2419 ERR("out of memory\n");
2420 MmUnlockPages(master_mdl);
2421 IoFreeMdl(master_mdl);
2423 goto exit;
2424 }
2425
2426 RtlZeroMemory(stripeoff, sizeof(uint32_t) * ci->num_stripes);
2427
2428 pos = 0;
2429
2430 while (pos < length) {
2431 PFN_NUMBER* stripe_pfns;
2432
2433 parity1 = (((addr - offset + pos) / ((ci->num_stripes - 2) * ci->stripe_length)) + ci->num_stripes - 2) % ci->num_stripes;
2434
2435 if (pos == 0) {
2436 uint16_t stripe = (parity1 + startoffstripe + 2) % ci->num_stripes;
2437 uint32_t readlen = min(length - pos, (uint32_t)min(context.stripes[stripe].stripeend - context.stripes[stripe].stripestart,
2438 ci->stripe_length - (context.stripes[stripe].stripestart % ci->stripe_length)));
2439
2440 stripe_pfns = (PFN_NUMBER*)(context.stripes[stripe].mdl + 1);
2441
2442 RtlCopyMemory(stripe_pfns, pfns, readlen * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
2443
2444 stripeoff[stripe] = readlen;
2445 pos += readlen;
2446
2447 stripe = (stripe + 1) % ci->num_stripes;
2448
2449 while (stripe != parity1) {
2450 stripe_pfns = (PFN_NUMBER*)(context.stripes[stripe].mdl + 1);
2451 readlen = (uint32_t)min(length - pos, min(context.stripes[stripe].stripeend - context.stripes[stripe].stripestart, ci->stripe_length));
2452
2453 if (readlen == 0)
2454 break;
2455
2456 RtlCopyMemory(stripe_pfns, &pfns[pos >> PAGE_SHIFT], readlen * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
2457
2458 stripeoff[stripe] = readlen;
2459 pos += readlen;
2460
2461 stripe = (stripe + 1) % ci->num_stripes;
2462 }
2463 } else if (length - pos >= ci->stripe_length * (ci->num_stripes - 2)) {
2464 uint16_t stripe = (parity1 + 2) % ci->num_stripes;
2465 uint16_t parity2 = (parity1 + 1) % ci->num_stripes;
2466 ULONG k;
2467
2468 while (stripe != parity1) {
2469 stripe_pfns = (PFN_NUMBER*)(context.stripes[stripe].mdl + 1);
2470
2471 RtlCopyMemory(&stripe_pfns[stripeoff[stripe] >> PAGE_SHIFT], &pfns[pos >> PAGE_SHIFT], (ULONG)(ci->stripe_length * sizeof(PFN_NUMBER) >> PAGE_SHIFT));
2472
2473 stripeoff[stripe] += (uint32_t)ci->stripe_length;
2474 pos += (uint32_t)ci->stripe_length;
2475
2476 stripe = (stripe + 1) % ci->num_stripes;
2477 }
2478
2479 stripe_pfns = (PFN_NUMBER*)(context.stripes[parity1].mdl + 1);
2480
2481 for (k = 0; k < ci->stripe_length >> PAGE_SHIFT; k++) {
2482 stripe_pfns[stripeoff[parity1] >> PAGE_SHIFT] = dummy;
2483 stripeoff[parity1] += PAGE_SIZE;
2484 }
2485
2486 stripe_pfns = (PFN_NUMBER*)(context.stripes[parity2].mdl + 1);
2487
2488 for (k = 0; k < ci->stripe_length >> PAGE_SHIFT; k++) {
2489 stripe_pfns[stripeoff[parity2] >> PAGE_SHIFT] = dummy;
2490 stripeoff[parity2] += PAGE_SIZE;
2491 }
2492 } else {
2493 uint16_t stripe = (parity1 + 2) % ci->num_stripes;
2494 uint32_t readlen;
2495
2496 while (pos < length) {
2497 stripe_pfns = (PFN_NUMBER*)(context.stripes[stripe].mdl + 1);
2498 readlen = (uint32_t)min(length - pos, min(context.stripes[stripe].stripeend - context.stripes[stripe].stripestart, ci->stripe_length));
2499
2500 if (readlen == 0)
2501 break;
2502
2503 RtlCopyMemory(&stripe_pfns[stripeoff[stripe] >> PAGE_SHIFT], &pfns[pos >> PAGE_SHIFT], readlen * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
2504
2505 stripeoff[stripe] += readlen;
2506 pos += readlen;
2507
2508 stripe = (stripe + 1) % ci->num_stripes;
2509 }
2510 }
2511 }
2512
2513 MmUnlockPages(master_mdl);
2514 IoFreeMdl(master_mdl);
2515
2516 ExFreePool(stripeoff);
2517 }
2518
2519 context.address = addr;
2520
2521 for (i = 0; i < ci->num_stripes; i++) {
2522 if (!devices[i] || !devices[i]->devobj || context.stripes[i].stripestart == context.stripes[i].stripeend) {
2523 context.stripes[i].status = ReadDataStatus_MissingDevice;
2524 context.stripes_left--;
2525
2526 if (!devices[i] || !devices[i]->devobj)
2527 missing_devices++;
2528 }
2529 }
2530
2531 if (missing_devices > allowed_missing) {
2532 ERR("not enough devices to service request (%u missing)\n", missing_devices);
2534 goto exit;
2535 }
2536
2537 for (i = 0; i < ci->num_stripes; i++) {
2539
2540 if (devices[i] && devices[i]->devobj && context.stripes[i].stripestart != context.stripes[i].stripeend && context.stripes[i].status != ReadDataStatus_Skip) {
2541 context.stripes[i].context = (struct read_data_context*)&context;
2542
2543 if (type == BLOCK_FLAG_RAID10) {
2544 context.stripes[i].stripenum = i / ci->sub_stripes;
2545 }
2546
2547 if (!Irp) {
2548 context.stripes[i].Irp = IoAllocateIrp(devices[i]->devobj->StackSize, false);
2549
2550 if (!context.stripes[i].Irp) {
2551 ERR("IoAllocateIrp failed\n");
2553 goto exit;
2554 }
2555 } else {
2556 context.stripes[i].Irp = IoMakeAssociatedIrp(Irp, devices[i]->devobj->StackSize);
2557
2558 if (!context.stripes[i].Irp) {
2559 ERR("IoMakeAssociatedIrp failed\n");
2561 goto exit;
2562 }
2563 }
2564
2565 IrpSp = IoGetNextIrpStackLocation(context.stripes[i].Irp);
2568 IrpSp->FileObject = devices[i]->fileobj;
2569
2570 if (devices[i]->devobj->Flags & DO_BUFFERED_IO) {
2571 context.stripes[i].Irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag(NonPagedPool, (ULONG)(context.stripes[i].stripeend - context.stripes[i].stripestart), ALLOC_TAG);
2572 if (!context.stripes[i].Irp->AssociatedIrp.SystemBuffer) {
2573 ERR("out of memory\n");
2575 goto exit;
2576 }
2577
2579
2580 context.stripes[i].Irp->UserBuffer = MmGetSystemAddressForMdlSafe(context.stripes[i].mdl, priority);
2581 } else if (devices[i]->devobj->Flags & DO_DIRECT_IO)
2582 context.stripes[i].Irp->MdlAddress = context.stripes[i].mdl;
2583 else
2584 context.stripes[i].Irp->UserBuffer = MmGetSystemAddressForMdlSafe(context.stripes[i].mdl, priority);
2585
2586 IrpSp->Parameters.Read.Length = (ULONG)(context.stripes[i].stripeend - context.stripes[i].stripestart);
2587 IrpSp->Parameters.Read.ByteOffset.QuadPart = context.stripes[i].stripestart + cis[i].offset;
2588
2589 total_reading += IrpSp->Parameters.Read.Length;
2590
2591 context.stripes[i].Irp->UserIosb = &context.stripes[i].iosb;
2592
2593 IoSetCompletionRoutine(context.stripes[i].Irp, read_data_completion, &context.stripes[i], true, true, true);
2594
2595 context.stripes[i].status = ReadDataStatus_Pending;
2596 }
2597 }
2598
2599 need_to_wait = false;
2600 for (i = 0; i < ci->num_stripes; i++) {
2601 if (context.stripes[i].status != ReadDataStatus_MissingDevice && context.stripes[i].status != ReadDataStatus_Skip) {
2602 IoCallDriver(devices[i]->devobj, context.stripes[i].Irp);
2603 need_to_wait = true;
2604 }
2605 }
2606
2607 if (need_to_wait)
2609
2610 if (diskacc)
2611 fFsRtlUpdateDiskCounters(total_reading, 0);
2612
2613 // check if any of the devices return a "user-induced" error
2614
2615 for (i = 0; i < ci->num_stripes; i++) {
2616 if (context.stripes[i].status == ReadDataStatus_Error && IoIsErrorUserInduced(context.stripes[i].iosb.Status)) {
2617 Status = context.stripes[i].iosb.Status;
2618 goto exit;
2619 }
2620 }
2621
2622 if (type == BLOCK_FLAG_RAID0) {
2624 if (!NT_SUCCESS(Status)) {
2625 ERR("read_data_raid0 returned %08lx\n", Status);
2626
2627 if (file_read)
2628 ExFreePool(context.va);
2629
2630 goto exit;
2631 }
2632
2633 if (file_read) {
2635 ExFreePool(context.va);
2636 }
2637 } else if (type == BLOCK_FLAG_RAID10) {
2639
2640 if (!NT_SUCCESS(Status)) {
2641 ERR("read_data_raid10 returned %08lx\n", Status);
2642
2643 if (file_read)
2644 ExFreePool(context.va);
2645
2646 goto exit;
2647 }
2648
2649 if (file_read) {
2651 ExFreePool(context.va);
2652 }
2653 } else if (type == BLOCK_FLAG_DUPLICATE) {
2654 Status = read_data_dup(Vcb, file_read ? context.va : buf, addr, &context, ci, devices, generation);
2655 if (!NT_SUCCESS(Status)) {
2656 ERR("read_data_dup returned %08lx\n", Status);
2657
2658 if (file_read)
2659 ExFreePool(context.va);
2660
2661 goto exit;
2662 }
2663
2664 if (file_read) {
2666 ExFreePool(context.va);
2667 }
2668 } else if (type == BLOCK_FLAG_RAID5) {
2669 Status = read_data_raid5(Vcb, file_read ? context.va : buf, addr, length, &context, ci, devices, offset, generation, c, missing_devices > 0 ? true : false);
2670 if (!NT_SUCCESS(Status)) {
2671 ERR("read_data_raid5 returned %08lx\n", Status);
2672
2673 if (file_read)
2674 ExFreePool(context.va);
2675
2676 goto exit;
2677 }
2678
2679 if (file_read) {
2681 ExFreePool(context.va);
2682 }
2683 } else if (type == BLOCK_FLAG_RAID6) {
2684 Status = read_data_raid6(Vcb, file_read ? context.va : buf, addr, length, &context, ci, devices, offset, generation, c, missing_devices > 0 ? true : false);
2685 if (!NT_SUCCESS(Status)) {
2686 ERR("read_data_raid6 returned %08lx\n", Status);
2687
2688 if (file_read)
2689 ExFreePool(context.va);
2690
2691 goto exit;
2692 }
2693
2694 if (file_read) {
2696 ExFreePool(context.va);
2697 }
2698 }
2699
2700exit:
2701 if (c && (type == BLOCK_FLAG_RAID5 || type == BLOCK_FLAG_RAID6))
2702 chunk_unlock_range(Vcb, c, lockaddr, locklen);
2703
2704 if (dummy_mdl)
2705 IoFreeMdl(dummy_mdl);
2706
2707 if (dummypage)
2708 ExFreePool(dummypage);
2709
2710 for (i = 0; i < ci->num_stripes; i++) {
2711 if (context.stripes[i].mdl) {
2712 if (context.stripes[i].mdl->MdlFlags & MDL_PAGES_LOCKED)
2713 MmUnlockPages(context.stripes[i].mdl);
2714
2715 IoFreeMdl(context.stripes[i].mdl);
2716 }
2717
2718 if (context.stripes[i].Irp)
2719 IoFreeIrp(context.stripes[i].Irp);
2720 }
2721
2722 ExFreePool(context.stripes);
2723
2724 if (!Vcb->log_to_phys_loaded)
2726
2727 return Status;
2728}
#define skip(...)
Definition: atltest.h:64
NTSTATUS bool void get_raid56_lock_range(chunk *c, uint64_t address, uint64_t length, uint64_t *lockaddr, uint64_t *locklen) __attribute__((nonnull(1
INT WSAAPI send(IN SOCKET s, IN CONST CHAR FAR *buf, IN INT len, IN INT flags)
Definition: send.c:23
void chunk_lock_range(_In_ device_extension *Vcb, _In_ chunk *c, _In_ uint64_t start, _In_ uint64_t length)
Definition: btrfs.c:5844
void chunk_unlock_range(_In_ device_extension *Vcb, _In_ chunk *c, _In_ uint64_t start, _In_ uint64_t length)
Definition: btrfs.c:5891
_Ret_maybenull_ device * find_device_from_uuid(_In_ device_extension *Vcb, _In_ BTRFS_UUID *uuid)
Definition: btrfs.c:3299
#define BLOCK_FLAG_RAID1C4
Definition: btrfs.h:88
#define TYPE_CHUNK_ITEM
Definition: btrfs.h:48
#define BLOCK_FLAG_RAID1C3
Definition: btrfs.h:87
static struct all_devices * devices
Definition: dsm_ctrl.c:48
#define DO_BUFFERED_IO
Definition: env_spec_w32.h:394
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define DO_DIRECT_IO
Definition: env_spec_w32.h:396
@ ReadDataStatus_MissingDevice
Definition: read.c:26
@ ReadDataStatus_Error
Definition: read.c:25
@ ReadDataStatus_Skip
Definition: read.c:27
@ ReadDataStatus_Pending
Definition: read.c:23
static NTSTATUS read_data_raid6(device_extension *Vcb, uint8_t *buf, uint64_t addr, uint32_t length, read_data_context *context, CHUNK_ITEM *ci, device **devices, uint64_t offset, uint64_t generation, chunk *c, bool degraded)
Definition: read.c:996
tFsRtlUpdateDiskCounters fFsRtlUpdateDiskCounters
Definition: btrfs.c:94
static NTSTATUS read_data_raid0(device_extension *Vcb, uint8_t *buf, uint64_t addr, uint32_t length, read_data_context *context, CHUNK_ITEM *ci, device **devices, uint64_t generation, uint64_t offset)
Definition: read.c:397
static NTSTATUS read_data_raid5(device_extension *Vcb, uint8_t *buf, uint64_t addr, uint32_t length, read_data_context *context, CHUNK_ITEM *ci, device **devices, uint64_t offset, uint64_t generation, chunk *c, bool degraded)
Definition: read.c:651
static NTSTATUS read_data_dup(device_extension *Vcb, uint8_t *buf, uint64_t addr, read_data_context *context, CHUNK_ITEM *ci, device **devices, uint64_t generation)
Definition: read.c:236
static NTSTATUS read_data_raid10(device_extension *Vcb, uint8_t *buf, uint64_t addr, uint32_t length, read_data_context *context, CHUNK_ITEM *ci, device **devices, uint64_t generation, uint64_t offset)
Definition: read.c:467
MDL * mdl
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:490
VOID NTAPI MmUnlockPages(IN PMDL Mdl)
Definition: mdlsup.c:1435
VOID NTAPI MmBuildMdlForNonPagedPool(IN PMDL Mdl)
Definition: mdlsup.c:424
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
Definition: irp.c:615
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
PIRP NTAPI IoMakeAssociatedIrp(IN PIRP Irp, IN CCHAR StackSize)
Definition: irp.c:1925
#define STATUS_UNEXPECTED_IO_ERROR
Definition: ntstatus.h:469
ULONG PFN_NUMBER
Definition: ke.h:9
#define exit(n)
Definition: config.h:202
#define BLOCK_FLAG_DUPLICATE
Definition: shellext.h:80
#define BLOCK_FLAG_RAID1
Definition: shellext.h:79
void * data
Definition: btrfs_drv.h:622
#define IoIsErrorUserInduced(Status)
Definition: iofuncs.h:2817
#define IRP_DEALLOCATE_BUFFER
#define IRP_INPUT_OPERATION
#define IRP_BUFFERED_IO
#define IRP_MN_NORMAL
Definition: iotypes.h:4417
#define MDL_PAGES_LOCKED
Definition: mmtypes.h:19

◆ read_file()

◆ read_registry()

void read_registry ( PUNICODE_STRING  regpath,
bool  refresh 
)

Definition at line 777 of file registry.c.

777 {
780 HANDLE h;
782#ifdef _DEBUG
784 ULONG kvfilen, old_debug_log_level = debug_log_level;
785 UNICODE_STRING us, old_log_file, old_log_device;
786
787 static const WCHAR def_log_file[] = L"\\??\\C:\\btrfs.log";
788#endif
789
791
792 read_mappings(regpath);
793 read_group_mappings(regpath);
794
796
798
800
801 if (!NT_SUCCESS(Status)) {
802 ERR("ZwCreateKey returned %08lx\n", Status);
803 return;
804 }
805
806 if (!refresh)
807 reset_subkeys(h, regpath);
808
824
825 if (!refresh)
826 get_registry_value(h, L"NoPNP", REG_DWORD, &no_pnp, sizeof(no_pnp));
827
828 if (mount_flush_interval == 0)
830
831#ifdef _DEBUG
832 get_registry_value(h, L"DebugLogLevel", REG_DWORD, &debug_log_level, sizeof(debug_log_level));
833
834 RtlInitUnicodeString(&us, L"LogDevice");
835
836 kvfi = NULL;
837 kvfilen = 0;
838 Status = ZwQueryValueKey(h, &us, KeyValueFullInformation, kvfi, kvfilen, &kvfilen);
839
840 old_log_device = log_device;
841
844
845 if ((Status == STATUS_BUFFER_TOO_SMALL || Status == STATUS_BUFFER_OVERFLOW) && kvfilen > 0) {
846 kvfi = ExAllocatePoolWithTag(PagedPool, kvfilen, ALLOC_TAG);
847
848 if (!kvfi) {
849 ERR("out of memory\n");
850 ZwClose(h);
851 return;
852 }
853
854 Status = ZwQueryValueKey(h, &us, KeyValueFullInformation, kvfi, kvfilen, &kvfilen);
855
856 if (NT_SUCCESS(Status)) {
857 if ((kvfi->Type == REG_SZ || kvfi->Type == REG_EXPAND_SZ) && kvfi->DataLength >= sizeof(WCHAR)) {
860
861 if (!log_device.Buffer) {
862 ERR("out of memory\n");
863 ExFreePool(kvfi);
864 ZwClose(h);
865 return;
866 }
867
868 RtlCopyMemory(log_device.Buffer, ((uint8_t*)kvfi) + kvfi->DataOffset, log_device.Length);
869
870 if (log_device.Buffer[(log_device.Length / sizeof(WCHAR)) - 1] == 0)
871 log_device.Length -= sizeof(WCHAR);
872 } else {
873 ERR("LogDevice was type %lu, length %lu\n", kvfi->Type, kvfi->DataLength);
874
876 if (!NT_SUCCESS(Status)) {
877 ERR("ZwDeleteValueKey returned %08lx\n", Status);
878 }
879 }
880 }
881
882 ExFreePool(kvfi);
883 } else if (Status != STATUS_OBJECT_NAME_NOT_FOUND) {
884 ERR("ZwQueryValueKey returned %08lx\n", Status);
885 }
886
887 ExAcquireResourceExclusiveLite(&log_lock, true);
888
889 if (refresh && (log_device.Length != old_log_device.Length || RtlCompareMemory(log_device.Buffer, old_log_device.Buffer, log_device.Length) != log_device.Length ||
890 (!comfo && log_device.Length > 0) || (old_debug_log_level == 0 && debug_log_level > 0) || (old_debug_log_level > 0 && debug_log_level == 0))) {
891 if (comfo)
892 ObDereferenceObject(comfo);
893
894 if (log_handle) {
895 ZwClose(log_handle);
896 log_handle = NULL;
897 }
898
899 comfo = NULL;
900 comdo = NULL;
901
902 if (log_device.Length > 0 && debug_log_level > 0) {
904 if (!NT_SUCCESS(Status))
905 DbgPrint("IoGetDeviceObjectPointer returned %08lx\n", Status);
906 }
907 }
908
909 ExReleaseResourceLite(&log_lock);
910
911 if (old_log_device.Buffer)
912 ExFreePool(old_log_device.Buffer);
913
914 RtlInitUnicodeString(&us, L"LogFile");
915
916 kvfi = NULL;
917 kvfilen = 0;
918 Status = ZwQueryValueKey(h, &us, KeyValueFullInformation, kvfi, kvfilen, &kvfilen);
919
920 old_log_file = log_file;
921
922 if ((Status == STATUS_BUFFER_TOO_SMALL || Status == STATUS_BUFFER_OVERFLOW) && kvfilen > 0) {
923 kvfi = ExAllocatePoolWithTag(PagedPool, kvfilen, ALLOC_TAG);
924
925 if (!kvfi) {
926 ERR("out of memory\n");
927 ZwClose(h);
928 return;
929 }
930
931 Status = ZwQueryValueKey(h, &us, KeyValueFullInformation, kvfi, kvfilen, &kvfilen);
932
933 if (NT_SUCCESS(Status)) {
934 if ((kvfi->Type == REG_SZ || kvfi->Type == REG_EXPAND_SZ) && kvfi->DataLength >= sizeof(WCHAR)) {
937
938 if (!log_file.Buffer) {
939 ERR("out of memory\n");
940 ExFreePool(kvfi);
941 ZwClose(h);
942 return;
943 }
944
945 RtlCopyMemory(log_file.Buffer, ((uint8_t*)kvfi) + kvfi->DataOffset, log_file.Length);
946
947 if (log_file.Buffer[(log_file.Length / sizeof(WCHAR)) - 1] == 0)
948 log_file.Length -= sizeof(WCHAR);
949 } else {
950 ERR("LogFile was type %lu, length %lu\n", kvfi->Type, kvfi->DataLength);
951
953 if (!NT_SUCCESS(Status))
954 ERR("ZwDeleteValueKey returned %08lx\n", Status);
955
956 log_file.Length = 0;
957 }
958 } else {
959 ERR("ZwQueryValueKey returned %08lx\n", Status);
960 log_file.Length = 0;
961 }
962
963 ExFreePool(kvfi);
964 } else if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
965 Status = ZwSetValueKey(h, &us, 0, REG_SZ, (void*)def_log_file, sizeof(def_log_file));
966
967 if (!NT_SUCCESS(Status))
968 ERR("ZwSetValueKey returned %08lx\n", Status);
969
970 log_file.Length = 0;
971 } else {
972 ERR("ZwQueryValueKey returned %08lx\n", Status);
973 log_file.Length = 0;
974 }
975
976 if (log_file.Length == 0) {
977 log_file.Length = log_file.MaximumLength = sizeof(def_log_file) - sizeof(WCHAR);
979
980 if (!log_file.Buffer) {
981 ERR("out of memory\n");
982 ZwClose(h);
983 return;
984 }
985
987 }
988
989 ExAcquireResourceExclusiveLite(&log_lock, true);
990
991 if (refresh && (log_file.Length != old_log_file.Length || RtlCompareMemory(log_file.Buffer, old_log_file.Buffer, log_file.Length) != log_file.Length ||
992 (!log_handle && log_file.Length > 0) || (old_debug_log_level == 0 && debug_log_level > 0) || (old_debug_log_level > 0 && debug_log_level == 0))) {
993 if (log_handle) {
994 ZwClose(log_handle);
995 log_handle = NULL;
996 }
997
998 if (!comfo && log_file.Length > 0 && refresh && debug_log_level > 0) {
1000
1002
1003 Status = ZwCreateFile(&log_handle, FILE_WRITE_DATA, &oa, &iosb, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
1005 if (!NT_SUCCESS(Status)) {
1006 DbgPrint("ZwCreateFile returned %08lx\n", Status);
1007 log_handle = NULL;
1008 }
1009 }
1010 }
1011
1012 ExReleaseResourceLite(&log_lock);
1013
1014 if (old_log_file.Buffer)
1015 ExFreePool(old_log_file.Buffer);
1016#endif
1017
1018 ZwClose(h);
1019}
#define FILE_NON_DIRECTORY_FILE
Definition: constants.h:492
#define FILE_SHARE_READ
Definition: compat.h:136
uint32_t mount_readonly
Definition: btrfs.c:84
uint32_t mount_max_inline
Definition: btrfs.c:78
uint32_t mount_no_trim
Definition: btrfs.c:81
uint32_t mount_compress
Definition: btrfs.c:72
uint32_t mount_allow_degraded
Definition: btrfs.c:83
uint32_t mount_skip_balance
Definition: btrfs.c:79
uint32_t mount_zlib_level
Definition: btrfs.c:75
uint32_t mount_zstd_level
Definition: btrfs.c:76
uint32_t mount_nodatacow
Definition: btrfs.c:86
uint32_t mount_compress_type
Definition: btrfs.c:74
uint32_t mount_no_root_dir
Definition: btrfs.c:85
uint32_t mount_flush_interval
Definition: btrfs.c:77
uint32_t mount_no_barrier
Definition: btrfs.c:80
uint32_t mount_compress_force
Definition: btrfs.c:73
uint32_t mount_clear_cache
Definition: btrfs.c:82
uint32_t debug_log_level
Definition: btrfs.c:71
UNICODE_STRING log_file
Definition: registry.c:21
static void get_registry_value(HANDLE h, WCHAR *string, ULONG type, void *val, ULONG size)
Definition: registry.c:726
static void read_mappings(PUNICODE_STRING regpath)
Definition: registry.c:544
UNICODE_STRING log_device
Definition: btrfs.c:89
static void reset_subkeys(HANDLE h, PUNICODE_STRING reg_path)
Definition: registry.c:454
ERESOURCE mapping_lock
Definition: btrfs.c:103
static void read_group_mappings(PUNICODE_STRING regpath)
Definition: registry.c:622
#define FILE_WRITE_THROUGH
Definition: from_kernel.h:26
#define FILE_OPEN_IF
Definition: from_kernel.h:56
#define FILE_SYNCHRONOUS_IO_ALERT
Definition: from_kernel.h:30
NTSYSAPI NTSTATUS NTAPI ZwDeleteValueKey(__in IN HANDLE Key, __in IN PUNICODE_STRING ValueName)
#define DbgPrint
Definition: hal.h:12
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define REG_SZ
Definition: layer.c:22
static ACCESS_MASK const OBJECT_ATTRIBUTES ULONG const UNICODE_STRING ULONG PULONG dispos
Definition: reg.c:132
#define FILE_WRITE_DATA
Definition: nt_native.h:631
@ KeyValueFullInformation
Definition: nt_native.h:1181
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
#define KEY_ENUMERATE_SUB_KEYS
Definition: nt_native.h:1019
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
#define L(x)
Definition: ntvdm.h:50
#define REG_DWORD
Definition: sdbapi.c:596

Referenced by _Function_class_().

◆ read_send_buffer()

NTSTATUS read_send_buffer ( device_extension Vcb,
PFILE_OBJECT  FileObject,
void data,
ULONG  datalen,
ULONG_PTR retlen,
KPROCESSOR_MODE  processor_mode 
)

Definition at line 3839 of file send.c.

3839 {
3840 ccb* ccb;
3842
3843 ccb = FileObject ? FileObject->FsContext2 : NULL;
3844 if (!ccb)
3846
3847 if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), processor_mode))
3849
3850 ExAcquireResourceExclusiveLite(&Vcb->send_load_lock, true);
3851
3852 if (!ccb->send) {
3853 ExReleaseResourceLite(&Vcb->send_load_lock);
3855 }
3856
3858
3859 KeWaitForSingleObject(&context->buffer_event, Executive, KernelMode, false, NULL);
3860
3861 if (datalen == 0) {
3862 ExReleaseResourceLite(&Vcb->send_load_lock);
3863 return STATUS_SUCCESS;
3864 }
3865
3866 RtlCopyMemory(data, context->data, min(datalen, context->datalen));
3867
3868 if (datalen < context->datalen) { // not empty yet
3869 *retlen = datalen;
3870 RtlMoveMemory(context->data, &context->data[datalen], context->datalen - datalen);
3871 context->datalen -= datalen;
3872 ExReleaseResourceLite(&Vcb->send_load_lock);
3873 } else {
3874 *retlen = context->datalen;
3875 context->datalen = 0;
3876 ExReleaseResourceLite(&Vcb->send_load_lock);
3877
3878 KeClearEvent(&context->buffer_event);
3879 KeSetEvent(&ccb->send->cleared_event, 0, false);
3880 }
3881
3882 return STATUS_SUCCESS;
3883}
NTSTATUS send_status
Definition: btrfs_drv.h:393
send_info * send
Definition: btrfs_drv.h:392
KEVENT cleared_event
Definition: btrfs_drv.h:365
void * context
Definition: btrfs_drv.h:364

Referenced by fsctl_request().

◆ read_stream()

NTSTATUS NTSTATUS read_stream ( fcb fcb,
uint8_t data,
uint64_t  start,
ULONG  length,
ULONG pbr 
)

◆ reap_fcb()

void reap_fcb ( fcb fcb)

Definition at line 1743 of file btrfs.c.

1743 {
1744 uint8_t c = fcb->hash >> 24;
1745
1746 if (fcb->subvol && fcb->subvol->fcbs_ptrs[c] == &fcb->list_entry) {
1747 if (fcb->list_entry.Flink != &fcb->subvol->fcbs && (CONTAINING_RECORD(fcb->list_entry.Flink, struct _fcb, list_entry)->hash >> 24) == c)
1748 fcb->subvol->fcbs_ptrs[c] = fcb->list_entry.Flink;
1749 else
1750 fcb->subvol->fcbs_ptrs[c] = NULL;
1751 }
1752
1753 if (fcb->list_entry.Flink) {
1755
1756 if (fcb->subvol && fcb->subvol->dropped && IsListEmpty(&fcb->subvol->fcbs)) {
1757 ExDeleteResourceLite(&fcb->subvol->nonpaged->load_tree_lock);
1758 ExFreePool(fcb->subvol->nonpaged);
1760 }
1761 }
1762
1765
1766 ExDeleteResourceLite(&fcb->nonpaged->resource);
1767 ExDeleteResourceLite(&fcb->nonpaged->paging_resource);
1768 ExDeleteResourceLite(&fcb->nonpaged->dir_children_lock);
1769
1770 ExFreeToNPagedLookasideList(&fcb->Vcb->fcb_np_lookaside, fcb->nonpaged);
1771
1772 if (fcb->sd)
1773 ExFreePool(fcb->sd);
1774
1775 if (fcb->adsxattr.Buffer)
1777
1780
1781 if (fcb->ea_xattr.Buffer)
1783
1784 if (fcb->adsdata.Buffer)
1786
1787 while (!IsListEmpty(&fcb->extents)) {
1790
1791 if (ext->csum)
1792 ExFreePool(ext->csum);
1793
1794 ExFreePool(ext);
1795 }
1796
1797 while (!IsListEmpty(&fcb->hardlinks)) {
1800
1801 if (hl->name.Buffer)
1802 ExFreePool(hl->name.Buffer);
1803
1804 if (hl->utf8.Buffer)
1805 ExFreePool(hl->utf8.Buffer);
1806
1807 ExFreePool(hl);
1808 }
1809
1810 while (!IsListEmpty(&fcb->xattrs)) {
1812
1813 ExFreePool(xa);
1814 }
1815
1816 while (!IsListEmpty(&fcb->dir_children_index)) {
1818 dir_child* dc = CONTAINING_RECORD(le, dir_child, list_entry_index);
1819
1820 ExFreePool(dc->utf8.Buffer);
1821 ExFreePool(dc->name.Buffer);
1822 ExFreePool(dc->name_uc.Buffer);
1823 ExFreePool(dc);
1824 }
1825
1826 if (fcb->hash_ptrs)
1828
1829 if (fcb->hash_ptrs_uc)
1831
1834
1835 if (fcb->pool_type == NonPagedPool)
1836 ExFreePool(fcb);
1837 else
1838 ExFreeToPagedLookasideList(&fcb->Vcb->fcb_lookaside, fcb);
1839}
VOID NTAPI FsRtlUninitializeFileLock(IN PFILE_LOCK FileLock)
Definition: filelock.c:1279
VOID NTAPI FsRtlUninitializeOplock(IN POPLOCK Oplock)
Definition: oplock.c:1600

Referenced by allocate_cache_chunk(), clear_free_space_cache(), create_directory_fcb(), create_stream(), create_subvol(), drop_chunk(), mknod(), mount_vol(), open_fcb(), open_fcb_stream(), open_fileref_child(), reap_fcbs(), rename_file_to_stream(), rename_stream_to_file(), uninit(), and update_chunk_usage().

◆ reap_fcbs()

void reap_fcbs ( device_extension Vcb)

Definition at line 1841 of file btrfs.c.

1841 {
1842 LIST_ENTRY* le;
1843
1844 le = Vcb->all_fcbs.Flink;
1845 while (le != &Vcb->all_fcbs) {
1846 fcb* fcb = CONTAINING_RECORD(le, struct _fcb, list_entry_all);
1847 LIST_ENTRY* le2 = le->Flink;
1848
1849 if (fcb->refcount == 0)
1850 reap_fcb(fcb);
1851
1852 le = le2;
1853 }
1854}

◆ reap_fileref()

void reap_fileref ( device_extension Vcb,
file_ref fr 
)

Definition at line 1875 of file btrfs.c.

1875 {
1876 // FIXME - do we need a file_ref lock?
1877
1878 // FIXME - do delete if needed
1879
1880 // FIXME - throw error if children not empty
1881
1882 if (fr->fcb->fileref == fr)
1883 fr->fcb->fileref = NULL;
1884
1885 if (fr->dc) {
1886 if (fr->fcb->ads)
1887 fr->dc->size = fr->fcb->adsdata.Length;
1888
1889 fr->dc->fileref = NULL;
1890 }
1891
1892 if (fr->list_entry.Flink)
1894
1895 if (fr->parent)
1896 free_fileref(fr->parent);
1897
1898 free_fcb(fr->fcb);
1899
1900 if (fr->oldutf8.Buffer)
1902
1903 ExFreeToPagedLookasideList(&Vcb->fileref_lookaside, fr);
1904}
ANSI_STRING oldutf8
Definition: btrfs_drv.h:343
ULONG size
Definition: btrfs_drv.h:259
struct _file_ref * fileref
Definition: btrfs_drv.h:260

Referenced by create_stream(), file_create2(), open_fileref_child(), reap_filerefs(), and rename_file_to_stream().

◆ reap_filerefs()

void reap_filerefs ( device_extension Vcb,
file_ref fr 
)

Definition at line 1906 of file btrfs.c.

1906 {
1907 LIST_ENTRY* le;
1908
1909 // FIXME - recursion is a bad idea in kernel mode
1910
1911 le = fr->children.Flink;
1912 while (le != &fr->children) {
1914 LIST_ENTRY* le2 = le->Flink;
1915
1917
1918 le = le2;
1919 }
1920
1921 if (fr->refcount == 0)
1922 reap_fileref(Vcb, fr);
1923}
void reap_filerefs(device_extension *Vcb, file_ref *fr)
Definition: btrfs.c:1906

Referenced by reap_filerefs().

◆ registry_load_volume_options()

NTSTATUS registry_load_volume_options ( device_extension Vcb)

Definition at line 36 of file registry.c.

36 {
37 BTRFS_UUID* uuid = &Vcb->superblock.uuid;
38 mount_options* options = &Vcb->options;
39 UNICODE_STRING path, ignoreus, compressus, compressforceus, compresstypeus, readonlyus, zliblevelus, flushintervalus,
40 maxinlineus, subvolidus, skipbalanceus, nobarrierus, notrimus, clearcacheus, allowdegradedus, zstdlevelus,
41 norootdirus, nodatacowus;
44 ULONG i, j, kvfilen, index, retlen;
46 HANDLE h;
47
48 options->compress = mount_compress;
49 options->compress_force = mount_compress_force;
51 options->readonly = mount_readonly;
52 options->zlib_level = mount_zlib_level;
53 options->zstd_level = mount_zstd_level;
54 options->flush_interval = mount_flush_interval;
55 options->max_inline = min(mount_max_inline, Vcb->superblock.node_size - sizeof(tree_header) - sizeof(leaf_node) - sizeof(EXTENT_DATA) + 1);
56 options->skip_balance = mount_skip_balance;
57 options->no_barrier = mount_no_barrier;
58 options->no_trim = mount_no_trim;
59 options->clear_cache = mount_clear_cache;
60 options->allow_degraded = mount_allow_degraded;
61 options->subvol_id = 0;
62 options->no_root_dir = mount_no_root_dir;
63 options->nodatacow = mount_nodatacow;
64
65 path.Length = path.MaximumLength = registry_path.Length + (37 * sizeof(WCHAR));
67
68 if (!path.Buffer) {
69 ERR("out of memory\n");
71 }
72
74 i = registry_path.Length / sizeof(WCHAR);
75
76 path.Buffer[i] = '\\';
77 i++;
78
79 for (j = 0; j < 16; j++) {
80 path.Buffer[i] = hex_digit((uuid->uuid[j] & 0xF0) >> 4);
81 path.Buffer[i+1] = hex_digit(uuid->uuid[j] & 0xF);
82
83 i += 2;
84
85 if (j == 3 || j == 5 || j == 7 || j == 9) {
86 path.Buffer[i] = '-';
87 i++;
88 }
89 }
90
91 kvfilen = sizeof(KEY_VALUE_FULL_INFORMATION) - sizeof(WCHAR) + (255 * sizeof(WCHAR));
93 if (!kvfi) {
94 ERR("out of memory\n");
96 goto end;
97 }
98
100
101 Status = ZwOpenKey(&h, KEY_QUERY_VALUE, &oa);
104 goto end;
105 } else if (!NT_SUCCESS(Status)) {
106 ERR("ZwOpenKey returned %08lx\n", Status);
107 goto end;
108 }
109
110 index = 0;
111
112 RtlInitUnicodeString(&ignoreus, L"Ignore");
113 RtlInitUnicodeString(&compressus, L"Compress");
114 RtlInitUnicodeString(&compressforceus, L"CompressForce");
115 RtlInitUnicodeString(&compresstypeus, L"CompressType");
116 RtlInitUnicodeString(&readonlyus, L"Readonly");
117 RtlInitUnicodeString(&zliblevelus, L"ZlibLevel");
118 RtlInitUnicodeString(&flushintervalus, L"FlushInterval");
119 RtlInitUnicodeString(&maxinlineus, L"MaxInline");
120 RtlInitUnicodeString(&subvolidus, L"SubvolId");
121 RtlInitUnicodeString(&skipbalanceus, L"SkipBalance");
122 RtlInitUnicodeString(&nobarrierus, L"NoBarrier");
123 RtlInitUnicodeString(&notrimus, L"NoTrim");
124 RtlInitUnicodeString(&clearcacheus, L"ClearCache");
125 RtlInitUnicodeString(&allowdegradedus, L"AllowDegraded");
126 RtlInitUnicodeString(&zstdlevelus, L"ZstdLevel");
127 RtlInitUnicodeString(&norootdirus, L"NoRootDir");
128 RtlInitUnicodeString(&nodatacowus, L"NoDataCOW");
129
130 do {
131 Status = ZwEnumerateValueKey(h, index, KeyValueFullInformation, kvfi, kvfilen, &retlen);
132
133 index++;
134
135 if (NT_SUCCESS(Status)) {
137
138 us.Length = us.MaximumLength = (USHORT)kvfi->NameLength;
139 us.Buffer = kvfi->Name;
140
141 if (FsRtlAreNamesEqual(&ignoreus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
142 DWORD* val = (DWORD*)((uint8_t*)kvfi + kvfi->DataOffset);
143
144 options->ignore = *val != 0 ? true : false;
145 } else if (FsRtlAreNamesEqual(&compressus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
146 DWORD* val = (DWORD*)((uint8_t*)kvfi + kvfi->DataOffset);
147
148 options->compress = *val != 0 ? true : false;
149 } else if (FsRtlAreNamesEqual(&compressforceus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
150 DWORD* val = (DWORD*)((uint8_t*)kvfi + kvfi->DataOffset);
151
152 options->compress_force = *val != 0 ? true : false;
153 } else if (FsRtlAreNamesEqual(&compresstypeus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
154 DWORD* val = (DWORD*)((uint8_t*)kvfi + kvfi->DataOffset);
155
156 options->compress_type = (uint8_t)(*val > BTRFS_COMPRESSION_ZSTD ? 0 : *val);
157 } else if (FsRtlAreNamesEqual(&readonlyus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
158 DWORD* val = (DWORD*)((uint8_t*)kvfi + kvfi->DataOffset);
159
160 options->readonly = *val != 0 ? true : false;
161 } else if (FsRtlAreNamesEqual(&zliblevelus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
162 DWORD* val = (DWORD*)((uint8_t*)kvfi + kvfi->DataOffset);
163
164 options->zlib_level = *val;
165 } else if (FsRtlAreNamesEqual(&flushintervalus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
166 DWORD* val = (DWORD*)((uint8_t*)kvfi + kvfi->DataOffset);
167
168 options->flush_interval = *val;
169 } else if (FsRtlAreNamesEqual(&maxinlineus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
170 DWORD* val = (DWORD*)((uint8_t*)kvfi + kvfi->DataOffset);
171
172 options->max_inline = min(*val, Vcb->superblock.node_size - sizeof(tree_header) - sizeof(leaf_node) - sizeof(EXTENT_DATA) + 1);
173 } else if (FsRtlAreNamesEqual(&subvolidus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_QWORD) {
174 uint64_t* val = (uint64_t*)((uint8_t*)kvfi + kvfi->DataOffset);
175
176 options->subvol_id = *val;
177 } else if (FsRtlAreNamesEqual(&skipbalanceus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
178 DWORD* val = (DWORD*)((uint8_t*)kvfi + kvfi->DataOffset);
179
180 options->skip_balance = *val;
181 } else if (FsRtlAreNamesEqual(&nobarrierus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
182 DWORD* val = (DWORD*)((uint8_t*)kvfi + kvfi->DataOffset);
183
184 options->no_barrier = *val;
185 } else if (FsRtlAreNamesEqual(&notrimus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
186 DWORD* val = (DWORD*)((uint8_t*)kvfi + kvfi->DataOffset);
187
188 options->no_trim = *val;
189 } else if (FsRtlAreNamesEqual(&clearcacheus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
190 DWORD* val = (DWORD*)((uint8_t*)kvfi + kvfi->DataOffset);
191
192 options->clear_cache = *val;
193 } else if (FsRtlAreNamesEqual(&allowdegradedus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
194 DWORD* val = (DWORD*)((uint8_t*)kvfi + kvfi->DataOffset);
195
196 options->allow_degraded = *val;
197 } else if (FsRtlAreNamesEqual(&zstdlevelus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
198 DWORD* val = (DWORD*)((uint8_t*)kvfi + kvfi->DataOffset);
199
200 options->zstd_level = *val;
201 } else if (FsRtlAreNamesEqual(&norootdirus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
202 DWORD* val = (DWORD*)((uint8_t*)kvfi + kvfi->DataOffset);
203
204 options->no_root_dir = *val;
205 } else if (FsRtlAreNamesEqual(&nodatacowus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
206 DWORD* val = (DWORD*)((uint8_t*)kvfi + kvfi->DataOffset);
207
208 options->nodatacow = *val;
209 }
210 } else if (Status != STATUS_NO_MORE_ENTRIES) {
211 ERR("ZwEnumerateValueKey returned %08lx\n", Status);
212 goto end2;
213 }
214 } while (NT_SUCCESS(Status));
215
216 if (!options->compress && options->compress_force)
217 options->compress = true;
218
219 if (options->zlib_level > 9)
220 options->zlib_level = 9;
221
222 if (options->zstd_level > (uint32_t)ZSTD_maxCLevel())
223 options->zstd_level = ZSTD_maxCLevel();
224
225 if (options->flush_interval == 0)
226 options->flush_interval = mount_flush_interval;
227
229
230end2:
231 ZwClose(h);
232
233end:
234 ExFreePool(path.Buffer);
235
236 if (kvfi)
237 ExFreePool(kvfi);
238
239 return Status;
240}
#define hex_digit(c)
Definition: btrfs_drv.h:1748
UNICODE_STRING registry_path
Definition: registry.c:21
struct _KEY_VALUE_FULL_INFORMATION KEY_VALUE_FULL_INFORMATION
BOOLEAN NTAPI FsRtlAreNamesEqual(IN PCUNICODE_STRING Name1, IN PCUNICODE_STRING Name2, IN BOOLEAN IgnoreCase, IN PCWCH UpcaseTable OPTIONAL)
Definition: name.c:296
#define STATUS_NO_MORE_ENTRIES
Definition: ntstatus.h:205
#define REG_QWORD
Definition: sdbapi.c:597
ZSTDLIB_API int ZSTD_maxCLevel(void)

Referenced by mount_vol().

◆ registry_mark_volume_mounted()

NTSTATUS registry_mark_volume_mounted ( BTRFS_UUID uuid)

Definition at line 242 of file registry.c.

242 {
243 UNICODE_STRING path, mountedus;
244 ULONG i, j;
247 HANDLE h;
248 DWORD data;
249
250 path.Length = path.MaximumLength = registry_path.Length + (37 * sizeof(WCHAR));
252
253 if (!path.Buffer) {
254 ERR("out of memory\n");
256 }
257
259 i = registry_path.Length / sizeof(WCHAR);
260
261 path.Buffer[i] = '\\';
262 i++;
263
264 for (j = 0; j < 16; j++) {
265 path.Buffer[i] = hex_digit((uuid->uuid[j] & 0xF0) >> 4);
266 path.Buffer[i+1] = hex_digit(uuid->uuid[j] & 0xF);
267
268 i += 2;
269
270 if (j == 3 || j == 5 || j == 7 || j == 9) {
271 path.Buffer[i] = '-';
272 i++;
273 }
274 }
275
277
278 Status = ZwCreateKey(&h, KEY_SET_VALUE, &oa, 0, NULL, REG_OPTION_NON_VOLATILE, NULL);
279 if (!NT_SUCCESS(Status)) {
280 ERR("ZwCreateKey returned %08lx\n", Status);
281 goto end;
282 }
283
284 mountedus.Buffer = (WCHAR*)option_mounted;
285 mountedus.Length = mountedus.MaximumLength = sizeof(option_mounted) - sizeof(WCHAR);
286
287 data = 1;
288
289 Status = ZwSetValueKey(h, &mountedus, 0, REG_DWORD, &data, sizeof(DWORD));
290 if (!NT_SUCCESS(Status)) {
291 ERR("ZwSetValueKey returned %08lx\n", Status);
292 goto end2;
293 }
294
296
297end2:
298 ZwClose(h);
299
300end:
301 ExFreePool(path.Buffer);
302
303 return Status;
304}
static const WCHAR option_mounted[]
Definition: registry.c:34
#define KEY_SET_VALUE
Definition: nt_native.h:1017

Referenced by mount_vol().

◆ registry_mark_volume_unmounted()

NTSTATUS registry_mark_volume_unmounted ( BTRFS_UUID uuid)

Definition at line 385 of file registry.c.

385 {
388 ULONG i, j;
389
390 path.Length = path.MaximumLength = registry_path.Length + (37 * sizeof(WCHAR));
392
393 if (!path.Buffer) {
394 ERR("out of memory\n");
396 }
397
399 i = registry_path.Length / sizeof(WCHAR);
400
401 path.Buffer[i] = '\\';
402 i++;
403
404 for (j = 0; j < 16; j++) {
405 path.Buffer[i] = hex_digit((uuid->uuid[j] & 0xF0) >> 4);
406 path.Buffer[i+1] = hex_digit(uuid->uuid[j] & 0xF);
407
408 i += 2;
409
410 if (j == 3 || j == 5 || j == 7 || j == 9) {
411 path.Buffer[i] = '-';
412 i++;
413 }
414 }
415
417 if (!NT_SUCCESS(Status)) {
418 ERR("registry_mark_volume_unmounted_path returned %08lx\n", Status);
419 goto end;
420 }
421
423
424end:
425 ExFreePool(path.Buffer);
426
427 return Status;
428}
static NTSTATUS registry_mark_volume_unmounted_path(PUNICODE_STRING path)
Definition: registry.c:306

Referenced by uninit().

◆ remove_device()

NTSTATUS remove_device ( device_extension Vcb,
void data,
ULONG  length,
KPROCESSOR_MODE  processor_mode 
)

Definition at line 3799 of file balance.c.

3799 {
3800 uint64_t devid;
3801 LIST_ENTRY* le;
3802 device* dev = NULL;
3804 int i;
3805 uint64_t num_rw_devices;
3807
3808 TRACE("(%p, %p, %lx)\n", Vcb, data, length);
3809
3810 if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), processor_mode))
3812
3813 if (length < sizeof(uint64_t))
3815
3816 devid = *(uint64_t*)data;
3817
3818 ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
3819
3820 if (Vcb->readonly) {
3821 ExReleaseResourceLite(&Vcb->tree_lock);
3823 }
3824
3825 num_rw_devices = 0;
3826
3827 le = Vcb->devices.Flink;
3828 while (le != &Vcb->devices) {
3830
3831 if (dev2->devitem.dev_id == devid)
3832 dev = dev2;
3833
3834 if (!dev2->readonly)
3835 num_rw_devices++;
3836
3837 le = le->Flink;
3838 }
3839
3840 if (!dev) {
3841 ExReleaseResourceLite(&Vcb->tree_lock);
3842 WARN("device %I64x not found\n", devid);
3843 return STATUS_NOT_FOUND;
3844 }
3845
3846 if (!dev->readonly) {
3847 if (num_rw_devices == 1) {
3848 ExReleaseResourceLite(&Vcb->tree_lock);
3849 WARN("not removing last non-readonly device\n");
3851 }
3852
3853 if (num_rw_devices == 4 &&
3854 ((Vcb->data_flags & BLOCK_FLAG_RAID10 || Vcb->metadata_flags & BLOCK_FLAG_RAID10 || Vcb->system_flags & BLOCK_FLAG_RAID10) ||
3855 (Vcb->data_flags & BLOCK_FLAG_RAID6 || Vcb->metadata_flags & BLOCK_FLAG_RAID6 || Vcb->system_flags & BLOCK_FLAG_RAID6) ||
3856 (Vcb->data_flags & BLOCK_FLAG_RAID1C4 || Vcb->metadata_flags & BLOCK_FLAG_RAID1C4 || Vcb->system_flags & BLOCK_FLAG_RAID1C4)
3857 )
3858 ) {
3859 ExReleaseResourceLite(&Vcb->tree_lock);
3860 ERR("would not be enough devices to satisfy RAID requirement (RAID6/10/1C4)\n");
3861 return STATUS_CANNOT_DELETE;
3862 }
3863
3864 if (num_rw_devices == 3 &&
3865 ((Vcb->data_flags & BLOCK_FLAG_RAID5 || Vcb->metadata_flags & BLOCK_FLAG_RAID5 || Vcb->system_flags & BLOCK_FLAG_RAID5) ||
3866 (Vcb->data_flags & BLOCK_FLAG_RAID1C3 || Vcb->metadata_flags & BLOCK_FLAG_RAID1C3 || Vcb->system_flags & BLOCK_FLAG_RAID1C3))
3867 ) {
3868 ExReleaseResourceLite(&Vcb->tree_lock);
3869 ERR("would not be enough devices to satisfy RAID requirement (RAID5/1C3)\n");
3870 return STATUS_CANNOT_DELETE;
3871 }
3872
3873 if (num_rw_devices == 2 &&
3874 ((Vcb->data_flags & BLOCK_FLAG_RAID0 || Vcb->metadata_flags & BLOCK_FLAG_RAID0 || Vcb->system_flags & BLOCK_FLAG_RAID0) ||
3875 (Vcb->data_flags & BLOCK_FLAG_RAID1 || Vcb->metadata_flags & BLOCK_FLAG_RAID1 || Vcb->system_flags & BLOCK_FLAG_RAID1))
3876 ) {
3877 ExReleaseResourceLite(&Vcb->tree_lock);
3878 ERR("would not be enough devices to satisfy RAID requirement (RAID0/1)\n");
3879 return STATUS_CANNOT_DELETE;
3880 }
3881 }
3882
3883 ExReleaseResourceLite(&Vcb->tree_lock);
3884
3885 if (Vcb->balance.thread) {
3886 WARN("balance already running\n");
3888 }
3889
3890 dev->reloc = true;
3891
3892 RtlZeroMemory(Vcb->balance.opts, sizeof(btrfs_balance_opts) * 3);
3893
3894 for (i = 0; i < 3; i++) {
3896 Vcb->balance.opts[i].devid = devid;
3897 }
3898
3899 Vcb->balance.paused = false;
3900 Vcb->balance.removing = true;
3901 Vcb->balance.shrinking = false;
3902 Vcb->balance.status = STATUS_SUCCESS;
3903 KeInitializeEvent(&Vcb->balance.event, NotificationEvent, !Vcb->balance.paused);
3904
3906
3907 Status = PsCreateSystemThread(&Vcb->balance.thread, 0, &oa, NULL, NULL, balance_thread, Vcb);
3908 if (!NT_SUCCESS(Status)) {
3909 ERR("PsCreateSystemThread returned %08lx\n", Status);
3910 dev->reloc = false;
3911 return Status;
3912 }
3913
3914 return STATUS_SUCCESS;
3915}
#define BTRFS_BALANCE_OPTS_DEVID
Definition: btrfsioctl.h:132
#define STATUS_CANNOT_DELETE
Definition: shellext.h:71

Referenced by fsctl_request().

◆ remove_dir_child_from_hash_lists()

void remove_dir_child_from_hash_lists ( fcb fcb,
dir_child dc 
)

Definition at line 744 of file fileinfo.c.

744 {
745 uint8_t c;
746
747 c = dc->hash >> 24;
748
749 if (fcb->hash_ptrs[c] == &dc->list_entry_hash) {
750 if (dc->list_entry_hash.Flink == &fcb->dir_children_hash)
751 fcb->hash_ptrs[c] = NULL;
752 else {
753 dir_child* dc2 = CONTAINING_RECORD(dc->list_entry_hash.Flink, dir_child, list_entry_hash);
754
755 if (dc2->hash >> 24 == c)
756 fcb->hash_ptrs[c] = &dc2->list_entry_hash;
757 else
758 fcb->hash_ptrs[c] = NULL;
759 }
760 }
761
762 RemoveEntryList(&dc->list_entry_hash);
763
764 c = dc->hash_uc >> 24;
765
766 if (fcb->hash_ptrs_uc[c] == &dc->list_entry_hash_uc) {
767 if (dc->list_entry_hash_uc.Flink == &fcb->dir_children_hash_uc)
769 else {
770 dir_child* dc2 = CONTAINING_RECORD(dc->list_entry_hash_uc.Flink, dir_child, list_entry_hash_uc);
771
772 if (dc2->hash_uc >> 24 == c)
774 else
776 }
777 }
778
779 RemoveEntryList(&dc->list_entry_hash_uc);
780}
LIST_ENTRY list_entry_hash_uc
Definition: btrfs_drv.h:264
LIST_ENTRY list_entry_hash
Definition: btrfs_drv.h:263

Referenced by delete_fileref(), move_across_subvols(), and set_rename_information().

◆ remove_drive_letter()

void void void NTSTATUS void NTSTATUS NTSTATUS remove_drive_letter ( PDEVICE_OBJECT  mountmgr,
PUNICODE_STRING  devpath 
)

Definition at line 407 of file search.c.

407 {
410 ULONG mmpsize;
411 MOUNTMGR_MOUNT_POINTS mmps1, *mmps2;
412
413 TRACE("removing drive letter\n");
414
415 mmpsize = sizeof(MOUNTMGR_MOUNT_POINT) + devpath->Length;
416
418 if (!mmp) {
419 ERR("out of memory\n");
421 }
422
423 RtlZeroMemory(mmp, mmpsize);
424
426 mmp->DeviceNameLength = devpath->Length;
427 RtlCopyMemory(&mmp[1], devpath->Buffer, devpath->Length);
428
429 Status = dev_ioctl(mountmgr, IOCTL_MOUNTMGR_DELETE_POINTS, mmp, mmpsize, &mmps1, sizeof(MOUNTMGR_MOUNT_POINTS), false, NULL);
430
432 ERR("IOCTL_MOUNTMGR_DELETE_POINTS 1 returned %08lx\n", Status);
433 ExFreePool(mmp);
434 return Status;
435 }
436
437 if (Status != STATUS_BUFFER_OVERFLOW || mmps1.Size == 0) {
438 ExFreePool(mmp);
439 return STATUS_NOT_FOUND;
440 }
441
443 if (!mmps2) {
444 ERR("out of memory\n");
445 ExFreePool(mmp);
447 }
448
449 Status = dev_ioctl(mountmgr, IOCTL_MOUNTMGR_DELETE_POINTS, mmp, mmpsize, mmps2, mmps1.Size, false, NULL);
450
451 if (!NT_SUCCESS(Status))
452 ERR("IOCTL_MOUNTMGR_DELETE_POINTS 2 returned %08lx\n", Status);
453
454 ExFreePool(mmps2);
455 ExFreePool(mmp);
456
457 return Status;
458}
#define IOCTL_MOUNTMGR_DELETE_POINTS
Definition: imports.h:124
struct _MOUNTMGR_MOUNT_POINT MOUNTMGR_MOUNT_POINT
USHORT DeviceNameLength
Definition: imports.h:171

Referenced by add_device(), do_shutdown(), drive_letter_callback2(), and mountmgr_process_drive().

◆ remove_fcb_from_subvol()

void remove_fcb_from_subvol ( _In_ _Requires_exclusive_lock_held_(_Curr_->Vcb->fcb_lock) fcb fcb)

Definition at line 937 of file fileinfo.c.

937 {
938 uint8_t c = fcb->hash >> 24;
939
940 if (fcb->subvol->fcbs_ptrs[c] == &fcb->list_entry) {
941 if (fcb->list_entry.Flink != &fcb->subvol->fcbs && (CONTAINING_RECORD(fcb->list_entry.Flink, struct _fcb, list_entry)->hash >> 24) == c)
942 fcb->subvol->fcbs_ptrs[c] = fcb->list_entry.Flink;
943 else
944 fcb->subvol->fcbs_ptrs[c] = NULL;
945 }
946
948}

Referenced by move_across_subvols().

◆ remove_volume_child()

void remove_volume_child ( _Inout_ _Requires_exclusive_lock_held_(_Curr_->child_lock) _Releases_exclusive_lock_(_Curr_->child_lock) _In_ volume_device_extension vde,
_In_ volume_child vc,
_In_ bool  skip_dev 
)

Definition at line 531 of file search.c.

532 {
534 pdo_device_extension* pdode = vde->pdode;
535 device_extension* Vcb = vde->mounted_device ? vde->mounted_device->DeviceExtension : NULL;
536
537 if (vc->notification_entry) {
539 fIoUnregisterPlugPlayNotificationEx(vc->notification_entry);
540 else
541 IoUnregisterPlugPlayNotification(vc->notification_entry);
542 }
543
544 if (vde->mounted_device && (!Vcb || !Vcb->options.allow_degraded)) {
545 Status = pnp_surprise_removal(vde->mounted_device, NULL);
546 if (!NT_SUCCESS(Status))
547 ERR("pnp_surprise_removal returned %08lx\n", Status);
548 }
549
550 if (!Vcb || !Vcb->options.allow_degraded) {
551 Status = IoSetDeviceInterfaceState(&vde->bus_name, false);
552 if (!NT_SUCCESS(Status))
553 WARN("IoSetDeviceInterfaceState returned %08lx\n", Status);
554 }
555
556 if (pdode->children_loaded > 0) {
557 UNICODE_STRING mmdevpath;
560 LIST_ENTRY* le;
561
562 if (!Vcb || !Vcb->options.allow_degraded) {
565 if (!NT_SUCCESS(Status))
566 ERR("IoGetDeviceObjectPointer returned %08lx\n", Status);
567 else {
568 le = pdode->children.Flink;
569
570 while (le != &pdode->children) {
572
573 if (vc2->had_drive_letter) { // re-add entry to mountmgr
574 MOUNTDEV_NAME mdn;
575
578 ERR("IOCTL_MOUNTDEV_QUERY_DEVICE_NAME returned %08lx\n", Status);
579 else {
580 MOUNTDEV_NAME* mdn2;
581 ULONG mdnsize = (ULONG)offsetof(MOUNTDEV_NAME, Name[0]) + mdn.NameLength;
582
583 mdn2 = ExAllocatePoolWithTag(PagedPool, mdnsize, ALLOC_TAG);
584 if (!mdn2)
585 ERR("out of memory\n");
586 else {
587 Status = dev_ioctl(vc2->devobj, IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, NULL, 0, mdn2, mdnsize, true, NULL);
588 if (!NT_SUCCESS(Status))
589 ERR("IOCTL_MOUNTDEV_QUERY_DEVICE_NAME returned %08lx\n", Status);
590 else {
592
593 name.Buffer = mdn2->Name;
594 name.Length = name.MaximumLength = mdn2->NameLength;
595
597 if (!NT_SUCCESS(Status))
598 WARN("mountmgr_add_drive_letter returned %08lx\n", Status);
599 }
600
601 ExFreePool(mdn2);
602 }
603 }
604 }
605
606 le = le->Flink;
607 }
608
610 }
611 } else if (!skip_dev) {
612 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
613
614 le = Vcb->devices.Flink;
615 while (le != &Vcb->devices) {
617
618 if (dev->devobj == vc->devobj) {
619 dev->devobj = NULL; // mark as missing
620 break;
621 }
622
623 le = le->Flink;
624 }
625
626 ExReleaseResourceLite(&Vcb->tree_lock);
627 }
628
629 if (vde->device->Characteristics & FILE_REMOVABLE_MEDIA) {
630 vde->device->Characteristics &= ~FILE_REMOVABLE_MEDIA;
631
632 le = pdode->children.Flink;
633 while (le != &pdode->children) {
635
636 if (vc2 != vc && vc2->devobj->Characteristics & FILE_REMOVABLE_MEDIA) {
637 vde->device->Characteristics |= FILE_REMOVABLE_MEDIA;
638 break;
639 }
640
641 le = le->Flink;
642 }
643 }
644 }
645
646 ObDereferenceObject(vc->fileobj);
647 ExFreePool(vc->pnp_name.Buffer);
648 RemoveEntryList(&vc->list_entry);
649 ExFreePool(vc);
650
651 pdode->children_loaded--;
652
653 if (pdode->children_loaded == 0) { // remove volume device
654 bool remove = false;
655
657
658 vde->removing = true;
659
660 Status = IoSetDeviceInterfaceState(&vde->bus_name, false);
661 if (!NT_SUCCESS(Status))
662 WARN("IoSetDeviceInterfaceState returned %08lx\n", Status);
663
664 if (vde->pdo->AttachedDevice)
665 IoDetachDevice(vde->pdo);
666
667 if (vde->open_count == 0)
668 remove = true;
669
671
672 if (!no_pnp) {
674
676 }
677
678 if (remove) {
679 if (vde->name.Buffer)
680 ExFreePool(vde->name.Buffer);
681
682 if (Vcb)
683 Vcb->vde = NULL;
684
686
687 IoDeleteDevice(vde->device);
688 }
689 } else
691}
NTSTATUS pnp_surprise_removal(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: pnp.c:77
NTSTATUS mountmgr_add_drive_letter(PDEVICE_OBJECT mountmgr, PUNICODE_STRING devpath)
Definition: volume.c:832
tIoUnregisterPlugPlayNotificationEx fIoUnregisterPlugPlayNotificationEx
Definition: btrfs.c:95
PDEVICE_OBJECT busobj
Definition: btrfs.c:66
#define IOCTL_MOUNTDEV_QUERY_DEVICE_NAME
Definition: imports.h:93
int remove
Definition: msacm.c:1366
USHORT NameLength
Definition: imports.h:143
WCHAR Name[1]
Definition: imports.h:144

Referenced by mount_vol(), verify_device(), volume_arrival(), and volume_removal().

◆ resume_balance()

NTSTATUS resume_balance ( device_extension Vcb,
KPROCESSOR_MODE  processor_mode 
)

Definition at line 3765 of file balance.c.

3765 {
3766 if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), processor_mode))
3768
3769 if (!Vcb->balance.thread)
3771
3772 if (!Vcb->balance.paused)
3774
3775 if (Vcb->readonly)
3777
3778 Vcb->balance.paused = false;
3779 KeSetEvent(&Vcb->balance.event, 0, false);
3780
3781 return STATUS_SUCCESS;
3782}

Referenced by fsctl_request().

◆ resume_scrub()

NTSTATUS resume_scrub ( device_extension Vcb,
KPROCESSOR_MODE  processor_mode 
)

Definition at line 3422 of file scrub.c.

3422 {
3423 if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), processor_mode))
3425
3426 if (!Vcb->scrub.thread)
3428
3429 if (!Vcb->scrub.paused)
3431
3432 Vcb->scrub.paused = false;
3433 KeSetEvent(&Vcb->scrub.event, 0, false);
3434
3435 KeQuerySystemTime(&Vcb->scrub.resume_time);
3436
3437 return STATUS_SUCCESS;
3438}

Referenced by fsctl_request().

◆ send_notification_fileref()

void send_notification_fileref ( _In_ file_ref fileref,
_In_ ULONG  filter_match,
_In_ ULONG  action,
_In_opt_ PUNICODE_STRING  stream 
)

Definition at line 1517 of file btrfs.c.

1517 {
1520 ULONG reqlen;
1521 USHORT name_offset;
1522 fcb* fcb = fileref->fcb;
1523
1524 fn.Length = fn.MaximumLength = 0;
1525 Status = fileref_get_filename(fileref, &fn, NULL, &reqlen);
1527 ERR("fileref_get_filename returned %08lx\n", Status);
1528 return;
1529 }
1530
1531 if (reqlen > 0xffff) {
1532 WARN("reqlen was too long for FsRtlNotifyFilterReportChange\n");
1533 return;
1534 }
1535
1536 fn.Buffer = ExAllocatePoolWithTag(PagedPool, reqlen, ALLOC_TAG);
1537 if (!fn.Buffer) {
1538 ERR("out of memory\n");
1539 return;
1540 }
1541
1542 fn.MaximumLength = (USHORT)reqlen;
1543 fn.Length = 0;
1544
1545 Status = fileref_get_filename(fileref, &fn, &name_offset, &reqlen);
1546 if (!NT_SUCCESS(Status)) {
1547 ERR("fileref_get_filename returned %08lx\n", Status);
1548 ExFreePool(fn.Buffer);
1549 return;
1550 }
1551
1552 FsRtlNotifyFilterReportChange(fcb->Vcb->NotifySync, &fcb->Vcb->DirNotifyList, (PSTRING)&fn, name_offset,
1553 (PSTRING)stream, NULL, filter_match, action, NULL, NULL);
1554 ExFreePool(fn.Buffer);
1555}
NTSTATUS fileref_get_filename(file_ref *fileref, PUNICODE_STRING fn, USHORT *name_offset, ULONG *preqlen)
Definition: fileinfo.c:4245
VOID NTAPI FsRtlNotifyFilterReportChange(IN PNOTIFY_SYNC NotifySync, IN PLIST_ENTRY NotifyList, IN PSTRING FullTargetName, IN USHORT TargetNameOffset, IN PSTRING StreamName OPTIONAL, IN PSTRING NormalizedParentName OPTIONAL, IN ULONG FilterMatch, IN ULONG Action, IN PVOID TargetContext, IN PVOID FilterContext)
Definition: notify.c:997

Referenced by _Dispatch_type_(), create_snapshot(), create_stream(), create_subvol(), do_create_snapshot(), file_create(), mknod(), move_across_subvols(), send_notification_fcb(), set_link_information(), and set_rename_information().

◆ send_subvol()

NTSTATUS send_subvol ( device_extension Vcb,
void data,
ULONG  datalen,
PFILE_OBJECT  FileObject,
PIRP  Irp 
)

Definition at line 3593 of file send.c.

3593 {
3595 fcb* fcb;
3596 ccb* ccb;
3597 root* parsubvol = NULL;
3599 send_info* send;
3600 ULONG num_clones = 0;
3601 root** clones = NULL;
3603
3604 if (!FileObject || !FileObject->FsContext || !FileObject->FsContext2 || FileObject->FsContext == Vcb->volume_fcb)
3606
3607 if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), Irp->RequestorMode))
3609
3610 fcb = FileObject->FsContext;
3611 ccb = FileObject->FsContext2;
3612
3613 if (fcb->inode != SUBVOL_ROOT_INODE || fcb == Vcb->root_fileref->fcb)
3615
3616 if (!Vcb->readonly && !(fcb->subvol->root_item.flags & BTRFS_SUBVOL_READONLY))
3618
3619 if (data) {
3621 HANDLE parent;
3622
3623#if defined(_WIN64)
3624 if (IoIs32bitProcess(Irp)) {
3626
3627 if (datalen < offsetof(btrfs_send_subvol32, num_clones))
3629
3630 parent = Handle32ToHandle(bss32->parent);
3631
3632 if (datalen >= offsetof(btrfs_send_subvol32, clones[0]))
3633 num_clones = bss32->num_clones;
3634
3635 if (datalen < offsetof(btrfs_send_subvol32, clones[0]) + (num_clones * sizeof(uint32_t)))
3637 } else {
3638#endif
3639 if (datalen < offsetof(btrfs_send_subvol, num_clones))
3641
3642 parent = bss->parent;
3643
3644 if (datalen >= offsetof(btrfs_send_subvol, clones[0]))
3645 num_clones = bss->num_clones;
3646
3647 if (datalen < offsetof(btrfs_send_subvol, clones[0]) + (num_clones * sizeof(HANDLE)))
3649#if defined(_WIN64)
3650 }
3651#endif
3652
3653 if (parent) {
3654 PFILE_OBJECT fileobj;
3655 struct _fcb* parfcb;
3656
3657 Status = ObReferenceObjectByHandle(parent, 0, *IoFileObjectType, Irp->RequestorMode, (void**)&fileobj, NULL);
3658 if (!NT_SUCCESS(Status)) {
3659 ERR("ObReferenceObjectByHandle returned %08lx\n", Status);
3660 return Status;
3661 }
3662
3663 if (fileobj->DeviceObject != FileObject->DeviceObject) {
3664 ObDereferenceObject(fileobj);
3666 }
3667
3668 parfcb = fileobj->FsContext;
3669
3670 if (!parfcb || parfcb == Vcb->root_fileref->fcb || parfcb == Vcb->volume_fcb || parfcb->inode != SUBVOL_ROOT_INODE) {
3671 ObDereferenceObject(fileobj);
3673 }
3674
3675 parsubvol = parfcb->subvol;
3676 ObDereferenceObject(fileobj);
3677
3678 if (!Vcb->readonly && !(parsubvol->root_item.flags & BTRFS_SUBVOL_READONLY))
3680
3681 if (parsubvol == fcb->subvol)
3683 }
3684
3685 if (num_clones > 0) {
3686 ULONG i;
3687
3688 clones = ExAllocatePoolWithTag(PagedPool, sizeof(root*) * num_clones, ALLOC_TAG);
3689 if (!clones) {
3690 ERR("out of memory\n");
3692 }
3693
3694 for (i = 0; i < num_clones; i++) {
3695 HANDLE h;
3696 PFILE_OBJECT fileobj;
3697 struct _fcb* clonefcb;
3698
3699#if defined(_WIN64)
3700 if (IoIs32bitProcess(Irp)) {
3702
3703 h = Handle32ToHandle(bss32->clones[i]);
3704 } else
3705#endif
3706 h = bss->clones[i];
3707
3708 Status = ObReferenceObjectByHandle(h, 0, *IoFileObjectType, Irp->RequestorMode, (void**)&fileobj, NULL);
3709 if (!NT_SUCCESS(Status)) {
3710 ERR("ObReferenceObjectByHandle returned %08lx\n", Status);
3711 ExFreePool(clones);
3712 return Status;
3713 }
3714
3715 if (fileobj->DeviceObject != FileObject->DeviceObject) {
3716 ObDereferenceObject(fileobj);
3717 ExFreePool(clones);
3719 }
3720
3721 clonefcb = fileobj->FsContext;
3722
3723 if (!clonefcb || clonefcb == Vcb->root_fileref->fcb || clonefcb == Vcb->volume_fcb || clonefcb->inode != SUBVOL_ROOT_INODE) {
3724 ObDereferenceObject(fileobj);
3725 ExFreePool(clones);
3727 }
3728
3729 clones[i] = clonefcb->subvol;
3730 ObDereferenceObject(fileobj);
3731
3732 if (!Vcb->readonly && !(clones[i]->root_item.flags & BTRFS_SUBVOL_READONLY)) {
3733 ExFreePool(clones);
3735 }
3736 }
3737 }
3738 }
3739
3740 ExAcquireResourceExclusiveLite(&Vcb->send_load_lock, true);
3741
3742 if (ccb->send) {
3743 WARN("send operation already running\n");
3744 ExReleaseResourceLite(&Vcb->send_load_lock);
3746 }
3747
3749 if (!context) {
3750 ERR("out of memory\n");
3751
3752 if (clones)
3753 ExFreePool(clones);
3754
3755 ExReleaseResourceLite(&Vcb->send_load_lock);
3757 }
3758
3759 context->Vcb = Vcb;
3760 context->root = fcb->subvol;
3761 context->parent = parsubvol;
3762 InitializeListHead(&context->orphans);
3764 InitializeListHead(&context->pending_rmdirs);
3765 context->lastinode.inode = 0;
3766 context->lastinode.path = NULL;
3767 context->lastinode.sd = NULL;
3768 context->root_dir = NULL;
3769 context->num_clones = num_clones;
3770 context->clones = clones;
3771 InitializeListHead(&context->lastinode.refs);
3772 InitializeListHead(&context->lastinode.oldrefs);
3773 InitializeListHead(&context->lastinode.exts);
3774 InitializeListHead(&context->lastinode.oldexts);
3775
3776 context->data = ExAllocatePoolWithTag(PagedPool, SEND_BUFFER_LENGTH + (2 * MAX_SEND_WRITE), ALLOC_TAG); // give ourselves some wiggle room
3777 if (!context->data) {
3779 ExReleaseResourceLite(&Vcb->send_load_lock);
3781 }
3782
3783 context->datalen = 0;
3784
3785 send_subvol_header(context, fcb->subvol, ccb->fileref); // FIXME - fileref needs some sort of lock here
3786
3787 KeInitializeEvent(&context->buffer_event, NotificationEvent, false);
3788
3790 if (!send) {
3791 ERR("out of memory\n");
3792 ExFreePool(context->data);
3794
3795 if (clones)
3796 ExFreePool(clones);
3797
3798 ExReleaseResourceLite(&Vcb->send_load_lock);
3800 }
3801
3802 KeInitializeEvent(&send->cleared_event, NotificationEvent, false);
3803
3804 send->context = context;
3805 context->send = send;
3806
3807 ccb->send = send;
3808 send->ccb = ccb;
3810
3811 send->cancelling = false;
3812
3813 InterlockedIncrement(&Vcb->running_sends);
3814
3816
3818 if (!NT_SUCCESS(Status)) {
3819 ERR("PsCreateSystemThread returned %08lx\n", Status);
3820 ccb->send = NULL;
3821 InterlockedDecrement(&Vcb->running_sends);
3823 ExFreePool(context->data);
3825
3826 if (clones)
3827 ExFreePool(clones);
3828
3829 ExReleaseResourceLite(&Vcb->send_load_lock);
3830 return Status;
3831 }
3832
3833 InsertTailList(&Vcb->send_ops, &send->list_entry);
3834 ExReleaseResourceLite(&Vcb->send_load_lock);
3835
3836 return STATUS_SUCCESS;
3837}
#define SEND_BUFFER_LENGTH
Definition: send.c:111
static void send_subvol_header(send_context *context, root *r, file_ref *fr)
Definition: send.c:969
#define MAX_SEND_WRITE
Definition: send.c:110
POBJECT_TYPE IoFileObjectType
Definition: iomgr.c:36
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
static DWORD WINAPI send_thread(LPVOID lpParameter)
Definition: send.cpp:227
void *POINTER_32 parent
Definition: btrfsioctl.h:274
void *POINTER_32 clones[1]
Definition: btrfsioctl.h:276
HANDLE clones[1]
Definition: btrfsioctl.h:270

◆ set_reparse_point()

NTSTATUS set_reparse_point ( PIRP  Irp)

Definition at line 409 of file reparse.c.

409 {
412 void* buffer = Irp->AssociatedIrp.SystemBuffer;
414 DWORD buflen = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
416 fcb* fcb;
417 ccb* ccb;
418 file_ref* fileref;
420
421 TRACE("(%p)\n", Irp);
422
424
425 if (!FileObject) {
426 ERR("FileObject was NULL\n");
428 }
429
430 // IFSTest insists on this, for some reason...
431 if (Irp->UserBuffer)
433
434 fcb = FileObject->FsContext;
435 ccb = FileObject->FsContext2;
436
437 if (!ccb) {
438 ERR("ccb was NULL\n");
440 }
441
442 if (Irp->RequestorMode == UserMode && !(ccb->access & (FILE_WRITE_ATTRIBUTES | FILE_WRITE_DATA))) {
443 WARN("insufficient privileges\n");
445 }
446
447 fileref = ccb->fileref;
448
449 if (!fileref) {
450 ERR("fileref was NULL\n");
452 }
453
454 if (fcb->ads) {
455 fileref = fileref->parent;
456 fcb = fileref->fcb;
457 }
458
459 ExAcquireResourceSharedLite(&fcb->Vcb->tree_lock, true);
461
462 Status = set_reparse_point2(fcb, rdb, buflen, ccb, fileref, Irp, &rollback);
463 if (!NT_SUCCESS(Status)) {
464 ERR("set_reparse_point2 returned %08lx\n", Status);
465 goto end;
466 }
467
469
470end:
471 if (NT_SUCCESS(Status))
473 else
475
477 ExReleaseResourceLite(&fcb->Vcb->tree_lock);
478
479 return Status;
480}
NTSTATUS set_reparse_point2(fcb *fcb, REPARSE_DATA_BUFFER *rdb, ULONG buflen, ccb *ccb, file_ref *fileref, PIRP Irp, LIST_ENTRY *rollback)
Definition: reparse.c:307

Referenced by fsctl_request().

◆ set_reparse_point2()

NTSTATUS set_reparse_point2 ( fcb fcb,
REPARSE_DATA_BUFFER rdb,
ULONG  buflen,
ccb ccb,
file_ref fileref,
PIRP  Irp,
LIST_ENTRY rollback 
)

Definition at line 307 of file reparse.c.

307 {
309 ULONG tag;
310
311 if (fcb->type == BTRFS_TYPE_SYMLINK) {
312 WARN("tried to set a reparse point on an existing symlink\n");
314 }
315
316 // FIXME - fail if we already have the attribute FILE_ATTRIBUTE_REPARSE_POINT
317
318 // FIXME - die if not file or directory
319
321 TRACE("directory not empty\n");
323 }
324
325 if (buflen < sizeof(ULONG)) {
326 WARN("buffer was not long enough to hold tag\n");
328 }
329
331 if (!NT_SUCCESS(Status)) {
332 ERR("FsRtlValidateReparsePointBuffer returned %08lx\n", Status);
333 return Status;
334 }
335
336 tag = *(ULONG*)rdb;
337
340
341 if (fcb->type == BTRFS_TYPE_FILE &&
343 Status = set_symlink(Irp, fileref, fcb, ccb, rdb, buflen, rollback);
345 } else {
348
349 if (fcb->type == BTRFS_TYPE_DIRECTORY || fcb->type == BTRFS_TYPE_CHARDEV || fcb->type == BTRFS_TYPE_BLOCKDEV) { // store as xattr
351
352 buf.Buffer = ExAllocatePoolWithTag(PagedPool, buflen, ALLOC_TAG);
353 if (!buf.Buffer) {
354 ERR("out of memory\n");
356 }
357 buf.Length = buf.MaximumLength = (uint16_t)buflen;
358
361
363 RtlCopyMemory(buf.Buffer, rdb, buflen);
364
366
368 } else { // otherwise, store as file data
370 if (!NT_SUCCESS(Status)) {
371 ERR("truncate_file returned %08lx\n", Status);
372 return Status;
373 }
374
375 offset.QuadPart = 0;
376
377 Status = write_file2(fcb->Vcb, Irp, offset, rdb, &buflen, false, true, true, false, false, rollback);
378 if (!NT_SUCCESS(Status)) {
379 ERR("write_file2 returned %08lx\n", Status);
380 return Status;
381 }
382 }
383
386
387 fcb->inode_item.transid = fcb->Vcb->superblock.generation;
389
390 if (!ccb || !ccb->user_set_change_time)
392
393 if (!ccb || !ccb->user_set_write_time)
395
397 fcb->atts_changed = true;
398
399 fcb->subvol->root_item.ctransid = fcb->Vcb->superblock.generation;
400 fcb->subvol->root_item.ctime = now;
401
402 fcb->inode_item_changed = true;
404 }
405
406 return STATUS_SUCCESS;
407}
NTSTATUS NTSTATUS write_file2(device_extension *Vcb, PIRP Irp, LARGE_INTEGER offset, void *buf, ULONG *length, bool paging_io, bool no_cache, bool wait, bool deferred_write, bool write_irp, LIST_ENTRY *rollback) __attribute__((nonnull(1
#define STATUS_INVALID_BUFFER_SIZE
Definition: ntstatus.h:650
static NTSTATUS set_symlink(PIRP Irp, file_ref *fileref, fcb *fcb, ccb *ccb, REPARSE_DATA_BUFFER *rdb, ULONG buflen, LIST_ENTRY *rollback)
Definition: reparse.c:179
tFsRtlValidateReparsePointBuffer fFsRtlValidateReparsePointBuffer
Definition: btrfs.c:98
#define STATUS_DIRECTORY_NOT_EMPTY
Definition: udferr_usr.h:167
#define STATUS_NOT_A_DIRECTORY
Definition: udferr_usr.h:169

Referenced by file_create(), and set_reparse_point().

◆ sid_to_uid()

uint32_t sid_to_uid ( PSID  sid)

Definition at line 310 of file security.c.

310 {
311 LIST_ENTRY* le;
312 sid_header* sh = sid;
313
315
316 le = uid_map_list.Flink;
317 while (le != &uid_map_list) {
318 uid_map* um = CONTAINING_RECORD(le, uid_map, listentry);
319
320 if (RtlEqualSid(sid, um->sid)) {
322 return um->uid;
323 }
324
325 le = le->Flink;
326 }
327
329
330 if (RtlEqualSid(sid, &sid_SY))
331 return 0; // root
332
333 // Samba's SID scheme: S-1-22-1-X
334 if (sh->revision == 1 && sh->elements == 2 && sh->auth[0] == 0 && sh->auth[1] == 0 && sh->auth[2] == 0 && sh->auth[3] == 0 &&
335 sh->auth[4] == 0 && sh->auth[5] == 22 && sh->nums[0] == 1)
336 return sh->nums[1];
337
338 return UID_NOBODY;
339}
static sid_header sid_SY
Definition: security.c:31
NTSYSAPI BOOLEAN NTAPI RtlEqualSid(_In_ PSID Sid1, _In_ PSID Sid2)
short sh
Definition: format.c:272

Referenced by create_directory_fcb(), create_subvol(), fcb_get_new_sd(), and mknod().

◆ skip_to_difference()

void void void NTSTATUS void NTSTATUS skip_to_difference ( device_extension Vcb,
traverse_ptr tp,
traverse_ptr tp2,
bool ended1,
bool ended2 
)

Referenced by _Function_class_().

◆ space_list_add()

void space_list_add ( chunk c,
uint64_t  address,
uint64_t  length,
LIST_ENTRY rollback 
)

Definition at line 2146 of file free-space.c.

2146 {
2147 TRACE("(%p, %I64x, %I64x, %p)\n", c, address, length, rollback);
2148
2149 c->changed = true;
2150 c->space_changed = true;
2151
2152 space_list_add2(&c->deleting, NULL, address, length, c, rollback);
2153}
void space_list_add2(LIST_ENTRY *list, LIST_ENTRY *list_size, uint64_t address, uint64_t length, chunk *c, LIST_ENTRY *rollback)
Definition: free-space.c:1446

Referenced by add_data_reloc(), add_metadata_reloc(), flush_changed_extent(), rationalize_extents(), and reduce_tree_extent().

◆ space_list_add2()

void space_list_add2 ( LIST_ENTRY list,
LIST_ENTRY list_size,
uint64_t  address,
uint64_t  length,
chunk c,
LIST_ENTRY rollback 
)

Definition at line 1446 of file free-space.c.

1446 {
1447 LIST_ENTRY* le;
1448 space *s, *s2;
1449
1450 if (IsListEmpty(list)) {
1452
1453 if (!s) {
1454 ERR("out of memory\n");
1455 return;
1456 }
1457
1458 s->address = address;
1459 s->size = length;
1460 InsertTailList(list, &s->list_entry);
1461
1462 if (list_size)
1463 InsertTailList(list_size, &s->list_entry_size);
1464
1465 if (rollback)
1466 add_rollback_space(rollback, true, list, list_size, address, length, c);
1467
1468 return;
1469 }
1470
1471 le = list->Flink;
1472 do {
1474
1475 // old entry envelops new one completely
1476 if (s2->address <= address && s2->address + s2->size >= address + length)
1477 return;
1478
1479 // new entry envelops old one completely
1480 if (address <= s2->address && address + length >= s2->address + s2->size) {
1481 if (address < s2->address) {
1482 if (rollback)
1483 add_rollback_space(rollback, true, list, list_size, address, s2->address - address, c);
1484
1485 s2->size += s2->address - address;
1486 s2->address = address;
1487
1488 while (s2->list_entry.Blink != list) {
1489 space* s3 = CONTAINING_RECORD(s2->list_entry.Blink, space, list_entry);
1490
1491 if (s3->address + s3->size == s2->address) {
1492 s2->address = s3->address;
1493 s2->size += s3->size;
1494
1496
1497 if (list_size)
1499
1500 ExFreePool(s3);
1501 } else
1502 break;
1503 }
1504 }
1505
1506 if (length > s2->size) {
1507 if (rollback)
1508 add_rollback_space(rollback, true, list, list_size, s2->address + s2->size, address + length - s2->address - s2->size, c);
1509
1510 s2->size = length;
1511
1512 while (s2->list_entry.Flink != list) {
1513 space* s3 = CONTAINING_RECORD(s2->list_entry.Flink, space, list_entry);
1514
1515 if (s3->address <= s2->address + s2->size) {
1516 s2->size = max(s2->size, s3->address + s3->size - s2->address);
1517
1519
1520 if (list_size)
1522
1523 ExFreePool(s3);
1524 } else
1525 break;
1526 }
1527 }
1528
1529 if (list_size) {
1530 RemoveEntryList(&s2->list_entry_size);
1531 order_space_entry(s2, list_size);
1532 }
1533
1534 return;
1535 }
1536
1537 // new entry overlaps start of old one
1538 if (address < s2->address && address + length >= s2->address) {
1539 if (rollback)
1540 add_rollback_space(rollback, true, list, list_size, address, s2->address - address, c);
1541
1542 s2->size += s2->address - address;
1543 s2->address = address;
1544
1545 while (s2->list_entry.Blink != list) {
1546 space* s3 = CONTAINING_RECORD(s2->list_entry.Blink, space, list_entry);
1547
1548 if (s3->address + s3->size == s2->address) {
1549 s2->address = s3->address;
1550 s2->size += s3->size;
1551
1553
1554 if (list_size)
1556
1557 ExFreePool(s3);
1558 } else
1559 break;
1560 }
1561
1562 if (list_size) {
1563 RemoveEntryList(&s2->list_entry_size);
1564 order_space_entry(s2, list_size);
1565 }
1566
1567 return;
1568 }
1569
1570 // new entry overlaps end of old one
1571 if (address <= s2->address + s2->size && address + length > s2->address + s2->size) {
1572 if (rollback)
1573 add_rollback_space(rollback, true, list, list_size, address, s2->address + s2->size - address, c);
1574
1575 s2->size = address + length - s2->address;
1576
1577 while (s2->list_entry.Flink != list) {
1578 space* s3 = CONTAINING_RECORD(s2->list_entry.Flink, space, list_entry);
1579
1580 if (s3->address <= s2->address + s2->size) {
1581 s2->size = max(s2->size, s3->address + s3->size - s2->address);
1582
1584
1585 if (list_size)
1587
1588 ExFreePool(s3);
1589 } else
1590 break;
1591 }
1592
1593 if (list_size) {
1594 RemoveEntryList(&s2->list_entry_size);
1595 order_space_entry(s2, list_size);
1596 }
1597
1598 return;
1599 }
1600
1601 // add completely separate entry
1602 if (s2->address > address + length) {
1604
1605 if (!s) {
1606 ERR("out of memory\n");
1607 return;
1608 }
1609
1610 if (rollback)
1611 add_rollback_space(rollback, true, list, list_size, address, length, c);
1612
1613 s->address = address;
1614 s->size = length;
1615 InsertHeadList(s2->list_entry.Blink, &s->list_entry);
1616
1617 if (list_size)
1618 order_space_entry(s, list_size);
1619
1620 return;
1621 }
1622
1623 le = le->Flink;
1624 } while (le != list);
1625
1626 // check if contiguous with last entry
1627 if (s2->address + s2->size == address) {
1628 s2->size += length;
1629
1630 if (list_size) {
1631 RemoveEntryList(&s2->list_entry_size);
1632 order_space_entry(s2, list_size);
1633 }
1634
1635 return;
1636 }
1637
1638 // otherwise, insert at end
1640
1641 if (!s) {
1642 ERR("out of memory\n");
1643 return;
1644 }
1645
1646 s->address = address;
1647 s->size = length;
1648 InsertTailList(list, &s->list_entry);
1649
1650 if (list_size)
1651 order_space_entry(s, list_size);
1652
1653 if (rollback)
1654 add_rollback_space(rollback, true, list, list_size, address, length, c);
1655}
static void add_rollback_space(LIST_ENTRY *rollback, bool add, LIST_ENTRY *list, LIST_ENTRY *list_size, uint64_t address, uint64_t length, chunk *c)
Definition: free-space.c:1428
LIST_ENTRY list_entry
Definition: btrfs_drv.h:520
LIST_ENTRY list_entry_size
Definition: btrfs_drv.h:521
uint64_t address
Definition: btrfs_drv.h:518
uint64_t size
Definition: btrfs_drv.h:519

Referenced by drop_chunk(), regenerate_space_list(), resize_device(), space_list_add(), and space_list_merge().

◆ space_list_merge()

void space_list_merge ( LIST_ENTRY spacelist,
LIST_ENTRY spacelist_size,
LIST_ENTRY deleting 
)

Definition at line 1657 of file free-space.c.

1657 {
1658 LIST_ENTRY* le = deleting->Flink;
1659
1660 while (le != deleting) {
1662
1663 space_list_add2(spacelist, spacelist_size, s->address, s->size, NULL, NULL);
1664
1665 le = le->Flink;
1666 }
1667}

Referenced by clean_space_cache(), update_chunk_cache(), and update_chunk_cache_tree().

◆ space_list_subtract()

void space_list_subtract ( chunk c,
uint64_t  address,
uint64_t  length,
LIST_ENTRY rollback 
)

Definition at line 2234 of file free-space.c.

2234 {
2235 c->changed = true;
2236 c->space_changed = true;
2237
2238 space_list_subtract2(&c->space, &c->space_size, address, length, c, rollback);
2239
2241}
void space_list_subtract2(LIST_ENTRY *list, LIST_ENTRY *list_size, uint64_t address, uint64_t length, chunk *c, LIST_ENTRY *rollback)
Definition: free-space.c:2155

Referenced by balance_data_chunk(), insert_extent_chunk(), insert_tree_extent(), insert_tree_extent_skinny(), protect_superblocks(), write_compressed(), and write_metadata_items().

◆ space_list_subtract2()

void space_list_subtract2 ( LIST_ENTRY list,
LIST_ENTRY list_size,
uint64_t  address,
uint64_t  length,
chunk c,
LIST_ENTRY rollback 
)

Definition at line 2155 of file free-space.c.

2155 {
2156 LIST_ENTRY *le, *le2;
2157 space *s, *s2;
2158
2159 if (IsListEmpty(list))
2160 return;
2161
2162 le = list->Flink;
2163 while (le != list) {
2165 le2 = le->Flink;
2166
2167 if (s2->address >= address + length)
2168 return;
2169
2170 if (s2->address >= address && s2->address + s2->size <= address + length) { // remove entry entirely
2171 if (rollback)
2172 add_rollback_space(rollback, false, list, list_size, s2->address, s2->size, c);
2173
2174 RemoveEntryList(&s2->list_entry);
2175
2176 if (list_size)
2177 RemoveEntryList(&s2->list_entry_size);
2178
2179 ExFreePool(s2);
2180 } else if (address + length > s2->address && address + length < s2->address + s2->size) {
2181 if (address > s2->address) { // cut out hole
2182 if (rollback)
2183 add_rollback_space(rollback, false, list, list_size, address, length, c);
2184
2186
2187 if (!s) {
2188 ERR("out of memory\n");
2189 return;
2190 }
2191
2192 s->address = s2->address;
2193 s->size = address - s2->address;
2194 InsertHeadList(s2->list_entry.Blink, &s->list_entry);
2195
2196 s2->size = s2->address + s2->size - address - length;
2197 s2->address = address + length;
2198
2199 if (list_size) {
2200 RemoveEntryList(&s2->list_entry_size);
2201 order_space_entry(s2, list_size);
2202 order_space_entry(s, list_size);
2203 }
2204
2205 return;
2206 } else { // remove start of entry
2207 if (rollback)
2208 add_rollback_space(rollback, false, list, list_size, s2->address, address + length - s2->address, c);
2209
2210 s2->size -= address + length - s2->address;
2211 s2->address = address + length;
2212
2213 if (list_size) {
2214 RemoveEntryList(&s2->list_entry_size);
2215 order_space_entry(s2, list_size);
2216 }
2217 }
2218 } else if (address > s2->address && address < s2->address + s2->size) { // remove end of entry
2219 if (rollback)
2220 add_rollback_space(rollback, false, list, list_size, address, s2->address + s2->size - address, c);
2221
2222 s2->size = address - s2->address;
2223
2224 if (list_size) {
2225 RemoveEntryList(&s2->list_entry_size);
2226 order_space_entry(s2, list_size);
2227 }
2228 }
2229
2230 le = le2;
2231 }
2232}

Referenced by __attribute__(), find_disk_holes(), regenerate_space_list(), resize_device(), and space_list_subtract().

◆ start_balance()

NTSTATUS start_balance ( device_extension Vcb,
void data,
ULONG  length,
KPROCESSOR_MODE  processor_mode 
)

Definition at line 3511 of file balance.c.

3511 {
3515 uint8_t i;
3516
3517 if (length < sizeof(btrfs_start_balance) || !data)
3519
3520 if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), processor_mode))
3522
3523 if (Vcb->locked) {
3524 WARN("cannot start balance while locked\n");
3526 }
3527
3528 if (Vcb->scrub.thread) {
3529 WARN("cannot start balance while scrub running\n");
3531 }
3532
3533 if (Vcb->balance.thread) {
3534 WARN("balance already running\n");
3536 }
3537
3538 if (Vcb->readonly)
3540
3544 return STATUS_SUCCESS;
3545
3546 for (i = 0; i < 3; i++) {
3547 if (bsb->opts[i].flags & BTRFS_BALANCE_OPTS_ENABLED) {
3552
3553 if (bsb->opts[i].profiles == 0)
3555 }
3556
3557 if (bsb->opts[i].flags & BTRFS_BALANCE_OPTS_DEVID) {
3558 if (bsb->opts[i].devid == 0)
3560 }
3561
3562 if (bsb->opts[i].flags & BTRFS_BALANCE_OPTS_DRANGE) {
3563 if (bsb->opts[i].drange_start > bsb->opts[i].drange_end)
3565 }
3566
3567 if (bsb->opts[i].flags & BTRFS_BALANCE_OPTS_VRANGE) {
3568 if (bsb->opts[i].vrange_start > bsb->opts[i].vrange_end)
3570 }
3571
3572 if (bsb->opts[i].flags & BTRFS_BALANCE_OPTS_LIMIT) {
3573 bsb->opts[i].limit_start = max(1, bsb->opts[i].limit_start);
3574 bsb->opts[i].limit_end = max(1, bsb->opts[i].limit_end);
3575
3576 if (bsb->opts[i].limit_start > bsb->opts[i].limit_end)
3578 }
3579
3580 if (bsb->opts[i].flags & BTRFS_BALANCE_OPTS_STRIPES) {
3581 bsb->opts[i].stripes_start = max(1, bsb->opts[i].stripes_start);
3582 bsb->opts[i].stripes_end = max(1, bsb->opts[i].stripes_end);
3583
3584 if (bsb->opts[i].stripes_start > bsb->opts[i].stripes_end)
3586 }
3587
3588 if (bsb->opts[i].flags & BTRFS_BALANCE_OPTS_USAGE) {
3589 bsb->opts[i].usage_start = min(100, bsb->opts[i].stripes_start);
3590 bsb->opts[i].usage_end = min(100, bsb->opts[i].stripes_end);
3591
3592 if (bsb->opts[i].stripes_start > bsb->opts[i].stripes_end)
3594 }
3595
3596 if (bsb->opts[i].flags & BTRFS_BALANCE_OPTS_CONVERT) {
3597 if (bsb->opts[i].convert != BLOCK_FLAG_RAID0 && bsb->opts[i].convert != BLOCK_FLAG_RAID1 &&
3603 }
3604 }
3605 }
3606
3610
3611 Vcb->balance.paused = false;
3612 Vcb->balance.removing = false;
3613 Vcb->balance.shrinking = false;
3614 Vcb->balance.status = STATUS_SUCCESS;
3615 KeInitializeEvent(&Vcb->balance.event, NotificationEvent, !Vcb->balance.paused);
3616
3618
3619 Status = PsCreateSystemThread(&Vcb->balance.thread, 0, &oa, NULL, NULL, balance_thread, Vcb);
3620 if (!NT_SUCCESS(Status)) {
3621 ERR("PsCreateSystemThread returned %08lx\n", Status);
3622 return Status;
3623 }
3624
3625 return STATUS_SUCCESS;
3626}
#define BTRFS_BALANCE_OPTS_DRANGE
Definition: btrfsioctl.h:133
#define BTRFS_BALANCE_OPTS_PROFILES
Definition: btrfsioctl.h:131
#define BTRFS_BALANCE_OPTS_VRANGE
Definition: btrfsioctl.h:134
#define BTRFS_BALANCE_OPTS_STRIPES
Definition: btrfsioctl.h:136
uint16_t stripes_start
Definition: btrfsioctl.h:153
uint64_t drange_start
Definition: btrfsioctl.h:147
uint64_t drange_end
Definition: btrfsioctl.h:148
uint64_t limit_start
Definition: btrfsioctl.h:151
uint64_t vrange_start
Definition: btrfsioctl.h:149
uint64_t limit_end
Definition: btrfsioctl.h:152
uint16_t stripes_end
Definition: btrfsioctl.h:154
uint64_t vrange_end
Definition: btrfsioctl.h:150
btrfs_balance_opts opts[3]
Definition: btrfsioctl.h:178

Referenced by fsctl_request().

◆ start_scrub()

NTSTATUS start_scrub ( device_extension Vcb,
KPROCESSOR_MODE  processor_mode 
)

Definition at line 3260 of file scrub.c.

3260 {
3263
3264 if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), processor_mode))
3266
3267 if (Vcb->locked) {
3268 WARN("cannot start scrub while locked\n");
3270 }
3271
3272 if (Vcb->balance.thread) {
3273 WARN("cannot start scrub while balance running\n");
3275 }
3276
3277 if (Vcb->scrub.thread) {
3278 WARN("scrub already running\n");
3280 }
3281
3282 if (Vcb->readonly)
3284
3285 Vcb->scrub.stopping = false;
3286 Vcb->scrub.paused = false;
3287 Vcb->scrub.error = STATUS_SUCCESS;
3288 KeInitializeEvent(&Vcb->scrub.event, NotificationEvent, !Vcb->scrub.paused);
3289
3291
3292 Status = PsCreateSystemThread(&Vcb->scrub.thread, 0, &oa, NULL, NULL, scrub_thread, Vcb);
3293 if (!NT_SUCCESS(Status)) {
3294 ERR("PsCreateSystemThread returned %08lx\n", Status);
3295 return Status;
3296 }
3297
3298 return STATUS_SUCCESS;
3299}

Referenced by fsctl_request().

◆ stop_balance()

NTSTATUS stop_balance ( device_extension Vcb,
KPROCESSOR_MODE  processor_mode 
)

Definition at line 3784 of file balance.c.

3784 {
3785 if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), processor_mode))
3787
3788 if (!Vcb->balance.thread)
3790
3791 Vcb->balance.paused = false;
3792 Vcb->balance.stopping = true;
3793 Vcb->balance.status = STATUS_SUCCESS;
3794 KeSetEvent(&Vcb->balance.event, 0, false);
3795
3796 return STATUS_SUCCESS;
3797}

Referenced by fsctl_request().

◆ stop_scrub()

NTSTATUS stop_scrub ( device_extension Vcb,
KPROCESSOR_MODE  processor_mode 
)

Definition at line 3440 of file scrub.c.

3440 {
3441 if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), processor_mode))
3443
3444 if (!Vcb->scrub.thread)
3446
3447 Vcb->scrub.paused = false;
3448 Vcb->scrub.stopping = true;
3449 KeSetEvent(&Vcb->scrub.event, 0, false);
3450
3451 return STATUS_SUCCESS;
3452}

Referenced by fsctl_request().

◆ stream_set_end_of_file_information()

NTSTATUS stream_set_end_of_file_information ( device_extension Vcb,
uint16_t  end,
fcb fcb,
file_ref fileref,
bool  advance_only 
)

Definition at line 3170 of file fileinfo.c.

3170 {
3173
3174 TRACE("setting new end to %x bytes (currently %x)\n", end, fcb->adsdata.Length);
3175
3176 if (!fileref || !fileref->parent) {
3177 ERR("no fileref for stream\n");
3178 return STATUS_INTERNAL_ERROR;
3179 }
3180
3181 if (end < fcb->adsdata.Length) {
3182 if (advance_only)
3183 return STATUS_SUCCESS;
3184
3185 TRACE("truncating stream to %x bytes\n", end);
3186
3187 fcb->adsdata.Length = end;
3188 } else if (end > fcb->adsdata.Length) {
3189 TRACE("extending stream to %x bytes\n", end);
3190
3191 if (end > fcb->adsmaxlen) {
3192 ERR("error - xattr too long (%u > %lu)\n", end, fcb->adsmaxlen);
3193 return STATUS_DISK_FULL;
3194 }
3195
3196 if (end > fcb->adsdata.MaximumLength) {
3198 if (!data) {
3199 ERR("out of memory\n");
3202 }
3203
3204 if (fcb->adsdata.Buffer) {
3207 }
3208
3211 }
3212
3214
3215 fcb->adsdata.Length = end;
3216 }
3217
3219
3220 fcb->Header.AllocationSize.QuadPart = end;
3221 fcb->Header.FileSize.QuadPart = end;
3222 fcb->Header.ValidDataLength.QuadPart = end;
3223
3226
3227 fileref->parent->fcb->inode_item.transid = Vcb->superblock.generation;
3228 fileref->parent->fcb->inode_item.sequence++;
3229 fileref->parent->fcb->inode_item.st_ctime = now;
3230
3231 fileref->parent->fcb->inode_item_changed = true;
3232 mark_fcb_dirty(fileref->parent->fcb);
3233
3234 fileref->parent->fcb->subvol->root_item.ctransid = Vcb->superblock.generation;
3235 fileref->parent->fcb->subvol->root_item.ctime = now;
3236
3237 return STATUS_SUCCESS;
3238}
ULONG adsmaxlen
Definition: btrfs_drv.h:332

Referenced by __attribute__(), open_file3(), and set_end_of_file_information().

◆ sync_read_phys()

NTSTATUS sync_read_phys ( _In_ PDEVICE_OBJECT  DeviceObject,
_In_ PFILE_OBJECT  FileObject,
_In_ uint64_t  StartingOffset,
_In_ ULONG  Length,
_Out_writes_bytes_(Length) PUCHAR  Buffer,
_In_ bool  override 
)

Definition at line 2732 of file btrfs.c.

2733 {
2736 PIRP Irp;
2740
2741 num_reads++;
2742
2745
2746 Offset.QuadPart = (LONGLONG)StartingOffset;
2747
2748 Irp = IoAllocateIrp(DeviceObject->StackSize, false);
2749
2750 if (!Irp) {
2751 ERR("IoAllocateIrp failed\n");
2753 }
2754
2755 Irp->Flags |= IRP_NOCACHE;
2759
2760 if (override)
2762
2763 if (DeviceObject->Flags & DO_BUFFERED_IO) {
2764 Irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag(NonPagedPool, Length, ALLOC_TAG);
2765 if (!Irp->AssociatedIrp.SystemBuffer) {
2766 ERR("out of memory\n");
2768 goto exit;
2769 }
2770
2772
2773 Irp->UserBuffer = Buffer;
2774 } else if (DeviceObject->Flags & DO_DIRECT_IO) {
2775 Irp->MdlAddress = IoAllocateMdl(Buffer, Length, false, false, NULL);
2776 if (!Irp->MdlAddress) {
2777 ERR("IoAllocateMdl failed\n");
2779 goto exit;
2780 }
2781
2783
2784 _SEH2_TRY {
2788 } _SEH2_END;
2789
2790 if (!NT_SUCCESS(Status)) {
2791 ERR("MmProbeAndLockPages threw exception %08lx\n", Status);
2792 IoFreeMdl(Irp->MdlAddress);
2793 goto exit;
2794 }
2795 } else
2796 Irp->UserBuffer = Buffer;
2797
2798 IrpSp->Parameters.Read.Length = Length;
2799 IrpSp->Parameters.Read.ByteOffset = Offset;
2800
2801 Irp->UserIosb = &IoStatus;
2802
2803 Irp->UserEvent = &context.Event;
2804
2805 IoSetCompletionRoutine(Irp, read_completion, &context, true, true, true);
2806
2808
2809 if (Status == STATUS_PENDING) {
2811 Status = context.iosb.Status;
2812 }
2813
2814 if (DeviceObject->Flags & DO_DIRECT_IO) {
2815 MmUnlockPages(Irp->MdlAddress);
2816 IoFreeMdl(Irp->MdlAddress);
2817 }
2818
2819exit:
2820 IoFreeIrp(Irp);
2821
2822 return Status;
2823}
_In_ PFCB _In_ LONGLONG StartingOffset
Definition: cdprocs.h:291
Definition: bufpool.h:45
uint64_t num_reads
Definition: btrfs.c:67
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
int64_t LONGLONG
Definition: typedefs.h:68

Referenced by device_still_valid(), is_device_part_of_mounted_btrfs_raid(), partial_stripe_read(), read_data_dup(), read_data_raid10(), read_data_raid5(), read_data_raid6(), read_superblock(), still_has_superblock(), test_vol(), and verify_device().

◆ trim_whole_device()

void trim_whole_device ( device dev)

Definition at line 2716 of file fsctl.c.

2716 {
2719
2720 // FIXME - avoid "bootloader area"??
2721
2725 dmdsa.ParameterBlockOffset = 0;
2726 dmdsa.ParameterBlockLength = 0;
2727 dmdsa.DataSetRangesOffset = 0;
2728 dmdsa.DataSetRangesLength = 0;
2729
2731 if (!NT_SUCCESS(Status))
2732 WARN("IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES returned %08lx\n", Status);
2733}
struct _DEVICE_MANAGE_DATA_SET_ATTRIBUTES DEVICE_MANAGE_DATA_SET_ATTRIBUTES
#define DEVICE_DSM_FLAG_ENTIRE_DATA_SET_RANGE
Definition: ntddstor.h:306
#define DEVICE_DSM_FLAG_TRIM_NOT_FS_ALLOCATED
Definition: ntddstor.h:764
#define IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES
Definition: ntddstor.h:181
#define DeviceDsmAction_Trim
Definition: ntddstor.h:276
DEVICE_DATA_MANAGEMENT_SET_ACTION Action
Definition: ntddstor.h:773

Referenced by add_device(), and finish_removing_device().

◆ truncate_file()

◆ uid_to_sid()

NTSTATUS uid_to_sid ( uint32_t  uid,
PSID sid 
)

Definition at line 229 of file security.c.

229 {
230 LIST_ENTRY* le;
231 sid_header* sh;
232 UCHAR els;
233
235
236 le = uid_map_list.Flink;
237 while (le != &uid_map_list) {
238 uid_map* um = CONTAINING_RECORD(le, uid_map, listentry);
239
240 if (um->uid == uid) {
242 if (!*sid) {
243 ERR("out of memory\n");
246 }
247
248 RtlCopyMemory(*sid, um->sid, RtlLengthSid(um->sid));
250 return STATUS_SUCCESS;
251 }
252
253 le = le->Flink;
254 }
255
257
258 if (uid == 0) { // root
259 // FIXME - find actual Administrator account, rather than SYSTEM (S-1-5-18)
260 // (of form S-1-5-21-...-500)
261
262 els = 1;
263
264 sh = ExAllocatePoolWithTag(PagedPool, sizeof(sid_header) + ((els - 1) * sizeof(uint32_t)), ALLOC_TAG);
265 if (!sh) {
266 ERR("out of memory\n");
267 *sid = NULL;
269 }
270
271 sh->revision = 1;
272 sh->elements = els;
273
274 sh->auth[0] = 0;
275 sh->auth[1] = 0;
276 sh->auth[2] = 0;
277 sh->auth[3] = 0;
278 sh->auth[4] = 0;
279 sh->auth[5] = 5;
280
281 sh->nums[0] = 18;
282 } else {
283 // fallback to S-1-22-1-X, Samba's SID scheme
285 if (!sh) {
286 ERR("out of memory\n");
287 *sid = NULL;
289 }
290
291 sh->revision = 1;
292 sh->elements = 2;
293
294 sh->auth[0] = 0;
295 sh->auth[1] = 0;
296 sh->auth[2] = 0;
297 sh->auth[3] = 0;
298 sh->auth[4] = 0;
299 sh->auth[5] = 22;
300
301 sh->nums[0] = 1;
302 sh->nums[1] = uid;
303 }
304
305 *sid = sh;
306
307 return STATUS_SUCCESS;
308}
NTSYSAPI ULONG NTAPI RtlLengthSid(IN PSID Sid)
Definition: sid.c:150
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by fcb_get_sd(), and get_top_level_sd().

◆ uninit()

void uninit ( _In_ device_extension Vcb)

Definition at line 2001 of file btrfs.c.

2001 {
2002 uint64_t i;
2003 KIRQL irql;
2005 LIST_ENTRY* le;
2007
2008 if (!Vcb->removing) {
2009 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
2010 Vcb->removing = true;
2011 ExReleaseResourceLite(&Vcb->tree_lock);
2012 }
2013
2014 if (Vcb->vde && Vcb->vde->mounted_device == Vcb->devobj)
2015 Vcb->vde->mounted_device = NULL;
2016
2018 Vcb->Vpb->Flags &= ~VPB_MOUNTED;
2019 Vcb->Vpb->Flags |= VPB_DIRECT_WRITES_ALLOWED;
2020 Vcb->Vpb->DeviceObject = NULL;
2022
2023 // FIXME - needs global_loading_lock to be held
2024 if (Vcb->list_entry.Flink)
2025 RemoveEntryList(&Vcb->list_entry);
2026
2027 if (Vcb->balance.thread) {
2028 Vcb->balance.paused = false;
2029 Vcb->balance.stopping = true;
2030 KeSetEvent(&Vcb->balance.event, 0, false);
2031 KeWaitForSingleObject(&Vcb->balance.finished, Executive, KernelMode, false, NULL);
2032 }
2033
2034 if (Vcb->scrub.thread) {
2035 Vcb->scrub.paused = false;
2036 Vcb->scrub.stopping = true;
2037 KeSetEvent(&Vcb->scrub.event, 0, false);
2038 KeWaitForSingleObject(&Vcb->scrub.finished, Executive, KernelMode, false, NULL);
2039 }
2040
2041 if (Vcb->running_sends != 0) {
2042 bool send_cancelled = false;
2043
2044 ExAcquireResourceExclusiveLite(&Vcb->send_load_lock, true);
2045
2046 le = Vcb->send_ops.Flink;
2047 while (le != &Vcb->send_ops) {
2049
2050 if (!send->cancelling) {
2051 send->cancelling = true;
2052 send_cancelled = true;
2053 send->ccb = NULL;
2054 KeSetEvent(&send->cleared_event, 0, false);
2055 }
2056
2057 le = le->Flink;
2058 }
2059
2060 ExReleaseResourceLite(&Vcb->send_load_lock);
2061
2062 if (send_cancelled) {
2063 while (Vcb->running_sends != 0) {
2064 ExAcquireResourceExclusiveLite(&Vcb->send_load_lock, true);
2065 ExReleaseResourceLite(&Vcb->send_load_lock);
2066 }
2067 }
2068 }
2069
2070 Status = registry_mark_volume_unmounted(&Vcb->superblock.uuid);
2072 WARN("registry_mark_volume_unmounted returned %08lx\n", Status);
2073
2074 for (i = 0; i < Vcb->calcthreads.num_threads; i++) {
2075 Vcb->calcthreads.threads[i].quit = true;
2076 }
2077
2078 KeSetEvent(&Vcb->calcthreads.event, 0, false);
2079
2080 for (i = 0; i < Vcb->calcthreads.num_threads; i++) {
2081 KeWaitForSingleObject(&Vcb->calcthreads.threads[i].finished, Executive, KernelMode, false, NULL);
2082
2083 ZwClose(Vcb->calcthreads.threads[i].handle);
2084 }
2085
2086 ExFreePool(Vcb->calcthreads.threads);
2087
2088 time.QuadPart = 0;
2089 KeSetTimer(&Vcb->flush_thread_timer, time, NULL); // trigger the timer early
2090 KeWaitForSingleObject(&Vcb->flush_thread_finished, Executive, KernelMode, false, NULL);
2091
2092 reap_fcb(Vcb->volume_fcb);
2093 reap_fcb(Vcb->dummy_fcb);
2094
2095 if (Vcb->root_file)
2096 ObDereferenceObject(Vcb->root_file);
2097
2098 le = Vcb->chunks.Flink;
2099 while (le != &Vcb->chunks) {
2101
2102 if (c->cache) {
2103 reap_fcb(c->cache);
2104 c->cache = NULL;
2105 }
2106
2107 le = le->Flink;
2108 }
2109
2110 while (!IsListEmpty(&Vcb->all_fcbs)) {
2111 fcb* fcb = CONTAINING_RECORD(Vcb->all_fcbs.Flink, struct _fcb, list_entry_all);
2112
2113 reap_fcb(fcb);
2114 }
2115
2116 while (!IsListEmpty(&Vcb->sys_chunks)) {
2118
2119 if (sc->data)
2120 ExFreePool(sc->data);
2121
2122 ExFreePool(sc);
2123 }
2124
2125 while (!IsListEmpty(&Vcb->roots)) {
2127
2128 ExDeleteResourceLite(&r->nonpaged->load_tree_lock);
2129 ExFreePool(r->nonpaged);
2130 ExFreePool(r);
2131 }
2132
2133 while (!IsListEmpty(&Vcb->chunks)) {
2135
2136 while (!IsListEmpty(&c->space)) {
2137 LIST_ENTRY* le2 = RemoveHeadList(&c->space);
2139
2140 ExFreePool(s);
2141 }
2142
2143 while (!IsListEmpty(&c->deleting)) {
2144 LIST_ENTRY* le2 = RemoveHeadList(&c->deleting);
2146
2147 ExFreePool(s);
2148 }
2149
2150 if (c->devices)
2151 ExFreePool(c->devices);
2152
2153 if (c->cache)
2154 reap_fcb(c->cache);
2155
2156 ExDeleteResourceLite(&c->range_locks_lock);
2157 ExDeleteResourceLite(&c->partial_stripes_lock);
2158 ExDeleteResourceLite(&c->lock);
2159 ExDeleteResourceLite(&c->changed_extents_lock);
2160
2161 ExFreePool(c->chunk_item);
2162 ExFreePool(c);
2163 }
2164
2165 while (!IsListEmpty(&Vcb->devices)) {
2167
2168 while (!IsListEmpty(&dev->space)) {
2169 LIST_ENTRY* le2 = RemoveHeadList(&dev->space);
2171
2172 ExFreePool(s);
2173 }
2174
2175 ExFreePool(dev);
2176 }
2177
2178 ExAcquireResourceExclusiveLite(&Vcb->scrub.stats_lock, true);
2179 while (!IsListEmpty(&Vcb->scrub.errors)) {
2181
2182 ExFreePool(err);
2183 }
2184 ExReleaseResourceLite(&Vcb->scrub.stats_lock);
2185
2186 ExDeleteResourceLite(&Vcb->fcb_lock);
2187 ExDeleteResourceLite(&Vcb->fileref_lock);
2188 ExDeleteResourceLite(&Vcb->load_lock);
2189 ExDeleteResourceLite(&Vcb->tree_lock);
2190 ExDeleteResourceLite(&Vcb->chunk_lock);
2191 ExDeleteResourceLite(&Vcb->dirty_fcbs_lock);
2192 ExDeleteResourceLite(&Vcb->dirty_filerefs_lock);
2193 ExDeleteResourceLite(&Vcb->dirty_subvols_lock);
2194 ExDeleteResourceLite(&Vcb->scrub.stats_lock);
2195 ExDeleteResourceLite(&Vcb->send_load_lock);
2196
2197 ExDeletePagedLookasideList(&Vcb->tree_data_lookaside);
2198 ExDeletePagedLookasideList(&Vcb->traverse_ptr_lookaside);
2199 ExDeletePagedLookasideList(&Vcb->batch_item_lookaside);
2200 ExDeletePagedLookasideList(&Vcb->fileref_lookaside);
2201 ExDeletePagedLookasideList(&Vcb->fcb_lookaside);
2202 ExDeletePagedLookasideList(&Vcb->name_bit_lookaside);
2203 ExDeleteNPagedLookasideList(&Vcb->range_lock_lookaside);
2204 ExDeleteNPagedLookasideList(&Vcb->fcb_np_lookaside);
2205
2206 ZwClose(Vcb->flush_thread_handle);
2207
2208 if (Vcb->devobj->AttachedDevice)
2209 IoDetachDevice(Vcb->devobj);
2210
2211 IoDeleteDevice(Vcb->devobj);
2212}
NTSTATUS registry_mark_volume_unmounted(BTRFS_UUID *uuid)
Definition: registry.c:385
VOID NTAPI ExDeletePagedLookasideList(IN PPAGED_LOOKASIDE_LIST Lookaside)
Definition: lookas.c:194
VOID NTAPI ExDeleteNPagedLookasideList(IN PNPAGED_LOOKASIDE_LIST Lookaside)
Definition: lookas.c:170
#define STATUS_TOO_LATE
Definition: ntstatus.h:626
BOOLEAN NTAPI KeSetTimer(IN OUT PKTIMER Timer, IN LARGE_INTEGER DueTime, IN PKDPC Dpc OPTIONAL)
Definition: timerobj.c:281

Referenced by close_file(), dismount_volume(), invalidate_volumes(), pnp_remove_device(), pnp_surprise_removal(), test_validtypes(), and verify_volume().

◆ unix_time_to_win()

static __inline uint64_t unix_time_to_win ( BTRFS_TIME t)
static

Definition at line 985 of file btrfs_drv.h.

985 {
986 return (t->seconds * 10000000) + (t->nanoseconds / 100) + 116444736000000000;
987}

◆ update_changed_extent_ref()

NTSTATUS update_changed_extent_ref ( device_extension Vcb,
chunk c,
uint64_t  address,
uint64_t  size,
uint64_t  root,
uint64_t  objid,
uint64_t  offset,
int32_t  count,
bool  no_csum,
bool  superseded,
PIRP  Irp 
)

Definition at line 1951 of file extent-tree.c.

1952 {
1953 LIST_ENTRY* le;
1954 changed_extent* ce;
1955 changed_extent_ref* cer;
1957 KEY searchkey;
1959 uint32_t old_count;
1960
1961 ExAcquireResourceExclusiveLite(&c->changed_extents_lock, true);
1962
1963 ce = get_changed_extent_item(c, address, size, no_csum);
1964
1965 if (!ce) {
1966 ERR("get_changed_extent_item failed\n");
1968 goto end;
1969 }
1970
1971 if (IsListEmpty(&ce->refs) && IsListEmpty(&ce->old_refs)) { // new entry
1972 searchkey.obj_id = address;
1973 searchkey.obj_type = TYPE_EXTENT_ITEM;
1974 searchkey.offset = 0xffffffffffffffff;
1975
1976 Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, Irp);
1977 if (!NT_SUCCESS(Status)) {
1978 ERR("error - find_item returned %08lx\n", Status);
1979 goto end;
1980 }
1981
1982 if (tp.item->key.obj_id != searchkey.obj_id || tp.item->key.obj_type != searchkey.obj_type) {
1983 ERR("could not find address %I64x in extent tree\n", address);
1985 goto end;
1986 }
1987
1988 if (tp.item->key.offset != size) {
1989 ERR("extent %I64x had size %I64x, not %I64x as expected\n", address, tp.item->key.offset, size);
1991 goto end;
1992 }
1993
1994 if (tp.item->size == sizeof(EXTENT_ITEM_V0)) {
1996
1997 ce->count = ce->old_count = eiv0->refcount;
1998 } else if (tp.item->size >= sizeof(EXTENT_ITEM)) {
2000
2001 ce->count = ce->old_count = ei->refcount;
2002 } else {
2003 ERR("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(EXTENT_ITEM));
2005 goto end;
2006 }
2007 }
2008
2009 le = ce->refs.Flink;
2010 while (le != &ce->refs) {
2012
2013 if (cer->type == TYPE_EXTENT_DATA_REF && cer->edr.root == root && cer->edr.objid == objid && cer->edr.offset == offset) {
2014 ce->count += count;
2015 cer->edr.count += count;
2017
2018 if (superseded)
2019 ce->superseded = true;
2020
2021 goto end;
2022 }
2023
2024 le = le->Flink;
2025 }
2026
2027 old_count = find_extent_data_refcount(Vcb, address, size, root, objid, offset, Irp);
2028
2029 if (old_count > 0) {
2031
2032 if (!cer) {
2033 ERR("out of memory\n");
2035 goto end;
2036 }
2037
2039 cer->edr.root = root;
2040 cer->edr.objid = objid;
2041 cer->edr.offset = offset;
2042 cer->edr.count = old_count;
2043
2044 InsertTailList(&ce->old_refs, &cer->list_entry);
2045 }
2046
2048
2049 if (!cer) {
2050 ERR("out of memory\n");
2052 goto end;
2053 }
2054
2056 cer->edr.root = root;
2057 cer->edr.objid = objid;
2058 cer->edr.offset = offset;
2059 cer->edr.count = old_count + count;
2060
2061 InsertTailList(&ce->refs, &cer->list_entry);
2062
2063 ce->count += count;
2064
2065 if (superseded)
2066 ce->superseded = true;
2067
2069
2070end:
2071 ExReleaseResourceLite(&c->changed_extents_lock);
2072
2073 return Status;
2074}
static uint32_t find_extent_data_refcount(device_extension *Vcb, uint64_t address, uint64_t size, uint64_t root, uint64_t objid, uint64_t offset, PIRP Irp)
Definition: extent-tree.c:1569
uint64_t old_count
Definition: btrfs_drv.h:601
LIST_ENTRY old_refs
Definition: btrfs_drv.h:605

Referenced by __attribute__(), duplicate_extents(), flush_fcb(), move_across_subvols(), and rationalize_extents().

◆ update_chunk_caches()

NTSTATUS update_chunk_caches ( device_extension Vcb,
PIRP  Irp,
LIST_ENTRY rollback 
)

Definition at line 2043 of file free-space.c.

2043 {
2044 LIST_ENTRY *le, batchlist;
2046 chunk* c;
2049
2052
2053 InitializeListHead(&batchlist);
2054
2055 le = Vcb->chunks.Flink;
2056 while (le != &Vcb->chunks) {
2058
2059 if (c->space_changed && c->chunk_item->size >= 0x6400000) { // 100MB
2061 Status = update_chunk_cache(Vcb, c, &now, &batchlist, Irp, rollback);
2063
2064 if (!NT_SUCCESS(Status)) {
2065 ERR("update_chunk_cache(%I64x) returned %08lx\n", c->offset, Status);
2066 clear_batch_list(Vcb, &batchlist);
2067 return Status;
2068 }
2069 }
2070
2071 le = le->Flink;
2072 }
2073
2074 Status = commit_batch_list(Vcb, &batchlist, Irp);
2075 if (!NT_SUCCESS(Status)) {
2076 ERR("commit_batch_list returned %08lx\n", Status);
2077 return Status;
2078 }
2079
2080 le = Vcb->chunks.Flink;
2081 while (le != &Vcb->chunks) {
2083
2084 if (c->changed && (c->chunk_item->type & BLOCK_FLAG_RAID5 || c->chunk_item->type & BLOCK_FLAG_RAID6)) {
2085 ExAcquireResourceExclusiveLite(&c->partial_stripes_lock, true);
2086
2087 while (!IsListEmpty(&c->partial_stripes)) {
2089
2091
2092 if (ps->bmparr)
2093 ExFreePool(ps->bmparr);
2094
2095 ExFreePool(ps);
2096
2097 if (!NT_SUCCESS(Status)) {
2098 ERR("flush_partial_stripe returned %08lx\n", Status);
2099 ExReleaseResourceLite(&c->partial_stripes_lock);
2100 return Status;
2101 }
2102 }
2103
2104 ExReleaseResourceLite(&c->partial_stripes_lock);
2105 }
2106
2107 le = le->Flink;
2108 }
2109
2110 return STATUS_SUCCESS;
2111}
NTSTATUS flush_partial_stripe(device_extension *Vcb, chunk *c, partial_stripe *ps)
Definition: flushthread.c:5958
static NTSTATUS update_chunk_cache(device_extension *Vcb, chunk *c, BTRFS_TIME *now, LIST_ENTRY *batchlist, PIRP Irp, LIST_ENTRY *rollback)
Definition: free-space.c:1694

Referenced by update_root_root().

◆ update_chunk_caches_tree()

NTSTATUS update_chunk_caches_tree ( device_extension Vcb,
PIRP  Irp 
)

Definition at line 2113 of file free-space.c.

2113 {
2114 LIST_ENTRY *le;
2116 chunk* c;
2117
2118 Vcb->superblock.compat_ro_flags |= BTRFS_COMPAT_RO_FLAGS_FREE_SPACE_CACHE_VALID;
2119
2120 ExAcquireResourceSharedLite(&Vcb->chunk_lock, true);
2121
2122 le = Vcb->chunks.Flink;
2123 while (le != &Vcb->chunks) {
2125
2126 if (c->space_changed) {
2130
2131 if (!NT_SUCCESS(Status)) {
2132 ERR("update_chunk_cache_tree(%I64x) returned %08lx\n", c->offset, Status);
2133 ExReleaseResourceLite(&Vcb->chunk_lock);
2134 return Status;
2135 }
2136 }
2137
2138 le = le->Flink;
2139 }
2140
2141 ExReleaseResourceLite(&Vcb->chunk_lock);
2142
2143 return STATUS_SUCCESS;
2144}
#define BTRFS_COMPAT_RO_FLAGS_FREE_SPACE_CACHE_VALID
Definition: btrfs.h:112
static NTSTATUS update_chunk_cache_tree(device_extension *Vcb, chunk *c, PIRP Irp)
Definition: free-space.c:1837

Referenced by do_write2().

◆ update_dev_item()

NTSTATUS update_dev_item ( device_extension Vcb,
device device,
PIRP  Irp 
)

Definition at line 4093 of file flushthread.c.

4093 {
4094 KEY searchkey;
4096 DEV_ITEM* di;
4098
4099 searchkey.obj_id = 1;
4100 searchkey.obj_type = TYPE_DEV_ITEM;
4101 searchkey.offset = device->devitem.dev_id;
4102
4103 Status = find_item(Vcb, Vcb->chunk_root, &tp, &searchkey, false, Irp);
4104 if (!NT_SUCCESS(Status)) {
4105 ERR("error - find_item returned %08lx\n", Status);
4106 return Status;
4107 }
4108
4109 if (keycmp(tp.item->key, searchkey)) {
4110 ERR("error - could not find DEV_ITEM for device %I64x\n", device->devitem.dev_id);
4111 return STATUS_INTERNAL_ERROR;
4112 }
4113
4115 if (!NT_SUCCESS(Status)) {
4116 ERR("delete_tree_item returned %08lx\n", Status);
4117 return Status;
4118 }
4119
4121 if (!di) {
4122 ERR("out of memory\n");
4124 }
4125
4126 RtlCopyMemory(di, &device->devitem, sizeof(DEV_ITEM));
4127
4128 Status = insert_tree_item(Vcb, Vcb->chunk_root, 1, TYPE_DEV_ITEM, device->devitem.dev_id, di, sizeof(DEV_ITEM), NULL, Irp);
4129 if (!NT_SUCCESS(Status)) {
4130 ERR("insert_tree_item returned %08lx\n", Status);
4131 ExFreePool(di);
4132 return Status;
4133 }
4134
4135 return STATUS_SUCCESS;
4136}
#define TYPE_DEV_ITEM
Definition: btrfs.h:47

Referenced by _Function_class_(), create_chunk(), and resize_device().

◆ update_extent_flags()

void update_extent_flags ( device_extension Vcb,
uint64_t  address,
uint64_t  flags,
PIRP  Irp 
)

Definition at line 1876 of file extent-tree.c.

1876 {
1877 KEY searchkey;
1880 EXTENT_ITEM* ei;
1881
1882 searchkey.obj_id = address;
1883 searchkey.obj_type = Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA ? TYPE_METADATA_ITEM : TYPE_EXTENT_ITEM;
1884 searchkey.offset = 0xffffffffffffffff;
1885
1886 Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, Irp);
1887 if (!NT_SUCCESS(Status)) {
1888 ERR("error - find_item returned %08lx\n", Status);
1889 return;
1890 }
1891
1892 if (Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA && tp.item->key.obj_id == address &&
1894 ei = (EXTENT_ITEM*)tp.item->data;
1895 ei->flags = flags;
1896 return;
1897 }
1898
1900 ERR("couldn't find %I64x in extent tree\n", address);
1901 return;
1902 }
1903
1904 if (tp.item->size == sizeof(EXTENT_ITEM_V0))
1905 return;
1906 else if (tp.item->size < sizeof(EXTENT_ITEM)) {
1907 ERR("(%I64x,%x,%I64x) was %x bytes, expected at least %Ix\n", tp.item->key.obj_id, tp.item->key.obj_type,
1908 tp.item->key.offset, tp.item->size, sizeof(EXTENT_ITEM));
1909 return;
1910 }
1911
1912 ei = (EXTENT_ITEM*)tp.item->data;
1913 ei->flags = flags;
1914}

Referenced by update_tree_extents().

◆ utf16_to_utf8()

NTSTATUS utf16_to_utf8 ( char dest,
ULONG  dest_max,
ULONG dest_len,
WCHAR src,
ULONG  src_len 
)

Definition at line 894 of file btrfs.c.

894 {
896 uint16_t* in = (uint16_t*)src;
897 uint8_t* out = (uint8_t*)dest;
898 ULONG in_len = src_len / sizeof(uint16_t);
899 ULONG needed = 0, left = dest_max;
900
901 for (ULONG i = 0; i < in_len; i++) {
902 uint32_t cp = *in;
903 in++;
904
905 if ((cp & 0xfc00) == 0xd800) {
906 if (i == in_len - 1 || (*in & 0xfc00) != 0xdc00) {
907 cp = 0xfffd;
909 } else {
910 cp = (cp & 0x3ff) << 10;
911 cp |= *in & 0x3ff;
912 cp += 0x10000;
913
914 in++;
915 i++;
916 }
917 } else if ((cp & 0xfc00) == 0xdc00) {
918 cp = 0xfffd;
920 }
921
922 if (cp > 0x10ffff) {
923 cp = 0xfffd;
925 }
926
927 if (dest) {
928 if (cp < 0x80) {
929 if (left < 1)
931
932 *out = (uint8_t)cp;
933 out++;
934
935 left--;
936 } else if (cp < 0x800) {
937 if (left < 2)
939
940 *out = 0xc0 | ((cp & 0x7c0) >> 6);
941 out++;
942
943 *out = 0x80 | (cp & 0x3f);
944 out++;
945
946 left -= 2;
947 } else if (cp < 0x10000) {
948 if (left < 3)
950
951 *out = 0xe0 | ((cp & 0xf000) >> 12);
952 out++;
953
954 *out = 0x80 | ((cp & 0xfc0) >> 6);
955 out++;
956
957 *out = 0x80 | (cp & 0x3f);
958 out++;
959
960 left -= 3;
961 } else {
962 if (left < 4)
964
965 *out = 0xf0 | ((cp & 0x1c0000) >> 18);
966 out++;
967
968 *out = 0x80 | ((cp & 0x3f000) >> 12);
969 out++;
970
971 *out = 0x80 | ((cp & 0xfc0) >> 6);
972 out++;
973
974 *out = 0x80 | (cp & 0x3f);
975 out++;
976
977 left -= 4;
978 }
979 }
980
981 if (cp < 0x80)
982 needed++;
983 else if (cp < 0x800)
984 needed += 2;
985 else if (cp < 0x10000)
986 needed += 3;
987 else
988 needed += 4;
989 }
990
991 if (dest_len)
992 *dest_len = needed;
993
994 return Status;
995}
GLint left
Definition: glext.h:7726
POINT cp
Definition: magnifier.c:59
#define STATUS_SOME_NOT_MAPPED
Definition: ntstatus.h:86

Referenced by check_file_name_valid(), and set_label().

◆ utf8_to_utf16()

NTSTATUS utf8_to_utf16 ( WCHAR dest,
ULONG  dest_max,
ULONG dest_len,
char src,
ULONG  src_len 
)

Definition at line 811 of file btrfs.c.

811 {
813 uint8_t* in = (uint8_t*)src;
815 ULONG needed = 0, left = dest_max / sizeof(uint16_t);
816
817 for (ULONG i = 0; i < src_len; i++) {
818 uint32_t cp;
819
820 if (!(in[i] & 0x80))
821 cp = in[i];
822 else if ((in[i] & 0xe0) == 0xc0) {
823 if (i == src_len - 1 || (in[i+1] & 0xc0) != 0x80) {
824 cp = 0xfffd;
826 } else {
827 cp = ((in[i] & 0x1f) << 6) | (in[i+1] & 0x3f);
828 i++;
829 }
830 } else if ((in[i] & 0xf0) == 0xe0) {
831 if (i >= src_len - 2 || (in[i+1] & 0xc0) != 0x80 || (in[i+2] & 0xc0) != 0x80) {
832 cp = 0xfffd;
834 } else {
835 cp = ((in[i] & 0xf) << 12) | ((in[i+1] & 0x3f) << 6) | (in[i+2] & 0x3f);
836 i += 2;
837 }
838 } else if ((in[i] & 0xf8) == 0xf0) {
839 if (i >= src_len - 3 || (in[i+1] & 0xc0) != 0x80 || (in[i+2] & 0xc0) != 0x80 || (in[i+3] & 0xc0) != 0x80) {
840 cp = 0xfffd;
842 } else {
843 cp = ((in[i] & 0x7) << 18) | ((in[i+1] & 0x3f) << 12) | ((in[i+2] & 0x3f) << 6) | (in[i+3] & 0x3f);
844 i += 3;
845 }
846 } else {
847 cp = 0xfffd;
849 }
850
851 if (cp > 0x10ffff) {
852 cp = 0xfffd;
854 }
855
856 if (dest) {
857 if (cp <= 0xffff) {
858 if (left < 1)
860
861 *out = (uint16_t)cp;
862 out++;
863
864 left--;
865 } else {
866 if (left < 2)
868
869 cp -= 0x10000;
870
871 *out = 0xd800 | ((cp & 0xffc00) >> 10);
872 out++;
873
874 *out = 0xdc00 | (cp & 0x3ff);
875 out++;
876
877 left -= 2;
878 }
879 }
880
881 if (cp <= 0xffff)
882 needed += sizeof(uint16_t);
883 else
884 needed += 2 * sizeof(uint16_t);
885 }
886
887 if (dest_len)
888 *dest_len = needed;
889
890 return Status;
891}

Referenced by _Dispatch_type_().

◆ vol_close()

NTSTATUS vol_close ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp 
)

Definition at line 95 of file volume.c.

95 {
96 volume_device_extension* vde = DeviceObject->DeviceExtension;
97 pdo_device_extension* pdode = vde->pdode;
98
99 TRACE("(%p, %p)\n", DeviceObject, Irp);
100
101 Irp->IoStatus.Information = 0;
102
103 if (vde->dead)
104 return STATUS_SUCCESS;
105
107
108 if (vde->dead) {
110 return STATUS_SUCCESS;
111 }
112
114
115 if (InterlockedDecrement(&vde->open_count) == 0 && vde->removing) {
117
118 free_vol(vde);
119 } else
121
123
124 return STATUS_SUCCESS;
125}
void free_vol(volume_device_extension *vde)
Definition: volume.c:50

Referenced by _Dispatch_type_().

◆ vol_create()

NTSTATUS vol_create ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp 
)

Definition at line 36 of file volume.c.

36 {
37 volume_device_extension* vde = DeviceObject->DeviceExtension;
38
39 TRACE("(%p, %p)\n", DeviceObject, Irp);
40
41 if (vde->removing)
43
44 Irp->IoStatus.Information = FILE_OPENED;
46
47 return STATUS_SUCCESS;
48}
#define FILE_OPENED
Definition: nt_native.h:769

Referenced by _Dispatch_type_().

◆ vol_device_control()

NTSTATUS vol_device_control ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp 
)

Definition at line 755 of file volume.c.

755 {
756 volume_device_extension* vde = DeviceObject->DeviceExtension;
758
759 TRACE("(%p, %p)\n", DeviceObject, Irp);
760
761 Irp->IoStatus.Information = 0;
762
763 switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
765 return vol_query_device_name(vde, Irp);
766
768 return vol_query_unique_id(vde, Irp);
769
771 return vol_get_device_number(vde, Irp);
772
774 TRACE("unhandled control code IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME\n");
775 break;
776
778 return vol_query_stable_guid(vde, Irp);
779
781 TRACE("unhandled control code IOCTL_MOUNTDEV_LINK_CREATED\n");
782 break;
783
786
788 return vol_is_dynamic(Irp);
789
791 Irp->IoStatus.Information = 0;
792 return STATUS_SUCCESS;
793
795 Irp->IoStatus.Information = 0;
796 return STATUS_SUCCESS;
797
800
802 return vol_is_writable(vde);
803
805 return vol_get_length(vde, Irp);
806
809 return vol_check_verify(vde);
810
812 return vol_get_disk_extents(vde, Irp);
813
814 default: { // pass ioctl through if only one child device
816#ifdef _DEBUG
817 ULONG code = IrpSp->Parameters.DeviceIoControl.IoControlCode;
818
819 if (NT_SUCCESS(Status))
820 TRACE("passing through ioctl %lx (returning %08lx)\n", code, Status);
821 else
822 WARN("passing through ioctl %lx (returning %08lx)\n", code, Status);
823#endif
824
825 return Status;
826 }
827 }
828
830}
#define IOCTL_DISK_CHECK_VERIFY
Definition: cdrw_usr.h:175
#define IOCTL_DISK_GET_DRIVE_GEOMETRY
Definition: cdrw_usr.h:169
static NTSTATUS vol_query_unique_id(volume_device_extension *vde, PIRP Irp)
Definition: volume.c:333
static NTSTATUS vol_query_stable_guid(volume_device_extension *vde, PIRP Irp)
Definition: volume.c:731
static NTSTATUS vol_check_verify(volume_device_extension *vde)
Definition: volume.c:379
static NTSTATUS vol_get_disk_extents(volume_device_extension *vde, PIRP Irp)
Definition: volume.c:405
#define IOCTL_VOLUME_IS_DYNAMIC
Definition: volume.c:25
static NTSTATUS vol_get_length(volume_device_extension *vde, PIRP Irp)
Definition: volume.c:526
static NTSTATUS vol_ioctl_passthrough(volume_device_extension *vde, PIRP Irp)
Definition: volume.c:661
static NTSTATUS vol_get_gpt_attributes(PIRP Irp)
Definition: volume.c:595
#define IOCTL_VOLUME_POST_ONLINE
Definition: volume.c:26
static NTSTATUS vol_get_drive_geometry(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: volume.c:557
static NTSTATUS vol_is_writable(volume_device_extension *vde)
Definition: volume.c:495
static NTSTATUS vol_query_device_name(volume_device_extension *vde, PIRP Irp)
Definition: volume.c:306
static NTSTATUS vol_get_device_number(volume_device_extension *vde, PIRP Irp)
Definition: volume.c:611
static NTSTATUS vol_is_dynamic(PIRP Irp)
Definition: volume.c:363
#define IOCTL_MOUNTDEV_LINK_CREATED
Definition: imports.h:106
#define IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME
Definition: imports.h:99
#define IOCTL_MOUNTDEV_QUERY_STABLE_GUID
Definition: imports.h:255
#define IOCTL_MOUNTDEV_QUERY_UNIQUE_ID
Definition: imports.h:80
#define IOCTL_STORAGE_CHECK_VERIFY
Definition: ntddstor.h:98
#define IOCTL_VOLUME_GET_GPT_ATTRIBUTES
Definition: ntddvol.h:56
#define IOCTL_VOLUME_ONLINE
Definition: ntddvol.h:62
#define IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
Definition: ntddvol.h:41
Definition: inflate.c:139

Referenced by _Dispatch_type_().

◆ vol_read()

NTSTATUS vol_read ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp 
)

Definition at line 144 of file volume.c.

144 {
145 volume_device_extension* vde = DeviceObject->DeviceExtension;
146 pdo_device_extension* pdode = vde->pdode;
147 volume_child* vc;
149 PIRP Irp2;
152
153 TRACE("(%p, %p)\n", DeviceObject, Irp);
154
156
157 if (IsListEmpty(&pdode->children)) {
160 goto end;
161 }
162
164
165 // We can't use IoSkipCurrentIrpStackLocation as the device isn't in our stack
166
167 Irp2 = IoAllocateIrp(vc->devobj->StackSize, false);
168
169 if (!Irp2) {
170 ERR("IoAllocateIrp failed\n");
173 goto end;
174 }
175
177 IrpSp2 = IoGetNextIrpStackLocation(Irp2);
178
179 IrpSp2->MajorFunction = IRP_MJ_READ;
180 IrpSp2->FileObject = vc->fileobj;
181
182 if (vc->devobj->Flags & DO_BUFFERED_IO) {
183 Irp2->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag(NonPagedPool, IrpSp->Parameters.Read.Length, ALLOC_TAG);
184 if (!Irp2->AssociatedIrp.SystemBuffer) {
185 ERR("out of memory\n");
188 goto end;
189 }
190
192
193 Irp2->UserBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
194 } else if (vc->devobj->Flags & DO_DIRECT_IO)
195 Irp2->MdlAddress = Irp->MdlAddress;
196 else
197 Irp2->UserBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
198
199 IrpSp2->Parameters.Read.Length = IrpSp->Parameters.Read.Length;
200 IrpSp2->Parameters.Read.ByteOffset.QuadPart = IrpSp->Parameters.Read.ByteOffset.QuadPart;
201
203 Irp2->UserIosb = &context.iosb;
204
205 IoSetCompletionRoutine(Irp2, vol_read_completion, &context, true, true, true);
206
207 Status = IoCallDriver(vc->devobj, Irp2);
208
209 if (Status == STATUS_PENDING) {
211 Status = context.iosb.Status;
212 }
213
215
216 Irp->IoStatus.Information = context.iosb.Information;
217
218end:
219 Irp->IoStatus.Status = Status;
221
222 return Status;
223}

Referenced by _Dispatch_type_().

◆ vol_write()

NTSTATUS vol_write ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp 
)

Definition at line 225 of file volume.c.

225 {
226 volume_device_extension* vde = DeviceObject->DeviceExtension;
227 pdo_device_extension* pdode = vde->pdode;
228 volume_child* vc;
230 PIRP Irp2;
233
234 TRACE("(%p, %p)\n", DeviceObject, Irp);
235
237
238 if (IsListEmpty(&pdode->children)) {
241 goto end;
242 }
243
245
246 if (vc->list_entry.Flink != &pdode->children) { // more than once device
249 goto end;
250 }
251
252 // We can't use IoSkipCurrentIrpStackLocation as the device isn't in our stack
253
254 Irp2 = IoAllocateIrp(vc->devobj->StackSize, false);
255
256 if (!Irp2) {
257 ERR("IoAllocateIrp failed\n");
260 goto end;
261 }
262
264 IrpSp2 = IoGetNextIrpStackLocation(Irp2);
265
266 IrpSp2->MajorFunction = IRP_MJ_WRITE;
267 IrpSp2->FileObject = vc->fileobj;
268
269 if (vc->devobj->Flags & DO_BUFFERED_IO) {
270 Irp2->AssociatedIrp.SystemBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
271
272 Irp2->Flags |= IRP_BUFFERED_IO;
273
274 Irp2->UserBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
275 } else if (vc->devobj->Flags & DO_DIRECT_IO)
276 Irp2->MdlAddress = Irp->MdlAddress;
277 else
278 Irp2->UserBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
279
280 IrpSp2->Parameters.Write.Length = IrpSp->Parameters.Write.Length;
281 IrpSp2->Parameters.Write.ByteOffset.QuadPart = IrpSp->Parameters.Write.ByteOffset.QuadPart;
282
284 Irp2->UserIosb = &context.iosb;
285
286 IoSetCompletionRoutine(Irp2, vol_read_completion, &context, true, true, true);
287
288 Status = IoCallDriver(vc->devobj, Irp2);
289
290 if (Status == STATUS_PENDING) {
292 Status = context.iosb.Status;
293 }
294
296
297 Irp->IoStatus.Information = context.iosb.Information;
298
299end:
300 Irp->IoStatus.Status = Status;
302
303 return Status;
304}

Referenced by _Dispatch_type_().

◆ volume_arrival()

bool volume_arrival ( PUNICODE_STRING  devpath,
bool  fve_callback 
)

Definition at line 693 of file search.c.

693 {
695 PFILE_OBJECT fileobj;
696 PDEVICE_OBJECT devobj;
699 bool ret = true;
700
701 TRACE("%.*S\n", (int)(devpath->Length / sizeof(WCHAR)), devpath->Buffer);
702
704
705 Status = IoGetDeviceObjectPointer(devpath, FILE_READ_ATTRIBUTES, &fileobj, &devobj);
706 if (!NT_SUCCESS(Status)) {
708 ERR("IoGetDeviceObjectPointer returned %08lx\n", Status);
709 return false;
710 }
711
712 // make sure we're not processing devices we've created ourselves
713
714 if (devobj->DriverObject == drvobj)
715 goto end;
716
717 Status = dev_ioctl(devobj, IOCTL_VOLUME_ONLINE, NULL, 0, NULL, 0, true, NULL);
718 if (!NT_SUCCESS(Status))
719 TRACE("IOCTL_VOLUME_ONLINE returned %08lx\n", Status);
720
721 Status = dev_ioctl(devobj, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &gli, sizeof(gli), true, NULL);
722 if (!NT_SUCCESS(Status)) {
723 ERR("IOCTL_DISK_GET_LENGTH_INFO returned %08lx\n", Status);
724 goto end;
725 }
726
728 &sdn, sizeof(STORAGE_DEVICE_NUMBER), true, NULL);
729 if (!NT_SUCCESS(Status)) {
730 TRACE("IOCTL_STORAGE_GET_DEVICE_NUMBER returned %08lx\n", Status);
731 sdn.DeviceNumber = 0xffffffff;
732 sdn.PartitionNumber = 0;
733 } else
734 TRACE("DeviceType = %lu, DeviceNumber = %lu, PartitionNumber = %lu\n", sdn.DeviceType, sdn.DeviceNumber, sdn.PartitionNumber);
735
736 // If we've just added a partition to a whole-disk filesystem, unmount it
737 if (sdn.DeviceNumber != 0xffffffff && sdn.PartitionNumber != 0) {
738 LIST_ENTRY* le;
739
741
742 le = pdo_list.Flink;
743 while (le != &pdo_list) {
745 LIST_ENTRY* le2;
746 bool changed = false;
747
748 if (pdode->vde) {
750
751 le2 = pdode->children.Flink;
752 while (le2 != &pdode->children) {
754 LIST_ENTRY* le3 = le2->Flink;
755
756 if (vc->disk_num == sdn.DeviceNumber && vc->part_num == 0) {
757 TRACE("removing device\n");
758
759 remove_volume_child(pdode->vde, vc, false);
760 changed = true;
761
762 break;
763 }
764
765 le2 = le3;
766 }
767
768 if (!changed)
770 else
771 break;
772 }
773
774 le = le->Flink;
775 }
776
778 }
779
780 ret = test_vol(devobj, fileobj, devpath, sdn.DeviceNumber, sdn.PartitionNumber,
781 gli.Length.QuadPart, fve_callback);
782
783end:
784 ObDereferenceObject(fileobj);
785
787
788 return ret;
789}
PDRIVER_OBJECT drvobj
Definition: btrfs.c:65
LIST_ENTRY pdo_list
Definition: btrfs.c:104
ERESOURCE pdo_list_lock
Definition: btrfs.c:103
void remove_volume_child(_Inout_ _Requires_exclusive_lock_held_(_Curr_->child_lock) _Releases_exclusive_lock_(_Curr_->child_lock) _In_ volume_device_extension *vde, _In_ volume_child *vc, _In_ bool skip_dev)
Definition: search.c:531

Referenced by _Function_class_(), probe_volume(), and volume_arrival2().

◆ volume_removal()

void volume_removal ( PUNICODE_STRING  devpath)

Definition at line 795 of file search.c.

795 {
796 LIST_ENTRY* le;
797 UNICODE_STRING devpath2;
798
799 TRACE("%.*S\n", (int)(devpath->Length / sizeof(WCHAR)), devpath->Buffer);
800
801 devpath2 = *devpath;
802
803 if (devpath->Length > 4 * sizeof(WCHAR) && devpath->Buffer[0] == '\\' && (devpath->Buffer[1] == '\\' || devpath->Buffer[1] == '?') &&
804 devpath->Buffer[2] == '?' && devpath->Buffer[3] == '\\') {
805 devpath2.Buffer = &devpath2.Buffer[3];
806 devpath2.Length -= 3 * sizeof(WCHAR);
807 devpath2.MaximumLength -= 3 * sizeof(WCHAR);
808 }
809
811
812 le = pdo_list.Flink;
813 while (le != &pdo_list) {
815 LIST_ENTRY* le2;
816 bool changed = false;
817
818 if (pdode->vde) {
820
821 le2 = pdode->children.Flink;
822 while (le2 != &pdode->children) {
824 LIST_ENTRY* le3 = le2->Flink;
825
826 if (vc->pnp_name.Length == devpath2.Length && RtlCompareMemory(vc->pnp_name.Buffer, devpath2.Buffer, devpath2.Length) == devpath2.Length) {
827 TRACE("removing device\n");
828
829 if (!vc->boot_volume) {
830 remove_volume_child(pdode->vde, vc, false);
831 changed = true;
832 }
833
834 break;
835 }
836
837 le2 = le3;
838 }
839
840 if (!changed)
842 else
843 break;
844 }
845
846 le = le->Flink;
847 }
848
850}

Referenced by _Function_class_(), add_device(), and probe_volume().

◆ watch_registry()

void watch_registry ( HANDLE  regh)

Definition at line 1036 of file registry.c.

1036 {
1039
1040 ExInitializeWorkItem(&wqi, registry_work_item, regh);
1041
1042 Status = ZwNotifyChangeKey(regh, NULL, (PVOID)&wqi, (PVOID)DelayedWorkQueue, &iosb, REG_NOTIFY_CHANGE_LAST_SET, true, NULL, 0, true);
1043 if (!NT_SUCCESS(Status))
1044 ERR("ZwNotifyChangeKey returned %08lx\n", Status);
1045}
WORK_QUEUE_ITEM wqi
Definition: registry.c:32
#define REG_NOTIFY_CHANGE_LAST_SET
Definition: winreg.h:40

Referenced by _Function_class_().

◆ win_time_to_unix()

◆ write_compressed()

NTSTATUS write_compressed ( fcb fcb,
uint64_t  start_data,
uint64_t  end_data,
void data,
PIRP  Irp,
LIST_ENTRY rollback 
)

Definition at line 875 of file compress.c.

875 {
877 uint64_t i;
878 unsigned int num_parts = (unsigned int)sector_align(end_data - start_data, COMPRESSED_EXTENT_SIZE) / COMPRESSED_EXTENT_SIZE;
881 unsigned int buflen = 0;
882 uint8_t* buf;
883 chunk* c = NULL;
884 LIST_ENTRY* le;
885 uint64_t address, extaddr;
886 void* csum = NULL;
887
888 if (fcb->Vcb->options.compress_type != 0 && fcb->prop_compression == PropCompression_None)
889 type = fcb->Vcb->options.compress_type;
890 else {
891 if (!(fcb->Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_COMPRESS_ZSTD) && fcb->prop_compression == PropCompression_ZSTD)
895 else if (!(fcb->Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_COMPRESS_LZO) && fcb->prop_compression == PropCompression_LZO)
897 else if (fcb->Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_COMPRESS_LZO && fcb->prop_compression != PropCompression_Zlib)
899 else
901 }
902
904 if (!NT_SUCCESS(Status)) {
905 ERR("excise_extents returned %08lx\n", Status);
906 return Status;
907 }
908
910 if (!parts) {
911 ERR("out of memory\n");
913 }
914
915 for (i = 0; i < num_parts; i++) {
916 if (i == num_parts - 1)
917 parts[i].inlen = ((unsigned int)(end_data - start_data) - ((num_parts - 1) * COMPRESSED_EXTENT_SIZE));
918 else
920
922 parts[i].buf, parts[i].inlen, &parts[i].cj);
923 if (!NT_SUCCESS(Status)) {
924 ERR("add_calc_job_comp returned %08lx\n", Status);
925
926 for (unsigned int j = 0; j < i; j++) {
929 }
930
932 return Status;
933 }
934 }
935
937
938 for (int i = num_parts - 1; i >= 0; i--) {
940
942
943 if (!NT_SUCCESS(parts[i].cj->Status))
944 Status = parts[i].cj->Status;
945 }
946
947 if (!NT_SUCCESS(Status)) {
948 ERR("calc job returned %08lx\n", Status);
949
950 for (unsigned int i = 0; i < num_parts; i++) {
952 }
953
955 return Status;
956 }
957
958 for (unsigned int i = 0; i < num_parts; i++) {
959 if (parts[i].cj->space_left >= fcb->Vcb->superblock.sector_size) {
960 parts[i].compression_type = type;
961 parts[i].outlen = parts[i].inlen - parts[i].cj->space_left;
962
964 fcb->Vcb->superblock.incompat_flags |= BTRFS_INCOMPAT_FLAGS_COMPRESS_LZO;
965 else if (type == BTRFS_COMPRESSION_ZSTD)
966 fcb->Vcb->superblock.incompat_flags |= BTRFS_INCOMPAT_FLAGS_COMPRESS_ZSTD;
967
968 if ((parts[i].outlen & (fcb->Vcb->superblock.sector_size - 1)) != 0) {
969 unsigned int newlen = (unsigned int)sector_align(parts[i].outlen, fcb->Vcb->superblock.sector_size);
970
971 RtlZeroMemory(parts[i].buf + parts[i].outlen, newlen - parts[i].outlen);
972
973 parts[i].outlen = newlen;
974 }
975 } else {
976 parts[i].compression_type = BTRFS_COMPRESSION_NONE;
977 parts[i].outlen = (unsigned int)sector_align(parts[i].inlen, fcb->Vcb->superblock.sector_size);
978 }
979
980 buflen += parts[i].outlen;
982 }
983
984 // check if first 128 KB of file is incompressible
985
986 if (start_data == 0 && parts[0].compression_type == BTRFS_COMPRESSION_NONE && !fcb->Vcb->options.compress_force) {
987 TRACE("adding nocompress flag to subvol %I64x, inode %I64x\n", fcb->subvol->id, fcb->inode);
988
990 fcb->inode_item_changed = true;
992 }
993
994 // join together into continuous buffer
995
997 if (!buf) {
998 ERR("out of memory\n");
1001 }
1002
1003 {
1004 uint8_t* buf2 = buf;
1005
1006 for (i = 0; i < num_parts; i++) {
1007 if (parts[i].compression_type == BTRFS_COMPRESSION_NONE)
1008 RtlCopyMemory(buf2, (uint8_t*)data + (i * COMPRESSED_EXTENT_SIZE), parts[i].outlen);
1009 else
1010 RtlCopyMemory(buf2, parts[i].buf, parts[i].outlen);
1011
1012 buf2 += parts[i].outlen;
1013 }
1014 }
1015
1016 // find an address
1017
1018 ExAcquireResourceSharedLite(&fcb->Vcb->chunk_lock, true);
1019
1020 le = fcb->Vcb->chunks.Flink;
1021 while (le != &fcb->Vcb->chunks) {
1023
1024 if (!c2->readonly && !c2->reloc) {
1026
1027 if (c2->chunk_item->type == fcb->Vcb->data_flags && (c2->chunk_item->size - c2->used) >= buflen) {
1028 if (find_data_address_in_chunk(fcb->Vcb, c2, buflen, &address)) {
1029 c = c2;
1030 c->used += buflen;
1033 break;
1034 }
1035 }
1036
1038 }
1039
1040 le = le->Flink;
1041 }
1042
1043 ExReleaseResourceLite(&fcb->Vcb->chunk_lock);
1044
1045 if (!c) {
1046 chunk* c2;
1047
1048 ExAcquireResourceExclusiveLite(&fcb->Vcb->chunk_lock, true);
1049
1050 Status = alloc_chunk(fcb->Vcb, fcb->Vcb->data_flags, &c2, false);
1051
1052 ExReleaseResourceLite(&fcb->Vcb->chunk_lock);
1053
1054 if (!NT_SUCCESS(Status)) {
1055 ERR("alloc_chunk returned %08lx\n", Status);
1056 ExFreePool(buf);
1058 return Status;
1059 }
1060
1062
1063 if (find_data_address_in_chunk(fcb->Vcb, c2, buflen, &address)) {
1064 c = c2;
1065 c->used += buflen;
1067 }
1068
1070 }
1071
1072 if (!c) {
1073 WARN("couldn't find any data chunks with %x bytes free\n", buflen);
1074 ExFreePool(buf);
1076 return STATUS_DISK_FULL;
1077 }
1078
1079 // write to disk
1080
1081 TRACE("writing %x bytes to %I64x\n", buflen, address);
1082
1083 Status = write_data_complete(fcb->Vcb, address, buf, buflen, Irp, NULL, false, 0,
1085 if (!NT_SUCCESS(Status)) {
1086 ERR("write_data_complete returned %08lx\n", Status);
1087 ExFreePool(buf);
1089 return Status;
1090 }
1091
1092 // FIXME - do rest of the function while we're waiting for I/O to finish?
1093
1094 // calculate csums if necessary
1095
1097 unsigned int sl = buflen >> fcb->Vcb->sector_shift;
1098
1099 csum = ExAllocatePoolWithTag(PagedPool, sl * fcb->Vcb->csum_size, ALLOC_TAG);
1100 if (!csum) {
1101 ERR("out of memory\n");
1102 ExFreePool(buf);
1105 }
1106
1107 do_calc_job(fcb->Vcb, buf, sl, csum);
1108 }
1109
1110 ExFreePool(buf);
1111
1112 // add extents to fcb
1113
1114 extaddr = address;
1115
1116 for (i = 0; i < num_parts; i++) {
1117 EXTENT_DATA* ed;
1118 EXTENT_DATA2* ed2;
1119 void* csum2;
1120
1122 if (!ed) {
1123 ERR("out of memory\n");
1125
1126 if (csum)
1128
1130 }
1131
1132 ed->generation = fcb->Vcb->superblock.generation;
1133 ed->decoded_size = parts[i].inlen;
1134 ed->compression = parts[i].compression_type;
1138
1139 ed2 = (EXTENT_DATA2*)ed->data;
1140 ed2->address = extaddr;
1141 ed2->size = parts[i].outlen;
1142 ed2->offset = 0;
1143 ed2->num_bytes = parts[i].inlen;
1144
1145 if (csum) {
1146 csum2 = ExAllocatePoolWithTag(PagedPool, (parts[i].outlen * fcb->Vcb->csum_size) >> fcb->Vcb->sector_shift, ALLOC_TAG);
1147 if (!csum2) {
1148 ERR("out of memory\n");
1149 ExFreePool(ed);
1153 }
1154
1155 RtlCopyMemory(csum2, (uint8_t*)csum + (((extaddr - address) * fcb->Vcb->csum_size) >> fcb->Vcb->sector_shift),
1156 (parts[i].outlen * fcb->Vcb->csum_size) >> fcb->Vcb->sector_shift);
1157 } else
1158 csum2 = NULL;
1159
1161 true, csum2, rollback);
1162 if (!NT_SUCCESS(Status)) {
1163 ERR("add_extent_to_fcb returned %08lx\n", Status);
1164 ExFreePool(ed);
1166
1167 if (csum)
1169
1170 return Status;
1171 }
1172
1173 ExFreePool(ed);
1174
1175 fcb->inode_item.st_blocks += parts[i].inlen;
1176
1177 extaddr += parts[i].outlen;
1178 }
1179
1180 if (csum)
1182
1183 // update extent refcounts
1184
1185 ExAcquireResourceExclusiveLite(&c->changed_extents_lock, true);
1186
1187 extaddr = address;
1188
1189 for (i = 0; i < num_parts; i++) {
1190 add_changed_extent_ref(c, extaddr, parts[i].outlen, fcb->subvol->id, fcb->inode,
1192
1193 extaddr += parts[i].outlen;
1194 }
1195
1196 ExReleaseResourceLite(&c->changed_extents_lock);
1197
1198 fcb->extents_changed = true;
1199 fcb->inode_item_changed = true;
1201
1203
1204 return STATUS_SUCCESS;
1205}
NTSTATUS bool find_data_address_in_chunk(device_extension *Vcb, chunk *c, uint64_t length, uint64_t *address) __attribute__((nonnull(1
NTSTATUS add_calc_job_comp(device_extension *Vcb, uint8_t compression, void *in, unsigned int inlen, void *out, unsigned int outlen, calc_job **pcj)
Definition: calcthread.c:237
_In_ fcb _In_ chunk _In_ uint64_t start_data
Definition: btrfs_drv.h:1364
#define COMPRESSED_EXTENT_SIZE
Definition: btrfs_drv.h:112
void add_changed_extent_ref(chunk *c, uint64_t address, uint64_t size, uint64_t root, uint64_t objid, uint64_t offset, uint32_t count, bool no_csum)
Definition: extent-tree.c:2076
NTSTATUS bool void 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) void *csum, _In_ LIST_ENTRY *rollback) __attribute__((nonnull(1
NTSTATUS NTSTATUS NTSTATUS write_data_complete(device_extension *Vcb, uint64_t address, void *data, uint32_t length, PIRP Irp, chunk *c, bool file_write, uint64_t irp_offset, ULONG priority) __attribute__((nonnull(1
void calc_thread_main(device_extension *Vcb, calc_job *cj)
Definition: calcthread.c:22
#define BTRFS_INCOMPAT_FLAGS_COMPRESS_ZSTD
Definition: btrfs.h:119
#define BTRFS_ENCODING_NONE
Definition: btrfs.h:72
#define BTRFS_ENCRYPTION_NONE
Definition: btrfs.h:70
#define BTRFS_INCOMPAT_FLAGS_COMPRESS_LZO
Definition: btrfs.h:118
#define BTRFS_INODE_NOCOMPRESS
Definition: propsheet.h:79
uint64_t generation
Definition: btrfs.h:358
uint16_t encoding
Definition: btrfs.h:362
uint8_t encryption
Definition: btrfs.h:361
uint8_t compression
Definition: btrfs.h:360
uint64_t used
Definition: btrfs_drv.h:565

Referenced by __attribute__(), and zero_data().

◆ write_data()

NTSTATUS NTSTATUS write_data ( _In_ device_extension Vcb,
_In_ uint64_t  address,
_In_reads_bytes_(length) void data,
_In_ uint32_t  length,
_In_ write_data_context wtc,
_In_opt_ PIRP  Irp,
_In_opt_ chunk c,
_In_ bool  file_write,
_In_ uint64_t  irp_offset,
_In_ ULONG  priority 
)

◆ write_data_complete()

NTSTATUS NTSTATUS NTSTATUS write_data_complete ( device_extension Vcb,
uint64_t  address,
void data,
uint32_t  length,
PIRP  Irp,
chunk c,
bool  file_write,
uint64_t  irp_offset,
ULONG  priority 
)

◆ write_data_phys()

NTSTATUS write_data_phys ( _In_ PDEVICE_OBJECT  device,
_In_ PFILE_OBJECT  fileobj,
_In_ uint64_t  address,
_In_reads_bytes_(length) void data,
_In_ uint32_t  length 
)

Definition at line 70 of file flushthread.c.

71 {
74 PIRP Irp;
77
78 TRACE("(%p, %I64x, %p, %x)\n", device, address, data, length);
79
81
83
84 offset.QuadPart = address;
85
86 Irp = IoAllocateIrp(device->StackSize, false);
87
88 if (!Irp) {
89 ERR("IoAllocateIrp failed\n");
91 }
92
95 IrpSp->FileObject = fileobj;
96
97 if (device->Flags & DO_BUFFERED_IO) {
98 Irp->AssociatedIrp.SystemBuffer = data;
99
100 Irp->Flags = IRP_BUFFERED_IO;
101 } else if (device->Flags & DO_DIRECT_IO) {
102 Irp->MdlAddress = IoAllocateMdl(data, length, false, false, NULL);
103 if (!Irp->MdlAddress) {
104 DbgPrint("IoAllocateMdl failed\n");
106 goto exit;
107 }
108
110
111 _SEH2_TRY {
115 } _SEH2_END;
116
117 if (!NT_SUCCESS(Status)) {
118 ERR("MmProbeAndLockPages threw exception %08lx\n", Status);
119 IoFreeMdl(Irp->MdlAddress);
120 goto exit;
121 }
122 } else {
123 Irp->UserBuffer = data;
124 }
125
126 IrpSp->Parameters.Write.Length = length;
127 IrpSp->Parameters.Write.ByteOffset = offset;
128
129 Irp->UserIosb = &context.iosb;
130
131 Irp->UserEvent = &context.Event;
132
133 IoSetCompletionRoutine(Irp, write_completion, &context, true, true, true);
134
136
137 if (Status == STATUS_PENDING) {
139 Status = context.iosb.Status;
140 }
141
142 if (!NT_SUCCESS(Status)) {
143 ERR("IoCallDriver returned %08lx\n", Status);
144 }
145
146 if (device->Flags & DO_DIRECT_IO) {
147 MmUnlockPages(Irp->MdlAddress);
148 IoFreeMdl(Irp->MdlAddress);
149 }
150
151exit:
152 IoFreeIrp(Irp);
153
154 return Status;
155}

Referenced by add_device(), flush_partial_stripe(), read_data_dup(), read_data_raid10(), read_data_raid5(), read_data_raid6(), remove_superblocks(), scrub_chunk_raid56_stripe_run(), scrub_extent_dup(), and scrub_extent_raid10().

◆ write_fcb_compressed()

static __inline bool write_fcb_compressed ( fcb fcb)
static

Definition at line 1706 of file btrfs_drv.h.

1706 {
1708 return false;
1709
1710 // make sure we don't accidentally write the cache inodes or pagefile compressed
1712 return false;
1713
1714 if (fcb->Vcb->options.compress_force)
1715 return true;
1716
1718 return false;
1719
1720 if (fcb->inode_item.flags & BTRFS_INODE_COMPRESS || fcb->Vcb->options.compress)
1721 return true;
1722
1723 return false;
1724}
#define BTRFS_ROOT_ROOT
Definition: btrfs.h:54
#define BTRFS_INODE_COMPRESS
Definition: propsheet.h:87

Referenced by __attribute__(), file_create2(), and zero_data().

◆ write_file()

NTSTATUS write_file ( device_extension Vcb,
PIRP  Irp,
bool  wait,
bool  deferred_write 
)

◆ write_file2()

NTSTATUS NTSTATUS write_file2 ( device_extension Vcb,
PIRP  Irp,
LARGE_INTEGER  offset,
void buf,
ULONG length,
bool  paging_io,
bool  no_cache,
bool  wait,
bool  deferred_write,
bool  write_irp,
LIST_ENTRY rollback 
)

Referenced by set_reparse_point2(), and set_symlink().

◆ zlib_compress()

NTSTATUS zlib_compress ( uint8_t inbuf,
uint32_t  inlen,
uint8_t outbuf,
uint32_t  outlen,
unsigned int  level,
unsigned int space_left 
)

Definition at line 336 of file compress.c.

336 {
337 z_stream c_stream;
338 int ret;
339
340 c_stream.zalloc = zlib_alloc;
341 c_stream.zfree = zlib_free;
342 c_stream.opaque = (voidpf)0;
343
344 ret = deflateInit(&c_stream, level);
345
346 if (ret != Z_OK) {
347 ERR("deflateInit returned %i\n", ret);
349 }
350
351 c_stream.next_in = inbuf;
352 c_stream.avail_in = inlen;
353
354 c_stream.next_out = outbuf;
355 c_stream.avail_out = outlen;
356
357 do {
358 ret = deflate(&c_stream, Z_FINISH);
359
360 if (ret != Z_OK && ret != Z_STREAM_END) {
361 ERR("deflate returned %i\n", ret);
362 deflateEnd(&c_stream);
364 }
365
366 if (c_stream.avail_in == 0 || c_stream.avail_out == 0)
367 break;
368 } while (ret != Z_STREAM_END);
369
370 deflateEnd(&c_stream);
371
372 *space_left = c_stream.avail_in > 0 ? 0 : c_stream.avail_out;
373
374 return STATUS_SUCCESS;
375}
void FAR * voidpf
Definition: zlib.h:42
#define Z_STREAM_END
Definition: zlib.h:115
#define Z_FINISH
Definition: zlib.h:109
#define Z_OK
Definition: zlib.h:114
int deflate(z_streamp strm, int flush) DECLSPEC_HIDDEN
Definition: deflate.c:815
int deflateEnd(z_streamp strm) DECLSPEC_HIDDEN
Definition: deflate.c:1130
static void zlib_free(void *opaque, void *ptr)
Definition: compress.c:330
static void * zlib_alloc(void *opaque, unsigned int items, unsigned int size)
Definition: compress.c:324
#define deflateInit(strm, level)
Definition: zlib.h:1810
uInt avail_in
Definition: zlib.h:60
z_const Bytef * next_in
Definition: zlib.h:59
alloc_func zalloc
Definition: zlib.h:70
uInt avail_out
Definition: zlib.h:64
Bytef * next_out
Definition: zlib.h:63
free_func zfree
Definition: zlib.h:71
voidpf opaque
Definition: zlib.h:72

Referenced by calc_thread_main().

◆ zlib_decompress()

NTSTATUS zlib_decompress ( uint8_t inbuf,
uint32_t  inlen,
uint8_t outbuf,
uint32_t  outlen 
)

Definition at line 377 of file compress.c.

377 {
378 z_stream c_stream;
379 int ret;
380
381 c_stream.zalloc = zlib_alloc;
382 c_stream.zfree = zlib_free;
383 c_stream.opaque = (voidpf)0;
384
385 ret = inflateInit(&c_stream);
386
387 if (ret != Z_OK) {
388 ERR("inflateInit returned %i\n", ret);
390 }
391
392 c_stream.next_in = inbuf;
393 c_stream.avail_in = inlen;
394
395 c_stream.next_out = outbuf;
396 c_stream.avail_out = outlen;
397
398 do {
399 ret = inflate(&c_stream, Z_NO_FLUSH);
400
401 if (ret != Z_OK && ret != Z_STREAM_END) {
402 ERR("inflate returned %i\n", ret);
403 inflateEnd(&c_stream);
405 }
406
407 if (c_stream.avail_out == 0)
408 break;
409 } while (ret != Z_STREAM_END);
410
411 ret = inflateEnd(&c_stream);
412
413 if (ret != Z_OK) {
414 ERR("inflateEnd returned %i\n", ret);
416 }
417
418 // FIXME - if we're short, should we zero the end of outbuf so we don't leak information into userspace?
419
420 return STATUS_SUCCESS;
421}
int inflate(z_streamp strm, int flush)
Definition: inflate.c:1257
int inflateEnd(z_streamp strm)
Definition: inflate.c:1910
#define Z_NO_FLUSH
Definition: zlib.h:105
#define inflateInit(strm)
Definition: zlib.h:1812

Referenced by calc_thread_main(), and flush_extents().

◆ zstd_compress()

NTSTATUS zstd_compress ( uint8_t inbuf,
uint32_t  inlen,
uint8_t outbuf,
uint32_t  outlen,
uint32_t  level,
unsigned int space_left 
)

Definition at line 805 of file compress.c.

805 {
807 size_t init_res, written;
809 ZSTD_outBuffer output;
810 ZSTD_parameters params;
811
813
814 if (!stream) {
815 ERR("ZSTD_createCStream failed.\n");
817 }
818
819 params = ZSTD_getParams(level, inlen, 0);
820
821 if (params.cParams.windowLog > ZSTD_BTRFS_MAX_WINDOWLOG)
822 params.cParams.windowLog = ZSTD_BTRFS_MAX_WINDOWLOG;
823
824 init_res = ZSTD_initCStream_advanced(stream, NULL, 0, params, inlen);
825
826 if (ZSTD_isError(init_res)) {
827 ERR("ZSTD_initCStream_advanced failed: %s\n", ZSTD_getErrorName(init_res));
830 }
831
832 input.src = inbuf;
833 input.size = inlen;
834 input.pos = 0;
835
836 output.dst = outbuf;
837 output.size = outlen;
838 output.pos = 0;
839
840 while (input.pos < input.size && output.pos < output.size) {
841 written = ZSTD_compressStream(stream, &output, &input);
842
843 if (ZSTD_isError(written)) {
844 ERR("ZSTD_compressStream failed: %s\n", ZSTD_getErrorName(written));
847 }
848 }
849
850 written = ZSTD_endStream(stream, &output);
851 if (ZSTD_isError(written)) {
852 ERR("ZSTD_endStream failed: %s\n", ZSTD_getErrorName(written));
855 }
856
858
859 if (input.pos < input.size) // output would be larger than input
860 *space_left = 0;
861 else
862 *space_left = output.size - output.pos;
863
864 return STATUS_SUCCESS;
865}
#define ZSTD_BTRFS_MAX_WINDOWLOG
Definition: compress.c:92
ZSTD_customMem zstd_mem
Definition: compress.c:98
GLenum const GLfloat * params
Definition: glext.h:5645
size_t size
Definition: zstd.h:574
size_t pos
Definition: zstd.h:575
void * dst
Definition: zstd.h:573
ZSTDLIB_API size_t ZSTD_compressStream(ZSTD_CStream *zcs, ZSTD_outBuffer *output, ZSTD_inBuffer *input)
ZSTDLIB_API size_t ZSTD_freeCStream(ZSTD_CStream *zcs)
ZSTDLIB_API const char * ZSTD_getErrorName(size_t code)
Definition: zstd_common.c:41
ZSTDLIB_API size_t ZSTD_endStream(ZSTD_CStream *zcs, ZSTD_outBuffer *output)
ZSTD_CStream * ZSTD_createCStream_advanced(ZSTD_customMem customMem)
ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize)
size_t ZSTD_initCStream_advanced(ZSTD_CStream *zcs, const void *dict, size_t dictSize, ZSTD_parameters params, unsigned long long pss)
#define ZSTD_isError
Definition: zstd_internal.h:46

Referenced by calc_thread_main().

◆ zstd_decompress()

NTSTATUS zstd_decompress ( uint8_t inbuf,
uint32_t  inlen,
uint8_t outbuf,
uint32_t  outlen 
)

Definition at line 676 of file compress.c.

676 {
679 size_t init_res, read;
681 ZSTD_outBuffer output;
682
684
685 if (!stream) {
686 ERR("ZSTD_createDStream failed.\n");
688 }
689
690 init_res = ZSTD_initDStream(stream);
691
692 if (ZSTD_isError(init_res)) {
693 ERR("ZSTD_initDStream failed: %s\n", ZSTD_getErrorName(init_res));
695 goto end;
696 }
697
698 input.src = inbuf;
699 input.size = inlen;
700 input.pos = 0;
701
702 output.dst = outbuf;
703 output.size = outlen;
704 output.pos = 0;
705
706 do {
708
709 if (ZSTD_isError(read)) {
710 ERR("ZSTD_decompressStream failed: %s\n", ZSTD_getErrorName(read));
712 goto end;
713 }
714
715 if (output.pos == output.size)
716 break;
717 } while (read != 0);
718
720
721end:
723
724 return Status;
725}
#define read
Definition: acwin.h:96
ZSTDLIB_API size_t ZSTD_initDStream(ZSTD_DStream *zds)
ZSTDLIB_API size_t ZSTD_decompressStream(ZSTD_DStream *zds, ZSTD_outBuffer *output, ZSTD_inBuffer *input)
ZSTDLIB_API size_t ZSTD_freeDStream(ZSTD_DStream *zds)
ZSTD_DStream * ZSTD_createDStream_advanced(ZSTD_customMem customMem)

Referenced by calc_thread_main(), and flush_extents().

Variable Documentation

◆ a

Initial value:
{
if (n & (a - 1))
n = (n + a) & ~(a - 1)
_In_ uint64_t a
Definition: btrfs_drv.h:1026
GLdouble n
Definition: glext.h:7729

Definition at line 1026 of file btrfs_drv.h.

◆ atts

◆ boot_uuid

BTRFS_UUID boot_uuid
extern

◆ c

Definition at line 1364 of file btrfs_drv.h.

◆ cache_callbacks

CACHE_MANAGER_CALLBACKS cache_callbacks
extern

Definition at line 20 of file cache.c.

Referenced by init_cache(), init_file_cache(), and mount_vol().

◆ compression

◆ Context

Definition at line 1326 of file btrfs_drv.h.

Referenced by oplock_complete().

◆ data

◆ decoded_size

◆ do_xor

◆ file_write

◆ fve_data_lock

KSPIN_LOCK fve_data_lock
extern

Definition at line 63 of file search.c.

Referenced by _Function_class_(), event_notification(), and register_fve_callback().

◆ Irp

Definition at line 1365 of file btrfs_drv.h.

◆ len

Definition at line 1107 of file btrfs_drv.h.

◆ length

◆ lxdev

const char lxdev[] = "$LXDEV"
static

Definition at line 1290 of file btrfs_drv.h.

Referenced by file_create_parse_ea().

◆ lxgid

const char lxgid[] = "$LXGID"
static

Definition at line 1288 of file btrfs_drv.h.

Referenced by file_create_parse_ea().

◆ lxmod

const char lxmod[] = "$LXMOD"
static

Definition at line 1289 of file btrfs_drv.h.

Referenced by file_create_parse_ea().

◆ lxuid

const char lxuid[] = "$LXUID"
static

Definition at line 1287 of file btrfs_drv.h.

Referenced by file_create_parse_ea().

◆ mount_allow_degraded

uint32_t mount_allow_degraded
extern

Definition at line 83 of file btrfs.c.

Referenced by allow_degraded_mount(), read_registry(), and registry_load_volume_options().

◆ mount_clear_cache

uint32_t mount_clear_cache
extern

Definition at line 82 of file btrfs.c.

Referenced by read_registry(), and registry_load_volume_options().

◆ mount_compress

uint32_t mount_compress
extern

Definition at line 72 of file btrfs.c.

Referenced by read_registry(), and registry_load_volume_options().

◆ mount_compress_force

uint32_t mount_compress_force
extern

Definition at line 73 of file btrfs.c.

Referenced by read_registry(), and registry_load_volume_options().

◆ mount_compress_type

uint32_t mount_compress_type
extern

Definition at line 74 of file btrfs.c.

Referenced by read_registry(), and registry_load_volume_options().

◆ mount_flush_interval

uint32_t mount_flush_interval
extern

Definition at line 77 of file btrfs.c.

Referenced by read_registry(), and registry_load_volume_options().

◆ mount_max_inline

uint32_t mount_max_inline
extern

Definition at line 78 of file btrfs.c.

Referenced by read_registry(), and registry_load_volume_options().

◆ mount_no_barrier

uint32_t mount_no_barrier
extern

Definition at line 80 of file btrfs.c.

Referenced by read_registry(), and registry_load_volume_options().

◆ mount_no_root_dir

uint32_t mount_no_root_dir
extern

Definition at line 85 of file btrfs.c.

Referenced by read_registry(), and registry_load_volume_options().

◆ mount_no_trim

uint32_t mount_no_trim
extern

Definition at line 81 of file btrfs.c.

Referenced by read_registry(), and registry_load_volume_options().

◆ mount_nodatacow

uint32_t mount_nodatacow
extern

Definition at line 86 of file btrfs.c.

Referenced by read_registry(), and registry_load_volume_options().

◆ mount_readonly

uint32_t mount_readonly
extern

Definition at line 84 of file btrfs.c.

Referenced by read_registry(), and registry_load_volume_options().

◆ mount_skip_balance

uint32_t mount_skip_balance
extern

Definition at line 79 of file btrfs.c.

Referenced by read_registry(), and registry_load_volume_options().

◆ mount_zlib_level

uint32_t mount_zlib_level
extern

Definition at line 75 of file btrfs.c.

Referenced by read_registry(), and registry_load_volume_options().

◆ mount_zstd_level

uint32_t mount_zstd_level
extern

Definition at line 76 of file btrfs.c.

Referenced by read_registry(), and registry_load_volume_options().

◆ n

Definition at line 1030 of file btrfs_drv.h.

◆ no_pnp

uint32_t no_pnp
extern

Definition at line 87 of file btrfs.c.

Referenced by add_volume_device(), bus_pnp(), free_vol(), read_registry(), and remove_volume_child().

◆ PhysicalDeviceObject

◆ prealloc

◆ rollback

Definition at line 1365 of file btrfs_drv.h.

Referenced by __attribute__(), _Dispatch_type_(), add_data_reloc(), add_metadata_reloc(), add_metadata_reloc_parent(), add_rollback_space(), allocate_cache(), allocate_cache_chunk(), allocate_tree_extents(), balance_data_chunk(), balance_metadata_chunk(), check_for_orphans_root(), clear_free_space_cache(), create_stream(), data_reloc_add_tree_edr(), delete_fileref(), delete_fileref_fcb(), delete_reparse_point(), do_create_snapshot(), do_splits(), do_write(), do_write2(), drop_chunk(), drop_root(), drop_roots(), duplicate_extents(), file_create(), file_create2(), flush_changed_extent(), get_tree_new_address(), insert_cache_extent(), insert_extent_chunk(), insert_tree_extent(), insert_tree_extent_skinny(), load_stored_free_space_cache(), move_across_subvols(), open_file(), open_file2(), open_file3(), oplock_complete(), reduce_tree_extent(), remove_free_space_inode(), remove_root_extents(), rename_file_to_stream(), rename_stream(), rename_stream_to_file(), set_end_of_file_information(), set_link_information(), set_rename_information(), set_reparse_point(), set_reparse_point2(), set_symlink(), set_valid_data_length_information(), set_zero_data(), shared_tree_is_unique(), snapshot_tree_copy(), space_list_add(), space_list_add2(), space_list_subtract(), space_list_subtract2(), try_tree_amalgamate(), update_chunk_cache(), update_chunk_caches(), update_chunk_usage(), update_chunks(), update_root_root(), update_tree_extents(), update_tree_extents_recursive(), write_compressed(), write_metadata_items(), xsltTestCompMatch(), and zero_data().

◆ start_data