-
Notifications
You must be signed in to change notification settings - Fork 1
/
ideas3.txt
181 lines (143 loc) · 4.32 KB
/
ideas3.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
read write open sync release rename remove
size_t read(size_t length, const uint8_t* data);
size_t write(size_t length, uint8_t* data);
fid_t open(fid_t fd, const char* path, mode_t mode);
void sync(fid_t fd);
void release(fid_t fd);
void rename(fid_t fd, fid_t nd, const char* name);
void remove(fid_t fd);
struct pnixfs* pnix
struct inode* ino
struct fnode* fno
File:
* opened file (including paths)
* always well-defined: parent + path, even if hardlinks > 1
* filesystem is recursively defined, so every file is also an inode
Transient subfile:
* Only available after opening its parent
* Opening the apparently same transient subfile on multiple open file descriptors always gives a different file which might not be synchronized
struct fnode_ops {
ssize_t read(struct fnode* fno, size_t length, void* data);
ssize_t write(struct fnode* fno, size_t length, const void* data);
int open(struct fnode* fno, const char* path, mode_t mode, struct fnode* nf);
int sync(struct fnode* fno);
int release(struct fnode* fno);
int rename(struct fnode* fno, struct fnode* nd, const char* name);
int remove(struct fnode* fno);
int permission(struct fnode* fno, const char* path, struct user* u);
};
struct fnode {
struct fnode_ops* ops;
struct dentry* dent;
void* data;
};
Project layers:
* Kernel module - exposes a few fs interfaces for mounting and passes low-level command messages from an interfacing device file to the appropriate fs
* Userspace daemon - handles subfile mounting by keeping a mapping of contype:handlers and translates these into low-level messages to pass to the kernel module
* Handler library - dynamically linked libraries exposing a FUSE-like interface which are loaded lazily based on the daemon's configuration (eg image/png:libpngfs.1.so). Might want to support multiple handlers per library as well to enable code reuse in related subfiles
Configuration:
* [contypes...]: library
- library provides handlers for all of the given contypes - if any are needed, the whole library is loaded
void register_contype_handler(content_t contype, struct subfile_operations* handler)
Library exposes:
* list_contypes() -> contype[]
- verification about what this library supports, could be used to autogenerate configuration file from a directory of these libraries\
- alternatively, inline variable?
* get_contype_handler(contype) -> subfile_operations + private data (?)
- Daemon calls this and expects lazy initialization and caching to be handled by the library
int create_fnode(struct fnode* fno, content_t ct)
struct int_subfile {
};
ssize_t tsf_offset_read(struct fnode* fno, size_t length, void* data) {
size_t offset = ((struct seekable*)fno->data)->offset;
switch(length) {
case 0:
return -EOVERFLOW;
case 1:
if(offset <= 0xff) {
*((uint8_t*)data) = offset;
break;
}
else {
return -EOVERFLOW;
}
case 2:
if(offset <= 0xffff) {
*((uint16_t*)data) = offset;
break;
}
else {
return -EOVERFLOW;
}
case 4:
if(offset <= 0xffffffff) {
*((uint32_t*)data) = offset;
break;
}
else {
return -EOVERFLOW;
}
case 8:
*((uint64_t*)data) = offset;
break;
default:
if(length >= 8) {
return tsf_offset_read(fno, 8, data);
}
else if(length >= 4) {
return tsf_offset_read(fno, 4, data);
}
else if(length >= 2) {
return tsf_offset_read(fno, 2, data);
}
else {
return tsf_offset_read(fno, 1, data);
}
}
return length;
}
ssize_t tsf_offset_write(struct fnode* fno, size_t length, void* data) {
size_t* offset = &((struct seekable*)fno->data)->offset;
switch(length) {
case 1:
if(offset <= 0xff) {
*((uint8_t*)data) = offset;
break;
}
else {
return -EOVERFLOW;
}
case 2:
if(offset <= 0xffff) {
*((uint16_t*)data) = offset;
break;
}
else {
return -EOVERFLOW;
}
case 4:
if(offset <= 0xffffffff) {
*((uint32_t*)data) = offset;
break;
}
else {
return -EOVERFLOW;
}
case 8:
*((uint64_t*)data) = offset;
break;
}
return length;
}
ssize_t tsf_stat_read(struct fnode* fno, size_t length, void* data) {
if(length >= sizeof(struct stat)) {
fill_stat(fno->dent->d_inode, (struct stat*)data);
}
else {
struct stat s;
fill_stat(fno->dent->d_inode, &s);
memcpy(&s, data, length);
}
return sizeof(struct stat);
}
struct fnode* open(struct fnode* base, const char* name, mode_t mode);