ReactOS 0.4.15-dev-8222-g9164419
fsctl.c File Reference
#include "btrfs_drv.h"
#include "btrfsioctl.h"
#include "crc32c.h"
#include <ntddstor.h>
#include <ntdddisk.h>
#include <sys/stat.h>
Include dependency graph for fsctl.c:

Go to the source code of this file.

Macros

#define FSCTL_CSV_CONTROL   CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 181, METHOD_BUFFERED, FILE_ANY_ACCESS)
 
#define FSCTL_QUERY_VOLUME_CONTAINER_STATE   CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 228, METHOD_BUFFERED, FILE_ANY_ACCESS)
 
#define DOTDOT   ".."
 
#define SEF_AVOID_PRIVILEGE_CHECK   0x08
 
#define SEF_SACL_AUTO_INHERIT   0x02
 

Functions

static void mark_subvol_dirty (device_extension *Vcb, root *r)
 
static NTSTATUS get_file_ids (PFILE_OBJECT FileObject, void *data, ULONG length)
 
static void get_uuid (BTRFS_UUID *uuid)
 
static NTSTATUS snapshot_tree_copy (device_extension *Vcb, uint64_t addr, root *subvol, uint64_t *newaddr, PIRP Irp, LIST_ENTRY *rollback)
 
void flush_subvol_fcbs (root *subvol)
 
static NTSTATUS do_create_snapshot (device_extension *Vcb, PFILE_OBJECT parent, fcb *subvol_fcb, PANSI_STRING utf8, PUNICODE_STRING name, bool readonly, PIRP Irp)
 
static NTSTATUS create_snapshot (device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG length, PIRP Irp)
 
static NTSTATUS create_subvol (device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG datalen, PIRP Irp)
 
static NTSTATUS get_inode_info (PFILE_OBJECT FileObject, void *data, ULONG length)
 
static NTSTATUS set_inode_info (PFILE_OBJECT FileObject, void *data, ULONG length, PIRP Irp)
 
static NTSTATUS get_devices (device_extension *Vcb, void *data, ULONG length)
 
static NTSTATUS get_usage (device_extension *Vcb, void *data, ULONG length, PIRP Irp)
 
static NTSTATUS is_volume_mounted (device_extension *Vcb, PIRP Irp)
 
static NTSTATUS fs_get_statistics (void *buffer, DWORD buflen, ULONG_PTR *retlen)
 
static NTSTATUS set_sparse (device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG length, PIRP Irp)
 
static NTSTATUS zero_data (device_extension *Vcb, fcb *fcb, uint64_t start, uint64_t length, PIRP Irp, LIST_ENTRY *rollback)
 
static NTSTATUS set_zero_data (device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG length, PIRP Irp)
 
static NTSTATUS query_ranges (PFILE_OBJECT FileObject, FILE_ALLOCATED_RANGE_BUFFER *inbuf, ULONG inbuflen, void *outbuf, ULONG outbuflen, ULONG_PTR *retlen)
 
static NTSTATUS get_object_id (PFILE_OBJECT FileObject, FILE_OBJECTID_BUFFER *buf, ULONG buflen, ULONG_PTR *retlen)
 
static void flush_fcb_caches (device_extension *Vcb)
 
static NTSTATUS lock_volume (device_extension *Vcb, PIRP Irp)
 
void do_unlock_volume (device_extension *Vcb)
 
static NTSTATUS unlock_volume (device_extension *Vcb, PIRP Irp)
 
static NTSTATUS invalidate_volumes (PIRP Irp)
 
static NTSTATUS is_volume_dirty (device_extension *Vcb, PIRP Irp)
 
static NTSTATUS get_compression (PIRP Irp)
 
static NTSTATUS set_compression (PIRP Irp)
 
static void update_volumes (device_extension *Vcb)
 
NTSTATUS dismount_volume (device_extension *Vcb, bool shutdown, PIRP Irp)
 
static NTSTATUS is_device_part_of_mounted_btrfs_raid (PDEVICE_OBJECT devobj, PFILE_OBJECT fileobj)
 
void trim_whole_device (device *dev)
 
static NTSTATUS add_device (device_extension *Vcb, PIRP Irp, KPROCESSOR_MODE processor_mode)
 
static NTSTATUS allow_extended_dasd_io (device_extension *Vcb, PFILE_OBJECT FileObject)
 
static NTSTATUS query_uuid (device_extension *Vcb, void *data, ULONG length)
 
static NTSTATUS reset_stats (device_extension *Vcb, void *data, ULONG length, KPROCESSOR_MODE processor_mode)
 
static NTSTATUS get_integrity_information (device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG datalen)
 
static NTSTATUS set_integrity_information (PFILE_OBJECT FileObject, void *data, ULONG datalen)
 
bool fcb_is_inline (fcb *fcb)
 
static NTSTATUS duplicate_extents (device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG datalen, PIRP Irp)
 
static NTSTATUS check_inode_used (_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *subvol, _In_ uint64_t inode, _In_ uint32_t hash, _In_opt_ PIRP Irp)
 
static NTSTATUS mknod (device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG datalen, PIRP Irp)
 
static NTSTATUS recvd_subvol (device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG datalen, KPROCESSOR_MODE processor_mode)
 
static NTSTATUS fsctl_get_xattrs (device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG datalen, KPROCESSOR_MODE processor_mode)
 
static NTSTATUS fsctl_set_xattr (device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG datalen, PIRP Irp)
 
static NTSTATUS reserve_subvol (device_extension *Vcb, PFILE_OBJECT FileObject, PIRP Irp)
 
static NTSTATUS get_subvol_path (device_extension *Vcb, uint64_t id, WCHAR *out, ULONG outlen, PIRP Irp)
 
static NTSTATUS find_subvol (device_extension *Vcb, void *in, ULONG inlen, void *out, ULONG outlen, PIRP Irp)
 
static NTSTATUS resize_device (device_extension *Vcb, void *data, ULONG len, PIRP Irp)
 
static NTSTATUS fsctl_oplock (device_extension *Vcb, PIRP *Pirp)
 
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)
 
static NTSTATUS add_csum_sparse_extents (device_extension *Vcb, uint64_t sparse_extents, uint8_t **ptr, bool found, void *hash_ptr)
 
static NTSTATUS get_csum_info (device_extension *Vcb, PFILE_OBJECT FileObject, btrfs_csum_info *buf, ULONG buflen, ULONG_PTR *retlen, KPROCESSOR_MODE processor_mode)
 
NTSTATUS fsctl_request (PDEVICE_OBJECT DeviceObject, PIRP *Pirp, uint32_t type)
 

Variables

LIST_ENTRY VcbList
 
ERESOURCE global_loading_lock
 
PDRIVER_OBJECT drvobj
 
tFsRtlCheckLockForOplockRequest fFsRtlCheckLockForOplockRequest
 
tFsRtlAreThereCurrentOrInProgressFileLocks fFsRtlAreThereCurrentOrInProgressFileLocks
 

Macro Definition Documentation

◆ DOTDOT

#define DOTDOT   ".."

Definition at line 35 of file fsctl.c.

◆ FSCTL_CSV_CONTROL

Definition at line 28 of file fsctl.c.

◆ FSCTL_QUERY_VOLUME_CONTAINER_STATE

#define FSCTL_QUERY_VOLUME_CONTAINER_STATE   CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 228, METHOD_BUFFERED, FILE_ANY_ACCESS)

Definition at line 32 of file fsctl.c.

◆ SEF_AVOID_PRIVILEGE_CHECK

#define SEF_AVOID_PRIVILEGE_CHECK   0x08

Definition at line 37 of file fsctl.c.

◆ SEF_SACL_AUTO_INHERIT

#define SEF_SACL_AUTO_INHERIT   0x02

Definition at line 39 of file fsctl.c.

Function Documentation

◆ add_csum_sparse_extents()

static NTSTATUS add_csum_sparse_extents ( device_extension Vcb,
uint64_t  sparse_extents,
uint8_t **  ptr,
bool  found,
void hash_ptr 
)
static

Definition at line 5148 of file fsctl.c.

5148 {
5149 if (!found) {
5150 uint8_t* sector = ExAllocatePoolWithTag(PagedPool, Vcb->superblock.sector_size, ALLOC_TAG);
5151
5152 if (!sector) {
5153 ERR("out of memory\n");
5155 }
5156
5157 memset(sector, 0, Vcb->superblock.sector_size);
5158
5159 get_sector_csum(Vcb, sector, hash_ptr);
5160
5162 }
5163
5164 switch (Vcb->superblock.csum_type) {
5165 case CSUM_TYPE_CRC32C: {
5166 uint32_t* csum = (uint32_t*)*ptr;
5167 uint32_t sparse_hash = *(uint32_t*)hash_ptr;
5168
5169 for (uint64_t i = 0; i < sparse_extents; i++) {
5170 csum[i] = sparse_hash;
5171 }
5172
5173 break;
5174 }
5175
5176 case CSUM_TYPE_XXHASH: {
5177 uint64_t* csum = (uint64_t*)*ptr;
5178 uint64_t sparse_hash = *(uint64_t*)hash_ptr;
5179
5180 for (uint64_t i = 0; i < sparse_extents; i++) {
5181 csum[i] = sparse_hash;
5182 }
5183
5184 break;
5185 }
5186
5187 case CSUM_TYPE_SHA256:
5188 case CSUM_TYPE_BLAKE2: {
5189 uint8_t* csum = (uint8_t*)*ptr;
5190
5191 for (uint64_t i = 0; i < sparse_extents; i++) {
5192 memcpy(csum, hash_ptr, 32);
5193 csum += 32;
5194 }
5195
5196 break;
5197 }
5198
5199 default:
5200 ERR("unrecognized hash type %x\n", Vcb->superblock.csum_type);
5201 return STATUS_INTERNAL_ERROR;
5202 }
5203
5204 *ptr += sparse_extents * Vcb->csum_size;
5205
5206 return STATUS_SUCCESS;
5207}
#define ERR(fmt,...)
Definition: debug.h:113
#define ALLOC_TAG
Definition: btrfs_drv.h:87
void get_sector_csum(device_extension *Vcb, void *buf, void *csum)
Definition: read.c:182
UINT32 uint32_t
Definition: types.h:75
UINT64 uint64_t
Definition: types.h:77
#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
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define PagedPool
Definition: env_spec_w32.h:308
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
uint32_t sector
Definition: isohybrid.c:61
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static PVOID ptr
Definition: dispmode.c:27
BYTE uint8_t
Definition: msvideo1.c:66
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define Vcb
Definition: cdprocs.h:1415
#define memset(x, y, z)
Definition: compat.h:39
#define STATUS_SUCCESS
Definition: shellext.h:65
Definition: ffs.h:52
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158

Referenced by get_csum_info().

◆ add_device()

static NTSTATUS add_device ( device_extension Vcb,
PIRP  Irp,
KPROCESSOR_MODE  processor_mode 
)
static

Definition at line 2735 of file fsctl.c.

