Changes in / [fea0ce6:e095644] in mainline
- Location:
- uspace
- Files:
-
- 4 added
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/bdsh/Makefile
rfea0ce6 re095644 48 48 cmds/modules/mv/mv.c \ 49 49 cmds/modules/mount/mount.c \ 50 cmds/modules/unmount/unmount.c \ 50 51 cmds/modules/kcon/kcon.c \ 51 52 cmds/builtins/exit/exit.c \ -
uspace/app/bdsh/cmds/modules/module_aliases.h
rfea0ce6 re095644 14 14 char *mod_aliases[] = { 15 15 "ren", "mv", 16 "umount", "unmount", 16 17 NULL, NULL 17 18 }; -
uspace/app/bdsh/cmds/modules/modules.h
rfea0ce6 re095644 31 31 #include "mv/entry.h" 32 32 #include "mount/entry.h" 33 #include "unmount/entry.h" 33 34 #include "kcon/entry.h" 34 35 … … 51 52 #include "mv/mv_def.h" 52 53 #include "mount/mount_def.h" 54 #include "unmount/unmount_def.h" 53 55 #include "kcon/kcon_def.h" 54 56 -
uspace/lib/libc/generic/adt/hash_table.c
rfea0ce6 re095644 193 193 } 194 194 195 /** Apply fucntion to all items in hash table. 196 * 197 * @param h Hash table. 198 * @param f Function to be applied. 199 * @param arg Argument to be passed to the function. 200 */ 201 void 202 hash_table_apply(hash_table_t *h, void (*f)(link_t *, void *), void *arg) 203 { 204 hash_index_t bucket; 205 link_t *cur; 206 207 for (bucket = 0; bucket < h->entries; bucket++) { 208 for (cur = h->entry[bucket].next; cur != &h->entry[bucket]; 209 cur = cur->next) { 210 f(cur, arg); 211 } 212 } 213 } 214 195 215 /** @} 196 216 */ -
uspace/lib/libc/generic/vfs/vfs.c
rfea0ce6 re095644 197 197 } 198 198 199 int unmount(const char *mp) 200 { 201 ipcarg_t rc; 202 ipcarg_t rc_orig; 203 aid_t req; 204 size_t mpa_size; 205 char *mpa; 206 207 mpa = absolutize(mp, &mpa_size); 208 if (!mpa) 209 return ENOMEM; 210 211 futex_down(&vfs_phone_futex); 212 async_serialize_start(); 213 vfs_connect(); 214 215 req = async_send_0(vfs_phone, VFS_IN_UNMOUNT, NULL); 216 rc = async_data_write_start(vfs_phone, (void *) mpa, mpa_size); 217 if (rc != EOK) { 218 async_wait_for(req, &rc_orig); 219 async_serialize_end(); 220 futex_up(&vfs_phone_futex); 221 free(mpa); 222 if (rc_orig == EOK) 223 return (int) rc; 224 else 225 return (int) rc_orig; 226 } 227 228 229 async_wait_for(req, &rc); 230 async_serialize_end(); 231 futex_up(&vfs_phone_futex); 232 free(mpa); 233 234 return (int) rc; 235 } 236 199 237 static int open_internal(const char *abs, size_t abs_size, int lflag, int oflag) 200 238 { -
uspace/lib/libc/include/adt/hash_table.h
rfea0ce6 re095644 88 88 extern void hash_table_remove(hash_table_t *, unsigned long [], hash_count_t); 89 89 extern void hash_table_destroy(hash_table_t *); 90 extern void hash_table_apply(hash_table_t *, void (*)(link_t *, void *), 91 void *); 90 92 91 93 #endif -
uspace/lib/libc/include/ipc/vfs.h
rfea0ce6 re095644 86 86 VFS_OUT_MOUNTED, 87 87 VFS_OUT_UNMOUNT, 88 VFS_OUT_UNMOUNTED, 88 89 VFS_OUT_SYNC, 89 90 VFS_OUT_STAT, … … 140 141 141 142 /** 142 * L_OPEN is used to indicate that the lookup operation is a part of VFS_ OPEN143 * L_OPEN is used to indicate that the lookup operation is a part of VFS_IN_OPEN 143 144 * call from the client. This means that the server might allocate some 144 145 * resources for the opened file. This flag cannot be passed directly by the … … 147 148 #define L_OPEN 64 148 149 150 /** 151 * L_NOCROSS_LAST_MP is used exclusively during the VFS_IN_UNMOUNT operation. It 152 * tells the lookup routine not to cross the last mount point in the lookup 153 * path. 154 */ 155 #define L_NOCROSS_LAST_MP 128 156 149 157 #endif 150 158 -
uspace/lib/libc/include/vfs/vfs.h
rfea0ce6 re095644 55 55 extern int mount(const char *, const char *, const char *, const char *, 56 56 unsigned int); 57 extern int unmount(const char *); 57 58 58 59 extern void __stdio_init(int filc, fdi_node_t *filv[]); -
uspace/lib/libfs/libfs.c
rfea0ce6 re095644 304 304 on_error(rc, goto out_with_answer); 305 305 306 if ((tmp) && (tmp->mp_data.mp_active)) { 306 /* 307 * If the matching component is a mount point, there are two 308 * legitimate semantics of the lookup operation. The first is 309 * the commonly used one in which the lookup crosses each mount 310 * point into the mounted file system. The second semantics is 311 * used mostly during unmount() and differs from the first one 312 * only in that the last mount point in the looked up path, 313 * which is also its last component, is not crossed. 314 */ 315 316 if ((tmp) && (tmp->mp_data.mp_active) && 317 (!(lflag & L_NOCROSS_LAST_MP) || (next <= last))) { 307 318 if (next > last) 308 319 next = last = first; -
uspace/srv/vfs/vfs.c
rfea0ce6 re095644 86 86 case VFS_IN_MOUNT: 87 87 vfs_mount(callid, &call); 88 break; 89 case VFS_IN_UNMOUNT: 90 vfs_unmount(callid, &call); 88 91 break; 89 92 case VFS_IN_OPEN: -
uspace/srv/vfs/vfs.h
rfea0ce6 re095644 181 181 extern vfs_node_t *vfs_node_get(vfs_lookup_res_t *); 182 182 extern void vfs_node_put(vfs_node_t *); 183 extern void vfs_node_forget(vfs_node_t *); 184 extern unsigned vfs_nodes_refcount_sum_get(fs_handle_t, dev_handle_t); 185 183 186 184 187 #define MAX_OPEN_FILES 128 … … 198 201 extern void vfs_register(ipc_callid_t, ipc_call_t *); 199 202 extern void vfs_mount(ipc_callid_t, ipc_call_t *); 203 extern void vfs_unmount(ipc_callid_t, ipc_call_t *); 200 204 extern void vfs_open(ipc_callid_t, ipc_call_t *); 201 205 extern void vfs_open_node(ipc_callid_t, ipc_call_t *); -
uspace/srv/vfs/vfs_node.c
rfea0ce6 re095644 137 137 if (free_vfs_node) 138 138 free(node); 139 } 140 141 /** Forget node. 142 * 143 * This function will remove the node from the node hash table and deallocate 144 * its memory, regardless of the node's reference count. 145 * 146 * @param node Node to be forgotten. 147 */ 148 void vfs_node_forget(vfs_node_t *node) 149 { 150 fibril_mutex_lock(&nodes_mutex); 151 unsigned long key[] = { 152 [KEY_FS_HANDLE] = node->fs_handle, 153 [KEY_DEV_HANDLE] = node->dev_handle, 154 [KEY_INDEX] = node->index 155 }; 156 hash_table_remove(&nodes, key, 3); 157 fibril_mutex_unlock(&nodes_mutex); 158 free(node); 139 159 } 140 160 … … 231 251 } 232 252 253 struct refcnt_data { 254 /** Sum of all reference counts for this file system instance. */ 255 unsigned refcnt; 256 fs_handle_t fs_handle; 257 dev_handle_t dev_handle; 258 }; 259 260 static void refcnt_visitor(link_t *item, void *arg) 261 { 262 vfs_node_t *node = hash_table_get_instance(item, vfs_node_t, nh_link); 263 struct refcnt_data *rd = (void *) arg; 264 265 if ((node->fs_handle == rd->fs_handle) && 266 (node->dev_handle == rd->dev_handle)) 267 rd->refcnt += node->refcnt; 268 } 269 270 unsigned 271 vfs_nodes_refcount_sum_get(fs_handle_t fs_handle, dev_handle_t dev_handle) 272 { 273 struct refcnt_data rd = { 274 .refcnt = 0, 275 .fs_handle = fs_handle, 276 .dev_handle = dev_handle 277 }; 278 279 fibril_mutex_lock(&nodes_mutex); 280 hash_table_apply(&nodes, refcnt_visitor, &rd); 281 fibril_mutex_unlock(&nodes_mutex); 282 283 return rd.refcnt; 284 } 285 233 286 /** 234 287 * @} -
uspace/srv/vfs/vfs_ops.c
rfea0ce6 re095644 429 429 } 430 430 431 void vfs_unmount(ipc_callid_t rid, ipc_call_t *request) 432 { 433 int rc; 434 char *mp; 435 vfs_lookup_res_t mp_res; 436 vfs_lookup_res_t mr_res; 437 vfs_node_t *mp_node; 438 vfs_node_t *mr_node; 439 int phone; 440 441 /* 442 * Receive the mount point path. 443 */ 444 rc = async_data_string_receive(&mp, MAX_PATH_LEN); 445 if (rc != EOK) 446 ipc_answer_0(rid, rc); 447 448 /* 449 * Taking the namespace lock will do two things for us. First, it will 450 * prevent races with other lookup operations. Second, it will stop new 451 * references to already existing VFS nodes and creation of new VFS 452 * nodes. This is because new references are added as a result of some 453 * lookup operation or at least of some operation which is protected by 454 * the namespace lock. 455 */ 456 fibril_rwlock_write_lock(&namespace_rwlock); 457 458 /* 459 * Lookup the mounted root and instantiate it. 460 */ 461 rc = vfs_lookup_internal(mp, L_NONE, &mr_res, NULL); 462 if (rc != EOK) { 463 fibril_rwlock_write_unlock(&namespace_rwlock); 464 free(mp); 465 ipc_answer_0(rid, rc); 466 return; 467 } 468 mr_node = vfs_node_get(&mr_res); 469 if (!mr_node) { 470 fibril_rwlock_write_unlock(&namespace_rwlock); 471 free(mp); 472 ipc_answer_0(rid, ENOMEM); 473 return; 474 } 475 476 /* 477 * Count the total number of references for the mounted file system. We 478 * are expecting at least two. One which we got above and one which we 479 * got when the file system was mounted. If we find more, it means that 480 * the file system cannot be gracefully unmounted at the moment because 481 * someone is working with it. 482 */ 483 if (vfs_nodes_refcount_sum_get(mr_node->fs_handle, 484 mr_node->dev_handle) != 2) { 485 fibril_rwlock_write_unlock(&namespace_rwlock); 486 vfs_node_put(mr_node); 487 free(mp); 488 ipc_answer_0(rid, EBUSY); 489 return; 490 } 491 492 if (str_cmp(mp, "/") == 0) { 493 494 /* 495 * Unmounting the root file system. 496 * 497 * In this case, there is no mount point node and we send 498 * VFS_OUT_UNMOUNTED directly to the mounted file system. 499 */ 500 501 free(mp); 502 phone = vfs_grab_phone(mr_node->fs_handle); 503 rc = async_req_1_0(phone, VFS_OUT_UNMOUNTED, 504 mr_node->dev_handle); 505 vfs_release_phone(phone); 506 if (rc != EOK) { 507 fibril_rwlock_write_unlock(&namespace_rwlock); 508 vfs_node_put(mr_node); 509 ipc_answer_0(rid, rc); 510 return; 511 } 512 rootfs.fs_handle = 0; 513 rootfs.dev_handle = 0; 514 } else { 515 516 /* 517 * Unmounting a non-root file system. 518 * 519 * We have a regular mount point node representing the parent 520 * file system, so we delegate the operation to it. 521 */ 522 523 /* 524 * The L_NOCROSS_LAST_MP flag is essential if we really want to 525 * lookup the mount point and not the mounted root. 526 */ 527 rc = vfs_lookup_internal(mp, L_NOCROSS_LAST_MP, &mp_res, NULL); 528 free(mp); 529 if (rc != EOK) { 530 fibril_rwlock_write_unlock(&namespace_rwlock); 531 vfs_node_put(mr_node); 532 ipc_answer_0(rid, rc); 533 return; 534 } 535 vfs_node_t *mp_node = vfs_node_get(&mp_res); 536 if (!mp_node) { 537 fibril_rwlock_write_unlock(&namespace_rwlock); 538 vfs_node_put(mr_node); 539 ipc_answer_0(rid, ENOMEM); 540 return; 541 } 542 543 phone = vfs_grab_phone(mp_node->fs_handle); 544 rc = async_req_2_0(phone, VFS_OUT_UNMOUNT, mp_node->fs_handle, 545 mp_node->dev_handle); 546 vfs_release_phone(phone); 547 if (rc != EOK) { 548 fibril_rwlock_write_unlock(&namespace_rwlock); 549 vfs_node_put(mp_node); 550 vfs_node_put(mr_node); 551 ipc_answer_0(rid, rc); 552 return; 553 } 554 555 /* Drop the reference we got above. */ 556 vfs_node_put(mp_node); 557 /* Drop the reference from when the file system was mounted. */ 558 vfs_node_put(mp_node); 559 } 560 561 562 /* 563 * All went well, the mounted file system was successfully unmounted. 564 * The only thing left is to forget the unmounted root VFS node. 565 */ 566 vfs_node_forget(mr_node); 567 568 fibril_rwlock_write_unlock(&namespace_rwlock); 569 ipc_answer_0(rid, EOK); 570 } 571 431 572 void vfs_open(ipc_callid_t rid, ipc_call_t *request) 432 573 { … … 454 595 /* 455 596 * Make sure that we are called with exactly one of L_FILE and 456 * L_DIRECTORY. Make sure that the user does not pass L_OPEN. 597 * L_DIRECTORY. Make sure that the user does not pass L_OPEN or 598 * L_NOCROSS_LAST_MP. 457 599 */ 458 600 if (((lflag & (L_FILE | L_DIRECTORY)) == 0) || 459 601 ((lflag & (L_FILE | L_DIRECTORY)) == (L_FILE | L_DIRECTORY)) || 460 ( (lflag & L_OPEN) != 0)) {602 (lflag & L_OPEN) || (lflag & L_NOCROSS_LAST_MP)) { 461 603 ipc_answer_0(rid, EINVAL); 462 604 return;
Note:
See TracChangeset
for help on using the changeset viewer.