⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 reconcile.c

📁 lustre 1.6.5 source code
💻 C
字号:
/* *    This Cplant(TM) source code is the property of Sandia National *    Laboratories. * *    This Cplant(TM) source code is copyrighted by Sandia National *    Laboratories. * *    The redistribution of this Cplant(TM) source code is subject to the *    terms of the GNU Lesser General Public License *    (see cit/LGPL or http://www.gnu.org/licenses/lgpl.html) * *    Cplant(TM) Copyright 1998-2004 Sandia Corporation.  *    Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive *    license for use of this work by or on behalf of the US Government. *    Export of this program may require a license from the United States *    Government. *//* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. *  * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. *  * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Questions or comments about this library should be sent to: * * Lee Ward * Sandia National Laboratories, New Mexico * P.O. Box 5800 * Albuquerque, NM 87185-1110 * * lee@sandia.gov */#include <stdlib.h>#include <string.h>#include <errno.h>#include <assert.h>#include <sys/uio.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/queue.h>#include "sysio.h"#include "xtio.h"/* * Extent-vector IO support. *//* * Arguments to IO vector enumerator callback when used by _sysio_doio(). */struct doio_helper_args {	ssize_t (*f)(void *, size_t, _SYSIO_OFF_T, void *);	/* base func */	void	*arg;						/* caller arg */};/* * General help validating strided-IO vectors. * * A driver may call this to make sure underflow/overflow of an off_t can't * occur and overflow of a ssize_t can't occur when writing. The sum * of the reconciled transfer length is returned or some appropriate * error depending on underflow/overflow. * * The following algorithm assumes: * * a) sizeof(size_t) >= sizeof(ssize_t) * b) 2's complement arithmetic * c) The compiler won't optimize away code because it's developers *	believed that something with an undefined result in `C' can't happen. */ssize_t_sysio_validx(const struct intnl_xtvec *xtv, size_t xtvlen,	      const struct iovec *iov, size_t iovlen,	      _SYSIO_OFF_T limit){	ssize_t	acc, cc;	struct iovec iovec;	struct intnl_xtvec xtvec;	_SYSIO_OFF_T off;	if (!(xtvlen && iovlen))		return -EINVAL;	acc = 0;	xtvec.xtv_len = iovec.iov_len = 0;	do {		while (!xtvec.xtv_len) {			if (!xtvlen--)				break;			if (!xtv->xtv_len) {				xtv++;				continue;			}			xtvec = *xtv++;			if (xtvec.xtv_off < 0)				return -EINVAL;		}		if (!xtvec.xtv_len)			break;		do {			while (!iovec.iov_len) {				if (!iovlen--)					break;				if (!iov->iov_len) {					iov++;					continue;				}				iovec = *iov++;			}			if (!iovec.iov_len)				break;			cc = iovec.iov_len;			if (cc < 0)				return -EINVAL;			if ((size_t )cc > xtvec.xtv_len)				cc = xtvec.xtv_len;			xtvec.xtv_len -= cc;			iovec.iov_len -= cc;			off = xtvec.xtv_off + cc;			if (xtvec.xtv_off && off <= xtvec.xtv_off)				return off < 0 ? -EINVAL : -EOVERFLOW;			if (off > limit)				return -EFBIG;			xtvec.xtv_off = off;			cc += acc;			if (acc && (cc <= acc))				return -EINVAL;			acc = cc;		} while (xtvec.xtv_len && iovlen);	} while ((xtvlen || xtvec.xtv_len) && iovlen);	return acc;}/* */ssize_t_sysio_enumerate_extents(const struct intnl_xtvec *xtv, size_t xtvlen,			 const struct iovec *iov, size_t iovlen,			 ssize_t (*f)(const struct iovec *, int,				      _SYSIO_OFF_T,				      ssize_t,				      void *),			 void *arg){	ssize_t	acc, tmp, cc;	struct iovec iovec;	struct intnl_xtvec xtvec;	const struct iovec *start;	_SYSIO_OFF_T off;	size_t	n;	size_t	remain;		acc = 0;	iovec.iov_len = 0;	while (xtvlen) {		/*		 * Coalesce contiguous extent vector entries.		 */		off = xtvec.xtv_off = xtv->xtv_off;		off += xtvec.xtv_len = xtv->xtv_len;		while (++xtv, --xtvlen) {			if (off != xtv->xtv_off) {				/*				 * Not contiguous.				 */				break;			}			if (!xtv->xtv_len) {				/*				 * Zero length.				 */				continue;			}			off += xtv->xtv_len;			xtvec.xtv_len += xtv->xtv_len;		}		while (xtvec.xtv_len) {			if (iovec.iov_len) {				tmp = iovec.iov_len; 				if (iovec.iov_len > xtvec.xtv_len)					iovec.iov_len = xtvec.xtv_len;				cc =				    (*f)(&iovec, 1,					 xtvec.xtv_off,					 xtvec.xtv_len,					 arg);				if (cc <= 0) {					if (acc)						return acc;					return cc;				}				iovec.iov_base = (char *)iovec.iov_base + cc;				iovec.iov_len = tmp - cc; 				tmp = cc + acc;				if (acc && tmp <= acc)					abort();		/* paranoia */				acc = tmp;			} else if (iovlen) {				start = iov;				n = xtvec.xtv_len;				do {					if (iov->iov_len > n) {						/*						 * That'll do.						 */						break;					}					n -= iov->iov_len;					iov++;				} while (--iovlen);				if (iov == start) {					iovec = *iov++;					iovlen--;					continue;				}				remain = xtvec.xtv_len - n;				cc =				    (*f)(start, iov - start,					 xtvec.xtv_off,					 remain,					 arg);				if (cc <= 0) {					if (acc)						return acc;					return cc;				}												tmp = cc + acc;				if (acc && tmp <= acc)					abort();		/* paranoia */				acc = tmp;				remain -= cc;				if (remain)					return acc;		/* short */			} else				return acc;			/* short out */			xtvec.xtv_off += cc;			xtvec.xtv_len -= cc;		}	}	return acc;}ssize_t_sysio_enumerate_iovec(const struct iovec *iov, size_t count,		       _SYSIO_OFF_T off,		       ssize_t limit,		       ssize_t (*f)(void *, size_t, _SYSIO_OFF_T, void *),		       void *arg){	ssize_t	acc, cc;	size_t	n;	unsigned indx;	size_t	remain;	if (!count)		return -EINVAL;	assert(limit >= 0);	acc = 0;	n = limit;	for (indx = 0; n && indx < count; indx++) {		if (iov[indx].iov_len < n) {			cc = (ssize_t )iov[indx].iov_len;			if (cc < 0)				return -EINVAL;		} else			cc = (ssize_t )n;		if (!cc)			continue;		n -= cc;		cc += acc;		if (acc && cc <= acc)			return -EINVAL;		acc = cc;	}	if (!acc)		return 0;	acc = 0;	do {		if (!iov->iov_len) {			iov++;			continue;		}		n =		    iov->iov_len < (size_t )limit		      ? iov->iov_len		      : (size_t )limit;		cc = (*f)(iov->iov_base, n, off, arg);		if (cc <= 0) {			if (acc)				return acc;			return cc;		}		off += cc;		limit -= cc;		remain = iov->iov_len - cc;		cc += acc;		if (acc && cc <= acc)			abort();			/* bad driver! */		acc = cc;		if (remain || !limit)			break;				/* short/limited read */		iov++;	} while (--count);	return acc;}static ssize_t_sysio_doio_helper(const struct iovec *iov, int count,		   _SYSIO_OFF_T off,		   ssize_t limit,		   struct doio_helper_args *args){	return _sysio_enumerate_iovec(iov, count,				      off, limit,				      args->f,				      args->arg);}/* * A meta-driver for the whole strided-io process. Appropriate when * the driver can't handle anything but simple p{read,write}-like * interface. */ssize_t_sysio_doio(const struct intnl_xtvec *xtv, size_t xtvlen,	    const struct iovec *iov, size_t iovlen,	    ssize_t (*f)(void *, size_t, _SYSIO_OFF_T, void *),	    void *arg){	struct doio_helper_args arguments;	arguments.f = f;	arguments.arg = arg;	return _sysio_enumerate_extents(xtv, xtvlen,					iov, iovlen,					(ssize_t (*)(const struct iovec *, int,						     _SYSIO_OFF_T,						     ssize_t,						     void *))_sysio_doio_helper,					&arguments);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -