d1681e
From 2c8b94fb5359424a17dc0380b86cb17058f07bf6 Mon Sep 17 00:00:00 2001
d1681e
From: Sachin Prabhu <sprabhu@redhat.com>
d1681e
Date: Wed, 14 Feb 2018 10:36:27 +0530
d1681e
Subject: [PATCH 200/201] quick-read: Discard cache for fallocate, zerofill and
d1681e
 discard ops
d1681e
d1681e
The fallocate, zerofill and discard modify file data on the server thus
d1681e
rendering stale any cache held by the xlator on the client.
d1681e
d1681e
mainline:
d1681e
> BUG: 1524252
d1681e
> Reviewed-on: https://review.gluster.org/19018
d1681e
> Reviewed-by: Raghavendra G <rgowdapp@redhat.com>
d1681e
> Signed-off-by: Sachin Prabhu <sprabhu@redhat.com>
d1681e
(cherry picked from commit 429f2436b33793136836042ccc43ce4cfd7f89f3)
d1681e
d1681e
BUG: 1523599
d1681e
Change-Id: I432146c6390a0cd5869420c373f598da43915f3f
d1681e
Signed-off-by: Sachin Prabhu <sprabhu@redhat.com>
d1681e
Reviewed-on: https://code.engineering.redhat.com/gerrit/130229
d1681e
Tested-by: RHGS Build Bot <nigelb@redhat.com>
d1681e
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
d1681e
---
d1681e
 tests/bugs/quick-read/bz1523599/bz1523599.t      |  32 ++++
d1681e
 tests/bugs/quick-read/bz1523599/test_bz1523599.c | 196 +++++++++++++++++++++++
d1681e
 xlators/performance/quick-read/src/quick-read.c  |  40 ++++-
d1681e
 3 files changed, 267 insertions(+), 1 deletion(-)
d1681e
 create mode 100755 tests/bugs/quick-read/bz1523599/bz1523599.t
d1681e
 create mode 100644 tests/bugs/quick-read/bz1523599/test_bz1523599.c
