File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -61,10 +61,8 @@ xfs_bmap_compute_maxlevels(
6161 int sz ; /* root block size */
6262
6363 /*
64- * The maximum number of extents in a file, hence the maximum number of
65- * leaf entries, is controlled by the size of the on-disk extent count,
66- * either a signed 32-bit number for the data fork, or a signed 16-bit
67- * number for the attr fork.
64+ * The maximum number of extents in a fork, hence the maximum number of
65+ * leaf entries, is controlled by the size of the on-disk extent count.
6866 *
6967 * Note that we can no longer assume that if we are in ATTR1 that the
7068 * fork offset of all the inodes will be
@@ -74,7 +72,8 @@ xfs_bmap_compute_maxlevels(
7472 * ATTR2 we have to assume the worst case scenario of a minimum size
7573 * available.
7674 */
77- maxleafents = xfs_iext_max_nextents (whichfork );
75+ maxleafents = xfs_iext_max_nextents (xfs_has_large_extent_counts (mp ),
76+ whichfork );
7877 if (whichfork == XFS_DATA_FORK )
7978 sz = XFS_BMDR_SPACE_CALC (MINDBTPTRS );
8079 else
Original file line number Diff line number Diff line change @@ -597,7 +597,11 @@ xfs_bmbt_maxrecs(
597597 return xfs_bmbt_block_maxrecs (blocklen , leaf );
598598}
599599
600- /* Compute the max possible height for block mapping btrees. */
600+ /*
601+ * Calculate the maximum possible height of the btree that the on-disk format
602+ * supports. This is used for sizing structures large enough to support every
603+ * possible configuration of a filesystem that might get mounted.
604+ */
601605unsigned int
602606xfs_bmbt_maxlevels_ondisk (void )
603607{
@@ -611,7 +615,8 @@ xfs_bmbt_maxlevels_ondisk(void)
611615 minrecs [1 ] = xfs_bmbt_block_maxrecs (blocklen , false) / 2 ;
612616
613617 /* One extra level for the inode root. */
614- return xfs_btree_compute_maxlevels (minrecs , MAXEXTNUM ) + 1 ;
618+ return xfs_btree_compute_maxlevels (minrecs ,
619+ XFS_MAX_EXTCNT_DATA_FORK_LARGE ) + 1 ;
615620}
616621
617622/*
Original file line number Diff line number Diff line change @@ -872,9 +872,29 @@ enum xfs_dinode_fmt {
872872
873873/*
874874 * Max values for extnum and aextnum.
875+ *
876+ * The original on-disk extent counts were held in signed fields, resulting in
877+ * maximum extent counts of 2^31 and 2^15 for the data and attr forks
878+ * respectively. Similarly the maximum extent length is limited to 2^21 blocks
879+ * by the 21-bit wide blockcount field of a BMBT extent record.
880+ *
881+ * The newly introduced data fork extent counter can hold a 64-bit value,
882+ * however the maximum number of extents in a file is also limited to 2^54
883+ * extents by the 54-bit wide startoff field of a BMBT extent record.
884+ *
885+ * It is further limited by the maximum supported file size of 2^63
886+ * *bytes*. This leads to a maximum extent count for maximally sized filesystem
887+ * blocks (64kB) of:
888+ *
889+ * 2^63 bytes / 2^16 bytes per block = 2^47 blocks
890+ *
891+ * Rounding up 47 to the nearest multiple of bits-per-byte results in 48. Hence
892+ * 2^48 was chosen as the maximum data fork extent count.
875893 */
876- #define MAXEXTNUM ((xfs_extnum_t)0x7fffffff) /* signed int */
877- #define MAXAEXTNUM ((xfs_aextnum_t)0x7fff) /* signed short */
894+ #define XFS_MAX_EXTCNT_DATA_FORK_LARGE ((xfs_extnum_t)((1ULL << 48) - 1))
895+ #define XFS_MAX_EXTCNT_ATTR_FORK_LARGE ((xfs_extnum_t)((1ULL << 32) - 1))
896+ #define XFS_MAX_EXTCNT_DATA_FORK_SMALL ((xfs_extnum_t)((1ULL << 31) - 1))
897+ #define XFS_MAX_EXTCNT_ATTR_FORK_SMALL ((xfs_extnum_t)((1ULL << 15) - 1))
878898
879899/*
880900 * Inode minimum and maximum sizes.
Original file line number Diff line number Diff line change @@ -361,7 +361,9 @@ xfs_dinode_verify_fork(
361361 return __this_address ;
362362 break ;
363363 case XFS_DINODE_FMT_BTREE :
364- max_extents = xfs_iext_max_nextents (whichfork );
364+ max_extents = xfs_iext_max_nextents (
365+ xfs_dinode_has_large_extent_counts (dip ),
366+ whichfork );
365367 if (di_nextents > max_extents )
366368 return __this_address ;
367369 break ;
Original file line number Diff line number Diff line change @@ -744,7 +744,8 @@ xfs_iext_count_may_overflow(
744744 if (whichfork == XFS_COW_FORK )
745745 return 0 ;
746746
747- max_exts = xfs_iext_max_nextents (whichfork );
747+ max_exts = xfs_iext_max_nextents (xfs_inode_has_large_extent_counts (ip ),
748+ whichfork );
748749
749750 if (XFS_TEST_ERROR (false, ip -> i_mount , XFS_ERRTAG_REDUCE_MAX_IEXTENTS ))
750751 max_exts = 10 ;
Original file line number Diff line number Diff line change @@ -133,12 +133,25 @@ static inline int8_t xfs_ifork_format(struct xfs_ifork *ifp)
133133 return ifp -> if_format ;
134134}
135135
136- static inline xfs_extnum_t xfs_iext_max_nextents (int whichfork )
136+ static inline xfs_extnum_t xfs_iext_max_nextents (bool has_large_extent_counts ,
137+ int whichfork )
137138{
138- if (whichfork == XFS_DATA_FORK || whichfork == XFS_COW_FORK )
139- return MAXEXTNUM ;
139+ switch (whichfork ) {
140+ case XFS_DATA_FORK :
141+ case XFS_COW_FORK :
142+ if (has_large_extent_counts )
143+ return XFS_MAX_EXTCNT_DATA_FORK_LARGE ;
144+ return XFS_MAX_EXTCNT_DATA_FORK_SMALL ;
145+
146+ case XFS_ATTR_FORK :
147+ if (has_large_extent_counts )
148+ return XFS_MAX_EXTCNT_ATTR_FORK_LARGE ;
149+ return XFS_MAX_EXTCNT_ATTR_FORK_SMALL ;
140150
141- return MAXAEXTNUM ;
151+ default :
152+ ASSERT (0 );
153+ return 0 ;
154+ }
142155}
143156
144157static inline xfs_extnum_t
You can’t perform that action at this time.
0 commit comments