Skip to content

Debatable error handling approach for corrupted directory by fuse-exfat #217

@baby-lynch

Description

@baby-lynch

I came across this problem when accessing a faulty directory on my USB.
When I tried to do ls -al under this directory or rm -rf this directory, an EIO error was thrown.
I added debug information and found out the EIO error was from the code below:
Function call trace: fuse_exfat_readdir->exfat_opendir->exfat_cache_directory->readdir->parse_file_entry->parse_file_entries->check_entries
The check_entries() function (node.c:165-207) performs strict validation:

// node.c:171-204
/* check transitions between entries types */
for (i = 0; i < n + 1; previous = current, i++) {
    // Validates entry type transitions:
    // - EXFAT_ENTRY_NONE -> EXFAT_ENTRY_FILE
    // - EXFAT_ENTRY_FILE -> EXFAT_ENTRY_FILE_INFO
    // - EXFAT_ENTRY_FILE_INFO -> EXFAT_ENTRY_FILE_NAME
    // - EXFAT_ENTRY_FILE_NAME -> EXFAT_ENTRY_FILE_NAME or EXFAT_ENTRY_NONE
    // ...
    if (!valid) {
        exfat_error("unexpected entry type %#x after %#x at %d/%d",
                current, previous, i, n);
        return false;
    }
}

This error is probably caused by corrupted entry data on disk due to unknown reasons yet.

However, I tried to do the same thing on linux kernel's version of exfat and found the behaviors were different: ls -al can be performed under this faulty directory, rm -rf threw the error of ENOTEMPTY.

I looked the code and discovered that linux kernal handles this error differently:

  • Linux kernel exfat: Skips corrupted entries and continues reading, showing subsequent valid files with code implementation as such:
    exfat_readdir() (dir.c:68):
// dir.c:121-134
ep = exfat_get_dentry(sb, &clu, i, &bh);
if (!ep)
    return -EIO;  // Read error, but handled by caller

type = exfat_get_entry_type(ep);
if (type == TYPE_UNUSED) {
    brelse(bh);
    break;
}

if (type != TYPE_FILE && type != TYPE_DIR) {
    brelse(bh);
    continue;  // Skip invalid entry types, continue reading
}
// Process file/directory entry...
  • fuse-exfat: Returns -EIO error immediately upon encountering any corrupted entry, making all subsequent files inaccessible with code implementation aforementioned.

I think it is worthwhile to consider to align fuse-exfat behavior with the linux kernel, because under this circumstance, linux kernel's version of "best effort" approach seems to make more sense and provides better user experience.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions