ReactOS  0.4.15-dev-1018-g0695ecb
fsctl.c File Reference
#include "btrfs_drv.h"
#include "btrfsioctl.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 DEVICE_DSM_FLAG_TRIM_NOT_FS_ALLOCATED   0x80000000
 
#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 (device_extension *Vcb, 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 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)
 
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

◆ DEVICE_DSM_FLAG_TRIM_NOT_FS_ALLOCATED

#define DEVICE_DSM_FLAG_TRIM_NOT_FS_ALLOCATED   0x80000000

Definition at line 39 of file fsctl.c.

◆ DOTDOT

#define DOTDOT   ".."

Definition at line 34 of file fsctl.c.

◆ FSCTL_CSV_CONTROL

Definition at line 27 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 31 of file fsctl.c.

◆ SEF_AVOID_PRIVILEGE_CHECK

#define SEF_AVOID_PRIVILEGE_CHECK   0x08

Definition at line 36 of file fsctl.c.

◆ SEF_SACL_AUTO_INHERIT

#define SEF_SACL_AUTO_INHERIT   0x02

Definition at line 42 of file fsctl.c.

Function Documentation

◆ add_device()

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

Definition at line 2729 of file fsctl.c.

2729  {
2731  NTSTATUS Status;
2732  PFILE_OBJECT fileobj, mountmgrfo;
2734  HANDLE h;
2735  LIST_ENTRY* le;
2736  device* dev;
2737  DEV_ITEM* di;
2738  uint64_t dev_id, size;
2739  uint8_t* mb;
2740  uint64_t* stats;
2741  UNICODE_STRING mmdevpath, pnp_name, pnp_name2;
2742  volume_child* vc;
2744  KEY searchkey;
2745  traverse_ptr tp;
2748  pdo_device_extension* pdode;
2749  const GUID* pnp_guid;
2751 
2752  pnp_name.Buffer = NULL;
2753 
2754  if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), processor_mode))
2756 
2757  if (!Vcb->vde) {
2758  WARN("not allowing second device to be added to non-PNP device\n");
2759  return STATUS_NOT_SUPPORTED;
2760  }
2761 
2762  if (Vcb->readonly) // FIXME - handle adding R/W device to seeding device
2764 
2765 #if defined(_WIN64)
2766  if (IoIs32bitProcess(Irp)) {
2767  if (IrpSp->Parameters.FileSystemControl.InputBufferLength != sizeof(uint32_t))
2768  return STATUS_INVALID_PARAMETER;
2769 
2770  h = (HANDLE)LongToHandle((*(uint32_t*)Irp->AssociatedIrp.SystemBuffer));
2771  } else {
2772 #endif
2773  if (IrpSp->Parameters.FileSystemControl.InputBufferLength != sizeof(HANDLE))
2774  return STATUS_INVALID_PARAMETER;
2775 
2776  h = *(PHANDLE)Irp->AssociatedIrp.SystemBuffer;
2777 #if defined(_WIN64)
2778  }
2779 #endif
2780 
2781  Status = ObReferenceObjectByHandle(h, 0, *IoFileObjectType, Irp->RequestorMode, (void**)&fileobj, NULL);
2782 
2783  if (!NT_SUCCESS(Status)) {
2784  ERR("ObReferenceObjectByHandle returned %08lx\n", Status);
2785  return Status;
2786  }
2787 
2788  DeviceObject = fileobj->DeviceObject;
2789 
2791  if (!NT_SUCCESS(Status)) {
2792  ERR("get_device_pnp_name returned %08lx\n", Status);
2793  ObDereferenceObject(fileobj);
2794  return Status;
2795  }
2796 
2797  // If this is a disk, we have been handed the PDO, so need to go up to find something we can use
2798  if (RtlCompareMemory(pnp_guid, &GUID_DEVINTERFACE_DISK, sizeof(GUID)) == sizeof(GUID) && DeviceObject->AttachedDevice)
2799  DeviceObject = DeviceObject->AttachedDevice;
2800 
2802  if (!NT_SUCCESS(Status)) {
2803  ERR("IOCTL_DISK_IS_WRITABLE returned %08lx\n", Status);
2804  ObDereferenceObject(fileobj);
2805  return Status;
2806  }
2807 
2809  if (!NT_SUCCESS(Status)) {
2810  ERR("is_device_part_of_mounted_btrfs_raid returned %08lx\n", Status);
2811  ObDereferenceObject(fileobj);
2812  return Status;
2813  }
2814 
2815  // if disk, check it has no partitions
2816  if (RtlCompareMemory(pnp_guid, &GUID_DEVINTERFACE_DISK, sizeof(GUID)) == sizeof(GUID)) {
2817  ULONG dlisize;
2819 
2820  dlisize = 0;
2821 
2822  do {
2823  dlisize += 1024;
2824 
2825  if (dli)
2826  ExFreePool(dli);
2827 
2828  dli = ExAllocatePoolWithTag(PagedPool, dlisize, ALLOC_TAG);
2829  if (!dli) {
2830  ERR("out of memory\n");
2832  goto end2;
2833  }
2834 
2836  } while (Status == STATUS_BUFFER_TOO_SMALL);
2837 
2838  if (NT_SUCCESS(Status) && dli->PartitionCount > 0) {
2839  ExFreePool(dli);
2840  ERR("not adding disk which has partitions\n");
2842  goto end2;
2843  }
2844 
2845  ExFreePool(dli);
2846  }
2847 
2849  &sdn, sizeof(STORAGE_DEVICE_NUMBER), true, NULL);
2850  if (NT_SUCCESS(Status)) {
2851  if (sdn.DeviceType != FILE_DEVICE_DISK) { // FIXME - accept floppies and CDs?
2852  WARN("device was not disk\n");
2853  ObDereferenceObject(fileobj);
2854  return STATUS_INVALID_PARAMETER;
2855  }
2856  } else {
2857  sdn.DeviceNumber = 0xffffffff;
2858  sdn.PartitionNumber = 0xffffffff;
2859  }
2860 
2862  &gli, sizeof(gli), true, NULL);
2863  if (!NT_SUCCESS(Status)) {
2864  ERR("error reading length information: %08lx\n", Status);
2865  ObDereferenceObject(fileobj);
2866  return Status;
2867  }
2868 
2869  size = gli.Length.QuadPart;
2870 
2871  if (size < 0x100000) {
2872  ERR("device was not large enough to hold FS (%I64x bytes, need at least 1 MB)\n", size);
2873  ObDereferenceObject(fileobj);
2874  return STATUS_INTERNAL_ERROR;
2875  }
2876 
2878 
2879  ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
2880 
2881  if (Vcb->need_write)
2882  Status = do_write(Vcb, Irp);
2883  else
2885 
2886  free_trees(Vcb);
2887 
2888  if (!NT_SUCCESS(Status)) {
2889  ERR("do_write returned %08lx\n", Status);
2890  goto end;
2891  }
2892 
2894  if (!dev) {
2895  ERR("out of memory\n");
2897  goto end;
2898  }
2899 
2900  RtlZeroMemory(dev, sizeof(device));
2901 
2902  dev->devobj = DeviceObject;
2903  dev->fileobj = fileobj;
2904  dev->seeding = false;
2905  init_device(Vcb, dev, true);
2906 
2907  InitializeListHead(&dev->space);
2908 
2909  if (size > 0x100000) { // add disk hole - the first MB is marked as used
2910  Status = add_space_entry(&dev->space, NULL, 0x100000, size - 0x100000);
2911  if (!NT_SUCCESS(Status)) {
2912  ERR("add_space_entry returned %08lx\n", Status);
2913  goto end;
2914  }
2915  }
2916 
2917  dev_id = 0;
2918 
2919  le = Vcb->devices.Flink;
2920  while (le != &Vcb->devices) {
2921  device* dev2 = CONTAINING_RECORD(le, device, list_entry);
2922 
2923  if (dev2->devitem.dev_id > dev_id)
2924  dev_id = dev2->devitem.dev_id;
2925 
2926  le = le->Flink;
2927  }
2928 
2929  dev_id++;
2930 
2931  dev->devitem.dev_id = dev_id;
2932  dev->devitem.num_bytes = size;
2933  dev->devitem.bytes_used = 0;
2934  dev->devitem.optimal_io_align = Vcb->superblock.sector_size;
2935  dev->devitem.optimal_io_width = Vcb->superblock.sector_size;
2936  dev->devitem.minimal_io_size = Vcb->superblock.sector_size;
2937  dev->devitem.type = 0;
2938  dev->devitem.generation = 0;
2939  dev->devitem.start_offset = 0;
2940  dev->devitem.dev_group = 0;
2941  dev->devitem.seek_speed = 0;
2942  dev->devitem.bandwidth = 0;
2943  get_uuid(&dev->devitem.device_uuid);
2944  dev->devitem.fs_uuid = Vcb->superblock.uuid;
2945 
2947  if (!di) {
2948  ERR("out of memory\n");
2949  goto end;
2950  }
2951 
2952  RtlCopyMemory(di, &dev->devitem, sizeof(DEV_ITEM));
2953 
2954  Status = insert_tree_item(Vcb, Vcb->chunk_root, 1, TYPE_DEV_ITEM, di->dev_id, di, sizeof(DEV_ITEM), NULL, Irp);
2955  if (!NT_SUCCESS(Status)) {
2956  ERR("insert_tree_item returned %08lx\n", Status);
2957  ExFreePool(di);
2958  goto end;
2959  }
2960 
2961  // add stats entry to dev tree
2962  stats = ExAllocatePoolWithTag(PagedPool, sizeof(uint64_t) * 5, ALLOC_TAG);
2963  if (!stats) {
2964  ERR("out of memory\n");
2966  goto end;
2967  }
2968 
2969  RtlZeroMemory(stats, sizeof(uint64_t) * 5);
2970 
2971  searchkey.obj_id = 0;
2972  searchkey.obj_type = TYPE_DEV_STATS;
2973  searchkey.offset = di->dev_id;
2974 
2975  Status = find_item(Vcb, Vcb->dev_root, &tp, &searchkey, false, Irp);
2976  if (!NT_SUCCESS(Status)) {
2977  ERR("error - find_item returned %08lx\n", Status);
2978  ExFreePool(stats);
2979  goto end;
2980  }
2981 
2982  if (!keycmp(tp.item->key, searchkey)) {
2984  if (!NT_SUCCESS(Status)) {
2985  ERR("delete_tree_item returned %08lx\n", Status);
2986  ExFreePool(stats);
2987  goto end;
2988  }
2989  }
2990 
2991  Status = insert_tree_item(Vcb, Vcb->dev_root, 0, TYPE_DEV_STATS, di->dev_id, stats, sizeof(uint64_t) * 5, NULL, Irp);
2992  if (!NT_SUCCESS(Status)) {
2993  ERR("insert_tree_item returned %08lx\n", Status);
2994  ExFreePool(stats);
2995  goto end;
2996  }
2997 
2998  if (dev->trim && !dev->readonly && !Vcb->options.no_trim)
3000 
3001  // We clear the first megabyte of the device, so Windows doesn't identify it as another FS
3002  mb = ExAllocatePoolWithTag(PagedPool, 0x100000, ALLOC_TAG);
3003  if (!mb) {
3004  ERR("out of memory\n");
3006  goto end;
3007  }
3008 
3009  RtlZeroMemory(mb, 0x100000);
3010 
3011  Status = write_data_phys(DeviceObject, fileobj, 0, mb, 0x100000);
3012  if (!NT_SUCCESS(Status)) {
3013  ERR("write_data_phys returned %08lx\n", Status);
3014  ExFreePool(mb);
3015  goto end;
3016  }
3017 
3018  ExFreePool(mb);
3019 
3020  vde = Vcb->vde;
3021  pdode = vde->pdode;
3022 
3024  if (!vc) {
3025  ERR("out of memory\n");
3027  goto end;
3028  }
3029 
3030  vc->uuid = dev->devitem.device_uuid;
3031  vc->devid = dev_id;
3032  vc->generation = Vcb->superblock.generation;
3033  vc->devobj = DeviceObject;
3034  vc->fileobj = fileobj;
3035  vc->notification_entry = NULL;
3036  vc->boot_volume = false;
3037 
3039  drvobj, pnp_removal, vde->pdode, &vc->notification_entry);
3040  if (!NT_SUCCESS(Status))
3041  WARN("IoRegisterPlugPlayNotification returned %08lx\n", Status);
3042 
3043  pnp_name2 = pnp_name;
3044 
3045  if (pnp_name.Length > 4 * sizeof(WCHAR) && pnp_name.Buffer[0] == '\\' && (pnp_name.Buffer[1] == '\\' || pnp_name.Buffer[1] == '?') &&
3046  pnp_name.Buffer[2] == '?' && pnp_name.Buffer[3] == '\\') {
3047  pnp_name2.Buffer = &pnp_name2.Buffer[3];
3048  pnp_name2.Length -= 3 * sizeof(WCHAR);
3049  pnp_name2.MaximumLength -= 3 * sizeof(WCHAR);
3050  }
3051 
3052  vc->pnp_name.Length = vc->pnp_name.MaximumLength = pnp_name2.Length;
3053 
3054  if (pnp_name2.Length == 0)
3055  vc->pnp_name.Buffer = NULL;
3056  else {
3058  if (!vc->pnp_name.Buffer) {
3059  ERR("out of memory\n");
3061  goto end;
3062  }
3063 
3064  RtlCopyMemory(vc->pnp_name.Buffer, pnp_name2.Buffer, pnp_name2.Length);
3065  }
3066 
3067  vc->size = size;
3068  vc->seeding = false;
3069  vc->disk_num = sdn.DeviceNumber;
3070  vc->part_num = sdn.PartitionNumber;
3071  vc->had_drive_letter = false;
3072 
3074  InsertTailList(&pdode->children, &vc->list_entry);
3075  pdode->num_children++;
3076  pdode->children_loaded++;
3078 
3080  Status = IoGetDeviceObjectPointer(&mmdevpath, FILE_READ_ATTRIBUTES, &mountmgrfo, &mountmgr);
3081  if (!NT_SUCCESS(Status))
3082  ERR("IoGetDeviceObjectPointer returned %08lx\n", Status);
3083  else {
3086  WARN("remove_drive_letter returned %08lx\n", Status);
3087 
3089 
3090  ObDereferenceObject(mountmgrfo);
3091  }
3092 
3093  Vcb->superblock.num_devices++;
3094  Vcb->superblock.total_bytes += size;
3095  Vcb->devices_loaded++;
3096  InsertTailList(&Vcb->devices, &dev->list_entry);
3097 
3098  // FIXME - send notification that volume size has increased
3099 
3100  ObReferenceObject(DeviceObject); // for Vcb
3101 
3102  Status = do_write(Vcb, Irp);
3103  if (!NT_SUCCESS(Status))
3104  ERR("do_write returned %08lx\n", Status);
3105 
3106  ObReferenceObject(fileobj);
3107 
3108 end:
3109  free_trees(Vcb);
3110 
3111  ExReleaseResourceLite(&Vcb->tree_lock);
3112 
3113 end2:
3114  ObDereferenceObject(fileobj);
3115 
3116  if (pnp_name.Buffer)
3118 
3119  if (NT_SUCCESS(Status))
3121 
3122  return Status;
3123 }
DEVICE_TYPE DeviceType
Definition: ntddstor.h:313
uint64_t obj_id
Definition: btrfs.h:137
bool boot_volume
Definition: btrfs_drv.h:874
#define TYPE_DEV_ITEM
Definition: btrfs.h:43
#define FILE_DEVICE_DISK
Definition: winioctl.h:112
#define STATUS_PRIVILEGE_NOT_HELD
Definition: DriverTester.h:9
UNICODE_STRING pnp_name
Definition: btrfs_drv.h:867
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
uint8_t obj_type
Definition: btrfs.h:138
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
USHORT MaximumLength
Definition: env_spec_w32.h:370
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define TYPE_DEV_STATS
Definition: btrfs.h:46
NTSTATUS do_write(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7789
#define keycmp(key1, key2)
Definition: btrfs_drv.h:1024
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
#define IOCTL_DISK_IS_WRITABLE
Definition: cdrw_usr.h:172
BOOLEAN NTAPI SeSinglePrivilegeCheck(IN LUID PrivilegeValue, IN KPROCESSOR_MODE PreviousMode)
Definition: priv.c:524
NTSTATUS NTAPI IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName, IN ACCESS_MASK DesiredAccess, OUT PFILE_OBJECT *FileObject, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1435
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
GLuint GLuint end
Definition: gl.h:1545
ULONG part_num
Definition: btrfs_drv.h:873
#define InsertTailList(ListHead, Entry)
static void get_uuid(BTRFS_UUID *uuid)
Definition: fsctl.c:76
uint64_t offset
Definition: btrfs.h:139
#define MOUNTMGR_DEVICE_NAME
Definition: imports.h:76
static int dev
Definition: mkdosfs.c:536
void init_device(_In_ device_extension *Vcb, _Inout_ device *dev, _In_ bool get_nums)
Definition: btrfs.c:3349
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
BTRFS_UUID uuid
Definition: btrfs_drv.h:862
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
uint64_t num_children
Definition: btrfs_drv.h:902
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define ALLOC_TAG
Definition: btrfs_drv.h:91
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:496
uint64_t generation
Definition: btrfs_drv.h:864
NTSTATUS add_space_entry(LIST_ENTRY *list, LIST_ENTRY *list_size, uint64_t offset, uint64_t size)
Definition: free-space.c:190
PDRIVER_OBJECT drvobj
Definition: btrfs.c:68
Definition: devices.h:37
bool seeding
Definition: btrfs_drv.h:869
smooth NULL
Definition: ftsmooth.c:416
PDEVICE_OBJECT devobj
Definition: btrfs_drv.h:865
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
#define IOCTL_STORAGE_GET_DEVICE_NUMBER
Definition: ntddstor.h:132
struct pdo_device_extension * pdode
Definition: btrfs_drv.h:886
static NTSTATUS is_device_part_of_mounted_btrfs_raid(PDEVICE_OBJECT devobj, PFILE_OBJECT fileobj)
Definition: fsctl.c:2631
void free_trees(device_extension *Vcb)
Definition: treefuncs.c:794
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define IOCTL_DISK_GET_LENGTH_INFO
Definition: imports.h:192
#define FSRTL_VOLUME_CHANGE_SIZE
Definition: fsrtltypes.h:101
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2930
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define STATUS_NOT_FOUND
Definition: shellext.h:72
uint64_t children_loaded
Definition: btrfs_drv.h:903
NTSTATUS get_device_pnp_name(_In_ PDEVICE_OBJECT DeviceObject, _Out_ PUNICODE_STRING pnp_name, _Out_ const GUID **guid)
Definition: btrfs.c:4192
GLsizeiptr size
Definition: glext.h:5919
NTSTATUS NTAPI FsRtlNotifyVolumeEvent(IN PFILE_OBJECT FileObject, IN ULONG EventCode)
Definition: pnp.c:38
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:65
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
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:2888
bool had_drive_letter
Definition: btrfs_drv.h:870
#define Vcb
Definition: cdprocs.h:1415
PVOID HANDLE
Definition: typedefs.h:73
ERESOURCE child_lock
Definition: btrfs_drv.h:904
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
void * notification_entry
Definition: btrfs_drv.h:871
* PFILE_OBJECT
Definition: iotypes.h:1962
ULONG disk_num
Definition: btrfs_drv.h:872
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)
Definition: treefuncs.c:858
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
tree_data * item
Definition: btrfs_drv.h:518
PFILE_OBJECT fileobj
Definition: btrfs_drv.h:866
Status
Definition: gdiplustypes.h:24
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:454
uint64_t dev_id
Definition: btrfs.h:171
#define LongToHandle(h)
Definition: basetsd.h:82
NTSTATUS NTAPI IoRegisterPlugPlayNotification(IN IO_NOTIFICATION_EVENT_CATEGORY EventCategory, IN ULONG EventCategoryFlags, IN PVOID EventCategoryData OPTIONAL, IN PDRIVER_OBJECT DriverObject, IN PDRIVER_NOTIFICATION_CALLBACK_ROUTINE CallbackRoutine, IN PVOID Context, OUT PVOID *NotificationEntry)
Definition: pnpnotify.c:249
Definition: typedefs.h:119
POBJECT_TYPE IoFileObjectType
Definition: iomgr.c:36
BYTE uint8_t
Definition: msvideo1.c:66
LARGE_INTEGER Length
Definition: winioctl.h:423
#define ERR(fmt,...)
Definition: debug.h:110
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1569
Definition: btrfs.h:136
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2789
#define SE_MANAGE_VOLUME_PRIVILEGE
Definition: security.c:682
UINT64 uint64_t
Definition: types.h:77
#define IOCTL_DISK_GET_DRIVE_LAYOUT_EX
Definition: ntddk_ex.h:207
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
Definition: list.h:27
DEV_ITEM devitem
Definition: btrfs_drv.h:536
uint64_t dev_id
UINT32 uint32_t
Definition: types.h:75
UNICODE_STRING pnp_name
Definition: btrfs.c:4221
void trim_whole_device(device *dev)
Definition: fsctl.c:2710
uint64_t size
Definition: btrfs_drv.h:868
#define ObReferenceObject
Definition: obfuncs.h:204
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
LIST_ENTRY list_entry
Definition: btrfs_drv.h:875
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSTATUS remove_drive_letter(PDEVICE_OBJECT mountmgr, PUNICODE_STRING devpath)
Definition: search.c:205
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint64_t devid
Definition: btrfs_drv.h:863
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2779
LIST_ENTRY children
Definition: btrfs_drv.h:905
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
LONGLONG QuadPart
Definition: typedefs.h:114
NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp)
Definition: treefuncs.c:990
void volume_removal(PDRIVER_OBJECT DriverObject, PUNICODE_STRING devpath)
Definition: search.c:586
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70

