6363 */
6464static void dbAllocBits (struct bmap * bmp , struct dmap * dp , s64 blkno ,
6565 int nblocks );
66- static void dbSplit (dmtree_t * tp , int leafno , int splitsz , int newval );
67- static int dbBackSplit (dmtree_t * tp , int leafno );
68- static int dbJoin (dmtree_t * tp , int leafno , int newval );
69- static void dbAdjTree (dmtree_t * tp , int leafno , int newval );
66+ static void dbSplit (dmtree_t * tp , int leafno , int splitsz , int newval , bool is_ctl );
67+ static int dbBackSplit (dmtree_t * tp , int leafno , bool is_ctl );
68+ static int dbJoin (dmtree_t * tp , int leafno , int newval , bool is_ctl );
69+ static void dbAdjTree (dmtree_t * tp , int leafno , int newval , bool is_ctl );
7070static int dbAdjCtl (struct bmap * bmp , s64 blkno , int newval , int alloc ,
7171 int level );
7272static int dbAllocAny (struct bmap * bmp , s64 nblocks , int l2nb , s64 * results );
@@ -2103,7 +2103,7 @@ static int dbFreeDmap(struct bmap * bmp, struct dmap * dp, s64 blkno,
21032103 * system.
21042104 */
21052105 if (dp -> tree .stree [word ] == NOFREE )
2106- dbBackSplit ((dmtree_t * ) & dp -> tree , word );
2106+ dbBackSplit ((dmtree_t * )& dp -> tree , word , false );
21072107
21082108 dbAllocBits (bmp , dp , blkno , nblocks );
21092109 }
@@ -2189,7 +2189,7 @@ static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
21892189 * the binary system of the leaves if need be.
21902190 */
21912191 dbSplit (tp , word , BUDMIN ,
2192- dbMaxBud ((u8 * ) & dp -> wmap [word ]));
2192+ dbMaxBud ((u8 * )& dp -> wmap [word ]), false );
21932193
21942194 word += 1 ;
21952195 } else {
@@ -2229,7 +2229,7 @@ static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
22292229 * system of the leaves to reflect the current
22302230 * allocation (size).
22312231 */
2232- dbSplit (tp , word , size , NOFREE );
2232+ dbSplit (tp , word , size , NOFREE , false );
22332233
22342234 /* get the number of dmap words handled */
22352235 nw = BUDSIZE (size , BUDMIN );
@@ -2336,7 +2336,7 @@ static int dbFreeBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
23362336 /* update the leaf for this dmap word.
23372337 */
23382338 rc = dbJoin (tp , word ,
2339- dbMaxBud ((u8 * ) & dp -> wmap [word ]));
2339+ dbMaxBud ((u8 * )& dp -> wmap [word ]), false );
23402340 if (rc )
23412341 return rc ;
23422342
@@ -2369,7 +2369,7 @@ static int dbFreeBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
23692369
23702370 /* update the leaf.
23712371 */
2372- rc = dbJoin (tp , word , size );
2372+ rc = dbJoin (tp , word , size , false );
23732373 if (rc )
23742374 return rc ;
23752375
@@ -2521,16 +2521,16 @@ dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc, int level)
25212521 * that it is at the front of a binary buddy system.
25222522 */
25232523 if (oldval == NOFREE ) {
2524- rc = dbBackSplit ((dmtree_t * ) dcp , leafno );
2524+ rc = dbBackSplit ((dmtree_t * )dcp , leafno , true );
25252525 if (rc ) {
25262526 release_metapage (mp );
25272527 return rc ;
25282528 }
25292529 oldval = dcp -> stree [ti ];
25302530 }
2531- dbSplit ((dmtree_t * ) dcp , leafno , dcp -> budmin , newval );
2531+ dbSplit ((dmtree_t * ) dcp , leafno , dcp -> budmin , newval , true );
25322532 } else {
2533- rc = dbJoin ((dmtree_t * ) dcp , leafno , newval );
2533+ rc = dbJoin ((dmtree_t * ) dcp , leafno , newval , true );
25342534 if (rc ) {
25352535 release_metapage (mp );
25362536 return rc ;
@@ -2561,7 +2561,7 @@ dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc, int level)
25612561 */
25622562 if (alloc ) {
25632563 dbJoin ((dmtree_t * ) dcp , leafno ,
2564- oldval );
2564+ oldval , true );
25652565 } else {
25662566 /* the dbJoin() above might have
25672567 * caused a larger binary buddy system
@@ -2571,9 +2571,9 @@ dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc, int level)
25712571 */
25722572 if (dcp -> stree [ti ] == NOFREE )
25732573 dbBackSplit ((dmtree_t * )
2574- dcp , leafno );
2574+ dcp , leafno , true );
25752575 dbSplit ((dmtree_t * ) dcp , leafno ,
2576- dcp -> budmin , oldval );
2576+ dcp -> budmin , oldval , true );
25772577 }
25782578
25792579 /* release the buffer and return the error.
@@ -2621,7 +2621,7 @@ dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc, int level)
26212621 *
26222622 * serialization: IREAD_LOCK(ipbmap) or IWRITE_LOCK(ipbmap) held on entry/exit;
26232623 */
2624- static void dbSplit (dmtree_t * tp , int leafno , int splitsz , int newval )
2624+ static void dbSplit (dmtree_t * tp , int leafno , int splitsz , int newval , bool is_ctl )
26252625{
26262626 int budsz ;
26272627 int cursz ;
@@ -2643,7 +2643,7 @@ static void dbSplit(dmtree_t * tp, int leafno, int splitsz, int newval)
26432643 while (cursz >= splitsz ) {
26442644 /* update the buddy's leaf with its new value.
26452645 */
2646- dbAdjTree (tp , leafno ^ budsz , cursz );
2646+ dbAdjTree (tp , leafno ^ budsz , cursz , is_ctl );
26472647
26482648 /* on to the next size and buddy.
26492649 */
@@ -2655,7 +2655,7 @@ static void dbSplit(dmtree_t * tp, int leafno, int splitsz, int newval)
26552655 /* adjust the dmap tree to reflect the specified leaf's new
26562656 * value.
26572657 */
2658- dbAdjTree (tp , leafno , newval );
2658+ dbAdjTree (tp , leafno , newval , is_ctl );
26592659}
26602660
26612661
@@ -2686,7 +2686,7 @@ static void dbSplit(dmtree_t * tp, int leafno, int splitsz, int newval)
26862686 *
26872687 * serialization: IREAD_LOCK(ipbmap) or IWRITE_LOCK(ipbmap) held on entry/exit;
26882688 */
2689- static int dbBackSplit (dmtree_t * tp , int leafno )
2689+ static int dbBackSplit (dmtree_t * tp , int leafno , bool is_ctl )
26902690{
26912691 int budsz , bud , w , bsz , size ;
26922692 int cursz ;
@@ -2737,7 +2737,7 @@ static int dbBackSplit(dmtree_t * tp, int leafno)
27372737 * system in two.
27382738 */
27392739 cursz = leaf [bud ] - 1 ;
2740- dbSplit (tp , bud , cursz , cursz );
2740+ dbSplit (tp , bud , cursz , cursz , is_ctl );
27412741 break ;
27422742 }
27432743 }
@@ -2763,9 +2763,11 @@ static int dbBackSplit(dmtree_t * tp, int leafno)
27632763 * leafno - the number of the leaf to be updated.
27642764 * newval - the new value for the leaf.
27652765 *
2766- * RETURN VALUES: none
2766+ * RETURN VALUES:
2767+ * 0 - success
2768+ * -EIO - i/o error
27672769 */
2768- static int dbJoin (dmtree_t * tp , int leafno , int newval )
2770+ static int dbJoin (dmtree_t * tp , int leafno , int newval , bool is_ctl )
27692771{
27702772 int budsz , buddy ;
27712773 s8 * leaf ;
@@ -2790,6 +2792,10 @@ static int dbJoin(dmtree_t * tp, int leafno, int newval)
27902792 * get the buddy size (number of words covered) of
27912793 * the new value.
27922794 */
2795+
2796+ if ((newval - tp -> dmt_budmin ) > BUDMIN )
2797+ return - EIO ;
2798+
27932799 budsz = BUDSIZE (newval , tp -> dmt_budmin );
27942800
27952801 /* try to join.
@@ -2820,12 +2826,12 @@ static int dbJoin(dmtree_t * tp, int leafno, int newval)
28202826 if (leafno < buddy ) {
28212827 /* leafno is the left buddy.
28222828 */
2823- dbAdjTree (tp , buddy , NOFREE );
2829+ dbAdjTree (tp , buddy , NOFREE , is_ctl );
28242830 } else {
28252831 /* buddy is the left buddy and becomes
28262832 * leafno.
28272833 */
2828- dbAdjTree (tp , leafno , NOFREE );
2834+ dbAdjTree (tp , leafno , NOFREE , is_ctl );
28292835 leafno = buddy ;
28302836 }
28312837
@@ -2838,7 +2844,7 @@ static int dbJoin(dmtree_t * tp, int leafno, int newval)
28382844
28392845 /* update the leaf value.
28402846 */
2841- dbAdjTree (tp , leafno , newval );
2847+ dbAdjTree (tp , leafno , newval , is_ctl );
28422848
28432849 return 0 ;
28442850}
@@ -2859,15 +2865,20 @@ static int dbJoin(dmtree_t * tp, int leafno, int newval)
28592865 *
28602866 * RETURN VALUES: none
28612867 */
2862- static void dbAdjTree (dmtree_t * tp , int leafno , int newval )
2868+ static void dbAdjTree (dmtree_t * tp , int leafno , int newval , bool is_ctl )
28632869{
28642870 int lp , pp , k ;
2865- int max ;
2871+ int max , size ;
2872+
2873+ size = is_ctl ? CTLTREESIZE : TREESIZE ;
28662874
28672875 /* pick up the index of the leaf for this leafno.
28682876 */
28692877 lp = leafno + le32_to_cpu (tp -> dmt_leafidx );
28702878
2879+ if (WARN_ON_ONCE (lp >= size || lp < 0 ))
2880+ return ;
2881+
28712882 /* is the current value the same as the old value ? if so,
28722883 * there is nothing to do.
28732884 */
0 commit comments