Changeset 3d0c96c7 in rtems


Ignore:
Timestamp:
May 7, 2012, 2:31:15 PM (7 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
4.11, master
Children:
84ab4fce
Parents:
d61b0a5
git-author:
Sebastian Huber <sebastian.huber@…> (05/07/12 14:31:15)
git-committer:
Sebastian Huber <sebastian.huber@…> (05/11/12 11:58:43)
Message:

Filesystem: PR1893: Fix write and truncate handler

Space that grows due to truncate or write offsets beyond the current
file size must be zero filled.

Location:
cpukit/libfs/src
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • cpukit/libfs/src/dosfs/fat.c

    rd61b0a5 r3d0c96c7  
    262262    }
    263263    return cmpltd;
     264}
     265
     266int
     267_fat_block_zero(
     268    rtems_filesystem_mount_table_entry_t *mt_entry,
     269    uint32_t                              start,
     270    uint32_t                              offset,
     271    uint32_t                              count)
     272{
     273    int                 rc = RC_OK;
     274    fat_fs_info_t      *fs_info = mt_entry->fs_info;
     275    uint32_t            blk  = start;
     276    uint32_t            ofs = offset;
     277    rtems_bdbuf_buffer *block = NULL;
     278    uint32_t            c = 0;
     279
     280    while(count > 0)
     281    {
     282        c = MIN(count, (fs_info->vol.bps - ofs));
     283
     284        if (c == fs_info->vol.bps)
     285            rc = fat_buf_access(fs_info, blk, FAT_OP_TYPE_GET, &block);
     286        else
     287            rc = fat_buf_access(fs_info, blk, FAT_OP_TYPE_READ, &block);
     288        if (rc != RC_OK)
     289            return -1;
     290
     291        memset((block->buffer + ofs), 0, c);
     292
     293        fat_buf_mark_modified(fs_info);
     294
     295        count -= c;
     296        blk++;
     297        ofs = 0;
     298    }
     299    return 0;
    264300}
    265301
  • cpukit/libfs/src/dosfs/fat.h

    rd61b0a5 r3d0c96c7  
    466466
    467467int
     468_fat_block_zero(rtems_filesystem_mount_table_entry_t *mt_entry,
     469                 uint32_t                              start,
     470                 uint32_t                              offset,
     471                 uint32_t                              count);
     472
     473int
    468474_fat_block_release(rtems_filesystem_mount_table_entry_t *mt_entry);
    469475
  • cpukit/libfs/src/dosfs/fat_fat_operations.c

    rd61b0a5 r3d0c96c7  
    4747    uint32_t                              count,
    4848    uint32_t                             *cls_added,
    49     uint32_t                             *last_cl
     49    uint32_t                             *last_cl,
     50    bool                                  zero_fill
    5051    )
    5152{
     
    114115                rc = fat_set_fat_cluster(mt_entry, save_cln, cl4find);
    115116                if ( rc != RC_OK )
    116                 {
    117                     /* cleanup activity */
    118                     fat_free_fat_clusters_chain(mt_entry, (*chain));
    119                     /* trying to save last allocated cluster for future use */
    120                     fat_set_fat_cluster(mt_entry, cl4find, FAT_GENFAT_FREE);
    121                     fat_buf_release(fs_info);
    122                     return rc;
    123                 }
     117                    goto cleanup;
     118            }
     119
     120            if (zero_fill) {
     121                uint32_t sec = fat_cluster_num_to_sector_num(mt_entry,
     122                                                             cl4find);
     123
     124                rc = _fat_block_zero(mt_entry, sec, 0, fs_info->vol.bpc);
     125                if ( rc != RC_OK )
     126                    goto cleanup;
    124127            }
    125128
     
    151154    fat_buf_release(fs_info);
    152155    return RC_OK;
     156
     157cleanup:
     158
     159    /* cleanup activity */
     160    fat_free_fat_clusters_chain(mt_entry, (*chain));
     161    /* trying to save last allocated cluster for future use */
     162    fat_set_fat_cluster(mt_entry, cl4find, FAT_GENFAT_FREE);
     163    fat_buf_release(fs_info);
     164    return rc;
    153165}
    154166
  • cpukit/libfs/src/dosfs/fat_fat_operations.h

    rd61b0a5 r3d0c96c7  
    4444    uint32_t                              count,
    4545    uint32_t                             *cls_added,
    46     uint32_t                             *last_cl
     46    uint32_t                             *last_cl,
     47    bool                                  zero_fill
    4748);
    4849
  • cpukit/libfs/src/dosfs/fat_file.c

    rd61b0a5 r3d0c96c7  
    382382    uint32_t       byte = 0;
    383383    uint32_t       c = 0;
     384    bool           zero_fill = start > fat_fd->fat_file_size;
    384385
    385386    if ( count == 0 )
    386387        return cmpltd;
    387388
    388     if ( start > fat_fd->fat_file_size )
    389         rtems_set_errno_and_return_minus_one( EIO );
    390 
    391     if ((count > fat_fd->size_limit) ||
    392         (start > fat_fd->size_limit - count))
    393         rtems_set_errno_and_return_minus_one( EIO );
    394 
    395     rc = fat_file_extend(mt_entry, fat_fd, start + count, &c);
     389    if (start >= fat_fd->size_limit)
     390        rtems_set_errno_and_return_minus_one(EFBIG);
     391
     392    if (count > fat_fd->size_limit - start)
     393        count = fat_fd->size_limit - start;
     394
     395    rc = fat_file_extend(mt_entry, fat_fd, zero_fill, start + count, &c);
    396396    if (rc != RC_OK)
    397397        return rc;
     
    476476    rtems_filesystem_mount_table_entry_t *mt_entry,
    477477    fat_file_fd_t                        *fat_fd,
     478    bool                                  zero_fill,
    478479    uint32_t                              new_length,
    479480    uint32_t                             *a_length
     
    510511        bytes2add = 0;
    511512
     513    if (zero_fill && bytes_remain > 0) {
     514        uint32_t start = fat_fd->fat_file_size;
     515        uint32_t cl_start = start >> fs_info->vol.bpc_log2;
     516        uint32_t ofs = start & (fs_info->vol.bpc - 1);
     517        uint32_t cur_cln;
     518        uint32_t sec;
     519        uint32_t byte;
     520
     521        rc = fat_file_lseek(mt_entry, fat_fd, cl_start, &cur_cln);
     522        if (rc != RC_OK)
     523            return rc;
     524
     525        sec = fat_cluster_num_to_sector_num(mt_entry, cur_cln);
     526        sec += ofs >> fs_info->vol.sec_log2;
     527        byte = ofs & (fs_info->vol.bps - 1);
     528
     529        rc = _fat_block_zero(mt_entry, sec, byte, bytes_remain);
     530        if (rc != RC_OK)
     531            return rc;
     532    }
     533
    512534    /*
    513535     * if in last cluster allocated for the file there is enough room to
     
    521543
    522544    rc = fat_scan_fat_for_free_clusters(mt_entry, &chain, cls2add,
    523                                         &cls_added, &last_cl);
     545                                        &cls_added, &last_cl, zero_fill);
    524546
    525547    /* this means that low level I/O error occured */
  • cpukit/libfs/src/dosfs/fat_file.h

    rd61b0a5 r3d0c96c7  
    159159fat_file_extend(rtems_filesystem_mount_table_entry_t *mt_entry,
    160160                fat_file_fd_t                        *fat_fd,
     161                bool                                  zero_fill,
    161162                uint32_t                              new_length,
    162163                uint32_t                             *a_length);
  • cpukit/libfs/src/dosfs/msdos_file.c

    rd61b0a5 r3d0c96c7  
    204204
    205205/* msdos_file_ftruncate --
    206  *     Truncate the file (if new length is greater then current do nothing).
     206 *     Truncate the file.
    207207 *
    208208 * PARAMETERS:
     
    220220    msdos_fs_info_t   *fs_info = iop->pathinfo.mt_entry->fs_info;
    221221    fat_file_fd_t     *fat_fd = iop->pathinfo.node_access;
    222 
    223     if (length >= fat_fd->fat_file_size)
    224         return RC_OK;
    225 
    226     sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
    227                                 MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
    228     if (sc != RTEMS_SUCCESSFUL)
    229         rtems_set_errno_and_return_minus_one(EIO);
    230 
    231     rc = fat_file_truncate(iop->pathinfo.mt_entry, fat_fd, length);
    232     if (rc != RC_OK)
    233     {
    234         rtems_semaphore_release(fs_info->vol_sema);
    235         return rc;
    236     }
    237 
    238     /*
    239      * fat_file_truncate do nothing if new length >= fat-file size, so update
    240      * file size only if length < fat-file size
    241      */
    242     if (length < fat_fd->fat_file_size)
     222    uint32_t old_length;
     223
     224    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
     225                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
     226    if (sc != RTEMS_SUCCESSFUL)
     227        rtems_set_errno_and_return_minus_one(EIO);
     228
     229    old_length = fat_fd->fat_file_size;
     230    if (length < old_length) {
     231        rc = fat_file_truncate(iop->pathinfo.mt_entry, fat_fd, length);
     232    } else {
     233        uint32_t new_length;
     234
     235        rc = fat_file_extend(iop->pathinfo.mt_entry,
     236                             fat_fd,
     237                             true,
     238                             length,
     239                             &new_length);
     240        if (rc == RC_OK && length != new_length) {
     241            fat_file_truncate(iop->pathinfo.mt_entry, fat_fd, old_length);
     242            errno = ENOSPC;
     243            rc = -1;
     244        }
     245    }
     246
     247    if (rc == RC_OK) {
    243248        fat_fd->fat_file_size = length;
    244 
    245     rtems_semaphore_release(fs_info->vol_sema);
    246     return RC_OK;
     249    }
     250
     251    rtems_semaphore_release(fs_info->vol_sema);
     252
     253    return rc;
    247254}
    248255
  • cpukit/libfs/src/dosfs/msdos_misc.c

    rd61b0a5 r3d0c96c7  
    14121412            printf ("MSFS:[9.2] extending file:%li\n", empty_space_offset);
    14131413#endif
    1414             ret = fat_file_extend (mt_entry, fat_fd, empty_space_offset * bts2rd,
    1415                                    &new_length);
     1414            ret = fat_file_extend (mt_entry, fat_fd, false,
     1415                                   empty_space_offset * bts2rd, &new_length);
    14161416
    14171417            if (ret != RC_OK)
  • cpukit/libfs/src/imfs/memfile.c

    rd61b0a5 r3d0c96c7  
    3434MEMFILE_STATIC int IMFS_memfile_extend(
    3535   IMFS_jnode_t  *the_jnode,
     36   bool           zero_fill,
    3637   off_t          new_length
    3738);
     
    196197
    197198  if ( length > the_jnode->info.file.size )
    198     return IMFS_memfile_extend( the_jnode, length );
     199    return IMFS_memfile_extend( the_jnode, true, length );
    199200
    200201  /*
     
    219220MEMFILE_STATIC int IMFS_memfile_extend(
    220221   IMFS_jnode_t  *the_jnode,
     222   bool           zero_fill,
    221223   off_t          new_length
    222224)
     
    225227  unsigned int   new_blocks;
    226228  unsigned int   old_blocks;
     229  unsigned int   offset;
    227230
    228231  /*
     
    249252  new_blocks = new_length / IMFS_MEMFILE_BYTES_PER_BLOCK;
    250253  old_blocks = the_jnode->info.file.size / IMFS_MEMFILE_BYTES_PER_BLOCK;
     254  offset = the_jnode->info.file.size - old_blocks * IMFS_MEMFILE_BYTES_PER_BLOCK;
    251255
    252256  /*
     
    254258   */
    255259  for ( block=old_blocks ; block<=new_blocks ; block++ ) {
    256     if ( IMFS_memfile_addblock( the_jnode, block ) ) {
     260    if ( !IMFS_memfile_addblock( the_jnode, block ) ) {
     261       if ( zero_fill ) {
     262          size_t count = IMFS_MEMFILE_BYTES_PER_BLOCK - offset;
     263          block_p *block_ptr =
     264            IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
     265
     266          memset( &(*block_ptr) [offset], 0, count);
     267          offset = 0;
     268       }
     269    } else {
    257270       for ( ; block>=old_blocks ; block-- ) {
    258271         IMFS_memfile_remove_block( the_jnode, block );
     
    623636  last_byte = start + my_length;
    624637  if ( last_byte > the_jnode->info.file.size ) {
    625     status = IMFS_memfile_extend( the_jnode, last_byte );
     638    bool zero_fill = start > the_jnode->info.file.size;
     639
     640    status = IMFS_memfile_extend( the_jnode, zero_fill, last_byte );
    626641    if ( status )
    627642      return status;
Note: See TracChangeset for help on using the changeset viewer.