Referenced by fsctl_request().

◆ allow_extended_dasd_io()

static NTSTATUS allow_extended_dasd_io ( device_extension Vcb,
PFILE_OBJECT  FileObject 
)
static

Definition at line 3125 of file fsctl.c.

3125  {
3126  fcb* fcb;
3127  ccb* ccb;
3128 
3129  TRACE("FSCTL_ALLOW_EXTENDED_DASD_IO\n");
3130 
3131  if (!FileObject)
3132  return STATUS_INVALID_PARAMETER;
3133 
3134  fcb = FileObject->FsContext;
3135  ccb = FileObject->FsContext2;
3136 
3137  if (!fcb)
3138  return STATUS_INVALID_PARAMETER;
3139 
3140  if (fcb != Vcb->volume_fcb)
3141  return STATUS_INVALID_PARAMETER;
3142 
3143  if (!ccb)
3144  return STATUS_INVALID_PARAMETER;
3145 
3146  ccb->allow_extended_dasd_io = true;
3147 
3148  return STATUS_SUCCESS;
3149 }
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:588
#define TRACE(s)
Definition: solgame.cpp:4
struct _fcb fcb
Definition: btrfs_drv.h:1357
#define Vcb
Definition: cdprocs.h:1415
bool allow_extended_dasd_io
Definition: btrfs_drv.h:396
struct _ccb ccb
return STATUS_SUCCESS
Definition: btrfs.c:3014

Referenced by fsctl_request().

◆ create_snapshot()

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

Definition at line 523 of file fsctl.c.

523  {
524  PFILE_OBJECT subvol_obj;
527  fcb* subvol_fcb;
528  HANDLE subvolh;
529  bool readonly, posix;
530  ANSI_STRING utf8;
531  UNICODE_STRING nameus;
532  ULONG len;
533  fcb* fcb;
534  ccb* ccb;
535  file_ref *fileref, *fr2;
536 
537 #if defined(_WIN64)
538  if (IoIs32bitProcess(Irp)) {
539  btrfs_create_snapshot32* bcs32 = data;
540 
543 
546 
547  subvolh = Handle32ToHandle(bcs32->subvol);
548 
549  nameus.Buffer = bcs32->name;
550  nameus.Length = nameus.MaximumLength = bcs32->namelen;
551 
552  readonly = bcs32->readonly;
553  posix = bcs32->posix;
554  } else {
555 #endif
558 
561 
562  subvolh = bcs->subvol;
563 
564  nameus.Buffer = bcs->name;
565  nameus.Length = nameus.MaximumLength = bcs->namelen;
566 
567  readonly = bcs->readonly;
568  posix = bcs->posix;
569 #if defined(_WIN64)
570  }
571 #endif
572 
573  if (!subvolh)
575 
576  if (!FileObject || !FileObject->FsContext)
578 
579  fcb = FileObject->FsContext;
580  ccb = FileObject->FsContext2;
581 
582  if (!fcb || !ccb || fcb->type != BTRFS_TYPE_DIRECTORY)
584 
585  fileref = ccb->fileref;
586 
587  if (!fileref) {
588  ERR("fileref was NULL\n");
590  }
591 
592  if (!(ccb->access & FILE_ADD_SUBDIRECTORY)) {
593  WARN("insufficient privileges\n");
594  return STATUS_ACCESS_DENIED;
595  }
596 
597  if (Vcb->readonly)
599 
601  return STATUS_ACCESS_DENIED;
602 
603  if (!is_file_name_valid(&nameus, posix, false))
605 
606  utf8.Buffer = NULL;
607 
608  Status = utf16_to_utf8(NULL, 0, &len, nameus.Buffer, nameus.Length);
609  if (!NT_SUCCESS(Status)) {
610  ERR("utf16_to_utf8 failed with error %08lx\n", Status);
611  return Status;
612  }
613 
614  if (len == 0) {
615  ERR("utf16_to_utf8 returned a length of 0\n");
616  return STATUS_INTERNAL_ERROR;
617  }
618 
619  if (len > 0xffff) {
620  ERR("len was too long\n");
622  }
623 
624  utf8.MaximumLength = utf8.Length = (USHORT)len;
626 
627  if (!utf8.Buffer) {
628  ERR("out of memory\n");
630  }
631 
632  Status = utf16_to_utf8(utf8.Buffer, len, &len, nameus.Buffer, nameus.Length);
633  if (!NT_SUCCESS(Status)) {
634  ERR("utf16_to_utf8 failed with error %08lx\n", Status);
635  goto end2;
636  }
637 
638  ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
639 
640  // no need for fcb_lock as we have tree_lock exclusively
641  Status = open_fileref(fcb->Vcb, &fr2, &nameus, fileref, false, NULL, NULL, PagedPool, ccb->case_sensitive || posix, Irp);
642 
643  if (NT_SUCCESS(Status)) {
644  if (!fr2->deleted) {
645  WARN("file already exists\n");
646  free_fileref(fr2);
648  goto end3;
649  } else
650  free_fileref(fr2);
652  ERR("open_fileref returned %08lx\n", Status);
653  goto end3;
654  }
655 
656  Status = ObReferenceObjectByHandle(subvolh, 0, *IoFileObjectType, Irp->RequestorMode, (void**)&subvol_obj, NULL);
657  if (!NT_SUCCESS(Status)) {
658  ERR("ObReferenceObjectByHandle returned %08lx\n", Status);
659  goto end3;
660  }
661 
662  if (subvol_obj->DeviceObject != FileObject->DeviceObject) {
664  goto end;
665  }
666 
667  subvol_fcb = subvol_obj->FsContext;
668  if (!subvol_fcb) {
670  goto end;
671  }
672 
673  if (subvol_fcb->inode != subvol_fcb->subvol->root_item.objid) {
674  WARN("handle inode was %I64x, expected %I64x\n", subvol_fcb->inode, subvol_fcb->subvol->root_item.objid);
676  goto end;
677  }
678 
679  ccb = subvol_obj->FsContext2;
680 
681  if (!ccb) {
683  goto end;
684  }
685 
686  if (!(ccb->access & FILE_TRAVERSE)) {
687  WARN("insufficient privileges\n");
689  goto end;
690  }
691 
692  if (fcb == Vcb->dummy_fcb) {
694  goto end;
695  }
696 
697  // clear unique flag on extents of open files in subvol
698  if (!IsListEmpty(&subvol_fcb->subvol->fcbs)) {
699  LIST_ENTRY* le = subvol_fcb->subvol->fcbs.Flink;
700 
701  while (le != &subvol_fcb->subvol->fcbs) {
702  struct _fcb* openfcb = CONTAINING_RECORD(le, struct _fcb, list_entry);
703  LIST_ENTRY* le2;
704 
705  le2 = openfcb->extents.Flink;
706 
707  while (le2 != &openfcb->extents) {
709 
710  ext->unique = false;
711 
712  le2 = le2->Flink;
713  }
714 
715  le = le->Flink;
716  }
717  }
718 
719  Status = do_create_snapshot(Vcb, FileObject, subvol_fcb, &utf8, &nameus, readonly, Irp);
720 
721  if (NT_SUCCESS(Status)) {
722  file_ref* fr;
723 
724  Status = open_fileref(Vcb, &fr, &nameus, fileref, false, NULL, NULL, PagedPool, false, Irp);
725 
726  if (!NT_SUCCESS(Status)) {
727  ERR("open_fileref returned %08lx\n", Status);
729  } else {
731  free_fileref(fr);
732  }
733  }
734 
735 end:
736  ObDereferenceObject(subvol_obj);
737 
738 end3:
739  ExReleaseResourceLite(&Vcb->tree_lock);
740 
741 end2:
742  ExFreePool(utf8.Buffer);
743 
744  return Status;
745 }
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
USHORT MaximumLength
Definition: env_spec_w32.h:370
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
GLuint GLuint end
Definition: gl.h:1545
ACCESS_MASK access
Definition: btrfs_drv.h:398
#define FILE_NOTIFY_CHANGE_DIR_NAME
void send_notification_fileref(_In_ file_ref *fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream)
Definition: btrfs.c:1449
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define ALLOC_TAG
Definition: btrfs_drv.h:91
#define FILE_TRAVERSE
Definition: nt_native.h:643
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:496
static __inline bool is_subvol_readonly(root *r, PIRP Irp)
Definition: btrfs_drv.h:1041
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:86
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
char ext[3]
Definition: mkdosfs.c:358
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
static string utf16_to_utf8(const wstring_view &utf16)
Definition: main.cpp:672
uint8_t type
Definition: btrfs_drv.h:302
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:588
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
bool deleted
Definition: btrfs_drv.h:362
USHORT MaximumLength
Definition: env_spec_w32.h:377
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
struct _fcb fcb
Definition: btrfs_drv.h:1357
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
uint64_t inode
Definition: btrfs_drv.h:300
#define Vcb
Definition: cdprocs.h:1415
struct _file_ref * fileref
Definition: btrfs_drv.h:316
LIST_ENTRY extents
Definition: btrfs_drv.h:311
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
* PFILE_OBJECT
Definition: iotypes.h:1962
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
Status
Definition: gdiplustypes.h:24
bool case_sensitive
Definition: btrfs_drv.h:402
#define FILE_ADD_SUBDIRECTORY
Definition: nt_native.h:635
GLenum GLsizei len
Definition: glext.h:6722
Definition: typedefs.h:119
POBJECT_TYPE IoFileObjectType
Definition: iomgr.c:36
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:1680
void *POINTER_32 subvol
Definition: btrfsioctl.h:56
bool is_file_name_valid(_In_ PUNICODE_STRING us, _In_ bool posix, _In_ bool stream)
Definition: btrfs.c:5724
#define ERR(fmt,...)
Definition: debug.h:110
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
unsigned short USHORT
Definition: pedump.c:61
#define STATUS_OBJECT_NAME_INVALID
Definition: udferr_usr.h:148
struct _root * subvol
Definition: btrfs_drv.h:299
Definition: list.h:27
void free_fileref(_Inout_ file_ref *fr)
Definition: btrfs.c:1786
#define FILE_ACTION_ADDED
Definition: name.c:38
unsigned int ULONG
Definition: retypes.h:1
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:263
struct _ccb ccb
file_ref * fileref
Definition: btrfs_drv.h:399
return STATUS_SUCCESS
Definition: btrfs.c:3014
struct _device_extension * Vcb
Definition: btrfs_drv.h:298
#define ExFreePool(addr)
Definition: env_spec_w32.h:352

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 747 of file fsctl.c.

