ReactOS  0.4.13-dev-92-gf251225
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 addr, root *subvol, UINT64 *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 start, UINT64 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)
 
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 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 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 2699 of file fsctl.c.

2699  {
2701  NTSTATUS Status;
2702  PFILE_OBJECT fileobj, mountmgrfo;
2704  HANDLE h;
2705  LIST_ENTRY* le;
2706  device* dev;
2707  DEV_ITEM* di;
2708  UINT64 dev_id, size;
2709  UINT8* mb;
2710  UINT64* stats;
2711  UNICODE_STRING mmdevpath, pnp_name, pnp_name2;
2712  volume_child* vc;
2713  PDEVICE_OBJECT mountmgr;
2714  KEY searchkey;
2715  traverse_ptr tp;
2718  pdo_device_extension* pdode;
2719  const GUID* pnp_guid;
2721 
2722  pnp_name.Buffer = NULL;
2723 
2724  if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), processor_mode))
2726 
2727  if (!Vcb->vde) {
2728  WARN("not allowing second device to be added to non-PNP device\n");
2729  return STATUS_NOT_SUPPORTED;
2730  }
2731 
2732  if (Vcb->readonly) // FIXME - handle adding R/W device to seeding device
2734 
2735 #if defined(_WIN64)
2736  if (IoIs32bitProcess(Irp)) {
2737  if (IrpSp->Parameters.FileSystemControl.InputBufferLength != sizeof(UINT32))
2738  return STATUS_INVALID_PARAMETER;
2739 
2740  h = (HANDLE)LongToHandle((*(PUINT32)Irp->AssociatedIrp.SystemBuffer));
2741  } else {
2742 #endif
2743  if (IrpSp->Parameters.FileSystemControl.InputBufferLength != sizeof(HANDLE))
2744  return STATUS_INVALID_PARAMETER;
2745 
2746  h = *(PHANDLE)Irp->AssociatedIrp.SystemBuffer;
2747 #if defined(_WIN64)
2748  }
2749 #endif
2750 
2751  Status = ObReferenceObjectByHandle(h, 0, *IoFileObjectType, Irp->RequestorMode, (void**)&fileobj, NULL);
2752 
2753  if (!NT_SUCCESS(Status)) {
2754  ERR("ObReferenceObjectByHandle returned %08x\n", Status);
2755  return Status;
2756  }
2757 
2758  DeviceObject = fileobj->DeviceObject;
2759 
2761  if (!NT_SUCCESS(Status)) {
2762  ERR("get_device_pnp_name returned %08x\n", Status);
2763  ObDereferenceObject(fileobj);
2764  return Status;
2765  }
2766 
2767  // If this is a disk, we have been handed the PDO, so need to go up to find something we can use
2768  if (RtlCompareMemory(pnp_guid, &GUID_DEVINTERFACE_DISK, sizeof(GUID)) == sizeof(GUID) && DeviceObject->AttachedDevice)
2769  DeviceObject = DeviceObject->AttachedDevice;
2770 
2772  if (!NT_SUCCESS(Status)) {
2773  ERR("IOCTL_DISK_IS_WRITABLE returned %08x\n", Status);
2774  ObDereferenceObject(fileobj);
2775  return Status;
2776  }
2777 
2779  if (!NT_SUCCESS(Status)) {
2780  ERR("is_device_part_of_mounted_btrfs_raid returned %08x\n", Status);
2781  ObDereferenceObject(fileobj);
2782  return Status;
2783  }
2784 
2785  // if disk, check it has no partitions
2786  if (RtlCompareMemory(pnp_guid, &GUID_DEVINTERFACE_DISK, sizeof(GUID)) == sizeof(GUID)) {
2787  ULONG dlisize;
2789 
2790  dlisize = 0;
2791 
2792  do {
2793  dlisize += 1024;
2794 
2795  if (dli)
2796  ExFreePool(dli);
2797 
2798  dli = ExAllocatePoolWithTag(PagedPool, dlisize, ALLOC_TAG);
2799  if (!dli) {
2800  ERR("out of memory\n");
2802  goto end2;
2803  }
2804 
2806  } while (Status == STATUS_BUFFER_TOO_SMALL);
2807 
2808  if (NT_SUCCESS(Status) && dli->PartitionCount > 0) {
2809  ExFreePool(dli);
2810  ERR("not adding disk which has partitions\n");
2812  goto end2;
2813  }
2814 
2815  ExFreePool(dli);
2816  }
2817 
2819  &sdn, sizeof(STORAGE_DEVICE_NUMBER), TRUE, NULL);
2820  if (NT_SUCCESS(Status)) {
2821  if (sdn.DeviceType != FILE_DEVICE_DISK) { // FIXME - accept floppies and CDs?
2822  WARN("device was not disk\n");
2823  ObDereferenceObject(fileobj);
2824  return STATUS_INVALID_PARAMETER;
2825  }
2826  } else {
2827  sdn.DeviceNumber = 0xffffffff;
2828  sdn.PartitionNumber = 0xffffffff;
2829  }
2830 
2832  &gli, sizeof(gli), TRUE, NULL);
2833  if (!NT_SUCCESS(Status)) {
2834  ERR("error reading length information: %08x\n", Status);
2835  ObDereferenceObject(fileobj);
2836  return Status;
2837  }
2838 
2839  size = gli.Length.QuadPart;
2840 
2841  if (size < 0x100000) {
2842  ERR("device was not large enough to hold FS (%llx bytes, need at least 1 MB)\n", size);
2843  ObDereferenceObject(fileobj);
2844  return STATUS_INTERNAL_ERROR;
2845  }
2846 
2848 
2849  ExAcquireResourceExclusiveLite(&Vcb->tree_lock, TRUE);
2850 
2851  if (Vcb->need_write)
2852  Status = do_write(Vcb, Irp);
2853  else
2855 
2856  free_trees(Vcb);
2857 
2858  if (!NT_SUCCESS(Status)) {
2859  ERR("do_write returned %08x\n", Status);
2860  goto end;
2861  }
2862 
2864  if (!dev) {
2865  ERR("out of memory\n");
2867  goto end;
2868  }
2869 
2870  RtlZeroMemory(dev, sizeof(device));
2871 
2872  dev->devobj = DeviceObject;
2873  dev->seeding = FALSE;
2874  init_device(Vcb, dev, TRUE);
2875 
2876  InitializeListHead(&dev->space);
2877 
2878  if (size > 0x100000) { // add disk hole - the first MB is marked as used
2879  Status = add_space_entry(&dev->space, NULL, 0x100000, size - 0x100000);
2880  if (!NT_SUCCESS(Status)) {
2881  ERR("add_space_entry returned %08x\n", Status);
2882  goto end;
2883  }
2884  }
2885 
2886  dev_id = 0;
2887 
2888  le = Vcb->devices.Flink;
2889  while (le != &Vcb->devices) {
2890  device* dev2 = CONTAINING_RECORD(le, device, list_entry);
2891 
2892  if (dev2->devitem.dev_id > dev_id)
2893  dev_id = dev2->devitem.dev_id;
2894 
2895  le = le->Flink;
2896  }
2897 
2898  dev_id++;
2899 
2900  dev->devitem.dev_id = dev_id;
2901  dev->devitem.num_bytes = size;
2902  dev->devitem.bytes_used = 0;
2903  dev->devitem.optimal_io_align = Vcb->superblock.sector_size;
2904  dev->devitem.optimal_io_width = Vcb->superblock.sector_size;
2905  dev->devitem.minimal_io_size = Vcb->superblock.sector_size;
2906  dev->devitem.type = 0;
2907  dev->devitem.generation = 0;
2908  dev->devitem.start_offset = 0;
2909  dev->devitem.dev_group = 0;
2910  dev->devitem.seek_speed = 0;
2911  dev->devitem.bandwidth = 0;
2912  get_uuid(&dev->devitem.device_uuid);
2913  dev->devitem.fs_uuid = Vcb->superblock.uuid;
2914 
2916  if (!di) {
2917  ERR("out of memory\n");
2918  goto end;
2919  }
2920 
2921  RtlCopyMemory(di, &dev->devitem, sizeof(DEV_ITEM));
2922 
2923  Status = insert_tree_item(Vcb, Vcb->chunk_root, 1, TYPE_DEV_ITEM, di->dev_id, di, sizeof(DEV_ITEM), NULL, Irp);
2924  if (!NT_SUCCESS(Status)) {
2925  ERR("insert_tree_item returned %08x\n", Status);
2926  ExFreePool(di);
2927  goto end;
2928  }
2929 
2930  // add stats entry to dev tree
2931  stats = ExAllocatePoolWithTag(PagedPool, sizeof(UINT64) * 5, ALLOC_TAG);
2932  if (!stats) {
2933  ERR("out of memory\n");
2935  goto end;
2936  }
2937 
2938  RtlZeroMemory(stats, sizeof(UINT64) * 5);
2939 
2940  searchkey.obj_id = 0;
2941  searchkey.obj_type = TYPE_DEV_STATS;
2942  searchkey.offset = di->dev_id;
2943 
2944  Status = find_item(Vcb, Vcb->dev_root, &tp, &searchkey, FALSE, Irp);
2945  if (!NT_SUCCESS(Status)) {
2946  ERR("error - find_item returned %08x\n", Status);
2947  ExFreePool(stats);
2948  goto end;
2949  }
2950 
2951  if (!keycmp(tp.item->key, searchkey)) {
2953  if (!NT_SUCCESS(Status)) {
2954  ERR("delete_tree_item returned %08x\n", Status);
2955  ExFreePool(stats);
2956  goto end;
2957  }
2958  }
2959 
2960  Status = insert_tree_item(Vcb, Vcb->dev_root, 0, TYPE_DEV_STATS, di->dev_id, stats, sizeof(UINT64) * 5, NULL, Irp);
2961  if (!NT_SUCCESS(Status)) {
2962  ERR("insert_tree_item returned %08x\n", Status);
2963  ExFreePool(stats);
2964  goto end;
2965  }
2966 
2967  if (dev->trim && !dev->readonly && !Vcb->options.no_trim)
2969 
2970  // We clear the first megabyte of the device, so Windows doesn't identify it as another FS
2971  mb = ExAllocatePoolWithTag(PagedPool, 0x100000, ALLOC_TAG);
2972  if (!mb) {
2973  ERR("out of memory\n");
2975  goto end;
2976  }
2977 
2978  RtlZeroMemory(mb, 0x100000);
2979 
2980  Status = write_data_phys(DeviceObject, 0, mb, 0x100000);
2981  if (!NT_SUCCESS(Status)) {
2982  ERR("write_data_phys returned %08x\n", Status);
2983  ExFreePool(mb);
2984  goto end;
2985  }
2986 
2987  ExFreePool(mb);
2988 
2989  vde = Vcb->vde;
2990  pdode = vde->pdode;
2991 
2993  if (!vc) {
2994  ERR("out of memory\n");
2996  goto end;
2997  }
2998 
2999  vc->uuid = dev->devitem.device_uuid;
3000  vc->devid = dev_id;
3001  vc->generation = Vcb->superblock.generation;
3002  vc->devobj = DeviceObject;
3003  vc->fileobj = fileobj;
3004  vc->notification_entry = NULL;
3005 
3007  drvobj, pnp_removal, vde->pdode, &vc->notification_entry);
3008  if (!NT_SUCCESS(Status))
3009  WARN("IoRegisterPlugPlayNotification returned %08x\n", Status);
3010 
3011  pnp_name2 = pnp_name;
3012 
3013  if (pnp_name.Length > 4 * sizeof(WCHAR) && pnp_name.Buffer[0] == '\\' && (pnp_name.Buffer[1] == '\\' || pnp_name.Buffer[1] == '?') &&
3014  pnp_name.Buffer[2] == '?' && pnp_name.Buffer[3] == '\\') {
3015  pnp_name2.Buffer = &pnp_name2.Buffer[3];
3016  pnp_name2.Length -= 3 * sizeof(WCHAR);
3017  pnp_name2.MaximumLength -= 3 * sizeof(WCHAR);
3018  }
3019 
3020  vc->pnp_name.Length = vc->pnp_name.MaximumLength = pnp_name2.Length;
3021 
3022  if (pnp_name2.Length == 0)
3023  vc->pnp_name.Buffer = NULL;
3024  else {
3026  if (!vc->pnp_name.Buffer) {
3027  ERR("out of memory\n");
3029  goto end;
3030  }
3031 
3032  RtlCopyMemory(vc->pnp_name.Buffer, pnp_name2.Buffer, pnp_name2.Length);
3033  }
3034 
3035  vc->size = size;
3036  vc->seeding = FALSE;
3037  vc->disk_num = sdn.DeviceNumber;
3038  vc->part_num = sdn.PartitionNumber;
3039  vc->had_drive_letter = FALSE;
3040 
3042  InsertTailList(&pdode->children, &vc->list_entry);
3043  pdode->num_children++;
3044  pdode->children_loaded++;
3046 
3048  Status = IoGetDeviceObjectPointer(&mmdevpath, FILE_READ_ATTRIBUTES, &mountmgrfo, &mountmgr);
3049  if (!NT_SUCCESS(Status))
3050  ERR("IoGetDeviceObjectPointer returned %08x\n", Status);
3051  else {
3052  Status = remove_drive_letter(mountmgr, &pnp_name);
3054  WARN("remove_drive_letter returned %08x\n", Status);
3055 
3057 
3058  ObDereferenceObject(mountmgrfo);
3059  }
3060 
3061  Vcb->superblock.num_devices++;
3062  Vcb->superblock.total_bytes += size;
3063  Vcb->devices_loaded++;
3064  InsertTailList(&Vcb->devices, &dev->list_entry);
3065 
3066  // FIXME - send notification that volume size has increased
3067 
3068  ObReferenceObject(DeviceObject); // for Vcb
3069 
3070  Status = do_write(Vcb, Irp);
3071  if (!NT_SUCCESS(Status))
3072  ERR("do_write returned %08x\n", Status);
3073 
3074  ObReferenceObject(fileobj);
3075 
3076 end:
3077  free_trees(Vcb);
3078 
3079  ExReleaseResourceLite(&Vcb->tree_lock);
3080 
3081 end2:
3082  ObDereferenceObject(fileobj);
3083 
3084  if (pnp_name.Buffer)
3086 
3087  if (NT_SUCCESS(Status))
3089 
3090  return Status;
3091 }
DEVICE_TYPE DeviceType
Definition: ntddstor.h:232
#define TYPE_DEV_ITEM
Definition: btrfs.h:41
#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:814
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
UINT64 offset
Definition: btrfs.h:125
USHORT MaximumLength
Definition: env_spec_w32.h:370
_In_ PIRP Irp
Definition: csq.h:116
unsigned int * PUINT32
Definition: basetsd.h:127
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define TYPE_DEV_STATS
Definition: btrfs.h:44
void init_device(_In_ device_extension *Vcb, _Inout_ device *dev, _In_ BOOL get_nums)
Definition: btrfs.c:3059
NTSTATUS do_write(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7287
#define keycmp(key1, key2)
Definition: btrfs_drv.h:995
#define WARN(fmt,...)
Definition: debug.h:111
LONG NTSTATUS
Definition: precomp.h:26
UINT64 obj_id
Definition: btrfs.h:123
#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:1434
UINT64 dev_id
Definition: btrfs.h:157
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
NTSTATUS add_space_entry(LIST_ENTRY *list, LIST_ENTRY *list_size, UINT64 offset, UINT64 size)
Definition: free-space.c:189
GLuint GLuint end
Definition: gl.h:1545
_In_ UINT64 _In_ UINT64 _In_ UINT64 _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2645
ULONG part_num
Definition: btrfs_drv.h:820
#define InsertTailList(ListHead, Entry)
static void get_uuid(BTRFS_UUID *uuid)
Definition: fsctl.c:74
UINT64 generation
Definition: btrfs_drv.h:811
#define MOUNTMGR_DEVICE_NAME
Definition: imports.h:76
static int dev
Definition: mkdosfs.c:536
UINT8 obj_type
Definition: btrfs.h:124
#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:809
BOOL had_drive_letter
Definition: btrfs_drv.h:817
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:86
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_ BOOLEAN Override, _Out_opt_ IO_STATUS_BLOCK *iosb)
Definition: btrfs.c:2603
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
unsigned int UINT32
PDRIVER_OBJECT drvobj
Definition: btrfs.c:60
Definition: devices.h:37
smooth NULL
Definition: ftsmooth.c:416
PDEVICE_OBJECT devobj
Definition: btrfs_drv.h:812
#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:832
void free_trees(device_extension *Vcb)
Definition: treefuncs.c:777
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
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
NTSTATUS get_device_pnp_name(_In_ PDEVICE_OBJECT DeviceObject, _Out_ PUNICODE_STRING pnp_name, _Out_ const GUID **guid)
Definition: btrfs.c:3848
GLsizeiptr size
Definition: glext.h:5919
NTSTATUS NTAPI FsRtlNotifyVolumeEvent(IN PFILE_OBJECT FileObject, IN ULONG EventCode)
Definition: pnp.c:38
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
PVOID HANDLE
Definition: typedefs.h:71
ERESOURCE child_lock
Definition: btrfs_drv.h:848
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
void * notification_entry
Definition: btrfs_drv.h:818
* PFILE_OBJECT
Definition: iotypes.h:1954
ULONG disk_num
Definition: btrfs_drv.h:819
#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:468
PFILE_OBJECT fileobj
Definition: btrfs_drv.h:813
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:414
#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:250
static NTSTATUS is_device_part_of_mounted_btrfs_raid(PDEVICE_OBJECT devobj)
Definition: fsctl.c:2598
Definition: typedefs.h:117
BOOL seeding
Definition: btrfs_drv.h:816
NTSTATUS insert_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_ UINT64 obj_id, _In_ UINT8 obj_type, _In_ UINT64 offset, _In_reads_bytes_opt_(size) _When_(return >=0, __drv_aliasesMem) void *data, _In_ UINT16 size, _Out_opt_ traverse_ptr *ptp, _In_opt_ PIRP Irp)
Definition: treefuncs.c:838
POBJECT_TYPE IoFileObjectType
Definition: iomgr.c:36
LARGE_INTEGER Length
Definition: winioctl.h:423
Status
Definition: gdiplustypes.h:24
UINT64 devid
Definition: btrfs_drv.h:810
#define ERR(fmt,...)
Definition: debug.h:109
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
Definition: btrfs.h:122
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
#define SE_MANAGE_VOLUME_PRIVILEGE
Definition: security.c:682
#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:485
uint64_t dev_id
UNICODE_STRING pnp_name
Definition: btrfs.c:3878
void trim_whole_device(device *dev)
Definition: fsctl.c:2680
NTSTATUS write_data_phys(_In_ PDEVICE_OBJECT device, _In_ UINT64 address, _In_reads_bytes_(length) void *data, _In_ UINT32 length)
Definition: flushthread.c:67
#define ObReferenceObject
Definition: obfuncs.h:204
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:409
LIST_ENTRY list_entry
Definition: btrfs_drv.h:821
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
unsigned long long UINT64
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2771
LIST_ENTRY children
Definition: btrfs_drv.h:849
return STATUS_SUCCESS
Definition: btrfs.c:2725
unsigned char UINT8
UINT64 size
Definition: btrfs_drv.h:815
#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:972
void volume_removal(PDRIVER_OBJECT DriverObject, PUNICODE_STRING devpath)
Definition: search.c:601
#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 3093 of file fsctl.c.

