ReactOS  0.4.15-dev-1068-g467feb9
send.c File Reference
#include "btrfs_drv.h"
#include "crc32c.h"
Include dependency graph for send.c:

Go to the source code of this file.

Classes

struct  send_dir
 
struct  orphan
 
struct  deleted_child
 
struct  ref
 
struct  pending_rmdir
 
struct  send_ext
 
struct  send_context
 
struct  xattr_cmp
 

Macros

#define MAX_SEND_WRITE   0xc000
 
#define SEND_BUFFER_LENGTH   0x100000
 

Typedefs

typedef struct send_dir send_dir
 

Functions

static NTSTATUS find_send_dir (send_context *context, uint64_t dir, uint64_t generation, send_dir **psd, bool *added_dummy)
 
static NTSTATUS wait_for_flush (send_context *context, traverse_ptr *tp1, traverse_ptr *tp2)
 
static void send_command (send_context *context, uint16_t cmd)
 
static void send_command_finish (send_context *context, ULONG pos)
 
static void send_add_tlv (send_context *context, uint16_t type, void *data, uint16_t length)
 
static charuint64_to_char (uint64_t num, char *buf)
 
static NTSTATUS get_orphan_name (send_context *context, uint64_t inode, uint64_t generation, char *name)
 
static void add_orphan (send_context *context, orphan *o)
 
static NTSTATUS send_read_symlink (send_context *context, uint64_t inode, char **link, uint16_t *linklen)
 
static NTSTATUS send_inode (send_context *context, traverse_ptr *tp, traverse_ptr *tp2)
 
static NTSTATUS send_add_dir (send_context *context, uint64_t inode, send_dir *parent, char *name, uint16_t namelen, bool dummy, LIST_ENTRY *lastentry, send_dir **psd)
 
static __inline uint16_t find_path_len (send_dir *parent, uint16_t namelen)
 
static void find_path (char *path, send_dir *parent, char *name, ULONG namelen)
 
static void send_add_tlv_path (send_context *context, uint16_t type, send_dir *parent, char *name, uint16_t namelen)
 
static NTSTATUS found_path (send_context *context, send_dir *parent, char *name, uint16_t namelen)
 
static void send_utimes_command_dir (send_context *context, send_dir *sd, BTRFS_TIME *atime, BTRFS_TIME *mtime, BTRFS_TIME *ctime)
 
static NTSTATUS send_inode_ref (send_context *context, traverse_ptr *tp, bool tree2)
 
static NTSTATUS send_inode_extref (send_context *context, traverse_ptr *tp, bool tree2)
 
static void send_subvol_header (send_context *context, root *r, file_ref *fr)
 
static void send_chown_command (send_context *context, char *path, uint64_t uid, uint64_t gid)
 
static void send_chmod_command (send_context *context, char *path, uint64_t mode)
 
static void send_utimes_command (send_context *context, char *path, BTRFS_TIME *atime, BTRFS_TIME *mtime, BTRFS_TIME *ctime)
 
static void send_truncate_command (send_context *context, char *path, uint64_t size)
 
static NTSTATUS send_unlink_command (send_context *context, send_dir *parent, uint16_t namelen, char *name)
 
static void send_rmdir_command (send_context *context, uint16_t pathlen, char *path)
 
static NTSTATUS get_dir_last_child (send_context *context, uint64_t *last_inode)
 
static NTSTATUS add_pending_rmdir (send_context *context, uint64_t last_inode)
 
static NTSTATUS look_for_collision (send_context *context, send_dir *sd, char *name, ULONG namelen, uint64_t *inode, bool *dir)
 
static NTSTATUS make_file_orphan (send_context *context, uint64_t inode, bool dir, uint64_t generation, ref *r)
 
static NTSTATUS flush_refs (send_context *context, traverse_ptr *tp1, traverse_ptr *tp2)
 
static NTSTATUS add_ext_holes (device_extension *Vcb, LIST_ENTRY *exts, uint64_t size)
 
static NTSTATUS divide_ext (send_ext *ext, uint64_t len, bool trunc)
 
static NTSTATUS sync_ext_cutoff_points (send_context *context)
 
static bool send_add_tlv_clone_path (send_context *context, root *r, uint64_t inode)
 
static bool try_clone_edr (send_context *context, send_ext *se, EXTENT_DATA_REF *edr)
 
static bool try_clone (send_context *context, send_ext *se)
 
static NTSTATUS flush_extents (send_context *context, traverse_ptr *tp1, traverse_ptr *tp2)
 
static NTSTATUS finish_inode (send_context *context, traverse_ptr *tp1, traverse_ptr *tp2)
 
static NTSTATUS send_extent_data (send_context *context, traverse_ptr *tp, traverse_ptr *tp2)
 
static NTSTATUS send_xattr (send_context *context, traverse_ptr *tp, traverse_ptr *tp2)
 
 _Function_class_ (KSTART_ROUTINE)
 
NTSTATUS send_subvol (device_extension *Vcb, void *data, ULONG datalen, PFILE_OBJECT FileObject, PIRP Irp)
 
NTSTATUS read_send_buffer (device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG datalen, ULONG_PTR *retlen, KPROCESSOR_MODE processor_mode)
 

Macro Definition Documentation

◆ MAX_SEND_WRITE

#define MAX_SEND_WRITE   0xc000

Definition at line 110 of file send.c.

◆ SEND_BUFFER_LENGTH

#define SEND_BUFFER_LENGTH   0x100000

Definition at line 111 of file send.c.

Typedef Documentation

◆ send_dir

Function Documentation

◆ _Function_class_()

_Function_class_ ( KSTART_ROUTINE  )

Definition at line 2970 of file send.c.

