Changeset c05642d in mainline for uspace/srv


Ignore:
Timestamp:
2011-09-07T00:03:26Z (14 years ago)
Author:
Petr Koupy <petr.koupy@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
5081276
Parents:
bb74dabe (diff), 038b289 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes.

Location:
uspace/srv
Files:
30 added
18 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/bd/ata_bd/ata_bd.c

    rbb74dabe rc05642d  
    118118static int ata_pcmd_inquiry(int dev_idx, void *obuf, size_t obuf_size);
    119119static int ata_pcmd_read_12(int dev_idx, uint64_t ba, size_t cnt,
     120    void *obuf, size_t obuf_size);
     121static int ata_pcmd_read_toc(int dev_idx, uint8_t ses,
    120122    void *obuf, size_t obuf_size);
    121123static void disk_print_summary(disk_t *d);
     
    353355                            UPPER32(disk[disk_id].blocks));
    354356                        continue;
     357                case BD_READ_TOC:
     358                        cnt = IPC_GET_ARG1(call);
     359                        if (disk[disk_id].dev_type == ata_pkt_dev)
     360                                retval = ata_pcmd_read_toc(disk_id, cnt, fs_va,
     361                                    disk[disk_id].block_size);
     362                        else
     363                                retval = EINVAL;
     364                        break;
    355365                default:
    356366                        retval = EINVAL;
     
    810820}
    811821
     822/** Issue ATAPI read TOC command.
     823 *
     824 * Read TOC in 'multi-session' format (first and last session number
     825 * with last session LBA).
     826 *
     827 * http://suif.stanford.edu/~csapuntz/specs/INF-8020.PDF page 171
     828 *
     829 * Output buffer must be large enough to hold the data, otherwise the
     830 * function will fail.
     831 *
     832 * @param dev_idx       Device index (0 or 1)
     833 * @param session       Starting session
     834 * @param obuf          Buffer for storing inquiry data read from device
     835 * @param obuf_size     Size of obuf in bytes
     836 *
     837 * @return EOK on success, EIO on error.
     838 */
     839static int ata_pcmd_read_toc(int dev_idx, uint8_t session, void *obuf,
     840    size_t obuf_size)
     841{
     842        ata_pcmd_read_toc_t cp;
     843        int rc;
     844
     845        memset(&cp, 0, sizeof(cp));
     846
     847        cp.opcode = PCMD_READ_TOC;
     848        cp.msf = 0;
     849        cp.format = 0x01; /* 0x01 = multi-session mode */
     850        cp.start = session;
     851        cp.size = host2uint16_t_be(obuf_size);
     852        cp.oldformat = 0x40; /* 0x01 = multi-session mode (shifted to MSB) */
     853       
     854        rc = ata_cmd_packet(0, &cp, sizeof(cp), obuf, obuf_size);
     855        if (rc != EOK)
     856                return rc;
     857       
     858        return EOK;
     859}
     860
    812861/** Read a physical from the device.
    813862 *
  • uspace/srv/bd/ata_bd/ata_hw.h

    rbb74dabe rc05642d  
    244244enum ata_pkt_command {
    245245        PCMD_INQUIRY            = 0x12,
    246         PCMD_READ_12            = 0xa8
     246        PCMD_READ_12            = 0xa8,
     247        PCMD_READ_TOC           = 0x43
    247248};
    248249
     
    269270        uint8_t _res2;
    270271} __attribute__ ((packed)) ata_pcmd_read_12_t;
     272
     273/** ATAPI Read TOC command */
     274typedef struct {
     275        uint8_t opcode;         /**< Operation code (PCMD_READ_TOC) */
     276        uint8_t msf;            /**< 0x2 = MSF bit set */
     277        uint8_t format;         /**< low 3 bits */
     278        uint8_t _res0;
     279        uint8_t _res1;
     280        uint8_t _res2;
     281        uint8_t start;          /**< starting track/session number */
     282        uint16_t size;          /**< Allocation length */
     283        uint8_t oldformat;         /**< high 2 bits */
     284        uint8_t _res3;
     285        uint8_t _res4;
     286} __attribute__ ((packed)) ata_pcmd_read_toc_t;
    271287
    272288/** Data returned from Inquiry command (mandatory part) */
  • uspace/srv/devman/devman.c

    rbb74dabe rc05642d  
    3030 * @{
    3131 */
     32/** @file Device Manager
     33 *
     34 * Locking order:
     35 *   (1) driver_t.driver_mutex
     36 *   (2) dev_tree_t.rwlock
     37 *
     38 * Synchronization:
     39 *    - device_tree.rwlock protects:
     40 *        - tree root, complete tree topology
     41 *        - complete contents of device and function nodes
     42 *    - dev_node_t.refcnt, fun_node_t.refcnt prevent nodes from
     43 *      being deallocated
     44 *    - find_xxx() functions increase reference count of returned object
     45 *    - find_xxx_no_lock() do not increase reference count
     46 *
     47 * TODO
     48 *    - Track all steady and transient device/function states
     49 *    - Check states, wait for steady state on certain operations
     50 */
    3251
    3352#include <errno.h>
     
    4362#include "devman.h"
    4463
    45 fun_node_t *find_node_child(fun_node_t *parent, const char *name);
     64static fun_node_t *find_node_child(dev_tree_t *, fun_node_t *, const char *);
    4665
    4766/* hash table operations */
     
    406425        }
    407426       
     427        fun_add_ref(fun);
    408428        insert_fun_node(tree, fun, str_dup(""), NULL);
     429       
    409430        match_id_t *id = create_match_id();
    410431        id->id = str_dup("root");
     
    422443        }
    423444       
     445        dev_add_ref(dev);
    424446        insert_dev_node(tree, dev, fun);
    425447       
     
    467489/** Assign a driver to a device.
    468490 *
     491 * @param tree          Device tree
    469492 * @param node          The device's node in the device tree.
    470493 * @param drv           The driver.
    471494 */
    472 void attach_driver(dev_node_t *dev, driver_t *drv)
     495void attach_driver(dev_tree_t *tree, dev_node_t *dev, driver_t *drv)
    473496{
    474497        log_msg(LVL_DEBUG, "attach_driver(dev=\"%s\",drv=\"%s\")",
     
    476499       
    477500        fibril_mutex_lock(&drv->driver_mutex);
     501        fibril_rwlock_write_lock(&tree->rwlock);
    478502       
    479503        dev->drv = drv;
    480504        list_append(&dev->driver_devices, &drv->devices);
    481505       
     506        fibril_rwlock_write_unlock(&tree->rwlock);
     507        fibril_mutex_unlock(&drv->driver_mutex);
     508}
     509
     510/** Detach driver from device.
     511 *
     512 * @param tree          Device tree
     513 * @param node          The device's node in the device tree.
     514 * @param drv           The driver.
     515 */
     516void detach_driver(dev_tree_t *tree, dev_node_t *dev)
     517{
     518        driver_t *drv = dev->drv;
     519       
     520        assert(drv != NULL);
     521       
     522        log_msg(LVL_DEBUG, "detach_driver(dev=\"%s\",drv=\"%s\")",
     523            dev->pfun->pathname, drv->name);
     524       
     525        fibril_mutex_lock(&drv->driver_mutex);
     526        fibril_rwlock_write_lock(&tree->rwlock);
     527       
     528        dev->drv = NULL;
     529        list_remove(&dev->driver_devices);
     530       
     531        fibril_rwlock_write_unlock(&tree->rwlock);
    482532        fibril_mutex_unlock(&drv->driver_mutex);
    483533}
     
    556606        while (link != &driver->devices.head) {
    557607                dev = list_get_instance(link, dev_node_t, driver_devices);
     608                fibril_rwlock_write_lock(&tree->rwlock);
     609               
    558610                if (dev->passed_to_driver) {
     611                        fibril_rwlock_write_unlock(&tree->rwlock);
    559612                        link = link->next;
    560613                        continue;
    561614                }
    562615
    563                 /*
    564                  * We remove the device from the list to allow safe adding
    565                  * of new devices (no one will touch our item this way).
    566                  */
    567                 list_remove(link);
     616                log_msg(LVL_DEBUG, "pass_devices_to_driver: dev->refcnt=%d\n",
     617                    (int)atomic_get(&dev->refcnt));
     618                dev_add_ref(dev);
    568619
    569620                /*
     
    572623                 */
    573624                fibril_mutex_unlock(&driver->driver_mutex);
     625                fibril_rwlock_write_unlock(&tree->rwlock);
    574626
    575627                add_device(driver, dev, tree);
     628
     629                dev_del_ref(dev);
    576630
    577631                /*
     
    580634                 */
    581635                fibril_mutex_lock(&driver->driver_mutex);
    582 
    583                 /*
    584                  * Insert the device back.
    585                  * The order is not relevant here so no harm is done
    586                  * (actually, the order would be preserved in most cases).
    587                  */
    588                 list_append(link, &driver->devices);
    589636
    590637                /*
     
    679726        char *loc_name = NULL;
    680727       
     728        assert(fibril_rwlock_is_locked(&tree->rwlock));
     729       
    681730        asprintf(&loc_name, "%s", fun->pathname);
    682731        if (loc_name == NULL)
     
    726775       
    727776        ipc_call_t answer;
    728         aid_t req = async_send_2(exch, DRIVER_ADD_DEVICE, dev->handle,
     777        aid_t req = async_send_2(exch, DRIVER_DEV_ADD, dev->handle,
    729778            parent_handle, &answer);
    730779       
     
    783832       
    784833        /* Attach the driver to the device. */
    785         attach_driver(dev, drv);
     834        attach_driver(tree, dev, drv);
    786835       
    787836        fibril_mutex_lock(&drv->driver_mutex);
     
    797846                add_device(drv, dev, tree);
    798847       
     848        fibril_mutex_lock(&drv->driver_mutex);
     849        fibril_mutex_unlock(&drv->driver_mutex);
     850
     851        fibril_rwlock_write_lock(&tree->rwlock);
     852        if (dev->pfun != NULL) {
     853                dev->pfun->state = FUN_ON_LINE;
     854        }
     855        fibril_rwlock_write_unlock(&tree->rwlock);
    799856        return true;
     857}
     858
     859int driver_dev_remove(dev_tree_t *tree, dev_node_t *dev)
     860{
     861        async_exch_t *exch;
     862        sysarg_t retval;
     863        driver_t *drv;
     864        devman_handle_t handle;
     865       
     866        assert(dev != NULL);
     867       
     868        log_msg(LVL_DEBUG, "driver_dev_remove(%p)", dev);
     869       
     870        fibril_rwlock_read_lock(&tree->rwlock);
     871        drv = dev->drv;
     872        handle = dev->handle;
     873        fibril_rwlock_read_unlock(&tree->rwlock);
     874       
     875        exch = async_exchange_begin(drv->sess);
     876        retval = async_req_1_0(exch, DRIVER_DEV_REMOVE, handle);
     877        async_exchange_end(exch);
     878       
     879        return retval;
     880}
     881
     882int driver_dev_gone(dev_tree_t *tree, dev_node_t *dev)
     883{
     884        async_exch_t *exch;
     885        sysarg_t retval;
     886        driver_t *drv;
     887        devman_handle_t handle;
     888       
     889        assert(dev != NULL);
     890       
     891        log_msg(LVL_DEBUG, "driver_dev_gone(%p)", dev);
     892       
     893        fibril_rwlock_read_lock(&tree->rwlock);
     894        drv = dev->drv;
     895        handle = dev->handle;
     896        fibril_rwlock_read_unlock(&tree->rwlock);
     897       
     898        exch = async_exchange_begin(drv->sess);
     899        retval = async_req_1_0(exch, DRIVER_DEV_GONE, handle);
     900        async_exchange_end(exch);
     901       
     902        return retval;
     903}
     904
     905int driver_fun_online(dev_tree_t *tree, fun_node_t *fun)
     906{
     907        async_exch_t *exch;
     908        sysarg_t retval;
     909        driver_t *drv;
     910        devman_handle_t handle;
     911       
     912        log_msg(LVL_DEBUG, "driver_fun_online(%p)", fun);
     913
     914        fibril_rwlock_read_lock(&tree->rwlock);
     915       
     916        if (fun->dev == NULL) {
     917                /* XXX root function? */
     918                fibril_rwlock_read_unlock(&tree->rwlock);
     919                return EINVAL;
     920        }
     921       
     922        drv = fun->dev->drv;
     923        handle = fun->handle;
     924        fibril_rwlock_read_unlock(&tree->rwlock);
     925       
     926        exch = async_exchange_begin(drv->sess);
     927        retval = async_req_1_0(exch, DRIVER_FUN_ONLINE, handle);
     928        loc_exchange_end(exch);
     929       
     930        return retval;
     931}
     932
     933int driver_fun_offline(dev_tree_t *tree, fun_node_t *fun)
     934{
     935        async_exch_t *exch;
     936        sysarg_t retval;
     937        driver_t *drv;
     938        devman_handle_t handle;
     939       
     940        log_msg(LVL_DEBUG, "driver_fun_offline(%p)", fun);
     941
     942        fibril_rwlock_read_lock(&tree->rwlock);
     943        if (fun->dev == NULL) {
     944                /* XXX root function? */
     945                fibril_rwlock_read_unlock(&tree->rwlock);
     946                return EINVAL;
     947        }
     948       
     949        drv = fun->dev->drv;
     950        handle = fun->handle;
     951        fibril_rwlock_read_unlock(&tree->rwlock);
     952       
     953        exch = async_exchange_begin(drv->sess);
     954        retval = async_req_1_0(exch, DRIVER_FUN_OFFLINE, handle);
     955        loc_exchange_end(exch);
     956       
     957        return retval;
     958
    800959}
    801960
     
    826985        if (!create_root_nodes(tree))
    827986                return false;
    828 
     987   
    829988        /* Find suitable driver and start it. */
    830         return assign_driver(tree->root_node->child, drivers_list, tree);
     989        dev_node_t *rdev = tree->root_node->child;
     990        dev_add_ref(rdev);
     991        int rc = assign_driver(rdev, drivers_list, tree);
     992        dev_del_ref(rdev);
     993       
     994        return rc;
    831995}
    832996
     
    8391003dev_node_t *create_dev_node(void)
    8401004{
    841         dev_node_t *res = malloc(sizeof(dev_node_t));
    842        
    843         if (res != NULL) {
    844                 memset(res, 0, sizeof(dev_node_t));
    845                 list_initialize(&res->functions);
    846                 link_initialize(&res->driver_devices);
    847                 link_initialize(&res->devman_dev);
    848         }
    849        
    850         return res;
     1005        dev_node_t *dev;
     1006       
     1007        dev = calloc(1, sizeof(dev_node_t));
     1008        if (dev == NULL)
     1009                return NULL;
     1010       
     1011        atomic_set(&dev->refcnt, 0);
     1012        list_initialize(&dev->functions);
     1013        link_initialize(&dev->driver_devices);
     1014        link_initialize(&dev->devman_dev);
     1015       
     1016        return dev;
    8511017}
    8521018
     
    8641030}
    8651031
     1032/** Increase device node reference count.
     1033 *
     1034 * @param dev   Device node
     1035 */
     1036void dev_add_ref(dev_node_t *dev)
     1037{
     1038        atomic_inc(&dev->refcnt);
     1039}
     1040
     1041/** Decrease device node reference count.
     1042 *
     1043 * When the count drops to zero the device node is freed.
     1044 *
     1045 * @param dev   Device node
     1046 */
     1047void dev_del_ref(dev_node_t *dev)
     1048{
     1049        if (atomic_predec(&dev->refcnt) == 0)
     1050                delete_dev_node(dev);
     1051}
     1052
     1053
    8661054/** Find the device node structure of the device witch has the specified handle.
    8671055 *
     
    8931081        fibril_rwlock_read_lock(&tree->rwlock);
    8941082        dev = find_dev_node_no_lock(tree, handle);
     1083        if (dev != NULL)
     1084                dev_add_ref(dev);
     1085       
    8951086        fibril_rwlock_read_unlock(&tree->rwlock);
    8961087       
     
    9201111                    list_get_instance(item, fun_node_t, dev_functions);
    9211112
    922                 if (pos < buf_cnt)
     1113                if (pos < buf_cnt) {
    9231114                        hdl_buf[pos] = fun->handle;
     1115                }
     1116
    9241117                pos++;
    9251118        }
     
    9371130fun_node_t *create_fun_node(void)
    9381131{
    939         fun_node_t *res = malloc(sizeof(fun_node_t));
    940        
    941         if (res != NULL) {
    942                 memset(res, 0, sizeof(fun_node_t));
    943                 link_initialize(&res->dev_functions);
    944                 list_initialize(&res->match_ids.ids);
    945                 link_initialize(&res->devman_fun);
    946                 link_initialize(&res->loc_fun);
    947         }
    948        
    949         return res;
     1132        fun_node_t *fun;
     1133
     1134        fun = calloc(1, sizeof(fun_node_t));
     1135        if (fun == NULL)
     1136                return NULL;
     1137       
     1138        fun->state = FUN_INIT;
     1139        atomic_set(&fun->refcnt, 0);
     1140        link_initialize(&fun->dev_functions);
     1141        list_initialize(&fun->match_ids.ids);
     1142        link_initialize(&fun->devman_fun);
     1143        link_initialize(&fun->loc_fun);
     1144       
     1145        return fun;
    9501146}
    9511147
     
    9651161}
    9661162
     1163/** Increase function node reference count.
     1164 *
     1165 * @param fun   Function node
     1166 */
     1167void fun_add_ref(fun_node_t *fun)
     1168{
     1169        atomic_inc(&fun->refcnt);
     1170}
     1171
     1172/** Decrease function node reference count.
     1173 *
     1174 * When the count drops to zero the function node is freed.
     1175 *
     1176 * @param fun   Function node
     1177 */
     1178void fun_del_ref(fun_node_t *fun)
     1179{
     1180        if (atomic_predec(&fun->refcnt) == 0)
     1181                delete_fun_node(fun);
     1182}
     1183
    9671184/** Find the function node with the specified handle.
    9681185 *
     
    9751192        unsigned long key = handle;
    9761193        link_t *link;
     1194        fun_node_t *fun;
    9771195       
    9781196        assert(fibril_rwlock_is_locked(&tree->rwlock));
     
    9821200                return NULL;
    9831201       
    984         return hash_table_get_instance(link, fun_node_t, devman_fun);
     1202        fun = hash_table_get_instance(link, fun_node_t, devman_fun);
     1203       
     1204        return fun;
    9851205}
    9861206
     
    9961216       
    9971217        fibril_rwlock_read_lock(&tree->rwlock);
     1218       
    9981219        fun = find_fun_node_no_lock(tree, handle);
     1220        if (fun != NULL)
     1221                fun_add_ref(fun);
     1222       
    9991223        fibril_rwlock_read_unlock(&tree->rwlock);
    10001224       
     
    10041228/** Create and set device's full path in device tree.
    10051229 *
     1230 * @param tree          Device tree
    10061231 * @param node          The device's device node.
    10071232 * @param parent        The parent device node.
     
    10091234 *                      resources etc.).
    10101235 */
    1011 static bool set_fun_path(fun_node_t *fun, fun_node_t *parent)
    1012 {
     1236static bool set_fun_path(dev_tree_t *tree, fun_node_t *fun, fun_node_t *parent)
     1237{
     1238        assert(fibril_rwlock_is_write_locked(&tree->rwlock));
    10131239        assert(fun->name != NULL);
    10141240       
     
    10371263 *
    10381264 * @param tree          The device tree.
    1039  * @param node          The newly added device node.
    1040  * @param dev_name      The name of the newly added device.
    1041  * @param parent        The parent device node.
     1265 * @param dev           The newly added device node.
     1266 * @param pfun          The parent function node.
    10421267 *
    10431268 * @return              True on success, false otherwise (insufficient resources
     
    10461271bool insert_dev_node(dev_tree_t *tree, dev_node_t *dev, fun_node_t *pfun)
    10471272{
    1048         assert(dev != NULL);
    1049         assert(tree != NULL);
    10501273        assert(fibril_rwlock_is_write_locked(&tree->rwlock));
    10511274       
     
    10651288}
    10661289
     1290/** Remove device from device tree.
     1291 *
     1292 * @param tree          Device tree
     1293 * @param dev           Device node
     1294 */
     1295void remove_dev_node(dev_tree_t *tree, dev_node_t *dev)
     1296{
     1297        assert(fibril_rwlock_is_write_locked(&tree->rwlock));
     1298       
     1299        log_msg(LVL_DEBUG, "remove_dev_node(dev=%p)", dev);
     1300       
     1301        /* Remove node from the handle-to-node map. */
     1302        unsigned long key = dev->handle;
     1303        hash_table_remove(&tree->devman_devices, &key, 1);
     1304       
     1305        /* Unlink from parent function. */
     1306        dev->pfun->child = NULL;
     1307        dev->pfun = NULL;
     1308       
     1309        dev->state = DEVICE_REMOVED;
     1310}
     1311
     1312
    10671313/** Insert new function into device tree.
    10681314 *
    10691315 * @param tree          The device tree.
    1070  * @param node          The newly added function node.
    1071  * @param dev_name      The name of the newly added function.
    1072  * @param parent        Owning device node.
     1316 * @param fun           The newly added function node.
     1317 * @param fun_name      The name of the newly added function.
     1318 * @param dev           Owning device node.
    10731319 *
    10741320 * @return              True on success, false otherwise (insufficient resources
     
    10801326        fun_node_t *pfun;
    10811327       
    1082         assert(fun != NULL);
    1083         assert(tree != NULL);
    10841328        assert(fun_name != NULL);
    10851329        assert(fibril_rwlock_is_write_locked(&tree->rwlock));
     
    10921336       
    10931337        fun->name = fun_name;
    1094         if (!set_fun_path(fun, pfun)) {
     1338        if (!set_fun_path(tree, fun, pfun)) {
    10951339                return false;
    10961340        }
     
    11161360void remove_fun_node(dev_tree_t *tree, fun_node_t *fun)
    11171361{
    1118         assert(tree != NULL);
    1119         assert(fun != NULL);
    11201362        assert(fibril_rwlock_is_write_locked(&tree->rwlock));
    11211363       
     
    11271369        if (fun->dev != NULL)
    11281370                list_remove(&fun->dev_functions);
     1371       
     1372        fun->dev = NULL;
     1373        fun->state = FUN_REMOVED;
    11291374}
    11301375
     
    11481393       
    11491394        fun_node_t *fun = tree->root_node;
     1395        fun_add_ref(fun);
    11501396        /*
    11511397         * Relative path to the function from its parent (but with '/' at the
     
    11651411                }
    11661412               
    1167                 fun = find_node_child(fun, rel_path + 1);
     1413                fun_node_t *cfun = find_node_child(tree, fun, rel_path + 1);
     1414                fun_del_ref(fun);
     1415                fun = cfun;
    11681416               
    11691417                if (cont) {
     
    11831431 * Device tree rwlock should be held at least for reading.
    11841432 *
     1433 * @param tree Device tree
    11851434 * @param dev Device the function belongs to.
    11861435 * @param name Function name (not path).
     
    11881437 * @retval NULL No function with given name.
    11891438 */
    1190 fun_node_t *find_fun_node_in_device(dev_node_t *dev, const char *name)
    1191 {
    1192         assert(dev != NULL);
     1439fun_node_t *find_fun_node_in_device(dev_tree_t *tree, dev_node_t *dev,
     1440    const char *name)
     1441{
    11931442        assert(name != NULL);
     1443        assert(fibril_rwlock_is_locked(&tree->rwlock));
    11941444
    11951445        fun_node_t *fun;
     
    11981448                fun = list_get_instance(link, fun_node_t, dev_functions);
    11991449
    1200                 if (str_cmp(name, fun->name) == 0)
     1450                if (str_cmp(name, fun->name) == 0) {
     1451                        fun_add_ref(fun);
    12011452                        return fun;
     1453                }
    12021454        }
    12031455
     
    12091461 * Device tree rwlock should be held at least for reading.
    12101462 *
     1463 * @param tree          Device tree
    12111464 * @param parent        The parent function node.
    12121465 * @param name          The name of the child function.
    12131466 * @return              The child function node.
    12141467 */
    1215 fun_node_t *find_node_child(fun_node_t *pfun, const char *name)
    1216 {
    1217         return find_fun_node_in_device(pfun->child, name);
     1468static fun_node_t *find_node_child(dev_tree_t *tree, fun_node_t *pfun,
     1469    const char *name)
     1470{
     1471        return find_fun_node_in_device(tree, pfun->child, name);
    12181472}
    12191473
     
    12281482        fibril_rwlock_read_lock(&tree->rwlock);
    12291483        link = hash_table_find(&tree->loc_functions, &key);
    1230         if (link != NULL)
     1484        if (link != NULL) {
    12311485                fun = hash_table_get_instance(link, fun_node_t, loc_fun);
     1486                fun_add_ref(fun);
     1487        }
    12321488        fibril_rwlock_read_unlock(&tree->rwlock);
    12331489       
     
    12371493void tree_add_loc_function(dev_tree_t *tree, fun_node_t *fun)
    12381494{
     1495        assert(fibril_rwlock_is_write_locked(&tree->rwlock));
     1496       
    12391497        unsigned long key = (unsigned long) fun->service_id;
    1240         fibril_rwlock_write_lock(&tree->rwlock);
    12411498        hash_table_insert(&tree->loc_functions, &key, &fun->loc_fun);
    1242         fibril_rwlock_write_unlock(&tree->rwlock);
    12431499}
    12441500
  • uspace/srv/devman/devman.h

    rbb74dabe rc05642d  
    118118} driver_list_t;
    119119
    120 /** The state of the device. */
     120/** Device state */
    121121typedef enum {
    122122        DEVICE_NOT_INITIALIZED = 0,
    123123        DEVICE_USABLE,
    124124        DEVICE_NOT_PRESENT,
    125         DEVICE_INVALID
     125        DEVICE_INVALID,
     126        /** Device node has been removed from the tree */
     127        DEVICE_REMOVED
    126128} device_state_t;
    127129
    128130/** Device node in the device tree. */
    129131struct dev_node {
     132        /** Reference count */
     133        atomic_t refcnt;
     134       
    130135        /** The global unique identifier of the device. */
    131136        devman_handle_t handle;
     
    154159};
    155160
     161/** Function state */
     162typedef enum {
     163        FUN_INIT = 0,
     164        FUN_OFF_LINE,
     165        FUN_ON_LINE,
     166        /** Function node has been removed from the tree */
     167        FUN_REMOVED
     168} fun_state_t;
     169
    156170/** Function node in the device tree. */
    157171struct fun_node {
     172        /** Reference count */
     173        atomic_t refcnt;
     174        /** State */
     175        fun_state_t state;
     176       
    158177        /** The global unique identifier of the function */
    159178        devman_handle_t handle;
     
    239258
    240259extern void add_driver(driver_list_t *, driver_t *);
    241 extern void attach_driver(dev_node_t *, driver_t *);
     260extern void attach_driver(dev_tree_t *, dev_node_t *, driver_t *);
     261extern void detach_driver(dev_tree_t *, dev_node_t *);
    242262extern void add_device(driver_t *, dev_node_t *, dev_tree_t *);
    243263extern bool start_driver(driver_t *);
     264extern int driver_dev_remove(dev_tree_t *, dev_node_t *);
     265extern int driver_dev_gone(dev_tree_t *, dev_node_t *);
     266extern int driver_fun_online(dev_tree_t *, fun_node_t *);
     267extern int driver_fun_offline(dev_tree_t *, fun_node_t *);
    244268
    245269extern driver_t *find_driver(driver_list_t *, const char *);
     
    254278extern dev_node_t *create_dev_node(void);
    255279extern void delete_dev_node(dev_node_t *node);
     280extern void dev_add_ref(dev_node_t *);
     281extern void dev_del_ref(dev_node_t *);
    256282extern dev_node_t *find_dev_node_no_lock(dev_tree_t *tree,
    257283    devman_handle_t handle);
     
    263289extern fun_node_t *create_fun_node(void);
    264290extern void delete_fun_node(fun_node_t *);
     291extern void fun_add_ref(fun_node_t *);
     292extern void fun_del_ref(fun_node_t *);
    265293extern fun_node_t *find_fun_node_no_lock(dev_tree_t *tree,
    266294    devman_handle_t handle);
    267295extern fun_node_t *find_fun_node(dev_tree_t *tree, devman_handle_t handle);
    268296extern fun_node_t *find_fun_node_by_path(dev_tree_t *, char *);
    269 extern fun_node_t *find_fun_node_in_device(dev_node_t *, const char *);
     297extern fun_node_t *find_fun_node_in_device(dev_tree_t *tree, dev_node_t *,
     298    const char *);
    270299
    271300/* Device tree */
     
    274303extern bool create_root_nodes(dev_tree_t *);
    275304extern bool insert_dev_node(dev_tree_t *, dev_node_t *, fun_node_t *);
     305extern void remove_dev_node(dev_tree_t *, dev_node_t *);
    276306extern bool insert_fun_node(dev_tree_t *, fun_node_t *, char *, dev_node_t *);
    277307extern void remove_fun_node(dev_tree_t *, fun_node_t *);
  • uspace/srv/devman/main.c

    rbb74dabe rc05642d  
    234234        dev_node_t *dev_node = (dev_node_t *) arg;
    235235        assign_driver(dev_node, &drivers_list, &device_tree);
     236
     237        /* Delete one reference we got from the caller. */
     238        dev_del_ref(dev_node);
    236239        return EOK;
    237240}
    238241
    239 /** Handle function registration.
    240  *
    241  * Child devices are registered by their parent's device driver.
    242  */
    243 static void devman_add_function(ipc_callid_t callid, ipc_call_t *call)
    244 {
    245         fun_type_t ftype = (fun_type_t) IPC_GET_ARG1(*call);
    246         devman_handle_t dev_handle = IPC_GET_ARG2(*call);
    247         sysarg_t match_count = IPC_GET_ARG3(*call);
    248         dev_tree_t *tree = &device_tree;
    249        
    250         fibril_rwlock_write_lock(&tree->rwlock);
    251 
    252         dev_node_t *dev = NULL;
    253         dev_node_t *pdev = find_dev_node_no_lock(&device_tree, dev_handle);
    254        
    255         if (pdev == NULL) {
    256                 fibril_rwlock_write_unlock(&tree->rwlock);
    257                 async_answer_0(callid, ENOENT);
    258                 return;
    259         }
    260        
    261         if (ftype != fun_inner && ftype != fun_exposed) {
    262                 /* Unknown function type */
    263                 log_msg(LVL_ERROR,
    264                     "Unknown function type %d provided by driver.",
    265                     (int) ftype);
    266 
    267                 fibril_rwlock_write_unlock(&tree->rwlock);
    268                 async_answer_0(callid, EINVAL);
    269                 return;
    270         }
    271        
    272         char *fun_name = NULL;
    273         int rc = async_data_write_accept((void **)&fun_name, true, 0, 0, 0, 0);
    274         if (rc != EOK) {
    275                 fibril_rwlock_write_unlock(&tree->rwlock);
    276                 async_answer_0(callid, rc);
    277                 return;
    278         }
    279        
    280         /* Check that function with same name is not there already. */
    281         if (find_fun_node_in_device(pdev, fun_name) != NULL) {
    282                 fibril_rwlock_write_unlock(&tree->rwlock);
    283                 async_answer_0(callid, EEXISTS);
    284                 printf(NAME ": Warning, driver tried to register `%s' twice.\n",
    285                     fun_name);
    286                 free(fun_name);
    287                 return;
    288         }
    289        
    290         fun_node_t *fun = create_fun_node();
    291         fun->ftype = ftype;
    292        
    293         if (!insert_fun_node(&device_tree, fun, fun_name, pdev)) {
    294                 fibril_rwlock_write_unlock(&tree->rwlock);
    295                 delete_fun_node(fun);
    296                 async_answer_0(callid, ENOMEM);
    297                 return;
    298         }
    299 
    300         if (ftype == fun_inner) {
     242static int online_function(fun_node_t *fun)
     243{
     244        dev_node_t *dev;
     245       
     246        fibril_rwlock_write_lock(&device_tree.rwlock);
     247
     248        if (fun->state == FUN_ON_LINE) {
     249                fibril_rwlock_write_unlock(&device_tree.rwlock);
     250                log_msg(LVL_WARN, "Function %s is already on line.",
     251                    fun->pathname);
     252                return EOK;
     253        }
     254       
     255        if (fun->ftype == fun_inner) {
    301256                dev = create_dev_node();
    302257                if (dev == NULL) {
    303                         fibril_rwlock_write_unlock(&tree->rwlock);
    304                         delete_fun_node(fun);
    305                         async_answer_0(callid, ENOMEM);
    306                         return;
     258                        fibril_rwlock_write_unlock(&device_tree.rwlock);
     259                        return ENOMEM;
    307260                }
    308261
    309                 insert_dev_node(tree, dev, fun);
    310         }
    311 
    312         fibril_rwlock_write_unlock(&tree->rwlock);
     262                insert_dev_node(&device_tree, dev, fun);
     263                dev_add_ref(dev);
     264        }
    313265       
    314266        log_msg(LVL_DEBUG, "devman_add_function(fun=\"%s\")", fun->pathname);
    315267       
    316         devman_receive_match_ids(match_count, &fun->match_ids);
    317 
    318         if (ftype == fun_inner) {
     268        if (fun->ftype == fun_inner) {
     269                dev = fun->child;
    319270                assert(dev != NULL);
     271               
     272                /* Give one reference over to assign_driver_fibril(). */
     273                dev_add_ref(dev);
    320274                /*
    321275                 * Try to find a suitable driver and assign it to the device.  We do
     
    327281                fid_t assign_fibril = fibril_create(assign_driver_fibril, dev);
    328282                if (assign_fibril == 0) {
    329                         /*
    330                          * Fallback in case we are out of memory.
    331                          * Probably not needed as we will die soon anyway ;-).
    332                          */
    333                         (void) assign_driver_fibril(fun);
    334                 } else {
    335                         fibril_add_ready(assign_fibril);
     283                        log_msg(LVL_ERROR, "Failed to create fibril for "
     284                            "assigning driver.");
     285                        /* XXX Cleanup */
     286                        fibril_rwlock_write_unlock(&device_tree.rwlock);
     287                        return ENOMEM;
     288                }
     289                fibril_add_ready(assign_fibril);
     290        } else {
     291                loc_register_tree_function(fun, &device_tree);
     292        }
     293       
     294        fibril_rwlock_write_unlock(&device_tree.rwlock);
     295       
     296        return EOK;
     297}
     298
     299static int offline_function(fun_node_t *fun)
     300{
     301        int rc;
     302       
     303        fibril_rwlock_write_lock(&device_tree.rwlock);
     304       
     305        if (fun->state == FUN_OFF_LINE) {
     306                fibril_rwlock_write_unlock(&device_tree.rwlock);
     307                log_msg(LVL_WARN, "Function %s is already off line.",
     308                    fun->pathname);
     309                return EOK;
     310        }
     311       
     312        if (fun->ftype == fun_inner) {
     313                log_msg(LVL_DEBUG, "Offlining inner function %s.",
     314                    fun->pathname);
     315               
     316                if (fun->child != NULL) {
     317                        dev_node_t *dev = fun->child;
     318                        device_state_t dev_state;
     319                       
     320                        dev_add_ref(dev);
     321                        dev_state = dev->state;
     322                       
     323                        fibril_rwlock_write_unlock(&device_tree.rwlock);
     324
     325                        /* If device is owned by driver, ask driver to give it up. */
     326                        if (dev_state == DEVICE_USABLE) {
     327                                rc = driver_dev_remove(&device_tree, dev);
     328                                if (rc != EOK) {
     329                                        dev_del_ref(dev);
     330                                        return ENOTSUP;
     331                                }
     332                        }
     333                       
     334                        /* Verify that driver removed all functions */
     335                        fibril_rwlock_read_lock(&device_tree.rwlock);
     336                        if (!list_empty(&dev->functions)) {
     337                                fibril_rwlock_read_unlock(&device_tree.rwlock);
     338                                dev_del_ref(dev);
     339                                return EIO;
     340                        }
     341                       
     342                        driver_t *driver = dev->drv;
     343                        fibril_rwlock_read_unlock(&device_tree.rwlock);
     344                       
     345                        if (driver)
     346                                detach_driver(&device_tree, dev);
     347                       
     348                        fibril_rwlock_write_lock(&device_tree.rwlock);
     349                        remove_dev_node(&device_tree, dev);
     350                       
     351                        /* Delete ref created when node was inserted */
     352                        dev_del_ref(dev);
     353                        /* Delete ref created by dev_add_ref(dev) above */
     354                        dev_del_ref(dev);
    336355                }
    337356        } else {
    338                 loc_register_tree_function(fun, tree);
     357                /* Unregister from location service */
     358                rc = loc_service_unregister(fun->service_id);
     359                if (rc != EOK) {
     360                        fibril_rwlock_write_unlock(&device_tree.rwlock);
     361                        log_msg(LVL_ERROR, "Failed unregistering tree service.");
     362                        return EIO;
     363                }
     364               
     365                fun->service_id = 0;
     366        }
     367       
     368        fun->state = FUN_OFF_LINE;
     369        fibril_rwlock_write_unlock(&device_tree.rwlock);
     370       
     371        return EOK;
     372}
     373
     374/** Handle function registration.
     375 *
     376 * Child devices are registered by their parent's device driver.
     377 */
     378static void devman_add_function(ipc_callid_t callid, ipc_call_t *call)
     379{
     380        fun_type_t ftype = (fun_type_t) IPC_GET_ARG1(*call);
     381        devman_handle_t dev_handle = IPC_GET_ARG2(*call);
     382        sysarg_t match_count = IPC_GET_ARG3(*call);
     383        dev_tree_t *tree = &device_tree;
     384       
     385        dev_node_t *pdev = find_dev_node(&device_tree, dev_handle);
     386        if (pdev == NULL) {
     387                async_answer_0(callid, ENOENT);
     388                return;
     389        }
     390       
     391        if (ftype != fun_inner && ftype != fun_exposed) {
     392                /* Unknown function type */
     393                log_msg(LVL_ERROR,
     394                    "Unknown function type %d provided by driver.",
     395                    (int) ftype);
     396
     397                dev_del_ref(pdev);
     398                async_answer_0(callid, EINVAL);
     399                return;
     400        }
     401       
     402        char *fun_name = NULL;
     403        int rc = async_data_write_accept((void **)&fun_name, true, 0, 0, 0, 0);
     404        if (rc != EOK) {
     405                dev_del_ref(pdev);
     406                async_answer_0(callid, rc);
     407                return;
     408        }
     409       
     410        fibril_rwlock_write_lock(&tree->rwlock);
     411       
     412        /* Check device state */
     413        if (pdev->state == DEVICE_REMOVED) {
     414                fibril_rwlock_write_unlock(&tree->rwlock);
     415                dev_del_ref(pdev);
     416                async_answer_0(callid, ENOENT);
     417                return;
     418        }
     419       
     420        /* Check that function with same name is not there already. */
     421        if (find_fun_node_in_device(tree, pdev, fun_name) != NULL) {
     422                fibril_rwlock_write_unlock(&tree->rwlock);
     423                dev_del_ref(pdev);
     424                async_answer_0(callid, EEXISTS);
     425                printf(NAME ": Warning, driver tried to register `%s' twice.\n",
     426                    fun_name);
     427                free(fun_name);
     428                return;
     429        }
     430       
     431        fun_node_t *fun = create_fun_node();
     432        fun_add_ref(fun);
     433        fun->ftype = ftype;
     434       
     435        if (!insert_fun_node(&device_tree, fun, fun_name, pdev)) {
     436                fibril_rwlock_write_unlock(&tree->rwlock);
     437                dev_del_ref(pdev);
     438                delete_fun_node(fun);
     439                async_answer_0(callid, ENOMEM);
     440                return;
     441        }
     442       
     443        fibril_rwlock_write_unlock(&tree->rwlock);
     444        dev_del_ref(pdev);
     445       
     446        devman_receive_match_ids(match_count, &fun->match_ids);
     447       
     448        rc = online_function(fun);
     449        if (rc != EOK) {
     450                /* XXX clean up */
     451                async_answer_0(callid, rc);
     452                return;
    339453        }
    340454       
     
    356470                async_answer_0(callid, rc);
    357471                return;
    358         }       
     472        }
    359473       
    360474        fun_node_t *fun = find_fun_node(&device_tree, handle);
    361475        if (fun == NULL) {
     476                async_answer_0(callid, ENOENT);
     477                return;
     478        }
     479       
     480        fibril_rwlock_read_lock(&device_tree.rwlock);
     481       
     482        /* Check function state */
     483        if (fun->state == FUN_REMOVED) {
     484                fibril_rwlock_read_unlock(&device_tree.rwlock);
    362485                async_answer_0(callid, ENOENT);
    363486                return;
     
    375498            fun->pathname, cat_name);
    376499
     500        fibril_rwlock_read_unlock(&device_tree.rwlock);
     501        fun_del_ref(fun);
     502
    377503        async_answer_0(callid, EOK);
     504}
     505
     506/** Online function by driver request.
     507 *
     508 */
     509static void devman_drv_fun_online(ipc_callid_t iid, ipc_call_t *icall,
     510    driver_t *drv)
     511{
     512        fun_node_t *fun;
     513        int rc;
     514       
     515        log_msg(LVL_DEBUG, "devman_drv_fun_online()");
     516       
     517        fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall));
     518        if (fun == NULL) {
     519                async_answer_0(iid, ENOENT);
     520                return;
     521        }
     522       
     523        fibril_rwlock_read_lock(&device_tree.rwlock);
     524        if (fun->dev == NULL || fun->dev->drv != drv) {
     525                fibril_rwlock_read_unlock(&device_tree.rwlock);
     526                fun_del_ref(fun);
     527                async_answer_0(iid, ENOENT);
     528                return;
     529        }
     530        fibril_rwlock_read_unlock(&device_tree.rwlock);
     531       
     532        rc = online_function(fun);
     533        if (rc != EOK) {
     534                fun_del_ref(fun);
     535                async_answer_0(iid, (sysarg_t) rc);
     536                return;
     537        }
     538       
     539        fun_del_ref(fun);
     540       
     541        async_answer_0(iid, (sysarg_t) EOK);
     542}
     543
     544
     545/** Offline function by driver request.
     546 *
     547 */
     548static void devman_drv_fun_offline(ipc_callid_t iid, ipc_call_t *icall,
     549    driver_t *drv)
     550{
     551        fun_node_t *fun;
     552        int rc;
     553
     554        fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall));
     555        if (fun == NULL) {
     556                async_answer_0(iid, ENOENT);
     557                return;
     558        }
     559       
     560        fibril_rwlock_write_lock(&device_tree.rwlock);
     561        if (fun->dev == NULL || fun->dev->drv != drv) {
     562                fun_del_ref(fun);
     563                async_answer_0(iid, ENOENT);
     564                return;
     565        }
     566        fibril_rwlock_write_unlock(&device_tree.rwlock);
     567       
     568        rc = offline_function(fun);
     569        if (rc != EOK) {
     570                fun_del_ref(fun);
     571                async_answer_0(iid, (sysarg_t) rc);
     572                return;
     573        }
     574       
     575        fun_del_ref(fun);
     576        async_answer_0(iid, (sysarg_t) EOK);
    378577}
    379578
     
    385584        int rc;
    386585       
     586        fun_node_t *fun = find_fun_node(&device_tree, fun_handle);
     587        if (fun == NULL) {
     588                async_answer_0(callid, ENOENT);
     589                return;
     590        }
     591       
    387592        fibril_rwlock_write_lock(&tree->rwlock);
    388593       
    389         fun_node_t *fun = find_fun_node_no_lock(&device_tree, fun_handle);
    390         if (fun == NULL) {
     594        log_msg(LVL_DEBUG, "devman_remove_function(fun='%s')", fun->pathname);
     595       
     596        /* Check function state */
     597        if (fun->state == FUN_REMOVED) {
    391598                fibril_rwlock_write_unlock(&tree->rwlock);
    392599                async_answer_0(callid, ENOENT);
     
    394601        }
    395602       
    396         log_msg(LVL_DEBUG, "devman_remove_function(fun='%s')", fun->pathname);
    397        
    398603        if (fun->ftype == fun_inner) {
    399                 /* Handle possible descendants */
    400                 /* TODO */
    401                 log_msg(LVL_WARN, "devman_remove_function(): not handling "
    402                     "descendants\n");
     604                /* This is a surprise removal. Handle possible descendants */
     605                if (fun->child != NULL) {
     606                        dev_node_t *dev = fun->child;
     607                        device_state_t dev_state;
     608                        int gone_rc;
     609                       
     610                        dev_add_ref(dev);
     611                        dev_state = dev->state;
     612                       
     613                        fibril_rwlock_write_unlock(&device_tree.rwlock);
     614                       
     615                        /* If device is owned by driver, inform driver it is gone. */
     616                        if (dev_state == DEVICE_USABLE)
     617                                gone_rc = driver_dev_gone(&device_tree, dev);
     618                        else
     619                                gone_rc = EOK;
     620                       
     621                        fibril_rwlock_read_lock(&device_tree.rwlock);
     622                       
     623                        /* Verify that driver succeeded and removed all functions */
     624                        if (gone_rc != EOK || !list_empty(&dev->functions)) {
     625                                log_msg(LVL_ERROR, "Driver did not remove "
     626                                    "functions for device that is gone. "
     627                                    "Device node is now defunct.");
     628                               
     629                                /*
     630                                 * Not much we can do but mark the device
     631                                 * node as having invalid state. This
     632                                 * is a driver bug.
     633                                 */
     634                                dev->state = DEVICE_INVALID;
     635                                fibril_rwlock_read_unlock(&device_tree.rwlock);
     636                                dev_del_ref(dev);
     637                                return;
     638                        }
     639                       
     640                        driver_t *driver = dev->drv;
     641                        fibril_rwlock_read_unlock(&device_tree.rwlock);
     642                       
     643                        if (driver)
     644                                detach_driver(&device_tree, dev);
     645                       
     646                        fibril_rwlock_write_lock(&device_tree.rwlock);
     647                        remove_dev_node(&device_tree, dev);
     648                       
     649                        /* Delete ref created when node was inserted */
     650                        dev_del_ref(dev);
     651                        /* Delete ref created by dev_add_ref(dev) above */
     652                        dev_del_ref(dev);
     653                }
    403654        } else {
    404                 /* Unregister from location service */
    405                 rc = loc_service_unregister(fun->service_id);
    406                 if (rc != EOK) {
    407                         log_msg(LVL_ERROR, "Failed unregistering tree service.");
    408                         fibril_rwlock_write_unlock(&tree->rwlock);
    409                         async_answer_0(callid, EIO);
    410                         return;
     655                if (fun->service_id != 0) {
     656                        /* Unregister from location service */
     657                        rc = loc_service_unregister(fun->service_id);
     658                        if (rc != EOK) {
     659                                log_msg(LVL_ERROR, "Failed unregistering tree "
     660                                    "service.");
     661                                fibril_rwlock_write_unlock(&tree->rwlock);
     662                                fun_del_ref(fun);
     663                                async_answer_0(callid, EIO);
     664                                return;
     665                        }
    411666                }
    412667        }
     
    414669        remove_fun_node(&device_tree, fun);
    415670        fibril_rwlock_write_unlock(&tree->rwlock);
    416         delete_fun_node(fun);
     671       
     672        /* Delete ref added when inserting function into tree */
     673        fun_del_ref(fun);
     674        /* Delete ref added above when looking up function */
     675        fun_del_ref(fun);
    417676       
    418677        log_msg(LVL_DEBUG, "devman_remove_function() succeeded.");
     
    485744                        devman_add_function_to_cat(callid, &call);
    486745                        break;
     746                case DEVMAN_DRV_FUN_ONLINE:
     747                        devman_drv_fun_online(callid, &call, driver);
     748                        break;
     749                case DEVMAN_DRV_FUN_OFFLINE:
     750                        devman_drv_fun_offline(callid, &call, driver);
     751                        break;
    487752                case DEVMAN_REMOVE_FUNCTION:
    488753                        devman_remove_function(callid, &call);
    489754                        break;
    490755                default:
    491                         async_answer_0(callid, EINVAL); 
     756                        async_answer_0(callid, EINVAL);
    492757                        break;
    493758                }
     
    500765{
    501766        char *pathname;
     767        devman_handle_t handle;
    502768       
    503769        int rc = async_data_write_accept((void **) &pathname, true, 0, 0, 0, 0);
     
    516782        }
    517783
    518         async_answer_1(iid, EOK, fun->handle);
     784        fibril_rwlock_read_lock(&device_tree.rwlock);
     785
     786        /* Check function state */
     787        if (fun->state == FUN_REMOVED) {
     788                fibril_rwlock_read_unlock(&device_tree.rwlock);
     789                async_answer_0(iid, ENOENT);
     790                return;
     791        }
     792        handle = fun->handle;
     793
     794        fibril_rwlock_read_unlock(&device_tree.rwlock);
     795
     796        /* Delete reference created above by find_fun_node_by_path() */
     797        fun_del_ref(fun);
     798
     799        async_answer_1(iid, EOK, handle);
    519800}
    520801
     
    534815        if (!async_data_read_receive(&data_callid, &data_len)) {
    535816                async_answer_0(iid, EINVAL);
     817                fun_del_ref(fun);
    536818                return;
    537819        }
     
    541823                async_answer_0(data_callid, ENOMEM);
    542824                async_answer_0(iid, ENOMEM);
     825                fun_del_ref(fun);
     826                return;
     827        }
     828
     829        fibril_rwlock_read_lock(&device_tree.rwlock);
     830
     831        /* Check function state */
     832        if (fun->state == FUN_REMOVED) {
     833                fibril_rwlock_read_unlock(&device_tree.rwlock);
     834                free(buffer);
     835
     836                async_answer_0(data_callid, ENOENT);
     837                async_answer_0(iid, ENOENT);
     838                fun_del_ref(fun);
    543839                return;
    544840        }
     
    552848        async_answer_0(iid, EOK);
    553849
     850        fibril_rwlock_read_unlock(&device_tree.rwlock);
     851        fun_del_ref(fun);
    554852        free(buffer);
    555853}
     
    571869        if (!async_data_read_receive(&data_callid, &data_len)) {
    572870                async_answer_0(iid, EINVAL);
     871                fun_del_ref(fun);
    573872                return;
    574873        }
     
    578877                async_answer_0(data_callid, ENOMEM);
    579878                async_answer_0(iid, ENOMEM);
    580                 return;
    581         }
    582 
     879                fun_del_ref(fun);
     880                return;
     881        }
     882       
     883        fibril_rwlock_read_lock(&device_tree.rwlock);
     884       
     885        /* Check function state */
     886        if (fun->state == FUN_REMOVED) {
     887                fibril_rwlock_read_unlock(&device_tree.rwlock);
     888                free(buffer);
     889
     890                async_answer_0(data_callid, ENOENT);
     891                async_answer_0(iid, ENOENT);
     892                fun_del_ref(fun);
     893                return;
     894        }
     895       
    583896        size_t sent_length = str_size(fun->pathname);
    584897        if (sent_length > data_len) {
     
    589902        async_answer_0(iid, EOK);
    590903
     904        fibril_rwlock_read_unlock(&device_tree.rwlock);
     905        fun_del_ref(fun);
    591906        free(buffer);
    592907}
     
    609924        dev_node_t *dev = find_dev_node_no_lock(&device_tree,
    610925            IPC_GET_ARG1(*icall));
    611         if (dev == NULL) {
     926        if (dev == NULL || dev->state == DEVICE_REMOVED) {
    612927                fibril_rwlock_read_unlock(&device_tree.rwlock);
    613928                async_answer_0(callid, ENOENT);
     
    648963        fibril_rwlock_read_lock(&device_tree.rwlock);
    649964       
     965        fun = find_fun_node_no_lock(&device_tree, IPC_GET_ARG1(*icall));
     966        if (fun == NULL || fun->state == FUN_REMOVED) {
     967                fibril_rwlock_read_unlock(&device_tree.rwlock);
     968                async_answer_0(iid, ENOENT);
     969                return;
     970        }
     971       
     972        if (fun->child == NULL) {
     973                fibril_rwlock_read_unlock(&device_tree.rwlock);
     974                async_answer_0(iid, ENOENT);
     975                return;
     976        }
     977       
     978        async_answer_1(iid, EOK, fun->child->handle);
     979       
     980        fibril_rwlock_read_unlock(&device_tree.rwlock);
     981}
     982
     983/** Online function.
     984 *
     985 * Send a request to online a function to the responsible driver.
     986 * The driver may offline other functions if necessary (i.e. if the state
     987 * of this function is linked to state of another function somehow).
     988 */
     989static void devman_fun_online(ipc_callid_t iid, ipc_call_t *icall)
     990{
     991        fun_node_t *fun;
     992        int rc;
     993
    650994        fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall));
    651995        if (fun == NULL) {
    652                 fibril_rwlock_read_unlock(&device_tree.rwlock);
    653                 async_answer_0(iid, ENOENT);
    654                 return;
    655         }
    656        
    657         if (fun->child == NULL) {
    658                 fibril_rwlock_read_unlock(&device_tree.rwlock);
    659                 async_answer_0(iid, ENOENT);
    660                 return;
    661         }
    662        
    663         async_answer_1(iid, EOK, fun->child->handle);
    664        
    665         fibril_rwlock_read_unlock(&device_tree.rwlock);
     996                async_answer_0(iid, ENOENT);
     997                return;
     998        }
     999       
     1000        rc = driver_fun_online(&device_tree, fun);
     1001        fun_del_ref(fun);
     1002       
     1003        async_answer_0(iid, (sysarg_t) rc);
     1004}
     1005
     1006/** Offline function.
     1007 *
     1008 * Send a request to offline a function to the responsible driver. As
     1009 * a result the subtree rooted at that function should be cleanly
     1010 * detatched. The driver may offline other functions if necessary
     1011 * (i.e. if the state of this function is linked to state of another
     1012 * function somehow).
     1013 */
     1014static void devman_fun_offline(ipc_callid_t iid, ipc_call_t *icall)
     1015{
     1016        fun_node_t *fun;
     1017        int rc;
     1018
     1019        fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall));
     1020        if (fun == NULL) {
     1021                async_answer_0(iid, ENOENT);
     1022                return;
     1023        }
     1024       
     1025        rc = driver_fun_offline(&device_tree, fun);
     1026        fun_del_ref(fun);
     1027       
     1028        async_answer_0(iid, (sysarg_t) rc);
    6661029}
    6671030
     
    6781041        }
    6791042
     1043        fibril_rwlock_read_lock(&device_tree.rwlock);
     1044
     1045        /* Check function state */
     1046        if (fun->state == FUN_REMOVED) {
     1047                fibril_rwlock_read_unlock(&device_tree.rwlock);
     1048                async_answer_0(iid, ENOENT);
     1049                return;
     1050        }
     1051
    6801052        async_answer_1(iid, EOK, fun->handle);
     1053        fibril_rwlock_read_unlock(&device_tree.rwlock);
     1054        fun_del_ref(fun);
    6811055}
    6821056
     
    7101084                        devman_fun_get_path(callid, &call);
    7111085                        break;
     1086                case DEVMAN_FUN_ONLINE:
     1087                        devman_fun_online(callid, &call);
     1088                        break;
     1089                case DEVMAN_FUN_OFFLINE:
     1090                        devman_fun_offline(callid, &call);
     1091                        break;
    7121092                case DEVMAN_FUN_SID_TO_HANDLE:
    7131093                        devman_fun_sid_to_handle(callid, &call);
     
    7301110        if (fun == NULL)
    7311111                dev = find_dev_node(&device_tree, handle);
    732         else
     1112        else {
     1113                fibril_rwlock_read_lock(&device_tree.rwlock);
    7331114                dev = fun->dev;
     1115                if (dev != NULL)
     1116                        dev_add_ref(dev);
     1117                fibril_rwlock_read_unlock(&device_tree.rwlock);
     1118        }
    7341119
    7351120        /*
     
    7431128                    "function with handle %" PRIun " was found.", handle);
    7441129                async_answer_0(iid, ENOENT);
    745                 return;
     1130                goto cleanup;
    7461131        }
    7471132
     
    7511136                    handle);
    7521137                async_answer_0(iid, ENOENT);
    753                 return;
     1138                goto cleanup;
    7541139        }
    7551140       
    7561141        driver_t *driver = NULL;
     1142       
     1143        fibril_rwlock_read_lock(&device_tree.rwlock);
    7571144       
    7581145        if (drv_to_parent) {
     
    7691156        }
    7701157       
     1158        fibril_rwlock_read_unlock(&device_tree.rwlock);
     1159       
    7711160        if (driver == NULL) {
    7721161                log_msg(LVL_ERROR, "IPC forwarding refused - " \
    7731162                    "the device %" PRIun " is not in usable state.", handle);
    7741163                async_answer_0(iid, ENOENT);
    775                 return;
     1164                goto cleanup;
    7761165        }
    7771166       
     
    7861175                    "Could not forward to driver `%s'.", driver->name);
    7871176                async_answer_0(iid, EINVAL);
    788                 return;
     1177                goto cleanup;
    7891178        }
    7901179
     
    8021191        async_forward_fast(iid, exch, method, fwd_h, 0, IPC_FF_NONE);
    8031192        async_exchange_end(exch);
     1193
     1194cleanup:
     1195        if (dev != NULL)
     1196                dev_del_ref(dev);
     1197        if (fun != NULL)
     1198                fun_del_ref(fun);
    8041199}
    8051200
     
    8111206        fun_node_t *fun;
    8121207        dev_node_t *dev;
     1208        devman_handle_t handle;
     1209        driver_t *driver;
    8131210
    8141211        fun = find_loc_tree_function(&device_tree, service_id);
    8151212       
    816         if (fun == NULL || fun->dev->drv == NULL) {
     1213        fibril_rwlock_read_lock(&device_tree.rwlock);
     1214       
     1215        if (fun == NULL || fun->dev == NULL || fun->dev->drv == NULL) {
    8171216                log_msg(LVL_WARN, "devman_connection_loc(): function "
    8181217                    "not found.\n");
     1218                fibril_rwlock_read_unlock(&device_tree.rwlock);
    8191219                async_answer_0(iid, ENOENT);
    8201220                return;
     
    8221222       
    8231223        dev = fun->dev;
    824        
    825         async_exch_t *exch = async_exchange_begin(dev->drv->sess);
    826         async_forward_fast(iid, exch, DRIVER_CLIENT, fun->handle, 0,
     1224        driver = dev->drv;
     1225        handle = fun->handle;
     1226       
     1227        fibril_rwlock_read_unlock(&device_tree.rwlock);
     1228       
     1229        async_exch_t *exch = async_exchange_begin(driver->sess);
     1230        async_forward_fast(iid, exch, DRIVER_CLIENT, handle, 0,
    8271231            IPC_FF_NONE);
    8281232        async_exchange_end(exch);
     
    8301234        log_msg(LVL_DEBUG,
    8311235            "Forwarding loc service request for `%s' function to driver `%s'.",
    832             fun->pathname, dev->drv->name);
     1236            fun->pathname, driver->name);
     1237
     1238        fun_del_ref(fun);
    8331239}
    8341240
  • uspace/srv/fs/ext2fs/ext2fs_ops.c

    rbb74dabe rc05642d  
    112112static bool ext2fs_is_directory(fs_node_t *);
    113113static bool ext2fs_is_file(fs_node_t *node);
    114 static service_id_t ext2fs_device_get(fs_node_t *node);
     114static service_id_t ext2fs_service_get(fs_node_t *node);
    115115
    116116/*
     
    557557}
    558558
    559 service_id_t ext2fs_device_get(fs_node_t *fn)
     559service_id_t ext2fs_service_get(fs_node_t *fn)
    560560{
    561561        EXT2FS_DBG("");
     
    581581        .is_directory = ext2fs_is_directory,
    582582        .is_file = ext2fs_is_file,
    583         .device_get = ext2fs_device_get
     583        .service_get = ext2fs_service_get
    584584};
    585585
  • uspace/srv/fs/fat/Makefile

    rbb74dabe rc05642d  
    3939        fat_idx.c \
    4040        fat_dentry.c \
     41        fat_directory.c \
    4142        fat_fat.c
    4243
  • uspace/srv/fs/fat/fat.c

    rbb74dabe rc05642d  
    22 * Copyright (c) 2006 Martin Decky
    33 * Copyright (c) 2008 Jakub Jermar
     4 * Copyright (c) 2011 Oleg Romanenko
    45 * All rights reserved.
    56 *
  • uspace/srv/fs/fat/fat.h

    rbb74dabe rc05642d  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
     3 * Copyright (c) 2011 Oleg Romanenko
    34 * All rights reserved.
    45 *
     
    4647#endif
    4748
    48 #define min(a, b)               ((a) < (b) ? (a) : (b))
     49#define min(a, b)       ((a) < (b) ? (a) : (b))
    4950
    5051/*
     
    5556#define RSCNT(bs)       uint16_t_le2host((bs)->rscnt)
    5657#define FATCNT(bs)      (bs)->fatcnt
    57 #define SF(bs)          uint16_t_le2host((bs)->sec_per_fat)
     58
     59#define SF(bs)          (uint16_t_le2host((bs)->sec_per_fat) ? \
     60    uint16_t_le2host((bs)->sec_per_fat) : \
     61    uint32_t_le2host(bs->fat32.sectors_per_fat))
     62
    5863#define RDE(bs)         uint16_t_le2host((bs)->root_ent_max)
    59 #define TS(bs)          (uint16_t_le2host((bs)->totsec16) != 0 ? \
    60                         uint16_t_le2host((bs)->totsec16) : \
    61                         uint32_t_le2host(bs->totsec32))
    62 
    63 #define BS_BLOCK                0
    64 #define BS_SIZE                 512
     64
     65#define TS(bs)          (uint16_t_le2host((bs)->totsec16) ? \
     66    uint16_t_le2host((bs)->totsec16) : \
     67    uint32_t_le2host(bs->totsec32))
     68
     69#define BS_BLOCK        0
     70#define BS_SIZE         512
    6571
    6672typedef struct fat_bs {
  • uspace/srv/fs/fat/fat_dentry.c

    rbb74dabe rc05642d  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
     3 * Copyright (c) 2011 Oleg Romanenko
    34 * All rights reserved.
    45 *
     
    3940#include <ctype.h>
    4041#include <str.h>
    41 
    42 static bool is_d_char(const char ch)
    43 {
    44         if (isalnum(ch) || ch == '_')
    45                 return true;
    46         else
    47                 return false;
    48 }
     42#include <errno.h>
     43#include <byteorder.h>
     44#include <assert.h>
    4945
    5046/** Compare path component with the name read from the dentry.
     
    8076}
    8177
    82 bool fat_dentry_name_verify(const char *name)
     78void fat_dentry_name_get(const fat_dentry_t *d, char *buf)
     79{
     80        unsigned int i;
     81       
     82        for (i = 0; i < FAT_NAME_LEN; i++) {
     83                if (d->name[i] == FAT_PAD)
     84                        break;
     85               
     86                if (d->name[i] == FAT_DENTRY_E5_ESC)
     87                        *buf++ = 0xe5;
     88                else {
     89                        if (d->lcase & FAT_LCASE_LOWER_NAME)
     90                                *buf++ = tolower(d->name[i]);
     91                        else
     92                                *buf++ = d->name[i];
     93                }
     94        }
     95       
     96        if (d->ext[0] != FAT_PAD)
     97                *buf++ = '.';
     98       
     99        for (i = 0; i < FAT_EXT_LEN; i++) {
     100                if (d->ext[i] == FAT_PAD) {
     101                        *buf = '\0';
     102                        return;
     103                }
     104               
     105                if (d->ext[i] == FAT_DENTRY_E5_ESC)
     106                        *buf++ = 0xe5;
     107                else {
     108                        if (d->lcase & FAT_LCASE_LOWER_EXT)
     109                                *buf++ = tolower(d->ext[i]);
     110                        else
     111                                *buf++ = d->ext[i];
     112                }
     113        }
     114       
     115        *buf = '\0';
     116}
     117
     118void fat_dentry_name_set(fat_dentry_t *d, const char *name)
     119{
     120        unsigned int i;
     121        const char fake_ext[] = "   ";
     122        bool lower_name = true;
     123        bool lower_ext = true;
     124       
     125        for (i = 0; i < FAT_NAME_LEN; i++) {
     126                switch ((uint8_t) *name) {
     127                case 0xe5:
     128                        d->name[i] = FAT_DENTRY_E5_ESC;
     129                        name++;
     130                        break;
     131                case '\0':
     132                case '.':
     133                        d->name[i] = FAT_PAD;
     134                        break;
     135                default:
     136                        if (isalpha(*name)) {
     137                                if (!islower(*name))
     138                                        lower_name = false;
     139                        }
     140                       
     141                        d->name[i] = toupper(*name++);
     142                        break;
     143                }
     144        }
     145       
     146        if (*name++ != '.')
     147                name = fake_ext;
     148       
     149        for (i = 0; i < FAT_EXT_LEN; i++) {
     150                switch ((uint8_t) *name) {
     151                case 0xe5:
     152                        d->ext[i] = FAT_DENTRY_E5_ESC;
     153                        name++;
     154                        break;
     155                case '\0':
     156                        d->ext[i] = FAT_PAD;
     157                        break;
     158                default:
     159                        if (isalpha(*name)) {
     160                                if (!islower(*name))
     161                                        lower_ext = false;
     162                        }
     163                       
     164                        d->ext[i] = toupper(*name++);
     165                        break;
     166                }
     167        }
     168       
     169        if (lower_name)
     170                d->lcase |= FAT_LCASE_LOWER_NAME;
     171        else
     172                d->lcase &= ~FAT_LCASE_LOWER_NAME;
     173       
     174        if (lower_ext)
     175                d->lcase |= FAT_LCASE_LOWER_EXT;
     176        else
     177                d->lcase &= ~FAT_LCASE_LOWER_EXT;
     178}
     179
     180fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *d)
     181{
     182        if (d->attr == FAT_ATTR_LFN) {
     183                /* long name entry */
     184                if (FAT_LFN_ORDER(d) & FAT_LFN_ERASED)
     185                        return FAT_DENTRY_FREE;
     186                else
     187                        return FAT_DENTRY_LFN;
     188        }
     189        if (d->attr & FAT_ATTR_VOLLABEL) {
     190                /* volume label entry */
     191                return FAT_DENTRY_SKIP;
     192        }
     193        if (d->name[0] == FAT_DENTRY_ERASED) {
     194                /* not-currently-used entry */
     195                return FAT_DENTRY_FREE;
     196        }
     197        if (d->name[0] == FAT_DENTRY_UNUSED) {
     198                /* never used entry */
     199                return FAT_DENTRY_LAST;
     200        }
     201        if (d->name[0] == FAT_DENTRY_DOT) {
     202                /*
     203                 * Most likely '.' or '..'.
     204                 * It cannot occur in a regular file name.
     205                 */
     206                return FAT_DENTRY_SKIP;
     207        }
     208        return FAT_DENTRY_VALID;
     209}
     210
     211/** Compute checksum of Node name.
     212 *
     213 * Returns an unsigned byte checksum computed on an unsigned byte
     214 * array. The array must be 11 bytes long and is assumed to contain
     215 * a name stored in the format of a MS-DOS directory entry.
     216 *
     217 * @param name          Node name read from the dentry.
     218 *
     219 * @return              An 8-bit unsigned checksum of the name.
     220 */
     221uint8_t fat_dentry_chksum(uint8_t *name)
     222{
     223        uint8_t i, sum = 0;
     224
     225        for (i = 0; i < (FAT_NAME_LEN + FAT_EXT_LEN); i++)
     226                sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) + name[i];
     227
     228        return sum;
     229}
     230
     231/** Get number of bytes in a string with size limit.
     232 *
     233 * @param str  NULL-terminated (or not) string.
     234 * @param size Maximum number of bytes to consider.
     235 *
     236 * @return Number of bytes in string (without 0 and ff).
     237 *
     238 */
     239size_t fat_lfn_str_nlength(const uint16_t *str, size_t size)
     240{
     241        size_t offset = 0;
     242
     243        while (offset < size) {
     244                if (str[offset] == 0 || str[offset] == FAT_LFN_PAD)
     245                        break;
     246                offset++;
     247        }
     248        return offset;
     249}
     250
     251/** Get number of bytes in a FAT long entry occuped by characters.
     252 *
     253 * @param d FAT long entry.
     254 *
     255 * @return Number of bytes.
     256 *
     257 */
     258size_t fat_lfn_size(const fat_dentry_t *d)
     259{
     260        size_t size = 0;
     261       
     262        size += fat_lfn_str_nlength(FAT_LFN_PART1(d), FAT_LFN_PART1_SIZE);
     263        size += fat_lfn_str_nlength(FAT_LFN_PART2(d), FAT_LFN_PART2_SIZE);
     264        size += fat_lfn_str_nlength(FAT_LFN_PART3(d), FAT_LFN_PART3_SIZE);     
     265       
     266        return size;
     267}
     268
     269size_t fat_lfn_get_entry(const fat_dentry_t *d, uint16_t *dst, size_t *offset)
     270{
     271        int i;
     272        for (i = FAT_LFN_PART3_SIZE - 1; i >= 0 && *offset > 0; i--) {
     273                if (d->lfn.part3[i] == 0 || d->lfn.part3[i] == FAT_LFN_PAD)
     274                        continue;
     275                (*offset)--;
     276                dst[(*offset)] = uint16_t_le2host(d->lfn.part3[i]);
     277        }
     278        for (i = FAT_LFN_PART2_SIZE - 1; i >= 0 && *offset > 0; i--) {
     279                if (d->lfn.part2[i] == 0 || d->lfn.part2[i] == FAT_LFN_PAD)
     280                        continue;
     281                (*offset)--;
     282                dst[(*offset)] = uint16_t_le2host(d->lfn.part2[i]);
     283        }
     284        for (i = FAT_LFN_PART1_SIZE - 1; i >= 0 && *offset > 0; i--) {
     285                if (d->lfn.part1[i] == 0 || d->lfn.part1[i] == FAT_LFN_PAD)
     286                        continue;
     287                (*offset)--;
     288                dst[(*offset)] = uint16_t_le2host(d->lfn.part1[i]);
     289        }
     290        return *offset;
     291}
     292
     293size_t fat_lfn_set_entry(const uint16_t *src, size_t *offset, size_t size,
     294    fat_dentry_t *d)
     295{
     296        size_t idx;
     297        for (idx = 0; idx < FAT_LFN_PART1_SIZE; idx++) {
     298                if (*offset < size) {
     299                        d->lfn.part1[idx] = host2uint16_t_le(src[*offset]);
     300                        (*offset)++;
     301                } else
     302                        d->lfn.part1[idx] = FAT_LFN_PAD;
     303        }
     304        for (idx = 0; idx < FAT_LFN_PART2_SIZE; idx++) {
     305                if (*offset < size) {
     306                        d->lfn.part2[idx] = host2uint16_t_le(src[*offset]);
     307                        (*offset)++;
     308                } else
     309                        d->lfn.part2[idx] = FAT_LFN_PAD;
     310        }
     311        for (idx = 0; idx < FAT_LFN_PART3_SIZE; idx++) {
     312                if (*offset < size) {
     313                        d->lfn.part3[idx] = host2uint16_t_le(src[*offset]);
     314                        (*offset)++;
     315                } else
     316                        d->lfn.part3[idx] = FAT_LFN_PAD;
     317        }
     318
     319        if (src[*offset] == 0)
     320                offset++;
     321        FAT_LFN_ATTR(d) = FAT_ATTR_LFN;
     322        d->lfn.type = 0;
     323        d->lfn.firstc_lo = 0;
     324       
     325        return *offset;
     326}
     327
     328void str_to_ascii(char *dst, const char *src, size_t count, uint8_t pad)
     329{
     330        wchar_t ch;
     331        size_t off = 0;
     332        size_t i = 0;
     333       
     334        while (i < count) {
     335                if ((ch = str_decode(src, &off, STR_NO_LIMIT)) != 0) {
     336                        if (ascii_check(ch) & IS_D_CHAR(ch))
     337                                *dst = toupper(ch);
     338                        else
     339                                *dst = pad;
     340                } else
     341                        break;
     342
     343                dst++;
     344                i++;
     345        }
     346        *dst = '\0';
     347}
     348
     349bool fat_valid_name(const char *name)
     350{
     351        wchar_t ch;
     352        size_t offset=0;
     353        bool result = true;
     354       
     355        while ((ch = str_decode(name, &offset, STR_NO_LIMIT)) != 0) {
     356                if (str_chr(FAT_STOP_CHARS, ch) != NULL) {
     357                        result = false;
     358                        break;
     359                }
     360        }
     361        return result;
     362}
     363
     364bool fat_valid_short_name(const char *name)
    83365{
    84366        unsigned int i;
    85367        unsigned int dot = 0;
    86368        bool dot_found = false;
    87        
    88369
    89370        for (i = 0; name[i]; i++) {
     
    96377                        }
    97378                } else {
    98                         if (!is_d_char(name[i]))
     379                        if (!IS_D_CHAR(name[i]))
    99380                                return false;
    100381                }
     
    114395}
    115396
    116 void fat_dentry_name_get(const fat_dentry_t *d, char *buf)
    117 {
    118         unsigned int i;
    119        
    120         for (i = 0; i < FAT_NAME_LEN; i++) {
    121                 if (d->name[i] == FAT_PAD)
    122                         break;
    123                
    124                 if (d->name[i] == FAT_DENTRY_E5_ESC)
    125                         *buf++ = 0xe5;
    126                 else {
    127                         if (d->lcase & FAT_LCASE_LOWER_NAME)
    128                                 *buf++ = tolower(d->name[i]);
    129                         else
    130                                 *buf++ = d->name[i];
    131                 }
    132         }
    133        
    134         if (d->ext[0] != FAT_PAD)
    135                 *buf++ = '.';
    136        
    137         for (i = 0; i < FAT_EXT_LEN; i++) {
    138                 if (d->ext[i] == FAT_PAD) {
    139                         *buf = '\0';
    140                         return;
    141                 }
    142                
    143                 if (d->ext[i] == FAT_DENTRY_E5_ESC)
    144                         *buf++ = 0xe5;
    145                 else {
    146                         if (d->lcase & FAT_LCASE_LOWER_EXT)
    147                                 *buf++ = tolower(d->ext[i]);
    148                         else
    149                                 *buf++ = d->ext[i];
    150                 }
    151         }
    152        
    153         *buf = '\0';
    154 }
    155 
    156 void fat_dentry_name_set(fat_dentry_t *d, const char *name)
    157 {
    158         unsigned int i;
    159         const char fake_ext[] = "   ";
    160         bool lower_name = true;
    161         bool lower_ext = true;
    162        
    163         for (i = 0; i < FAT_NAME_LEN; i++) {
    164                 switch ((uint8_t) *name) {
    165                 case 0xe5:
    166                         d->name[i] = FAT_DENTRY_E5_ESC;
    167                         name++;
    168                         break;
    169                 case '\0':
    170                 case '.':
    171                         d->name[i] = FAT_PAD;
    172                         break;
    173                 default:
    174                         if (isalpha(*name)) {
    175                                 if (!islower(*name))
    176                                         lower_name = false;
    177                         }
    178                        
    179                         d->name[i] = toupper(*name++);
    180                         break;
    181                 }
    182         }
    183        
    184         if (*name++ != '.')
    185                 name = fake_ext;
    186        
    187         for (i = 0; i < FAT_EXT_LEN; i++) {
    188                 switch ((uint8_t) *name) {
    189                 case 0xe5:
    190                         d->ext[i] = FAT_DENTRY_E5_ESC;
    191                         name++;
    192                         break;
    193                 case '\0':
    194                         d->ext[i] = FAT_PAD;
    195                         break;
    196                 default:
    197                         if (isalpha(*name)) {
    198                                 if (!islower(*name))
    199                                         lower_ext = false;
    200                         }
    201                        
    202                         d->ext[i] = toupper(*name++);
    203                         break;
    204                 }
    205         }
    206        
    207         if (lower_name)
    208                 d->lcase |= FAT_LCASE_LOWER_NAME;
    209         else
    210                 d->lcase &= ~FAT_LCASE_LOWER_NAME;
    211        
    212         if (lower_ext)
    213                 d->lcase |= FAT_LCASE_LOWER_EXT;
    214         else
    215                 d->lcase &= ~FAT_LCASE_LOWER_EXT;
    216 }
    217 
    218 fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *d)
    219 {
    220         if (d->attr & FAT_ATTR_VOLLABEL) {
    221                 /* volume label entry */
    222                 return FAT_DENTRY_SKIP;
    223         }
    224         if (d->name[0] == FAT_DENTRY_ERASED) {
    225                 /* not-currently-used entry */
    226                 return FAT_DENTRY_FREE;
    227         }
    228         if (d->name[0] == FAT_DENTRY_UNUSED) {
    229                 /* never used entry */
    230                 return FAT_DENTRY_LAST;
    231         }
    232         if (d->name[0] == FAT_DENTRY_DOT) {
    233                 /*
    234                  * Most likely '.' or '..'.
    235                  * It cannot occur in a regular file name.
    236                  */
    237                 return FAT_DENTRY_SKIP;
    238         }
    239         return FAT_DENTRY_VALID;
     397size_t utf16_length(const uint16_t *wstr)
     398{
     399        size_t len = 0;
     400       
     401        while (*wstr++ != 0)
     402                len++;
     403       
     404        return len;
    240405}
    241406
  • uspace/srv/fs/fat/fat_dentry.h

    rbb74dabe rc05642d  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
     3 * Copyright (c) 2011 Oleg Romanenko
    34 * All rights reserved.
    45 *
     
    3738#include <bool.h>
    3839
     40#define IS_D_CHAR(ch) (isalnum(ch) || ch == '_')
     41#define FAT_STOP_CHARS "*?/\\\n\t|'"
     42
    3943#define FAT_NAME_LEN            8
    4044#define FAT_EXT_LEN             3
     
    4448#define FAT_EXT_PAD             "   "
    4549
    46 #define FAT_ATTR_RDONLY         (1 << 0)
    47 #define FAT_ATTR_VOLLABEL       (1 << 3)
    48 #define FAT_ATTR_SUBDIR         (1 << 4)
    49 
     50#define FAT_ATTR_RDONLY   0x01
     51#define FAT_ATTR_HIDDEN   0x02
     52#define FAT_ATTR_SYSTEM   0x04
     53#define FAT_ATTR_VOLLABEL 0x08
     54#define FAT_ATTR_SUBDIR   0x10
     55#define FAT_ATTR_ARCHIVE  0x20
     56#define FAT_ATTR_LFN \
     57    (FAT_ATTR_RDONLY | FAT_ATTR_HIDDEN | FAT_ATTR_SYSTEM | FAT_ATTR_VOLLABEL)
     58   
    5059#define FAT_LCASE_LOWER_NAME    0x08
    5160#define FAT_LCASE_LOWER_EXT     0x10
    5261
    53 #define FAT_PAD                 ' '
     62#define FAT_PAD                 ' '
     63#define FAT_LFN_PAD     0xffff
     64#define FAT_SFN_CHAR '_'
    5465
    5566#define FAT_DENTRY_UNUSED       0x00
     
    5768#define FAT_DENTRY_DOT          0x2e
    5869#define FAT_DENTRY_ERASED       0xe5
     70#define FAT_LFN_LAST            0x40
     71#define FAT_LFN_ERASED          0x80
     72
     73#define FAT_LFN_ORDER(d) ((d)->lfn.order)
     74#define FAT_IS_LFN(d) \
     75    ((FAT_LFN_ORDER((d)) & FAT_LFN_LAST) == FAT_LFN_LAST)
     76#define FAT_LFN_COUNT(d) \
     77    (FAT_LFN_ORDER((d)) ^ FAT_LFN_LAST)
     78#define FAT_LFN_PART1(d) ((d)->lfn.part1)
     79#define FAT_LFN_PART2(d) ((d)->lfn.part2)
     80#define FAT_LFN_PART3(d) ((d)->lfn.part3)
     81#define FAT_LFN_ATTR(d) ((d)->lfn.attr)
     82#define FAT_LFN_CHKSUM(d) ((d)->lfn.check_sum)
     83
     84#define FAT_LFN_NAME_SIZE   260
     85#define FAT_LFN_MAX_COUNT   20
     86#define FAT_LFN_PART1_SIZE  5
     87#define FAT_LFN_PART2_SIZE  6
     88#define FAT_LFN_PART3_SIZE  2
     89#define FAT_LFN_ENTRY_SIZE \
     90    (FAT_LFN_PART1_SIZE + FAT_LFN_PART2_SIZE + FAT_LFN_PART3_SIZE)
    5991
    6092typedef enum {
     
    6294        FAT_DENTRY_LAST,
    6395        FAT_DENTRY_FREE,
    64         FAT_DENTRY_VALID
     96        FAT_DENTRY_VALID,
     97        FAT_DENTRY_LFN
    6598} fat_dentry_clsf_t;
    6699
    67 typedef struct {
    68         uint8_t         name[8];
    69         uint8_t         ext[3];
    70         uint8_t         attr;
    71         uint8_t         lcase;
    72         uint8_t         ctime_fine;
    73         uint16_t        ctime;
    74         uint16_t        cdate;
    75         uint16_t        adate;
    76         union {
    77                 uint16_t        eaidx;          /* FAT12/FAT16 */
    78                 uint16_t        firstc_hi;      /* FAT32 */
     100typedef union {
     101        struct {
     102                uint8_t         name[8];
     103                uint8_t         ext[3];
     104                uint8_t         attr;
     105                uint8_t         lcase;
     106                uint8_t         ctime_fine;
     107                uint16_t        ctime;
     108                uint16_t        cdate;
     109                uint16_t        adate;
     110                union {
     111                        uint16_t        eaidx;          /* FAT12/FAT16 */
     112                        uint16_t        firstc_hi;      /* FAT32 */
     113                } __attribute__ ((packed));
     114                uint16_t        mtime;
     115                uint16_t        mdate;
     116                union {
     117                        uint16_t        firstc;         /* FAT12/FAT16 */
     118                        uint16_t        firstc_lo;      /* FAT32 */
     119                } __attribute__ ((packed));
     120                uint32_t        size;
    79121        } __attribute__ ((packed));
    80         uint16_t        mtime;
    81         uint16_t        mdate;
    82         union {
    83                 uint16_t        firstc;         /* FAT12/FAT16 */
    84                 uint16_t        firstc_lo;      /* FAT32 */
    85         } __attribute__ ((packed));
    86         uint32_t        size;
     122        struct {
     123                uint8_t         order;
     124                uint16_t        part1[FAT_LFN_PART1_SIZE];
     125                uint8_t         attr;
     126                uint8_t         type;
     127                uint8_t         check_sum;
     128                uint16_t        part2[FAT_LFN_PART2_SIZE];
     129                uint16_t        firstc_lo; /* MUST be 0 */
     130                uint16_t        part3[FAT_LFN_PART3_SIZE];
     131        } __attribute__ ((packed)) lfn;
    87132} __attribute__ ((packed)) fat_dentry_t;
    88133
     134
    89135extern int fat_dentry_namecmp(char *, const char *);
    90 extern bool fat_dentry_name_verify(const char *);
    91136extern void fat_dentry_name_get(const fat_dentry_t *, char *);
    92137extern void fat_dentry_name_set(fat_dentry_t *, const char *);
    93138extern fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *);
     139extern uint8_t fat_dentry_chksum(uint8_t *);
     140
     141extern size_t fat_lfn_str_nlength(const uint16_t *, size_t);
     142extern size_t fat_lfn_size(const fat_dentry_t *);
     143extern size_t fat_lfn_get_entry(const fat_dentry_t *, uint16_t *, size_t *);
     144extern size_t fat_lfn_set_entry(const uint16_t *, size_t *, size_t,
     145    fat_dentry_t *);
     146
     147extern void str_to_ascii(char *, const char *, size_t, uint8_t);
     148extern size_t utf16_length(const uint16_t *);
     149
     150extern bool fat_valid_name(const char *);
     151extern bool fat_valid_short_name(const char *);
    94152
    95153#endif
  • uspace/srv/fs/fat/fat_fat.c

    rbb74dabe rc05642d  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
     3 * Copyright (c) 2011 Oleg Romanenko
    34 * All rights reserved.
    45 *
     
    2930/** @addtogroup fs
    3031 * @{
    31  */ 
     32 */
    3233
    3334/**
     
    5051#include <mem.h>
    5152
    52 /*
    53  * Convenience macros for computing some frequently used values from the
    54  * primitive boot sector members.
    55  */
    56 #define RDS(bs)         ((sizeof(fat_dentry_t) * RDE((bs))) / BPS((bs))) + \
    57                         (((sizeof(fat_dentry_t) * RDE((bs))) % BPS((bs))) != 0)
    58 #define SSA(bs)         (RSCNT((bs)) + FATCNT((bs)) * SF((bs)) + RDS(bs))
    59 
    60 #define CLBN2PBN(bs, cl, bn) \
    61         (SSA((bs)) + ((cl) - FAT_CLST_FIRST) * SPC((bs)) + (bn) % SPC((bs)))
     53#define IS_ODD(number)  (number & 0x1)
    6254
    6355/**
     
    6557 * during allocation of clusters. The lock does not have to be held durring
    6658 * deallocation of clusters.
    67  */ 
     59 */
    6860static FIBRIL_MUTEX_INITIALIZE(fat_alloc_lock);
    6961
     
    7769 * @param numc          If non-NULL, output argument holding the number of
    7870 *                      clusters seen during the walk.
    79  * @param max_clusters  Maximum number of clusters to visit.   
     71 * @param max_clusters  Maximum number of clusters to visit.
    8072 *
    8173 * @return              EOK on success or a negative error code.
    8274 */
    83 int 
     75int
    8476fat_cluster_walk(fat_bs_t *bs, service_id_t service_id, fat_cluster_t firstc,
    85     fat_cluster_t *lastc, uint16_t *numc, uint16_t max_clusters)
    86 {
    87         block_t *b;
    88         uint16_t clusters = 0;
    89         fat_cluster_t clst = firstc;
     77    fat_cluster_t *lastc, uint32_t *numc, uint32_t max_clusters)
     78{
     79        uint32_t clusters = 0;
     80        fat_cluster_t clst = firstc, clst_last1 = FAT_CLST_LAST1(bs);
     81        fat_cluster_t clst_bad = FAT_CLST_BAD(bs);
    9082        int rc;
    9183
     
    9991        }
    10092
    101         while (clst < FAT_CLST_LAST1 && clusters < max_clusters) {
    102                 aoff64_t fsec;  /* sector offset relative to FAT1 */
    103                 unsigned fidx;  /* FAT1 entry index */
    104 
     93        while (clst < clst_last1 && clusters < max_clusters) {
    10594                assert(clst >= FAT_CLST_FIRST);
    10695                if (lastc)
    10796                        *lastc = clst;  /* remember the last cluster number */
    108                 fsec = (clst * sizeof(fat_cluster_t)) / BPS(bs);
    109                 fidx = clst % (BPS(bs) / sizeof(fat_cluster_t));
     97
    11098                /* read FAT1 */
    111                 rc = block_get(&b, service_id, RSCNT(bs) + fsec,
    112                     BLOCK_FLAGS_NONE);
    113                 if (rc != EOK)
    114                         return rc;
    115                 clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]);
    116                 assert(clst != FAT_CLST_BAD);
    117                 rc = block_put(b);
    118                 if (rc != EOK)
    119                         return rc;
     99                rc = fat_get_cluster(bs, service_id, FAT1, clst, &clst);
     100                if (rc != EOK)
     101                        return rc;
     102
     103                assert(clst != clst_bad);
    120104                clusters++;
    121105        }
    122106
    123         if (lastc && clst < FAT_CLST_LAST1)
     107        if (lastc && clst < clst_last1)
    124108                *lastc = clst;
    125109        if (numc)
     
    151135                return ELIMIT;
    152136
    153         if (nodep->firstc == FAT_CLST_ROOT)
     137        if (!FAT_IS_FAT32(bs) && nodep->firstc == FAT_CLST_ROOT)
    154138                goto fall_through;
    155139
     
    178162        if (rc != EOK)
    179163                return rc;
    180        
     164
    181165        /*
    182166         * Update the "current" cluster cache.
     
    198182 * @param clp           If not NULL, address where the cluster containing bn
    199183 *                      will be stored.
    200  *                      stored 
     184 *                      stored
    201185 * @param bn            Block number.
    202186 * @param flags         Flags passed to libblock.
     
    208192    fat_cluster_t fcl, fat_cluster_t *clp, aoff64_t bn, int flags)
    209193{
    210         uint16_t clusters;
    211         unsigned max_clusters;
     194        uint32_t clusters;
     195        uint32_t max_clusters;
    212196        fat_cluster_t c;
    213197        int rc;
     
    219203                return ELIMIT;
    220204
    221         if (fcl == FAT_CLST_ROOT) {
     205        if (!FAT_IS_FAT32(bs) && fcl == FAT_CLST_ROOT) {
    222206                /* root directory special case */
    223207                assert(bn < RDS(bs));
     
    253237 * @return              EOK on success or a negative error code.
    254238 */
    255 int fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, aoff64_t pos)
     239int
     240fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, aoff64_t pos)
    256241{
    257242        block_t *b;
     
    275260                        return rc;
    276261        }
    277        
     262
    278263        if (o >= pos)
    279264                return EOK;
    280        
     265
    281266        /* zero out the initial part of the new cluster chain */
    282267        for (o = boundary; o < pos; o += BPS(bs)) {
     
    304289 * @return              EOK or a negative error code.
    305290 */
     291static int
     292fat_get_cluster_fat12(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
     293    fat_cluster_t clst, fat_cluster_t *value)
     294{
     295        block_t *b, *b1;
     296        uint16_t byte1, byte2;
     297        aoff64_t offset;
     298        int rc;
     299
     300        offset = (clst + clst / 2);
     301        if (offset / BPS(bs) >= SF(bs))
     302                return ERANGE;
     303
     304        rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
     305            offset / BPS(bs), BLOCK_FLAGS_NONE);
     306        if (rc != EOK)
     307                return rc;
     308
     309        byte1 = ((uint8_t *) b->data)[offset % BPS(bs)];
     310        /* This cluster access spans a sector boundary. Check only for FAT12 */
     311        if ((offset % BPS(bs)) + 1 == BPS(bs)) {
     312                /* Is this the last sector of FAT? */
     313                if (offset / BPS(bs) < SF(bs)) {
     314                        /* No, read the next sector */
     315                        rc = block_get(&b1, service_id, 1 + RSCNT(bs) +
     316                            SF(bs) * fatno + offset / BPS(bs),
     317                            BLOCK_FLAGS_NONE);
     318                        if (rc != EOK) {
     319                                block_put(b);
     320                                return rc;
     321                        }
     322                        /*
     323                        * Combining value with last byte of current sector and
     324                        * first byte of next sector
     325                        */
     326                        byte2 = ((uint8_t*) b1->data)[0];
     327
     328                        rc = block_put(b1);
     329                        if (rc != EOK) {
     330                                block_put(b);
     331                                return rc;
     332                        }
     333                } else {
     334                        /* Yes. This is the last sector of FAT */
     335                        block_put(b);
     336                        return ERANGE;
     337                }
     338        } else
     339                byte2 = ((uint8_t *) b->data)[(offset % BPS(bs)) + 1];
     340
     341        *value = uint16_t_le2host(byte1 | (byte2 << 8));
     342        if (IS_ODD(clst))
     343                *value = (*value) >> 4;
     344        else
     345                *value = (*value) & FAT12_MASK;
     346       
     347        rc = block_put(b);
     348
     349        return rc;
     350}
     351
     352/** Get cluster from the first FAT.
     353 *
     354 * @param bs            Buffer holding the boot sector for the file system.
     355 * @param service_id    Service ID for the file system.
     356 * @param clst          Cluster which to get.
     357 * @param value         Output argument holding the value of the cluster.
     358 *
     359 * @return              EOK or a negative error code.
     360 */
     361static int
     362fat_get_cluster_fat16(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
     363    fat_cluster_t clst, fat_cluster_t *value)
     364{
     365        block_t *b;
     366        aoff64_t offset;
     367        int rc;
     368
     369        offset = (clst * FAT16_CLST_SIZE);
     370
     371        rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
     372            offset / BPS(bs), BLOCK_FLAGS_NONE);
     373        if (rc != EOK)
     374                return rc;
     375
     376        *value = uint16_t_le2host(*(uint16_t *)(b->data + offset % BPS(bs)));
     377
     378        rc = block_put(b);
     379
     380        return rc;
     381}
     382
     383/** Get cluster from the first FAT.
     384 *
     385 * @param bs            Buffer holding the boot sector for the file system.
     386 * @param service_id    Service ID for the file system.
     387 * @param clst          Cluster which to get.
     388 * @param value         Output argument holding the value of the cluster.
     389 *
     390 * @return              EOK or a negative error code.
     391 */
     392static int
     393fat_get_cluster_fat32(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
     394    fat_cluster_t clst, fat_cluster_t *value)
     395{
     396        block_t *b;
     397        aoff64_t offset;
     398        int rc;
     399
     400        offset = (clst * FAT32_CLST_SIZE);
     401
     402        rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
     403            offset / BPS(bs), BLOCK_FLAGS_NONE);
     404        if (rc != EOK)
     405                return rc;
     406
     407        *value = uint32_t_le2host(*(uint32_t *)(b->data + offset % BPS(bs))) &
     408            FAT32_MASK;
     409
     410        rc = block_put(b);
     411
     412        return rc;
     413}
     414
     415
     416/** Get cluster from the first FAT.
     417 *
     418 * @param bs            Buffer holding the boot sector for the file system.
     419 * @param service_id    Service ID for the file system.
     420 * @param clst          Cluster which to get.
     421 * @param value         Output argument holding the value of the cluster.
     422 *
     423 * @return              EOK or a negative error code.
     424 */
    306425int
    307426fat_get_cluster(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
    308427    fat_cluster_t clst, fat_cluster_t *value)
    309428{
    310         block_t *b;
    311         fat_cluster_t *cp;
    312         int rc;
    313 
     429        int rc;
     430
     431        assert(fatno < FATCNT(bs));
     432
     433        if (FAT_IS_FAT12(bs))
     434                rc = fat_get_cluster_fat12(bs, service_id, fatno, clst, value);
     435        else if (FAT_IS_FAT16(bs))
     436                rc = fat_get_cluster_fat16(bs, service_id, fatno, clst, value);
     437        else
     438                rc = fat_get_cluster_fat32(bs, service_id, fatno, clst, value);
     439
     440        return rc;
     441}
     442
     443/** Set cluster in one instance of FAT.
     444 *
     445 * @param bs            Buffer holding the boot sector for the file system.
     446 * @param service_id    Service ID for the file system.
     447 * @param fatno         Number of the FAT instance where to make the change.
     448 * @param clst          Cluster which is to be set.
     449 * @param value         Value to set the cluster with.
     450 *
     451 * @return              EOK on success or a negative error code.
     452 */
     453static int
     454fat_set_cluster_fat12(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
     455    fat_cluster_t clst, fat_cluster_t value)
     456{
     457        block_t *b, *b1 = NULL;
     458        aoff64_t offset;
     459        uint16_t byte1, byte2;
     460        int rc;
     461
     462        offset = (clst + clst / 2);
     463        if (offset / BPS(bs) >= SF(bs))
     464                return ERANGE;
     465       
    314466        rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
    315             (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE);
     467            offset / BPS(bs), BLOCK_FLAGS_NONE);
    316468        if (rc != EOK)
    317469                return rc;
    318         cp = (fat_cluster_t *)b->data +
    319             clst % (BPS(bs) / sizeof(fat_cluster_t));
    320         *value = uint16_t_le2host(*cp);
     470
     471        byte1 = ((uint8_t*) b->data)[offset % BPS(bs)];
     472        bool border = false;
     473        /* This cluster access spans a sector boundary. */
     474        if ((offset % BPS(bs)) + 1 == BPS(bs)) {
     475                /* Is it the last sector of FAT? */
     476                if (offset / BPS(bs) < SF(bs)) {
     477                        /* No, read the next sector */
     478                        rc = block_get(&b1, service_id, 1 + RSCNT(bs) +
     479                            SF(bs) * fatno + offset / BPS(bs),
     480                            BLOCK_FLAGS_NONE);
     481                        if (rc != EOK) {
     482                                block_put(b);
     483                                return rc;
     484                        }
     485                        /*
     486                         * Combining value with last byte of current sector and
     487                         * first byte of next sector
     488                         */
     489                        byte2 = ((uint8_t *) b1->data)[0];
     490                        border = true;
     491                } else {
     492                        /* Yes. This is the last sector of FAT */
     493                        block_put(b);
     494                        return ERANGE;
     495                }
     496        } else
     497                byte2 = ((uint8_t*) b->data)[(offset % BPS(bs)) + 1];
     498
     499        if (IS_ODD(clst)) {
     500                byte1 &= 0x0f;
     501                byte2 = 0;
     502                value = (value << 4);
     503        } else {
     504                byte1 = 0;
     505                byte2 &= 0xf0;
     506                value &= FAT12_MASK;
     507        }
     508
     509        byte1 = byte1 | (value & 0xff);
     510        byte2 = byte2 | (value >> 8);
     511
     512        ((uint8_t *) b->data)[(offset % BPS(bs))] = byte1;
     513        if (border) {
     514                ((uint8_t *) b1->data)[0] = byte2;
     515
     516                b1->dirty = true;
     517                rc = block_put(b1);
     518                if (rc != EOK) {
     519                        block_put(b);
     520                        return rc;
     521                }
     522        } else
     523                ((uint8_t *) b->data)[(offset % BPS(bs)) + 1] = byte2;
     524
     525        b->dirty = true;        /* need to sync block */
    321526        rc = block_put(b);
    322        
     527
     528        return rc;
     529}
     530
     531/** Set cluster in one instance of FAT.
     532 *
     533 * @param bs            Buffer holding the boot sector for the file system.
     534 * @param service_id    Service ID for the file system.
     535 * @param fatno         Number of the FAT instance where to make the change.
     536 * @param clst          Cluster which is to be set.
     537 * @param value         Value to set the cluster with.
     538 *
     539 * @return              EOK on success or a negative error code.
     540 */
     541static int
     542fat_set_cluster_fat16(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
     543    fat_cluster_t clst, fat_cluster_t value)
     544{
     545        block_t *b;
     546        aoff64_t offset;
     547        int rc;
     548
     549        offset = (clst * FAT16_CLST_SIZE);
     550
     551        rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
     552            offset / BPS(bs), BLOCK_FLAGS_NONE);
     553        if (rc != EOK)
     554                return rc;
     555
     556        *(uint16_t *)(b->data + offset % BPS(bs)) = host2uint16_t_le(value);
     557
     558        b->dirty = true;        /* need to sync block */
     559        rc = block_put(b);
     560
     561        return rc;
     562}
     563
     564/** Set cluster in one instance of FAT.
     565 *
     566 * @param bs            Buffer holding the boot sector for the file system.
     567 * @param service_id    Service ID for the file system.
     568 * @param fatno         Number of the FAT instance where to make the change.
     569 * @param clst          Cluster which is to be set.
     570 * @param value         Value to set the cluster with.
     571 *
     572 * @return              EOK on success or a negative error code.
     573 */
     574static int
     575fat_set_cluster_fat32(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
     576    fat_cluster_t clst, fat_cluster_t value)
     577{
     578        block_t *b;
     579        aoff64_t offset;
     580        int rc;
     581        fat_cluster_t temp;
     582
     583        offset = (clst * FAT32_CLST_SIZE);
     584
     585        rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
     586            offset / BPS(bs), BLOCK_FLAGS_NONE);
     587        if (rc != EOK)
     588                return rc;
     589
     590        temp = uint32_t_le2host(*(uint32_t *)(b->data + offset % BPS(bs)));
     591        temp &= 0xf0000000;
     592        temp |= (value & FAT32_MASK);
     593        *(uint32_t *)(b->data + offset % BPS(bs)) = host2uint32_t_le(temp);
     594
     595        b->dirty = true;        /* need to sync block */
     596        rc = block_put(b);
     597
    323598        return rc;
    324599}
     
    338613    fat_cluster_t clst, fat_cluster_t value)
    339614{
    340         block_t *b;
    341         fat_cluster_t *cp;
    342615        int rc;
    343616
    344617        assert(fatno < FATCNT(bs));
    345         rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
    346             (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE);
    347         if (rc != EOK)
    348                 return rc;
    349         cp = (fat_cluster_t *)b->data +
    350             clst % (BPS(bs) / sizeof(fat_cluster_t));
    351         *cp = host2uint16_t_le(value);
    352         b->dirty = true;                /* need to sync block */
    353         rc = block_put(b);
     618
     619        if (FAT_IS_FAT12(bs))
     620                rc = fat_set_cluster_fat12(bs, service_id, fatno, clst, value);
     621        else if (FAT_IS_FAT16(bs))
     622                rc = fat_set_cluster_fat16(bs, service_id, fatno, clst, value);
     623        else
     624                rc = fat_set_cluster_fat32(bs, service_id, fatno, clst, value);
     625
    354626        return rc;
    355627}
     
    369641        uint8_t fatno;
    370642        unsigned c;
    371         int rc;
    372 
    373         for (fatno = FAT1 + 1; fatno < bs->fatcnt; fatno++) {
     643        fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs);
     644        int rc;
     645
     646        for (fatno = FAT1 + 1; fatno < FATCNT(bs); fatno++) {
    374647                for (c = 0; c < nclsts; c++) {
    375648                        rc = fat_set_cluster(bs, service_id, fatno, lifo[c],
    376                             c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]);
     649                            c == 0 ? clst_last1 : lifo[c - 1]);
    377650                        if (rc != EOK)
    378651                                return rc;
     
    404677    fat_cluster_t *mcl, fat_cluster_t *lcl)
    405678{
    406         block_t *blk;
    407         fat_cluster_t *lifo;    /* stack for storing free cluster numbers */
    408         unsigned found = 0;     /* top of the free cluster number stack */
    409         unsigned b, c, cl;
    410         int rc;
     679        fat_cluster_t *lifo;    /* stack for storing free cluster numbers */
     680        unsigned found = 0;     /* top of the free cluster number stack */
     681        fat_cluster_t clst, value, clst_last1 = FAT_CLST_LAST1(bs);
     682        int rc = EOK;
    411683
    412684        lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t));
     
    418690         */
    419691        fibril_mutex_lock(&fat_alloc_lock);
    420         for (b = 0, cl = 0; b < SF(bs); b++) {
    421                 rc = block_get(&blk, service_id, RSCNT(bs) + b,
    422                     BLOCK_FLAGS_NONE);
    423                 if (rc != EOK)
    424                         goto error;
    425                 for (c = 0; c < BPS(bs) / sizeof(fat_cluster_t); c++, cl++) {
     692        for (clst = FAT_CLST_FIRST; clst < CC(bs) + 2 && found < nclsts;
     693            clst++) {
     694                rc = fat_get_cluster(bs, service_id, FAT1, clst, &value);
     695                if (rc != EOK)
     696                        break;
     697
     698                if (value == FAT_CLST_RES0) {
    426699                        /*
    427                          * Check if the entire cluster is physically there.
    428                          * This check becomes necessary when the file system is
    429                          * created with fewer total sectors than how many is
    430                          * inferred from the size of the file allocation table
    431                          * or when the last cluster ends beyond the end of the
    432                          * device.
     700                         * The cluster is free. Put it into our stack
     701                         * of found clusters and mark it as non-free.
    433702                         */
    434                         if ((cl >= FAT_CLST_FIRST) &&
    435                             CLBN2PBN(bs, cl, SPC(bs) - 1) >= TS(bs)) {
    436                                 rc = block_put(blk);
    437                                 if (rc != EOK)
    438                                         goto error;
    439                                 goto out;
    440                         }
    441 
    442                         fat_cluster_t *clst = (fat_cluster_t *)blk->data + c;
    443                         if (uint16_t_le2host(*clst) == FAT_CLST_RES0) {
    444                                 /*
    445                                  * The cluster is free. Put it into our stack
    446                                  * of found clusters and mark it as non-free.
    447                                  */
    448                                 lifo[found] = cl;
    449                                 *clst = (found == 0) ?
    450                                     host2uint16_t_le(FAT_CLST_LAST1) :
    451                                     host2uint16_t_le(lifo[found - 1]);
    452                                 blk->dirty = true;      /* need to sync block */
    453                                 if (++found == nclsts) {
    454                                         /* we are almost done */
    455                                         rc = block_put(blk);
    456                                         if (rc != EOK)
    457                                                 goto error;
    458                                         /* update the shadow copies of FAT */
    459                                         rc = fat_alloc_shadow_clusters(bs,
    460                                             service_id, lifo, nclsts);
    461                                         if (rc != EOK)
    462                                                 goto error;
    463                                         *mcl = lifo[found - 1];
    464                                         *lcl = lifo[0];
    465                                         free(lifo);
    466                                         fibril_mutex_unlock(&fat_alloc_lock);
    467                                         return EOK;
    468                                 }
    469                         }
     703                        lifo[found] = clst;
     704                        rc = fat_set_cluster(bs, service_id, FAT1, clst,
     705                            (found == 0) ?  clst_last1 : lifo[found - 1]);
     706                        if (rc != EOK)
     707                                break;
     708
     709                        found++;
    470710                }
    471                 rc = block_put(blk);
    472                 if (rc != EOK) {
    473 error:
     711        }
     712
     713        if (rc == EOK && found == nclsts) {
     714                rc = fat_alloc_shadow_clusters(bs, service_id, lifo, nclsts);
     715                if (rc == EOK) {
     716                        *mcl = lifo[found - 1];
     717                        *lcl = lifo[0];
     718                        free(lifo);
    474719                        fibril_mutex_unlock(&fat_alloc_lock);
    475                         free(lifo);
    476                         return rc;
     720                        return EOK;
    477721                }
    478722        }
    479 out:
     723
     724        /* If something wrong - free the clusters */
     725        while (found--) {
     726                (void) fat_set_cluster(bs, service_id, FAT1, lifo[found],
     727                    FAT_CLST_RES0);
     728        }
     729
     730        free(lifo);
    480731        fibril_mutex_unlock(&fat_alloc_lock);
    481732
    482         /*
    483          * We could not find enough clusters. Now we need to free the clusters
    484          * we have allocated so far.
    485          */
    486         while (found--) {
    487                 rc = fat_set_cluster(bs, service_id, FAT1, lifo[found],
    488                     FAT_CLST_RES0);
    489                 if (rc != EOK) {
    490                         free(lifo);
    491                         return rc;
    492                 }
    493         }
    494        
    495         free(lifo);
    496733        return ENOSPC;
    497734}
     
    509746{
    510747        unsigned fatno;
    511         fat_cluster_t nextc;
     748        fat_cluster_t nextc, clst_bad = FAT_CLST_BAD(bs);
    512749        int rc;
    513750
    514751        /* Mark all clusters in the chain as free in all copies of FAT. */
    515         while (firstc < FAT_CLST_LAST1) {
    516                 assert(firstc >= FAT_CLST_FIRST && firstc < FAT_CLST_BAD);
     752        while (firstc < FAT_CLST_LAST1(bs)) {
     753                assert(firstc >= FAT_CLST_FIRST && firstc < clst_bad);
     754
    517755                rc = fat_get_cluster(bs, service_id, FAT1, firstc, &nextc);
    518756                if (rc != EOK)
    519757                        return rc;
    520                 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
     758
     759                for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {
    521760                        rc = fat_set_cluster(bs, service_id, fatno, firstc,
    522761                            FAT_CLST_RES0);
     
    540779 * @return              EOK on success or a negative error code.
    541780 */
    542 int
    543 fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl,
     781int fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl,
    544782    fat_cluster_t lcl)
    545783{
     
    559797                } else {
    560798                        rc = fat_cluster_walk(bs, service_id, nodep->firstc,
    561                             &lastc, NULL, (uint16_t) -1);
     799                            &lastc, NULL, (uint32_t) -1);
    562800                        if (rc != EOK)
    563801                                return rc;
    564802                }
    565803
    566                 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
    567                         rc = fat_set_cluster(bs, nodep->idx->service_id, fatno,
    568                             lastc, mcl);
     804                for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {
     805                        rc = fat_set_cluster(bs, nodep->idx->service_id,
     806                            fatno, lastc, mcl);
    569807                        if (rc != EOK)
    570808                                return rc;
     
    590828int fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lcl)
    591829{
     830        fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs);
    592831        int rc;
    593832        service_id_t service_id = nodep->idx->service_id;
     
    616855
    617856                /* Terminate the cluster chain in all copies of FAT. */
    618                 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
     857                for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {
    619858                        rc = fat_set_cluster(bs, service_id, fatno, lcl,
    620                             FAT_CLST_LAST1);
     859                            clst_last1);
    621860                        if (rc != EOK)
    622861                                return rc;
     
    673912
    674913        /* Check number of FATs. */
    675         if (bs->fatcnt == 0)
     914        if (FATCNT(bs) == 0)
    676915                return ENOTSUP;
    677916
    678917        /* Check total number of sectors. */
    679 
    680         if (bs->totsec16 == 0 && bs->totsec32 == 0)
     918        if (TS(bs) == 0)
    681919                return ENOTSUP;
    682920
    683921        if (bs->totsec16 != 0 && bs->totsec32 != 0 &&
    684             bs->totsec16 != bs->totsec32) 
     922            bs->totsec16 != bs->totsec32)
    685923                return ENOTSUP;
    686924
     
    690928
    691929        /* Check number of sectors per FAT. */
    692         if (bs->sec_per_fat == 0)
     930        if (SF(bs) == 0)
    693931                return ENOTSUP;
    694932
     
    700938         * sanitized to support file systems with this property.
    701939         */
    702         if ((uint16_t_le2host(bs->root_ent_max) * sizeof(fat_dentry_t)) %
    703             uint16_t_le2host(bs->bps) != 0)
     940        if (!FAT_IS_FAT32(bs) &&
     941            (RDE(bs) * sizeof(fat_dentry_t)) % BPS(bs) != 0)
    704942                return ENOTSUP;
    705943
    706944        /* Check signature of each FAT. */
    707 
    708         for (fat_no = 0; fat_no < bs->fatcnt; fat_no++) {
     945        for (fat_no = 0; fat_no < FATCNT(bs); fat_no++) {
    709946                rc = fat_get_cluster(bs, service_id, fat_no, 0, &e0);
    710947                if (rc != EOK)
     
    715952                        return EIO;
    716953
    717                 /* Check that first byte of FAT contains the media descriptor. */
     954                /*
     955                 * Check that first byte of FAT contains the media descriptor.
     956                 */
    718957                if ((e0 & 0xff) != bs->mdesc)
    719958                        return ENOTSUP;
     
    723962                 * set to one.
    724963                 */
    725                 if ((e0 >> 8) != 0xff || e1 != 0xffff)
     964                if (!FAT_IS_FAT12(bs) &&
     965                    ((e0 >> 8) != (FAT_MASK(bs) >> 8) || e1 != FAT_MASK(bs)))
    726966                        return ENOTSUP;
    727967        }
     
    732972/**
    733973 * @}
    734  */ 
     974 */
  • uspace/srv/fs/fat/fat_fat.h

    rbb74dabe rc05642d  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
     3 * Copyright (c) 2011 Oleg Romanenko
    34 * All rights reserved.
    45 *
     
    2930/** @addtogroup fs
    3031 * @{
    31  */ 
     32 */
    3233
    3334#ifndef FAT_FAT_FAT_H_
     
    4041#define FAT1            0
    4142
    42 #define FAT_CLST_RES0   0x0000
    43 #define FAT_CLST_RES1   0x0001
    44 #define FAT_CLST_FIRST  0x0002
    45 #define FAT_CLST_BAD    0xfff7
    46 #define FAT_CLST_LAST1  0xfff8
    47 #define FAT_CLST_LAST8  0xffff
     43#define FAT_CLST_RES0     0
     44#define FAT_CLST_RES1     1
     45#define FAT_CLST_FIRST    2
     46
     47#define FAT32_CLST_BAD    0x0ffffff7
     48#define FAT32_CLST_LAST1  0x0ffffff8
     49#define FAT32_CLST_LAST8  0x0fffffff
     50
     51#define FAT12_MASK        0x0fff
     52#define FAT16_MASK        0xffff
     53#define FAT32_MASK        0x0fffffff
     54
     55#define FAT12_CLST_MAX    4085
     56#define FAT16_CLST_MAX    65525
     57
     58/* Size in bytes for cluster value of FAT */
     59#define FAT12_CLST_SIZE   2
     60#define FAT16_CLST_SIZE   2
     61#define FAT32_CLST_SIZE   4
    4862
    4963/* internally used to mark root directory's parent */
     
    5266#define FAT_CLST_ROOT           FAT_CLST_RES1
    5367
     68/*
     69 * Convenience macros for computing some frequently used values from the
     70 * primitive boot sector members.
     71 */
     72#define RDS(bs)   ((sizeof(fat_dentry_t) * RDE((bs))) / BPS((bs))) + \
     73                   (((sizeof(fat_dentry_t) * RDE((bs))) % BPS((bs))) != 0)
     74#define SSA(bs)   (RSCNT((bs)) + FATCNT((bs)) * SF((bs)) + RDS(bs))
     75#define DS(bs)    (TS(bs) - SSA(bs))
     76#define CC(bs)    (DS(bs) / SPC(bs))
     77
     78#define CLBN2PBN(bs, cl, bn) \
     79        (SSA((bs)) + ((cl) - FAT_CLST_FIRST) * SPC((bs)) + (bn) % SPC((bs)))
     80
     81#define FAT_IS_FAT12(bs)        (CC(bs) < FAT12_CLST_MAX)
     82#define FAT_IS_FAT16(bs) \
     83    ((CC(bs) >= FAT12_CLST_MAX) && (CC(bs) < FAT16_CLST_MAX))
     84#define FAT_IS_FAT32(bs)        (CC(bs) >= FAT16_CLST_MAX)
     85
     86#define FAT_CLST_SIZE(bs) \
     87    (FAT_IS_FAT32(bs) ? FAT32_CLST_SIZE : FAT16_CLST_SIZE)
     88
     89#define FAT_MASK(bs) \
     90    (FAT_IS_FAT12(bs) ? FAT12_MASK : \
     91    (FAT_IS_FAT32(bs) ? FAT32_MASK : FAT16_MASK))
     92
     93#define FAT_CLST_LAST1(bs)      (FAT32_CLST_LAST1 & FAT_MASK((bs)))
     94#define FAT_CLST_LAST8(bs)      (FAT32_CLST_LAST8 & FAT_MASK((bs)))
     95#define FAT_CLST_BAD(bs)        (FAT32_CLST_BAD & FAT_MASK((bs)))
     96
     97#define FAT_ROOT_CLST(bs) \
     98    (FAT_IS_FAT32(bs) ? uint32_t_le2host(bs->fat32.root_cluster) : \
     99    FAT_CLST_ROOT)
     100
    54101/* forward declarations */
    55102struct block;
     
    57104struct fat_bs;
    58105
    59 typedef uint16_t fat_cluster_t;
     106typedef uint32_t fat_cluster_t;
    60107
    61 #define fat_clusters_get(numc, bs, dh, fc) \
    62     fat_cluster_walk((bs), (dh), (fc), NULL, (numc), (uint16_t) -1)
     108#define fat_clusters_get(numc, bs, sid, fc) \
     109    fat_cluster_walk((bs), (sid), (fc), NULL, (numc), (uint32_t) -1)
    63110extern int fat_cluster_walk(struct fat_bs *, service_id_t, fat_cluster_t,
    64     fat_cluster_t *, uint16_t *, uint16_t);
     111    fat_cluster_t *, uint32_t *, uint32_t);
    65112
    66113extern int fat_block_get(block_t **, struct fat_bs *, struct fat_node *,
  • uspace/srv/fs/fat/fat_idx.c

    rbb74dabe rc05642d  
    116116#define UPH_BUCKETS     (1 << UPH_BUCKETS_LOG)
    117117
    118 #define UPH_DH_KEY      0
     118#define UPH_SID_KEY     0
    119119#define UPH_PFC_KEY     1
    120120#define UPH_PDI_KEY     2
     
    122122static hash_index_t pos_hash(unsigned long key[])
    123123{
    124         service_id_t service_id = (service_id_t)key[UPH_DH_KEY];
     124        service_id_t service_id = (service_id_t)key[UPH_SID_KEY];
    125125        fat_cluster_t pfc = (fat_cluster_t)key[UPH_PFC_KEY];
    126126        unsigned pdi = (unsigned)key[UPH_PDI_KEY];
     
    150150static int pos_compare(unsigned long key[], hash_count_t keys, link_t *item)
    151151{
    152         service_id_t service_id = (service_id_t)key[UPH_DH_KEY];
     152        service_id_t service_id = (service_id_t)key[UPH_SID_KEY];
    153153        fat_cluster_t pfc;
    154154        unsigned pdi;
     
    190190#define UIH_BUCKETS     (1 << UIH_BUCKETS_LOG)
    191191
    192 #define UIH_DH_KEY      0
     192#define UIH_SID_KEY     0
    193193#define UIH_INDEX_KEY   1
    194194
    195195static hash_index_t idx_hash(unsigned long key[])
    196196{
    197         service_id_t service_id = (service_id_t)key[UIH_DH_KEY];
     197        service_id_t service_id = (service_id_t)key[UIH_SID_KEY];
    198198        fs_index_t index = (fs_index_t)key[UIH_INDEX_KEY];
    199199
     
    209209static int idx_compare(unsigned long key[], hash_count_t keys, link_t *item)
    210210{
    211         service_id_t service_id = (service_id_t)key[UIH_DH_KEY];
     211        service_id_t service_id = (service_id_t)key[UIH_SID_KEY];
    212212        fs_index_t index;
    213213        fat_idx_t *fidx = list_get_instance(item, fat_idx_t, uih_link);
     
    402402               
    403403        unsigned long ikey[] = {
    404                 [UIH_DH_KEY] = service_id,
     404                [UIH_SID_KEY] = service_id,
    405405                [UIH_INDEX_KEY] = fidx->index,
    406406        };
     
    420420        link_t *l;
    421421        unsigned long pkey[] = {
    422                 [UPH_DH_KEY] = service_id,
     422                [UPH_SID_KEY] = service_id,
    423423                [UPH_PFC_KEY] = pfc,
    424424                [UPH_PDI_KEY] = pdi,
     
    439439               
    440440                unsigned long ikey[] = {
    441                         [UIH_DH_KEY] = service_id,
     441                        [UIH_SID_KEY] = service_id,
    442442                        [UIH_INDEX_KEY] = fidx->index,
    443443                };
     
    458458{
    459459        unsigned long pkey[] = {
    460                 [UPH_DH_KEY] = idx->service_id,
     460                [UPH_SID_KEY] = idx->service_id,
    461461                [UPH_PFC_KEY] = idx->pfc,
    462462                [UPH_PDI_KEY] = idx->pdi,
     
    471471{
    472472        unsigned long pkey[] = {
    473                 [UPH_DH_KEY] = idx->service_id,
     473                [UPH_SID_KEY] = idx->service_id,
    474474                [UPH_PFC_KEY] = idx->pfc,
    475475                [UPH_PDI_KEY] = idx->pdi,
     
    487487        link_t *l;
    488488        unsigned long ikey[] = {
    489                 [UIH_DH_KEY] = service_id,
     489                [UIH_SID_KEY] = service_id,
    490490                [UIH_INDEX_KEY] = index,
    491491        };
     
    509509{
    510510        unsigned long ikey[] = {
    511                 [UIH_DH_KEY] = idx->service_id,
     511                [UIH_SID_KEY] = idx->service_id,
    512512                [UIH_INDEX_KEY] = idx->index,
    513513        };
     
    571571{
    572572        unsigned long ikey[] = {
    573                 [UIH_DH_KEY] = service_id
     573                [UIH_SID_KEY] = service_id
    574574        };
    575575        unsigned long pkey[] = {
    576                 [UPH_DH_KEY] = service_id
     576                [UPH_SID_KEY] = service_id
    577577        };
    578578
  • uspace/srv/fs/fat/fat_ops.c

    rbb74dabe rc05642d  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
     3 * Copyright (c) 2011 Oleg Romanenko
    34 * All rights reserved.
    45 *
     
    2930/** @addtogroup fs
    3031 * @{
    31  */ 
     32 */
    3233
    3334/**
     
    3940#include "fat_dentry.h"
    4041#include "fat_fat.h"
     42#include "fat_directory.h"
    4143#include "../../vfs/vfs.h"
    4244#include <libfs.h>
     
    5658#include <align.h>
    5759#include <malloc.h>
     60#include <str.h>
    5861
    5962#define FAT_NODE(node)  ((node) ? (fat_node_t *) (node)->data : NULL)
     
    8790static bool fat_is_directory(fs_node_t *);
    8891static bool fat_is_file(fs_node_t *node);
    89 static service_id_t fat_device_get(fs_node_t *node);
     92static service_id_t fat_service_get(fs_node_t *node);
    9093
    9194/*
     
    104107        node->dirty = false;
    105108        node->lastc_cached_valid = false;
    106         node->lastc_cached_value = FAT_CLST_LAST1;
     109        node->lastc_cached_value = 0;
    107110        node->currc_cached_valid = false;
    108111        node->currc_cached_bn = 0;
    109         node->currc_cached_value = FAT_CLST_LAST1;
     112        node->currc_cached_value = 0;
    110113}
    111114
     
    116119        fat_dentry_t *d;
    117120        int rc;
    118        
     121
    119122        assert(node->dirty);
    120123
    121124        bs = block_bb_get(node->idx->service_id);
    122        
     125
    123126        /* Read the block that contains the dentry of interest. */
    124127        rc = _fat_block_get(&b, bs, node->idx->service_id, node->idx->pfc,
     
    136139                d->attr = FAT_ATTR_SUBDIR;
    137140        }
    138        
     141
    139142        /* TODO: update other fields? (e.g time fields) */
    140        
     143
    141144        b->dirty = true;                /* need to sync block */
    142145        rc = block_put(b);
     
    255258        fn->data = nodep;
    256259        nodep->bp = fn;
    257        
     260
    258261        *nodepp = nodep;
    259262        return EOK;
     
    291294         * We must instantiate the node from the file system.
    292295         */
    293        
     296
    294297        assert(idxp->pfc);
    295298
     
    309312
    310313        d = ((fat_dentry_t *)b->data) + (idxp->pdi % DPS(bs));
     314        if (FAT_IS_FAT32(bs)) {
     315                nodep->firstc = uint16_t_le2host(d->firstc_lo) |
     316                    (uint16_t_le2host(d->firstc_hi) << 16);
     317        } else
     318                nodep->firstc = uint16_t_le2host(d->firstc);
     319
    311320        if (d->attr & FAT_ATTR_SUBDIR) {
    312                 /* 
     321                /*
    313322                 * The only directory which does not have this bit set is the
    314323                 * root directory itself. The root directory node is handled
     
    316325                 */
    317326                nodep->type = FAT_DIRECTORY;
     327
    318328                /*
    319329                 * Unfortunately, the 'size' field of the FAT dentry is not
     
    321331                 * size of the directory by walking the FAT.
    322332                 */
    323                 uint16_t clusters;
     333                uint32_t clusters;
    324334                rc = fat_clusters_get(&clusters, bs, idxp->service_id,
    325                     uint16_t_le2host(d->firstc));
     335                    nodep->firstc);
    326336                if (rc != EOK) {
    327337                        (void) block_put(b);
     
    334344                nodep->size = uint32_t_le2host(d->size);
    335345        }
    336         nodep->firstc = uint16_t_le2host(d->firstc);
     346
    337347        nodep->lnkcnt = 1;
    338348        nodep->refcnt = 1;
     
    363373int fat_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
    364374{
    365         fat_bs_t *bs;
    366375        fat_node_t *parentp = FAT_NODE(pfn);
    367         char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1];
    368         unsigned i, j;
    369         unsigned blocks;
     376        char name[FAT_LFN_NAME_SIZE];
    370377        fat_dentry_t *d;
    371378        service_id_t service_id;
    372         block_t *b;
    373379        int rc;
    374380
     
    376382        service_id = parentp->idx->service_id;
    377383        fibril_mutex_unlock(&parentp->idx->lock);
    378 
    379         bs = block_bb_get(service_id);
    380         blocks = parentp->size / BPS(bs);
    381         for (i = 0; i < blocks; i++) {
    382                 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
    383                 if (rc != EOK)
    384                         return rc;
    385                 for (j = 0; j < DPS(bs); j++) {
    386                         d = ((fat_dentry_t *)b->data) + j;
    387                         switch (fat_classify_dentry(d)) {
    388                         case FAT_DENTRY_SKIP:
    389                         case FAT_DENTRY_FREE:
    390                                 continue;
    391                         case FAT_DENTRY_LAST:
    392                                 /* miss */
    393                                 rc = block_put(b);
    394                                 *rfn = NULL;
    395                                 return rc;
    396                         default:
    397                         case FAT_DENTRY_VALID:
    398                                 fat_dentry_name_get(d, name);
    399                                 break;
     384       
     385        fat_directory_t di;
     386        rc = fat_directory_open(parentp, &di);
     387        if (rc != EOK)
     388                return rc;
     389
     390        while (fat_directory_read(&di, name, &d) == EOK) {
     391                if (fat_dentry_namecmp(name, component) == 0) {
     392                        /* hit */
     393                        fat_node_t *nodep;
     394                        aoff64_t o = di.pos %
     395                            (BPS(di.bs) / sizeof(fat_dentry_t));
     396                        fat_idx_t *idx = fat_idx_get_by_pos(service_id,
     397                            parentp->firstc, di.bnum * DPS(di.bs) + o);
     398                        if (!idx) {
     399                                /*
     400                                 * Can happen if memory is low or if we
     401                                 * run out of 32-bit indices.
     402                                 */
     403                                rc = fat_directory_close(&di);
     404                                return (rc == EOK) ? ENOMEM : rc;
    400405                        }
    401                         if (fat_dentry_namecmp(name, component) == 0) {
    402                                 /* hit */
    403                                 fat_node_t *nodep;
    404                                 fat_idx_t *idx = fat_idx_get_by_pos(service_id,
    405                                     parentp->firstc, i * DPS(bs) + j);
    406                                 if (!idx) {
    407                                         /*
    408                                          * Can happen if memory is low or if we
    409                                          * run out of 32-bit indices.
    410                                          */
    411                                         rc = block_put(b);
    412                                         return (rc == EOK) ? ENOMEM : rc;
    413                                 }
    414                                 rc = fat_node_get_core(&nodep, idx);
    415                                 fibril_mutex_unlock(&idx->lock);
    416                                 if (rc != EOK) {
    417                                         (void) block_put(b);
    418                                         return rc;
    419                                 }
    420                                 *rfn = FS_NODE(nodep);
    421                                 rc = block_put(b);
    422                                 if (rc != EOK)
    423                                         (void) fat_node_put(*rfn);
     406                        rc = fat_node_get_core(&nodep, idx);
     407                        fibril_mutex_unlock(&idx->lock);
     408                        if (rc != EOK) {
     409                                (void) fat_directory_close(&di);
    424410                                return rc;
    425411                        }
    426                 }
    427                 rc = block_put(b);
    428                 if (rc != EOK)
     412                        *rfn = FS_NODE(nodep);
     413                        rc = fat_directory_close(&di);
     414                        if (rc != EOK)
     415                                (void) fat_node_put(*rfn);
    429416                        return rc;
    430         }
    431 
     417                } else {
     418                        rc = fat_directory_next(&di);
     419                        if (rc != EOK)
     420                                break;
     421                }
     422        }
     423        (void) fat_directory_close(&di);
    432424        *rfn = NULL;
    433425        return EOK;
     
    591583        fat_bs_t *bs;
    592584        block_t *b;
    593         unsigned i, j;
    594         unsigned blocks;
    595         fat_cluster_t mcl, lcl;
     585        fat_directory_t di;
     586        fat_dentry_t de;
    596587        int rc;
    597588
     
    607598        fibril_mutex_unlock(&childp->lock);
    608599
    609         if (!fat_dentry_name_verify(name)) {
    610                 /*
    611                  * Attempt to create unsupported name.
    612                  */
     600        if (!fat_valid_name(name))
    613601                return ENOTSUP;
    614         }
    615 
    616         /*
    617          * Get us an unused parent node's dentry or grow the parent and allocate
    618          * a new one.
    619          */
    620        
     602
    621603        fibril_mutex_lock(&parentp->idx->lock);
    622604        bs = block_bb_get(parentp->idx->service_id);
    623 
    624         blocks = parentp->size / BPS(bs);
    625 
    626         for (i = 0; i < blocks; i++) {
    627                 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
    628                 if (rc != EOK) {
    629                         fibril_mutex_unlock(&parentp->idx->lock);
    630                         return rc;
    631                 }
    632                 for (j = 0; j < DPS(bs); j++) {
    633                         d = ((fat_dentry_t *)b->data) + j;
    634                         switch (fat_classify_dentry(d)) {
    635                         case FAT_DENTRY_SKIP:
    636                         case FAT_DENTRY_VALID:
    637                                 /* skipping used and meta entries */
    638                                 continue;
    639                         case FAT_DENTRY_FREE:
    640                         case FAT_DENTRY_LAST:
    641                                 /* found an empty slot */
    642                                 goto hit;
    643                         }
    644                 }
    645                 rc = block_put(b);
    646                 if (rc != EOK) {
    647                         fibril_mutex_unlock(&parentp->idx->lock);
    648                         return rc;
    649                 }
    650         }
    651         j = 0;
    652        
    653         /*
    654          * We need to grow the parent in order to create a new unused dentry.
    655          */
    656         if (parentp->firstc == FAT_CLST_ROOT) {
    657                 /* Can't grow the root directory. */
    658                 fibril_mutex_unlock(&parentp->idx->lock);
    659                 return ENOSPC;
    660         }
    661         rc = fat_alloc_clusters(bs, parentp->idx->service_id, 1, &mcl, &lcl);
     605        rc = fat_directory_open(parentp, &di);
    662606        if (rc != EOK) {
    663607                fibril_mutex_unlock(&parentp->idx->lock);
    664608                return rc;
    665609        }
    666         rc = fat_zero_cluster(bs, parentp->idx->service_id, mcl);
    667         if (rc != EOK) {
    668                 (void) fat_free_clusters(bs, parentp->idx->service_id, mcl);
    669                 fibril_mutex_unlock(&parentp->idx->lock);
    670                 return rc;
    671         }
    672         rc = fat_append_clusters(bs, parentp, mcl, lcl);
    673         if (rc != EOK) {
    674                 (void) fat_free_clusters(bs, parentp->idx->service_id, mcl);
    675                 fibril_mutex_unlock(&parentp->idx->lock);
    676                 return rc;
    677         }
    678         parentp->size += BPS(bs) * SPC(bs);
    679         parentp->dirty = true;          /* need to sync node */
    680         rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
    681         if (rc != EOK) {
    682                 fibril_mutex_unlock(&parentp->idx->lock);
    683                 return rc;
    684         }
    685         d = (fat_dentry_t *)b->data;
    686 
    687 hit:
     610
    688611        /*
    689612         * At this point we only establish the link between the parent and the
     
    692615         * dentry data is kept in the child node structure.
    693616         */
    694         memset(d, 0, sizeof(fat_dentry_t));
    695         fat_dentry_name_set(d, name);
    696         b->dirty = true;                /* need to sync block */
    697         rc = block_put(b);
     617        memset(&de, 0, sizeof(fat_dentry_t));
     618
     619        rc = fat_directory_write(&di, name, &de);
     620        if (rc != EOK) {
     621                (void) fat_directory_close(&di);
     622                fibril_mutex_unlock(&parentp->idx->lock);
     623                return rc;
     624        }
     625        rc = fat_directory_close(&di);
     626        if (rc != EOK) {
     627                fibril_mutex_unlock(&parentp->idx->lock);
     628                return rc;
     629        }
     630
    698631        fibril_mutex_unlock(&parentp->idx->lock);
    699         if (rc != EOK)
    700                 return rc;
    701632
    702633        fibril_mutex_lock(&childp->idx->lock);
    703        
     634
    704635        if (childp->type == FAT_DIRECTORY) {
    705636                /*
     
    720651                d = (fat_dentry_t *) b->data;
    721652                if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) ||
    722                     (str_cmp((char *) d->name, FAT_NAME_DOT)) == 0) {
     653                    (bcmp(d->name, FAT_NAME_DOT, FAT_NAME_LEN)) == 0) {
    723654                        memset(d, 0, sizeof(fat_dentry_t));
    724655                        memcpy(d->name, FAT_NAME_DOT, FAT_NAME_LEN);
     
    730661                d++;
    731662                if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) ||
    732                     (str_cmp((char *) d->name, FAT_NAME_DOT_DOT) == 0)) {
     663                    (bcmp(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN) == 0)) {
    733664                        memset(d, 0, sizeof(fat_dentry_t));
    734665                        memcpy(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN);
    735666                        memcpy(d->ext, FAT_EXT_PAD, FAT_EXT_LEN);
    736667                        d->attr = FAT_ATTR_SUBDIR;
    737                         d->firstc = (parentp->firstc == FAT_CLST_ROOT) ?
    738                             host2uint16_t_le(FAT_CLST_RES0) :
     668                        d->firstc = (parentp->firstc == FAT_ROOT_CLST(bs)) ?
     669                            host2uint16_t_le(FAT_CLST_ROOTPAR) :
    739670                            host2uint16_t_le(parentp->firstc);
    740671                        /* TODO: initialize also the date/time members. */
     
    750681
    751682        childp->idx->pfc = parentp->firstc;
    752         childp->idx->pdi = i * DPS(bs) + j;
     683        childp->idx->pdi = di.pos;      /* di.pos holds absolute position of SFN entry */
    753684        fibril_mutex_unlock(&childp->idx->lock);
    754685
     
    770701        fat_node_t *parentp = FAT_NODE(pfn);
    771702        fat_node_t *childp = FAT_NODE(cfn);
    772         fat_bs_t *bs;
    773         fat_dentry_t *d;
    774         block_t *b;
    775703        bool has_children;
    776704        int rc;
     
    778706        if (!parentp)
    779707                return EBUSY;
    780        
     708
    781709        rc = fat_has_children(&has_children, cfn);
    782710        if (rc != EOK)
     
    789717        assert(childp->lnkcnt == 1);
    790718        fibril_mutex_lock(&childp->idx->lock);
    791         bs = block_bb_get(childp->idx->service_id);
    792 
    793         rc = _fat_block_get(&b, bs, childp->idx->service_id, childp->idx->pfc,
    794             NULL, (childp->idx->pdi * sizeof(fat_dentry_t)) / BPS(bs),
    795             BLOCK_FLAGS_NONE);
    796         if (rc != EOK)
     719       
     720        fat_directory_t di;
     721        rc = fat_directory_open(parentp, &di);
     722        if (rc != EOK)
    797723                goto error;
    798         d = (fat_dentry_t *)b->data +
    799             (childp->idx->pdi % (BPS(bs) / sizeof(fat_dentry_t)));
    800         /* mark the dentry as not-currently-used */
    801         d->name[0] = FAT_DENTRY_ERASED;
    802         b->dirty = true;                /* need to sync block */
    803         rc = block_put(b);
     724        rc = fat_directory_seek(&di, childp->idx->pdi);
     725        if (rc != EOK)
     726                goto error;
     727        rc = fat_directory_erase(&di);
     728        if (rc != EOK)
     729                goto error;
     730        rc = fat_directory_close(&di);
    804731        if (rc != EOK)
    805732                goto error;
     
    820747
    821748error:
    822         fibril_mutex_unlock(&parentp->idx->lock);
     749        (void) fat_directory_close(&di);
     750        fibril_mutex_unlock(&childp->idx->lock);
    823751        fibril_mutex_unlock(&childp->lock);
    824         fibril_mutex_unlock(&childp->idx->lock);
     752        fibril_mutex_unlock(&parentp->lock);
    825753        return rc;
    826754}
     
    839767                return EOK;
    840768        }
    841        
     769
    842770        fibril_mutex_lock(&nodep->idx->lock);
    843771        bs = block_bb_get(nodep->idx->service_id);
     
    847775        for (i = 0; i < blocks; i++) {
    848776                fat_dentry_t *d;
    849        
     777
    850778                rc = fat_block_get(&b, bs, nodep, i, BLOCK_FLAGS_NONE);
    851779                if (rc != EOK) {
     
    875803                if (rc != EOK) {
    876804                        fibril_mutex_unlock(&nodep->idx->lock);
    877                         return rc;     
     805                        return rc;
    878806                }
    879807        }
     
    910838}
    911839
    912 service_id_t fat_device_get(fs_node_t *node)
     840service_id_t fat_service_get(fs_node_t *node)
    913841{
    914842        return 0;
     
    932860        .is_directory = fat_is_directory,
    933861        .is_file = fat_is_file,
    934         .device_get = fat_device_get
     862        .service_get = fat_service_get
    935863};
    936864
     
    946874        fat_bs_t *bs;
    947875        int rc;
    948        
     876
    949877        /* Check for option enabling write through. */
    950878        if (str_cmp(opts, "wtcache") == 0)
     
    1003931                return ENOMEM;
    1004932        }
     933
    1005934        fs_node_initialize(rfn);
    1006935        fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t));
     
    1027956
    1028957        rootp->type = FAT_DIRECTORY;
    1029         rootp->firstc = FAT_CLST_ROOT;
     958        rootp->firstc = FAT_ROOT_CLST(bs);
    1030959        rootp->refcnt = 1;
    1031960        rootp->lnkcnt = 0;      /* FS root is not linked */
    1032         rootp->size = RDE(bs) * sizeof(fat_dentry_t);
     961
     962        if (FAT_IS_FAT32(bs)) {
     963                uint32_t clusters;
     964                rc = fat_clusters_get(&clusters, bs, service_id, rootp->firstc);
     965                if (rc != EOK) {
     966                        free(rfn);
     967                        free(rootp);
     968                        (void) block_cache_fini(service_id);
     969                        block_fini(service_id);
     970                        fat_idx_fini_by_service_id(service_id);
     971                        return ENOTSUP;
     972                }
     973                rootp->size = BPS(bs) * SPC(bs) * clusters;
     974        } else
     975                rootp->size = RDE(bs) * sizeof(fat_dentry_t);
     976
    1033977        rootp->idx = ridxp;
    1034978        ridxp->nodep = rootp;
    1035979        rootp->bp = rfn;
    1036980        rfn->data = rootp;
    1037        
     981
    1038982        fibril_mutex_unlock(&ridxp->lock);
    1039983
     
    10641008                return EBUSY;
    10651009        }
    1066        
     1010
    10671011        /*
    10681012         * Put the root node and force it to the FAT free node list.
     
    11411085                }
    11421086        } else {
    1143                 unsigned bnum;
    11441087                aoff64_t spos = pos;
    1145                 char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1];
     1088                char name[FAT_LFN_NAME_SIZE];
    11461089                fat_dentry_t *d;
    11471090
     
    11501093                assert(BPS(bs) % sizeof(fat_dentry_t) == 0);
    11511094
    1152                 /*
    1153                  * Our strategy for readdir() is to use the position pointer as
    1154                  * an index into the array of all dentries. On entry, it points
    1155                  * to the first unread dentry. If we skip any dentries, we bump
    1156                  * the position pointer accordingly.
    1157                  */
    1158                 bnum = (pos * sizeof(fat_dentry_t)) / BPS(bs);
    1159                 while (bnum < nodep->size / BPS(bs)) {
    1160                         aoff64_t o;
    1161 
    1162                         rc = fat_block_get(&b, bs, nodep, bnum,
    1163                             BLOCK_FLAGS_NONE);
    1164                         if (rc != EOK)
    1165                                 goto err;
    1166                         for (o = pos % (BPS(bs) / sizeof(fat_dentry_t));
    1167                             o < BPS(bs) / sizeof(fat_dentry_t);
    1168                             o++, pos++) {
    1169                                 d = ((fat_dentry_t *)b->data) + o;
    1170                                 switch (fat_classify_dentry(d)) {
    1171                                 case FAT_DENTRY_SKIP:
    1172                                 case FAT_DENTRY_FREE:
    1173                                         continue;
    1174                                 case FAT_DENTRY_LAST:
    1175                                         rc = block_put(b);
    1176                                         if (rc != EOK)
    1177                                                 goto err;
    1178                                         goto miss;
    1179                                 default:
    1180                                 case FAT_DENTRY_VALID:
    1181                                         fat_dentry_name_get(d, name);
    1182                                         rc = block_put(b);
    1183                                         if (rc != EOK)
    1184                                                 goto err;
    1185                                         goto hit;
    1186                                 }
    1187                         }
    1188                         rc = block_put(b);
    1189                         if (rc != EOK)
    1190                                 goto err;
    1191                         bnum++;
    1192                 }
     1095                fat_directory_t di;
     1096                rc = fat_directory_open(nodep, &di);
     1097                if (rc != EOK)
     1098                        goto err;
     1099                rc = fat_directory_seek(&di, pos);
     1100                if (rc != EOK) {
     1101                        (void) fat_directory_close(&di);
     1102                        goto err;
     1103                }
     1104
     1105                rc = fat_directory_read(&di, name, &d);
     1106                if (rc == EOK)
     1107                        goto hit;
     1108                if (rc == ENOENT)
     1109                        goto miss;
     1110
     1111err:
     1112                (void) fat_node_put(fn);
     1113                async_answer_0(callid, rc);
     1114                return rc;
     1115
    11931116miss:
     1117                rc = fat_directory_close(&di);
     1118                if (rc != EOK)
     1119                        goto err;
    11941120                rc = fat_node_put(fn);
    11951121                async_answer_0(callid, rc != EOK ? rc : ENOENT);
     
    11971123                return rc != EOK ? rc : ENOENT;
    11981124
    1199 err:
    1200                 (void) fat_node_put(fn);
    1201                 async_answer_0(callid, rc);
    1202                 return rc;
    1203 
    12041125hit:
    1205                 (void) async_data_read_finalize(callid, name, str_size(name) + 1);
     1126                pos = di.pos;
     1127                rc = fat_directory_close(&di);
     1128                if (rc != EOK)
     1129                        goto err;
     1130                (void) async_data_read_finalize(callid, name,
     1131                    str_size(name) + 1);
    12061132                bytes = (pos - spos) + 1;
    12071133        }
     
    12311157                return ENOENT;
    12321158        nodep = FAT_NODE(fn);
    1233        
     1159
    12341160        ipc_callid_t callid;
    12351161        size_t len;
     
    12471173         * but this one greatly simplifies fat_write(). Note that we can afford
    12481174         * to do this because the client must be ready to handle the return
    1249          * value signalizing a smaller number of bytes written. 
    1250          */ 
     1175         * value signalizing a smaller number of bytes written.
     1176         */
    12511177        bytes = min(len, BPS(bs) - pos % BPS(bs));
    12521178        if (bytes == BPS(bs))
    12531179                flags |= BLOCK_FLAGS_NOREAD;
    1254        
     1180
    12551181        boundary = ROUND_UP(nodep->size, BPC(bs));
    12561182        if (pos < boundary) {
     
    12951221                 */
    12961222                unsigned nclsts;
    1297                 fat_cluster_t mcl, lcl; 
    1298  
     1223                fat_cluster_t mcl, lcl;
     1224
    12991225                nclsts = (ROUND_UP(pos + bytes, BPC(bs)) - boundary) / BPC(bs);
    13001226                /* create an independent chain of nclsts clusters in all FATs */
     
    13801306                nodep->size = size;
    13811307                nodep->dirty = true;            /* need to sync node */
    1382                 rc = EOK;       
     1308                rc = EOK;
    13831309        } else {
    13841310                /*
     
    14011327                nodep->size = size;
    14021328                nodep->dirty = true;            /* need to sync node */
    1403                 rc = EOK;       
     1329                rc = EOK;
    14041330        }
    14051331out:
     
    14441370        if (!fn)
    14451371                return ENOENT;
    1446        
     1372
    14471373        fat_node_t *nodep = FAT_NODE(fn);
    1448        
     1374
    14491375        nodep->dirty = true;
    14501376        rc = fat_node_sync(nodep);
    1451        
     1377
    14521378        fat_node_put(fn);
    14531379        return rc;
  • uspace/srv/fs/locfs/locfs_ops.c

    rbb74dabe rc05642d  
    418418}
    419419
    420 static service_id_t locfs_device_get(fs_node_t *fn)
     420static service_id_t locfs_service_get(fs_node_t *fn)
    421421{
    422422        locfs_node_t *node = (locfs_node_t *) fn->data;
     
    445445        .is_directory = locfs_is_directory,
    446446        .is_file = locfs_is_file,
    447         .device_get = locfs_device_get
     447        .service_get = locfs_service_get
    448448};
    449449
  • uspace/srv/fs/tmpfs/tmpfs_ops.c

    rbb74dabe rc05642d  
    114114}
    115115
    116 static service_id_t tmpfs_device_get(fs_node_t *fn)
     116static service_id_t tmpfs_service_get(fs_node_t *fn)
    117117{
    118118        return 0;
     
    136136        .is_directory = tmpfs_is_directory,
    137137        .is_file = tmpfs_is_file,
    138         .device_get = tmpfs_device_get
     138        .service_get = tmpfs_service_get
    139139};
    140140
  • uspace/srv/loc/loc.c

    rbb74dabe rc05642d  
    12311231        svc = loc_service_find_id(svc_id);
    12321232       
     1233        if (cat == NULL || svc == NULL) {
     1234                fibril_mutex_unlock(&cdir.mutex);
     1235                fibril_mutex_unlock(&services_list_mutex);
     1236                async_answer_0(iid, ENOENT);
     1237                return;
     1238        }
     1239       
    12331240        fibril_mutex_lock(&cat->mutex);
    12341241        retval = category_add_service(cat, svc);
     
    12701277        categ_dir_add_cat(&cdir, cat);
    12711278
     1279        cat = category_new("test3");
     1280        categ_dir_add_cat(&cdir, cat);
     1281
    12721282        cat = category_new("usbhc");
    12731283        categ_dir_add_cat(&cdir, cat);
    12741284
     1285        cat = category_new("virt-null");
     1286        categ_dir_add_cat(&cdir, cat);
     1287
    12751288        cat = category_new("virtual");
    12761289        categ_dir_add_cat(&cdir, cat);
     1290
    12771291
    12781292        return true;
Note: See TracChangeset for help on using the changeset viewer.