xref: /titanic_41/usr/src/lib/libast/common/sfio/sfsync.c (revision a38dd497aa503e9d80665c24b521fee255609df4)
1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *           Copyright (c) 1985-2007 AT&T Knowledge Ventures            *
5 *                      and is licensed under the                       *
6 *                  Common Public License, Version 1.0                  *
7 *                      by AT&T Knowledge Ventures                      *
8 *                                                                      *
9 *                A copy of the License is available at                 *
10 *            http://www.opensource.org/licenses/cpl1.0.txt             *
11 *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12 *                                                                      *
13 *              Information and Software Systems Research               *
14 *                            AT&T Research                             *
15 *                           Florham Park NJ                            *
16 *                                                                      *
17 *                 Glenn Fowler <gsf@research.att.com>                  *
18 *                  David Korn <dgk@research.att.com>                   *
19 *                   Phong Vo <kpv@research.att.com>                    *
20 *                                                                      *
21 ***********************************************************************/
22 #include	"sfhdr.h"
23 
24 /*	Synchronize data in buffers with the file system.
25 **	If f is nil, all streams are sync-ed
26 **
27 **	Written by Kiem-Phong Vo.
28 */
29 
30 #if __STD_C
31 static int _sfall(void)
32 #else
33 static int _sfall()
34 #endif
35 {
36 	reg Sfpool_t	*p, *next;
37 	reg Sfio_t*	f;
38 	reg int		n, rv;
39 	reg int		nsync, count, loop;
40 #define MAXLOOP 3
41 
42 	for(loop = 0; loop < MAXLOOP; ++loop)
43 	{	rv = nsync = count = 0;
44 		for(p = &_Sfpool; p; p = next)
45 		{	/* find the next legitimate pool */
46 			for(next = p->next; next; next = next->next)
47 				if(next->n_sf > 0)
48 					break;
49 
50 			/* walk the streams for _Sfpool only */
51 			for(n = 0; n < ((p == &_Sfpool) ? p->n_sf : 1); ++n)
52 			{	count += 1;
53 				f = p->sf[n];
54 
55 				if(f->flags&SF_STRING )
56 					goto did_sync;
57 				if(SFFROZEN(f))
58 					continue;
59 				if((f->mode&SF_READ) && (f->mode&SF_SYNCED) )
60 					goto did_sync;
61 				if((f->mode&SF_READ) && !(f->bits&SF_MMAP) &&
62 				   f->next == f->endb)
63 					goto did_sync;
64 				if((f->mode&SF_WRITE) && !(f->bits&SF_HOLE) &&
65 				   f->next == f->data)
66 					goto did_sync;
67 
68 				if(sfsync(f) < 0)
69 					rv = -1;
70 
71 			did_sync:
72 				nsync += 1;
73 			}
74 		}
75 
76 		if(nsync == count)
77 			break;
78 	}
79 	return rv;
80 }
81 
82 #if __STD_C
83 int sfsync(reg Sfio_t* f)
84 #else
85 int sfsync(f)
86 reg Sfio_t*	f;	/* stream to be synchronized */
87 #endif
88 {
89 	int	local, rv, mode, lock;
90 	Sfio_t*	origf;
91 
92 	if(!(origf = f) )
93 		return _sfall();
94 
95 	SFMTXSTART(origf,-1);
96 
97 	GETLOCAL(origf,local);
98 
99 	if(origf->disc == _Sfudisc)	/* throw away ungetc */
100 		(void)sfclose((*_Sfstack)(origf,NIL(Sfio_t*)));
101 
102 	rv = 0;
103 
104 	lock = origf->mode&SF_LOCK;
105 	if(origf->mode == (SF_SYNCED|SF_READ) ) /* already synced */
106 		goto done;
107 
108 	if((origf->mode&SF_RDWR) != SFMODE(origf,local) && _sfmode(origf,0,local) < 0)
109 	{	rv = -1;
110 		goto done;
111 	}
112 
113 	for(; f; f = f->push)
114 	{
115 		if((f->flags&SF_IOCHECK) && f->disc && f->disc->exceptf)
116 			(void)(*f->disc->exceptf)(f,SF_SYNC,(Void_t*)((int)1),f->disc);
117 
118 		SFLOCK(f,local);
119 
120 		/* pretend that this stream is not on a stack */
121 		mode = f->mode&SF_PUSH;
122 		f->mode &= ~SF_PUSH;
123 
124 		/* these streams do not need synchronization */
125 		if((f->flags&SF_STRING) || (f->mode&SF_SYNCED))
126 			goto next;
127 
128 		if((f->mode&SF_WRITE) && (f->next > f->data || (f->bits&SF_HOLE)) )
129 		{	/* sync the buffer, make sure pool don't move */
130 			reg int pool = f->mode&SF_POOL;
131 			f->mode &= ~SF_POOL;
132 			if(f->next > f->data && (SFWRALL(f), SFFLSBUF(f,-1)) < 0)
133 				rv = -1;
134 			if(!SFISNULL(f) && (f->bits&SF_HOLE) )
135 			{	/* realize a previously created hole of 0's */
136 				if(SFSK(f,(Sfoff_t)(-1),SEEK_CUR,f->disc) >= 0)
137 					(void)SFWR(f,"",1,f->disc);
138 				f->bits &= ~SF_HOLE;
139 			}
140 			f->mode |= pool;
141 		}
142 
143 		if((f->mode&SF_READ) && f->extent >= 0 &&
144 		   ((f->bits&SF_MMAP) || f->next < f->endb) )
145 		{	/* make sure the file pointer is at the right place */
146 			f->here -= (f->endb-f->next);
147 			f->endr = f->endw = f->data;
148 			f->mode = SF_READ|SF_SYNCED|lock;
149 			(void)SFSK(f,f->here,SEEK_SET,f->disc);
150 
151 			if((f->flags&SF_SHARE) && !(f->flags&SF_PUBLIC) &&
152 			   !(f->bits&SF_MMAP) )
153 			{	f->endb = f->next = f->data;
154 				f->mode &= ~SF_SYNCED;
155 			}
156 		}
157 
158 	next:
159 		f->mode |= mode;
160 		SFOPEN(f,local);
161 
162 		if((f->flags&SF_IOCHECK) && f->disc && f->disc->exceptf)
163 			(void)(*f->disc->exceptf)(f,SF_SYNC,(Void_t*)((int)0),f->disc);
164 	}
165 
166 done:
167 	if(!local && f && (f->mode&SF_POOL) && f->pool && f != f->pool->sf[0])
168 		SFSYNC(f->pool->sf[0]);
169 
170 	SFMTXRETURN(origf, rv);
171 }
172