The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.


Fuse::TagLayer - A read-only tag-filesystem overlay for hierarchical filesystems


  use Fuse::TagLayer;
  my $ftl = Fuse::PerlSSH::FS->new(
        realdir         => '/some/local/path',
        mountpoint      => '/some/local/mountpoint',
        debug           => 2,

The bundled taglayer mounting script uses this module here, Fuse::TagLayer, as its backend. On mount, it scans a specified dir for tags and mounts them as the TagLayer filesystem at the mountpoint, by default /path/to/specified-dir/+tags.

  taglayer <real directory> [<tag directory mountpoint>]


Fuse::TagLayer offers all the tags found in one subdir/volume as a tag-based file-system at the mountpoint you specify, currently read-only. This is in addition to the real filesystem which is considered to be 'canonical' - with the tag-file-system being just another "layer" to access these files (thus the name).

How it works

Fuse::TagLayer, on mount, scans a specified dir-path and gathers all the tags found in the files' "user.tags" extended-attribute. These xattr-tags are supplemented by "tags" derrived from what could be called "directory fragments". That means, a path like "/Path/to/file" is interpreted as being the tags "Path" and "to" (dropping the filename as source for tags for now). All these tags then are inserted into a database backend (SQLite or a pure Perl one) and the db is used to expose a tag-based file system at the mountpoint.


Right now, the module offers some OO-ish methods, and some plain functions. The mounting script uses the below OO methods new(), mount() and umount(). But note the quirk that $self is stored in a global our variable, to mediate between the OO API and the Fuse-style functions.





A growing list of functions that match the FUSE bindings, some prefixed by "virt_" and some by "real_". The latter faciliating the loopback/ pass-through to the real filesystem:



As of version 0.12, TagLayer ships with two backends, PurePerl and SQLite. Both backends solve the info retrieval tasks required to expose the tag hierarchy in their own way. SQLite relies on AND-concatenated REGEX queries. The PurePerl implementation uses a Hash of Arrays as inverted index and does a number of boolean intersect operations, supported by pre-compiled sub-tag indices. Both apporaches are far from optimal. As a result, the Backend API is just as much in flux as the underlying storage structures. Currently, backends expose these functions internally:



Fuse::TagLayer exports nothing.


Should root contain all or no files?

When we regard the root dir as displaying files without any tags, then only these should show up. When we regard tags as filters, root would show all files, as on root-level, no tags (filters) are applied, a bit like in a global key-value filesystem. But when we think of webapps, most apps will ask you for at least one tag before you can browse results, so following this paradigm, root should show no files.


Currently, filenames, just as tags, are treated as being unique within the tag-filesystem. So, files of the same name in different directories are not handled properly. Only one of these name-doublettes might show up after the internal deduplication.

No tests

No working tests. But everything is read-only so trying TagLayer should be safe.

On "tagging" (or why it's read-only)

Right now, the resulting tag-fs is read-only, as we haven't implemented write() to the tag-based path so far. Eventually, when TagLayer grows into a real loop layer, this might change. Also, once this happens, we have to decide if tags coming from the 'canonical path' directory elements parsing, are to be considered read-only or not. (Would adding/removing a tag result in a mv within the underlying real file-system?)

Tagged directories

Via xattr, it is possible to tag a directory. This is ignored for now, as we regard all dirs within the tag-path to be "virtual" and only files in there as being "real". Makes things easier and is probably in-line with the idea behind a tag-based fs, putting away with directories.


The newer PurePerl backend has issues with non-ascii directory names and relies on sub-optimal regex matching.


FUSE, obviously.


Clipland GmbH


Copyright 2012-2013 Clipland GmbH. All rights reserved.

This library is free software, dual-licensed under GPLv3/AL2. You can redistribute it and/or modify it under the same terms as Perl itself.