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