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

Commit 173f8654 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull ext4 updates from Ted Ts'o:
 "The usual collection of bug fixes and optimizations.  Perhaps of
  greatest note is a speed up for parallel, non-allocating DIO writes,
  since we no longer take the i_mutex lock in that case.

  For bug fixes, we fix an incorrect overhead calculation which caused
  slightly incorrect results for df(1) and statfs(2).  We also fixed
  bugs in the metadata checksum feature."

* tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: (23 commits)
  ext4: undo ext4_calc_metadata_amount if we fail to claim space
  ext4: don't let i_reserved_meta_blocks go negative
  ext4: fix hole punch failure when depth is greater than 0
  ext4: remove unnecessary argument from __ext4_handle_dirty_metadata()
  ext4: weed out ext4_write_super
  ext4: remove unnecessary superblock dirtying
  ext4: convert last user of ext4_mark_super_dirty() to ext4_handle_dirty_super()
  ext4: remove useless marking of superblock dirty
  ext4: fix ext4 mismerge back in January
  ext4: remove dynamic array size in ext4_chksum()
  ext4: remove unused variable in ext4_update_super()
  ext4: make quota as first class supported feature
  ext4: don't take the i_mutex lock when doing DIO overwrites
  ext4: add a new nolock flag in ext4_map_blocks
  ext4: split ext4_file_write into buffered IO and direct IO
  ext4: remove an unused statement in ext4_mb_get_buddy_page_lock()
  ext4: fix out-of-date comments in extents.c
  ext4: use s_csum_seed instead of i_csum_seed for xattr block
  ext4: use proper csum calculation in ext4_rename
  ext4: fix overhead calculation used by ext4_statfs()
  ...
parents cea8f46c 03179fe9
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -609,7 +609,8 @@ ext4_fsblk_t ext4_count_free_clusters(struct super_block *sb)
		if (bitmap_bh == NULL)
		if (bitmap_bh == NULL)
			continue;
			continue;


		x = ext4_count_free(bitmap_bh, sb->s_blocksize);
		x = ext4_count_free(bitmap_bh->b_data,
				    EXT4_BLOCKS_PER_GROUP(sb) / 8);
		printk(KERN_DEBUG "group %u: stored = %d, counted = %u\n",
		printk(KERN_DEBUG "group %u: stored = %d, counted = %u\n",
			i, ext4_free_group_clusters(sb, gdp), x);
			i, ext4_free_group_clusters(sb, gdp), x);
		bitmap_count += x;
		bitmap_count += x;
+3 −9
Original line number Original line Diff line number Diff line
@@ -11,24 +11,18 @@
#include <linux/jbd2.h>
#include <linux/jbd2.h>
#include "ext4.h"
#include "ext4.h"


#ifdef EXT4FS_DEBUG

static const int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
static const int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};


unsigned int ext4_count_free(struct buffer_head *map, unsigned int numchars)
unsigned int ext4_count_free(char *bitmap, unsigned int numchars)
{
{
	unsigned int i, sum = 0;
	unsigned int i, sum = 0;


	if (!map)
		return 0;
	for (i = 0; i < numchars; i++)
	for (i = 0; i < numchars; i++)
		sum += nibblemap[map->b_data[i] & 0xf] +
		sum += nibblemap[bitmap[i] & 0xf] +
			nibblemap[(map->b_data[i] >> 4) & 0xf];
			nibblemap[(bitmap[i] >> 4) & 0xf];
	return sum;
	return sum;
}
}


#endif  /*  EXT4FS_DEBUG  */

int ext4_inode_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
int ext4_inode_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
				  struct ext4_group_desc *gdp,
				  struct ext4_group_desc *gdp,
				  struct buffer_head *bh, int sz)
				  struct buffer_head *bh, int sz)
