Rev 4420 | Rev 4537 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 4420 | Rev 4439 | ||
|---|---|---|---|
| Line 72... | Line 72... | ||
| 72 | * This rwlock prevents the race between a triplet-to-VFS-node resolution and a |
72 | * This rwlock prevents the race between a triplet-to-VFS-node resolution and a |
| 73 | * concurrent VFS operation which modifies the file system namespace. |
73 | * concurrent VFS operation which modifies the file system namespace. |
| 74 | */ |
74 | */ |
| 75 | RWLOCK_INITIALIZE(namespace_rwlock); |
75 | RWLOCK_INITIALIZE(namespace_rwlock); |
| 76 | 76 | ||
| 77 | futex_t rootfs_futex = FUTEX_INITIALIZER; |
- | |
| 78 | vfs_pair_t rootfs = { |
77 | vfs_pair_t rootfs = { |
| 79 | .fs_handle = 0, |
78 | .fs_handle = 0, |
| 80 | .dev_handle = 0 |
79 | .dev_handle = 0 |
| 81 | }; |
80 | }; |
| 82 | 81 | ||
| Line 93... | Line 92... | ||
| 93 | ipcarg_t rc; |
92 | ipcarg_t rc; |
| 94 | int phone; |
93 | int phone; |
| 95 | aid_t msg; |
94 | aid_t msg; |
| 96 | ipc_call_t answer; |
95 | ipc_call_t answer; |
| 97 | 96 | ||
| 98 | - | ||
| 99 | /* Resolve the path to the mountpoint. */ |
97 | /* Resolve the path to the mountpoint. */ |
| 100 | futex_down(&rootfs_futex); |
98 | rwlock_write_lock(&namespace_rwlock); |
| 101 | if (rootfs.fs_handle) { |
99 | if (rootfs.fs_handle) { |
| 102 | /* We already have the root FS. */ |
100 | /* We already have the root FS. */ |
| 103 | rwlock_write_lock(&namespace_rwlock); |
- | |
| 104 | if (str_cmp(mp, "/") == 0) { |
101 | if (str_cmp(mp, "/") == 0) { |
| 105 | /* Trying to mount root FS over root FS */ |
102 | /* Trying to mount root FS over root FS */ |
| 106 | rwlock_write_unlock(&namespace_rwlock); |
- | |
| 107 | futex_up(&rootfs_futex); |
- | |
| 108 | ipc_answer_0(rid, EBUSY); |
103 | ipc_answer_0(rid, EBUSY); |
| - | 104 | rwlock_write_unlock(&namespace_rwlock); |
|
| 109 | return; |
105 | return; |
| 110 | } |
106 | } |
| 111 | 107 | ||
| 112 | rc = vfs_lookup_internal(mp, L_DIRECTORY, &mp_res, NULL); |
108 | rc = vfs_lookup_internal(mp, L_DIRECTORY, &mp_res, NULL); |
| 113 | if (rc != EOK) { |
109 | if (rc != EOK) { |
| 114 | /* The lookup failed for some reason. */ |
110 | /* The lookup failed for some reason. */ |
| 115 | rwlock_write_unlock(&namespace_rwlock); |
- | |
| 116 | futex_up(&rootfs_futex); |
- | |
| 117 | ipc_answer_0(rid, rc); |
111 | ipc_answer_0(rid, rc); |
| - | 112 | rwlock_write_unlock(&namespace_rwlock); |
|
| 118 | return; |
113 | return; |
| 119 | } |
114 | } |
| 120 | 115 | ||
| 121 | mp_node = vfs_node_get(&mp_res); |
116 | mp_node = vfs_node_get(&mp_res); |
| 122 | if (!mp_node) { |
117 | if (!mp_node) { |
| 123 | rwlock_write_unlock(&namespace_rwlock); |
- | |
| 124 | futex_up(&rootfs_futex); |
- | |
| 125 | ipc_answer_0(rid, ENOMEM); |
118 | ipc_answer_0(rid, ENOMEM); |
| - | 119 | rwlock_write_unlock(&namespace_rwlock); |
|
| 126 | return; |
120 | return; |
| 127 | } |
121 | } |
| 128 | 122 | ||
| 129 | /* |
123 | /* |
| 130 | * Now we hold a reference to mp_node. |
124 | * Now we hold a reference to mp_node. |
| 131 | * It will be dropped upon the corresponding VFS_UNMOUNT. |
125 | * It will be dropped upon the corresponding VFS_UNMOUNT. |
| 132 | * This prevents the mount point from being deleted. |
126 | * This prevents the mount point from being deleted. |
| 133 | */ |
127 | */ |
| 134 | rwlock_write_unlock(&namespace_rwlock); |
- | |
| 135 | } else { |
128 | } else { |
| 136 | /* We still don't have the root file system mounted. */ |
129 | /* We still don't have the root file system mounted. */ |
| 137 | if (str_cmp(mp, "/") == 0) { |
130 | if (str_cmp(mp, "/") == 0) { |
| 138 | /* |
131 | /* |
| 139 | * For this simple, but important case, |
132 | * For this simple, but important case, |
| Line 148... | Line 141... | ||
| 148 | rc = ipc_data_write_start(phone, (void *)opts, |
141 | rc = ipc_data_write_start(phone, (void *)opts, |
| 149 | str_size(opts)); |
142 | str_size(opts)); |
| 150 | if (rc != EOK) { |
143 | if (rc != EOK) { |
| 151 | async_wait_for(msg, NULL); |
144 | async_wait_for(msg, NULL); |
| 152 | vfs_release_phone(phone); |
145 | vfs_release_phone(phone); |
| 153 | futex_up(&rootfs_futex); |
- | |
| 154 | ipc_answer_0(rid, rc); |
146 | ipc_answer_0(rid, rc); |
| - | 147 | rwlock_write_unlock(&namespace_rwlock); |
|
| 155 | return; |
148 | return; |
| 156 | } |
149 | } |
| 157 | async_wait_for(msg, &rc); |
150 | async_wait_for(msg, &rc); |
| 158 | vfs_release_phone(phone); |
151 | vfs_release_phone(phone); |
| 159 | 152 | ||
| 160 | if (rc != EOK) { |
153 | if (rc != EOK) { |
| 161 | futex_up(&rootfs_futex); |
- | |
| 162 | ipc_answer_0(rid, rc); |
154 | ipc_answer_0(rid, rc); |
| - | 155 | rwlock_write_unlock(&namespace_rwlock); |
|
| 163 | return; |
156 | return; |
| 164 | } |
157 | } |
| 165 | 158 | ||
| 166 | rindex = (fs_index_t) IPC_GET_ARG1(answer); |
159 | rindex = (fs_index_t) IPC_GET_ARG1(answer); |
| 167 | rsize = (size_t) IPC_GET_ARG2(answer); |
160 | rsize = (size_t) IPC_GET_ARG2(answer); |
| Line 174... | Line 167... | ||
| 174 | mr_res.lnkcnt = rlnkcnt; |
167 | mr_res.lnkcnt = rlnkcnt; |
| 175 | mr_res.type = VFS_NODE_DIRECTORY; |
168 | mr_res.type = VFS_NODE_DIRECTORY; |
| 176 | 169 | ||
| 177 | rootfs.fs_handle = fs_handle; |
170 | rootfs.fs_handle = fs_handle; |
| 178 | rootfs.dev_handle = dev_handle; |
171 | rootfs.dev_handle = dev_handle; |
| 179 | futex_up(&rootfs_futex); |
- | |
| 180 | 172 | ||
| 181 | /* Add reference to the mounted root. */ |
173 | /* Add reference to the mounted root. */ |
| 182 | mr_node = vfs_node_get(&mr_res); |
174 | mr_node = vfs_node_get(&mr_res); |
| 183 | assert(mr_node); |
175 | assert(mr_node); |
| 184 | 176 | ||
| 185 | ipc_answer_0(rid, rc); |
177 | ipc_answer_0(rid, rc); |
| - | 178 | rwlock_write_unlock(&namespace_rwlock); |
|
| 186 | return; |
179 | return; |
| 187 | } else { |
180 | } else { |
| 188 | /* |
181 | /* |
| 189 | * We can't resolve this without the root filesystem |
182 | * We can't resolve this without the root filesystem |
| 190 | * being mounted first. |
183 | * being mounted first. |
| 191 | */ |
184 | */ |
| 192 | futex_up(&rootfs_futex); |
- | |
| 193 | ipc_answer_0(rid, ENOENT); |
185 | ipc_answer_0(rid, ENOENT); |
| - | 186 | rwlock_write_unlock(&namespace_rwlock); |
|
| 194 | return; |
187 | return; |
| 195 | } |
188 | } |
| 196 | } |
189 | } |
| 197 | futex_up(&rootfs_futex); |
- | |
| 198 | 190 | ||
| 199 | /* |
191 | /* |
| 200 | * At this point, we have all necessary pieces: file system and device |
192 | * At this point, we have all necessary pieces: file system and device |
| 201 | * handles, and we know the mount point VFS node. |
193 | * handles, and we know the mount point VFS node. |
| 202 | */ |
194 | */ |
| Line 219... | Line 211... | ||
| 219 | vfs_release_phone(phone); |
211 | vfs_release_phone(phone); |
| 220 | /* Mount failed, drop reference to mp_node. */ |
212 | /* Mount failed, drop reference to mp_node. */ |
| 221 | if (mp_node) |
213 | if (mp_node) |
| 222 | vfs_node_put(mp_node); |
214 | vfs_node_put(mp_node); |
| 223 | ipc_answer_0(rid, rc); |
215 | ipc_answer_0(rid, rc); |
| - | 216 | rwlock_write_unlock(&namespace_rwlock); |
|
| 224 | return; |
217 | return; |
| 225 | } |
218 | } |
| 226 | 219 | ||
| 227 | /* send the mount options */ |
220 | /* send the mount options */ |
| 228 | rc = ipc_data_write_start(phone, (void *)opts, str_size(opts)); |
221 | rc = ipc_data_write_start(phone, (void *)opts, str_size(opts)); |
| Line 231... | Line 224... | ||
| 231 | vfs_release_phone(phone); |
224 | vfs_release_phone(phone); |
| 232 | /* Mount failed, drop reference to mp_node. */ |
225 | /* Mount failed, drop reference to mp_node. */ |
| 233 | if (mp_node) |
226 | if (mp_node) |
| 234 | vfs_node_put(mp_node); |
227 | vfs_node_put(mp_node); |
| 235 | ipc_answer_0(rid, rc); |
228 | ipc_answer_0(rid, rc); |
| - | 229 | rwlock_write_unlock(&namespace_rwlock); |
|
| 236 | return; |
230 | return; |
| 237 | } |
231 | } |
| 238 | async_wait_for(msg, &rc); |
232 | async_wait_for(msg, &rc); |
| 239 | vfs_release_phone(phone); |
233 | vfs_release_phone(phone); |
| 240 | 234 | ||
| 241 | if (rc != EOK) { |
235 | if (rc == EOK) { |
| - | 236 | rindex = (fs_index_t) IPC_GET_ARG1(answer); |
|
| - | 237 | rsize = (size_t) IPC_GET_ARG2(answer); |
|
| - | 238 | rlnkcnt = (unsigned) IPC_GET_ARG3(answer); |
|
| - | 239 | ||
| - | 240 | mr_res.triplet.fs_handle = fs_handle; |
|
| - | 241 | mr_res.triplet.dev_handle = dev_handle; |
|
| - | 242 | mr_res.triplet.index = rindex; |
|
| - | 243 | mr_res.size = rsize; |
|
| - | 244 | mr_res.lnkcnt = rlnkcnt; |
|
| - | 245 | mr_res.type = VFS_NODE_DIRECTORY; |
|
| - | 246 | ||
| - | 247 | /* Add reference to the mounted root. */ |
|
| - | 248 | mr_node = vfs_node_get(&mr_res); |
|
| - | 249 | assert(mr_node); |
|
| - | 250 | } else { |
|
| 242 | /* Mount failed, drop reference to mp_node. */ |
251 | /* Mount failed, drop reference to mp_node. */ |
| 243 | if (mp_node) |
252 | if (mp_node) |
| 244 | vfs_node_put(mp_node); |
253 | vfs_node_put(mp_node); |
| 245 | } |
254 | } |
| 246 | - | ||
| 247 | rindex = (fs_index_t) IPC_GET_ARG1(answer); |
- | |
| 248 | rsize = (size_t) IPC_GET_ARG2(answer); |
- | |
| 249 | rlnkcnt = (unsigned) IPC_GET_ARG3(answer); |
- | |
| 250 | - | ||
| 251 | mr_res.triplet.fs_handle = fs_handle; |
- | |
| 252 | mr_res.triplet.dev_handle = dev_handle; |
- | |
| 253 | mr_res.triplet.index = rindex; |
- | |
| 254 | mr_res.size = rsize; |
- | |
| 255 | mr_res.lnkcnt = rlnkcnt; |
- | |
| 256 | mr_res.type = VFS_NODE_DIRECTORY; |
- | |
| 257 | - | ||
| 258 | /* Add reference to the mounted root. */ |
- | |
| 259 | mr_node = vfs_node_get(&mr_res); |
- | |
| 260 | assert(mr_node); |
- | |
| 261 | 255 | ||
| 262 | ipc_answer_0(rid, rc); |
256 | ipc_answer_0(rid, rc); |
| - | 257 | rwlock_write_unlock(&namespace_rwlock); |
|
| 263 | } |
258 | } |
| 264 | 259 | ||
| 265 | /** Process pending mount requests */ |
260 | /** Process pending mount requests */ |
| 266 | void vfs_process_pending_mount() |
261 | void vfs_process_pending_mount(void) |
| 267 | { |
262 | { |
| 268 | link_t *cur; |
263 | link_t *cur; |
| 269 | 264 | ||
| 270 | loop: |
265 | loop: |
| 271 | for (cur = pending_req.next; cur != &pending_req; cur = cur->next) { |
266 | for (cur = pending_req.next; cur != &pending_req; cur = cur->next) { |
| Line 1028... | Line 1023... | ||
| 1028 | ipc_answer_0(rid, rc); |
1023 | ipc_answer_0(rid, rc); |
| 1029 | free(old); |
1024 | free(old); |
| 1030 | free(new); |
1025 | free(new); |
| 1031 | return; |
1026 | return; |
| 1032 | } |
1027 | } |
| 1033 | char *lastsl = str_rchr(parentc + 1, L'/'); |
1028 | char *lastsl = str_rchr(parentc + 1, '/'); |
| 1034 | if (lastsl) |
1029 | if (lastsl) |
| 1035 | *lastsl = '\0'; |
1030 | *lastsl = '\0'; |
| 1036 | else |
1031 | else |
| 1037 | parentc[1] = '\0'; |
1032 | parentc[1] = '\0'; |
| 1038 | /* Lookup parent of the new file name. */ |
1033 | /* Lookup parent of the new file name. */ |