b7d4d7
From 211d0f7dbb4991b2191925973222ebc79f010e84 Mon Sep 17 00:00:00 2001
b7d4d7
From: Xavi Hernandez <xhernandez@redhat.com>
b7d4d7
Date: Sun, 8 Mar 2020 18:36:45 +0100
b7d4d7
Subject: [PATCH 521/526] open-behind: fix missing fd reference
b7d4d7
b7d4d7
Open behind was not keeping any reference on fd's pending to be
b7d4d7
opened. This makes it possible that a concurrent close and en entry
b7d4d7
fop (unlink, rename, ...) caused destruction of the fd while it
b7d4d7
was still being used.
b7d4d7
b7d4d7
Upstream patch:
b7d4d7
> Upstream patch link: https://review.gluster.org/c/glusterfs/+/24204
b7d4d7
> Change-Id: Ie9e992902cf2cd7be4af1f8b4e57af9bd6afd8e9
b7d4d7
> Fixes: bz#1810934
b7d4d7
> Signed-off-by: Xavi Hernandez <xhernandez@redhat.com>
b7d4d7
b7d4d7
Change-Id: Ie9e992902cf2cd7be4af1f8b4e57af9bd6afd8e9
b7d4d7
BUG: 1830713
b7d4d7
Signed-off-by: Xavi Hernandez <xhernandez@redhat.com>
b7d4d7
Reviewed-on: https://code.engineering.redhat.com/gerrit/224485
b7d4d7
Tested-by: RHGS Build Bot <nigelb@redhat.com>
b7d4d7
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
b7d4d7
---
b7d4d7
 xlators/performance/open-behind/src/open-behind.c | 27 ++++++++++++++---------
b7d4d7
 1 file changed, 16 insertions(+), 11 deletions(-)
b7d4d7
b7d4d7
diff --git a/xlators/performance/open-behind/src/open-behind.c b/xlators/performance/open-behind/src/open-behind.c
b7d4d7
index 3ee3c40..dd2f2fd 100644
b7d4d7
--- a/xlators/performance/open-behind/src/open-behind.c
b7d4d7
+++ b/xlators/performance/open-behind/src/open-behind.c
b7d4d7
@@ -206,8 +206,13 @@ ob_fd_free(ob_fd_t *ob_fd)
b7d4d7
     if (ob_fd->xdata)
b7d4d7
         dict_unref(ob_fd->xdata);
b7d4d7
 
b7d4d7
-    if (ob_fd->open_frame)
b7d4d7
+    if (ob_fd->open_frame) {
b7d4d7
+        /* If we sill have a frame it means that background open has never
b7d4d7
+         * been triggered. We need to release the pending reference. */
b7d4d7
+        fd_unref(ob_fd->fd);
b7d4d7
+
b7d4d7
         STACK_DESTROY(ob_fd->open_frame->root);
b7d4d7
+    }
b7d4d7
 
b7d4d7
     GF_FREE(ob_fd);
b7d4d7
 }
b7d4d7
@@ -297,6 +302,7 @@ ob_wake_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret,
b7d4d7
             call_resume(stub);
b7d4d7
     }
b7d4d7
 
b7d4d7
+    /* The background open is completed. We can release the 'fd' reference. */
b7d4d7
     fd_unref(fd);
b7d4d7
 
b7d4d7
     STACK_DESTROY(frame->root);
b7d4d7
@@ -331,7 +337,9 @@ ob_fd_wake(xlator_t *this, fd_t *fd, ob_fd_t *ob_fd)
b7d4d7
     }
b7d4d7
 
b7d4d7
     if (frame) {
b7d4d7
-        frame->local = fd_ref(fd);
b7d4d7
+        /* We don't need to take a reference here. We already have a reference
b7d4d7
+         * while the open is pending. */
b7d4d7
+        frame->local = fd;
b7d4d7
 
b7d4d7
         STACK_WIND(frame, ob_wake_cbk, FIRST_CHILD(this),
b7d4d7
                    FIRST_CHILD(this)->fops->open, &ob_fd->loc, ob_fd->flags, fd,
b7d4d7
@@ -345,15 +353,12 @@ void
b7d4d7
 ob_inode_wake(xlator_t *this, struct list_head *ob_fds)
b7d4d7
 {
b7d4d7
     ob_fd_t *ob_fd = NULL, *tmp = NULL;
b7d4d7
-    fd_t *fd = NULL;
b7d4d7
 
b7d4d7
     if (!list_empty(ob_fds)) {
b7d4d7
         list_for_each_entry_safe(ob_fd, tmp, ob_fds, ob_fds_on_inode)
b7d4d7
         {
b7d4d7
             ob_fd_wake(this, ob_fd->fd, ob_fd);
b7d4d7
-            fd = ob_fd->fd;
b7d4d7
             ob_fd_free(ob_fd);
b7d4d7
-            fd_unref(fd);
b7d4d7
         }
b7d4d7
     }
b7d4d7
 }
b7d4d7
@@ -365,7 +370,7 @@ ob_fd_copy(ob_fd_t *src, ob_fd_t *dst)
b7d4d7
     if (!src || !dst)
b7d4d7
         goto out;
b7d4d7
 
b7d4d7
-    dst->fd = __fd_ref(src->fd);
b7d4d7
+    dst->fd = src->fd;
b7d4d7
     dst->loc.inode = inode_ref(src->loc.inode);
b7d4d7
     gf_uuid_copy(dst->loc.gfid, src->loc.gfid);
b7d4d7
     dst->flags = src->flags;
b7d4d7
@@ -509,7 +514,6 @@ ob_open_behind(call_frame_t *frame, xlator_t *this, loc_t *loc, int flags,
b7d4d7
 
b7d4d7
     ob_fd->ob_inode = ob_inode;
b7d4d7
 
b7d4d7
-    /* don't do fd_ref, it'll cause leaks */
b7d4d7
     ob_fd->fd = fd;
b7d4d7
 
b7d4d7
     ob_fd->open_frame = copy_frame(frame);
b7d4d7
@@ -539,15 +543,16 @@ ob_open_behind(call_frame_t *frame, xlator_t *this, loc_t *loc, int flags,
b7d4d7
     }
b7d4d7
     UNLOCK(&fd->inode->lock);
b7d4d7
 
b7d4d7
-    if (!open_in_progress && !unlinked) {
b7d4d7
-        fd_ref(fd);
b7d4d7
+    /* We take a reference while the background open is pending or being
b7d4d7
+     * processed. If we finally wind the request in the foreground, then
b7d4d7
+     * ob_fd_free() will take care of this additional reference. */
b7d4d7
+    fd_ref(fd);
b7d4d7
 
b7d4d7
+    if (!open_in_progress && !unlinked) {
b7d4d7
         STACK_UNWIND_STRICT(open, frame, 0, 0, fd, xdata);
b7d4d7
 
b7d4d7
         if (!conf->lazy_open)
b7d4d7
             ob_fd_wake(this, fd, NULL);
b7d4d7
-
b7d4d7
-        fd_unref(fd);
b7d4d7
     } else {
b7d4d7
         ob_fd_free(ob_fd);
b7d4d7
         STACK_WIND(frame, default_open_cbk, FIRST_CHILD(this),
b7d4d7
-- 
b7d4d7
1.8.3.1
b7d4d7