Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/fs/cdfs/cdfs_ops.c

    rfeeac0d r3abf70c7  
    3939#include "cdfs_ops.h"
    4040#include <stdbool.h>
     41#include <adt/list.h>
    4142#include <adt/hash_table.h>
    4243#include <adt/hash.h>
     
    4748#include <errno.h>
    4849#include <block.h>
     50#include <scsi/mmc.h>
    4951#include <str.h>
    5052#include <byteorder.h>
     
    6567
    6668#define CDFS_STANDARD_IDENT  "CD001"
     69
     70enum {
     71        CDFS_NAME_CURDIR = '\x00',
     72        CDFS_NAME_PARENTDIR = '\x01'
     73};
    6774
    6875typedef enum {
     
    126133
    127134typedef struct {
    128         uint8_t res0;
     135        uint8_t flags; /* reserved in primary */
    129136       
    130137        uint8_t system_ident[32];
     
    134141        uint32_t_lb lba_size;
    135142       
    136         uint8_t res2[32];
     143        uint8_t esc_seq[32]; /* reserved in primary */
    137144        uint16_t_lb set_size;
    138145        uint16_t_lb sequence_nr;
     
    164171       
    165172        uint8_t fs_version;
    166 } __attribute__((packed)) cdfs_vol_desc_primary_t;
     173} __attribute__((packed)) cdfs_vol_desc_prisec_t;
    167174
    168175typedef struct {
     
    172179        union {
    173180                cdfs_vol_desc_boot_t boot;
    174                 cdfs_vol_desc_primary_t primary;
     181                cdfs_vol_desc_prisec_t prisec;
    175182        } data;
    176183} __attribute__((packed)) cdfs_vol_desc_t;
     184
     185typedef enum {
     186        /** ASCII character set / encoding (base ISO 9660) */
     187        enc_ascii,
     188        /** UCS-2 character set / encoding (Joliet) */
     189        enc_ucs2
     190} cdfs_enc_t;
    177191
    178192typedef enum {
     
    191205
    192206typedef struct {
     207        link_t link;              /**< Link to list of all instances */
     208        service_id_t service_id;  /**< Service ID of block device */
     209        cdfs_enc_t enc;           /**< Filesystem string encoding */
     210} cdfs_t;
     211
     212typedef struct {
    193213        fs_node_t *fs_node;       /**< FS node */
    194214        fs_index_t index;         /**< Node index */
    195         service_id_t service_id;  /**< Service ID of block device */
     215        cdfs_t *fs;               /**< File system */
    196216       
    197217        ht_link_t nh_link;        /**< Nodes hash table link */
     
    207227} cdfs_node_t;
    208228
     229/** String encoding */
     230enum {
     231        /** ASCII - standard ISO 9660 */
     232        ucs2_esc_seq_no = 3,
     233        /** USC-2 - Joliet */
     234        ucs2_esc_seq_len = 3
     235};
     236
     237/** Joliet SVD UCS-2 escape sequences */
     238static uint8_t ucs2_esc_seq[ucs2_esc_seq_no][ucs2_esc_seq_len] = {
     239        { 0x25, 0x2f, 0x40 },
     240        { 0x25, 0x2f, 0x43 },
     241        { 0x25, 0x2f, 0x45 }
     242};
     243
     244/** List of all instances */
     245static LIST_INITIALIZE(cdfs_instances);
     246
    209247/** Shared index of nodes */
    210248static fs_index_t cdfs_index = 1;
     
    234272{
    235273        cdfs_node_t *node = hash_table_get_inst(item, cdfs_node_t, nh_link);
    236         return hash_combine(node->service_id, node->index);
     274        return hash_combine(node->fs->service_id, node->index);
    237275}
    238276
     
    242280        ht_key_t *key = (ht_key_t*)k;
    243281       
    244         return key->service_id == node->service_id && key->index == node->index;
     282        return key->service_id == node->fs->service_id && key->index == node->index;
    245283}
    246284
     
    249287        cdfs_node_t *node = hash_table_get_inst(item, cdfs_node_t, nh_link);
    250288       
    251         assert(node->type == CDFS_DIRECTORY);
    252        
    253         link_t *link;
    254         while ((link = list_first(&node->cs_list)) != NULL) {
    255                 cdfs_dentry_t *dentry = list_get_instance(link, cdfs_dentry_t, link);
    256                 list_remove(&dentry->link);
    257                 free(dentry);
     289        if (node->type == CDFS_DIRECTORY) {
     290                link_t *link;
     291                while ((link = list_first(&node->cs_list)) != NULL) {
     292                        cdfs_dentry_t *dentry = list_get_instance(link, cdfs_dentry_t, link);
     293                        list_remove(&dentry->link);
     294                        free(dentry);
     295                }
    258296        }
    259297       
     
    300338        node->fs_node = NULL;
    301339        node->index = 0;
    302         node->service_id = 0;
     340        node->fs = NULL;
    303341        node->type = CDFS_NONE;
    304342        node->lnkcnt = 0;
     
    311349}
    312350
    313 static int create_node(fs_node_t **rfn, service_id_t service_id, int lflag,
     351static int create_node(fs_node_t **rfn, cdfs_t *fs, int lflag,
    314352    fs_index_t index)
    315353{
     
    332370       
    333371        fs_node_t *rootfn;
    334         int rc = cdfs_root_get(&rootfn, service_id);
     372        int rc = cdfs_root_get(&rootfn, fs->service_id);
    335373       
    336374        assert(rc == EOK);
     
    341379                node->index = index;
    342380       
    343         node->service_id = service_id;
     381        node->fs = fs;
    344382       
    345383        if (lflag & L_DIRECTORY)
     
    391429}
    392430
    393 static bool cdfs_readdir(service_id_t service_id, fs_node_t *fs_node)
     431/** Decode CDFS string.
     432 *
     433 * @param data  Pointer to string data
     434 * @param dsize Size of data in bytes
     435 * @param enc   String encoding
     436 * @return      Decoded string
     437 */
     438static char *cdfs_decode_str(void *data, size_t dsize, cdfs_enc_t enc)
     439{
     440        int rc;
     441        char *str;
     442        uint16_t *buf;
     443       
     444        switch (enc) {
     445        case enc_ascii:
     446                str = malloc(dsize + 1);
     447                if (str == NULL)
     448                        return NULL;
     449                memcpy(str, data, dsize);
     450                str[dsize] = '\0';
     451                break;
     452        case enc_ucs2:
     453                buf = calloc(dsize + 2, 1);
     454                if (buf == NULL)
     455                        return NULL;
     456               
     457                size_t i;
     458                for (i = 0; i < dsize / sizeof(uint16_t); i++) {
     459                        buf[i] = uint16_t_be2host(((uint16_t *)data)[i]);
     460                }
     461               
     462                size_t dstr_size = dsize / sizeof(uint16_t) * 4 + 1;
     463                str = malloc(dstr_size);
     464                if (str == NULL)
     465                        return NULL;
     466               
     467                rc = utf16_to_str(str, dstr_size, buf);
     468                free(buf);
     469               
     470                if (rc != EOK)
     471                        return NULL;
     472                break;
     473        default:
     474                assert(false);
     475                str = NULL;
     476        }
     477       
     478        return str;
     479}
     480
     481/** Decode file name.
     482 *
     483 * @param data  File name buffer
     484 * @param dsize Fine name buffer size
     485 * @param dtype Directory entry type
     486 * @return      Decoded file name (allocated string)
     487 */
     488static char *cdfs_decode_name(void *data, size_t dsize, cdfs_enc_t enc,
     489    cdfs_dentry_type_t dtype)
     490{
     491        char *name;
     492        char *dot;
     493        char *scolon;
     494       
     495        name = cdfs_decode_str(data, dsize, enc);
     496        if (name == NULL)
     497                return NULL;
     498       
     499        if (dtype == CDFS_DIRECTORY)
     500                return name;
     501       
     502        dot = str_chr(name, '.');
     503       
     504        if (dot != NULL) {
     505                scolon = str_chr(dot, ';');
     506                if (scolon != NULL) {
     507                        /* Trim version part */
     508                        *scolon = '\0';
     509                }
     510       
     511                /* If the extension is an empty string, trim the dot separator. */
     512                if (dot[1] == '\0')
     513                        *dot = '\0';
     514        }
     515       
     516        return name;
     517}
     518
     519static bool cdfs_readdir(cdfs_t *fs, fs_node_t *fs_node)
    394520{
    395521        cdfs_node_t *node = CDFS_NODE(fs_node);
     
    405531        for (uint32_t i = 0; i < blocks; i++) {
    406532                block_t *block;
    407                 int rc = block_get(&block, service_id, node->lba + i, BLOCK_FLAGS_NONE);
     533                int rc = block_get(&block, fs->service_id, node->lba + i, BLOCK_FLAGS_NONE);
    408534                if (rc != EOK)
    409535                        return false;
    410536               
    411                 cdfs_dir_t *dir = (cdfs_dir_t *) block->data;
    412                
    413                 // FIXME: skip '.' and '..'
    414                
    415                 for (size_t offset = 0;
    416                     (dir->length != 0) && (offset < BLOCK_SIZE);
     537                cdfs_dir_t *dir;
     538               
     539                for (size_t offset = 0; offset < BLOCK_SIZE;
    417540                    offset += dir->length) {
    418541                        dir = (cdfs_dir_t *) (block->data + offset);
     542                        if (dir->length == 0)
     543                                break;
     544                        if (offset + dir->length > BLOCK_SIZE) {
     545                                /* XXX Incorrect FS structure */
     546                                break;
     547                        }
    419548                       
    420549                        cdfs_dentry_type_t dentry_type;
     
    424553                                dentry_type = CDFS_FILE;
    425554                       
     555                        /* Skip special entries */
     556                       
     557                        if (dir->name_length == 1 &&
     558                            dir->name[0] == CDFS_NAME_CURDIR)
     559                                continue;
     560                        if (dir->name_length == 1 &&
     561                            dir->name[0] == CDFS_NAME_PARENTDIR)
     562                                continue;
     563                       
    426564                        // FIXME: hack - indexing by dentry byte offset on disc
    427565                       
    428566                        fs_node_t *fn;
    429                         int rc = create_node(&fn, service_id, dentry_type,
     567                        int rc = create_node(&fn, fs, dentry_type,
    430568                            (node->lba + i) * BLOCK_SIZE + offset);
    431569                        if ((rc != EOK) || (fn == NULL))
     
    436574                        cur->size = uint32_lb(dir->size);
    437575                       
    438                         char *name = (char *) malloc(dir->name_length + 1);
     576                        char *name = cdfs_decode_name(dir->name,
     577                            dir->name_length, node->fs->enc, dentry_type);
    439578                        if (name == NULL)
    440579                                return false;
    441                        
    442                         memcpy(name, dir->name, dir->name_length);
    443                         name[dir->name_length] = 0;
    444580                       
    445581                        // FIXME: check return value
     
    459595}
    460596
    461 static fs_node_t *get_uncached_node(service_id_t service_id, fs_index_t index)
     597static fs_node_t *get_uncached_node(cdfs_t *fs, fs_index_t index)
    462598{
    463599        cdfs_lba_t lba = index / BLOCK_SIZE;
     
    465601       
    466602        block_t *block;
    467         int rc = block_get(&block, service_id, lba, BLOCK_FLAGS_NONE);
     603        int rc = block_get(&block, fs->service_id, lba, BLOCK_FLAGS_NONE);
    468604        if (rc != EOK)
    469605                return NULL;
     
    478614       
    479615        fs_node_t *fn;
    480         rc = create_node(&fn, service_id, dentry_type, index);
     616        rc = create_node(&fn, fs, dentry_type, index);
    481617        if ((rc != EOK) || (fn == NULL))
    482618                return NULL;
     
    494630}
    495631
    496 static fs_node_t *get_cached_node(service_id_t service_id, fs_index_t index)
     632static fs_node_t *get_cached_node(cdfs_t *fs, fs_index_t index)
    497633{
    498634        ht_key_t key = {
    499635                .index = index,
    500                 .service_id = service_id
     636                .service_id = fs->service_id
    501637        };
    502638       
     
    508644        }
    509645       
    510         return get_uncached_node(service_id, index);
     646        return get_uncached_node(fs, index);
    511647}
    512648
     
    516652       
    517653        if (!parent->processed) {
    518                 int rc = cdfs_readdir(parent->service_id, pfn);
     654                int rc = cdfs_readdir(parent->fs, pfn);
    519655                if (rc != EOK)
    520656                        return rc;
     
    523659        list_foreach(parent->cs_list, link, cdfs_dentry_t, dentry) {
    524660                if (str_cmp(dentry->name, component) == 0) {
    525                         *fn = get_cached_node(parent->service_id, dentry->index);
     661                        *fn = get_cached_node(parent->fs, dentry->index);
    526662                        return EOK;
    527663                }
     
    537673       
    538674        if (!node->processed)
    539                 cdfs_readdir(node->service_id, fn);
     675                cdfs_readdir(node->fs, fn);
    540676       
    541677        node->opened++;
     
    578714       
    579715        if ((node->type == CDFS_DIRECTORY) && (!node->processed))
    580                 cdfs_readdir(node->service_id, fn);
     716                cdfs_readdir(node->fs, fn);
    581717       
    582718        *has_children = !list_empty(&node->cs_list);
     
    617753{
    618754        return 0;
     755}
     756
     757static int cdfs_size_block(service_id_t service_id, uint32_t *size)
     758{
     759        *size = BLOCK_SIZE;
     760       
     761        return EOK;
     762}
     763
     764static int cdfs_total_block_count(service_id_t service_id, uint64_t *count)
     765{
     766        *count = 0;
     767       
     768        return EOK;
     769}
     770
     771static int cdfs_free_block_count(service_id_t service_id, uint64_t *count)
     772{
     773        *count = 0;
     774       
     775        return EOK;
    619776}
    620777
     
    635792        .is_directory = cdfs_is_directory,
    636793        .is_file = cdfs_is_file,
    637         .service_get = cdfs_service_get
     794        .service_get = cdfs_service_get,
     795        .size_block = cdfs_size_block,
     796        .total_block_count = cdfs_total_block_count,
     797        .free_block_count = cdfs_free_block_count
    638798};
    639799
    640 static bool iso_readfs(service_id_t service_id, fs_node_t *rfn,
     800/** Verify that escape sequence corresonds to one of the allowed encoding
     801 * escape sequences allowed for Joliet. */
     802static int cdfs_verify_joliet_esc_seq(uint8_t *seq)
     803{
     804        size_t i, j, k;
     805        bool match;
     806       
     807        i = 0;
     808        while (i + ucs2_esc_seq_len <= 32) {
     809                if (seq[i] == 0)
     810                        break;
     811               
     812                for (j = 0; j < ucs2_esc_seq_no; j++) {
     813                        match = true;
     814                        for (k = 0; k < ucs2_esc_seq_len; k++)
     815                                if (seq[i + k] != ucs2_esc_seq[j][k])
     816                                        match = false;
     817                        if (match) {
     818                                break;
     819                        }
     820                }
     821               
     822                if (!match)
     823                        return EINVAL;
     824               
     825                i += ucs2_esc_seq_len;
     826        }
     827       
     828        while (i < 32) {
     829                if (seq[i] != 0)
     830                        return EINVAL;
     831                ++i;
     832        }
     833       
     834        return EOK;
     835}
     836
     837/** Find Joliet supplementary volume descriptor.
     838 *
     839 * @param sid           Block device service ID
     840 * @param altroot       First filesystem block
     841 * @param rlba          Place to store LBA of root dir
     842 * @param rsize         Place to store size of root dir
     843 * @return              EOK if found, ENOENT if not
     844 */
     845static int cdfs_find_joliet_svd(service_id_t sid, cdfs_lba_t altroot,
     846    uint32_t *rlba, uint32_t *rsize)
     847{
     848        cdfs_lba_t bi;
     849
     850        for (bi = altroot + 17; ; bi++) {
     851                block_t *block;
     852                int rc = block_get(&block, sid, bi, BLOCK_FLAGS_NONE);
     853                if (rc != EOK)
     854                        break;
     855               
     856                cdfs_vol_desc_t *vol_desc = (cdfs_vol_desc_t *) block->data;
     857               
     858                if (vol_desc->type == VOL_DESC_SET_TERMINATOR) {
     859                        block_put(block);
     860                        break;
     861                }
     862               
     863                if ((vol_desc->type != VOL_DESC_SUPPLEMENTARY) ||
     864                    (memcmp(vol_desc->standard_ident, CDFS_STANDARD_IDENT, 5) != 0) ||
     865                    (vol_desc->version != 1)) {
     866                        block_put(block);
     867                        continue;
     868                }
     869               
     870                uint16_t set_size = uint16_lb(vol_desc->data.prisec.set_size);
     871                if (set_size > 1) {
     872                        /*
     873                         * Technically, we don't support multi-disc sets.
     874                         * But one can encounter erroneously mastered
     875                         * images in the wild and it might actually work
     876                         * for the first disc in the set.
     877                         */
     878                }
     879               
     880                uint16_t sequence_nr = uint16_lb(vol_desc->data.prisec.sequence_nr);
     881                if (sequence_nr != 1) {
     882                        /*
     883                         * We only support the first disc
     884                         * in multi-disc sets.
     885                         */
     886                        block_put(block);
     887                        continue;
     888                }
     889               
     890                uint16_t block_size = uint16_lb(vol_desc->data.prisec.block_size);
     891                if (block_size != BLOCK_SIZE) {
     892                        block_put(block);
     893                        continue;
     894                }
     895               
     896                rc = cdfs_verify_joliet_esc_seq(vol_desc->data.prisec.esc_seq);
     897                if (rc != EOK)
     898                        continue;
     899                *rlba = uint32_lb(vol_desc->data.prisec.root_dir.lba);
     900                *rsize = uint32_lb(vol_desc->data.prisec.root_dir.size);
     901                block_put(block);
     902                return EOK;
     903        }
     904       
     905        return ENOENT;
     906}
     907
     908static bool iso_readfs(cdfs_t *fs, fs_node_t *rfn,
    641909    cdfs_lba_t altroot)
    642910{
    643911        /* First 16 blocks of isofs are empty */
    644912        block_t *block;
    645         int rc = block_get(&block, service_id, altroot + 16, BLOCK_FLAGS_NONE);
     913        int rc = block_get(&block, fs->service_id, altroot + 16, BLOCK_FLAGS_NONE);
    646914        if (rc != EOK)
    647915                return false;
     
    660928        }
    661929       
    662         uint16_t set_size = uint16_lb(vol_desc->data.primary.set_size);
     930        uint16_t set_size = uint16_lb(vol_desc->data.prisec.set_size);
    663931        if (set_size > 1) {
    664932                /*
     
    670938        }
    671939       
    672         uint16_t sequence_nr = uint16_lb(vol_desc->data.primary.sequence_nr);
     940        uint16_t sequence_nr = uint16_lb(vol_desc->data.prisec.sequence_nr);
    673941        if (sequence_nr != 1) {
    674942                /*
     
    680948        }
    681949       
    682         uint16_t block_size = uint16_lb(vol_desc->data.primary.block_size);
     950        uint16_t block_size = uint16_lb(vol_desc->data.prisec.block_size);
    683951        if (block_size != BLOCK_SIZE) {
    684952                block_put(block);
     
    689957       
    690958        cdfs_node_t *node = CDFS_NODE(rfn);
    691         node->lba = uint32_lb(vol_desc->data.primary.root_dir.lba);
    692         node->size = uint32_lb(vol_desc->data.primary.root_dir.size);
    693        
    694         if (!cdfs_readdir(service_id, rfn)) {
     959       
     960        /* Search for Joliet SVD */
     961       
     962        uint32_t jrlba;
     963        uint32_t jrsize;
     964       
     965        rc = cdfs_find_joliet_svd(fs->service_id, altroot, &jrlba, &jrsize);
     966        if (rc == EOK) {
     967                /* Found */
     968                node->lba = jrlba;
     969                node->size = jrsize;
     970                fs->enc = enc_ucs2;
     971        } else {
     972                node->lba = uint32_lb(vol_desc->data.prisec.root_dir.lba);
     973                node->size = uint32_lb(vol_desc->data.prisec.root_dir.size);
     974                fs->enc = enc_ascii;
     975        }
     976       
     977        if (!cdfs_readdir(fs, rfn)) {
    695978                block_put(block);
    696979                return false;
     
    704987 *
    705988 */
    706 static bool cdfs_instance_init(service_id_t service_id, cdfs_lba_t altroot)
    707 {
     989static cdfs_t *cdfs_fs_create(service_id_t sid, cdfs_lba_t altroot)
     990{
     991        cdfs_t *fs = NULL;
     992        fs_node_t *rfn = NULL;
     993
     994        fs = calloc(1, sizeof(cdfs_t));
     995        if (fs == NULL)
     996                goto error;
     997       
     998        fs->service_id = sid;
     999       
    7081000        /* Create root node */
    709         fs_node_t *rfn;
    710         int rc = create_node(&rfn, service_id, L_DIRECTORY, cdfs_index++);
     1001        int rc = create_node(&rfn, fs, L_DIRECTORY, cdfs_index++);
    7111002       
    7121003        if ((rc != EOK) || (!rfn))
    713                 return false;
     1004                goto error;
    7141005       
    7151006        /* FS root is not linked */
     
    7191010       
    7201011        /* Check if there is cdfs in given session */
    721         if (!iso_readfs(service_id, rfn, altroot)) {
    722                 // XXX destroy node
    723                 return false;
    724         }
    725        
    726         return true;
     1012        if (!iso_readfs(fs, rfn, altroot))
     1013                goto error;
     1014       
     1015        list_append(&fs->link, &cdfs_instances);
     1016        return fs;
     1017error:
     1018        // XXX destroy node
     1019        free(fs);
     1020        return NULL;
    7271021}
    7281022
     
    7421036                        altroot = 0;
    7431037        } else {
    744                 /* Read TOC and find the last session */
    745                 toc_block_t *toc = block_get_toc(service_id, 1);
    746                 if ((toc != NULL) && (uint16_t_be2host(toc->size) == 10)) {
    747                         altroot = uint32_t_be2host(toc->first_lba);
    748                         free(toc);
    749                 }
     1038                /*
     1039                 * Read TOC multisession information and get the start address
     1040                 * of the first track in the last session
     1041                 */
     1042                scsi_toc_multisess_data_t toc;
     1043
     1044                rc = block_read_toc(service_id, 1, &toc, sizeof(toc));
     1045                if (rc == EOK && (uint16_t_be2host(toc.toc_len) == 10))
     1046                        altroot = uint32_t_be2host(toc.ftrack_lsess.start_addr);
    7501047        }
    7511048       
     
    7681065        }
    7691066       
    770         /* Initialize cdfs instance */
    771         if (!cdfs_instance_init(service_id, altroot)) {
     1067        /* Create cdfs instance */
     1068        if (cdfs_fs_create(service_id, altroot) == NULL) {
    7721069                block_cache_fini(service_id);
    7731070                block_fini(service_id);
     
    7921089        cdfs_node_t *node = hash_table_get_inst(item, cdfs_node_t, nh_link);
    7931090       
    794         if (node->service_id == service_id) {
     1091        if (node->fs->service_id == service_id) {
    7951092                hash_table_remove_item(&nodes, &node->nh_link);
    7961093        }
     
    7991096}
    8001097
    801 static void cdfs_instance_done(service_id_t service_id)
    802 {
    803         hash_table_apply(&nodes, rm_service_id_nodes, &service_id);
    804         block_cache_fini(service_id);
    805         block_fini(service_id);
     1098static void cdfs_fs_destroy(cdfs_t *fs)
     1099{
     1100        list_remove(&fs->link);
     1101        hash_table_apply(&nodes, rm_service_id_nodes, &fs->service_id);
     1102        block_cache_fini(fs->service_id);
     1103        block_fini(fs->service_id);
     1104        free(fs);
     1105}
     1106
     1107static cdfs_t *cdfs_find_by_sid(service_id_t service_id)
     1108{
     1109        list_foreach(cdfs_instances, link, cdfs_t, fs) {
     1110                if (fs->service_id == service_id)
     1111                        return fs;
     1112        }
     1113       
     1114        return NULL;
    8061115}
    8071116
    8081117static int cdfs_unmounted(service_id_t service_id)
    8091118{
    810         cdfs_instance_done(service_id);
     1119        cdfs_t *fs;
     1120
     1121        fs = cdfs_find_by_sid(service_id);
     1122        if (fs == NULL)
     1123                return ENOENT;
     1124       
     1125        cdfs_fs_destroy(fs);
    8111126        return EOK;
    8121127}
     
    8281143       
    8291144        if (!node->processed) {
    830                 int rc = cdfs_readdir(service_id, FS_NODE(node));
     1145                int rc = cdfs_readdir(node->fs, FS_NODE(node));
    8311146                if (rc != EOK)
    8321147                        return rc;
     
    9111226        /* Some nodes were requested to be removed from the cache. */
    9121227        if (0 < *premove_cnt) {
    913                 cdfs_node_t *node =     hash_table_get_inst(item, cdfs_node_t, nh_link);
     1228                cdfs_node_t *node = hash_table_get_inst(item, cdfs_node_t, nh_link);
    9141229
    9151230                if (!node->opened) {
Note: See TracChangeset for help on using the changeset viewer.