ReactOS  0.4.14-dev-606-g14ebc0b
send.c File Reference
#include "btrfs_drv.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 109 of file send.c.

◆ SEND_BUFFER_LENGTH

#define SEND_BUFFER_LENGTH   0x100000

Definition at line 110 of file send.c.

Typedef Documentation

◆ send_dir

Function Documentation

◆ _Function_class_()

_Function_class_ ( KSTART_ROUTINE  )

Definition at line 2969 of file send.c.

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

◆ add_ext_holes()

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

Definition at line 1651 of file send.c.

1651  {
1652  uint64_t lastoff = 0;
1653  LIST_ENTRY* le;
1654 
1655  le = exts->Flink;
1656  while (le != exts) {
1658 
1659  if (ext->offset > lastoff) {
1661  EXTENT_DATA2* ed2;
1662 
1663  if (!ext2) {
1664  ERR("out of memory\n");
1666  }
1667 
1668  ed2 = (EXTENT_DATA2*)ext2->data.data;
1669 
1670  ext2->offset = lastoff;
1671  ext2->datalen = offsetof(EXTENT_DATA, data) + sizeof(EXTENT_DATA2);
1672  ext2->data.decoded_size = ed2->num_bytes = ext->offset - lastoff;
1673  ext2->data.type = EXTENT_TYPE_REGULAR;
1674  ed2->address = ed2->size = ed2->offset = 0;
1675 
1676  InsertHeadList(le->Blink, &ext2->list_entry);
1677  }
1678 
1679  if (ext->data.type == EXTENT_TYPE_INLINE)
1680  lastoff = ext->offset + ext->data.decoded_size;
1681  else {
1682  EXTENT_DATA2* ed2 = (EXTENT_DATA2*)ext->data.data;
1683  lastoff = ext->offset + ed2->num_bytes;
1684  }
1685 
1686  le = le->Flink;
1687  }
1688 
1689  if (size > lastoff) {
1691  EXTENT_DATA2* ed2;
1692 
1693  if (!ext2) {
1694  ERR("out of memory\n");
1696  }
1697 
1698  ed2 = (EXTENT_DATA2*)ext2->data.data;
1699 
1700  ext2->offset = lastoff;
1701  ext2->datalen = offsetof(EXTENT_DATA, data) + sizeof(EXTENT_DATA2);
1702  ext2->data.decoded_size = ed2->num_bytes = sector_align(size - lastoff, Vcb->superblock.sector_size);
1703  ext2->data.type = EXTENT_TYPE_REGULAR;
1704  ed2->address = ed2->size = ed2->offset = 0;
1705 
1706  InsertTailList(exts, &ext2->list_entry);
1707  }
1708 
1709  return STATUS_SUCCESS;
1710 }
Definition: send.c:60
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
EXTENT_DATA2 * ed2
Definition: write.c:2819
struct _LIST_ENTRY * Blink
Definition: typedefs.h:120
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:346
#define offsetof(TYPE, MEMBER)
char ext[3]
Definition: mkdosfs.c:358
uint64_t size
Definition: btrfs.h:347
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
GLsizeiptr size
Definition: glext.h:5919
#define Vcb
Definition: cdprocs.h:1425
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:117
uint64_t num_bytes
Definition: btrfs.h:349
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:71
static const struct encodedExtensions exts[]
Definition: encode.c:2703
#define ERR(fmt,...)
Definition: debug.h:109
UINT64 uint64_t
Definition: types.h:77
Definition: list.h:27
uint64_t offset
Definition: btrfs.h:348
EXTENT_DATA data
Definition: send.c:64
return STATUS_SUCCESS
Definition: btrfs.c:2938
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 216 of file send.c.

216  {
217  LIST_ENTRY* le;
218 
219  le = context->orphans.Flink;
220  while (le != &context->orphans) {
222 
223  if (o2->inode > o->inode) {
225  return;
226  }
227 
228  le = le->Flink;
229  }
230 
231  InsertTailList(&context->orphans, &o->list_entry);
232 }
Definition: send.c:33
Definition: http.c:7098
struct _LIST_ENTRY * Blink
Definition: typedefs.h:120
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:35
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
Definition: typedefs.h:117
Definition: list.h:27
LIST_ENTRY list_entry
Definition: send.c:34

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 1102 of file send.c.

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

Referenced by flush_refs().

◆ divide_ext()

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

Definition at line 1712 of file send.c.

1712  {
1713  send_ext* ext2;
1714  EXTENT_DATA2 *ed2a, *ed2b;
1715 
1716  if (ext->data.type == EXTENT_TYPE_INLINE) {
1717  if (!trunc) {
1718  ext2 = ExAllocatePoolWithTag(PagedPool, (ULONG)(offsetof(send_ext, data.data) + ext->data.decoded_size - len), ALLOC_TAG);
1719 
1720  if (!ext2) {
1721  ERR("out of memory\n");
1723  }
1724 
1725  ext2->offset = ext->offset + len;
1726  ext2->datalen = (ULONG)(ext->data.decoded_size - len);
1727  ext2->data.decoded_size = ext->data.decoded_size - len;
1728  ext2->data.compression = ext->data.compression;
1729  ext2->data.encryption = ext->data.encryption;
1730  ext2->data.encoding = ext->data.encoding;
1731  ext2->data.type = ext->data.type;
1732  RtlCopyMemory(ext2->data.data, ext->data.data + len, (ULONG)(ext->data.decoded_size - len));
1733 
1734  InsertHeadList(&ext->list_entry, &ext2->list_entry);
1735  }
1736 
1737  ext->data.decoded_size = len;
1738 
1739  return STATUS_SUCCESS;
1740  }
1741 
1742  ed2a = (EXTENT_DATA2*)ext->data.data;
1743 
1744  if (!trunc) {
1746 
1747  if (!ext2) {
1748  ERR("out of memory\n");
1750  }
1751 
1752  ed2b = (EXTENT_DATA2*)ext2->data.data;
1753 
1754  ext2->offset = ext->offset + len;
1755  ext2->datalen = offsetof(EXTENT_DATA, data) + sizeof(EXTENT_DATA2);
1756 
1757  ext2->data.compression = ext->data.compression;
1758  ext2->data.encryption = ext->data.encryption;
1759  ext2->data.encoding = ext->data.encoding;
1760  ext2->data.type = ext->data.type;
1761  ed2b->num_bytes = ed2a->num_bytes - len;
1762 
1763  if (ed2a->size == 0) {
1764  ext2->data.decoded_size = ed2b->num_bytes;
1765  ext->data.decoded_size = len;
1766 
1767  ed2b->address = ed2b->size = ed2b->offset = 0;
1768  } else {
1769  ext2->data.decoded_size = ext->data.decoded_size;
1770 
1771  ed2b->address = ed2a->address;
1772  ed2b->size = ed2a->size;
1773  ed2b->offset = ed2a->offset + len;
1774  }
1775 
1776  InsertHeadList(&ext->list_entry, &ext2->list_entry);
1777  }
1778 
1779  ed2a->num_bytes = len;
1780 
1781  return STATUS_SUCCESS;
1782 }
Definition: send.c:60
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:346
double __cdecl trunc(double)
#define offsetof(TYPE, MEMBER)
char ext[3]
Definition: mkdosfs.c:358
uint64_t size
Definition: btrfs.h:347
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:349
#define ERR(fmt,...)
Definition: debug.h:109
unsigned int ULONG
Definition: retypes.h:1
uint64_t offset
Definition: btrfs.h:348
EXTENT_DATA data
Definition: send.c:64
return STATUS_SUCCESS
Definition: btrfs.c:2938

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 570 of file send.c.

570  {
571  ULONG len = namelen;
572 
574 
575  while (parent && parent->namelen > 0) {
576  RtlMoveMemory(path + parent->namelen + 1, path, len);
577  RtlCopyMemory(path, parent->name, parent->namelen);
578  path[parent->namelen] = '/';
579  len += parent->namelen + 1;
580 
581  parent = parent->parent;
582  }
583 }
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:263
r parent
Definition: btrfs.c:2869
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 559 of file send.c.

559  {
560  uint16_t len = namelen;
561 
562  while (parent && parent->namelen > 0) {
563  len += parent->namelen + 1;
564  parent = parent->parent;
565  }
566 
567  return len;
568 }
unsigned short int uint16_t
Definition: acefiex.h:54
GLint namelen
Definition: glext.h:7232
r parent
Definition: btrfs.c:2869
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 669 of file send.c.

