Skip to content

Commit

Permalink
reevaluate support for sparse files periodically
Browse files Browse the repository at this point in the history
if a given filesystem were to disappear (e.g. removable storage)
followed by another filesystem appearing at the same location,
this would not get noticed by up2k in a timely manner

fix this by discarding the mtab cache after `--mtab-age` seconds and
rebuild it from scratch, unless the previous values are definitely
correct (as indicated by identical output from `/bin/mount`)

probably reduces windows performance by an acceptable amount
  • Loading branch information
9001 committed Apr 24, 2024
1 parent c5f7cfc commit f6e693f
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 7 deletions.
1 change: 1 addition & 0 deletions copyparty/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -860,6 +860,7 @@ def add_fs(ap):
ap2.add_argument("--rm-retry", metavar="T/R", type=u, default=rm_re_def, help="if a file cannot be deleted because it is busy, continue trying for \033[33mT\033[0m seconds, retry every \033[33mR\033[0m seconds; disable with 0/0 (volflag=rm_retry)")
ap2.add_argument("--mv-retry", metavar="T/R", type=u, default=rm_re_def, help="if a file cannot be renamed because it is busy, continue trying for \033[33mT\033[0m seconds, retry every \033[33mR\033[0m seconds; disable with 0/0 (volflag=mv_retry)")
ap2.add_argument("--iobuf", metavar="BYTES", type=int, default=256*1024, help="file I/O buffer-size; if your volumes are on a network drive, try increasing to \033[32m524288\033[0m or even \033[32m4194304\033[0m (and let me know if that improves your performance)")
ap2.add_argument("--mtab-age", metavar="SEC", type=int, default=60, help="rebuild mountpoint cache every \033[33mSEC\033[0m to keep track of sparse-files support; keep low on servers with removable media")


def add_upload(ap):
Expand Down
30 changes: 25 additions & 5 deletions copyparty/fsutil.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# coding: utf-8
from __future__ import print_function, unicode_literals

import argparse
import os
import re
import time
Expand All @@ -17,20 +18,26 @@


class Fstab(object):
def __init__(self, log: "RootLogger"):
def __init__(self, log: "RootLogger", args: argparse.Namespace):
self.log_func = log

self.warned = False
self.trusted = False
self.tab: Optional[VFS] = None
self.oldtab: Optional[VFS] = None
self.srctab = "a"
self.cache: dict[str, str] = {}
self.age = 0.0
self.maxage = args.mtab_age

def log(self, msg: str, c: Union[int, str] = 0) -> None:
self.log_func("fstab", msg, c)

def get(self, path: str) -> str:
if len(self.cache) > 9000:
self.age = time.time()
now = time.time()
if now - self.age > self.maxage or len(self.cache) > 9000:
self.age = now
self.oldtab = self.tab or self.oldtab
self.tab = None
self.cache = {}

Expand Down Expand Up @@ -75,7 +82,7 @@ def build_fallback(self) -> None:
self.trusted = False

def build_tab(self) -> None:
self.log("building tab")
self.log("inspecting mtab for changes")

sptn = r"^.*? on (.*) type ([^ ]+) \(.*"
if MACOS:
Expand All @@ -84,13 +91,23 @@ def build_tab(self) -> None:
ptn = re.compile(sptn)
so, _ = chkcmd(["mount"])
tab1: list[tuple[str, str]] = []
atab = []
for ln in so.split("\n"):
m = ptn.match(ln)
if not m:
continue

zs1, zs2 = m.groups()
tab1.append((str(zs1), str(zs2)))
atab.append(ln)

# keep empirically-correct values if mounttab unchanged
srctab = "\n".join(sorted(atab))
if srctab == self.srctab:
self.tab = self.oldtab
return

self.log("mtab has changed; reevaluating support for sparse files")

tab1.sort(key=lambda x: (len(x[0]), x[0]))
path1, fs1 = tab1[0]
Expand All @@ -99,6 +116,7 @@ def build_tab(self) -> None:
tab.add(fs, path.lstrip("/"))

self.tab = tab
self.srctab = srctab

def relabel(self, path: str, nval: str) -> None:
assert self.tab
Expand Down Expand Up @@ -133,7 +151,9 @@ def get_unix(self, path: str) -> str:
self.trusted = True
except:
# prisonparty or other restrictive environment
self.log("failed to build tab:\n{}".format(min_ex()), 3)
if not self.warned:
self.warned = True
self.log("failed to build tab:\n{}".format(min_ex()), 3)
self.build_fallback()

assert self.tab
Expand Down
2 changes: 1 addition & 1 deletion copyparty/up2k.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ def __init__(self, hub: "SvcHub") -> None:
t = "could not initialize sqlite3, will use in-memory registry only"
self.log(t, 3)

self.fstab = Fstab(self.log_func)
self.fstab = Fstab(self.log_func, self.args)
self.gen_fk = self._gen_fk if self.args.log_fk else gen_filekey

if self.args.hash_mt < 2:
Expand Down
2 changes: 1 addition & 1 deletion tests/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ def __init__(self, a=None, v=None, c=None, **ka0):
ex = "hash_mt srch_time u2abort u2j"
ka.update(**{k: 1 for k in ex.split()})

ex = "reg_cap s_thead s_tbody th_convt"
ex = "mtab_age reg_cap s_thead s_tbody th_convt"
ka.update(**{k: 9 for k in ex.split()})

ex = "db_act df k304 loris re_maxage rproxy rsp_jtr rsp_slp s_wr_slp snap_wri theme themes turbo"
Expand Down

0 comments on commit f6e693f

Please sign in to comment.