747  {
748  btrfs_create_subvol* bcs;
749  fcb *fcb, *rootfcb = NULL;
750  ccb* ccb;
751  file_ref* fileref;
753  uint64_t id;
754  root* r = NULL;
756  BTRFS_TIME now;
757  ULONG len;
758  uint16_t irsize;
759  UNICODE_STRING nameus;
760  ANSI_STRING utf8;
761  INODE_REF* ir;
762  KEY searchkey;
764  SECURITY_SUBJECT_CONTEXT subjcont;
765  PSID owner;
766  BOOLEAN defaulted;
767  uint64_t* root_num;
768  file_ref *fr = NULL, *fr2;
769  dir_child* dc = NULL;
770 
771  fcb = FileObject->FsContext;
772  if (!fcb) {
773  ERR("error - fcb was NULL\n");
774  return STATUS_INTERNAL_ERROR;
775  }
776 
777  ccb = FileObject->FsContext2;
778  if (!ccb) {
779  ERR("error - ccb was NULL\n");
780  return STATUS_INTERNAL_ERROR;
781  }
782 
783  fileref = ccb->fileref;
784 
785  if (fcb->type != BTRFS_TYPE_DIRECTORY) {
786  ERR("parent FCB was not a directory\n");
787  return STATUS_NOT_A_DIRECTORY;
788  }
789 
790  if (!fileref) {
791  ERR("fileref was NULL\n");
793  }
794 
795  if (fileref->deleted || fcb->deleted) {
796  ERR("parent has been deleted\n");
797  return STATUS_FILE_DELETED;
798  }
799 
800  if (!(ccb->access & FILE_ADD_SUBDIRECTORY)) {
801  WARN("insufficient privileges\n");
802  return STATUS_ACCESS_DENIED;
803  }
804 
805  if (Vcb->readonly)
807 
809  return STATUS_ACCESS_DENIED;
810 
811  if (fcb == Vcb->dummy_fcb)
812  return STATUS_ACCESS_DENIED;
813 
814  if (!data || datalen < sizeof(btrfs_create_subvol))
816 
817  bcs = (btrfs_create_subvol*)data;
818 
819  if (offsetof(btrfs_create_subvol, name[0]) + bcs->namelen > datalen)
821 
822  nameus.Length = nameus.MaximumLength = bcs->namelen;
823  nameus.Buffer = bcs->name;
824 
825  if (!is_file_name_valid(&nameus, bcs->posix, false))
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");
838  return STATUS_INTERNAL_ERROR;
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 
906  root_num = ExAllocatePoolWithTag(PagedPool, sizeof(uint64_t), ALLOC_TAG);
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 = 0xffffffff80000000; // FIXME - find out what these mean
940 
941  if (bcs->readonly)
942  r->root_item.flags |= BTRFS_SUBVOL_READONLY;
943 
944  r->root_item.objid = SUBVOL_ROOT_INODE;
945  r->root_item.bytes_used = Vcb->superblock.node_size;
946  r->root_item.ctransid = Vcb->superblock.generation;
947  r->root_item.otransid = Vcb->superblock.generation;
948  r->root_item.ctime = now;
949  r->root_item.otime = now;
950 
951  // add .. inode to new subvol
952 
953  rootfcb = create_fcb(Vcb, PagedPool);
954  if (!rootfcb) {
955  ERR("out of memory\n");
957  goto end;
958  }
959 
960  rootfcb->Vcb = Vcb;
961 
962  rootfcb->subvol = r;
963  rootfcb->inode = SUBVOL_ROOT_INODE;
964  rootfcb->type = BTRFS_TYPE_DIRECTORY;
965 
966  rootfcb->inode_item.generation = Vcb->superblock.generation;
967  rootfcb->inode_item.transid = Vcb->superblock.generation;
968  rootfcb->inode_item.st_nlink = 1;
969  rootfcb->inode_item.st_mode = __S_IFDIR | inherit_mode(fileref->fcb, true);
970  rootfcb->inode_item.st_atime = rootfcb->inode_item.st_ctime = rootfcb->inode_item.st_mtime = rootfcb->inode_item.otime = now;
971  rootfcb->inode_item.st_gid = GID_NOBODY;
972 
973  rootfcb->atts = get_file_attributes(Vcb, rootfcb->subvol, rootfcb->inode, rootfcb->type, false, true, Irp);
974 
975  if (r->root_item.flags & BTRFS_SUBVOL_READONLY)
976  rootfcb->atts |= FILE_ATTRIBUTE_READONLY;
977 
978  SeCaptureSubjectContext(&subjcont);
979 
980  Status = SeAssignSecurity(fcb->sd, NULL, (void**)&rootfcb->sd, true, &subjcont, IoGetFileObjectGenericMapping(), PagedPool);
981 
982  if (!NT_SUCCESS(Status)) {
983  ERR("SeAssignSecurity returned %08lx\n", Status);
984  goto end;
985  }
986 
987  if (!rootfcb->sd) {
988  ERR("SeAssignSecurity returned NULL security descriptor\n");
990  goto end;
991  }
992 
993  Status = RtlGetOwnerSecurityDescriptor(rootfcb->sd, &owner, &defaulted);
994  if (!NT_SUCCESS(Status)) {
995  ERR("RtlGetOwnerSecurityDescriptor returned %08lx\n", Status);
996  rootfcb->inode_item.st_uid = UID_NOBODY;
997  rootfcb->sd_dirty = true;
998  } else {
999  rootfcb->inode_item.st_uid = sid_to_uid(owner);
1000  rootfcb->sd_dirty = rootfcb->inode_item.st_uid == UID_NOBODY;
1001  }
1002 
1003  find_gid(rootfcb, fileref->fcb, &subjcont);
1004 
1005  rootfcb->inode_item_changed = true;
1006 
1007  acquire_fcb_lock_exclusive(Vcb);
1008  InsertTailList(&r->fcbs, &rootfcb->list_entry);
1009  InsertTailList(&Vcb->all_fcbs, &rootfcb->list_entry_all);
1010  r->fcbs_version++;
1011  release_fcb_lock(Vcb);
1012 
1013  rootfcb->Header.IsFastIoPossible = fast_io_possible(rootfcb);
1014  rootfcb->Header.AllocationSize.QuadPart = 0;
1015  rootfcb->Header.FileSize.QuadPart = 0;
1016  rootfcb->Header.ValidDataLength.QuadPart = 0;
1017 
1018  rootfcb->created = true;
1019 
1020  if (fileref->fcb->inode_item.flags & BTRFS_INODE_COMPRESS)
1022 
1023  rootfcb->prop_compression = fileref->fcb->prop_compression;
1025 
1026  r->lastinode = rootfcb->inode;
1027 
1028  // add INODE_REF
1029 
1030  irsize = (uint16_t)(offsetof(INODE_REF, name[0]) + sizeof(DOTDOT) - 1);
1031  ir = ExAllocatePoolWithTag(PagedPool, irsize, ALLOC_TAG);
1032  if (!ir) {
1033  ERR("out of memory\n");
1035  goto end;
1036  }
1037 
1038  ir->index = 0;
1039  ir->n = sizeof(DOTDOT) - 1;
1040  RtlCopyMemory(ir->name, DOTDOT, ir->n);
1041 
1042  Status = insert_tree_item(Vcb, r, r->root_item.objid, TYPE_INODE_REF, r->root_item.objid, ir, irsize, NULL, Irp);
1043  if (!NT_SUCCESS(Status)) {
1044  ERR("insert_tree_item returned %08lx\n", Status);
1045  ExFreePool(ir);
1046  goto end;
1047  }
1048 
1049  // create fileref for entry in other subvolume
1050 
1051  fr = create_fileref(Vcb);
1052  if (!fr) {
1053  ERR("out of memory\n");
1054 
1055  reap_fcb(rootfcb);
1056 
1058  goto end;
1059  }
1060 
1061  fr->fcb = rootfcb;
1062 
1063  mark_fcb_dirty(rootfcb);
1064 
1065  fr->parent = fileref;
1066 
1067  Status = add_dir_child(fileref->fcb, r->id, true, &utf8, &nameus, BTRFS_TYPE_DIRECTORY, &dc);
1068  if (!NT_SUCCESS(Status))
1069  WARN("add_dir_child returned %08lx\n", Status);
1070 
1071  fr->dc = dc;
1072  dc->fileref = fr;
1073 
1075  if (!fr->fcb->hash_ptrs) {
1076  ERR("out of memory\n");
1077  free_fileref(fr);
1079  goto end;
1080  }
1081 
1082  RtlZeroMemory(fr->fcb->hash_ptrs, sizeof(LIST_ENTRY*) * 256);
1083 
1085  if (!fr->fcb->hash_ptrs_uc) {
1086  ERR("out of memory\n");
1087  free_fileref(fr);
1089  goto end;
1090  }
1091 
1092  RtlZeroMemory(fr->fcb->hash_ptrs_uc, sizeof(LIST_ENTRY*) * 256);
1093 
1094  ExAcquireResourceExclusiveLite(&fileref->fcb->nonpaged->dir_children_lock, true);
1095  InsertTailList(&fileref->children, &fr->list_entry);
1096  ExReleaseResourceLite(&fileref->fcb->nonpaged->dir_children_lock);
1097 
1099 
1100  if (fr->fcb->type == BTRFS_TYPE_DIRECTORY)
1101  fr->fcb->fileref = fr;
1102 
1103  fr->created = true;
1104  mark_fileref_dirty(fr);
1105 
1106  // change fcb->subvol's ROOT_ITEM
1107 
1108  fcb->subvol->root_item.ctransid = Vcb->superblock.generation;
1109  fcb->subvol->root_item.ctime = now;
1110 
1111  // change fcb's INODE_ITEM
1112 
1113  fcb->inode_item.transid = Vcb->superblock.generation;
1114  fcb->inode_item.st_size += utf8.Length * 2;
1115  fcb->inode_item.sequence++;
1116 
1117  if (!ccb->user_set_change_time)
1119 
1120  if (!ccb->user_set_write_time)
1122 
1123  fcb->inode_item_changed = true;
1125 
1126  fr->fcb->subvol->parent = fcb->subvol->id;
1127 
1129 
1130 end:
1131  if (!NT_SUCCESS(Status)) {
1132  if (fr) {
1133  fr->deleted = true;
1134  mark_fileref_dirty(fr);
1135  } else if (rootfcb) {
1136  rootfcb->deleted = true;
1137  mark_fcb_dirty(rootfcb);
1138  }
1139 
1140  if (r) {
1141  RemoveEntryList(&r->list_entry);
1142  InsertTailList(&Vcb->drop_roots, &r->list_entry);
1143  }
1144  }
1145 
1146  ExReleaseResourceLite(&Vcb->tree_lock);
1147 
1148  if (NT_SUCCESS(Status)) {
1151  }
1152 
1153 end2:
1154  if (fr)
1155  free_fileref(fr);
1156 
1157  return Status;
1158 }
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
PGENERIC_MAPPING NTAPI IoGetFileObjectGenericMapping(VOID)
Definition: file.c:3266
#define DOTDOT
Definition: fsctl.c:34
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
struct _file_ref * parent
Definition: btrfs_drv.h:368
uint64_t obj_id
Definition: btrfs.h:137
VOID NTAPI SeCaptureSubjectContext(OUT PSECURITY_SUBJECT_CONTEXT SubjectContext)
Definition: access.c:301
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
uint8_t obj_type
Definition: btrfs.h:138
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
BTRFS_TIME otime
Definition: btrfs.h:296
USHORT MaximumLength
Definition: env_spec_w32.h:370
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
#define SUBVOL_ROOT_INODE
Definition: propsheet.cpp:42
fcb * create_fcb(device_extension *Vcb, POOL_TYPE pool_type)
Definition: create.c:79
#define keycmp(key1, key2)
Definition: btrfs_drv.h:1024
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
enum prop_compression_type prop_compression
Definition: btrfs_drv.h:318
#define FILE_NOTIFY_CHANGE_LAST_WRITE
GLuint GLuint end
Definition: gl.h:1545
__u16 time
Definition: mkdosfs.c:366
ACCESS_MASK access
Definition: btrfs_drv.h:398
unsigned short int uint16_t
Definition: acefiex.h:54
#define uint16_t
Definition: nsiface.idl:60
#define InsertTailList(ListHead, Entry)
int const JOCTET unsigned int datalen
Definition: jpeglib.h:1030
#define FILE_NOTIFY_CHANGE_DIR_NAME
void send_notification_fileref(_In_ file_ref *fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream)
Definition: btrfs.c:1449
static void get_uuid(BTRFS_UUID *uuid)
Definition: fsctl.c:76
BTRFS_TIME st_ctime
Definition: btrfs.h:294
uint64_t offset
Definition: btrfs.h:139
LIST_ENTRY list_entry_all
Definition: btrfs_drv.h:348
bool user_set_write_time
Definition: btrfs_drv.h:405
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
uint32_t sid_to_uid(PSID sid)
Definition: security.c:310
#define ALLOC_TAG
Definition: btrfs_drv.h: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:1861
uint32_t st_gid
Definition: btrfs.h:287
SECURITY_DESCRIPTOR * sd
Definition: btrfs_drv.h:304
void mark_fileref_dirty(_In_ file_ref *fileref)
Definition: btrfs.c:1647
#define STATUS_NOT_A_DIRECTORY
Definition: udferr_usr.h:169
file_ref * create_fileref(device_extension *Vcb)
Definition: create.c:148
tree * tree
Definition: btrfs_drv.h:517
static __inline bool is_subvol_readonly(root *r, PIRP Irp)
Definition: btrfs_drv.h:1041
#define BTRFS_INODE_COMPRESS
Definition: propsheet.h:87
LIST_ENTRY list_entry
Definition: btrfs_drv.h:347
#define S_IRGRP
Definition: propsheet.h:41
#define S_IXOTH
Definition: propsheet.h:61
uint64_t sequence
Definition: btrfs.h:291
uint32_t st_nlink
Definition: btrfs.h:285
time_t now
Definition: finger.c:65
bool created
Definition: btrfs_drv.h:363
#define FILE_ACTION_MODIFIED
char name[1]
Definition: btrfs.h:365
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:86
unsigned char BOOLEAN
void reap_fcb(fcb *fcb)
Definition: btrfs.c:1673
LIST_ENTRY ** hash_ptrs_uc
Definition: btrfs_drv.h:329
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
void mark_fcb_dirty(_In_ fcb *fcb)
Definition: btrfs.c:1625
#define TYPE_INODE_REF
Definition: btrfs.h:20
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
static string utf16_to_utf8(const wstring_view &utf16)
Definition: main.cpp:672
uint16_t n
Definition: btrfs.h:364
uint8_t type
Definition: btrfs_drv.h:302
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:588
BTRFS_TIME st_mtime
Definition: btrfs.h:295
#define increase_fileref_refcount(fileref)
Definition: btrfs_drv.h:1785
#define STATUS_FILE_DELETED
Definition: udferr_usr.h:172
bool prop_compression_changed
Definition: btrfs_drv.h:337
void find_gid(struct _fcb *fcb, struct _fcb *parfcb, PSECURITY_SUBJECT_CONTEXT subjcont)
Definition: security.c:924
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2930
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:294
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
bool deleted
Definition: btrfs_drv.h:362
USHORT MaximumLength
Definition: env_spec_w32.h:377
#define S_IXGRP
Definition: propsheet.h:49
uint64_t st_size
Definition: btrfs.h:282
#define TRACE(s)
Definition: solgame.cpp:4
#define InterlockedIncrement64
Definition: interlocked.h:211
#define S_IWUSR
Definition: propsheet.h:33
struct _fcb fcb
Definition: btrfs_drv.h:1357
bool sd_dirty
Definition: btrfs_drv.h:332
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:2600
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define TYPE_SUBVOL_UUID
Definition: btrfs.h:47
uint64_t inode
Definition: btrfs_drv.h:300
bool user_set_change_time
Definition: btrfs_drv.h:406
#define Vcb
Definition: cdprocs.h:1415
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
struct _file_ref * fileref
Definition: btrfs_drv.h:316
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
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)
Definition: treefuncs.c:858
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
BTRFS_TIME st_atime
Definition: btrfs.h:293
dir_child * dc
Definition: btrfs_drv.h:369
tree_data * item
Definition: btrfs_drv.h:518
Status
Definition: gdiplustypes.h:24
#define S_IXUSR
Definition: propsheet.h:37
#define S_IROTH
Definition: propsheet.h:53
bool case_sensitive
Definition: btrfs_drv.h:402
#define FILE_ADD_SUBDIRECTORY
Definition: nt_native.h:635
GLenum GLsizei len
Definition: glext.h:6722
bool created
Definition: btrfs_drv.h:339
fcb * fcb
Definition: btrfs_drv.h:357
Definition: typedefs.h:119
static __inline FAST_IO_POSSIBLE fast_io_possible(fcb *fcb)
Definition: btrfs_drv.h:1690
INODE_ITEM inode_item
Definition: btrfs_drv.h:303
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:1199
uint64_t generation
Definition: btrfs.h:280
uint64_t flags
Definition: btrfs.h:290
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:1680
bool is_file_name_valid(_In_ PUNICODE_STRING us, _In_ bool posix, _In_ bool stream)
Definition: btrfs.c:5724
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:136
UINT64 uint64_t
Definition: types.h:77
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
ULONG atts
Definition: btrfs_drv.h:308
unsigned short USHORT
Definition: pedump.c:61
#define BTRFS_ROOT_UUID
Definition: btrfs.h:57
bool deleted
Definition: btrfs_drv.h:306
uint32_t inherit_mode(fcb *parfcb, bool is_dir)
Definition: create.c:1936
uint64_t index
Definition: btrfs.h:363
uint64_t transid
Definition: btrfs.h:281
#define STATUS_OBJECT_NAME_INVALID
Definition: udferr_usr.h:148
#define S_IRUSR
Definition: propsheet.h:29
struct _root * subvol
Definition: btrfs_drv.h:299
void free_fileref(_Inout_ file_ref *fr)
Definition: btrfs.c:1786
NTSYSAPI NTSTATUS NTAPI RtlGetOwnerSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, OUT PSID *Owner, OUT PBOOLEAN OwnerDefaulted)
Definition: sd.c:257
#define FILE_ACTION_ADDED
#define __S_IFDIR
Definition: btrfs_drv.h:1800
Definition: name.c:38
static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME *out)
Definition: btrfs_drv.h:997
unsigned int ULONG
Definition: retypes.h:1
GLenum GLuint id
Definition: glext.h:5579
LIST_ENTRY ** hash_ptrs
Definition: btrfs_drv.h:328
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
static const WCHAR dc[]
struct _ccb ccb
file_ref * fileref
Definition: btrfs_drv.h:399
uint32_t st_uid
Definition: btrfs.h:286
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define BTRFS_SUBVOL_READONLY
Definition: btrfs.h:103
bool inode_item_changed
Definition: btrfs_drv.h:317
#define GID_NOBODY
Definition: btrfs_drv.h:95
struct _device_extension * Vcb
Definition: btrfs_drv.h:298
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define UID_NOBODY
Definition: btrfs_drv.h:94
LIST_ENTRY list_entry
Definition: btrfs_drv.h:373
uint32_t st_mode
Definition: btrfs.h:288

