|
|
d2787b |
From cb0d240004e6d40f8d7f30d177d5970ebc8e25fb Mon Sep 17 00:00:00 2001
|
|
|
d2787b |
From: Vinayak hariharmath <65405035+VHariharmath-rh@users.noreply.github.com>
|
|
|
d2787b |
Date: Wed, 3 Feb 2021 17:04:25 +0530
|
|
|
d2787b |
Subject: [PATCH 574/584] features/shard: delay unlink of a file that has
|
|
|
d2787b |
fd_count > 0
|
|
|
d2787b |
|
|
|
d2787b |
When there are multiple processes working on a file and if any
|
|
|
d2787b |
process unlinks that file then unlink operation shouldn't harm
|
|
|
d2787b |
other processes working on it. This is a posix a compliant
|
|
|
d2787b |
behavior and this should be supported when shard feature is
|
|
|
d2787b |
enabled also.
|
|
|
d2787b |
|
|
|
d2787b |
Problem description:
|
|
|
d2787b |
Let's consider 2 clients C1 and C2 working on a file F1 with 5
|
|
|
d2787b |
shards on gluster mount and gluster server has 4 bricks
|
|
|
d2787b |
B1, B2, B3, B4.
|
|
|
d2787b |
|
|
|
d2787b |
Assume that base file/shard is present on B1, 1st, 2nd shards
|
|
|
d2787b |
on B2, 3rd and 4th shards on B3 and 5th shard falls on B4 C1
|
|
|
d2787b |
has opened the F1 in append mode and is writing to it. The
|
|
|
d2787b |
write FOP goes to 5th shard in this case. So the
|
|
|
d2787b |
inode->fd_count = 1 on B1(base file) and B4 (5th shard).
|
|
|
d2787b |
|
|
|
d2787b |
C2 at the same time issued unlink to F1. On the server, the
|
|
|
d2787b |
base file has fd_count = 1 (since C1 has opened the file),
|
|
|
d2787b |
the base file is renamed under .glusterfs/unlink and
|
|
|
d2787b |
returned to C2. Then unlink will be sent to shards on all
|
|
|
d2787b |
bricks and shards on B2 and B3 will be deleted which have
|
|
|
d2787b |
no open reference yet. C1 starts getting errors while
|
|
|
d2787b |
accessing the remaining shards though it has open references
|
|
|
d2787b |
for the file.
|
|
|
d2787b |
|
|
|
d2787b |
This is one such undefined behavior. Likewise we will
|
|
|
d2787b |
encounter many such undefined behaviors as we dont have one
|
|
|
d2787b |
global lock to access all shards as one. Of Course having such
|
|
|
d2787b |
global lock will lead to performance hit as it reduces window
|
|
|
d2787b |
for parallel access of shards.
|
|
|
d2787b |
|
|
|
d2787b |
Solution:
|
|
|
d2787b |
The above undefined behavior can be addressed by delaying the
|
|
|
d2787b |
unlink of a file when there are open references on it.
|
|
|
d2787b |
File unlink happens in 2 steps.
|
|
|
d2787b |
step 1: client creates marker file under .shard/remove_me and
|
|
|
d2787b |
sends unlink on base file to the server
|
|
|
d2787b |
step 2: on return from the server, the associated shards will
|
|
|
d2787b |
be cleaned up and finally marker file will be removed.
|
|
|
d2787b |
|
|
|
d2787b |
In step 2, the back ground deletion process does nameless
|
|
|
d2787b |
lookup using marker file name (marker file is named after the
|
|
|
d2787b |
gfid of the base file) in glusterfs/unlink dir. If the nameless
|
|
|
d2787b |
look up is successful then that means the gfid still has open
|
|
|
d2787b |
fds and deletion of shards has to be delayed. If nameless
|
|
|
d2787b |
lookup fails then that indicates the gfid is unlinked and no
|
|
|
d2787b |
open fds on that file (the gfid path is unlinked during final
|
|
|
d2787b |
close on the file). The shards on which deletion is delayed
|
|
|
d2787b |
are unlinked one the all open fds are closed and this is
|
|
|
d2787b |
done through a thread which wakes up every 10 mins.
|
|
|
d2787b |
|
|
|
d2787b |
Also removed active_fd_count from inode structure and
|
|
|
d2787b |
referring fd_count wherever active_fd_count was used.
|
|
|
d2787b |
|
|
|
d2787b |
Backport of:
|
|
|
d2787b |
> Upstream-patch: https://github.com/gluster/glusterfs/pull/1563
|
|
|
d2787b |
> Fixes: #1358
|
|
|
d2787b |
> Change-Id: I8985093386e26215e0b0dce294c534a66f6ca11c
|
|
|
d2787b |
> Signed-off-by: Vinayakswami Hariharmath <vharihar@redhat.com>
|
|
|
d2787b |
|
|
|
d2787b |
BUG: 1782428
|
|
|
d2787b |
Change-Id: I8985093386e26215e0b0dce294c534a66f6ca11c
|
|
|
d2787b |
Signed-off-by: Vinayakswami Hariharmath <vharihar@redhat.com>
|
|
|
d2787b |
Reviewed-on: https://code.engineering.redhat.com/gerrit/c/rhs-glusterfs/+/244967
|
|
|
d2787b |
Tested-by: RHGS Build Bot <nigelb@redhat.com>
|
|
|
d2787b |
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
|
|
|
d2787b |
---
|
|
|
d2787b |
libglusterfs/src/glusterfs/glusterfs.h | 1 +
|
|
|
d2787b |
tests/bugs/shard/issue-1358.t | 100 +++++++++++++
|
|
|
d2787b |
tests/bugs/shard/unlinks-and-renames.t | 5 +
|
|
|
d2787b |
xlators/features/shard/src/shard.c | 199 ++++++++++++++++++++++++-
|
|
|
d2787b |
xlators/features/shard/src/shard.h | 11 ++
|
|
|
d2787b |
xlators/storage/posix/src/posix-entry-ops.c | 36 +++++
|
|
|
d2787b |
xlators/storage/posix/src/posix-inode-fd-ops.c | 64 +++++---
|
|
|
d2787b |
7 files changed, 391 insertions(+), 25 deletions(-)
|
|
|
d2787b |
create mode 100644 tests/bugs/shard/issue-1358.t
|
|
|
d2787b |
|
|
|
d2787b |
diff --git a/libglusterfs/src/glusterfs/glusterfs.h b/libglusterfs/src/glusterfs/glusterfs.h
|
|
|
d2787b |
index d3400bf..4401cf6 100644
|
|
|
d2787b |
--- a/libglusterfs/src/glusterfs/glusterfs.h
|
|
|
d2787b |
+++ b/libglusterfs/src/glusterfs/glusterfs.h
|
|
|
d2787b |
@@ -261,6 +261,7 @@ enum gf_internal_fop_indicator {
|
|
|
d2787b |
#define GF_XATTROP_PURGE_INDEX "glusterfs.xattrop-purge-index"
|
|
|
d2787b |
|
|
|
d2787b |
#define GF_GFIDLESS_LOOKUP "gfidless-lookup"
|
|
|
d2787b |
+#define GF_UNLINKED_LOOKUP "unlinked-lookup"
|
|
|
d2787b |
/* replace-brick and pump related internal xattrs */
|
|
|
d2787b |
#define RB_PUMP_CMD_START "glusterfs.pump.start"
|
|
|
d2787b |
#define RB_PUMP_CMD_PAUSE "glusterfs.pump.pause"
|
|
|
d2787b |
diff --git a/tests/bugs/shard/issue-1358.t b/tests/bugs/shard/issue-1358.t
|
|
|
d2787b |
new file mode 100644
|
|
|
d2787b |
index 0000000..1838e06
|
|
|
d2787b |
--- /dev/null
|
|
|
d2787b |
+++ b/tests/bugs/shard/issue-1358.t
|
|
|
d2787b |
@@ -0,0 +1,100 @@
|
|
|
d2787b |
+#!/bin/bash
|
|
|
d2787b |
+
|
|
|
d2787b |
+. $(dirname $0)/../../include.rc
|
|
|
d2787b |
+. $(dirname $0)/../../volume.rc
|
|
|
d2787b |
+
|
|
|
d2787b |
+cleanup;
|
|
|
d2787b |
+
|
|
|
d2787b |
+FILE_COUNT_TIME=5
|
|
|
d2787b |
+
|
|
|
d2787b |
+function get_file_count {
|
|
|
d2787b |
+ ls $1* | wc -l
|
|
|
d2787b |
+}
|
|
|
d2787b |
+
|
|
|
d2787b |
+TEST glusterd
|
|
|
d2787b |
+TEST pidof glusterd
|
|
|
d2787b |
+TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0,1}
|
|
|
d2787b |
+TEST $CLI volume set $V0 features.shard on
|
|
|
d2787b |
+TEST $CLI volume set $V0 features.shard-block-size 4MB
|
|
|
d2787b |
+TEST $CLI volume set $V0 performance.quick-read off
|
|
|
d2787b |
+TEST $CLI volume set $V0 performance.io-cache off
|
|
|
d2787b |
+TEST $CLI volume set $V0 performance.read-ahead off
|
|
|
d2787b |
+TEST $CLI volume set $V0 performance.write-behind off
|
|
|
d2787b |
+TEST $CLI volume start $V0
|
|
|
d2787b |
+
|
|
|
d2787b |
+TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0
|
|
|
d2787b |
+
|
|
|
d2787b |
+TEST mkdir $M0/dir
|
|
|
d2787b |
+TEST dd if=/dev/urandom of=$M0/dir/foo bs=4M count=5
|
|
|
d2787b |
+gfid_new=$(get_gfid_string $M0/dir/foo)
|
|
|
d2787b |
+
|
|
|
d2787b |
+# Ensure its shards dir is created now.
|
|
|
d2787b |
+TEST stat $B0/${V0}0/.shard/$gfid_new.1
|
|
|
d2787b |
+TEST stat $B0/${V0}1/.shard/$gfid_new.1
|
|
|
d2787b |
+TEST stat $B0/${V0}0/.shard/$gfid_new.2
|
|
|
d2787b |
+TEST stat $B0/${V0}1/.shard/$gfid_new.2
|
|
|
d2787b |
+
|
|
|
d2787b |
+# Open a file and store descriptor in fd = 5
|
|
|
d2787b |
+exec 5>$M0/dir/foo
|
|
|
d2787b |
+
|
|
|
d2787b |
+# Write something on the file using the open fd = 5
|
|
|
d2787b |
+echo "issue-1358" >&5
|
|
|
d2787b |
+
|
|
|
d2787b |
+# Write on the descriptor should be succesful
|
|
|
d2787b |
+EXPECT 0 echo $?
|
|
|
d2787b |
+
|
|
|
d2787b |
+# Unlink the same file which is opened in prev step
|
|
|
d2787b |
+TEST unlink $M0/dir/foo
|
|
|
d2787b |
+
|
|
|
d2787b |
+# Check the base file
|
|
|
d2787b |
+TEST ! stat $M0/dir/foo
|
|
|
d2787b |
+TEST ! stat $B0/${V0}0/foo
|
|
|
d2787b |
+TEST ! stat $B0/${V0}1/foo
|
|
|
d2787b |
+
|
|
|
d2787b |
+# Write something on the file using the open fd = 5
|
|
|
d2787b |
+echo "issue-1281" >&5
|
|
|
d2787b |
+
|
|
|
d2787b |
+# Write on the descriptor should be succesful
|
|
|
d2787b |
+EXPECT 0 echo $?
|
|
|
d2787b |
+
|
|
|
d2787b |
+# Check ".shard/.remove_me"
|
|
|
d2787b |
+EXPECT_WITHIN $FILE_COUNT_TIME 1 get_file_count $B0/${V0}0/.shard/.remove_me/$gfid_new
|
|
|
d2787b |
+EXPECT_WITHIN $FILE_COUNT_TIME 1 get_file_count $B0/${V0}1/.shard/.remove_me/$gfid_new
|
|
|
d2787b |
+
|
|
|
d2787b |
+# Close the fd = 5
|
|
|
d2787b |
+exec 5>&-
|
|
|
d2787b |
+
|
|
|
d2787b |
+###### To see the shards deleted, wait for 10 mins or repeat the same steps i.e open a file #####
|
|
|
d2787b |
+###### write something to it, unlink it and close it. This will wake up the thread that is ######
|
|
|
d2787b |
+###### responsible to delete the shards
|
|
|
d2787b |
+
|
|
|
d2787b |
+TEST touch $M0/dir/new
|
|
|
d2787b |
+exec 6>$M0/dir/new
|
|
|
d2787b |
+echo "issue-1358" >&6
|
|
|
d2787b |
+EXPECT 0 echo $?
|
|
|
d2787b |
+TEST unlink $M0/dir/new
|
|
|
d2787b |
+exec 6>&-
|
|
|
d2787b |
+
|
|
|
d2787b |
+# Now check the ".shard/remove_me" and the gfid will not be there
|
|
|
d2787b |
+EXPECT_WITHIN $FILE_COUNT_TIME 0 get_file_count $B0/${V0}0/.shard/.remove_me/$gfid_new
|
|
|
d2787b |
+EXPECT_WITHIN $FILE_COUNT_TIME 0 get_file_count $B0/${V0}1/.shard/.remove_me/$gfid_new
|
|
|
d2787b |
+
|
|
|
d2787b |
+# check for the absence of shards
|
|
|
d2787b |
+TEST ! stat $B0/${V0}0/.shard/$gfid_new.1
|
|
|
d2787b |
+TEST ! stat $B0/${V0}1/.shard/$gfid_new.1
|
|
|
d2787b |
+TEST ! stat $B0/${V0}0/.shard/$gfid_new.2
|
|
|
d2787b |
+TEST ! stat $B0/${V0}1/.shard/$gfid_new.2
|
|
|
d2787b |
+
|
|
|
d2787b |
+#### Create the file with same name and check creation and deletion works fine ######
|
|
|
d2787b |
+TEST dd if=/dev/urandom of=$M0/dir/foo bs=4M count=5
|
|
|
d2787b |
+gfid_new=$(get_gfid_string $M0/dir/foo)
|
|
|
d2787b |
+
|
|
|
d2787b |
+# Ensure its shards dir is created now.
|
|
|
d2787b |
+TEST stat $B0/${V0}0/.shard/$gfid_new.1
|
|
|
d2787b |
+TEST stat $B0/${V0}1/.shard/$gfid_new.1
|
|
|
d2787b |
+TEST stat $B0/${V0}0/.shard/$gfid_new.2
|
|
|
d2787b |
+TEST stat $B0/${V0}1/.shard/$gfid_new.2
|
|
|
d2787b |
+
|
|
|
d2787b |
+TEST unlink $M0/dir/foo
|
|
|
d2787b |
+cleanup
|
|
|
d2787b |
+
|
|
|
d2787b |
diff --git a/tests/bugs/shard/unlinks-and-renames.t b/tests/bugs/shard/unlinks-and-renames.t
|
|
|
d2787b |
index 990ca69..3280fcb 100644
|
|
|
d2787b |
--- a/tests/bugs/shard/unlinks-and-renames.t
|
|
|
d2787b |
+++ b/tests/bugs/shard/unlinks-and-renames.t
|
|
|
d2787b |
@@ -24,6 +24,11 @@ TEST pidof glusterd
|
|
|
d2787b |
TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0,1}
|
|
|
d2787b |
TEST $CLI volume set $V0 features.shard on
|
|
|
d2787b |
TEST $CLI volume set $V0 features.shard-block-size 4MB
|
|
|
d2787b |
+TEST $CLI volume set $V0 performance.quick-read off
|
|
|
d2787b |
+TEST $CLI volume set $V0 performance.io-cache off
|
|
|
d2787b |
+TEST $CLI volume set $V0 performance.read-ahead off
|
|
|
d2787b |
+TEST $CLI volume set $V0 performance.write-behind off
|
|
|
d2787b |
+
|
|
|
d2787b |
TEST $CLI volume start $V0
|
|
|
d2787b |
TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 $M0
|
|
|
d2787b |
|
|
|
d2787b |
diff --git a/xlators/features/shard/src/shard.c b/xlators/features/shard/src/shard.c
|
|
|
d2787b |
index 8d4a970..b828ff9 100644
|
|
|
d2787b |
--- a/xlators/features/shard/src/shard.c
|
|
|
d2787b |
+++ b/xlators/features/shard/src/shard.c
|
|
|
d2787b |
@@ -1242,7 +1242,8 @@ out:
|
|
|
d2787b |
|
|
|
d2787b |
static inode_t *
|
|
|
d2787b |
shard_link_internal_dir_inode(shard_local_t *local, inode_t *inode,
|
|
|
d2787b |
- struct iatt *buf, shard_internal_dir_type_t type)
|
|
|
d2787b |
+ xlator_t *this, struct iatt *buf,
|
|
|
d2787b |
+ shard_internal_dir_type_t type)
|
|
|
d2787b |
{
|
|
|
d2787b |
inode_t *linked_inode = NULL;
|
|
|
d2787b |
shard_priv_t *priv = NULL;
|
|
|
d2787b |
@@ -1250,7 +1251,7 @@ shard_link_internal_dir_inode(shard_local_t *local, inode_t *inode,
|
|
|
d2787b |
inode_t **priv_inode = NULL;
|
|
|
d2787b |
inode_t *parent = NULL;
|
|
|
d2787b |
|
|
|
d2787b |
- priv = THIS->private;
|
|
|
d2787b |
+ priv = this->private;
|
|
|
d2787b |
|
|
|
d2787b |
switch (type) {
|
|
|
d2787b |
case SHARD_INTERNAL_DIR_DOT_SHARD:
|
|
|
d2787b |
@@ -1294,7 +1295,7 @@ shard_refresh_internal_dir_cbk(call_frame_t *frame, void *cookie,
|
|
|
d2787b |
/* To-Do: Fix refcount increment per call to
|
|
|
d2787b |
* shard_link_internal_dir_inode().
|
|
|
d2787b |
*/
|
|
|
d2787b |
- linked_inode = shard_link_internal_dir_inode(local, inode, buf, type);
|
|
|
d2787b |
+ linked_inode = shard_link_internal_dir_inode(local, inode, this, buf, type);
|
|
|
d2787b |
shard_inode_ctx_mark_dir_refreshed(linked_inode, this);
|
|
|
d2787b |
out:
|
|
|
d2787b |
shard_common_resolve_shards(frame, this, local->post_res_handler);
|
|
|
d2787b |
@@ -1383,7 +1384,7 @@ shard_lookup_internal_dir_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
|
|
|
d2787b |
goto unwind;
|
|
|
d2787b |
}
|
|
|
d2787b |
|
|
|
d2787b |
- link_inode = shard_link_internal_dir_inode(local, inode, buf, type);
|
|
|
d2787b |
+ link_inode = shard_link_internal_dir_inode(local, inode, this, buf, type);
|
|
|
d2787b |
if (link_inode != inode) {
|
|
|
d2787b |
shard_refresh_internal_dir(frame, this, type);
|
|
|
d2787b |
} else {
|
|
|
d2787b |
@@ -3586,7 +3587,8 @@ shard_resolve_internal_dir(xlator_t *this, shard_local_t *local,
|
|
|
d2787b |
"Lookup on %s failed, exiting", bname);
|
|
|
d2787b |
goto err;
|
|
|
d2787b |
} else {
|
|
|
d2787b |
- shard_link_internal_dir_inode(local, loc->inode, &stbuf, type);
|
|
|
d2787b |
+ shard_link_internal_dir_inode(local, loc->inode, this, &stbuf,
|
|
|
d2787b |
+ type);
|
|
|
d2787b |
}
|
|
|
d2787b |
}
|
|
|
d2787b |
ret = 0;
|
|
|
d2787b |
@@ -3633,6 +3635,45 @@ err:
|
|
|
d2787b |
return ret;
|
|
|
d2787b |
}
|
|
|
d2787b |
|
|
|
d2787b |
+static int
|
|
|
d2787b |
+shard_nameless_lookup_base_file(xlator_t *this, char *gfid)
|
|
|
d2787b |
+{
|
|
|
d2787b |
+ int ret = 0;
|
|
|
d2787b |
+ loc_t loc = {
|
|
|
d2787b |
+ 0,
|
|
|
d2787b |
+ };
|
|
|
d2787b |
+ dict_t *xattr_req = dict_new();
|
|
|
d2787b |
+ if (!xattr_req) {
|
|
|
d2787b |
+ ret = -1;
|
|
|
d2787b |
+ goto out;
|
|
|
d2787b |
+ }
|
|
|
d2787b |
+
|
|
|
d2787b |
+ loc.inode = inode_new(this->itable);
|
|
|
d2787b |
+ if (loc.inode == NULL) {
|
|
|
d2787b |
+ ret = -1;
|
|
|
d2787b |
+ goto out;
|
|
|
d2787b |
+ }
|
|
|
d2787b |
+
|
|
|
d2787b |
+ ret = gf_uuid_parse(gfid, loc.gfid);
|
|
|
d2787b |
+ if (ret < 0)
|
|
|
d2787b |
+ goto out;
|
|
|
d2787b |
+
|
|
|
d2787b |
+ ret = dict_set_uint32(xattr_req, GF_UNLINKED_LOOKUP, 1);
|
|
|
d2787b |
+ if (ret < 0)
|
|
|
d2787b |
+ goto out;
|
|
|
d2787b |
+
|
|
|
d2787b |
+ ret = syncop_lookup(FIRST_CHILD(this), &loc, NULL, NULL, xattr_req, NULL);
|
|
|
d2787b |
+ if (ret < 0)
|
|
|
d2787b |
+ goto out;
|
|
|
d2787b |
+
|
|
|
d2787b |
+out:
|
|
|
d2787b |
+ if (xattr_req)
|
|
|
d2787b |
+ dict_unref(xattr_req);
|
|
|
d2787b |
+ loc_wipe(&loc;;
|
|
|
d2787b |
+
|
|
|
d2787b |
+ return ret;
|
|
|
d2787b |
+}
|
|
|
d2787b |
+
|
|
|
d2787b |
int
|
|
|
d2787b |
shard_delete_shards(void *opaque)
|
|
|
d2787b |
{
|
|
|
d2787b |
@@ -3734,6 +3775,11 @@ shard_delete_shards(void *opaque)
|
|
|
d2787b |
if (ret < 0)
|
|
|
d2787b |
continue;
|
|
|
d2787b |
}
|
|
|
d2787b |
+
|
|
|
d2787b |
+ ret = shard_nameless_lookup_base_file(this, entry->d_name);
|
|
|
d2787b |
+ if (!ret)
|
|
|
d2787b |
+ continue;
|
|
|
d2787b |
+
|
|
|
d2787b |
link_inode = inode_link(entry->inode, local->fd->inode,
|
|
|
d2787b |
entry->d_name, &entry->d_stat);
|
|
|
d2787b |
|
|
|
d2787b |
@@ -4105,6 +4151,9 @@ err:
|
|
|
d2787b |
int
|
|
|
d2787b |
shard_unlock_entrylk(call_frame_t *frame, xlator_t *this);
|
|
|
d2787b |
|
|
|
d2787b |
+static int
|
|
|
d2787b |
+shard_unlink_handler_spawn(xlator_t *this);
|
|
|
d2787b |
+
|
|
|
d2787b |
int
|
|
|
d2787b |
shard_unlink_base_file_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
|
|
|
d2787b |
int32_t op_ret, int32_t op_errno,
|
|
|
d2787b |
@@ -4126,7 +4175,7 @@ shard_unlink_base_file_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
|
|
|
d2787b |
if (xdata)
|
|
|
d2787b |
local->xattr_rsp = dict_ref(xdata);
|
|
|
d2787b |
if (local->cleanup_required)
|
|
|
d2787b |
- shard_start_background_deletion(this);
|
|
|
d2787b |
+ shard_unlink_handler_spawn(this);
|
|
|
d2787b |
}
|
|
|
d2787b |
|
|
|
d2787b |
if (local->entrylk_frame) {
|
|
|
d2787b |
@@ -5785,7 +5834,7 @@ shard_mkdir_internal_dir_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
|
|
|
d2787b |
}
|
|
|
d2787b |
}
|
|
|
d2787b |
|
|
|
d2787b |
- link_inode = shard_link_internal_dir_inode(local, inode, buf, type);
|
|
|
d2787b |
+ link_inode = shard_link_internal_dir_inode(local, inode, this, buf, type);
|
|
|
d2787b |
if (link_inode != inode) {
|
|
|
d2787b |
shard_refresh_internal_dir(frame, this, type);
|
|
|
d2787b |
} else {
|
|
|
d2787b |
@@ -7098,6 +7147,132 @@ shard_seek(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset,
|
|
|
d2787b |
return 0;
|
|
|
d2787b |
}
|
|
|
d2787b |
|
|
|
d2787b |
+static void
|
|
|
d2787b |
+shard_unlink_wait(shard_unlink_thread_t *ti)
|
|
|
d2787b |
+{
|
|
|
d2787b |
+ struct timespec wait_till = {
|
|
|
d2787b |
+ 0,
|
|
|
d2787b |
+ };
|
|
|
d2787b |
+
|
|
|
d2787b |
+ pthread_mutex_lock(&ti->mutex);
|
|
|
d2787b |
+ {
|
|
|
d2787b |
+ /* shard_unlink_handler() runs every 10 mins of interval */
|
|
|
d2787b |
+ wait_till.tv_sec = time(NULL) + 600;
|
|
|
d2787b |
+
|
|
|
d2787b |
+ while (!ti->rerun) {
|
|
|
d2787b |
+ if (pthread_cond_timedwait(&ti->cond, &ti->mutex, &wait_till) ==
|
|
|
d2787b |
+ ETIMEDOUT)
|
|
|
d2787b |
+ break;
|
|
|
d2787b |
+ }
|
|
|
d2787b |
+ ti->rerun = _gf_false;
|
|
|
d2787b |
+ }
|
|
|
d2787b |
+ pthread_mutex_unlock(&ti->mutex);
|
|
|
d2787b |
+}
|
|
|
d2787b |
+
|
|
|
d2787b |
+static void *
|
|
|
d2787b |
+shard_unlink_handler(void *data)
|
|
|
d2787b |
+{
|
|
|
d2787b |
+ shard_unlink_thread_t *ti = data;
|
|
|
d2787b |
+ xlator_t *this = ti->this;
|
|
|
d2787b |
+
|
|
|
d2787b |
+ THIS = this;
|
|
|
d2787b |
+
|
|
|
d2787b |
+ while (!ti->stop) {
|
|
|
d2787b |
+ shard_start_background_deletion(this);
|
|
|
d2787b |
+ shard_unlink_wait(ti);
|
|
|
d2787b |
+ }
|
|
|
d2787b |
+ return NULL;
|
|
|
d2787b |
+}
|
|
|
d2787b |
+
|
|
|
d2787b |
+static int
|
|
|
d2787b |
+shard_unlink_handler_spawn(xlator_t *this)
|
|
|
d2787b |
+{
|
|
|
d2787b |
+ int ret = 0;
|
|
|
d2787b |
+ shard_priv_t *priv = this->private;
|
|
|
d2787b |
+ shard_unlink_thread_t *ti = &priv->thread_info;
|
|
|
d2787b |
+
|
|
|
d2787b |
+ ti->this = this;
|
|
|
d2787b |
+
|
|
|
d2787b |
+ pthread_mutex_lock(&ti->mutex);
|
|
|
d2787b |
+ {
|
|
|
d2787b |
+ if (ti->running) {
|
|
|
d2787b |
+ pthread_cond_signal(&ti->cond);
|
|
|
d2787b |
+ } else {
|
|
|
d2787b |
+ ret = gf_thread_create(&ti->thread, NULL, shard_unlink_handler, ti,
|
|
|
d2787b |
+ "shard_unlink");
|
|
|
d2787b |
+ if (ret < 0) {
|
|
|
d2787b |
+ gf_log(this->name, GF_LOG_ERROR,
|
|
|
d2787b |
+ "Failed to create \"shard_unlink\" thread");
|
|
|
d2787b |
+ goto unlock;
|
|
|
d2787b |
+ }
|
|
|
d2787b |
+ ti->running = _gf_true;
|
|
|
d2787b |
+ }
|
|
|
d2787b |
+
|
|
|
d2787b |
+ ti->rerun = _gf_true;
|
|
|
d2787b |
+ }
|
|
|
d2787b |
+unlock:
|
|
|
d2787b |
+ pthread_mutex_unlock(&ti->mutex);
|
|
|
d2787b |
+ return ret;
|
|
|
d2787b |
+}
|
|
|
d2787b |
+
|
|
|
d2787b |
+static int
|
|
|
d2787b |
+shard_unlink_handler_init(shard_unlink_thread_t *ti)
|
|
|
d2787b |
+{
|
|
|
d2787b |
+ int ret = 0;
|
|
|
d2787b |
+ xlator_t *this = THIS;
|
|
|
d2787b |
+
|
|
|
d2787b |
+ ret = pthread_mutex_init(&ti->mutex, NULL);
|
|
|
d2787b |
+ if (ret) {
|
|
|
d2787b |
+ gf_log(this->name, GF_LOG_ERROR,
|
|
|
d2787b |
+ "Failed to init mutex for \"shard_unlink\" thread");
|
|
|
d2787b |
+ goto out;
|
|
|
d2787b |
+ }
|
|
|
d2787b |
+
|
|
|
d2787b |
+ ret = pthread_cond_init(&ti->cond, NULL);
|
|
|
d2787b |
+ if (ret) {
|
|
|
d2787b |
+ gf_log(this->name, GF_LOG_ERROR,
|
|
|
d2787b |
+ "Failed to init cond var for \"shard_unlink\" thread");
|
|
|
d2787b |
+ pthread_mutex_destroy(&ti->mutex);
|
|
|
d2787b |
+ goto out;
|
|
|
d2787b |
+ }
|
|
|
d2787b |
+
|
|
|
d2787b |
+ ti->running = _gf_false;
|
|
|
d2787b |
+ ti->rerun = _gf_false;
|
|
|
d2787b |
+ ti->stop = _gf_false;
|
|
|
d2787b |
+
|
|
|
d2787b |
+out:
|
|
|
d2787b |
+ return -ret;
|
|
|
d2787b |
+}
|
|
|
d2787b |
+
|
|
|
d2787b |
+static void
|
|
|
d2787b |
+shard_unlink_handler_fini(shard_unlink_thread_t *ti)
|
|
|
d2787b |
+{
|
|
|
d2787b |
+ int ret = 0;
|
|
|
d2787b |
+ xlator_t *this = THIS;
|
|
|
d2787b |
+ if (!ti)
|
|
|
d2787b |
+ return;
|
|
|
d2787b |
+
|
|
|
d2787b |
+ pthread_mutex_lock(&ti->mutex);
|
|
|
d2787b |
+ if (ti->running) {
|
|
|
d2787b |
+ ti->rerun = _gf_true;
|
|
|
d2787b |
+ ti->stop = _gf_true;
|
|
|
d2787b |
+ pthread_cond_signal(&ti->cond);
|
|
|
d2787b |
+ }
|
|
|
d2787b |
+ pthread_mutex_unlock(&ti->mutex);
|
|
|
d2787b |
+
|
|
|
d2787b |
+ if (ti->running) {
|
|
|
d2787b |
+ ret = pthread_join(ti->thread, NULL);
|
|
|
d2787b |
+ if (ret)
|
|
|
d2787b |
+ gf_msg(this->name, GF_LOG_WARNING, 0, 0,
|
|
|
d2787b |
+ "Failed to clean up shard unlink thread.");
|
|
|
d2787b |
+ ti->running = _gf_false;
|
|
|
d2787b |
+ }
|
|
|
d2787b |
+ ti->thread = 0;
|
|
|
d2787b |
+
|
|
|
d2787b |
+ pthread_cond_destroy(&ti->cond);
|
|
|
d2787b |
+ pthread_mutex_destroy(&ti->mutex);
|
|
|
d2787b |
+}
|
|
|
d2787b |
+
|
|
|
d2787b |
int32_t
|
|
|
d2787b |
mem_acct_init(xlator_t *this)
|
|
|
d2787b |
{
|
|
|
d2787b |
@@ -7164,6 +7339,14 @@ init(xlator_t *this)
|
|
|
d2787b |
this->private = priv;
|
|
|
d2787b |
LOCK_INIT(&priv->lock);
|
|
|
d2787b |
INIT_LIST_HEAD(&priv->ilist_head);
|
|
|
d2787b |
+
|
|
|
d2787b |
+ ret = shard_unlink_handler_init(&priv->thread_info);
|
|
|
d2787b |
+ if (ret) {
|
|
|
d2787b |
+ gf_log(this->name, GF_LOG_ERROR,
|
|
|
d2787b |
+ "Failed to initialize resources for \"shard_unlink\" thread");
|
|
|
d2787b |
+ goto out;
|
|
|
d2787b |
+ }
|
|
|
d2787b |
+
|
|
|
d2787b |
ret = 0;
|
|
|
d2787b |
out:
|
|
|
d2787b |
if (ret) {
|
|
|
d2787b |
@@ -7188,6 +7371,8 @@ fini(xlator_t *this)
|
|
|
d2787b |
if (!priv)
|
|
|
d2787b |
goto out;
|
|
|
d2787b |
|
|
|
d2787b |
+ shard_unlink_handler_fini(&priv->thread_info);
|
|
|
d2787b |
+
|
|
|
d2787b |
this->private = NULL;
|
|
|
d2787b |
LOCK_DESTROY(&priv->lock);
|
|
|
d2787b |
GF_FREE(priv);
|
|
|
d2787b |
diff --git a/xlators/features/shard/src/shard.h b/xlators/features/shard/src/shard.h
|
|
|
d2787b |
index 4fe181b..3dcb112 100644
|
|
|
d2787b |
--- a/xlators/features/shard/src/shard.h
|
|
|
d2787b |
+++ b/xlators/features/shard/src/shard.h
|
|
|
d2787b |
@@ -207,6 +207,16 @@ typedef enum {
|
|
|
d2787b |
|
|
|
d2787b |
/* rm = "remove me" */
|
|
|
d2787b |
|
|
|
d2787b |
+typedef struct shard_unlink_thread {
|
|
|
d2787b |
+ pthread_mutex_t mutex;
|
|
|
d2787b |
+ pthread_cond_t cond;
|
|
|
d2787b |
+ pthread_t thread;
|
|
|
d2787b |
+ gf_boolean_t running;
|
|
|
d2787b |
+ gf_boolean_t rerun;
|
|
|
d2787b |
+ gf_boolean_t stop;
|
|
|
d2787b |
+ xlator_t *this;
|
|
|
d2787b |
+} shard_unlink_thread_t;
|
|
|
d2787b |
+
|
|
|
d2787b |
typedef struct shard_priv {
|
|
|
d2787b |
uint64_t block_size;
|
|
|
d2787b |
uuid_t dot_shard_gfid;
|
|
|
d2787b |
@@ -220,6 +230,7 @@ typedef struct shard_priv {
|
|
|
d2787b |
shard_bg_deletion_state_t bg_del_state;
|
|
|
d2787b |
gf_boolean_t first_lookup_done;
|
|
|
d2787b |
uint64_t lru_limit;
|
|
|
d2787b |
+ shard_unlink_thread_t thread_info;
|
|
|
d2787b |
} shard_priv_t;
|
|
|
d2787b |
|
|
|
d2787b |
typedef struct {
|
|
|
d2787b |
diff --git a/xlators/storage/posix/src/posix-entry-ops.c b/xlators/storage/posix/src/posix-entry-ops.c
|
|
|
d2787b |
index b3a5381..1511e68 100644
|
|
|
d2787b |
--- a/xlators/storage/posix/src/posix-entry-ops.c
|
|
|
d2787b |
+++ b/xlators/storage/posix/src/posix-entry-ops.c
|
|
|
d2787b |
@@ -183,6 +183,11 @@ posix_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata)
|
|
|
d2787b |
struct posix_private *priv = NULL;
|
|
|
d2787b |
posix_inode_ctx_t *ctx = NULL;
|
|
|
d2787b |
int ret = 0;
|
|
|
d2787b |
+ uint32_t lookup_unlink_dir = 0;
|
|
|
d2787b |
+ char *unlink_path = NULL;
|
|
|
d2787b |
+ struct stat lstatbuf = {
|
|
|
d2787b |
+ 0,
|
|
|
d2787b |
+ };
|
|
|
d2787b |
|
|
|
d2787b |
VALIDATE_OR_GOTO(frame, out);
|
|
|
d2787b |
VALIDATE_OR_GOTO(this, out);
|
|
|
d2787b |
@@ -208,7 +213,36 @@ posix_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata)
|
|
|
d2787b |
op_ret = -1;
|
|
|
d2787b |
if (gf_uuid_is_null(loc->pargfid) || (loc->name == NULL)) {
|
|
|
d2787b |
/* nameless lookup */
|
|
|
d2787b |
+ op_ret = op_errno = errno = 0;
|
|
|
d2787b |
MAKE_INODE_HANDLE(real_path, this, loc, &buf;;
|
|
|
d2787b |
+
|
|
|
d2787b |
+ /* The gfid will be renamed to ".glusterfs/unlink" in case
|
|
|
d2787b |
+ * there are any open fds on the file in posix_unlink path.
|
|
|
d2787b |
+ * So client can request server to do nameless lookup with
|
|
|
d2787b |
+ * xdata = GF_UNLINKED_LOOKUP in ".glusterfs/unlink"
|
|
|
d2787b |
+ * dir if a client wants to know the status of the all open fds
|
|
|
d2787b |
+ * on the unlinked file. If the file still present in the
|
|
|
d2787b |
+ * ".glusterfs/unlink" dir then it indicates there still
|
|
|
d2787b |
+ * open fds present on the file and the file is still under
|
|
|
d2787b |
+ * unlink process */
|
|
|
d2787b |
+ if (op_ret < 0 && errno == ENOENT) {
|
|
|
d2787b |
+ ret = dict_get_uint32(xdata, GF_UNLINKED_LOOKUP,
|
|
|
d2787b |
+ &lookup_unlink_dir);
|
|
|
d2787b |
+ if (!ret && lookup_unlink_dir) {
|
|
|
d2787b |
+ op_ret = op_errno = errno = 0;
|
|
|
d2787b |
+ POSIX_GET_FILE_UNLINK_PATH(priv->base_path, loc->gfid,
|
|
|
d2787b |
+ unlink_path);
|
|
|
d2787b |
+ ret = sys_lstat(unlink_path, &lstatbuf);
|
|
|
d2787b |
+ if (ret) {
|
|
|
d2787b |
+ op_ret = -1;
|
|
|
d2787b |
+ op_errno = errno;
|
|
|
d2787b |
+ } else {
|
|
|
d2787b |
+ iatt_from_stat(&buf, &lstatbuf);
|
|
|
d2787b |
+ buf.ia_nlink = 0;
|
|
|
d2787b |
+ }
|
|
|
d2787b |
+ goto nameless_lookup_unlink_dir_out;
|
|
|
d2787b |
+ }
|
|
|
d2787b |
+ }
|
|
|
d2787b |
} else {
|
|
|
d2787b |
MAKE_ENTRY_HANDLE(real_path, par_path, this, loc, &buf;;
|
|
|
d2787b |
if (!real_path || !par_path) {
|
|
|
d2787b |
@@ -328,6 +362,8 @@ out:
|
|
|
d2787b |
|
|
|
d2787b |
if (op_ret == 0)
|
|
|
d2787b |
op_errno = 0;
|
|
|
d2787b |
+
|
|
|
d2787b |
+nameless_lookup_unlink_dir_out:
|
|
|
d2787b |
STACK_UNWIND_STRICT(lookup, frame, op_ret, op_errno,
|
|
|
d2787b |
(loc) ? loc->inode : NULL, &buf, xattr, &postparent);
|
|
|
d2787b |
|
|
|
d2787b |
diff --git a/xlators/storage/posix/src/posix-inode-fd-ops.c b/xlators/storage/posix/src/posix-inode-fd-ops.c
|
|
|
d2787b |
index 761e018..4c2983a 100644
|
|
|
d2787b |
--- a/xlators/storage/posix/src/posix-inode-fd-ops.c
|
|
|
d2787b |
+++ b/xlators/storage/posix/src/posix-inode-fd-ops.c
|
|
|
d2787b |
@@ -2504,6 +2504,39 @@ out:
|
|
|
d2787b |
return 0;
|
|
|
d2787b |
}
|
|
|
d2787b |
|
|
|
d2787b |
+static int
|
|
|
d2787b |
+posix_unlink_renamed_file(xlator_t *this, inode_t *inode)
|
|
|
d2787b |
+{
|
|
|
d2787b |
+ int ret = 0;
|
|
|
d2787b |
+ char *unlink_path = NULL;
|
|
|
d2787b |
+ uint64_t ctx_uint = 0;
|
|
|
d2787b |
+ posix_inode_ctx_t *ctx = NULL;
|
|
|
d2787b |
+ struct posix_private *priv = this->private;
|
|
|
d2787b |
+
|
|
|
d2787b |
+ ret = inode_ctx_get(inode, this, &ctx_uint);
|
|
|
d2787b |
+
|
|
|
d2787b |
+ if (ret < 0)
|
|
|
d2787b |
+ goto out;
|
|
|
d2787b |
+
|
|
|
d2787b |
+ ctx = (posix_inode_ctx_t *)(uintptr_t)ctx_uint;
|
|
|
d2787b |
+
|
|
|
d2787b |
+ if (ctx->unlink_flag == GF_UNLINK_TRUE) {
|
|
|
d2787b |
+ POSIX_GET_FILE_UNLINK_PATH(priv->base_path, inode->gfid, unlink_path);
|
|
|
d2787b |
+ if (!unlink_path) {
|
|
|
d2787b |
+ gf_msg(this->name, GF_LOG_ERROR, ENOMEM, P_MSG_UNLINK_FAILED,
|
|
|
d2787b |
+ "Failed to remove gfid :%s", uuid_utoa(inode->gfid));
|
|
|
d2787b |
+ ret = -1;
|
|
|
d2787b |
+ } else {
|
|
|
d2787b |
+ ret = sys_unlink(unlink_path);
|
|
|
d2787b |
+ if (!ret)
|
|
|
d2787b |
+ ctx->unlink_flag = GF_UNLINK_FALSE;
|
|
|
d2787b |
+ }
|
|
|
d2787b |
+ }
|
|
|
d2787b |
+
|
|
|
d2787b |
+out:
|
|
|
d2787b |
+ return ret;
|
|
|
d2787b |
+}
|
|
|
d2787b |
+
|
|
|
d2787b |
int32_t
|
|
|
d2787b |
posix_release(xlator_t *this, fd_t *fd)
|
|
|
d2787b |
{
|
|
|
d2787b |
@@ -2514,6 +2547,9 @@ posix_release(xlator_t *this, fd_t *fd)
|
|
|
d2787b |
VALIDATE_OR_GOTO(this, out);
|
|
|
d2787b |
VALIDATE_OR_GOTO(fd, out);
|
|
|
d2787b |
|
|
|
d2787b |
+ if (fd->inode->active_fd_count == 0)
|
|
|
d2787b |
+ posix_unlink_renamed_file(this, fd->inode);
|
|
|
d2787b |
+
|
|
|
d2787b |
ret = fd_ctx_del(fd, this, &tmp_pfd);
|
|
|
d2787b |
if (ret < 0) {
|
|
|
d2787b |
gf_msg(this->name, GF_LOG_WARNING, 0, P_MSG_PFD_NULL,
|
|
|
d2787b |
@@ -5881,41 +5917,33 @@ posix_forget(xlator_t *this, inode_t *inode)
|
|
|
d2787b |
uint64_t ctx_uint1 = 0;
|
|
|
d2787b |
uint64_t ctx_uint2 = 0;
|
|
|
d2787b |
posix_inode_ctx_t *ctx = NULL;
|
|
|
d2787b |
- posix_mdata_t *mdata = NULL;
|
|
|
d2787b |
- struct posix_private *priv_posix = NULL;
|
|
|
d2787b |
-
|
|
|
d2787b |
- priv_posix = (struct posix_private *)this->private;
|
|
|
d2787b |
- if (!priv_posix)
|
|
|
d2787b |
- return 0;
|
|
|
d2787b |
+ struct posix_private *priv = this->private;
|
|
|
d2787b |
|
|
|
d2787b |
ret = inode_ctx_del2(inode, this, &ctx_uint1, &ctx_uint2);
|
|
|
d2787b |
+
|
|
|
d2787b |
+ if (ctx_uint2)
|
|
|
d2787b |
+ GF_FREE((posix_mdata_t *)(uintptr_t)ctx_uint2);
|
|
|
d2787b |
+
|
|
|
d2787b |
if (!ctx_uint1)
|
|
|
d2787b |
- goto check_ctx2;
|
|
|
d2787b |
+ return 0;
|
|
|
d2787b |
|
|
|
d2787b |
ctx = (posix_inode_ctx_t *)(uintptr_t)ctx_uint1;
|
|
|
d2787b |
|
|
|
d2787b |
if (ctx->unlink_flag == GF_UNLINK_TRUE) {
|
|
|
d2787b |
- POSIX_GET_FILE_UNLINK_PATH(priv_posix->base_path, inode->gfid,
|
|
|
d2787b |
- unlink_path);
|
|
|
d2787b |
+ POSIX_GET_FILE_UNLINK_PATH(priv->base_path, inode->gfid, unlink_path);
|
|
|
d2787b |
if (!unlink_path) {
|
|
|
d2787b |
gf_msg(this->name, GF_LOG_ERROR, ENOMEM, P_MSG_UNLINK_FAILED,
|
|
|
d2787b |
"Failed to remove gfid :%s", uuid_utoa(inode->gfid));
|
|
|
d2787b |
ret = -1;
|
|
|
d2787b |
- goto ctx_free;
|
|
|
d2787b |
+ } else {
|
|
|
d2787b |
+ ret = sys_unlink(unlink_path);
|
|
|
d2787b |
}
|
|
|
d2787b |
- ret = sys_unlink(unlink_path);
|
|
|
d2787b |
}
|
|
|
d2787b |
-ctx_free:
|
|
|
d2787b |
+
|
|
|
d2787b |
pthread_mutex_destroy(&ctx->xattrop_lock);
|
|
|
d2787b |
pthread_mutex_destroy(&ctx->write_atomic_lock);
|
|
|
d2787b |
pthread_mutex_destroy(&ctx->pgfid_lock);
|
|
|
d2787b |
GF_FREE(ctx);
|
|
|
d2787b |
|
|
|
d2787b |
-check_ctx2:
|
|
|
d2787b |
- if (ctx_uint2) {
|
|
|
d2787b |
- mdata = (posix_mdata_t *)(uintptr_t)ctx_uint2;
|
|
|
d2787b |
- }
|
|
|
d2787b |
-
|
|
|
d2787b |
- GF_FREE(mdata);
|
|
|
d2787b |
return ret;
|
|
|
d2787b |
}
|
|
|
d2787b |
--
|
|
|
d2787b |
1.8.3.1
|
|
|
d2787b |
|