diff options
author | Jiffin Tony Thottan <jthottan@redhat.com> | 2017-05-18 11:22:16 +0530 |
---|---|---|
committer | Raghavendra G <rgowdapp@redhat.com> | 2017-06-22 06:27:42 +0000 |
commit | 237648780336d41cd6d820c337b38dd13f4d9e72 (patch) | |
tree | f1c6723764b4f0a21f86caf9d57e57aa61ae7e3c /xlators/cluster/dht/src/dht-common.c | |
parent | b2522297dd1e8b444a75b9cf177b2e6f6dffa05e (diff) |
dht/hardlink : Remove stale linkto file incase of failure
This is a similar issue fixed for rename in https://review.gluster.org/#/c/16016/
For hardlinks, if cached and hashed subvolumes are different, then it will first
create linkto file in hashed using root permission, but actually hardlink creation
fails with EACESS and stale linkto file is never removed.All the followup hardlink
calls with file name will result ESTALE because linktofile creation fails with EEXIST
and follow up lookup on linkto file returns gfid-mismatching(old linkto file) and
finally fails with ESTALE
Steps to produce :
(From link/00.t test from posix-testsuite)
Steps executed in script
* create a file "abc" using root
* change the ownership of file to a non root user
* create hardlink "link" for "abc" using a non root user, it fails with EACESS
* delete "abc"
* create directory "abc" using root
* again try to create hadrlink "link" for "abc" using non root user, fails with ESTALE
Also tried to fix other bugs in dht_linkfile_create_cbk() and posix_lookup.
Thanks Susant for the help in debugging the issue and suggestion for this patch.
Change-Id: I7a5a1899d3fd1fdb13578b37f9d52a084492e35d
BUG: 1452084
Signed-off-by: Jiffin Tony Thottan <jthottan@redhat.com>
Reviewed-on: https://review.gluster.org/17331
Smoke: Gluster Build System <jenkins@build.gluster.org>
Reviewed-by: N Balachandran <nbalacha@redhat.com>
CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
Reviewed-by: Raghavendra G <rgowdapp@redhat.com>
Diffstat (limited to 'xlators/cluster/dht/src/dht-common.c')
-rw-r--r-- | xlators/cluster/dht/src/dht-common.c | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c index dfc58e49c17..272a639aee6 100644 --- a/xlators/cluster/dht/src/dht-common.c +++ b/xlators/cluster/dht/src/dht-common.c @@ -6333,10 +6333,32 @@ dht_link_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int ret = -1; gf_boolean_t stbuf_merged = _gf_false; xlator_t *subvol = NULL; + call_frame_t *cleanup_frame = NULL; + dht_local_t *cleanup_local = NULL; local = frame->local; if (op_ret == -1) { + /* Remove the linkto if exists */ + if (local->linked) { + cleanup_frame = create_frame (this, this->ctx->pool); + if (cleanup_frame) { + cleanup_local = dht_local_init (cleanup_frame, + &local->loc2, + NULL, 0); + if (!cleanup_local || !local->link_subvol) { + DHT_STACK_DESTROY (cleanup_frame); + goto out; + } + cleanup_local->link_subvol = local->link_subvol; + FRAME_SU_DO (cleanup_frame, dht_local_t); + ret = synctask_new (this->ctx->env, + dht_remove_stale_linkto, + dht_remove_stale_linkto_cbk, + cleanup_frame, + cleanup_frame); + } + } /* No continuation on DHT inode missing errors, as we should * then have a good stbuf that states P2 happened. We would * get inode missing if, the file completed migrated between @@ -9471,3 +9493,54 @@ dht_release (xlator_t *this, fd_t *fd) { return dht_fd_ctx_destroy (this, fd); } + +int +dht_remove_stale_linkto (void *data) +{ + call_frame_t *frame = NULL; + dht_local_t *local = NULL; + xlator_t *this = NULL; + dict_t *xdata_in = NULL; + int ret = 0; + + GF_VALIDATE_OR_GOTO ("dht", data, out); + + frame = data; + local = frame->local; + this = frame->this; + GF_VALIDATE_OR_GOTO ("dht", this, out); + GF_VALIDATE_OR_GOTO ("dht", local, out); + GF_VALIDATE_OR_GOTO ("dht", local->link_subvol, out); + + xdata_in = dict_new (); + if (!xdata_in) + goto out; + + ret = dht_fill_dict_to_avoid_unlink_of_migrating_file (xdata_in); + if (ret) { + gf_msg (this->name, GF_LOG_WARNING, -ret, 0, + "Failed to set keys for stale linkto" + "deletion on path %s", local->loc.path); + goto out; + } + + ret = syncop_unlink (local->link_subvol, &local->loc, xdata_in, NULL); + if (ret) { + gf_msg (this->name, GF_LOG_WARNING, -ret, 0, + "Removal of linkto failed" + " on path %s at subvol %s", + local->loc.path, local->link_subvol->name); + + } +out: + if (xdata_in) + dict_unref (xdata_in); + return ret; +} + +int +dht_remove_stale_linkto_cbk (int ret, call_frame_t *sync_frame, void *data) +{ + DHT_STACK_DESTROY (sync_frame); + return 0; +} |