2971  {
2973  NTSTATUS Status;
2974  KEY searchkey;
2975  traverse_ptr tp, tp2;
2976 
2977  InterlockedIncrement(&context->root->send_ops);
2978 
2979  if (context->parent)
2980  InterlockedIncrement(&context->parent->send_ops);
2981 
2982  if (context->clones) {
2983  ULONG i;
2984 
2985  for (i = 0; i < context->num_clones; i++) {
2986  InterlockedIncrement(&context->clones[i]->send_ops);
2987  }
2988  }
2989 
2990  ExAcquireResourceExclusiveLite(&context->Vcb->tree_lock, true);
2991 
2992  flush_subvol_fcbs(context->root);
2993 
2994  if (context->parent)
2995  flush_subvol_fcbs(context->parent);
2996 
2997  if (context->Vcb->need_write)
2998  Status = do_write(context->Vcb, NULL);
2999  else
3001 
3002  free_trees(context->Vcb);
3003 
3004  if (!NT_SUCCESS(Status)) {
3005  ERR("do_write returned %08lx\n", Status);
3006  ExReleaseResourceLite(&context->Vcb->tree_lock);
3007  goto end;
3008  }
3009 
3010  ExConvertExclusiveToSharedLite(&context->Vcb->tree_lock);
3011 
3012  searchkey.obj_id = searchkey.offset = 0;
3013  searchkey.obj_type = 0;
3014 
3015  Status = find_item(context->Vcb, context->root, &tp, &searchkey, false, NULL);
3016  if (!NT_SUCCESS(Status)) {
3017  ERR("find_item returned %08lx\n", Status);
3018  ExReleaseResourceLite(&context->Vcb->tree_lock);
3019  goto end;
3020  }
3021 
3022  if (context->parent) {
3023  bool ended1 = false, ended2 = false;
3024  Status = find_item(context->Vcb, context->parent, &tp2, &searchkey, false, NULL);
3025  if (!NT_SUCCESS(Status)) {
3026  ERR("find_item returned %08lx\n", Status);
3027  ExReleaseResourceLite(&context->Vcb->tree_lock);
3028  goto end;
3029  }
3030 
3031  do {
3032  traverse_ptr next_tp;
3033 
3034  if (context->datalen > SEND_BUFFER_LENGTH) {
3035  KEY key1 = tp.item->key, key2 = tp2.item->key;
3036 
3037  ExReleaseResourceLite(&context->Vcb->tree_lock);
3038 
3039  KeClearEvent(&context->send->cleared_event);
3040  KeSetEvent(&context->buffer_event, 0, true);
3041  KeWaitForSingleObject(&context->send->cleared_event, Executive, KernelMode, false, NULL);
3042 
3043  if (context->send->cancelling)
3044  goto end;
3045 
3046  ExAcquireResourceSharedLite(&context->Vcb->tree_lock, true);
3047 
3048  if (!ended1) {
3049  Status = find_item(context->Vcb, context->root, &tp, &key1, false, NULL);
3050  if (!NT_SUCCESS(Status)) {
3051  ERR("find_item returned %08lx\n", Status);
3052  ExReleaseResourceLite(&context->Vcb->tree_lock);
3053  goto end;
3054  }
3055 
3056  if (keycmp(tp.item->key, key1)) {
3057  ERR("readonly subvolume changed\n");
3058  ExReleaseResourceLite(&context->Vcb->tree_lock);
3060  goto end;
3061  }
3062  }
3063 
3064  if (!ended2) {
3065  Status = find_item(context->Vcb, context->parent, &tp2, &key2, false, NULL);
3066  if (!NT_SUCCESS(Status)) {
3067  ERR("find_item returned %08lx\n", Status);
3068  ExReleaseResourceLite(&context->Vcb->tree_lock);
3069  goto end;
3070  }
3071 
3072  if (keycmp(tp2.item->key, key2)) {
3073  ERR("readonly subvolume changed\n");
3074  ExReleaseResourceLite(&context->Vcb->tree_lock);
3076  goto end;
3077  }
3078  }
3079  }
3080 
3081  while (!ended1 && !ended2 && tp.tree->header.address == tp2.tree->header.address) {
3082  Status = skip_to_difference(context->Vcb, &tp, &tp2, &ended1, &ended2);
3083  if (!NT_SUCCESS(Status)) {
3084  ERR("skip_to_difference returned %08lx\n", Status);
3085  ExReleaseResourceLite(&context->Vcb->tree_lock);
3086  goto end;
3087  }
3088  }
3089 
3090  if (!ended1 && !ended2 && !keycmp(tp.item->key, tp2.item->key)) {
3091  bool no_next = false, no_next2 = false;
3092 
3093  TRACE("~ %I64x,%x,%I64x\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset);
3094 
3095  if (context->lastinode.inode != 0 && tp.item->key.obj_id > context->lastinode.inode) {
3096  Status = finish_inode(context, ended1 ? NULL : &tp, ended2 ? NULL : &tp2);
3097  if (!NT_SUCCESS(Status)) {
3098  ERR("finish_inode returned %08lx\n", Status);
3099  ExReleaseResourceLite(&context->Vcb->tree_lock);
3100  goto end;
3101  }
3102 
3103  if (context->send->cancelling) {
3104  ExReleaseResourceLite(&context->Vcb->tree_lock);
3105  goto end;
3106  }
3107  }
3108 
3109  if (tp.item->key.obj_type == TYPE_INODE_ITEM) {
3110  if (tp.item->size == tp2.item->size && tp.item->size > 0 && RtlCompareMemory(tp.item->data, tp2.item->data, tp.item->size) == tp.item->size) {
3112 
3113  while (true) {
3114  if (!find_next_item(context->Vcb, &tp, &next_tp, false, NULL)) {
3115  ended1 = true;
3116  break;
3117  }
3118 
3119  tp = next_tp;
3120 
3121  if (tp.item->key.obj_id != inode)
3122  break;
3123  }
3124 
3125  while (true) {
3126  if (!find_next_item(context->Vcb, &tp2, &next_tp, false, NULL)) {
3127  ended2 = true;
3128  break;
3129  }
3130 
3131  tp2 = next_tp;
3132 
3133  if (tp2.item->key.obj_id != inode)
3134  break;
3135  }
3136 
3137  no_next = true;
3138  } else if (tp.item->size > sizeof(uint64_t) && tp2.item->size > sizeof(uint64_t) && *(uint64_t*)tp.item->data != *(uint64_t*)tp2.item->data) {
3140 
3141  Status = send_inode(context, NULL, &tp2);
3142  if (!NT_SUCCESS(Status)) {
3143  ERR("send_inode returned %08lx\n", Status);
3144  ExReleaseResourceLite(&context->Vcb->tree_lock);
3145  goto end;
3146  }
3147 
3148  while (true) {
3149  if (!find_next_item(context->Vcb, &tp2, &next_tp, false, NULL)) {
3150  ended2 = true;
3151  break;
3152  }
3153 
3154  tp2 = next_tp;
3155 
3156  if (tp2.item->key.obj_id != inode)
3157  break;
3158 
3159  if (tp2.item->key.obj_type == TYPE_INODE_REF) {
3160  Status = send_inode_ref(context, &tp2, true);
3161  if (!NT_SUCCESS(Status)) {
3162  ERR("send_inode_ref returned %08lx\n", Status);
3163  ExReleaseResourceLite(&context->Vcb->tree_lock);
3164  goto end;
3165  }
3166  } else if (tp2.item->key.obj_type == TYPE_INODE_EXTREF) {
3167  Status = send_inode_extref(context, &tp2, true);
3168  if (!NT_SUCCESS(Status)) {
3169  ERR("send_inode_extref returned %08lx\n", Status);
3170  ExReleaseResourceLite(&context->Vcb->tree_lock);
3171  goto end;
3172  }
3173  }
3174  }
3175 
3176  Status = finish_inode(context, ended1 ? NULL : &tp, ended2 ? NULL : &tp2);
3177  if (!NT_SUCCESS(Status)) {
3178  ERR("finish_inode returned %08lx\n", Status);
3179  ExReleaseResourceLite(&context->Vcb->tree_lock);
3180  goto end;
3181  }
3182 
3183  if (context->send->cancelling) {
3184  ExReleaseResourceLite(&context->Vcb->tree_lock);
3185  goto end;
3186  }
3187 
3188  no_next2 = true;
3189 
3191  if (!NT_SUCCESS(Status)) {
3192  ERR("send_inode returned %08lx\n", Status);
3193  ExReleaseResourceLite(&context->Vcb->tree_lock);
3194  goto end;
3195  }
3196  } else {
3197  Status = send_inode(context, &tp, &tp2);
3198  if (!NT_SUCCESS(Status)) {
3199  ERR("send_inode returned %08lx\n", Status);
3200  ExReleaseResourceLite(&context->Vcb->tree_lock);
3201  goto end;
3202  }
3203  }
3204  } else if (tp.item->key.obj_type == TYPE_INODE_REF) {
3205  Status = send_inode_ref(context, &tp, false);
3206  if (!NT_SUCCESS(Status)) {
3207  ERR("send_inode_ref returned %08lx\n", Status);
3208  ExReleaseResourceLite(&context->Vcb->tree_lock);
3209  goto end;
3210  }
3211 
3212  Status = send_inode_ref(context, &tp2, true);
3213  if (!NT_SUCCESS(Status)) {
3214  ERR("send_inode_ref returned %08lx\n", Status);
3215  ExReleaseResourceLite(&context->Vcb->tree_lock);
3216  goto end;
3217  }
3218  } else if (tp.item->key.obj_type == TYPE_INODE_EXTREF) {
3219  Status = send_inode_extref(context, &tp, false);
3220  if (!NT_SUCCESS(Status)) {
3221  ERR("send_inode_extref returned %08lx\n", Status);
3222  ExReleaseResourceLite(&context->Vcb->tree_lock);
3223  goto end;
3224  }
3225 
3226  Status = send_inode_extref(context, &tp2, true);
3227  if (!NT_SUCCESS(Status)) {
3228  ERR("send_inode_extref returned %08lx\n", Status);
3229  ExReleaseResourceLite(&context->Vcb->tree_lock);
3230  goto end;
3231  }
3232  } else if (tp.item->key.obj_type == TYPE_EXTENT_DATA) {
3233  Status = send_extent_data(context, &tp, &tp2);
3234  if (!NT_SUCCESS(Status)) {
3235  ERR("send_extent_data returned %08lx\n", Status);
3236  ExReleaseResourceLite(&context->Vcb->tree_lock);
3237  goto end;
3238  }
3239 
3240  if (context->send->cancelling) {
3241  ExReleaseResourceLite(&context->Vcb->tree_lock);
3242  goto end;
3243  }
3244  } else if (tp.item->key.obj_type == TYPE_XATTR_ITEM) {
3245  Status = send_xattr(context, &tp, &tp2);
3246  if (!NT_SUCCESS(Status)) {
3247  ERR("send_xattr returned %08lx\n", Status);
3248  ExReleaseResourceLite(&context->Vcb->tree_lock);
3249  goto end;
3250  }
3251 
3252  if (context->send->cancelling) {
3253  ExReleaseResourceLite(&context->Vcb->tree_lock);
3254  goto end;
3255  }
3256  }
3257 
3258  if (!no_next) {
3259  if (find_next_item(context->Vcb, &tp, &next_tp, false, NULL))
3260  tp = next_tp;
3261  else
3262  ended1 = true;
3263 
3264  if (!no_next2) {
3265  if (find_next_item(context->Vcb, &tp2, &next_tp, false, NULL))
3266  tp2 = next_tp;
3267  else
3268  ended2 = true;
3269  }
3270  }
3271  } else if (ended2 || (!ended1 && !ended2 && keycmp(tp.item->key, tp2.item->key) == -1)) {
3272  TRACE("A %I64x,%x,%I64x\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset);
3273 
3274  if (context->lastinode.inode != 0 && tp.item->key.obj_id > context->lastinode.inode) {
3275  Status = finish_inode(context, ended1 ? NULL : &tp, ended2 ? NULL : &tp2);
3276  if (!NT_SUCCESS(Status)) {
3277  ERR("finish_inode returned %08lx\n", Status);
3278  ExReleaseResourceLite(&context->Vcb->tree_lock);
3279  goto end;
3280  }
3281 
3282  if (context->send->cancelling) {
3283  ExReleaseResourceLite(&context->Vcb->tree_lock);
3284  goto end;
3285  }
3286  }
3287 
3288  if (tp.item->key.obj_type == TYPE_INODE_ITEM) {
3290  if (!NT_SUCCESS(Status)) {
3291  ERR("send_inode returned %08lx\n", Status);
3292  ExReleaseResourceLite(&context->Vcb->tree_lock);
3293  goto end;
3294  }
3295  } else if (tp.item->key.obj_type == TYPE_INODE_REF) {
3296  Status = send_inode_ref(context, &tp, false);
3297  if (!NT_SUCCESS(Status)) {
3298  ERR("send_inode_ref returned %08lx\n", Status);
3299  ExReleaseResourceLite(&context->Vcb->tree_lock);
3300  goto end;
3301  }
3302  } else if (tp.item->key.obj_type == TYPE_INODE_EXTREF) {
3303  Status = send_inode_extref(context, &tp, false);
3304  if (!NT_SUCCESS(Status)) {
3305  ERR("send_inode_extref returned %08lx\n", Status);
3306  ExReleaseResourceLite(&context->Vcb->tree_lock);
3307  goto end;
3308  }
3309  } else if (tp.item->key.obj_type == TYPE_EXTENT_DATA) {
3311  if (!NT_SUCCESS(Status)) {
3312  ERR("send_extent_data returned %08lx\n", Status);
3313  ExReleaseResourceLite(&context->Vcb->tree_lock);
3314  goto end;
3315  }
3316 
3317  if (context->send->cancelling) {
3318  ExReleaseResourceLite(&context->Vcb->tree_lock);
3319  goto end;
3320  }
3321  } else if (tp.item->key.obj_type == TYPE_XATTR_ITEM) {
3323  if (!NT_SUCCESS(Status)) {
3324  ERR("send_xattr returned %08lx\n", Status);
3325  ExReleaseResourceLite(&context->Vcb->tree_lock);
3326  goto end;
3327  }
3328 
3329  if (context->send->cancelling) {
3330  ExReleaseResourceLite(&context->Vcb->tree_lock);
3331  goto end;
3332  }
3333  }
3334 
3335  if (find_next_item(context->Vcb, &tp, &next_tp, false, NULL))
3336  tp = next_tp;
3337  else
3338  ended1 = true;
3339  } else if (ended1 || (!ended1 && !ended2 && keycmp(tp.item->key, tp2.item->key) == 1)) {
3340  TRACE("B %I64x,%x,%I64x\n", tp2.item->key.obj_id, tp2.item->key.obj_type, tp2.item->key.offset);
3341 
3342  if (context->lastinode.inode != 0 && tp2.item->key.obj_id > context->lastinode.inode) {
3343  Status = finish_inode(context, ended1 ? NULL : &tp, ended2 ? NULL : &tp2);
3344  if (!NT_SUCCESS(Status)) {
3345  ERR("finish_inode returned %08lx\n", Status);
3346  ExReleaseResourceLite(&context->Vcb->tree_lock);
3347  goto end;
3348  }
3349 
3350  if (context->send->cancelling) {
3351  ExReleaseResourceLite(&context->Vcb->tree_lock);
3352  goto end;
3353  }
3354  }
3355 
3356  if (tp2.item->key.obj_type == TYPE_INODE_ITEM) {
3357  Status = send_inode(context, NULL, &tp2);
3358  if (!NT_SUCCESS(Status)) {
3359  ERR("send_inode returned %08lx\n", Status);
3360  ExReleaseResourceLite(&context->Vcb->tree_lock);
3361  goto end;
3362  }
3363  } else if (tp2.item->key.obj_type == TYPE_INODE_REF) {
3364  Status = send_inode_ref(context, &tp2, true);
3365  if (!NT_SUCCESS(Status)) {
3366  ERR("send_inode_ref returned %08lx\n", Status);
3367  ExReleaseResourceLite(&context->Vcb->tree_lock);
3368  goto end;
3369  }
3370  } else if (tp2.item->key.obj_type == TYPE_INODE_EXTREF) {
3371  Status = send_inode_extref(context, &tp2, true);
3372  if (!NT_SUCCESS(Status)) {
3373  ERR("send_inode_extref returned %08lx\n", Status);
3374  ExReleaseResourceLite(&context->Vcb->tree_lock);
3375  goto end;
3376  }
3377  } else if (tp2.item->key.obj_type == TYPE_EXTENT_DATA && !context->lastinode.deleting) {
3378  Status = send_extent_data(context, NULL, &tp2);
3379  if (!NT_SUCCESS(Status)) {
3380  ERR("send_extent_data returned %08lx\n", Status);
3381  ExReleaseResourceLite(&context->Vcb->tree_lock);
3382  goto end;
3383  }
3384 
3385  if (context->send->cancelling) {
3386  ExReleaseResourceLite(&context->Vcb->tree_lock);
3387  goto end;
3388  }
3389  } else if (tp2.item->key.obj_type == TYPE_XATTR_ITEM && !context->lastinode.deleting) {
3390  Status = send_xattr(context, NULL, &tp2);
3391  if (!NT_SUCCESS(Status)) {
3392  ERR("send_xattr returned %08lx\n", Status);
3393  ExReleaseResourceLite(&context->Vcb->tree_lock);
3394  goto end;
3395  }
3396 
3397  if (context->send->cancelling) {
3398  ExReleaseResourceLite(&context->Vcb->tree_lock);
3399  goto end;
3400  }
3401  }
3402 
3403  if (find_next_item(context->Vcb, &tp2, &next_tp, false, NULL))
3404  tp2 = next_tp;
3405  else
3406  ended2 = true;
3407  }
3408  } while (!ended1 || !ended2);
3409  } else {
3410  do {
3411  traverse_ptr next_tp;
3412 
3413  if (context->datalen > SEND_BUFFER_LENGTH) {
3414  KEY key = tp.item->key;
3415 
3416  ExReleaseResourceLite(&context->Vcb->tree_lock);
3417 
3418  KeClearEvent(&context->send->cleared_event);
3419  KeSetEvent(&context->buffer_event, 0, true);
3420  KeWaitForSingleObject(&context->send->cleared_event, Executive, KernelMode, false, NULL);
3421 
3422  if (context->send->cancelling)
3423  goto end;
3424 
3425  ExAcquireResourceSharedLite(&context->Vcb->tree_lock, true);
3426 
3427  Status = find_item(context->Vcb, context->root, &tp, &key, false, NULL);
3428  if (!NT_SUCCESS(Status)) {
3429  ERR("find_item returned %08lx\n", Status);
3430  ExReleaseResourceLite(&context->Vcb->tree_lock);
3431  goto end;
3432  }
3433 
3434  if (keycmp(tp.item->key, key)) {
3435  ERR("readonly subvolume changed\n");
3436  ExReleaseResourceLite(&context->Vcb->tree_lock);
3438  goto end;
3439  }
3440  }
3441 
3442  if (context->lastinode.inode != 0 && tp.item->key.obj_id > context->lastinode.inode) {
3444  if (!NT_SUCCESS(Status)) {
3445  ERR("finish_inode returned %08lx\n", Status);
3446  ExReleaseResourceLite(&context->Vcb->tree_lock);
3447  goto end;
3448  }
3449 
3450  if (context->send->cancelling) {
3451  ExReleaseResourceLite(&context->Vcb->tree_lock);
3452  goto end;
3453  }
3454  }
3455 
3456  if (tp.item->key.obj_type == TYPE_INODE_ITEM) {
3458  if (!NT_SUCCESS(Status)) {
3459  ERR("send_inode returned %08lx\n", Status);
3460  ExReleaseResourceLite(&context->Vcb->tree_lock);
3461  goto end;
3462  }
3463  } else if (tp.item->key.obj_type == TYPE_INODE_REF) {
3464  Status = send_inode_ref(context, &tp, false);
3465  if (!NT_SUCCESS(Status)) {
3466  ERR("send_inode_ref returned %08lx\n", Status);
3467  ExReleaseResourceLite(&context->Vcb->tree_lock);
3468  goto end;
3469  }
3470  } else if (tp.item->key.obj_type == TYPE_INODE_EXTREF) {
3471  Status = send_inode_extref(context, &tp, false);
3472  if (!NT_SUCCESS(Status)) {
3473  ERR("send_inode_extref returned %08lx\n", Status);
3474  ExReleaseResourceLite(&context->Vcb->tree_lock);
3475  goto end;
3476  }
3477  } else if (tp.item->key.obj_type == TYPE_EXTENT_DATA) {
3479  if (!NT_SUCCESS(Status)) {
3480  ERR("send_extent_data returned %08lx\n", Status);
3481  ExReleaseResourceLite(&context->Vcb->tree_lock);
3482  goto end;
3483  }
3484 
3485  if (context->send->cancelling) {
3486  ExReleaseResourceLite(&context->Vcb->tree_lock);
3487  goto end;
3488  }
3489  } else if (tp.item->key.obj_type == TYPE_XATTR_ITEM) {
3491  if (!NT_SUCCESS(Status)) {
3492  ERR("send_xattr returned %08lx\n", Status);
3493  ExReleaseResourceLite(&context->Vcb->tree_lock);
3494  goto end;
3495  }
3496 
3497  if (context->send->cancelling) {
3498  ExReleaseResourceLite(&context->Vcb->tree_lock);
3499  goto end;
3500  }
3501  }
3502 
3503  if (find_next_item(context->Vcb, &tp, &next_tp, false, NULL))
3504  tp = next_tp;
3505  else
3506  break;
3507  } while (true);
3508  }
3509 
3510  if (context->lastinode.inode != 0) {
3512  if (!NT_SUCCESS(Status)) {
3513  ERR("finish_inode returned %08lx\n", Status);
3514  ExReleaseResourceLite(&context->Vcb->tree_lock);
3515  goto end;
3516  }
3517 
3518  ExReleaseResourceLite(&context->Vcb->tree_lock);
3519 
3520  if (context->send->cancelling)
3521  goto end;
3522  } else
3523  ExReleaseResourceLite(&context->Vcb->tree_lock);
3524 
3525  KeClearEvent(&context->send->cleared_event);
3526  KeSetEvent(&context->buffer_event, 0, true);
3527  KeWaitForSingleObject(&context->send->cleared_event, Executive, KernelMode, false, NULL);
3528 
3530 
3531 end:
3532  if (!NT_SUCCESS(Status)) {
3533  KeSetEvent(&context->buffer_event, 0, false);
3534 
3535  if (context->send->ccb)
3536  context->send->ccb->send_status = Status;
3537  }
3538 
3539  ExAcquireResourceExclusiveLite(&context->Vcb->send_load_lock, true);
3540 
3541  while (!IsListEmpty(&context->orphans)) {
3543  ExFreePool(o);
3544  }
3545 
3546  while (!IsListEmpty(&context->dirs)) {
3548 
3549  if (sd->name)
3550  ExFreePool(sd->name);
3551 
3552  while (!IsListEmpty(&sd->deleted_children)) {
3554  ExFreePool(dc);
3555  }
3556 
3557  ExFreePool(sd);
3558  }
3559 
3560  ZwClose(context->send->thread);
3561  context->send->thread = NULL;
3562 
3563  if (context->send->ccb)
3564  context->send->ccb->send = NULL;
3565 
3566  RemoveEntryList(&context->send->list_entry);
3567  ExFreePool(context->send);
3568  ExFreePool(context->data);
3569 
3570  InterlockedDecrement(&context->Vcb->running_sends);
3571  InterlockedDecrement(&context->root->send_ops);
3572 
3573  if (context->parent)
3574  InterlockedDecrement(&context->parent->send_ops);
3575 
3576  ExReleaseResourceLite(&context->Vcb->send_load_lock);
3577 
3578  if (context->clones) {
3579  ULONG i;
3580 
3581  for (i = 0; i < context->num_clones; i++) {
3582  InterlockedDecrement(&context->clones[i]->send_ops);
3583  }
3584 
3585  ExFreePool(context->clones);
3586  }
3587 
3589 
3591 }
uint64_t obj_id
Definition: btrfs.h:137
static NTSTATUS send_inode_ref(send_context *context, traverse_ptr *tp, bool tree2)
Definition: send.c:770
uint8_t obj_type
Definition: btrfs.h:138
GLuint64EXT GLuint GLuint GLenum GLenum GLuint GLuint GLenum GLuint GLuint key1
Definition: glext.h:10608
Definition: send.c:34
Definition: http.c:7094
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
NTSTATUS do_write(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7789
#define keycmp(key1, key2)
Definition: btrfs_drv.h:1024
VOID NTAPI ExConvertExclusiveToSharedLite(IN PERESOURCE Resource)
Definition: resource.c:1402
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:430
static NTSTATUS send_inode(send_context *context, traverse_ptr *tp, traverse_ptr *tp2)
Definition: send.c:283
GLuint GLuint end
Definition: gl.h:1545
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
uint64_t offset
Definition: btrfs.h:139
uint8_t * data
Definition: btrfs_drv.h:431
Definition: fs.h:78
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
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
uint64_t address
Definition: btrfs.h:149
tree * tree
Definition: btrfs_drv.h:517
void flush_subvol_fcbs(root *subvol)
Definition: fsctl.c:246
smooth NULL
Definition: ftsmooth.c:416
#define TYPE_INODE_REF
Definition: btrfs.h:20
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
void free_trees(device_extension *Vcb)
Definition: treefuncs.c:794
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2930
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
static NTSTATUS send_extent_data(send_context *context, traverse_ptr *tp, traverse_ptr *tp2)
Definition: send.c:2619
static NTSTATUS finish_inode(send_context *context, traverse_ptr *tp1, traverse_ptr *tp2)
Definition: send.c:2532
#define TRACE(s)
Definition: solgame.cpp:4
#define TYPE_XATTR_ITEM
Definition: btrfs.h:22
bool find_next_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, const traverse_ptr *tp, traverse_ptr *next_tp, bool ignore, PIRP Irp)
Definition: treefuncs.c:593
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
Definition: send.c:21
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
static const WCHAR sd[]
Definition: suminfo.c:287
tree_data * item
Definition: btrfs_drv.h:518
Status
Definition: gdiplustypes.h:24
tree_header header
Definition: btrfs_drv.h:442
#define InterlockedDecrement
Definition: armddk.h:52
#define TYPE_INODE_EXTREF
Definition: btrfs.h:21
#define TYPE_INODE_ITEM
Definition: btrfs.h:19
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:136
NTSTATUS skip_to_difference(device_extension *Vcb, traverse_ptr *tp, traverse_ptr *tp2, bool *ended1, bool *ended2)
Definition: treefuncs.c:369
UINT64 uint64_t
Definition: types.h:77
#define InterlockedIncrement
Definition: armddk.h:53
NTSTATUS NTAPI PsTerminateSystemThread(IN NTSTATUS ExitStatus)
Definition: kill.c:1144
Definition: list.h:27
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
unsigned int ULONG
Definition: retypes.h:1
static const WCHAR dc[]
static NTSTATUS send_xattr(send_context *context, traverse_ptr *tp, traverse_ptr *tp2)
Definition: send.c:2770
static NTSTATUS send_inode_extref(send_context *context, traverse_ptr *tp, bool tree2)
Definition: send.c:872
#define TYPE_EXTENT_DATA
Definition: btrfs.h:26
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
Definition: path.c:41
#define SEND_BUFFER_LENGTH
Definition: send.c:111

◆ add_ext_holes()

static NTSTATUS add_ext_holes ( device_extension Vcb,
LIST_ENTRY exts,
uint64_t  size 
)
static

Definition at line 1652 of file send.c.

1652  {
1653  uint64_t lastoff = 0;
1654  LIST_ENTRY* le;
1655 
1656  le = exts->Flink;
1657  while (le != exts) {
1659 
1660  if (ext->offset > lastoff) {
1662  EXTENT_DATA2* ed2;
1663 
1664  if (!ext2) {
1665  ERR("out of memory\n");
1667  }
1668 
1669  ed2 = (EXTENT_DATA2*)ext2->data.data;
1670 
1671  ext2->offset = lastoff;
1672  ext2->datalen = offsetof(EXTENT_DATA, data) + sizeof(EXTENT_DATA2);
1673  ext2->data.decoded_size = ed2->num_bytes = ext->offset - lastoff;
1674  ext2->data.type = EXTENT_TYPE_REGULAR;
1675  ed2->address = ed2->size = ed2->offset = 0;
1676 
1677  InsertHeadList(le->Blink, &ext2->list_entry);
1678  }
1679 
1680  if (ext->data.type == EXTENT_TYPE_INLINE)
1681  lastoff = ext->offset + ext->data.decoded_size;
1682  else {
1683  EXTENT_DATA2* ed2 = (EXTENT_DATA2*)ext->data.data;
1684  lastoff = ext->offset + ed2->num_bytes;
1685  }
1686 
1687  le = le->Flink;
1688  }
1689 
1690  if (size > lastoff) {
1692  EXTENT_DATA2* ed2;
1693 
1694  if (!ext2) {
1695  ERR("out of memory\n");
1697  }
1698 
1699  ed2 = (EXTENT_DATA2*)ext2->data.data;
1700 
1701  ext2->offset = lastoff;
1702  ext2->datalen = offsetof(EXTENT_DATA, data) + sizeof(EXTENT_DATA2);
1703  ext2->data.decoded_size = ed2->num_bytes = sector_align(size - lastoff, Vcb->superblock.sector_size);
1704  ext2->data.type = EXTENT_TYPE_REGULAR;
1705  ed2->address = ed2->size = ed2->offset = 0;
1706 
1707  InsertTailList(exts, &ext2->list_entry);
1708  }
1709 
1710  return STATUS_SUCCESS;
1711 }
Definition: send.c:61
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
EXTENT_DATA2 * ed2
Definition: write.c:2805
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
#define InsertTailList(ListHead, Entry)
#define ALLOC_TAG
Definition: btrfs_drv.h:91
#define EXTENT_TYPE_INLINE
Definition: btrfs.h:70
uint64_t address
Definition: btrfs.h:356
#define offsetof(TYPE, MEMBER)
char ext[3]
Definition: mkdosfs.c:358
uint64_t size
Definition: btrfs.h:357
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
GLsizeiptr size
Definition: glext.h:5919
#define Vcb
Definition: cdprocs.h:1415
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
static const BYTE ext2[]
Definition: encode.c:2699
Definition: typedefs.h:119
uint64_t num_bytes
Definition: btrfs.h:359
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:71
static const struct encodedExtensions exts[]
Definition: encode.c:2703
#define ERR(fmt,...)
Definition: debug.h:110
UINT64 uint64_t
Definition: types.h:77
Definition: list.h:27
uint64_t offset
Definition: btrfs.h:358
EXTENT_DATA data
Definition: send.c:65
return STATUS_SUCCESS
Definition: btrfs.c:3014
static uint64_t __inline sector_align(uint64_t n, uint64_t a)

Referenced by flush_extents().

◆ add_orphan()

static void add_orphan ( send_context context,
orphan o 
)
static

Definition at line 217 of file send.c.

217  {
218  LIST_ENTRY* le;
219 
220  le = context->orphans.Flink;
221  while (le != &context->orphans) {
223 
224  if (o2->inode > o->inode) {
226  return;
227  }
228 
229  le = le->Flink;
230  }
231 
232  InsertTailList(&context->orphans, &o->list_entry);
233 }
Definition: send.c:34
Definition: http.c:7094
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
#define InsertTailList(ListHead, Entry)
uint64_t inode
Definition: send.c:36
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
Definition: list.h:27
LIST_ENTRY list_entry
Definition: send.c:35

Referenced by make_file_orphan(), send_inode(), send_inode_extref(), and send_inode_ref().

◆ add_pending_rmdir()

static NTSTATUS add_pending_rmdir ( send_context context,
uint64_t  last_inode 
)
static

Definition at line 1103 of file send.c.

1103  {
1104  pending_rmdir* pr;
1105  LIST_ENTRY* le;
1106 
1108  if (!pr) {
1109  ERR("out of memory\n");
1111  }
1112 
1113  pr->sd = context->lastinode.sd;
1114  pr->last_child_inode = last_inode;
1115 
1116  le = context->pending_rmdirs.Flink;
1117  while (le != &context->pending_rmdirs) {
1119 
1120  if (pr2->last_child_inode > pr->last_child_inode) {
1121  InsertHeadList(pr2->list_entry.Blink, &pr->list_entry);
1122  return STATUS_SUCCESS;
1123  }
1124 
1125  le = le->Flink;
1126  }
1127 
1128  InsertTailList(&context->pending_rmdirs, &pr->list_entry);
1129 
1130  return STATUS_SUCCESS;
1131 }
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
static double pr2[6]
Definition: j1_y1.c:326
Definition: http.c:7094
send_dir * sd
Definition: send.c:56
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
LIST_ENTRY list_entry
Definition: send.c:58
#define InsertTailList(ListHead, Entry)
#define ALLOC_TAG
Definition: btrfs_drv.h:91
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 ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
Definition: typedefs.h:119
#define ERR(fmt,...)
Definition: debug.h:110
uint64_t last_child_inode
Definition: send.c:57
Definition: list.h:27
return STATUS_SUCCESS
Definition: btrfs.c:3014

Referenced by flush_refs().

◆ divide_ext()

static NTSTATUS divide_ext ( send_ext ext,
uint64_t  len,
bool  trunc 
)
static

Definition at line 1713 of file send.c.

1713  {
1714  send_ext* ext2;
1715  EXTENT_DATA2 *ed2a, *ed2b;
1716 
1717  if (ext->data.type == EXTENT_TYPE_INLINE) {
1718  if (!trunc) {
1719  ext2 = ExAllocatePoolWithTag(PagedPool, (ULONG)(offsetof(send_ext, data.data) + ext->data.decoded_size - len), ALLOC_TAG);
1720 
1721  if (!ext2) {
1722  ERR("out of memory\n");
1724  }
1725 
1726  ext2->offset = ext->offset + len;
1727  ext2->datalen = (ULONG)(ext->data.decoded_size - len);
1728  ext2->data.decoded_size = ext->data.decoded_size - len;
1729  ext2->data.compression = ext->data.compression;
1730  ext2->data.encryption = ext->data.encryption;
1731  ext2->data.encoding = ext->data.encoding;
1732  ext2->data.type = ext->data.type;
1733  RtlCopyMemory(ext2->data.data, ext->data.data + len, (ULONG)(ext->data.decoded_size - len));
1734 
1735  InsertHeadList(&ext->list_entry, &ext2->list_entry);
1736  }
1737 
1738  ext->data.decoded_size = len;
1739 
1740  return STATUS_SUCCESS;
1741  }
1742 
1743  ed2a = (EXTENT_DATA2*)ext->data.data;
1744 
1745  if (!trunc) {
1747 
1748  if (!ext2) {
1749  ERR("out of memory\n");
1751  }
1752 
1753  ed2b = (EXTENT_DATA2*)ext2->data.data;
1754 
1755  ext2->offset = ext->offset + len;
1756  ext2->datalen = offsetof(EXTENT_DATA, data) + sizeof(EXTENT_DATA2);
1757 
1758  ext2->data.compression = ext->data.compression;
1759  ext2->data.encryption = ext->data.encryption;
1760  ext2->data.encoding = ext->data.encoding;
1761  ext2->data.type = ext->data.type;
1762  ed2b->num_bytes = ed2a->num_bytes - len;
1763 
1764  if (ed2a->size == 0) {
1765  ext2->data.decoded_size = ed2b->num_bytes;
1766  ext->data.decoded_size = len;
1767 
1768  ed2b->address = ed2b->size = ed2b->offset = 0;
1769  } else {
1770  ext2->data.decoded_size = ext->data.decoded_size;
1771 
1772  ed2b->address = ed2a->address;
1773  ed2b->size = ed2a->size;
1774  ed2b->offset = ed2a->offset + len;
1775  }
1776 
1777  InsertHeadList(&ext->list_entry, &ext2->list_entry);
1778  }
1779 
1780  ed2a->num_bytes = len;
1781 
1782  return STATUS_SUCCESS;
1783 }
Definition: send.c:61
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
#define ALLOC_TAG
Definition: btrfs_drv.h:91
#define EXTENT_TYPE_INLINE
Definition: btrfs.h:70
uint64_t address
Definition: btrfs.h:356
double __cdecl trunc(double)
#define offsetof(TYPE, MEMBER)
char ext[3]
Definition: mkdosfs.c:358
uint64_t size
Definition: btrfs.h:357
if(!(yy_init))
Definition: macro.lex.yy.c:714
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
static const BYTE ext2[]
Definition: encode.c:2699
GLenum GLsizei len
Definition: glext.h:6722
uint64_t num_bytes
Definition: btrfs.h:359
#define ERR(fmt,...)
Definition: debug.h:110
unsigned int ULONG
Definition: retypes.h:1
uint64_t offset
Definition: btrfs.h:358
EXTENT_DATA data
Definition: send.c:65
return STATUS_SUCCESS
Definition: btrfs.c:3014

Referenced by sync_ext_cutoff_points().

◆ find_path()

static void find_path ( char path,
send_dir parent,
char name,
ULONG  namelen 
)
static

Definition at line 571 of file send.c.

571  {
572  ULONG len = namelen;
573 
575 
576  while (parent && parent->namelen > 0) {
577  RtlMoveMemory(path + parent->namelen + 1, path, len);
578  RtlCopyMemory(path, parent->name, parent->namelen);
579  path[parent->namelen] = '/';
580  len += parent->namelen + 1;
581 
582  parent = parent->parent;
583  }
584 }
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
GLint namelen
Definition: glext.h:7232
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
r parent
Definition: btrfs.c:2944
GLenum GLsizei len
Definition: glext.h:6722
Definition: name.c:38
unsigned int ULONG
Definition: retypes.h:1

Referenced by flush_refs(), found_path(), send_add_tlv_path(), and send_unlink_command().

◆ find_path_len()

static __inline uint16_t find_path_len ( send_dir parent,
uint16_t  namelen 
)
static

Definition at line 560 of file send.c.

560  {
561  uint16_t len = namelen;
562 
563  while (parent && parent->namelen > 0) {
564  len += parent->namelen + 1;
565  parent = parent->parent;
566  }
567 
568  return len;
569 }
unsigned short int uint16_t
Definition: acefiex.h:54
GLint namelen
Definition: glext.h:7232
r parent
Definition: btrfs.c:2944
GLenum GLsizei len
Definition: glext.h:6722

Referenced by flush_refs(), found_path(), send_add_tlv_path(), and send_unlink_command().

◆ find_send_dir()

static NTSTATUS find_send_dir ( send_context context,
uint64_t  dir,
uint64_t  generation,
send_dir **  psd,
bool added_dummy 
)
static

Definition at line 670 of file send.c.

670  {
672  LIST_ENTRY* le;
673  char name[64];
674 
675  le = context->dirs.Flink;
676  while (le != &context->dirs) {
678 
679  if (sd2->inode > dir)
680  break;
681  else if (sd2->inode == dir) {
682  *psd = sd2;
683 
684  if (added_dummy)
685  *added_dummy = false;
686 
687  return STATUS_SUCCESS;
688  }
689 
690  le = le->Flink;
691  }
692 
693  if (dir == SUBVOL_ROOT_INODE) {
694  Status = send_add_dir(context, dir, NULL, NULL, 0, false, le, psd);
695  if (!NT_SUCCESS(Status)) {
696  ERR("send_add_dir returned %08lx\n", Status);
697  return Status;
698  }
699 
700  if (added_dummy)
701  *added_dummy = false;
702 
703  return STATUS_SUCCESS;
704  }
705 
706  if (context->parent) {
707  KEY searchkey;
709 
710  searchkey.obj_id = dir;
711  searchkey.obj_type = TYPE_INODE_REF; // directories should never have an extiref
712  searchkey.offset = 0xffffffffffffffff;
713 
714  Status = find_item(context->Vcb, context->parent, &tp, &searchkey, false, NULL);
715  if (!NT_SUCCESS(Status)) {
716  ERR("find_item returned %08lx\n", Status);
717  return Status;
718  }
719 
720  if (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == searchkey.obj_type) {
721  INODE_REF* ir = (INODE_REF*)tp.item->data;
722  send_dir* parent;
723 
724  if (tp.item->size < sizeof(INODE_REF) || tp.item->size < offsetof(INODE_REF, name[0]) + ir->n) {
725  ERR("(%I64x,%x,%I64x) was truncated\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset);
726  return STATUS_INTERNAL_ERROR;
727  }
728 
730  parent = context->root_dir;
731  else {
733  if (!NT_SUCCESS(Status)) {
734  ERR("find_send_dir returned %08lx\n", Status);
735  return Status;
736  }
737  }
738 
739  Status = send_add_dir(context, dir, parent, ir->name, ir->n, true, NULL, psd);
740  if (!NT_SUCCESS(Status)) {
741  ERR("send_add_dir returned %08lx\n", Status);
742  return Status;
743  }
744 
745  if (added_dummy)
746  *added_dummy = false;
747 
748  return STATUS_SUCCESS;
749  }
750  }
751 
753  if (!NT_SUCCESS(Status)) {
754  ERR("get_orphan_name returned %08lx\n", Status);
755  return Status;
756  }
757 
758  Status = send_add_dir(context, dir, NULL, name, (uint16_t)strlen(name), true, le, psd);
759  if (!NT_SUCCESS(Status)) {
760  ERR("send_add_dir returned %08lx\n", Status);
761  return Status;
762  }
763 
764  if (added_dummy)
765  *added_dummy = true;
766 
767  return STATUS_SUCCESS;
768 }
uint64_t obj_id
Definition: btrfs.h:137
uint8_t obj_type
Definition: btrfs.h:138
Definition: http.c:7094
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define SUBVOL_ROOT_INODE
Definition: propsheet.cpp:42
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:430
static NTSTATUS get_orphan_name(send_context *context, uint64_t inode, uint64_t generation, char *name)
Definition: send.c:164
unsigned short int uint16_t
Definition: acefiex.h:54
static NTSTATUS send_add_dir(send_context *context, uint64_t inode, send_dir *parent, char *name, uint16_t namelen, bool dummy, LIST_ENTRY *lastentry, send_dir **psd)
Definition: send.c:497
uint64_t offset
Definition: btrfs.h:139
uint8_t * data
Definition: btrfs_drv.h:431
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
char name[1]
Definition: btrfs.h:365
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
#define TYPE_INODE_REF
Definition: btrfs.h:20
unsigned int dir
Definition: maze.c:112
uint16_t n
Definition: btrfs.h:364
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2930
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
r parent
Definition: btrfs.c:2944
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
Definition: send.c:21
tree_data * item
Definition: btrfs_drv.h:518
Status
Definition: gdiplustypes.h:24
Definition: typedefs.h:119
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:136
uint64_t inode
Definition: send.c:23
_In_ uint64_t _In_ uint64_t _In_ uint64_t generation
Definition: btrfs.c:2929
Definition: list.h:27
Definition: name.c:38
return STATUS_SUCCESS
Definition: btrfs.c:3014
static NTSTATUS find_send_dir(send_context *context, uint64_t dir, uint64_t generation, send_dir **psd, bool *added_dummy)
Definition: send.c:670

Referenced by flush_refs(), make_file_orphan(), send_inode(), send_inode_extref(), and send_inode_ref().

◆ finish_inode()

static NTSTATUS finish_inode ( send_context context,
traverse_ptr tp1,
traverse_ptr tp2 
)
static

Definition at line 2532 of file send.c.

2532  {
2533  LIST_ENTRY* le;
2534 
2535  if (!IsListEmpty(&context->lastinode.refs) || !IsListEmpty(&context->lastinode.oldrefs)) {
2536  NTSTATUS Status = flush_refs(context, tp1, tp2);
2537  if (!NT_SUCCESS(Status)) {
2538  ERR("flush_refs returned %08lx\n", Status);
2539  return Status;
2540  }
2541 
2542  if (context->send->cancelling)
2543  return STATUS_SUCCESS;
2544  }
2545 
2546  if (!context->lastinode.deleting) {
2547  if (context->lastinode.file) {
2548  NTSTATUS Status = flush_extents(context, tp1, tp2);
2549  if (!NT_SUCCESS(Status)) {
2550  ERR("flush_extents returned %08lx\n", Status);
2551  return Status;
2552  }
2553 
2554  if (context->send->cancelling)
2555  return STATUS_SUCCESS;
2556 
2557  send_truncate_command(context, context->lastinode.path, context->lastinode.size);
2558  }
2559 
2560  if (context->lastinode.new || context->lastinode.uid != context->lastinode.olduid || context->lastinode.gid != context->lastinode.oldgid)
2561  send_chown_command(context, context->lastinode.path, context->lastinode.uid, context->lastinode.gid);
2562 
2563  if (((context->lastinode.mode & __S_IFLNK) != __S_IFLNK || ((context->lastinode.mode & 07777) != 0777)) &&
2564  (context->lastinode.new || context->lastinode.mode != context->lastinode.oldmode))
2565  send_chmod_command(context, context->lastinode.path, context->lastinode.mode);
2566 
2567  send_utimes_command(context, context->lastinode.path, &context->lastinode.atime, &context->lastinode.mtime, &context->lastinode.ctime);
2568  }
2569 
2570  while (!IsListEmpty(&context->lastinode.exts)) {
2572  }
2573 
2574  while (!IsListEmpty(&context->lastinode.oldexts)) {
2576  }
2577 
2578  if (context->parent) {
2579  le = context->pending_rmdirs.Flink;
2580 
2581  while (le != &context->pending_rmdirs) {
2583 
2584  if (pr->last_child_inode <= context->lastinode.inode) {
2585  le = le->Flink;
2586 
2587  send_rmdir_command(context, pr->sd->namelen, pr->sd->name);
2588 
2589  RemoveEntryList(&pr->sd->list_entry);
2590 
2591  if (pr->sd->name)
2592  ExFreePool(pr->sd->name);
2593 
2594  while (!IsListEmpty(&pr->sd->deleted_children)) {
2596  ExFreePool(dc);
2597  }
2598 
2599  ExFreePool(pr->sd);
2600 
2602  ExFreePool(pr);
2603  } else
2604  break;
2605  }
2606  }
2607 
2608  context->lastinode.inode = 0;
2609  context->lastinode.o = NULL;
2610 
2611  if (context->lastinode.path) {
2612  ExFreePool(context->lastinode.path);
2613  context->lastinode.path = NULL;
2614  }
2615 
2616  return STATUS_SUCCESS;
2617 }
Definition: send.c:61
LIST_ENTRY deleted_children
Definition: send.c:31
Definition: http.c:7094
char * name
Definition: send.c:30
send_dir * sd
Definition: send.c:56
LONG NTSTATUS
Definition: precomp.h:26
static void send_utimes_command(send_context *context, char *path, BTRFS_TIME *atime, BTRFS_TIME *mtime, BTRFS_TIME *ctime)
Definition: send.c:1013
LIST_ENTRY list_entry
Definition: send.c:58
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
static void send_rmdir_command(send_context *context, uint16_t pathlen, char *path)
Definition: send.c:1053
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
uint16_t namelen
Definition: send.c:29
static void send_chmod_command(send_context *context, char *path, uint64_t mode)
Definition: send.c:1000
static NTSTATUS flush_extents(send_context *context, traverse_ptr *tp1, traverse_ptr *tp2)
Definition: send.c:2127
smooth NULL
Definition: ftsmooth.c:416
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
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
static void send_chown_command(send_context *context, char *path, uint64_t uid, uint64_t gid)
Definition: send.c:988
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
Status
Definition: gdiplustypes.h:24
Definition: typedefs.h:119
static void send_truncate_command(send_context *context, char *path, uint64_t size)
Definition: send.c:1026
static NTSTATUS flush_refs(send_context *context, traverse_ptr *tp1, traverse_ptr *tp2)
Definition: send.c:1274
#define ERR(fmt,...)
Definition: debug.h:110
LIST_ENTRY list_entry
Definition: send.c:22
uint64_t last_child_inode
Definition: send.c:57
Definition: list.h:27
static const WCHAR dc[]
#define __S_IFLNK
Definition: btrfs_drv.h:1805
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define ExFreePool(addr)
Definition: env_spec_w32.h:352

Referenced by _Function_class_().

◆ flush_extents()

static NTSTATUS flush_extents ( send_context context,
traverse_ptr tp1,
traverse_ptr tp2 
)
static

Definition at line 2127 of file send.c.

2127  {
2128  NTSTATUS Status;
2129 
2130  if ((IsListEmpty(&context->lastinode.exts) && IsListEmpty(&context->lastinode.oldexts)) || context->lastinode.size == 0)
2131  return STATUS_SUCCESS;
2132 
2133  if (context->parent) {
2134  Status = add_ext_holes(context->Vcb, &context->lastinode.exts, context->lastinode.size);
2135  if (!NT_SUCCESS(Status)) {
2136  ERR("add_ext_holes returned %08lx\n", Status);
2137  return Status;
2138  }
2139 
2140  Status = add_ext_holes(context->Vcb, &context->lastinode.oldexts, context->lastinode.size);
2141  if (!NT_SUCCESS(Status)) {
2142  ERR("add_ext_holes returned %08lx\n", Status);
2143  return Status;
2144  }
2145 
2147  if (!NT_SUCCESS(Status)) {
2148  ERR("sync_ext_cutoff_points returned %08lx\n", Status);
2149  return Status;
2150  }
2151  }
2152 
2153  while (!IsListEmpty(&context->lastinode.exts)) {
2155  send_ext* se2 = context->parent ? CONTAINING_RECORD(RemoveHeadList(&context->lastinode.oldexts), send_ext, list_entry) : NULL;
2156  ULONG pos;
2157  EXTENT_DATA2* ed2;
2158 
2159  if (se2) {
2160  if (se->data.type == EXTENT_TYPE_INLINE && se2->data.type == EXTENT_TYPE_INLINE &&
2162  ExFreePool(se);
2163  ExFreePool(se2);
2164  continue;
2165  }
2166 
2167  if (se->data.type == EXTENT_TYPE_REGULAR && se2->data.type == EXTENT_TYPE_REGULAR) {
2168  EXTENT_DATA2 *ed2a, *ed2b;
2169 
2170  ed2a = (EXTENT_DATA2*)se->data.data;
2171  ed2b = (EXTENT_DATA2*)se2->data.data;
2172 
2173  if (RtlCompareMemory(ed2a, ed2b, sizeof(EXTENT_DATA2)) == sizeof(EXTENT_DATA2)) {
2174  ExFreePool(se);
2175  ExFreePool(se2);
2176  continue;
2177  }
2178  }
2179  }
2180 
2181  if (se->data.type == EXTENT_TYPE_INLINE) {
2182  pos = context->datalen;
2183 
2185 
2186  send_add_tlv(context, BTRFS_SEND_TLV_PATH, context->lastinode.path, context->lastinode.path ? (uint16_t)strlen(context->lastinode.path) : 0);
2188 
2192  ULONG inlen = se->datalen - (ULONG)offsetof(EXTENT_DATA, data[0]);
2193 
2195  RtlZeroMemory(&context->data[context->datalen - se->data.decoded_size], (ULONG)se->data.decoded_size);
2196 
2198  Status = zlib_decompress(se->data.data, inlen, &context->data[context->datalen - se->data.decoded_size], (uint32_t)se->data.decoded_size);
2199  if (!NT_SUCCESS(Status)) {
2200  ERR("zlib_decompress returned %08lx\n", Status);
2201  ExFreePool(se);
2202  if (se2) ExFreePool(se2);
2203  return Status;
2204  }
2205  } else if (se->data.compression == BTRFS_COMPRESSION_LZO) {
2206  if (inlen < sizeof(uint32_t)) {
2207  ERR("extent data was truncated\n");
2208  ExFreePool(se);
2209  if (se2) ExFreePool(se2);
2210  return STATUS_INTERNAL_ERROR;
2211  } else
2212  inlen -= sizeof(uint32_t);
2213 
2214  Status = lzo_decompress(se->data.data + sizeof(uint32_t), inlen, &context->data[context->datalen - se->data.decoded_size], (uint32_t)se->data.decoded_size, sizeof(uint32_t));
2215  if (!NT_SUCCESS(Status)) {
2216  ERR("lzo_decompress returned %08lx\n", Status);
2217  ExFreePool(se);
2218  if (se2) ExFreePool(se2);
2219  return Status;
2220  }
2221  } else if (se->data.compression == BTRFS_COMPRESSION_ZSTD) {
2222  Status = zstd_decompress(se->data.data, inlen, &context->data[context->datalen - se->data.decoded_size], (uint32_t)se->data.decoded_size);
2223  if (!NT_SUCCESS(Status)) {
2224  ERR("zlib_decompress returned %08lx\n", Status);
2225  ExFreePool(se);
2226  if (se2) ExFreePool(se2);
2227  return Status;
2228  }
2229  }
2230  } else {
2231  ERR("unhandled compression type %x\n", se->data.compression);
2232  ExFreePool(se);
2233  if (se2) ExFreePool(se2);
2234  return STATUS_NOT_IMPLEMENTED;
2235  }
2236 
2238 
2239  ExFreePool(se);
2240  if (se2) ExFreePool(se2);
2241  continue;
2242  }
2243 
2244  ed2 = (EXTENT_DATA2*)se->data.data;
2245 
2246  if (ed2->size != 0 && (context->parent || context->num_clones > 0)) {
2247  if (try_clone(context, se)) {
2248  ExFreePool(se);
2249  if (se2) ExFreePool(se2);
2250  continue;
2251  }
2252  }
2253 
2254  if (ed2->size == 0) { // write sparse
2255  uint64_t off, offset;
2256 
2257  for (off = ed2->offset; off < ed2->offset + ed2->num_bytes; off += MAX_SEND_WRITE) {
2258  uint16_t length = (uint16_t)min(min(ed2->offset + ed2->num_bytes - off, MAX_SEND_WRITE), context->lastinode.size - se->offset - off);
2259 
2260  if (context->datalen > SEND_BUFFER_LENGTH) {
2261  Status = wait_for_flush(context, tp1, tp2);
2262  if (!NT_SUCCESS(Status)) {
2263  ERR("wait_for_flush returned %08lx\n", Status);
2264  ExFreePool(se);
2265  if (se2) ExFreePool(se2);
2266  return Status;
2267  }
2268 
2269  if (context->send->cancelling) {
2270  ExFreePool(se);
2271  if (se2) ExFreePool(se2);
2272  return STATUS_SUCCESS;
2273  }
2274  }
2275 
2276  pos = context->datalen;
2277 
2279 
2280  send_add_tlv(context, BTRFS_SEND_TLV_PATH, context->lastinode.path, context->lastinode.path ? (uint16_t)strlen(context->lastinode.path) : 0);
2281 
2282  offset = se->offset + off;
2284 
2286  RtlZeroMemory(&context->data[context->datalen - length], length);
2287 
2289  }
2290  } else if (se->data.compression == BTRFS_COMPRESSION_NONE) {
2291  uint64_t off, offset;
2292  uint8_t* buf;
2293 
2294  buf = ExAllocatePoolWithTag(NonPagedPool, MAX_SEND_WRITE + (2 * context->Vcb->superblock.sector_size), ALLOC_TAG);
2295  if (!buf) {
2296  ERR("out of memory\n");
2297  ExFreePool(se);
2298  if (se2) ExFreePool(se2);
2300  }
2301 
2302  for (off = ed2->offset; off < ed2->offset + ed2->num_bytes; off += MAX_SEND_WRITE) {
2304  ULONG skip_start;
2305  uint64_t addr = ed2->address + off;
2306  void* csum;
2307 
2308  if (context->datalen > SEND_BUFFER_LENGTH) {
2309  Status = wait_for_flush(context, tp1, tp2);
2310  if (!NT_SUCCESS(Status)) {
2311  ERR("wait_for_flush returned %08lx\n", Status);
2312  ExFreePool(buf);
2313  ExFreePool(se);
2314  if (se2) ExFreePool(se2);
2315  return Status;
2316  }
2317 
2318  if (context->send->cancelling) {
2319  ExFreePool(buf);
2320  ExFreePool(se);
2321  if (se2) ExFreePool(se2);
2322  return STATUS_SUCCESS;
2323  }
2324  }
2325 
2326  skip_start = addr % context->Vcb->superblock.sector_size;
2327  addr -= skip_start;
2328 
2329  if (context->lastinode.flags & BTRFS_INODE_NODATASUM)
2330  csum = NULL;
2331  else {
2332  uint32_t len;
2333 
2334  len = (uint32_t)sector_align(length + skip_start, context->Vcb->superblock.sector_size) / context->Vcb->superblock.sector_size;
2335 
2336  csum = ExAllocatePoolWithTag(PagedPool, len * context->Vcb->csum_size, ALLOC_TAG);
2337  if (!csum) {
2338  ERR("out of memory\n");
2339  ExFreePool(buf);
2340  ExFreePool(se);
2341  if (se2) ExFreePool(se2);
2343  }
2344 
2345  Status = load_csum(context->Vcb, csum, addr, len, NULL);
2346  if (!NT_SUCCESS(Status)) {
2347  ERR("load_csum returned %08lx\n", Status);
2348  ExFreePool(csum);
2349  ExFreePool(buf);
2350  ExFreePool(se);
2351  if (se2) ExFreePool(se2);
2353  }
2354  }
2355 
2356  Status = read_data(context->Vcb, addr, (uint32_t)sector_align(length + skip_start, context->Vcb->superblock.sector_size),
2357  csum, false, buf, NULL, NULL, NULL, 0, false, NormalPagePriority);
2358  if (!NT_SUCCESS(Status)) {
2359  ERR("read_data returned %08lx\n", Status);
2360  ExFreePool(buf);
2361  ExFreePool(se);
2362  if (se2) ExFreePool(se2);
2363  if (csum) ExFreePool(csum);
2364  return Status;
2365  }
2366 
2367  if (csum)
2368  ExFreePool(csum);
2369 
2370  pos = context->datalen;
2371 
2373 
2374  send_add_tlv(context, BTRFS_SEND_TLV_PATH, context->lastinode.path, context->lastinode.path ? (uint16_t)strlen(context->lastinode.path) : 0);
2375 
2376  offset = se->offset + off;
2378 
2379  length = (uint16_t)min(context->lastinode.size - se->offset - off, length);
2381 
2383  }
2384 
2385  ExFreePool(buf);
2386  } else {
2387  uint8_t *buf, *compbuf;
2388  uint64_t off;
2389  void* csum;
2390 
2392  if (!buf) {
2393  ERR("out of memory\n");
2394  ExFreePool(se);
2395  if (se2) ExFreePool(se2);
2397  }
2398 
2400  if (!compbuf) {
2401  ERR("out of memory\n");
2402  ExFreePool(buf);
2403  ExFreePool(se);
2404  if (se2) ExFreePool(se2);
2406  }
2407 
2408  if (context->lastinode.flags & BTRFS_INODE_NODATASUM)
2409  csum = NULL;
2410  else {
2411  uint32_t len;
2412 
2413  len = (uint32_t)(ed2->size / context->Vcb->superblock.sector_size);
2414 
2415  csum = ExAllocatePoolWithTag(PagedPool, len * context->Vcb->csum_size, ALLOC_TAG);
2416  if (!csum) {
2417  ERR("out of memory\n");
2418  ExFreePool(compbuf);
2419  ExFreePool(buf);
2420  ExFreePool(se);
2421  if (se2) ExFreePool(se2);
2423  }
2424 
2425  Status = load_csum(context->Vcb, csum, ed2->address, len, NULL);
2426  if (!NT_SUCCESS(Status)) {
2427  ERR("load_csum returned %08lx\n", Status);
2428  ExFreePool(csum);
2429  ExFreePool(compbuf);
2430  ExFreePool(buf);
2431  ExFreePool(se);
2432  if (se2) ExFreePool(se2);
2433  return Status;
2434  }
2435  }
2436 
2437  Status = read_data(context->Vcb, ed2->address, (uint32_t)ed2->size, csum, false, compbuf, NULL, NULL, NULL, 0, false, NormalPagePriority);
2438  if (!NT_SUCCESS(Status)) {
2439  ERR("read_data returned %08lx\n", Status);
2440  ExFreePool(compbuf);
2441  ExFreePool(buf);
2442  ExFreePool(se);
2443  if (se2) ExFreePool(se2);
2444  if (csum) ExFreePool(csum);
2445  return Status;
2446  }
2447 
2448  if (csum)
2449  ExFreePool(csum);
2450 
2453  if (!NT_SUCCESS(Status)) {
2454  ERR("zlib_decompress returned %08lx\n", Status);
2455  ExFreePool(compbuf);
2456  ExFreePool(buf);
2457  ExFreePool(se);
2458  if (se2) ExFreePool(se2);
2459  return Status;
2460  }
2461  } else if (se->data.compression == BTRFS_COMPRESSION_LZO) {
2462  Status = lzo_decompress(&compbuf[sizeof(uint32_t)], (uint32_t)ed2->size, buf, (uint32_t)se->data.decoded_size, sizeof(uint32_t));
2463  if (!NT_SUCCESS(Status)) {
2464  ERR("lzo_decompress returned %08lx\n", Status);
2465  ExFreePool(compbuf);
2466  ExFreePool(buf);
2467  ExFreePool(se);
2468  if (se2) ExFreePool(se2);
2469  return Status;
2470  }
2471  } else if (se->data.compression == BTRFS_COMPRESSION_ZSTD) {
2473  if (!NT_SUCCESS(Status)) {
2474  ERR("zstd_decompress returned %08lx\n", Status);
2475  ExFreePool(compbuf);
2476  ExFreePool(buf);
2477  ExFreePool(se);
2478  if (se2) ExFreePool(se2);
2479  return Status;
2480  }
2481  }
2482 
2483  ExFreePool(compbuf);
2484 
2485  for (off = ed2->offset; off < ed2->offset + ed2->num_bytes; off += MAX_SEND_WRITE) {
2487  uint64_t offset;
2488 
2489  if (context->datalen > SEND_BUFFER_LENGTH) {
2490  Status = wait_for_flush(context, tp1, tp2);
2491  if (!NT_SUCCESS(Status)) {
2492  ERR("wait_for_flush returned %08lx\n", Status);
2493  ExFreePool(buf);
2494  ExFreePool(se);
2495  if (se2) ExFreePool(se2);
2496  return Status;
2497  }
2498 
2499  if (context->send->cancelling) {
2500  ExFreePool(buf);
2501  ExFreePool(se);
2502  if (se2) ExFreePool(se2);
2503  return STATUS_SUCCESS;
2504  }
2505  }
2506 
2507  pos = context->datalen;
2508 
2510 
2511  send_add_tlv(context, BTRFS_SEND_TLV_PATH, context->lastinode.path, context->lastinode.path ? (uint16_t)strlen(context->lastinode.path) : 0);
2512 
2513  offset = se->offset + off;
2515 
2516  length = (uint16_t)min(context->lastinode.size - se->offset - off, length);
2518 
2520  }
2521 
2522  ExFreePool(buf);
2523  }
2524 
2525  ExFreePool(se);
2526  if (se2) ExFreePool(se2);
2527  }
2528 
2529  return STATUS_SUCCESS;
2530 }
#define BTRFS_SEND_TLV_OFFSET
Definition: btrfs.h:573
Definition: send.c:61
NTSTATUS zstd_decompress(uint8_t *inbuf, uint32_t inlen, uint8_t *outbuf, uint32_t outlen)
Definition: compress.c:676
uint8_t type
Definition: btrfs.h:351
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
static bool try_clone(send_context *context, send_ext *se)
Definition: send.c:2028
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
#define BTRFS_COMPRESSION_NONE
Definition: btrfs.h:61
#define BTRFS_SEND_TLV_DATA
Definition: btrfs.h:574
Definition: http.c:7094
EXTENT_DATA2 * ed2
Definition: write.c:2805
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
uint64_t decoded_size
Definition: btrfs.h:347
LONG NTSTATUS
Definition: precomp.h:26
GLintptr offset
Definition: glext.h:5920
NTSTATUS load_csum(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, void *csum, uint64_t start, uint64_t length, PIRP Irp)
Definition: create.c:446
static NTSTATUS sync_ext_cutoff_points(send_context *context)
Definition: send.c:1785
#define BTRFS_COMPRESSION_LZO
Definition: btrfs.h:63
#define BTRFS_COMPRESSION_ZSTD
Definition: btrfs.h:64
uint64_t offset
Definition: send.c:62
unsigned short int uint16_t
Definition: acefiex.h:54
#define uint16_t
Definition: nsiface.idl:60
ULONG datalen
Definition: send.c:64
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
#define BTRFS_COMPRESSION_ZLIB
Definition: btrfs.h:62
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define ALLOC_TAG
Definition: btrfs_drv.h:91
#define EXTENT_TYPE_INLINE
Definition: btrfs.h:70
static void send_command(send_context *context, uint16_t cmd)
Definition: send.c:116
uint64_t address
Definition: btrfs.h:356
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
static NTSTATUS wait_for_flush(send_context *context, traverse_ptr *tp1, traverse_ptr *tp2)
Definition: send.c:1602
uint64_t size
Definition: btrfs.h:357
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
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
#define BTRFS_INODE_NODATASUM
Definition: propsheet.h:76
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define BTRFS_SEND_CMD_WRITE
Definition: btrfs.h:547
#define BTRFS_SEND_TLV_PATH
Definition: btrfs.h:570
Status
Definition: gdiplustypes.h:24
GLenum const GLvoid * addr
Definition: glext.h:9621
NTSTATUS lzo_decompress(uint8_t *inbuf, uint32_t inlen, uint8_t *outbuf, uint32_t outlen, uint32_t inpageoff)
Definition: compress.c:278
GLenum GLsizei len
Definition: glext.h:6722
BYTE uint8_t
Definition: msvideo1.c:66
uint64_t num_bytes
Definition: btrfs.h:359
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:71
#define ERR(fmt,...)
Definition: debug.h:110
uint8_t data[1]
Definition: btrfs.h:352
NTSTATUS zlib_decompress(uint8_t *inbuf, uint32_t inlen, uint8_t *outbuf, uint32_t outlen)
Definition: compress.c:377
UINT64 uint64_t
Definition: types.h:77
#define min(a, b)
Definition: monoChain.cc:55
Definition: list.h:27
UINT32 uint32_t
Definition: types.h:75
Definition: fs.h:216
static BOOL read_data(struct request *request, void *buffer, DWORD size, DWORD *read, BOOL async)
Definition: request.c:2018
static void send_command_finish(send_context *context, ULONG pos)
Definition: send.c:125
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint64_t offset
Definition: btrfs.h:358
EXTENT_DATA data
Definition: send.c:65
#define uint32_t
Definition: nsiface.idl:61
return STATUS_SUCCESS
Definition: btrfs.c:3014
static void send_add_tlv(send_context *context, uint16_t type, void *data, uint16_t length)
Definition: send.c:132
static uint64_t __inline sector_align(uint64_t n, uint64_t a)
static NTSTATUS add_ext_holes(device_extension *Vcb, LIST_ENTRY *exts, uint64_t size)
Definition: send.c:1652
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
uint8_t compression
Definition: btrfs.h:348
void * csum
Definition: write.c:2807
off
Definition: i386-dis.c:3909
#define SEND_BUFFER_LENGTH
Definition: send.c:111
#define MAX_SEND_WRITE
Definition: send.c:110

