d2787b
From adeec3d5d85baad8b50d203f34a47ad5360d7cd7 Mon Sep 17 00:00:00 2001
d2787b
From: karthik-us <ksubrahm@redhat.com>
d2787b
Date: Mon, 7 Jun 2021 18:36:11 +0530
d2787b
Subject: [PATCH 582/584] protocol/client: Fix lock memory leak
d2787b
d2787b
Problem-1:
d2787b
When an overlapping lock is issued the merged lock is not assigned the
d2787b
owner. When flush is issued on the fd, this particular lock is not freed
d2787b
leading to memory leak
d2787b
d2787b
Fix-1:
d2787b
Assign the owner while merging the locks.
d2787b
d2787b
Problem-2:
d2787b
On fd-destroy lock structs could be present in fdctx. For some reason
d2787b
with flock -x command and closing of the bash fd, it leads to this code
d2787b
path. Which leaks the lock structs.
d2787b
d2787b
Fix-2:
d2787b
When fdctx is being destroyed in client, make sure to cleanup any lock
d2787b
structs.
d2787b
d2787b
> Upstream patch: https://github.com/gluster/glusterfs/pull/2338/commits/926402f639471d2664bf00c6692221ba297c525f
d2787b
> fixes: gluster#2337
d2787b
> Change-Id: I298124213ce5a1cf2b1f1756d5e8a9745d9c0a1c
d2787b
> Signed-off-by: Pranith Kumar K <pranith.karampuri@phonepe.com>
d2787b
d2787b
BUG: 1689375
d2787b
Change-Id: I298124213ce5a1cf2b1f1756d5e8a9745d9c0a1c
d2787b
Signed-off-by: karthik-us <ksubrahm@redhat.com>
d2787b
Reviewed-on: https://code.engineering.redhat.com/gerrit/c/rhs-glusterfs/+/245603
d2787b
Tested-by: RHGS Build Bot <nigelb@redhat.com>
d2787b
Reviewed-by: Ravishankar Narayanankutty <ravishankar@redhat.com>
d2787b
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
d2787b
---
d2787b
 tests/bugs/client/issue-2337-lock-mem-leak.c | 52 ++++++++++++++++++
d2787b
 tests/bugs/client/issue-2337-lock-mem-leak.t | 42 ++++++++++++++
d2787b
 tests/bugs/replicate/do-not-reopen-fd.t      | 65 ++++++++++++++--------
d2787b
 tests/volume.rc                              |  8 +++
d2787b
 xlators/protocol/client/src/client-helpers.c | 10 ++++
d2787b
 xlators/protocol/client/src/client-lk.c      | 82 ++++++++++++++++++----------
d2787b
 xlators/protocol/client/src/client.h         |  8 ++-
d2787b
 7 files changed, 213 insertions(+), 54 deletions(-)
d2787b
 create mode 100644 tests/bugs/client/issue-2337-lock-mem-leak.c
d2787b
 create mode 100644 tests/bugs/client/issue-2337-lock-mem-leak.t