2735 {
2738 PFILE_OBJECT fileobj, mountmgrfo;
2740 HANDLE h;
2741 LIST_ENTRY* le;
2742 device* dev;
2743 DEV_ITEM* di;
2744 uint64_t dev_id, size;
2745 uint8_t* mb;
2746 uint64_t* stats;
2747 UNICODE_STRING mmdevpath, pnp_name, pnp_name2;
2748 volume_child* vc;
2750 KEY searchkey;
2754 pdo_device_extension* pdode;
2755 const GUID* pnp_guid;
2757
2758 pnp_name.Buffer = NULL;
2759
2760 if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), processor_mode))
2762
2763 if (!Vcb->vde) {
2764 WARN("not allowing second device to be added to non-PNP device\n");
2765 return STATUS_NOT_SUPPORTED;
2766 }
2767
2768 if (Vcb->readonly) // FIXME - handle adding R/W device to seeding device
2770
2771#if defined(_WIN64)
2772 if (IoIs32bitProcess(Irp)) {
2773 if (IrpSp->Parameters.FileSystemControl.InputBufferLength != sizeof(uint32_t))
2775
2776 h = (HANDLE)LongToHandle((*(uint32_t*)Irp->AssociatedIrp.SystemBuffer));
2777 } else {
2778#endif
2779 if (IrpSp->Parameters.FileSystemControl.InputBufferLength != sizeof(HANDLE))
2781
2782 h = *(PHANDLE)Irp->AssociatedIrp.SystemBuffer;
2783#if defined(_WIN64)
2784 }
2785#endif
2786
2787 Status = ObReferenceObjectByHandle(h, 0, *IoFileObjectType, Irp->RequestorMode, (void**)&fileobj, NULL);
2788
2789 if (!NT_SUCCESS(Status)) {
2790 ERR("ObReferenceObjectByHandle returned %08lx\n", Status);
2791 return Status;
2792 }
2793
2794 DeviceObject = fileobj->DeviceObject;
2795
2796 Status = get_device_pnp_name(DeviceObject, &pnp_name, &pnp_guid);
2797 if (!NT_SUCCESS(Status)) {
2798 ERR("get_device_pnp_name returned %08lx\n", Status);
2799 ObDereferenceObject(fileobj);
2800 return Status;
2801 }
2802
2803 // If this is a disk, we have been handed the PDO, so need to go up to find something we can use
2804 if (RtlCompareMemory(pnp_guid, &GUID_DEVINTERFACE_DISK, sizeof(GUID)) == sizeof(GUID) && DeviceObject->AttachedDevice)
2805 DeviceObject = DeviceObject->AttachedDevice;
2806
2808 if (!NT_SUCCESS(Status)) {
2809 ERR("IOCTL_DISK_IS_WRITABLE returned %08lx\n", Status);
2810 ObDereferenceObject(fileobj);
2811 return Status;
2812 }
2813
2815 if (!NT_SUCCESS(Status)) {
2816 ERR("is_device_part_of_mounted_btrfs_raid returned %08lx\n", Status);
2817 ObDereferenceObject(fileobj);
2818 return Status;
2819 }
2820
2821 // if disk, check it has no partitions
2822 if (RtlCompareMemory(pnp_guid, &GUID_DEVINTERFACE_DISK, sizeof(GUID)) == sizeof(GUID)) {
2823 ULONG dlisize;
2824 DRIVE_LAYOUT_INFORMATION_EX* dli = NULL;
2825
2826 dlisize = 0;
2827
2828 do {
2829 dlisize += 1024;
2830
2831 if (dli)
2832 ExFreePool(dli);
2833
2834 dli = ExAllocatePoolWithTag(PagedPool, dlisize, ALLOC_TAG);
2835 if (!dli) {
2836 ERR("out of memory\n");
2838 goto end2;
2839 }
2840
2842 } while (Status == STATUS_BUFFER_TOO_SMALL);
2843
2844 if (NT_SUCCESS(Status) && dli->PartitionCount > 0) {
2845 ExFreePool(dli);
2846 ERR("not adding disk which has partitions\n");
2848 goto end2;
2849 }
2850
2851 ExFreePool(dli);
2852 }
2853
2855 &sdn, sizeof(STORAGE_DEVICE_NUMBER), true, NULL);
2856 if (NT_SUCCESS(Status)) {
2857 if (sdn.DeviceType != FILE_DEVICE_DISK) { // FIXME - accept floppies and CDs?
2858 WARN("device was not disk\n");
2859 ObDereferenceObject(fileobj);
2861 }
2862 } else {
2863 sdn.DeviceNumber = 0xffffffff;
2864 sdn.PartitionNumber = 0xffffffff;
2865 }
2866
2868 &gli, sizeof(gli), true, NULL);
2869 if (!NT_SUCCESS(Status)) {
2870 ERR("error reading length information: %08lx\n", Status);
2871 ObDereferenceObject(fileobj);
2872 return Status;
2873 }
2874
2875 size = gli.Length.QuadPart;
2876
2877 if (size < 0x100000) {
2878 ERR("device was not large enough to hold FS (%I64x bytes, need at least 1 MB)\n", size);
2879 ObDereferenceObject(fileobj);
2880 return STATUS_INTERNAL_ERROR;
2881 }
2882
2883 volume_removal(&pnp_name);
2884
2885 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
2886
2887 if (Vcb->need_write)
2888 Status = do_write(Vcb, Irp);
2889 else
2891
2892 free_trees(Vcb);
2893
2894 if (!NT_SUCCESS(Status)) {
2895 ERR("do_write returned %08lx\n", Status);
2896 goto end;
2897 }
2898
2900 if (!dev) {
2901 ERR("out of memory\n");
2903 goto end;
2904 }
2905
2906 RtlZeroMemory(dev, sizeof(device));
2907
2908 dev->devobj = DeviceObject;
2909 dev->fileobj = fileobj;
2910 dev->seeding = false;
2911 init_device(Vcb, dev, true);
2912
2913 InitializeListHead(&dev->space);
2914
2915 if (size > 0x100000) { // add disk hole - the first MB is marked as used
2916 Status = add_space_entry(&dev->space, NULL, 0x100000, size - 0x100000);
2917 if (!NT_SUCCESS(Status)) {
2918 ERR("add_space_entry returned %08lx\n", Status);
2919 goto end;
2920 }
2921 }
2922
2923 dev_id = 0;
2924
2925 le = Vcb->devices.Flink;
2926 while (le != &Vcb->devices) {
2928
2929 if (dev2->devitem.dev_id > dev_id)
2930 dev_id = dev2->devitem.dev_id;
2931
2932 le = le->Flink;
2933 }
2934
2935 dev_id++;
2936
2937 dev->devitem.dev_id = dev_id;
2938 dev->devitem.num_bytes = size;
2939 dev->devitem.bytes_used = 0;
2940 dev->devitem.optimal_io_align = Vcb->superblock.sector_size;
2941 dev->devitem.optimal_io_width = Vcb->superblock.sector_size;
2942 dev->devitem.minimal_io_size = Vcb->superblock.sector_size;
2943 dev->devitem.type = 0;
2944 dev->devitem.generation = 0;
2945 dev->devitem.start_offset = 0;
2946 dev->devitem.dev_group = 0;
2947 dev->devitem.seek_speed = 0;
2948 dev->devitem.bandwidth = 0;
2949 get_uuid(&dev->devitem.device_uuid);
2950 dev->devitem.fs_uuid = Vcb->superblock.uuid;
2951
2953 if (!di) {
2954 ERR("out of memory\n");
2955 goto end;
2956 }
2957
2958 RtlCopyMemory(di, &dev->devitem, sizeof(DEV_ITEM));
2959
2960 Status = insert_tree_item(Vcb, Vcb->chunk_root, 1, TYPE_DEV_ITEM, di->dev_id, di, sizeof(DEV_ITEM), NULL, Irp);
2961 if (!NT_SUCCESS(Status)) {
2962 ERR("insert_tree_item returned %08lx\n", Status);
2963 ExFreePool(di);
2964 goto end;
2965 }
2966
2967 // add stats entry to dev tree
2968 stats = ExAllocatePoolWithTag(PagedPool, sizeof(uint64_t) * 5, ALLOC_TAG);
2969 if (!stats) {
2970 ERR("out of memory\n");
2972 goto end;
2973 }
2974
2975 RtlZeroMemory(stats, sizeof(uint64_t) * 5);
2976
2977 searchkey.obj_id = 0;
2978 searchkey.obj_type = TYPE_DEV_STATS;
2979 searchkey.offset = di->dev_id;
2980
2981 Status = find_item(Vcb, Vcb->dev_root, &tp, &searchkey, false, Irp);
2982 if (!NT_SUCCESS(Status)) {
2983 ERR("error - find_item returned %08lx\n", Status);
2984 ExFreePool(stats);
2985 goto end;
2986 }
2987
2988 if (!keycmp(tp.item->key, searchkey)) {
2990 if (!NT_SUCCESS(Status)) {
2991 ERR("delete_tree_item returned %08lx\n", Status);
2992 ExFreePool(stats);
2993 goto end;
2994 }
2995 }
2996
2997 Status = insert_tree_item(Vcb, Vcb->dev_root, 0, TYPE_DEV_STATS, di->dev_id, stats, sizeof(uint64_t) * 5, NULL, Irp);
2998 if (!NT_SUCCESS(Status)) {
2999 ERR("insert_tree_item returned %08lx\n", Status);
3000 ExFreePool(stats);
3001 goto end;
3002 }
3003
3004 if (dev->trim && !dev->readonly && !Vcb->options.no_trim)
3006
3007 // We clear the first megabyte of the device, so Windows doesn't identify it as another FS
3008 mb = ExAllocatePoolWithTag(PagedPool, 0x100000, ALLOC_TAG);
3009 if (!mb) {
3010 ERR("out of memory\n");
3012 goto end;
3013 }
3014
3015 RtlZeroMemory(mb, 0x100000);
3016
3017 Status = write_data_phys(DeviceObject, fileobj, 0, mb, 0x100000);
3018 if (!NT_SUCCESS(Status)) {
3019 ERR("write_data_phys returned %08lx\n", Status);
3020 ExFreePool(mb);
3021 goto end;
3022 }
3023
3024 ExFreePool(mb);
3025
3026 vde = Vcb->vde;
3027 pdode = vde->pdode;
3028
3030 if (!vc) {
3031 ERR("out of memory\n");
3033 goto end;
3034 }
3035
3036 vc->uuid = dev->devitem.device_uuid;
3037 vc->devid = dev_id;
3038 vc->generation = Vcb->superblock.generation;
3039 vc->devobj = DeviceObject;
3040 vc->fileobj = fileobj;
3042 vc->boot_volume = false;
3043
3045 drvobj, pnp_removal, vde->pdode, &vc->notification_entry);
3046 if (!NT_SUCCESS(Status))
3047 WARN("IoRegisterPlugPlayNotification returned %08lx\n", Status);
3048
3049 pnp_name2 = pnp_name;
3050
3051 if (pnp_name.Length > 4 * sizeof(WCHAR) && pnp_name.Buffer[0] == '\\' && (pnp_name.Buffer[1] == '\\' || pnp_name.Buffer[1] == '?') &&
3052 pnp_name.Buffer[2] == '?' && pnp_name.Buffer[3] == '\\') {
3053 pnp_name2.Buffer = &pnp_name2.Buffer[3];
3054 pnp_name2.Length -= 3 * sizeof(WCHAR);
3055 pnp_name2.MaximumLength -= 3 * sizeof(WCHAR);
3056 }
3057
3058 vc->pnp_name.Length = vc->pnp_name.MaximumLength = pnp_name2.Length;
3059
3060 if (pnp_name2.Length == 0)
3061 vc->pnp_name.Buffer = NULL;
3062 else {
3064 if (!vc->pnp_name.Buffer) {
3065 ERR("out of memory\n");
3067 goto end;
3068 }
3069
3070 RtlCopyMemory(vc->pnp_name.Buffer, pnp_name2.Buffer, pnp_name2.Length);
3071 }
3072
3073 vc->size = size;
3074 vc->seeding = false;
3075 vc->disk_num = sdn.DeviceNumber;
3076 vc->part_num = sdn.PartitionNumber;
3077 vc->had_drive_letter = false;
3078
3080 InsertTailList(&pdode->children, &vc->list_entry);
3081 pdode->num_children++;
3082 pdode->children_loaded++;
3084
3086 Status = IoGetDeviceObjectPointer(&mmdevpath, FILE_READ_ATTRIBUTES, &mountmgrfo, &mountmgr);
3087 if (!NT_SUCCESS(Status))
3088 ERR("IoGetDeviceObjectPointer returned %08lx\n", Status);
3089 else {
3090 Status = remove_drive_letter(mountmgr, &pnp_name);
3092 WARN("remove_drive_letter returned %08lx\n", Status);
3093
3095
3096 ObDereferenceObject(mountmgrfo);
3097 }
3098
3099 Vcb->superblock.num_devices++;
3100 Vcb->superblock.total_bytes += size;
3101 Vcb->devices_loaded++;
3102 InsertTailList(&Vcb->devices, &dev->list_entry);
3103
3104 // FIXME - send notification that volume size has increased
3105
3106 ObReferenceObject(DeviceObject); // for Vcb
3107
3108 Status = do_write(Vcb, Irp);
3109 if (!NT_SUCCESS(Status))
3110 ERR("do_write returned %08lx\n", Status);
3111
3112 ObReferenceObject(fileobj);
3113
3114end:
3115 free_trees(Vcb);
3116
3117 ExReleaseResourceLite(&Vcb->tree_lock);
3118
3119end2:
3120 ObDereferenceObject(fileobj);
3121
3122 if (pnp_name.Buffer)
3123 ExFreePool(pnp_name.Buffer);
3124
3125 if (NT_SUCCESS(Status))
3127
3128 return Status;
3129}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
#define STATUS_PRIVILEGE_NOT_HELD
Definition: DriverTester.h:9
LONG NTSTATUS
Definition: precomp.h:26
#define LongToHandle(h)
Definition: basetsd.h:82
#define WARN(fmt,...)
Definition: debug.h:115
PDRIVER_OBJECT drvobj
Definition: btrfs.c:65
static void get_uuid(BTRFS_UUID *uuid)
Definition: fsctl.c:73
static NTSTATUS is_device_part_of_mounted_btrfs_raid(PDEVICE_OBJECT devobj, PFILE_OBJECT fileobj)
Definition: fsctl.c:2637
void trim_whole_device(device *dev)
Definition: fsctl.c:2716
#define keycmp(key1, key2)
Definition: btrfs_drv.h:1016
NTSTATUS add_space_entry(LIST_ENTRY *list, LIST_ENTRY *list_size, uint64_t offset, uint64_t size)
Definition: free-space.c:190
void void void NTSTATUS void NTSTATUS NTSTATUS remove_drive_letter(PDEVICE_OBJECT mountmgr, PUNICODE_STRING devpath)
Definition: search.c:407
NTSTATUS do_write(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7877
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
void volume_removal(PUNICODE_STRING devpath)
Definition: search.c:795
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
#define IOCTL_DISK_IS_WRITABLE
Definition: cdrw_usr.h:172
_In_ PIRP Irp
Definition: csq.h:116
#define NULL
Definition: types.h:112
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
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
NTSTATUS get_device_pnp_name(_In_ PDEVICE_OBJECT DeviceObject, _Out_ PUNICODE_STRING pnp_name, _Out_ const GUID **guid)
Definition: btrfs.c:4233
void init_device(_In_ device_extension *Vcb, _Inout_ device *dev, _In_ bool get_nums)
Definition: btrfs.c:3416
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
#define TYPE_DEV_ITEM
Definition: btrfs.h:47
#define TYPE_DEV_STATS
Definition: btrfs.h:50
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
#define InsertTailList(ListHead, Entry)
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
#define ExAcquireResourceExclusiveLite(res, wait)
Definition: env_spec_w32.h:615
#define NonPagedPool
Definition: env_spec_w32.h:307
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define IOCTL_DISK_GET_DRIVE_LAYOUT_EX
Definition: ntddk_ex.h:207
#define FSRTL_VOLUME_CHANGE_SIZE
Definition: fsrtltypes.h:101
Status
Definition: gdiplustypes.h:25
GLuint GLuint end
Definition: gl.h:1545
GLsizeiptr size
Definition: glext.h:5919
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
POBJECT_TYPE IoFileObjectType
Definition: iomgr.c:36
#define IOCTL_DISK_GET_LENGTH_INFO
Definition: imports.h:192
#define MOUNTMGR_DEVICE_NAME
Definition: imports.h:76
#define SE_MANAGE_VOLUME_PRIVILEGE
Definition: security.c:682
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define IOCTL_STORAGE_GET_DEVICE_NUMBER
Definition: ntddstor.h:143
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1822
NTSTATUS NTAPI FsRtlNotifyVolumeEvent(IN PFILE_OBJECT FileObject, IN ULONG EventCode)
Definition: pnp.c:38
NTSTATUS NTAPI IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName, IN ACCESS_MASK DesiredAccess, OUT PFILE_OBJECT *FileObject, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1435
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
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
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
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
#define FILE_DEVICE_DISK
Definition: winioctl.h:52
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70
#define STATUS_NOT_FOUND
Definition: shellext.h:72
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
uint64_t dev_id
Definition: btrfs.h:178
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
LARGE_INTEGER Length
Definition: imports.h:232
struct _IO_STACK_LOCATION::@3991::@4006 FileSystemControl
union _IO_STACK_LOCATION::@1573 Parameters
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
DEVICE_TYPE DeviceType
Definition: ntddstor.h:324
USHORT MaximumLength
Definition: env_spec_w32.h:370
struct pdo_device_extension * pdode
Definition: btrfs_drv.h:878
uint64_t dev_id
Definition: devices.h:37
DEV_ITEM devitem
Definition: btrfs_drv.h:527
Definition: list.h:27
ERESOURCE child_lock
Definition: btrfs_drv.h:896
uint64_t children_loaded
Definition: btrfs_drv.h:895
LIST_ENTRY children
Definition: btrfs_drv.h:897
uint64_t num_children
Definition: btrfs_drv.h:894
tree_data * item
Definition: btrfs_drv.h:509
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
PVOID HANDLE
Definition: typedefs.h:73
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
LONGLONG QuadPart
Definition: typedefs.h:114
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
@ EventCategoryTargetDeviceChange
Definition: iotypes.h:1227
* PFILE_OBJECT
Definition: iotypes.h:1998
#define ObDereferenceObject
Definition: obfuncs.h:203
#define ObReferenceObject
Definition: obfuncs.h:204
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by fsctl_request().

◆ allow_extended_dasd_io()

static NTSTATUS allow_extended_dasd_io ( device_extension Vcb,
PFILE_OBJECT  FileObject 
)
static

Definition at line 3131 of file fsctl.c.

3131 {
3132 fcb* fcb;
3133 ccb* ccb;
3134
3135 TRACE("FSCTL_ALLOW_EXTENDED_DASD_IO\n");
3136
3137 if (!FileObject)
3139
3140 fcb = FileObject->FsContext;
3141 ccb = FileObject->FsContext2;
3142
3143 if (!fcb)
3145
3146 if (fcb != Vcb->volume_fcb)
3148
3149 if (!ccb)
3151
3153
3154 return STATUS_SUCCESS;
3155}
struct _fcb fcb
Definition: btrfs_drv.h:1364
struct _ccb ccb
#define TRACE(s)
Definition: solgame.cpp:4
bool allow_extended_dasd_io
Definition: btrfs_drv.h:380
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550

Referenced by fsctl_request().

◆ check_inode_used()

static NTSTATUS check_inode_used ( _In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension Vcb,
_In_ root subvol,
_In_ uint64_t  inode,
_In_ uint32_t  hash,
_In_opt_ PIRP  Irp 
)
static

Definition at line 3701 of file fsctl.c.

3702 {
3703 KEY searchkey;
3706 uint8_t c = hash >> 24;
3707
3708 if (subvol->fcbs_ptrs[c]) {
3709 LIST_ENTRY* le = subvol->fcbs_ptrs[c];
3710
3711 while (le != &subvol->fcbs) {
3712 struct _fcb* fcb2 = CONTAINING_RECORD(le, struct _fcb, list_entry);
3713
3714 if (fcb2->inode == inode)
3715 return STATUS_SUCCESS;
3716 else if (fcb2->hash > hash)
3717 break;
3718
3719 le = le->Flink;
3720 }
3721 }
3722
3723 searchkey.obj_id = inode;
3724 searchkey.obj_type = TYPE_INODE_ITEM;
3725 searchkey.offset = 0xffffffffffffffff;
3726
3727 Status = find_item(Vcb, subvol, &tp, &searchkey, false, Irp);
3728 if (!NT_SUCCESS(Status)) {
3729 ERR("find_item returned %08lx\n", Status);
3730 return Status;
3731 }
3732
3733 if (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == searchkey.obj_type)
3734 return STATUS_SUCCESS;
3735
3736 return STATUS_NOT_FOUND;
3737}
#define TYPE_INODE_ITEM
Definition: btrfs.h:23
const GLubyte * c
Definition: glext.h:8905
#define c
Definition: ke_i.h:80
uint64_t inode
Definition: btrfs_drv.h:289
struct _root * subvol
Definition: btrfs_drv.h:288
uint32_t hash
Definition: btrfs_drv.h:290
Definition: _hash_fun.h:40
Definition: fs.h:78

Referenced by mknod().

◆ create_snapshot()

static NTSTATUS create_snapshot ( device_extension Vcb,
PFILE_OBJECT  FileObject,
void data,
ULONG  length,
PIRP  Irp 
)
static

Definition at line 521 of file fsctl.c.

521 {
522 PFILE_OBJECT subvol_obj;
525 fcb* subvol_fcb;
526 HANDLE subvolh;
527 bool readonly, posix;
528 ANSI_STRING utf8;
529 UNICODE_STRING nameus;
530 ULONG len;
531 fcb* fcb;
532 ccb* ccb;
533 file_ref *fileref, *fr2;
534
535#if defined(_WIN64)
536 if (IoIs32bitProcess(Irp)) {
538
541
544
545 subvolh = Handle32ToHandle(bcs32->subvol);
546
547 nameus.Buffer = bcs32->name;
548 nameus.Length = nameus.MaximumLength = bcs32->namelen;
549
550 readonly = bcs32->readonly;
551 posix = bcs32->posix;
552 } else {
553#endif
556
559
560 subvolh = bcs->subvol;
561
562 nameus.Buffer = bcs->name;
563 nameus.Length = nameus.MaximumLength = bcs->namelen;
564
565 readonly = bcs->readonly;
566 posix = bcs->posix;
567#if defined(_WIN64)
568 }
569#endif
570
571 if (!subvolh)
573
574 if (!FileObject || !FileObject->FsContext)
576
577 fcb = FileObject->FsContext;
578 ccb = FileObject->FsContext2;
579
580 if (!fcb || !ccb || fcb->type != BTRFS_TYPE_DIRECTORY)
582
583 fileref = ccb->fileref;
584
585 if (!fileref) {
586 ERR("fileref was NULL\n");
588 }
589
590 if (!(ccb->access & FILE_ADD_SUBDIRECTORY)) {
591 WARN("insufficient privileges\n");
593 }
594
595 if (Vcb->readonly)
597
600
601 Status = check_file_name_valid(&nameus, posix, false);
602 if (!NT_SUCCESS(Status))
603 return Status;
604
605 utf8.Buffer = NULL;
606
607 Status = utf16_to_utf8(NULL, 0, &len, nameus.Buffer, nameus.Length);
608 if (!NT_SUCCESS(Status)) {
609 ERR("utf16_to_utf8 failed with error %08lx\n", Status);
610 return Status;
611 }
612
613 if (len == 0) {
614 ERR("utf16_to_utf8 returned a length of 0\n");
616 }
617
618 if (len > 0xffff) {
619 ERR("len was too long\n");
621 }
622
623 utf8.MaximumLength = utf8.Length = (USHORT)len;
625
626 if (!utf8.Buffer) {
627 ERR("out of memory\n");
629 }
630
631 Status = utf16_to_utf8(utf8.Buffer, len, &len, nameus.Buffer, nameus.Length);
632 if (!NT_SUCCESS(Status)) {
633 ERR("utf16_to_utf8 failed with error %08lx\n", Status);
634 goto end2;
635 }
636
637 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
638
639 // no need for fcb_lock as we have tree_lock exclusively
640 Status = open_fileref(fcb->Vcb, &fr2, &nameus, fileref, false, NULL, NULL, PagedPool, ccb->case_sensitive || posix, Irp);
641
642 if (NT_SUCCESS(Status)) {
643 if (!fr2->deleted) {
644 WARN("file already exists\n");
645 free_fileref(fr2);
647 goto end3;
648 } else
649 free_fileref(fr2);
651 ERR("open_fileref returned %08lx\n", Status);
652 goto end3;
653 }
654
655 Status = ObReferenceObjectByHandle(subvolh, 0, *IoFileObjectType, Irp->RequestorMode, (void**)&subvol_obj, NULL);
656 if (!NT_SUCCESS(Status)) {
657 ERR("ObReferenceObjectByHandle returned %08lx\n", Status);
658 goto end3;
659 }
660
661 if (subvol_obj->DeviceObject != FileObject->DeviceObject) {
663 goto end;
664 }
665
666 subvol_fcb = subvol_obj->FsContext;
667 if (!subvol_fcb) {
669 goto end;
670 }
671
672 if (subvol_fcb->inode != subvol_fcb->subvol->root_item.objid) {
673 WARN("handle inode was %I64x, expected %I64x\n", subvol_fcb->inode, subvol_fcb->subvol->root_item.objid);
675 goto end;
676 }
677
678 ccb = subvol_obj->FsContext2;
679
680 if (!ccb) {
682 goto end;
683 }
684
685 if (!(ccb->access & FILE_TRAVERSE)) {
686 WARN("insufficient privileges\n");
688 goto end;
689 }
690
691 if (fcb == Vcb->dummy_fcb) {
693 goto end;
694 }
695
696 // clear unique flag on extents of open files in subvol
697 if (!IsListEmpty(&subvol_fcb->subvol->fcbs)) {
698 LIST_ENTRY* le = subvol_fcb->subvol->fcbs.Flink;
699
700 while (le != &subvol_fcb->subvol->fcbs) {
701 struct _fcb* openfcb = CONTAINING_RECORD(le, struct _fcb, list_entry);
702 LIST_ENTRY* le2;
703
704 le2 = openfcb->extents.Flink;
705
706 while (le2 != &openfcb->extents) {
708
709 ext->unique = false;
710
711 le2 = le2->Flink;
712 }
713
714 le = le->Flink;
715 }
716 }
717
718 Status = do_create_snapshot(Vcb, FileObject, subvol_fcb, &utf8, &nameus, readonly, Irp);
719
720 if (NT_SUCCESS(Status)) {
721 file_ref* fr;
722
723 Status = open_fileref(Vcb, &fr, &nameus, fileref, false, NULL, NULL, PagedPool, false, Irp);
724
725 if (!NT_SUCCESS(Status)) {
726 ERR("open_fileref returned %08lx\n", Status);
728 } else {
730 free_fileref(fr);
731 }
732 }
733
734end:
735 ObDereferenceObject(subvol_obj);
736
737end3:
738 ExReleaseResourceLite(&Vcb->tree_lock);
739
740end2:
741 ExFreePool(utf8.Buffer);
742
743 return Status;
744}
static NTSTATUS do_create_snapshot(device_extension *Vcb, PFILE_OBJECT parent, fcb *subvol_fcb, PANSI_STRING utf8, PUNICODE_STRING name, bool readonly, PIRP Irp)
Definition: fsctl.c:260
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: create.c:1690
static __inline bool is_subvol_readonly(root *r, PIRP Irp)
Definition: btrfs_drv.h:1033
static string utf16_to_utf8(const wstring_view &utf16)
Definition: main.cpp:670
static const WCHAR *const ext[]
Definition: module.c:53
void free_fileref(_Inout_ file_ref *fr)
Definition: btrfs.c:1856
NTSTATUS check_file_name_valid(_In_ PUNICODE_STRING us, _In_ bool posix, _In_ bool stream)
Definition: btrfs.c:5797
void send_notification_fileref(_In_ file_ref *fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream)
Definition: btrfs.c:1517
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLenum GLsizei len
Definition: glext.h:6722
#define FILE_TRAVERSE
Definition: nt_native.h:643
#define FILE_ADD_SUBDIRECTORY
Definition: nt_native.h:635
unsigned short USHORT
Definition: pedump.c:61
#define offsetof(TYPE, MEMBER)
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:86
USHORT MaximumLength
Definition: env_spec_w32.h:377
ACCESS_MASK access
Definition: btrfs_drv.h:382
file_ref * fileref
Definition: btrfs_drv.h:383
bool case_sensitive
Definition: btrfs_drv.h:386
struct _file_ref * fileref
Definition: btrfs_drv.h:305
LIST_ENTRY extents
Definition: btrfs_drv.h:300
uint8_t type
Definition: btrfs_drv.h:291
struct _device_extension * Vcb
Definition: btrfs_drv.h:287
bool deleted
Definition: btrfs_drv.h:347
void *POINTER_32 subvol
Definition: btrfsioctl.h:57
Definition: name.c:39
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
#define FILE_ACTION_ADDED
#define FILE_NOTIFY_CHANGE_DIR_NAME

Referenced by fsctl_request().

◆ create_subvol()

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

Definition at line 746 of file fsctl.c.

746 {
748 fcb *fcb, *rootfcb = NULL;
749 ccb* ccb;
750 file_ref* fileref;
752 uint64_t id;
753 root* r = NULL;
756 ULONG len;
757 uint16_t irsize;
758 UNICODE_STRING nameus;
759 ANSI_STRING utf8;
760 INODE_REF* ir;
761 KEY searchkey;
764 PSID owner;
765 BOOLEAN defaulted;
766 uint64_t* root_num;
767 file_ref *fr = NULL, *fr2;
768 dir_child* dc = NULL;
769
770 fcb = FileObject->FsContext;
771 if (!fcb) {
772 ERR("error - fcb was NULL\n");
774 }
775
776 ccb = FileObject->FsContext2;
777 if (!ccb) {
778 ERR("error - ccb was NULL\n");
780 }
781
782 fileref = ccb->fileref;
783
784 if (fcb->type != BTRFS_TYPE_DIRECTORY) {
785 ERR("parent FCB was not a directory\n");
787 }
788
789 if (!fileref) {
790 ERR("fileref was NULL\n");
792 }
793
794 if (fileref->deleted || fcb->deleted) {
795 ERR("parent has been deleted\n");
796 return STATUS_FILE_DELETED;
797 }
798
799 if (!(ccb->access & FILE_ADD_SUBDIRECTORY)) {
800 WARN("insufficient privileges\n");
802 }
803
804 if (Vcb->readonly)
806
809
810 if (fcb == Vcb->dummy_fcb)
812
813 if (!data || datalen < sizeof(btrfs_create_subvol))
815
817
820
821 nameus.Length = nameus.MaximumLength = bcs->namelen;
822 nameus.Buffer = bcs->name;
823
824 Status = check_file_name_valid(&nameus, bcs->posix, false);
825 if (!NT_SUCCESS(Status))
826 return Status;
827
828 utf8.Buffer = NULL;
829
830 Status = utf16_to_utf8(NULL, 0, &len, nameus.Buffer, nameus.Length);
831 if (!NT_SUCCESS(Status)) {
832 ERR("utf16_to_utf8 failed with error %08lx\n", Status);
833 return Status;
834 }
835
836 if (len == 0) {
837 ERR("utf16_to_utf8 returned a length of 0\n");
839 }
840
841 if (len > 0xffff) {
842 ERR("len was too long\n");
844 }
845
846 utf8.MaximumLength = utf8.Length = (USHORT)len;
848
849 if (!utf8.Buffer) {
850 ERR("out of memory\n");
852 }
853
854 Status = utf16_to_utf8(utf8.Buffer, len, &len, nameus.Buffer, nameus.Length);
855 if (!NT_SUCCESS(Status)) {
856 ERR("utf16_to_utf8 failed with error %08lx\n", Status);
857 goto end2;
858 }
859
860 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
861
864
865 // no need for fcb_lock as we have tree_lock exclusively
866 Status = open_fileref(fcb->Vcb, &fr2, &nameus, fileref, false, NULL, NULL, PagedPool, ccb->case_sensitive || bcs->posix, Irp);
867
868 if (NT_SUCCESS(Status)) {
869 if (!fr2->deleted) {
870 WARN("file already exists\n");
871 free_fileref(fr2);
873 goto end;
874 } else
875 free_fileref(fr2);
877 ERR("open_fileref returned %08lx\n", Status);
878 goto end;
879 }
880
881 id = InterlockedIncrement64(&Vcb->root_root->lastinode);
882 Status = create_root(Vcb, id, &r, false, 0, Irp);
883
884 if (!NT_SUCCESS(Status)) {
885 ERR("create_root returned %08lx\n", Status);
886 goto end;
887 }
888
889 TRACE("created root %I64x\n", id);
890
891 if (!Vcb->uuid_root) {
892 root* uuid_root;
893
894 TRACE("uuid root doesn't exist, creating it\n");
895
896 Status = create_root(Vcb, BTRFS_ROOT_UUID, &uuid_root, false, 0, Irp);
897
898 if (!NT_SUCCESS(Status)) {
899 ERR("create_root returned %08lx\n", Status);
900 goto end;
901 }
902
903 Vcb->uuid_root = uuid_root;
904 }
905
907 if (!root_num) {
908 ERR("out of memory\n");
910 goto end;
911 }
912
913 tp.tree = NULL;
914
915 do {
916 get_uuid(&r->root_item.uuid);
917
918 RtlCopyMemory(&searchkey.obj_id, &r->root_item.uuid, sizeof(uint64_t));
919 searchkey.obj_type = TYPE_SUBVOL_UUID;
920 RtlCopyMemory(&searchkey.offset, &r->root_item.uuid.uuid[sizeof(uint64_t)], sizeof(uint64_t));
921
922 Status = find_item(Vcb, Vcb->uuid_root, &tp, &searchkey, false, Irp);
923 } while (NT_SUCCESS(Status) && !keycmp(searchkey, tp.item->key));
924
925 *root_num = r->id;
926
927 Status = insert_tree_item(Vcb, Vcb->uuid_root, searchkey.obj_id, searchkey.obj_type, searchkey.offset, root_num, sizeof(uint64_t), NULL, Irp);
928 if (!NT_SUCCESS(Status)) {
929 ERR("insert_tree_item returned %08lx\n", Status);
930 ExFreePool(root_num);
931 goto end;
932 }
933
934 r->root_item.inode.generation = 1;
935 r->root_item.inode.st_size = 3;
936 r->root_item.inode.st_blocks = Vcb->superblock.node_size;
937 r->root_item.inode.st_nlink = 1;
938 r->root_item.inode.st_mode = __S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; // 40755
939 r->root_item.inode.flags = 0x80000000; // FIXME - find out what these mean
940 r->root_item.inode.flags_ro = 0xffffffff; // FIXME - find out what these mean
941
942 if (bcs->readonly)
943 r->root_item.flags |= BTRFS_SUBVOL_READONLY;
944
945 r->root_item.objid = SUBVOL_ROOT_INODE;
946 r->root_item.bytes_used = Vcb->superblock.node_size;
947 r->root_item.ctransid = Vcb->superblock.generation;
948 r->root_item.otransid = Vcb->superblock.generation;
949 r->root_item.ctime = now;
950 r->root_item.otime = now;
951
952 // add .. inode to new subvol
953
954 rootfcb = create_fcb(Vcb, PagedPool);
955 if (!rootfcb) {
956 ERR("out of memory\n");
958 goto end;
959 }
960
961 rootfcb->Vcb = Vcb;
962
963 rootfcb->subvol = r;
964 rootfcb->type = BTRFS_TYPE_DIRECTORY;
965 rootfcb->inode = SUBVOL_ROOT_INODE;
966 rootfcb->hash = calc_crc32c(0xffffffff, (uint8_t*)&rootfcb->inode, sizeof(uint64_t)); // FIXME - we can hardcode this
967
968 rootfcb->inode_item.generation = Vcb->superblock.generation;
969 rootfcb->inode_item.transid = Vcb->superblock.generation;
970 rootfcb->inode_item.st_nlink = 1;
971 rootfcb->inode_item.st_mode = __S_IFDIR | inherit_mode(fileref->fcb, true);
972 rootfcb->inode_item.st_atime = rootfcb->inode_item.st_ctime = rootfcb->inode_item.st_mtime = rootfcb->inode_item.otime = now;
973 rootfcb->inode_item.st_gid = GID_NOBODY;
974
975 rootfcb->atts = get_file_attributes(Vcb, rootfcb->subvol, rootfcb->inode, rootfcb->type, false, true, Irp);
976
977 if (r->root_item.flags & BTRFS_SUBVOL_READONLY)
978 rootfcb->atts |= FILE_ATTRIBUTE_READONLY;
979
980 SeCaptureSubjectContext(&subjcont);
981
982 Status = SeAssignSecurity(fcb->sd, NULL, (void**)&rootfcb->sd, true, &subjcont, IoGetFileObjectGenericMapping(), PagedPool);
983
984 if (!NT_SUCCESS(Status)) {
985 ERR("SeAssignSecurity returned %08lx\n", Status);
986 goto end;
987 }
988
989 if (!rootfcb->sd) {
990 ERR("SeAssignSecurity returned NULL security descriptor\n");
992 goto end;
993 }
994
995 Status = RtlGetOwnerSecurityDescriptor(rootfcb->sd, &owner, &defaulted);
996 if (!NT_SUCCESS(Status)) {
997 ERR("RtlGetOwnerSecurityDescriptor returned %08lx\n", Status);
998 rootfcb->inode_item.st_uid = UID_NOBODY;
999 rootfcb->sd_dirty = true;
1000 } else {
1001 rootfcb->inode_item.st_uid = sid_to_uid(owner);
1002 rootfcb->sd_dirty = rootfcb->inode_item.st_uid == UID_NOBODY;
1003 }
1004
1005 find_gid(rootfcb, fileref->fcb, &subjcont);
1006
1007 rootfcb->inode_item_changed = true;
1008
1009 acquire_fcb_lock_exclusive(Vcb);
1010 add_fcb_to_subvol(rootfcb);
1011 InsertTailList(&Vcb->all_fcbs, &rootfcb->list_entry_all);
1012 r->fcbs_version++;
1013 release_fcb_lock(Vcb);
1014
1015 rootfcb->Header.IsFastIoPossible = fast_io_possible(rootfcb);
1016 rootfcb->Header.AllocationSize.QuadPart = 0;
1017 rootfcb->Header.FileSize.QuadPart = 0;
1018 rootfcb->Header.ValidDataLength.QuadPart = 0;
1019
1020 rootfcb->created = true;
1021
1022 if (fileref->fcb->inode_item.flags & BTRFS_INODE_COMPRESS)
1024
1025 rootfcb->prop_compression = fileref->fcb->prop_compression;
1027
1028 r->lastinode = rootfcb->inode;
1029
1030 // add INODE_REF
1031
1032 irsize = (uint16_t)(offsetof(INODE_REF, name[0]) + sizeof(DOTDOT) - 1);
1034 if (!ir) {
1035 ERR("out of memory\n");
1037 goto end;
1038 }
1039
1040 ir->index = 0;
1041 ir->n = sizeof(DOTDOT) - 1;
1042 RtlCopyMemory(ir->name, DOTDOT, ir->n);
1043
1044 Status = insert_tree_item(Vcb, r, r->root_item.objid, TYPE_INODE_REF, r->root_item.objid, ir, irsize, NULL, Irp);
1045 if (!NT_SUCCESS(Status)) {
1046 ERR("insert_tree_item returned %08lx\n", Status);
1047 ExFreePool(ir);
1048 goto end;
1049 }
1050
1051 // create fileref for entry in other subvolume
1052
1053 fr = create_fileref(Vcb);
1054 if (!fr) {
1055 ERR("out of memory\n");
1056
1057 reap_fcb(rootfcb);
1058
1060 goto end;
1061 }
1062
1063 fr->fcb = rootfcb;
1064
1065 mark_fcb_dirty(rootfcb);
1066
1067 fr->parent = fileref;
1068
1069 Status = add_dir_child(fileref->fcb, r->id, true, &utf8, &nameus, BTRFS_TYPE_DIRECTORY, &dc);
1070 if (!NT_SUCCESS(Status))
1071 WARN("add_dir_child returned %08lx\n", Status);
1072
1073 fr->dc = dc;
1074 dc->fileref = fr;
1075
1077 if (!fr->fcb->hash_ptrs) {
1078 ERR("out of memory\n");
1079 free_fileref(fr);
1081 goto end;
1082 }
1083
1084 RtlZeroMemory(fr->fcb->hash_ptrs, sizeof(LIST_ENTRY*) * 256);
1085
1087 if (!fr->fcb->hash_ptrs_uc) {
1088 ERR("out of memory\n");
1089 free_fileref(fr);
1091 goto end;
1092 }
1093
1094 RtlZeroMemory(fr->fcb->hash_ptrs_uc, sizeof(LIST_ENTRY*) * 256);
1095
1096 ExAcquireResourceExclusiveLite(&fileref->fcb->nonpaged->dir_children_lock, true);
1097 InsertTailList(&fileref->children, &fr->list_entry);
1098 ExReleaseResourceLite(&fileref->fcb->nonpaged->dir_children_lock);
1099
1101
1102 if (fr->fcb->type == BTRFS_TYPE_DIRECTORY)
1103 fr->fcb->fileref = fr;
1104
1105 fr->created = true;
1107
1108 // change fcb->subvol's ROOT_ITEM
1109
1110 fcb->subvol->root_item.ctransid = Vcb->superblock.generation;
1111 fcb->subvol->root_item.ctime = now;
1112
1113 // change fcb's INODE_ITEM
1114
1115 fcb->inode_item.transid = Vcb->superblock.generation;
1116 fcb->inode_item.st_size += utf8.Length * 2;
1118
1121
1124
1125 fcb->inode_item_changed = true;
1127
1128 fr->fcb->subvol->parent = fcb->subvol->id;
1129
1131
1132end:
1133 if (!NT_SUCCESS(Status)) {
1134 if (fr) {
1135 fr->deleted = true;
1137 } else if (rootfcb) {
1138 rootfcb->deleted = true;
1139 mark_fcb_dirty(rootfcb);
1140 }
1141
1142 if (r) {
1143 RemoveEntryList(&r->list_entry);
1144 InsertTailList(&Vcb->drop_roots, &r->list_entry);
1145 }
1146 }
1147
1148 ExReleaseResourceLite(&Vcb->tree_lock);
1149
1150 if (NT_SUCCESS(Status)) {
1153 }
1154
1155end2:
1156 if (fr)
1157 free_fileref(fr);
1158
1159 return Status;
1160}
unsigned char BOOLEAN
unsigned short int uint16_t
Definition: acefiex.h:54
#define DOTDOT
Definition: fsctl.c:35
#define GID_NOBODY
Definition: btrfs_drv.h:91
#define increase_fileref_refcount(fileref)
Definition: btrfs_drv.h:1739
#define InterlockedIncrement64(a)
Definition: btrfs_drv.h:143
static __inline FAST_IO_POSSIBLE fast_io_possible(fcb *fcb)
Definition: btrfs_drv.h:1684
#define UID_NOBODY
Definition: btrfs_drv.h:90
#define __S_IFDIR
Definition: btrfs_drv.h:1754
uint32_t sid_to_uid(PSID sid)
Definition: security.c:310
static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME *out)
Definition: btrfs_drv.h:989
uint32_t inherit_mode(fcb *parfcb, bool is_dir)
Definition: create.c:1948
void find_gid(struct _fcb *fcb, struct _fcb *parfcb, PSECURITY_SUBJECT_CONTEXT subjcont)
Definition: security.c:924
void add_fcb_to_subvol(_In_ _Requires_exclusive_lock_held_(_Curr_->Vcb->fcb_lock) fcb *fcb)
Definition: fileinfo.c:888
fcb * create_fcb(device_extension *Vcb, POOL_TYPE pool_type)
Definition: create.c:91
NTSTATUS add_dir_child(fcb *fcb, uint64_t inode, bool subvol, PANSI_STRING utf8, PUNICODE_STRING name, uint8_t type, dir_child **pdc)
Definition: create.c:1871
@ PropCompression_None
Definition: btrfs_drv.h:268
file_ref * create_fileref(device_extension *Vcb)
Definition: create.c:160
crc_func calc_crc32c
Definition: crc32c.c:23
void mark_fcb_dirty(_In_ fcb *fcb)
Definition: btrfs.c:1695
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: btrfs.c:1271
void mark_fileref_dirty(_In_ file_ref *fileref)
Definition: btrfs.c:1717
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
void reap_fcb(fcb *fcb)
Definition: btrfs.c:1743
#define BTRFS_ROOT_UUID
Definition: btrfs.h:61
#define BTRFS_SUBVOL_READONLY
Definition: btrfs.h:109
#define TYPE_SUBVOL_UUID
Definition: btrfs.h:51
#define TYPE_INODE_REF
Definition: btrfs.h:24
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
time_t now
Definition: finger.c:65
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLuint id
Definition: glext.h:5910
int const JOCTET unsigned int datalen
Definition: jpeglib.h:1031
static const WCHAR dc[]
__u16 time
Definition: mkdosfs.c:8
#define uint16_t
Definition: nsiface.idl:60
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
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
#define SUBVOL_ROOT_INODE
Definition: propsheet.cpp:42
#define S_IXGRP
Definition: propsheet.h:49
#define S_IROTH
Definition: propsheet.h:53
#define BTRFS_INODE_COMPRESS
Definition: propsheet.h:87
#define S_IXOTH
Definition: propsheet.h:61
#define S_IRGRP
Definition: propsheet.h:41
#define S_IRUSR
Definition: propsheet.h:29
#define S_IWUSR
Definition: propsheet.h:33
#define S_IXUSR
Definition: propsheet.h:37
uint32_t st_mode
Definition: btrfs.h:295
uint32_t st_nlink
Definition: btrfs.h:292
uint32_t flags
Definition: btrfs.h:297
BTRFS_TIME otime
Definition: btrfs.h:304
BTRFS_TIME st_mtime
Definition: btrfs.h:303
uint64_t st_size
Definition: btrfs.h:289
uint32_t st_uid
Definition: btrfs.h:293
BTRFS_TIME st_atime
Definition: btrfs.h:301
uint64_t sequence
Definition: btrfs.h:299
BTRFS_TIME st_ctime
Definition: btrfs.h:302
uint64_t transid
Definition: btrfs.h:288
uint32_t st_gid
Definition: btrfs.h:294
uint64_t generation
Definition: btrfs.h:287
uint64_t index
Definition: btrfs.h:375
char name[1]
Definition: btrfs.h:377
uint16_t n
Definition: btrfs.h:376
bool user_set_change_time
Definition: btrfs_drv.h:390
bool user_set_write_time
Definition: btrfs_drv.h:389
LIST_ENTRY list_entry_all
Definition: btrfs_drv.h:337
ULONG atts
Definition: btrfs_drv.h:297
bool sd_dirty
Definition: btrfs_drv.h:321
bool deleted
Definition: btrfs_drv.h:295
SECURITY_DESCRIPTOR * sd
Definition: btrfs_drv.h:293
INODE_ITEM inode_item
Definition: btrfs_drv.h:292
bool created
Definition: btrfs_drv.h:328
LIST_ENTRY ** hash_ptrs_uc
Definition: btrfs_drv.h:318
LIST_ENTRY ** hash_ptrs
Definition: btrfs_drv.h:317
enum prop_compression_type prop_compression
Definition: btrfs_drv.h:307
struct _fcb_nonpaged * nonpaged
Definition: btrfs_drv.h:284
bool prop_compression_changed
Definition: btrfs_drv.h:326
bool inode_item_changed
Definition: btrfs_drv.h:306
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:283
struct _file_ref * parent
Definition: btrfs_drv.h:352
fcb * fcb
Definition: btrfs_drv.h:342
dir_child * dc
Definition: btrfs_drv.h:353
LIST_ENTRY list_entry
Definition: btrfs_drv.h:357
LIST_ENTRY children
Definition: btrfs_drv.h:349
bool created
Definition: btrfs_drv.h:348
tree * tree
Definition: btrfs_drv.h:508
VOID NTAPI SeCaptureSubjectContext(_Out_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
Captures the security subject context of the calling thread and calling process.
Definition: subject.c:85
#define STATUS_NOT_A_DIRECTORY
Definition: udferr_usr.h:169
#define STATUS_FILE_DELETED
Definition: udferr_usr.h:172
#define FILE_ACTION_MODIFIED
#define FILE_NOTIFY_CHANGE_LAST_WRITE

Referenced by fsctl_request().

◆ 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_create_snapshot()

static NTSTATUS do_create_snapshot ( device_extension Vcb,
PFILE_OBJECT  parent,
fcb subvol_fcb,
PANSI_STRING  utf8,
PUNICODE_STRING  name,
bool  readonly,
PIRP  Irp 
)
static

Definition at line 260 of file fsctl.c.

260 {
262 uint64_t id;
264 root *r, *subvol = subvol_fcb->subvol;
265 KEY searchkey;
267 uint64_t address, *root_num;
270 fcb* fcb = parent->FsContext;
271 ccb* ccb = parent->FsContext2;
272 LIST_ENTRY* le;
273 file_ref *fileref, *fr;
274 dir_child* dc = NULL;
275
276 if (!ccb) {
277 ERR("error - ccb was NULL\n");
279 }
280
281 if (!(ccb->access & FILE_ADD_SUBDIRECTORY)) {
282 WARN("insufficient privileges\n");
284 }
285
286 fileref = ccb->fileref;
287
288 if (fileref->fcb == Vcb->dummy_fcb)
290
291 // flush open files on this subvol
292
293 flush_subvol_fcbs(subvol);
294
295 // flush metadata
296
297 if (Vcb->need_write)
299 else
301
303
304 if (!NT_SUCCESS(Status)) {
305 ERR("do_write returned %08lx\n", Status);
306 return Status;
307 }
308
310
311 // create new root
312
313 id = InterlockedIncrement64(&Vcb->root_root->lastinode);
314 Status = create_root(Vcb, id, &r, true, Vcb->superblock.generation, Irp);
315
316 if (!NT_SUCCESS(Status)) {
317 ERR("create_root returned %08lx\n", Status);
318 goto end;
319 }
320
321 r->lastinode = subvol->lastinode;
322
323 if (!Vcb->uuid_root) {
324 root* uuid_root;
325
326 TRACE("uuid root doesn't exist, creating it\n");
327
328 Status = create_root(Vcb, BTRFS_ROOT_UUID, &uuid_root, false, 0, Irp);
329
330 if (!NT_SUCCESS(Status)) {
331 ERR("create_root returned %08lx\n", Status);
332 goto end;
333 }
334
335 Vcb->uuid_root = uuid_root;
336 }
337
339 if (!root_num) {
340 ERR("out of memory\n");
342 goto end;
343 }
344
345 tp.tree = NULL;
346
347 do {
348 get_uuid(&r->root_item.uuid);
349
350 RtlCopyMemory(&searchkey.obj_id, &r->root_item.uuid, sizeof(uint64_t));
351 searchkey.obj_type = TYPE_SUBVOL_UUID;
352 RtlCopyMemory(&searchkey.offset, &r->root_item.uuid.uuid[sizeof(uint64_t)], sizeof(uint64_t));
353
354 Status = find_item(Vcb, Vcb->uuid_root, &tp, &searchkey, false, Irp);
355 } while (NT_SUCCESS(Status) && !keycmp(searchkey, tp.item->key));
356
357 *root_num = r->id;
358
359 Status = insert_tree_item(Vcb, Vcb->uuid_root, searchkey.obj_id, searchkey.obj_type, searchkey.offset, root_num, sizeof(uint64_t), NULL, Irp);
360 if (!NT_SUCCESS(Status)) {
361 ERR("insert_tree_item returned %08lx\n", Status);
362 ExFreePool(root_num);
363 goto end;
364 }
365
366 searchkey.obj_id = r->id;
367 searchkey.obj_type = TYPE_ROOT_ITEM;
368 searchkey.offset = 0xffffffffffffffff;
369
370 Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
371 if (!NT_SUCCESS(Status)) {
372 ERR("error - find_item returned %08lx\n", Status);
373 goto end;
374 }
375
377 if (!NT_SUCCESS(Status)) {
378 ERR("snapshot_tree_copy returned %08lx\n", Status);
379 goto end;
380 }
381
384
385 r->root_item.inode.generation = 1;
386 r->root_item.inode.st_size = 3;
387 r->root_item.inode.st_blocks = subvol->root_item.inode.st_blocks;
388 r->root_item.inode.st_nlink = 1;
389 r->root_item.inode.st_mode = __S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; // 40755
390 r->root_item.inode.flags = 0x80000000; // FIXME - find out what these mean
391 r->root_item.inode.flags_ro = 0xffffffff; // FIXME - find out what these mean
392 r->root_item.generation = Vcb->superblock.generation;
393 r->root_item.objid = subvol->root_item.objid;
394 r->root_item.block_number = address;
395 r->root_item.bytes_used = subvol->root_item.bytes_used;
396 r->root_item.last_snapshot_generation = Vcb->superblock.generation;
397 r->root_item.root_level = subvol->root_item.root_level;
398 r->root_item.generation2 = Vcb->superblock.generation;
399 r->root_item.parent_uuid = subvol->root_item.uuid;
400 r->root_item.ctransid = subvol->root_item.ctransid;
401 r->root_item.otransid = Vcb->superblock.generation;
402 r->root_item.ctime = subvol->root_item.ctime;
403 r->root_item.otime = now;
404
405 if (readonly)
406 r->root_item.flags |= BTRFS_SUBVOL_READONLY;
407
408 r->treeholder.address = address;
409
410 // FIXME - do we need to copy over the send and receive fields too?
411
412 if (tp.item->key.obj_id != searchkey.obj_id || tp.item->key.obj_type != searchkey.obj_type) {
413 ERR("error - could not find ROOT_ITEM for subvol %I64x\n", r->id);
415 goto end;
416 }
417
418 RtlCopyMemory(tp.item->data, &r->root_item, sizeof(ROOT_ITEM));
419
420 // update ROOT_ITEM of original subvol
421
422 subvol->root_item.last_snapshot_generation = Vcb->superblock.generation;
423
424 mark_subvol_dirty(Vcb, subvol);
425
426 // create fileref for entry in other subvolume
427
428 fr = create_fileref(Vcb);
429 if (!fr) {
430 ERR("out of memory\n");
432 goto end;
433 }
434
435 Status = open_fcb(Vcb, r, r->root_item.objid, BTRFS_TYPE_DIRECTORY, utf8, false, fcb, &fr->fcb, PagedPool, Irp);
436 if (!NT_SUCCESS(Status)) {
437 ERR("open_fcb returned %08lx\n", Status);
438 free_fileref(fr);
439 goto end;
440 }
441
442 fr->parent = fileref;
443
444 Status = add_dir_child(fileref->fcb, r->id, true, utf8, name, BTRFS_TYPE_DIRECTORY, &dc);
445 if (!NT_SUCCESS(Status))
446 WARN("add_dir_child returned %08lx\n", Status);
447
448 fr->dc = dc;
449 dc->fileref = fr;
450
451 ExAcquireResourceExclusiveLite(&fileref->fcb->nonpaged->dir_children_lock, true);
452 InsertTailList(&fileref->children, &fr->list_entry);
453 ExReleaseResourceLite(&fileref->fcb->nonpaged->dir_children_lock);
454
456
457 fr->created = true;
459
460 if (fr->fcb->type == BTRFS_TYPE_DIRECTORY)
461 fr->fcb->fileref = fr;
462
463 fr->fcb->subvol->parent = fileref->fcb->subvol->id;
464
465 free_fileref(fr);
466
467 // change fcb's INODE_ITEM
468
469 fcb->inode_item.transid = Vcb->superblock.generation;
471 fcb->inode_item.st_size += utf8->Length * 2;
472
475
478
479 fcb->inode_item_changed = true;
481
482 fcb->subvol->root_item.ctime = now;
483 fcb->subvol->root_item.ctransid = Vcb->superblock.generation;
484
487
488 le = subvol->fcbs.Flink;
489 while (le != &subvol->fcbs) {
490 struct _fcb* fcb2 = CONTAINING_RECORD(le, struct _fcb, list_entry);
491 LIST_ENTRY* le2 = fcb2->extents.Flink;
492
493 while (le2 != &fcb2->extents) {
495
496 if (!ext->ignore)
497 ext->unique = false;
498
499 le2 = le2->Flink;
500 }
501
502 le = le->Flink;
503 }
504
506
508
509 if (!NT_SUCCESS(Status))
510 ERR("do_write returned %08lx\n", Status);
511
512end:
513 if (NT_SUCCESS(Status))
515 else
517
518 return Status;
519}
void flush_subvol_fcbs(root *subvol)
Definition: fsctl.c:243
static void mark_subvol_dirty(device_extension *Vcb, root *r)
Definition: fsctl.c:4108
static NTSTATUS snapshot_tree_copy(device_extension *Vcb, uint64_t addr, root *subvol, uint64_t *newaddr, PIRP Irp, LIST_ENTRY *rollback)
Definition: fsctl.c:87
_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 do_rollback(device_extension *Vcb, LIST_ENTRY *rollback) __attribute__((nonnull(1
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
NTSTATUS NTSTATUS void clear_rollback(LIST_ENTRY *rollback) __attribute__((nonnull(1)))
r parent
Definition: btrfs.c:3010
#define TYPE_ROOT_ITEM
Definition: btrfs.h:32
GLuint address
Definition: glext.h:9393
uint64_t st_blocks
Definition: btrfs.h:290
uint64_t bytes_used
Definition: btrfs.h:317
uint64_t ctransid
Definition: btrfs.h:328
uint64_t objid
Definition: btrfs.h:314
uint8_t root_level
Definition: btrfs.h:323
BTRFS_TIME ctime
Definition: btrfs.h:332
uint64_t block_number
Definition: btrfs.h:315
uint64_t last_snapshot_generation
Definition: btrfs.h:318
INODE_ITEM inode
Definition: btrfs.h:312
BTRFS_UUID uuid
Definition: btrfs.h:325
LIST_ENTRY fcbs
Definition: btrfs_drv.h:464
LONGLONG lastinode
Definition: btrfs_drv.h:452
ROOT_ITEM root_item
Definition: btrfs_drv.h:455
uint8_t * data
Definition: btrfs_drv.h:415

Referenced by create_snapshot().

◆ 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}
KIRQL irql
Definition: wave.h:1
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
VOID NTAPI IoReleaseVpbSpinLock(IN KIRQL Irql)
Definition: volume.c:1215
VOID NTAPI IoAcquireVpbSpinLock(OUT PKIRQL Irql)
Definition: volume.c:1204

Referenced by _Dispatch_type_(), and unlock_volume().

◆ duplicate_extents()

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

Definition at line 3262 of file fsctl.c.

3262 {
3264 fcb *fcb = FileObject ? FileObject->FsContext : NULL, *sourcefcb;
3265 ccb *ccb = FileObject ? FileObject->FsContext2 : NULL, *sourceccb;
3267 PFILE_OBJECT sourcefo;
3268 uint64_t sourcelen, nbytes = 0;
3269 LIST_ENTRY rollback, *le, newexts;
3272 bool make_inline;
3273
3274 if (!ded || datalen < sizeof(DUPLICATE_EXTENTS_DATA))
3276
3277 if (Vcb->readonly)
3279
3280 if (ded->ByteCount.QuadPart == 0)
3281 return STATUS_SUCCESS;
3282
3283 if (!fcb || !ccb || fcb == Vcb->volume_fcb)
3285
3287 return STATUS_ACCESS_DENIED;
3288
3289 if (Irp->RequestorMode == UserMode && !(ccb->access & FILE_WRITE_DATA)) {
3290 WARN("insufficient privileges\n");
3291 return STATUS_ACCESS_DENIED;
3292 }
3293
3296
3297 Status = ObReferenceObjectByHandle(ded->FileHandle, 0, *IoFileObjectType, Irp->RequestorMode, (void**)&sourcefo, NULL);
3298 if (!NT_SUCCESS(Status)) {
3299 ERR("ObReferenceObjectByHandle returned %08lx\n", Status);
3300 return Status;
3301 }
3302
3303 if (sourcefo->DeviceObject != FileObject->DeviceObject) {
3304 WARN("source and destination are on different volumes\n");
3305 ObDereferenceObject(sourcefo);
3307 }
3308
3309 sourcefcb = sourcefo->FsContext;
3310 sourceccb = sourcefo->FsContext2;
3311
3312 if (!sourcefcb || !sourceccb || sourcefcb == Vcb->volume_fcb) {
3313 ObDereferenceObject(sourcefo);
3315 }
3316
3317 if (!sourcefcb->ads && !fcb->ads) {
3318 if ((ded->SourceFileOffset.QuadPart & (Vcb->superblock.sector_size - 1)) || (ded->TargetFileOffset.QuadPart & (Vcb->superblock.sector_size - 1))) {
3319 ObDereferenceObject(sourcefo);
3321 }
3322
3323 if (ded->ByteCount.QuadPart & (Vcb->superblock.sector_size - 1)) {
3324 ObDereferenceObject(sourcefo);
3326 }
3327 }
3328
3329 if (Irp->RequestorMode == UserMode && (!(sourceccb->access & FILE_READ_DATA) || !(sourceccb->access & FILE_READ_ATTRIBUTES))) {
3330 WARN("insufficient privileges\n");
3331 ObDereferenceObject(sourcefo);
3332 return STATUS_ACCESS_DENIED;
3333 }
3334
3335 if (!sourcefcb->ads && sourcefcb->type != BTRFS_TYPE_FILE && sourcefcb->type != BTRFS_TYPE_SYMLINK) {
3336 ObDereferenceObject(sourcefo);
3338 }
3339
3340 sourcelen = sourcefcb->ads ? sourcefcb->adsdata.Length : sourcefcb->inode_item.st_size;
3341
3342 if (sector_align(sourcelen, Vcb->superblock.sector_size) < (uint64_t)ded->SourceFileOffset.QuadPart + (uint64_t)ded->ByteCount.QuadPart) {
3343 ObDereferenceObject(sourcefo);
3344 return STATUS_NOT_SUPPORTED;
3345 }
3346
3347 if (fcb == sourcefcb &&
3350 WARN("source and destination are the same, and the ranges overlap\n");
3351 ObDereferenceObject(sourcefo);
3353 }
3354
3355 // fail if nocsum flag set on one file but not the other
3356 if (!fcb->ads && !sourcefcb->ads && (fcb->inode_item.flags & BTRFS_INODE_NODATASUM) != (sourcefcb->inode_item.flags & BTRFS_INODE_NODATASUM)) {
3357 ObDereferenceObject(sourcefo);
3359 }
3360
3362 InitializeListHead(&newexts);
3363
3364 ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
3365
3366 ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
3367
3368 if (fcb != sourcefcb)
3369 ExAcquireResourceSharedLite(sourcefcb->Header.Resource, true);
3370
3373 goto end;
3374 }
3375
3376 if (!FsRtlFastCheckLockForRead(&sourcefcb->lock, &ded->SourceFileOffset, &ded->ByteCount, 0, FileObject, PsGetCurrentProcess())) {
3378 goto end;
3379 }
3380
3381 make_inline = fcb->ads ? false : (fcb->inode_item.st_size <= Vcb->options.max_inline || fcb_is_inline(fcb));
3382
3383 if (fcb->ads || sourcefcb->ads || make_inline || fcb_is_inline(sourcefcb)) {
3384 uint8_t* data2;
3385 ULONG bytes_read, dataoff, datalen2;
3386
3387 if (make_inline) {
3388 dataoff = (ULONG)ded->TargetFileOffset.QuadPart;
3389 datalen2 = (ULONG)fcb->inode_item.st_size;
3390 } else if (fcb->ads) {
3391 dataoff = 0;
3392 datalen2 = (ULONG)ded->ByteCount.QuadPart;
3393 } else {
3394 dataoff = ded->TargetFileOffset.QuadPart & (Vcb->superblock.sector_size - 1);
3395 datalen2 = (ULONG)sector_align(ded->ByteCount.QuadPart + dataoff, Vcb->superblock.sector_size);
3396 }
3397
3399 if (!data2) {
3400 ERR("out of memory\n");
3402 goto end;
3403 }
3404
3405 if (dataoff > 0) {
3406 if (make_inline)
3407 Status = read_file(fcb, data2, 0, datalen2, NULL, Irp);
3408 else
3409 Status = read_file(fcb, data2, ded->TargetFileOffset.QuadPart - dataoff, dataoff, NULL, Irp);
3410
3411 if (!NT_SUCCESS(Status)) {
3412 ERR("read_file returned %08lx\n", Status);
3414 goto end;
3415 }
3416 }
3417
3418 if (sourcefcb->ads) {
3419 Status = read_stream(sourcefcb, data2 + dataoff, ded->SourceFileOffset.QuadPart, (ULONG)ded->ByteCount.QuadPart, &bytes_read);
3420 if (!NT_SUCCESS(Status)) {
3421 ERR("read_stream returned %08lx\n", Status);
3423 goto end;
3424 }
3425 } else {
3426 Status = read_file(sourcefcb, data2 + dataoff, ded->SourceFileOffset.QuadPart, ded->ByteCount.QuadPart, &bytes_read, Irp);
3427 if (!NT_SUCCESS(Status)) {
3428 ERR("read_file returned %08lx\n", Status);
3430 goto end;
3431 }
3432 }
3433
3434 if (dataoff + bytes_read < datalen2)
3435 RtlZeroMemory(data2 + dataoff + bytes_read, datalen2 - bytes_read);
3436
3437 if (fcb->ads)
3439 else if (make_inline) {
3440 uint16_t edsize;
3441 EXTENT_DATA* ed;
3442
3443 Status = excise_extents(Vcb, fcb, 0, sector_align(fcb->inode_item.st_size, Vcb->superblock.sector_size), Irp, &rollback);
3444 if (!NT_SUCCESS(Status)) {
3445 ERR("excise_extents returned %08lx\n", Status);
3447 goto end;
3448 }
3449
3450 edsize = (uint16_t)(offsetof(EXTENT_DATA, data[0]) + datalen2);
3451
3453 if (!ed) {
3454 ERR("out of memory\n");
3457 goto end;
3458 }
3459
3460 ed->generation = Vcb->superblock.generation;
3466
3467 RtlCopyMemory(ed->data, data2, datalen2);
3468
3469 Status = add_extent_to_fcb(fcb, 0, ed, edsize, false, NULL, &rollback);
3470 if (!NT_SUCCESS(Status)) {
3471 ERR("add_extent_to_fcb returned %08lx\n", Status);
3473 goto end;
3474 }
3475
3476 fcb->inode_item.st_blocks += datalen2;
3477 } else {
3478 uint64_t start = ded->TargetFileOffset.QuadPart - (ded->TargetFileOffset.QuadPart & (Vcb->superblock.sector_size - 1));
3479
3480 Status = do_write_file(fcb, start, start + datalen2, data2, Irp, false, 0, &rollback);
3481 if (!NT_SUCCESS(Status)) {
3482 ERR("do_write_file returned %08lx\n", Status);
3484 goto end;
3485 }
3486 }
3487
3489 } else {
3490 LIST_ENTRY* lastextle;
3491
3492 le = sourcefcb->extents.Flink;
3493 while (le != &sourcefcb->extents) {
3495
3496 if (!ext->ignore) {
3497 if (ext->offset >= (uint64_t)ded->SourceFileOffset.QuadPart + (uint64_t)ded->ByteCount.QuadPart)
3498 break;
3499
3500 if (ext->extent_data.type != EXTENT_TYPE_INLINE) {
3501 ULONG extlen = offsetof(extent, extent_data) + sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2);
3502 extent* ext2;
3503 EXTENT_DATA2 *ed2s, *ed2d;
3504 chunk* c;
3505
3506 ed2s = (EXTENT_DATA2*)ext->extent_data.data;
3507
3508 if (ext->offset + ed2s->num_bytes <= (uint64_t)ded->SourceFileOffset.QuadPart) {
3509 le = le->Flink;
3510 continue;
3511 }
3512
3514 if (!ext2) {
3515 ERR("out of memory\n");
3517 goto end;
3518 }
3519
3520 if (ext->offset < (uint64_t)ded->SourceFileOffset.QuadPart)
3521 ext2->offset = ded->TargetFileOffset.QuadPart;
3522 else
3523 ext2->offset = ext->offset - ded->SourceFileOffset.QuadPart + ded->TargetFileOffset.QuadPart;
3524
3525 ext2->datalen = sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2);
3526 ext2->unique = false;
3527 ext2->ignore = false;
3528 ext2->inserted = true;
3529
3530 ext2->extent_data.generation = Vcb->superblock.generation;
3531 ext2->extent_data.decoded_size = ext->extent_data.decoded_size;
3532 ext2->extent_data.compression = ext->extent_data.compression;
3533 ext2->extent_data.encryption = ext->extent_data.encryption;
3534 ext2->extent_data.encoding = ext->extent_data.encoding;
3535 ext2->extent_data.type = ext->extent_data.type;
3536
3537 ed2d = (EXTENT_DATA2*)ext2->extent_data.data;
3538
3539 ed2d->address = ed2s->address;
3540 ed2d->size = ed2s->size;
3541
3542 if (ext->offset < (uint64_t)ded->SourceFileOffset.QuadPart) {
3543 ed2d->offset = ed2s->offset + ded->SourceFileOffset.QuadPart - ext->offset;
3544 ed2d->num_bytes = min((uint64_t)ded->ByteCount.QuadPart, ed2s->num_bytes + ext->offset - ded->SourceFileOffset.QuadPart);
3545 } else {
3546 ed2d->offset = ed2s->offset;
3547 ed2d->num_bytes = min(ded->SourceFileOffset.QuadPart + ded->ByteCount.QuadPart - ext->offset, ed2s->num_bytes);
3548 }
3549
3550 if (ext->csum) {
3551 if (ext->extent_data.compression == BTRFS_COMPRESSION_NONE) {
3552 ext2->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)((ed2d->num_bytes * Vcb->csum_size) >> Vcb->sector_shift), ALLOC_TAG);
3553 if (!ext2->csum) {
3554 ERR("out of memory\n");
3557 goto end;
3558 }
3559
3560 RtlCopyMemory(ext2->csum, (uint8_t*)ext->csum + (((ed2d->offset - ed2s->offset) * Vcb->csum_size) >> Vcb->sector_shift),
3561 (ULONG)((ed2d->num_bytes * Vcb->csum_size) >> Vcb->sector_shift));
3562 } else {
3563 ext2->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)((ed2d->size * Vcb->csum_size) >> Vcb->sector_shift), ALLOC_TAG);
3564 if (!ext2->csum) {
3565 ERR("out of memory\n");
3568 goto end;
3569 }
3570
3571 RtlCopyMemory(ext2->csum, ext->csum, (ULONG)((ed2s->size * Vcb->csum_size) >> Vcb->sector_shift));
3572 }
3573 } else
3574 ext2->csum = NULL;
3575
3576 InsertTailList(&newexts, &ext2->list_entry);
3577
3579 if (!c) {
3580 ERR("get_chunk_from_address(%I64x) failed\n", ed2s->address);
3582 goto end;
3583 }
3584
3585 Status = update_changed_extent_ref(Vcb, c, ed2s->address, ed2s->size, fcb->subvol->id, fcb->inode, ext2->offset - ed2d->offset,
3587 if (!NT_SUCCESS(Status)) {
3588 ERR("update_changed_extent_ref returned %08lx\n", Status);
3589 goto end;
3590 }
3591
3592 nbytes += ed2d->num_bytes;
3593 }
3594 }
3595
3596 le = le->Flink;
3597 }
3598
3600 if (!NT_SUCCESS(Status)) {
3601 ERR("excise_extents returned %08lx\n", Status);
3602
3603 while (!IsListEmpty(&newexts)) {
3605 ExFreePool(ext);
3606 }
3607
3608 goto end;
3609 }
3610
3611 // clear unique flags in source fcb
3612 le = sourcefcb->extents.Flink;
3613 while (le != &sourcefcb->extents) {
3615
3616 if (!ext->ignore && ext->unique && (ext->extent_data.type == EXTENT_TYPE_REGULAR || ext->extent_data.type == EXTENT_TYPE_PREALLOC)) {
3617 EXTENT_DATA2* ed2s = (EXTENT_DATA2*)ext->extent_data.data;
3618 LIST_ENTRY* le2;
3619
3620 le2 = newexts.Flink;
3621 while (le2 != &newexts) {
3623
3624 if (ext2->extent_data.type == EXTENT_TYPE_REGULAR || ext2->extent_data.type == EXTENT_TYPE_PREALLOC) {
3625 EXTENT_DATA2* ed2d = (EXTENT_DATA2*)ext2->extent_data.data;
3626
3627 if (ed2d->address == ed2s->address && ed2d->size == ed2s->size) {
3628 ext->unique = false;
3629 break;
3630 }
3631 }
3632
3633 le2 = le2->Flink;
3634 }
3635 }
3636
3637 le = le->Flink;
3638 }
3639
3640 lastextle = &fcb->extents;
3641 while (!IsListEmpty(&newexts)) {
3643
3644 add_extent(fcb, lastextle, ext);
3645 lastextle = &ext->list_entry;
3646 }
3647 }
3648
3651
3652 if (fcb->ads) {
3653 ccb->fileref->parent->fcb->inode_item.sequence++;
3654
3656 ccb->fileref->parent->fcb->inode_item.st_ctime = now;
3657
3658 ccb->fileref->parent->fcb->inode_item_changed = true;
3660 } else {
3661 fcb->inode_item.st_blocks += nbytes;
3663
3666
3667 if (!ccb->user_set_write_time) {
3670 }
3671
3672 fcb->inode_item_changed = true;
3673 fcb->extents_changed = true;
3674 }
3675
3677
3678 if (FileObject->SectionObjectPointer->DataSectionObject)
3679 CcPurgeCacheSection(FileObject->SectionObjectPointer, &ded->TargetFileOffset, (ULONG)ded->ByteCount.QuadPart, false);
3680
3682
3683end:
3684 ObDereferenceObject(sourcefo);
3685
3686 if (NT_SUCCESS(Status))
3688 else
3690
3691 if (fcb != sourcefcb)
3692 ExReleaseResourceLite(sourcefcb->Header.Resource);
3693
3694 ExReleaseResourceLite(fcb->Header.Resource);
3695
3696 ExReleaseResourceLite(&Vcb->tree_lock);
3697
3698 return Status;
3699}
HRESULT read_stream(BSCallback *, IStream *, void *, DWORD, DWORD *) DECLSPEC_HIDDEN
Definition: navigate.c:602
bool fcb_is_inline(fcb *fcb)
Definition: fsctl.c:3246
NTSTATUS read_file(fcb *fcb, uint8_t *data, uint64_t start, uint64_t length, ULONG *pbr, PIRP Irp) __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 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 NTSTATUS NTSTATUS NTSTATUS NTSTATUS chunk * get_chunk_from_address(device_extension *Vcb, uint64_t address) __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 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
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
static uint64_t __inline sector_align(uint64_t n, uint64_t a)
void queue_notification_fcb(_In_ file_ref *fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream)
Definition: btrfs.c:1667
#define EXTENT_TYPE_PREALLOC
Definition: btrfs.h:76
#define BTRFS_ENCODING_NONE
Definition: btrfs.h:72
#define EXTENT_TYPE_INLINE
Definition: btrfs.h:74
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:75
#define BTRFS_COMPRESSION_NONE
Definition: btrfs.h:65
#define BTRFS_ENCRYPTION_NONE
Definition: btrfs.h:70
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define ExAcquireResourceSharedLite(res, wait)
Definition: env_spec_w32.h:621
BOOLEAN NTAPI FsRtlFastCheckLockForWrite(IN PFILE_LOCK FileLock, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, IN ULONG Key, IN PFILE_OBJECT FileObject, IN PVOID Process)
Definition: filelock.c:782
BOOLEAN NTAPI FsRtlFastCheckLockForRead(IN PFILE_LOCK FileLock, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, IN ULONG Key, IN PFILE_OBJECT FileObject, IN PVOID Process)
Definition: filelock.c:748
BOOLEAN NTAPI CcPurgeCacheSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN UninitializeCacheMaps)
Definition: fssup.c:386
GLuint start
Definition: gl.h:1545
if(dx< 0)
Definition: linetemp.h:194
static const BYTE ext2[]
Definition: encode.c:2699
#define min(a, b)
Definition: monoChain.cc:55
#define UserMode
Definition: asm.h:35
#define FILE_WRITE_DATA
Definition: nt_native.h:631
#define FILE_READ_DATA
Definition: nt_native.h:628
#define STATUS_FILE_LOCK_CONFLICT
Definition: ntstatus.h:320
#define BTRFS_INODE_NODATASUM
Definition: propsheet.h:76
#define BTRFS_TYPE_FILE
Definition: shellext.h:85
#define BTRFS_TYPE_SYMLINK
Definition: shellext.h:91
#define false
Definition: stdbool.h:37
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
uint64_t generation
Definition: btrfs.h:358
uint8_t type
Definition: btrfs.h:363
uint16_t encoding
Definition: btrfs.h:362
uint8_t encryption
Definition: btrfs.h:361
uint8_t compression
Definition: btrfs.h:360
uint64_t decoded_size
Definition: btrfs.h:359
LARGE_INTEGER ByteCount
Definition: shellext.h:202
LARGE_INTEGER SourceFileOffset
Definition: shellext.h:200
LARGE_INTEGER TargetFileOffset
Definition: shellext.h:201
bool ads
Definition: btrfs_drv.h:330
FILE_LOCK lock
Definition: btrfs_drv.h:294
ANSI_STRING adsdata
Definition: btrfs_drv.h:334
bool extents_changed
Definition: btrfs_drv.h:323
Definition: tftpd.h:138
#define PsGetCurrentProcess
Definition: psfuncs.h:17

