ReactOS  0.4.14-dev-77-gd9e7c48
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)
 
static NTSTATUS dismount_volume (device_extension *Vcb, 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)
 
NTSTATUS fsctl_request (PDEVICE_OBJECT DeviceObject, PIRP *Pirp, uint32_t type)
 

Variables

LIST_ENTRY VcbList
 
ERESOURCE global_loading_lock
 
PDRIVER_OBJECT drvobj
 

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

2717  {
2719  NTSTATUS Status;
2720  PFILE_OBJECT fileobj, mountmgrfo;
2722  HANDLE h;
2723  LIST_ENTRY* le;
2724  device* dev;
2725  DEV_ITEM* di;
2726  uint64_t dev_id, size;
2727  uint8_t* mb;
2728  uint64_t* stats;
2729  UNICODE_STRING mmdevpath, pnp_name, pnp_name2;
2730  volume_child* vc;
2731  PDEVICE_OBJECT mountmgr;
2732  KEY searchkey;
2733  traverse_ptr tp;
2736  pdo_device_extension* pdode;
2737  const GUID* pnp_guid;
2739 
2740  pnp_name.Buffer = NULL;
2741 
2742  if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), processor_mode))
2744 
2745  if (!Vcb->vde) {
2746  WARN("not allowing second device to be added to non-PNP device\n");
2747  return STATUS_NOT_SUPPORTED;
2748  }
2749 
2750  if (Vcb->readonly) // FIXME - handle adding R/W device to seeding device
2752 
2753 #if defined(_WIN64)
2754  if (IoIs32bitProcess(Irp)) {
2755  if (IrpSp->Parameters.FileSystemControl.InputBufferLength != sizeof(uint32_t))
2756  return STATUS_INVALID_PARAMETER;
2757 
2758  h = (HANDLE)LongToHandle((*(uint32_t*)Irp->AssociatedIrp.SystemBuffer));
2759  } else {
2760 #endif
2761  if (IrpSp->Parameters.FileSystemControl.InputBufferLength != sizeof(HANDLE))
2762  return STATUS_INVALID_PARAMETER;
2763 
2764  h = *(PHANDLE)Irp->AssociatedIrp.SystemBuffer;
2765 #if defined(_WIN64)
2766  }
2767 #endif
2768 
2769  Status = ObReferenceObjectByHandle(h, 0, *IoFileObjectType, Irp->RequestorMode, (void**)&fileobj, NULL);
2770 
2771  if (!NT_SUCCESS(Status)) {
2772  ERR("ObReferenceObjectByHandle returned %08x\n", Status);
2773  return Status;
2774  }
2775 
2776  DeviceObject = fileobj->DeviceObject;
2777 
2779  if (!NT_SUCCESS(Status)) {
2780  ERR("get_device_pnp_name returned %08x\n", Status);
2781  ObDereferenceObject(fileobj);
2782  return Status;
2783  }
2784 
2785  // If this is a disk, we have been handed the PDO, so need to go up to find something we can use
2786  if (RtlCompareMemory(pnp_guid, &GUID_DEVINTERFACE_DISK, sizeof(GUID)) == sizeof(GUID) && DeviceObject->AttachedDevice)
2787  DeviceObject = DeviceObject->AttachedDevice;
2788 
2790  if (!NT_SUCCESS(Status)) {
2791  ERR("IOCTL_DISK_IS_WRITABLE returned %08x\n", Status);
2792  ObDereferenceObject(fileobj);
2793  return Status;
2794  }
2795 
2797  if (!NT_SUCCESS(Status)) {
2798  ERR("is_device_part_of_mounted_btrfs_raid returned %08x\n", Status);
2799  ObDereferenceObject(fileobj);
2800  return Status;
2801  }
2802 
2803  // if disk, check it has no partitions
2804  if (RtlCompareMemory(pnp_guid, &GUID_DEVINTERFACE_DISK, sizeof(GUID)) == sizeof(GUID)) {
2805  ULONG dlisize;
2807 
2808  dlisize = 0;
2809 
2810  do {
2811  dlisize += 1024;
2812 
2813  if (dli)
2814  ExFreePool(dli);
2815 
2816  dli = ExAllocatePoolWithTag(PagedPool, dlisize, ALLOC_TAG);
2817  if (!dli) {
2818  ERR("out of memory\n");
2820  goto end2;
2821  }
2822 
2824  } while (Status == STATUS_BUFFER_TOO_SMALL);
2825 
2826  if (NT_SUCCESS(Status) && dli->PartitionCount > 0) {
2827  ExFreePool(dli);
2828  ERR("not adding disk which has partitions\n");
2830  goto end2;
2831  }
2832 
2833  ExFreePool(dli);
2834  }
2835 
2837  &sdn, sizeof(STORAGE_DEVICE_NUMBER), true, NULL);
2838  if (NT_SUCCESS(Status)) {
2839  if (sdn.DeviceType != FILE_DEVICE_DISK) { // FIXME - accept floppies and CDs?
2840  WARN("device was not disk\n");
2841  ObDereferenceObject(fileobj);
2842  return STATUS_INVALID_PARAMETER;
2843  }
2844  } else {
2845  sdn.DeviceNumber = 0xffffffff;
2846  sdn.PartitionNumber = 0xffffffff;
2847  }
2848 
2850  &gli, sizeof(gli), true, NULL);
2851  if (!NT_SUCCESS(Status)) {
2852  ERR("error reading length information: %08x\n", Status);
2853  ObDereferenceObject(fileobj);
2854  return Status;
2855  }
2856 
2857  size = gli.Length.QuadPart;
2858 
2859  if (size < 0x100000) {
2860  ERR("device was not large enough to hold FS (%I64x bytes, need at least 1 MB)\n", size);
2861  ObDereferenceObject(fileobj);
2862  return STATUS_INTERNAL_ERROR;
2863  }
2864 
2866 
2867  ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
2868 
2869  if (Vcb->need_write)
2870  Status = do_write(Vcb, Irp);
2871  else
2873 
2874  free_trees(Vcb);
2875 
2876  if (!NT_SUCCESS(Status)) {
2877  ERR("do_write returned %08x\n", Status);
2878  goto end;
2879  }
2880 
2882  if (!dev) {
2883  ERR("out of memory\n");
2885  goto end;
2886  }
2887 
2888  RtlZeroMemory(dev, sizeof(device));
2889 
2890  dev->devobj = DeviceObject;
2891  dev->fileobj = fileobj;
2892  dev->seeding = false;
2893  init_device(Vcb, dev, true);
2894 
2895  InitializeListHead(&dev->space);
2896 
2897  if (size > 0x100000) { // add disk hole - the first MB is marked as used
2898  Status = add_space_entry(&dev->space, NULL, 0x100000, size - 0x100000);
2899  if (!NT_SUCCESS(Status)) {
2900  ERR("add_space_entry returned %08x\n", Status);
2901  goto end;
2902  }
2903  }
2904 
2905  dev_id = 0;
2906 
2907  le = Vcb->devices.Flink;
2908  while (le != &Vcb->devices) {
2909  device* dev2 = CONTAINING_RECORD(le, device, list_entry);
2910 
2911  if (dev2->devitem.dev_id > dev_id)
2912  dev_id = dev2->devitem.dev_id;
2913 
2914  le = le->Flink;
2915  }
2916 
2917  dev_id++;
2918 
2919  dev->devitem.dev_id = dev_id;
2920  dev->devitem.num_bytes = size;
2921  dev->devitem.bytes_used = 0;
2922  dev->devitem.optimal_io_align = Vcb->superblock.sector_size;
2923  dev->devitem.optimal_io_width = Vcb->superblock.sector_size;
2924  dev->devitem.minimal_io_size = Vcb->superblock.sector_size;
2925  dev->devitem.type = 0;
2926  dev->devitem.generation = 0;
2927  dev->devitem.start_offset = 0;
2928  dev->devitem.dev_group = 0;
2929  dev->devitem.seek_speed = 0;
2930  dev->devitem.bandwidth = 0;
2931  get_uuid(&dev->devitem.device_uuid);
2932  dev->devitem.fs_uuid = Vcb->superblock.uuid;
2933 
2935  if (!di) {
2936  ERR("out of memory\n");
2937  goto end;
2938  }
2939 
2940  RtlCopyMemory(di, &dev->devitem, sizeof(DEV_ITEM));
2941 
2942  Status = insert_tree_item(Vcb, Vcb->chunk_root, 1, TYPE_DEV_ITEM, di->dev_id, di, sizeof(DEV_ITEM), NULL, Irp);
2943  if (!NT_SUCCESS(Status)) {
2944  ERR("insert_tree_item returned %08x\n", Status);
2945  ExFreePool(di);
2946  goto end;
2947  }
2948 
2949  // add stats entry to dev tree
2950  stats = ExAllocatePoolWithTag(PagedPool, sizeof(uint64_t) * 5, ALLOC_TAG);
2951  if (!stats) {
2952  ERR("out of memory\n");
2954  goto end;
2955  }
2956 
2957  RtlZeroMemory(stats, sizeof(uint64_t) * 5);
2958 
2959  searchkey.obj_id = 0;
2960  searchkey.obj_type = TYPE_DEV_STATS;
2961  searchkey.offset = di->dev_id;
2962 
2963  Status = find_item(Vcb, Vcb->dev_root, &tp, &searchkey, false, Irp);
2964  if (!NT_SUCCESS(Status)) {
2965  ERR("error - find_item returned %08x\n", Status);
2966  ExFreePool(stats);
2967  goto end;
2968  }
2969 
2970  if (!keycmp(tp.item->key, searchkey)) {
2972  if (!NT_SUCCESS(Status)) {
2973  ERR("delete_tree_item returned %08x\n", Status);
2974  ExFreePool(stats);
2975  goto end;
2976  }
2977  }
2978 
2979  Status = insert_tree_item(Vcb, Vcb->dev_root, 0, TYPE_DEV_STATS, di->dev_id, stats, sizeof(uint64_t) * 5, NULL, Irp);
2980  if (!NT_SUCCESS(Status)) {
2981  ERR("insert_tree_item returned %08x\n", Status);
2982  ExFreePool(stats);
2983  goto end;
2984  }
2985 
2986  if (dev->trim && !dev->readonly && !Vcb->options.no_trim)
2988 
2989  // We clear the first megabyte of the device, so Windows doesn't identify it as another FS
2990  mb = ExAllocatePoolWithTag(PagedPool, 0x100000, ALLOC_TAG);
2991  if (!mb) {
2992  ERR("out of memory\n");
2994  goto end;
2995  }
2996 
2997  RtlZeroMemory(mb, 0x100000);
2998 
2999  Status = write_data_phys(DeviceObject, fileobj, 0, mb, 0x100000);
3000  if (!NT_SUCCESS(Status)) {
3001  ERR("write_data_phys returned %08x\n", Status);
3002  ExFreePool(mb);
3003  goto end;
3004  }
3005 
3006  ExFreePool(mb);
3007 
3008  vde = Vcb->vde;
3009  pdode = vde->pdode;
3010 
3012  if (!vc) {
3013  ERR("out of memory\n");
3015  goto end;
3016  }
3017 
3018  vc->uuid = dev->devitem.device_uuid;
3019  vc->devid = dev_id;
3020  vc->generation = Vcb->superblock.generation;
3021  vc->devobj = DeviceObject;
3022  vc->fileobj = fileobj;
3023  vc->notification_entry = NULL;
3024 
3026  drvobj, pnp_removal, vde->pdode, &vc->notification_entry);
3027  if (!NT_SUCCESS(Status))
3028  WARN("IoRegisterPlugPlayNotification returned %08x\n", Status);
3029 
3030  pnp_name2 = pnp_name;
3031 
3032  if (pnp_name.Length > 4 * sizeof(WCHAR) && pnp_name.Buffer[0] == '\\' && (pnp_name.Buffer[1] == '\\' || pnp_name.Buffer[1] == '?') &&
3033  pnp_name.Buffer[2] == '?' && pnp_name.Buffer[3] == '\\') {
3034  pnp_name2.Buffer = &pnp_name2.Buffer[3];
3035  pnp_name2.Length -= 3 * sizeof(WCHAR);
3036  pnp_name2.MaximumLength -= 3 * sizeof(WCHAR);
3037  }
3038 
3039  vc->pnp_name.Length = vc->pnp_name.MaximumLength = pnp_name2.Length;
3040 
3041  if (pnp_name2.Length == 0)
3042  vc->pnp_name.Buffer = NULL;
3043  else {
3045  if (!vc->pnp_name.Buffer) {
3046  ERR("out of memory\n");
3048  goto end;
3049  }
3050 
3051  RtlCopyMemory(vc->pnp_name.Buffer, pnp_name2.Buffer, pnp_name2.Length);
3052  }
3053 
3054  vc->size = size;
3055  vc->seeding = false;
3056  vc->disk_num = sdn.DeviceNumber;
3057  vc->part_num = sdn.PartitionNumber;
3058  vc->had_drive_letter = false;
3059 
3061  InsertTailList(&pdode->children, &vc->list_entry);
3062  pdode->num_children++;
3063  pdode->children_loaded++;
3065 
3067  Status = IoGetDeviceObjectPointer(&mmdevpath, FILE_READ_ATTRIBUTES, &mountmgrfo, &mountmgr);
3068  if (!NT_SUCCESS(Status))
3069  ERR("IoGetDeviceObjectPointer returned %08x\n", Status);
3070  else {
3071  Status = remove_drive_letter(mountmgr, &pnp_name);
3073  WARN("remove_drive_letter returned %08x\n", Status);
3074 
3076 
3077  ObDereferenceObject(mountmgrfo);
3078  }
3079 
3080  Vcb->superblock.num_devices++;
3081  Vcb->superblock.total_bytes += size;
3082  Vcb->devices_loaded++;
3083  InsertTailList(&Vcb->devices, &dev->list_entry);
3084 
3085  // FIXME - send notification that volume size has increased
3086 
3087  ObReferenceObject(DeviceObject); // for Vcb
3088 
3089  Status = do_write(Vcb, Irp);
3090  if (!NT_SUCCESS(Status))
3091  ERR("do_write returned %08x\n", Status);
3092 
3093  ObReferenceObject(fileobj);
3094 
3095 end:
3096  free_trees(Vcb);
3097 
3098  ExReleaseResourceLite(&Vcb->tree_lock);
3099 
3100 end2:
3101  ObDereferenceObject(fileobj);
3102 
3103  if (pnp_name.Buffer)
3105 
3106  if (NT_SUCCESS(Status))
3108 
3109  return Status;
3110 }
DEVICE_TYPE DeviceType
Definition: ntddstor.h:232
uint64_t obj_id
Definition: btrfs.h:127
#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:827
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
uint8_t obj_type
Definition: btrfs.h:128
#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:7652
#define keycmp(key1, key2)
Definition: btrfs_drv.h:980
#define WARN(fmt,...)
Definition: debug.h:111
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:833
#define InsertTailList(ListHead, Entry)
static void get_uuid(BTRFS_UUID *uuid)
Definition: fsctl.c:74
uint64_t offset
Definition: btrfs.h:129
#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:3301
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:64
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
BTRFS_UUID uuid
Definition: btrfs_drv.h:822
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
uint64_t num_children
Definition: btrfs_drv.h:859
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
#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:824
NTSTATUS add_space_entry(LIST_ENTRY *list, LIST_ENTRY *list_size, uint64_t offset, uint64_t size)
Definition: free-space.c:189
PDRIVER_OBJECT drvobj
Definition: btrfs.c:66
Definition: devices.h:37
bool seeding
Definition: btrfs_drv.h:829
smooth NULL
Definition: ftsmooth.c:416
PDEVICE_OBJECT devobj
Definition: btrfs_drv.h:825
#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:845
static NTSTATUS is_device_part_of_mounted_btrfs_raid(PDEVICE_OBJECT devobj, PFILE_OBJECT fileobj)
Definition: fsctl.c:2616
void free_trees(device_extension *Vcb)
Definition: treefuncs.c:793
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:2883
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
#define STATUS_NOT_FOUND
Definition: shellext.h:67
uint64_t children_loaded
Definition: btrfs_drv.h:860
NTSTATUS get_device_pnp_name(_In_ PDEVICE_OBJECT DeviceObject, _Out_ PUNICODE_STRING pnp_name, _Out_ const GUID **guid)
Definition: btrfs.c:4134
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:63
__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:2841
bool had_drive_letter
Definition: btrfs_drv.h:830
#define Vcb
Definition: cdprocs.h:1425
PVOID HANDLE
Definition: typedefs.h:71
ERESOURCE child_lock
Definition: btrfs_drv.h:861
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
void * notification_entry
Definition: btrfs_drv.h:831
* PFILE_OBJECT
Definition: iotypes.h:1955
ULONG disk_num
Definition: btrfs_drv.h:832
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:857
#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:496
PFILE_OBJECT fileobj
Definition: btrfs_drv.h:826
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:414
uint64_t dev_id
Definition: btrfs.h:161
#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:117
POBJECT_TYPE IoFileObjectType
Definition: iomgr.c:36
BYTE uint8_t
Definition: msvideo1.c:66
LARGE_INTEGER Length
Definition: winioctl.h:423
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
Definition: btrfs.h:126
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
#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:4157
Definition: list.h:27
DEV_ITEM devitem
Definition: btrfs_drv.h:514
uint64_t dev_id
UINT32 uint32_t
Definition: types.h:75
UNICODE_STRING pnp_name
Definition: btrfs.c:4164
void trim_whole_device(device *dev)
Definition: fsctl.c:2698
uint64_t size
Definition: btrfs_drv.h:828
#define ObReferenceObject
Definition: obfuncs.h:204
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:409
LIST_ENTRY list_entry
Definition: btrfs_drv.h:834
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:208
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
uint64_t devid
Definition: btrfs_drv.h:823
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2772
LIST_ENTRY children
Definition: btrfs_drv.h:862
return STATUS_SUCCESS
Definition: btrfs.c:2966
#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:112
NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp)
Definition: treefuncs.c:989
void volume_removal(PDRIVER_OBJECT DriverObject, PUNICODE_STRING devpath)
Definition: search.c:575
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:65

