1 /*********************************************************************** 2 * * 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 * 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 rv = 0; 61 62 #ifdef F_DIOINFO 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); 69 } 70 71 for(rw = (n/di->dio.d_miniosz)*di->dio.d_miniosz;; ) 72 { size_t io; 73 74 if((io = rw) > di->dio.d_maxiosz ) 75 io = di->dio.d_maxiosz; 76 if(type == SF_READ) 77 rv = read(f->file,buf,io); 78 else rv = write(f->file,buf,io); 79 80 if(rv > 0) 81 { rw -= rv; done += rv; 82 buf = (Void_t*)((char*)buf + rv); 83 } 84 85 if(rv < io || rw < di->dio.d_miniosz) 86 break; 87 } 88 } 89 90 if(done < n && (di->cntl & FDIRECT) ) 91 { /* turn off directIO for remaining IO operation */ 92 di->cntl &= ~FDIRECT; 93 (void)fcntl(f->file, F_SETFL, di->cntl); 94 } 95 #endif /*F_DIOINFO*/ 96 97 if((rw = n-done) > 0 && 98 (rv = type == SF_READ ? read(f->file,buf,rw) : write(f->file,buf,rw)) > 0 ) 99 done += rv; 100 101 return done ? done : rv; 102 } 103 104 #if __STD_C 105 static ssize_t dioread(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc) 106 #else 107 static ssize_t dioread(f, buf, n, disc) 108 Sfio_t* f; 109 Void_t* buf; 110 size_t n; 111 Sfdisc_t* disc; 112 #endif 113 { 114 return diordwr(f, buf, n, (Direct_t*)disc, SF_READ); 115 } 116 117 #if __STD_C 118 static ssize_t diowrite(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc) 119 #else 120 static ssize_t diowrite(f, buf, n, disc) 121 Sfio_t* f; 122 Void_t* buf; 123 size_t n; 124 Sfdisc_t* disc; 125 #endif 126 { 127 return diordwr(f, (Void_t*)buf, n, (Direct_t*)disc, SF_WRITE); 128 } 129 130 #if __STD_C 131 static int dioexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc) 132 #else 133 static int dioexcept(f,type,data,disc) 134 Sfio_t* f; 135 int type; 136 Void_t* data; 137 Sfdisc_t* disc; 138 #endif 139 { 140 Direct_t* di = (Direct_t*)disc; 141 142 if(type == SF_FINAL || type == SF_DPOP) 143 { 144 #ifdef F_DIOINFO 145 if(di->cntl&FDIRECT) 146 { di->cntl &= ~FDIRECT; 147 (void)fcntl(f->file,F_SETFL,di->cntl); 148 } 149 #endif 150 free(disc); 151 } 152 153 return 0; 154 } 155 156 #if __STD_C 157 int sfdcdio(Sfio_t* f, size_t bufsize) 158 #else 159 int sfdcdio(f, bufsize) 160 Sfio_t* f; 161 size_t bufsize; 162 #endif 163 { 164 #ifndef F_DIOINFO 165 return -1; 166 #else 167 int cntl; 168 struct dioattr dio; 169 Void_t* buf; 170 Direct_t* di; 171 172 if(f->extent < 0 || (f->flags&SF_STRING)) 173 return -1; 174 175 if((cntl = fcntl(f->file,F_GETFL,0)) < 0) 176 return -1; 177 178 if(!(cntl&FDIRECT) ) 179 { cntl |= FDIRECT; 180 if(fcntl(f->file,F_SETFL,cntl) < 0) 181 return -1; 182 } 183 184 if(fcntl(f->file,F_DIOINFO,&dio) < 0) 185 goto no_direct; 186 187 if(bufsize > 0) 188 bufsize = (bufsize/dio.d_miniosz)*dio.d_miniosz; 189 if(bufsize <= 0) 190 bufsize = dio.d_miniosz*64; 191 if(bufsize > dio.d_maxiosz) 192 bufsize = dio.d_maxiosz; 193 194 if(!(di = (Direct_t*)malloc(sizeof(Direct_t))) ) 195 goto no_direct; 196 197 if(!(buf = (Void_t*)memalign(dio.d_mem,bufsize)) ) 198 { free(di); 199 goto no_direct; 200 } 201 202 sfsetbuf(f,buf,bufsize); 203 if(sfsetbuf(f,buf,0) == buf) 204 sfset(f,SF_MALLOC,1); 205 else 206 { free(buf); 207 free(di); 208 goto no_direct; 209 } 210 211 di->disc.readf = dioread; 212 di->disc.writef = diowrite; 213 di->disc.seekf = NIL(Sfseek_f); 214 di->disc.exceptf = dioexcept; 215 di->cntl = cntl; 216 di->dio = dio; 217 218 if(sfdisc(f,(Sfdisc_t*)di) != (Sfdisc_t*)di) 219 { free(di); 220 no_direct: 221 cntl &= ~FDIRECT; 222 (void)fcntl(f->file,F_SETFL,cntl); 223 return -1; 224 } 225 226 return 0; 227 228 #endif /*F_DIOINFO*/ 229 } 230