summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Spisla <david.spisla@iternity.com>2020-02-25 10:57:36 +0100
committerAmar Tumballi <amar@kadalu.io>2020-03-17 04:24:14 +0000
commit476139c962c298b2d00a3d42b90632fc25401526 (patch)
treebf4ee55352605542e1d9a646844e90945bc01ab6
parentb30f76980fc5d01b569d9409b68d24d809444ff8 (diff)
WORM-Xlator: Initial write of a file succeeds if auto-commit-period 0
If worm-file-level enabled and auto-commit-period 0 an initial write of a file (e.g. $ echo test >> file1.txt) would lead to an zero byte file because the WORM xlator immediately WORMed the file when it was created. To avoid this we move the setting of trusted.worm_file from worm_create_cbk to worm_release . This means that this xattr will set when the filehandle is closed and all initial WRITE FOPs succeed. Finally we also perform gf_worm_state_transition in worm_release to ensure that the file will be immediately WORMed after the file handle was closed. Change-Id: I5d02e18975b646ca1a27ed41d836e9d0dc333204 Fixes: bz#1808421 Signed-off-by: David Spisla <david.spisla@iternity.com>
-rwxr-xr-xtests/features/worm.t8
-rw-r--r--xlators/features/read-only/src/worm.c77
2 files changed, 68 insertions, 17 deletions
diff --git a/tests/features/worm.t b/tests/features/worm.t
index 8b2574c8a47..168d326571b 100755
--- a/tests/features/worm.t
+++ b/tests/features/worm.t
@@ -72,6 +72,14 @@ sleep 10
TEST `echo "worm 1" >> $M0/file4`
TEST ! rm -f $M0/file4
+## Test for state transition if auto-commit-period is 0
+TEST $CLI volume set $V0 features.auto-commit-period 0
+TEST `echo "worm 1" > $M0/file5`
+EXPECT '3/10/0' echo $(getfattr -e text --absolute-names --only-value -n "trusted.reten_state" $B0/${V0}1/file5)
+EXPECT 'worm 1' cat $M0/file5
+TEST ! rm -f $M0/file5
+TEST $CLI volume set $V0 features.auto-commit-period 5
+
## Test for checking if retention-period is updated on increasing the access time of a WORM-RETAINED file.
TEST $CLI volume set $V0 features.worm-files-deletable 1
TEST `echo "worm 1" >> $M0/file1`
diff --git a/xlators/features/read-only/src/worm.c b/xlators/features/read-only/src/worm.c
index 46078c1a96e..056e429dd62 100644
--- a/xlators/features/read-only/src/worm.c
+++ b/xlators/features/read-only/src/worm.c
@@ -452,24 +452,12 @@ worm_create_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
priv = this->private;
GF_ASSERT(priv);
if (priv->worm_file) {
- dict = dict_new();
- if (!dict) {
- gf_log(this->name, GF_LOG_ERROR,
- "Error creating the "
- "dict");
- goto out;
- }
- ret = dict_set_int8(dict, "trusted.worm_file", 1);
+ ret = fd_ctx_set(fd, this, 1);
if (ret) {
gf_log(this->name, GF_LOG_ERROR,
- "Error in setting "
- "the dict");
- goto out;
- }
- ret = syncop_fsetxattr(this, fd, dict, 0, NULL, NULL);
- if (ret) {
- gf_log(this->name, GF_LOG_ERROR, "Error setting xattr");
- goto out;
+ "Failed to set the fd ctx "
+ "for gfid:%s . Worm feature may not work for the gfid",
+ uuid_utoa(inode->gfid));
}
ret = worm_init_state(this, _gf_true, fd);
if (ret) {
@@ -617,7 +605,62 @@ struct xlator_fops fops = {
.lk = ro_lk,
};
-struct xlator_cbks cbks;
+int32_t
+worm_release(xlator_t *this, fd_t *fd)
+{
+ dict_t *dict = NULL;
+ int ret = -1;
+ dict = dict_new();
+ uint64_t value = 0;
+ loc_t loc = {
+ 0,
+ };
+ read_only_priv_t *priv = NULL;
+ priv = this->private;
+
+ if (priv->worm_file) {
+ if (!dict) {
+ gf_log(this->name, GF_LOG_ERROR, "Error creating the dict");
+ goto out;
+ }
+
+ ret = fd_ctx_get(fd, this, &value);
+ if (ret) {
+ gf_log(this->name, GF_LOG_DEBUG, "Failed to get the fd ctx");
+ }
+ if (!value) {
+ goto out;
+ }
+
+ ret = dict_set_int8(dict, "trusted.worm_file", 1);
+ if (ret) {
+ gf_log(this->name, GF_LOG_ERROR,
+ "Error in setting "
+ "the dict");
+ goto out;
+ }
+
+ loc.inode = inode_ref(fd->inode);
+ gf_uuid_copy(loc.gfid, fd->inode->gfid);
+ ret = syncop_setxattr(this, &loc, dict, 0, NULL, NULL);
+ if (ret) {
+ gf_log(this->name, GF_LOG_ERROR, "Error setting xattr");
+ goto out;
+ }
+
+ gf_worm_state_transition(this, _gf_false, &loc, GF_FOP_WRITE);
+ }
+
+out:
+ loc_wipe(&loc);
+ if (dict)
+ dict_unref(dict);
+ return 0;
+}
+
+struct xlator_cbks cbks = {
+ .release = worm_release,
+};
struct volume_options options[] = {
{.key = {"worm"},