#
# SPDX-License-Identifier: AGPL-3.0
-from future.utils import native_str
-from builtins import range
-from builtins import object
import argparse
import arvados
import daemon
const='all',
dest='mode',
help="""
-Mount a subdirectory for each mode: home, shared, by_id, and by_tag
-(default if no --mount-* options are given)
+Mount a subdirectory for each mode: `home`, `shared`, `by_id`, and `by_tag`
+(default if no `--mount-*` options are given)
""",
)
mode.add_argument(
const=None,
dest='mode',
help="""
-Mount a subdirectory for each mode specified by a --mount-* option
-(default if any --mount-* options are given;
+Mount a subdirectory for each mode specified by a `--mount-*` option
+(default if any `--mount-*` options are given;
see "Mount custom layout and filtering" section)
""",
)
metavar='PATH',
action='append',
default=[],
- help="Make your home project available under the mount at PATH",
+ help="Make your home project available under the mount at `PATH`",
)
mounts.add_argument(
'--mount-shared',
metavar='PATH',
action='append',
default=[],
- help="Make projects shared with you available under the mount at PATH",
+ help="Make projects shared with you available under the mount at `PATH`",
)
mounts.add_argument(
'--mount-tmp',
action='append',
default=[],
help="""
-Make a new temporary writable collection available under the mount at PATH.
+Make a new temporary writable collection available under the mount at `PATH`.
This collection is deleted when the mount is unmounted.
""",
)
action='append',
default=[],
help="""
-Make a magic directory available under the mount at PATH where collections and
+Make a magic directory available under the mount at `PATH` where collections and
projects are accessible through subdirectories named after their UUID or
portable data hash
""",
action='append',
default=[],
help="""
-Make a magic directory available under the mount at PATH where collections
+Make a magic directory available under the mount at `PATH` where collections
are accessible through subdirectories named after portable data hash
""",
)
default=[],
help="""
Make a subdirectory for each tag attached to a collection or project available
-under the mount at PATH
+under the mount at `PATH`
""" ,
)
dest="exec_args",
help="""
Mount data, run the specified command, then unmount and exit.
---exec reads all remaining options as the command to run,
+`--exec` reads all remaining options as the command to run,
so it must be the last option you specify.
Either end your command arguments (and other options) with a `--` argument,
-or specify --exec after your mount point.
+or specify `--exec` after your mount point.
""",
)
lifecycle.add_argument(
help="""
If a FUSE mount is already mounted at the given directory,
unmount it before mounting the requested data.
-If --subtype is specified, unmount only if the mount has that subtype.
+If `--subtype` is specified, unmount only if the mount has that subtype.
WARNING: This command can affect any kind of FUSE mount, not just arv-mount.
""",
)
default=False,
help="""
If a FUSE mount is already mounted at the given directory, unmount it and exit.
-If --subtype is specified, unmount only if the mount has that subtype.
+If `--subtype` is specified, unmount only if the mount has that subtype.
WARNING: This command can affect any kind of FUSE mount, not just arv-mount.
""",
)
default=False,
help="""
Unmount all FUSE mounts at or below the given directory, then exit.
-If --subtype is specified, unmount only if the mount has that subtype.
+If `--subtype` is specified, unmount only if the mount has that subtype.
WARNING: This command can affect any kind of FUSE mount, not just arv-mount.
""",
)
default=2.0,
metavar='SECONDS',
help="""
-The number of seconds to wait for a clean unmount after an --exec command has
+The number of seconds to wait for a clean unmount after an `--exec` command has
exited (default %(default).01f).
After this time, the mount will be forcefully unmounted.
""",
cache.add_argument(
'--disk-cache-dir',
metavar="DIRECTORY",
- help="Filesystem cache location (default ~/.cache/arvados/keep)",
+ help="Filesystem cache location (default `~/.cache/arvados/keep`)",
)
cache.add_argument(
'--directory-cache',
metavar='CLASSES',
help="Comma-separated list of storage classes to request for new collections",
)
-
+ # This is a hidden argument used by tests. Normally this
+ # value will be extracted from the cluster config, but mocking
+ # the cluster config under the presence of multiple threads
+ # and processes turned out to be too complicated and brittle.
+ plumbing.add_argument(
+ '--fsns',
+ type=str,
+ default=None,
+ help=argparse.SUPPRESS)
class Mount(object):
def __init__(self, args, logger=logging.getLogger('arvados.arv-mount')):
if self.args.replace:
unmount(path=self.args.mountpoint,
timeout=self.args.unmount_timeout)
- llfuse.init(self.operations, native_str(self.args.mountpoint), self._fuse_options())
+ llfuse.init(self.operations, str(self.args.mountpoint), self._fuse_options())
if self.daemon:
daemon.DaemonContext(
working_directory=os.path.dirname(self.args.mountpoint),
disk_cache=self.args.disk_cache,
disk_cache_dir=self.args.disk_cache_dir)
- # If there's too many prefetch threads and you
- # max out the CPU, delivering data to the FUSE
- # layer actually ends up being slower.
- # Experimentally, capping 7 threads seems to
- # be a sweet spot.
- prefetch_threads = min(max((block_cache.cache_max // (64 * 1024 * 1024)) - 1, 1), 7)
-
self.api = arvados.safeapi.ThreadSafeApiCache(
apiconfig=arvados.config.settings(),
api_params={
},
keep_params={
'block_cache': block_cache,
- 'num_prefetch_threads': prefetch_threads,
'num_retries': self.args.retries,
},
version='v1',
api_client=self.api,
encoding=self.args.encoding,
inode_cache=InodeCache(cap=self.args.directory_cache),
- enable_write=self.args.enable_write)
+ enable_write=self.args.enable_write,
+ fsns=self.args.fsns)
if self.args.crunchstat_interval:
statsthread = threading.Thread(
e = self.operations.inodes.add_entry(Directory(
llfuse.ROOT_INODE,
self.operations.inodes,
- self.api.config,
self.args.enable_write,
self.args.filters,
))
def _llfuse_main(self):
try:
- llfuse.main()
+ llfuse.main(workers=10)
except:
llfuse.close(unmount=False)
raise
+ self.operations.begin_shutdown()
llfuse.close()