Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/fs/mfs/mfs_ops.c

    rc2e50d7 r7a46bfe  
    4343
    4444static bool check_magic_number(uint16_t magic, bool *native,
    45     mfs_version_t *version, bool *longfilenames);
     45                               mfs_version_t *version, bool *longfilenames);
    4646static int mfs_node_core_get(fs_node_t **rfn, struct mfs_instance *inst,
    47     fs_index_t index);
     47                             fs_index_t index);
     48
    4849static int mfs_node_put(fs_node_t *fsnode);
    4950static int mfs_node_open(fs_node_t *fsnode);
     
    5455static int mfs_has_children(bool *has_children, fs_node_t *fsnode);
    5556static int mfs_root_get(fs_node_t **rfn, service_id_t service_id);
    56 static service_id_t mfs_service_get(fs_node_t *fsnode);
     57static service_id_t mfs_device_get(fs_node_t *fsnode);
    5758static aoff64_t mfs_size_get(fs_node_t *node);
    5859static int mfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component);
     
    6364static hash_index_t open_nodes_hash(unsigned long key[]);
    6465static int open_nodes_compare(unsigned long key[], hash_count_t keys,
    65     link_t *item);
     66                link_t *item);
    6667static void open_nodes_remove_cb(link_t *link);
     68
    6769static int mfs_node_get(fs_node_t **rfn, service_id_t service_id,
    68     fs_index_t index);
    69 static int mfs_instance_get(service_id_t service_id,
    70     struct mfs_instance **instance);
    71 static int mfs_check_sanity(struct mfs_sb_info *sbi);
    72 static bool is_power_of_two(uint32_t n);
    73 
     70                        fs_index_t index);
     71static int
     72mfs_instance_get(service_id_t service_id, struct mfs_instance **instance);
     73
     74
     75static LIST_INITIALIZE(inst_list);
     76static FIBRIL_MUTEX_INITIALIZE(inst_list_mutex);
    7477static hash_table_t open_nodes;
    7578static FIBRIL_MUTEX_INITIALIZE(open_nodes_lock);
     
    7881        .size_get = mfs_size_get,
    7982        .root_get = mfs_root_get,
    80         .service_get = mfs_service_get,
     83        .device_get = mfs_device_get,
    8184        .is_directory = mfs_is_directory,
    8285        .is_file = mfs_is_file,
     
    9598
    9699/* Hash table interface for open nodes hash table */
    97 static hash_index_t
    98 open_nodes_hash(unsigned long key[])
     100static hash_index_t open_nodes_hash(unsigned long key[])
    99101{
    100102        /* TODO: This is very simple and probably can be improved */
     
    102104}
    103105
    104 static int
    105 open_nodes_compare(unsigned long key[], hash_count_t keys,
    106     link_t *item)
     106static int open_nodes_compare(unsigned long key[], hash_count_t keys,
     107                link_t *item)
    107108{
    108109        struct mfs_node *mnode = hash_table_get_instance(item, struct mfs_node, link);
     
    119120}
    120121
    121 static void
    122 open_nodes_remove_cb(link_t *link)
     122static void open_nodes_remove_cb(link_t *link)
    123123{
    124124        /* We don't use remove callback for this hash table */
     
    131131};
    132132
    133 int
    134 mfs_global_init(void)
     133int mfs_global_init(void)
    135134{
    136135        if (!hash_table_create(&open_nodes, OPEN_NODES_BUCKETS,
    137             OPEN_NODES_KEYS, &open_nodes_ops)) {
     136                        OPEN_NODES_KEYS, &open_nodes_ops)) {
    138137                return ENOMEM;
    139138        }
     
    143142static int
    144143mfs_mounted(service_id_t service_id, const char *opts, fs_index_t *index,
    145     aoff64_t *size, unsigned *linkcnt)
     144                aoff64_t *size, unsigned *linkcnt)
    146145{
    147146        enum cache_mode cmode;
    148         struct mfs_superblock *sb = NULL;
    149         struct mfs3_superblock *sb3 = NULL;
    150         struct mfs_sb_info *sbi = NULL;
    151         struct mfs_instance *instance = NULL;
     147        struct mfs_superblock *sb;
     148        struct mfs3_superblock *sb3;
     149        struct mfs_sb_info *sbi;
     150        struct mfs_instance *instance;
    152151        bool native, longnames;
    153152        mfs_version_t version;
     
    166165                return rc;
    167166
    168         /* Allocate space for generic MFS superblock */
     167        /*Allocate space for generic MFS superblock*/
    169168        sbi = malloc(sizeof(*sbi));
    170169        if (!sbi) {
    171                 rc = ENOMEM;
    172                 goto out_error;
    173         }
    174 
    175         /* Allocate space for filesystem instance */
     170                block_fini(service_id);
     171                return ENOMEM;
     172        }
     173
     174        /*Allocate space for filesystem instance*/
    176175        instance = malloc(sizeof(*instance));
    177176        if (!instance) {
    178                 rc = ENOMEM;
    179                 goto out_error;
    180         }
     177                free(sbi);
     178                block_fini(service_id);
     179                return ENOMEM;
     180        }
     181
     182        instance->open_nodes_cnt = 0;
    181183
    182184        sb = malloc(MFS_SUPERBLOCK_SIZE);
    183185        if (!sb) {
    184                 rc = ENOMEM;
    185                 goto out_error;
     186                free(instance);
     187                free(sbi);
     188                block_fini(service_id);
     189                return ENOMEM;
    186190        }
    187191
    188192        /* Read the superblock */
    189193        rc = block_read_direct(service_id, MFS_SUPERBLOCK << 1, 2, sb);
    190         if (rc != EOK)
    191                 goto out_error;
     194        if (rc != EOK) {
     195                free(instance);
     196                free(sbi);
     197                free(sb);
     198                block_fini(service_id);
     199                return rc;
     200        }
    192201
    193202        sb3 = (struct mfs3_superblock *) sb;
    194203
    195204        if (check_magic_number(sb->s_magic, &native, &version, &longnames)) {
    196                 /* This is a V1 or V2 Minix filesystem */
     205                /*This is a V1 or V2 Minix filesystem*/
    197206                magic = sb->s_magic;
    198207        } else if (check_magic_number(sb3->s_magic, &native, &version, &longnames)) {
    199                 /* This is a V3 Minix filesystem */
     208                /*This is a V3 Minix filesystem*/
    200209                magic = sb3->s_magic;
    201210        } else {
    202                 /* Not recognized */
     211                /*Not recognized*/
    203212                mfsdebug("magic number not recognized\n");
    204                 rc = ENOTSUP;
    205                 goto out_error;
     213                free(instance);
     214                free(sbi);
     215                free(sb);
     216                block_fini(service_id);
     217                return ENOTSUP;
    206218        }
    207219
    208220        mfsdebug("magic number recognized = %04x\n", magic);
    209221
    210         /* Fill superblock info structure */
     222        /*Fill superblock info structure*/
    211223
    212224        sbi->fs_version = version;
     
    246258                sbi->dirsize = longnames ? MFSL_DIRSIZE : MFS_DIRSIZE;
    247259                sbi->max_name_len = longnames ? MFS_L_MAX_NAME_LEN :
    248                     MFS_MAX_NAME_LEN;
    249         }
    250 
    251         if (sbi->log2_zone_size != 0) {
    252                 /* In MFS, file space is allocated per zones.
    253                  * Zones are a collection of consecutive blocks on disk.
    254                  *
    255                  * The current MFS implementation supports only filesystems
    256                  * where the size of a zone is equal to the
    257                  * size of a block.
    258                  */
    259                 rc = ENOTSUP;
    260                 goto out_error;
    261         }
    262 
     260                                    MFS_MAX_NAME_LEN;
     261        }
    263262        sbi->itable_off = 2 + sbi->ibmap_blocks + sbi->zbmap_blocks;
    264         if ((rc = mfs_check_sanity(sbi)) != EOK) {
    265                 fprintf(stderr, "Filesystem corrupted, invalid superblock");
    266                 goto out_error;
    267         }
     263
     264        free(sb);
    268265
    269266        rc = block_cache_init(service_id, sbi->block_size, 0, cmode);
    270267        if (rc != EOK) {
     268                free(instance);
     269                free(sbi);
     270                free(sb);
     271                block_cache_fini(service_id);
     272                block_fini(service_id);
    271273                mfsdebug("block cache initialization failed\n");
    272                 rc = EINVAL;
    273                 goto out_error;
    274         }
    275 
    276         /* Initialize the instance structure and remember it */
     274                return EINVAL;
     275        }
     276
     277        /*Initialize the instance structure and add it to the list*/
     278        link_initialize(&instance->link);
    277279        instance->service_id = service_id;
    278280        instance->sbi = sbi;
    279         instance->open_nodes_cnt = 0;
    280         rc = fs_instance_create(service_id, instance);
    281         if (rc != EOK) {
    282                 block_cache_fini(service_id);
    283                 mfsdebug("fs instance creation failed\n");
    284                 goto out_error;
    285         }
     281
     282        fibril_mutex_lock(&inst_list_mutex);
     283        list_append(&instance->link, &inst_list);
     284        fibril_mutex_unlock(&inst_list_mutex);
    286285
    287286        mfsdebug("mount successful\n");
     
    296295        *linkcnt = 1;
    297296
    298         free(sb);
    299 
    300297        return mfs_node_put(fn);
    301 
    302 out_error:
    303         block_fini(service_id);
    304         if (sb)
    305                 free(sb);
    306         if (sbi)
    307                 free(sbi);
    308         if(instance)
    309                 free(instance);
    310         return rc;
    311298}
    312299
     
    328315        block_fini(service_id);
    329316
    330         /* Remove and destroy the instance */
    331         (void) fs_instance_destroy(service_id);
     317        /* Remove the instance from the list */
     318        fibril_mutex_lock(&inst_list_mutex);
     319        list_remove(&inst->link);
     320        fibril_mutex_unlock(&inst_list_mutex);
     321
    332322        free(inst->sbi);
    333323        free(inst);
     
    335325}
    336326
    337 service_id_t
    338 mfs_service_get(fs_node_t *fsnode)
     327service_id_t mfs_device_get(fs_node_t *fsnode)
    339328{
    340329        struct mfs_node *node = fsnode->data;
     
    342331}
    343332
    344 static int
    345 mfs_create_node(fs_node_t **rfn, service_id_t service_id, int flags)
     333static int mfs_create_node(fs_node_t **rfn, service_id_t service_id, int flags)
    346334{
    347335        int r;
     
    357345                return r;
    358346
    359         /* Alloc a new inode */
     347        /*Alloc a new inode*/
    360348        r = mfs_alloc_inode(inst, &inum);
    361349        if (r != EOK)
     
    384372        if (flags & L_DIRECTORY) {
    385373                ino_i->i_mode = S_IFDIR;
    386                 ino_i->i_nlinks = 1; /* This accounts for the '.' dentry */
    387         } else
     374                ino_i->i_nlinks = 2; /*This accounts for the '.' dentry*/
     375        } else {
    388376                ino_i->i_mode = S_IFREG;
     377                ino_i->i_nlinks = 1;
     378        }
    389379
    390380        ino_i->i_uid = 0;
     
    435425}
    436426
    437 static int
    438 mfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
     427static int mfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
    439428{
    440429        struct mfs_node *mnode = pfn->data;
     
    458447
    459448                if (!d_info.d_inum) {
    460                         /* This entry is not used */
     449                        /*This entry is not used*/
    461450                        continue;
    462451                }
     
    465454
    466455                if (comp_size == dentry_name_size &&
    467                     !bcmp(component, d_info.d_name, dentry_name_size)) {
    468                         /* Hit! */
     456                        !bcmp(component, d_info.d_name, dentry_name_size)) {
     457                        /*Hit!*/
    469458                        mfs_node_core_get(rfn, mnode->instance,
    470                             d_info.d_inum);
     459                                          d_info.d_inum);
    471460                        goto found;
    472461                }
     
    477466}
    478467
    479 static aoff64_t
    480 mfs_size_get(fs_node_t *node)
    481 {
     468static aoff64_t mfs_size_get(fs_node_t *node)
     469{
     470        assert(node);
     471
    482472        const struct mfs_node *mnode = node->data;
     473        assert(mnode);
     474        assert(mnode->ino_i);
     475
    483476        return mnode->ino_i->i_size;
    484477}
     
    486479static int
    487480mfs_node_get(fs_node_t **rfn, service_id_t service_id,
    488     fs_index_t index)
     481                        fs_index_t index)
    489482{
    490483        int rc;
     
    520513                assert(mnode->instance->open_nodes_cnt > 0);
    521514                mnode->instance->open_nodes_cnt--;
    522                 rc = mfs_put_inode(mnode);
     515                rc = mfs_put_inode_core(mnode);
    523516                free(mnode->ino_i);
    524517                free(mnode);
     
    530523}
    531524
    532 static int
    533 mfs_node_open(fs_node_t *fsnode)
     525static int mfs_node_open(fs_node_t *fsnode)
    534526{
    535527        /*
     
    540532}
    541533
    542 static fs_index_t
    543 mfs_index_get(fs_node_t *fsnode)
     534static fs_index_t mfs_index_get(fs_node_t *fsnode)
    544535{
    545536        struct mfs_node *mnode = fsnode->data;
     537
     538        assert(mnode->ino_i);
    546539        return mnode->ino_i->index;
    547540}
    548541
    549 static unsigned
    550 mfs_lnkcnt_get(fs_node_t *fsnode)
     542static unsigned mfs_lnkcnt_get(fs_node_t *fsnode)
    551543{
    552544        struct mfs_node *mnode = fsnode->data;
     
    563555}
    564556
    565 static int
    566 mfs_node_core_get(fs_node_t **rfn, struct mfs_instance *inst,
    567     fs_index_t index)
     557static int mfs_node_core_get(fs_node_t **rfn, struct mfs_instance *inst,
     558                             fs_index_t index)
    568559{
    569560        fs_node_t *node = NULL;
     
    637628}
    638629
    639 static bool
    640 mfs_is_directory(fs_node_t *fsnode)
     630static bool mfs_is_directory(fs_node_t *fsnode)
    641631{
    642632        const struct mfs_node *node = fsnode->data;
     
    644634}
    645635
    646 static bool
    647 mfs_is_file(fs_node_t *fsnode)
     636static bool mfs_is_file(fs_node_t *fsnode)
    648637{
    649638        struct mfs_node *node = fsnode->data;
     
    651640}
    652641
    653 static int
    654 mfs_root_get(fs_node_t **rfn, service_id_t service_id)
     642static int mfs_root_get(fs_node_t **rfn, service_id_t service_id)
    655643{
    656644        int rc = mfs_node_get(rfn, service_id, MFS_ROOT_INO);
     
    658646}
    659647
    660 static int
    661 mfs_link(fs_node_t *pfn, fs_node_t *cfn, const char *name)
     648static int mfs_link(fs_node_t *pfn, fs_node_t *cfn, const char *name)
    662649{
    663650        struct mfs_node *parent = pfn->data;
    664651        struct mfs_node *child = cfn->data;
    665652        struct mfs_sb_info *sbi = parent->instance->sbi;
    666         bool destroy_dentry = false;
    667653
    668654        mfsdebug("%s()\n", __FUNCTION__);
     
    673659        int r = mfs_insert_dentry(parent, name, child->ino_i->index);
    674660        if (r != EOK)
    675                 return r;
     661                goto exit_error;
    676662
    677663        if (S_ISDIR(child->ino_i->i_mode)) {
    678                 if (child->ino_i->i_nlinks != 1) {
    679                         /* It's not possible to hardlink directories in MFS */
    680                         destroy_dentry = true;
    681                         r = EMLINK;
    682                         goto exit;
    683                 }
    684664                r = mfs_insert_dentry(child, ".", child->ino_i->index);
    685                 if (r != EOK) {
    686                         destroy_dentry = true;
    687                         goto exit;
    688                 }
     665                if (r != EOK)
     666                        goto exit_error;
    689667
    690668                r = mfs_insert_dentry(child, "..", parent->ino_i->index);
    691                 if (r != EOK) {
    692                         destroy_dentry = true;
    693                         goto exit;
    694                 }
     669                if (r != EOK)
     670                        goto exit_error;
    695671
    696672                parent->ino_i->i_nlinks++;
     
    698674        }
    699675
    700 exit:
    701         if (destroy_dentry) {
    702                 int r2 = mfs_remove_dentry(parent, name);
    703                 if (r2 != EOK)
    704                         r = r2;
    705         } else {
    706                 child->ino_i->i_nlinks++;
    707                 child->ino_i->dirty = true;
    708         }
     676exit_error:
    709677        return r;
    710678}
     
    753721}
    754722
    755 static int
    756 mfs_has_children(bool *has_children, fs_node_t *fsnode)
     723static int mfs_has_children(bool *has_children, fs_node_t *fsnode)
    757724{
    758725        struct mfs_node *mnode = fsnode->data;
     
    775742
    776743                if (d_info.d_inum) {
    777                         /* A valid entry has been found */
     744                        /*A valid entry has been found*/
    778745                        *has_children = true;
    779746                        break;
     
    787754static int
    788755mfs_read(service_id_t service_id, fs_index_t index, aoff64_t pos,
    789     size_t *rbytes)
     756                size_t *rbytes)
    790757{
    791758        int rc;
     
    817784
    818785                if (pos < 2) {
    819                         /* Skip the first two dentries ('.' and '..') */
     786                        /*Skip the first two dentries ('.' and '..')*/
    820787                        pos = 2;
    821788                }
     
    827794
    828795                        if (d_info.d_inum) {
    829                                 /* Dentry found! */
     796                                /*Dentry found!*/
    830797                                goto found;
    831798                        }
     
    837804found:
    838805                async_data_read_finalize(callid, d_info.d_name,
    839                     str_size(d_info.d_name) + 1);
     806                                        str_size(d_info.d_name) + 1);
    840807                bytes = ((pos - spos) + 1);
    841808        } else {
     
    843810
    844811                if (pos >= (size_t) ino_i->i_size) {
    845                         /* Trying to read beyond the end of file */
     812                        /*Trying to read beyond the end of file*/
    846813                        bytes = 0;
    847814                        (void) async_data_read_finalize(callid, NULL, 0);
     
    860827
    861828                if (zone == 0) {
    862                         /* sparse file */
     829                        /*sparse file*/
    863830                        uint8_t *buf = malloc(sbi->block_size);
    864831                        if (!buf) {
     
    868835                        memset(buf, 0, sizeof(sbi->block_size));
    869836                        async_data_read_finalize(callid,
    870                             buf + pos % sbi->block_size, bytes);
     837                                                buf + pos % sbi->block_size, bytes);
    871838                        free(buf);
    872839                        goto out_success;
     
    878845
    879846                async_data_read_finalize(callid, b->data +
    880                     pos % sbi->block_size, bytes);
     847                                        pos % sbi->block_size, bytes);
    881848
    882849                rc = block_put(b);
     
    899866static int
    900867mfs_write(service_id_t service_id, fs_index_t index, aoff64_t pos,
    901     size_t *wbytes, aoff64_t *nsize)
     868                size_t *wbytes, aoff64_t *nsize)
    902869{
    903870        fs_node_t *fn;
     
    923890        struct mfs_ino_info *ino_i = mnode->ino_i;
    924891        const size_t bs = sbi->block_size;
    925         size_t bytes = min(len, bs - (pos % bs));
     892        size_t bytes = min(len, bs - pos % bs);
     893        size_t boundary = ROUND_UP(ino_i->i_size, bs);
    926894        uint32_t block;
    927895
     
    929897                flags = BLOCK_FLAGS_NOREAD;
    930898
    931         r = mfs_read_map(&block, mnode, pos);
    932         if (r != EOK)
    933                 goto out_err;
    934 
    935         if (block == 0) {
     899        if (pos < boundary) {
     900                r = mfs_read_map(&block, mnode, pos);
     901                if (r != EOK)
     902                        goto out_err;
     903
     904                if (block == 0) {
     905                        /*Writing in a sparse block*/
     906                        r = mfs_alloc_zone(mnode->instance, &block);
     907                        if (r != EOK)
     908                                goto out_err;
     909                        flags = BLOCK_FLAGS_NOREAD;
     910                }
     911        } else {
    936912                uint32_t dummy;
    937913
     
    939915                if (r != EOK)
    940916                        goto out_err;
    941                
     917
    942918                r = mfs_write_map(mnode, pos, block, &dummy);
    943919                if (r != EOK)
    944920                        goto out_err;
    945 
    946                 flags = BLOCK_FLAGS_NOREAD;
    947921        }
    948922
     
    952926                goto out_err;
    953927
    954         if (flags == BLOCK_FLAGS_NOREAD)
    955                 memset(b->data, 0, sbi->block_size);
    956 
    957         async_data_write_finalize(callid, b->data + (pos % bs), bytes);
     928        async_data_write_finalize(callid, b->data + pos % bs, bytes);
    958929        b->dirty = true;
    959930
     
    964935        }
    965936
    966         if (pos + bytes > ino_i->i_size) {
    967                 ino_i->i_size = pos + bytes;
    968                 ino_i->dirty = true;
    969         }
     937        ino_i->i_size = pos + bytes;
     938        ino_i->dirty = true;
    970939        r = mfs_node_put(fn);
    971         *nsize = ino_i->i_size;
     940        *nsize = pos + bytes;
    972941        *wbytes = bytes;
    973942        return r;
     
    991960                return ENOENT;
    992961
    993         /* Destroy the inode */
     962        /*Destroy the inode*/
    994963        return mfs_destroy_node(fn);
    995964}
     
    1010979        assert(!has_children);
    1011980
    1012         /* Free the entire inode content */
     981        /*Free the entire inode content*/
    1013982        r = mfs_inode_shrink(mnode, mnode->ino_i->i_size);
    1014983        if (r != EOK)
    1015984                goto out;
    1016985
    1017         /* Mark the inode as free in the bitmap */
     986        /*Mark the inode as free in the bitmap*/
    1018987        r = mfs_free_inode(mnode->instance, mnode->ino_i->index);
    1019988
     
    10501019mfs_instance_get(service_id_t service_id, struct mfs_instance **instance)
    10511020{
    1052         void *data;
    1053         int rc;
    1054 
    1055         rc = fs_instance_get(service_id, &data);
    1056         if (rc == EOK)
    1057                 *instance = (struct mfs_instance *) data;
    1058         else {
    1059                 mfsdebug("instance not found\n");
    1060         }
    1061 
    1062         return rc;
    1063 }
    1064 
    1065 static bool
    1066 check_magic_number(uint16_t magic, bool *native,
    1067                 mfs_version_t *version, bool *longfilenames)
     1021        struct mfs_instance *instance_ptr;
     1022
     1023        fibril_mutex_lock(&inst_list_mutex);
     1024
     1025        if (list_empty(&inst_list)) {
     1026                fibril_mutex_unlock(&inst_list_mutex);
     1027                return EINVAL;
     1028        }
     1029
     1030        list_foreach(inst_list, link) {
     1031                instance_ptr = list_get_instance(link, struct mfs_instance,
     1032                                                 link);
     1033
     1034                if (instance_ptr->service_id == service_id) {
     1035                        *instance = instance_ptr;
     1036                        fibril_mutex_unlock(&inst_list_mutex);
     1037                        return EOK;
     1038                }
     1039        }
     1040
     1041        mfsdebug("Instance not found\n");
     1042
     1043        fibril_mutex_unlock(&inst_list_mutex);
     1044        return EINVAL;
     1045}
     1046
     1047static bool check_magic_number(uint16_t magic, bool *native,
     1048                               mfs_version_t *version, bool *longfilenames)
    10681049{
    10691050        bool rc = true;
     
    10931074}
    10941075
    1095 /** Filesystem sanity check
    1096  *
    1097  * @param Pointer to the MFS superblock.
    1098  *
    1099  * @return EOK on success, ENOTSUP otherwise.
    1100  */
    1101 static int
    1102 mfs_check_sanity(struct mfs_sb_info *sbi)
    1103 {
    1104         if (!is_power_of_two(sbi->block_size) ||
    1105             sbi->block_size < MFS_MIN_BLOCKSIZE ||
    1106             sbi->block_size > MFS_MAX_BLOCKSIZE)
    1107                 return ENOTSUP;
    1108         else if (sbi->ibmap_blocks == 0 || sbi->zbmap_blocks == 0)
    1109                 return ENOTSUP;
    1110         else if (sbi->ninodes == 0 || sbi->nzones == 0)
    1111                 return ENOTSUP;
    1112         else if (sbi->firstdatazone == 0)
    1113                 return ENOTSUP;
    1114 
    1115         return EOK;
    1116 }
    1117 
    11181076static int
    11191077mfs_close(service_id_t service_id, fs_index_t index)
     
    11361094
    11371095        return mfs_node_put(fn);
    1138 }
    1139 
    1140 /** Check if a given number is a power of two.
    1141  *
    1142  * @param n     The number to check.
    1143  *
    1144  * @return      true if it is a power of two, false otherwise.
    1145  */
    1146 static bool
    1147 is_power_of_two(uint32_t n)
    1148 {
    1149         if (n == 0)
    1150                 return false;
    1151 
    1152         return (n & (n - 1)) == 0;
    11531096}
    11541097
Note: See TracChangeset for help on using the changeset viewer.