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

Go to the source code of this file.

Macros

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

Functions

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

Variables

LIST_ENTRY VcbList
 
ERESOURCE global_loading_lock
 
PDRIVER_OBJECT drvobj
 
tFsRtlCheckLockForOplockRequest fFsRtlCheckLockForOplockRequest
 
tFsRtlAreThereCurrentOrInProgressFileLocks fFsRtlAreThereCurrentOrInProgressFileLocks
 

Macro Definition Documentation

◆ DOTDOT

#define DOTDOT   ".."

Definition at line 35 of file fsctl.c.

◆ FSCTL_CSV_CONTROL

Definition at line 28 of file fsctl.c.

◆ FSCTL_QUERY_VOLUME_CONTAINER_STATE

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

Definition at line 32 of file fsctl.c.

◆ SEF_AVOID_PRIVILEGE_CHECK

#define SEF_AVOID_PRIVILEGE_CHECK   0x08

Definition at line 37 of file fsctl.c.

◆ SEF_SACL_AUTO_INHERIT

#define SEF_SACL_AUTO_INHERIT   0x02

Definition at line 39 of file fsctl.c.

Function Documentation

◆ add_csum_sparse_extents()

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

Definition at line 5148 of file fsctl.c.

5148  {
5149  if (!found) {
5150  uint8_t* sector = ExAllocatePoolWithTag(PagedPool, Vcb->superblock.sector_size, ALLOC_TAG);
5151 
5152  if (!sector) {
5153  ERR("out of memory\n");
5155  }
5156 
5157  memset(sector, 0, Vcb->superblock.sector_size);
5158 
5159  get_sector_csum(Vcb, sector, hash_ptr);
5160 
5161  ExFreePool(sector);
5162  }
5163 
5164  switch (Vcb->superblock.csum_type) {
5165  case CSUM_TYPE_CRC32C: {
5166  uint32_t* csum = (uint32_t*)*ptr;
5167  uint32_t sparse_hash = *(uint32_t*)hash_ptr;
5168 
5169  for (uint64_t i = 0; i < sparse_extents; i++) {
5170  csum[i] = sparse_hash;
5171  }
5172 
5173  break;
5174  }
5175 
5176  case CSUM_TYPE_XXHASH: {
5177  uint64_t* csum = (uint64_t*)*ptr;
5178  uint64_t sparse_hash = *(uint64_t*)hash_ptr;
5179 
5180  for (uint64_t i = 0; i < sparse_extents; i++) {
5181  csum[i] = sparse_hash;
5182  }
5183 
5184  break;
5185  }
5186 
5187  case CSUM_TYPE_SHA256:
5188  case CSUM_TYPE_BLAKE2: {
5189  uint8_t* csum = (uint8_t*)*ptr;
5190 
5191  for (uint64_t i = 0; i < sparse_extents; i++) {
5192  memcpy(csum, hash_ptr, 32);
5193  csum += 32;
5194  }
5195 
5196  break;
5197  }
5198 
5199  default:
5200  ERR("unrecognized hash type %x\n", Vcb->superblock.csum_type);
5201  return STATUS_INTERNAL_ERROR;
5202  }
5203 
5204  *ptr += sparse_extents * Vcb->csum_size;
5205 
5206  return STATUS_SUCCESS;
5207 }
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 2735 of file fsctl.c.

