Changeset 2c448fb in mainline


Ignore:
Timestamp:
2008-02-27T22:49:48Z (17 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
7fe1f75
Parents:
56976a17
Message:

Move the core lookup logic from TMPFS to libfs.

Location:
uspace
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/libfs/libfs.c

    r56976a17 r2c448fb  
    11/*
    2  * Copyright (c) 2007 Jakub Jermar
     2 * Copyright (c) 2008 Jakub Jermar
    33 * All rights reserved.
    44 *
     
    4141#include <ipc/ipc.h>
    4242#include <as.h>
     43#include <assert.h>
     44#include <dirent.h>
    4345
    4446/** Register file system server.
     
    121123}
    122124
     125void libfs_lookup(libfs_ops_t *ops, int fs_handle, ipc_callid_t rid,
     126    ipc_call_t *request)
     127{
     128        unsigned next = IPC_GET_ARG1(*request);
     129        unsigned last = IPC_GET_ARG2(*request);
     130        int dev_handle = IPC_GET_ARG3(*request);
     131        int lflag = IPC_GET_ARG4(*request);
     132
     133        if (last < next)
     134                last += PLB_SIZE;
     135
     136        void *cur = ops->root_get();
     137        void *tmp = ops->child_get(cur);
     138
     139        if (ops->plb_get_char(next) == '/')
     140                next++;         /* eat slash */
     141       
     142        char component[NAME_MAX + 1];
     143        int len = 0;
     144        while (tmp && next <= last) {
     145
     146                /* collect the component */
     147                if (ops->plb_get_char(next) != '/') {
     148                        if (len + 1 == NAME_MAX) {
     149                                /* comopnent length overflow */
     150                                ipc_answer_0(rid, ENAMETOOLONG);
     151                                return;
     152                        }
     153                        component[len++] = ops->plb_get_char(next);
     154                        next++; /* process next character */
     155                        if (next <= last)
     156                                continue;
     157                }
     158
     159                assert(len);
     160                component[len] = '\0';
     161                next++;         /* eat slash */
     162                len = 0;
     163
     164                /* match the component */
     165                while (tmp && !ops->match(tmp, component))
     166                        tmp = ops->sibling_get(tmp);
     167
     168                /* handle miss: match amongst siblings */
     169                if (!tmp) {
     170                        if ((next > last) && (lflag & L_CREATE)) {
     171                                /* no components left and L_CREATE specified */
     172                                if (!ops->is_directory(cur)) {
     173                                        ipc_answer_0(rid, ENOTDIR);
     174                                        return;
     175                                }
     176                                void *nodep = ops->create(lflag);
     177                                if (nodep) {
     178                                        if (!ops->link(cur, nodep, component)) {
     179                                                ops->destroy(nodep);
     180                                                ipc_answer_0(rid, ENOSPC);
     181                                        } else {
     182                                                ipc_answer_5(rid, EOK,
     183                                                    fs_handle, dev_handle,
     184                                                    ops->index_get(nodep), 0,
     185                                                    ops->lnkcnt_get(nodep));
     186                                        }
     187                                } else {
     188                                        ipc_answer_0(rid, ENOSPC);
     189                                }
     190                                return;
     191                        }
     192                        ipc_answer_0(rid, ENOENT);
     193                        return;
     194                }
     195
     196                /* descend one level */
     197                cur = tmp;
     198                tmp = ops->child_get(tmp);
     199        }
     200
     201        /* handle miss: excessive components */
     202        if (!tmp && next <= last) {
     203                if (lflag & L_CREATE) {
     204                        if (!ops->is_directory(cur)) {
     205                                ipc_answer_0(rid, ENOTDIR);
     206                                return;
     207                        }
     208
     209                        /* collect next component */
     210                        while (next <= last) {
     211                                if (ops->plb_get_char(next) == '/') {
     212                                        /* more than one component */
     213                                        ipc_answer_0(rid, ENOENT);
     214                                        return;
     215                                }
     216                                if (len + 1 == NAME_MAX) {
     217                                        /* component length overflow */
     218                                        ipc_answer_0(rid, ENAMETOOLONG);
     219                                        return;
     220                                }
     221                                component[len++] = ops->plb_get_char(next);
     222                                next++; /* process next character */
     223                        }
     224                        assert(len);
     225                        component[len] = '\0';
     226                        len = 0;
     227                               
     228                        void *nodep = ops->create(lflag);
     229                        if (nodep) {
     230                                if (!ops->link(cur, nodep, component)) {
     231                                        ops->destroy(nodep);
     232                                        ipc_answer_0(rid, ENOSPC);
     233                                } else {
     234                                        ipc_answer_5(rid, EOK,
     235                                            fs_handle, dev_handle,
     236                                            ops->index_get(nodep), 0,
     237                                            ops->lnkcnt_get(nodep));
     238                                }
     239                        } else {
     240                                ipc_answer_0(rid, ENOSPC);
     241                        }
     242                        return;
     243                }
     244                ipc_answer_0(rid, ENOENT);
     245                return;
     246        }
     247
     248        /* handle hit */
     249        if (lflag & L_DESTROY) {
     250                unsigned old_lnkcnt = ops->lnkcnt_get(cur);
     251                int res = ops->unlink(cur);
     252                ipc_answer_5(rid, (ipcarg_t)res, fs_handle, dev_handle,
     253                    ops->index_get(cur), ops->size_get(cur), old_lnkcnt);
     254                return;
     255        }
     256        if ((lflag & (L_CREATE | L_EXCLUSIVE)) == (L_CREATE | L_EXCLUSIVE)) {
     257                ipc_answer_0(rid, EEXIST);
     258                return;
     259        }
     260        if ((lflag & L_FILE) && (ops->is_directory(cur))) {
     261                ipc_answer_0(rid, EISDIR);
     262                return;
     263        }
     264        if ((lflag & L_DIRECTORY) && (ops->is_file(cur))) {
     265                ipc_answer_0(rid, ENOTDIR);
     266                return;
     267        }
     268
     269        ipc_answer_5(rid, EOK, fs_handle, dev_handle, ops->index_get(cur),
     270            ops->size_get(cur), ops->lnkcnt_get(cur));
     271}
     272
    123273/** @}
    124274 */
  • uspace/lib/libfs/libfs.h

    r56976a17 r2c448fb  
    4343
    4444typedef struct {
     45        bool (* match)(void *, const char *);
     46        void * (* create)(int);
     47        void (* destroy)(void *);
     48        bool (* link)(void *, void *, const char *);
     49        int (* unlink)(void *);
     50        unsigned long (* index_get)(void *);
     51        unsigned long (* size_get)(void *);
     52        unsigned (* lnkcnt_get)(void *);
     53        void *(* child_get)(void *);
     54        void *(* sibling_get)(void *);
     55        void *(* root_get)(void);
     56        char (* plb_get_char)(unsigned pos);   
     57        bool (* is_directory)(void *);
     58        bool (* is_file)(void *);
     59} libfs_ops_t;
     60
     61typedef struct {
    4562        int fs_handle;          /**< File system handle. */
    4663        ipcarg_t vfs_phonehash; /**< Initial VFS phonehash. */
     
    5673extern void node_del_mp(int, unsigned long);
    5774extern bool node_is_mp(int, unsigned long);
     75
     76extern void libfs_lookup(libfs_ops_t *, int, ipc_callid_t, ipc_call_t *);
     77
    5878#endif
    5979
  • uspace/srv/fs/tmpfs/tmpfs_ops.c

    r56976a17 r2c448fb  
    4646#include <string.h>
    4747#include <stdio.h>
    48 #include <dirent.h>
    4948#include <assert.h>
    5049#include <sys/types.h>
    5150#include <libadt/hash_table.h>
    5251#include <as.h>
     52#include <libfs.h>
    5353
    5454#define min(a, b)               ((a) < (b) ? (a) : (b))
    5555#define max(a, b)               ((a) > (b) ? (a) : (b))
    5656
    57 #define PLB_GET_CHAR(i)         (tmpfs_reg.plb_ro[(i) % PLB_SIZE])
    58 
    5957#define DENTRIES_BUCKETS        256
    6058
    61 #define TMPFS_GET_INDEX(x)      (((tmpfs_dentry_t *)(x))->index)
    62 #define TMPFS_GET_LNKCNT(x)     1
     59/*
     60 * For now, we don't distinguish between different dev_handles/instances. All
     61 * requests resolve to the only instance, rooted in the following variable.
     62 */
     63static tmpfs_dentry_t *root;
     64
     65/*
     66 * Implementation of the libfs interface.
     67 */
    6368
    6469/* Forward declarations of static functions. */
    65 static void *create_node(int);
    66 static bool link_node(void *, void *, const char *);
    67 static int unlink_node(void *);
    68 static void destroy_node(void *);
     70static bool tmpfs_match(void *, const char *);
     71static void *tmpfs_create_node(int);
     72static bool tmpfs_link_node(void *, void *, const char *);
     73static int tmpfs_unlink_node(void *);
     74static void tmpfs_destroy_node(void *);
     75
     76/* Implementation of helper functions. */
     77static unsigned long tmpfs_index_get(void *nodep)
     78{
     79        return ((tmpfs_dentry_t *) nodep)->index;
     80}
     81
     82static unsigned long tmpfs_size_get(void *nodep)
     83{
     84        return ((tmpfs_dentry_t *) nodep)->size;
     85}
     86
     87static unsigned tmpfs_lnkcnt_get(void *nodep)
     88{
     89        return 1;
     90}
     91
     92static void *tmpfs_child_get(void *nodep)
     93{
     94        return ((tmpfs_dentry_t *) nodep)->child;
     95}
     96
     97static void *tmpfs_sibling_get(void *nodep)
     98{
     99        return ((tmpfs_dentry_t *) nodep)->sibling;
     100}
     101
     102static void *tmpfs_root_get(void)
     103{
     104        return root;
     105}
     106
     107static char tmpfs_plb_get_char(unsigned pos)
     108{
     109        return tmpfs_reg.plb_ro[pos % PLB_SIZE];
     110}
     111
     112static bool tmpfs_is_directory(void *nodep)
     113{
     114        return ((tmpfs_dentry_t *) nodep)->type == TMPFS_DIRECTORY;
     115}
     116
     117static bool tmpfs_is_file(void *nodep)
     118{
     119        return ((tmpfs_dentry_t *) nodep)->type == TMPFS_FILE;
     120}
     121
     122/** libfs operations */
     123libfs_ops_t tmpfs_libfs_ops = {
     124        .match = tmpfs_match,
     125        .create = tmpfs_create_node,
     126        .destroy = tmpfs_destroy_node,
     127        .link = tmpfs_link_node,
     128        .unlink = tmpfs_unlink_node,
     129        .index_get = tmpfs_index_get,
     130        .size_get = tmpfs_size_get,
     131        .lnkcnt_get = tmpfs_lnkcnt_get,
     132        .child_get = tmpfs_child_get,
     133        .sibling_get = tmpfs_sibling_get,
     134        .root_get = tmpfs_root_get,
     135        .plb_get_char = tmpfs_plb_get_char,
     136        .is_directory = tmpfs_is_directory,
     137        .is_file = tmpfs_is_file
     138};
    69139
    70140/** Hash table of all directory entries. */
    71141hash_table_t dentries;
    72142
     143/* Implementation of hash table interface. */
    73144static hash_index_t dentries_hash(unsigned long *key)
    74145{
     
    110181}
    111182
    112 /*
    113  * For now, we don't distinguish between different dev_handles/instances. All
    114  * requests resolve to the only instance, rooted in the following variable.
    115  */
    116 static tmpfs_dentry_t *root;
    117 
    118183static bool tmpfs_init(void)
    119184{
    120185        if (!hash_table_create(&dentries, DENTRIES_BUCKETS, 1, &dentries_ops))
    121186                return false;
    122         root = (tmpfs_dentry_t *) create_node(L_DIRECTORY);
     187        root = (tmpfs_dentry_t *) tmpfs_create_node(L_DIRECTORY);
    123188        return root != NULL;
    124189}
     
    131196 * @return              True on match, false otherwise.
    132197 */
    133 static bool match_component(void *nodep, const char *component)
     198bool tmpfs_match(void *nodep, const char *component)
    134199{
    135200        tmpfs_dentry_t *dentry = (tmpfs_dentry_t *) nodep;
     
    138203}
    139204
    140 void *create_node(int lflag)
     205void *tmpfs_create_node(int lflag)
    141206{
    142207        assert((lflag & L_FILE) ^ (lflag & L_DIRECTORY));
     
    158223}
    159224
    160 bool link_node(void *prnt, void *chld, const char *nm)
     225bool tmpfs_link_node(void *prnt, void *chld, const char *nm)
    161226{
    162227        tmpfs_dentry_t *parentp = (tmpfs_dentry_t *) prnt;
     
    186251}
    187252
    188 int unlink_node(void *nodeptr)
     253int tmpfs_unlink_node(void *nodeptr)
    189254{
    190255        tmpfs_dentry_t *dentry = (tmpfs_dentry_t *)nodeptr;
     
    214279}
    215280
    216 void destroy_node(void *nodep)
     281void tmpfs_destroy_node(void *nodep)
    217282{
    218283        tmpfs_dentry_t *dentry = (tmpfs_dentry_t *) nodep;
     
    231296void tmpfs_lookup(ipc_callid_t rid, ipc_call_t *request)
    232297{
    233         unsigned next = IPC_GET_ARG1(*request);
    234         unsigned last = IPC_GET_ARG2(*request);
    235         int dev_handle = IPC_GET_ARG3(*request);
    236         int lflag = IPC_GET_ARG4(*request);
    237 
    238         if (last < next)
    239                 last += PLB_SIZE;
    240 
    241         /*
    242          * Initialize TMPFS.
    243          */
     298        /* Initialize TMPFS. */
    244299        if (!root && !tmpfs_init()) {
    245300                ipc_answer_0(rid, ENOMEM);
    246301                return;
    247302        }
    248 
    249         tmpfs_dentry_t *dtmp = root->child;
    250         tmpfs_dentry_t *dcur = root;
    251 
    252         if (PLB_GET_CHAR(next) == '/')
    253                 next++;         /* eat slash */
    254        
    255         char component[NAME_MAX + 1];
    256         int len = 0;
    257         while (dtmp && next <= last) {
    258 
    259                 /* collect the component */
    260                 if (PLB_GET_CHAR(next) != '/') {
    261                         if (len + 1 == NAME_MAX) {
    262                                 /* comopnent length overflow */
    263                                 ipc_answer_0(rid, ENAMETOOLONG);
    264                                 return;
    265                         }
    266                         component[len++] = PLB_GET_CHAR(next);
    267                         next++; /* process next character */
    268                         if (next <= last)
    269                                 continue;
    270                 }
    271 
    272                 assert(len);
    273                 component[len] = '\0';
    274                 next++;         /* eat slash */
    275                 len = 0;
    276 
    277                 /* match the component */
    278                 while (dtmp && !match_component(dtmp, component))
    279                         dtmp = dtmp->sibling;
    280 
    281                 /* handle miss: match amongst siblings */
    282                 if (!dtmp) {
    283                         if ((next > last) && (lflag & L_CREATE)) {
    284                                 /* no components left and L_CREATE specified */
    285                                 if (dcur->type != TMPFS_DIRECTORY) {
    286                                         ipc_answer_0(rid, ENOTDIR);
    287                                         return;
    288                                 }
    289                                 void *nodep = create_node(lflag);
    290                                 if (nodep) {
    291                                         if (!link_node(dcur, nodep,
    292                                             component)) {
    293                                                 destroy_node(nodep);
    294                                                 ipc_answer_0(rid, ENOSPC);
    295                                         } else {
    296                                                 ipc_answer_5(rid, EOK,
    297                                                     tmpfs_reg.fs_handle,
    298                                                     dev_handle,
    299                                                     TMPFS_GET_INDEX(nodep), 0,
    300                                                     TMPFS_GET_LNKCNT(nodep));
    301                                         }
    302                                 } else {
    303                                         ipc_answer_0(rid, ENOSPC);
    304                                 }
    305                                 return;
    306                         }
    307                         ipc_answer_0(rid, ENOENT);
    308                         return;
    309                 }
    310 
    311                 /* descend one level */
    312                 dcur = dtmp;
    313                 dtmp = dtmp->child;
    314         }
    315 
    316         /* handle miss: excessive components */
    317         if (!dtmp && next <= last) {
    318                 if (lflag & L_CREATE) {
    319                         if (dcur->type != TMPFS_DIRECTORY) {
    320                                 ipc_answer_0(rid, ENOTDIR);
    321                                 return;
    322                         }
    323 
    324                         /* collect next component */
    325                         while (next <= last) {
    326                                 if (PLB_GET_CHAR(next) == '/') {
    327                                         /* more than one component */
    328                                         ipc_answer_0(rid, ENOENT);
    329                                         return;
    330                                 }
    331                                 if (len + 1 == NAME_MAX) {
    332                                         /* component length overflow */
    333                                         ipc_answer_0(rid, ENAMETOOLONG);
    334                                         return;
    335                                 }
    336                                 component[len++] = PLB_GET_CHAR(next);
    337                                 next++; /* process next character */
    338                         }
    339                         assert(len);
    340                         component[len] = '\0';
    341                         len = 0;
    342                                
    343                         void *nodep = create_node(lflag);
    344                         if (nodep) {
    345                                 if (!link_node(dcur, nodep, component)) {
    346                                         destroy_node(nodep);
    347                                         ipc_answer_0(rid, ENOSPC);
    348                                 } else {
    349                                         ipc_answer_5(rid, EOK,
    350                                             tmpfs_reg.fs_handle,
    351                                             dev_handle, TMPFS_GET_INDEX(nodep),
    352                                             0, TMPFS_GET_LNKCNT(nodep));
    353                                 }
    354                         } else {
    355                                 ipc_answer_0(rid, ENOSPC);
    356                         }
    357                         return;
    358                 }
    359                 ipc_answer_0(rid, ENOENT);
    360                 return;
    361         }
    362 
    363         /* handle hit */
    364         if (lflag & L_DESTROY) {
    365                 unsigned old_lnkcnt = TMPFS_GET_LNKCNT(dcur);
    366                 int res = unlink_node(dcur);
    367                 ipc_answer_5(rid, (ipcarg_t)res, tmpfs_reg.fs_handle,
    368                     dev_handle, dcur->index, dcur->size, old_lnkcnt);
    369                 return;
    370         }
    371         if ((lflag & (L_CREATE | L_EXCLUSIVE)) == (L_CREATE | L_EXCLUSIVE)) {
    372                 ipc_answer_0(rid, EEXIST);
    373                 return;
    374         }
    375         if ((lflag & L_FILE) && (dcur->type != TMPFS_FILE)) {
    376                 ipc_answer_0(rid, EISDIR);
    377                 return;
    378         }
    379         if ((lflag & L_DIRECTORY) && (dcur->type != TMPFS_DIRECTORY)) {
    380                 ipc_answer_0(rid, ENOTDIR);
    381                 return;
    382         }
    383 
    384         ipc_answer_5(rid, EOK, tmpfs_reg.fs_handle, dev_handle, dcur->index,
    385             dcur->size, TMPFS_GET_LNKCNT(dcur));
     303        libfs_lookup(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request);
    386304}
    387305
     
    562480        tmpfs_dentry_t *dentry = hash_table_get_instance(hlp, tmpfs_dentry_t,
    563481            dh_link);
    564         destroy_node(dentry);
     482        tmpfs_destroy_node(dentry);
    565483        ipc_answer_0(rid, EOK);
    566484}
Note: See TracChangeset for help on using the changeset viewer.