Referenced by fsctl_request().

◆ 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}

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

◆ find_subvol()

static NTSTATUS find_subvol ( device_extension Vcb,
void in,
ULONG  inlen,
void out,
ULONG  outlen,
PIRP  Irp 
)
static

Definition at line 4586 of file fsctl.c.

4586 {
4587 btrfs_find_subvol* bfs;
4590 KEY searchkey;
4591
4592 if (!in || inlen < sizeof(btrfs_find_subvol))
4594
4595 if (!out || outlen < sizeof(WCHAR))
4597
4598 if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), Irp->RequestorMode))
4600
4601 bfs = (btrfs_find_subvol*)in;
4602
4603 ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
4604
4605 if (!Vcb->uuid_root) {
4606 ERR("couldn't find uuid root\n");
4608 goto end;
4609 }
4610
4611 RtlCopyMemory(&searchkey.obj_id, &bfs->uuid, sizeof(uint64_t));
4612 searchkey.obj_type = TYPE_SUBVOL_UUID;
4613 RtlCopyMemory(&searchkey.offset, &bfs->uuid.uuid[sizeof(uint64_t)], sizeof(uint64_t));
4614
4615 Status = find_item(Vcb, Vcb->uuid_root, &tp, &searchkey, false, Irp);
4616
4617 if (!NT_SUCCESS(Status)) {
4618 ERR("find_item returned %08lx\n", Status);
4619 goto end;
4620 }
4621
4622 if (!keycmp(searchkey, tp.item->key) && tp.item->size >= sizeof(uint64_t)) {
4623 uint64_t* id = (uint64_t*)tp.item->data;
4624
4625 if (bfs->ctransid != 0) {
4626 KEY searchkey2;
4627 traverse_ptr tp2;
4628
4629 searchkey2.obj_id = *id;
4630 searchkey2.obj_type = TYPE_ROOT_ITEM;
4631 searchkey2.offset = 0xffffffffffffffff;
4632
4633 Status = find_item(Vcb, Vcb->root_root, &tp2, &searchkey2, false, Irp);
4634 if (!NT_SUCCESS(Status)) {
4635 ERR("find_item returned %08lx\n", Status);
4636 goto end;
4637 }
4638
4639 if (tp2.item->key.obj_id == searchkey2.obj_id && tp2.item->key.obj_type == searchkey2.obj_type &&
4640 tp2.item->size >= offsetof(ROOT_ITEM, otransid)) {
4641 ROOT_ITEM* ri = (ROOT_ITEM*)tp2.item->data;
4642
4643 if (ri->ctransid == bfs->ctransid) {
4644 TRACE("found subvol %I64x\n", *id);
4645 Status = get_subvol_path(Vcb, *id, out, outlen, Irp);
4646 goto end;
4647 }
4648 }
4649 } else {
4650 TRACE("found subvol %I64x\n", *id);
4651 Status = get_subvol_path(Vcb, *id, out, outlen, Irp);
4652 goto end;
4653 }
4654 }
4655
4656 searchkey.obj_type = TYPE_SUBVOL_REC_UUID;
4657
4658 Status = find_item(Vcb, Vcb->uuid_root, &tp, &searchkey, false, Irp);
4659
4660 if (!NT_SUCCESS(Status)) {
4661 ERR("find_item returned %08lx\n", Status);
4662 goto end;
4663 }
4664
4665 if (!keycmp(searchkey, tp.item->key) && tp.item->size >= sizeof(uint64_t)) {
4667 ULONG i;
4668
4669 for (i = 0; i < tp.item->size / sizeof(uint64_t); i++) {
4670 if (bfs->ctransid != 0) {
4671 KEY searchkey2;
4672 traverse_ptr tp2;
4673
4674 searchkey2.obj_id = ids[i];
4675 searchkey2.obj_type = TYPE_ROOT_ITEM;
4676 searchkey2.offset = 0xffffffffffffffff;
4677
4678 Status = find_item(Vcb, Vcb->root_root, &tp2, &searchkey2, false, Irp);
4679 if (!NT_SUCCESS(Status)) {
4680 ERR("find_item returned %08lx\n", Status);
4681 goto end;
4682 }
4683
4684 if (tp2.item->key.obj_id == searchkey2.obj_id && tp2.item->key.obj_type == searchkey2.obj_type &&
4685 tp2.item->size >= offsetof(ROOT_ITEM, otransid)) {
4686 ROOT_ITEM* ri = (ROOT_ITEM*)tp2.item->data;
4687
4688 if (ri->ctransid == bfs->ctransid) {
4689 TRACE("found subvol %I64x\n", ids[i]);
4690 Status = get_subvol_path(Vcb, ids[i], out, outlen, Irp);
4691 goto end;
4692 }
4693 }
4694 } else {
4695 TRACE("found subvol %I64x\n", ids[i]);
4696 Status = get_subvol_path(Vcb, ids[i], out, outlen, Irp);
4697 goto end;
4698 }
4699 }
4700 }
4701
4703
4704end:
4705 ExReleaseResourceLite(&Vcb->tree_lock);
4706
4707 return Status;
4708}
static NTSTATUS get_subvol_path(device_extension *Vcb, uint64_t id, WCHAR *out, ULONG outlen, PIRP Irp)
Definition: fsctl.c:4535
#define TYPE_SUBVOL_REC_UUID
Definition: btrfs.h:52
GLuint * ids
Definition: glext.h:5907
GLuint in
Definition: glext.h:9616
#define for
Definition: utility.h:88
#define uint64_t
Definition: nsiface.idl:62
static FILE * out
Definition: regtests2xml.c:44
uint8_t uuid[16]
Definition: btrfs.h:140
uint16_t size
Definition: btrfs_drv.h:414
BTRFS_UUID uuid
Definition: btrfsioctl.h:263
uint64_t ctransid
Definition: btrfsioctl.h:264

