Message ID | 2200f9340973d627ee304ac4470f5921061266f9.1627418762.git.rgoldwyn@suse.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Allocate structures on stack instead of kmalloc() | expand |
On 28/07/2021 05:17, Goldwyn Rodrigues wrote: > From: Goldwyn Rodrigues <rgoldwyn@suse.com> > > Instead of using kmalloc() to allocate btrfs_ioctl_get_subvol_info_args, > allocate btrfs_ioctl_get_subvol_info_args on stack. > > sizeof(btrfs_ioctl_get_subvol_info_args) = 504 > > Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com> Looks good. Reviewed-by: Anand Jain <anand.jain@oracle.com> > --- > fs/btrfs/ioctl.c | 55 +++++++++++++++++++++--------------------------- > 1 file changed, 24 insertions(+), 31 deletions(-) > > diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c > index 0ba98e08a029..90b134b5a653 100644 > --- a/fs/btrfs/ioctl.c > +++ b/fs/btrfs/ioctl.c > @@ -2681,7 +2681,7 @@ static int btrfs_ioctl_ino_lookup_user(struct file *file, void __user *argp) > /* Get the subvolume information in BTRFS_ROOT_ITEM and BTRFS_ROOT_BACKREF */ > static int btrfs_ioctl_get_subvol_info(struct file *file, void __user *argp) > { > - struct btrfs_ioctl_get_subvol_info_args *subvol_info; > + struct btrfs_ioctl_get_subvol_info_args subvol_info = {0}; > struct btrfs_fs_info *fs_info; > struct btrfs_root *root; > struct btrfs_path *path; > @@ -2699,12 +2699,6 @@ static int btrfs_ioctl_get_subvol_info(struct file *file, void __user *argp) > if (!path) > return -ENOMEM; > > - subvol_info = kzalloc(sizeof(*subvol_info), GFP_KERNEL); > - if (!subvol_info) { > - btrfs_free_path(path); > - return -ENOMEM; > - } > - > inode = file_inode(file); > fs_info = BTRFS_I(inode)->root->fs_info; > > @@ -2717,32 +2711,32 @@ static int btrfs_ioctl_get_subvol_info(struct file *file, void __user *argp) > } > root_item = &root->root_item; > > - subvol_info->treeid = key.objectid; > + subvol_info.treeid = key.objectid; > > - subvol_info->generation = btrfs_root_generation(root_item); > - subvol_info->flags = btrfs_root_flags(root_item); > + subvol_info.generation = btrfs_root_generation(root_item); > + subvol_info.flags = btrfs_root_flags(root_item); > > - memcpy(subvol_info->uuid, root_item->uuid, BTRFS_UUID_SIZE); > - memcpy(subvol_info->parent_uuid, root_item->parent_uuid, > + memcpy(subvol_info.uuid, root_item->uuid, BTRFS_UUID_SIZE); > + memcpy(subvol_info.parent_uuid, root_item->parent_uuid, > BTRFS_UUID_SIZE); > - memcpy(subvol_info->received_uuid, root_item->received_uuid, > + memcpy(subvol_info.received_uuid, root_item->received_uuid, > BTRFS_UUID_SIZE); > > - subvol_info->ctransid = btrfs_root_ctransid(root_item); > - subvol_info->ctime.sec = btrfs_stack_timespec_sec(&root_item->ctime); > - subvol_info->ctime.nsec = btrfs_stack_timespec_nsec(&root_item->ctime); > + subvol_info.ctransid = btrfs_root_ctransid(root_item); > + subvol_info.ctime.sec = btrfs_stack_timespec_sec(&root_item->ctime); > + subvol_info.ctime.nsec = btrfs_stack_timespec_nsec(&root_item->ctime); > > - subvol_info->otransid = btrfs_root_otransid(root_item); > - subvol_info->otime.sec = btrfs_stack_timespec_sec(&root_item->otime); > - subvol_info->otime.nsec = btrfs_stack_timespec_nsec(&root_item->otime); > + subvol_info.otransid = btrfs_root_otransid(root_item); > + subvol_info.otime.sec = btrfs_stack_timespec_sec(&root_item->otime); > + subvol_info.otime.nsec = btrfs_stack_timespec_nsec(&root_item->otime); > > - subvol_info->stransid = btrfs_root_stransid(root_item); > - subvol_info->stime.sec = btrfs_stack_timespec_sec(&root_item->stime); > - subvol_info->stime.nsec = btrfs_stack_timespec_nsec(&root_item->stime); > + subvol_info.stransid = btrfs_root_stransid(root_item); > + subvol_info.stime.sec = btrfs_stack_timespec_sec(&root_item->stime); > + subvol_info.stime.nsec = btrfs_stack_timespec_nsec(&root_item->stime); > > - subvol_info->rtransid = btrfs_root_rtransid(root_item); > - subvol_info->rtime.sec = btrfs_stack_timespec_sec(&root_item->rtime); > - subvol_info->rtime.nsec = btrfs_stack_timespec_nsec(&root_item->rtime); > + subvol_info.rtransid = btrfs_root_rtransid(root_item); > + subvol_info.rtime.sec = btrfs_stack_timespec_sec(&root_item->rtime); > + subvol_info.rtime.nsec = btrfs_stack_timespec_nsec(&root_item->rtime); > > if (key.objectid != BTRFS_FS_TREE_OBJECTID) { > /* Search root tree for ROOT_BACKREF of this subvolume */ > @@ -2765,18 +2759,18 @@ static int btrfs_ioctl_get_subvol_info(struct file *file, void __user *argp) > leaf = path->nodes[0]; > slot = path->slots[0]; > btrfs_item_key_to_cpu(leaf, &key, slot); > - if (key.objectid == subvol_info->treeid && > + if (key.objectid == subvol_info.treeid && > key.type == BTRFS_ROOT_BACKREF_KEY) { > - subvol_info->parent_id = key.offset; > + subvol_info.parent_id = key.offset; > > rref = btrfs_item_ptr(leaf, slot, struct btrfs_root_ref); > - subvol_info->dirid = btrfs_root_ref_dirid(leaf, rref); > + subvol_info.dirid = btrfs_root_ref_dirid(leaf, rref); > > item_off = btrfs_item_ptr_offset(leaf, slot) > + sizeof(struct btrfs_root_ref); > item_len = btrfs_item_size_nr(leaf, slot) > - sizeof(struct btrfs_root_ref); > - read_extent_buffer(leaf, subvol_info->name, > + read_extent_buffer(leaf, subvol_info.name, > item_off, item_len); > } else { > ret = -ENOENT; > @@ -2784,14 +2778,13 @@ static int btrfs_ioctl_get_subvol_info(struct file *file, void __user *argp) > } > } > > - if (copy_to_user(argp, subvol_info, sizeof(*subvol_info))) > + if (copy_to_user(argp, &subvol_info, sizeof(subvol_info))) > ret = -EFAULT; > > out: > btrfs_put_root(root); > out_free: > btrfs_free_path(path); > - kfree(subvol_info); > return ret; > } > >
On Tue, Jul 27, 2021 at 04:17:27PM -0500, Goldwyn Rodrigues wrote: > From: Goldwyn Rodrigues <rgoldwyn@suse.com> > > Instead of using kmalloc() to allocate btrfs_ioctl_get_subvol_info_args, > allocate btrfs_ioctl_get_subvol_info_args on stack. > > sizeof(btrfs_ioctl_get_subvol_info_args) = 504 > > Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com> > --- > fs/btrfs/ioctl.c | 55 +++++++++++++++++++++--------------------------- > 1 file changed, 24 insertions(+), 31 deletions(-) > > diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c > index 0ba98e08a029..90b134b5a653 100644 > --- a/fs/btrfs/ioctl.c > +++ b/fs/btrfs/ioctl.c > @@ -2681,7 +2681,7 @@ static int btrfs_ioctl_ino_lookup_user(struct file *file, void __user *argp) > /* Get the subvolume information in BTRFS_ROOT_ITEM and BTRFS_ROOT_BACKREF */ > static int btrfs_ioctl_get_subvol_info(struct file *file, void __user *argp) > { > - struct btrfs_ioctl_get_subvol_info_args *subvol_info; > + struct btrfs_ioctl_get_subvol_info_args subvol_info = {0}; There are concerns [1] if the {0} initialization zeroes all the bytes entirely, including padding between members and at the end, but as I understand it, this should be safe. [1] long thread, https://lore.kernel.org/lkml/20210727205855.411487-20-keescook@chromium.org/T/#m7e4e04af9664f204232a569390c3f3dc2e4bf907 If it turns out {0} is not sufficient, we'll have to add explicit memset() in case the on-stack structure is then copied back with copy_to_user.
On Tue, Jul 27, 2021 at 04:17:27PM -0500, Goldwyn Rodrigues wrote: > From: Goldwyn Rodrigues <rgoldwyn@suse.com> > > Instead of using kmalloc() to allocate btrfs_ioctl_get_subvol_info_args, > allocate btrfs_ioctl_get_subvol_info_args on stack. > > sizeof(btrfs_ioctl_get_subvol_info_args) = 504 I'm not sure about this one, it's a lot and it's not a perf critical ioctl. Reading information about a subvolume can potentially trigger a lot of reads in a cold state, thus triggering all the deep call chains.
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 0ba98e08a029..90b134b5a653 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -2681,7 +2681,7 @@ static int btrfs_ioctl_ino_lookup_user(struct file *file, void __user *argp) /* Get the subvolume information in BTRFS_ROOT_ITEM and BTRFS_ROOT_BACKREF */ static int btrfs_ioctl_get_subvol_info(struct file *file, void __user *argp) { - struct btrfs_ioctl_get_subvol_info_args *subvol_info; + struct btrfs_ioctl_get_subvol_info_args subvol_info = {0}; struct btrfs_fs_info *fs_info; struct btrfs_root *root; struct btrfs_path *path; @@ -2699,12 +2699,6 @@ static int btrfs_ioctl_get_subvol_info(struct file *file, void __user *argp) if (!path) return -ENOMEM; - subvol_info = kzalloc(sizeof(*subvol_info), GFP_KERNEL); - if (!subvol_info) { - btrfs_free_path(path); - return -ENOMEM; - } - inode = file_inode(file); fs_info = BTRFS_I(inode)->root->fs_info; @@ -2717,32 +2711,32 @@ static int btrfs_ioctl_get_subvol_info(struct file *file, void __user *argp) } root_item = &root->root_item; - subvol_info->treeid = key.objectid; + subvol_info.treeid = key.objectid; - subvol_info->generation = btrfs_root_generation(root_item); - subvol_info->flags = btrfs_root_flags(root_item); + subvol_info.generation = btrfs_root_generation(root_item); + subvol_info.flags = btrfs_root_flags(root_item); - memcpy(subvol_info->uuid, root_item->uuid, BTRFS_UUID_SIZE); - memcpy(subvol_info->parent_uuid, root_item->parent_uuid, + memcpy(subvol_info.uuid, root_item->uuid, BTRFS_UUID_SIZE); + memcpy(subvol_info.parent_uuid, root_item->parent_uuid, BTRFS_UUID_SIZE); - memcpy(subvol_info->received_uuid, root_item->received_uuid, + memcpy(subvol_info.received_uuid, root_item->received_uuid, BTRFS_UUID_SIZE); - subvol_info->ctransid = btrfs_root_ctransid(root_item); - subvol_info->ctime.sec = btrfs_stack_timespec_sec(&root_item->ctime); - subvol_info->ctime.nsec = btrfs_stack_timespec_nsec(&root_item->ctime); + subvol_info.ctransid = btrfs_root_ctransid(root_item); + subvol_info.ctime.sec = btrfs_stack_timespec_sec(&root_item->ctime); + subvol_info.ctime.nsec = btrfs_stack_timespec_nsec(&root_item->ctime); - subvol_info->otransid = btrfs_root_otransid(root_item); - subvol_info->otime.sec = btrfs_stack_timespec_sec(&root_item->otime); - subvol_info->otime.nsec = btrfs_stack_timespec_nsec(&root_item->otime); + subvol_info.otransid = btrfs_root_otransid(root_item); + subvol_info.otime.sec = btrfs_stack_timespec_sec(&root_item->otime); + subvol_info.otime.nsec = btrfs_stack_timespec_nsec(&root_item->otime); - subvol_info->stransid = btrfs_root_stransid(root_item); - subvol_info->stime.sec = btrfs_stack_timespec_sec(&root_item->stime); - subvol_info->stime.nsec = btrfs_stack_timespec_nsec(&root_item->stime); + subvol_info.stransid = btrfs_root_stransid(root_item); + subvol_info.stime.sec = btrfs_stack_timespec_sec(&root_item->stime); + subvol_info.stime.nsec = btrfs_stack_timespec_nsec(&root_item->stime); - subvol_info->rtransid = btrfs_root_rtransid(root_item); - subvol_info->rtime.sec = btrfs_stack_timespec_sec(&root_item->rtime); - subvol_info->rtime.nsec = btrfs_stack_timespec_nsec(&root_item->rtime); + subvol_info.rtransid = btrfs_root_rtransid(root_item); + subvol_info.rtime.sec = btrfs_stack_timespec_sec(&root_item->rtime); + subvol_info.rtime.nsec = btrfs_stack_timespec_nsec(&root_item->rtime); if (key.objectid != BTRFS_FS_TREE_OBJECTID) { /* Search root tree for ROOT_BACKREF of this subvolume */ @@ -2765,18 +2759,18 @@ static int btrfs_ioctl_get_subvol_info(struct file *file, void __user *argp) leaf = path->nodes[0]; slot = path->slots[0]; btrfs_item_key_to_cpu(leaf, &key, slot); - if (key.objectid == subvol_info->treeid && + if (key.objectid == subvol_info.treeid && key.type == BTRFS_ROOT_BACKREF_KEY) { - subvol_info->parent_id = key.offset; + subvol_info.parent_id = key.offset; rref = btrfs_item_ptr(leaf, slot, struct btrfs_root_ref); - subvol_info->dirid = btrfs_root_ref_dirid(leaf, rref); + subvol_info.dirid = btrfs_root_ref_dirid(leaf, rref); item_off = btrfs_item_ptr_offset(leaf, slot) + sizeof(struct btrfs_root_ref); item_len = btrfs_item_size_nr(leaf, slot) - sizeof(struct btrfs_root_ref); - read_extent_buffer(leaf, subvol_info->name, + read_extent_buffer(leaf, subvol_info.name, item_off, item_len); } else { ret = -ENOENT; @@ -2784,14 +2778,13 @@ static int btrfs_ioctl_get_subvol_info(struct file *file, void __user *argp) } } - if (copy_to_user(argp, subvol_info, sizeof(*subvol_info))) + if (copy_to_user(argp, &subvol_info, sizeof(subvol_info))) ret = -EFAULT; out: btrfs_put_root(root); out_free: btrfs_free_path(path); - kfree(subvol_info); return ret; }