if obj.in_use():
_logger.debug("InodeCache cannot clear inode %i, in use", obj.inode)
return
- if obj.has_ref(only_children=True):
+ if obj.has_ref(True):
obj.kernel_invalidate()
_logger.debug("InodeCache sent kernel invalidate inode %i", obj.inode)
return
obj.clear()
+
+ # The llfuse lock is released in del_entry(), which is called by
+ # Directory.clear(). While the llfuse lock is released, it can happen
+ # that a reentrant call removes this entry before this call gets to it.
+ # Ensure that the entry is still valid before trying to remove it.
+ if obj.inode not in self._entries:
+ return
+
self._total -= obj.cache_size
del self._entries[obj.inode]
if obj.cache_uuid:
for ent in self._entries.values():
if self._total < self.cap or len(self._entries) < self.min_entries:
break
- # The llfuse lock is released in del_entry(), which is called
- # when clearing the contents of a directory. While the llfuse
- # lock is released, it can happen that cap_cache is called
- # reentrantly. It is possible for the reentrant call to remove
- # entries this call hasn't gotten to yet. Ensure that the
- # entry is still valid before trying to remove it.
- if ent.inode in self._entries:
- self._remove(ent, True)
- else:
- break
+ self._remove(ent, True)
def manage(self, obj):
if obj.persisted():
return True
def listen_for_events(self):
- self.events = arvados.events.subscribe(self._api_client,
- [["event_type", "in", ["create", "update", "delete"]]],
- self.on_event)
+ self.events = arvados.events.subscribe(
+ self._api_client,
+ [["event_type", "in", ["create", "update", "delete"]]],
+ self.on_event)
@catch_exceptions
def on_event(self, ev):
self._filehandles[fh] = FileHandle(fh, p)
self.inodes.touch(p)
+ # Normally, we will have received an "update" event if the
+ # parent collection is stale here. However, even if the parent
+ # collection hasn't changed, the manifest might have been
+ # fetched so long ago that the signatures on the data block
+ # locators have expired. Calling checkupdate() on all
+ # ancestors ensures the signatures will be refreshed if
+ # necessary.
+ while p.parent_inode in self.inodes:
+ if p == self.inodes[p.parent_inode]:
+ break
+ p = self.inodes[p.parent_inode]
+ self.inodes.touch(p)
+ p.checkupdate()
+
_logger.debug("arv-mount open inode %i flags %x fh %i", inode, flags, fh)
return fh