669  {
671  LIST_ENTRY* le;
672  char name[64];
673 
674  le = context->dirs.Flink;
675  while (le != &context->dirs) {
677 
678  if (sd2->inode > dir)
679  break;
680  else if (sd2->inode == dir) {
681  *psd = sd2;
682 
683  if (added_dummy)
684  *added_dummy = false;
685 
686  return STATUS_SUCCESS;
687  }
688 
689  le = le->Flink;
690  }
691 
692  if (dir == SUBVOL_ROOT_INODE) {
693  Status = send_add_dir(context, dir, NULL, NULL, 0, false, le, psd);
694  if (!NT_SUCCESS(Status)) {
695  ERR("send_add_dir returned %08x\n", Status);
696  return Status;
697  }
698 
699  if (added_dummy)
700  *added_dummy = false;
701 
702  return STATUS_SUCCESS;
703  }
704 
705  if (context->parent) {
706  KEY searchkey;
708 
709  searchkey.obj_id = dir;
710  searchkey.obj_type = TYPE_INODE_REF; // directories should never have an extiref
711  searchkey.offset = 0xffffffffffffffff;
712 
713  Status = find_item(context->Vcb, context->parent, &tp, &searchkey, false, NULL);
714  if (!NT_SUCCESS(Status)) {
715  ERR("find_item returned %08x\n", Status);
716  return Status;
717  }
718 
719  if (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == searchkey.obj_type) {
720  INODE_REF* ir = (INODE_REF*)tp.item->data;
721  send_dir* parent;
722 
723  if (tp.item->size < sizeof(INODE_REF) || tp.item->size < offsetof(INODE_REF, name[0]) + ir->n) {
724  ERR("(%I64x,%x,%I64x) was truncated\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset);
725  return STATUS_INTERNAL_ERROR;
726  }
727 
729  parent = context->root_dir;
730  else {
732  if (!NT_SUCCESS(Status)) {
733  ERR("find_send_dir returned %08x\n", Status);
734  return Status;
735  }
736  }
737 
738  Status = send_add_dir(context, dir, parent, ir->name, ir->n, true, NULL, psd);
739  if (!NT_SUCCESS(Status)) {
740  ERR("send_add_dir returned %08x\n", Status);
741  return Status;
742  }
743 
744  if (added_dummy)
745  *added_dummy = false;
746 
747  return STATUS_SUCCESS;
748  }
749  }
750 
752  if (!NT_SUCCESS(Status)) {
753  ERR("get_orphan_name returned %08x\n", Status);
754  return Status;
755  }
756 
757  Status = send_add_dir(context, dir, NULL, name, (uint16_t)strlen(name), true, le, psd);
758  if (!NT_SUCCESS(Status)) {
759  ERR("send_add_dir returned %08x\n", Status);
760  return Status;
761  }
762 
763  if (added_dummy)
764  *added_dummy = true;
765 
766  return STATUS_SUCCESS;
767 }
uint64_t obj_id
Definition: btrfs.h:128
uint8_t obj_type
Definition: btrfs.h:129
Definition: http.c:7098
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:415
static NTSTATUS get_orphan_name(send_context *context, uint64_t inode, uint64_t generation, char *name)
Definition: send.c:163
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:496
uint64_t offset
Definition: btrfs.h:130
uint8_t * data
Definition: btrfs_drv.h:416
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
char name[1]
Definition: btrfs.h:355
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:354
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:2855
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
r parent
Definition: btrfs.c:2869
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
Definition: send.c:20
tree_data * item
Definition: btrfs_drv.h:502
Definition: typedefs.h:117
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
Definition: btrfs.h:127
uint64_t inode
Definition: send.c:22
_In_ uint64_t _In_ uint64_t _In_ uint64_t generation
Definition: btrfs.c:2854
Definition: list.h:27
Definition: name.c:38
return STATUS_SUCCESS
Definition: btrfs.c:2938
static NTSTATUS find_send_dir(send_context *context, uint64_t dir, uint64_t generation, send_dir **psd, bool *added_dummy)
Definition: send.c:669

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 2531 of file send.c.

2531  {
2532  LIST_ENTRY* le;
2533 
2534  if (!IsListEmpty(&context->lastinode.refs) || !IsListEmpty(&context->lastinode.oldrefs)) {
2535  NTSTATUS Status = flush_refs(context, tp1, tp2);
2536  if (!NT_SUCCESS(Status)) {
2537  ERR("flush_refs returned %08x\n", Status);
2538  return Status;
2539  }
2540 
2541  if (context->send->cancelling)
2542  return STATUS_SUCCESS;
2543  }
2544 
2545  if (!context->lastinode.deleting) {
2546  if (context->lastinode.file) {
2547  NTSTATUS Status = flush_extents(context, tp1, tp2);
2548  if (!NT_SUCCESS(Status)) {
2549  ERR("flush_extents returned %08x\n", Status);
2550  return Status;
2551  }
2552 
2553  if (context->send->cancelling)
2554  return STATUS_SUCCESS;
2555 
2556  send_truncate_command(context, context->lastinode.path, context->lastinode.size);
2557  }
2558 
2559  if (context->lastinode.new || context->lastinode.uid != context->lastinode.olduid || context->lastinode.gid != context->lastinode.oldgid)
2560  send_chown_command(context, context->lastinode.path, context->lastinode.uid, context->lastinode.gid);
2561 
2562  if (((context->lastinode.mode & __S_IFLNK) != __S_IFLNK || ((context->lastinode.mode & 07777) != 0777)) &&
2563  (context->lastinode.new || context->lastinode.mode != context->lastinode.oldmode))
2564  send_chmod_command(context, context->lastinode.path, context->lastinode.mode);
2565 
2566  send_utimes_command(context, context->lastinode.path, &context->lastinode.atime, &context->lastinode.mtime, &context->lastinode.ctime);
2567  }
2568 
2569  while (!IsListEmpty(&context->lastinode.exts)) {
2571  }
2572 
2573  while (!IsListEmpty(&context->lastinode.oldexts)) {
2575  }
2576 
2577  if (context->parent) {
2578  le = context->pending_rmdirs.Flink;
2579 
2580  while (le != &context->pending_rmdirs) {
2582 
2583  if (pr->last_child_inode <= context->lastinode.inode) {
2584  le = le->Flink;
2585 
2586  send_rmdir_command(context, pr->sd->namelen, pr->sd->name);
2587 
2588  RemoveEntryList(&pr->sd->list_entry);
2589 
2590  if (pr->sd->name)
2591  ExFreePool(pr->sd->name);
2592 
2593  while (!IsListEmpty(&pr->sd->deleted_children)) {
2595  ExFreePool(dc);
2596  }
2597 
2598  ExFreePool(pr->sd);
2599 
2601  ExFreePool(pr);
2602  } else
2603  break;
2604  }
2605  }
2606 
2607  context->lastinode.inode = 0;
2608  context->lastinode.o = NULL;
2609 
2610  if (context->lastinode.path) {
2611  ExFreePool(context->lastinode.path);
2612  context->lastinode.path = NULL;
2613  }
2614 
2615  return STATUS_SUCCESS;
2616 }
Definition: send.c:60
LIST_ENTRY deleted_children
Definition: send.c:30
Definition: http.c:7098
char * name
Definition: send.c:29
send_dir * sd
Definition: send.c:55
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:1012
LIST_ENTRY list_entry
Definition: send.c:57
_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:1052
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
uint16_t namelen
Definition: send.c:28
static void send_chmod_command(send_context *context, char *path, uint64_t mode)
Definition: send.c:999
static NTSTATUS flush_extents(send_context *context, traverse_ptr *tp1, traverse_ptr *tp2)
Definition: send.c:2126
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:119
static void send_chown_command(send_context *context, char *path, uint64_t uid, uint64_t gid)
Definition: send.c:987
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
Definition: typedefs.h:117
static void send_truncate_command(send_context *context, char *path, uint64_t size)
Definition: send.c:1025
Status
Definition: gdiplustypes.h:24
static NTSTATUS flush_refs(send_context *context, traverse_ptr *tp1, traverse_ptr *tp2)
Definition: send.c:1273
#define ERR(fmt,...)
Definition: debug.h:109
LIST_ENTRY list_entry
Definition: send.c:21
uint64_t last_child_inode
Definition: send.c:56
Definition: list.h:27
static const WCHAR dc[]
#define __S_IFLNK
Definition: btrfs_drv.h:1736
return STATUS_SUCCESS
Definition: btrfs.c:2938
#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 2126 of file send.c.

2126  {
2127  NTSTATUS Status;
2128 
2129  if ((IsListEmpty(&context->lastinode.exts) && IsListEmpty(&context->lastinode.oldexts)) || context->lastinode.size == 0)
2130  return STATUS_SUCCESS;
2131 
2132  if (context->parent) {
2133  Status = add_ext_holes(context->Vcb, &context->lastinode.exts, context->lastinode.size);
2134  if (!NT_SUCCESS(Status)) {
2135  ERR("add_ext_holes returned %08x\n", Status);
2136  return Status;
2137  }
2138 
2139  Status = add_ext_holes(context->Vcb, &context->lastinode.oldexts, context->lastinode.size);
2140  if (!NT_SUCCESS(Status)) {
2141  ERR("add_ext_holes returned %08x\n", Status);
2142  return Status;
2143  }
2144 
2146  if (!NT_SUCCESS(Status)) {
2147  ERR("sync_ext_cutoff_points returned %08x\n", Status);
2148  return Status;
2149  }
2150  }
2151 
2152  while (!IsListEmpty(&context->lastinode.exts)) {
2154  send_ext* se2 = context->parent ? CONTAINING_RECORD(RemoveHeadList(&context->lastinode.oldexts), send_ext, list_entry) : NULL;
2155  ULONG pos;
2156  EXTENT_DATA2* ed2;
2157 
2158  if (se2) {
2159  if (se->data.type == EXTENT_TYPE_INLINE && se2->data.type == EXTENT_TYPE_INLINE &&
2161  ExFreePool(se);
2162  ExFreePool(se2);
2163  continue;
2164  }
2165 
2166  if (se->data.type == EXTENT_TYPE_REGULAR && se2->data.type == EXTENT_TYPE_REGULAR) {
2167  EXTENT_DATA2 *ed2a, *ed2b;
2168 
2169  ed2a = (EXTENT_DATA2*)se->data.data;
2170  ed2b = (EXTENT_DATA2*)se2->data.data;
2171 
2172  if (RtlCompareMemory(ed2a, ed2b, sizeof(EXTENT_DATA2)) == sizeof(EXTENT_DATA2)) {
2173  ExFreePool(se);
2174  ExFreePool(se2);
2175  continue;
2176  }
2177  }
2178  }
2179 
2180  if (se->data.type == EXTENT_TYPE_INLINE) {
2181  pos = context->datalen;
2182 
2184 
2185  send_add_tlv(context, BTRFS_SEND_TLV_PATH, context->lastinode.path, context->lastinode.path ? (uint16_t)strlen(context->lastinode.path) : 0);
2187 
2191  ULONG inlen = se->datalen - (ULONG)offsetof(EXTENT_DATA, data[0]);
2192 
2194  RtlZeroMemory(&context->data[context->datalen - se->data.decoded_size], (ULONG)se->data.decoded_size);
2195 
2197  Status = zlib_decompress(se->data.data, inlen, &context->data[context->datalen - se->data.decoded_size], (uint32_t)se->data.decoded_size);
2198  if (!NT_SUCCESS(Status)) {
2199  ERR("zlib_decompress returned %08x\n", Status);
2200  ExFreePool(se);
2201  if (se2) ExFreePool(se2);
2202  return Status;
2203  }
2204  } else if (se->data.compression == BTRFS_COMPRESSION_LZO) {
2205  if (inlen < sizeof(uint32_t)) {
2206  ERR("extent data was truncated\n");
2207  ExFreePool(se);
2208  if (se2) ExFreePool(se2);
2209  return STATUS_INTERNAL_ERROR;
2210  } else
2211  inlen -= sizeof(uint32_t);
2212 
2213  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));
2214  if (!NT_SUCCESS(Status)) {
2215  ERR("lzo_decompress returned %08x\n", Status);
2216  ExFreePool(se);
2217  if (se2) ExFreePool(se2);
2218  return Status;
2219  }
2220  } else if (se->data.compression == BTRFS_COMPRESSION_ZSTD) {
2221  Status = zstd_decompress(se->data.data, inlen, &context->data[context->datalen - se->data.decoded_size], (uint32_t)se->data.decoded_size);
2222  if (!NT_SUCCESS(Status)) {
2223  ERR("zlib_decompress returned %08x\n", Status);
2224  ExFreePool(se);
2225  if (se2) ExFreePool(se2);
2226  return Status;
2227  }
2228  }
2229  } else {
2230  ERR("unhandled compression type %x\n", se->data.compression);
2231  ExFreePool(se);
2232  if (se2) ExFreePool(se2);
2233  return STATUS_NOT_IMPLEMENTED;
2234  }
2235 
2237 
2238  ExFreePool(se);
2239  if (se2) ExFreePool(se2);
2240  continue;
2241  }
2242 
2243  ed2 = (EXTENT_DATA2*)se->data.data;
2244 
2245  if (ed2->size != 0 && (context->parent || context->num_clones > 0)) {
2246  if (try_clone(context, se)) {
2247  ExFreePool(se);
2248  if (se2) ExFreePool(se2);
2249  continue;
2250  }
2251  }
2252 
2253  if (ed2->size == 0) { // write sparse
2254  uint64_t off, offset;
2255 
2256  for (off = ed2->offset; off < ed2->offset + ed2->num_bytes; off += MAX_SEND_WRITE) {
2257  uint16_t length = (uint16_t)min(min(ed2->offset + ed2->num_bytes - off, MAX_SEND_WRITE), context->lastinode.size - se->offset - off);
2258 
2259  if (context->datalen > SEND_BUFFER_LENGTH) {
2260  Status = wait_for_flush(context, tp1, tp2);
2261  if (!NT_SUCCESS(Status)) {
2262  ERR("wait_for_flush returned %08x\n", Status);
2263  ExFreePool(se);
2264  if (se2) ExFreePool(se2);
2265  return Status;
2266  }
2267 
2268  if (context->send->cancelling) {
2269  ExFreePool(se);
2270  if (se2) ExFreePool(se2);
2271  return STATUS_SUCCESS;
2272  }
2273  }
2274 
2275  pos = context->datalen;
2276 
2278 
2279  send_add_tlv(context, BTRFS_SEND_TLV_PATH, context->lastinode.path, context->lastinode.path ? (uint16_t)strlen(context->lastinode.path) : 0);
2280 
2281  offset = se->offset + off;
2283 
2285  RtlZeroMemory(&context->data[context->datalen - length], length);
2286 
2288  }
2289  } else if (se->data.compression == BTRFS_COMPRESSION_NONE) {
2290  uint64_t off, offset;
2291  uint8_t* buf;
2292 
2293  buf = ExAllocatePoolWithTag(NonPagedPool, MAX_SEND_WRITE + (2 * context->Vcb->superblock.sector_size), ALLOC_TAG);
2294  if (!buf) {
2295  ERR("out of memory\n");
2296  ExFreePool(se);
2297  if (se2) ExFreePool(se2);
2299  }
2300 
2301  for (off = ed2->offset; off < ed2->offset + ed2->num_bytes; off += MAX_SEND_WRITE) {
2303  ULONG skip_start;
2304  uint64_t addr = ed2->address + off;
2305  uint32_t* csum;
2306 
2307  if (context->datalen > SEND_BUFFER_LENGTH) {
2308  Status = wait_for_flush(context, tp1, tp2);
2309  if (!NT_SUCCESS(Status)) {
2310  ERR("wait_for_flush returned %08x\n", Status);
2311  ExFreePool(buf);
2312  ExFreePool(se);
2313  if (se2) ExFreePool(se2);
2314  return Status;
2315  }
2316 
2317  if (context->send->cancelling) {
2318  ExFreePool(buf);
2319  ExFreePool(se);
2320  if (se2) ExFreePool(se2);
2321  return STATUS_SUCCESS;
2322  }
2323  }
2324 
2325  skip_start = addr % context->Vcb->superblock.sector_size;
2326  addr -= skip_start;
2327 
2328  if (context->lastinode.flags & BTRFS_INODE_NODATASUM)
2329  csum = NULL;
2330  else {
2331  uint32_t len;
2332 
2333  len = (uint32_t)sector_align(length + skip_start, context->Vcb->superblock.sector_size) / context->Vcb->superblock.sector_size;
2334 
2336  if (!csum) {
2337  ERR("out of memory\n");
2338  ExFreePool(buf);
2339  ExFreePool(se);
2340  if (se2) ExFreePool(se2);
2342  }
2343 
2344  Status = load_csum(context->Vcb, csum, addr, len, NULL);
2345  if (!NT_SUCCESS(Status)) {
2346  ERR("load_csum returned %08x\n", Status);
2347  ExFreePool(csum);
2348  ExFreePool(buf);
2349  ExFreePool(se);
2350  if (se2) ExFreePool(se2);
2352  }
2353  }
2354 
2355  Status = read_data(context->Vcb, addr, (uint32_t)sector_align(length + skip_start, context->Vcb->superblock.sector_size),
2356  csum, false, buf, NULL, NULL, NULL, 0, false, NormalPagePriority);
2357  if (!NT_SUCCESS(Status)) {
2358  ERR("read_data returned %08x\n", Status);
2359  ExFreePool(buf);
2360  ExFreePool(se);
2361  if (se2) ExFreePool(se2);
2362  if (csum) ExFreePool(csum);
2363  return Status;
2364  }
2365 
2366  if (csum)
2367  ExFreePool(csum);
2368 
2369  pos = context->datalen;
2370 
2372 
2373  send_add_tlv(context, BTRFS_SEND_TLV_PATH, context->lastinode.path, context->lastinode.path ? (uint16_t)strlen(context->lastinode.path) : 0);
2374 
2375  offset = se->offset + off;
2377 
2378  length = (uint16_t)min(context->lastinode.size - se->offset - off, length);
2380 
2382  }
2383 
2384  ExFreePool(buf);
2385  } else {
2386  uint8_t *buf, *compbuf;
2387  uint64_t off;
2388  uint32_t* csum;
2389 
2391  if (!buf) {
2392  ERR("out of memory\n");
2393  ExFreePool(se);
2394  if (se2) ExFreePool(se2);
2396  }
2397 
2399  if (!compbuf) {
2400  ERR("out of memory\n");
2401  ExFreePool(buf);
2402  ExFreePool(se);
2403  if (se2) ExFreePool(se2);
2405  }
2406 
2407  if (context->lastinode.flags & BTRFS_INODE_NODATASUM)
2408  csum = NULL;
2409  else {
2410  uint32_t len;
2411 
2412  len = (uint32_t)(ed2->size / context->Vcb->superblock.sector_size);
2413 
2415  if (!csum) {
2416  ERR("out of memory\n");
2417  ExFreePool(compbuf);
2418  ExFreePool(buf);
2419  ExFreePool(se);
2420  if (se2) ExFreePool(se2);
2422  }
2423 
2424  Status = load_csum(context->Vcb, csum, ed2->address, len, NULL);
2425  if (!NT_SUCCESS(Status)) {
2426  ERR("load_csum returned %08x\n", Status);
2427  ExFreePool(csum);
2428  ExFreePool(compbuf);
2429  ExFreePool(buf);
2430  ExFreePool(se);
2431  if (se2) ExFreePool(se2);
2432  return Status;
2433  }
2434  }
2435 
2436  Status = read_data(context->Vcb, ed2->address, (uint32_t)ed2->size, csum, false, compbuf, NULL, NULL, NULL, 0, false, NormalPagePriority);
2437  if (!NT_SUCCESS(Status)) {
2438  ERR("read_data returned %08x\n", Status);
2439  ExFreePool(compbuf);
2440  ExFreePool(buf);
2441  ExFreePool(se);
2442  if (se2) ExFreePool(se2);
2443  if (csum) ExFreePool(csum);
2444  return Status;
2445  }
2446 
2447  if (csum)
2448  ExFreePool(csum);
2449 
2452  if (!NT_SUCCESS(Status)) {
2453  ERR("zlib_decompress returned %08x\n", Status);
2454  ExFreePool(compbuf);
2455  ExFreePool(buf);
2456  ExFreePool(se);
2457  if (se2) ExFreePool(se2);
2458  return Status;
2459  }
2460  } else if (se->data.compression == BTRFS_COMPRESSION_LZO) {
2461  Status = lzo_decompress(&compbuf[sizeof(uint32_t)], (uint32_t)ed2->size, buf, (uint32_t)se->data.decoded_size, sizeof(uint32_t));
2462  if (!NT_SUCCESS(Status)) {
2463  ERR("lzo_decompress returned %08x\n", Status);
2464  ExFreePool(compbuf);
2465  ExFreePool(buf);
2466  ExFreePool(se);
2467  if (se2) ExFreePool(se2);
2468  return Status;
2469  }
2470  } else if (se->data.compression == BTRFS_COMPRESSION_ZSTD) {
2472  if (!NT_SUCCESS(Status)) {
2473  ERR("zstd_decompress returned %08x\n", Status);
2474  ExFreePool(compbuf);
2475  ExFreePool(buf);
2476  ExFreePool(se);
2477  if (se2) ExFreePool(se2);
2478  return Status;
2479  }
2480  }
2481 
2482  ExFreePool(compbuf);
2483 
2484  for (off = ed2->offset; off < ed2->offset + ed2->num_bytes; off += MAX_SEND_WRITE) {
2486  uint64_t offset;
2487 
2488  if (context->datalen > SEND_BUFFER_LENGTH) {
2489  Status = wait_for_flush(context, tp1, tp2);
2490  if (!NT_SUCCESS(Status)) {
2491  ERR("wait_for_flush returned %08x\n", Status);
2492  ExFreePool(buf);
2493  ExFreePool(se);
2494  if (se2) ExFreePool(se2);
2495  return Status;
2496  }
2497 
2498  if (context->send->cancelling) {
2499  ExFreePool(buf);
2500  ExFreePool(se);
2501  if (se2) ExFreePool(se2);
2502  return STATUS_SUCCESS;
2503  }
2504  }
2505 
2506  pos = context->datalen;
2507 
2509 
2510  send_add_tlv(context, BTRFS_SEND_TLV_PATH, context->lastinode.path, context->lastinode.path ? (uint16_t)strlen(context->lastinode.path) : 0);
2511 
2512  offset = se->offset + off;
2514 
2515  length = (uint16_t)min(context->lastinode.size - se->offset - off, length);
2517 
2519  }
2520 
2521  ExFreePool(buf);
2522  }
2523 
2524  ExFreePool(se);
2525  if (se2) ExFreePool(se2);
2526  }
2527 
2528  return STATUS_SUCCESS;
2529 }
#define BTRFS_SEND_TLV_OFFSET
Definition: btrfs.h:563
Definition: send.c:60
NTSTATUS zstd_decompress(uint8_t *inbuf, uint32_t inlen, uint8_t *outbuf, uint32_t outlen)
Definition: compress.c:1133
uint8_t type
Definition: btrfs.h:341
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
static bool try_clone(send_context *context, send_ext *se)
Definition: send.c:2027
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:225
#define BTRFS_COMPRESSION_NONE
Definition: btrfs.h:61
#define BTRFS_SEND_TLV_DATA
Definition: btrfs.h:564
Definition: http.c:7098
EXTENT_DATA2 * ed2
Definition: write.c:2819
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:337
LONG NTSTATUS
Definition: precomp.h:26
GLintptr offset
Definition: glext.h:5920
static NTSTATUS sync_ext_cutoff_points(send_context *context)
Definition: send.c:1784
#define BTRFS_COMPRESSION_LZO
Definition: btrfs.h:63
#define BTRFS_COMPRESSION_ZSTD
Definition: btrfs.h:64
uint64_t offset
Definition: send.c:61
unsigned short int uint16_t
Definition: acefiex.h:54
#define uint16_t
Definition: nsiface.idl:60
ULONG datalen
Definition: send.c:63
_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:451
#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:115
uint64_t address
Definition: btrfs.h:346
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:1601
uint64_t size
Definition: btrfs.h:347
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
uint32_t * csum
Definition: write.c:2821
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
NTSTATUS load_csum(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, uint32_t *csum, uint64_t start, uint64_t length, PIRP Irp)
Definition: create.c:418
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:537
#define BTRFS_SEND_TLV_PATH
Definition: btrfs.h:560
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:349
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:71
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
uint8_t data[1]
Definition: btrfs.h:342
NTSTATUS zlib_decompress(uint8_t *inbuf, uint32_t inlen, uint8_t *outbuf, uint32_t outlen)
Definition: compress.c:336
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:124
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
uint64_t offset
Definition: btrfs.h:348
EXTENT_DATA data
Definition: send.c:64
#define uint32_t
Definition: nsiface.idl:61
return STATUS_SUCCESS
Definition: btrfs.c:2938
static void send_add_tlv(send_context *context, uint16_t type, void *data, uint16_t length)
Definition: send.c:131
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:1651
#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:338
off
Definition: i386-dis.c:3909
#define SEND_BUFFER_LENGTH
Definition: send.c:110
#define MAX_SEND_WRITE
Definition: send.c:109

