ReactOS  0.4.13-dev-79-gcd489d8
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 dir, UINT64 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 cmd)
 
static void send_command_finish (send_context *context, ULONG pos)
 
static void send_add_tlv (send_context *context, UINT16 type, void *data, UINT16 length)
 
static charuint64_to_char (UINT64 num, char *buf)
 
static NTSTATUS get_orphan_name (send_context *context, UINT64 inode, UINT64 generation, char *name)
 
static void add_orphan (send_context *context, orphan *o)
 
static NTSTATUS send_read_symlink (send_context *context, UINT64 inode, char **link, UINT16 *linklen)
 
static NTSTATUS send_inode (send_context *context, traverse_ptr *tp, traverse_ptr *tp2)
 
static NTSTATUS send_add_dir (send_context *context, UINT64 inode, send_dir *parent, char *name, UINT16 namelen, BOOL dummy, LIST_ENTRY *lastentry, send_dir **psd)
 
static __inline UINT16 find_path_len (send_dir *parent, UINT16 namelen)
 
static void find_path (char *path, send_dir *parent, char *name, ULONG namelen)
 
static void send_add_tlv_path (send_context *context, UINT16 type, send_dir *parent, char *name, UINT16 namelen)
 
static NTSTATUS found_path (send_context *context, send_dir *parent, char *name, UINT16 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 uid, UINT64 gid)
 
static void send_chmod_command (send_context *context, char *path, UINT64 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 size)
 
static NTSTATUS send_unlink_command (send_context *context, send_dir *parent, UINT16 namelen, char *name)
 
static void send_rmdir_command (send_context *context, UINT16 pathlen, char *path)
 
static NTSTATUS get_dir_last_child (send_context *context, UINT64 *last_inode)
 
static NTSTATUS add_pending_rmdir (send_context *context, UINT64 last_inode)
 
static NTSTATUS look_for_collision (send_context *context, send_dir *sd, char *name, ULONG namelen, UINT64 *inode, BOOL *dir)
 
static NTSTATUS make_file_orphan (send_context *context, UINT64 inode, BOOL dir, UINT64 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 size)
 