d1681e
d1681e
diff --git a/tests/bugs/quick-read/bz1523599/bz1523599.t b/tests/bugs/quick-read/bz1523599/bz1523599.t
d1681e
new file mode 100755
d1681e
index 0000000..5027efe
d1681e
--- /dev/null
d1681e
+++ b/tests/bugs/quick-read/bz1523599/bz1523599.t
d1681e
@@ -0,0 +1,32 @@
d1681e
+#!/bin/bash
d1681e
+
d1681e
+. $(dirname $0)/../../../include.rc
d1681e
+. $(dirname $0)/../../../volume.rc
d1681e
+. $(dirname $0)/../../../fileio.rc
d1681e
+
d1681e
+cleanup;
d1681e
+
d1681e
+TEST glusterd
d1681e
+TEST pidof glusterd
d1681e
+
d1681e
+TEST $CLI volume create $V0 $H0:$B0/brick1;
d1681e
+EXPECT 'Created' volinfo_field $V0 'Status';
d1681e
+
d1681e
+TEST $CLI volume start $V0;
d1681e
+EXPECT 'Started' volinfo_field $V0 'Status';
d1681e
+
d1681e
+logdir=`gluster --print-logdir`
d1681e
+
d1681e
+TEST build_tester $(dirname $0)/test_bz1523599.c -lgfapi -o $(dirname $0)/test_bz1523599
d1681e
+TEST ./$(dirname $0)/test_bz1523599 0 $H0 $V0 test_bz1523599 $logdir/bz1523599.log
d1681e
+TEST ./$(dirname $0)/test_bz1523599 1 $H0 $V0 test_bz1523599 $logdir/bz1523599.log
d1681e
+TEST ./$(dirname $0)/test_bz1523599 0 $H0 $V0 test_bz1523599 $logdir/bz1523599.log
d1681e
+TEST ./$(dirname $0)/test_bz1523599 2 $H0 $V0 test_bz1523599 $logdir/bz1523599.log
d1681e
+
d1681e
+cleanup_tester $(dirname $0)/test_bz1523599
d1681e
+
d1681e
+TEST $CLI volume stop $V0
d1681e
+TEST $CLI volume delete $V0
d1681e
+
d1681e
+cleanup;
d1681e
+
d1681e
diff --git a/tests/bugs/quick-read/bz1523599/test_bz1523599.c b/tests/bugs/quick-read/bz1523599/test_bz1523599.c
d1681e
new file mode 100644
d1681e
index 0000000..f0166e1
d1681e
--- /dev/null
d1681e
+++ b/tests/bugs/quick-read/bz1523599/test_bz1523599.c
d1681e
@@ -0,0 +1,196 @@
d1681e
+/*
d1681e
+ * ./test_bz1523599 0 vm140-111 gv0 test211 log
d1681e
+ * ./test_bz1523599 1 vm140-111 gv0 test211 log
d1681e
+ * Open - Discard - Read - Then check read information to see if the initial TEST_STR_LEN/2 bytes read zero
d1681e
+ */
d1681e
+
d1681e
+#define _GNU_SOURCE
d1681e
+#include <stdio.h>
d1681e
+#include <stdlib.h>
d1681e
+#include <glusterfs/api/glfs.h>
d1681e
+#include <glusterfs/api/glfs-handles.h>
d1681e
+#include <errno.h>
d1681e
+#include <sys/uio.h>
d1681e
+
d1681e
+#define TEST_STR_LEN 2048
d1681e
+
d1681e
+enum fallocate_flag {
d1681e
+        TEST_WRITE,
d1681e
+        TEST_DISCARD,
d1681e
+        TEST_ZEROFILL,
d1681e
+};
d1681e
+
d1681e
+void print_str(char *str, int len)
d1681e
+{
d1681e
+        int i, addr;
d1681e
+
d1681e
+        printf("%07x\t", 0);
d1681e
+        for (i = 0; i < len; i++) {
d1681e
+                printf("%02x", str[i]);
d1681e
+                if (i) {
d1681e
+                        if ((i + 1) % 16 == 0)
d1681e
+                                printf("\n%07x\t", i+1);
d1681e
+                        else if ((i + 1) % 4 == 0)
d1681e
+                                printf(" ");
d1681e
+                }
d1681e
+        }
d1681e
+        printf("\n");
d1681e
+}
d1681e
+
d1681e
+int
d1681e
+test_read(char *str, int total_length, int len_zero)
d1681e
+{
d1681e
+        int i;
d1681e
+        int ret = 0;
d1681e
+
d1681e
+        for (i = 0; i < len_zero; i++) {
d1681e
+                if (str[i]) {
d1681e
+                        fprintf(stderr, "char at position %d not zeroed out\n",
d1681e
+                                i);
d1681e
+                        ret = -EIO;
d1681e
+                        goto out;
d1681e
+                }
d1681e
+        }
d1681e
+
d1681e
+        for (i = len_zero; i < total_length; i++) {
d1681e
+                if (str[i] != 0x11) {
d1681e
+                        fprintf(stderr,
d1681e
+                                "char at position %d does not contain pattern\n",
d1681e
+                                i);
d1681e
+                        ret = -EIO;
d1681e
+                        goto out;
d1681e
+                }
d1681e
+        }
d1681e
+out:
d1681e
+        return ret;
d1681e
+}
d1681e
+
d1681e
+int main(int argc, char *argv[])
d1681e
+{
d1681e
+        int opcode;
d1681e
+        char *host_name, *volume_name, *file_path, *glfs_log_path;
d1681e
+        glfs_t *fs = NULL;
d1681e
+        glfs_fd_t *fd = NULL;
d1681e
+        off_t offset = 0;
d1681e
+        size_t len_zero = TEST_STR_LEN / 2;
d1681e
+        char writestr[TEST_STR_LEN];
d1681e
+        char readstr[TEST_STR_LEN];
d1681e
+        struct iovec iov = {&readstr, TEST_STR_LEN};
d1681e
+        int i;
d1681e
+        int ret = 1;
d1681e
+
d1681e
+        for (i = 0; i < TEST_STR_LEN; i++)
d1681e
+                writestr[i] = 0x11;
d1681e
+        for (i = 0; i < TEST_STR_LEN; i++)
d1681e
+                readstr[i] = 0x22;
d1681e
+
d1681e
+        if (argc != 6) {
d1681e
+                fprintf(stderr,
d1681e
+                        "Syntax: %s <test type> <host> <volname> <file-path> <log-file>\n",
d1681e
+                        argv[0]);
d1681e
+                return 1;
d1681e
+        }
d1681e
+
d1681e
+        opcode = atoi(argv[1]);
d1681e
+        host_name = argv[2];
d1681e
+        volume_name = argv[3];
d1681e
+        file_path = argv[4];
d1681e
+        glfs_log_path = argv[5];
d1681e
+
d1681e
+        fs = glfs_new(volume_name);
d1681e
+        if (!fs) {
d1681e
+                perror("glfs_new");
d1681e
+                return 1;
d1681e
+        }
d1681e
+
d1681e
+        ret = glfs_set_volfile_server(fs, "tcp", host_name, 24007);
d1681e
+        if (ret != 0) {
d1681e
+                perror("glfs_set_volfile_server");
d1681e
+                goto out;
d1681e
+        }
d1681e
+
d1681e
+        ret = glfs_set_logging(fs, glfs_log_path, 7);
d1681e
+        if (ret != 0) {
d1681e
+                perror("glfs_set_logging");
d1681e
+                goto out;
d1681e
+        }
d1681e
+
d1681e
+        ret = glfs_init(fs);
d1681e
+        if (ret != 0) {
d1681e
+                perror("glfs_init");
d1681e
+                goto out;
d1681e
+        }
d1681e
+
d1681e
+        fd = glfs_creat(fs, file_path, O_RDWR, 0777);
d1681e
+        if (fd == NULL) {
d1681e
+                perror("glfs_creat");
d1681e
+                ret = -1;
d1681e
+                goto out;
d1681e
+        }
d1681e
+
d1681e
+        switch (opcode) {
d1681e
+        case TEST_WRITE:
d1681e
+                fprintf(stderr, "Test Write\n");
d1681e
+                ret = glfs_write(fd, writestr, TEST_STR_LEN, 0);
d1681e
+                if (ret < 0) {
d1681e
+                        perror("glfs_write");
d1681e
+                        goto out;
d1681e
+                } else if (ret != TEST_STR_LEN) {
d1681e
+                        fprintf(stderr, "insufficient data written %d \n", ret);
d1681e
+                        ret = -EIO;
d1681e
+                        goto out;
d1681e
+                }
d1681e
+                ret = 0;
d1681e
+                goto out;
d1681e
+        case TEST_DISCARD:
d1681e
+                fprintf(stderr, "Test Discard\n");
d1681e
+                ret = glfs_discard(fd, offset, len_zero);
d1681e
+                if (ret < 0) {
d1681e
+                        if (errno == EOPNOTSUPP) {
d1681e
+                                fprintf(stderr, "Operation not supported\n");
d1681e
+                                ret = 0;
d1681e
+                                goto out;
d1681e
+                        }
d1681e
+                        perror("glfs_discard");
d1681e
+                        goto out;
d1681e
+                }
d1681e
+                goto test_read;
d1681e
+        case TEST_ZEROFILL:
d1681e
+                fprintf(stderr, "Test Zerofill\n");
d1681e
+                ret = glfs_zerofill(fd, offset, len_zero);
d1681e
+                if (ret < 0) {
d1681e
+                        if (errno == EOPNOTSUPP) {
d1681e
+                                fprintf(stderr, "Operation not supported\n");
d1681e
+                                ret = 0;
d1681e
+                                goto out;
d1681e
+                        }
d1681e
+                        perror("glfs_zerofill");
d1681e
+                        goto out;
d1681e
+                }
d1681e
+                goto test_read;
d1681e
+        default:
d1681e
+                ret = -1;
d1681e
+                fprintf(stderr, "Incorrect test code %d\n", opcode);
d1681e
+                goto out;
d1681e
+        }
d1681e
+
d1681e
+test_read:
d1681e
+        ret = glfs_readv(fd, &iov, 1, 0);
d1681e
+        if (ret < 0) {
d1681e
+                perror("glfs_readv");
d1681e
+                goto out;
d1681e
+        }
d1681e
+
d1681e
+        /* printf("Read str\n"); print_str(readstr, TEST_STR_LEN); printf("\n"); */
d1681e
+        ret = test_read(readstr, TEST_STR_LEN, len_zero);
d1681e
+
d1681e
+out:
d1681e
+        if (fd)
d1681e
+                glfs_close(fd);
d1681e
+        glfs_fini(fs);
d1681e
+
d1681e
+        if (ret)
d1681e
+                return -1;
d1681e
+
d1681e
+        return 0;
d1681e
+}
d1681e
diff --git a/xlators/performance/quick-read/src/quick-read.c b/xlators/performance/quick-read/src/quick-read.c
d1681e
index 92b2f82..61232c1 100644
d1681e
--- a/xlators/performance/quick-read/src/quick-read.c
d1681e
+++ b/xlators/performance/quick-read/src/quick-read.c
d1681e
@@ -668,6 +668,41 @@ qr_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset,
d1681e
 	return 0;
