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