ფაილები ისევე როგორც დირექტორიები გაერთიანებულია ერთ დეიტა თაიფში inode
-ში. ყოველ inode
-ს აქვს უნიკალური აიდი. inode
-ს სტრუქტურა ასე გამოიყურება :
struct inode {
int id; // უნიკალური id
int open_cnt; // აინოუდის ჰოლდერების რაოდენობა, აინოუდი არ წაიშლება სანამ არ განულდება
bool is_deleted; // ინდიკატორი იმისა წაიშალა თუ არა აინოუდი. როცა ჰოლდერების რაოდენობა განულდება მხოლოდ მაშინ წაიშლება.
struct list_elem elem; // აინოუდების ლისტი
int magic;
pthread_mutex_t lock; // ლოქი აინოუდისთვის
struct inode_disk_metadata metadata;
};
struct inode_disk_metadata {
size_t length; // აინოუდში შენახული ბაიტების რაოდენობა
bool is_dir; // ინახავს ფაილის ტიპს, დირექტორიაა თუ ჩვეულებრივი ფაილი
__mode_t mode; // ინახავს ფაილის მოუდს, ფერმიშენებს და ა.შ
__uid_t uid; // მომხმარებლის id
__gid_t gid; // ჯგუფის id
size_t link_cnt; // აიდოუდზე ლინკების რაოდენობა
size_t xattrs_length; // custom ატრიბუტების დეითის სიგრძე
};
თითოეული აინოუდის შესახებ ინფორმაცია მემქეშში ასე ინახება. id#METADATA
-ზე ვინახავ inode_disk_metadata
სტრუქტურას. ხოლო შემდეგ id#0
, id#1
, id#2
წარმოადგენენ 4K სიგრძის ბლოკებს სადაც ფაილის შიგთავსი ინახება.
xattr ებს და დირექტორიებს ერთნაირი სტრუქტურებით ვინახავ. დირექტორია წარმოადგენს inode-ს რომლის კონტენტშიც წერია dir_entry
სტრუქტურების მასივი
struct dir_entry {
int inode_id; // inode-ს id
char name[NAME_MAX + 1]; // ფაილის სახელი
bool is_deleted; // აჩვენებს წაშლილია თუ არა ფაილი
};
როგორც სტრუქტურიდან ჩანს ფაილურ სისტემას არ აქვს 23-ზე დიდი ფაილის სახელების მხარდაჭერა. როცა დირექტორიიდან ფაილის ენტრის წაშლა ხდება ის ფაილის კონტენტიდან არ იშლება, რადგან ამ შემთხვევაში დანარჩენი კონტენტის მარცხნივ გადმოკოპირება იქნებოდა საჭირო რაც ძვირი ოპერაციაა. მე გადავწყვიტე უბრალოდ წაშლილის ფლაგი დავუსვა და როცა ახალი ჩანაწერის გაკეთების დრო დგება, პირველივე წაშლილ ფლაგს თავზე გადავაწერო ახალი აინოუდი.
დამატებით, რეკურსიული ძებნის თავიდან ასარიდებლად ვინახავ ყოველი full path-სთვის შესაბამისი აინოუდის id-ს.