Changes in / [f0bdfb7:95e6c4f] in mainline


Ignore:
Files:
40 added
25 edited

Legend:

Unmodified
Added
Removed
  • HelenOS.config

    rf0bdfb7 r95e6c4f  
    3131
    3232% Platform
     33@ "abs32le" abstract 32-bit little endian
    3334@ "amd64" AMD64/Intel EM64T (PC)
    3435@ "arm32" ARM 32-bit
     
    9192
    9293% Kernel architecture
     94@ "abs32le"
     95! [PLATFORM=abs32le] KARCH (choice)
     96
     97% Kernel architecture
    9398@ "amd64"
    9499! [PLATFORM=amd64] KARCH (choice)
     
    130135
    131136% User space architecture
     137@ "abs32le"
     138! [PLATFORM=abs32le] UARCH (choice)
     139
     140% User space architecture
    132141@ "amd64"
    133142! [PLATFORM=amd64] UARCH (choice)
     
    167176
    168177## Mapping between platform and boot architecture
     178
     179% Boot architecture
     180@ "abs32le"
     181! [PLATFORM=abs32le] BARCH (choice)
    169182
    170183% Boot architecture
     
    243256! [PLATFORM=arm32|PLATFORM=mips32|PLATFORM=ppc32] COMPILER (choice)
    244257
     258% Compiler
     259@ "gcc_native" GNU C Compiler (native)
     260@ "clang" Clang
     261! [PLATFORM=abs32le] COMPILER (choice)
     262
    245263
    246264## Kernel configuration
     
    259277
    260278% 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)
    262280
    263281% Page hash table support
  • Makefile

    rf0bdfb7 r95e6c4f  
    5959
    6060distclean: 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
    6262
    6363clean:
  • uspace/app/bdsh/Makefile

    rf0bdfb7 r95e6c4f  
    4848        cmds/modules/mv/mv.c \
    4949        cmds/modules/mount/mount.c \
     50        cmds/modules/unmount/unmount.c \
    5051        cmds/modules/kcon/kcon.c \
    5152        cmds/builtins/exit/exit.c \
  • uspace/app/bdsh/cmds/modules/module_aliases.h

    rf0bdfb7 r95e6c4f  
    1414char *mod_aliases[] = {
    1515        "ren", "mv",
     16        "umount", "unmount",
    1617        NULL, NULL
    1718};
  • uspace/app/bdsh/cmds/modules/modules.h

    rf0bdfb7 r95e6c4f  
    3131#include "mv/entry.h"
    3232#include "mount/entry.h"
     33#include "unmount/entry.h"
    3334#include "kcon/entry.h"
    3435
     
    5152#include "mv/mv_def.h"
    5253#include "mount/mount_def.h"
     54#include "unmount/unmount_def.h"
    5355#include "kcon/kcon_def.h"
    5456
  • uspace/lib/libc/generic/adt/hash_table.c

    rf0bdfb7 r95e6c4f  
    193193}
    194194
     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 */
     201void
     202hash_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
    195215/** @}
    196216 */
  • uspace/lib/libc/generic/vfs/vfs.c

    rf0bdfb7 r95e6c4f  
    197197}
    198198
     199int 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
    199237static int open_internal(const char *abs, size_t abs_size, int lflag, int oflag)
    200238{
  • uspace/lib/libc/include/adt/hash_table.h

    rf0bdfb7 r95e6c4f  
    8888extern void hash_table_remove(hash_table_t *, unsigned long [], hash_count_t);
    8989extern void hash_table_destroy(hash_table_t *);
     90extern void hash_table_apply(hash_table_t *, void (*)(link_t *, void *),
     91    void *);
    9092
    9193#endif
  • uspace/lib/libc/include/ipc/vfs.h

    rf0bdfb7 r95e6c4f  
    8686        VFS_OUT_MOUNTED,
    8787        VFS_OUT_UNMOUNT,
     88        VFS_OUT_UNMOUNTED,
    8889        VFS_OUT_SYNC,
    8990        VFS_OUT_STAT,
     
    100101 * No lookup flags used.
    101102 */
    102 #define L_NONE  0
     103#define L_NONE                  0
    103104
    104105/**
     
    107108 * with L_DIRECTORY.
    108109 */
    109 #define L_FILE  1
     110#define L_FILE                  1
    110111
    111112/**
    112  * Lookup wil succeed only if the object is a directory. If L_CREATE is
     113 * Lookup will succeed only if the object is a directory. If L_CREATE is
    113114 * specified, an empty directory will be created. This flag is mutually
    114115 * exclusive with L_FILE.
    115116 */
    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
    117131
    118132/**
     
    120134 * object already exists. L_EXCLUSIVE is implied when L_DIRECTORY is used.
    121135 */
    122 #define L_EXCLUSIVE  4
     136#define L_EXCLUSIVE             16
    123137
    124138/**
    125139 * L_CREATE is used for creating both regular files and directories.
    126140 */
    127 #define L_CREATE  8
     141#define L_CREATE                32
    128142
    129143/**
    130144 * L_LINK is used for linking to an already existing nodes.
    131145 */
    132 #define L_LINK  16
     146#define L_LINK                  64
    133147
    134148/**
     
    137151 * VFS_UNLINK.
    138152 */
    139 #define L_UNLINK  32
     153#define L_UNLINK                128
    140154
    141155/**
    142  * L_OPEN is used to indicate that the lookup operation is a part of VFS_OPEN
     156 * L_OPEN is used to indicate that the lookup operation is a part of VFS_IN_OPEN
    143157 * call from the client. This means that the server might allocate some
    144158 * resources for the opened file. This flag cannot be passed directly by the
    145159 * client.
    146160 */
    147 #define L_OPEN  64
     161#define L_OPEN                  256
    148162
    149163#endif
  • uspace/lib/libc/include/vfs/vfs.h

    rf0bdfb7 r95e6c4f  
    5555extern int mount(const char *, const char *, const char *, const char *,
    5656    unsigned int);
     57extern int unmount(const char *);
    5758
    5859extern void __stdio_init(int filc, fdi_node_t *filv[]);
  • uspace/lib/libfs/libfs.c

    rf0bdfb7 r95e6c4f  
    224224        ipc_answer_3(rid, rc, IPC_GET_ARG1(answer), IPC_GET_ARG2(answer),
    225225            IPC_GET_ARG3(answer));
     226}
     227
     228void 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);
    226271}
    227272
     
    304349                on_error(rc, goto out_with_answer);
    305350               
    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))) {
    307363                        if (next > last)
    308364                                next = last = first;
     
    475531                goto out;
    476532        }
     533
     534        if ((lflag & L_ROOT) && par) {
     535                ipc_answer_0(rid, EINVAL);
     536                goto out;
     537        }
    477538       
    478539out_with_answer:
  • uspace/lib/libfs/libfs.h

    rf0bdfb7 r95e6c4f  
    9595
    9696extern void libfs_mount(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *);
     97extern void libfs_unmount(libfs_ops_t *, ipc_callid_t, ipc_call_t *);
    9798extern void libfs_lookup(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *);
    9899extern void libfs_stat(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *);
  • uspace/srv/fs/devfs/devfs.c

    rf0bdfb7 r95e6c4f  
    7575                        devfs_mount(callid, &call);
    7676                        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;
    7783                case VFS_OUT_LOOKUP:
    7884                        devfs_lookup(callid, &call);
  • uspace/srv/fs/devfs/devfs_ops.c

    rf0bdfb7 r95e6c4f  
    434434}
    435435
     436void devfs_unmounted(ipc_callid_t rid, ipc_call_t *request)
     437{
     438        ipc_answer_0(rid, ENOTSUP);
     439}
     440
     441void devfs_unmount(ipc_callid_t rid, ipc_call_t *request)
     442{
     443        libfs_unmount(&devfs_libfs_ops, rid, request);
     444}
     445
    436446void devfs_lookup(ipc_callid_t rid, ipc_call_t *request)
    437447{
  • uspace/srv/fs/devfs/devfs_ops.h

    rf0bdfb7 r95e6c4f  
    4141extern void devfs_mounted(ipc_callid_t, ipc_call_t *);
    4242extern void devfs_mount(ipc_callid_t, ipc_call_t *);
     43extern void devfs_unmounted(ipc_callid_t, ipc_call_t *);
     44extern void devfs_unmount(ipc_callid_t, ipc_call_t *);
    4345extern void devfs_lookup(ipc_callid_t, ipc_call_t *);
    4446extern void devfs_open_node(ipc_callid_t, ipc_call_t *);
  • uspace/srv/fs/fat/fat.c

    rf0bdfb7 r95e6c4f  
    100100                        fat_mount(callid, &call);
    101101                        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;
    102108                case VFS_OUT_LOOKUP:
    103109                        fat_lookup(callid, &call);
  • uspace/srv/fs/fat/fat.h

    rf0bdfb7 r95e6c4f  
    204204extern void fat_mounted(ipc_callid_t, ipc_call_t *);
    205205extern void fat_mount(ipc_callid_t, ipc_call_t *);
     206extern void fat_unmounted(ipc_callid_t, ipc_call_t *);
     207extern void fat_unmount(ipc_callid_t, ipc_call_t *);
    206208extern void fat_lookup(ipc_callid_t, ipc_call_t *);
    207209extern void fat_read(ipc_callid_t, ipc_call_t *);
  • uspace/srv/fs/fat/fat_ops.c

    rf0bdfb7 r95e6c4f  
    11171117}
    11181118
     1119void fat_unmounted(ipc_callid_t rid, ipc_call_t *request)
     1120{
     1121        ipc_answer_0(rid, ENOTSUP);
     1122}
     1123
     1124void fat_unmount(ipc_callid_t rid, ipc_call_t *request)
     1125{
     1126        libfs_unmount(&fat_libfs_ops, rid, request);
     1127}
     1128
    11191129void fat_lookup(ipc_callid_t rid, ipc_call_t *request)
    11201130{
  • uspace/srv/fs/tmpfs/tmpfs.c

    rf0bdfb7 r95e6c4f  
    106106                        tmpfs_mount(callid, &call);
    107107                        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;
    108114                case VFS_OUT_LOOKUP:
    109115                        tmpfs_lookup(callid, &call);
  • uspace/srv/fs/tmpfs/tmpfs.h

    rf0bdfb7 r95e6c4f  
    8383extern void tmpfs_mounted(ipc_callid_t, ipc_call_t *);
    8484extern void tmpfs_mount(ipc_callid_t, ipc_call_t *);
     85extern void tmpfs_unmounted(ipc_callid_t, ipc_call_t *);
     86extern void tmpfs_unmount(ipc_callid_t, ipc_call_t *);
    8587extern void tmpfs_lookup(ipc_callid_t, ipc_call_t *);
    8688extern void tmpfs_read(ipc_callid_t, ipc_call_t *);
  • uspace/srv/fs/tmpfs/tmpfs_ops.c

    rf0bdfb7 r95e6c4f  
    147147hash_table_t nodes;
    148148
    149 #define NODES_KEY_INDEX 0
    150 #define NODES_KEY_DEV   1
     149#define NODES_KEY_DEV   0       
     150#define NODES_KEY_INDEX 1
    151151
    152152/* Implementation of hash table interface for the nodes hash table. */
     
    160160        tmpfs_node_t *nodep = hash_table_get_instance(item, tmpfs_node_t,
    161161            nh_link);
    162         return (nodep->index == key[NODES_KEY_INDEX] &&
    163             nodep->dev_handle == key[NODES_KEY_DEV]);
     162       
     163        switch (keys) {
     164        case 1:
     165                return (nodep->dev_handle == key[NODES_KEY_DEV]);
     166        case 2:
     167                return ((nodep->dev_handle == key[NODES_KEY_DEV]) &&
     168                    (nodep->index == key[NODES_KEY_INDEX]));
     169        default:
     170                abort();
     171        }
    164172}
    165173
    166174static void nodes_remove_callback(link_t *item)
    167175{
     176        tmpfs_node_t *nodep = hash_table_get_instance(item, tmpfs_node_t,
     177            nh_link);
     178
     179        while (!list_empty(&nodep->cs_head)) {
     180                tmpfs_dentry_t *dentryp = list_get_instance(nodep->cs_head.next,
     181                    tmpfs_dentry_t, link);
     182
     183                assert(nodep->type == TMPFS_DIRECTORY);
     184                list_remove(&dentryp->link);
     185                free(dentryp);
     186        }
     187
     188        if (nodep->data) {
     189                assert(nodep->type == TMPFS_FILE);
     190                free(nodep->data);
     191        }
     192        free(nodep->bp);
     193        free(nodep);
    168194}
    169195
     
    215241}
    216242
     243static void tmpfs_instance_done(dev_handle_t dev_handle)
     244{
     245        unsigned long key[] = {
     246                [NODES_KEY_DEV] = dev_handle
     247        };
     248        /*
     249         * Here we are making use of one special feature of our hash table
     250         * implementation, which allows to remove more items based on a partial
     251         * key match. In the following, we are going to remove all nodes
     252         * matching our device handle. The nodes_remove_callback() function will
     253         * take care of resource deallocation.
     254         */
     255        hash_table_remove(&nodes, key, 1);
     256}
     257
    217258int tmpfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
    218259{
     
    237278{
    238279        unsigned long key[] = {
    239                 [NODES_KEY_INDEX] = index,
    240                 [NODES_KEY_DEV] = dev_handle
     280                [NODES_KEY_DEV] = dev_handle,
     281                [NODES_KEY_INDEX] = index
    241282        };
    242283        link_t *lnk = hash_table_find(&nodes, key);
     
    296337        /* Insert the new node into the nodes hash table. */
    297338        unsigned long key[] = {
    298                 [NODES_KEY_INDEX] = nodep->index,
    299                 [NODES_KEY_DEV] = nodep->dev_handle
     339                [NODES_KEY_DEV] = nodep->dev_handle,
     340                [NODES_KEY_INDEX] = nodep->index
    300341        };
    301342        hash_table_insert(&nodes, key, &nodep->nh_link);
     
    312353
    313354        unsigned long key[] = {
    314                 [NODES_KEY_INDEX] = nodep->index,
    315                 [NODES_KEY_DEV] = nodep->dev_handle
     355                [NODES_KEY_DEV] = nodep->dev_handle,
     356                [NODES_KEY_INDEX] = nodep->index
    316357        };
    317358        hash_table_remove(&nodes, key, 2);
    318359
    319         if (nodep->type == TMPFS_FILE)
    320                 free(nodep->data);
    321         free(nodep->bp);
    322         free(nodep);
     360        /*
     361         * The nodes_remove_callback() function takes care of the actual
     362         * resource deallocation.
     363         */
    323364        return EOK;
    324365}
     
    424465        /* Initialize TMPFS instance. */
    425466        if (!tmpfs_instance_init(dev_handle)) {
     467                free(opts);
    426468                ipc_answer_0(rid, ENOMEM);
    427469                return;
     
    442484                    rootp->lnkcnt);
    443485        }
     486        free(opts);
    444487}
    445488
     
    447490{
    448491        libfs_mount(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request);
     492}
     493
     494void tmpfs_unmounted(ipc_callid_t rid, ipc_call_t *request)
     495{
     496        dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
     497
     498        tmpfs_instance_done(dev_handle);
     499        ipc_answer_0(rid, EOK);
     500}
     501
     502void tmpfs_unmount(ipc_callid_t rid, ipc_call_t *request)
     503{
     504        libfs_unmount(&tmpfs_libfs_ops, rid, request);
    449505}
    450506
     
    465521        link_t *hlp;
    466522        unsigned long key[] = {
    467                 [NODES_KEY_INDEX] = index,
    468523                [NODES_KEY_DEV] = dev_handle,
     524                [NODES_KEY_INDEX] = index
    469525        };
    470526        hlp = hash_table_find(&nodes, key);
     
    539595        link_t *hlp;
    540596        unsigned long key[] = {
    541                 [NODES_KEY_INDEX] = index,
    542                 [NODES_KEY_DEV] = dev_handle
     597                [NODES_KEY_DEV] = dev_handle,
     598                [NODES_KEY_INDEX] = index
    543599        };
    544600        hlp = hash_table_find(&nodes, key);
     
    603659        link_t *hlp;
    604660        unsigned long key[] = {
    605                 [NODES_KEY_INDEX] = index,
    606                 [NODES_KEY_DEV] = dev_handle
     661                [NODES_KEY_DEV] = dev_handle,
     662                [NODES_KEY_INDEX] = index
    607663        };
    608664        hlp = hash_table_find(&nodes, key);
     
    646702        link_t *hlp;
    647703        unsigned long key[] = {
    648                 [NODES_KEY_INDEX] = index,
    649                 [NODES_KEY_DEV] = dev_handle
     704                [NODES_KEY_DEV] = dev_handle,
     705                [NODES_KEY_INDEX] = index
    650706        };
    651707        hlp = hash_table_find(&nodes, key);
  • uspace/srv/vfs/vfs.c

    rf0bdfb7 r95e6c4f  
    8686                case VFS_IN_MOUNT:
    8787                        vfs_mount(callid, &call);
     88                        break;
     89                case VFS_IN_UNMOUNT:
     90                        vfs_unmount(callid, &call);
    8891                        break;
    8992                case VFS_IN_OPEN:
  • uspace/srv/vfs/vfs.h

    rf0bdfb7 r95e6c4f  
    181181extern vfs_node_t *vfs_node_get(vfs_lookup_res_t *);
    182182extern void vfs_node_put(vfs_node_t *);
     183extern void vfs_node_forget(vfs_node_t *);
     184extern unsigned vfs_nodes_refcount_sum_get(fs_handle_t, dev_handle_t);
     185
    183186
    184187#define MAX_OPEN_FILES  128
     
    198201extern void vfs_register(ipc_callid_t, ipc_call_t *);
    199202extern void vfs_mount(ipc_callid_t, ipc_call_t *);
     203extern void vfs_unmount(ipc_callid_t, ipc_call_t *);
    200204extern void vfs_open(ipc_callid_t, ipc_call_t *);
    201205extern void vfs_open_node(ipc_callid_t, ipc_call_t *);
  • uspace/srv/vfs/vfs_node.c

    rf0bdfb7 r95e6c4f  
    137137        if (free_vfs_node)
    138138                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 */
     148void 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);
    139159}
    140160
     
    231251}
    232252
     253struct 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
     260static 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
     270unsigned
     271vfs_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
    233286/**
    234287 * @}
  • uspace/srv/vfs/vfs_ops.c

    rf0bdfb7 r95e6c4f  
    9292                }
    9393               
    94                 rc = vfs_lookup_internal(mp, L_DIRECTORY, &mp_res, NULL);
     94                rc = vfs_lookup_internal(mp, L_MP, &mp_res, NULL);
    9595                if (rc != EOK) {
    9696                        /* The lookup failed for some reason. */
     
    429429}
    430430
     431void 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
    431568void vfs_open(ipc_callid_t rid, ipc_call_t *request)
    432569{
     
    454591        /*
    455592         * 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.
    457595         */
    458596        if (((lflag & (L_FILE | L_DIRECTORY)) == 0) ||
    459597            ((lflag & (L_FILE | L_DIRECTORY)) == (L_FILE | L_DIRECTORY)) ||
    460             ((lflag & L_OPEN) != 0)) {
     598            (lflag & (L_OPEN | L_ROOT | L_MP))) {
    461599                ipc_answer_0(rid, EINVAL);
    462600                return;
Note: See TracChangeset for help on using the changeset viewer.