+12 −14
Original line number Original line Diff line number Diff line
@@ -571,6 +571,8 @@ enum {
#define EXT4_GET_BLOCKS_NO_NORMALIZE		0x0040
#define EXT4_GET_BLOCKS_NO_NORMALIZE		0x0040
	/* Request will not result in inode size update (user for fallocate) */
	/* Request will not result in inode size update (user for fallocate) */
#define EXT4_GET_BLOCKS_KEEP_SIZE		0x0080
#define EXT4_GET_BLOCKS_KEEP_SIZE		0x0080
	/* Do not take i_data_sem locking in ext4_map_blocks */
#define EXT4_GET_BLOCKS_NO_LOCK			0x0100


/*
/*
 * Flags used by ext4_free_blocks
 * Flags used by ext4_free_blocks
@@ -1161,8 +1163,7 @@ struct ext4_sb_info {
	unsigned long s_desc_per_block;	/* Number of group descriptors per block */
	unsigned long s_desc_per_block;	/* Number of group descriptors per block */
	ext4_group_t s_groups_count;	/* Number of groups in the fs */
	ext4_group_t s_groups_count;	/* Number of groups in the fs */
	ext4_group_t s_blockfile_groups;/* Groups acceptable for non-extent files */
	ext4_group_t s_blockfile_groups;/* Groups acceptable for non-extent files */
	unsigned long s_overhead_last;  /* Last calculated overhead */
	unsigned long s_overhead;  /* # of fs overhead clusters */
	unsigned long s_blocks_last;    /* Last seen block count */
	unsigned int s_cluster_ratio;	/* Number of blocks per cluster */
	unsigned int s_cluster_ratio;	/* Number of blocks per cluster */
	unsigned int s_cluster_bits;	/* log2 of s_cluster_ratio */
	unsigned int s_cluster_bits;	/* log2 of s_cluster_ratio */
	loff_t s_bitmap_maxbytes;	/* max bytes for bitmap files */
	loff_t s_bitmap_maxbytes;	/* max bytes for bitmap files */
@@ -1314,6 +1315,8 @@ static inline struct timespec ext4_current_time(struct inode *inode)
static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
{
{
	return ino == EXT4_ROOT_INO ||
	return ino == EXT4_ROOT_INO ||
		ino == EXT4_USR_QUOTA_INO ||
		ino == EXT4_GRP_QUOTA_INO ||
		ino == EXT4_JOURNAL_INO ||
		ino == EXT4_JOURNAL_INO ||
		ino == EXT4_RESIZE_INO ||
		ino == EXT4_RESIZE_INO ||
		(ino >= EXT4_FIRST_INO(sb) &&
		(ino >= EXT4_FIRST_INO(sb) &&
@@ -1496,7 +1499,8 @@ static inline void ext4_clear_state_flags(struct ext4_inode_info *ei)
					 EXT4_FEATURE_RO_COMPAT_BTREE_DIR |\
					 EXT4_FEATURE_RO_COMPAT_BTREE_DIR |\
					 EXT4_FEATURE_RO_COMPAT_HUGE_FILE |\
					 EXT4_FEATURE_RO_COMPAT_HUGE_FILE |\
					 EXT4_FEATURE_RO_COMPAT_BIGALLOC |\
					 EXT4_FEATURE_RO_COMPAT_BIGALLOC |\
					 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)
					 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM|\
					 EXT4_FEATURE_RO_COMPAT_QUOTA)


/*
/*
 * Default values for user and/or group using reserved blocks
 * Default values for user and/or group using reserved blocks
@@ -1663,10 +1667,12 @@ static inline u32 ext4_chksum(struct ext4_sb_info *sbi, u32 crc,
{
{
	struct {
	struct {
		struct shash_desc shash;
		struct shash_desc shash;
		char ctx[crypto_shash_descsize(sbi->s_chksum_driver)];
		char ctx[4];
	} desc;
	} desc;
	int err;
	int err;


	BUG_ON(crypto_shash_descsize(sbi->s_chksum_driver)!=sizeof(desc.ctx));

	desc.shash.tfm = sbi->s_chksum_driver;
	desc.shash.tfm = sbi->s_chksum_driver;
	desc.shash.flags = 0;
	desc.shash.flags = 0;
	*(u32 *)desc.ctx = crc;
	*(u32 *)desc.ctx = crc;
@@ -1852,7 +1858,7 @@ struct mmpd_data {
# define NORET_AND	noreturn,
# define NORET_AND	noreturn,


/* bitmap.c */
/* bitmap.c */
extern unsigned int ext4_count_free(struct buffer_head *, unsigned);
extern unsigned int ext4_count_free(char *bitmap, unsigned numchars);
void ext4_inode_bitmap_csum_set(struct super_block *sb, ext4_group_t group,
void ext4_inode_bitmap_csum_set(struct super_block *sb, ext4_group_t group,
				struct ext4_group_desc *gdp,
				struct ext4_group_desc *gdp,
				struct buffer_head *bh, int sz);
				struct buffer_head *bh, int sz);
@@ -2037,6 +2043,7 @@ extern int ext4_group_extend(struct super_block *sb,
extern int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count);
extern int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count);


/* super.c */
/* super.c */
extern int ext4_calculate_overhead(struct super_block *sb);
extern int ext4_superblock_csum_verify(struct super_block *sb,
extern int ext4_superblock_csum_verify(struct super_block *sb,
				       struct ext4_super_block *es);
				       struct ext4_super_block *es);
extern void ext4_superblock_csum_set(struct super_block *sb,
extern void ext4_superblock_csum_set(struct super_block *sb,
@@ -2321,15 +2328,6 @@ static inline void ext4_unlock_group(struct super_block *sb,
	spin_unlock(ext4_group_lock_ptr(sb, group));
	spin_unlock(ext4_group_lock_ptr(sb, group));
}
}


static inline void ext4_mark_super_dirty(struct super_block *sb)
{
	struct ext4_super_block *es = EXT4_SB(sb)->s_es;

	ext4_superblock_csum_set(sb, es);
	if (EXT4_SB(sb)->s_journal == NULL)
		sb->s_dirt =1;
}

/*
/*
 * Block validity checking
 * Block validity checking
 */
 */
+3 −5
Original line number Original line Diff line number Diff line
@@ -138,8 +138,7 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
}
}


int __ext4_handle_dirty_super(const char *where, unsigned int line,
int __ext4_handle_dirty_super(const char *where, unsigned int line,
			      handle_t *handle, struct super_block *sb,
			      handle_t *handle, struct super_block *sb)
			      int now)
{
{
	struct buffer_head *bh = EXT4_SB(sb)->s_sbh;
	struct buffer_head *bh = EXT4_SB(sb)->s_sbh;
	int err = 0;
	int err = 0;
@@ -151,11 +150,10 @@ int __ext4_handle_dirty_super(const char *where, unsigned int line,
		if (err)
		if (err)
			ext4_journal_abort_handle(where, line, __func__,
			ext4_journal_abort_handle(where, line, __func__,
						  bh, handle, err);
						  bh, handle, err);
	} else if (now) {
	} else {
		ext4_superblock_csum_set(sb,
		ext4_superblock_csum_set(sb,
				(struct ext4_super_block *)bh->b_data);
				(struct ext4_super_block *)bh->b_data);
		mark_buffer_dirty(bh);
		mark_buffer_dirty(bh);
	} else
	}
		sb->s_dirt = 1;
	return err;
	return err;
}
}
+14 −11
Original line number Original line Diff line number Diff line
@@ -87,14 +87,20 @@
#ifdef CONFIG_QUOTA
#ifdef CONFIG_QUOTA
/* Amount of blocks needed for quota update - we know that the structure was
/* Amount of blocks needed for quota update - we know that the structure was
 * allocated so we need to update only data block */
 * allocated so we need to update only data block */
