Changeset 8dc72b64 in mainline for uspace/srv/vfs/vfs_ops.c
- Timestamp:
- 2009-03-02T17:37:19Z (16 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 16da5f8e
- Parents:
- 6519d6f
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/vfs/vfs_ops.c
r6519d6f r8dc72b64 29 29 /** @addtogroup fs 30 30 * @{ 31 */ 31 */ 32 32 33 33 /** 34 * @file 35 * @brief 34 * @file vfs_ops.c 35 * @brief Operations that VFS offers to its clients. 36 36 */ 37 37 … … 56 56 static int vfs_truncate_internal(fs_handle_t, dev_handle_t, fs_index_t, size_t); 57 57 58 /** Pending mount structure. */ 59 typedef struct { 60 link_t link; 61 char *fs_name; /**< File system name */ 62 char *mp; /**< Mount point */ 63 ipc_callid_t callid; /**< Call ID waiting for the mount */ 64 ipc_callid_t rid; /**< Request ID */ 65 dev_handle_t dev_handle; /**< Device handle */ 66 } pending_req_t; 67 68 LIST_INITIALIZE(pending_req); 69 58 70 /** 59 71 * This rwlock prevents the race between a triplet-to-VFS-node resolution and a … … 68 80 }; 69 81 70 void vfs_mount(ipc_callid_t rid, ipc_call_t *request) 71 { 72 dev_handle_t dev_handle; 82 static void vfs_mount_internal(ipc_callid_t rid, dev_handle_t dev_handle, 83 fs_handle_t fs_handle, char *mp) 84 { 85 /* Resolve the path to the mountpoint. */ 86 vfs_lookup_res_t mp_res; 73 87 vfs_node_t *mp_node = NULL; 74 ipc_callid_t callid;75 ipc_call_t data;76 88 int rc; 77 89 int phone; 78 size_t size;79 80 /*81 * We expect the library to do the device-name to device-handle82 * translation for us, thus the device handle will arrive as ARG183 * in the request.84 */85 dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);86 87 /*88 * For now, don't make use of ARG2 and ARG3, but they can be used to89 * carry mount options in the future.90 */91 92 /*93 * Now, we expect the client to send us data with the name of the file94 * system.95 */96 if (!ipc_data_write_receive(&callid, &size)) {97 ipc_answer_0(callid, EINVAL);98 ipc_answer_0(rid, EINVAL);99 return;100 }101 102 /*103 * Don't receive more than is necessary for storing a full file system104 * name.105 */106 if (size < 1 || size > FS_NAME_MAXLEN) {107 ipc_answer_0(callid, EINVAL);108 ipc_answer_0(rid, EINVAL);109 return;110 }111 112 /* Deliver the file system name. */113 char fs_name[FS_NAME_MAXLEN + 1];114 (void) ipc_data_write_finalize(callid, fs_name, size);115 fs_name[size] = '\0';116 117 /*118 * Wait for IPC_M_PING so that we can return an error if we don't know119 * fs_name.120 */121 callid = async_get_call(&data);122 if (IPC_GET_METHOD(data) != IPC_M_PING) {123 ipc_answer_0(callid, ENOTSUP);124 ipc_answer_0(rid, ENOTSUP);125 return;126 }127 128 /*129 * Check if we know a file system with the same name as is in fs_name.130 * This will also give us its file system handle.131 */132 fs_handle_t fs_handle = fs_name_to_handle(fs_name, true);133 if (!fs_handle) {134 ipc_answer_0(callid, ENOENT);135 ipc_answer_0(rid, ENOENT);136 return;137 }138 139 /* Acknowledge that we know fs_name. */140 ipc_answer_0(callid, EOK);141 142 /* Now, we want the client to send us the mount point. */143 if (!ipc_data_write_receive(&callid, &size)) {144 ipc_answer_0(callid, EINVAL);145 ipc_answer_0(rid, EINVAL);146 return;147 }148 149 /* Check whether size is reasonable wrt. the mount point. */150 if (size < 1 || size > MAX_PATH_LEN) {151 ipc_answer_0(callid, EINVAL);152 ipc_answer_0(rid, EINVAL);153 return;154 }155 /* Allocate buffer for the mount point data being received. */156 char *buf;157 buf = malloc(size + 1);158 if (!buf) {159 ipc_answer_0(callid, ENOMEM);160 ipc_answer_0(rid, ENOMEM);161 return;162 }163 164 /* Deliver the mount point. */165 (void) ipc_data_write_finalize(callid, buf, size);166 buf[size] = '\0';167 168 /* Resolve the path to the mountpoint. */169 vfs_lookup_res_t mp_res;170 90 futex_down(&rootfs_futex); 171 91 if (rootfs.fs_handle) { 172 92 /* We already have the root FS. */ 173 93 rwlock_write_lock(&namespace_rwlock); 174 if ((s ize == 1) && (buf[0] == '/')) {94 if ((strlen(mp) == 1) && (mp[0] == '/')) { 175 95 /* Trying to mount root FS over root FS */ 176 96 rwlock_write_unlock(&namespace_rwlock); 177 97 futex_up(&rootfs_futex); 178 free(buf);179 98 ipc_answer_0(rid, EBUSY); 180 99 return; 181 100 } 182 rc = vfs_lookup_internal(buf, L_DIRECTORY, &mp_res, NULL); 101 102 rc = vfs_lookup_internal(mp, L_DIRECTORY, &mp_res, NULL); 183 103 if (rc != EOK) { 184 104 /* The lookup failed for some reason. */ 185 105 rwlock_write_unlock(&namespace_rwlock); 186 106 futex_up(&rootfs_futex); 187 free(buf);188 107 ipc_answer_0(rid, rc); 189 108 return; 190 109 } 110 191 111 mp_node = vfs_node_get(&mp_res); 192 112 if (!mp_node) { 193 113 rwlock_write_unlock(&namespace_rwlock); 194 114 futex_up(&rootfs_futex); 195 free(buf);196 115 ipc_answer_0(rid, ENOMEM); 197 116 return; 198 117 } 118 199 119 /* 200 120 * Now we hold a reference to mp_node. … … 205 125 } else { 206 126 /* We still don't have the root file system mounted. */ 207 if ((s ize == 1) && (buf[0] == '/')) {127 if ((strlen(mp) == 1) && (mp[0] == '/')) { 208 128 vfs_lookup_res_t mr_res; 209 129 vfs_node_t *mr_node; … … 211 131 ipcarg_t rsize; 212 132 ipcarg_t rlnkcnt; 213 133 214 134 /* 215 135 * For this simple, but important case, 216 136 * we are almost done. 217 137 */ 218 free(buf);219 138 220 139 /* Tell the mountee that it is being mounted. */ … … 229 148 return; 230 149 } 231 150 232 151 mr_res.triplet.fs_handle = fs_handle; 233 152 mr_res.triplet.dev_handle = dev_handle; … … 236 155 mr_res.lnkcnt = (unsigned) rlnkcnt; 237 156 mr_res.type = VFS_NODE_DIRECTORY; 238 157 239 158 rootfs.fs_handle = fs_handle; 240 159 rootfs.dev_handle = dev_handle; 241 160 futex_up(&rootfs_futex); 242 161 243 162 /* Add reference to the mounted root. */ 244 163 mr_node = vfs_node_get(&mr_res); 245 164 assert(mr_node); 246 165 247 166 ipc_answer_0(rid, rc); 248 167 return; … … 253 172 */ 254 173 futex_up(&rootfs_futex); 255 free(buf);256 174 ipc_answer_0(rid, ENOENT); 257 175 return; … … 260 178 futex_up(&rootfs_futex); 261 179 262 free(buf); /* The buffer is not needed anymore. */263 264 180 /* 265 181 * At this point, we have all necessary pieces: file system and device 266 182 * handles, and we know the mount point VFS node. 267 183 */ 268 184 269 185 phone = vfs_grab_phone(mp_res.triplet.fs_handle); 270 186 rc = async_req_4_0(phone, VFS_MOUNT, … … 274 190 (ipcarg_t) dev_handle); 275 191 vfs_release_phone(phone); 276 192 277 193 if (rc != EOK) { 278 194 /* Mount failed, drop reference to mp_node. */ … … 282 198 283 199 ipc_answer_0(rid, rc); 200 } 201 202 /** Process pending mount requests */ 203 void vfs_process_pending_mount() 204 { 205 link_t *cur; 206 207 loop: 208 for (cur = pending_req.next; cur != &pending_req; cur = cur->next) { 209 pending_req_t *pr = list_get_instance(cur, pending_req_t, link); 210 211 fs_handle_t fs_handle = fs_name_to_handle(pr->fs_name, true); 212 if (!fs_handle) 213 continue; 214 215 /* Acknowledge that we know fs_name. */ 216 ipc_answer_0(pr->callid, EOK); 217 218 /* Do the mount */ 219 vfs_mount_internal(pr->rid, pr->dev_handle, fs_handle, pr->mp); 220 221 free(pr->fs_name); 222 free(pr->mp); 223 list_remove(cur); 224 free(pr); 225 goto loop; 226 } 227 } 228 229 void vfs_mount(ipc_callid_t rid, ipc_call_t *request) 230 { 231 /* 232 * We expect the library to do the device-name to device-handle 233 * translation for us, thus the device handle will arrive as ARG1 234 * in the request. 235 */ 236 dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); 237 238 /* 239 * Mount flags are passed as ARG2. 240 */ 241 unsigned int flags = (unsigned int) IPC_GET_ARG2(*request); 242 243 /* 244 * For now, don't make use of ARG3, but it can be used to 245 * carry mount options in the future. 246 */ 247 248 /* We want the client to send us the mount point. */ 249 ipc_callid_t callid; 250 size_t size; 251 if (!ipc_data_write_receive(&callid, &size)) { 252 ipc_answer_0(callid, EINVAL); 253 ipc_answer_0(rid, EINVAL); 254 return; 255 } 256 257 /* Check whether size is reasonable wrt. the mount point. */ 258 if ((size < 1) || (size > MAX_PATH_LEN)) { 259 ipc_answer_0(callid, EINVAL); 260 ipc_answer_0(rid, EINVAL); 261 return; 262 } 263 264 /* Allocate buffer for the mount point data being received. */ 265 char *mp = malloc(size + 1); 266 if (!mp) { 267 ipc_answer_0(callid, ENOMEM); 268 ipc_answer_0(rid, ENOMEM); 269 return; 270 } 271 272 /* Deliver the mount point. */ 273 ipcarg_t retval = ipc_data_write_finalize(callid, mp, size); 274 if (retval != EOK) { 275 ipc_answer_0(rid, EREFUSED); 276 free(mp); 277 return; 278 } 279 mp[size] = '\0'; 280 281 /* 282 * Now, we expect the client to send us data with the name of the file 283 * system. 284 */ 285 if (!ipc_data_write_receive(&callid, &size)) { 286 ipc_answer_0(callid, EINVAL); 287 ipc_answer_0(rid, EINVAL); 288 free(mp); 289 return; 290 } 291 292 /* 293 * Don't receive more than is necessary for storing a full file system 294 * name. 295 */ 296 if ((size < 1) || (size > FS_NAME_MAXLEN)) { 297 ipc_answer_0(callid, EINVAL); 298 ipc_answer_0(rid, EINVAL); 299 free(mp); 300 return; 301 } 302 303 /* 304 * Allocate buffer for file system name. 305 */ 306 char *fs_name = (char *) malloc(size + 1); 307 if (fs_name == NULL) { 308 ipc_answer_0(callid, ENOMEM); 309 ipc_answer_0(rid, EREFUSED); 310 free(mp); 311 return; 312 } 313 314 /* Deliver the file system name. */ 315 retval = ipc_data_write_finalize(callid, fs_name, size); 316 if (retval != EOK) { 317 ipc_answer_0(rid, EREFUSED); 318 free(mp); 319 free(fs_name); 320 return; 321 } 322 fs_name[size] = '\0'; 323 324 /* 325 * Check if we know a file system with the same name as is in fs_name. 326 * This will also give us its file system handle. 327 */ 328 fs_handle_t fs_handle = fs_name_to_handle(fs_name, true); 329 if (!fs_handle) { 330 if (flags & IPC_FLAG_BLOCKING) { 331 /* Blocking mount, add to pending list */ 332 pending_req_t *pr = (pending_req_t *) malloc(sizeof(pending_req_t)); 333 if (!pr) { 334 ipc_answer_0(callid, ENOMEM); 335 ipc_answer_0(rid, ENOMEM); 336 free(mp); 337 free(fs_name); 338 return; 339 } 340 341 pr->fs_name = fs_name; 342 pr->mp = mp; 343 pr->callid = callid; 344 pr->rid = rid; 345 pr->dev_handle = dev_handle; 346 list_append(&pr->link, &pending_req); 347 return; 348 } 349 350 ipc_answer_0(callid, ENOENT); 351 ipc_answer_0(rid, ENOENT); 352 free(mp); 353 free(fs_name); 354 return; 355 } 356 357 /* Acknowledge that we know fs_name. */ 358 ipc_answer_0(callid, EOK); 359 360 /* Do the mount */ 361 vfs_mount_internal(rid, dev_handle, fs_handle, mp); 362 free(mp); 363 free(fs_name); 284 364 } 285 365
Note:
See TracChangeset
for help on using the changeset viewer.