1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin * *
3da2e3ebdSchin * This software is part of the ast package *
4*3e14f97fSRoger A. Faulkner * Copyright (c) 1985-2010 AT&T Intellectual Property *
5da2e3ebdSchin * and is licensed under the *
6da2e3ebdSchin * Common Public License, Version 1.0 *
77c2fbfb3SApril Chin * by AT&T Intellectual Property *
8da2e3ebdSchin * *
9da2e3ebdSchin * A copy of the License is available at *
10da2e3ebdSchin * http://www.opensource.org/licenses/cpl1.0.txt *
11da2e3ebdSchin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
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
31da2e3ebdSchin #undef F_FIOINFO
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