diff options
| -rw-r--r-- | tests/basic/ec/ec-seek.t | 57 | ||||
| -rw-r--r-- | tests/basic/ec/seek.c | 185 | ||||
| -rw-r--r-- | xlators/cluster/ec/src/ec-inode-read.c | 18 | 
3 files changed, 260 insertions, 0 deletions
diff --git a/tests/basic/ec/ec-seek.t b/tests/basic/ec/ec-seek.t new file mode 100644 index 00000000000..6a0060870c8 --- /dev/null +++ b/tests/basic/ec/ec-seek.t @@ -0,0 +1,57 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup + +SEEK=$(dirname $0)/seek +build_tester $(dirname $0)/seek.c -o ${SEEK} + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume info + +TEST mkdir -p $B0/${V0}{0..2} +TEST $CLI volume create $V0 disperse 3 redundancy 1 $H0:$B0/${V0}{0..2} + +EXPECT "$V0" volinfo_field $V0 'Volume Name' +EXPECT 'Created' volinfo_field $V0 'Status' +EXPECT '3' brick_count $V0 + +TEST $CLI volume start $V0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'Started' volinfo_field $V0 'Status' + +TEST $GFS -s $H0 --volfile-id $V0 $M0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 + +TEST ${SEEK} create ${M0}/test 0 1 1048576 1 +# Determine underlying filesystem allocation block size +BSIZE="$(($(${SEEK} scan ${M0}/test hole 0) * 2))" + +TEST ${SEEK} create ${M0}/test 0 ${BSIZE} $((${BSIZE} * 4 + 512)) ${BSIZE} + +EXPECT "^0$" ${SEEK} scan ${M0}/test data 0 +EXPECT "^$((${BSIZE} / 2))$" ${SEEK} scan ${M0}/test data $((${BSIZE} / 2)) +EXPECT "^$((${BSIZE} - 1))$" ${SEEK} scan ${M0}/test data $((${BSIZE} - 1)) +EXPECT "^$((${BSIZE} * 4))$" ${SEEK} scan ${M0}/test data ${BSIZE} +EXPECT "^$((${BSIZE} * 4))$" ${SEEK} scan ${M0}/test data $((${BSIZE} * 4)) +EXPECT "^$((${BSIZE} * 5))$" ${SEEK} scan ${M0}/test data $((${BSIZE} * 5)) +EXPECT "^$((${BSIZE} * 5 + 511))$" ${SEEK} scan ${M0}/test data $((${BSIZE} * 5 + 511)) +EXPECT "^ENXIO$" ${SEEK} scan ${M0}/test data $((${BSIZE} * 5 + 512)) +EXPECT "^ENXIO$" ${SEEK} scan ${M0}/test data $((${BSIZE} * 6)) + +EXPECT "^${BSIZE}$" ${SEEK} scan ${M0}/test hole 0 +EXPECT "^${BSIZE}$" ${SEEK} scan ${M0}/test hole $((${BSIZE} / 2)) +EXPECT "^${BSIZE}$" ${SEEK} scan ${M0}/test hole $((${BSIZE} - 1)) +EXPECT "^${BSIZE}$" ${SEEK} scan ${M0}/test hole ${BSIZE} +EXPECT "^$((${BSIZE} * 5 + 512))$" ${SEEK} scan ${M0}/test hole $((${BSIZE} * 4)) +EXPECT "^$((${BSIZE} * 5 + 512))$" ${SEEK} scan ${M0}/test hole $((${BSIZE} * 5)) +EXPECT "^$((${BSIZE} * 5 + 512))$" ${SEEK} scan ${M0}/test hole $((${BSIZE} * 5 + 511)) +EXPECT "^ENXIO$" ${SEEK} scan ${M0}/test hole $((${BSIZE} * 5 + 512)) +EXPECT "^ENXIO$" ${SEEK} scan ${M0}/test hole $((${BSIZE} * 6)) + +cleanup + +# Centos6 regression slaves seem to not support SEEK_DATA/SEEK_HOLE +#G_TESTDEF_TEST_STATUS_CENTOS6=BAD_TEST,BUG=000000 diff --git a/tests/basic/ec/seek.c b/tests/basic/ec/seek.c new file mode 100644 index 00000000000..67036ad4e75 --- /dev/null +++ b/tests/basic/ec/seek.c @@ -0,0 +1,185 @@ + +#define _GNU_SOURCE + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <errno.h> + +static char buffer[65536]; + +static int +parse_int(const char *text, size_t *value) +{ +        char *ptr; +        size_t val; + +        val = strtoul(text, &ptr, 0); +        if (*ptr != 0) { +                return 0; +        } + +        *value = val; + +        return 1; +} + +static int +fill_area(int fd, off_t offset, size_t size) +{ +        size_t len; +        ssize_t res; + +        while (size > 0) { +                len = sizeof(buffer); +                if (len > size) { +                        len = size; +                } +                res = pwrite(fd, buffer, len, offset); +                if (res < 0) { +                        fprintf(stderr, +                                "pwrite(%d, %p, %lu, %lu) failed: %d\n", +                                fd, buffer, size, offset, errno); +                        return 0; +                } +                if (res != len) { +                        fprintf(stderr, +                                "pwrite(%d, %p, %lu, %lu) didn't wrote all " +                                "data: %lu/%lu\n", +                                fd, buffer, size, offset, res, len); +                        return 0; +                } +                offset += len; +                size -= len; +        } + +        return 1; +} + +static void +syntax(void) +{ +        fprintf(stderr, "Syntax: seek create <path> <offset> <size> [...]\n"); +        fprintf(stderr, "        seek scan <path> data|hole <offset>\n"); +} + +static int +seek_create(const char *path, int argc, char *argv[]) +{ +        size_t off, size; +        int fd; +        int ret = 1; + +        fd = open(path, O_CREAT | O_TRUNC | O_RDWR, 0644); +        if (fd < 0) { +                fprintf(stderr, "Failed to create the file\n"); +                goto out; +        } + +        while (argc > 0) { +                if (!parse_int(argv[0], &off) || +                    !parse_int(argv[1], &size)) { +                        syntax(); +                        goto out_close; +                } +                if (!fill_area(fd, off, size)) { +                        goto out_close; +                } +                argv += 2; +                argc -= 2; +        } + +        ret = 0; + +out_close: +        close(fd); +out: +        return ret; +} + +static int +seek_scan(const char *path, const char *type, const char *pos) +{ +        size_t off, res; +        int fd, whence; +        int ret = 1; + +        if (strcmp(type, "data") == 0) { +                whence = SEEK_DATA; +        } else if (strcmp(type, "hole") == 0) { +                whence = SEEK_HOLE; +        } else { +                syntax(); +                goto out; +        } + +        if (!parse_int(pos, &off)) { +                syntax(); +                goto out; +        } + +        fd = open(path, O_RDWR); +        if (fd < 0) { +                fprintf(stderr, "Failed to open the file\n"); +                goto out; +        } + +        res = lseek(fd, off, whence); +        if (res == (off_t)-1) { +                if (errno != ENXIO) { +                        fprintf(stderr, "seek(%d, %lu, %d) failed: %d\n", fd, +                                off, whence, errno); +                        goto out_close; +                } +                fprintf(stdout, "ENXIO\n"); +        } else { +                fprintf(stdout, "%lu\n", res); +        } + +        ret = 0; + +out_close: +        close(fd); +out: +        return ret; +} + +int +main(int argc, char *argv[]) +{ +        int ret = 1; + +        memset(buffer, 0x55, sizeof(buffer)); + +        if (argc < 3) { +                syntax(); +                goto out; +        } + +        if (strcmp(argv[1], "create") == 0) { +                if (((argc - 3) & 1) != 0) { +                        syntax(); +                        goto out; +                } +                ret = seek_create(argv[2], argc - 3, argv + 3); +        } else if (strcmp(argv[1], "scan") == 0) { +                if (argc != 5) { +                        syntax(); +                        goto out; +                } +                ret = seek_scan(argv[2], argv[3], argv[4]); +        } else { +                syntax(); +                goto out; +        } + +        ret = 0; + +out: +        return ret; +} + diff --git a/xlators/cluster/ec/src/ec-inode-read.c b/xlators/cluster/ec/src/ec-inode-read.c index d03b4483a67..d925e82ba36 100644 --- a/xlators/cluster/ec/src/ec-inode-read.c +++ b/xlators/cluster/ec/src/ec-inode-read.c @@ -1556,6 +1556,7 @@ void ec_wind_seek(ec_t *ec, ec_fop_data_t *fop, int32_t idx)  int32_t ec_manager_seek(ec_fop_data_t *fop, int32_t state)  {      ec_cbk_data_t *cbk; +    size_t size;      switch (state) {      case EC_STATE_INIT: @@ -1571,6 +1572,16 @@ int32_t ec_manager_seek(ec_fop_data_t *fop, int32_t state)          return EC_STATE_DISPATCH;      case EC_STATE_DISPATCH: +        /* This shouldn't fail because we have the inode locked. */ +        GF_ASSERT(ec_get_inode_size(fop, fop->locks[0].lock->loc.inode, +                                    &size)); + +        if (fop->user_size >= size) { +            ec_fop_set_error(fop, ENXIO); + +            return EC_STATE_REPORT; +        } +          ec_dispatch_one(fop);          return EC_STATE_PREPARE_ANSWER; @@ -1582,10 +1593,17 @@ int32_t ec_manager_seek(ec_fop_data_t *fop, int32_t state)          if ((cbk != NULL) && (cbk->op_ret >= 0)) {              ec_t *ec = fop->xl->private; +            /* This shouldn't fail because we have the inode locked. */ +            GF_ASSERT(ec_get_inode_size(fop, fop->locks[0].lock->loc.inode, +                                        &size)); +              cbk->offset *= ec->fragments;              if (cbk->offset < fop->user_size) {                  cbk->offset = fop->user_size;              } +            if (cbk->offset > size) { +                cbk->offset = size; +            }          }          return EC_STATE_REPORT;  | 