Referenced by finish_inode().

◆ flush_refs()

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

Definition at line 1273 of file send.c.

1273  {
1274  NTSTATUS Status;
1275  LIST_ENTRY* le;
1276  ref *nameref = NULL, *nameref2 = NULL;
1277 
1278  if (context->lastinode.mode & __S_IFDIR) { // directory
1279  ref* r = IsListEmpty(&context->lastinode.refs) ? NULL : CONTAINING_RECORD(context->lastinode.refs.Flink, ref, list_entry);
1280  ref* or = IsListEmpty(&context->lastinode.oldrefs) ? NULL : CONTAINING_RECORD(context->lastinode.oldrefs.Flink, ref, list_entry);
1281 
1282  if (or && !context->lastinode.o) {
1283  ULONG len = find_path_len(or->sd, or->namelen);
1284 
1285  context->lastinode.path = ExAllocatePoolWithTag(PagedPool, len + 1, ALLOC_TAG);
1286  if (!context->lastinode.path) {
1287  ERR("out of memory\n");
1289  }
1290 
1291  find_path(context->lastinode.path, or->sd, or->name, or->namelen);
1292  context->lastinode.path[len] = 0;
1293 
1294  if (!context->lastinode.sd) {
1295  Status = find_send_dir(context, context->lastinode.inode, context->lastinode.gen, &context->lastinode.sd, false);
1296  if (!NT_SUCCESS(Status)) {
1297  ERR("find_send_dir returned %08x\n", Status);
1298  return Status;
1299  }
1300  }
1301  }
1302 
1303  if (r && or) {
1304  uint64_t inode;
1305  bool dir;
1306 
1307  Status = look_for_collision(context, r->sd, r->name, r->namelen, &inode, &dir);
1309  ERR("look_for_collision returned %08x\n", Status);
1310  return Status;
1311  }
1312 
1313  if (Status == STATUS_OBJECT_NAME_COLLISION && inode > context->lastinode.inode) {
1314  Status = make_file_orphan(context, inode, dir, context->parent->root_item.ctransid, r);
1315  if (!NT_SUCCESS(Status)) {
1316  ERR("make_file_orphan returned %08x\n", Status);
1317  return Status;
1318  }
1319  }
1320 
1321  if (context->lastinode.o) {
1322  Status = found_path(context, r->sd, r->name, r->namelen);
1323  if (!NT_SUCCESS(Status)) {
1324  ERR("found_path returned %08x\n", Status);
1325  return Status;
1326  }
1327 
1328  if (!r->sd->dummy)
1329  send_utimes_command_dir(context, r->sd, &r->sd->atime, &r->sd->mtime, &r->sd->ctime);
1330  } else if (r->sd != or->sd || r->namelen != or->namelen || RtlCompareMemory(r->name, or->name, r->namelen) != r->namelen) { // moved or renamed
1331  ULONG pos = context->datalen, len;
1332 
1334 
1335  send_add_tlv(context, BTRFS_SEND_TLV_PATH, context->lastinode.path, (uint16_t)strlen(context->lastinode.path));
1336 
1338 
1340 
1341  if (!r->sd->dummy)
1342  send_utimes_command_dir(context, r->sd, &r->sd->atime, &r->sd->mtime, &r->sd->ctime);
1343 
1344  if (context->lastinode.sd->name)
1345  ExFreePool(context->lastinode.sd->name);
1346 
1347  context->lastinode.sd->name = ExAllocatePoolWithTag(PagedPool, r->namelen, ALLOC_TAG);
1348  if (!context->lastinode.sd->name) {
1349  ERR("out of memory\n");
1351  }
1352 
1353  RtlCopyMemory(context->lastinode.sd->name, r->name, r->namelen);
1354  context->lastinode.sd->parent = r->sd;
1355 
1356  if (context->lastinode.path)
1357  ExFreePool(context->lastinode.path);
1358 
1359  len = find_path_len(r->sd, r->namelen);
1360  context->lastinode.path = ExAllocatePoolWithTag(PagedPool, len + 1, ALLOC_TAG);
1361  if (!context->lastinode.path) {
1362  ERR("out of memory\n");
1364  }
1365 
1366  find_path(context->lastinode.path, r->sd, r->name, r->namelen);
1367  context->lastinode.path[len] = 0;
1368  }
1369  } else if (r && !or) { // new
1370  Status = found_path(context, r->sd, r->name, r->namelen);
1371  if (!NT_SUCCESS(Status)) {
1372  ERR("found_path returned %08x\n", Status);
1373  return Status;
1374  }
1375 
1376  if (!r->sd->dummy)
1377  send_utimes_command_dir(context, r->sd, &r->sd->atime, &r->sd->mtime, &r->sd->ctime);
1378  } else { // deleted
1379  uint64_t last_inode;
1380 
1381  Status = get_dir_last_child(context, &last_inode);
1382  if (!NT_SUCCESS(Status)) {
1383  ERR("get_dir_last_child returned %08x\n", Status);
1384  return Status;
1385  }
1386 
1387  if (last_inode <= context->lastinode.inode) {
1388  send_rmdir_command(context, (uint16_t)strlen(context->lastinode.path), context->lastinode.path);
1389 
1390  if (!or->sd->dummy)
1391  send_utimes_command_dir(context, or->sd, &or->sd->atime, &or->sd->mtime, &or->sd->ctime);
1392  } else {
1393  char name[64];
1394  ULONG pos = context->datalen;
1395 
1396  Status = get_orphan_name(context, context->lastinode.inode, context->lastinode.gen, name);
1397  if (!NT_SUCCESS(Status)) {
1398  ERR("get_orphan_name returned %08x\n", Status);
1399  return Status;
1400  }
1401 
1403  send_add_tlv(context, BTRFS_SEND_TLV_PATH, context->lastinode.path, (uint16_t)strlen(context->lastinode.path));
1406 
1407  if (context->lastinode.sd->name)
1408  ExFreePool(context->lastinode.sd->name);
1409 
1410  context->lastinode.sd->name = ExAllocatePoolWithTag(PagedPool, strlen(name), ALLOC_TAG);
1411  if (!context->lastinode.sd->name) {
1412  ERR("out of memory\n");
1414  }
1415 
1416  RtlCopyMemory(context->lastinode.sd->name, name, strlen(name));
1417  context->lastinode.sd->namelen = (uint16_t)strlen(name);
1418  context->lastinode.sd->dummy = true;
1419  context->lastinode.sd->parent = NULL;
1420 
1421  send_utimes_command(context, NULL, &context->root_dir->atime, &context->root_dir->mtime, &context->root_dir->ctime);
1422 
1423  Status = add_pending_rmdir(context, last_inode);
1424  if (!NT_SUCCESS(Status)) {
1425  ERR("add_pending_rmdir returned %08x\n", Status);
1426  return Status;
1427  }
1428  }
1429  }
1430 
1431  while (!IsListEmpty(&context->lastinode.refs)) {
1432  r = CONTAINING_RECORD(RemoveHeadList(&context->lastinode.refs), ref, list_entry);
1433  ExFreePool(r);
1434  }
1435 
1436  while (!IsListEmpty(&context->lastinode.oldrefs)) {
1437  or = CONTAINING_RECORD(RemoveHeadList(&context->lastinode.oldrefs), ref, list_entry);
1438  ExFreePool(or);
1439  }
1440 
1441  return STATUS_SUCCESS;
1442  } else {
1443  if (!IsListEmpty(&context->lastinode.oldrefs)) {
1444  ref* or = CONTAINING_RECORD(context->lastinode.oldrefs.Flink, ref, list_entry);
1445  ULONG len = find_path_len(or->sd, or->namelen);
1446 
1447  context->lastinode.path = ExAllocatePoolWithTag(PagedPool, len + 1, ALLOC_TAG);
1448  if (!context->lastinode.path) {
1449  ERR("out of memory\n");
1451  }
1452 
1453  find_path(context->lastinode.path, or->sd, or->name, or->namelen);
1454  context->lastinode.path[len] = 0;
1455  nameref = or;
1456  }
1457 
1458  // remove unchanged refs
1459  le = context->lastinode.oldrefs.Flink;
1460  while (le != &context->lastinode.oldrefs) {
1461  ref* or = CONTAINING_RECORD(le, ref, list_entry);
1462  LIST_ENTRY* le2;
1463  bool matched = false;
1464 
1465  le2 = context->lastinode.refs.Flink;
1466  while (le2 != &context->lastinode.refs) {
1467  ref* r = CONTAINING_RECORD(le2, ref, list_entry);
1468 
1469  if (r->sd == or->sd && r->namelen == or->namelen && RtlCompareMemory(r->name, or->name, r->namelen) == r->namelen) {
1470  RemoveEntryList(&r->list_entry);
1471  ExFreePool(r);
1472  matched = true;
1473  break;
1474  }
1475 
1476  le2 = le2->Flink;
1477  }
1478 
1479  if (matched) {
1480  le = le->Flink;
1482  ExFreePool(or);
1483  continue;
1484  }
1485 
1486  le = le->Flink;
1487  }
1488 
1489  while (!IsListEmpty(&context->lastinode.refs)) {
1490  ref* r = CONTAINING_RECORD(RemoveHeadList(&context->lastinode.refs), ref, list_entry);
1491  uint64_t inode;
1492  bool dir;
1493 
1494  if (context->parent) {
1495  Status = look_for_collision(context, r->sd, r->name, r->namelen, &inode, &dir);
1497  ERR("look_for_collision returned %08x\n", Status);
1498  return Status;
1499  }
1500 
1501  if (Status == STATUS_OBJECT_NAME_COLLISION && inode > context->lastinode.inode) {
1502  Status = make_file_orphan(context, inode, dir, context->lastinode.gen, r);
1503  if (!NT_SUCCESS(Status)) {
1504  ERR("make_file_orphan returned %08x\n", Status);
1505  return Status;
1506  }
1507  }
1508  }
1509 
1510  if (context->datalen > SEND_BUFFER_LENGTH) {
1511  Status = wait_for_flush(context, tp1, tp2);
1512  if (!NT_SUCCESS(Status)) {
1513  ERR("wait_for_flush returned %08x\n", Status);
1514  return Status;
1515  }
1516 
1517  if (context->send->cancelling)
1518  return STATUS_SUCCESS;
1519  }
1520 
1521  Status = found_path(context, r->sd, r->name, r->namelen);
1522  if (!NT_SUCCESS(Status)) {
1523  ERR("found_path returned %08x\n", Status);
1524  return Status;
1525  }
1526 
1527  if (!r->sd->dummy)
1528  send_utimes_command_dir(context, r->sd, &r->sd->atime, &r->sd->mtime, &r->sd->ctime);
1529 
1530  if (nameref && !nameref2)
1531  nameref2 = r;
1532  else
1533  ExFreePool(r);
1534  }
1535 
1536  while (!IsListEmpty(&context->lastinode.oldrefs)) {
1537  ref* or = CONTAINING_RECORD(RemoveHeadList(&context->lastinode.oldrefs), ref, list_entry);
1538  bool deleted = false;
1539 
1540  le = or->sd->deleted_children.Flink;
1541  while (le != &or->sd->deleted_children) {
1543 
1544  if (dc->namelen == or->namelen && RtlCompareMemory(dc->name, or->name, or->namelen) == or->namelen) {
1545  RemoveEntryList(&dc->list_entry);
1546  ExFreePool(dc);
1547  deleted = true;
1548  break;
1549  }
1550 
1551  le = le->Flink;
1552  }
1553 
1554  if (!deleted) {
1555  if (context->datalen > SEND_BUFFER_LENGTH) {
1556  Status = wait_for_flush(context, tp1, tp2);
1557  if (!NT_SUCCESS(Status)) {
1558  ERR("wait_for_flush returned %08x\n", Status);
1559  return Status;
1560  }
1561 
1562  if (context->send->cancelling)
1563  return STATUS_SUCCESS;
1564  }
1565 
1566  Status = send_unlink_command(context, or->sd, or->namelen, or->name);
1567  if (!NT_SUCCESS(Status)) {
1568  ERR("send_unlink_command returned %08x\n", Status);
1569  return Status;
1570  }
1571 
1572  if (!or->sd->dummy)
1573  send_utimes_command_dir(context, or->sd, &or->sd->atime, &or->sd->mtime, &or->sd->ctime);
1574  }
1575 
1576  if (or == nameref && nameref2) {
1577  uint16_t len = find_path_len(nameref2->sd, nameref2->namelen);
1578 
1579  if (context->lastinode.path)
1580  ExFreePool(context->lastinode.path);
1581 
1582  context->lastinode.path = ExAllocatePoolWithTag(PagedPool, len + 1, ALLOC_TAG);
1583  if (!context->lastinode.path) {
1584  ERR("out of memory\n");
1586  }
1587 
1588  find_path(context->lastinode.path, nameref2->sd, nameref2->name, nameref2->namelen);
1589  context->lastinode.path[len] = 0;
1590 
1591  ExFreePool(nameref2);
1592  }
1593 
1594  ExFreePool(or);
1595  }
1596  }
1597 
1598  return STATUS_SUCCESS;
1599 }
#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:1102
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LIST_ENTRY deleted_children
Definition: send.c:30
bool dummy
Definition: send.c:23
#define BTRFS_SEND_TLV_PATH_TO
Definition: btrfs.h:561
Definition: http.c:7098
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:559
r lastinode
Definition: btrfs.c:2885
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:163
static void send_utimes_command(send_context *context, char *path, BTRFS_TIME *atime, BTRFS_TIME *mtime, BTRFS_TIME *ctime)
Definition: send.c:1012
unsigned short int uint16_t
Definition: acefiex.h:54
#define uint16_t
Definition: nsiface.idl:60
LIST_ENTRY list_entry
Definition: send.c:48
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
Definition: send.c:47
static void send_rmdir_command(send_context *context, uint16_t pathlen, char *path)
Definition: send.c:1052
Definition: fs.h:78
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
uint16_t namelen
Definition: send.c:28
#define ALLOC_TAG
Definition: btrfs_drv.h:91
static void send_command(send_context *context, uint16_t cmd)
Definition: send.c:115
char name[1]
Definition: send.c:51
static NTSTATUS found_path(send_context *context, send_dir *parent, char *name, uint16_t namelen)
Definition: send.c:594
static NTSTATUS make_file_orphan(send_context *context, uint64_t inode, bool dir, uint64_t generation, ref *r)
Definition: send.c:1174
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:1601
unsigned int dir
Definition: maze.c:112
BTRFS_TIME mtime
Definition: send.c:25
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:570
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
static NTSTATUS get_dir_last_child(send_context *context, uint64_t *last_inode)
Definition: send.c:1060
#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:1036
uint16_t namelen
Definition: send.c:50
BTRFS_TIME atime
Definition: send.c:24
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define BTRFS_SEND_TLV_PATH
Definition: btrfs.h:560
BTRFS_TIME ctime
Definition: send.c:26
GLenum GLsizei len
Definition: glext.h:6722
Definition: typedefs.h:117
#define BTRFS_SEND_CMD_RENAME
Definition: btrfs.h:531
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
UINT64 uint64_t
Definition: types.h:77
Definition: list.h:27
#define __S_IFDIR
Definition: btrfs_drv.h:1731
Definition: name.c:38
static void send_command_finish(send_context *context, ULONG pos)
Definition: send.c:124
unsigned int ULONG
Definition: retypes.h:1
static const WCHAR dc[]
send_dir * sd
Definition: send.c:49
static void send_add_tlv_path(send_context *context, uint16_t type, send_dir *parent, char *name, uint16_t namelen)
Definition: send.c:585
return STATUS_SUCCESS
Definition: btrfs.c:2938
static void send_add_tlv(send_context *context, uint16_t type, void *data, uint16_t length)
Definition: send.c:131
#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:669
#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:655
static NTSTATUS look_for_collision(send_context *context, send_dir *sd, char *name, ULONG namelen, uint64_t *inode, bool *dir)
Definition: send.c:1132
#define SEND_BUFFER_LENGTH
Definition: send.c:110

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 594 of file send.c.

