1 /***********************************************************************
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Phong Vo <kpv@research.att.com> *
21 ***********************************************************************/
24 /* Discipline to turn on direct IO capability.
25 ** This currently only works for XFS on SGI's.
27 ** Written by Kiem-Phong Vo, kpv@research.att.com, 03/18/1998.
34 typedef struct _direct_s
35 { Sfdisc_t disc
; /* Sfio discipline */
36 int cntl
; /* file control flags */
38 struct dioattr dio
; /* direct IO params */
42 /* convert a pointer to an int */
43 #define P2I(p) (Sfulong_t)((char*)(p) - (char*)0)
46 static ssize_t
diordwr(Sfio_t
* f
, Void_t
* buf
, size_t n
, Direct_t
* di
, int type
)
48 static ssize_t
diordwr(f
, buf
, n
, di
, type
)
59 done
= 0; /* amount processed by direct IO */
63 if((P2I(buf
)%di
->dio
.d_mem
) == 0 &&
64 (f
->here
%di
->dio
.d_miniosz
) == 0 && n
>= di
->dio
.d_miniosz
)
65 { /* direct IO ok, make sure we're in the right mode */
66 if(!(di
->cntl
& FDIRECT
) )
67 { di
->cntl
|= FDIRECT
;
68 (void)fcntl(f
->file
, F_SETFL
, di
->cntl
);
71 for(rw
= (n
/di
->dio
.d_miniosz
)*di
->dio
.d_miniosz
;; )
74 if((io
= rw
) > di
->dio
.d_maxiosz
)
75 io
= di
->dio
.d_maxiosz
;
77 rv
= read(f
->file
,buf
,io
);
78 else rv
= write(f
->file
,buf
,io
);
81 { rw
-= rv
; done
+= rv
;
82 buf
= (Void_t
*)((char*)buf
+ rv
);
85 if(rv
< io
|| rw
< di
->dio
.d_miniosz
)
90 if(done
< n
&& (di
->cntl
& FDIRECT
) )
91 { /* turn off directIO for remaining IO operation */
93 (void)fcntl(f
->file
, F_SETFL
, di
->cntl
);
97 if((rw
= n
-done
) > 0 &&
98 (rv
= type
== SF_READ
? read(f
->file
,buf
,rw
) : write(f
->file
,buf
,rw
)) > 0 )
101 return done
? done
: rv
;
105 static ssize_t
dioread(Sfio_t
* f
, Void_t
* buf
, size_t n
, Sfdisc_t
* disc
)
107 static ssize_t
dioread(f
, buf
, n
, disc
)
114 return diordwr(f
, buf
, n
, (Direct_t
*)disc
, SF_READ
);
118 static ssize_t
diowrite(Sfio_t
* f
, const Void_t
* buf
, size_t n
, Sfdisc_t
* disc
)
120 static ssize_t
diowrite(f
, buf
, n
, disc
)
127 return diordwr(f
, (Void_t
*)buf
, n
, (Direct_t
*)disc
, SF_WRITE
);
131 static int dioexcept(Sfio_t
* f
, int type
, Void_t
* data
, Sfdisc_t
* disc
)
133 static int dioexcept(f
,type
,data
,disc
)
140 Direct_t
* di
= (Direct_t
*)disc
;
142 if(type
== SF_FINAL
|| type
== SF_DPOP
)
146 { di
->cntl
&= ~FDIRECT
;
147 (void)fcntl(f
->file
,F_SETFL
,di
->cntl
);
157 int sfdcdio(Sfio_t
* f
, size_t bufsize
)
159 int sfdcdio(f
, bufsize
)
172 if(f
->extent
< 0 || (f
->flags
&SF_STRING
))
175 if((cntl
= fcntl(f
->file
,F_GETFL
,0)) < 0)
180 if(fcntl(f
->file
,F_SETFL
,cntl
) < 0)
184 if(fcntl(f
->file
,F_DIOINFO
,&dio
) < 0)
188 bufsize
= (bufsize
/dio
.d_miniosz
)*dio
.d_miniosz
;
190 bufsize
= dio
.d_miniosz
*64;
191 if(bufsize
> dio
.d_maxiosz
)
192 bufsize
= dio
.d_maxiosz
;
194 if(!(di
= (Direct_t
*)malloc(sizeof(Direct_t
))) )
197 if(!(buf
= (Void_t
*)memalign(dio
.d_mem
,bufsize
)) )
202 sfsetbuf(f
,buf
,bufsize
);
203 if(sfsetbuf(f
,buf
,0) == buf
)
204 sfset(f
,SF_MALLOC
,1);
211 di
->disc
.readf
= dioread
;
212 di
->disc
.writef
= diowrite
;
213 di
->disc
.seekf
= NIL(Sfseek_f
);
214 di
->disc
.exceptf
= dioexcept
;
218 if(sfdisc(f
,(Sfdisc_t
*)di
) != (Sfdisc_t
*)di
)
222 (void)fcntl(f
->file
,F_SETFL
,cntl
);