mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-11-20 08:38:24 +08:00
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: ext4: Update documentation to remind users to update mke2fs.conf ext4: Fix small file fragmentation ext4: Initialize writeback_index to 0 when allocating a new inode ext4: make sure ext4_has_free_blocks returns 0 for ENOSPC ext4: journal credit fix for the delayed allocation's writepages() function ext4: Rework the ext4_da_writepages() function ext4: journal credits reservation fixes for DIO, fallocate ext4: journal credits reservation fixes for extent file writepage ext4: journal credits calulation cleanup and fix for non-extent writepage ext4: Fix bug where we return ENOSPC even though we have plenty of inodes ext4: don't try to resize if there are no reserved gdt blocks left ext4: Use ext4_discard_reservations instead of mballoc-specific call ext4: Fix ext4_dx_readdir hash collision handling ext4: Fix delalloc release block reservation for truncate ext4: Fix potential truncate BUG due to i_prealloc_list being non-empty ext4: Handle unwritten extent properly with delayed allocation
This commit is contained in:
commit
ee26562772
@ -26,6 +26,12 @@ Mailing list: linux-ext4@vger.kernel.org
|
||||
|
||||
git://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git
|
||||
|
||||
- Note that it is highly important to install the mke2fs.conf file
|
||||
that comes with the e2fsprogs 1.41.x sources in /etc/mke2fs.conf. If
|
||||
you have edited the /etc/mke2fs.conf file installed on your system,
|
||||
you will need to merge your changes with the version from e2fsprogs
|
||||
1.41.x.
|
||||
|
||||
- Create a new filesystem using the ext4dev filesystem type:
|
||||
|
||||
# mke2fs -t ext4dev /dev/hda1
|
||||
|
@ -1626,6 +1626,9 @@ ext4_fsblk_t ext4_has_free_blocks(struct ext4_sb_info *sbi,
|
||||
free_blocks =
|
||||
percpu_counter_sum_and_set(&sbi->s_freeblocks_counter);
|
||||
#endif
|
||||
if (free_blocks <= root_blocks)
|
||||
/* we don't have free space */
|
||||
return 0;
|
||||
if (free_blocks - root_blocks < nblocks)
|
||||
return free_blocks - root_blocks;
|
||||
return nblocks;
|
||||
|
@ -411,7 +411,7 @@ static int call_filldir(struct file * filp, void * dirent,
|
||||
get_dtype(sb, fname->file_type));
|
||||
if (error) {
|
||||
filp->f_pos = curr_pos;
|
||||
info->extra_fname = fname->next;
|
||||
info->extra_fname = fname;
|
||||
return error;
|
||||
}
|
||||
fname = fname->next;
|
||||
@ -450,11 +450,21 @@ static int ext4_dx_readdir(struct file * filp,
|
||||
* If there are any leftover names on the hash collision
|
||||
* chain, return them first.
|
||||
*/
|
||||
if (info->extra_fname &&
|
||||
call_filldir(filp, dirent, filldir, info->extra_fname))
|
||||
goto finished;
|
||||
if (info->extra_fname) {
|
||||
if (call_filldir(filp, dirent, filldir, info->extra_fname))
|
||||
goto finished;
|
||||
|
||||
if (!info->curr_node)
|
||||
info->extra_fname = NULL;
|
||||
info->curr_node = rb_next(info->curr_node);
|
||||
if (!info->curr_node) {
|
||||
if (info->next_hash == ~0) {
|
||||
filp->f_pos = EXT4_HTREE_EOF;
|
||||
goto finished;
|
||||
}
|
||||
info->curr_hash = info->next_hash;
|
||||
info->curr_minor_hash = 0;
|
||||
}
|
||||
} else if (!info->curr_node)
|
||||
info->curr_node = rb_first(&info->root);
|
||||
|
||||
while (1) {
|
||||
|
@ -1072,6 +1072,8 @@ extern void ext4_set_inode_flags(struct inode *);
|
||||
extern void ext4_get_inode_flags(struct ext4_inode_info *);
|
||||
extern void ext4_set_aops(struct inode *inode);
|
||||
extern int ext4_writepage_trans_blocks(struct inode *);
|
||||
extern int ext4_meta_trans_blocks(struct inode *, int nrblocks, int idxblocks);
|
||||
extern int ext4_chunk_trans_blocks(struct inode *, int nrblocks);
|
||||
extern int ext4_block_truncate_page(handle_t *handle,
|
||||
struct address_space *mapping, loff_t from);
|
||||
extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct page *page);
|
||||
@ -1227,6 +1229,8 @@ extern const struct inode_operations ext4_fast_symlink_inode_operations;
|
||||
/* extents.c */
|
||||
extern int ext4_ext_tree_init(handle_t *handle, struct inode *);
|
||||
extern int ext4_ext_writepage_trans_blocks(struct inode *, int);
|
||||
extern int ext4_ext_index_trans_blocks(struct inode *inode, int nrblocks,
|
||||
int chunk);
|
||||
extern int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
|
||||
ext4_lblk_t iblock,
|
||||
unsigned long max_blocks, struct buffer_head *bh_result,
|
||||
|
@ -216,7 +216,9 @@ extern int ext4_ext_calc_metadata_amount(struct inode *inode, int blocks);
|
||||
extern ext4_fsblk_t idx_pblock(struct ext4_extent_idx *);
|
||||
extern void ext4_ext_store_pblock(struct ext4_extent *, ext4_fsblk_t);
|
||||
extern int ext4_extent_tree_init(handle_t *, struct inode *);
|
||||
extern int ext4_ext_calc_credits_for_insert(struct inode *, struct ext4_ext_path *);
|
||||
extern int ext4_ext_calc_credits_for_single_extent(struct inode *inode,
|
||||
int num,
|
||||
struct ext4_ext_path *path);
|
||||
extern int ext4_ext_try_to_merge(struct inode *inode,
|
||||
struct ext4_ext_path *path,
|
||||
struct ext4_extent *);
|
||||
|
@ -51,6 +51,14 @@
|
||||
EXT4_XATTR_TRANS_BLOCKS - 2 + \
|
||||
2*EXT4_QUOTA_TRANS_BLOCKS(sb))
|
||||
|
||||
/*
|
||||
* Define the number of metadata blocks we need to account to modify data.
|
||||
*
|
||||
* This include super block, inode block, quota blocks and xattr blocks
|
||||
*/
|
||||
#define EXT4_META_TRANS_BLOCKS(sb) (EXT4_XATTR_TRANS_BLOCKS + \
|
||||
2*EXT4_QUOTA_TRANS_BLOCKS(sb))
|
||||
|
||||
/* Delete operations potentially hit one directory's namespace plus an
|
||||
* entire inode, plus arbitrary amounts of bitmap/indirection data. Be
|
||||
* generous. We can grow the delete transaction later if necessary. */
|
||||
|
@ -1747,54 +1747,61 @@ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode,
|
||||
}
|
||||
|
||||
/*
|
||||
* ext4_ext_calc_credits_for_insert:
|
||||
* This routine returns max. credits that the extent tree can consume.
|
||||
* It should be OK for low-performance paths like ->writepage()
|
||||
* To allow many writing processes to fit into a single transaction,
|
||||
* the caller should calculate credits under i_data_sem and
|
||||
* pass the actual path.
|
||||
* ext4_ext_calc_credits_for_single_extent:
|
||||
* This routine returns max. credits that needed to insert an extent
|
||||
* to the extent tree.
|
||||
* When pass the actual path, the caller should calculate credits
|
||||
* under i_data_sem.
|
||||
*/
|
||||
int ext4_ext_calc_credits_for_insert(struct inode *inode,
|
||||
int ext4_ext_calc_credits_for_single_extent(struct inode *inode, int nrblocks,
|
||||
struct ext4_ext_path *path)
|
||||
{
|
||||
int depth, needed;
|
||||
|
||||
if (path) {
|
||||
int depth = ext_depth(inode);
|
||||
int ret = 0;
|
||||
|
||||
/* probably there is space in leaf? */
|
||||
depth = ext_depth(inode);
|
||||
if (le16_to_cpu(path[depth].p_hdr->eh_entries)
|
||||
< le16_to_cpu(path[depth].p_hdr->eh_max))
|
||||
return 1;
|
||||
< le16_to_cpu(path[depth].p_hdr->eh_max)) {
|
||||
|
||||
/*
|
||||
* There are some space in the leaf tree, no
|
||||
* need to account for leaf block credit
|
||||
*
|
||||
* bitmaps and block group descriptor blocks
|
||||
* and other metadat blocks still need to be
|
||||
* accounted.
|
||||
*/
|
||||
/* 1 bitmap, 1 block group descriptor */
|
||||
ret = 2 + EXT4_META_TRANS_BLOCKS(inode->i_sb);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* given 32-bit logical block (4294967296 blocks), max. tree
|
||||
* can be 4 levels in depth -- 4 * 340^4 == 53453440000.
|
||||
* Let's also add one more level for imbalance.
|
||||
*/
|
||||
depth = 5;
|
||||
return ext4_chunk_trans_blocks(inode, nrblocks);
|
||||
}
|
||||
|
||||
/* allocation of new data block(s) */
|
||||
needed = 2;
|
||||
/*
|
||||
* How many index/leaf blocks need to change/allocate to modify nrblocks?
|
||||
*
|
||||
* if nrblocks are fit in a single extent (chunk flag is 1), then
|
||||
* in the worse case, each tree level index/leaf need to be changed
|
||||
* if the tree split due to insert a new extent, then the old tree
|
||||
* index/leaf need to be updated too
|
||||
*
|
||||
* If the nrblocks are discontiguous, they could cause
|
||||
* the whole tree split more than once, but this is really rare.
|
||||
*/
|
||||
int ext4_ext_index_trans_blocks(struct inode *inode, int nrblocks, int chunk)
|
||||
{
|
||||
int index;
|
||||
int depth = ext_depth(inode);
|
||||
|
||||
/*
|
||||
* tree can be full, so it would need to grow in depth:
|
||||
* we need one credit to modify old root, credits for
|
||||
* new root will be added in split accounting
|
||||
*/
|
||||
needed += 1;
|
||||
if (chunk)
|
||||
index = depth * 2;
|
||||
else
|
||||
index = depth * 3;
|
||||
|
||||
/*
|
||||
* Index split can happen, we would need:
|
||||
* allocate intermediate indexes (bitmap + group)
|
||||
* + change two blocks at each level, but root (already included)
|
||||
*/
|
||||
needed += (depth * 2) + (depth * 2);
|
||||
|
||||
/* any allocation modifies superblock */
|
||||
needed += 1;
|
||||
|
||||
return needed;
|
||||
return index;
|
||||
}
|
||||
|
||||
static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
|
||||
@ -1921,9 +1928,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
|
||||
correct_index = 1;
|
||||
credits += (ext_depth(inode)) + 1;
|
||||
}
|
||||
#ifdef CONFIG_QUOTA
|
||||
credits += 2 * EXT4_QUOTA_TRANS_BLOCKS(inode->i_sb);
|
||||
#endif
|
||||
|
||||
err = ext4_ext_journal_restart(handle, credits);
|
||||
if (err)
|
||||
@ -2805,7 +2810,7 @@ void ext4_ext_truncate(struct inode *inode)
|
||||
/*
|
||||
* probably first extent we're gonna free will be last in block
|
||||
*/
|
||||
err = ext4_writepage_trans_blocks(inode) + 3;
|
||||
err = ext4_writepage_trans_blocks(inode);
|
||||
handle = ext4_journal_start(inode, err);
|
||||
if (IS_ERR(handle))
|
||||
return;
|
||||
@ -2819,7 +2824,7 @@ void ext4_ext_truncate(struct inode *inode)
|
||||
down_write(&EXT4_I(inode)->i_data_sem);
|
||||
ext4_ext_invalidate_cache(inode);
|
||||
|
||||
ext4_mb_discard_inode_preallocations(inode);
|
||||
ext4_discard_reservation(inode);
|
||||
|
||||
/*
|
||||
* TODO: optimization is possible here.
|
||||
@ -2858,27 +2863,6 @@ out_stop:
|
||||
ext4_journal_stop(handle);
|
||||
}
|
||||
|
||||
/*
|
||||
* ext4_ext_writepage_trans_blocks:
|
||||
* calculate max number of blocks we could modify
|
||||
* in order to allocate new block for an inode
|
||||
*/
|
||||
int ext4_ext_writepage_trans_blocks(struct inode *inode, int num)
|
||||
{
|
||||
int needed;
|
||||
|
||||
needed = ext4_ext_calc_credits_for_insert(inode, NULL);
|
||||
|
||||
/* caller wants to allocate num blocks, but note it includes sb */
|
||||
needed = needed * num - (num - 1);
|
||||
|
||||
#ifdef CONFIG_QUOTA
|
||||
needed += 2 * EXT4_QUOTA_TRANS_BLOCKS(inode->i_sb);
|
||||
#endif
|
||||
|
||||
return needed;
|
||||
}
|
||||
|
||||
static void ext4_falloc_update_inode(struct inode *inode,
|
||||
int mode, loff_t new_size, int update_ctime)
|
||||
{
|
||||
@ -2939,10 +2923,9 @@ long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len)
|
||||
max_blocks = (EXT4_BLOCK_ALIGN(len + offset, blkbits) >> blkbits)
|
||||
- block;
|
||||
/*
|
||||
* credits to insert 1 extent into extent tree + buffers to be able to
|
||||
* modify 1 super block, 1 block bitmap and 1 group descriptor.
|
||||
* credits to insert 1 extent into extent tree
|
||||
*/
|
||||
credits = EXT4_DATA_TRANS_BLOCKS(inode->i_sb) + 3;
|
||||
credits = ext4_chunk_trans_blocks(inode, max_blocks);
|
||||
mutex_lock(&inode->i_mutex);
|
||||
retry:
|
||||
while (ret >= 0 && ret < max_blocks) {
|
||||
|
@ -351,7 +351,7 @@ find_close_to_parent:
|
||||
goto found_flexbg;
|
||||
}
|
||||
|
||||
if (best_flex < 0 ||
|
||||
if (flex_group[best_flex].free_inodes == 0 ||
|
||||
(flex_group[i].free_blocks >
|
||||
flex_group[best_flex].free_blocks &&
|
||||
flex_group[i].free_inodes))
|
||||
|
488
fs/ext4/inode.c
488
fs/ext4/inode.c
@ -41,6 +41,8 @@
|
||||
#include "acl.h"
|
||||
#include "ext4_extents.h"
|
||||
|
||||
#define MPAGE_DA_EXTENT_TAIL 0x01
|
||||
|
||||
static inline int ext4_begin_ordered_truncate(struct inode *inode,
|
||||
loff_t new_size)
|
||||
{
|
||||
@ -1005,6 +1007,9 @@ static int ext4_indirect_calc_metadata_amount(struct inode *inode, int blocks)
|
||||
*/
|
||||
static int ext4_calc_metadata_amount(struct inode *inode, int blocks)
|
||||
{
|
||||
if (!blocks)
|
||||
return 0;
|
||||
|
||||
if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)
|
||||
return ext4_ext_calc_metadata_amount(inode, blocks);
|
||||
|
||||
@ -1041,18 +1046,6 @@ static void ext4_da_update_reserve_space(struct inode *inode, int used)
|
||||
spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
|
||||
}
|
||||
|
||||
/* Maximum number of blocks we map for direct IO at once. */
|
||||
#define DIO_MAX_BLOCKS 4096
|
||||
/*
|
||||
* Number of credits we need for writing DIO_MAX_BLOCKS:
|
||||
* We need sb + group descriptor + bitmap + inode -> 4
|
||||
* For B blocks with A block pointers per block we need:
|
||||
* 1 (triple ind.) + (B/A/A + 2) (doubly ind.) + (B/A + 2) (indirect).
|
||||
* If we plug in 4096 for B and 256 for A (for 1KB block size), we get 25.
|
||||
*/
|
||||
#define DIO_CREDITS 25
|
||||
|
||||
|
||||
/*
|
||||
* The ext4_get_blocks_wrap() function try to look up the requested blocks,
|
||||
* and returns if the blocks are already mapped.
|
||||
@ -1164,19 +1157,23 @@ int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode, sector_t block,
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Maximum number of blocks we map for direct IO at once. */
|
||||
#define DIO_MAX_BLOCKS 4096
|
||||
|
||||
static int ext4_get_block(struct inode *inode, sector_t iblock,
|
||||
struct buffer_head *bh_result, int create)
|
||||
{
|
||||
handle_t *handle = ext4_journal_current_handle();
|
||||
int ret = 0, started = 0;
|
||||
unsigned max_blocks = bh_result->b_size >> inode->i_blkbits;
|
||||
int dio_credits;
|
||||
|
||||
if (create && !handle) {
|
||||
/* Direct IO write... */
|
||||
if (max_blocks > DIO_MAX_BLOCKS)
|
||||
max_blocks = DIO_MAX_BLOCKS;
|
||||
handle = ext4_journal_start(inode, DIO_CREDITS +
|
||||
2 * EXT4_QUOTA_TRANS_BLOCKS(inode->i_sb));
|
||||
dio_credits = ext4_chunk_trans_blocks(inode, max_blocks);
|
||||
handle = ext4_journal_start(inode, dio_credits);
|
||||
if (IS_ERR(handle)) {
|
||||
ret = PTR_ERR(handle);
|
||||
goto out;
|
||||
@ -1559,7 +1556,25 @@ static void ext4_da_release_space(struct inode *inode, int to_free)
|
||||
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
|
||||
int total, mdb, mdb_free, release;
|
||||
|
||||
if (!to_free)
|
||||
return; /* Nothing to release, exit */
|
||||
|
||||
spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
|
||||
|
||||
if (!EXT4_I(inode)->i_reserved_data_blocks) {
|
||||
/*
|
||||
* if there is no reserved blocks, but we try to free some
|
||||
* then the counter is messed up somewhere.
|
||||
* but since this function is called from invalidate
|
||||
* page, it's harmless to return without any action
|
||||
*/
|
||||
printk(KERN_INFO "ext4 delalloc try to release %d reserved "
|
||||
"blocks for inode %lu, but there is no reserved "
|
||||
"data blocks\n", to_free, inode->i_ino);
|
||||
spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
/* recalculate the number of metablocks still need to be reserved */
|
||||
total = EXT4_I(inode)->i_reserved_data_blocks - to_free;
|
||||
mdb = ext4_calc_metadata_amount(inode, total);
|
||||
@ -1613,11 +1628,13 @@ struct mpage_da_data {
|
||||
unsigned long first_page, next_page; /* extent of pages */
|
||||
get_block_t *get_block;
|
||||
struct writeback_control *wbc;
|
||||
int io_done;
|
||||
long pages_written;
|
||||
};
|
||||
|
||||
/*
|
||||
* mpage_da_submit_io - walks through extent of pages and try to write
|
||||
* them with __mpage_writepage()
|
||||
* them with writepage() call back
|
||||
*
|
||||
* @mpd->inode: inode
|
||||
* @mpd->first_page: first page of the extent
|
||||
@ -1632,18 +1649,11 @@ struct mpage_da_data {
|
||||
static int mpage_da_submit_io(struct mpage_da_data *mpd)
|
||||
{
|
||||
struct address_space *mapping = mpd->inode->i_mapping;
|
||||
struct mpage_data mpd_pp = {
|
||||
.bio = NULL,
|
||||
.last_block_in_bio = 0,
|
||||
.get_block = mpd->get_block,
|
||||
.use_writepage = 1,
|
||||
};
|
||||
int ret = 0, err, nr_pages, i;
|
||||
unsigned long index, end;
|
||||
struct pagevec pvec;
|
||||
|
||||
BUG_ON(mpd->next_page <= mpd->first_page);
|
||||
|
||||
pagevec_init(&pvec, 0);
|
||||
index = mpd->first_page;
|
||||
end = mpd->next_page - 1;
|
||||
@ -1661,8 +1671,9 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd)
|
||||
break;
|
||||
index++;
|
||||
|
||||
err = __mpage_writepage(page, mpd->wbc, &mpd_pp);
|
||||
|
||||
err = mapping->a_ops->writepage(page, mpd->wbc);
|
||||
if (!err)
|
||||
mpd->pages_written++;
|
||||
/*
|
||||
* In error case, we have to continue because
|
||||
* remaining pages are still locked
|
||||
@ -1673,9 +1684,6 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd)
|
||||
}
|
||||
pagevec_release(&pvec);
|
||||
}
|
||||
if (mpd_pp.bio)
|
||||
mpage_bio_submit(WRITE, mpd_pp.bio);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1698,7 +1706,7 @@ static void mpage_put_bnr_to_bhs(struct mpage_da_data *mpd, sector_t logical,
|
||||
int blocks = exbh->b_size >> inode->i_blkbits;
|
||||
sector_t pblock = exbh->b_blocknr, cur_logical;
|
||||
struct buffer_head *head, *bh;
|
||||
unsigned long index, end;
|
||||
pgoff_t index, end;
|
||||
struct pagevec pvec;
|
||||
int nr_pages, i;
|
||||
|
||||
@ -1741,6 +1749,13 @@ static void mpage_put_bnr_to_bhs(struct mpage_da_data *mpd, sector_t logical,
|
||||
if (buffer_delay(bh)) {
|
||||
bh->b_blocknr = pblock;
|
||||
clear_buffer_delay(bh);
|
||||
bh->b_bdev = inode->i_sb->s_bdev;
|
||||
} else if (buffer_unwritten(bh)) {
|
||||
bh->b_blocknr = pblock;
|
||||
clear_buffer_unwritten(bh);
|
||||
set_buffer_mapped(bh);
|
||||
set_buffer_new(bh);
|
||||
bh->b_bdev = inode->i_sb->s_bdev;
|
||||
} else if (buffer_mapped(bh))
|
||||
BUG_ON(bh->b_blocknr != pblock);
|
||||
|
||||
@ -1776,13 +1791,11 @@ static inline void __unmap_underlying_blocks(struct inode *inode,
|
||||
*
|
||||
* The function skips space we know is already mapped to disk blocks.
|
||||
*
|
||||
* The function ignores errors ->get_block() returns, thus real
|
||||
* error handling is postponed to __mpage_writepage()
|
||||
*/
|
||||
static void mpage_da_map_blocks(struct mpage_da_data *mpd)
|
||||
{
|
||||
int err = 0;
|
||||
struct buffer_head *lbh = &mpd->lbh;
|
||||
int err = 0, remain = lbh->b_size;
|
||||
sector_t next = lbh->b_blocknr;
|
||||
struct buffer_head new;
|
||||
|
||||
@ -1792,38 +1805,36 @@ static void mpage_da_map_blocks(struct mpage_da_data *mpd)
|
||||
if (buffer_mapped(lbh) && !buffer_delay(lbh))
|
||||
return;
|
||||
|
||||
while (remain) {
|
||||
new.b_state = lbh->b_state;
|
||||
new.b_blocknr = 0;
|
||||
new.b_size = remain;
|
||||
err = mpd->get_block(mpd->inode, next, &new, 1);
|
||||
if (err) {
|
||||
/*
|
||||
* Rather than implement own error handling
|
||||
* here, we just leave remaining blocks
|
||||
* unallocated and try again with ->writepage()
|
||||
*/
|
||||
break;
|
||||
}
|
||||
BUG_ON(new.b_size == 0);
|
||||
new.b_state = lbh->b_state;
|
||||
new.b_blocknr = 0;
|
||||
new.b_size = lbh->b_size;
|
||||
|
||||
if (buffer_new(&new))
|
||||
__unmap_underlying_blocks(mpd->inode, &new);
|
||||
/*
|
||||
* If we didn't accumulate anything
|
||||
* to write simply return
|
||||
*/
|
||||
if (!new.b_size)
|
||||
return;
|
||||
err = mpd->get_block(mpd->inode, next, &new, 1);
|
||||
if (err)
|
||||
return;
|
||||
BUG_ON(new.b_size == 0);
|
||||
|
||||
/*
|
||||
* If blocks are delayed marked, we need to
|
||||
* put actual blocknr and drop delayed bit
|
||||
*/
|
||||
if (buffer_delay(lbh))
|
||||
mpage_put_bnr_to_bhs(mpd, next, &new);
|
||||
if (buffer_new(&new))
|
||||
__unmap_underlying_blocks(mpd->inode, &new);
|
||||
|
||||
/* go for the remaining blocks */
|
||||
next += new.b_size >> mpd->inode->i_blkbits;
|
||||
remain -= new.b_size;
|
||||
}
|
||||
/*
|
||||
* If blocks are delayed marked, we need to
|
||||
* put actual blocknr and drop delayed bit
|
||||
*/
|
||||
if (buffer_delay(lbh) || buffer_unwritten(lbh))
|
||||
mpage_put_bnr_to_bhs(mpd, next, &new);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#define BH_FLAGS ((1 << BH_Uptodate) | (1 << BH_Mapped) | (1 << BH_Delay))
|
||||
#define BH_FLAGS ((1 << BH_Uptodate) | (1 << BH_Mapped) | \
|
||||
(1 << BH_Delay) | (1 << BH_Unwritten))
|
||||
|
||||
/*
|
||||
* mpage_add_bh_to_extent - try to add one more block to extent of blocks
|
||||
@ -1837,41 +1848,61 @@ static void mpage_da_map_blocks(struct mpage_da_data *mpd)
|
||||
static void mpage_add_bh_to_extent(struct mpage_da_data *mpd,
|
||||
sector_t logical, struct buffer_head *bh)
|
||||
{
|
||||
struct buffer_head *lbh = &mpd->lbh;
|
||||
sector_t next;
|
||||
size_t b_size = bh->b_size;
|
||||
struct buffer_head *lbh = &mpd->lbh;
|
||||
int nrblocks = lbh->b_size >> mpd->inode->i_blkbits;
|
||||
|
||||
next = lbh->b_blocknr + (lbh->b_size >> mpd->inode->i_blkbits);
|
||||
|
||||
/* check if thereserved journal credits might overflow */
|
||||
if (!(EXT4_I(mpd->inode)->i_flags & EXT4_EXTENTS_FL)) {
|
||||
if (nrblocks >= EXT4_MAX_TRANS_DATA) {
|
||||
/*
|
||||
* With non-extent format we are limited by the journal
|
||||
* credit available. Total credit needed to insert
|
||||
* nrblocks contiguous blocks is dependent on the
|
||||
* nrblocks. So limit nrblocks.
|
||||
*/
|
||||
goto flush_it;
|
||||
} else if ((nrblocks + (b_size >> mpd->inode->i_blkbits)) >
|
||||
EXT4_MAX_TRANS_DATA) {
|
||||
/*
|
||||
* Adding the new buffer_head would make it cross the
|
||||
* allowed limit for which we have journal credit
|
||||
* reserved. So limit the new bh->b_size
|
||||
*/
|
||||
b_size = (EXT4_MAX_TRANS_DATA - nrblocks) <<
|
||||
mpd->inode->i_blkbits;
|
||||
/* we will do mpage_da_submit_io in the next loop */
|
||||
}
|
||||
}
|
||||
/*
|
||||
* First block in the extent
|
||||
*/
|
||||
if (lbh->b_size == 0) {
|
||||
lbh->b_blocknr = logical;
|
||||
lbh->b_size = bh->b_size;
|
||||
lbh->b_size = b_size;
|
||||
lbh->b_state = bh->b_state & BH_FLAGS;
|
||||
return;
|
||||
}
|
||||
|
||||
next = lbh->b_blocknr + nrblocks;
|
||||
/*
|
||||
* Can we merge the block to our big extent?
|
||||
*/
|
||||
if (logical == next && (bh->b_state & BH_FLAGS) == lbh->b_state) {
|
||||
lbh->b_size += bh->b_size;
|
||||
lbh->b_size += b_size;
|
||||
return;
|
||||
}
|
||||
|
||||
flush_it:
|
||||
/*
|
||||
* We couldn't merge the block to our extent, so we
|
||||
* need to flush current extent and start new one
|
||||
*/
|
||||
mpage_da_map_blocks(mpd);
|
||||
|
||||
/*
|
||||
* Now start a new extent
|
||||
*/
|
||||
lbh->b_size = bh->b_size;
|
||||
lbh->b_state = bh->b_state & BH_FLAGS;
|
||||
lbh->b_blocknr = logical;
|
||||
mpage_da_submit_io(mpd);
|
||||
mpd->io_done = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1891,17 +1922,35 @@ static int __mpage_da_writepage(struct page *page,
|
||||
struct buffer_head *bh, *head, fake;
|
||||
sector_t logical;
|
||||
|
||||
if (mpd->io_done) {
|
||||
/*
|
||||
* Rest of the page in the page_vec
|
||||
* redirty then and skip then. We will
|
||||
* try to to write them again after
|
||||
* starting a new transaction
|
||||
*/
|
||||
redirty_page_for_writepage(wbc, page);
|
||||
unlock_page(page);
|
||||
return MPAGE_DA_EXTENT_TAIL;
|
||||
}
|
||||
/*
|
||||
* Can we merge this page to current extent?
|
||||
*/
|
||||
if (mpd->next_page != page->index) {
|
||||
/*
|
||||
* Nope, we can't. So, we map non-allocated blocks
|
||||
* and start IO on them using __mpage_writepage()
|
||||
* and start IO on them using writepage()
|
||||
*/
|
||||
if (mpd->next_page != mpd->first_page) {
|
||||
mpage_da_map_blocks(mpd);
|
||||
mpage_da_submit_io(mpd);
|
||||
/*
|
||||
* skip rest of the page in the page_vec
|
||||
*/
|
||||
mpd->io_done = 1;
|
||||
redirty_page_for_writepage(wbc, page);
|
||||
unlock_page(page);
|
||||
return MPAGE_DA_EXTENT_TAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1932,6 +1981,8 @@ static int __mpage_da_writepage(struct page *page,
|
||||
set_buffer_dirty(bh);
|
||||
set_buffer_uptodate(bh);
|
||||
mpage_add_bh_to_extent(mpd, logical, bh);
|
||||
if (mpd->io_done)
|
||||
return MPAGE_DA_EXTENT_TAIL;
|
||||
} else {
|
||||
/*
|
||||
* Page with regular buffer heads, just add all dirty ones
|
||||
@ -1940,8 +1991,12 @@ static int __mpage_da_writepage(struct page *page,
|
||||
bh = head;
|
||||
do {
|
||||
BUG_ON(buffer_locked(bh));
|
||||
if (buffer_dirty(bh))
|
||||
if (buffer_dirty(bh) &&
|
||||
(!buffer_mapped(bh) || buffer_delay(bh))) {
|
||||
mpage_add_bh_to_extent(mpd, logical, bh);
|
||||
if (mpd->io_done)
|
||||
return MPAGE_DA_EXTENT_TAIL;
|
||||
}
|
||||
logical++;
|
||||
} while ((bh = bh->b_this_page) != head);
|
||||
}
|
||||
@ -1960,22 +2015,13 @@ static int __mpage_da_writepage(struct page *page,
|
||||
*
|
||||
* This is a library function, which implements the writepages()
|
||||
* address_space_operation.
|
||||
*
|
||||
* In order to avoid duplication of logic that deals with partial pages,
|
||||
* multiple bio per page, etc, we find non-allocated blocks, allocate
|
||||
* them with minimal calls to ->get_block() and re-use __mpage_writepage()
|
||||
*
|
||||
* It's important that we call __mpage_writepage() only once for each
|
||||
* involved page, otherwise we'd have to implement more complicated logic
|
||||
* to deal with pages w/o PG_lock or w/ PG_writeback and so on.
|
||||
*
|
||||
* See comments to mpage_writepages()
|
||||
*/
|
||||
static int mpage_da_writepages(struct address_space *mapping,
|
||||
struct writeback_control *wbc,
|
||||
get_block_t get_block)
|
||||
{
|
||||
struct mpage_da_data mpd;
|
||||
long to_write;
|
||||
int ret;
|
||||
|
||||
if (!get_block)
|
||||
@ -1989,17 +2035,22 @@ static int mpage_da_writepages(struct address_space *mapping,
|
||||
mpd.first_page = 0;
|
||||
mpd.next_page = 0;
|
||||
mpd.get_block = get_block;
|
||||
mpd.io_done = 0;
|
||||
mpd.pages_written = 0;
|
||||
|
||||
to_write = wbc->nr_to_write;
|
||||
|
||||
ret = write_cache_pages(mapping, wbc, __mpage_da_writepage, &mpd);
|
||||
|
||||
/*
|
||||
* Handle last extent of pages
|
||||
*/
|
||||
if (mpd.next_page != mpd.first_page) {
|
||||
if (!mpd.io_done && mpd.next_page != mpd.first_page) {
|
||||
mpage_da_map_blocks(&mpd);
|
||||
mpage_da_submit_io(&mpd);
|
||||
}
|
||||
|
||||
wbc->nr_to_write = to_write - mpd.pages_written;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2204,63 +2255,95 @@ static int ext4_da_writepage(struct page *page,
|
||||
}
|
||||
|
||||
/*
|
||||
* For now just follow the DIO way to estimate the max credits
|
||||
* needed to write out EXT4_MAX_WRITEBACK_PAGES.
|
||||
* todo: need to calculate the max credits need for
|
||||
* extent based files, currently the DIO credits is based on
|
||||
* indirect-blocks mapping way.
|
||||
*
|
||||
* Probably should have a generic way to calculate credits
|
||||
* for DIO, writepages, and truncate
|
||||
* This is called via ext4_da_writepages() to
|
||||
* calulate the total number of credits to reserve to fit
|
||||
* a single extent allocation into a single transaction,
|
||||
* ext4_da_writpeages() will loop calling this before
|
||||
* the block allocation.
|
||||
*/
|
||||
#define EXT4_MAX_WRITEBACK_PAGES DIO_MAX_BLOCKS
|
||||
#define EXT4_MAX_WRITEBACK_CREDITS DIO_CREDITS
|
||||
|
||||
static int ext4_da_writepages_trans_blocks(struct inode *inode)
|
||||
{
|
||||
int max_blocks = EXT4_I(inode)->i_reserved_data_blocks;
|
||||
|
||||
/*
|
||||
* With non-extent format the journal credit needed to
|
||||
* insert nrblocks contiguous block is dependent on
|
||||
* number of contiguous block. So we will limit
|
||||
* number of contiguous block to a sane value
|
||||
*/
|
||||
if (!(inode->i_flags & EXT4_EXTENTS_FL) &&
|
||||
(max_blocks > EXT4_MAX_TRANS_DATA))
|
||||
max_blocks = EXT4_MAX_TRANS_DATA;
|
||||
|
||||
return ext4_chunk_trans_blocks(inode, max_blocks);
|
||||
}
|
||||
|
||||
static int ext4_da_writepages(struct address_space *mapping,
|
||||
struct writeback_control *wbc)
|
||||
struct writeback_control *wbc)
|
||||
{
|
||||
struct inode *inode = mapping->host;
|
||||
handle_t *handle = NULL;
|
||||
int needed_blocks;
|
||||
int ret = 0;
|
||||
long to_write;
|
||||
loff_t range_start = 0;
|
||||
struct inode *inode = mapping->host;
|
||||
int needed_blocks, ret = 0, nr_to_writebump = 0;
|
||||
long to_write, pages_skipped = 0;
|
||||
struct ext4_sb_info *sbi = EXT4_SB(mapping->host->i_sb);
|
||||
|
||||
/*
|
||||
* No pages to write? This is mainly a kludge to avoid starting
|
||||
* a transaction for special inodes like journal inode on last iput()
|
||||
* because that could violate lock ordering on umount
|
||||
*/
|
||||
if (!mapping->nrpages)
|
||||
if (!mapping->nrpages || !mapping_tagged(mapping, PAGECACHE_TAG_DIRTY))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Estimate the worse case needed credits to write out
|
||||
* EXT4_MAX_BUF_BLOCKS pages
|
||||
* Make sure nr_to_write is >= sbi->s_mb_stream_request
|
||||
* This make sure small files blocks are allocated in
|
||||
* single attempt. This ensure that small files
|
||||
* get less fragmented.
|
||||
*/
|
||||
needed_blocks = EXT4_MAX_WRITEBACK_CREDITS;
|
||||
if (wbc->nr_to_write < sbi->s_mb_stream_request) {
|
||||
nr_to_writebump = sbi->s_mb_stream_request - wbc->nr_to_write;
|
||||
wbc->nr_to_write = sbi->s_mb_stream_request;
|
||||
}
|
||||
|
||||
to_write = wbc->nr_to_write;
|
||||
if (!wbc->range_cyclic) {
|
||||
if (!wbc->range_cyclic)
|
||||
/*
|
||||
* If range_cyclic is not set force range_cont
|
||||
* and save the old writeback_index
|
||||
*/
|
||||
wbc->range_cont = 1;
|
||||
range_start = wbc->range_start;
|
||||
}
|
||||
|
||||
while (!ret && to_write) {
|
||||
range_start = wbc->range_start;
|
||||
pages_skipped = wbc->pages_skipped;
|
||||
|
||||
restart_loop:
|
||||
to_write = wbc->nr_to_write;
|
||||
while (!ret && to_write > 0) {
|
||||
|
||||
/*
|
||||
* we insert one extent at a time. So we need
|
||||
* credit needed for single extent allocation.
|
||||
* journalled mode is currently not supported
|
||||
* by delalloc
|
||||
*/
|
||||
BUG_ON(ext4_should_journal_data(inode));
|
||||
needed_blocks = ext4_da_writepages_trans_blocks(inode);
|
||||
|
||||
/* start a new transaction*/
|
||||
handle = ext4_journal_start(inode, needed_blocks);
|
||||
if (IS_ERR(handle)) {
|
||||
ret = PTR_ERR(handle);
|
||||
printk(KERN_EMERG "%s: jbd2_start: "
|
||||
"%ld pages, ino %lu; err %d\n", __func__,
|
||||
wbc->nr_to_write, inode->i_ino, ret);
|
||||
dump_stack();
|
||||
goto out_writepages;
|
||||
}
|
||||
if (ext4_should_order_data(inode)) {
|
||||
/*
|
||||
* With ordered mode we need to add
|
||||
* the inode to the journal handle
|
||||
* the inode to the journal handl
|
||||
* when we do block allocation.
|
||||
*/
|
||||
ret = ext4_jbd2_file_inode(handle, inode);
|
||||
@ -2268,20 +2351,20 @@ static int ext4_da_writepages(struct address_space *mapping,
|
||||
ext4_journal_stop(handle);
|
||||
goto out_writepages;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* set the max dirty pages could be write at a time
|
||||
* to fit into the reserved transaction credits
|
||||
*/
|
||||
if (wbc->nr_to_write > EXT4_MAX_WRITEBACK_PAGES)
|
||||
wbc->nr_to_write = EXT4_MAX_WRITEBACK_PAGES;
|
||||
|
||||
to_write -= wbc->nr_to_write;
|
||||
ret = mpage_da_writepages(mapping, wbc,
|
||||
ext4_da_get_block_write);
|
||||
ext4_da_get_block_write);
|
||||
ext4_journal_stop(handle);
|
||||
if (wbc->nr_to_write) {
|
||||
if (ret == MPAGE_DA_EXTENT_TAIL) {
|
||||
/*
|
||||
* got one extent now try with
|
||||
* rest of the pages
|
||||
*/
|
||||
to_write += wbc->nr_to_write;
|
||||
ret = 0;
|
||||
} else if (wbc->nr_to_write) {
|
||||
/*
|
||||
* There is no more writeout needed
|
||||
* or we requested for a noblocking writeout
|
||||
@ -2293,10 +2376,18 @@ static int ext4_da_writepages(struct address_space *mapping,
|
||||
wbc->nr_to_write = to_write;
|
||||
}
|
||||
|
||||
out_writepages:
|
||||
wbc->nr_to_write = to_write;
|
||||
if (range_start)
|
||||
if (wbc->range_cont && (pages_skipped != wbc->pages_skipped)) {
|
||||
/* We skipped pages in this loop */
|
||||
wbc->range_start = range_start;
|
||||
wbc->nr_to_write = to_write +
|
||||
wbc->pages_skipped - pages_skipped;
|
||||
wbc->pages_skipped = pages_skipped;
|
||||
goto restart_loop;
|
||||
}
|
||||
|
||||
out_writepages:
|
||||
wbc->nr_to_write = to_write - nr_to_writebump;
|
||||
wbc->range_start = range_start;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -3486,6 +3577,9 @@ void ext4_truncate(struct inode *inode)
|
||||
* modify the block allocation tree.
|
||||
*/
|
||||
down_write(&ei->i_data_sem);
|
||||
|
||||
ext4_discard_reservation(inode);
|
||||
|
||||
/*
|
||||
* The orphan list entry will now protect us from any crash which
|
||||
* occurs before the truncate completes, so it is now safe to propagate
|
||||
@ -3555,8 +3649,6 @@ do_indirects:
|
||||
;
|
||||
}
|
||||
|
||||
ext4_discard_reservation(inode);
|
||||
|
||||
up_write(&ei->i_data_sem);
|
||||
inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
|
||||
ext4_mark_inode_dirty(handle, inode);
|
||||
@ -4324,56 +4416,128 @@ int ext4_getattr(struct vfsmount *mnt, struct dentry *dentry,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* How many blocks doth make a writepage()?
|
||||
*
|
||||
* With N blocks per page, it may be:
|
||||
* N data blocks
|
||||
* 2 indirect block
|
||||
* 2 dindirect
|
||||
* 1 tindirect
|
||||
* N+5 bitmap blocks (from the above)
|
||||
* N+5 group descriptor summary blocks
|
||||
* 1 inode block
|
||||
* 1 superblock.
|
||||
* 2 * EXT4_SINGLEDATA_TRANS_BLOCKS for the quote files
|
||||
*
|
||||
* 3 * (N + 5) + 2 + 2 * EXT4_SINGLEDATA_TRANS_BLOCKS
|
||||
*
|
||||
* With ordered or writeback data it's the same, less the N data blocks.
|
||||
*
|
||||
* If the inode's direct blocks can hold an integral number of pages then a
|
||||
* page cannot straddle two indirect blocks, and we can only touch one indirect
|
||||
* and dindirect block, and the "5" above becomes "3".
|
||||
*
|
||||
* This still overestimates under most circumstances. If we were to pass the
|
||||
* start and end offsets in here as well we could do block_to_path() on each
|
||||
* block and work out the exact number of indirects which are touched. Pah.
|
||||
*/
|
||||
static int ext4_indirect_trans_blocks(struct inode *inode, int nrblocks,
|
||||
int chunk)
|
||||
{
|
||||
int indirects;
|
||||
|
||||
/* if nrblocks are contiguous */
|
||||
if (chunk) {
|
||||
/*
|
||||
* With N contiguous data blocks, it need at most
|
||||
* N/EXT4_ADDR_PER_BLOCK(inode->i_sb) indirect blocks
|
||||
* 2 dindirect blocks
|
||||
* 1 tindirect block
|
||||
*/
|
||||
indirects = nrblocks / EXT4_ADDR_PER_BLOCK(inode->i_sb);
|
||||
return indirects + 3;
|
||||
}
|
||||
/*
|
||||
* if nrblocks are not contiguous, worse case, each block touch
|
||||
* a indirect block, and each indirect block touch a double indirect
|
||||
* block, plus a triple indirect block
|
||||
*/
|
||||
indirects = nrblocks * 2 + 1;
|
||||
return indirects;
|
||||
}
|
||||
|
||||
static int ext4_index_trans_blocks(struct inode *inode, int nrblocks, int chunk)
|
||||
{
|
||||
if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL))
|
||||
return ext4_indirect_trans_blocks(inode, nrblocks, 0);
|
||||
return ext4_ext_index_trans_blocks(inode, nrblocks, 0);
|
||||
}
|
||||
/*
|
||||
* Account for index blocks, block groups bitmaps and block group
|
||||
* descriptor blocks if modify datablocks and index blocks
|
||||
* worse case, the indexs blocks spread over different block groups
|
||||
*
|
||||
* If datablocks are discontiguous, they are possible to spread over
|
||||
* different block groups too. If they are contiugous, with flexbg,
|
||||
* they could still across block group boundary.
|
||||
*
|
||||
* Also account for superblock, inode, quota and xattr blocks
|
||||
*/
|
||||
int ext4_meta_trans_blocks(struct inode *inode, int nrblocks, int chunk)
|
||||
{
|
||||
int groups, gdpblocks;
|
||||
int idxblocks;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
* How many index blocks need to touch to modify nrblocks?
|
||||
* The "Chunk" flag indicating whether the nrblocks is
|
||||
* physically contiguous on disk
|
||||
*
|
||||
* For Direct IO and fallocate, they calls get_block to allocate
|
||||
* one single extent at a time, so they could set the "Chunk" flag
|
||||
*/
|
||||
idxblocks = ext4_index_trans_blocks(inode, nrblocks, chunk);
|
||||
|
||||
ret = idxblocks;
|
||||
|
||||
/*
|
||||
* Now let's see how many group bitmaps and group descriptors need
|
||||
* to account
|
||||
*/
|
||||
groups = idxblocks;
|
||||
if (chunk)
|
||||
groups += 1;
|
||||
else
|
||||
groups += nrblocks;
|
||||
|
||||
gdpblocks = groups;
|
||||
if (groups > EXT4_SB(inode->i_sb)->s_groups_count)
|
||||
groups = EXT4_SB(inode->i_sb)->s_groups_count;
|
||||
if (groups > EXT4_SB(inode->i_sb)->s_gdb_count)
|
||||
gdpblocks = EXT4_SB(inode->i_sb)->s_gdb_count;
|
||||
|
||||
/* bitmaps and block group descriptor blocks */
|
||||
ret += groups + gdpblocks;
|
||||
|
||||
/* Blocks for super block, inode, quota and xattr blocks */
|
||||
ret += EXT4_META_TRANS_BLOCKS(inode->i_sb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calulate the total number of credits to reserve to fit
|
||||
* the modification of a single pages into a single transaction,
|
||||
* which may include multiple chunks of block allocations.
|
||||
*
|
||||
* This could be called via ext4_write_begin()
|
||||
*
|
||||
* We need to consider the worse case, when
|
||||
* one new block per extent.
|
||||
*/
|
||||
int ext4_writepage_trans_blocks(struct inode *inode)
|
||||
{
|
||||
int bpp = ext4_journal_blocks_per_page(inode);
|
||||
int indirects = (EXT4_NDIR_BLOCKS % bpp) ? 5 : 3;
|
||||
int ret;
|
||||
|
||||
if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)
|
||||
return ext4_ext_writepage_trans_blocks(inode, bpp);
|
||||
ret = ext4_meta_trans_blocks(inode, bpp, 0);
|
||||
|
||||
/* Account for data blocks for journalled mode */
|
||||
if (ext4_should_journal_data(inode))
|
||||
ret = 3 * (bpp + indirects) + 2;
|
||||
else
|
||||
ret = 2 * (bpp + indirects) + 2;
|
||||
|
||||
#ifdef CONFIG_QUOTA
|
||||
/* We know that structure was already allocated during DQUOT_INIT so
|
||||
* we will be updating only the data blocks + inodes */
|
||||
ret += 2*EXT4_QUOTA_TRANS_BLOCKS(inode->i_sb);
|
||||
#endif
|
||||
|
||||
ret += bpp;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the journal credits for a chunk of data modification.
|
||||
*
|
||||
* This is called from DIO, fallocate or whoever calling
|
||||
* ext4_get_blocks_wrap() to map/allocate a chunk of contigous disk blocks.
|
||||
*
|
||||
* journal buffers for data blocks are not included here, as DIO
|
||||
* and fallocate do no need to journal data buffers.
|
||||
*/
|
||||
int ext4_chunk_trans_blocks(struct inode *inode, int nrblocks)
|
||||
{
|
||||
return ext4_meta_trans_blocks(inode, nrblocks, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* The caller must have previously called ext4_reserve_inode_write().
|
||||
* Give this, we know that the caller already has write access to iloc->bh.
|
||||
|
@ -3281,6 +3281,35 @@ static void ext4_mb_use_group_pa(struct ext4_allocation_context *ac,
|
||||
mb_debug("use %u/%u from group pa %p\n", pa->pa_lstart-len, len, pa);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the prealloc space that have minimal distance
|
||||
* from the goal block. @cpa is the prealloc
|
||||
* space that is having currently known minimal distance
|
||||
* from the goal block.
|
||||
*/
|
||||
static struct ext4_prealloc_space *
|
||||
ext4_mb_check_group_pa(ext4_fsblk_t goal_block,
|
||||
struct ext4_prealloc_space *pa,
|
||||
struct ext4_prealloc_space *cpa)
|
||||
{
|
||||
ext4_fsblk_t cur_distance, new_distance;
|
||||
|
||||
if (cpa == NULL) {
|
||||
atomic_inc(&pa->pa_count);
|
||||
return pa;
|
||||
}
|
||||
cur_distance = abs(goal_block - cpa->pa_pstart);
|
||||
new_distance = abs(goal_block - pa->pa_pstart);
|
||||
|
||||
if (cur_distance < new_distance)
|
||||
return cpa;
|
||||
|
||||
/* drop the previous reference */
|
||||
atomic_dec(&cpa->pa_count);
|
||||
atomic_inc(&pa->pa_count);
|
||||
return pa;
|
||||
}
|
||||
|
||||
/*
|
||||
* search goal blocks in preallocated space
|
||||
*/
|
||||
@ -3290,7 +3319,8 @@ ext4_mb_use_preallocated(struct ext4_allocation_context *ac)
|
||||
int order, i;
|
||||
struct ext4_inode_info *ei = EXT4_I(ac->ac_inode);
|
||||
struct ext4_locality_group *lg;
|
||||
struct ext4_prealloc_space *pa;
|
||||
struct ext4_prealloc_space *pa, *cpa = NULL;
|
||||
ext4_fsblk_t goal_block;
|
||||
|
||||
/* only data can be preallocated */
|
||||
if (!(ac->ac_flags & EXT4_MB_HINT_DATA))
|
||||
@ -3333,6 +3363,13 @@ ext4_mb_use_preallocated(struct ext4_allocation_context *ac)
|
||||
/* The max size of hash table is PREALLOC_TB_SIZE */
|
||||
order = PREALLOC_TB_SIZE - 1;
|
||||
|
||||
goal_block = ac->ac_g_ex.fe_group * EXT4_BLOCKS_PER_GROUP(ac->ac_sb) +
|
||||
ac->ac_g_ex.fe_start +
|
||||
le32_to_cpu(EXT4_SB(ac->ac_sb)->s_es->s_first_data_block);
|
||||
/*
|
||||
* search for the prealloc space that is having
|
||||
* minimal distance from the goal block.
|
||||
*/
|
||||
for (i = order; i < PREALLOC_TB_SIZE; i++) {
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(pa, &lg->lg_prealloc_list[i],
|
||||
@ -3340,17 +3377,19 @@ ext4_mb_use_preallocated(struct ext4_allocation_context *ac)
|
||||
spin_lock(&pa->pa_lock);
|
||||
if (pa->pa_deleted == 0 &&
|
||||
pa->pa_free >= ac->ac_o_ex.fe_len) {
|
||||
atomic_inc(&pa->pa_count);
|
||||
ext4_mb_use_group_pa(ac, pa);
|
||||
spin_unlock(&pa->pa_lock);
|
||||
ac->ac_criteria = 20;
|
||||
rcu_read_unlock();
|
||||
return 1;
|
||||
|
||||
cpa = ext4_mb_check_group_pa(goal_block,
|
||||
pa, cpa);
|
||||
}
|
||||
spin_unlock(&pa->pa_lock);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
if (cpa) {
|
||||
ext4_mb_use_group_pa(ac, cpa);
|
||||
ac->ac_criteria = 20;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,8 @@ static int finish_range(handle_t *handle, struct inode *inode,
|
||||
* credit. But below we try to not accumalate too much
|
||||
* of them by restarting the journal.
|
||||
*/
|
||||
needed = ext4_ext_calc_credits_for_insert(inode, path);
|
||||
needed = ext4_ext_calc_credits_for_single_extent(inode,
|
||||
lb->last_block - lb->first_block + 1, path);
|
||||
|
||||
/*
|
||||
* Make sure the credit we accumalated is not really high
|
||||
|
@ -773,7 +773,8 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
|
||||
|
||||
if (reserved_gdb || gdb_off == 0) {
|
||||
if (!EXT4_HAS_COMPAT_FEATURE(sb,
|
||||
EXT4_FEATURE_COMPAT_RESIZE_INODE)){
|
||||
EXT4_FEATURE_COMPAT_RESIZE_INODE)
|
||||
|| !le16_to_cpu(es->s_reserved_gdt_blocks)) {
|
||||
ext4_warning(sb, __func__,
|
||||
"No reserved GDT blocks, can't resize");
|
||||
return -EPERM;
|
||||
|
@ -568,6 +568,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
|
||||
#endif
|
||||
ei->i_block_alloc_info = NULL;
|
||||
ei->vfs_inode.i_version = 1;
|
||||
ei->vfs_inode.i_data.writeback_index = 0;
|
||||
memset(&ei->i_cached_extent, 0, sizeof(struct ext4_ext_cache));
|
||||
INIT_LIST_HEAD(&ei->i_prealloc_list);
|
||||
spin_lock_init(&ei->i_prealloc_lock);
|
||||
|
Loading…
Reference in New Issue
Block a user