Referenced by finish_inode().

◆ flush_refs()

static NTSTATUS flush_refs ( send_context context,
traverse_ptr tp1,
traverse_ptr tp2 
)
static

Definition at line 1274 of file send.c.

1274  {
1275  NTSTATUS Status;
1276  LIST_ENTRY* le;
1277  ref *nameref = NULL, *nameref2 = NULL;
1278 
1279  if (context->lastinode.mode & __S_IFDIR) { // directory
1280  ref* r = IsListEmpty(&context->lastinode.refs) ? NULL : CONTAINING_RECORD(context->lastinode.refs.Flink, ref, list_entry);
1281  ref* or = IsListEmpty(&context->lastinode.oldrefs) ? NULL : CONTAINING_RECORD(context->lastinode.oldrefs.Flink, ref, list_entry);
1282 
1283  if (or && !context->lastinode.o) {
1284  ULONG len = find_path_len(or->sd, or->namelen);
1285 
1286  context->lastinode.path = ExAllocatePoolWithTag(PagedPool, len + 1, ALLOC_TAG);
1287  if (!context->lastinode.path) {
1288  ERR("out of memory\n");
1290  }
1291 
1292  find_path(context->lastinode.path, or->sd, or->name, or->namelen);
1293  context->lastinode.path[len] = 0;
1294 
1295  if (!context->lastinode.sd) {
1296  Status = find_send_dir(context, context->lastinode.inode, context->lastinode.gen, &context->lastinode.sd, false);
1297  if (!NT_SUCCESS(Status)) {
1298  ERR("find_send_dir returned %08lx\n", Status);
1299  return Status;
1300  }
1301  }
1302  }
1303 
1304  if (r && or) {
1305  uint64_t inode;
1306  bool dir;
1307 
1308  Status = look_for_collision(context, r->sd, r->name, r->namelen, &inode, &dir);
1310  ERR("look_for_collision returned %08lx\n", Status);
1311  return Status;
1312  }
1313 
1314  if (Status == STATUS_OBJECT_NAME_COLLISION && inode > context->lastinode.inode) {
1315  Status = make_file_orphan(context, inode, dir, context->parent->root_item.ctransid, r);
1316  if (!NT_SUCCESS(Status)) {
1317  ERR("make_file_orphan returned %08lx\n", Status);
1318  return Status;
1319  }
1320  }
1321 
1322  if (context->lastinode.o) {
1323  Status = found_path(context, r->sd, r->name, r->namelen);
1324  if (!NT_SUCCESS(Status)) {
1325  ERR("found_path returned %08lx\n", Status);
1326  return Status;
1327  }
1328 
1329  if (!r->sd->dummy)
1330  send_utimes_command_dir(context, r->sd, &r->sd->atime, &r->sd->mtime, &r->sd->ctime);
1331  } else if (r->sd != or->sd || r->namelen != or->namelen || RtlCompareMemory(r->name, or->name, r->namelen) != r->namelen) { // moved or renamed
1332  ULONG pos = context->datalen, len;
1333 
1335 
1336  send_add_tlv(context, BTRFS_SEND_TLV_PATH, context->lastinode.path, (uint16_t)strlen(context->lastinode.path));
1337 
1339 
1341 
1342  if (!r->sd->dummy)
1343  send_utimes_command_dir(context, r->sd, &r->sd->atime, &r->sd->mtime, &r->sd->ctime);
1344 
1345  if (context->lastinode.sd->name)
1346  ExFreePool(context->lastinode.sd->name);
1347 
1348  context->lastinode.sd->name = ExAllocatePoolWithTag(PagedPool, r->namelen, ALLOC_TAG);
1349  if (!context->lastinode.sd->name) {
1350  ERR("out of memory\n");
1352  }
1353 
1354  RtlCopyMemory(context->lastinode.sd->name, r->name, r->namelen);
1355  context->lastinode.sd->parent = r->sd;
1356 
1357  if (context->lastinode.path)
1358  ExFreePool(context->lastinode.path);
1359 
1360  len = find_path_len(r->sd, r->namelen);
1361  context->lastinode.path = ExAllocatePoolWithTag(PagedPool, len + 1, ALLOC_TAG);
1362  if (!context->lastinode.path) {
1363  ERR("out of memory\n");
1365  }
1366 
1367  find_path(context->lastinode.path, r->sd, r->name, r->namelen);
1368  context->lastinode.path[len] = 0;
1369  }
1370  } else if (r && !or) { // new
1371  Status = found_path(context, r->sd, r->name, r->namelen);
1372  if (!NT_SUCCESS(Status)) {
1373  ERR("found_path returned %08lx\n", Status);
1374  return Status;
1375  }
1376 
1377  if (!r->sd->dummy)
1378  send_utimes_command_dir(context, r->sd, &r->sd->atime, &r->sd->mtime, &r->sd->ctime);
1379  } else { // deleted
1380  uint64_t last_inode;
1381 
1382  Status = get_dir_last_child(context, &last_inode);
1383  if (!NT_SUCCESS(Status)) {
1384  ERR("get_dir_last_child returned %08lx\n", Status);
1385  return Status;
1386  }
1387 
1388  if (last_inode <= context->lastinode.inode) {
1389  send_rmdir_command(context, (uint16_t)strlen(context->lastinode.path), context->lastinode.path);
1390 
1391  if (!or->sd->dummy)
1392  send_utimes_command_dir(context, or->sd, &or->sd->atime, &or->sd->mtime, &or->sd->ctime);
1393  } else {
1394  char name[64];
1395  ULONG pos = context->datalen;
1396 
1397  Status = get_orphan_name(context, context->lastinode.inode, context->lastinode.gen, name);
1398  if (!NT_SUCCESS(Status)) {
1399  ERR("get_orphan_name returned %08lx\n", Status);
1400  return Status;
1401  }
1402 
1404  send_add_tlv(context, BTRFS_SEND_TLV_PATH, context->lastinode.path, (uint16_t)strlen(context->lastinode.path));
1407 
1408  if (context->lastinode.sd->name)
1409  ExFreePool(context->lastinode.sd->name);
1410 
1411  context->lastinode.sd->name = ExAllocatePoolWithTag(PagedPool, strlen(name), ALLOC_TAG);
1412  if (!context->lastinode.sd->name) {
1413  ERR("out of memory\n");
1415  }
1416 
1417  RtlCopyMemory(context->lastinode.sd->name, name, strlen(name));
1418  context->lastinode.sd->namelen = (uint16_t)strlen(name);
1419  context->lastinode.sd->dummy = true;
1420  context->lastinode.sd->parent = NULL;
1421 
1422  send_utimes_command(context, NULL, &context->root_dir->atime, &context->root_dir->mtime, &context->root_dir->ctime);
1423 
1424  Status = add_pending_rmdir(context, last_inode);
1425  if (!NT_SUCCESS(Status)) {
1426  ERR("add_pending_rmdir returned %08lx\n", Status);
1427  return Status;
1428  }
1429  }
1430  }
1431 
1432  while (!IsListEmpty(&context->lastinode.refs)) {
1433  r = CONTAINING_RECORD(RemoveHeadList(&context->lastinode.refs), ref, list_entry);
1434  ExFreePool(r);
1435  }
1436 
1437  while (!IsListEmpty(&context->lastinode.oldrefs)) {
1438  or = CONTAINING_RECORD(RemoveHeadList(&context->lastinode.oldrefs), ref, list_entry);
1439  ExFreePool(or);
1440  }
1441 
1442  return STATUS_SUCCESS;
1443  } else {
1444  if (!IsListEmpty(&context->lastinode.oldrefs)) {
1445  ref* or = CONTAINING_RECORD(context->lastinode.oldrefs.Flink, ref, list_entry);
1446  ULONG len = find_path_len(or->sd, or->namelen);
1447 
1448  context->lastinode.path = ExAllocatePoolWithTag(PagedPool, len + 1, ALLOC_TAG);
1449  if (!context->lastinode.path) {
1450  ERR("out of memory\n");
1452  }
1453 
1454  find_path(context->lastinode.path, or->sd, or->name, or->namelen);
1455  context->lastinode.path[len] = 0;
1456  nameref = or;
1457  }
1458 
1459  // remove unchanged refs
1460  le = context->lastinode.oldrefs.Flink;
1461  while (le != &context->lastinode.oldrefs) {
1462  ref* or = CONTAINING_RECORD(le, ref, list_entry);
1463  LIST_ENTRY* le2;
1464  bool matched = false;
1465 
1466  le2 = context->lastinode.refs.Flink;
1467  while (le2 != &context->lastinode.refs) {
1468  ref* r = CONTAINING_RECORD(le2, ref, list_entry);
1469 
1470  if (r->sd == or->sd && r->namelen == or->namelen && RtlCompareMemory(r->name, or->name, r->namelen) == r->namelen) {
1471  RemoveEntryList(&r->list_entry);
1472  ExFreePool(r);
1473  matched = true;
1474  break;
1475  }
1476 
1477  le2 = le2->Flink;
1478  }
1479 
1480  if (matched) {
1481  le = le->Flink;
1483  ExFreePool(or);
1484  continue;
1485  }
1486 
1487  le = le->Flink;
1488  }
1489 
1490  while (!IsListEmpty(&context->lastinode.refs)) {
1491  ref* r = CONTAINING_RECORD(RemoveHeadList(&context->lastinode.refs), ref, list_entry);
1492  uint64_t inode;
1493  bool dir;
1494 
1495  if (context->parent) {
1496  Status = look_for_collision(context, r->sd, r->name, r->namelen, &inode, &dir);
1498  ERR("look_for_collision returned %08lx\n", Status);
1499  return Status;
1500  }
1501 
1502  if (Status == STATUS_OBJECT_NAME_COLLISION && inode > context->lastinode.inode) {
1503  Status = make_file_orphan(context, inode, dir, context->lastinode.gen, r);
1504  if (!NT_SUCCESS(Status)) {
1505  ERR("make_file_orphan returned %08lx\n", Status);
1506  return Status;
1507  }
1508  }
1509  }
1510 
1511  if (context->datalen > SEND_BUFFER_LENGTH) {
1512  Status = wait_for_flush(context, tp1, tp2);
1513  if (!NT_SUCCESS(Status)) {
1514  ERR("wait_for_flush returned %08lx\n", Status);
1515  return Status;
1516  }
1517 
1518  if (context->send->cancelling)
1519  return STATUS_SUCCESS;
1520  }
1521 
1522  Status = found_path(context, r->sd, r->name, r->namelen);
1523  if (!NT_SUCCESS(Status)) {
1524  ERR("found_path returned %08lx\n", Status);
1525  return Status;
1526  }
1527 
1528  if (!r->sd->dummy)
1529  send_utimes_command_dir(context, r->sd, &r->sd->atime, &r->sd->mtime, &r->sd->ctime);
1530 
1531  if (nameref && !nameref2)
1532  nameref2 = r;
1533  else
1534  ExFreePool(r);
1535  }
1536 
1537  while (!IsListEmpty(&context->lastinode.oldrefs)) {
1538  ref* or = CONTAINING_RECORD(RemoveHeadList(&context->lastinode.oldrefs), ref, list_entry);
1539  bool deleted = false;
1540 
1541  le = or->sd->deleted_children.Flink;
1542  while (le != &or->sd->deleted_children) {
1544 
1545  if (dc->namelen == or->namelen && RtlCompareMemory(dc->name, or->name, or->namelen) == or->namelen) {
1546  RemoveEntryList(&dc->list_entry);
1547  ExFreePool(dc);
1548  deleted = true;
1549  break;
1550  }
1551 
1552  le = le->Flink;
1553  }
1554 
1555  if (!deleted) {
1556  if (context->datalen > SEND_BUFFER_LENGTH) {
1557  Status = wait_for_flush(context, tp1, tp2);
1558  if (!NT_SUCCESS(Status)) {
1559  ERR("wait_for_flush returned %08lx\n", Status);
1560  return Status;
1561  }
1562 
1563  if (context->send->cancelling)
1564  return STATUS_SUCCESS;
1565  }
1566 
1567  Status = send_unlink_command(context, or->sd, or->namelen, or->name);
1568  if (!NT_SUCCESS(Status)) {
1569  ERR("send_unlink_command returned %08lx\n", Status);
1570  return Status;
1571  }
1572 
1573  if (!or->sd->dummy)
1574  send_utimes_command_dir(context, or->sd, &or->sd->atime, &or->sd->mtime, &or->sd->ctime);
1575  }
1576 
1577  if (or == nameref && nameref2) {
1578  uint16_t len = find_path_len(nameref2->sd, nameref2->namelen);
1579 
1580  if (context->lastinode.path)
1581  ExFreePool(context->lastinode.path);
1582 
1583  context->lastinode.path = ExAllocatePoolWithTag(PagedPool, len + 1, ALLOC_TAG);
1584  if (!context->lastinode.path) {
1585  ERR("out of memory\n");
1587  }
1588 
1589  find_path(context->lastinode.path, nameref2->sd, nameref2->name, nameref2->namelen);
1590  context->lastinode.path[len] = 0;
1591 
1592  ExFreePool(nameref2);
1593  }
1594 
1595  ExFreePool(or);
1596  }
1597  }
1598 
1599  return STATUS_SUCCESS;
1600 }
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
static NTSTATUS add_pending_rmdir(send_context *context, uint64_t last_inode)
Definition: send.c:1103
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LIST_ENTRY deleted_children
Definition: send.c:31
bool dummy
Definition: send.c:24
#define BTRFS_SEND_TLV_PATH_TO
Definition: btrfs.h:571
Definition: http.c:7094
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
static __inline uint16_t find_path_len(send_dir *parent, uint16_t namelen)
Definition: send.c:560
r lastinode
Definition: btrfs.c:2961
LONG NTSTATUS
Definition: precomp.h:26
static NTSTATUS get_orphan_name(send_context *context, uint64_t inode, uint64_t generation, char *name)
Definition: send.c:164
static void send_utimes_command(send_context *context, char *path, BTRFS_TIME *atime, BTRFS_TIME *mtime, BTRFS_TIME *ctime)
Definition: send.c:1013
unsigned short int uint16_t
Definition: acefiex.h:54
#define uint16_t
Definition: nsiface.idl:60
LIST_ENTRY list_entry
Definition: send.c:49
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
Definition: send.c:48
static void send_rmdir_command(send_context *context, uint16_t pathlen, char *path)
Definition: send.c:1053
Definition: fs.h:78
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
uint16_t namelen
Definition: send.c:29
#define ALLOC_TAG
Definition: btrfs_drv.h:91
static void send_command(send_context *context, uint16_t cmd)
Definition: send.c:116
char name[1]
Definition: send.c:52
static NTSTATUS found_path(send_context *context, send_dir *parent, char *name, uint16_t namelen)
Definition: send.c:595
static NTSTATUS make_file_orphan(send_context *context, uint64_t inode, bool dir, uint64_t generation, ref *r)
Definition: send.c:1175
smooth NULL
Definition: ftsmooth.c:416
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
static NTSTATUS wait_for_flush(send_context *context, traverse_ptr *tp1, traverse_ptr *tp2)
Definition: send.c:1602
unsigned int dir
Definition: maze.c:112
BTRFS_TIME mtime
Definition: send.c:26
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
static void find_path(char *path, send_dir *parent, char *name, ULONG namelen)
Definition: send.c:571
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
static NTSTATUS get_dir_last_child(send_context *context, uint64_t *last_inode)
Definition: send.c:1061
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
char * name
Definition: compiler.c:66
static NTSTATUS send_unlink_command(send_context *context, send_dir *parent, uint16_t namelen, char *name)
Definition: send.c:1037
uint16_t namelen
Definition: send.c:51
BTRFS_TIME atime
Definition: send.c:25
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define BTRFS_SEND_TLV_PATH
Definition: btrfs.h:570
BTRFS_TIME ctime
Definition: send.c:27
Status
Definition: gdiplustypes.h:24
GLenum GLsizei len
Definition: glext.h:6722
Definition: typedefs.h:119
#define BTRFS_SEND_CMD_RENAME
Definition: btrfs.h:541
#define ERR(fmt,...)
Definition: debug.h:110
UINT64 uint64_t
Definition: types.h:77
Definition: list.h:27
#define __S_IFDIR
Definition: btrfs_drv.h:1800
Definition: name.c:38
static void send_command_finish(send_context *context, ULONG pos)
Definition: send.c:125
unsigned int ULONG
Definition: retypes.h:1
static const WCHAR dc[]
send_dir * sd
Definition: send.c:50
static void send_add_tlv_path(send_context *context, uint16_t type, send_dir *parent, char *name, uint16_t namelen)
Definition: send.c:586
return STATUS_SUCCESS
Definition: btrfs.c:3014
static void send_add_tlv(send_context *context, uint16_t type, void *data, uint16_t length)
Definition: send.c:132
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
static NTSTATUS find_send_dir(send_context *context, uint64_t dir, uint64_t generation, send_dir **psd, bool *added_dummy)
Definition: send.c:670
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
static void send_utimes_command_dir(send_context *context, send_dir *sd, BTRFS_TIME *atime, BTRFS_TIME *mtime, BTRFS_TIME *ctime)
Definition: send.c:656
static NTSTATUS look_for_collision(send_context *context, send_dir *sd, char *name, ULONG namelen, uint64_t *inode, bool *dir)
Definition: send.c:1133
#define SEND_BUFFER_LENGTH
Definition: send.c:111