Referenced by fsctl_request().

◆ dismount_volume()

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

Definition at line 2578 of file fsctl.c.

2578  {
2579  NTSTATUS Status;
2580  bool open_files;
2581 
2582  TRACE("FSCTL_DISMOUNT_VOLUME\n");
2583 
2584  if (!(Vcb->Vpb->Flags & VPB_MOUNTED))
2585  return STATUS_SUCCESS;
2586 
2587  if (!shutdown) {
2588  if (Vcb->disallow_dismount || Vcb->page_file_count != 0) {
2589  WARN("attempting to dismount boot volume or one containing a pagefile\n");
2590  return STATUS_ACCESS_DENIED;
2591  }
2592 
2594  if (!NT_SUCCESS(Status)) {
2595  WARN("FsRtlNotifyVolumeEvent returned %08lx\n", Status);
2596  }
2597  }
2598 
2599  ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
2600 
2601  if (!Vcb->locked) {
2603 
2604  if (Vcb->need_write && !Vcb->readonly) {
2605  Status = do_write(Vcb, Irp);
2606 
2607  if (!NT_SUCCESS(Status))
2608  ERR("do_write returned %08lx\n", Status);
2609  }
2610  }
2611 
2612  free_trees(Vcb);
2613 
2614  Vcb->removing = true;
2615 
2616  open_files = Vcb->open_files > 0;
2617 
2618  if (Vcb->vde) {
2620  Vcb->vde->mounted_device = NULL;
2621  }
2622 
2623  ExReleaseResourceLite(&Vcb->tree_lock);
2624 
2625  if (!open_files)
2626  uninit(Vcb);
2627 
2628  return STATUS_SUCCESS;
2629 }
#define FSRTL_VOLUME_DISMOUNT
Definition: ntifs_ex.h:439
_In_ PIRP Irp
Definition: csq.h:116
NTSTATUS do_write(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7789
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
void uninit(_In_ device_extension *Vcb)
Definition: btrfs.c:1936
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
smooth NULL
Definition: ftsmooth.c:416
void free_trees(device_extension *Vcb)
Definition: treefuncs.c:794
#define TRACE(s)
Definition: solgame.cpp:4
NTSTATUS NTAPI FsRtlNotifyVolumeEvent(IN PFILE_OBJECT FileObject, IN ULONG EventCode)
Definition: pnp.c:38
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
INT WSAAPI shutdown(IN SOCKET s, IN INT how)
Definition: sockctrl.c:506
#define Vcb
Definition: cdprocs.h:1415
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
static void flush_fcb_caches(device_extension *Vcb)
Definition: fsctl.c:2216
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:110
return STATUS_SUCCESS
Definition: btrfs.c:3014
static void update_volumes(device_extension *Vcb)
Definition: fsctl.c:2555
#define VPB_MOUNTED
Definition: iotypes.h:1771

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 263 of file fsctl.c.

263  {
265  uint64_t id;
267  root *r, *subvol = subvol_fcb->subvol;
268  KEY searchkey;
270  uint64_t address, *root_num;
272  BTRFS_TIME now;
273  fcb* fcb = parent->FsContext;
274  ccb* ccb = parent->FsContext2;
275  LIST_ENTRY* le;
276  file_ref *fileref, *fr;
277  dir_child* dc = NULL;
278 
279  if (!ccb) {
280  ERR("error - ccb was NULL\n");
281  return STATUS_INTERNAL_ERROR;
282  }
283 
284  if (!(ccb->access & FILE_ADD_SUBDIRECTORY)) {
285  WARN("insufficient privileges\n");
286  return STATUS_ACCESS_DENIED;
287  }
288 
289  fileref = ccb->fileref;
290 
291  if (fileref->fcb == Vcb->dummy_fcb)
292  return STATUS_ACCESS_DENIED;
293 
294  // flush open files on this subvol
295 
297 
298  // flush metadata
299 
300  if (Vcb->need_write)
301  Status = do_write(Vcb, Irp);
302  else
304 
305  free_trees(Vcb);
306 
307  if (!NT_SUCCESS(Status)) {
308  ERR("do_write returned %08lx\n", Status);
309  return Status;
310  }
311 
313 
314  // create new root
315 
316  id = InterlockedIncrement64(&Vcb->root_root->lastinode);
317  Status = create_root(Vcb, id, &r, true, Vcb->superblock.generation, Irp);
318 
319  if (!NT_SUCCESS(Status)) {
320  ERR("create_root returned %08lx\n", Status);
321  goto end;
322  }
323 
324  r->lastinode = subvol->lastinode;
325 
326  if (!Vcb->uuid_root) {
327  root* uuid_root;
328 
329  TRACE("uuid root doesn't exist, creating it\n");
330 
331  Status = create_root(Vcb, BTRFS_ROOT_UUID, &uuid_root, false, 0, Irp);
332 
333  if (!NT_SUCCESS(Status)) {
334  ERR("create_root returned %08lx\n", Status);
335  goto end;
336  }
337 
338  Vcb->uuid_root = uuid_root;
339  }
340 
341  root_num = ExAllocatePoolWithTag(PagedPool, sizeof(uint64_t), ALLOC_TAG);
342  if (!root_num) {
343  ERR("out of memory\n");
345  goto end;
346  }
347 
348  tp.tree = NULL;
349 
350  do {
351  get_uuid(&r->root_item.uuid);
352 
353  RtlCopyMemory(&searchkey.obj_id, &r->root_item.uuid, sizeof(uint64_t));
354  searchkey.obj_type = TYPE_SUBVOL_UUID;
355  RtlCopyMemory(&searchkey.offset, &r->root_item.uuid.uuid[sizeof(uint64_t)], sizeof(uint64_t));
356 
357  Status = find_item(Vcb, Vcb->uuid_root, &tp, &searchkey, false, Irp);
358  } while (NT_SUCCESS(Status) && !keycmp(searchkey, tp.item->key));
359 
360  *root_num = r->id;
361 
362  Status = insert_tree_item(Vcb, Vcb->uuid_root, searchkey.obj_id, searchkey.obj_type, searchkey.offset, root_num, sizeof(uint64_t), NULL, Irp);
363  if (!NT_SUCCESS(Status)) {
364  ERR("insert_tree_item returned %08lx\n", Status);
365  ExFreePool(root_num);
366  goto end;
367  }
368 
369  searchkey.obj_id = r->id;
370  searchkey.obj_type = TYPE_ROOT_ITEM;
371  searchkey.offset = 0xffffffffffffffff;
372 
373  Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
374  if (!NT_SUCCESS(Status)) {
375  ERR("error - find_item returned %08lx\n", Status);
376  goto end;
377  }
378 
379  Status = snapshot_tree_copy(Vcb, subvol->root_item.block_number, r, &address, Irp, &rollback);
380  if (!NT_SUCCESS(Status)) {
381  ERR("snapshot_tree_copy returned %08lx\n", Status);
382  goto end;
383  }
384 
387 
388  r->root_item.inode.generation = 1;
389  r->root_item.inode.st_size = 3;
390  r->root_item.inode.st_blocks = subvol->root_item.inode.st_blocks;
391  r->root_item.inode.st_nlink = 1;
392  r->root_item.inode.st_mode = __S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; // 40755
393  r->root_item.inode.flags = 0xffffffff80000000; // FIXME - find out what these mean
394  r->root_item.generation = Vcb->superblock.generation;
395  r->root_item.objid = subvol->root_item.objid;
396  r->root_item.block_number = address;
397  r->root_item.bytes_used = subvol->root_item.bytes_used;
398  r->root_item.last_snapshot_generation = Vcb->superblock.generation;
399  r->root_item.root_level = subvol->root_item.root_level;
400  r->root_item.generation2 = Vcb->superblock.generation;
401  r->root_item.parent_uuid = subvol->root_item.uuid;
402  r->root_item.ctransid = subvol->root_item.ctransid;
403  r->root_item.otransid = Vcb->superblock.generation;
404  r->root_item.ctime = subvol->root_item.ctime;
405  r->root_item.otime = now;
406 
407  if (readonly)
408  r->root_item.flags |= BTRFS_SUBVOL_READONLY;
409 
410  r->treeholder.address = address;
411 
412  // FIXME - do we need to copy over the send and receive fields too?
413 
414  if (tp.item->key.obj_id != searchkey.obj_id || tp.item->key.obj_type != searchkey.obj_type) {
415  ERR("error - could not find ROOT_ITEM for subvol %I64x\n", r->id);
417  goto end;
418  }
419 
420  RtlCopyMemory(tp.item->data, &r->root_item, sizeof(ROOT_ITEM));
421 
422  // update ROOT_ITEM of original subvol
423 
424  subvol->root_item.last_snapshot_generation = Vcb->superblock.generation;
425 
427 
428  // create fileref for entry in other subvolume
429 
430  fr = create_fileref(Vcb);
431  if (!fr) {
432  ERR("out of memory\n");
434  goto end;
435  }
436 
437  Status = open_fcb(Vcb, r, r->root_item.objid, BTRFS_TYPE_DIRECTORY, utf8, false, fcb, &fr->fcb, PagedPool, Irp);
438  if (!NT_SUCCESS(Status)) {
439  ERR("open_fcb returned %08lx\n", Status);
440  free_fileref(fr);
441  goto end;
442  }
443 
444  fr->parent = fileref;
445 
446  Status = add_dir_child(fileref->fcb, r->id, true, utf8, name, BTRFS_TYPE_DIRECTORY, &dc);
447  if (!NT_SUCCESS(Status))
448  WARN("add_dir_child returned %08lx\n", Status);
449 
450  fr->dc = dc;
451  dc->fileref = fr;
452 
453  ExAcquireResourceExclusiveLite(&fileref->fcb->nonpaged->dir_children_lock, true);
454  InsertTailList(&fileref->children, &fr->list_entry);
455  ExReleaseResourceLite(&fileref->fcb->nonpaged->dir_children_lock);
456 
458 
459  fr->created = true;
460  mark_fileref_dirty(fr);
461 
462  if (fr->fcb->type == BTRFS_TYPE_DIRECTORY)
463  fr->fcb->fileref = fr;
464 
465  fr->fcb->subvol->parent = fileref->fcb->subvol->id;
466 
467  free_fileref(fr);
468 
469  // change fcb's INODE_ITEM
470 
471  fcb->inode_item.transid = Vcb->superblock.generation;
473  fcb->inode_item.st_size += utf8->Length * 2;
474 
477 
478  if (!ccb->user_set_write_time)
480 
481  fcb->inode_item_changed = true;
483 
484  fcb->subvol->root_item.ctime = now;
485  fcb->subvol->root_item.ctransid = Vcb->superblock.generation;
486 
489 
490  le = subvol->fcbs.Flink;
491  while (le != &subvol->fcbs) {
492  struct _fcb* fcb2 = CONTAINING_RECORD(le, struct _fcb, list_entry);
493  LIST_ENTRY* le2 = fcb2->extents.Flink;
494 
495  while (le2 != &fcb2->extents) {
497 
498  if (!ext->ignore)
499  ext->unique = false;
500 
501  le2 = le2->Flink;
502  }
503 
504  le = le->Flink;
505  }
506 
507  Status = do_write(Vcb, Irp);
508 
509  free_trees(Vcb);
510 
511  if (!NT_SUCCESS(Status))
512  ERR("do_write returned %08lx\n", Status);
513 
514 end:
515  if (NT_SUCCESS(Status))
517  else
519 
520  return Status;
521 }
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
struct _file_ref * parent
Definition: btrfs_drv.h:368
uint64_t obj_id
Definition: btrfs.h:137
void do_rollback(device_extension *Vcb, LIST_ENTRY *rollback)
Definition: treefuncs.c:1050
void clear_rollback(LIST_ENTRY *rollback)
Definition: treefuncs.c:1029
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
uint8_t obj_type
Definition: btrfs.h:138
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ PIRP Irp
Definition: csq.h:116
static NTSTATUS snapshot_tree_copy(device_extension *Vcb, uint64_t addr, root *subvol, uint64_t *newaddr, PIRP Irp, LIST_ENTRY *rollback)
Definition: fsctl.c:90
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
NTSTATUS do_write(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7789
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:699
#define keycmp(key1, key2)
Definition: btrfs_drv.h:1024
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
#define FILE_NOTIFY_CHANGE_LAST_WRITE
GLuint GLuint end
Definition: gl.h:1545
__u16 time
Definition: mkdosfs.c:366
ACCESS_MASK access
Definition: btrfs_drv.h:398
#define InsertTailList(ListHead, Entry)
#define FILE_NOTIFY_CHANGE_DIR_NAME
void send_notification_fileref(_In_ file_ref *fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream)
Definition: btrfs.c:1449
static void get_uuid(BTRFS_UUID *uuid)
Definition: fsctl.c:76
BTRFS_TIME st_ctime
Definition: btrfs.h:294
uint64_t offset
Definition: btrfs.h:139
uint8_t * data
Definition: btrfs_drv.h:431
bool user_set_write_time
Definition: btrfs_drv.h:405
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define ALLOC_TAG
Definition: btrfs_drv.h: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:1861
void mark_fileref_dirty(_In_ file_ref *fileref)
Definition: btrfs.c:1647
file_ref * create_fileref(device_extension *Vcb)
Definition: create.c:148
tree * tree
Definition: btrfs_drv.h:517
#define S_IRGRP
Definition: propsheet.h:41
#define S_IXOTH
Definition: propsheet.h:61
uint64_t sequence
Definition: btrfs.h:291
time_t now
Definition: finger.c:65
bool created
Definition: btrfs_drv.h:363
#define FILE_ACTION_MODIFIED
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:86
smooth NULL
Definition: ftsmooth.c:416
char ext[3]
Definition: mkdosfs.c:358
void mark_fcb_dirty(_In_ fcb *fcb)
Definition: btrfs.c:1625
uint8_t type
Definition: btrfs_drv.h:302
void free_trees(device_extension *Vcb)
Definition: treefuncs.c:794
void flush_subvol_fcbs(root *subvol)
Definition: fsctl.c:246
BTRFS_TIME st_mtime
Definition: btrfs.h:295
#define increase_fileref_refcount(fileref)
Definition: btrfs_drv.h:1785
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2930
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define S_IXGRP
Definition: propsheet.h:49
uint64_t st_size
Definition: btrfs.h:282
#define TRACE(s)
Definition: solgame.cpp:4
#define InterlockedIncrement64
Definition: interlocked.h:211
#define S_IWUSR
Definition: propsheet.h:33
r parent
Definition: btrfs.c:2944
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define TYPE_SUBVOL_UUID
Definition: btrfs.h:47
bool user_set_change_time
Definition: btrfs_drv.h:406
#define Vcb
Definition: cdprocs.h:1415
GLuint address
Definition: glext.h:9393
struct _file_ref * fileref
Definition: btrfs_drv.h:316
LIST_ENTRY extents
Definition: btrfs_drv.h:311
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
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)
Definition: treefuncs.c:858
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
dir_child * dc
Definition: btrfs_drv.h:369
tree_data * item
Definition: btrfs_drv.h:518
Status
Definition: gdiplustypes.h:24
#define S_IXUSR
Definition: propsheet.h:37
#define S_IROTH
Definition: propsheet.h:53
#define FILE_ADD_SUBDIRECTORY
Definition: nt_native.h:635
fcb * fcb
Definition: btrfs_drv.h:357
Definition: typedefs.h:119
INODE_ITEM inode_item
Definition: btrfs_drv.h:303
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:1199
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:136
UINT64 uint64_t
Definition: types.h:77
#define BTRFS_ROOT_UUID
Definition: btrfs.h:57
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define TYPE_ROOT_ITEM
Definition: btrfs.h:28
uint64_t transid
Definition: btrfs.h:281
#define S_IRUSR
Definition: propsheet.h:29
static void mark_subvol_dirty(device_extension *Vcb, root *r)
Definition: fsctl.c:4067
struct _root * subvol
Definition: btrfs_drv.h:299
Definition: list.h:27
_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:1357
void free_fileref(_Inout_ file_ref *fr)
Definition: btrfs.c:1786
#define FILE_ACTION_ADDED
#define __S_IFDIR
Definition: btrfs_drv.h:1800
Definition: name.c:38
static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME *out)
Definition: btrfs_drv.h:997
GLenum GLuint id
Definition: glext.h:5579
static const WCHAR dc[]
file_ref * fileref
Definition: btrfs_drv.h:399
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define BTRFS_SUBVOL_READONLY
Definition: btrfs.h:103
bool inode_item_changed
Definition: btrfs_drv.h:317
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
LIST_ENTRY list_entry
Definition: btrfs_drv.h:373

