diff --git a/src/borg/fuse2.py b/src/borg/fuse2.py index dd01ccd70..4b0fabc11 100644 --- a/src/borg/fuse2.py +++ b/src/borg/fuse2.py @@ -39,11 +39,11 @@ def debug_log(msg): f.write(f"{timestamp} {msg}\n") -class Node: - def __init__(self, id, parent=None): - self.id = id +class DirEntry: + def __init__(self, ino, parent=None): + self.ino = ino self.parent = parent - self.children = {} # name (bytes) -> Node + self.children = {} # name (bytes) -> DirEntry class FuseBackend: @@ -60,10 +60,10 @@ class FuseBackend: self.default_gid = os.getgid() self.default_dir = None - self.node_count = 0 - self.items = {} # node.id -> packed item + self.current_ino = 0 + self.inodes = {} # node.ino -> packed item self.root = self._create_node() - self.pending_archives = {} # Node -> Archive + self.pending_archives = {} # DirEntry -> Archive self.allow_damaged_files = False self.versions = False @@ -80,25 +80,25 @@ class FuseBackend: self.chunks_cache = LRUCache(capacity=10) def _create_node(self, item=None, parent=None): - self.node_count += 1 + self.current_ino += 1 if item is not None: - self.set_item(self.node_count, item) - return Node(self.node_count, parent) + self.set_inode(self.current_ino, item) + return DirEntry(self.current_ino, parent) - def get_item(self, id): - packed = self.items.get(id) + def get_inode(self, ino): + packed = self.inodes.get(ino) if packed is None: return None return Item(internal_dict=msgpack.unpackb(packed)) - def set_item(self, id, item): + def set_inode(self, ino, item): if item is None: - self.items.pop(id, None) + self.inodes.pop(ino, None) else: - self.items[id] = msgpack.packb(item.as_dict()) + self.inodes[ino] = msgpack.packb(item.as_dict()) def _create_filesystem(self): - self.set_item(self.root.id, self.default_dir) + self.set_inode(self.root.ino, self.default_dir) self.versions_index = FuseVersionsIndex() if getattr(self._args, "name", None): @@ -127,7 +127,7 @@ class FuseBackend: # Create a directory item for the archive item = Item(internal_dict=self.default_dir.as_dict()) item.mtime = int(archive.ts.timestamp() * 1e9) - self.set_item(archive_node.id, item) + self.set_inode(archive_node.ino, item) self.root.children[name_bytes] = archive_node self.pending_archives[archive_node] = archive @@ -180,7 +180,7 @@ class FuseBackend: if segment not in node.children: new_node = self._create_node(parent=node) # We might need a default directory item if it's an implicit directory - self.set_item(new_node.id, Item(internal_dict=self.default_dir.as_dict())) + self.set_inode(new_node.ino, Item(internal_dict=self.default_dir.as_dict())) node.children[segment] = new_node node = node.children[segment] @@ -189,7 +189,7 @@ class FuseBackend: if leaf_name in node.children: # Already exists (e.g. implicit dir became explicit) child = node.children[leaf_name] - self.set_item(child.id, item) # Update item + self.set_inode(child.ino, item) # Update item node = child else: new_node = self._create_node(item, parent=node) @@ -204,13 +204,13 @@ class FuseBackend: target_node = self._find_node_from_root(root_node, target_path) if target_node: # Reuse ID and Item to share inode and attributes - node.id = target_node.id + node.ino = target_node.ino # node.item = target_node.item # implicitly shared via ID - item = self.get_item(node.id) + item = self.get_inode(node.ino) if "nlink" not in item: item.nlink = 1 item.nlink += 1 - self.set_item(node.id, item) + self.set_inode(node.ino, item) else: logger.warning("Hardlink target not found: %s", link_target) else: @@ -247,7 +247,7 @@ class FuseBackend: for segment in segments[:-1]: if segment not in node.children: new_node = self._create_node(parent=node) - self.set_item(new_node.id, Item(internal_dict=self.default_dir.as_dict())) + self.set_inode(new_node.ino, Item(internal_dict=self.default_dir.as_dict())) node.children[segment] = new_node node = node.children[segment] @@ -255,7 +255,7 @@ class FuseBackend: leaf_name = segments[-1] if leaf_name not in node.children: intermediate_node = self._create_node(parent=node) - self.set_item(intermediate_node.id, Item(internal_dict=self.default_dir.as_dict())) + self.set_inode(intermediate_node.ino, Item(internal_dict=self.default_dir.as_dict())) node.children[leaf_name] = intermediate_node else: intermediate_node = node.children[leaf_name] @@ -286,15 +286,15 @@ class FuseBackend: if target_versioned in target_intermediate.children: original_node = target_intermediate.children[target_versioned] # Create new node but reuse the ID and item from original - item = self.get_item(original_node.id) + item = self.get_inode(original_node.ino) file_node = self._create_node(item, parent=intermediate_node) - file_node.id = original_node.id + file_node.ino = original_node.ino # Update nlink count - item = self.get_item(file_node.id) + item = self.get_inode(file_node.ino) if "nlink" not in item: item.nlink = 1 item.nlink += 1 - self.set_item(file_node.id, item) + self.set_inode(file_node.ino, item) intermediate_node.children[versioned_name] = file_node return @@ -372,9 +372,9 @@ class FuseBackend: def _make_stat_dict(self, node): """Create a stat dictionary from a node.""" - item = self.get_item(node.id) + item = self.get_inode(node.ino) st = {} - st["st_ino"] = node.id + st["st_ino"] = node.ino st["st_mode"] = item.mode & ~self.umask st["st_nlink"] = item.get("nlink", 1) if stat.S_ISDIR(st["st_mode"]): @@ -416,7 +416,7 @@ class borgfs(mfuse.Operations, FuseBackend): def sig_info_handler(self, sig_no, stack): # Simplified instrumentation - logger.debug("fuse: %d nodes", self.node_count) + logger.debug("fuse: %d inodes", self.current_ino) def mount(self, mountpoint, mount_options, foreground=False, show_rc=False): """Mount filesystem on *mountpoint* with *mount_options*.""" @@ -519,7 +519,7 @@ class borgfs(mfuse.Operations, FuseBackend): node = self._find_node(path) if node is None: raise mfuse.FuseOSError(errno.ENOENT) - item = self.get_item(node.id) + item = self.get_inode(node.ino) result = [k.decode("utf-8", "surrogateescape") for k in item.get("xattrs", {}).keys()] debug_log(f"listxattr -> {result}") return result @@ -529,7 +529,7 @@ class borgfs(mfuse.Operations, FuseBackend): node = self._find_node(path) if node is None: raise mfuse.FuseOSError(errno.ENOENT) - item = self.get_item(node.id) + item = self.get_inode(node.ino) try: if isinstance(name, str): name = name.encode("utf-8", "surrogateescape") @@ -569,7 +569,7 @@ class borgfs(mfuse.Operations, FuseBackend): # But read should be fast. raise mfuse.FuseOSError(errno.EBADF) - item = self.get_item(node.id) + item = self.get_inode(node.ino) parts = [] # optimize for linear reads: @@ -645,7 +645,7 @@ class borgfs(mfuse.Operations, FuseBackend): node = self._find_node(path) if node is None: raise mfuse.FuseOSError(errno.ENOENT) - item = self.get_item(node.id) + item = self.get_inode(node.ino) result = item.target debug_log(f"readlink -> {result!r}") return result