d2787b
d2787b
diff --git a/tests/bugs/client/issue-2337-lock-mem-leak.c b/tests/bugs/client/issue-2337-lock-mem-leak.c
d2787b
new file mode 100644
d2787b
index 0000000..d4e02a7
d2787b
--- /dev/null
d2787b
+++ b/tests/bugs/client/issue-2337-lock-mem-leak.c
d2787b
@@ -0,0 +1,52 @@
d2787b
+#include <sys/file.h>
d2787b
+#include <stdio.h>
d2787b
+#include <string.h>
d2787b
+#include <errno.h>
d2787b
+#include <sys/types.h>
d2787b
+#include <sys/stat.h>
d2787b
+#include <fcntl.h>
d2787b
+
d2787b
+int
d2787b
+main(int argc, char *argv[])
d2787b
+{
d2787b
+    int fd = -1;
d2787b
+    char *filename = NULL;
d2787b
+    struct flock lock = {
d2787b
+        0,
d2787b
+    };
d2787b
+    int i = 0;
d2787b
+    int ret = -1;
d2787b
+
d2787b
+    if (argc != 2) {
d2787b
+        fprintf(stderr, "Usage: %s <filename> ", argv[0]);
d2787b
+        goto out;
d2787b
+    }
d2787b
+
d2787b
+    filename = argv[1];
d2787b
+
d2787b
+    fd = open(filename, O_RDWR | O_CREAT, 0);
d2787b
+    if (fd < 0) {
d2787b
+        fprintf(stderr, "open (%s) failed (%s)\n", filename, strerror(errno));
d2787b
+        goto out;
d2787b
+    }
d2787b
+
d2787b
+    lock.l_type = F_WRLCK;
d2787b
+    lock.l_whence = SEEK_SET;
d2787b
+    lock.l_len = 2;
d2787b
+
d2787b
+    while (i < 100) {
d2787b
+        lock.l_start = i;
d2787b
+        ret = fcntl(fd, F_SETLK, &lock);
d2787b
+        if (ret < 0) {
d2787b
+            fprintf(stderr, "fcntl setlk failed (%s)\n", strerror(errno));
d2787b
+            goto out;
d2787b
+        }
d2787b
+
d2787b
+        i++;
d2787b
+    }
d2787b
+
d2787b
+    ret = 0;
d2787b
+
d2787b
+out:
d2787b
+    return ret;
d2787b
+}
d2787b
diff --git a/tests/bugs/client/issue-2337-lock-mem-leak.t b/tests/bugs/client/issue-2337-lock-mem-leak.t
d2787b
new file mode 100644
d2787b
index 0000000..64132a2
d2787b
--- /dev/null
d2787b
+++ b/tests/bugs/client/issue-2337-lock-mem-leak.t
d2787b
@@ -0,0 +1,42 @@
d2787b
+#!/bin/bash
d2787b
+
d2787b
+#Test that lock fop is not leaking any memory for overlapping regions
d2787b
+. $(dirname $0)/../../include.rc
d2787b
+. $(dirname $0)/../../volume.rc
d2787b
+. $(dirname $0)/../../fileio.rc
d2787b
+
d2787b
+cleanup;
d2787b
+
d2787b
+LOCK_TEST=$(dirname $0)/issue-2337-lock-mem-leak
d2787b
+build_tester $(dirname $0)/issue-2337-lock-mem-leak.c -o ${LOCK_TEST}
d2787b
+
d2787b
+TEST glusterd
d2787b
+TEST pidof glusterd
d2787b
+TEST $CLI volume create $V0 $H0:$B0/${V0}1
d2787b
+#Guard against flush-behind
d2787b
+TEST $CLI volume set $V0 performance.write-behind off
d2787b
+TEST $CLI volume start $V0
d2787b
+TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0
d2787b
+
d2787b
+TEST touch $M0/a
d2787b
+TEST fd1=`fd_available`
d2787b
+TEST fd_open $fd1 'w' $M0/a
d2787b
+TEST flock -x $fd1
d2787b
+statedump=$(generate_mount_statedump $V0 $M0)
d2787b
+EXPECT_NOT "^nostatedump$" echo $statedump
d2787b
+#Making sure no one changes this mem-tracker name
d2787b
+TEST grep gf_client_mt_clnt_lock_t $statedump
d2787b
+TEST fd_close $fd1
d2787b
+
d2787b
+statedump=$(generate_mount_statedump $V0 $M0)
d2787b
+EXPECT_NOT "^nostatedump$" echo $statedump
d2787b
+TEST ! grep gf_client_mt_clnt_lock_t $statedump
d2787b
+
d2787b
+TEST ${LOCK_TEST} $M0/a
d2787b
+
d2787b
+statedump=$(generate_mount_statedump $V0 $M0)
d2787b
+EXPECT_NOT "^nostatedump$" echo $statedump
d2787b
+TEST ! grep gf_client_mt_clnt_lock_t $statedump
d2787b
+TEST cleanup_mount_statedump $V0
d2787b
+TEST rm ${LOCK_TEST}
d2787b
+cleanup
d2787b
diff --git a/tests/bugs/replicate/do-not-reopen-fd.t b/tests/bugs/replicate/do-not-reopen-fd.t
d2787b
index 76d8e70..13b5218 100644
d2787b
--- a/tests/bugs/replicate/do-not-reopen-fd.t
d2787b
+++ b/tests/bugs/replicate/do-not-reopen-fd.t
d2787b
@@ -45,13 +45,17 @@ EXPECT "data-2" cat $B0/${V0}2/a
d2787b
 gfid_a=$(gf_get_gfid_xattr $B0/${V0}0/a)
d2787b
 gfid_str_a=$(gf_gfid_xattr_to_str $gfid_a)
