meganz / MEGAsync

Easy automated syncing between your computers and your MEGA Cloud Drive
Other
1.62k stars 279 forks source link

MEGAsync hallucinating filesystem mismatch, leading to sync creation failure #964

Open loukamb opened 3 months ago

loukamb commented 3 months ago

As retrieved from MEGAsync's logs:

06/30-12:59:23.234314 139682277643968 DBG  Adding sync: /home/louka/MEGA vs / [megaclient.cpp:15871]
06/30-12:59:23.234359 139682277643968 DBG  Sync pqZ8LiVeI2g now in runState: 1 enabled: 1 error: 0 [sync.cpp:3870]
06/30-12:59:23.234409 139682277643968 DBG  Sync being created on filesystem type 9: XFS [sync.cpp:617]              
06/30-12:59:23.234425 139682277643968 DTL  Opening mount database: /proc/mounts [fs.cpp:2064]                       
06/30-12:59:23.234907 139682277643968 WARN Couldn't resolve device symlink: /dev/nvme0n1p2. Error was: No such file or directory [fs.cpp:2176]
06/30-12:59:23.234918 139682277643968 DTL  Opening mount database: /etc/mtab [fs.cpp:2064]                          
06/30-12:59:23.235266 139682277643968 WARN Couldn't resolve device symlink: /dev/nvme0n1p2. Error was: No such file or directory [fs.cpp:2176]
06/30-12:59:23.235271 139682277643968 WARN Couldn't determine which device contains path: /home/louka/MEGA [fs.cpp:2213]
06/30-12:59:23.235272 139682277643968 WARN Falling back to legacy filesystem fingerprint: /home/louka/MEGA [fs.cpp:2332]
06/30-12:59:23.235290 139682277643968 ERR  Sync root path is a different Filesystem than when the sync was created. Original filesystem id: (fingerprint: 66308, uuid: undefined)  Current: (fingerprint: 66310, uuid: undefined) [sync.cpp:659]
06/30-12:59:23.235293 139682277643968 ERR  Sync creation failed, syncerr: 15 [sync.cpp:3829]

For some reason, MEGAsync is hallucinating that the filesystem hosting /home/louka/MEGA is somehow no longer the same filesystem. I can guarantee that it is the exact same filesystem on the exact same disk. The only thing that changed is that I rebooted my computer to fix a monitor issue, with literally no other change to my computer whatsoever. Additionally, I have absolutely no idea what the "filesystem id" is or why it changes, shouldn't the application use the IDs returned by lsblk -o name,uuid if it really doesn't want to use paths? As to why MEGAsync is trying to parse my disk from its handle in /dev (why would you even do this?) and failing, I have no idea why because my main partition (/dev/nvme0n1p2) is properly mounted, as lsblk shows:

louka@desktop ~ $ lsblk
NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
nvme1n1     259:0    0 931.5G  0 disk 
├─nvme1n1p1 259:1    0    16M  0 part 
└─nvme1n1p2 259:2    0 931.5G  0 part 
nvme0n1     259:3    0 931.5G  0 disk 
├─nvme0n1p1 259:4    0   954M  0 part /efi
└─nvme0n1p2 259:5    0 930.6G  0 part /

I have attempted the following:

Judging from what the logs say is happening, I suggest that you use literally any other way of retrieving the sync folder. I see no reason why you want to even care about the device files - theoretically, someone should be allowed to move the sync folder to another SSD and have MEGA just read from it for further sync. If not, then you either need to massively improve your filesystem identification mechanism/fingerprinting, because rebooting your computer is apparently enough to break it. And if you don't want to change it, then at least give us the option to bypass it! That should be an obvious feature to add.

ChiwTheNeko commented 3 months ago