Referenced by create_snapshot().

◆ do_unlock_volume()

void do_unlock_volume ( device_extension Vcb)

Definition at line 2320 of file fsctl.c.

2320  {
2321  KIRQL irql;
2322 
2324 
2325  Vcb->locked = false;
2326  Vcb->Vpb->Flags &= ~VPB_LOCKED;
2327  Vcb->locked_fileobj = NULL;
2328 
2330 
2331  if (Vcb->lock_paused_balance)
2332  KeSetEvent(&Vcb->balance.event, 0, false);
2333 }
VOID NTAPI IoAcquireVpbSpinLock(OUT PKIRQL Irql)
Definition: volume.c:1209
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define VPB_LOCKED
Definition: iotypes.h:1772
smooth NULL
Definition: ftsmooth.c:416
#define Vcb
Definition: cdprocs.h:1415
KIRQL irql
Definition: wave.h:1
VOID NTAPI IoReleaseVpbSpinLock(IN KIRQL Irql)
Definition: volume.c:1220

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 3256 of file fsctl.c.

3256  {
3258  fcb *fcb = FileObject ? FileObject->FsContext : NULL, *sourcefcb;
3259  ccb *ccb = FileObject ? FileObject->FsContext2 : NULL, *sourceccb;
3260  NTSTATUS Status;
3261  PFILE_OBJECT sourcefo;
3262  uint64_t sourcelen, nbytes = 0;
3263  LIST_ENTRY rollback, *le, newexts;
3265  BTRFS_TIME now;
3266  bool make_inline;
3267 
3268  if (!ded || datalen < sizeof(DUPLICATE_EXTENTS_DATA))
3269  return STATUS_BUFFER_TOO_SMALL;
3270 
3271  if (Vcb->readonly)
3273 
3274  if (ded->ByteCount.QuadPart == 0)
3275  return STATUS_SUCCESS;
3276 
3277  if (!fcb || !ccb || fcb == Vcb->volume_fcb)
3278  return STATUS_INVALID_PARAMETER;
3279 
3281  return STATUS_ACCESS_DENIED;
3282 
3283  if (Irp->RequestorMode == UserMode && !(ccb->access & FILE_WRITE_DATA)) {
3284  WARN("insufficient privileges\n");
3285  return STATUS_ACCESS_DENIED;
3286  }
3287 
3288  if (!fcb->ads && fcb->type != BTRFS_TYPE_FILE && fcb->type != BTRFS_TYPE_SYMLINK)
3289  return STATUS_INVALID_PARAMETER;
3290 
3291  Status = ObReferenceObjectByHandle(ded->FileHandle, 0, *IoFileObjectType, Irp->RequestorMode, (void**)&sourcefo, NULL);
3292  if (!NT_SUCCESS(Status)) {
3293  ERR("ObReferenceObjectByHandle returned %08lx\n", Status);
3294  return Status;
3295  }
3296 
3297  if (sourcefo->DeviceObject != FileObject->DeviceObject) {
3298  WARN("source and destination are on different volumes\n");
3299  ObDereferenceObject(sourcefo);
3300  return STATUS_INVALID_PARAMETER;
3301  }
3302 
3303  sourcefcb = sourcefo->FsContext;
3304  sourceccb = sourcefo->FsContext2;
3305 
3306  if (!sourcefcb || !sourceccb || sourcefcb == Vcb->volume_fcb) {
3307  ObDereferenceObject(sourcefo);
3308  return STATUS_INVALID_PARAMETER;
3309  }
3310 
3311  if (!sourcefcb->ads && !fcb->ads) {
3312  if ((ded->SourceFileOffset.QuadPart & (Vcb->superblock.sector_size - 1)) || (ded->TargetFileOffset.QuadPart & (Vcb->superblock.sector_size - 1))) {
3313  ObDereferenceObject(sourcefo);
3314  return STATUS_INVALID_PARAMETER;
3315  }
3316 
3317  if (ded->ByteCount.QuadPart & (Vcb->superblock.sector_size - 1)) {
3318  ObDereferenceObject(sourcefo);
3319  return STATUS_INVALID_PARAMETER;
3320  }
3321  }
3322 
3323  if (Irp->RequestorMode == UserMode && (!(sourceccb->access & FILE_READ_DATA) || !(sourceccb->access & FILE_READ_ATTRIBUTES))) {
3324  WARN("insufficient privileges\n");
3325  ObDereferenceObject(sourcefo);
3326  return STATUS_ACCESS_DENIED;
3327  }
3328 
3329  if (!sourcefcb->ads && sourcefcb->type != BTRFS_TYPE_FILE && sourcefcb->type != BTRFS_TYPE_SYMLINK) {
3330  ObDereferenceObject(sourcefo);
3331  return STATUS_INVALID_PARAMETER;
3332  }
3333 
3334  sourcelen = sourcefcb->ads ? sourcefcb->adsdata.Length : sourcefcb->inode_item.st_size;
3335 
3336  if (sector_align(sourcelen, Vcb->superblock.sector_size) < (uint64_t)ded->SourceFileOffset.QuadPart + (uint64_t)ded->ByteCount.QuadPart) {
3337  ObDereferenceObject(sourcefo);
3338  return STATUS_NOT_SUPPORTED;
3339  }
3340 
3341  if (fcb == sourcefcb &&
3344  WARN("source and destination are the same, and the ranges overlap\n");
3345  ObDereferenceObject(sourcefo);
3346  return STATUS_INVALID_PARAMETER;
3347  }
3348 
3349  // fail if nocsum flag set on one file but not the other
3350  if (!fcb->ads && !sourcefcb->ads && (fcb->inode_item.flags & BTRFS_INODE_NODATASUM) != (sourcefcb->inode_item.flags & BTRFS_INODE_NODATASUM)) {
3351  ObDereferenceObject(sourcefo);
3352  return STATUS_INVALID_PARAMETER;
3353  }
3354 
3356  InitializeListHead(&newexts);
3357 
3358  ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
3359 
3360  ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
3361 
3362  if (fcb != sourcefcb)
3363  ExAcquireResourceSharedLite(sourcefcb->Header.Resource, true);
3364 
3367  goto end;
3368  }
3369 
3370  if (!FsRtlFastCheckLockForRead(&sourcefcb->lock, &ded->SourceFileOffset, &ded->ByteCount, 0, FileObject, PsGetCurrentProcess())) {
3372  goto end;
3373  }
3374 
3375  make_inline = fcb->ads ? false : (fcb->inode_item.st_size <= Vcb->options.max_inline || fcb_is_inline(fcb));
3376 
3377  if (fcb->ads || sourcefcb->ads || make_inline || fcb_is_inline(sourcefcb)) {
3378  uint8_t* data2;
3379  ULONG bytes_read, dataoff, datalen2;
3380 
3381  if (make_inline) {
3382  dataoff = (ULONG)ded->TargetFileOffset.QuadPart;
3383  datalen2 = (ULONG)fcb->inode_item.st_size;
3384  } else if (fcb->ads) {
3385  dataoff = 0;
3386  datalen2 = (ULONG)ded->ByteCount.QuadPart;
3387  } else {
3388  dataoff = ded->TargetFileOffset.QuadPart % Vcb->superblock.sector_size;
3389  datalen2 = (ULONG)sector_align(ded->ByteCount.QuadPart + dataoff, Vcb->superblock.sector_size);
3390  }
3391 
3393  if (!data2) {
3394  ERR("out of memory\n");
3396  goto end;
3397  }
3398 
3399  if (dataoff > 0) {
3400  if (make_inline)
3401  Status = read_file(fcb, data2, 0, datalen2, NULL, Irp);
3402  else
3403  Status = read_file(fcb, data2, ded->TargetFileOffset.QuadPart - dataoff, dataoff, NULL, Irp);
3404 
3405  if (!NT_SUCCESS(Status)) {
3406  ERR("read_file returned %08lx\n", Status);
3407  ExFreePool(data2);
3408  goto end;
3409  }
3410  }
3411 
3412  if (sourcefcb->ads) {
3413  Status = read_stream(sourcefcb, data2 + dataoff, ded->SourceFileOffset.QuadPart, (ULONG)ded->ByteCount.QuadPart, &bytes_read);
3414  if (!NT_SUCCESS(Status)) {
3415  ERR("read_stream returned %08lx\n", Status);
3416  ExFreePool(data2);
3417  goto end;
3418  }
3419  } else {
3420  Status = read_file(sourcefcb, data2 + dataoff, ded->SourceFileOffset.QuadPart, ded->ByteCount.QuadPart, &bytes_read, Irp);
3421  if (!NT_SUCCESS(Status)) {
3422  ERR("read_file returned %08lx\n", Status);
3423  ExFreePool(data2);
3424  goto end;
3425  }
3426  }
3427 
3428  if (dataoff + bytes_read < datalen2)
3429  RtlZeroMemory(data2 + dataoff + bytes_read, datalen2 - bytes_read);
3430 
3431  if (fcb->ads)
3433  else if (make_inline) {
3434  uint16_t edsize;
3435  EXTENT_DATA* ed;
3436 
3437  Status = excise_extents(Vcb, fcb, 0, sector_align(fcb->inode_item.st_size, Vcb->superblock.sector_size), Irp, &rollback);
3438  if (!NT_SUCCESS(Status)) {
3439  ERR("excise_extents returned %08lx\n", Status);
3440  ExFreePool(data2);
3441  goto end;
3442  }
3443 
3444  edsize = (uint16_t)(offsetof(EXTENT_DATA, data[0]) + datalen2);
3445 
3447  if (!ed) {
3448  ERR("out of memory\n");
3449  ExFreePool(data2);
3451  goto end;
3452  }
3453 
3454  ed->generation = Vcb->superblock.generation;
3460 
3461  RtlCopyMemory(ed->data, data2, datalen2);
3462 
3463  Status = add_extent_to_fcb(fcb, 0, ed, edsize, false, NULL, &rollback);
3464  if (!NT_SUCCESS(Status)) {
3465  ERR("add_extent_to_fcb returned %08lx\n", Status);
3466  ExFreePool(data2);
3467  goto end;
3468  }
3469 
3470  fcb->inode_item.st_blocks += datalen2;
3471  } else {
3472  uint64_t start = ded->TargetFileOffset.QuadPart - (ded->TargetFileOffset.QuadPart % Vcb->superblock.sector_size);
3473 
3474  Status = do_write_file(fcb, start, start + datalen2, data2, Irp, false, 0, &rollback);
3475  if (!NT_SUCCESS(Status)) {
3476  ERR("do_write_file returned %08lx\n", Status);
3477  ExFreePool(data2);
3478  goto end;
3479  }
3480  }
3481 
3482  ExFreePool(data2);
3483  } else {
3484  LIST_ENTRY* lastextle;
3485 
3486  le = sourcefcb->extents.Flink;
3487  while (le != &sourcefcb->extents) {
3489 
3490  if (!ext->ignore) {
3491  if (ext->offset >= (uint64_t)ded->SourceFileOffset.QuadPart + (uint64_t)ded->ByteCount.QuadPart)
3492  break;
3493 
3494  if (ext->extent_data.type != EXTENT_TYPE_INLINE) {
3495  ULONG extlen = offsetof(extent, extent_data) + sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2);
3496  extent* ext2;
3497  EXTENT_DATA2 *ed2s, *ed2d;
3498  chunk* c;
3499 
3500  ed2s = (EXTENT_DATA2*)ext->extent_data.data;
3501 
3502  if (ext->offset + ed2s->num_bytes <= (uint64_t)ded->SourceFileOffset.QuadPart) {
3503  le = le->Flink;
3504  continue;
3505  }
3506 
3508  if (!ext2) {
3509  ERR("out of memory\n");
3511  goto end;
3512  }
3513 
3514  if (ext->offset < (uint64_t)ded->SourceFileOffset.QuadPart)
3515  ext2->offset = ded->TargetFileOffset.QuadPart;
3516  else
3517  ext2->offset = ext->offset - ded->SourceFileOffset.QuadPart + ded->TargetFileOffset.QuadPart;
3518 
3519  ext2->datalen = sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2);
3520  ext2->unique = false;
3521  ext2->ignore = false;
3522  ext2->inserted = true;
3523 
3524  ext2->extent_data.generation = Vcb->superblock.generation;
3525  ext2->extent_data.decoded_size = ext->extent_data.decoded_size;
3526  ext2->extent_data.compression = ext->extent_data.compression;
3527  ext2->extent_data.encryption = ext->extent_data.encryption;
3528  ext2->extent_data.encoding = ext->extent_data.encoding;
3529  ext2->extent_data.type = ext->extent_data.type;
3530 
3531  ed2d = (EXTENT_DATA2*)ext2->extent_data.data;
3532 
3533  ed2d->address = ed2s->address;
3534  ed2d->size = ed2s->size;
3535 
3536  if (ext->offset < (uint64_t)ded->SourceFileOffset.QuadPart) {
3537  ed2d->offset = ed2s->offset + ded->SourceFileOffset.QuadPart - ext->offset;
3538  ed2d->num_bytes = min((uint64_t)ded->ByteCount.QuadPart, ed2s->num_bytes + ext->offset - ded->SourceFileOffset.QuadPart);
3539  } else {
3540  ed2d->offset = ed2s->offset;
3541  ed2d->num_bytes = min(ded->SourceFileOffset.QuadPart + ded->ByteCount.QuadPart - ext->offset, ed2s->num_bytes);
3542  }
3543 
3544  if (ext->csum) {
3545  if (ext->extent_data.compression == BTRFS_COMPRESSION_NONE) {
3546  ext2->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(ed2d->num_bytes * Vcb->csum_size / Vcb->superblock.sector_size), ALLOC_TAG);
3547  if (!ext2->csum) {
3548  ERR("out of memory\n");
3550  ExFreePool(ext2);
3551  goto end;
3552  }
3553 
3554  RtlCopyMemory(ext2->csum, (uint8_t*)ext->csum + ((ed2d->offset - ed2s->offset) * Vcb->csum_size / Vcb->superblock.sector_size),
3555  (ULONG)(ed2d->num_bytes * Vcb->csum_size / Vcb->superblock.sector_size));
3556  } else {
3557  ext2->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(ed2d->size * Vcb->csum_size / Vcb->superblock.sector_size), ALLOC_TAG);
3558  if (!ext2->csum) {
3559  ERR("out of memory\n");
3561  ExFreePool(ext2);
3562  goto end;
3563  }
3564 
3565  RtlCopyMemory(ext2->csum, ext->csum, (ULONG)(ed2s->size * Vcb->csum_size / Vcb->superblock.sector_size));
3566  }
3567  } else
3568  ext2->csum = NULL;
3569 
3570  InsertTailList(&newexts, &ext2->list_entry);
3571 
3572  c = get_chunk_from_address(Vcb, ed2s->address);
3573  if (!c) {
3574  ERR("get_chunk_from_address(%I64x) failed\n", ed2s->address);
3576  goto end;
3577  }
3578 
3579  Status = update_changed_extent_ref(Vcb, c, ed2s->address, ed2s->size, fcb->subvol->id, fcb->inode, ext2->offset - ed2d->offset,
3580  1, fcb->inode_item.flags & BTRFS_INODE_NODATASUM, false, Irp);
3581  if (!NT_SUCCESS(Status)) {
3582  ERR("update_changed_extent_ref returned %08lx\n", Status);
3583  goto end;
3584  }
3585 
3586  nbytes += ed2d->num_bytes;
3587  }
3588  }
3589 
3590  le = le->Flink;
3591  }
3592 
3594  if (!NT_SUCCESS(Status)) {
3595  ERR("excise_extents returned %08lx\n", Status);
3596 
3597  while (!IsListEmpty(&newexts)) {
3599  ExFreePool(ext);
3600  }
3601 
3602  goto end;
3603  }
3604 
3605  // clear unique flags in source fcb
3606  le = sourcefcb->extents.Flink;
3607  while (le != &sourcefcb->extents) {
3609 
3610  if (!ext->ignore && ext->unique && (ext->extent_data.type == EXTENT_TYPE_REGULAR || ext->extent_data.type == EXTENT_TYPE_PREALLOC)) {
3611  EXTENT_DATA2* ed2s = (EXTENT_DATA2*)ext->extent_data.data;
3612  LIST_ENTRY* le2;
3613 
3614  le2 = newexts.Flink;
3615  while (le2 != &newexts) {
3617 
3618  if (ext2->extent_data.type == EXTENT_TYPE_REGULAR || ext2->extent_data.type == EXTENT_TYPE_PREALLOC) {
3619  EXTENT_DATA2* ed2d = (EXTENT_DATA2*)ext2->extent_data.data;
3620 
3621  if (ed2d->address == ed2s->address && ed2d->size == ed2s->size) {
3622  ext->unique = false;
3623  break;
3624  }
3625  }
3626 
3627  le2 = le2->Flink;
3628  }
3629  }
3630 
3631  le = le->Flink;
3632  }
3633 
3634  lastextle = &fcb->extents;
3635  while (!IsListEmpty(&newexts)) {
3637 
3638  add_extent(fcb, lastextle, ext);
3639  lastextle = &ext->list_entry;
3640  }
3641  }
3642 
3645 
3646  if (fcb->ads) {
3647  ccb->fileref->parent->fcb->inode_item.sequence++;
3648 
3649  if (!ccb->user_set_change_time)
3650  ccb->fileref->parent->fcb->inode_item.st_ctime = now;
3651 
3652  ccb->fileref->parent->fcb->inode_item_changed = true;
3653  mark_fcb_dirty(ccb->fileref->parent->fcb);
3654  } else {
3655  fcb->inode_item.st_blocks += nbytes;
3656  fcb->inode_item.sequence++;
3657 
3658  if (!ccb->user_set_change_time)
3660 
3661  if (!ccb->user_set_write_time) {
3664  }
3665 
3666  fcb->inode_item_changed = true;
3667  fcb->extents_changed = true;
3668  }
3669 
3671 
3672  if (FileObject->SectionObjectPointer->DataSectionObject)
3673  CcPurgeCacheSection(FileObject->SectionObjectPointer, &ded->TargetFileOffset, (ULONG)ded->ByteCount.QuadPart, false);
3674 
3676 
3677 end:
3678  ObDereferenceObject(sourcefo);
3679 
3680  if (NT_SUCCESS(Status))
3682  else
3684 
3685  if (fcb != sourcefcb)
3686  ExReleaseResourceLite(sourcefcb->Header.Resource);
3687 
3688  ExReleaseResourceLite(fcb->Header.Resource);
3689 
3690  ExReleaseResourceLite(&Vcb->tree_lock);
3691 
3692  return Status;
3693 }
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
uint64_t generation
Definition: btrfs.h:346
struct _file_ref * parent
Definition: btrfs_drv.h:368
void do_rollback(device_extension *Vcb, LIST_ENTRY *rollback)
Definition: treefuncs.c:1050
BOOLEAN NTAPI CcPurgeCacheSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN UninitializeCacheMaps)
Definition: fssup.c:386
void clear_rollback(LIST_ENTRY *rollback)
Definition: treefuncs.c:1029
uint8_t type
Definition: btrfs.h:351
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
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:752
NTSTATUS update_changed_extent_ref(device_extension *Vcb, chunk *c, uint64_t address, uint64_t size, uint64_t root, uint64_t objid, uint64_t offset, int32_t count, bool no_csum, bool superseded, PIRP Irp)
Definition: extent-tree.c:1951
#define BTRFS_COMPRESSION_NONE
Definition: btrfs.h:61
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
uint64_t decoded_size
Definition: btrfs.h:347
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
#define FILE_NOTIFY_CHANGE_LAST_WRITE
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
GLuint GLuint end
Definition: gl.h:1545
__u16 time
Definition: mkdosfs.c:366
ACCESS_MASK access
Definition: btrfs_drv.h:398
unsigned short int uint16_t
Definition: acefiex.h:54
NTSTATUS read_file(fcb *fcb, uint8_t *data, uint64_t start, uint64_t length, ULONG *pbr, PIRP Irp)
Definition: read.c:2828
#define uint16_t
Definition: nsiface.idl:60
#define InsertTailList(ListHead, Entry)
int const JOCTET unsigned int datalen
Definition: jpeglib.h:1030
BTRFS_TIME st_ctime
Definition: btrfs.h:294
uint8_t encryption
Definition: btrfs.h:349
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
bool user_set_write_time
Definition: btrfs_drv.h:405
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define ALLOC_TAG
Definition: btrfs_drv.h:91
#define EXTENT_TYPE_INLINE
Definition: btrfs.h:70
while(1)
Definition: macro.lex.yy.c:740
void queue_notification_fcb(_In_ file_ref *fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream)
Definition: btrfs.c:1597
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:496
static __inline bool is_subvol_readonly(root *r, PIRP Irp)
Definition: btrfs_drv.h:1041
uint64_t address
Definition: btrfs.h:356
uint64_t sequence
Definition: btrfs.h:291
time_t now
Definition: finger.c:65
#define FILE_READ_DATA
Definition: nt_native.h:628
bool extents_changed
Definition: btrfs_drv.h:334
#define FILE_ACTION_MODIFIED
#define PsGetCurrentProcess
Definition: psfuncs.h:17
#define BTRFS_ENCODING_NONE
Definition: btrfs.h:68
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
char ext[3]
Definition: mkdosfs.c:358
void mark_fcb_dirty(_In_ fcb *fcb)
Definition: btrfs.c:1625
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
uint64_t size
Definition: btrfs.h:357
#define false
Definition: osdep.h:35
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)
Definition: write.c:3891
uint8_t type
Definition: btrfs_drv.h:302
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:588
BTRFS_TIME st_mtime
Definition: btrfs.h:295
#define FILE_WRITE_DATA
Definition: nt_native.h:631
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
FILE_LOCK lock
Definition: btrfs_drv.h:305
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:294
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
LARGE_INTEGER SourceFileOffset
Definition: shellext.h:200
uint16_t encoding
Definition: btrfs.h:350
#define BTRFS_ENCRYPTION_NONE
Definition: btrfs.h:66
uint64_t st_size
Definition: btrfs.h:282
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
uint64_t inode
Definition: btrfs_drv.h:300
#define BTRFS_INODE_NODATASUM
Definition: propsheet.h:76
bool user_set_change_time
Definition: btrfs_drv.h:406
#define Vcb
Definition: cdprocs.h:1415
const GLubyte * c
Definition: glext.h:8905
LIST_ENTRY extents
Definition: btrfs_drv.h:311
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
* PFILE_OBJECT
Definition: iotypes.h:1962
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
static const BYTE ext2[]
Definition: encode.c:2699
NTSTATUS excise_extents(device_extension *Vcb, fcb *fcb, uint64_t start_data, uint64_t end_data, PIRP Irp, LIST_ENTRY *rollback)
Definition: write.c:2384
Status
Definition: gdiplustypes.h:24
Definition: typedefs.h:119
#define EXTENT_TYPE_PREALLOC
Definition: btrfs.h:72
INODE_ITEM inode_item
Definition: btrfs_drv.h:303
POBJECT_TYPE IoFileObjectType
Definition: iomgr.c:36
BYTE uint8_t
Definition: msvideo1.c:66
uint64_t num_bytes
Definition: btrfs.h:359
uint64_t st_blocks
Definition: btrfs.h:283
uint64_t flags
Definition: btrfs.h:290
uint16_t edsize
Definition: write.c:2806
void add_extent(_In_ fcb *fcb, _In_ LIST_ENTRY *prevextle, _In_ __drv_aliasesMem extent *newext)
Definition: write.c:2367
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:71
#define ERR(fmt,...)
Definition: debug.h:110
uint8_t data[1]
Definition: btrfs.h:352
chunk * get_chunk_from_address(device_extension *Vcb, uint64_t address)
Definition: write.c:89
UINT64 uint64_t
Definition: types.h:77
static const WCHAR data2[]
Definition: db.c:2971
unsigned short USHORT
Definition: pedump.c:61
GLuint start
Definition: gl.h:1545
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
struct _root * subvol
Definition: btrfs_drv.h:299
#define min(a, b)
Definition: monoChain.cc:55
Definition: list.h:27
ANSI_STRING adsdata
Definition: btrfs_drv.h:345
_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:1357
bool fcb_is_inline(fcb *fcb)
Definition: fsctl.c:3240
LARGE_INTEGER TargetFileOffset
Definition: shellext.h:201
HRESULT read_stream(BSCallback *, IStream *, void *, DWORD, DWORD *) DECLSPEC_HIDDEN
Definition: navigate.c:602
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
#define BTRFS_TYPE_FILE
Definition: shellext.h:85
bool ads
Definition: btrfs_drv.h:341
#define STATUS_FILE_LOCK_CONFLICT
Definition: ntstatus.h:320
static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME *out)
Definition: btrfs_drv.h:997
#define c
Definition: ke_i.h:80
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint64_t offset
Definition: btrfs.h:358
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)
Definition: write.c:2736
file_ref * fileref
Definition: btrfs_drv.h:399
return STATUS_SUCCESS
Definition: btrfs.c:3014
EXTENT_DATA * ed
Definition: write.c:2804
bool inode_item_changed
Definition: btrfs_drv.h:317
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:786
static uint64_t __inline sector_align(uint64_t n, uint64_t a)
LARGE_INTEGER ByteCount
Definition: shellext.h:202
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
uint8_t compression
Definition: btrfs.h:348
LONGLONG QuadPart
Definition: typedefs.h:114
#define BTRFS_TYPE_SYMLINK
Definition: shellext.h:91
Definition: tftpd.h:137