Referenced by finish_inode(), send_extent_data(), and send_xattr().

◆ found_path()

static NTSTATUS found_path ( send_context context,
send_dir parent,
char name,
uint16_t  namelen 
)
static

Definition at line 595 of file send.c.

595  {
596  ULONG pos = context->datalen;
597 
598  if (context->lastinode.o) {
600 
601  send_add_tlv_path(context, BTRFS_SEND_TLV_PATH, context->root_dir, context->lastinode.o->tmpname, (uint16_t)strlen(context->lastinode.o->tmpname));
602 
604 
606  } else {
608 
610 
611  send_add_tlv(context, BTRFS_SEND_TLV_PATH_LINK, context->lastinode.path, context->lastinode.path ? (uint16_t)strlen(context->lastinode.path) : 0);
612 
614  }
615 
616  if (context->lastinode.o) {
617  uint16_t pathlen;
618 
619  if (context->lastinode.o->sd) {
620  if (context->lastinode.o->sd->name)
621  ExFreePool(context->lastinode.o->sd->name);
622 
623  context->lastinode.o->sd->name = ExAllocatePoolWithTag(PagedPool, namelen, ALLOC_TAG);
624  if (!context->lastinode.o->sd->name) {
625  ERR("out of memory\n");
627  }
628 
629  RtlCopyMemory(context->lastinode.o->sd->name, name, namelen);
630  context->lastinode.o->sd->namelen = namelen;
631  context->lastinode.o->sd->parent = parent;
632  }
633 
634  if (context->lastinode.path)
635  ExFreePool(context->lastinode.path);
636 
637  pathlen = find_path_len(parent, namelen);
638  context->lastinode.path = ExAllocatePoolWithTag(PagedPool, pathlen + 1, ALLOC_TAG);
639  if (!context->lastinode.path) {
640  ERR("out of memory\n");
642  }
643 
644  find_path(context->lastinode.path, parent, name, namelen);
645  context->lastinode.path[pathlen] = 0;
646 
647  RemoveEntryList(&context->lastinode.o->list_entry);
648  ExFreePool(context->lastinode.o);
649 
650  context->lastinode.o = NULL;
651  }
652 
653  return STATUS_SUCCESS;
654 }
#define BTRFS_SEND_CMD_LINK
Definition: btrfs.h:542
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define BTRFS_SEND_TLV_PATH_TO
Definition: btrfs.h:571
Definition: http.c:7094
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
static __inline uint16_t find_path_len(send_dir *parent, uint16_t namelen)
Definition: send.c:560
unsigned short int uint16_t
Definition: acefiex.h:54
GLint namelen
Definition: glext.h:7232
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
#define ALLOC_TAG
Definition: btrfs_drv.h:91
static void send_command(send_context *context, uint16_t cmd)
Definition: send.c:116
smooth NULL
Definition: ftsmooth.c:416
static void find_path(char *path, send_dir *parent, char *name, ULONG namelen)
Definition: send.c:571
#define BTRFS_SEND_TLV_PATH_LINK
Definition: btrfs.h:572
r parent
Definition: btrfs.c:2944
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define BTRFS_SEND_TLV_PATH
Definition: btrfs.h:570
#define BTRFS_SEND_CMD_RENAME
Definition: btrfs.h:541
#define ERR(fmt,...)
Definition: debug.h:110
Definition: name.c:38
static void send_command_finish(send_context *context, ULONG pos)
Definition: send.c:125
unsigned int ULONG
Definition: retypes.h:1
static void send_add_tlv_path(send_context *context, uint16_t type, send_dir *parent, char *name, uint16_t namelen)
Definition: send.c:586
return STATUS_SUCCESS
Definition: btrfs.c:3014
static void send_add_tlv(send_context *context, uint16_t type, void *data, uint16_t length)
Definition: send.c:132
#define ExFreePool(addr)
Definition: env_spec_w32.h:352