2735  {
2737  NTSTATUS Status;
2738  PFILE_OBJECT fileobj, mountmgrfo;
2740  HANDLE h;
2741  LIST_ENTRY* le;
2742  device* dev;
2743  DEV_ITEM* di;
2744  uint64_t dev_id, size;
2745  uint8_t* mb;
2746  uint64_t* stats;
2747  UNICODE_STRING mmdevpath, pnp_name, pnp_name2;
2748  volume_child* vc;
2750  KEY searchkey;
2751  traverse_ptr tp;
2754  pdo_device_extension* pdode;
2755  const GUID* pnp_guid;
2757 
2758  pnp_name.Buffer = NULL;
2759 
2760  if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), processor_mode))
2762 
2763  if (!Vcb->vde) {
2764  WARN("not allowing second device to be added to non-PNP device\n");
2765  return STATUS_NOT_SUPPORTED;
2766  }
2767 
2768  if (Vcb->readonly) // FIXME - handle adding R/W device to seeding device
2770 
2771 #if defined(_WIN64)
2772  if (IoIs32bitProcess(Irp)) {
2773  if (IrpSp->Parameters.FileSystemControl.InputBufferLength != sizeof(uint32_t))
2774  return STATUS_INVALID_PARAMETER;
2775 
2776  h = (HANDLE)LongToHandle((*(uint32_t*)Irp->AssociatedIrp.SystemBuffer));
2777  } else {
2778 #endif
2779  if (IrpSp->Parameters.FileSystemControl.InputBufferLength != sizeof(HANDLE))
2780  return STATUS_INVALID_PARAMETER;
2781 
2782  h = *(PHANDLE)Irp->AssociatedIrp.SystemBuffer;
2783 #if defined(_WIN64)
2784  }
2785 #endif
2786 
2787  Status = ObReferenceObjectByHandle(h, 0, *IoFileObjectType, Irp->RequestorMode, (void**)&fileobj, NULL);
2788 
2789  if (!NT_SUCCESS(Status)) {
2790  ERR("ObReferenceObjectByHandle returned %08lx\n", Status);
2791  return Status;
2792  }
2793 
2794  DeviceObject = fileobj->DeviceObject;
2795 
2796  Status = get_device_pnp_name(DeviceObject, &pnp_name, &pnp_guid);
2797  if (!NT_SUCCESS(Status)) {
2798  ERR("get_device_pnp_name returned %08lx\n", Status);
2799  ObDereferenceObject(fileobj);
2800  return Status;
2801  }
2802 
2803  // If this is a disk, we have been handed the PDO, so need to go up to find something we can use
2804  if (RtlCompareMemory(pnp_guid, &GUID_DEVINTERFACE_DISK, sizeof(GUID)) == sizeof(GUID) && DeviceObject->AttachedDevice)
2805  DeviceObject = DeviceObject->AttachedDevice;
2806 
2808  if (!NT_SUCCESS(Status)) {
2809  ERR("IOCTL_DISK_IS_WRITABLE returned %08lx\n", Status);
2810  ObDereferenceObject(fileobj);
2811  return Status;
2812  }
2813 
2815  if (!NT_SUCCESS(Status)) {
2816  ERR("is_device_part_of_mounted_btrfs_raid returned %08lx\n", Status);
2817  ObDereferenceObject(fileobj);
2818  return Status;
2819  }
2820 
2821  // if disk, check it has no partitions
2822  if (RtlCompareMemory(pnp_guid, &GUID_DEVINTERFACE_DISK, sizeof(GUID)) == sizeof(GUID)) {
2823  ULONG dlisize;
2824  DRIVE_LAYOUT_INFORMATION_EX* dli = NULL;
2825 
2826  dlisize = 0;
2827 
2828  do {
2829  dlisize += 1024;
2830 
2831  if (dli)
2832  ExFreePool(dli);
2833 
2834  dli = ExAllocatePoolWithTag(PagedPool, dlisize, ALLOC_TAG);
2835  if (!dli) {
2836  ERR("out of memory\n");
2838  goto end2;
2839  }
2840 
2842  } while (Status == STATUS_BUFFER_TOO_SMALL);
2843 
2844  if (NT_SUCCESS(Status) && dli->PartitionCount > 0) {
2845  ExFreePool(dli);
2846  ERR("not adding disk which has partitions\n");
2848  goto end2;
2849  }
2850 
2851  ExFreePool(dli);
2852  }
2853 
2855  &sdn, sizeof(STORAGE_DEVICE_NUMBER), true, NULL);
2856  if (NT_SUCCESS(Status)) {
2857  if (sdn.DeviceType != FILE_DEVICE_DISK) { // FIXME - accept floppies and CDs?
2858  WARN("device was not disk\n");
2859  ObDereferenceObject(fileobj);
2860  return STATUS_INVALID_PARAMETER;
2861  }
2862  } else {
2863  sdn.DeviceNumber = 0xffffffff;
2864  sdn.PartitionNumber = 0xffffffff;
2865  }
2866 
2868  &gli, sizeof(gli), true, NULL);
2869  if (!NT_SUCCESS(Status)) {
2870  ERR("error reading length information: %08lx\n", Status);
2871  ObDereferenceObject(fileobj);
2872  return Status;
2873  }
2874 
2875  size = gli.Length.QuadPart;
2876 
2877  if (size < 0x100000) {
2878  ERR("device was not large enough to hold FS (%I64x bytes, need at least 1 MB)\n", size);
2879  ObDereferenceObject(fileobj);
2880  return STATUS_INTERNAL_ERROR;
2881  }
2882 
2883  volume_removal(&pnp_name);
2884 
2885  ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
2886 
2887  if (Vcb->need_write)
2888  Status = do_write(Vcb, Irp);
2889  else
2891 
2892  free_trees(Vcb);
2893 
2894  if (!NT_SUCCESS(Status)) {
2895  ERR("do_write returned %08lx\n", Status);
2896  goto end;
2897  }
2898 
2900  if (!dev) {
2901  ERR("out of memory\n");
2903  goto end;
2904  }
2905 
2906  RtlZeroMemory(dev, sizeof(device));
2907 
2908  dev->devobj = DeviceObject;
2909  dev->fileobj = fileobj;
2910  dev->seeding = false;
2911  init_device(Vcb, dev, true);
2912 
2913  InitializeListHead(&dev->space);
2914 
2915  if (size > 0x100000) { // add disk hole - the first MB is marked as used
2916  Status = add_space_entry(&dev->space, NULL, 0x100000, size - 0x100000);
2917  if (!NT_SUCCESS(Status)) {
2918  ERR("add_space_entry returned %08lx\n", Status);
2919  goto end;
2920  }
2921  }
2922 
2923  dev_id = 0;
2924 
2925  le = Vcb->devices.Flink;
2926  while (le != &Vcb->devices) {
2927  device* dev2 = CONTAINING_RECORD(le, device, list_entry);
2928 
2929  if (dev2->devitem.dev_id > dev_id)
2930  dev_id = dev2->devitem.dev_id;
2931 
2932  le = le->Flink;
2933  }
2934 
2935  dev_id++;
2936 
2937  dev->devitem.dev_id = dev_id;
2938  dev->devitem.num_bytes = size;
2939  dev->devitem.bytes_used = 0;
2940  dev->devitem.optimal_io_align = Vcb->superblock.sector_size;
2941  dev->devitem.optimal_io_width = Vcb->superblock.sector_size;
2942  dev->devitem.minimal_io_size = Vcb->superblock.sector_size;
2943  dev->devitem.type = 0;
2944  dev->devitem.generation = 0;
2945  dev->devitem.start_offset = 0;
2946  dev->devitem.dev_group = 0;
2947  dev->devitem.seek_speed = 0;
2948  dev->devitem.bandwidth = 0;
2949  get_uuid(&dev->devitem.device_uuid);
2950  dev->devitem.fs_uuid = Vcb->superblock.uuid;
2951 
2953  if (!di) {
2954  ERR("out of memory\n");
2955  goto end;
2956  }
2957 
2958  RtlCopyMemory(di, &dev->devitem, sizeof(DEV_ITEM));
2959 
2960  Status = insert_tree_item(Vcb, Vcb->chunk_root, 1, TYPE_DEV_ITEM, di->dev_id, di, sizeof(DEV_ITEM), NULL, Irp);
2961  if (!NT_SUCCESS(Status)) {
2962  ERR("insert_tree_item returned %08lx\n", Status);
2963  ExFreePool(di);
2964  goto end;
2965  }
2966 
2967  // add stats entry to dev tree
2968  stats = ExAllocatePoolWithTag(PagedPool, sizeof(uint64_t) * 5, ALLOC_TAG);
2969  if (!stats) {
2970  ERR("out of memory\n");
2972  goto end;
2973  }
2974 
2975  RtlZeroMemory(stats, sizeof(uint64_t) * 5);
2976 
2977  searchkey.obj_id = 0;
2978  searchkey.obj_type = TYPE_DEV_STATS;
2979  searchkey.offset = di->dev_id;
2980 
2981  Status = find_item(Vcb, Vcb->dev_root, &tp, &searchkey, false, Irp);
2982  if (!NT_SUCCESS(Status)) {
2983  ERR("error - find_item returned %08lx\n", Status);
2984  ExFreePool(stats);
2985  goto end;
2986  }
2987 
2988  if (!keycmp(tp.item->key, searchkey)) {
2990  if (!NT_SUCCESS(Status)) {
2991  ERR("delete_tree_item returned %08lx\n", Status);
2992  ExFreePool(stats);
2993  goto end;
2994  }
2995  }
2996 
2997  Status = insert_tree_item(Vcb, Vcb->dev_root, 0, TYPE_DEV_STATS, di->dev_id, stats, sizeof(uint64_t) * 5, NULL, Irp);
2998  if (!NT_SUCCESS(Status)) {
2999  ERR("insert_tree_item returned %08lx\n", Status);
3000  ExFreePool(stats);
3001  goto end;
3002  }
3003 
3004  if (dev->trim && !dev->readonly && !Vcb->options.no_trim)
3006 
3007  // We clear the first megabyte of the device, so Windows doesn't identify it as another FS
3008  mb = ExAllocatePoolWithTag(PagedPool, 0x100000, ALLOC_TAG);
3009  if (!mb) {
3010  ERR("out of memory\n");
3012  goto end;
3013  }
3014 
3015  RtlZeroMemory(mb, 0x100000);
3016 
3017  Status = write_data_phys(DeviceObject, fileobj, 0, mb, 0x100000);
3018  if (!NT_SUCCESS(Status)) {
3019  ERR("write_data_phys returned %08lx\n", Status);
3020  ExFreePool(mb);
3021  goto end;
3022  }
3023 
3024  ExFreePool(mb);
3025 
3026  vde = Vcb->vde;
3027  pdode = vde->pdode;
3028 
3030  if (!vc) {
3031  ERR("out of memory\n");
3033  goto end;
3034  }
3035 
3036  vc->uuid = dev->devitem.device_uuid;
3037  vc->devid = dev_id;
3038  vc->generation = Vcb->superblock.generation;
3039  vc->devobj = DeviceObject;
3040  vc->fileobj = fileobj;
3041  vc->notification_entry = NULL;
3042  vc->boot_volume = false;
3043 
3045  drvobj, pnp_removal, vde->pdode, &vc->notification_entry);
3046  if (!NT_SUCCESS(Status))
3047  WARN("IoRegisterPlugPlayNotification returned %08lx\n", Status);
3048 
3049  pnp_name2 = pnp_name;
3050 
3051  if (pnp_name.Length > 4 * sizeof(WCHAR) && pnp_name.Buffer[0] == '\\' && (pnp_name.Buffer[1] == '\\' || pnp_name.Buffer[1] == '?') &&
3052  pnp_name.Buffer[2] == '?' && pnp_name.Buffer[3] == '\\') {
3053  pnp_name2.Buffer = &pnp_name2.Buffer[3];
3054  pnp_name2.Length -= 3 * sizeof(WCHAR);
3055  pnp_name2.MaximumLength -= 3 * sizeof(WCHAR);
3056  }
3057 
3058  vc->pnp_name.Length = vc->pnp_name.MaximumLength = pnp_name2.Length;
3059 
3060  if (pnp_name2.Length == 0)
3061  vc->pnp_name.Buffer = NULL;
3062  else {
3064  if (!vc->pnp_name.Buffer) {
3065  ERR("out of memory\n");
3067  goto end;
3068  }
3069 
3070  RtlCopyMemory(vc->pnp_name.Buffer, pnp_name2.Buffer, pnp_name2.Length);
3071  }
3072 
3073  vc->size = size;
3074  vc->seeding = false;
3075  vc->disk_num = sdn.DeviceNumber;
3076  vc->part_num = sdn.PartitionNumber;
3077  vc->had_drive_letter = false;
3078 
3080  InsertTailList(&pdode->children, &vc->list_entry);
3081  pdode->num_children++;
3082  pdode->children_loaded++;
3084 
3086  Status = IoGetDeviceObjectPointer(&mmdevpath, FILE_READ_ATTRIBUTES, &mountmgrfo, &mountmgr);
3087  if (!NT_SUCCESS(Status))
3088  ERR("IoGetDeviceObjectPointer returned %08lx\n", Status);
3089  else {
3090  Status = remove_drive_letter(mountmgr, &pnp_name);
3092  WARN("remove_drive_letter returned %08lx\n", Status);
3093 
3095 
3096  ObDereferenceObject(mountmgrfo);
3097  }
3098 
3099  Vcb->superblock.num_devices++;
3100  Vcb->superblock.total_bytes += size;
3101  Vcb->devices_loaded++;
3102  InsertTailList(&Vcb->devices, &dev->list_entry);
3103 
3104  // FIXME - send notification that volume size has increased
3105 
3106  ObReferenceObject(DeviceObject); // for Vcb
3107 
3108  Status = do_write(Vcb, Irp);
3109  if (!NT_SUCCESS(Status))
3110  ERR("do_write returned %08lx\n", Status);
3111 
3112  ObReferenceObject(fileobj);
3113 
3114 end:
3115  free_trees(Vcb);
3116 
3117  ExReleaseResourceLite(&Vcb->tree_lock);
3118 
3119 end2:
3120  ObDereferenceObject(fileobj);
3121 
3122  if (pnp_name.Buffer)
3123  ExFreePool(pnp_name.Buffer);
3124 
3125  if (NT_SUCCESS(Status))
3127 
3128  return Status;
3129 }
DEVICE_TYPE DeviceType
Definition: ntddstor.h:324
uint64_t obj_id
Definition: btrfs.h:144
bool boot_volume
Definition: btrfs_drv.h:866
#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:859
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:7877
#define keycmp(key1, key2)
Definition: btrfs_drv.h:1016
#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:865
#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:3416
#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:854
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
uint64_t num_children
Definition: btrfs_drv.h:894
#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:856
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:861
PDEVICE_OBJECT devobj
Definition: btrfs_drv.h:857
#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:878
static NTSTATUS is_device_part_of_mounted_btrfs_raid(PDEVICE_OBJECT devobj, PFILE_OBJECT fileobj)
Definition: fsctl.c:2637
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:2996
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:895
NTSTATUS get_device_pnp_name(_In_ PDEVICE_OBJECT DeviceObject, _Out_ PUNICODE_STRING pnp_name, _Out_ const GUID **guid)
Definition: btrfs.c:4233
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:70
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:2954
bool had_drive_letter
Definition: btrfs_drv.h:862
#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:896
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
void * notification_entry
Definition: btrfs_drv.h:863
* PFILE_OBJECT
Definition: iotypes.h:1998
ULONG disk_num
Definition: btrfs_drv.h:864
#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:509
PFILE_OBJECT fileobj
Definition: btrfs_drv.h:858
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
Definition: list.h:27
DEV_ITEM devitem
Definition: btrfs_drv.h:527
#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:2716
uint64_t size
Definition: btrfs_drv.h:860
#define ObReferenceObject
Definition: obfuncs.h:204
LIST_ENTRY list_entry
Definition: btrfs_drv.h:867
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:855
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3128
LIST_ENTRY children
Definition: btrfs_drv.h:897
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
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 3131 of file fsctl.c.

