2013-05-17 03:35:21 +04:00
# include <linux/uaccess.h>
# include <linux/export.h>
# include <linux/uio.h>
/*
* Copy iovec to kernel . Returns - EFAULT on error .
*
* Note : this modifies the original iovec .
*/
int memcpy_fromiovec ( unsigned char * kdata , struct iovec * iov , int len )
{
while ( len > 0 ) {
if ( iov - > iov_len ) {
int copy = min_t ( unsigned int , len , iov - > iov_len ) ;
if ( copy_from_user ( kdata , iov - > iov_base , copy ) )
return - EFAULT ;
len - = copy ;
kdata + = copy ;
iov - > iov_base + = copy ;
iov - > iov_len - = copy ;
}
iov + + ;
}
return 0 ;
}
EXPORT_SYMBOL ( memcpy_fromiovec ) ;
/*
* Copy kernel to iovec . Returns - EFAULT on error .
*
* Note : this modifies the original iovec .
*/
int memcpy_toiovec ( struct iovec * iov , unsigned char * kdata , int len )
{
while ( len > 0 ) {
if ( iov - > iov_len ) {
int copy = min_t ( unsigned int , iov - > iov_len , len ) ;
if ( copy_to_user ( iov - > iov_base , kdata , copy ) )
return - EFAULT ;
kdata + = copy ;
len - = copy ;
iov - > iov_len - = copy ;
iov - > iov_base + = copy ;
}
iov + + ;
}
return 0 ;
}
EXPORT_SYMBOL ( memcpy_toiovec ) ;
2014-06-19 22:22:56 +04:00
/*
* Copy kernel to iovec . Returns - EFAULT on error .
*/
int memcpy_toiovecend ( const struct iovec * iov , unsigned char * kdata ,
int offset , int len )
{
int copy ;
for ( ; len > 0 ; + + iov ) {
/* Skip over the finished iovecs */
if ( unlikely ( offset > = iov - > iov_len ) ) {
offset - = iov - > iov_len ;
continue ;
}
copy = min_t ( unsigned int , iov - > iov_len - offset , len ) ;
if ( copy_to_user ( iov - > iov_base + offset , kdata , copy ) )
return - EFAULT ;
offset = 0 ;
kdata + = copy ;
len - = copy ;
}
return 0 ;
}
EXPORT_SYMBOL ( memcpy_toiovecend ) ;
/*
* Copy iovec to kernel . Returns - EFAULT on error .
*/
int memcpy_fromiovecend ( unsigned char * kdata , const struct iovec * iov ,
int offset , int len )
{
2014-08-01 07:00:35 +04:00
/* No data? Done! */
if ( len = = 0 )
return 0 ;
2014-06-19 22:22:56 +04:00
/* Skip over the finished iovecs */
while ( offset > = iov - > iov_len ) {
offset - = iov - > iov_len ;
iov + + ;
}
while ( len > 0 ) {
u8 __user * base = iov - > iov_base + offset ;
int copy = min_t ( unsigned int , len , iov - > iov_len - offset ) ;
offset = 0 ;
if ( copy_from_user ( kdata , base , copy ) )
return - EFAULT ;
len - = copy ;
kdata + = copy ;
iov + + ;
}
return 0 ;
}
EXPORT_SYMBOL ( memcpy_fromiovecend ) ;