3093  {
3094  fcb* fcb;
3095  ccb* ccb;
3096 
3097  TRACE("FSCTL_ALLOW_EXTENDED_DASD_IO\n");
3098 
3099  if (!FileObject)
3100  return STATUS_INVALID_PARAMETER;
3101 
3102  fcb = FileObject->FsContext;
3103  ccb = FileObject->FsContext2;
3104 
3105  if (!fcb)
3106  return STATUS_INVALID_PARAMETER;
3107 
3108  if (fcb != Vcb->volume_fcb)
3109  return STATUS_INVALID_PARAMETER;
3110 
3111  if (!ccb)
3112  return STATUS_INVALID_PARAMETER;
3113 
3115 
3116  return STATUS_SUCCESS;
3117 }
#define TRUE
Definition: types.h:120
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
BOOL allow_extended_dasd_io
Definition: btrfs_drv.h:355
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:593
#define TRACE(s)
Definition: solgame.cpp:4
struct _fcb fcb
Definition: btrfs_drv.h:1321
#define Vcb
Definition: cdprocs.h:1425
struct _ccb ccb
return STATUS_SUCCESS
Definition: btrfs.c:2725

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 = RtlUnicodeToUTF8N(NULL, 0, &len, nameus.Buffer, nameus.Length);
607  if (!NT_SUCCESS(Status)) {
608  ERR("RtlUnicodeToUTF8N failed with error %08x\n", Status);
609  return Status;
610  }
611 
612  if (len == 0) {
613  ERR("RtlUnicodeToUTF8N 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 = RtlUnicodeToUTF8N(utf8.Buffer, len, &len, nameus.Buffer, nameus.Length);
631  if (!NT_SUCCESS(Status)) {
632  ERR("RtlUnicodeToUTF8N failed with error %08x\n", Status);
633  goto end2;
634  }
635 
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(Vcb, fr2);
646  goto end3;
647  } else
648  free_fileref(Vcb, 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 %llx, expected %llx\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(Vcb, 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 free_fileref(_Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension *Vcb, _Inout_ file_ref *fr)
Definition: btrfs.c:1610
#define TRUE
Definition: types.h:120
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
BOOL case_sensitive
Definition: btrfs_drv.h:361
USHORT MaximumLength
Definition: env_spec_w32.h:370
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
UINT64 inode
Definition: btrfs_drv.h:262
#define WARN(fmt,...)
Definition: debug.h:111
LONG NTSTATUS
Definition: precomp.h:26
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
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
GLuint GLuint end
Definition: gl.h:1545
ACCESS_MASK access
Definition: btrfs_drv.h:357
#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:1343
_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:86
#define FILE_TRAVERSE
Definition: nt_native.h:643
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:496
unsigned int BOOL
Definition: ntddk_ex.h:94
#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
_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
USHORT MaximumLength
Definition: env_spec_w32.h:377
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
struct _fcb fcb
Definition: btrfs_drv.h:1321
static __inline BOOL is_subvol_readonly(root *r, PIRP Irp)
Definition: btrfs_drv.h:1012
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
#define Vcb
Definition: cdprocs.h:1425
struct _file_ref * fileref
Definition: btrfs_drv.h:278
LIST_ENTRY extents
Definition: btrfs_drv.h:273
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
* PFILE_OBJECT
Definition: iotypes.h:1954
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 is_file_name_valid(_In_ PUNICODE_STRING us, _In_ BOOL posix)
Definition: btrfs.c:5101
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:1397
#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
Status
Definition: gdiplustypes.h:24
void *POINTER_32 subvol
Definition: btrfsioctl.h:56
#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:261
Definition: list.h:27
#define FILE_ACTION_ADDED
Definition: name.c:36
UINT8 type
Definition: btrfs_drv.h:263
unsigned int ULONG
Definition: retypes.h:1
BOOL deleted
Definition: btrfs_drv.h:320
struct _ccb ccb
file_ref * fileref
Definition: btrfs_drv.h:358
return STATUS_SUCCESS
Definition: btrfs.c:2725
struct _device_extension * Vcb
Definition: btrfs_drv.h:260
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
NTSTATUS NTAPI RtlUnicodeToUTF8N(PCHAR UTF8StringDestination, ULONG UTF8StringMaxByteCount, PULONG UTF8StringActualByteCount, PCWCH UnicodeStringSource, ULONG UnicodeStringByteCount)

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 id;
752  root* r = NULL;
754  BTRFS_TIME now;
755  ULONG len;
756  UINT16 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* 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 = RtlUnicodeToUTF8N(NULL, 0, &len, nameus.Buffer, nameus.Length);
829  if (!NT_SUCCESS(Status)) {
830  ERR("RtlUnicodeToUTF8N failed with error %08x\n", Status);
831  return Status;
832  }
833 
834  if (len == 0) {
835  ERR("RtlUnicodeToUTF8N 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 = RtlUnicodeToUTF8N(utf8.Buffer, len, &len, nameus.Buffer, nameus.Length);
853  if (!NT_SUCCESS(Status)) {
854  ERR("RtlUnicodeToUTF8N failed with error %08x\n", Status);
855  goto end2;
856  }
857 
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(Vcb, fr2);
871  goto end;
872  } else
873  free_fileref(Vcb, 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 %llx\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), 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));
917  searchkey.obj_type = TYPE_SUBVOL_UUID;
918  RtlCopyMemory(&searchkey.offset, &r->root_item.uuid.uuid[sizeof(UINT64)], sizeof(UINT64));
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), 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  release_fcb_lock(Vcb);
1009 
1010  rootfcb->Header.IsFastIoPossible = fast_io_possible(rootfcb);
1011  rootfcb->Header.AllocationSize.QuadPart = 0;
1012  rootfcb->Header.FileSize.QuadPart = 0;
1013  rootfcb->Header.ValidDataLength.QuadPart = 0;
1014 
1015  rootfcb->created = TRUE;
1016 
1017  if (fileref->fcb->inode_item.flags & BTRFS_INODE_COMPRESS)
1019 
1020  rootfcb->prop_compression = fileref->fcb->prop_compression;
1022 
1023  r->lastinode = rootfcb->inode;
1024 
1025  // add INODE_REF
1026 
1027  irsize = (UINT16)(offsetof(INODE_REF, name[0]) + sizeof(DOTDOT) - 1);
1028  ir = ExAllocatePoolWithTag(PagedPool, irsize, ALLOC_TAG);
1029  if (!ir) {
1030  ERR("out of memory\n");
1032  goto end;
1033  }
1034 
1035  ir->index = 0;
1036  ir->n = sizeof(DOTDOT) - 1;
1037  RtlCopyMemory(ir->name, DOTDOT, ir->n);
1038 
1039  Status = insert_tree_item(Vcb, r, r->root_item.objid, TYPE_INODE_REF, r->root_item.objid, ir, irsize, NULL, Irp);
1040  if (!NT_SUCCESS(Status)) {
1041  ERR("insert_tree_item returned %08x\n", Status);
1042  ExFreePool(ir);
1043  goto end;
1044  }
1045 
1046  // create fileref for entry in other subvolume
1047 
1048  fr = create_fileref(Vcb);
1049  if (!fr) {
1050  ERR("out of memory\n");
1051 
1052  acquire_fcb_lock_exclusive(Vcb);
1053  free_fcb(Vcb, rootfcb);
1054  release_fcb_lock(Vcb);
1055 
1057  goto end;
1058  }
1059 
1060  fr->fcb = rootfcb;
1061 
1062  mark_fcb_dirty(rootfcb);
1063 
1064  fr->parent = fileref;
1065 
1066  Status = add_dir_child(fileref->fcb, r->id, TRUE, &utf8, &nameus, BTRFS_TYPE_DIRECTORY, &dc);
1067  if (!NT_SUCCESS(Status))
1068  WARN("add_dir_child returned %08x\n", Status);
1069 
1070  fr->dc = dc;
1071  dc->fileref = fr;
1072 
1074  if (!fr->fcb->hash_ptrs) {
1075  ERR("out of memory\n");
1076  acquire_fcb_lock_exclusive(Vcb);
1077  free_fileref(Vcb, fr);
1078  release_fcb_lock(Vcb);
1080  goto end;
1081  }
1082 
1083  RtlZeroMemory(fr->fcb->hash_ptrs, sizeof(LIST_ENTRY*) * 256);
1084 
1086  if (!fr->fcb->hash_ptrs_uc) {
1087  ERR("out of memory\n");
1088  acquire_fcb_lock_exclusive(Vcb);
1089  free_fileref(Vcb, fr);
1090  release_fcb_lock(Vcb);
1092  goto end;
1093  }
1094 
1095  RtlZeroMemory(fr->fcb->hash_ptrs_uc, sizeof(LIST_ENTRY*) * 256);
1096 
1097  ExAcquireResourceExclusiveLite(&fileref->nonpaged->children_lock, TRUE);
1098  InsertTailList(&fileref->children, &fr->list_entry);
1099  ExReleaseResourceLite(&fileref->nonpaged->children_lock);
1100 
1102 
1103  if (fr->fcb->type == BTRFS_TYPE_DIRECTORY)
1104  fr->fcb->fileref = fr;
1105 
1106  fr->created = TRUE;
1107  mark_fileref_dirty(fr);
1108 
1109  // change fcb->subvol's ROOT_ITEM
1110 
1111  fcb->subvol->root_item.ctransid = Vcb->superblock.generation;
1112  fcb->subvol->root_item.ctime = now;
1113 
1114  // change fcb's INODE_ITEM
1115 
1116  fcb->inode_item.transid = Vcb->superblock.generation;
1117  fcb->inode_item.st_size += utf8.Length * 2;
1118  fcb->inode_item.sequence++;
1119 
1120  if (!ccb->user_set_change_time)
1122 
1123  if (!ccb->user_set_write_time)
1125 
1128 
1129  fr->fcb->subvol->parent = fcb->subvol->id;
1130 
1132 
1133 end:
1134  if (!NT_SUCCESS(Status)) {
1135  if (fr) {
1136  fr->deleted = TRUE;
1137  mark_fileref_dirty(fr);
1138  } else if (rootfcb) {
1139  rootfcb->deleted = TRUE;
1140  mark_fcb_dirty(rootfcb);
1141  }
1142 
1143  if (r) {
1144  RemoveEntryList(&r->list_entry);
1145  InsertTailList(&Vcb->drop_roots, &r->list_entry);
1146  }
1147  }
1148 
1149  ExReleaseResourceLite(&Vcb->tree_lock);
1150 
1151  if (NT_SUCCESS(Status)) {
1154  }
1155 
1156 end2:
1157  if (fr) {
1158  acquire_fcb_lock_exclusive(Vcb);
1159  free_fileref(Vcb, fr);
1160  release_fcb_lock(Vcb);
1161  }
1162 
1163  return Status;
1164 }
#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:326
VOID NTAPI SeCaptureSubjectContext(OUT PSECURITY_SUBJECT_CONTEXT SubjectContext)
Definition: access.c:301
void free_fileref(_Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension *Vcb, _Inout_ file_ref *fr)
Definition: btrfs.c:1610
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
BOOL sd_dirty
Definition: btrfs_drv.h:290
UINT64 offset
Definition: btrfs.h:125
BOOL case_sensitive
Definition: btrfs_drv.h:361
BTRFS_TIME otime
Definition: btrfs.h:281
USHORT MaximumLength
Definition: env_spec_w32.h:370
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
UINT32 st_gid
Definition: btrfs.h:272
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
#define SUBVOL_ROOT_INODE
Definition: propsheet.cpp:42
UINT64 inode
Definition: btrfs_drv.h:262
fcb * create_fcb(device_extension *Vcb, POOL_TYPE pool_type)
Definition: create.c:45
UINT32 st_uid
Definition: btrfs.h:271
#define keycmp(key1, key2)
Definition: btrfs_drv.h:995
#define WARN(fmt,...)
Definition: debug.h:111
LONG NTSTATUS
Definition: precomp.h:26
enum prop_compression_type prop_compression
Definition: btrfs_drv.h:280
UINT64 obj_id
Definition: btrfs.h:123
HDC dc
Definition: cylfrac.c:34
#define FILE_NOTIFY_CHANGE_LAST_WRITE
void free_fcb(_Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension *Vcb, _Inout_ fcb *fcb)
Definition: btrfs.c:1502
GLuint GLuint end
Definition: gl.h:1545
_In_ UINT64 _In_ UINT64 _In_ UINT64 _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2645
__u16 time
Definition: mkdosfs.c:366
ACCESS_MASK access
Definition: btrfs_drv.h:357
#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:1343
static void get_uuid(BTRFS_UUID *uuid)
Definition: fsctl.c:74
BTRFS_TIME st_ctime
Definition: btrfs.h:279
UINT32 st_mode
Definition: btrfs.h:273
UINT8 obj_type
Definition: btrfs.h:124
UINT64 generation
Definition: btrfs.h:265
LIST_ENTRY list_entry_all
Definition: btrfs_drv.h:306
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
#define ALLOC_TAG
Definition: btrfs_drv.h:86
SECURITY_DESCRIPTOR * sd
Definition: btrfs_drv.h:265
void mark_fileref_dirty(_In_ file_ref *fileref)
Definition: btrfs.c:1486
#define STATUS_NOT_A_DIRECTORY
Definition: udferr_usr.h:169
file_ref * create_fileref(device_extension *Vcb)
Definition: create.c:113
tree * tree
Definition: btrfs_drv.h:467
#define BTRFS_INODE_COMPRESS
Definition: propsheet.h:87
LIST_ENTRY list_entry
Definition: btrfs_drv.h:305
#define S_IRGRP
Definition: propsheet.h:41
#define S_IXOTH
Definition: propsheet.h:61
time_t now
Definition: finger.c:65
#define FILE_ACTION_MODIFIED
char name[1]
Definition: btrfs.h:350
BOOL prop_compression_changed
Definition: btrfs_drv.h:295
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:81
unsigned char BOOLEAN
UINT64 index
Definition: btrfs.h:348
LIST_ENTRY ** hash_ptrs_uc
Definition: btrfs_drv.h:287
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
void mark_fcb_dirty(_In_ fcb *fcb)
Definition: btrfs.c:1464
#define TYPE_INODE_REF
Definition: btrfs.h:19
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:593
BTRFS_TIME st_mtime
Definition: btrfs.h:280
#define increase_fileref_refcount(fileref)
Definition: btrfs_drv.h:1677
#define STATUS_FILE_DELETED
Definition: udferr_usr.h:172
void find_gid(struct _fcb *fcb, struct _fcb *parfcb, PSECURITY_SUBJECT_CONTEXT subjcont)
Definition: security.c:841
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:256
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
USHORT MaximumLength
Definition: env_spec_w32.h:377
#define S_IXGRP
Definition: propsheet.h:49
#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:1321
static __inline BOOL is_subvol_readonly(root *r, PIRP Irp)
Definition: btrfs_drv.h:1012
BOOL created
Definition: btrfs_drv.h:321
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define TYPE_SUBVOL_UUID
Definition: btrfs.h:45
#define Vcb
Definition: cdprocs.h:1425
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
struct _file_ref * fileref
Definition: btrfs_drv.h:278
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
BOOL deleted
Definition: btrfs_drv.h:267
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 ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
BOOL inode_item_changed
Definition: btrfs_drv.h:279
BTRFS_TIME st_atime
Definition: btrfs.h:278
dir_child * dc
Definition: btrfs_drv.h:328
tree_data * item
Definition: btrfs_drv.h:468
#define S_IXUSR
Definition: propsheet.h:37
BOOL is_file_name_valid(_In_ PUNICODE_STRING us, _In_ BOOL posix)
Definition: btrfs.c:5101
#define S_IROTH
Definition: propsheet.h:53
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:1397
#define FILE_ADD_SUBDIRECTORY
Definition: nt_native.h:635
GLenum GLsizei len
Definition: glext.h:6722
fcb * fcb
Definition: btrfs_drv.h:316
Definition: typedefs.h:117
INODE_ITEM inode_item
Definition: btrfs_drv.h:264
NTSTATUS insert_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_ UINT64 obj_id, _In_ UINT8 obj_type, _In_ UINT64 offset, _In_reads_bytes_opt_(size) _When_(return >=0, __drv_aliasesMem) void *data, _In_ UINT16 size, _Out_opt_ traverse_ptr *ptp, _In_opt_ PIRP Irp)
Definition: treefuncs.c:838
NTSTATUS create_root(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ UINT64 id, _Out_ root **rootptr, _In_ BOOL no_tree, _In_ UINT64 offset, _In_opt_ PIRP Irp)
Definition: btrfs.c:1009
BOOL user_set_write_time
Definition: btrfs_drv.h:364
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
Definition: btrfs.h:122
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
ULONG atts
Definition: btrfs_drv.h:269
UINT64 st_size
Definition: btrfs.h:267
unsigned short USHORT
Definition: pedump.c:61
#define BTRFS_ROOT_UUID
Definition: btrfs.h:54
UINT64 transid
Definition: btrfs.h:266
#define STATUS_OBJECT_NAME_INVALID
Definition: udferr_usr.h:148
#define S_IRUSR
Definition: propsheet.h:29
unsigned short UINT16
struct _root * subvol
Definition: btrfs_drv.h:261
UINT64 flags
Definition: btrfs.h:275
BOOL created
Definition: btrfs_drv.h:297
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:1692
Definition: name.c:36
UINT8 type
Definition: btrfs_drv.h:263
static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME *out)
Definition: btrfs_drv.h:968
UINT32 st_nlink
Definition: btrfs.h:270
unsigned int ULONG
Definition: retypes.h:1
GLenum GLuint id
Definition: glext.h:5579
UINT16 n
Definition: btrfs.h:349
LIST_ENTRY ** hash_ptrs
Definition: btrfs_drv.h:286
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define fast_io_possible(fcb)
Definition: btrfs_drv.h:1605
UINT32 sid_to_uid(PSID sid)
Definition: security.c:310
ULONG get_file_attributes(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_ UINT64 inode, _In_ UINT8 type, _In_ BOOL dotfile, _In_ BOOL ignore_xa, _In_opt_ PIRP Irp)
Definition: btrfs.c:2366
BOOL deleted
Definition: btrfs_drv.h:320
struct _ccb ccb
file_ref * fileref
Definition: btrfs_drv.h:358
unsigned long long UINT64
UINT32 inherit_mode(fcb *parfcb, BOOL is_dir)
Definition: create.c:1656
return STATUS_SUCCESS
Definition: btrfs.c:2725
#define BTRFS_SUBVOL_READONLY
Definition: btrfs.h:98
NTSTATUS add_dir_child(fcb *fcb, UINT64 inode, BOOL subvol, PANSI_STRING utf8, PUNICODE_STRING name, UINT8 type, dir_child **pdc)
Definition: create.c:1586
BOOL user_set_change_time
Definition: btrfs_drv.h:365
#define GID_NOBODY
Definition: btrfs_drv.h:90
struct _device_extension * Vcb
Definition: btrfs_drv.h:260
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define UID_NOBODY
Definition: btrfs_drv.h:89
UINT64 sequence
Definition: btrfs.h:276
LIST_ENTRY list_entry
Definition: btrfs_drv.h:332
NTSTATUS NTAPI RtlUnicodeToUTF8N(PCHAR UTF8StringDestination, ULONG UTF8StringMaxByteCount, PULONG UTF8StringActualByteCount, PCWCH UnicodeStringSource, ULONG UnicodeStringByteCount)

