summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tests/bugs/posix/bug-1651445.t1
-rw-r--r--xlators/storage/posix/src/posix-entry-ops.c1
-rw-r--r--xlators/storage/posix/src/posix-inode-fd-ops.c141
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 85bc7bb..aadc590 100644
--- a/xlators/storage/posix/src/posix-entry-ops.c
+++ b/xlators/storage/posix/src/posix-entry-ops.c
@@ -1632,7 +1632,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 e5c51ee..bd1279c 100644
--- a/xlators/storage/posix/src/posix-inode-fd-ops.c
+++ b/xlators/storage/posix/src/posix-inode-fd-ops.c
@@ -698,6 +698,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;
@@ -717,7 +721,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) {
@@ -741,7 +748,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) {
@@ -751,7 +758,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;
}
}
@@ -762,7 +769,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);
@@ -770,16 +777,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;
@@ -1089,25 +1127,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;
@@ -1872,19 +1942,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)",
@@ -2026,6 +2105,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);