14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*8462SApril.Chin@Sun.COM * Copyright (c) 1985-2008 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 7*8462SApril.Chin@Sun.COM * by AT&T Intellectual Property * 84887Schin * * 94887Schin * A copy of the License is available at * 104887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 124887Schin * * 134887Schin * Information and Software Systems Research * 144887Schin * AT&T Research * 154887Schin * Florham Park NJ * 164887Schin * * 174887Schin * Glenn Fowler <gsf@research.att.com> * 184887Schin * David Korn <dgk@research.att.com> * 194887Schin * Phong Vo <kpv@research.att.com> * 204887Schin * * 214887Schin ***********************************************************************/ 224887Schin #include "sfdchdr.h" 234887Schin 244887Schin /* Discipline to turn on direct IO capability. 254887Schin ** This currently only works for XFS on SGI's. 264887Schin ** 274887Schin ** Written by Kiem-Phong Vo, kpv@research.att.com, 03/18/1998. 284887Schin */ 294887Schin 304887Schin #ifndef FDIRECT 314887Schin #undef F_FIOINFO 324887Schin #endif 334887Schin 344887Schin typedef struct _direct_s 354887Schin { Sfdisc_t disc; /* Sfio discipline */ 364887Schin int cntl; /* file control flags */ 374887Schin #ifdef F_DIOINFO 384887Schin struct dioattr dio; /* direct IO params */ 394887Schin #endif 404887Schin } Direct_t; 414887Schin 424887Schin /* convert a pointer to an int */ 434887Schin #define P2I(p) (Sfulong_t)((char*)(p) - (char*)0) 444887Schin 454887Schin #if __STD_C 464887Schin static ssize_t diordwr(Sfio_t* f, Void_t* buf, size_t n, Direct_t* di, int type) 474887Schin #else 484887Schin static ssize_t diordwr(f, buf, n, di, type) 494887Schin Sfio_t* f; 504887Schin Void_t* buf; 514887Schin size_t n; 524887Schin Direct_t* di; 534887Schin int type; 544887Schin #endif 554887Schin { 564887Schin size_t rw, done; 574887Schin ssize_t rv; 584887Schin 594887Schin done = 0; /* amount processed by direct IO */ 60*8462SApril.Chin@Sun.COM rv = 0; 614887Schin 624887Schin #ifdef F_DIOINFO 634887Schin if((P2I(buf)%di->dio.d_mem) == 0 && 644887Schin (f->here%di->dio.d_miniosz) == 0 && n >= di->dio.d_miniosz ) 654887Schin { /* direct IO ok, make sure we're in the right mode */ 664887Schin if(!(di->cntl & FDIRECT) ) 674887Schin { di->cntl |= FDIRECT; 684887Schin (void)fcntl(f->file, F_SETFL, di->cntl); 694887Schin } 704887Schin 714887Schin for(rw = (n/di->dio.d_miniosz)*di->dio.d_miniosz;; ) 724887Schin { size_t io; 734887Schin 744887Schin if((io = rw) > di->dio.d_maxiosz ) 754887Schin io = di->dio.d_maxiosz; 764887Schin if(type == SF_READ) 774887Schin rv = read(f->file,buf,io); 784887Schin else rv = write(f->file,buf,io); 794887Schin 804887Schin if(rv > 0) 814887Schin { rw -= rv; done += rv; 824887Schin buf = (Void_t*)((char*)buf + rv); 834887Schin } 844887Schin 854887Schin if(rv < io || rw < di->dio.d_miniosz) 864887Schin break; 874887Schin } 884887Schin } 894887Schin 904887Schin if(done < n && (di->cntl & FDIRECT) ) 914887Schin { /* turn off directIO for remaining IO operation */ 924887Schin di->cntl &= ~FDIRECT; 934887Schin (void)fcntl(f->file, F_SETFL, di->cntl); 944887Schin } 954887Schin #endif /*F_DIOINFO*/ 964887Schin 974887Schin if((rw = n-done) > 0 && 984887Schin (rv = type == SF_READ ? read(f->file,buf,rw) : write(f->file,buf,rw)) > 0 ) 994887Schin done += rv; 1004887Schin 1014887Schin return done ? done : rv; 1024887Schin } 1034887Schin 1044887Schin #if __STD_C 1054887Schin static ssize_t dioread(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc) 1064887Schin #else 1074887Schin static ssize_t dioread(f, buf, n, disc) 1084887Schin Sfio_t* f; 1094887Schin Void_t* buf; 1104887Schin size_t n; 1114887Schin Sfdisc_t* disc; 1124887Schin #endif 1134887Schin { 1144887Schin return diordwr(f, buf, n, (Direct_t*)disc, SF_READ); 1154887Schin } 1164887Schin 1174887Schin #if __STD_C 1184887Schin static ssize_t diowrite(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc) 1194887Schin #else 1204887Schin static ssize_t diowrite(f, buf, n, disc) 1214887Schin Sfio_t* f; 1224887Schin Void_t* buf; 1234887Schin size_t n; 1244887Schin Sfdisc_t* disc; 1254887Schin #endif 1264887Schin { 1274887Schin return diordwr(f, (Void_t*)buf, n, (Direct_t*)disc, SF_WRITE); 1284887Schin } 1294887Schin 1304887Schin #if __STD_C 1314887Schin static int dioexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc) 1324887Schin #else 1334887Schin static int dioexcept(f,type,data,disc) 1344887Schin Sfio_t* f; 1354887Schin int type; 1364887Schin Void_t* data; 1374887Schin Sfdisc_t* disc; 1384887Schin #endif 1394887Schin { 1404887Schin Direct_t* di = (Direct_t*)disc; 1414887Schin 1424887Schin if(type == SF_FINAL || type == SF_DPOP) 1434887Schin { 1444887Schin #ifdef F_DIOINFO 1454887Schin if(di->cntl&FDIRECT) 1464887Schin { di->cntl &= ~FDIRECT; 1474887Schin (void)fcntl(f->file,F_SETFL,di->cntl); 1484887Schin } 1494887Schin #endif 1504887Schin free(disc); 1514887Schin } 1524887Schin 1534887Schin return 0; 1544887Schin } 1554887Schin 1564887Schin #if __STD_C 1574887Schin int sfdcdio(Sfio_t* f, size_t bufsize) 1584887Schin #else 1594887Schin int sfdcdio(f, bufsize) 1604887Schin Sfio_t* f; 1614887Schin size_t bufsize; 1624887Schin #endif 1634887Schin { 1644887Schin #ifndef F_DIOINFO 1654887Schin return -1; 1664887Schin #else 1674887Schin int cntl; 1684887Schin struct dioattr dio; 1694887Schin Void_t* buf; 1704887Schin Direct_t* di; 1714887Schin 1724887Schin if(f->extent < 0 || (f->flags&SF_STRING)) 1734887Schin return -1; 1744887Schin 1754887Schin if((cntl = fcntl(f->file,F_GETFL,0)) < 0) 1764887Schin return -1; 1774887Schin 1784887Schin if(!(cntl&FDIRECT) ) 1794887Schin { cntl |= FDIRECT; 1804887Schin if(fcntl(f->file,F_SETFL,cntl) < 0) 1814887Schin return -1; 1824887Schin } 1834887Schin 1844887Schin if(fcntl(f->file,F_DIOINFO,&dio) < 0) 1854887Schin goto no_direct; 1864887Schin 1874887Schin if(bufsize > 0) 1884887Schin bufsize = (bufsize/dio.d_miniosz)*dio.d_miniosz; 1894887Schin if(bufsize <= 0) 1904887Schin bufsize = dio.d_miniosz*64; 1914887Schin if(bufsize > dio.d_maxiosz) 1924887Schin bufsize = dio.d_maxiosz; 1934887Schin 1944887Schin if(!(di = (Direct_t*)malloc(sizeof(Direct_t))) ) 1954887Schin goto no_direct; 1964887Schin 1974887Schin if(!(buf = (Void_t*)memalign(dio.d_mem,bufsize)) ) 1984887Schin { free(di); 1994887Schin goto no_direct; 2004887Schin } 2014887Schin 2024887Schin sfsetbuf(f,buf,bufsize); 2034887Schin if(sfsetbuf(f,buf,0) == buf) 2044887Schin sfset(f,SF_MALLOC,1); 2054887Schin else 2064887Schin { free(buf); 2074887Schin free(di); 2084887Schin goto no_direct; 2094887Schin } 2104887Schin 2114887Schin di->disc.readf = dioread; 2124887Schin di->disc.writef = diowrite; 2134887Schin di->disc.seekf = NIL(Sfseek_f); 2144887Schin di->disc.exceptf = dioexcept; 2154887Schin di->cntl = cntl; 2164887Schin di->dio = dio; 2174887Schin 2184887Schin if(sfdisc(f,(Sfdisc_t*)di) != (Sfdisc_t*)di) 2194887Schin { free(di); 2204887Schin no_direct: 2214887Schin cntl &= ~FDIRECT; 2224887Schin (void)fcntl(f->file,F_SETFL,cntl); 2234887Schin return -1; 2244887Schin } 2254887Schin 2264887Schin return 0; 2274887Schin 2284887Schin #endif /*F_DIOINFO*/ 2294887Schin } 230