Btrfs: just bunch of patches to ioctl.c
cover Btrfs: just bunch of patches to ioctl.c
1st patch, remove 16MiB restriction from extent_same ioctl(), by doing iterations over passed range.
I did not see much difference in performance, so it's just remove logic restriction.
2-3 pathes, update defrag ioctl():
- Fix bad behaviour with full rewriting all compressed
extents in defrag range. (that also make autodefrag on compressed fs not so expensive)
- Allow userspace specify NONE as target compression type, that allow users to uncompress files by defragmentation with btrfs-progs
- Make defrag ioctl understood requested compression type and current compression type of extents, to make btrfs fi def -rc<type> idempotent operation.
i.e. now possible to say, make all extents compressed with lzo, and btrfs will not recompress lzo compressed data.
Same for zlib, zstd, none.
(patch to btrfs-progs in PR on kdave GitHub).
4th patch, reduce size of struct btrfs_inode
- btrfs_inode store fields like: prop_compress, defrag_compress and after 3rd patch, change_compress.
They use unsigned as a type, and use 12 bytes in sum. But change_compress is a bitflag, and prop_compress/defrag_compress only store compression type, that currently use 0-3 of 2^32-1.
So, set a bitfields on that vars, and reduce size of btrfs_inode:
1136 -> 1128.
Timofey Titovets (4):
Btrfs: btrfs_dedupe_file_range() ioctl, remove 16MiB restriction
Btrfs: make should_defrag_range() understood compressed extents
Btrfs: allow btrfs_defrag_file() uncompress files on defragmentation
Btrfs: reduce size of struct btrfs_inode
fs/btrfs/btrfs_inode.h | 5 +- fs/btrfs/inode.c | 4 +- fs/btrfs/ioctl.c | 203 +++++++++++++++++++++++++++++++------------------ 3 files changed, 133 insertions(+), 79 deletions(-)
Signature · 1 line
2.15.1
PATCH RESEND 1/4 Btrfs: btrfs_dedupe_file_range() ioctl, remove 16MiB restriction
At now btrfs_dedupe_file_range() restricted to 16MiB range for limit locking time and memory requirement for dedup ioctl()
For too big input range code silently set range to 16MiB
Let's remove that restriction by do iterating over dedup range. That's backward compatible and will not change anything for request less then 16MiB.
Changes:
v1 -> v2:
- Refactor btrfs_cmp_data_prepare and btrfs_extent_same
- Store memory of pages array between iterations
- Lock inodes once, not on each iteration
- Small inplace cleanups
--- fs/btrfs/ioctl.c | 160 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 94 insertions(+), 66 deletions(-)
fs/btrfs/ioctl.c +94 -66
@@ -2965,8 +2965,8 @@ static void btrfs_cmp_data_free(struct cmp_pages *cmp)put_page (pg); } } -kfree (cmp->src_pages); -kfree (cmp->dst_pages); + + cmp->num_pages =0 ; } static int btrfs_cmp_data_prepare(struct inode *src, u64 loff,
@@ -2974,41 +2974,22 @@ static int btrfs_cmp_data_prepare(struct inode *src, u64 loff, u64 len, struct cmp_pages *cmp) { int ret; -int num_pages =PAGE_ALIGN (len) >>PAGE_SHIFT ; -struct page **src_pgarr, **dst_pgarr; - -/* -* We must gather up all the pages before we initiate our -* extent locking. We use an array for the page pointers. Size -* of the array is bounded by len, which is in turn bounded by -* BTRFS_MAX_DEDUPE_LEN. -*/ - src_pgarr =kcalloc (num_pages,sizeof (struct page *),GFP_KERNEL ); - dst_pgarr =kcalloc (num_pages,sizeof (struct page *),GFP_KERNEL ); -if (!src_pgarr || !dst_pgarr) { -kfree (src_pgarr); -kfree (dst_pgarr); -return -ENOMEM ; - } - cmp->num_pages = num_pages; - cmp->src_pages = src_pgarr; - cmp->dst_pages = dst_pgarr;/* * If deduping ranges in the same inode, locking rules make it mandatory * to always lock pages in ascending order to avoid deadlocks with * concurrent tasks (such as starting writeback/delalloc). */ -if (src == dst && dst_loff < loff) { -swap (src_pgarr, dst_pgarr); +if (src == dst && dst_loff < loff)swap (loff, dst_loff); - } - ret =gather_extent_pages (src, src_pgarr, cmp->num_pages, loff); + cmp->num_pages =PAGE_ALIGN (len) >>PAGE_SHIFT ; + + ret =gather_extent_pages (src, cmp->src_pages, cmp->num_pages, loff);if (ret) goto out; - ret =gather_extent_pages (dst, dst_pgarr, cmp->num_pages, dst_loff); + ret =gather_extent_pages (dst, cmp->dst_pages, cmp->num_pages, dst_loff); out:if (ret)
@@ -3078,31 +3059,23 @@ static int extent_same_check_offsets(struct inode *inode, u64 off, u64 *plen,return 0 ; } -static int btrfs_extent_same (struct inode *src,u64 loff,u64 olen, -struct inode *dst,u64 dst_loff) +static int __btrfs_extent_same (struct inode *src,u64 loff,u64 olen, +struct inode *dst,u64 dst_loff, +struct cmp_pages *cmp) {int ret;u64 len = olen; -struct cmp_pages cmp;bool same_inode = (src == dst);u64 same_lock_start =0 ;u64 same_lock_len =0 ; -if (len ==0 ) -return 0 ; - -if (same_inode) -inode_lock (src); -else -btrfs_double_inode_lock (src, dst); - ret =extent_same_check_offsets (src, loff, &len, olen);if (ret) - goto out_unlock; +return ret; ret =extent_same_check_offsets (dst, dst_loff, &len, olen);if (ret) - goto out_unlock; +return ret;if (same_inode) {/*
@@ -3119,32 +3092,21 @@ static int btrfs_extent_same(struct inode *src, u64 loff, u64 olen,* allow an unaligned length so long as it ends at * i_size. */ -if (len != olen) { - ret = -EINVAL ; - goto out_unlock; - } +if (len != olen) +return -EINVAL ;/* Check for overlapping ranges */ -if (dst_loff + len > loff && dst_loff < loff + len) { - ret = -EINVAL ; - goto out_unlock; - } +if (dst_loff + len > loff && dst_loff < loff + len) +return -EINVAL ; same_lock_start =min_t (u64, loff, dst_loff); same_lock_len =max_t (u64, loff, dst_loff) + len - same_lock_start; } -/* don't make the dst file partly checksummed */ -if ((BTRFS_I (src)->flags &BTRFS_INODE_NODATASUM ) != - (BTRFS_I (dst)->flags &BTRFS_INODE_NODATASUM )) { - ret = -EINVAL ; - goto out_unlock; - } - again: - ret =btrfs_cmp_data_prepare (src, loff, dst, dst_loff, olen, &cmp); + ret =btrfs_cmp_data_prepare (src, loff, dst, dst_loff, olen, cmp);if (ret) - goto out_unlock; +return ret;if (same_inode) ret = lock_extent_range(src, same_lock_start, same_lock_len,
@@ -3165,7 +3127,7 @@ static int btrfs_extent_same(struct inode *src, u64 loff, u64 olen,* Ranges in the io trees already unlocked. Now unlock all * pages before waiting for all IO to complete. */ -btrfs_cmp_data_free (&cmp); +btrfs_cmp_data_free (cmp);if (same_inode) {btrfs_wait_ordered_range (src, same_lock_start, same_lock_len);
@@ -3178,12 +3140,12 @@ static int btrfs_extent_same(struct inode *src, u64 loff, u64 olen,ASSERT (ret ==0 );if (WARN_ON (ret)) {/* ranges in the io trees already unlocked */ -btrfs_cmp_data_free (&cmp); +btrfs_cmp_data_free (cmp);return ret; }/* pass original length for comparison so we stay within i_size */ - ret =btrfs_cmp_data (olen, &cmp); + ret =btrfs_cmp_data (olen, cmp);if (ret ==0 ) ret =btrfs_clone (src, dst, loff, olen, len, dst_loff,1 );
@@ -3193,8 +3155,79 @@ static int btrfs_extent_same(struct inode *src, u64 loff, u64 olen,else btrfs_double_extent_unlock (src, loff, dst, dst_loff, len); -btrfs_cmp_data_free (&cmp); -out_unlock: +btrfs_cmp_data_free (cmp); + +return ret; +} + +#define BTRFS_MAX_DEDUPE_LEN SZ_16M + +static int btrfs_extent_same (struct inode *src,u64 loff,u64 olen, +struct inode *dst,u64 dst_loff) +{ +int ret; +int num_pages; +bool same_inode = (src == dst); +u64 i, tail_len, chunk_count; +struct cmp_pages cmp; + +if (olen ==0 ) +return 0 ; + +/* don't make the dst file partly checksummed */ +if ((BTRFS_I (src)->flags &BTRFS_INODE_NODATASUM ) != + (BTRFS_I (dst)->flags &BTRFS_INODE_NODATASUM )) { +return -EINVAL ; + } + +if (same_inode) +inode_lock (src); +else +btrfs_double_inode_lock (src, dst); + + tail_len = olen %BTRFS_MAX_DEDUPE_LEN ; + chunk_count =div_u64 (olen,BTRFS_MAX_DEDUPE_LEN ); + +if (chunk_count >0 ) { + num_pages =PAGE_ALIGN (BTRFS_MAX_DEDUPE_LEN ) >>PAGE_SHIFT ; + }else { + num_pages =PAGE_ALIGN (tail_len) >>PAGE_SHIFT ; + } +/* +* We must gather up all the pages before we initiate our +* extent locking. We use an array for the page pointers. Size +* of the array is bounded by len, which is in turn bounded by +* BTRFS_MAX_DEDUPE_LEN. +*/ + ret = -ENOMEM ; + cmp.src_pages =kcalloc (num_pages,sizeof (struct page *), +GFP_KERNEL ); +if (!cmp.src_pages) + goto out; + cmp.dst_pages =kcalloc (num_pages,sizeof (struct page *), +GFP_KERNEL ); +if (!cmp.dst_pages) + goto out; + + +for (i =0 ; i < chunk_count; i++) { + ret =__btrfs_extent_same (src, loff,BTRFS_MAX_DEDUPE_LEN , + dst, dst_loff, &cmp); +if (ret) + goto out; + + loff +=BTRFS_MAX_DEDUPE_LEN ; + dst_loff +=BTRFS_MAX_DEDUPE_LEN ; + } + +if (tail_len >0 ) + ret =__btrfs_extent_same (src, loff, tail_len, + dst, dst_loff, &cmp); + +out: +kfree (cmp.src_pages); +kfree (cmp.dst_pages); +if (same_inode)inode_unlock (src);else
@@ -3203,8 +3236,6 @@ static int btrfs_extent_same(struct inode *src, u64 loff, u64 olen,return ret; } -#define BTRFS_MAX_DEDUPE_LEN SZ_16M -ssize_t btrfs_dedupe_file_range (struct file *src_file,u64 loff,u64 olen,struct file *dst_file,u64 dst_loff) {
@@ -3213,9 +3244,6 @@ ssize_t btrfs_dedupe_file_range(struct file *src_file, u64 loff, u64 olen,u64 bs =BTRFS_I (src)->root->fs_info->sb->s_blocksize;ssize_t res; -if (olen >BTRFS_MAX_DEDUPE_LEN ) - olen =BTRFS_MAX_DEDUPE_LEN ; -if (WARN_ON_ONCE (bs <PAGE_SIZE )) {/* * Btrfs does not support blocksize < page_size. As a
Signature · 1 line
2.15.1
Re: [PATCH 1/4] [RESEND] Btrfs: btrfs_dedupe_file_range() ioctl, remove 16MiB restriction
Quoted 9 lines · Timofey Titovets
At now
btrfs_dedupe_file_range()restricted to 16MiB range for limit locking time and memory requirement for dedupioctl()For too big input range code silently set range to 16MiB
Let's remove that restriction by do iterating over dedup range. That's backward compatible and will not change anything for request less then 16MiB.
Quoted 6 lines
Changes:
v1 -> v2:
- Refactorbtrfs_cmp_data_prepareandbtrfs_extent_same
- Store memory of pages array between iterations
- Lock inodes once, not on each iteration
- Small inplace cleanups
I think this patch should be split into more, there are several logical changes mixed together.
I can add the patch to for-next to see if there are any problems caught by the existing test, but will expect more revisions of the patch. I don't see any fundamental problems so far.
Suggested changes:
* factor out __btrfs_extent_same
* adjust parameters if needed by the followup patches
* add the chunk counting logic
* any other cleanups
Re: [PATCH 1/4] [RESEND] Btrfs: btrfs_dedupe_file_range() ioctl, remove 16MiB restriction
чт, 26 апр. 2018 г. в 17:05, David Sterba <[email protected]>:
Quoted 24 lines · Timofey Titovets
Quoted 9 lines
At now
btrfs_dedupe_file_range()restricted to 16MiB range for limit locking time and memory requirement for dedupioctl()For too big input range code silently set range to 16MiB
Let's remove that restriction by do iterating over dedup range. That's backward compatible and will not change anything for request less then 16MiB.
Quoted 6 lines
Changes:
v1 -> v2:
- Refactorbtrfs_cmp_data_prepareandbtrfs_extent_same
- Store memory of pages array between iterations
- Lock inodes once, not on each iteration
- Small inplace cleanupsI think this patch should be split into more, there are several logical changes mixed together.
I can add the patch to for-next to see if there are any problems caught by the existing test, but will expect more revisions of the patch. I don't see any fundamental problems so far.
Quoted 5 lines
Suggested changes:
* factor out__btrfs_extent_same
* adjust parameters if needed by the followup patches
* add the chunk counting logic
* any other cleanups
Thanks, i will try split it out.
Signature · 2 lines
Have a nice day, Timofey.
PATCH RESEND 2/4 Btrfs: make should_defrag_range() understood compressed extents
In reply to Timofey Titovets Both, defrag ioctl and autodefrag - call btrfs_defrag_file() for file defragmentation.
Kernel default target extent size - 256KiB.
Btrfs progs default - 32MiB.
Both bigger then maximum size of compressed extent - 128KiB. That lead to rewrite all compressed data on disk.
Fix that by check compression extents with different logic.
As addition, make should_defrag_range() understood compressed extent type, if requested target compression are same as current extent compression type. Just don't recompress/rewrite extents.
To avoid useless recompression of compressed extents.
--- fs/btrfs/ioctl.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-)
fs/btrfs/ioctl.c +25 -3
@@ -1008,7 +1008,7 @@ static bool defrag_check_next_extent(struct inode *inode, struct extent_map *em)static int should_defrag_range (struct inode *inode,u64 start,u32 thresh,u64 *last_len,u64 *skip,u64 *defrag_end, -int compress) +int compress,int compress_type) {struct extent_map *em;int ret =1 ;
@@ -1043,8 +1043,29 @@ static int should_defrag_range(struct inode *inode, u64 start, u32 thresh,* real extent, don't bother defragging it */ if (!compress && (*last_len ==0 || *last_len >= thresh) && - (em->len >= thresh || (!next_mergeable && !prev_mergeable))) + (em->len >= thresh || (!next_mergeable && !prev_mergeable))) { ret =0 ; + goto out; + } + + +/* +* Try not recompress compressed extents +* thresh >= BTRFS_MAX_UNCOMPRESSED will lead to +* recompress all compressed extents +*/ +if (em->compress_type !=0 && thresh >=BTRFS_MAX_UNCOMPRESSED ) { +if (!compress) { +if (em->len ==BTRFS_MAX_UNCOMPRESSED ) + ret =0 ; + }else { +if (em->compress_type != compress_type) + goto out; +if (em->len ==BTRFS_MAX_UNCOMPRESSED ) + ret =0 ; + } + } + out:/* * last_len ends up being a counter of how many bytes we've defragged.
@@ -1342,7 +1363,8 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,if (!should_defrag_range (inode, (u64 )i <<PAGE_SHIFT , extent_thresh, &last_len, &skip, - &defrag_end, do_compress)){ + &defrag_end, do_compress, + compress_type)){unsigned long next;/* * the should_defrag function tells us how much to skip
Signature · 1 line
2.15.1
PATCH RESEND 3/4 Btrfs: allow btrfs_defrag_file() uncompress files on defragmentation
In reply to Timofey TitovetsCurrently defrag ioctl only support recompress files with specified compression type.
Allow set compression type to none, while call defrag, and use BTRFS_DEFRAG_RANGE_COMPRESS as flag, that user request change of compression type.
--- fs/btrfs/btrfs_inode.h | 1 + fs/btrfs/inode.c | 4 ++-- fs/btrfs/ioctl.c | 17 ++++++++++------- 3 files changed, 13 insertions(+), 9 deletions(-)
fs/btrfs/btrfs_inode.h +1 -0
@@ -187,6 +187,7 @@ struct btrfs_inode {* different from prop_compress and takes precedence if set */ unsigned defrag_compress; +unsigned change_compress;struct btrfs_delayed_node *delayed_node;
fs/btrfs/inode.c +2 -2
@@ -412,8 +412,8 @@ static inline int inode_need_compress(struct inode *inode, u64 start, u64 end)if (btrfs_test_opt (fs_info,FORCE_COMPRESS ))return 1 ;/* defrag ioctl */ -if (BTRFS_I (inode)->defrag_compress) -return 1 ; +if (BTRFS_I (inode)->change_compress) +return BTRFS_I (inode)->defrag_compress;/* bad compression ratios */ if (BTRFS_I (inode)->flags &BTRFS_INODE_NOCOMPRESS )return 0 ;
fs/btrfs/ioctl.c +10 -7
@@ -1276,7 +1276,7 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,unsigned long cluster = max_cluster;u64 new_align = ~((u64 )SZ_128K -1 );struct page **pages =NULL ; -bool do_compress = range->flags &BTRFS_DEFRAG_RANGE_COMPRESS ; +bool change_compress = range->flags &BTRFS_DEFRAG_RANGE_COMPRESS ;if (isize ==0 )return 0 ;
@@ -1284,11 +1284,10 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,if (range->start >= isize)return -EINVAL ; -if (do_compress) { +if (change_compress) {if (range->compress_type >BTRFS_COMPRESS_TYPES )return -EINVAL ; -if (range->compress_type) - compress_type = range->compress_type; + compress_type = range->compress_type; }if (extent_thresh ==0 )
@@ -1363,7 +1362,7 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,if (!should_defrag_range (inode, (u64 )i <<PAGE_SHIFT , extent_thresh, &last_len, &skip, - &defrag_end, do_compress, + &defrag_end, change_compress, compress_type)){unsigned long next;/*
@@ -1392,8 +1391,11 @@ int btrfs_defrag_file(struct inode *inode, struct file *file, }inode_lock (inode); -if (do_compress) +if (change_compress) { +BTRFS_I (inode)->change_compress = change_compress;BTRFS_I (inode)->defrag_compress = compress_type; + } + ret =cluster_pages_for_defrag (inode, pages, i, cluster);if (ret <0 ) {inode_unlock (inode);
@@ -1449,8 +1451,9 @@ int btrfs_defrag_file(struct inode *inode, struct file *file, ret = defrag_count; out_ra: -if (do_compress) { +if (change_compress) {inode_lock (inode); +BTRFS_I (inode)->change_compress =0 ;BTRFS_I (inode)->defrag_compress =BTRFS_COMPRESS_NONE ;inode_unlock (inode); }
Signature · 1 line
2.15.1
PATCH RESEND 4/4 Btrfs: reduce size of struct btrfs_inode
In reply to Timofey TitovetsCurrently btrfs_inode have size equal 1136 bytes. (On x86_64).
struct btrfs_inode store several vars releated to compression code, all states use 1 or 2 bits.
Lets declare bitfields for compression releated vars, to reduce sizeof btrfs_inode to 1128 bytes.
--- fs/btrfs/btrfs_inode.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
fs/btrfs/btrfs_inode.h +3 -3
@@ -181,13 +181,13 @@ struct btrfs_inode {/* * Cached values of inode properties */ -unsigned prop_compress;/* per-file compression algorithm */ + unsigned prop_compress : 2; /* per-file compression algorithm *//* * Force compression on the file using the defrag ioctl, could be * different from prop_compress and takes precedence if set */ -unsigned defrag_compress; -unsigned change_compress; + unsigned defrag_compress : 2; + unsigned change_compress : 1;struct btrfs_delayed_node *delayed_node;
Signature · 1 line
2.15.1
Re: [PATCH 4/4] [RESEND] Btrfs: reduce size of struct btrfs_inode
Quoted 7 lines · Timofey Titovets
Currently
btrfs_inodehave size equal 1136 bytes. (Onx86_64).struct
btrfs_inodestore several vars releated to compression code, all states use 1 or 2 bits.Lets declare bitfields for compression releated vars, to reduce sizeof
btrfs_inodeto 1128 bytes.
Unfortunatelly, this has no big effect. The inodes are allocated from a slab page, that's 4k and there are at most 3 inodes there. Snippet from /proc/slabinfo:
# name <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> btrfs_inode 256043 278943 1096 3 1
The size on my box is 1096 as it's 4.14, but this should not matter to demonstrate the idea.
objperslab is 3 here, ie. there are 3 btrfs_inode in the page, and there's 4096 - 3 * 1096 = 808 of slack space. In order to pack 4 inodes per page, we'd have to squeeze the inode size to 1024 bytes. I've looked into that and did not see enough members to remove or substitute. IIRC there were like 24-32 bytes possible to shave, but that was it.
Once we'd get to 1024, adding anything new to btrfs_inode would be quite difficult and as it goes, there's always something to add to the inode.
So I'd take a different approach, to regroup items and decide by cacheline access patterns what to put together and what to separate.
The maximum size of inode before going to 2 objects per page is 1365, so there's enough space for cacheline alignments.
Re: [PATCH 4/4] [RESEND] Btrfs: reduce size of struct btrfs_inode
чт, 26 апр. 2018 г. в 16:44, David Sterba <[email protected]>:
Quoted 6 lines · Timofey Titovets
Quoted 5 lines
Currently
btrfs_inodehave size equal 1136 bytes. (Onx86_64).struct
btrfs_inodestore several vars releated to compression code, all states use 1 or 2 bits.
Quoted 8 lines
Quoted 2 lines
Lets declare bitfields for compression releated vars, to reduce sizeof
btrfs_inodeto 1128 bytes.Unfortunatelly, this has no big effect. The inodes are allocated from a slab page, that's 4k and there are at most 3 inodes there. Snippet from
/proc/slabinfo:# name <active_objs> <num_objs> <objsize> <objperslab>
<pagesperslab>
Quoted 11 lines
btrfs_inode256043 278943 1096 3 1The size on my box is 1096 as it's 4.14, but this should not matter to demonstrate the idea.
objperslab is 3 here, ie. there are 3
btrfs_inodein the page, and there's 4096 - 3 * 1096 = 808 of slack space. In order to pack 4 inodes per page, we'd have to squeeze the inode size to 1024 bytes. I've looked into that and did not see enough members to remove or substitute. IIRC there were like 24-32 bytes possible to shave, but that was it.
Quoted 8 lines
Once we'd get to 1024, adding anything new to
btrfs_inodewould be quite difficult and as it goes, there's always something to add to the inode.So I'd take a different approach, to regroup items and decide by cacheline access patterns what to put together and what to separate.
The maximum size of inode before going to 2 objects per page is 1365, so there's enough space for cacheline alignments.
May be i misunderstood something, but i was think that slab combine several pages
in continuous range, so object in slab can cross page boundary. So, all calculation will be very depends on scale of slab size.
i.e. on my machine that looks quite different:
name <active_objs> <num_objs> <objsize> <objperslab>
<pagesperslab>btrfs_inode 142475 146272 1136 28
8
So,PAGE_SIZE * pagesperslab / objperslab
4096 * 8 / 28 = 1170.28
4096*8 - 1136*28 = 960
That's looks like object can cross page boundary in slab. So, if size reduced to 1128,
4096 * 8 / 29 = 1129.93
4096*8 - 1128*29 = 56
Did i miss something?
Thanks.
Signature · 2 lines
Have a nice day, Timofey.
Re: [PATCH 4/4] [RESEND] Btrfs: reduce size of struct btrfs_inode
Quoted 13 lines · Timofey Titovets
May be i misunderstood something, but i was think that slab combine several pages in continuous range, so object in slab can cross page boundary. So, all calculation will be very depends on scale of slab size.
i.e. on my machine that looks quite different:
name <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> btrfs_inode 142475 146272 1136 28 8So,
PAGE_SIZE* pagesperslab / objperslab
4096 * 8 / 28 = 1170.28
Quoted 8 lines
4096*8 - 1136*28 = 960
That's looks like object can cross page boundary in slab. So, if size reduced to 1128,
4096 * 8 / 29 = 1129.93
4096*8 - 1128*29 = 56Did i miss something?
Then this depends on the allocator, SLAB does 4k pages and SLUB 32k, so there's a value in reducing the inode size.