Referenced by fsctl_request().

◆ dismount_volume()

static NTSTATUS dismount_volume ( device_extension Vcb,
PIRP  Irp 
)
static

Definition at line 2553 of file fsctl.c.

2553  {
2554  NTSTATUS Status;
2555 
2556  TRACE("FSCTL_DISMOUNT_VOLUME\n");
2557 
2558  if (!(Vcb->Vpb->Flags & VPB_MOUNTED))
2559  return STATUS_SUCCESS;
2560 
2561  if (Vcb->disallow_dismount) {
2562  WARN("attempting to dismount boot volume or one containing a pagefile\n");
2563  return STATUS_ACCESS_DENIED;
2564  }
2565 
2567  if (!NT_SUCCESS(Status)) {
2568  WARN("FsRtlNotifyVolumeEvent returned %08x\n", Status);
2569  }
2570 
2571  ExAcquireResourceExclusiveLite(&Vcb->tree_lock, TRUE);
2572 
2573  if (!Vcb->locked) {
2575 
2576  if (Vcb->need_write && !Vcb->readonly) {
2577  Status = do_write(Vcb, Irp);
2578 
2579  if (!NT_SUCCESS(Status))
2580  ERR("do_write returned %08x\n", Status);
2581  }
2582  }
2583 
2584  free_trees(Vcb);
2585 
2586  Vcb->removing = TRUE;
2587 
2588  if (Vcb->vde) {
2590  Vcb->vde->mounted_device = NULL;
2591  }
2592 
2593  ExReleaseResourceLite(&Vcb->tree_lock);
2594 
2595  return STATUS_SUCCESS;
2596 }
#define FSRTL_VOLUME_DISMOUNT
Definition: ntifs_ex.h:439
#define TRUE
Definition: types.h:120
_In_ PIRP Irp
Definition: csq.h:116
NTSTATUS do_write(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7287
#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:777
#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:2196
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
return STATUS_SUCCESS
Definition: btrfs.c:2725
static void update_volumes(device_extension *Vcb)
Definition: fsctl.c:2530
#define VPB_MOUNTED
Definition: iotypes.h:1763

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 id;
265  root *r, *subvol = subvol_fcb->subvol;
266  KEY searchkey;
268  UINT64 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), 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));
352  searchkey.obj_type = TYPE_SUBVOL_UUID;
353  RtlCopyMemory(&searchkey.offset, &r->root_item.uuid.uuid[sizeof(UINT64)], sizeof(UINT64));
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), 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 %llx\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, fcb, &fr->fcb, PagedPool, Irp);
436  if (!NT_SUCCESS(Status)) {
437  ERR("open_fcb returned %08x\n", Status);
438  free_fileref(Vcb, 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->nonpaged->children_lock, TRUE);
452  InsertTailList(&fileref->children, &fr->list_entry);
453  ExReleaseResourceLite(&fileref->nonpaged->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(Vcb, 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 
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:326
void do_rollback(device_extension *Vcb, LIST_ENTRY *rollback)
Definition: treefuncs.c:1032
void clear_rollback(LIST_ENTRY *rollback)
Definition: treefuncs.c:1011
void free_fileref(_Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension *Vcb, _Inout_ file_ref *fr)
Definition: btrfs.c:1610
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
UINT64 offset
Definition: btrfs.h:125
_In_ PIRP Irp
Definition: csq.h:116
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
NTSTATUS do_write(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7287
#define keycmp(key1, key2)
Definition: btrfs_drv.h:995
#define WARN(fmt,...)
Definition: debug.h:111
LONG NTSTATUS
Definition: precomp.h:26
UINT64 obj_id
Definition: btrfs.h:123
HDC dc
Definition: cylfrac.c:34
#define FILE_NOTIFY_CHANGE_LAST_WRITE
GLuint GLuint end
Definition: gl.h:1545
_In_ UINT64 _In_ UINT64 _In_ UINT64 _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2645
__u16 time
Definition: mkdosfs.c:366
ACCESS_MASK access
Definition: btrfs_drv.h:357
#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:1343
static void get_uuid(BTRFS_UUID *uuid)
Definition: fsctl.c:74
BTRFS_TIME st_ctime
Definition: btrfs.h:279
UINT8 obj_type
Definition: btrfs.h:124
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:86
void mark_fileref_dirty(_In_ file_ref *fileref)
Definition: btrfs.c:1486
file_ref * create_fileref(device_extension *Vcb)
Definition: create.c:113
tree * tree
Definition: btrfs_drv.h:467
#define S_IRGRP
Definition: propsheet.h:41
#define S_IXOTH
Definition: propsheet.h:61
time_t now
Definition: finger.c:65
NTSTATUS open_fcb(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension *Vcb, root *subvol, UINT64 inode, UINT8 type, PANSI_STRING utf8, fcb *parent, fcb **pfcb, POOL_TYPE pooltype, PIRP Irp)
Definition: create.c:571
#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:1464
static NTSTATUS snapshot_tree_copy(device_extension *Vcb, UINT64 addr, root *subvol, UINT64 *newaddr, PIRP Irp, LIST_ENTRY *rollback)
Definition: fsctl.c:88
void free_trees(device_extension *Vcb)
Definition: treefuncs.c:777
void flush_subvol_fcbs(root *subvol)
Definition: fsctl.c:244
BTRFS_TIME st_mtime
Definition: btrfs.h:280
#define increase_fileref_refcount(fileref)
Definition: btrfs_drv.h:1677
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
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
#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:2659
BOOL created
Definition: btrfs_drv.h:321
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define TYPE_SUBVOL_UUID
Definition: btrfs.h:45
#define Vcb
Definition: cdprocs.h:1425
GLuint address
Definition: glext.h:9393
struct _file_ref * fileref
Definition: btrfs_drv.h:278
LIST_ENTRY extents
Definition: btrfs_drv.h:273
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
BOOL inode_item_changed
Definition: btrfs_drv.h:279
dir_child * dc
Definition: btrfs_drv.h:328
tree_data * item
Definition: btrfs_drv.h:468
#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:316
Definition: typedefs.h:117
INODE_ITEM inode_item
Definition: btrfs_drv.h:264
NTSTATUS insert_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_ UINT64 obj_id, _In_ UINT8 obj_type, _In_ UINT64 offset, _In_reads_bytes_opt_(size) _When_(return >=0, __drv_aliasesMem) void *data, _In_ UINT16 size, _Out_opt_ traverse_ptr *ptp, _In_opt_ PIRP Irp)
Definition: treefuncs.c:838
_In_ fcb _In_ chunk _In_ UINT64 _In_ UINT64 _In_ BOOL _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: btrfs_drv.h:1321
NTSTATUS create_root(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ UINT64 id, _Out_ root **rootptr, _In_ BOOL no_tree, _In_ UINT64 offset, _In_opt_ PIRP Irp)
Definition: btrfs.c:1009
BOOL user_set_write_time
Definition: btrfs_drv.h:364
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
Definition: btrfs.h:122
UINT64 st_size
Definition: btrfs.h:267
#define BTRFS_ROOT_UUID
Definition: btrfs.h:54
UINT64 transid
Definition: btrfs.h:266
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define TYPE_ROOT_ITEM
Definition: btrfs.h:26
#define S_IRUSR
Definition: propsheet.h:29
static void mark_subvol_dirty(device_extension *Vcb, root *r)
Definition: fsctl.c:4018
struct _root * subvol
Definition: btrfs_drv.h:261
Definition: list.h:27
#define FILE_ACTION_ADDED
#define __S_IFDIR
Definition: btrfs_drv.h:1692
Definition: name.c:36
UINT8 type
Definition: btrfs_drv.h:263
static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME *out)
Definition: btrfs_drv.h:968
GLenum GLuint id
Definition: glext.h:5579
file_ref * fileref
Definition: btrfs_drv.h:358
unsigned long long UINT64
return STATUS_SUCCESS
Definition: btrfs.c:2725
#define BTRFS_SUBVOL_READONLY
Definition: btrfs.h:98
NTSTATUS add_dir_child(fcb *fcb, UINT64 inode, BOOL subvol, PANSI_STRING utf8, PUNICODE_STRING name, UINT8 type, dir_child **pdc)
Definition: create.c:1586
BOOL user_set_change_time
Definition: btrfs_drv.h:365
UINT8 * data
Definition: btrfs_drv.h:390
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
UINT64 sequence
Definition: btrfs.h:276
LIST_ENTRY list_entry
Definition: btrfs_drv.h:332

Referenced by create_snapshot().

◆ do_unlock_volume()

void do_unlock_volume ( device_extension Vcb)

Definition at line 2300 of file fsctl.c.

2300  {
2301  KIRQL irql;
2302 
2304 
2305  Vcb->locked = FALSE;
2306  Vcb->Vpb->Flags &= ~VPB_LOCKED;
2307  Vcb->locked_fileobj = NULL;
2308 
2310 
2311  if (Vcb->lock_paused_balance)
2312  KeSetEvent(&Vcb->balance.event, 0, FALSE);
2313 }
VOID NTAPI IoAcquireVpbSpinLock(OUT PKIRQL Irql)
Definition: volume.c:1201
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:1764
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:1212

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

3224  {
3226  fcb *fcb = FileObject ? FileObject->FsContext : NULL, *sourcefcb;
3227  ccb *ccb = FileObject ? FileObject->FsContext2 : NULL, *sourceccb;
3228  NTSTATUS Status;
3229  PFILE_OBJECT sourcefo;
3230  UINT64 sourcelen, nbytes = 0;
3231  LIST_ENTRY rollback, *le, newexts;
3233  BTRFS_TIME now;
3234  BOOL make_inline;
3235 
3236  if (!ded || datalen < sizeof(DUPLICATE_EXTENTS_DATA))
3237  return STATUS_BUFFER_TOO_SMALL;
3238 
3239  if (Vcb->readonly)
3241 
3242  if (ded->ByteCount.QuadPart == 0)
3243  return STATUS_SUCCESS;
3244 
3245  if (!fcb || !ccb || fcb == Vcb->volume_fcb)
3246  return STATUS_INVALID_PARAMETER;
3247 
3249  return STATUS_ACCESS_DENIED;
3250 
3251  if (Irp->RequestorMode == UserMode && !(ccb->access & FILE_WRITE_DATA)) {
3252  WARN("insufficient privileges\n");
3253  return STATUS_ACCESS_DENIED;
3254  }
3255 
3256  if (!fcb->ads && fcb->type != BTRFS_TYPE_FILE && fcb->type != BTRFS_TYPE_SYMLINK)
3257  return STATUS_INVALID_PARAMETER;
3258 
3259  Status = ObReferenceObjectByHandle(ded->FileHandle, 0, *IoFileObjectType, Irp->RequestorMode, (void**)&sourcefo, NULL);
3260  if (!NT_SUCCESS(Status)) {
3261  ERR("ObReferenceObjectByHandle returned %08x\n", Status);
3262  return Status;
3263  }
3264 
3265  if (sourcefo->DeviceObject != FileObject->DeviceObject) {
3266  WARN("source and destination are on different volumes\n");
3267  ObDereferenceObject(sourcefo);
3268  return STATUS_INVALID_PARAMETER;
3269  }
3270 
3271  sourcefcb = sourcefo->FsContext;
3272  sourceccb = sourcefo->FsContext2;
3273 
3274  if (!sourcefcb || !sourceccb || sourcefcb == Vcb->volume_fcb) {
3275  ObDereferenceObject(sourcefo);
3276  return STATUS_INVALID_PARAMETER;
3277  }
3278 
3279  if (!sourcefcb->ads && !fcb->ads) {
3280  if ((ded->SourceFileOffset.QuadPart & (Vcb->superblock.sector_size - 1)) || (ded->TargetFileOffset.QuadPart & (Vcb->superblock.sector_size - 1))) {
3281  ObDereferenceObject(sourcefo);
3282  return STATUS_INVALID_PARAMETER;
3283  }
3284 
3285  if (ded->ByteCount.QuadPart & (Vcb->superblock.sector_size - 1)) {
3286  ObDereferenceObject(sourcefo);
3287  return STATUS_INVALID_PARAMETER;
3288  }
3289  }
3290 
3291  if (Irp->RequestorMode == UserMode && (!(sourceccb->access & FILE_READ_DATA) || !(sourceccb->access & FILE_READ_ATTRIBUTES))) {
3292  WARN("insufficient privileges\n");
3293  ObDereferenceObject(sourcefo);
3294  return STATUS_ACCESS_DENIED;
3295  }
3296 
3297  if (!sourcefcb->ads && sourcefcb->type != BTRFS_TYPE_FILE && sourcefcb->type != BTRFS_TYPE_SYMLINK) {
3298  ObDereferenceObject(sourcefo);
3299  return STATUS_INVALID_PARAMETER;
3300  }
3301 
3302  sourcelen = sourcefcb->ads ? sourcefcb->adsdata.Length : sourcefcb->inode_item.st_size;
3303 
3304  if (sector_align(sourcelen, Vcb->superblock.sector_size) < (UINT64)ded->SourceFileOffset.QuadPart + (UINT64)ded->ByteCount.QuadPart) {
3305  ObDereferenceObject(sourcefo);
3306  return STATUS_NOT_SUPPORTED;
3307  }
3308 
3309  if (fcb == sourcefcb &&
3312  WARN("source and destination are the same, and the ranges overlap\n");
3313  ObDereferenceObject(sourcefo);
3314  return STATUS_INVALID_PARAMETER;
3315  }
3316 
3317  // fail if nocsum flag set on one file but not the other
3318  if (!fcb->ads && !sourcefcb->ads && (fcb->inode_item.flags & BTRFS_INODE_NODATASUM) != (sourcefcb->inode_item.flags & BTRFS_INODE_NODATASUM)) {
3319  ObDereferenceObject(sourcefo);
3320  return STATUS_INVALID_PARAMETER;
3321  }
3322 
3324  InitializeListHead(&newexts);
3325 
3326  ExAcquireResourceSharedLite(&Vcb->tree_lock, TRUE);
3327 
3329 
3330  if (fcb != sourcefcb)
3331  ExAcquireResourceSharedLite(sourcefcb->Header.Resource, TRUE);
3332 
3335  goto end;
3336  }
3337 
3338  if (!FsRtlFastCheckLockForRead(&sourcefcb->lock, &ded->SourceFileOffset, &ded->ByteCount, 0, FileObject, PsGetCurrentProcess())) {
3340  goto end;
3341  }
3342 
3343  make_inline = fcb->ads ? FALSE : (fcb->inode_item.st_size <= Vcb->options.max_inline || fcb_is_inline(fcb));
3344 
3345  if (fcb->ads || sourcefcb->ads || make_inline || fcb_is_inline(sourcefcb)) {
3346  UINT8* data2;
3347  ULONG bytes_read, dataoff, datalen2;
3348 
3349  if (make_inline) {
3350  dataoff = (ULONG)ded->TargetFileOffset.QuadPart;
3351  datalen2 = (ULONG)fcb->inode_item.st_size;
3352  } else if (fcb->ads) {
3353  dataoff = 0;
3354  datalen2 = (ULONG)ded->ByteCount.QuadPart;
3355  } else {
3356  dataoff = ded->TargetFileOffset.QuadPart % Vcb->superblock.sector_size;
3357  datalen2 = (ULONG)sector_align(ded->ByteCount.QuadPart + dataoff, Vcb->superblock.sector_size);
3358  }
3359 
3361  if (!data2) {
3362  ERR("out of memory\n");
3364  goto end;
3365  }
3366 
3367  if (dataoff > 0) {
3368  if (make_inline)
3369  Status = read_file(fcb, data2, 0, datalen2, NULL, Irp);
3370  else
3371  Status = read_file(fcb, data2, ded->TargetFileOffset.QuadPart - dataoff, dataoff, NULL, Irp);
3372 
3373  if (!NT_SUCCESS(Status)) {
3374  ERR("read_file returned %08x\n", Status);
3375  ExFreePool(data2);
3376  goto end;
3377  }
3378  }
3379 
3380  if (sourcefcb->ads) {
3381  Status = read_stream(sourcefcb, data2 + dataoff, ded->SourceFileOffset.QuadPart, (ULONG)ded->ByteCount.QuadPart, &bytes_read);
3382  if (!NT_SUCCESS(Status)) {
3383  ERR("read_stream returned %08x\n", Status);
3384  ExFreePool(data2);
3385  goto end;
3386  }
3387  } else {
3388  Status = read_file(sourcefcb, data2 + dataoff, ded->SourceFileOffset.QuadPart, ded->ByteCount.QuadPart, &bytes_read, Irp);
3389  if (!NT_SUCCESS(Status)) {
3390  ERR("read_file returned %08x\n", Status);
3391  ExFreePool(data2);
3392  goto end;
3393  }
3394  }
3395 
3396  if (dataoff + bytes_read < datalen2)
3397  RtlZeroMemory(data2 + dataoff + bytes_read, datalen2 - bytes_read);
3398 
3399  if (fcb->ads)
3401  else if (make_inline) {
3402  UINT16 edsize;
3403  EXTENT_DATA* ed;
3404 
3405  Status = excise_extents(Vcb, fcb, 0, sector_align(fcb->inode_item.st_size, Vcb->superblock.sector_size), Irp, &rollback);
3406  if (!NT_SUCCESS(Status)) {
3407  ERR("excise_extents returned %08x\n", Status);
3408  ExFreePool(data2);
3409  goto end;
3410  }
3411 
3412  edsize = (UINT16)(offsetof(EXTENT_DATA, data[0]) + datalen2);
3413 
3415  if (!ed) {
3416  ERR("out of memory\n");
3417  ExFreePool(data2);
3419  goto end;
3420  }
3421 
3422  ed->generation = Vcb->superblock.generation;
3428 
3429  RtlCopyMemory(ed->data, data2, datalen2);
3430 
3432  if (!NT_SUCCESS(Status)) {
3433  ERR("add_extent_to_fcb returned %08x\n", Status);
3434  ExFreePool(data2);
3435  goto end;
3436  }
3437 
3438  fcb->inode_item.st_blocks += datalen2;
3439  } else {
3440  UINT64 start = ded->TargetFileOffset.QuadPart - (ded->TargetFileOffset.QuadPart % Vcb->superblock.sector_size);
3441 
3442  Status = do_write_file(fcb, start, start + datalen2, data2, Irp, FALSE, 0, &rollback);
3443  if (!NT_SUCCESS(Status)) {
3444  ERR("do_write_file returned %08x\n", Status);
3445  ExFreePool(data2);
3446  goto end;
3447  }
3448  }
3449 
3450  ExFreePool(data2);
3451  } else {
3452  LIST_ENTRY* lastextle;
3453 
3454  le = sourcefcb->extents.Flink;
3455  while (le != &sourcefcb->extents) {
3457 
3458  if (!ext->ignore) {
3459  if (ext->offset >= (UINT64)ded->SourceFileOffset.QuadPart + (UINT64)ded->ByteCount.QuadPart)
3460  break;
3461 
3462  if (ext->extent_data.type != EXTENT_TYPE_INLINE) {
3463  ULONG extlen = offsetof(extent, extent_data) + sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2);
3464  extent* ext2;
3465  EXTENT_DATA2 *ed2s, *ed2d;
3466  chunk* c;
3467 
3468  ed2s = (EXTENT_DATA2*)ext->extent_data.data;
3469 
3470  if (ext->offset + ed2s->num_bytes <= (UINT64)ded->SourceFileOffset.QuadPart) {
3471  le = le->Flink;
3472  continue;
3473  }
3474 
3476  if (!ext2) {
3477  ERR("out of memory\n");
3479  goto end;
3480  }
3481 
3482  if (ext->offset < (UINT64)ded->SourceFileOffset.QuadPart)
3483  ext2->offset = ded->TargetFileOffset.QuadPart;
3484  else
3485  ext2->offset = ext->offset - ded->SourceFileOffset.QuadPart + ded->TargetFileOffset.QuadPart;
3486 
3487  ext2->datalen = sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2);
3488  ext2->unique = FALSE;
3489  ext2->ignore = FALSE;
3490  ext2->inserted = TRUE;
3491 
3492  ext2->extent_data.generation = Vcb->superblock.generation;
3493  ext2->extent_data.decoded_size = ext->extent_data.decoded_size;
3494  ext2->extent_data.compression = ext->extent_data.compression;
3495  ext2->extent_data.encryption = ext->extent_data.encryption;
3496  ext2->extent_data.encoding = ext->extent_data.encoding;
3497  ext2->extent_data.type = ext->extent_data.type;
3498 
3499  ed2d = (EXTENT_DATA2*)ext2->extent_data.data;
3500 
3501  ed2d->address = ed2s->address;
3502  ed2d->size = ed2s->size;
3503 
3504  if (ext->offset < (UINT64)ded->SourceFileOffset.QuadPart) {
3505  ed2d->offset = ed2s->offset + ded->SourceFileOffset.QuadPart - ext->offset;
3506  ed2d->num_bytes = min((UINT64)ded->ByteCount.QuadPart, ed2s->num_bytes + ext->offset - ded->SourceFileOffset.QuadPart);
3507  } else {
3508  ed2d->offset = ed2s->offset;
3509  ed2d->num_bytes = min(ded->SourceFileOffset.QuadPart + ded->ByteCount.QuadPart - ext->offset, ed2s->num_bytes);
3510  }
3511 
3512  if (ext->csum) {
3513  if (ext->extent_data.compression == BTRFS_COMPRESSION_NONE) {
3514  ext2->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(ed2d->num_bytes * sizeof(UINT32) / Vcb->superblock.sector_size), ALLOC_TAG);
3515  if (!ext2->csum) {
3516  ERR("out of memory\n");
3518  ExFreePool(ext2);
3519  goto end;
3520  }
3521 
3522  RtlCopyMemory(ext2->csum, &ext->csum[(ed2d->offset - ed2s->offset) / Vcb->superblock.sector_size],
3523  (ULONG)(ed2d->num_bytes * sizeof(UINT32) / Vcb->superblock.sector_size));
3524  } else {
3525  ext2->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(ed2d->size * sizeof(UINT32) / Vcb->superblock.sector_size), ALLOC_TAG);
3526  if (!ext2->csum) {
3527  ERR("out of memory\n");
3529  ExFreePool(ext2);
3530  goto end;
3531  }
3532 
3533  RtlCopyMemory(ext2->csum, ext->csum, (ULONG)(ed2s->size * sizeof(UINT32) / Vcb->superblock.sector_size));
3534  }
3535  } else
3536  ext2->csum = NULL;
3537 
3538  InsertTailList(&newexts, &ext2->list_entry);
3539 
3540  c = get_chunk_from_address(Vcb, ed2s->address);
3541  if (!c) {
3542  ERR("get_chunk_from_address(%llx) failed\n", ed2s->address);
3544  goto end;
3545  }
3546 
3547  Status = update_changed_extent_ref(Vcb, c, ed2s->address, ed2s->size, fcb->subvol->id, fcb->inode, ext2->offset - ed2d->offset,
3549  if (!NT_SUCCESS(Status)) {
3550  ERR("update_changed_extent_ref returned %08x\n", Status);
3551  goto end;
3552  }
3553 
3554  nbytes += ed2d->num_bytes;
3555  }
3556  }
3557 
3558  le = le->Flink;
3559  }
3560 
3562  if (!NT_SUCCESS(Status)) {
3563  ERR("excise_extents returned %08x\n", Status);
3564 
3565  while (!IsListEmpty(&newexts)) {
3567  ExFreePool(ext);
3568  }
3569 
3570  goto end;
3571  }
3572 
3573  // clear unique flags in source fcb
3574  le = sourcefcb->extents.Flink;
3575  while (le != &sourcefcb->extents) {
3577 
3578  if (!ext->ignore && ext->unique && (ext->extent_data.type == EXTENT_TYPE_REGULAR || ext->extent_data.type == EXTENT_TYPE_PREALLOC)) {
3579  EXTENT_DATA2* ed2s = (EXTENT_DATA2*)ext->extent_data.data;
3580  LIST_ENTRY* le2;
3581 
3582  le2 = newexts.Flink;
3583  while (le2 != &newexts) {
3585 
3586  if (ext2->extent_data.type == EXTENT_TYPE_REGULAR || ext2->extent_data.type == EXTENT_TYPE_PREALLOC) {
3587  EXTENT_DATA2* ed2d = (EXTENT_DATA2*)ext2->extent_data.data;
3588 
3589  if (ed2d->address == ed2s->address && ed2d->size == ed2s->size) {
3590  ext->unique = FALSE;
3591  break;
3592  }
3593  }
3594 
3595  le2 = le2->Flink;
3596  }
3597  }
3598 
3599  le = le->Flink;
3600  }
3601 
3602  lastextle = &fcb->extents;
3603  while (!IsListEmpty(&newexts)) {
3605 
3606  add_extent(fcb, lastextle, ext);
3607  lastextle = &ext->list_entry;
3608  }
3609  }
3610 
3613 
3614  if (fcb->ads) {
3615  ccb->fileref->parent->fcb->inode_item.sequence++;
3616 
3617  if (!ccb->user_set_change_time)
3618  ccb->fileref->parent->fcb->inode_item.st_ctime = now;
3619 
3620  ccb->fileref->parent->fcb->inode_item_changed = TRUE;
3621  mark_fcb_dirty(ccb->fileref->parent->fcb);
3622  } else {
3623  fcb->inode_item.st_blocks += nbytes;
3624  fcb->inode_item.sequence++;
3625 
3626  if (!ccb->user_set_change_time)
3628 
3629  if (!ccb->user_set_write_time) {
3632  }
3633 
3636  }
3637 
3639 
3640  if (fcb->nonpaged->segment_object.DataSectionObject)
3641  CcPurgeCacheSection(&fcb->nonpaged->segment_object, &ded->TargetFileOffset, (ULONG)ded->ByteCount.QuadPart, FALSE);
3642 
3644 
3645 end:
3646  ObDereferenceObject(sourcefo);
3647 
3648  if (NT_SUCCESS(Status))
3650  else
3652 
3653  if (fcb != sourcefcb)
3654  ExReleaseResourceLite(sourcefcb->Header.Resource);
3655 
3656  ExReleaseResourceLite(fcb->Header.Resource);
3657 
3658  ExReleaseResourceLite(&Vcb->tree_lock);
3659 
3660  return Status;
3661 }
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
struct _file_ref * parent
Definition: btrfs_drv.h:326
void do_rollback(device_extension *Vcb, LIST_ENTRY *rollback)
Definition: treefuncs.c:1032
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:1011
#define TRUE
Definition: types.h:120
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
#define BTRFS_COMPRESSION_NONE
Definition: btrfs.h:58
NTSTATUS excise_extents(device_extension *Vcb, fcb *fcb, UINT64 start_data, UINT64 end_data, PIRP Irp, LIST_ENTRY *rollback)
Definition: write.c:2376
UINT64 num_bytes
Definition: btrfs.h:344
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
UINT64 size
Definition: btrfs.h:342
UINT64 inode
Definition: btrfs_drv.h:262
#define WARN(fmt,...)
Definition: debug.h:111
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS add_extent_to_fcb(_In_ fcb *fcb, _In_ UINT64 offset, _In_reads_bytes_(edsize) EXTENT_DATA *ed, _In_ UINT16 edsize, _In_ BOOL unique, _In_opt_ _When_(return >=0, __drv_aliasesMem) UINT32 *csum, _In_ LIST_ENTRY *rollback)
Definition: write.c:2728
#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:357
#define InsertTailList(ListHead, Entry)
int const JOCTET unsigned int datalen
Definition: jpeglib.h:1027
BOOL fcb_is_inline(fcb *fcb)
Definition: fsctl.c:3208
BTRFS_TIME st_ctime
Definition: btrfs.h:279
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
UINT8 data[1]
Definition: btrfs.h:337
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:64
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:86
UINT64 decoded_size
Definition: btrfs.h:332
#define EXTENT_TYPE_INLINE
Definition: btrfs.h:67
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
UINT8 encryption
Definition: btrfs.h:334
unsigned int UINT32
chunk * get_chunk_from_address(device_extension *Vcb, UINT64 address)
Definition: write.c:93
unsigned int BOOL
Definition: ntddk_ex.h:94
time_t now
Definition: finger.c:65
#define FILE_READ_DATA
Definition: nt_native.h:628
UINT64 address
Definition: btrfs.h:341
#define FILE_ACTION_MODIFIED
#define PsGetCurrentProcess
Definition: psfuncs.h:17
UINT8 type
Definition: btrfs.h:336
#define BTRFS_ENCODING_NONE
Definition: btrfs.h:65
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:1464
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
NTSTATUS do_write_file(fcb *fcb, UINT64 start_data, UINT64 end_data, void *data, PIRP Irp, BOOL file_write, UINT32 irp_offset, LIST_ENTRY *rollback)
Definition: write.c:3947
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:593
BOOL extents_changed
Definition: btrfs_drv.h:292
BTRFS_TIME st_mtime
Definition: btrfs.h:280
#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:266
UINT64 offset
Definition: btrfs.h:343
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:256
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
LARGE_INTEGER SourceFileOffset
Definition: shellext.h:176
#define BTRFS_ENCRYPTION_NONE
Definition: btrfs.h:63
if(!(yy_init))
Definition: macro.lex.yy.c:714
static __inline BOOL is_subvol_readonly(root *r, PIRP Irp)
Definition: btrfs_drv.h:1012
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define BTRFS_INODE_NODATASUM
Definition: propsheet.h:76
#define Vcb
Definition: cdprocs.h:1425
const GLubyte * c
Definition: glext.h:8905
LIST_ENTRY extents
Definition: btrfs_drv.h:273
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
* PFILE_OBJECT
Definition: iotypes.h:1954
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
NTSTATUS update_changed_extent_ref(device_extension *Vcb, chunk *c, UINT64 address, UINT64 size, UINT64 root, UINT64 objid, UINT64 offset, INT32 count, BOOL no_csum, BOOL superseded, PIRP Irp)
Definition: extent-tree.c:1950
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
NTSTATUS read_file(fcb *fcb, UINT8 *data, UINT64 start, UINT64 length, ULONG *pbr, PIRP Irp)
Definition: read.c:2737
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
static const BYTE ext2[]
Definition: encode.c:2699
BOOL inode_item_changed
Definition: btrfs_drv.h:279
UINT64 st_blocks
Definition: btrfs.h:268
BOOL ads
Definition: btrfs_drv.h:299
UINT16 encoding
Definition: btrfs.h:335
Definition: typedefs.h:117
#define EXTENT_TYPE_PREALLOC
Definition: btrfs.h:69
INODE_ITEM inode_item
Definition: btrfs_drv.h:264
POBJECT_TYPE IoFileObjectType
Definition: iomgr.c:36
_In_ fcb _In_ chunk _In_ UINT64 _In_ UINT64 _In_ BOOL _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: btrfs_drv.h:1321
UINT8 compression
Definition: btrfs.h:333
void add_extent(_In_ fcb *fcb, _In_ LIST_ENTRY *prevextle, _In_ __drv_aliasesMem extent *newext)
Definition: write.c:2359
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:68
BOOL user_set_write_time
Definition: btrfs_drv.h:364
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
UINT64 st_size
Definition: btrfs.h:267
struct _fcb_nonpaged * nonpaged
Definition: btrfs_drv.h:257
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
unsigned short UINT16
struct _root * subvol
Definition: btrfs_drv.h:261
#define min(a, b)
Definition: monoChain.cc:55
Definition: list.h:27
UINT64 generation
Definition: btrfs.h:331
UINT64 flags
Definition: btrfs.h:275
ANSI_STRING adsdata
Definition: btrfs_drv.h:303
LARGE_INTEGER TargetFileOffset
Definition: shellext.h:177
HRESULT read_stream(BSCallback *, IStream *, void *, DWORD, DWORD *) DECLSPEC_HIDDEN
Definition: navigate.c:602
UINT16 edsize
Definition: write.c:2828
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
#define BTRFS_TYPE_FILE
Definition: shellext.h:80
#define STATUS_FILE_LOCK_CONFLICT
Definition: ntstatus.h:306
UINT8 type
Definition: btrfs_drv.h:263
static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME *out)
Definition: btrfs_drv.h:968
#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:1383
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
file_ref * fileref
Definition: btrfs_drv.h:358
unsigned long long UINT64
return STATUS_SUCCESS
Definition: btrfs.c:2725
unsigned char UINT8
EXTENT_DATA * ed
Definition: write.c:2826
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
BOOL user_set_change_time
Definition: btrfs_drv.h:365
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
LONGLONG QuadPart
Definition: typedefs.h:112
#define BTRFS_TYPE_SYMLINK
Definition: shellext.h:86
UINT64 sequence
Definition: btrfs.h:276
Definition: tftpd.h:137

