Import first working version
[fuse-aexplorer.git] / AEpy / FusePatches.py
1 # Ugly patches for fusepy to accommodate inflexible userspace applications.
2 #
3
4 from ctypes import c_uint, cast, POINTER, Structure
5 from fusepy import FUSE
6
7
8 class fuse_conn_info(Structure):
9     _fields_ = [
10         ('proto_major', c_uint),
11         ('proto_minor', c_uint),
12         ('async_read', c_uint),
13         ('max_write', c_uint),
14         ('max_readahead', c_uint),
15         ('capable', c_uint),
16         ('want', c_uint),
17         ('max_background', c_uint),
18         ('congestion_threshold', c_uint)
19     ]
20
21
22 # Ugly patch for fusepy to allow changing max_readahead.
23 #
24 # This is necessary for FUSE filesystems which need to avoid unnecessary
25 # data transfers.
26 #
27 # Example:
28 # If a GIO (as in GLib/GNOME's GIO) based file manager (e.g. XFCE's Thunar)
29 # tries to determine each file's type by inspecting its header (GLib 2.50
30 # reads up to 4 KB of each file), this results in a lot of traffic. If the
31 # kernel increases this to 16 KB as part of its buffered I/O's readahead,
32 # things become very slow on exotically slow links or host media.
33 # In fact, this patch has been written with a 2 KByte/s link in mind.
34 #
35 # Why not turn off this header-sniffing feature in userspace?
36 # Because... Neither Thunar nor GLib/GIO have this option, and exotic FUSE
37 # filesystems still need to work on them until they have a mechanism to turn
38 # this off. Preferably with a hint in stat() or statfs().
39 #
40 # NOTE:
41 # The kernel will impose a lower bound on max_readahead.
42 # As of 4.9 on x86-64, this is 4096 bytes.
43 # (still a lot on a 2 KB/s link, but Thunar won't be *completely* useless)
44 #
45 def patch_max_readahead(max_readahead):
46     old_init = FUSE.init
47
48     def _new_fuse_init(self, conn):
49         conn2 = cast(conn, POINTER(fuse_conn_info))
50         conn2.contents.max_readahead = max_readahead
51         return old_init(self, conn)
52
53     FUSE.init = _new_fuse_init