1 /* $FreeBSD: src/sys/msdosfs/msdosfs_fat.c,v 1.23 2000/01/27 14:43:06 nyan Exp $ */ 2 /* $NetBSD: msdosfs_fat.c,v 1.28 1997/11/17 15:36:49 ws Exp $ */ 3 4 /*- 5 * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. 6 * Copyright (C) 1994, 1995, 1997 TooLs GmbH. 7 * All rights reserved. 8 * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below). 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by TooLs GmbH. 21 * 4. The name of TooLs GmbH may not be used to endorse or promote products 22 * derived from this software without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 27 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 29 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 30 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 31 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 32 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 33 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 */ 35 /* 36 * Written by Paul Popelka (paulp@uts.amdahl.com) 37 * 38 * You can do anything you want with this software, just don't say you wrote 39 * it, and don't remove this notice. 40 * 41 * This software is provided "as is". 42 * 43 * The author supplies this software to be publicly redistributed on the 44 * understanding that the author is not responsible for the correct 45 * functioning of this software in any circumstances and is not liable for 46 * any damages caused by this software. 47 * 48 * October 1992 49 */ 50 51 /* 52 * kernel include files. 53 */ 54 #include <sys/param.h> 55 #include <sys/systm.h> 56 #include <sys/buf.h> 57 #include <sys/mount.h> /* to define statfs structure */ 58 #include <sys/vnode.h> /* to define vattr structure */ 59 60 #include <sys/buf2.h> 61 62 /* 63 * msdosfs include files. 64 */ 65 #include "bpb.h" 66 #include "msdosfsmount.h" 67 #include "direntry.h" 68 #include "denode.h" 69 #include "fat.h" 70 71 /* 72 * Fat cache stats. 73 */ 74 static int fc_fileextends; /* # of file extends */ 75 static int fc_lfcempty; /* # of time last file cluster cache entry 76 * was empty */ 77 static int fc_bmapcalls; /* # of times pcbmap was called */ 78 79 #define LMMAX 20 80 static int fc_lmdistance[LMMAX];/* counters for how far off the last 81 * cluster mapped entry was. */ 82 static int fc_largedistance; /* off by more than LMMAX */ 83 84 static void fc_lookup(struct denode *dep, u_long findcn, u_long *frcnp, 85 u_long *fsrcnp); 86 87 /* 88 * Given a byte offset `ofs` within FAT, return block number in backing device, 89 * block size, and byte offset within a block in FAT. 90 */ 91 static void 92 fatblock(struct msdosfsmount *pmp, u_long ofs, u_long *bnp, u_long *sizep, 93 u_long *bop) 94 { 95 u_long bn, size; 96 97 bn = ofs / pmp->pm_fatblocksize * pmp->pm_fatblocksec; 98 size = min(pmp->pm_fatblocksec, pmp->pm_FATsecs - bn) * DEV_BSIZE; 99 bn += pmp->pm_fatblk + pmp->pm_curfat * pmp->pm_FATsecs; 100 101 if (bnp) 102 *bnp = bn; 103 if (sizep) 104 *sizep = size; 105 if (bop) 106 *bop = ofs % pmp->pm_fatblocksize; 107 } 108 109 /* 110 * Map the logical cluster number of a file into a physical disk sector 111 * that is filesystem relative. 112 * 113 * dep - address of denode representing the file of interest 114 * findcn - file relative cluster whose filesystem relative cluster number 115 * and/or block number are/is to be found 116 * bnp - address of where to place the file system relative block number. 117 * If this pointer is null then don't return this quantity. 118 * cnp - address of where to place the file system relative cluster number. 119 * If this pointer is null then don't return this quantity. 120 * 121 * NOTE: Either bnp or cnp must be non-null. 122 * This function has one side effect. If the requested file relative cluster 123 * is beyond the end of file, then the actual number of clusters in the file 124 * is returned in *cnp. This is useful for determining how long a directory is. 125 * If cnp is null, nothing is returned. 126 */ 127 int 128 pcbmap(struct denode *dep, 129 u_long findcn, /* file relative cluster to get */ 130 daddr_t *bnp, /* returned filesys relative blk number */ 131 u_long *cnp, /* returned cluster number */ 132 int *sp) /* returned block size */ 133 { 134 int error; 135 u_long i; 136 u_long cn; 137 u_long prevcn = 0; /* XXX: prevcn could be used unititialized */ 138 u_long byteoffset; 139 u_long bn; 140 u_long bo; 141 struct buf *bp = NULL; 142 u_long bp_bn = -1; 143 struct msdosfsmount *pmp = dep->de_pmp; 144 u_long bsize; 145 146 fc_bmapcalls++; 147 148 /* 149 * If they don't give us someplace to return a value then don't 150 * bother doing anything. 151 */ 152 if (bnp == NULL && cnp == NULL && sp == NULL) 153 return (0); 154 155 cn = dep->de_StartCluster; 156 /* 157 * The "file" that makes up the root directory is contiguous, 158 * permanently allocated, of fixed size, and is not made up of 159 * clusters. If the cluster number is beyond the end of the root 160 * directory, then return the number of clusters in the file. 161 */ 162 if (cn == MSDOSFSROOT) { 163 if (dep->de_Attributes & ATTR_DIRECTORY) { 164 if (de_cn2off(pmp, findcn) >= dep->de_FileSize) { 165 if (cnp) 166 *cnp = de_bn2cn(pmp, 167 pmp->pm_rootdirsize); 168 return (E2BIG); 169 } 170 if (bnp) 171 *bnp = pmp->pm_rootdirblk + 172 de_cn2bn(pmp, findcn); 173 if (cnp) 174 *cnp = MSDOSFSROOT; 175 if (sp) 176 *sp = min(pmp->pm_bpcluster, 177 dep->de_FileSize - de_cn2off(pmp, findcn)); 178 return (0); 179 } else { /* just an empty file */ 180 if (cnp) 181 *cnp = 0; 182 return (E2BIG); 183 } 184 } 185 186 /* 187 * All other files do I/O in cluster sized blocks 188 */ 189 if (sp) 190 *sp = pmp->pm_bpcluster; 191 192 /* 193 * Rummage around in the fat cache, maybe we can avoid tromping 194 * thru every fat entry for the file. And, keep track of how far 195 * off the cache was from where we wanted to be. 196 */ 197 i = 0; 198 fc_lookup(dep, findcn, &i, &cn); 199 if ((bn = findcn - i) >= LMMAX) 200 fc_largedistance++; 201 else 202 fc_lmdistance[bn]++; 203 204 /* 205 * Handle all other files or directories the normal way. 206 */ 207 for (; i < findcn; i++) { 208 /* 209 * Stop with all reserved clusters, not just with EOF. 210 */ 211 if ((cn | ~pmp->pm_fatmask) >= CLUST_RSRVD) 212 goto hiteof; 213 byteoffset = FATOFS(pmp, cn); 214 fatblock(pmp, byteoffset, &bn, &bsize, &bo); 215 if (bn != bp_bn) { 216 if (bp) 217 brelse(bp); 218 error = bread(pmp->pm_devvp, de_bntodoff(pmp, bn), 219 bsize, &bp); 220 if (error) { 221 brelse(bp); 222 return (error); 223 } 224 bp_bn = bn; 225 } 226 prevcn = cn; 227 if (FAT32(pmp)) 228 cn = getulong(&bp->b_data[bo]); 229 else 230 cn = getushort(&bp->b_data[bo]); 231 if (FAT12(pmp) && (prevcn & 1)) 232 cn >>= 4; 233 cn &= pmp->pm_fatmask; 234 235 /* 236 * Force the special cluster numbers 237 * to be the same for all cluster sizes 238 * to let the rest of msdosfs handle 239 * all cases the same. 240 */ 241 if ((cn | ~pmp->pm_fatmask) >= CLUST_RSRVD) 242 cn |= ~pmp->pm_fatmask; 243 } 244 245 if (!MSDOSFSEOF(pmp, cn)) { 246 if (bp) 247 brelse(bp); 248 if (bnp) 249 *bnp = xcntobn(pmp, cn); 250 if (cnp) 251 *cnp = cn; 252 fc_setcache(dep, FC_LASTMAP, i, cn); 253 return (0); 254 } 255 256 hiteof: 257 if (cnp) 258 *cnp = i; 259 if (bp) 260 brelse(bp); 261 /* update last file cluster entry in the fat cache */ 262 fc_setcache(dep, FC_LASTFC, i - 1, prevcn); 263 return (E2BIG); 264 } 265 266 /* 267 * Find the closest entry in the fat cache to the cluster we are looking 268 * for. 269 */ 270 static void 271 fc_lookup(struct denode *dep, u_long findcn, u_long *frcnp, u_long *fsrcnp) 272 { 273 int i; 274 u_long cn; 275 struct fatcache *closest = NULL; 276 277 for (i = 0; i < FC_SIZE; i++) { 278 cn = dep->de_fc[i].fc_frcn; 279 if (cn != FCE_EMPTY && cn <= findcn) { 280 if (closest == NULL || cn > closest->fc_frcn) 281 closest = &dep->de_fc[i]; 282 } 283 } 284 if (closest) { 285 *frcnp = closest->fc_frcn; 286 *fsrcnp = closest->fc_fsrcn; 287 } 288 } 289 290 /* 291 * Purge the fat cache in denode dep of all entries relating to file 292 * relative cluster frcn and beyond. 293 */ 294 void 295 fc_purge(struct denode *dep, u_int frcn) 296 { 297 int i; 298 struct fatcache *fcp; 299 300 fcp = dep->de_fc; 301 for (i = 0; i < FC_SIZE; i++, fcp++) { 302 if (fcp->fc_frcn >= frcn) 303 fcp->fc_frcn = FCE_EMPTY; 304 } 305 } 306 307 /* 308 * Update the fat. 309 * If mirroring the fat, update all copies, with the first copy as last. 310 * Else update only the current fat (ignoring the others). 311 * 312 * pmp - msdosfsmount structure for filesystem to update 313 * bp - addr of modified fat block 314 * fatbn - block number relative to begin of filesystem of the modified fat block. 315 */ 316 static void 317 updatefats(struct msdosfsmount *pmp, struct buf *bp, u_long fatbn) 318 { 319 int i; 320 struct buf *bpn; 321 322 mprintf("updatefats(pmp %p, bp %p, fatbn %lu)\n", pmp, bp, fatbn); 323 324 /* 325 * If we have an FSInfo block, update it. 326 */ 327 if (pmp->pm_fsinfo) { 328 u_long cn = pmp->pm_nxtfree; 329 330 if (pmp->pm_freeclustercount 331 && (pmp->pm_inusemap[cn / N_INUSEBITS] 332 & (1 << (cn % N_INUSEBITS)))) { 333 /* 334 * The cluster indicated in FSInfo isn't free 335 * any longer. Got get a new free one. 336 */ 337 for (cn = 0; cn < pmp->pm_maxcluster; cn += N_INUSEBITS) 338 if (pmp->pm_inusemap[cn / N_INUSEBITS] != (u_int)-1) 339 break; 340 pmp->pm_nxtfree = cn 341 + ffs(pmp->pm_inusemap[cn / N_INUSEBITS] 342 ^ (u_int)-1) - 1; 343 } 344 if (bread(pmp->pm_devvp, de_bntodoff(pmp, pmp->pm_fsinfo), 345 fsi_size(pmp), &bpn) != 0) { 346 /* 347 * Ignore the error, but turn off FSInfo update for the future. 348 */ 349 pmp->pm_fsinfo = 0; 350 brelse(bpn); 351 } else { 352 struct fsinfo *fp = (struct fsinfo *)bpn->b_data; 353 354 putulong(fp->fsinfree, pmp->pm_freeclustercount); 355 putulong(fp->fsinxtfree, pmp->pm_nxtfree); 356 if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT) 357 bwrite(bpn); 358 else 359 bdwrite(bpn); 360 } 361 } 362 363 if (pmp->pm_flags & MSDOSFS_FATMIRROR) { 364 /* 365 * Now copy the block(s) of the modified fat to the other copies of 366 * the fat and write them out. This is faster than reading in the 367 * other fats and then writing them back out. This could tie up 368 * the fat for quite a while. Preventing others from accessing it. 369 * To prevent us from going after the fat quite so much we use 370 * delayed writes, unless they specfied "synchronous" when the 371 * filesystem was mounted. If synch is asked for then use 372 * bwrite()'s and really slow things down. 373 */ 374 for (i = 1; i < pmp->pm_FATs; i++) { 375 fatbn += pmp->pm_FATsecs; 376 /* getblk() never fails */ 377 bpn = getblk(pmp->pm_devvp, de_bntodoff(pmp, fatbn), 378 bp->b_bcount, 0, 0); 379 bcopy(bp->b_data, bpn->b_data, bp->b_bcount); 380 if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT) 381 bwrite(bpn); 382 else 383 bdwrite(bpn); 384 } 385 } 386 387 /* 388 * Write out the first (or current) fat last. 389 */ 390 if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT) 391 bwrite(bp); 392 else 393 bdwrite(bp); 394 /* 395 * Maybe update fsinfo sector here? 396 */ 397 } 398 399 /* 400 * Updating entries in 12 bit fats is a pain in the butt. 401 * 402 * The following picture shows where nibbles go when moving from a 12 bit 403 * cluster number into the appropriate bytes in the FAT. 404 * 405 * byte m byte m+1 byte m+2 406 * +----+----+ +----+----+ +----+----+ 407 * | 0 1 | | 2 3 | | 4 5 | FAT bytes 408 * +----+----+ +----+----+ +----+----+ 409 * 410 * +----+----+----+ +----+----+----+ 411 * | 3 0 1 | | 4 5 2 | 412 * +----+----+----+ +----+----+----+ 413 * cluster n cluster n+1 414 * 415 * Where n is even. m = n + (n >> 2) 416 * 417 */ 418 static __inline void 419 usemap_alloc(struct msdosfsmount *pmp, u_long cn) 420 { 421 pmp->pm_inusemap[cn / N_INUSEBITS] |= 1 << (cn % N_INUSEBITS); 422 pmp->pm_freeclustercount--; 423 } 424 425 static __inline void 426 usemap_free(struct msdosfsmount *pmp, u_long cn) 427 { 428 pmp->pm_freeclustercount++; 429 pmp->pm_inusemap[cn / N_INUSEBITS] &= ~(1 << (cn % N_INUSEBITS)); 430 } 431 432 int 433 clusterfree(struct msdosfsmount *pmp, u_long cluster, u_long *oldcnp) 434 { 435 int error; 436 u_long oldcn; 437 438 usemap_free(pmp, cluster); 439 error = fatentry(FAT_GET_AND_SET, pmp, cluster, &oldcn, MSDOSFSFREE); 440 if (error) { 441 usemap_alloc(pmp, cluster); 442 return (error); 443 } 444 /* 445 * If the cluster was successfully marked free, then update 446 * the count of free clusters, and turn off the "allocated" 447 * bit in the "in use" cluster bit map. 448 */ 449 if (oldcnp) 450 *oldcnp = oldcn; 451 return (0); 452 } 453 454 /* 455 * Get or Set or 'Get and Set' the cluster'th entry in the fat. 456 * 457 * function - whether to get or set a fat entry 458 * pmp - address of the msdosfsmount structure for the filesystem 459 * whose fat is to be manipulated. 460 * cn - which cluster is of interest 461 * oldcontents - address of a word that is to receive the contents of the 462 * cluster'th entry if this is a get function 463 * newcontents - the new value to be written into the cluster'th element of 464 * the fat if this is a set function. 465 * 466 * This function can also be used to free a cluster by setting the fat entry 467 * for a cluster to 0. 468 * 469 * All copies of the fat are updated if this is a set function. NOTE: If 470 * fatentry() marks a cluster as free it does not update the inusemap in 471 * the msdosfsmount structure. This is left to the caller. 472 */ 473 int 474 fatentry(int function, struct msdosfsmount *pmp, u_long cn, u_long *oldcontents, 475 u_long newcontents) 476 { 477 int error; 478 u_long readcn; 479 u_long bn, bo, bsize, byteoffset; 480 struct buf *bp; 481 482 mprintf("fatentry(func %d, pmp %p, clust %lu, oldcon %p, newcon %lx)\n", 483 function, pmp, cn, oldcontents, newcontents); 484 485 #ifdef DIAGNOSTIC 486 /* 487 * Be sure they asked us to do something. 488 */ 489 if ((function & (FAT_SET | FAT_GET)) == 0) { 490 kprintf("fatentry(): function code doesn't specify get or set\n"); 491 return (EINVAL); 492 } 493 494 /* 495 * If they asked us to return a cluster number but didn't tell us 496 * where to put it, give them an error. 497 */ 498 if ((function & FAT_GET) && oldcontents == NULL) { 499 kprintf("fatentry(): get function with no place to put result\n"); 500 return (EINVAL); 501 } 502 #endif 503 504 /* 505 * Be sure the requested cluster is in the filesystem. 506 */ 507 if (cn < CLUST_FIRST || cn > pmp->pm_maxcluster) 508 return (EINVAL); 509 510 byteoffset = FATOFS(pmp, cn); 511 fatblock(pmp, byteoffset, &bn, &bsize, &bo); 512 error = bread(pmp->pm_devvp, de_bntodoff(pmp, bn), bsize, &bp); 513 if (error) { 514 brelse(bp); 515 return (error); 516 } 517 518 if (function & FAT_GET) { 519 if (FAT32(pmp)) 520 readcn = getulong(&bp->b_data[bo]); 521 else 522 readcn = getushort(&bp->b_data[bo]); 523 if (FAT12(pmp) & (cn & 1)) 524 readcn >>= 4; 525 readcn &= pmp->pm_fatmask; 526 /* map reserved fat entries to same values for all fats */ 527 if ((readcn | ~pmp->pm_fatmask) >= CLUST_RSRVD) 528 readcn |= ~pmp->pm_fatmask; 529 *oldcontents = readcn; 530 } 531 if (function & FAT_SET) { 532 switch (pmp->pm_fatmask) { 533 case FAT12_MASK: 534 readcn = getushort(&bp->b_data[bo]); 535 if (cn & 1) { 536 readcn &= 0x000f; 537 readcn |= newcontents << 4; 538 } else { 539 readcn &= 0xf000; 540 readcn |= newcontents & 0xfff; 541 } 542 putushort(&bp->b_data[bo], readcn); 543 break; 544 case FAT16_MASK: 545 putushort(&bp->b_data[bo], newcontents); 546 break; 547 case FAT32_MASK: 548 /* 549 * According to spec we have to retain the 550 * high order bits of the fat entry. 551 */ 552 readcn = getulong(&bp->b_data[bo]); 553 readcn &= ~FAT32_MASK; 554 readcn |= newcontents & FAT32_MASK; 555 putulong(&bp->b_data[bo], readcn); 556 break; 557 } 558 updatefats(pmp, bp, bn); 559 bp = NULL; 560 pmp->pm_fmod = 1; 561 } 562 if (bp) 563 brelse(bp); 564 return (0); 565 } 566 567 /* 568 * Update a contiguous cluster chain 569 * 570 * pmp - mount point 571 * start - first cluster of chain 572 * count - number of clusters in chain 573 * fillwith - what to write into fat entry of last cluster 574 */ 575 static int 576 fatchain(struct msdosfsmount *pmp, u_long start, u_long count, u_long fillwith) 577 { 578 int error; 579 u_long bn, bo, bsize, byteoffset, readcn, newc; 580 struct buf *bp; 581 582 mprintf("fatchain(pmp %p, start %lu, count %lu, fillwith %lx)\n", 583 pmp, start, count, fillwith); 584 /* 585 * Be sure the clusters are in the filesystem. 586 */ 587 if (start < CLUST_FIRST || start + count - 1 > pmp->pm_maxcluster) 588 return (EINVAL); 589 590 while (count > 0) { 591 byteoffset = FATOFS(pmp, start); 592 fatblock(pmp, byteoffset, &bn, &bsize, &bo); 593 error = bread(pmp->pm_devvp, de_bntodoff(pmp, bn), bsize, &bp); 594 if (error) { 595 brelse(bp); 596 return (error); 597 } 598 while (count > 0) { 599 start++; /* Callers must guarantee contiguous free 600 clusters. */ 601 newc = --count > 0 ? start : fillwith; 602 switch (pmp->pm_fatmask) { 603 case FAT12_MASK: 604 readcn = getushort(&bp->b_data[bo]); 605 if (start & 1) { 606 readcn &= 0xf000; 607 readcn |= newc & 0xfff; 608 } else { 609 readcn &= 0x000f; 610 readcn |= newc << 4; 611 } 612 putushort(&bp->b_data[bo], readcn); 613 bo++; 614 if (!(start & 1)) 615 bo++; 616 break; 617 case FAT16_MASK: 618 putushort(&bp->b_data[bo], newc); 619 bo += 2; 620 break; 621 case FAT32_MASK: 622 readcn = getulong(&bp->b_data[bo]); 623 readcn &= ~pmp->pm_fatmask; 624 readcn |= newc & pmp->pm_fatmask; 625 putulong(&bp->b_data[bo], readcn); 626 bo += 4; 627 break; 628 } 629 if (bo >= bsize) 630 break; 631 } 632 updatefats(pmp, bp, bn); 633 } 634 pmp->pm_fmod = 1; 635 return (0); 636 } 637 638 /* 639 * Check the length of a free cluster chain starting at start. 640 * 641 * pmp - mount point 642 * start - start of chain 643 * count - maximum interesting length 644 */ 645 static int 646 chainlength(struct msdosfsmount *pmp, u_long start, u_long count) 647 { 648 u_long idx, max_idx; 649 u_int map; 650 u_long len; 651 652 max_idx = pmp->pm_maxcluster / N_INUSEBITS; 653 idx = start / N_INUSEBITS; 654 start %= N_INUSEBITS; 655 map = pmp->pm_inusemap[idx]; 656 map &= ~((1 << start) - 1); 657 if (map) { 658 len = ffs(map) - 1 - start; 659 return (len > count ? count : len); 660 } 661 len = N_INUSEBITS - start; 662 if (len >= count) 663 return (count); 664 while (++idx <= max_idx) { 665 if (len >= count) 666 break; 667 map = pmp->pm_inusemap[idx]; 668 if (map) { 669 len += ffs(map) - 1; 670 break; 671 } 672 len += N_INUSEBITS; 673 } 674 return (len > count ? count : len); 675 } 676 677 /* 678 * Allocate contigous free clusters. 679 * 680 * pmp - mount point. 681 * start - start of cluster chain. 682 * count - number of clusters to allocate. 683 * fillwith - put this value into the fat entry for the 684 * last allocated cluster. 685 * retcluster - put the first allocated cluster's number here. 686 * got - how many clusters were actually allocated. 687 */ 688 static int 689 chainalloc(struct msdosfsmount *pmp, u_long start, u_long count, 690 u_long fillwith, u_long *retcluster, u_long *got) 691 { 692 int error; 693 u_long cl, n; 694 695 for (cl = start, n = count; n-- > 0;) 696 usemap_alloc(pmp, cl++); 697 698 error = fatchain(pmp, start, count, fillwith); 699 if (error != 0) 700 return (error); 701 mprintf("clusteralloc(): allocated cluster chain at %lu (%lu clusters)\n", 702 start, count); 703 if (retcluster) 704 *retcluster = start; 705 if (got) 706 *got = count; 707 return (0); 708 } 709 710 /* 711 * Allocate contiguous free clusters. 712 * 713 * pmp - mount point. 714 * start - preferred start of cluster chain. 715 * count - number of clusters requested. 716 * fillwith - put this value into the fat entry for the 717 * last allocated cluster. 718 * retcluster - put the first allocated cluster's number here. 719 * got - how many clusters were actually allocated. 720 */ 721 int 722 clusteralloc(struct msdosfsmount *pmp, u_long start, u_long count, 723 u_long fillwith, u_long *retcluster, u_long *got) 724 { 725 u_long idx; 726 u_long len, newst, foundl, cn, l; 727 u_long foundcn = 0; /* XXX: foundcn could be used unititialized */ 728 u_int map; 729 730 mprintf("clusteralloc(): find %lu clusters\n",count); 731 if (start) { 732 if ((len = chainlength(pmp, start, count)) >= count) 733 return (chainalloc(pmp, start, count, fillwith, 734 retcluster, got)); 735 } else 736 len = 0; 737 738 /* 739 * Start at a (pseudo) random place to maximize cluster runs 740 * under multiple writers. 741 */ 742 newst = krandom() % (pmp->pm_maxcluster + 1); 743 foundl = 0; 744 745 for (cn = newst; cn <= pmp->pm_maxcluster;) { 746 idx = cn / N_INUSEBITS; 747 map = pmp->pm_inusemap[idx]; 748 map |= (1 << (cn % N_INUSEBITS)) - 1; 749 if (map != (u_int)-1) { 750 cn = idx * N_INUSEBITS + ffs(map^(u_int)-1) - 1; 751 if ((l = chainlength(pmp, cn, count)) >= count) 752 return (chainalloc(pmp, cn, count, fillwith, 753 retcluster, got)); 754 if (l > foundl) { 755 foundcn = cn; 756 foundl = l; 757 } 758 cn += l + 1; 759 continue; 760 } 761 cn += N_INUSEBITS - cn % N_INUSEBITS; 762 } 763 for (cn = 0; cn < newst;) { 764 idx = cn / N_INUSEBITS; 765 map = pmp->pm_inusemap[idx]; 766 map |= (1 << (cn % N_INUSEBITS)) - 1; 767 if (map != (u_int)-1) { 768 cn = idx * N_INUSEBITS + ffs(map^(u_int)-1) - 1; 769 if ((l = chainlength(pmp, cn, count)) >= count) 770 return (chainalloc(pmp, cn, count, fillwith, 771 retcluster, got)); 772 if (l > foundl) { 773 foundcn = cn; 774 foundl = l; 775 } 776 cn += l + 1; 777 continue; 778 } 779 cn += N_INUSEBITS - cn % N_INUSEBITS; 780 } 781 782 if (!foundl) 783 return (ENOSPC); 784 785 if (len) 786 return (chainalloc(pmp, start, len, fillwith, retcluster, got)); 787 else 788 return (chainalloc(pmp, foundcn, foundl, fillwith, retcluster, 789 got)); 790 } 791 792 793 /* 794 * Free a chain of clusters. 795 * 796 * pmp - address of the msdosfs mount structure for the filesystem 797 * containing the cluster chain to be freed. 798 * startcluster - number of the 1st cluster in the chain of clusters to be 799 * freed. 800 */ 801 int 802 freeclusterchain(struct msdosfsmount *pmp, u_long cluster) 803 { 804 int error; 805 struct buf *bp = NULL; 806 u_long bn, bo, bsize, byteoffset; 807 u_long readcn, lbn = -1; 808 809 while (cluster >= CLUST_FIRST && cluster <= pmp->pm_maxcluster) { 810 byteoffset = FATOFS(pmp, cluster); 811 fatblock(pmp, byteoffset, &bn, &bsize, &bo); 812 if (lbn != bn) { 813 if (bp) 814 updatefats(pmp, bp, lbn); 815 error = bread(pmp->pm_devvp, de_bntodoff(pmp, bn), 816 bsize, &bp); 817 if (error) { 818 brelse(bp); 819 return (error); 820 } 821 lbn = bn; 822 } 823 usemap_free(pmp, cluster); 824 switch (pmp->pm_fatmask) { 825 case FAT12_MASK: 826 readcn = getushort(&bp->b_data[bo]); 827 if (cluster & 1) { 828 cluster = readcn >> 4; 829 readcn &= 0x000f; 830 readcn |= MSDOSFSFREE << 4; 831 } else { 832 cluster = readcn; 833 readcn &= 0xf000; 834 readcn |= MSDOSFSFREE & 0xfff; 835 } 836 putushort(&bp->b_data[bo], readcn); 837 break; 838 case FAT16_MASK: 839 cluster = getushort(&bp->b_data[bo]); 840 putushort(&bp->b_data[bo], MSDOSFSFREE); 841 break; 842 case FAT32_MASK: 843 cluster = getulong(&bp->b_data[bo]); 844 putulong(&bp->b_data[bo], 845 (MSDOSFSFREE & FAT32_MASK) | 846 (cluster & ~FAT32_MASK)); 847 break; 848 } 849 cluster &= pmp->pm_fatmask; 850 if ((cluster | ~pmp->pm_fatmask) >= CLUST_RSRVD) 851 cluster |= pmp->pm_fatmask; 852 } 853 if (bp) 854 updatefats(pmp, bp, bn); 855 return (0); 856 } 857 858 /* 859 * Read in fat blocks looking for free clusters. For every free cluster 860 * found turn off its corresponding bit in the pm_inusemap. 861 */ 862 int 863 fillinusemap(struct msdosfsmount *pmp) 864 { 865 struct buf *bp = NULL; 866 u_long cn, readcn; 867 int error; 868 u_long bn, bo, bsize, byteoffset; 869 870 /* 871 * Mark all clusters in use, we mark the free ones in the fat scan 872 * loop further down. 873 */ 874 for (cn = 0; cn < (pmp->pm_maxcluster + N_INUSEBITS) / N_INUSEBITS; cn++) 875 pmp->pm_inusemap[cn] = (u_int)-1; 876 877 /* 878 * Figure how many free clusters are in the filesystem by ripping 879 * through the fat counting the number of entries whose content is 880 * zero. These represent free clusters. 881 */ 882 pmp->pm_freeclustercount = 0; 883 for (cn = CLUST_FIRST; cn <= pmp->pm_maxcluster; cn++) { 884 byteoffset = FATOFS(pmp, cn); 885 bo = byteoffset % pmp->pm_fatblocksize; 886 if (!bo || !bp) { 887 /* Read new FAT block */ 888 if (bp) 889 brelse(bp); 890 fatblock(pmp, byteoffset, &bn, &bsize, NULL); 891 error = bread(pmp->pm_devvp, de_bntodoff(pmp, bn), 892 bsize, &bp); 893 if (error) { 894 brelse(bp); 895 return (error); 896 } 897 } 898 if (FAT32(pmp)) 899 readcn = getulong(&bp->b_data[bo]); 900 else 901 readcn = getushort(&bp->b_data[bo]); 902 if (FAT12(pmp) && (cn & 1)) 903 readcn >>= 4; 904 readcn &= pmp->pm_fatmask; 905 906 if (readcn == 0) 907 usemap_free(pmp, cn); 908 } 909 brelse(bp); 910 return (0); 911 } 912 913 /* 914 * Allocate a new cluster and chain it onto the end of the file. 915 * 916 * dep - the file to extend 917 * count - number of clusters to allocate 918 * bpp - where to return the address of the buf header for the first new 919 * file block 920 * ncp - where to put cluster number of the first newly allocated cluster 921 * If this pointer is 0, do not return the cluster number. 922 * flags - see fat.h 923 * 924 * NOTE: This function is not responsible for turning on the DE_UPDATE bit of 925 * the de_flag field of the denode and it does not change the de_FileSize 926 * field. This is left for the caller to do. 927 */ 928 int 929 extendfile(struct denode *dep, u_long count, struct buf **bpp, u_long *ncp, 930 int flags) 931 { 932 int error; 933 u_long frcn; 934 u_long cn, got; 935 struct msdosfsmount *pmp = dep->de_pmp; 936 struct buf *bp; 937 938 /* 939 * Don't try to extend the root directory 940 */ 941 if (dep->de_StartCluster == MSDOSFSROOT 942 && (dep->de_Attributes & ATTR_DIRECTORY)) { 943 kprintf("extendfile(): attempt to extend root directory\n"); 944 return (ENOSPC); 945 } 946 947 /* 948 * If the "file's last cluster" cache entry is empty, and the file 949 * is not empty, then fill the cache entry by calling pcbmap(). 950 */ 951 fc_fileextends++; 952 if (dep->de_fc[FC_LASTFC].fc_frcn == FCE_EMPTY && 953 dep->de_StartCluster != 0) { 954 fc_lfcempty++; 955 error = pcbmap(dep, 0xffff, NULL, &cn, NULL); 956 /* we expect it to return E2BIG */ 957 if (error != E2BIG) 958 return (error); 959 } 960 961 while (count > 0) { 962 /* 963 * Allocate a new cluster chain and cat onto the end of the 964 * file. * If the file is empty we make de_StartCluster point 965 * to the new block. Note that de_StartCluster being 0 is 966 * sufficient to be sure the file is empty since we exclude 967 * attempts to extend the root directory above, and the root 968 * dir is the only file with a startcluster of 0 that has 969 * blocks allocated (sort of). 970 */ 971 if (dep->de_StartCluster == 0) 972 cn = 0; 973 else 974 cn = dep->de_fc[FC_LASTFC].fc_fsrcn + 1; 975 error = clusteralloc(pmp, cn, count, CLUST_EOFE, &cn, &got); 976 if (error) 977 return (error); 978 979 count -= got; 980 981 /* 982 * Give them the filesystem relative cluster number if they want 983 * it. 984 */ 985 if (ncp) { 986 *ncp = cn; 987 ncp = NULL; 988 } 989 990 if (dep->de_StartCluster == 0) { 991 dep->de_StartCluster = cn; 992 frcn = 0; 993 } else { 994 error = fatentry(FAT_SET, pmp, 995 dep->de_fc[FC_LASTFC].fc_fsrcn, 996 0, cn); 997 if (error) { 998 clusterfree(pmp, cn, NULL); 999 return (error); 1000 } 1001 frcn = dep->de_fc[FC_LASTFC].fc_frcn + 1; 1002 } 1003 1004 /* 1005 * Update the "last cluster of the file" entry in the 1006 * denode's fat cache. 1007 */ 1008 fc_setcache(dep, FC_LASTFC, frcn + got - 1, cn + got - 1); 1009 1010 if (flags & DE_CLEAR) { 1011 while (got-- > 0) { 1012 /* 1013 * Get the buf header for the new block of the file. 1014 */ 1015 if (dep->de_Attributes & ATTR_DIRECTORY) { 1016 bp = getblk(pmp->pm_devvp, 1017 xcntodoff(pmp, cn), 1018 pmp->pm_bpcluster, 0, 0); 1019 ++cn; 1020 } else { 1021 daddr_t dblkno; 1022 1023 bp = getblk(DETOV(dep), 1024 de_cn2doff(pmp, frcn), 1025 pmp->pm_bpcluster, 0, 0); 1026 ++frcn; 1027 /* 1028 * Do the bmap now, as in msdosfs_write 1029 */ 1030 if (pcbmap(dep, 1031 de_bn2cn(pmp, de_off2bn(pmp, 1032 bp->b_bio1.bio_offset)), 1033 &dblkno, NULL, NULL)) { 1034 bp->b_bio2.bio_offset = NOOFFSET; 1035 } else { 1036 bp->b_bio2.bio_offset = de_bntodoff(pmp, dblkno); 1037 } 1038 if (bp->b_bio2.bio_offset == NOOFFSET) 1039 panic("extendfile: pcbmap"); 1040 } 1041 clrbuf(bp); 1042 if (bpp) { 1043 *bpp = bp; 1044 bpp = NULL; 1045 } else 1046 bdwrite(bp); 1047 } 1048 } 1049 } 1050 1051 return (0); 1052 } 1053