594  {
595  ULONG pos = context->datalen;
596 
597  if (context->lastinode.o) {
599 
600  send_add_tlv_path(context, BTRFS_SEND_TLV_PATH, context->root_dir, context->lastinode.o->tmpname, (uint16_t)strlen(context->lastinode.o->tmpname));
601 
603 
605  } else {
607 
609 
610  send_add_tlv(context, BTRFS_SEND_TLV_PATH_LINK, context->lastinode.path, context->lastinode.path ? (uint16_t)strlen(context->lastinode.path) : 0);
611 
613  }
614 
615  if (context->lastinode.o) {
616  uint16_t pathlen;
617 
618  if (context->lastinode.o->sd) {
619  if (context->lastinode.o->sd->name)
620  ExFreePool(context->lastinode.o->sd->name);
621 
622  context->lastinode.o->sd->name = ExAllocatePoolWithTag(PagedPool, namelen, ALLOC_TAG);
623  if (!context->lastinode.o->sd->name) {
624  ERR("out of memory\n");
626  }
627 
628  RtlCopyMemory(context->lastinode.o->sd->name, name, namelen);
629  context->lastinode.o->sd->namelen = namelen;
630  context->lastinode.o->sd->parent = parent;
631  }
632 
633  if (context->lastinode.path)
634  ExFreePool(context->lastinode.path);
635 
636  pathlen = find_path_len(parent, namelen);
637  context->lastinode.path = ExAllocatePoolWithTag(PagedPool, pathlen + 1, ALLOC_TAG);
638  if (!context->lastinode.path) {
639  ERR("out of memory\n");
641  }
642 
643  find_path(context->lastinode.path, parent, name, namelen);
644  context->lastinode.path[pathlen] = 0;
645 
646  RemoveEntryList(&context->lastinode.o->list_entry);
647  ExFreePool(context->lastinode.o);
648 
649  context->lastinode.o = NULL;
650  }
651 
652  return STATUS_SUCCESS;
653 }
#define BTRFS_SEND_CMD_LINK
Definition: btrfs.h:532
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:561
Definition: http.c:7098
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:559
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:115
smooth NULL
Definition: ftsmooth.c:416
static void find_path(char *path, send_dir *parent, char *name, ULONG namelen)
Definition: send.c:570
#define BTRFS_SEND_TLV_PATH_LINK
Definition: btrfs.h:562
r parent
Definition: btrfs.c:2869
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define BTRFS_SEND_TLV_PATH
Definition: btrfs.h:560
#define BTRFS_SEND_CMD_RENAME
Definition: btrfs.h:531
#define ERR(fmt,...)
Definition: debug.h:109
Definition: name.c:38
static void send_command_finish(send_context *context, ULONG pos)
Definition: send.c:124
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:585
return STATUS_SUCCESS
Definition: btrfs.c:2938
static void send_add_tlv(send_context *context, uint16_t type, void *data, uint16_t length)
Definition: send.c:131
#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 1060 of file send.c.

