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

1
mergerfs.spec

@ -35,6 +35,7 @@ make install PREFIX=%{_prefix} DESTDIR=%{buildroot}
/usr/bin/mergerfs
/usr/bin/mergerfs-fusermount
/usr/bin/fsck.mergerfs
/usr/bin/mergerfs.collect-info
/sbin/mount.mergerfs
/usr/lib/mergerfs/preload.so
%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
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
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
@ -16,27 +16,35 @@ you are encountering may have been addressed already.**
**For commercial support or feature requests please [contact me
directly.](mailto:support@spawn.link)**
### Information to include in bug reports
* [Information about the broader problem along with any attempted
solutions.](https://xyproblem.info)
* 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 client app making the requests: version, uid/gid
* **All** information about the application making the requests: version, uid/gid
* 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:
* `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

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 "fsck_mergerfs.hpp"
#include "mergerfs_fsck.hpp"
#include "mergerfs_collect_info.hpp"
#include "fs_path.hpp"
#include "fs_readahead.hpp"
@ -272,8 +273,8 @@ namespace l
}
int
main(const int argc_,
char **argv_)
main(int argc_,
char **argv_)
{
int rv;
Config::Read cfg;
@ -339,7 +340,9 @@ _pick_app_and_run(int argc_,
appname = appname.filename();
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_);
}

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_lchown.hpp"
#include "fs_close.hpp"
#include "fs_ioctl.hpp"
#include "fs_lgetxattr.hpp"
#include "fs_lstat.hpp"
#include "fs_open.hpp"
#include "int_types.h"
#include "mergerfs_ioctl.hpp"
#include "str.hpp"
#include "fs_copyfile.hpp"
#include "mergerfs_api.hpp"
#include "fmt/core.h"
#include "fmt/chrono.h"
@ -169,22 +168,13 @@ int
_get_allpaths(const std::string &mergerfs_path_,
PathStatVec &pathstats_)
{
int fd;
int rv;
IOCTL_BUF buf;
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)
pathstats_.emplace_back(path);
@ -396,8 +386,8 @@ _fsck(const FS::path &path_,
}
int
fsck::main(int argc_,
char **argv_)
mergerfs::fsck::main(int argc_,
char **argv_)
{
CLI::App app;
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)
#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_FILE_INFO _IOWR(IOCTL_APP_TYPE,0,IOCTL_BUF)
#define IOCTL_GC _IO(IOCTL_APP_TYPE,1)

Loading…
Cancel
Save