ext2_alloc.c revision 30492
1/* 2 * modified for Lites 1.1 3 * 4 * Aug 1995, Godmar Back (gback@cs.utah.edu) 5 * University of Utah, Department of Computer Science 6 */ 7/* 8 * Copyright (c) 1982, 1986, 1989, 1993 9 * The Regents of the University of California. All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the University of 22 * California, Berkeley and its contributors. 23 * 4. Neither the name of the University nor the names of its contributors 24 * may be used to endorse or promote products derived from this software 25 * without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 * 39 * @(#)ext2_alloc.c 8.8 (Berkeley) 2/21/94 40 */ 41 42#if !defined(__FreeBSD__) 43#include "quota.h" 44#include "diagnostic.h" 45#else 46#include "opt_quota.h" 47#endif 48 49#include <sys/param.h> 50#include <sys/systm.h> 51#include <sys/vnode.h> 52#include <sys/stat.h> 53#include <sys/mount.h> 54#include <sys/kernel.h> 55#include <sys/syslog.h> 56 57#include <ufs/ufs/quota.h> 58#include <ufs/ufs/inode.h> 59#include <ufs/ufs/ufsmount.h> 60 61#include <gnu/ext2fs/ext2_fs.h> 62#include <gnu/ext2fs/ext2_fs_sb.h> 63#include <gnu/ext2fs/fs.h> 64#include <gnu/ext2fs/ext2_extern.h> 65 66extern u_long nextgennumber; 67 68static void ext2_fserr __P((struct ext2_sb_info *, u_int, char *)); 69 70/* 71 * Linux calls this functions at the following locations: 72 * (1) the inode is freed 73 * (2) a preallocation miss occurs 74 * (3) truncate is called 75 * (4) release_file is called and f_mode & 2 76 * 77 * I call it in ext2_inactive, ext2_truncate, ext2_vfree and in (2) 78 * the call in vfree might be redundant 79 */ 80void 81ext2_discard_prealloc(ip) 82 struct inode * ip; 83{ 84#ifdef EXT2_PREALLOCATE 85 if (ip->i_prealloc_count) { 86 int i = ip->i_prealloc_count; 87 ip->i_prealloc_count = 0; 88 ext2_free_blocks (ITOV(ip)->v_mount, 89 ip->i_prealloc_block, 90 i); 91 } 92#endif 93} 94 95/* 96 * Allocate a block in the file system. 97 * 98 * this takes the framework from ffs_alloc. To implement the 99 * actual allocation, it calls ext2_new_block, the ported version 100 * of the same Linux routine. 101 * 102 * we note that this is always called in connection with ext2_blkpref 103 * 104 * preallocation is done as Linux does it 105 */ 106int 107ext2_alloc(ip, lbn, bpref, size, cred, bnp) 108 register struct inode *ip; 109 daddr_t lbn, bpref; 110 int size; 111 struct ucred *cred; 112 daddr_t *bnp; 113{ 114 register struct ext2_sb_info *fs; 115 daddr_t bno; 116#if QUOTA 117 int error; 118#endif 119 120 *bnp = 0; 121 fs = ip->i_e2fs; 122#if DIAGNOSTIC 123 if ((u_int)size > fs->s_blocksize || blkoff(fs, size) != 0) { 124 printf("dev = 0x%x, bsize = %d, size = %d, fs = %s\n", 125 ip->i_dev, fs->s_blocksize, size, fs->fs_fsmnt); 126 panic("ext2_alloc: bad size"); 127 } 128 if (cred == NOCRED) 129 panic("ext2_alloc: missing credential"); 130#endif /* DIAGNOSTIC */ 131 if (size == fs->s_blocksize && fs->s_es->s_free_blocks_count == 0) 132 goto nospace; 133 if (cred->cr_uid != 0 && 134 fs->s_es->s_free_blocks_count < fs->s_es->s_r_blocks_count) 135 goto nospace; 136#if QUOTA 137 if (error = chkdq(ip, (long)btodb(size), cred, 0)) 138 return (error); 139#endif 140 if (bpref >= fs->s_es->s_blocks_count) 141 bpref = 0; 142 /* call the Linux code */ 143#ifdef EXT2_PREALLOCATE 144 /* To have a preallocation hit, we must 145 * - have at least one block preallocated 146 * - and our preferred block must have that block number or one below 147 */ 148 if (ip->i_prealloc_count && 149 (bpref == ip->i_prealloc_block || 150 bpref + 1 == ip->i_prealloc_block)) 151 { 152 bno = ip->i_prealloc_block++; 153 ip->i_prealloc_count--; 154 /* ext2_debug ("preallocation hit (%lu/%lu).\n", 155 ++alloc_hits, ++alloc_attempts); */ 156 157 /* Linux gets, clears, and releases the buffer at this 158 point - we don't have to that; we leave it to the caller 159 */ 160 } else { 161 ext2_discard_prealloc (ip); 162 /* ext2_debug ("preallocation miss (%lu/%lu).\n", 163 alloc_hits, ++alloc_attempts); */ 164 if (S_ISREG(ip->i_mode)) 165 bno = ext2_new_block 166 (ITOV(ip)->v_mount, bpref, 167 &ip->i_prealloc_count, 168 &ip->i_prealloc_block); 169 else 170 bno = (daddr_t)ext2_new_block(ITOV(ip)->v_mount, 171 bpref, 0, 0); 172 } 173#else 174 bno = (daddr_t)ext2_new_block(ITOV(ip)->v_mount, bpref, 0, 0); 175#endif 176 177 if (bno > 0) { 178 /* set next_alloc fields as done in block_getblk */ 179 ip->i_next_alloc_block = lbn; 180 ip->i_next_alloc_goal = bno; 181 182 ip->i_blocks += btodb(size); 183 ip->i_flag |= IN_CHANGE | IN_UPDATE; 184 *bnp = bno; 185 return (0); 186 } 187#if QUOTA 188 /* 189 * Restore user's disk quota because allocation failed. 190 */ 191 (void) chkdq(ip, (long)-btodb(size), cred, FORCE); 192#endif 193nospace: 194 ext2_fserr(fs, cred->cr_uid, "file system full"); 195 uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); 196 return (ENOSPC); 197} 198 199/* 200 * Reallocate a sequence of blocks into a contiguous sequence of blocks. 201 * 202 * The vnode and an array of buffer pointers for a range of sequential 203 * logical blocks to be made contiguous is given. The allocator attempts 204 * to find a range of sequential blocks starting as close as possible to 205 * an fs_rotdelay offset from the end of the allocation for the logical 206 * block immediately preceeding the current range. If successful, the 207 * physical block numbers in the buffer pointers and in the inode are 208 * changed to reflect the new allocation. If unsuccessful, the allocation 209 * is left unchanged. The success in doing the reallocation is returned. 210 * Note that the error return is not reflected back to the user. Rather 211 * the previous block allocation will be used. 212 */ 213 214#ifdef FANCY_REALLOC 215#include <sys/sysctl.h> 216static int doasyncfree = 1; 217#ifdef OPT_DEBUG 218SYSCTL_INT(_debug, 14, doasyncfree, CTLFLAG_RW, &doasyncfree, 0, ""); 219#endif /* OPT_DEBUG */ 220#endif 221 222int 223ext2_reallocblks(ap) 224 struct vop_reallocblks_args /* { 225 struct vnode *a_vp; 226 struct cluster_save *a_buflist; 227 } */ *ap; 228{ 229#ifndef FANCY_REALLOC 230/* printf("ext2_reallocblks not implemented\n"); */ 231return ENOSPC; 232#else 233 234 struct ext2_sb_info *fs; 235 struct inode *ip; 236 struct vnode *vp; 237 struct buf *sbp, *ebp; 238 daddr_t *bap, *sbap, *ebap; 239 struct cluster_save *buflist; 240 daddr_t start_lbn, end_lbn, soff, eoff, newblk, blkno; 241 struct indir start_ap[NIADDR + 1], end_ap[NIADDR + 1], *idp; 242 int i, len, start_lvl, end_lvl, pref, ssize; 243 struct timeval tv; 244 245 vp = ap->a_vp; 246 ip = VTOI(vp); 247 fs = ip->i_e2fs; 248#ifdef UNKLAR 249 if (fs->fs_contigsumsize <= 0) 250 return (ENOSPC); 251#endif 252 buflist = ap->a_buflist; 253 len = buflist->bs_nchildren; 254 start_lbn = buflist->bs_children[0]->b_lblkno; 255 end_lbn = start_lbn + len - 1; 256#if DIAGNOSTIC 257 for (i = 1; i < len; i++) 258 if (buflist->bs_children[i]->b_lblkno != start_lbn + i) 259 panic("ext2_reallocblks: non-cluster"); 260#endif 261 /* 262 * If the latest allocation is in a new cylinder group, assume that 263 * the filesystem has decided to move and do not force it back to 264 * the previous cylinder group. 265 */ 266 if (dtog(fs, dbtofsb(fs, buflist->bs_children[0]->b_blkno)) != 267 dtog(fs, dbtofsb(fs, buflist->bs_children[len - 1]->b_blkno))) 268 return (ENOSPC); 269 if (ufs_getlbns(vp, start_lbn, start_ap, &start_lvl) || 270 ufs_getlbns(vp, end_lbn, end_ap, &end_lvl)) 271 return (ENOSPC); 272 /* 273 * Get the starting offset and block map for the first block. 274 */ 275 if (start_lvl == 0) { 276 sbap = &ip->i_db[0]; 277 soff = start_lbn; 278 } else { 279 idp = &start_ap[start_lvl - 1]; 280 if (bread(vp, idp->in_lbn, (int)fs->s_blocksize, NOCRED, &sbp)) { 281 brelse(sbp); 282 return (ENOSPC); 283 } 284 sbap = (daddr_t *)sbp->b_data; 285 soff = idp->in_off; 286 } 287 /* 288 * Find the preferred location for the cluster. 289 */ 290 pref = ext2_blkpref(ip, start_lbn, soff, sbap); 291 /* 292 * If the block range spans two block maps, get the second map. 293 */ 294 if (end_lvl == 0 || (idp = &end_ap[end_lvl - 1])->in_off + 1 >= len) { 295 ssize = len; 296 } else { 297#if DIAGNOSTIC 298 if (start_ap[start_lvl-1].in_lbn == idp->in_lbn) 299 panic("ext2_reallocblk: start == end"); 300#endif 301 ssize = len - (idp->in_off + 1); 302 if (bread(vp, idp->in_lbn, (int)fs->s_blocksize, NOCRED, &ebp)) 303 goto fail; 304 ebap = (daddr_t *)ebp->b_data; 305 } 306 /* 307 * Search the block map looking for an allocation of the desired size. 308 */ 309 if ((newblk = (daddr_t)ext2_hashalloc(ip, dtog(fs, pref), (long)pref, 310 len, (u_long (*)())ext2_clusteralloc)) == 0) 311 goto fail; 312 /* 313 * We have found a new contiguous block. 314 * 315 * First we have to replace the old block pointers with the new 316 * block pointers in the inode and indirect blocks associated 317 * with the file. 318 */ 319 blkno = newblk; 320 for (bap = &sbap[soff], i = 0; i < len; i++, blkno += fs->s_frags_per_block) { 321 if (i == ssize) 322 bap = ebap; 323#if DIAGNOSTIC 324 if (buflist->bs_children[i]->b_blkno != fsbtodb(fs, *bap)) 325 panic("ext2_reallocblks: alloc mismatch"); 326#endif 327 *bap++ = blkno; 328 } 329 /* 330 * Next we must write out the modified inode and indirect blocks. 331 * For strict correctness, the writes should be synchronous since 332 * the old block values may have been written to disk. In practise 333 * they are almost never written, but if we are concerned about 334 * strict correctness, the `doasyncfree' flag should be set to zero. 335 * 336 * The test on `doasyncfree' should be changed to test a flag 337 * that shows whether the associated buffers and inodes have 338 * been written. The flag should be set when the cluster is 339 * started and cleared whenever the buffer or inode is flushed. 340 * We can then check below to see if it is set, and do the 341 * synchronous write only when it has been cleared. 342 */ 343 if (sbap != &ip->i_db[0]) { 344 if (doasyncfree) 345 bdwrite(sbp); 346 else 347 bwrite(sbp); 348 } else { 349 ip->i_flag |= IN_CHANGE | IN_UPDATE; 350 if (!doasyncfree) { 351 gettime(&tv); 352 UFS_UPDATE(vp, &tv, &tv, MNT_WAIT); 353 } 354 } 355 if (ssize < len) 356 if (doasyncfree) 357 bdwrite(ebp); 358 else 359 bwrite(ebp); 360 /* 361 * Last, free the old blocks and assign the new blocks to the buffers. 362 */ 363 for (blkno = newblk, i = 0; i < len; i++, blkno += fs->s_frags_per_block) { 364 ext2_blkfree(ip, dbtofsb(fs, buflist->bs_children[i]->b_blkno), 365 fs->s_blocksize); 366 buflist->bs_children[i]->b_blkno = fsbtodb(fs, blkno); 367 } 368 return (0); 369 370fail: 371 if (ssize < len) 372 brelse(ebp); 373 if (sbap != &ip->i_db[0]) 374 brelse(sbp); 375 return (ENOSPC); 376 377#endif /* FANCY_REALLOC */ 378} 379 380/* 381 * Allocate an inode in the file system. 382 * 383 * we leave the actual allocation strategy to the (modified) 384 * ext2_new_inode(), to make sure we get the policies right 385 */ 386int 387ext2_valloc(pvp, mode, cred, vpp) 388 struct vnode *pvp; 389 int mode; 390 struct ucred *cred; 391 struct vnode **vpp; 392{ 393 register struct inode *pip; 394 register struct ext2_sb_info *fs; 395 register struct inode *ip; 396 ino_t ino; 397 int i, error; 398#if !defined(__FreeBSD__) 399 struct timeval time; 400#endif 401 402 *vpp = NULL; 403 pip = VTOI(pvp); 404 fs = pip->i_e2fs; 405 if (fs->s_es->s_free_inodes_count == 0) 406 goto noinodes; 407 408 /* call the Linux routine - it returns the inode number only */ 409 ino = ext2_new_inode(pip, mode); 410 411 if (ino == 0) 412 goto noinodes; 413 error = VFS_VGET(pvp->v_mount, ino, vpp); 414 if (error) { 415 UFS_VFREE(pvp, ino, mode); 416 return (error); 417 } 418 ip = VTOI(*vpp); 419 420 /* 421 the question is whether using VGET was such good idea at all - 422 Linux doesn't read the old inode in when it's allocating a 423 new one. I will set at least i_size & i_blocks the zero. 424 */ 425 ip->i_mode = 0; 426 ip->i_size = 0; 427 ip->i_blocks = 0; 428 ip->i_flags = 0; 429 /* now we want to make sure that the block pointers are zeroed out */ 430 for(i = 0; i < EXT2_NDIR_BLOCKS; i++) 431 ip->i_db[i] = 0; 432 433 /* 434 * Set up a new generation number for this inode. 435 * XXX check if this makes sense in ext2 436 */ 437#if !defined(__FreeBSD__) 438 gettime(&time); 439#endif 440 if (++nextgennumber < (u_long)time.tv_sec) 441 nextgennumber = time.tv_sec; 442 ip->i_gen = nextgennumber; 443/* 444printf("ext2_valloc: allocated inode %d\n", ino); 445*/ 446 return (0); 447noinodes: 448 ext2_fserr(fs, cred->cr_uid, "out of inodes"); 449 uprintf("\n%s: create/symlink failed, no inodes free\n", fs->fs_fsmnt); 450 return (ENOSPC); 451} 452 453/* 454 * Select the desired position for the next block in a file. 455 * 456 * we try to mimic what Remy does in inode_getblk/block_getblk 457 * 458 * we note: blocknr == 0 means that we're about to allocate either 459 * a direct block or a pointer block at the first level of indirection 460 * (In other words, stuff that will go in i_db[] or i_ib[]) 461 * 462 * blocknr != 0 means that we're allocating a block that is none 463 * of the above. Then, blocknr tells us the number of the block 464 * that will hold the pointer 465 */ 466daddr_t 467ext2_blkpref(ip, lbn, indx, bap, blocknr) 468 struct inode *ip; 469 daddr_t lbn; 470 int indx; 471 daddr_t *bap; 472 daddr_t blocknr; 473{ 474 int tmp; 475 476 /* if the next block is actually what we thought it is, 477 then set the goal to what we thought it should be 478 */ 479 if(ip->i_next_alloc_block == lbn) 480 return ip->i_next_alloc_goal; 481 482 /* now check whether we were provided with an array that basically 483 tells us previous blocks to which we want to stay closeby 484 */ 485 if(bap) 486 for (tmp = indx - 1; tmp >= 0; tmp--) 487 if (bap[tmp]) 488 return bap[tmp]; 489 490 /* else let's fall back to the blocknr, or, if there is none, 491 follow the rule that a block should be allocated near it's inode 492 */ 493 return blocknr ? blocknr : 494 (daddr_t)(ip->i_block_group * 495 EXT2_BLOCKS_PER_GROUP(ip->i_e2fs)) + 496 ip->i_e2fs->s_es->s_first_data_block; 497} 498 499/* 500 * Free a block or fragment. 501 * 502 * pass on to the Linux code 503 */ 504void 505ext2_blkfree(ip, bno, size) 506 register struct inode *ip; 507 daddr_t bno; 508 long size; 509{ 510 register struct ext2_sb_info *fs; 511 512 fs = ip->i_e2fs; 513 /* 514 * call Linux code with mount *, block number, count 515 */ 516 ext2_free_blocks(ITOV(ip)->v_mount, bno, size / fs->s_frag_size); 517} 518 519/* 520 * Free an inode. 521 * 522 * the maintenance of the actual bitmaps is again up to the linux code 523 */ 524int 525ext2_vfree(pvp, ino, mode) 526 struct vnode *pvp; 527 ino_t ino; 528 int mode; 529{ 530 register struct ext2_sb_info *fs; 531 register struct inode *pip; 532 533 pip = VTOI(pvp); 534 fs = pip->i_e2fs; 535 if ((u_int)ino >= fs->s_inodes_per_group * fs->s_groups_count) 536 panic("ifree: range: dev = 0x%x, ino = %d, fs = %s", 537 pip->i_dev, ino, fs->fs_fsmnt); 538 539/* ext2_debug("ext2_vfree (%d, %d) called\n", pip->i_number, mode); 540 */ 541 ext2_discard_prealloc(pip); 542 543 /* we need to make sure that ext2_free_inode can adjust the 544 used_dir_counts in the group summary information - I'd 545 really like to know what the rationale behind this 546 'set i_mode to zero to denote an unused inode' is 547 */ 548 mode = pip->i_mode; 549 pip->i_mode = mode; 550 ext2_free_inode(pip); 551 pip->i_mode = mode; 552 return (0); 553} 554 555/* 556 * Fserr prints the name of a file system with an error diagnostic. 557 * 558 * The form of the error message is: 559 * fs: error message 560 */ 561static void 562ext2_fserr(fs, uid, cp) 563 struct ext2_sb_info *fs; 564 u_int uid; 565 char *cp; 566{ 567 568 log(LOG_ERR, "uid %d on %s: %s\n", uid, fs->fs_fsmnt, cp); 569} 570