X-Git-Url: https://git.enpas.org/?a=blobdiff_plain;f=AEpy%2FFusePatches.py;fp=AEpy%2FFusePatches.py;h=f02ddd2a2a186e8144fee757d495ff2934a39c87;hb=f06df88629c6ae1205f522148102a0c3d04d1cf2;hp=0000000000000000000000000000000000000000;hpb=8fc49cd8badf6ceb6b6dfe03deb961cadf61839f;p=fuse-aexplorer.git diff --git a/AEpy/FusePatches.py b/AEpy/FusePatches.py new file mode 100644 index 0000000..f02ddd2 --- /dev/null +++ b/AEpy/FusePatches.py @@ -0,0 +1,53 @@ +# Ugly patches for fusepy to accommodate inflexible userspace applications. +# + +from ctypes import c_uint, cast, POINTER, Structure +from fusepy import FUSE + + +class fuse_conn_info(Structure): + _fields_ = [ + ('proto_major', c_uint), + ('proto_minor', c_uint), + ('async_read', c_uint), + ('max_write', c_uint), + ('max_readahead', c_uint), + ('capable', c_uint), + ('want', c_uint), + ('max_background', c_uint), + ('congestion_threshold', c_uint) + ] + + +# Ugly patch for fusepy to allow changing max_readahead. +# +# This is necessary for FUSE filesystems which need to avoid unnecessary +# data transfers. +# +# Example: +# If a GIO (as in GLib/GNOME's GIO) based file manager (e.g. XFCE's Thunar) +# tries to determine each file's type by inspecting its header (GLib 2.50 +# reads up to 4 KB of each file), this results in a lot of traffic. If the +# kernel increases this to 16 KB as part of its buffered I/O's readahead, +# things become very slow on exotically slow links or host media. +# In fact, this patch has been written with a 2 KByte/s link in mind. +# +# Why not turn off this header-sniffing feature in userspace? +# Because... Neither Thunar nor GLib/GIO have this option, and exotic FUSE +# filesystems still need to work on them until they have a mechanism to turn +# this off. Preferably with a hint in stat() or statfs(). +# +# NOTE: +# The kernel will impose a lower bound on max_readahead. +# As of 4.9 on x86-64, this is 4096 bytes. +# (still a lot on a 2 KB/s link, but Thunar won't be *completely* useless) +# +def patch_max_readahead(max_readahead): + old_init = FUSE.init + + def _new_fuse_init(self, conn): + conn2 = cast(conn, POINTER(fuse_conn_info)) + conn2.contents.max_readahead = max_readahead + return old_init(self, conn) + + FUSE.init = _new_fuse_init