d2787b
 
d2787b
-EXPECT "N" gf_check_file_opened_in_brick $V0 $H0 $B0/${V0}0 $gfid_str_a
d2787b
-EXPECT "Y" gf_check_file_opened_in_brick $V0 $H0 $B0/${V0}1 $gfid_str_a
d2787b
-EXPECT "Y" gf_check_file_opened_in_brick $V0 $H0 $B0/${V0}2 $gfid_str_a
d2787b
+EXPECT "^0$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}0 $gfid_str_a
d2787b
+EXPECT "^1$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}1 $gfid_str_a
d2787b
+EXPECT "^1$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}2 $gfid_str_a
d2787b
 
d2787b
 TEST fd2=`fd_available`
d2787b
 TEST fd_open $fd2 'rw' $M1/a
d2787b
 
d2787b
+EXPECT "^1$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}0 $gfid_str_a
d2787b
+EXPECT "^2$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}1 $gfid_str_a
d2787b
+EXPECT "^2$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}2 $gfid_str_a
d2787b
+
d2787b
 # Kill 2nd brick and try writing to the file. The write should fail due to
d2787b
 # quorum failure.
d2787b
 TEST kill_brick $V0 $H0 $B0/${V0}1
d2787b
@@ -66,6 +70,9 @@ EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^1$" brick_up_status $V0 $H0 $B0/${V0}1
d2787b
 EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status_meta $M0 $V0-replicate-0 1
d2787b
 TEST ! fd_write $fd1 "data-4"
d2787b
 TEST ! fd_cat $fd1
d2787b
+EXPECT "^1$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}0 $gfid_str_a
d2787b
+EXPECT "^1$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}1 $gfid_str_a
d2787b
+EXPECT "^2$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}2 $gfid_str_a
d2787b
 
d2787b
 # Enable heal and check the files will have same content on all the bricks after
d2787b
 # the heal is completed.
d2787b
@@ -89,7 +96,9 @@ TEST ! fd_write $fd1 "data-5"
d2787b
 
d2787b
 # At this point only one brick will have the lock. Try taking the lock again on
d2787b
 # the bad fd, which should also fail with EBADFD.
d2787b
-TEST ! flock -x $fd1
d2787b
+# TODO: At the moment quorum failure in lk leads to unlock on the bricks where
d2787b
+# lock succeeds. This will change lock state on 3rd brick, commenting for now
d2787b
+#TEST ! flock -x $fd1
d2787b
 
d2787b
 # Kill the only brick that is having lock and try taking lock on another client
d2787b
 # which should succeed.
d2787b
@@ -97,15 +106,25 @@ TEST kill_brick $V0 $H0 $B0/${V0}2
d2787b
 EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "0" afr_child_up_status_meta $M0 $V0-replicate-0 2
d2787b
 TEST flock -x $fd2
d2787b
 TEST fd_write $fd2 "data-6"
d2787b
+EXPECT "^1$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}0 $gfid_str_a
d2787b
+EXPECT "^1$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}1 $gfid_str_a
d2787b
+
d2787b
 
d2787b
 # Bring the brick up and try writing & reading on the old fd, which should still
d2787b
 # fail and operations on the 2nd fd should succeed.
d2787b
 TEST $CLI volume start $V0 force
d2787b
 EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^1$" brick_up_status $V0 $H0 $B0/${V0}2
d2787b
 EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status_meta $M0 $V0-replicate-0 2
d2787b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status_meta $M1 $V0-replicate-0 2
d2787b
+EXPECT "^1$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}0 $gfid_str_a
d2787b
+EXPECT "^1$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}1 $gfid_str_a
d2787b
+EXPECT "^1$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}2 $gfid_str_a
d2787b
 TEST ! fd_write $fd1 "data-7"
d2787b
 
d2787b
 TEST ! fd_cat $fd1
d2787b
+EXPECT "^1$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}0 $gfid_str_a
d2787b
+EXPECT "^1$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}1 $gfid_str_a
d2787b
+EXPECT "^1$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}2 $gfid_str_a
d2787b
 TEST fd_cat $fd2
d2787b
 
d2787b
 # Close both the fds which will release the locks and then re-open and take lock
d2787b
@@ -113,17 +132,15 @@ TEST fd_cat $fd2
d2787b
 TEST fd_close $fd1
d2787b
 TEST fd_close $fd2
d2787b
 
