Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 9104bb5 in mainline


Ignore:
Timestamp:
2012-03-20T20:22:19Z (10 years ago)
Author:
Frantisek Princ <frantisek.princ@…>
Branches:
lfn, master
Children:
a4419e7
Parents:
cd581120
Message:

changes according to reading inode data with extent

Location:
uspace
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/ext4/libext4_balloc.c

    rcd581120 r9104bb5  
    193193        if (inode_block_count > 0) {
    194194                // TODO check retval
    195                 ext4_filesystem_get_inode_data_block_index(fs, inode_ref->inode, inode_block_count - 1, &goal);
     195                ext4_filesystem_get_inode_data_block_index(fs, inode_ref, inode_block_count - 1, &goal);
    196196
    197197                // TODO
  • uspace/lib/ext4/libext4_directory.c

    rcd581120 r9104bb5  
    187187                uint32_t next_block_phys_idx;
    188188                rc = ext4_filesystem_get_inode_data_block_index(it->fs,
    189                     it->inode_ref->inode, next_block_idx, &next_block_phys_idx);
     189                    it->inode_ref, next_block_idx, &next_block_phys_idx);
    190190                if (rc != EOK) {
    191191                        return rc;
     
    356356        for (iblock = 0; iblock < total_blocks; ++iblock) {
    357357
    358                 rc = ext4_filesystem_get_inode_data_block_index(fs, parent->inode, iblock, &fblock);
     358                rc = ext4_filesystem_get_inode_data_block_index(fs, parent, iblock, &fblock);
    359359                if (rc != EOK) {
    360360                        return rc;
     
    443443        for (iblock = 0; iblock < total_blocks; ++iblock) {
    444444
    445                 rc = ext4_filesystem_get_inode_data_block_index(fs, parent->inode, iblock, &fblock);
     445                rc = ext4_filesystem_get_inode_data_block_index(fs, parent, iblock, &fblock);
    446446                if (rc != EOK) {
    447447                        return rc;
  • uspace/lib/ext4/libext4_directory_index.c

    rcd581120 r9104bb5  
    189189
    190190static int ext4_directory_dx_get_leaf(ext4_hash_info_t *hinfo,
    191                 ext4_filesystem_t *fs, ext4_inode_t *inode, block_t *root_block,
     191                ext4_filesystem_t *fs, ext4_inode_ref_t *inode_ref, block_t *root_block,
    192192                ext4_directory_dx_block_t **dx_block, ext4_directory_dx_block_t *dx_blocks)
    193193{
     
    239239
    240240        uint32_t fblock;
    241         rc = ext4_filesystem_get_inode_data_block_index(fs, inode, next_block, &fblock);
     241        rc = ext4_filesystem_get_inode_data_block_index(fs, inode_ref, next_block, &fblock);
    242242        if (rc != EOK) {
    243243                return rc;
     
    270270
    271271
    272 static int ext4_directory_dx_next_block(ext4_filesystem_t *fs, ext4_inode_t *inode, uint32_t hash,
     272static int ext4_directory_dx_next_block(ext4_filesystem_t *fs,
     273                ext4_inode_ref_t *inode_ref, uint32_t hash,
    273274                ext4_directory_dx_block_t *handle, ext4_directory_dx_block_t *handles)
    274275{
     
    309310        uint32_t block_idx = ext4_directory_dx_entry_get_block(p->position);
    310311        uint32_t block_addr;
    311         rc = ext4_filesystem_get_inode_data_block_index(fs, inode, block_idx, &block_addr);
     312        rc = ext4_filesystem_get_inode_data_block_index(fs, inode_ref, block_idx, &block_addr);
    312313        if (rc != EOK) {
    313314                return rc;
     
    339340        // get direct block 0 (index root)
    340341        uint32_t root_block_addr;
    341         rc = ext4_filesystem_get_inode_data_block_index(fs, inode_ref->inode, 0, &root_block_addr);
     342        rc = ext4_filesystem_get_inode_data_block_index(fs, inode_ref, 0, &root_block_addr);
    342343        if (rc != EOK) {
    343344                return rc;
     
    360361        ext4_directory_dx_block_t dx_blocks[2];
    361362        ext4_directory_dx_block_t *dx_block, *tmp;
    362         rc = ext4_directory_dx_get_leaf(&hinfo, fs, inode_ref->inode, root_block, &dx_block, dx_blocks);
     363        rc = ext4_directory_dx_get_leaf(&hinfo, fs, inode_ref, root_block, &dx_block, dx_blocks);
    363364        if (rc != EOK) {
    364365                block_put(root_block);
     
    371372                uint32_t leaf_block_idx = ext4_directory_dx_entry_get_block(dx_block->position);
    372373                uint32_t leaf_block_addr;
    373         rc = ext4_filesystem_get_inode_data_block_index(fs, inode_ref->inode, leaf_block_idx, &leaf_block_addr);
     374        rc = ext4_filesystem_get_inode_data_block_index(fs, inode_ref, leaf_block_idx, &leaf_block_addr);
    374375        if (rc != EOK) {
    375376                goto cleanup;
     
    399400                }
    400401
    401                 rc = ext4_directory_dx_next_block(fs, inode_ref->inode, hinfo.hash, dx_block, &dx_blocks[0]);
     402                rc = ext4_directory_dx_next_block(fs, inode_ref, hinfo.hash, dx_block, &dx_blocks[0]);
    402403                if (rc < 0) {
    403404                        goto cleanup;
     
    747748        // get direct block 0 (index root)
    748749        uint32_t root_block_addr;
    749         rc = ext4_filesystem_get_inode_data_block_index(fs, parent->inode, 0, &root_block_addr);
     750        rc = ext4_filesystem_get_inode_data_block_index(fs, parent, 0, &root_block_addr);
    750751        if (rc != EOK) {
    751752                return rc;
     
    769770        ext4_directory_dx_block_t dx_blocks[2];
    770771        ext4_directory_dx_block_t *dx_block, *dx_it;
    771         rc = ext4_directory_dx_get_leaf(&hinfo, fs, parent->inode, root_block, &dx_block, dx_blocks);
     772        rc = ext4_directory_dx_get_leaf(&hinfo, fs, parent, root_block, &dx_block, dx_blocks);
    772773        if (rc != EOK) {
    773774                rc = EXT4_ERR_BAD_DX_DIR;
     
    779780        uint32_t leaf_block_idx = ext4_directory_dx_entry_get_block(dx_block->position);
    780781        uint32_t leaf_block_addr;
    781         rc = ext4_filesystem_get_inode_data_block_index(fs, parent->inode, leaf_block_idx, &leaf_block_addr);
     782        rc = ext4_filesystem_get_inode_data_block_index(fs, parent, leaf_block_idx, &leaf_block_addr);
    782783        if (rc != EOK) {
    783784                goto release_index;
  • uspace/lib/ext4/libext4_extent.c

    rcd581120 r9104bb5  
    149149}
    150150
    151 static void ext4_extent_binsearch_idx(ext4_extent_path_t *path, uint32_t iblock)
    152 {
    153         ext4_extent_header_t *header = path->header;
    154         ext4_extent_index_t *r, *l, *m;
    155 
    156         uint16_t entries_count = ext4_extent_header_get_entries_count(header);
    157         l = EXT4_EXTENT_FIRST_INDEX(header) + 1;
    158         r = l + entries_count - 1;
    159 
    160         while (l <= r) {
    161                 m = l + (r - l) / 2;
    162                 uint32_t block = ext4_extent_index_get_first_block(m);
    163                 if (iblock < block) {
    164                                 r = m - 1;
    165                 } else {
    166                                 l = m + 1;
     151//static void ext4_extent_binsearch_idx(ext4_extent_path_t *path, uint32_t iblock)
     152//{
     153//      ext4_extent_header_t *header = path->header;
     154//      ext4_extent_index_t *r, *l, *m;
     155//
     156//      uint16_t entries_count = ext4_extent_header_get_entries_count(header);
     157//      l = EXT4_EXTENT_FIRST_INDEX(header) + 1;
     158//      r = l + entries_count - 1;
     159//
     160//      while (l <= r) {
     161//              m = l + (r - l) / 2;
     162//              uint32_t block = ext4_extent_index_get_first_block(m);
     163//              if (iblock < block) {
     164//                              r = m - 1;
     165//              } else {
     166//                              l = m + 1;
     167//              }
     168//      }
     169//
     170//      path->index = l - 1;
     171//}
     172//
     173//static void ext4_extent_binsearch(ext4_extent_path_t *path, uint32_t iblock)
     174//{
     175//      ext4_extent_header_t *header = path->header;
     176//      ext4_extent_t *r, *l, *m;
     177//
     178//      uint16_t entries_count = ext4_extent_header_get_entries_count(header);
     179//
     180//      if (entries_count == 0) {
     181//              // this leaf is empty
     182//              return;
     183//      }
     184//
     185//      l = EXT4_EXTENT_FIRST(header) + 1;
     186//      r = l + entries_count - 1;
     187//
     188//      while (l <= r) {
     189//              m = l + (r - l) / 2;
     190//              uint32_t block = ext4_extent_get_first_block(m);
     191//              if (iblock < block) {
     192//                              r = m - 1;
     193//              } else {
     194//                              l = m + 1;
     195//              }
     196//      }
     197//
     198//      path->extent = l - 1;
     199//
     200//}
     201
     202static int ext4_extent_find_extent(ext4_filesystem_t *fs, ext4_inode_ref_t *inode_ref, uint32_t iblock, ext4_extent_t **ret_extent)
     203{
     204        int rc;
     205
     206        block_t* block = NULL;
     207
     208        ext4_extent_header_t *header = ext4_inode_get_extent_header(inode_ref->inode);
     209        while (ext4_extent_header_get_depth(header) != 0) {
     210
     211                ext4_extent_index_t *extent_index = EXT4_EXTENT_FIRST_INDEX(header);
     212
     213                for (uint16_t i = 0; i < ext4_extent_header_get_entries_count(header); ++i) {
     214                        if (iblock >= ext4_extent_index_get_first_block(extent_index)) {
     215
     216                                uint64_t child = ext4_extent_index_get_leaf(extent_index);
     217
     218                                if (block != NULL) {
     219                                        block_put(block);
     220                                }
     221
     222                                rc = block_get(&block, fs->device, child, BLOCK_FLAGS_NONE);
     223                                if (rc != EOK) {
     224                                        return rc;
     225                                }
     226
     227                                header = (ext4_extent_header_t *)block->data;
     228                                break;
     229                        }
    167230                }
    168231        }
    169232
    170         path->index = l - 1;
    171 }
    172 
    173 static void ext4_extent_binsearch(ext4_extent_path_t *path, uint32_t iblock)
    174 {
    175         ext4_extent_header_t *header = path->header;
    176         ext4_extent_t *r, *l, *m;
    177 
    178         uint16_t entries_count = ext4_extent_header_get_entries_count(header);
    179 
    180         if (entries_count == 0) {
    181                 // this leaf is empty
    182                 return;
     233        ext4_extent_t *extent = EXT4_EXTENT_FIRST(header);
     234//      uint64_t phys_block = 0;
     235
     236        for (uint16_t i = 0; i < ext4_extent_header_get_entries_count(header); ++i) {
     237
     238                uint32_t first_block = ext4_extent_get_first_block(extent);
     239                uint16_t block_count = ext4_extent_get_block_count(extent);
     240
     241                if ((iblock >= first_block) && (iblock < first_block + block_count)) {
     242                        break;
     243                }
     244                // Go to the next extent
     245                ++extent;
    183246        }
    184247
    185         l = EXT4_EXTENT_FIRST(header) + 1;
    186         r = l + entries_count - 1;
    187 
    188         while (l <= r) {
    189                 m = l + (r - l) / 2;
    190                 uint32_t block = ext4_extent_get_first_block(m);
    191                 if (iblock < block) {
    192                                 r = m - 1;
    193                 } else {
    194                                 l = m + 1;
    195                 }
     248        *ret_extent = extent;
     249
     250        return EOK;
     251}
     252
     253int ext4_extent_find_block(ext4_filesystem_t *fs,
     254                ext4_inode_ref_t *inode_ref, uint32_t iblock, uint32_t *fblock)
     255{
     256        int rc;
     257
     258        ext4_extent_t *extent = NULL;
     259        rc = ext4_extent_find_extent(fs, inode_ref, iblock, &extent);
     260        if (rc != EOK) {
     261                return rc;
    196262        }
    197263
    198         path->extent = l - 1;
    199 
    200 }
    201 
    202 int ext4_extent_find_block(ext4_filesystem_t *fs, ext4_extent_path_t **path,
    203                 ext4_extent_header_t *header, uint32_t iblock)
    204 {
    205         int rc;
    206 
    207         uint16_t depth = ext4_extent_header_get_depth(header);
    208 
    209         ext4_extent_header_t *eh = header;
    210 
    211         ext4_extent_path_t *tmp_path;
    212 
    213         // Added 2 for possible tree growing
    214         tmp_path = malloc(sizeof(ext4_extent_path_t) * (depth + 2));
    215         if (tmp_path == NULL) {
    216                 *path = NULL;
    217                 return ENOMEM;
    218         }
    219 
    220         tmp_path[0].block = NULL;
    221         tmp_path[0].header = eh;
    222 
    223         uint16_t pos = 0, idx = depth;
    224         while (idx > 0) {
    225 
    226                 ext4_extent_binsearch_idx(tmp_path + pos, iblock);
    227 
    228                 tmp_path[pos].depth = idx;
    229                 tmp_path[pos].extent = NULL;
    230 
    231                 uint64_t fblock = ext4_extent_index_get_leaf(tmp_path[pos].index);
    232                 block_t *block;
    233                 rc = block_get(&block, fs->device, fblock, BLOCK_FLAGS_NONE);
    234                 if (rc != EOK) {
    235                         // TODO cleanup
    236                 }
    237 
    238                 eh = (ext4_extent_header_t *)tmp_path[pos].block->data;
    239                 pos++;
    240 
    241                 tmp_path[pos].block = block;
    242                 tmp_path[pos].header = eh;
    243 
    244                 idx--;
    245 
    246         }
    247 
    248         tmp_path[pos].depth = idx;
    249         tmp_path[pos].extent = NULL;
    250         tmp_path[pos].index = NULL;
    251 
    252     /* find extent */
    253         ext4_extent_binsearch(tmp_path + pos, iblock);
    254 
    255         /* if not an empty leaf */
    256         if (tmp_path[pos].extent) {
    257                 uint64_t fblock = ext4_extent_get_start(tmp_path[pos].extent);
    258                 block_t *block;
    259                 rc = block_get(&block, fs->device, fblock, BLOCK_FLAGS_NONE);
    260                 if (rc != EOK) {
    261                         // TODO cleanup
    262                 }
    263                 tmp_path[pos].block = block;
    264         }
     264        uint32_t phys_block;
     265        phys_block = ext4_extent_get_start(extent) + iblock;
     266        phys_block -= ext4_extent_get_first_block(extent);
     267
     268
     269        *fblock = phys_block;
    265270
    266271        return EOK;
     272
     273
     274//      ext4_extent_header_t *eh =
     275//                      ext4_inode_get_extent_header(inode_ref->inode);
     276//
     277//      uint16_t depth = ext4_extent_header_get_depth(eh);
     278//
     279//      ext4_extent_path_t *tmp_path;
     280//
     281//      // Added 2 for possible tree growing
     282//      tmp_path = malloc(sizeof(ext4_extent_path_t) * (depth + 2));
     283//      if (tmp_path == NULL) {
     284//              *path = NULL;
     285//              return ENOMEM;
     286//      }
     287//
     288//      tmp_path[0].block = inode_ref->block;
     289//      tmp_path[0].header = eh;
     290//
     291//      uint16_t pos = 0;
     292//      while (ext4_extent_header_get_depth(eh) != 0) {
     293//
     294//              EXT4FS_DBG("count == \%u", ext4_extent_header_get_entries_count(eh));
     295//
     296//              ext4_extent_binsearch_idx(tmp_path + pos, iblock);
     297//
     298//              uint32_t offset = (void *)tmp_path[pos].index - (void *)EXT4_EXTENT_FIRST_INDEX(eh);
     299//
     300//              EXT4FS_DBG("offset = \%u", offset);
     301//
     302//              EXT4FS_DBG("first block = \%u, leaf = \%u",
     303//                              ext4_extent_index_get_first_block(tmp_path[pos].index),
     304//                              (uint32_t)ext4_extent_index_get_leaf(tmp_path[pos].index));
     305//
     306//              tmp_path[pos].depth = depth;
     307//              tmp_path[pos].extent = NULL;
     308//
     309//              assert(tmp_path[pos].index != NULL);
     310//
     311//              uint64_t fblock = ext4_extent_index_get_leaf(tmp_path[pos].index);
     312//
     313//              EXT4FS_DBG("fblock = \%u", (uint32_t)fblock);
     314//
     315//              block_t *block;
     316//              rc = block_get(&block, fs->device, fblock, BLOCK_FLAGS_NONE);
     317//              if (rc != EOK) {
     318//                      // TODO cleanup
     319//                      EXT4FS_DBG("ERRRR");
     320//                      return rc;
     321//              }
     322//
     323//              EXT4FS_DBG("block loaded");
     324//
     325//              pos++;
     326//
     327//              eh = (ext4_extent_header_t *)block->data;
     328//              tmp_path[pos].block = block;
     329//              tmp_path[pos].header = eh;
     330//
     331//      }
     332//
     333//      tmp_path[pos].depth = 0;
     334//      tmp_path[pos].extent = NULL;
     335//      tmp_path[pos].index = NULL;
     336//
     337//      EXT4FS_DBG("pos = \%u", pos);
     338//
     339//    /* find extent */
     340//      ext4_extent_binsearch(tmp_path + pos, iblock);
     341//
     342//      EXT4FS_DBG("after binsearch in extent");
     343//
     344//      /* if not an empty leaf */
     345//      if (tmp_path[pos].extent) {
     346//              EXT4FS_DBG("nonempty leaf");
     347//
     348////            uint64_t fblock = ext4_extent_get_start(tmp_path[pos].extent);
     349////            block_t *block;
     350////            rc = block_get(&block, fs->device, fblock, BLOCK_FLAGS_NONE);
     351////            if (rc != EOK) {
     352////                    // TODO cleanup
     353////            }
     354////            tmp_path[pos].block = block;
     355//      }
     356//
     357//      *path = tmp_path;
     358//
     359//      return EOK;
    267360}
    268361
  • uspace/lib/ext4/libext4_extent.h

    rcd581120 r9104bb5  
    6161extern void ext4_extent_header_set_generation(ext4_extent_header_t *, uint32_t);
    6262
    63 extern int ext4_extent_find_block(ext4_filesystem_t *, ext4_extent_path_t **,
    64                 ext4_extent_header_t *, uint32_t);
     63extern int ext4_extent_find_block(ext4_filesystem_t *, ext4_inode_ref_t *,
     64                uint32_t, uint32_t *);
    6565#endif
    6666
  • uspace/lib/ext4/libext4_filesystem.c

    rcd581120 r9104bb5  
    494494}
    495495
    496 int ext4_filesystem_get_inode_data_block_index(ext4_filesystem_t *fs, ext4_inode_t* inode,
    497     aoff64_t iblock, uint32_t* fblock)
     496int ext4_filesystem_get_inode_data_block_index(ext4_filesystem_t *fs,
     497                ext4_inode_ref_t *inode_ref, aoff64_t iblock, uint32_t* fblock)
    498498{
    499499        int rc;
     
    504504        /* Handle inode using extents */
    505505        if (ext4_superblock_has_feature_incompatible(fs->superblock, EXT4_FEATURE_INCOMPAT_EXTENTS) &&
    506                         ext4_inode_has_flag(inode, EXT4_INODE_FLAG_EXTENTS)) {
    507                 current_block = ext4_inode_get_extent_block(inode, iblock, fs->device);
     506                        ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS)) {
     507                rc = ext4_extent_find_block(fs, inode_ref, iblock, &current_block);
     508
     509                if (rc != EOK) {
     510                        return rc;
     511                }
     512
    508513                *fblock = current_block;
    509514                return EOK;
    510515
    511516        }
     517
     518        ext4_inode_t *inode = inode_ref->inode;
    512519
    513520        /* Handle simple case when we are dealing with direct reference */
  • uspace/lib/ext4/libext4_filesystem.h

    rcd581120 r9104bb5  
    5353                ext4_inode_ref_t *, aoff64_t);
    5454extern int ext4_filesystem_get_inode_data_block_index(ext4_filesystem_t *,
    55         ext4_inode_t *, aoff64_t iblock, uint32_t *);
     55        ext4_inode_ref_t *, aoff64_t iblock, uint32_t *);
    5656extern int ext4_filesystem_set_inode_data_block_index(ext4_filesystem_t *,
    5757                ext4_inode_ref_t *, aoff64_t, uint32_t);
  • uspace/lib/ext4/libext4_inode.c

    rcd581120 r9104bb5  
    278278}
    279279
    280 
    281 uint32_t ext4_inode_get_extent_block(ext4_inode_t *inode, uint64_t idx, service_id_t service_id)
    282 {
    283         int rc;
    284 
    285         block_t* block = NULL;
    286 
    287         ext4_extent_header_t *header = ext4_inode_get_extent_header(inode);
    288         while (ext4_extent_header_get_depth(header) != 0) {
    289 
    290                 ext4_extent_index_t *extent_index = EXT4_EXTENT_FIRST_INDEX(header);
    291 
    292                 for (uint16_t i = 0; i < ext4_extent_header_get_entries_count(header); ++i) {
    293                         if (idx >= ext4_extent_index_get_first_block(extent_index)) {
    294 
    295                                 uint64_t child = ext4_extent_index_get_leaf(extent_index);
    296 
    297                                 if (block != NULL) {
    298                                         block_put(block);
    299                                 }
    300 
    301                                 rc = block_get(&block, service_id, child, BLOCK_FLAGS_NONE);
    302                                 if (rc != EOK) {
    303                                         return 0;
    304                                 }
    305 
    306                                 header = (ext4_extent_header_t *)block->data;
    307                                 break;
    308                         }
    309                 }
    310         }
    311 
    312         ext4_extent_t *extent = EXT4_EXTENT_FIRST(header);
    313         uint64_t phys_block = 0;
    314 
    315         for (uint16_t i = 0; i < ext4_extent_header_get_entries_count(header); ++i) {
    316 
    317                 uint32_t first_block = ext4_extent_get_first_block(extent);
    318                 uint16_t block_count = ext4_extent_get_block_count(extent);
    319 
    320                 if ((idx >= first_block) && (idx < first_block + block_count)) {
    321                          phys_block = ext4_extent_get_start(extent) + idx;
    322                          phys_block -= ext4_extent_get_first_block(extent);
    323 
    324                          // Memory leak prevention
    325                          if (block != NULL) {
    326                                  block_put(block);
    327                          }
    328                          return phys_block;
    329                 }
    330                 // Go to the next extent
    331                 ++extent;
    332         }
    333 
    334 
    335         EXT4FS_DBG("ERROR - reached function end");
    336         return phys_block;
    337 }
    338 
    339280bool ext4_inode_is_type(ext4_superblock_t *sb, ext4_inode_t *inode, uint32_t type)
    340281{
  • uspace/lib/ext4/libext4_inode.h

    rcd581120 r9104bb5  
    8080extern uint32_t ext4_inode_get_indirect_block(ext4_inode_t *, uint32_t);
    8181extern void ext4_inode_set_indirect_block(ext4_inode_t *, uint32_t, uint32_t);
    82 extern uint32_t ext4_inode_get_extent_block(ext4_inode_t *, uint64_t, service_id_t);
    8382extern ext4_extent_header_t * ext4_inode_get_extent_header(ext4_inode_t *);
    8483extern bool ext4_inode_is_type(ext4_superblock_t *, ext4_inode_t *, uint32_t);
  • uspace/srv/fs/ext4fs/ext4fs_ops.c

    rcd581120 r9104bb5  
    10031003        uint32_t fs_block;
    10041004        rc = ext4_filesystem_get_inode_data_block_index(inst->filesystem,
    1005                 inode_ref->inode, file_block, &fs_block);
     1005                inode_ref, file_block, &fs_block);
    10061006        if (rc != EOK) {
    10071007                async_answer_0(callid, rc);
     
    10901090
    10911091        ext4_inode_ref_t *inode_ref = enode->inode_ref;
    1092         rc = ext4_filesystem_get_inode_data_block_index(fs, inode_ref->inode, iblock, &fblock);
     1092        rc = ext4_filesystem_get_inode_data_block_index(fs, inode_ref, iblock, &fblock);
    10931093        if (rc != EOK) {
    10941094                ext4fs_node_put(fn);
Note: See TracChangeset for help on using the changeset viewer.