Browse Source

Add mergerfs.collect-info

A tool to collect info for support requests.
pull/1491/head
Antonio SJ Musumeci 1 week ago
parent
commit
768d3a2aac
  1. 2
      Makefile
  2. 1
      mergerfs.spec
  3. 7
      mkdocs/build-venv
  4. 36
      mkdocs/docs/support.md
  5. 6
      src/fsck_mergerfs.hpp
  6. 11
      src/mergerfs.cpp
  7. 68
      src/mergerfs_api.cpp
  8. 24
      src/mergerfs_api.hpp
  9. 227
      src/mergerfs_collect_info.cpp
  10. 11
      src/mergerfs_collect_info.hpp
  11. 24
      src/mergerfs_fsck.cpp
  12. 9
      src/mergerfs_fsck.hpp
  13. 7
      src/mergerfs_ioctl.hpp

2
Makefile

@ -137,6 +137,7 @@ build/tests: build/mergerfs tests-objects
mergerfs: build/mergerfs mergerfs: build/mergerfs
ln -fs "mergerfs" "build/fsck.mergerfs" ln -fs "mergerfs" "build/fsck.mergerfs"
ln -fs "mergerfs" "build/mergerfs.collect-info"
tests: build/tests tests: build/tests
@ -184,6 +185,7 @@ install-base: build/mergerfs
$(MKDIR) -p "$(INSTALLBINDIR)" $(MKDIR) -p "$(INSTALLBINDIR)"
$(INSTALL) -v -m 0755 "build/mergerfs" "$(INSTALLBINDIR)/mergerfs" $(INSTALL) -v -m 0755 "build/mergerfs" "$(INSTALLBINDIR)/mergerfs"
ln -s "mergerfs" "${INSTALLBINDIR}/fsck.mergerfs" ln -s "mergerfs" "${INSTALLBINDIR}/fsck.mergerfs"
ln -s "mergerfs" "${INSTALLBINDIR}/mergerfs.collect-info"
install-mount-tools: install-base install-mount-tools: install-base
$(MKDIR) -p "$(INSTALLBINDIR)" $(MKDIR) -p "$(INSTALLBINDIR)"

1
mergerfs.spec

