diff options
Diffstat (limited to 'fs/ext4/extents.c')
| -rw-r--r-- | fs/ext4/extents.c | 281 |
1 files changed, 264 insertions, 17 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index b24d3c53f20c..ea2ce3c0ae66 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
| @@ -40,6 +40,7 @@ | |||
| 40 | #include <linux/slab.h> | 40 | #include <linux/slab.h> |
| 41 | #include <linux/falloc.h> | 41 | #include <linux/falloc.h> |
| 42 | #include <asm/uaccess.h> | 42 | #include <asm/uaccess.h> |
| 43 | #include <linux/fiemap.h> | ||
| 43 | #include "ext4_jbd2.h" | 44 | #include "ext4_jbd2.h" |
| 44 | #include "ext4_extents.h" | 45 | #include "ext4_extents.h" |
| 45 | 46 | ||
| @@ -383,8 +384,8 @@ static void ext4_ext_show_leaf(struct inode *inode, struct ext4_ext_path *path) | |||
| 383 | ext_debug("\n"); | 384 | ext_debug("\n"); |
| 384 | } | 385 | } |
| 385 | #else | 386 | #else |
| 386 | #define ext4_ext_show_path(inode,path) | 387 | #define ext4_ext_show_path(inode, path) |
| 387 | #define ext4_ext_show_leaf(inode,path) | 388 | #define ext4_ext_show_leaf(inode, path) |
| 388 | #endif | 389 | #endif |
| 389 | 390 | ||
| 390 | void ext4_ext_drop_refs(struct ext4_ext_path *path) | 391 | void ext4_ext_drop_refs(struct ext4_ext_path *path) |
| @@ -440,9 +441,10 @@ ext4_ext_binsearch_idx(struct inode *inode, | |||
| 440 | for (k = 0; k < le16_to_cpu(eh->eh_entries); k++, ix++) { | 441 | for (k = 0; k < le16_to_cpu(eh->eh_entries); k++, ix++) { |
| 441 | if (k != 0 && | 442 | if (k != 0 && |
| 442 | le32_to_cpu(ix->ei_block) <= le32_to_cpu(ix[-1].ei_block)) { | 443 | le32_to_cpu(ix->ei_block) <= le32_to_cpu(ix[-1].ei_block)) { |
| 443 | printk("k=%d, ix=0x%p, first=0x%p\n", k, | 444 | printk(KERN_DEBUG "k=%d, ix=0x%p, " |
| 444 | ix, EXT_FIRST_INDEX(eh)); | 445 | "first=0x%p\n", k, |
| 445 | printk("%u <= %u\n", | 446 | ix, EXT_FIRST_INDEX(eh)); |
| 447 | printk(KERN_DEBUG "%u <= %u\n", | ||
| 446 | le32_to_cpu(ix->ei_block), | 448 | le32_to_cpu(ix->ei_block), |
| 447 | le32_to_cpu(ix[-1].ei_block)); | 449 | le32_to_cpu(ix[-1].ei_block)); |
| 448 | } | 450 | } |
| @@ -1475,7 +1477,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode, | |||
| 1475 | struct ext4_ext_path *path, | 1477 | struct ext4_ext_path *path, |
| 1476 | struct ext4_extent *newext) | 1478 | struct ext4_extent *newext) |
| 1477 | { | 1479 | { |
| 1478 | struct ext4_extent_header * eh; | 1480 | struct ext4_extent_header *eh; |
| 1479 | struct ext4_extent *ex, *fex; | 1481 | struct ext4_extent *ex, *fex; |
| 1480 | struct ext4_extent *nearex; /* nearest extent */ | 1482 | struct ext4_extent *nearex; /* nearest extent */ |
| 1481 | struct ext4_ext_path *npath = NULL; | 1483 | struct ext4_ext_path *npath = NULL; |
| @@ -1625,6 +1627,113 @@ cleanup: | |||
| 1625 | return err; | 1627 | return err; |
| 1626 | } | 1628 | } |
| 1627 | 1629 | ||
| 1630 | int ext4_ext_walk_space(struct inode *inode, ext4_lblk_t block, | ||
| 1631 | ext4_lblk_t num, ext_prepare_callback func, | ||
| 1632 | void *cbdata) | ||
| 1633 | { | ||
| 1634 | struct ext4_ext_path *path = NULL; | ||
| 1635 | struct ext4_ext_cache cbex; | ||
| 1636 | struct ext4_extent *ex; | ||
| 1637 | ext4_lblk_t next, start = 0, end = 0; | ||
| 1638 | ext4_lblk_t last = block + num; | ||
| 1639 | int depth, exists, err = 0; | ||
| 1640 | |||
| 1641 | BUG_ON(func == NULL); | ||
| 1642 | BUG_ON(inode == NULL); | ||
| 1643 | |||
| 1644 | while (block < last && block != EXT_MAX_BLOCK) { | ||
| 1645 | num = last - block; | ||
| 1646 | /* find extent for this block */ | ||
| 1647 | path = ext4_ext_find_extent(inode, block, path); | ||
| 1648 | if (IS_ERR(path)) { | ||
| 1649 | err = PTR_ERR(path); | ||
| 1650 | path = NULL; | ||
| 1651 | break; | ||
| 1652 | } | ||
| 1653 | |||
| 1654 | depth = ext_depth(inode); | ||
| 1655 | BUG_ON(path[depth].p_hdr == NULL); | ||
| 1656 | ex = path[depth].p_ext; | ||
| 1657 | next = ext4_ext_next_allocated_block(path); | ||
| 1658 | |||
| 1659 | exists = 0; | ||
| 1660 | if (!ex) { | ||
| 1661 | /* there is no extent yet, so try to allocate | ||
| 1662 | * all requested space */ | ||
| 1663 | start = block; | ||
| 1664 | end = block + num; | ||
| 1665 | } else if (le32_to_cpu(ex->ee_block) > block) { | ||
| 1666 | /* need to allocate space before found extent */ | ||
| 1667 | start = block; | ||
| 1668 | end = le32_to_cpu(ex->ee_block); | ||
| 1669 | if (block + num < end) | ||
| 1670 | end = block + num; | ||
| 1671 | } else if (block >= le32_to_cpu(ex->ee_block) | ||
| 1672 | + ext4_ext_get_actual_len(ex)) { | ||
| 1673 | /* need to allocate space after found extent */ | ||
| 1674 | start = block; | ||
| 1675 | end = block + num; | ||
| 1676 | if (end >= next) | ||
| 1677 | end = next; | ||
| 1678 | } else if (block >= le32_to_cpu(ex->ee_block)) { | ||
| 1679 | /* | ||
| 1680 | * some part of requested space is covered | ||
| 1681 | * by found extent | ||
| 1682 | */ | ||
| 1683 | start = block; | ||
| 1684 | end = le32_to_cpu(ex->ee_block) | ||
| 1685 | + ext4_ext_get_actual_len(ex); | ||
| 1686 | if (block + num < end) | ||
| 1687 | end = block + num; | ||
| 1688 | exists = 1; | ||
| 1689 | } else { | ||
| 1690 | BUG(); | ||
| 1691 | } | ||
| 1692 | BUG_ON(end <= start); | ||
| 1693 | |||
| 1694 | if (!exists) { | ||
| 1695 | cbex.ec_block = start; | ||
| 1696 | cbex.ec_len = end - start; | ||
| 1697 | cbex.ec_start = 0; | ||
| 1698 | cbex.ec_type = EXT4_EXT_CACHE_GAP; | ||
| 1699 | } else { | ||
| 1700 | cbex.ec_block = le32_to_cpu(ex->ee_block); | ||
| 1701 | cbex.ec_len = ext4_ext_get_actual_len(ex); | ||
| 1702 | cbex.ec_start = ext_pblock(ex); | ||
| 1703 | cbex.ec_type = EXT4_EXT_CACHE_EXTENT; | ||
| 1704 | } | ||
| 1705 | |||
| 1706 | BUG_ON(cbex.ec_len == 0); | ||
| 1707 | err = func(inode, path, &cbex, ex, cbdata); | ||
| 1708 | ext4_ext_drop_refs(path); | ||
| 1709 | |||
| 1710 | if (err < 0) | ||
| 1711 | break; | ||
| 1712 | |||
| 1713 | if (err == EXT_REPEAT) | ||
| 1714 | continue; | ||
| 1715 | else if (err == EXT_BREAK) { | ||
| 1716 | err = 0; | ||
| 1717 | break; | ||
| 1718 | } | ||
| 1719 | |||
| 1720 | if (ext_depth(inode) != depth) { | ||
| 1721 | /* depth was changed. we have to realloc path */ | ||
| 1722 | kfree(path); | ||
| 1723 | path = NULL; | ||
| 1724 | } | ||
| 1725 | |||
| 1726 | block = cbex.ec_block + cbex.ec_len; | ||
| 1727 | } | ||
| 1728 | |||
| 1729 | if (path) { | ||
| 1730 | ext4_ext_drop_refs(path); | ||
| 1731 | kfree(path); | ||
| 1732 | } | ||
| 1733 | |||
| 1734 | return err; | ||
| 1735 | } | ||
| 1736 | |||
| 1628 | static void | 1737 | static void |
| 1629 | ext4_ext_put_in_cache(struct inode *inode, ext4_lblk_t block, | 1738 | ext4_ext_put_in_cache(struct inode *inode, ext4_lblk_t block, |
| 1630 | __u32 len, ext4_fsblk_t start, int type) | 1739 | __u32 len, ext4_fsblk_t start, int type) |
| @@ -2142,7 +2251,7 @@ void ext4_ext_init(struct super_block *sb) | |||
| 2142 | */ | 2251 | */ |
| 2143 | 2252 | ||
| 2144 | if (test_opt(sb, EXTENTS)) { | 2253 | if (test_opt(sb, EXTENTS)) { |
| 2145 | printk("EXT4-fs: file extents enabled"); | 2254 | printk(KERN_INFO "EXT4-fs: file extents enabled"); |
| 2146 | #ifdef AGGRESSIVE_TEST | 2255 | #ifdef AGGRESSIVE_TEST |
| 2147 | printk(", aggressive tests"); | 2256 | printk(", aggressive tests"); |
| 2148 | #endif | 2257 | #endif |
| @@ -2696,11 +2805,8 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | |||
| 2696 | goto out2; | 2805 | goto out2; |
| 2697 | } | 2806 | } |
| 2698 | /* | 2807 | /* |
| 2699 | * Okay, we need to do block allocation. Lazily initialize the block | 2808 | * Okay, we need to do block allocation. |
| 2700 | * allocation info here if necessary. | ||
| 2701 | */ | 2809 | */ |
| 2702 | if (S_ISREG(inode->i_mode) && (!EXT4_I(inode)->i_block_alloc_info)) | ||
| 2703 | ext4_init_block_alloc_info(inode); | ||
| 2704 | 2810 | ||
| 2705 | /* find neighbour allocated blocks */ | 2811 | /* find neighbour allocated blocks */ |
| 2706 | ar.lleft = iblock; | 2812 | ar.lleft = iblock; |
| @@ -2760,7 +2866,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | |||
| 2760 | /* free data blocks we just allocated */ | 2866 | /* free data blocks we just allocated */ |
| 2761 | /* not a good idea to call discard here directly, | 2867 | /* not a good idea to call discard here directly, |
| 2762 | * but otherwise we'd need to call it every free() */ | 2868 | * but otherwise we'd need to call it every free() */ |
| 2763 | ext4_mb_discard_inode_preallocations(inode); | 2869 | ext4_discard_preallocations(inode); |
| 2764 | ext4_free_blocks(handle, inode, ext_pblock(&newex), | 2870 | ext4_free_blocks(handle, inode, ext_pblock(&newex), |
| 2765 | ext4_ext_get_actual_len(&newex), 0); | 2871 | ext4_ext_get_actual_len(&newex), 0); |
| 2766 | goto out2; | 2872 | goto out2; |
| @@ -2824,7 +2930,7 @@ void ext4_ext_truncate(struct inode *inode) | |||
| 2824 | down_write(&EXT4_I(inode)->i_data_sem); | 2930 | down_write(&EXT4_I(inode)->i_data_sem); |
| 2825 | ext4_ext_invalidate_cache(inode); | 2931 | ext4_ext_invalidate_cache(inode); |
| 2826 | 2932 | ||
| 2827 | ext4_discard_reservation(inode); | 2933 | ext4_discard_preallocations(inode); |
| 2828 | 2934 | ||
| 2829 | /* | 2935 | /* |
| 2830 | * TODO: optimization is possible here. | 2936 | * TODO: optimization is possible here. |
| @@ -2877,10 +2983,11 @@ static void ext4_falloc_update_inode(struct inode *inode, | |||
| 2877 | * Update only when preallocation was requested beyond | 2983 | * Update only when preallocation was requested beyond |
| 2878 | * the file size. | 2984 | * the file size. |
| 2879 | */ | 2985 | */ |
| 2880 | if (!(mode & FALLOC_FL_KEEP_SIZE) && | 2986 | if (!(mode & FALLOC_FL_KEEP_SIZE)) { |
| 2881 | new_size > i_size_read(inode)) { | 2987 | if (new_size > i_size_read(inode)) |
| 2882 | i_size_write(inode, new_size); | 2988 | i_size_write(inode, new_size); |
| 2883 | EXT4_I(inode)->i_disksize = new_size; | 2989 | if (new_size > EXT4_I(inode)->i_disksize) |
| 2990 | ext4_update_i_disksize(inode, new_size); | ||
| 2884 | } | 2991 | } |
| 2885 | 2992 | ||
| 2886 | } | 2993 | } |
| @@ -2972,3 +3079,143 @@ retry: | |||
| 2972 | mutex_unlock(&inode->i_mutex); | 3079 | mutex_unlock(&inode->i_mutex); |
| 2973 | return ret > 0 ? ret2 : ret; | 3080 | return ret > 0 ? ret2 : ret; |
| 2974 | } | 3081 | } |
| 3082 | |||
| 3083 | /* | ||
| 3084 | * Callback function called for each extent to gather FIEMAP information. | ||
| 3085 | */ | ||
| 3086 | int ext4_ext_fiemap_cb(struct inode *inode, struct ext4_ext_path *path, | ||
| 3087 | struct ext4_ext_cache *newex, struct ext4_extent *ex, | ||
| 3088 | void *data) | ||
| 3089 | { | ||
| 3090 | struct fiemap_extent_info *fieinfo = data; | ||
| 3091 | unsigned long blksize_bits = inode->i_sb->s_blocksize_bits; | ||
| 3092 | __u64 logical; | ||
| 3093 | __u64 physical; | ||
| 3094 | __u64 length; | ||
| 3095 | __u32 flags = 0; | ||
| 3096 | int error; | ||
| 3097 | |||
| 3098 | logical = (__u64)newex->ec_block << blksize_bits; | ||
| 3099 | |||
| 3100 | if (newex->ec_type == EXT4_EXT_CACHE_GAP) { | ||
| 3101 | pgoff_t offset; | ||
| 3102 | struct page *page; | ||
| 3103 | struct buffer_head *bh = NULL; | ||
| 3104 | |||
| 3105 | offset = logical >> PAGE_SHIFT; | ||
| 3106 | page = find_get_page(inode->i_mapping, offset); | ||
| 3107 | if (!page || !page_has_buffers(page)) | ||
| 3108 | return EXT_CONTINUE; | ||
| 3109 | |||
| 3110 | bh = page_buffers(page); | ||
| 3111 | |||
| 3112 | if (!bh) | ||
| 3113 | return EXT_CONTINUE; | ||
| 3114 | |||
| 3115 | if (buffer_delay(bh)) { | ||
| 3116 | flags |= FIEMAP_EXTENT_DELALLOC; | ||
| 3117 | page_cache_release(page); | ||
| 3118 | } else { | ||
| 3119 | page_cache_release(page); | ||
| 3120 | return EXT_CONTINUE; | ||
| 3121 | } | ||
| 3122 | } | ||
| 3123 | |||
| 3124 | physical = (__u64)newex->ec_start << blksize_bits; | ||
| 3125 | length = (__u64)newex->ec_len << blksize_bits; | ||
| 3126 | |||
| 3127 | if (ex && ext4_ext_is_uninitialized(ex)) | ||
| 3128 | flags |= FIEMAP_EXTENT_UNWRITTEN; | ||
| 3129 | |||
| 3130 | /* | ||
| 3131 | * If this extent reaches EXT_MAX_BLOCK, it must be last. | ||
| 3132 | * | ||
| 3133 | * Or if ext4_ext_next_allocated_block is EXT_MAX_BLOCK, | ||
| 3134 | * this also indicates no more allocated blocks. | ||
| 3135 | * | ||
| 3136 | * XXX this might miss a single-block extent at EXT_MAX_BLOCK | ||
| 3137 | */ | ||
| 3138 | if (logical + length - 1 == EXT_MAX_BLOCK || | ||
| 3139 | ext4_ext_next_allocated_block(path) == EXT_MAX_BLOCK) | ||
| 3140 | flags |= FIEMAP_EXTENT_LAST; | ||
| 3141 | |||
| 3142 | error = fiemap_fill_next_extent(fieinfo, logical, physical, | ||
| 3143 | length, flags); | ||
| 3144 | if (error < 0) | ||
| 3145 | return error; | ||
| 3146 | if (error == 1) | ||
| 3147 | return EXT_BREAK; | ||
| 3148 | |||
| 3149 | return EXT_CONTINUE; | ||
| 3150 | } | ||
| 3151 | |||
| 3152 | /* fiemap flags we can handle specified here */ | ||
| 3153 | #define EXT4_FIEMAP_FLAGS (FIEMAP_FLAG_SYNC|FIEMAP_FLAG_XATTR) | ||
| 3154 | |||
| 3155 | int ext4_xattr_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo) | ||
| 3156 | { | ||
| 3157 | __u64 physical = 0; | ||
| 3158 | __u64 length; | ||
| 3159 | __u32 flags = FIEMAP_EXTENT_LAST; | ||
| 3160 | int blockbits = inode->i_sb->s_blocksize_bits; | ||
| 3161 | int error = 0; | ||
| 3162 | |||
| 3163 | /* in-inode? */ | ||
| 3164 | if (EXT4_I(inode)->i_state & EXT4_STATE_XATTR) { | ||
| 3165 | struct ext4_iloc iloc; | ||
| 3166 | int offset; /* offset of xattr in inode */ | ||
| 3167 | |||
| 3168 | error = ext4_get_inode_loc(inode, &iloc); | ||
| 3169 | if (error) | ||
| 3170 | return error; | ||
| 3171 | physical = iloc.bh->b_blocknr << blockbits; | ||
| 3172 | offset = EXT4_GOOD_OLD_INODE_SIZE + | ||
| 3173 | EXT4_I(inode)->i_extra_isize; | ||
| 3174 | physical += offset; | ||
| 3175 | length = EXT4_SB(inode->i_sb)->s_inode_size - offset; | ||
| 3176 | flags |= FIEMAP_EXTENT_DATA_INLINE; | ||
| 3177 | } else { /* external block */ | ||
| 3178 | physical = EXT4_I(inode)->i_file_acl << blockbits; | ||
| 3179 | length = inode->i_sb->s_blocksize; | ||
| 3180 | } | ||
| 3181 | |||
| 3182 | if (physical) | ||
| 3183 | error = fiemap_fill_next_extent(fieinfo, 0, physical, | ||
| 3184 | length, flags); | ||
| 3185 | return (error < 0 ? error : 0); | ||
| 3186 | } | ||
| 3187 | |||
| 3188 | int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | ||
| 3189 | __u64 start, __u64 len) | ||
| 3190 | { | ||
| 3191 | ext4_lblk_t start_blk; | ||
| 3192 | ext4_lblk_t len_blks; | ||
| 3193 | int error = 0; | ||
| 3194 | |||
| 3195 | /* fallback to generic here if not in extents fmt */ | ||
| 3196 | if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)) | ||
| 3197 | return generic_block_fiemap(inode, fieinfo, start, len, | ||
| 3198 | ext4_get_block); | ||
| 3199 | |||
| 3200 | if (fiemap_check_flags(fieinfo, EXT4_FIEMAP_FLAGS)) | ||
| 3201 | return -EBADR; | ||
| 3202 | |||
| 3203 | if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) { | ||
| 3204 | error = ext4_xattr_fiemap(inode, fieinfo); | ||
| 3205 | } else { | ||
| 3206 | start_blk = start >> inode->i_sb->s_blocksize_bits; | ||
| 3207 | len_blks = len >> inode->i_sb->s_blocksize_bits; | ||
| 3208 | |||
| 3209 | /* | ||
| 3210 | * Walk the extent tree gathering extent information. | ||
| 3211 | * ext4_ext_fiemap_cb will push extents back to user. | ||
| 3212 | */ | ||
| 3213 | down_write(&EXT4_I(inode)->i_data_sem); | ||
| 3214 | error = ext4_ext_walk_space(inode, start_blk, len_blks, | ||
| 3215 | ext4_ext_fiemap_cb, fieinfo); | ||
| 3216 | up_write(&EXT4_I(inode)->i_data_sem); | ||
| 3217 | } | ||
| 3218 | |||
| 3219 | return error; | ||
| 3220 | } | ||
| 3221 | |||