3131  {
3132  fcb* fcb;
3133  ccb* ccb;
3134 
3135  TRACE("FSCTL_ALLOW_EXTENDED_DASD_IO\n");
3136 
3137  if (!FileObject)
3138  return STATUS_INVALID_PARAMETER;
3139 
3140  fcb = FileObject->FsContext;
3141  ccb = FileObject->FsContext2;
3142 
3143  if (!fcb)
3144  return STATUS_INVALID_PARAMETER;
3145 
3146  if (fcb != Vcb->volume_fcb)
3147  return STATUS_INVALID_PARAMETER;
3148 
3149  if (!ccb)
3150  return STATUS_INVALID_PARAMETER;
3151 
3152  ccb->allow_extended_dasd_io = true;
3153 
3154  return STATUS_SUCCESS;
3155 }
#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:1364
#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 3701 of file fsctl.c.

3702  {
3703  KEY searchkey;
3704  traverse_ptr tp;
3705  NTSTATUS Status;
3706  uint8_t c = hash >> 24;
3707 
3708  if (subvol->fcbs_ptrs[c]) {
3709  LIST_ENTRY* le = subvol->fcbs_ptrs[c];
3710 
3711  while (le != &subvol->fcbs) {
3712  struct _fcb* fcb2 = CONTAINING_RECORD(le, struct _fcb, list_entry);
3713 
3714  if (fcb2->inode == inode)
3715  return STATUS_SUCCESS;
3716  else if (fcb2->hash > hash)
3717  break;
3718 
3719  le = le->Flink;
3720  }
3721  }
3722 
3723  searchkey.obj_id = inode;
3724  searchkey.obj_type = TYPE_INODE_ITEM;
3725  searchkey.offset = 0xffffffffffffffff;
3726 
3727  Status = find_item(Vcb, subvol, &tp, &searchkey, false, Irp);
3728  if (!NT_SUCCESS(Status)) {
3729  ERR("find_item returned %08lx\n", Status);
3730  return Status;
3731  }
3732 
3733  if (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == searchkey.obj_type)
3734  return STATUS_SUCCESS;
3735 
3736  return STATUS_NOT_FOUND;
3737 }
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:2996
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:509
#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:1517
_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:1033
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:1364
#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:1856
#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:5797
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:1016
#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:1517
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:1717
#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:508
_In_ PIRP Irp
Definition: csq.h:116
static __inline bool is_subvol_readonly(root *r, PIRP Irp)
Definition: btrfs_drv.h:1033
#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:1743
LIST_ENTRY ** hash_ptrs_uc
Definition: btrfs_drv.h:318
#define offsetof(TYPE, MEMBER)
void mark_fcb_dirty(_In_ fcb *fcb)
Definition: btrfs.c:1695
#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:1739
#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:2996
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:1364
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:2664
#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:509
#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:1684
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:1271
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:1856
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:1754
Definition: name.c:38
static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME *out)
Definition: btrfs_drv.h:989
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:5797
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 2584 of file fsctl.c.

