diff options
| author | David Spisla <david.spisla@iternity.com> | 2020-02-25 10:57:36 +0100 | 
|---|---|---|
| committer | Amar Tumballi <amar@kadalu.io> | 2020-03-17 04:24:14 +0000 | 
| commit | 476139c962c298b2d00a3d42b90632fc25401526 (patch) | |
| tree | bf4ee55352605542e1d9a646844e90945bc01ab6 | |
| parent | b30f76980fc5d01b569d9409b68d24d809444ff8 (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-x | tests/features/worm.t | 8 | ||||
| -rw-r--r-- | xlators/features/read-only/src/worm.c | 77 | 
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"},  | 
