svc: send revalidate lookup on special dir

.snaps directory is a virtual direcotory, that doesn't
exist on the backend. Even though it is a special dentry,
it doesn't have a dedicated inode. So the inode number is
always random. Which means it will get different inode
number when reboot happens on snapd process.

Now with windows client the show-direcotry feature requires
a lookup on the .snpas direcoty post readdirp on root.
If the snapd restarted after a lookup, then subsequent lookup
will fail, because linked inode will be stale.

This patch will do a revalidate lookup with a new inode.

Change-Id: If97c07ecb307cefe7c86be8ebd05e28cbf678d1f
BUG: 1467513
Signed-off-by: Mohammed Rafi KC <rkavunga@redhat.com>
Reviewed-on: https://review.gluster.org/17690
CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
Reviewed-by: Raghavendra Bhat <raghavendra@redhat.com>
Smoke: Gluster Build System <jenkins@build.gluster.org>
This commit is contained in:
Mohammed Rafi KC 2017-07-03 12:45:38 +05:30 committed by Atin Mukherjee
parent ecd92d42bb
commit 70a5dfdea4
2 changed files with 81 additions and 0 deletions

View File

@ -1665,6 +1665,14 @@ gf_svc_readdirp_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
dict_unref (xdata);
if (op_ret) {
if (op_errno == ESTALE && !local->revalidate) {
local->revalidate = 1;
ret = gf_svc_special_dir_revalidate_lookup (frame,
this);
if (!ret)
return 0;
}
op_ret = 0;
op_errno = ENOENT;
goto out;
@ -1714,6 +1722,75 @@ out:
return 0;
}
int
gf_svc_special_dir_revalidate_lookup (call_frame_t *frame, xlator_t *this)
{
svc_private_t *private = NULL;
svc_local_t *local = NULL;
loc_t *loc = NULL;
dict_t *tmp_xdata = NULL;
char *path = NULL;
int ret = -1;
GF_VALIDATE_OR_GOTO ("snapview-client", this, out);
GF_VALIDATE_OR_GOTO (this->name, this->private, out);
private = this->private;
local = frame->local;
loc = &local->loc;
inode_unref (loc->inode);
loc->inode = inode_new (loc->parent->table);
if (!loc->inode) {
gf_log (this->name, GF_LOG_ERROR, "failed to "
"allocate new inode");
goto out;
}
gf_uuid_copy (local->loc.gfid, loc->inode->gfid);
ret = inode_path (loc->parent, private->path, &path);
if (ret < 0)
goto out;
if (loc->path)
GF_FREE ((char *)loc->path);
loc->path = gf_strdup (path);
if (loc->path) {
if (!loc->name ||
(loc->name && !strcmp (loc->name, ""))) {
loc->name = strrchr (loc->path, '/');
if (loc->name)
loc->name++;
}
} else
loc->path = NULL;
tmp_xdata = dict_new ();
if (!tmp_xdata) {
ret = -1;
goto out;
}
ret = dict_set_str (tmp_xdata, "entry-point", "true");
if (ret) {
gf_log (this->name, GF_LOG_ERROR, "failed to set dict");
goto out;
}
STACK_WIND (frame, gf_svc_readdirp_lookup_cbk,
SECOND_CHILD (this),
SECOND_CHILD (this)->fops->lookup, loc,
tmp_xdata);
out:
if (tmp_xdata)
dict_unref (tmp_xdata);
GF_FREE (path);
return ret;
}
static gf_boolean_t
gf_svc_readdir_on_special_dir (call_frame_t *frame, void *cookie,
xlator_t *this, int32_t op_ret,

View File

@ -23,6 +23,7 @@ struct __svc_local {
fd_t *fd;
void *cookie;
dict_t *xdata;
uint16_t revalidate;
};
typedef struct __svc_local svc_local_t;
@ -94,4 +95,7 @@ typedef enum {
VIRTUAL_INODE
} inode_type_t;
int
gf_svc_special_dir_revalidate_lookup (call_frame_t *frame, xlator_t *this);
#endif /* __SNAP_VIEW_CLIENT_H__ */