Referenced by fsctl_request().

◆ fcb_is_inline()

bool fcb_is_inline ( fcb fcb)

Definition at line 3240 of file fsctl.c.

3240  {
3241  LIST_ENTRY* le;
3242 
3243  le = fcb->extents.Flink;
3244  while (le != &fcb->extents) {
3246 
3247  if (!ext->ignore)
3248  return ext->extent_data.type == EXTENT_TYPE_INLINE;
3249 
3250  le = le->Flink;
3251  }
3252 
3253  return false;
3254 }
#define EXTENT_TYPE_INLINE
Definition: btrfs.h:70
char ext[3]
Definition: mkdosfs.c:358
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
LIST_ENTRY extents
Definition: btrfs_drv.h:311
Definition: typedefs.h:119
Definition: list.h:27

Referenced by duplicate_extents(), truncate_file(), write_file2(), 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 4545 of file fsctl.c.

4545  {
4546  btrfs_find_subvol* bfs;
4547  NTSTATUS Status;
4548  traverse_ptr tp;
4549  KEY searchkey;
4550 
4551  if (!in || inlen < sizeof(btrfs_find_subvol))
4552  return STATUS_INVALID_PARAMETER;
4553 
4554  if (!out || outlen < sizeof(WCHAR))
4555  return STATUS_INVALID_PARAMETER;
4556 
4557  if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), Irp->RequestorMode))
4559 
4560  bfs = (btrfs_find_subvol*)in;
4561 
4562  ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
4563 
4564  if (!Vcb->uuid_root) {
4565  ERR("couldn't find uuid root\n");
4567  goto end;
4568  }
4569 
4570  RtlCopyMemory(&searchkey.obj_id, &bfs->uuid, sizeof(uint64_t));
4571  searchkey.obj_type = TYPE_SUBVOL_UUID;
4572  RtlCopyMemory(&searchkey.offset, &bfs->uuid.uuid[sizeof(uint64_t)], sizeof(uint64_t));
4573 
4574  Status = find_item(Vcb, Vcb->uuid_root, &tp, &searchkey, false, Irp);
4575 
4576  if (!NT_SUCCESS(Status)) {
4577  ERR("find_item returned %08lx\n", Status);
4578  goto end;
4579  }
4580 
4581  if (!keycmp(searchkey, tp.item->key) && tp.item->size >= sizeof(uint64_t)) {
4582  uint64_t* id = (uint64_t*)tp.item->data;
4583 
4584  if (bfs->ctransid != 0) {
4585  KEY searchkey2;
4586  traverse_ptr tp2;
4587 
4588  searchkey2.obj_id = *id;
4589  searchkey2.obj_type = TYPE_ROOT_ITEM;
4590  searchkey2.offset = 0xffffffffffffffff;
4591 
4592  Status = find_item(Vcb, Vcb->root_root, &tp2, &searchkey2, false, Irp);
4593  if (!NT_SUCCESS(Status)) {
4594  ERR("find_item returned %08lx\n", Status);
4595  goto end;
4596  }
4597 
4598  if (tp2.item->key.obj_id == searchkey2.obj_id && tp2.item->key.obj_type == searchkey2.obj_type &&
4599  tp2.item->size >= offsetof(ROOT_ITEM, otransid)) {
4600  ROOT_ITEM* ri = (ROOT_ITEM*)tp2.item->data;
4601 
4602  if (ri->ctransid == bfs->ctransid) {
4603  TRACE("found subvol %I64x\n", *id);
4604  Status = get_subvol_path(Vcb, *id, out, outlen, Irp);
4605  goto end;
4606  }
4607  }
4608  } else {
4609  TRACE("found subvol %I64x\n", *id);
4610  Status = get_subvol_path(Vcb, *id, out, outlen, Irp);
4611  goto end;
4612  }
4613  }
4614 
4615  searchkey.obj_type = TYPE_SUBVOL_REC_UUID;
4616 
4617  Status = find_item(Vcb, Vcb->uuid_root, &tp, &searchkey, false, Irp);
4618 
4619  if (!NT_SUCCESS(Status)) {
4620  ERR("find_item returned %08lx\n", Status);
4621  goto end;
4622  }
4623 
4624  if (!keycmp(searchkey, tp.item->key) && tp.item->size >= sizeof(uint64_t)) {
4625  uint64_t* ids = (uint64_t*)tp.item->data;
4626  ULONG i;
4627 
4628  for (i = 0; i < tp.item->size / sizeof(uint64_t); i++) {
4629  if (bfs->ctransid != 0) {
4630  KEY searchkey2;
4631  traverse_ptr tp2;
4632 
4633  searchkey2.obj_id = ids[i];
4634  searchkey2.obj_type = TYPE_ROOT_ITEM;
4635  searchkey2.offset = 0xffffffffffffffff;
4636 
4637  Status = find_item(Vcb, Vcb->root_root, &tp2, &searchkey2, false, Irp);
4638  if (!NT_SUCCESS(Status)) {
4639  ERR("find_item returned %08lx\n", Status);
4640  goto end;
4641  }
4642 
4643  if (tp2.item->key.obj_id == searchkey2.obj_id && tp2.item->key.obj_type == searchkey2.obj_type &&
4644  tp2.item->size >= offsetof(ROOT_ITEM, otransid)) {
4645  ROOT_ITEM* ri = (ROOT_ITEM*)tp2.item->data;
4646 
4647  if (ri->ctransid == bfs->ctransid) {
4648  TRACE("found subvol %I64x\n", ids[i]);
4649  Status = get_subvol_path(Vcb, ids[i], out, outlen, Irp);
4650  goto end;
4651  }
4652  }
4653  } else {
4654  TRACE("found subvol %I64x\n", ids[i]);
4655  Status = get_subvol_path(Vcb, ids[i], out, outlen, Irp);
4656  goto end;
4657  }
4658  }
4659  }
4660 
4662 
4663 end:
4664  ExReleaseResourceLite(&Vcb->tree_lock);
4665 
4666  return Status;
4667 }
uint64_t obj_id
Definition: btrfs.h:137
#define STATUS_PRIVILEGE_NOT_HELD
Definition: DriverTester.h:9
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
uint8_t obj_type
Definition: btrfs.h:138
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define keycmp(key1, key2)
Definition: btrfs_drv.h:1024
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:430
BOOLEAN NTAPI SeSinglePrivilegeCheck(IN LUID PrivilegeValue, IN KPROCESSOR_MODE PreviousMode)
Definition: priv.c:524
GLuint GLuint end
Definition: gl.h:1545
uint64_t offset
Definition: btrfs.h:139
uint8_t * data
Definition: btrfs_drv.h:431
GLuint * ids
Definition: glext.h:5907
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
BTRFS_UUID uuid
Definition: btrfsioctl.h:262
#define offsetof(TYPE, MEMBER)
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2930
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
uint64_t ctransid
Definition: btrfs.h:316
#define STATUS_NOT_FOUND
Definition: shellext.h:72
#define TRACE(s)
Definition: solgame.cpp:4
if(!(yy_init))
Definition: macro.lex.yy.c:714
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define TYPE_SUBVOL_UUID
Definition: btrfs.h:47
#define Vcb
Definition: cdprocs.h:1415
static FILE * out
Definition: regtests2xml.c:44
#define for
Definition: utility.h:88
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
tree_data * item
Definition: btrfs_drv.h:518
Status
Definition: gdiplustypes.h:24
#define uint64_t
Definition: nsiface.idl:62
#define ERR(fmt,...)
Definition: debug.h:110
uint8_t uuid[16]
Definition: btrfs.h:133
Definition: btrfs.h:136
#define SE_MANAGE_VOLUME_PRIVILEGE
Definition: security.c:682
UINT64 uint64_t
Definition: types.h:77
GLuint in
Definition: glext.h:9616
static NTSTATUS get_subvol_path(device_extension *Vcb, uint64_t id, WCHAR *out, ULONG outlen, PIRP Irp)
Definition: fsctl.c:4494
#define TYPE_ROOT_ITEM
Definition: btrfs.h:28
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
unsigned int ULONG
Definition: retypes.h:1
GLenum GLuint id
Definition: glext.h:5579
#define TYPE_SUBVOL_REC_UUID
Definition: btrfs.h:48
uint64_t ctransid
Definition: btrfsioctl.h:263

