1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) International Business Machines Corp., 2000-2004 4 */ 5 6 #include <linux/fs.h> 7 #include <linux/quotaops.h> 8 #include "jfs_incore.h" 9 #include "jfs_inode.h" 10 #include "jfs_superblock.h" 11 #include "jfs_dmap.h" 12 #include "jfs_extent.h" 13 #include "jfs_debug.h" 14 15 /* 16 * forward references 17 */ 18 static int extBalloc(struct inode *, s64, s64 *, s64 *); 19 #ifdef _NOTYET 20 static int extBrealloc(struct inode *, s64, s64, s64 *, s64 *); 21 #endif 22 static s64 extRoundDown(s64 nb); 23 24 #define DPD(a) (printk("(a): %d\n",(a))) 25 #define DPC(a) (printk("(a): %c\n",(a))) 26 #define DPL1(a) \ 27 { \ 28 if ((a) >> 32) \ 29 printk("(a): %x%08x ",(a)); \ 30 else \ 31 printk("(a): %x ",(a) << 32); \ 32 } 33 #define DPL(a) \ 34 { \ 35 if ((a) >> 32) \ 36 printk("(a): %x%08x\n",(a)); \ 37 else \ 38 printk("(a): %x\n",(a) << 32); \ 39 } 40 41 #define DPD1(a) (printk("(a): %d ",(a))) 42 #define DPX(a) (printk("(a): %08x\n",(a))) 43 #define DPX1(a) (printk("(a): %08x ",(a))) 44 #define DPS(a) (printk("%s\n",(a))) 45 #define DPE(a) (printk("\nENTERING: %s\n",(a))) 46 #define DPE1(a) (printk("\nENTERING: %s",(a))) 47 #define DPS1(a) (printk(" %s ",(a))) 48 49 50 /* 51 * NAME: extAlloc() 52 * 53 * FUNCTION: allocate an extent for a specified page range within a 54 * file. 55 * 56 * PARAMETERS: 57 * ip - the inode of the file. 58 * xlen - requested extent length. 59 * pno - the starting page number with the file. 60 * xp - pointer to an xad. on entry, xad describes an 61 * extent that is used as an allocation hint if the 62 * xaddr of the xad is non-zero. on successful exit, 63 * the xad describes the newly allocated extent. 64 * abnr - bool indicating whether the newly allocated extent 65 * should be marked as allocated but not recorded. 66 * 67 * RETURN VALUES: 68 * 0 - success 69 * -EIO - i/o error. 70 * -ENOSPC - insufficient disk resources. 71 */ 72 int 73 extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, bool abnr) 74 { 75 struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb); 76 s64 nxlen, nxaddr, xoff, hint, xaddr = 0; 77 int rc; 78 int xflag; 79 80 /* This blocks if we are low on resources */ 81 txBeginAnon(ip->i_sb); 82 83 /* Avoid race with jfs_commit_inode() */ 84 mutex_lock(&JFS_IP(ip)->commit_mutex); 85 86 /* validate extent length */ 87 if (xlen > MAXXLEN) 88 xlen = MAXXLEN; 89 90 /* get the page's starting extent offset */ 91 xoff = pno << sbi->l2nbperpage; 92 93 /* check if an allocation hint was provided */ 94 if ((hint = addressXAD(xp))) { 95 /* get the size of the extent described by the hint */ 96 nxlen = lengthXAD(xp); 97 98 /* check if the hint is for the portion of the file 99 * immediately previous to the current allocation 100 * request and if hint extent has the same abnr 101 * value as the current request. if so, we can 102 * extend the hint extent to include the current 103 * extent if we can allocate the blocks immediately 104 * following the hint extent. 105 */ 106 if (offsetXAD(xp) + nxlen == xoff && 107 abnr == ((xp->flag & XAD_NOTRECORDED) ? true : false)) 108 xaddr = hint + nxlen; 109 110 /* adjust the hint to the last block of the extent */ 111 hint += (nxlen - 1); 112 } 113 114 /* allocate the disk blocks for the extent. initially, extBalloc() 115 * will try to allocate disk blocks for the requested size (xlen). 116 * if this fails (xlen contiguous free blocks not available), it'll 117 * try to allocate a smaller number of blocks (producing a smaller 118 * extent), with this smaller number of blocks consisting of the 119 * requested number of blocks rounded down to the next smaller 120 * power of 2 number (i.e. 16 -> 8). it'll continue to round down 121 * and retry the allocation until the number of blocks to allocate 122 * is smaller than the number of blocks per page. 123 */ 124 nxlen = xlen; 125 if ((rc = extBalloc(ip, hint ? hint : INOHINT(ip), &nxlen, &nxaddr))) { 126 mutex_unlock(&JFS_IP(ip)->commit_mutex); 127 return (rc); 128 } 129 130 /* Allocate blocks to quota. */ 131 rc = dquot_alloc_block(ip, nxlen); 132 if (rc) { 133 dbFree(ip, nxaddr, (s64) nxlen); 134 mutex_unlock(&JFS_IP(ip)->commit_mutex); 135 return rc; 136 } 137 138 /* determine the value of the extent flag */ 139 xflag = abnr ? XAD_NOTRECORDED : 0; 140 141 /* if we can extend the hint extent to cover the current request, 142 * extend it. otherwise, insert a new extent to 143 * cover the current request. 144 */ 145 if (xaddr && xaddr == nxaddr) 146 rc = xtExtend(0, ip, xoff, (int) nxlen, 0); 147 else 148 rc = xtInsert(0, ip, xflag, xoff, (int) nxlen, &nxaddr, 0); 149 150 /* if the extend or insert failed, 151 * free the newly allocated blocks and return the error. 152 */ 153 if (rc) { 154 dbFree(ip, nxaddr, nxlen); 155 dquot_free_block(ip, nxlen); 156 mutex_unlock(&JFS_IP(ip)->commit_mutex); 157 return (rc); 158 } 159 160 /* set the results of the extent allocation */ 161 XADaddress(xp, nxaddr); 162 XADlength(xp, nxlen); 163 XADoffset(xp, xoff); 164 xp->flag = xflag; 165 166 mark_inode_dirty(ip); 167 168 mutex_unlock(&JFS_IP(ip)->commit_mutex); 169 /* 170 * COMMIT_SyncList flags an anonymous tlock on page that is on 171 * sync list. 172 * We need to commit the inode to get the page written disk. 173 */ 174 if (test_and_clear_cflag(COMMIT_Synclist,ip)) 175 jfs_commit_inode(ip, 0); 176 177 return (0); 178 } 179 180 181 #ifdef _NOTYET 182 /* 183 * NAME: extRealloc() 184 * 185 * FUNCTION: extend the allocation of a file extent containing a 186 * partial back last page. 187 * 188 * PARAMETERS: 189 * ip - the inode of the file. 190 * cp - cbuf for the partial backed last page. 191 * xlen - request size of the resulting extent. 192 * xp - pointer to an xad. on successful exit, the xad 193 * describes the newly allocated extent. 194 * abnr - bool indicating whether the newly allocated extent 195 * should be marked as allocated but not recorded. 196 * 197 * RETURN VALUES: 198 * 0 - success 199 * -EIO - i/o error. 200 * -ENOSPC - insufficient disk resources. 201 */ 202 int extRealloc(struct inode *ip, s64 nxlen, xad_t * xp, bool abnr) 203 { 204 struct super_block *sb = ip->i_sb; 205 s64 xaddr, xlen, nxaddr, delta, xoff; 206 s64 ntail, nextend, ninsert; 207 int rc, nbperpage = JFS_SBI(sb)->nbperpage; 208 int xflag; 209 210 /* This blocks if we are low on resources */ 211 txBeginAnon(ip->i_sb); 212 213 mutex_lock(&JFS_IP(ip)->commit_mutex); 214 /* validate extent length */ 215 if (nxlen > MAXXLEN) 216 nxlen = MAXXLEN; 217 218 /* get the extend (partial) page's disk block address and 219 * number of blocks. 220 */ 221 xaddr = addressXAD(xp); 222 xlen = lengthXAD(xp); 223 xoff = offsetXAD(xp); 224 225 /* if the extend page is abnr and if the request is for 226 * the extent to be allocated and recorded, 227 * make the page allocated and recorded. 228 */ 229 if ((xp->flag & XAD_NOTRECORDED) && !abnr) { 230 xp->flag = 0; 231 if ((rc = xtUpdate(0, ip, xp))) 232 goto exit; 233 } 234 235 /* try to allocated the request number of blocks for the 236 * extent. dbRealloc() first tries to satisfy the request 237 * by extending the allocation in place. otherwise, it will 238 * try to allocate a new set of blocks large enough for the 239 * request. in satisfying a request, dbReAlloc() may allocate 240 * less than what was request but will always allocate enough 241 * space as to satisfy the extend page. 242 */ 243 if ((rc = extBrealloc(ip, xaddr, xlen, &nxlen, &nxaddr))) 244 goto exit; 245 246 /* Allocat blocks to quota. */ 247 rc = dquot_alloc_block(ip, nxlen); 248 if (rc) { 249 dbFree(ip, nxaddr, (s64) nxlen); 250 mutex_unlock(&JFS_IP(ip)->commit_mutex); 251 return rc; 252 } 253 254 delta = nxlen - xlen; 255 256 /* check if the extend page is not abnr but the request is abnr 257 * and the allocated disk space is for more than one page. if this 258 * is the case, there is a miss match of abnr between the extend page 259 * and the one or more pages following the extend page. as a result, 260 * two extents will have to be manipulated. the first will be that 261 * of the extent of the extend page and will be manipulated thru 262 * an xtExtend() or an xtTailgate(), depending upon whether the 263 * disk allocation occurred as an inplace extension. the second 264 * extent will be manipulated (created) through an xtInsert() and 265 * will be for the pages following the extend page. 266 */ 267 if (abnr && (!(xp->flag & XAD_NOTRECORDED)) && (nxlen > nbperpage)) { 268 ntail = nbperpage; 269 nextend = ntail - xlen; 270 ninsert = nxlen - nbperpage; 271 272 xflag = XAD_NOTRECORDED; 273 } else { 274 ntail = nxlen; 275 nextend = delta; 276 ninsert = 0; 277 278 xflag = xp->flag; 279 } 280 281 /* if we were able to extend the disk allocation in place, 282 * extend the extent. otherwise, move the extent to a 283 * new disk location. 284 */ 285 if (xaddr == nxaddr) { 286 /* extend the extent */ 287 if ((rc = xtExtend(0, ip, xoff + xlen, (int) nextend, 0))) { 288 dbFree(ip, xaddr + xlen, delta); 289 dquot_free_block(ip, nxlen); 290 goto exit; 291 } 292 } else { 293 /* 294 * move the extent to a new location: 295 * 296 * xtTailgate() accounts for relocated tail extent; 297 */ 298 if ((rc = xtTailgate(0, ip, xoff, (int) ntail, nxaddr, 0))) { 299 dbFree(ip, nxaddr, nxlen); 300 dquot_free_block(ip, nxlen); 301 goto exit; 302 } 303 } 304 305 306 /* check if we need to also insert a new extent */ 307 if (ninsert) { 308 /* perform the insert. if it fails, free the blocks 309 * to be inserted and make it appear that we only did 310 * the xtExtend() or xtTailgate() above. 311 */ 312 xaddr = nxaddr + ntail; 313 if (xtInsert (0, ip, xflag, xoff + ntail, (int) ninsert, 314 &xaddr, 0)) { 315 dbFree(ip, xaddr, (s64) ninsert); 316 delta = nextend; 317 nxlen = ntail; 318 xflag = 0; 319 } 320 } 321 322 /* set the return results */ 323 XADaddress(xp, nxaddr); 324 XADlength(xp, nxlen); 325 XADoffset(xp, xoff); 326 xp->flag = xflag; 327 328 mark_inode_dirty(ip); 329 exit: 330 mutex_unlock(&JFS_IP(ip)->commit_mutex); 331 return (rc); 332 } 333 #endif /* _NOTYET */ 334 335 336 /* 337 * NAME: extHint() 338 * 339 * FUNCTION: produce an extent allocation hint for a file offset. 340 * 341 * PARAMETERS: 342 * ip - the inode of the file. 343 * offset - file offset for which the hint is needed. 344 * xp - pointer to the xad that is to be filled in with 345 * the hint. 346 * 347 * RETURN VALUES: 348 * 0 - success 349 * -EIO - i/o error. 350 */ 351 int extHint(struct inode *ip, s64 offset, xad_t * xp) 352 { 353 struct super_block *sb = ip->i_sb; 354 int nbperpage = JFS_SBI(sb)->nbperpage; 355 s64 prev; 356 int rc = 0; 357 s64 xaddr; 358 int xlen; 359 int xflag; 360 361 /* init the hint as "no hint provided" */ 362 XADaddress(xp, 0); 363 364 /* determine the starting extent offset of the page previous 365 * to the page containing the offset. 366 */ 367 prev = ((offset & ~POFFSET) >> JFS_SBI(sb)->l2bsize) - nbperpage; 368 369 /* if the offset is in the first page of the file, no hint provided. 370 */ 371 if (prev < 0) 372 goto out; 373 374 rc = xtLookup(ip, prev, nbperpage, &xflag, &xaddr, &xlen, 0); 375 376 if ((rc == 0) && xlen) { 377 if (xlen != nbperpage) { 378 jfs_error(ip->i_sb, "corrupt xtree\n"); 379 rc = -EIO; 380 } 381 XADaddress(xp, xaddr); 382 XADlength(xp, xlen); 383 XADoffset(xp, prev); 384 /* 385 * only preserve the abnr flag within the xad flags 386 * of the returned hint. 387 */ 388 xp->flag = xflag & XAD_NOTRECORDED; 389 } else 390 rc = 0; 391 392 out: 393 return (rc); 394 } 395 396 397 /* 398 * NAME: extRecord() 399 * 400 * FUNCTION: change a page with a file from not recorded to recorded. 401 * 402 * PARAMETERS: 403 * ip - inode of the file. 404 * cp - cbuf of the file page. 405 * 406 * RETURN VALUES: 407 * 0 - success 408 * -EIO - i/o error. 409 * -ENOSPC - insufficient disk resources. 410 */ 411 int extRecord(struct inode *ip, xad_t * xp) 412 { 413 int rc; 414 415 txBeginAnon(ip->i_sb); 416 417 mutex_lock(&JFS_IP(ip)->commit_mutex); 418 419 /* update the extent */ 420 rc = xtUpdate(0, ip, xp); 421 422 mutex_unlock(&JFS_IP(ip)->commit_mutex); 423 return rc; 424 } 425 426 427 #ifdef _NOTYET 428 /* 429 * NAME: extFill() 430 * 431 * FUNCTION: allocate disk space for a file page that represents 432 * a file hole. 433 * 434 * PARAMETERS: 435 * ip - the inode of the file. 436 * cp - cbuf of the file page represent the hole. 437 * 438 * RETURN VALUES: 439 * 0 - success 440 * -EIO - i/o error. 441 * -ENOSPC - insufficient disk resources. 442 */ 443 int extFill(struct inode *ip, xad_t * xp) 444 { 445 int rc, nbperpage = JFS_SBI(ip->i_sb)->nbperpage; 446 s64 blkno = offsetXAD(xp) >> ip->i_blkbits; 447 448 // assert(ISSPARSE(ip)); 449 450 /* initialize the extent allocation hint */ 451 XADaddress(xp, 0); 452 453 /* allocate an extent to fill the hole */ 454 if ((rc = extAlloc(ip, nbperpage, blkno, xp, false))) 455 return (rc); 456 457 assert(lengthPXD(xp) == nbperpage); 458 459 return (0); 460 } 461 #endif /* _NOTYET */ 462 463 464 /* 465 * NAME: extBalloc() 466 * 467 * FUNCTION: allocate disk blocks to form an extent. 468 * 469 * initially, we will try to allocate disk blocks for the 470 * requested size (nblocks). if this fails (nblocks 471 * contiguous free blocks not available), we'll try to allocate 472 * a smaller number of blocks (producing a smaller extent), with 473 * this smaller number of blocks consisting of the requested 474 * number of blocks rounded down to the next smaller power of 2 475 * number (i.e. 16 -> 8). we'll continue to round down and 476 * retry the allocation until the number of blocks to allocate 477 * is smaller than the number of blocks per page. 478 * 479 * PARAMETERS: 480 * ip - the inode of the file. 481 * hint - disk block number to be used as an allocation hint. 482 * *nblocks - pointer to an s64 value. on entry, this value specifies 483 * the desired number of block to be allocated. on successful 484 * exit, this value is set to the number of blocks actually 485 * allocated. 486 * blkno - pointer to a block address that is filled in on successful 487 * return with the starting block number of the newly 488 * allocated block range. 489 * 490 * RETURN VALUES: 491 * 0 - success 492 * -EIO - i/o error. 493 * -ENOSPC - insufficient disk resources. 494 */ 495 static int 496 extBalloc(struct inode *ip, s64 hint, s64 * nblocks, s64 * blkno) 497 { 498 struct jfs_inode_info *ji = JFS_IP(ip); 499 struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb); 500 s64 nb, nblks, daddr, max; 501 int rc, nbperpage = sbi->nbperpage; 502 struct bmap *bmp = sbi->bmap; 503 int ag; 504 505 /* get the number of blocks to initially attempt to allocate. 506 * we'll first try the number of blocks requested unless this 507 * number is greater than the maximum number of contiguous free 508 * blocks in the map. in that case, we'll start off with the 509 * maximum free. 510 */ 511 max = (s64) 1 << bmp->db_maxfreebud; 512 if (*nblocks >= max && *nblocks > nbperpage) 513 nb = nblks = (max > nbperpage) ? max : nbperpage; 514 else 515 nb = nblks = *nblocks; 516 517 /* try to allocate blocks */ 518 while ((rc = dbAlloc(ip, hint, nb, &daddr)) != 0) { 519 /* if something other than an out of space error, 520 * stop and return this error. 521 */ 522 if (rc != -ENOSPC) 523 return (rc); 524 525 /* decrease the allocation request size */ 526 nb = min(nblks, extRoundDown(nb)); 527 528 /* give up if we cannot cover a page */ 529 if (nb < nbperpage) 530 return (rc); 531 } 532 533 *nblocks = nb; 534 *blkno = daddr; 535 536 if (S_ISREG(ip->i_mode) && (ji->fileset == FILESYSTEM_I)) { 537 ag = BLKTOAG(daddr, sbi); 538 spin_lock_irq(&ji->ag_lock); 539 if (ji->active_ag == -1) { 540 atomic_inc(&bmp->db_active[ag]); 541 ji->active_ag = ag; 542 } else if (ji->active_ag != ag) { 543 atomic_dec(&bmp->db_active[ji->active_ag]); 544 atomic_inc(&bmp->db_active[ag]); 545 ji->active_ag = ag; 546 } 547 spin_unlock_irq(&ji->ag_lock); 548 } 549 550 return (0); 551 } 552 553 554 #ifdef _NOTYET 555 /* 556 * NAME: extBrealloc() 557 * 558 * FUNCTION: attempt to extend an extent's allocation. 559 * 560 * Initially, we will try to extend the extent's allocation 561 * in place. If this fails, we'll try to move the extent 562 * to a new set of blocks. If moving the extent, we initially 563 * will try to allocate disk blocks for the requested size 564 * (newnblks). if this fails (new contiguous free blocks not 565 * available), we'll try to allocate a smaller number of 566 * blocks (producing a smaller extent), with this smaller 567 * number of blocks consisting of the requested number of 568 * blocks rounded down to the next smaller power of 2 569 * number (i.e. 16 -> 8). We'll continue to round down and 570 * retry the allocation until the number of blocks to allocate 571 * is smaller than the number of blocks per page. 572 * 573 * PARAMETERS: 574 * ip - the inode of the file. 575 * blkno - starting block number of the extents current allocation. 576 * nblks - number of blocks within the extents current allocation. 577 * newnblks - pointer to a s64 value. on entry, this value is the 578 * the new desired extent size (number of blocks). on 579 * successful exit, this value is set to the extent's actual 580 * new size (new number of blocks). 581 * newblkno - the starting block number of the extents new allocation. 582 * 583 * RETURN VALUES: 584 * 0 - success 585 * -EIO - i/o error. 586 * -ENOSPC - insufficient disk resources. 587 */ 588 static int 589 extBrealloc(struct inode *ip, 590 s64 blkno, s64 nblks, s64 * newnblks, s64 * newblkno) 591 { 592 int rc; 593 594 /* try to extend in place */ 595 if ((rc = dbExtend(ip, blkno, nblks, *newnblks - nblks)) == 0) { 596 *newblkno = blkno; 597 return (0); 598 } else { 599 if (rc != -ENOSPC) 600 return (rc); 601 } 602 603 /* in place extension not possible. 604 * try to move the extent to a new set of blocks. 605 */ 606 return (extBalloc(ip, blkno, newnblks, newblkno)); 607 } 608 #endif /* _NOTYET */ 609 610 611 /* 612 * NAME: extRoundDown() 613 * 614 * FUNCTION: round down a specified number of blocks to the next 615 * smallest power of 2 number. 616 * 617 * PARAMETERS: 618 * nb - the inode of the file. 619 * 620 * RETURN VALUES: 621 * next smallest power of 2 number. 622 */ 623 static s64 extRoundDown(s64 nb) 624 { 625 int i; 626 u64 m, k; 627 628 for (i = 0, m = (u64) 1 << 63; i < 64; i++, m >>= 1) { 629 if (m & nb) 630 break; 631 } 632 633 i = 63 - i; 634 k = (u64) 1 << i; 635 k = ((k - 1) & nb) ? k : k >> 1; 636 637 return (k); 638 } 639