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 *
cfsd_fscache_create(const char * name,const char * cachepath,int fscacheid)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
cfsd_fscache_destroy(cfsd_fscache_object_t * fscache_object_p)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
fscache_lock(cfsd_fscache_object_t * fscache_object_p)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
fscache_unlock(cfsd_fscache_object_t * fscache_object_p)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
fscache_setup(cfsd_fscache_object_t * fscache_object_p)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
fscache_process(cfsd_fscache_object_t * fscache_object_p)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
fscache_simdisconnect(cfsd_fscache_object_t * fscache_object_p,int disconnect)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
fscache_unmount(cfsd_fscache_object_t * fscache_object_p,int flag)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
fscache_server_alive(cfsd_fscache_object_t * fscache_object_p,cfsd_kmod_object_t * kmod_object_p)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
fscache_pingserver(cfsd_fscache_object_t * fscache_object_p)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
fscache_roll(cfsd_fscache_object_t * fscache_object_p,cfsd_kmod_object_t * kmod_object_p)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
fscache_rollone(cfsd_fscache_object_t * fscache_object_p,cfsd_kmod_object_t * kmod_object_p,cfsd_maptbl_object_t * maptbl_object_p,cfsd_logfile_object_t * logfile_object_p,ulong_t seq)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
fscache_addagain(cfsd_fscache_object_t * fscache_object_p,cfsd_logfile_object_t * logfile_object_p,ulong_t nseq)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
fscache_fsproblem(cfsd_fscache_object_t * fscache_object_p,cfsd_kmod_object_t * kmod_object_p)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
fscache_changes(cfsd_fscache_object_t * fscache_object_p,int tt)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