2013-08-27 40 views
12

Tôi đang triển khai hệ thống tệp FUSE nhằm cung cấp quyền truy cập thông qua các cuộc gọi POSIX quen thuộc vào các tệp thực sự được lưu trữ phía sau API RESTful. Hệ thống tập tin lưu trữ các tập tin một khi chúng đã được truy xuất lần đầu tiên để chúng dễ dàng hơn trong các lần truy cập tiếp theo.Nếu hoạt động của FUSE getattr luôn luôn được tuần tự hóa?

Tôi đang chạy hệ thống tệp ở chế độ đa luồng (mặc định là FUSE) nhưng nhận thấy các cuộc gọi getattr dường như được tuần tự hóa, mặc dù các cuộc gọi khác có thể diễn ra song song.

Khi mở tệp FUSE luôn gọi getattr trước và ứng dụng tôi hỗ trợ cần kích thước tệp được trả về bởi lệnh gọi ban đầu này là chính xác (tôi không có quyền kiểm soát hành vi này). Điều này có nghĩa là nếu tôi không có tệp được lưu trữ, tôi cần thực sự nhận được thông tin qua các lệnh gọi RESTful API. Đôi khi các cuộc gọi này xảy ra trên mạng có độ trễ cao, với thời gian chuyến đi khứ hồi khoảng 600 mili giây.

Do tính chất tuần tự rõ ràng của cuộc gọi getattr, bất kỳ quyền truy cập nào vào tệp hiện không được lưu trữ sẽ khiến toàn bộ hệ thống tệp chặn bất kỳ thao tác mới nào trong khi getattr này được bảo trì.

Tôi đã đưa ra một số cách để làm việc vòng này, nhưng tất cả dường như xấu xí hoặc dài gió, thực sự tôi chỉ muốn các cuộc gọi getattr chạy song song giống như tất cả các cuộc gọi khác dường như.

Nhìn vào mã nguồn tôi không thấy tại sao getattr nên hoạt động như thế này, FUSE khóa khóa tree_lock mutex, nhưng chỉ để đọc, và không có ghi nào xảy ra cùng một lúc.

Vì lợi ích của việc đăng nội dung đơn giản trong câu hỏi này, tôi đã thực hiện một triển khai cơ bản cực kỳ chỉ hỗ trợ getattr và cho phép trình diễn dễ dàng vấn đề.

#ifndef FUSE_USE_VERSION 
#define FUSE_USE_VERSION 22 
#endif 

#include <fuse.h> 
#include <iostream> 

static int GetAttr(const char *path, struct stat *stbuf) 
{ 
    std::cout << "Before: " << path << std::endl; 
    sleep(5); 
    std::cout << "After: " << path << std::endl; 
    return -1; 
} 

static struct fuse_operations ops; 

int main(int argc, char *argv[]) 
{ 
    ops.getattr = GetAttr; 
    return fuse_main(argc, argv, &ops); 
} 

Sử dụng một vài thiết bị đầu cuối để gọi ls trên một con đường ở (khoảng) đồng thời cho thấy các cuộc gọi getattr thứ hai chỉ bắt đầu lần đầu tiên đã kết thúc, điều này gây ra ls thứ hai để mất ~ 10 giây thay vì của 5.

ga 1

$ date; sudo ls /mnt/cachefs/file1.ext; date 
Tue Aug 27 16:56:34 BST 2013 
ls: /mnt/cachefs/file1.ext: Operation not permitted 
Tue Aug 27 16:56:39 BST 2013 

ga 2

$ date; sudo ls /mnt/cachefs/file2.ext; date 
Tue Aug 27 16:56:35 BST 2013 
ls: /mnt/cachefs/file2.ext: Operation not permitted 
Tue Aug 27 16:56:44 BST 2013 

Như bạn có thể thấy, chênh lệch thời gian từ hai kết quả đầu ra date từ trước ls chỉ khác một giây, nhưng hai từ sau ls khác 5 giây, tương ứng với độ trễ trong hàm GetAttr. Điều này cho thấy cuộc gọi thứ hai bị chặn ở đâu đó sâu trong FUSE.

Output

$ sudo ./cachefs /mnt/cachefs -f -d 
unique: 1, opcode: INIT (26), nodeid: 0, insize: 56 
INIT: 7.10 
flags=0x0000000b 
max_readahead=0x00020000 
    INIT: 7.8 
    flags=0x00000000 
    max_readahead=0x00020000 
    max_write=0x00020000 
    unique: 1, error: 0 (Success), outsize: 40 