d2787b
-TEST ! ls /proc/$$/fd/$fd1
d2787b
-TEST ! ls /proc/$$/fd/$fd2
d2787b
-EXPECT_WITHIN $REOPEN_TIMEOUT "N" gf_check_file_opened_in_brick $V0 $H0 $B0/${V0}0 $gfid_str_a
d2787b
-EXPECT_WITHIN $REOPEN_TIMEOUT "N" gf_check_file_opened_in_brick $V0 $H0 $B0/${V0}1 $gfid_str_a
d2787b
-EXPECT_WITHIN $REOPEN_TIMEOUT "N" gf_check_file_opened_in_brick $V0 $H0 $B0/${V0}2 $gfid_str_a
d2787b
+EXPECT_WITHIN $REOPEN_TIMEOUT "^0$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}0 $gfid_str_a
d2787b
+EXPECT_WITHIN $REOPEN_TIMEOUT "^0$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}1 $gfid_str_a
d2787b
+EXPECT_WITHIN $REOPEN_TIMEOUT "^0$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}2 $gfid_str_a
d2787b
 
d2787b
 TEST fd1=`fd_available`
d2787b
 TEST fd_open $fd1 'rw' $M0/a
d2787b
-EXPECT_WITHIN $REOPEN_TIMEOUT "Y" gf_check_file_opened_in_brick $V0 $H0 $B0/${V0}0 $gfid_str_a
d2787b
-EXPECT_WITHIN $REOPEN_TIMEOUT "Y" gf_check_file_opened_in_brick $V0 $H0 $B0/${V0}1 $gfid_str_a
d2787b
-EXPECT_WITHIN $REOPEN_TIMEOUT "Y" gf_check_file_opened_in_brick $V0 $H0 $B0/${V0}2 $gfid_str_a
d2787b
+EXPECT_WITHIN $REOPEN_TIMEOUT "^1$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}0 $gfid_str_a
d2787b
+EXPECT_WITHIN $REOPEN_TIMEOUT "^1$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}1 $gfid_str_a
d2787b
+EXPECT_WITHIN $REOPEN_TIMEOUT "^1$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}2 $gfid_str_a
d2787b
 
d2787b
 TEST flock -x $fd1
d2787b
 TEST fd_write $fd1 "data-8"
d2787b
@@ -134,6 +151,10 @@ EXPECT "data-8" head -n 1 $B0/${V0}1/a
d2787b
 EXPECT "data-8" head -n 1 $B0/${V0}2/a
d2787b
 
d2787b
 TEST fd_close $fd1
d2787b
+EXPECT_WITHIN $REOPEN_TIMEOUT "^0$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}0 $gfid_str_a
d2787b
+EXPECT_WITHIN $REOPEN_TIMEOUT "^0$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}1 $gfid_str_a
d2787b
+EXPECT_WITHIN $REOPEN_TIMEOUT "^0$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}2 $gfid_str_a
d2787b
+
d2787b
 
d2787b
 # Heal the volume
d2787b
 TEST $CLI volume heal $V0 enable
d2787b
@@ -152,9 +173,9 @@ EXPECT_WITHIN $PROCESS_DOWN_TIMEOUT "0" afr_child_up_status_meta $M0 $V0-replica
d2787b
 TEST fd1=`fd_available`
d2787b
 TEST fd_open $fd1 'rw' $M0/a
d2787b
 
d2787b
-EXPECT "N" gf_check_file_opened_in_brick $V0 $H0 $B0/${V0}0 $gfid_str_a
d2787b
-EXPECT "Y" gf_check_file_opened_in_brick $V0 $H0 $B0/${V0}1 $gfid_str_a
d2787b
-EXPECT "Y" gf_check_file_opened_in_brick $V0 $H0 $B0/${V0}2 $gfid_str_a
d2787b
+EXPECT "^0$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}0 $gfid_str_a
d2787b
+EXPECT "^1$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}1 $gfid_str_a
d2787b
+EXPECT "^1$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}2 $gfid_str_a
d2787b
 
d2787b
 # Restart the brick and then write. Now fd should get re-opened and write should
d2787b
 # succeed on the previously down brick as well since there are no locks held on
d2787b
@@ -163,7 +184,7 @@ TEST $CLI volume start $V0 force
d2787b
 EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^1$" brick_up_status $V0 $H0 $B0/${V0}0
d2787b
 EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status_meta $M0 $V0-replicate-0 0
