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