|
|
3604df |
From dd56ebdefdc8e3d0fe1bbeea6185b72ba0e57871 Mon Sep 17 00:00:00 2001
|
|
|
3604df |
From: Krutika Dhananjay <kdhananj@redhat.com>
|
|
|
3604df |
Date: Mon, 17 Oct 2016 15:13:28 +0530
|
|
|
3604df |
Subject: [PATCH 141/141] compound fops: Fix file corruption issue
|
|
|
3604df |
|
|
|
3604df |
Backport of: http://review.gluster.org/#/c/15654/
|
|
|
3604df |
|
|
|
3604df |
1. Address of a local variable @args is copied into state->req
|
|
|
3604df |
in server3_3_compound (). But even after the function has gone out of
|
|
|
3604df |
scope, in server_compound_resume () this pointer is accessed and
|
|
|
3604df |
dereferenced. This patch fixes that.
|
|
|
3604df |
|
|
|
3604df |
2. Compound fops, by virtue of NOT having a vector sizer (like the one
|
|
|
3604df |
writev has), ends up having both the header and the data (in case one of
|
|
|
3604df |
its member fops is WRITEV) in the same hdr_iobuf. This buffer was not
|
|
|
3604df |
being preserved through the lifetime of the compound fop, causing it to
|
|
|
3604df |
be overwritten by a parallel write fop, even when the writev associated
|
|
|
3604df |
with the currently executing compound fop is yet to hit the desk, thereby
|
|
|
3604df |
corrupting the file's data. This is fixed by associating the hdr_iobuf with
|
|
|
3604df |
the iobref so its memory remains valid through the lifetime of the fop.
|
|
|
3604df |
|
|
|
3604df |
3. Also fixed a use-after-free bug in protocol/client in compound fops cbk,
|
|
|
3604df |
missed by Linux but caught by NetBSD.
|
|
|
3604df |
|
|
|
3604df |
Finally, big thanks to Pranith Kumar K and Raghavendra Gowdappa for their
|
|
|
3604df |
help in debugging this file corruption issue.
|
|
|
3604df |
|
|
|
3604df |
Change-Id: I0e926dc84b7cc8b9b34b7433ed392516ecdd44bd
|
|
|
3604df |
BUG: 1379919
|
|
|
3604df |
Signed-off-by: Krutika Dhananjay <kdhananj@redhat.com>
|
|
|
3604df |
Reviewed-on: https://code.engineering.redhat.com/gerrit/87999
|
|
|
3604df |
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
|
|
|
3604df |
Tested-by: Atin Mukherjee <amukherj@redhat.com>
|
|
|
3604df |
---
|
|
|
3604df |
rpc/rpc-lib/src/rpc-transport.c | 6 +---
|
|
|
3604df |
rpc/rpc-lib/src/rpc-transport.h | 1 -
|
|
|
3604df |
rpc/rpc-lib/src/rpcsvc.c | 6 ----
|
|
|
3604df |
rpc/rpc-lib/src/rpcsvc.h | 3 --
|
|
|
3604df |
tests/basic/afr/compounded-write-txns.t | 37 +++++++++++++++++++++++++
|
|
|
3604df |
xlators/protocol/client/src/client-rpc-fops.c | 9 +++---
|
|
|
3604df |
xlators/protocol/server/src/server-rpc-fops.c | 4 +-
|
|
|
3604df |
xlators/protocol/server/src/server.h | 2 +-
|
|
|
3604df |
8 files changed, 46 insertions(+), 22 deletions(-)
|
|
|
3604df |
create mode 100644 tests/basic/afr/compounded-write-txns.t
|
|
|
3604df |
|
|
|
3604df |
diff --git a/rpc/rpc-lib/src/rpc-transport.c b/rpc/rpc-lib/src/rpc-transport.c
|
|
|
3604df |
index a74aa22..f3ebe2d 100644
|
|
|
3604df |
--- a/rpc/rpc-lib/src/rpc-transport.c
|
|
|
3604df |
+++ b/rpc/rpc-lib/src/rpc-transport.c
|
|
|
3604df |
@@ -123,10 +123,6 @@ rpc_transport_pollin_destroy (rpc_transport_pollin_t *pollin)
|
|
|
3604df |
iobref_unref (pollin->iobref);
|
|
|
3604df |
}
|
|
|
3604df |
|
|
|
3604df |
- if (pollin->hdr_iobuf) {
|
|
|
3604df |
- iobuf_unref (pollin->hdr_iobuf);
|
|
|
3604df |
- }
|
|
|
3604df |
-
|
|
|
3604df |
if (pollin->private) {
|
|
|
3604df |
/* */
|
|
|
3604df |
GF_FREE (pollin->private);
|
|
|
3604df |
@@ -158,7 +154,7 @@ rpc_transport_pollin_alloc (rpc_transport_t *this, struct iovec *vector,
|
|
|
3604df |
msg->iobref = iobref_ref (iobref);
|
|
|
3604df |
msg->private = private;
|
|
|
3604df |
if (hdr_iobuf)
|
|
|
3604df |
- msg->hdr_iobuf = iobuf_ref (hdr_iobuf);
|
|
|
3604df |
+ iobref_add (iobref, hdr_iobuf);
|
|
|
3604df |
|
|
|
3604df |
out:
|
|
|
3604df |
return msg;
|
|
|
3604df |
diff --git a/rpc/rpc-lib/src/rpc-transport.h b/rpc/rpc-lib/src/rpc-transport.h
|
|
|
3604df |
index 227911a..1d4b444 100644
|
|
|
3604df |
--- a/rpc/rpc-lib/src/rpc-transport.h
|
|
|
3604df |
+++ b/rpc/rpc-lib/src/rpc-transport.h
|
|
|
3604df |
@@ -163,7 +163,6 @@ struct rpc_transport_pollin {
|
|
|
3604df |
char vectored;
|
|
|
3604df |
void *private;
|
|
|
3604df |
struct iobref *iobref;
|
|
|
3604df |
- struct iobuf *hdr_iobuf;
|
|
|
3604df |
char is_reply;
|
|
|
3604df |
};
|
|
|
3604df |
typedef struct rpc_transport_pollin rpc_transport_pollin_t;
|
|
|
3604df |
diff --git a/rpc/rpc-lib/src/rpcsvc.c b/rpc/rpc-lib/src/rpcsvc.c
|
|
|
3604df |
index 05d2696..2a2ca64 100644
|
|
|
3604df |
--- a/rpc/rpc-lib/src/rpcsvc.c
|
|
|
3604df |
+++ b/rpc/rpc-lib/src/rpcsvc.c
|
|
|
3604df |
@@ -373,9 +373,6 @@ rpcsvc_request_destroy (rpcsvc_request_t *req)
|
|
|
3604df |
iobref_unref (req->iobref);
|
|
|
3604df |
}
|
|
|
3604df |
|
|
|
3604df |
- if (req->hdr_iobuf)
|
|
|
3604df |
- iobuf_unref (req->hdr_iobuf);
|
|
|
3604df |
-
|
|
|
3604df |
/* This marks the "end" of an RPC request. Reply is
|
|
|
3604df |
completely written to the socket and is on the way
|
|
|
3604df |
to the client. It is time to decrement the
|
|
|
3604df |
@@ -690,9 +687,6 @@ rpcsvc_handle_rpc_call (rpcsvc_t *svc, rpc_transport_t *trans,
|
|
|
3604df |
}
|
|
|
3604df |
|
|
|
3604df |
if (req->synctask) {
|
|
|
3604df |
- if (msg->hdr_iobuf)
|
|
|
3604df |
- req->hdr_iobuf = iobuf_ref (msg->hdr_iobuf);
|
|
|
3604df |
-
|
|
|
3604df |
ret = synctask_new (THIS->ctx->env,
|
|
|
3604df |
(synctask_fn_t) actor_fn,
|
|
|
3604df |
rpcsvc_check_and_reply_error, NULL,
|
|
|
3604df |
diff --git a/rpc/rpc-lib/src/rpcsvc.h b/rpc/rpc-lib/src/rpcsvc.h
|
|
|
3604df |
index 02e467e..63a6dad 100644
|
|
|
3604df |
--- a/rpc/rpc-lib/src/rpcsvc.h
|
|
|
3604df |
+++ b/rpc/rpc-lib/src/rpcsvc.h
|
|
|
3604df |
@@ -244,9 +244,6 @@ struct rpcsvc_request {
|
|
|
3604df |
/* Container for transport to store request-specific item */
|
|
|
3604df |
void *trans_private;
|
|
|
3604df |
|
|
|
3604df |
- /* we need to ref the 'iobuf' in case of 'synctasking' it */
|
|
|
3604df |
- struct iobuf *hdr_iobuf;
|
|
|
3604df |
-
|
|
|
3604df |
/* pointer to cached reply for use in DRC */
|
|
|
3604df |
drc_cached_op_t *reply;
|
|
|
3604df |
};
|
|
|
3604df |
diff --git a/tests/basic/afr/compounded-write-txns.t b/tests/basic/afr/compounded-write-txns.t
|
|
|
3604df |
new file mode 100644
|
|
|
3604df |
index 0000000..7cecd87
|
|
|
3604df |
--- /dev/null
|
|
|
3604df |
+++ b/tests/basic/afr/compounded-write-txns.t
|
|
|
3604df |
@@ -0,0 +1,37 @@
|
|
|
3604df |
+#!/bin/bash
|
|
|
3604df |
+. $(dirname $0)/../../include.rc
|
|
|
3604df |
+. $(dirname $0)/../../volume.rc
|
|
|
3604df |
+
|
|
|
3604df |
+cleanup
|
|
|
3604df |
+
|
|
|
3604df |
+TEST glusterd
|
|
|
3604df |
+TEST pidof glusterd
|
|
|
3604df |
+TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0,1,2}
|
|
|
3604df |
+TEST $CLI volume set $V0 write-behind off
|
|
|
3604df |
+TEST $CLI volume set $V0 client-io-threads off
|
|
|
3604df |
+TEST $CLI volume start $V0
|
|
|
3604df |
+TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0
|
|
|
3604df |
+
|
|
|
3604df |
+# Create and generate data into a src file
|
|
|
3604df |
+
|
|
|
3604df |
+TEST `printf %1024s |tr " " "1" > /tmp/source`
|
|
|
3604df |
+TEST `printf %1024s |tr " " "2" >> /tmp/source`
|
|
|
3604df |
+
|
|
|
3604df |
+TEST dd if=/tmp/source of=$M0/file bs=1024 count=2 2>/dev/null
|
|
|
3604df |
+md5sum_file=$(md5sum $M0/file | awk '{print $1}')
|
|
|
3604df |
+
|
|
|
3604df |
+TEST $CLI volume set $V0 cluster.use-compound-fops on
|
|
|
3604df |
+
|
|
|
3604df |
+TEST dd if=$M0/file of=$M0/file-copy bs=1024 count=2 2>/dev/null
|
|
|
3604df |
+
|
|
|
3604df |
+EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0
|
|
|
3604df |
+TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0
|
|
|
3604df |
+
|
|
|
3604df |
+EXPECT "$md5sum_file" echo `md5sum $M0/file-copy | awk '{print $1}'`
|
|
|
3604df |
+
|
|
|
3604df |
+EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0
|
|
|
3604df |
+TEST $CLI volume stop $V0
|
|
|
3604df |
+TEST $CLI volume delete $V0
|
|
|
3604df |
+
|
|
|
3604df |
+TEST rm -f /tmp/source
|
|
|
3604df |
+cleanup
|
|
|
3604df |
diff --git a/xlators/protocol/client/src/client-rpc-fops.c b/xlators/protocol/client/src/client-rpc-fops.c
|
|
|
3604df |
index c122941..8085aec 100644
|
|
|
3604df |
--- a/xlators/protocol/client/src/client-rpc-fops.c
|
|
|
3604df |
+++ b/xlators/protocol/client/src/client-rpc-fops.c
|
|
|
3604df |
@@ -3166,7 +3166,8 @@ client3_3_compound_cbk (struct rpc_req *req, struct iovec *iov, int count,
|
|
|
3604df |
dict_t *xdata = NULL;
|
|
|
3604df |
clnt_local_t *local = NULL;
|
|
|
3604df |
int op_errno = 0;
|
|
|
3604df |
- int i,length = 0;
|
|
|
3604df |
+ int i = 0;
|
|
|
3604df |
+ int length = 0;
|
|
|
3604df |
int ret = -1;
|
|
|
3604df |
|
|
|
3604df |
this = THIS;
|
|
|
3604df |
@@ -3187,12 +3188,12 @@ client3_3_compound_cbk (struct rpc_req *req, struct iovec *iov, int count,
|
|
|
3604df |
goto out;
|
|
|
3604df |
}
|
|
|
3604df |
|
|
|
3604df |
+ length = local->length;
|
|
|
3604df |
+
|
|
|
3604df |
GF_PROTOCOL_DICT_UNSERIALIZE (this, xdata, (rsp.xdata.xdata_val),
|
|
|
3604df |
(rsp.xdata.xdata_len), rsp.op_ret,
|
|
|
3604df |
rsp.op_errno, out);
|
|
|
3604df |
|
|
|
3604df |
- length = local->length;
|
|
|
3604df |
-
|
|
|
3604df |
args_cbk = compound_args_cbk_alloc (length, xdata);
|
|
|
3604df |
if (!args_cbk) {
|
|
|
3604df |
op_errno = ENOMEM;
|
|
|
3604df |
@@ -3215,7 +3216,7 @@ out:
|
|
|
3604df |
|
|
|
3604df |
free (rsp.xdata.xdata_val);
|
|
|
3604df |
|
|
|
3604df |
- client_compound_rsp_cleanup (&rsp, local->length);
|
|
|
3604df |
+ client_compound_rsp_cleanup (&rsp, length);
|
|
|
3604df |
|
|
|
3604df |
if (xdata)
|
|
|
3604df |
dict_unref (xdata);
|
|
|
3604df |
diff --git a/xlators/protocol/server/src/server-rpc-fops.c b/xlators/protocol/server/src/server-rpc-fops.c
|
|
|
3604df |
index 756275e..d8ad6a7 100644
|
|
|
3604df |
--- a/xlators/protocol/server/src/server-rpc-fops.c
|
|
|
3604df |
+++ b/xlators/protocol/server/src/server-rpc-fops.c
|
|
|
3604df |
@@ -3332,7 +3332,7 @@ server_compound_resume (call_frame_t *frame, xlator_t *bound_xl)
|
|
|
3604df |
goto err;
|
|
|
3604df |
}
|
|
|
3604df |
|
|
|
3604df |
- req = state->req;
|
|
|
3604df |
+ req = &state->req;
|
|
|
3604df |
|
|
|
3604df |
length = req->compound_req_array.compound_req_array_len;
|
|
|
3604df |
state->args = compound_fop_alloc (length, req->compound_fop_enum,
|
|
|
3604df |
@@ -6736,7 +6736,7 @@ server3_3_compound (rpcsvc_request_t *req)
|
|
|
3604df |
goto out;
|
|
|
3604df |
}
|
|
|
3604df |
|
|
|
3604df |
- state->req = &arg;;
|
|
|
3604df |
+ state->req = args;
|
|
|
3604df |
state->iobref = iobref_ref (req->iobref);
|
|
|
3604df |
|
|
|
3604df |
if (len < req->msg[0].iov_len) {
|
|
|
3604df |
diff --git a/xlators/protocol/server/src/server.h b/xlators/protocol/server/src/server.h
|
|
|
3604df |
index f50e9ab..3272106 100644
|
|
|
3604df |
--- a/xlators/protocol/server/src/server.h
|
|
|
3604df |
+++ b/xlators/protocol/server/src/server.h
|
|
|
3604df |
@@ -191,7 +191,7 @@ struct _server_state {
|
|
|
3604df |
struct gf_lease lease;
|
|
|
3604df |
lock_migration_info_t locklist;
|
|
|
3604df |
/* required for compound fops */
|
|
|
3604df |
- gfs3_compound_req *req;
|
|
|
3604df |
+ gfs3_compound_req req;
|
|
|
3604df |
/* last length till which iovec for compound
|
|
|
3604df |
* writes was processed */
|
|
|
3604df |
int write_length;
|
|
|
3604df |
--
|
|
|
3604df |
1.7.1
|
|
|
3604df |
|