summaryrefslogtreecommitdiffstats
path: root/api
diff options
context:
space:
mode:
authorRaghavendra Bhat <raghavendra@redhat.com>2015-06-12 15:12:05 +0530
committerNiels de Vos <ndevos@redhat.com>2015-07-02 02:15:54 -0700
commitc1a8ae20bd055227921d199b952582eca4104f67 (patch)
tree8e56a6c2c4da95d00212408e25171c7e0c800e9b /api
parente7f2547f89dbcd90cdb3714f63620a36bdc2ef3a (diff)
libgfapi: send explicit lookups on inodes linked in readdirp
If the inode is linked via readdirp, then the consuners of gfapi which are using handles (got either in lookup or readdirp) might not send an explicit lookup on that object again (ex: NFS, samba, USS). If there is a replicate volume where the replicas of the object are not in sync, then readdirp followed by fops might lead data being served from the subvolume which is not in sync with latest data. And since lookup is needed to trigger self-heal on that object the consumers might keep getting wrong data until an explicit lookup is not done. Fuse handles this situation by sending an explicit lookup by itself (fuse xlator) on those inodes which are linked via readdirp, whenever a fop comes on that inode. The same procedure is done in gfapi as well to address this situation. Thanks to shyam(srangana@redhat.com) for valuable inputs Change-Id: I64f0591495dddc1dea7f8dc319f2558a7e342871 BUG: 1236009 Signed-off-by: Raghavendra Bhat <raghavendra@redhat.com> Reviewed-on: http://review.gluster.org/11236 Tested-by: NetBSD Build System <jenkins@build.gluster.org> Reviewed-by: Shyamsundar Ranganathan <srangana@redhat.com> Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Niels de Vos <ndevos@redhat.com>
Diffstat (limited to 'api')
-rw-r--r--api/src/glfs-fops.c16
-rw-r--r--api/src/glfs-resolve.c49
2 files changed, 51 insertions, 14 deletions
diff --git a/api/src/glfs-fops.c b/api/src/glfs-fops.c
index 37fa688a702..46842d411cb 100644
--- a/api/src/glfs-fops.c
+++ b/api/src/glfs-fops.c
@@ -2271,6 +2271,7 @@ glfd_entry_refresh (struct glfs_fd *glfd, int plus)
xlator_t *subvol = NULL;
gf_dirent_t entries;
gf_dirent_t old;
+ gf_dirent_t *entry = NULL;
int ret = -1;
fd_t *fd = NULL;
@@ -2305,8 +2306,20 @@ glfd_entry_refresh (struct glfs_fd *glfd, int plus)
&entries, NULL, NULL);
DECODE_SYNCOP_ERR (ret);
if (ret >= 0) {
- if (plus)
+ if (plus) {
+ /**
+ * Set inode_needs_lookup flag before linking the
+ * inode. Doing it later post linkage might lead
+ * to a race where a fop comes after inode link
+ * but before setting need_lookup flag.
+ */
+ list_for_each_entry (entry, &glfd->entries, list) {
+ if (entry->inode)
+ inode_set_need_lookup (entry->inode, THIS);
+ }
+
gf_link_inodes_from_dirent (THIS, fd->inode, &entries);
+ }
list_splice_init (&glfd->entries, &old.list);
list_splice_init (&entries.list, &glfd->entries);
@@ -2315,6 +2328,7 @@ glfd_entry_refresh (struct glfs_fd *glfd, int plus)
errno = 0;
}
+
if (ret > 0)
glfd->next = list_entry (glfd->entries.next, gf_dirent_t, list);
diff --git a/api/src/glfs-resolve.c b/api/src/glfs-resolve.c
index c185e211a53..65fe590144d 100644
--- a/api/src/glfs-resolve.c
+++ b/api/src/glfs-resolve.c
@@ -70,27 +70,44 @@ __glfs_first_lookup (struct glfs *fs, xlator_t *subvol)
}
+/**
+ * We have to check if need_lookup flag is set in both old and the new inodes.
+ * If its set in oldinode, then directly go ahead and do an explicit lookup.
+ * But if its not set in the oldinode, then check if the newinode is linked
+ * via readdirp. If so an explicit lookup is needed on the new inode, so that
+ * below xlators can set their respective contexts.
+ */
inode_t *
-glfs_refresh_inode_safe (xlator_t *subvol, inode_t *oldinode)
+glfs_refresh_inode_safe (xlator_t *subvol, inode_t *oldinode,
+ gf_boolean_t need_lookup)
{
loc_t loc = {0, };
int ret = -1;
struct iatt iatt = {0, };
inode_t *newinode = NULL;
+ gf_boolean_t lookup_needed = _gf_false;
if (!oldinode)
return NULL;
- if (oldinode->table->xl == subvol)
+ if (!need_lookup && oldinode->table->xl == subvol)
return inode_ref (oldinode);
newinode = inode_find (subvol->itable, oldinode->gfid);
- if (newinode)
- return newinode;
+ if (!need_lookup && newinode) {
+
+ lookup_needed = inode_needs_lookup (newinode, THIS);
+ if (!lookup_needed)
+ return newinode;
+ }
gf_uuid_copy (loc.gfid, oldinode->gfid);
- loc.inode = inode_new (subvol->itable);
+ if (!newinode)
+ loc.inode = inode_new (subvol->itable);
+ else
+ loc.inode = newinode;
+
if (!loc.inode)
return NULL;
@@ -117,14 +134,15 @@ glfs_refresh_inode_safe (xlator_t *subvol, inode_t *oldinode)
inode_t *
-__glfs_refresh_inode (struct glfs *fs, xlator_t *subvol, inode_t *inode)
+__glfs_refresh_inode (struct glfs *fs, xlator_t *subvol, inode_t *inode,
+ gf_boolean_t need_lookup)
{
inode_t *newinode = NULL;
fs->migration_in_progress = 1;
pthread_mutex_unlock (&fs->mutex);
{
- newinode = glfs_refresh_inode_safe (subvol, inode);
+ newinode = glfs_refresh_inode_safe (subvol, inode, need_lookup);
}
pthread_mutex_lock (&fs->mutex);
fs->migration_in_progress = 0;
@@ -617,7 +635,7 @@ glfs_migrate_fd_safe (struct glfs *fs, xlator_t *newsubvol, fd_t *oldfd)
}
}
- newinode = glfs_refresh_inode_safe (newsubvol, oldinode);
+ newinode = glfs_refresh_inode_safe (newsubvol, oldinode, _gf_false);
if (!newinode) {
gf_msg (fs->volname, GF_LOG_WARNING, errno,
API_MSG_INODE_REFRESH_FAILED,
@@ -805,7 +823,8 @@ __glfs_active_subvol (struct glfs *fs)
}
if (fs->cwd) {
- new_cwd = __glfs_refresh_inode (fs, new_subvol, fs->cwd);
+ new_cwd = __glfs_refresh_inode (fs, new_subvol, fs->cwd,
+ _gf_false);
if (!new_cwd) {
char buf1[64];
@@ -899,7 +918,8 @@ int
__glfs_cwd_set (struct glfs *fs, inode_t *inode)
{
if (inode->table->xl != fs->active_subvol) {
- inode = __glfs_refresh_inode (fs, fs->active_subvol, inode);
+ inode = __glfs_refresh_inode (fs, fs->active_subvol, inode,
+ _gf_false);
if (!inode)
return -1;
} else {
@@ -943,7 +963,7 @@ __glfs_cwd_get (struct glfs *fs)
return cwd;
}
- cwd = __glfs_refresh_inode (fs, fs->active_subvol, fs->cwd);
+ cwd = __glfs_refresh_inode (fs, fs->active_subvol, fs->cwd, _gf_false);
return cwd;
}
@@ -967,12 +987,15 @@ __glfs_resolve_inode (struct glfs *fs, xlator_t *subvol,
struct glfs_object *object)
{
inode_t *inode = NULL;
+ gf_boolean_t lookup_needed = _gf_false;
+
+ lookup_needed = inode_needs_lookup (object->inode, THIS);
- if (object->inode->table->xl == subvol)
+ if (!lookup_needed && object->inode->table->xl == subvol)
return inode_ref (object->inode);
inode = __glfs_refresh_inode (fs, fs->active_subvol,
- object->inode);
+ object->inode, lookup_needed);
if (!inode)
return NULL;