Referenced by fsctl_request().

◆ fcb_is_inline()

BOOL fcb_is_inline ( fcb fcb)

Definition at line 3208 of file fsctl.c.

3208  {
3209  LIST_ENTRY* le;
3210 
3211  le = fcb->extents.Flink;
3212  while (le != &fcb->extents) {
3214 
3215  if (!ext->ignore)
3216  return ext->extent_data.type == EXTENT_TYPE_INLINE;
3217 
3218  le = le->Flink;
3219  }
3220 
3221  return FALSE;
3222 }
#define EXTENT_TYPE_INLINE
Definition: btrfs.h:67
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:273
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 4488 of file fsctl.c.

4488  {
4489  btrfs_find_subvol* bfs;
4490  NTSTATUS Status;
4491  traverse_ptr tp;
4492  KEY searchkey;
4493 
4494  if (!in || inlen < sizeof(btrfs_find_subvol))
4495  return STATUS_INVALID_PARAMETER;
4496 
4497  if (!out || outlen < sizeof(WCHAR))
4498  return STATUS_INVALID_PARAMETER;
4499 
4500  if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), Irp->RequestorMode))
4502 
4503  bfs = (btrfs_find_subvol*)in;
4504 
4505  ExAcquireResourceSharedLite(&Vcb->tree_lock, TRUE);
4506 
4507  if (!Vcb->uuid_root) {
4508  ERR("couldn't find uuid root\n");
4510  goto end;
4511  }
4512 
4513  RtlCopyMemory(&searchkey.obj_id, &bfs->uuid, sizeof(UINT64));
4514  searchkey.obj_type = TYPE_SUBVOL_UUID;
4515  RtlCopyMemory(&searchkey.offset, &bfs->uuid.uuid[sizeof(UINT64)], sizeof(UINT64));
4516 
4517  Status = find_item(Vcb, Vcb->uuid_root, &tp, &searchkey, FALSE, Irp);
4518 
4519  if (!NT_SUCCESS(Status)) {
4520  ERR("find_item returned %08x\n", Status);
4521  goto end;
4522  }
4523 
4524  if (!keycmp(searchkey, tp.item->key) && tp.item->size >= sizeof(UINT64)) {
4525  UINT64* id = (UINT64*)tp.item->data;
4526 
4527  if (bfs->ctransid != 0) {
4528  KEY searchkey2;
4529  traverse_ptr tp2;
4530 
4531  searchkey2.obj_id = *id;
4532  searchkey2.obj_type = TYPE_ROOT_ITEM;
4533  searchkey2.offset = 0xffffffffffffffff;
4534 
4535  Status = find_item(Vcb, Vcb->root_root, &tp2, &searchkey2, FALSE, Irp);
4536  if (!NT_SUCCESS(Status)) {
4537  ERR("find_item returned %08x\n", Status);
4538  goto end;
4539  }
4540 
4541  if (tp2.item->key.obj_id == searchkey2.obj_id && tp2.item->key.obj_type == searchkey2.obj_type &&
4542  tp2.item->size >= offsetof(ROOT_ITEM, otransid)) {
4543  ROOT_ITEM* ri = (ROOT_ITEM*)tp2.item->data;
4544 
4545  if (ri->ctransid == bfs->ctransid) {
4546  TRACE("found subvol %llx\n", *id);
4547  Status = get_subvol_path(Vcb, *id, out, outlen, Irp);
4548  goto end;
4549  }
4550  }
4551  } else {
4552  TRACE("found subvol %llx\n", *id);
4553  Status = get_subvol_path(Vcb, *id, out, outlen, Irp);
4554  goto end;
4555  }
4556  }
4557 
4558  searchkey.obj_type = TYPE_SUBVOL_REC_UUID;
4559 
4560  Status = find_item(Vcb, Vcb->uuid_root, &tp, &searchkey, FALSE, Irp);
4561 
4562  if (!NT_SUCCESS(Status)) {
4563  ERR("find_item returned %08x\n", Status);
4564  goto end;
4565  }
4566 
4567  if (!keycmp(searchkey, tp.item->key) && tp.item->size >= sizeof(UINT64)) {
4568  UINT64* ids = (UINT64*)tp.item->data;
4569  ULONG i;
4570 
4571  for (i = 0; i < tp.item->size / sizeof(UINT64); i++) {
4572  if (bfs->ctransid != 0) {
4573  KEY searchkey2;
4574  traverse_ptr tp2;
4575 
4576  searchkey2.obj_id = ids[i];
4577  searchkey2.obj_type = TYPE_ROOT_ITEM;
4578  searchkey2.offset = 0xffffffffffffffff;
4579 
4580  Status = find_item(Vcb, Vcb->root_root, &tp2, &searchkey2, FALSE, Irp);
4581  if (!NT_SUCCESS(Status)) {
4582  ERR("find_item returned %08x\n", Status);
4583  goto end;
4584  }
4585 
4586  if (tp2.item->key.obj_id == searchkey2.obj_id && tp2.item->key.obj_type == searchkey2.obj_type &&
4587  tp2.item->size >= offsetof(ROOT_ITEM, otransid)) {
4588  ROOT_ITEM* ri = (ROOT_ITEM*)tp2.item->data;
4589 
4590  if (ri->ctransid == bfs->ctransid) {
4591  TRACE("found subvol %llx\n", ids[i]);
4592  Status = get_subvol_path(Vcb, ids[i], out, outlen, Irp);
4593  goto end;
4594  }
4595  }
4596  } else {
4597  TRACE("found subvol %llx\n", ids[i]);
4598  Status = get_subvol_path(Vcb, ids[i], out, outlen, Irp);
4599  goto end;
4600  }
4601  }
4602  }
4603 
4605 
4606 end:
4607  ExReleaseResourceLite(&Vcb->tree_lock);
4608 
4609  return Status;
4610 }
#define STATUS_PRIVILEGE_NOT_HELD
Definition: DriverTester.h:9
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
UINT64 offset
Definition: btrfs.h:125
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
UINT8 uuid[16]
Definition: btrfs.h:119
#define keycmp(key1, key2)
Definition: btrfs_drv.h:995
LONG NTSTATUS
Definition: precomp.h:26
UINT64 obj_id
Definition: btrfs.h:123
BOOLEAN NTAPI SeSinglePrivilegeCheck(IN LUID PrivilegeValue, IN KPROCESSOR_MODE PreviousMode)
Definition: priv.c:524
GLuint GLuint end
Definition: gl.h:1545
_In_ UINT64 _In_ UINT64 _In_ UINT64 _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2645
UINT16 size
Definition: btrfs_drv.h:389
UINT8 obj_type
Definition: btrfs.h:124
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:276
#define offsetof(TYPE, MEMBER)
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
#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:45
#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:468
Status
Definition: gdiplustypes.h:24
static NTSTATUS get_subvol_path(device_extension *Vcb, UINT64 id, WCHAR *out, ULONG outlen, PIRP Irp)
Definition: fsctl.c:4437
#define ERR(fmt,...)
Definition: debug.h:109
Definition: btrfs.h:122
#define SE_MANAGE_VOLUME_PRIVILEGE
Definition: security.c:682
GLuint in
Definition: glext.h:9616
#define TYPE_ROOT_ITEM
Definition: btrfs.h:26
UINT64 ctransid
Definition: btrfs.h:301
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:46
unsigned long long UINT64
UINT8 * data
Definition: btrfs_drv.h:390