Referenced by fsctl_request().

◆ flush_fcb_caches()

static void flush_fcb_caches ( device_extension Vcb)
static

Definition at line 2222 of file fsctl.c.

2222 {
2223 LIST_ENTRY* le;
2224
2225 le = Vcb->all_fcbs.Flink;
2226 while (le != &Vcb->all_fcbs) {
2227 struct _fcb* fcb = CONTAINING_RECORD(le, struct _fcb, list_entry_all);
2229
2231 CcFlushCache(&fcb->nonpaged->segment_object, NULL, 0, &iosb);
2232
2233 le = le->Flink;
2234 }
2235}
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
static PIO_STATUS_BLOCK iosb
Definition: file.c:98

Referenced by dismount_volume(), invalidate_volumes(), and lock_volume().

◆ 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}

Referenced by _Function_class_(), and do_create_snapshot().

◆ fs_get_statistics()

static NTSTATUS fs_get_statistics ( void buffer,
DWORD  buflen,
ULONG_PTR retlen 
)
static

Definition at line 1705 of file fsctl.c.

1705 {
1707
1708 WARN("STUB: FSCTL_FILESYSTEM_GET_STATISTICS\n");
1709
1710 // This is hideously wrong, but at least it stops SMB from breaking
1711
1712 if (buflen < sizeof(FILESYSTEM_STATISTICS))
1714
1715 fss = buffer;
1717
1718 fss->Version = 1;
1721
1722 *retlen = sizeof(FILESYSTEM_STATISTICS);
1723
1724 return STATUS_SUCCESS;
1725}
GLuint buffer
Definition: glext.h:5915
#define FILESYSTEM_STATISTICS_TYPE_NTFS
Definition: winioctl.h:838
struct _FILESYSTEM_STATISTICS FILESYSTEM_STATISTICS
ULONG SizeOfCompleteStructure
Definition: winioctl.h:823