Referenced by fsctl_request().

◆ allow_extended_dasd_io()

static NTSTATUS allow_extended_dasd_io ( device_extension Vcb,
PFILE_OBJECT  FileObject 
)
static

Definition at line 3112 of file fsctl.c.

3112  {
3113  fcb* fcb;
3114  ccb* ccb;
3115 
3116  TRACE("FSCTL_ALLOW_EXTENDED_DASD_IO\n");
3117 
3118  if (!FileObject)
3119  return STATUS_INVALID_PARAMETER;
3120 
3121  fcb = FileObject->FsContext;
3122  ccb = FileObject->FsContext2;
3123 
3124  if (!fcb)
3125  return STATUS_INVALID_PARAMETER;
3126 
3127  if (fcb != Vcb->volume_fcb)
3128  return STATUS_INVALID_PARAMETER;
3129 
3130  if (!ccb)
3131  return STATUS_INVALID_PARAMETER;
3132 
3133  ccb->allow_extended_dasd_io = true;
3134 
3135  return STATUS_SUCCESS;
3136 }
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:593
#define TRACE(s)
Definition: solgame.cpp:4
struct _fcb fcb
Definition: btrfs_drv.h:1301
#define Vcb
Definition: cdprocs.h:1425
bool allow_extended_dasd_io
Definition: btrfs_drv.h:375
struct _ccb ccb
return STATUS_SUCCESS
Definition: btrfs.c:2966

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

521  {
522  PFILE_OBJECT subvol_obj;
525  fcb* subvol_fcb;
526  HANDLE subvolh;
527  bool readonly, posix;
528  ANSI_STRING utf8;
529  UNICODE_STRING nameus;
530  ULONG len;
531  fcb* fcb;
532  ccb* ccb;
533  file_ref *fileref, *fr2;
534 
535 #if defined(_WIN64)
536  if (IoIs32bitProcess(Irp)) {
537  btrfs_create_snapshot32* bcs32 = data;
538 
541 
544 
545  subvolh = Handle32ToHandle(bcs32->subvol);
546 
547  nameus.Buffer = bcs32->name;
548  nameus.Length = nameus.MaximumLength = bcs32->namelen;
549 
550  readonly = bcs32->readonly;
551  posix = bcs32->posix;
552  } else {
553 #endif
556 
559 
560  subvolh = bcs->subvol;
561 
562  nameus.Buffer = bcs->name;
563  nameus.Length = nameus.MaximumLength = bcs->namelen;
564 
565  readonly = bcs->readonly;
566  posix = bcs->posix;
567 #if defined(_WIN64)
568  }
569 #endif
570 
571  if (!subvolh)
573 
574  if (!FileObject || !FileObject->FsContext)
576 
577  fcb = FileObject->FsContext;
578  ccb = FileObject->FsContext2;
579 
580  if (!fcb || !ccb || fcb->type != BTRFS_TYPE_DIRECTORY)
582 
583  fileref = ccb->fileref;
584 
585  if (!fileref) {
586  ERR("fileref was NULL\n");
588  }
589 
590  if (!(ccb->access & FILE_ADD_SUBDIRECTORY)) {
591  WARN("insufficient privileges\n");
592  return STATUS_ACCESS_DENIED;
593  }
594 
595  if (Vcb->readonly)
597 
599  return STATUS_ACCESS_DENIED;
600 
601  if (!is_file_name_valid(&nameus, posix))
603 
604  utf8.Buffer = NULL;
605 
606  Status = utf16_to_utf8(NULL, 0, &len, nameus.Buffer, nameus.Length);
607  if (!NT_SUCCESS(Status)) {
608  ERR("utf16_to_utf8 failed with error %08x\n", Status);
609  return Status;
610  }
611 
612  if (len == 0) {
613  ERR("utf16_to_utf8 returned a length of 0\n");
614  return STATUS_INTERNAL_ERROR;
615  }
616 
617  if (len > 0xffff) {
618  ERR("len was too long\n");
620  }
621 
622  utf8.MaximumLength = utf8.Length = (USHORT)len;
624 
625  if (!utf8.Buffer) {
626  ERR("out of memory\n");
628  }
629 
630  Status = utf16_to_utf8(utf8.Buffer, len, &len, nameus.Buffer, nameus.Length);
631  if (!NT_SUCCESS(Status)) {
632  ERR("utf16_to_utf8 failed with error %08x\n", Status);
633  goto end2;
634  }
635 
636  ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
637 
638  // no need for fcb_lock as we have tree_lock exclusively
639  Status = open_fileref(fcb->Vcb, &fr2, &nameus, fileref, false, NULL, NULL, PagedPool, ccb->case_sensitive || posix, Irp);
640 
641  if (NT_SUCCESS(Status)) {
642  if (!fr2->deleted) {
643  WARN("file already exists\n");
644  free_fileref(fr2);
646  goto end3;
647  } else
648  free_fileref(fr2);
650  ERR("open_fileref returned %08x\n", Status);
651  goto end3;
652  }
653 
654  Status = ObReferenceObjectByHandle(subvolh, 0, *IoFileObjectType, Irp->RequestorMode, (void**)&subvol_obj, NULL);
655  if (!NT_SUCCESS(Status)) {
656  ERR("ObReferenceObjectByHandle returned %08x\n", Status);
657  goto end3;
658  }
659 
660  if (subvol_obj->DeviceObject != FileObject->DeviceObject) {
662  goto end;
663  }
664 
665  subvol_fcb = subvol_obj->FsContext;
666  if (!subvol_fcb) {
668  goto end;
669  }
670 
671  if (subvol_fcb->inode != subvol_fcb->subvol->root_item.objid) {
672  WARN("handle inode was %I64x, expected %I64x\n", subvol_fcb->inode, subvol_fcb->subvol->root_item.objid);
674  goto end;
675  }
676 
677  ccb = subvol_obj->FsContext2;
678 
679  if (!ccb) {
681  goto end;
682  }
683 
684  if (!(ccb->access & FILE_TRAVERSE)) {
685  WARN("insufficient privileges\n");
687  goto end;
688  }
689 
690  if (fcb == Vcb->dummy_fcb) {
692  goto end;
693  }
694 
695  // clear unique flag on extents of open files in subvol
696  if (!IsListEmpty(&subvol_fcb->subvol->fcbs)) {
697  LIST_ENTRY* le = subvol_fcb->subvol->fcbs.Flink;
698 
699  while (le != &subvol_fcb->subvol->fcbs) {
700  struct _fcb* openfcb = CONTAINING_RECORD(le, struct _fcb, list_entry);
701  LIST_ENTRY* le2;
702 
703  le2 = openfcb->extents.Flink;
704 
705  while (le2 != &openfcb->extents) {
707 
708  ext->unique = false;
709 
710  le2 = le2->Flink;
711  }
712 
713  le = le->Flink;
714  }
715  }
716 
717  Status = do_create_snapshot(Vcb, FileObject, subvol_fcb, &utf8, &nameus, readonly, Irp);
718 
719  if (NT_SUCCESS(Status)) {
720  file_ref* fr;
721 
722  Status = open_fileref(Vcb, &fr, &nameus, fileref, false, NULL, NULL, PagedPool, false, Irp);
723 
724  if (!NT_SUCCESS(Status)) {
725  ERR("open_fileref returned %08x\n", Status);
727  } else {
729  free_fileref(fr);
730  }
731  }
732 
733 end:
734  ObDereferenceObject(subvol_obj);
735 
736 end3:
737  ExReleaseResourceLite(&Vcb->tree_lock);
738 
739 end2:
740  ExFreePool(utf8.Buffer);
741 
742  return Status;
743 }
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
void utf16_to_utf8(const wstring &utf16, string &utf8)
Definition: main.cpp:694
#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:111
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:377
#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:1543
_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:451
#define ALLOC_TAG
Definition: btrfs_drv.h:91
#define FILE_TRAVERSE
Definition: nt_native.h:643
bool is_file_name_valid(_In_ PUNICODE_STRING us, _In_ bool posix)
Definition: btrfs.c:5383
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:997
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:81
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
uint8_t type
Definition: btrfs_drv.h:280
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:593
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:340
USHORT MaximumLength
Definition: env_spec_w32.h:377
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
struct _fcb fcb
Definition: btrfs_drv.h:1301
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
uint64_t inode
Definition: btrfs_drv.h:278
#define Vcb
Definition: cdprocs.h:1425
struct _file_ref * fileref
Definition: btrfs_drv.h:295
LIST_ENTRY extents
Definition: btrfs_drv.h:290
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
* PFILE_OBJECT
Definition: iotypes.h:1955
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
bool case_sensitive
Definition: btrfs_drv.h:381
#define FILE_ADD_SUBDIRECTORY
Definition: nt_native.h:635
GLenum GLsizei len
Definition: glext.h:6722
Definition: typedefs.h:117
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:1576
Status
Definition: gdiplustypes.h:24
void *POINTER_32 subvol
Definition: btrfsioctl.h:55
#define ERR(fmt,...)
Definition: debug.h:109
#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:277
Definition: list.h:27
void free_fileref(_Inout_ file_ref *fr)
Definition: btrfs.c:1820
#define FILE_ACTION_ADDED
Definition: name.c:36
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:261
struct _ccb ccb
file_ref * fileref
Definition: btrfs_drv.h:378
return STATUS_SUCCESS
Definition: btrfs.c:2966
struct _device_extension * Vcb
Definition: btrfs_drv.h:276
#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 745 of file fsctl.c.