Referenced by fsctl_request().

◆ flush_fcb_caches()

static void flush_fcb_caches ( device_extension Vcb)
static

Definition at line 2196 of file fsctl.c.

2196  {
2197  LIST_ENTRY* le;
2198 
2199  le = Vcb->all_fcbs.Flink;
2200  while (le != &Vcb->all_fcbs) {
2201  struct _fcb* fcb = CONTAINING_RECORD(le, struct _fcb, list_entry_all);
2203 
2204  if (fcb->type != BTRFS_TYPE_DIRECTORY && !fcb->deleted)
2205  CcFlushCache(&fcb->nonpaged->segment_object, NULL, 0, &iosb);
2206 
2207  le = le->Flink;
2208  }
2209 }
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:306
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:81
smooth NULL
Definition: ftsmooth.c:416
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
BOOL deleted
Definition: btrfs_drv.h:267
Definition: typedefs.h:117
struct _fcb_nonpaged * nonpaged
Definition: btrfs_drv.h:257
UINT8 type
Definition: btrfs_drv.h:263

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
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
BOOL deleted
Definition: btrfs_drv.h:267
Definition: typedefs.h:117
struct _fcb_nonpaged * nonpaged
Definition: btrfs_drv.h:257
struct _root * subvol
Definition: btrfs_drv.h:261
Definition: list.h:27
UINT8 type
Definition: btrfs_drv.h:263

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

