Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
Pull ext4 updates from Ted Ts'o: "A large number of cleanups and bug fixes, with some (minor) journal optimizations" [ This got sent to me before -rc1, but was stuck in my spam folder. - Linus ] * tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: (67 commits) ext4: check s_chksum_driver when looking for bg csum presence ext4: move error report out of atomic context in ext4_init_block_bitmap() ext4: Replace open coded mdata csum feature to helper function ext4: delete useless comments about ext4_move_extents ext4: fix reservation overflow in ext4_da_write_begin ext4: add ext4_iget_normal() which is to be used for dir tree lookups ext4: don't orphan or truncate the boot loader inode ext4: grab missed write_count for EXT4_IOC_SWAP_BOOT ext4: optimize block allocation on grow indepth ext4: get rid of code duplication ext4: fix over-defensive complaint after journal abort ext4: fix return value of ext4_do_update_inode ext4: fix mmap data corruption when blocksize < pagesize vfs: fix data corruption when blocksize < pagesize for mmaped data ext4: fold ext4_nojournal_sops into ext4_sops ext4: support freezing ext2 (nojournal) file systems ext4: fold ext4_sync_fs_nojournal() into ext4_sync_fs() ext4: don't check quota format when there are no quota files jbd2: simplify calling convention around __jbd2_journal_clean_checkpoint_list jbd2: avoid pointless scanning of checkpoint lists ...
This commit is contained in:
48
fs/buffer.c
48
fs/buffer.c
@@ -993,7 +993,7 @@ init_page_buffers(struct page *page, struct block_device *bdev,
|
||||
*/
|
||||
static int
|
||||
grow_dev_page(struct block_device *bdev, sector_t block,
|
||||
pgoff_t index, int size, int sizebits)
|
||||
pgoff_t index, int size, int sizebits, gfp_t gfp)
|
||||
{
|
||||
struct inode *inode = bdev->bd_inode;
|
||||
struct page *page;
|
||||
@@ -1002,8 +1002,8 @@ grow_dev_page(struct block_device *bdev, sector_t block,
|
||||
int ret = 0; /* Will call free_more_memory() */
|
||||
gfp_t gfp_mask;
|
||||
|
||||
gfp_mask = mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS;
|
||||
gfp_mask |= __GFP_MOVABLE;
|
||||
gfp_mask = (mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS) | gfp;
|
||||
|
||||
/*
|
||||
* XXX: __getblk_slow() can not really deal with failure and
|
||||
* will endlessly loop on improvised global reclaim. Prefer
|
||||
@@ -1060,7 +1060,7 @@ failed:
|
||||
* that page was dirty, the buffers are set dirty also.
|
||||
*/
|
||||
static int
|
||||
grow_buffers(struct block_device *bdev, sector_t block, int size)
|
||||
grow_buffers(struct block_device *bdev, sector_t block, int size, gfp_t gfp)
|
||||
{
|
||||
pgoff_t index;
|
||||
int sizebits;
|
||||
@@ -1087,11 +1087,12 @@ grow_buffers(struct block_device *bdev, sector_t block, int size)
|
||||
}
|
||||
|
||||
/* Create a page with the proper size buffers.. */
|
||||
return grow_dev_page(bdev, block, index, size, sizebits);
|
||||
return grow_dev_page(bdev, block, index, size, sizebits, gfp);
|
||||
}
|
||||
|
||||
static struct buffer_head *
|
||||
__getblk_slow(struct block_device *bdev, sector_t block, int size)
|
||||
struct buffer_head *
|
||||
__getblk_slow(struct block_device *bdev, sector_t block,
|
||||
unsigned size, gfp_t gfp)
|
||||
{
|
||||
/* Size must be multiple of hard sectorsize */
|
||||
if (unlikely(size & (bdev_logical_block_size(bdev)-1) ||
|
||||
@@ -1113,13 +1114,14 @@ __getblk_slow(struct block_device *bdev, sector_t block, int size)
|
||||
if (bh)
|
||||
return bh;
|
||||
|
||||
ret = grow_buffers(bdev, block, size);
|
||||
ret = grow_buffers(bdev, block, size, gfp);
|
||||
if (ret < 0)
|
||||
return NULL;
|
||||
if (ret == 0)
|
||||
free_more_memory();
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(__getblk_slow);
|
||||
|
||||
/*
|
||||
* The relationship between dirty buffers and dirty pages:
|
||||
@@ -1373,24 +1375,25 @@ __find_get_block(struct block_device *bdev, sector_t block, unsigned size)
|
||||
EXPORT_SYMBOL(__find_get_block);
|
||||
|
||||
/*
|
||||
* __getblk will locate (and, if necessary, create) the buffer_head
|
||||
* __getblk_gfp() will locate (and, if necessary, create) the buffer_head
|
||||
* which corresponds to the passed block_device, block and size. The
|
||||
* returned buffer has its reference count incremented.
|
||||
*
|
||||
* __getblk() will lock up the machine if grow_dev_page's try_to_free_buffers()
|
||||
* attempt is failing. FIXME, perhaps?
|
||||
* __getblk_gfp() will lock up the machine if grow_dev_page's
|
||||
* try_to_free_buffers() attempt is failing. FIXME, perhaps?
|
||||
*/
|
||||
struct buffer_head *
|
||||
__getblk(struct block_device *bdev, sector_t block, unsigned size)
|
||||
__getblk_gfp(struct block_device *bdev, sector_t block,
|
||||
unsigned size, gfp_t gfp)
|
||||
{
|
||||
struct buffer_head *bh = __find_get_block(bdev, block, size);
|
||||
|
||||
might_sleep();
|
||||
if (bh == NULL)
|
||||
bh = __getblk_slow(bdev, block, size);
|
||||
bh = __getblk_slow(bdev, block, size, gfp);
|
||||
return bh;
|
||||
}
|
||||
EXPORT_SYMBOL(__getblk);
|
||||
EXPORT_SYMBOL(__getblk_gfp);
|
||||
|
||||
/*
|
||||
* Do async read-ahead on a buffer..
|
||||
@@ -1406,24 +1409,28 @@ void __breadahead(struct block_device *bdev, sector_t block, unsigned size)
|
||||
EXPORT_SYMBOL(__breadahead);
|
||||
|
||||
/**
|
||||
* __bread() - reads a specified block and returns the bh
|
||||
* __bread_gfp() - reads a specified block and returns the bh
|
||||
* @bdev: the block_device to read from
|
||||
* @block: number of block
|
||||
* @size: size (in bytes) to read
|
||||
*
|
||||
* @gfp: page allocation flag
|
||||
*
|
||||
* Reads a specified block, and returns buffer head that contains it.
|
||||
* The page cache can be allocated from non-movable area
|
||||
* not to prevent page migration if you set gfp to zero.
|
||||
* It returns NULL if the block was unreadable.
|
||||
*/
|
||||
struct buffer_head *
|
||||
__bread(struct block_device *bdev, sector_t block, unsigned size)
|
||||
__bread_gfp(struct block_device *bdev, sector_t block,
|
||||
unsigned size, gfp_t gfp)
|
||||
{
|
||||
struct buffer_head *bh = __getblk(bdev, block, size);
|
||||
struct buffer_head *bh = __getblk_gfp(bdev, block, size, gfp);
|
||||
|
||||
if (likely(bh) && !buffer_uptodate(bh))
|
||||
bh = __bread_slow(bh);
|
||||
return bh;
|
||||
}
|
||||
EXPORT_SYMBOL(__bread);
|
||||
EXPORT_SYMBOL(__bread_gfp);
|
||||
|
||||
/*
|
||||
* invalidate_bh_lrus() is called rarely - but not only at unmount.
|
||||
@@ -2082,6 +2089,7 @@ int generic_write_end(struct file *file, struct address_space *mapping,
|
||||
struct page *page, void *fsdata)
|
||||
{
|
||||
struct inode *inode = mapping->host;
|
||||
loff_t old_size = inode->i_size;
|
||||
int i_size_changed = 0;
|
||||
|
||||
copied = block_write_end(file, mapping, pos, len, copied, page, fsdata);
|
||||
@@ -2101,6 +2109,8 @@ int generic_write_end(struct file *file, struct address_space *mapping,
|
||||
unlock_page(page);
|
||||
page_cache_release(page);
|
||||
|
||||
if (old_size < pos)
|
||||
pagecache_isize_extended(inode, old_size, pos);
|
||||
/*
|
||||
* Don't mark the inode dirty under page lock. First, it unnecessarily
|
||||
* makes the holding time of page lock longer. Second, it forces lock
|
||||
|
Reference in New Issue
Block a user