1060  {
1061  NTSTATUS Status;
1062  KEY searchkey;
1063  traverse_ptr tp;
1064 
1065  *last_inode = 0;
1066 
1067  searchkey.obj_id = context->lastinode.inode;
1068  searchkey.obj_type = TYPE_DIR_INDEX;
1069  searchkey.offset = 2;
1070 
1071  Status = find_item(context->Vcb, context->parent, &tp, &searchkey, false, NULL);
1072  if (!NT_SUCCESS(Status)) {
1073  ERR("find_item returned %08x\n", Status);
1074  return Status;
1075  }
1076 
1077  do {
1078  traverse_ptr next_tp;
1079 
1080  if (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == searchkey.obj_type) {
1081  DIR_ITEM* di = (DIR_ITEM*)tp.item->data;
1082 
1083  if (tp.item->size < sizeof(DIR_ITEM) || tp.item->size < offsetof(DIR_ITEM, name[0]) + di->m + di->n) {
1084  ERR("(%I64x,%x,%I64x) was truncated\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset);
1085  return STATUS_INTERNAL_ERROR;
1086  }
1087 
1088  if (di->key.obj_type == TYPE_INODE_ITEM)
1089  *last_inode = max(*last_inode, di->key.obj_id);
1090  } else
1091  break;
1092 
1093  if (find_next_item(context->Vcb, &tp, &next_tp, false, NULL))
1094  tp = next_tp;
1095  else
1096  break;
1097  } while (true);
1098 
1099  return STATUS_SUCCESS;
1100 }
uint64_t obj_id
Definition: btrfs.h:128
#define max(a, b)
Definition: svc.c:63
uint8_t obj_type
Definition: btrfs.h:129
Definition: http.c:7098
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:415
#define TYPE_DIR_INDEX
Definition: btrfs.h:25
uint64_t offset
Definition: btrfs.h:130
uint8_t * data
Definition: btrfs_drv.h:416
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
uint16_t m
Definition: btrfs.h:258
KEY key
Definition: btrfs.h:256
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:2855
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:592
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
tree_data * item
Definition: btrfs_drv.h:502
#define TYPE_INODE_ITEM
Definition: btrfs.h:19
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
Definition: btrfs.h:127
Definition: name.c:38
uint16_t n
Definition: btrfs.h:259
return STATUS_SUCCESS
Definition: btrfs.c:2938

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 163 of file send.c.

163  {
164  char *ptr, *ptr2;
165  uint64_t index = 0;
166  KEY searchkey;
167 
168  name[0] = 'o';
169 
170  ptr = uint64_to_char(inode, &name[1]);
171  *ptr = '-'; ptr++;
173  *ptr = '-'; ptr++;
174  ptr2 = ptr;
175 
176  searchkey.obj_id = SUBVOL_ROOT_INODE;
177  searchkey.obj_type = TYPE_DIR_ITEM;
178 
179  do {
182 
184  *ptr = 0;
185 
186  searchkey.offset = calc_crc32c(0xfffffffe, (uint8_t*)name, (ULONG)(ptr - name));
187 
188  Status = find_item(context->Vcb, context->root, &tp, &searchkey, false, NULL);
189  if (!NT_SUCCESS(Status)) {
190  ERR("find_item returned %08x\n", Status);
191  return Status;
192  }
193 
194  if (!keycmp(searchkey, tp.item->key))
195  goto cont;
196 
197  if (context->parent) {
198  Status = find_item(context->Vcb, context->parent, &tp, &searchkey, false, NULL);
199  if (!NT_SUCCESS(Status)) {
200  ERR("find_item returned %08x\n", Status);
201  return Status;
202  }
203 
204  if (!keycmp(searchkey, tp.item->key))
205  goto cont;
206  }
207 
208  return STATUS_SUCCESS;
209 
210 cont:
211  index++;
212  ptr = ptr2;
213  } while (true);
214 }
uint64_t obj_id
Definition: btrfs.h:128
uint8_t obj_type
Definition: btrfs.h:129
Definition: http.c:7098
#define SUBVOL_ROOT_INODE
Definition: propsheet.cpp:42
#define keycmp(key1, key2)
Definition: btrfs_drv.h:991
LONG NTSTATUS
Definition: precomp.h:26
uint64_t offset
Definition: btrfs.h:130
static uint32_t calc_crc32c(uint32_t seed, uint8_t *msg, ULONG msglen)
Definition: recv.cpp:134
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:2855
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:143
tree_data * item
Definition: btrfs_drv.h:502
BYTE uint8_t
Definition: msvideo1.c:66
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
Definition: btrfs.h:127
UINT64 uint64_t
Definition: types.h:77
_In_ uint64_t _In_ uint64_t _In_ uint64_t generation
Definition: btrfs.c:2854
#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:2938

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 1132 of file send.c.

1132  {
1133  NTSTATUS Status;
1134  KEY searchkey;
1135  traverse_ptr tp;
1136  DIR_ITEM* di;
1137  uint16_t len;
1138 
1139  searchkey.obj_id = sd->inode;
1140  searchkey.obj_type = TYPE_DIR_ITEM;
1141  searchkey.offset = calc_crc32c(0xfffffffe, (uint8_t*)name, namelen);
1142 
1143  Status = find_item(context->Vcb, context->parent, &tp, &searchkey, false, NULL);
1144  if (!NT_SUCCESS(Status)) {
1145  ERR("find_item returned %08x\n", Status);
1146  return Status;
1147  }
1148 
1149  if (keycmp(tp.item->key, searchkey))
1150  return STATUS_SUCCESS;
1151 
1152  di = (DIR_ITEM*)tp.item->data;
1153  len = tp.item->size;
1154 
1155  do {
1156  if (len < sizeof(DIR_ITEM) || len < offsetof(DIR_ITEM, name[0]) + di->m + di->n) {
1157  ERR("(%I64x,%x,%I64x) was truncated\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset);
1158  return STATUS_INTERNAL_ERROR;
1159  }
1160 
1161  if (di->n == namelen && RtlCompareMemory(di->name, name, namelen) == namelen) {
1162  *inode = di->key.obj_type == TYPE_INODE_ITEM ? di->key.obj_id : 0;
1163  *dir = di->type == BTRFS_TYPE_DIRECTORY ? true: false;
1165  }
1166 
1167  di = (DIR_ITEM*)&di->name[di->m + di->n];
1168  len -= (uint16_t)offsetof(DIR_ITEM, name[0]) + di->m + di->n;
1169  } while (len > 0);
1170 
1171  return STATUS_SUCCESS;
1172 }
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
uint64_t obj_id
Definition: btrfs.h:128
uint8_t obj_type
Definition: btrfs.h:129
Definition: http.c:7098
#define keycmp(key1, key2)
Definition: btrfs_drv.h:991
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:415
unsigned short int uint16_t
Definition: acefiex.h:54
GLint namelen
Definition: glext.h:7232
uint64_t offset
Definition: btrfs.h:130
static uint32_t calc_crc32c(uint32_t seed, uint8_t *msg, ULONG msglen)
Definition: recv.cpp:134
uint8_t * data
Definition: btrfs_drv.h:416
Definition: fs.h:78
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
uint16_t m
Definition: btrfs.h:258
KEY key
Definition: btrfs.h:256
char name[1]
Definition: btrfs.h:261
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:86
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
uint8_t type
Definition: btrfs.h:260
unsigned int dir
Definition: maze.c:112
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2855
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:502
#define TYPE_INODE_ITEM
Definition: btrfs.h:19
GLenum GLsizei len
Definition: glext.h:6722
BYTE uint8_t
Definition: msvideo1.c:66
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
Definition: btrfs.h:127
#define TYPE_DIR_ITEM
Definition: btrfs.h:24
Definition: name.c:38
uint16_t n
Definition: btrfs.h:259
return STATUS_SUCCESS
Definition: btrfs.c:2938
#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 1174 of file send.c.

1174  {
1175  NTSTATUS Status;
1176  ULONG pos = context->datalen;
1177  send_dir* sd = NULL;
1178  orphan* o;
1179  LIST_ENTRY* le;
1180  char name[64];
1181 
1182  if (!dir) {
1183  deleted_child* dc;
1184 
1186  if (!dc) {
1187  ERR("out of memory\n");
1189  }
1190 
1191  dc->namelen = r->namelen;
1192  RtlCopyMemory(dc->name, r->name, r->namelen);
1193  InsertTailList(&r->sd->deleted_children, &dc->list_entry);
1194  }
1195 
1196  le = context->orphans.Flink;
1197  while (le != &context->orphans) {
1199 
1200  if (o2->inode == inode) {
1202 
1203  send_add_tlv_path(context, BTRFS_SEND_TLV_PATH, r->sd, r->name, r->namelen);
1204 
1206 
1207  return STATUS_SUCCESS;
1208  } else if (o2->inode > inode)
1209  break;
1210 
1211  le = le->Flink;
1212  }
1213 
1215  if (!NT_SUCCESS(Status)) {
1216  ERR("get_orphan_name returned %08x\n", Status);
1217  return Status;
1218  }
1219 
1220  if (dir) {
1222  if (!NT_SUCCESS(Status)) {
1223  ERR("find_send_dir returned %08x\n", Status);
1224  return Status;
1225  }
1226 
1227  sd->dummy = true;
1228 
1230 
1231  send_add_tlv_path(context, BTRFS_SEND_TLV_PATH, r->sd, r->name, r->namelen);
1233 
1235 
1236  if (sd->name)
1237  ExFreePool(sd->name);
1238 
1239  sd->namelen = (uint16_t)strlen(name);
1240  sd->name = ExAllocatePoolWithTag(PagedPool, sd->namelen, ALLOC_TAG);
1241  if (!sd->name) {
1242  ERR("out of memory\n");
1244  }
1245 
1246  RtlCopyMemory(sd->name, name, sd->namelen);
1247  sd->parent = context->root_dir;
1248  } else {
1250 
1251  send_add_tlv_path(context, BTRFS_SEND_TLV_PATH, r->sd, r->name, r->namelen);
1252 
1254 
1256  }
1257 
1259  if (!o) {
1260  ERR("out of memory\n");
1262  }
1263 
1264  o->inode = inode;
1265  o->dir = true;
1266  strcpy(o->tmpname, name);
1267  o->sd = sd;
1268  add_orphan(context, o);
1269 
1270  return STATUS_SUCCESS;
1271 }
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:33
#define BTRFS_SEND_TLV_PATH_TO
Definition: btrfs.h:561
Definition: http.c:7098
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:163
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:35
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:115
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:119
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
char tmpname[64]
Definition: send.c:38
bool dir
Definition: send.c:36
char * name
Definition: compiler.c:66
Definition: send.c:20
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define BTRFS_SEND_TLV_PATH
Definition: btrfs.h:560
static const WCHAR sd[]
Definition: suminfo.c:287
send_dir * sd
Definition: send.c:37
Definition: typedefs.h:117
#define BTRFS_SEND_CMD_RENAME
Definition: btrfs.h:531
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
_In_ uint64_t _In_ uint64_t _In_ uint64_t generation
Definition: btrfs.c:2854
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:124
unsigned int ULONG
Definition: retypes.h:1
static const WCHAR dc[]
#define BTRFS_SEND_CMD_UNLINK
Definition: btrfs.h:533
static void send_add_tlv_path(send_context *context, uint16_t type, send_dir *parent, char *name, uint16_t namelen)
Definition: send.c:585
return STATUS_SUCCESS
Definition: btrfs.c:2938
#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:669
static void add_orphan(send_context *context, orphan *o)
Definition: send.c:216

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 3838 of file send.c.

3838  {
3839  ccb* ccb;
3841 
3842  ccb = FileObject ? FileObject->FsContext2 : NULL;
3843  if (!ccb)
3844  return STATUS_INVALID_PARAMETER;
3845 
3846  if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), processor_mode))
3848 
3849  ExAcquireResourceExclusiveLite(&Vcb->send_load_lock, true);
3850 
3851  if (!ccb->send) {
3852  ExReleaseResourceLite(&Vcb->send_load_lock);
3854  }
3855 
3857 
3858  KeWaitForSingleObject(&context->buffer_event, Executive, KernelMode, false, NULL);
3859 
3860  if (datalen == 0) {
3861  ExReleaseResourceLite(&Vcb->send_load_lock);
3862  return STATUS_SUCCESS;
3863  }
3864 
3865  RtlCopyMemory(data, context->data, min(datalen, context->datalen));
3866 
3867  if (datalen < context->datalen) { // not empty yet
3868  *retlen = datalen;
3869  RtlMoveMemory(context->data, &context->data[datalen], context->datalen - datalen);
3870  context->datalen -= datalen;
3871  ExReleaseResourceLite(&Vcb->send_load_lock);
3872  } else {
3873  *retlen = context->datalen;
3874  context->datalen = 0;
3875  ExReleaseResourceLite(&Vcb->send_load_lock);
3876 
3877  KeClearEvent(&context->buffer_event);
3878  KeSetEvent(&ccb->send->cleared_event, 0, false);
3879  }
3880 
3881  return STATUS_SUCCESS;
3882 }
#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:7098
#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:1027
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:263
#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:593
NTSTATUS send_status
Definition: btrfs_drv.h:394
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
KEVENT cleared_event
Definition: btrfs_drv.h:366
#define Vcb
Definition: cdprocs.h:1425
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:365
#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:2938
send_info * send
Definition: btrfs_drv.h:393

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 496 of file send.c.