1679  {
1680  FILESYSTEM_STATISTICS* fss;
1681 
1682  WARN("STUB: FSCTL_FILESYSTEM_GET_STATISTICS\n");
1683 
1684  // This is hideously wrong, but at least it stops SMB from breaking
1685 
1686  if (buflen < sizeof(FILESYSTEM_STATISTICS))
1687  return STATUS_BUFFER_TOO_SMALL;
1688 
1689  fss = buffer;
1690  RtlZeroMemory(fss, sizeof(FILESYSTEM_STATISTICS));
1691 
1692  fss->Version = 1;
1695 
1696  *retlen = sizeof(FILESYSTEM_STATISTICS);
1697 
1698  return STATUS_SUCCESS;
1699 }
#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:2725
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 4080 of file fsctl.c.

4080  {
4081  LIST_ENTRY* le;
4082  btrfs_set_xattr* bsxa;
4083  ULONG reqlen = (ULONG)offsetof(btrfs_set_xattr, data[0]);
4084  fcb* fcb;
4085  ccb* ccb;
4086 
4087  if (!data || datalen < reqlen)
4088  return STATUS_INVALID_PARAMETER;
4089 
4090  if (!FileObject || !FileObject->FsContext || !FileObject->FsContext2 || FileObject->FsContext == Vcb->volume_fcb)
4091  return STATUS_INVALID_PARAMETER;
4092 
4093  fcb = FileObject->FsContext;
4094  ccb = FileObject->FsContext2;
4095 
4096  if (!(ccb->access & (FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES)) && processor_mode == UserMode) {
4097  WARN("insufficient privileges\n");
4098  return STATUS_ACCESS_DENIED;
4099  }
4100 
4102 
4103  le = fcb->xattrs.Flink;
4104  while (le != &fcb->xattrs) {
4106 
4107  if (xa->valuelen > 0)
4108  reqlen += (ULONG)offsetof(btrfs_set_xattr, data[0]) + xa->namelen + xa->valuelen;
4109 
4110  le = le->Flink;
4111  }
4112 
4113  if (datalen < reqlen) {
4114  ExReleaseResourceLite(fcb->Header.Resource);
4115  return STATUS_BUFFER_OVERFLOW;
4116  }
4117 
4118  bsxa = (btrfs_set_xattr*)data;
4119 
4120  if (reqlen > 0) {
4121  le = fcb->xattrs.Flink;
4122  while (le != &fcb->xattrs) {
4124 
4125  if (xa->valuelen > 0) {
4126  bsxa->namelen = xa->namelen;
4127  bsxa->valuelen = xa->valuelen;
4128  memcpy(bsxa->data, xa->data, xa->namelen + xa->valuelen);
4129 
4130  bsxa = (btrfs_set_xattr*)&bsxa->data[xa->namelen + xa->valuelen];
4131  }
4132 
4133  le = le->Flink;
4134  }
4135  }
4136 
4137  bsxa->namelen = 0;
4138  bsxa->valuelen = 0;
4139 
4140  ExReleaseResourceLite(fcb->Header.Resource);
4141 
4142  return STATUS_SUCCESS;
4143 }
#define TRUE
Definition: types.h:120
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define WARN(fmt,...)
Definition: debug.h:111
ACCESS_MASK access
Definition: btrfs_drv.h:357
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:256
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
struct _fcb fcb
Definition: btrfs_drv.h:1321
LIST_ENTRY xattrs
Definition: btrfs_drv.h:281
#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:250
#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:249
unsigned int ULONG
Definition: retypes.h:1
struct _ccb ccb
return STATUS_SUCCESS
Definition: btrfs.c:2725
char data[1]
Definition: btrfs_drv.h:252

