From 0e453ede1f248a004965d0d368e2c4beb83f2ce1 Mon Sep 17 00:00:00 2001
From: Vinayakswami Hariharmath <vharihar@redhat.com>
Date: Mon, 25 Jan 2021 17:32:14 +0530
Subject: [PATCH 573/584] features/shard: unlink fails due to nospace to mknod
marker file
When we hit the max capacity of the storage space, shard_unlink()
starts failing if there is no space left on the brick to create a
marker file.
shard_unlink() happens in below steps:
1. create a marker file in the name of gfid of the base file under
BRICK_PATH/.shard/.remove_me
2. unlink the base file
3. shard_delete_shards() deletes the shards in background by
picking the entries in BRICK_PATH/.shard/.remove_me
If a marker file creation fails then we can't really delete the
shards which eventually a problem for user who is looking to make
space by deleting unwanted data.
Solution:
Create the marker file by marking xdata = GLUSTERFS_INTERNAL_FOP_KEY
which is considered to be internal op and allowed to create under
reserved space.
Backport of:
> Upstream-patch: https://github.com/gluster/glusterfs/pull/2057
> Fixes: #2038
> Change-Id: I7facebab940f9aeee81d489df429e00ef4fb7c5d
> Signed-off-by: Vinayakswami Hariharmath <vharihar@redhat.com>
BUG: 1891403
Change-Id: I7facebab940f9aeee81d489df429e00ef4fb7c5d
Signed-off-by: Vinayakswami Hariharmath <vharihar@redhat.com>
Reviewed-on: https://code.engineering.redhat.com/gerrit/c/rhs-glusterfs/+/244966
Tested-by: RHGS Build Bot <nigelb@redhat.com>
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
---
tests/bugs/shard/issue-2038.t | 56 ++++++++++++++++++++++++++++++++++++++
xlators/features/shard/src/shard.c | 20 ++++++++++++++
2 files changed, 76 insertions(+)
create mode 100644 tests/bugs/shard/issue-2038.t
diff --git a/tests/bugs/shard/issue-2038.t b/tests/bugs/shard/issue-2038.t
new file mode 100644
index 0000000..fc3e7f9
--- /dev/null
+++ b/tests/bugs/shard/issue-2038.t
@@ -0,0 +1,56 @@
+#!/bin/bash
+
+. $(dirname $0)/../../include.rc
+. $(dirname $0)/../../volume.rc
+. $(dirname $0)/../../snapshot.rc
+
+cleanup
+
+FILE_COUNT_TIME=5
+
+function get_file_count {
+ ls $1* | wc -l
+}
+
+TEST verify_lvm_version
+TEST glusterd
+TEST pidof glusterd
+TEST init_n_bricks 1
+TEST setup_lvm 1
+
+TEST $CLI volume create $V0 $H0:$L1
+TEST $CLI volume start $V0
+
+$CLI volume info
+
+TEST $CLI volume set $V0 features.shard on
+TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0
+
+#Setting the size in percentage
+TEST $CLI volume set $V0 storage.reserve 40
+
+#wait 5s to reset disk_space_full flag
+sleep 5
+
+TEST touch $M0/test
+TEST unlink $M0/test
+
+TEST dd if=/dev/zero of=$M0/a bs=80M count=1
+TEST dd if=/dev/zero of=$M0/b bs=10M count=1
+
+gfid_new=$(get_gfid_string $M0/a)
+
+# Wait 5s to update disk_space_full flag because thread check disk space
+# after every 5s
+
+sleep 5
+# setup_lvm create lvm partition of 150M and 40M are reserve so after
+# consuming more than 110M next unlink should not fail
+# Delete the base shard and check shards get cleaned up
+TEST unlink $M0/a
+TEST ! stat $M0/a
+
+TEST $CLI volume stop $V0
+TEST $CLI volume delete $V0
+
+cleanup
diff --git a/xlators/features/shard/src/shard.c b/xlators/features/shard/src/shard.c
index d1d7d7a..8d4a970 100644
--- a/xlators/features/shard/src/shard.c
+++ b/xlators/features/shard/src/shard.c
@@ -4078,6 +4078,16 @@ shard_create_marker_file_under_remove_me(call_frame_t *frame, xlator_t *this,
SHARD_INODE_CREATE_INIT(this, bs, xattr_req, &local->newloc,
local->prebuf.ia_size, 0, err);
+ /* Mark this as an internal operation, so that in case of disk full,
+ * the marker file will be created as part of reserve space */
+ ret = dict_set_int32_sizen(xattr_req, GLUSTERFS_INTERNAL_FOP_KEY, 1);
+ if (ret < 0) {
+ gf_msg(this->name, GF_LOG_WARNING, 0, SHARD_MSG_DICT_OP_FAILED,
+ "Failed to set key: %s on path %s", GLUSTERFS_INTERNAL_FOP_KEY,
+ local->newloc.path);
+ goto err;
+ }
+
STACK_WIND(frame, shard_create_marker_file_under_remove_me_cbk,
FIRST_CHILD(this), FIRST_CHILD(this)->fops->mknod,
&local->newloc, 0, 0, 0644, xattr_req);
@@ -5843,6 +5853,16 @@ shard_mkdir_internal_dir(call_frame_t *frame, xlator_t *this,
SHARD_SET_ROOT_FS_ID(frame, local);
+ /* Mark this as an internal operation, so that in case of disk full
+ * the internal dir will be created as part of reserve space */
+ ret = dict_set_int32_sizen(xattr_req, GLUSTERFS_INTERNAL_FOP_KEY, 1);
+ if (ret < 0) {
+ gf_msg(this->name, GF_LOG_WARNING, 0, SHARD_MSG_DICT_OP_FAILED,
+ "Failed to set key: %s on path %s", GLUSTERFS_INTERNAL_FOP_KEY,
+ loc->path);
+ goto err;
+ }
+
STACK_WIND_COOKIE(frame, shard_mkdir_internal_dir_cbk, (void *)(long)type,
FIRST_CHILD(this), FIRST_CHILD(this)->fops->mkdir, loc,
0755, 0, xattr_req);
--
1.8.3.1