FUSE readdir() 작업에서 조회를 올바르게 구현합니다.

FUSE readdir() 작업에서 조회를 올바르게 구현합니다.

readdir()저는 장난감 파일 시스템을 구현하려고 하며 효율적이고 확장 가능한 방식으로 이를 올바르게 수행하는 방법을 찾으려고 노력하고 있습니다 . FUSE에서 사용하는 인터페이스를 이해하기 위해 주로 설명서를 읽었습니다.파이퓨즈3, 그러나 다른 FUSE 래퍼를 사용해도 문제가 해결될 것이라고 생각하지 않습니다.

내 이해는 내가 구현할 때readdir()불려지리라고, 불려지길 기대했어readdir_reply()메서드가 반환될 때까지 연속된 디렉터리 항목을 갖습니다 False. 이 작업을 수행할 때 각 항목을 이라는 고유한 [1] 64비트 ID와 연결하려고 합니다 next_id. 다음 호출에서는 readdir()이러한 ID 중 하나를 받게 되며 이전 호출에서 해당 ID가 반환될 것으로 예상됩니다. ID와 연관된 항목 다음에 시작되는 디렉토리 항목입니다.

호출 사이에 디렉토리가 변경되는 경우(예: 항목 추가 또는 제거) readdir()연속 호출에서 추가된 항목을 포함하거나 제거된 항목을 생략할지 여부를 자유롭게 선택할 수 있지만 다른 모든 항목은 ID를 유지해야 합니다. 건너뛰거나 두 번 반환됩니다.

의미상으로는 이 모든 것이 나에게는 괜찮은 것 같습니다. 제가 생각할 수 있는 가장 간단한 구현은 모든 디렉토리 항목을 배열로 읽은 opendir()다음 배열에 있는 각 항목의 인덱스를 ID로 사용하는 것입니다. 모든 항목을 한 번에 읽지 않으려면 readdir()호출할 때마다 배열을 계속해서 구축할 수 있습니다. 그러나 파일 핸들을 해제하기 전에는 배열[2]을 지울 수 없습니다.

최신 파일 시스템은 수억 개의 파일이 포함된 디렉터리를 쉽게 처리할 수 있습니다. 나는 이러한 구현이 디렉터리 파일 핸들당 디렉터리 항목 수 순서에 따른 메모리 할당을 허용할 수 없다고 가정합니다(예: 천만 파일 × 항목당 100바이트 = 1GB). 이러한 파일 시스템은 일반적으로 FUSE를 통하지 않고 커널에서 거의 독점적으로 구현됩니다.

이 모든 사실은 다음 진술 중 적어도 하나가 사실이라는 결론을 내립니다.

  1. FUSE 작동 요구사항을 잘못 이해했습니다 readdir().
  2. 제가 볼 수 없는 이러한 요구 사항을 충족하는 더 효율적인 솔루션이 있습니다.
  3. 커널 내의 파일 시스템에 대해 구현할 수 있는 더 나은 API가 있는데, 이 API는 이 모든 상태를 유지할 필요가 없습니다.
  4. 파일 시스템은 readdir()동등한 기능을 올바르게 구현하지 않지만 대신 응용 프로그램이 일반적으로 신경 쓰지 않는 방식으로 구현합니다.
  5. 파일 시스템은 디렉터리를 탐색할 때 기가바이트의 메모리를 할당하지만 아무도 이에 대해 신경 쓰지 않습니다.

그래서 그것은 어느 것입니까?

readdir()다른 파일 시스템 구현이 일반적으로 충족하는 모든 기대를 충족하는 방식으로 FUSE 작업을 효율적으로 구현하는 방법을 이해하고 싶습니다 .

[1]: 단일 파일 핸들 내에서 고유합니다.
[2]: 또는 readdir()호출 시 start_id로 설정 될 수도 있습니다 0.

답변1

동시 수정 및 하드 링크의 경우 효율성을 위해서는 쿠키 B트리가 필요합니다. POSIX에서 다른 올바른 off_t 방법을 모릅니다.

이 의견이 대부분의 답변을 제공한다고 생각합니다.https://github.com/facebookexperimental/eden/blob/5cc682e8ff24ef182be2dbe07e484396539e80f4/eden/fs/inodes/TreeInode.cpp#L1798-L1833

참조 링크를 포함하여 여기에 복사하겠습니다.

디렉토리를 동시에 수정하는 상황에서 readdir을 올바르게 구현하는 것은 쉽지 않습니다. 이 함수는 여러 번 호출됩니다. 첫 번째 읽기에서 제공된 off_t 값은 0이거나 마지막 항목의 오프셋에 해당하는 값입니다. (또는 eekdir 및 Telldir이 지정된 항목의 오프셋 값).

POSIX 규정을 준수하려면 전체 디렉터리 스트림에 걸쳐 일련의 readdir 호출이 주어지면 수정되지 않은 모든 항목이 정확히 한 번 반환되어야 합니다. readdir 호출 사이에 추가되거나 제거된 항목이 반환될 수 있지만 반드시 그럴 필요는 없습니다.

따라서 off_t는 순서가 지정된 항목 목록에 대한 색인으로 충분하지 않습니다. 항목이 연결되지 않은 경우 다음 readdir은 해당 항목을 건너뜁니다.

한 가지 옵션은 off_t를 항목 이름의 해시로 채우는 것입니다. off_t에는 63개의 사용 가능한 비트가 있습니다(초기 요청을 위해 예약된 0 값 제외). 실제로는 SpookyHashV2 63비트로 충분할 수 있지만 충돌이 있는 디렉터리를 생성하여 항목이 중복되거나 무한 루프가 발생할 수 있습니다. 또한 off다음 readdir 이전에 삭제된 항목을 처리하는 방법도 명확하지 않습니다 . (스트림에서 다시 시작할 위치를 찾는 방법은 무엇입니까?)

현재 Eden은 하드 링크를 지원하지 않습니다. 따라서 단기적으로는 inode 번호를 off_t에 저장하고 이를 inode별로 정렬된 항목 목록의 색인으로 처리할 수 있습니다. 이는 추가 인덱스가 없으면 2차 시간 복잡도를 가지지만 정확합니다.

장기적으로, 특히 Eden의 트리 디렉토리 구조가 SQLite 또는 이와 유사한 것에 저장되어 있는 경우,eekdir/readdir 쿠키 인덱스를 유지하고 해당 쿠키를 사용하여 항목을 열거해야 합니다.

관련 정보