Referenced by flush_refs().

◆ get_dir_last_child()

static NTSTATUS get_dir_last_child ( send_context context,
uint64_t last_inode 
)
static

Definition at line 1061 of file send.c.

1061  {
1062  NTSTATUS Status;
1063  KEY searchkey;
1064  traverse_ptr tp;
1065 
1066  *last_inode = 0;
1067 
1068  searchkey.obj_id = context->lastinode.inode;
1069  searchkey.obj_type = TYPE_DIR_INDEX;
1070  searchkey.offset = 2;
1071 
1072  Status = find_item(context->Vcb, context->parent, &tp, &searchkey, false, NULL);
1073  if (!NT_SUCCESS(Status)) {
1074  ERR("find_item returned %08lx\n", Status);
1075  return Status;
1076  }
1077 
1078  do {
1079  traverse_ptr next_tp;
1080 
1081  if (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == searchkey.obj_type) {
1082  DIR_ITEM* di = (DIR_ITEM*)tp.item->data;
1083 
1084  if (tp.item->size < sizeof(DIR_ITEM) || tp.item->size < offsetof(DIR_ITEM, name[0]) + di->m + di->n) {
1085  ERR("(%I64x,%x,%I64x) was truncated\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset);
1086  return STATUS_INTERNAL_ERROR;
1087  }
1088 
1089  if (di->key.obj_type == TYPE_INODE_ITEM)
1090  *last_inode = max(*last_inode, di->key.obj_id);
1091  } else
1092  break;
1093 
1094  if (find_next_item(context->Vcb, &tp, &next_tp, false, NULL))
1095  tp = next_tp;
1096  else
1097  break;
1098  } while (true);
1099 
1100  return STATUS_SUCCESS;
1101 }
uint64_t obj_id
Definition: btrfs.h:137
#define max(a, b)
Definition: svc.c:63
uint8_t obj_type
Definition: btrfs.h:138
Definition: http.c:7094
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:430
#define TYPE_DIR_INDEX
Definition: btrfs.h:25
uint64_t offset
Definition: btrfs.h:139
uint8_t * data
Definition: btrfs_drv.h:431
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
uint16_t m
Definition: btrfs.h:268
KEY key
Definition: btrfs.h:266
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2930
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
bool find_next_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, const traverse_ptr *tp, traverse_ptr *next_tp, bool ignore, PIRP Irp)
Definition: treefuncs.c:593
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
tree_data * item
Definition: btrfs_drv.h:518
Status
Definition: gdiplustypes.h:24
#define TYPE_INODE_ITEM
Definition: btrfs.h:19
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:136
Definition: name.c:38
uint16_t n
Definition: btrfs.h:269
return STATUS_SUCCESS
Definition: btrfs.c:3014

