Rev 4427 | Rev 4443 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4427 | Rev 4431 | ||
---|---|---|---|
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() |
267 | { |
262 | { |