Referenced by fsctl_request().

◆ fsctl_get_xattrs()

static NTSTATUS fsctl_get_xattrs ( device_extension Vcb,
PFILE_OBJECT  FileObject,
void data,
ULONG  datalen,
KPROCESSOR_MODE  processor_mode 
)
static

Definition at line 4170 of file fsctl.c.

4170 {
4171 LIST_ENTRY* le;
4172 btrfs_set_xattr* bsxa;
4173 ULONG reqlen = (ULONG)offsetof(btrfs_set_xattr, data[0]);
4174 fcb* fcb;
4175 ccb* ccb;
4176
4177 if (!data || datalen < reqlen)
4179
4180 if (!FileObject || !FileObject->FsContext || !FileObject->FsContext2 || FileObject->FsContext == Vcb->volume_fcb)
4182
4183 fcb = FileObject->FsContext;
4184 ccb = FileObject->FsContext2;
4185
4186 if (!(ccb->access & (FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES)) && processor_mode == UserMode) {
4187 WARN("insufficient privileges\n");
4188 return STATUS_ACCESS_DENIED;
4189 }
4190
4191 ExAcquireResourceSharedLite(fcb->Header.Resource, true);
4192
4193 le = fcb->xattrs.Flink;
4194 while (le != &fcb->xattrs) {
4196
4197 if (xa->valuelen > 0)
4198 reqlen += (ULONG)offsetof(btrfs_set_xattr, data[0]) + xa->namelen + xa->valuelen;
4199
4200 le = le->Flink;
4201 }
4202
4203 if (datalen < reqlen) {
4204 ExReleaseResourceLite(fcb->Header.Resource);
4206 }
4207
4208 bsxa = (btrfs_set_xattr*)data;
4209
4210 if (reqlen > 0) {
4211 le = fcb->xattrs.Flink;
4212 while (le != &fcb->xattrs) {
4214
4215 if (xa->valuelen > 0) {
4216 bsxa->namelen = xa->namelen;
4217 bsxa->valuelen = xa->valuelen;
4218 memcpy(bsxa->data, xa->data, xa->namelen + xa->valuelen);
4219
4220 bsxa = (btrfs_set_xattr*)&bsxa->data[xa->namelen + xa->valuelen];
4221 }
4222
4223 le = le->Flink;
4224 }
4225 }
4226
4227 bsxa->namelen = 0;
4228 bsxa->valuelen = 0;
4229
4230 ExReleaseResourceLite(fcb->Header.Resource);
4231
4232 return STATUS_SUCCESS;
4233}
#define FILE_WRITE_ATTRIBUTES
Definition: nt_native.h:649
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
LIST_ENTRY xattrs
Definition: btrfs_drv.h:308
USHORT namelen
Definition: btrfs_drv.h:276
char data[1]
Definition: btrfs_drv.h:279
USHORT valuelen
Definition: btrfs_drv.h:277

