You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
297 lines
10 KiB
297 lines
10 KiB
From 50318713486e79d9258cf22e656caff402256dde Mon Sep 17 00:00:00 2001 |
|
From: Mohit Agrawal <moagrawal@redhat.com> |
|
Date: Sun, 20 Oct 2019 22:01:01 +0530 |
|
Subject: [PATCH 389/449] posix: Avoid diskpace error in case of overwriting |
|
the data |
|
|
|
Problem: Sometime fops like posix_writev, posix_fallocate, posix_zerofile |
|
failed and throw error ENOSPC if storage.reserve threshold limit |
|
has reached even fops is overwriting the data |
|
|
|
Solution: Retry the fops in case of overwrite if diskspace check |
|
is failed |
|
|
|
> Credits: kinsu <vpolakis@gmail.com> |
|
> Change-Id: I987d73bcf47ed1bb27878df40c39751296e95fe8 |
|
> Updates: #745 |
|
> Signed-off-by: Mohit Agrawal <moagrawa@redhat.com> |
|
> (Cherry pick from commit ca3e5905ac02fb9c373ac3de10b44f061d04cd6f) |
|
> (Reviewed on upstream link https://review.gluster.org/#/c/glusterfs/+/23572/) |
|
|
|
Change-Id: I987d73bcf47ed1bb27878df40c39751296e95fe8 |
|
BUG: 1787331 |
|
Signed-off-by: Mohit Agrawal <moagrawa@redhat.com> |
|
Reviewed-on: https://code.engineering.redhat.com/gerrit/202307 |
|
Tested-by: RHGS Build Bot <nigelb@redhat.com> |
|
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com> |
|
--- |
|
tests/bugs/posix/bug-1651445.t | 1 + |
|
xlators/storage/posix/src/posix-entry-ops.c | 1 - |
|
xlators/storage/posix/src/posix-inode-fd-ops.c | 141 ++++++++++++++++++++++--- |
|
3 files changed, 126 insertions(+), 17 deletions(-) |
|
|
|
diff --git a/tests/bugs/posix/bug-1651445.t b/tests/bugs/posix/bug-1651445.t |
|
index 5248d47..4d08b69 100644 |
|
--- a/tests/bugs/posix/bug-1651445.t |
|
+++ b/tests/bugs/posix/bug-1651445.t |
|
@@ -33,6 +33,7 @@ sleep 5 |
|
# setup_lvm create lvm partition of 150M and 40M are reserve so after |
|
# consuming more than 110M next dd should fail |
|
TEST ! dd if=/dev/zero of=$M0/c bs=5M count=1 |
|
+TEST dd if=/dev/urandom of=$M0/a bs=1022 count=1 oflag=seek_bytes,sync seek=102 conv=notrunc |
|
|
|
rm -rf $M0/* |
|
|
|
diff --git a/xlators/storage/posix/src/posix-entry-ops.c b/xlators/storage/posix/src/posix-entry-ops.c |
|
index 283b305..bea0bbf 100644 |
|
--- a/xlators/storage/posix/src/posix-entry-ops.c |
|
+++ b/xlators/storage/posix/src/posix-entry-ops.c |
|
@@ -1634,7 +1634,6 @@ posix_rename(call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, |
|
|
|
priv = this->private; |
|
VALIDATE_OR_GOTO(priv, out); |
|
- DISK_SPACE_CHECK_AND_GOTO(frame, priv, xdata, op_ret, op_errno, out); |
|
|
|
SET_FS_ID(frame->root->uid, frame->root->gid); |
|
MAKE_ENTRY_HANDLE(real_oldpath, par_oldpath, this, oldloc, NULL); |
|
diff --git a/xlators/storage/posix/src/posix-inode-fd-ops.c b/xlators/storage/posix/src/posix-inode-fd-ops.c |
|
index a2a518f..bcce06e 100644 |
|
--- a/xlators/storage/posix/src/posix-inode-fd-ops.c |
|
+++ b/xlators/storage/posix/src/posix-inode-fd-ops.c |
|
@@ -692,6 +692,10 @@ posix_do_fallocate(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t flags, |
|
gf_boolean_t locked = _gf_false; |
|
posix_inode_ctx_t *ctx = NULL; |
|
struct posix_private *priv = NULL; |
|
+ gf_boolean_t check_space_error = _gf_false; |
|
+ struct stat statbuf = { |
|
+ 0, |
|
+ }; |
|
|
|
DECLARE_OLD_FS_ID_VAR; |
|
|
|
@@ -711,7 +715,10 @@ posix_do_fallocate(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t flags, |
|
if (priv->disk_reserve) |
|
posix_disk_space_check(this); |
|
|
|
- DISK_SPACE_CHECK_AND_GOTO(frame, priv, xdata, ret, ret, out); |
|
+ DISK_SPACE_CHECK_AND_GOTO(frame, priv, xdata, ret, ret, unlock); |
|
+ |
|
+overwrite: |
|
+ check_space_error = _gf_true; |
|
|
|
ret = posix_fd_ctx_get(fd, this, &pfd, &op_errno); |
|
if (ret < 0) { |
|
@@ -735,7 +742,7 @@ posix_do_fallocate(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t flags, |
|
ret = -errno; |
|
gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_FSTAT_FAILED, |
|
"fallocate (fstat) failed on fd=%p", fd); |
|
- goto out; |
|
+ goto unlock; |
|
} |
|
|
|
if (xdata) { |
|
@@ -745,7 +752,7 @@ posix_do_fallocate(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t flags, |
|
gf_msg(this->name, GF_LOG_ERROR, 0, 0, |
|
"file state check failed, fd %p", fd); |
|
ret = -EIO; |
|
- goto out; |
|
+ goto unlock; |
|
} |
|
} |
|
|
|
@@ -756,7 +763,7 @@ posix_do_fallocate(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t flags, |
|
"fallocate failed on %s offset: %jd, " |
|
"len:%zu, flags: %d", |
|
uuid_utoa(fd->inode->gfid), offset, len, flags); |
|
- goto out; |
|
+ goto unlock; |
|
} |
|
|
|
ret = posix_fdstat(this, fd->inode, pfd->fd, statpost); |
|
@@ -764,16 +771,47 @@ posix_do_fallocate(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t flags, |
|
ret = -errno; |
|
gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_FSTAT_FAILED, |
|
"fallocate (fstat) failed on fd=%p", fd); |
|
- goto out; |
|
+ goto unlock; |
|
} |
|
|
|
posix_set_ctime(frame, this, NULL, pfd->fd, fd->inode, statpost); |
|
|
|
-out: |
|
+unlock: |
|
if (locked) { |
|
pthread_mutex_unlock(&ctx->write_atomic_lock); |
|
locked = _gf_false; |
|
} |
|
+ |
|
+ if (op_errno == ENOSPC && priv->disk_space_full && !check_space_error) { |
|
+#ifdef FALLOC_FL_KEEP_SIZE |
|
+ if (flags & FALLOC_FL_KEEP_SIZE) { |
|
+ goto overwrite; |
|
+ } |
|
+#endif |
|
+ ret = posix_fd_ctx_get(fd, this, &pfd, &op_errno); |
|
+ if (ret < 0) { |
|
+ gf_msg(this->name, GF_LOG_WARNING, ret, P_MSG_PFD_NULL, |
|
+ "pfd is NULL from fd=%p", fd); |
|
+ goto out; |
|
+ } |
|
+ |
|
+ if (sys_fstat(pfd->fd, &statbuf) < 0) { |
|
+ gf_msg(this->name, GF_LOG_WARNING, op_errno, P_MSG_FILE_OP_FAILED, |
|
+ "%d", pfd->fd); |
|
+ goto out; |
|
+ } |
|
+ |
|
+ if (offset + len <= statbuf.st_size) { |
|
+ gf_msg_debug(this->name, 0, |
|
+ "io vector size will not" |
|
+ " change disk size so allow overwrite for" |
|
+ " fd %d", |
|
+ pfd->fd); |
|
+ goto overwrite; |
|
+ } |
|
+ } |
|
+ |
|
+out: |
|
SET_TO_OLD_FS_ID(); |
|
if (ret == ENOSPC) |
|
ret = -ENOSPC; |
|
@@ -1083,25 +1121,57 @@ posix_zerofill(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, |
|
int op_ret = -1; |
|
int op_errno = EINVAL; |
|
dict_t *rsp_xdata = NULL; |
|
+ gf_boolean_t check_space_error = _gf_false; |
|
+ struct posix_fd *pfd = NULL; |
|
+ struct stat statbuf = { |
|
+ 0, |
|
+ }; |
|
|
|
- VALIDATE_OR_GOTO(frame, out); |
|
- VALIDATE_OR_GOTO(this, out); |
|
+ VALIDATE_OR_GOTO(frame, unwind); |
|
+ VALIDATE_OR_GOTO(this, unwind); |
|
|
|
priv = this->private; |
|
DISK_SPACE_CHECK_AND_GOTO(frame, priv, xdata, op_ret, op_errno, out); |
|
|
|
+overwrite: |
|
+ check_space_error = _gf_true; |
|
ret = posix_do_zerofill(frame, this, fd, offset, len, &statpre, &statpost, |
|
xdata, &rsp_xdata); |
|
if (ret < 0) { |
|
op_ret = -1; |
|
op_errno = -ret; |
|
- goto out; |
|
+ goto unwind; |
|
} |
|
|
|
STACK_UNWIND_STRICT(zerofill, frame, 0, 0, &statpre, &statpost, rsp_xdata); |
|
return 0; |
|
|
|
out: |
|
+ if (op_errno == ENOSPC && priv->disk_space_full && !check_space_error) { |
|
+ ret = posix_fd_ctx_get(fd, this, &pfd, &op_errno); |
|
+ if (ret < 0) { |
|
+ gf_msg(this->name, GF_LOG_WARNING, ret, P_MSG_PFD_NULL, |
|
+ "pfd is NULL from fd=%p", fd); |
|
+ goto out; |
|
+ } |
|
+ |
|
+ if (sys_fstat(pfd->fd, &statbuf) < 0) { |
|
+ gf_msg(this->name, GF_LOG_WARNING, op_errno, P_MSG_FILE_OP_FAILED, |
|
+ "%d", pfd->fd); |
|
+ goto out; |
|
+ } |
|
+ |
|
+ if (offset + len <= statbuf.st_size) { |
|
+ gf_msg_debug(this->name, 0, |
|
+ "io vector size will not" |
|
+ " change disk size so allow overwrite for" |
|
+ " fd %d", |
|
+ pfd->fd); |
|
+ goto overwrite; |
|
+ } |
|
+ } |
|
+ |
|
+unwind: |
|
STACK_UNWIND_STRICT(zerofill, frame, op_ret, op_errno, NULL, NULL, |
|
rsp_xdata); |
|
return 0; |
|
@@ -1857,19 +1927,28 @@ posix_writev(call_frame_t *frame, xlator_t *this, fd_t *fd, |
|
gf_boolean_t write_append = _gf_false; |
|
gf_boolean_t update_atomic = _gf_false; |
|
posix_inode_ctx_t *ctx = NULL; |
|
+ gf_boolean_t check_space_error = _gf_false; |
|
+ struct stat statbuf = { |
|
+ 0, |
|
+ }; |
|
+ int totlen = 0; |
|
+ int idx = 0; |
|
|
|
- VALIDATE_OR_GOTO(frame, out); |
|
- VALIDATE_OR_GOTO(this, out); |
|
- VALIDATE_OR_GOTO(fd, out); |
|
- VALIDATE_OR_GOTO(fd->inode, out); |
|
- VALIDATE_OR_GOTO(vector, out); |
|
- VALIDATE_OR_GOTO(this->private, out); |
|
+ VALIDATE_OR_GOTO(frame, unwind); |
|
+ VALIDATE_OR_GOTO(this, unwind); |
|
+ VALIDATE_OR_GOTO(fd, unwind); |
|
+ VALIDATE_OR_GOTO(fd->inode, unwind); |
|
+ VALIDATE_OR_GOTO(vector, unwind); |
|
+ VALIDATE_OR_GOTO(this->private, unwind); |
|
|
|
priv = this->private; |
|
|
|
- VALIDATE_OR_GOTO(priv, out); |
|
+ VALIDATE_OR_GOTO(priv, unwind); |
|
DISK_SPACE_CHECK_AND_GOTO(frame, priv, xdata, op_ret, op_errno, out); |
|
|
|
+overwrite: |
|
+ |
|
+ check_space_error = _gf_true; |
|
if ((fd->inode->ia_type == IA_IFBLK) || (fd->inode->ia_type == IA_IFCHR)) { |
|
gf_msg(this->name, GF_LOG_ERROR, EINVAL, P_MSG_INVALID_ARGUMENT, |
|
"writev received on a block/char file (%s)", |
|
@@ -2011,6 +2090,36 @@ out: |
|
locked = _gf_false; |
|
} |
|
|
|
+ if (op_errno == ENOSPC && priv->disk_space_full && !check_space_error) { |
|
+ ret = posix_fd_ctx_get(fd, this, &pfd, &op_errno); |
|
+ if (ret < 0) { |
|
+ gf_msg(this->name, GF_LOG_WARNING, ret, P_MSG_PFD_NULL, |
|
+ "pfd is NULL from fd=%p", fd); |
|
+ goto unwind; |
|
+ } |
|
+ |
|
+ if (sys_fstat(pfd->fd, &statbuf) < 0) { |
|
+ gf_msg(this->name, GF_LOG_WARNING, op_errno, P_MSG_FILE_OP_FAILED, |
|
+ "%d", pfd->fd); |
|
+ goto unwind; |
|
+ } |
|
+ |
|
+ for (idx = 0; idx < count; idx++) { |
|
+ totlen = vector[idx].iov_len; |
|
+ } |
|
+ |
|
+ if ((offset + totlen <= statbuf.st_size) && |
|
+ !(statbuf.st_blocks * statbuf.st_blksize < statbuf.st_size)) { |
|
+ gf_msg_debug(this->name, 0, |
|
+ "io vector size will not" |
|
+ " change disk size so allow overwrite for" |
|
+ " fd %d", |
|
+ pfd->fd); |
|
+ goto overwrite; |
|
+ } |
|
+ } |
|
+ |
|
+unwind: |
|
STACK_UNWIND_STRICT(writev, frame, op_ret, op_errno, &preop, &postop, |
|
rsp_xdata); |
|
|
|
-- |
|
1.8.3.1 |
|
|
|
|