diff options
-rw-r--r-- | api/src/glfs-fops.c | 16 | ||||
-rw-r--r-- | api/src/glfs-resolve.c | 49 | ||||
-rw-r--r-- | libglusterfs/src/inode.c | 31 | ||||
-rw-r--r-- | libglusterfs/src/inode.h | 6 | ||||
-rw-r--r-- | xlators/mount/fuse/src/fuse-bridge.c | 35 | ||||
-rw-r--r-- | xlators/mount/fuse/src/fuse-resolve.c | 8 |
6 files changed, 92 insertions, 53 deletions
diff --git a/api/src/glfs-fops.c b/api/src/glfs-fops.c index e1762ae1285..b66f336338d 100644 --- a/api/src/glfs-fops.c +++ b/api/src/glfs-fops.c @@ -2270,6 +2270,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; @@ -2304,8 +2305,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); @@ -2314,6 +2327,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 2767abf1c39..b5efcbae0e7 100644 --- a/api/src/glfs-resolve.c +++ b/api/src/glfs-resolve.c @@ -75,27 +75,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; @@ -122,14 +139,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; @@ -622,7 +640,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, @@ -810,7 +828,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]; @@ -904,7 +923,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 { @@ -948,7 +968,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; } @@ -972,12 +992,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; diff --git a/libglusterfs/src/inode.c b/libglusterfs/src/inode.c index 7d3215ed16e..579b94ca036 100644 --- a/libglusterfs/src/inode.c +++ b/libglusterfs/src/inode.c @@ -1775,6 +1775,37 @@ out: return inode; } +void +inode_set_need_lookup (inode_t *inode, xlator_t *this) +{ + uint64_t need_lookup = 1; + + if (!inode | !this) + return; + + inode_ctx_set (inode, this, &need_lookup); + + return; +} + +gf_boolean_t +inode_needs_lookup (inode_t *inode, xlator_t *this) +{ + uint64_t need_lookup = 0; + gf_boolean_t ret = _gf_false; + + if (!inode || !this) + return ret; + + inode_ctx_get (inode, this, &need_lookup); + if (need_lookup) { + ret = _gf_true; + need_lookup = 0; + inode_ctx_set (inode, this, &need_lookup); + } + + return ret; +} int __inode_ctx_set2 (inode_t *inode, xlator_t *xlator, uint64_t *value1_p, diff --git a/libglusterfs/src/inode.h b/libglusterfs/src/inode.h index 474dc3992fc..b8bac7932c3 100644 --- a/libglusterfs/src/inode.h +++ b/libglusterfs/src/inode.h @@ -272,4 +272,10 @@ inode_ctx_merge (fd_t *fd, inode_t *inode, inode_t *linked_inode); int inode_is_linked (inode_t *inode); +void +inode_set_need_lookup (inode_t *inode, xlator_t *this); + +gf_boolean_t +inode_needs_lookup (inode_t *inode, xlator_t *this); + #endif /* _INODE_H */ diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c index 84efd6ca510..b67a60a76b1 100644 --- a/xlators/mount/fuse/src/fuse-bridge.c +++ b/xlators/mount/fuse/src/fuse-bridge.c @@ -63,39 +63,6 @@ fuse_forget_cbk (xlator_t *this, inode_t *inode) return 0; } -void -fuse_inode_set_need_lookup (inode_t *inode, xlator_t *this) -{ - uint64_t need_lookup = 1; - - if (!inode || !this) - return; - - inode_ctx_set (inode, this, &need_lookup); - - return; -} - - -gf_boolean_t -fuse_inode_needs_lookup (inode_t *inode, xlator_t *this) -{ - uint64_t need_lookup = 0; - gf_boolean_t ret = _gf_false; - - if (!inode || !this) - return ret; - - inode_ctx_get (inode, this, &need_lookup); - if (need_lookup) - ret = _gf_true; - need_lookup = 0; - inode_ctx_set (inode, this, &need_lookup); - - return ret; -} - - fuse_fd_ctx_t * __fuse_fd_ctx_check_n_create (xlator_t *this, fd_t *fd) { @@ -2787,7 +2754,7 @@ fuse_readdirp_cbk (call_frame_t *frame, void *cookie, xlator_t *this, feo->nodeid = inode_to_fuse_nodeid (linked_inode); - fuse_inode_set_need_lookup (linked_inode, this); + inode_set_need_lookup (linked_inode, this); inode_unref (linked_inode); diff --git a/xlators/mount/fuse/src/fuse-resolve.c b/xlators/mount/fuse/src/fuse-resolve.c index 2ddb31cd076..a670f4f6dac 100644 --- a/xlators/mount/fuse/src/fuse-resolve.c +++ b/xlators/mount/fuse/src/fuse-resolve.c @@ -26,8 +26,6 @@ int fuse_migrate_fd (xlator_t *this, fd_t *fd, xlator_t *old_subvol, fuse_fd_ctx_t * fuse_fd_ctx_get (xlator_t *this, fd_t *fd); -gf_boolean_t fuse_inode_needs_lookup (inode_t *inode, xlator_t *this); - static int fuse_resolve_loc_touchup (fuse_state_t *state) { @@ -229,7 +227,7 @@ fuse_resolve_parent_simple (fuse_state_t *state) parent = resolve->parhint; if (parent->table == state->itable) { - if (fuse_inode_needs_lookup (parent, THIS)) + if (inode_needs_lookup (parent, THIS)) return 1; /* no graph switches since */ @@ -258,7 +256,7 @@ fuse_resolve_parent_simple (fuse_state_t *state) /* non decisive result - parent missing */ return 1; } - if (fuse_inode_needs_lookup (parent, THIS)) { + if (inode_needs_lookup (parent, THIS)) { inode_unref (parent); return 1; } @@ -317,7 +315,7 @@ fuse_resolve_inode_simple (fuse_state_t *state) inode = inode_find (state->itable, resolve->gfid); if (inode) { - if (!fuse_inode_needs_lookup (inode, THIS)) + if (!inode_needs_lookup (inode, THIS)) goto found; /* inode was linked through readdirplus */ inode_unref (inode); |