[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