static NTSTATUS divide_ext (send_ext *ext, UINT64 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 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.

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

◆ add_ext_holes()

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

Definition at line 1651 of file send.c.

1651  {
1652  UINT64 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
UINT64 num_bytes
Definition: btrfs.h:344
EXTENT_DATA2 * ed2
Definition: write.c:2827
UINT64 size
Definition: btrfs.h:342
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:86
#define EXTENT_TYPE_INLINE
Definition: btrfs.h:67
UINT64 address
Definition: btrfs.h:341
#define offsetof(TYPE, MEMBER)
char ext[3]
Definition: mkdosfs.c:358
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
UINT64 offset
Definition: btrfs.h:343
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
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:68
static const struct encodedExtensions exts[]
Definition: encode.c:2703
#define ERR(fmt,...)
Definition: debug.h:109
Definition: list.h:27
EXTENT_DATA data
Definition: send.c:64
unsigned long long UINT64
return STATUS_SUCCESS
Definition: btrfs.c:2725
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:6587
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 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  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:6587
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:86
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
UINT64 last_child_inode
Definition: send.c:56
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
Definition: typedefs.h:117
#define ERR(fmt,...)
Definition: debug.h:109
Definition: list.h:27
return STATUS_SUCCESS
Definition: btrfs.c:2725

Referenced by flush_refs().

◆ divide_ext()

static NTSTATUS divide_ext ( send_ext ext,
UINT64  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
UINT64 num_bytes
Definition: btrfs.h:344
UINT64 size
Definition: btrfs.h:342
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
#define ALLOC_TAG
Definition: btrfs_drv.h:86
#define EXTENT_TYPE_INLINE
Definition: btrfs.h:67
UINT64 address
Definition: btrfs.h:341
double __cdecl trunc(double)
#define offsetof(TYPE, MEMBER)
char ext[3]
Definition: mkdosfs.c:358
UINT64 offset
Definition: btrfs.h:343
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
#define ERR(fmt,...)
Definition: debug.h:109
unsigned int ULONG
Definition: retypes.h:1
EXTENT_DATA data
Definition: send.c:64
return STATUS_SUCCESS
Definition: btrfs.c:2725

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:2659
GLenum GLsizei len
Definition: glext.h:6722
Definition: services.c:325
Definition: name.c:36
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 find_path_len ( send_dir parent,
UINT16  namelen 
)
static

Definition at line 559 of file send.c.

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

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  dir,
UINT64  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("(%llx,%x,%llx) 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 
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 }
#define TRUE
Definition: types.h:120
UINT64 offset
Definition: btrfs.h:125
Definition: http.c:6587
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define SUBVOL_ROOT_INODE
Definition: propsheet.cpp:42
static NTSTATUS find_send_dir(send_context *context, UINT64 dir, UINT64 generation, send_dir **psd, BOOL *added_dummy)
Definition: send.c:669
LONG NTSTATUS
Definition: precomp.h:26
UINT64 obj_id
Definition: btrfs.h:123
_In_ UINT64 _In_ UINT64 _In_ UINT64 _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2645
UINT16 size
Definition: btrfs_drv.h:389
UINT8 obj_type
Definition: btrfs.h:124
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
char name[1]
Definition: btrfs.h:350
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
#define TYPE_INODE_REF
Definition: btrfs.h:19
static NTSTATUS get_orphan_name(send_context *context, UINT64 inode, UINT64 generation, char *name)
Definition: send.c:163
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
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:2659
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:468
Definition: typedefs.h:117
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
Definition: btrfs.h:122
_In_ UINT64 _In_ UINT64 _In_ UINT64 generation
Definition: btrfs.c:2644
unsigned short UINT16
Definition: list.h:27
static NTSTATUS send_add_dir(send_context *context, UINT64 inode, send_dir *parent, char *name, UINT16 namelen, BOOL dummy, LIST_ENTRY *lastentry, send_dir **psd)
Definition: send.c:496
UINT64 inode
Definition: send.c:22
Definition: name.c:36
UINT16 n
Definition: btrfs.h:349
return STATUS_SUCCESS
Definition: btrfs.c:2725
UINT8 * data
Definition: btrfs_drv.h:390

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:6587
char * name
Definition: send.c:29
send_dir * sd
Definition: send.c:55
LONG NTSTATUS
Definition: precomp.h:26
HDC dc
Definition: cylfrac.c:34
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
UINT16 namelen
Definition: send.c:28
static void send_chown_command(send_context *context, char *path, UINT64 uid, UINT64 gid)
Definition: send.c:987
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
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
static void send_truncate_command(send_context *context, char *path, UINT64 size)
Definition: send.c:1025
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_chmod_command(send_context *context, char *path, UINT64 mode)
Definition: send.c:999
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
UINT64 last_child_inode
Definition: send.c:56
Definition: typedefs.h:117
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
Definition: list.h:27
static void send_rmdir_command(send_context *context, UINT16 pathlen, char *path)
Definition: send.c:1052
#define __S_IFLNK
Definition: btrfs_drv.h:1697
return STATUS_SUCCESS
Definition: btrfs.c:2725
#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)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)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)) {
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);
2212 
2213  Status = lzo_decompress(se->data.data + sizeof(UINT32), inlen, &context->data[context->datalen - se->data.decoded_size], (UINT32)se->data.decoded_size, sizeof(UINT32));
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)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 off, offset;
2255 
2256  for (off = ed2->offset; off < ed2->offset + ed2->num_bytes; off += MAX_SEND_WRITE) {
2257  UINT16 length = (UINT16)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)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 off, offset;
2291  UINT8* 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 addr = ed2->address + off;
2305  UINT32* 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 len;
2332 
2333  len = (UINT32)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)sector_align(length + skip_start, context->Vcb->superblock.sector_size),
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)strlen(context->lastinode.path) : 0);
2374 
2375  offset = se->offset + off;
2377 
2378  length = (UINT16)min(context->lastinode.size - se->offset - off, length);
2380 
2382  }
2383 
2384  ExFreePool(buf);
2385  } else {
2386  UINT8 *buf, *compbuf;
2387  UINT64 off;
2388  UINT32* 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 len;
2411 
2412  len = (UINT32)(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 
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)], (UINT32)ed2->size, buf, (UINT32)se->data.decoded_size, sizeof(UINT32));
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 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)strlen(context->lastinode.path) : 0);
2511 
2512  offset = se->offset + off;
2514 
2515  length = (UINT16)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:558
Definition: send.c:60
UINT64 offset
Definition: send.c:61
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
NTSTATUS lzo_decompress(UINT8 *inbuf, UINT32 inlen, UINT8 *outbuf, UINT32 outlen, UINT32 inpageoff)
Definition: compress.c:278
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:225
#define BTRFS_COMPRESSION_NONE
Definition: btrfs.h:58
#define BTRFS_SEND_TLV_DATA
Definition: btrfs.h:559
UINT64 num_bytes
Definition: btrfs.h:344
Definition: http.c:6587
EXTENT_DATA2 * ed2
Definition: write.c:2827
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
UINT64 size
Definition: btrfs.h:342
LONG NTSTATUS
Definition: precomp.h:26
GLintptr offset
Definition: glext.h:5920
UINT32 * csum
Definition: write.c:2829
static NTSTATUS sync_ext_cutoff_points(send_context *context)
Definition: send.c:1784
#define BTRFS_COMPRESSION_LZO
Definition: btrfs.h:60
#define BTRFS_COMPRESSION_ZSTD
Definition: btrfs.h:61
ULONG datalen
Definition: send.c:63
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
UINT8 data[1]
Definition: btrfs.h:337
#define BTRFS_COMPRESSION_ZLIB
Definition: btrfs.h:59
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
#define ALLOC_TAG
Definition: btrfs_drv.h:86
UINT64 decoded_size
Definition: btrfs.h:332
#define EXTENT_TYPE_INLINE
Definition: btrfs.h:67
static BOOL read_data(request_t *request, void *buffer, DWORD size, DWORD *read, BOOL async)
Definition: request.c:2012
unsigned int UINT32
UINT64 address
Definition: btrfs.h:341
UINT8 type
Definition: btrfs.h:336
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
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
UINT64 offset
Definition: btrfs.h:343
if(!(yy_init))
Definition: macro.lex.yy.c:714
static void send_add_tlv(send_context *context, UINT16 type, void *data, UINT16 length)
Definition: send.c:131
#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 zstd_decompress(UINT8 *inbuf, UINT32 inlen, UINT8 *outbuf, UINT32 outlen)
Definition: compress.c:1133
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:532
#define BTRFS_SEND_TLV_PATH
Definition: btrfs.h:555
static void send_command(send_context *context, UINT16 cmd)
Definition: send.c:115
GLenum const GLvoid * addr
Definition: glext.h:9621
GLenum GLsizei len
Definition: glext.h:6722
UINT8 compression
Definition: btrfs.h:333
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:68
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
NTSTATUS load_csum(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, UINT32 *csum, UINT64 start, UINT64 length, PIRP Irp)
Definition: create.c:382
unsigned short UINT16
#define min(a, b)
Definition: monoChain.cc:55
Definition: list.h:27
Definition: fs.h:216
static NTSTATUS add_ext_holes(device_extension *Vcb, LIST_ENTRY *exts, UINT64 size)
Definition: send.c:1651
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
EXTENT_DATA data
Definition: send.c:64
unsigned long long UINT64
static BOOL try_clone(send_context *context, send_ext *se)
Definition: send.c:2027
return STATUS_SUCCESS
Definition: btrfs.c:2725
unsigned char UINT8
static uint64_t __inline sector_align(uint64_t n, uint64_t a)
NTSTATUS zlib_decompress(UINT8 *inbuf, UINT32 inlen, UINT8 *outbuf, UINT32 outlen)
Definition: compress.c:336
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
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 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)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 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)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)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)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 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 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
char * name
Definition: wpp.c:36
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LIST_ENTRY deleted_children
Definition: send.c:30
UINT16 namelen
Definition: send.c:50
#define BTRFS_SEND_TLV_PATH_TO
Definition: btrfs.h:556
Definition: http.c:6587
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
r lastinode
Definition: btrfs.c:2672
static NTSTATUS find_send_dir(send_context *context, UINT64 dir, UINT64 generation, send_dir **psd, BOOL *added_dummy)
Definition: send.c:669
LONG NTSTATUS
Definition: precomp.h:26
HDC dc
Definition: cylfrac.c:34
static void send_utimes_command(send_context *context, char *path, BTRFS_TIME *atime, BTRFS_TIME *mtime, BTRFS_TIME *ctime)
Definition: send.c:1012
UINT16 namelen
Definition: send.c:28
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
Definition: fs.h:78
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
#define ALLOC_TAG
Definition: btrfs_drv.h:86
static NTSTATUS get_dir_last_child(send_context *context, UINT64 *last_inode)
Definition: send.c:1060
unsigned int BOOL
Definition: ntddk_ex.h:94
char name[1]
Definition: send.c:51
BOOL dummy
Definition: send.c:23
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
static NTSTATUS get_orphan_name(send_context *context, UINT64 inode, UINT64 generation, char *name)
Definition: send.c:163
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 make_file_orphan(send_context *context, UINT64 inode, BOOL dir, UINT64 generation, ref *r)
Definition: send.c:1174
static void send_add_tlv(send_context *context, UINT16 type, void *data, UINT16 length)
Definition: send.c:131
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static void send_add_tlv_path(send_context *context, UINT16 type, send_dir *parent, char *name, UINT16 namelen)
Definition: send.c:585
BTRFS_TIME atime
Definition: send.c:24
static NTSTATUS found_path(send_context *context, send_dir *parent, char *name, UINT16 namelen)
Definition: send.c:594
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define BTRFS_SEND_TLV_PATH
Definition: btrfs.h:555
static void send_command(send_context *context, UINT16 cmd)
Definition: send.c:115
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:526
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
static NTSTATUS look_for_collision(send_context *context, send_dir *sd, char *name, ULONG namelen, UINT64 *inode, BOOL *dir)
Definition: send.c:1132
static NTSTATUS send_unlink_command(send_context *context, send_dir *parent, UINT16 namelen, char *name)
Definition: send.c:1036
unsigned short UINT16
Definition: list.h:27
static void send_rmdir_command(send_context *context, UINT16 pathlen, char *path)
Definition: send.c:1052
#define __S_IFDIR
Definition: btrfs_drv.h:1692
Definition: name.c:36
static void send_command_finish(send_context *context, ULONG pos)
Definition: send.c:124
unsigned int ULONG
Definition: retypes.h:1
send_dir * sd
Definition: send.c:49
unsigned long long UINT64
return STATUS_SUCCESS
Definition: btrfs.c:2725
static NTSTATUS add_pending_rmdir(send_context *context, UINT64 last_inode)
Definition: send.c:1102
static __inline UINT16 find_path_len(send_dir *parent, UINT16 namelen)
Definition: send.c:559
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#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
#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  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)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)strlen(context->lastinode.path) : 0);
611 
613  }
614 
615  if (context->lastinode.o) {
616  UINT16 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:527
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:556
Definition: http.c:6587
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
GLint namelen
Definition: glext.h:7232
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
#define ALLOC_TAG
Definition: btrfs_drv.h:86
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:557
r parent
Definition: btrfs.c:2659
static void send_add_tlv(send_context *context, UINT16 type, void *data, UINT16 length)
Definition: send.c:131
static void send_add_tlv_path(send_context *context, UINT16 type, send_dir *parent, char *name, UINT16 namelen)
Definition: send.c:585
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define BTRFS_SEND_TLV_PATH
Definition: btrfs.h:555
static void send_command(send_context *context, UINT16 cmd)
Definition: send.c:115
#define BTRFS_SEND_CMD_RENAME
Definition: btrfs.h:526
#define ERR(fmt,...)
Definition: debug.h:109
unsigned short UINT16
Definition: name.c:36
static void send_command_finish(send_context *context, ULONG pos)
Definition: send.c:124
unsigned int ULONG
Definition: retypes.h:1
return STATUS_SUCCESS
Definition: btrfs.c:2725
static __inline UINT16 find_path_len(send_dir *parent, UINT16 namelen)
Definition: send.c:559
#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 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("(%llx,%x,%llx) 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 }
#define max(a, b)
Definition: svc.c:63
#define TRUE
Definition: types.h:120
UINT64 offset
Definition: btrfs.h:125
Definition: http.c:6587
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:582
LONG NTSTATUS
Definition: precomp.h:26
UINT64 obj_id
Definition: btrfs.h:123
_In_ UINT64 _In_ UINT64 _In_ UINT64 _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2645
#define TYPE_DIR_INDEX
Definition: btrfs.h:23
UINT16 m
Definition: btrfs.h:253
UINT16 size
Definition: btrfs_drv.h:389
UINT8 obj_type
Definition: btrfs.h:124
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
KEY key
Definition: btrfs.h:251
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
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
tree_data * item
Definition: btrfs_drv.h:468
#define TYPE_INODE_ITEM
Definition: btrfs.h:18
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
Definition: btrfs.h:122
Definition: name.c:36
return STATUS_SUCCESS
Definition: btrfs.c:2725
UINT16 n
Definition: btrfs.h:254
UINT8 * data
Definition: btrfs_drv.h:390

Referenced by flush_refs().

◆ get_orphan_name()

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

Definition at line 163 of file send.c.

163  {
164  char *ptr, *ptr2;
165  UINT64 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*)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 }
#define TRUE
Definition: types.h:120
static char * uint64_to_char(UINT64 num, char *buf)
Definition: send.c:143
UINT64 offset
Definition: btrfs.h:125
Definition: http.c:6587
#define SUBVOL_ROOT_INODE
Definition: propsheet.cpp:42
#define keycmp(key1, key2)
Definition: btrfs_drv.h:995
LONG NTSTATUS
Definition: precomp.h:26
UINT64 obj_id
Definition: btrfs.h:123
_In_ UINT64 _In_ UINT64 _In_ UINT64 _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2645
static uint32_t calc_crc32c(uint32_t seed, uint8_t *msg, ULONG msglen)
Definition: recv.cpp:134
UINT8 obj_type
Definition: btrfs.h:124
Definition: fs.h:78
static PVOID ptr
Definition: dispmode.c:27
smooth NULL
Definition: ftsmooth.c:416
GLuint index
Definition: glext.h:6031
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
tree_data * item
Definition: btrfs_drv.h:468
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
Definition: btrfs.h:122
_In_ UINT64 _In_ UINT64 _In_ UINT64 generation
Definition: btrfs.c:2644
#define TYPE_DIR_ITEM
Definition: btrfs.h:22
Definition: name.c:36
unsigned int ULONG
Definition: retypes.h:1
unsigned long long UINT64
return STATUS_SUCCESS
Definition: btrfs.c:2725
unsigned char UINT8

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 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 len;
1138 
1139  searchkey.obj_id = sd->inode;
1140  searchkey.obj_type = TYPE_DIR_ITEM;
1141  searchkey.offset = calc_crc32c(0xfffffffe, (UINT8*)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("(%llx,%x,%llx) 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)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
#define TRUE
Definition: types.h:120
UINT64 offset
Definition: btrfs.h:125
Definition: http.c:6587
#define keycmp(key1, key2)
Definition: btrfs_drv.h:995
LONG NTSTATUS
Definition: precomp.h:26
UINT64 obj_id
Definition: btrfs.h:123
_In_ UINT64 _In_ UINT64 _In_ UINT64 _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2645
UINT16 m
Definition: btrfs.h:253
UINT16 size
Definition: btrfs_drv.h:389
GLint namelen
Definition: glext.h:7232
static uint32_t calc_crc32c(uint32_t seed, uint8_t *msg, ULONG msglen)
Definition: recv.cpp:134
UINT8 obj_type
Definition: btrfs.h:124
Definition: fs.h:78
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
KEY key
Definition: btrfs.h:251
char name[1]
Definition: btrfs.h:256
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:81
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
unsigned int dir
Definition: maze.c:112
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:468
UINT8 type
Definition: btrfs.h:255
#define TYPE_INODE_ITEM
Definition: btrfs.h:18
GLenum GLsizei len
Definition: glext.h:6722
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
Definition: btrfs.h:122
#define TYPE_DIR_ITEM
Definition: btrfs.h:22
unsigned short UINT16
Definition: name.c:36
return STATUS_SUCCESS
Definition: btrfs.c:2725
unsigned char UINT8
UINT16 n
Definition: btrfs.h:254
UINT8 * data
Definition: btrfs_drv.h:390
#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  inode,
BOOL  dir,
UINT64  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)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 }
char * name
Definition: wpp.c:36
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
Definition: send.c:33
#define BTRFS_SEND_TLV_PATH_TO
Definition: btrfs.h:556
Definition: http.c:6587
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
static NTSTATUS find_send_dir(send_context *context, UINT64 dir, UINT64 generation, send_dir **psd, BOOL *added_dummy)
Definition: send.c:669
LONG NTSTATUS
Definition: precomp.h:26
HDC dc
Definition: cylfrac.c:34
#define InsertTailList(ListHead, Entry)
Definition: fs.h:78
#define ALLOC_TAG
Definition: btrfs_drv.h:86
UINT64 inode
Definition: send.c:35
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
static NTSTATUS get_orphan_name(send_context *context, UINT64 inode, UINT64 generation, char *name)
Definition: send.c:163
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
static void send_add_tlv_path(send_context *context, UINT16 type, send_dir *parent, char *name, UINT16 namelen)
Definition: send.c:585
char tmpname[64]
Definition: send.c:38
Definition: send.c:20
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define BTRFS_SEND_TLV_PATH
Definition: btrfs.h:555
static const WCHAR sd[]
Definition: suminfo.c:287
static void send_command(send_context *context, UINT16 cmd)
Definition: send.c:115
send_dir * sd
Definition: send.c:37
Definition: typedefs.h:117
#define BTRFS_SEND_CMD_RENAME
Definition: btrfs.h:526
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
BOOL dir
Definition: send.c:36
_In_ UINT64 _In_ UINT64 _In_ UINT64 generation
Definition: btrfs.c:2644
unsigned short UINT16
Definition: list.h:27
Definition: name.c:36
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
#define BTRFS_SEND_CMD_UNLINK
Definition: btrfs.h:528
return STATUS_SUCCESS
Definition: btrfs.c:2725
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
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 3839 of file send.c.

