Changes in / [3698e44:2314381] in mainline
- Files:
-
- 40 added
- 25 edited
Legend:
- Unmodified
- Added
- Removed
-
HelenOS.config
r3698e44 r2314381 31 31 32 32 % Platform 33 @ "abs32le" abstract 32-bit little endian 33 34 @ "amd64" AMD64/Intel EM64T (PC) 34 35 @ "arm32" ARM 32-bit … … 91 92 92 93 % Kernel architecture 94 @ "abs32le" 95 ! [PLATFORM=abs32le] KARCH (choice) 96 97 % Kernel architecture 93 98 @ "amd64" 94 99 ! [PLATFORM=amd64] KARCH (choice) … … 130 135 131 136 % User space architecture 137 @ "abs32le" 138 ! [PLATFORM=abs32le] UARCH (choice) 139 140 % User space architecture 132 141 @ "amd64" 133 142 ! [PLATFORM=amd64] UARCH (choice) … … 167 176 168 177 ## Mapping between platform and boot architecture 178 179 % Boot architecture 180 @ "abs32le" 181 ! [PLATFORM=abs32le] BARCH (choice) 169 182 170 183 % Boot architecture … … 243 256 ! [PLATFORM=arm32|PLATFORM=mips32|PLATFORM=ppc32] COMPILER (choice) 244 257 258 % Compiler 259 @ "gcc_native" GNU C Compiler (native) 260 @ "clang" Clang 261 ! [PLATFORM=abs32le] COMPILER (choice) 262 245 263 246 264 ## Kernel configuration … … 259 277 260 278 % Hierarchical page tables support 261 ! [PLATFORM= ia32|PLATFORM=amd64|PLATFORM=arm32|PLATFORM=mips32|PLATFORM=ppc32] CONFIG_PAGE_PT (y)279 ! [PLATFORM=abs32le|PLATFORM=ia32|PLATFORM=amd64|PLATFORM=arm32|PLATFORM=mips32|PLATFORM=ppc32] CONFIG_PAGE_PT (y) 262 280 263 281 % Page hash table support -
Makefile
r3698e44 r2314381 59 59 60 60 distclean: clean 61 rm -f $(CSCOPE).out Makefile.config config.h config.defs tools/*.pyc 61 rm -f $(CSCOPE).out Makefile.config config.h config.defs tools/*.pyc tools/checkers/*.pyc 62 62 63 63 clean: -
uspace/app/bdsh/Makefile
r3698e44 r2314381 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
r3698e44 r2314381 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
r3698e44 r2314381 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
r3698e44 r2314381 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
r3698e44 r2314381 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
r3698e44 r2314381 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
r3698e44 r2314381 86 86 VFS_OUT_MOUNTED, 87 87 VFS_OUT_UNMOUNT, 88 VFS_OUT_UNMOUNTED, 88 89 VFS_OUT_SYNC, 89 90 VFS_OUT_STAT, … … 100 101 * No lookup flags used. 101 102 */ 102 #define L_NONE 103 #define L_NONE 0 103 104 104 105 /** … … 107 108 * with L_DIRECTORY. 108 109 */ 109 #define L_FILE 110 #define L_FILE 1 110 111 111 112 /** 112 * Lookup wil succeed only if the object is a directory. If L_CREATE is113 * Lookup will succeed only if the object is a directory. If L_CREATE is 113 114 * specified, an empty directory will be created. This flag is mutually 114 115 * exclusive with L_FILE. 115 116 */ 116 #define L_DIRECTORY 2 117 #define L_DIRECTORY 2 118 119 /** 120 * Lookup will succeed only if the object is a root directory. The flag is 121 * mutually exclusive with L_FILE and L_MP. 122 */ 123 #define L_ROOT 4 124 125 /** 126 * Lookup will succeed only if the object is a mount point. The flag is mutually 127 * exclusive with L_FILE and L_ROOT. 128 */ 129 #define L_MP 8 130 117 131 118 132 /** … … 120 134 * object already exists. L_EXCLUSIVE is implied when L_DIRECTORY is used. 121 135 */ 122 #define L_EXCLUSIVE 4136 #define L_EXCLUSIVE 16 123 137 124 138 /** 125 139 * L_CREATE is used for creating both regular files and directories. 126 140 */ 127 #define L_CREATE 8141 #define L_CREATE 32 128 142 129 143 /** 130 144 * L_LINK is used for linking to an already existing nodes. 131 145 */ 132 #define L_LINK 16146 #define L_LINK 64 133 147 134 148 /** … … 137 151 * VFS_UNLINK. 138 152 */ 139 #define L_UNLINK 32153 #define L_UNLINK 128 140 154 141 155 /** 142 * L_OPEN is used to indicate that the lookup operation is a part of VFS_ OPEN156 * L_OPEN is used to indicate that the lookup operation is a part of VFS_IN_OPEN 143 157 * call from the client. This means that the server might allocate some 144 158 * resources for the opened file. This flag cannot be passed directly by the 145 159 * client. 146 160 */ 147 #define L_OPEN 64161 #define L_OPEN 256 148 162 149 163 #endif -
uspace/lib/libc/include/vfs/vfs.h
r3698e44 r2314381 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
r3698e44 r2314381 224 224 ipc_answer_3(rid, rc, IPC_GET_ARG1(answer), IPC_GET_ARG2(answer), 225 225 IPC_GET_ARG3(answer)); 226 } 227 228 void libfs_unmount(libfs_ops_t *ops, ipc_callid_t rid, ipc_call_t *request) 229 { 230 dev_handle_t mp_dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); 231 fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*request); 232 fs_node_t *fn; 233 int res; 234 235 res = ops->node_get(&fn, mp_dev_handle, mp_fs_index); 236 if ((res != EOK) || (!fn)) { 237 ipc_answer_0(rid, combine_rc(res, ENOENT)); 238 return; 239 } 240 241 /* 242 * We are clearly expecting to find the mount point active. 243 */ 244 if (!fn->mp_data.mp_active) { 245 (void) ops->node_put(fn); 246 ipc_answer_0(rid, EINVAL); 247 return; 248 } 249 250 /* 251 * Tell the mounted file system to unmount. 252 */ 253 res = async_req_1_0(fn->mp_data.phone, VFS_OUT_UNMOUNTED, 254 fn->mp_data.dev_handle); 255 256 /* 257 * If everything went well, perform the clean-up on our side. 258 */ 259 if (res == EOK) { 260 ipc_hangup(fn->mp_data.phone); 261 fn->mp_data.mp_active = false; 262 fn->mp_data.fs_handle = 0; 263 fn->mp_data.dev_handle = 0; 264 fn->mp_data.phone = 0; 265 /* Drop the reference created in libfs_mount(). */ 266 (void) ops->node_put(fn); 267 } 268 269 (void) ops->node_put(fn); 270 ipc_answer_0(rid, res); 226 271 } 227 272 … … 304 349 on_error(rc, goto out_with_answer); 305 350 306 if ((tmp) && (tmp->mp_data.mp_active)) { 351 /* 352 * If the matching component is a mount point, there are two 353 * legitimate semantics of the lookup operation. The first is 354 * the commonly used one in which the lookup crosses each mount 355 * point into the mounted file system. The second semantics is 356 * used mostly during unmount() and differs from the first one 357 * only in that the last mount point in the looked up path, 358 * which is also its last component, is not crossed. 359 */ 360 361 if ((tmp) && (tmp->mp_data.mp_active) && 362 (!(lflag & L_MP) || (next <= last))) { 307 363 if (next > last) 308 364 next = last = first; … … 475 531 goto out; 476 532 } 533 534 if ((lflag & L_ROOT) && par) { 535 ipc_answer_0(rid, EINVAL); 536 goto out; 537 } 477 538 478 539 out_with_answer: -
uspace/lib/libfs/libfs.h
r3698e44 r2314381 95 95 96 96 extern void libfs_mount(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *); 97 extern void libfs_unmount(libfs_ops_t *, ipc_callid_t, ipc_call_t *); 97 98 extern void libfs_lookup(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *); 98 99 extern void libfs_stat(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *); -
uspace/srv/fs/devfs/devfs.c
r3698e44 r2314381 75 75 devfs_mount(callid, &call); 76 76 break; 77 case VFS_OUT_UNMOUNTED: 78 devfs_unmounted(callid, &call); 79 break; 80 case VFS_OUT_UNMOUNT: 81 devfs_unmount(callid, &call); 82 break; 77 83 case VFS_OUT_LOOKUP: 78 84 devfs_lookup(callid, &call); -
uspace/srv/fs/devfs/devfs_ops.c
r3698e44 r2314381 434 434 } 435 435 436 void devfs_unmounted(ipc_callid_t rid, ipc_call_t *request) 437 { 438 ipc_answer_0(rid, ENOTSUP); 439 } 440 441 void devfs_unmount(ipc_callid_t rid, ipc_call_t *request) 442 { 443 libfs_unmount(&devfs_libfs_ops, rid, request); 444 } 445 436 446 void devfs_lookup(ipc_callid_t rid, ipc_call_t *request) 437 447 { -
uspace/srv/fs/devfs/devfs_ops.h
r3698e44 r2314381 41 41 extern void devfs_mounted(ipc_callid_t, ipc_call_t *); 42 42 extern void devfs_mount(ipc_callid_t, ipc_call_t *); 43 extern void devfs_unmounted(ipc_callid_t, ipc_call_t *); 44 extern void devfs_unmount(ipc_callid_t, ipc_call_t *); 43 45 extern void devfs_lookup(ipc_callid_t, ipc_call_t *); 44 46 extern void devfs_open_node(ipc_callid_t, ipc_call_t *); -
uspace/srv/fs/fat/fat.c
r3698e44 r2314381 100 100 fat_mount(callid, &call); 101 101 break; 102 case VFS_OUT_UNMOUNTED: 103 fat_unmounted(callid, &call); 104 break; 105 case VFS_OUT_UNMOUNT: 106 fat_unmount(callid, &call); 107 break; 102 108 case VFS_OUT_LOOKUP: 103 109 fat_lookup(callid, &call); -
uspace/srv/fs/fat/fat.h
r3698e44 r2314381 204 204 extern void fat_mounted(ipc_callid_t, ipc_call_t *); 205 205 extern void fat_mount(ipc_callid_t, ipc_call_t *); 206 extern void fat_unmounted(ipc_callid_t, ipc_call_t *); 207 extern void fat_unmount(ipc_callid_t, ipc_call_t *); 206 208 extern void fat_lookup(ipc_callid_t, ipc_call_t *); 207 209 extern void fat_read(ipc_callid_t, ipc_call_t *); -
uspace/srv/fs/fat/fat_ops.c
r3698e44 r2314381 1117 1117 } 1118 1118 1119 void fat_unmounted(ipc_callid_t rid, ipc_call_t *request) 1120 { 1121 ipc_answer_0(rid, ENOTSUP); 1122 } 1123 1124 void fat_unmount(ipc_callid_t rid, ipc_call_t *request) 1125 { 1126 libfs_unmount(&fat_libfs_ops, rid, request); 1127 } 1128 1119 1129 void fat_lookup(ipc_callid_t rid, ipc_call_t *request) 1120 1130 { -
uspace/srv/fs/tmpfs/tmpfs.c
r3698e44 r2314381 106 106 tmpfs_mount(callid, &call); 107 107 break; 108 case VFS_OUT_UNMOUNTED: 109 tmpfs_unmounted(callid, &call); 110 break; 111 case VFS_OUT_UNMOUNT: 112 tmpfs_unmount(callid, &call); 113 break; 108 114 case VFS_OUT_LOOKUP: 109 115 tmpfs_lookup(callid, &call); -
uspace/srv/fs/tmpfs/tmpfs.h
r3698e44 r2314381 83 83 extern void tmpfs_mounted(ipc_callid_t, ipc_call_t *); 84 84 extern void tmpfs_mount(ipc_callid_t, ipc_call_t *); 85 extern void tmpfs_unmounted(ipc_callid_t, ipc_call_t *); 86 extern void tmpfs_unmount(ipc_callid_t, ipc_call_t *); 85 87 extern void tmpfs_lookup(ipc_callid_t, ipc_call_t *); 86 88 extern void tmpfs_read(ipc_callid_t, ipc_call_t *); -
uspace/srv/fs/tmpfs/tmpfs_ops.c
r3698e44 r2314381 147 147 hash_table_t nodes; 148 148 149 #define NODES_KEY_ INDEX 0150 #define NODES_KEY_ DEV1149 #define NODES_KEY_DEV 0 150 #define NODES_KEY_INDEX 1 151 151 152 152 /* Implementation of hash table interface for the nodes hash table. */ … … 166 166 static void nodes_remove_callback(link_t *item) 167 167 { 168 tmpfs_node_t *nodep = hash_table_get_instance(item, tmpfs_node_t, 169 nh_link); 170 171 while (!list_empty(&nodep->cs_head)) { 172 tmpfs_dentry_t *dentryp = list_get_instance(nodep->cs_head.next, 173 tmpfs_dentry_t, link); 174 175 assert(nodep->type == TMPFS_DIRECTORY); 176 list_remove(&dentryp->link); 177 free(dentryp); 178 } 179 180 if (nodep->data) { 181 assert(nodep->type == TMPFS_FILE); 182 free(nodep->data); 183 } 184 free(nodep->bp); 185 free(nodep); 168 186 } 169 187 … … 215 233 } 216 234 235 static void tmpfs_instance_done(dev_handle_t dev_handle) 236 { 237 unsigned long key[] = { 238 [NODES_KEY_DEV] = dev_handle 239 }; 240 /* 241 * Here we are making use of one special feature of our hash table 242 * implementation, which allows to remove more items based on a partial 243 * key match. In the following, we are going to remove all nodes 244 * matching our device handle. The nodes_remove_callback() function will 245 * take care of resource deallocation. 246 */ 247 hash_table_remove(&nodes, key, 1); 248 } 249 217 250 int tmpfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component) 218 251 { … … 237 270 { 238 271 unsigned long key[] = { 239 [NODES_KEY_ INDEX] = index,240 [NODES_KEY_ DEV] = dev_handle272 [NODES_KEY_DEV] = dev_handle, 273 [NODES_KEY_INDEX] = index 241 274 }; 242 275 link_t *lnk = hash_table_find(&nodes, key); … … 296 329 /* Insert the new node into the nodes hash table. */ 297 330 unsigned long key[] = { 298 [NODES_KEY_ INDEX] = nodep->index,299 [NODES_KEY_ DEV] = nodep->dev_handle331 [NODES_KEY_DEV] = nodep->dev_handle, 332 [NODES_KEY_INDEX] = nodep->index 300 333 }; 301 334 hash_table_insert(&nodes, key, &nodep->nh_link); … … 312 345 313 346 unsigned long key[] = { 314 [NODES_KEY_ INDEX] = nodep->index,315 [NODES_KEY_ DEV] = nodep->dev_handle347 [NODES_KEY_DEV] = nodep->dev_handle, 348 [NODES_KEY_INDEX] = nodep->index 316 349 }; 317 350 hash_table_remove(&nodes, key, 2); 318 351 319 if (nodep->type == TMPFS_FILE)320 free(nodep->data);321 free(nodep->bp);322 free(nodep);352 /* 353 * The nodes_remove_callback() function takes care of the actual 354 * resource deallocation. 355 */ 323 356 return EOK; 324 357 } … … 424 457 /* Initialize TMPFS instance. */ 425 458 if (!tmpfs_instance_init(dev_handle)) { 459 free(opts); 426 460 ipc_answer_0(rid, ENOMEM); 427 461 return; … … 442 476 rootp->lnkcnt); 443 477 } 478 free(opts); 444 479 } 445 480 … … 447 482 { 448 483 libfs_mount(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request); 484 } 485 486 void tmpfs_unmounted(ipc_callid_t rid, ipc_call_t *request) 487 { 488 dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); 489 490 tmpfs_instance_done(dev_handle); 491 ipc_answer_0(rid, EOK); 492 } 493 494 void tmpfs_unmount(ipc_callid_t rid, ipc_call_t *request) 495 { 496 libfs_unmount(&tmpfs_libfs_ops, rid, request); 449 497 } 450 498 … … 465 513 link_t *hlp; 466 514 unsigned long key[] = { 467 [NODES_KEY_INDEX] = index,468 515 [NODES_KEY_DEV] = dev_handle, 516 [NODES_KEY_INDEX] = index 469 517 }; 470 518 hlp = hash_table_find(&nodes, key); … … 539 587 link_t *hlp; 540 588 unsigned long key[] = { 541 [NODES_KEY_ INDEX] = index,542 [NODES_KEY_ DEV] = dev_handle589 [NODES_KEY_DEV] = dev_handle, 590 [NODES_KEY_INDEX] = index 543 591 }; 544 592 hlp = hash_table_find(&nodes, key); … … 603 651 link_t *hlp; 604 652 unsigned long key[] = { 605 [NODES_KEY_ INDEX] = index,606 [NODES_KEY_ DEV] = dev_handle653 [NODES_KEY_DEV] = dev_handle, 654 [NODES_KEY_INDEX] = index 607 655 }; 608 656 hlp = hash_table_find(&nodes, key); … … 646 694 link_t *hlp; 647 695 unsigned long key[] = { 648 [NODES_KEY_ INDEX] = index,649 [NODES_KEY_ DEV] = dev_handle696 [NODES_KEY_DEV] = dev_handle, 697 [NODES_KEY_INDEX] = index 650 698 }; 651 699 hlp = hash_table_find(&nodes, key); -
uspace/srv/vfs/vfs.c
r3698e44 r2314381 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
r3698e44 r2314381 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
r3698e44 r2314381 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
r3698e44 r2314381 92 92 } 93 93 94 rc = vfs_lookup_internal(mp, L_ DIRECTORY, &mp_res, NULL);94 rc = vfs_lookup_internal(mp, L_MP, &mp_res, NULL); 95 95 if (rc != EOK) { 96 96 /* The lookup failed for some reason. */ … … 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_ROOT, &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 rc = vfs_lookup_internal(mp, L_MP, &mp_res, NULL); 524 free(mp); 525 if (rc != EOK) { 526 fibril_rwlock_write_unlock(&namespace_rwlock); 527 vfs_node_put(mr_node); 528 ipc_answer_0(rid, rc); 529 return; 530 } 531 vfs_node_t *mp_node = vfs_node_get(&mp_res); 532 if (!mp_node) { 533 fibril_rwlock_write_unlock(&namespace_rwlock); 534 vfs_node_put(mr_node); 535 ipc_answer_0(rid, ENOMEM); 536 return; 537 } 538 539 phone = vfs_grab_phone(mp_node->fs_handle); 540 rc = async_req_2_0(phone, VFS_OUT_UNMOUNT, mp_node->dev_handle, 541 mp_node->index); 542 vfs_release_phone(phone); 543 if (rc != EOK) { 544 fibril_rwlock_write_unlock(&namespace_rwlock); 545 vfs_node_put(mp_node); 546 vfs_node_put(mr_node); 547 ipc_answer_0(rid, rc); 548 return; 549 } 550 551 /* Drop the reference we got above. */ 552 vfs_node_put(mp_node); 553 /* Drop the reference from when the file system was mounted. */ 554 vfs_node_put(mp_node); 555 } 556 557 558 /* 559 * All went well, the mounted file system was successfully unmounted. 560 * The only thing left is to forget the unmounted root VFS node. 561 */ 562 vfs_node_forget(mr_node); 563 564 fibril_rwlock_write_unlock(&namespace_rwlock); 565 ipc_answer_0(rid, EOK); 566 } 567 431 568 void vfs_open(ipc_callid_t rid, ipc_call_t *request) 432 569 { … … 454 591 /* 455 592 * 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. 593 * L_DIRECTORY. Make sure that the user does not pass L_OPEN, 594 * L_ROOT or L_MP. 457 595 */ 458 596 if (((lflag & (L_FILE | L_DIRECTORY)) == 0) || 459 597 ((lflag & (L_FILE | L_DIRECTORY)) == (L_FILE | L_DIRECTORY)) || 460 ( (lflag & L_OPEN) != 0)) {598 (lflag & (L_OPEN | L_ROOT | L_MP))) { 461 599 ipc_answer_0(rid, EINVAL); 462 600 return;
Note:
See TracChangeset
for help on using the changeset viewer.