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