diff options
author | Alexander Block <ablock84@googlemail.com> | 2012-07-28 08:11:31 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@fusionio.com> | 2012-10-01 15:18:54 -0400 |
commit | 766702ef49b8b5299d819f3a0ac42613c23424d1 (patch) | |
tree | bcfd79b83b5732fc942487710ceca8c4a50b3b6d /fs/btrfs/send.c | |
parent | e479d9bb5f8366a064915b3c9ac47ed6e9fcc7d3 (diff) |
Btrfs: add/fix comments/documentation for send/receive
As the subject already said, add/fix comments.
Signed-off-by: Alexander Block <ablock84@googlemail.com>
Diffstat (limited to 'fs/btrfs/send.c')
-rw-r--r-- | fs/btrfs/send.c | 140 |
1 files changed, 134 insertions, 6 deletions
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index f618224d2326..6926546939f6 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c | |||
@@ -1067,6 +1067,7 @@ static int __clone_root_cmp_sort(const void *e1, const void *e2) | |||
1067 | 1067 | ||
1068 | /* | 1068 | /* |
1069 | * Called for every backref that is found for the current extent. | 1069 | * Called for every backref that is found for the current extent. |
1070 | * Results are collected in sctx->clone_roots->ino/offset/found_refs | ||
1070 | */ | 1071 | */ |
1071 | static int __iterate_backrefs(u64 ino, u64 offset, u64 root, void *ctx_) | 1072 | static int __iterate_backrefs(u64 ino, u64 offset, u64 root, void *ctx_) |
1072 | { | 1073 | { |
@@ -1090,7 +1091,7 @@ static int __iterate_backrefs(u64 ino, u64 offset, u64 root, void *ctx_) | |||
1090 | } | 1091 | } |
1091 | 1092 | ||
1092 | /* | 1093 | /* |
1093 | * There are inodes that have extents that lie behind it's i_size. Don't | 1094 | * There are inodes that have extents that lie behind its i_size. Don't |
1094 | * accept clones from these extents. | 1095 | * accept clones from these extents. |
1095 | */ | 1096 | */ |
1096 | ret = get_inode_info(found->root, ino, &i_size, NULL, NULL, NULL, NULL, | 1097 | ret = get_inode_info(found->root, ino, &i_size, NULL, NULL, NULL, NULL, |
@@ -1137,6 +1138,12 @@ static int __iterate_backrefs(u64 ino, u64 offset, u64 root, void *ctx_) | |||
1137 | } | 1138 | } |
1138 | 1139 | ||
1139 | /* | 1140 | /* |
1141 | * Given an inode, offset and extent item, it finds a good clone for a clone | ||
1142 | * instruction. Returns -ENOENT when none could be found. The function makes | ||
1143 | * sure that the returned clone is usable at the point where sending is at the | ||
1144 | * moment. This means, that no clones are accepted which lie behind the current | ||
1145 | * inode+offset. | ||
1146 | * | ||
1140 | * path must point to the extent item when called. | 1147 | * path must point to the extent item when called. |
1141 | */ | 1148 | */ |
1142 | static int find_extent_clone(struct send_ctx *sctx, | 1149 | static int find_extent_clone(struct send_ctx *sctx, |
@@ -1529,6 +1536,10 @@ out: | |||
1529 | return ret; | 1536 | return ret; |
1530 | } | 1537 | } |
1531 | 1538 | ||
1539 | /* | ||
1540 | * Looks up the first btrfs_inode_ref of a given ino. It returns the parent dir, | ||
1541 | * generation of the parent dir and the name of the dir entry. | ||
1542 | */ | ||
1532 | static int get_first_ref(struct send_ctx *sctx, | 1543 | static int get_first_ref(struct send_ctx *sctx, |
1533 | struct btrfs_root *root, u64 ino, | 1544 | struct btrfs_root *root, u64 ino, |
1534 | u64 *dir, u64 *dir_gen, struct fs_path *name) | 1545 | u64 *dir, u64 *dir_gen, struct fs_path *name) |
@@ -1615,6 +1626,16 @@ out: | |||
1615 | return ret; | 1626 | return ret; |
1616 | } | 1627 | } |
1617 | 1628 | ||
1629 | /* | ||
1630 | * Used by process_recorded_refs to determine if a new ref would overwrite an | ||
1631 | * already existing ref. In case it detects an overwrite, it returns the | ||
1632 | * inode/gen in who_ino/who_gen. | ||
1633 | * When an overwrite is detected, process_recorded_refs does proper orphanizing | ||
1634 | * to make sure later references to the overwritten inode are possible. | ||
1635 | * Orphanizing is however only required for the first ref of an inode. | ||
1636 | * process_recorded_refs does an additional is_first_ref check to see if | ||
1637 | * orphanizing is really required. | ||
1638 | */ | ||
1618 | static int will_overwrite_ref(struct send_ctx *sctx, u64 dir, u64 dir_gen, | 1639 | static int will_overwrite_ref(struct send_ctx *sctx, u64 dir, u64 dir_gen, |
1619 | const char *name, int name_len, | 1640 | const char *name, int name_len, |
1620 | u64 *who_ino, u64 *who_gen) | 1641 | u64 *who_ino, u64 *who_gen) |
@@ -1639,6 +1660,11 @@ static int will_overwrite_ref(struct send_ctx *sctx, u64 dir, u64 dir_gen, | |||
1639 | goto out; | 1660 | goto out; |
1640 | } | 1661 | } |
1641 | 1662 | ||
1663 | /* | ||
1664 | * Check if the overwritten ref was already processed. If yes, the ref | ||
1665 | * was already unlinked/moved, so we can safely assume that we will not | ||
1666 | * overwrite anything at this point in time. | ||
1667 | */ | ||
1642 | if (other_inode > sctx->send_progress) { | 1668 | if (other_inode > sctx->send_progress) { |
1643 | ret = get_inode_info(sctx->parent_root, other_inode, NULL, | 1669 | ret = get_inode_info(sctx->parent_root, other_inode, NULL, |
1644 | who_gen, NULL, NULL, NULL, NULL); | 1670 | who_gen, NULL, NULL, NULL, NULL); |
@@ -1655,6 +1681,13 @@ out: | |||
1655 | return ret; | 1681 | return ret; |
1656 | } | 1682 | } |
1657 | 1683 | ||
1684 | /* | ||
1685 | * Checks if the ref was overwritten by an already processed inode. This is | ||
1686 | * used by __get_cur_name_and_parent to find out if the ref was orphanized and | ||
1687 | * thus the orphan name needs be used. | ||
1688 | * process_recorded_refs also uses it to avoid unlinking of refs that were | ||
1689 | * overwritten. | ||
1690 | */ | ||
1658 | static int did_overwrite_ref(struct send_ctx *sctx, | 1691 | static int did_overwrite_ref(struct send_ctx *sctx, |
1659 | u64 dir, u64 dir_gen, | 1692 | u64 dir, u64 dir_gen, |
1660 | u64 ino, u64 ino_gen, | 1693 | u64 ino, u64 ino_gen, |
@@ -1703,6 +1736,11 @@ out: | |||
1703 | return ret; | 1736 | return ret; |
1704 | } | 1737 | } |
1705 | 1738 | ||
1739 | /* | ||
1740 | * Same as did_overwrite_ref, but also checks if it is the first ref of an inode | ||
1741 | * that got overwritten. This is used by process_recorded_refs to determine | ||
1742 | * if it has to use the path as returned by get_cur_path or the orphan name. | ||
1743 | */ | ||
1706 | static int did_overwrite_first_ref(struct send_ctx *sctx, u64 ino, u64 gen) | 1744 | static int did_overwrite_first_ref(struct send_ctx *sctx, u64 ino, u64 gen) |
1707 | { | 1745 | { |
1708 | int ret = 0; | 1746 | int ret = 0; |
@@ -1731,6 +1769,11 @@ out: | |||
1731 | return ret; | 1769 | return ret; |
1732 | } | 1770 | } |
1733 | 1771 | ||
1772 | /* | ||
1773 | * Insert a name cache entry. On 32bit kernels the radix tree index is 32bit, | ||
1774 | * so we need to do some special handling in case we have clashes. This function | ||
1775 | * takes care of this with the help of name_cache_entry::radix_list. | ||
1776 | */ | ||
1734 | static int name_cache_insert(struct send_ctx *sctx, | 1777 | static int name_cache_insert(struct send_ctx *sctx, |
1735 | struct name_cache_entry *nce) | 1778 | struct name_cache_entry *nce) |
1736 | { | 1779 | { |
@@ -1792,12 +1835,19 @@ static struct name_cache_entry *name_cache_search(struct send_ctx *sctx, | |||
1792 | return NULL; | 1835 | return NULL; |
1793 | } | 1836 | } |
1794 | 1837 | ||
1838 | /* | ||
1839 | * Removes the entry from the list and adds it back to the end. This marks the | ||
1840 | * entry as recently used so that name_cache_clean_unused does not remove it. | ||
1841 | */ | ||
1795 | static void name_cache_used(struct send_ctx *sctx, struct name_cache_entry *nce) | 1842 | static void name_cache_used(struct send_ctx *sctx, struct name_cache_entry *nce) |
1796 | { | 1843 | { |
1797 | list_del(&nce->list); | 1844 | list_del(&nce->list); |
1798 | list_add_tail(&nce->list, &sctx->name_cache_list); | 1845 | list_add_tail(&nce->list, &sctx->name_cache_list); |
1799 | } | 1846 | } |
1800 | 1847 | ||
1848 | /* | ||
1849 | * Remove some entries from the beginning of name_cache_list. | ||
1850 | */ | ||
1801 | static void name_cache_clean_unused(struct send_ctx *sctx) | 1851 | static void name_cache_clean_unused(struct send_ctx *sctx) |
1802 | { | 1852 | { |
1803 | struct name_cache_entry *nce; | 1853 | struct name_cache_entry *nce; |
@@ -1824,6 +1874,14 @@ static void name_cache_free(struct send_ctx *sctx) | |||
1824 | } | 1874 | } |
1825 | } | 1875 | } |
1826 | 1876 | ||
1877 | /* | ||
1878 | * Used by get_cur_path for each ref up to the root. | ||
1879 | * Returns 0 if it succeeded. | ||
1880 | * Returns 1 if the inode is not existent or got overwritten. In that case, the | ||
1881 | * name is an orphan name. This instructs get_cur_path to stop iterating. If 1 | ||
1882 | * is returned, parent_ino/parent_gen are not guaranteed to be valid. | ||
1883 | * Returns <0 in case of error. | ||
1884 | */ | ||
1827 | static int __get_cur_name_and_parent(struct send_ctx *sctx, | 1885 | static int __get_cur_name_and_parent(struct send_ctx *sctx, |
1828 | u64 ino, u64 gen, | 1886 | u64 ino, u64 gen, |
1829 | u64 *parent_ino, | 1887 | u64 *parent_ino, |
@@ -1835,6 +1893,11 @@ static int __get_cur_name_and_parent(struct send_ctx *sctx, | |||
1835 | struct btrfs_path *path = NULL; | 1893 | struct btrfs_path *path = NULL; |
1836 | struct name_cache_entry *nce = NULL; | 1894 | struct name_cache_entry *nce = NULL; |
1837 | 1895 | ||
1896 | /* | ||
1897 | * First check if we already did a call to this function with the same | ||
1898 | * ino/gen. If yes, check if the cache entry is still up-to-date. If yes | ||
1899 | * return the cached result. | ||
1900 | */ | ||
1838 | nce = name_cache_search(sctx, ino, gen); | 1901 | nce = name_cache_search(sctx, ino, gen); |
1839 | if (nce) { | 1902 | if (nce) { |
1840 | if (ino < sctx->send_progress && nce->need_later_update) { | 1903 | if (ino < sctx->send_progress && nce->need_later_update) { |
@@ -1857,6 +1920,11 @@ static int __get_cur_name_and_parent(struct send_ctx *sctx, | |||
1857 | if (!path) | 1920 | if (!path) |
1858 | return -ENOMEM; | 1921 | return -ENOMEM; |
1859 | 1922 | ||
1923 | /* | ||
1924 | * If the inode is not existent yet, add the orphan name and return 1. | ||
1925 | * This should only happen for the parent dir that we determine in | ||
1926 | * __record_new_ref | ||
1927 | */ | ||
1860 | ret = is_inode_existent(sctx, ino, gen); | 1928 | ret = is_inode_existent(sctx, ino, gen); |
1861 | if (ret < 0) | 1929 | if (ret < 0) |
1862 | goto out; | 1930 | goto out; |
@@ -1869,6 +1937,10 @@ static int __get_cur_name_and_parent(struct send_ctx *sctx, | |||
1869 | goto out_cache; | 1937 | goto out_cache; |
1870 | } | 1938 | } |
1871 | 1939 | ||
1940 | /* | ||
1941 | * Depending on whether the inode was already processed or not, use | ||
1942 | * send_root or parent_root for ref lookup. | ||
1943 | */ | ||
1872 | if (ino < sctx->send_progress) | 1944 | if (ino < sctx->send_progress) |
1873 | ret = get_first_ref(sctx, sctx->send_root, ino, | 1945 | ret = get_first_ref(sctx, sctx->send_root, ino, |
1874 | parent_ino, parent_gen, dest); | 1946 | parent_ino, parent_gen, dest); |
@@ -1878,6 +1950,10 @@ static int __get_cur_name_and_parent(struct send_ctx *sctx, | |||
1878 | if (ret < 0) | 1950 | if (ret < 0) |
1879 | goto out; | 1951 | goto out; |
1880 | 1952 | ||
1953 | /* | ||
1954 | * Check if the ref was overwritten by an inode's ref that was processed | ||
1955 | * earlier. If yes, treat as orphan and return 1. | ||
1956 | */ | ||
1881 | ret = did_overwrite_ref(sctx, *parent_ino, *parent_gen, ino, gen, | 1957 | ret = did_overwrite_ref(sctx, *parent_ino, *parent_gen, ino, gen, |
1882 | dest->start, dest->end - dest->start); | 1958 | dest->start, dest->end - dest->start); |
1883 | if (ret < 0) | 1959 | if (ret < 0) |
@@ -1891,6 +1967,9 @@ static int __get_cur_name_and_parent(struct send_ctx *sctx, | |||
1891 | } | 1967 | } |
1892 | 1968 | ||
1893 | out_cache: | 1969 | out_cache: |
1970 | /* | ||
1971 | * Store the result of the lookup in the name cache. | ||
1972 | */ | ||
1894 | nce = kmalloc(sizeof(*nce) + fs_path_len(dest) + 1, GFP_NOFS); | 1973 | nce = kmalloc(sizeof(*nce) + fs_path_len(dest) + 1, GFP_NOFS); |
1895 | if (!nce) { | 1974 | if (!nce) { |
1896 | ret = -ENOMEM; | 1975 | ret = -ENOMEM; |
@@ -2278,7 +2357,7 @@ verbose_printk("btrfs: send_utimes %llu\n", ino); | |||
2278 | btrfs_inode_mtime(ii)); | 2357 | btrfs_inode_mtime(ii)); |
2279 | TLV_PUT_BTRFS_TIMESPEC(sctx, BTRFS_SEND_A_CTIME, eb, | 2358 | TLV_PUT_BTRFS_TIMESPEC(sctx, BTRFS_SEND_A_CTIME, eb, |
2280 | btrfs_inode_ctime(ii)); | 2359 | btrfs_inode_ctime(ii)); |
2281 | /* TODO otime? */ | 2360 | /* TODO Add otime support when the otime patches get into upstream */ |
2282 | 2361 | ||
2283 | ret = send_cmd(sctx); | 2362 | ret = send_cmd(sctx); |
2284 | 2363 | ||
@@ -2520,7 +2599,7 @@ static void free_recorded_refs(struct send_ctx *sctx) | |||
2520 | } | 2599 | } |
2521 | 2600 | ||
2522 | /* | 2601 | /* |
2523 | * Renames/moves a file/dir to it's orphan name. Used when the first | 2602 | * Renames/moves a file/dir to its orphan name. Used when the first |
2524 | * ref of an unprocessed inode gets overwritten and for all non empty | 2603 | * ref of an unprocessed inode gets overwritten and for all non empty |
2525 | * directories. | 2604 | * directories. |
2526 | */ | 2605 | */ |
@@ -2840,7 +2919,9 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino); | |||
2840 | * If the inode is still orphan, unlink the orphan. This may | 2919 | * If the inode is still orphan, unlink the orphan. This may |
2841 | * happen when a previous inode did overwrite the first ref | 2920 | * happen when a previous inode did overwrite the first ref |
2842 | * of this inode and no new refs were added for the current | 2921 | * of this inode and no new refs were added for the current |
2843 | * inode. | 2922 | * inode. Unlinking does not mean that the inode is deleted in |
2923 | * all cases. There may still be links to this inode in other | ||
2924 | * places. | ||
2844 | */ | 2925 | */ |
2845 | if (is_orphan) { | 2926 | if (is_orphan) { |
2846 | ret = send_unlink(sctx, valid_path); | 2927 | ret = send_unlink(sctx, valid_path); |
@@ -2857,6 +2938,11 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino); | |||
2857 | */ | 2938 | */ |
2858 | ULIST_ITER_INIT(&uit); | 2939 | ULIST_ITER_INIT(&uit); |
2859 | while ((un = ulist_next(check_dirs, &uit))) { | 2940 | while ((un = ulist_next(check_dirs, &uit))) { |
2941 | /* | ||
2942 | * In case we had refs into dirs that were not processed yet, | ||
2943 | * we don't need to do the utime and rmdir logic for these dirs. | ||
2944 | * The dir will be processed later. | ||
2945 | */ | ||
2860 | if (un->val > sctx->cur_ino) | 2946 | if (un->val > sctx->cur_ino) |
2861 | continue; | 2947 | continue; |
2862 | 2948 | ||
@@ -4048,7 +4134,17 @@ static int changed_inode(struct send_ctx *sctx, | |||
4048 | sctx->cur_inode_mode = btrfs_inode_mode( | 4134 | sctx->cur_inode_mode = btrfs_inode_mode( |
4049 | sctx->right_path->nodes[0], right_ii); | 4135 | sctx->right_path->nodes[0], right_ii); |
4050 | } else if (result == BTRFS_COMPARE_TREE_CHANGED) { | 4136 | } else if (result == BTRFS_COMPARE_TREE_CHANGED) { |
4137 | /* | ||
4138 | * We need to do some special handling in case the inode was | ||
4139 | * reported as changed with a changed generation number. This | ||
4140 | * means that the original inode was deleted and new inode | ||
4141 | * reused the same inum. So we have to treat the old inode as | ||
4142 | * deleted and the new one as new. | ||
4143 | */ | ||
4051 | if (sctx->cur_inode_new_gen) { | 4144 | if (sctx->cur_inode_new_gen) { |
4145 | /* | ||
4146 | * First, process the inode as if it was deleted. | ||
4147 | */ | ||
4052 | sctx->cur_inode_gen = right_gen; | 4148 | sctx->cur_inode_gen = right_gen; |
4053 | sctx->cur_inode_new = 0; | 4149 | sctx->cur_inode_new = 0; |
4054 | sctx->cur_inode_deleted = 1; | 4150 | sctx->cur_inode_deleted = 1; |
@@ -4061,6 +4157,9 @@ static int changed_inode(struct send_ctx *sctx, | |||
4061 | if (ret < 0) | 4157 | if (ret < 0) |
4062 | goto out; | 4158 | goto out; |
4063 | 4159 | ||
4160 | /* | ||
4161 | * Now process the inode as if it was new. | ||
4162 | */ | ||
4064 | sctx->cur_inode_gen = left_gen; | 4163 | sctx->cur_inode_gen = left_gen; |
4065 | sctx->cur_inode_new = 1; | 4164 | sctx->cur_inode_new = 1; |
4066 | sctx->cur_inode_deleted = 0; | 4165 | sctx->cur_inode_deleted = 0; |
@@ -4080,6 +4179,11 @@ static int changed_inode(struct send_ctx *sctx, | |||
4080 | * process_recorded_refs_if_needed in the new_gen case. | 4179 | * process_recorded_refs_if_needed in the new_gen case. |
4081 | */ | 4180 | */ |
4082 | sctx->send_progress = sctx->cur_ino + 1; | 4181 | sctx->send_progress = sctx->cur_ino + 1; |
4182 | |||
4183 | /* | ||
4184 | * Now process all extents and xattrs of the inode as if | ||
4185 | * they were all new. | ||
4186 | */ | ||
4083 | ret = process_all_extents(sctx); | 4187 | ret = process_all_extents(sctx); |
4084 | if (ret < 0) | 4188 | if (ret < 0) |
4085 | goto out; | 4189 | goto out; |
@@ -4102,6 +4206,16 @@ out: | |||
4102 | return ret; | 4206 | return ret; |
4103 | } | 4207 | } |
4104 | 4208 | ||
4209 | /* | ||
4210 | * We have to process new refs before deleted refs, but compare_trees gives us | ||
4211 | * the new and deleted refs mixed. To fix this, we record the new/deleted refs | ||
4212 | * first and later process them in process_recorded_refs. | ||
4213 | * For the cur_inode_new_gen case, we skip recording completely because | ||
4214 | * changed_inode did already initiate processing of refs. The reason for this is | ||
4215 | * that in this case, compare_tree actually compares the refs of 2 different | ||
4216 | * inodes. To fix this, process_all_refs is used in changed_inode to handle all | ||
4217 | * refs of the right tree as deleted and all refs of the left tree as new. | ||
4218 | */ | ||
4105 | static int changed_ref(struct send_ctx *sctx, | 4219 | static int changed_ref(struct send_ctx *sctx, |
4106 | enum btrfs_compare_tree_result result) | 4220 | enum btrfs_compare_tree_result result) |
4107 | { | 4221 | { |
@@ -4122,6 +4236,11 @@ static int changed_ref(struct send_ctx *sctx, | |||
4122 | return ret; | 4236 | return ret; |
4123 | } | 4237 | } |
4124 | 4238 | ||
4239 | /* | ||
4240 | * Process new/deleted/changed xattrs. We skip processing in the | ||
4241 | * cur_inode_new_gen case because changed_inode did already initiate processing | ||
4242 | * of xattrs. The reason is the same as in changed_ref | ||
4243 | */ | ||
4125 | static int changed_xattr(struct send_ctx *sctx, | 4244 | static int changed_xattr(struct send_ctx *sctx, |
4126 | enum btrfs_compare_tree_result result) | 4245 | enum btrfs_compare_tree_result result) |
4127 | { | 4246 | { |
@@ -4141,6 +4260,11 @@ static int changed_xattr(struct send_ctx *sctx, | |||
4141 | return ret; | 4260 | return ret; |
4142 | } | 4261 | } |
4143 | 4262 | ||
4263 | /* | ||
4264 | * Process new/deleted/changed extents. We skip processing in the | ||
4265 | * cur_inode_new_gen case because changed_inode did already initiate processing | ||
4266 | * of extents. The reason is the same as in changed_ref | ||
4267 | */ | ||
4144 | static int changed_extent(struct send_ctx *sctx, | 4268 | static int changed_extent(struct send_ctx *sctx, |
4145 | enum btrfs_compare_tree_result result) | 4269 | enum btrfs_compare_tree_result result) |
4146 | { | 4270 | { |
@@ -4157,7 +4281,10 @@ static int changed_extent(struct send_ctx *sctx, | |||
4157 | return ret; | 4281 | return ret; |
4158 | } | 4282 | } |
4159 | 4283 | ||
4160 | 4284 | /* | |
4285 | * Updates compare related fields in sctx and simply forwards to the actual | ||
4286 | * changed_xxx functions. | ||
4287 | */ | ||
4161 | static int changed_cb(struct btrfs_root *left_root, | 4288 | static int changed_cb(struct btrfs_root *left_root, |
4162 | struct btrfs_root *right_root, | 4289 | struct btrfs_root *right_root, |
4163 | struct btrfs_path *left_path, | 4290 | struct btrfs_path *left_path, |
@@ -4229,7 +4356,8 @@ join_trans: | |||
4229 | } | 4356 | } |
4230 | 4357 | ||
4231 | /* | 4358 | /* |
4232 | * Make sure the tree has not changed | 4359 | * Make sure the tree has not changed after re-joining. We detect this |
4360 | * by comparing start_ctransid and ctransid. They should always match. | ||
4233 | */ | 4361 | */ |
4234 | spin_lock(&send_root->root_times_lock); | 4362 | spin_lock(&send_root->root_times_lock); |
4235 | ctransid = btrfs_root_ctransid(&send_root->root_item); | 4363 | ctransid = btrfs_root_ctransid(&send_root->root_item); |