xref: /onnv-gate/usr/src/lib/libast/common/disc/sfdcdio.c (revision 12068:08a39a083754)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*12068SRoger.Faulkner@Oracle.COM *          Copyright (c) 1985-2010 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
78462SApril.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
diordwr(Sfio_t * f,Void_t * buf,size_t n,Direct_t * di,int type)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 */
608462SApril.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
dioread(Sfio_t * f,Void_t * buf,size_t n,Sfdisc_t * disc)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
diowrite(Sfio_t * f,const Void_t * buf,size_t n,Sfdisc_t * disc)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
dioexcept(Sfio_t * f,int type,Void_t * data,Sfdisc_t * disc)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
sfdcdio(Sfio_t * f,size_t bufsize)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