496  {
497  LIST_ENTRY* le;
499 
500  if (!sd) {
501  ERR("out of memory\n");
503  }
504 
505  sd->inode = inode;
506  sd->dummy = dummy;
507  sd->parent = parent;
508 
509  if (!dummy) {
510  sd->atime = context->lastinode.atime;
511  sd->mtime = context->lastinode.mtime;
512  sd->ctime = context->lastinode.ctime;
513  }
514 
515  if (namelen > 0) {
517  if (!sd->name) {
518  ERR("out of memory\n");
519  ExFreePool(sd);
521  }
522 
523  memcpy(sd->name, name, namelen);
524  } else
525  sd->name = NULL;
526 
527  sd->namelen = namelen;
528 
529  InitializeListHead(&sd->deleted_children);
530 
531  if (lastentry)
532  InsertHeadList(lastentry, &sd->list_entry);
533  else {
534  le = context->dirs.Flink;
535  while (le != &context->dirs) {
537 
538  if (sd2->inode > sd->inode) {
539  InsertHeadList(sd2->list_entry.Blink, &sd->list_entry);
540 
541  if (psd)
542  *psd = sd;
543 
544  return STATUS_SUCCESS;
545  }
546 
547  le = le->Flink;
548  }
549 
550  InsertTailList(&context->dirs, &sd->list_entry);
551  }
552 
553  if (psd)
554  *psd = sd;
555 
556  return STATUS_SUCCESS;
557 }
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
Definition: http.c:7098
struct _LIST_ENTRY * Blink
Definition: typedefs.h:120
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:119
r parent
Definition: btrfs.c:2869
Definition: send.c:20
#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:117
#define ERR(fmt,...)
Definition: debug.h:109
LIST_ENTRY list_entry
Definition: send.c:21
unsigned char dummy
Definition: maze.c:118
uint64_t inode
Definition: send.c:22
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
Definition: list.h:27
Definition: name.c:38
return STATUS_SUCCESS
Definition: btrfs.c:2938
#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 131 of file send.c.

