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