1e06536a6SDarrick J. Wong // SPDX-License-Identifier: GPL-2.0-or-later 2e06536a6SDarrick J. Wong /* 3e06536a6SDarrick J. Wong * Copyright (C) 2020 Oracle. All Rights Reserved. 4e06536a6SDarrick J. Wong * Author: Darrick J. Wong <darrick.wong@oracle.com> 5e06536a6SDarrick J. Wong */ 6e06536a6SDarrick J. Wong #include "xfs.h" 7e06536a6SDarrick J. Wong #include "xfs_fs.h" 8e06536a6SDarrick J. Wong #include "xfs_shared.h" 9e06536a6SDarrick J. Wong #include "xfs_format.h" 10e06536a6SDarrick J. Wong #include "xfs_log_format.h" 11e06536a6SDarrick J. Wong #include "xfs_trans_resv.h" 12e06536a6SDarrick J. Wong #include "xfs_bit.h" 13e06536a6SDarrick J. Wong #include "xfs_mount.h" 14e06536a6SDarrick J. Wong #include "xfs_inode.h" 15e06536a6SDarrick J. Wong #include "xfs_trans.h" 16e06536a6SDarrick J. Wong #include "xfs_btree.h" 17e06536a6SDarrick J. Wong #include "xfs_trace.h" 18e06536a6SDarrick J. Wong #include "xfs_btree_staging.h" 19e06536a6SDarrick J. Wong 20e06536a6SDarrick J. Wong /* 21e06536a6SDarrick J. Wong * Staging Cursors and Fake Roots for Btrees 22e06536a6SDarrick J. Wong * ========================================= 23e06536a6SDarrick J. Wong * 24e06536a6SDarrick J. Wong * A staging btree cursor is a special type of btree cursor that callers must 25e06536a6SDarrick J. Wong * use to construct a new btree index using the btree bulk loader code. The 26e06536a6SDarrick J. Wong * bulk loading code uses the staging btree cursor to abstract the details of 27e06536a6SDarrick J. Wong * initializing new btree blocks and filling them with records or key/ptr 28e06536a6SDarrick J. Wong * pairs. Regular btree operations (e.g. queries and modifications) are not 29e06536a6SDarrick J. Wong * supported with staging cursors, and callers must not invoke them. 30e06536a6SDarrick J. Wong * 31e06536a6SDarrick J. Wong * Fake root structures contain all the information about a btree that is under 32e06536a6SDarrick J. Wong * construction by the bulk loading code. Staging btree cursors point to fake 33e06536a6SDarrick J. Wong * root structures instead of the usual AG header or inode structure. 34e06536a6SDarrick J. Wong * 35e06536a6SDarrick J. Wong * Callers are expected to initialize a fake root structure and pass it into 36e06536a6SDarrick J. Wong * the _stage_cursor function for a specific btree type. When bulk loading is 37e06536a6SDarrick J. Wong * complete, callers should call the _commit_staged_btree function for that 38e06536a6SDarrick J. Wong * specific btree type to commit the new btree into the filesystem. 39e06536a6SDarrick J. Wong */ 40e06536a6SDarrick J. Wong 41e06536a6SDarrick J. Wong /* 42e06536a6SDarrick J. Wong * Don't allow staging cursors to be duplicated because they're supposed to be 43e06536a6SDarrick J. Wong * kept private to a single thread. 44e06536a6SDarrick J. Wong */ 45e06536a6SDarrick J. Wong STATIC struct xfs_btree_cur * 46e06536a6SDarrick J. Wong xfs_btree_fakeroot_dup_cursor( 47e06536a6SDarrick J. Wong struct xfs_btree_cur *cur) 48e06536a6SDarrick J. Wong { 49e06536a6SDarrick J. Wong ASSERT(0); 50e06536a6SDarrick J. Wong return NULL; 51e06536a6SDarrick J. Wong } 52e06536a6SDarrick J. Wong 53e06536a6SDarrick J. Wong /* 54e06536a6SDarrick J. Wong * Don't allow block allocation for a staging cursor, because staging cursors 55e06536a6SDarrick J. Wong * do not support regular btree modifications. 56e06536a6SDarrick J. Wong * 57e06536a6SDarrick J. Wong * Bulk loading uses a separate callback to obtain new blocks from a 58e06536a6SDarrick J. Wong * preallocated list, which prevents ENOSPC failures during loading. 59e06536a6SDarrick J. Wong */ 60e06536a6SDarrick J. Wong STATIC int 61e06536a6SDarrick J. Wong xfs_btree_fakeroot_alloc_block( 62e06536a6SDarrick J. Wong struct xfs_btree_cur *cur, 63e06536a6SDarrick J. Wong union xfs_btree_ptr *start_bno, 64e06536a6SDarrick J. Wong union xfs_btree_ptr *new_bno, 65e06536a6SDarrick J. Wong int *stat) 66e06536a6SDarrick J. Wong { 67e06536a6SDarrick J. Wong ASSERT(0); 68e06536a6SDarrick J. Wong return -EFSCORRUPTED; 69e06536a6SDarrick J. Wong } 70e06536a6SDarrick J. Wong 71e06536a6SDarrick J. Wong /* 72e06536a6SDarrick J. Wong * Don't allow block freeing for a staging cursor, because staging cursors 73e06536a6SDarrick J. Wong * do not support regular btree modifications. 74e06536a6SDarrick J. Wong */ 75e06536a6SDarrick J. Wong STATIC int 76e06536a6SDarrick J. Wong xfs_btree_fakeroot_free_block( 77e06536a6SDarrick J. Wong struct xfs_btree_cur *cur, 78e06536a6SDarrick J. Wong struct xfs_buf *bp) 79e06536a6SDarrick J. Wong { 80e06536a6SDarrick J. Wong ASSERT(0); 81e06536a6SDarrick J. Wong return -EFSCORRUPTED; 82e06536a6SDarrick J. Wong } 83e06536a6SDarrick J. Wong 84e06536a6SDarrick J. Wong /* Initialize a pointer to the root block from the fakeroot. */ 85e06536a6SDarrick J. Wong STATIC void 86e06536a6SDarrick J. Wong xfs_btree_fakeroot_init_ptr_from_cur( 87e06536a6SDarrick J. Wong struct xfs_btree_cur *cur, 88e06536a6SDarrick J. Wong union xfs_btree_ptr *ptr) 89e06536a6SDarrick J. Wong { 90e06536a6SDarrick J. Wong struct xbtree_afakeroot *afake; 91e06536a6SDarrick J. Wong 92e06536a6SDarrick J. Wong ASSERT(cur->bc_flags & XFS_BTREE_STAGING); 93e06536a6SDarrick J. Wong 94e06536a6SDarrick J. Wong afake = cur->bc_ag.afake; 95e06536a6SDarrick J. Wong ptr->s = cpu_to_be32(afake->af_root); 96e06536a6SDarrick J. Wong } 97e06536a6SDarrick J. Wong 98e06536a6SDarrick J. Wong /* 99e06536a6SDarrick J. Wong * Bulk Loading for AG Btrees 100e06536a6SDarrick J. Wong * ========================== 101e06536a6SDarrick J. Wong * 102e06536a6SDarrick J. Wong * For a btree rooted in an AG header, pass a xbtree_afakeroot structure to the 103e06536a6SDarrick J. Wong * staging cursor. Callers should initialize this to zero. 104e06536a6SDarrick J. Wong * 105e06536a6SDarrick J. Wong * The _stage_cursor() function for a specific btree type should call 106e06536a6SDarrick J. Wong * xfs_btree_stage_afakeroot to set up the in-memory cursor as a staging 107e06536a6SDarrick J. Wong * cursor. The corresponding _commit_staged_btree() function should log the 108e06536a6SDarrick J. Wong * new root and call xfs_btree_commit_afakeroot() to transform the staging 109e06536a6SDarrick J. Wong * cursor into a regular btree cursor. 110e06536a6SDarrick J. Wong */ 111e06536a6SDarrick J. Wong 112e06536a6SDarrick J. Wong /* Update the btree root information for a per-AG fake root. */ 113e06536a6SDarrick J. Wong STATIC void 114e06536a6SDarrick J. Wong xfs_btree_afakeroot_set_root( 115e06536a6SDarrick J. Wong struct xfs_btree_cur *cur, 116e06536a6SDarrick J. Wong union xfs_btree_ptr *ptr, 117e06536a6SDarrick J. Wong int inc) 118e06536a6SDarrick J. Wong { 119e06536a6SDarrick J. Wong struct xbtree_afakeroot *afake = cur->bc_ag.afake; 120e06536a6SDarrick J. Wong 121e06536a6SDarrick J. Wong ASSERT(cur->bc_flags & XFS_BTREE_STAGING); 122e06536a6SDarrick J. Wong afake->af_root = be32_to_cpu(ptr->s); 123e06536a6SDarrick J. Wong afake->af_levels += inc; 124e06536a6SDarrick J. Wong } 125e06536a6SDarrick J. Wong 126e06536a6SDarrick J. Wong /* 127e06536a6SDarrick J. Wong * Initialize a AG-rooted btree cursor with the given AG btree fake root. 128e06536a6SDarrick J. Wong * The btree cursor's bc_ops will be overridden as needed to make the staging 129e06536a6SDarrick J. Wong * functionality work. 130e06536a6SDarrick J. Wong */ 131e06536a6SDarrick J. Wong void 132e06536a6SDarrick J. Wong xfs_btree_stage_afakeroot( 133e06536a6SDarrick J. Wong struct xfs_btree_cur *cur, 134e06536a6SDarrick J. Wong struct xbtree_afakeroot *afake) 135e06536a6SDarrick J. Wong { 136e06536a6SDarrick J. Wong struct xfs_btree_ops *nops; 137e06536a6SDarrick J. Wong 138e06536a6SDarrick J. Wong ASSERT(!(cur->bc_flags & XFS_BTREE_STAGING)); 139e06536a6SDarrick J. Wong ASSERT(!(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE)); 140e06536a6SDarrick J. Wong ASSERT(cur->bc_tp == NULL); 141e06536a6SDarrick J. Wong 142e06536a6SDarrick J. Wong nops = kmem_alloc(sizeof(struct xfs_btree_ops), KM_NOFS); 143e06536a6SDarrick J. Wong memcpy(nops, cur->bc_ops, sizeof(struct xfs_btree_ops)); 144e06536a6SDarrick J. Wong nops->alloc_block = xfs_btree_fakeroot_alloc_block; 145e06536a6SDarrick J. Wong nops->free_block = xfs_btree_fakeroot_free_block; 146e06536a6SDarrick J. Wong nops->init_ptr_from_cur = xfs_btree_fakeroot_init_ptr_from_cur; 147e06536a6SDarrick J. Wong nops->set_root = xfs_btree_afakeroot_set_root; 148e06536a6SDarrick J. Wong nops->dup_cursor = xfs_btree_fakeroot_dup_cursor; 149e06536a6SDarrick J. Wong 150e06536a6SDarrick J. Wong cur->bc_ag.afake = afake; 151e06536a6SDarrick J. Wong cur->bc_nlevels = afake->af_levels; 152e06536a6SDarrick J. Wong cur->bc_ops = nops; 153e06536a6SDarrick J. Wong cur->bc_flags |= XFS_BTREE_STAGING; 154e06536a6SDarrick J. Wong } 155e06536a6SDarrick J. Wong 156e06536a6SDarrick J. Wong /* 157e06536a6SDarrick J. Wong * Transform an AG-rooted staging btree cursor back into a regular cursor by 158e06536a6SDarrick J. Wong * substituting a real btree root for the fake one and restoring normal btree 159e06536a6SDarrick J. Wong * cursor ops. The caller must log the btree root change prior to calling 160e06536a6SDarrick J. Wong * this. 161e06536a6SDarrick J. Wong */ 162e06536a6SDarrick J. Wong void 163e06536a6SDarrick J. Wong xfs_btree_commit_afakeroot( 164e06536a6SDarrick J. Wong struct xfs_btree_cur *cur, 165e06536a6SDarrick J. Wong struct xfs_trans *tp, 166e06536a6SDarrick J. Wong struct xfs_buf *agbp, 167e06536a6SDarrick J. Wong const struct xfs_btree_ops *ops) 168e06536a6SDarrick J. Wong { 169e06536a6SDarrick J. Wong ASSERT(cur->bc_flags & XFS_BTREE_STAGING); 170e06536a6SDarrick J. Wong ASSERT(cur->bc_tp == NULL); 171e06536a6SDarrick J. Wong 172e06536a6SDarrick J. Wong trace_xfs_btree_commit_afakeroot(cur); 173e06536a6SDarrick J. Wong 174e06536a6SDarrick J. Wong kmem_free((void *)cur->bc_ops); 175e06536a6SDarrick J. Wong cur->bc_ag.agbp = agbp; 176e06536a6SDarrick J. Wong cur->bc_ops = ops; 177e06536a6SDarrick J. Wong cur->bc_flags &= ~XFS_BTREE_STAGING; 178e06536a6SDarrick J. Wong cur->bc_tp = tp; 179e06536a6SDarrick J. Wong } 180349e1c03SDarrick J. Wong 181349e1c03SDarrick J. Wong /* 182349e1c03SDarrick J. Wong * Bulk Loading for Inode-Rooted Btrees 183349e1c03SDarrick J. Wong * ==================================== 184349e1c03SDarrick J. Wong * 185349e1c03SDarrick J. Wong * For a btree rooted in an inode fork, pass a xbtree_ifakeroot structure to 186349e1c03SDarrick J. Wong * the staging cursor. This structure should be initialized as follows: 187349e1c03SDarrick J. Wong * 188349e1c03SDarrick J. Wong * - if_fork_size field should be set to the number of bytes available to the 189349e1c03SDarrick J. Wong * fork in the inode. 190349e1c03SDarrick J. Wong * 191349e1c03SDarrick J. Wong * - if_fork should point to a freshly allocated struct xfs_ifork. 192349e1c03SDarrick J. Wong * 193349e1c03SDarrick J. Wong * - if_format should be set to the appropriate fork type (e.g. 194349e1c03SDarrick J. Wong * XFS_DINODE_FMT_BTREE). 195349e1c03SDarrick J. Wong * 196349e1c03SDarrick J. Wong * All other fields must be zero. 197349e1c03SDarrick J. Wong * 198349e1c03SDarrick J. Wong * The _stage_cursor() function for a specific btree type should call 199349e1c03SDarrick J. Wong * xfs_btree_stage_ifakeroot to set up the in-memory cursor as a staging 200349e1c03SDarrick J. Wong * cursor. The corresponding _commit_staged_btree() function should log the 201349e1c03SDarrick J. Wong * new root and call xfs_btree_commit_ifakeroot() to transform the staging 202349e1c03SDarrick J. Wong * cursor into a regular btree cursor. 203349e1c03SDarrick J. Wong */ 204349e1c03SDarrick J. Wong 205349e1c03SDarrick J. Wong /* 206349e1c03SDarrick J. Wong * Initialize an inode-rooted btree cursor with the given inode btree fake 207349e1c03SDarrick J. Wong * root. The btree cursor's bc_ops will be overridden as needed to make the 208349e1c03SDarrick J. Wong * staging functionality work. If new_ops is not NULL, these new ops will be 209349e1c03SDarrick J. Wong * passed out to the caller for further overriding. 210349e1c03SDarrick J. Wong */ 211349e1c03SDarrick J. Wong void 212349e1c03SDarrick J. Wong xfs_btree_stage_ifakeroot( 213349e1c03SDarrick J. Wong struct xfs_btree_cur *cur, 214349e1c03SDarrick J. Wong struct xbtree_ifakeroot *ifake, 215349e1c03SDarrick J. Wong struct xfs_btree_ops **new_ops) 216349e1c03SDarrick J. Wong { 217349e1c03SDarrick J. Wong struct xfs_btree_ops *nops; 218349e1c03SDarrick J. Wong 219349e1c03SDarrick J. Wong ASSERT(!(cur->bc_flags & XFS_BTREE_STAGING)); 220349e1c03SDarrick J. Wong ASSERT(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE); 221349e1c03SDarrick J. Wong ASSERT(cur->bc_tp == NULL); 222349e1c03SDarrick J. Wong 223349e1c03SDarrick J. Wong nops = kmem_alloc(sizeof(struct xfs_btree_ops), KM_NOFS); 224349e1c03SDarrick J. Wong memcpy(nops, cur->bc_ops, sizeof(struct xfs_btree_ops)); 225349e1c03SDarrick J. Wong nops->alloc_block = xfs_btree_fakeroot_alloc_block; 226349e1c03SDarrick J. Wong nops->free_block = xfs_btree_fakeroot_free_block; 227349e1c03SDarrick J. Wong nops->init_ptr_from_cur = xfs_btree_fakeroot_init_ptr_from_cur; 228349e1c03SDarrick J. Wong nops->dup_cursor = xfs_btree_fakeroot_dup_cursor; 229349e1c03SDarrick J. Wong 230349e1c03SDarrick J. Wong cur->bc_ino.ifake = ifake; 231349e1c03SDarrick J. Wong cur->bc_nlevels = ifake->if_levels; 232349e1c03SDarrick J. Wong cur->bc_ops = nops; 233349e1c03SDarrick J. Wong cur->bc_flags |= XFS_BTREE_STAGING; 234349e1c03SDarrick J. Wong 235349e1c03SDarrick J. Wong if (new_ops) 236349e1c03SDarrick J. Wong *new_ops = nops; 237349e1c03SDarrick J. Wong } 238349e1c03SDarrick J. Wong 239349e1c03SDarrick J. Wong /* 240349e1c03SDarrick J. Wong * Transform an inode-rooted staging btree cursor back into a regular cursor by 241349e1c03SDarrick J. Wong * substituting a real btree root for the fake one and restoring normal btree 242349e1c03SDarrick J. Wong * cursor ops. The caller must log the btree root change prior to calling 243349e1c03SDarrick J. Wong * this. 244349e1c03SDarrick J. Wong */ 245349e1c03SDarrick J. Wong void 246349e1c03SDarrick J. Wong xfs_btree_commit_ifakeroot( 247349e1c03SDarrick J. Wong struct xfs_btree_cur *cur, 248349e1c03SDarrick J. Wong struct xfs_trans *tp, 249349e1c03SDarrick J. Wong int whichfork, 250349e1c03SDarrick J. Wong const struct xfs_btree_ops *ops) 251349e1c03SDarrick J. Wong { 252349e1c03SDarrick J. Wong ASSERT(cur->bc_flags & XFS_BTREE_STAGING); 253349e1c03SDarrick J. Wong ASSERT(cur->bc_tp == NULL); 254349e1c03SDarrick J. Wong 255349e1c03SDarrick J. Wong trace_xfs_btree_commit_ifakeroot(cur); 256349e1c03SDarrick J. Wong 257349e1c03SDarrick J. Wong kmem_free((void *)cur->bc_ops); 258349e1c03SDarrick J. Wong cur->bc_ino.ifake = NULL; 259349e1c03SDarrick J. Wong cur->bc_ino.whichfork = whichfork; 260349e1c03SDarrick J. Wong cur->bc_ops = ops; 261349e1c03SDarrick J. Wong cur->bc_flags &= ~XFS_BTREE_STAGING; 262349e1c03SDarrick J. Wong cur->bc_tp = tp; 263349e1c03SDarrick J. Wong } 264