@@ -5025,34 +5025,116 @@ xfs_btree_diff_two_ptrs(
50255025 return (int64_t )be32_to_cpu (a -> s ) - be32_to_cpu (b -> s );
50265026}
50275027
5028- /* If there's an extent, we're done. */
5028+ struct xfs_btree_has_records {
5029+ /* Keys for the start and end of the range we want to know about. */
5030+ union xfs_btree_key start_key ;
5031+ union xfs_btree_key end_key ;
5032+
5033+ /* Highest record key we've seen so far. */
5034+ union xfs_btree_key high_key ;
5035+
5036+ enum xbtree_recpacking outcome ;
5037+ };
5038+
50295039STATIC int
5030- xfs_btree_has_record_helper (
5040+ xfs_btree_has_records_helper (
50315041 struct xfs_btree_cur * cur ,
50325042 const union xfs_btree_rec * rec ,
50335043 void * priv )
50345044{
5035- return - ECANCELED ;
5045+ union xfs_btree_key rec_key ;
5046+ union xfs_btree_key rec_high_key ;
5047+ struct xfs_btree_has_records * info = priv ;
5048+ enum xbtree_key_contig key_contig ;
5049+
5050+ cur -> bc_ops -> init_key_from_rec (& rec_key , rec );
5051+
5052+ if (info -> outcome == XBTREE_RECPACKING_EMPTY ) {
5053+ info -> outcome = XBTREE_RECPACKING_SPARSE ;
5054+
5055+ /*
5056+ * If the first record we find does not overlap the start key,
5057+ * then there is a hole at the start of the search range.
5058+ * Classify this as sparse and stop immediately.
5059+ */
5060+ if (xfs_btree_keycmp_lt (cur , & info -> start_key , & rec_key ))
5061+ return - ECANCELED ;
5062+ } else {
5063+ /*
5064+ * If a subsequent record does not overlap with the any record
5065+ * we've seen so far, there is a hole in the middle of the
5066+ * search range. Classify this as sparse and stop.
5067+ * If the keys overlap and this btree does not allow overlap,
5068+ * signal corruption.
5069+ */
5070+ key_contig = cur -> bc_ops -> keys_contiguous (cur , & info -> high_key ,
5071+ & rec_key );
5072+ if (key_contig == XBTREE_KEY_OVERLAP &&
5073+ !(cur -> bc_flags & XFS_BTREE_OVERLAPPING ))
5074+ return - EFSCORRUPTED ;
5075+ if (key_contig == XBTREE_KEY_GAP )
5076+ return - ECANCELED ;
5077+ }
5078+
5079+ /*
5080+ * If high_key(rec) is larger than any other high key we've seen,
5081+ * remember it for later.
5082+ */
5083+ cur -> bc_ops -> init_high_key_from_rec (& rec_high_key , rec );
5084+ if (xfs_btree_keycmp_gt (cur , & rec_high_key , & info -> high_key ))
5085+ info -> high_key = rec_high_key ; /* struct copy */
5086+
5087+ return 0 ;
50365088}
50375089
5038- /* Is there a record covering a given range of keys? */
5090+ /*
5091+ * Scan part of the keyspace of a btree and tell us if that keyspace does not
5092+ * map to any records; is fully mapped to records; or is partially mapped to
5093+ * records. This is the btree record equivalent to determining if a file is
5094+ * sparse.
5095+ */
50395096int
5040- xfs_btree_has_record (
5097+ xfs_btree_has_records (
50415098 struct xfs_btree_cur * cur ,
50425099 const union xfs_btree_irec * low ,
50435100 const union xfs_btree_irec * high ,
5044- bool * exists )
5101+ enum xbtree_recpacking * outcome )
50455102{
5103+ struct xfs_btree_has_records info = {
5104+ .outcome = XBTREE_RECPACKING_EMPTY ,
5105+ };
50465106 int error ;
50475107
5048- error = xfs_btree_query_range (cur , low , high ,
5049- & xfs_btree_has_record_helper , NULL );
5050- if (error == - ECANCELED ) {
5051- * exists = true;
5052- return 0 ;
5108+ /* Not all btrees support this operation. */
5109+ if (!cur -> bc_ops -> keys_contiguous ) {
5110+ ASSERT (0 );
5111+ return - EOPNOTSUPP ;
50535112 }
5054- * exists = false;
5055- return error ;
5113+
5114+ xfs_btree_key_from_irec (cur , & info .start_key , low );
5115+ xfs_btree_key_from_irec (cur , & info .end_key , high );
5116+
5117+ error = xfs_btree_query_range (cur , low , high ,
5118+ xfs_btree_has_records_helper , & info );
5119+ if (error == - ECANCELED )
5120+ goto out ;
5121+ if (error )
5122+ return error ;
5123+
5124+ if (info .outcome == XBTREE_RECPACKING_EMPTY )
5125+ goto out ;
5126+
5127+ /*
5128+ * If the largest high_key(rec) we saw during the walk is greater than
5129+ * the end of the search range, classify this as full. Otherwise,
5130+ * there is a hole at the end of the search range.
5131+ */
5132+ if (xfs_btree_keycmp_ge (cur , & info .high_key , & info .end_key ))
5133+ info .outcome = XBTREE_RECPACKING_FULL ;
5134+
5135+ out :
5136+ * outcome = info .outcome ;
5137+ return 0 ;
50565138}
50575139
50585140/* Are there more records in this btree? */
0 commit comments