Referenced by flush_refs().

◆ get_orphan_name()

static NTSTATUS get_orphan_name ( send_context context,
uint64_t  inode,
uint64_t  generation,
char name 
)
static

Definition at line 164 of file send.c.

164  {
165  char *ptr, *ptr2;
166  uint64_t index = 0;
167  KEY searchkey;
168 
169  name[0] = 'o';
170 
171  ptr = uint64_to_char(inode, &name[1]);
172  *ptr = '-'; ptr++;
174  *ptr = '-'; ptr++;
175  ptr2 = ptr;
176 
177  searchkey.obj_id = SUBVOL_ROOT_INODE;
178  searchkey.obj_type = TYPE_DIR_ITEM;
179 
180  do {
183 
185  *ptr = 0;
186 
187  searchkey.offset = calc_crc32c(0xfffffffe, (uint8_t*)name, (ULONG)(ptr - name));
188 
189  Status = find_item(context->Vcb, context->root, &tp, &searchkey, false, NULL);
190  if (!NT_SUCCESS(Status)) {
191  ERR("find_item returned %08lx\n", Status);
192  return Status;
193  }
194 
195  if (!keycmp(searchkey, tp.item->key))
196  goto cont;
197 
198  if (context->parent) {
199  Status = find_item(context->Vcb, context->parent, &tp, &searchkey, false, NULL);
200  if (!NT_SUCCESS(Status)) {
201  ERR("find_item returned %08lx\n", Status);
202  return Status;
203  }
204 
205  if (!keycmp(searchkey, tp.item->key))
206  goto cont;
207  }
208 
209  return STATUS_SUCCESS;
210 
211 cont:
212  index++;
213  ptr = ptr2;
214  } while (true);
215 }
uint64_t obj_id
Definition: btrfs.h:137
uint8_t obj_type
Definition: btrfs.h:138
Definition: http.c:7094
#define SUBVOL_ROOT_INODE
Definition: propsheet.cpp:42
#define keycmp(key1, key2)
Definition: btrfs_drv.h:1024
LONG NTSTATUS
Definition: precomp.h:26
uint64_t offset
Definition: btrfs.h:139
Definition: fs.h:78
static PVOID ptr
Definition: dispmode.c:27
smooth NULL
Definition: ftsmooth.c:416
GLuint index
Definition: glext.h:6031
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2930
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static char * uint64_to_char(uint64_t num, char *buf)
Definition: send.c:144
tree_data * item
Definition: btrfs_drv.h:518
Status
Definition: gdiplustypes.h:24
crc_func calc_crc32c
Definition: crc32c.c:23
BYTE uint8_t
Definition: msvideo1.c:66
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:136
UINT64 uint64_t
Definition: types.h:77
_In_ uint64_t _In_ uint64_t _In_ uint64_t generation
Definition: btrfs.c:2929
#define TYPE_DIR_ITEM
Definition: btrfs.h:24
Definition: name.c:38
unsigned int ULONG
Definition: retypes.h:1
return STATUS_SUCCESS
Definition: btrfs.c:3014

