[Ocfs2-tools-devel] [PATCH] o2image: Autodetect pipes and use proper FILENO defines. v2
Sunil Mushran
sunil.mushran at oracle.com
Fri Jun 11 17:56:46 PDT 2010
Signed-off-by: Sunil Mushran<sunil.mushran at oracle.com>
On 06/11/2010 03:57 PM, Joel Becker wrote:
> [Take two - forgot to reset fpos when lseek fails]
>
> First off, don't use a naked '1' where we mean STDOUT_FILENO. Fixed.
>
> Secondly, detect whether our file descriptor is a stream with lseek().
> That way we can eventually do our own compression if we want, and the
> write code won't care.
>
> With a write function that detects where we're writing, we can do our
> zeroing in hunks of 1MB. Might be faster.
>
> Signed-off-by: Joel Becker<joel.becker at oracle.com>
> ---
> o2image/o2image.c | 135 ++++++++++++++++++++++++++++++++++++++++------------
> 1 files changed, 104 insertions(+), 31 deletions(-)
>
> diff --git a/o2image/o2image.c b/o2image/o2image.c
> index 891ec3a..215503c 100644
> --- a/o2image/o2image.c
> +++ b/o2image/o2image.c
> @@ -405,10 +405,98 @@ out:
> return ret;
> }
>
> +/*
> + * This write function takes a file descriptor and pretends to be
> + * pwrite64(). If the descriptor is seekable, it will just call
> + * pwrite64(). Otherwise it will send zeros down to fill any holes. The
> + * caller can't go backwards in the file, because seeking may not be
> + * possible.
> + *
> + * It returns -1 if it fails to finish up at offset+count. It will
> + * print its error, so the caller does not need to.
> + */
> +#define ZERO_BUF_SIZE (1<<20)
> +static ssize_t raw_write(ocfs2_filesys *fs, int fd, const void *buf,
> + size_t count, loff_t offset)
> +{
> + errcode_t ret;
> + ssize_t written;
> + static char *zero_buf = NULL;
> + static int can_seek = -1;
> + static loff_t fpos = 0;
> + loff_t to_write;
> +
> + if (can_seek == -1) {
> + /* Test if we can seek/pwrite */
> + fpos = lseek64(fd, 0, SEEK_CUR);
> + if (fpos< 0) {
> + fpos = 0;
> + can_seek = 0;
> + } else
> + can_seek = 1;
> + }
> +
> + if (!can_seek&& !zero_buf) {
> + ret = ocfs2_malloc_blocks(fs->fs_io,
> + ZERO_BUF_SIZE / fs->fs_blocksize,
> + &zero_buf);
> + if (ret) {
> + com_err(program_name, ret,
> + "while allocating zero buffer");
> + written = -1;
> + goto out;
> + }
> + memset(zero_buf, 0, ZERO_BUF_SIZE);
> + }
> +
> + if (can_seek) {
> + written = pwrite64(fd, buf, count, offset);
> + goto out;
> + }
> +
> + /* Ok, let's fake pwrite64() for the caller */
> + if (fpos> offset) {
> + com_err(program_name, OCFS2_ET_INTERNAL_FAILURE,
> + ": file position went backwards while writing "
> + "image file");
> + written = -1;
> + goto out;
> + }
> +
> + while (fpos< offset) {
> + to_write = ocfs2_min((loff_t)ZERO_BUF_SIZE, offset - fpos);
> + written = write(fd, zero_buf, to_write);
> + if (written< 0) {
> + com_err(program_name, OCFS2_ET_IO,
> + "while writing zero blocks: %s",
> + strerror(errno));
> + goto out;
> + }
> + fpos += written;
> + }
> +
> + to_write = count;
> + while (to_write) {
> + written = write(fd, buf, to_write);
> + if (written< 0) {
> + com_err(program_name, OCFS2_ET_IO,
> + "while writing data blocks: %s",
> + strerror(errno));
> + goto out;
> + }
> + fpos += written;
> + to_write -= written;
> + }
> + /* Ok, we did it */
> + written = count;
> +
> +out:
> + return written;
> +}
> +
> static errcode_t write_raw_image_file(ocfs2_filesys *ofs, int fd)
> {
> struct ocfs2_super_block *super;
> - char *zero_buf = NULL;
> char *blk_buf = NULL;
> uint64_t blk = -1;
> ssize_t count;
> @@ -417,47 +505,32 @@ static errcode_t write_raw_image_file(ocfs2_filesys *ofs, int fd)
> super = OCFS2_RAW_SB(ofs->fs_super);
> ret = ocfs2_malloc_block(ofs->fs_io,&blk_buf);
> if (ret) {
> - com_err(program_name, ret, "error while allocating buffer ");
> - goto out;
> - }
> -
> - ret = ocfs2_malloc_block(ofs->fs_io,&zero_buf);
> - if (ret) {
> - com_err(program_name, ret, "error while allocating buffer ");
> + com_err(program_name, ret, "while allocating I/O buffer");
> goto out;
> }
> - memset(zero_buf, 0, ofs->fs_blocksize);
>
> while (++blk< ofs->fs_blocks) {
> if (ocfs2_image_test_bit(ofs, blk)) {
> ret = ocfs2_read_blocks(ofs, blk, 1, blk_buf);
> if (ret) {
> - com_err(program_name, ret, "error occurred "
> - "during read cluster %"PRIu64"", blk);
> - goto out;
> + com_err(program_name, ret,
> + "while reading block %"PRIu64, blk);
> + break;
> }
>
> - if (fd == 1)
> - count = write(fd, blk_buf, ofs->fs_blocksize);
> - else
> - count = pwrite64(fd, blk_buf, ofs->fs_blocksize,
> - (__off64_t)(blk * ofs->fs_blocksize));
> - } else if (fd == 1) {
> - count = write(fd, zero_buf, ofs->fs_blocksize);
> - } else
> - continue;
> -
> - if ((count == -1) || (count< ofs->fs_blocksize)) {
> - com_err(program_name, errno, "error writing "
> - "blk %"PRIu64"", blk);
> - goto out;
> + count = raw_write(ofs, fd, blk_buf,
> + ofs->fs_blocksize,
> + (loff_t)(blk * ofs->fs_blocksize));
> + if (count< 0) {
> + ret = OCFS2_ET_IO;
> + break;
> + }
> }
> }
> +
> out:
> if (blk_buf)
> ocfs2_free(&blk_buf);
> - if (zero_buf)
> - ocfs2_free(&zero_buf);
> return ret;
> }
>
> @@ -621,7 +694,7 @@ int main(int argc, char **argv)
> int raw_flag = 0;
> int install_flag = 0;
> int interactive = 0;
> - int fd = 1;
> + int fd = STDOUT_FILENO;
> int c;
>
> if (argc&& *argv)
> @@ -716,7 +789,7 @@ int main(int argc, char **argv)
> }
>
> if (strcmp(dest_file, "-") == 0)
> - fd = 1;
> + fd = STDOUT_FILENO;
> else {
> /* prompt user for image creation */
> if (interactive&& !install_flag&&
> @@ -754,7 +827,7 @@ out:
> com_err(program_name, ret, "while closing file \"%s\"",
> src_file);
>
> - if (fd&& (fd != 1))
> + if (fd&& (fd != STDOUT_FILENO))
> close(fd);
>
> return ret;
>
More information about the Ocfs2-tools-devel
mailing list