d2787b
 TEST fd_write $fd1 "data-10"
d2787b
-EXPECT "Y" gf_check_file_opened_in_brick $V0 $H0 $B0/${V0}0 $gfid_str_a
d2787b
+EXPECT "^1$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}0 $gfid_str_a
d2787b
 
d2787b
 EXPECT "data-10" head -n 1 $B0/${V0}0/a
d2787b
 EXPECT "data-10" head -n 1 $B0/${V0}1/a
d2787b
@@ -177,9 +198,9 @@ TEST fd1=`fd_available`
d2787b
 TEST fd_open $fd1 'rw' $M0/a
d2787b
 TEST flock -x $fd1
d2787b
 
d2787b
-EXPECT "N" gf_check_file_opened_in_brick $V0 $H0 $B0/${V0}0 $gfid_str_a
d2787b
-EXPECT "Y" gf_check_file_opened_in_brick $V0 $H0 $B0/${V0}1 $gfid_str_a
d2787b
-EXPECT "Y" gf_check_file_opened_in_brick $V0 $H0 $B0/${V0}2 $gfid_str_a
d2787b
+EXPECT "^0$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}0 $gfid_str_a
d2787b
+EXPECT "^1$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}1 $gfid_str_a
d2787b
+EXPECT "^1$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}2 $gfid_str_a
d2787b
 
d2787b
 # Kill & restart another brick so that it will return EBADFD
d2787b
 TEST kill_brick $V0 $H0 $B0/${V0}1
d2787b
@@ -194,9 +215,9 @@ EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^1$" brick_up_status $V0 $H0 $B0/${V0}1
d2787b
 EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status_meta $M0 $V0-replicate-0 0
d2787b
 EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status_meta $M0 $V0-replicate-0 1
d2787b
 TEST ! fd_write $fd1 "data-11"
d2787b
-EXPECT "N" gf_check_file_opened_in_brick $V0 $H0 $B0/${V0}0 $gfid_str_a
d2787b
-EXPECT "N" gf_check_file_opened_in_brick $V0 $H0 $B0/${V0}1 $gfid_str_a
d2787b
-EXPECT "Y" gf_check_file_opened_in_brick $V0 $H0 $B0/${V0}2 $gfid_str_a
d2787b
+EXPECT "^0$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}0 $gfid_str_a
d2787b
+EXPECT "^0$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}1 $gfid_str_a
d2787b
+EXPECT "^1$" gf_open_file_count_in_brick $V0 $H0 $B0/${V0}2 $gfid_str_a
d2787b
 
d2787b
 EXPECT "data-10" head -n 1 $B0/${V0}0/a
d2787b
 EXPECT "data-10" head -n 1 $B0/${V0}1/a
d2787b
diff --git a/tests/volume.rc b/tests/volume.rc
d2787b
index f5dd0b1..17c3835 100644
d2787b
--- a/tests/volume.rc
d2787b
+++ b/tests/volume.rc
d2787b
@@ -407,6 +407,14 @@ function gf_check_file_opened_in_brick {
d2787b
         fi
d2787b
 }
d2787b
 