Referenced by find_send_dir(), flush_refs(), make_file_orphan(), and send_inode().

◆ look_for_collision()

static NTSTATUS look_for_collision ( send_context context,
send_dir sd,
char name,
ULONG  namelen,
uint64_t inode,
bool dir 
)
static

Definition at line 1133 of file send.c.

1133  {
1134  NTSTATUS Status;
1135  KEY searchkey;
1136  traverse_ptr tp;
1137  DIR_ITEM* di;
1138  uint16_t len;
1139 
1140  searchkey.obj_id = sd->inode;
1141  searchkey.obj_type = TYPE_DIR_ITEM;
1142  searchkey.offset = calc_crc32c(0xfffffffe, (uint8_t*)name, namelen);
1143 
1144  Status = find_item(context->Vcb, context->parent, &tp, &searchkey, false, NULL);
1145  if (!NT_SUCCESS(Status)) {
1146  ERR("find_item returned %08lx\n", Status);
1147  return Status;
1148  }
1149 
1150  if (keycmp(tp.item->key, searchkey))
1151  return STATUS_SUCCESS;
1152 
1153  di = (DIR_ITEM*)tp.item->data;
1154  len = tp.item->size;
1155 
1156  do {
1157  if (len < sizeof(DIR_ITEM) || len < offsetof(DIR_ITEM, name[0]) + di->m + di->n) {
1158  ERR("(%I64x,%x,%I64x) was truncated\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset);
1159  return STATUS_INTERNAL_ERROR;
1160  }
1161 
1162  if (di->n == namelen && RtlCompareMemory(di->name, name, namelen) == namelen) {
1163  *inode = di->key.obj_type == TYPE_INODE_ITEM ? di->key.obj_id : 0;
1164  *dir = di->type == BTRFS_TYPE_DIRECTORY ? true: false;
1166  }
1167 
1168  di = (DIR_ITEM*)&di->name[di->m + di->n];
1169  len -= (uint16_t)offsetof(DIR_ITEM, name[0]) + di->m + di->n;
1170  } while (len > 0);
1171 
1172  return STATUS_SUCCESS;
1173 }
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
uint64_t obj_id
Definition: btrfs.h:137
uint8_t obj_type
Definition: btrfs.h:138
Definition: http.c:7094
#define keycmp(key1, key2)
Definition: btrfs_drv.h:1024
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:430
unsigned short int uint16_t
Definition: acefiex.h:54
GLint namelen
Definition: glext.h:7232
uint64_t offset
Definition: btrfs.h:139
uint8_t * data
Definition: btrfs_drv.h:431
Definition: fs.h:78
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
uint16_t m
Definition: btrfs.h:268
KEY key
Definition: btrfs.h:266
char name[1]
Definition: btrfs.h:271
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:86
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
uint8_t type
Definition: btrfs.h:270
unsigned int dir
Definition: maze.c:112
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2930
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static const WCHAR sd[]
Definition: suminfo.c:287
tree_data * item
Definition: btrfs_drv.h:518
Status
Definition: gdiplustypes.h:24
#define TYPE_INODE_ITEM
Definition: btrfs.h:19
GLenum GLsizei len
Definition: glext.h:6722
crc_func calc_crc32c
Definition: crc32c.c:23
BYTE uint8_t
Definition: msvideo1.c:66
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:136
#define TYPE_DIR_ITEM
Definition: btrfs.h:24
Definition: name.c:38
uint16_t n
Definition: btrfs.h:269
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465

Referenced by flush_refs().

◆ make_file_orphan()

static NTSTATUS make_file_orphan ( send_context context,
uint64_t  inode,
bool  dir,
uint64_t  generation,
ref r 
)
static

Definition at line 1175 of file send.c.

1175  {
1176  NTSTATUS Status;
1177  ULONG pos = context->datalen;
1178  send_dir* sd = NULL;
1179  orphan* o;
1180  LIST_ENTRY* le;
1181  char name[64];
1182 
1183  if (!dir) {
1184  deleted_child* dc;
1185 
1187  if (!dc) {
1188  ERR("out of memory\n");
1190  }
1191 
1192  dc->namelen = r->namelen;
1193  RtlCopyMemory(dc->name, r->name, r->namelen);
1194  InsertTailList(&r->sd->deleted_children, &dc->list_entry);
1195  }
1196 
1197  le = context->orphans.Flink;
1198  while (le != &context->orphans) {
1200 
1201  if (o2->inode == inode) {
1203 
1204  send_add_tlv_path(context, BTRFS_SEND_TLV_PATH, r->sd, r->name, r->namelen);
1205 
1207 
1208  return STATUS_SUCCESS;
1209  } else if (o2->inode > inode)
1210  break;
1211 
1212  le = le->Flink;
1213  }
1214 
1216  if (!NT_SUCCESS(Status)) {
1217  ERR("get_orphan_name returned %08lx\n", Status);
1218  return Status;
1219  }
1220 
1221  if (dir) {
1223  if (!NT_SUCCESS(Status)) {
1224  ERR("find_send_dir returned %08lx\n", Status);
1225  return Status;
1226  }
1227 
1228  sd->dummy = true;
1229 
1231 
1232  send_add_tlv_path(context, BTRFS_SEND_TLV_PATH, r->sd, r->name, r->namelen);
1234 
1236 
1237  if (sd->name)
1238  ExFreePool(sd->name);
1239 
1240  sd->namelen = (uint16_t)strlen(name);
1241  sd->name = ExAllocatePoolWithTag(PagedPool, sd->namelen, ALLOC_TAG);
1242  if (!sd->name) {
1243  ERR("out of memory\n");
1245  }
1246 
1247  RtlCopyMemory(sd->name, name, sd->namelen);
1248  sd->parent = context->root_dir;
1249  } else {
1251 
1252  send_add_tlv_path(context, BTRFS_SEND_TLV_PATH, r->sd, r->name, r->namelen);
1253 
1255 
1257  }
1258 
1260  if (!o) {
1261  ERR("out of memory\n");
1263  }
1264 
1265  o->inode = inode;
1266  o->dir = true;
1267  strcpy(o->tmpname, name);
1268  o->sd = sd;
1269  add_orphan(context, o);
1270 
1271  return STATUS_SUCCESS;
1272 }
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
Definition: send.c:34
#define BTRFS_SEND_TLV_PATH_TO
Definition: btrfs.h:571
Definition: http.c:7094
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
LONG NTSTATUS
Definition: precomp.h:26
static NTSTATUS get_orphan_name(send_context *context, uint64_t inode, uint64_t generation, char *name)
Definition: send.c:164
unsigned short int uint16_t
Definition: acefiex.h:54
#define uint16_t
Definition: nsiface.idl:60
#define InsertTailList(ListHead, Entry)
uint64_t inode
Definition: send.c:36
Definition: fs.h:78
#define ALLOC_TAG
Definition: btrfs_drv.h:91
static void send_command(send_context *context, uint16_t cmd)
Definition: send.c:116
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
unsigned int dir
Definition: maze.c:112
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 NT_SUCCESS(StatCode)
Definition: apphelp.c:32
char tmpname[64]
Definition: send.c:39
bool dir
Definition: send.c:37
char * name
Definition: compiler.c:66
Definition: send.c:21
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define BTRFS_SEND_TLV_PATH
Definition: btrfs.h:570
static const WCHAR sd[]
Definition: suminfo.c:287
Status
Definition: gdiplustypes.h:24
send_dir * sd
Definition: send.c:38
Definition: typedefs.h:119
#define BTRFS_SEND_CMD_RENAME
Definition: btrfs.h:541
#define ERR(fmt,...)
Definition: debug.h:110
_In_ uint64_t _In_ uint64_t _In_ uint64_t generation
Definition: btrfs.c:2929
Definition: list.h:27
Definition: name.c:38
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
static void send_command_finish(send_context *context, ULONG pos)
Definition: send.c:125
unsigned int ULONG
Definition: retypes.h:1
static const WCHAR dc[]
#define BTRFS_SEND_CMD_UNLINK
Definition: btrfs.h:543
static void send_add_tlv_path(send_context *context, uint16_t type, send_dir *parent, char *name, uint16_t namelen)
Definition: send.c:586
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
static NTSTATUS find_send_dir(send_context *context, uint64_t dir, uint64_t generation, send_dir **psd, bool *added_dummy)
Definition: send.c:670
static void add_orphan(send_context *context, orphan *o)
Definition: send.c:217

Referenced by flush_refs().

◆ read_send_buffer()

NTSTATUS read_send_buffer ( device_extension Vcb,
PFILE_OBJECT  FileObject,
void data,
ULONG  datalen,
ULONG_PTR retlen,
KPROCESSOR_MODE  processor_mode 
)

Definition at line 3839 of file send.c.

3839  {
3840  ccb* ccb;
3842 
3843  ccb = FileObject ? FileObject->FsContext2 : NULL;
3844  if (!ccb)
3845  return STATUS_INVALID_PARAMETER;
3846 
3847  if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), processor_mode))
3849 
3850  ExAcquireResourceExclusiveLite(&Vcb->send_load_lock, true);
3851 
3852  if (!ccb->send) {
3853  ExReleaseResourceLite(&Vcb->send_load_lock);
3855  }
3856 
3858 
3859  KeWaitForSingleObject(&context->buffer_event, Executive, KernelMode, false, NULL);
3860 
3861  if (datalen == 0) {
3862  ExReleaseResourceLite(&Vcb->send_load_lock);
3863  return STATUS_SUCCESS;
3864  }
3865 
3866  RtlCopyMemory(data, context->data, min(datalen, context->datalen));
3867 
3868  if (datalen < context->datalen) { // not empty yet
3869  *retlen = datalen;
3870  RtlMoveMemory(context->data, &context->data[datalen], context->datalen - datalen);
3871  context->datalen -= datalen;
3872  ExReleaseResourceLite(&Vcb->send_load_lock);
3873  } else {
3874  *retlen = context->datalen;
3875  context->datalen = 0;
3876  ExReleaseResourceLite(&Vcb->send_load_lock);
3877 
3878  KeClearEvent(&context->buffer_event);
3879  KeSetEvent(&ccb->send->cleared_event, 0, false);
3880  }
3881 
3882  return STATUS_SUCCESS;
3883 }
#define STATUS_PRIVILEGE_NOT_HELD
Definition: DriverTester.h:9
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
Definition: http.c:7094
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
BOOLEAN NTAPI SeSinglePrivilegeCheck(IN LUID PrivilegeValue, IN KPROCESSOR_MODE PreviousMode)
Definition: priv.c:524
int const JOCTET unsigned int datalen
Definition: jpeglib.h:1030
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
#define STATUS_END_OF_FILE
Definition: shellext.h:67
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
smooth NULL
Definition: ftsmooth.c:416
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:588
NTSTATUS send_status
Definition: btrfs_drv.h:409
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
KEVENT cleared_event
Definition: btrfs_drv.h:381
#define Vcb
Definition: cdprocs.h:1415
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 SE_MANAGE_VOLUME_PRIVILEGE
Definition: security.c:682
void * context
Definition: btrfs_drv.h:380
#define min(a, b)
Definition: monoChain.cc:55
struct _ccb ccb
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
return STATUS_SUCCESS
Definition: btrfs.c:3014
send_info * send
Definition: btrfs_drv.h:408