2584  {
2585  NTSTATUS Status;
2586  bool open_files;
2587 
2588  TRACE("FSCTL_DISMOUNT_VOLUME\n");
2589 
2590  if (!(Vcb->Vpb->Flags & VPB_MOUNTED))
2591  return STATUS_SUCCESS;
2592 
2593  if (!shutdown) {
2594  if (Vcb->disallow_dismount || Vcb->page_file_count != 0) {
2595  WARN("attempting to dismount boot volume or one containing a pagefile\n");
2596  return STATUS_ACCESS_DENIED;
2597  }
2598 
2600  if (!NT_SUCCESS(Status)) {
2601  WARN("FsRtlNotifyVolumeEvent returned %08lx\n", Status);
2602  }
2603  }
2604 
2605  ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
2606 
2607  if (!Vcb->locked) {
2609 
2610  if (Vcb->need_write && !Vcb->readonly) {
2611  Status = do_write(Vcb, Irp);
2612 
2613  if (!NT_SUCCESS(Status))
2614  ERR("do_write returned %08lx\n", Status);
2615  }
2616  }
2617 
2618  free_trees(Vcb);
2619 
2620  Vcb->removing = true;
2621 
2622  open_files = Vcb->open_files > 0;
2623 
2624  if (Vcb->vde) {
2626  Vcb->vde->mounted_device = NULL;
2627  }
2628 
2629  ExReleaseResourceLite(&Vcb->tree_lock);
2630 
2631  if (!open_files)
2632  uninit(Vcb);
2633 
2634  return STATUS_SUCCESS;
2635 }
#define FSRTL_VOLUME_DISMOUNT
Definition: ntifs_ex.h:439
NTSTATUS do_write(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7877
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
void uninit(_In_ device_extension *Vcb)
Definition: btrfs.c:2001
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:2222
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:2561
#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:7877
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:1016
#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:1517
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:1717
file_ref * create_fileref(device_extension *Vcb)
Definition: create.c:160
tree * tree
Definition: btrfs_drv.h:508
_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:1695
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:1739
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:2996
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:3010
#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:509
#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:1271
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:4108
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:1364
void free_fileref(_Inout_ file_ref *fr)
Definition: btrfs.c:1856
#define FILE_ACTION_ADDED
#define __S_IFDIR
Definition: btrfs_drv.h:1754
Definition: name.c:38
static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME *out)
Definition: btrfs_drv.h:989
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 2326 of file fsctl.c.