d2787b
+function gf_open_file_count_in_brick {
d2787b
+        vol=$1
d2787b
+        host=$2
d2787b
+        brick=$3
d2787b
+        realpath=$4
d2787b
+        ls -l /proc/$(get_brick_pid $vol $host $brick)/fd | grep "${realpath}$" | wc -l
d2787b
+}
d2787b
+
d2787b
 function gf_get_gfid_backend_file_path {
d2787b
         brickpath=$1
d2787b
         filepath_in_brick=$2
d2787b
diff --git a/xlators/protocol/client/src/client-helpers.c b/xlators/protocol/client/src/client-helpers.c
d2787b
index 48b6448..a80f303 100644
d2787b
--- a/xlators/protocol/client/src/client-helpers.c
d2787b
+++ b/xlators/protocol/client/src/client-helpers.c
d2787b
@@ -3156,11 +3156,14 @@ client_fdctx_destroy(xlator_t *this, clnt_fd_ctx_t *fdctx)
d2787b
     int32_t ret = -1;
d2787b
     char parent_down = 0;
d2787b
     fd_lk_ctx_t *lk_ctx = NULL;
d2787b
+    gf_lkowner_t null_owner = {0};
d2787b
+    struct list_head deleted_list;
d2787b
 
d2787b
     GF_VALIDATE_OR_GOTO("client", this, out);
d2787b
     GF_VALIDATE_OR_GOTO(this->name, fdctx, out);
d2787b
 
d2787b
     conf = (clnt_conf_t *)this->private;
d2787b
+    INIT_LIST_HEAD(&deleted_list);
d2787b
 
d2787b
     if (fdctx->remote_fd == -1) {
d2787b
         gf_msg_debug(this->name, 0, "not a valid fd");
d2787b
@@ -3174,6 +3177,13 @@ client_fdctx_destroy(xlator_t *this, clnt_fd_ctx_t *fdctx)
d2787b
     pthread_mutex_unlock(&conf->lock);
d2787b
     lk_ctx = fdctx->lk_ctx;
d2787b
     fdctx->lk_ctx = NULL;
d2787b
+    pthread_spin_lock(&conf->fd_lock);
d2787b
+    {
d2787b
+        __delete_granted_locks_owner_from_fdctx(fdctx, &null_owner,
d2787b
+                                                &deleted_list);
d2787b
+    }
d2787b
+    pthread_spin_unlock(&conf->fd_lock);
d2787b
+    destroy_client_locks_from_list(&deleted_list);
d2787b
 
d2787b
     if (lk_ctx)
d2787b
         fd_lk_ctx_unref(lk_ctx);
d2787b
diff --git a/xlators/protocol/client/src/client-lk.c b/xlators/protocol/client/src/client-lk.c
d2787b
index c1fb055..cb4e894 100644
d2787b
--- a/xlators/protocol/client/src/client-lk.c
d2787b
+++ b/xlators/protocol/client/src/client-lk.c
d2787b
@@ -253,6 +253,7 @@ __insert_and_merge(clnt_fd_ctx_t *fdctx, client_posix_lock_t *lock)
d2787b
                 sum = add_locks(lock, conf);
d2787b
 
d2787b
                 sum->fd = lock->fd;
d2787b
+                sum->owner = conf->owner;
d2787b
 
d2787b
                 __delete_client_lock(conf);
d2787b
                 __destroy_client_lock(conf);
d2787b
@@ -320,56 +321,77 @@ destroy_client_lock(client_posix_lock_t *lock)
d2787b
     GF_FREE(lock);
d2787b
 }
d2787b
 
d2787b
-int32_t
d2787b
-delete_granted_locks_owner(fd_t *fd, gf_lkowner_t *owner)
d2787b
+void
d2787b
+destroy_client_locks_from_list(struct list_head *deleted)
d2787b
 {
d2787b
-    clnt_fd_ctx_t *fdctx = NULL;
d2787b
     client_posix_lock_t *lock = NULL;
d2787b
     client_posix_lock_t *tmp = NULL;
d2787b
-    xlator_t *this = NULL;
d2787b
-    clnt_conf_t *conf = NULL;
d2787b
-
d2787b
-    struct list_head delete_list;
d2787b
-    int ret = 0;
d2787b
+    xlator_t *this = THIS;
d2787b
     int count = 0;
d2787b
 
d2787b
-    INIT_LIST_HEAD(&delete_list);
d2787b
-    this = THIS;
d2787b
-    conf = this->private;
d2787b
+    list_for_each_entry_safe(lock, tmp, deleted, list)
d2787b
+    {
d2787b
+        list_del_init(&lock->list);
d2787b
+        destroy_client_lock(lock);
d2787b
+        count++;
d2787b
+    }
d2787b
 
d2787b
-    pthread_spin_lock(&conf->fd_lock);
d2787b
+    /* FIXME: Need to actually print the locks instead of count */
d2787b
+    gf_msg_trace(this->name, 0, "Number of locks cleared=%d", count);
d2787b
+}
d2787b
 
d2787b
-    fdctx = this_fd_get_ctx(fd, this);
d2787b
-    if (!fdctx) {
d2787b
-        pthread_spin_unlock(&conf->fd_lock);
d2787b
+void
d2787b
+__delete_granted_locks_owner_from_fdctx(clnt_fd_ctx_t *fdctx,
d2787b
+                                        gf_lkowner_t *owner,
d2787b
+                                        struct list_head *deleted)
d2787b
+{
d2787b
+    client_posix_lock_t *lock = NULL;
d2787b
+    client_posix_lock_t *tmp = NULL;
d2787b
 
d2787b
-        gf_msg(this->name, GF_LOG_WARNING, EINVAL, PC_MSG_FD_CTX_INVALID,
d2787b
-               "fdctx not valid");
d2787b
-        ret = -1;
d2787b
-        goto out;
d2787b
+    gf_boolean_t is_null_lkowner = _gf_false;
d2787b
+
d2787b
+    if (is_lk_owner_null(owner)) {
d2787b
+        is_null_lkowner = _gf_true;
d2787b
     }
d2787b
 
d2787b
     list_for_each_entry_safe(lock, tmp, &fdctx->lock_list, list)
d2787b
     {
d2787b
-        if (is_same_lkowner(&lock->owner, owner)) {
d2787b
+        if (is_null_lkowner || is_same_lkowner(&lock->owner, owner)) {
d2787b
             list_del_init(&lock->list);
d2787b
-            list_add_tail(&lock->list, &delete_list);
d2787b
-            count++;
d2787b
+            list_add_tail(&lock->list, deleted);
d2787b
         }
d2787b
     }
d2787b
+}
d2787b
 
d2787b
-    pthread_spin_unlock(&conf->fd_lock);
d2787b
+int32_t
d2787b
+delete_granted_locks_owner(fd_t *fd, gf_lkowner_t *owner)
d2787b
+{
d2787b
+    clnt_fd_ctx_t *fdctx = NULL;
d2787b
+    xlator_t *this = NULL;
d2787b
+    clnt_conf_t *conf = NULL;
d2787b
+    int ret = 0;
d2787b
+    struct list_head deleted_locks;
d2787b
 
d2787b
-    if (!list_empty(&delete_list)) {
d2787b
-        list_for_each_entry_safe(lock, tmp, &delete_list, list)
d2787b
-        {
d2787b
-            list_del_init(&lock->list);
d2787b
-            destroy_client_lock(lock);
d2787b
+    this = THIS;
d2787b
+    conf = this->private;
d2787b
+    INIT_LIST_HEAD(&deleted_locks);
d2787b
+
d2787b
+    pthread_spin_lock(&conf->fd_lock);
d2787b
+    {
d2787b
+        fdctx = this_fd_get_ctx(fd, this);
d2787b
+        if (!fdctx) {
d2787b
+            pthread_spin_unlock(&conf->fd_lock);
d2787b
+
d2787b
+            gf_smsg(this->name, GF_LOG_WARNING, EINVAL, PC_MSG_FD_CTX_INVALID,
d2787b
+                    NULL);
d2787b
+            ret = -1;
d2787b
+            goto out;
d2787b
         }
d2787b
+        __delete_granted_locks_owner_from_fdctx(fdctx, owner, &deleted_locks);
d2787b
     }
d2787b
+    pthread_spin_unlock(&conf->fd_lock);
d2787b
 
d2787b
-    /* FIXME: Need to actually print the locks instead of count */
d2787b
-    gf_msg_trace(this->name, 0, "Number of locks cleared=%d", count);
d2787b
+    destroy_client_locks_from_list(&deleted_locks);
d2787b
 
d2787b
 out:
d2787b
     return ret;
d2787b
diff --git a/xlators/protocol/client/src/client.h b/xlators/protocol/client/src/client.h
d2787b
index 2a50625..f952aea 100644
d2787b
--- a/xlators/protocol/client/src/client.h
d2787b
+++ b/xlators/protocol/client/src/client.h
d2787b
@@ -406,8 +406,12 @@ int
d2787b
 client_attempt_lock_recovery(xlator_t *this, clnt_fd_ctx_t *fdctx);
d2787b
 int32_t
d2787b
 delete_granted_locks_owner(fd_t *fd, gf_lkowner_t *owner);
d2787b
-int32_t
d2787b
-delete_granted_locks_fd(clnt_fd_ctx_t *fdctx);
d2787b
+void
d2787b
+__delete_granted_locks_owner_from_fdctx(clnt_fd_ctx_t *fdctx,
d2787b
+                                        gf_lkowner_t *owner,
d2787b
+                                        struct list_head *deleted);
d2787b
+void
d2787b
+destroy_client_locks_from_list(struct list_head *deleted);
d2787b
 int32_t
d2787b
 client_cmd_to_gf_cmd(int32_t cmd, int32_t *gf_cmd);
d2787b
 void
d2787b
-- 
d2787b
1.8.3.1
d2787b