1 /*
2  * Copyright (c) 2024, Google Inc. All rights reserved.
3  * Author: codycswong@google.com (Cody Wong)
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files
7  * (the "Software"), to deal in the Software without restriction,
8  * including without limitation the rights to use, copy, modify, merge,
9  * publish, distribute, sublicense, and/or sell copies of the Software,
10  * and to permit persons to whom the Software is furnished to do so,
11  * subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 #include <dev/virtio/9p.h>
25 #include <lib/fs.h>
26 #include <lk/list.h>
27 #include <kernel/mutex.h>
28 
29 typedef struct v9fs_fid {
30     uint32_t fid;
31     uint32_t iounit;
32     virtio_9p_qid_t qid;
33 } v9fs_fid_t;
34 
35 typedef struct v9fs {
36     struct virtio_device *dev;
37     bdev_t *bdev;
38 
39     uint32_t unused_fid;
40     v9fs_fid_t root;
41     mutex_t lock;
42 
43     struct list_node files;
44     struct list_node dirs;
45 } v9fs_t;
46 
47 #define V9FS_FILE_PAGE_BUFFER_SIZE (1 << 12)
48 #define V9FS_FILE_LOCK_TIMEOUT 3000
49 
50 typedef struct v9fs_file {
51     v9fs_t *v9fs;
52     v9fs_fid_t fid;
53 
54     struct list_node node;
55     mutex_t lock;
56 
57     struct fs_page_buffer {
58         size_t size;
59         off_t index;
60         bool need_update;
61         bool dirty;
62         uint8_t data[V9FS_FILE_PAGE_BUFFER_SIZE];
63     } pg_buf;
64 } v9fs_file_t;
65 
66 typedef struct v9fs_dir {
67     v9fs_t *v9fs;
68     v9fs_fid_t fid;
69     uint64_t offset;
70 
71     uint32_t head;
72     uint32_t tail;
73     uint8_t data[PAGE_SIZE];
74 
75     struct list_node node;
76 } v9fs_dir_t;
77 
78 status_t v9fs_mount(bdev_t *dev, fscookie **cookie);
79 status_t v9fs_unmount(fscookie *cookie);
80 status_t v9fs_open_file(fscookie *cookie, const char *path,
81                         filecookie **fcookie);
82 status_t v9fs_create_file(fscookie *cookie, const char *path,
83                           filecookie **fcookie, uint64_t len);
84 ssize_t v9fs_read_file(filecookie *fcookie, void *buf, off_t offset,
85                        size_t len);
86 ssize_t v9fs_write_file(filecookie *fcookie, const void *buf, off_t offset,
87                         size_t len);
88 status_t v9fs_close_file(filecookie *fcookie);
89 status_t v9fs_stat_file(filecookie *fcookie, struct file_stat *stat);
90 status_t v9fs_open_dir(fscookie *cookie, const char *path, dircookie **dcookie);
91 status_t v9fs_mkdir(fscookie *cookie, const char *path);
92 status_t v9fs_read_dir(dircookie *dcookie, struct dirent *ent);
93 status_t v9fs_close_dir(dircookie *dcookie);
94 
95 status_t path_to_wname(char *path, uint16_t *nwname, const char *wname[P9_MAXWELEM]) __NONNULL((1)) __NONNULL((2));
96 uint32_t get_unused_fid(v9fs_t *v9fs);
97 void put_fid(v9fs_t *v9fs, uint32_t fid);
98