From 0e453ede1f248a004965d0d368e2c4beb83f2ce1 Mon Sep 17 00:00:00 2001 From: Vinayakswami Hariharmath 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 BUG: 1891403 Change-Id: I7facebab940f9aeee81d489df429e00ef4fb7c5d Signed-off-by: Vinayakswami Hariharmath Reviewed-on: https://code.engineering.redhat.com/gerrit/c/rhs-glusterfs/+/244966 Tested-by: RHGS Build Bot Reviewed-by: Sunil Kumar Heggodu Gopala Acharya --- 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