.. | .. |
---|
148 | 148 | struct super_block *sb = inode->i_sb; |
---|
149 | 149 | Indirect *p = chain; |
---|
150 | 150 | struct buffer_head *bh; |
---|
| 151 | + unsigned int key; |
---|
151 | 152 | int ret = -EIO; |
---|
152 | 153 | |
---|
153 | 154 | *err = 0; |
---|
.. | .. |
---|
156 | 157 | if (!p->key) |
---|
157 | 158 | goto no_block; |
---|
158 | 159 | while (--depth) { |
---|
159 | | - bh = sb_getblk(sb, le32_to_cpu(p->key)); |
---|
| 160 | + key = le32_to_cpu(p->key); |
---|
| 161 | + if (key > ext4_blocks_count(EXT4_SB(sb)->s_es)) { |
---|
| 162 | + /* the block was out of range */ |
---|
| 163 | + ret = -EFSCORRUPTED; |
---|
| 164 | + goto failure; |
---|
| 165 | + } |
---|
| 166 | + bh = sb_getblk(sb, key); |
---|
160 | 167 | if (unlikely(!bh)) { |
---|
161 | 168 | ret = -ENOMEM; |
---|
162 | 169 | goto failure; |
---|
.. | .. |
---|
642 | 649 | |
---|
643 | 650 | ext4_update_inode_fsync_trans(handle, inode, 1); |
---|
644 | 651 | count = ar.len; |
---|
| 652 | + |
---|
| 653 | + /* |
---|
| 654 | + * Update reserved blocks/metadata blocks after successful block |
---|
| 655 | + * allocation which had been deferred till now. |
---|
| 656 | + */ |
---|
| 657 | + if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) |
---|
| 658 | + ext4_da_update_reserve_space(inode, count, 1); |
---|
| 659 | + |
---|
645 | 660 | got_it: |
---|
646 | 661 | map->m_flags |= EXT4_MAP_MAPPED; |
---|
647 | 662 | map->m_pblk = le32_to_cpu(chain[depth-1].key); |
---|
.. | .. |
---|
705 | 720 | |
---|
706 | 721 | /* |
---|
707 | 722 | * Truncate transactions can be complex and absolutely huge. So we need to |
---|
708 | | - * be able to restart the transaction at a conventient checkpoint to make |
---|
| 723 | + * be able to restart the transaction at a convenient checkpoint to make |
---|
709 | 724 | * sure we don't overflow the journal. |
---|
710 | 725 | * |
---|
711 | 726 | * Try to extend this transaction for the purposes of truncation. If |
---|