Referenced by fsctl_request().

◆ send_add_dir()

static NTSTATUS send_add_dir ( send_context context,
uint64_t  inode,
send_dir parent,
char name,
uint16_t  namelen,
bool  dummy,
LIST_ENTRY lastentry,
send_dir **  psd 
)
static

Definition at line 497 of file send.c.

497  {
498  LIST_ENTRY* le;
500 
501  if (!sd) {
502  ERR("out of memory\n");
504  }
505 
506  sd->inode = inode;
507  sd->dummy = dummy;
508  sd->parent = parent;
509 
510  if (!dummy) {
511  sd->atime = context->lastinode.atime;
512  sd->mtime = context->lastinode.mtime;
513  sd->ctime = context->lastinode.ctime;
514  }
515 
516  if (namelen > 0) {
518  if (!sd->name) {
519  ERR("out of memory\n");
520  ExFreePool(sd);
522  }
523 
524  memcpy(sd->name, name, namelen);
525  } else
526  sd->name = NULL;
527 
528  sd->namelen = namelen;
529 
530  InitializeListHead(&sd->deleted_children);
531 
532  if (lastentry)
533  InsertHeadList(lastentry, &sd->list_entry);
534  else {
535  le = context->dirs.Flink;
536  while (le != &context->dirs) {
538 
539  if (sd2->inode > sd->inode) {
540  InsertHeadList(sd2->list_entry.Blink, &sd->list_entry);
541 
542  if (psd)
543  *psd = sd;
544 
545  return STATUS_SUCCESS;
546  }
547 
548  le = le->Flink;
549  }
550 
551  InsertTailList(&context->dirs, &sd->list_entry);
552  }
553 
554  if (psd)
555  *psd = sd;
556 
557  return STATUS_SUCCESS;
558 }
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
Definition: http.c:7094
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
#define InsertTailList(ListHead, Entry)
GLint namelen
Definition: glext.h:7232
Definition: fs.h:78
#define ALLOC_TAG
Definition: btrfs_drv.h:91
smooth NULL
Definition: ftsmooth.c:416
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
r parent
Definition: btrfs.c:2944
Definition: send.c:21
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
static const WCHAR sd[]
Definition: suminfo.c:287
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
Definition: typedefs.h:119
#define ERR(fmt,...)
Definition: debug.h:110
LIST_ENTRY list_entry
Definition: send.c:22
unsigned char dummy
Definition: maze.c:118
uint64_t inode
Definition: send.c:23
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
Definition: list.h:27
Definition: name.c:38
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define ExFreePool(addr)
Definition: env_spec_w32.h:352

Referenced by find_send_dir().

◆ send_add_tlv()

static void send_add_tlv ( send_context context,
uint16_t  type,
void data,
uint16_t  length 
)
static

Definition at line 132 of file send.c.

132  {
133  btrfs_send_tlv* tlv = (btrfs_send_tlv*)&context->data[context->datalen];
134 
135  tlv->type = type;
136  tlv->length = length;
137 
138  if (length > 0 && data)
139  RtlCopyMemory(&tlv[1], data, length);
140 
141  context->datalen += sizeof(btrfs_send_tlv) + length;
142 }
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
Definition: http.c:7094
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
if(!(yy_init))
Definition: macro.lex.yy.c:714
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
uint16_t type
Definition: btrfs.h:595
uint16_t length
Definition: btrfs.h:596

Referenced by flush_extents(), flush_refs(), found_path(), send_add_tlv_clone_path(), send_add_tlv_path(), send_chmod_command(), send_chown_command(), send_inode(), send_inode_extref(), send_inode_ref(), send_rmdir_command(), send_subvol_header(), send_truncate_command(), send_unlink_command(), send_utimes_command(), send_utimes_command_dir(), send_xattr(), and try_clone_edr().

◆ send_add_tlv_clone_path()

static bool send_add_tlv_clone_path ( send_context context,
root r,
uint64_t  inode 
)
static

Definition at line 1841 of file send.c.

1841  {
1842  NTSTATUS Status;
1843  KEY searchkey;
1844  traverse_ptr tp;
1845  uint16_t len = 0;
1846  uint64_t num;
1847  uint8_t* ptr;
1848 
1849  num = inode;
1850 
1851  while (num != SUBVOL_ROOT_INODE) {
1852  searchkey.obj_id = num;
1853  searchkey.obj_type = TYPE_INODE_EXTREF;
1854  searchkey.offset = 0xffffffffffffffff;
1855 
1856  Status = find_item(context->Vcb, r, &tp, &searchkey, false, NULL);
1857  if (!NT_SUCCESS(Status)) {
1858  ERR("find_item returned %08lx\n", Status);
1859  return false;
1860  }
1861 
1862  if (tp.item->key.obj_id != searchkey.obj_id || (tp.item->key.obj_type != TYPE_INODE_REF && tp.item->key.obj_type != TYPE_INODE_EXTREF)) {
1863  ERR("could not find INODE_REF for inode %I64x\n", searchkey.obj_id);
1864  return false;
1865  }
1866 
1867  if (len > 0)
1868  len++;
1869 
1870  if (tp.item->key.obj_type == TYPE_INODE_REF) {
1871  INODE_REF* ir = (INODE_REF*)tp.item->data;
1872 
1873  if (tp.item->size < sizeof(INODE_REF) || tp.item->size < offsetof(INODE_REF, name[0]) + ir->n) {
1874  ERR("(%I64x,%x,%I64x) was truncated\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset);
1875  return false;
1876  }
1877 
1878  len += ir->n;
1879  num = tp.item->key.offset;
1880  } else {
1881  INODE_EXTREF* ier = (INODE_EXTREF*)tp.item->data;
1882 
1883  if (tp.item->size < sizeof(INODE_EXTREF) || tp.item->size < offsetof(INODE_EXTREF, name[0]) + ier->n) {
1884  ERR("(%I64x,%x,%I64x) was truncated\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset);
1885  return false;
1886  }
1887 
1888  len += ier->n;
1889  num = ier->dir;
1890  }
1891  }
1892 
1894  ptr = &context->data[context->datalen];
1895 
1896  num = inode;
1897 
1898  while (num != SUBVOL_ROOT_INODE) {
1899  searchkey.obj_id = num;
1900  searchkey.obj_type = TYPE_INODE_EXTREF;
1901  searchkey.offset = 0xffffffffffffffff;
1902 
1903  Status = find_item(context->Vcb, r, &tp, &searchkey, false, NULL);
1904  if (!NT_SUCCESS(Status)) {
1905  ERR("find_item returned %08lx\n", Status);
1906  return false;
1907  }
1908 
1909  if (tp.item->key.obj_id != searchkey.obj_id || (tp.item->key.obj_type != TYPE_INODE_REF && tp.item->key.obj_type != TYPE_INODE_EXTREF)) {
1910  ERR("could not find INODE_REF for inode %I64x\n", searchkey.obj_id);
1911  return false;
1912  }
1913 
1914  if (num != inode) {
1915  ptr--;
1916  *ptr = '/';
1917  }
1918 
1919  if (tp.item->key.obj_type == TYPE_INODE_REF) {
1920  INODE_REF* ir = (INODE_REF*)tp.item->data;
1921 
1922  RtlCopyMemory(ptr - ir->n, ir->name, ir->n);
1923  ptr -= ir->n;
1924  num = tp.item->key.offset;
1925  } else {
1926  INODE_EXTREF* ier = (INODE_EXTREF*)tp.item->data;
1927 
1928  RtlCopyMemory(ptr - ier->n, ier->name, ier->n);
1929  ptr -= ier->n;
1930  num = ier->dir;
1931  }
1932  }
1933 
1934  return true;
1935 }
uint64_t obj_id
Definition: btrfs.h:137
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
uint8_t obj_type
Definition: btrfs.h:138
uint16_t n
Definition: btrfs.h:371
Definition: http.c:7094
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
#define SUBVOL_ROOT_INODE
Definition: propsheet.cpp:42
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:430
unsigned short int uint16_t
Definition: acefiex.h:54
uint64_t offset
Definition: btrfs.h:139
uint8_t * data
Definition: btrfs_drv.h:431
Definition: fs.h:78
#define BTRFS_SEND_TLV_CLONE_PATH
Definition: btrfs.h:577
static PVOID ptr
Definition: dispmode.c:27
char name[1]
Definition: btrfs.h:365
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
#define TYPE_INODE_REF
Definition: btrfs.h:20
uint16_t n
Definition: btrfs.h:364
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2930
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
GLuint GLuint num
Definition: glext.h:9618
tree_data * item
Definition: btrfs_drv.h:518
Status
Definition: gdiplustypes.h:24
#define TYPE_INODE_EXTREF
Definition: btrfs.h:21
GLenum GLsizei len
Definition: glext.h:6722
BYTE uint8_t
Definition: msvideo1.c:66
uint64_t dir
Definition: btrfs.h:369
char name[1]
Definition: btrfs.h:372
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:136
UINT64 uint64_t
Definition: types.h:77
Definition: name.c:38
static void send_add_tlv(send_context *context, uint16_t type, void *data, uint16_t length)
Definition: send.c:132

Referenced by try_clone_edr().

◆ send_add_tlv_path()

static void send_add_tlv_path ( send_context context,
uint16_t  type,
send_dir parent,
char name,
uint16_t  namelen 
)
static

Definition at line 586 of file send.c.

586  {
588 
590 
591  if (len > 0)
592  find_path((char*)&context->data[context->datalen - len], parent, name, namelen);
593 }
Definition: http.c:7094
static __inline uint16_t find_path_len(send_dir *parent, uint16_t namelen)
Definition: send.c:560
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
unsigned short int uint16_t
Definition: acefiex.h:54
GLint namelen
Definition: glext.h:7232
smooth NULL
Definition: ftsmooth.c:416
static void find_path(char *path, send_dir *parent, char *name, ULONG namelen)
Definition: send.c:571
r parent
Definition: btrfs.c:2944
GLenum GLsizei len
Definition: glext.h:6722
Definition: name.c:38
static void send_add_tlv(send_context *context, uint16_t type, void *data, uint16_t length)
Definition: send.c:132

Referenced by flush_refs(), found_path(), make_file_orphan(), send_inode_extref(), send_inode_ref(), and send_utimes_command_dir().

◆ send_chmod_command()

static void send_chmod_command ( send_context context,
char path,
uint64_t  mode 
)
static

Definition at line 1000 of file send.c.

1000  {
1001  ULONG pos = context->datalen;
1002 
1004 
1005  mode &= 07777;
1006 
1009 
1011 }
Definition: http.c:7094
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
unsigned short int uint16_t
Definition: acefiex.h:54
static void send_command(send_context *context, uint16_t cmd)
Definition: send.c:116
#define BTRFS_SEND_TLV_PATH
Definition: btrfs.h:570