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 | |
| 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>
| -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 | */ |