745  {
746  btrfs_create_subvol* bcs;
747  fcb *fcb, *rootfcb = NULL;
748  ccb* ccb;
749  file_ref* fileref;
751  uint64_t id;
752  root* r = NULL;
754  BTRFS_TIME now;
755  ULONG len;
756  uint16_t irsize;
757  UNICODE_STRING nameus;
758  ANSI_STRING utf8;
759  INODE_REF* ir;
760  KEY searchkey;
762  SECURITY_SUBJECT_CONTEXT subjcont;
763  PSID owner;
764  BOOLEAN defaulted;
765  uint64_t* root_num;
766  file_ref *fr = NULL, *fr2;
767  dir_child* dc = NULL;
768 
769  fcb = FileObject->FsContext;
770  if (!fcb) {
771  ERR("error - fcb was NULL\n");
772  return STATUS_INTERNAL_ERROR;
773  }
774 
775  ccb = FileObject->FsContext2;
776  if (!ccb) {
777  ERR("error - ccb was NULL\n");
778  return STATUS_INTERNAL_ERROR;
779  }
780 
781  fileref = ccb->fileref;
782 
783  if (fcb->type != BTRFS_TYPE_DIRECTORY) {
784  ERR("parent FCB was not a directory\n");
785  return STATUS_NOT_A_DIRECTORY;
786  }
787 
788  if (!fileref) {
789  ERR("fileref was NULL\n");
791  }
792 
793  if (fileref->deleted || fcb->deleted) {
794  ERR("parent has been deleted\n");
795  return STATUS_FILE_DELETED;
796  }
797 
798  if (!(ccb->access & FILE_ADD_SUBDIRECTORY)) {
799  WARN("insufficient privileges\n");
800  return STATUS_ACCESS_DENIED;
801  }
802 
803  if (Vcb->readonly)
805 
807  return STATUS_ACCESS_DENIED;
808 
809  if (fcb == Vcb->dummy_fcb)
810  return STATUS_ACCESS_DENIED;
811 
812  if (!data || datalen < sizeof(btrfs_create_subvol))
814 
815  bcs = (btrfs_create_subvol*)data;
816 
817  if (offsetof(btrfs_create_subvol, name[0]) + bcs->namelen > datalen)
819 
820  nameus.Length = nameus.MaximumLength = bcs->namelen;
821  nameus.Buffer = bcs->name;
822 
823  if (!is_file_name_valid(&nameus, bcs->posix))
825 
826  utf8.Buffer = NULL;
827 
828  Status = utf16_to_utf8(NULL, 0, &len, nameus.Buffer, nameus.Length);
829  if (!NT_SUCCESS(Status)) {
830  ERR("utf16_to_utf8 failed with error %08x\n", Status);
831  return Status;
832  }
833 
834  if (len == 0) {
835  ERR("utf16_to_utf8 returned a length of 0\n");
836  return STATUS_INTERNAL_ERROR;
837  }
838 
839  if (len > 0xffff) {
840  ERR("len was too long\n");
842  }
843 
844  utf8.MaximumLength = utf8.Length = (USHORT)len;
846 
847  if (!utf8.Buffer) {
848  ERR("out of memory\n");
850  }
851 
852  Status = utf16_to_utf8(utf8.Buffer, len, &len, nameus.Buffer, nameus.Length);
853  if (!NT_SUCCESS(Status)) {
854  ERR("utf16_to_utf8 failed with error %08x\n", Status);
855  goto end2;
856  }
857 
858  ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
859 
862 
863  // no need for fcb_lock as we have tree_lock exclusively
864  Status = open_fileref(fcb->Vcb, &fr2, &nameus, fileref, false, NULL, NULL, PagedPool, ccb->case_sensitive || bcs->posix, Irp);
865 
866  if (NT_SUCCESS(Status)) {
867  if (!fr2->deleted) {
868  WARN("file already exists\n");
869  free_fileref(fr2);
871  goto end;
872  } else
873  free_fileref(fr2);
875  ERR("open_fileref returned %08x\n", Status);
876  goto end;
877  }
878 
879  id = InterlockedIncrement64(&Vcb->root_root->lastinode);
880  Status = create_root(Vcb, id, &r, false, 0, Irp);
881 
882  if (!NT_SUCCESS(Status)) {
883  ERR("create_root returned %08x\n", Status);
884  goto end;
885  }
886 
887  TRACE("created root %I64x\n", id);
888 
889  if (!Vcb->uuid_root) {
890  root* uuid_root;
891 
892  TRACE("uuid root doesn't exist, creating it\n");
893 
894  Status = create_root(Vcb, BTRFS_ROOT_UUID, &uuid_root, false, 0, Irp);
895 
896  if (!NT_SUCCESS(Status)) {
897  ERR("create_root returned %08x\n", Status);
898  goto end;
899  }
900 
901  Vcb->uuid_root = uuid_root;
902  }
903 
904  root_num = ExAllocatePoolWithTag(PagedPool, sizeof(uint64_t), ALLOC_TAG);
905  if (!root_num) {
906  ERR("out of memory\n");
908  goto end;
909  }
910 
911  tp.tree = NULL;
912 
913  do {
914  get_uuid(&r->root_item.uuid);
915 
916  RtlCopyMemory(&searchkey.obj_id, &r->root_item.uuid, sizeof(uint64_t));
917  searchkey.obj_type = TYPE_SUBVOL_UUID;
918  RtlCopyMemory(&searchkey.offset, &r->root_item.uuid.uuid[sizeof(uint64_t)], sizeof(uint64_t));
919 
920  Status = find_item(Vcb, Vcb->uuid_root, &tp, &searchkey, false, Irp);
921  } while (NT_SUCCESS(Status) && !keycmp(searchkey, tp.item->key));
922 
923  *root_num = r->id;
924 
925  Status = insert_tree_item(Vcb, Vcb->uuid_root, searchkey.obj_id, searchkey.obj_type, searchkey.offset, root_num, sizeof(uint64_t), NULL, Irp);
926  if (!NT_SUCCESS(Status)) {
927  ERR("insert_tree_item returned %08x\n", Status);
928  ExFreePool(root_num);
929  goto end;
930  }
931 
932  r->root_item.inode.generation = 1;
933  r->root_item.inode.st_size = 3;
934  r->root_item.inode.st_blocks = Vcb->superblock.node_size;
935  r->root_item.inode.st_nlink = 1;
936  r->root_item.inode.st_mode = __S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; // 40755
937  r->root_item.inode.flags = 0xffffffff80000000; // FIXME - find out what these mean
938 
939  if (bcs->readonly)
940  r->root_item.flags |= BTRFS_SUBVOL_READONLY;
941 
942  r->root_item.objid = SUBVOL_ROOT_INODE;
943  r->root_item.bytes_used = Vcb->superblock.node_size;
944  r->root_item.ctransid = Vcb->superblock.generation;
945  r->root_item.otransid = Vcb->superblock.generation;
946  r->root_item.ctime = now;
947  r->root_item.otime = now;
948 
949  // add .. inode to new subvol
950 
951  rootfcb = create_fcb(Vcb, PagedPool);
952  if (!rootfcb) {
953  ERR("out of memory\n");
955  goto end;
956  }
957 
958  rootfcb->Vcb = Vcb;
959 
960  rootfcb->subvol = r;
961  rootfcb->inode = SUBVOL_ROOT_INODE;
962  rootfcb->type = BTRFS_TYPE_DIRECTORY;
963 
964  rootfcb->inode_item.generation = Vcb->superblock.generation;
965  rootfcb->inode_item.transid = Vcb->superblock.generation;
966  rootfcb->inode_item.st_nlink = 1;
967  rootfcb->inode_item.st_mode = __S_IFDIR | inherit_mode(fileref->fcb, true);
968  rootfcb->inode_item.st_atime = rootfcb->inode_item.st_ctime = rootfcb->inode_item.st_mtime = rootfcb->inode_item.otime = now;
969  rootfcb->inode_item.st_gid = GID_NOBODY;
970 
971  rootfcb->atts = get_file_attributes(Vcb, rootfcb->subvol, rootfcb->inode, rootfcb->type, false, true, Irp);
972 
973  if (r->root_item.flags & BTRFS_SUBVOL_READONLY)
974  rootfcb->atts |= FILE_ATTRIBUTE_READONLY;
975 
976  SeCaptureSubjectContext(&subjcont);
977 
978  Status = SeAssignSecurity(fcb->sd, NULL, (void**)&rootfcb->sd, true, &subjcont, IoGetFileObjectGenericMapping(), PagedPool);
979 
980  if (!NT_SUCCESS(Status)) {
981  ERR("SeAssignSecurity returned %08x\n", Status);
982  goto end;
983  }
984 
985  if (!rootfcb->sd) {
986  ERR("SeAssignSecurity returned NULL security descriptor\n");
988  goto end;
989  }
990 
991  Status = RtlGetOwnerSecurityDescriptor(rootfcb->sd, &owner, &defaulted);
992  if (!NT_SUCCESS(Status)) {
993  ERR("RtlGetOwnerSecurityDescriptor returned %08x\n", Status);
994  rootfcb->inode_item.st_uid = UID_NOBODY;
995  rootfcb->sd_dirty = true;
996  } else {
997  rootfcb->inode_item.st_uid = sid_to_uid(owner);
998  rootfcb->sd_dirty = rootfcb->inode_item.st_uid == UID_NOBODY;
999  }
1000 
1001  find_gid(rootfcb, fileref->fcb, &subjcont);
1002 
1003  rootfcb->inode_item_changed = true;
1004 
1005  acquire_fcb_lock_exclusive(Vcb);
1006  InsertTailList(&r->fcbs, &rootfcb->list_entry);
1007  InsertTailList(&Vcb->all_fcbs, &rootfcb->list_entry_all);
1008  r->fcbs_version++;
1009  release_fcb_lock(Vcb);
1010 
1011  rootfcb->Header.IsFastIoPossible = fast_io_possible(rootfcb);
1012  rootfcb->Header.AllocationSize.QuadPart = 0;
1013  rootfcb->Header.FileSize.QuadPart = 0;
1014  rootfcb->Header.ValidDataLength.QuadPart = 0;
1015 
1016  rootfcb->created = true;
1017 
1018  if (fileref->fcb->inode_item.flags & BTRFS_INODE_COMPRESS)
1020 
1021  rootfcb->prop_compression = fileref->fcb->prop_compression;
1023 
1024  r->lastinode = rootfcb->inode;
1025 
1026  // add INODE_REF
1027 
1028  irsize = (uint16_t)(offsetof(INODE_REF, name[0]) + sizeof(DOTDOT) - 1);
1029  ir = ExAllocatePoolWithTag(PagedPool, irsize, ALLOC_TAG);
1030  if (!ir) {
1031  ERR("out of memory\n");
1033  goto end;
1034  }
1035 
1036  ir->index = 0;
1037  ir->n = sizeof(DOTDOT) - 1;
1038  RtlCopyMemory(ir->name, DOTDOT, ir->n);
1039 
1040  Status = insert_tree_item(Vcb, r, r->root_item.objid, TYPE_INODE_REF, r->root_item.objid, ir, irsize, NULL, Irp);
1041  if (!NT_SUCCESS(Status)) {
1042  ERR("insert_tree_item returned %08x\n", Status);
1043  ExFreePool(ir);
1044  goto end;
1045  }
1046 
1047  // create fileref for entry in other subvolume
1048 
1049  fr = create_fileref(Vcb);
1050  if (!fr) {
1051  ERR("out of memory\n");
1052 
1053  reap_fcb(rootfcb);
1054 
1056  goto end;
1057  }
1058 
1059  fr->fcb = rootfcb;
1060 
1061  mark_fcb_dirty(rootfcb);
1062 
1063  fr->parent = fileref;
1064 
1065  Status = add_dir_child(fileref->fcb, r->id, true, &utf8, &nameus, BTRFS_TYPE_DIRECTORY, &dc);
1066  if (!NT_SUCCESS(Status))
1067  WARN("add_dir_child returned %08x\n", Status);
1068 
1069  fr->dc = dc;
1070  dc->fileref = fr;
1071 
1073  if (!fr->fcb->hash_ptrs) {
1074  ERR("out of memory\n");
1075  free_fileref(fr);
1077  goto end;
1078  }
1079 
1080  RtlZeroMemory(fr->fcb->hash_ptrs, sizeof(LIST_ENTRY*) * 256);
1081 
1083  if (!fr->fcb->hash_ptrs_uc) {
1084  ERR("out of memory\n");
1085  free_fileref(fr);
1087  goto end;
1088  }
1089 
1090  RtlZeroMemory(fr->fcb->hash_ptrs_uc, sizeof(LIST_ENTRY*) * 256);
1091 
1092  ExAcquireResourceExclusiveLite(&fileref->fcb->nonpaged->dir_children_lock, true);
1093  InsertTailList(&fileref->children, &fr->list_entry);
1094  ExReleaseResourceLite(&fileref->fcb->nonpaged->dir_children_lock);
1095 
1097 
1098  if (fr->fcb->type == BTRFS_TYPE_DIRECTORY)
1099  fr->fcb->fileref = fr;
1100 
1101  fr->created = true;
1102  mark_fileref_dirty(fr);
1103 
1104  // change fcb->subvol's ROOT_ITEM
1105 
1106  fcb->subvol->root_item.ctransid = Vcb->superblock.generation;
1107  fcb->subvol->root_item.ctime = now;
1108 
1109  // change fcb's INODE_ITEM
1110 
1111  fcb->inode_item.transid = Vcb->superblock.generation;
1112  fcb->inode_item.st_size += utf8.Length * 2;
1113  fcb->inode_item.sequence++;
1114 
1115  if (!ccb->user_set_change_time)
1117 
1118  if (!ccb->user_set_write_time)
1120 
1121  fcb->inode_item_changed = true;
1123 
1124  fr->fcb->subvol->parent = fcb->subvol->id;
1125 
1127 
1128 end:
1129  if (!NT_SUCCESS(Status)) {
1130  if (fr) {
1131  fr->deleted = true;
1132  mark_fileref_dirty(fr);
1133  } else if (rootfcb) {
1134  rootfcb->deleted = true;
1135  mark_fcb_dirty(rootfcb);
1136  }
1137 
1138  if (r) {
1139  RemoveEntryList(&r->list_entry);
1140  InsertTailList(&Vcb->drop_roots, &r->list_entry);
1141  }
1142  }
1143 
1144  ExReleaseResourceLite(&Vcb->tree_lock);
1145 
1146  if (NT_SUCCESS(Status)) {
1149  }
1150 
1151 end2:
1152  if (fr)
1153  free_fileref(fr);
1154 
1155  return Status;
1156 }
#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:346
uint64_t obj_id
Definition: btrfs.h:127
VOID NTAPI SeCaptureSubjectContext(OUT PSECURITY_SUBJECT_CONTEXT SubjectContext)
Definition: access.c:301
void utf16_to_utf8(const wstring &utf16, string &utf8)
Definition: main.cpp:694
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
uint8_t obj_type
Definition: btrfs.h:128
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
BTRFS_TIME otime
Definition: btrfs.h:285
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:48
#define keycmp(key1, key2)
Definition: btrfs_drv.h:980
#define WARN(fmt,...)
Definition: debug.h:111
LONG NTSTATUS
Definition: precomp.h:26
enum prop_compression_type prop_compression
Definition: btrfs_drv.h:297
HDC dc
Definition: cylfrac.c:34
#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:377
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:1027
#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:1543
static void get_uuid(BTRFS_UUID *uuid)
Definition: fsctl.c:74
BTRFS_TIME st_ctime
Definition: btrfs.h:283
uint64_t offset
Definition: btrfs.h:129
LIST_ENTRY list_entry_all
Definition: btrfs_drv.h:326
bool user_set_write_time
Definition: btrfs_drv.h:384
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:451
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:1757
uint32_t st_gid
Definition: btrfs.h:276
SECURITY_DESCRIPTOR * sd
Definition: btrfs_drv.h:282
void mark_fileref_dirty(_In_ file_ref *fileref)
Definition: btrfs.c:1686
#define STATUS_NOT_A_DIRECTORY
Definition: udferr_usr.h:169
bool is_file_name_valid(_In_ PUNICODE_STRING us, _In_ bool posix)
Definition: btrfs.c:5383
file_ref * create_fileref(device_extension *Vcb)
Definition: create.c:116
tree * tree
Definition: btrfs_drv.h:495
static __inline bool is_subvol_readonly(root *r, PIRP Irp)
Definition: btrfs_drv.h:997
#define BTRFS_INODE_COMPRESS
Definition: propsheet.h:87
LIST_ENTRY list_entry
Definition: btrfs_drv.h:325
#define S_IRGRP
Definition: propsheet.h:41
#define S_IXOTH
Definition: propsheet.h:61
uint64_t sequence
Definition: btrfs.h:280
uint32_t st_nlink
Definition: btrfs.h:274
time_t now
Definition: finger.c:65
bool created
Definition: btrfs_drv.h:341
#define FILE_ACTION_MODIFIED
char name[1]
Definition: btrfs.h:354
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:81
unsigned char BOOLEAN
void reap_fcb(fcb *fcb)
Definition: btrfs.c:1712
LIST_ENTRY ** hash_ptrs_uc
Definition: btrfs_drv.h:307
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
void mark_fcb_dirty(_In_ fcb *fcb)
Definition: btrfs.c:1664
#define TYPE_INODE_REF
Definition: btrfs.h:20
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
uint16_t n
Definition: btrfs.h:353
uint8_t type
Definition: btrfs_drv.h:280
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:593
BTRFS_TIME st_mtime
Definition: btrfs.h:284
#define increase_fileref_refcount(fileref)
Definition: btrfs_drv.h:1647
#define STATUS_FILE_DELETED
Definition: udferr_usr.h:172
bool prop_compression_changed
Definition: btrfs_drv.h:315
void find_gid(struct _fcb *fcb, struct _fcb *parfcb, PSECURITY_SUBJECT_CONTEXT subjcont)
Definition: security.c:841
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2883
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:272
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
bool deleted
Definition: btrfs_drv.h:340
USHORT MaximumLength
Definition: env_spec_w32.h:377
#define S_IXGRP
Definition: propsheet.h:49
uint64_t st_size
Definition: btrfs.h:271
#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:1301
bool sd_dirty
Definition: btrfs_drv.h:310
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:2603
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define TYPE_SUBVOL_UUID
Definition: btrfs.h:47
uint64_t inode
Definition: btrfs_drv.h:278
bool user_set_change_time
Definition: btrfs_drv.h:385
#define Vcb
Definition: cdprocs.h:1425
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
struct _file_ref * fileref
Definition: btrfs_drv.h:295
#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:857
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
BTRFS_TIME st_atime
Definition: btrfs.h:282
dir_child * dc
Definition: btrfs_drv.h:348
tree_data * item
Definition: btrfs_drv.h:496
#define S_IXUSR
Definition: propsheet.h:37
#define S_IROTH
Definition: propsheet.h:53
bool case_sensitive
Definition: btrfs_drv.h:381
#define FILE_ADD_SUBDIRECTORY
Definition: nt_native.h:635
GLenum GLsizei len
Definition: glext.h:6722
bool created
Definition: btrfs_drv.h:317
fcb * fcb
Definition: btrfs_drv.h:335
Definition: typedefs.h:117
INODE_ITEM inode_item
Definition: btrfs_drv.h:281
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:1205
uint64_t generation
Definition: btrfs.h:269
uint64_t flags
Definition: btrfs.h:279
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:1576
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
Definition: btrfs.h:126
UINT64 uint64_t
Definition: types.h:77
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
ULONG atts
Definition: btrfs_drv.h:286
unsigned short USHORT
Definition: pedump.c:61
#define BTRFS_ROOT_UUID
Definition: btrfs.h:56
bool deleted
Definition: btrfs_drv.h:284
uint32_t inherit_mode(fcb *parfcb, bool is_dir)
Definition: create.c:1832
uint64_t index
Definition: btrfs.h:352
uint64_t transid
Definition: btrfs.h:270
#define STATUS_OBJECT_NAME_INVALID
Definition: udferr_usr.h:148
#define S_IRUSR
Definition: propsheet.h:29
struct _root * subvol
Definition: btrfs_drv.h:277
void free_fileref(_Inout_ file_ref *fr)
Definition: btrfs.c:1820
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:1662
Definition: name.c:36
static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME *out)
Definition: btrfs_drv.h:953
unsigned int ULONG
Definition: retypes.h:1
GLenum GLuint id
Definition: glext.h:5579
LIST_ENTRY ** hash_ptrs
Definition: btrfs_drv.h:306
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define fast_io_possible(fcb)
Definition: btrfs_drv.h:1575
struct _ccb ccb
file_ref * fileref
Definition: btrfs_drv.h:378
uint32_t st_uid
Definition: btrfs.h:275
return STATUS_SUCCESS
Definition: btrfs.c:2966
#define BTRFS_SUBVOL_READONLY
Definition: btrfs.h:100
bool inode_item_changed
Definition: btrfs_drv.h:296
#define GID_NOBODY
Definition: btrfs_drv.h:95
struct _device_extension * Vcb
Definition: btrfs_drv.h:276
#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:352
uint32_t st_mode
Definition: btrfs.h:277

