On Fri, 16 Aug 2024 at 10:55, Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx> wrote: > > Oh, and can we please make 'dup_fd()' return an error pointer instead > of having that other int pointer argument for the error code? Something like this, IOW.. Entirely untested, but looks obvious enough. Linus
fs/file.c | 13 ++++++------- include/linux/fdtable.h | 2 +- kernel/fork.c | 26 ++++++++++++-------------- 3 files changed, 19 insertions(+), 22 deletions(-) diff --git a/fs/file.c b/fs/file.c index 655338effe9c..de3920d96341 100644 --- a/fs/file.c +++ b/fs/file.c @@ -314,17 +314,17 @@ static unsigned int sane_fdtable_size(struct fdtable *fdt, unsigned int max_fds) * passed in files structure. * errorp will be valid only when the returned files_struct is NULL. */ -struct files_struct *dup_fd(struct files_struct *oldf, unsigned int max_fds, int *errorp) +struct files_struct *dup_fd(struct files_struct *oldf, unsigned int max_fds) { struct files_struct *newf; struct file **old_fds, **new_fds; unsigned int open_files, i; struct fdtable *old_fdt, *new_fdt; + int error; - *errorp = -ENOMEM; newf = kmem_cache_alloc(files_cachep, GFP_KERNEL); if (!newf) - goto out; + return ERR_PTR(-ENOMEM); atomic_set(&newf->count, 1); @@ -354,14 +354,14 @@ struct files_struct *dup_fd(struct files_struct *oldf, unsigned int max_fds, int new_fdt = alloc_fdtable(open_files - 1); if (!new_fdt) { - *errorp = -ENOMEM; + error = -ENOMEM; goto out_release; } /* beyond sysctl_nr_open; nothing to do */ if (unlikely(new_fdt->max_fds < open_files)) { __free_fdtable(new_fdt); - *errorp = -EMFILE; + error = -EMFILE; goto out_release; } @@ -406,8 +406,7 @@ struct files_struct *dup_fd(struct files_struct *oldf, unsigned int max_fds, int out_release: kmem_cache_free(files_cachep, newf); -out: - return NULL; + return ERR_PTR(error); } static struct fdtable *close_files(struct files_struct * files) diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h index 2944d4aa413b..b936d35beb57 100644 --- a/include/linux/fdtable.h +++ b/include/linux/fdtable.h @@ -106,7 +106,7 @@ struct task_struct; void put_files_struct(struct files_struct *fs); int unshare_files(void); -struct files_struct *dup_fd(struct files_struct *, unsigned, int *) __latent_entropy; +struct files_struct *dup_fd(struct files_struct *, unsigned) __latent_entropy; void do_close_on_exec(struct files_struct *); int iterate_fd(struct files_struct *, unsigned, int (*)(const void *, struct file *, unsigned), diff --git a/kernel/fork.c b/kernel/fork.c index 18bdc87209d0..0c7a12cb8617 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1754,33 +1754,30 @@ static int copy_files(unsigned long clone_flags, struct task_struct *tsk, int no_files) { struct files_struct *oldf, *newf; - int error = 0; /* * A background process may not have any files ... */ oldf = current->files; if (!oldf) - goto out; + return 0; if (no_files) { tsk->files = NULL; - goto out; + return 0; } if (clone_flags & CLONE_FILES) { atomic_inc(&oldf->count); - goto out; + return 0; } - newf = dup_fd(oldf, NR_OPEN_MAX, &error); - if (!newf) - goto out; + newf = dup_fd(oldf, NR_OPEN_MAX); + if (IS_ERR(newf)) + return PTR_ERR(newf); tsk->files = newf; - error = 0; -out: - return error; + return 0; } static int copy_sighand(unsigned long clone_flags, struct task_struct *tsk) @@ -3255,13 +3252,14 @@ int unshare_fd(unsigned long unshare_flags, unsigned int max_fds, struct files_struct **new_fdp) { struct files_struct *fd = current->files; - int error = 0; if ((unshare_flags & CLONE_FILES) && (fd && atomic_read(&fd->count) > 1)) { - *new_fdp = dup_fd(fd, max_fds, &error); - if (!*new_fdp) - return error; + struct files_struct *newf; + newf = dup_fd(fd, max_fds); + if (IS_ERR(newf)) + return PTR_ERR(newf); + *new_fdp = newf; } return 0;