162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2012 Alexander Block. All rights reserved. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <linux/bsearch.h> 762306a36Sopenharmony_ci#include <linux/fs.h> 862306a36Sopenharmony_ci#include <linux/file.h> 962306a36Sopenharmony_ci#include <linux/sort.h> 1062306a36Sopenharmony_ci#include <linux/mount.h> 1162306a36Sopenharmony_ci#include <linux/xattr.h> 1262306a36Sopenharmony_ci#include <linux/posix_acl_xattr.h> 1362306a36Sopenharmony_ci#include <linux/radix-tree.h> 1462306a36Sopenharmony_ci#include <linux/vmalloc.h> 1562306a36Sopenharmony_ci#include <linux/string.h> 1662306a36Sopenharmony_ci#include <linux/compat.h> 1762306a36Sopenharmony_ci#include <linux/crc32c.h> 1862306a36Sopenharmony_ci#include <linux/fsverity.h> 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#include "send.h" 2162306a36Sopenharmony_ci#include "ctree.h" 2262306a36Sopenharmony_ci#include "backref.h" 2362306a36Sopenharmony_ci#include "locking.h" 2462306a36Sopenharmony_ci#include "disk-io.h" 2562306a36Sopenharmony_ci#include "btrfs_inode.h" 2662306a36Sopenharmony_ci#include "transaction.h" 2762306a36Sopenharmony_ci#include "compression.h" 2862306a36Sopenharmony_ci#include "xattr.h" 2962306a36Sopenharmony_ci#include "print-tree.h" 3062306a36Sopenharmony_ci#include "accessors.h" 3162306a36Sopenharmony_ci#include "dir-item.h" 3262306a36Sopenharmony_ci#include "file-item.h" 3362306a36Sopenharmony_ci#include "ioctl.h" 3462306a36Sopenharmony_ci#include "verity.h" 3562306a36Sopenharmony_ci#include "lru_cache.h" 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci/* 3862306a36Sopenharmony_ci * Maximum number of references an extent can have in order for us to attempt to 3962306a36Sopenharmony_ci * issue clone operations instead of write operations. This currently exists to 4062306a36Sopenharmony_ci * avoid hitting limitations of the backreference walking code (taking a lot of 4162306a36Sopenharmony_ci * time and using too much memory for extents with large number of references). 4262306a36Sopenharmony_ci */ 4362306a36Sopenharmony_ci#define SEND_MAX_EXTENT_REFS 1024 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci/* 4662306a36Sopenharmony_ci * A fs_path is a helper to dynamically build path names with unknown size. 4762306a36Sopenharmony_ci * It reallocates the internal buffer on demand. 4862306a36Sopenharmony_ci * It allows fast adding of path elements on the right side (normal path) and 4962306a36Sopenharmony_ci * fast adding to the left side (reversed path). A reversed path can also be 5062306a36Sopenharmony_ci * unreversed if needed. 5162306a36Sopenharmony_ci */ 5262306a36Sopenharmony_cistruct fs_path { 5362306a36Sopenharmony_ci union { 5462306a36Sopenharmony_ci struct { 5562306a36Sopenharmony_ci char *start; 5662306a36Sopenharmony_ci char *end; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci char *buf; 5962306a36Sopenharmony_ci unsigned short buf_len:15; 6062306a36Sopenharmony_ci unsigned short reversed:1; 6162306a36Sopenharmony_ci char inline_buf[]; 6262306a36Sopenharmony_ci }; 6362306a36Sopenharmony_ci /* 6462306a36Sopenharmony_ci * Average path length does not exceed 200 bytes, we'll have 6562306a36Sopenharmony_ci * better packing in the slab and higher chance to satisfy 6662306a36Sopenharmony_ci * a allocation later during send. 6762306a36Sopenharmony_ci */ 6862306a36Sopenharmony_ci char pad[256]; 6962306a36Sopenharmony_ci }; 7062306a36Sopenharmony_ci}; 7162306a36Sopenharmony_ci#define FS_PATH_INLINE_SIZE \ 7262306a36Sopenharmony_ci (sizeof(struct fs_path) - offsetof(struct fs_path, inline_buf)) 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci/* reused for each extent */ 7662306a36Sopenharmony_cistruct clone_root { 7762306a36Sopenharmony_ci struct btrfs_root *root; 7862306a36Sopenharmony_ci u64 ino; 7962306a36Sopenharmony_ci u64 offset; 8062306a36Sopenharmony_ci u64 num_bytes; 8162306a36Sopenharmony_ci bool found_ref; 8262306a36Sopenharmony_ci}; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci#define SEND_MAX_NAME_CACHE_SIZE 256 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci/* 8762306a36Sopenharmony_ci * Limit the root_ids array of struct backref_cache_entry to 17 elements. 8862306a36Sopenharmony_ci * This makes the size of a cache entry to be exactly 192 bytes on x86_64, which 8962306a36Sopenharmony_ci * can be satisfied from the kmalloc-192 slab, without wasting any space. 9062306a36Sopenharmony_ci * The most common case is to have a single root for cloning, which corresponds 9162306a36Sopenharmony_ci * to the send root. Having the user specify more than 16 clone roots is not 9262306a36Sopenharmony_ci * common, and in such rare cases we simply don't use caching if the number of 9362306a36Sopenharmony_ci * cloning roots that lead down to a leaf is more than 17. 9462306a36Sopenharmony_ci */ 9562306a36Sopenharmony_ci#define SEND_MAX_BACKREF_CACHE_ROOTS 17 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci/* 9862306a36Sopenharmony_ci * Max number of entries in the cache. 9962306a36Sopenharmony_ci * With SEND_MAX_BACKREF_CACHE_ROOTS as 17, the size in bytes, excluding 10062306a36Sopenharmony_ci * maple tree's internal nodes, is 24K. 10162306a36Sopenharmony_ci */ 10262306a36Sopenharmony_ci#define SEND_MAX_BACKREF_CACHE_SIZE 128 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci/* 10562306a36Sopenharmony_ci * A backref cache entry maps a leaf to a list of IDs of roots from which the 10662306a36Sopenharmony_ci * leaf is accessible and we can use for clone operations. 10762306a36Sopenharmony_ci * With SEND_MAX_BACKREF_CACHE_ROOTS as 12, each cache entry is 128 bytes (on 10862306a36Sopenharmony_ci * x86_64). 10962306a36Sopenharmony_ci */ 11062306a36Sopenharmony_cistruct backref_cache_entry { 11162306a36Sopenharmony_ci struct btrfs_lru_cache_entry entry; 11262306a36Sopenharmony_ci u64 root_ids[SEND_MAX_BACKREF_CACHE_ROOTS]; 11362306a36Sopenharmony_ci /* Number of valid elements in the root_ids array. */ 11462306a36Sopenharmony_ci int num_roots; 11562306a36Sopenharmony_ci}; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci/* See the comment at lru_cache.h about struct btrfs_lru_cache_entry. */ 11862306a36Sopenharmony_cistatic_assert(offsetof(struct backref_cache_entry, entry) == 0); 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci/* 12162306a36Sopenharmony_ci * Max number of entries in the cache that stores directories that were already 12262306a36Sopenharmony_ci * created. The cache uses raw struct btrfs_lru_cache_entry entries, so it uses 12362306a36Sopenharmony_ci * at most 4096 bytes - sizeof(struct btrfs_lru_cache_entry) is 48 bytes, but 12462306a36Sopenharmony_ci * the kmalloc-64 slab is used, so we get 4096 bytes (64 bytes * 64). 12562306a36Sopenharmony_ci */ 12662306a36Sopenharmony_ci#define SEND_MAX_DIR_CREATED_CACHE_SIZE 64 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci/* 12962306a36Sopenharmony_ci * Max number of entries in the cache that stores directories that were already 13062306a36Sopenharmony_ci * created. The cache uses raw struct btrfs_lru_cache_entry entries, so it uses 13162306a36Sopenharmony_ci * at most 4096 bytes - sizeof(struct btrfs_lru_cache_entry) is 48 bytes, but 13262306a36Sopenharmony_ci * the kmalloc-64 slab is used, so we get 4096 bytes (64 bytes * 64). 13362306a36Sopenharmony_ci */ 13462306a36Sopenharmony_ci#define SEND_MAX_DIR_UTIMES_CACHE_SIZE 64 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_cistruct send_ctx { 13762306a36Sopenharmony_ci struct file *send_filp; 13862306a36Sopenharmony_ci loff_t send_off; 13962306a36Sopenharmony_ci char *send_buf; 14062306a36Sopenharmony_ci u32 send_size; 14162306a36Sopenharmony_ci u32 send_max_size; 14262306a36Sopenharmony_ci /* 14362306a36Sopenharmony_ci * Whether BTRFS_SEND_A_DATA attribute was already added to current 14462306a36Sopenharmony_ci * command (since protocol v2, data must be the last attribute). 14562306a36Sopenharmony_ci */ 14662306a36Sopenharmony_ci bool put_data; 14762306a36Sopenharmony_ci struct page **send_buf_pages; 14862306a36Sopenharmony_ci u64 flags; /* 'flags' member of btrfs_ioctl_send_args is u64 */ 14962306a36Sopenharmony_ci /* Protocol version compatibility requested */ 15062306a36Sopenharmony_ci u32 proto; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci struct btrfs_root *send_root; 15362306a36Sopenharmony_ci struct btrfs_root *parent_root; 15462306a36Sopenharmony_ci struct clone_root *clone_roots; 15562306a36Sopenharmony_ci int clone_roots_cnt; 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci /* current state of the compare_tree call */ 15862306a36Sopenharmony_ci struct btrfs_path *left_path; 15962306a36Sopenharmony_ci struct btrfs_path *right_path; 16062306a36Sopenharmony_ci struct btrfs_key *cmp_key; 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci /* 16362306a36Sopenharmony_ci * Keep track of the generation of the last transaction that was used 16462306a36Sopenharmony_ci * for relocating a block group. This is periodically checked in order 16562306a36Sopenharmony_ci * to detect if a relocation happened since the last check, so that we 16662306a36Sopenharmony_ci * don't operate on stale extent buffers for nodes (level >= 1) or on 16762306a36Sopenharmony_ci * stale disk_bytenr values of file extent items. 16862306a36Sopenharmony_ci */ 16962306a36Sopenharmony_ci u64 last_reloc_trans; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci /* 17262306a36Sopenharmony_ci * infos of the currently processed inode. In case of deleted inodes, 17362306a36Sopenharmony_ci * these are the values from the deleted inode. 17462306a36Sopenharmony_ci */ 17562306a36Sopenharmony_ci u64 cur_ino; 17662306a36Sopenharmony_ci u64 cur_inode_gen; 17762306a36Sopenharmony_ci u64 cur_inode_size; 17862306a36Sopenharmony_ci u64 cur_inode_mode; 17962306a36Sopenharmony_ci u64 cur_inode_rdev; 18062306a36Sopenharmony_ci u64 cur_inode_last_extent; 18162306a36Sopenharmony_ci u64 cur_inode_next_write_offset; 18262306a36Sopenharmony_ci bool cur_inode_new; 18362306a36Sopenharmony_ci bool cur_inode_new_gen; 18462306a36Sopenharmony_ci bool cur_inode_deleted; 18562306a36Sopenharmony_ci bool ignore_cur_inode; 18662306a36Sopenharmony_ci bool cur_inode_needs_verity; 18762306a36Sopenharmony_ci void *verity_descriptor; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci u64 send_progress; 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci struct list_head new_refs; 19262306a36Sopenharmony_ci struct list_head deleted_refs; 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci struct btrfs_lru_cache name_cache; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci /* 19762306a36Sopenharmony_ci * The inode we are currently processing. It's not NULL only when we 19862306a36Sopenharmony_ci * need to issue write commands for data extents from this inode. 19962306a36Sopenharmony_ci */ 20062306a36Sopenharmony_ci struct inode *cur_inode; 20162306a36Sopenharmony_ci struct file_ra_state ra; 20262306a36Sopenharmony_ci u64 page_cache_clear_start; 20362306a36Sopenharmony_ci bool clean_page_cache; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci /* 20662306a36Sopenharmony_ci * We process inodes by their increasing order, so if before an 20762306a36Sopenharmony_ci * incremental send we reverse the parent/child relationship of 20862306a36Sopenharmony_ci * directories such that a directory with a lower inode number was 20962306a36Sopenharmony_ci * the parent of a directory with a higher inode number, and the one 21062306a36Sopenharmony_ci * becoming the new parent got renamed too, we can't rename/move the 21162306a36Sopenharmony_ci * directory with lower inode number when we finish processing it - we 21262306a36Sopenharmony_ci * must process the directory with higher inode number first, then 21362306a36Sopenharmony_ci * rename/move it and then rename/move the directory with lower inode 21462306a36Sopenharmony_ci * number. Example follows. 21562306a36Sopenharmony_ci * 21662306a36Sopenharmony_ci * Tree state when the first send was performed: 21762306a36Sopenharmony_ci * 21862306a36Sopenharmony_ci * . 21962306a36Sopenharmony_ci * |-- a (ino 257) 22062306a36Sopenharmony_ci * |-- b (ino 258) 22162306a36Sopenharmony_ci * | 22262306a36Sopenharmony_ci * | 22362306a36Sopenharmony_ci * |-- c (ino 259) 22462306a36Sopenharmony_ci * | |-- d (ino 260) 22562306a36Sopenharmony_ci * | 22662306a36Sopenharmony_ci * |-- c2 (ino 261) 22762306a36Sopenharmony_ci * 22862306a36Sopenharmony_ci * Tree state when the second (incremental) send is performed: 22962306a36Sopenharmony_ci * 23062306a36Sopenharmony_ci * . 23162306a36Sopenharmony_ci * |-- a (ino 257) 23262306a36Sopenharmony_ci * |-- b (ino 258) 23362306a36Sopenharmony_ci * |-- c2 (ino 261) 23462306a36Sopenharmony_ci * |-- d2 (ino 260) 23562306a36Sopenharmony_ci * |-- cc (ino 259) 23662306a36Sopenharmony_ci * 23762306a36Sopenharmony_ci * The sequence of steps that lead to the second state was: 23862306a36Sopenharmony_ci * 23962306a36Sopenharmony_ci * mv /a/b/c/d /a/b/c2/d2 24062306a36Sopenharmony_ci * mv /a/b/c /a/b/c2/d2/cc 24162306a36Sopenharmony_ci * 24262306a36Sopenharmony_ci * "c" has lower inode number, but we can't move it (2nd mv operation) 24362306a36Sopenharmony_ci * before we move "d", which has higher inode number. 24462306a36Sopenharmony_ci * 24562306a36Sopenharmony_ci * So we just memorize which move/rename operations must be performed 24662306a36Sopenharmony_ci * later when their respective parent is processed and moved/renamed. 24762306a36Sopenharmony_ci */ 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci /* Indexed by parent directory inode number. */ 25062306a36Sopenharmony_ci struct rb_root pending_dir_moves; 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci /* 25362306a36Sopenharmony_ci * Reverse index, indexed by the inode number of a directory that 25462306a36Sopenharmony_ci * is waiting for the move/rename of its immediate parent before its 25562306a36Sopenharmony_ci * own move/rename can be performed. 25662306a36Sopenharmony_ci */ 25762306a36Sopenharmony_ci struct rb_root waiting_dir_moves; 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci /* 26062306a36Sopenharmony_ci * A directory that is going to be rm'ed might have a child directory 26162306a36Sopenharmony_ci * which is in the pending directory moves index above. In this case, 26262306a36Sopenharmony_ci * the directory can only be removed after the move/rename of its child 26362306a36Sopenharmony_ci * is performed. Example: 26462306a36Sopenharmony_ci * 26562306a36Sopenharmony_ci * Parent snapshot: 26662306a36Sopenharmony_ci * 26762306a36Sopenharmony_ci * . (ino 256) 26862306a36Sopenharmony_ci * |-- a/ (ino 257) 26962306a36Sopenharmony_ci * |-- b/ (ino 258) 27062306a36Sopenharmony_ci * |-- c/ (ino 259) 27162306a36Sopenharmony_ci * | |-- x/ (ino 260) 27262306a36Sopenharmony_ci * | 27362306a36Sopenharmony_ci * |-- y/ (ino 261) 27462306a36Sopenharmony_ci * 27562306a36Sopenharmony_ci * Send snapshot: 27662306a36Sopenharmony_ci * 27762306a36Sopenharmony_ci * . (ino 256) 27862306a36Sopenharmony_ci * |-- a/ (ino 257) 27962306a36Sopenharmony_ci * |-- b/ (ino 258) 28062306a36Sopenharmony_ci * |-- YY/ (ino 261) 28162306a36Sopenharmony_ci * |-- x/ (ino 260) 28262306a36Sopenharmony_ci * 28362306a36Sopenharmony_ci * Sequence of steps that lead to the send snapshot: 28462306a36Sopenharmony_ci * rm -f /a/b/c/foo.txt 28562306a36Sopenharmony_ci * mv /a/b/y /a/b/YY 28662306a36Sopenharmony_ci * mv /a/b/c/x /a/b/YY 28762306a36Sopenharmony_ci * rmdir /a/b/c 28862306a36Sopenharmony_ci * 28962306a36Sopenharmony_ci * When the child is processed, its move/rename is delayed until its 29062306a36Sopenharmony_ci * parent is processed (as explained above), but all other operations 29162306a36Sopenharmony_ci * like update utimes, chown, chgrp, etc, are performed and the paths 29262306a36Sopenharmony_ci * that it uses for those operations must use the orphanized name of 29362306a36Sopenharmony_ci * its parent (the directory we're going to rm later), so we need to 29462306a36Sopenharmony_ci * memorize that name. 29562306a36Sopenharmony_ci * 29662306a36Sopenharmony_ci * Indexed by the inode number of the directory to be deleted. 29762306a36Sopenharmony_ci */ 29862306a36Sopenharmony_ci struct rb_root orphan_dirs; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci struct rb_root rbtree_new_refs; 30162306a36Sopenharmony_ci struct rb_root rbtree_deleted_refs; 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci struct btrfs_lru_cache backref_cache; 30462306a36Sopenharmony_ci u64 backref_cache_last_reloc_trans; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci struct btrfs_lru_cache dir_created_cache; 30762306a36Sopenharmony_ci struct btrfs_lru_cache dir_utimes_cache; 30862306a36Sopenharmony_ci}; 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_cistruct pending_dir_move { 31162306a36Sopenharmony_ci struct rb_node node; 31262306a36Sopenharmony_ci struct list_head list; 31362306a36Sopenharmony_ci u64 parent_ino; 31462306a36Sopenharmony_ci u64 ino; 31562306a36Sopenharmony_ci u64 gen; 31662306a36Sopenharmony_ci struct list_head update_refs; 31762306a36Sopenharmony_ci}; 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_cistruct waiting_dir_move { 32062306a36Sopenharmony_ci struct rb_node node; 32162306a36Sopenharmony_ci u64 ino; 32262306a36Sopenharmony_ci /* 32362306a36Sopenharmony_ci * There might be some directory that could not be removed because it 32462306a36Sopenharmony_ci * was waiting for this directory inode to be moved first. Therefore 32562306a36Sopenharmony_ci * after this directory is moved, we can try to rmdir the ino rmdir_ino. 32662306a36Sopenharmony_ci */ 32762306a36Sopenharmony_ci u64 rmdir_ino; 32862306a36Sopenharmony_ci u64 rmdir_gen; 32962306a36Sopenharmony_ci bool orphanized; 33062306a36Sopenharmony_ci}; 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_cistruct orphan_dir_info { 33362306a36Sopenharmony_ci struct rb_node node; 33462306a36Sopenharmony_ci u64 ino; 33562306a36Sopenharmony_ci u64 gen; 33662306a36Sopenharmony_ci u64 last_dir_index_offset; 33762306a36Sopenharmony_ci u64 dir_high_seq_ino; 33862306a36Sopenharmony_ci}; 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_cistruct name_cache_entry { 34162306a36Sopenharmony_ci /* 34262306a36Sopenharmony_ci * The key in the entry is an inode number, and the generation matches 34362306a36Sopenharmony_ci * the inode's generation. 34462306a36Sopenharmony_ci */ 34562306a36Sopenharmony_ci struct btrfs_lru_cache_entry entry; 34662306a36Sopenharmony_ci u64 parent_ino; 34762306a36Sopenharmony_ci u64 parent_gen; 34862306a36Sopenharmony_ci int ret; 34962306a36Sopenharmony_ci int need_later_update; 35062306a36Sopenharmony_ci int name_len; 35162306a36Sopenharmony_ci char name[]; 35262306a36Sopenharmony_ci}; 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci/* See the comment at lru_cache.h about struct btrfs_lru_cache_entry. */ 35562306a36Sopenharmony_cistatic_assert(offsetof(struct name_cache_entry, entry) == 0); 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci#define ADVANCE 1 35862306a36Sopenharmony_ci#define ADVANCE_ONLY_NEXT -1 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_cienum btrfs_compare_tree_result { 36162306a36Sopenharmony_ci BTRFS_COMPARE_TREE_NEW, 36262306a36Sopenharmony_ci BTRFS_COMPARE_TREE_DELETED, 36362306a36Sopenharmony_ci BTRFS_COMPARE_TREE_CHANGED, 36462306a36Sopenharmony_ci BTRFS_COMPARE_TREE_SAME, 36562306a36Sopenharmony_ci}; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci__cold 36862306a36Sopenharmony_cistatic void inconsistent_snapshot_error(struct send_ctx *sctx, 36962306a36Sopenharmony_ci enum btrfs_compare_tree_result result, 37062306a36Sopenharmony_ci const char *what) 37162306a36Sopenharmony_ci{ 37262306a36Sopenharmony_ci const char *result_string; 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci switch (result) { 37562306a36Sopenharmony_ci case BTRFS_COMPARE_TREE_NEW: 37662306a36Sopenharmony_ci result_string = "new"; 37762306a36Sopenharmony_ci break; 37862306a36Sopenharmony_ci case BTRFS_COMPARE_TREE_DELETED: 37962306a36Sopenharmony_ci result_string = "deleted"; 38062306a36Sopenharmony_ci break; 38162306a36Sopenharmony_ci case BTRFS_COMPARE_TREE_CHANGED: 38262306a36Sopenharmony_ci result_string = "updated"; 38362306a36Sopenharmony_ci break; 38462306a36Sopenharmony_ci case BTRFS_COMPARE_TREE_SAME: 38562306a36Sopenharmony_ci ASSERT(0); 38662306a36Sopenharmony_ci result_string = "unchanged"; 38762306a36Sopenharmony_ci break; 38862306a36Sopenharmony_ci default: 38962306a36Sopenharmony_ci ASSERT(0); 39062306a36Sopenharmony_ci result_string = "unexpected"; 39162306a36Sopenharmony_ci } 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci btrfs_err(sctx->send_root->fs_info, 39462306a36Sopenharmony_ci "Send: inconsistent snapshot, found %s %s for inode %llu without updated inode item, send root is %llu, parent root is %llu", 39562306a36Sopenharmony_ci result_string, what, sctx->cmp_key->objectid, 39662306a36Sopenharmony_ci sctx->send_root->root_key.objectid, 39762306a36Sopenharmony_ci (sctx->parent_root ? 39862306a36Sopenharmony_ci sctx->parent_root->root_key.objectid : 0)); 39962306a36Sopenharmony_ci} 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci__maybe_unused 40262306a36Sopenharmony_cistatic bool proto_cmd_ok(const struct send_ctx *sctx, int cmd) 40362306a36Sopenharmony_ci{ 40462306a36Sopenharmony_ci switch (sctx->proto) { 40562306a36Sopenharmony_ci case 1: return cmd <= BTRFS_SEND_C_MAX_V1; 40662306a36Sopenharmony_ci case 2: return cmd <= BTRFS_SEND_C_MAX_V2; 40762306a36Sopenharmony_ci case 3: return cmd <= BTRFS_SEND_C_MAX_V3; 40862306a36Sopenharmony_ci default: return false; 40962306a36Sopenharmony_ci } 41062306a36Sopenharmony_ci} 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_cistatic int is_waiting_for_move(struct send_ctx *sctx, u64 ino); 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_cistatic struct waiting_dir_move * 41562306a36Sopenharmony_ciget_waiting_dir_move(struct send_ctx *sctx, u64 ino); 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_cistatic int is_waiting_for_rm(struct send_ctx *sctx, u64 dir_ino, u64 gen); 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_cistatic int need_send_hole(struct send_ctx *sctx) 42062306a36Sopenharmony_ci{ 42162306a36Sopenharmony_ci return (sctx->parent_root && !sctx->cur_inode_new && 42262306a36Sopenharmony_ci !sctx->cur_inode_new_gen && !sctx->cur_inode_deleted && 42362306a36Sopenharmony_ci S_ISREG(sctx->cur_inode_mode)); 42462306a36Sopenharmony_ci} 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_cistatic void fs_path_reset(struct fs_path *p) 42762306a36Sopenharmony_ci{ 42862306a36Sopenharmony_ci if (p->reversed) { 42962306a36Sopenharmony_ci p->start = p->buf + p->buf_len - 1; 43062306a36Sopenharmony_ci p->end = p->start; 43162306a36Sopenharmony_ci *p->start = 0; 43262306a36Sopenharmony_ci } else { 43362306a36Sopenharmony_ci p->start = p->buf; 43462306a36Sopenharmony_ci p->end = p->start; 43562306a36Sopenharmony_ci *p->start = 0; 43662306a36Sopenharmony_ci } 43762306a36Sopenharmony_ci} 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_cistatic struct fs_path *fs_path_alloc(void) 44062306a36Sopenharmony_ci{ 44162306a36Sopenharmony_ci struct fs_path *p; 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci p = kmalloc(sizeof(*p), GFP_KERNEL); 44462306a36Sopenharmony_ci if (!p) 44562306a36Sopenharmony_ci return NULL; 44662306a36Sopenharmony_ci p->reversed = 0; 44762306a36Sopenharmony_ci p->buf = p->inline_buf; 44862306a36Sopenharmony_ci p->buf_len = FS_PATH_INLINE_SIZE; 44962306a36Sopenharmony_ci fs_path_reset(p); 45062306a36Sopenharmony_ci return p; 45162306a36Sopenharmony_ci} 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_cistatic struct fs_path *fs_path_alloc_reversed(void) 45462306a36Sopenharmony_ci{ 45562306a36Sopenharmony_ci struct fs_path *p; 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci p = fs_path_alloc(); 45862306a36Sopenharmony_ci if (!p) 45962306a36Sopenharmony_ci return NULL; 46062306a36Sopenharmony_ci p->reversed = 1; 46162306a36Sopenharmony_ci fs_path_reset(p); 46262306a36Sopenharmony_ci return p; 46362306a36Sopenharmony_ci} 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_cistatic void fs_path_free(struct fs_path *p) 46662306a36Sopenharmony_ci{ 46762306a36Sopenharmony_ci if (!p) 46862306a36Sopenharmony_ci return; 46962306a36Sopenharmony_ci if (p->buf != p->inline_buf) 47062306a36Sopenharmony_ci kfree(p->buf); 47162306a36Sopenharmony_ci kfree(p); 47262306a36Sopenharmony_ci} 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_cistatic int fs_path_len(struct fs_path *p) 47562306a36Sopenharmony_ci{ 47662306a36Sopenharmony_ci return p->end - p->start; 47762306a36Sopenharmony_ci} 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_cistatic int fs_path_ensure_buf(struct fs_path *p, int len) 48062306a36Sopenharmony_ci{ 48162306a36Sopenharmony_ci char *tmp_buf; 48262306a36Sopenharmony_ci int path_len; 48362306a36Sopenharmony_ci int old_buf_len; 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci len++; 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci if (p->buf_len >= len) 48862306a36Sopenharmony_ci return 0; 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci if (len > PATH_MAX) { 49162306a36Sopenharmony_ci WARN_ON(1); 49262306a36Sopenharmony_ci return -ENOMEM; 49362306a36Sopenharmony_ci } 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci path_len = p->end - p->start; 49662306a36Sopenharmony_ci old_buf_len = p->buf_len; 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci /* 49962306a36Sopenharmony_ci * Allocate to the next largest kmalloc bucket size, to let 50062306a36Sopenharmony_ci * the fast path happen most of the time. 50162306a36Sopenharmony_ci */ 50262306a36Sopenharmony_ci len = kmalloc_size_roundup(len); 50362306a36Sopenharmony_ci /* 50462306a36Sopenharmony_ci * First time the inline_buf does not suffice 50562306a36Sopenharmony_ci */ 50662306a36Sopenharmony_ci if (p->buf == p->inline_buf) { 50762306a36Sopenharmony_ci tmp_buf = kmalloc(len, GFP_KERNEL); 50862306a36Sopenharmony_ci if (tmp_buf) 50962306a36Sopenharmony_ci memcpy(tmp_buf, p->buf, old_buf_len); 51062306a36Sopenharmony_ci } else { 51162306a36Sopenharmony_ci tmp_buf = krealloc(p->buf, len, GFP_KERNEL); 51262306a36Sopenharmony_ci } 51362306a36Sopenharmony_ci if (!tmp_buf) 51462306a36Sopenharmony_ci return -ENOMEM; 51562306a36Sopenharmony_ci p->buf = tmp_buf; 51662306a36Sopenharmony_ci p->buf_len = len; 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci if (p->reversed) { 51962306a36Sopenharmony_ci tmp_buf = p->buf + old_buf_len - path_len - 1; 52062306a36Sopenharmony_ci p->end = p->buf + p->buf_len - 1; 52162306a36Sopenharmony_ci p->start = p->end - path_len; 52262306a36Sopenharmony_ci memmove(p->start, tmp_buf, path_len + 1); 52362306a36Sopenharmony_ci } else { 52462306a36Sopenharmony_ci p->start = p->buf; 52562306a36Sopenharmony_ci p->end = p->start + path_len; 52662306a36Sopenharmony_ci } 52762306a36Sopenharmony_ci return 0; 52862306a36Sopenharmony_ci} 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_cistatic int fs_path_prepare_for_add(struct fs_path *p, int name_len, 53162306a36Sopenharmony_ci char **prepared) 53262306a36Sopenharmony_ci{ 53362306a36Sopenharmony_ci int ret; 53462306a36Sopenharmony_ci int new_len; 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci new_len = p->end - p->start + name_len; 53762306a36Sopenharmony_ci if (p->start != p->end) 53862306a36Sopenharmony_ci new_len++; 53962306a36Sopenharmony_ci ret = fs_path_ensure_buf(p, new_len); 54062306a36Sopenharmony_ci if (ret < 0) 54162306a36Sopenharmony_ci goto out; 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci if (p->reversed) { 54462306a36Sopenharmony_ci if (p->start != p->end) 54562306a36Sopenharmony_ci *--p->start = '/'; 54662306a36Sopenharmony_ci p->start -= name_len; 54762306a36Sopenharmony_ci *prepared = p->start; 54862306a36Sopenharmony_ci } else { 54962306a36Sopenharmony_ci if (p->start != p->end) 55062306a36Sopenharmony_ci *p->end++ = '/'; 55162306a36Sopenharmony_ci *prepared = p->end; 55262306a36Sopenharmony_ci p->end += name_len; 55362306a36Sopenharmony_ci *p->end = 0; 55462306a36Sopenharmony_ci } 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ciout: 55762306a36Sopenharmony_ci return ret; 55862306a36Sopenharmony_ci} 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_cistatic int fs_path_add(struct fs_path *p, const char *name, int name_len) 56162306a36Sopenharmony_ci{ 56262306a36Sopenharmony_ci int ret; 56362306a36Sopenharmony_ci char *prepared; 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci ret = fs_path_prepare_for_add(p, name_len, &prepared); 56662306a36Sopenharmony_ci if (ret < 0) 56762306a36Sopenharmony_ci goto out; 56862306a36Sopenharmony_ci memcpy(prepared, name, name_len); 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ciout: 57162306a36Sopenharmony_ci return ret; 57262306a36Sopenharmony_ci} 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_cistatic int fs_path_add_path(struct fs_path *p, struct fs_path *p2) 57562306a36Sopenharmony_ci{ 57662306a36Sopenharmony_ci int ret; 57762306a36Sopenharmony_ci char *prepared; 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci ret = fs_path_prepare_for_add(p, p2->end - p2->start, &prepared); 58062306a36Sopenharmony_ci if (ret < 0) 58162306a36Sopenharmony_ci goto out; 58262306a36Sopenharmony_ci memcpy(prepared, p2->start, p2->end - p2->start); 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ciout: 58562306a36Sopenharmony_ci return ret; 58662306a36Sopenharmony_ci} 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_cistatic int fs_path_add_from_extent_buffer(struct fs_path *p, 58962306a36Sopenharmony_ci struct extent_buffer *eb, 59062306a36Sopenharmony_ci unsigned long off, int len) 59162306a36Sopenharmony_ci{ 59262306a36Sopenharmony_ci int ret; 59362306a36Sopenharmony_ci char *prepared; 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci ret = fs_path_prepare_for_add(p, len, &prepared); 59662306a36Sopenharmony_ci if (ret < 0) 59762306a36Sopenharmony_ci goto out; 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci read_extent_buffer(eb, prepared, off, len); 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ciout: 60262306a36Sopenharmony_ci return ret; 60362306a36Sopenharmony_ci} 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_cistatic int fs_path_copy(struct fs_path *p, struct fs_path *from) 60662306a36Sopenharmony_ci{ 60762306a36Sopenharmony_ci p->reversed = from->reversed; 60862306a36Sopenharmony_ci fs_path_reset(p); 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci return fs_path_add_path(p, from); 61162306a36Sopenharmony_ci} 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_cistatic void fs_path_unreverse(struct fs_path *p) 61462306a36Sopenharmony_ci{ 61562306a36Sopenharmony_ci char *tmp; 61662306a36Sopenharmony_ci int len; 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci if (!p->reversed) 61962306a36Sopenharmony_ci return; 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci tmp = p->start; 62262306a36Sopenharmony_ci len = p->end - p->start; 62362306a36Sopenharmony_ci p->start = p->buf; 62462306a36Sopenharmony_ci p->end = p->start + len; 62562306a36Sopenharmony_ci memmove(p->start, tmp, len + 1); 62662306a36Sopenharmony_ci p->reversed = 0; 62762306a36Sopenharmony_ci} 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_cistatic struct btrfs_path *alloc_path_for_send(void) 63062306a36Sopenharmony_ci{ 63162306a36Sopenharmony_ci struct btrfs_path *path; 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci path = btrfs_alloc_path(); 63462306a36Sopenharmony_ci if (!path) 63562306a36Sopenharmony_ci return NULL; 63662306a36Sopenharmony_ci path->search_commit_root = 1; 63762306a36Sopenharmony_ci path->skip_locking = 1; 63862306a36Sopenharmony_ci path->need_commit_sem = 1; 63962306a36Sopenharmony_ci return path; 64062306a36Sopenharmony_ci} 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_cistatic int write_buf(struct file *filp, const void *buf, u32 len, loff_t *off) 64362306a36Sopenharmony_ci{ 64462306a36Sopenharmony_ci int ret; 64562306a36Sopenharmony_ci u32 pos = 0; 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci while (pos < len) { 64862306a36Sopenharmony_ci ret = kernel_write(filp, buf + pos, len - pos, off); 64962306a36Sopenharmony_ci if (ret < 0) 65062306a36Sopenharmony_ci return ret; 65162306a36Sopenharmony_ci if (ret == 0) 65262306a36Sopenharmony_ci return -EIO; 65362306a36Sopenharmony_ci pos += ret; 65462306a36Sopenharmony_ci } 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci return 0; 65762306a36Sopenharmony_ci} 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_cistatic int tlv_put(struct send_ctx *sctx, u16 attr, const void *data, int len) 66062306a36Sopenharmony_ci{ 66162306a36Sopenharmony_ci struct btrfs_tlv_header *hdr; 66262306a36Sopenharmony_ci int total_len = sizeof(*hdr) + len; 66362306a36Sopenharmony_ci int left = sctx->send_max_size - sctx->send_size; 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci if (WARN_ON_ONCE(sctx->put_data)) 66662306a36Sopenharmony_ci return -EINVAL; 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci if (unlikely(left < total_len)) 66962306a36Sopenharmony_ci return -EOVERFLOW; 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_ci hdr = (struct btrfs_tlv_header *) (sctx->send_buf + sctx->send_size); 67262306a36Sopenharmony_ci put_unaligned_le16(attr, &hdr->tlv_type); 67362306a36Sopenharmony_ci put_unaligned_le16(len, &hdr->tlv_len); 67462306a36Sopenharmony_ci memcpy(hdr + 1, data, len); 67562306a36Sopenharmony_ci sctx->send_size += total_len; 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci return 0; 67862306a36Sopenharmony_ci} 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci#define TLV_PUT_DEFINE_INT(bits) \ 68162306a36Sopenharmony_ci static int tlv_put_u##bits(struct send_ctx *sctx, \ 68262306a36Sopenharmony_ci u##bits attr, u##bits value) \ 68362306a36Sopenharmony_ci { \ 68462306a36Sopenharmony_ci __le##bits __tmp = cpu_to_le##bits(value); \ 68562306a36Sopenharmony_ci return tlv_put(sctx, attr, &__tmp, sizeof(__tmp)); \ 68662306a36Sopenharmony_ci } 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ciTLV_PUT_DEFINE_INT(8) 68962306a36Sopenharmony_ciTLV_PUT_DEFINE_INT(32) 69062306a36Sopenharmony_ciTLV_PUT_DEFINE_INT(64) 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_cistatic int tlv_put_string(struct send_ctx *sctx, u16 attr, 69362306a36Sopenharmony_ci const char *str, int len) 69462306a36Sopenharmony_ci{ 69562306a36Sopenharmony_ci if (len == -1) 69662306a36Sopenharmony_ci len = strlen(str); 69762306a36Sopenharmony_ci return tlv_put(sctx, attr, str, len); 69862306a36Sopenharmony_ci} 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_cistatic int tlv_put_uuid(struct send_ctx *sctx, u16 attr, 70162306a36Sopenharmony_ci const u8 *uuid) 70262306a36Sopenharmony_ci{ 70362306a36Sopenharmony_ci return tlv_put(sctx, attr, uuid, BTRFS_UUID_SIZE); 70462306a36Sopenharmony_ci} 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_cistatic int tlv_put_btrfs_timespec(struct send_ctx *sctx, u16 attr, 70762306a36Sopenharmony_ci struct extent_buffer *eb, 70862306a36Sopenharmony_ci struct btrfs_timespec *ts) 70962306a36Sopenharmony_ci{ 71062306a36Sopenharmony_ci struct btrfs_timespec bts; 71162306a36Sopenharmony_ci read_extent_buffer(eb, &bts, (unsigned long)ts, sizeof(bts)); 71262306a36Sopenharmony_ci return tlv_put(sctx, attr, &bts, sizeof(bts)); 71362306a36Sopenharmony_ci} 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci#define TLV_PUT(sctx, attrtype, data, attrlen) \ 71762306a36Sopenharmony_ci do { \ 71862306a36Sopenharmony_ci ret = tlv_put(sctx, attrtype, data, attrlen); \ 71962306a36Sopenharmony_ci if (ret < 0) \ 72062306a36Sopenharmony_ci goto tlv_put_failure; \ 72162306a36Sopenharmony_ci } while (0) 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci#define TLV_PUT_INT(sctx, attrtype, bits, value) \ 72462306a36Sopenharmony_ci do { \ 72562306a36Sopenharmony_ci ret = tlv_put_u##bits(sctx, attrtype, value); \ 72662306a36Sopenharmony_ci if (ret < 0) \ 72762306a36Sopenharmony_ci goto tlv_put_failure; \ 72862306a36Sopenharmony_ci } while (0) 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci#define TLV_PUT_U8(sctx, attrtype, data) TLV_PUT_INT(sctx, attrtype, 8, data) 73162306a36Sopenharmony_ci#define TLV_PUT_U16(sctx, attrtype, data) TLV_PUT_INT(sctx, attrtype, 16, data) 73262306a36Sopenharmony_ci#define TLV_PUT_U32(sctx, attrtype, data) TLV_PUT_INT(sctx, attrtype, 32, data) 73362306a36Sopenharmony_ci#define TLV_PUT_U64(sctx, attrtype, data) TLV_PUT_INT(sctx, attrtype, 64, data) 73462306a36Sopenharmony_ci#define TLV_PUT_STRING(sctx, attrtype, str, len) \ 73562306a36Sopenharmony_ci do { \ 73662306a36Sopenharmony_ci ret = tlv_put_string(sctx, attrtype, str, len); \ 73762306a36Sopenharmony_ci if (ret < 0) \ 73862306a36Sopenharmony_ci goto tlv_put_failure; \ 73962306a36Sopenharmony_ci } while (0) 74062306a36Sopenharmony_ci#define TLV_PUT_PATH(sctx, attrtype, p) \ 74162306a36Sopenharmony_ci do { \ 74262306a36Sopenharmony_ci ret = tlv_put_string(sctx, attrtype, p->start, \ 74362306a36Sopenharmony_ci p->end - p->start); \ 74462306a36Sopenharmony_ci if (ret < 0) \ 74562306a36Sopenharmony_ci goto tlv_put_failure; \ 74662306a36Sopenharmony_ci } while(0) 74762306a36Sopenharmony_ci#define TLV_PUT_UUID(sctx, attrtype, uuid) \ 74862306a36Sopenharmony_ci do { \ 74962306a36Sopenharmony_ci ret = tlv_put_uuid(sctx, attrtype, uuid); \ 75062306a36Sopenharmony_ci if (ret < 0) \ 75162306a36Sopenharmony_ci goto tlv_put_failure; \ 75262306a36Sopenharmony_ci } while (0) 75362306a36Sopenharmony_ci#define TLV_PUT_BTRFS_TIMESPEC(sctx, attrtype, eb, ts) \ 75462306a36Sopenharmony_ci do { \ 75562306a36Sopenharmony_ci ret = tlv_put_btrfs_timespec(sctx, attrtype, eb, ts); \ 75662306a36Sopenharmony_ci if (ret < 0) \ 75762306a36Sopenharmony_ci goto tlv_put_failure; \ 75862306a36Sopenharmony_ci } while (0) 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_cistatic int send_header(struct send_ctx *sctx) 76162306a36Sopenharmony_ci{ 76262306a36Sopenharmony_ci struct btrfs_stream_header hdr; 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci strcpy(hdr.magic, BTRFS_SEND_STREAM_MAGIC); 76562306a36Sopenharmony_ci hdr.version = cpu_to_le32(sctx->proto); 76662306a36Sopenharmony_ci return write_buf(sctx->send_filp, &hdr, sizeof(hdr), 76762306a36Sopenharmony_ci &sctx->send_off); 76862306a36Sopenharmony_ci} 76962306a36Sopenharmony_ci 77062306a36Sopenharmony_ci/* 77162306a36Sopenharmony_ci * For each command/item we want to send to userspace, we call this function. 77262306a36Sopenharmony_ci */ 77362306a36Sopenharmony_cistatic int begin_cmd(struct send_ctx *sctx, int cmd) 77462306a36Sopenharmony_ci{ 77562306a36Sopenharmony_ci struct btrfs_cmd_header *hdr; 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci if (WARN_ON(!sctx->send_buf)) 77862306a36Sopenharmony_ci return -EINVAL; 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_ci BUG_ON(sctx->send_size); 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci sctx->send_size += sizeof(*hdr); 78362306a36Sopenharmony_ci hdr = (struct btrfs_cmd_header *)sctx->send_buf; 78462306a36Sopenharmony_ci put_unaligned_le16(cmd, &hdr->cmd); 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci return 0; 78762306a36Sopenharmony_ci} 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_cistatic int send_cmd(struct send_ctx *sctx) 79062306a36Sopenharmony_ci{ 79162306a36Sopenharmony_ci int ret; 79262306a36Sopenharmony_ci struct btrfs_cmd_header *hdr; 79362306a36Sopenharmony_ci u32 crc; 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ci hdr = (struct btrfs_cmd_header *)sctx->send_buf; 79662306a36Sopenharmony_ci put_unaligned_le32(sctx->send_size - sizeof(*hdr), &hdr->len); 79762306a36Sopenharmony_ci put_unaligned_le32(0, &hdr->crc); 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_ci crc = btrfs_crc32c(0, (unsigned char *)sctx->send_buf, sctx->send_size); 80062306a36Sopenharmony_ci put_unaligned_le32(crc, &hdr->crc); 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci ret = write_buf(sctx->send_filp, sctx->send_buf, sctx->send_size, 80362306a36Sopenharmony_ci &sctx->send_off); 80462306a36Sopenharmony_ci 80562306a36Sopenharmony_ci sctx->send_size = 0; 80662306a36Sopenharmony_ci sctx->put_data = false; 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_ci return ret; 80962306a36Sopenharmony_ci} 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_ci/* 81262306a36Sopenharmony_ci * Sends a move instruction to user space 81362306a36Sopenharmony_ci */ 81462306a36Sopenharmony_cistatic int send_rename(struct send_ctx *sctx, 81562306a36Sopenharmony_ci struct fs_path *from, struct fs_path *to) 81662306a36Sopenharmony_ci{ 81762306a36Sopenharmony_ci struct btrfs_fs_info *fs_info = sctx->send_root->fs_info; 81862306a36Sopenharmony_ci int ret; 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_ci btrfs_debug(fs_info, "send_rename %s -> %s", from->start, to->start); 82162306a36Sopenharmony_ci 82262306a36Sopenharmony_ci ret = begin_cmd(sctx, BTRFS_SEND_C_RENAME); 82362306a36Sopenharmony_ci if (ret < 0) 82462306a36Sopenharmony_ci goto out; 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_ci TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, from); 82762306a36Sopenharmony_ci TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH_TO, to); 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_ci ret = send_cmd(sctx); 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_citlv_put_failure: 83262306a36Sopenharmony_ciout: 83362306a36Sopenharmony_ci return ret; 83462306a36Sopenharmony_ci} 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_ci/* 83762306a36Sopenharmony_ci * Sends a link instruction to user space 83862306a36Sopenharmony_ci */ 83962306a36Sopenharmony_cistatic int send_link(struct send_ctx *sctx, 84062306a36Sopenharmony_ci struct fs_path *path, struct fs_path *lnk) 84162306a36Sopenharmony_ci{ 84262306a36Sopenharmony_ci struct btrfs_fs_info *fs_info = sctx->send_root->fs_info; 84362306a36Sopenharmony_ci int ret; 84462306a36Sopenharmony_ci 84562306a36Sopenharmony_ci btrfs_debug(fs_info, "send_link %s -> %s", path->start, lnk->start); 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ci ret = begin_cmd(sctx, BTRFS_SEND_C_LINK); 84862306a36Sopenharmony_ci if (ret < 0) 84962306a36Sopenharmony_ci goto out; 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_ci TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, path); 85262306a36Sopenharmony_ci TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH_LINK, lnk); 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci ret = send_cmd(sctx); 85562306a36Sopenharmony_ci 85662306a36Sopenharmony_citlv_put_failure: 85762306a36Sopenharmony_ciout: 85862306a36Sopenharmony_ci return ret; 85962306a36Sopenharmony_ci} 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci/* 86262306a36Sopenharmony_ci * Sends an unlink instruction to user space 86362306a36Sopenharmony_ci */ 86462306a36Sopenharmony_cistatic int send_unlink(struct send_ctx *sctx, struct fs_path *path) 86562306a36Sopenharmony_ci{ 86662306a36Sopenharmony_ci struct btrfs_fs_info *fs_info = sctx->send_root->fs_info; 86762306a36Sopenharmony_ci int ret; 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_ci btrfs_debug(fs_info, "send_unlink %s", path->start); 87062306a36Sopenharmony_ci 87162306a36Sopenharmony_ci ret = begin_cmd(sctx, BTRFS_SEND_C_UNLINK); 87262306a36Sopenharmony_ci if (ret < 0) 87362306a36Sopenharmony_ci goto out; 87462306a36Sopenharmony_ci 87562306a36Sopenharmony_ci TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, path); 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_ci ret = send_cmd(sctx); 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_citlv_put_failure: 88062306a36Sopenharmony_ciout: 88162306a36Sopenharmony_ci return ret; 88262306a36Sopenharmony_ci} 88362306a36Sopenharmony_ci 88462306a36Sopenharmony_ci/* 88562306a36Sopenharmony_ci * Sends a rmdir instruction to user space 88662306a36Sopenharmony_ci */ 88762306a36Sopenharmony_cistatic int send_rmdir(struct send_ctx *sctx, struct fs_path *path) 88862306a36Sopenharmony_ci{ 88962306a36Sopenharmony_ci struct btrfs_fs_info *fs_info = sctx->send_root->fs_info; 89062306a36Sopenharmony_ci int ret; 89162306a36Sopenharmony_ci 89262306a36Sopenharmony_ci btrfs_debug(fs_info, "send_rmdir %s", path->start); 89362306a36Sopenharmony_ci 89462306a36Sopenharmony_ci ret = begin_cmd(sctx, BTRFS_SEND_C_RMDIR); 89562306a36Sopenharmony_ci if (ret < 0) 89662306a36Sopenharmony_ci goto out; 89762306a36Sopenharmony_ci 89862306a36Sopenharmony_ci TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, path); 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_ci ret = send_cmd(sctx); 90162306a36Sopenharmony_ci 90262306a36Sopenharmony_citlv_put_failure: 90362306a36Sopenharmony_ciout: 90462306a36Sopenharmony_ci return ret; 90562306a36Sopenharmony_ci} 90662306a36Sopenharmony_ci 90762306a36Sopenharmony_cistruct btrfs_inode_info { 90862306a36Sopenharmony_ci u64 size; 90962306a36Sopenharmony_ci u64 gen; 91062306a36Sopenharmony_ci u64 mode; 91162306a36Sopenharmony_ci u64 uid; 91262306a36Sopenharmony_ci u64 gid; 91362306a36Sopenharmony_ci u64 rdev; 91462306a36Sopenharmony_ci u64 fileattr; 91562306a36Sopenharmony_ci u64 nlink; 91662306a36Sopenharmony_ci}; 91762306a36Sopenharmony_ci 91862306a36Sopenharmony_ci/* 91962306a36Sopenharmony_ci * Helper function to retrieve some fields from an inode item. 92062306a36Sopenharmony_ci */ 92162306a36Sopenharmony_cistatic int get_inode_info(struct btrfs_root *root, u64 ino, 92262306a36Sopenharmony_ci struct btrfs_inode_info *info) 92362306a36Sopenharmony_ci{ 92462306a36Sopenharmony_ci int ret; 92562306a36Sopenharmony_ci struct btrfs_path *path; 92662306a36Sopenharmony_ci struct btrfs_inode_item *ii; 92762306a36Sopenharmony_ci struct btrfs_key key; 92862306a36Sopenharmony_ci 92962306a36Sopenharmony_ci path = alloc_path_for_send(); 93062306a36Sopenharmony_ci if (!path) 93162306a36Sopenharmony_ci return -ENOMEM; 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_ci key.objectid = ino; 93462306a36Sopenharmony_ci key.type = BTRFS_INODE_ITEM_KEY; 93562306a36Sopenharmony_ci key.offset = 0; 93662306a36Sopenharmony_ci ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); 93762306a36Sopenharmony_ci if (ret) { 93862306a36Sopenharmony_ci if (ret > 0) 93962306a36Sopenharmony_ci ret = -ENOENT; 94062306a36Sopenharmony_ci goto out; 94162306a36Sopenharmony_ci } 94262306a36Sopenharmony_ci 94362306a36Sopenharmony_ci if (!info) 94462306a36Sopenharmony_ci goto out; 94562306a36Sopenharmony_ci 94662306a36Sopenharmony_ci ii = btrfs_item_ptr(path->nodes[0], path->slots[0], 94762306a36Sopenharmony_ci struct btrfs_inode_item); 94862306a36Sopenharmony_ci info->size = btrfs_inode_size(path->nodes[0], ii); 94962306a36Sopenharmony_ci info->gen = btrfs_inode_generation(path->nodes[0], ii); 95062306a36Sopenharmony_ci info->mode = btrfs_inode_mode(path->nodes[0], ii); 95162306a36Sopenharmony_ci info->uid = btrfs_inode_uid(path->nodes[0], ii); 95262306a36Sopenharmony_ci info->gid = btrfs_inode_gid(path->nodes[0], ii); 95362306a36Sopenharmony_ci info->rdev = btrfs_inode_rdev(path->nodes[0], ii); 95462306a36Sopenharmony_ci info->nlink = btrfs_inode_nlink(path->nodes[0], ii); 95562306a36Sopenharmony_ci /* 95662306a36Sopenharmony_ci * Transfer the unchanged u64 value of btrfs_inode_item::flags, that's 95762306a36Sopenharmony_ci * otherwise logically split to 32/32 parts. 95862306a36Sopenharmony_ci */ 95962306a36Sopenharmony_ci info->fileattr = btrfs_inode_flags(path->nodes[0], ii); 96062306a36Sopenharmony_ci 96162306a36Sopenharmony_ciout: 96262306a36Sopenharmony_ci btrfs_free_path(path); 96362306a36Sopenharmony_ci return ret; 96462306a36Sopenharmony_ci} 96562306a36Sopenharmony_ci 96662306a36Sopenharmony_cistatic int get_inode_gen(struct btrfs_root *root, u64 ino, u64 *gen) 96762306a36Sopenharmony_ci{ 96862306a36Sopenharmony_ci int ret; 96962306a36Sopenharmony_ci struct btrfs_inode_info info = { 0 }; 97062306a36Sopenharmony_ci 97162306a36Sopenharmony_ci ASSERT(gen); 97262306a36Sopenharmony_ci 97362306a36Sopenharmony_ci ret = get_inode_info(root, ino, &info); 97462306a36Sopenharmony_ci *gen = info.gen; 97562306a36Sopenharmony_ci return ret; 97662306a36Sopenharmony_ci} 97762306a36Sopenharmony_ci 97862306a36Sopenharmony_citypedef int (*iterate_inode_ref_t)(int num, u64 dir, int index, 97962306a36Sopenharmony_ci struct fs_path *p, 98062306a36Sopenharmony_ci void *ctx); 98162306a36Sopenharmony_ci 98262306a36Sopenharmony_ci/* 98362306a36Sopenharmony_ci * Helper function to iterate the entries in ONE btrfs_inode_ref or 98462306a36Sopenharmony_ci * btrfs_inode_extref. 98562306a36Sopenharmony_ci * The iterate callback may return a non zero value to stop iteration. This can 98662306a36Sopenharmony_ci * be a negative value for error codes or 1 to simply stop it. 98762306a36Sopenharmony_ci * 98862306a36Sopenharmony_ci * path must point to the INODE_REF or INODE_EXTREF when called. 98962306a36Sopenharmony_ci */ 99062306a36Sopenharmony_cistatic int iterate_inode_ref(struct btrfs_root *root, struct btrfs_path *path, 99162306a36Sopenharmony_ci struct btrfs_key *found_key, int resolve, 99262306a36Sopenharmony_ci iterate_inode_ref_t iterate, void *ctx) 99362306a36Sopenharmony_ci{ 99462306a36Sopenharmony_ci struct extent_buffer *eb = path->nodes[0]; 99562306a36Sopenharmony_ci struct btrfs_inode_ref *iref; 99662306a36Sopenharmony_ci struct btrfs_inode_extref *extref; 99762306a36Sopenharmony_ci struct btrfs_path *tmp_path; 99862306a36Sopenharmony_ci struct fs_path *p; 99962306a36Sopenharmony_ci u32 cur = 0; 100062306a36Sopenharmony_ci u32 total; 100162306a36Sopenharmony_ci int slot = path->slots[0]; 100262306a36Sopenharmony_ci u32 name_len; 100362306a36Sopenharmony_ci char *start; 100462306a36Sopenharmony_ci int ret = 0; 100562306a36Sopenharmony_ci int num = 0; 100662306a36Sopenharmony_ci int index; 100762306a36Sopenharmony_ci u64 dir; 100862306a36Sopenharmony_ci unsigned long name_off; 100962306a36Sopenharmony_ci unsigned long elem_size; 101062306a36Sopenharmony_ci unsigned long ptr; 101162306a36Sopenharmony_ci 101262306a36Sopenharmony_ci p = fs_path_alloc_reversed(); 101362306a36Sopenharmony_ci if (!p) 101462306a36Sopenharmony_ci return -ENOMEM; 101562306a36Sopenharmony_ci 101662306a36Sopenharmony_ci tmp_path = alloc_path_for_send(); 101762306a36Sopenharmony_ci if (!tmp_path) { 101862306a36Sopenharmony_ci fs_path_free(p); 101962306a36Sopenharmony_ci return -ENOMEM; 102062306a36Sopenharmony_ci } 102162306a36Sopenharmony_ci 102262306a36Sopenharmony_ci 102362306a36Sopenharmony_ci if (found_key->type == BTRFS_INODE_REF_KEY) { 102462306a36Sopenharmony_ci ptr = (unsigned long)btrfs_item_ptr(eb, slot, 102562306a36Sopenharmony_ci struct btrfs_inode_ref); 102662306a36Sopenharmony_ci total = btrfs_item_size(eb, slot); 102762306a36Sopenharmony_ci elem_size = sizeof(*iref); 102862306a36Sopenharmony_ci } else { 102962306a36Sopenharmony_ci ptr = btrfs_item_ptr_offset(eb, slot); 103062306a36Sopenharmony_ci total = btrfs_item_size(eb, slot); 103162306a36Sopenharmony_ci elem_size = sizeof(*extref); 103262306a36Sopenharmony_ci } 103362306a36Sopenharmony_ci 103462306a36Sopenharmony_ci while (cur < total) { 103562306a36Sopenharmony_ci fs_path_reset(p); 103662306a36Sopenharmony_ci 103762306a36Sopenharmony_ci if (found_key->type == BTRFS_INODE_REF_KEY) { 103862306a36Sopenharmony_ci iref = (struct btrfs_inode_ref *)(ptr + cur); 103962306a36Sopenharmony_ci name_len = btrfs_inode_ref_name_len(eb, iref); 104062306a36Sopenharmony_ci name_off = (unsigned long)(iref + 1); 104162306a36Sopenharmony_ci index = btrfs_inode_ref_index(eb, iref); 104262306a36Sopenharmony_ci dir = found_key->offset; 104362306a36Sopenharmony_ci } else { 104462306a36Sopenharmony_ci extref = (struct btrfs_inode_extref *)(ptr + cur); 104562306a36Sopenharmony_ci name_len = btrfs_inode_extref_name_len(eb, extref); 104662306a36Sopenharmony_ci name_off = (unsigned long)&extref->name; 104762306a36Sopenharmony_ci index = btrfs_inode_extref_index(eb, extref); 104862306a36Sopenharmony_ci dir = btrfs_inode_extref_parent(eb, extref); 104962306a36Sopenharmony_ci } 105062306a36Sopenharmony_ci 105162306a36Sopenharmony_ci if (resolve) { 105262306a36Sopenharmony_ci start = btrfs_ref_to_path(root, tmp_path, name_len, 105362306a36Sopenharmony_ci name_off, eb, dir, 105462306a36Sopenharmony_ci p->buf, p->buf_len); 105562306a36Sopenharmony_ci if (IS_ERR(start)) { 105662306a36Sopenharmony_ci ret = PTR_ERR(start); 105762306a36Sopenharmony_ci goto out; 105862306a36Sopenharmony_ci } 105962306a36Sopenharmony_ci if (start < p->buf) { 106062306a36Sopenharmony_ci /* overflow , try again with larger buffer */ 106162306a36Sopenharmony_ci ret = fs_path_ensure_buf(p, 106262306a36Sopenharmony_ci p->buf_len + p->buf - start); 106362306a36Sopenharmony_ci if (ret < 0) 106462306a36Sopenharmony_ci goto out; 106562306a36Sopenharmony_ci start = btrfs_ref_to_path(root, tmp_path, 106662306a36Sopenharmony_ci name_len, name_off, 106762306a36Sopenharmony_ci eb, dir, 106862306a36Sopenharmony_ci p->buf, p->buf_len); 106962306a36Sopenharmony_ci if (IS_ERR(start)) { 107062306a36Sopenharmony_ci ret = PTR_ERR(start); 107162306a36Sopenharmony_ci goto out; 107262306a36Sopenharmony_ci } 107362306a36Sopenharmony_ci BUG_ON(start < p->buf); 107462306a36Sopenharmony_ci } 107562306a36Sopenharmony_ci p->start = start; 107662306a36Sopenharmony_ci } else { 107762306a36Sopenharmony_ci ret = fs_path_add_from_extent_buffer(p, eb, name_off, 107862306a36Sopenharmony_ci name_len); 107962306a36Sopenharmony_ci if (ret < 0) 108062306a36Sopenharmony_ci goto out; 108162306a36Sopenharmony_ci } 108262306a36Sopenharmony_ci 108362306a36Sopenharmony_ci cur += elem_size + name_len; 108462306a36Sopenharmony_ci ret = iterate(num, dir, index, p, ctx); 108562306a36Sopenharmony_ci if (ret) 108662306a36Sopenharmony_ci goto out; 108762306a36Sopenharmony_ci num++; 108862306a36Sopenharmony_ci } 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_ciout: 109162306a36Sopenharmony_ci btrfs_free_path(tmp_path); 109262306a36Sopenharmony_ci fs_path_free(p); 109362306a36Sopenharmony_ci return ret; 109462306a36Sopenharmony_ci} 109562306a36Sopenharmony_ci 109662306a36Sopenharmony_citypedef int (*iterate_dir_item_t)(int num, struct btrfs_key *di_key, 109762306a36Sopenharmony_ci const char *name, int name_len, 109862306a36Sopenharmony_ci const char *data, int data_len, 109962306a36Sopenharmony_ci void *ctx); 110062306a36Sopenharmony_ci 110162306a36Sopenharmony_ci/* 110262306a36Sopenharmony_ci * Helper function to iterate the entries in ONE btrfs_dir_item. 110362306a36Sopenharmony_ci * The iterate callback may return a non zero value to stop iteration. This can 110462306a36Sopenharmony_ci * be a negative value for error codes or 1 to simply stop it. 110562306a36Sopenharmony_ci * 110662306a36Sopenharmony_ci * path must point to the dir item when called. 110762306a36Sopenharmony_ci */ 110862306a36Sopenharmony_cistatic int iterate_dir_item(struct btrfs_root *root, struct btrfs_path *path, 110962306a36Sopenharmony_ci iterate_dir_item_t iterate, void *ctx) 111062306a36Sopenharmony_ci{ 111162306a36Sopenharmony_ci int ret = 0; 111262306a36Sopenharmony_ci struct extent_buffer *eb; 111362306a36Sopenharmony_ci struct btrfs_dir_item *di; 111462306a36Sopenharmony_ci struct btrfs_key di_key; 111562306a36Sopenharmony_ci char *buf = NULL; 111662306a36Sopenharmony_ci int buf_len; 111762306a36Sopenharmony_ci u32 name_len; 111862306a36Sopenharmony_ci u32 data_len; 111962306a36Sopenharmony_ci u32 cur; 112062306a36Sopenharmony_ci u32 len; 112162306a36Sopenharmony_ci u32 total; 112262306a36Sopenharmony_ci int slot; 112362306a36Sopenharmony_ci int num; 112462306a36Sopenharmony_ci 112562306a36Sopenharmony_ci /* 112662306a36Sopenharmony_ci * Start with a small buffer (1 page). If later we end up needing more 112762306a36Sopenharmony_ci * space, which can happen for xattrs on a fs with a leaf size greater 112862306a36Sopenharmony_ci * then the page size, attempt to increase the buffer. Typically xattr 112962306a36Sopenharmony_ci * values are small. 113062306a36Sopenharmony_ci */ 113162306a36Sopenharmony_ci buf_len = PATH_MAX; 113262306a36Sopenharmony_ci buf = kmalloc(buf_len, GFP_KERNEL); 113362306a36Sopenharmony_ci if (!buf) { 113462306a36Sopenharmony_ci ret = -ENOMEM; 113562306a36Sopenharmony_ci goto out; 113662306a36Sopenharmony_ci } 113762306a36Sopenharmony_ci 113862306a36Sopenharmony_ci eb = path->nodes[0]; 113962306a36Sopenharmony_ci slot = path->slots[0]; 114062306a36Sopenharmony_ci di = btrfs_item_ptr(eb, slot, struct btrfs_dir_item); 114162306a36Sopenharmony_ci cur = 0; 114262306a36Sopenharmony_ci len = 0; 114362306a36Sopenharmony_ci total = btrfs_item_size(eb, slot); 114462306a36Sopenharmony_ci 114562306a36Sopenharmony_ci num = 0; 114662306a36Sopenharmony_ci while (cur < total) { 114762306a36Sopenharmony_ci name_len = btrfs_dir_name_len(eb, di); 114862306a36Sopenharmony_ci data_len = btrfs_dir_data_len(eb, di); 114962306a36Sopenharmony_ci btrfs_dir_item_key_to_cpu(eb, di, &di_key); 115062306a36Sopenharmony_ci 115162306a36Sopenharmony_ci if (btrfs_dir_ftype(eb, di) == BTRFS_FT_XATTR) { 115262306a36Sopenharmony_ci if (name_len > XATTR_NAME_MAX) { 115362306a36Sopenharmony_ci ret = -ENAMETOOLONG; 115462306a36Sopenharmony_ci goto out; 115562306a36Sopenharmony_ci } 115662306a36Sopenharmony_ci if (name_len + data_len > 115762306a36Sopenharmony_ci BTRFS_MAX_XATTR_SIZE(root->fs_info)) { 115862306a36Sopenharmony_ci ret = -E2BIG; 115962306a36Sopenharmony_ci goto out; 116062306a36Sopenharmony_ci } 116162306a36Sopenharmony_ci } else { 116262306a36Sopenharmony_ci /* 116362306a36Sopenharmony_ci * Path too long 116462306a36Sopenharmony_ci */ 116562306a36Sopenharmony_ci if (name_len + data_len > PATH_MAX) { 116662306a36Sopenharmony_ci ret = -ENAMETOOLONG; 116762306a36Sopenharmony_ci goto out; 116862306a36Sopenharmony_ci } 116962306a36Sopenharmony_ci } 117062306a36Sopenharmony_ci 117162306a36Sopenharmony_ci if (name_len + data_len > buf_len) { 117262306a36Sopenharmony_ci buf_len = name_len + data_len; 117362306a36Sopenharmony_ci if (is_vmalloc_addr(buf)) { 117462306a36Sopenharmony_ci vfree(buf); 117562306a36Sopenharmony_ci buf = NULL; 117662306a36Sopenharmony_ci } else { 117762306a36Sopenharmony_ci char *tmp = krealloc(buf, buf_len, 117862306a36Sopenharmony_ci GFP_KERNEL | __GFP_NOWARN); 117962306a36Sopenharmony_ci 118062306a36Sopenharmony_ci if (!tmp) 118162306a36Sopenharmony_ci kfree(buf); 118262306a36Sopenharmony_ci buf = tmp; 118362306a36Sopenharmony_ci } 118462306a36Sopenharmony_ci if (!buf) { 118562306a36Sopenharmony_ci buf = kvmalloc(buf_len, GFP_KERNEL); 118662306a36Sopenharmony_ci if (!buf) { 118762306a36Sopenharmony_ci ret = -ENOMEM; 118862306a36Sopenharmony_ci goto out; 118962306a36Sopenharmony_ci } 119062306a36Sopenharmony_ci } 119162306a36Sopenharmony_ci } 119262306a36Sopenharmony_ci 119362306a36Sopenharmony_ci read_extent_buffer(eb, buf, (unsigned long)(di + 1), 119462306a36Sopenharmony_ci name_len + data_len); 119562306a36Sopenharmony_ci 119662306a36Sopenharmony_ci len = sizeof(*di) + name_len + data_len; 119762306a36Sopenharmony_ci di = (struct btrfs_dir_item *)((char *)di + len); 119862306a36Sopenharmony_ci cur += len; 119962306a36Sopenharmony_ci 120062306a36Sopenharmony_ci ret = iterate(num, &di_key, buf, name_len, buf + name_len, 120162306a36Sopenharmony_ci data_len, ctx); 120262306a36Sopenharmony_ci if (ret < 0) 120362306a36Sopenharmony_ci goto out; 120462306a36Sopenharmony_ci if (ret) { 120562306a36Sopenharmony_ci ret = 0; 120662306a36Sopenharmony_ci goto out; 120762306a36Sopenharmony_ci } 120862306a36Sopenharmony_ci 120962306a36Sopenharmony_ci num++; 121062306a36Sopenharmony_ci } 121162306a36Sopenharmony_ci 121262306a36Sopenharmony_ciout: 121362306a36Sopenharmony_ci kvfree(buf); 121462306a36Sopenharmony_ci return ret; 121562306a36Sopenharmony_ci} 121662306a36Sopenharmony_ci 121762306a36Sopenharmony_cistatic int __copy_first_ref(int num, u64 dir, int index, 121862306a36Sopenharmony_ci struct fs_path *p, void *ctx) 121962306a36Sopenharmony_ci{ 122062306a36Sopenharmony_ci int ret; 122162306a36Sopenharmony_ci struct fs_path *pt = ctx; 122262306a36Sopenharmony_ci 122362306a36Sopenharmony_ci ret = fs_path_copy(pt, p); 122462306a36Sopenharmony_ci if (ret < 0) 122562306a36Sopenharmony_ci return ret; 122662306a36Sopenharmony_ci 122762306a36Sopenharmony_ci /* we want the first only */ 122862306a36Sopenharmony_ci return 1; 122962306a36Sopenharmony_ci} 123062306a36Sopenharmony_ci 123162306a36Sopenharmony_ci/* 123262306a36Sopenharmony_ci * Retrieve the first path of an inode. If an inode has more then one 123362306a36Sopenharmony_ci * ref/hardlink, this is ignored. 123462306a36Sopenharmony_ci */ 123562306a36Sopenharmony_cistatic int get_inode_path(struct btrfs_root *root, 123662306a36Sopenharmony_ci u64 ino, struct fs_path *path) 123762306a36Sopenharmony_ci{ 123862306a36Sopenharmony_ci int ret; 123962306a36Sopenharmony_ci struct btrfs_key key, found_key; 124062306a36Sopenharmony_ci struct btrfs_path *p; 124162306a36Sopenharmony_ci 124262306a36Sopenharmony_ci p = alloc_path_for_send(); 124362306a36Sopenharmony_ci if (!p) 124462306a36Sopenharmony_ci return -ENOMEM; 124562306a36Sopenharmony_ci 124662306a36Sopenharmony_ci fs_path_reset(path); 124762306a36Sopenharmony_ci 124862306a36Sopenharmony_ci key.objectid = ino; 124962306a36Sopenharmony_ci key.type = BTRFS_INODE_REF_KEY; 125062306a36Sopenharmony_ci key.offset = 0; 125162306a36Sopenharmony_ci 125262306a36Sopenharmony_ci ret = btrfs_search_slot_for_read(root, &key, p, 1, 0); 125362306a36Sopenharmony_ci if (ret < 0) 125462306a36Sopenharmony_ci goto out; 125562306a36Sopenharmony_ci if (ret) { 125662306a36Sopenharmony_ci ret = 1; 125762306a36Sopenharmony_ci goto out; 125862306a36Sopenharmony_ci } 125962306a36Sopenharmony_ci btrfs_item_key_to_cpu(p->nodes[0], &found_key, p->slots[0]); 126062306a36Sopenharmony_ci if (found_key.objectid != ino || 126162306a36Sopenharmony_ci (found_key.type != BTRFS_INODE_REF_KEY && 126262306a36Sopenharmony_ci found_key.type != BTRFS_INODE_EXTREF_KEY)) { 126362306a36Sopenharmony_ci ret = -ENOENT; 126462306a36Sopenharmony_ci goto out; 126562306a36Sopenharmony_ci } 126662306a36Sopenharmony_ci 126762306a36Sopenharmony_ci ret = iterate_inode_ref(root, p, &found_key, 1, 126862306a36Sopenharmony_ci __copy_first_ref, path); 126962306a36Sopenharmony_ci if (ret < 0) 127062306a36Sopenharmony_ci goto out; 127162306a36Sopenharmony_ci ret = 0; 127262306a36Sopenharmony_ci 127362306a36Sopenharmony_ciout: 127462306a36Sopenharmony_ci btrfs_free_path(p); 127562306a36Sopenharmony_ci return ret; 127662306a36Sopenharmony_ci} 127762306a36Sopenharmony_ci 127862306a36Sopenharmony_cistruct backref_ctx { 127962306a36Sopenharmony_ci struct send_ctx *sctx; 128062306a36Sopenharmony_ci 128162306a36Sopenharmony_ci /* number of total found references */ 128262306a36Sopenharmony_ci u64 found; 128362306a36Sopenharmony_ci 128462306a36Sopenharmony_ci /* 128562306a36Sopenharmony_ci * used for clones found in send_root. clones found behind cur_objectid 128662306a36Sopenharmony_ci * and cur_offset are not considered as allowed clones. 128762306a36Sopenharmony_ci */ 128862306a36Sopenharmony_ci u64 cur_objectid; 128962306a36Sopenharmony_ci u64 cur_offset; 129062306a36Sopenharmony_ci 129162306a36Sopenharmony_ci /* may be truncated in case it's the last extent in a file */ 129262306a36Sopenharmony_ci u64 extent_len; 129362306a36Sopenharmony_ci 129462306a36Sopenharmony_ci /* The bytenr the file extent item we are processing refers to. */ 129562306a36Sopenharmony_ci u64 bytenr; 129662306a36Sopenharmony_ci /* The owner (root id) of the data backref for the current extent. */ 129762306a36Sopenharmony_ci u64 backref_owner; 129862306a36Sopenharmony_ci /* The offset of the data backref for the current extent. */ 129962306a36Sopenharmony_ci u64 backref_offset; 130062306a36Sopenharmony_ci}; 130162306a36Sopenharmony_ci 130262306a36Sopenharmony_cistatic int __clone_root_cmp_bsearch(const void *key, const void *elt) 130362306a36Sopenharmony_ci{ 130462306a36Sopenharmony_ci u64 root = (u64)(uintptr_t)key; 130562306a36Sopenharmony_ci const struct clone_root *cr = elt; 130662306a36Sopenharmony_ci 130762306a36Sopenharmony_ci if (root < cr->root->root_key.objectid) 130862306a36Sopenharmony_ci return -1; 130962306a36Sopenharmony_ci if (root > cr->root->root_key.objectid) 131062306a36Sopenharmony_ci return 1; 131162306a36Sopenharmony_ci return 0; 131262306a36Sopenharmony_ci} 131362306a36Sopenharmony_ci 131462306a36Sopenharmony_cistatic int __clone_root_cmp_sort(const void *e1, const void *e2) 131562306a36Sopenharmony_ci{ 131662306a36Sopenharmony_ci const struct clone_root *cr1 = e1; 131762306a36Sopenharmony_ci const struct clone_root *cr2 = e2; 131862306a36Sopenharmony_ci 131962306a36Sopenharmony_ci if (cr1->root->root_key.objectid < cr2->root->root_key.objectid) 132062306a36Sopenharmony_ci return -1; 132162306a36Sopenharmony_ci if (cr1->root->root_key.objectid > cr2->root->root_key.objectid) 132262306a36Sopenharmony_ci return 1; 132362306a36Sopenharmony_ci return 0; 132462306a36Sopenharmony_ci} 132562306a36Sopenharmony_ci 132662306a36Sopenharmony_ci/* 132762306a36Sopenharmony_ci * Called for every backref that is found for the current extent. 132862306a36Sopenharmony_ci * Results are collected in sctx->clone_roots->ino/offset. 132962306a36Sopenharmony_ci */ 133062306a36Sopenharmony_cistatic int iterate_backrefs(u64 ino, u64 offset, u64 num_bytes, u64 root_id, 133162306a36Sopenharmony_ci void *ctx_) 133262306a36Sopenharmony_ci{ 133362306a36Sopenharmony_ci struct backref_ctx *bctx = ctx_; 133462306a36Sopenharmony_ci struct clone_root *clone_root; 133562306a36Sopenharmony_ci 133662306a36Sopenharmony_ci /* First check if the root is in the list of accepted clone sources */ 133762306a36Sopenharmony_ci clone_root = bsearch((void *)(uintptr_t)root_id, bctx->sctx->clone_roots, 133862306a36Sopenharmony_ci bctx->sctx->clone_roots_cnt, 133962306a36Sopenharmony_ci sizeof(struct clone_root), 134062306a36Sopenharmony_ci __clone_root_cmp_bsearch); 134162306a36Sopenharmony_ci if (!clone_root) 134262306a36Sopenharmony_ci return 0; 134362306a36Sopenharmony_ci 134462306a36Sopenharmony_ci /* This is our own reference, bail out as we can't clone from it. */ 134562306a36Sopenharmony_ci if (clone_root->root == bctx->sctx->send_root && 134662306a36Sopenharmony_ci ino == bctx->cur_objectid && 134762306a36Sopenharmony_ci offset == bctx->cur_offset) 134862306a36Sopenharmony_ci return 0; 134962306a36Sopenharmony_ci 135062306a36Sopenharmony_ci /* 135162306a36Sopenharmony_ci * Make sure we don't consider clones from send_root that are 135262306a36Sopenharmony_ci * behind the current inode/offset. 135362306a36Sopenharmony_ci */ 135462306a36Sopenharmony_ci if (clone_root->root == bctx->sctx->send_root) { 135562306a36Sopenharmony_ci /* 135662306a36Sopenharmony_ci * If the source inode was not yet processed we can't issue a 135762306a36Sopenharmony_ci * clone operation, as the source extent does not exist yet at 135862306a36Sopenharmony_ci * the destination of the stream. 135962306a36Sopenharmony_ci */ 136062306a36Sopenharmony_ci if (ino > bctx->cur_objectid) 136162306a36Sopenharmony_ci return 0; 136262306a36Sopenharmony_ci /* 136362306a36Sopenharmony_ci * We clone from the inode currently being sent as long as the 136462306a36Sopenharmony_ci * source extent is already processed, otherwise we could try 136562306a36Sopenharmony_ci * to clone from an extent that does not exist yet at the 136662306a36Sopenharmony_ci * destination of the stream. 136762306a36Sopenharmony_ci */ 136862306a36Sopenharmony_ci if (ino == bctx->cur_objectid && 136962306a36Sopenharmony_ci offset + bctx->extent_len > 137062306a36Sopenharmony_ci bctx->sctx->cur_inode_next_write_offset) 137162306a36Sopenharmony_ci return 0; 137262306a36Sopenharmony_ci } 137362306a36Sopenharmony_ci 137462306a36Sopenharmony_ci bctx->found++; 137562306a36Sopenharmony_ci clone_root->found_ref = true; 137662306a36Sopenharmony_ci 137762306a36Sopenharmony_ci /* 137862306a36Sopenharmony_ci * If the given backref refers to a file extent item with a larger 137962306a36Sopenharmony_ci * number of bytes than what we found before, use the new one so that 138062306a36Sopenharmony_ci * we clone more optimally and end up doing less writes and getting 138162306a36Sopenharmony_ci * less exclusive, non-shared extents at the destination. 138262306a36Sopenharmony_ci */ 138362306a36Sopenharmony_ci if (num_bytes > clone_root->num_bytes) { 138462306a36Sopenharmony_ci clone_root->ino = ino; 138562306a36Sopenharmony_ci clone_root->offset = offset; 138662306a36Sopenharmony_ci clone_root->num_bytes = num_bytes; 138762306a36Sopenharmony_ci 138862306a36Sopenharmony_ci /* 138962306a36Sopenharmony_ci * Found a perfect candidate, so there's no need to continue 139062306a36Sopenharmony_ci * backref walking. 139162306a36Sopenharmony_ci */ 139262306a36Sopenharmony_ci if (num_bytes >= bctx->extent_len) 139362306a36Sopenharmony_ci return BTRFS_ITERATE_EXTENT_INODES_STOP; 139462306a36Sopenharmony_ci } 139562306a36Sopenharmony_ci 139662306a36Sopenharmony_ci return 0; 139762306a36Sopenharmony_ci} 139862306a36Sopenharmony_ci 139962306a36Sopenharmony_cistatic bool lookup_backref_cache(u64 leaf_bytenr, void *ctx, 140062306a36Sopenharmony_ci const u64 **root_ids_ret, int *root_count_ret) 140162306a36Sopenharmony_ci{ 140262306a36Sopenharmony_ci struct backref_ctx *bctx = ctx; 140362306a36Sopenharmony_ci struct send_ctx *sctx = bctx->sctx; 140462306a36Sopenharmony_ci struct btrfs_fs_info *fs_info = sctx->send_root->fs_info; 140562306a36Sopenharmony_ci const u64 key = leaf_bytenr >> fs_info->sectorsize_bits; 140662306a36Sopenharmony_ci struct btrfs_lru_cache_entry *raw_entry; 140762306a36Sopenharmony_ci struct backref_cache_entry *entry; 140862306a36Sopenharmony_ci 140962306a36Sopenharmony_ci if (btrfs_lru_cache_size(&sctx->backref_cache) == 0) 141062306a36Sopenharmony_ci return false; 141162306a36Sopenharmony_ci 141262306a36Sopenharmony_ci /* 141362306a36Sopenharmony_ci * If relocation happened since we first filled the cache, then we must 141462306a36Sopenharmony_ci * empty the cache and can not use it, because even though we operate on 141562306a36Sopenharmony_ci * read-only roots, their leaves and nodes may have been reallocated and 141662306a36Sopenharmony_ci * now be used for different nodes/leaves of the same tree or some other 141762306a36Sopenharmony_ci * tree. 141862306a36Sopenharmony_ci * 141962306a36Sopenharmony_ci * We are called from iterate_extent_inodes() while either holding a 142062306a36Sopenharmony_ci * transaction handle or holding fs_info->commit_root_sem, so no need 142162306a36Sopenharmony_ci * to take any lock here. 142262306a36Sopenharmony_ci */ 142362306a36Sopenharmony_ci if (fs_info->last_reloc_trans > sctx->backref_cache_last_reloc_trans) { 142462306a36Sopenharmony_ci btrfs_lru_cache_clear(&sctx->backref_cache); 142562306a36Sopenharmony_ci return false; 142662306a36Sopenharmony_ci } 142762306a36Sopenharmony_ci 142862306a36Sopenharmony_ci raw_entry = btrfs_lru_cache_lookup(&sctx->backref_cache, key, 0); 142962306a36Sopenharmony_ci if (!raw_entry) 143062306a36Sopenharmony_ci return false; 143162306a36Sopenharmony_ci 143262306a36Sopenharmony_ci entry = container_of(raw_entry, struct backref_cache_entry, entry); 143362306a36Sopenharmony_ci *root_ids_ret = entry->root_ids; 143462306a36Sopenharmony_ci *root_count_ret = entry->num_roots; 143562306a36Sopenharmony_ci 143662306a36Sopenharmony_ci return true; 143762306a36Sopenharmony_ci} 143862306a36Sopenharmony_ci 143962306a36Sopenharmony_cistatic void store_backref_cache(u64 leaf_bytenr, const struct ulist *root_ids, 144062306a36Sopenharmony_ci void *ctx) 144162306a36Sopenharmony_ci{ 144262306a36Sopenharmony_ci struct backref_ctx *bctx = ctx; 144362306a36Sopenharmony_ci struct send_ctx *sctx = bctx->sctx; 144462306a36Sopenharmony_ci struct btrfs_fs_info *fs_info = sctx->send_root->fs_info; 144562306a36Sopenharmony_ci struct backref_cache_entry *new_entry; 144662306a36Sopenharmony_ci struct ulist_iterator uiter; 144762306a36Sopenharmony_ci struct ulist_node *node; 144862306a36Sopenharmony_ci int ret; 144962306a36Sopenharmony_ci 145062306a36Sopenharmony_ci /* 145162306a36Sopenharmony_ci * We're called while holding a transaction handle or while holding 145262306a36Sopenharmony_ci * fs_info->commit_root_sem (at iterate_extent_inodes()), so must do a 145362306a36Sopenharmony_ci * NOFS allocation. 145462306a36Sopenharmony_ci */ 145562306a36Sopenharmony_ci new_entry = kmalloc(sizeof(struct backref_cache_entry), GFP_NOFS); 145662306a36Sopenharmony_ci /* No worries, cache is optional. */ 145762306a36Sopenharmony_ci if (!new_entry) 145862306a36Sopenharmony_ci return; 145962306a36Sopenharmony_ci 146062306a36Sopenharmony_ci new_entry->entry.key = leaf_bytenr >> fs_info->sectorsize_bits; 146162306a36Sopenharmony_ci new_entry->entry.gen = 0; 146262306a36Sopenharmony_ci new_entry->num_roots = 0; 146362306a36Sopenharmony_ci ULIST_ITER_INIT(&uiter); 146462306a36Sopenharmony_ci while ((node = ulist_next(root_ids, &uiter)) != NULL) { 146562306a36Sopenharmony_ci const u64 root_id = node->val; 146662306a36Sopenharmony_ci struct clone_root *root; 146762306a36Sopenharmony_ci 146862306a36Sopenharmony_ci root = bsearch((void *)(uintptr_t)root_id, sctx->clone_roots, 146962306a36Sopenharmony_ci sctx->clone_roots_cnt, sizeof(struct clone_root), 147062306a36Sopenharmony_ci __clone_root_cmp_bsearch); 147162306a36Sopenharmony_ci if (!root) 147262306a36Sopenharmony_ci continue; 147362306a36Sopenharmony_ci 147462306a36Sopenharmony_ci /* Too many roots, just exit, no worries as caching is optional. */ 147562306a36Sopenharmony_ci if (new_entry->num_roots >= SEND_MAX_BACKREF_CACHE_ROOTS) { 147662306a36Sopenharmony_ci kfree(new_entry); 147762306a36Sopenharmony_ci return; 147862306a36Sopenharmony_ci } 147962306a36Sopenharmony_ci 148062306a36Sopenharmony_ci new_entry->root_ids[new_entry->num_roots] = root_id; 148162306a36Sopenharmony_ci new_entry->num_roots++; 148262306a36Sopenharmony_ci } 148362306a36Sopenharmony_ci 148462306a36Sopenharmony_ci /* 148562306a36Sopenharmony_ci * We may have not added any roots to the new cache entry, which means 148662306a36Sopenharmony_ci * none of the roots is part of the list of roots from which we are 148762306a36Sopenharmony_ci * allowed to clone. Cache the new entry as it's still useful to avoid 148862306a36Sopenharmony_ci * backref walking to determine which roots have a path to the leaf. 148962306a36Sopenharmony_ci * 149062306a36Sopenharmony_ci * Also use GFP_NOFS because we're called while holding a transaction 149162306a36Sopenharmony_ci * handle or while holding fs_info->commit_root_sem. 149262306a36Sopenharmony_ci */ 149362306a36Sopenharmony_ci ret = btrfs_lru_cache_store(&sctx->backref_cache, &new_entry->entry, 149462306a36Sopenharmony_ci GFP_NOFS); 149562306a36Sopenharmony_ci ASSERT(ret == 0 || ret == -ENOMEM); 149662306a36Sopenharmony_ci if (ret) { 149762306a36Sopenharmony_ci /* Caching is optional, no worries. */ 149862306a36Sopenharmony_ci kfree(new_entry); 149962306a36Sopenharmony_ci return; 150062306a36Sopenharmony_ci } 150162306a36Sopenharmony_ci 150262306a36Sopenharmony_ci /* 150362306a36Sopenharmony_ci * We are called from iterate_extent_inodes() while either holding a 150462306a36Sopenharmony_ci * transaction handle or holding fs_info->commit_root_sem, so no need 150562306a36Sopenharmony_ci * to take any lock here. 150662306a36Sopenharmony_ci */ 150762306a36Sopenharmony_ci if (btrfs_lru_cache_size(&sctx->backref_cache) == 1) 150862306a36Sopenharmony_ci sctx->backref_cache_last_reloc_trans = fs_info->last_reloc_trans; 150962306a36Sopenharmony_ci} 151062306a36Sopenharmony_ci 151162306a36Sopenharmony_cistatic int check_extent_item(u64 bytenr, const struct btrfs_extent_item *ei, 151262306a36Sopenharmony_ci const struct extent_buffer *leaf, void *ctx) 151362306a36Sopenharmony_ci{ 151462306a36Sopenharmony_ci const u64 refs = btrfs_extent_refs(leaf, ei); 151562306a36Sopenharmony_ci const struct backref_ctx *bctx = ctx; 151662306a36Sopenharmony_ci const struct send_ctx *sctx = bctx->sctx; 151762306a36Sopenharmony_ci 151862306a36Sopenharmony_ci if (bytenr == bctx->bytenr) { 151962306a36Sopenharmony_ci const u64 flags = btrfs_extent_flags(leaf, ei); 152062306a36Sopenharmony_ci 152162306a36Sopenharmony_ci if (WARN_ON(flags & BTRFS_EXTENT_FLAG_TREE_BLOCK)) 152262306a36Sopenharmony_ci return -EUCLEAN; 152362306a36Sopenharmony_ci 152462306a36Sopenharmony_ci /* 152562306a36Sopenharmony_ci * If we have only one reference and only the send root as a 152662306a36Sopenharmony_ci * clone source - meaning no clone roots were given in the 152762306a36Sopenharmony_ci * struct btrfs_ioctl_send_args passed to the send ioctl - then 152862306a36Sopenharmony_ci * it's our reference and there's no point in doing backref 152962306a36Sopenharmony_ci * walking which is expensive, so exit early. 153062306a36Sopenharmony_ci */ 153162306a36Sopenharmony_ci if (refs == 1 && sctx->clone_roots_cnt == 1) 153262306a36Sopenharmony_ci return -ENOENT; 153362306a36Sopenharmony_ci } 153462306a36Sopenharmony_ci 153562306a36Sopenharmony_ci /* 153662306a36Sopenharmony_ci * Backreference walking (iterate_extent_inodes() below) is currently 153762306a36Sopenharmony_ci * too expensive when an extent has a large number of references, both 153862306a36Sopenharmony_ci * in time spent and used memory. So for now just fallback to write 153962306a36Sopenharmony_ci * operations instead of clone operations when an extent has more than 154062306a36Sopenharmony_ci * a certain amount of references. 154162306a36Sopenharmony_ci */ 154262306a36Sopenharmony_ci if (refs > SEND_MAX_EXTENT_REFS) 154362306a36Sopenharmony_ci return -ENOENT; 154462306a36Sopenharmony_ci 154562306a36Sopenharmony_ci return 0; 154662306a36Sopenharmony_ci} 154762306a36Sopenharmony_ci 154862306a36Sopenharmony_cistatic bool skip_self_data_ref(u64 root, u64 ino, u64 offset, void *ctx) 154962306a36Sopenharmony_ci{ 155062306a36Sopenharmony_ci const struct backref_ctx *bctx = ctx; 155162306a36Sopenharmony_ci 155262306a36Sopenharmony_ci if (ino == bctx->cur_objectid && 155362306a36Sopenharmony_ci root == bctx->backref_owner && 155462306a36Sopenharmony_ci offset == bctx->backref_offset) 155562306a36Sopenharmony_ci return true; 155662306a36Sopenharmony_ci 155762306a36Sopenharmony_ci return false; 155862306a36Sopenharmony_ci} 155962306a36Sopenharmony_ci 156062306a36Sopenharmony_ci/* 156162306a36Sopenharmony_ci * Given an inode, offset and extent item, it finds a good clone for a clone 156262306a36Sopenharmony_ci * instruction. Returns -ENOENT when none could be found. The function makes 156362306a36Sopenharmony_ci * sure that the returned clone is usable at the point where sending is at the 156462306a36Sopenharmony_ci * moment. This means, that no clones are accepted which lie behind the current 156562306a36Sopenharmony_ci * inode+offset. 156662306a36Sopenharmony_ci * 156762306a36Sopenharmony_ci * path must point to the extent item when called. 156862306a36Sopenharmony_ci */ 156962306a36Sopenharmony_cistatic int find_extent_clone(struct send_ctx *sctx, 157062306a36Sopenharmony_ci struct btrfs_path *path, 157162306a36Sopenharmony_ci u64 ino, u64 data_offset, 157262306a36Sopenharmony_ci u64 ino_size, 157362306a36Sopenharmony_ci struct clone_root **found) 157462306a36Sopenharmony_ci{ 157562306a36Sopenharmony_ci struct btrfs_fs_info *fs_info = sctx->send_root->fs_info; 157662306a36Sopenharmony_ci int ret; 157762306a36Sopenharmony_ci int extent_type; 157862306a36Sopenharmony_ci u64 logical; 157962306a36Sopenharmony_ci u64 disk_byte; 158062306a36Sopenharmony_ci u64 num_bytes; 158162306a36Sopenharmony_ci struct btrfs_file_extent_item *fi; 158262306a36Sopenharmony_ci struct extent_buffer *eb = path->nodes[0]; 158362306a36Sopenharmony_ci struct backref_ctx backref_ctx = { 0 }; 158462306a36Sopenharmony_ci struct btrfs_backref_walk_ctx backref_walk_ctx = { 0 }; 158562306a36Sopenharmony_ci struct clone_root *cur_clone_root; 158662306a36Sopenharmony_ci int compressed; 158762306a36Sopenharmony_ci u32 i; 158862306a36Sopenharmony_ci 158962306a36Sopenharmony_ci /* 159062306a36Sopenharmony_ci * With fallocate we can get prealloc extents beyond the inode's i_size, 159162306a36Sopenharmony_ci * so we don't do anything here because clone operations can not clone 159262306a36Sopenharmony_ci * to a range beyond i_size without increasing the i_size of the 159362306a36Sopenharmony_ci * destination inode. 159462306a36Sopenharmony_ci */ 159562306a36Sopenharmony_ci if (data_offset >= ino_size) 159662306a36Sopenharmony_ci return 0; 159762306a36Sopenharmony_ci 159862306a36Sopenharmony_ci fi = btrfs_item_ptr(eb, path->slots[0], struct btrfs_file_extent_item); 159962306a36Sopenharmony_ci extent_type = btrfs_file_extent_type(eb, fi); 160062306a36Sopenharmony_ci if (extent_type == BTRFS_FILE_EXTENT_INLINE) 160162306a36Sopenharmony_ci return -ENOENT; 160262306a36Sopenharmony_ci 160362306a36Sopenharmony_ci disk_byte = btrfs_file_extent_disk_bytenr(eb, fi); 160462306a36Sopenharmony_ci if (disk_byte == 0) 160562306a36Sopenharmony_ci return -ENOENT; 160662306a36Sopenharmony_ci 160762306a36Sopenharmony_ci compressed = btrfs_file_extent_compression(eb, fi); 160862306a36Sopenharmony_ci num_bytes = btrfs_file_extent_num_bytes(eb, fi); 160962306a36Sopenharmony_ci logical = disk_byte + btrfs_file_extent_offset(eb, fi); 161062306a36Sopenharmony_ci 161162306a36Sopenharmony_ci /* 161262306a36Sopenharmony_ci * Setup the clone roots. 161362306a36Sopenharmony_ci */ 161462306a36Sopenharmony_ci for (i = 0; i < sctx->clone_roots_cnt; i++) { 161562306a36Sopenharmony_ci cur_clone_root = sctx->clone_roots + i; 161662306a36Sopenharmony_ci cur_clone_root->ino = (u64)-1; 161762306a36Sopenharmony_ci cur_clone_root->offset = 0; 161862306a36Sopenharmony_ci cur_clone_root->num_bytes = 0; 161962306a36Sopenharmony_ci cur_clone_root->found_ref = false; 162062306a36Sopenharmony_ci } 162162306a36Sopenharmony_ci 162262306a36Sopenharmony_ci backref_ctx.sctx = sctx; 162362306a36Sopenharmony_ci backref_ctx.cur_objectid = ino; 162462306a36Sopenharmony_ci backref_ctx.cur_offset = data_offset; 162562306a36Sopenharmony_ci backref_ctx.bytenr = disk_byte; 162662306a36Sopenharmony_ci /* 162762306a36Sopenharmony_ci * Use the header owner and not the send root's id, because in case of a 162862306a36Sopenharmony_ci * snapshot we can have shared subtrees. 162962306a36Sopenharmony_ci */ 163062306a36Sopenharmony_ci backref_ctx.backref_owner = btrfs_header_owner(eb); 163162306a36Sopenharmony_ci backref_ctx.backref_offset = data_offset - btrfs_file_extent_offset(eb, fi); 163262306a36Sopenharmony_ci 163362306a36Sopenharmony_ci /* 163462306a36Sopenharmony_ci * The last extent of a file may be too large due to page alignment. 163562306a36Sopenharmony_ci * We need to adjust extent_len in this case so that the checks in 163662306a36Sopenharmony_ci * iterate_backrefs() work. 163762306a36Sopenharmony_ci */ 163862306a36Sopenharmony_ci if (data_offset + num_bytes >= ino_size) 163962306a36Sopenharmony_ci backref_ctx.extent_len = ino_size - data_offset; 164062306a36Sopenharmony_ci else 164162306a36Sopenharmony_ci backref_ctx.extent_len = num_bytes; 164262306a36Sopenharmony_ci 164362306a36Sopenharmony_ci /* 164462306a36Sopenharmony_ci * Now collect all backrefs. 164562306a36Sopenharmony_ci */ 164662306a36Sopenharmony_ci backref_walk_ctx.bytenr = disk_byte; 164762306a36Sopenharmony_ci if (compressed == BTRFS_COMPRESS_NONE) 164862306a36Sopenharmony_ci backref_walk_ctx.extent_item_pos = btrfs_file_extent_offset(eb, fi); 164962306a36Sopenharmony_ci backref_walk_ctx.fs_info = fs_info; 165062306a36Sopenharmony_ci backref_walk_ctx.cache_lookup = lookup_backref_cache; 165162306a36Sopenharmony_ci backref_walk_ctx.cache_store = store_backref_cache; 165262306a36Sopenharmony_ci backref_walk_ctx.indirect_ref_iterator = iterate_backrefs; 165362306a36Sopenharmony_ci backref_walk_ctx.check_extent_item = check_extent_item; 165462306a36Sopenharmony_ci backref_walk_ctx.user_ctx = &backref_ctx; 165562306a36Sopenharmony_ci 165662306a36Sopenharmony_ci /* 165762306a36Sopenharmony_ci * If have a single clone root, then it's the send root and we can tell 165862306a36Sopenharmony_ci * the backref walking code to skip our own backref and not resolve it, 165962306a36Sopenharmony_ci * since we can not use it for cloning - the source and destination 166062306a36Sopenharmony_ci * ranges can't overlap and in case the leaf is shared through a subtree 166162306a36Sopenharmony_ci * due to snapshots, we can't use those other roots since they are not 166262306a36Sopenharmony_ci * in the list of clone roots. 166362306a36Sopenharmony_ci */ 166462306a36Sopenharmony_ci if (sctx->clone_roots_cnt == 1) 166562306a36Sopenharmony_ci backref_walk_ctx.skip_data_ref = skip_self_data_ref; 166662306a36Sopenharmony_ci 166762306a36Sopenharmony_ci ret = iterate_extent_inodes(&backref_walk_ctx, true, iterate_backrefs, 166862306a36Sopenharmony_ci &backref_ctx); 166962306a36Sopenharmony_ci if (ret < 0) 167062306a36Sopenharmony_ci return ret; 167162306a36Sopenharmony_ci 167262306a36Sopenharmony_ci down_read(&fs_info->commit_root_sem); 167362306a36Sopenharmony_ci if (fs_info->last_reloc_trans > sctx->last_reloc_trans) { 167462306a36Sopenharmony_ci /* 167562306a36Sopenharmony_ci * A transaction commit for a transaction in which block group 167662306a36Sopenharmony_ci * relocation was done just happened. 167762306a36Sopenharmony_ci * The disk_bytenr of the file extent item we processed is 167862306a36Sopenharmony_ci * possibly stale, referring to the extent's location before 167962306a36Sopenharmony_ci * relocation. So act as if we haven't found any clone sources 168062306a36Sopenharmony_ci * and fallback to write commands, which will read the correct 168162306a36Sopenharmony_ci * data from the new extent location. Otherwise we will fail 168262306a36Sopenharmony_ci * below because we haven't found our own back reference or we 168362306a36Sopenharmony_ci * could be getting incorrect sources in case the old extent 168462306a36Sopenharmony_ci * was already reallocated after the relocation. 168562306a36Sopenharmony_ci */ 168662306a36Sopenharmony_ci up_read(&fs_info->commit_root_sem); 168762306a36Sopenharmony_ci return -ENOENT; 168862306a36Sopenharmony_ci } 168962306a36Sopenharmony_ci up_read(&fs_info->commit_root_sem); 169062306a36Sopenharmony_ci 169162306a36Sopenharmony_ci btrfs_debug(fs_info, 169262306a36Sopenharmony_ci "find_extent_clone: data_offset=%llu, ino=%llu, num_bytes=%llu, logical=%llu", 169362306a36Sopenharmony_ci data_offset, ino, num_bytes, logical); 169462306a36Sopenharmony_ci 169562306a36Sopenharmony_ci if (!backref_ctx.found) { 169662306a36Sopenharmony_ci btrfs_debug(fs_info, "no clones found"); 169762306a36Sopenharmony_ci return -ENOENT; 169862306a36Sopenharmony_ci } 169962306a36Sopenharmony_ci 170062306a36Sopenharmony_ci cur_clone_root = NULL; 170162306a36Sopenharmony_ci for (i = 0; i < sctx->clone_roots_cnt; i++) { 170262306a36Sopenharmony_ci struct clone_root *clone_root = &sctx->clone_roots[i]; 170362306a36Sopenharmony_ci 170462306a36Sopenharmony_ci if (!clone_root->found_ref) 170562306a36Sopenharmony_ci continue; 170662306a36Sopenharmony_ci 170762306a36Sopenharmony_ci /* 170862306a36Sopenharmony_ci * Choose the root from which we can clone more bytes, to 170962306a36Sopenharmony_ci * minimize write operations and therefore have more extent 171062306a36Sopenharmony_ci * sharing at the destination (the same as in the source). 171162306a36Sopenharmony_ci */ 171262306a36Sopenharmony_ci if (!cur_clone_root || 171362306a36Sopenharmony_ci clone_root->num_bytes > cur_clone_root->num_bytes) { 171462306a36Sopenharmony_ci cur_clone_root = clone_root; 171562306a36Sopenharmony_ci 171662306a36Sopenharmony_ci /* 171762306a36Sopenharmony_ci * We found an optimal clone candidate (any inode from 171862306a36Sopenharmony_ci * any root is fine), so we're done. 171962306a36Sopenharmony_ci */ 172062306a36Sopenharmony_ci if (clone_root->num_bytes >= backref_ctx.extent_len) 172162306a36Sopenharmony_ci break; 172262306a36Sopenharmony_ci } 172362306a36Sopenharmony_ci } 172462306a36Sopenharmony_ci 172562306a36Sopenharmony_ci if (cur_clone_root) { 172662306a36Sopenharmony_ci *found = cur_clone_root; 172762306a36Sopenharmony_ci ret = 0; 172862306a36Sopenharmony_ci } else { 172962306a36Sopenharmony_ci ret = -ENOENT; 173062306a36Sopenharmony_ci } 173162306a36Sopenharmony_ci 173262306a36Sopenharmony_ci return ret; 173362306a36Sopenharmony_ci} 173462306a36Sopenharmony_ci 173562306a36Sopenharmony_cistatic int read_symlink(struct btrfs_root *root, 173662306a36Sopenharmony_ci u64 ino, 173762306a36Sopenharmony_ci struct fs_path *dest) 173862306a36Sopenharmony_ci{ 173962306a36Sopenharmony_ci int ret; 174062306a36Sopenharmony_ci struct btrfs_path *path; 174162306a36Sopenharmony_ci struct btrfs_key key; 174262306a36Sopenharmony_ci struct btrfs_file_extent_item *ei; 174362306a36Sopenharmony_ci u8 type; 174462306a36Sopenharmony_ci u8 compression; 174562306a36Sopenharmony_ci unsigned long off; 174662306a36Sopenharmony_ci int len; 174762306a36Sopenharmony_ci 174862306a36Sopenharmony_ci path = alloc_path_for_send(); 174962306a36Sopenharmony_ci if (!path) 175062306a36Sopenharmony_ci return -ENOMEM; 175162306a36Sopenharmony_ci 175262306a36Sopenharmony_ci key.objectid = ino; 175362306a36Sopenharmony_ci key.type = BTRFS_EXTENT_DATA_KEY; 175462306a36Sopenharmony_ci key.offset = 0; 175562306a36Sopenharmony_ci ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); 175662306a36Sopenharmony_ci if (ret < 0) 175762306a36Sopenharmony_ci goto out; 175862306a36Sopenharmony_ci if (ret) { 175962306a36Sopenharmony_ci /* 176062306a36Sopenharmony_ci * An empty symlink inode. Can happen in rare error paths when 176162306a36Sopenharmony_ci * creating a symlink (transaction committed before the inode 176262306a36Sopenharmony_ci * eviction handler removed the symlink inode items and a crash 176362306a36Sopenharmony_ci * happened in between or the subvol was snapshoted in between). 176462306a36Sopenharmony_ci * Print an informative message to dmesg/syslog so that the user 176562306a36Sopenharmony_ci * can delete the symlink. 176662306a36Sopenharmony_ci */ 176762306a36Sopenharmony_ci btrfs_err(root->fs_info, 176862306a36Sopenharmony_ci "Found empty symlink inode %llu at root %llu", 176962306a36Sopenharmony_ci ino, root->root_key.objectid); 177062306a36Sopenharmony_ci ret = -EIO; 177162306a36Sopenharmony_ci goto out; 177262306a36Sopenharmony_ci } 177362306a36Sopenharmony_ci 177462306a36Sopenharmony_ci ei = btrfs_item_ptr(path->nodes[0], path->slots[0], 177562306a36Sopenharmony_ci struct btrfs_file_extent_item); 177662306a36Sopenharmony_ci type = btrfs_file_extent_type(path->nodes[0], ei); 177762306a36Sopenharmony_ci if (unlikely(type != BTRFS_FILE_EXTENT_INLINE)) { 177862306a36Sopenharmony_ci ret = -EUCLEAN; 177962306a36Sopenharmony_ci btrfs_crit(root->fs_info, 178062306a36Sopenharmony_ci"send: found symlink extent that is not inline, ino %llu root %llu extent type %d", 178162306a36Sopenharmony_ci ino, btrfs_root_id(root), type); 178262306a36Sopenharmony_ci goto out; 178362306a36Sopenharmony_ci } 178462306a36Sopenharmony_ci compression = btrfs_file_extent_compression(path->nodes[0], ei); 178562306a36Sopenharmony_ci if (unlikely(compression != BTRFS_COMPRESS_NONE)) { 178662306a36Sopenharmony_ci ret = -EUCLEAN; 178762306a36Sopenharmony_ci btrfs_crit(root->fs_info, 178862306a36Sopenharmony_ci"send: found symlink extent with compression, ino %llu root %llu compression type %d", 178962306a36Sopenharmony_ci ino, btrfs_root_id(root), compression); 179062306a36Sopenharmony_ci goto out; 179162306a36Sopenharmony_ci } 179262306a36Sopenharmony_ci 179362306a36Sopenharmony_ci off = btrfs_file_extent_inline_start(ei); 179462306a36Sopenharmony_ci len = btrfs_file_extent_ram_bytes(path->nodes[0], ei); 179562306a36Sopenharmony_ci 179662306a36Sopenharmony_ci ret = fs_path_add_from_extent_buffer(dest, path->nodes[0], off, len); 179762306a36Sopenharmony_ci 179862306a36Sopenharmony_ciout: 179962306a36Sopenharmony_ci btrfs_free_path(path); 180062306a36Sopenharmony_ci return ret; 180162306a36Sopenharmony_ci} 180262306a36Sopenharmony_ci 180362306a36Sopenharmony_ci/* 180462306a36Sopenharmony_ci * Helper function to generate a file name that is unique in the root of 180562306a36Sopenharmony_ci * send_root and parent_root. This is used to generate names for orphan inodes. 180662306a36Sopenharmony_ci */ 180762306a36Sopenharmony_cistatic int gen_unique_name(struct send_ctx *sctx, 180862306a36Sopenharmony_ci u64 ino, u64 gen, 180962306a36Sopenharmony_ci struct fs_path *dest) 181062306a36Sopenharmony_ci{ 181162306a36Sopenharmony_ci int ret = 0; 181262306a36Sopenharmony_ci struct btrfs_path *path; 181362306a36Sopenharmony_ci struct btrfs_dir_item *di; 181462306a36Sopenharmony_ci char tmp[64]; 181562306a36Sopenharmony_ci int len; 181662306a36Sopenharmony_ci u64 idx = 0; 181762306a36Sopenharmony_ci 181862306a36Sopenharmony_ci path = alloc_path_for_send(); 181962306a36Sopenharmony_ci if (!path) 182062306a36Sopenharmony_ci return -ENOMEM; 182162306a36Sopenharmony_ci 182262306a36Sopenharmony_ci while (1) { 182362306a36Sopenharmony_ci struct fscrypt_str tmp_name; 182462306a36Sopenharmony_ci 182562306a36Sopenharmony_ci len = snprintf(tmp, sizeof(tmp), "o%llu-%llu-%llu", 182662306a36Sopenharmony_ci ino, gen, idx); 182762306a36Sopenharmony_ci ASSERT(len < sizeof(tmp)); 182862306a36Sopenharmony_ci tmp_name.name = tmp; 182962306a36Sopenharmony_ci tmp_name.len = strlen(tmp); 183062306a36Sopenharmony_ci 183162306a36Sopenharmony_ci di = btrfs_lookup_dir_item(NULL, sctx->send_root, 183262306a36Sopenharmony_ci path, BTRFS_FIRST_FREE_OBJECTID, 183362306a36Sopenharmony_ci &tmp_name, 0); 183462306a36Sopenharmony_ci btrfs_release_path(path); 183562306a36Sopenharmony_ci if (IS_ERR(di)) { 183662306a36Sopenharmony_ci ret = PTR_ERR(di); 183762306a36Sopenharmony_ci goto out; 183862306a36Sopenharmony_ci } 183962306a36Sopenharmony_ci if (di) { 184062306a36Sopenharmony_ci /* not unique, try again */ 184162306a36Sopenharmony_ci idx++; 184262306a36Sopenharmony_ci continue; 184362306a36Sopenharmony_ci } 184462306a36Sopenharmony_ci 184562306a36Sopenharmony_ci if (!sctx->parent_root) { 184662306a36Sopenharmony_ci /* unique */ 184762306a36Sopenharmony_ci ret = 0; 184862306a36Sopenharmony_ci break; 184962306a36Sopenharmony_ci } 185062306a36Sopenharmony_ci 185162306a36Sopenharmony_ci di = btrfs_lookup_dir_item(NULL, sctx->parent_root, 185262306a36Sopenharmony_ci path, BTRFS_FIRST_FREE_OBJECTID, 185362306a36Sopenharmony_ci &tmp_name, 0); 185462306a36Sopenharmony_ci btrfs_release_path(path); 185562306a36Sopenharmony_ci if (IS_ERR(di)) { 185662306a36Sopenharmony_ci ret = PTR_ERR(di); 185762306a36Sopenharmony_ci goto out; 185862306a36Sopenharmony_ci } 185962306a36Sopenharmony_ci if (di) { 186062306a36Sopenharmony_ci /* not unique, try again */ 186162306a36Sopenharmony_ci idx++; 186262306a36Sopenharmony_ci continue; 186362306a36Sopenharmony_ci } 186462306a36Sopenharmony_ci /* unique */ 186562306a36Sopenharmony_ci break; 186662306a36Sopenharmony_ci } 186762306a36Sopenharmony_ci 186862306a36Sopenharmony_ci ret = fs_path_add(dest, tmp, strlen(tmp)); 186962306a36Sopenharmony_ci 187062306a36Sopenharmony_ciout: 187162306a36Sopenharmony_ci btrfs_free_path(path); 187262306a36Sopenharmony_ci return ret; 187362306a36Sopenharmony_ci} 187462306a36Sopenharmony_ci 187562306a36Sopenharmony_cienum inode_state { 187662306a36Sopenharmony_ci inode_state_no_change, 187762306a36Sopenharmony_ci inode_state_will_create, 187862306a36Sopenharmony_ci inode_state_did_create, 187962306a36Sopenharmony_ci inode_state_will_delete, 188062306a36Sopenharmony_ci inode_state_did_delete, 188162306a36Sopenharmony_ci}; 188262306a36Sopenharmony_ci 188362306a36Sopenharmony_cistatic int get_cur_inode_state(struct send_ctx *sctx, u64 ino, u64 gen, 188462306a36Sopenharmony_ci u64 *send_gen, u64 *parent_gen) 188562306a36Sopenharmony_ci{ 188662306a36Sopenharmony_ci int ret; 188762306a36Sopenharmony_ci int left_ret; 188862306a36Sopenharmony_ci int right_ret; 188962306a36Sopenharmony_ci u64 left_gen; 189062306a36Sopenharmony_ci u64 right_gen = 0; 189162306a36Sopenharmony_ci struct btrfs_inode_info info; 189262306a36Sopenharmony_ci 189362306a36Sopenharmony_ci ret = get_inode_info(sctx->send_root, ino, &info); 189462306a36Sopenharmony_ci if (ret < 0 && ret != -ENOENT) 189562306a36Sopenharmony_ci goto out; 189662306a36Sopenharmony_ci left_ret = (info.nlink == 0) ? -ENOENT : ret; 189762306a36Sopenharmony_ci left_gen = info.gen; 189862306a36Sopenharmony_ci if (send_gen) 189962306a36Sopenharmony_ci *send_gen = ((left_ret == -ENOENT) ? 0 : info.gen); 190062306a36Sopenharmony_ci 190162306a36Sopenharmony_ci if (!sctx->parent_root) { 190262306a36Sopenharmony_ci right_ret = -ENOENT; 190362306a36Sopenharmony_ci } else { 190462306a36Sopenharmony_ci ret = get_inode_info(sctx->parent_root, ino, &info); 190562306a36Sopenharmony_ci if (ret < 0 && ret != -ENOENT) 190662306a36Sopenharmony_ci goto out; 190762306a36Sopenharmony_ci right_ret = (info.nlink == 0) ? -ENOENT : ret; 190862306a36Sopenharmony_ci right_gen = info.gen; 190962306a36Sopenharmony_ci if (parent_gen) 191062306a36Sopenharmony_ci *parent_gen = ((right_ret == -ENOENT) ? 0 : info.gen); 191162306a36Sopenharmony_ci } 191262306a36Sopenharmony_ci 191362306a36Sopenharmony_ci if (!left_ret && !right_ret) { 191462306a36Sopenharmony_ci if (left_gen == gen && right_gen == gen) { 191562306a36Sopenharmony_ci ret = inode_state_no_change; 191662306a36Sopenharmony_ci } else if (left_gen == gen) { 191762306a36Sopenharmony_ci if (ino < sctx->send_progress) 191862306a36Sopenharmony_ci ret = inode_state_did_create; 191962306a36Sopenharmony_ci else 192062306a36Sopenharmony_ci ret = inode_state_will_create; 192162306a36Sopenharmony_ci } else if (right_gen == gen) { 192262306a36Sopenharmony_ci if (ino < sctx->send_progress) 192362306a36Sopenharmony_ci ret = inode_state_did_delete; 192462306a36Sopenharmony_ci else 192562306a36Sopenharmony_ci ret = inode_state_will_delete; 192662306a36Sopenharmony_ci } else { 192762306a36Sopenharmony_ci ret = -ENOENT; 192862306a36Sopenharmony_ci } 192962306a36Sopenharmony_ci } else if (!left_ret) { 193062306a36Sopenharmony_ci if (left_gen == gen) { 193162306a36Sopenharmony_ci if (ino < sctx->send_progress) 193262306a36Sopenharmony_ci ret = inode_state_did_create; 193362306a36Sopenharmony_ci else 193462306a36Sopenharmony_ci ret = inode_state_will_create; 193562306a36Sopenharmony_ci } else { 193662306a36Sopenharmony_ci ret = -ENOENT; 193762306a36Sopenharmony_ci } 193862306a36Sopenharmony_ci } else if (!right_ret) { 193962306a36Sopenharmony_ci if (right_gen == gen) { 194062306a36Sopenharmony_ci if (ino < sctx->send_progress) 194162306a36Sopenharmony_ci ret = inode_state_did_delete; 194262306a36Sopenharmony_ci else 194362306a36Sopenharmony_ci ret = inode_state_will_delete; 194462306a36Sopenharmony_ci } else { 194562306a36Sopenharmony_ci ret = -ENOENT; 194662306a36Sopenharmony_ci } 194762306a36Sopenharmony_ci } else { 194862306a36Sopenharmony_ci ret = -ENOENT; 194962306a36Sopenharmony_ci } 195062306a36Sopenharmony_ci 195162306a36Sopenharmony_ciout: 195262306a36Sopenharmony_ci return ret; 195362306a36Sopenharmony_ci} 195462306a36Sopenharmony_ci 195562306a36Sopenharmony_cistatic int is_inode_existent(struct send_ctx *sctx, u64 ino, u64 gen, 195662306a36Sopenharmony_ci u64 *send_gen, u64 *parent_gen) 195762306a36Sopenharmony_ci{ 195862306a36Sopenharmony_ci int ret; 195962306a36Sopenharmony_ci 196062306a36Sopenharmony_ci if (ino == BTRFS_FIRST_FREE_OBJECTID) 196162306a36Sopenharmony_ci return 1; 196262306a36Sopenharmony_ci 196362306a36Sopenharmony_ci ret = get_cur_inode_state(sctx, ino, gen, send_gen, parent_gen); 196462306a36Sopenharmony_ci if (ret < 0) 196562306a36Sopenharmony_ci goto out; 196662306a36Sopenharmony_ci 196762306a36Sopenharmony_ci if (ret == inode_state_no_change || 196862306a36Sopenharmony_ci ret == inode_state_did_create || 196962306a36Sopenharmony_ci ret == inode_state_will_delete) 197062306a36Sopenharmony_ci ret = 1; 197162306a36Sopenharmony_ci else 197262306a36Sopenharmony_ci ret = 0; 197362306a36Sopenharmony_ci 197462306a36Sopenharmony_ciout: 197562306a36Sopenharmony_ci return ret; 197662306a36Sopenharmony_ci} 197762306a36Sopenharmony_ci 197862306a36Sopenharmony_ci/* 197962306a36Sopenharmony_ci * Helper function to lookup a dir item in a dir. 198062306a36Sopenharmony_ci */ 198162306a36Sopenharmony_cistatic int lookup_dir_item_inode(struct btrfs_root *root, 198262306a36Sopenharmony_ci u64 dir, const char *name, int name_len, 198362306a36Sopenharmony_ci u64 *found_inode) 198462306a36Sopenharmony_ci{ 198562306a36Sopenharmony_ci int ret = 0; 198662306a36Sopenharmony_ci struct btrfs_dir_item *di; 198762306a36Sopenharmony_ci struct btrfs_key key; 198862306a36Sopenharmony_ci struct btrfs_path *path; 198962306a36Sopenharmony_ci struct fscrypt_str name_str = FSTR_INIT((char *)name, name_len); 199062306a36Sopenharmony_ci 199162306a36Sopenharmony_ci path = alloc_path_for_send(); 199262306a36Sopenharmony_ci if (!path) 199362306a36Sopenharmony_ci return -ENOMEM; 199462306a36Sopenharmony_ci 199562306a36Sopenharmony_ci di = btrfs_lookup_dir_item(NULL, root, path, dir, &name_str, 0); 199662306a36Sopenharmony_ci if (IS_ERR_OR_NULL(di)) { 199762306a36Sopenharmony_ci ret = di ? PTR_ERR(di) : -ENOENT; 199862306a36Sopenharmony_ci goto out; 199962306a36Sopenharmony_ci } 200062306a36Sopenharmony_ci btrfs_dir_item_key_to_cpu(path->nodes[0], di, &key); 200162306a36Sopenharmony_ci if (key.type == BTRFS_ROOT_ITEM_KEY) { 200262306a36Sopenharmony_ci ret = -ENOENT; 200362306a36Sopenharmony_ci goto out; 200462306a36Sopenharmony_ci } 200562306a36Sopenharmony_ci *found_inode = key.objectid; 200662306a36Sopenharmony_ci 200762306a36Sopenharmony_ciout: 200862306a36Sopenharmony_ci btrfs_free_path(path); 200962306a36Sopenharmony_ci return ret; 201062306a36Sopenharmony_ci} 201162306a36Sopenharmony_ci 201262306a36Sopenharmony_ci/* 201362306a36Sopenharmony_ci * Looks up the first btrfs_inode_ref of a given ino. It returns the parent dir, 201462306a36Sopenharmony_ci * generation of the parent dir and the name of the dir entry. 201562306a36Sopenharmony_ci */ 201662306a36Sopenharmony_cistatic int get_first_ref(struct btrfs_root *root, u64 ino, 201762306a36Sopenharmony_ci u64 *dir, u64 *dir_gen, struct fs_path *name) 201862306a36Sopenharmony_ci{ 201962306a36Sopenharmony_ci int ret; 202062306a36Sopenharmony_ci struct btrfs_key key; 202162306a36Sopenharmony_ci struct btrfs_key found_key; 202262306a36Sopenharmony_ci struct btrfs_path *path; 202362306a36Sopenharmony_ci int len; 202462306a36Sopenharmony_ci u64 parent_dir; 202562306a36Sopenharmony_ci 202662306a36Sopenharmony_ci path = alloc_path_for_send(); 202762306a36Sopenharmony_ci if (!path) 202862306a36Sopenharmony_ci return -ENOMEM; 202962306a36Sopenharmony_ci 203062306a36Sopenharmony_ci key.objectid = ino; 203162306a36Sopenharmony_ci key.type = BTRFS_INODE_REF_KEY; 203262306a36Sopenharmony_ci key.offset = 0; 203362306a36Sopenharmony_ci 203462306a36Sopenharmony_ci ret = btrfs_search_slot_for_read(root, &key, path, 1, 0); 203562306a36Sopenharmony_ci if (ret < 0) 203662306a36Sopenharmony_ci goto out; 203762306a36Sopenharmony_ci if (!ret) 203862306a36Sopenharmony_ci btrfs_item_key_to_cpu(path->nodes[0], &found_key, 203962306a36Sopenharmony_ci path->slots[0]); 204062306a36Sopenharmony_ci if (ret || found_key.objectid != ino || 204162306a36Sopenharmony_ci (found_key.type != BTRFS_INODE_REF_KEY && 204262306a36Sopenharmony_ci found_key.type != BTRFS_INODE_EXTREF_KEY)) { 204362306a36Sopenharmony_ci ret = -ENOENT; 204462306a36Sopenharmony_ci goto out; 204562306a36Sopenharmony_ci } 204662306a36Sopenharmony_ci 204762306a36Sopenharmony_ci if (found_key.type == BTRFS_INODE_REF_KEY) { 204862306a36Sopenharmony_ci struct btrfs_inode_ref *iref; 204962306a36Sopenharmony_ci iref = btrfs_item_ptr(path->nodes[0], path->slots[0], 205062306a36Sopenharmony_ci struct btrfs_inode_ref); 205162306a36Sopenharmony_ci len = btrfs_inode_ref_name_len(path->nodes[0], iref); 205262306a36Sopenharmony_ci ret = fs_path_add_from_extent_buffer(name, path->nodes[0], 205362306a36Sopenharmony_ci (unsigned long)(iref + 1), 205462306a36Sopenharmony_ci len); 205562306a36Sopenharmony_ci parent_dir = found_key.offset; 205662306a36Sopenharmony_ci } else { 205762306a36Sopenharmony_ci struct btrfs_inode_extref *extref; 205862306a36Sopenharmony_ci extref = btrfs_item_ptr(path->nodes[0], path->slots[0], 205962306a36Sopenharmony_ci struct btrfs_inode_extref); 206062306a36Sopenharmony_ci len = btrfs_inode_extref_name_len(path->nodes[0], extref); 206162306a36Sopenharmony_ci ret = fs_path_add_from_extent_buffer(name, path->nodes[0], 206262306a36Sopenharmony_ci (unsigned long)&extref->name, len); 206362306a36Sopenharmony_ci parent_dir = btrfs_inode_extref_parent(path->nodes[0], extref); 206462306a36Sopenharmony_ci } 206562306a36Sopenharmony_ci if (ret < 0) 206662306a36Sopenharmony_ci goto out; 206762306a36Sopenharmony_ci btrfs_release_path(path); 206862306a36Sopenharmony_ci 206962306a36Sopenharmony_ci if (dir_gen) { 207062306a36Sopenharmony_ci ret = get_inode_gen(root, parent_dir, dir_gen); 207162306a36Sopenharmony_ci if (ret < 0) 207262306a36Sopenharmony_ci goto out; 207362306a36Sopenharmony_ci } 207462306a36Sopenharmony_ci 207562306a36Sopenharmony_ci *dir = parent_dir; 207662306a36Sopenharmony_ci 207762306a36Sopenharmony_ciout: 207862306a36Sopenharmony_ci btrfs_free_path(path); 207962306a36Sopenharmony_ci return ret; 208062306a36Sopenharmony_ci} 208162306a36Sopenharmony_ci 208262306a36Sopenharmony_cistatic int is_first_ref(struct btrfs_root *root, 208362306a36Sopenharmony_ci u64 ino, u64 dir, 208462306a36Sopenharmony_ci const char *name, int name_len) 208562306a36Sopenharmony_ci{ 208662306a36Sopenharmony_ci int ret; 208762306a36Sopenharmony_ci struct fs_path *tmp_name; 208862306a36Sopenharmony_ci u64 tmp_dir; 208962306a36Sopenharmony_ci 209062306a36Sopenharmony_ci tmp_name = fs_path_alloc(); 209162306a36Sopenharmony_ci if (!tmp_name) 209262306a36Sopenharmony_ci return -ENOMEM; 209362306a36Sopenharmony_ci 209462306a36Sopenharmony_ci ret = get_first_ref(root, ino, &tmp_dir, NULL, tmp_name); 209562306a36Sopenharmony_ci if (ret < 0) 209662306a36Sopenharmony_ci goto out; 209762306a36Sopenharmony_ci 209862306a36Sopenharmony_ci if (dir != tmp_dir || name_len != fs_path_len(tmp_name)) { 209962306a36Sopenharmony_ci ret = 0; 210062306a36Sopenharmony_ci goto out; 210162306a36Sopenharmony_ci } 210262306a36Sopenharmony_ci 210362306a36Sopenharmony_ci ret = !memcmp(tmp_name->start, name, name_len); 210462306a36Sopenharmony_ci 210562306a36Sopenharmony_ciout: 210662306a36Sopenharmony_ci fs_path_free(tmp_name); 210762306a36Sopenharmony_ci return ret; 210862306a36Sopenharmony_ci} 210962306a36Sopenharmony_ci 211062306a36Sopenharmony_ci/* 211162306a36Sopenharmony_ci * Used by process_recorded_refs to determine if a new ref would overwrite an 211262306a36Sopenharmony_ci * already existing ref. In case it detects an overwrite, it returns the 211362306a36Sopenharmony_ci * inode/gen in who_ino/who_gen. 211462306a36Sopenharmony_ci * When an overwrite is detected, process_recorded_refs does proper orphanizing 211562306a36Sopenharmony_ci * to make sure later references to the overwritten inode are possible. 211662306a36Sopenharmony_ci * Orphanizing is however only required for the first ref of an inode. 211762306a36Sopenharmony_ci * process_recorded_refs does an additional is_first_ref check to see if 211862306a36Sopenharmony_ci * orphanizing is really required. 211962306a36Sopenharmony_ci */ 212062306a36Sopenharmony_cistatic int will_overwrite_ref(struct send_ctx *sctx, u64 dir, u64 dir_gen, 212162306a36Sopenharmony_ci const char *name, int name_len, 212262306a36Sopenharmony_ci u64 *who_ino, u64 *who_gen, u64 *who_mode) 212362306a36Sopenharmony_ci{ 212462306a36Sopenharmony_ci int ret; 212562306a36Sopenharmony_ci u64 parent_root_dir_gen; 212662306a36Sopenharmony_ci u64 other_inode = 0; 212762306a36Sopenharmony_ci struct btrfs_inode_info info; 212862306a36Sopenharmony_ci 212962306a36Sopenharmony_ci if (!sctx->parent_root) 213062306a36Sopenharmony_ci return 0; 213162306a36Sopenharmony_ci 213262306a36Sopenharmony_ci ret = is_inode_existent(sctx, dir, dir_gen, NULL, &parent_root_dir_gen); 213362306a36Sopenharmony_ci if (ret <= 0) 213462306a36Sopenharmony_ci return 0; 213562306a36Sopenharmony_ci 213662306a36Sopenharmony_ci /* 213762306a36Sopenharmony_ci * If we have a parent root we need to verify that the parent dir was 213862306a36Sopenharmony_ci * not deleted and then re-created, if it was then we have no overwrite 213962306a36Sopenharmony_ci * and we can just unlink this entry. 214062306a36Sopenharmony_ci * 214162306a36Sopenharmony_ci * @parent_root_dir_gen was set to 0 if the inode does not exist in the 214262306a36Sopenharmony_ci * parent root. 214362306a36Sopenharmony_ci */ 214462306a36Sopenharmony_ci if (sctx->parent_root && dir != BTRFS_FIRST_FREE_OBJECTID && 214562306a36Sopenharmony_ci parent_root_dir_gen != dir_gen) 214662306a36Sopenharmony_ci return 0; 214762306a36Sopenharmony_ci 214862306a36Sopenharmony_ci ret = lookup_dir_item_inode(sctx->parent_root, dir, name, name_len, 214962306a36Sopenharmony_ci &other_inode); 215062306a36Sopenharmony_ci if (ret == -ENOENT) 215162306a36Sopenharmony_ci return 0; 215262306a36Sopenharmony_ci else if (ret < 0) 215362306a36Sopenharmony_ci return ret; 215462306a36Sopenharmony_ci 215562306a36Sopenharmony_ci /* 215662306a36Sopenharmony_ci * Check if the overwritten ref was already processed. If yes, the ref 215762306a36Sopenharmony_ci * was already unlinked/moved, so we can safely assume that we will not 215862306a36Sopenharmony_ci * overwrite anything at this point in time. 215962306a36Sopenharmony_ci */ 216062306a36Sopenharmony_ci if (other_inode > sctx->send_progress || 216162306a36Sopenharmony_ci is_waiting_for_move(sctx, other_inode)) { 216262306a36Sopenharmony_ci ret = get_inode_info(sctx->parent_root, other_inode, &info); 216362306a36Sopenharmony_ci if (ret < 0) 216462306a36Sopenharmony_ci return ret; 216562306a36Sopenharmony_ci 216662306a36Sopenharmony_ci *who_ino = other_inode; 216762306a36Sopenharmony_ci *who_gen = info.gen; 216862306a36Sopenharmony_ci *who_mode = info.mode; 216962306a36Sopenharmony_ci return 1; 217062306a36Sopenharmony_ci } 217162306a36Sopenharmony_ci 217262306a36Sopenharmony_ci return 0; 217362306a36Sopenharmony_ci} 217462306a36Sopenharmony_ci 217562306a36Sopenharmony_ci/* 217662306a36Sopenharmony_ci * Checks if the ref was overwritten by an already processed inode. This is 217762306a36Sopenharmony_ci * used by __get_cur_name_and_parent to find out if the ref was orphanized and 217862306a36Sopenharmony_ci * thus the orphan name needs be used. 217962306a36Sopenharmony_ci * process_recorded_refs also uses it to avoid unlinking of refs that were 218062306a36Sopenharmony_ci * overwritten. 218162306a36Sopenharmony_ci */ 218262306a36Sopenharmony_cistatic int did_overwrite_ref(struct send_ctx *sctx, 218362306a36Sopenharmony_ci u64 dir, u64 dir_gen, 218462306a36Sopenharmony_ci u64 ino, u64 ino_gen, 218562306a36Sopenharmony_ci const char *name, int name_len) 218662306a36Sopenharmony_ci{ 218762306a36Sopenharmony_ci int ret; 218862306a36Sopenharmony_ci u64 ow_inode; 218962306a36Sopenharmony_ci u64 ow_gen = 0; 219062306a36Sopenharmony_ci u64 send_root_dir_gen; 219162306a36Sopenharmony_ci 219262306a36Sopenharmony_ci if (!sctx->parent_root) 219362306a36Sopenharmony_ci return 0; 219462306a36Sopenharmony_ci 219562306a36Sopenharmony_ci ret = is_inode_existent(sctx, dir, dir_gen, &send_root_dir_gen, NULL); 219662306a36Sopenharmony_ci if (ret <= 0) 219762306a36Sopenharmony_ci return ret; 219862306a36Sopenharmony_ci 219962306a36Sopenharmony_ci /* 220062306a36Sopenharmony_ci * @send_root_dir_gen was set to 0 if the inode does not exist in the 220162306a36Sopenharmony_ci * send root. 220262306a36Sopenharmony_ci */ 220362306a36Sopenharmony_ci if (dir != BTRFS_FIRST_FREE_OBJECTID && send_root_dir_gen != dir_gen) 220462306a36Sopenharmony_ci return 0; 220562306a36Sopenharmony_ci 220662306a36Sopenharmony_ci /* check if the ref was overwritten by another ref */ 220762306a36Sopenharmony_ci ret = lookup_dir_item_inode(sctx->send_root, dir, name, name_len, 220862306a36Sopenharmony_ci &ow_inode); 220962306a36Sopenharmony_ci if (ret == -ENOENT) { 221062306a36Sopenharmony_ci /* was never and will never be overwritten */ 221162306a36Sopenharmony_ci return 0; 221262306a36Sopenharmony_ci } else if (ret < 0) { 221362306a36Sopenharmony_ci return ret; 221462306a36Sopenharmony_ci } 221562306a36Sopenharmony_ci 221662306a36Sopenharmony_ci if (ow_inode == ino) { 221762306a36Sopenharmony_ci ret = get_inode_gen(sctx->send_root, ow_inode, &ow_gen); 221862306a36Sopenharmony_ci if (ret < 0) 221962306a36Sopenharmony_ci return ret; 222062306a36Sopenharmony_ci 222162306a36Sopenharmony_ci /* It's the same inode, so no overwrite happened. */ 222262306a36Sopenharmony_ci if (ow_gen == ino_gen) 222362306a36Sopenharmony_ci return 0; 222462306a36Sopenharmony_ci } 222562306a36Sopenharmony_ci 222662306a36Sopenharmony_ci /* 222762306a36Sopenharmony_ci * We know that it is or will be overwritten. Check this now. 222862306a36Sopenharmony_ci * The current inode being processed might have been the one that caused 222962306a36Sopenharmony_ci * inode 'ino' to be orphanized, therefore check if ow_inode matches 223062306a36Sopenharmony_ci * the current inode being processed. 223162306a36Sopenharmony_ci */ 223262306a36Sopenharmony_ci if (ow_inode < sctx->send_progress) 223362306a36Sopenharmony_ci return 1; 223462306a36Sopenharmony_ci 223562306a36Sopenharmony_ci if (ino != sctx->cur_ino && ow_inode == sctx->cur_ino) { 223662306a36Sopenharmony_ci if (ow_gen == 0) { 223762306a36Sopenharmony_ci ret = get_inode_gen(sctx->send_root, ow_inode, &ow_gen); 223862306a36Sopenharmony_ci if (ret < 0) 223962306a36Sopenharmony_ci return ret; 224062306a36Sopenharmony_ci } 224162306a36Sopenharmony_ci if (ow_gen == sctx->cur_inode_gen) 224262306a36Sopenharmony_ci return 1; 224362306a36Sopenharmony_ci } 224462306a36Sopenharmony_ci 224562306a36Sopenharmony_ci return 0; 224662306a36Sopenharmony_ci} 224762306a36Sopenharmony_ci 224862306a36Sopenharmony_ci/* 224962306a36Sopenharmony_ci * Same as did_overwrite_ref, but also checks if it is the first ref of an inode 225062306a36Sopenharmony_ci * that got overwritten. This is used by process_recorded_refs to determine 225162306a36Sopenharmony_ci * if it has to use the path as returned by get_cur_path or the orphan name. 225262306a36Sopenharmony_ci */ 225362306a36Sopenharmony_cistatic int did_overwrite_first_ref(struct send_ctx *sctx, u64 ino, u64 gen) 225462306a36Sopenharmony_ci{ 225562306a36Sopenharmony_ci int ret = 0; 225662306a36Sopenharmony_ci struct fs_path *name = NULL; 225762306a36Sopenharmony_ci u64 dir; 225862306a36Sopenharmony_ci u64 dir_gen; 225962306a36Sopenharmony_ci 226062306a36Sopenharmony_ci if (!sctx->parent_root) 226162306a36Sopenharmony_ci goto out; 226262306a36Sopenharmony_ci 226362306a36Sopenharmony_ci name = fs_path_alloc(); 226462306a36Sopenharmony_ci if (!name) 226562306a36Sopenharmony_ci return -ENOMEM; 226662306a36Sopenharmony_ci 226762306a36Sopenharmony_ci ret = get_first_ref(sctx->parent_root, ino, &dir, &dir_gen, name); 226862306a36Sopenharmony_ci if (ret < 0) 226962306a36Sopenharmony_ci goto out; 227062306a36Sopenharmony_ci 227162306a36Sopenharmony_ci ret = did_overwrite_ref(sctx, dir, dir_gen, ino, gen, 227262306a36Sopenharmony_ci name->start, fs_path_len(name)); 227362306a36Sopenharmony_ci 227462306a36Sopenharmony_ciout: 227562306a36Sopenharmony_ci fs_path_free(name); 227662306a36Sopenharmony_ci return ret; 227762306a36Sopenharmony_ci} 227862306a36Sopenharmony_ci 227962306a36Sopenharmony_cistatic inline struct name_cache_entry *name_cache_search(struct send_ctx *sctx, 228062306a36Sopenharmony_ci u64 ino, u64 gen) 228162306a36Sopenharmony_ci{ 228262306a36Sopenharmony_ci struct btrfs_lru_cache_entry *entry; 228362306a36Sopenharmony_ci 228462306a36Sopenharmony_ci entry = btrfs_lru_cache_lookup(&sctx->name_cache, ino, gen); 228562306a36Sopenharmony_ci if (!entry) 228662306a36Sopenharmony_ci return NULL; 228762306a36Sopenharmony_ci 228862306a36Sopenharmony_ci return container_of(entry, struct name_cache_entry, entry); 228962306a36Sopenharmony_ci} 229062306a36Sopenharmony_ci 229162306a36Sopenharmony_ci/* 229262306a36Sopenharmony_ci * Used by get_cur_path for each ref up to the root. 229362306a36Sopenharmony_ci * Returns 0 if it succeeded. 229462306a36Sopenharmony_ci * Returns 1 if the inode is not existent or got overwritten. In that case, the 229562306a36Sopenharmony_ci * name is an orphan name. This instructs get_cur_path to stop iterating. If 1 229662306a36Sopenharmony_ci * is returned, parent_ino/parent_gen are not guaranteed to be valid. 229762306a36Sopenharmony_ci * Returns <0 in case of error. 229862306a36Sopenharmony_ci */ 229962306a36Sopenharmony_cistatic int __get_cur_name_and_parent(struct send_ctx *sctx, 230062306a36Sopenharmony_ci u64 ino, u64 gen, 230162306a36Sopenharmony_ci u64 *parent_ino, 230262306a36Sopenharmony_ci u64 *parent_gen, 230362306a36Sopenharmony_ci struct fs_path *dest) 230462306a36Sopenharmony_ci{ 230562306a36Sopenharmony_ci int ret; 230662306a36Sopenharmony_ci int nce_ret; 230762306a36Sopenharmony_ci struct name_cache_entry *nce; 230862306a36Sopenharmony_ci 230962306a36Sopenharmony_ci /* 231062306a36Sopenharmony_ci * First check if we already did a call to this function with the same 231162306a36Sopenharmony_ci * ino/gen. If yes, check if the cache entry is still up-to-date. If yes 231262306a36Sopenharmony_ci * return the cached result. 231362306a36Sopenharmony_ci */ 231462306a36Sopenharmony_ci nce = name_cache_search(sctx, ino, gen); 231562306a36Sopenharmony_ci if (nce) { 231662306a36Sopenharmony_ci if (ino < sctx->send_progress && nce->need_later_update) { 231762306a36Sopenharmony_ci btrfs_lru_cache_remove(&sctx->name_cache, &nce->entry); 231862306a36Sopenharmony_ci nce = NULL; 231962306a36Sopenharmony_ci } else { 232062306a36Sopenharmony_ci *parent_ino = nce->parent_ino; 232162306a36Sopenharmony_ci *parent_gen = nce->parent_gen; 232262306a36Sopenharmony_ci ret = fs_path_add(dest, nce->name, nce->name_len); 232362306a36Sopenharmony_ci if (ret < 0) 232462306a36Sopenharmony_ci goto out; 232562306a36Sopenharmony_ci ret = nce->ret; 232662306a36Sopenharmony_ci goto out; 232762306a36Sopenharmony_ci } 232862306a36Sopenharmony_ci } 232962306a36Sopenharmony_ci 233062306a36Sopenharmony_ci /* 233162306a36Sopenharmony_ci * If the inode is not existent yet, add the orphan name and return 1. 233262306a36Sopenharmony_ci * This should only happen for the parent dir that we determine in 233362306a36Sopenharmony_ci * record_new_ref_if_needed(). 233462306a36Sopenharmony_ci */ 233562306a36Sopenharmony_ci ret = is_inode_existent(sctx, ino, gen, NULL, NULL); 233662306a36Sopenharmony_ci if (ret < 0) 233762306a36Sopenharmony_ci goto out; 233862306a36Sopenharmony_ci 233962306a36Sopenharmony_ci if (!ret) { 234062306a36Sopenharmony_ci ret = gen_unique_name(sctx, ino, gen, dest); 234162306a36Sopenharmony_ci if (ret < 0) 234262306a36Sopenharmony_ci goto out; 234362306a36Sopenharmony_ci ret = 1; 234462306a36Sopenharmony_ci goto out_cache; 234562306a36Sopenharmony_ci } 234662306a36Sopenharmony_ci 234762306a36Sopenharmony_ci /* 234862306a36Sopenharmony_ci * Depending on whether the inode was already processed or not, use 234962306a36Sopenharmony_ci * send_root or parent_root for ref lookup. 235062306a36Sopenharmony_ci */ 235162306a36Sopenharmony_ci if (ino < sctx->send_progress) 235262306a36Sopenharmony_ci ret = get_first_ref(sctx->send_root, ino, 235362306a36Sopenharmony_ci parent_ino, parent_gen, dest); 235462306a36Sopenharmony_ci else 235562306a36Sopenharmony_ci ret = get_first_ref(sctx->parent_root, ino, 235662306a36Sopenharmony_ci parent_ino, parent_gen, dest); 235762306a36Sopenharmony_ci if (ret < 0) 235862306a36Sopenharmony_ci goto out; 235962306a36Sopenharmony_ci 236062306a36Sopenharmony_ci /* 236162306a36Sopenharmony_ci * Check if the ref was overwritten by an inode's ref that was processed 236262306a36Sopenharmony_ci * earlier. If yes, treat as orphan and return 1. 236362306a36Sopenharmony_ci */ 236462306a36Sopenharmony_ci ret = did_overwrite_ref(sctx, *parent_ino, *parent_gen, ino, gen, 236562306a36Sopenharmony_ci dest->start, dest->end - dest->start); 236662306a36Sopenharmony_ci if (ret < 0) 236762306a36Sopenharmony_ci goto out; 236862306a36Sopenharmony_ci if (ret) { 236962306a36Sopenharmony_ci fs_path_reset(dest); 237062306a36Sopenharmony_ci ret = gen_unique_name(sctx, ino, gen, dest); 237162306a36Sopenharmony_ci if (ret < 0) 237262306a36Sopenharmony_ci goto out; 237362306a36Sopenharmony_ci ret = 1; 237462306a36Sopenharmony_ci } 237562306a36Sopenharmony_ci 237662306a36Sopenharmony_ciout_cache: 237762306a36Sopenharmony_ci /* 237862306a36Sopenharmony_ci * Store the result of the lookup in the name cache. 237962306a36Sopenharmony_ci */ 238062306a36Sopenharmony_ci nce = kmalloc(sizeof(*nce) + fs_path_len(dest) + 1, GFP_KERNEL); 238162306a36Sopenharmony_ci if (!nce) { 238262306a36Sopenharmony_ci ret = -ENOMEM; 238362306a36Sopenharmony_ci goto out; 238462306a36Sopenharmony_ci } 238562306a36Sopenharmony_ci 238662306a36Sopenharmony_ci nce->entry.key = ino; 238762306a36Sopenharmony_ci nce->entry.gen = gen; 238862306a36Sopenharmony_ci nce->parent_ino = *parent_ino; 238962306a36Sopenharmony_ci nce->parent_gen = *parent_gen; 239062306a36Sopenharmony_ci nce->name_len = fs_path_len(dest); 239162306a36Sopenharmony_ci nce->ret = ret; 239262306a36Sopenharmony_ci strcpy(nce->name, dest->start); 239362306a36Sopenharmony_ci 239462306a36Sopenharmony_ci if (ino < sctx->send_progress) 239562306a36Sopenharmony_ci nce->need_later_update = 0; 239662306a36Sopenharmony_ci else 239762306a36Sopenharmony_ci nce->need_later_update = 1; 239862306a36Sopenharmony_ci 239962306a36Sopenharmony_ci nce_ret = btrfs_lru_cache_store(&sctx->name_cache, &nce->entry, GFP_KERNEL); 240062306a36Sopenharmony_ci if (nce_ret < 0) { 240162306a36Sopenharmony_ci kfree(nce); 240262306a36Sopenharmony_ci ret = nce_ret; 240362306a36Sopenharmony_ci } 240462306a36Sopenharmony_ci 240562306a36Sopenharmony_ciout: 240662306a36Sopenharmony_ci return ret; 240762306a36Sopenharmony_ci} 240862306a36Sopenharmony_ci 240962306a36Sopenharmony_ci/* 241062306a36Sopenharmony_ci * Magic happens here. This function returns the first ref to an inode as it 241162306a36Sopenharmony_ci * would look like while receiving the stream at this point in time. 241262306a36Sopenharmony_ci * We walk the path up to the root. For every inode in between, we check if it 241362306a36Sopenharmony_ci * was already processed/sent. If yes, we continue with the parent as found 241462306a36Sopenharmony_ci * in send_root. If not, we continue with the parent as found in parent_root. 241562306a36Sopenharmony_ci * If we encounter an inode that was deleted at this point in time, we use the 241662306a36Sopenharmony_ci * inodes "orphan" name instead of the real name and stop. Same with new inodes 241762306a36Sopenharmony_ci * that were not created yet and overwritten inodes/refs. 241862306a36Sopenharmony_ci * 241962306a36Sopenharmony_ci * When do we have orphan inodes: 242062306a36Sopenharmony_ci * 1. When an inode is freshly created and thus no valid refs are available yet 242162306a36Sopenharmony_ci * 2. When a directory lost all it's refs (deleted) but still has dir items 242262306a36Sopenharmony_ci * inside which were not processed yet (pending for move/delete). If anyone 242362306a36Sopenharmony_ci * tried to get the path to the dir items, it would get a path inside that 242462306a36Sopenharmony_ci * orphan directory. 242562306a36Sopenharmony_ci * 3. When an inode is moved around or gets new links, it may overwrite the ref 242662306a36Sopenharmony_ci * of an unprocessed inode. If in that case the first ref would be 242762306a36Sopenharmony_ci * overwritten, the overwritten inode gets "orphanized". Later when we 242862306a36Sopenharmony_ci * process this overwritten inode, it is restored at a new place by moving 242962306a36Sopenharmony_ci * the orphan inode. 243062306a36Sopenharmony_ci * 243162306a36Sopenharmony_ci * sctx->send_progress tells this function at which point in time receiving 243262306a36Sopenharmony_ci * would be. 243362306a36Sopenharmony_ci */ 243462306a36Sopenharmony_cistatic int get_cur_path(struct send_ctx *sctx, u64 ino, u64 gen, 243562306a36Sopenharmony_ci struct fs_path *dest) 243662306a36Sopenharmony_ci{ 243762306a36Sopenharmony_ci int ret = 0; 243862306a36Sopenharmony_ci struct fs_path *name = NULL; 243962306a36Sopenharmony_ci u64 parent_inode = 0; 244062306a36Sopenharmony_ci u64 parent_gen = 0; 244162306a36Sopenharmony_ci int stop = 0; 244262306a36Sopenharmony_ci 244362306a36Sopenharmony_ci name = fs_path_alloc(); 244462306a36Sopenharmony_ci if (!name) { 244562306a36Sopenharmony_ci ret = -ENOMEM; 244662306a36Sopenharmony_ci goto out; 244762306a36Sopenharmony_ci } 244862306a36Sopenharmony_ci 244962306a36Sopenharmony_ci dest->reversed = 1; 245062306a36Sopenharmony_ci fs_path_reset(dest); 245162306a36Sopenharmony_ci 245262306a36Sopenharmony_ci while (!stop && ino != BTRFS_FIRST_FREE_OBJECTID) { 245362306a36Sopenharmony_ci struct waiting_dir_move *wdm; 245462306a36Sopenharmony_ci 245562306a36Sopenharmony_ci fs_path_reset(name); 245662306a36Sopenharmony_ci 245762306a36Sopenharmony_ci if (is_waiting_for_rm(sctx, ino, gen)) { 245862306a36Sopenharmony_ci ret = gen_unique_name(sctx, ino, gen, name); 245962306a36Sopenharmony_ci if (ret < 0) 246062306a36Sopenharmony_ci goto out; 246162306a36Sopenharmony_ci ret = fs_path_add_path(dest, name); 246262306a36Sopenharmony_ci break; 246362306a36Sopenharmony_ci } 246462306a36Sopenharmony_ci 246562306a36Sopenharmony_ci wdm = get_waiting_dir_move(sctx, ino); 246662306a36Sopenharmony_ci if (wdm && wdm->orphanized) { 246762306a36Sopenharmony_ci ret = gen_unique_name(sctx, ino, gen, name); 246862306a36Sopenharmony_ci stop = 1; 246962306a36Sopenharmony_ci } else if (wdm) { 247062306a36Sopenharmony_ci ret = get_first_ref(sctx->parent_root, ino, 247162306a36Sopenharmony_ci &parent_inode, &parent_gen, name); 247262306a36Sopenharmony_ci } else { 247362306a36Sopenharmony_ci ret = __get_cur_name_and_parent(sctx, ino, gen, 247462306a36Sopenharmony_ci &parent_inode, 247562306a36Sopenharmony_ci &parent_gen, name); 247662306a36Sopenharmony_ci if (ret) 247762306a36Sopenharmony_ci stop = 1; 247862306a36Sopenharmony_ci } 247962306a36Sopenharmony_ci 248062306a36Sopenharmony_ci if (ret < 0) 248162306a36Sopenharmony_ci goto out; 248262306a36Sopenharmony_ci 248362306a36Sopenharmony_ci ret = fs_path_add_path(dest, name); 248462306a36Sopenharmony_ci if (ret < 0) 248562306a36Sopenharmony_ci goto out; 248662306a36Sopenharmony_ci 248762306a36Sopenharmony_ci ino = parent_inode; 248862306a36Sopenharmony_ci gen = parent_gen; 248962306a36Sopenharmony_ci } 249062306a36Sopenharmony_ci 249162306a36Sopenharmony_ciout: 249262306a36Sopenharmony_ci fs_path_free(name); 249362306a36Sopenharmony_ci if (!ret) 249462306a36Sopenharmony_ci fs_path_unreverse(dest); 249562306a36Sopenharmony_ci return ret; 249662306a36Sopenharmony_ci} 249762306a36Sopenharmony_ci 249862306a36Sopenharmony_ci/* 249962306a36Sopenharmony_ci * Sends a BTRFS_SEND_C_SUBVOL command/item to userspace 250062306a36Sopenharmony_ci */ 250162306a36Sopenharmony_cistatic int send_subvol_begin(struct send_ctx *sctx) 250262306a36Sopenharmony_ci{ 250362306a36Sopenharmony_ci int ret; 250462306a36Sopenharmony_ci struct btrfs_root *send_root = sctx->send_root; 250562306a36Sopenharmony_ci struct btrfs_root *parent_root = sctx->parent_root; 250662306a36Sopenharmony_ci struct btrfs_path *path; 250762306a36Sopenharmony_ci struct btrfs_key key; 250862306a36Sopenharmony_ci struct btrfs_root_ref *ref; 250962306a36Sopenharmony_ci struct extent_buffer *leaf; 251062306a36Sopenharmony_ci char *name = NULL; 251162306a36Sopenharmony_ci int namelen; 251262306a36Sopenharmony_ci 251362306a36Sopenharmony_ci path = btrfs_alloc_path(); 251462306a36Sopenharmony_ci if (!path) 251562306a36Sopenharmony_ci return -ENOMEM; 251662306a36Sopenharmony_ci 251762306a36Sopenharmony_ci name = kmalloc(BTRFS_PATH_NAME_MAX, GFP_KERNEL); 251862306a36Sopenharmony_ci if (!name) { 251962306a36Sopenharmony_ci btrfs_free_path(path); 252062306a36Sopenharmony_ci return -ENOMEM; 252162306a36Sopenharmony_ci } 252262306a36Sopenharmony_ci 252362306a36Sopenharmony_ci key.objectid = send_root->root_key.objectid; 252462306a36Sopenharmony_ci key.type = BTRFS_ROOT_BACKREF_KEY; 252562306a36Sopenharmony_ci key.offset = 0; 252662306a36Sopenharmony_ci 252762306a36Sopenharmony_ci ret = btrfs_search_slot_for_read(send_root->fs_info->tree_root, 252862306a36Sopenharmony_ci &key, path, 1, 0); 252962306a36Sopenharmony_ci if (ret < 0) 253062306a36Sopenharmony_ci goto out; 253162306a36Sopenharmony_ci if (ret) { 253262306a36Sopenharmony_ci ret = -ENOENT; 253362306a36Sopenharmony_ci goto out; 253462306a36Sopenharmony_ci } 253562306a36Sopenharmony_ci 253662306a36Sopenharmony_ci leaf = path->nodes[0]; 253762306a36Sopenharmony_ci btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); 253862306a36Sopenharmony_ci if (key.type != BTRFS_ROOT_BACKREF_KEY || 253962306a36Sopenharmony_ci key.objectid != send_root->root_key.objectid) { 254062306a36Sopenharmony_ci ret = -ENOENT; 254162306a36Sopenharmony_ci goto out; 254262306a36Sopenharmony_ci } 254362306a36Sopenharmony_ci ref = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_root_ref); 254462306a36Sopenharmony_ci namelen = btrfs_root_ref_name_len(leaf, ref); 254562306a36Sopenharmony_ci read_extent_buffer(leaf, name, (unsigned long)(ref + 1), namelen); 254662306a36Sopenharmony_ci btrfs_release_path(path); 254762306a36Sopenharmony_ci 254862306a36Sopenharmony_ci if (parent_root) { 254962306a36Sopenharmony_ci ret = begin_cmd(sctx, BTRFS_SEND_C_SNAPSHOT); 255062306a36Sopenharmony_ci if (ret < 0) 255162306a36Sopenharmony_ci goto out; 255262306a36Sopenharmony_ci } else { 255362306a36Sopenharmony_ci ret = begin_cmd(sctx, BTRFS_SEND_C_SUBVOL); 255462306a36Sopenharmony_ci if (ret < 0) 255562306a36Sopenharmony_ci goto out; 255662306a36Sopenharmony_ci } 255762306a36Sopenharmony_ci 255862306a36Sopenharmony_ci TLV_PUT_STRING(sctx, BTRFS_SEND_A_PATH, name, namelen); 255962306a36Sopenharmony_ci 256062306a36Sopenharmony_ci if (!btrfs_is_empty_uuid(sctx->send_root->root_item.received_uuid)) 256162306a36Sopenharmony_ci TLV_PUT_UUID(sctx, BTRFS_SEND_A_UUID, 256262306a36Sopenharmony_ci sctx->send_root->root_item.received_uuid); 256362306a36Sopenharmony_ci else 256462306a36Sopenharmony_ci TLV_PUT_UUID(sctx, BTRFS_SEND_A_UUID, 256562306a36Sopenharmony_ci sctx->send_root->root_item.uuid); 256662306a36Sopenharmony_ci 256762306a36Sopenharmony_ci TLV_PUT_U64(sctx, BTRFS_SEND_A_CTRANSID, 256862306a36Sopenharmony_ci btrfs_root_ctransid(&sctx->send_root->root_item)); 256962306a36Sopenharmony_ci if (parent_root) { 257062306a36Sopenharmony_ci if (!btrfs_is_empty_uuid(parent_root->root_item.received_uuid)) 257162306a36Sopenharmony_ci TLV_PUT_UUID(sctx, BTRFS_SEND_A_CLONE_UUID, 257262306a36Sopenharmony_ci parent_root->root_item.received_uuid); 257362306a36Sopenharmony_ci else 257462306a36Sopenharmony_ci TLV_PUT_UUID(sctx, BTRFS_SEND_A_CLONE_UUID, 257562306a36Sopenharmony_ci parent_root->root_item.uuid); 257662306a36Sopenharmony_ci TLV_PUT_U64(sctx, BTRFS_SEND_A_CLONE_CTRANSID, 257762306a36Sopenharmony_ci btrfs_root_ctransid(&sctx->parent_root->root_item)); 257862306a36Sopenharmony_ci } 257962306a36Sopenharmony_ci 258062306a36Sopenharmony_ci ret = send_cmd(sctx); 258162306a36Sopenharmony_ci 258262306a36Sopenharmony_citlv_put_failure: 258362306a36Sopenharmony_ciout: 258462306a36Sopenharmony_ci btrfs_free_path(path); 258562306a36Sopenharmony_ci kfree(name); 258662306a36Sopenharmony_ci return ret; 258762306a36Sopenharmony_ci} 258862306a36Sopenharmony_ci 258962306a36Sopenharmony_cistatic int send_truncate(struct send_ctx *sctx, u64 ino, u64 gen, u64 size) 259062306a36Sopenharmony_ci{ 259162306a36Sopenharmony_ci struct btrfs_fs_info *fs_info = sctx->send_root->fs_info; 259262306a36Sopenharmony_ci int ret = 0; 259362306a36Sopenharmony_ci struct fs_path *p; 259462306a36Sopenharmony_ci 259562306a36Sopenharmony_ci btrfs_debug(fs_info, "send_truncate %llu size=%llu", ino, size); 259662306a36Sopenharmony_ci 259762306a36Sopenharmony_ci p = fs_path_alloc(); 259862306a36Sopenharmony_ci if (!p) 259962306a36Sopenharmony_ci return -ENOMEM; 260062306a36Sopenharmony_ci 260162306a36Sopenharmony_ci ret = begin_cmd(sctx, BTRFS_SEND_C_TRUNCATE); 260262306a36Sopenharmony_ci if (ret < 0) 260362306a36Sopenharmony_ci goto out; 260462306a36Sopenharmony_ci 260562306a36Sopenharmony_ci ret = get_cur_path(sctx, ino, gen, p); 260662306a36Sopenharmony_ci if (ret < 0) 260762306a36Sopenharmony_ci goto out; 260862306a36Sopenharmony_ci TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, p); 260962306a36Sopenharmony_ci TLV_PUT_U64(sctx, BTRFS_SEND_A_SIZE, size); 261062306a36Sopenharmony_ci 261162306a36Sopenharmony_ci ret = send_cmd(sctx); 261262306a36Sopenharmony_ci 261362306a36Sopenharmony_citlv_put_failure: 261462306a36Sopenharmony_ciout: 261562306a36Sopenharmony_ci fs_path_free(p); 261662306a36Sopenharmony_ci return ret; 261762306a36Sopenharmony_ci} 261862306a36Sopenharmony_ci 261962306a36Sopenharmony_cistatic int send_chmod(struct send_ctx *sctx, u64 ino, u64 gen, u64 mode) 262062306a36Sopenharmony_ci{ 262162306a36Sopenharmony_ci struct btrfs_fs_info *fs_info = sctx->send_root->fs_info; 262262306a36Sopenharmony_ci int ret = 0; 262362306a36Sopenharmony_ci struct fs_path *p; 262462306a36Sopenharmony_ci 262562306a36Sopenharmony_ci btrfs_debug(fs_info, "send_chmod %llu mode=%llu", ino, mode); 262662306a36Sopenharmony_ci 262762306a36Sopenharmony_ci p = fs_path_alloc(); 262862306a36Sopenharmony_ci if (!p) 262962306a36Sopenharmony_ci return -ENOMEM; 263062306a36Sopenharmony_ci 263162306a36Sopenharmony_ci ret = begin_cmd(sctx, BTRFS_SEND_C_CHMOD); 263262306a36Sopenharmony_ci if (ret < 0) 263362306a36Sopenharmony_ci goto out; 263462306a36Sopenharmony_ci 263562306a36Sopenharmony_ci ret = get_cur_path(sctx, ino, gen, p); 263662306a36Sopenharmony_ci if (ret < 0) 263762306a36Sopenharmony_ci goto out; 263862306a36Sopenharmony_ci TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, p); 263962306a36Sopenharmony_ci TLV_PUT_U64(sctx, BTRFS_SEND_A_MODE, mode & 07777); 264062306a36Sopenharmony_ci 264162306a36Sopenharmony_ci ret = send_cmd(sctx); 264262306a36Sopenharmony_ci 264362306a36Sopenharmony_citlv_put_failure: 264462306a36Sopenharmony_ciout: 264562306a36Sopenharmony_ci fs_path_free(p); 264662306a36Sopenharmony_ci return ret; 264762306a36Sopenharmony_ci} 264862306a36Sopenharmony_ci 264962306a36Sopenharmony_cistatic int send_fileattr(struct send_ctx *sctx, u64 ino, u64 gen, u64 fileattr) 265062306a36Sopenharmony_ci{ 265162306a36Sopenharmony_ci struct btrfs_fs_info *fs_info = sctx->send_root->fs_info; 265262306a36Sopenharmony_ci int ret = 0; 265362306a36Sopenharmony_ci struct fs_path *p; 265462306a36Sopenharmony_ci 265562306a36Sopenharmony_ci if (sctx->proto < 2) 265662306a36Sopenharmony_ci return 0; 265762306a36Sopenharmony_ci 265862306a36Sopenharmony_ci btrfs_debug(fs_info, "send_fileattr %llu fileattr=%llu", ino, fileattr); 265962306a36Sopenharmony_ci 266062306a36Sopenharmony_ci p = fs_path_alloc(); 266162306a36Sopenharmony_ci if (!p) 266262306a36Sopenharmony_ci return -ENOMEM; 266362306a36Sopenharmony_ci 266462306a36Sopenharmony_ci ret = begin_cmd(sctx, BTRFS_SEND_C_FILEATTR); 266562306a36Sopenharmony_ci if (ret < 0) 266662306a36Sopenharmony_ci goto out; 266762306a36Sopenharmony_ci 266862306a36Sopenharmony_ci ret = get_cur_path(sctx, ino, gen, p); 266962306a36Sopenharmony_ci if (ret < 0) 267062306a36Sopenharmony_ci goto out; 267162306a36Sopenharmony_ci TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, p); 267262306a36Sopenharmony_ci TLV_PUT_U64(sctx, BTRFS_SEND_A_FILEATTR, fileattr); 267362306a36Sopenharmony_ci 267462306a36Sopenharmony_ci ret = send_cmd(sctx); 267562306a36Sopenharmony_ci 267662306a36Sopenharmony_citlv_put_failure: 267762306a36Sopenharmony_ciout: 267862306a36Sopenharmony_ci fs_path_free(p); 267962306a36Sopenharmony_ci return ret; 268062306a36Sopenharmony_ci} 268162306a36Sopenharmony_ci 268262306a36Sopenharmony_cistatic int send_chown(struct send_ctx *sctx, u64 ino, u64 gen, u64 uid, u64 gid) 268362306a36Sopenharmony_ci{ 268462306a36Sopenharmony_ci struct btrfs_fs_info *fs_info = sctx->send_root->fs_info; 268562306a36Sopenharmony_ci int ret = 0; 268662306a36Sopenharmony_ci struct fs_path *p; 268762306a36Sopenharmony_ci 268862306a36Sopenharmony_ci btrfs_debug(fs_info, "send_chown %llu uid=%llu, gid=%llu", 268962306a36Sopenharmony_ci ino, uid, gid); 269062306a36Sopenharmony_ci 269162306a36Sopenharmony_ci p = fs_path_alloc(); 269262306a36Sopenharmony_ci if (!p) 269362306a36Sopenharmony_ci return -ENOMEM; 269462306a36Sopenharmony_ci 269562306a36Sopenharmony_ci ret = begin_cmd(sctx, BTRFS_SEND_C_CHOWN); 269662306a36Sopenharmony_ci if (ret < 0) 269762306a36Sopenharmony_ci goto out; 269862306a36Sopenharmony_ci 269962306a36Sopenharmony_ci ret = get_cur_path(sctx, ino, gen, p); 270062306a36Sopenharmony_ci if (ret < 0) 270162306a36Sopenharmony_ci goto out; 270262306a36Sopenharmony_ci TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, p); 270362306a36Sopenharmony_ci TLV_PUT_U64(sctx, BTRFS_SEND_A_UID, uid); 270462306a36Sopenharmony_ci TLV_PUT_U64(sctx, BTRFS_SEND_A_GID, gid); 270562306a36Sopenharmony_ci 270662306a36Sopenharmony_ci ret = send_cmd(sctx); 270762306a36Sopenharmony_ci 270862306a36Sopenharmony_citlv_put_failure: 270962306a36Sopenharmony_ciout: 271062306a36Sopenharmony_ci fs_path_free(p); 271162306a36Sopenharmony_ci return ret; 271262306a36Sopenharmony_ci} 271362306a36Sopenharmony_ci 271462306a36Sopenharmony_cistatic int send_utimes(struct send_ctx *sctx, u64 ino, u64 gen) 271562306a36Sopenharmony_ci{ 271662306a36Sopenharmony_ci struct btrfs_fs_info *fs_info = sctx->send_root->fs_info; 271762306a36Sopenharmony_ci int ret = 0; 271862306a36Sopenharmony_ci struct fs_path *p = NULL; 271962306a36Sopenharmony_ci struct btrfs_inode_item *ii; 272062306a36Sopenharmony_ci struct btrfs_path *path = NULL; 272162306a36Sopenharmony_ci struct extent_buffer *eb; 272262306a36Sopenharmony_ci struct btrfs_key key; 272362306a36Sopenharmony_ci int slot; 272462306a36Sopenharmony_ci 272562306a36Sopenharmony_ci btrfs_debug(fs_info, "send_utimes %llu", ino); 272662306a36Sopenharmony_ci 272762306a36Sopenharmony_ci p = fs_path_alloc(); 272862306a36Sopenharmony_ci if (!p) 272962306a36Sopenharmony_ci return -ENOMEM; 273062306a36Sopenharmony_ci 273162306a36Sopenharmony_ci path = alloc_path_for_send(); 273262306a36Sopenharmony_ci if (!path) { 273362306a36Sopenharmony_ci ret = -ENOMEM; 273462306a36Sopenharmony_ci goto out; 273562306a36Sopenharmony_ci } 273662306a36Sopenharmony_ci 273762306a36Sopenharmony_ci key.objectid = ino; 273862306a36Sopenharmony_ci key.type = BTRFS_INODE_ITEM_KEY; 273962306a36Sopenharmony_ci key.offset = 0; 274062306a36Sopenharmony_ci ret = btrfs_search_slot(NULL, sctx->send_root, &key, path, 0, 0); 274162306a36Sopenharmony_ci if (ret > 0) 274262306a36Sopenharmony_ci ret = -ENOENT; 274362306a36Sopenharmony_ci if (ret < 0) 274462306a36Sopenharmony_ci goto out; 274562306a36Sopenharmony_ci 274662306a36Sopenharmony_ci eb = path->nodes[0]; 274762306a36Sopenharmony_ci slot = path->slots[0]; 274862306a36Sopenharmony_ci ii = btrfs_item_ptr(eb, slot, struct btrfs_inode_item); 274962306a36Sopenharmony_ci 275062306a36Sopenharmony_ci ret = begin_cmd(sctx, BTRFS_SEND_C_UTIMES); 275162306a36Sopenharmony_ci if (ret < 0) 275262306a36Sopenharmony_ci goto out; 275362306a36Sopenharmony_ci 275462306a36Sopenharmony_ci ret = get_cur_path(sctx, ino, gen, p); 275562306a36Sopenharmony_ci if (ret < 0) 275662306a36Sopenharmony_ci goto out; 275762306a36Sopenharmony_ci TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, p); 275862306a36Sopenharmony_ci TLV_PUT_BTRFS_TIMESPEC(sctx, BTRFS_SEND_A_ATIME, eb, &ii->atime); 275962306a36Sopenharmony_ci TLV_PUT_BTRFS_TIMESPEC(sctx, BTRFS_SEND_A_MTIME, eb, &ii->mtime); 276062306a36Sopenharmony_ci TLV_PUT_BTRFS_TIMESPEC(sctx, BTRFS_SEND_A_CTIME, eb, &ii->ctime); 276162306a36Sopenharmony_ci if (sctx->proto >= 2) 276262306a36Sopenharmony_ci TLV_PUT_BTRFS_TIMESPEC(sctx, BTRFS_SEND_A_OTIME, eb, &ii->otime); 276362306a36Sopenharmony_ci 276462306a36Sopenharmony_ci ret = send_cmd(sctx); 276562306a36Sopenharmony_ci 276662306a36Sopenharmony_citlv_put_failure: 276762306a36Sopenharmony_ciout: 276862306a36Sopenharmony_ci fs_path_free(p); 276962306a36Sopenharmony_ci btrfs_free_path(path); 277062306a36Sopenharmony_ci return ret; 277162306a36Sopenharmony_ci} 277262306a36Sopenharmony_ci 277362306a36Sopenharmony_ci/* 277462306a36Sopenharmony_ci * If the cache is full, we can't remove entries from it and do a call to 277562306a36Sopenharmony_ci * send_utimes() for each respective inode, because we might be finishing 277662306a36Sopenharmony_ci * processing an inode that is a directory and it just got renamed, and existing 277762306a36Sopenharmony_ci * entries in the cache may refer to inodes that have the directory in their 277862306a36Sopenharmony_ci * full path - in which case we would generate outdated paths (pre-rename) 277962306a36Sopenharmony_ci * for the inodes that the cache entries point to. Instead of prunning the 278062306a36Sopenharmony_ci * cache when inserting, do it after we finish processing each inode at 278162306a36Sopenharmony_ci * finish_inode_if_needed(). 278262306a36Sopenharmony_ci */ 278362306a36Sopenharmony_cistatic int cache_dir_utimes(struct send_ctx *sctx, u64 dir, u64 gen) 278462306a36Sopenharmony_ci{ 278562306a36Sopenharmony_ci struct btrfs_lru_cache_entry *entry; 278662306a36Sopenharmony_ci int ret; 278762306a36Sopenharmony_ci 278862306a36Sopenharmony_ci entry = btrfs_lru_cache_lookup(&sctx->dir_utimes_cache, dir, gen); 278962306a36Sopenharmony_ci if (entry != NULL) 279062306a36Sopenharmony_ci return 0; 279162306a36Sopenharmony_ci 279262306a36Sopenharmony_ci /* Caching is optional, don't fail if we can't allocate memory. */ 279362306a36Sopenharmony_ci entry = kmalloc(sizeof(*entry), GFP_KERNEL); 279462306a36Sopenharmony_ci if (!entry) 279562306a36Sopenharmony_ci return send_utimes(sctx, dir, gen); 279662306a36Sopenharmony_ci 279762306a36Sopenharmony_ci entry->key = dir; 279862306a36Sopenharmony_ci entry->gen = gen; 279962306a36Sopenharmony_ci 280062306a36Sopenharmony_ci ret = btrfs_lru_cache_store(&sctx->dir_utimes_cache, entry, GFP_KERNEL); 280162306a36Sopenharmony_ci ASSERT(ret != -EEXIST); 280262306a36Sopenharmony_ci if (ret) { 280362306a36Sopenharmony_ci kfree(entry); 280462306a36Sopenharmony_ci return send_utimes(sctx, dir, gen); 280562306a36Sopenharmony_ci } 280662306a36Sopenharmony_ci 280762306a36Sopenharmony_ci return 0; 280862306a36Sopenharmony_ci} 280962306a36Sopenharmony_ci 281062306a36Sopenharmony_cistatic int trim_dir_utimes_cache(struct send_ctx *sctx) 281162306a36Sopenharmony_ci{ 281262306a36Sopenharmony_ci while (btrfs_lru_cache_size(&sctx->dir_utimes_cache) > 281362306a36Sopenharmony_ci SEND_MAX_DIR_UTIMES_CACHE_SIZE) { 281462306a36Sopenharmony_ci struct btrfs_lru_cache_entry *lru; 281562306a36Sopenharmony_ci int ret; 281662306a36Sopenharmony_ci 281762306a36Sopenharmony_ci lru = btrfs_lru_cache_lru_entry(&sctx->dir_utimes_cache); 281862306a36Sopenharmony_ci ASSERT(lru != NULL); 281962306a36Sopenharmony_ci 282062306a36Sopenharmony_ci ret = send_utimes(sctx, lru->key, lru->gen); 282162306a36Sopenharmony_ci if (ret) 282262306a36Sopenharmony_ci return ret; 282362306a36Sopenharmony_ci 282462306a36Sopenharmony_ci btrfs_lru_cache_remove(&sctx->dir_utimes_cache, lru); 282562306a36Sopenharmony_ci } 282662306a36Sopenharmony_ci 282762306a36Sopenharmony_ci return 0; 282862306a36Sopenharmony_ci} 282962306a36Sopenharmony_ci 283062306a36Sopenharmony_ci/* 283162306a36Sopenharmony_ci * Sends a BTRFS_SEND_C_MKXXX or SYMLINK command to user space. We don't have 283262306a36Sopenharmony_ci * a valid path yet because we did not process the refs yet. So, the inode 283362306a36Sopenharmony_ci * is created as orphan. 283462306a36Sopenharmony_ci */ 283562306a36Sopenharmony_cistatic int send_create_inode(struct send_ctx *sctx, u64 ino) 283662306a36Sopenharmony_ci{ 283762306a36Sopenharmony_ci struct btrfs_fs_info *fs_info = sctx->send_root->fs_info; 283862306a36Sopenharmony_ci int ret = 0; 283962306a36Sopenharmony_ci struct fs_path *p; 284062306a36Sopenharmony_ci int cmd; 284162306a36Sopenharmony_ci struct btrfs_inode_info info; 284262306a36Sopenharmony_ci u64 gen; 284362306a36Sopenharmony_ci u64 mode; 284462306a36Sopenharmony_ci u64 rdev; 284562306a36Sopenharmony_ci 284662306a36Sopenharmony_ci btrfs_debug(fs_info, "send_create_inode %llu", ino); 284762306a36Sopenharmony_ci 284862306a36Sopenharmony_ci p = fs_path_alloc(); 284962306a36Sopenharmony_ci if (!p) 285062306a36Sopenharmony_ci return -ENOMEM; 285162306a36Sopenharmony_ci 285262306a36Sopenharmony_ci if (ino != sctx->cur_ino) { 285362306a36Sopenharmony_ci ret = get_inode_info(sctx->send_root, ino, &info); 285462306a36Sopenharmony_ci if (ret < 0) 285562306a36Sopenharmony_ci goto out; 285662306a36Sopenharmony_ci gen = info.gen; 285762306a36Sopenharmony_ci mode = info.mode; 285862306a36Sopenharmony_ci rdev = info.rdev; 285962306a36Sopenharmony_ci } else { 286062306a36Sopenharmony_ci gen = sctx->cur_inode_gen; 286162306a36Sopenharmony_ci mode = sctx->cur_inode_mode; 286262306a36Sopenharmony_ci rdev = sctx->cur_inode_rdev; 286362306a36Sopenharmony_ci } 286462306a36Sopenharmony_ci 286562306a36Sopenharmony_ci if (S_ISREG(mode)) { 286662306a36Sopenharmony_ci cmd = BTRFS_SEND_C_MKFILE; 286762306a36Sopenharmony_ci } else if (S_ISDIR(mode)) { 286862306a36Sopenharmony_ci cmd = BTRFS_SEND_C_MKDIR; 286962306a36Sopenharmony_ci } else if (S_ISLNK(mode)) { 287062306a36Sopenharmony_ci cmd = BTRFS_SEND_C_SYMLINK; 287162306a36Sopenharmony_ci } else if (S_ISCHR(mode) || S_ISBLK(mode)) { 287262306a36Sopenharmony_ci cmd = BTRFS_SEND_C_MKNOD; 287362306a36Sopenharmony_ci } else if (S_ISFIFO(mode)) { 287462306a36Sopenharmony_ci cmd = BTRFS_SEND_C_MKFIFO; 287562306a36Sopenharmony_ci } else if (S_ISSOCK(mode)) { 287662306a36Sopenharmony_ci cmd = BTRFS_SEND_C_MKSOCK; 287762306a36Sopenharmony_ci } else { 287862306a36Sopenharmony_ci btrfs_warn(sctx->send_root->fs_info, "unexpected inode type %o", 287962306a36Sopenharmony_ci (int)(mode & S_IFMT)); 288062306a36Sopenharmony_ci ret = -EOPNOTSUPP; 288162306a36Sopenharmony_ci goto out; 288262306a36Sopenharmony_ci } 288362306a36Sopenharmony_ci 288462306a36Sopenharmony_ci ret = begin_cmd(sctx, cmd); 288562306a36Sopenharmony_ci if (ret < 0) 288662306a36Sopenharmony_ci goto out; 288762306a36Sopenharmony_ci 288862306a36Sopenharmony_ci ret = gen_unique_name(sctx, ino, gen, p); 288962306a36Sopenharmony_ci if (ret < 0) 289062306a36Sopenharmony_ci goto out; 289162306a36Sopenharmony_ci 289262306a36Sopenharmony_ci TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, p); 289362306a36Sopenharmony_ci TLV_PUT_U64(sctx, BTRFS_SEND_A_INO, ino); 289462306a36Sopenharmony_ci 289562306a36Sopenharmony_ci if (S_ISLNK(mode)) { 289662306a36Sopenharmony_ci fs_path_reset(p); 289762306a36Sopenharmony_ci ret = read_symlink(sctx->send_root, ino, p); 289862306a36Sopenharmony_ci if (ret < 0) 289962306a36Sopenharmony_ci goto out; 290062306a36Sopenharmony_ci TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH_LINK, p); 290162306a36Sopenharmony_ci } else if (S_ISCHR(mode) || S_ISBLK(mode) || 290262306a36Sopenharmony_ci S_ISFIFO(mode) || S_ISSOCK(mode)) { 290362306a36Sopenharmony_ci TLV_PUT_U64(sctx, BTRFS_SEND_A_RDEV, new_encode_dev(rdev)); 290462306a36Sopenharmony_ci TLV_PUT_U64(sctx, BTRFS_SEND_A_MODE, mode); 290562306a36Sopenharmony_ci } 290662306a36Sopenharmony_ci 290762306a36Sopenharmony_ci ret = send_cmd(sctx); 290862306a36Sopenharmony_ci if (ret < 0) 290962306a36Sopenharmony_ci goto out; 291062306a36Sopenharmony_ci 291162306a36Sopenharmony_ci 291262306a36Sopenharmony_citlv_put_failure: 291362306a36Sopenharmony_ciout: 291462306a36Sopenharmony_ci fs_path_free(p); 291562306a36Sopenharmony_ci return ret; 291662306a36Sopenharmony_ci} 291762306a36Sopenharmony_ci 291862306a36Sopenharmony_cistatic void cache_dir_created(struct send_ctx *sctx, u64 dir) 291962306a36Sopenharmony_ci{ 292062306a36Sopenharmony_ci struct btrfs_lru_cache_entry *entry; 292162306a36Sopenharmony_ci int ret; 292262306a36Sopenharmony_ci 292362306a36Sopenharmony_ci /* Caching is optional, ignore any failures. */ 292462306a36Sopenharmony_ci entry = kmalloc(sizeof(*entry), GFP_KERNEL); 292562306a36Sopenharmony_ci if (!entry) 292662306a36Sopenharmony_ci return; 292762306a36Sopenharmony_ci 292862306a36Sopenharmony_ci entry->key = dir; 292962306a36Sopenharmony_ci entry->gen = 0; 293062306a36Sopenharmony_ci ret = btrfs_lru_cache_store(&sctx->dir_created_cache, entry, GFP_KERNEL); 293162306a36Sopenharmony_ci if (ret < 0) 293262306a36Sopenharmony_ci kfree(entry); 293362306a36Sopenharmony_ci} 293462306a36Sopenharmony_ci 293562306a36Sopenharmony_ci/* 293662306a36Sopenharmony_ci * We need some special handling for inodes that get processed before the parent 293762306a36Sopenharmony_ci * directory got created. See process_recorded_refs for details. 293862306a36Sopenharmony_ci * This function does the check if we already created the dir out of order. 293962306a36Sopenharmony_ci */ 294062306a36Sopenharmony_cistatic int did_create_dir(struct send_ctx *sctx, u64 dir) 294162306a36Sopenharmony_ci{ 294262306a36Sopenharmony_ci int ret = 0; 294362306a36Sopenharmony_ci int iter_ret = 0; 294462306a36Sopenharmony_ci struct btrfs_path *path = NULL; 294562306a36Sopenharmony_ci struct btrfs_key key; 294662306a36Sopenharmony_ci struct btrfs_key found_key; 294762306a36Sopenharmony_ci struct btrfs_key di_key; 294862306a36Sopenharmony_ci struct btrfs_dir_item *di; 294962306a36Sopenharmony_ci 295062306a36Sopenharmony_ci if (btrfs_lru_cache_lookup(&sctx->dir_created_cache, dir, 0)) 295162306a36Sopenharmony_ci return 1; 295262306a36Sopenharmony_ci 295362306a36Sopenharmony_ci path = alloc_path_for_send(); 295462306a36Sopenharmony_ci if (!path) 295562306a36Sopenharmony_ci return -ENOMEM; 295662306a36Sopenharmony_ci 295762306a36Sopenharmony_ci key.objectid = dir; 295862306a36Sopenharmony_ci key.type = BTRFS_DIR_INDEX_KEY; 295962306a36Sopenharmony_ci key.offset = 0; 296062306a36Sopenharmony_ci 296162306a36Sopenharmony_ci btrfs_for_each_slot(sctx->send_root, &key, &found_key, path, iter_ret) { 296262306a36Sopenharmony_ci struct extent_buffer *eb = path->nodes[0]; 296362306a36Sopenharmony_ci 296462306a36Sopenharmony_ci if (found_key.objectid != key.objectid || 296562306a36Sopenharmony_ci found_key.type != key.type) { 296662306a36Sopenharmony_ci ret = 0; 296762306a36Sopenharmony_ci break; 296862306a36Sopenharmony_ci } 296962306a36Sopenharmony_ci 297062306a36Sopenharmony_ci di = btrfs_item_ptr(eb, path->slots[0], struct btrfs_dir_item); 297162306a36Sopenharmony_ci btrfs_dir_item_key_to_cpu(eb, di, &di_key); 297262306a36Sopenharmony_ci 297362306a36Sopenharmony_ci if (di_key.type != BTRFS_ROOT_ITEM_KEY && 297462306a36Sopenharmony_ci di_key.objectid < sctx->send_progress) { 297562306a36Sopenharmony_ci ret = 1; 297662306a36Sopenharmony_ci cache_dir_created(sctx, dir); 297762306a36Sopenharmony_ci break; 297862306a36Sopenharmony_ci } 297962306a36Sopenharmony_ci } 298062306a36Sopenharmony_ci /* Catch error found during iteration */ 298162306a36Sopenharmony_ci if (iter_ret < 0) 298262306a36Sopenharmony_ci ret = iter_ret; 298362306a36Sopenharmony_ci 298462306a36Sopenharmony_ci btrfs_free_path(path); 298562306a36Sopenharmony_ci return ret; 298662306a36Sopenharmony_ci} 298762306a36Sopenharmony_ci 298862306a36Sopenharmony_ci/* 298962306a36Sopenharmony_ci * Only creates the inode if it is: 299062306a36Sopenharmony_ci * 1. Not a directory 299162306a36Sopenharmony_ci * 2. Or a directory which was not created already due to out of order 299262306a36Sopenharmony_ci * directories. See did_create_dir and process_recorded_refs for details. 299362306a36Sopenharmony_ci */ 299462306a36Sopenharmony_cistatic int send_create_inode_if_needed(struct send_ctx *sctx) 299562306a36Sopenharmony_ci{ 299662306a36Sopenharmony_ci int ret; 299762306a36Sopenharmony_ci 299862306a36Sopenharmony_ci if (S_ISDIR(sctx->cur_inode_mode)) { 299962306a36Sopenharmony_ci ret = did_create_dir(sctx, sctx->cur_ino); 300062306a36Sopenharmony_ci if (ret < 0) 300162306a36Sopenharmony_ci return ret; 300262306a36Sopenharmony_ci else if (ret > 0) 300362306a36Sopenharmony_ci return 0; 300462306a36Sopenharmony_ci } 300562306a36Sopenharmony_ci 300662306a36Sopenharmony_ci ret = send_create_inode(sctx, sctx->cur_ino); 300762306a36Sopenharmony_ci 300862306a36Sopenharmony_ci if (ret == 0 && S_ISDIR(sctx->cur_inode_mode)) 300962306a36Sopenharmony_ci cache_dir_created(sctx, sctx->cur_ino); 301062306a36Sopenharmony_ci 301162306a36Sopenharmony_ci return ret; 301262306a36Sopenharmony_ci} 301362306a36Sopenharmony_ci 301462306a36Sopenharmony_cistruct recorded_ref { 301562306a36Sopenharmony_ci struct list_head list; 301662306a36Sopenharmony_ci char *name; 301762306a36Sopenharmony_ci struct fs_path *full_path; 301862306a36Sopenharmony_ci u64 dir; 301962306a36Sopenharmony_ci u64 dir_gen; 302062306a36Sopenharmony_ci int name_len; 302162306a36Sopenharmony_ci struct rb_node node; 302262306a36Sopenharmony_ci struct rb_root *root; 302362306a36Sopenharmony_ci}; 302462306a36Sopenharmony_ci 302562306a36Sopenharmony_cistatic struct recorded_ref *recorded_ref_alloc(void) 302662306a36Sopenharmony_ci{ 302762306a36Sopenharmony_ci struct recorded_ref *ref; 302862306a36Sopenharmony_ci 302962306a36Sopenharmony_ci ref = kzalloc(sizeof(*ref), GFP_KERNEL); 303062306a36Sopenharmony_ci if (!ref) 303162306a36Sopenharmony_ci return NULL; 303262306a36Sopenharmony_ci RB_CLEAR_NODE(&ref->node); 303362306a36Sopenharmony_ci INIT_LIST_HEAD(&ref->list); 303462306a36Sopenharmony_ci return ref; 303562306a36Sopenharmony_ci} 303662306a36Sopenharmony_ci 303762306a36Sopenharmony_cistatic void recorded_ref_free(struct recorded_ref *ref) 303862306a36Sopenharmony_ci{ 303962306a36Sopenharmony_ci if (!ref) 304062306a36Sopenharmony_ci return; 304162306a36Sopenharmony_ci if (!RB_EMPTY_NODE(&ref->node)) 304262306a36Sopenharmony_ci rb_erase(&ref->node, ref->root); 304362306a36Sopenharmony_ci list_del(&ref->list); 304462306a36Sopenharmony_ci fs_path_free(ref->full_path); 304562306a36Sopenharmony_ci kfree(ref); 304662306a36Sopenharmony_ci} 304762306a36Sopenharmony_ci 304862306a36Sopenharmony_cistatic void set_ref_path(struct recorded_ref *ref, struct fs_path *path) 304962306a36Sopenharmony_ci{ 305062306a36Sopenharmony_ci ref->full_path = path; 305162306a36Sopenharmony_ci ref->name = (char *)kbasename(ref->full_path->start); 305262306a36Sopenharmony_ci ref->name_len = ref->full_path->end - ref->name; 305362306a36Sopenharmony_ci} 305462306a36Sopenharmony_ci 305562306a36Sopenharmony_cistatic int dup_ref(struct recorded_ref *ref, struct list_head *list) 305662306a36Sopenharmony_ci{ 305762306a36Sopenharmony_ci struct recorded_ref *new; 305862306a36Sopenharmony_ci 305962306a36Sopenharmony_ci new = recorded_ref_alloc(); 306062306a36Sopenharmony_ci if (!new) 306162306a36Sopenharmony_ci return -ENOMEM; 306262306a36Sopenharmony_ci 306362306a36Sopenharmony_ci new->dir = ref->dir; 306462306a36Sopenharmony_ci new->dir_gen = ref->dir_gen; 306562306a36Sopenharmony_ci list_add_tail(&new->list, list); 306662306a36Sopenharmony_ci return 0; 306762306a36Sopenharmony_ci} 306862306a36Sopenharmony_ci 306962306a36Sopenharmony_cistatic void __free_recorded_refs(struct list_head *head) 307062306a36Sopenharmony_ci{ 307162306a36Sopenharmony_ci struct recorded_ref *cur; 307262306a36Sopenharmony_ci 307362306a36Sopenharmony_ci while (!list_empty(head)) { 307462306a36Sopenharmony_ci cur = list_entry(head->next, struct recorded_ref, list); 307562306a36Sopenharmony_ci recorded_ref_free(cur); 307662306a36Sopenharmony_ci } 307762306a36Sopenharmony_ci} 307862306a36Sopenharmony_ci 307962306a36Sopenharmony_cistatic void free_recorded_refs(struct send_ctx *sctx) 308062306a36Sopenharmony_ci{ 308162306a36Sopenharmony_ci __free_recorded_refs(&sctx->new_refs); 308262306a36Sopenharmony_ci __free_recorded_refs(&sctx->deleted_refs); 308362306a36Sopenharmony_ci} 308462306a36Sopenharmony_ci 308562306a36Sopenharmony_ci/* 308662306a36Sopenharmony_ci * Renames/moves a file/dir to its orphan name. Used when the first 308762306a36Sopenharmony_ci * ref of an unprocessed inode gets overwritten and for all non empty 308862306a36Sopenharmony_ci * directories. 308962306a36Sopenharmony_ci */ 309062306a36Sopenharmony_cistatic int orphanize_inode(struct send_ctx *sctx, u64 ino, u64 gen, 309162306a36Sopenharmony_ci struct fs_path *path) 309262306a36Sopenharmony_ci{ 309362306a36Sopenharmony_ci int ret; 309462306a36Sopenharmony_ci struct fs_path *orphan; 309562306a36Sopenharmony_ci 309662306a36Sopenharmony_ci orphan = fs_path_alloc(); 309762306a36Sopenharmony_ci if (!orphan) 309862306a36Sopenharmony_ci return -ENOMEM; 309962306a36Sopenharmony_ci 310062306a36Sopenharmony_ci ret = gen_unique_name(sctx, ino, gen, orphan); 310162306a36Sopenharmony_ci if (ret < 0) 310262306a36Sopenharmony_ci goto out; 310362306a36Sopenharmony_ci 310462306a36Sopenharmony_ci ret = send_rename(sctx, path, orphan); 310562306a36Sopenharmony_ci 310662306a36Sopenharmony_ciout: 310762306a36Sopenharmony_ci fs_path_free(orphan); 310862306a36Sopenharmony_ci return ret; 310962306a36Sopenharmony_ci} 311062306a36Sopenharmony_ci 311162306a36Sopenharmony_cistatic struct orphan_dir_info *add_orphan_dir_info(struct send_ctx *sctx, 311262306a36Sopenharmony_ci u64 dir_ino, u64 dir_gen) 311362306a36Sopenharmony_ci{ 311462306a36Sopenharmony_ci struct rb_node **p = &sctx->orphan_dirs.rb_node; 311562306a36Sopenharmony_ci struct rb_node *parent = NULL; 311662306a36Sopenharmony_ci struct orphan_dir_info *entry, *odi; 311762306a36Sopenharmony_ci 311862306a36Sopenharmony_ci while (*p) { 311962306a36Sopenharmony_ci parent = *p; 312062306a36Sopenharmony_ci entry = rb_entry(parent, struct orphan_dir_info, node); 312162306a36Sopenharmony_ci if (dir_ino < entry->ino) 312262306a36Sopenharmony_ci p = &(*p)->rb_left; 312362306a36Sopenharmony_ci else if (dir_ino > entry->ino) 312462306a36Sopenharmony_ci p = &(*p)->rb_right; 312562306a36Sopenharmony_ci else if (dir_gen < entry->gen) 312662306a36Sopenharmony_ci p = &(*p)->rb_left; 312762306a36Sopenharmony_ci else if (dir_gen > entry->gen) 312862306a36Sopenharmony_ci p = &(*p)->rb_right; 312962306a36Sopenharmony_ci else 313062306a36Sopenharmony_ci return entry; 313162306a36Sopenharmony_ci } 313262306a36Sopenharmony_ci 313362306a36Sopenharmony_ci odi = kmalloc(sizeof(*odi), GFP_KERNEL); 313462306a36Sopenharmony_ci if (!odi) 313562306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 313662306a36Sopenharmony_ci odi->ino = dir_ino; 313762306a36Sopenharmony_ci odi->gen = dir_gen; 313862306a36Sopenharmony_ci odi->last_dir_index_offset = 0; 313962306a36Sopenharmony_ci odi->dir_high_seq_ino = 0; 314062306a36Sopenharmony_ci 314162306a36Sopenharmony_ci rb_link_node(&odi->node, parent, p); 314262306a36Sopenharmony_ci rb_insert_color(&odi->node, &sctx->orphan_dirs); 314362306a36Sopenharmony_ci return odi; 314462306a36Sopenharmony_ci} 314562306a36Sopenharmony_ci 314662306a36Sopenharmony_cistatic struct orphan_dir_info *get_orphan_dir_info(struct send_ctx *sctx, 314762306a36Sopenharmony_ci u64 dir_ino, u64 gen) 314862306a36Sopenharmony_ci{ 314962306a36Sopenharmony_ci struct rb_node *n = sctx->orphan_dirs.rb_node; 315062306a36Sopenharmony_ci struct orphan_dir_info *entry; 315162306a36Sopenharmony_ci 315262306a36Sopenharmony_ci while (n) { 315362306a36Sopenharmony_ci entry = rb_entry(n, struct orphan_dir_info, node); 315462306a36Sopenharmony_ci if (dir_ino < entry->ino) 315562306a36Sopenharmony_ci n = n->rb_left; 315662306a36Sopenharmony_ci else if (dir_ino > entry->ino) 315762306a36Sopenharmony_ci n = n->rb_right; 315862306a36Sopenharmony_ci else if (gen < entry->gen) 315962306a36Sopenharmony_ci n = n->rb_left; 316062306a36Sopenharmony_ci else if (gen > entry->gen) 316162306a36Sopenharmony_ci n = n->rb_right; 316262306a36Sopenharmony_ci else 316362306a36Sopenharmony_ci return entry; 316462306a36Sopenharmony_ci } 316562306a36Sopenharmony_ci return NULL; 316662306a36Sopenharmony_ci} 316762306a36Sopenharmony_ci 316862306a36Sopenharmony_cistatic int is_waiting_for_rm(struct send_ctx *sctx, u64 dir_ino, u64 gen) 316962306a36Sopenharmony_ci{ 317062306a36Sopenharmony_ci struct orphan_dir_info *odi = get_orphan_dir_info(sctx, dir_ino, gen); 317162306a36Sopenharmony_ci 317262306a36Sopenharmony_ci return odi != NULL; 317362306a36Sopenharmony_ci} 317462306a36Sopenharmony_ci 317562306a36Sopenharmony_cistatic void free_orphan_dir_info(struct send_ctx *sctx, 317662306a36Sopenharmony_ci struct orphan_dir_info *odi) 317762306a36Sopenharmony_ci{ 317862306a36Sopenharmony_ci if (!odi) 317962306a36Sopenharmony_ci return; 318062306a36Sopenharmony_ci rb_erase(&odi->node, &sctx->orphan_dirs); 318162306a36Sopenharmony_ci kfree(odi); 318262306a36Sopenharmony_ci} 318362306a36Sopenharmony_ci 318462306a36Sopenharmony_ci/* 318562306a36Sopenharmony_ci * Returns 1 if a directory can be removed at this point in time. 318662306a36Sopenharmony_ci * We check this by iterating all dir items and checking if the inode behind 318762306a36Sopenharmony_ci * the dir item was already processed. 318862306a36Sopenharmony_ci */ 318962306a36Sopenharmony_cistatic int can_rmdir(struct send_ctx *sctx, u64 dir, u64 dir_gen) 319062306a36Sopenharmony_ci{ 319162306a36Sopenharmony_ci int ret = 0; 319262306a36Sopenharmony_ci int iter_ret = 0; 319362306a36Sopenharmony_ci struct btrfs_root *root = sctx->parent_root; 319462306a36Sopenharmony_ci struct btrfs_path *path; 319562306a36Sopenharmony_ci struct btrfs_key key; 319662306a36Sopenharmony_ci struct btrfs_key found_key; 319762306a36Sopenharmony_ci struct btrfs_key loc; 319862306a36Sopenharmony_ci struct btrfs_dir_item *di; 319962306a36Sopenharmony_ci struct orphan_dir_info *odi = NULL; 320062306a36Sopenharmony_ci u64 dir_high_seq_ino = 0; 320162306a36Sopenharmony_ci u64 last_dir_index_offset = 0; 320262306a36Sopenharmony_ci 320362306a36Sopenharmony_ci /* 320462306a36Sopenharmony_ci * Don't try to rmdir the top/root subvolume dir. 320562306a36Sopenharmony_ci */ 320662306a36Sopenharmony_ci if (dir == BTRFS_FIRST_FREE_OBJECTID) 320762306a36Sopenharmony_ci return 0; 320862306a36Sopenharmony_ci 320962306a36Sopenharmony_ci odi = get_orphan_dir_info(sctx, dir, dir_gen); 321062306a36Sopenharmony_ci if (odi && sctx->cur_ino < odi->dir_high_seq_ino) 321162306a36Sopenharmony_ci return 0; 321262306a36Sopenharmony_ci 321362306a36Sopenharmony_ci path = alloc_path_for_send(); 321462306a36Sopenharmony_ci if (!path) 321562306a36Sopenharmony_ci return -ENOMEM; 321662306a36Sopenharmony_ci 321762306a36Sopenharmony_ci if (!odi) { 321862306a36Sopenharmony_ci /* 321962306a36Sopenharmony_ci * Find the inode number associated with the last dir index 322062306a36Sopenharmony_ci * entry. This is very likely the inode with the highest number 322162306a36Sopenharmony_ci * of all inodes that have an entry in the directory. We can 322262306a36Sopenharmony_ci * then use it to avoid future calls to can_rmdir(), when 322362306a36Sopenharmony_ci * processing inodes with a lower number, from having to search 322462306a36Sopenharmony_ci * the parent root b+tree for dir index keys. 322562306a36Sopenharmony_ci */ 322662306a36Sopenharmony_ci key.objectid = dir; 322762306a36Sopenharmony_ci key.type = BTRFS_DIR_INDEX_KEY; 322862306a36Sopenharmony_ci key.offset = (u64)-1; 322962306a36Sopenharmony_ci 323062306a36Sopenharmony_ci ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); 323162306a36Sopenharmony_ci if (ret < 0) { 323262306a36Sopenharmony_ci goto out; 323362306a36Sopenharmony_ci } else if (ret > 0) { 323462306a36Sopenharmony_ci /* Can't happen, the root is never empty. */ 323562306a36Sopenharmony_ci ASSERT(path->slots[0] > 0); 323662306a36Sopenharmony_ci if (WARN_ON(path->slots[0] == 0)) { 323762306a36Sopenharmony_ci ret = -EUCLEAN; 323862306a36Sopenharmony_ci goto out; 323962306a36Sopenharmony_ci } 324062306a36Sopenharmony_ci path->slots[0]--; 324162306a36Sopenharmony_ci } 324262306a36Sopenharmony_ci 324362306a36Sopenharmony_ci btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]); 324462306a36Sopenharmony_ci if (key.objectid != dir || key.type != BTRFS_DIR_INDEX_KEY) { 324562306a36Sopenharmony_ci /* No index keys, dir can be removed. */ 324662306a36Sopenharmony_ci ret = 1; 324762306a36Sopenharmony_ci goto out; 324862306a36Sopenharmony_ci } 324962306a36Sopenharmony_ci 325062306a36Sopenharmony_ci di = btrfs_item_ptr(path->nodes[0], path->slots[0], 325162306a36Sopenharmony_ci struct btrfs_dir_item); 325262306a36Sopenharmony_ci btrfs_dir_item_key_to_cpu(path->nodes[0], di, &loc); 325362306a36Sopenharmony_ci dir_high_seq_ino = loc.objectid; 325462306a36Sopenharmony_ci if (sctx->cur_ino < dir_high_seq_ino) { 325562306a36Sopenharmony_ci ret = 0; 325662306a36Sopenharmony_ci goto out; 325762306a36Sopenharmony_ci } 325862306a36Sopenharmony_ci 325962306a36Sopenharmony_ci btrfs_release_path(path); 326062306a36Sopenharmony_ci } 326162306a36Sopenharmony_ci 326262306a36Sopenharmony_ci key.objectid = dir; 326362306a36Sopenharmony_ci key.type = BTRFS_DIR_INDEX_KEY; 326462306a36Sopenharmony_ci key.offset = (odi ? odi->last_dir_index_offset : 0); 326562306a36Sopenharmony_ci 326662306a36Sopenharmony_ci btrfs_for_each_slot(root, &key, &found_key, path, iter_ret) { 326762306a36Sopenharmony_ci struct waiting_dir_move *dm; 326862306a36Sopenharmony_ci 326962306a36Sopenharmony_ci if (found_key.objectid != key.objectid || 327062306a36Sopenharmony_ci found_key.type != key.type) 327162306a36Sopenharmony_ci break; 327262306a36Sopenharmony_ci 327362306a36Sopenharmony_ci di = btrfs_item_ptr(path->nodes[0], path->slots[0], 327462306a36Sopenharmony_ci struct btrfs_dir_item); 327562306a36Sopenharmony_ci btrfs_dir_item_key_to_cpu(path->nodes[0], di, &loc); 327662306a36Sopenharmony_ci 327762306a36Sopenharmony_ci dir_high_seq_ino = max(dir_high_seq_ino, loc.objectid); 327862306a36Sopenharmony_ci last_dir_index_offset = found_key.offset; 327962306a36Sopenharmony_ci 328062306a36Sopenharmony_ci dm = get_waiting_dir_move(sctx, loc.objectid); 328162306a36Sopenharmony_ci if (dm) { 328262306a36Sopenharmony_ci dm->rmdir_ino = dir; 328362306a36Sopenharmony_ci dm->rmdir_gen = dir_gen; 328462306a36Sopenharmony_ci ret = 0; 328562306a36Sopenharmony_ci goto out; 328662306a36Sopenharmony_ci } 328762306a36Sopenharmony_ci 328862306a36Sopenharmony_ci if (loc.objectid > sctx->cur_ino) { 328962306a36Sopenharmony_ci ret = 0; 329062306a36Sopenharmony_ci goto out; 329162306a36Sopenharmony_ci } 329262306a36Sopenharmony_ci } 329362306a36Sopenharmony_ci if (iter_ret < 0) { 329462306a36Sopenharmony_ci ret = iter_ret; 329562306a36Sopenharmony_ci goto out; 329662306a36Sopenharmony_ci } 329762306a36Sopenharmony_ci free_orphan_dir_info(sctx, odi); 329862306a36Sopenharmony_ci 329962306a36Sopenharmony_ci ret = 1; 330062306a36Sopenharmony_ci 330162306a36Sopenharmony_ciout: 330262306a36Sopenharmony_ci btrfs_free_path(path); 330362306a36Sopenharmony_ci 330462306a36Sopenharmony_ci if (ret) 330562306a36Sopenharmony_ci return ret; 330662306a36Sopenharmony_ci 330762306a36Sopenharmony_ci if (!odi) { 330862306a36Sopenharmony_ci odi = add_orphan_dir_info(sctx, dir, dir_gen); 330962306a36Sopenharmony_ci if (IS_ERR(odi)) 331062306a36Sopenharmony_ci return PTR_ERR(odi); 331162306a36Sopenharmony_ci 331262306a36Sopenharmony_ci odi->gen = dir_gen; 331362306a36Sopenharmony_ci } 331462306a36Sopenharmony_ci 331562306a36Sopenharmony_ci odi->last_dir_index_offset = last_dir_index_offset; 331662306a36Sopenharmony_ci odi->dir_high_seq_ino = max(odi->dir_high_seq_ino, dir_high_seq_ino); 331762306a36Sopenharmony_ci 331862306a36Sopenharmony_ci return 0; 331962306a36Sopenharmony_ci} 332062306a36Sopenharmony_ci 332162306a36Sopenharmony_cistatic int is_waiting_for_move(struct send_ctx *sctx, u64 ino) 332262306a36Sopenharmony_ci{ 332362306a36Sopenharmony_ci struct waiting_dir_move *entry = get_waiting_dir_move(sctx, ino); 332462306a36Sopenharmony_ci 332562306a36Sopenharmony_ci return entry != NULL; 332662306a36Sopenharmony_ci} 332762306a36Sopenharmony_ci 332862306a36Sopenharmony_cistatic int add_waiting_dir_move(struct send_ctx *sctx, u64 ino, bool orphanized) 332962306a36Sopenharmony_ci{ 333062306a36Sopenharmony_ci struct rb_node **p = &sctx->waiting_dir_moves.rb_node; 333162306a36Sopenharmony_ci struct rb_node *parent = NULL; 333262306a36Sopenharmony_ci struct waiting_dir_move *entry, *dm; 333362306a36Sopenharmony_ci 333462306a36Sopenharmony_ci dm = kmalloc(sizeof(*dm), GFP_KERNEL); 333562306a36Sopenharmony_ci if (!dm) 333662306a36Sopenharmony_ci return -ENOMEM; 333762306a36Sopenharmony_ci dm->ino = ino; 333862306a36Sopenharmony_ci dm->rmdir_ino = 0; 333962306a36Sopenharmony_ci dm->rmdir_gen = 0; 334062306a36Sopenharmony_ci dm->orphanized = orphanized; 334162306a36Sopenharmony_ci 334262306a36Sopenharmony_ci while (*p) { 334362306a36Sopenharmony_ci parent = *p; 334462306a36Sopenharmony_ci entry = rb_entry(parent, struct waiting_dir_move, node); 334562306a36Sopenharmony_ci if (ino < entry->ino) { 334662306a36Sopenharmony_ci p = &(*p)->rb_left; 334762306a36Sopenharmony_ci } else if (ino > entry->ino) { 334862306a36Sopenharmony_ci p = &(*p)->rb_right; 334962306a36Sopenharmony_ci } else { 335062306a36Sopenharmony_ci kfree(dm); 335162306a36Sopenharmony_ci return -EEXIST; 335262306a36Sopenharmony_ci } 335362306a36Sopenharmony_ci } 335462306a36Sopenharmony_ci 335562306a36Sopenharmony_ci rb_link_node(&dm->node, parent, p); 335662306a36Sopenharmony_ci rb_insert_color(&dm->node, &sctx->waiting_dir_moves); 335762306a36Sopenharmony_ci return 0; 335862306a36Sopenharmony_ci} 335962306a36Sopenharmony_ci 336062306a36Sopenharmony_cistatic struct waiting_dir_move * 336162306a36Sopenharmony_ciget_waiting_dir_move(struct send_ctx *sctx, u64 ino) 336262306a36Sopenharmony_ci{ 336362306a36Sopenharmony_ci struct rb_node *n = sctx->waiting_dir_moves.rb_node; 336462306a36Sopenharmony_ci struct waiting_dir_move *entry; 336562306a36Sopenharmony_ci 336662306a36Sopenharmony_ci while (n) { 336762306a36Sopenharmony_ci entry = rb_entry(n, struct waiting_dir_move, node); 336862306a36Sopenharmony_ci if (ino < entry->ino) 336962306a36Sopenharmony_ci n = n->rb_left; 337062306a36Sopenharmony_ci else if (ino > entry->ino) 337162306a36Sopenharmony_ci n = n->rb_right; 337262306a36Sopenharmony_ci else 337362306a36Sopenharmony_ci return entry; 337462306a36Sopenharmony_ci } 337562306a36Sopenharmony_ci return NULL; 337662306a36Sopenharmony_ci} 337762306a36Sopenharmony_ci 337862306a36Sopenharmony_cistatic void free_waiting_dir_move(struct send_ctx *sctx, 337962306a36Sopenharmony_ci struct waiting_dir_move *dm) 338062306a36Sopenharmony_ci{ 338162306a36Sopenharmony_ci if (!dm) 338262306a36Sopenharmony_ci return; 338362306a36Sopenharmony_ci rb_erase(&dm->node, &sctx->waiting_dir_moves); 338462306a36Sopenharmony_ci kfree(dm); 338562306a36Sopenharmony_ci} 338662306a36Sopenharmony_ci 338762306a36Sopenharmony_cistatic int add_pending_dir_move(struct send_ctx *sctx, 338862306a36Sopenharmony_ci u64 ino, 338962306a36Sopenharmony_ci u64 ino_gen, 339062306a36Sopenharmony_ci u64 parent_ino, 339162306a36Sopenharmony_ci struct list_head *new_refs, 339262306a36Sopenharmony_ci struct list_head *deleted_refs, 339362306a36Sopenharmony_ci const bool is_orphan) 339462306a36Sopenharmony_ci{ 339562306a36Sopenharmony_ci struct rb_node **p = &sctx->pending_dir_moves.rb_node; 339662306a36Sopenharmony_ci struct rb_node *parent = NULL; 339762306a36Sopenharmony_ci struct pending_dir_move *entry = NULL, *pm; 339862306a36Sopenharmony_ci struct recorded_ref *cur; 339962306a36Sopenharmony_ci int exists = 0; 340062306a36Sopenharmony_ci int ret; 340162306a36Sopenharmony_ci 340262306a36Sopenharmony_ci pm = kmalloc(sizeof(*pm), GFP_KERNEL); 340362306a36Sopenharmony_ci if (!pm) 340462306a36Sopenharmony_ci return -ENOMEM; 340562306a36Sopenharmony_ci pm->parent_ino = parent_ino; 340662306a36Sopenharmony_ci pm->ino = ino; 340762306a36Sopenharmony_ci pm->gen = ino_gen; 340862306a36Sopenharmony_ci INIT_LIST_HEAD(&pm->list); 340962306a36Sopenharmony_ci INIT_LIST_HEAD(&pm->update_refs); 341062306a36Sopenharmony_ci RB_CLEAR_NODE(&pm->node); 341162306a36Sopenharmony_ci 341262306a36Sopenharmony_ci while (*p) { 341362306a36Sopenharmony_ci parent = *p; 341462306a36Sopenharmony_ci entry = rb_entry(parent, struct pending_dir_move, node); 341562306a36Sopenharmony_ci if (parent_ino < entry->parent_ino) { 341662306a36Sopenharmony_ci p = &(*p)->rb_left; 341762306a36Sopenharmony_ci } else if (parent_ino > entry->parent_ino) { 341862306a36Sopenharmony_ci p = &(*p)->rb_right; 341962306a36Sopenharmony_ci } else { 342062306a36Sopenharmony_ci exists = 1; 342162306a36Sopenharmony_ci break; 342262306a36Sopenharmony_ci } 342362306a36Sopenharmony_ci } 342462306a36Sopenharmony_ci 342562306a36Sopenharmony_ci list_for_each_entry(cur, deleted_refs, list) { 342662306a36Sopenharmony_ci ret = dup_ref(cur, &pm->update_refs); 342762306a36Sopenharmony_ci if (ret < 0) 342862306a36Sopenharmony_ci goto out; 342962306a36Sopenharmony_ci } 343062306a36Sopenharmony_ci list_for_each_entry(cur, new_refs, list) { 343162306a36Sopenharmony_ci ret = dup_ref(cur, &pm->update_refs); 343262306a36Sopenharmony_ci if (ret < 0) 343362306a36Sopenharmony_ci goto out; 343462306a36Sopenharmony_ci } 343562306a36Sopenharmony_ci 343662306a36Sopenharmony_ci ret = add_waiting_dir_move(sctx, pm->ino, is_orphan); 343762306a36Sopenharmony_ci if (ret) 343862306a36Sopenharmony_ci goto out; 343962306a36Sopenharmony_ci 344062306a36Sopenharmony_ci if (exists) { 344162306a36Sopenharmony_ci list_add_tail(&pm->list, &entry->list); 344262306a36Sopenharmony_ci } else { 344362306a36Sopenharmony_ci rb_link_node(&pm->node, parent, p); 344462306a36Sopenharmony_ci rb_insert_color(&pm->node, &sctx->pending_dir_moves); 344562306a36Sopenharmony_ci } 344662306a36Sopenharmony_ci ret = 0; 344762306a36Sopenharmony_ciout: 344862306a36Sopenharmony_ci if (ret) { 344962306a36Sopenharmony_ci __free_recorded_refs(&pm->update_refs); 345062306a36Sopenharmony_ci kfree(pm); 345162306a36Sopenharmony_ci } 345262306a36Sopenharmony_ci return ret; 345362306a36Sopenharmony_ci} 345462306a36Sopenharmony_ci 345562306a36Sopenharmony_cistatic struct pending_dir_move *get_pending_dir_moves(struct send_ctx *sctx, 345662306a36Sopenharmony_ci u64 parent_ino) 345762306a36Sopenharmony_ci{ 345862306a36Sopenharmony_ci struct rb_node *n = sctx->pending_dir_moves.rb_node; 345962306a36Sopenharmony_ci struct pending_dir_move *entry; 346062306a36Sopenharmony_ci 346162306a36Sopenharmony_ci while (n) { 346262306a36Sopenharmony_ci entry = rb_entry(n, struct pending_dir_move, node); 346362306a36Sopenharmony_ci if (parent_ino < entry->parent_ino) 346462306a36Sopenharmony_ci n = n->rb_left; 346562306a36Sopenharmony_ci else if (parent_ino > entry->parent_ino) 346662306a36Sopenharmony_ci n = n->rb_right; 346762306a36Sopenharmony_ci else 346862306a36Sopenharmony_ci return entry; 346962306a36Sopenharmony_ci } 347062306a36Sopenharmony_ci return NULL; 347162306a36Sopenharmony_ci} 347262306a36Sopenharmony_ci 347362306a36Sopenharmony_cistatic int path_loop(struct send_ctx *sctx, struct fs_path *name, 347462306a36Sopenharmony_ci u64 ino, u64 gen, u64 *ancestor_ino) 347562306a36Sopenharmony_ci{ 347662306a36Sopenharmony_ci int ret = 0; 347762306a36Sopenharmony_ci u64 parent_inode = 0; 347862306a36Sopenharmony_ci u64 parent_gen = 0; 347962306a36Sopenharmony_ci u64 start_ino = ino; 348062306a36Sopenharmony_ci 348162306a36Sopenharmony_ci *ancestor_ino = 0; 348262306a36Sopenharmony_ci while (ino != BTRFS_FIRST_FREE_OBJECTID) { 348362306a36Sopenharmony_ci fs_path_reset(name); 348462306a36Sopenharmony_ci 348562306a36Sopenharmony_ci if (is_waiting_for_rm(sctx, ino, gen)) 348662306a36Sopenharmony_ci break; 348762306a36Sopenharmony_ci if (is_waiting_for_move(sctx, ino)) { 348862306a36Sopenharmony_ci if (*ancestor_ino == 0) 348962306a36Sopenharmony_ci *ancestor_ino = ino; 349062306a36Sopenharmony_ci ret = get_first_ref(sctx->parent_root, ino, 349162306a36Sopenharmony_ci &parent_inode, &parent_gen, name); 349262306a36Sopenharmony_ci } else { 349362306a36Sopenharmony_ci ret = __get_cur_name_and_parent(sctx, ino, gen, 349462306a36Sopenharmony_ci &parent_inode, 349562306a36Sopenharmony_ci &parent_gen, name); 349662306a36Sopenharmony_ci if (ret > 0) { 349762306a36Sopenharmony_ci ret = 0; 349862306a36Sopenharmony_ci break; 349962306a36Sopenharmony_ci } 350062306a36Sopenharmony_ci } 350162306a36Sopenharmony_ci if (ret < 0) 350262306a36Sopenharmony_ci break; 350362306a36Sopenharmony_ci if (parent_inode == start_ino) { 350462306a36Sopenharmony_ci ret = 1; 350562306a36Sopenharmony_ci if (*ancestor_ino == 0) 350662306a36Sopenharmony_ci *ancestor_ino = ino; 350762306a36Sopenharmony_ci break; 350862306a36Sopenharmony_ci } 350962306a36Sopenharmony_ci ino = parent_inode; 351062306a36Sopenharmony_ci gen = parent_gen; 351162306a36Sopenharmony_ci } 351262306a36Sopenharmony_ci return ret; 351362306a36Sopenharmony_ci} 351462306a36Sopenharmony_ci 351562306a36Sopenharmony_cistatic int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm) 351662306a36Sopenharmony_ci{ 351762306a36Sopenharmony_ci struct fs_path *from_path = NULL; 351862306a36Sopenharmony_ci struct fs_path *to_path = NULL; 351962306a36Sopenharmony_ci struct fs_path *name = NULL; 352062306a36Sopenharmony_ci u64 orig_progress = sctx->send_progress; 352162306a36Sopenharmony_ci struct recorded_ref *cur; 352262306a36Sopenharmony_ci u64 parent_ino, parent_gen; 352362306a36Sopenharmony_ci struct waiting_dir_move *dm = NULL; 352462306a36Sopenharmony_ci u64 rmdir_ino = 0; 352562306a36Sopenharmony_ci u64 rmdir_gen; 352662306a36Sopenharmony_ci u64 ancestor; 352762306a36Sopenharmony_ci bool is_orphan; 352862306a36Sopenharmony_ci int ret; 352962306a36Sopenharmony_ci 353062306a36Sopenharmony_ci name = fs_path_alloc(); 353162306a36Sopenharmony_ci from_path = fs_path_alloc(); 353262306a36Sopenharmony_ci if (!name || !from_path) { 353362306a36Sopenharmony_ci ret = -ENOMEM; 353462306a36Sopenharmony_ci goto out; 353562306a36Sopenharmony_ci } 353662306a36Sopenharmony_ci 353762306a36Sopenharmony_ci dm = get_waiting_dir_move(sctx, pm->ino); 353862306a36Sopenharmony_ci ASSERT(dm); 353962306a36Sopenharmony_ci rmdir_ino = dm->rmdir_ino; 354062306a36Sopenharmony_ci rmdir_gen = dm->rmdir_gen; 354162306a36Sopenharmony_ci is_orphan = dm->orphanized; 354262306a36Sopenharmony_ci free_waiting_dir_move(sctx, dm); 354362306a36Sopenharmony_ci 354462306a36Sopenharmony_ci if (is_orphan) { 354562306a36Sopenharmony_ci ret = gen_unique_name(sctx, pm->ino, 354662306a36Sopenharmony_ci pm->gen, from_path); 354762306a36Sopenharmony_ci } else { 354862306a36Sopenharmony_ci ret = get_first_ref(sctx->parent_root, pm->ino, 354962306a36Sopenharmony_ci &parent_ino, &parent_gen, name); 355062306a36Sopenharmony_ci if (ret < 0) 355162306a36Sopenharmony_ci goto out; 355262306a36Sopenharmony_ci ret = get_cur_path(sctx, parent_ino, parent_gen, 355362306a36Sopenharmony_ci from_path); 355462306a36Sopenharmony_ci if (ret < 0) 355562306a36Sopenharmony_ci goto out; 355662306a36Sopenharmony_ci ret = fs_path_add_path(from_path, name); 355762306a36Sopenharmony_ci } 355862306a36Sopenharmony_ci if (ret < 0) 355962306a36Sopenharmony_ci goto out; 356062306a36Sopenharmony_ci 356162306a36Sopenharmony_ci sctx->send_progress = sctx->cur_ino + 1; 356262306a36Sopenharmony_ci ret = path_loop(sctx, name, pm->ino, pm->gen, &ancestor); 356362306a36Sopenharmony_ci if (ret < 0) 356462306a36Sopenharmony_ci goto out; 356562306a36Sopenharmony_ci if (ret) { 356662306a36Sopenharmony_ci LIST_HEAD(deleted_refs); 356762306a36Sopenharmony_ci ASSERT(ancestor > BTRFS_FIRST_FREE_OBJECTID); 356862306a36Sopenharmony_ci ret = add_pending_dir_move(sctx, pm->ino, pm->gen, ancestor, 356962306a36Sopenharmony_ci &pm->update_refs, &deleted_refs, 357062306a36Sopenharmony_ci is_orphan); 357162306a36Sopenharmony_ci if (ret < 0) 357262306a36Sopenharmony_ci goto out; 357362306a36Sopenharmony_ci if (rmdir_ino) { 357462306a36Sopenharmony_ci dm = get_waiting_dir_move(sctx, pm->ino); 357562306a36Sopenharmony_ci ASSERT(dm); 357662306a36Sopenharmony_ci dm->rmdir_ino = rmdir_ino; 357762306a36Sopenharmony_ci dm->rmdir_gen = rmdir_gen; 357862306a36Sopenharmony_ci } 357962306a36Sopenharmony_ci goto out; 358062306a36Sopenharmony_ci } 358162306a36Sopenharmony_ci fs_path_reset(name); 358262306a36Sopenharmony_ci to_path = name; 358362306a36Sopenharmony_ci name = NULL; 358462306a36Sopenharmony_ci ret = get_cur_path(sctx, pm->ino, pm->gen, to_path); 358562306a36Sopenharmony_ci if (ret < 0) 358662306a36Sopenharmony_ci goto out; 358762306a36Sopenharmony_ci 358862306a36Sopenharmony_ci ret = send_rename(sctx, from_path, to_path); 358962306a36Sopenharmony_ci if (ret < 0) 359062306a36Sopenharmony_ci goto out; 359162306a36Sopenharmony_ci 359262306a36Sopenharmony_ci if (rmdir_ino) { 359362306a36Sopenharmony_ci struct orphan_dir_info *odi; 359462306a36Sopenharmony_ci u64 gen; 359562306a36Sopenharmony_ci 359662306a36Sopenharmony_ci odi = get_orphan_dir_info(sctx, rmdir_ino, rmdir_gen); 359762306a36Sopenharmony_ci if (!odi) { 359862306a36Sopenharmony_ci /* already deleted */ 359962306a36Sopenharmony_ci goto finish; 360062306a36Sopenharmony_ci } 360162306a36Sopenharmony_ci gen = odi->gen; 360262306a36Sopenharmony_ci 360362306a36Sopenharmony_ci ret = can_rmdir(sctx, rmdir_ino, gen); 360462306a36Sopenharmony_ci if (ret < 0) 360562306a36Sopenharmony_ci goto out; 360662306a36Sopenharmony_ci if (!ret) 360762306a36Sopenharmony_ci goto finish; 360862306a36Sopenharmony_ci 360962306a36Sopenharmony_ci name = fs_path_alloc(); 361062306a36Sopenharmony_ci if (!name) { 361162306a36Sopenharmony_ci ret = -ENOMEM; 361262306a36Sopenharmony_ci goto out; 361362306a36Sopenharmony_ci } 361462306a36Sopenharmony_ci ret = get_cur_path(sctx, rmdir_ino, gen, name); 361562306a36Sopenharmony_ci if (ret < 0) 361662306a36Sopenharmony_ci goto out; 361762306a36Sopenharmony_ci ret = send_rmdir(sctx, name); 361862306a36Sopenharmony_ci if (ret < 0) 361962306a36Sopenharmony_ci goto out; 362062306a36Sopenharmony_ci } 362162306a36Sopenharmony_ci 362262306a36Sopenharmony_cifinish: 362362306a36Sopenharmony_ci ret = cache_dir_utimes(sctx, pm->ino, pm->gen); 362462306a36Sopenharmony_ci if (ret < 0) 362562306a36Sopenharmony_ci goto out; 362662306a36Sopenharmony_ci 362762306a36Sopenharmony_ci /* 362862306a36Sopenharmony_ci * After rename/move, need to update the utimes of both new parent(s) 362962306a36Sopenharmony_ci * and old parent(s). 363062306a36Sopenharmony_ci */ 363162306a36Sopenharmony_ci list_for_each_entry(cur, &pm->update_refs, list) { 363262306a36Sopenharmony_ci /* 363362306a36Sopenharmony_ci * The parent inode might have been deleted in the send snapshot 363462306a36Sopenharmony_ci */ 363562306a36Sopenharmony_ci ret = get_inode_info(sctx->send_root, cur->dir, NULL); 363662306a36Sopenharmony_ci if (ret == -ENOENT) { 363762306a36Sopenharmony_ci ret = 0; 363862306a36Sopenharmony_ci continue; 363962306a36Sopenharmony_ci } 364062306a36Sopenharmony_ci if (ret < 0) 364162306a36Sopenharmony_ci goto out; 364262306a36Sopenharmony_ci 364362306a36Sopenharmony_ci ret = cache_dir_utimes(sctx, cur->dir, cur->dir_gen); 364462306a36Sopenharmony_ci if (ret < 0) 364562306a36Sopenharmony_ci goto out; 364662306a36Sopenharmony_ci } 364762306a36Sopenharmony_ci 364862306a36Sopenharmony_ciout: 364962306a36Sopenharmony_ci fs_path_free(name); 365062306a36Sopenharmony_ci fs_path_free(from_path); 365162306a36Sopenharmony_ci fs_path_free(to_path); 365262306a36Sopenharmony_ci sctx->send_progress = orig_progress; 365362306a36Sopenharmony_ci 365462306a36Sopenharmony_ci return ret; 365562306a36Sopenharmony_ci} 365662306a36Sopenharmony_ci 365762306a36Sopenharmony_cistatic void free_pending_move(struct send_ctx *sctx, struct pending_dir_move *m) 365862306a36Sopenharmony_ci{ 365962306a36Sopenharmony_ci if (!list_empty(&m->list)) 366062306a36Sopenharmony_ci list_del(&m->list); 366162306a36Sopenharmony_ci if (!RB_EMPTY_NODE(&m->node)) 366262306a36Sopenharmony_ci rb_erase(&m->node, &sctx->pending_dir_moves); 366362306a36Sopenharmony_ci __free_recorded_refs(&m->update_refs); 366462306a36Sopenharmony_ci kfree(m); 366562306a36Sopenharmony_ci} 366662306a36Sopenharmony_ci 366762306a36Sopenharmony_cistatic void tail_append_pending_moves(struct send_ctx *sctx, 366862306a36Sopenharmony_ci struct pending_dir_move *moves, 366962306a36Sopenharmony_ci struct list_head *stack) 367062306a36Sopenharmony_ci{ 367162306a36Sopenharmony_ci if (list_empty(&moves->list)) { 367262306a36Sopenharmony_ci list_add_tail(&moves->list, stack); 367362306a36Sopenharmony_ci } else { 367462306a36Sopenharmony_ci LIST_HEAD(list); 367562306a36Sopenharmony_ci list_splice_init(&moves->list, &list); 367662306a36Sopenharmony_ci list_add_tail(&moves->list, stack); 367762306a36Sopenharmony_ci list_splice_tail(&list, stack); 367862306a36Sopenharmony_ci } 367962306a36Sopenharmony_ci if (!RB_EMPTY_NODE(&moves->node)) { 368062306a36Sopenharmony_ci rb_erase(&moves->node, &sctx->pending_dir_moves); 368162306a36Sopenharmony_ci RB_CLEAR_NODE(&moves->node); 368262306a36Sopenharmony_ci } 368362306a36Sopenharmony_ci} 368462306a36Sopenharmony_ci 368562306a36Sopenharmony_cistatic int apply_children_dir_moves(struct send_ctx *sctx) 368662306a36Sopenharmony_ci{ 368762306a36Sopenharmony_ci struct pending_dir_move *pm; 368862306a36Sopenharmony_ci LIST_HEAD(stack); 368962306a36Sopenharmony_ci u64 parent_ino = sctx->cur_ino; 369062306a36Sopenharmony_ci int ret = 0; 369162306a36Sopenharmony_ci 369262306a36Sopenharmony_ci pm = get_pending_dir_moves(sctx, parent_ino); 369362306a36Sopenharmony_ci if (!pm) 369462306a36Sopenharmony_ci return 0; 369562306a36Sopenharmony_ci 369662306a36Sopenharmony_ci tail_append_pending_moves(sctx, pm, &stack); 369762306a36Sopenharmony_ci 369862306a36Sopenharmony_ci while (!list_empty(&stack)) { 369962306a36Sopenharmony_ci pm = list_first_entry(&stack, struct pending_dir_move, list); 370062306a36Sopenharmony_ci parent_ino = pm->ino; 370162306a36Sopenharmony_ci ret = apply_dir_move(sctx, pm); 370262306a36Sopenharmony_ci free_pending_move(sctx, pm); 370362306a36Sopenharmony_ci if (ret) 370462306a36Sopenharmony_ci goto out; 370562306a36Sopenharmony_ci pm = get_pending_dir_moves(sctx, parent_ino); 370662306a36Sopenharmony_ci if (pm) 370762306a36Sopenharmony_ci tail_append_pending_moves(sctx, pm, &stack); 370862306a36Sopenharmony_ci } 370962306a36Sopenharmony_ci return 0; 371062306a36Sopenharmony_ci 371162306a36Sopenharmony_ciout: 371262306a36Sopenharmony_ci while (!list_empty(&stack)) { 371362306a36Sopenharmony_ci pm = list_first_entry(&stack, struct pending_dir_move, list); 371462306a36Sopenharmony_ci free_pending_move(sctx, pm); 371562306a36Sopenharmony_ci } 371662306a36Sopenharmony_ci return ret; 371762306a36Sopenharmony_ci} 371862306a36Sopenharmony_ci 371962306a36Sopenharmony_ci/* 372062306a36Sopenharmony_ci * We might need to delay a directory rename even when no ancestor directory 372162306a36Sopenharmony_ci * (in the send root) with a higher inode number than ours (sctx->cur_ino) was 372262306a36Sopenharmony_ci * renamed. This happens when we rename a directory to the old name (the name 372362306a36Sopenharmony_ci * in the parent root) of some other unrelated directory that got its rename 372462306a36Sopenharmony_ci * delayed due to some ancestor with higher number that got renamed. 372562306a36Sopenharmony_ci * 372662306a36Sopenharmony_ci * Example: 372762306a36Sopenharmony_ci * 372862306a36Sopenharmony_ci * Parent snapshot: 372962306a36Sopenharmony_ci * . (ino 256) 373062306a36Sopenharmony_ci * |---- a/ (ino 257) 373162306a36Sopenharmony_ci * | |---- file (ino 260) 373262306a36Sopenharmony_ci * | 373362306a36Sopenharmony_ci * |---- b/ (ino 258) 373462306a36Sopenharmony_ci * |---- c/ (ino 259) 373562306a36Sopenharmony_ci * 373662306a36Sopenharmony_ci * Send snapshot: 373762306a36Sopenharmony_ci * . (ino 256) 373862306a36Sopenharmony_ci * |---- a/ (ino 258) 373962306a36Sopenharmony_ci * |---- x/ (ino 259) 374062306a36Sopenharmony_ci * |---- y/ (ino 257) 374162306a36Sopenharmony_ci * |----- file (ino 260) 374262306a36Sopenharmony_ci * 374362306a36Sopenharmony_ci * Here we can not rename 258 from 'b' to 'a' without the rename of inode 257 374462306a36Sopenharmony_ci * from 'a' to 'x/y' happening first, which in turn depends on the rename of 374562306a36Sopenharmony_ci * inode 259 from 'c' to 'x'. So the order of rename commands the send stream 374662306a36Sopenharmony_ci * must issue is: 374762306a36Sopenharmony_ci * 374862306a36Sopenharmony_ci * 1 - rename 259 from 'c' to 'x' 374962306a36Sopenharmony_ci * 2 - rename 257 from 'a' to 'x/y' 375062306a36Sopenharmony_ci * 3 - rename 258 from 'b' to 'a' 375162306a36Sopenharmony_ci * 375262306a36Sopenharmony_ci * Returns 1 if the rename of sctx->cur_ino needs to be delayed, 0 if it can 375362306a36Sopenharmony_ci * be done right away and < 0 on error. 375462306a36Sopenharmony_ci */ 375562306a36Sopenharmony_cistatic int wait_for_dest_dir_move(struct send_ctx *sctx, 375662306a36Sopenharmony_ci struct recorded_ref *parent_ref, 375762306a36Sopenharmony_ci const bool is_orphan) 375862306a36Sopenharmony_ci{ 375962306a36Sopenharmony_ci struct btrfs_fs_info *fs_info = sctx->parent_root->fs_info; 376062306a36Sopenharmony_ci struct btrfs_path *path; 376162306a36Sopenharmony_ci struct btrfs_key key; 376262306a36Sopenharmony_ci struct btrfs_key di_key; 376362306a36Sopenharmony_ci struct btrfs_dir_item *di; 376462306a36Sopenharmony_ci u64 left_gen; 376562306a36Sopenharmony_ci u64 right_gen; 376662306a36Sopenharmony_ci int ret = 0; 376762306a36Sopenharmony_ci struct waiting_dir_move *wdm; 376862306a36Sopenharmony_ci 376962306a36Sopenharmony_ci if (RB_EMPTY_ROOT(&sctx->waiting_dir_moves)) 377062306a36Sopenharmony_ci return 0; 377162306a36Sopenharmony_ci 377262306a36Sopenharmony_ci path = alloc_path_for_send(); 377362306a36Sopenharmony_ci if (!path) 377462306a36Sopenharmony_ci return -ENOMEM; 377562306a36Sopenharmony_ci 377662306a36Sopenharmony_ci key.objectid = parent_ref->dir; 377762306a36Sopenharmony_ci key.type = BTRFS_DIR_ITEM_KEY; 377862306a36Sopenharmony_ci key.offset = btrfs_name_hash(parent_ref->name, parent_ref->name_len); 377962306a36Sopenharmony_ci 378062306a36Sopenharmony_ci ret = btrfs_search_slot(NULL, sctx->parent_root, &key, path, 0, 0); 378162306a36Sopenharmony_ci if (ret < 0) { 378262306a36Sopenharmony_ci goto out; 378362306a36Sopenharmony_ci } else if (ret > 0) { 378462306a36Sopenharmony_ci ret = 0; 378562306a36Sopenharmony_ci goto out; 378662306a36Sopenharmony_ci } 378762306a36Sopenharmony_ci 378862306a36Sopenharmony_ci di = btrfs_match_dir_item_name(fs_info, path, parent_ref->name, 378962306a36Sopenharmony_ci parent_ref->name_len); 379062306a36Sopenharmony_ci if (!di) { 379162306a36Sopenharmony_ci ret = 0; 379262306a36Sopenharmony_ci goto out; 379362306a36Sopenharmony_ci } 379462306a36Sopenharmony_ci /* 379562306a36Sopenharmony_ci * di_key.objectid has the number of the inode that has a dentry in the 379662306a36Sopenharmony_ci * parent directory with the same name that sctx->cur_ino is being 379762306a36Sopenharmony_ci * renamed to. We need to check if that inode is in the send root as 379862306a36Sopenharmony_ci * well and if it is currently marked as an inode with a pending rename, 379962306a36Sopenharmony_ci * if it is, we need to delay the rename of sctx->cur_ino as well, so 380062306a36Sopenharmony_ci * that it happens after that other inode is renamed. 380162306a36Sopenharmony_ci */ 380262306a36Sopenharmony_ci btrfs_dir_item_key_to_cpu(path->nodes[0], di, &di_key); 380362306a36Sopenharmony_ci if (di_key.type != BTRFS_INODE_ITEM_KEY) { 380462306a36Sopenharmony_ci ret = 0; 380562306a36Sopenharmony_ci goto out; 380662306a36Sopenharmony_ci } 380762306a36Sopenharmony_ci 380862306a36Sopenharmony_ci ret = get_inode_gen(sctx->parent_root, di_key.objectid, &left_gen); 380962306a36Sopenharmony_ci if (ret < 0) 381062306a36Sopenharmony_ci goto out; 381162306a36Sopenharmony_ci ret = get_inode_gen(sctx->send_root, di_key.objectid, &right_gen); 381262306a36Sopenharmony_ci if (ret < 0) { 381362306a36Sopenharmony_ci if (ret == -ENOENT) 381462306a36Sopenharmony_ci ret = 0; 381562306a36Sopenharmony_ci goto out; 381662306a36Sopenharmony_ci } 381762306a36Sopenharmony_ci 381862306a36Sopenharmony_ci /* Different inode, no need to delay the rename of sctx->cur_ino */ 381962306a36Sopenharmony_ci if (right_gen != left_gen) { 382062306a36Sopenharmony_ci ret = 0; 382162306a36Sopenharmony_ci goto out; 382262306a36Sopenharmony_ci } 382362306a36Sopenharmony_ci 382462306a36Sopenharmony_ci wdm = get_waiting_dir_move(sctx, di_key.objectid); 382562306a36Sopenharmony_ci if (wdm && !wdm->orphanized) { 382662306a36Sopenharmony_ci ret = add_pending_dir_move(sctx, 382762306a36Sopenharmony_ci sctx->cur_ino, 382862306a36Sopenharmony_ci sctx->cur_inode_gen, 382962306a36Sopenharmony_ci di_key.objectid, 383062306a36Sopenharmony_ci &sctx->new_refs, 383162306a36Sopenharmony_ci &sctx->deleted_refs, 383262306a36Sopenharmony_ci is_orphan); 383362306a36Sopenharmony_ci if (!ret) 383462306a36Sopenharmony_ci ret = 1; 383562306a36Sopenharmony_ci } 383662306a36Sopenharmony_ciout: 383762306a36Sopenharmony_ci btrfs_free_path(path); 383862306a36Sopenharmony_ci return ret; 383962306a36Sopenharmony_ci} 384062306a36Sopenharmony_ci 384162306a36Sopenharmony_ci/* 384262306a36Sopenharmony_ci * Check if inode ino2, or any of its ancestors, is inode ino1. 384362306a36Sopenharmony_ci * Return 1 if true, 0 if false and < 0 on error. 384462306a36Sopenharmony_ci */ 384562306a36Sopenharmony_cistatic int check_ino_in_path(struct btrfs_root *root, 384662306a36Sopenharmony_ci const u64 ino1, 384762306a36Sopenharmony_ci const u64 ino1_gen, 384862306a36Sopenharmony_ci const u64 ino2, 384962306a36Sopenharmony_ci const u64 ino2_gen, 385062306a36Sopenharmony_ci struct fs_path *fs_path) 385162306a36Sopenharmony_ci{ 385262306a36Sopenharmony_ci u64 ino = ino2; 385362306a36Sopenharmony_ci 385462306a36Sopenharmony_ci if (ino1 == ino2) 385562306a36Sopenharmony_ci return ino1_gen == ino2_gen; 385662306a36Sopenharmony_ci 385762306a36Sopenharmony_ci while (ino > BTRFS_FIRST_FREE_OBJECTID) { 385862306a36Sopenharmony_ci u64 parent; 385962306a36Sopenharmony_ci u64 parent_gen; 386062306a36Sopenharmony_ci int ret; 386162306a36Sopenharmony_ci 386262306a36Sopenharmony_ci fs_path_reset(fs_path); 386362306a36Sopenharmony_ci ret = get_first_ref(root, ino, &parent, &parent_gen, fs_path); 386462306a36Sopenharmony_ci if (ret < 0) 386562306a36Sopenharmony_ci return ret; 386662306a36Sopenharmony_ci if (parent == ino1) 386762306a36Sopenharmony_ci return parent_gen == ino1_gen; 386862306a36Sopenharmony_ci ino = parent; 386962306a36Sopenharmony_ci } 387062306a36Sopenharmony_ci return 0; 387162306a36Sopenharmony_ci} 387262306a36Sopenharmony_ci 387362306a36Sopenharmony_ci/* 387462306a36Sopenharmony_ci * Check if inode ino1 is an ancestor of inode ino2 in the given root for any 387562306a36Sopenharmony_ci * possible path (in case ino2 is not a directory and has multiple hard links). 387662306a36Sopenharmony_ci * Return 1 if true, 0 if false and < 0 on error. 387762306a36Sopenharmony_ci */ 387862306a36Sopenharmony_cistatic int is_ancestor(struct btrfs_root *root, 387962306a36Sopenharmony_ci const u64 ino1, 388062306a36Sopenharmony_ci const u64 ino1_gen, 388162306a36Sopenharmony_ci const u64 ino2, 388262306a36Sopenharmony_ci struct fs_path *fs_path) 388362306a36Sopenharmony_ci{ 388462306a36Sopenharmony_ci bool free_fs_path = false; 388562306a36Sopenharmony_ci int ret = 0; 388662306a36Sopenharmony_ci int iter_ret = 0; 388762306a36Sopenharmony_ci struct btrfs_path *path = NULL; 388862306a36Sopenharmony_ci struct btrfs_key key; 388962306a36Sopenharmony_ci 389062306a36Sopenharmony_ci if (!fs_path) { 389162306a36Sopenharmony_ci fs_path = fs_path_alloc(); 389262306a36Sopenharmony_ci if (!fs_path) 389362306a36Sopenharmony_ci return -ENOMEM; 389462306a36Sopenharmony_ci free_fs_path = true; 389562306a36Sopenharmony_ci } 389662306a36Sopenharmony_ci 389762306a36Sopenharmony_ci path = alloc_path_for_send(); 389862306a36Sopenharmony_ci if (!path) { 389962306a36Sopenharmony_ci ret = -ENOMEM; 390062306a36Sopenharmony_ci goto out; 390162306a36Sopenharmony_ci } 390262306a36Sopenharmony_ci 390362306a36Sopenharmony_ci key.objectid = ino2; 390462306a36Sopenharmony_ci key.type = BTRFS_INODE_REF_KEY; 390562306a36Sopenharmony_ci key.offset = 0; 390662306a36Sopenharmony_ci 390762306a36Sopenharmony_ci btrfs_for_each_slot(root, &key, &key, path, iter_ret) { 390862306a36Sopenharmony_ci struct extent_buffer *leaf = path->nodes[0]; 390962306a36Sopenharmony_ci int slot = path->slots[0]; 391062306a36Sopenharmony_ci u32 cur_offset = 0; 391162306a36Sopenharmony_ci u32 item_size; 391262306a36Sopenharmony_ci 391362306a36Sopenharmony_ci if (key.objectid != ino2) 391462306a36Sopenharmony_ci break; 391562306a36Sopenharmony_ci if (key.type != BTRFS_INODE_REF_KEY && 391662306a36Sopenharmony_ci key.type != BTRFS_INODE_EXTREF_KEY) 391762306a36Sopenharmony_ci break; 391862306a36Sopenharmony_ci 391962306a36Sopenharmony_ci item_size = btrfs_item_size(leaf, slot); 392062306a36Sopenharmony_ci while (cur_offset < item_size) { 392162306a36Sopenharmony_ci u64 parent; 392262306a36Sopenharmony_ci u64 parent_gen; 392362306a36Sopenharmony_ci 392462306a36Sopenharmony_ci if (key.type == BTRFS_INODE_EXTREF_KEY) { 392562306a36Sopenharmony_ci unsigned long ptr; 392662306a36Sopenharmony_ci struct btrfs_inode_extref *extref; 392762306a36Sopenharmony_ci 392862306a36Sopenharmony_ci ptr = btrfs_item_ptr_offset(leaf, slot); 392962306a36Sopenharmony_ci extref = (struct btrfs_inode_extref *) 393062306a36Sopenharmony_ci (ptr + cur_offset); 393162306a36Sopenharmony_ci parent = btrfs_inode_extref_parent(leaf, 393262306a36Sopenharmony_ci extref); 393362306a36Sopenharmony_ci cur_offset += sizeof(*extref); 393462306a36Sopenharmony_ci cur_offset += btrfs_inode_extref_name_len(leaf, 393562306a36Sopenharmony_ci extref); 393662306a36Sopenharmony_ci } else { 393762306a36Sopenharmony_ci parent = key.offset; 393862306a36Sopenharmony_ci cur_offset = item_size; 393962306a36Sopenharmony_ci } 394062306a36Sopenharmony_ci 394162306a36Sopenharmony_ci ret = get_inode_gen(root, parent, &parent_gen); 394262306a36Sopenharmony_ci if (ret < 0) 394362306a36Sopenharmony_ci goto out; 394462306a36Sopenharmony_ci ret = check_ino_in_path(root, ino1, ino1_gen, 394562306a36Sopenharmony_ci parent, parent_gen, fs_path); 394662306a36Sopenharmony_ci if (ret) 394762306a36Sopenharmony_ci goto out; 394862306a36Sopenharmony_ci } 394962306a36Sopenharmony_ci } 395062306a36Sopenharmony_ci ret = 0; 395162306a36Sopenharmony_ci if (iter_ret < 0) 395262306a36Sopenharmony_ci ret = iter_ret; 395362306a36Sopenharmony_ci 395462306a36Sopenharmony_ciout: 395562306a36Sopenharmony_ci btrfs_free_path(path); 395662306a36Sopenharmony_ci if (free_fs_path) 395762306a36Sopenharmony_ci fs_path_free(fs_path); 395862306a36Sopenharmony_ci return ret; 395962306a36Sopenharmony_ci} 396062306a36Sopenharmony_ci 396162306a36Sopenharmony_cistatic int wait_for_parent_move(struct send_ctx *sctx, 396262306a36Sopenharmony_ci struct recorded_ref *parent_ref, 396362306a36Sopenharmony_ci const bool is_orphan) 396462306a36Sopenharmony_ci{ 396562306a36Sopenharmony_ci int ret = 0; 396662306a36Sopenharmony_ci u64 ino = parent_ref->dir; 396762306a36Sopenharmony_ci u64 ino_gen = parent_ref->dir_gen; 396862306a36Sopenharmony_ci u64 parent_ino_before, parent_ino_after; 396962306a36Sopenharmony_ci struct fs_path *path_before = NULL; 397062306a36Sopenharmony_ci struct fs_path *path_after = NULL; 397162306a36Sopenharmony_ci int len1, len2; 397262306a36Sopenharmony_ci 397362306a36Sopenharmony_ci path_after = fs_path_alloc(); 397462306a36Sopenharmony_ci path_before = fs_path_alloc(); 397562306a36Sopenharmony_ci if (!path_after || !path_before) { 397662306a36Sopenharmony_ci ret = -ENOMEM; 397762306a36Sopenharmony_ci goto out; 397862306a36Sopenharmony_ci } 397962306a36Sopenharmony_ci 398062306a36Sopenharmony_ci /* 398162306a36Sopenharmony_ci * Our current directory inode may not yet be renamed/moved because some 398262306a36Sopenharmony_ci * ancestor (immediate or not) has to be renamed/moved first. So find if 398362306a36Sopenharmony_ci * such ancestor exists and make sure our own rename/move happens after 398462306a36Sopenharmony_ci * that ancestor is processed to avoid path build infinite loops (done 398562306a36Sopenharmony_ci * at get_cur_path()). 398662306a36Sopenharmony_ci */ 398762306a36Sopenharmony_ci while (ino > BTRFS_FIRST_FREE_OBJECTID) { 398862306a36Sopenharmony_ci u64 parent_ino_after_gen; 398962306a36Sopenharmony_ci 399062306a36Sopenharmony_ci if (is_waiting_for_move(sctx, ino)) { 399162306a36Sopenharmony_ci /* 399262306a36Sopenharmony_ci * If the current inode is an ancestor of ino in the 399362306a36Sopenharmony_ci * parent root, we need to delay the rename of the 399462306a36Sopenharmony_ci * current inode, otherwise don't delayed the rename 399562306a36Sopenharmony_ci * because we can end up with a circular dependency 399662306a36Sopenharmony_ci * of renames, resulting in some directories never 399762306a36Sopenharmony_ci * getting the respective rename operations issued in 399862306a36Sopenharmony_ci * the send stream or getting into infinite path build 399962306a36Sopenharmony_ci * loops. 400062306a36Sopenharmony_ci */ 400162306a36Sopenharmony_ci ret = is_ancestor(sctx->parent_root, 400262306a36Sopenharmony_ci sctx->cur_ino, sctx->cur_inode_gen, 400362306a36Sopenharmony_ci ino, path_before); 400462306a36Sopenharmony_ci if (ret) 400562306a36Sopenharmony_ci break; 400662306a36Sopenharmony_ci } 400762306a36Sopenharmony_ci 400862306a36Sopenharmony_ci fs_path_reset(path_before); 400962306a36Sopenharmony_ci fs_path_reset(path_after); 401062306a36Sopenharmony_ci 401162306a36Sopenharmony_ci ret = get_first_ref(sctx->send_root, ino, &parent_ino_after, 401262306a36Sopenharmony_ci &parent_ino_after_gen, path_after); 401362306a36Sopenharmony_ci if (ret < 0) 401462306a36Sopenharmony_ci goto out; 401562306a36Sopenharmony_ci ret = get_first_ref(sctx->parent_root, ino, &parent_ino_before, 401662306a36Sopenharmony_ci NULL, path_before); 401762306a36Sopenharmony_ci if (ret < 0 && ret != -ENOENT) { 401862306a36Sopenharmony_ci goto out; 401962306a36Sopenharmony_ci } else if (ret == -ENOENT) { 402062306a36Sopenharmony_ci ret = 0; 402162306a36Sopenharmony_ci break; 402262306a36Sopenharmony_ci } 402362306a36Sopenharmony_ci 402462306a36Sopenharmony_ci len1 = fs_path_len(path_before); 402562306a36Sopenharmony_ci len2 = fs_path_len(path_after); 402662306a36Sopenharmony_ci if (ino > sctx->cur_ino && 402762306a36Sopenharmony_ci (parent_ino_before != parent_ino_after || len1 != len2 || 402862306a36Sopenharmony_ci memcmp(path_before->start, path_after->start, len1))) { 402962306a36Sopenharmony_ci u64 parent_ino_gen; 403062306a36Sopenharmony_ci 403162306a36Sopenharmony_ci ret = get_inode_gen(sctx->parent_root, ino, &parent_ino_gen); 403262306a36Sopenharmony_ci if (ret < 0) 403362306a36Sopenharmony_ci goto out; 403462306a36Sopenharmony_ci if (ino_gen == parent_ino_gen) { 403562306a36Sopenharmony_ci ret = 1; 403662306a36Sopenharmony_ci break; 403762306a36Sopenharmony_ci } 403862306a36Sopenharmony_ci } 403962306a36Sopenharmony_ci ino = parent_ino_after; 404062306a36Sopenharmony_ci ino_gen = parent_ino_after_gen; 404162306a36Sopenharmony_ci } 404262306a36Sopenharmony_ci 404362306a36Sopenharmony_ciout: 404462306a36Sopenharmony_ci fs_path_free(path_before); 404562306a36Sopenharmony_ci fs_path_free(path_after); 404662306a36Sopenharmony_ci 404762306a36Sopenharmony_ci if (ret == 1) { 404862306a36Sopenharmony_ci ret = add_pending_dir_move(sctx, 404962306a36Sopenharmony_ci sctx->cur_ino, 405062306a36Sopenharmony_ci sctx->cur_inode_gen, 405162306a36Sopenharmony_ci ino, 405262306a36Sopenharmony_ci &sctx->new_refs, 405362306a36Sopenharmony_ci &sctx->deleted_refs, 405462306a36Sopenharmony_ci is_orphan); 405562306a36Sopenharmony_ci if (!ret) 405662306a36Sopenharmony_ci ret = 1; 405762306a36Sopenharmony_ci } 405862306a36Sopenharmony_ci 405962306a36Sopenharmony_ci return ret; 406062306a36Sopenharmony_ci} 406162306a36Sopenharmony_ci 406262306a36Sopenharmony_cistatic int update_ref_path(struct send_ctx *sctx, struct recorded_ref *ref) 406362306a36Sopenharmony_ci{ 406462306a36Sopenharmony_ci int ret; 406562306a36Sopenharmony_ci struct fs_path *new_path; 406662306a36Sopenharmony_ci 406762306a36Sopenharmony_ci /* 406862306a36Sopenharmony_ci * Our reference's name member points to its full_path member string, so 406962306a36Sopenharmony_ci * we use here a new path. 407062306a36Sopenharmony_ci */ 407162306a36Sopenharmony_ci new_path = fs_path_alloc(); 407262306a36Sopenharmony_ci if (!new_path) 407362306a36Sopenharmony_ci return -ENOMEM; 407462306a36Sopenharmony_ci 407562306a36Sopenharmony_ci ret = get_cur_path(sctx, ref->dir, ref->dir_gen, new_path); 407662306a36Sopenharmony_ci if (ret < 0) { 407762306a36Sopenharmony_ci fs_path_free(new_path); 407862306a36Sopenharmony_ci return ret; 407962306a36Sopenharmony_ci } 408062306a36Sopenharmony_ci ret = fs_path_add(new_path, ref->name, ref->name_len); 408162306a36Sopenharmony_ci if (ret < 0) { 408262306a36Sopenharmony_ci fs_path_free(new_path); 408362306a36Sopenharmony_ci return ret; 408462306a36Sopenharmony_ci } 408562306a36Sopenharmony_ci 408662306a36Sopenharmony_ci fs_path_free(ref->full_path); 408762306a36Sopenharmony_ci set_ref_path(ref, new_path); 408862306a36Sopenharmony_ci 408962306a36Sopenharmony_ci return 0; 409062306a36Sopenharmony_ci} 409162306a36Sopenharmony_ci 409262306a36Sopenharmony_ci/* 409362306a36Sopenharmony_ci * When processing the new references for an inode we may orphanize an existing 409462306a36Sopenharmony_ci * directory inode because its old name conflicts with one of the new references 409562306a36Sopenharmony_ci * of the current inode. Later, when processing another new reference of our 409662306a36Sopenharmony_ci * inode, we might need to orphanize another inode, but the path we have in the 409762306a36Sopenharmony_ci * reference reflects the pre-orphanization name of the directory we previously 409862306a36Sopenharmony_ci * orphanized. For example: 409962306a36Sopenharmony_ci * 410062306a36Sopenharmony_ci * parent snapshot looks like: 410162306a36Sopenharmony_ci * 410262306a36Sopenharmony_ci * . (ino 256) 410362306a36Sopenharmony_ci * |----- f1 (ino 257) 410462306a36Sopenharmony_ci * |----- f2 (ino 258) 410562306a36Sopenharmony_ci * |----- d1/ (ino 259) 410662306a36Sopenharmony_ci * |----- d2/ (ino 260) 410762306a36Sopenharmony_ci * 410862306a36Sopenharmony_ci * send snapshot looks like: 410962306a36Sopenharmony_ci * 411062306a36Sopenharmony_ci * . (ino 256) 411162306a36Sopenharmony_ci * |----- d1 (ino 258) 411262306a36Sopenharmony_ci * |----- f2/ (ino 259) 411362306a36Sopenharmony_ci * |----- f2_link/ (ino 260) 411462306a36Sopenharmony_ci * | |----- f1 (ino 257) 411562306a36Sopenharmony_ci * | 411662306a36Sopenharmony_ci * |----- d2 (ino 258) 411762306a36Sopenharmony_ci * 411862306a36Sopenharmony_ci * When processing inode 257 we compute the name for inode 259 as "d1", and we 411962306a36Sopenharmony_ci * cache it in the name cache. Later when we start processing inode 258, when 412062306a36Sopenharmony_ci * collecting all its new references we set a full path of "d1/d2" for its new 412162306a36Sopenharmony_ci * reference with name "d2". When we start processing the new references we 412262306a36Sopenharmony_ci * start by processing the new reference with name "d1", and this results in 412362306a36Sopenharmony_ci * orphanizing inode 259, since its old reference causes a conflict. Then we 412462306a36Sopenharmony_ci * move on the next new reference, with name "d2", and we find out we must 412562306a36Sopenharmony_ci * orphanize inode 260, as its old reference conflicts with ours - but for the 412662306a36Sopenharmony_ci * orphanization we use a source path corresponding to the path we stored in the 412762306a36Sopenharmony_ci * new reference, which is "d1/d2" and not "o259-6-0/d2" - this makes the 412862306a36Sopenharmony_ci * receiver fail since the path component "d1/" no longer exists, it was renamed 412962306a36Sopenharmony_ci * to "o259-6-0/" when processing the previous new reference. So in this case we 413062306a36Sopenharmony_ci * must recompute the path in the new reference and use it for the new 413162306a36Sopenharmony_ci * orphanization operation. 413262306a36Sopenharmony_ci */ 413362306a36Sopenharmony_cistatic int refresh_ref_path(struct send_ctx *sctx, struct recorded_ref *ref) 413462306a36Sopenharmony_ci{ 413562306a36Sopenharmony_ci char *name; 413662306a36Sopenharmony_ci int ret; 413762306a36Sopenharmony_ci 413862306a36Sopenharmony_ci name = kmemdup(ref->name, ref->name_len, GFP_KERNEL); 413962306a36Sopenharmony_ci if (!name) 414062306a36Sopenharmony_ci return -ENOMEM; 414162306a36Sopenharmony_ci 414262306a36Sopenharmony_ci fs_path_reset(ref->full_path); 414362306a36Sopenharmony_ci ret = get_cur_path(sctx, ref->dir, ref->dir_gen, ref->full_path); 414462306a36Sopenharmony_ci if (ret < 0) 414562306a36Sopenharmony_ci goto out; 414662306a36Sopenharmony_ci 414762306a36Sopenharmony_ci ret = fs_path_add(ref->full_path, name, ref->name_len); 414862306a36Sopenharmony_ci if (ret < 0) 414962306a36Sopenharmony_ci goto out; 415062306a36Sopenharmony_ci 415162306a36Sopenharmony_ci /* Update the reference's base name pointer. */ 415262306a36Sopenharmony_ci set_ref_path(ref, ref->full_path); 415362306a36Sopenharmony_ciout: 415462306a36Sopenharmony_ci kfree(name); 415562306a36Sopenharmony_ci return ret; 415662306a36Sopenharmony_ci} 415762306a36Sopenharmony_ci 415862306a36Sopenharmony_ci/* 415962306a36Sopenharmony_ci * This does all the move/link/unlink/rmdir magic. 416062306a36Sopenharmony_ci */ 416162306a36Sopenharmony_cistatic int process_recorded_refs(struct send_ctx *sctx, int *pending_move) 416262306a36Sopenharmony_ci{ 416362306a36Sopenharmony_ci struct btrfs_fs_info *fs_info = sctx->send_root->fs_info; 416462306a36Sopenharmony_ci int ret = 0; 416562306a36Sopenharmony_ci struct recorded_ref *cur; 416662306a36Sopenharmony_ci struct recorded_ref *cur2; 416762306a36Sopenharmony_ci LIST_HEAD(check_dirs); 416862306a36Sopenharmony_ci struct fs_path *valid_path = NULL; 416962306a36Sopenharmony_ci u64 ow_inode = 0; 417062306a36Sopenharmony_ci u64 ow_gen; 417162306a36Sopenharmony_ci u64 ow_mode; 417262306a36Sopenharmony_ci int did_overwrite = 0; 417362306a36Sopenharmony_ci int is_orphan = 0; 417462306a36Sopenharmony_ci u64 last_dir_ino_rm = 0; 417562306a36Sopenharmony_ci bool can_rename = true; 417662306a36Sopenharmony_ci bool orphanized_dir = false; 417762306a36Sopenharmony_ci bool orphanized_ancestor = false; 417862306a36Sopenharmony_ci 417962306a36Sopenharmony_ci btrfs_debug(fs_info, "process_recorded_refs %llu", sctx->cur_ino); 418062306a36Sopenharmony_ci 418162306a36Sopenharmony_ci /* 418262306a36Sopenharmony_ci * This should never happen as the root dir always has the same ref 418362306a36Sopenharmony_ci * which is always '..' 418462306a36Sopenharmony_ci */ 418562306a36Sopenharmony_ci BUG_ON(sctx->cur_ino <= BTRFS_FIRST_FREE_OBJECTID); 418662306a36Sopenharmony_ci 418762306a36Sopenharmony_ci valid_path = fs_path_alloc(); 418862306a36Sopenharmony_ci if (!valid_path) { 418962306a36Sopenharmony_ci ret = -ENOMEM; 419062306a36Sopenharmony_ci goto out; 419162306a36Sopenharmony_ci } 419262306a36Sopenharmony_ci 419362306a36Sopenharmony_ci /* 419462306a36Sopenharmony_ci * First, check if the first ref of the current inode was overwritten 419562306a36Sopenharmony_ci * before. If yes, we know that the current inode was already orphanized 419662306a36Sopenharmony_ci * and thus use the orphan name. If not, we can use get_cur_path to 419762306a36Sopenharmony_ci * get the path of the first ref as it would like while receiving at 419862306a36Sopenharmony_ci * this point in time. 419962306a36Sopenharmony_ci * New inodes are always orphan at the beginning, so force to use the 420062306a36Sopenharmony_ci * orphan name in this case. 420162306a36Sopenharmony_ci * The first ref is stored in valid_path and will be updated if it 420262306a36Sopenharmony_ci * gets moved around. 420362306a36Sopenharmony_ci */ 420462306a36Sopenharmony_ci if (!sctx->cur_inode_new) { 420562306a36Sopenharmony_ci ret = did_overwrite_first_ref(sctx, sctx->cur_ino, 420662306a36Sopenharmony_ci sctx->cur_inode_gen); 420762306a36Sopenharmony_ci if (ret < 0) 420862306a36Sopenharmony_ci goto out; 420962306a36Sopenharmony_ci if (ret) 421062306a36Sopenharmony_ci did_overwrite = 1; 421162306a36Sopenharmony_ci } 421262306a36Sopenharmony_ci if (sctx->cur_inode_new || did_overwrite) { 421362306a36Sopenharmony_ci ret = gen_unique_name(sctx, sctx->cur_ino, 421462306a36Sopenharmony_ci sctx->cur_inode_gen, valid_path); 421562306a36Sopenharmony_ci if (ret < 0) 421662306a36Sopenharmony_ci goto out; 421762306a36Sopenharmony_ci is_orphan = 1; 421862306a36Sopenharmony_ci } else { 421962306a36Sopenharmony_ci ret = get_cur_path(sctx, sctx->cur_ino, sctx->cur_inode_gen, 422062306a36Sopenharmony_ci valid_path); 422162306a36Sopenharmony_ci if (ret < 0) 422262306a36Sopenharmony_ci goto out; 422362306a36Sopenharmony_ci } 422462306a36Sopenharmony_ci 422562306a36Sopenharmony_ci /* 422662306a36Sopenharmony_ci * Before doing any rename and link operations, do a first pass on the 422762306a36Sopenharmony_ci * new references to orphanize any unprocessed inodes that may have a 422862306a36Sopenharmony_ci * reference that conflicts with one of the new references of the current 422962306a36Sopenharmony_ci * inode. This needs to happen first because a new reference may conflict 423062306a36Sopenharmony_ci * with the old reference of a parent directory, so we must make sure 423162306a36Sopenharmony_ci * that the path used for link and rename commands don't use an 423262306a36Sopenharmony_ci * orphanized name when an ancestor was not yet orphanized. 423362306a36Sopenharmony_ci * 423462306a36Sopenharmony_ci * Example: 423562306a36Sopenharmony_ci * 423662306a36Sopenharmony_ci * Parent snapshot: 423762306a36Sopenharmony_ci * 423862306a36Sopenharmony_ci * . (ino 256) 423962306a36Sopenharmony_ci * |----- testdir/ (ino 259) 424062306a36Sopenharmony_ci * | |----- a (ino 257) 424162306a36Sopenharmony_ci * | 424262306a36Sopenharmony_ci * |----- b (ino 258) 424362306a36Sopenharmony_ci * 424462306a36Sopenharmony_ci * Send snapshot: 424562306a36Sopenharmony_ci * 424662306a36Sopenharmony_ci * . (ino 256) 424762306a36Sopenharmony_ci * |----- testdir_2/ (ino 259) 424862306a36Sopenharmony_ci * | |----- a (ino 260) 424962306a36Sopenharmony_ci * | 425062306a36Sopenharmony_ci * |----- testdir (ino 257) 425162306a36Sopenharmony_ci * |----- b (ino 257) 425262306a36Sopenharmony_ci * |----- b2 (ino 258) 425362306a36Sopenharmony_ci * 425462306a36Sopenharmony_ci * Processing the new reference for inode 257 with name "b" may happen 425562306a36Sopenharmony_ci * before processing the new reference with name "testdir". If so, we 425662306a36Sopenharmony_ci * must make sure that by the time we send a link command to create the 425762306a36Sopenharmony_ci * hard link "b", inode 259 was already orphanized, since the generated 425862306a36Sopenharmony_ci * path in "valid_path" already contains the orphanized name for 259. 425962306a36Sopenharmony_ci * We are processing inode 257, so only later when processing 259 we do 426062306a36Sopenharmony_ci * the rename operation to change its temporary (orphanized) name to 426162306a36Sopenharmony_ci * "testdir_2". 426262306a36Sopenharmony_ci */ 426362306a36Sopenharmony_ci list_for_each_entry(cur, &sctx->new_refs, list) { 426462306a36Sopenharmony_ci ret = get_cur_inode_state(sctx, cur->dir, cur->dir_gen, NULL, NULL); 426562306a36Sopenharmony_ci if (ret < 0) 426662306a36Sopenharmony_ci goto out; 426762306a36Sopenharmony_ci if (ret == inode_state_will_create) 426862306a36Sopenharmony_ci continue; 426962306a36Sopenharmony_ci 427062306a36Sopenharmony_ci /* 427162306a36Sopenharmony_ci * Check if this new ref would overwrite the first ref of another 427262306a36Sopenharmony_ci * unprocessed inode. If yes, orphanize the overwritten inode. 427362306a36Sopenharmony_ci * If we find an overwritten ref that is not the first ref, 427462306a36Sopenharmony_ci * simply unlink it. 427562306a36Sopenharmony_ci */ 427662306a36Sopenharmony_ci ret = will_overwrite_ref(sctx, cur->dir, cur->dir_gen, 427762306a36Sopenharmony_ci cur->name, cur->name_len, 427862306a36Sopenharmony_ci &ow_inode, &ow_gen, &ow_mode); 427962306a36Sopenharmony_ci if (ret < 0) 428062306a36Sopenharmony_ci goto out; 428162306a36Sopenharmony_ci if (ret) { 428262306a36Sopenharmony_ci ret = is_first_ref(sctx->parent_root, 428362306a36Sopenharmony_ci ow_inode, cur->dir, cur->name, 428462306a36Sopenharmony_ci cur->name_len); 428562306a36Sopenharmony_ci if (ret < 0) 428662306a36Sopenharmony_ci goto out; 428762306a36Sopenharmony_ci if (ret) { 428862306a36Sopenharmony_ci struct name_cache_entry *nce; 428962306a36Sopenharmony_ci struct waiting_dir_move *wdm; 429062306a36Sopenharmony_ci 429162306a36Sopenharmony_ci if (orphanized_dir) { 429262306a36Sopenharmony_ci ret = refresh_ref_path(sctx, cur); 429362306a36Sopenharmony_ci if (ret < 0) 429462306a36Sopenharmony_ci goto out; 429562306a36Sopenharmony_ci } 429662306a36Sopenharmony_ci 429762306a36Sopenharmony_ci ret = orphanize_inode(sctx, ow_inode, ow_gen, 429862306a36Sopenharmony_ci cur->full_path); 429962306a36Sopenharmony_ci if (ret < 0) 430062306a36Sopenharmony_ci goto out; 430162306a36Sopenharmony_ci if (S_ISDIR(ow_mode)) 430262306a36Sopenharmony_ci orphanized_dir = true; 430362306a36Sopenharmony_ci 430462306a36Sopenharmony_ci /* 430562306a36Sopenharmony_ci * If ow_inode has its rename operation delayed 430662306a36Sopenharmony_ci * make sure that its orphanized name is used in 430762306a36Sopenharmony_ci * the source path when performing its rename 430862306a36Sopenharmony_ci * operation. 430962306a36Sopenharmony_ci */ 431062306a36Sopenharmony_ci wdm = get_waiting_dir_move(sctx, ow_inode); 431162306a36Sopenharmony_ci if (wdm) 431262306a36Sopenharmony_ci wdm->orphanized = true; 431362306a36Sopenharmony_ci 431462306a36Sopenharmony_ci /* 431562306a36Sopenharmony_ci * Make sure we clear our orphanized inode's 431662306a36Sopenharmony_ci * name from the name cache. This is because the 431762306a36Sopenharmony_ci * inode ow_inode might be an ancestor of some 431862306a36Sopenharmony_ci * other inode that will be orphanized as well 431962306a36Sopenharmony_ci * later and has an inode number greater than 432062306a36Sopenharmony_ci * sctx->send_progress. We need to prevent 432162306a36Sopenharmony_ci * future name lookups from using the old name 432262306a36Sopenharmony_ci * and get instead the orphan name. 432362306a36Sopenharmony_ci */ 432462306a36Sopenharmony_ci nce = name_cache_search(sctx, ow_inode, ow_gen); 432562306a36Sopenharmony_ci if (nce) 432662306a36Sopenharmony_ci btrfs_lru_cache_remove(&sctx->name_cache, 432762306a36Sopenharmony_ci &nce->entry); 432862306a36Sopenharmony_ci 432962306a36Sopenharmony_ci /* 433062306a36Sopenharmony_ci * ow_inode might currently be an ancestor of 433162306a36Sopenharmony_ci * cur_ino, therefore compute valid_path (the 433262306a36Sopenharmony_ci * current path of cur_ino) again because it 433362306a36Sopenharmony_ci * might contain the pre-orphanization name of 433462306a36Sopenharmony_ci * ow_inode, which is no longer valid. 433562306a36Sopenharmony_ci */ 433662306a36Sopenharmony_ci ret = is_ancestor(sctx->parent_root, 433762306a36Sopenharmony_ci ow_inode, ow_gen, 433862306a36Sopenharmony_ci sctx->cur_ino, NULL); 433962306a36Sopenharmony_ci if (ret > 0) { 434062306a36Sopenharmony_ci orphanized_ancestor = true; 434162306a36Sopenharmony_ci fs_path_reset(valid_path); 434262306a36Sopenharmony_ci ret = get_cur_path(sctx, sctx->cur_ino, 434362306a36Sopenharmony_ci sctx->cur_inode_gen, 434462306a36Sopenharmony_ci valid_path); 434562306a36Sopenharmony_ci } 434662306a36Sopenharmony_ci if (ret < 0) 434762306a36Sopenharmony_ci goto out; 434862306a36Sopenharmony_ci } else { 434962306a36Sopenharmony_ci /* 435062306a36Sopenharmony_ci * If we previously orphanized a directory that 435162306a36Sopenharmony_ci * collided with a new reference that we already 435262306a36Sopenharmony_ci * processed, recompute the current path because 435362306a36Sopenharmony_ci * that directory may be part of the path. 435462306a36Sopenharmony_ci */ 435562306a36Sopenharmony_ci if (orphanized_dir) { 435662306a36Sopenharmony_ci ret = refresh_ref_path(sctx, cur); 435762306a36Sopenharmony_ci if (ret < 0) 435862306a36Sopenharmony_ci goto out; 435962306a36Sopenharmony_ci } 436062306a36Sopenharmony_ci ret = send_unlink(sctx, cur->full_path); 436162306a36Sopenharmony_ci if (ret < 0) 436262306a36Sopenharmony_ci goto out; 436362306a36Sopenharmony_ci } 436462306a36Sopenharmony_ci } 436562306a36Sopenharmony_ci 436662306a36Sopenharmony_ci } 436762306a36Sopenharmony_ci 436862306a36Sopenharmony_ci list_for_each_entry(cur, &sctx->new_refs, list) { 436962306a36Sopenharmony_ci /* 437062306a36Sopenharmony_ci * We may have refs where the parent directory does not exist 437162306a36Sopenharmony_ci * yet. This happens if the parent directories inum is higher 437262306a36Sopenharmony_ci * than the current inum. To handle this case, we create the 437362306a36Sopenharmony_ci * parent directory out of order. But we need to check if this 437462306a36Sopenharmony_ci * did already happen before due to other refs in the same dir. 437562306a36Sopenharmony_ci */ 437662306a36Sopenharmony_ci ret = get_cur_inode_state(sctx, cur->dir, cur->dir_gen, NULL, NULL); 437762306a36Sopenharmony_ci if (ret < 0) 437862306a36Sopenharmony_ci goto out; 437962306a36Sopenharmony_ci if (ret == inode_state_will_create) { 438062306a36Sopenharmony_ci ret = 0; 438162306a36Sopenharmony_ci /* 438262306a36Sopenharmony_ci * First check if any of the current inodes refs did 438362306a36Sopenharmony_ci * already create the dir. 438462306a36Sopenharmony_ci */ 438562306a36Sopenharmony_ci list_for_each_entry(cur2, &sctx->new_refs, list) { 438662306a36Sopenharmony_ci if (cur == cur2) 438762306a36Sopenharmony_ci break; 438862306a36Sopenharmony_ci if (cur2->dir == cur->dir) { 438962306a36Sopenharmony_ci ret = 1; 439062306a36Sopenharmony_ci break; 439162306a36Sopenharmony_ci } 439262306a36Sopenharmony_ci } 439362306a36Sopenharmony_ci 439462306a36Sopenharmony_ci /* 439562306a36Sopenharmony_ci * If that did not happen, check if a previous inode 439662306a36Sopenharmony_ci * did already create the dir. 439762306a36Sopenharmony_ci */ 439862306a36Sopenharmony_ci if (!ret) 439962306a36Sopenharmony_ci ret = did_create_dir(sctx, cur->dir); 440062306a36Sopenharmony_ci if (ret < 0) 440162306a36Sopenharmony_ci goto out; 440262306a36Sopenharmony_ci if (!ret) { 440362306a36Sopenharmony_ci ret = send_create_inode(sctx, cur->dir); 440462306a36Sopenharmony_ci if (ret < 0) 440562306a36Sopenharmony_ci goto out; 440662306a36Sopenharmony_ci cache_dir_created(sctx, cur->dir); 440762306a36Sopenharmony_ci } 440862306a36Sopenharmony_ci } 440962306a36Sopenharmony_ci 441062306a36Sopenharmony_ci if (S_ISDIR(sctx->cur_inode_mode) && sctx->parent_root) { 441162306a36Sopenharmony_ci ret = wait_for_dest_dir_move(sctx, cur, is_orphan); 441262306a36Sopenharmony_ci if (ret < 0) 441362306a36Sopenharmony_ci goto out; 441462306a36Sopenharmony_ci if (ret == 1) { 441562306a36Sopenharmony_ci can_rename = false; 441662306a36Sopenharmony_ci *pending_move = 1; 441762306a36Sopenharmony_ci } 441862306a36Sopenharmony_ci } 441962306a36Sopenharmony_ci 442062306a36Sopenharmony_ci if (S_ISDIR(sctx->cur_inode_mode) && sctx->parent_root && 442162306a36Sopenharmony_ci can_rename) { 442262306a36Sopenharmony_ci ret = wait_for_parent_move(sctx, cur, is_orphan); 442362306a36Sopenharmony_ci if (ret < 0) 442462306a36Sopenharmony_ci goto out; 442562306a36Sopenharmony_ci if (ret == 1) { 442662306a36Sopenharmony_ci can_rename = false; 442762306a36Sopenharmony_ci *pending_move = 1; 442862306a36Sopenharmony_ci } 442962306a36Sopenharmony_ci } 443062306a36Sopenharmony_ci 443162306a36Sopenharmony_ci /* 443262306a36Sopenharmony_ci * link/move the ref to the new place. If we have an orphan 443362306a36Sopenharmony_ci * inode, move it and update valid_path. If not, link or move 443462306a36Sopenharmony_ci * it depending on the inode mode. 443562306a36Sopenharmony_ci */ 443662306a36Sopenharmony_ci if (is_orphan && can_rename) { 443762306a36Sopenharmony_ci ret = send_rename(sctx, valid_path, cur->full_path); 443862306a36Sopenharmony_ci if (ret < 0) 443962306a36Sopenharmony_ci goto out; 444062306a36Sopenharmony_ci is_orphan = 0; 444162306a36Sopenharmony_ci ret = fs_path_copy(valid_path, cur->full_path); 444262306a36Sopenharmony_ci if (ret < 0) 444362306a36Sopenharmony_ci goto out; 444462306a36Sopenharmony_ci } else if (can_rename) { 444562306a36Sopenharmony_ci if (S_ISDIR(sctx->cur_inode_mode)) { 444662306a36Sopenharmony_ci /* 444762306a36Sopenharmony_ci * Dirs can't be linked, so move it. For moved 444862306a36Sopenharmony_ci * dirs, we always have one new and one deleted 444962306a36Sopenharmony_ci * ref. The deleted ref is ignored later. 445062306a36Sopenharmony_ci */ 445162306a36Sopenharmony_ci ret = send_rename(sctx, valid_path, 445262306a36Sopenharmony_ci cur->full_path); 445362306a36Sopenharmony_ci if (!ret) 445462306a36Sopenharmony_ci ret = fs_path_copy(valid_path, 445562306a36Sopenharmony_ci cur->full_path); 445662306a36Sopenharmony_ci if (ret < 0) 445762306a36Sopenharmony_ci goto out; 445862306a36Sopenharmony_ci } else { 445962306a36Sopenharmony_ci /* 446062306a36Sopenharmony_ci * We might have previously orphanized an inode 446162306a36Sopenharmony_ci * which is an ancestor of our current inode, 446262306a36Sopenharmony_ci * so our reference's full path, which was 446362306a36Sopenharmony_ci * computed before any such orphanizations, must 446462306a36Sopenharmony_ci * be updated. 446562306a36Sopenharmony_ci */ 446662306a36Sopenharmony_ci if (orphanized_dir) { 446762306a36Sopenharmony_ci ret = update_ref_path(sctx, cur); 446862306a36Sopenharmony_ci if (ret < 0) 446962306a36Sopenharmony_ci goto out; 447062306a36Sopenharmony_ci } 447162306a36Sopenharmony_ci ret = send_link(sctx, cur->full_path, 447262306a36Sopenharmony_ci valid_path); 447362306a36Sopenharmony_ci if (ret < 0) 447462306a36Sopenharmony_ci goto out; 447562306a36Sopenharmony_ci } 447662306a36Sopenharmony_ci } 447762306a36Sopenharmony_ci ret = dup_ref(cur, &check_dirs); 447862306a36Sopenharmony_ci if (ret < 0) 447962306a36Sopenharmony_ci goto out; 448062306a36Sopenharmony_ci } 448162306a36Sopenharmony_ci 448262306a36Sopenharmony_ci if (S_ISDIR(sctx->cur_inode_mode) && sctx->cur_inode_deleted) { 448362306a36Sopenharmony_ci /* 448462306a36Sopenharmony_ci * Check if we can already rmdir the directory. If not, 448562306a36Sopenharmony_ci * orphanize it. For every dir item inside that gets deleted 448662306a36Sopenharmony_ci * later, we do this check again and rmdir it then if possible. 448762306a36Sopenharmony_ci * See the use of check_dirs for more details. 448862306a36Sopenharmony_ci */ 448962306a36Sopenharmony_ci ret = can_rmdir(sctx, sctx->cur_ino, sctx->cur_inode_gen); 449062306a36Sopenharmony_ci if (ret < 0) 449162306a36Sopenharmony_ci goto out; 449262306a36Sopenharmony_ci if (ret) { 449362306a36Sopenharmony_ci ret = send_rmdir(sctx, valid_path); 449462306a36Sopenharmony_ci if (ret < 0) 449562306a36Sopenharmony_ci goto out; 449662306a36Sopenharmony_ci } else if (!is_orphan) { 449762306a36Sopenharmony_ci ret = orphanize_inode(sctx, sctx->cur_ino, 449862306a36Sopenharmony_ci sctx->cur_inode_gen, valid_path); 449962306a36Sopenharmony_ci if (ret < 0) 450062306a36Sopenharmony_ci goto out; 450162306a36Sopenharmony_ci is_orphan = 1; 450262306a36Sopenharmony_ci } 450362306a36Sopenharmony_ci 450462306a36Sopenharmony_ci list_for_each_entry(cur, &sctx->deleted_refs, list) { 450562306a36Sopenharmony_ci ret = dup_ref(cur, &check_dirs); 450662306a36Sopenharmony_ci if (ret < 0) 450762306a36Sopenharmony_ci goto out; 450862306a36Sopenharmony_ci } 450962306a36Sopenharmony_ci } else if (S_ISDIR(sctx->cur_inode_mode) && 451062306a36Sopenharmony_ci !list_empty(&sctx->deleted_refs)) { 451162306a36Sopenharmony_ci /* 451262306a36Sopenharmony_ci * We have a moved dir. Add the old parent to check_dirs 451362306a36Sopenharmony_ci */ 451462306a36Sopenharmony_ci cur = list_entry(sctx->deleted_refs.next, struct recorded_ref, 451562306a36Sopenharmony_ci list); 451662306a36Sopenharmony_ci ret = dup_ref(cur, &check_dirs); 451762306a36Sopenharmony_ci if (ret < 0) 451862306a36Sopenharmony_ci goto out; 451962306a36Sopenharmony_ci } else if (!S_ISDIR(sctx->cur_inode_mode)) { 452062306a36Sopenharmony_ci /* 452162306a36Sopenharmony_ci * We have a non dir inode. Go through all deleted refs and 452262306a36Sopenharmony_ci * unlink them if they were not already overwritten by other 452362306a36Sopenharmony_ci * inodes. 452462306a36Sopenharmony_ci */ 452562306a36Sopenharmony_ci list_for_each_entry(cur, &sctx->deleted_refs, list) { 452662306a36Sopenharmony_ci ret = did_overwrite_ref(sctx, cur->dir, cur->dir_gen, 452762306a36Sopenharmony_ci sctx->cur_ino, sctx->cur_inode_gen, 452862306a36Sopenharmony_ci cur->name, cur->name_len); 452962306a36Sopenharmony_ci if (ret < 0) 453062306a36Sopenharmony_ci goto out; 453162306a36Sopenharmony_ci if (!ret) { 453262306a36Sopenharmony_ci /* 453362306a36Sopenharmony_ci * If we orphanized any ancestor before, we need 453462306a36Sopenharmony_ci * to recompute the full path for deleted names, 453562306a36Sopenharmony_ci * since any such path was computed before we 453662306a36Sopenharmony_ci * processed any references and orphanized any 453762306a36Sopenharmony_ci * ancestor inode. 453862306a36Sopenharmony_ci */ 453962306a36Sopenharmony_ci if (orphanized_ancestor) { 454062306a36Sopenharmony_ci ret = update_ref_path(sctx, cur); 454162306a36Sopenharmony_ci if (ret < 0) 454262306a36Sopenharmony_ci goto out; 454362306a36Sopenharmony_ci } 454462306a36Sopenharmony_ci ret = send_unlink(sctx, cur->full_path); 454562306a36Sopenharmony_ci if (ret < 0) 454662306a36Sopenharmony_ci goto out; 454762306a36Sopenharmony_ci } 454862306a36Sopenharmony_ci ret = dup_ref(cur, &check_dirs); 454962306a36Sopenharmony_ci if (ret < 0) 455062306a36Sopenharmony_ci goto out; 455162306a36Sopenharmony_ci } 455262306a36Sopenharmony_ci /* 455362306a36Sopenharmony_ci * If the inode is still orphan, unlink the orphan. This may 455462306a36Sopenharmony_ci * happen when a previous inode did overwrite the first ref 455562306a36Sopenharmony_ci * of this inode and no new refs were added for the current 455662306a36Sopenharmony_ci * inode. Unlinking does not mean that the inode is deleted in 455762306a36Sopenharmony_ci * all cases. There may still be links to this inode in other 455862306a36Sopenharmony_ci * places. 455962306a36Sopenharmony_ci */ 456062306a36Sopenharmony_ci if (is_orphan) { 456162306a36Sopenharmony_ci ret = send_unlink(sctx, valid_path); 456262306a36Sopenharmony_ci if (ret < 0) 456362306a36Sopenharmony_ci goto out; 456462306a36Sopenharmony_ci } 456562306a36Sopenharmony_ci } 456662306a36Sopenharmony_ci 456762306a36Sopenharmony_ci /* 456862306a36Sopenharmony_ci * We did collect all parent dirs where cur_inode was once located. We 456962306a36Sopenharmony_ci * now go through all these dirs and check if they are pending for 457062306a36Sopenharmony_ci * deletion and if it's finally possible to perform the rmdir now. 457162306a36Sopenharmony_ci * We also update the inode stats of the parent dirs here. 457262306a36Sopenharmony_ci */ 457362306a36Sopenharmony_ci list_for_each_entry(cur, &check_dirs, list) { 457462306a36Sopenharmony_ci /* 457562306a36Sopenharmony_ci * In case we had refs into dirs that were not processed yet, 457662306a36Sopenharmony_ci * we don't need to do the utime and rmdir logic for these dirs. 457762306a36Sopenharmony_ci * The dir will be processed later. 457862306a36Sopenharmony_ci */ 457962306a36Sopenharmony_ci if (cur->dir > sctx->cur_ino) 458062306a36Sopenharmony_ci continue; 458162306a36Sopenharmony_ci 458262306a36Sopenharmony_ci ret = get_cur_inode_state(sctx, cur->dir, cur->dir_gen, NULL, NULL); 458362306a36Sopenharmony_ci if (ret < 0) 458462306a36Sopenharmony_ci goto out; 458562306a36Sopenharmony_ci 458662306a36Sopenharmony_ci if (ret == inode_state_did_create || 458762306a36Sopenharmony_ci ret == inode_state_no_change) { 458862306a36Sopenharmony_ci ret = cache_dir_utimes(sctx, cur->dir, cur->dir_gen); 458962306a36Sopenharmony_ci if (ret < 0) 459062306a36Sopenharmony_ci goto out; 459162306a36Sopenharmony_ci } else if (ret == inode_state_did_delete && 459262306a36Sopenharmony_ci cur->dir != last_dir_ino_rm) { 459362306a36Sopenharmony_ci ret = can_rmdir(sctx, cur->dir, cur->dir_gen); 459462306a36Sopenharmony_ci if (ret < 0) 459562306a36Sopenharmony_ci goto out; 459662306a36Sopenharmony_ci if (ret) { 459762306a36Sopenharmony_ci ret = get_cur_path(sctx, cur->dir, 459862306a36Sopenharmony_ci cur->dir_gen, valid_path); 459962306a36Sopenharmony_ci if (ret < 0) 460062306a36Sopenharmony_ci goto out; 460162306a36Sopenharmony_ci ret = send_rmdir(sctx, valid_path); 460262306a36Sopenharmony_ci if (ret < 0) 460362306a36Sopenharmony_ci goto out; 460462306a36Sopenharmony_ci last_dir_ino_rm = cur->dir; 460562306a36Sopenharmony_ci } 460662306a36Sopenharmony_ci } 460762306a36Sopenharmony_ci } 460862306a36Sopenharmony_ci 460962306a36Sopenharmony_ci ret = 0; 461062306a36Sopenharmony_ci 461162306a36Sopenharmony_ciout: 461262306a36Sopenharmony_ci __free_recorded_refs(&check_dirs); 461362306a36Sopenharmony_ci free_recorded_refs(sctx); 461462306a36Sopenharmony_ci fs_path_free(valid_path); 461562306a36Sopenharmony_ci return ret; 461662306a36Sopenharmony_ci} 461762306a36Sopenharmony_ci 461862306a36Sopenharmony_cistatic int rbtree_ref_comp(const void *k, const struct rb_node *node) 461962306a36Sopenharmony_ci{ 462062306a36Sopenharmony_ci const struct recorded_ref *data = k; 462162306a36Sopenharmony_ci const struct recorded_ref *ref = rb_entry(node, struct recorded_ref, node); 462262306a36Sopenharmony_ci int result; 462362306a36Sopenharmony_ci 462462306a36Sopenharmony_ci if (data->dir > ref->dir) 462562306a36Sopenharmony_ci return 1; 462662306a36Sopenharmony_ci if (data->dir < ref->dir) 462762306a36Sopenharmony_ci return -1; 462862306a36Sopenharmony_ci if (data->dir_gen > ref->dir_gen) 462962306a36Sopenharmony_ci return 1; 463062306a36Sopenharmony_ci if (data->dir_gen < ref->dir_gen) 463162306a36Sopenharmony_ci return -1; 463262306a36Sopenharmony_ci if (data->name_len > ref->name_len) 463362306a36Sopenharmony_ci return 1; 463462306a36Sopenharmony_ci if (data->name_len < ref->name_len) 463562306a36Sopenharmony_ci return -1; 463662306a36Sopenharmony_ci result = strcmp(data->name, ref->name); 463762306a36Sopenharmony_ci if (result > 0) 463862306a36Sopenharmony_ci return 1; 463962306a36Sopenharmony_ci if (result < 0) 464062306a36Sopenharmony_ci return -1; 464162306a36Sopenharmony_ci return 0; 464262306a36Sopenharmony_ci} 464362306a36Sopenharmony_ci 464462306a36Sopenharmony_cistatic bool rbtree_ref_less(struct rb_node *node, const struct rb_node *parent) 464562306a36Sopenharmony_ci{ 464662306a36Sopenharmony_ci const struct recorded_ref *entry = rb_entry(node, struct recorded_ref, node); 464762306a36Sopenharmony_ci 464862306a36Sopenharmony_ci return rbtree_ref_comp(entry, parent) < 0; 464962306a36Sopenharmony_ci} 465062306a36Sopenharmony_ci 465162306a36Sopenharmony_cistatic int record_ref_in_tree(struct rb_root *root, struct list_head *refs, 465262306a36Sopenharmony_ci struct fs_path *name, u64 dir, u64 dir_gen, 465362306a36Sopenharmony_ci struct send_ctx *sctx) 465462306a36Sopenharmony_ci{ 465562306a36Sopenharmony_ci int ret = 0; 465662306a36Sopenharmony_ci struct fs_path *path = NULL; 465762306a36Sopenharmony_ci struct recorded_ref *ref = NULL; 465862306a36Sopenharmony_ci 465962306a36Sopenharmony_ci path = fs_path_alloc(); 466062306a36Sopenharmony_ci if (!path) { 466162306a36Sopenharmony_ci ret = -ENOMEM; 466262306a36Sopenharmony_ci goto out; 466362306a36Sopenharmony_ci } 466462306a36Sopenharmony_ci 466562306a36Sopenharmony_ci ref = recorded_ref_alloc(); 466662306a36Sopenharmony_ci if (!ref) { 466762306a36Sopenharmony_ci ret = -ENOMEM; 466862306a36Sopenharmony_ci goto out; 466962306a36Sopenharmony_ci } 467062306a36Sopenharmony_ci 467162306a36Sopenharmony_ci ret = get_cur_path(sctx, dir, dir_gen, path); 467262306a36Sopenharmony_ci if (ret < 0) 467362306a36Sopenharmony_ci goto out; 467462306a36Sopenharmony_ci ret = fs_path_add_path(path, name); 467562306a36Sopenharmony_ci if (ret < 0) 467662306a36Sopenharmony_ci goto out; 467762306a36Sopenharmony_ci 467862306a36Sopenharmony_ci ref->dir = dir; 467962306a36Sopenharmony_ci ref->dir_gen = dir_gen; 468062306a36Sopenharmony_ci set_ref_path(ref, path); 468162306a36Sopenharmony_ci list_add_tail(&ref->list, refs); 468262306a36Sopenharmony_ci rb_add(&ref->node, root, rbtree_ref_less); 468362306a36Sopenharmony_ci ref->root = root; 468462306a36Sopenharmony_ciout: 468562306a36Sopenharmony_ci if (ret) { 468662306a36Sopenharmony_ci if (path && (!ref || !ref->full_path)) 468762306a36Sopenharmony_ci fs_path_free(path); 468862306a36Sopenharmony_ci recorded_ref_free(ref); 468962306a36Sopenharmony_ci } 469062306a36Sopenharmony_ci return ret; 469162306a36Sopenharmony_ci} 469262306a36Sopenharmony_ci 469362306a36Sopenharmony_cistatic int record_new_ref_if_needed(int num, u64 dir, int index, 469462306a36Sopenharmony_ci struct fs_path *name, void *ctx) 469562306a36Sopenharmony_ci{ 469662306a36Sopenharmony_ci int ret = 0; 469762306a36Sopenharmony_ci struct send_ctx *sctx = ctx; 469862306a36Sopenharmony_ci struct rb_node *node = NULL; 469962306a36Sopenharmony_ci struct recorded_ref data; 470062306a36Sopenharmony_ci struct recorded_ref *ref; 470162306a36Sopenharmony_ci u64 dir_gen; 470262306a36Sopenharmony_ci 470362306a36Sopenharmony_ci ret = get_inode_gen(sctx->send_root, dir, &dir_gen); 470462306a36Sopenharmony_ci if (ret < 0) 470562306a36Sopenharmony_ci goto out; 470662306a36Sopenharmony_ci 470762306a36Sopenharmony_ci data.dir = dir; 470862306a36Sopenharmony_ci data.dir_gen = dir_gen; 470962306a36Sopenharmony_ci set_ref_path(&data, name); 471062306a36Sopenharmony_ci node = rb_find(&data, &sctx->rbtree_deleted_refs, rbtree_ref_comp); 471162306a36Sopenharmony_ci if (node) { 471262306a36Sopenharmony_ci ref = rb_entry(node, struct recorded_ref, node); 471362306a36Sopenharmony_ci recorded_ref_free(ref); 471462306a36Sopenharmony_ci } else { 471562306a36Sopenharmony_ci ret = record_ref_in_tree(&sctx->rbtree_new_refs, 471662306a36Sopenharmony_ci &sctx->new_refs, name, dir, dir_gen, 471762306a36Sopenharmony_ci sctx); 471862306a36Sopenharmony_ci } 471962306a36Sopenharmony_ciout: 472062306a36Sopenharmony_ci return ret; 472162306a36Sopenharmony_ci} 472262306a36Sopenharmony_ci 472362306a36Sopenharmony_cistatic int record_deleted_ref_if_needed(int num, u64 dir, int index, 472462306a36Sopenharmony_ci struct fs_path *name, void *ctx) 472562306a36Sopenharmony_ci{ 472662306a36Sopenharmony_ci int ret = 0; 472762306a36Sopenharmony_ci struct send_ctx *sctx = ctx; 472862306a36Sopenharmony_ci struct rb_node *node = NULL; 472962306a36Sopenharmony_ci struct recorded_ref data; 473062306a36Sopenharmony_ci struct recorded_ref *ref; 473162306a36Sopenharmony_ci u64 dir_gen; 473262306a36Sopenharmony_ci 473362306a36Sopenharmony_ci ret = get_inode_gen(sctx->parent_root, dir, &dir_gen); 473462306a36Sopenharmony_ci if (ret < 0) 473562306a36Sopenharmony_ci goto out; 473662306a36Sopenharmony_ci 473762306a36Sopenharmony_ci data.dir = dir; 473862306a36Sopenharmony_ci data.dir_gen = dir_gen; 473962306a36Sopenharmony_ci set_ref_path(&data, name); 474062306a36Sopenharmony_ci node = rb_find(&data, &sctx->rbtree_new_refs, rbtree_ref_comp); 474162306a36Sopenharmony_ci if (node) { 474262306a36Sopenharmony_ci ref = rb_entry(node, struct recorded_ref, node); 474362306a36Sopenharmony_ci recorded_ref_free(ref); 474462306a36Sopenharmony_ci } else { 474562306a36Sopenharmony_ci ret = record_ref_in_tree(&sctx->rbtree_deleted_refs, 474662306a36Sopenharmony_ci &sctx->deleted_refs, name, dir, 474762306a36Sopenharmony_ci dir_gen, sctx); 474862306a36Sopenharmony_ci } 474962306a36Sopenharmony_ciout: 475062306a36Sopenharmony_ci return ret; 475162306a36Sopenharmony_ci} 475262306a36Sopenharmony_ci 475362306a36Sopenharmony_cistatic int record_new_ref(struct send_ctx *sctx) 475462306a36Sopenharmony_ci{ 475562306a36Sopenharmony_ci int ret; 475662306a36Sopenharmony_ci 475762306a36Sopenharmony_ci ret = iterate_inode_ref(sctx->send_root, sctx->left_path, 475862306a36Sopenharmony_ci sctx->cmp_key, 0, record_new_ref_if_needed, sctx); 475962306a36Sopenharmony_ci if (ret < 0) 476062306a36Sopenharmony_ci goto out; 476162306a36Sopenharmony_ci ret = 0; 476262306a36Sopenharmony_ci 476362306a36Sopenharmony_ciout: 476462306a36Sopenharmony_ci return ret; 476562306a36Sopenharmony_ci} 476662306a36Sopenharmony_ci 476762306a36Sopenharmony_cistatic int record_deleted_ref(struct send_ctx *sctx) 476862306a36Sopenharmony_ci{ 476962306a36Sopenharmony_ci int ret; 477062306a36Sopenharmony_ci 477162306a36Sopenharmony_ci ret = iterate_inode_ref(sctx->parent_root, sctx->right_path, 477262306a36Sopenharmony_ci sctx->cmp_key, 0, record_deleted_ref_if_needed, 477362306a36Sopenharmony_ci sctx); 477462306a36Sopenharmony_ci if (ret < 0) 477562306a36Sopenharmony_ci goto out; 477662306a36Sopenharmony_ci ret = 0; 477762306a36Sopenharmony_ci 477862306a36Sopenharmony_ciout: 477962306a36Sopenharmony_ci return ret; 478062306a36Sopenharmony_ci} 478162306a36Sopenharmony_ci 478262306a36Sopenharmony_cistatic int record_changed_ref(struct send_ctx *sctx) 478362306a36Sopenharmony_ci{ 478462306a36Sopenharmony_ci int ret = 0; 478562306a36Sopenharmony_ci 478662306a36Sopenharmony_ci ret = iterate_inode_ref(sctx->send_root, sctx->left_path, 478762306a36Sopenharmony_ci sctx->cmp_key, 0, record_new_ref_if_needed, sctx); 478862306a36Sopenharmony_ci if (ret < 0) 478962306a36Sopenharmony_ci goto out; 479062306a36Sopenharmony_ci ret = iterate_inode_ref(sctx->parent_root, sctx->right_path, 479162306a36Sopenharmony_ci sctx->cmp_key, 0, record_deleted_ref_if_needed, sctx); 479262306a36Sopenharmony_ci if (ret < 0) 479362306a36Sopenharmony_ci goto out; 479462306a36Sopenharmony_ci ret = 0; 479562306a36Sopenharmony_ci 479662306a36Sopenharmony_ciout: 479762306a36Sopenharmony_ci return ret; 479862306a36Sopenharmony_ci} 479962306a36Sopenharmony_ci 480062306a36Sopenharmony_ci/* 480162306a36Sopenharmony_ci * Record and process all refs at once. Needed when an inode changes the 480262306a36Sopenharmony_ci * generation number, which means that it was deleted and recreated. 480362306a36Sopenharmony_ci */ 480462306a36Sopenharmony_cistatic int process_all_refs(struct send_ctx *sctx, 480562306a36Sopenharmony_ci enum btrfs_compare_tree_result cmd) 480662306a36Sopenharmony_ci{ 480762306a36Sopenharmony_ci int ret = 0; 480862306a36Sopenharmony_ci int iter_ret = 0; 480962306a36Sopenharmony_ci struct btrfs_root *root; 481062306a36Sopenharmony_ci struct btrfs_path *path; 481162306a36Sopenharmony_ci struct btrfs_key key; 481262306a36Sopenharmony_ci struct btrfs_key found_key; 481362306a36Sopenharmony_ci iterate_inode_ref_t cb; 481462306a36Sopenharmony_ci int pending_move = 0; 481562306a36Sopenharmony_ci 481662306a36Sopenharmony_ci path = alloc_path_for_send(); 481762306a36Sopenharmony_ci if (!path) 481862306a36Sopenharmony_ci return -ENOMEM; 481962306a36Sopenharmony_ci 482062306a36Sopenharmony_ci if (cmd == BTRFS_COMPARE_TREE_NEW) { 482162306a36Sopenharmony_ci root = sctx->send_root; 482262306a36Sopenharmony_ci cb = record_new_ref_if_needed; 482362306a36Sopenharmony_ci } else if (cmd == BTRFS_COMPARE_TREE_DELETED) { 482462306a36Sopenharmony_ci root = sctx->parent_root; 482562306a36Sopenharmony_ci cb = record_deleted_ref_if_needed; 482662306a36Sopenharmony_ci } else { 482762306a36Sopenharmony_ci btrfs_err(sctx->send_root->fs_info, 482862306a36Sopenharmony_ci "Wrong command %d in process_all_refs", cmd); 482962306a36Sopenharmony_ci ret = -EINVAL; 483062306a36Sopenharmony_ci goto out; 483162306a36Sopenharmony_ci } 483262306a36Sopenharmony_ci 483362306a36Sopenharmony_ci key.objectid = sctx->cmp_key->objectid; 483462306a36Sopenharmony_ci key.type = BTRFS_INODE_REF_KEY; 483562306a36Sopenharmony_ci key.offset = 0; 483662306a36Sopenharmony_ci btrfs_for_each_slot(root, &key, &found_key, path, iter_ret) { 483762306a36Sopenharmony_ci if (found_key.objectid != key.objectid || 483862306a36Sopenharmony_ci (found_key.type != BTRFS_INODE_REF_KEY && 483962306a36Sopenharmony_ci found_key.type != BTRFS_INODE_EXTREF_KEY)) 484062306a36Sopenharmony_ci break; 484162306a36Sopenharmony_ci 484262306a36Sopenharmony_ci ret = iterate_inode_ref(root, path, &found_key, 0, cb, sctx); 484362306a36Sopenharmony_ci if (ret < 0) 484462306a36Sopenharmony_ci goto out; 484562306a36Sopenharmony_ci } 484662306a36Sopenharmony_ci /* Catch error found during iteration */ 484762306a36Sopenharmony_ci if (iter_ret < 0) { 484862306a36Sopenharmony_ci ret = iter_ret; 484962306a36Sopenharmony_ci goto out; 485062306a36Sopenharmony_ci } 485162306a36Sopenharmony_ci btrfs_release_path(path); 485262306a36Sopenharmony_ci 485362306a36Sopenharmony_ci /* 485462306a36Sopenharmony_ci * We don't actually care about pending_move as we are simply 485562306a36Sopenharmony_ci * re-creating this inode and will be rename'ing it into place once we 485662306a36Sopenharmony_ci * rename the parent directory. 485762306a36Sopenharmony_ci */ 485862306a36Sopenharmony_ci ret = process_recorded_refs(sctx, &pending_move); 485962306a36Sopenharmony_ciout: 486062306a36Sopenharmony_ci btrfs_free_path(path); 486162306a36Sopenharmony_ci return ret; 486262306a36Sopenharmony_ci} 486362306a36Sopenharmony_ci 486462306a36Sopenharmony_cistatic int send_set_xattr(struct send_ctx *sctx, 486562306a36Sopenharmony_ci struct fs_path *path, 486662306a36Sopenharmony_ci const char *name, int name_len, 486762306a36Sopenharmony_ci const char *data, int data_len) 486862306a36Sopenharmony_ci{ 486962306a36Sopenharmony_ci int ret = 0; 487062306a36Sopenharmony_ci 487162306a36Sopenharmony_ci ret = begin_cmd(sctx, BTRFS_SEND_C_SET_XATTR); 487262306a36Sopenharmony_ci if (ret < 0) 487362306a36Sopenharmony_ci goto out; 487462306a36Sopenharmony_ci 487562306a36Sopenharmony_ci TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, path); 487662306a36Sopenharmony_ci TLV_PUT_STRING(sctx, BTRFS_SEND_A_XATTR_NAME, name, name_len); 487762306a36Sopenharmony_ci TLV_PUT(sctx, BTRFS_SEND_A_XATTR_DATA, data, data_len); 487862306a36Sopenharmony_ci 487962306a36Sopenharmony_ci ret = send_cmd(sctx); 488062306a36Sopenharmony_ci 488162306a36Sopenharmony_citlv_put_failure: 488262306a36Sopenharmony_ciout: 488362306a36Sopenharmony_ci return ret; 488462306a36Sopenharmony_ci} 488562306a36Sopenharmony_ci 488662306a36Sopenharmony_cistatic int send_remove_xattr(struct send_ctx *sctx, 488762306a36Sopenharmony_ci struct fs_path *path, 488862306a36Sopenharmony_ci const char *name, int name_len) 488962306a36Sopenharmony_ci{ 489062306a36Sopenharmony_ci int ret = 0; 489162306a36Sopenharmony_ci 489262306a36Sopenharmony_ci ret = begin_cmd(sctx, BTRFS_SEND_C_REMOVE_XATTR); 489362306a36Sopenharmony_ci if (ret < 0) 489462306a36Sopenharmony_ci goto out; 489562306a36Sopenharmony_ci 489662306a36Sopenharmony_ci TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, path); 489762306a36Sopenharmony_ci TLV_PUT_STRING(sctx, BTRFS_SEND_A_XATTR_NAME, name, name_len); 489862306a36Sopenharmony_ci 489962306a36Sopenharmony_ci ret = send_cmd(sctx); 490062306a36Sopenharmony_ci 490162306a36Sopenharmony_citlv_put_failure: 490262306a36Sopenharmony_ciout: 490362306a36Sopenharmony_ci return ret; 490462306a36Sopenharmony_ci} 490562306a36Sopenharmony_ci 490662306a36Sopenharmony_cistatic int __process_new_xattr(int num, struct btrfs_key *di_key, 490762306a36Sopenharmony_ci const char *name, int name_len, const char *data, 490862306a36Sopenharmony_ci int data_len, void *ctx) 490962306a36Sopenharmony_ci{ 491062306a36Sopenharmony_ci int ret; 491162306a36Sopenharmony_ci struct send_ctx *sctx = ctx; 491262306a36Sopenharmony_ci struct fs_path *p; 491362306a36Sopenharmony_ci struct posix_acl_xattr_header dummy_acl; 491462306a36Sopenharmony_ci 491562306a36Sopenharmony_ci /* Capabilities are emitted by finish_inode_if_needed */ 491662306a36Sopenharmony_ci if (!strncmp(name, XATTR_NAME_CAPS, name_len)) 491762306a36Sopenharmony_ci return 0; 491862306a36Sopenharmony_ci 491962306a36Sopenharmony_ci p = fs_path_alloc(); 492062306a36Sopenharmony_ci if (!p) 492162306a36Sopenharmony_ci return -ENOMEM; 492262306a36Sopenharmony_ci 492362306a36Sopenharmony_ci /* 492462306a36Sopenharmony_ci * This hack is needed because empty acls are stored as zero byte 492562306a36Sopenharmony_ci * data in xattrs. Problem with that is, that receiving these zero byte 492662306a36Sopenharmony_ci * acls will fail later. To fix this, we send a dummy acl list that 492762306a36Sopenharmony_ci * only contains the version number and no entries. 492862306a36Sopenharmony_ci */ 492962306a36Sopenharmony_ci if (!strncmp(name, XATTR_NAME_POSIX_ACL_ACCESS, name_len) || 493062306a36Sopenharmony_ci !strncmp(name, XATTR_NAME_POSIX_ACL_DEFAULT, name_len)) { 493162306a36Sopenharmony_ci if (data_len == 0) { 493262306a36Sopenharmony_ci dummy_acl.a_version = 493362306a36Sopenharmony_ci cpu_to_le32(POSIX_ACL_XATTR_VERSION); 493462306a36Sopenharmony_ci data = (char *)&dummy_acl; 493562306a36Sopenharmony_ci data_len = sizeof(dummy_acl); 493662306a36Sopenharmony_ci } 493762306a36Sopenharmony_ci } 493862306a36Sopenharmony_ci 493962306a36Sopenharmony_ci ret = get_cur_path(sctx, sctx->cur_ino, sctx->cur_inode_gen, p); 494062306a36Sopenharmony_ci if (ret < 0) 494162306a36Sopenharmony_ci goto out; 494262306a36Sopenharmony_ci 494362306a36Sopenharmony_ci ret = send_set_xattr(sctx, p, name, name_len, data, data_len); 494462306a36Sopenharmony_ci 494562306a36Sopenharmony_ciout: 494662306a36Sopenharmony_ci fs_path_free(p); 494762306a36Sopenharmony_ci return ret; 494862306a36Sopenharmony_ci} 494962306a36Sopenharmony_ci 495062306a36Sopenharmony_cistatic int __process_deleted_xattr(int num, struct btrfs_key *di_key, 495162306a36Sopenharmony_ci const char *name, int name_len, 495262306a36Sopenharmony_ci const char *data, int data_len, void *ctx) 495362306a36Sopenharmony_ci{ 495462306a36Sopenharmony_ci int ret; 495562306a36Sopenharmony_ci struct send_ctx *sctx = ctx; 495662306a36Sopenharmony_ci struct fs_path *p; 495762306a36Sopenharmony_ci 495862306a36Sopenharmony_ci p = fs_path_alloc(); 495962306a36Sopenharmony_ci if (!p) 496062306a36Sopenharmony_ci return -ENOMEM; 496162306a36Sopenharmony_ci 496262306a36Sopenharmony_ci ret = get_cur_path(sctx, sctx->cur_ino, sctx->cur_inode_gen, p); 496362306a36Sopenharmony_ci if (ret < 0) 496462306a36Sopenharmony_ci goto out; 496562306a36Sopenharmony_ci 496662306a36Sopenharmony_ci ret = send_remove_xattr(sctx, p, name, name_len); 496762306a36Sopenharmony_ci 496862306a36Sopenharmony_ciout: 496962306a36Sopenharmony_ci fs_path_free(p); 497062306a36Sopenharmony_ci return ret; 497162306a36Sopenharmony_ci} 497262306a36Sopenharmony_ci 497362306a36Sopenharmony_cistatic int process_new_xattr(struct send_ctx *sctx) 497462306a36Sopenharmony_ci{ 497562306a36Sopenharmony_ci int ret = 0; 497662306a36Sopenharmony_ci 497762306a36Sopenharmony_ci ret = iterate_dir_item(sctx->send_root, sctx->left_path, 497862306a36Sopenharmony_ci __process_new_xattr, sctx); 497962306a36Sopenharmony_ci 498062306a36Sopenharmony_ci return ret; 498162306a36Sopenharmony_ci} 498262306a36Sopenharmony_ci 498362306a36Sopenharmony_cistatic int process_deleted_xattr(struct send_ctx *sctx) 498462306a36Sopenharmony_ci{ 498562306a36Sopenharmony_ci return iterate_dir_item(sctx->parent_root, sctx->right_path, 498662306a36Sopenharmony_ci __process_deleted_xattr, sctx); 498762306a36Sopenharmony_ci} 498862306a36Sopenharmony_ci 498962306a36Sopenharmony_cistruct find_xattr_ctx { 499062306a36Sopenharmony_ci const char *name; 499162306a36Sopenharmony_ci int name_len; 499262306a36Sopenharmony_ci int found_idx; 499362306a36Sopenharmony_ci char *found_data; 499462306a36Sopenharmony_ci int found_data_len; 499562306a36Sopenharmony_ci}; 499662306a36Sopenharmony_ci 499762306a36Sopenharmony_cistatic int __find_xattr(int num, struct btrfs_key *di_key, const char *name, 499862306a36Sopenharmony_ci int name_len, const char *data, int data_len, void *vctx) 499962306a36Sopenharmony_ci{ 500062306a36Sopenharmony_ci struct find_xattr_ctx *ctx = vctx; 500162306a36Sopenharmony_ci 500262306a36Sopenharmony_ci if (name_len == ctx->name_len && 500362306a36Sopenharmony_ci strncmp(name, ctx->name, name_len) == 0) { 500462306a36Sopenharmony_ci ctx->found_idx = num; 500562306a36Sopenharmony_ci ctx->found_data_len = data_len; 500662306a36Sopenharmony_ci ctx->found_data = kmemdup(data, data_len, GFP_KERNEL); 500762306a36Sopenharmony_ci if (!ctx->found_data) 500862306a36Sopenharmony_ci return -ENOMEM; 500962306a36Sopenharmony_ci return 1; 501062306a36Sopenharmony_ci } 501162306a36Sopenharmony_ci return 0; 501262306a36Sopenharmony_ci} 501362306a36Sopenharmony_ci 501462306a36Sopenharmony_cistatic int find_xattr(struct btrfs_root *root, 501562306a36Sopenharmony_ci struct btrfs_path *path, 501662306a36Sopenharmony_ci struct btrfs_key *key, 501762306a36Sopenharmony_ci const char *name, int name_len, 501862306a36Sopenharmony_ci char **data, int *data_len) 501962306a36Sopenharmony_ci{ 502062306a36Sopenharmony_ci int ret; 502162306a36Sopenharmony_ci struct find_xattr_ctx ctx; 502262306a36Sopenharmony_ci 502362306a36Sopenharmony_ci ctx.name = name; 502462306a36Sopenharmony_ci ctx.name_len = name_len; 502562306a36Sopenharmony_ci ctx.found_idx = -1; 502662306a36Sopenharmony_ci ctx.found_data = NULL; 502762306a36Sopenharmony_ci ctx.found_data_len = 0; 502862306a36Sopenharmony_ci 502962306a36Sopenharmony_ci ret = iterate_dir_item(root, path, __find_xattr, &ctx); 503062306a36Sopenharmony_ci if (ret < 0) 503162306a36Sopenharmony_ci return ret; 503262306a36Sopenharmony_ci 503362306a36Sopenharmony_ci if (ctx.found_idx == -1) 503462306a36Sopenharmony_ci return -ENOENT; 503562306a36Sopenharmony_ci if (data) { 503662306a36Sopenharmony_ci *data = ctx.found_data; 503762306a36Sopenharmony_ci *data_len = ctx.found_data_len; 503862306a36Sopenharmony_ci } else { 503962306a36Sopenharmony_ci kfree(ctx.found_data); 504062306a36Sopenharmony_ci } 504162306a36Sopenharmony_ci return ctx.found_idx; 504262306a36Sopenharmony_ci} 504362306a36Sopenharmony_ci 504462306a36Sopenharmony_ci 504562306a36Sopenharmony_cistatic int __process_changed_new_xattr(int num, struct btrfs_key *di_key, 504662306a36Sopenharmony_ci const char *name, int name_len, 504762306a36Sopenharmony_ci const char *data, int data_len, 504862306a36Sopenharmony_ci void *ctx) 504962306a36Sopenharmony_ci{ 505062306a36Sopenharmony_ci int ret; 505162306a36Sopenharmony_ci struct send_ctx *sctx = ctx; 505262306a36Sopenharmony_ci char *found_data = NULL; 505362306a36Sopenharmony_ci int found_data_len = 0; 505462306a36Sopenharmony_ci 505562306a36Sopenharmony_ci ret = find_xattr(sctx->parent_root, sctx->right_path, 505662306a36Sopenharmony_ci sctx->cmp_key, name, name_len, &found_data, 505762306a36Sopenharmony_ci &found_data_len); 505862306a36Sopenharmony_ci if (ret == -ENOENT) { 505962306a36Sopenharmony_ci ret = __process_new_xattr(num, di_key, name, name_len, data, 506062306a36Sopenharmony_ci data_len, ctx); 506162306a36Sopenharmony_ci } else if (ret >= 0) { 506262306a36Sopenharmony_ci if (data_len != found_data_len || 506362306a36Sopenharmony_ci memcmp(data, found_data, data_len)) { 506462306a36Sopenharmony_ci ret = __process_new_xattr(num, di_key, name, name_len, 506562306a36Sopenharmony_ci data, data_len, ctx); 506662306a36Sopenharmony_ci } else { 506762306a36Sopenharmony_ci ret = 0; 506862306a36Sopenharmony_ci } 506962306a36Sopenharmony_ci } 507062306a36Sopenharmony_ci 507162306a36Sopenharmony_ci kfree(found_data); 507262306a36Sopenharmony_ci return ret; 507362306a36Sopenharmony_ci} 507462306a36Sopenharmony_ci 507562306a36Sopenharmony_cistatic int __process_changed_deleted_xattr(int num, struct btrfs_key *di_key, 507662306a36Sopenharmony_ci const char *name, int name_len, 507762306a36Sopenharmony_ci const char *data, int data_len, 507862306a36Sopenharmony_ci void *ctx) 507962306a36Sopenharmony_ci{ 508062306a36Sopenharmony_ci int ret; 508162306a36Sopenharmony_ci struct send_ctx *sctx = ctx; 508262306a36Sopenharmony_ci 508362306a36Sopenharmony_ci ret = find_xattr(sctx->send_root, sctx->left_path, sctx->cmp_key, 508462306a36Sopenharmony_ci name, name_len, NULL, NULL); 508562306a36Sopenharmony_ci if (ret == -ENOENT) 508662306a36Sopenharmony_ci ret = __process_deleted_xattr(num, di_key, name, name_len, data, 508762306a36Sopenharmony_ci data_len, ctx); 508862306a36Sopenharmony_ci else if (ret >= 0) 508962306a36Sopenharmony_ci ret = 0; 509062306a36Sopenharmony_ci 509162306a36Sopenharmony_ci return ret; 509262306a36Sopenharmony_ci} 509362306a36Sopenharmony_ci 509462306a36Sopenharmony_cistatic int process_changed_xattr(struct send_ctx *sctx) 509562306a36Sopenharmony_ci{ 509662306a36Sopenharmony_ci int ret = 0; 509762306a36Sopenharmony_ci 509862306a36Sopenharmony_ci ret = iterate_dir_item(sctx->send_root, sctx->left_path, 509962306a36Sopenharmony_ci __process_changed_new_xattr, sctx); 510062306a36Sopenharmony_ci if (ret < 0) 510162306a36Sopenharmony_ci goto out; 510262306a36Sopenharmony_ci ret = iterate_dir_item(sctx->parent_root, sctx->right_path, 510362306a36Sopenharmony_ci __process_changed_deleted_xattr, sctx); 510462306a36Sopenharmony_ci 510562306a36Sopenharmony_ciout: 510662306a36Sopenharmony_ci return ret; 510762306a36Sopenharmony_ci} 510862306a36Sopenharmony_ci 510962306a36Sopenharmony_cistatic int process_all_new_xattrs(struct send_ctx *sctx) 511062306a36Sopenharmony_ci{ 511162306a36Sopenharmony_ci int ret = 0; 511262306a36Sopenharmony_ci int iter_ret = 0; 511362306a36Sopenharmony_ci struct btrfs_root *root; 511462306a36Sopenharmony_ci struct btrfs_path *path; 511562306a36Sopenharmony_ci struct btrfs_key key; 511662306a36Sopenharmony_ci struct btrfs_key found_key; 511762306a36Sopenharmony_ci 511862306a36Sopenharmony_ci path = alloc_path_for_send(); 511962306a36Sopenharmony_ci if (!path) 512062306a36Sopenharmony_ci return -ENOMEM; 512162306a36Sopenharmony_ci 512262306a36Sopenharmony_ci root = sctx->send_root; 512362306a36Sopenharmony_ci 512462306a36Sopenharmony_ci key.objectid = sctx->cmp_key->objectid; 512562306a36Sopenharmony_ci key.type = BTRFS_XATTR_ITEM_KEY; 512662306a36Sopenharmony_ci key.offset = 0; 512762306a36Sopenharmony_ci btrfs_for_each_slot(root, &key, &found_key, path, iter_ret) { 512862306a36Sopenharmony_ci if (found_key.objectid != key.objectid || 512962306a36Sopenharmony_ci found_key.type != key.type) { 513062306a36Sopenharmony_ci ret = 0; 513162306a36Sopenharmony_ci break; 513262306a36Sopenharmony_ci } 513362306a36Sopenharmony_ci 513462306a36Sopenharmony_ci ret = iterate_dir_item(root, path, __process_new_xattr, sctx); 513562306a36Sopenharmony_ci if (ret < 0) 513662306a36Sopenharmony_ci break; 513762306a36Sopenharmony_ci } 513862306a36Sopenharmony_ci /* Catch error found during iteration */ 513962306a36Sopenharmony_ci if (iter_ret < 0) 514062306a36Sopenharmony_ci ret = iter_ret; 514162306a36Sopenharmony_ci 514262306a36Sopenharmony_ci btrfs_free_path(path); 514362306a36Sopenharmony_ci return ret; 514462306a36Sopenharmony_ci} 514562306a36Sopenharmony_ci 514662306a36Sopenharmony_cistatic int send_verity(struct send_ctx *sctx, struct fs_path *path, 514762306a36Sopenharmony_ci struct fsverity_descriptor *desc) 514862306a36Sopenharmony_ci{ 514962306a36Sopenharmony_ci int ret; 515062306a36Sopenharmony_ci 515162306a36Sopenharmony_ci ret = begin_cmd(sctx, BTRFS_SEND_C_ENABLE_VERITY); 515262306a36Sopenharmony_ci if (ret < 0) 515362306a36Sopenharmony_ci goto out; 515462306a36Sopenharmony_ci 515562306a36Sopenharmony_ci TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, path); 515662306a36Sopenharmony_ci TLV_PUT_U8(sctx, BTRFS_SEND_A_VERITY_ALGORITHM, 515762306a36Sopenharmony_ci le8_to_cpu(desc->hash_algorithm)); 515862306a36Sopenharmony_ci TLV_PUT_U32(sctx, BTRFS_SEND_A_VERITY_BLOCK_SIZE, 515962306a36Sopenharmony_ci 1U << le8_to_cpu(desc->log_blocksize)); 516062306a36Sopenharmony_ci TLV_PUT(sctx, BTRFS_SEND_A_VERITY_SALT_DATA, desc->salt, 516162306a36Sopenharmony_ci le8_to_cpu(desc->salt_size)); 516262306a36Sopenharmony_ci TLV_PUT(sctx, BTRFS_SEND_A_VERITY_SIG_DATA, desc->signature, 516362306a36Sopenharmony_ci le32_to_cpu(desc->sig_size)); 516462306a36Sopenharmony_ci 516562306a36Sopenharmony_ci ret = send_cmd(sctx); 516662306a36Sopenharmony_ci 516762306a36Sopenharmony_citlv_put_failure: 516862306a36Sopenharmony_ciout: 516962306a36Sopenharmony_ci return ret; 517062306a36Sopenharmony_ci} 517162306a36Sopenharmony_ci 517262306a36Sopenharmony_cistatic int process_verity(struct send_ctx *sctx) 517362306a36Sopenharmony_ci{ 517462306a36Sopenharmony_ci int ret = 0; 517562306a36Sopenharmony_ci struct btrfs_fs_info *fs_info = sctx->send_root->fs_info; 517662306a36Sopenharmony_ci struct inode *inode; 517762306a36Sopenharmony_ci struct fs_path *p; 517862306a36Sopenharmony_ci 517962306a36Sopenharmony_ci inode = btrfs_iget(fs_info->sb, sctx->cur_ino, sctx->send_root); 518062306a36Sopenharmony_ci if (IS_ERR(inode)) 518162306a36Sopenharmony_ci return PTR_ERR(inode); 518262306a36Sopenharmony_ci 518362306a36Sopenharmony_ci ret = btrfs_get_verity_descriptor(inode, NULL, 0); 518462306a36Sopenharmony_ci if (ret < 0) 518562306a36Sopenharmony_ci goto iput; 518662306a36Sopenharmony_ci 518762306a36Sopenharmony_ci if (ret > FS_VERITY_MAX_DESCRIPTOR_SIZE) { 518862306a36Sopenharmony_ci ret = -EMSGSIZE; 518962306a36Sopenharmony_ci goto iput; 519062306a36Sopenharmony_ci } 519162306a36Sopenharmony_ci if (!sctx->verity_descriptor) { 519262306a36Sopenharmony_ci sctx->verity_descriptor = kvmalloc(FS_VERITY_MAX_DESCRIPTOR_SIZE, 519362306a36Sopenharmony_ci GFP_KERNEL); 519462306a36Sopenharmony_ci if (!sctx->verity_descriptor) { 519562306a36Sopenharmony_ci ret = -ENOMEM; 519662306a36Sopenharmony_ci goto iput; 519762306a36Sopenharmony_ci } 519862306a36Sopenharmony_ci } 519962306a36Sopenharmony_ci 520062306a36Sopenharmony_ci ret = btrfs_get_verity_descriptor(inode, sctx->verity_descriptor, ret); 520162306a36Sopenharmony_ci if (ret < 0) 520262306a36Sopenharmony_ci goto iput; 520362306a36Sopenharmony_ci 520462306a36Sopenharmony_ci p = fs_path_alloc(); 520562306a36Sopenharmony_ci if (!p) { 520662306a36Sopenharmony_ci ret = -ENOMEM; 520762306a36Sopenharmony_ci goto iput; 520862306a36Sopenharmony_ci } 520962306a36Sopenharmony_ci ret = get_cur_path(sctx, sctx->cur_ino, sctx->cur_inode_gen, p); 521062306a36Sopenharmony_ci if (ret < 0) 521162306a36Sopenharmony_ci goto free_path; 521262306a36Sopenharmony_ci 521362306a36Sopenharmony_ci ret = send_verity(sctx, p, sctx->verity_descriptor); 521462306a36Sopenharmony_ci if (ret < 0) 521562306a36Sopenharmony_ci goto free_path; 521662306a36Sopenharmony_ci 521762306a36Sopenharmony_cifree_path: 521862306a36Sopenharmony_ci fs_path_free(p); 521962306a36Sopenharmony_ciiput: 522062306a36Sopenharmony_ci iput(inode); 522162306a36Sopenharmony_ci return ret; 522262306a36Sopenharmony_ci} 522362306a36Sopenharmony_ci 522462306a36Sopenharmony_cistatic inline u64 max_send_read_size(const struct send_ctx *sctx) 522562306a36Sopenharmony_ci{ 522662306a36Sopenharmony_ci return sctx->send_max_size - SZ_16K; 522762306a36Sopenharmony_ci} 522862306a36Sopenharmony_ci 522962306a36Sopenharmony_cistatic int put_data_header(struct send_ctx *sctx, u32 len) 523062306a36Sopenharmony_ci{ 523162306a36Sopenharmony_ci if (WARN_ON_ONCE(sctx->put_data)) 523262306a36Sopenharmony_ci return -EINVAL; 523362306a36Sopenharmony_ci sctx->put_data = true; 523462306a36Sopenharmony_ci if (sctx->proto >= 2) { 523562306a36Sopenharmony_ci /* 523662306a36Sopenharmony_ci * Since v2, the data attribute header doesn't include a length, 523762306a36Sopenharmony_ci * it is implicitly to the end of the command. 523862306a36Sopenharmony_ci */ 523962306a36Sopenharmony_ci if (sctx->send_max_size - sctx->send_size < sizeof(__le16) + len) 524062306a36Sopenharmony_ci return -EOVERFLOW; 524162306a36Sopenharmony_ci put_unaligned_le16(BTRFS_SEND_A_DATA, sctx->send_buf + sctx->send_size); 524262306a36Sopenharmony_ci sctx->send_size += sizeof(__le16); 524362306a36Sopenharmony_ci } else { 524462306a36Sopenharmony_ci struct btrfs_tlv_header *hdr; 524562306a36Sopenharmony_ci 524662306a36Sopenharmony_ci if (sctx->send_max_size - sctx->send_size < sizeof(*hdr) + len) 524762306a36Sopenharmony_ci return -EOVERFLOW; 524862306a36Sopenharmony_ci hdr = (struct btrfs_tlv_header *)(sctx->send_buf + sctx->send_size); 524962306a36Sopenharmony_ci put_unaligned_le16(BTRFS_SEND_A_DATA, &hdr->tlv_type); 525062306a36Sopenharmony_ci put_unaligned_le16(len, &hdr->tlv_len); 525162306a36Sopenharmony_ci sctx->send_size += sizeof(*hdr); 525262306a36Sopenharmony_ci } 525362306a36Sopenharmony_ci return 0; 525462306a36Sopenharmony_ci} 525562306a36Sopenharmony_ci 525662306a36Sopenharmony_cistatic int put_file_data(struct send_ctx *sctx, u64 offset, u32 len) 525762306a36Sopenharmony_ci{ 525862306a36Sopenharmony_ci struct btrfs_root *root = sctx->send_root; 525962306a36Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 526062306a36Sopenharmony_ci struct page *page; 526162306a36Sopenharmony_ci pgoff_t index = offset >> PAGE_SHIFT; 526262306a36Sopenharmony_ci pgoff_t last_index; 526362306a36Sopenharmony_ci unsigned pg_offset = offset_in_page(offset); 526462306a36Sopenharmony_ci int ret; 526562306a36Sopenharmony_ci 526662306a36Sopenharmony_ci ret = put_data_header(sctx, len); 526762306a36Sopenharmony_ci if (ret) 526862306a36Sopenharmony_ci return ret; 526962306a36Sopenharmony_ci 527062306a36Sopenharmony_ci last_index = (offset + len - 1) >> PAGE_SHIFT; 527162306a36Sopenharmony_ci 527262306a36Sopenharmony_ci while (index <= last_index) { 527362306a36Sopenharmony_ci unsigned cur_len = min_t(unsigned, len, 527462306a36Sopenharmony_ci PAGE_SIZE - pg_offset); 527562306a36Sopenharmony_ci 527662306a36Sopenharmony_ci page = find_lock_page(sctx->cur_inode->i_mapping, index); 527762306a36Sopenharmony_ci if (!page) { 527862306a36Sopenharmony_ci page_cache_sync_readahead(sctx->cur_inode->i_mapping, 527962306a36Sopenharmony_ci &sctx->ra, NULL, index, 528062306a36Sopenharmony_ci last_index + 1 - index); 528162306a36Sopenharmony_ci 528262306a36Sopenharmony_ci page = find_or_create_page(sctx->cur_inode->i_mapping, 528362306a36Sopenharmony_ci index, GFP_KERNEL); 528462306a36Sopenharmony_ci if (!page) { 528562306a36Sopenharmony_ci ret = -ENOMEM; 528662306a36Sopenharmony_ci break; 528762306a36Sopenharmony_ci } 528862306a36Sopenharmony_ci } 528962306a36Sopenharmony_ci 529062306a36Sopenharmony_ci if (PageReadahead(page)) 529162306a36Sopenharmony_ci page_cache_async_readahead(sctx->cur_inode->i_mapping, 529262306a36Sopenharmony_ci &sctx->ra, NULL, page_folio(page), 529362306a36Sopenharmony_ci index, last_index + 1 - index); 529462306a36Sopenharmony_ci 529562306a36Sopenharmony_ci if (!PageUptodate(page)) { 529662306a36Sopenharmony_ci btrfs_read_folio(NULL, page_folio(page)); 529762306a36Sopenharmony_ci lock_page(page); 529862306a36Sopenharmony_ci if (!PageUptodate(page)) { 529962306a36Sopenharmony_ci unlock_page(page); 530062306a36Sopenharmony_ci btrfs_err(fs_info, 530162306a36Sopenharmony_ci "send: IO error at offset %llu for inode %llu root %llu", 530262306a36Sopenharmony_ci page_offset(page), sctx->cur_ino, 530362306a36Sopenharmony_ci sctx->send_root->root_key.objectid); 530462306a36Sopenharmony_ci put_page(page); 530562306a36Sopenharmony_ci ret = -EIO; 530662306a36Sopenharmony_ci break; 530762306a36Sopenharmony_ci } 530862306a36Sopenharmony_ci } 530962306a36Sopenharmony_ci 531062306a36Sopenharmony_ci memcpy_from_page(sctx->send_buf + sctx->send_size, page, 531162306a36Sopenharmony_ci pg_offset, cur_len); 531262306a36Sopenharmony_ci unlock_page(page); 531362306a36Sopenharmony_ci put_page(page); 531462306a36Sopenharmony_ci index++; 531562306a36Sopenharmony_ci pg_offset = 0; 531662306a36Sopenharmony_ci len -= cur_len; 531762306a36Sopenharmony_ci sctx->send_size += cur_len; 531862306a36Sopenharmony_ci } 531962306a36Sopenharmony_ci 532062306a36Sopenharmony_ci return ret; 532162306a36Sopenharmony_ci} 532262306a36Sopenharmony_ci 532362306a36Sopenharmony_ci/* 532462306a36Sopenharmony_ci * Read some bytes from the current inode/file and send a write command to 532562306a36Sopenharmony_ci * user space. 532662306a36Sopenharmony_ci */ 532762306a36Sopenharmony_cistatic int send_write(struct send_ctx *sctx, u64 offset, u32 len) 532862306a36Sopenharmony_ci{ 532962306a36Sopenharmony_ci struct btrfs_fs_info *fs_info = sctx->send_root->fs_info; 533062306a36Sopenharmony_ci int ret = 0; 533162306a36Sopenharmony_ci struct fs_path *p; 533262306a36Sopenharmony_ci 533362306a36Sopenharmony_ci p = fs_path_alloc(); 533462306a36Sopenharmony_ci if (!p) 533562306a36Sopenharmony_ci return -ENOMEM; 533662306a36Sopenharmony_ci 533762306a36Sopenharmony_ci btrfs_debug(fs_info, "send_write offset=%llu, len=%d", offset, len); 533862306a36Sopenharmony_ci 533962306a36Sopenharmony_ci ret = begin_cmd(sctx, BTRFS_SEND_C_WRITE); 534062306a36Sopenharmony_ci if (ret < 0) 534162306a36Sopenharmony_ci goto out; 534262306a36Sopenharmony_ci 534362306a36Sopenharmony_ci ret = get_cur_path(sctx, sctx->cur_ino, sctx->cur_inode_gen, p); 534462306a36Sopenharmony_ci if (ret < 0) 534562306a36Sopenharmony_ci goto out; 534662306a36Sopenharmony_ci 534762306a36Sopenharmony_ci TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, p); 534862306a36Sopenharmony_ci TLV_PUT_U64(sctx, BTRFS_SEND_A_FILE_OFFSET, offset); 534962306a36Sopenharmony_ci ret = put_file_data(sctx, offset, len); 535062306a36Sopenharmony_ci if (ret < 0) 535162306a36Sopenharmony_ci goto out; 535262306a36Sopenharmony_ci 535362306a36Sopenharmony_ci ret = send_cmd(sctx); 535462306a36Sopenharmony_ci 535562306a36Sopenharmony_citlv_put_failure: 535662306a36Sopenharmony_ciout: 535762306a36Sopenharmony_ci fs_path_free(p); 535862306a36Sopenharmony_ci return ret; 535962306a36Sopenharmony_ci} 536062306a36Sopenharmony_ci 536162306a36Sopenharmony_ci/* 536262306a36Sopenharmony_ci * Send a clone command to user space. 536362306a36Sopenharmony_ci */ 536462306a36Sopenharmony_cistatic int send_clone(struct send_ctx *sctx, 536562306a36Sopenharmony_ci u64 offset, u32 len, 536662306a36Sopenharmony_ci struct clone_root *clone_root) 536762306a36Sopenharmony_ci{ 536862306a36Sopenharmony_ci int ret = 0; 536962306a36Sopenharmony_ci struct fs_path *p; 537062306a36Sopenharmony_ci u64 gen; 537162306a36Sopenharmony_ci 537262306a36Sopenharmony_ci btrfs_debug(sctx->send_root->fs_info, 537362306a36Sopenharmony_ci "send_clone offset=%llu, len=%d, clone_root=%llu, clone_inode=%llu, clone_offset=%llu", 537462306a36Sopenharmony_ci offset, len, clone_root->root->root_key.objectid, 537562306a36Sopenharmony_ci clone_root->ino, clone_root->offset); 537662306a36Sopenharmony_ci 537762306a36Sopenharmony_ci p = fs_path_alloc(); 537862306a36Sopenharmony_ci if (!p) 537962306a36Sopenharmony_ci return -ENOMEM; 538062306a36Sopenharmony_ci 538162306a36Sopenharmony_ci ret = begin_cmd(sctx, BTRFS_SEND_C_CLONE); 538262306a36Sopenharmony_ci if (ret < 0) 538362306a36Sopenharmony_ci goto out; 538462306a36Sopenharmony_ci 538562306a36Sopenharmony_ci ret = get_cur_path(sctx, sctx->cur_ino, sctx->cur_inode_gen, p); 538662306a36Sopenharmony_ci if (ret < 0) 538762306a36Sopenharmony_ci goto out; 538862306a36Sopenharmony_ci 538962306a36Sopenharmony_ci TLV_PUT_U64(sctx, BTRFS_SEND_A_FILE_OFFSET, offset); 539062306a36Sopenharmony_ci TLV_PUT_U64(sctx, BTRFS_SEND_A_CLONE_LEN, len); 539162306a36Sopenharmony_ci TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, p); 539262306a36Sopenharmony_ci 539362306a36Sopenharmony_ci if (clone_root->root == sctx->send_root) { 539462306a36Sopenharmony_ci ret = get_inode_gen(sctx->send_root, clone_root->ino, &gen); 539562306a36Sopenharmony_ci if (ret < 0) 539662306a36Sopenharmony_ci goto out; 539762306a36Sopenharmony_ci ret = get_cur_path(sctx, clone_root->ino, gen, p); 539862306a36Sopenharmony_ci } else { 539962306a36Sopenharmony_ci ret = get_inode_path(clone_root->root, clone_root->ino, p); 540062306a36Sopenharmony_ci } 540162306a36Sopenharmony_ci if (ret < 0) 540262306a36Sopenharmony_ci goto out; 540362306a36Sopenharmony_ci 540462306a36Sopenharmony_ci /* 540562306a36Sopenharmony_ci * If the parent we're using has a received_uuid set then use that as 540662306a36Sopenharmony_ci * our clone source as that is what we will look for when doing a 540762306a36Sopenharmony_ci * receive. 540862306a36Sopenharmony_ci * 540962306a36Sopenharmony_ci * This covers the case that we create a snapshot off of a received 541062306a36Sopenharmony_ci * subvolume and then use that as the parent and try to receive on a 541162306a36Sopenharmony_ci * different host. 541262306a36Sopenharmony_ci */ 541362306a36Sopenharmony_ci if (!btrfs_is_empty_uuid(clone_root->root->root_item.received_uuid)) 541462306a36Sopenharmony_ci TLV_PUT_UUID(sctx, BTRFS_SEND_A_CLONE_UUID, 541562306a36Sopenharmony_ci clone_root->root->root_item.received_uuid); 541662306a36Sopenharmony_ci else 541762306a36Sopenharmony_ci TLV_PUT_UUID(sctx, BTRFS_SEND_A_CLONE_UUID, 541862306a36Sopenharmony_ci clone_root->root->root_item.uuid); 541962306a36Sopenharmony_ci TLV_PUT_U64(sctx, BTRFS_SEND_A_CLONE_CTRANSID, 542062306a36Sopenharmony_ci btrfs_root_ctransid(&clone_root->root->root_item)); 542162306a36Sopenharmony_ci TLV_PUT_PATH(sctx, BTRFS_SEND_A_CLONE_PATH, p); 542262306a36Sopenharmony_ci TLV_PUT_U64(sctx, BTRFS_SEND_A_CLONE_OFFSET, 542362306a36Sopenharmony_ci clone_root->offset); 542462306a36Sopenharmony_ci 542562306a36Sopenharmony_ci ret = send_cmd(sctx); 542662306a36Sopenharmony_ci 542762306a36Sopenharmony_citlv_put_failure: 542862306a36Sopenharmony_ciout: 542962306a36Sopenharmony_ci fs_path_free(p); 543062306a36Sopenharmony_ci return ret; 543162306a36Sopenharmony_ci} 543262306a36Sopenharmony_ci 543362306a36Sopenharmony_ci/* 543462306a36Sopenharmony_ci * Send an update extent command to user space. 543562306a36Sopenharmony_ci */ 543662306a36Sopenharmony_cistatic int send_update_extent(struct send_ctx *sctx, 543762306a36Sopenharmony_ci u64 offset, u32 len) 543862306a36Sopenharmony_ci{ 543962306a36Sopenharmony_ci int ret = 0; 544062306a36Sopenharmony_ci struct fs_path *p; 544162306a36Sopenharmony_ci 544262306a36Sopenharmony_ci p = fs_path_alloc(); 544362306a36Sopenharmony_ci if (!p) 544462306a36Sopenharmony_ci return -ENOMEM; 544562306a36Sopenharmony_ci 544662306a36Sopenharmony_ci ret = begin_cmd(sctx, BTRFS_SEND_C_UPDATE_EXTENT); 544762306a36Sopenharmony_ci if (ret < 0) 544862306a36Sopenharmony_ci goto out; 544962306a36Sopenharmony_ci 545062306a36Sopenharmony_ci ret = get_cur_path(sctx, sctx->cur_ino, sctx->cur_inode_gen, p); 545162306a36Sopenharmony_ci if (ret < 0) 545262306a36Sopenharmony_ci goto out; 545362306a36Sopenharmony_ci 545462306a36Sopenharmony_ci TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, p); 545562306a36Sopenharmony_ci TLV_PUT_U64(sctx, BTRFS_SEND_A_FILE_OFFSET, offset); 545662306a36Sopenharmony_ci TLV_PUT_U64(sctx, BTRFS_SEND_A_SIZE, len); 545762306a36Sopenharmony_ci 545862306a36Sopenharmony_ci ret = send_cmd(sctx); 545962306a36Sopenharmony_ci 546062306a36Sopenharmony_citlv_put_failure: 546162306a36Sopenharmony_ciout: 546262306a36Sopenharmony_ci fs_path_free(p); 546362306a36Sopenharmony_ci return ret; 546462306a36Sopenharmony_ci} 546562306a36Sopenharmony_ci 546662306a36Sopenharmony_cistatic int send_hole(struct send_ctx *sctx, u64 end) 546762306a36Sopenharmony_ci{ 546862306a36Sopenharmony_ci struct fs_path *p = NULL; 546962306a36Sopenharmony_ci u64 read_size = max_send_read_size(sctx); 547062306a36Sopenharmony_ci u64 offset = sctx->cur_inode_last_extent; 547162306a36Sopenharmony_ci int ret = 0; 547262306a36Sopenharmony_ci 547362306a36Sopenharmony_ci /* 547462306a36Sopenharmony_ci * A hole that starts at EOF or beyond it. Since we do not yet support 547562306a36Sopenharmony_ci * fallocate (for extent preallocation and hole punching), sending a 547662306a36Sopenharmony_ci * write of zeroes starting at EOF or beyond would later require issuing 547762306a36Sopenharmony_ci * a truncate operation which would undo the write and achieve nothing. 547862306a36Sopenharmony_ci */ 547962306a36Sopenharmony_ci if (offset >= sctx->cur_inode_size) 548062306a36Sopenharmony_ci return 0; 548162306a36Sopenharmony_ci 548262306a36Sopenharmony_ci /* 548362306a36Sopenharmony_ci * Don't go beyond the inode's i_size due to prealloc extents that start 548462306a36Sopenharmony_ci * after the i_size. 548562306a36Sopenharmony_ci */ 548662306a36Sopenharmony_ci end = min_t(u64, end, sctx->cur_inode_size); 548762306a36Sopenharmony_ci 548862306a36Sopenharmony_ci if (sctx->flags & BTRFS_SEND_FLAG_NO_FILE_DATA) 548962306a36Sopenharmony_ci return send_update_extent(sctx, offset, end - offset); 549062306a36Sopenharmony_ci 549162306a36Sopenharmony_ci p = fs_path_alloc(); 549262306a36Sopenharmony_ci if (!p) 549362306a36Sopenharmony_ci return -ENOMEM; 549462306a36Sopenharmony_ci ret = get_cur_path(sctx, sctx->cur_ino, sctx->cur_inode_gen, p); 549562306a36Sopenharmony_ci if (ret < 0) 549662306a36Sopenharmony_ci goto tlv_put_failure; 549762306a36Sopenharmony_ci while (offset < end) { 549862306a36Sopenharmony_ci u64 len = min(end - offset, read_size); 549962306a36Sopenharmony_ci 550062306a36Sopenharmony_ci ret = begin_cmd(sctx, BTRFS_SEND_C_WRITE); 550162306a36Sopenharmony_ci if (ret < 0) 550262306a36Sopenharmony_ci break; 550362306a36Sopenharmony_ci TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, p); 550462306a36Sopenharmony_ci TLV_PUT_U64(sctx, BTRFS_SEND_A_FILE_OFFSET, offset); 550562306a36Sopenharmony_ci ret = put_data_header(sctx, len); 550662306a36Sopenharmony_ci if (ret < 0) 550762306a36Sopenharmony_ci break; 550862306a36Sopenharmony_ci memset(sctx->send_buf + sctx->send_size, 0, len); 550962306a36Sopenharmony_ci sctx->send_size += len; 551062306a36Sopenharmony_ci ret = send_cmd(sctx); 551162306a36Sopenharmony_ci if (ret < 0) 551262306a36Sopenharmony_ci break; 551362306a36Sopenharmony_ci offset += len; 551462306a36Sopenharmony_ci } 551562306a36Sopenharmony_ci sctx->cur_inode_next_write_offset = offset; 551662306a36Sopenharmony_citlv_put_failure: 551762306a36Sopenharmony_ci fs_path_free(p); 551862306a36Sopenharmony_ci return ret; 551962306a36Sopenharmony_ci} 552062306a36Sopenharmony_ci 552162306a36Sopenharmony_cistatic int send_encoded_inline_extent(struct send_ctx *sctx, 552262306a36Sopenharmony_ci struct btrfs_path *path, u64 offset, 552362306a36Sopenharmony_ci u64 len) 552462306a36Sopenharmony_ci{ 552562306a36Sopenharmony_ci struct btrfs_root *root = sctx->send_root; 552662306a36Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 552762306a36Sopenharmony_ci struct inode *inode; 552862306a36Sopenharmony_ci struct fs_path *fspath; 552962306a36Sopenharmony_ci struct extent_buffer *leaf = path->nodes[0]; 553062306a36Sopenharmony_ci struct btrfs_key key; 553162306a36Sopenharmony_ci struct btrfs_file_extent_item *ei; 553262306a36Sopenharmony_ci u64 ram_bytes; 553362306a36Sopenharmony_ci size_t inline_size; 553462306a36Sopenharmony_ci int ret; 553562306a36Sopenharmony_ci 553662306a36Sopenharmony_ci inode = btrfs_iget(fs_info->sb, sctx->cur_ino, root); 553762306a36Sopenharmony_ci if (IS_ERR(inode)) 553862306a36Sopenharmony_ci return PTR_ERR(inode); 553962306a36Sopenharmony_ci 554062306a36Sopenharmony_ci fspath = fs_path_alloc(); 554162306a36Sopenharmony_ci if (!fspath) { 554262306a36Sopenharmony_ci ret = -ENOMEM; 554362306a36Sopenharmony_ci goto out; 554462306a36Sopenharmony_ci } 554562306a36Sopenharmony_ci 554662306a36Sopenharmony_ci ret = begin_cmd(sctx, BTRFS_SEND_C_ENCODED_WRITE); 554762306a36Sopenharmony_ci if (ret < 0) 554862306a36Sopenharmony_ci goto out; 554962306a36Sopenharmony_ci 555062306a36Sopenharmony_ci ret = get_cur_path(sctx, sctx->cur_ino, sctx->cur_inode_gen, fspath); 555162306a36Sopenharmony_ci if (ret < 0) 555262306a36Sopenharmony_ci goto out; 555362306a36Sopenharmony_ci 555462306a36Sopenharmony_ci btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); 555562306a36Sopenharmony_ci ei = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_file_extent_item); 555662306a36Sopenharmony_ci ram_bytes = btrfs_file_extent_ram_bytes(leaf, ei); 555762306a36Sopenharmony_ci inline_size = btrfs_file_extent_inline_item_len(leaf, path->slots[0]); 555862306a36Sopenharmony_ci 555962306a36Sopenharmony_ci TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, fspath); 556062306a36Sopenharmony_ci TLV_PUT_U64(sctx, BTRFS_SEND_A_FILE_OFFSET, offset); 556162306a36Sopenharmony_ci TLV_PUT_U64(sctx, BTRFS_SEND_A_UNENCODED_FILE_LEN, 556262306a36Sopenharmony_ci min(key.offset + ram_bytes - offset, len)); 556362306a36Sopenharmony_ci TLV_PUT_U64(sctx, BTRFS_SEND_A_UNENCODED_LEN, ram_bytes); 556462306a36Sopenharmony_ci TLV_PUT_U64(sctx, BTRFS_SEND_A_UNENCODED_OFFSET, offset - key.offset); 556562306a36Sopenharmony_ci ret = btrfs_encoded_io_compression_from_extent(fs_info, 556662306a36Sopenharmony_ci btrfs_file_extent_compression(leaf, ei)); 556762306a36Sopenharmony_ci if (ret < 0) 556862306a36Sopenharmony_ci goto out; 556962306a36Sopenharmony_ci TLV_PUT_U32(sctx, BTRFS_SEND_A_COMPRESSION, ret); 557062306a36Sopenharmony_ci 557162306a36Sopenharmony_ci ret = put_data_header(sctx, inline_size); 557262306a36Sopenharmony_ci if (ret < 0) 557362306a36Sopenharmony_ci goto out; 557462306a36Sopenharmony_ci read_extent_buffer(leaf, sctx->send_buf + sctx->send_size, 557562306a36Sopenharmony_ci btrfs_file_extent_inline_start(ei), inline_size); 557662306a36Sopenharmony_ci sctx->send_size += inline_size; 557762306a36Sopenharmony_ci 557862306a36Sopenharmony_ci ret = send_cmd(sctx); 557962306a36Sopenharmony_ci 558062306a36Sopenharmony_citlv_put_failure: 558162306a36Sopenharmony_ciout: 558262306a36Sopenharmony_ci fs_path_free(fspath); 558362306a36Sopenharmony_ci iput(inode); 558462306a36Sopenharmony_ci return ret; 558562306a36Sopenharmony_ci} 558662306a36Sopenharmony_ci 558762306a36Sopenharmony_cistatic int send_encoded_extent(struct send_ctx *sctx, struct btrfs_path *path, 558862306a36Sopenharmony_ci u64 offset, u64 len) 558962306a36Sopenharmony_ci{ 559062306a36Sopenharmony_ci struct btrfs_root *root = sctx->send_root; 559162306a36Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 559262306a36Sopenharmony_ci struct inode *inode; 559362306a36Sopenharmony_ci struct fs_path *fspath; 559462306a36Sopenharmony_ci struct extent_buffer *leaf = path->nodes[0]; 559562306a36Sopenharmony_ci struct btrfs_key key; 559662306a36Sopenharmony_ci struct btrfs_file_extent_item *ei; 559762306a36Sopenharmony_ci u64 disk_bytenr, disk_num_bytes; 559862306a36Sopenharmony_ci u32 data_offset; 559962306a36Sopenharmony_ci struct btrfs_cmd_header *hdr; 560062306a36Sopenharmony_ci u32 crc; 560162306a36Sopenharmony_ci int ret; 560262306a36Sopenharmony_ci 560362306a36Sopenharmony_ci inode = btrfs_iget(fs_info->sb, sctx->cur_ino, root); 560462306a36Sopenharmony_ci if (IS_ERR(inode)) 560562306a36Sopenharmony_ci return PTR_ERR(inode); 560662306a36Sopenharmony_ci 560762306a36Sopenharmony_ci fspath = fs_path_alloc(); 560862306a36Sopenharmony_ci if (!fspath) { 560962306a36Sopenharmony_ci ret = -ENOMEM; 561062306a36Sopenharmony_ci goto out; 561162306a36Sopenharmony_ci } 561262306a36Sopenharmony_ci 561362306a36Sopenharmony_ci ret = begin_cmd(sctx, BTRFS_SEND_C_ENCODED_WRITE); 561462306a36Sopenharmony_ci if (ret < 0) 561562306a36Sopenharmony_ci goto out; 561662306a36Sopenharmony_ci 561762306a36Sopenharmony_ci ret = get_cur_path(sctx, sctx->cur_ino, sctx->cur_inode_gen, fspath); 561862306a36Sopenharmony_ci if (ret < 0) 561962306a36Sopenharmony_ci goto out; 562062306a36Sopenharmony_ci 562162306a36Sopenharmony_ci btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); 562262306a36Sopenharmony_ci ei = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_file_extent_item); 562362306a36Sopenharmony_ci disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, ei); 562462306a36Sopenharmony_ci disk_num_bytes = btrfs_file_extent_disk_num_bytes(leaf, ei); 562562306a36Sopenharmony_ci 562662306a36Sopenharmony_ci TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, fspath); 562762306a36Sopenharmony_ci TLV_PUT_U64(sctx, BTRFS_SEND_A_FILE_OFFSET, offset); 562862306a36Sopenharmony_ci TLV_PUT_U64(sctx, BTRFS_SEND_A_UNENCODED_FILE_LEN, 562962306a36Sopenharmony_ci min(key.offset + btrfs_file_extent_num_bytes(leaf, ei) - offset, 563062306a36Sopenharmony_ci len)); 563162306a36Sopenharmony_ci TLV_PUT_U64(sctx, BTRFS_SEND_A_UNENCODED_LEN, 563262306a36Sopenharmony_ci btrfs_file_extent_ram_bytes(leaf, ei)); 563362306a36Sopenharmony_ci TLV_PUT_U64(sctx, BTRFS_SEND_A_UNENCODED_OFFSET, 563462306a36Sopenharmony_ci offset - key.offset + btrfs_file_extent_offset(leaf, ei)); 563562306a36Sopenharmony_ci ret = btrfs_encoded_io_compression_from_extent(fs_info, 563662306a36Sopenharmony_ci btrfs_file_extent_compression(leaf, ei)); 563762306a36Sopenharmony_ci if (ret < 0) 563862306a36Sopenharmony_ci goto out; 563962306a36Sopenharmony_ci TLV_PUT_U32(sctx, BTRFS_SEND_A_COMPRESSION, ret); 564062306a36Sopenharmony_ci TLV_PUT_U32(sctx, BTRFS_SEND_A_ENCRYPTION, 0); 564162306a36Sopenharmony_ci 564262306a36Sopenharmony_ci ret = put_data_header(sctx, disk_num_bytes); 564362306a36Sopenharmony_ci if (ret < 0) 564462306a36Sopenharmony_ci goto out; 564562306a36Sopenharmony_ci 564662306a36Sopenharmony_ci /* 564762306a36Sopenharmony_ci * We want to do I/O directly into the send buffer, so get the next page 564862306a36Sopenharmony_ci * boundary in the send buffer. This means that there may be a gap 564962306a36Sopenharmony_ci * between the beginning of the command and the file data. 565062306a36Sopenharmony_ci */ 565162306a36Sopenharmony_ci data_offset = PAGE_ALIGN(sctx->send_size); 565262306a36Sopenharmony_ci if (data_offset > sctx->send_max_size || 565362306a36Sopenharmony_ci sctx->send_max_size - data_offset < disk_num_bytes) { 565462306a36Sopenharmony_ci ret = -EOVERFLOW; 565562306a36Sopenharmony_ci goto out; 565662306a36Sopenharmony_ci } 565762306a36Sopenharmony_ci 565862306a36Sopenharmony_ci /* 565962306a36Sopenharmony_ci * Note that send_buf is a mapping of send_buf_pages, so this is really 566062306a36Sopenharmony_ci * reading into send_buf. 566162306a36Sopenharmony_ci */ 566262306a36Sopenharmony_ci ret = btrfs_encoded_read_regular_fill_pages(BTRFS_I(inode), offset, 566362306a36Sopenharmony_ci disk_bytenr, disk_num_bytes, 566462306a36Sopenharmony_ci sctx->send_buf_pages + 566562306a36Sopenharmony_ci (data_offset >> PAGE_SHIFT)); 566662306a36Sopenharmony_ci if (ret) 566762306a36Sopenharmony_ci goto out; 566862306a36Sopenharmony_ci 566962306a36Sopenharmony_ci hdr = (struct btrfs_cmd_header *)sctx->send_buf; 567062306a36Sopenharmony_ci hdr->len = cpu_to_le32(sctx->send_size + disk_num_bytes - sizeof(*hdr)); 567162306a36Sopenharmony_ci hdr->crc = 0; 567262306a36Sopenharmony_ci crc = btrfs_crc32c(0, sctx->send_buf, sctx->send_size); 567362306a36Sopenharmony_ci crc = btrfs_crc32c(crc, sctx->send_buf + data_offset, disk_num_bytes); 567462306a36Sopenharmony_ci hdr->crc = cpu_to_le32(crc); 567562306a36Sopenharmony_ci 567662306a36Sopenharmony_ci ret = write_buf(sctx->send_filp, sctx->send_buf, sctx->send_size, 567762306a36Sopenharmony_ci &sctx->send_off); 567862306a36Sopenharmony_ci if (!ret) { 567962306a36Sopenharmony_ci ret = write_buf(sctx->send_filp, sctx->send_buf + data_offset, 568062306a36Sopenharmony_ci disk_num_bytes, &sctx->send_off); 568162306a36Sopenharmony_ci } 568262306a36Sopenharmony_ci sctx->send_size = 0; 568362306a36Sopenharmony_ci sctx->put_data = false; 568462306a36Sopenharmony_ci 568562306a36Sopenharmony_citlv_put_failure: 568662306a36Sopenharmony_ciout: 568762306a36Sopenharmony_ci fs_path_free(fspath); 568862306a36Sopenharmony_ci iput(inode); 568962306a36Sopenharmony_ci return ret; 569062306a36Sopenharmony_ci} 569162306a36Sopenharmony_ci 569262306a36Sopenharmony_cistatic int send_extent_data(struct send_ctx *sctx, struct btrfs_path *path, 569362306a36Sopenharmony_ci const u64 offset, const u64 len) 569462306a36Sopenharmony_ci{ 569562306a36Sopenharmony_ci const u64 end = offset + len; 569662306a36Sopenharmony_ci struct extent_buffer *leaf = path->nodes[0]; 569762306a36Sopenharmony_ci struct btrfs_file_extent_item *ei; 569862306a36Sopenharmony_ci u64 read_size = max_send_read_size(sctx); 569962306a36Sopenharmony_ci u64 sent = 0; 570062306a36Sopenharmony_ci 570162306a36Sopenharmony_ci if (sctx->flags & BTRFS_SEND_FLAG_NO_FILE_DATA) 570262306a36Sopenharmony_ci return send_update_extent(sctx, offset, len); 570362306a36Sopenharmony_ci 570462306a36Sopenharmony_ci ei = btrfs_item_ptr(leaf, path->slots[0], 570562306a36Sopenharmony_ci struct btrfs_file_extent_item); 570662306a36Sopenharmony_ci if ((sctx->flags & BTRFS_SEND_FLAG_COMPRESSED) && 570762306a36Sopenharmony_ci btrfs_file_extent_compression(leaf, ei) != BTRFS_COMPRESS_NONE) { 570862306a36Sopenharmony_ci bool is_inline = (btrfs_file_extent_type(leaf, ei) == 570962306a36Sopenharmony_ci BTRFS_FILE_EXTENT_INLINE); 571062306a36Sopenharmony_ci 571162306a36Sopenharmony_ci /* 571262306a36Sopenharmony_ci * Send the compressed extent unless the compressed data is 571362306a36Sopenharmony_ci * larger than the decompressed data. This can happen if we're 571462306a36Sopenharmony_ci * not sending the entire extent, either because it has been 571562306a36Sopenharmony_ci * partially overwritten/truncated or because this is a part of 571662306a36Sopenharmony_ci * the extent that we couldn't clone in clone_range(). 571762306a36Sopenharmony_ci */ 571862306a36Sopenharmony_ci if (is_inline && 571962306a36Sopenharmony_ci btrfs_file_extent_inline_item_len(leaf, 572062306a36Sopenharmony_ci path->slots[0]) <= len) { 572162306a36Sopenharmony_ci return send_encoded_inline_extent(sctx, path, offset, 572262306a36Sopenharmony_ci len); 572362306a36Sopenharmony_ci } else if (!is_inline && 572462306a36Sopenharmony_ci btrfs_file_extent_disk_num_bytes(leaf, ei) <= len) { 572562306a36Sopenharmony_ci return send_encoded_extent(sctx, path, offset, len); 572662306a36Sopenharmony_ci } 572762306a36Sopenharmony_ci } 572862306a36Sopenharmony_ci 572962306a36Sopenharmony_ci if (sctx->cur_inode == NULL) { 573062306a36Sopenharmony_ci struct btrfs_root *root = sctx->send_root; 573162306a36Sopenharmony_ci 573262306a36Sopenharmony_ci sctx->cur_inode = btrfs_iget(root->fs_info->sb, sctx->cur_ino, root); 573362306a36Sopenharmony_ci if (IS_ERR(sctx->cur_inode)) { 573462306a36Sopenharmony_ci int err = PTR_ERR(sctx->cur_inode); 573562306a36Sopenharmony_ci 573662306a36Sopenharmony_ci sctx->cur_inode = NULL; 573762306a36Sopenharmony_ci return err; 573862306a36Sopenharmony_ci } 573962306a36Sopenharmony_ci memset(&sctx->ra, 0, sizeof(struct file_ra_state)); 574062306a36Sopenharmony_ci file_ra_state_init(&sctx->ra, sctx->cur_inode->i_mapping); 574162306a36Sopenharmony_ci 574262306a36Sopenharmony_ci /* 574362306a36Sopenharmony_ci * It's very likely there are no pages from this inode in the page 574462306a36Sopenharmony_ci * cache, so after reading extents and sending their data, we clean 574562306a36Sopenharmony_ci * the page cache to avoid trashing the page cache (adding pressure 574662306a36Sopenharmony_ci * to the page cache and forcing eviction of other data more useful 574762306a36Sopenharmony_ci * for applications). 574862306a36Sopenharmony_ci * 574962306a36Sopenharmony_ci * We decide if we should clean the page cache simply by checking 575062306a36Sopenharmony_ci * if the inode's mapping nrpages is 0 when we first open it, and 575162306a36Sopenharmony_ci * not by using something like filemap_range_has_page() before 575262306a36Sopenharmony_ci * reading an extent because when we ask the readahead code to 575362306a36Sopenharmony_ci * read a given file range, it may (and almost always does) read 575462306a36Sopenharmony_ci * pages from beyond that range (see the documentation for 575562306a36Sopenharmony_ci * page_cache_sync_readahead()), so it would not be reliable, 575662306a36Sopenharmony_ci * because after reading the first extent future calls to 575762306a36Sopenharmony_ci * filemap_range_has_page() would return true because the readahead 575862306a36Sopenharmony_ci * on the previous extent resulted in reading pages of the current 575962306a36Sopenharmony_ci * extent as well. 576062306a36Sopenharmony_ci */ 576162306a36Sopenharmony_ci sctx->clean_page_cache = (sctx->cur_inode->i_mapping->nrpages == 0); 576262306a36Sopenharmony_ci sctx->page_cache_clear_start = round_down(offset, PAGE_SIZE); 576362306a36Sopenharmony_ci } 576462306a36Sopenharmony_ci 576562306a36Sopenharmony_ci while (sent < len) { 576662306a36Sopenharmony_ci u64 size = min(len - sent, read_size); 576762306a36Sopenharmony_ci int ret; 576862306a36Sopenharmony_ci 576962306a36Sopenharmony_ci ret = send_write(sctx, offset + sent, size); 577062306a36Sopenharmony_ci if (ret < 0) 577162306a36Sopenharmony_ci return ret; 577262306a36Sopenharmony_ci sent += size; 577362306a36Sopenharmony_ci } 577462306a36Sopenharmony_ci 577562306a36Sopenharmony_ci if (sctx->clean_page_cache && PAGE_ALIGNED(end)) { 577662306a36Sopenharmony_ci /* 577762306a36Sopenharmony_ci * Always operate only on ranges that are a multiple of the page 577862306a36Sopenharmony_ci * size. This is not only to prevent zeroing parts of a page in 577962306a36Sopenharmony_ci * the case of subpage sector size, but also to guarantee we evict 578062306a36Sopenharmony_ci * pages, as passing a range that is smaller than page size does 578162306a36Sopenharmony_ci * not evict the respective page (only zeroes part of its content). 578262306a36Sopenharmony_ci * 578362306a36Sopenharmony_ci * Always start from the end offset of the last range cleared. 578462306a36Sopenharmony_ci * This is because the readahead code may (and very often does) 578562306a36Sopenharmony_ci * reads pages beyond the range we request for readahead. So if 578662306a36Sopenharmony_ci * we have an extent layout like this: 578762306a36Sopenharmony_ci * 578862306a36Sopenharmony_ci * [ extent A ] [ extent B ] [ extent C ] 578962306a36Sopenharmony_ci * 579062306a36Sopenharmony_ci * When we ask page_cache_sync_readahead() to read extent A, it 579162306a36Sopenharmony_ci * may also trigger reads for pages of extent B. If we are doing 579262306a36Sopenharmony_ci * an incremental send and extent B has not changed between the 579362306a36Sopenharmony_ci * parent and send snapshots, some or all of its pages may end 579462306a36Sopenharmony_ci * up being read and placed in the page cache. So when truncating 579562306a36Sopenharmony_ci * the page cache we always start from the end offset of the 579662306a36Sopenharmony_ci * previously processed extent up to the end of the current 579762306a36Sopenharmony_ci * extent. 579862306a36Sopenharmony_ci */ 579962306a36Sopenharmony_ci truncate_inode_pages_range(&sctx->cur_inode->i_data, 580062306a36Sopenharmony_ci sctx->page_cache_clear_start, 580162306a36Sopenharmony_ci end - 1); 580262306a36Sopenharmony_ci sctx->page_cache_clear_start = end; 580362306a36Sopenharmony_ci } 580462306a36Sopenharmony_ci 580562306a36Sopenharmony_ci return 0; 580662306a36Sopenharmony_ci} 580762306a36Sopenharmony_ci 580862306a36Sopenharmony_ci/* 580962306a36Sopenharmony_ci * Search for a capability xattr related to sctx->cur_ino. If the capability is 581062306a36Sopenharmony_ci * found, call send_set_xattr function to emit it. 581162306a36Sopenharmony_ci * 581262306a36Sopenharmony_ci * Return 0 if there isn't a capability, or when the capability was emitted 581362306a36Sopenharmony_ci * successfully, or < 0 if an error occurred. 581462306a36Sopenharmony_ci */ 581562306a36Sopenharmony_cistatic int send_capabilities(struct send_ctx *sctx) 581662306a36Sopenharmony_ci{ 581762306a36Sopenharmony_ci struct fs_path *fspath = NULL; 581862306a36Sopenharmony_ci struct btrfs_path *path; 581962306a36Sopenharmony_ci struct btrfs_dir_item *di; 582062306a36Sopenharmony_ci struct extent_buffer *leaf; 582162306a36Sopenharmony_ci unsigned long data_ptr; 582262306a36Sopenharmony_ci char *buf = NULL; 582362306a36Sopenharmony_ci int buf_len; 582462306a36Sopenharmony_ci int ret = 0; 582562306a36Sopenharmony_ci 582662306a36Sopenharmony_ci path = alloc_path_for_send(); 582762306a36Sopenharmony_ci if (!path) 582862306a36Sopenharmony_ci return -ENOMEM; 582962306a36Sopenharmony_ci 583062306a36Sopenharmony_ci di = btrfs_lookup_xattr(NULL, sctx->send_root, path, sctx->cur_ino, 583162306a36Sopenharmony_ci XATTR_NAME_CAPS, strlen(XATTR_NAME_CAPS), 0); 583262306a36Sopenharmony_ci if (!di) { 583362306a36Sopenharmony_ci /* There is no xattr for this inode */ 583462306a36Sopenharmony_ci goto out; 583562306a36Sopenharmony_ci } else if (IS_ERR(di)) { 583662306a36Sopenharmony_ci ret = PTR_ERR(di); 583762306a36Sopenharmony_ci goto out; 583862306a36Sopenharmony_ci } 583962306a36Sopenharmony_ci 584062306a36Sopenharmony_ci leaf = path->nodes[0]; 584162306a36Sopenharmony_ci buf_len = btrfs_dir_data_len(leaf, di); 584262306a36Sopenharmony_ci 584362306a36Sopenharmony_ci fspath = fs_path_alloc(); 584462306a36Sopenharmony_ci buf = kmalloc(buf_len, GFP_KERNEL); 584562306a36Sopenharmony_ci if (!fspath || !buf) { 584662306a36Sopenharmony_ci ret = -ENOMEM; 584762306a36Sopenharmony_ci goto out; 584862306a36Sopenharmony_ci } 584962306a36Sopenharmony_ci 585062306a36Sopenharmony_ci ret = get_cur_path(sctx, sctx->cur_ino, sctx->cur_inode_gen, fspath); 585162306a36Sopenharmony_ci if (ret < 0) 585262306a36Sopenharmony_ci goto out; 585362306a36Sopenharmony_ci 585462306a36Sopenharmony_ci data_ptr = (unsigned long)(di + 1) + btrfs_dir_name_len(leaf, di); 585562306a36Sopenharmony_ci read_extent_buffer(leaf, buf, data_ptr, buf_len); 585662306a36Sopenharmony_ci 585762306a36Sopenharmony_ci ret = send_set_xattr(sctx, fspath, XATTR_NAME_CAPS, 585862306a36Sopenharmony_ci strlen(XATTR_NAME_CAPS), buf, buf_len); 585962306a36Sopenharmony_ciout: 586062306a36Sopenharmony_ci kfree(buf); 586162306a36Sopenharmony_ci fs_path_free(fspath); 586262306a36Sopenharmony_ci btrfs_free_path(path); 586362306a36Sopenharmony_ci return ret; 586462306a36Sopenharmony_ci} 586562306a36Sopenharmony_ci 586662306a36Sopenharmony_cistatic int clone_range(struct send_ctx *sctx, struct btrfs_path *dst_path, 586762306a36Sopenharmony_ci struct clone_root *clone_root, const u64 disk_byte, 586862306a36Sopenharmony_ci u64 data_offset, u64 offset, u64 len) 586962306a36Sopenharmony_ci{ 587062306a36Sopenharmony_ci struct btrfs_path *path; 587162306a36Sopenharmony_ci struct btrfs_key key; 587262306a36Sopenharmony_ci int ret; 587362306a36Sopenharmony_ci struct btrfs_inode_info info; 587462306a36Sopenharmony_ci u64 clone_src_i_size = 0; 587562306a36Sopenharmony_ci 587662306a36Sopenharmony_ci /* 587762306a36Sopenharmony_ci * Prevent cloning from a zero offset with a length matching the sector 587862306a36Sopenharmony_ci * size because in some scenarios this will make the receiver fail. 587962306a36Sopenharmony_ci * 588062306a36Sopenharmony_ci * For example, if in the source filesystem the extent at offset 0 588162306a36Sopenharmony_ci * has a length of sectorsize and it was written using direct IO, then 588262306a36Sopenharmony_ci * it can never be an inline extent (even if compression is enabled). 588362306a36Sopenharmony_ci * Then this extent can be cloned in the original filesystem to a non 588462306a36Sopenharmony_ci * zero file offset, but it may not be possible to clone in the 588562306a36Sopenharmony_ci * destination filesystem because it can be inlined due to compression 588662306a36Sopenharmony_ci * on the destination filesystem (as the receiver's write operations are 588762306a36Sopenharmony_ci * always done using buffered IO). The same happens when the original 588862306a36Sopenharmony_ci * filesystem does not have compression enabled but the destination 588962306a36Sopenharmony_ci * filesystem has. 589062306a36Sopenharmony_ci */ 589162306a36Sopenharmony_ci if (clone_root->offset == 0 && 589262306a36Sopenharmony_ci len == sctx->send_root->fs_info->sectorsize) 589362306a36Sopenharmony_ci return send_extent_data(sctx, dst_path, offset, len); 589462306a36Sopenharmony_ci 589562306a36Sopenharmony_ci path = alloc_path_for_send(); 589662306a36Sopenharmony_ci if (!path) 589762306a36Sopenharmony_ci return -ENOMEM; 589862306a36Sopenharmony_ci 589962306a36Sopenharmony_ci /* 590062306a36Sopenharmony_ci * There are inodes that have extents that lie behind its i_size. Don't 590162306a36Sopenharmony_ci * accept clones from these extents. 590262306a36Sopenharmony_ci */ 590362306a36Sopenharmony_ci ret = get_inode_info(clone_root->root, clone_root->ino, &info); 590462306a36Sopenharmony_ci btrfs_release_path(path); 590562306a36Sopenharmony_ci if (ret < 0) 590662306a36Sopenharmony_ci goto out; 590762306a36Sopenharmony_ci clone_src_i_size = info.size; 590862306a36Sopenharmony_ci 590962306a36Sopenharmony_ci /* 591062306a36Sopenharmony_ci * We can't send a clone operation for the entire range if we find 591162306a36Sopenharmony_ci * extent items in the respective range in the source file that 591262306a36Sopenharmony_ci * refer to different extents or if we find holes. 591362306a36Sopenharmony_ci * So check for that and do a mix of clone and regular write/copy 591462306a36Sopenharmony_ci * operations if needed. 591562306a36Sopenharmony_ci * 591662306a36Sopenharmony_ci * Example: 591762306a36Sopenharmony_ci * 591862306a36Sopenharmony_ci * mkfs.btrfs -f /dev/sda 591962306a36Sopenharmony_ci * mount /dev/sda /mnt 592062306a36Sopenharmony_ci * xfs_io -f -c "pwrite -S 0xaa 0K 100K" /mnt/foo 592162306a36Sopenharmony_ci * cp --reflink=always /mnt/foo /mnt/bar 592262306a36Sopenharmony_ci * xfs_io -c "pwrite -S 0xbb 50K 50K" /mnt/foo 592362306a36Sopenharmony_ci * btrfs subvolume snapshot -r /mnt /mnt/snap 592462306a36Sopenharmony_ci * 592562306a36Sopenharmony_ci * If when we send the snapshot and we are processing file bar (which 592662306a36Sopenharmony_ci * has a higher inode number than foo) we blindly send a clone operation 592762306a36Sopenharmony_ci * for the [0, 100K[ range from foo to bar, the receiver ends up getting 592862306a36Sopenharmony_ci * a file bar that matches the content of file foo - iow, doesn't match 592962306a36Sopenharmony_ci * the content from bar in the original filesystem. 593062306a36Sopenharmony_ci */ 593162306a36Sopenharmony_ci key.objectid = clone_root->ino; 593262306a36Sopenharmony_ci key.type = BTRFS_EXTENT_DATA_KEY; 593362306a36Sopenharmony_ci key.offset = clone_root->offset; 593462306a36Sopenharmony_ci ret = btrfs_search_slot(NULL, clone_root->root, &key, path, 0, 0); 593562306a36Sopenharmony_ci if (ret < 0) 593662306a36Sopenharmony_ci goto out; 593762306a36Sopenharmony_ci if (ret > 0 && path->slots[0] > 0) { 593862306a36Sopenharmony_ci btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0] - 1); 593962306a36Sopenharmony_ci if (key.objectid == clone_root->ino && 594062306a36Sopenharmony_ci key.type == BTRFS_EXTENT_DATA_KEY) 594162306a36Sopenharmony_ci path->slots[0]--; 594262306a36Sopenharmony_ci } 594362306a36Sopenharmony_ci 594462306a36Sopenharmony_ci while (true) { 594562306a36Sopenharmony_ci struct extent_buffer *leaf = path->nodes[0]; 594662306a36Sopenharmony_ci int slot = path->slots[0]; 594762306a36Sopenharmony_ci struct btrfs_file_extent_item *ei; 594862306a36Sopenharmony_ci u8 type; 594962306a36Sopenharmony_ci u64 ext_len; 595062306a36Sopenharmony_ci u64 clone_len; 595162306a36Sopenharmony_ci u64 clone_data_offset; 595262306a36Sopenharmony_ci bool crossed_src_i_size = false; 595362306a36Sopenharmony_ci 595462306a36Sopenharmony_ci if (slot >= btrfs_header_nritems(leaf)) { 595562306a36Sopenharmony_ci ret = btrfs_next_leaf(clone_root->root, path); 595662306a36Sopenharmony_ci if (ret < 0) 595762306a36Sopenharmony_ci goto out; 595862306a36Sopenharmony_ci else if (ret > 0) 595962306a36Sopenharmony_ci break; 596062306a36Sopenharmony_ci continue; 596162306a36Sopenharmony_ci } 596262306a36Sopenharmony_ci 596362306a36Sopenharmony_ci btrfs_item_key_to_cpu(leaf, &key, slot); 596462306a36Sopenharmony_ci 596562306a36Sopenharmony_ci /* 596662306a36Sopenharmony_ci * We might have an implicit trailing hole (NO_HOLES feature 596762306a36Sopenharmony_ci * enabled). We deal with it after leaving this loop. 596862306a36Sopenharmony_ci */ 596962306a36Sopenharmony_ci if (key.objectid != clone_root->ino || 597062306a36Sopenharmony_ci key.type != BTRFS_EXTENT_DATA_KEY) 597162306a36Sopenharmony_ci break; 597262306a36Sopenharmony_ci 597362306a36Sopenharmony_ci ei = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item); 597462306a36Sopenharmony_ci type = btrfs_file_extent_type(leaf, ei); 597562306a36Sopenharmony_ci if (type == BTRFS_FILE_EXTENT_INLINE) { 597662306a36Sopenharmony_ci ext_len = btrfs_file_extent_ram_bytes(leaf, ei); 597762306a36Sopenharmony_ci ext_len = PAGE_ALIGN(ext_len); 597862306a36Sopenharmony_ci } else { 597962306a36Sopenharmony_ci ext_len = btrfs_file_extent_num_bytes(leaf, ei); 598062306a36Sopenharmony_ci } 598162306a36Sopenharmony_ci 598262306a36Sopenharmony_ci if (key.offset + ext_len <= clone_root->offset) 598362306a36Sopenharmony_ci goto next; 598462306a36Sopenharmony_ci 598562306a36Sopenharmony_ci if (key.offset > clone_root->offset) { 598662306a36Sopenharmony_ci /* Implicit hole, NO_HOLES feature enabled. */ 598762306a36Sopenharmony_ci u64 hole_len = key.offset - clone_root->offset; 598862306a36Sopenharmony_ci 598962306a36Sopenharmony_ci if (hole_len > len) 599062306a36Sopenharmony_ci hole_len = len; 599162306a36Sopenharmony_ci ret = send_extent_data(sctx, dst_path, offset, 599262306a36Sopenharmony_ci hole_len); 599362306a36Sopenharmony_ci if (ret < 0) 599462306a36Sopenharmony_ci goto out; 599562306a36Sopenharmony_ci 599662306a36Sopenharmony_ci len -= hole_len; 599762306a36Sopenharmony_ci if (len == 0) 599862306a36Sopenharmony_ci break; 599962306a36Sopenharmony_ci offset += hole_len; 600062306a36Sopenharmony_ci clone_root->offset += hole_len; 600162306a36Sopenharmony_ci data_offset += hole_len; 600262306a36Sopenharmony_ci } 600362306a36Sopenharmony_ci 600462306a36Sopenharmony_ci if (key.offset >= clone_root->offset + len) 600562306a36Sopenharmony_ci break; 600662306a36Sopenharmony_ci 600762306a36Sopenharmony_ci if (key.offset >= clone_src_i_size) 600862306a36Sopenharmony_ci break; 600962306a36Sopenharmony_ci 601062306a36Sopenharmony_ci if (key.offset + ext_len > clone_src_i_size) { 601162306a36Sopenharmony_ci ext_len = clone_src_i_size - key.offset; 601262306a36Sopenharmony_ci crossed_src_i_size = true; 601362306a36Sopenharmony_ci } 601462306a36Sopenharmony_ci 601562306a36Sopenharmony_ci clone_data_offset = btrfs_file_extent_offset(leaf, ei); 601662306a36Sopenharmony_ci if (btrfs_file_extent_disk_bytenr(leaf, ei) == disk_byte) { 601762306a36Sopenharmony_ci clone_root->offset = key.offset; 601862306a36Sopenharmony_ci if (clone_data_offset < data_offset && 601962306a36Sopenharmony_ci clone_data_offset + ext_len > data_offset) { 602062306a36Sopenharmony_ci u64 extent_offset; 602162306a36Sopenharmony_ci 602262306a36Sopenharmony_ci extent_offset = data_offset - clone_data_offset; 602362306a36Sopenharmony_ci ext_len -= extent_offset; 602462306a36Sopenharmony_ci clone_data_offset += extent_offset; 602562306a36Sopenharmony_ci clone_root->offset += extent_offset; 602662306a36Sopenharmony_ci } 602762306a36Sopenharmony_ci } 602862306a36Sopenharmony_ci 602962306a36Sopenharmony_ci clone_len = min_t(u64, ext_len, len); 603062306a36Sopenharmony_ci 603162306a36Sopenharmony_ci if (btrfs_file_extent_disk_bytenr(leaf, ei) == disk_byte && 603262306a36Sopenharmony_ci clone_data_offset == data_offset) { 603362306a36Sopenharmony_ci const u64 src_end = clone_root->offset + clone_len; 603462306a36Sopenharmony_ci const u64 sectorsize = SZ_64K; 603562306a36Sopenharmony_ci 603662306a36Sopenharmony_ci /* 603762306a36Sopenharmony_ci * We can't clone the last block, when its size is not 603862306a36Sopenharmony_ci * sector size aligned, into the middle of a file. If we 603962306a36Sopenharmony_ci * do so, the receiver will get a failure (-EINVAL) when 604062306a36Sopenharmony_ci * trying to clone or will silently corrupt the data in 604162306a36Sopenharmony_ci * the destination file if it's on a kernel without the 604262306a36Sopenharmony_ci * fix introduced by commit ac765f83f1397646 604362306a36Sopenharmony_ci * ("Btrfs: fix data corruption due to cloning of eof 604462306a36Sopenharmony_ci * block). 604562306a36Sopenharmony_ci * 604662306a36Sopenharmony_ci * So issue a clone of the aligned down range plus a 604762306a36Sopenharmony_ci * regular write for the eof block, if we hit that case. 604862306a36Sopenharmony_ci * 604962306a36Sopenharmony_ci * Also, we use the maximum possible sector size, 64K, 605062306a36Sopenharmony_ci * because we don't know what's the sector size of the 605162306a36Sopenharmony_ci * filesystem that receives the stream, so we have to 605262306a36Sopenharmony_ci * assume the largest possible sector size. 605362306a36Sopenharmony_ci */ 605462306a36Sopenharmony_ci if (src_end == clone_src_i_size && 605562306a36Sopenharmony_ci !IS_ALIGNED(src_end, sectorsize) && 605662306a36Sopenharmony_ci offset + clone_len < sctx->cur_inode_size) { 605762306a36Sopenharmony_ci u64 slen; 605862306a36Sopenharmony_ci 605962306a36Sopenharmony_ci slen = ALIGN_DOWN(src_end - clone_root->offset, 606062306a36Sopenharmony_ci sectorsize); 606162306a36Sopenharmony_ci if (slen > 0) { 606262306a36Sopenharmony_ci ret = send_clone(sctx, offset, slen, 606362306a36Sopenharmony_ci clone_root); 606462306a36Sopenharmony_ci if (ret < 0) 606562306a36Sopenharmony_ci goto out; 606662306a36Sopenharmony_ci } 606762306a36Sopenharmony_ci ret = send_extent_data(sctx, dst_path, 606862306a36Sopenharmony_ci offset + slen, 606962306a36Sopenharmony_ci clone_len - slen); 607062306a36Sopenharmony_ci } else { 607162306a36Sopenharmony_ci ret = send_clone(sctx, offset, clone_len, 607262306a36Sopenharmony_ci clone_root); 607362306a36Sopenharmony_ci } 607462306a36Sopenharmony_ci } else if (crossed_src_i_size && clone_len < len) { 607562306a36Sopenharmony_ci /* 607662306a36Sopenharmony_ci * If we are at i_size of the clone source inode and we 607762306a36Sopenharmony_ci * can not clone from it, terminate the loop. This is 607862306a36Sopenharmony_ci * to avoid sending two write operations, one with a 607962306a36Sopenharmony_ci * length matching clone_len and the final one after 608062306a36Sopenharmony_ci * this loop with a length of len - clone_len. 608162306a36Sopenharmony_ci * 608262306a36Sopenharmony_ci * When using encoded writes (BTRFS_SEND_FLAG_COMPRESSED 608362306a36Sopenharmony_ci * was passed to the send ioctl), this helps avoid 608462306a36Sopenharmony_ci * sending an encoded write for an offset that is not 608562306a36Sopenharmony_ci * sector size aligned, in case the i_size of the source 608662306a36Sopenharmony_ci * inode is not sector size aligned. That will make the 608762306a36Sopenharmony_ci * receiver fallback to decompression of the data and 608862306a36Sopenharmony_ci * writing it using regular buffered IO, therefore while 608962306a36Sopenharmony_ci * not incorrect, it's not optimal due decompression and 609062306a36Sopenharmony_ci * possible re-compression at the receiver. 609162306a36Sopenharmony_ci */ 609262306a36Sopenharmony_ci break; 609362306a36Sopenharmony_ci } else { 609462306a36Sopenharmony_ci ret = send_extent_data(sctx, dst_path, offset, 609562306a36Sopenharmony_ci clone_len); 609662306a36Sopenharmony_ci } 609762306a36Sopenharmony_ci 609862306a36Sopenharmony_ci if (ret < 0) 609962306a36Sopenharmony_ci goto out; 610062306a36Sopenharmony_ci 610162306a36Sopenharmony_ci len -= clone_len; 610262306a36Sopenharmony_ci if (len == 0) 610362306a36Sopenharmony_ci break; 610462306a36Sopenharmony_ci offset += clone_len; 610562306a36Sopenharmony_ci clone_root->offset += clone_len; 610662306a36Sopenharmony_ci 610762306a36Sopenharmony_ci /* 610862306a36Sopenharmony_ci * If we are cloning from the file we are currently processing, 610962306a36Sopenharmony_ci * and using the send root as the clone root, we must stop once 611062306a36Sopenharmony_ci * the current clone offset reaches the current eof of the file 611162306a36Sopenharmony_ci * at the receiver, otherwise we would issue an invalid clone 611262306a36Sopenharmony_ci * operation (source range going beyond eof) and cause the 611362306a36Sopenharmony_ci * receiver to fail. So if we reach the current eof, bail out 611462306a36Sopenharmony_ci * and fallback to a regular write. 611562306a36Sopenharmony_ci */ 611662306a36Sopenharmony_ci if (clone_root->root == sctx->send_root && 611762306a36Sopenharmony_ci clone_root->ino == sctx->cur_ino && 611862306a36Sopenharmony_ci clone_root->offset >= sctx->cur_inode_next_write_offset) 611962306a36Sopenharmony_ci break; 612062306a36Sopenharmony_ci 612162306a36Sopenharmony_ci data_offset += clone_len; 612262306a36Sopenharmony_cinext: 612362306a36Sopenharmony_ci path->slots[0]++; 612462306a36Sopenharmony_ci } 612562306a36Sopenharmony_ci 612662306a36Sopenharmony_ci if (len > 0) 612762306a36Sopenharmony_ci ret = send_extent_data(sctx, dst_path, offset, len); 612862306a36Sopenharmony_ci else 612962306a36Sopenharmony_ci ret = 0; 613062306a36Sopenharmony_ciout: 613162306a36Sopenharmony_ci btrfs_free_path(path); 613262306a36Sopenharmony_ci return ret; 613362306a36Sopenharmony_ci} 613462306a36Sopenharmony_ci 613562306a36Sopenharmony_cistatic int send_write_or_clone(struct send_ctx *sctx, 613662306a36Sopenharmony_ci struct btrfs_path *path, 613762306a36Sopenharmony_ci struct btrfs_key *key, 613862306a36Sopenharmony_ci struct clone_root *clone_root) 613962306a36Sopenharmony_ci{ 614062306a36Sopenharmony_ci int ret = 0; 614162306a36Sopenharmony_ci u64 offset = key->offset; 614262306a36Sopenharmony_ci u64 end; 614362306a36Sopenharmony_ci u64 bs = sctx->send_root->fs_info->sb->s_blocksize; 614462306a36Sopenharmony_ci 614562306a36Sopenharmony_ci end = min_t(u64, btrfs_file_extent_end(path), sctx->cur_inode_size); 614662306a36Sopenharmony_ci if (offset >= end) 614762306a36Sopenharmony_ci return 0; 614862306a36Sopenharmony_ci 614962306a36Sopenharmony_ci if (clone_root && IS_ALIGNED(end, bs)) { 615062306a36Sopenharmony_ci struct btrfs_file_extent_item *ei; 615162306a36Sopenharmony_ci u64 disk_byte; 615262306a36Sopenharmony_ci u64 data_offset; 615362306a36Sopenharmony_ci 615462306a36Sopenharmony_ci ei = btrfs_item_ptr(path->nodes[0], path->slots[0], 615562306a36Sopenharmony_ci struct btrfs_file_extent_item); 615662306a36Sopenharmony_ci disk_byte = btrfs_file_extent_disk_bytenr(path->nodes[0], ei); 615762306a36Sopenharmony_ci data_offset = btrfs_file_extent_offset(path->nodes[0], ei); 615862306a36Sopenharmony_ci ret = clone_range(sctx, path, clone_root, disk_byte, 615962306a36Sopenharmony_ci data_offset, offset, end - offset); 616062306a36Sopenharmony_ci } else { 616162306a36Sopenharmony_ci ret = send_extent_data(sctx, path, offset, end - offset); 616262306a36Sopenharmony_ci } 616362306a36Sopenharmony_ci sctx->cur_inode_next_write_offset = end; 616462306a36Sopenharmony_ci return ret; 616562306a36Sopenharmony_ci} 616662306a36Sopenharmony_ci 616762306a36Sopenharmony_cistatic int is_extent_unchanged(struct send_ctx *sctx, 616862306a36Sopenharmony_ci struct btrfs_path *left_path, 616962306a36Sopenharmony_ci struct btrfs_key *ekey) 617062306a36Sopenharmony_ci{ 617162306a36Sopenharmony_ci int ret = 0; 617262306a36Sopenharmony_ci struct btrfs_key key; 617362306a36Sopenharmony_ci struct btrfs_path *path = NULL; 617462306a36Sopenharmony_ci struct extent_buffer *eb; 617562306a36Sopenharmony_ci int slot; 617662306a36Sopenharmony_ci struct btrfs_key found_key; 617762306a36Sopenharmony_ci struct btrfs_file_extent_item *ei; 617862306a36Sopenharmony_ci u64 left_disknr; 617962306a36Sopenharmony_ci u64 right_disknr; 618062306a36Sopenharmony_ci u64 left_offset; 618162306a36Sopenharmony_ci u64 right_offset; 618262306a36Sopenharmony_ci u64 left_offset_fixed; 618362306a36Sopenharmony_ci u64 left_len; 618462306a36Sopenharmony_ci u64 right_len; 618562306a36Sopenharmony_ci u64 left_gen; 618662306a36Sopenharmony_ci u64 right_gen; 618762306a36Sopenharmony_ci u8 left_type; 618862306a36Sopenharmony_ci u8 right_type; 618962306a36Sopenharmony_ci 619062306a36Sopenharmony_ci path = alloc_path_for_send(); 619162306a36Sopenharmony_ci if (!path) 619262306a36Sopenharmony_ci return -ENOMEM; 619362306a36Sopenharmony_ci 619462306a36Sopenharmony_ci eb = left_path->nodes[0]; 619562306a36Sopenharmony_ci slot = left_path->slots[0]; 619662306a36Sopenharmony_ci ei = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item); 619762306a36Sopenharmony_ci left_type = btrfs_file_extent_type(eb, ei); 619862306a36Sopenharmony_ci 619962306a36Sopenharmony_ci if (left_type != BTRFS_FILE_EXTENT_REG) { 620062306a36Sopenharmony_ci ret = 0; 620162306a36Sopenharmony_ci goto out; 620262306a36Sopenharmony_ci } 620362306a36Sopenharmony_ci left_disknr = btrfs_file_extent_disk_bytenr(eb, ei); 620462306a36Sopenharmony_ci left_len = btrfs_file_extent_num_bytes(eb, ei); 620562306a36Sopenharmony_ci left_offset = btrfs_file_extent_offset(eb, ei); 620662306a36Sopenharmony_ci left_gen = btrfs_file_extent_generation(eb, ei); 620762306a36Sopenharmony_ci 620862306a36Sopenharmony_ci /* 620962306a36Sopenharmony_ci * Following comments will refer to these graphics. L is the left 621062306a36Sopenharmony_ci * extents which we are checking at the moment. 1-8 are the right 621162306a36Sopenharmony_ci * extents that we iterate. 621262306a36Sopenharmony_ci * 621362306a36Sopenharmony_ci * |-----L-----| 621462306a36Sopenharmony_ci * |-1-|-2a-|-3-|-4-|-5-|-6-| 621562306a36Sopenharmony_ci * 621662306a36Sopenharmony_ci * |-----L-----| 621762306a36Sopenharmony_ci * |--1--|-2b-|...(same as above) 621862306a36Sopenharmony_ci * 621962306a36Sopenharmony_ci * Alternative situation. Happens on files where extents got split. 622062306a36Sopenharmony_ci * |-----L-----| 622162306a36Sopenharmony_ci * |-----------7-----------|-6-| 622262306a36Sopenharmony_ci * 622362306a36Sopenharmony_ci * Alternative situation. Happens on files which got larger. 622462306a36Sopenharmony_ci * |-----L-----| 622562306a36Sopenharmony_ci * |-8-| 622662306a36Sopenharmony_ci * Nothing follows after 8. 622762306a36Sopenharmony_ci */ 622862306a36Sopenharmony_ci 622962306a36Sopenharmony_ci key.objectid = ekey->objectid; 623062306a36Sopenharmony_ci key.type = BTRFS_EXTENT_DATA_KEY; 623162306a36Sopenharmony_ci key.offset = ekey->offset; 623262306a36Sopenharmony_ci ret = btrfs_search_slot_for_read(sctx->parent_root, &key, path, 0, 0); 623362306a36Sopenharmony_ci if (ret < 0) 623462306a36Sopenharmony_ci goto out; 623562306a36Sopenharmony_ci if (ret) { 623662306a36Sopenharmony_ci ret = 0; 623762306a36Sopenharmony_ci goto out; 623862306a36Sopenharmony_ci } 623962306a36Sopenharmony_ci 624062306a36Sopenharmony_ci /* 624162306a36Sopenharmony_ci * Handle special case where the right side has no extents at all. 624262306a36Sopenharmony_ci */ 624362306a36Sopenharmony_ci eb = path->nodes[0]; 624462306a36Sopenharmony_ci slot = path->slots[0]; 624562306a36Sopenharmony_ci btrfs_item_key_to_cpu(eb, &found_key, slot); 624662306a36Sopenharmony_ci if (found_key.objectid != key.objectid || 624762306a36Sopenharmony_ci found_key.type != key.type) { 624862306a36Sopenharmony_ci /* If we're a hole then just pretend nothing changed */ 624962306a36Sopenharmony_ci ret = (left_disknr) ? 0 : 1; 625062306a36Sopenharmony_ci goto out; 625162306a36Sopenharmony_ci } 625262306a36Sopenharmony_ci 625362306a36Sopenharmony_ci /* 625462306a36Sopenharmony_ci * We're now on 2a, 2b or 7. 625562306a36Sopenharmony_ci */ 625662306a36Sopenharmony_ci key = found_key; 625762306a36Sopenharmony_ci while (key.offset < ekey->offset + left_len) { 625862306a36Sopenharmony_ci ei = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item); 625962306a36Sopenharmony_ci right_type = btrfs_file_extent_type(eb, ei); 626062306a36Sopenharmony_ci if (right_type != BTRFS_FILE_EXTENT_REG && 626162306a36Sopenharmony_ci right_type != BTRFS_FILE_EXTENT_INLINE) { 626262306a36Sopenharmony_ci ret = 0; 626362306a36Sopenharmony_ci goto out; 626462306a36Sopenharmony_ci } 626562306a36Sopenharmony_ci 626662306a36Sopenharmony_ci if (right_type == BTRFS_FILE_EXTENT_INLINE) { 626762306a36Sopenharmony_ci right_len = btrfs_file_extent_ram_bytes(eb, ei); 626862306a36Sopenharmony_ci right_len = PAGE_ALIGN(right_len); 626962306a36Sopenharmony_ci } else { 627062306a36Sopenharmony_ci right_len = btrfs_file_extent_num_bytes(eb, ei); 627162306a36Sopenharmony_ci } 627262306a36Sopenharmony_ci 627362306a36Sopenharmony_ci /* 627462306a36Sopenharmony_ci * Are we at extent 8? If yes, we know the extent is changed. 627562306a36Sopenharmony_ci * This may only happen on the first iteration. 627662306a36Sopenharmony_ci */ 627762306a36Sopenharmony_ci if (found_key.offset + right_len <= ekey->offset) { 627862306a36Sopenharmony_ci /* If we're a hole just pretend nothing changed */ 627962306a36Sopenharmony_ci ret = (left_disknr) ? 0 : 1; 628062306a36Sopenharmony_ci goto out; 628162306a36Sopenharmony_ci } 628262306a36Sopenharmony_ci 628362306a36Sopenharmony_ci /* 628462306a36Sopenharmony_ci * We just wanted to see if when we have an inline extent, what 628562306a36Sopenharmony_ci * follows it is a regular extent (wanted to check the above 628662306a36Sopenharmony_ci * condition for inline extents too). This should normally not 628762306a36Sopenharmony_ci * happen but it's possible for example when we have an inline 628862306a36Sopenharmony_ci * compressed extent representing data with a size matching 628962306a36Sopenharmony_ci * the page size (currently the same as sector size). 629062306a36Sopenharmony_ci */ 629162306a36Sopenharmony_ci if (right_type == BTRFS_FILE_EXTENT_INLINE) { 629262306a36Sopenharmony_ci ret = 0; 629362306a36Sopenharmony_ci goto out; 629462306a36Sopenharmony_ci } 629562306a36Sopenharmony_ci 629662306a36Sopenharmony_ci right_disknr = btrfs_file_extent_disk_bytenr(eb, ei); 629762306a36Sopenharmony_ci right_offset = btrfs_file_extent_offset(eb, ei); 629862306a36Sopenharmony_ci right_gen = btrfs_file_extent_generation(eb, ei); 629962306a36Sopenharmony_ci 630062306a36Sopenharmony_ci left_offset_fixed = left_offset; 630162306a36Sopenharmony_ci if (key.offset < ekey->offset) { 630262306a36Sopenharmony_ci /* Fix the right offset for 2a and 7. */ 630362306a36Sopenharmony_ci right_offset += ekey->offset - key.offset; 630462306a36Sopenharmony_ci } else { 630562306a36Sopenharmony_ci /* Fix the left offset for all behind 2a and 2b */ 630662306a36Sopenharmony_ci left_offset_fixed += key.offset - ekey->offset; 630762306a36Sopenharmony_ci } 630862306a36Sopenharmony_ci 630962306a36Sopenharmony_ci /* 631062306a36Sopenharmony_ci * Check if we have the same extent. 631162306a36Sopenharmony_ci */ 631262306a36Sopenharmony_ci if (left_disknr != right_disknr || 631362306a36Sopenharmony_ci left_offset_fixed != right_offset || 631462306a36Sopenharmony_ci left_gen != right_gen) { 631562306a36Sopenharmony_ci ret = 0; 631662306a36Sopenharmony_ci goto out; 631762306a36Sopenharmony_ci } 631862306a36Sopenharmony_ci 631962306a36Sopenharmony_ci /* 632062306a36Sopenharmony_ci * Go to the next extent. 632162306a36Sopenharmony_ci */ 632262306a36Sopenharmony_ci ret = btrfs_next_item(sctx->parent_root, path); 632362306a36Sopenharmony_ci if (ret < 0) 632462306a36Sopenharmony_ci goto out; 632562306a36Sopenharmony_ci if (!ret) { 632662306a36Sopenharmony_ci eb = path->nodes[0]; 632762306a36Sopenharmony_ci slot = path->slots[0]; 632862306a36Sopenharmony_ci btrfs_item_key_to_cpu(eb, &found_key, slot); 632962306a36Sopenharmony_ci } 633062306a36Sopenharmony_ci if (ret || found_key.objectid != key.objectid || 633162306a36Sopenharmony_ci found_key.type != key.type) { 633262306a36Sopenharmony_ci key.offset += right_len; 633362306a36Sopenharmony_ci break; 633462306a36Sopenharmony_ci } 633562306a36Sopenharmony_ci if (found_key.offset != key.offset + right_len) { 633662306a36Sopenharmony_ci ret = 0; 633762306a36Sopenharmony_ci goto out; 633862306a36Sopenharmony_ci } 633962306a36Sopenharmony_ci key = found_key; 634062306a36Sopenharmony_ci } 634162306a36Sopenharmony_ci 634262306a36Sopenharmony_ci /* 634362306a36Sopenharmony_ci * We're now behind the left extent (treat as unchanged) or at the end 634462306a36Sopenharmony_ci * of the right side (treat as changed). 634562306a36Sopenharmony_ci */ 634662306a36Sopenharmony_ci if (key.offset >= ekey->offset + left_len) 634762306a36Sopenharmony_ci ret = 1; 634862306a36Sopenharmony_ci else 634962306a36Sopenharmony_ci ret = 0; 635062306a36Sopenharmony_ci 635162306a36Sopenharmony_ci 635262306a36Sopenharmony_ciout: 635362306a36Sopenharmony_ci btrfs_free_path(path); 635462306a36Sopenharmony_ci return ret; 635562306a36Sopenharmony_ci} 635662306a36Sopenharmony_ci 635762306a36Sopenharmony_cistatic int get_last_extent(struct send_ctx *sctx, u64 offset) 635862306a36Sopenharmony_ci{ 635962306a36Sopenharmony_ci struct btrfs_path *path; 636062306a36Sopenharmony_ci struct btrfs_root *root = sctx->send_root; 636162306a36Sopenharmony_ci struct btrfs_key key; 636262306a36Sopenharmony_ci int ret; 636362306a36Sopenharmony_ci 636462306a36Sopenharmony_ci path = alloc_path_for_send(); 636562306a36Sopenharmony_ci if (!path) 636662306a36Sopenharmony_ci return -ENOMEM; 636762306a36Sopenharmony_ci 636862306a36Sopenharmony_ci sctx->cur_inode_last_extent = 0; 636962306a36Sopenharmony_ci 637062306a36Sopenharmony_ci key.objectid = sctx->cur_ino; 637162306a36Sopenharmony_ci key.type = BTRFS_EXTENT_DATA_KEY; 637262306a36Sopenharmony_ci key.offset = offset; 637362306a36Sopenharmony_ci ret = btrfs_search_slot_for_read(root, &key, path, 0, 1); 637462306a36Sopenharmony_ci if (ret < 0) 637562306a36Sopenharmony_ci goto out; 637662306a36Sopenharmony_ci ret = 0; 637762306a36Sopenharmony_ci btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]); 637862306a36Sopenharmony_ci if (key.objectid != sctx->cur_ino || key.type != BTRFS_EXTENT_DATA_KEY) 637962306a36Sopenharmony_ci goto out; 638062306a36Sopenharmony_ci 638162306a36Sopenharmony_ci sctx->cur_inode_last_extent = btrfs_file_extent_end(path); 638262306a36Sopenharmony_ciout: 638362306a36Sopenharmony_ci btrfs_free_path(path); 638462306a36Sopenharmony_ci return ret; 638562306a36Sopenharmony_ci} 638662306a36Sopenharmony_ci 638762306a36Sopenharmony_cistatic int range_is_hole_in_parent(struct send_ctx *sctx, 638862306a36Sopenharmony_ci const u64 start, 638962306a36Sopenharmony_ci const u64 end) 639062306a36Sopenharmony_ci{ 639162306a36Sopenharmony_ci struct btrfs_path *path; 639262306a36Sopenharmony_ci struct btrfs_key key; 639362306a36Sopenharmony_ci struct btrfs_root *root = sctx->parent_root; 639462306a36Sopenharmony_ci u64 search_start = start; 639562306a36Sopenharmony_ci int ret; 639662306a36Sopenharmony_ci 639762306a36Sopenharmony_ci path = alloc_path_for_send(); 639862306a36Sopenharmony_ci if (!path) 639962306a36Sopenharmony_ci return -ENOMEM; 640062306a36Sopenharmony_ci 640162306a36Sopenharmony_ci key.objectid = sctx->cur_ino; 640262306a36Sopenharmony_ci key.type = BTRFS_EXTENT_DATA_KEY; 640362306a36Sopenharmony_ci key.offset = search_start; 640462306a36Sopenharmony_ci ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); 640562306a36Sopenharmony_ci if (ret < 0) 640662306a36Sopenharmony_ci goto out; 640762306a36Sopenharmony_ci if (ret > 0 && path->slots[0] > 0) 640862306a36Sopenharmony_ci path->slots[0]--; 640962306a36Sopenharmony_ci 641062306a36Sopenharmony_ci while (search_start < end) { 641162306a36Sopenharmony_ci struct extent_buffer *leaf = path->nodes[0]; 641262306a36Sopenharmony_ci int slot = path->slots[0]; 641362306a36Sopenharmony_ci struct btrfs_file_extent_item *fi; 641462306a36Sopenharmony_ci u64 extent_end; 641562306a36Sopenharmony_ci 641662306a36Sopenharmony_ci if (slot >= btrfs_header_nritems(leaf)) { 641762306a36Sopenharmony_ci ret = btrfs_next_leaf(root, path); 641862306a36Sopenharmony_ci if (ret < 0) 641962306a36Sopenharmony_ci goto out; 642062306a36Sopenharmony_ci else if (ret > 0) 642162306a36Sopenharmony_ci break; 642262306a36Sopenharmony_ci continue; 642362306a36Sopenharmony_ci } 642462306a36Sopenharmony_ci 642562306a36Sopenharmony_ci btrfs_item_key_to_cpu(leaf, &key, slot); 642662306a36Sopenharmony_ci if (key.objectid < sctx->cur_ino || 642762306a36Sopenharmony_ci key.type < BTRFS_EXTENT_DATA_KEY) 642862306a36Sopenharmony_ci goto next; 642962306a36Sopenharmony_ci if (key.objectid > sctx->cur_ino || 643062306a36Sopenharmony_ci key.type > BTRFS_EXTENT_DATA_KEY || 643162306a36Sopenharmony_ci key.offset >= end) 643262306a36Sopenharmony_ci break; 643362306a36Sopenharmony_ci 643462306a36Sopenharmony_ci fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item); 643562306a36Sopenharmony_ci extent_end = btrfs_file_extent_end(path); 643662306a36Sopenharmony_ci if (extent_end <= start) 643762306a36Sopenharmony_ci goto next; 643862306a36Sopenharmony_ci if (btrfs_file_extent_disk_bytenr(leaf, fi) == 0) { 643962306a36Sopenharmony_ci search_start = extent_end; 644062306a36Sopenharmony_ci goto next; 644162306a36Sopenharmony_ci } 644262306a36Sopenharmony_ci ret = 0; 644362306a36Sopenharmony_ci goto out; 644462306a36Sopenharmony_cinext: 644562306a36Sopenharmony_ci path->slots[0]++; 644662306a36Sopenharmony_ci } 644762306a36Sopenharmony_ci ret = 1; 644862306a36Sopenharmony_ciout: 644962306a36Sopenharmony_ci btrfs_free_path(path); 645062306a36Sopenharmony_ci return ret; 645162306a36Sopenharmony_ci} 645262306a36Sopenharmony_ci 645362306a36Sopenharmony_cistatic int maybe_send_hole(struct send_ctx *sctx, struct btrfs_path *path, 645462306a36Sopenharmony_ci struct btrfs_key *key) 645562306a36Sopenharmony_ci{ 645662306a36Sopenharmony_ci int ret = 0; 645762306a36Sopenharmony_ci 645862306a36Sopenharmony_ci if (sctx->cur_ino != key->objectid || !need_send_hole(sctx)) 645962306a36Sopenharmony_ci return 0; 646062306a36Sopenharmony_ci 646162306a36Sopenharmony_ci if (sctx->cur_inode_last_extent == (u64)-1) { 646262306a36Sopenharmony_ci ret = get_last_extent(sctx, key->offset - 1); 646362306a36Sopenharmony_ci if (ret) 646462306a36Sopenharmony_ci return ret; 646562306a36Sopenharmony_ci } 646662306a36Sopenharmony_ci 646762306a36Sopenharmony_ci if (path->slots[0] == 0 && 646862306a36Sopenharmony_ci sctx->cur_inode_last_extent < key->offset) { 646962306a36Sopenharmony_ci /* 647062306a36Sopenharmony_ci * We might have skipped entire leafs that contained only 647162306a36Sopenharmony_ci * file extent items for our current inode. These leafs have 647262306a36Sopenharmony_ci * a generation number smaller (older) than the one in the 647362306a36Sopenharmony_ci * current leaf and the leaf our last extent came from, and 647462306a36Sopenharmony_ci * are located between these 2 leafs. 647562306a36Sopenharmony_ci */ 647662306a36Sopenharmony_ci ret = get_last_extent(sctx, key->offset - 1); 647762306a36Sopenharmony_ci if (ret) 647862306a36Sopenharmony_ci return ret; 647962306a36Sopenharmony_ci } 648062306a36Sopenharmony_ci 648162306a36Sopenharmony_ci if (sctx->cur_inode_last_extent < key->offset) { 648262306a36Sopenharmony_ci ret = range_is_hole_in_parent(sctx, 648362306a36Sopenharmony_ci sctx->cur_inode_last_extent, 648462306a36Sopenharmony_ci key->offset); 648562306a36Sopenharmony_ci if (ret < 0) 648662306a36Sopenharmony_ci return ret; 648762306a36Sopenharmony_ci else if (ret == 0) 648862306a36Sopenharmony_ci ret = send_hole(sctx, key->offset); 648962306a36Sopenharmony_ci else 649062306a36Sopenharmony_ci ret = 0; 649162306a36Sopenharmony_ci } 649262306a36Sopenharmony_ci sctx->cur_inode_last_extent = btrfs_file_extent_end(path); 649362306a36Sopenharmony_ci return ret; 649462306a36Sopenharmony_ci} 649562306a36Sopenharmony_ci 649662306a36Sopenharmony_cistatic int process_extent(struct send_ctx *sctx, 649762306a36Sopenharmony_ci struct btrfs_path *path, 649862306a36Sopenharmony_ci struct btrfs_key *key) 649962306a36Sopenharmony_ci{ 650062306a36Sopenharmony_ci struct clone_root *found_clone = NULL; 650162306a36Sopenharmony_ci int ret = 0; 650262306a36Sopenharmony_ci 650362306a36Sopenharmony_ci if (S_ISLNK(sctx->cur_inode_mode)) 650462306a36Sopenharmony_ci return 0; 650562306a36Sopenharmony_ci 650662306a36Sopenharmony_ci if (sctx->parent_root && !sctx->cur_inode_new) { 650762306a36Sopenharmony_ci ret = is_extent_unchanged(sctx, path, key); 650862306a36Sopenharmony_ci if (ret < 0) 650962306a36Sopenharmony_ci goto out; 651062306a36Sopenharmony_ci if (ret) { 651162306a36Sopenharmony_ci ret = 0; 651262306a36Sopenharmony_ci goto out_hole; 651362306a36Sopenharmony_ci } 651462306a36Sopenharmony_ci } else { 651562306a36Sopenharmony_ci struct btrfs_file_extent_item *ei; 651662306a36Sopenharmony_ci u8 type; 651762306a36Sopenharmony_ci 651862306a36Sopenharmony_ci ei = btrfs_item_ptr(path->nodes[0], path->slots[0], 651962306a36Sopenharmony_ci struct btrfs_file_extent_item); 652062306a36Sopenharmony_ci type = btrfs_file_extent_type(path->nodes[0], ei); 652162306a36Sopenharmony_ci if (type == BTRFS_FILE_EXTENT_PREALLOC || 652262306a36Sopenharmony_ci type == BTRFS_FILE_EXTENT_REG) { 652362306a36Sopenharmony_ci /* 652462306a36Sopenharmony_ci * The send spec does not have a prealloc command yet, 652562306a36Sopenharmony_ci * so just leave a hole for prealloc'ed extents until 652662306a36Sopenharmony_ci * we have enough commands queued up to justify rev'ing 652762306a36Sopenharmony_ci * the send spec. 652862306a36Sopenharmony_ci */ 652962306a36Sopenharmony_ci if (type == BTRFS_FILE_EXTENT_PREALLOC) { 653062306a36Sopenharmony_ci ret = 0; 653162306a36Sopenharmony_ci goto out; 653262306a36Sopenharmony_ci } 653362306a36Sopenharmony_ci 653462306a36Sopenharmony_ci /* Have a hole, just skip it. */ 653562306a36Sopenharmony_ci if (btrfs_file_extent_disk_bytenr(path->nodes[0], ei) == 0) { 653662306a36Sopenharmony_ci ret = 0; 653762306a36Sopenharmony_ci goto out; 653862306a36Sopenharmony_ci } 653962306a36Sopenharmony_ci } 654062306a36Sopenharmony_ci } 654162306a36Sopenharmony_ci 654262306a36Sopenharmony_ci ret = find_extent_clone(sctx, path, key->objectid, key->offset, 654362306a36Sopenharmony_ci sctx->cur_inode_size, &found_clone); 654462306a36Sopenharmony_ci if (ret != -ENOENT && ret < 0) 654562306a36Sopenharmony_ci goto out; 654662306a36Sopenharmony_ci 654762306a36Sopenharmony_ci ret = send_write_or_clone(sctx, path, key, found_clone); 654862306a36Sopenharmony_ci if (ret) 654962306a36Sopenharmony_ci goto out; 655062306a36Sopenharmony_ciout_hole: 655162306a36Sopenharmony_ci ret = maybe_send_hole(sctx, path, key); 655262306a36Sopenharmony_ciout: 655362306a36Sopenharmony_ci return ret; 655462306a36Sopenharmony_ci} 655562306a36Sopenharmony_ci 655662306a36Sopenharmony_cistatic int process_all_extents(struct send_ctx *sctx) 655762306a36Sopenharmony_ci{ 655862306a36Sopenharmony_ci int ret = 0; 655962306a36Sopenharmony_ci int iter_ret = 0; 656062306a36Sopenharmony_ci struct btrfs_root *root; 656162306a36Sopenharmony_ci struct btrfs_path *path; 656262306a36Sopenharmony_ci struct btrfs_key key; 656362306a36Sopenharmony_ci struct btrfs_key found_key; 656462306a36Sopenharmony_ci 656562306a36Sopenharmony_ci root = sctx->send_root; 656662306a36Sopenharmony_ci path = alloc_path_for_send(); 656762306a36Sopenharmony_ci if (!path) 656862306a36Sopenharmony_ci return -ENOMEM; 656962306a36Sopenharmony_ci 657062306a36Sopenharmony_ci key.objectid = sctx->cmp_key->objectid; 657162306a36Sopenharmony_ci key.type = BTRFS_EXTENT_DATA_KEY; 657262306a36Sopenharmony_ci key.offset = 0; 657362306a36Sopenharmony_ci btrfs_for_each_slot(root, &key, &found_key, path, iter_ret) { 657462306a36Sopenharmony_ci if (found_key.objectid != key.objectid || 657562306a36Sopenharmony_ci found_key.type != key.type) { 657662306a36Sopenharmony_ci ret = 0; 657762306a36Sopenharmony_ci break; 657862306a36Sopenharmony_ci } 657962306a36Sopenharmony_ci 658062306a36Sopenharmony_ci ret = process_extent(sctx, path, &found_key); 658162306a36Sopenharmony_ci if (ret < 0) 658262306a36Sopenharmony_ci break; 658362306a36Sopenharmony_ci } 658462306a36Sopenharmony_ci /* Catch error found during iteration */ 658562306a36Sopenharmony_ci if (iter_ret < 0) 658662306a36Sopenharmony_ci ret = iter_ret; 658762306a36Sopenharmony_ci 658862306a36Sopenharmony_ci btrfs_free_path(path); 658962306a36Sopenharmony_ci return ret; 659062306a36Sopenharmony_ci} 659162306a36Sopenharmony_ci 659262306a36Sopenharmony_cistatic int process_recorded_refs_if_needed(struct send_ctx *sctx, int at_end, 659362306a36Sopenharmony_ci int *pending_move, 659462306a36Sopenharmony_ci int *refs_processed) 659562306a36Sopenharmony_ci{ 659662306a36Sopenharmony_ci int ret = 0; 659762306a36Sopenharmony_ci 659862306a36Sopenharmony_ci if (sctx->cur_ino == 0) 659962306a36Sopenharmony_ci goto out; 660062306a36Sopenharmony_ci if (!at_end && sctx->cur_ino == sctx->cmp_key->objectid && 660162306a36Sopenharmony_ci sctx->cmp_key->type <= BTRFS_INODE_EXTREF_KEY) 660262306a36Sopenharmony_ci goto out; 660362306a36Sopenharmony_ci if (list_empty(&sctx->new_refs) && list_empty(&sctx->deleted_refs)) 660462306a36Sopenharmony_ci goto out; 660562306a36Sopenharmony_ci 660662306a36Sopenharmony_ci ret = process_recorded_refs(sctx, pending_move); 660762306a36Sopenharmony_ci if (ret < 0) 660862306a36Sopenharmony_ci goto out; 660962306a36Sopenharmony_ci 661062306a36Sopenharmony_ci *refs_processed = 1; 661162306a36Sopenharmony_ciout: 661262306a36Sopenharmony_ci return ret; 661362306a36Sopenharmony_ci} 661462306a36Sopenharmony_ci 661562306a36Sopenharmony_cistatic int finish_inode_if_needed(struct send_ctx *sctx, int at_end) 661662306a36Sopenharmony_ci{ 661762306a36Sopenharmony_ci int ret = 0; 661862306a36Sopenharmony_ci struct btrfs_inode_info info; 661962306a36Sopenharmony_ci u64 left_mode; 662062306a36Sopenharmony_ci u64 left_uid; 662162306a36Sopenharmony_ci u64 left_gid; 662262306a36Sopenharmony_ci u64 left_fileattr; 662362306a36Sopenharmony_ci u64 right_mode; 662462306a36Sopenharmony_ci u64 right_uid; 662562306a36Sopenharmony_ci u64 right_gid; 662662306a36Sopenharmony_ci u64 right_fileattr; 662762306a36Sopenharmony_ci int need_chmod = 0; 662862306a36Sopenharmony_ci int need_chown = 0; 662962306a36Sopenharmony_ci bool need_fileattr = false; 663062306a36Sopenharmony_ci int need_truncate = 1; 663162306a36Sopenharmony_ci int pending_move = 0; 663262306a36Sopenharmony_ci int refs_processed = 0; 663362306a36Sopenharmony_ci 663462306a36Sopenharmony_ci if (sctx->ignore_cur_inode) 663562306a36Sopenharmony_ci return 0; 663662306a36Sopenharmony_ci 663762306a36Sopenharmony_ci ret = process_recorded_refs_if_needed(sctx, at_end, &pending_move, 663862306a36Sopenharmony_ci &refs_processed); 663962306a36Sopenharmony_ci if (ret < 0) 664062306a36Sopenharmony_ci goto out; 664162306a36Sopenharmony_ci 664262306a36Sopenharmony_ci /* 664362306a36Sopenharmony_ci * We have processed the refs and thus need to advance send_progress. 664462306a36Sopenharmony_ci * Now, calls to get_cur_xxx will take the updated refs of the current 664562306a36Sopenharmony_ci * inode into account. 664662306a36Sopenharmony_ci * 664762306a36Sopenharmony_ci * On the other hand, if our current inode is a directory and couldn't 664862306a36Sopenharmony_ci * be moved/renamed because its parent was renamed/moved too and it has 664962306a36Sopenharmony_ci * a higher inode number, we can only move/rename our current inode 665062306a36Sopenharmony_ci * after we moved/renamed its parent. Therefore in this case operate on 665162306a36Sopenharmony_ci * the old path (pre move/rename) of our current inode, and the 665262306a36Sopenharmony_ci * move/rename will be performed later. 665362306a36Sopenharmony_ci */ 665462306a36Sopenharmony_ci if (refs_processed && !pending_move) 665562306a36Sopenharmony_ci sctx->send_progress = sctx->cur_ino + 1; 665662306a36Sopenharmony_ci 665762306a36Sopenharmony_ci if (sctx->cur_ino == 0 || sctx->cur_inode_deleted) 665862306a36Sopenharmony_ci goto out; 665962306a36Sopenharmony_ci if (!at_end && sctx->cmp_key->objectid == sctx->cur_ino) 666062306a36Sopenharmony_ci goto out; 666162306a36Sopenharmony_ci ret = get_inode_info(sctx->send_root, sctx->cur_ino, &info); 666262306a36Sopenharmony_ci if (ret < 0) 666362306a36Sopenharmony_ci goto out; 666462306a36Sopenharmony_ci left_mode = info.mode; 666562306a36Sopenharmony_ci left_uid = info.uid; 666662306a36Sopenharmony_ci left_gid = info.gid; 666762306a36Sopenharmony_ci left_fileattr = info.fileattr; 666862306a36Sopenharmony_ci 666962306a36Sopenharmony_ci if (!sctx->parent_root || sctx->cur_inode_new) { 667062306a36Sopenharmony_ci need_chown = 1; 667162306a36Sopenharmony_ci if (!S_ISLNK(sctx->cur_inode_mode)) 667262306a36Sopenharmony_ci need_chmod = 1; 667362306a36Sopenharmony_ci if (sctx->cur_inode_next_write_offset == sctx->cur_inode_size) 667462306a36Sopenharmony_ci need_truncate = 0; 667562306a36Sopenharmony_ci } else { 667662306a36Sopenharmony_ci u64 old_size; 667762306a36Sopenharmony_ci 667862306a36Sopenharmony_ci ret = get_inode_info(sctx->parent_root, sctx->cur_ino, &info); 667962306a36Sopenharmony_ci if (ret < 0) 668062306a36Sopenharmony_ci goto out; 668162306a36Sopenharmony_ci old_size = info.size; 668262306a36Sopenharmony_ci right_mode = info.mode; 668362306a36Sopenharmony_ci right_uid = info.uid; 668462306a36Sopenharmony_ci right_gid = info.gid; 668562306a36Sopenharmony_ci right_fileattr = info.fileattr; 668662306a36Sopenharmony_ci 668762306a36Sopenharmony_ci if (left_uid != right_uid || left_gid != right_gid) 668862306a36Sopenharmony_ci need_chown = 1; 668962306a36Sopenharmony_ci if (!S_ISLNK(sctx->cur_inode_mode) && left_mode != right_mode) 669062306a36Sopenharmony_ci need_chmod = 1; 669162306a36Sopenharmony_ci if (!S_ISLNK(sctx->cur_inode_mode) && left_fileattr != right_fileattr) 669262306a36Sopenharmony_ci need_fileattr = true; 669362306a36Sopenharmony_ci if ((old_size == sctx->cur_inode_size) || 669462306a36Sopenharmony_ci (sctx->cur_inode_size > old_size && 669562306a36Sopenharmony_ci sctx->cur_inode_next_write_offset == sctx->cur_inode_size)) 669662306a36Sopenharmony_ci need_truncate = 0; 669762306a36Sopenharmony_ci } 669862306a36Sopenharmony_ci 669962306a36Sopenharmony_ci if (S_ISREG(sctx->cur_inode_mode)) { 670062306a36Sopenharmony_ci if (need_send_hole(sctx)) { 670162306a36Sopenharmony_ci if (sctx->cur_inode_last_extent == (u64)-1 || 670262306a36Sopenharmony_ci sctx->cur_inode_last_extent < 670362306a36Sopenharmony_ci sctx->cur_inode_size) { 670462306a36Sopenharmony_ci ret = get_last_extent(sctx, (u64)-1); 670562306a36Sopenharmony_ci if (ret) 670662306a36Sopenharmony_ci goto out; 670762306a36Sopenharmony_ci } 670862306a36Sopenharmony_ci if (sctx->cur_inode_last_extent < sctx->cur_inode_size) { 670962306a36Sopenharmony_ci ret = range_is_hole_in_parent(sctx, 671062306a36Sopenharmony_ci sctx->cur_inode_last_extent, 671162306a36Sopenharmony_ci sctx->cur_inode_size); 671262306a36Sopenharmony_ci if (ret < 0) { 671362306a36Sopenharmony_ci goto out; 671462306a36Sopenharmony_ci } else if (ret == 0) { 671562306a36Sopenharmony_ci ret = send_hole(sctx, sctx->cur_inode_size); 671662306a36Sopenharmony_ci if (ret < 0) 671762306a36Sopenharmony_ci goto out; 671862306a36Sopenharmony_ci } else { 671962306a36Sopenharmony_ci /* Range is already a hole, skip. */ 672062306a36Sopenharmony_ci ret = 0; 672162306a36Sopenharmony_ci } 672262306a36Sopenharmony_ci } 672362306a36Sopenharmony_ci } 672462306a36Sopenharmony_ci if (need_truncate) { 672562306a36Sopenharmony_ci ret = send_truncate(sctx, sctx->cur_ino, 672662306a36Sopenharmony_ci sctx->cur_inode_gen, 672762306a36Sopenharmony_ci sctx->cur_inode_size); 672862306a36Sopenharmony_ci if (ret < 0) 672962306a36Sopenharmony_ci goto out; 673062306a36Sopenharmony_ci } 673162306a36Sopenharmony_ci } 673262306a36Sopenharmony_ci 673362306a36Sopenharmony_ci if (need_chown) { 673462306a36Sopenharmony_ci ret = send_chown(sctx, sctx->cur_ino, sctx->cur_inode_gen, 673562306a36Sopenharmony_ci left_uid, left_gid); 673662306a36Sopenharmony_ci if (ret < 0) 673762306a36Sopenharmony_ci goto out; 673862306a36Sopenharmony_ci } 673962306a36Sopenharmony_ci if (need_chmod) { 674062306a36Sopenharmony_ci ret = send_chmod(sctx, sctx->cur_ino, sctx->cur_inode_gen, 674162306a36Sopenharmony_ci left_mode); 674262306a36Sopenharmony_ci if (ret < 0) 674362306a36Sopenharmony_ci goto out; 674462306a36Sopenharmony_ci } 674562306a36Sopenharmony_ci if (need_fileattr) { 674662306a36Sopenharmony_ci ret = send_fileattr(sctx, sctx->cur_ino, sctx->cur_inode_gen, 674762306a36Sopenharmony_ci left_fileattr); 674862306a36Sopenharmony_ci if (ret < 0) 674962306a36Sopenharmony_ci goto out; 675062306a36Sopenharmony_ci } 675162306a36Sopenharmony_ci 675262306a36Sopenharmony_ci if (proto_cmd_ok(sctx, BTRFS_SEND_C_ENABLE_VERITY) 675362306a36Sopenharmony_ci && sctx->cur_inode_needs_verity) { 675462306a36Sopenharmony_ci ret = process_verity(sctx); 675562306a36Sopenharmony_ci if (ret < 0) 675662306a36Sopenharmony_ci goto out; 675762306a36Sopenharmony_ci } 675862306a36Sopenharmony_ci 675962306a36Sopenharmony_ci ret = send_capabilities(sctx); 676062306a36Sopenharmony_ci if (ret < 0) 676162306a36Sopenharmony_ci goto out; 676262306a36Sopenharmony_ci 676362306a36Sopenharmony_ci /* 676462306a36Sopenharmony_ci * If other directory inodes depended on our current directory 676562306a36Sopenharmony_ci * inode's move/rename, now do their move/rename operations. 676662306a36Sopenharmony_ci */ 676762306a36Sopenharmony_ci if (!is_waiting_for_move(sctx, sctx->cur_ino)) { 676862306a36Sopenharmony_ci ret = apply_children_dir_moves(sctx); 676962306a36Sopenharmony_ci if (ret) 677062306a36Sopenharmony_ci goto out; 677162306a36Sopenharmony_ci /* 677262306a36Sopenharmony_ci * Need to send that every time, no matter if it actually 677362306a36Sopenharmony_ci * changed between the two trees as we have done changes to 677462306a36Sopenharmony_ci * the inode before. If our inode is a directory and it's 677562306a36Sopenharmony_ci * waiting to be moved/renamed, we will send its utimes when 677662306a36Sopenharmony_ci * it's moved/renamed, therefore we don't need to do it here. 677762306a36Sopenharmony_ci */ 677862306a36Sopenharmony_ci sctx->send_progress = sctx->cur_ino + 1; 677962306a36Sopenharmony_ci 678062306a36Sopenharmony_ci /* 678162306a36Sopenharmony_ci * If the current inode is a non-empty directory, delay issuing 678262306a36Sopenharmony_ci * the utimes command for it, as it's very likely we have inodes 678362306a36Sopenharmony_ci * with an higher number inside it. We want to issue the utimes 678462306a36Sopenharmony_ci * command only after adding all dentries to it. 678562306a36Sopenharmony_ci */ 678662306a36Sopenharmony_ci if (S_ISDIR(sctx->cur_inode_mode) && sctx->cur_inode_size > 0) 678762306a36Sopenharmony_ci ret = cache_dir_utimes(sctx, sctx->cur_ino, sctx->cur_inode_gen); 678862306a36Sopenharmony_ci else 678962306a36Sopenharmony_ci ret = send_utimes(sctx, sctx->cur_ino, sctx->cur_inode_gen); 679062306a36Sopenharmony_ci 679162306a36Sopenharmony_ci if (ret < 0) 679262306a36Sopenharmony_ci goto out; 679362306a36Sopenharmony_ci } 679462306a36Sopenharmony_ci 679562306a36Sopenharmony_ciout: 679662306a36Sopenharmony_ci if (!ret) 679762306a36Sopenharmony_ci ret = trim_dir_utimes_cache(sctx); 679862306a36Sopenharmony_ci 679962306a36Sopenharmony_ci return ret; 680062306a36Sopenharmony_ci} 680162306a36Sopenharmony_ci 680262306a36Sopenharmony_cistatic void close_current_inode(struct send_ctx *sctx) 680362306a36Sopenharmony_ci{ 680462306a36Sopenharmony_ci u64 i_size; 680562306a36Sopenharmony_ci 680662306a36Sopenharmony_ci if (sctx->cur_inode == NULL) 680762306a36Sopenharmony_ci return; 680862306a36Sopenharmony_ci 680962306a36Sopenharmony_ci i_size = i_size_read(sctx->cur_inode); 681062306a36Sopenharmony_ci 681162306a36Sopenharmony_ci /* 681262306a36Sopenharmony_ci * If we are doing an incremental send, we may have extents between the 681362306a36Sopenharmony_ci * last processed extent and the i_size that have not been processed 681462306a36Sopenharmony_ci * because they haven't changed but we may have read some of their pages 681562306a36Sopenharmony_ci * through readahead, see the comments at send_extent_data(). 681662306a36Sopenharmony_ci */ 681762306a36Sopenharmony_ci if (sctx->clean_page_cache && sctx->page_cache_clear_start < i_size) 681862306a36Sopenharmony_ci truncate_inode_pages_range(&sctx->cur_inode->i_data, 681962306a36Sopenharmony_ci sctx->page_cache_clear_start, 682062306a36Sopenharmony_ci round_up(i_size, PAGE_SIZE) - 1); 682162306a36Sopenharmony_ci 682262306a36Sopenharmony_ci iput(sctx->cur_inode); 682362306a36Sopenharmony_ci sctx->cur_inode = NULL; 682462306a36Sopenharmony_ci} 682562306a36Sopenharmony_ci 682662306a36Sopenharmony_cistatic int changed_inode(struct send_ctx *sctx, 682762306a36Sopenharmony_ci enum btrfs_compare_tree_result result) 682862306a36Sopenharmony_ci{ 682962306a36Sopenharmony_ci int ret = 0; 683062306a36Sopenharmony_ci struct btrfs_key *key = sctx->cmp_key; 683162306a36Sopenharmony_ci struct btrfs_inode_item *left_ii = NULL; 683262306a36Sopenharmony_ci struct btrfs_inode_item *right_ii = NULL; 683362306a36Sopenharmony_ci u64 left_gen = 0; 683462306a36Sopenharmony_ci u64 right_gen = 0; 683562306a36Sopenharmony_ci 683662306a36Sopenharmony_ci close_current_inode(sctx); 683762306a36Sopenharmony_ci 683862306a36Sopenharmony_ci sctx->cur_ino = key->objectid; 683962306a36Sopenharmony_ci sctx->cur_inode_new_gen = false; 684062306a36Sopenharmony_ci sctx->cur_inode_last_extent = (u64)-1; 684162306a36Sopenharmony_ci sctx->cur_inode_next_write_offset = 0; 684262306a36Sopenharmony_ci sctx->ignore_cur_inode = false; 684362306a36Sopenharmony_ci 684462306a36Sopenharmony_ci /* 684562306a36Sopenharmony_ci * Set send_progress to current inode. This will tell all get_cur_xxx 684662306a36Sopenharmony_ci * functions that the current inode's refs are not updated yet. Later, 684762306a36Sopenharmony_ci * when process_recorded_refs is finished, it is set to cur_ino + 1. 684862306a36Sopenharmony_ci */ 684962306a36Sopenharmony_ci sctx->send_progress = sctx->cur_ino; 685062306a36Sopenharmony_ci 685162306a36Sopenharmony_ci if (result == BTRFS_COMPARE_TREE_NEW || 685262306a36Sopenharmony_ci result == BTRFS_COMPARE_TREE_CHANGED) { 685362306a36Sopenharmony_ci left_ii = btrfs_item_ptr(sctx->left_path->nodes[0], 685462306a36Sopenharmony_ci sctx->left_path->slots[0], 685562306a36Sopenharmony_ci struct btrfs_inode_item); 685662306a36Sopenharmony_ci left_gen = btrfs_inode_generation(sctx->left_path->nodes[0], 685762306a36Sopenharmony_ci left_ii); 685862306a36Sopenharmony_ci } else { 685962306a36Sopenharmony_ci right_ii = btrfs_item_ptr(sctx->right_path->nodes[0], 686062306a36Sopenharmony_ci sctx->right_path->slots[0], 686162306a36Sopenharmony_ci struct btrfs_inode_item); 686262306a36Sopenharmony_ci right_gen = btrfs_inode_generation(sctx->right_path->nodes[0], 686362306a36Sopenharmony_ci right_ii); 686462306a36Sopenharmony_ci } 686562306a36Sopenharmony_ci if (result == BTRFS_COMPARE_TREE_CHANGED) { 686662306a36Sopenharmony_ci right_ii = btrfs_item_ptr(sctx->right_path->nodes[0], 686762306a36Sopenharmony_ci sctx->right_path->slots[0], 686862306a36Sopenharmony_ci struct btrfs_inode_item); 686962306a36Sopenharmony_ci 687062306a36Sopenharmony_ci right_gen = btrfs_inode_generation(sctx->right_path->nodes[0], 687162306a36Sopenharmony_ci right_ii); 687262306a36Sopenharmony_ci 687362306a36Sopenharmony_ci /* 687462306a36Sopenharmony_ci * The cur_ino = root dir case is special here. We can't treat 687562306a36Sopenharmony_ci * the inode as deleted+reused because it would generate a 687662306a36Sopenharmony_ci * stream that tries to delete/mkdir the root dir. 687762306a36Sopenharmony_ci */ 687862306a36Sopenharmony_ci if (left_gen != right_gen && 687962306a36Sopenharmony_ci sctx->cur_ino != BTRFS_FIRST_FREE_OBJECTID) 688062306a36Sopenharmony_ci sctx->cur_inode_new_gen = true; 688162306a36Sopenharmony_ci } 688262306a36Sopenharmony_ci 688362306a36Sopenharmony_ci /* 688462306a36Sopenharmony_ci * Normally we do not find inodes with a link count of zero (orphans) 688562306a36Sopenharmony_ci * because the most common case is to create a snapshot and use it 688662306a36Sopenharmony_ci * for a send operation. However other less common use cases involve 688762306a36Sopenharmony_ci * using a subvolume and send it after turning it to RO mode just 688862306a36Sopenharmony_ci * after deleting all hard links of a file while holding an open 688962306a36Sopenharmony_ci * file descriptor against it or turning a RO snapshot into RW mode, 689062306a36Sopenharmony_ci * keep an open file descriptor against a file, delete it and then 689162306a36Sopenharmony_ci * turn the snapshot back to RO mode before using it for a send 689262306a36Sopenharmony_ci * operation. The former is what the receiver operation does. 689362306a36Sopenharmony_ci * Therefore, if we want to send these snapshots soon after they're 689462306a36Sopenharmony_ci * received, we need to handle orphan inodes as well. Moreover, orphans 689562306a36Sopenharmony_ci * can appear not only in the send snapshot but also in the parent 689662306a36Sopenharmony_ci * snapshot. Here are several cases: 689762306a36Sopenharmony_ci * 689862306a36Sopenharmony_ci * Case 1: BTRFS_COMPARE_TREE_NEW 689962306a36Sopenharmony_ci * | send snapshot | action 690062306a36Sopenharmony_ci * -------------------------------- 690162306a36Sopenharmony_ci * nlink | 0 | ignore 690262306a36Sopenharmony_ci * 690362306a36Sopenharmony_ci * Case 2: BTRFS_COMPARE_TREE_DELETED 690462306a36Sopenharmony_ci * | parent snapshot | action 690562306a36Sopenharmony_ci * ---------------------------------- 690662306a36Sopenharmony_ci * nlink | 0 | as usual 690762306a36Sopenharmony_ci * Note: No unlinks will be sent because there're no paths for it. 690862306a36Sopenharmony_ci * 690962306a36Sopenharmony_ci * Case 3: BTRFS_COMPARE_TREE_CHANGED 691062306a36Sopenharmony_ci * | | parent snapshot | send snapshot | action 691162306a36Sopenharmony_ci * ----------------------------------------------------------------------- 691262306a36Sopenharmony_ci * subcase 1 | nlink | 0 | 0 | ignore 691362306a36Sopenharmony_ci * subcase 2 | nlink | >0 | 0 | new_gen(deletion) 691462306a36Sopenharmony_ci * subcase 3 | nlink | 0 | >0 | new_gen(creation) 691562306a36Sopenharmony_ci * 691662306a36Sopenharmony_ci */ 691762306a36Sopenharmony_ci if (result == BTRFS_COMPARE_TREE_NEW) { 691862306a36Sopenharmony_ci if (btrfs_inode_nlink(sctx->left_path->nodes[0], left_ii) == 0) { 691962306a36Sopenharmony_ci sctx->ignore_cur_inode = true; 692062306a36Sopenharmony_ci goto out; 692162306a36Sopenharmony_ci } 692262306a36Sopenharmony_ci sctx->cur_inode_gen = left_gen; 692362306a36Sopenharmony_ci sctx->cur_inode_new = true; 692462306a36Sopenharmony_ci sctx->cur_inode_deleted = false; 692562306a36Sopenharmony_ci sctx->cur_inode_size = btrfs_inode_size( 692662306a36Sopenharmony_ci sctx->left_path->nodes[0], left_ii); 692762306a36Sopenharmony_ci sctx->cur_inode_mode = btrfs_inode_mode( 692862306a36Sopenharmony_ci sctx->left_path->nodes[0], left_ii); 692962306a36Sopenharmony_ci sctx->cur_inode_rdev = btrfs_inode_rdev( 693062306a36Sopenharmony_ci sctx->left_path->nodes[0], left_ii); 693162306a36Sopenharmony_ci if (sctx->cur_ino != BTRFS_FIRST_FREE_OBJECTID) 693262306a36Sopenharmony_ci ret = send_create_inode_if_needed(sctx); 693362306a36Sopenharmony_ci } else if (result == BTRFS_COMPARE_TREE_DELETED) { 693462306a36Sopenharmony_ci sctx->cur_inode_gen = right_gen; 693562306a36Sopenharmony_ci sctx->cur_inode_new = false; 693662306a36Sopenharmony_ci sctx->cur_inode_deleted = true; 693762306a36Sopenharmony_ci sctx->cur_inode_size = btrfs_inode_size( 693862306a36Sopenharmony_ci sctx->right_path->nodes[0], right_ii); 693962306a36Sopenharmony_ci sctx->cur_inode_mode = btrfs_inode_mode( 694062306a36Sopenharmony_ci sctx->right_path->nodes[0], right_ii); 694162306a36Sopenharmony_ci } else if (result == BTRFS_COMPARE_TREE_CHANGED) { 694262306a36Sopenharmony_ci u32 new_nlinks, old_nlinks; 694362306a36Sopenharmony_ci 694462306a36Sopenharmony_ci new_nlinks = btrfs_inode_nlink(sctx->left_path->nodes[0], left_ii); 694562306a36Sopenharmony_ci old_nlinks = btrfs_inode_nlink(sctx->right_path->nodes[0], right_ii); 694662306a36Sopenharmony_ci if (new_nlinks == 0 && old_nlinks == 0) { 694762306a36Sopenharmony_ci sctx->ignore_cur_inode = true; 694862306a36Sopenharmony_ci goto out; 694962306a36Sopenharmony_ci } else if (new_nlinks == 0 || old_nlinks == 0) { 695062306a36Sopenharmony_ci sctx->cur_inode_new_gen = 1; 695162306a36Sopenharmony_ci } 695262306a36Sopenharmony_ci /* 695362306a36Sopenharmony_ci * We need to do some special handling in case the inode was 695462306a36Sopenharmony_ci * reported as changed with a changed generation number. This 695562306a36Sopenharmony_ci * means that the original inode was deleted and new inode 695662306a36Sopenharmony_ci * reused the same inum. So we have to treat the old inode as 695762306a36Sopenharmony_ci * deleted and the new one as new. 695862306a36Sopenharmony_ci */ 695962306a36Sopenharmony_ci if (sctx->cur_inode_new_gen) { 696062306a36Sopenharmony_ci /* 696162306a36Sopenharmony_ci * First, process the inode as if it was deleted. 696262306a36Sopenharmony_ci */ 696362306a36Sopenharmony_ci if (old_nlinks > 0) { 696462306a36Sopenharmony_ci sctx->cur_inode_gen = right_gen; 696562306a36Sopenharmony_ci sctx->cur_inode_new = false; 696662306a36Sopenharmony_ci sctx->cur_inode_deleted = true; 696762306a36Sopenharmony_ci sctx->cur_inode_size = btrfs_inode_size( 696862306a36Sopenharmony_ci sctx->right_path->nodes[0], right_ii); 696962306a36Sopenharmony_ci sctx->cur_inode_mode = btrfs_inode_mode( 697062306a36Sopenharmony_ci sctx->right_path->nodes[0], right_ii); 697162306a36Sopenharmony_ci ret = process_all_refs(sctx, 697262306a36Sopenharmony_ci BTRFS_COMPARE_TREE_DELETED); 697362306a36Sopenharmony_ci if (ret < 0) 697462306a36Sopenharmony_ci goto out; 697562306a36Sopenharmony_ci } 697662306a36Sopenharmony_ci 697762306a36Sopenharmony_ci /* 697862306a36Sopenharmony_ci * Now process the inode as if it was new. 697962306a36Sopenharmony_ci */ 698062306a36Sopenharmony_ci if (new_nlinks > 0) { 698162306a36Sopenharmony_ci sctx->cur_inode_gen = left_gen; 698262306a36Sopenharmony_ci sctx->cur_inode_new = true; 698362306a36Sopenharmony_ci sctx->cur_inode_deleted = false; 698462306a36Sopenharmony_ci sctx->cur_inode_size = btrfs_inode_size( 698562306a36Sopenharmony_ci sctx->left_path->nodes[0], 698662306a36Sopenharmony_ci left_ii); 698762306a36Sopenharmony_ci sctx->cur_inode_mode = btrfs_inode_mode( 698862306a36Sopenharmony_ci sctx->left_path->nodes[0], 698962306a36Sopenharmony_ci left_ii); 699062306a36Sopenharmony_ci sctx->cur_inode_rdev = btrfs_inode_rdev( 699162306a36Sopenharmony_ci sctx->left_path->nodes[0], 699262306a36Sopenharmony_ci left_ii); 699362306a36Sopenharmony_ci ret = send_create_inode_if_needed(sctx); 699462306a36Sopenharmony_ci if (ret < 0) 699562306a36Sopenharmony_ci goto out; 699662306a36Sopenharmony_ci 699762306a36Sopenharmony_ci ret = process_all_refs(sctx, BTRFS_COMPARE_TREE_NEW); 699862306a36Sopenharmony_ci if (ret < 0) 699962306a36Sopenharmony_ci goto out; 700062306a36Sopenharmony_ci /* 700162306a36Sopenharmony_ci * Advance send_progress now as we did not get 700262306a36Sopenharmony_ci * into process_recorded_refs_if_needed in the 700362306a36Sopenharmony_ci * new_gen case. 700462306a36Sopenharmony_ci */ 700562306a36Sopenharmony_ci sctx->send_progress = sctx->cur_ino + 1; 700662306a36Sopenharmony_ci 700762306a36Sopenharmony_ci /* 700862306a36Sopenharmony_ci * Now process all extents and xattrs of the 700962306a36Sopenharmony_ci * inode as if they were all new. 701062306a36Sopenharmony_ci */ 701162306a36Sopenharmony_ci ret = process_all_extents(sctx); 701262306a36Sopenharmony_ci if (ret < 0) 701362306a36Sopenharmony_ci goto out; 701462306a36Sopenharmony_ci ret = process_all_new_xattrs(sctx); 701562306a36Sopenharmony_ci if (ret < 0) 701662306a36Sopenharmony_ci goto out; 701762306a36Sopenharmony_ci } 701862306a36Sopenharmony_ci } else { 701962306a36Sopenharmony_ci sctx->cur_inode_gen = left_gen; 702062306a36Sopenharmony_ci sctx->cur_inode_new = false; 702162306a36Sopenharmony_ci sctx->cur_inode_new_gen = false; 702262306a36Sopenharmony_ci sctx->cur_inode_deleted = false; 702362306a36Sopenharmony_ci sctx->cur_inode_size = btrfs_inode_size( 702462306a36Sopenharmony_ci sctx->left_path->nodes[0], left_ii); 702562306a36Sopenharmony_ci sctx->cur_inode_mode = btrfs_inode_mode( 702662306a36Sopenharmony_ci sctx->left_path->nodes[0], left_ii); 702762306a36Sopenharmony_ci } 702862306a36Sopenharmony_ci } 702962306a36Sopenharmony_ci 703062306a36Sopenharmony_ciout: 703162306a36Sopenharmony_ci return ret; 703262306a36Sopenharmony_ci} 703362306a36Sopenharmony_ci 703462306a36Sopenharmony_ci/* 703562306a36Sopenharmony_ci * We have to process new refs before deleted refs, but compare_trees gives us 703662306a36Sopenharmony_ci * the new and deleted refs mixed. To fix this, we record the new/deleted refs 703762306a36Sopenharmony_ci * first and later process them in process_recorded_refs. 703862306a36Sopenharmony_ci * For the cur_inode_new_gen case, we skip recording completely because 703962306a36Sopenharmony_ci * changed_inode did already initiate processing of refs. The reason for this is 704062306a36Sopenharmony_ci * that in this case, compare_tree actually compares the refs of 2 different 704162306a36Sopenharmony_ci * inodes. To fix this, process_all_refs is used in changed_inode to handle all 704262306a36Sopenharmony_ci * refs of the right tree as deleted and all refs of the left tree as new. 704362306a36Sopenharmony_ci */ 704462306a36Sopenharmony_cistatic int changed_ref(struct send_ctx *sctx, 704562306a36Sopenharmony_ci enum btrfs_compare_tree_result result) 704662306a36Sopenharmony_ci{ 704762306a36Sopenharmony_ci int ret = 0; 704862306a36Sopenharmony_ci 704962306a36Sopenharmony_ci if (sctx->cur_ino != sctx->cmp_key->objectid) { 705062306a36Sopenharmony_ci inconsistent_snapshot_error(sctx, result, "reference"); 705162306a36Sopenharmony_ci return -EIO; 705262306a36Sopenharmony_ci } 705362306a36Sopenharmony_ci 705462306a36Sopenharmony_ci if (!sctx->cur_inode_new_gen && 705562306a36Sopenharmony_ci sctx->cur_ino != BTRFS_FIRST_FREE_OBJECTID) { 705662306a36Sopenharmony_ci if (result == BTRFS_COMPARE_TREE_NEW) 705762306a36Sopenharmony_ci ret = record_new_ref(sctx); 705862306a36Sopenharmony_ci else if (result == BTRFS_COMPARE_TREE_DELETED) 705962306a36Sopenharmony_ci ret = record_deleted_ref(sctx); 706062306a36Sopenharmony_ci else if (result == BTRFS_COMPARE_TREE_CHANGED) 706162306a36Sopenharmony_ci ret = record_changed_ref(sctx); 706262306a36Sopenharmony_ci } 706362306a36Sopenharmony_ci 706462306a36Sopenharmony_ci return ret; 706562306a36Sopenharmony_ci} 706662306a36Sopenharmony_ci 706762306a36Sopenharmony_ci/* 706862306a36Sopenharmony_ci * Process new/deleted/changed xattrs. We skip processing in the 706962306a36Sopenharmony_ci * cur_inode_new_gen case because changed_inode did already initiate processing 707062306a36Sopenharmony_ci * of xattrs. The reason is the same as in changed_ref 707162306a36Sopenharmony_ci */ 707262306a36Sopenharmony_cistatic int changed_xattr(struct send_ctx *sctx, 707362306a36Sopenharmony_ci enum btrfs_compare_tree_result result) 707462306a36Sopenharmony_ci{ 707562306a36Sopenharmony_ci int ret = 0; 707662306a36Sopenharmony_ci 707762306a36Sopenharmony_ci if (sctx->cur_ino != sctx->cmp_key->objectid) { 707862306a36Sopenharmony_ci inconsistent_snapshot_error(sctx, result, "xattr"); 707962306a36Sopenharmony_ci return -EIO; 708062306a36Sopenharmony_ci } 708162306a36Sopenharmony_ci 708262306a36Sopenharmony_ci if (!sctx->cur_inode_new_gen && !sctx->cur_inode_deleted) { 708362306a36Sopenharmony_ci if (result == BTRFS_COMPARE_TREE_NEW) 708462306a36Sopenharmony_ci ret = process_new_xattr(sctx); 708562306a36Sopenharmony_ci else if (result == BTRFS_COMPARE_TREE_DELETED) 708662306a36Sopenharmony_ci ret = process_deleted_xattr(sctx); 708762306a36Sopenharmony_ci else if (result == BTRFS_COMPARE_TREE_CHANGED) 708862306a36Sopenharmony_ci ret = process_changed_xattr(sctx); 708962306a36Sopenharmony_ci } 709062306a36Sopenharmony_ci 709162306a36Sopenharmony_ci return ret; 709262306a36Sopenharmony_ci} 709362306a36Sopenharmony_ci 709462306a36Sopenharmony_ci/* 709562306a36Sopenharmony_ci * Process new/deleted/changed extents. We skip processing in the 709662306a36Sopenharmony_ci * cur_inode_new_gen case because changed_inode did already initiate processing 709762306a36Sopenharmony_ci * of extents. The reason is the same as in changed_ref 709862306a36Sopenharmony_ci */ 709962306a36Sopenharmony_cistatic int changed_extent(struct send_ctx *sctx, 710062306a36Sopenharmony_ci enum btrfs_compare_tree_result result) 710162306a36Sopenharmony_ci{ 710262306a36Sopenharmony_ci int ret = 0; 710362306a36Sopenharmony_ci 710462306a36Sopenharmony_ci /* 710562306a36Sopenharmony_ci * We have found an extent item that changed without the inode item 710662306a36Sopenharmony_ci * having changed. This can happen either after relocation (where the 710762306a36Sopenharmony_ci * disk_bytenr of an extent item is replaced at 710862306a36Sopenharmony_ci * relocation.c:replace_file_extents()) or after deduplication into a 710962306a36Sopenharmony_ci * file in both the parent and send snapshots (where an extent item can 711062306a36Sopenharmony_ci * get modified or replaced with a new one). Note that deduplication 711162306a36Sopenharmony_ci * updates the inode item, but it only changes the iversion (sequence 711262306a36Sopenharmony_ci * field in the inode item) of the inode, so if a file is deduplicated 711362306a36Sopenharmony_ci * the same amount of times in both the parent and send snapshots, its 711462306a36Sopenharmony_ci * iversion becomes the same in both snapshots, whence the inode item is 711562306a36Sopenharmony_ci * the same on both snapshots. 711662306a36Sopenharmony_ci */ 711762306a36Sopenharmony_ci if (sctx->cur_ino != sctx->cmp_key->objectid) 711862306a36Sopenharmony_ci return 0; 711962306a36Sopenharmony_ci 712062306a36Sopenharmony_ci if (!sctx->cur_inode_new_gen && !sctx->cur_inode_deleted) { 712162306a36Sopenharmony_ci if (result != BTRFS_COMPARE_TREE_DELETED) 712262306a36Sopenharmony_ci ret = process_extent(sctx, sctx->left_path, 712362306a36Sopenharmony_ci sctx->cmp_key); 712462306a36Sopenharmony_ci } 712562306a36Sopenharmony_ci 712662306a36Sopenharmony_ci return ret; 712762306a36Sopenharmony_ci} 712862306a36Sopenharmony_ci 712962306a36Sopenharmony_cistatic int changed_verity(struct send_ctx *sctx, enum btrfs_compare_tree_result result) 713062306a36Sopenharmony_ci{ 713162306a36Sopenharmony_ci int ret = 0; 713262306a36Sopenharmony_ci 713362306a36Sopenharmony_ci if (!sctx->cur_inode_new_gen && !sctx->cur_inode_deleted) { 713462306a36Sopenharmony_ci if (result == BTRFS_COMPARE_TREE_NEW) 713562306a36Sopenharmony_ci sctx->cur_inode_needs_verity = true; 713662306a36Sopenharmony_ci } 713762306a36Sopenharmony_ci return ret; 713862306a36Sopenharmony_ci} 713962306a36Sopenharmony_ci 714062306a36Sopenharmony_cistatic int dir_changed(struct send_ctx *sctx, u64 dir) 714162306a36Sopenharmony_ci{ 714262306a36Sopenharmony_ci u64 orig_gen, new_gen; 714362306a36Sopenharmony_ci int ret; 714462306a36Sopenharmony_ci 714562306a36Sopenharmony_ci ret = get_inode_gen(sctx->send_root, dir, &new_gen); 714662306a36Sopenharmony_ci if (ret) 714762306a36Sopenharmony_ci return ret; 714862306a36Sopenharmony_ci 714962306a36Sopenharmony_ci ret = get_inode_gen(sctx->parent_root, dir, &orig_gen); 715062306a36Sopenharmony_ci if (ret) 715162306a36Sopenharmony_ci return ret; 715262306a36Sopenharmony_ci 715362306a36Sopenharmony_ci return (orig_gen != new_gen) ? 1 : 0; 715462306a36Sopenharmony_ci} 715562306a36Sopenharmony_ci 715662306a36Sopenharmony_cistatic int compare_refs(struct send_ctx *sctx, struct btrfs_path *path, 715762306a36Sopenharmony_ci struct btrfs_key *key) 715862306a36Sopenharmony_ci{ 715962306a36Sopenharmony_ci struct btrfs_inode_extref *extref; 716062306a36Sopenharmony_ci struct extent_buffer *leaf; 716162306a36Sopenharmony_ci u64 dirid = 0, last_dirid = 0; 716262306a36Sopenharmony_ci unsigned long ptr; 716362306a36Sopenharmony_ci u32 item_size; 716462306a36Sopenharmony_ci u32 cur_offset = 0; 716562306a36Sopenharmony_ci int ref_name_len; 716662306a36Sopenharmony_ci int ret = 0; 716762306a36Sopenharmony_ci 716862306a36Sopenharmony_ci /* Easy case, just check this one dirid */ 716962306a36Sopenharmony_ci if (key->type == BTRFS_INODE_REF_KEY) { 717062306a36Sopenharmony_ci dirid = key->offset; 717162306a36Sopenharmony_ci 717262306a36Sopenharmony_ci ret = dir_changed(sctx, dirid); 717362306a36Sopenharmony_ci goto out; 717462306a36Sopenharmony_ci } 717562306a36Sopenharmony_ci 717662306a36Sopenharmony_ci leaf = path->nodes[0]; 717762306a36Sopenharmony_ci item_size = btrfs_item_size(leaf, path->slots[0]); 717862306a36Sopenharmony_ci ptr = btrfs_item_ptr_offset(leaf, path->slots[0]); 717962306a36Sopenharmony_ci while (cur_offset < item_size) { 718062306a36Sopenharmony_ci extref = (struct btrfs_inode_extref *)(ptr + 718162306a36Sopenharmony_ci cur_offset); 718262306a36Sopenharmony_ci dirid = btrfs_inode_extref_parent(leaf, extref); 718362306a36Sopenharmony_ci ref_name_len = btrfs_inode_extref_name_len(leaf, extref); 718462306a36Sopenharmony_ci cur_offset += ref_name_len + sizeof(*extref); 718562306a36Sopenharmony_ci if (dirid == last_dirid) 718662306a36Sopenharmony_ci continue; 718762306a36Sopenharmony_ci ret = dir_changed(sctx, dirid); 718862306a36Sopenharmony_ci if (ret) 718962306a36Sopenharmony_ci break; 719062306a36Sopenharmony_ci last_dirid = dirid; 719162306a36Sopenharmony_ci } 719262306a36Sopenharmony_ciout: 719362306a36Sopenharmony_ci return ret; 719462306a36Sopenharmony_ci} 719562306a36Sopenharmony_ci 719662306a36Sopenharmony_ci/* 719762306a36Sopenharmony_ci * Updates compare related fields in sctx and simply forwards to the actual 719862306a36Sopenharmony_ci * changed_xxx functions. 719962306a36Sopenharmony_ci */ 720062306a36Sopenharmony_cistatic int changed_cb(struct btrfs_path *left_path, 720162306a36Sopenharmony_ci struct btrfs_path *right_path, 720262306a36Sopenharmony_ci struct btrfs_key *key, 720362306a36Sopenharmony_ci enum btrfs_compare_tree_result result, 720462306a36Sopenharmony_ci struct send_ctx *sctx) 720562306a36Sopenharmony_ci{ 720662306a36Sopenharmony_ci int ret = 0; 720762306a36Sopenharmony_ci 720862306a36Sopenharmony_ci /* 720962306a36Sopenharmony_ci * We can not hold the commit root semaphore here. This is because in 721062306a36Sopenharmony_ci * the case of sending and receiving to the same filesystem, using a 721162306a36Sopenharmony_ci * pipe, could result in a deadlock: 721262306a36Sopenharmony_ci * 721362306a36Sopenharmony_ci * 1) The task running send blocks on the pipe because it's full; 721462306a36Sopenharmony_ci * 721562306a36Sopenharmony_ci * 2) The task running receive, which is the only consumer of the pipe, 721662306a36Sopenharmony_ci * is waiting for a transaction commit (for example due to a space 721762306a36Sopenharmony_ci * reservation when doing a write or triggering a transaction commit 721862306a36Sopenharmony_ci * when creating a subvolume); 721962306a36Sopenharmony_ci * 722062306a36Sopenharmony_ci * 3) The transaction is waiting to write lock the commit root semaphore, 722162306a36Sopenharmony_ci * but can not acquire it since it's being held at 1). 722262306a36Sopenharmony_ci * 722362306a36Sopenharmony_ci * Down this call chain we write to the pipe through kernel_write(). 722462306a36Sopenharmony_ci * The same type of problem can also happen when sending to a file that 722562306a36Sopenharmony_ci * is stored in the same filesystem - when reserving space for a write 722662306a36Sopenharmony_ci * into the file, we can trigger a transaction commit. 722762306a36Sopenharmony_ci * 722862306a36Sopenharmony_ci * Our caller has supplied us with clones of leaves from the send and 722962306a36Sopenharmony_ci * parent roots, so we're safe here from a concurrent relocation and 723062306a36Sopenharmony_ci * further reallocation of metadata extents while we are here. Below we 723162306a36Sopenharmony_ci * also assert that the leaves are clones. 723262306a36Sopenharmony_ci */ 723362306a36Sopenharmony_ci lockdep_assert_not_held(&sctx->send_root->fs_info->commit_root_sem); 723462306a36Sopenharmony_ci 723562306a36Sopenharmony_ci /* 723662306a36Sopenharmony_ci * We always have a send root, so left_path is never NULL. We will not 723762306a36Sopenharmony_ci * have a leaf when we have reached the end of the send root but have 723862306a36Sopenharmony_ci * not yet reached the end of the parent root. 723962306a36Sopenharmony_ci */ 724062306a36Sopenharmony_ci if (left_path->nodes[0]) 724162306a36Sopenharmony_ci ASSERT(test_bit(EXTENT_BUFFER_UNMAPPED, 724262306a36Sopenharmony_ci &left_path->nodes[0]->bflags)); 724362306a36Sopenharmony_ci /* 724462306a36Sopenharmony_ci * When doing a full send we don't have a parent root, so right_path is 724562306a36Sopenharmony_ci * NULL. When doing an incremental send, we may have reached the end of 724662306a36Sopenharmony_ci * the parent root already, so we don't have a leaf at right_path. 724762306a36Sopenharmony_ci */ 724862306a36Sopenharmony_ci if (right_path && right_path->nodes[0]) 724962306a36Sopenharmony_ci ASSERT(test_bit(EXTENT_BUFFER_UNMAPPED, 725062306a36Sopenharmony_ci &right_path->nodes[0]->bflags)); 725162306a36Sopenharmony_ci 725262306a36Sopenharmony_ci if (result == BTRFS_COMPARE_TREE_SAME) { 725362306a36Sopenharmony_ci if (key->type == BTRFS_INODE_REF_KEY || 725462306a36Sopenharmony_ci key->type == BTRFS_INODE_EXTREF_KEY) { 725562306a36Sopenharmony_ci ret = compare_refs(sctx, left_path, key); 725662306a36Sopenharmony_ci if (!ret) 725762306a36Sopenharmony_ci return 0; 725862306a36Sopenharmony_ci if (ret < 0) 725962306a36Sopenharmony_ci return ret; 726062306a36Sopenharmony_ci } else if (key->type == BTRFS_EXTENT_DATA_KEY) { 726162306a36Sopenharmony_ci return maybe_send_hole(sctx, left_path, key); 726262306a36Sopenharmony_ci } else { 726362306a36Sopenharmony_ci return 0; 726462306a36Sopenharmony_ci } 726562306a36Sopenharmony_ci result = BTRFS_COMPARE_TREE_CHANGED; 726662306a36Sopenharmony_ci ret = 0; 726762306a36Sopenharmony_ci } 726862306a36Sopenharmony_ci 726962306a36Sopenharmony_ci sctx->left_path = left_path; 727062306a36Sopenharmony_ci sctx->right_path = right_path; 727162306a36Sopenharmony_ci sctx->cmp_key = key; 727262306a36Sopenharmony_ci 727362306a36Sopenharmony_ci ret = finish_inode_if_needed(sctx, 0); 727462306a36Sopenharmony_ci if (ret < 0) 727562306a36Sopenharmony_ci goto out; 727662306a36Sopenharmony_ci 727762306a36Sopenharmony_ci /* Ignore non-FS objects */ 727862306a36Sopenharmony_ci if (key->objectid == BTRFS_FREE_INO_OBJECTID || 727962306a36Sopenharmony_ci key->objectid == BTRFS_FREE_SPACE_OBJECTID) 728062306a36Sopenharmony_ci goto out; 728162306a36Sopenharmony_ci 728262306a36Sopenharmony_ci if (key->type == BTRFS_INODE_ITEM_KEY) { 728362306a36Sopenharmony_ci ret = changed_inode(sctx, result); 728462306a36Sopenharmony_ci } else if (!sctx->ignore_cur_inode) { 728562306a36Sopenharmony_ci if (key->type == BTRFS_INODE_REF_KEY || 728662306a36Sopenharmony_ci key->type == BTRFS_INODE_EXTREF_KEY) 728762306a36Sopenharmony_ci ret = changed_ref(sctx, result); 728862306a36Sopenharmony_ci else if (key->type == BTRFS_XATTR_ITEM_KEY) 728962306a36Sopenharmony_ci ret = changed_xattr(sctx, result); 729062306a36Sopenharmony_ci else if (key->type == BTRFS_EXTENT_DATA_KEY) 729162306a36Sopenharmony_ci ret = changed_extent(sctx, result); 729262306a36Sopenharmony_ci else if (key->type == BTRFS_VERITY_DESC_ITEM_KEY && 729362306a36Sopenharmony_ci key->offset == 0) 729462306a36Sopenharmony_ci ret = changed_verity(sctx, result); 729562306a36Sopenharmony_ci } 729662306a36Sopenharmony_ci 729762306a36Sopenharmony_ciout: 729862306a36Sopenharmony_ci return ret; 729962306a36Sopenharmony_ci} 730062306a36Sopenharmony_ci 730162306a36Sopenharmony_cistatic int search_key_again(const struct send_ctx *sctx, 730262306a36Sopenharmony_ci struct btrfs_root *root, 730362306a36Sopenharmony_ci struct btrfs_path *path, 730462306a36Sopenharmony_ci const struct btrfs_key *key) 730562306a36Sopenharmony_ci{ 730662306a36Sopenharmony_ci int ret; 730762306a36Sopenharmony_ci 730862306a36Sopenharmony_ci if (!path->need_commit_sem) 730962306a36Sopenharmony_ci lockdep_assert_held_read(&root->fs_info->commit_root_sem); 731062306a36Sopenharmony_ci 731162306a36Sopenharmony_ci /* 731262306a36Sopenharmony_ci * Roots used for send operations are readonly and no one can add, 731362306a36Sopenharmony_ci * update or remove keys from them, so we should be able to find our 731462306a36Sopenharmony_ci * key again. The only exception is deduplication, which can operate on 731562306a36Sopenharmony_ci * readonly roots and add, update or remove keys to/from them - but at 731662306a36Sopenharmony_ci * the moment we don't allow it to run in parallel with send. 731762306a36Sopenharmony_ci */ 731862306a36Sopenharmony_ci ret = btrfs_search_slot(NULL, root, key, path, 0, 0); 731962306a36Sopenharmony_ci ASSERT(ret <= 0); 732062306a36Sopenharmony_ci if (ret > 0) { 732162306a36Sopenharmony_ci btrfs_print_tree(path->nodes[path->lowest_level], false); 732262306a36Sopenharmony_ci btrfs_err(root->fs_info, 732362306a36Sopenharmony_ci"send: key (%llu %u %llu) not found in %s root %llu, lowest_level %d, slot %d", 732462306a36Sopenharmony_ci key->objectid, key->type, key->offset, 732562306a36Sopenharmony_ci (root == sctx->parent_root ? "parent" : "send"), 732662306a36Sopenharmony_ci root->root_key.objectid, path->lowest_level, 732762306a36Sopenharmony_ci path->slots[path->lowest_level]); 732862306a36Sopenharmony_ci return -EUCLEAN; 732962306a36Sopenharmony_ci } 733062306a36Sopenharmony_ci 733162306a36Sopenharmony_ci return ret; 733262306a36Sopenharmony_ci} 733362306a36Sopenharmony_ci 733462306a36Sopenharmony_cistatic int full_send_tree(struct send_ctx *sctx) 733562306a36Sopenharmony_ci{ 733662306a36Sopenharmony_ci int ret; 733762306a36Sopenharmony_ci struct btrfs_root *send_root = sctx->send_root; 733862306a36Sopenharmony_ci struct btrfs_key key; 733962306a36Sopenharmony_ci struct btrfs_fs_info *fs_info = send_root->fs_info; 734062306a36Sopenharmony_ci struct btrfs_path *path; 734162306a36Sopenharmony_ci 734262306a36Sopenharmony_ci path = alloc_path_for_send(); 734362306a36Sopenharmony_ci if (!path) 734462306a36Sopenharmony_ci return -ENOMEM; 734562306a36Sopenharmony_ci path->reada = READA_FORWARD_ALWAYS; 734662306a36Sopenharmony_ci 734762306a36Sopenharmony_ci key.objectid = BTRFS_FIRST_FREE_OBJECTID; 734862306a36Sopenharmony_ci key.type = BTRFS_INODE_ITEM_KEY; 734962306a36Sopenharmony_ci key.offset = 0; 735062306a36Sopenharmony_ci 735162306a36Sopenharmony_ci down_read(&fs_info->commit_root_sem); 735262306a36Sopenharmony_ci sctx->last_reloc_trans = fs_info->last_reloc_trans; 735362306a36Sopenharmony_ci up_read(&fs_info->commit_root_sem); 735462306a36Sopenharmony_ci 735562306a36Sopenharmony_ci ret = btrfs_search_slot_for_read(send_root, &key, path, 1, 0); 735662306a36Sopenharmony_ci if (ret < 0) 735762306a36Sopenharmony_ci goto out; 735862306a36Sopenharmony_ci if (ret) 735962306a36Sopenharmony_ci goto out_finish; 736062306a36Sopenharmony_ci 736162306a36Sopenharmony_ci while (1) { 736262306a36Sopenharmony_ci btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]); 736362306a36Sopenharmony_ci 736462306a36Sopenharmony_ci ret = changed_cb(path, NULL, &key, 736562306a36Sopenharmony_ci BTRFS_COMPARE_TREE_NEW, sctx); 736662306a36Sopenharmony_ci if (ret < 0) 736762306a36Sopenharmony_ci goto out; 736862306a36Sopenharmony_ci 736962306a36Sopenharmony_ci down_read(&fs_info->commit_root_sem); 737062306a36Sopenharmony_ci if (fs_info->last_reloc_trans > sctx->last_reloc_trans) { 737162306a36Sopenharmony_ci sctx->last_reloc_trans = fs_info->last_reloc_trans; 737262306a36Sopenharmony_ci up_read(&fs_info->commit_root_sem); 737362306a36Sopenharmony_ci /* 737462306a36Sopenharmony_ci * A transaction used for relocating a block group was 737562306a36Sopenharmony_ci * committed or is about to finish its commit. Release 737662306a36Sopenharmony_ci * our path (leaf) and restart the search, so that we 737762306a36Sopenharmony_ci * avoid operating on any file extent items that are 737862306a36Sopenharmony_ci * stale, with a disk_bytenr that reflects a pre 737962306a36Sopenharmony_ci * relocation value. This way we avoid as much as 738062306a36Sopenharmony_ci * possible to fallback to regular writes when checking 738162306a36Sopenharmony_ci * if we can clone file ranges. 738262306a36Sopenharmony_ci */ 738362306a36Sopenharmony_ci btrfs_release_path(path); 738462306a36Sopenharmony_ci ret = search_key_again(sctx, send_root, path, &key); 738562306a36Sopenharmony_ci if (ret < 0) 738662306a36Sopenharmony_ci goto out; 738762306a36Sopenharmony_ci } else { 738862306a36Sopenharmony_ci up_read(&fs_info->commit_root_sem); 738962306a36Sopenharmony_ci } 739062306a36Sopenharmony_ci 739162306a36Sopenharmony_ci ret = btrfs_next_item(send_root, path); 739262306a36Sopenharmony_ci if (ret < 0) 739362306a36Sopenharmony_ci goto out; 739462306a36Sopenharmony_ci if (ret) { 739562306a36Sopenharmony_ci ret = 0; 739662306a36Sopenharmony_ci break; 739762306a36Sopenharmony_ci } 739862306a36Sopenharmony_ci } 739962306a36Sopenharmony_ci 740062306a36Sopenharmony_ciout_finish: 740162306a36Sopenharmony_ci ret = finish_inode_if_needed(sctx, 1); 740262306a36Sopenharmony_ci 740362306a36Sopenharmony_ciout: 740462306a36Sopenharmony_ci btrfs_free_path(path); 740562306a36Sopenharmony_ci return ret; 740662306a36Sopenharmony_ci} 740762306a36Sopenharmony_ci 740862306a36Sopenharmony_cistatic int replace_node_with_clone(struct btrfs_path *path, int level) 740962306a36Sopenharmony_ci{ 741062306a36Sopenharmony_ci struct extent_buffer *clone; 741162306a36Sopenharmony_ci 741262306a36Sopenharmony_ci clone = btrfs_clone_extent_buffer(path->nodes[level]); 741362306a36Sopenharmony_ci if (!clone) 741462306a36Sopenharmony_ci return -ENOMEM; 741562306a36Sopenharmony_ci 741662306a36Sopenharmony_ci free_extent_buffer(path->nodes[level]); 741762306a36Sopenharmony_ci path->nodes[level] = clone; 741862306a36Sopenharmony_ci 741962306a36Sopenharmony_ci return 0; 742062306a36Sopenharmony_ci} 742162306a36Sopenharmony_ci 742262306a36Sopenharmony_cistatic int tree_move_down(struct btrfs_path *path, int *level, u64 reada_min_gen) 742362306a36Sopenharmony_ci{ 742462306a36Sopenharmony_ci struct extent_buffer *eb; 742562306a36Sopenharmony_ci struct extent_buffer *parent = path->nodes[*level]; 742662306a36Sopenharmony_ci int slot = path->slots[*level]; 742762306a36Sopenharmony_ci const int nritems = btrfs_header_nritems(parent); 742862306a36Sopenharmony_ci u64 reada_max; 742962306a36Sopenharmony_ci u64 reada_done = 0; 743062306a36Sopenharmony_ci 743162306a36Sopenharmony_ci lockdep_assert_held_read(&parent->fs_info->commit_root_sem); 743262306a36Sopenharmony_ci 743362306a36Sopenharmony_ci BUG_ON(*level == 0); 743462306a36Sopenharmony_ci eb = btrfs_read_node_slot(parent, slot); 743562306a36Sopenharmony_ci if (IS_ERR(eb)) 743662306a36Sopenharmony_ci return PTR_ERR(eb); 743762306a36Sopenharmony_ci 743862306a36Sopenharmony_ci /* 743962306a36Sopenharmony_ci * Trigger readahead for the next leaves we will process, so that it is 744062306a36Sopenharmony_ci * very likely that when we need them they are already in memory and we 744162306a36Sopenharmony_ci * will not block on disk IO. For nodes we only do readahead for one, 744262306a36Sopenharmony_ci * since the time window between processing nodes is typically larger. 744362306a36Sopenharmony_ci */ 744462306a36Sopenharmony_ci reada_max = (*level == 1 ? SZ_128K : eb->fs_info->nodesize); 744562306a36Sopenharmony_ci 744662306a36Sopenharmony_ci for (slot++; slot < nritems && reada_done < reada_max; slot++) { 744762306a36Sopenharmony_ci if (btrfs_node_ptr_generation(parent, slot) > reada_min_gen) { 744862306a36Sopenharmony_ci btrfs_readahead_node_child(parent, slot); 744962306a36Sopenharmony_ci reada_done += eb->fs_info->nodesize; 745062306a36Sopenharmony_ci } 745162306a36Sopenharmony_ci } 745262306a36Sopenharmony_ci 745362306a36Sopenharmony_ci path->nodes[*level - 1] = eb; 745462306a36Sopenharmony_ci path->slots[*level - 1] = 0; 745562306a36Sopenharmony_ci (*level)--; 745662306a36Sopenharmony_ci 745762306a36Sopenharmony_ci if (*level == 0) 745862306a36Sopenharmony_ci return replace_node_with_clone(path, 0); 745962306a36Sopenharmony_ci 746062306a36Sopenharmony_ci return 0; 746162306a36Sopenharmony_ci} 746262306a36Sopenharmony_ci 746362306a36Sopenharmony_cistatic int tree_move_next_or_upnext(struct btrfs_path *path, 746462306a36Sopenharmony_ci int *level, int root_level) 746562306a36Sopenharmony_ci{ 746662306a36Sopenharmony_ci int ret = 0; 746762306a36Sopenharmony_ci int nritems; 746862306a36Sopenharmony_ci nritems = btrfs_header_nritems(path->nodes[*level]); 746962306a36Sopenharmony_ci 747062306a36Sopenharmony_ci path->slots[*level]++; 747162306a36Sopenharmony_ci 747262306a36Sopenharmony_ci while (path->slots[*level] >= nritems) { 747362306a36Sopenharmony_ci if (*level == root_level) { 747462306a36Sopenharmony_ci path->slots[*level] = nritems - 1; 747562306a36Sopenharmony_ci return -1; 747662306a36Sopenharmony_ci } 747762306a36Sopenharmony_ci 747862306a36Sopenharmony_ci /* move upnext */ 747962306a36Sopenharmony_ci path->slots[*level] = 0; 748062306a36Sopenharmony_ci free_extent_buffer(path->nodes[*level]); 748162306a36Sopenharmony_ci path->nodes[*level] = NULL; 748262306a36Sopenharmony_ci (*level)++; 748362306a36Sopenharmony_ci path->slots[*level]++; 748462306a36Sopenharmony_ci 748562306a36Sopenharmony_ci nritems = btrfs_header_nritems(path->nodes[*level]); 748662306a36Sopenharmony_ci ret = 1; 748762306a36Sopenharmony_ci } 748862306a36Sopenharmony_ci return ret; 748962306a36Sopenharmony_ci} 749062306a36Sopenharmony_ci 749162306a36Sopenharmony_ci/* 749262306a36Sopenharmony_ci * Returns 1 if it had to move up and next. 0 is returned if it moved only next 749362306a36Sopenharmony_ci * or down. 749462306a36Sopenharmony_ci */ 749562306a36Sopenharmony_cistatic int tree_advance(struct btrfs_path *path, 749662306a36Sopenharmony_ci int *level, int root_level, 749762306a36Sopenharmony_ci int allow_down, 749862306a36Sopenharmony_ci struct btrfs_key *key, 749962306a36Sopenharmony_ci u64 reada_min_gen) 750062306a36Sopenharmony_ci{ 750162306a36Sopenharmony_ci int ret; 750262306a36Sopenharmony_ci 750362306a36Sopenharmony_ci if (*level == 0 || !allow_down) { 750462306a36Sopenharmony_ci ret = tree_move_next_or_upnext(path, level, root_level); 750562306a36Sopenharmony_ci } else { 750662306a36Sopenharmony_ci ret = tree_move_down(path, level, reada_min_gen); 750762306a36Sopenharmony_ci } 750862306a36Sopenharmony_ci 750962306a36Sopenharmony_ci /* 751062306a36Sopenharmony_ci * Even if we have reached the end of a tree, ret is -1, update the key 751162306a36Sopenharmony_ci * anyway, so that in case we need to restart due to a block group 751262306a36Sopenharmony_ci * relocation, we can assert that the last key of the root node still 751362306a36Sopenharmony_ci * exists in the tree. 751462306a36Sopenharmony_ci */ 751562306a36Sopenharmony_ci if (*level == 0) 751662306a36Sopenharmony_ci btrfs_item_key_to_cpu(path->nodes[*level], key, 751762306a36Sopenharmony_ci path->slots[*level]); 751862306a36Sopenharmony_ci else 751962306a36Sopenharmony_ci btrfs_node_key_to_cpu(path->nodes[*level], key, 752062306a36Sopenharmony_ci path->slots[*level]); 752162306a36Sopenharmony_ci 752262306a36Sopenharmony_ci return ret; 752362306a36Sopenharmony_ci} 752462306a36Sopenharmony_ci 752562306a36Sopenharmony_cistatic int tree_compare_item(struct btrfs_path *left_path, 752662306a36Sopenharmony_ci struct btrfs_path *right_path, 752762306a36Sopenharmony_ci char *tmp_buf) 752862306a36Sopenharmony_ci{ 752962306a36Sopenharmony_ci int cmp; 753062306a36Sopenharmony_ci int len1, len2; 753162306a36Sopenharmony_ci unsigned long off1, off2; 753262306a36Sopenharmony_ci 753362306a36Sopenharmony_ci len1 = btrfs_item_size(left_path->nodes[0], left_path->slots[0]); 753462306a36Sopenharmony_ci len2 = btrfs_item_size(right_path->nodes[0], right_path->slots[0]); 753562306a36Sopenharmony_ci if (len1 != len2) 753662306a36Sopenharmony_ci return 1; 753762306a36Sopenharmony_ci 753862306a36Sopenharmony_ci off1 = btrfs_item_ptr_offset(left_path->nodes[0], left_path->slots[0]); 753962306a36Sopenharmony_ci off2 = btrfs_item_ptr_offset(right_path->nodes[0], 754062306a36Sopenharmony_ci right_path->slots[0]); 754162306a36Sopenharmony_ci 754262306a36Sopenharmony_ci read_extent_buffer(left_path->nodes[0], tmp_buf, off1, len1); 754362306a36Sopenharmony_ci 754462306a36Sopenharmony_ci cmp = memcmp_extent_buffer(right_path->nodes[0], tmp_buf, off2, len1); 754562306a36Sopenharmony_ci if (cmp) 754662306a36Sopenharmony_ci return 1; 754762306a36Sopenharmony_ci return 0; 754862306a36Sopenharmony_ci} 754962306a36Sopenharmony_ci 755062306a36Sopenharmony_ci/* 755162306a36Sopenharmony_ci * A transaction used for relocating a block group was committed or is about to 755262306a36Sopenharmony_ci * finish its commit. Release our paths and restart the search, so that we are 755362306a36Sopenharmony_ci * not using stale extent buffers: 755462306a36Sopenharmony_ci * 755562306a36Sopenharmony_ci * 1) For levels > 0, we are only holding references of extent buffers, without 755662306a36Sopenharmony_ci * any locks on them, which does not prevent them from having been relocated 755762306a36Sopenharmony_ci * and reallocated after the last time we released the commit root semaphore. 755862306a36Sopenharmony_ci * The exception are the root nodes, for which we always have a clone, see 755962306a36Sopenharmony_ci * the comment at btrfs_compare_trees(); 756062306a36Sopenharmony_ci * 756162306a36Sopenharmony_ci * 2) For leaves, level 0, we are holding copies (clones) of extent buffers, so 756262306a36Sopenharmony_ci * we are safe from the concurrent relocation and reallocation. However they 756362306a36Sopenharmony_ci * can have file extent items with a pre relocation disk_bytenr value, so we 756462306a36Sopenharmony_ci * restart the start from the current commit roots and clone the new leaves so 756562306a36Sopenharmony_ci * that we get the post relocation disk_bytenr values. Not doing so, could 756662306a36Sopenharmony_ci * make us clone the wrong data in case there are new extents using the old 756762306a36Sopenharmony_ci * disk_bytenr that happen to be shared. 756862306a36Sopenharmony_ci */ 756962306a36Sopenharmony_cistatic int restart_after_relocation(struct btrfs_path *left_path, 757062306a36Sopenharmony_ci struct btrfs_path *right_path, 757162306a36Sopenharmony_ci const struct btrfs_key *left_key, 757262306a36Sopenharmony_ci const struct btrfs_key *right_key, 757362306a36Sopenharmony_ci int left_level, 757462306a36Sopenharmony_ci int right_level, 757562306a36Sopenharmony_ci const struct send_ctx *sctx) 757662306a36Sopenharmony_ci{ 757762306a36Sopenharmony_ci int root_level; 757862306a36Sopenharmony_ci int ret; 757962306a36Sopenharmony_ci 758062306a36Sopenharmony_ci lockdep_assert_held_read(&sctx->send_root->fs_info->commit_root_sem); 758162306a36Sopenharmony_ci 758262306a36Sopenharmony_ci btrfs_release_path(left_path); 758362306a36Sopenharmony_ci btrfs_release_path(right_path); 758462306a36Sopenharmony_ci 758562306a36Sopenharmony_ci /* 758662306a36Sopenharmony_ci * Since keys can not be added or removed to/from our roots because they 758762306a36Sopenharmony_ci * are readonly and we do not allow deduplication to run in parallel 758862306a36Sopenharmony_ci * (which can add, remove or change keys), the layout of the trees should 758962306a36Sopenharmony_ci * not change. 759062306a36Sopenharmony_ci */ 759162306a36Sopenharmony_ci left_path->lowest_level = left_level; 759262306a36Sopenharmony_ci ret = search_key_again(sctx, sctx->send_root, left_path, left_key); 759362306a36Sopenharmony_ci if (ret < 0) 759462306a36Sopenharmony_ci return ret; 759562306a36Sopenharmony_ci 759662306a36Sopenharmony_ci right_path->lowest_level = right_level; 759762306a36Sopenharmony_ci ret = search_key_again(sctx, sctx->parent_root, right_path, right_key); 759862306a36Sopenharmony_ci if (ret < 0) 759962306a36Sopenharmony_ci return ret; 760062306a36Sopenharmony_ci 760162306a36Sopenharmony_ci /* 760262306a36Sopenharmony_ci * If the lowest level nodes are leaves, clone them so that they can be 760362306a36Sopenharmony_ci * safely used by changed_cb() while not under the protection of the 760462306a36Sopenharmony_ci * commit root semaphore, even if relocation and reallocation happens in 760562306a36Sopenharmony_ci * parallel. 760662306a36Sopenharmony_ci */ 760762306a36Sopenharmony_ci if (left_level == 0) { 760862306a36Sopenharmony_ci ret = replace_node_with_clone(left_path, 0); 760962306a36Sopenharmony_ci if (ret < 0) 761062306a36Sopenharmony_ci return ret; 761162306a36Sopenharmony_ci } 761262306a36Sopenharmony_ci 761362306a36Sopenharmony_ci if (right_level == 0) { 761462306a36Sopenharmony_ci ret = replace_node_with_clone(right_path, 0); 761562306a36Sopenharmony_ci if (ret < 0) 761662306a36Sopenharmony_ci return ret; 761762306a36Sopenharmony_ci } 761862306a36Sopenharmony_ci 761962306a36Sopenharmony_ci /* 762062306a36Sopenharmony_ci * Now clone the root nodes (unless they happen to be the leaves we have 762162306a36Sopenharmony_ci * already cloned). This is to protect against concurrent snapshotting of 762262306a36Sopenharmony_ci * the send and parent roots (see the comment at btrfs_compare_trees()). 762362306a36Sopenharmony_ci */ 762462306a36Sopenharmony_ci root_level = btrfs_header_level(sctx->send_root->commit_root); 762562306a36Sopenharmony_ci if (root_level > 0) { 762662306a36Sopenharmony_ci ret = replace_node_with_clone(left_path, root_level); 762762306a36Sopenharmony_ci if (ret < 0) 762862306a36Sopenharmony_ci return ret; 762962306a36Sopenharmony_ci } 763062306a36Sopenharmony_ci 763162306a36Sopenharmony_ci root_level = btrfs_header_level(sctx->parent_root->commit_root); 763262306a36Sopenharmony_ci if (root_level > 0) { 763362306a36Sopenharmony_ci ret = replace_node_with_clone(right_path, root_level); 763462306a36Sopenharmony_ci if (ret < 0) 763562306a36Sopenharmony_ci return ret; 763662306a36Sopenharmony_ci } 763762306a36Sopenharmony_ci 763862306a36Sopenharmony_ci return 0; 763962306a36Sopenharmony_ci} 764062306a36Sopenharmony_ci 764162306a36Sopenharmony_ci/* 764262306a36Sopenharmony_ci * This function compares two trees and calls the provided callback for 764362306a36Sopenharmony_ci * every changed/new/deleted item it finds. 764462306a36Sopenharmony_ci * If shared tree blocks are encountered, whole subtrees are skipped, making 764562306a36Sopenharmony_ci * the compare pretty fast on snapshotted subvolumes. 764662306a36Sopenharmony_ci * 764762306a36Sopenharmony_ci * This currently works on commit roots only. As commit roots are read only, 764862306a36Sopenharmony_ci * we don't do any locking. The commit roots are protected with transactions. 764962306a36Sopenharmony_ci * Transactions are ended and rejoined when a commit is tried in between. 765062306a36Sopenharmony_ci * 765162306a36Sopenharmony_ci * This function checks for modifications done to the trees while comparing. 765262306a36Sopenharmony_ci * If it detects a change, it aborts immediately. 765362306a36Sopenharmony_ci */ 765462306a36Sopenharmony_cistatic int btrfs_compare_trees(struct btrfs_root *left_root, 765562306a36Sopenharmony_ci struct btrfs_root *right_root, struct send_ctx *sctx) 765662306a36Sopenharmony_ci{ 765762306a36Sopenharmony_ci struct btrfs_fs_info *fs_info = left_root->fs_info; 765862306a36Sopenharmony_ci int ret; 765962306a36Sopenharmony_ci int cmp; 766062306a36Sopenharmony_ci struct btrfs_path *left_path = NULL; 766162306a36Sopenharmony_ci struct btrfs_path *right_path = NULL; 766262306a36Sopenharmony_ci struct btrfs_key left_key; 766362306a36Sopenharmony_ci struct btrfs_key right_key; 766462306a36Sopenharmony_ci char *tmp_buf = NULL; 766562306a36Sopenharmony_ci int left_root_level; 766662306a36Sopenharmony_ci int right_root_level; 766762306a36Sopenharmony_ci int left_level; 766862306a36Sopenharmony_ci int right_level; 766962306a36Sopenharmony_ci int left_end_reached = 0; 767062306a36Sopenharmony_ci int right_end_reached = 0; 767162306a36Sopenharmony_ci int advance_left = 0; 767262306a36Sopenharmony_ci int advance_right = 0; 767362306a36Sopenharmony_ci u64 left_blockptr; 767462306a36Sopenharmony_ci u64 right_blockptr; 767562306a36Sopenharmony_ci u64 left_gen; 767662306a36Sopenharmony_ci u64 right_gen; 767762306a36Sopenharmony_ci u64 reada_min_gen; 767862306a36Sopenharmony_ci 767962306a36Sopenharmony_ci left_path = btrfs_alloc_path(); 768062306a36Sopenharmony_ci if (!left_path) { 768162306a36Sopenharmony_ci ret = -ENOMEM; 768262306a36Sopenharmony_ci goto out; 768362306a36Sopenharmony_ci } 768462306a36Sopenharmony_ci right_path = btrfs_alloc_path(); 768562306a36Sopenharmony_ci if (!right_path) { 768662306a36Sopenharmony_ci ret = -ENOMEM; 768762306a36Sopenharmony_ci goto out; 768862306a36Sopenharmony_ci } 768962306a36Sopenharmony_ci 769062306a36Sopenharmony_ci tmp_buf = kvmalloc(fs_info->nodesize, GFP_KERNEL); 769162306a36Sopenharmony_ci if (!tmp_buf) { 769262306a36Sopenharmony_ci ret = -ENOMEM; 769362306a36Sopenharmony_ci goto out; 769462306a36Sopenharmony_ci } 769562306a36Sopenharmony_ci 769662306a36Sopenharmony_ci left_path->search_commit_root = 1; 769762306a36Sopenharmony_ci left_path->skip_locking = 1; 769862306a36Sopenharmony_ci right_path->search_commit_root = 1; 769962306a36Sopenharmony_ci right_path->skip_locking = 1; 770062306a36Sopenharmony_ci 770162306a36Sopenharmony_ci /* 770262306a36Sopenharmony_ci * Strategy: Go to the first items of both trees. Then do 770362306a36Sopenharmony_ci * 770462306a36Sopenharmony_ci * If both trees are at level 0 770562306a36Sopenharmony_ci * Compare keys of current items 770662306a36Sopenharmony_ci * If left < right treat left item as new, advance left tree 770762306a36Sopenharmony_ci * and repeat 770862306a36Sopenharmony_ci * If left > right treat right item as deleted, advance right tree 770962306a36Sopenharmony_ci * and repeat 771062306a36Sopenharmony_ci * If left == right do deep compare of items, treat as changed if 771162306a36Sopenharmony_ci * needed, advance both trees and repeat 771262306a36Sopenharmony_ci * If both trees are at the same level but not at level 0 771362306a36Sopenharmony_ci * Compare keys of current nodes/leafs 771462306a36Sopenharmony_ci * If left < right advance left tree and repeat 771562306a36Sopenharmony_ci * If left > right advance right tree and repeat 771662306a36Sopenharmony_ci * If left == right compare blockptrs of the next nodes/leafs 771762306a36Sopenharmony_ci * If they match advance both trees but stay at the same level 771862306a36Sopenharmony_ci * and repeat 771962306a36Sopenharmony_ci * If they don't match advance both trees while allowing to go 772062306a36Sopenharmony_ci * deeper and repeat 772162306a36Sopenharmony_ci * If tree levels are different 772262306a36Sopenharmony_ci * Advance the tree that needs it and repeat 772362306a36Sopenharmony_ci * 772462306a36Sopenharmony_ci * Advancing a tree means: 772562306a36Sopenharmony_ci * If we are at level 0, try to go to the next slot. If that's not 772662306a36Sopenharmony_ci * possible, go one level up and repeat. Stop when we found a level 772762306a36Sopenharmony_ci * where we could go to the next slot. We may at this point be on a 772862306a36Sopenharmony_ci * node or a leaf. 772962306a36Sopenharmony_ci * 773062306a36Sopenharmony_ci * If we are not at level 0 and not on shared tree blocks, go one 773162306a36Sopenharmony_ci * level deeper. 773262306a36Sopenharmony_ci * 773362306a36Sopenharmony_ci * If we are not at level 0 and on shared tree blocks, go one slot to 773462306a36Sopenharmony_ci * the right if possible or go up and right. 773562306a36Sopenharmony_ci */ 773662306a36Sopenharmony_ci 773762306a36Sopenharmony_ci down_read(&fs_info->commit_root_sem); 773862306a36Sopenharmony_ci left_level = btrfs_header_level(left_root->commit_root); 773962306a36Sopenharmony_ci left_root_level = left_level; 774062306a36Sopenharmony_ci /* 774162306a36Sopenharmony_ci * We clone the root node of the send and parent roots to prevent races 774262306a36Sopenharmony_ci * with snapshot creation of these roots. Snapshot creation COWs the 774362306a36Sopenharmony_ci * root node of a tree, so after the transaction is committed the old 774462306a36Sopenharmony_ci * extent can be reallocated while this send operation is still ongoing. 774562306a36Sopenharmony_ci * So we clone them, under the commit root semaphore, to be race free. 774662306a36Sopenharmony_ci */ 774762306a36Sopenharmony_ci left_path->nodes[left_level] = 774862306a36Sopenharmony_ci btrfs_clone_extent_buffer(left_root->commit_root); 774962306a36Sopenharmony_ci if (!left_path->nodes[left_level]) { 775062306a36Sopenharmony_ci ret = -ENOMEM; 775162306a36Sopenharmony_ci goto out_unlock; 775262306a36Sopenharmony_ci } 775362306a36Sopenharmony_ci 775462306a36Sopenharmony_ci right_level = btrfs_header_level(right_root->commit_root); 775562306a36Sopenharmony_ci right_root_level = right_level; 775662306a36Sopenharmony_ci right_path->nodes[right_level] = 775762306a36Sopenharmony_ci btrfs_clone_extent_buffer(right_root->commit_root); 775862306a36Sopenharmony_ci if (!right_path->nodes[right_level]) { 775962306a36Sopenharmony_ci ret = -ENOMEM; 776062306a36Sopenharmony_ci goto out_unlock; 776162306a36Sopenharmony_ci } 776262306a36Sopenharmony_ci /* 776362306a36Sopenharmony_ci * Our right root is the parent root, while the left root is the "send" 776462306a36Sopenharmony_ci * root. We know that all new nodes/leaves in the left root must have 776562306a36Sopenharmony_ci * a generation greater than the right root's generation, so we trigger 776662306a36Sopenharmony_ci * readahead for those nodes and leaves of the left root, as we know we 776762306a36Sopenharmony_ci * will need to read them at some point. 776862306a36Sopenharmony_ci */ 776962306a36Sopenharmony_ci reada_min_gen = btrfs_header_generation(right_root->commit_root); 777062306a36Sopenharmony_ci 777162306a36Sopenharmony_ci if (left_level == 0) 777262306a36Sopenharmony_ci btrfs_item_key_to_cpu(left_path->nodes[left_level], 777362306a36Sopenharmony_ci &left_key, left_path->slots[left_level]); 777462306a36Sopenharmony_ci else 777562306a36Sopenharmony_ci btrfs_node_key_to_cpu(left_path->nodes[left_level], 777662306a36Sopenharmony_ci &left_key, left_path->slots[left_level]); 777762306a36Sopenharmony_ci if (right_level == 0) 777862306a36Sopenharmony_ci btrfs_item_key_to_cpu(right_path->nodes[right_level], 777962306a36Sopenharmony_ci &right_key, right_path->slots[right_level]); 778062306a36Sopenharmony_ci else 778162306a36Sopenharmony_ci btrfs_node_key_to_cpu(right_path->nodes[right_level], 778262306a36Sopenharmony_ci &right_key, right_path->slots[right_level]); 778362306a36Sopenharmony_ci 778462306a36Sopenharmony_ci sctx->last_reloc_trans = fs_info->last_reloc_trans; 778562306a36Sopenharmony_ci 778662306a36Sopenharmony_ci while (1) { 778762306a36Sopenharmony_ci if (need_resched() || 778862306a36Sopenharmony_ci rwsem_is_contended(&fs_info->commit_root_sem)) { 778962306a36Sopenharmony_ci up_read(&fs_info->commit_root_sem); 779062306a36Sopenharmony_ci cond_resched(); 779162306a36Sopenharmony_ci down_read(&fs_info->commit_root_sem); 779262306a36Sopenharmony_ci } 779362306a36Sopenharmony_ci 779462306a36Sopenharmony_ci if (fs_info->last_reloc_trans > sctx->last_reloc_trans) { 779562306a36Sopenharmony_ci ret = restart_after_relocation(left_path, right_path, 779662306a36Sopenharmony_ci &left_key, &right_key, 779762306a36Sopenharmony_ci left_level, right_level, 779862306a36Sopenharmony_ci sctx); 779962306a36Sopenharmony_ci if (ret < 0) 780062306a36Sopenharmony_ci goto out_unlock; 780162306a36Sopenharmony_ci sctx->last_reloc_trans = fs_info->last_reloc_trans; 780262306a36Sopenharmony_ci } 780362306a36Sopenharmony_ci 780462306a36Sopenharmony_ci if (advance_left && !left_end_reached) { 780562306a36Sopenharmony_ci ret = tree_advance(left_path, &left_level, 780662306a36Sopenharmony_ci left_root_level, 780762306a36Sopenharmony_ci advance_left != ADVANCE_ONLY_NEXT, 780862306a36Sopenharmony_ci &left_key, reada_min_gen); 780962306a36Sopenharmony_ci if (ret == -1) 781062306a36Sopenharmony_ci left_end_reached = ADVANCE; 781162306a36Sopenharmony_ci else if (ret < 0) 781262306a36Sopenharmony_ci goto out_unlock; 781362306a36Sopenharmony_ci advance_left = 0; 781462306a36Sopenharmony_ci } 781562306a36Sopenharmony_ci if (advance_right && !right_end_reached) { 781662306a36Sopenharmony_ci ret = tree_advance(right_path, &right_level, 781762306a36Sopenharmony_ci right_root_level, 781862306a36Sopenharmony_ci advance_right != ADVANCE_ONLY_NEXT, 781962306a36Sopenharmony_ci &right_key, reada_min_gen); 782062306a36Sopenharmony_ci if (ret == -1) 782162306a36Sopenharmony_ci right_end_reached = ADVANCE; 782262306a36Sopenharmony_ci else if (ret < 0) 782362306a36Sopenharmony_ci goto out_unlock; 782462306a36Sopenharmony_ci advance_right = 0; 782562306a36Sopenharmony_ci } 782662306a36Sopenharmony_ci 782762306a36Sopenharmony_ci if (left_end_reached && right_end_reached) { 782862306a36Sopenharmony_ci ret = 0; 782962306a36Sopenharmony_ci goto out_unlock; 783062306a36Sopenharmony_ci } else if (left_end_reached) { 783162306a36Sopenharmony_ci if (right_level == 0) { 783262306a36Sopenharmony_ci up_read(&fs_info->commit_root_sem); 783362306a36Sopenharmony_ci ret = changed_cb(left_path, right_path, 783462306a36Sopenharmony_ci &right_key, 783562306a36Sopenharmony_ci BTRFS_COMPARE_TREE_DELETED, 783662306a36Sopenharmony_ci sctx); 783762306a36Sopenharmony_ci if (ret < 0) 783862306a36Sopenharmony_ci goto out; 783962306a36Sopenharmony_ci down_read(&fs_info->commit_root_sem); 784062306a36Sopenharmony_ci } 784162306a36Sopenharmony_ci advance_right = ADVANCE; 784262306a36Sopenharmony_ci continue; 784362306a36Sopenharmony_ci } else if (right_end_reached) { 784462306a36Sopenharmony_ci if (left_level == 0) { 784562306a36Sopenharmony_ci up_read(&fs_info->commit_root_sem); 784662306a36Sopenharmony_ci ret = changed_cb(left_path, right_path, 784762306a36Sopenharmony_ci &left_key, 784862306a36Sopenharmony_ci BTRFS_COMPARE_TREE_NEW, 784962306a36Sopenharmony_ci sctx); 785062306a36Sopenharmony_ci if (ret < 0) 785162306a36Sopenharmony_ci goto out; 785262306a36Sopenharmony_ci down_read(&fs_info->commit_root_sem); 785362306a36Sopenharmony_ci } 785462306a36Sopenharmony_ci advance_left = ADVANCE; 785562306a36Sopenharmony_ci continue; 785662306a36Sopenharmony_ci } 785762306a36Sopenharmony_ci 785862306a36Sopenharmony_ci if (left_level == 0 && right_level == 0) { 785962306a36Sopenharmony_ci up_read(&fs_info->commit_root_sem); 786062306a36Sopenharmony_ci cmp = btrfs_comp_cpu_keys(&left_key, &right_key); 786162306a36Sopenharmony_ci if (cmp < 0) { 786262306a36Sopenharmony_ci ret = changed_cb(left_path, right_path, 786362306a36Sopenharmony_ci &left_key, 786462306a36Sopenharmony_ci BTRFS_COMPARE_TREE_NEW, 786562306a36Sopenharmony_ci sctx); 786662306a36Sopenharmony_ci advance_left = ADVANCE; 786762306a36Sopenharmony_ci } else if (cmp > 0) { 786862306a36Sopenharmony_ci ret = changed_cb(left_path, right_path, 786962306a36Sopenharmony_ci &right_key, 787062306a36Sopenharmony_ci BTRFS_COMPARE_TREE_DELETED, 787162306a36Sopenharmony_ci sctx); 787262306a36Sopenharmony_ci advance_right = ADVANCE; 787362306a36Sopenharmony_ci } else { 787462306a36Sopenharmony_ci enum btrfs_compare_tree_result result; 787562306a36Sopenharmony_ci 787662306a36Sopenharmony_ci WARN_ON(!extent_buffer_uptodate(left_path->nodes[0])); 787762306a36Sopenharmony_ci ret = tree_compare_item(left_path, right_path, 787862306a36Sopenharmony_ci tmp_buf); 787962306a36Sopenharmony_ci if (ret) 788062306a36Sopenharmony_ci result = BTRFS_COMPARE_TREE_CHANGED; 788162306a36Sopenharmony_ci else 788262306a36Sopenharmony_ci result = BTRFS_COMPARE_TREE_SAME; 788362306a36Sopenharmony_ci ret = changed_cb(left_path, right_path, 788462306a36Sopenharmony_ci &left_key, result, sctx); 788562306a36Sopenharmony_ci advance_left = ADVANCE; 788662306a36Sopenharmony_ci advance_right = ADVANCE; 788762306a36Sopenharmony_ci } 788862306a36Sopenharmony_ci 788962306a36Sopenharmony_ci if (ret < 0) 789062306a36Sopenharmony_ci goto out; 789162306a36Sopenharmony_ci down_read(&fs_info->commit_root_sem); 789262306a36Sopenharmony_ci } else if (left_level == right_level) { 789362306a36Sopenharmony_ci cmp = btrfs_comp_cpu_keys(&left_key, &right_key); 789462306a36Sopenharmony_ci if (cmp < 0) { 789562306a36Sopenharmony_ci advance_left = ADVANCE; 789662306a36Sopenharmony_ci } else if (cmp > 0) { 789762306a36Sopenharmony_ci advance_right = ADVANCE; 789862306a36Sopenharmony_ci } else { 789962306a36Sopenharmony_ci left_blockptr = btrfs_node_blockptr( 790062306a36Sopenharmony_ci left_path->nodes[left_level], 790162306a36Sopenharmony_ci left_path->slots[left_level]); 790262306a36Sopenharmony_ci right_blockptr = btrfs_node_blockptr( 790362306a36Sopenharmony_ci right_path->nodes[right_level], 790462306a36Sopenharmony_ci right_path->slots[right_level]); 790562306a36Sopenharmony_ci left_gen = btrfs_node_ptr_generation( 790662306a36Sopenharmony_ci left_path->nodes[left_level], 790762306a36Sopenharmony_ci left_path->slots[left_level]); 790862306a36Sopenharmony_ci right_gen = btrfs_node_ptr_generation( 790962306a36Sopenharmony_ci right_path->nodes[right_level], 791062306a36Sopenharmony_ci right_path->slots[right_level]); 791162306a36Sopenharmony_ci if (left_blockptr == right_blockptr && 791262306a36Sopenharmony_ci left_gen == right_gen) { 791362306a36Sopenharmony_ci /* 791462306a36Sopenharmony_ci * As we're on a shared block, don't 791562306a36Sopenharmony_ci * allow to go deeper. 791662306a36Sopenharmony_ci */ 791762306a36Sopenharmony_ci advance_left = ADVANCE_ONLY_NEXT; 791862306a36Sopenharmony_ci advance_right = ADVANCE_ONLY_NEXT; 791962306a36Sopenharmony_ci } else { 792062306a36Sopenharmony_ci advance_left = ADVANCE; 792162306a36Sopenharmony_ci advance_right = ADVANCE; 792262306a36Sopenharmony_ci } 792362306a36Sopenharmony_ci } 792462306a36Sopenharmony_ci } else if (left_level < right_level) { 792562306a36Sopenharmony_ci advance_right = ADVANCE; 792662306a36Sopenharmony_ci } else { 792762306a36Sopenharmony_ci advance_left = ADVANCE; 792862306a36Sopenharmony_ci } 792962306a36Sopenharmony_ci } 793062306a36Sopenharmony_ci 793162306a36Sopenharmony_ciout_unlock: 793262306a36Sopenharmony_ci up_read(&fs_info->commit_root_sem); 793362306a36Sopenharmony_ciout: 793462306a36Sopenharmony_ci btrfs_free_path(left_path); 793562306a36Sopenharmony_ci btrfs_free_path(right_path); 793662306a36Sopenharmony_ci kvfree(tmp_buf); 793762306a36Sopenharmony_ci return ret; 793862306a36Sopenharmony_ci} 793962306a36Sopenharmony_ci 794062306a36Sopenharmony_cistatic int send_subvol(struct send_ctx *sctx) 794162306a36Sopenharmony_ci{ 794262306a36Sopenharmony_ci int ret; 794362306a36Sopenharmony_ci 794462306a36Sopenharmony_ci if (!(sctx->flags & BTRFS_SEND_FLAG_OMIT_STREAM_HEADER)) { 794562306a36Sopenharmony_ci ret = send_header(sctx); 794662306a36Sopenharmony_ci if (ret < 0) 794762306a36Sopenharmony_ci goto out; 794862306a36Sopenharmony_ci } 794962306a36Sopenharmony_ci 795062306a36Sopenharmony_ci ret = send_subvol_begin(sctx); 795162306a36Sopenharmony_ci if (ret < 0) 795262306a36Sopenharmony_ci goto out; 795362306a36Sopenharmony_ci 795462306a36Sopenharmony_ci if (sctx->parent_root) { 795562306a36Sopenharmony_ci ret = btrfs_compare_trees(sctx->send_root, sctx->parent_root, sctx); 795662306a36Sopenharmony_ci if (ret < 0) 795762306a36Sopenharmony_ci goto out; 795862306a36Sopenharmony_ci ret = finish_inode_if_needed(sctx, 1); 795962306a36Sopenharmony_ci if (ret < 0) 796062306a36Sopenharmony_ci goto out; 796162306a36Sopenharmony_ci } else { 796262306a36Sopenharmony_ci ret = full_send_tree(sctx); 796362306a36Sopenharmony_ci if (ret < 0) 796462306a36Sopenharmony_ci goto out; 796562306a36Sopenharmony_ci } 796662306a36Sopenharmony_ci 796762306a36Sopenharmony_ciout: 796862306a36Sopenharmony_ci free_recorded_refs(sctx); 796962306a36Sopenharmony_ci return ret; 797062306a36Sopenharmony_ci} 797162306a36Sopenharmony_ci 797262306a36Sopenharmony_ci/* 797362306a36Sopenharmony_ci * If orphan cleanup did remove any orphans from a root, it means the tree 797462306a36Sopenharmony_ci * was modified and therefore the commit root is not the same as the current 797562306a36Sopenharmony_ci * root anymore. This is a problem, because send uses the commit root and 797662306a36Sopenharmony_ci * therefore can see inode items that don't exist in the current root anymore, 797762306a36Sopenharmony_ci * and for example make calls to btrfs_iget, which will do tree lookups based 797862306a36Sopenharmony_ci * on the current root and not on the commit root. Those lookups will fail, 797962306a36Sopenharmony_ci * returning a -ESTALE error, and making send fail with that error. So make 798062306a36Sopenharmony_ci * sure a send does not see any orphans we have just removed, and that it will 798162306a36Sopenharmony_ci * see the same inodes regardless of whether a transaction commit happened 798262306a36Sopenharmony_ci * before it started (meaning that the commit root will be the same as the 798362306a36Sopenharmony_ci * current root) or not. 798462306a36Sopenharmony_ci */ 798562306a36Sopenharmony_cistatic int ensure_commit_roots_uptodate(struct send_ctx *sctx) 798662306a36Sopenharmony_ci{ 798762306a36Sopenharmony_ci int i; 798862306a36Sopenharmony_ci struct btrfs_trans_handle *trans = NULL; 798962306a36Sopenharmony_ci 799062306a36Sopenharmony_ciagain: 799162306a36Sopenharmony_ci if (sctx->parent_root && 799262306a36Sopenharmony_ci sctx->parent_root->node != sctx->parent_root->commit_root) 799362306a36Sopenharmony_ci goto commit_trans; 799462306a36Sopenharmony_ci 799562306a36Sopenharmony_ci for (i = 0; i < sctx->clone_roots_cnt; i++) 799662306a36Sopenharmony_ci if (sctx->clone_roots[i].root->node != 799762306a36Sopenharmony_ci sctx->clone_roots[i].root->commit_root) 799862306a36Sopenharmony_ci goto commit_trans; 799962306a36Sopenharmony_ci 800062306a36Sopenharmony_ci if (trans) 800162306a36Sopenharmony_ci return btrfs_end_transaction(trans); 800262306a36Sopenharmony_ci 800362306a36Sopenharmony_ci return 0; 800462306a36Sopenharmony_ci 800562306a36Sopenharmony_cicommit_trans: 800662306a36Sopenharmony_ci /* Use any root, all fs roots will get their commit roots updated. */ 800762306a36Sopenharmony_ci if (!trans) { 800862306a36Sopenharmony_ci trans = btrfs_join_transaction(sctx->send_root); 800962306a36Sopenharmony_ci if (IS_ERR(trans)) 801062306a36Sopenharmony_ci return PTR_ERR(trans); 801162306a36Sopenharmony_ci goto again; 801262306a36Sopenharmony_ci } 801362306a36Sopenharmony_ci 801462306a36Sopenharmony_ci return btrfs_commit_transaction(trans); 801562306a36Sopenharmony_ci} 801662306a36Sopenharmony_ci 801762306a36Sopenharmony_ci/* 801862306a36Sopenharmony_ci * Make sure any existing dellaloc is flushed for any root used by a send 801962306a36Sopenharmony_ci * operation so that we do not miss any data and we do not race with writeback 802062306a36Sopenharmony_ci * finishing and changing a tree while send is using the tree. This could 802162306a36Sopenharmony_ci * happen if a subvolume is in RW mode, has delalloc, is turned to RO mode and 802262306a36Sopenharmony_ci * a send operation then uses the subvolume. 802362306a36Sopenharmony_ci * After flushing delalloc ensure_commit_roots_uptodate() must be called. 802462306a36Sopenharmony_ci */ 802562306a36Sopenharmony_cistatic int flush_delalloc_roots(struct send_ctx *sctx) 802662306a36Sopenharmony_ci{ 802762306a36Sopenharmony_ci struct btrfs_root *root = sctx->parent_root; 802862306a36Sopenharmony_ci int ret; 802962306a36Sopenharmony_ci int i; 803062306a36Sopenharmony_ci 803162306a36Sopenharmony_ci if (root) { 803262306a36Sopenharmony_ci ret = btrfs_start_delalloc_snapshot(root, false); 803362306a36Sopenharmony_ci if (ret) 803462306a36Sopenharmony_ci return ret; 803562306a36Sopenharmony_ci btrfs_wait_ordered_extents(root, U64_MAX, 0, U64_MAX); 803662306a36Sopenharmony_ci } 803762306a36Sopenharmony_ci 803862306a36Sopenharmony_ci for (i = 0; i < sctx->clone_roots_cnt; i++) { 803962306a36Sopenharmony_ci root = sctx->clone_roots[i].root; 804062306a36Sopenharmony_ci ret = btrfs_start_delalloc_snapshot(root, false); 804162306a36Sopenharmony_ci if (ret) 804262306a36Sopenharmony_ci return ret; 804362306a36Sopenharmony_ci btrfs_wait_ordered_extents(root, U64_MAX, 0, U64_MAX); 804462306a36Sopenharmony_ci } 804562306a36Sopenharmony_ci 804662306a36Sopenharmony_ci return 0; 804762306a36Sopenharmony_ci} 804862306a36Sopenharmony_ci 804962306a36Sopenharmony_cistatic void btrfs_root_dec_send_in_progress(struct btrfs_root* root) 805062306a36Sopenharmony_ci{ 805162306a36Sopenharmony_ci spin_lock(&root->root_item_lock); 805262306a36Sopenharmony_ci root->send_in_progress--; 805362306a36Sopenharmony_ci /* 805462306a36Sopenharmony_ci * Not much left to do, we don't know why it's unbalanced and 805562306a36Sopenharmony_ci * can't blindly reset it to 0. 805662306a36Sopenharmony_ci */ 805762306a36Sopenharmony_ci if (root->send_in_progress < 0) 805862306a36Sopenharmony_ci btrfs_err(root->fs_info, 805962306a36Sopenharmony_ci "send_in_progress unbalanced %d root %llu", 806062306a36Sopenharmony_ci root->send_in_progress, root->root_key.objectid); 806162306a36Sopenharmony_ci spin_unlock(&root->root_item_lock); 806262306a36Sopenharmony_ci} 806362306a36Sopenharmony_ci 806462306a36Sopenharmony_cistatic void dedupe_in_progress_warn(const struct btrfs_root *root) 806562306a36Sopenharmony_ci{ 806662306a36Sopenharmony_ci btrfs_warn_rl(root->fs_info, 806762306a36Sopenharmony_ci"cannot use root %llu for send while deduplications on it are in progress (%d in progress)", 806862306a36Sopenharmony_ci root->root_key.objectid, root->dedupe_in_progress); 806962306a36Sopenharmony_ci} 807062306a36Sopenharmony_ci 807162306a36Sopenharmony_cilong btrfs_ioctl_send(struct inode *inode, struct btrfs_ioctl_send_args *arg) 807262306a36Sopenharmony_ci{ 807362306a36Sopenharmony_ci int ret = 0; 807462306a36Sopenharmony_ci struct btrfs_root *send_root = BTRFS_I(inode)->root; 807562306a36Sopenharmony_ci struct btrfs_fs_info *fs_info = send_root->fs_info; 807662306a36Sopenharmony_ci struct btrfs_root *clone_root; 807762306a36Sopenharmony_ci struct send_ctx *sctx = NULL; 807862306a36Sopenharmony_ci u32 i; 807962306a36Sopenharmony_ci u64 *clone_sources_tmp = NULL; 808062306a36Sopenharmony_ci int clone_sources_to_rollback = 0; 808162306a36Sopenharmony_ci size_t alloc_size; 808262306a36Sopenharmony_ci int sort_clone_roots = 0; 808362306a36Sopenharmony_ci struct btrfs_lru_cache_entry *entry; 808462306a36Sopenharmony_ci struct btrfs_lru_cache_entry *tmp; 808562306a36Sopenharmony_ci 808662306a36Sopenharmony_ci if (!capable(CAP_SYS_ADMIN)) 808762306a36Sopenharmony_ci return -EPERM; 808862306a36Sopenharmony_ci 808962306a36Sopenharmony_ci /* 809062306a36Sopenharmony_ci * The subvolume must remain read-only during send, protect against 809162306a36Sopenharmony_ci * making it RW. This also protects against deletion. 809262306a36Sopenharmony_ci */ 809362306a36Sopenharmony_ci spin_lock(&send_root->root_item_lock); 809462306a36Sopenharmony_ci if (btrfs_root_readonly(send_root) && send_root->dedupe_in_progress) { 809562306a36Sopenharmony_ci dedupe_in_progress_warn(send_root); 809662306a36Sopenharmony_ci spin_unlock(&send_root->root_item_lock); 809762306a36Sopenharmony_ci return -EAGAIN; 809862306a36Sopenharmony_ci } 809962306a36Sopenharmony_ci send_root->send_in_progress++; 810062306a36Sopenharmony_ci spin_unlock(&send_root->root_item_lock); 810162306a36Sopenharmony_ci 810262306a36Sopenharmony_ci /* 810362306a36Sopenharmony_ci * Userspace tools do the checks and warn the user if it's 810462306a36Sopenharmony_ci * not RO. 810562306a36Sopenharmony_ci */ 810662306a36Sopenharmony_ci if (!btrfs_root_readonly(send_root)) { 810762306a36Sopenharmony_ci ret = -EPERM; 810862306a36Sopenharmony_ci goto out; 810962306a36Sopenharmony_ci } 811062306a36Sopenharmony_ci 811162306a36Sopenharmony_ci /* 811262306a36Sopenharmony_ci * Check that we don't overflow at later allocations, we request 811362306a36Sopenharmony_ci * clone_sources_count + 1 items, and compare to unsigned long inside 811462306a36Sopenharmony_ci * access_ok. Also set an upper limit for allocation size so this can't 811562306a36Sopenharmony_ci * easily exhaust memory. Max number of clone sources is about 200K. 811662306a36Sopenharmony_ci */ 811762306a36Sopenharmony_ci if (arg->clone_sources_count > SZ_8M / sizeof(struct clone_root)) { 811862306a36Sopenharmony_ci ret = -EINVAL; 811962306a36Sopenharmony_ci goto out; 812062306a36Sopenharmony_ci } 812162306a36Sopenharmony_ci 812262306a36Sopenharmony_ci if (arg->flags & ~BTRFS_SEND_FLAG_MASK) { 812362306a36Sopenharmony_ci ret = -EOPNOTSUPP; 812462306a36Sopenharmony_ci goto out; 812562306a36Sopenharmony_ci } 812662306a36Sopenharmony_ci 812762306a36Sopenharmony_ci sctx = kzalloc(sizeof(struct send_ctx), GFP_KERNEL); 812862306a36Sopenharmony_ci if (!sctx) { 812962306a36Sopenharmony_ci ret = -ENOMEM; 813062306a36Sopenharmony_ci goto out; 813162306a36Sopenharmony_ci } 813262306a36Sopenharmony_ci 813362306a36Sopenharmony_ci INIT_LIST_HEAD(&sctx->new_refs); 813462306a36Sopenharmony_ci INIT_LIST_HEAD(&sctx->deleted_refs); 813562306a36Sopenharmony_ci 813662306a36Sopenharmony_ci btrfs_lru_cache_init(&sctx->name_cache, SEND_MAX_NAME_CACHE_SIZE); 813762306a36Sopenharmony_ci btrfs_lru_cache_init(&sctx->backref_cache, SEND_MAX_BACKREF_CACHE_SIZE); 813862306a36Sopenharmony_ci btrfs_lru_cache_init(&sctx->dir_created_cache, 813962306a36Sopenharmony_ci SEND_MAX_DIR_CREATED_CACHE_SIZE); 814062306a36Sopenharmony_ci /* 814162306a36Sopenharmony_ci * This cache is periodically trimmed to a fixed size elsewhere, see 814262306a36Sopenharmony_ci * cache_dir_utimes() and trim_dir_utimes_cache(). 814362306a36Sopenharmony_ci */ 814462306a36Sopenharmony_ci btrfs_lru_cache_init(&sctx->dir_utimes_cache, 0); 814562306a36Sopenharmony_ci 814662306a36Sopenharmony_ci sctx->pending_dir_moves = RB_ROOT; 814762306a36Sopenharmony_ci sctx->waiting_dir_moves = RB_ROOT; 814862306a36Sopenharmony_ci sctx->orphan_dirs = RB_ROOT; 814962306a36Sopenharmony_ci sctx->rbtree_new_refs = RB_ROOT; 815062306a36Sopenharmony_ci sctx->rbtree_deleted_refs = RB_ROOT; 815162306a36Sopenharmony_ci 815262306a36Sopenharmony_ci sctx->flags = arg->flags; 815362306a36Sopenharmony_ci 815462306a36Sopenharmony_ci if (arg->flags & BTRFS_SEND_FLAG_VERSION) { 815562306a36Sopenharmony_ci if (arg->version > BTRFS_SEND_STREAM_VERSION) { 815662306a36Sopenharmony_ci ret = -EPROTO; 815762306a36Sopenharmony_ci goto out; 815862306a36Sopenharmony_ci } 815962306a36Sopenharmony_ci /* Zero means "use the highest version" */ 816062306a36Sopenharmony_ci sctx->proto = arg->version ?: BTRFS_SEND_STREAM_VERSION; 816162306a36Sopenharmony_ci } else { 816262306a36Sopenharmony_ci sctx->proto = 1; 816362306a36Sopenharmony_ci } 816462306a36Sopenharmony_ci if ((arg->flags & BTRFS_SEND_FLAG_COMPRESSED) && sctx->proto < 2) { 816562306a36Sopenharmony_ci ret = -EINVAL; 816662306a36Sopenharmony_ci goto out; 816762306a36Sopenharmony_ci } 816862306a36Sopenharmony_ci 816962306a36Sopenharmony_ci sctx->send_filp = fget(arg->send_fd); 817062306a36Sopenharmony_ci if (!sctx->send_filp || !(sctx->send_filp->f_mode & FMODE_WRITE)) { 817162306a36Sopenharmony_ci ret = -EBADF; 817262306a36Sopenharmony_ci goto out; 817362306a36Sopenharmony_ci } 817462306a36Sopenharmony_ci 817562306a36Sopenharmony_ci sctx->send_root = send_root; 817662306a36Sopenharmony_ci /* 817762306a36Sopenharmony_ci * Unlikely but possible, if the subvolume is marked for deletion but 817862306a36Sopenharmony_ci * is slow to remove the directory entry, send can still be started 817962306a36Sopenharmony_ci */ 818062306a36Sopenharmony_ci if (btrfs_root_dead(sctx->send_root)) { 818162306a36Sopenharmony_ci ret = -EPERM; 818262306a36Sopenharmony_ci goto out; 818362306a36Sopenharmony_ci } 818462306a36Sopenharmony_ci 818562306a36Sopenharmony_ci sctx->clone_roots_cnt = arg->clone_sources_count; 818662306a36Sopenharmony_ci 818762306a36Sopenharmony_ci if (sctx->proto >= 2) { 818862306a36Sopenharmony_ci u32 send_buf_num_pages; 818962306a36Sopenharmony_ci 819062306a36Sopenharmony_ci sctx->send_max_size = BTRFS_SEND_BUF_SIZE_V2; 819162306a36Sopenharmony_ci sctx->send_buf = vmalloc(sctx->send_max_size); 819262306a36Sopenharmony_ci if (!sctx->send_buf) { 819362306a36Sopenharmony_ci ret = -ENOMEM; 819462306a36Sopenharmony_ci goto out; 819562306a36Sopenharmony_ci } 819662306a36Sopenharmony_ci send_buf_num_pages = sctx->send_max_size >> PAGE_SHIFT; 819762306a36Sopenharmony_ci sctx->send_buf_pages = kcalloc(send_buf_num_pages, 819862306a36Sopenharmony_ci sizeof(*sctx->send_buf_pages), 819962306a36Sopenharmony_ci GFP_KERNEL); 820062306a36Sopenharmony_ci if (!sctx->send_buf_pages) { 820162306a36Sopenharmony_ci ret = -ENOMEM; 820262306a36Sopenharmony_ci goto out; 820362306a36Sopenharmony_ci } 820462306a36Sopenharmony_ci for (i = 0; i < send_buf_num_pages; i++) { 820562306a36Sopenharmony_ci sctx->send_buf_pages[i] = 820662306a36Sopenharmony_ci vmalloc_to_page(sctx->send_buf + (i << PAGE_SHIFT)); 820762306a36Sopenharmony_ci } 820862306a36Sopenharmony_ci } else { 820962306a36Sopenharmony_ci sctx->send_max_size = BTRFS_SEND_BUF_SIZE_V1; 821062306a36Sopenharmony_ci sctx->send_buf = kvmalloc(sctx->send_max_size, GFP_KERNEL); 821162306a36Sopenharmony_ci } 821262306a36Sopenharmony_ci if (!sctx->send_buf) { 821362306a36Sopenharmony_ci ret = -ENOMEM; 821462306a36Sopenharmony_ci goto out; 821562306a36Sopenharmony_ci } 821662306a36Sopenharmony_ci 821762306a36Sopenharmony_ci sctx->clone_roots = kvcalloc(sizeof(*sctx->clone_roots), 821862306a36Sopenharmony_ci arg->clone_sources_count + 1, 821962306a36Sopenharmony_ci GFP_KERNEL); 822062306a36Sopenharmony_ci if (!sctx->clone_roots) { 822162306a36Sopenharmony_ci ret = -ENOMEM; 822262306a36Sopenharmony_ci goto out; 822362306a36Sopenharmony_ci } 822462306a36Sopenharmony_ci 822562306a36Sopenharmony_ci alloc_size = array_size(sizeof(*arg->clone_sources), 822662306a36Sopenharmony_ci arg->clone_sources_count); 822762306a36Sopenharmony_ci 822862306a36Sopenharmony_ci if (arg->clone_sources_count) { 822962306a36Sopenharmony_ci clone_sources_tmp = kvmalloc(alloc_size, GFP_KERNEL); 823062306a36Sopenharmony_ci if (!clone_sources_tmp) { 823162306a36Sopenharmony_ci ret = -ENOMEM; 823262306a36Sopenharmony_ci goto out; 823362306a36Sopenharmony_ci } 823462306a36Sopenharmony_ci 823562306a36Sopenharmony_ci ret = copy_from_user(clone_sources_tmp, arg->clone_sources, 823662306a36Sopenharmony_ci alloc_size); 823762306a36Sopenharmony_ci if (ret) { 823862306a36Sopenharmony_ci ret = -EFAULT; 823962306a36Sopenharmony_ci goto out; 824062306a36Sopenharmony_ci } 824162306a36Sopenharmony_ci 824262306a36Sopenharmony_ci for (i = 0; i < arg->clone_sources_count; i++) { 824362306a36Sopenharmony_ci clone_root = btrfs_get_fs_root(fs_info, 824462306a36Sopenharmony_ci clone_sources_tmp[i], true); 824562306a36Sopenharmony_ci if (IS_ERR(clone_root)) { 824662306a36Sopenharmony_ci ret = PTR_ERR(clone_root); 824762306a36Sopenharmony_ci goto out; 824862306a36Sopenharmony_ci } 824962306a36Sopenharmony_ci spin_lock(&clone_root->root_item_lock); 825062306a36Sopenharmony_ci if (!btrfs_root_readonly(clone_root) || 825162306a36Sopenharmony_ci btrfs_root_dead(clone_root)) { 825262306a36Sopenharmony_ci spin_unlock(&clone_root->root_item_lock); 825362306a36Sopenharmony_ci btrfs_put_root(clone_root); 825462306a36Sopenharmony_ci ret = -EPERM; 825562306a36Sopenharmony_ci goto out; 825662306a36Sopenharmony_ci } 825762306a36Sopenharmony_ci if (clone_root->dedupe_in_progress) { 825862306a36Sopenharmony_ci dedupe_in_progress_warn(clone_root); 825962306a36Sopenharmony_ci spin_unlock(&clone_root->root_item_lock); 826062306a36Sopenharmony_ci btrfs_put_root(clone_root); 826162306a36Sopenharmony_ci ret = -EAGAIN; 826262306a36Sopenharmony_ci goto out; 826362306a36Sopenharmony_ci } 826462306a36Sopenharmony_ci clone_root->send_in_progress++; 826562306a36Sopenharmony_ci spin_unlock(&clone_root->root_item_lock); 826662306a36Sopenharmony_ci 826762306a36Sopenharmony_ci sctx->clone_roots[i].root = clone_root; 826862306a36Sopenharmony_ci clone_sources_to_rollback = i + 1; 826962306a36Sopenharmony_ci } 827062306a36Sopenharmony_ci kvfree(clone_sources_tmp); 827162306a36Sopenharmony_ci clone_sources_tmp = NULL; 827262306a36Sopenharmony_ci } 827362306a36Sopenharmony_ci 827462306a36Sopenharmony_ci if (arg->parent_root) { 827562306a36Sopenharmony_ci sctx->parent_root = btrfs_get_fs_root(fs_info, arg->parent_root, 827662306a36Sopenharmony_ci true); 827762306a36Sopenharmony_ci if (IS_ERR(sctx->parent_root)) { 827862306a36Sopenharmony_ci ret = PTR_ERR(sctx->parent_root); 827962306a36Sopenharmony_ci goto out; 828062306a36Sopenharmony_ci } 828162306a36Sopenharmony_ci 828262306a36Sopenharmony_ci spin_lock(&sctx->parent_root->root_item_lock); 828362306a36Sopenharmony_ci sctx->parent_root->send_in_progress++; 828462306a36Sopenharmony_ci if (!btrfs_root_readonly(sctx->parent_root) || 828562306a36Sopenharmony_ci btrfs_root_dead(sctx->parent_root)) { 828662306a36Sopenharmony_ci spin_unlock(&sctx->parent_root->root_item_lock); 828762306a36Sopenharmony_ci ret = -EPERM; 828862306a36Sopenharmony_ci goto out; 828962306a36Sopenharmony_ci } 829062306a36Sopenharmony_ci if (sctx->parent_root->dedupe_in_progress) { 829162306a36Sopenharmony_ci dedupe_in_progress_warn(sctx->parent_root); 829262306a36Sopenharmony_ci spin_unlock(&sctx->parent_root->root_item_lock); 829362306a36Sopenharmony_ci ret = -EAGAIN; 829462306a36Sopenharmony_ci goto out; 829562306a36Sopenharmony_ci } 829662306a36Sopenharmony_ci spin_unlock(&sctx->parent_root->root_item_lock); 829762306a36Sopenharmony_ci } 829862306a36Sopenharmony_ci 829962306a36Sopenharmony_ci /* 830062306a36Sopenharmony_ci * Clones from send_root are allowed, but only if the clone source 830162306a36Sopenharmony_ci * is behind the current send position. This is checked while searching 830262306a36Sopenharmony_ci * for possible clone sources. 830362306a36Sopenharmony_ci */ 830462306a36Sopenharmony_ci sctx->clone_roots[sctx->clone_roots_cnt++].root = 830562306a36Sopenharmony_ci btrfs_grab_root(sctx->send_root); 830662306a36Sopenharmony_ci 830762306a36Sopenharmony_ci /* We do a bsearch later */ 830862306a36Sopenharmony_ci sort(sctx->clone_roots, sctx->clone_roots_cnt, 830962306a36Sopenharmony_ci sizeof(*sctx->clone_roots), __clone_root_cmp_sort, 831062306a36Sopenharmony_ci NULL); 831162306a36Sopenharmony_ci sort_clone_roots = 1; 831262306a36Sopenharmony_ci 831362306a36Sopenharmony_ci ret = flush_delalloc_roots(sctx); 831462306a36Sopenharmony_ci if (ret) 831562306a36Sopenharmony_ci goto out; 831662306a36Sopenharmony_ci 831762306a36Sopenharmony_ci ret = ensure_commit_roots_uptodate(sctx); 831862306a36Sopenharmony_ci if (ret) 831962306a36Sopenharmony_ci goto out; 832062306a36Sopenharmony_ci 832162306a36Sopenharmony_ci ret = send_subvol(sctx); 832262306a36Sopenharmony_ci if (ret < 0) 832362306a36Sopenharmony_ci goto out; 832462306a36Sopenharmony_ci 832562306a36Sopenharmony_ci btrfs_lru_cache_for_each_entry_safe(&sctx->dir_utimes_cache, entry, tmp) { 832662306a36Sopenharmony_ci ret = send_utimes(sctx, entry->key, entry->gen); 832762306a36Sopenharmony_ci if (ret < 0) 832862306a36Sopenharmony_ci goto out; 832962306a36Sopenharmony_ci btrfs_lru_cache_remove(&sctx->dir_utimes_cache, entry); 833062306a36Sopenharmony_ci } 833162306a36Sopenharmony_ci 833262306a36Sopenharmony_ci if (!(sctx->flags & BTRFS_SEND_FLAG_OMIT_END_CMD)) { 833362306a36Sopenharmony_ci ret = begin_cmd(sctx, BTRFS_SEND_C_END); 833462306a36Sopenharmony_ci if (ret < 0) 833562306a36Sopenharmony_ci goto out; 833662306a36Sopenharmony_ci ret = send_cmd(sctx); 833762306a36Sopenharmony_ci if (ret < 0) 833862306a36Sopenharmony_ci goto out; 833962306a36Sopenharmony_ci } 834062306a36Sopenharmony_ci 834162306a36Sopenharmony_ciout: 834262306a36Sopenharmony_ci WARN_ON(sctx && !ret && !RB_EMPTY_ROOT(&sctx->pending_dir_moves)); 834362306a36Sopenharmony_ci while (sctx && !RB_EMPTY_ROOT(&sctx->pending_dir_moves)) { 834462306a36Sopenharmony_ci struct rb_node *n; 834562306a36Sopenharmony_ci struct pending_dir_move *pm; 834662306a36Sopenharmony_ci 834762306a36Sopenharmony_ci n = rb_first(&sctx->pending_dir_moves); 834862306a36Sopenharmony_ci pm = rb_entry(n, struct pending_dir_move, node); 834962306a36Sopenharmony_ci while (!list_empty(&pm->list)) { 835062306a36Sopenharmony_ci struct pending_dir_move *pm2; 835162306a36Sopenharmony_ci 835262306a36Sopenharmony_ci pm2 = list_first_entry(&pm->list, 835362306a36Sopenharmony_ci struct pending_dir_move, list); 835462306a36Sopenharmony_ci free_pending_move(sctx, pm2); 835562306a36Sopenharmony_ci } 835662306a36Sopenharmony_ci free_pending_move(sctx, pm); 835762306a36Sopenharmony_ci } 835862306a36Sopenharmony_ci 835962306a36Sopenharmony_ci WARN_ON(sctx && !ret && !RB_EMPTY_ROOT(&sctx->waiting_dir_moves)); 836062306a36Sopenharmony_ci while (sctx && !RB_EMPTY_ROOT(&sctx->waiting_dir_moves)) { 836162306a36Sopenharmony_ci struct rb_node *n; 836262306a36Sopenharmony_ci struct waiting_dir_move *dm; 836362306a36Sopenharmony_ci 836462306a36Sopenharmony_ci n = rb_first(&sctx->waiting_dir_moves); 836562306a36Sopenharmony_ci dm = rb_entry(n, struct waiting_dir_move, node); 836662306a36Sopenharmony_ci rb_erase(&dm->node, &sctx->waiting_dir_moves); 836762306a36Sopenharmony_ci kfree(dm); 836862306a36Sopenharmony_ci } 836962306a36Sopenharmony_ci 837062306a36Sopenharmony_ci WARN_ON(sctx && !ret && !RB_EMPTY_ROOT(&sctx->orphan_dirs)); 837162306a36Sopenharmony_ci while (sctx && !RB_EMPTY_ROOT(&sctx->orphan_dirs)) { 837262306a36Sopenharmony_ci struct rb_node *n; 837362306a36Sopenharmony_ci struct orphan_dir_info *odi; 837462306a36Sopenharmony_ci 837562306a36Sopenharmony_ci n = rb_first(&sctx->orphan_dirs); 837662306a36Sopenharmony_ci odi = rb_entry(n, struct orphan_dir_info, node); 837762306a36Sopenharmony_ci free_orphan_dir_info(sctx, odi); 837862306a36Sopenharmony_ci } 837962306a36Sopenharmony_ci 838062306a36Sopenharmony_ci if (sort_clone_roots) { 838162306a36Sopenharmony_ci for (i = 0; i < sctx->clone_roots_cnt; i++) { 838262306a36Sopenharmony_ci btrfs_root_dec_send_in_progress( 838362306a36Sopenharmony_ci sctx->clone_roots[i].root); 838462306a36Sopenharmony_ci btrfs_put_root(sctx->clone_roots[i].root); 838562306a36Sopenharmony_ci } 838662306a36Sopenharmony_ci } else { 838762306a36Sopenharmony_ci for (i = 0; sctx && i < clone_sources_to_rollback; i++) { 838862306a36Sopenharmony_ci btrfs_root_dec_send_in_progress( 838962306a36Sopenharmony_ci sctx->clone_roots[i].root); 839062306a36Sopenharmony_ci btrfs_put_root(sctx->clone_roots[i].root); 839162306a36Sopenharmony_ci } 839262306a36Sopenharmony_ci 839362306a36Sopenharmony_ci btrfs_root_dec_send_in_progress(send_root); 839462306a36Sopenharmony_ci } 839562306a36Sopenharmony_ci if (sctx && !IS_ERR_OR_NULL(sctx->parent_root)) { 839662306a36Sopenharmony_ci btrfs_root_dec_send_in_progress(sctx->parent_root); 839762306a36Sopenharmony_ci btrfs_put_root(sctx->parent_root); 839862306a36Sopenharmony_ci } 839962306a36Sopenharmony_ci 840062306a36Sopenharmony_ci kvfree(clone_sources_tmp); 840162306a36Sopenharmony_ci 840262306a36Sopenharmony_ci if (sctx) { 840362306a36Sopenharmony_ci if (sctx->send_filp) 840462306a36Sopenharmony_ci fput(sctx->send_filp); 840562306a36Sopenharmony_ci 840662306a36Sopenharmony_ci kvfree(sctx->clone_roots); 840762306a36Sopenharmony_ci kfree(sctx->send_buf_pages); 840862306a36Sopenharmony_ci kvfree(sctx->send_buf); 840962306a36Sopenharmony_ci kvfree(sctx->verity_descriptor); 841062306a36Sopenharmony_ci 841162306a36Sopenharmony_ci close_current_inode(sctx); 841262306a36Sopenharmony_ci 841362306a36Sopenharmony_ci btrfs_lru_cache_clear(&sctx->name_cache); 841462306a36Sopenharmony_ci btrfs_lru_cache_clear(&sctx->backref_cache); 841562306a36Sopenharmony_ci btrfs_lru_cache_clear(&sctx->dir_created_cache); 841662306a36Sopenharmony_ci btrfs_lru_cache_clear(&sctx->dir_utimes_cache); 841762306a36Sopenharmony_ci 841862306a36Sopenharmony_ci kfree(sctx); 841962306a36Sopenharmony_ci } 842062306a36Sopenharmony_ci 842162306a36Sopenharmony_ci return ret; 842262306a36Sopenharmony_ci} 8423