Referenced by fsctl_request().

◆ dismount_volume()

static NTSTATUS dismount_volume ( device_extension Vcb,
PIRP  Irp 
)
static

Definition at line 2571 of file fsctl.c.

2571  {
2572  NTSTATUS Status;
2573 
2574  TRACE("FSCTL_DISMOUNT_VOLUME\n");
2575 
2576  if (!(Vcb->Vpb->Flags & VPB_MOUNTED))
2577  return STATUS_SUCCESS;
2578 
2579  if (Vcb->disallow_dismount || Vcb->page_file_count != 0) {
2580  WARN("attempting to dismount boot volume or one containing a pagefile\n");
2581  return STATUS_ACCESS_DENIED;
2582  }
2583 
2585  if (!NT_SUCCESS(Status)) {
2586  WARN("FsRtlNotifyVolumeEvent returned %08x\n", Status);
2587  }
2588 
2589  ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
2590 
2591  if (!Vcb->locked) {
2593 
2594  if (Vcb->need_write && !Vcb->readonly) {
2595  Status = do_write(Vcb, Irp);
2596 
2597  if (!NT_SUCCESS(Status))
2598  ERR("do_write returned %08x\n", Status);
2599  }
2600  }
2601 
2602  free_trees(Vcb);
2603 
2604  Vcb->removing = true;
2605 
2606  if (Vcb->vde) {
2608  Vcb->vde->mounted_device = NULL;
2609  }
2610 
2611  ExReleaseResourceLite(&Vcb->tree_lock);
2612 
2613  return STATUS_SUCCESS;
2614 }
#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:7652
#define WARN(fmt,...)
Definition: debug.h:111
LONG NTSTATUS
Definition: precomp.h:26
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:793
#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
#define Vcb
Definition: cdprocs.h:1425
#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:2214
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
return STATUS_SUCCESS
Definition: btrfs.c:2966
static void update_volumes(device_extension *Vcb)
Definition: fsctl.c:2548
#define VPB_MOUNTED
Definition: iotypes.h:1764

Referenced by 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 261 of file fsctl.c.