Referenced by fsctl_request().

◆ fsctl_oplock()

static NTSTATUS fsctl_oplock ( device_extension Vcb,
PIRP Pirp 
)
static

Definition at line 4895 of file fsctl.c.

4895 {
4897 PIRP Irp = *Pirp;
4899 uint32_t fsctl = IrpSp->Parameters.FileSystemControl.FsControlCode;
4901 fcb* fcb = FileObject ? FileObject->FsContext : NULL;
4902 ccb* ccb = FileObject ? FileObject->FsContext2 : NULL;
4903 file_ref* fileref = ccb ? ccb->fileref : NULL;
4904#if (NTDDI_VERSION >= NTDDI_WIN7)
4905 PREQUEST_OPLOCK_INPUT_BUFFER buf = NULL;
4906 bool oplock_request = false, oplock_ack = false;
4907#else
4908 bool oplock_request = false;
4909#endif
4910 ULONG oplock_count = 0;
4911#ifdef __REACTOS__
4912 bool shared_request;
4913#endif
4914
4915 if (!fcb) {
4916 ERR("fcb was NULL\n");
4918 }
4919
4920 if (!fileref) {
4921 ERR("fileref was NULL\n");
4923 }
4924
4927
4928#if (NTDDI_VERSION >= NTDDI_WIN7)
4929 if (fsctl == FSCTL_REQUEST_OPLOCK) {
4930 if (IrpSp->Parameters.FileSystemControl.InputBufferLength < sizeof(REQUEST_OPLOCK_INPUT_BUFFER))
4932
4933 if (IrpSp->Parameters.FileSystemControl.OutputBufferLength < sizeof(REQUEST_OPLOCK_OUTPUT_BUFFER))
4935
4936 buf = Irp->AssociatedIrp.SystemBuffer;
4937
4938 // flags are mutually exclusive
4939 if (buf->Flags & REQUEST_OPLOCK_INPUT_FLAG_REQUEST && buf->Flags & REQUEST_OPLOCK_INPUT_FLAG_ACK)
4941
4942 oplock_request = buf->Flags & REQUEST_OPLOCK_INPUT_FLAG_REQUEST;
4943 oplock_ack = buf->Flags & REQUEST_OPLOCK_INPUT_FLAG_ACK;
4944
4945 if (!oplock_request && !oplock_ack)
4947 }
4948#endif
4949
4950#if (NTDDI_VERSION >= NTDDI_WIN7)
4951 bool shared_request = (fsctl == FSCTL_REQUEST_OPLOCK_LEVEL_2) || (fsctl == FSCTL_REQUEST_OPLOCK && !(buf->RequestedOplockLevel & OPLOCK_LEVEL_CACHE_WRITE));
4952#else
4953 shared_request = (fsctl == FSCTL_REQUEST_OPLOCK_LEVEL_2);
4954#endif
4955
4956#if (NTDDI_VERSION >= NTDDI_WIN7)
4957 if (fcb->type == BTRFS_TYPE_DIRECTORY && (fsctl != FSCTL_REQUEST_OPLOCK || !shared_request)) {
4958#else
4959 if (fcb->type == BTRFS_TYPE_DIRECTORY && !shared_request) {
4960#endif
4961 WARN("oplock requests on directories can only be for read or read-handle oplocks\n");
4963 }
4964
4965 ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
4966
4967 ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
4968
4970 fsctl == FSCTL_REQUEST_OPLOCK_LEVEL_2 || oplock_request) {
4971 if (shared_request) {
4972 if (fcb->type == BTRFS_TYPE_FILE) {
4974 oplock_count = !fFsRtlCheckLockForOplockRequest(&fcb->lock, &fcb->Header.AllocationSize);
4977 else
4978 oplock_count = FsRtlAreThereCurrentFileLocks(&fcb->lock);
4979 }
4980 } else
4981 oplock_count = fileref->open_count;
4982 }
4983
4984#if (NTDDI_VERSION >= NTDDI_WIN7)
4985 if ((fsctl == FSCTL_REQUEST_FILTER_OPLOCK || fsctl == FSCTL_REQUEST_BATCH_OPLOCK ||
4986 (fsctl == FSCTL_REQUEST_OPLOCK && buf->RequestedOplockLevel & OPLOCK_LEVEL_CACHE_HANDLE)) &&
4987#else
4989#endif
4990 fileref->delete_on_close) {
4991 ExReleaseResourceLite(fcb->Header.Resource);
4992 ExReleaseResourceLite(&Vcb->tree_lock);
4993 return STATUS_DELETE_PENDING;
4994 }
4995
4996 Status = FsRtlOplockFsctrl(fcb_oplock(fcb), Irp, oplock_count);
4997
4998 *Pirp = NULL;
4999
5000 fcb->Header.IsFastIoPossible = fast_io_possible(fcb);
5001
5002 ExReleaseResourceLite(fcb->Header.Resource);
5003 ExReleaseResourceLite(&Vcb->tree_lock);
5004
5005 return Status;
5006}
tFsRtlAreThereCurrentOrInProgressFileLocks fFsRtlAreThereCurrentOrInProgressFileLocks
Definition: btrfs.c:100
tFsRtlCheckLockForOplockRequest fFsRtlCheckLockForOplockRequest
Definition: btrfs.c:99
static __inline POPLOCK fcb_oplock(fcb *fcb)
Definition: btrfs_drv.h:1677
#define FsRtlAreThereCurrentFileLocks(FL)
Definition: fsrtlfuncs.h:1584
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
#define FSCTL_REQUEST_OPLOCK_LEVEL_1
Definition: nt_native.h:826
#define FSCTL_REQUEST_FILTER_OPLOCK
Definition: nt_native.h:849
#define FSCTL_REQUEST_BATCH_OPLOCK
Definition: nt_native.h:828
#define FSCTL_REQUEST_OPLOCK_LEVEL_2
Definition: nt_native.h:827
NTSTATUS NTAPI FsRtlOplockFsctrl(IN POPLOCK Oplock, IN PIRP Irp, IN ULONG OpenCount)
Definition: oplock.c:1430
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
LONG open_count
Definition: btrfs_drv.h:351
bool delete_on_close
Definition: btrfs_drv.h:345

Referenced by fsctl_request().

◆ 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
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
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
5829 break;
5830
5832 Status = set_inode_info(IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp);
5833 break;
5834
5837 break;
5838
5841 break;
5842
5844 Status = start_balance(DeviceObject->DeviceExtension, Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp->RequestorMode);
5845 break;
5846
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
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
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