MOS Source Code
Loading...
Searching...
No Matches
userfs.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-3.0-or-later
2// userspace filesystems
3
5
10#include "proto/filesystem.pb.h"
12
13#include <algorithm>
14#include <librpc/macro_magic.h>
15#include <librpc/rpc.h>
16#include <librpc/rpc_client.h>
17#include <librpc/rpc_server.h>
19#include <mos_stdio.hpp>
20#include <mos_stdlib.hpp>
21#include <mos_string.hpp>
22#include <pb.h>
23#include <pb_decode.h>
24#include <pb_encode.h>
25
26MOS_RPC_USERFS_CLIENT(fs_client)
27
28extern const inode_ops_t userfs_iops;
29extern const file_ops_t userfs_fops;
32
33template<typename... TPrint>
34userfs_t *userfs_get(filesystem_t *fs, TPrint... print)
35{
36 const auto _userfs = container_of(fs, userfs_t, fs);
38 auto stream = dInfo2<userfs> << "calling '" << fs->name << "' (rpc_server '" << _userfs->rpc_server_name << "'): ";
39 ((stream << print), ...);
40 return _userfs;
41}
42
44{
45 const pb_msgdesc_t *const fields;
46 void *data;
47
48 void skip()
49 {
50 data = nullptr;
51 }
52
53 explicit AutoCleanup(const pb_msgdesc_t *fields, void *data) : fields(fields), data(data) {};
55 {
56 if (fields && data)
58 }
59};
60
62{
63 // enum pb_file_type_t -> enum file_type_t is safe here because they have the same values
64 inode_t *i = inode_create(sb, stat->ino, (file_type_t) stat->type);
65 i->created = stat->created;
66 i->modified = stat->modified;
67 i->accessed = stat->accessed;
68 i->size = stat->size;
69 i->uid = stat->uid;
70 i->gid = stat->gid;
71 i->perm = stat->perm;
72 i->nlinks = stat->nlinks;
73 i->suid = stat->suid;
74 i->sgid = stat->sgid;
75 i->sticky = stat->sticky;
76 i->private_data = private_data;
77 i->ops = &userfs_iops;
79 return i;
80}
81
83{
84 pbi->ino = i->ino;
85 pbi->type = i->type;
86 pbi->created = i->created;
87 pbi->modified = i->modified;
88 pbi->accessed = i->accessed;
89 pbi->size = i->size;
90 pbi->uid = i->uid;
91 pbi->gid = i->gid;
92 pbi->perm = i->perm;
93 pbi->nlinks = i->nlinks;
94 pbi->suid = i->suid;
95 pbi->sgid = i->sgid;
96 pbi->sticky = i->sticky;
97 // pbi->private_data = (ptr_t) i->private;
98 return pbi;
99}
100
102{
103 mosrpc_fs_inode_ref ref = { .data = (ptr_t) i->private_data }; // for userfs, private_data is the inode reference used by the server
104 return ref;
105}
106
108{
109 if (likely(userfs->rpc_server))
110 return;
111
113 if (unlikely(!userfs->rpc_server))
114 {
115 mWarn << "userfs_ensure_connected: failed to connect to " << userfs->rpc_server_name;
116 return;
117 }
118}
119
120static bool userfs_iop_hardlink(dentry_t *d, inode_t *i, dentry_t *new_d)
121{
122 MOS_UNUSED(i);
123 MOS_UNUSED(new_d);
124
125 const auto name = dentry_name(d);
126 userfs_t *userfs = userfs_get(d->superblock->fs, "hardlink", name);
127 MOS_UNUSED(userfs);
128
129 return false;
130}
131
133{
134 const auto name = dentry_name(dentry);
135 userfs_t *ufs = userfs_get(dentry->superblock->fs, "iterate_dir", name);
136
137 mosrpc_fs_readdir_request req = { .i_ref = i_to_pb_ref(dentry->inode) };
139
140 const pf_point_t ev = profile_enter();
141 const int result = fs_client_readdir(ufs->rpc_server, &req, &resp);
142 profile_leave(ev, "userfs.'%s'.readdir", userfs->rpc_server_name);
143
145
146 if (result != RPC_RESULT_OK)
147 {
148 mWarn << "userfs_iop_iterate_dir: failed to readdir " << name << ": " << result;
149 return;
150 }
151
152 if (!resp.entries_count)
153 {
154 dWarn<userfs> << "userfs_iop_iterate_dir: failed to readdir " << name << ": " << resp.result.error;
155 return;
156 }
157
158 for (size_t i = 0; i < resp.entries_count; i++)
159 {
160 const mosrpc_fs_pb_dirent *pbde = &resp.entries[i];
161 MOS_ASSERT(pbde->name);
162 add_record(state, pbde->ino, pbde->name, (file_type_t) pbde->type);
163 }
164}
165
166static bool userfs_iop_lookup(inode_t *dir, dentry_t *dentry)
167{
168 const auto name = dentry_name(dentry);
169 userfs_t *fs = userfs_get(dir->superblock->fs, "lookup", name);
170
172 .i_ref = i_to_pb_ref(dir),
173 .name = (char *) name.c_str(),
174 };
175
177 const pf_point_t ev = profile_enter();
178 const int result = fs_client_lookup(fs->rpc_server, &req, &resp);
179 profile_leave(ev, "userfs.'%s'.lookup", ufs->rpc_server_name);
180
182
183 if (result != RPC_RESULT_OK)
184 {
185 mWarn << "userfs_iop_lookup: failed to lookup " << name << ": " << result;
186 return false;
187 }
188
189 if (!resp.result.success)
190 {
191 return false; // ENOENT is not a big deal
192 }
193
194 inode_t *i = i_from_pbfull(&resp.i_info, dir->superblock, (void *) resp.i_ref.data);
195 dentry_attach(dentry, i);
196 dentry->superblock = i->superblock = dir->superblock;
197 i->ops = &userfs_iops;
199 i->file_ops = &userfs_fops;
200 return true;
201}
202
203static bool userfs_iop_mkdir(inode_t *dir, dentry_t *dentry, file_perm_t perm)
204{
205 const auto name = dentry_name(dentry);
206 userfs_t *fs = userfs_get(dir->superblock->fs, "mkdir", name);
207
209 .i_ref = i_to_pb_ref(dir),
210 .name = (char *) name.c_str(),
211 .perm = perm,
212 };
214
215 const pf_point_t pp = profile_enter();
216 const int result = fs_client_make_dir(fs->rpc_server, &req, &resp);
217 profile_leave(pp, "userfs.'%s'.make_dir", userfs->rpc_server_name);
218
220
221 if (result != RPC_RESULT_OK)
222 {
223 mWarn << "userfs_iop_mkdir: failed to mkdir " << name << ": " << result;
224 return false;
225 }
226
227 if (!resp.result.success)
228 {
229 dWarn<userfs> << "userfs_iop_mkdir: failed to mkdir " << name << ": " << resp.result.error;
230 return false;
231 }
232
233 inode_t *i = i_from_pbfull(&resp.i_info, dir->superblock, (void *) resp.i_ref.data);
234 dentry_attach(dentry, i);
235 dentry->superblock = i->superblock = dir->superblock;
236 i->ops = &userfs_iops;
238 i->file_ops = &userfs_fops;
239 return true;
240}
241
242static bool userfs_iop_mknode(inode_t *dir, dentry_t *dentry, file_type_t type, file_perm_t perm, dev_t dev)
243{
244 MOS_UNUSED(dir);
245 MOS_UNUSED(dentry);
246 MOS_UNUSED(type);
247 MOS_UNUSED(perm);
248 MOS_UNUSED(dev);
249
250 const auto name = dentry_name(dentry);
251 userfs_t *userfs = userfs_get(dir->superblock->fs, "mknode", name);
252 MOS_UNUSED(userfs);
253
254 return false;
255}
256
257static bool userfs_iop_newfile(inode_t *dir, dentry_t *dentry, file_type_t type, file_perm_t perm)
258{
259 const auto name = dentry_name(dentry);
260 userfs_t *fs = userfs_get(dir->superblock->fs, "newfile", name);
261
263 .i_ref = i_to_pb_ref(dir),
264 .name = (char *) name.c_str(),
265 .type = type,
266 .perm = perm,
267 };
269
270 const pf_point_t pp = profile_enter();
271 const int result = fs_client_create_file(fs->rpc_server, &req, &resp);
272 profile_leave(pp, "userfs.'%s'.create_file", userfs->rpc_server_name);
273
275
276 if (result != RPC_RESULT_OK)
277 {
278 mWarn << "userfs_iop_newfile: failed to create file " << name << ": " << result;
279 return false;
280 }
281
282 if (!resp.result.success)
283 {
284 dWarn<userfs> << "userfs_iop_newfile: failed to create file " << name << ": " << resp.result.error;
285 return false;
286 }
287
288 inode_t *i = i_from_pbfull(&resp.i_info, dir->superblock, (void *) resp.i_ref.data);
289 dentry_attach(dentry, i);
290 dentry->superblock = i->superblock = dir->superblock;
291 i->ops = &userfs_iops;
293 i->file_ops = &userfs_fops;
294 return true;
295}
296
297static size_t userfs_iop_readlink(dentry_t *dentry, char *buffer, size_t buflen)
298{
299 const auto name = dentry_name(dentry);
300 userfs_t *fs = userfs_get(dentry->superblock->fs, "readlink", name);
301
302 const mosrpc_fs_readlink_request req = {
303 .i_ref = i_to_pb_ref(dentry->inode),
304 };
306
307 const pf_point_t pp = profile_enter();
308 const int result = fs_client_readlink(fs->rpc_server, &req, &resp);
309 profile_leave(pp, "userfs.'%s'.readlink", userfs->rpc_server_name);
310
312
313 if (result != RPC_RESULT_OK)
314 {
315 mWarn << "userfs_iop_readlink: failed to readlink " << name << ": " << result;
316 return -EIO;
317 }
318
319 if (!resp.result.success)
320 {
321 dWarn<userfs> << "userfs_iop_readlink: failed to readlink " << name << ": " << resp.result.error;
322 return -EIO;
323 }
324
325 size_t len = strlen(resp.target);
326 if (len > buflen)
327 len = buflen;
328
329 memcpy(buffer, resp.target, len);
330 return len;
331}
332
333static bool userfs_iop_rename(inode_t *old_dir, dentry_t *old_dentry, inode_t *new_dir, dentry_t *new_dentry)
334{
335 MOS_UNUSED(old_dir);
336 MOS_UNUSED(old_dentry);
337 MOS_UNUSED(new_dir);
338 MOS_UNUSED(new_dentry);
339
340 const auto old_name = dentry_name(old_dentry);
341 const auto new_name = dentry_name(new_dentry);
342 userfs_t *userfs = userfs_get(old_dir->superblock->fs, "rename", old_name, " to ", new_name);
343 MOS_UNUSED(userfs);
344
345 return false;
346}
347
348static bool userfs_iop_rmdir(inode_t *dir, dentry_t *dentry)
349{
350 MOS_UNUSED(dir);
351 MOS_UNUSED(dentry);
352
353 const auto name = dentry_name(dentry);
354 userfs_t *userfs = userfs_get(dir->superblock->fs, "rmdir", name);
355 MOS_UNUSED(userfs);
356
357 return false;
358}
359
360static bool userfs_iop_symlink(inode_t *dir, dentry_t *dentry, const char *symname)
361{
362 MOS_UNUSED(dir);
363 MOS_UNUSED(dentry);
364 MOS_UNUSED(symname);
365
366 const auto name = dentry_name(dentry);
367 userfs_t *userfs = userfs_get(dir->superblock->fs, "symlink", name);
368 MOS_UNUSED(userfs);
369
370 return false;
371}
372
373static bool userfs_iop_unlink(inode_t *dir, dentry_t *dentry)
374{
375 const auto name = dentry_name(dentry);
376 userfs_t *fs = userfs_get(dir->superblock->fs, "unlink", name);
377
378 const mosrpc_fs_unlink_request req = {
379 .i_ref = i_to_pb_ref(dir),
380 .dentry = { .inode_id = dentry->inode->ino, .name = (char *) name.c_str() },
381 };
383
384 const pf_point_t pp = profile_enter();
385 const int result = fs_client_unlink(fs->rpc_server, &req, &resp);
386 profile_leave(pp, "userfs.'%s'.unlink", userfs->rpc_server_name);
387
389
390 if (result != RPC_RESULT_OK)
391 {
392 mWarn << "userfs_iop_unlink: failed to unlink " << name << ": " << result;
393 return false;
394 }
395
396 if (!resp.result.success)
397 {
398 dWarn<userfs> << "userfs_iop_unlink: failed to unlink " << name << ": " << resp.result.error;
399 return false;
400 }
401
402 return true;
403}
404
406 .hardlink = userfs_iop_hardlink,
407 .iterate_dir = userfs_iop_iterate_dir,
408 .lookup = userfs_iop_lookup,
409 .mkdir = userfs_iop_mkdir,
410 .mknode = userfs_iop_mknode,
411 .newfile = userfs_iop_newfile,
412 .readlink = userfs_iop_readlink,
413 .rename = userfs_iop_rename,
414 .rmdir = userfs_iop_rmdir,
415 .symlink = userfs_iop_symlink,
416 .unlink = userfs_iop_unlink,
417};
418
419static bool userfs_fop_open(inode_t *inode, FsBaseFile *file, bool created)
420{
421 MOS_UNUSED(inode);
422 MOS_UNUSED(file);
423 MOS_UNUSED(created);
424
425 return true;
426}
427
429 .open = userfs_fop_open,
430 .read = vfs_generic_read,
431 .write = vfs_generic_write,
432 .release = NULL,
433 .seek = NULL,
434 .mmap = NULL,
435 .munmap = NULL,
436};
437
439{
440 userfs_t *fs = userfs_get(cache->owner->superblock->fs, "fill_cache");
441
442 const mosrpc_fs_getpage_request req = {
443 .i_ref = i_to_pb_ref(cache->owner),
444 .pgoff = pgoff,
445 };
446
448
449 const pf_point_t pp = profile_enter();
450 const int result = fs_client_get_page(fs->rpc_server, &req, &resp);
451 profile_leave(pp, "userfs.'%s'.getpage", userfs->rpc_server_name);
452
454
455 if (result != RPC_RESULT_OK)
456 {
457 mWarn << "userfs_inode_cache_fill_cache: failed to getpage: " << result;
458 return -EIO;
459 }
460
461 if (!resp.result.success)
462 {
463 dWarn<userfs> << "userfs_inode_cache_fill_cache: failed to getpage: " << resp.result.error;
464 return -EIO;
465 }
466
467 // allocate a page
469 if (!page)
470 {
471 mWarn << "userfs_inode_cache_fill_cache: failed to allocate page";
472 return -ENOMEM;
473 }
474
475 // copy the data from the server
476 memcpy((void *) phyframe_va(page), resp.data->bytes, std::min(resp.data->size, (pb_size_t) MOS_PAGE_SIZE));
477 return page;
478}
479
481{
482 userfs_t *fs = userfs_get(cache->owner->superblock->fs, "flush_page");
483
485 .i_ref = i_to_pb_ref(cache->owner),
486 .pgoff = pgoff,
487 .data = nullptr,
488 };
489 req.data = (pb_bytes_array_t *) kcalloc<char>(PB_BYTES_ARRAY_T_ALLOCSIZE(MOS_PAGE_SIZE));
490 req.data->size = MOS_PAGE_SIZE;
491 memcpy(req.data->bytes, (void *) phyframe_va(page), MOS_PAGE_SIZE);
492
494
495 const pf_point_t pp = profile_enter();
496 const int result = fs_client_put_page(fs->rpc_server, &req, &resp);
497 profile_leave(pp, "userfs.'%s'.putpage", userfs->rpc_server_name);
498
501
502 if (result != RPC_RESULT_OK)
503 {
504 mWarn << "userfs_inode_cache_flush_page: failed to putpage: " << result;
505 return -EIO;
506 }
507
508 if (!resp.result.success)
509 {
510 dWarn<userfs> << "userfs_inode_cache_flush_page: failed to putpage: " << resp.result.error;
511 return -EIO;
512 }
513
514 return 0;
515}
516
518 .fill_cache = userfs_inode_cache_fill_cache,
519 .page_write_begin = simple_page_write_begin,
520 .page_write_end = simple_page_write_end,
521 .flush_page = userfs_inode_cache_flush_page,
522};
523
525{
526 userfs_t *fs = userfs_get(inode->superblock->fs, "sync_inode: %llu", inode->ino);
527
529 req.i_ref = i_to_pb_ref(inode);
530 req.i_info = *i_to_pb_full(inode, &req.i_info);
531
533 const pf_point_t pp = profile_enter();
534 const int result = fs_client_sync_inode(fs->rpc_server, &req, &resp);
535 profile_leave(pp, "userfs.'%s'.sync_inode", userfs->rpc_server_name);
536
537 if (result != RPC_RESULT_OK)
538 {
539 mWarn << "userfs_sync_inode: failed to sync inode " << inode->ino << ": " << result;
540 return -EIO;
541 }
542
543 if (!resp.result.success)
544 {
545 dWarn<userfs> << "userfs_sync_inode: failed to sync inode " << inode->ino << ": " << resp.result.error;
546 return -EIO;
547 }
548
549 return 0;
550}
551
553 .drop_inode = NULL,
554 .sync_inode = userfs_sync_inode,
555};
556
557PtrResult<dentry_t> userfs_fsop_mount(filesystem_t *fs, const char *device, const char *options)
558{
559 userfs_t *userfs = userfs_get(fs, "mount", fs->name);
560
561 const mosrpc_fs_mount_request req = {
562 .fs_name = (char *) fs->name.c_str(),
563 .device = (char *) device,
564 .options = (char *) options,
565 };
566
567 mosrpc_fs_mount_response resp = {};
568
569 const pf_point_t pp = profile_enter();
570 const int result = fs_client_mount(userfs->rpc_server, &req, &resp);
571 profile_leave(pp, "userfs.'%s'.mount", userfs->rpc_server_name);
572
574
575 if (result != RPC_RESULT_OK)
576 {
577 mWarn << "userfs_fsop_mount: failed to mount " << fs->name << ": " << result;
578 return -EIO;
579 }
580
581 if (!resp.result.success)
582 {
583 mWarn << "userfs_fsop_mount: failed to mount " << fs->name << ": " << resp.result.error;
584 return -EIO;
585 }
586
588 sb->ops = &userfs_sb_ops;
589
590 inode_t *i = i_from_pbfull(&resp.root_info, sb, (void *) resp.root_ref.data);
591
592 sb->fs = fs;
594 sb->root->superblock = i->superblock = sb;
595 dentry_attach(sb->root, i);
596 return sb->root;
597}
#define MOS_ASSERT(cond)
Definition assert.hpp:19
#define MOS_PAGE_SIZE
Definition autoconf.h:6
const Char * c_str() const
Definition string.hpp:259
#define mosrpc_fs_create_file_response_fields
#define mosrpc_fs_readlink_response_fields
#define mosrpc_fs_putpage_response_fields
#define mosrpc_fs_putpage_request_fields
#define mosrpc_fs_unlink_response_fields
#define mosrpc_fs_mount_response_fields
#define mosrpc_fs_getpage_response_fields
#define mosrpc_fs_lookup_response_fields
#define mosrpc_fs_make_dir_response_fields
#define mosrpc_fs_readdir_response_fields
u16 file_perm_t
Definition fs_types.h:52
file_type_t
Definition fs_types.h:14
void dentry_attach(dentry_t *d, inode_t *inode)
Attach an inode to a dentry.
Definition dentry.cpp:279
#define phyframe_va(frame)
Definition mm.hpp:86
phyframe_t * mm_get_free_page(void)
Definition mm.cpp:38
#define pmm_ref_one(thing)
Definition pmm.hpp:159
inode_t * inode_create(superblock_t *sb, u64 ino, file_type_t type)
Definition inode.cpp:59
static vmap_global_mstat_t stat[_MEM_MAX_TYPES]
Definition mmstat.cpp:22
#define likely(x)
Definition mos_global.h:39
#define MOS_UNUSED(x)
Definition mos_global.h:65
#define unlikely(x)
Definition mos_global.h:40
T * create(Args &&...args)
Definition allocator.hpp:12
#define uint64_t
uint_least16_t pb_size_t
Definition pb.h:330
#define PB_BYTES_ARRAY_T_ALLOCSIZE(n)
Definition pb.h:397
void pb_release(const pb_msgdesc_t *fields, void *dest_struct)
Definition pb_decode.c:1355
static void * memcpy(void *s1, const void *s2, size_t n)
Definition pb_syshdr.h:90
#define NULL
Definition pb_syshdr.h:46
static size_t strlen(const char *s)
Definition pb_syshdr.h:80
#define profile_enter()
Definition profiling.hpp:33
u64 pf_point_t
Definition profiling.hpp:8
#define profile_leave(p,...)
Definition profiling.hpp:35
@ RPC_RESULT_OK
Definition rpc.h:26
MOSAPI rpc_server_stub_t * rpc_client_create(const char *server_name)
Create a new RPC client stub for the given server.
const char * name
Definition slab.cpp:33
void skip()
Definition userfs.cpp:48
const pb_msgdesc_t *const fields
Definition userfs.cpp:45
void * data
Definition userfs.cpp:46
AutoCleanup(const pb_msgdesc_t *fields, void *data)
Definition userfs.cpp:53
superblock_t * superblock
inode_t * inode
mos::string name
inode_t * owner
const inode_cache_ops_t * ops
superblock_t * superblock
uid_t uid
u64 modified
u64 accessed
u64 created
file_perm_t perm
const inode_ops_t * ops
bool sgid
size_t size
file_type_t type
const file_ops_t * file_ops
bool suid
inode_cache_t cache
bool sticky
gid_t gid
void * private_data
ssize_t nlinks
mosrpc_fs_inode_info i_info
pb_bytes_array_t * data
mosrpc_fs_inode_info i_info
mosrpc_fs_inode_ref i_ref
mosrpc_fs_inode_info i_info
mosrpc_fs_inode_ref i_ref
mosrpc_fs_inode_info root_info
mosrpc_fs_inode_ref root_ref
pb_bytes_array_t * data
struct _mosrpc_fs_pb_dirent * entries
mosrpc_fs_inode_info i_info
mosrpc_fs_inode_ref i_ref
char * error
Definition mosrpc.pb.h:15
dentry_t * root
const superblock_ops_t * ops
filesystem_t * fs
mos::string rpc_server_name
The name of the RPC server.
Definition userfs.hpp:14
rpc_server_stub_t * rpc_server
The RPC server stub, if connected.
Definition userfs.hpp:15
constexpr auto dInfo2
Definition syslog.hpp:151
constexpr auto mWarn
Definition syslog.hpp:154
constexpr auto dWarn
Definition syslog.hpp:154
static char buffer[2048]
unsigned long ptr_t
Definition types.h:21
#define container_of(ptr, type, member)
Definition types.hpp:33
long userfs_inode_cache_flush_page(inode_cache_t *cache, uint64_t pgoff, phyframe_t *page)
Definition userfs.cpp:480
static bool userfs_iop_symlink(inode_t *dir, dentry_t *dentry, const char *symname)
Definition userfs.cpp:360
static bool userfs_iop_rename(inode_t *old_dir, dentry_t *old_dentry, inode_t *new_dir, dentry_t *new_dentry)
Definition userfs.cpp:333
const superblock_ops_t userfs_sb_ops
Definition userfs.cpp:552
void userfs_ensure_connected(userfs_t *userfs)
Ensure that the userfs is connected to the server.
Definition userfs.cpp:107
userfs_t * userfs_get(filesystem_t *fs, TPrint... print)
Definition userfs.cpp:34
mosrpc_fs_inode_info * i_to_pb_full(const inode_t *i, mosrpc_fs_inode_info *pbi)
Convert a kernel inode to a protobuf inode.
Definition userfs.cpp:82
const inode_ops_t userfs_iops
Definition userfs.cpp:405
mosrpc_fs_inode_ref i_to_pb_ref(const inode_t *i)
Definition userfs.cpp:101
static bool userfs_iop_mkdir(inode_t *dir, dentry_t *dentry, file_perm_t perm)
Definition userfs.cpp:203
static bool userfs_iop_rmdir(inode_t *dir, dentry_t *dentry)
Definition userfs.cpp:348
static size_t userfs_iop_readlink(dentry_t *dentry, char *buffer, size_t buflen)
Definition userfs.cpp:297
static bool userfs_iop_mknode(inode_t *dir, dentry_t *dentry, file_type_t type, file_perm_t perm, dev_t dev)
Definition userfs.cpp:242
const inode_cache_ops_t userfs_inode_cache_ops
Definition userfs.cpp:517
long userfs_sync_inode(inode_t *inode)
Definition userfs.cpp:524
const file_ops_t userfs_fops
Definition userfs.cpp:428
static void userfs_iop_iterate_dir(dentry_t *dentry, vfs_listdir_state_t *state, dentry_iterator_op add_record)
Definition userfs.cpp:132
static bool userfs_fop_open(inode_t *inode, FsBaseFile *file, bool created)
Definition userfs.cpp:419
static PtrResult< phyframe_t > userfs_inode_cache_fill_cache(inode_cache_t *cache, uint64_t pgoff)
Definition userfs.cpp:438
static bool userfs_iop_unlink(inode_t *dir, dentry_t *dentry)
Definition userfs.cpp:373
static bool userfs_iop_newfile(inode_t *dir, dentry_t *dentry, file_type_t type, file_perm_t perm)
Definition userfs.cpp:257
static bool userfs_iop_lookup(inode_t *dir, dentry_t *dentry)
Definition userfs.cpp:166
PtrResult< dentry_t > userfs_fsop_mount(filesystem_t *fs, const char *device, const char *options)
Definition userfs.cpp:557
inode_t * i_from_pbfull(const mosrpc_fs_inode_info *stat, superblock_t *sb, void *private_data)
Convert a protobuf inode to a kernel inode.
Definition userfs.cpp:61
static bool userfs_iop_hardlink(dentry_t *d, inode_t *i, dentry_t *new_d)
Definition userfs.cpp:120
mos::string dentry_name(const dentry_t *dentry)
void dentry_iterator_op(vfs_listdir_state_t *state, u64 ino, mos::string_view name, file_type_t type)
Definition vfs_types.hpp:64
dentry_t * dentry_get_from_parent(superblock_t *sb, dentry_t *parent, mos::string_view name)
Create a new dentry with the given name and parent.
Definition vfs_utils.cpp:37
bool simple_page_write_begin(inode_cache_t *icache, off_t offset, size_t size, phyframe_t **page, void **private_)
Definition vfs_utils.cpp:62
ssize_t vfs_generic_read(const FsBaseFile *file, void *buf, size_t size, off_t offset)
Definition vfs_utils.cpp:93
void simple_page_write_end(inode_cache_t *icache, off_t offset, size_t size, phyframe_t *page, void *private_)
Definition vfs_utils.cpp:74
ssize_t vfs_generic_write(const FsBaseFile *file, const void *buf, size_t size, off_t offset)