2326  {
2327  KIRQL irql;
2328 
2330 
2331  Vcb->locked = false;
2332  Vcb->Vpb->Flags &= ~VPB_LOCKED;
2333  Vcb->locked_fileobj = NULL;
2334 
2336 
2337  if (Vcb->lock_paused_balance)
2338  KeSetEvent(&Vcb->balance.event, 0, false);
2339 }
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 3262 of file fsctl.c.

3262  {
3264  fcb *fcb = FileObject ? FileObject->FsContext : NULL, *sourcefcb;
3265  ccb *ccb = FileObject ? FileObject->FsContext2 : NULL, *sourceccb;
3266  NTSTATUS Status;
3267  PFILE_OBJECT sourcefo;
3268  uint64_t sourcelen, nbytes = 0;
3269  LIST_ENTRY rollback, *le, newexts;
3271  BTRFS_TIME now;
3272  bool make_inline;
3273 
3274  if (!ded || datalen < sizeof(DUPLICATE_EXTENTS_DATA))
3275  return STATUS_BUFFER_TOO_SMALL;
3276 
3277  if (Vcb->readonly)
3279 
3280  if (ded->ByteCount.QuadPart == 0)
3281  return STATUS_SUCCESS;
3282 
3283  if (!fcb || !ccb || fcb == Vcb->volume_fcb)
3284  return STATUS_INVALID_PARAMETER;
3285 
3287  return STATUS_ACCESS_DENIED;
3288 
3289  if (Irp->RequestorMode == UserMode && !(ccb->access & FILE_WRITE_DATA)) {
3290  WARN("insufficient privileges\n");
3291  return STATUS_ACCESS_DENIED;
3292  }
3293 
3294  if (!fcb->ads && fcb->type != BTRFS_TYPE_FILE && fcb->type != BTRFS_TYPE_SYMLINK)
3295  return STATUS_INVALID_PARAMETER;
3296 
3297  Status = ObReferenceObjectByHandle(ded->FileHandle, 0, *IoFileObjectType, Irp->RequestorMode, (void**)&sourcefo, NULL);
3298  if (!NT_SUCCESS(Status)) {
3299  ERR("ObReferenceObjectByHandle returned %08lx\n", Status);
3300  return Status;
3301  }
3302 
3303  if (sourcefo->DeviceObject != FileObject->DeviceObject) {
3304  WARN("source and destination are on different volumes\n");
3305  ObDereferenceObject(sourcefo);
3306  return STATUS_INVALID_PARAMETER;
3307  }
3308 
3309  sourcefcb = sourcefo->FsContext;
3310  sourceccb = sourcefo->FsContext2;
3311 
3312  if (!sourcefcb || !sourceccb || sourcefcb == Vcb->volume_fcb) {
3313  ObDereferenceObject(sourcefo);
3314  return STATUS_INVALID_PARAMETER;
3315  }
3316 
3317  if (!sourcefcb->ads && !fcb->ads) {
3318  if ((ded->SourceFileOffset.QuadPart & (Vcb->superblock.sector_size - 1)) || (ded->TargetFileOffset.QuadPart & (Vcb->superblock.sector_size - 1))) {
3319  ObDereferenceObject(sourcefo);
3320  return STATUS_INVALID_PARAMETER;
3321  }
3322 
3323  if (ded->ByteCount.QuadPart & (Vcb->superblock.sector_size - 1)) {
3324  ObDereferenceObject(sourcefo);
3325  return STATUS_INVALID_PARAMETER;
3326  }
3327  }
3328 
3329  if (Irp->RequestorMode == UserMode && (!(sourceccb->access & FILE_READ_DATA) || !(sourceccb->access & FILE_READ_ATTRIBUTES))) {
3330  WARN("insufficient privileges\n");
3331  ObDereferenceObject(sourcefo);
3332  return STATUS_ACCESS_DENIED;
3333  }
3334 
3335  if (!sourcefcb->ads && sourcefcb->type != BTRFS_TYPE_FILE && sourcefcb->type != BTRFS_TYPE_SYMLINK) {
3336  ObDereferenceObject(sourcefo);
3337  return STATUS_INVALID_PARAMETER;
3338  }
3339 
3340  sourcelen = sourcefcb->ads ? sourcefcb->adsdata.Length : sourcefcb->inode_item.st_size;
3341 
3342  if (sector_align(sourcelen, Vcb->superblock.sector_size) < (uint64_t)ded->SourceFileOffset.QuadPart + (uint64_t)ded->ByteCount.QuadPart) {
3343  ObDereferenceObject(sourcefo);
3344  return STATUS_NOT_SUPPORTED;
3345  }
3346 
3347  if (fcb == sourcefcb &&
3350  WARN("source and destination are the same, and the ranges overlap\n");
3351  ObDereferenceObject(sourcefo);
3352  return STATUS_INVALID_PARAMETER;
3353  }
3354 
3355  // fail if nocsum flag set on one file but not the other
3356  if (!fcb->ads && !sourcefcb->ads && (fcb->inode_item.flags & BTRFS_INODE_NODATASUM) != (sourcefcb->inode_item.flags & BTRFS_INODE_NODATASUM)) {
3357  ObDereferenceObject(sourcefo);
3358  return STATUS_INVALID_PARAMETER;
3359  }
3360 
3362  InitializeListHead(&newexts);
3363 
3364  ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
3365 
3366  ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
3367 
3368  if (fcb != sourcefcb)
3369  ExAcquireResourceSharedLite(sourcefcb->Header.Resource, true);
3370 
3373  goto end;
3374  }
3375 
3376  if (!FsRtlFastCheckLockForRead(&sourcefcb->lock, &ded->SourceFileOffset, &ded->ByteCount, 0, FileObject, PsGetCurrentProcess())) {
3378  goto end;
3379  }
3380 
3381  make_inline = fcb->ads ? false : (fcb->inode_item.st_size <= Vcb->options.max_inline || fcb_is_inline(fcb));
3382 
3383  if (fcb->ads || sourcefcb->ads || make_inline || fcb_is_inline(sourcefcb)) {
3384  uint8_t* data2;
3385  ULONG bytes_read, dataoff, datalen2;
3386 
3387  if (make_inline) {
3388  dataoff = (ULONG)ded->TargetFileOffset.QuadPart;
3389  datalen2 = (ULONG)fcb->inode_item.st_size;
3390  } else if (fcb->ads) {
3391  dataoff = 0;
3392  datalen2 = (ULONG)ded->ByteCount.QuadPart;
3393  } else {
3394  dataoff = ded->TargetFileOffset.QuadPart & (Vcb->superblock.sector_size - 1);
3395  datalen2 = (ULONG)sector_align(ded->ByteCount.QuadPart + dataoff, Vcb->superblock.sector_size);
3396  }
3397 
3399  if (!data2) {
3400  ERR("out of memory\n");
3402  goto end;
3403  }
3404 
3405  if (dataoff > 0) {
3406  if (make_inline)
3407  Status = read_file(fcb, data2, 0, datalen2, NULL, Irp);
3408  else
3409  Status = read_file(fcb, data2, ded->TargetFileOffset.QuadPart - dataoff, dataoff, NULL, Irp);
3410 
3411  if (!NT_SUCCESS(Status)) {
3412  ERR("read_file returned %08lx\n", Status);
3413  ExFreePool(data2);
3414  goto end;
3415  }
3416  }
3417 
3418  if (sourcefcb->ads) {
3419  Status = read_stream(sourcefcb, data2 + dataoff, ded->SourceFileOffset.QuadPart, (ULONG)ded->ByteCount.QuadPart, &bytes_read);
3420  if (!NT_SUCCESS(Status)) {
3421  ERR("read_stream returned %08lx\n", Status);
3422  ExFreePool(data2);
3423  goto end;
3424  }
3425  } else {
3426  Status = read_file(sourcefcb, data2 + dataoff, ded->SourceFileOffset.QuadPart, ded->ByteCount.QuadPart, &bytes_read, Irp);
3427  if (!NT_SUCCESS(Status)) {
3428  ERR("read_file returned %08lx\n", Status);
3429  ExFreePool(data2);
3430  goto end;
3431  }
3432  }
3433 
3434  if (dataoff + bytes_read < datalen2)
3435  RtlZeroMemory(data2 + dataoff + bytes_read, datalen2 - bytes_read);
3436 
3437  if (fcb->ads)
3439  else if (make_inline) {
3440  uint16_t edsize;
3441  EXTENT_DATA* ed;
3442 
3443  Status = excise_extents(Vcb, fcb, 0, sector_align(fcb->inode_item.st_size, Vcb->superblock.sector_size), Irp, &rollback);
3444  if (!NT_SUCCESS(Status)) {
3445  ERR("excise_extents returned %08lx\n", Status);
3446  ExFreePool(data2);
3447  goto end;
3448  }
3449 
3450  edsize = (uint16_t)(offsetof(EXTENT_DATA, data[0]) + datalen2);
3451 
3452  ed = ExAllocatePoolWithTag(PagedPool, edsize, ALLOC_TAG);
3453  if (!ed) {
3454  ERR("out of memory\n");
3455  ExFreePool(data2);
3457  goto end;
3458  }
3459 
3460  ed->generation = Vcb->superblock.generation;
3465  ed->type = EXTENT_TYPE_INLINE;
3466 
3467  RtlCopyMemory(ed->data, data2, datalen2);
3468 
3469  Status = add_extent_to_fcb(fcb, 0, ed, edsize, false, NULL, &rollback);
3470  if (!NT_SUCCESS(Status)) {
3471  ERR("add_extent_to_fcb returned %08lx\n", Status);
3472  ExFreePool(data2);
3473  goto end;
3474  }
3475 
3476  fcb->inode_item.st_blocks += datalen2;
3477  } else {
3478  uint64_t start = ded->TargetFileOffset.QuadPart - (ded->TargetFileOffset.QuadPart & (Vcb->superblock.sector_size - 1));
3479 
3480  Status = do_write_file(fcb, start, start + datalen2, data2, Irp, false, 0, &rollback);
3481  if (!NT_SUCCESS(Status)) {
3482  ERR("do_write_file returned %08lx\n", Status);
3483  ExFreePool(data2);
3484  goto end;
3485  }
3486  }
3487 
3488  ExFreePool(data2);
3489  } else {
3490  LIST_ENTRY* lastextle;
3491 
3492  le = sourcefcb->extents.Flink;
3493  while (le != &sourcefcb->extents) {
3495 
3496  if (!ext->ignore) {
3497  if (ext->offset >= (uint64_t)ded->SourceFileOffset.QuadPart + (uint64_t)ded->ByteCount.QuadPart)
3498  break;
3499 
3500  if (ext->extent_data.type != EXTENT_TYPE_INLINE) {
3501  ULONG extlen = offsetof(extent, extent_data) + sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2);
3502  extent* ext2;
3503  EXTENT_DATA2 *ed2s, *ed2d;
3504  chunk* c;
3505 
3506  ed2s = (EXTENT_DATA2*)ext->extent_data.data;
3507 
3508  if (ext->offset + ed2s->num_bytes <= (uint64_t)ded->SourceFileOffset.QuadPart) {
3509  le = le->Flink;
3510  continue;
3511  }
3512 
3514  if (!ext2) {
3515  ERR("out of memory\n");
3517  goto end;
3518  }
3519 
3520  if (ext->offset < (uint64_t)ded->SourceFileOffset.QuadPart)
3521  ext2->offset = ded->TargetFileOffset.QuadPart;
3522  else
3523  ext2->offset = ext->offset - ded->SourceFileOffset.QuadPart + ded->TargetFileOffset.QuadPart;
3524 
3525  ext2->datalen = sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2);
3526  ext2->unique = false;
3527  ext2->ignore = false;
3528  ext2->inserted = true;
3529 
3530  ext2->extent_data.generation = Vcb->superblock.generation;
3531  ext2->extent_data.decoded_size = ext->extent_data.decoded_size;
3532  ext2->extent_data.compression = ext->extent_data.compression;
3533  ext2->extent_data.encryption = ext->extent_data.encryption;
3534  ext2->extent_data.encoding = ext->extent_data.encoding;
3535  ext2->extent_data.type = ext->extent_data.type;
3536 
3537  ed2d = (EXTENT_DATA2*)ext2->extent_data.data;
3538 
3539  ed2d->address = ed2s->address;
3540  ed2d->size = ed2s->size;
3541 
3542  if (ext->offset < (uint64_t)ded->SourceFileOffset.QuadPart) {
3543  ed2d->offset = ed2s->offset + ded->SourceFileOffset.QuadPart - ext->offset;
3544  ed2d->num_bytes = min((uint64_t)ded->ByteCount.QuadPart, ed2s->num_bytes + ext->offset - ded->SourceFileOffset.QuadPart);
3545  } else {
3546  ed2d->offset = ed2s->offset;
3547  ed2d->num_bytes = min(ded->SourceFileOffset.QuadPart + ded->ByteCount.QuadPart - ext->offset, ed2s->num_bytes);
3548  }
3549 
3550  if (ext->csum) {
3551  if (ext->extent_data.compression == BTRFS_COMPRESSION_NONE) {
3552  ext2->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)((ed2d->num_bytes * Vcb->csum_size) >> Vcb->sector_shift), ALLOC_TAG);
3553  if (!ext2->csum) {
3554  ERR("out of memory\n");
3556  ExFreePool(ext2);
3557  goto end;
3558  }
3559 
3560  RtlCopyMemory(ext2->csum, (uint8_t*)ext->csum + (((ed2d->offset - ed2s->offset) * Vcb->csum_size) >> Vcb->sector_shift),
3561  (ULONG)((ed2d->num_bytes * Vcb->csum_size) >> Vcb->sector_shift));
3562  } else {
3563  ext2->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)((ed2d->size * Vcb->csum_size) >> Vcb->sector_shift), ALLOC_TAG);
3564  if (!ext2->csum) {
3565  ERR("out of memory\n");
3567  ExFreePool(ext2);
3568  goto end;
3569  }
3570 
3571  RtlCopyMemory(ext2->csum, ext->csum, (ULONG)((ed2s->size * Vcb->csum_size) >> Vcb->sector_shift));
3572  }
3573  } else
3574  ext2->csum = NULL;
3575 
3576  InsertTailList(&newexts, &ext2->list_entry);
3577 
3578  c = get_chunk_from_address(Vcb, ed2s->address);
3579  if (!c) {
3580  ERR("get_chunk_from_address(%I64x) failed\n", ed2s->address);
3582  goto end;
3583  }
3584 
3585  Status = update_changed_extent_ref(Vcb, c, ed2s->address, ed2s->size, fcb->subvol->id, fcb->inode, ext2->offset - ed2d->offset,
3586  1, fcb->inode_item.flags & BTRFS_INODE_NODATASUM, false, Irp);
3587  if (!NT_SUCCESS(Status)) {
3588  ERR("update_changed_extent_ref returned %08lx\n", Status);
3589  goto end;
3590  }
3591 
3592  nbytes += ed2d->num_bytes;
3593  }
3594  }
3595 
3596  le = le->Flink;
3597  }
3598 
3600  if (!NT_SUCCESS(Status)) {
3601  ERR("excise_extents returned %08lx\n", Status);
3602 
3603  while (!IsListEmpty(&newexts)) {
3605  ExFreePool(ext);
3606  }
3607 
3608  goto end;
3609  }
3610 
3611  // clear unique flags in source fcb
3612  le = sourcefcb->extents.Flink;
3613  while (le != &sourcefcb->extents) {
3615 
3616  if (!ext->ignore && ext->unique && (ext->extent_data.type == EXTENT_TYPE_REGULAR || ext->extent_data.type == EXTENT_TYPE_PREALLOC)) {
3617  EXTENT_DATA2* ed2s = (EXTENT_DATA2*)ext->extent_data.data;
3618  LIST_ENTRY* le2;
3619 
3620  le2 = newexts.Flink;
3621  while (le2 != &newexts) {
3623 
3624  if (ext2->extent_data.type == EXTENT_TYPE_REGULAR || ext2->extent_data.type == EXTENT_TYPE_PREALLOC) {
3625  EXTENT_DATA2* ed2d = (EXTENT_DATA2*)ext2->extent_data.data;
3626 
3627  if (ed2d->address == ed2s->address && ed2d->size == ed2s->size) {
3628  ext->unique = false;
3629  break;
3630  }
3631  }
3632 
3633  le2 = le2->Flink;
3634  }
3635  }
3636 
3637  le = le->Flink;
3638  }
3639 
3640  lastextle = &fcb->extents;
3641  while (!IsListEmpty(&newexts)) {
3643 
3644  add_extent(fcb, lastextle, ext);
3645  lastextle = &ext->list_entry;
3646  }
3647  }
3648 
3651 
3652  if (fcb->ads) {
3653  ccb->fileref->parent->fcb->inode_item.sequence++;
3654 
3655  if (!ccb->user_set_change_time)
3656  ccb->fileref->parent->fcb->inode_item.st_ctime = now;
3657 
3658  ccb->fileref->parent->fcb->inode_item_changed = true;
3659  mark_fcb_dirty(ccb->fileref->parent->fcb);
3660  } else {
3661  fcb->inode_item.st_blocks += nbytes;
3662  fcb->inode_item.sequence++;
3663 
3664  if (!ccb->user_set_change_time)
3666 
3667  if (!ccb->user_set_write_time) {
3670  }
3671 
3672  fcb->inode_item_changed = true;
3673  fcb->extents_changed = true;
3674  }
3675 
3677 
3678  if (FileObject->SectionObjectPointer->DataSectionObject)
3679  CcPurgeCacheSection(FileObject->SectionObjectPointer, &ded->TargetFileOffset, (ULONG)ded->ByteCount.QuadPart, false);
3680 
3682 
3683 end:
3684  ObDereferenceObject(sourcefo);
3685 
3686  if (NT_SUCCESS(Status))
3688  else
3690 
3691  if (fcb != sourcefcb)
3692  ExReleaseResourceLite(sourcefcb->Header.Resource);
3693 
3694  ExReleaseResourceLite(fcb->Header.Resource);
3695 
3696  ExReleaseResourceLite(&Vcb->tree_lock);
3697 
3698  return Status;
3699 }
#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:1667
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:1033
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:1695
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: 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
Definition: stddef.h:5
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:1364
bool fcb_is_inline(fcb *fcb)
Definition: fsctl.c:3246
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:989
#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 3246 of file fsctl.c.