3839  {
3840  ccb* ccb;
3842 
3843  ccb = FileObject ? FileObject->FsContext2 : NULL;
3844  if (!ccb)
3845  return STATUS_INVALID_PARAMETER;
3846 
3847  if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), processor_mode))
3849 
3850  ExAcquireResourceExclusiveLite(&Vcb->send_load_lock, TRUE);
3851 
3852  if (!ccb->send) {
3853  ExReleaseResourceLite(&Vcb->send_load_lock);
3855  }
3856 
3858 
3860 
3861  if (datalen == 0) {
3862  ExReleaseResourceLite(&Vcb->send_load_lock);
3863  return STATUS_SUCCESS;
3864  }
3865 
3866  RtlCopyMemory(data, context->data, min(datalen, context->datalen));
3867 
3868  if (datalen < context->datalen) { // not empty yet
3869  *retlen = datalen;
3870  RtlMoveMemory(context->data, &context->data[datalen], context->datalen - datalen);
3871  context->datalen -= datalen;
3872  ExReleaseResourceLite(&Vcb->send_load_lock);
3873  } else {
3874  *retlen = context->datalen;
3875  context->datalen = 0;
3876  ExReleaseResourceLite(&Vcb->send_load_lock);
3877 
3878  KeClearEvent(&context->buffer_event);
3880  }
3881 
3882  return STATUS_SUCCESS;
3883 }
#define STATUS_PRIVILEGE_NOT_HELD
Definition: DriverTester.h:9
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
Definition: http.c:6587
#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:62
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:368
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
KEVENT cleared_event
Definition: btrfs_drv.h:340
#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:339
#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:2725
send_info * send
Definition: btrfs_drv.h:367

