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

Go to the source code of this file.

Macros

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

Functions

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

Variables

LIST_ENTRY VcbList
 
ERESOURCE global_loading_lock
 
PDRIVER_OBJECT drvobj
 
tFsRtlCheckLockForOplockRequest fFsRtlCheckLockForOplockRequest
 
tFsRtlAreThereCurrentOrInProgressFileLocks fFsRtlAreThereCurrentOrInProgressFileLocks
 

Macro Definition Documentation

◆ DOTDOT

#define DOTDOT   ".."

Definition at line 35 of file fsctl.c.

◆ FSCTL_CSV_CONTROL

Definition at line 28 of file fsctl.c.

◆ FSCTL_QUERY_VOLUME_CONTAINER_STATE

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

Definition at line 32 of file fsctl.c.

◆ SEF_AVOID_PRIVILEGE_CHECK

#define SEF_AVOID_PRIVILEGE_CHECK   0x08

Definition at line 37 of file fsctl.c.

◆ SEF_SACL_AUTO_INHERIT

#define SEF_SACL_AUTO_INHERIT   0x02

Definition at line 39 of file fsctl.c.

Function Documentation

◆ add_csum_sparse_extents()

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

Definition at line 5144 of file fsctl.c.

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

Referenced by get_csum_info().

◆ add_device()

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

Definition at line 2731 of file fsctl.c.

