Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 149b3060 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull ext4 updates from Ted Ts'o:
 "Mostly performance and bug fixes, plus some cleanups.  The one new
  feature this merge window is a new ioctl EXT4_IOC_SWAP_BOOT which
  allows installation of a hidden inode designed for boot loaders."

* tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: (50 commits)
  ext4: fix type-widening bug in inode table readahead code
  ext4: add check for inodes_count overflow in new resize ioctl
  ext4: fix Kconfig documentation for CONFIG_EXT4_DEBUG
  ext4: fix online resizing for ext3-compat file systems
  jbd2: trace when lock_buffer in do_get_write_access takes a long time
  ext4: mark metadata blocks using bh flags
  buffer: add BH_Prio and BH_Meta flags
  ext4: mark all metadata I/O with REQ_META
  ext4: fix readdir error in case inline_data+^dir_index.
  ext4: fix readdir error in the case of inline_data+dir_index
  jbd2: use kmem_cache_zalloc instead of kmem_cache_alloc/memset
  ext4: mext_insert_extents should update extent block checksum
  ext4: move quota initialization out of inode allocation transaction
  ext4: reserve xattr index for Rich ACL support
  jbd2: reduce journal_head size
  ext4: clear buffer_uninit flag when submitting IO
  ext4: use io_end for multiple bios
  ext4: make ext4_bio_write_page() use BH_Async_Write flags
  ext4: Use kstrtoul() instead of parse_strtoul()
  ext4: defragmentation code cleanup
  ...
parents b0ca4d01 0d606e2c
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -494,6 +494,17 @@ Files in /sys/fs/ext4/<devname>
 session_write_kbytes         This file is read-only and shows the number of
                              kilobytes of data that have been written to this
                              filesystem since it was mounted.

 reserved_clusters            This is RW file and contains number of reserved
                              clusters in the file system which will be used
                              in the specific situations to avoid costly
                              zeroout, unexpected ENOSPC, or possible data
                              loss. The default is 2% or 4096 clusters,
                              whichever is smaller and this can be changed
                              however it can never exceed number of clusters
                              in the file system. If there is not enough space
                              for the reserved space when mounting the file
                              mount will _not_ fail.
..............................................................................

Ioctls
@@ -587,6 +598,16 @@ Table of Ext4 specific ioctls
			      bitmaps and inode table, the userspace tool thus
			      just passes the new number of blocks.