261  {
263  uint64_t id;
265  root *r, *subvol = subvol_fcb->subvol;
266  KEY searchkey;
268  uint64_t address, *root_num;
270  BTRFS_TIME now;
271  fcb* fcb = parent->FsContext;
272  ccb* ccb = parent->FsContext2;
273  LIST_ENTRY* le;
274  file_ref *fileref, *fr;
275  dir_child* dc = NULL;
276 
277  if (!ccb) {
278  ERR("error - ccb was NULL\n");
279  return STATUS_INTERNAL_ERROR;
280  }
281 
282  if (!(ccb->access & FILE_ADD_SUBDIRECTORY)) {
283  WARN("insufficient privileges\n");
284  return STATUS_ACCESS_DENIED;
285  }
286 
287  fileref = ccb->fileref;
288 
289  if (fileref->fcb == Vcb->dummy_fcb)
290  return STATUS_ACCESS_DENIED;
291 
292  // flush open files on this subvol
293 
295 
296  // flush metadata
297 
298  if (Vcb->need_write)
299  Status = do_write(Vcb, Irp);
300  else
302 
303  free_trees(Vcb);
304 
305  if (!NT_SUCCESS(Status)) {
306  ERR("do_write returned %08x\n", Status);
307  return Status;
308  }
309 
311 
312  // create new root
313 
314  id = InterlockedIncrement64(&Vcb->root_root->lastinode);
315  Status = create_root(Vcb, id, &r, true, Vcb->superblock.generation, Irp);
316 
317  if (!NT_SUCCESS(Status)) {
318  ERR("create_root returned %08x\n", Status);
319  goto end;
320  }
321 
322  r->lastinode = subvol->lastinode;
323 
324  if (!Vcb->uuid_root) {
325  root* uuid_root;
326 
327  TRACE("uuid root doesn't exist, creating it\n");
328 
329  Status = create_root(Vcb, BTRFS_ROOT_UUID, &uuid_root, false, 0, Irp);
330 
331  if (!NT_SUCCESS(Status)) {
332  ERR("create_root returned %08x\n", Status);
333  goto end;
334  }
335 
336  Vcb->uuid_root = uuid_root;
337  }
338 
339  root_num = ExAllocatePoolWithTag(PagedPool, sizeof(uint64_t), ALLOC_TAG);
340  if (!root_num) {
341  ERR("out of memory\n");
343  goto end;
344  }
345 
346  tp.tree = NULL;
347 
348  do {
349  get_uuid(&r->root_item.uuid);
350 
351  RtlCopyMemory(&searchkey.obj_id, &r->root_item.uuid, sizeof(uint64_t));
352  searchkey.obj_type = TYPE_SUBVOL_UUID;
353  RtlCopyMemory(&searchkey.offset, &r->root_item.uuid.uuid[sizeof(uint64_t)], sizeof(uint64_t));
354 
355  Status = find_item(Vcb, Vcb->uuid_root, &tp, &searchkey, false, Irp);
356  } while (NT_SUCCESS(Status) && !keycmp(searchkey, tp.item->key));
357 
358  *root_num = r->id;
359 
360  Status = insert_tree_item(Vcb, Vcb->uuid_root, searchkey.obj_id, searchkey.obj_type, searchkey.offset, root_num, sizeof(uint64_t), NULL, Irp);
361  if (!NT_SUCCESS(Status)) {
362  ERR("insert_tree_item returned %08x\n", Status);
363  ExFreePool(root_num);
364  goto end;
365  }
366 
367  searchkey.obj_id = r->id;
368  searchkey.obj_type = TYPE_ROOT_ITEM;
369  searchkey.offset = 0xffffffffffffffff;
370 
371  Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
372  if (!NT_SUCCESS(Status)) {
373  ERR("error - find_item returned %08x\n", Status);
374  goto end;
375  }
376 
377  Status = snapshot_tree_copy(Vcb, subvol->root_item.block_number, r, &address, Irp, &rollback);
378  if (!NT_SUCCESS(Status)) {
379  ERR("snapshot_tree_copy returned %08x\n", Status);
380  goto end;
381  }
382 
385 
386  r->root_item.inode.generation = 1;
387  r->root_item.inode.st_size = 3;
388  r->root_item.inode.st_blocks = subvol->root_item.inode.st_blocks;
389  r->root_item.inode.st_nlink = 1;
390  r->root_item.inode.st_mode = __S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; // 40755
391  r->root_item.inode.flags = 0xffffffff80000000; // FIXME - find out what these mean
392  r->root_item.generation = Vcb->superblock.generation;
393  r->root_item.objid = subvol->root_item.objid;
394  r->root_item.block_number = address;
395  r->root_item.bytes_used = subvol->root_item.bytes_used;
396  r->root_item.last_snapshot_generation = Vcb->superblock.generation;
397  r->root_item.root_level = subvol->root_item.root_level;
398  r->root_item.generation2 = Vcb->superblock.generation;
399  r->root_item.parent_uuid = subvol->root_item.uuid;
400  r->root_item.ctransid = subvol->root_item.ctransid;
401  r->root_item.otransid = Vcb->superblock.generation;
402  r->root_item.ctime = subvol->root_item.ctime;
403  r->root_item.otime = now;
404 
405  if (readonly)
406  r->root_item.flags |= BTRFS_SUBVOL_READONLY;
407 
408  r->treeholder.address = address;
409 
410  // FIXME - do we need to copy over the send and receive fields too?
411 
412  if (tp.item->key.obj_id != searchkey.obj_id || tp.item->key.obj_type != searchkey.obj_type) {
413  ERR("error - could not find ROOT_ITEM for subvol %I64x\n", r->id);
415  goto end;
416  }
417 
418  RtlCopyMemory(tp.item->data, &r->root_item, sizeof(ROOT_ITEM));
419 
420  // update ROOT_ITEM of original subvol
421 
422  subvol->root_item.last_snapshot_generation = Vcb->superblock.generation;
423 
425 
426  // create fileref for entry in other subvolume
427 
428  fr = create_fileref(Vcb);
429  if (!fr) {
430  ERR("out of memory\n");
432  goto end;
433  }
434 
435  Status = open_fcb(Vcb, r, r->root_item.objid, BTRFS_TYPE_DIRECTORY, utf8, false, fcb, &fr->fcb, PagedPool, Irp);
436  if (!NT_SUCCESS(Status)) {
437  ERR("open_fcb returned %08x\n", Status);
438  free_fileref(fr);
439  goto end;
440  }
441 
442  fr->parent = fileref;
443 
444  Status = add_dir_child(fileref->fcb, r->id, true, utf8, name, BTRFS_TYPE_DIRECTORY, &dc);
445  if (!NT_SUCCESS(Status))
446  WARN("add_dir_child returned %08x\n", Status);
447 
448  fr->dc = dc;
449  dc->fileref = fr;
450 
451  ExAcquireResourceExclusiveLite(&fileref->fcb->nonpaged->dir_children_lock, true);
452  InsertTailList(&fileref->children, &fr->list_entry);
453  ExReleaseResourceLite(&fileref->fcb->nonpaged->dir_children_lock);
454 
456 
457  fr->created = true;
458  mark_fileref_dirty(fr);
459 
460  if (fr->fcb->type == BTRFS_TYPE_DIRECTORY)
461  fr->fcb->fileref = fr;
462 
463  fr->fcb->subvol->parent = fileref->fcb->subvol->id;
464 
465  free_fileref(fr);
466 
467  // change fcb's INODE_ITEM
468 
469  fcb->inode_item.transid = Vcb->superblock.generation;
471  fcb->inode_item.st_size += utf8->Length * 2;
472 
475 
476  if (!ccb->user_set_write_time)
478 
479  fcb->inode_item_changed = true;
481 
482  fcb->subvol->root_item.ctime = now;
483  fcb->subvol->root_item.ctransid = Vcb->superblock.generation;
484 
487 
488  le = subvol->fcbs.Flink;
489  while (le != &subvol->fcbs) {
490  struct _fcb* fcb2 = CONTAINING_RECORD(le, struct _fcb, list_entry);
491  LIST_ENTRY* le2 = fcb2->extents.Flink;
492 
493  while (le2 != &fcb2->extents) {
495 
496  if (!ext->ignore)
497  ext->unique = false;
498 
499  le2 = le2->Flink;
500  }
501 
502  le = le->Flink;
503  }
504 
505  Status = do_write(Vcb, Irp);
506 
507  free_trees(Vcb);
508 
509  if (!NT_SUCCESS(Status))
510  ERR("do_write returned %08x\n", Status);
511 
512 end:
513  if (NT_SUCCESS(Status))
515  else
517 
518  return Status;
519 }
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
struct _file_ref * parent
Definition: btrfs_drv.h:346
uint64_t obj_id
Definition: btrfs.h:127
void do_rollback(device_extension *Vcb, LIST_ENTRY *rollback)
Definition: treefuncs.c:1049
void clear_rollback(LIST_ENTRY *rollback)
Definition: treefuncs.c:1028
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
uint8_t obj_type
Definition: btrfs.h:128
#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:88
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
NTSTATUS do_write(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7652
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:598
#define keycmp(key1, key2)
Definition: btrfs_drv.h:980
#define WARN(fmt,...)
Definition: debug.h:111
LONG NTSTATUS
Definition: precomp.h:26
HDC dc
Definition: cylfrac.c:34
#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:377
#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:1543
static void get_uuid(BTRFS_UUID *uuid)
Definition: fsctl.c:74
BTRFS_TIME st_ctime
Definition: btrfs.h:283
uint64_t offset
Definition: btrfs.h:129
uint8_t * data
Definition: btrfs_drv.h:410
bool user_set_write_time
Definition: btrfs_drv.h:384
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
#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:1757
void mark_fileref_dirty(_In_ file_ref *fileref)
Definition: btrfs.c:1686
file_ref * create_fileref(device_extension *Vcb)
Definition: create.c:116
tree * tree
Definition: btrfs_drv.h:495
#define S_IRGRP
Definition: propsheet.h:41
#define S_IXOTH
Definition: propsheet.h:61
uint64_t sequence
Definition: btrfs.h:280
time_t now
Definition: finger.c:65
bool created
Definition: btrfs_drv.h:341
#define FILE_ACTION_MODIFIED
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:81
smooth NULL
Definition: ftsmooth.c:416
char ext[3]
Definition: mkdosfs.c:358
void mark_fcb_dirty(_In_ fcb *fcb)
Definition: btrfs.c:1664
uint8_t type
Definition: btrfs_drv.h:280
void free_trees(device_extension *Vcb)
Definition: treefuncs.c:793
void flush_subvol_fcbs(root *subvol)
Definition: fsctl.c:244
BTRFS_TIME st_mtime
Definition: btrfs.h:284
#define increase_fileref_refcount(fileref)
Definition: btrfs_drv.h:1647
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:2883
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
#define S_IXGRP
Definition: propsheet.h:49
uint64_t st_size
Definition: btrfs.h:271
#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:2897
#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:385
#define Vcb
Definition: cdprocs.h:1425
GLuint address
Definition: glext.h:9393
struct _file_ref * fileref
Definition: btrfs_drv.h:295
LIST_ENTRY extents
Definition: btrfs_drv.h:290
#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:857
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
dir_child * dc
Definition: btrfs_drv.h:348
tree_data * item
Definition: btrfs_drv.h:496
#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:335
Definition: typedefs.h:117
INODE_ITEM inode_item
Definition: btrfs_drv.h:281
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:1205
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
Definition: btrfs.h:126
UINT64 uint64_t
Definition: types.h:77
#define BTRFS_ROOT_UUID
Definition: btrfs.h:56
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define TYPE_ROOT_ITEM
Definition: btrfs.h:28
uint64_t transid
Definition: btrfs.h:270
#define S_IRUSR
Definition: propsheet.h:29
static void mark_subvol_dirty(device_extension *Vcb, root *r)
Definition: fsctl.c:4054
struct _root * subvol
Definition: btrfs_drv.h:277
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:1301
void free_fileref(_Inout_ file_ref *fr)
Definition: btrfs.c:1820
#define FILE_ACTION_ADDED
#define __S_IFDIR
Definition: btrfs_drv.h:1662
Definition: name.c:36
static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME *out)
Definition: btrfs_drv.h:953
GLenum GLuint id
Definition: glext.h:5579
file_ref * fileref
Definition: btrfs_drv.h:378
return STATUS_SUCCESS
Definition: btrfs.c:2966
#define BTRFS_SUBVOL_READONLY
Definition: btrfs.h:100
bool inode_item_changed
Definition: btrfs_drv.h:296
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
LIST_ENTRY list_entry
Definition: btrfs_drv.h:352

Referenced by create_snapshot().

◆ do_unlock_volume()

void do_unlock_volume ( device_extension Vcb)

Definition at line 2318 of file fsctl.c.

2318  {
2319  KIRQL irql;
2320 
2322 
2323  Vcb->locked = false;
2324  Vcb->Vpb->Flags &= ~VPB_LOCKED;
2325  Vcb->locked_fileobj = NULL;
2326 
2328 
2329  if (Vcb->lock_paused_balance)
2330  KeSetEvent(&Vcb->balance.event, 0, false);
2331 }
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:1765
smooth NULL
Definition: ftsmooth.c:416
#define Vcb
Definition: cdprocs.h:1425
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 3243 of file fsctl.c.