Referenced by fsctl_request().

◆ fsctl_request()

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

Definition at line 4794 of file fsctl.c.

4794  {
4795  PIRP Irp = *Pirp;
4797  NTSTATUS Status;
4798 
4799  switch (type) {
4800 #if (NTDDI_VERSION >= NTDDI_WIN7)
4801  case FSCTL_REQUEST_OPLOCK:
4802  WARN("STUB: FSCTL_REQUEST_OPLOCK\n");
4804  break;
4805 #endif
4806 
4808  WARN("STUB: FSCTL_REQUEST_OPLOCK_LEVEL_1\n");
4810  break;
4811 
4813  WARN("STUB: FSCTL_REQUEST_OPLOCK_LEVEL_2\n");
4815  break;
4816 
4818  WARN("STUB: FSCTL_REQUEST_BATCH_OPLOCK\n");
4820  break;
4821 
4823  WARN("STUB: FSCTL_OPLOCK_BREAK_ACKNOWLEDGE\n");
4825  break;
4826 
4828  WARN("STUB: FSCTL_OPLOCK_BREAK_ACK_NO_2\n");
4830  break;
4831 
4833  WARN("STUB: FSCTL_OPBATCH_ACK_CLOSE_PENDING\n");
4835  break;
4836 
4838  WARN("STUB: FSCTL_OPLOCK_BREAK_NOTIFY\n");
4840  break;
4841 
4843  WARN("STUB: FSCTL_REQUEST_FILTER_OPLOCK\n");
4845  break;
4846 
4847  case FSCTL_LOCK_VOLUME:
4849  break;
4850 
4851  case FSCTL_UNLOCK_VOLUME:
4853  break;
4854 
4855  case FSCTL_DISMOUNT_VOLUME:
4857  break;
4858 
4861  break;
4862 
4864  WARN("STUB: FSCTL_IS_PATHNAME_VALID\n");
4866  break;
4867 
4869  WARN("STUB: FSCTL_MARK_VOLUME_DIRTY\n");
4871  break;
4872 
4874  WARN("STUB: FSCTL_QUERY_RETRIEVAL_POINTERS\n");
4876  break;
4877 
4878  case FSCTL_GET_COMPRESSION:
4880  break;
4881 
4882  case FSCTL_SET_COMPRESSION:
4884  break;
4885 
4887  WARN("STUB: FSCTL_SET_BOOTLOADER_ACCESSED\n");
4889  break;
4890 
4893  break;
4894 
4895  case FSCTL_QUERY_FAT_BPB:
4896  WARN("STUB: FSCTL_QUERY_FAT_BPB\n");
4898  break;
4899 
4901  Status = fs_get_statistics(Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.FileSystemControl.OutputBufferLength, &Irp->IoStatus.Information);
4902  break;
4903 
4905  WARN("STUB: FSCTL_GET_NTFS_VOLUME_DATA\n");
4907  break;
4908 
4910  WARN("STUB: FSCTL_GET_NTFS_FILE_RECORD\n");
4912  break;
4913 
4915  WARN("STUB: FSCTL_GET_VOLUME_BITMAP\n");
4917  break;
4918 
4920  WARN("STUB: FSCTL_GET_RETRIEVAL_POINTERS\n");
4922  break;
4923 
4924  case FSCTL_MOVE_FILE:
4925  WARN("STUB: FSCTL_MOVE_FILE\n");
4927  break;
4928 
4929  case FSCTL_IS_VOLUME_DIRTY:
4931  break;
4932 
4935  break;
4936 
4938  WARN("STUB: FSCTL_FIND_FILES_BY_SID\n");
4940  break;
4941 
4942  case FSCTL_SET_OBJECT_ID:
4943  WARN("STUB: FSCTL_SET_OBJECT_ID\n");
4945  break;
4946 
4947  case FSCTL_GET_OBJECT_ID:
4949  IrpSp->Parameters.FileSystemControl.OutputBufferLength, &Irp->IoStatus.Information);
4950  break;
4951 
4953  WARN("STUB: FSCTL_DELETE_OBJECT_ID\n");
4955  break;
4956 
4959  break;
4960 
4962  Status = get_reparse_point(DeviceObject, IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer,
4963  IrpSp->Parameters.FileSystemControl.OutputBufferLength, &Irp->IoStatus.Information);
4964  break;
4965 
4968  break;
4969 
4970  case FSCTL_ENUM_USN_DATA:
4971  WARN("STUB: FSCTL_ENUM_USN_DATA\n");
4973  break;
4974 
4976  WARN("STUB: FSCTL_SECURITY_ID_CHECK\n");
4978  break;
4979 
4981  WARN("STUB: FSCTL_READ_USN_JOURNAL\n");
4983  break;
4984 
4986  WARN("STUB: FSCTL_SET_OBJECT_ID_EXTENDED\n");
4988  break;
4989 
4992  IrpSp->Parameters.FileSystemControl.OutputBufferLength, &Irp->IoStatus.Information);
4993  break;
4994 
4995  case FSCTL_SET_SPARSE:
4996  Status = set_sparse(DeviceObject->DeviceExtension, IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer,
4997  IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp);
4998  break;
4999 
5000  case FSCTL_SET_ZERO_DATA:
5001  Status = set_zero_data(DeviceObject->DeviceExtension, IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer,
5002  IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp);
5003  break;
5004 
5006  Status = query_ranges(IrpSp->FileObject, IrpSp->Parameters.FileSystemControl.Type3InputBuffer,
5007  IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp->UserBuffer,
5008  IrpSp->Parameters.FileSystemControl.OutputBufferLength, &Irp->IoStatus.Information);
5009  break;
5010 
5011  case FSCTL_ENABLE_UPGRADE:
5012  WARN("STUB: FSCTL_ENABLE_UPGRADE\n");
5014  break;
5015 
5016  case FSCTL_SET_ENCRYPTION:
5017  WARN("STUB: FSCTL_SET_ENCRYPTION\n");
5019  break;
5020 
5022  WARN("STUB: FSCTL_ENCRYPTION_FSCTL_IO\n");
5024  break;
5025 
5027  WARN("STUB: FSCTL_WRITE_RAW_ENCRYPTED\n");
5029  break;
5030 
5032  WARN("STUB: FSCTL_READ_RAW_ENCRYPTED\n");
5034  break;
5035 
5036