diff options
author | Eric Sandeen <sandeen@redhat.com> | 2010-08-05 01:46:37 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2010-08-05 01:46:37 -0400 |
commit | 0cfc9255a1efb0467de2162950197750570ecec0 (patch) | |
tree | 3bb2510d8b6d373d7db3a49bcda3cbbebd10330e /fs | |
parent | 8dd420466c7bfc459fa04680bd5690bfc41a4553 (diff) |
ext4: re-inline ext4_rec_len_(to|from)_disk functions
commit 3d0518f4, "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>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ext4/ext4.h | 39 | ||||
-rw-r--r-- | fs/ext4/namei.c | 24 |
2 files changed, 37 insertions, 26 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index ed14e1db0832..e03841d9f30b 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -1412,6 +1412,43 @@ struct ext4_dir_entry_2 { | |||
1412 | #define EXT4_MAX_REC_LEN ((1<<16)-1) | 1412 | #define EXT4_MAX_REC_LEN ((1<<16)-1) |
1413 | 1413 | ||
1414 | /* | 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 | |||
1451 | /* | ||
1415 | * Hash Tree Directory indexing | 1452 | * Hash Tree Directory indexing |
1416 | * (c) Daniel Phillips, 2001 | 1453 | * (c) Daniel Phillips, 2001 |
1417 | */ | 1454 | */ |
@@ -1636,8 +1673,6 @@ extern long ext4_compat_ioctl(struct file *, unsigned int, unsigned long); | |||
1636 | extern int ext4_ext_migrate(struct inode *); | 1673 | extern int ext4_ext_migrate(struct inode *); |
1637 | 1674 | ||
1638 | /* namei.c */ | 1675 | /* 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); | ||
1641 | extern int ext4_orphan_add(handle_t *, struct inode *); | 1676 | extern int ext4_orphan_add(handle_t *, struct inode *); |
1642 | extern int ext4_orphan_del(handle_t *, struct inode *); | 1677 | extern int ext4_orphan_del(handle_t *, struct inode *); |
1643 | extern int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash, | 1678 | extern int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash, |
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index ea8b59d96213..314c0d3b3fa9 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
@@ -179,30 +179,6 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, | |||
179 | static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry, | 179 | static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry, |
180 | struct inode *inode); | 180 | struct inode *inode); |
181 | 181 | ||
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 | |||
206 | /* | 182 | /* |
207 | * p is at least 6 bytes before the end of page | 183 | * p is at least 6 bytes before the end of page |
208 | */ | 184 | */ |