3243  {
3245  fcb *fcb = FileObject ? FileObject->FsContext : NULL, *sourcefcb;
3246  ccb *ccb = FileObject ? FileObject->FsContext2 : NULL, *sourceccb;
3247  NTSTATUS Status;
3248  PFILE_OBJECT sourcefo;
3249  uint64_t sourcelen, nbytes = 0;
3250  LIST_ENTRY rollback, *le, newexts;
3252  BTRFS_TIME now;
3253  bool make_inline;
3254 
3255  if (!ded || datalen < sizeof(DUPLICATE_EXTENTS_DATA))
3256  return STATUS_BUFFER_TOO_SMALL;
3257 
3258  if (Vcb->readonly)
3260 
3261  if (ded->ByteCount.QuadPart == 0)
3262  return STATUS_SUCCESS;
3263 
3264  if (!fcb || !ccb || fcb == Vcb->volume_fcb)
3265  return STATUS_INVALID_PARAMETER;
3266 
3268  return STATUS_ACCESS_DENIED;
3269 
3270  if (Irp->RequestorMode == UserMode && !(ccb->access & FILE_WRITE_DATA)) {
3271  WARN("insufficient privileges\n");
3272  return STATUS_ACCESS_DENIED;
3273  }
3274 
3275  if (!fcb->ads && fcb->type != BTRFS_TYPE_FILE && fcb->type != BTRFS_TYPE_SYMLINK)
3276  return STATUS_INVALID_PARAMETER;
3277 
3278  Status = ObReferenceObjectByHandle(ded->FileHandle, 0, *IoFileObjectType, Irp->RequestorMode, (void**)&sourcefo, NULL);
3279  if (!NT_SUCCESS(Status)) {
3280  ERR("ObReferenceObjectByHandle returned %08x\n", Status);
3281  return Status;
3282  }
3283 
3284  if (sourcefo->DeviceObject != FileObject->DeviceObject) {
3285  WARN("source and destination are on different volumes\n");
3286  ObDereferenceObject(sourcefo);
3287  return STATUS_INVALID_PARAMETER;
3288  }
3289 
3290  sourcefcb = sourcefo->FsContext;
3291  sourceccb = sourcefo->FsContext2;
3292 
3293  if (!sourcefcb || !sourceccb || sourcefcb == Vcb->volume_fcb) {
3294  ObDereferenceObject(sourcefo);
3295  return STATUS_INVALID_PARAMETER;
3296  }
3297 
3298  if (!sourcefcb->ads && !fcb->ads) {
3299  if ((ded->SourceFileOffset.QuadPart & (Vcb->superblock.sector_size - 1)) || (ded->TargetFileOffset.QuadPart & (Vcb->superblock.sector_size - 1))) {
3300  ObDereferenceObject(sourcefo);
3301  return STATUS_INVALID_PARAMETER;
3302  }
3303 
3304  if (ded->ByteCount.QuadPart & (Vcb->superblock.sector_size - 1)) {
3305  ObDereferenceObject(sourcefo);
3306  return STATUS_INVALID_PARAMETER;
3307  }
3308  }
3309 
3310  if (Irp->RequestorMode == UserMode && (!(sourceccb->access & FILE_READ_DATA) || !(sourceccb->access & FILE_READ_ATTRIBUTES))) {
3311  WARN("insufficient privileges\n");
3312  ObDereferenceObject(sourcefo);
3313  return STATUS_ACCESS_DENIED;
3314  }
3315 
3316  if (!sourcefcb->ads && sourcefcb->type != BTRFS_TYPE_FILE && sourcefcb->type != BTRFS_TYPE_SYMLINK) {
3317  ObDereferenceObject(sourcefo);
3318  return STATUS_INVALID_PARAMETER;
3319  }
3320 
3321  sourcelen = sourcefcb->ads ? sourcefcb->adsdata.Length : sourcefcb->inode_item.st_size;
3322 
3323  if (sector_align(sourcelen, Vcb->superblock.sector_size) < (uint64_t)ded->SourceFileOffset.QuadPart + (uint64_t)ded->ByteCount.QuadPart) {
3324  ObDereferenceObject(sourcefo);
3325  return STATUS_NOT_SUPPORTED;
3326  }
3327 
3328  if (fcb == sourcefcb &&
3331  WARN("source and destination are the same, and the ranges overlap\n");
3332  ObDereferenceObject(sourcefo);
3333  return STATUS_INVALID_PARAMETER;
3334  }
3335 
3336  // fail if nocsum flag set on one file but not the other
3337  if (!fcb->ads && !sourcefcb->ads && (fcb->inode_item.flags & BTRFS_INODE_NODATASUM) != (sourcefcb->inode_item.flags & BTRFS_INODE_NODATASUM)) {
3338  ObDereferenceObject(sourcefo);
3339  return STATUS_INVALID_PARAMETER;
3340  }
3341 
3343  InitializeListHead(&newexts);
3344 
3345  ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
3346 
3347  ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
3348 
3349  if (fcb != sourcefcb)
3350  ExAcquireResourceSharedLite(sourcefcb->Header.Resource, true);
3351 
3354  goto end;
3355  }
3356 
3357  if (!FsRtlFastCheckLockForRead(&sourcefcb->lock, &ded->SourceFileOffset, &ded->ByteCount, 0, FileObject, PsGetCurrentProcess())) {
3359  goto end;
3360  }
3361 
3362  make_inline = fcb->ads ? false : (fcb->inode_item.st_size <= Vcb->options.max_inline || fcb_is_inline(fcb));
3363 
3364  if (fcb->ads || sourcefcb->ads || make_inline || fcb_is_inline(sourcefcb)) {
3365  uint8_t* data2;
3366  ULONG bytes_read, dataoff, datalen2;
3367 
3368  if (make_inline) {
3369  dataoff = (ULONG)ded->TargetFileOffset.QuadPart;
3370  datalen2 = (ULONG)fcb->inode_item.st_size;
3371  } else if (fcb->ads) {
3372  dataoff = 0;
3373  datalen2 = (ULONG)ded->ByteCount.QuadPart;
3374  } else {
3375  dataoff = ded->TargetFileOffset.QuadPart % Vcb->superblock.sector_size;
3376  datalen2 = (ULONG)sector_align(ded->ByteCount.QuadPart + dataoff, Vcb->superblock.sector_size);
3377  }
3378 
3380  if (!data2) {
3381  ERR("out of memory\n");
3383  goto end;
3384  }
3385 
3386  if (dataoff > 0) {
3387  if (make_inline)
3388  Status = read_file(fcb, data2, 0, datalen2, NULL, Irp);
3389  else
3390  Status = read_file(fcb, data2, ded->TargetFileOffset.QuadPart - dataoff, dataoff, NULL, Irp);
3391 
3392  if (!NT_SUCCESS(Status)) {
3393  ERR("read_file returned %08x\n", Status);
3394  ExFreePool(data2);
3395  goto end;
3396  }
3397  }
3398 
3399  if (sourcefcb->ads) {
3400  Status = read_stream(sourcefcb, data2 + dataoff, ded->SourceFileOffset.QuadPart, (ULONG)ded->ByteCount.QuadPart, &bytes_read);
3401  if (!NT_SUCCESS(Status)) {
3402  ERR("read_stream returned %08x\n", Status);
3403  ExFreePool(data2);
3404  goto end;
3405  }
3406  } else {
3407  Status = read_file(sourcefcb, data2 + dataoff, ded->SourceFileOffset.QuadPart, ded->ByteCount.QuadPart, &bytes_read, Irp);
3408  if (!NT_SUCCESS(Status)) {
3409  ERR("read_file returned %08x\n", Status);
3410  ExFreePool(data2);
3411  goto end;
3412  }
3413  }
3414 
3415  if (dataoff + bytes_read < datalen2)
3416  RtlZeroMemory(data2 + dataoff + bytes_read, datalen2 - bytes_read);
3417 
3418  if (fcb->ads)
3420  else if (make_inline) {
3421  uint16_t edsize;
3422  EXTENT_DATA* ed;
3423 
3424  Status = excise_extents(Vcb, fcb, 0, sector_align(fcb->inode_item.st_size, Vcb->superblock.sector_size), Irp, &rollback);
3425  if (!NT_SUCCESS(Status)) {
3426  ERR("excise_extents returned %08x\n", Status);
3427  ExFreePool(data2);
3428  goto end;
3429  }
3430 
3431  edsize = (uint16_t)(offsetof(EXTENT_DATA, data[0]) + datalen2);
3432 
3434  if (!ed) {
3435  ERR("out of memory\n");
3436  ExFreePool(data2);
3438  goto end;
3439  }
3440 
3441  ed->generation = Vcb->superblock.generation;
3447 
3448  RtlCopyMemory(ed->data, data2, datalen2);
3449 
3450  Status = add_extent_to_fcb(fcb, 0, ed, edsize, false, NULL, &rollback);
3451  if (!NT_SUCCESS(Status)) {
3452  ERR("add_extent_to_fcb returned %08x\n", Status);
3453  ExFreePool(data2);
3454  goto end;
3455  }
3456 
3457  fcb->inode_item.st_blocks += datalen2;
3458  } else {
3459  uint64_t start = ded->TargetFileOffset.QuadPart - (ded->TargetFileOffset.QuadPart % Vcb->superblock.sector_size);
3460 
3461  Status = do_write_file(fcb, start, start + datalen2, data2, Irp, false, 0, &rollback);
3462  if (!NT_SUCCESS(Status)) {
3463  ERR("do_write_file returned %08x\n", Status);
3464  ExFreePool(data2);
3465  goto end;
3466  }
3467  }
3468 
3469  ExFreePool(data2);
3470  } else {
3471  LIST_ENTRY* lastextle;
3472 
3473  le = sourcefcb->extents.Flink;
3474  while (le != &sourcefcb->extents) {
3476 
3477  if (!ext->ignore) {
3478  if (ext->offset >= (uint64_t)ded->SourceFileOffset.QuadPart + (uint64_t)ded->ByteCount.QuadPart)
3479  break;
3480 
3481  if (ext->extent_data.type != EXTENT_TYPE_INLINE) {
3482  ULONG extlen = offsetof(extent, extent_data) + sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2);
3483  extent* ext2;
3484  EXTENT_DATA2 *ed2s, *ed2d;
3485  chunk* c;
3486 
3487  ed2s = (EXTENT_DATA2*)ext->extent_data.data;
3488 
3489  if (ext->offset + ed2s->num_bytes <= (uint64_t)ded->SourceFileOffset.QuadPart) {
3490  le = le->Flink;
3491  continue;
3492  }
3493 
3495  if (!ext2) {
3496  ERR("out of memory\n");
3498  goto end;
3499  }
3500 
3501  if (ext->offset < (uint64_t)ded->SourceFileOffset.QuadPart)
3502  ext2->offset = ded->TargetFileOffset.QuadPart;
3503  else
3504  ext2->offset = ext->offset - ded->SourceFileOffset.QuadPart + ded->TargetFileOffset.QuadPart;
3505 
3506  ext2->datalen = sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2);
3507  ext2->unique = false;
3508  ext2->ignore = false;
3509  ext2->inserted = true;
3510 
3511  ext2->extent_data.generation = Vcb->superblock.generation;
3512  ext2->extent_data.decoded_size = ext->extent_data.decoded_size;
3513  ext2->extent_data.compression = ext->extent_data.compression;
3514  ext2->extent_data.encryption = ext->extent_data.encryption;
3515  ext2->extent_data.encoding = ext->extent_data.encoding;
3516  ext2->extent_data.type = ext->extent_data.type;
3517 
3518  ed2d = (EXTENT_DATA2*)ext2->extent_data.data;
3519 
3520  ed2d->address = ed2s->address;
3521  ed2d->size = ed2s->size;
3522 
3523  if (ext->offset < (uint64_t)ded->SourceFileOffset.QuadPart) {
3524  ed2d->offset = ed2s->offset + ded->SourceFileOffset.QuadPart - ext->offset;
3525  ed2d->num_bytes = min((uint64_t)ded->ByteCount.QuadPart, ed2s->num_bytes + ext->offset - ded->SourceFileOffset.QuadPart);
3526  } else {
3527  ed2d->offset = ed2s->offset;
3528  ed2d->num_bytes = min(ded->SourceFileOffset.QuadPart + ded->ByteCount.QuadPart - ext->offset, ed2s->num_bytes);
3529  }
3530 
3531  if (ext->csum) {
3532  if (ext->extent_data.compression == BTRFS_COMPRESSION_NONE) {
3533  ext2->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(ed2d->num_bytes * sizeof(uint32_t) / Vcb->superblock.sector_size), ALLOC_TAG);
3534  if (!ext2->csum) {
3535  ERR("out of memory\n");
3537  ExFreePool(ext2);
3538  goto end;
3539  }
3540 
3541  RtlCopyMemory(ext2->csum, &ext->csum[(ed2d->offset - ed2s->offset) / Vcb->superblock.sector_size],
3542  (ULONG)(ed2d->num_bytes * sizeof(uint32_t) / Vcb->superblock.sector_size));
3543  } else {
3544  ext2->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(ed2d->size * sizeof(uint32_t) / Vcb->superblock.sector_size), ALLOC_TAG);
3545  if (!ext2->csum) {
3546  ERR("out of memory\n");
3548  ExFreePool(ext2);
3549  goto end;
3550  }
3551 
3552  RtlCopyMemory(ext2->csum, ext->csum, (ULONG)(ed2s->size * sizeof(uint32_t) / Vcb->superblock.sector_size));
3553  }
3554  } else
3555  ext2->csum = NULL;
3556 
3557  InsertTailList(&newexts, &ext2->list_entry);
3558 
3559  c = get_chunk_from_address(Vcb, ed2s->address);
3560  if (!c) {
3561  ERR("get_chunk_from_address(%I64x) failed\n", ed2s->address);
3563  goto end;
3564  }
3565 
3566  Status = update_changed_extent_ref(Vcb, c, ed2s->address, ed2s->size, fcb->subvol->id, fcb->inode, ext2->offset - ed2d->offset,
3567  1, fcb->inode_item.flags & BTRFS_INODE_NODATASUM, false, Irp);
3568  if (!NT_SUCCESS(Status)) {
3569  ERR("update_changed_extent_ref returned %08x\n", Status);
3570  goto end;
3571  }
3572 
3573  nbytes += ed2d->num_bytes;
3574  }
3575  }
3576 
3577  le = le->Flink;
3578  }
3579 
3581  if (!NT_SUCCESS(Status)) {
3582  ERR("excise_extents returned %08x\n", Status);
3583 
3584  while (!IsListEmpty(&newexts)) {
3586  ExFreePool(ext);
3587  }
3588 
3589  goto end;
3590  }
3591 
3592  // clear unique flags in source fcb
3593  le = sourcefcb->extents.Flink;
3594  while (le != &sourcefcb->extents) {
3596 
3597  if (!ext->ignore && ext->unique && (ext->extent_data.type == EXTENT_TYPE_REGULAR || ext->extent_data.type == EXTENT_TYPE_PREALLOC)) {
3598  EXTENT_DATA2* ed2s = (EXTENT_DATA2*)ext->extent_data.data;
3599  LIST_ENTRY* le2;
3600 
3601  le2 = newexts.Flink;
3602  while (le2 != &newexts) {
3604 
3605  if (ext2->extent_data.type == EXTENT_TYPE_REGULAR || ext2->extent_data.type == EXTENT_TYPE_PREALLOC) {
3606  EXTENT_DATA2* ed2d = (EXTENT_DATA2*)ext2->extent_data.data;
3607 
3608  if (ed2d->address == ed2s->address && ed2d->size == ed2s->size) {
3609  ext->unique = false;
3610  break;
3611  }
3612  }
3613 
3614  le2 = le2->Flink;
3615  }
3616  }
3617 
3618  le = le->Flink;
3619  }
3620 
3621  lastextle = &fcb->extents;
3622  while (!IsListEmpty(&newexts)) {
3624 
3625  add_extent(fcb, lastextle, ext);
3626  lastextle = &ext->list_entry;
3627  }
3628  }
3629 
3632 
3633  if (fcb->ads) {
3634  ccb->fileref->parent->fcb->inode_item.sequence++;
3635 
3636  if (!ccb->user_set_change_time)
3637  ccb->fileref->parent->fcb->inode_item.st_ctime = now;
3638 
3639  ccb->fileref->parent->fcb->inode_item_changed = true;
3640  mark_fcb_dirty(ccb->fileref->parent->fcb);
3641  } else {
3642  fcb->inode_item.st_blocks += nbytes;
3643  fcb->inode_item.sequence++;
3644 
3645  if (!ccb->user_set_change_time)
3647 
3648  if (!ccb->user_set_write_time) {
3651  }
3652 
3653  fcb->inode_item_changed = true;
3654  fcb->extents_changed = true;
3655  }
3656 
3658 
3659  if (FileObject->SectionObjectPointer->DataSectionObject)
3660  CcPurgeCacheSection(FileObject->SectionObjectPointer, &ded->TargetFileOffset, (ULONG)ded->ByteCount.QuadPart, false);
3661 
3663 
3664 end:
3665  ObDereferenceObject(sourcefo);
3666 
3667  if (NT_SUCCESS(Status))
3669  else
3671 
3672  if (fcb != sourcefcb)
3673  ExReleaseResourceLite(sourcefcb->Header.Resource);
3674 
3675  ExReleaseResourceLite(fcb->Header.Resource);
3676 
3677  ExReleaseResourceLite(&Vcb->tree_lock);
3678 
3679  return Status;
3680 }
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
uint64_t generation
Definition: btrfs.h:335
struct _file_ref * parent
Definition: btrfs_drv.h:346
void do_rollback(device_extension *Vcb, LIST_ENTRY *rollback)
Definition: treefuncs.c:1049
BOOLEAN NTAPI CcPurgeCacheSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN UninitializeCacheMaps)
Definition: fssup.c:384
void clear_rollback(LIST_ENTRY *rollback)
Definition: treefuncs.c:1028
uint8_t type
Definition: btrfs.h:340
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:1950
#define BTRFS_COMPRESSION_NONE
Definition: btrfs.h:60
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
uint64_t decoded_size
Definition: btrfs.h:336
#define WARN(fmt,...)
Definition: debug.h:111
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:377
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:2715
#define uint16_t
Definition: nsiface.idl:60
#define InsertTailList(ListHead, Entry)
int const JOCTET unsigned int datalen
Definition: jpeglib.h:1027
BTRFS_TIME st_ctime
Definition: btrfs.h:283
uint8_t encryption
Definition: btrfs.h:338
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:64
bool user_set_write_time
Definition: btrfs_drv.h:384
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
#define ALLOC_TAG
Definition: btrfs_drv.h:91
#define EXTENT_TYPE_INLINE
Definition: btrfs.h:69
while(1)
Definition: macro.lex.yy.c:740
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:997
uint64_t address
Definition: btrfs.h:345
uint64_t sequence
Definition: btrfs.h:280
time_t now
Definition: finger.c:65
#define FILE_READ_DATA
Definition: nt_native.h:628
bool extents_changed
Definition: btrfs_drv.h:312
#define FILE_ACTION_MODIFIED
#define PsGetCurrentProcess
Definition: psfuncs.h:17
#define BTRFS_ENCODING_NONE
Definition: btrfs.h:67
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:1664
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:346
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:3939
uint8_t type
Definition: btrfs_drv.h:280
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:593
BTRFS_TIME st_mtime
Definition: btrfs.h:284
#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:283
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:272
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
LARGE_INTEGER SourceFileOffset
Definition: shellext.h:176
uint16_t encoding
Definition: btrfs.h:339
#define BTRFS_ENCRYPTION_NONE
Definition: btrfs.h:65
uint64_t st_size
Definition: btrfs.h:271
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
uint64_t inode
Definition: btrfs_drv.h:278
#define BTRFS_INODE_NODATASUM
Definition: propsheet.h:76
bool user_set_change_time
Definition: btrfs_drv.h:385
#define Vcb
Definition: cdprocs.h:1425
const GLubyte * c
Definition: glext.h:8905
LIST_ENTRY extents
Definition: btrfs_drv.h:290
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
* PFILE_OBJECT
Definition: iotypes.h:1955
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:2368
#define false
Definition: stdbool.h:38
Definition: typedefs.h:117
#define EXTENT_TYPE_PREALLOC
Definition: btrfs.h:71
INODE_ITEM inode_item
Definition: btrfs_drv.h:281
POBJECT_TYPE IoFileObjectType
Definition: iomgr.c:36
BYTE uint8_t
Definition: msvideo1.c:66
uint64_t num_bytes
Definition: btrfs.h:348
uint64_t st_blocks
Definition: btrfs.h:272
uint64_t flags
Definition: btrfs.h:279
uint16_t edsize
Definition: write.c:2820
void add_extent(_In_ fcb *fcb, _In_ LIST_ENTRY *prevextle, _In_ __drv_aliasesMem extent *newext)
Definition: write.c:2351
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:70
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
uint8_t data[1]
Definition: btrfs.h:341
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:277
#define min(a, b)
Definition: monoChain.cc:55
Definition: list.h:27
ANSI_STRING adsdata
Definition: btrfs_drv.h:323
_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:1301
bool fcb_is_inline(fcb *fcb)
Definition: fsctl.c:3227
LARGE_INTEGER TargetFileOffset
Definition: shellext.h:177
HRESULT read_stream(BSCallback *, IStream *, void *, DWORD, DWORD *) DECLSPEC_HIDDEN
Definition: navigate.c:602
UINT32 uint32_t
Definition: types.h:75
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
NTSTATUS add_extent_to_fcb(_In_ fcb *fcb, _In_ uint64_t offset, _In_reads_bytes_(edsize) EXTENT_DATA *ed, _In_ uint16_t edsize, _In_ bool unique, _In_opt_ _When_(return >=0, __drv_aliasesMem) uint32_t *csum, _In_ LIST_ENTRY *rollback)
Definition: write.c:2720
#define BTRFS_TYPE_FILE
Definition: shellext.h:80
bool ads
Definition: btrfs_drv.h:319
#define STATUS_FILE_LOCK_CONFLICT
Definition: ntstatus.h:306
static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME *out)
Definition: btrfs_drv.h:953
#define c
Definition: ke_i.h:80
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:409
unsigned int ULONG
Definition: retypes.h:1
void send_notification_fcb(_In_ file_ref *fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream)
Definition: btrfs.c:1583
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
uint64_t offset
Definition: btrfs.h:347
file_ref * fileref
Definition: btrfs_drv.h:378
return STATUS_SUCCESS
Definition: btrfs.c:2966
EXTENT_DATA * ed
Definition: write.c:2818
bool inode_item_changed
Definition: btrfs_drv.h:296
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:178
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
uint8_t compression
Definition: btrfs.h:337
LONGLONG QuadPart
Definition: typedefs.h:112
#define BTRFS_TYPE_SYMLINK
Definition: shellext.h:86
Definition: tftpd.h:137