@ -35,6 +35,7 @@ make install PREFIX=%{_prefix} DESTDIR=%{buildroot}
/usr/bin/mergerfs /usr/bin/mergerfs
/usr/bin/mergerfs-fusermount /usr/bin/mergerfs-fusermount
/usr/bin/fsck.mergerfs /usr/bin/fsck.mergerfs
/usr/bin/mergerfs.collect-info
/sbin/mount.mergerfs /sbin/mount.mergerfs
/usr/lib/mergerfs/preload.so /usr/lib/mergerfs/preload.so
%doc %{_mandir}/* %doc %{_mandir}/*

7
mkdocs/build-venv

@ -0,0 +1,7 @@
#!/bin/sh
set -x
set -e
python3 -m venv venv
. ./venv/bin/activate
pip3 install --no-cache-dir mkdocs mkdocs-material pymdown-extensions mike

36
mkdocs/docs/support.md

@ -7,7 +7,7 @@ otherwise it will be difficult or impossible to diagnose. Also please
read the documentation as it provides details on many previously read the documentation as it provides details on many previously
encountered questions/issues. encountered questions/issues.
**Please make sure you are using the [latest
**Make sure you are using the [latest
release](https://github.com/trapexit/mergerfs/releases) or have tried release](https://github.com/trapexit/mergerfs/releases) or have tried
it in comparison. Old versions, which are often included in distros it in comparison. Old versions, which are often included in distros
like Debian and Ubuntu, are not ever going to be updated and the issue like Debian and Ubuntu, are not ever going to be updated and the issue
@ -16,27 +16,35 @@ you are encountering may have been addressed already.**
**For commercial support or feature requests please [contact me **For commercial support or feature requests please [contact me
directly.](mailto:support@spawn.link)** directly.](mailto:support@spawn.link)**
### Information to include in bug reports ### Information to include in bug reports
* [Information about the broader problem along with any attempted * [Information about the broader problem along with any attempted
solutions.](https://xyproblem.info) solutions.](https://xyproblem.info)
* Solution already ruled out and why. * Solution already ruled out and why.
* Version of mergerfs: `mergerfs --version`
* mergerfs settings / arguments: from fstab, systemd unit, command
line, OMV plugin, etc.
* Version of the OS: `uname -a` and `lsb_release -a`
* List of branches, their filesystem types, sizes (before and after issue): `df -h`
* The details from the output of the `mergerfs.collect-info` tool.
* Alternatively:
* Version of mergerfs: `mergerfs --version`
* mergerfs settings / arguments: from fstab, systemd unit, command
line, OMV plugin, etc.
* Version of the OS: `uname -a` and `lsb_release -a`
* List of branches, their filesystem types, sizes (before and after
issue): `df -h`, `lsblk -o NAME,FSTYPE,FSSIZE,SIZE,MOUNTPOINTS,RM,RO,ROTA`
* **All** information about the relevant paths and files: permissions, ownership, etc. * **All** information about the relevant paths and files: permissions, ownership, etc.
* **All** information about the client app making the requests: version, uid/gid
* **All** information about the application making the requests: version, uid/gid
* Runtime environment: * Runtime environment:
* Is mergerfs running within a container?
* Are the client apps using mergerfs running in a container?
* Is mergerfs running within a container?
* Are the client apps using mergerfs running in a container?
* A `strace` of the app having problems: * A `strace` of the app having problems:
* `strace -fvTtt -s 256 -o /tmp/app.strace.txt <cmd>`
* A `strace` of mergerfs while the program is trying to do whatever it is failing to do:
* `strace -fvTtt -s 256 -p <mergerfsPID> -o /tmp/mergerfs.strace.txt`
* **Precise** directions on replicating the issue. Do not leave **anything** out.
* Try to recreate the problem in the simplest way using standard programs: `ln`, `mv`, `cp`, `ls`, `dd`, etc.
* `strace -fvTtt -s 256 -o /tmp/app.strace.txt <cmd>`
* A `strace` of mergerfs while the program is trying to do whatever it
is failing to do:
* `strace -fvTtt -s 256 -p <mergerfsPID> -o /tmp/mergerfs.strace.txt`
* **Precise** directions on replicating the issue. Do not leave
**anything** out.
* Try to recreate the problem in the simplest way using standard
programs: `ln`, `mv`, `cp`, `ls`, `dd`, etc. With the most simple
mergerfs setup possible.
### Contact / Issue submission ### Contact / Issue submission

6
src/fsck_mergerfs.hpp

@ -1,6 +0,0 @@
#pragma once
namespace fsck
{
int main(int argc, char **argv);
}

11
src/mergerfs.cpp

@ -15,7 +15,8 @@
*/ */
#include "mergerfs.hpp" #include "mergerfs.hpp"
#include "fsck_mergerfs.hpp"
#include "mergerfs_fsck.hpp"
#include "mergerfs_collect_info.hpp"
#include "fs_path.hpp" #include "fs_path.hpp"
#include "fs_readahead.hpp" #include "fs_readahead.hpp"
@ -272,8 +273,8 @@ namespace l
} }
int int
main(const int argc_,
char **argv_)
main(int argc_,
char **argv_)
{ {
int rv; int rv;
Config::Read cfg; Config::Read cfg;
@ -339,7 +340,9 @@ _pick_app_and_run(int argc_,
appname = appname.filename(); appname = appname.filename();
if(appname == "fsck.mergerfs") if(appname == "fsck.mergerfs")
return fsck::main(argc_,argv_);
return mergerfs::fsck::main(argc_,argv_);
if(appname == "mergerfs.collect-info")
return mergerfs::collect_info::main(argc_,argv_);
return l::main(argc_,argv_); return l::main(argc_,argv_);
} }

68
src/mergerfs_api.cpp

@ -0,0 +1,68 @@
#include "mergerfs_api.hpp"
#include "fs_close.hpp"
#include "fs_ioctl.hpp"
#include "fs_open.hpp"
#include "mergerfs_ioctl.hpp"
#include "fs_lgetxattr.hpp"
#include "str.hpp"
#include "scope_guard.hpp"
#include <string.h>
int
mergerfs::api::allpaths(const std::string &input_path_,
std::vector<std::string> &output_paths_)
{
int rv;
IOCTL_BUF buf;
rv = fs::lgetxattr(input_path_,"user.mergerfs.allpaths",buf,sizeof(buf));
if(rv < 0)
return rv;
str::split_on_null(buf,rv,&output_paths_);
return 0;
}
int
_lgetxattr(const std::string &input_path_,
const std::string &key_,
std::string &value_)
{
int rv;
IOCTL_BUF buf;
rv = fs::lgetxattr(input_path_,key_,buf,sizeof(buf));
if(rv < 0)
return rv;
value_ = buf;
return rv;
}
int
mergerfs::api::basepath(const std::string &input_path_,
std::string &basepath_)
{
return ::_lgetxattr(input_path_,"user.mergerfs.basepath",basepath_);
}
int
mergerfs::api::relpath(const std::string &input_path_,
std::string &relpath_)
{
return ::_lgetxattr(input_path_,"user.mergerfs.relpath",relpath_);
}
int
mergerfs::api::fullpath(const std::string &input_path_,
std::string &fullpath_)
{
return ::_lgetxattr(input_path_,"user.mergerfs.fullpath",fullpath_);
}

24
src/mergerfs_api.hpp

@ -0,0 +1,24 @@
#pragma once
#include <string>
#include <vector>
namespace mergerfs
{
namespace api
{
int
basepath(const std::string &path,
std::string &basepath);
int
relpath(const std::string &path,
std::string &relpath);
int
fullpath(const std::string &path,
std::string &fullpath);
int
allpaths(const std::string &path,
std::vector<std::string> &paths);
}
}

227
src/mergerfs_collect_info.cpp

@ -0,0 +1,227 @@
#include "mergerfs_collect_info.hpp"
#include "mergerfs_api.hpp"
#include "fs_mounts.hpp"
#include "fs_unlink.hpp"
#include "CLI11.hpp"
#include "fmt/core.h"
#include "scope_guard.hpp"
#include "subprocess.hpp"
#include <stdio.h>
static
void
_write_str(const std::string &output_,
const std::string &str_)
{
FILE *f;
f = ::fopen(output_.c_str(),"a");
if(f == NULL)
return;
DEFER{ ::fclose(f); };
::fwrite(str_.c_str(),1,str_.size(),f);
}
static
void
_lsblk(const std::string &output_)
{
auto args =
{
"lsblk",
"--json",
"-o","NAME,FSTYPE,FSSIZE,SIZE,MOUNTPOINTS,RM,RO,ROTA"
};
subprocess::call(args,
subprocess::output{output_.c_str()});
}
static
void
_mounts(const std::string &output_)
{
auto args =
{
"cat",
"/proc/mounts"
};
subprocess::call(args,
subprocess::output{output_.c_str()});
}
static
void
_mount_point_stats(const std::string &output_)
{
fs::MountVec mounts;
fs::mounts(mounts);
for(const auto &mount : mounts)
{
std::vector<std::string> allpaths;
mergerfs::api::allpaths(mount.dir.string(),allpaths);
for(const auto &path : allpaths)
{
auto args = {"stat",path.c_str()};
subprocess::call(args,
subprocess::output{output_.c_str()});
}
}
}
static
void
_mergerfs_version(const std::string &output_)
{
auto args =
{
"mergerfs",
"--version"
};
try
{
subprocess::call(args,
subprocess::output{output_.c_str()});
}
catch(...)
{
}
}
static
void
_uname(const std::string &output_)
{
auto args =
{
"uname",
"-a"
};
try
{
subprocess::call(args,
subprocess::output{output_.c_str()});
}
catch(...)
{
}
}
static
void
_lsb_release(const std::string &output_)
{
auto args =
{
"lsb_release",
"-a"
};
try
{
subprocess::call(args,
subprocess::output{output_.c_str()});
}
catch(...)
{
}
}
static
void
_df(const std::string &output_)
{
auto args =
{
"df",
"-h"
};
try
{
subprocess::call(args,
subprocess::output{output_.c_str()});
}
catch(...)
{
}
}
static
void
_fstab(const std::string &output_)
{
auto args =
{
"cat",
"/etc/fstab"
};
try
{
subprocess::call(args,
subprocess::output{output_.c_str()});
}
catch(...)
{
}
}
int
mergerfs::collect_info::main(int argc_,
char **argv_)
{
CLI::App app;
const char *output_filepath = "/tmp/mergerfs.info.txt";
app.description("mergerfs.collect-info:"
" Collect info for support requests");
app.name("USAGE: mergerfs.collect-info");
try
{
app.parse(argc_,argv_);
}
catch(const CLI::ParseError &e)
{
return app.exit(e);
}
fmt::print("* Please have mergerfs mounted before running this tool.\n");
fs::unlink(output_filepath);
::_write_str(output_filepath,"::mergerfs --version::\n");
::_mergerfs_version(output_filepath);
::_write_str(output_filepath,"\n::uname -a::\n");
::_uname(output_filepath);
::_write_str(output_filepath,"\n::lsb_release -a::\n");
::_lsb_release(output_filepath);
::_write_str(output_filepath,"\n::df -h::\n");
::_df(output_filepath);
::_write_str(output_filepath,"\n::lsblk::\n");
::_lsblk(output_filepath);
::_write_str(output_filepath,"\n::cat /proc/mounts::\n");
::_mounts(output_filepath);
::_write_str(output_filepath,"\n::mount point stats::\n");
::_mount_point_stats(output_filepath);
::_write_str(output_filepath,"\n::cat /etc/fstab::\n");
::_fstab(output_filepath);
fmt::print("* Upload the following file to your"
" GitHub ticket or put on https://pastebin.com"
" when requesting support.\n* {}\n",output_filepath);
return 0;
}

11
src/mergerfs_collect_info.hpp

@ -0,0 +1,11 @@
#pragma once
namespace mergerfs
{
namespace collect_info
{
int
main(int argc,
char **argv);
}
}

24
src/fsck_mergerfs.cpp → src/mergerfs_fsck.cpp

@ -1,16 +1,15 @@
#include "fsck_mergerfs.hpp"
#include "mergerfs_fsck.hpp"
#include "fs_lchmod.hpp" #include "fs_lchmod.hpp"
#include "fs_lchown.hpp" #include "fs_lchown.hpp"
#include "fs_close.hpp" #include "fs_close.hpp"
#include "fs_ioctl.hpp"
#include "fs_lgetxattr.hpp" #include "fs_lgetxattr.hpp"
#include "fs_lstat.hpp" #include "fs_lstat.hpp"
#include "fs_open.hpp" #include "fs_open.hpp"
#include "int_types.h" #include "int_types.h"
#include "mergerfs_ioctl.hpp"
#include "str.hpp" #include "str.hpp"
#include "fs_copyfile.hpp" #include "fs_copyfile.hpp"
#include "mergerfs_api.hpp"
#include "fmt/core.h" #include "fmt/core.h"
#include "fmt/chrono.h" #include "fmt/chrono.h"
@ -169,22 +168,13 @@ int
_get_allpaths(const std::string &mergerfs_path_, _get_allpaths(const std::string &mergerfs_path_,
PathStatVec &pathstats_) PathStatVec &pathstats_)
{ {
int fd;
int rv; int rv;
IOCTL_BUF buf;
std::vector<std::string> allpaths; std::vector<std::string> allpaths;
strcpy(buf,"allpaths");
rv = mergerfs::api::allpaths(mergerfs_path_,allpaths);
if(rv < 0)
return rv;
fd = fs::open(mergerfs_path_,O_RDONLY|O_NOFOLLOW);
if(fd == -1)
return -errno;
rv = fs::ioctl(fd,IOCTL_FILE_INFO,buf);
fs::close(fd);
str::split_on_null(buf,rv,&allpaths);
for(const auto &path : allpaths) for(const auto &path : allpaths)
pathstats_.emplace_back(path); pathstats_.emplace_back(path);
@ -396,8 +386,8 @@ _fsck(const FS::path &path_,
} }
int int
fsck::main(int argc_,
char **argv_)
mergerfs::fsck::main(int argc_,
char **argv_)
{ {
CLI::App app; CLI::App app;
FS::path path; FS::path path;

9
src/mergerfs_fsck.hpp

@ -0,0 +1,9 @@
#pragma once
namespace mergerfs
{
namespace fsck
{
int main(int argc, char **argv);
}
}

7
src/mergerfs_ioctl.hpp

@ -6,7 +6,12 @@
#define _IOC_TYPE(X) (((X) >> 8) & 0xFF) #define _IOC_TYPE(X) (((X) >> 8) & 0xFF)
#endif #endif
typedef char IOCTL_BUF[4096];
#ifndef _IOC_SIZEBITS
#define _IOC_SIZEBITS 14
#endif
#define IOCTL_BUF_SIZE ((1 << _IOC_SIZEBITS) - 1)
typedef char IOCTL_BUF[IOCTL_BUF_SIZE];
#define IOCTL_APP_TYPE 0xDF #define IOCTL_APP_TYPE 0xDF
#define IOCTL_FILE_INFO _IOWR(IOCTL_APP_TYPE,0,IOCTL_BUF) #define IOCTL_FILE_INFO _IOWR(IOCTL_APP_TYPE,0,IOCTL_BUF)
#define IOCTL_GC _IO(IOCTL_APP_TYPE,1) #define IOCTL_GC _IO(IOCTL_APP_TYPE,1)

Loading…
Cancel
Save