Skip to content

Commit 0cfc925

Browse files
Eric Sandeentytso
authored andcommitted
ext4: re-inline ext4_rec_len_(to|from)_disk functions
commit 3d0518f, "ext4: New rec_len encoding for very large blocksizes" made several changes to this path, but from a perf perspective, un-inlining ext4_rec_len_from_disk() seems most significant. This function is called from ext4_check_dir_entry(), which on a file-creation workload is called extremely often. I tested this with bonnie: # bonnie++ -u root -s 0 -f -x 200 -d /mnt/test -n 32 (this does 200 iterations) and got this for the file creations: ext4 stock: Average = 21206.8 files/s ext4 inlined: Average = 22346.7 files/s (+5%) Signed-off-by: Eric Sandeen <sandeen@redhat.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
1 parent 8dd4204 commit 0cfc925

File tree

2 files changed

+37
-26
lines changed

2 files changed

+37
-26
lines changed

fs/ext4/ext4.h

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1411,6 +1411,43 @@ struct ext4_dir_entry_2 {
14111411
~EXT4_DIR_ROUND)
14121412
#define EXT4_MAX_REC_LEN ((1<<16)-1)
14131413

1414+
/*
1415+
* If we ever get support for fs block sizes > page_size, we'll need
1416+
* to remove the #if statements in the next two functions...
1417+
*/
1418+
static inline unsigned int
1419+
ext4_rec_len_from_disk(__le16 dlen, unsigned blocksize)
1420+
{
1421+
unsigned len = le16_to_cpu(dlen);
1422+
1423+
#if (PAGE_CACHE_SIZE >= 65536)
1424+
if (len == EXT4_MAX_REC_LEN || len == 0)
1425+
return blocksize;
1426+
return (len & 65532) | ((len & 3) << 16);
1427+
#else
1428+
return len;
1429+
#endif
1430+
}
1431+
1432+
static inline __le16 ext4_rec_len_to_disk(unsigned len, unsigned blocksize)
1433+
{
1434+
if ((len > blocksize) || (blocksize > (1 << 18)) || (len & 3))
1435+
BUG();
1436+
#if (PAGE_CACHE_SIZE >= 65536)
1437+
if (len < 65536)
1438+
return cpu_to_le16(len);
1439+
if (len == blocksize) {
1440+
if (blocksize == 65536)
1441+
return cpu_to_le16(EXT4_MAX_REC_LEN);
1442+
else
1443+
return cpu_to_le16(0);
1444+
}
1445+
return cpu_to_le16((len & 65532) | ((len >> 16) & 3));
1446+
#else
1447+
return cpu_to_le16(len);
1448+
#endif
1449+
}
1450+
14141451
/*
14151452
* Hash Tree Directory indexing
14161453
* (c) Daniel Phillips, 2001
@@ -1636,8 +1673,6 @@ extern long ext4_compat_ioctl(struct file *, unsigned int, unsigned long);
16361673
extern int ext4_ext_migrate(struct inode *);
16371674

16381675
/* namei.c */
1639-
extern unsigned int ext4_rec_len_from_disk(__le16 dlen, unsigned blocksize);
1640-
extern __le16 ext4_rec_len_to_disk(unsigned len, unsigned blocksize);
16411676
extern int ext4_orphan_add(handle_t *, struct inode *);
16421677
extern int ext4_orphan_del(handle_t *, struct inode *);
16431678
extern int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,

fs/ext4/namei.c

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -179,30 +179,6 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir,
179179
static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
180180
struct inode *inode);
181181

182-
unsigned int ext4_rec_len_from_disk(__le16 dlen, unsigned blocksize)
183-
{
184-
unsigned len = le16_to_cpu(dlen);
185-
186-
if (len == EXT4_MAX_REC_LEN || len == 0)
187-
return blocksize;
188-
return (len & 65532) | ((len & 3) << 16);
189-
}
190-
191-
__le16 ext4_rec_len_to_disk(unsigned len, unsigned blocksize)
192-
{
193-
if ((len > blocksize) || (blocksize > (1 << 18)) || (len & 3))
194-
BUG();
195-
if (len < 65536)
196-
return cpu_to_le16(len);
197-
if (len == blocksize) {
198-
if (blocksize == 65536)
199-
return cpu_to_le16(EXT4_MAX_REC_LEN);
200-
else
201-
return cpu_to_le16(0);
202-
}
203-
return cpu_to_le16((len & 65532) | ((len >> 16) & 3));
204-
}
205-
206182
/*
207183
* p is at least 6 bytes before the end of page
208184
*/

0 commit comments

Comments
 (0)