EXT4_IOC_SWAP_BOOT	      Swap i_blocks and associated attributes
			      (like i_blocks, i_size, i_flags, ...) from
			      the specified inode with inode
			      EXT4_BOOT_LOADER_INO (#5). This is typically
			      used to store a boot loader in a secure part of
			      the filesystem, where it can't be changed by a
			      normal user by accident.
			      The data blocks of the previous boot loader
			      will be associated with the given inode.

..............................................................................

References
+5 −0
Original line number Diff line number Diff line
@@ -2987,6 +2987,11 @@ int _submit_bh(int rw, struct buffer_head *bh, unsigned long bio_flags)
	/* Take care of bh's that straddle the end of the device */
	guard_bh_eod(rw, bio, bh);

	if (buffer_meta(bh))
		rw |= REQ_META;
	if (buffer_prio(bh))
		rw |= REQ_PRIO;

	bio_get(bio);
	submit_bio(rw, bio);

+2 −1
Original line number Diff line number Diff line
@@ -71,4 +71,5 @@ config EXT4_DEBUG
	  Enables run-time debugging support for the ext4 filesystem.

	  If you select Y here, then you will be able to turn on debugging
	  with a command such as "echo 1 > /sys/kernel/debug/ext4/mballoc-debug"
	  with a command such as:
		echo 1 > /sys/module/ext4/parameters/mballoc_debug
+41 −12
Original line number Diff line number Diff line
@@ -29,6 +29,23 @@ static unsigned ext4_num_base_meta_clusters(struct super_block *sb,
 * balloc.c contains the blocks allocation and deallocation routines
 */

/*
 * Calculate block group number for a given block number
 */
ext4_group_t ext4_get_group_number(struct super_block *sb,
				   ext4_fsblk_t block)
{
	ext4_group_t group;

	if (test_opt2(sb, STD_GROUP_SIZE))
		group = (le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block) +
			 block) >>
			(EXT4_BLOCK_SIZE_BITS(sb) + EXT4_CLUSTER_BITS(sb) + 3);
	else
		ext4_get_group_no_and_offset(sb, block, &group, NULL);
	return group;
}

/*
 * Calculate the block group number and offset into the block/cluster
 * allocation bitmap, given a block number
@@ -49,14 +66,18 @@ void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,

}

static int ext4_block_in_group(struct super_block *sb, ext4_fsblk_t block,
/*
 * Check whether the 'block' lives within the 'block_group'. Returns 1 if so
 * and 0 otherwise.
 */
static inline int ext4_block_in_group(struct super_block *sb,
				      ext4_fsblk_t block,
				      ext4_group_t block_group)
{
	ext4_group_t actual_group;
	ext4_get_group_no_and_offset(sb, block, &actual_group, NULL);
	if (actual_group == block_group)
		return 1;
	return 0;

	actual_group = ext4_get_group_number(sb, block);
	return (actual_group == block_group) ? 1 : 0;
}

/* Return the number of clusters used for file system metadata; this
@@ -420,7 +441,7 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group)
	trace_ext4_read_block_bitmap_load(sb, block_group);
	bh->b_end_io = ext4_end_bitmap_read;
	get_bh(bh);
	submit_bh(READ, bh);
	submit_bh(READ | REQ_META | REQ_PRIO, bh);
	return bh;
verify:
	ext4_validate_block_bitmap(sb, desc, block_group, bh);
@@ -478,20 +499,22 @@ ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group)
static int ext4_has_free_clusters(struct ext4_sb_info *sbi,
				  s64 nclusters, unsigned int flags)
{
	s64 free_clusters, dirty_clusters, root_clusters;
	s64 free_clusters, dirty_clusters, rsv, resv_clusters;
	struct percpu_counter *fcc = &sbi->s_freeclusters_counter;
	struct percpu_counter *dcc = &sbi->s_dirtyclusters_counter;

	free_clusters  = percpu_counter_read_positive(fcc);
	dirty_clusters = percpu_counter_read_positive(dcc);
	resv_clusters = atomic64_read(&sbi->s_resv_clusters);

	/*
	 * r_blocks_count should always be multiple of the cluster ratio so
	 * we are safe to do a plane bit shift only.
	 */
	root_clusters = ext4_r_blocks_count(sbi->s_es) >> sbi->s_cluster_bits;
	rsv = (ext4_r_blocks_count(sbi->s_es) >> sbi->s_cluster_bits) +
	      resv_clusters;

	if (free_clusters - (nclusters + root_clusters + dirty_clusters) <
	if (free_clusters - (nclusters + rsv + dirty_clusters) <
					EXT4_FREECLUSTERS_WATERMARK) {
		free_clusters  = percpu_counter_sum_positive(fcc);
		dirty_clusters = percpu_counter_sum_positive(dcc);
@@ -499,7 +522,7 @@ static int ext4_has_free_clusters(struct ext4_sb_info *sbi,
	/* Check whether we have space after accounting for current
	 * dirty clusters & root reserved clusters.
	 */
	if (free_clusters >= ((root_clusters + nclusters) + dirty_clusters))
	if (free_clusters >= (rsv + nclusters + dirty_clusters))
		return 1;

	/* Hm, nope.  Are (enough) root reserved clusters available? */
@@ -508,6 +531,12 @@ static int ext4_has_free_clusters(struct ext4_sb_info *sbi,
	    capable(CAP_SYS_RESOURCE) ||
	    (flags & EXT4_MB_USE_ROOT_BLOCKS)) {

		if (free_clusters >= (nclusters + dirty_clusters +
				      resv_clusters))
			return 1;
	}
	/* No free blocks. Let's see if we can dip into reserved pool */
	if (flags & EXT4_MB_USE_RESERVED) {
		if (free_clusters >= (nclusters + dirty_clusters))
			return 1;
	}
+11 −9
Original line number Diff line number Diff line
@@ -46,7 +46,8 @@ static int is_dx_dir(struct inode *inode)
	if (EXT4_HAS_COMPAT_FEATURE(inode->i_sb,
		     EXT4_FEATURE_COMPAT_DIR_INDEX) &&
	    ((ext4_test_inode_flag(inode, EXT4_INODE_INDEX)) ||
	     ((inode->i_size >> sb->s_blocksize_bits) == 1)))
	     ((inode->i_size >> sb->s_blocksize_bits) == 1) ||
	     ext4_has_inline_data(inode)))
		return 1;

	return 0;
@@ -115,14 +116,6 @@ static int ext4_readdir(struct file *filp,
	int ret = 0;
	int dir_has_error = 0;

	if (ext4_has_inline_data(inode)) {
		int has_inline_data = 1;
		ret = ext4_read_inline_dir(filp, dirent, filldir,
					   &has_inline_data);
		if (has_inline_data)
			return ret;
	}

	if (is_dx_dir(inode)) {
		err = ext4_dx_readdir(filp, dirent, filldir);
		if (err != ERR_BAD_DX_DIR) {
@@ -136,6 +129,15 @@ static int ext4_readdir(struct file *filp,
		ext4_clear_inode_flag(file_inode(filp),
				      EXT4_INODE_INDEX);
	}

	if (ext4_has_inline_data(inode)) {
		int has_inline_data = 1;
		ret = ext4_read_inline_dir(filp, dirent, filldir,
					   &has_inline_data);
		if (has_inline_data)
			return ret;
	}

	stored = 0;
	offset = filp->f_pos & (sb->s_blocksize - 1);

Loading