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 1994-2003 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Methods of the cfsd_fscache class. 31 */ 32 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <stddef.h> 37 #include <thread.h> 38 #include <synch.h> 39 #include <errno.h> 40 #include <unistd.h> 41 #include <stdarg.h> 42 #include <limits.h> 43 #include <fcntl.h> 44 #include <locale.h> 45 #include <nfs/nfs.h> 46 #include <sys/utsname.h> 47 #include <sys/param.h> 48 #include <sys/stat.h> 49 #include <sys/mount.h> 50 #include <sys/types.h> 51 #include <sys/wait.h> 52 #include <rpc/rpc.h> 53 #include <mdbug/mdbug.h> 54 #include <sys/fs/cachefs_fs.h> 55 #include <sys/fs/cachefs_dlog.h> 56 #include <sys/fs/cachefs_ioctl.h> 57 #include "cfsd.h" 58 #include "cfsd_kmod.h" 59 #include "cfsd_maptbl.h" 60 #include "cfsd_logfile.h" 61 #include "cfsd_logelem.h" 62 #include "cfsd_fscache.h" 63 64 /* 65 * ----------------------------------------------------------------- 66 * cfsd_fscache_create 67 * 68 * Description: 69 * Arguments: 70 * name 71 * cachepath 72 * Returns: 73 * Preconditions: 74 * precond(name) 75 * precond(cachepath) 76 */ 77 cfsd_fscache_object_t * 78 cfsd_fscache_create(const char *name, const char *cachepath, 79 int fscacheid) 80 { 81 cfsd_fscache_object_t *fscache_object_p; 82 int xx; 83 84 dbug_enter("cfsd_fscache_create"); 85 86 dbug_precond(name); 87 dbug_precond(cachepath); 88 89 fscache_object_p = cfsd_calloc(sizeof (cfsd_fscache_object_t)); 90 strlcpy(fscache_object_p->i_name, name, 91 sizeof (fscache_object_p->i_name)); 92 strlcpy(fscache_object_p->i_cachepath, cachepath, 93 sizeof (fscache_object_p->i_cachepath)); 94 fscache_object_p->i_fscacheid = fscacheid; 95 fscache_object_p->i_refcnt = 0; 96 fscache_object_p->i_disconnectable = 0; 97 fscache_object_p->i_mounted = 0; 98 fscache_object_p->i_threaded = 0; 99 fscache_object_p->i_connected = 0; 100 fscache_object_p->i_reconcile = 0; 101 fscache_object_p->i_changes = 0; 102 fscache_object_p->i_simdis = 0; 103 fscache_object_p->i_tryunmount = 0; 104 fscache_object_p->i_backunmount = 0; 105 fscache_object_p->i_time_state = 0; 106 fscache_object_p->i_time_mnt = 0; 107 fscache_object_p->i_modify = 1; 108 109 fscache_object_p->i_threadid = 0; 110 fscache_object_p->i_ofd = -1; 111 112 fscache_object_p->i_next = NULL; 113 114 /* initialize the locking mutex */ 115 xx = mutex_init(&fscache_object_p->i_lock, USYNC_THREAD, NULL); 116 dbug_assert(xx == 0); 117 118 xx = cond_init(&fscache_object_p->i_cvwait, USYNC_THREAD, 0); 119 dbug_assert(xx == 0); 120 121 dbug_leave("cfsd_fscache_create"); 122 return (fscache_object_p); 123 } 124 125 /* 126 * ----------------------------------------------------------------- 127 * cfsd_fscache_destroy 128 * 129 * Description: 130 * Arguments: 131 * Returns: 132 * Preconditions: 133 */ 134 void 135 cfsd_fscache_destroy(cfsd_fscache_object_t *fscache_object_p) 136 { 137 int xx; 138 139 dbug_enter("cfsd_fscache_destroy"); 140 141 dbug_precond(fscache_object_p); 142 /* dbug_assert(fscache_object_p->i_refcnt == 0); */ 143 144 /* close down the message file descriptor */ 145 if (fscache_object_p->i_ofd >= 0) { 146 if (close(fscache_object_p->i_ofd)) 147 dbug_print(("error", "cannot close fscache fd error %d", 148 errno)); 149 fscache_object_p->i_ofd = -1; 150 } 151 152 /* destroy the locking mutex */ 153 xx = mutex_destroy(&fscache_object_p->i_lock); 154 dbug_assert(xx == 0); 155 156 /* destroy the conditional variable */ 157 xx = cond_destroy(&fscache_object_p->i_cvwait); 158 dbug_assert(xx == 0); 159 160 cfsd_free(fscache_object_p); 161 162 dbug_leave("cfsd_fscache_destroy"); 163 } 164 165 /* 166 * ----------------------------------------------------------------- 167 * fscache_lock 168 * 169 * Description: 170 * Arguments: 171 * Returns: 172 * Preconditions: 173 */ 174 void 175 fscache_lock(cfsd_fscache_object_t *fscache_object_p) 176 { 177 dbug_enter("fscache_lock"); 178 179 dbug_precond(fscache_object_p); 180 mutex_lock(&fscache_object_p->i_lock); 181 dbug_leave("fscache_lock"); 182 } 183 184 /* 185 * ----------------------------------------------------------------- 186 * fscache_unlock 187 * 188 * Description: 189 * Arguments: 190 * Returns: 191 * Preconditions: 192 */ 193 void 194 fscache_unlock(cfsd_fscache_object_t *fscache_object_p) 195 { 196 dbug_enter("fscache_unlock"); 197 198 dbug_precond(fscache_object_p); 199 mutex_unlock(&fscache_object_p->i_lock); 200 dbug_leave("fscache_unlock"); 201 } 202 203 /* 204 * ----------------------------------------------------------------- 205 * fscache_setup 206 * 207 * Description: 208 * Arguments: 209 * Returns: 210 * Preconditions: 211 */ 212 void 213 fscache_setup(cfsd_fscache_object_t *fscache_object_p) 214 { 215 char *tmp; 216 char cfs_mnt_filename[MAXPATHLEN]; 217 FILE *fin; 218 /* 219 * Line input buffer allows for type field (magic number size 220 * of 50 is historic), the field separator ": ", a large value 221 * (again historic) and a '\n' character. 222 */ 223 char type[50]; 224 char value[MAXPATHLEN * 4]; 225 char buf[sizeof (type) + 2 + sizeof (value) + 1]; 226 int err = 0; 227 int xx; 228 char *options[] = { "snr", "disconnectable", NULL }; 229 char *strp = buf; 230 char *dummy; 231 struct stat64 sinfo; 232 time_t mtime; 233 234 dbug_enter("fscache_setup"); 235 dbug_precond(fscache_object_p); 236 237 fscache_object_p->i_modify++; 238 fscache_object_p->i_disconnectable = 0; 239 fscache_object_p->i_connected = 0; 240 fscache_object_p->i_reconcile = 0; 241 fscache_object_p->i_changes = 0; 242 fscache_object_p->i_time_state = 0; 243 fscache_object_p->i_time_mnt = 0; 244 fscache_object_p->i_mntpt[0] = '\0'; 245 fscache_object_p->i_backfs[0] = '\0'; 246 fscache_object_p->i_backpath[0] = '\0'; 247 fscache_object_p->i_backfstype[0] = '\0'; 248 fscache_object_p->i_cfsopt[0] = '\0'; 249 fscache_object_p->i_bfsopt[0] = '\0'; 250 251 snprintf(cfs_mnt_filename, sizeof (cfs_mnt_filename), "%s/%s/%s", 252 fscache_object_p->i_cachepath, fscache_object_p->i_name, 253 CACHEFS_MNT_FILE); 254 255 /* open for reading the file with the mount information */ 256 fin = fopen(cfs_mnt_filename, "r"); 257 if (fin == NULL) { 258 dbug_print(("err", "could not open %s, %d", cfs_mnt_filename, 259 errno)); 260 dbug_leave("fscache_setup"); 261 return; 262 } 263 /* get the modify time of the mount file */ 264 if (fstat64(fileno(fin), &sinfo) == -1) { 265 dbug_print(("err", "could not stat %s, %d", cfs_mnt_filename, 266 errno)); 267 if (fclose(fin)) 268 dbug_print(("err", "cannot close %s, %d", 269 cfs_mnt_filename, errno)); 270 dbug_leave("fscache_setup"); 271 return; 272 } 273 mtime = sinfo.st_mtime; 274 275 /* read the mount information from the file */ 276 while (fgets(buf, sizeof (buf), fin) != NULL) { 277 tmp = strtok(buf, ":"); 278 if (strlcpy(type, tmp, sizeof (type)) >= sizeof (type)) { 279 /* Buffer Overflow */ 280 dbug_print(("err", "overflow in type field" 281 " of file %s", cfs_mnt_filename)); 282 if (fclose(fin)) 283 dbug_print(("err", "cannot close %s, %d", 284 cfs_mnt_filename, errno)); 285 dbug_leave("fscache_setup"); 286 return; 287 } 288 tmp = strtok(NULL, "\n"); 289 if (tmp != NULL && *tmp == ' ') { 290 /* 291 * There is a valid value string so skip 292 * the space after the ":". 293 */ 294 tmp++; 295 if (strlcpy(value, tmp, sizeof (value)) 296 >= sizeof (value)) { 297 /* Buffer Overflow */ 298 dbug_print(("err", 299 "overflow in value field" 300 " of file %s", cfs_mnt_filename)); 301 if (fclose(fin)) 302 dbug_print(("err", 303 "cannot close %s, %d", 304 cfs_mnt_filename, errno)); 305 dbug_leave("fscache_setup"); 306 return; 307 } 308 } else { 309 value[0] = '\0'; 310 } 311 dbug_print(("info", "\"%s\" \"%s\"", type, value)); 312 if (strcmp(type, "cachedir") == 0) { 313 if (strcmp(fscache_object_p->i_cachepath, value) != 0) { 314 err = 1; 315 dbug_print(("err", "caches do not match %s, %s", 316 fscache_object_p->i_cachepath, buf)); 317 } 318 } else if (strcmp(type, "mnt_point") == 0) { 319 strlcpy(fscache_object_p->i_mntpt, value, 320 sizeof (fscache_object_p->i_mntpt)); 321 } else if (strcmp(type, "special") == 0) { 322 strlcpy(fscache_object_p->i_backfs, value, 323 sizeof (fscache_object_p->i_backfs)); 324 } else if (strcmp(type, "backpath") == 0) { 325 strlcpy(fscache_object_p->i_backpath, value, 326 sizeof (fscache_object_p->i_backpath)); 327 } else if (strcmp(type, "backfstype") == 0) { 328 strlcpy(fscache_object_p->i_backfstype, value, 329 sizeof (fscache_object_p->i_backfstype)); 330 } else if (strcmp(type, "cacheid") == 0) { 331 if (strcmp(fscache_object_p->i_name, value) != 0) { 332 err = 1; 333 dbug_print(("err", "ids do not match %s, %s", 334 fscache_object_p->i_name, value)); 335 } 336 } else if (strcmp(type, "cachefs_options") == 0) { 337 strlcpy(fscache_object_p->i_cfsopt, value, 338 sizeof (fscache_object_p->i_cfsopt)); 339 } else if (strcmp(type, "backfs_options") == 0) { 340 strlcpy(fscache_object_p->i_bfsopt, value, 341 sizeof (fscache_object_p->i_bfsopt)); 342 } else if (strcmp(type, "mount_time") == 0) { 343 continue; 344 } else { 345 dbug_print(("err", "unknown keyword \"%s\"", type)); 346 err = 1; 347 } 348 } 349 if (fclose(fin)) 350 dbug_print(("err", "cannot close %s, %d", 351 cfs_mnt_filename, errno)); 352 353 /* see if this is a file system that is disconnectable */ 354 if ((err == 0) && 355 (fscache_object_p->i_backfs[0] && 356 fscache_object_p->i_cfsopt[0])) { 357 strlcpy(buf, fscache_object_p->i_cfsopt, sizeof (buf)); 358 while (*strp != '\0') { 359 xx = getsubopt(&strp, options, &dummy); 360 if (xx != -1) { 361 fscache_object_p->i_disconnectable = 1; 362 break; 363 } 364 } 365 } 366 367 /* 368 * open up a fd on the sysmsg so we have a place to write 369 * log rolling errors 370 */ 371 if (fscache_object_p->i_disconnectable) { 372 if (fscache_object_p->i_ofd < 0) 373 fscache_object_p->i_ofd = open("/dev/sysmsg", 374 O_WRONLY); 375 if (fscache_object_p->i_ofd < 0) { 376 fprintf(stderr, 377 gettext("cachefsd: File system %s cannot be" 378 " disconnected.\n"), 379 fscache_object_p->i_mntpt); 380 fprintf(stderr, 381 gettext("cachefsd: Cannot open /dev/sysmsg\n")); 382 fscache_object_p->i_disconnectable = 0; 383 } 384 } 385 386 /* see if the file system is mounted */ 387 snprintf(cfs_mnt_filename, sizeof (cfs_mnt_filename), "%s/%s/%s", 388 fscache_object_p->i_cachepath, fscache_object_p->i_name, 389 CACHEFS_UNMNT_FILE); 390 if (stat64(cfs_mnt_filename, &sinfo) == 0) { 391 fscache_object_p->i_mounted = 0; 392 mtime = sinfo.st_mtime; 393 } else 394 fscache_object_p->i_mounted = 1; 395 396 /* save the time of the last mount or unmount */ 397 fscache_object_p->i_time_mnt = mtime; 398 399 dbug_print(("info", "disconnectable == %d, mounted == %d", 400 fscache_object_p->i_disconnectable, 401 fscache_object_p->i_mounted)); 402 dbug_leave("fscache_setup"); 403 } 404 405 /* 406 * ----------------------------------------------------------------- 407 * fscache_process 408 * 409 * Description: 410 * Arguments: 411 * Returns: 412 * Preconditions: 413 */ 414 void 415 fscache_process(cfsd_fscache_object_t *fscache_object_p) 416 { 417 int xx; 418 int changes; 419 cfsd_kmod_object_t *kmod_object_p; 420 int setup = 1; 421 int state; 422 423 dbug_enter("fscache_process"); 424 dbug_precond(fscache_object_p); 425 426 kmod_object_p = cfsd_kmod_create(); 427 for (;;) { 428 fscache_lock(fscache_object_p); 429 fscache_object_p->i_time_state = time(NULL); 430 fscache_object_p->i_modify++; 431 432 /* if we should try to unmount the file system */ 433 if (fscache_object_p->i_tryunmount) { 434 /* shut down the interface to the kmod */ 435 if (setup == 0) { 436 kmod_shutdown(kmod_object_p); 437 setup = 1; 438 } 439 440 /* try to unmount the file system */ 441 if (umount(fscache_object_p->i_mntpt) == -1) { 442 xx = errno; 443 dbug_print(("info", "unmount failed %s", 444 strerror(xx))); 445 } else { 446 fscache_object_p->i_mounted = 0; 447 } 448 449 /* wake up thread blocked in fscache_unmount */ 450 fscache_object_p->i_tryunmount = 0; 451 xx = cond_broadcast(&fscache_object_p->i_cvwait); 452 dbug_assert(xx == 0); 453 454 /* all done if unmount succeeded */ 455 if (fscache_object_p->i_mounted == 0) { 456 fscache_unlock(fscache_object_p); 457 break; 458 } 459 } 460 461 if (setup) { 462 setup = 0; 463 /* 464 * make an interface into the cachefs kmod for 465 * this fs 466 */ 467 xx = kmod_setup(kmod_object_p, 468 fscache_object_p->i_mntpt); 469 if (xx != 0) { 470 dbug_print(("err", 471 "setup of kmod interface failed %d", xx)); 472 fscache_object_p->i_disconnectable = 0; 473 fscache_object_p->i_modify++; 474 fscache_unlock(fscache_object_p); 475 break; 476 } 477 478 /* verify that we got the file system we expected XXX */ 479 } 480 481 /* get the current state of the file system */ 482 state = kmod_stateget(kmod_object_p); 483 484 if (fscache_object_p->i_simdis && (state == CFS_FS_CONNECTED)) { 485 dbug_print(("simdis", "simulating disconnection on %s", 486 fscache_object_p->i_mntpt)); 487 xx = kmod_stateset(kmod_object_p, CFS_FS_DISCONNECTED); 488 dbug_assert(xx == 0); 489 state = kmod_stateget(kmod_object_p); 490 dbug_assert(state == CFS_FS_DISCONNECTED); 491 } 492 fscache_unlock(fscache_object_p); 493 494 switch (state) { 495 case CFS_FS_CONNECTED: 496 fscache_lock(fscache_object_p); 497 fscache_object_p->i_connected = 1; 498 fscache_object_p->i_reconcile = 0; 499 fscache_object_p->i_modify++; 500 fscache_unlock(fscache_object_p); 501 502 /* wait for fs to switch to disconnecting */ 503 dbug_print(("info", "about to xwait")); 504 xx = kmod_xwait(kmod_object_p); 505 if (xx == EINTR) { 506 dbug_print(("info", "a. EINTR from xwait")); 507 continue; 508 } 509 dbug_assert(xx == 0); 510 state = kmod_stateget(kmod_object_p); 511 dbug_assert(state == CFS_FS_DISCONNECTED); 512 break; 513 514 case CFS_FS_DISCONNECTED: 515 fscache_lock(fscache_object_p); 516 fscache_object_p->i_connected = 0; 517 fscache_object_p->i_reconcile = 0; 518 fscache_object_p->i_modify++; 519 fscache_unlock(fscache_object_p); 520 521 /* wait until we are reconnected */ 522 fscache_server_alive(fscache_object_p, kmod_object_p); 523 if (fscache_object_p->i_tryunmount) 524 continue; 525 526 /* switch to reconnecting mode */ 527 xx = kmod_stateset(kmod_object_p, CFS_FS_RECONNECTING); 528 dbug_assert(xx == 0); 529 break; 530 531 case CFS_FS_RECONNECTING: 532 fscache_lock(fscache_object_p); 533 fscache_object_p->i_connected = 1; 534 fscache_object_p->i_reconcile = 1; 535 fscache_object_p->i_modify++; 536 changes = fscache_object_p->i_changes; 537 fscache_unlock(fscache_object_p); 538 539 /* roll the log */ 540 xx = fscache_roll(fscache_object_p, kmod_object_p); 541 if (xx) { 542 dbug_assert(xx == ETIMEDOUT); 543 /* switch to disconnected */ 544 xx = kmod_stateset(kmod_object_p, 545 CFS_FS_DISCONNECTED); 546 dbug_assert(xx == 0); 547 } else { 548 /* switch to connected */ 549 xx = kmod_stateset(kmod_object_p, 550 CFS_FS_CONNECTED); 551 dbug_assert(xx == 0); 552 changes = 0; 553 } 554 555 fscache_lock(fscache_object_p); 556 fscache_object_p->i_reconcile = 0; 557 fscache_changes(fscache_object_p, changes); 558 fscache_object_p->i_modify++; 559 fscache_unlock(fscache_object_p); 560 561 break; 562 563 default: 564 dbug_assert(0); 565 break; 566 } 567 } 568 cfsd_kmod_destroy(kmod_object_p); 569 dbug_leave("fscache_process"); 570 } 571 572 /* 573 * fscache_simdisconnect 574 * 575 * Description: 576 * Simulates disconnection or reconnects from a simulated disconnection. 577 * Arguments: 578 * disconnect 1 means disconnect, !1 means connect 579 * Returns: 580 * Returns 0 for success, !0 on an error 581 * Preconditions: 582 */ 583 int 584 fscache_simdisconnect(cfsd_fscache_object_t *fscache_object_p, int disconnect) 585 { 586 587 int xx; 588 int ret = 0; 589 char *strp; 590 int tcon; 591 int trec; 592 593 dbug_enter("fscache_simdisconnect"); 594 dbug_precond(fscache_object_p); 595 596 strp = disconnect ? "disconnection" : "reconnection"; 597 598 dbug_print(("simdis", "About to simulate %s", strp)); 599 600 fscache_lock(fscache_object_p); 601 602 if (disconnect) { 603 /* if file system cannot be disconnected */ 604 if (fscache_object_p->i_disconnectable == 0) { 605 ret = 1; 606 goto out; 607 } 608 609 /* if file system is already disconnected */ 610 if (fscache_object_p->i_connected == 0) { 611 ret = 2; 612 goto out; 613 } 614 fscache_object_p->i_simdis = 1; 615 } else { 616 /* if file system is already connected */ 617 if (fscache_object_p->i_connected) { 618 ret = 1; 619 goto out; 620 } 621 622 /* if file system is not "simulated" disconnected */ 623 if (fscache_object_p->i_simdis == 0) { 624 ret = 2; 625 goto out; 626 } 627 fscache_object_p->i_simdis = 0; 628 } 629 630 /* if fs thread not running */ 631 if (fscache_object_p->i_threaded == 0) { 632 if (fscache_object_p->i_mounted) { 633 dbug_print(("simdis", "thread not running")); 634 ret = -1; 635 } else { 636 if (fscache_object_p->i_simdis) 637 fscache_object_p->i_connected = 0; 638 else 639 fscache_object_p->i_connected = 1; 640 } 641 goto out; 642 } 643 644 /* get the attention of the thread */ 645 dbug_print(("info", "thread %d, killing %d with sigusr1", 646 thr_self(), fscache_object_p->i_threadid)); 647 xx = thr_kill(fscache_object_p->i_threadid, SIGUSR1); 648 if (xx) { 649 dbug_print(("simdis", "thr_kill failed %d, threadid %d", 650 xx, fscache_object_p->i_threadid)); 651 ret = -1; 652 } 653 654 out: 655 fscache_unlock(fscache_object_p); 656 657 if (ret == 0) { 658 for (;;) { 659 dbug_print(("simdis", " waiting for simulated %s", 660 strp)); 661 fscache_lock(fscache_object_p); 662 tcon = fscache_object_p->i_connected; 663 trec = fscache_object_p->i_reconcile; 664 fscache_unlock(fscache_object_p); 665 if (disconnect) { 666 if (tcon == 0) 667 break; 668 } else { 669 if ((tcon == 1) && (trec == 0)) 670 break; 671 } 672 cfsd_sleep(1); 673 } 674 dbug_print(("simdis", "DONE waiting for simulated %s", strp)); 675 } else { 676 dbug_print(("simdis", "simulated %s failed %d", strp, ret)); 677 } 678 679 dbug_leave("fscache_simdisconnect"); 680 return (ret); 681 } 682 683 /* 684 * fscache_unmount 685 * 686 * Description: 687 * Called to unmount the file system. 688 * Arguments: 689 * Returns: 690 * Returns 0 if the unmount is successful 691 * EIO if an error 692 * EBUSY if did not unmount because busy 693 * EAGAIN if umounted but should not unmount nfs mount 694 * ENOTSUP - forced unmount is not supported by cachefs 695 * Preconditions: 696 */ 697 698 int 699 fscache_unmount(cfsd_fscache_object_t *fscache_object_p, int flag) 700 { 701 int xx; 702 int ret = 0; 703 704 dbug_enter("fscache_unmount"); 705 dbug_precond(fscache_object_p); 706 707 fscache_lock(fscache_object_p); 708 709 /* if there is a thread running */ 710 if (fscache_object_p->i_threaded) { 711 /* do not bother unmounting if rolling the log */ 712 if (fscache_object_p->i_reconcile) { 713 ret = EBUSY; 714 goto out; 715 } 716 717 /* inform the thread to try the unmount */ 718 fscache_object_p->i_tryunmount = 1; 719 fscache_object_p->i_modify++; 720 721 /* get the attention of the thread */ 722 dbug_print(("info", "about to do umount kill")); 723 xx = thr_kill(fscache_object_p->i_threadid, SIGUSR1); 724 if (xx) { 725 dbug_print(("error", "thr_kill failed %d, threadid %d", 726 xx, fscache_object_p->i_threadid)); 727 ret = EIO; 728 goto out; 729 } 730 731 /* wait for the thread to wake us up */ 732 while (fscache_object_p->i_tryunmount) { 733 xx = cond_wait(&fscache_object_p->i_cvwait, 734 &fscache_object_p->i_lock); 735 dbug_print(("info", "cond_wait woke up %d %d", 736 xx, fscache_object_p->i_tryunmount)); 737 } 738 739 /* if the file system is still mounted */ 740 if (fscache_object_p->i_mounted) 741 ret = EBUSY; 742 } 743 744 /* else if there is no thread running */ 745 else { 746 /* try to unmount the file system */ 747 if (umount2(fscache_object_p->i_mntpt, flag) == -1) { 748 xx = errno; 749 dbug_print(("info", "unmount failed %s", 750 strerror(xx))); 751 if (xx == EBUSY) 752 ret = EBUSY; 753 else if (xx == ENOTSUP) 754 ret = ENOTSUP; 755 else 756 ret = EIO; 757 } else { 758 fscache_object_p->i_mounted = 0; 759 fscache_object_p->i_modify++; 760 } 761 } 762 out: 763 fscache_unlock(fscache_object_p); 764 dbug_leave("fscache_unmount"); 765 return (ret); 766 } 767 768 /* 769 * ----------------------------------------------------------------- 770 * fscache_server_alive 771 * 772 * Description: 773 * Arguments: 774 * Returns: 775 * Preconditions: 776 */ 777 void 778 fscache_server_alive(cfsd_fscache_object_t *fscache_object_p, 779 cfsd_kmod_object_t *kmod_object_p) 780 { 781 782 int xx; 783 cfs_fid_t rootfid; 784 dl_cred_t cr; 785 cfs_vattr_t va; 786 char cfsopt[CFS_MAXMNTOPTLEN]; 787 int child_pid; 788 int stat_loc; 789 790 dbug_enter("fscache_server_alive"); 791 792 dbug_precond(fscache_object_p); 793 dbug_precond(kmod_object_p); 794 795 for (;;) { 796 /* wait for a little while */ 797 if (fscache_object_p->i_simdis == 0) 798 cfsd_sleep(30); 799 /* if simulating disconnect */ 800 fscache_lock(fscache_object_p); 801 while (fscache_object_p->i_simdis && 802 !fscache_object_p->i_tryunmount) { 803 dbug_print(("simdis", "before calling cond_wait")); 804 xx = cond_wait(&fscache_object_p->i_cvwait, 805 &fscache_object_p->i_lock); 806 dbug_print(("simdis", "cond_wait woke up %d %d", 807 xx, fscache_object_p->i_simdis)); 808 } 809 fscache_unlock(fscache_object_p); 810 811 if (fscache_object_p->i_tryunmount) 812 break; 813 814 /* see if the server is alive */ 815 if (fscache_pingserver(fscache_object_p) == -1) { 816 /* dead server */ 817 continue; 818 } 819 820 /* try to mount the back file system if needed */ 821 if (fscache_object_p->i_backpath[0] == '\0') { 822 dbug_precond(fscache_object_p->i_cfsopt[0]); 823 dbug_precond(fscache_object_p->i_backfs[0]); 824 dbug_precond(fscache_object_p->i_mntpt[0]); 825 826 snprintf(cfsopt, sizeof (cfsopt), "%s,slide,remount", 827 fscache_object_p->i_cfsopt); 828 /* 829 * Mounting of a cachefs file system is done by calling 830 * out to /usr/lib/fs/cachefs/mount so that mounts 831 * done by the user, autofs and by us here in cachefsd 832 * are consistent. 833 */ 834 switch ((child_pid = fork1())) { 835 case -1: 836 /* 837 * The original code used system() 838 * but never checked for an error 839 * occurring. The rest of the code 840 * would suggest that "continue" is 841 * the correct thing to do. 842 */ 843 dbug_print(("info", "unable to fork mount " 844 "process for back fs %s %d", 845 fscache_object_p->i_backfs, errno)); 846 continue; 847 case 0: 848 (void) setsid(); 849 execl("/usr/sbin/mount", "mount", "-F", 850 "cachefs", "-o", cfsopt, 851 fscache_object_p->i_backfs, 852 fscache_object_p->i_mntpt, NULL); 853 break; 854 default: 855 (void) waitpid(child_pid, &stat_loc, WUNTRACED); 856 } 857 858 } 859 860 /* get the root fid of the file system */ 861 xx = kmod_rootfid(kmod_object_p, &rootfid); 862 if (xx) { 863 dbug_print(("info", "could not mount back fs %s %d", 864 fscache_object_p->i_backfs, xx)); 865 continue; 866 } 867 868 /* dummy up a fake kcred */ 869 (void) memset(&cr, 0, sizeof (cr)); 870 871 /* try to get attrs on the root */ 872 xx = kmod_getattrfid(kmod_object_p, &rootfid, &cr, &va); 873 if ((xx == ETIMEDOUT) || (xx == EIO)) { 874 dbug_print(("info", "Bogus error %d", xx)); 875 continue; 876 } 877 break; 878 } 879 dbug_leave("fscache_server_alive"); 880 } 881 882 /* 883 * fscache_pingserver 884 * 885 * Description: 886 * Trys to ping the nfs server to see if it is alive. 887 * Arguments: 888 * Returns: 889 * Returns 0 if it is alive, -1 if no answer. 890 * Preconditions: 891 */ 892 893 int 894 fscache_pingserver(cfsd_fscache_object_t *fscache_object_p) 895 { 896 897 static struct timeval TIMEOUT = { 25, 0 }; 898 CLIENT *clnt; 899 enum clnt_stat retval; 900 int ret = 0; 901 char hostname[sizeof (fscache_object_p->i_backfs)]; 902 char *cptr; 903 904 dbug_enter("fscache_pingserver"); 905 dbug_precond(fscache_object_p); 906 907 strlcpy(hostname, fscache_object_p->i_backfs, sizeof (hostname)); 908 if (cptr = strchr(hostname, ':')) 909 *cptr = '\0'; 910 911 dbug_assert(cptr != NULL); 912 dbug_print(("info", "remote host '%s' before clnt_create", hostname)); 913 914 dbug_print(("info", "before clnt_create")); 915 /* XXX this takes 75 seconds to time out */ 916 /* XXX should use lower level routines to reduce overhead */ 917 clnt = clnt_create(hostname, NFS_PROGRAM, NFS_VERSION, "udp"); 918 if (clnt == NULL) { 919 /* XXX what if this fails other than TIMEDOUT */ 920 /* clnt_pcreateerror(hostname); */ 921 dbug_print(("info", "clnt_create failed")); 922 ret = -1; 923 } else { 924 dbug_print(("info", "before null rpc")); 925 /* XXX this takes 45 seconds to time out */ 926 retval = clnt_call(clnt, 0, xdr_void, NULL, xdr_void, NULL, 927 TIMEOUT); 928 if (retval != RPC_SUCCESS) { 929 /* clnt_perror(clnt, "null rpc call failed"); */ 930 dbug_print(("info", "null rpc call failed %d", retval)); 931 ret = -1; 932 } 933 clnt_destroy(clnt); 934 } 935 dbug_leave("fscache_pingserver"); 936 return (ret); 937 } 938 939 /* 940 * fscache_roll 941 * 942 * Description: 943 * Rolls the contents of the log to the server. 944 * Arguments: 945 * kmodp interface to kernel functions 946 * Returns: 947 * Returns 0 for success or ETIMEDOUT if a timeout error occurred. 948 * Preconditions: 949 * precond(kmodp) 950 */ 951 int 952 fscache_roll(cfsd_fscache_object_t *fscache_object_p, 953 cfsd_kmod_object_t *kmod_object_p) 954 { 955 int error = 0; 956 cfsd_logelem_object_t *logelem_object_p; 957 char namebuf[MAXPATHLEN]; 958 char backupfile[MAXPATHLEN]; 959 int xx; 960 cfs_dlog_entry_t *entp; 961 off_t next_offset; 962 ulong_t curseq = 0; 963 int eof = 0; 964 char *xp; 965 cfsd_logfile_object_t *logfile_object_p; 966 cfsd_maptbl_object_t *maptbl_object_p; 967 968 dbug_enter("fscache_roll"); 969 970 dbug_precond(fscache_object_p); 971 dbug_precond(kmod_object_p); 972 973 /* map in the log file */ 974 logfile_object_p = cfsd_logfile_create(); 975 976 snprintf(namebuf, sizeof (namebuf), "%s/%s/%s", 977 fscache_object_p->i_cachepath, fscache_object_p->i_name, 978 CACHEFS_DLOG_FILE); 979 xx = logfile_setup(logfile_object_p, namebuf, CFS_DLOG_ENTRY_MAXSIZE); 980 if (xx) { 981 if (xx == ENOENT) { 982 cfsd_logfile_destroy(logfile_object_p); 983 dbug_leave("fscache_roll"); 984 return (0); 985 } 986 fscache_fsproblem(fscache_object_p, kmod_object_p); 987 cfsd_logfile_destroy(logfile_object_p); 988 dbug_leave("fscache_roll"); 989 return (0); 990 } 991 992 fscache_lock(fscache_object_p); 993 fscache_changes(fscache_object_p, 1); 994 fscache_unlock(fscache_object_p); 995 996 /* create a hashed mapping table for changes to cids */ 997 maptbl_object_p = cfsd_maptbl_create(); 998 snprintf(namebuf, sizeof (namebuf), "%s/%s/%s", 999 fscache_object_p->i_cachepath, fscache_object_p->i_name, 1000 CACHEFS_DMAP_FILE); 1001 xx = maptbl_setup(maptbl_object_p, namebuf); 1002 if (xx) { 1003 fscache_fsproblem(fscache_object_p, kmod_object_p); 1004 cfsd_logfile_destroy(logfile_object_p); 1005 cfsd_maptbl_destroy(maptbl_object_p); 1006 dbug_leave("fscache_roll"); 1007 return (0); 1008 } 1009 1010 /* 1011 * lock is not needed because they are only used when 1012 * rolling the log by fscache_roll and fscache_addagain 1013 */ 1014 fscache_object_p->i_again_offset = 0; 1015 fscache_object_p->i_again_seq = 0; 1016 1017 /* Pass 1: collect all cid to fid mappings */ 1018 next_offset = LOGFILE_ENTRY_START; 1019 for (;;) { 1020 /* get a pointer to the next record */ 1021 xx = logfile_entry(logfile_object_p, next_offset, &entp); 1022 if (xx == 1) 1023 break; 1024 if (xx == -1) { 1025 fscache_fsproblem(fscache_object_p, kmod_object_p); 1026 cfsd_logfile_destroy(logfile_object_p); 1027 cfsd_maptbl_destroy(maptbl_object_p); 1028 dbug_leave("fscache_roll"); 1029 return (0); 1030 } 1031 next_offset += entp->dl_len; 1032 1033 /* skip record if not valid */ 1034 if (entp->dl_valid != CFS_DLOG_VAL_COMMITTED) 1035 continue; 1036 1037 /* create an object for the appropriate log type */ 1038 logelem_object_p = NULL; 1039 switch (entp->dl_op) { 1040 case CFS_DLOG_CREATE: 1041 case CFS_DLOG_REMOVE: 1042 case CFS_DLOG_LINK: 1043 case CFS_DLOG_RENAME: 1044 case CFS_DLOG_MKDIR: 1045 case CFS_DLOG_RMDIR: 1046 case CFS_DLOG_SYMLINK: 1047 case CFS_DLOG_SETATTR: 1048 case CFS_DLOG_SETSECATTR: 1049 case CFS_DLOG_MODIFIED: 1050 case CFS_DLOG_TRAILER: 1051 break; 1052 1053 case CFS_DLOG_MAPFID: 1054 dbug_print(("info", "mapfid")); 1055 logelem_object_p = cfsd_logelem_mapfid_create( 1056 maptbl_object_p, logfile_object_p, 1057 kmod_object_p); 1058 break; 1059 1060 default: 1061 dbug_assert(0); 1062 fscache_fsproblem(fscache_object_p, kmod_object_p); 1063 break; 1064 } 1065 1066 /* do not bother if ignoring the record */ 1067 if (logelem_object_p == NULL) 1068 continue; 1069 1070 /* debuggging */ 1071 logelem_dump(logelem_object_p); 1072 1073 /* roll the entry */ 1074 xx = logelem_roll(logelem_object_p, (ulong_t *)NULL); 1075 if (xx) { 1076 fscache_fsproblem(fscache_object_p, kmod_object_p); 1077 cfsd_logelem_destroy(logelem_object_p); 1078 cfsd_maptbl_destroy(maptbl_object_p); 1079 cfsd_logfile_destroy(logfile_object_p); 1080 dbug_leave("fscache_roll"); 1081 return (0); 1082 } 1083 1084 /* mark record as completed */ 1085 entp->dl_valid = CFS_DLOG_VAL_PROCESSED; 1086 xx = logfile_sync(logfile_object_p); 1087 if (xx) { 1088 fscache_fsproblem(fscache_object_p, kmod_object_p); 1089 cfsd_logelem_destroy(logelem_object_p); 1090 cfsd_maptbl_destroy(maptbl_object_p); 1091 cfsd_logfile_destroy(logfile_object_p); 1092 dbug_leave("fscache_roll"); 1093 return (0); 1094 } 1095 1096 /* destroy the object */ 1097 cfsd_logelem_destroy(logelem_object_p); 1098 } 1099 1100 /* Pass 2: modify the back file system */ 1101 next_offset = LOGFILE_ENTRY_START; 1102 for (;;) { 1103 /* if we need the seq number of a deferred modify */ 1104 if (fscache_object_p->i_again_offset && 1105 (fscache_object_p->i_again_seq == 0)) { 1106 1107 /* get a pointer to the next record */ 1108 xx = logfile_entry(logfile_object_p, 1109 fscache_object_p->i_again_offset, &entp); 1110 if (xx == 1) 1111 break; 1112 if (xx == -1) { 1113 fscache_fsproblem(fscache_object_p, 1114 kmod_object_p); 1115 cfsd_logfile_destroy(logfile_object_p); 1116 cfsd_maptbl_destroy(maptbl_object_p); 1117 dbug_leave("fscache_roll"); 1118 return (0); 1119 } 1120 dbug_assert(entp->dl_op == CFS_DLOG_MODIFIED); 1121 fscache_object_p->i_again_seq = entp->dl_seq; 1122 dbug_assert(fscache_object_p->i_again_seq != 0); 1123 } 1124 1125 /* get a pointer to the next record to process */ 1126 if (!eof) { 1127 xx = logfile_entry(logfile_object_p, next_offset, 1128 &entp); 1129 if (xx == 1) { 1130 eof = 1; 1131 curseq = ULONG_MAX; 1132 } else if (xx) { 1133 break; 1134 } else { 1135 curseq = entp->dl_seq; 1136 } 1137 } 1138 1139 /* if its time to process a deferred modify entry */ 1140 if (fscache_object_p->i_again_seq && 1141 (eof || (fscache_object_p->i_again_seq < entp->dl_seq))) { 1142 xx = logfile_entry(logfile_object_p, 1143 fscache_object_p->i_again_offset, &entp); 1144 if (xx) 1145 break; 1146 dbug_assert(entp->dl_op == CFS_DLOG_MODIFIED); 1147 curseq = entp->dl_seq; 1148 fscache_object_p->i_again_offset = 1149 entp->dl_u.dl_modify.dl_next; 1150 fscache_object_p->i_again_seq = 0; 1151 entp->dl_u.dl_modify.dl_next = -1; 1152 } else if (eof) { 1153 xx = 0; 1154 break; 1155 } 1156 1157 /* else move the offset to the next record */ 1158 else { 1159 next_offset += entp->dl_len; 1160 } 1161 1162 /* skip record if not valid */ 1163 if (entp->dl_valid != CFS_DLOG_VAL_COMMITTED) 1164 continue; 1165 1166 /* process the record */ 1167 xx = fscache_rollone(fscache_object_p, kmod_object_p, 1168 maptbl_object_p, logfile_object_p, curseq); 1169 if (xx == ETIMEDOUT) { 1170 /* timeout error, back to disconnected */ 1171 cfsd_maptbl_destroy(maptbl_object_p); 1172 cfsd_logfile_destroy(logfile_object_p); 1173 dbug_print(("info", "timeout error occurred")); 1174 dbug_leave("fscache_roll"); 1175 return (xx); 1176 } else if (xx == EIO) { 1177 break; 1178 } else if (xx == EAGAIN) { 1179 continue; 1180 } else if (xx) { 1181 /* should never happen */ 1182 dbug_assert(0); 1183 break; 1184 } else { 1185 /* mark record as completed */ 1186 entp->dl_valid = CFS_DLOG_VAL_PROCESSED; 1187 xx = logfile_sync(logfile_object_p); 1188 if (xx) 1189 break; 1190 } 1191 } 1192 1193 /* if an unrecoverable error occurred */ 1194 if (xx) { 1195 dbug_print(("error", "error processing log file")); 1196 fscache_fsproblem(fscache_object_p, kmod_object_p); 1197 } 1198 1199 /* dump stats about the hash table */ 1200 maptbl_dumpstats(maptbl_object_p); 1201 1202 /* dump stats about the log file */ 1203 logfile_dumpstats(logfile_object_p); 1204 1205 /* debugging hack, rename the log files */ 1206 1207 if (snprintf(namebuf, sizeof (namebuf), "%s/%s/%s", 1208 fscache_object_p->i_cachepath, fscache_object_p->i_name, 1209 CACHEFS_DLOG_FILE) > ((sizeof (backupfile)) - (sizeof (".bak")))) { 1210 dbug_print(("error", "unable to create backup dlog_file " 1211 "for %s, path name is too long", namebuf)); 1212 } else { 1213 /* 1214 * No need to check return value from snprintf() as 1215 * the previous check should suffice. 1216 */ 1217 snprintf(backupfile, sizeof (backupfile), "%s.bak", namebuf); 1218 if (rename(namebuf, backupfile) == -1) { 1219 dbug_print(("error", 1220 "unable to create backup dlog_file")); 1221 } 1222 } 1223 1224 if (snprintf(namebuf, sizeof (namebuf), "%s/%s/%s", 1225 fscache_object_p->i_cachepath, fscache_object_p->i_name, 1226 CACHEFS_DMAP_FILE) > ((sizeof (backupfile)) - (sizeof (".bak")))) { 1227 dbug_print(("error", "unable to create backup dmap_file " 1228 "for %s, path name is too long", namebuf)); 1229 } else { 1230 /* 1231 * No need to check return value from snprintf() as 1232 * the previous check should suffice. 1233 */ 1234 snprintf(backupfile, sizeof (backupfile), "%s.bak", namebuf); 1235 if (rename(namebuf, backupfile) == -1) { 1236 dbug_print(("error", 1237 "unable to create backup dmap_file")); 1238 } 1239 } 1240 1241 /* delete the log file */ 1242 /* XXX */ 1243 1244 cfsd_maptbl_destroy(maptbl_object_p); 1245 cfsd_logfile_destroy(logfile_object_p); 1246 dbug_leave("fscache_roll"); 1247 return (error); 1248 } 1249 1250 /* 1251 * fscache_rollone 1252 * 1253 * Description: 1254 * Arguments: 1255 * kmodp 1256 * tblp 1257 * lfp 1258 * Returns: 1259 * Returns ... 1260 * Preconditions: 1261 * precond(kmodp) 1262 * precond(tblp) 1263 * precond(lfp) 1264 */ 1265 int 1266 fscache_rollone(cfsd_fscache_object_t *fscache_object_p, 1267 cfsd_kmod_object_t *kmod_object_p, 1268 cfsd_maptbl_object_t *maptbl_object_p, 1269 cfsd_logfile_object_t *logfile_object_p, 1270 ulong_t seq) 1271 { 1272 cfsd_logelem_object_t *logelem_object_p = NULL; 1273 cfs_dlog_entry_t *entp; 1274 int xx; 1275 char *strp; 1276 1277 dbug_enter("fscache_rollone"); 1278 1279 dbug_precond(fscache_object_p); 1280 dbug_precond(kmod_object_p); 1281 dbug_precond(maptbl_object_p); 1282 dbug_precond(logfile_object_p); 1283 1284 entp = logfile_object_p->i_cur_entry; 1285 1286 /* create an object for the appropriate log type */ 1287 switch (entp->dl_op) { 1288 case CFS_DLOG_CREATE: 1289 dbug_print(("info", "create")); 1290 logelem_object_p = cfsd_logelem_create_create(maptbl_object_p, 1291 logfile_object_p, kmod_object_p); 1292 break; 1293 1294 case CFS_DLOG_REMOVE: 1295 dbug_print(("info", "remove")); 1296 logelem_object_p = cfsd_logelem_remove_create(maptbl_object_p, 1297 logfile_object_p, kmod_object_p); 1298 break; 1299 1300 case CFS_DLOG_LINK: 1301 dbug_print(("info", "link")); 1302 logelem_object_p = cfsd_logelem_link_create(maptbl_object_p, 1303 logfile_object_p, kmod_object_p); 1304 break; 1305 1306 case CFS_DLOG_RENAME: 1307 dbug_print(("info", "rename")); 1308 logelem_object_p = cfsd_logelem_rename_create(maptbl_object_p, 1309 logfile_object_p, kmod_object_p); 1310 break; 1311 1312 case CFS_DLOG_MKDIR: 1313 dbug_print(("info", "mkdir")); 1314 logelem_object_p = cfsd_logelem_mkdir_create(maptbl_object_p, 1315 logfile_object_p, kmod_object_p); 1316 break; 1317 1318 case CFS_DLOG_RMDIR: 1319 dbug_print(("info", "rmdir")); 1320 logelem_object_p = cfsd_logelem_rmdir_create(maptbl_object_p, 1321 logfile_object_p, kmod_object_p); 1322 break; 1323 1324 case CFS_DLOG_SYMLINK: 1325 dbug_print(("info", "symlink")); 1326 logelem_object_p = cfsd_logelem_symlink_create(maptbl_object_p, 1327 logfile_object_p, kmod_object_p); 1328 break; 1329 1330 case CFS_DLOG_SETATTR: 1331 dbug_print(("info", "setattr")); 1332 logelem_object_p = cfsd_logelem_setattr_create(maptbl_object_p, 1333 logfile_object_p, kmod_object_p); 1334 break; 1335 1336 case CFS_DLOG_SETSECATTR: 1337 dbug_print(("info", "setsecattr")); 1338 logelem_object_p = cfsd_logelem_setsecattr_create( 1339 maptbl_object_p, logfile_object_p, kmod_object_p); 1340 break; 1341 1342 case CFS_DLOG_MODIFIED: 1343 dbug_print(("info", "modified")); 1344 logelem_object_p = cfsd_logelem_modified_create(maptbl_object_p, 1345 logfile_object_p, kmod_object_p); 1346 break; 1347 1348 case CFS_DLOG_MAPFID: 1349 dbug_print(("info", "mapfid")); 1350 break; 1351 1352 case CFS_DLOG_TRAILER: 1353 dbug_print(("info", "trailer")); 1354 break; 1355 1356 default: 1357 dbug_assert(0); 1358 dbug_leave("fscache_rollone"); 1359 return (EIO); 1360 } 1361 1362 /* do not bother if ignoring the record */ 1363 if (logelem_object_p == NULL) { 1364 dbug_print(("info", "record ignored")); 1365 dbug_leave("fscache_rollone"); 1366 return (0); 1367 } 1368 1369 /* XXX debugging */ 1370 logelem_dump(logelem_object_p); 1371 1372 /* roll the entry */ 1373 xx = logelem_roll(logelem_object_p, &seq); 1374 1375 strp = logelem_object_p->i_messagep; 1376 if (strp) { 1377 write(fscache_object_p->i_ofd, strp, strlen(strp)); 1378 dbug_print(("conflict", "%s", strp)); 1379 } 1380 1381 if (xx == EAGAIN) { 1382 dbug_assert(entp->dl_op == CFS_DLOG_MODIFIED); 1383 xx = fscache_addagain(fscache_object_p, logfile_object_p, seq); 1384 if (xx == 0) 1385 xx = EAGAIN; 1386 } 1387 1388 /* destroy the object */ 1389 cfsd_logelem_destroy(logelem_object_p); 1390 1391 dbug_leave("fscache_rollone"); 1392 return (xx); 1393 } 1394 1395 /* 1396 * fscache_addagain 1397 * 1398 * Description: 1399 * Arguments: 1400 * lfp 1401 * Returns: 1402 * Returns ... 1403 * Preconditions: 1404 * precond(lfp) 1405 */ 1406 int 1407 fscache_addagain(cfsd_fscache_object_t *fscache_object_p, 1408 cfsd_logfile_object_t *logfile_object_p, 1409 ulong_t nseq) 1410 { 1411 int xx; 1412 cfs_dlog_entry_t *entp; 1413 off_t noffset; 1414 off_t prevoff = 0; 1415 off_t toff; 1416 1417 dbug_enter("fscache_addagain"); 1418 1419 dbug_precond(fscache_object_p); 1420 dbug_precond(logfile_object_p); 1421 1422 entp = logfile_object_p->i_cur_entry; 1423 1424 noffset = logfile_object_p->i_cur_offset; 1425 1426 dbug_assert(entp->dl_op == CFS_DLOG_MODIFIED); 1427 dbug_assert(nseq); 1428 1429 /* both set or both zero */ 1430 dbug_assert((!fscache_object_p->i_again_seq ^ 1431 !fscache_object_p->i_again_offset) == 0); 1432 1433 entp->dl_seq = nseq; 1434 /* simple case, first one on list */ 1435 if ((fscache_object_p->i_again_seq == 0) || 1436 (nseq < fscache_object_p->i_again_seq)) { 1437 entp->dl_u.dl_modify.dl_next = fscache_object_p->i_again_offset; 1438 fscache_object_p->i_again_seq = nseq; 1439 fscache_object_p->i_again_offset = noffset; 1440 dbug_leave("fscache_addagain"); 1441 return (0); 1442 } 1443 1444 /* Search until we find the element on the list prior to the */ 1445 /* insertion point. */ 1446 for (toff = fscache_object_p->i_again_offset; toff != 0; 1447 toff = entp->dl_u.dl_modify.dl_next) { 1448 /* get pointer to next element on the list */ 1449 xx = logfile_entry(logfile_object_p, toff, &entp); 1450 if (xx) { 1451 dbug_leave("fscache_addagain"); 1452 return (xx); 1453 } 1454 dbug_assert(entp->dl_op == CFS_DLOG_MODIFIED); 1455 1456 /* done if we found the element after the insertion point */ 1457 if (nseq < entp->dl_seq) 1458 break; 1459 prevoff = toff; 1460 } 1461 dbug_assert(prevoff); 1462 1463 /* get pointer to element prior to the insertion point */ 1464 xx = logfile_entry(logfile_object_p, prevoff, &entp); 1465 if (xx) { 1466 dbug_leave("fscache_addagain"); 1467 return (xx); 1468 } 1469 dbug_assert(entp->dl_op == CFS_DLOG_MODIFIED); 1470 dbug_assert(entp->dl_u.dl_modify.dl_next == toff); 1471 1472 /* set element to point to our new element */ 1473 entp->dl_u.dl_modify.dl_next = noffset; 1474 1475 /* get pointer to our new element */ 1476 xx = logfile_entry(logfile_object_p, noffset, &entp); 1477 if (xx) { 1478 dbug_leave("fscache_addagain"); 1479 return (xx); 1480 } 1481 dbug_assert(entp->dl_op == CFS_DLOG_MODIFIED); 1482 1483 /* set it to point to next link or end of list */ 1484 entp->dl_u.dl_modify.dl_next = toff; 1485 1486 /* return success */ 1487 dbug_leave("fscache_addagain"); 1488 return (0); 1489 } 1490 1491 /* 1492 * fscache_fsproblem 1493 * 1494 * Description: 1495 * Arguments: 1496 * kmodp 1497 * Returns: 1498 * Preconditions: 1499 * precond(kmodp) 1500 */ 1501 void 1502 fscache_fsproblem(cfsd_fscache_object_t *fscache_object_p, 1503 cfsd_kmod_object_t *kmod_object_p) 1504 { 1505 #if 0 1506 int xx; 1507 #endif 1508 1509 dbug_enter("fscache_fsproblem"); 1510 1511 dbug_precond(fscache_object_p); 1512 dbug_precond(kmod_object_p); 1513 1514 #if 0 1515 /* first try to put all modified files in lost+found */ 1516 xx = kmod_lostfoundall(kmod_object_p); 1517 if (xx) { 1518 /* if that failed, put file system in read-only mode */ 1519 kmod_rofs(kmod_object_p); 1520 #endif 1521 fscache_lock(fscache_object_p); 1522 fscache_object_p->i_disconnectable = 0; 1523 fscache_object_p->i_modify++; 1524 fscache_unlock(fscache_object_p); 1525 #if 0 1526 } 1527 #endif 1528 dbug_leave("fscache_fsproblem"); 1529 } 1530 1531 /* 1532 * fscache_changes 1533 * 1534 * Description: 1535 * Used to specify whether or not there are changes to roll to the 1536 * server. 1537 * Arguments: 1538 * tt 1539 * Returns: 1540 * Preconditions: 1541 */ 1542 void 1543 fscache_changes(cfsd_fscache_object_t *fscache_object_p, int tt) 1544 { 1545 dbug_enter("fscache_changes"); 1546 dbug_precond(fscache_object_p); 1547 fscache_object_p->i_changes = tt; 1548 fscache_object_p->i_modify++; 1549 dbug_leave("fscache_changes"); 1550 } 1551