1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * Routines to allocate and deallocate data blocks on the disk 30 */ 31 32 #include <sys/param.h> 33 #include <sys/errno.h> 34 #include <sys/buf.h> 35 #include <sys/vfs.h> 36 #include <sys/vnode.h> 37 #include <sys/cmn_err.h> 38 #include <sys/debug.h> 39 #include <sys/sysmacros.h> 40 #include <sys/systm.h> 41 #include <sys/fs/pc_label.h> 42 #include <sys/fs/pc_fs.h> 43 #include <sys/fs/pc_dir.h> 44 #include <sys/fs/pc_node.h> 45 46 static pc_cluster32_t pc_getcluster(struct pcfs *fsp, pc_cluster32_t cn); 47 48 /* 49 * Convert file logical block (cluster) numbers to disk block numbers. 50 * Also return number of physically contiguous blocks if asked for. 51 * Used for reading only. Use pc_balloc for writing. 52 */ 53 int 54 pc_bmap( 55 struct pcnode *pcp, /* pcnode for file */ 56 daddr_t lcn, /* logical cluster no */ 57 daddr_t *dbnp, /* ptr to phys block no */ 58 uint_t *contigbp) /* ptr to number of contiguous bytes */ 59 /* may be zero if not wanted */ 60 { 61 struct pcfs *fsp; /* pcfs that file is in */ 62 struct vnode *vp; 63 pc_cluster32_t cn, ncn; /* current, next cluster number */ 64 daddr_t olcn = lcn; 65 66 vp = PCTOV(pcp); 67 fsp = VFSTOPCFS(vp->v_vfsp); 68 69 if (lcn < 0) 70 return (ENOENT); 71 72 /* 73 * FAT12 / FAT16 root directories are a continuous section on disk 74 * before the actual data clusters. Specialcase this here. 75 */ 76 if (!IS_FAT32(fsp) && (vp->v_flag & VROOT)) { 77 daddr_t lbn; /* logical (disk) block number */ 78 79 lbn = pc_cltodb(fsp, lcn); 80 if (lbn >= fsp->pcfs_rdirsec) { 81 PC_DPRINTF0(2, "pc_bmap: ENOENT1\n"); 82 return (ENOENT); 83 } 84 *dbnp = pc_dbdaddr(fsp, fsp->pcfs_rdirstart + lbn); 85 if (contigbp) { 86 ASSERT (*contigbp >= fsp->pcfs_secsize); 87 *contigbp = MIN(*contigbp, 88 fsp->pcfs_secsize * (fsp->pcfs_rdirsec - lbn)); 89 } 90 return (0); 91 } 92 93 if (lcn >= fsp->pcfs_ncluster) { 94 PC_DPRINTF0(2, "pc_bmap: ENOENT2\n"); 95 return (ENOENT); 96 } 97 if (vp->v_type == VREG && 98 (pcp->pc_size == 0 || 99 lcn >= (daddr_t)howmany((offset_t)pcp->pc_size, 100 fsp->pcfs_clsize))) { 101 PC_DPRINTF0(2, "pc_bmap: ENOENT3\n"); 102 return (ENOENT); 103 } 104 ncn = pcp->pc_scluster; 105 if (IS_FAT32(fsp) && ncn == 0) 106 ncn = fsp->pcfs_rdirstart; 107 108 /* Do we have a cached index/cluster pair? */ 109 if (pcp->pc_lindex > 0 && lcn >= pcp->pc_lindex) { 110 lcn -= pcp->pc_lindex; 111 ncn = pcp->pc_lcluster; 112 } 113 do { 114 cn = ncn; 115 if (!pc_validcl(fsp, cn)) { 116 if (IS_FAT32(fsp) && cn >= PCF_LASTCLUSTER32 && 117 vp->v_type == VDIR) { 118 PC_DPRINTF0(2, "pc_bmap: ENOENT4\n"); 119 return (ENOENT); 120 } else if (!IS_FAT32(fsp) && 121 cn >= PCF_LASTCLUSTER && 122 vp->v_type == VDIR) { 123 PC_DPRINTF0(2, "pc_bmap: ENOENT5\n"); 124 return (ENOENT); 125 } else { 126 PC_DPRINTF1(1, 127 "pc_bmap: badfs cn=%d\n", cn); 128 (void) pc_badfs(fsp); 129 return (EIO); 130 } 131 } 132 ncn = pc_getcluster(fsp, cn); 133 } while (lcn--); 134 135 /* 136 * Cache this cluster, as we'll most likely visit the 137 * one after this next time. Considerably improves 138 * performance on sequential reads and writes. 139 */ 140 pcp->pc_lindex = olcn; 141 pcp->pc_lcluster = cn; 142 *dbnp = pc_cldaddr(fsp, cn); 143 144 if (contigbp && *contigbp > fsp->pcfs_clsize) { 145 uint_t count = fsp->pcfs_clsize; 146 147 while ((cn + 1) == ncn && count < *contigbp && 148 pc_validcl(fsp, ncn)) { 149 count += fsp->pcfs_clsize; 150 cn = ncn; 151 ncn = pc_getcluster(fsp, ncn); 152 } 153 *contigbp = count; 154 } 155 return (0); 156 } 157 158 /* 159 * Allocate file logical blocks (clusters). 160 * Return disk address of last allocated cluster. 161 */ 162 int 163 pc_balloc( 164 struct pcnode *pcp, /* pcnode for file */ 165 daddr_t lcn, /* logical cluster no */ 166 int zwrite, /* zerofill blocks? */ 167 daddr_t *dbnp) /* ptr to phys block no */ 168 { 169 struct pcfs *fsp; /* pcfs that file is in */ 170 struct vnode *vp; 171 pc_cluster32_t cn; /* current cluster number */ 172 pc_cluster32_t ncn; /* next cluster number */ 173 174 vp = PCTOV(pcp); 175 fsp = VFSTOPCFS(vp -> v_vfsp); 176 177 if (lcn < 0) { 178 return (EFBIG); 179 } 180 181 /* 182 * Again, FAT12/FAT16 root directories are not data clusters. 183 */ 184 if (!IS_FAT32(fsp) && (vp->v_flag & VROOT)) { 185 daddr_t lbn; 186 187 lbn = pc_cltodb(fsp, lcn); 188 if (lbn >= fsp->pcfs_rdirsec) 189 return (ENOSPC); 190 *dbnp = pc_dbdaddr(fsp, fsp->pcfs_rdirstart + lbn); 191 return (0); 192 } 193 194 if (lcn >= fsp->pcfs_ncluster) 195 return (ENOSPC); 196 if ((vp->v_type == VREG && pcp->pc_size == 0) || 197 (vp->v_type == VDIR && lcn == 0)) { 198 switch (cn = pc_alloccluster(fsp, 1)) { 199 case PCF_FREECLUSTER: 200 return (ENOSPC); 201 case PCF_ERRORCLUSTER: 202 return (EIO); 203 } 204 pcp->pc_scluster = cn; 205 } else { 206 cn = pcp->pc_scluster; 207 if (IS_FAT32(fsp) && cn == 0) 208 cn = fsp->pcfs_rdirstart; 209 if (!pc_validcl(fsp, cn)) { 210 PC_DPRINTF1(1, "pc_balloc: badfs cn=%d\n", cn); 211 (void) pc_badfs(fsp); 212 return (EIO); 213 } 214 } 215 216 if (pcp->pc_lindex > 0 && lcn > pcp->pc_lindex) { 217 lcn -= pcp->pc_lindex; 218 cn = pcp->pc_lcluster; 219 } 220 while (lcn-- > 0) { 221 ncn = pc_getcluster(fsp, cn); 222 if ((IS_FAT32(fsp) && ncn >= PCF_LASTCLUSTER32) || 223 (!IS_FAT32(fsp) && ncn >= PCF_LASTCLUSTER)) { 224 /* 225 * Extend file (no holes). 226 */ 227 switch (ncn = pc_alloccluster(fsp, zwrite)) { 228 case PCF_FREECLUSTER: 229 return (ENOSPC); 230 case PCF_ERRORCLUSTER: 231 return (EIO); 232 } 233 pc_setcluster(fsp, cn, ncn); 234 } else if (!pc_validcl(fsp, ncn)) { 235 PC_DPRINTF1(1, 236 "pc_balloc: badfs ncn=%d\n", ncn); 237 (void) pc_badfs(fsp); 238 return (EIO); 239 } 240 cn = ncn; 241 } 242 /* 243 * Do not cache the new cluster/index values; when 244 * extending the file we're interested in the last 245 * written cluster and not the last cluster allocated. 246 */ 247 *dbnp = pc_cldaddr(fsp, cn); 248 249 return (0); 250 } 251 252 /* 253 * Free file cluster chain after the first skipcl clusters. 254 */ 255 int 256 pc_bfree(struct pcnode *pcp, pc_cluster32_t skipcl) 257 { 258 struct pcfs *fsp; 259 pc_cluster32_t cn; 260 pc_cluster32_t ncn; 261 int n; 262 struct vnode *vp; 263 264 vp = PCTOV(pcp); 265 fsp = VFSTOPCFS(vp->v_vfsp); 266 if (!IS_FAT32(fsp) && (vp->v_flag & VROOT)) { 267 panic("pc_bfree"); 268 } 269 270 if (pcp->pc_size == 0 && vp->v_type == VREG) { 271 return (0); 272 } 273 if (vp->v_type == VREG) { 274 n = (int)howmany((offset_t)pcp->pc_size, fsp->pcfs_clsize); 275 if (n > fsp->pcfs_ncluster) { 276 PC_DPRINTF1(1, "pc_bfree: badfs n=%d\n", n); 277 (void) pc_badfs(fsp); 278 return (EIO); 279 } 280 } else { 281 n = fsp->pcfs_ncluster; 282 } 283 cn = pcp->pc_scluster; 284 if (IS_FAT32(fsp) && cn == 0) 285 cn = fsp->pcfs_rdirstart; 286 if (skipcl == 0) { 287 if (IS_FAT32(fsp)) 288 pcp->pc_scluster = PCF_LASTCLUSTERMARK32; 289 else 290 pcp->pc_scluster = PCF_LASTCLUSTERMARK; 291 } 292 293 /* Invalidate last used cluster cache */ 294 pcp->pc_lindex = 0; 295 pcp->pc_lcluster = pcp->pc_scluster; 296 297 while (n--) { 298 if (!pc_validcl(fsp, cn)) { 299 PC_DPRINTF1(1, "pc_bfree: badfs cn=%d\n", cn); 300 (void) pc_badfs(fsp); 301 return (EIO); 302 } 303 ncn = pc_getcluster(fsp, cn); 304 if (skipcl == 0) { 305 pc_setcluster(fsp, cn, PCF_FREECLUSTER); 306 } else { 307 skipcl--; 308 if (skipcl == 0) { 309 if (IS_FAT32(fsp)) { 310 pc_setcluster(fsp, cn, 311 PCF_LASTCLUSTERMARK32); 312 } else 313 pc_setcluster(fsp, cn, 314 PCF_LASTCLUSTERMARK); 315 } 316 } 317 if (IS_FAT32(fsp) && ncn >= PCF_LASTCLUSTER32 && 318 vp->v_type == VDIR) 319 break; 320 if (!IS_FAT32(fsp) && ncn >= PCF_LASTCLUSTER && 321 vp->v_type == VDIR) 322 break; 323 cn = ncn; 324 } 325 return (0); 326 } 327 328 /* 329 * Return the number of free blocks in the filesystem. 330 */ 331 int 332 pc_freeclusters(struct pcfs *fsp) 333 { 334 pc_cluster32_t cn; 335 int free = 0; 336 337 if (IS_FAT32(fsp) && 338 fsp->pcfs_fsinfo.fs_free_clusters != FSINFO_UNKNOWN) 339 return (fsp->pcfs_fsinfo.fs_free_clusters); 340 341 /* 342 * make sure the FAT is in core 343 */ 344 for (cn = PCF_FIRSTCLUSTER; 345 (int)cn < fsp->pcfs_ncluster; cn++) { 346 if (pc_getcluster(fsp, cn) == PCF_FREECLUSTER) { 347 free++; 348 } 349 } 350 351 if (IS_FAT32(fsp)) { 352 ASSERT(fsp->pcfs_fsinfo.fs_free_clusters == FSINFO_UNKNOWN); 353 fsp->pcfs_fsinfo.fs_free_clusters = free; 354 } 355 return (free); 356 } 357 358 /* 359 * Cluster manipulation routines. 360 * FAT must be resident. 361 */ 362 363 /* 364 * Get the next cluster in the file cluster chain. 365 * cn = current cluster number in chain 366 */ 367 static pc_cluster32_t 368 pc_getcluster(struct pcfs *fsp, pc_cluster32_t cn) 369 { 370 unsigned char *fp; 371 372 if (fsp->pcfs_fatp == (uchar_t *)0 || !pc_validcl(fsp, cn)) 373 panic("pc_getcluster"); 374 375 switch (fsp->pcfs_fattype) { 376 case FAT32: 377 fp = fsp->pcfs_fatp + (cn << 2); 378 cn = ltohi(*(pc_cluster32_t *)fp); 379 break; 380 case FAT16: 381 fp = fsp->pcfs_fatp + (cn << 1); 382 cn = ltohs(*(pc_cluster16_t *)fp); 383 break; 384 case FAT12: 385 fp = fsp->pcfs_fatp + (cn + (cn >> 1)); 386 if (cn & 01) { 387 cn = (((unsigned int)*fp++ & 0xf0) >> 4); 388 cn += (*fp << 4); 389 } else { 390 cn = *fp++; 391 cn += ((*fp & 0x0f) << 8); 392 } 393 if (cn >= PCF_12BCLUSTER) 394 cn |= PCF_RESCLUSTER; 395 break; 396 default: 397 pc_mark_irrecov(fsp); 398 cn = PCF_ERRORCLUSTER; 399 } 400 return (cn); 401 } 402 403 /* 404 * Set a cluster in the FAT to a value. 405 * cn = cluster number to be set in FAT 406 * ncn = new value 407 */ 408 void 409 pc_setcluster(struct pcfs *fsp, pc_cluster32_t cn, pc_cluster32_t ncn) 410 { 411 unsigned char *fp; 412 pc_cluster16_t ncn16; 413 414 if (fsp->pcfs_fatp == (uchar_t *)0 || !pc_validcl(fsp, cn)) 415 panic("pc_setcluster"); 416 fsp->pcfs_flags |= PCFS_FATMOD; 417 pc_mark_fat_updated(fsp, cn); 418 switch (fsp->pcfs_fattype) { 419 case FAT32: 420 fp = fsp->pcfs_fatp + (cn << 2); 421 *(pc_cluster32_t *)fp = htoli(ncn); 422 break; 423 case FAT16: 424 fp = fsp->pcfs_fatp + (cn << 1); 425 ncn16 = (pc_cluster16_t)ncn; 426 *(pc_cluster16_t *)fp = htols(ncn16); 427 break; 428 case FAT12: 429 fp = fsp->pcfs_fatp + (cn + (cn >> 1)); 430 if (cn & 01) { 431 *fp = (*fp & 0x0f) | ((ncn << 4) & 0xf0); 432 fp++; 433 *fp = (ncn >> 4) & 0xff; 434 } else { 435 *fp++ = ncn & 0xff; 436 *fp = (*fp & 0xf0) | ((ncn >> 8) & 0x0f); 437 } 438 break; 439 default: 440 pc_mark_irrecov(fsp); 441 } 442 if (ncn == PCF_FREECLUSTER) { 443 fsp->pcfs_nxfrecls = PCF_FIRSTCLUSTER; 444 if (IS_FAT32(fsp)) { 445 if (fsp->pcfs_fsinfo.fs_free_clusters != 446 FSINFO_UNKNOWN) 447 fsp->pcfs_fsinfo.fs_free_clusters++; 448 } 449 } 450 } 451 452 /* 453 * Allocate a new cluster. 454 */ 455 pc_cluster32_t 456 pc_alloccluster( 457 struct pcfs *fsp, /* file sys to allocate in */ 458 int zwrite) /* boolean for writing zeroes */ 459 { 460 pc_cluster32_t cn; 461 int error; 462 463 if (fsp->pcfs_fatp == (uchar_t *)0) 464 panic("pc_addcluster: no FAT"); 465 466 for (cn = fsp->pcfs_nxfrecls; 467 (int)cn < fsp->pcfs_ncluster; cn++) { 468 if (pc_getcluster(fsp, cn) == PCF_FREECLUSTER) { 469 struct buf *bp; 470 471 if (IS_FAT32(fsp)) { 472 pc_setcluster(fsp, cn, PCF_LASTCLUSTERMARK32); 473 if (fsp->pcfs_fsinfo.fs_free_clusters != 474 FSINFO_UNKNOWN) 475 fsp->pcfs_fsinfo.fs_free_clusters--; 476 } else 477 pc_setcluster(fsp, cn, PCF_LASTCLUSTERMARK); 478 if (zwrite) { 479 /* 480 * zero the new cluster 481 */ 482 bp = ngeteblk(fsp->pcfs_clsize); 483 bp->b_edev = fsp->pcfs_xdev; 484 bp->b_dev = cmpdev(bp->b_edev); 485 bp->b_blkno = pc_cldaddr(fsp, cn); 486 clrbuf(bp); 487 bwrite2(bp); 488 error = geterror(bp); 489 brelse(bp); 490 if (error) { 491 pc_mark_irrecov(fsp); 492 return (PCF_ERRORCLUSTER); 493 } 494 } 495 fsp->pcfs_nxfrecls = cn + 1; 496 return (cn); 497 } 498 } 499 return (PCF_FREECLUSTER); 500 } 501 502 /* 503 * Get the number of clusters used by a file or subdirectory 504 */ 505 int 506 pc_fileclsize( 507 struct pcfs *fsp, 508 pc_cluster32_t startcl, pc_cluster32_t *ncl) 509 { 510 int count = 0; 511 512 *ncl = 0; 513 for (count = 0; pc_validcl(fsp, startcl); 514 startcl = pc_getcluster(fsp, startcl)) { 515 if (count++ >= fsp->pcfs_ncluster) 516 return (EIO); 517 } 518 *ncl = (pc_cluster32_t)count; 519 520 return (0); 521 } 522