unique: 2, opcode: LOOKUP (1), nodeid: 1, insize: 50 
LOOKUP /file1.ext 
Before: /file1.ext 
After: /file1.ext 
    unique: 2, error: -1 (Operation not permitted), outsize: 16 
unique: 3, opcode: LOOKUP (1), nodeid: 1, insize: 50 
LOOKUP /file2.ext 
Before: /file2.ext 
After: /file2.ext 
    unique: 3, error: -1 (Operation not permitted), outsize: 16 

Mã và các ví dụ trên là không có gì giống như ứng dụng thực tế hoặc làm thế nào ứng dụng được sử dụng, nhưng thể hiện hành vi tương tự. Tôi đã không hiển thị điều này trong ví dụ trên, nhưng tôi đã thấy rằng khi cuộc gọi getattr hoàn tất, các cuộc gọi mở tiếp theo có thể chạy song song, như tôi đã mong đợi.

Tôi đã xóa tài liệu để thử và giải thích hành vi này và cố tìm người khác báo cáo trải nghiệm tương tự nhưng dường như không tìm thấy bất kỳ điều gì.Có thể bởi vì hầu hết các triển khai của getattr sẽ nhanh đến mức bạn sẽ không chú ý hoặc quan tâm nếu nó được sắp xếp theo thứ tự, hoặc có thể bởi vì tôi đang làm điều gì đó ngớ ngẩn trong cấu hình. Tôi đang sử dụng phiên bản 2.7.4 của FUSE, vì vậy có thể đây là lỗi cũ đã được khắc phục.

Nếu có ai có bất kỳ thông tin chi tiết nào về điều này, nó sẽ được đánh giá cao!

+0

Câu hỏi rất hay, tôi cũng quan tâm. Có thể bạn cũng nên đăng nó lên Danh sách gửi thư của nhà phát triển FUSE. – rralf

+1

Xin lỗi rralf, tôi chỉ thấy điều này. Tôi đã đăng trên danh sách gửi thư và nhận được phản hồi gần đây, tôi sẽ sớm cập nhật câu hỏi này. – abulford

Trả lời

10

Tôi đã đăng ký vào danh sách FUSE gửi thư, gửi câu hỏi của tôi và gần đây đều có phản ứng sau đây từ Miklos Szeredi:

Lookup (ví dụ: đầu tiên tìm kiếm các tập tin liên kết với một tên) được đăng mỗi thư mục. Đây là trong VFS (hệ thống tập tin phổ biến một phần trong hạt nhân), vì vậy về cơ bản bất kỳ hệ thống tập tin nào cũng dễ bị vấn đề này, không chỉ cầu chì.

Rất cám ơn Miklos đã giúp đỡ. Để xem toàn bộ chuỗi, hãy xem http://fuse.996288.n3.nabble.com/GetAttr-calls-being-serialised-td11741.html.

Tôi cũng nhận thấy rằng việc tuần tự hóa là mỗi thư mục, tức là hiệu ứng trên sẽ được nhìn thấy nếu cả hai tệp nằm trong cùng một thư mục, nhưng không phải nếu chúng nằm trong các thư mục riêng biệt. Đối với ứng dụng của tôi, việc giảm thiểu này là đủ cho tôi, các khách hàng vào hệ thống tập tin của tôi sử dụng các thư mục như vậy, trong khi tôi có thể mong đợi rất nhiều cuộc gọi getattr liên tiếp, khả năng tất cả chúng xảy ra trên cùng một thư mục là đủ thấp để tôi không lo lắng về.

Đối với những người mà giảm thiểu này không đủ, nếu hệ thống tệp của bạn hỗ trợ danh sách thư mục, bạn có thể tận dụng đề xuất của David Strauss, sử dụng gọi readdir làm trình kích hoạt để đệm bộ nhớ cache:

Trong các hệ thống tập tin của chúng tôi, chúng tôi cố gắng prefetch và bộ nhớ cache thông tin thuộc tính (mà chắc chắn sẽ được yêu cầu) trong readdir vì vậy chúng tôi không cần phải nhấn backend cho mỗi một.

Vì phần phụ trợ cho hệ thống tệp của tôi không có khái niệm về thư mục nên tôi không thể tận dụng đề xuất của anh ấy, nhưng hy vọng điều này sẽ hữu ích cho người khác.