xref: /onnv-gate/usr/src/lib/libast/common/disc/sfdcdio.c (revision 4887:feebf9260c2e)
1*4887Schin /***********************************************************************
2*4887Schin *                                                                      *
3*4887Schin *               This software is part of the ast package               *
4*4887Schin *           Copyright (c) 1985-2007 AT&T Knowledge Ventures            *
5*4887Schin *                      and is licensed under the                       *
6*4887Schin *                  Common Public License, Version 1.0                  *
7*4887Schin *                      by AT&T Knowledge Ventures                      *
8*4887Schin *                                                                      *
9*4887Schin *                A copy of the License is available at                 *
10*4887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
11*4887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12*4887Schin *                                                                      *
13*4887Schin *              Information and Software Systems Research               *
14*4887Schin *                            AT&T Research                             *
15*4887Schin *                           Florham Park NJ                            *
16*4887Schin *                                                                      *
17*4887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
18*4887Schin *                  David Korn <dgk@research.att.com>                   *
19*4887Schin *                   Phong Vo <kpv@research.att.com>                    *
20*4887Schin *                                                                      *
21*4887Schin ***********************************************************************/
22*4887Schin #include	"sfdchdr.h"
23*4887Schin 
24*4887Schin /*	Discipline to turn on direct IO capability.
25*4887Schin **	This currently only works for XFS on SGI's.
26*4887Schin **
27*4887Schin **	Written by Kiem-Phong Vo, kpv@research.att.com, 03/18/1998.
28*4887Schin */
29*4887Schin 
30*4887Schin #ifndef FDIRECT
31*4887Schin #undef F_FIOINFO
32*4887Schin #endif
33*4887Schin 
34*4887Schin typedef struct _direct_s
35*4887Schin {	Sfdisc_t	disc;	/* Sfio discipline	*/
36*4887Schin 	int		cntl;	/* file control flags	*/
37*4887Schin #ifdef F_DIOINFO
38*4887Schin 	struct dioattr	dio;	/* direct IO params	*/
39*4887Schin #endif
40*4887Schin } Direct_t;
41*4887Schin 
42*4887Schin /* convert a pointer to an int */
43*4887Schin #define P2I(p)	(Sfulong_t)((char*)(p) - (char*)0)
44*4887Schin 
45*4887Schin #if __STD_C
46*4887Schin static ssize_t diordwr(Sfio_t* f, Void_t* buf, size_t n, Direct_t* di, int type)
47*4887Schin #else
48*4887Schin static ssize_t diordwr(f, buf, n, di, type)
49*4887Schin Sfio_t*		f;
50*4887Schin Void_t*		buf;
51*4887Schin size_t		n;
52*4887Schin Direct_t*	di;
53*4887Schin int		type;
54*4887Schin #endif
55*4887Schin {
56*4887Schin 	size_t	rw, done;
57*4887Schin 	ssize_t	rv;
58*4887Schin 
59*4887Schin 	done = 0;	/* amount processed by direct IO */
60*4887Schin 
61*4887Schin #ifdef F_DIOINFO
62*4887Schin 	if((P2I(buf)%di->dio.d_mem) == 0 &&
63*4887Schin 	   (f->here%di->dio.d_miniosz) == 0 && n >= di->dio.d_miniosz )
64*4887Schin 	{	/* direct IO ok, make sure we're in the right mode */
65*4887Schin 		if(!(di->cntl & FDIRECT) )
66*4887Schin 		{	di->cntl |= FDIRECT;
67*4887Schin 			(void)fcntl(f->file, F_SETFL, di->cntl);
68*4887Schin 		}
69*4887Schin 
70*4887Schin 		for(rw = (n/di->dio.d_miniosz)*di->dio.d_miniosz;; )
71*4887Schin 		{	size_t	io;
72*4887Schin 
73*4887Schin 			if((io = rw) > di->dio.d_maxiosz )
74*4887Schin 				io = di->dio.d_maxiosz;
75*4887Schin 			if(type == SF_READ)
76*4887Schin 				rv = read(f->file,buf,io);
77*4887Schin 			else	rv = write(f->file,buf,io);
78*4887Schin 
79*4887Schin 			if(rv > 0)
80*4887Schin 			{	rw -= rv; done += rv;
81*4887Schin 				buf = (Void_t*)((char*)buf + rv);
82*4887Schin 			}
83*4887Schin 
84*4887Schin 			if(rv < io || rw < di->dio.d_miniosz)
85*4887Schin 				break;
86*4887Schin 		}
87*4887Schin 	}
88*4887Schin 
89*4887Schin 	if(done < n && (di->cntl & FDIRECT) )
90*4887Schin 	{	/* turn off directIO for remaining IO operation */
91*4887Schin 		di->cntl &= ~FDIRECT;
92*4887Schin 		(void)fcntl(f->file, F_SETFL, di->cntl);
93*4887Schin 	}
94*4887Schin #endif /*F_DIOINFO*/
95*4887Schin 
96*4887Schin 	if((rw = n-done) > 0 &&
97*4887Schin 	   (rv = type == SF_READ ? read(f->file,buf,rw) : write(f->file,buf,rw)) > 0 )
98*4887Schin 		done += rv;
99*4887Schin 
100*4887Schin 	return done ? done : rv;
101*4887Schin }
102*4887Schin 
103*4887Schin #if __STD_C
104*4887Schin static ssize_t dioread(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc)
105*4887Schin #else
106*4887Schin static ssize_t dioread(f, buf, n, disc)
107*4887Schin Sfio_t*		f;
108*4887Schin Void_t*		buf;
109*4887Schin size_t		n;
110*4887Schin Sfdisc_t*	disc;
111*4887Schin #endif
112*4887Schin {
113*4887Schin 	return diordwr(f, buf, n, (Direct_t*)disc, SF_READ);
114*4887Schin }
115*4887Schin 
116*4887Schin #if __STD_C
117*4887Schin static ssize_t diowrite(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc)
118*4887Schin #else
119*4887Schin static ssize_t diowrite(f, buf, n, disc)
120*4887Schin Sfio_t*		f;
121*4887Schin Void_t*		buf;
122*4887Schin size_t		n;
123*4887Schin Sfdisc_t*	disc;
124*4887Schin #endif
125*4887Schin {
126*4887Schin 	return diordwr(f, (Void_t*)buf, n, (Direct_t*)disc, SF_WRITE);
127*4887Schin }
128*4887Schin 
129*4887Schin #if __STD_C
130*4887Schin static int dioexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc)
131*4887Schin #else
132*4887Schin static int dioexcept(f,type,data,disc)
133*4887Schin Sfio_t*		f;
134*4887Schin int		type;
135*4887Schin Void_t*		data;
136*4887Schin Sfdisc_t*	disc;
137*4887Schin #endif
138*4887Schin {
139*4887Schin 	Direct_t*	di = (Direct_t*)disc;
140*4887Schin 
141*4887Schin 	if(type == SF_FINAL || type == SF_DPOP)
142*4887Schin 	{
143*4887Schin #ifdef F_DIOINFO
144*4887Schin 		if(di->cntl&FDIRECT)
145*4887Schin 		{	di->cntl &= ~FDIRECT;
146*4887Schin 			(void)fcntl(f->file,F_SETFL,di->cntl);
147*4887Schin 		}
148*4887Schin #endif
149*4887Schin 		free(disc);
150*4887Schin 	}
151*4887Schin 
152*4887Schin 	return 0;
153*4887Schin }
154*4887Schin 
155*4887Schin #if __STD_C
156*4887Schin int sfdcdio(Sfio_t* f, size_t bufsize)
157*4887Schin #else
158*4887Schin int sfdcdio(f, bufsize)
159*4887Schin Sfio_t*	f;
160*4887Schin size_t	bufsize;
161*4887Schin #endif
162*4887Schin {
163*4887Schin #ifndef F_DIOINFO
164*4887Schin 	return -1;
165*4887Schin #else
166*4887Schin 	int		cntl;
167*4887Schin 	struct dioattr	dio;
168*4887Schin 	Void_t*		buf;
169*4887Schin 	Direct_t*	di;
170*4887Schin 
171*4887Schin 	if(f->extent < 0 || (f->flags&SF_STRING))
172*4887Schin 		return -1;
173*4887Schin 
174*4887Schin 	if((cntl = fcntl(f->file,F_GETFL,0)) < 0)
175*4887Schin 		return -1;
176*4887Schin 
177*4887Schin 	if(!(cntl&FDIRECT) )
178*4887Schin 	{	cntl |= FDIRECT;
179*4887Schin 		if(fcntl(f->file,F_SETFL,cntl) < 0)
180*4887Schin 			return -1;
181*4887Schin 	}
182*4887Schin 
183*4887Schin 	if(fcntl(f->file,F_DIOINFO,&dio) < 0)
184*4887Schin 		goto no_direct;
185*4887Schin 
186*4887Schin 	if(bufsize > 0)
187*4887Schin 		bufsize = (bufsize/dio.d_miniosz)*dio.d_miniosz;
188*4887Schin 	if(bufsize <= 0)
189*4887Schin 		bufsize = dio.d_miniosz*64;
190*4887Schin 	if(bufsize > dio.d_maxiosz)
191*4887Schin 		bufsize = dio.d_maxiosz;
192*4887Schin 
193*4887Schin 	if(!(di = (Direct_t*)malloc(sizeof(Direct_t))) )
194*4887Schin 		goto no_direct;
195*4887Schin 
196*4887Schin 	if(!(buf = (Void_t*)memalign(dio.d_mem,bufsize)) )
197*4887Schin 	{	free(di);
198*4887Schin 		goto no_direct;
199*4887Schin 	}
200*4887Schin 
201*4887Schin 	sfsetbuf(f,buf,bufsize);
202*4887Schin 	if(sfsetbuf(f,buf,0) == buf)
203*4887Schin 		sfset(f,SF_MALLOC,1);
204*4887Schin 	else
205*4887Schin 	{	free(buf);
206*4887Schin 		free(di);
207*4887Schin 		goto no_direct;
208*4887Schin 	}
209*4887Schin 
210*4887Schin 	di->disc.readf = dioread;
211*4887Schin 	di->disc.writef = diowrite;
212*4887Schin 	di->disc.seekf = NIL(Sfseek_f);
213*4887Schin 	di->disc.exceptf = dioexcept;
214*4887Schin 	di->cntl = cntl;
215*4887Schin 	di->dio = dio;
216*4887Schin 
217*4887Schin 	if(sfdisc(f,(Sfdisc_t*)di) != (Sfdisc_t*)di)
218*4887Schin 	{	free(di);
219*4887Schin 	no_direct:
220*4887Schin 		cntl &= ~FDIRECT;
221*4887Schin 		(void)fcntl(f->file,F_SETFL,cntl);
222*4887Schin 		return -1;
223*4887Schin 	}
224*4887Schin 
225*4887Schin 	return 0;
226*4887Schin 
227*4887Schin #endif /*F_DIOINFO*/
228*4887Schin }
229