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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <sys/param.h> 29 #include <sys/types.h> 30 #include <sys/systm.h> 31 #include <sys/cred.h> 32 #include <sys/proc.h> 33 #include <sys/user.h> 34 #include <sys/vfs.h> 35 #include <sys/vnode.h> 36 #include <sys/pathname.h> 37 #include <sys/uio.h> 38 #include <sys/tiuser.h> 39 #include <sys/sysmacros.h> 40 #include <sys/kmem.h> 41 #include <sys/mount.h> 42 #include <sys/ioctl.h> 43 #include <sys/statvfs.h> 44 #include <sys/errno.h> 45 #include <sys/debug.h> 46 #include <sys/cmn_err.h> 47 #include <sys/utsname.h> 48 #include <sys/bootconf.h> 49 #include <sys/modctl.h> 50 #include <sys/file.h> 51 #include <sys/stat.h> 52 53 #include <vm/hat.h> 54 #include <vm/as.h> 55 #include <vm/page.h> 56 #include <vm/pvn.h> 57 #include <vm/seg.h> 58 #include <vm/seg_map.h> 59 #include <vm/seg_vn.h> 60 #include <vm/rm.h> 61 #include <sys/fs/cachefs_fs.h> 62 #include <sys/fs/cachefs_log.h> 63 64 struct kmem_cache *cachefs_filegrp_cache = NULL; 65 66 #if (defined(_SYSCALL32_IMPL) || defined(_LP64)) 67 68 #define CACHEFS_ALLOC_CFS_METADATA(p, inp) \ 69 p = cachefs_kmem_zalloc(sizeof (struct cfs_cachefs_metadata), KM_SLEEP) 70 71 #define CACHEFS_FREE_CFS_METADATA(p) \ 72 cachefs_kmem_free(p, sizeof (struct cfs_cachefs_metadata)) 73 74 /* CACHEFS_COPY_COMMON_METADATA_FIELDS - common code for the metadata copy */ 75 #define CACHEFS_COPY_COMMON_METADATA_FIELDS(inmdp, outmdp) \ 76 (outmdp)->md_aclclass = (inmdp)->md_aclclass; \ 77 CACHEFS_FID_COPY(&(inmdp)->md_cookie, &(outmdp)->md_cookie); \ 78 (outmdp)->md_flags = (inmdp)->md_flags; \ 79 (outmdp)->md_rlno = (inmdp)->md_rlno; \ 80 (outmdp)->md_rltype = (inmdp)->md_rltype; \ 81 (outmdp)->md_consttype = (inmdp)->md_consttype; \ 82 CACHEFS_FID_COPY(&(inmdp)->md_fid, &(outmdp)->md_fid); \ 83 (outmdp)->md_frontblks = (inmdp)->md_frontblks; \ 84 (outmdp)->md_gen = (inmdp)->md_gen; \ 85 (outmdp)->md_parent = (inmdp)->md_parent; \ 86 (outmdp)->md_resettimes = (inmdp)->md_resettimes; \ 87 (outmdp)->md_localfileno = (inmdp)->md_localfileno; \ 88 (outmdp)->md_resetfileno = (inmdp)->md_resetfileno; \ 89 (outmdp)->md_seq = (inmdp)->md_seq; \ 90 (outmdp)->md_allocents = (inmdp)->md_allocents; \ 91 bcopy(&(inmdp)->md_allocinfo, &(outmdp)->md_allocinfo, \ 92 MIN(sizeof (inmdp)->md_allocinfo, sizeof (outmdp)->md_allocinfo)) 93 94 #define CACHEFS_COPY_METADATA_TO_CFS_METADATA(inmdp, outmdp, error) \ 95 CACHEFS_VATTR_TO_CFS_VATTR_COPY(&(inmdp)->md_vattr, \ 96 &(outmdp)->md_vattr, error); \ 97 CACHEFS_TS_TO_CFS_TS_COPY(&(inmdp)->md_timestamp, \ 98 &(outmdp)->md_timestamp, error); \ 99 CACHEFS_TS_TO_CFS_TS_COPY(&(inmdp)->md_x_time, \ 100 &(outmdp)->md_x_time, error); \ 101 CACHEFS_TS_TO_CFS_TS_COPY(&(inmdp)->md_localmtime, \ 102 &(outmdp)->md_localmtime, error); \ 103 CACHEFS_TS_TO_CFS_TS_COPY(&(inmdp)->md_localctime, \ 104 &(outmdp)->md_localctime, error); \ 105 CACHEFS_COPY_COMMON_METADATA_FIELDS(inmdp, outmdp) 106 107 #define CACHEFS_COPY_CFS_METADATA_TO_METADATA(inmdp, outmdp) \ 108 CACHEFS_CFS_VATTR_TO_VATTR_COPY(&(inmdp)->md_vattr, \ 109 &(outmdp)->md_vattr); \ 110 CACHEFS_CFS_TS_TO_TS_COPY(&(inmdp)->md_timestamp, \ 111 &(outmdp)->md_timestamp); \ 112 CACHEFS_CFS_TS_TO_TS_COPY(&(inmdp)->md_x_time, \ 113 &(outmdp)->md_x_time); \ 114 CACHEFS_CFS_TS_TO_TS_COPY(&(inmdp)->md_localmtime, \ 115 &(outmdp)->md_localmtime); \ 116 CACHEFS_CFS_TS_TO_TS_COPY(&(inmdp)->md_localctime, \ 117 &(outmdp)->md_localctime); \ 118 CACHEFS_COPY_COMMON_METADATA_FIELDS(inmdp, outmdp) 119 120 #else /* not (_SYSCALL32_IMPL || _LP64) */ 121 122 #define CACHEFS_ALLOC_CFS_METADATA(p, inp) \ 123 p = (cfs_cachefs_metadata_t *)(inp) 124 125 #define CACHEFS_FREE_CFS_METADATA(p) 126 127 #define CACHEFS_COPY_METADATA_TO_CFS_METADATA(inmdp, outmdp, error) 128 129 #define CACHEFS_COPY_CFS_METADATA_TO_METADATA(inmdp, outmdp) 130 131 #endif /* _SYSCALL32_IMPL || _LP64 */ 132 133 /* forward references */ 134 int filegrp_write_space(vnode_t *vp, offset_t offset, ssize_t cnt); 135 int filegrpattr_find(struct filegrp *fgp); 136 int filegrpattr_create(struct filegrp *fgp); 137 138 int 139 /*ARGSUSED*/ 140 filegrp_cache_create(void *voidp, void *cdrarg, int kmflags) 141 { 142 filegrp_t *fgp = (filegrp_t *)voidp; 143 144 mutex_init(&fgp->fg_mutex, NULL, MUTEX_DEFAULT, NULL); 145 mutex_init(&fgp->fg_cnodelock, NULL, MUTEX_DEFAULT, NULL); 146 return (0); 147 } 148 149 void 150 /*ARGSUSED*/ 151 filegrp_cache_destroy(void *voidp, void *cdrarg) 152 { 153 filegrp_t *fgp = (filegrp_t *)voidp; 154 155 mutex_destroy(&fgp->fg_mutex); 156 mutex_destroy(&fgp->fg_cnodelock); 157 } 158 159 /* 160 * ------------------------------------------------------------------ 161 * 162 * filegrp_create 163 * 164 * Description: 165 * Creates a filegrp object for the specified fscache. 166 * The CFS_FG_ALLOC_{ATTR, FILE} bits will be set in fg_flags 167 * if the cache is in NOCACHE and NOFILL mode or if 168 * the directory does not exist yet. 169 * The filegrp object maintains a reference to the specified 170 * fscache. 171 * Arguments: 172 * fscp fscache to create the file group in 173 * cidp start cid for the file group 174 * Returns: 175 * Returns the created filegrp object. 176 * Preconditions: 177 * precond(fscp) 178 * precond(cidp) 179 * precond(fscp->fs_info.fi_fgsize > 0) 180 */ 181 #define Bugid_1249206_notfixed 182 #ifdef Bugid_1249206_notfixed 183 int bugid_1249206 = 0; 184 #endif 185 filegrp_t * 186 filegrp_create(struct fscache *fscp, cfs_cid_t *cidp) 187 { 188 filegrp_t *fgp; 189 int fgsize; 190 int flags; 191 ino64_t nfgsize; 192 193 fgsize = fscp->fs_info.fi_fgsize; 194 195 fgp = (filegrp_t *) 196 kmem_cache_alloc(cachefs_filegrp_cache, KM_SLEEP); 197 198 fgp->fg_flags = CFS_FG_ALLOC_ATTR | CFS_FG_ALLOC_FILE; 199 fgp->fg_count = 0; 200 fgp->fg_id = *cidp; 201 #ifdef Bugid_1249206_notfixed 202 if (bugid_1249206) 203 cmn_err(CE_CONT, "fg_id assigned value is %" PRId64 "\n", 204 fgp->fg_id.cid_fileno); 205 #endif 206 nfgsize = (fgp->fg_id.cid_fileno / (ino64_t)fgsize); 207 fgp->fg_id.cid_fileno = (ino64_t)(nfgsize * (ino64_t)fgsize); 208 #ifdef Bugid_1249206_notfixed 209 if (bugid_1249206) { 210 cmn_err(CE_CONT, 211 "cid_fileno for fscp %p fgp %p is %" PRId64 "\n", 212 (void *)fscp, (void *)fgp, 213 fgp->fg_id.cid_fileno); 214 cmn_err(CE_CONT, 215 "sent fileno is %" PRId64 " fgsize %d nfgsize %" PRId64 216 "\n", cidp->cid_fileno, fgsize, nfgsize); 217 } 218 #endif 219 fgp->fg_fscp = fscp; 220 fgp->fg_cnodelist = NULL; 221 fgp->fg_next = NULL; 222 fgp->fg_dirvp = NULL; 223 fgp->fg_attrvp = NULL; 224 fgp->fg_header = NULL; 225 fgp->fg_offsets = NULL; 226 fgp->fg_alloclist = NULL; 227 228 fgp->fg_headersize = (u_int)sizeof (struct attrcache_header) + 229 (fgsize * (u_int)sizeof (struct attrcache_index)) + 230 ((fgsize + 7) >> 3); 231 232 fgp->fg_filesize = fgp->fg_headersize + 233 (fgsize * (u_int)sizeof (struct cfs_cachefs_metadata)); 234 235 flags = fscp->fs_flags; 236 if (flags & CFS_FS_READ) { 237 fgp->fg_flags |= CFS_FG_READ; 238 if (flags & CFS_FS_WRITE) { 239 fgp->fg_flags |= CFS_FG_WRITE; 240 } 241 } 242 243 if (fgp->fg_flags & CFS_FG_READ) { 244 /* find the attrcache file and frontfile directory */ 245 (void) filegrpattr_find(fgp); 246 247 /* 248 * XXX: we can tell from the file count in the attrcache 249 * whether we can expect to find a front file dir or 250 * not. If not, we can save the lookup here... 251 */ 252 (void) filegrpdir_find(fgp); 253 } 254 255 return (fgp); 256 } 257 258 /* 259 * ------------------------------------------------------------------ 260 * 261 * filegrp_destroy 262 * 263 * Description: 264 * Destroys the filegrp object and releases any kernel 265 * resource associated with it. 266 * Additionally if the on disk file group directory does 267 * not contain any front files it is removed. 268 * Arguments: 269 * fgp filegrp object to destroy 270 * Returns: 271 * Preconditions: 272 * precond(fgp is a valid filegrp object) 273 * precond(fgp->fg_count == 0) 274 * precond(fgp->fg_next == NULL) 275 */ 276 277 void 278 filegrp_destroy(filegrp_t *fgp) 279 { 280 struct fscache *fscp = fgp->fg_fscp; 281 char name[CFS_FRONTFILE_NAME_SIZE]; 282 char *fname; 283 int error; 284 285 ASSERT(fgp->fg_count == 0); 286 ASSERT(fgp->fg_next == NULL); 287 288 if (fgp->fg_attrvp) { 289 if (fgp->fg_flags & CFS_FG_UPDATED) { 290 error = filegrp_sync(fgp); 291 if (error) 292 cmn_err(CE_WARN, 293 "cachefs: UFS error on cache, " 294 "run fsck %d", error); 295 } 296 VN_RELE(fgp->fg_attrvp); 297 } 298 if (fgp->fg_header) { 299 /* 300 * If there are no attrcache entries in use and 301 * if we can modify the cache. 302 */ 303 if ((fgp->fg_header->ach_count == 0) && 304 (fgp->fg_flags & CFS_FG_WRITE)) { 305 ASSERT(fgp->fg_header->ach_nffs == 0); 306 307 /* remove attrcache file from the rl list */ 308 ASSERT(fgp->fg_header->ach_rl_current == 309 CACHEFS_RL_GC); 310 #ifdef CFSDEBUG 311 cachefs_rlent_verify(fscp->fs_cache, CACHEFS_RL_GC, 312 fgp->fg_header->ach_rlno); 313 #endif /* CFSDEBUG */ 314 315 /* 316 * XXX sam: since we're blowing away the 317 * attrcache file, i guess i don't need to set 318 * ach_rl_current to CACHEFS_RL_NONE and 319 * sync the attrcache file, right? 320 * 321 * fgp->fg_header->ach_rl_current = CACHEFS_RL_NONE; 322 * fgp->fg_flags |= CFS_FG_UPDATED; 323 */ 324 325 /* remove the attrcache file */ 326 make_ascii_name(&fgp->fg_id, name); 327 fname = name; 328 error = VOP_REMOVE(fscp->fs_fsattrdir, fname, kcred); 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 refrences 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 refrences 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 refrences 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); 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); 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, (cred_t *)NULL, 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 u_char 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] != (u_char)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 u_char 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); 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); 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, (cred_t *)NULL, 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 = ((u_char *)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); 1570 if (error) { 1571 fgp->fg_flags |= CFS_FG_NOCACHE; 1572 cachefs_freefile(fscp->fs_cache); 1573 cachefs_freeblocks(fscp->fs_cache, 1, 1574 fgp->fg_header->ach_rl_current); 1575 } else { 1576 fgp->fg_dirvp = dirvp; 1577 fgp->fg_flags &= ~CFS_FG_ALLOC_FILE; 1578 } 1579 1580 if (attrp) 1581 cachefs_kmem_free(attrp, sizeof (*attrp)); 1582 1583 return (error); 1584 } 1585 1586 /* 1587 * ------------------------------------------------------------------ 1588 * 1589 * filegrpattr_create 1590 * 1591 * Description: 1592 * Creates the attrcache file for the given filegrp. 1593 * If created CFS_FG_ALLOC_ATTR is turned off. 1594 * This routine should not be called if CFS_FG_ALLOC_ATTR is 1595 * already off. 1596 * Arguments: 1597 * fgp filegrp object 1598 * Returns: 1599 * Returns 0 on success, an errno value on failure. 1600 * Preconditions: 1601 * precond(fgp is a valid filegrp object) 1602 * precond(filegrp is writable) 1603 */ 1604 1605 int 1606 filegrpattr_create(struct filegrp *fgp) 1607 { 1608 int error; 1609 vnode_t *attrvp = NULL; 1610 struct attrcache_header *ahp = NULL; 1611 int nblks = 0; 1612 int gotrlent = 0; 1613 struct vattr *attrp = NULL; 1614 char name[CFS_FRONTFILE_NAME_SIZE]; 1615 char *fname; 1616 struct fscache *fscp = fgp->fg_fscp; 1617 rl_entry_t rl_ent; 1618 1619 ASSERT(fgp->fg_flags & CFS_FG_WRITE); 1620 1621 if (fgp->fg_flags & CFS_FG_NOCACHE) 1622 return (ENOENT); 1623 1624 cachefs_cache_dirty(fscp->fs_cache, 1); 1625 1626 /* allocate a file for the attrcache */ 1627 error = cachefs_allocfile(fscp->fs_cache); 1628 if (error) { 1629 goto out; 1630 } 1631 1632 make_ascii_name(&fgp->fg_id, name); 1633 fname = name; 1634 attrp = cachefs_kmem_alloc(sizeof (struct vattr), KM_SLEEP); 1635 attrp->va_mode = S_IFREG | 0666; 1636 attrp->va_uid = 0; 1637 attrp->va_gid = 0; 1638 attrp->va_type = VREG; 1639 attrp->va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID; 1640 error = VOP_CREATE(fscp->fs_fsattrdir, fname, attrp, EXCL, 0666, 1641 &attrvp, kcred, 0); 1642 if (error) { 1643 cachefs_freefile(fscp->fs_cache); 1644 goto out; 1645 } 1646 1647 /* alloc blocks for the attrcache header */ 1648 nblks = (fgp->fg_headersize + MAXBSIZE - 1) / MAXBSIZE; 1649 error = cachefs_allocblocks(fscp->fs_cache, nblks, CACHEFS_RL_NONE); 1650 if (error) { 1651 nblks = 0; 1652 goto out; 1653 } 1654 1655 /* Construct an attrcache header */ 1656 ahp = cachefs_kmem_zalloc(fgp->fg_headersize, KM_SLEEP); 1657 1658 /* write out the header to allocate space on ufs */ 1659 error = vn_rdwr(UIO_WRITE, attrvp, (caddr_t)ahp, 1660 fgp->fg_headersize, 0LL, UIO_SYSSPACE, 0, (rlim64_t)RLIM_INFINITY, 1661 kcred, NULL); 1662 if (error) 1663 goto out; 1664 error = filegrp_write_space(attrvp, (offset_t)fgp->fg_headersize, 1665 (nblks * MAXBSIZE) - fgp->fg_headersize); 1666 if (error) 1667 goto out; 1668 error = VOP_FSYNC(attrvp, FSYNC, kcred); 1669 if (error) 1670 goto out; 1671 1672 /* allocate an rl entry and mark it as an attrcache entry */ 1673 rl_ent.rl_fileno = fgp->fg_id.cid_fileno; 1674 rl_ent.rl_local = (fgp->fg_id.cid_flags & CFS_CID_LOCAL) ? 1 : 0; 1675 rl_ent.rl_fsid = fscp->fs_cfsid; 1676 rl_ent.rl_attrc = 1; 1677 error = cachefs_rl_alloc(fscp->fs_cache, &rl_ent, &ahp->ach_rlno); 1678 if (error) 1679 goto out; 1680 gotrlent = 1; 1681 if (fgp->fg_count == 0) { 1682 /* put on the gc */ 1683 cachefs_rlent_moveto(fgp->fg_fscp->fs_cache, CACHEFS_RL_GC, 1684 ahp->ach_rlno, nblks); 1685 ahp->ach_rl_current = CACHEFS_RL_GC; 1686 } else { 1687 /* put on attrfile list */ 1688 cachefs_rlent_moveto(fgp->fg_fscp->fs_cache, 1689 CACHEFS_RL_ATTRFILE, ahp->ach_rlno, nblks); 1690 ahp->ach_rl_current = CACHEFS_RL_ATTRFILE; 1691 } 1692 1693 out: 1694 if (error) { 1695 fgp->fg_flags |= CFS_FG_NOCACHE; 1696 if (attrvp) { 1697 VN_RELE(attrvp); 1698 (void) VOP_REMOVE(fscp->fs_fsattrdir, fname, kcred); 1699 cachefs_freefile(fscp->fs_cache); 1700 } 1701 if (nblks) 1702 cachefs_freeblocks(fscp->fs_cache, nblks, 1703 CACHEFS_RL_NONE); 1704 if (gotrlent) 1705 cachefs_rlent_moveto(fscp->fs_cache, 1706 CACHEFS_RL_FREE, ahp->ach_rlno, 0); 1707 if (ahp) 1708 cachefs_kmem_free(ahp, fgp->fg_headersize); 1709 } else { 1710 fgp->fg_attrvp = attrvp; 1711 fgp->fg_header = ahp; 1712 fgp->fg_offsets = (struct attrcache_index *)(ahp + 1); 1713 fgp->fg_alloclist = ((u_char *)fgp->fg_offsets) + 1714 (fscp->fs_info.fi_fgsize * 1715 sizeof (struct attrcache_index)); 1716 ahp->ach_count = 0; 1717 ahp->ach_nffs = 0; 1718 ahp->ach_nblks = nblks; 1719 fgp->fg_flags &= ~CFS_FG_ALLOC_ATTR; 1720 fgp->fg_flags |= CFS_FG_UPDATED; 1721 } 1722 1723 if (attrp) 1724 cachefs_kmem_free(attrp, sizeof (*attrp)); 1725 1726 return (error); 1727 } 1728 1729 /* 1730 * ------------------------------------------------------------------ 1731 * 1732 * filegrp_cid_to_slot 1733 * 1734 * Description: 1735 * Takes a file and returns the offset to the metadata 1736 * slot for the specified filegrp. 1737 * Arguments: 1738 * fgp filegrp object 1739 * cidp file to map to an offset 1740 * Returns: 1741 * Returns the offset or 0 if the slot is not allocated yet 1742 * or it is invalid. 1743 * Preconditions: 1744 * precond(fgp is a valid filegrp object) 1745 * precond(fgp is not ALLOC_PENDING or NOCACHE) 1746 */ 1747 1748 int 1749 filegrp_cid_to_slot(filegrp_t *fgp, cfs_cid_t *cidp) 1750 { 1751 int xx; 1752 int slot; 1753 int index; 1754 1755 index = (int) (cidp->cid_fileno - fgp->fg_id.cid_fileno); 1756 1757 if (index > fgp->fg_fscp->fs_info.fi_fgsize) { 1758 cmn_err(CE_WARN, "cachefs: attrcache error, run fsck"); 1759 return (0); 1760 } 1761 1762 slot = fgp->fg_offsets[index].ach_offset; 1763 if (slot == 0) 1764 return (0); 1765 1766 xx = fgp->fg_filesize - (int)sizeof (struct cfs_cachefs_metadata); 1767 if ((slot < fgp->fg_headersize) || (xx < slot)) { 1768 cmn_err(CE_WARN, "cachefs: attrcache error, run fsck"); 1769 return (0); 1770 } 1771 1772 return (slot); 1773 } 1774 1775 /* 1776 * 1777 * filegrp_write_space 1778 * 1779 * Description: 1780 * Writes garbage data to the specified file starting 1781 * at the specified location for the specified number of bytes. 1782 * slot for the specified filegrp. 1783 * Arguments: 1784 * vp vnode to write to 1785 * offset offset to write at 1786 * cnt number of bytes to write 1787 * Returns: 1788 * Returns 0 for success or on error the result of the 1789 * last vn_rdwr call. 1790 * Preconditions: 1791 * precond(vp) 1792 */ 1793 1794 int 1795 filegrp_write_space(vnode_t *vp, offset_t offset, ssize_t cnt) 1796 { 1797 char *bufp; 1798 int xx; 1799 int error = 0; 1800 1801 bufp = (char *)cachefs_kmem_zalloc(MAXBSIZE, KM_SLEEP); 1802 while (cnt > 0) { 1803 if (cnt > MAXBSIZE) 1804 xx = MAXBSIZE; 1805 else 1806 xx = (int)cnt; 1807 error = vn_rdwr(UIO_WRITE, vp, (caddr_t)bufp, 1808 xx, offset, UIO_SYSSPACE, 0, (rlim64_t)RLIM_INFINITY, 1809 kcred, NULL); 1810 if (error) 1811 break; 1812 offset += xx; 1813 cnt -= xx; 1814 } 1815 cachefs_kmem_free(bufp, MAXBSIZE); 1816 return (error); 1817 } 1818