Message ID | 20241118002024.451858-1-mjguzik@gmail.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | vfs: move getattr in inode_operations to a more commonly read area | expand |
On Mon 18-11-24 01:20:24, Mateusz Guzik wrote: > Notabaly occupied by lookup, get_link and permission. > > This pushes unlink to another cache line, otherwise the layout is the > same on that front. > > Signed-off-by: Mateusz Guzik <mjguzik@gmail.com> > --- > > Probably more can be done to rearrange struct. If someone is down to do > it, I'm happy with this patch being dropped. This makes some sense to me although I'd like to establish some higher level guidelines (and document them in a comment) about what goes where in the inode_operations struct. A lot of accesses to inode->i_op actually do get optimized away with inode->i_opflags (e.g. frequent stuff like .permission or .get_inode_acl) so there are actually high chances there's only one access to inode->i_op for the operation we are doing and in such case the ordering inside inode_operations doesn't really matter (it's likely cache cold anyway). So I'm somewhat uncertain what the right grouping should be and if it matters at all. Honza > diff --git a/include/linux/fs.h b/include/linux/fs.h > index 7e29433c5ecc..972147da71f9 100644 > --- a/include/linux/fs.h > +++ b/include/linux/fs.h > @@ -2140,6 +2140,8 @@ struct inode_operations { > const char * (*get_link) (struct dentry *, struct inode *, struct delayed_call *); > int (*permission) (struct mnt_idmap *, struct inode *, int); > struct posix_acl * (*get_inode_acl)(struct inode *, int, bool); > + int (*getattr) (struct mnt_idmap *, const struct path *, > + struct kstat *, u32, unsigned int); > > int (*readlink) (struct dentry *, char __user *,int); > > @@ -2157,8 +2159,6 @@ struct inode_operations { > int (*rename) (struct mnt_idmap *, struct inode *, struct dentry *, > struct inode *, struct dentry *, unsigned int); > int (*setattr) (struct mnt_idmap *, struct dentry *, struct iattr *); > - int (*getattr) (struct mnt_idmap *, const struct path *, > - struct kstat *, u32, unsigned int); > ssize_t (*listxattr) (struct dentry *, char *, size_t); > int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, > u64 len); > -- > 2.43.0 >
On Mon, Nov 18, 2024 at 12:26 PM Jan Kara <jack@suse.cz> wrote: > > On Mon 18-11-24 01:20:24, Mateusz Guzik wrote: > > Notabaly occupied by lookup, get_link and permission. > > > > This pushes unlink to another cache line, otherwise the layout is the > > same on that front. > > > > Signed-off-by: Mateusz Guzik <mjguzik@gmail.com> > > --- > > > > Probably more can be done to rearrange struct. If someone is down to do > > it, I'm happy with this patch being dropped. > > This makes some sense to me although I'd like to establish some higher > level guidelines (and document them in a comment) about what goes where in > the inode_operations struct. A lot of accesses to inode->i_op actually do > get optimized away with inode->i_opflags (e.g. frequent stuff like > .permission or .get_inode_acl) so there are actually high chances there's > only one access to inode->i_op for the operation we are doing and in such > case the ordering inside inode_operations doesn't really matter (it's > likely cache cold anyway). So I'm somewhat uncertain what the right > grouping should be and if it matters at all. > So I ran bpftrace attached to all ext4 inode ops during the venerable kernel build. As I expected getattr is most commonly used. But indeed the rest is a footnote in comparison, so it very well may be this change is a nop or close to it. So ye, I this is probably droppable as is, I'm not definitely not going to push one way or the other. result: @[kprobe:ext4_tmpfile]: 1 @[kprobe:ext4_symlink]: 2 @[kprobe:ext4_set_acl]: 18 @[kprobe:ext4_rename2]: 69 @[kprobe:ext4_rmdir]: 163 @[kprobe:ext4_mkdir]: 172 @[kprobe:ext4_get_acl]: 753 @[kprobe:ext4_setattr]: 3938 @[kprobe:ext4_unlink]: 7218 @[kprobe:ext4_create]: 18576 @[kprobe:ext4_lookup]: 99644 @[kprobe:ext4_file_getattr]: 5737047 @[kprobe:ext4_getattr]: 5909325 oneliner: bpftrace -e 'kprobe:ext4_create,kprobe:ext4_fiemap,kprobe:ext4_fileattr_get,kprobe:ext4_fileattr_set,kprobe:ext4_file_getattr,kprobe:ext4_get_acl,kprobe:ext4_getattr,kprobe:ext4_link,kprobe:ext4_listxattr,kprobe:ext4_lookup,kprobe:ext4_mkdir,kprobe:ext4_mknod,kprobe:ext4_rename2,kprobe:ext4_rmdir,kprobe:ext4_set_acl,kprobe:ext4_setattr,kprobe:ext4_symlink,kprobe:ext4_tmpfile,kprobe:ext4_unlink { @[probe] = count(); }'
diff --git a/include/linux/fs.h b/include/linux/fs.h index 7e29433c5ecc..972147da71f9 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2140,6 +2140,8 @@ struct inode_operations { const char * (*get_link) (struct dentry *, struct inode *, struct delayed_call *); int (*permission) (struct mnt_idmap *, struct inode *, int); struct posix_acl * (*get_inode_acl)(struct inode *, int, bool); + int (*getattr) (struct mnt_idmap *, const struct path *, + struct kstat *, u32, unsigned int); int (*readlink) (struct dentry *, char __user *,int); @@ -2157,8 +2159,6 @@ struct inode_operations { int (*rename) (struct mnt_idmap *, struct inode *, struct dentry *, struct inode *, struct dentry *, unsigned int); int (*setattr) (struct mnt_idmap *, struct dentry *, struct iattr *); - int (*getattr) (struct mnt_idmap *, const struct path *, - struct kstat *, u32, unsigned int); ssize_t (*listxattr) (struct dentry *, char *, size_t); int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len);
Notabaly occupied by lookup, get_link and permission. This pushes unlink to another cache line, otherwise the layout is the same on that front. Signed-off-by: Mateusz Guzik <mjguzik@gmail.com> --- Probably more can be done to rearrange struct. If someone is down to do it, I'm happy with this patch being dropped. include/linux/fs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)