Referenced by fsctl_request().

◆ send_add_dir()

static NTSTATUS send_add_dir ( send_context context,
UINT64  inode,
send_dir parent,
char name,
UINT16  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:6587
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:86
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:2659
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
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
Definition: list.h:27
UINT64 inode
Definition: send.c:22
Definition: name.c:36
return STATUS_SUCCESS
Definition: btrfs.c:2725
#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  type,
void data,
UINT16  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:6587
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
UINT16 type
Definition: btrfs.h:580
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 length
Definition: btrfs.h:581

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  inode 
)
static

Definition at line 1840 of file send.c.

1840  {
1841  NTSTATUS Status;
1842  KEY searchkey;
1843  traverse_ptr tp;
1844  UINT16 len = 0;
1845  UINT64 num;
1846  UINT8* 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 %llx\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("(%llx,%x,%llx) 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("(%llx,%x,%llx) 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 %llx\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 }
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
UINT64 offset
Definition: btrfs.h:125
Definition: http.c:6587
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
#define SUBVOL_ROOT_INODE
Definition: propsheet.cpp:42
LONG NTSTATUS
Definition: precomp.h:26
UINT64 obj_id
Definition: btrfs.h:123
_In_ UINT64 _In_ UINT64 _In_ UINT64 _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2645
UINT16 size
Definition: btrfs_drv.h:389
UINT8 obj_type
Definition: btrfs.h:124
Definition: fs.h:78
#define BTRFS_SEND_TLV_CLONE_PATH
Definition: btrfs.h:562
static PVOID ptr
Definition: dispmode.c:27
char name[1]
Definition: btrfs.h:350
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
#define TYPE_INODE_REF
Definition: btrfs.h:19
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
if(!(yy_init))
Definition: macro.lex.yy.c:714
static void send_add_tlv(send_context *context, UINT16 type, void *data, UINT16 length)
Definition: send.c:131
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
GLuint GLuint num
Definition: glext.h:9618
tree_data * item
Definition: btrfs_drv.h:468
#define TYPE_INODE_EXTREF
Definition: btrfs.h:20
GLenum GLsizei len
Definition: glext.h:6722
Status
Definition: gdiplustypes.h:24
char name[1]
Definition: btrfs.h:357
#define ERR(fmt,...)
Definition: debug.h:109
Definition: btrfs.h:122
unsigned short UINT16
UINT16 n
Definition: btrfs.h:356
Definition: name.c:36
UINT64 dir
Definition: btrfs.h:354
UINT16 n
Definition: btrfs.h:349
unsigned long long UINT64
unsigned char UINT8
UINT8 * data
Definition: btrfs_drv.h:390

Referenced by try_clone_edr().

◆ send_add_tlv_path()

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

Definition at line 585 of file send.c.

585