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