#define EXT4_QUOTA_TRANS_BLOCKS(sb) (test_opt(sb, QUOTA) ? 1 : 0)
#define EXT4_QUOTA_TRANS_BLOCKS(sb) ((test_opt(sb, QUOTA) ||\
		EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)) ?\
		1 : 0)
/* Amount of blocks needed for quota insert/delete - we do some block writes
/* Amount of blocks needed for quota insert/delete - we do some block writes
 * but inode, sb and group updates are done only once */
 * but inode, sb and group updates are done only once */
#define EXT4_QUOTA_INIT_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_INIT_ALLOC*\
#define EXT4_QUOTA_INIT_BLOCKS(sb) ((test_opt(sb, QUOTA) ||\
		(EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)+3+DQUOT_INIT_REWRITE) : 0)
		EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)) ?\

		(DQUOT_INIT_ALLOC*(EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)\
#define EXT4_QUOTA_DEL_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_DEL_ALLOC*\
		 +3+DQUOT_INIT_REWRITE) : 0)
		(EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)+3+DQUOT_DEL_REWRITE) : 0)

#define EXT4_QUOTA_DEL_BLOCKS(sb) ((test_opt(sb, QUOTA) ||\
		EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)) ?\
		(DQUOT_DEL_ALLOC*(EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)\
		 +3+DQUOT_DEL_REWRITE) : 0)
#else
#else
#define EXT4_QUOTA_TRANS_BLOCKS(sb) 0
#define EXT4_QUOTA_TRANS_BLOCKS(sb) 0
#define EXT4_QUOTA_INIT_BLOCKS(sb) 0
#define EXT4_QUOTA_INIT_BLOCKS(sb) 0
@@ -213,8 +219,7 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
				 struct buffer_head *bh);
				 struct buffer_head *bh);


int __ext4_handle_dirty_super(const char *where, unsigned int line,
int __ext4_handle_dirty_super(const char *where, unsigned int line,
			      handle_t *handle, struct super_block *sb,
			      handle_t *handle, struct super_block *sb);
			      int now);


#define ext4_journal_get_write_access(handle, bh) \
#define ext4_journal_get_write_access(handle, bh) \
	__ext4_journal_get_write_access(__func__, __LINE__, (handle), (bh))
	__ext4_journal_get_write_access(__func__, __LINE__, (handle), (bh))
@@ -226,10 +231,8 @@ int __ext4_handle_dirty_super(const char *where, unsigned int line,
#define ext4_handle_dirty_metadata(handle, inode, bh) \
#define ext4_handle_dirty_metadata(handle, inode, bh) \
	__ext4_handle_dirty_metadata(__func__, __LINE__, (handle), (inode), \
	__ext4_handle_dirty_metadata(__func__, __LINE__, (handle), (inode), \
				     (bh))
				     (bh))
#define ext4_handle_dirty_super_now(handle, sb) \
	__ext4_handle_dirty_super(__func__, __LINE__, (handle), (sb), 1)
#define ext4_handle_dirty_super(handle, sb) \
#define ext4_handle_dirty_super(handle, sb) \
	__ext4_handle_dirty_super(__func__, __LINE__, (handle), (sb), 0)
	__ext4_handle_dirty_super(__func__, __LINE__, (handle), (sb))


handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks);
handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks);
int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle);
int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle);
Loading