Referenced by fsctl_request().

◆ fcb_is_inline()

bool fcb_is_inline ( fcb fcb)

Definition at line 3227 of file fsctl.c.

3227  {
3228  LIST_ENTRY* le;
3229 
3230  le = fcb->extents.Flink;
3231  while (le != &fcb->extents) {
3233 
3234  if (!ext->ignore)
3235  return ext->extent_data.type == EXTENT_TYPE_INLINE;
3236 
3237  le = le->Flink;
3238  }
3239 
3240  return false;
3241 }
#define EXTENT_TYPE_INLINE
Definition: btrfs.h:69
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:119
LIST_ENTRY extents
Definition: btrfs_drv.h:290
Definition: typedefs.h:117
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 4532 of file fsctl.c.

4532  {
4533  btrfs_find_subvol* bfs;
4534  NTSTATUS Status;
4535  traverse_ptr tp;
4536  KEY searchkey;
4537 
4538  if (!in || inlen < sizeof(btrfs_find_subvol))
4539  return STATUS_INVALID_PARAMETER;
4540 
4541  if (!out || outlen < sizeof(WCHAR))
4542  return STATUS_INVALID_PARAMETER;
4543 
4544  if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), Irp->RequestorMode))
4546 
4547  bfs = (btrfs_find_subvol*)in;
4548 
4549  ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
4550 
4551  if (!Vcb->uuid_root) {
4552  ERR("couldn't find uuid root\n");
4554  goto end;
4555  }
4556 
4557  RtlCopyMemory(&searchkey.obj_id, &bfs->uuid, sizeof(uint64_t));
4558  searchkey.obj_type = TYPE_SUBVOL_UUID;
4559  RtlCopyMemory(&searchkey.offset, &bfs->uuid.uuid[sizeof(uint64_t)], sizeof(uint64_t));
4560 
4561  Status = find_item(Vcb, Vcb->uuid_root, &tp, &searchkey, false, Irp);
4562 
4563  if (!NT_SUCCESS(Status)) {
4564  ERR("find_item returned %08x\n", Status);
4565  goto end;
4566  }
4567 
4568  if (!keycmp(searchkey, tp.item->key) && tp.item->size >= sizeof(uint64_t)) {
4569  uint64_t* id = (uint64_t*)tp.item->data;
4570 
4571  if (bfs->ctransid != 0) {
4572  KEY searchkey2;
4573  traverse_ptr tp2;
4574 
4575  searchkey2.obj_id = *id;
4576  searchkey2.obj_type = TYPE_ROOT_ITEM;
4577  searchkey2.offset = 0xffffffffffffffff;
4578 
4579  Status = find_item(Vcb, Vcb->root_root, &tp2, &searchkey2, false, Irp);
4580  if (!NT_SUCCESS(Status)) {
4581  ERR("find_item returned %08x\n", Status);
4582  goto end;
4583  }
4584 
4585  if (tp2.item->key.obj_id == searchkey2.obj_id && tp2.item->key.obj_type == searchkey2.obj_type &&
4586  tp2.item->size >= offsetof(ROOT_ITEM, otransid)) {
4587  ROOT_ITEM* ri = (ROOT_ITEM*)tp2.item->data;
4588 
4589  if (ri->ctransid == bfs->ctransid) {
4590  TRACE("found subvol %I64x\n", *id);
4591  Status = get_subvol_path(Vcb, *id, out, outlen, Irp);
4592  goto end;
4593  }
4594  }
4595  } else {
4596  TRACE("found subvol %I64x\n", *id);
4597  Status = get_subvol_path(Vcb, *id, out, outlen, Irp);
4598  goto end;
4599  }
4600  }
4601 
4602  searchkey.obj_type = TYPE_SUBVOL_REC_UUID;
4603 
4604  Status = find_item(Vcb, Vcb->uuid_root, &tp, &searchkey, false, Irp);
4605 
4606  if (!NT_SUCCESS(Status)) {
4607  ERR("find_item returned %08x\n", Status);
4608  goto end;
4609  }
4610 
4611  if (!keycmp(searchkey, tp.item->key) && tp.item->size >= sizeof(uint64_t)) {
4612  uint64_t* ids = (uint64_t*)tp.item->data;
4613  ULONG i;
4614 
4615  for (i = 0; i < tp.item->size / sizeof(uint64_t); i++) {
4616  if (bfs->ctransid != 0) {
4617  KEY searchkey2;
4618  traverse_ptr tp2;
4619 
4620  searchkey2.obj_id = ids[i];
4621  searchkey2.obj_type = TYPE_ROOT_ITEM;
4622  searchkey2.offset = 0xffffffffffffffff;
4623 
4624  Status = find_item(Vcb, Vcb->root_root, &tp2, &searchkey2, false, Irp);
4625  if (!NT_SUCCESS(Status)) {
4626  ERR("find_item returned %08x\n", Status);
4627  goto end;
4628  }
4629 
4630  if (tp2.item->key.obj_id == searchkey2.obj_id && tp2.item->key.obj_type == searchkey2.obj_type &&
4631  tp2.item->size >= offsetof(ROOT_ITEM, otransid)) {
4632  ROOT_ITEM* ri = (ROOT_ITEM*)tp2.item->data;
4633 
4634  if (ri->ctransid == bfs->ctransid) {
4635  TRACE("found subvol %I64x\n", ids[i]);
4636  Status = get_subvol_path(Vcb, ids[i], out, outlen, Irp);
4637  goto end;
4638  }
4639  }
4640  } else {
4641  TRACE("found subvol %I64x\n", ids[i]);
4642  Status = get_subvol_path(Vcb, ids[i], out, outlen, Irp);
4643  goto end;
4644  }
4645  }
4646  }
4647 
4649 
4650 end:
4651  ExReleaseResourceLite(&Vcb->tree_lock);
4652 
4653  return Status;
4654 }
uint64_t obj_id
Definition: btrfs.h:127
#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:128
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define keycmp(key1, key2)
Definition: btrfs_drv.h:980
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:409
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:129
uint8_t * data
Definition: btrfs_drv.h:410
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:261
#define offsetof(TYPE, MEMBER)
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2883
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
uint64_t ctransid
Definition: btrfs.h:305
#define STATUS_NOT_FOUND
Definition: shellext.h:67
#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:1425
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:496
#define uint64_t
Definition: nsiface.idl:62
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
uint8_t uuid[16]
Definition: btrfs.h:123
Definition: btrfs.h:126
#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:4481
#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:262

Referenced by fsctl_request().

◆ flush_fcb_caches()

static void flush_fcb_caches ( device_extension Vcb)
static

Definition at line 2214 of file fsctl.c.

2214  {
2215  LIST_ENTRY* le;
2216 
2217  le = Vcb->all_fcbs.Flink;
2218  while (le != &Vcb->all_fcbs) {
2219  struct _fcb* fcb = CONTAINING_RECORD(le, struct _fcb, list_entry_all);
2221 
2222  if (fcb->type != BTRFS_TYPE_DIRECTORY && !fcb->deleted)
2223  CcFlushCache(&fcb->nonpaged->segment_object, NULL, 0, &iosb);
2224 
2225  le = le->Flink;
2226  }
2227 }
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:326
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:81
smooth NULL
Definition: ftsmooth.c:416
uint8_t type
Definition: btrfs_drv.h:280
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:119
#define Vcb
Definition: cdprocs.h:1425
Definition: typedefs.h:117
struct _fcb_nonpaged * nonpaged
Definition: btrfs_drv.h:273
bool deleted
Definition: btrfs_drv.h:284

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

