• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Institute of Parallel And Distributed Systems (IPADS), Shanghai Jiao Tong University (SJTU)
3  * Licensed under the Mulan PSL v2.
4  * You can use this software according to the terms and conditions of the Mulan PSL v2.
5  * You may obtain a copy of Mulan PSL v2 at:
6  *     http://license.coscl.org.cn/MulanPSL2
7  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8  * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9  * PURPOSE.
10  * See the Mulan PSL v2 for more details.
11  */
12 
13 #include <chcore/syscall.h>
14 #include <chcore-internal/fs_defs.h>
15 #include <chcore/container/list.h>
16 #include <assert.h>
17 #include <chcore/idman.h>
18 #include <malloc.h>
19 #include <chcore/ipc.h>
20 #include <fcntl.h>
21 #include <string.h>
22 #include <chcore-internal/fs_debug.h>
23 #include <pthread.h>
24 
25 #include "fs_client_defs.h"
26 
27 /* CWD */
28 char cwd_path[MAX_CWD_BUF_LEN];
29 int cwd_len;
30 
31 /* For client side mounted fs metadata */
32 cap_t mounted_fs_cap[MAX_MOUNT_ID] = {-1};
33 pthread_key_t mounted_fs_key;
34 
get_ipc_struct_by_mount_id(int mount_id)35 ipc_struct_t *get_ipc_struct_by_mount_id(int mount_id)
36 {
37     ipc_struct_t **mounted_fs_ipc_struct;
38     ipc_struct_t *res;
39 
40     /* Get thread local  */
41     mounted_fs_ipc_struct = pthread_getspecific(mounted_fs_key);
42     if (!mounted_fs_ipc_struct) {
43         mounted_fs_ipc_struct =
44             calloc(1, MAX_MOUNT_ID * sizeof(ipc_struct_t *));
45         BUG_ON(!mounted_fs_ipc_struct);
46         pthread_setspecific(mounted_fs_key, mounted_fs_ipc_struct);
47     }
48 
49     /* Find thread local ipc struct, register one if it's not existed */
50     if (!mounted_fs_ipc_struct[mount_id]) {
51         mounted_fs_ipc_struct[mount_id] =
52             ipc_register_client(mounted_fs_cap[mount_id]);
53         BUG_ON(!mounted_fs_ipc_struct[mount_id]);
54     }
55 
56     res = mounted_fs_ipc_struct[mount_id];
57 
58     /* Do sanity check here. */
59     BUG_ON(!res);
60     return res;
61 }
62 
disconnect_mounted_fs(void)63 void disconnect_mounted_fs(void)
64 {
65     int i;
66     ipc_struct_t **mounted_fs_ipc_struct;
67     /* Get thread local  */
68     mounted_fs_ipc_struct = pthread_getspecific(mounted_fs_key);
69     if (!mounted_fs_ipc_struct) {
70         return;
71     }
72 
73     for (i = 0; i < MAX_MOUNT_ID; i++) {
74         if (mounted_fs_ipc_struct[i]) {
75             ipc_client_close_connection(mounted_fs_ipc_struct[i]);
76         }
77     }
78 
79     free(mounted_fs_ipc_struct);
80 }
81 
82 /*
83  * Copy path to dst, dst_buf_size is dst's buffer size,
84  * return: -1 means dst_buf_size is not large enough,
85  *	  0 mean operation succeed.
86  */
pathcpy(char * dst,size_t dst_buf_size,const char * path,size_t path_len)87 int pathcpy(char *dst, size_t dst_buf_size, const char *path, size_t path_len)
88 {
89     if (dst_buf_size >= path_len + 1) {
90         memset(dst, 0, dst_buf_size);
91         strncpy(dst, path, path_len + 1);
92     } else {
93         return -1;
94     }
95 
96     dst[path_len] = '\0';
97     return 0;
98 }
99 
100 /* ++++++++++++++++++++++++ File Descriptor Extension ++++++++++++++++++++++ */
101 
_new_fd_record_extension(void)102 struct fd_record_extension *_new_fd_record_extension(void)
103 {
104     struct fd_record_extension *ret;
105     ret = (struct fd_record_extension *)calloc(1, sizeof(*ret));
106     if (ret == NULL) {
107         return NULL;
108     }
109     ret->mount_id = -1;
110     return ret;
111 }
112 
113 /* ++++++++++++++++++++++++ Path Resolution ++++++++++++++++++++++++++++++++ */
114 
path_from_fd(int fd)115 char *path_from_fd(int fd)
116 {
117     struct fd_record_extension *fd_ext;
118 
119     if (fd == AT_FDCWD)
120         return cwd_path;
121     else if (fd == AT_FDROOT)
122         return "/";
123 
124     fd_ext = (struct fd_record_extension *)fd_dic[fd]->private_data;
125 
126     return fd_ext->path;
127 }
128 
129 #define PATH_JOIN_SEPERATOR "/"
130 
__str_starts_with(const char * str,const char * start)131 static bool __str_starts_with(const char *str, const char *start)
132 {
133     for (;; str++, start++)
134         if (!*start)
135             return true;
136         else if (*str != *start)
137             return false;
138 }
139 
__str_ends_with(const char * str,const char * end)140 static bool __str_ends_with(const char *str, const char *end)
141 {
142     int end_len;
143     int str_len;
144 
145     if (NULL == str || NULL == end)
146         return false;
147 
148     end_len = strlen(end);
149     str_len = strlen(str);
150 
151     return str_len < end_len ? false : !strcmp(str + str_len - end_len, end);
152 }
153 
path_join(const char * dir,const char * file)154 char *path_join(const char *dir, const char *file)
155 {
156     char *filecopy;
157     int size;
158     char *buf;
159 
160     if (!dir)
161         dir = "\0";
162     if (!file)
163         file = "\0";
164 
165     size = strlen(dir) + strlen(file) + 2;
166     buf = malloc(size * sizeof(char));
167     if (NULL == buf)
168         return NULL;
169 
170     strcpy(buf, dir);
171 
172     /* add the sep if necessary */
173     if (!__str_ends_with(dir, PATH_JOIN_SEPERATOR))
174         strcat(buf, PATH_JOIN_SEPERATOR);
175 
176     /* remove the sep if necessary */
177     if (__str_starts_with(file, PATH_JOIN_SEPERATOR)) {
178         filecopy = strdup(file);
179         if (NULL == filecopy) {
180             free(buf);
181             return NULL;
182         }
183         strcat(buf, ++filecopy);
184         free(--filecopy);
185     } else {
186         strcat(buf, file);
187     }
188 
189     return buf;
190 }
191 
192 /* ++++++++++++++++++++++++++ IPC lib for FSM ++++++++++++++++++++++++++++++ */
193 
194 /*
195  * ipc_msg is FSM ipc message, and should be created outside
196  * return: fsm_req = ipc_msg_data(ipc_msg)
197  *	 fsm_req->mount_id = corresponding fs_server mount_id
198  *	 fsm_req->mount_path/path_len = corresponding fs_server mount_point
199  */
fsm_parse_path_forward(ipc_msg_t * ipc_msg,const char * full_path)200 struct fsm_request *fsm_parse_path_forward(ipc_msg_t *ipc_msg,
201                                            const char *full_path)
202 {
203     struct fsm_request *fsm_req;
204     ipc_struct_t **mounted_fs_ipc_structs;
205     int mount_id;
206     int ret;
207 
208     fsm_req = (struct fsm_request *)ipc_get_msg_data(ipc_msg);
209 
210     /* Send ipc to FSM */
211     fsm_req->req = FSM_REQ_PARSE_PATH;
212     if (pathcpy(fsm_req->path, FS_REQ_PATH_BUF_LEN, full_path, strlen(full_path))
213         != 0)
214         return NULL;
215 
216     BUG_ON(!fsm_ipc_struct);
217     ret = ipc_call(fsm_ipc_struct, ipc_msg);
218     if (ret < 0) {
219         return NULL;
220     }
221 
222     /* Bind mount_id and cap. */
223     mount_id = fsm_req->mount_id;
224     if (fsm_req->new_cap_flag) {
225         assert(mount_id >= 0 && mount_id < MAX_MOUNT_ID);
226         mounted_fs_cap[mount_id] = ipc_get_msg_cap(ipc_msg, 0);
227     }
228 
229     assert(mounted_fs_cap[mount_id] > 0);
230 
231     /* Call this for initialize tls ipc data, and we don't need return value
232      */
233     get_ipc_struct_by_mount_id(mount_id);
234 
235     return fsm_req;
236 }
237 
238 /* ++++++++++++++++++++++++++++++++ Others +++++++++++++++++++++++++++++++++ */
239 
init_fs_client_side(void)240 void init_fs_client_side(void)
241 {
242     pthread_key_create(&mounted_fs_key, NULL);
243 
244     /* Initialize cwd as ROOT */
245     cwd_path[0] = '/';
246     cwd_path[1] = '\0';
247     cwd_len = 1;
248 }
249