[Ocfs2-test-devel] [PATCH 2/4] Ocfs2-test: Add generic file operation funcs for libocfs2test.

Sunil Mushran sunil.mushran at oracle.com
Tue Mar 31 16:28:13 PDT 2009


Comments inlined.

Tristan Ye wrote:
> Provide generic utility fuctions on file operations for ocfs2-tests.
>
> Signed-off-by: Tristan Ye <tristan.ye at oracle.com>
> ---
>  programs/libocfs2test/file_ops.c |  345 ++++++++++++++++++++++++++++++++++++++
>  programs/libocfs2test/file_ops.h |   88 ++++++++++
>  2 files changed, 433 insertions(+), 0 deletions(-)
>  create mode 100644 programs/libocfs2test/file_ops.c
>  create mode 100644 programs/libocfs2test/file_ops.h
>
> diff --git a/programs/libocfs2test/file_ops.c b/programs/libocfs2test/file_ops.c
> new file mode 100644
> index 0000000..c979b5c
> --- /dev/null
> +++ b/programs/libocfs2test/file_ops.c
> @@ -0,0 +1,345 @@
> +/* -*- mode: c; c-basic-offset: 8; -*-
> + * vim: noexpandtab sw=8 ts=8 sts=0:
> + *
> + * file_ops.c
> + *
> + * Provide generic utility fuctions on file operations for ocfs2-tests
> + *
> + * Written by tristan.ye at oracle.com
> + *
> + * Copyright (C) 2008 Oracle.  All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public
> + * License version 2 as published by the Free Software Foundation.
> + *
> + * This program 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
> + * General Public License for more details.
> + */
> +
> +#include "file_ops.h"
> +
> +extern unsigned long get_rand(unsigned long min, unsigned long max)
> +{
> +	if (min == 0 && max == 0)
> +		return 0;
> +
> +	return min + (rand() % (max - min + 1));
> +}
> +
> +extern char rand_char(void)
> +{
> +	return 'A' + (char) get_rand(0, 25);
> +}
> +
> +extern int read_at(int fd, void *buf, size_t count, off_t offset)
> +{
> +	int ret;
> +
> +	ret = pread(fd, buf, count, offset);
> +
> +	if (ret < 0) {
> +		ret = errno;
> +		fprintf(stderr, "read error %d: \"%s\"\n", ret, strerror(ret));
> +		return -1;
> +	}
> +
> +	if (ret != count) {
> +		fprintf(stderr, "Short read: wanted %ld, got %d\n", count, ret);
> +		return -1;
> +	}
>   

Short read is a valid condition. When encountered, one
is expected to resubmit the read for the remaining count/offset.

while(bytes_read < count) {
  ret = read();
  if (ret > 0)
    bytes_read += ret;
}

> +
> +        return 0;
> +}
> +
> +extern int read_at_file(char *pathname, void *buf, size_t count, off_t offset)
> +{
> +	int fd, ret;
> +
> +	fd  = open64(pathname, FILE_RO_FLAGS);
> +	if (fd < 0) {
> +		fd = errno;
> +		fprintf(stderr, "open file %s failed:%d:%s\n", pathname, fd,
> +			strerror(fd));
> +		return fd;
> +	}
> +
> +        ret = read_at(fd, buf, count, offset);
> +
> +	if (ret < 0)
> +		return ret;
> +
> +	close(fd);
> +
> +	return 0;
> +}
> +
> +extern int mmap_read_at(int fd, char *buf, size_t count, off_t offset,
> +			size_t page_size)
> +{
> +	int i, j, ret;
> +	unsigned long mmap_size = page_size;
> +	unsigned long size = offset + count;
> +	char *region;
> +
> +	while (mmap_size < size)
> +		mmap_size += page_size;
> +
> +	region = mmap(NULL, mmap_size, PROT_READ, MAP_SHARED, fd, 0);
> +
> +	if (region == MAP_FAILED) {
> +		ret = errno;
> +		fprintf(stderr, "mmap (read) error %d: \"%s\"\n", ret,
> +			strerror(ret));
> +		return -1;
> +	}
> +
> +        j = 0;
> +
> +	for (i = offset; i < size; i++) {
> +		buf[j] = region[i];
> +		j++;
> +	}
>   

memcpy() ?

> +
> +	munmap(region, mmap_size);
> +
> +	return 0;
> +}
> +
> +extern int mmap_read_at_file(char *pathname, void *buf, size_t count,
> +			     off_t offset, size_t page_size)
> +{
> +	int fd, ret;
> +
> +	fd  = open64(pathname, FILE_RO_FLAGS);
> +
> +        if (fd < 0) {
> +                fd = errno;
> +                fprintf(stderr, "open file %s failed:%d:%s\n", pathname, fd,
> +                        strerror(fd));
> +                return fd;
> +        }
>   

Use tabs.

> +
> +        ret = mmap_read_at(fd, buf, count, offset, page_size);
> +
> +	if (ret < 0)
> +		return ret;
> +
> +        close(fd);
> +
> +        return ret;
> +}
> +
> +extern int write_at(int fd, const void *buf, size_t count, off_t offset)
> +{
> +	int ret;
> +
> +	ret = pwrite(fd, buf, count, offset);
> +
> +	if (ret < 0) {
> +		ret = errno;
> +		fprintf(stderr, "write error %d: \"%s\"\n", ret, strerror(ret));
> +		return -1;
> +	}
> +
> +	if (ret != count) {
> +		fprintf(stderr, "Short write: wanted %ld, got %d\n", count, ret);
> +		return -1;
> +	}
>   

Short write is valid.

> +
> +        return 0;
> +}
> +
> +extern int write_at_file(char *pathname, const void *buf, size_t count,
> +                         off_t offset)
> +{
> +	int fd, ret;
> +
> +        fd  = open64(pathname, FILE_RW_FLAGS);
> +
> +        if (fd < 0) {
> +		fd = errno;
> +		fprintf(stderr, "open file %s failed:%d:%s\n", pathname, fd,
> +			strerror(fd));
> +		return fd;
> +	}
> +
> +	ret = write_at(fd, buf, count, offset);
> +
> +	if (ret < 0)
> +		return ret;
> +
> +        close(fd);
> +
> +        return 0;
> +}
> +
> +extern int mmap_write_at(int fd, const char *buf, size_t count, off_t offset,
> +			 size_t page_size)
> +{
> +	int i, j, ret;
> +	unsigned long mmap_size = page_size;
> +	unsigned long size = offset + count;
> +	char *region;
> +
> +	while (mmap_size < size)
> +		mmap_size += page_size;
> +
> +	region = mmap(NULL, mmap_size, PROT_WRITE, MAP_SHARED, fd, 0);
> +	if (region == MAP_FAILED) {
> +		ret = errno;
> +		fprintf(stderr, "mmap (write) error %d: \"%s\"\n", ret,
> +			strerror(ret));
> +		return -1;
> +	}
> +
> +	j = 0;
> +
> +	for (i = offset; i < size; i++)
> +		region[i] = buf[j++];
>   

memcpy()?

> +
> +	munmap(region, mmap_size);
> +
> +	return 0;
> +}
> +
> +extern int mmap_write_at_file(char *pathname, const void *buf, size_t count,
> +			      off_t offset, size_t page_size)
> +{
> +	int fd, ret;
> +
> +	fd  = open64(pathname, FILE_RW_FLAGS);
> +
> +	if (fd < 0) {
> +		fd = errno;
> +		fprintf(stderr, "open file %s failed:%d:%s\n", pathname, fd,
> +			strerror(fd));
> +		return fd;
> +	}
> +
> +	ret = mmap_write_at(fd, buf, count, offset, page_size);
> +
> +	if (ret < 0)
> +		return ret;
> +
> +	close(fd);
> +
> +	return 0;
> +}
> +
> +extern int reflink(const char *oldpath, const char *newpath)
> +{
> +	int fd, ret;
> +	struct reflink_arguments args;
> +
> +	args.old_path = (__u64)oldpath;
> +	args.new_path = (__u64)newpath;
> +
> +	fd = open64(oldpath, FILE_RO_FLAGS);
> +
> +	if (fd < 0) {
> +		fd = errno;
> +		fprintf(stderr, "open file %s failed:%d:%s\n", oldpath, fd,
> +			strerror(fd));
> +		return fd;
> +	}
> +
> +	ret = ioctl(fd, OCFS2_IOC_REFLINK, &args);
> +
> +	if (ret) {
> +		ret = errno;
> +		fprintf(stderr, "ioctl failed:%d:%s\n", ret, strerror(ret));
> +		return ret;
> +	}
> +
> +	close(fd);
> +
> +	return 0;
> +}
> +
> +extern int do_write(int fd, struct write_unit *wu, int write_method, size_t page_size)
> +{
> +        int ret;
> +        char buf[MAX_WRITE_SIZE];
> +
> +        memset(buf, wu->w_char, wu->w_len);
> +
> +        if (write_method == 1)
> +
> +		ret = mmap_write_at(fd, buf, wu->w_len, wu->w_offset, page_size);
> +	else
> +		ret = write_at(fd, buf, wu->w_len, wu->w_offset);
> +
> +	return ret;
> +}
> +
> +extern int do_write_file(char *fname, struct write_unit *wu, int write_method,
> +			 size_t page_size)
> +{
> +        int fd, ret;
> +
> +        fd  = open64(fname, FILE_RW_FLAGS);
> +        if (fd < 0) {
> +                fd = errno;
> +                fprintf(stderr, "open file %s failed:%d:%s\n", fname, fd,
> +                        strerror(fd));
> +                return fd;
> +        }
> +
> +        ret = do_write(fd, wu, write_method, page_size);
> +
> +        close(fd);
> +
> +        return ret;
> +}
> +
> +extern int get_bs_cs(char * device_name, unsigned int *bs, unsigned long *cs,
> +		     unsigned long *max_inline_sz)
> +{
> +	int ret;
> +	int open_flags = OCFS2_FLAG_HEARTBEAT_DEV_OK | OCFS2_FLAG_RO;
> +
> +	ocfs2_filesys *fs;
> +	struct ocfs2_super_block *ocfs2_sb;
> +
> +	ret = ocfs2_open(device_name, open_flags, 0, 0, &fs);
> +
> +        if (ret < 0) {
> +                com_err("CurrentTest", ret,
> +                        "while opening file system.");
> +                return ret;
> +        }
> +
> +	ocfs2_sb = OCFS2_RAW_SB(fs->fs_super);
> +
> +	*bs = 1 << ocfs2_sb->s_blocksize_bits;
> +	*cs = 1 << ocfs2_sb->s_clustersize_bits;
>   

*bs = fs->fs_blocksize;
*cs = fs->fs_clustersize;

> +	*max_inline_sz = ocfs2_max_inline_data(*bs);
> +
> +	ocfs2_close(fs);
> +
> +	return 0;
> +}
> +
> +extern int punch_hole(int fd, struct write_unit *wu)
> +{
> +	int ret;
> +	struct ocfs2_space_resv sr;
> +
> +	memset(&sr, 0, sizeof(sr));
> +	sr.l_whence = 0;
> +	sr.l_start = wu->w_offset;
> +	sr.l_len = wu->w_len;
> +
> +	ret = ioctl(fd, OCFS2_IOC_UNRESVSP64, &sr);
> +	if (ret == -1) {
> +		fprintf(stderr, "ioctl error %d: \"%s\"\n",
> +			errno, strerror(errno));
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
> diff --git a/programs/libocfs2test/file_ops.h b/programs/libocfs2test/file_ops.h
> new file mode 100644
> index 0000000..dfe5b92
> --- /dev/null
> +++ b/programs/libocfs2test/file_ops.h
> @@ -0,0 +1,88 @@
> +/* -*- mode: c; c-basic-offset: 8; -*-
> + * vim: noexpandtab sw=8 ts=8 sts=0:
> + *
> + * file_ops.h
> + *
> + * Copyright (C) 2008 Oracle.  All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public
> + * License version 2 as published by the Free Software Foundation.
> + *
> + * This program 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
> + * General Public License for more details.
> + */
> +
> +#ifndef FILE_OPS_H
> +#define FILE_OPS_H
> +
> +#define _GNU_SOURCE
> +#define _XOPEN_SOURCE 500
> +#define _LARGEFILE64_SOURCE
> +#include <unistd.h>
> +#include <errno.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <fcntl.h>
> +#include <limits.h>
> +#include <signal.h>
> +#include <sys/mman.h>
> +#include <sys/ioctl.h>
> +#include <inttypes.h>
> +#include <linux/types.h>
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <assert.h>
> +#include <getopt.h>
> +
> +#include <ocfs2/ocfs2.h>
> +
> +#define OCFS2_MAX_FILENAME_LEN  255
> +#define MAX_WRITE_SIZE		32768
> +#define RAND_CHAR_START		'A'
> +#define MAGIC_HOLE_CHAR		(RAND_CHAR_START - 1)
> +
> +#define FILE_RW_FLAGS           (O_CREAT|O_RDWR)
> +#define FILE_RO_FLAGS           (O_RDONLY)
> +#define FILE_AP_FLAGS		(O_CREAT|O_RDWR|O_APPEND)
> +
> +#define FILE_MODE               (S_IRUSR|S_IWUSR|S_IXUSR|S_IROTH|\
> +                                 S_IWOTH|S_IXOTH|S_IRGRP|S_IWGRP|S_IXGRP)
> +
> +struct write_unit {
> +	char w_char;
> +	unsigned long w_offset;
> +	unsigned int  w_len;
> +};
> +
> +unsigned long get_rand(unsigned long min, unsigned long max);
> +char rand_char(void);
> +
> +int read_at(int fd, void *buf, size_t count, off_t offset);
> +int read_at_file(char *pathname, void *buf, size_t count, off_t offset);
> +int mmap_read_at(int fd, char *buf, size_t count, off_t offset,
> +		 size_t page_size);
> +int mmap_read_at_file(char *pathname, void *buf, size_t count, off_t offset,
> +		      size_t page_size);
> +int write_at(int fd, const void *buf, size_t count, off_t offset);
> +int write_at_file(char *pathname, const void *buf, size_t count, off_t offset);
> +int mmap_write_at(int fd, const char *buf, size_t count, off_t offset,
> +		  size_t page_size);
> +int mmap_write_at_file(char *pathname, const void *buf, size_t count,
> +		       off_t offset, size_t page_size);
> +
> +int reflink(const char *oldpath, const char *newpath);
> +
> +int do_write(int fd, struct write_unit *wu, int write_method, size_t page_size);
> +int do_write_file(char *fname, struct write_unit *wu, int write_method,
> +		  size_t page_size);
> +
> +int get_bs_cs(char * device_name, unsigned int *bs, unsigned long *cs,
> +	      unsigned long *max_inline_sz);
> +
> +int punch_hole(int fd, struct write_unit *wu);
> +#endif
>   




More information about the Ocfs2-test-devel mailing list