stripe read fix (when read() is done on a sparse file over glusterfs)

Signed-off-by: Amar Tumballi <amar@gluster.com>
Signed-off-by: Anand V. Avati <avati@dev.gluster.com>

BUG: 536 (fsx tool fails over stripe)
URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=536
This commit is contained in:
Amar Tumballi 2010-03-01 03:14:39 +00:00 committed by Anand V. Avati
parent 904fef5cfe
commit bf0b366cc9
2 changed files with 69 additions and 12 deletions

View File

@ -2831,9 +2831,17 @@ stripe_readv_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
main_local->replies[index].op_errno = op_errno;
if (op_ret >= 0) {
main_local->replies[index].stbuf = *stbuf;
main_local->replies[index].count = count;
main_local->replies[index].vector =
iov_dup (vector, count);
if ((main_local->wind_count >= 2) &&
(index < (main_local->wind_count -1)) &&
(op_ret < local->readv_size)) {
/* refer to bug :p #536 on bugs.gluster.com */
main_local->readv_pendingsize =
(local->readv_size - op_ret);
} else {
main_local->replies[index].count = count;
main_local->replies[index].vector =
iov_dup (vector, count);
}
if (!main_local->iobref)
main_local->iobref = iobref_new ();
@ -2850,28 +2858,74 @@ stripe_readv_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
struct iobref *iobref = NULL;
op_ret = 0;
/* FIXME: notice that st_ino, and st_dev (gen) will be
* different than what inode will have. Make sure this doesn't
* cause any bugs at higher levels */
memcpy (&tmp_stbuf, &main_local->replies[0].stbuf,
sizeof (struct stat));
for (index=0; index < main_local->wind_count; index++) {
/* TODO: check whether each stripe returned 'expected'
* number of bytes
*/
/* check whether each stripe returned
* 'expected' number of bytes */
if (main_local->replies[index].op_ret == -1) {
op_ret = -1;
op_errno = main_local->replies[index].op_errno;
break;
}
op_ret += main_local->replies[index].op_ret;
final_count += main_local->replies[index].count;
/* TODO: Do I need to send anything more in stbuf? */
if (tmp_stbuf.st_size <
/* ANSWER-ME: Do we need to send anything more in stbuf?
*/
if (tmp_stbuf.st_size <
main_local->replies[index].stbuf.st_size) {
tmp_stbuf.st_size =
tmp_stbuf.st_size =
main_local->replies[index].stbuf.st_size;
}
/* TODO: Should I handle a case where there is a hole
* in a read request which spans across two nodes?
* for now, Solving bug(536) without addressing that
* case */
if ((index < (main_local->wind_count - 1)) &&
(main_local->replies[index+1].op_ret > 0) &&
(main_local->readv_pendingsize)) {
/* Fill in zeroes */
struct iovec *tmp_vec = NULL;
struct iobuf *iobuf = NULL;
int tmp_count = 0;
tmp_count = main_local->replies[index].count;
tmp_vec = CALLOC (1, ((tmp_count + 1) *
sizeof (struct iovec)));
memcpy (tmp_vec,
main_local->replies[index].vector,
sizeof (struct iovec) * tmp_count);
iobuf = iobuf_get (this->ctx->iobuf_pool);
if (!iobuf) {
gf_log (this->name, GF_LOG_ERROR,
"Out of memory.");
op_ret = -1;
op_errno = ENOMEM;
goto done;
}
memset (iobuf->ptr, 0,
main_local->readv_pendingsize);
iobref_add (main_local->iobref, iobuf);
tmp_vec[tmp_count].iov_base = iobuf->ptr;
tmp_vec[tmp_count].iov_len =
main_local->readv_pendingsize;
main_local->replies[index].count++;
main_local->replies[index].op_ret +=
main_local->readv_pendingsize;
FREE (main_local->replies[index].vector);
main_local->replies[index].vector = tmp_vec;
}
op_ret += main_local->replies[index].op_ret;
final_count += main_local->replies[index].count;
}
if (op_ret != -1) {
final_vec = CALLOC (final_count,
final_vec = CALLOC (final_count,
sizeof (struct iovec));
if (!final_vec) {
op_ret = -1;
@ -2988,6 +3042,7 @@ stripe_readv (call_frame_t *frame, xlator_t *this, fd_t *fd,
rlocal->node_index = index - off_index;
rlocal->orig_frame = frame;
rlocal->readv_size = frame_size;
rframe->local = rlocal;
idx = (index % fctx->stripe_count);
STACK_WIND (rframe, stripe_readv_cbk, fctx->xl_array[idx],

View File

@ -119,6 +119,8 @@ struct stripe_local {
int8_t failed;
int8_t unwind;
size_t readv_size;
int32_t readv_pendingsize;
int32_t entry_count;
int32_t node_index;
int32_t call_count;