1 /* $NetBSD: lfs_subr.c,v 1.116 2026/10/30 03:40:41 perseant Exp $ */ 2 3 /*- 4 * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Konrad E. Schroder <perseant (at) hhhh.org>. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 /* 32 * Copyright (c) 1991, 1993 33 * The Regents of the University of California. All rights reserved. 34 * 35 * Redistribution and use in source and binary forms, with or without 36 * modification, are permitted provided that the following conditions 37 * are met: 38 * 1. Redistributions of source code must retain the above copyright 39 * notice, this list of conditions and the following disclaimer. 40 * 2. Redistributions in binary form must reproduce the above copyright 41 * notice, this list of conditions and the following disclaimer in the 42 * documentation and/or other materials provided with the distribution. 43 * 3. Neither the name of the University nor the names of its contributors 44 * may be used to endorse or promote products derived from this software 45 * without specific prior written permission. 46 * 47 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 50 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 57 * SUCH DAMAGE. 58 * 59 * @(#)lfs_subr.c 8.4 (Berkeley) 5/8/95 60 */ 61 62 #include <sys/cdefs.h> 63 __KERNEL_RCSID(0, "$NetBSD: lfs_subr.c,v 1.116 2026/10/30 03:40:41 perseant Exp $"); 64 65 #include <sys/param.h> 66 #include <sys/systm.h> 67 #include <sys/namei.h> 68 #include <sys/vnode.h> 69 #include <sys/buf.h> 70 #include <sys/mount.h> 71 #include <sys/malloc.h> 72 #include <sys/proc.h> 73 #include <sys/kauth.h> 74 75 #include <ufs/lfs/ulfs_inode.h> 76 #include <ufs/lfs/lfs.h> 77 #include <ufs/lfs/lfs_accessors.h> 78 #include <ufs/lfs/lfs_kernel.h> 79 #include <ufs/lfs/lfs_extern.h> 80 81 #ifdef DEBUG 82 const char *lfs_res_names[LFS_NB_COUNT] = { 83 "summary", 84 "superblock", 85 "file block", 86 "cluster", 87 "clean", 88 "blkiov", 89 }; 90 #endif 91 92 int lfs_res_qty[LFS_NB_COUNT] = { 93 LFS_N_SUMMARIES, 94 LFS_N_SBLOCKS, 95 LFS_N_IBLOCKS, 96 LFS_N_CLUSTERS, 97 LFS_N_CLEAN, 98 LFS_N_BLKIOV, 99 }; 100 101 void 102 lfs_setup_resblks(struct lfs *fs) 103 { 104 int i, j; 105 int maxbpp; 106 107 ASSERT_NO_SEGLOCK(fs); 108 fs->lfs_resblk = malloc(LFS_N_TOTAL * sizeof(res_t), M_SEGMENT, 109 M_WAITOK); 110 for (i = 0; i < LFS_N_TOTAL; i++) { 111 fs->lfs_resblk[i].inuse = 0; 112 fs->lfs_resblk[i].p = NULL; 113 } 114 for (i = 0; i < LFS_RESHASH_WIDTH; i++) 115 LIST_INIT(fs->lfs_reshash + i); 116 117 /* 118 * These types of allocations can be larger than a page, 119 * so we can't use the pool subsystem for them. 120 */ 121 for (i = 0, j = 0; j < LFS_N_SUMMARIES; j++, i++) 122 fs->lfs_resblk[i].size = lfs_sb_getsumsize(fs); 123 for (j = 0; j < LFS_N_SBLOCKS; j++, i++) 124 fs->lfs_resblk[i].size = LFS_SBPAD; 125 for (j = 0; j < LFS_N_IBLOCKS; j++, i++) 126 fs->lfs_resblk[i].size = lfs_sb_getbsize(fs); 127 for (j = 0; j < LFS_N_CLUSTERS; j++, i++) 128 fs->lfs_resblk[i].size = MAXPHYS; 129 for (j = 0; j < LFS_N_CLEAN; j++, i++) 130 fs->lfs_resblk[i].size = MAXPHYS; 131 for (j = 0; j < LFS_N_BLKIOV; j++, i++) 132 fs->lfs_resblk[i].size = LFS_MARKV_MAXBLKCNT * sizeof(BLOCK_INFO); 133 134 for (i = 0; i < LFS_N_TOTAL; i++) { 135 fs->lfs_resblk[i].p = malloc(fs->lfs_resblk[i].size, 136 M_SEGMENT, M_WAITOK); 137 } 138 139 /* 140 * Initialize pools for small types (XXX is BPP small?) 141 */ 142 pool_init(&fs->lfs_clpool, sizeof(struct lfs_cluster), 0, 0, 0, 143 "lfsclpl", &pool_allocator_nointr, IPL_NONE); 144 pool_init(&fs->lfs_segpool, sizeof(struct segment), 0, 0, 0, 145 "lfssegpool", &pool_allocator_nointr, IPL_NONE); 146 /* XXX: should this int32 be 32/64? */ 147 maxbpp = ((lfs_sb_getsumsize(fs) - SEGSUM_SIZE(fs)) / sizeof(int32_t) + 2); 148 maxbpp = MIN(maxbpp, lfs_segsize(fs) / lfs_sb_getfsize(fs) + 2); 149 pool_init(&fs->lfs_bpppool, maxbpp * sizeof(struct buf *), 0, 0, 0, 150 "lfsbpppl", &pool_allocator_nointr, IPL_NONE); 151 } 152 153 void 154 lfs_free_resblks(struct lfs *fs) 155 { 156 int i; 157 158 pool_destroy(&fs->lfs_bpppool); 159 pool_destroy(&fs->lfs_segpool); 160 pool_destroy(&fs->lfs_clpool); 161 162 mutex_enter(&lfs_lock); 163 for (i = 0; i < LFS_N_TOTAL; i++) { 164 while (fs->lfs_resblk[i].inuse) 165 mtsleep(&fs->lfs_resblk, PRIBIO + 1, "lfs_free", 0, 166 &lfs_lock); 167 if (fs->lfs_resblk[i].p != NULL) 168 free(fs->lfs_resblk[i].p, M_SEGMENT); 169 } 170 free(fs->lfs_resblk, M_SEGMENT); 171 mutex_exit(&lfs_lock); 172 } 173 174 static unsigned int 175 lfs_mhash(void *vp) 176 { 177 return (unsigned int)(((unsigned long)vp) >> 2) % LFS_RESHASH_WIDTH; 178 } 179 180 /* 181 * Return memory of the given size for the given purpose, or use one of a 182 * number of spare last-resort buffers, if malloc returns NULL. 183 */ 184 void * 185 lfs_malloc(struct lfs *fs, size_t size, int type) 186 { 187 struct lfs_res_blk *re; 188 void *r; 189 int i, start; 190 unsigned int h; 191 192 ASSERT_MAYBE_SEGLOCK(fs); 193 r = NULL; 194 195 /* If no mem allocated for this type, it just waits */ 196 if (lfs_res_qty[type] == 0) { 197 r = malloc(size, M_SEGMENT, M_WAITOK); 198 return r; 199 } 200 201 /* Otherwise try a quick malloc, and if it works, great */ 202 if ((r = malloc(size, M_SEGMENT, M_NOWAIT)) != NULL) { 203 return r; 204 } 205 206 /* 207 * If malloc returned NULL, we are forced to use one of our 208 * reserve blocks. We have on hand at least one summary block, 209 * at least one cluster block, at least one superblock, 210 * and several indirect blocks. 211 */ 212 213 mutex_enter(&lfs_lock); 214 /* skip over blocks of other types */ 215 for (i = 0, start = 0; i < type; i++) 216 start += lfs_res_qty[i]; 217 while (r == NULL) { 218 for (i = 0; i < lfs_res_qty[type]; i++) { 219 if (fs->lfs_resblk[start + i].inuse == 0) { 220 re = fs->lfs_resblk + start + i; 221 re->inuse = 1; 222 r = re->p; 223 KASSERT(re->size >= size); 224 h = lfs_mhash(r); 225 LIST_INSERT_HEAD(&fs->lfs_reshash[h], re, res); 226 mutex_exit(&lfs_lock); 227 return r; 228 } 229 } 230 DLOG((DLOG_MALLOC, "sleeping on %s (%d)\n", 231 lfs_res_names[type], lfs_res_qty[type])); 232 mtsleep(&fs->lfs_resblk, PVM, "lfs_malloc", 0, 233 &lfs_lock); 234 DLOG((DLOG_MALLOC, "done sleeping on %s\n", 235 lfs_res_names[type])); 236 } 237 /* NOTREACHED */ 238 mutex_exit(&lfs_lock); 239 return r; 240 } 241 242 void 243 lfs_free(struct lfs *fs, void *p, int type) 244 { 245 unsigned int h; 246 res_t *re; 247 248 ASSERT_MAYBE_SEGLOCK(fs); 249 h = lfs_mhash(p); 250 mutex_enter(&lfs_lock); 251 LIST_FOREACH(re, &fs->lfs_reshash[h], res) { 252 if (re->p == p) { 253 KASSERT(re->inuse == 1); 254 LIST_REMOVE(re, res); 255 re->inuse = 0; 256 wakeup(&fs->lfs_resblk); 257 mutex_exit(&lfs_lock); 258 return; 259 } 260 } 261 262 #ifdef notyet /* XXX this assert fires */ 263 for (int i = 0; i < LFS_N_TOTAL; i++) { 264 KDASSERTMSG(fs->lfs_resblk[i].p == p, 265 "lfs_free: inconsistent reserved block"); 266 } 267 #endif 268 269 mutex_exit(&lfs_lock); 270 271 /* 272 * If we didn't find it, free it. 273 */ 274 free(p, M_SEGMENT); 275 } 276 277 /* 278 * Fragment lock. This is a reader/writer lock controlling, primarily, 279 * the expansion of file fragments. 280 */ 281 void 282 lfs_fraglock_enter(struct lfs *fs, int enter_exit) 283 { 284 lfs_prelock(fs, 0); 285 } 286 287 bool 288 lfs_fraglock_held(struct lfs *fs, int read_write) 289 { 290 return lfs_prelock_held(fs); 291 } 292 293 void 294 lfs_fraglock_exit(struct lfs *fs) 295 { 296 lfs_preunlock(fs); 297 } 298 299 /* 300 * lfs_seglock -- 301 * Single thread the segment writer. 302 */ 303 int 304 lfs_seglock(struct lfs *fs, unsigned long flags) 305 { 306 struct segment *sp; 307 int error; 308 309 error = lfs_prelock(fs, flags); 310 if (error) 311 return error; 312 313 if (fs->lfs_seglock) { 314 ++fs->lfs_seglock; 315 fs->lfs_sp->seg_flags |= flags; 316 return 0; 317 } 318 319 fs->lfs_seglock = 1; 320 fs->lfs_cleanind = 0; 321 322 LFS_ENTER_LOG("seglock", __FILE__, __LINE__, 0, flags, curproc->p_pid); 323 324 sp = fs->lfs_sp = pool_get(&fs->lfs_segpool, PR_WAITOK); 325 sp->bpp = pool_get(&fs->lfs_bpppool, PR_WAITOK); 326 sp->seg_flags = flags; 327 sp->vp = NULL; 328 sp->seg_iocount = 0; 329 sp->bytes_written = 0; 330 sp->gatherblock_loopcount = 0; 331 (void) lfs_initseg(fs, 0); 332 333 /* 334 * Keep a cumulative count of the outstanding I/O operations. If the 335 * disk drive catches up with us it could go to zero before we finish, 336 * so we artificially increment it by one until we've scheduled all of 337 * the writes we intend to do. 338 */ 339 mutex_enter(&lfs_lock); 340 ++fs->lfs_iocount; 341 fs->lfs_startseg = lfs_sb_getcurseg(fs); 342 mutex_exit(&lfs_lock); 343 return 0; 344 } 345 346 /* 347 * Create a marker inode. 348 */ 349 struct inode * 350 lfs_create_marker(void) 351 { 352 struct inode *marker; 353 354 marker = pool_get(&lfs_inode_pool, PR_WAITOK); 355 memset(marker, 0, sizeof(*marker)); 356 marker->inode_ext.lfs = pool_get(&lfs_inoext_pool, PR_WAITOK); 357 memset(marker->inode_ext.lfs, 0, sizeof(*marker->inode_ext.lfs)); 358 marker->i_state |= IN_MARKER; 359 360 return marker; 361 } 362 363 void 364 lfs_destroy_marker(struct inode *marker) 365 { 366 pool_put(&lfs_inoext_pool, marker->inode_ext.lfs); 367 pool_put(&lfs_inode_pool, marker); 368 } 369 370 static void lfs_unmark_dirop(struct lfs *); 371 372 static void 373 lfs_unmark_dirop(struct lfs *fs) 374 { 375 struct inode *ip, *marker; 376 struct vnode *vp; 377 int doit; 378 379 KASSERT(fs != NULL); 380 ASSERT_NO_SEGLOCK(fs); 381 mutex_enter(&lfs_lock); 382 doit = !(fs->lfs_flags & LFS_UNDIROP); 383 if (doit) 384 fs->lfs_flags |= LFS_UNDIROP; 385 mutex_exit(&lfs_lock); 386 387 if (!doit) 388 return; 389 390 marker = lfs_create_marker(); 391 392 mutex_enter(&lfs_lock); 393 TAILQ_INSERT_HEAD(&fs->lfs_dchainhd, marker, i_lfs_dchain); 394 while ((ip = TAILQ_NEXT(marker, i_lfs_dchain)) != NULL) { 395 TAILQ_REMOVE(&fs->lfs_dchainhd, marker, i_lfs_dchain); 396 TAILQ_INSERT_AFTER(&fs->lfs_dchainhd, ip, marker, 397 i_lfs_dchain); 398 if (ip->i_state & IN_MARKER) 399 continue; 400 vp = ITOV(ip); 401 if ((ip->i_state & (IN_ADIROP | IN_CDIROP)) == IN_CDIROP) { 402 --lfs_dirvcount; 403 --fs->lfs_dirvcount; 404 vp->v_uflag &= ~VU_DIROP; 405 TAILQ_REMOVE(&fs->lfs_dchainhd, ip, i_lfs_dchain); 406 wakeup(&lfs_dirvcount); 407 fs->lfs_unlockvp = vp; 408 mutex_exit(&lfs_lock); 409 vrele(vp); 410 mutex_enter(&lfs_lock); 411 fs->lfs_unlockvp = NULL; 412 ip->i_state &= ~IN_CDIROP; 413 } 414 } 415 TAILQ_REMOVE(&fs->lfs_dchainhd, marker, i_lfs_dchain); 416 fs->lfs_flags &= ~LFS_UNDIROP; 417 wakeup(&fs->lfs_flags); 418 mutex_exit(&lfs_lock); 419 420 lfs_destroy_marker(marker); 421 } 422 423 /* 424 * Run through the segment list promoting empty segments. 425 * 426 * XXX We should keep a list of segments that have reached 427 * XXX su_nbytes == 0 (or blocks containing their SEGUSEs) 428 * XXX and process that, presumably much smaller, list 429 * XXX instead of always looking at every segment. 430 */ 431 void 432 lfs_auto_segclean(struct lfs *fs) 433 { 434 int i, j, waited, changed, any_changed; 435 SEGUSE *sup; 436 struct buf *bp; 437 438 waited = 0; 439 any_changed = 0; 440 for (i = 0; i < lfs_sb_getnseg(fs); i+= lfs_sb_getsepb(fs)) { 441 LFS_SEGENTRY(sup, fs, i, bp); 442 changed = 0; 443 for (j = 0; j < lfs_sb_getsepb(fs); j++) { 444 if (i + j >= lfs_sb_getnseg(fs)) 445 break; 446 if (sup->su_nbytes == 0) { 447 switch (sup->su_flags & (SEGUSE_ACTIVE 448 | SEGUSE_DIRTY 449 | SEGUSE_EMPTY 450 | SEGUSE_READY)) { 451 case SEGUSE_DIRTY: 452 sup->su_flags |= SEGUSE_EMPTY; 453 ++changed; 454 break; 455 456 case SEGUSE_DIRTY | SEGUSE_EMPTY: 457 sup->su_flags |= SEGUSE_READY; 458 ++changed; 459 break; 460 461 case SEGUSE_DIRTY 462 | SEGUSE_EMPTY 463 | SEGUSE_READY: 464 /* Make sure the sb is written */ 465 mutex_enter(&lfs_lock); 466 while (waited == 0 467 && fs->lfs_sbactive) { 468 mtsleep(&fs->lfs_sbactive, 469 PRIBIO+1, "lfs asb", 470 0, &lfs_lock); 471 } 472 mutex_exit(&lfs_lock); 473 waited = 1; 474 475 lfs_markclean(fs, i + j, sup, 0, 476 NOCRED, curlwp); 477 ++changed; 478 break; 479 480 default: 481 break; 482 } 483 } 484 LFS_SEGENTRY_NEXT(sup, fs); 485 } 486 if (changed) { 487 ++any_changed; 488 LFS_WRITESEGENTRY(sup, fs, i, bp); 489 } else 490 LFS_RELEASESEGENTRY(sup, fs, i, bp); 491 } 492 if (any_changed) 493 wakeup(&fs->lfs_availsleep); 494 } 495 496 bool 497 lfs_seglock_held(struct lfs *fs) 498 { 499 return lfs_prelock_held(fs) && fs->lfs_seglock != 0; 500 } 501 502 /* 503 * lfs_segunlock -- 504 * Single thread the segment writer. 505 */ 506 void 507 lfs_segunlock(struct lfs *fs) 508 { 509 struct segment *sp; 510 unsigned long sync, ckp; 511 struct buf *bp; 512 int do_unmark_dirop = 0; 513 514 sp = fs->lfs_sp; 515 516 if (!LFS_SEGLOCK_HELD(fs)) 517 panic("lfs seglock not held"); 518 519 if (fs->lfs_seglock == 1) { 520 if ((sp->seg_flags & SEGM_CLEAN) == 0) 521 do_unmark_dirop = 1; 522 sync = sp->seg_flags & SEGM_SYNC; 523 ckp = sp->seg_flags & SEGM_CKP; 524 525 /* We should have a segment summary, and nothing else */ 526 KASSERT(sp->cbpp == sp->bpp + 1); 527 528 /* Free allocated segment summary */ 529 lfs_sb_suboffset(fs, lfs_btofsb(fs, lfs_sb_getsumsize(fs))); 530 bp = *sp->bpp; 531 lfs_freebuf(fs, bp); 532 533 pool_put(&fs->lfs_bpppool, sp->bpp); 534 sp->bpp = NULL; 535 536 /* 537 * If we're not sync, we're done with sp, get rid of it. 538 * Otherwise, we keep a local copy around but free 539 * fs->lfs_sp so another process can use it (we have to 540 * wait but they don't have to wait for us). 541 */ 542 if (!sync) 543 pool_put(&fs->lfs_segpool, sp); 544 fs->lfs_sp = NULL; 545 546 /* 547 * If the I/O count is non-zero, sleep until it reaches zero. 548 * At the moment, the user's process hangs around so we can 549 * sleep. 550 */ 551 mutex_enter(&lfs_lock); 552 if (--fs->lfs_iocount <= 1) 553 wakeup(&fs->lfs_iocount); 554 mutex_exit(&lfs_lock); 555 556 /* 557 * If we're not checkpointing, we don't have to block 558 * other processes to wait for a synchronous write 559 * to complete. 560 */ 561 if (!ckp) { 562 LFS_ENTER_LOG("segunlock_std", __FILE__, __LINE__, 0, 0, curproc->p_pid); 563 564 --fs->lfs_seglock; 565 } 566 /* 567 * We let checkpoints happen asynchronously. That means 568 * that during recovery, we have to roll forward between 569 * the two segments described by the first and second 570 * superblocks to make sure that the checkpoint described 571 * by a superblock completed. 572 */ 573 mutex_enter(&lfs_lock); 574 while (ckp && sync && fs->lfs_iocount) { 575 (void)mtsleep(&fs->lfs_iocount, PRIBIO + 1, 576 "lfs_iocount", 0, &lfs_lock); 577 DLOG((DLOG_SEG, "sleeping on iocount %x == %d\n", fs, fs->lfs_iocount)); 578 } 579 while (sync && sp->seg_iocount) { 580 (void)mtsleep(&sp->seg_iocount, PRIBIO + 1, 581 "seg_iocount", 0, &lfs_lock); 582 DLOG((DLOG_SEG, "sleeping on iocount %x == %d\n", sp, sp->seg_iocount)); 583 } 584 mutex_exit(&lfs_lock); 585 if (sync) 586 pool_put(&fs->lfs_segpool, sp); 587 588 if (ckp) { 589 fs->lfs_nactive = 0; 590 /* If we *know* everything's on disk, write both sbs */ 591 /* XXX should wait for this one */ 592 if (sync) 593 lfs_writesuper(fs, lfs_sb_getsboff(fs, fs->lfs_activesb)); 594 lfs_writesuper(fs, lfs_sb_getsboff(fs, 1 - fs->lfs_activesb)); 595 if (!(fs->lfs_ivnode->v_mount->mnt_iflag & 596 (IMNT_UNMOUNT | IMNT_WANTRDONLY))) { 597 lfs_auto_segclean(fs); 598 /* If sync, we can clean the remainder too */ 599 if (sync) 600 lfs_auto_segclean(fs); 601 } 602 fs->lfs_activesb = 1 - fs->lfs_activesb; 603 604 LFS_ENTER_LOG("segunlock_ckp", __FILE__, __LINE__, 0, 0, curproc->p_pid); 605 606 --fs->lfs_seglock; 607 } 608 if (do_unmark_dirop) 609 lfs_unmark_dirop(fs); 610 } else { 611 --fs->lfs_seglock; 612 KASSERT(fs->lfs_seglock != 0); 613 } 614 615 lfs_preunlock(fs); 616 } 617 618 /* 619 * Single thread the cleaner. 620 */ 621 int 622 lfs_cleanerlock(struct lfs *fs) 623 { 624 int error; 625 626 mutex_enter(&lfs_lock); 627 while (fs->lfs_cleanlock) { 628 printf("cleanlock=%p, waiting\n", fs->lfs_cleanlock); 629 error = cv_wait_sig(&fs->lfs_cleanercv, &lfs_lock); 630 if (error) 631 break; 632 } 633 if (error == 0) 634 fs->lfs_cleanlock = curlwp; 635 mutex_exit(&lfs_lock); 636 637 return error; 638 } 639 640 /* 641 * Check whether we hold the cleaner lock. 642 */ 643 int 644 lfs_cleanerlock_held(struct lfs *fs) 645 { 646 int retval = 0; 647 648 mutex_enter(&lfs_lock); 649 retval = (fs->lfs_cleanlock == curlwp); 650 mutex_exit(&lfs_lock); 651 652 return retval; 653 } 654 655 /* 656 * Single thread the cleaner. 657 */ 658 void 659 lfs_cleanerunlock(struct lfs *fs) 660 { 661 struct inode *ip; 662 663 /* Clear out the cleaning list */ 664 while ((ip = TAILQ_FIRST(&fs->lfs_cleanhd)) != NULL) 665 lfs_clrclean(fs, ITOV(ip)); 666 667 mutex_enter(&lfs_lock); 668 fs->lfs_cleanlock = NULL; 669 cv_broadcast(&fs->lfs_cleanercv); 670 mutex_exit(&lfs_lock); 671 } 672 673 /* 674 * Preventative / prerequisite lock. 675 * This is the "lock" part of the segment lock, 676 * though it can also be taken independently to 677 * prevent segment writing. 678 */ 679 int 680 lfs_prelock(struct lfs *fs, unsigned long flags) 681 { 682 int error; 683 684 mutex_enter(&lfs_lock); 685 686 error = 0; 687 if (fs->lfs_prelock) { 688 if (fs->lfs_prelocklwp == curlwp) { 689 /* Locked by us already */ 690 ++fs->lfs_prelock; 691 goto errout; 692 } else if (flags & SEGM_PAGEDAEMON) { 693 /* Pagedaemon cannot wait */ 694 error = EWOULDBLOCK; 695 goto errout; 696 } else { 697 /* Wait for lock */ 698 while (fs->lfs_prelock) { 699 cv_wait(&fs->lfs_prelockcv, &lfs_lock); 700 } 701 } 702 } 703 704 /* Acquire lock */ 705 fs->lfs_prelock = 1; 706 fs->lfs_prelocklwp = curlwp; 707 708 mutex_exit(&lfs_lock); 709 EXCL_IFLOCK(fs); 710 return 0; 711 712 errout: 713 mutex_exit(&lfs_lock); 714 return error; 715 } 716 717 bool 718 lfs_prelock_held(struct lfs *fs) 719 { 720 bool held; 721 bool waslocked; 722 723 waslocked = mutex_owned(&lfs_lock); 724 if (!waslocked) 725 mutex_enter(&lfs_lock); 726 727 held = (fs->lfs_prelock && fs->lfs_prelocklwp == curlwp); 728 729 if (!waslocked) 730 mutex_exit(&lfs_lock); 731 732 return held; 733 } 734 735 void 736 lfs_preunlock(struct lfs *fs) 737 { 738 int last = 0; 739 740 mutex_enter(&lfs_lock); 741 last = (fs->lfs_prelock == 1); 742 mutex_exit(&lfs_lock); 743 if (last) 744 UNEXCL_IFLOCK(fs); 745 746 mutex_enter(&lfs_lock); 747 if (--fs->lfs_prelock > 0) { 748 mutex_exit(&lfs_lock); 749 return; 750 } 751 752 fs->lfs_prelocklwp = NULL; 753 cv_broadcast(&fs->lfs_prelockcv); 754 mutex_exit(&lfs_lock); 755 } 756 757 /* 758 * Drain dirops and start writer. 759 * 760 * No simple_locks are held when we enter and none are held when we return. 761 */ 762 void 763 lfs_writer_enter(struct lfs *fs, const char *wmesg) 764 { 765 int error __diagused; 766 767 ASSERT_NO_SEGLOCK(fs); 768 mutex_enter(&lfs_lock); 769 770 /* disallow dirops during flush */ 771 fs->lfs_writer++; 772 773 while (fs->lfs_dirops > 0) { 774 ++fs->lfs_diropwait; 775 error = mtsleep(&fs->lfs_writer, PRIBIO+1, wmesg, 0, 776 &lfs_lock); 777 KASSERT(error == 0); 778 --fs->lfs_diropwait; 779 } 780 781 mutex_exit(&lfs_lock); 782 } 783 784 int 785 lfs_writer_tryenter(struct lfs *fs) 786 { 787 int writer_set; 788 789 ASSERT_MAYBE_SEGLOCK(fs); 790 mutex_enter(&lfs_lock); 791 writer_set = (fs->lfs_dirops == 0); 792 if (writer_set) 793 fs->lfs_writer++; 794 mutex_exit(&lfs_lock); 795 796 return writer_set; 797 } 798 799 void 800 lfs_writer_leave(struct lfs *fs) 801 { 802 bool dowakeup; 803 804 ASSERT_MAYBE_SEGLOCK(fs); 805 mutex_enter(&lfs_lock); 806 dowakeup = !(--fs->lfs_writer); 807 if (dowakeup) 808 cv_broadcast(&fs->lfs_diropscv); 809 mutex_exit(&lfs_lock); 810 } 811 812 /* 813 * Unlock, wait for the cleaner, then relock to where we were before. 814 * To be used only at a fairly high level, to address a paucity of free 815 * segments propagated back from lfs_gop_write(). 816 */ 817 void 818 lfs_segunlock_relock(struct lfs *fs) 819 { 820 int n = fs->lfs_seglock; 821 u_int16_t seg_flags; 822 CLEANERINFO *cip; 823 struct buf *bp; 824 825 if (n == 0) 826 return; 827 828 /* Write anything we've already gathered to disk */ 829 lfs_writeseg(fs, fs->lfs_sp); 830 831 /* Tell cleaner */ 832 mutex_enter(&lfs_lock); 833 fs->lfs_flags |= LFS_MUSTCLEAN; 834 mutex_exit(&lfs_lock); 835 LFS_CLEANERINFO(cip, fs, bp); 836 lfs_ci_setflags(fs, cip, 837 lfs_ci_getflags(fs, cip) | LFS_CLEANER_MUST_CLEAN); 838 LFS_SYNC_CLEANERINFO(cip, fs, bp, 1); 839 840 /* Save segment flags for later */ 841 seg_flags = fs->lfs_sp->seg_flags; 842 843 while(fs->lfs_seglock) 844 lfs_segunlock(fs); 845 846 /* Wait for the cleaner */ 847 lfs_wakeup_cleaner(fs); 848 mutex_enter(&lfs_lock); 849 while (LFS_STARVED_FOR_SEGS(fs)) 850 mtsleep(&fs->lfs_availsleep, PRIBIO, "relock", 0, 851 &lfs_lock); 852 mutex_exit(&lfs_lock); 853 854 /* Put the segment lock back the way it was. */ 855 while(n--) 856 lfs_seglock(fs, seg_flags); 857 858 /* Cleaner can relax now */ 859 mutex_enter(&lfs_lock); 860 fs->lfs_flags &= ~LFS_MUSTCLEAN; 861 mutex_exit(&lfs_lock); 862 LFS_CLEANERINFO(cip, fs, bp); 863 lfs_ci_setflags(fs, cip, 864 lfs_ci_getflags(fs, cip) & ~LFS_CLEANER_MUST_CLEAN); 865 LFS_SYNC_CLEANERINFO(cip, fs, bp, 1); 866 867 return; 868 } 869 870 /* 871 * Wake up the cleaner, provided that nowrap is not set. 872 */ 873 void 874 lfs_wakeup_cleaner(struct lfs *fs) 875 { 876 if (fs->lfs_nowrap > 0) 877 return; 878 879 cv_broadcast(&fs->lfs_nextsegsleep); 880 cv_broadcast(&lfs_allclean_wakeup); 881 } 882 883 /* 884 * If it wasn't already on the cleaning list, 885 * add it and take a reference. We will clear 886 * the list before dropping the seglock. 887 */ 888 void 889 lfs_setclean(struct lfs *fs, struct vnode *vp) 890 { 891 struct inode *ip; 892 893 KASSERT(lfs_cleanerlock_held(fs)); 894 895 vref(vp); 896 897 ip = VTOI(vp); 898 mutex_enter(&lfs_lock); 899 if (ip->i_state & IN_CLEANING) { 900 mutex_exit(&lfs_lock); 901 vrele(vp); 902 return; 903 } 904 905 TAILQ_INSERT_HEAD(&fs->lfs_cleanhd, ip, i_lfs_clean); 906 LFS_SET_UINO(VTOI(vp), IN_CLEANING); 907 mutex_exit(&lfs_lock); 908 } 909 910 /* 911 * Remove a vnode from the cleaning list, 912 * clear IN_CLEANING and drop the reference. 913 * Find any invalid buffers on the vnode and 914 * toss them. 915 */ 916 void 917 lfs_clrclean(struct lfs *fs, struct vnode *vp) 918 { 919 struct inode *ip; 920 921 KASSERT(lfs_cleanerlock_held(fs)); 922 923 ip = VTOI(vp); 924 mutex_enter(&lfs_lock); 925 if (!(ip->i_state & IN_CLEANING)) { 926 mutex_exit(&lfs_lock); 927 return; 928 } 929 mutex_exit(&lfs_lock); 930 931 if (vp->v_type == VREG && vp != fs->lfs_ivnode) 932 lfs_ungather(fs, NULL, vp, lfs_match_data); 933 934 mutex_enter(&lfs_lock); 935 TAILQ_REMOVE(&fs->lfs_cleanhd, ip, i_lfs_clean); 936 LFS_CLR_UINO(VTOI(vp), IN_CLEANING); 937 mutex_exit(&lfs_lock); 938 vrele(vp); 939 } 940 941 /* 942 * Remove the specified flag from all segments. 943 */ 944 void 945 lfs_seguse_clrflag_all(struct lfs *fs, uint32_t flag) 946 { 947 SEGUSE *sup; 948 struct buf *bp; 949 int i; 950 951 for (i = 0; i < lfs_sb_getnseg(fs); i++) { 952 LFS_SEGENTRY(sup, fs, i, bp); 953 if (sup->su_flags & flag) { 954 sup->su_flags &= ~flag; 955 LFS_WRITESEGENTRY(sup, fs, i, bp); 956 } else 957 LFS_RELEASESEGENTRY(sup, fs, i, bp); 958 } 959 } 960 961