◆ flush_subvol_fcbs()

void flush_subvol_fcbs ( root subvol)

Definition at line 244 of file fsctl.c.

244  {
245  LIST_ENTRY* le = subvol->fcbs.Flink;
246 
247  if (IsListEmpty(&subvol->fcbs))
248  return;
249 
250  while (le != &subvol->fcbs) {
251  struct _fcb* fcb = CONTAINING_RECORD(le, struct _fcb, list_entry);
253 
254  if (fcb->type != BTRFS_TYPE_DIRECTORY && !fcb->deleted)
255  CcFlushCache(&fcb->nonpaged->segment_object, NULL, 0, &iosb);
256 
257  le = le->Flink;
258  }
259 }
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:81
smooth NULL
Definition: ftsmooth.c:416
uint8_t type
Definition: btrfs_drv.h:280
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:119
Definition: typedefs.h:117
struct _fcb_nonpaged * nonpaged
Definition: btrfs_drv.h:273
bool deleted
Definition: btrfs_drv.h:284
struct _root * subvol
Definition: btrfs_drv.h:277
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 1697 of file fsctl.c.

1697  {
1698  FILESYSTEM_STATISTICS* fss;
1699 
1700  WARN("STUB: FSCTL_FILESYSTEM_GET_STATISTICS\n");
1701 
1702  // This is hideously wrong, but at least it stops SMB from breaking
1703 
1704  if (buflen < sizeof(FILESYSTEM_STATISTICS))
1705  return STATUS_BUFFER_TOO_SMALL;
1706 
1707  fss = buffer;
1708  RtlZeroMemory(fss, sizeof(FILESYSTEM_STATISTICS));
1709 
1710  fss->Version = 1;
1713 
1714  *retlen = sizeof(FILESYSTEM_STATISTICS);
1715 
1716  return STATUS_SUCCESS;
1717 }
#define WARN(fmt,...)
Definition: debug.h:111
GLuint buffer
Definition: glext.h:5915
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:64
#define FILESYSTEM_STATISTICS_TYPE_NTFS
Definition: winioctl.h:672
struct _FILESYSTEM_STATISTICS FILESYSTEM_STATISTICS
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
return STATUS_SUCCESS
Definition: btrfs.c:2966
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 4116 of file fsctl.c.

4116  {
4117  LIST_ENTRY* le;
4118  btrfs_set_xattr* bsxa;
4119  ULONG reqlen = (ULONG)offsetof(btrfs_set_xattr, data[0]);
4120  fcb* fcb;
4121  ccb* ccb;
4122 
4123  if (!data || datalen < reqlen)
4124  return STATUS_INVALID_PARAMETER;
4125 
4126  if (!FileObject || !FileObject->FsContext || !FileObject->FsContext2 || FileObject->FsContext == Vcb->volume_fcb)
4127  return STATUS_INVALID_PARAMETER;
4128 
4129  fcb = FileObject->FsContext;
4130  ccb = FileObject->FsContext2;
4131 
4132  if (!(ccb->access & (FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES)) && processor_mode == UserMode) {
4133  WARN("insufficient privileges\n");
4134  return STATUS_ACCESS_DENIED;
4135  }
4136 
4137  ExAcquireResourceSharedLite(fcb->Header.Resource, true);
4138 
4139  le = fcb->xattrs.Flink;
4140  while (le != &fcb->xattrs) {
4142 
4143  if (xa->valuelen > 0)
4144  reqlen += (ULONG)offsetof(btrfs_set_xattr, data[0]) + xa->namelen + xa->valuelen;
4145 
4146  le = le->Flink;
4147  }
4148 
4149  if (datalen < reqlen) {
4150  ExReleaseResourceLite(fcb->Header.Resource);
4151  return STATUS_BUFFER_OVERFLOW;
4152  }
4153 
4154  bsxa = (btrfs_set_xattr*)data;
4155 
4156  if (reqlen > 0) {
4157  le = fcb->xattrs.Flink;
4158  while (le != &fcb->xattrs) {
4160 
4161  if (xa->valuelen > 0) {
4162  bsxa->namelen = xa->namelen;
4163  bsxa->valuelen = xa->valuelen;
4164  memcpy(bsxa->data, xa->data, xa->namelen + xa->valuelen);
4165 
4166  bsxa = (btrfs_set_xattr*)&bsxa->data[xa->namelen + xa->valuelen];
4167  }
4168 
4169  le = le->Flink;
4170  }
4171  }
4172 
4173  bsxa->namelen = 0;
4174  bsxa->valuelen = 0;
4175 
4176  ExReleaseResourceLite(fcb->Header.Resource);
4177 
4178  return STATUS_SUCCESS;
4179 }
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define WARN(fmt,...)
Definition: debug.h:111
ACCESS_MASK access
Definition: btrfs_drv.h:377
int const JOCTET unsigned int datalen
Definition: jpeglib.h:1027
#define FILE_WRITE_ATTRIBUTES
Definition: nt_native.h:649
#define offsetof(TYPE, MEMBER)
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:593
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:272
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
struct _fcb fcb
Definition: btrfs_drv.h:1301
LIST_ENTRY xattrs
Definition: btrfs_drv.h:298
#define Vcb
Definition: cdprocs.h:1425
#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:117
USHORT valuelen
Definition: btrfs_drv.h:266
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:61
Definition: list.h:27
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
USHORT namelen
Definition: btrfs_drv.h:265
unsigned int ULONG
Definition: retypes.h:1
struct _ccb ccb
return STATUS_SUCCESS
Definition: btrfs.c:2966
char data[1]
Definition: btrfs_drv.h:268

Referenced by fsctl_request().

◆ fsctl_request()

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

Definition at line 4838 of file fsctl.c.

4838  {
4839  PIRP Irp = *Pirp;
4841  NTSTATUS Status;
4842 
4843  switch (type) {
4844 #if (NTDDI_VERSION >= NTDDI_WIN7)
4845  case FSCTL_REQUEST_OPLOCK:
4846  WARN("STUB: FSCTL_REQUEST_OPLOCK\n");
4848  break;
4849 #endif
4850 
4852  WARN("STUB: FSCTL_REQUEST_OPLOCK_LEVEL_1\n");
4854  break;
4855 
4857  WARN("STUB: FSCTL_REQUEST_OPLOCK_LEVEL_2\n");
4859  break;
4860 
4862  WARN("STUB: FSCTL_REQUEST_BATCH_OPLOCK\n");
4864  break;
4865 
4867  WARN("STUB: FSCTL_OPLOCK_BREAK_ACKNOWLEDGE\n");
4869  break;
4870 
4872  WARN("STUB: FSCTL_OPLOCK_BREAK_ACK_NO_2\n");
4874  break;
4875 
4877  WARN("STUB: FSCTL_OPBATCH_ACK_CLOSE_PENDING\n");
4879  break;
4880 
4882  WARN("STUB: FSCTL_OPLOCK_BREAK_NOTIFY\n");
4884  break;
4885 
4887  WARN("STUB: FSCTL_REQUEST_FILTER_OPLOCK\n");
4889  break;
4890 
4891  case FSCTL_LOCK_VOLUME:
4893  break;
4894 
4895  case FSCTL_UNLOCK_VOLUME:
4897  break;
4898 
4899  case FSCTL_DISMOUNT_VOLUME:
4901  break;
4902 
4905  break;
4906 
4908  WARN("STUB: FSCTL_IS_PATHNAME_VALID\n");
4910  break;
4911 
4913  WARN("STUB: FSCTL_MARK_VOLUME_DIRTY\n");
4915  break;
4916 
4918  WARN("STUB: FSCTL_QUERY_RETRIEVAL_POINTERS\n");
4920  break;
4921 
4922  case FSCTL_GET_COMPRESSION:
4924  break;
4925 
4926  case FSCTL_SET_COMPRESSION:
4928  break;
4929 
4931  WARN("STUB: FSCTL_SET_BOOTLOADER_ACCESSED\n");
4933  break;
4934 
4937  break;
4938 
4939  case FSCTL_QUERY_FAT_BPB:
4940  WARN("STUB: FSCTL_QUERY_FAT_BPB\n");
4942  break;
4943 
4945  Status = fs_get_statistics(Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.FileSystemControl.OutputBufferLength, &Irp->IoStatus.Information);
4946  break;
4947 
4949  WARN("STUB: FSCTL_GET_NTFS_VOLUME_DATA\n");
4951  break;
4952 
4954  WARN("STUB: FSCTL_GET_NTFS_FILE_RECORD\n");
4956  break;
4957 
4959  WARN("STUB: FSCTL_GET_VOLUME_BITMAP\n");
4961  break;
4962 
4964  WARN("STUB: FSCTL_GET_RETRIEVAL_POINTERS\n");
4966  break;
4967 
4968  case FSCTL_MOVE_FILE:
4969  WARN("STUB: FSCTL_MOVE_FILE\n");
4971  break;
4972 
4973  case FSCTL_IS_VOLUME_DIRTY:
4975  break;
4976 
4979  break;
4980 
4982  WARN("STUB: FSCTL_FIND_FILES_BY_SID\n");
4984  break;
4985 
4986  case FSCTL_SET_OBJECT_ID:
4987  WARN("STUB: FSCTL_SET_OBJECT_ID\n");
4989  break;
4990 
4991  case FSCTL_GET_OBJECT_ID:
4993  IrpSp->Parameters.FileSystemControl.OutputBufferLength, &Irp->IoStatus.Information);
4994  break;
4995 
4997  WARN("STUB: FSCTL_DELETE_OBJECT_ID\n");
4999  break;
5000 
5003  break;
5004 
5006  Status = get_reparse_point(DeviceObject, IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer,
5007  IrpSp->Parameters.FileSystemControl.OutputBufferLength, &Irp->IoStatus.Information);
5008  break;
5009 
5012  break;
5013 
5014  case FSCTL_ENUM_USN_DATA:
5015  WARN("STUB: FSCTL_ENUM_USN_DATA\n");
5017  break;
5018 
5020  WARN("STUB: FSCTL_SECURITY_ID_CHECK\n");
5022  break;
5023 
5025  WARN("STUB: FSCTL_READ_USN_JOURNAL\n");
5027  break;
5028 
5030  WARN("STUB: FSCTL_SET_OBJECT_ID_EXTENDED\n");
5032  break;
5033 
5036  IrpSp->Parameters.FileSystemControl.OutputBufferLength, &Irp->IoStatus.Information);
5037  break;
5038 
5039  case FSCTL_SET_SPARSE:
5040  Status = set_sparse(DeviceObject->DeviceExtension, IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer,
5041  IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp);
5042  break;
5043 
5044  case FSCTL_SET_ZERO_DATA:
5045  Status = set_zero_data(DeviceObject->DeviceExtension, IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer,
5046  IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp);
5047  break;
5048 
5050  Status = query_ranges(IrpSp->FileObject, IrpSp->Parameters.FileSystemControl.Type3InputBuffer,
5051  IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp->UserBuffer,
5052  IrpSp->Parameters.FileSystemControl.OutputBufferLength, &Irp->IoStatus.Information);
5053  break;
5054 
5055  case FSCTL_ENABLE_UPGRADE:
5056  WARN("STUB: FSCTL_ENABLE_UPGRADE\n");
5058  break;
5059 
5060  case FSCTL_SET_ENCRYPTION:
5061  WARN("STUB: FSCTL_SET_ENCRYPTION\n");
5063  break;
5064 
5066  WARN("STUB: FSCTL_ENCRYPTION_FSCTL_IO\n");
5068  break;
5069 
5071  WARN("STUB: FSCTL_WRITE_RAW_ENCRYPTED\n");
5073  break;
5074 
5076  WARN("STUB: FSCTL_READ_RAW_ENCRYPTED\n");
5078  break;
5079 
5081  WARN("STUB: FSCTL_CREATE_USN_JOURNAL\n");
5083  break;
5084 
5086  WARN("STUB: FSCTL_READ_FILE_USN_DATA\n");
5088  break;
5089 
5091  WARN("STUB: FSCTL_WRITE_USN_CLOSE_RECORD\n");
5093  break;
5094 
5095  case FSCTL_EXTEND_VOLUME:
5096  WARN("STUB: FSCTL_EXTEND_VOLUME\n");
5098  break;
5099 
5101  WARN("STUB: FSCTL_QUERY_USN_JOURNAL\n");
5103  break;
5104 
5106  WARN("STUB: FSCTL_DELETE_USN_JOURNAL\n");
5108  break;
5109 
5110  case FSCTL_MARK_HANDLE:
5111  WARN("STUB: FSCTL_MARK_HANDLE\n");
5113  break;
5114 
5115  case FSCTL_SIS_COPYFILE:
5116  WARN("STUB: FSCTL_SIS_COPYFILE\n");
5118  break;
5119 
5120  case FSCTL_SIS_LINK_FILES:
5121  WARN("STUB: FSCTL_SIS_LINK_FILES\n");
5123  break;
5124 
5125  case FSCTL_RECALL_FILE:
5126  WARN("STUB: FSCTL_RECALL_FILE\n");
5128  break;
5129 
5130  case FSCTL_READ_FROM_PLEX:
5131  WARN("STUB: FSCTL_READ_FROM_PLEX\n");
5133  break;
5134 
5135  case FSCTL_FILE_PREFETCH:
5136  WARN("STUB: FSCTL_FILE_PREFETCH\n");
5138  break;
5139 
5140 #if _WIN32_WINNT >= 0x0600
5142  WARN("STUB: FSCTL_MAKE_MEDIA_COMPATIBLE\n");
5143  Status =