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