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