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 #pragma ident "%Z%%M% %I% %E% SMI" 26 27 #include <sys/param.h> 28 #include <sys/types.h> 29 #include <sys/systm.h> 30 #include <sys/cred.h> 31 #include <sys/proc.h> 32 #include <sys/user.h> 33 #include <sys/vfs.h> 34 #include <sys/vnode.h> 35 #include <sys/pathname.h> 36 #include <sys/uio.h> 37 #include <sys/tiuser.h> 38 #include <sys/sysmacros.h> 39 #include <sys/kmem.h> 40 #include <sys/mount.h> 41 #include <sys/ioctl.h> 42 #include <sys/statvfs.h> 43 #include <sys/errno.h> 44 #include <sys/debug.h> 45 #include <sys/cmn_err.h> 46 #include <sys/utsname.h> 47 #include <sys/bootconf.h> 48 #include <sys/modctl.h> 49 #include <sys/file.h> 50 #include <sys/stat.h> 51 52 #include <vm/hat.h> 53 #include <vm/as.h> 54 #include <vm/page.h> 55 #include <vm/pvn.h> 56 #include <vm/seg.h> 57 #include <vm/seg_map.h> 58 #include <vm/seg_vn.h> 59 #include <vm/rm.h> 60 #include <sys/fs/cachefs_fs.h> 61 #include <sys/fs/cachefs_log.h> 62 63 struct kmem_cache *cachefs_filegrp_cache = NULL; 64 65 #if (defined(_SYSCALL32_IMPL) || defined(_LP64)) 66 67 #define CACHEFS_ALLOC_CFS_METADATA(p, inp) \ 68 p = cachefs_kmem_zalloc(sizeof (struct cfs_cachefs_metadata), KM_SLEEP) 69 70 #define CACHEFS_FREE_CFS_METADATA(p) \ 71 cachefs_kmem_free(p, sizeof (struct cfs_cachefs_metadata)) 72 73 /* CACHEFS_COPY_COMMON_METADATA_FIELDS - common code for the metadata copy */ 74 #define CACHEFS_COPY_COMMON_METADATA_FIELDS(inmdp, outmdp) \ 75 (outmdp)->md_aclclass = (inmdp)->md_aclclass; \ 76 CACHEFS_FID_COPY(&(inmdp)->md_cookie, &(outmdp)->md_cookie); \ 77 (outmdp)->md_flags = (inmdp)->md_flags; \ 78 (outmdp)->md_rlno = (inmdp)->md_rlno; \ 79 (outmdp)->md_rltype = (inmdp)->md_rltype; \ 80 (outmdp)->md_consttype = (inmdp)->md_consttype; \ 81 CACHEFS_FID_COPY(&(inmdp)->md_fid, &(outmdp)->md_fid); \ 82 (outmdp)->md_frontblks = (inmdp)->md_frontblks; \ 83 (outmdp)->md_gen = (inmdp)->md_gen; \ 84 (outmdp)->md_parent = (inmdp)->md_parent; \ 85 (outmdp)->md_resettimes = (inmdp)->md_resettimes; \ 86 (outmdp)->md_localfileno = (inmdp)->md_localfileno; \ 87 (outmdp)->md_resetfileno = (inmdp)->md_resetfileno; \ 88 (outmdp)->md_seq = (inmdp)->md_seq; \ 89 (outmdp)->md_allocents = (inmdp)->md_allocents; \ 90 bcopy(&(inmdp)->md_allocinfo, &(outmdp)->md_allocinfo, \ 91 MIN(sizeof (inmdp)->md_allocinfo, sizeof (outmdp)->md_allocinfo)) 92 93 #define CACHEFS_COPY_METADATA_TO_CFS_METADATA(inmdp, outmdp, error) \ 94 CACHEFS_VATTR_TO_CFS_VATTR_COPY(&(inmdp)->md_vattr, \ 95 &(outmdp)->md_vattr, error); \ 96 CACHEFS_TS_TO_CFS_TS_COPY(&(inmdp)->md_timestamp, \ 97 &(outmdp)->md_timestamp, error); \ 98 CACHEFS_TS_TO_CFS_TS_COPY(&(inmdp)->md_x_time, \ 99 &(outmdp)->md_x_time, error); \ 100 CACHEFS_TS_TO_CFS_TS_COPY(&(inmdp)->md_localmtime, \ 101 &(outmdp)->md_localmtime, error); \ 102 CACHEFS_TS_TO_CFS_TS_COPY(&(inmdp)->md_localctime, \ 103 &(outmdp)->md_localctime, error); \ 104 CACHEFS_COPY_COMMON_METADATA_FIELDS(inmdp, outmdp) 105 106 #define CACHEFS_COPY_CFS_METADATA_TO_METADATA(inmdp, outmdp) \ 107 CACHEFS_CFS_VATTR_TO_VATTR_COPY(&(inmdp)->md_vattr, \ 108 &(outmdp)->md_vattr); \ 109 CACHEFS_CFS_TS_TO_TS_COPY(&(inmdp)->md_timestamp, \ 110 &(outmdp)->md_timestamp); \ 111 CACHEFS_CFS_TS_TO_TS_COPY(&(inmdp)->md_x_time, \ 112 &(outmdp)->md_x_time); \ 113 CACHEFS_CFS_TS_TO_TS_COPY(&(inmdp)->md_localmtime, \ 114 &(outmdp)->md_localmtime); \ 115 CACHEFS_CFS_TS_TO_TS_COPY(&(inmdp)->md_localctime, \ 116 &(outmdp)->md_localctime); \ 117 CACHEFS_COPY_COMMON_METADATA_FIELDS(inmdp, outmdp) 118 119 #else /* not (_SYSCALL32_IMPL || _LP64) */ 120 121 #define CACHEFS_ALLOC_CFS_METADATA(p, inp) \ 122 p = (cfs_cachefs_metadata_t *)(inp) 123 124 #define CACHEFS_FREE_CFS_METADATA(p) 125 126 #define CACHEFS_COPY_METADATA_TO_CFS_METADATA(inmdp, outmdp, error) 127 128 #define CACHEFS_COPY_CFS_METADATA_TO_METADATA(inmdp, outmdp) 129 130 #endif /* _SYSCALL32_IMPL || _LP64 */ 131 132 /* forward references */ 133 int filegrp_write_space(vnode_t *vp, offset_t offset, ssize_t cnt); 134 int filegrpattr_find(struct filegrp *fgp); 135 int filegrpattr_create(struct filegrp *fgp); 136 137 int 138 /*ARGSUSED*/ 139 filegrp_cache_create(void *voidp, void *cdrarg, int kmflags) 140 { 141 filegrp_t *fgp = (filegrp_t *)voidp; 142 143 mutex_init(&fgp->fg_mutex, NULL, MUTEX_DEFAULT, NULL); 144 mutex_init(&fgp->fg_cnodelock, NULL, MUTEX_DEFAULT, NULL); 145 return (0); 146 } 147 148 void 149 /*ARGSUSED*/ 150 filegrp_cache_destroy(void *voidp, void *cdrarg) 151 { 152 filegrp_t *fgp = (filegrp_t *)voidp; 153 154 mutex_destroy(&fgp->fg_mutex); 155 mutex_destroy(&fgp->fg_cnodelock); 156 } 157 158 /* 159 * ------------------------------------------------------------------ 160 * 161 * filegrp_create 162 * 163 * Description: 164 * Creates a filegrp object for the specified fscache. 165 * The CFS_FG_ALLOC_{ATTR, FILE} bits will be set in fg_flags 166 * if the cache is in NOCACHE and NOFILL mode or if 167 * the directory does not exist yet. 168 * The filegrp object maintains a reference to the specified 169 * fscache. 170 * Arguments: 171 * fscp fscache to create the file group in 172 * cidp start cid for the file group 173 * Returns: 174 * Returns the created filegrp object. 175 * Preconditions: 176 * precond(fscp) 177 * precond(cidp) 178 * precond(fscp->fs_info.fi_fgsize > 0) 179 */ 180 #define Bugid_1249206_notfixed 181 #ifdef Bugid_1249206_notfixed 182 int bugid_1249206 = 0; 183 #endif 184 filegrp_t * 185 filegrp_create(struct fscache *fscp, cfs_cid_t *cidp) 186 { 187 filegrp_t *fgp; 188 int fgsize; 189 int flags; 190 ino64_t nfgsize; 191 192 fgsize = fscp->fs_info.fi_fgsize; 193 194 fgp = (filegrp_t *) 195 kmem_cache_alloc(cachefs_filegrp_cache, KM_SLEEP); 196 197 fgp->fg_flags = CFS_FG_ALLOC_ATTR | CFS_FG_ALLOC_FILE; 198 fgp->fg_count = 0; 199 fgp->fg_id = *cidp; 200 #ifdef Bugid_1249206_notfixed 201 if (bugid_1249206) 202 cmn_err(CE_CONT, "fg_id assigned value is %" PRId64 "\n", 203 fgp->fg_id.cid_fileno); 204 #endif 205 nfgsize = (fgp->fg_id.cid_fileno / (ino64_t)fgsize); 206 fgp->fg_id.cid_fileno = (ino64_t)(nfgsize * (ino64_t)fgsize); 207 #ifdef Bugid_1249206_notfixed 208 if (bugid_1249206) { 209 cmn_err(CE_CONT, 210 "cid_fileno for fscp %p fgp %p is %" PRId64 "\n", 211 (void *)fscp, (void *)fgp, 212 fgp->fg_id.cid_fileno); 213 cmn_err(CE_CONT, 214 "sent fileno is %" PRId64 " fgsize %d nfgsize %" PRId64 215 "\n", cidp->cid_fileno, fgsize, nfgsize); 216 } 217 #endif 218 fgp->fg_fscp = fscp; 219 fgp->fg_cnodelist = NULL; 220 fgp->fg_next = NULL; 221 fgp->fg_dirvp = NULL; 222 fgp->fg_attrvp = NULL; 223 fgp->fg_header = NULL; 224 fgp->fg_offsets = NULL; 225 fgp->fg_alloclist = NULL; 226 227 fgp->fg_headersize = (u_int)sizeof (struct attrcache_header) + 228 (fgsize * (u_int)sizeof (struct attrcache_index)) + 229 ((fgsize + 7) >> 3); 230 231 fgp->fg_filesize = fgp->fg_headersize + 232 (fgsize * (u_int)sizeof (struct cfs_cachefs_metadata)); 233 234 flags = fscp->fs_flags; 235 if (flags & CFS_FS_READ) { 236 fgp->fg_flags |= CFS_FG_READ; 237 if (flags & CFS_FS_WRITE) { 238 fgp->fg_flags |= CFS_FG_WRITE; 239 } 240 } 241 242 if (fgp->fg_flags & CFS_FG_READ) { 243 /* find the attrcache file and frontfile directory */ 244 (void) filegrpattr_find(fgp); 245 246 /* 247 * XXX: we can tell from the file count in the attrcache 248 * whether we can expect to find a front file dir or 249 * not. If not, we can save the lookup here... 250 */ 251 (void) filegrpdir_find(fgp); 252 } 253 254 return (fgp); 255 } 256 257 /* 258 * ------------------------------------------------------------------ 259 * 260 * filegrp_destroy 261 * 262 * Description: 263 * Destroys the filegrp object and releases any kernel 264 * resource associated with it. 265 * Additionally if the on disk file group directory does 266 * not contain any front files it is removed. 267 * Arguments: 268 * fgp filegrp object to destroy 269 * Returns: 270 * Preconditions: 271 * precond(fgp is a valid filegrp object) 272 * precond(fgp->fg_count == 0) 273 * precond(fgp->fg_next == NULL) 274 */ 275 276 void 277 filegrp_destroy(filegrp_t *fgp) 278 { 279 struct fscache *fscp = fgp->fg_fscp; 280 char name[CFS_FRONTFILE_NAME_SIZE]; 281 char *fname; 282 int error; 283 284 ASSERT(fgp->fg_count == 0); 285 ASSERT(fgp->fg_next == NULL); 286 287 if (fgp->fg_attrvp) { 288 if (fgp->fg_flags & CFS_FG_UPDATED) { 289 error = filegrp_sync(fgp); 290 if (error) 291 cmn_err(CE_WARN, 292 "cachefs: UFS error on cache, " 293 "run fsck %d", error); 294 } 295 VN_RELE(fgp->fg_attrvp); 296 } 297 if (fgp->fg_header) { 298 /* 299 * If there are no attrcache entries in use and 300 * if we can modify the cache. 301 */ 302 if ((fgp->fg_header->ach_count == 0) && 303 (fgp->fg_flags & CFS_FG_WRITE)) { 304 ASSERT(fgp->fg_header->ach_nffs == 0); 305 306 /* remove attrcache file from the rl list */ 307 ASSERT(fgp->fg_header->ach_rl_current == 308 CACHEFS_RL_GC); 309 #ifdef CFSDEBUG 310 cachefs_rlent_verify(fscp->fs_cache, CACHEFS_RL_GC, 311 fgp->fg_header->ach_rlno); 312 #endif /* CFSDEBUG */ 313 314 /* 315 * XXX sam: since we're blowing away the 316 * attrcache file, i guess i don't need to set 317 * ach_rl_current to CACHEFS_RL_NONE and 318 * sync the attrcache file, right? 319 * 320 * fgp->fg_header->ach_rl_current = CACHEFS_RL_NONE; 321 * fgp->fg_flags |= CFS_FG_UPDATED; 322 */ 323 324 /* remove the attrcache file */ 325 make_ascii_name(&fgp->fg_id, name); 326 fname = name; 327 error = VOP_REMOVE(fscp->fs_fsattrdir, fname, kcred); 328 if (error) { 329 cmn_err(CE_WARN, 330 "cachefs: error in cache, run fsck"); 331 } else { 332 cachefs_freefile(fscp->fs_cache); 333 cachefs_freeblocks(fscp->fs_cache, 334 fgp->fg_header->ach_nblks, CACHEFS_RL_GC); 335 cachefs_rlent_moveto(fscp->fs_cache, 336 CACHEFS_RL_FREE, fgp->fg_header->ach_rlno, 337 0); 338 } 339 } 340 cachefs_kmem_free(fgp->fg_header, fgp->fg_headersize); 341 } 342 if (fgp->fg_dirvp) { 343 VN_RELE(fgp->fg_dirvp); 344 } 345 kmem_cache_free(cachefs_filegrp_cache, fgp); 346 } 347 348 /* 349 * ------------------------------------------------------------------ 350 * 351 * filegrp_allocattr 352 * 353 * Description: 354 * Tries to find the attrcache file for the given filegroup. 355 * If the file does not yet exist it is created. 356 * Arguments: 357 * fgp filegrp object 358 * Returns: 359 * Returns 0 on success, an errno value on failure. 360 * Preconditions: 361 * precond(fgp is a valid filegrp object) 362 */ 363 364 int 365 filegrp_allocattr(filegrp_t *fgp) 366 { 367 int error = 0; 368 369 mutex_enter(&fgp->fg_mutex); 370 371 /* if we do not yet have the attrcache file */ 372 if (fgp->fg_flags & CFS_FG_ALLOC_ATTR) { 373 /* fail if we tried to create it but failed previously */ 374 if (fgp->fg_flags & CFS_FG_NOCACHE) { 375 error = ENOENT; 376 goto out; 377 } 378 379 /* fail if we cannot read from the cache */ 380 if ((fgp->fg_flags & CFS_FG_READ) == 0) { 381 error = ENOENT; 382 goto out; 383 } 384 385 /* try to find the attrcache file in the cache */ 386 error = filegrpattr_find(fgp); 387 if (error == ENOENT) { 388 /* fail if we cannot create the attrcache file */ 389 if ((fgp->fg_flags & CFS_FG_WRITE) == 0) { 390 error = ENOENT; 391 goto out; 392 } 393 394 /* try to create the attrcache file */ 395 error = filegrpattr_create(fgp); 396 } 397 } 398 out: 399 mutex_exit(&fgp->fg_mutex); 400 401 return (error); 402 } 403 404 /* 405 * ------------------------------------------------------------------ 406 * 407 * filegrp_hold 408 * 409 * Description: 410 * Increments the number of references to this filegrp object. 411 * Arguments: 412 * fgp filegrp object to reference 413 * Returns: 414 * Preconditions: 415 * precond(fgp is a valid filegrp object) 416 */ 417 418 void 419 filegrp_hold(filegrp_t *fgp) 420 { 421 mutex_enter(&fgp->fg_mutex); 422 423 fgp->fg_count++; 424 425 /* remove attrcache file from the rl list if necessary */ 426 if ((fgp->fg_flags & CFS_FG_WRITE) && 427 (fgp->fg_header != NULL) && 428 (fgp->fg_header->ach_rl_current == CACHEFS_RL_GC)) { 429 #ifdef CFSDEBUG 430 cachefs_rlent_verify(fgp->fg_fscp->fs_cache, 431 CACHEFS_RL_GC, fgp->fg_header->ach_rlno); 432 #endif /* CFSDEBUG */ 433 cachefs_rlent_moveto(fgp->fg_fscp->fs_cache, 434 CACHEFS_RL_ATTRFILE, fgp->fg_header->ach_rlno, 435 fgp->fg_header->ach_nblks); 436 fgp->fg_header->ach_rl_current = CACHEFS_RL_ATTRFILE; 437 fgp->fg_flags |= CFS_FG_UPDATED; 438 } 439 440 mutex_exit(&fgp->fg_mutex); 441 } 442 443 /* 444 * ------------------------------------------------------------------ 445 * 446 * filegrp_rele 447 * 448 * Description: 449 * Decrements the number of references to this filegrp object. 450 * Arguments: 451 * fgp filegrp object to dereference 452 * Returns: 453 * Preconditions: 454 * precond(fgp is a valid filegrp object) 455 * precond(number of refrences to filegrp is > 0) 456 */ 457 458 void 459 filegrp_rele(filegrp_t *fgp) 460 { 461 mutex_enter(&fgp->fg_mutex); 462 ASSERT(fgp->fg_count > 0); 463 464 /* move attrcache file to the rl list if necessary */ 465 if (((fgp->fg_flags & CFS_FG_ALLOC_ATTR) == 0) && 466 (fgp->fg_flags & CFS_FG_WRITE) && 467 (fgp->fg_header->ach_rl_current != CACHEFS_RL_GC) && 468 (fgp->fg_count == 1) && 469 (fgp->fg_header->ach_nffs == 0)) { 470 #ifdef CFSDEBUG 471 cachefs_rlent_verify(fgp->fg_fscp->fs_cache, 472 CACHEFS_RL_ATTRFILE, fgp->fg_header->ach_rlno); 473 #endif /* CFSDEBUG */ 474 cachefs_rlent_moveto(fgp->fg_fscp->fs_cache, 475 CACHEFS_RL_GC, fgp->fg_header->ach_rlno, 476 fgp->fg_header->ach_nblks); 477 fgp->fg_header->ach_rl_current = CACHEFS_RL_GC; 478 fgp->fg_flags |= CFS_FG_UPDATED; 479 } 480 481 fgp->fg_count--; 482 483 mutex_exit(&fgp->fg_mutex); 484 485 } 486 487 /* 488 * ------------------------------------------------------------------ 489 * 490 * filegrp_ffhold 491 * 492 * Description: 493 * Increments the count of the number of front files for 494 * this filegrp by one. 495 * Arguments: 496 * fgp filegrp object to reference 497 * Returns: 498 * Returns 0 for success or a non-zero errno. 499 * Preconditions: 500 * precond(fgp is a valid filegrp object) 501 * precond(number of refrences to filegrp is > 0) 502 * precond(filegrp is writable) 503 */ 504 505 int 506 filegrp_ffhold(filegrp_t *fgp) 507 { 508 int error = 0; 509 510 cachefs_cache_dirty(fgp->fg_fscp->fs_cache, 1); 511 512 mutex_enter(&fgp->fg_mutex); 513 ASSERT(fgp->fg_flags & CFS_FG_WRITE); 514 ASSERT(fgp->fg_count > 0); 515 516 /* if the filegrp is no good, bail out with warning */ 517 if (fgp->fg_flags & CFS_FG_NOCACHE) { 518 error = EINVAL; 519 goto out; 520 } 521 522 /* if we do not have the directory vp yet */ 523 if (fgp->fg_flags & CFS_FG_ALLOC_FILE) { 524 525 /* create the directory if necessary */ 526 if (fgp->fg_header->ach_nffs == 0) { 527 error = filegrpdir_create(fgp); 528 if (error) 529 goto out; 530 } 531 532 /* else find the directory */ 533 else { 534 error = filegrpdir_find(fgp); 535 if (error) { 536 #ifdef CFSDEBUG 537 CFS_DEBUG(CFSDEBUG_FILEGRP) 538 printf("ffhold: no dir, errno %d, " 539 "fileno %llx\n", 540 error, (u_longlong_t)fgp->fg_id.cid_fileno); 541 #endif 542 goto out; 543 } 544 } 545 } 546 ASSERT(fgp->fg_dirvp); 547 548 #ifdef CFSDEBUG 549 if (fgp->fg_header->ach_nffs == 0) { 550 ASSERT(fgp->fg_header->ach_rl_current == CACHEFS_RL_ATTRFILE); 551 cachefs_rlent_verify(fgp->fg_fscp->fs_cache, 552 CACHEFS_RL_ATTRFILE, fgp->fg_header->ach_rlno); 553 554 /* 555 * XXX sam: this used to remove from the active list, 556 * and put on `NONE'. now, we're on 557 * CACHEFS_RL_ATTRFILE if either count or nffs is 558 * nonzero; CACHEFS_RL_GC otherwise. since we just 559 * asserted that we're not on CACHEFS_RL_GC, there's 560 * nothing more to do. right? 561 */ 562 } 563 #endif /* CFSDEBUG */ 564 565 fgp->fg_header->ach_nffs++; 566 fgp->fg_flags |= CFS_FG_UPDATED; 567 ASSERT(fgp->fg_header->ach_nffs <= fgp->fg_header->ach_count); 568 569 out: 570 mutex_exit(&fgp->fg_mutex); 571 572 return (error); 573 } 574 575 /* 576 * ------------------------------------------------------------------ 577 * 578 * filegrp_ffrele 579 * 580 * Description: 581 * Decrements the count of the number of front files for 582 * this filegrp by one. 583 * Arguments: 584 * fgp filegrp object to dereference 585 * Returns: 586 * Preconditions: 587 * precond(fgp is a valid filegrp object) 588 * precond(filegrp is writable) 589 * precond(number of refrences to filegrp is > 0) 590 * precond(number of front file references is > 0) 591 */ 592 593 void 594 filegrp_ffrele(filegrp_t *fgp) 595 { 596 char name[CFS_FRONTFILE_NAME_SIZE]; 597 char *fname; 598 struct fscache *fscp = fgp->fg_fscp; 599 int error = 0; 600 601 /* if the filegrp is corrupt, bail out with warning */ 602 if (fgp->fg_flags & CFS_FG_NOCACHE) { 603 return; 604 } 605 606 cachefs_cache_dirty(fgp->fg_fscp->fs_cache, 1); 607 608 mutex_enter(&fgp->fg_mutex); 609 ASSERT(fgp->fg_flags & CFS_FG_WRITE); 610 ASSERT((fgp->fg_flags & CFS_FG_ALLOC_FILE) == 0); 611 ASSERT(fgp->fg_dirvp != NULL); 612 ASSERT(fgp->fg_count > 0); 613 ASSERT(fgp->fg_header->ach_nffs > 0); 614 ASSERT(fgp->fg_header->ach_nffs <= fgp->fg_header->ach_count); 615 616 fgp->fg_header->ach_nffs--; 617 fgp->fg_flags |= CFS_FG_UPDATED; 618 619 if (fgp->fg_header->ach_nffs == 0) { 620 make_ascii_name(&fgp->fg_id, name); 621 fname = name; 622 error = VOP_RMDIR(fscp->fs_fscdirvp, fname, 623 fscp->fs_fscdirvp, kcred); 624 if (error == 0) { 625 cachefs_freefile(fscp->fs_cache); 626 cachefs_freeblocks(fscp->fs_cache, 1, 627 fgp->fg_header->ach_rl_current); 628 VN_RELE(fgp->fg_dirvp); 629 fgp->fg_dirvp = NULL; 630 fgp->fg_flags |= CFS_FG_ALLOC_FILE; 631 } else { 632 fgp->fg_flags |= CFS_FG_NOCACHE; 633 cmn_err(CE_WARN, "cachefs_ffrele:" 634 " frontfs cache error %d, run fsck", error); 635 } 636 637 /* 638 * XXX sam: this used to move from `NONE' to 639 * `CACHEFS_RL_ACTIVE'. now, we're on 640 * CACHEFS_RL_ATTRFILE if count and/or nffs is 641 * nonzero, and CACHEFS_RL_GC otherwise. since we 642 * just asserted that count > 0, there's nothing to 643 * do. right? 644 */ 645 #ifdef CFSDEBUG 646 cachefs_rlent_verify(fgp->fg_fscp->fs_cache, 647 CACHEFS_RL_ATTRFILE, fgp->fg_header->ach_rlno); 648 #endif /* CFSDEBUG */ 649 } 650 mutex_exit(&fgp->fg_mutex); 651 } 652 653 /* 654 * ------------------------------------------------------------------ 655 * 656 * filegrp_sync 657 * 658 * Description: 659 * Writes the file group's attrcache header to the attrcache 660 * file if necessary and syncs it. 661 * Arguments: 662 * fgp filegrp object 663 * Returns: 664 * Returns 0 on success, an errno value on failure. 665 * Preconditions: 666 * precond(fgp is a valid filegrp object) 667 */ 668 669 int 670 filegrp_sync(filegrp_t *fgp) 671 { 672 int error = 0; 673 674 mutex_enter(&fgp->fg_mutex); 675 676 if (((fgp->fg_flags & CFS_FG_UPDATED) == 0) || 677 (fgp->fg_flags & CFS_FG_ALLOC_ATTR) || 678 CFS_ISFS_BACKFS_NFSV4(fgp->fg_fscp)) { 679 mutex_exit(&fgp->fg_mutex); 680 return (0); 681 } 682 683 ASSERT(fgp->fg_header->ach_nffs <= fgp->fg_header->ach_count); 684 685 error = vn_rdwr(UIO_WRITE, fgp->fg_attrvp, (caddr_t)fgp->fg_header, 686 fgp->fg_headersize, 0LL, UIO_SYSSPACE, 0, (rlim64_t)RLIM_INFINITY, 687 kcred, NULL); 688 689 if (error == 0) 690 error = VOP_FSYNC(fgp->fg_attrvp, FSYNC, kcred); 691 692 if (error == 0) 693 fgp->fg_flags &= ~CFS_FG_UPDATED; 694 695 mutex_exit(&fgp->fg_mutex); 696 697 return (error); 698 } 699 700 /* 701 * ------------------------------------------------------------------ 702 * 703 * filegrp_read_metadata 704 * 705 * Description: 706 * Reads the metadata for the specified file from the attrcache 707 * file belonging to the filegrp object. Note that the md_rltype 708 * field may be incorrect if (cachep->c_flags & CACHE_CHECK_RLTYPE); 709 * in this case, if you care about md_rltype, you should double-check 710 * if rl_type is CACHEFS_RL_ACTIVE; cachefs_move_active_to_rl may have 711 * moved it without telling us. 712 * Arguments: 713 * fgp filegrp object 714 * cidp the file to search for 715 * mdp set to the metadata for the fileno 716 * Returns: 717 * Returns 0 on success, an errno value on failure. 718 * Preconditions: 719 * precond(fgp is a valid filegrp object) 720 * precond(mdp) 721 * precond(slotp) 722 */ 723 724 int 725 filegrp_read_metadata(filegrp_t *fgp, cfs_cid_t *cidp, 726 struct cachefs_metadata *mdp) 727 { 728 int slot; 729 int error; 730 int index; 731 struct cfs_cachefs_metadata *tmpmdp; 732 733 ASSERT(CFS_ISFS_BACKFS_NFSV4(fgp->fg_fscp) == 0); 734 735 mutex_enter(&fgp->fg_mutex); 736 if (fgp->fg_flags & CFS_FG_ALLOC_ATTR) { 737 mutex_exit(&fgp->fg_mutex); 738 return (ENOENT); 739 } 740 741 slot = filegrp_cid_to_slot(fgp, cidp); 742 if (slot == 0) { 743 mutex_exit(&fgp->fg_mutex); 744 return (ENOENT); 745 } 746 747 748 /* see if metadata was ever written */ 749 index = (int) (cidp->cid_fileno - fgp->fg_id.cid_fileno); 750 if (fgp->fg_offsets[index].ach_written == 0) { 751 mutex_exit(&fgp->fg_mutex); 752 return (ENOENT); 753 } 754 755 CACHEFS_ALLOC_CFS_METADATA(tmpmdp, mdp); 756 757 error = vn_rdwr(UIO_READ, fgp->fg_attrvp, 758 (caddr_t)tmpmdp, sizeof (struct cfs_cachefs_metadata), 759 (offset_t)slot, 760 UIO_SYSSPACE, 0, (long long)0, kcred, NULL); 761 if (error) { 762 cmn_err(CE_WARN, 763 "cachefs_read_metadata:" 764 " frontfs cache error %d, run fsck", error); 765 } 766 CACHEFS_COPY_CFS_METADATA_TO_METADATA(tmpmdp, mdp); 767 CACHEFS_FREE_CFS_METADATA(tmpmdp); 768 769 mutex_exit(&fgp->fg_mutex); 770 return (error); 771 } 772 773 /* 774 * ------------------------------------------------------------------ 775 * 776 * filegrp_create_metadata 777 * 778 * Description: 779 * Allocates a slot for the specified fileno. 780 * Arguments: 781 * fgp filegrp object 782 * cidp the file to allocate a slot for 783 * Returns: 784 * Returns 0 on success, an errno value on failure. 785 * Preconditions: 786 * precond(fgp is a valid filegrp object) 787 */ 788 789 int 790 filegrp_create_metadata(filegrp_t *fgp, struct cachefs_metadata *md, 791 cfs_cid_t *cidp) 792 { 793 struct fscache *fscp = fgp->fg_fscp; 794 cachefscache_t *cachep = fscp->fs_cache; 795 int slot; 796 int bitno; 797 u_char mask; 798 int last; 799 int xx; 800 int index; 801 802 ASSERT(CFS_ISFS_BACKFS_NFSV4(fgp->fg_fscp) == 0); 803 804 cachefs_cache_dirty(cachep, 1); 805 806 mutex_enter(&fgp->fg_mutex); 807 808 if (fgp->fg_flags & CFS_FG_ALLOC_ATTR) { 809 mutex_exit(&fgp->fg_mutex); 810 return (ENOENT); 811 } 812 813 slot = filegrp_cid_to_slot(fgp, cidp); 814 if (slot) { 815 mutex_exit(&fgp->fg_mutex); 816 return (0); 817 } 818 819 index = (int) (cidp->cid_fileno - fgp->fg_id.cid_fileno); 820 821 ASSERT(index < fgp->fg_fscp->fs_info.fi_fgsize); 822 823 last = (((fgp->fg_fscp->fs_info.fi_fgsize + 7) & ~(7)) / 8); 824 for (xx = 0; xx < last; xx++) { 825 if (fgp->fg_alloclist[xx] != (u_char)0xff) { 826 for (mask = 1, bitno = 0; bitno < 8; bitno++) { 827 if ((mask & fgp->fg_alloclist[xx]) == 0) { 828 slot = (xx * 8) + bitno; 829 goto found; 830 } 831 mask <<= 1; 832 } 833 } 834 } 835 found: 836 if (xx == last) { 837 cmn_err(CE_WARN, "cachefs: attrcache error, run fsck"); 838 mutex_exit(&fgp->fg_mutex); 839 return (ENOMEM); 840 } 841 842 slot = (slot * (int)sizeof (struct cfs_cachefs_metadata)) + 843 fgp->fg_headersize; 844 845 ASSERT(fgp->fg_header->ach_nffs <= fgp->fg_header->ach_count); 846 fgp->fg_header->ach_count++; 847 fgp->fg_offsets[index].ach_offset = slot; 848 fgp->fg_offsets[index].ach_written = 0; 849 fgp->fg_alloclist[xx] |= mask; 850 fgp->fg_flags |= CFS_FG_UPDATED; 851 852 mutex_exit(&fgp->fg_mutex); 853 854 if (CACHEFS_LOG_LOGGING(cachep, CACHEFS_LOG_MDCREATE)) 855 cachefs_log_mdcreate(cachep, 0, 856 fscp->fs_cfsvfsp, &md->md_cookie, cidp->cid_fileno, 857 fgp->fg_header->ach_count); 858 859 return (0); 860 } 861 862 /* 863 * ------------------------------------------------------------------ 864 * 865 * filegrp_write_metadata 866 * 867 * Description: 868 * Writes metadata to the slot held by file. 869 * Arguments: 870 * fgp filegrp object 871 * cidp the file to write the metadata for 872 * mdp the metadata to write 873 * Returns: 874 * Returns 0 on success, an errno value on failure. 875 * Preconditions: 876 * precond(fgp is a valid filegrp object) 877 * precond(mdp) 878 */ 879 int 880 filegrp_write_metadata(filegrp_t *fgp, cfs_cid_t *cidp, 881 struct cachefs_metadata *mdp) 882 { 883 int error = 0; 884 int slot; 885 blkcnt64_t nblks; 886 int index; 887 struct fscache *fscp = fgp->fg_fscp; 888 struct cfs_cachefs_metadata *tmpmdp; 889 890 ASSERT(CFS_ISFS_BACKFS_NFSV4(fgp->fg_fscp) == 0); 891 892 cachefs_cache_dirty(fscp->fs_cache, 1); 893 mutex_enter(&fgp->fg_mutex); 894 895 if (fgp->fg_flags & CFS_FG_ALLOC_ATTR) { 896 error = ENOENT; 897 goto out; 898 } 899 900 slot = filegrp_cid_to_slot(fgp, cidp); 901 if (slot == 0) { 902 error = ENOENT; 903 goto out; 904 } 905 906 /* allocate blocks for the data if necessary */ 907 nblks = slot + sizeof (struct cfs_cachefs_metadata); 908 nblks = (nblks + MAXBSIZE - 1) / MAXBSIZE; 909 nblks -= fgp->fg_header->ach_nblks; 910 if (nblks > 0) { 911 error = cachefs_allocblocks(fscp->fs_cache, nblks, 912 fgp->fg_header->ach_rl_current); 913 if (error) 914 goto out; 915 error = filegrp_write_space(fgp->fg_attrvp, 916 (offset_t)fgp->fg_header->ach_nblks * MAXBSIZE, 917 nblks * MAXBSIZE); 918 if (error) { 919 cachefs_freeblocks(fscp->fs_cache, nblks, 920 fgp->fg_header->ach_rl_current); 921 goto out; 922 } 923 } else 924 nblks = 0; 925 926 CACHEFS_ALLOC_CFS_METADATA(tmpmdp, mdp); 927 CACHEFS_COPY_METADATA_TO_CFS_METADATA(mdp, tmpmdp, error); 928 /* write the metadata */ 929 if (!error) 930 error = vn_rdwr(UIO_WRITE, fgp->fg_attrvp, (caddr_t)tmpmdp, 931 sizeof (struct cfs_cachefs_metadata), (offset_t)slot, 932 UIO_SYSSPACE, 0, (rlim64_t)RLIM_INFINITY, kcred, NULL); 933 934 CACHEFS_FREE_CFS_METADATA(tmpmdp); 935 936 if (error) { 937 if (error == EOVERFLOW) { 938 cmn_err(CE_WARN, "cachefs_write_metadata:" 939 " time/dev overflow error %d", error); 940 } else if (error != ENOSPC) { 941 cmn_err(CE_WARN, 942 "cachefs: UFS write error %d, run fsck", 943 error); 944 } 945 cachefs_freeblocks(fscp->fs_cache, nblks, 946 fgp->fg_header->ach_rl_current); 947 goto out; 948 } 949 950 /* mark metadata as having been written */ 951 index = (int) (cidp->cid_fileno - fgp->fg_id.cid_fileno); 952 fgp->fg_offsets[index].ach_written = 1; 953 954 /* update number of blocks used by the attrcache file */ 955 fgp->fg_header->ach_nblks += nblks; 956 957 /* force sync to be done eventually */ 958 fgp->fg_flags |= CFS_FG_UPDATED; 959 960 out: 961 mutex_exit(&fgp->fg_mutex); 962 return (error); 963 } 964 965 /* 966 * ------------------------------------------------------------------ 967 * 968 * filegrp_destroy_metadata 969 * 970 * Description: 971 * Destroys the metadata associated with the specified file. 972 * Arguments: 973 * fgp filegrp object 974 * cidp the file to destroy the metadata for 975 * Returns: 976 * Returns 0 on success, an errno value on failure. 977 * Preconditions: 978 * precond(fgp is a valid filegrp object) 979 */ 980 981 int 982 filegrp_destroy_metadata(filegrp_t *fgp, cfs_cid_t *cidp) 983 { 984 int i; 985 int bitno; 986 u_char mask = 1; 987 988 int slot; 989 990 ASSERT(CFS_ISFS_BACKFS_NFSV4(fgp->fg_fscp) == 0); 991 992 cachefs_cache_dirty(fgp->fg_fscp->fs_cache, 1); 993 mutex_enter(&fgp->fg_mutex); 994 995 if (fgp->fg_flags & CFS_FG_ALLOC_ATTR) { 996 mutex_exit(&fgp->fg_mutex); 997 return (ENOENT); 998 } 999 1000 slot = filegrp_cid_to_slot(fgp, cidp); 1001 if (slot == 0) { 1002 mutex_exit(&fgp->fg_mutex); 1003 return (ENOENT); 1004 } 1005 1006 i = (int)(cidp->cid_fileno - fgp->fg_id.cid_fileno); 1007 fgp->fg_offsets[i].ach_offset = 0; 1008 fgp->fg_offsets[i].ach_written = 0; 1009 i = (slot - fgp->fg_headersize) / 1010 (int)sizeof (struct cfs_cachefs_metadata); 1011 bitno = i & 7; 1012 i = i >> 3; 1013 mask <<= bitno; 1014 if (fgp->fg_alloclist[i] & mask) 1015 fgp->fg_alloclist[i] &= ~mask; 1016 else 1017 cmn_err(CE_WARN, 1018 "filegrp_destroy_metadata:" 1019 " fileno %" PRId64 " slot %d-%d fgp %p not allocated", 1020 cidp->cid_fileno, i, bitno, (void *)fgp); 1021 1022 fgp->fg_header->ach_count--; 1023 ASSERT(fgp->fg_header->ach_nffs <= fgp->fg_header->ach_count); 1024 fgp->fg_flags |= CFS_FG_UPDATED; 1025 mutex_exit(&fgp->fg_mutex); 1026 1027 return (0); 1028 } 1029 1030 /* 1031 * ------------------------------------------------------------------ 1032 * 1033 * filegrp_list_find 1034 * 1035 * Description: 1036 * Looks for the filegrp that owns the specified file 1037 * on the fscp filegrp lists. 1038 * The fscp->fs_fslock must be held while this routine is called. 1039 * By convention the filegrp object returned may be used as 1040 * long as the fs_fslock is held. To use the filegrp after 1041 * dropping fs_fslock, call filegrp_hold. 1042 * Arguments: 1043 * fscp fscache object 1044 * cidp the file to search on 1045 * Returns: 1046 * Returns the filegrp object if found, NULL if not. 1047 * Preconditions: 1048 * precond(fscp is a valid fscache object) 1049 */ 1050 1051 filegrp_t * 1052 filegrp_list_find(struct fscache *fscp, cfs_cid_t *cidp) 1053 { 1054 int fgsize = fscp->fs_info.fi_fgsize; 1055 struct filegrp *fgp; 1056 ino64_t fxx; 1057 int findex; 1058 ino64_t fileno; 1059 1060 ASSERT(MUTEX_HELD(&fscp->fs_fslock)); 1061 1062 /* get fileno of filegrp */ 1063 fxx = (ino64_t)(cidp->cid_fileno / fgsize); 1064 fileno = fxx * fgsize; 1065 1066 /* hash into array of file groups */ 1067 findex = (int) (fxx & (CFS_FS_FGP_BUCKET_SIZE - 1)); 1068 1069 /* search set of file groups for this hash bucket */ 1070 for (fgp = fscp->fs_filegrp[findex]; 1071 fgp != NULL; 1072 fgp = fgp->fg_next) { 1073 if ((fgp->fg_id.cid_fileno == fileno) && 1074 (fgp->fg_id.cid_flags == cidp->cid_flags)) 1075 break; 1076 } 1077 1078 return (fgp); 1079 } 1080 1081 /* 1082 * ------------------------------------------------------------------ 1083 * 1084 * filegrp_list_add 1085 * 1086 * Description: 1087 * Adds the filegrp to the list of filegrps in the fscp. 1088 * The fscp->fs_fslock must be held while this routine is called. 1089 * Arguments: 1090 * fscp fscache object 1091 * fgp filegrp object 1092 * Returns: 1093 * Preconditions: 1094 * precond(fscp is a valid fscache object) 1095 * precond(fgp is a valid filegrp object) 1096 * precond(fgp is not already on a list of filegrps) 1097 */ 1098 1099 void 1100 filegrp_list_add(struct fscache *fscp, filegrp_t *fgp) 1101 { 1102 int findex; 1103 int fgsize = fscp->fs_info.fi_fgsize; 1104 1105 ASSERT(MUTEX_HELD(&fscp->fs_fslock)); 1106 ASSERT(fgp->fg_next == NULL); 1107 1108 /* hash into array of file groups */ 1109 findex = (int) ((fgp->fg_id.cid_fileno / fgsize) & 1110 (CFS_FS_FGP_BUCKET_SIZE - 1)); 1111 1112 fgp->fg_next = fscp->fs_filegrp[findex]; 1113 fscp->fs_filegrp[findex] = fgp; 1114 fscp->fs_ref++; 1115 } 1116 1117 /* 1118 * ------------------------------------------------------------------ 1119 * 1120 * filegrp_list_remove 1121 * 1122 * Description: 1123 * Removes the filegrp from the list of filegrps in the fscp. 1124 * The fscp->fs_fslock must be held while this routine is called. 1125 * Arguments: 1126 * fscp fscache object 1127 * fgp filegrp object 1128 * Returns: 1129 * Preconditions: 1130 * precond(fscp is a valid fscache object) 1131 * precond(fgp is a valid filegrp object) 1132 * precond(fgp is on the list of filegrps in fscp) 1133 */ 1134 1135 void 1136 filegrp_list_remove(struct fscache *fscp, filegrp_t *fgp) 1137 { 1138 struct filegrp *fp; 1139 struct filegrp **pfgp; 1140 int found = 0; 1141 int findex; 1142 int fgsize = fscp->fs_info.fi_fgsize; 1143 1144 ASSERT(MUTEX_HELD(&fscp->fs_fslock)); 1145 1146 /* hash into array of file groups */ 1147 findex = (int) ((fgp->fg_id.cid_fileno / fgsize) & 1148 (CFS_FS_FGP_BUCKET_SIZE - 1)); 1149 fp = fscp->fs_filegrp[findex]; 1150 pfgp = &fscp->fs_filegrp[findex]; 1151 1152 while (fp != NULL) { 1153 if (fp == fgp) { 1154 *pfgp = fp->fg_next; 1155 fp->fg_next = NULL; 1156 found++; 1157 break; 1158 } 1159 pfgp = &fp->fg_next; 1160 fp = fp->fg_next; 1161 } 1162 ASSERT(found); 1163 fscp->fs_ref--; 1164 } 1165 1166 /* 1167 * ------------------------------------------------------------------ 1168 * 1169 * filegrp_list_gc 1170 * 1171 * Description: 1172 * Traverses the filegrp lists and throws away any filegrps that are 1173 * not in use. 1174 * The fscp->fs_fslock must be held while this routine is called. 1175 * Arguments: 1176 * fscp fscache object 1177 * Returns: 1178 * Preconditions: 1179 * precond(fscp is a valid fscache object) 1180 */ 1181 1182 void 1183 filegrp_list_gc(struct fscache *fscp) 1184 { 1185 struct filegrp *next, *fgp; 1186 int xx; 1187 1188 ASSERT(MUTEX_HELD(&fscp->fs_fslock)); 1189 1190 for (xx = 0; xx < CFS_FS_FGP_BUCKET_SIZE; xx++) { 1191 for (fgp = fscp->fs_filegrp[xx]; fgp != NULL; fgp = next) { 1192 next = fgp->fg_next; 1193 mutex_enter(&fgp->fg_mutex); 1194 if (fgp->fg_count > 0) { 1195 mutex_exit(&fgp->fg_mutex); 1196 continue; 1197 } 1198 mutex_exit(&fgp->fg_mutex); 1199 filegrp_list_remove(fscp, fgp); 1200 filegrp_destroy(fgp); 1201 } 1202 } 1203 } 1204 1205 /* 1206 * ------------------------------------------------------------------ 1207 * 1208 * filegrp_setup 1209 * 1210 * Description: 1211 * Perform initialization actions on the given filegrp. 1212 * The fgp->fg_mutex must be held while this routine is called. 1213 * Arguments: 1214 * fgp filegrp object 1215 * flags flags to be OR'ed into the fgp flags field 1216 * dorl indicates whether filegrp should be removed from rl or not 1217 * Returns: 1218 * Preconditions: 1219 * precond(fgp is a valid filegrp object) 1220 */ 1221 static void 1222 filegrp_setup(struct filegrp *fgp, int flags, int dorl) 1223 { 1224 ASSERT(MUTEX_HELD(&fgp->fg_mutex)); 1225 1226 /* turn on the specified flags */ 1227 if (flags) 1228 fgp->fg_flags |= flags; 1229 1230 /* if the attrcache file exists, find it */ 1231 if (fgp->fg_flags & CFS_FG_ALLOC_ATTR) 1232 (void) filegrpattr_find(fgp); 1233 1234 /* if the attrcache directory exists, find it */ 1235 if (((fgp->fg_flags & CFS_FG_ALLOC_ATTR) == 0) && 1236 (fgp->fg_flags & CFS_FG_ALLOC_FILE) && 1237 (fgp->fg_header->ach_nffs > 0)) { 1238 (void) filegrpdir_find(fgp); 1239 } 1240 1241 /* move from gc list to attrfile list if necessary */ 1242 if ((dorl != 0) && 1243 ((fgp->fg_flags & CFS_FG_ALLOC_ATTR) == 0) && 1244 (fgp->fg_header->ach_rl_current == CACHEFS_RL_GC)) { 1245 ASSERT(fgp->fg_header->ach_nffs == 0); 1246 if (fgp->fg_count > 0) { 1247 #ifdef CFSDEBUG 1248 cachefs_rlent_verify(fgp->fg_fscp->fs_cache, 1249 CACHEFS_RL_GC, fgp->fg_header->ach_rlno); 1250 #endif /* CFSDEBUG */ 1251 cachefs_rlent_moveto(fgp->fg_fscp->fs_cache, 1252 CACHEFS_RL_ATTRFILE, fgp->fg_header->ach_rlno, 1253 fgp->fg_header->ach_nblks); 1254 fgp->fg_header->ach_rl_current = CACHEFS_RL_ATTRFILE; 1255 fgp->fg_flags |= CFS_FG_UPDATED; 1256 } 1257 } 1258 } 1259 1260 /* 1261 * ------------------------------------------------------------------ 1262 * 1263 * filegrp_list_enable_caching_ro 1264 * 1265 * Description: 1266 * Traverses the filegrp lists and enables the 1267 * use of the cache read-only. 1268 * The fscp->fs_fslock must be held while this routine is called. 1269 * Arguments: 1270 * fscp fscache object 1271 * Returns: 1272 * Preconditions: 1273 * precond(fscp is a valid fscache object) 1274 */ 1275 1276 void 1277 filegrp_list_enable_caching_ro(struct fscache *fscp) 1278 { 1279 struct filegrp *fgp; 1280 int xx; 1281 1282 ASSERT(MUTEX_HELD(&fscp->fs_fslock)); 1283 1284 for (xx = 0; xx < CFS_FS_FGP_BUCKET_SIZE; xx++) { 1285 for (fgp = fscp->fs_filegrp[xx]; fgp != NULL; 1286 fgp = fgp->fg_next) { 1287 mutex_enter(&fgp->fg_mutex); 1288 filegrp_setup(fgp, 0, 0); 1289 mutex_exit(&fgp->fg_mutex); 1290 } 1291 } 1292 } 1293 1294 /* 1295 * ------------------------------------------------------------------ 1296 * 1297 * filegrp_list_enable_caching_rw 1298 * 1299 * Description: 1300 * Traverses the filegrp lists and enables the 1301 * use of the cache read-write. 1302 * The fscp->fs_fslock must be held while this routine is called. 1303 * Arguments: 1304 * fscp fscache object 1305 * Returns: 1306 * Preconditions: 1307 * precond(fscp is a valid fscache object) 1308 * precond(all filegrps must be in the read-only state) 1309 */ 1310 1311 void 1312 filegrp_list_enable_caching_rw(struct fscache *fscp) 1313 { 1314 struct filegrp *fgp; 1315 int xx; 1316 1317 ASSERT(MUTEX_HELD(&fscp->fs_fslock)); 1318 1319 for (xx = 0; xx < CFS_FS_FGP_BUCKET_SIZE; xx++) { 1320 for (fgp = fscp->fs_filegrp[xx]; fgp != NULL; 1321 fgp = fgp->fg_next) { 1322 mutex_enter(&fgp->fg_mutex); 1323 filegrp_setup(fgp, CFS_FG_READ|CFS_FG_WRITE, 1); 1324 mutex_exit(&fgp->fg_mutex); 1325 } 1326 } 1327 } 1328 1329 /* 1330 * ------------------------------------------------------------------ 1331 * 1332 * filegrpdir_find 1333 * 1334 * Description: 1335 * Tries to find the filegrp frontfile directory in the cache. 1336 * If found CFS_FG_ALLOC_FILE is turned off. 1337 * This routine should not be called if CFS_FG_ALLOC_FILE is 1338 * already off. 1339 * Arguments: 1340 * fgp filegrp object 1341 * Returns: 1342 * Returns 0 on success, an errno value on failure. 1343 * Preconditions: 1344 * precond(fgp is a valid filegrp object) 1345 */ 1346 1347 int 1348 filegrpdir_find(filegrp_t *fgp) 1349 { 1350 int error; 1351 vnode_t *dirvp; 1352 char name[CFS_FRONTFILE_NAME_SIZE]; 1353 char *fname; 1354 struct fscache *fscp = fgp->fg_fscp; 1355 1356 if (fgp->fg_flags & CFS_FG_ALLOC_ATTR) 1357 return (ENOENT); 1358 ASSERT(fgp->fg_flags & CFS_FG_ALLOC_FILE); 1359 1360 make_ascii_name(&fgp->fg_id, name); 1361 fname = name; 1362 error = VOP_LOOKUP(fscp->fs_fscdirvp, fname, &dirvp, NULL, 1363 0, NULL, kcred); 1364 if (error == 0) { 1365 fgp->fg_dirvp = dirvp; 1366 fgp->fg_flags &= ~CFS_FG_ALLOC_FILE; 1367 #ifdef CFSDEBUG 1368 if (fgp->fg_header->ach_nffs == 0) { 1369 CFS_DEBUG(CFSDEBUG_FILEGRP) 1370 printf("filegrpdir_find: " 1371 "%s found but no front files\n", fname); 1372 } 1373 #endif 1374 } 1375 #ifdef CFSDEBUG 1376 else if (fgp->fg_header->ach_nffs != 0) { 1377 CFS_DEBUG(CFSDEBUG_FILEGRP) 1378 printf("filegrpdir_find: " 1379 "%s NOT found but %d front files\n", 1380 fname, fgp->fg_header->ach_nffs); 1381 } 1382 #endif 1383 return (error); 1384 } 1385 1386 /* 1387 * ------------------------------------------------------------------ 1388 * 1389 * filegrparttr_find 1390 * 1391 * Description: 1392 * Tries to find the attrcache file for the given filegrp. 1393 * If found the header information is read in and 1394 * CFS_FG_ALLOC_ATTR is turned off. 1395 * This routine should not be called if CFS_FG_ALLOC_ATTR is 1396 * already off. 1397 * Arguments: 1398 * fgp filegrp object 1399 * Returns: 1400 * Returns 0 on success, an errno value on failure. 1401 * Preconditions: 1402 * precond(fgp is a valid filegrp object) 1403 * precond(fgp is readable) 1404 */ 1405 1406 int 1407 filegrpattr_find(struct filegrp *fgp) 1408 { 1409 int error = 0; 1410 struct fscache *fscp = fgp->fg_fscp; 1411 cachefscache_t *cachep = fscp->fs_cache; 1412 vnode_t *attrvp; 1413 struct attrcache_header *ahp; 1414 char name[CFS_FRONTFILE_NAME_SIZE]; 1415 char *fname; 1416 1417 if (fgp->fg_flags & CFS_FG_NOCACHE) 1418 return (ENOENT); 1419 1420 ASSERT(fgp->fg_flags & CFS_FG_ALLOC_ATTR); 1421 make_ascii_name(&fgp->fg_id, name); 1422 fname = name; 1423 error = VOP_LOOKUP(fscp->fs_fsattrdir, fname, 1424 &attrvp, NULL, 0, NULL, kcred); 1425 if (error) { 1426 return (error); 1427 } 1428 ahp = (struct attrcache_header *)cachefs_kmem_zalloc( 1429 fgp->fg_headersize, KM_SLEEP); 1430 1431 error = vn_rdwr(UIO_READ, attrvp, (caddr_t)ahp, 1432 fgp->fg_headersize, 0LL, UIO_SYSSPACE, 1433 0, (rlim64_t)RLIM_INFINITY, kcred, NULL); 1434 if (error) { 1435 cmn_err(CE_WARN, "cachefs: Read attrcache error %d, run fsck", 1436 error); 1437 cachefs_kmem_free(ahp, fgp->fg_headersize); 1438 fgp->fg_flags |= CFS_FG_NOCACHE; 1439 VN_RELE(attrvp); 1440 } else { 1441 ASSERT(ahp->ach_nffs <= ahp->ach_count); 1442 fgp->fg_attrvp = attrvp; 1443 fgp->fg_header = ahp; 1444 fgp->fg_offsets = (struct attrcache_index *)(ahp + 1); 1445 fgp->fg_alloclist = ((u_char *)fgp->fg_offsets) + 1446 (fscp->fs_info.fi_fgsize * 1447 sizeof (struct attrcache_index)); 1448 fgp->fg_flags &= ~CFS_FG_ALLOC_ATTR; 1449 1450 if ((cachep->c_flags & CACHE_CHECK_RLTYPE) && 1451 (ahp->ach_rl_current == CACHEFS_RL_ATTRFILE)) { 1452 rl_entry_t *rlp, rl; 1453 1454 mutex_enter(&cachep->c_contentslock); 1455 error = cachefs_rl_entry_get(cachep, ahp->ach_rlno, 1456 &rlp); 1457 if (error) { 1458 mutex_exit(&cachep->c_contentslock); 1459 cachefs_kmem_free(ahp, fgp->fg_headersize); 1460 fgp->fg_flags |= CFS_FG_NOCACHE; 1461 VN_RELE(attrvp); 1462 return (error); 1463 } 1464 1465 rl = *rlp; 1466 mutex_exit(&cachep->c_contentslock); 1467 1468 if (rl.rl_current != ahp->ach_rl_current) { 1469 ahp->ach_rl_current = rl.rl_current; 1470 fgp->fg_flags |= CFS_FG_UPDATED; 1471 } 1472 } 1473 1474 /* if the attr file is on the rl */ 1475 if (fgp->fg_header->ach_rl_current == CACHEFS_RL_GC) { 1476 #ifdef CFSDEBUG 1477 if (fgp->fg_flags & CFS_FG_WRITE) 1478 cachefs_rlent_verify(fgp->fg_fscp->fs_cache, 1479 CACHEFS_RL_GC, 1480 fgp->fg_header->ach_rlno); 1481 #endif /* CFSDEBUG */ 1482 if ((fgp->fg_count > 0) && 1483 (fgp->fg_flags & CFS_FG_WRITE)) { 1484 /* remove from rl, put on active */ 1485 cachefs_rlent_moveto(fgp->fg_fscp->fs_cache, 1486 CACHEFS_RL_ATTRFILE, 1487 fgp->fg_header->ach_rlno, 1488 fgp->fg_header->ach_nblks); 1489 fgp->fg_header->ach_rl_current = 1490 CACHEFS_RL_ATTRFILE; 1491 fgp->fg_flags |= CFS_FG_UPDATED; 1492 } 1493 } else { 1494 ASSERT(fgp->fg_header->ach_rl_current == 1495 CACHEFS_RL_ATTRFILE); 1496 #ifdef CFSDEBUG 1497 if (fgp->fg_flags & CFS_FG_WRITE) 1498 cachefs_rlent_verify(fgp->fg_fscp->fs_cache, 1499 CACHEFS_RL_ATTRFILE, 1500 fgp->fg_header->ach_rlno); 1501 #endif /* CFSDEBUG */ 1502 } 1503 } 1504 1505 return (error); 1506 } 1507 1508 /* 1509 * ------------------------------------------------------------------ 1510 * 1511 * filegrpdir_create 1512 * 1513 * Description: 1514 * Creates the filegrp directory in the cache. 1515 * If created CFS_FG_ALLOC_FILE is turned off. 1516 * This routine should not be called if CFS_FG_ALLOC_FILE is 1517 * already off. 1518 * Arguments: 1519 * fgp filegrp object 1520 * Returns: 1521 * Returns 0 on success, an errno value on failure. 1522 * Preconditions: 1523 * precond(fgp is a valid filegrp object) 1524 * precond(filegrp is writeable) 1525 */ 1526 1527 int 1528 filegrpdir_create(filegrp_t *fgp) 1529 { 1530 int error; 1531 vnode_t *dirvp = NULL; 1532 struct vattr *attrp = NULL; 1533 char name[CFS_FRONTFILE_NAME_SIZE]; 1534 char *fname; 1535 struct fscache *fscp = fgp->fg_fscp; 1536 1537 ASSERT(fgp->fg_flags & CFS_FG_WRITE); 1538 ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0); 1539 ASSERT(MUTEX_HELD(&fgp->fg_mutex)); 1540 1541 if (fgp->fg_flags & (CFS_FG_ALLOC_ATTR | CFS_FG_NOCACHE)) 1542 return (ENOENT); 1543 1544 /* allocate a 1 block file for the directory */ 1545 error = cachefs_allocfile(fscp->fs_cache); 1546 if (error) { 1547 return (error); 1548 } 1549 error = cachefs_allocblocks(fscp->fs_cache, 1, 1550 fgp->fg_header->ach_rl_current); 1551 if (error) { 1552 cachefs_freefile(fscp->fs_cache); 1553 return (error); 1554 } 1555 1556 /* 1557 * Construct a name for this file group directory and then do a mkdir 1558 */ 1559 make_ascii_name(&fgp->fg_id, name); 1560 fname = name; 1561 attrp = (struct vattr *)cachefs_kmem_alloc(sizeof (struct vattr), 1562 KM_SLEEP); 1563 attrp->va_mode = S_IFDIR | 0777; 1564 attrp->va_uid = 0; 1565 attrp->va_gid = 0; 1566 attrp->va_type = VDIR; 1567 attrp->va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID; 1568 error = VOP_MKDIR(fscp->fs_fscdirvp, fname, attrp, &dirvp, kcred); 1569 if (error) { 1570 fgp->fg_flags |= CFS_FG_NOCACHE; 1571 cachefs_freefile(fscp->fs_cache); 1572 cachefs_freeblocks(fscp->fs_cache, 1, 1573 fgp->fg_header->ach_rl_current); 1574 } else { 1575 fgp->fg_dirvp = dirvp; 1576 fgp->fg_flags &= ~CFS_FG_ALLOC_FILE; 1577 } 1578 1579 if (attrp) 1580 cachefs_kmem_free(attrp, sizeof (*attrp)); 1581 1582 return (error); 1583 } 1584 1585 /* 1586 * ------------------------------------------------------------------ 1587 * 1588 * filegrpattr_create 1589 * 1590 * Description: 1591 * Creates the attrcache file for the given filegrp. 1592 * If created CFS_FG_ALLOC_ATTR is turned off. 1593 * This routine should not be called if CFS_FG_ALLOC_ATTR is 1594 * already off. 1595 * Arguments: 1596 * fgp filegrp object 1597 * Returns: 1598 * Returns 0 on success, an errno value on failure. 1599 * Preconditions: 1600 * precond(fgp is a valid filegrp object) 1601 * precond(filegrp is writable) 1602 */ 1603 1604 int 1605 filegrpattr_create(struct filegrp *fgp) 1606 { 1607 int error; 1608 vnode_t *attrvp = NULL; 1609 struct attrcache_header *ahp = NULL; 1610 int nblks = 0; 1611 int gotrlent = 0; 1612 struct vattr *attrp = NULL; 1613 char name[CFS_FRONTFILE_NAME_SIZE]; 1614 char *fname; 1615 struct fscache *fscp = fgp->fg_fscp; 1616 rl_entry_t rl_ent; 1617 1618 ASSERT(fgp->fg_flags & CFS_FG_WRITE); 1619 1620 if (fgp->fg_flags & CFS_FG_NOCACHE) 1621 return (ENOENT); 1622 1623 cachefs_cache_dirty(fscp->fs_cache, 1); 1624 1625 /* allocate a file for the attrcache */ 1626 error = cachefs_allocfile(fscp->fs_cache); 1627 if (error) { 1628 goto out; 1629 } 1630 1631 make_ascii_name(&fgp->fg_id, name); 1632 fname = name; 1633 attrp = cachefs_kmem_alloc(sizeof (struct vattr), KM_SLEEP); 1634 attrp->va_mode = S_IFREG | 0666; 1635 attrp->va_uid = 0; 1636 attrp->va_gid = 0; 1637 attrp->va_type = VREG; 1638 attrp->va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID; 1639 error = VOP_CREATE(fscp->fs_fsattrdir, fname, attrp, EXCL, 0666, 1640 &attrvp, kcred, 0); 1641 if (error) { 1642 cachefs_freefile(fscp->fs_cache); 1643 goto out; 1644 } 1645 1646 /* alloc blocks for the attrcache header */ 1647 nblks = (fgp->fg_headersize + MAXBSIZE - 1) / MAXBSIZE; 1648 error = cachefs_allocblocks(fscp->fs_cache, nblks, CACHEFS_RL_NONE); 1649 if (error) { 1650 nblks = 0; 1651 goto out; 1652 } 1653 1654 /* Construct an attrcache header */ 1655 ahp = cachefs_kmem_zalloc(fgp->fg_headersize, KM_SLEEP); 1656 1657 /* write out the header to allocate space on ufs */ 1658 error = vn_rdwr(UIO_WRITE, attrvp, (caddr_t)ahp, 1659 fgp->fg_headersize, 0LL, UIO_SYSSPACE, 0, (rlim64_t)RLIM_INFINITY, 1660 kcred, NULL); 1661 if (error) 1662 goto out; 1663 error = filegrp_write_space(attrvp, (offset_t)fgp->fg_headersize, 1664 (nblks * MAXBSIZE) - fgp->fg_headersize); 1665 if (error) 1666 goto out; 1667 error = VOP_FSYNC(attrvp, FSYNC, kcred); 1668 if (error) 1669 goto out; 1670 1671 /* allocate an rl entry and mark it as an attrcache entry */ 1672 rl_ent.rl_fileno = fgp->fg_id.cid_fileno; 1673 rl_ent.rl_local = (fgp->fg_id.cid_flags & CFS_CID_LOCAL) ? 1 : 0; 1674 rl_ent.rl_fsid = fscp->fs_cfsid; 1675 rl_ent.rl_attrc = 1; 1676 error = cachefs_rl_alloc(fscp->fs_cache, &rl_ent, &ahp->ach_rlno); 1677 if (error) 1678 goto out; 1679 gotrlent = 1; 1680 if (fgp->fg_count == 0) { 1681 /* put on the gc */ 1682 cachefs_rlent_moveto(fgp->fg_fscp->fs_cache, CACHEFS_RL_GC, 1683 ahp->ach_rlno, nblks); 1684 ahp->ach_rl_current = CACHEFS_RL_GC; 1685 } else { 1686 /* put on attrfile list */ 1687 cachefs_rlent_moveto(fgp->fg_fscp->fs_cache, 1688 CACHEFS_RL_ATTRFILE, ahp->ach_rlno, nblks); 1689 ahp->ach_rl_current = CACHEFS_RL_ATTRFILE; 1690 } 1691 1692 out: 1693 if (error) { 1694 fgp->fg_flags |= CFS_FG_NOCACHE; 1695 if (attrvp) { 1696 VN_RELE(attrvp); 1697 (void) VOP_REMOVE(fscp->fs_fsattrdir, fname, kcred); 1698 cachefs_freefile(fscp->fs_cache); 1699 } 1700 if (nblks) 1701 cachefs_freeblocks(fscp->fs_cache, nblks, 1702 CACHEFS_RL_NONE); 1703 if (gotrlent) 1704 cachefs_rlent_moveto(fscp->fs_cache, 1705 CACHEFS_RL_FREE, ahp->ach_rlno, 0); 1706 if (ahp) 1707 cachefs_kmem_free(ahp, fgp->fg_headersize); 1708 } else { 1709 fgp->fg_attrvp = attrvp; 1710 fgp->fg_header = ahp; 1711 fgp->fg_offsets = (struct attrcache_index *)(ahp + 1); 1712 fgp->fg_alloclist = ((u_char *)fgp->fg_offsets) + 1713 (fscp->fs_info.fi_fgsize * 1714 sizeof (struct attrcache_index)); 1715 ahp->ach_count = 0; 1716 ahp->ach_nffs = 0; 1717 ahp->ach_nblks = nblks; 1718 fgp->fg_flags &= ~CFS_FG_ALLOC_ATTR; 1719 fgp->fg_flags |= CFS_FG_UPDATED; 1720 } 1721 1722 if (attrp) 1723 cachefs_kmem_free(attrp, sizeof (*attrp)); 1724 1725 return (error); 1726 } 1727 1728 /* 1729 * ------------------------------------------------------------------ 1730 * 1731 * filegrp_cid_to_slot 1732 * 1733 * Description: 1734 * Takes a file and returns the offset to the metadata 1735 * slot for the specified filegrp. 1736 * Arguments: 1737 * fgp filegrp object 1738 * cidp file to map to an offset 1739 * Returns: 1740 * Returns the offset or 0 if the slot is not allocated yet 1741 * or it is invalid. 1742 * Preconditions: 1743 * precond(fgp is a valid filegrp object) 1744 * precond(fgp is not ALLOC_PENDING or NOCACHE) 1745 */ 1746 1747 int 1748 filegrp_cid_to_slot(filegrp_t *fgp, cfs_cid_t *cidp) 1749 { 1750 int xx; 1751 int slot; 1752 int index; 1753 1754 index = (int) (cidp->cid_fileno - fgp->fg_id.cid_fileno); 1755 1756 if (index > fgp->fg_fscp->fs_info.fi_fgsize) { 1757 cmn_err(CE_WARN, "cachefs: attrcache error, run fsck"); 1758 return (0); 1759 } 1760 1761 slot = fgp->fg_offsets[index].ach_offset; 1762 if (slot == 0) 1763 return (0); 1764 1765 xx = fgp->fg_filesize - (int)sizeof (struct cfs_cachefs_metadata); 1766 if ((slot < fgp->fg_headersize) || (xx < slot)) { 1767 cmn_err(CE_WARN, "cachefs: attrcache error, run fsck"); 1768 return (0); 1769 } 1770 1771 return (slot); 1772 } 1773 1774 /* 1775 * 1776 * filegrp_write_space 1777 * 1778 * Description: 1779 * Writes garbage data to the specified file starting 1780 * at the specified location for the specified number of bytes. 1781 * slot for the specified filegrp. 1782 * Arguments: 1783 * vp vnode to write to 1784 * offset offset to write at 1785 * cnt number of bytes to write 1786 * Returns: 1787 * Returns 0 for success or on error the result of the 1788 * last vn_rdwr call. 1789 * Preconditions: 1790 * precond(vp) 1791 */ 1792 1793 int 1794 filegrp_write_space(vnode_t *vp, offset_t offset, ssize_t cnt) 1795 { 1796 char *bufp; 1797 int xx; 1798 int error = 0; 1799 1800 bufp = (char *)cachefs_kmem_zalloc(MAXBSIZE, KM_SLEEP); 1801 while (cnt > 0) { 1802 if (cnt > MAXBSIZE) 1803 xx = MAXBSIZE; 1804 else 1805 xx = (int)cnt; 1806 error = vn_rdwr(UIO_WRITE, vp, (caddr_t)bufp, 1807 xx, offset, UIO_SYSSPACE, 0, (rlim64_t)RLIM_INFINITY, 1808 kcred, NULL); 1809 if (error) 1810 break; 1811 offset += xx; 1812 cnt -= xx; 1813 } 1814 cachefs_kmem_free(bufp, MAXBSIZE); 1815 return (error); 1816 } 1817