3246  {
3247  LIST_ENTRY* le;
3248 
3249  le = fcb->extents.Flink;
3250  while (le != &fcb->extents) {
3252 
3253  if (!ext->ignore)
3254  return ext->extent_data.type == EXTENT_TYPE_INLINE;
3255 
3256  le = le->Flink;
3257  }
3258 
3259  return false;
3260 }
#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 4586 of file fsctl.c.

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

2222  {
2223  LIST_ENTRY* le;
2224 
2225  le = Vcb->all_fcbs.Flink;
2226  while (le != &Vcb->all_fcbs) {
2227  struct _fcb* fcb = CONTAINING_RECORD(le, struct _fcb, list_entry_all);
2229 
2230  if (fcb->type != BTRFS_TYPE_DIRECTORY && !fcb->deleted)
2231  CcFlushCache(&fcb->nonpaged->segment_object, NULL, 0, &iosb);
2232 
2233  le = le->Flink;
2234  }
2235 }
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 1705 of file fsctl.c.

1705  {
1706  FILESYSTEM_STATISTICS* fss;
1707 
1708  WARN("STUB: FSCTL_FILESYSTEM_GET_STATISTICS\n");
1709 
1710  // This is hideously wrong, but at least it stops SMB from breaking
1711 
1712  if (buflen < sizeof(FILESYSTEM_STATISTICS))
1713  return STATUS_BUFFER_TOO_SMALL;
1714 
1715  fss = buffer;
1716  RtlZeroMemory(fss, sizeof(FILESYSTEM_STATISTICS));
1717 
1718  fss->Version = 1;
1721 
1722  *retlen = sizeof(FILESYSTEM_STATISTICS);
1723 
1724  return STATUS_SUCCESS;
1725 }
#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 4170 of file fsctl.c.

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

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