@ -581,6 +581,52 @@ get_dirent_type(const char *path,
return result ;
}
/*
* Compute what remains to be done after a possibly partial vectored read or
* write . The part of ' source ' beginning after ' transferred ' bytes is copied
* to ' destination ' , and its length is returned . ' source ' and ' destination '
* may point to the same array , for in - place adjustment . A return value of
* zero indicates completion ( for callers without a cheaper way to know that ) .
*/
int
compute_remaining_iovec ( struct iovec * destination ,
const struct iovec * source ,
int iovcnt ,
size_t transferred )
{
Assert ( iovcnt > 0 ) ;
/* Skip wholly transferred iovecs. */
while ( source - > iov_len < = transferred )
{
transferred - = source - > iov_len ;
source + + ;
iovcnt - - ;
/* All iovecs transferred? */
if ( iovcnt = = 0 )
{
/*
* We don ' t expect the kernel to transfer more than we asked it
* to , or something is out of sync .
*/
Assert ( transferred = = 0 ) ;
return 0 ;
}
}
/* Copy the remaining iovecs to the front of the array. */
if ( source ! = destination )
memmove ( destination , source , sizeof ( * source ) * iovcnt ) ;
/* Adjust leading iovec, which may have been partially transferred. */
Assert ( destination - > iov_len > transferred ) ;
destination - > iov_base = ( char * ) destination - > iov_base + transferred ;
destination - > iov_len - = transferred ;
return iovcnt ;
}
/*
* pg_pwritev_with_retry
*
@ -601,7 +647,7 @@ pg_pwritev_with_retry(int fd, const struct iovec *iov, int iovcnt, off_t offset)
return - 1 ;
}
for ( ; ; )
do
{
/* Write as much as we can. */
part = pg_pwritev ( fd , iov , iovcnt , offset ) ;
@ -616,33 +662,14 @@ pg_pwritev_with_retry(int fd, const struct iovec *iov, int iovcnt, off_t offset)
sum + = part ;
offset + = part ;
/* Step over iovecs that are done. */
while ( iovcnt > 0 & & iov - > iov_len < = part )
{
part - = iov - > iov_len ;
+ + iov ;
- - iovcnt ;
}
/* Are they all done? */
if ( iovcnt = = 0 )
{
/* We don't expect the kernel to write more than requested. */
Assert ( part = = 0 ) ;
break ;
}
/*
* Move whatever ' s left to the front of our mutable copy and adjust
* the leading iovec .
* See what is left . On the first loop we used the caller ' s array ,
* but in later loops we ' ll use our local copy that we are allowed to
* mutate .
*/
Assert ( iovcnt > 0 ) ;
memmove ( iov_copy , iov , sizeof ( * iov ) * iovcnt ) ;
Assert ( iov - > iov_len > part ) ;
iov_copy [ 0 ] . iov_base = ( char * ) iov_copy [ 0 ] . iov_base + part ;
iov_copy [ 0 ] . iov_len - = part ;
iovcnt = compute_remaining_iovec ( iov_copy , iov , iovcnt , part ) ;
iov = iov_copy ;
}
} while ( iovcnt > 0 ) ;
return sum ;
}