summaryrefslogtreecommitdiffstats
path: root/xlators/cluster/dht/src/dht-common.c
diff options
context:
space:
mode:
authorJiffin Tony Thottan <jthottan@redhat.com>2017-05-18 11:22:16 +0530
committerRaghavendra G <rgowdapp@redhat.com>2017-06-22 06:27:42 +0000
commit237648780336d41cd6d820c337b38dd13f4d9e72 (patch)
treef1c6723764b4f0a21f86caf9d57e57aa61ae7e3c /xlators/cluster/dht/src/dht-common.c
parentb2522297dd1e8b444a75b9cf177b2e6f6dffa05e (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.c73
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;
+}