131  {
132  btrfs_send_tlv* tlv = (btrfs_send_tlv*)&context->data[context->datalen];
133 
134  tlv->type = type;
135  tlv->length = length;
136 
137  if (length > 0 && data)
138  RtlCopyMemory(&tlv[1], data, length);
139 
140  context->datalen += sizeof(btrfs_send_tlv) + length;
141 }
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
Definition: http.c:7098
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:585
uint16_t length
Definition: btrfs.h:586

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 1840 of file send.c.

1840  {
1841  NTSTATUS Status;
1842  KEY searchkey;
1843  traverse_ptr tp;
1844  uint16_t len = 0;
1845  uint64_t num;
1846  uint8_t* ptr;
1847 
1848  num = inode;
1849 
1850  while (num != SUBVOL_ROOT_INODE) {
1851  searchkey.obj_id = num;
1852  searchkey.obj_type = TYPE_INODE_EXTREF;
1853  searchkey.offset = 0xffffffffffffffff;
1854 
1855  Status = find_item(context->Vcb, r, &tp, &searchkey, false, NULL);
1856  if (!NT_SUCCESS(Status)) {
1857  ERR("find_item returned %08x\n", Status);
1858  return false;
1859  }
1860 
1861  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)) {
1862  ERR("could not find INODE_REF for inode %I64x\n", searchkey.obj_id);
1863  return false;
1864  }
1865 
1866  if (len > 0)
1867  len++;
1868 
1869  if (tp.item->key.obj_type == TYPE_INODE_REF) {
1870  INODE_REF* ir = (INODE_REF*)tp.item->data;
1871 
1872  if (tp.item->size < sizeof(INODE_REF) || tp.item->size < offsetof(INODE_REF, name[0]) + ir->n) {
1873  ERR("(%I64x,%x,%I64x) was truncated\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset);
1874  return false;
1875  }
1876 
1877  len += ir->n;
1878  num = tp.item->key.offset;
1879  } else {
1880  INODE_EXTREF* ier = (INODE_EXTREF*)tp.item->data;
1881 
1882  if (tp.item->size < sizeof(INODE_EXTREF) || tp.item->size < offsetof(INODE_EXTREF, name[0]) + ier->n) {
1883  ERR("(%I64x,%x,%I64x) was truncated\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset);
1884  return false;
1885  }
1886 
1887  len += ier->n;
1888  num = ier->dir;
1889  }
1890  }
1891 
1893  ptr = &context->data[context->datalen];
1894 
1895  num = inode;
1896 
1897  while (num != SUBVOL_ROOT_INODE) {
1898  searchkey.obj_id = num;
1899  searchkey.obj_type = TYPE_INODE_EXTREF;
1900  searchkey.offset = 0xffffffffffffffff;
1901 
1902  Status = find_item(context->Vcb, r, &tp, &searchkey, false, NULL);
1903  if (!NT_SUCCESS(Status)) {
1904  ERR("find_item returned %08x\n", Status);
1905  return false;
1906  }
1907 
1908  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)) {
1909  ERR("could not find INODE_REF for inode %I64x\n", searchkey.obj_id);
1910  return false;
1911  }
1912 
1913  if (num != inode) {
1914  ptr--;
1915  *ptr = '/';
1916  }
1917 
1918  if (tp.item->key.obj_type == TYPE_INODE_REF) {
1919  INODE_REF* ir = (INODE_REF*)tp.item->data;
1920 
1921  RtlCopyMemory(ptr - ir->n, ir->name, ir->n);
1922  ptr -= ir->n;
1923  num = tp.item->key.offset;
1924  } else {
1925  INODE_EXTREF* ier = (INODE_EXTREF*)tp.item->data;
1926 
1927  RtlCopyMemory(ptr - ier->n, ier->name, ier->n);
1928  ptr -= ier->n;
1929  num = ier->dir;
1930  }
1931  }
1932 
1933  return true;
1934 }
uint64_t obj_id
Definition: btrfs.h:128
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
uint8_t obj_type
Definition: btrfs.h:129
uint16_t n
Definition: btrfs.h:361
Definition: http.c:7098
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:415
unsigned short int uint16_t
Definition: acefiex.h:54
uint64_t offset
Definition: btrfs.h:130
uint8_t * data
Definition: btrfs_drv.h:416
Definition: fs.h:78
#define BTRFS_SEND_TLV_CLONE_PATH
Definition: btrfs.h:567
static PVOID ptr
Definition: dispmode.c:27
char name[1]
Definition: btrfs.h:355
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
#define TYPE_INODE_REF
Definition: btrfs.h:20
uint16_t n
Definition: btrfs.h:354
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2855
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:502
#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:359
Status
Definition: gdiplustypes.h:24
char name[1]
Definition: btrfs.h:362
#define ERR(fmt,...)
Definition: debug.h:109
Definition: btrfs.h:127
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:131

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 585 of file send.c.

585  {
587 
589 
590  if (len > 0)
591  find_path((char*)&context->data[context->datalen - len], parent, name, namelen);
592 }
Definition: http.c:7098
static __inline uint16_t find_path_len(send_dir *parent, uint16_t namelen)
Definition: send.c:559
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:570
r parent
Definition: btrfs.c:2869
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:131

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 999 of file send.c.

999  {
1000  ULONG pos = context->datalen;
1001 
1003 
1004  mode &= 07777;
1005 
1008 
1010 }
Definition: http.c:7098
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
unsigned short int uint16_t
Definition: acefiex.h:54
static void send_command(send_