diff options
Diffstat (limited to 'api')
-rw-r--r-- | api/src/glfs-fops.c | 16 | ||||
-rw-r--r-- | api/src/glfs-resolve.c | 49 |
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; |