Referenced by fsctl_request().

◆ flush_fcb_caches()

static void flush_fcb_caches ( device_extension Vcb)
static

Definition at line 2216 of file fsctl.c.

2216  {
2217  LIST_ENTRY* le;
2218 
2219  le = Vcb->all_fcbs.Flink;
2220  while (le != &Vcb->all_fcbs) {
2221  struct _fcb* fcb = CONTAINING_RECORD(le, struct _fcb, list_entry_all);
2223 
2224  if (fcb->type != BTRFS_TYPE_DIRECTORY && !fcb->deleted)
2225  CcFlushCache(&fcb->nonpaged->segment_object, NULL, 0, &iosb);
2226 
2227  le = le->Flink;
2228  }
2229 }
static PIO_STATUS_BLOCK iosb
Definition: file.c:98
VOID NTAPI CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, OUT OPTIONAL PIO_STATUS_BLOCK IoStatus)
Definition: cachesub.c:222
LIST_ENTRY list_entry_all
Definition: btrfs_drv.h:348
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:86
smooth NULL
Definition: ftsmooth.c:416
uint8_t type
Definition: btrfs_drv.h:302
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define Vcb
Definition: cdprocs.h:1415
Definition: typedefs.h:119
struct _fcb_nonpaged * nonpaged
Definition: btrfs_drv.h:295
bool deleted
Definition: btrfs_drv.h:306

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

◆ flush_subvol_fcbs()

void flush_subvol_fcbs ( root subvol)

Definition at line 246 of file fsctl.c.