d1681e
 }
d1681e
 
d1681e
+static int
d1681e
+qr_fallocate (call_frame_t *frame, xlator_t *this, fd_t *fd, int keep_size,
d1681e
+              off_t offset, size_t len, dict_t *xdata)
d1681e
+{
d1681e
+        qr_inode_prune (this, fd->inode);
d1681e
+
d1681e
+        STACK_WIND (frame, default_fallocate_cbk,
d1681e
+                    FIRST_CHILD (this), FIRST_CHILD (this)->fops->fallocate,
d1681e
+                    fd, keep_size, offset, len, xdata);
d1681e
+        return 0;
d1681e
+}
d1681e
+
d1681e
+static int
d1681e
+qr_discard (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset,
d1681e
+              size_t len, dict_t *xdata)
d1681e
+{
d1681e
+        qr_inode_prune (this, fd->inode);
d1681e
+
d1681e
+        STACK_WIND (frame, default_discard_cbk,
d1681e
+                    FIRST_CHILD (this), FIRST_CHILD (this)->fops->discard,
d1681e
+                    fd, offset, len, xdata);
d1681e
+        return 0;
d1681e
+}
d1681e
+
d1681e
+static int
d1681e
+qr_zerofill (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset,
d1681e
+              off_t len, dict_t *xdata)
d1681e
+{
d1681e
+        qr_inode_prune (this, fd->inode);
d1681e
+
d1681e
+        STACK_WIND (frame, default_zerofill_cbk,
d1681e
+                    FIRST_CHILD (this), FIRST_CHILD (this)->fops->zerofill,
d1681e
+                    fd, offset, len, xdata);
d1681e
+        return 0;
d1681e
+}
d1681e
 
d1681e
 int
d1681e
 qr_open (call_frame_t *frame, xlator_t *this, loc_t *loc, int flags,
d1681e
@@ -1128,7 +1163,10 @@ struct xlator_fops fops = {
d1681e
         .readv       = qr_readv,
d1681e
 	.writev      = qr_writev,
d1681e
 	.truncate    = qr_truncate,
d1681e
-	.ftruncate   = qr_ftruncate
d1681e
+        .ftruncate   = qr_ftruncate,
d1681e
+        .fallocate   = qr_fallocate,
d1681e
+        .discard     = qr_discard,
d1681e
+        .zerofill    = qr_zerofill
d1681e
 };
d1681e
 
d1681e
 struct xlator_cbks cbks = {
d1681e
-- 
d1681e
1.8.3.1
d1681e