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