246  {
247  LIST_ENTRY* le = subvol->fcbs.Flink;
248 
249  if (IsListEmpty(&subvol->fcbs))
250  return;
251 
252  while (le != &subvol->fcbs) {
253  struct _fcb* fcb = CONTAINING_RECORD(le, struct _fcb, list_entry);
255 
256  if (fcb->type != BTRFS_TYPE_DIRECTORY && !fcb->deleted)
257  CcFlushCache(&fcb->nonpaged->segment_object, NULL, 0, &iosb);
258 
259  le = le->Flink;
260  }
261 }
static PIO_STATUS_BLOCK iosb
Definition: file.c:98
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
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:86
smooth NULL
Definition: ftsmooth.c:416
uint8_t type
Definition: btrfs_drv.h:302
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
Definition: typedefs.h:119
struct _fcb_nonpaged * nonpaged
Definition: btrfs_drv.h:295
bool deleted
Definition: btrfs_drv.h:306
struct _root * subvol
Definition: btrfs_drv.h:299
Definition: list.h:27

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 1699 of file fsctl.c.

1699  {
1700  FILESYSTEM_STATISTICS* fss;
1701 
1702  WARN("STUB: FSCTL_FILESYSTEM_GET_STATISTICS\n");
1703 
1704  // This is hideously wrong, but at least it stops SMB from breaking
1705 
1706  if (buflen < sizeof(FILESYSTEM_STATISTICS))
1707  return STATUS_BUFFER_TOO_SMALL;
1708 
1709  fss = buffer;
1710  RtlZeroMemory(fss, sizeof(FILESYSTEM_STATISTICS));
1711 
1712  fss->Version = 1;
1715 
1716  *retlen = sizeof(FILESYSTEM_STATISTICS);
1717 
1718  return STATUS_SUCCESS;
1719 }
#define WARN(fmt,...)
Definition: debug.h:112
GLuint buffer
Definition: glext.h:5915
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define FILESYSTEM_STATISTICS_TYPE_NTFS
Definition: winioctl.h:672
struct _FILESYSTEM_STATISTICS FILESYSTEM_STATISTICS
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
return STATUS_SUCCESS
Definition: btrfs.c:3014
ULONG SizeOfCompleteStructure
Definition: winioctl.h:657

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 4129 of file fsctl.c.

4129  {
4130  LIST_ENTRY* le;
4131  btrfs_set_xattr* bsxa;
4132  ULONG reqlen = (ULONG)offsetof(btrfs_set_xattr, data[0]);
4133  fcb* fcb;
4134  ccb* ccb;
4135 
4136  if (!data || datalen < reqlen)
4137  return STATUS_INVALID_PARAMETER;
4138 
4139  if (!FileObject || !FileObject->FsContext || !FileObject->FsContext2 || FileObject->FsContext == Vcb->volume_fcb)
4140  return STATUS_INVALID_PARAMETER;
4141 
4142  fcb = FileObject->FsContext;
4143  ccb = FileObject->FsContext2;
4144 
4145  if (!(ccb->access & (FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES)) && processor_mode == UserMode) {
4146  WARN("insufficient privileges\n");
4147  return STATUS_ACCESS_DENIED;
4148  }
4149 
4150  ExAcquireResourceSharedLite(fcb->Header.Resource, true);
4151 
4152  le = fcb->xattrs.Flink;
4153  while (le != &fcb->xattrs) {
4155 
4156  if (xa->valuelen > 0)
4157  reqlen += (ULONG)offsetof(btrfs_set_xattr, data[0]) + xa->namelen + xa->valuelen;
4158 
4159  le = le->Flink;
4160  }
4161 
4162  if (datalen < reqlen) {
4163  ExReleaseResourceLite(fcb->Header.Resource);
4164  return STATUS_BUFFER_OVERFLOW;
4165  }
4166 
4167  bsxa = (btrfs_set_xattr*)data;
4168 
4169  if (reqlen > 0) {
4170  le = fcb->xattrs.Flink;
4171  while (le != &fcb->xattrs) {
4173 
4174  if (xa->valuelen > 0) {
4175  bsxa->namelen = xa->namelen;
4176  bsxa->valuelen = xa->valuelen;
4177  memcpy(bsxa->data, xa->data, xa->namelen + xa->valuelen);
4178 
4179  bsxa = (btrfs_set_xattr*)&bsxa->data[xa->namelen + xa->valuelen];
4180  }
4181 
4182  le = le->Flink;
4183  }
4184  }
4185 
4186  bsxa->namelen = 0;
4187  bsxa->valuelen = 0;
4188 
4189  ExReleaseResourceLite(fcb->Header.Resource);
4190 
4191  return STATUS_SUCCESS;
4192 }
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define WARN(fmt,...)
Definition: debug.h:112
ACCESS_MASK access
Definition: btrfs_drv.h:398
int const JOCTET unsigned int datalen
Definition: jpeglib.h:1030
#define FILE_WRITE_ATTRIBUTES
Definition: nt_native.h:649
#define offsetof(TYPE, MEMBER)
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:588
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:294
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
struct _fcb fcb
Definition: btrfs_drv.h:1357
LIST_ENTRY xattrs
Definition: btrfs_drv.h:319
#define Vcb
Definition: cdprocs.h:1415
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
Definition: typedefs.h:119
USHORT valuelen
Definition: btrfs_drv.h:288
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
Definition: list.h:27
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
USHORT namelen
Definition: btrfs_drv.h:287
unsigned int ULONG
Definition: retypes.h:1
struct _ccb ccb
return STATUS_SUCCESS
Definition: btrfs.c:3014
char data[1]
Definition: btrfs_drv.h:290

Referenced by fsctl_request().

◆ fsctl_oplock()

static NTSTATUS fsctl_oplock ( device_extension Vcb,
PIRP Pirp 
)
static

Definition at line 4854 of file fsctl.c.

4854  {
4855  NTSTATUS Status;
4856  PIRP Irp = *Pirp;
4858  uint32_t fsctl = IrpSp->Parameters.FileSystemControl.FsControlCode;
4860  fcb* fcb = FileObject ? FileObject->FsContext : NULL;
4861  ccb* ccb = FileObject ? FileObject->FsContext2 : NULL;
4862  file_ref* fileref = ccb ? ccb->fileref : NULL;
4863 #if (NTDDI_VERSION >= NTDDI_WIN7)
4864  PREQUEST_OPLOCK_INPUT_BUFFER buf = NULL;
4865  bool oplock_request = false, oplock_ack = false;
4866 #else
4867  bool oplock_request = false;
4868 #endif
4869  ULONG oplock_count = 0;
4870 #ifdef __REACTOS__
4871  bool shared_request;
4872 #endif
4873 
4874  if (!fcb) {
4875  ERR("fcb was NULL\n");
4876  return STATUS_INVALID_PARAMETER;
4877  }
4878 
4879  if (!fileref) {
4880  ERR("fileref was NULL\n");
4881  return STATUS_INVALID_PARAMETER;
4882  }
4883 
4885  return STATUS_INVALID_PARAMETER;
4886 
4887 #if (NTDDI_VERSION >= NTDDI_WIN7)
4888  if (fsctl == FSCTL_REQUEST_OPLOCK) {
4889  if (IrpSp->Parameters.FileSystemControl.InputBufferLength < sizeof(REQUEST_OPLOCK_INPUT_BUFFER))
4890  return STATUS_BUFFER_TOO_SMALL;
4891 
4892  if (IrpSp->Parameters.FileSystemControl.OutputBufferLength < sizeof(REQUEST_OPLOCK_OUTPUT_BUFFER))
4893  return STATUS_BUFFER_TOO_SMALL;
4894 
4895  buf = Irp->AssociatedIrp.SystemBuffer;
4896 
4897  // flags are mutually exclusive
4898  if (buf->Flags & REQUEST_OPLOCK_INPUT_FLAG_REQUEST && buf->Flags & REQUEST_OPLOCK_INPUT_FLAG_ACK)
4899  return STATUS_INVALID_PARAMETER;
4900 
4901  oplock_request = buf->Flags & REQUEST_OPLOCK_INPUT_FLAG_REQUEST;
4902  oplock_ack = buf->Flags & REQUEST_OPLOCK_INPUT_FLAG_ACK;
4903 
4904  if (!oplock_request && !oplock_ack)
4905  return STATUS_INVALID_PARAMETER;
4906  }
4907 #endif
4908 
4909 #if (NTDDI_VERSION >= NTDDI_WIN7)
4910  bool shared_request = (fsctl == FSCTL_REQUEST_OPLOCK_LEVEL_2) || (fsctl == FSCTL_REQUEST_OPLOCK && !(buf->RequestedOplockLevel & OPLOCK_LEVEL_CACHE_WRITE));
4911 #else
4912  shared_request = (fsctl == FSCTL_REQUEST_OPLOCK_LEVEL_2);
4913 #endif
4914 
4915 #if (NTDDI_VERSION >= NTDDI_WIN7)
4916  if (fcb->type == BTRFS_TYPE_DIRECTORY && (fsctl != FSCTL_REQUEST_OPLOCK || !shared_request)) {
4917 #else
4918  if (fcb->type == BTRFS_TYPE_DIRECTORY && !shared_request) {
4919 #endif
4920  WARN("oplock requests on directories can only be for read or read-handle oplocks\n");
4921  return STATUS_INVALID_PARAMETER;
4922  }
4923 
4924  ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
4925 
4927  fsctl == FSCTL_REQUEST_OPLOCK_LEVEL_2 || oplock_request) {
4928  ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
4929 
4930  if (shared_request) {
4931  if (fcb->type == BTRFS_TYPE_FILE) {
4933  oplock_count = !fFsRtlCheckLockForOplockRequest(&fcb->lock, &fcb->Header.AllocationSize);
4936  else
4937  oplock_count = FsRtlAreThereCurrentFileLocks(&fcb->lock);
4938  }
4939  } else
4940  oplock_count = fileref->open_count;
4941  } else
4942  ExAcquireResourceSharedLite(fcb->Header.Resource, true);
4943 
4944 #if (NTDDI_VERSION >= NTDDI_WIN7)
4945  if ((fsctl == FSCTL_REQUEST_FILTER_OPLOCK || fsctl == FSCTL_REQUEST_BATCH_OPLOCK ||
4946  (fsctl == FSCTL_REQUEST_OPLOCK && buf->RequestedOplockLevel & OPLOCK_LEVEL_CACHE_HANDLE)) &&
4947 #else
4948  if ((fsctl == FSCTL_REQUEST_FILTER_OPLOCK || fsctl == FSCTL_REQUEST_BATCH_OPLOCK) &&
4949 #endif
4950  fileref->delete_on_close) {
4951  ExReleaseResourceLite(fcb->Header.Resource);
4952  ExReleaseResourceLite(&Vcb->tree_lock);
4953  return STATUS_DELETE_PENDING;
4954  }
4955 
4956  Status = FsRtlOplockFsctrl(fcb_oplock(fcb), Irp, oplock_count);
4957 
4958  *Pirp = NULL;
4959 
4960  fcb->Header.IsFastIoPossible = fast_io_possible(fcb);
4961 
4962  ExReleaseResourceLite(fcb->Header.Resource);
4963  ExReleaseResourceLite(&Vcb->tree_lock);
4964 
4965  return Status;
4966 }
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
#define FSCTL_REQUEST_BATCH_OPLOCK
Definition: nt_native.h:828
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
NTSTATUS NTAPI FsRtlOplockFsctrl(IN POPLOCK Oplock, IN PIRP Irp, IN ULONG OpenCount)
Definition: oplock.c:1432
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:86
smooth NULL
Definition: ftsmooth.c:416
uint8_t type
Definition: btrfs_drv.h:302
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:588
#define FsRtlAreThereCurrentFileLocks(FL)
Definition: fsrtlfuncs.h:1584
FILE_LOCK lock
Definition: btrfs_drv.h:305
tFsRtlAreThereCurrentOrInProgressFileLocks fFsRtlAreThereCurrentOrInProgressFileLocks
Definition: btrfs.c:105
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:294
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define FSCTL_REQUEST_OPLOCK_LEVEL_2
Definition: nt_native.h:827
#define Vcb
Definition: cdprocs.h:1415
struct _file_ref * fileref
Definition: btrfs_drv.h:316
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
* PFILE_OBJECT
Definition: iotypes.h:1962
Status
Definition: gdiplustypes.h:24
#define FSCTL_REQUEST_OPLOCK_LEVEL_1
Definition: nt_native.h:826
static __inline FAST_IO_POSSIBLE fast_io_possible(fcb *fcb)
Definition: btrfs_drv.h:1690
tFsRtlCheckLockForOplockRequest fFsRtlCheckLockForOplockRequest
Definition: btrfs.c:104
#define ERR(fmt,...)
Definition: debug.h:110
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2789
PFILE_OBJECT FileObject
Definition: iotypes.h:2820
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
#define FSCTL_REQUEST_FILTER_OPLOCK
Definition: nt_native.h:849
UINT32 uint32_t
Definition: types.h:75
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
#define BTRFS_TYPE_FILE
Definition: shellext.h:85
static __inline POPLOCK fcb_oplock(fcb *fcb)
Definition: btrfs_drv.h:1683
unsigned int ULONG
Definition: retypes.h:1
file_ref * fileref
Definition: btrfs_drv.h:399
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2779

Referenced by fsctl_request().

◆ fsctl_request()

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

Definition at line 4968 of file fsctl.c.

4968  {
4969  PIRP Irp = *Pirp;
4971  NTSTATUS Status;
4972 
4973  if (IrpSp->FileObject && IrpSp->FileObject->FsContext) {
4975 
4976  if (Vcb->type == VCB_TYPE_FS)
4978  }
4979 
4980  switch (type) {
4989 #if (NTDDI_VERSION >= NTDDI_WIN7)
4990  case FSCTL_REQUEST_OPLOCK:
4991 #endif
4993  break;
4994 
4995  case FSCTL_LOCK_VOLUME:
4997  break;
4998 
4999  case FSCTL_UNLOCK_VOLUME:
5001  break;
5002 
5003  case FSCTL_DISMOUNT_VOLUME:
5005  break;
5006 
5009  break;
5010 
5012  WARN("STUB: FSCTL_IS_PATHNAME_VALID\n");
5014  break;
5015 
5017  WARN("STUB: FSCTL_MARK_VOLUME_DIRTY\n");
5019  break;
5020 
5022  WARN("STUB: FSCTL_QUERY_RETRIEVAL_POINTERS\n");
5024  break;
5025 
5026  case FSCTL_GET_COMPRESSION:
5028  break;
5029 
5030  case FSCTL_SET_COMPRESSION:
5032  break;
5033 
5035  WARN("STUB: FSCTL_SET_BOOTLOADER_ACCESSED\n");
5037  break;
5038 
5041  break;
5042 
5043  case FSCTL_QUERY_FAT_BPB:
5044  WARN("STUB: FSCTL_QUERY_FAT_BPB\n");
5046  break;
5047 
5049  Status = fs_get_statistics(Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.FileSystemControl.OutputBufferLength, &Irp->IoStatus.Information);
5050  break;
5051 
5053  WARN("STUB: FSCTL_GET_NTFS_VOLUME_DATA\n");
5055  break;
5056 
5058  WARN(