ext4 ext4_map_blocks
来源:互联网 发布:人工智能爱酱cv 编辑:程序博客网 时间:2024/04/30 11:43
struct ext4_map_blocks {ext4_fsblk_t m_pblk;ext4_lblk_t m_lblk;unsigned int m_len;unsigned int m_flags;};
/* * The ext4_map_blocks() function tries to look up the requested blocks, * and returns if the blocks are already mapped. * * Otherwise it takes the write lock of the i_data_sem and allocate blocks * and store the allocated blocks in the result buffer head and mark it * mapped. * * If file type is extents based, it will call ext4_ext_map_blocks(), * Otherwise, call with ext4_ind_map_blocks() to handle indirect mapping * based files * * On success, it returns the number of blocks being mapped or allocated. if * create==0 and the blocks are pre-allocated and unwritten, the resulting @map * is marked as unwritten. If the create == 1, it will mark @map as mapped. * * It returns 0 if plain look up failed (blocks have not been allocated), in * that case, @map is returned as unmapped but we still do fill map->m_len to * indicate the length of a hole starting at map->m_lblk. * * It returns the error in case of allocation failure. */int ext4_map_blocks(handle_t *handle, struct inode *inode, struct ext4_map_blocks *map, int flags){struct extent_status es;int retval;int ret = 0;#ifdef ES_AGGRESSIVE_TESTstruct ext4_map_blocks orig_map;memcpy(&orig_map, map, sizeof(*map));#endifmap->m_flags = 0;ext_debug("ext4_map_blocks(): inode %lu, flag %d, max_blocks %u," "logical block %lu\n", inode->i_ino, flags, map->m_len, (unsigned long) map->m_lblk);/* * ext4_map_blocks returns an int, and m_len is an unsigned int */if (unlikely(map->m_len > INT_MAX))map->m_len = INT_MAX;/* We can handle the block number less than EXT_MAX_BLOCKS */if (unlikely(map->m_lblk >= EXT_MAX_BLOCKS))return -EFSCORRUPTED;/* Lookup extent status tree firstly */if (ext4_es_lookup_extent(inode, map->m_lblk, &es)) {if (ext4_es_is_written(&es) || ext4_es_is_unwritten(&es)) {map->m_pblk = ext4_es_pblock(&es) +map->m_lblk - es.es_lblk;map->m_flags |= ext4_es_is_written(&es) ?EXT4_MAP_MAPPED : EXT4_MAP_UNWRITTEN;retval = es.es_len - (map->m_lblk - es.es_lblk);if (retval > map->m_len)retval = map->m_len;map->m_len = retval;} else if (ext4_es_is_delayed(&es) || ext4_es_is_hole(&es)) {map->m_pblk = 0;retval = es.es_len - (map->m_lblk - es.es_lblk);if (retval > map->m_len)retval = map->m_len;map->m_len = retval;retval = 0;} else {BUG_ON(1);}#ifdef ES_AGGRESSIVE_TESText4_map_blocks_es_recheck(handle, inode, map, &orig_map, flags);#endifgoto found;}/* * Try to see if we can get the block without requesting a new * file system block. */down_read(&EXT4_I(inode)->i_data_sem);if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) {retval = ext4_ext_map_blocks(handle, inode, map, flags & EXT4_GET_BLOCKS_KEEP_SIZE);} else {retval = ext4_ind_map_blocks(handle, inode, map, flags & EXT4_GET_BLOCKS_KEEP_SIZE);}if (retval > 0) {unsigned int status;if (unlikely(retval != map->m_len)) {ext4_warning(inode->i_sb, "ES len assertion failed for inode " "%lu: retval %d != map->m_len %d", inode->i_ino, retval, map->m_len);WARN_ON(1);}status = map->m_flags & EXT4_MAP_UNWRITTEN ?EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN;if (!(flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) && !(status & EXTENT_STATUS_WRITTEN) && ext4_find_delalloc_range(inode, map->m_lblk, map->m_lblk + map->m_len - 1))status |= EXTENT_STATUS_DELAYED;ret = ext4_es_insert_extent(inode, map->m_lblk, map->m_len, map->m_pblk, status);if (ret < 0)retval = ret;}up_read((&EXT4_I(inode)->i_data_sem));found:if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) {ret = check_block_validity(inode, map);if (ret != 0)return ret;}/* If it is only a block(s) look up */if ((flags & EXT4_GET_BLOCKS_CREATE) == 0)return retval;/* * Returns if the blocks have already allocated * * Note that if blocks have been preallocated * ext4_ext_get_block() returns the create = 0 * with buffer head unmapped. */if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED)/* * If we need to convert extent to unwritten * we continue and do the actual work in * ext4_ext_map_blocks() */if (!(flags & EXT4_GET_BLOCKS_CONVERT_UNWRITTEN))return retval;/* * Here we clear m_flags because after allocating an new extent, * it will be set again. */map->m_flags &= ~EXT4_MAP_FLAGS;/* * New blocks allocate and/or writing to unwritten extent * will possibly result in updating i_data, so we take * the write lock of i_data_sem, and call get_block() * with create == 1 flag. */down_write(&EXT4_I(inode)->i_data_sem);/* * We need to check for EXT4 here because migrate * could have changed the inode type in between */if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) {retval = ext4_ext_map_blocks(handle, inode, map, flags);} else {retval = ext4_ind_map_blocks(handle, inode, map, flags);if (retval > 0 && map->m_flags & EXT4_MAP_NEW) {/* * We allocated new blocks which will result in * i_data's format changing. Force the migrate * to fail by clearing migrate flags */ext4_clear_inode_state(inode, EXT4_STATE_EXT_MIGRATE);}/* * Update reserved blocks/metadata blocks after successful * block allocation which had been deferred till now. We don't * support fallocate for non extent files. So we can update * reserve space here. */if ((retval > 0) &&(flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE))ext4_da_update_reserve_space(inode, retval, 1);}if (retval > 0) {unsigned int status;if (unlikely(retval != map->m_len)) {ext4_warning(inode->i_sb, "ES len assertion failed for inode " "%lu: retval %d != map->m_len %d", inode->i_ino, retval, map->m_len);WARN_ON(1);}/* * We have to zeroout blocks before inserting them into extent * status tree. Otherwise someone could look them up there and * use them before they are really zeroed. We also have to * unmap metadata before zeroing as otherwise writeback can * overwrite zeros with stale data from block device. */if (flags & EXT4_GET_BLOCKS_ZERO && map->m_flags & EXT4_MAP_MAPPED && map->m_flags & EXT4_MAP_NEW) {ext4_lblk_t i;for (i = 0; i < map->m_len; i++) {unmap_underlying_metadata(inode->i_sb->s_bdev, map->m_pblk + i);}ret = ext4_issue_zeroout(inode, map->m_lblk, map->m_pblk, map->m_len);if (ret) {retval = ret;goto out_sem;}}/* * If the extent has been zeroed out, we don't need to update * extent status tree. */if ((flags & EXT4_GET_BLOCKS_PRE_IO) && ext4_es_lookup_extent(inode, map->m_lblk, &es)) {if (ext4_es_is_written(&es))goto out_sem;}status = map->m_flags & EXT4_MAP_UNWRITTEN ?EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN;if (!(flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) && !(status & EXTENT_STATUS_WRITTEN) && ext4_find_delalloc_range(inode, map->m_lblk, map->m_lblk + map->m_len - 1))status |= EXTENT_STATUS_DELAYED;ret = ext4_es_insert_extent(inode, map->m_lblk, map->m_len, map->m_pblk, status);if (ret < 0) {retval = ret;goto out_sem;}}out_sem:up_write((&EXT4_I(inode)->i_data_sem));if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) {ret = check_block_validity(inode, map);if (ret != 0)return ret;/* * Inodes with freshly allocated blocks where contents will be * visible after transaction commit must be on transaction's * ordered data list. */if (map->m_flags & EXT4_MAP_NEW && !(map->m_flags & EXT4_MAP_UNWRITTEN) && !(flags & EXT4_GET_BLOCKS_ZERO) && !IS_NOQUOTA(inode) && ext4_should_order_data(inode)) {if (flags & EXT4_GET_BLOCKS_IO_SUBMIT)ret = ext4_jbd2_inode_add_wait(handle, inode);elseret = ext4_jbd2_inode_add_write(handle, inode);if (ret)return ret;}}return retval;}
0 0
- ext4 ext4_map_blocks
- Ext4
- Ext4
- ext4
- Ext4 features
- ext4.0
- 剖析ext4
- ext4 介绍
- 剖析 ext4
- ext4 学习
- EXt4 文件系统
- ext4 2
- ext4文件系统
- Ext4.0
- ext4格式
- ext4文件系统
- 剖析 ext4
- ext4 文件系统
- .net平台的rabbitmq使用封装
- swift插入或者删除字符串
- 透视摄像机模型
- angularjs 最新安装步骤-2017
- 初识工厂三姐妹
- ext4 ext4_map_blocks
- 对象属性选择性拷贝 JAVA生成密码随机数
- linux下文件及文件夹操作
- 数组最值函数
- POJ1905
- leetcode解题报告3. Longest Substring Without Repeating Characters
- 芬语录3.5
- STM32中通过普通延时函数来精确延时
- busybox安装根文件系统(待续)