2731  {
2733  NTSTATUS Status;
2734  PFILE_OBJECT fileobj, mountmgrfo;
2736  HANDLE h;
2737  LIST_ENTRY* le;
2738  device* dev;
2739  DEV_ITEM* di;
2740  uint64_t dev_id, size;
2741  uint8_t* mb;
2742  uint64_t* stats;
2743  UNICODE_STRING mmdevpath, pnp_name, pnp_name2;
2744  volume_child* vc;
2746  KEY searchkey;
2747  traverse_ptr tp;
2750  pdo_device_extension* pdode;
2751  const GUID* pnp_guid;
2753 
2754  pnp_name.Buffer = NULL;
2755 
2756  if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), processor_mode))
2758 
2759  if (!Vcb->vde) {
2760  WARN("not allowing second device to be added to non-PNP device\n");
2761  return STATUS_NOT_SUPPORTED;
2762  }
2763 
2764  if (Vcb->readonly) // FIXME - handle adding R/W device to seeding device
2766 
2767 #if defined(_WIN64)
2768  if (IoIs32bitProcess(Irp)) {
2769  if (IrpSp->Parameters.FileSystemControl.InputBufferLength != sizeof(uint32_t))
2770  return STATUS_INVALID_PARAMETER;
2771 
2772  h = (HANDLE)LongToHandle((*(uint32_t*)Irp->AssociatedIrp.SystemBuffer));
2773  } else {
2774 #endif
2775  if (IrpSp->Parameters.FileSystemControl.InputBufferLength != sizeof(HANDLE))
2776  return STATUS_INVALID_PARAMETER;
2777 
2778  h = *(PHANDLE)Irp->AssociatedIrp.SystemBuffer;
2779 #if defined(_WIN64)
2780  }
2781 #endif
2782 
2783  Status = ObReferenceObjectByHandle(h, 0, *IoFileObjectType, Irp->RequestorMode, (void**)&fileobj, NULL);
2784 
2785  if (!NT_SUCCESS(Status)) {
2786  ERR("ObReferenceObjectByHandle returned %08lx\n", Status);
2787  return Status;
2788  }
2789 
2790  DeviceObject = fileobj->DeviceObject;
2791 
2792  Status = get_device_pnp_name(DeviceObject, &pnp_name, &pnp_guid);
2793  if (!NT_SUCCESS(Status)) {
2794  ERR("get_device_pnp_name returned %08lx\n", Status);
2795  ObDereferenceObject(fileobj);
2796  return Status;
2797  }
2798 
2799  // If this is a disk, we have been handed the PDO, so need to go up to find something we can use
2800  if (RtlCompareMemory(pnp_guid, &GUID_DEVINTERFACE_DISK, sizeof(GUID)) == sizeof(GUID) && DeviceObject->AttachedDevice)
2801  DeviceObject = DeviceObject->AttachedDevice;
2802 
2804  if (!NT_SUCCESS(Status)) {
2805  ERR("IOCTL_DISK_IS_WRITABLE returned %08lx\n", Status);
2806  ObDereferenceObject(fileobj);
2807  return Status;
2808  }
2809 
2811  if (!NT_SUCCESS(Status)) {
2812  ERR("is_device_part_of_mounted_btrfs_raid returned %08lx\n", Status);
2813  ObDereferenceObject(fileobj);
2814  return Status;
2815  }
2816 
2817  // if disk, check it has no partitions
2818  if (RtlCompareMemory(pnp_guid, &GUID_DEVINTERFACE_DISK, sizeof(GUID)) == sizeof(GUID)) {
2819  ULONG dlisize;
2820  DRIVE_LAYOUT_INFORMATION_EX* dli = NULL;
2821 
2822  dlisize = 0;
2823 
2824  do {
2825  dlisize += 1024;
2826 
2827  if (dli)
2828  ExFreePool(dli);
2829 
2830  dli = ExAllocatePoolWithTag(PagedPool, dlisize, ALLOC_TAG);
2831  if (!dli) {
2832  ERR("out of memory\n");
2834  goto end2;
2835  }
2836 
2838  } while (Status == STATUS_BUFFER_TOO_SMALL);
2839 
2840  if (NT_SUCCESS(Status) && dli->PartitionCount > 0) {
2841  ExFreePool(dli);
2842  ERR("not adding disk which has partitions\n");
2844  goto end2;
2845  }
2846 
2847  ExFreePool(dli);
2848  }
2849 
2851  &sdn, sizeof(STORAGE_DEVICE_NUMBER), true, NULL);
2852  if (NT_SUCCESS(Status)) {
2853  if (sdn.DeviceType != FILE_DEVICE_DISK) { // FIXME - accept floppies and CDs?
2854  WARN("device was not disk\n");
2855  ObDereferenceObject(fileobj);
2856  return STATUS_INVALID_PARAMETER;
2857  }
2858  } else {
2859  sdn.DeviceNumber = 0xffffffff;
2860  sdn.PartitionNumber = 0xffffffff;
2861  }
2862 
2864  &gli, sizeof(gli), true, NULL);
2865  if (!NT_SUCCESS(Status)) {
2866  ERR("error reading length information: %08lx\n", Status);
2867  ObDereferenceObject(fileobj);
2868  return Status;
2869  }
2870 
2871  size = gli.Length.QuadPart;
2872 
2873  if (size < 0x100000) {
2874  ERR("device was not large enough to hold FS (%I64x bytes, need at least 1 MB)\n", size);
2875  ObDereferenceObject(fileobj);
2876  return STATUS_INTERNAL_ERROR;
2877  }
2878 
2879  volume_removal(&pnp_name);
2880 
2881  ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
2882 
2883  if (Vcb->need_write)
2884  Status = do_write(Vcb, Irp);
2885  else
2887 
2888  free_trees(Vcb);
2889 
2890  if (!NT_SUCCESS(Status)) {
2891  ERR("do_write returned %08lx\n", Status);
2892  goto end;
2893  }
2894 
2896  if (!dev) {
2897  ERR("out of memory\n");
2899  goto end;
2900  }
2901 
2902  RtlZeroMemory(dev, sizeof(device));
2903 
2904  dev->devobj = DeviceObject;
2905  dev->fileobj = fileobj;
2906  dev->seeding = false;
2907  init_device(Vcb, dev, true);
2908 
2909  InitializeListHead(&dev->space);
2910 
2911  if (size > 0x100000) { // add disk hole - the first MB is marked as used
2912  Status = add_space_entry(&dev->space, NULL, 0x100000, size - 0x100000);
2913  if (!NT_SUCCESS(Status)) {
2914  ERR("add_space_entry returned %08lx\n", Status);
2915  goto end;
2916  }
2917  }
2918 
2919  dev_id = 0;
2920 
2921  le = Vcb->devices.Flink;
2922  while (le != &Vcb->devices) {
2923  device* dev2 = CONTAINING_RECORD(le, device, list_entry);
2924 
2925  if (dev2->devitem.dev_id > dev_id)
2926  dev_id = dev2->devitem.dev_id;
2927 
2928  le = le->Flink;
2929  }
2930 
2931  dev_id++;
2932 
2933  dev->devitem.dev_id = dev_id;
2934  dev->devitem.num_bytes = size;
2935  dev->devitem.bytes_used = 0;
2936  dev->devitem.optimal_io_align = Vcb->superblock.sector_size;
2937  dev->devitem.optimal_io_width = Vcb->superblock.sector_size;
2938  dev->devitem.minimal_io_size = Vcb->superblock.sector_size;
2939  dev->devitem.type = 0;
2940  dev->devitem.generation = 0;
2941  dev->devitem.start_offset = 0;
2942  dev->devitem.dev_group = 0;
2943  dev->devitem.seek_speed = 0;
2944  dev->devitem.bandwidth = 0;
2945  get_uuid(&dev->devitem.device_uuid);
2946  dev->devitem.fs_uuid = Vcb->superblock.uuid;
2947 
2949  if (!di) {
2950  ERR("out of memory\n");
2951  goto end;
2952  }
2953 
2954  RtlCopyMemory(di, &dev->devitem, sizeof(DEV_ITEM));
2955 
2956  Status = insert_tree_item(Vcb, Vcb->chunk_root, 1, TYPE_DEV_ITEM, di->dev_id, di, sizeof(DEV_ITEM), NULL, Irp);
2957  if (!NT_SUCCESS(Status)) {
2958  ERR("insert_tree_item returned %08lx\n", Status);
2959  ExFreePool(di);
2960  goto end;
2961  }
2962 
2963  // add stats entry to dev tree
2964  stats = ExAllocatePoolWithTag(PagedPool, sizeof(uint64_t) * 5, ALLOC_TAG);
2965  if (!stats) {
2966  ERR("out of memory\n");
2968  goto end;
2969  }
2970 
2971  RtlZeroMemory(stats, sizeof(uint64_t) * 5);
2972 
2973  searchkey.obj_id = 0;
2974  searchkey.obj_type = TYPE_DEV_STATS;
2975  searchkey.offset = di->dev_id;
2976 
2977  Status = find_item(Vcb, Vcb->dev_root, &tp, &searchkey, false, Irp);
2978  if (!NT_SUCCESS(Status)) {
2979  ERR("error - find_item returned %08lx\n", Status);
2980  ExFreePool(stats);
2981  goto end;
2982  }
2983 
2984  if (!keycmp(tp.item->key, searchkey)) {
2986  if (!NT_SUCCESS(Status)) {
2987  ERR("delete_tree_item returned %08lx\n", Status);
2988  ExFreePool(stats);
2989  goto end;
2990  }
2991  }
2992 
2993  Status = insert_tree_item(Vcb, Vcb->dev_root, 0, TYPE_DEV_STATS, di->dev_id, stats, sizeof(uint64_t) * 5, NULL, Irp);
2994  if (!NT_SUCCESS(Status)) {
2995  ERR("insert_tree_item returned %08lx\n", Status);
2996  ExFreePool(stats);
2997  goto end;
2998  }
2999 
3000  if (dev->trim && !dev->readonly && !Vcb->options.no_trim)
3002 
3003  // We clear the first megabyte of the device, so Windows doesn't identify it as another FS
3004  mb = ExAllocatePoolWithTag(PagedPool, 0x100000, ALLOC_TAG);
3005  if (!mb) {
3006  ERR("out of memory\n");
3008  goto end;
3009  }
3010 
3011  RtlZeroMemory(mb, 0x100000);
3012 
3013  Status = write_data_phys(DeviceObject, fileobj, 0, mb, 0x100000);
3014  if (!NT_SUCCESS(Status)) {
3015  ERR("write_data_phys returned %08lx\n", Status);
3016  ExFreePool(mb);
3017  goto end;
3018  }
3019 
3020  ExFreePool(mb);
3021 
3022  vde = Vcb->vde;
3023  pdode = vde->pdode;
3024 
3026  if (!vc) {
3027  ERR("out of memory\n");
3029  goto end;
3030  }
3031 
3032  vc->uuid = dev->devitem.device_uuid;
3033  vc->devid = dev_id;
3034  vc->generation = Vcb->superblock.generation;
3035  vc->devobj = DeviceObject;
3036  vc->fileobj = fileobj;
3037  vc->notification_entry = NULL;
3038  vc->boot_volume = false;
3039 
3041  drvobj, pnp_removal, vde->pdode, &vc->notification_entry);
3042  if (!NT_SUCCESS(Status))
3043  WARN("IoRegisterPlugPlayNotification returned %08lx\n", Status);
3044 
3045  pnp_name2 = pnp_name;
3046 
3047  if (pnp_name.Length > 4 * sizeof(WCHAR) && pnp_name.Buffer[0] == '\\' && (pnp_name.Buffer[1] == '\\' || pnp_name.Buffer[1] == '?') &&
3048  pnp_name.Buffer[2] == '?' && pnp_name.Buffer[3] == '\\') {
3049  pnp_name2.Buffer = &pnp_name2.Buffer[3];
3050  pnp_name2.Length -= 3 * sizeof(WCHAR);
3051  pnp_name2.MaximumLength -= 3 * sizeof(WCHAR);
3052  }
3053 
3054  vc->pnp_name.Length = vc->pnp_name.MaximumLength = pnp_name2.Length;
3055 
3056  if (pnp_name2.Length == 0)
3057  vc->pnp_name.Buffer = NULL;
3058  else {
3060  if (!vc->pnp_name.Buffer) {
3061  ERR("out of memory\n");
3063  goto end;
3064  }
3065 
3066  RtlCopyMemory(vc->pnp_name.Buffer, pnp_name2.Buffer, pnp_name2.Length);
3067  }
3068 
3069  vc->size = size;
3070  vc->seeding = false;
3071  vc->disk_num = sdn.DeviceNumber;
3072  vc->part_num = sdn.PartitionNumber;
3073  vc->had_drive_letter = false;
3074 
3076  InsertTailList(&pdode->children, &vc->list_entry);
3077  pdode->num_children++;
3078  pdode->children_loaded++;
3080 
3082  Status = IoGetDeviceObjectPointer(&mmdevpath, FILE_READ_ATTRIBUTES, &mountmgrfo, &mountmgr);
3083  if (!NT_SUCCESS(Status))
3084  ERR("IoGetDeviceObjectPointer returned %08lx\n", Status);
3085  else {
3086  Status = remove_drive_letter(mountmgr, &pnp_name);
3088  WARN("remove_drive_letter returned %08lx\n", Status);
3089 
3091 
3092  ObDereferenceObject(mountmgrfo);
3093  }
3094 
3095  Vcb->superblock.num_devices++;
3096  Vcb->superblock.total_bytes += size;
3097  Vcb->devices_loaded++;
3098  InsertTailList(&Vcb->devices, &dev->list_entry);
3099 
3100  // FIXME - send notification that volume size has increased
3101 
3102  ObReferenceObject(DeviceObject); // for Vcb
3103 
3104  Status = do_write(Vcb, Irp);
3105  if (!NT_SUCCESS(Status))
3106  ERR("do_write returned %08lx\n", Status);
3107 
3108  ObReferenceObject(fileobj);
3109 
3110 end:
3111  free_trees(Vcb);
3112 
3113  ExReleaseResourceLite(&Vcb->tree_lock);
3114 
3115 end2:
3116  ObDereferenceObject(fileobj);
3117 
3118  if (pnp_name.Buffer)
3119  ExFreePool(pnp_name.Buffer);
3120 
3121  if (NT_SUCCESS(Status))
3123 
3124  return Status;
3125 }
DEVICE_TYPE DeviceType
Definition: ntddstor.h:324
uint64_t obj_id
Definition: btrfs.h:144
bool boot_volume
Definition: btrfs_drv.h:858
#define TYPE_DEV_ITEM
Definition: btrfs.h:47
#define FILE_DEVICE_DISK
Definition: winioctl.h:113
return STATUS_NOT_SUPPORTED
#define STATUS_PRIVILEGE_NOT_HELD
Definition: DriverTester.h:9
UNICODE_STRING pnp_name
Definition: btrfs_drv.h:851
uint8_t obj_type
Definition: btrfs.h:145
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define TYPE_DEV_STATS
Definition: btrfs.h:50
NTSTATUS do_write(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7759
#define keycmp(key1, key2)
Definition: btrfs_drv.h:1008
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
#define IOCTL_DISK_IS_WRITABLE
Definition: cdrw_usr.h:172
NTSTATUS NTAPI IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName, IN ACCESS_MASK DesiredAccess, OUT PFILE_OBJECT *FileObject, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1435
ULONG part_num
Definition: btrfs_drv.h:857
#define InsertTailList(ListHead, Entry)
static void get_uuid(BTRFS_UUID *uuid)
Definition: fsctl.c:73
uint64_t offset
Definition: btrfs.h:146
#define MOUNTMGR_DEVICE_NAME
Definition: imports.h:76
static int dev
Definition: mkdosfs.c:536
void init_device(_In_ device_extension *Vcb, _Inout_ device *dev, _In_ bool get_nums)
Definition: btrfs.c:3385
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
BTRFS_UUID uuid
Definition: btrfs_drv.h:846
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
uint64_t num_children
Definition: btrfs_drv.h:886
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define ALLOC_TAG
Definition: btrfs_drv.h:87
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
_In_ PIRP Irp
Definition: csq.h:116
uint64_t generation
Definition: btrfs_drv.h:848
NTSTATUS add_space_entry(LIST_ENTRY *list, LIST_ENTRY *list_size, uint64_t offset, uint64_t size)
Definition: free-space.c:190
void volume_removal(PUNICODE_STRING devpath)
Definition: search.c:795
PDRIVER_OBJECT drvobj
Definition: btrfs.c:65
Definition: devices.h:37
bool seeding
Definition: btrfs_drv.h:853
PDEVICE_OBJECT devobj
Definition: btrfs_drv.h:849
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
#define IOCTL_STORAGE_GET_DEVICE_NUMBER
Definition: ntddstor.h:143
NTSTATUS insert_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_ uint64_t obj_id, _In_ uint8_t obj_type, _In_ uint64_t offset, _In_reads_bytes_opt_(size) _When_(return >=0, __drv_aliasesMem) void *data, _In_ uint16_t size, _Out_opt_ traverse_ptr *ptp, _In_opt_ PIRP Irp) __attribute__((nonnull(1
struct pdo_device_extension * pdode
Definition: btrfs_drv.h:870
static NTSTATUS is_device_part_of_mounted_btrfs_raid(PDEVICE_OBJECT devobj, PFILE_OBJECT fileobj)
Definition: fsctl.c:2633
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define IOCTL_DISK_GET_LENGTH_INFO
Definition: imports.h:192
#define FSRTL_VOLUME_CHANGE_SIZE
Definition: fsrtltypes.h:101
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2965
Status
Definition: gdiplustypes.h:24
void void void NTSTATUS void NTSTATUS NTSTATUS remove_drive_letter(PDEVICE_OBJECT mountmgr, PUNICODE_STRING devpath)
Definition: search.c:407
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define STATUS_NOT_FOUND
Definition: shellext.h:72
uint64_t children_loaded
Definition: btrfs_drv.h:887
NTSTATUS get_device_pnp_name(_In_ PDEVICE_OBJECT DeviceObject, _Out_ PUNICODE_STRING pnp_name, _Out_ const GUID **guid)
Definition: btrfs.c:4202
GLsizeiptr size
Definition: glext.h:5919
NTSTATUS NTAPI FsRtlNotifyVolumeEvent(IN PFILE_OBJECT FileObject, IN ULONG EventCode)
Definition: pnp.c:38
NTSTATUS write_data_phys(_In_ PDEVICE_OBJECT device, _In_ PFILE_OBJECT fileobj, _In_ uint64_t address, _In_reads_bytes_(length) void *data, _In_ uint32_t length)
Definition: flushthread.c:64
NTSTATUS find_item(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _Out_ traverse_ptr *tp, _In_ const KEY *searchkey, _In_ bool ignore, _In_opt_ PIRP Irp) __attribute__((nonnull(1
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
NTSTATUS dev_ioctl(_In_ PDEVICE_OBJECT DeviceObject, _In_ ULONG ControlCode, _In_reads_bytes_opt_(InputBufferSize) PVOID InputBuffer, _In_ ULONG InputBufferSize, _Out_writes_bytes_opt_(OutputBufferSize) PVOID OutputBuffer, _In_ ULONG OutputBufferSize, _In_ bool Override, _Out_opt_ IO_STATUS_BLOCK *iosb)
Definition: btrfs.c:2923
bool had_drive_letter
Definition: btrfs_drv.h:854
#define Vcb
Definition: cdprocs.h:1415
#define ObDereferenceObject
Definition: obfuncs.h:203
PVOID HANDLE
Definition: typedefs.h:73
ERESOURCE child_lock
Definition: btrfs_drv.h:888
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
void * notification_entry
Definition: btrfs_drv.h:855
* PFILE_OBJECT
Definition: iotypes.h:1998
ULONG disk_num
Definition: btrfs_drv.h:856
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
GLuint GLuint end
Definition: gl.h:1545
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
tree_data * item
Definition: btrfs_drv.h:502
PFILE_OBJECT fileobj
Definition: btrfs_drv.h:850
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:454
uint64_t dev_id
Definition: btrfs.h:178
#define LongToHandle(h)
Definition: basetsd.h:82
Definition: typedefs.h:119
POBJECT_TYPE IoFileObjectType
Definition: iomgr.c:36
BYTE uint8_t
Definition: msvideo1.c:66
LARGE_INTEGER Length
Definition: winioctl.h:560
NTSTATUS NTSTATUS bool bool void free_trees(device_extension *Vcb) __attribute__((nonnull(1)))
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:143
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793
#define SE_MANAGE_VOLUME_PRIVILEGE
Definition: security.c:682
UINT64 uint64_t
Definition: types.h:77
#define IOCTL_DISK_GET_DRIVE_LAYOUT_EX
Definition: ntddk_ex.h:207
NTSTATUS NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp) __attribute__((nonnull(1
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
Definition: list.h:27
DEV_ITEM devitem
Definition: btrfs_drv.h:520
#define NULL
Definition: types.h:112
uint64_t dev_id
UINT32 uint32_t
Definition: types.h:75
BOOLEAN NTAPI SeSinglePrivilegeCheck(_In_ LUID PrivilegeValue, _In_ KPROCESSOR_MODE PreviousMode)
Checks if a single privilege is present in the context of the calling thread.
Definition: priv.c:744
void trim_whole_device(device *dev)
Definition: fsctl.c:2712
uint64_t size
Definition: btrfs_drv.h:852
#define ObReferenceObject
Definition: obfuncs.h:204
LIST_ENTRY list_entry
Definition: btrfs_drv.h:859
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
NTSTATUS NTAPI IoRegisterPlugPlayNotification(_In_ IO_NOTIFICATION_EVENT_CATEGORY EventCategory, _In_ ULONG EventCategoryFlags, _In_opt_ PVOID EventCategoryData, _In_ PDRIVER_OBJECT DriverObject, _In_ PDRIVER_NOTIFICATION_CALLBACK_ROUTINE CallbackRoutine, _Inout_opt_ PVOID Context, _Out_ PVOID *NotificationEntry)
Definition: pnpnotify.c:345
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_SUCCESS
Definition: shellext.h:65
uint64_t devid
Definition: btrfs_drv.h:847
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3128
LIST_ENTRY children
Definition: btrfs_drv.h:889
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
LONGLONG QuadPart
Definition: typedefs.h:114
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70

Referenced by fsctl_request().

◆ allow_extended_dasd_io()

static NTSTATUS allow_extended_dasd_io ( device_extension Vcb,
PFILE_OBJECT  FileObject 
)
static

Definition at line 3127 of file fsctl.c.

3127  {
3128  fcb* fcb;
3129  ccb* ccb;
3130 
3131  TRACE("FSCTL_ALLOW_EXTENDED_DASD_IO\n");
3132 
3133  if (!FileObject)
3134  return STATUS_INVALID_PARAMETER;
3135 
3136  fcb = FileObject->FsContext;
3137  ccb = FileObject->FsContext2;
3138 
3139  if (!fcb)
3140  return STATUS_INVALID_PARAMETER;
3141 
3142  if (fcb != Vcb->volume_fcb)
3143  return STATUS_INVALID_PARAMETER;
3144 
3145  if (!ccb)
3146  return STATUS_INVALID_PARAMETER;
3147 
3148  ccb->allow_extended_dasd_io = true;
3149 
3150  return STATUS_SUCCESS;
3151 }
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:547
#define TRACE(s)
Definition: solgame.cpp:4
struct _fcb fcb
Definition: btrfs_drv.h:1355
#define Vcb
Definition: cdprocs.h:1415
bool allow_extended_dasd_io
Definition: btrfs_drv.h:380
#define STATUS_SUCCESS
Definition: shellext.h:65
struct _ccb ccb

Referenced by fsctl_request().

◆ check_inode_used()

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

Definition at line 3697 of file fsctl.c.

3698  {
3699  KEY searchkey;
3700  traverse_ptr tp;
3701  NTSTATUS Status;
3702  uint8_t c = hash >> 24;
3703 
3704  if (subvol->fcbs_ptrs[c]) {
3705  LIST_ENTRY* le = subvol->fcbs_ptrs[c];
3706 
3707  while (le != &subvol->fcbs) {
3708  struct _fcb* fcb2 = CONTAINING_RECORD(le, struct _fcb, list_entry);
3709 
3710  if (fcb2->inode == inode)
3711  return STATUS_SUCCESS;
3712  else if (fcb2->hash > hash)
3713  break;
3714 
3715  le = le->Flink;
3716  }
3717  }
3718 
3719  searchkey.obj_id = inode;
3720  searchkey.obj_type = TYPE_INODE_ITEM;
3721  searchkey.offset = 0xffffffffffffffff;
3722 
3723  Status = find_item(Vcb, subvol, &tp, &searchkey, false, Irp);
3724  if (!NT_SUCCESS(Status)) {
3725  ERR("find_item returned %08lx\n", Status);
3726  return Status;
3727  }
3728 
3729  if (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == searchkey.obj_type)
3730  return STATUS_SUCCESS;
3731 
3732  return STATUS_NOT_FOUND;
3733 }
uint64_t obj_id
Definition: btrfs.h:144
uint8_t obj_type
Definition: btrfs.h:145
LONG NTSTATUS
Definition: precomp.h:26
uint64_t offset
Definition: btrfs.h:146
Definition: fs.h:78
_In_ PIRP Irp
Definition: csq.h:116
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2965
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define STATUS_NOT_FOUND
Definition: shellext.h:72
NTSTATUS find_item(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _Out_ traverse_ptr *tp, _In_ const KEY *searchkey, _In_ bool ignore, _In_opt_ PIRP Irp) __attribute__((nonnull(1
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
uint64_t inode
Definition: btrfs_drv.h:289
#define Vcb
Definition: cdprocs.h:1415
const GLubyte * c
Definition: glext.h:8905
uint32_t hash
Definition: btrfs_drv.h:290
tree_data * item
Definition: btrfs_drv.h:502
#define TYPE_INODE_ITEM
Definition: btrfs.h:23
Definition: typedefs.h:119
BYTE uint8_t
Definition: msvideo1.c:66
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:143
struct _root * subvol
Definition: btrfs_drv.h:288
Definition: list.h:27
#define c
Definition: ke_i.h:80
#define STATUS_SUCCESS
Definition: shellext.h:65
Definition: _hash_fun.h:40

Referenced by mknod().

◆ create_snapshot()

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

Definition at line 521 of file fsctl.c.

521  {
522  PFILE_OBJECT subvol_obj;
525  fcb* subvol_fcb;
526  HANDLE subvolh;
527  bool readonly, posix;
528  ANSI_STRING utf8;
529  UNICODE_STRING nameus;
530  ULONG len;
531  fcb* fcb;
532  ccb* ccb;
533  file_ref *fileref, *fr2;
534 
535 #if defined(_WIN64)
536  if (IoIs32bitProcess(Irp)) {
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  Status = check_file_name_valid(&nameus, posix, false);
602  if (!NT_SUCCESS(Status))
603  return Status;
604 
605  utf8.Buffer = NULL;
606 
607  Status = utf16_to_utf8(NULL, 0, &len, nameus.Buffer, nameus.Length);
608  if (!NT_SUCCESS(Status)) {
609  ERR("utf16_to_utf8 failed with error %08lx\n", Status);
610  return Status;
611  }
612 
613  if (len == 0) {
614  ERR("utf16_to_utf8 returned a length of 0\n");
615  return STATUS_INTERNAL_ERROR;
616  }
617 
618  if (len > 0xffff) {
619  ERR("len was too long\n");
621  }
622 
623  utf8.MaximumLength = utf8.Length = (USHORT)len;
625 
626  if (!utf8.Buffer) {
627  ERR("out of memory\n");
629  }
630 
631  Status = utf16_to_utf8(utf8.Buffer, len, &len, nameus.Buffer, nameus.Length);
632  if (!NT_SUCCESS(Status)) {
633  ERR("utf16_to_utf8 failed with error %08lx\n", Status);
634  goto end2;
635  }
636 
637  ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
638 
639  // no need for fcb_lock as we have tree_lock exclusively
640  Status = open_fileref(fcb->Vcb, &fr2, &nameus, fileref, false, NULL, NULL, PagedPool, ccb->case_sensitive || posix, Irp);
641 
642  if (NT_SUCCESS(Status)) {
643  if (!fr2->deleted) {
644  WARN("file already exists\n");
645  free_fileref(fr2);
647  goto end3;
648  } else
649  free_fileref(fr2);
651  ERR("open_fileref returned %08lx\n", Status);
652  goto end3;
653  }
654 
655  Status = ObReferenceObjectByHandle(subvolh, 0, *IoFileObjectType, Irp->RequestorMode, (void**)&subvol_obj, NULL);
656  if (!NT_SUCCESS(Status)) {
657  ERR("ObReferenceObjectByHandle returned %08lx\n", Status);
658  goto end3;
659  }
660 
661  if (subvol_obj->DeviceObject != FileObject->DeviceObject) {
663  goto end;
664  }
665 
666  subvol_fcb = subvol_obj->FsContext;
667  if (!subvol_fcb) {
669  goto end;
670  }
671 
672  if (subvol_fcb->inode != subvol_fcb->subvol->root_item.objid) {
673  WARN("handle inode was %I64x, expected %I64x\n", subvol_fcb->inode, subvol_fcb->subvol->root_item.objid);
675  goto end;
676  }
677 
678  ccb = subvol_obj->FsContext2;
679 
680  if (!ccb) {
682  goto end;
683  }
684 
685  if (!(ccb->access & FILE_TRAVERSE)) {
686  WARN("insufficient privileges\n");
688  goto end;
689  }
690 
691  if (fcb == Vcb->dummy_fcb) {
693  goto end;
694  }
695 
696  // clear unique flag on extents of open files in subvol
697  if (!IsListEmpty(&subvol_fcb->subvol->fcbs)) {
698  LIST_ENTRY* le = subvol_fcb->subvol->fcbs.Flink;
699 
700  while (le != &subvol_fcb->subvol->fcbs) {
701  struct _fcb* openfcb = CONTAINING_RECORD(le, struct _fcb, list_entry);
702  LIST_ENTRY* le2;
703 
704  le2 = openfcb->extents.Flink;
705 
706  while (le2 != &openfcb->extents) {
708 
709  ext->unique = false;
710 
711  le2 = le2->Flink;
712  }
713 
714  le = le->Flink;
715  }
716  }
717 
718  Status = do_create_snapshot(Vcb, FileObject, subvol_fcb, &utf8, &nameus, readonly, Irp);
719 
720  if (NT_SUCCESS(Status)) {
721  file_ref* fr;
722 
723  Status = open_fileref(Vcb, &fr, &nameus, fileref, false, NULL, NULL, PagedPool, false, Irp);
724 
725  if (!NT_SUCCESS(Status)) {
726  ERR("open_fileref returned %08lx\n", Status);
728  } else {
730  free_fileref(fr);
731  }
732  }
733 
734 end:
735  ObDereferenceObject(subvol_obj);
736 
737 end3:
738  ExReleaseResourceLite(&Vcb->tree_lock);
739 
740 end2:
741  ExFreePool(utf8.Buffer);
742 
743  return Status;
744 }
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
ACCESS_MASK access
Definition: btrfs_drv.h:382
#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:1486
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define ALLOC_TAG
Definition: btrfs_drv.h:87
#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:494
_In_ PIRP Irp
Definition: csq.h:116
static __inline bool is_subvol_readonly(root *r, PIRP Irp)
Definition: btrfs_drv.h:1025
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:86
#define offsetof(TYPE, MEMBER)
char ext[3]
Definition: mkdosfs.c:358
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
static string utf16_to_utf8(const wstring_view &utf16)
Definition: main.cpp:670
uint8_t type
Definition: btrfs_drv.h:291
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:547
Status
Definition: gdiplustypes.h:24
bool deleted
Definition: btrfs_drv.h:347
USHORT MaximumLength
Definition: env_spec_w32.h:377
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
struct _fcb fcb
Definition: btrfs_drv.h:1355
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
uint64_t inode
Definition: btrfs_drv.h:289
#define Vcb
Definition: cdprocs.h:1415
#define ObDereferenceObject
Definition: obfuncs.h:203
struct _file_ref * fileref
Definition: btrfs_drv.h:305
LIST_ENTRY extents
Definition: btrfs_drv.h:300
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
* PFILE_OBJECT
Definition: iotypes.h:1998
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLuint GLuint end
Definition: gl.h:1545
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
bool case_sensitive
Definition: btrfs_drv.h:386
#define FILE_ADD_SUBDIRECTORY
Definition: nt_native.h:635
GLenum GLsizei len
Definition: glext.h:6722
Definition: typedefs.h:119
POBJECT_TYPE IoFileObjectType
Definition: iomgr.c:36
NTSTATUS open_fileref(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension *Vcb, _Out_ file_ref **pfr, _In_ PUNICODE_STRING fnus, _In_opt_ file_ref *related, _In_ bool parent, _Out_opt_ USHORT *parsed, _Out_opt_ ULONG *fn_offset, _In_ POOL_TYPE pooltype, _In_ bool case_sensitive, _In_opt_ PIRP Irp)
Definition: create.c:1690
void *POINTER_32 subvol
Definition: btrfsioctl.h:57
#define ERR(fmt,...)
Definition: debug.h:110
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
unsigned short USHORT
Definition: pedump.c:61
struct _root * subvol
Definition: btrfs_drv.h:288
Definition: list.h:27
#define NULL
Definition: types.h:112
void free_fileref(_Inout_ file_ref *fr)
Definition: btrfs.c:1825
#define FILE_ACTION_ADDED
Definition: name.c:38
unsigned int ULONG
Definition: retypes.h:1
static NTSTATUS do_create_snapshot(device_extension *Vcb, PFILE_OBJECT parent, fcb *subvol_fcb, PANSI_STRING utf8, PUNICODE_STRING name, bool readonly, PIRP Irp)
Definition: fsctl.c:260
#define STATUS_SUCCESS
Definition: shellext.h:65
struct _ccb ccb
file_ref * fileref
Definition: btrfs_drv.h:383
NTSTATUS check_file_name_valid(_In_ PUNICODE_STRING us, _In_ bool posix, _In_ bool stream)
Definition: btrfs.c:5766
struct _device_extension * Vcb
Definition: btrfs_drv.h:287
#define ExFreePool(addr)
Definition: env_spec_w32.h:352

Referenced by fsctl_request().

◆ create_subvol()

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

Definition at line 746 of file fsctl.c.

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

Referenced by fsctl_request().

◆ dismount_volume()

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

Definition at line 2580 of file fsctl.c.

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

Referenced by do_shutdown(), and fsctl_request().

◆ do_create_snapshot()

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

Definition at line 260 of file fsctl.c.

260  {
262  uint64_t id;
264  root *r, *subvol = subvol_fcb->subvol;
265  KEY searchkey;
267  uint64_t address, *root_num;
269  BTRFS_TIME now;
270  fcb* fcb = parent->FsContext;
271  ccb* ccb = parent->FsContext2;
272  LIST_ENTRY* le;
273  file_ref *fileref, *fr;
274  dir_child* dc = NULL;
275 
276  if (!ccb) {
277  ERR("error - ccb was NULL\n");
278  return STATUS_INTERNAL_ERROR;
279  }
280 
281  if (!(ccb->access & FILE_ADD_SUBDIRECTORY)) {
282  WARN("insufficient privileges\n");
283  return STATUS_ACCESS_DENIED;
284  }
285 
286  fileref = ccb->fileref;
287 
288  if (fileref->fcb == Vcb->dummy_fcb)
289  return STATUS_ACCESS_DENIED;
290 
291  // flush open files on this subvol
292 
294 
295  // flush metadata
296 
297  if (Vcb->need_write)
298  Status = do_write(Vcb, Irp);
299  else
301 
302  free_trees(Vcb);
303 
304  if (!NT_SUCCESS(Status)) {
305  ERR("do_write returned %08lx\n", Status);
306  return Status;
307  }
308 
310 
311  // create new root
312 
313  id = InterlockedIncrement64(&Vcb->root_root->lastinode);
314  Status = create_root(Vcb, id, &r, true, Vcb->superblock.generation, Irp);
315 
316  if (!NT_SUCCESS(Status)) {
317  ERR("create_root returned %08lx\n", Status);
318  goto end;
319  }
320 
321  r->lastinode = subvol->lastinode;
322 
323  if (!Vcb->uuid_root) {
324  root* uuid_root;
325 
326  TRACE("uuid root doesn't exist, creating it\n");
327 
328  Status = create_root(Vcb, BTRFS_ROOT_UUID, &uuid_root, false, 0, Irp);
329 
330  if (!NT_SUCCESS(Status)) {
331  ERR("create_root returned %08lx\n", Status);
332  goto end;
333  }
334 
335  Vcb->uuid_root = uuid_root;
336  }
337 
338  root_num = ExAllocatePoolWithTag(PagedPool, sizeof(uint64_t), ALLOC_TAG);
339  if (!root_num) {
340  ERR("out of memory\n");
342  goto end;
343  }
344 
345  tp.tree = NULL;
346 
347  do {
348  get_uuid(&r->root_item.uuid);
349 
350  RtlCopyMemory(&searchkey.obj_id, &r->root_item.uuid, sizeof(uint64_t));
351  searchkey.obj_type = TYPE_SUBVOL_UUID;
352  RtlCopyMemory(&searchkey.offset, &r->root_item.uuid.uuid[sizeof(uint64_t)], sizeof(uint64_t));
353 
354  Status = find_item(Vcb, Vcb->uuid_root, &tp, &searchkey, false, Irp);
355  } while (NT_SUCCESS(Status) && !keycmp(searchkey, tp.item->key));
356 
357  *root_num = r->id;
358 
359  Status = insert_tree_item(Vcb, Vcb->uuid_root, searchkey.obj_id, searchkey.obj_type, searchkey.offset, root_num, sizeof(uint64_t), NULL, Irp);
360  if (!NT_SUCCESS(Status)) {
361  ERR("insert_tree_item returned %08lx\n", Status);
362  ExFreePool(root_num);
363  goto end;
364  }
365 
366  searchkey.obj_id = r->id;
367  searchkey.obj_type = TYPE_ROOT_ITEM;
368  searchkey.offset = 0xffffffffffffffff;
369 
370  Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
371  if (!NT_SUCCESS(Status)) {
372  ERR("error - find_item returned %08lx\n", Status);
373  goto end;
374  }
375 
376  Status = snapshot_tree_copy(Vcb, subvol->root_item.block_number, r, &address, Irp, &rollback);
377  if (!NT_SUCCESS(Status)) {
378  ERR("snapshot_tree_copy returned %08lx\n", Status);
379  goto end;
380  }
381 
384 
385  r->root_item.inode.generation = 1;
386  r->root_item.inode.st_size = 3;
387  r->root_item.inode.st_blocks = subvol->root_item.inode.st_blocks;
388  r->root_item.inode.st_nlink = 1;
389  r->root_item.inode.st_mode = __S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; // 40755
390  r->root_item.inode.flags = 0x80000000; // FIXME - find out what these mean
391  r->root_item.inode.flags_ro = 0xffffffff; // FIXME - find out what these mean
392  r->root_item.generation = Vcb->superblock.generation;
393  r->root_item.objid = subvol->root_item.objid;
394  r->root_item.block_number = address;
395  r->root_item.bytes_used = subvol->root_item.bytes_used;
396  r->root_item.last_snapshot_generation = Vcb->superblock.generation;
397  r->root_item.root_level = subvol->root_item.root_level;
398  r->root_item.generation2 = Vcb->superblock.generation;
399  r->root_item.parent_uuid = subvol->root_item.uuid;
400  r->root_item.ctransid = subvol->root_item.ctransid;
401  r->root_item.otransid = Vcb->superblock.generation;
402  r->root_item.ctime = subvol->root_item.ctime;
403  r->root_item.otime = now;
404 
405  if (readonly)
406  r->root_item.flags |= BTRFS_SUBVOL_READONLY;
407 
408  r->treeholder.address = address;
409 
410  // FIXME - do we need to copy over the send and receive fields too?
411 
412  if (tp.item->key.obj_id != searchkey.obj_id || tp.item->key.obj_type != searchkey.obj_type) {
413  ERR("error - could not find ROOT_ITEM for subvol %I64x\n", r->id);
415  goto end;
416  }
417 
418  RtlCopyMemory(tp.item->data, &r->root_item, sizeof(ROOT_ITEM));
419 
420  // update ROOT_ITEM of original subvol
421 
422  subvol->root_item.last_snapshot_generation = Vcb->superblock.generation;
423 
425 
426  // create fileref for entry in other subvolume
427 
428  fr = create_fileref(Vcb);
429  if (!fr) {
430  ERR("out of memory\n");
432  goto end;
433  }
434 
435  Status = open_fcb(Vcb, r, r->root_item.objid, BTRFS_TYPE_DIRECTORY, utf8, false, fcb, &fr->fcb, PagedPool, Irp);
436  if (!NT_SUCCESS(Status)) {
437  ERR("open_fcb returned %08lx\n", Status);
438  free_fileref(fr);
439  goto end;
440  }
441 
442  fr->parent = fileref;
443 
444  Status = add_dir_child(fileref->fcb, r->id, true, utf8, name, BTRFS_TYPE_DIRECTORY, &dc);
445  if (!NT_SUCCESS(Status))
446  WARN("add_dir_child returned %08lx\n", Status);
447 
448  fr->dc = dc;
449  dc->fileref = fr;
450 
451  ExAcquireResourceExclusiveLite(&fileref->fcb->nonpaged->dir_children_lock, true);
452  InsertTailList(&fileref->children, &fr->list_entry);
453  ExReleaseResourceLite(&fileref->fcb->nonpaged->dir_children_lock);
454 
456 
457  fr->created = true;
458  mark_fileref_dirty(fr);
459 
460  if (fr->fcb->type == BTRFS_TYPE_DIRECTORY)
461  fr->fcb->fileref = fr;
462 
463  fr->fcb->subvol->parent = fileref->fcb->subvol->id;
464 
465  free_fileref(fr);
466 
467  // change fcb's INODE_ITEM
468 
469  fcb->inode_item.transid = Vcb->superblock.generation;
471  fcb->inode_item.st_size += utf8->Length * 2;
472 
475 
476  if (!ccb->user_set_write_time)
478 
479  fcb->inode_item_changed = true;
481 
482  fcb->subvol->root_item.ctime = now;
483  fcb->subvol->root_item.ctransid = Vcb->superblock.generation;
484 
487 
488  le = subvol->fcbs.Flink;
489  while (le != &subvol->fcbs) {
490  struct _fcb* fcb2 = CONTAINING_RECORD(le, struct _fcb, list_entry);
491  LIST_ENTRY* le2 = fcb2->extents.Flink;
492 
493  while (le2 != &fcb2->extents) {
495 
496  if (!ext->ignore)
497  ext->unique = false;
498 
499  le2 = le2->Flink;
500  }
501 
502  le = le->Flink;
503  }
504 
505  Status = do_write(Vcb, Irp);
506 
507  free_trees(Vcb);
508 
509  if (!NT_SUCCESS(Status))
510  ERR("do_write returned %08lx\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:352
uint64_t obj_id
Definition: btrfs.h:144
uint8_t obj_type
Definition: btrfs.h:145
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
static NTSTATUS snapshot_tree_copy(device_extension *Vcb, uint64_t addr, root *subvol, uint64_t *newaddr, PIRP Irp, LIST_ENTRY *rollback)
Definition: fsctl.c:87
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
NTSTATUS do_write(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7759
NTSTATUS open_fcb(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension *Vcb, root *subvol, uint64_t inode, uint8_t type, PANSI_STRING utf8, bool always_add_hl, fcb *parent, fcb **pfcb, POOL_TYPE pooltype, PIRP Irp)
Definition: create.c:706
#define keycmp(key1, key2)
Definition: btrfs_drv.h:1008
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
#define FILE_NOTIFY_CHANGE_LAST_WRITE
__u16 time
Definition: mkdosfs.c:366
ACCESS_MASK access
Definition: btrfs_drv.h:382
#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:1486
static void get_uuid(BTRFS_UUID *uuid)
Definition: fsctl.c:73
BTRFS_TIME st_ctime
Definition: btrfs.h:302
uint64_t offset
Definition: btrfs.h:146
uint8_t * data
Definition: btrfs_drv.h:415
bool user_set_write_time
Definition: btrfs_drv.h:389
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define ALLOC_TAG
Definition: btrfs_drv.h:87
NTSTATUS add_dir_child(fcb *fcb, uint64_t inode, bool subvol, PANSI_STRING utf8, PUNICODE_STRING name, uint8_t type, dir_child **pdc)
Definition: create.c:1871
void mark_fileref_dirty(_In_ file_ref *fileref)
Definition: btrfs.c:1686
file_ref * create_fileref(device_extension *Vcb)
Definition: create.c:160
tree * tree
Definition: btrfs_drv.h:501
_In_ PIRP Irp
Definition: csq.h:116
#define S_IRGRP
Definition: propsheet.h:41
#define S_IXOTH
Definition: propsheet.h:61
uint64_t sequence
Definition: btrfs.h:299
time_t now
Definition: finger.c:65
bool created
Definition: btrfs_drv.h:348
#define FILE_ACTION_MODIFIED
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:86
char ext[3]
Definition: mkdosfs.c:358
void mark_fcb_dirty(_In_ fcb *fcb)
Definition: btrfs.c:1664
NTSTATUS insert_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_ uint64_t obj_id, _In_ uint8_t obj_type, _In_ uint64_t offset, _In_reads_bytes_opt_(size) _When_(return >=0, __drv_aliasesMem) void *data, _In_ uint16_t size, _Out_opt_ traverse_ptr *ptp, _In_opt_ PIRP Irp) __attribute__((nonnull(1
uint8_t type
Definition: btrfs_drv.h:291
void flush_subvol_fcbs(root *subvol)
Definition: fsctl.c:243
BTRFS_TIME st_mtime
Definition: btrfs.h:303
#define increase_fileref_refcount(fileref)
Definition: btrfs_drv.h:1729
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2965
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define S_IXGRP
Definition: propsheet.h:49
uint64_t st_size
Definition: btrfs.h:289
#define TRACE(s)
Definition: solgame.cpp:4
#define S_IWUSR
Definition: propsheet.h:33
NTSTATUS find_item(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _Out_ traverse_ptr *tp, _In_ const KEY *searchkey, _In_ bool ignore, _In_opt_ PIRP Irp) __attribute__((nonnull(1
r parent
Definition: btrfs.c:2979
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define TYPE_SUBVOL_UUID
Definition: btrfs.h:51
bool user_set_change_time
Definition: btrfs_drv.h:390
#define Vcb
Definition: cdprocs.h:1415
NTSTATUS NTSTATUS void clear_rollback(LIST_ENTRY *rollback) __attribute__((nonnull(1)))
GLuint address
Definition: glext.h:9393
#define InterlockedIncrement64(a)
Definition: btrfs_drv.h:143
struct _file_ref * fileref
Definition: btrfs_drv.h:305
LIST_ENTRY extents
Definition: btrfs_drv.h:300
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
GLuint GLuint end
Definition: gl.h:1545
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
dir_child * dc
Definition: btrfs_drv.h:353
tree_data * item
Definition: btrfs_drv.h:502
#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:342
Definition: typedefs.h:119
void do_rollback(device_extension *Vcb, LIST_ENTRY *rollback) __attribute__((nonnull(1
INODE_ITEM inode_item
Definition: btrfs_drv.h:292
NTSTATUS create_root(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ uint64_t id, _Out_ root **rootptr, _In_ bool no_tree, _In_ uint64_t offset, _In_opt_ PIRP Irp)
Definition: btrfs.c:1240
NTSTATUS NTSTATUS bool bool void free_trees(device_extension *Vcb) __attribute__((nonnull(1)))
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:143
UINT64 uint64_t
Definition: types.h:77
#define BTRFS_ROOT_UUID
Definition: btrfs.h:61
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define TYPE_ROOT_ITEM
Definition: btrfs.h:32
uint64_t transid
Definition: btrfs.h:288
#define S_IRUSR
Definition: propsheet.h:29
static void mark_subvol_dirty(device_extension *Vcb, root *r)
Definition: fsctl.c:4104
struct _root * subvol
Definition: btrfs_drv.h:288
Definition: list.h:27
#define NULL
Definition: types.h:112
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: btrfs_drv.h:1355
void free_fileref(_Inout_ file_ref *fr)
Definition: btrfs.c:1825
#define FILE_ACTION_ADDED
#define __S_IFDIR
Definition: btrfs_drv.h:1744
Definition: name.c:38
static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME *out)
Definition: btrfs_drv.h:981
GLenum GLuint id
Definition: glext.h:5579
static const WCHAR dc[]
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_SUCCESS
Definition: shellext.h:65
file_ref * fileref
Definition: btrfs_drv.h:383
#define BTRFS_SUBVOL_READONLY
Definition: btrfs.h:109
bool inode_item_changed
Definition: btrfs_drv.h:306
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
LIST_ENTRY list_entry
Definition: btrfs_drv.h:357

Referenced by create_snapshot().

◆ do_unlock_volume()

void do_unlock_volume ( device_extension Vcb)

Definition at line 2322 of file fsctl.c.

2322  {
2323  KIRQL irql;
2324 
2326 
2327  Vcb->locked = false;
2328  Vcb->Vpb->Flags &= ~VPB_LOCKED;
2329  Vcb->locked_fileobj = NULL;
2330 
2332 
2333  if (Vcb->lock_paused_balance)
2334  KeSetEvent(&Vcb->balance.event, 0, false);
2335 }
VOID NTAPI IoAcquireVpbSpinLock(OUT PKIRQL Irql)
Definition: volume.c:1204
KIRQL irql
Definition: wave.h:1
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:1808
#define Vcb
Definition: cdprocs.h:1415
#define NULL
Definition: types.h:112
VOID NTAPI IoReleaseVpbSpinLock(IN KIRQL Irql)
Definition: volume.c:1215

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

3258  {
3260  fcb *fcb = FileObject ? FileObject->FsContext : NULL, *sourcefcb;
3261  ccb *ccb = FileObject ? FileObject->FsContext2 : NULL, *sourceccb;
3262  NTSTATUS Status;
3263  PFILE_OBJECT sourcefo;
3264  uint64_t sourcelen, nbytes = 0;
3265  LIST_ENTRY rollback, *le, newexts;
3267  BTRFS_TIME now;
3268  bool make_inline;
3269 
3270  if (!ded || datalen < sizeof(DUPLICATE_EXTENTS_DATA))
3271  return STATUS_BUFFER_TOO_SMALL;
3272 
3273  if (Vcb->readonly)
3275 
3276  if (ded->ByteCount.QuadPart == 0)
3277  return STATUS_SUCCESS;
3278 
3279  if (!fcb || !ccb || fcb == Vcb->volume_fcb)
3280  return STATUS_INVALID_PARAMETER;
3281 
3283  return STATUS_ACCESS_DENIED;
3284 
3285  if (Irp->RequestorMode == UserMode && !(ccb->access & FILE_WRITE_DATA)) {
3286  WARN("insufficient privileges\n");
3287  return STATUS_ACCESS_DENIED;
3288  }
3289 
3290  if (!fcb->ads && fcb->type != BTRFS_TYPE_FILE && fcb->type != BTRFS_TYPE_SYMLINK)
3291  return STATUS_INVALID_PARAMETER;
3292 
3293  Status = ObReferenceObjectByHandle(ded->FileHandle, 0, *IoFileObjectType, Irp->RequestorMode, (void**)&sourcefo, NULL);
3294  if (!NT_SUCCESS(Status)) {
3295  ERR("ObReferenceObjectByHandle returned %08lx\n", Status);
3296  return Status;
3297  }
3298 
3299  if (sourcefo->DeviceObject != FileObject->DeviceObject) {
3300  WARN("source and destination are on different volumes\n");
3301  ObDereferenceObject(sourcefo);
3302  return STATUS_INVALID_PARAMETER;
3303  }
3304 
3305  sourcefcb = sourcefo->FsContext;
3306  sourceccb = sourcefo->FsContext2;
3307 
3308  if (!sourcefcb || !sourceccb || sourcefcb == Vcb->volume_fcb) {
3309  ObDereferenceObject(sourcefo);
3310  return STATUS_INVALID_PARAMETER;
3311  }
3312 
3313  if (!sourcefcb->ads && !fcb->ads) {
3314  if ((ded->SourceFileOffset.QuadPart & (Vcb->superblock.sector_size - 1)) || (ded->TargetFileOffset.QuadPart & (Vcb->superblock.sector_size - 1))) {
3315  ObDereferenceObject(sourcefo);
3316  return STATUS_INVALID_PARAMETER;
3317  }
3318 
3319  if (ded->ByteCount.QuadPart & (Vcb->superblock.sector_size - 1)) {
3320  ObDereferenceObject(sourcefo);
3321  return STATUS_INVALID_PARAMETER;
3322  }
3323  }
3324 
3325  if (Irp->RequestorMode == UserMode && (!(sourceccb->access & FILE_READ_DATA) || !(sourceccb->access & FILE_READ_ATTRIBUTES))) {
3326  WARN("insufficient privileges\n");
3327  ObDereferenceObject(sourcefo);
3328  return STATUS_ACCESS_DENIED;
3329  }
3330 
3331  if (!sourcefcb->ads && sourcefcb->type != BTRFS_TYPE_FILE && sourcefcb->type != BTRFS_TYPE_SYMLINK) {
3332  ObDereferenceObject(sourcefo);
3333  return STATUS_INVALID_PARAMETER;
3334  }
3335 
3336  sourcelen = sourcefcb->ads ? sourcefcb->adsdata.Length : sourcefcb->inode_item.st_size;
3337 
3338  if (sector_align(sourcelen, Vcb->superblock.sector_size) < (uint64_t)ded->SourceFileOffset.QuadPart + (uint64_t)ded->ByteCount.QuadPart) {
3339  ObDereferenceObject(sourcefo);
3340  return STATUS_NOT_SUPPORTED;
3341  }
3342 
3343  if (fcb == sourcefcb &&
3346  WARN("source and destination are the same, and the ranges overlap\n");
3347  ObDereferenceObject(sourcefo);
3348  return STATUS_INVALID_PARAMETER;
3349  }
3350 
3351  // fail if nocsum flag set on one file but not the other
3352  if (!fcb->ads && !sourcefcb->ads && (fcb->inode_item.flags & BTRFS_INODE_NODATASUM) != (sourcefcb->inode_item.flags & BTRFS_INODE_NODATASUM)) {
3353  ObDereferenceObject(sourcefo);
3354  return STATUS_INVALID_PARAMETER;
3355  }
3356 
3358  InitializeListHead(&newexts);
3359 
3360  ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
3361 
3362  ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
3363 
3364  if (fcb != sourcefcb)
3365  ExAcquireResourceSharedLite(sourcefcb->Header.Resource, true);
3366 
3369  goto end;
3370  }
3371 
3372  if (!FsRtlFastCheckLockForRead(&sourcefcb->lock, &ded->SourceFileOffset, &ded->ByteCount, 0, FileObject, PsGetCurrentProcess())) {
3374  goto end;
3375  }
3376 
3377  make_inline = fcb->ads ? false : (fcb->inode_item.st_size <= Vcb->options.max_inline || fcb_is_inline(fcb));
3378 
3379  if (fcb->ads || sourcefcb->ads || make_inline || fcb_is_inline(sourcefcb)) {
3380  uint8_t* data2;
3381  ULONG bytes_read, dataoff, datalen2;
3382 
3383  if (make_inline) {
3384  dataoff = (ULONG)ded->TargetFileOffset.QuadPart;
3385  datalen2 = (ULONG)fcb->inode_item.st_size;
3386  } else if (fcb->ads) {
3387  dataoff = 0;
3388  datalen2 = (ULONG)ded->ByteCount.QuadPart;
3389  } else {
3390  dataoff = ded->TargetFileOffset.QuadPart & (Vcb->superblock.sector_size - 1);
3391  datalen2 = (ULONG)sector_align(ded->ByteCount.QuadPart + dataoff, Vcb->superblock.sector_size);
3392  }
3393 
3395  if (!data2) {
3396  ERR("out of memory\n");
3398  goto end;
3399  }
3400 
3401  if (dataoff > 0) {
3402  if (make_inline)
3403  Status = read_file(fcb, data2, 0, datalen2, NULL, Irp);
3404  else
3405  Status = read_file(fcb, data2, ded->TargetFileOffset.QuadPart - dataoff, dataoff, NULL, Irp);
3406 
3407  if (!NT_SUCCESS(Status)) {
3408  ERR("read_file returned %08lx\n", Status);
3409  ExFreePool(data2);
3410  goto end;
3411  }
3412  }
3413 
3414  if (sourcefcb->ads) {
3415  Status = read_stream(sourcefcb, data2 + dataoff, ded->SourceFileOffset.QuadPart, (ULONG)ded->ByteCount.QuadPart, &bytes_read);
3416  if (!NT_SUCCESS(Status)) {
3417  ERR("read_stream returned %08lx\n", Status);
3418  ExFreePool(data2);
3419  goto end;
3420  }
3421  } else {
3422  Status = read_file(sourcefcb, data2 + dataoff, ded->SourceFileOffset.QuadPart, ded->ByteCount.QuadPart, &bytes_read, Irp);
3423  if (!NT_SUCCESS(Status)) {
3424  ERR("read_file returned %08lx\n", Status);
3425  ExFreePool(data2);
3426  goto end;
3427  }
3428  }
3429 
3430  if (dataoff + bytes_read < datalen2)
3431  RtlZeroMemory(data2 + dataoff + bytes_read, datalen2 - bytes_read);
3432 
3433  if (fcb->ads)
3435  else if (make_inline) {
3436  uint16_t edsize;
3437  EXTENT_DATA* ed;
3438 
3439  Status = excise_extents(Vcb, fcb, 0, sector_align(fcb->inode_item.st_size, Vcb->superblock.sector_size), Irp, &rollback);
3440  if (!NT_SUCCESS(Status)) {
3441  ERR("excise_extents returned %08lx\n", Status);
3442  ExFreePool(data2);
3443  goto end;
3444  }
3445 
3446  edsize = (uint16_t)(offsetof(EXTENT_DATA, data[0]) + datalen2);
3447 
3448  ed = ExAllocatePoolWithTag(PagedPool, edsize, ALLOC_TAG);
3449  if (!ed) {
3450  ERR("out of memory\n");
3451  ExFreePool(data2);
3453  goto end;
3454  }
3455 
3456  ed->generation = Vcb->superblock.generation;
3461  ed->type = EXTENT_TYPE_INLINE;
3462 
3463  RtlCopyMemory(ed->data, data2, datalen2);
3464 
3465  Status = add_extent_to_fcb(fcb, 0, ed, edsize, false, NULL, &rollback);
3466  if (!NT_SUCCESS(Status)) {
3467  ERR("add_extent_to_fcb returned %08lx\n", Status);
3468  ExFreePool(data2);
3469  goto end;
3470  }
3471 
3472  fcb->inode_item.st_blocks += datalen2;
3473  } else {
3474  uint64_t start = ded->TargetFileOffset.QuadPart - (ded->TargetFileOffset.QuadPart & (Vcb->superblock.sector_size - 1));
3475 
3476  Status = do_write_file(fcb, start, start + datalen2, data2, Irp, false, 0, &rollback);
3477  if (!NT_SUCCESS(Status)) {
3478  ERR("do_write_file returned %08lx\n", Status);
3479  ExFreePool(data2);
3480  goto end;
3481  }
3482  }
3483 
3484  ExFreePool(data2);
3485  } else {
3486  LIST_ENTRY* lastextle;
3487 
3488  le = sourcefcb->extents.Flink;
3489  while (le != &sourcefcb->extents) {
3491 
3492  if (!ext->ignore) {
3493  if (ext->offset >= (uint64_t)ded->SourceFileOffset.QuadPart + (uint64_t)ded->ByteCount.QuadPart)
3494  break;
3495 
3496  if (ext->extent_data.type != EXTENT_TYPE_INLINE) {
3497  ULONG extlen = offsetof(extent, extent_data) + sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2);
3498  extent* ext2;
3499  EXTENT_DATA2 *ed2s, *ed2d;
3500  chunk* c;
3501 
3502  ed2s = (EXTENT_DATA2*)ext->extent_data.data;
3503 
3504  if (ext->offset + ed2s->num_bytes <= (uint64_t)ded->SourceFileOffset.QuadPart) {
3505  le = le->Flink;
3506  continue;
3507  }
3508 
3510  if (!ext2) {
3511  ERR("out of memory\n");
3513  goto end;
3514  }
3515 
3516  if (ext->offset < (uint64_t)ded->SourceFileOffset.QuadPart)
3517  ext2->offset = ded->TargetFileOffset.QuadPart;
3518  else
3519  ext2->offset = ext->offset - ded->SourceFileOffset.QuadPart + ded->TargetFileOffset.QuadPart;
3520 
3521  ext2->datalen = sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2);
3522  ext2->unique = false;
3523  ext2->ignore = false;
3524  ext2->inserted = true;
3525 
3526  ext2->extent_data.generation = Vcb->superblock.generation;
3527  ext2->extent_data.decoded_size = ext->extent_data.decoded_size;
3528  ext2->extent_data.compression = ext->extent_data.compression;
3529  ext2->extent_data.encryption = ext->extent_data.encryption;
3530  ext2->extent_data.encoding = ext->extent_data.encoding;
3531  ext2->extent_data.type = ext->extent_data.type;
3532 
3533  ed2d = (EXTENT_DATA2*)ext2->extent_data.data;
3534 
3535  ed2d->address = ed2s->address;
3536  ed2d->size = ed2s->size;
3537 
3538  if (ext->offset < (uint64_t)ded->SourceFileOffset.QuadPart) {
3539  ed2d->offset = ed2s->offset + ded->SourceFileOffset.QuadPart - ext->offset;
3540  ed2d->num_bytes = min((uint64_t)ded->ByteCount.QuadPart, ed2s->num_bytes + ext->offset - ded->SourceFileOffset.QuadPart);
3541  } else {
3542  ed2d->offset = ed2s->offset;
3543  ed2d->num_bytes = min(ded->SourceFileOffset.QuadPart + ded->ByteCount.QuadPart - ext->offset, ed2s->num_bytes);
3544  }
3545 
3546  if (ext->csum) {
3547  if (ext->extent_data.compression == BTRFS_COMPRESSION_NONE) {
3548  ext2->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)((ed2d->num_bytes * Vcb->csum_size) >> Vcb->sector_shift), ALLOC_TAG);
3549  if (!ext2->csum) {
3550  ERR("out of memory\n");
3552  ExFreePool(ext2);
3553  goto end;
3554  }
3555 
3556  RtlCopyMemory(ext2->csum, (uint8_t*)ext->csum + (((ed2d->offset - ed2s->offset) * Vcb->csum_size) >> Vcb->sector_shift),
3557  (ULONG)((ed2d->num_bytes * Vcb->csum_size) >> Vcb->sector_shift));
3558  } else {
3559  ext2->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)((ed2d->size * Vcb->csum_size) >> Vcb->sector_shift), ALLOC_TAG);
3560  if (!ext2->csum) {
3561  ERR("out of memory\n");
3563  ExFreePool(ext2);
3564  goto end;
3565  }
3566 
3567  RtlCopyMemory(ext2->csum, ext->csum, (ULONG)((ed2s->size * Vcb->csum_size) >> Vcb->sector_shift));
3568  }
3569  } else
3570  ext2->csum = NULL;
3571 
3572  InsertTailList(&newexts, &ext2->list_entry);
3573 
3574  c = get_chunk_from_address(Vcb, ed2s->address);
3575  if (!c) {
3576  ERR("get_chunk_from_address(%I64x) failed\n", ed2s->address);
3578  goto end;
3579  }
3580 
3581  Status = update_changed_extent_ref(Vcb, c, ed2s->address, ed2s->size, fcb->subvol->id, fcb->inode, ext2->offset - ed2d->offset,
3582  1, fcb->inode_item.flags & BTRFS_INODE_NODATASUM, false, Irp);
3583  if (!NT_SUCCESS(Status)) {
3584  ERR("update_changed_extent_ref returned %08lx\n", Status);
3585  goto end;
3586  }
3587 
3588  nbytes += ed2d->num_bytes;
3589  }
3590  }
3591 
3592  le = le->Flink;
3593  }
3594 
3596  if (!NT_SUCCESS(Status)) {
3597  ERR("excise_extents returned %08lx\n", Status);
3598 
3599  while (!IsListEmpty(&newexts)) {
3601  ExFreePool(ext);
3602  }
3603 
3604  goto end;
3605  }
3606 
3607  // clear unique flags in source fcb
3608  le = sourcefcb->extents.Flink;
3609  while (le != &sourcefcb->extents) {
3611 
3612  if (!ext->ignore && ext->unique && (ext->extent_data.type == EXTENT_TYPE_REGULAR || ext->extent_data.type == EXTENT_TYPE_PREALLOC)) {
3613  EXTENT_DATA2* ed2s = (EXTENT_DATA2*)ext->extent_data.data;
3614  LIST_ENTRY* le2;
3615 
3616  le2 = newexts.Flink;
3617  while (le2 != &newexts) {
3619 
3620  if (ext2->extent_data.type == EXTENT_TYPE_REGULAR || ext2->extent_data.type == EXTENT_TYPE_PREALLOC) {
3621  EXTENT_DATA2* ed2d = (EXTENT_DATA2*)ext2->extent_data.data;
3622 
3623  if (ed2d->address == ed2s->address && ed2d->size == ed2s->size) {
3624  ext->unique = false;
3625  break;
3626  }
3627  }
3628 
3629  le2 = le2->Flink;
3630  }
3631  }
3632 
3633  le = le->Flink;
3634  }
3635 
3636  lastextle = &fcb->extents;
3637  while (!IsListEmpty(&newexts)) {
3639 
3640  add_extent(fcb, lastextle, ext);
3641  lastextle = &ext->list_entry;
3642  }
3643  }
3644 
3647 
3648  if (fcb->ads) {
3649  ccb->fileref->parent->fcb->inode_item.sequence++;
3650 
3651  if (!ccb->user_set_change_time)
3652  ccb->fileref->parent->fcb->inode_item.st_ctime = now;
3653 
3654  ccb->fileref->parent->fcb->inode_item_changed = true;
3655  mark_fcb_dirty(ccb->fileref->parent->fcb);
3656  } else {
3657  fcb->inode_item.st_blocks += nbytes;
3658  fcb->inode_item.sequence++;
3659 
3660  if (!ccb->user_set_change_time)
3662 
3663  if (!ccb->user_set_write_time) {
3666  }
3667 
3668  fcb->inode_item_changed = true;
3669  fcb->extents_changed = true;
3670  }
3671 
3673 
3674  if (FileObject->SectionObjectPointer->DataSectionObject)
3675  CcPurgeCacheSection(FileObject->SectionObjectPointer, &ded->TargetFileOffset, (ULONG)ded->ByteCount.QuadPart, false);
3676 
3678 
3679 end:
3680  ObDereferenceObject(sourcefo);
3681 
3682  if (NT_SUCCESS(Status))
3684  else
3686 
3687  if (fcb != sourcefcb)
3688  ExReleaseResourceLite(sourcefcb->Header.Resource);
3689 
3690  ExReleaseResourceLite(fcb->Header.Resource);
3691 
3692  ExReleaseResourceLite(&Vcb->tree_lock);
3693 
3694  return Status;
3695 }
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
uint64_t generation
Definition: btrfs.h:358
struct _file_ref * parent
Definition: btrfs_drv.h:352
NTSTATUS do_write_file(fcb *fcb, uint64_t start_data, uint64_t end_data, void *data, PIRP Irp, bool file_write, uint32_t irp_offset, LIST_ENTRY *rollback) __attribute__((nonnull(1
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
BOOLEAN NTAPI CcPurgeCacheSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN UninitializeCacheMaps)
Definition: fssup.c:386
return STATUS_NOT_SUPPORTED
uint8_t type
Definition: btrfs.h:363
#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:748
NTSTATUS update_changed_extent_ref(device_extension *Vcb, chunk *c, uint64_t address, uint64_t size, uint64_t root, uint64_t objid, uint64_t offset, int32_t count, bool no_csum, bool superseded, PIRP Irp)
Definition: extent-tree.c:1951
#define BTRFS_COMPRESSION_NONE
Definition: btrfs.h:65
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
uint64_t decoded_size
Definition: btrfs.h:359
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS read_file(fcb *fcb, uint8_t *data, uint64_t start, uint64_t length, ULONG *pbr, PIRP Irp) __attribute__((nonnull(1
#define FILE_NOTIFY_CHANGE_LAST_WRITE
__u16 time
Definition: mkdosfs.c:366
ACCESS_MASK access
Definition: btrfs_drv.h:382
unsigned short int uint16_t
Definition: acefiex.h:54
#define uint16_t
Definition: nsiface.idl:60
#define InsertTailList(ListHead, Entry)
uint32_t flags
Definition: btrfs.h:297
if(dx==0 &&dy==0)
Definition: linetemp.h:174
int const JOCTET unsigned int datalen
Definition: jpeglib.h:1030
BTRFS_TIME st_ctime
Definition: btrfs.h:302
uint8_t encryption
Definition: btrfs.h:361
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
bool user_set_write_time
Definition: btrfs_drv.h:389
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define ALLOC_TAG
Definition: btrfs_drv.h:87
#define EXTENT_TYPE_INLINE
Definition: btrfs.h:74
void queue_notification_fcb(_In_ file_ref *fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream)
Definition: btrfs.c:1636
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
_In_ PIRP Irp
Definition: csq.h:116
static __inline bool is_subvol_readonly(root *r, PIRP Irp)
Definition: btrfs_drv.h:1025
uint64_t address
Definition: btrfs.h:368
uint64_t sequence
Definition: btrfs.h:299
time_t now
Definition: finger.c:65
#define FILE_READ_DATA
Definition: nt_native.h:628
bool extents_changed
Definition: btrfs_drv.h:323
#define FILE_ACTION_MODIFIED
#define PsGetCurrentProcess
Definition: psfuncs.h:17
#define BTRFS_ENCODING_NONE
Definition: btrfs.h:72
#define offsetof(TYPE, MEMBER)
char ext[3]
Definition: mkdosfs.c:358
void mark_fcb_dirty(_In_ fcb *fcb)
Definition: btrfs.c:1664
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
uint64_t size
Definition: btrfs.h:369
uint8_t type
Definition: btrfs_drv.h:291
BTRFS_TIME st_mtime
Definition: btrfs.h:303
#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
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:547
FILE_LOCK lock
Definition: btrfs_drv.h:294
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:283
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
LARGE_INTEGER SourceFileOffset
Definition: shellext.h:200
uint16_t encoding
Definition: btrfs.h:362
#define BTRFS_ENCRYPTION_NONE
Definition: btrfs.h:70
uint64_t st_size
Definition: btrfs.h:289
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
uint64_t inode
Definition: btrfs_drv.h:289
#define BTRFS_INODE_NODATASUM
Definition: propsheet.h:76
bool user_set_change_time
Definition: btrfs_drv.h:390
#define Vcb
Definition: cdprocs.h:1415
#define ObDereferenceObject
Definition: obfuncs.h:203
const GLubyte * c
Definition: glext.h:8905
NTSTATUS NTSTATUS void clear_rollback(LIST_ENTRY *rollback) __attribute__((nonnull(1)))
LIST_ENTRY extents
Definition: btrfs_drv.h:300
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
* PFILE_OBJECT
Definition: iotypes.h:1998
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
GLuint GLuint end
Definition: gl.h:1545
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
static const BYTE ext2[]
Definition: encode.c:2699
NTSTATUS bool void NTSTATUS add_extent_to_fcb(_In_ fcb *fcb, _In_ uint64_t offset, _In_reads_bytes_(edsize) EXTENT_DATA *ed, _In_ uint16_t edsize, _In_ bool unique, _In_opt_ _When_(return >=0, __drv_aliasesMem) void *csum, _In_ LIST_ENTRY *rollback) __attribute__((nonnull(1
Definition: stddef.h:5
Definition: typedefs.h:119
void do_rollback(device_extension *Vcb, LIST_ENTRY *rollback) __attribute__((nonnull(1
#define EXTENT_TYPE_PREALLOC
Definition: btrfs.h:76
INODE_ITEM inode_item
Definition: btrfs_drv.h:292
POBJECT_TYPE IoFileObjectType
Definition: iomgr.c:36
BYTE uint8_t
Definition: msvideo1.c:66
uint64_t num_bytes
Definition: btrfs.h:371
uint64_t st_blocks
Definition: btrfs.h:290
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:75
#define ERR(fmt,...)
Definition: debug.h:110
uint8_t data[1]
Definition: btrfs.h:364
NTSTATUS NTSTATUS NTSTATUS NTSTATUS NTSTATUS excise_extents(device_extension *Vcb, fcb *fcb, uint64_t start_data, uint64_t end_data, PIRP Irp, LIST_ENTRY *rollback) __attribute__((nonnull(1
UINT64 uint64_t
Definition: types.h:77
static const WCHAR data2[]
Definition: db.c:2892
unsigned short USHORT
Definition: pedump.c:61
GLuint start
Definition: gl.h:1545
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
struct _root * subvol
Definition: btrfs_drv.h:288
#define min(a, b)
Definition: monoChain.cc:55
Definition: list.h:27
#define NULL
Definition: types.h:112
ANSI_STRING adsdata
Definition: btrfs_drv.h:334
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: btrfs_drv.h:1355
bool fcb_is_inline(fcb *fcb)
Definition: fsctl.c:3242
LARGE_INTEGER TargetFileOffset
Definition: shellext.h:201
HRESULT read_stream(BSCallback *, IStream *, void *, DWORD, DWORD *) DECLSPEC_HIDDEN
Definition: navigate.c:602
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
#define BTRFS_TYPE_FILE
Definition: shellext.h:85
bool ads
Definition: btrfs_drv.h:330
#define STATUS_FILE_LOCK_CONFLICT
Definition: ntstatus.h:320
NTSTATUS bool void NTSTATUS void add_extent(_In_ fcb *fcb, _In_ LIST_ENTRY *prevextle, _In_ __drv_aliasesMem extent *newext) __attribute__((nonnull(1
static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME *out)
Definition: btrfs_drv.h:981
#define c
Definition: ke_i.h:80
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint64_t offset
Definition: btrfs.h:370
#define STATUS_SUCCESS
Definition: shellext.h:65
file_ref * fileref
Definition: btrfs_drv.h:383
bool inode_item_changed
Definition: btrfs_drv.h:306
BOOLEAN NTAPI FsRtlFastCheckLockForWrite(IN PFILE_LOCK FileLock, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, IN ULONG Key, IN PFILE_OBJECT FileObject, IN PVOID Process)
Definition: filelock.c:782
static uint64_t __inline sector_align(uint64_t n, uint64_t a)
LARGE_INTEGER ByteCount
Definition: shellext.h:202
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
uint8_t compression
Definition: btrfs.h:360
NTSTATUS NTSTATUS NTSTATUS NTSTATUS NTSTATUS chunk * get_chunk_from_address(device_extension *Vcb, uint64_t address) __attribute__((nonnull(1)))
LONGLONG QuadPart
Definition: typedefs.h:114
#define BTRFS_TYPE_SYMLINK
Definition: shellext.h:91
Definition: tftpd.h:137

Referenced by fsctl_request().

◆ fcb_is_inline()

bool fcb_is_inline ( fcb fcb)

Definition at line 3242 of file fsctl.c.

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

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

◆ find_subvol()

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

Definition at line 4582 of file fsctl.c.

4582  {
4583  btrfs_find_subvol* bfs;
4584  NTSTATUS Status;
4585  traverse_ptr tp;
4586  KEY searchkey;
4587 
4588  if (!in || inlen < sizeof(btrfs_find_subvol))
4589  return STATUS_INVALID_PARAMETER;
4590 
4591  if (!out || outlen < sizeof(WCHAR))
4592  return STATUS_INVALID_PARAMETER;
4593 
4594  if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), Irp->RequestorMode))
4596 
4597  bfs = (btrfs_find_subvol*)in;
4598 
4599  ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
4600 
4601  if (!Vcb->uuid_root) {
4602  ERR("couldn't find uuid root\n");
4604  goto end;
4605  }
4606 
4607  RtlCopyMemory(&searchkey.obj_id, &bfs->uuid, sizeof(uint64_t));
4608  searchkey.obj_type = TYPE_SUBVOL_UUID;
4609  RtlCopyMemory(&searchkey.offset, &bfs->uuid.uuid[sizeof(uint64_t)], sizeof(uint64_t));
4610 
4611  Status = find_item(Vcb, Vcb->uuid_root, &tp, &searchkey, false, Irp);
4612 
4613  if (!NT_SUCCESS(Status)) {
4614  ERR("find_item returned %08lx\n", Status);
4615  goto end;
4616  }
4617 
4618  if (!keycmp(searchkey, tp.item->key) && tp.item->size >= sizeof(uint64_t)) {
4619  uint64_t* id = (uint64_t*)tp.item->data;
4620 
4621  if (bfs->ctransid != 0) {
4622  KEY searchkey2;
4623  traverse_ptr tp2;
4624 
4625  searchkey2.obj_id = *id;
4626  searchkey2.obj_type = TYPE_ROOT_ITEM;
4627  searchkey2.offset = 0xffffffffffffffff;
4628 
4629  Status = find_item(Vcb, Vcb->root_root, &tp2, &searchkey2, false, Irp);
4630  if (!NT_SUCCESS(Status)) {
4631  ERR("find_item returned %08lx\n", Status);
4632  goto end;
4633  }
4634 
4635  if (tp2.item->key.obj_id == searchkey2.obj_id && tp2.item->key.obj_type == searchkey2.obj_type &&
4636  tp2.item->size >= offsetof(ROOT_ITEM, otransid)) {
4637  ROOT_ITEM* ri = (ROOT_ITEM*)tp2.item->data;
4638 
4639  if (ri->ctransid == bfs->ctransid) {
4640  TRACE("found subvol %I64x\n", *id);
4641  Status = get_subvol_path(Vcb, *id, out, outlen, Irp);
4642  goto end;
4643  }
4644  }
4645  } else {
4646  TRACE("found subvol %I64x\n", *id);
4647  Status = get_subvol_path(Vcb, *id, out, outlen, Irp);
4648  goto end;
4649  }
4650  }
4651 
4652  searchkey.obj_type = TYPE_SUBVOL_REC_UUID;
4653 
4654  Status = find_item(Vcb, Vcb->uuid_root, &tp, &searchkey, false, Irp);
4655 
4656  if (!NT_SUCCESS(Status)) {
4657  ERR("find_item returned %08lx\n", Status);
4658  goto end;
4659  }
4660 
4661  if (!keycmp(searchkey, tp.item->key) && tp.item->size >= sizeof(uint64_t)) {
4662  uint64_t* ids = (uint64_t*)tp.item->data;
4663  ULONG i;
4664 
4665  for (i = 0; i < tp.item->size / sizeof(uint64_t); i++) {
4666  if (bfs->ctransid != 0) {
4667  KEY searchkey2;
4668  traverse_ptr tp2;
4669 
4670  searchkey2.obj_id = ids[i];
4671  searchkey2.obj_type = TYPE_ROOT_ITEM;
4672  searchkey2.offset = 0xffffffffffffffff;
4673 
4674  Status = find_item(Vcb, Vcb->root_root, &tp2, &searchkey2, false, Irp);
4675  if (!NT_SUCCESS(Status)) {
4676  ERR("find_item returned %08lx\n", Status);
4677  goto end;
4678  }
4679 
4680  if (tp2.item->key.obj_id == searchkey2.obj_id && tp2.item->key.obj_type == searchkey2.obj_type &&
4681  tp2.item->size >= offsetof(ROOT_ITEM, otransid)) {
4682  ROOT_ITEM* ri = (ROOT_ITEM*)tp2.item->data;
4683 
4684  if (ri->ctransid == bfs->ctransid) {
4685  TRACE("found subvol %I64x\n", ids[i]);
4686  Status = get_subvol_path(Vcb, ids[i], out, outlen, Irp);
4687  goto end;
4688  }
4689  }
4690  } else {
4691  TRACE("found subvol %I64x\n", ids[i]);
4692  Status = get_subvol_path(Vcb, ids[i], out, outlen, Irp);
4693  goto end;
4694  }
4695  }
4696  }
4697 
4699 
4700 end:
4701  ExReleaseResourceLite(&Vcb->tree_lock);
4702 
4703  return Status;
4704 }
uint64_t obj_id
Definition: btrfs.h:144
#define STATUS_PRIVILEGE_NOT_HELD
Definition: DriverTester.h:9
uint8_t obj_type
Definition: btrfs.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define keycmp(key1, key2)
Definition: btrfs_drv.h:1008
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:414
if(dx==0 &&dy==0)
Definition: linetemp.h:174
uint64_t offset
Definition: btrfs.h:146
uint8_t * data
Definition: btrfs_drv.h:415
GLuint * ids
Definition: glext.h:5907
_In_ PIRP Irp
Definition: csq.h:116
BTRFS_UUID uuid
Definition: btrfsioctl.h:263
#define offsetof(TYPE, MEMBER)
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2965
Status
Definition: gdiplustypes.h:24
uint64_t ctransid
Definition: btrfs.h:328
#define STATUS_NOT_FOUND
Definition: shellext.h:72
#define TRACE(s)
Definition: solgame.cpp:4
NTSTATUS find_item(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _Out_ traverse_ptr *tp, _In_ const KEY *searchkey, _In_ bool ignore, _In_opt_ PIRP Irp) __attribute__((nonnull(1
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define TYPE_SUBVOL_UUID
Definition: btrfs.h:51
#define Vcb
Definition: cdprocs.h:1415
static FILE * out
Definition: regtests2xml.c:44
#define for
Definition: utility.h:88
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
GLuint GLuint end
Definition: gl.h:1545
tree_data * item
Definition: btrfs_drv.h:502
#define uint64_t
Definition: nsiface.idl:62
#define ERR(fmt,...)
Definition: debug.h:110
uint8_t uuid[16]
Definition: btrfs.h:140
Definition: btrfs.h:143
#define SE_MANAGE_VOLUME_PRIVILEGE
Definition: security.c:682
UINT64 uint64_t
Definition: types.h:77
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
GLuint in
Definition: glext.h:9616
static NTSTATUS get_subvol_path(device_extension *Vcb, uint64_t id, WCHAR *out, ULONG outlen, PIRP Irp)
Definition: fsctl.c:4531
#define TYPE_ROOT_ITEM
Definition: btrfs.h:32
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
BOOLEAN NTAPI SeSinglePrivilegeCheck(_In_ LUID PrivilegeValue, _In_ KPROCESSOR_MODE PreviousMode)
Checks if a single privilege is present in the context of the calling thread.
Definition: priv.c:744
unsigned int ULONG
Definition: retypes.h:1
GLenum GLuint id
Definition: glext.h:5579
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define TYPE_SUBVOL_REC_UUID
Definition: btrfs.h:52
uint64_t ctransid
Definition: btrfsioctl.h:264

Referenced by fsctl_request().

◆ flush_fcb_caches()

static void flush_fcb_caches ( device_extension Vcb)
static

Definition at line 2218 of file fsctl.c.

2218  {
2219  LIST_ENTRY* le;
2220 
2221  le = Vcb->all_fcbs.Flink;
2222  while (le != &Vcb->all_fcbs) {
2223  struct _fcb* fcb = CONTAINING_RECORD(le, struct _fcb, list_entry_all);
2225 
2226  if (fcb->type != BTRFS_TYPE_DIRECTORY && !fcb->deleted)
2227  CcFlushCache(&fcb->nonpaged->segment_object, NULL, 0, &iosb);
2228 
2229  le = le->Flink;
2230  }
2231 }
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:337
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:86
uint8_t type
Definition: btrfs_drv.h:291
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define Vcb
Definition: cdprocs.h:1415
Definition: typedefs.h:119
struct _fcb_nonpaged * nonpaged
Definition: btrfs_drv.h:284
bool deleted
Definition: btrfs_drv.h:295
#define NULL
Definition: types.h:112

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

◆ flush_subvol_fcbs()

void flush_subvol_fcbs ( root subvol)

Definition at line 243 of file fsctl.c.

243  {
244  LIST_ENTRY* le = subvol->fcbs.Flink;
245 
246  if (IsListEmpty(&subvol->fcbs))
247  return;
248 
249  while (le != &subvol->fcbs) {
250  struct _fcb* fcb = CONTAINING_RECORD(le, struct _fcb, list_entry);
252 
253  if (fcb->type != BTRFS_TYPE_DIRECTORY && !fcb->deleted)
254  CcFlushCache(&fcb->nonpaged->segment_object, NULL, 0, &iosb);
255 
256  le = le->Flink;
257  }
258 }
static PIO_STATUS_BLOCK iosb
Definition: file.c:98
VOID NTAPI CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, OUT OPTIONAL PIO_STATUS_BLOCK IoStatus)
Definition: cachesub.c:222
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:86
uint8_t type
Definition: btrfs_drv.h:291
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
Definition: typedefs.h:119
struct _fcb_nonpaged * nonpaged
Definition: btrfs_drv.h:284
bool deleted
Definition: btrfs_drv.h:295
struct _root * subvol
Definition: btrfs_drv.h:288
Definition: list.h:27
#define NULL
Definition: types.h:112

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

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

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

4166  {
4167  LIST_ENTRY* le;
4168  btrfs_set_xattr* bsxa;
4169  ULONG reqlen = (ULONG)offsetof(btrfs_set_xattr, data[0]);
4170  fcb* fcb;
4171  ccb* ccb;
4172 
4173  if (!data || datalen < reqlen)
4174  return STATUS_INVALID_PARAMETER;
4175 
4176  if (!FileObject || !FileObject->FsContext || !FileObject->FsContext2 || FileObject->FsContext == Vcb->volume_fcb)
4177  return STATUS_INVALID_PARAMETER;
4178 
4179  fcb = FileObject->FsContext;
4180  ccb = FileObject->FsContext2;
4181 
4182  if (!(ccb->access & (FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES)) && processor_mode == UserMode) {
4183  WARN("insufficient privileges\n");
4184  return STATUS_ACCESS_DENIED;
4185  }
4186 
4187  ExAcquireResourceSharedLite(fcb->Header.Resource, true);
4188 
4189  le = fcb->xattrs.Flink;
4190  while (le != &fcb->xattrs) {
4192 
4193  if (xa->valuelen > 0)
4194  reqlen += (ULONG)offsetof(btrfs_set_xattr, data[0]) + xa->namelen + xa->valuelen;
4195 
4196  le = le->Flink;
4197  }
4198 
4199  if (datalen < reqlen) {
4200  ExReleaseResourceLite(fcb->Header.Resource);
4201  return STATUS_BUFFER_OVERFLOW;
4202  }
4203 
4204  bsxa = (btrfs_set_xattr*)data;
4205 
4206  if (reqlen > 0) {
4207  le = fcb->xattrs.Flink;
4208  while (le != &fcb->xattrs) {
4210 
4211  if (xa->valuelen > 0) {
4212  bsxa->namelen = xa->namelen;
4213  bsxa->valuelen = xa->valuelen;
4214  memcpy(bsxa->data, xa->data, xa->namelen + xa->valuelen);
4215 
4216  bsxa = (btrfs_set_xattr*)&bsxa->data[xa->namelen + xa->valuelen];
4217  }
4218 
4219  le = le->Flink;
4220  }
4221  }
4222 
4223  bsxa->namelen = 0;
4224  bsxa->valuelen = 0;
4225 
4226  ExReleaseResourceLite(fcb->Header.Resource);
4227 
4228  return STATUS_SUCCESS;
4229 }
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define WARN(fmt,...)
Definition: debug.h:112
ACCESS_MASK access
Definition: btrfs_drv.h:382
int const JOCTET unsigned int datalen
Definition: jpeglib.h:1030
#define FILE_WRITE_ATTRIBUTES
Definition: nt_native.h:649
#define offsetof(TYPE, MEMBER)
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:547
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:283
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
struct _fcb fcb
Definition: btrfs_drv.h:1355
LIST_ENTRY xattrs
Definition: btrfs_drv.h:308
#define Vcb
Definition: cdprocs.h:1415
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
Definition: typedefs.h:119
USHORT valuelen
Definition: btrfs_drv.h:277
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
Definition: list.h:27
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
USHORT namelen
Definition: btrfs_drv.h:276
unsigned int ULONG
Definition: retypes.h:1
#define STATUS_SUCCESS
Definition: shellext.h:65
struct _ccb ccb
char data[1]
Definition: btrfs_drv.h:279

Referenced by fsctl_request().

◆ fsctl_oplock()

static NTSTATUS fsctl_oplock ( device_extension Vcb,
PIRP Pirp 
)
static

Definition at line 4891 of file fsctl.c.

4891  {
4892  NTSTATUS Status;
4893  PIRP Irp = *Pirp;
4895  uint32_t fsctl = IrpSp->Parameters.FileSystemControl.FsControlCode;
4897  fcb* fcb = FileObject ? FileObject->FsContext : NULL;
4898  ccb* ccb = FileObject ? FileObject->FsContext2 : NULL;
4899  file_ref* fileref = ccb ? ccb->fileref : NULL;
4900 #if (NTDDI_VERSION >= NTDDI_WIN7)
4901  PREQUEST_OPLOCK_INPUT_BUFFER buf = NULL;
4902  bool oplock_request = false, oplock_ack = false;
4903 #else
4904  bool oplock_request = false;
4905 #endif
4906  ULONG oplock_count = 0;
4907 #ifdef __REACTOS__
4908  bool shared_request;
4909 #endif
4910 
4911  if (!fcb) {
4912  ERR("fcb was NULL\n");
4913  return STATUS_INVALID_PARAMETER;
4914  }
4915 
4916  if (!fileref) {
4917  ERR("fileref was NULL\n");
4918  return STATUS_INVALID_PARAMETER;
4919  }
4920 
4922  return STATUS_INVALID_PARAMETER;
4923 
4924 #if (NTDDI_VERSION >= NTDDI_WIN7)
4925  if (fsctl == FSCTL_REQUEST_OPLOCK) {
4926  if (IrpSp->Parameters.FileSystemControl.InputBufferLength < sizeof(REQUEST_OPLOCK_INPUT_BUFFER))
4927  return STATUS_BUFFER_TOO_SMALL;
4928 
4929  if (IrpSp->Parameters.FileSystemControl.OutputBufferLength < sizeof(REQUEST_OPLOCK_OUTPUT_BUFFER))
4930  return STATUS_BUFFER_TOO_SMALL;
4931 
4932  buf = Irp->AssociatedIrp.SystemBuffer;
4933 
4934  // flags are mutually exclusive
4935  if (buf->Flags & REQUEST_OPLOCK_INPUT_FLAG_REQUEST && buf->Flags & REQUEST_OPLOCK_INPUT_FLAG_ACK)
4936  return STATUS_INVALID_PARAMETER;
4937 
4938  oplock_request = buf->Flags & REQUEST_OPLOCK_INPUT_FLAG_REQUEST;
4939  oplock_ack = buf->Flags & REQUEST_OPLOCK_INPUT_FLAG_ACK;
4940 
4941  if (!oplock_request && !oplock_ack)
4942  return STATUS_INVALID_PARAMETER;
4943  }
4944 #endif
4945 
4946 #if (NTDDI_VERSION >= NTDDI_WIN7)
4947  bool shared_request = (fsctl == FSCTL_REQUEST_OPLOCK_LEVEL_2) || (fsctl == FSCTL_REQUEST_OPLOCK && !(buf->RequestedOplockLevel & OPLOCK_LEVEL_CACHE_WRITE));
4948 #else
4949  shared_request = (fsctl == FSCTL_REQUEST_OPLOCK_LEVEL_2);
4950 #endif
4951 
4952 #if (NTDDI_VERSION >= NTDDI_WIN7)
4953  if (fcb->type == BTRFS_TYPE_DIREC