The source of the error is into Mega SDK (https://github.com/meganz/sdk). Maybe the issue should be reported there instead.

ChiwTheNeko commented 3 months ago

Taking a look at the code now I'm getting a better understanding of the situation.

The Mega SDK has two fingerprint systems. One is UUID that is reliable and persistent and the other is an uint64_t that, by their own admission in the comment, is very unreliable and unlikely to persist across reboot.

When checking the path the SDK try to identify which device the path is on. If it can find the device it will use the reliable UUID. If it can't figure out which device the path is on then it will fall back to the unreliable uint64_t. In the log you can see the message "Falling back to legacy filesystem fingerprint" indicating that it failed to find the device and is falling back to the unreliable uint64_t.

The SDK try to identify the device from the path by checking both /proc/mounts and /etc/mtab. The log message "Couldn't resolve device symlink: /dev/nvme0n1p2" indicates that it failed for some yet unknown reason. If I can figure out why this happen then I can fix the problem.

ChiwTheNeko commented 3 months ago

@loukamb could you please try 'realpath /dev/nvme0n1p2' in a shell?

loukamb commented 3 months ago

@ChiwTheNeko

louka@desktop ~ $ realpath /dev/nvme0n1p2
/dev/nvme0n1p2
ChiwTheNeko commented 3 months ago

@ChiwTheNeko

louka@desktop ~ $ realpath /dev/nvme0n1p2
/dev/nvme0n1p2

That's weird. It seems the cause of the error is not the same for you than for me even though it's in the same part of the code. I'm starting to wonder if there could be more than one bug in there.

If you are able, could you please compile and run that code on your machine? This is the function that the Mega SDK uses to identify the device your sync is on, with my proposed fix included. If it doesn't work for you that means there is another bug.

#include <mntent.h>
#include <string>
#include <functional>
#include <memory>
#include <cstring>
#include <cassert>
#include <iostream>
#include <linux/limits.h>

static std::string deviceOf(const std::string& database,
                            const std::string& path)
{
    // Convenience.
    using FileDeleter = std::function<int(FILE*)>;
    using FilePtr     = std::unique_ptr<FILE, FileDeleter>;

    std::cout << "Opening mount database: "
              << database
              << std::endl;

    // Try and open mount database.
    FilePtr mounts(setmntent(database.c_str(), "r"), endmntent);

    // Couldn't open mount database.
    if (!mounts)
    {
        // Latch error.
        auto error = errno;

        std::cout << "Couldn't open mount database: "
                  << database
                  << ". Error was: "
                  << strerror(error)
                  << std::endl;

        return std::string();
    }

    // What device contains path?
    std::string device;

    // Determines which device is the strongest match.
    //
    // As an example consider:
    // /dev/sda1 -> /mnt/usb
    // /dev/sda2 -> /mnt/usb/a/b/c
    //
    // /dev/sda2 is a better match for /mnt/usb/a/b/c/d.
    std::size_t score = 0;

    // Temporary storage space for mount entries.
    std::string storage(3 * PATH_MAX, '\x0');

    // Try and determine which device contains path.
    for (errno = 0; ; )
    {
        struct mntent entry;

        // Couldn't retrieve mount entry.
        if (!getmntent_r(mounts.get(),
                         &entry,
                         storage.data(),
                         static_cast<int>(storage.size())))
            break;

        // Where is this device mounted?
        std::string target = entry.mnt_dir;

        // Path's too short to be contained by target.
        if (path.size() < target.size())
            continue;

        // Target doesn't contain path.
        if (path.compare(0, target.size(), target))
            continue;

        // Existing device is a better match.
        if (score >= target.size())
            continue;

        // This device is a better match.
        device = entry.mnt_fsname;
        score  = target.size();
    }

    // Couldn't retrieve mount entry.
    if (errno)
    {
        // Latch error.
        auto error = errno;

        std::cout << "Couldn't enumerate mount database: "
                  << database
                  << ". Error was: "
                  << std::strerror(error)
                  << std::endl;

        return std::string();
    }

    // No device seems to contain path.
    if (device.empty())
    {
        std::cout << "No device seems to contain path: "
                  << path
                  << std::endl;

        return std::string();
    }

    // Device isn't actually a device.
    if (device.front() != '/')
    {
        std::cout << "A virtual device "
                  << device
                  << " seems to contain path: "
                  << path
                  << std::endl;

        return std::string();
    }

    std::cout << "Path "
              << path
              << " is on device "
              << device
              << std::endl;

    // Couldn't resolve symlinks in device.
    //
    // This is necessary to correctly handle nodes managed by device-mapper.
    // Say, the user is using LUKS or LVM.
    if (!realpath(device.c_str(), storage.data()))
    {
        // Latch error.
        auto error = errno;

        std::cout << "Couldn't resolve device symlink: "
                  << device
                  << ". Error was: "
                  << std::strerror(error)
                  << std::endl;

        return std::string();
    }

    // Truncate storage down to size.
    auto it = std::find(storage.begin(), storage.end(), '\x0');
    int index = std::distance(storage.begin(), it);
    std::cout << "index " << index << std::endl;

    storage.erase(std::find(storage.begin(), storage.end(), '\x0'), storage.end());

    // Sanity.
    assert(!storage.empty());

    // For debugging purposes.
    std::cout << "Path "
              << path
              << " is on storage "
              << storage
              << std::endl;

    // Return device to caller.
    return storage;
}

int main()
{
  deviceOf("/proc/mounts", "/home/louka/MEGA");
  deviceOf("/etc/mtab", "/home/louka/MEGA");
  return 0;
}
SJai-mega commented 3 months ago

Hello. We apologize for the lack of comms on this. Our developers are aware of the issue and are working to resolve it.

According to our developers there are 2 fixes that need to be implemented to resolve the issue. The first fix will be deployed in ver 5.4.0 of the desktop application and the second fix will be deployed in a future release as we are still currently testing it.

MTom1984 commented 1 month ago

Hello. We apologize for the lack of comms on this. Our developers are aware of the issue and are working to resolve it.

According to our developers there are 2 fixes that need to be implemented to resolve the issue. The first fix will be deployed in ver 5.4.0 of the desktop application and the second fix will be deployed in a future release as we are still currently testing it.

Hi. Any idea when this will be fixed as megasync is currently unusable for me until this is resolved.

elvis0288 commented 1 month ago

i installed v5.4.0 but that still did not fix the issue. my local folder is still stopping the backup. it give me the error "Problem syncing or backing up this folder" if i recreate the local folder it works but it does not make sense to do that all the time

MTom1984 commented 1 month ago

I found the problem for me. I was using an external SSD with exFAT file system. Reformatted to Ext4 and everything seems to be working now.

elvis0288 commented 1 month ago

I am using unraid and all my disks are btrs