summaryrefslogtreecommitdiff
path: root/net/socket.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2025-12-01 17:32:07 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2025-12-01 17:32:07 -0800
commit1b5dd29869b1e63f7e5c37d7552e2dcf22de3c26 (patch)
tree11785d66fcfc49273da7448bb28fcb64238c2afd /net/socket.c
parentffbf700df204dd25a48a19979a126e37f5dd1e6a (diff)
parent0512bf9701f339c8fee2cc82b6fc35f0a8f6be7a (diff)
Merge tag 'vfs-6.19-rc1.fd_prepare.fs' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
Pull fd prepare updates from Christian Brauner: "This adds the FD_ADD() and FD_PREPARE() primitive. They simplify the common pattern of get_unused_fd_flags() + create file + fd_install() that is used extensively throughout the kernel and currently requires cumbersome cleanup paths. FD_ADD() - For simple cases where a file is installed immediately: fd = FD_ADD(O_CLOEXEC, vfio_device_open_file(device)); if (fd < 0) vfio_device_put_registration(device); return fd; FD_PREPARE() - For cases requiring access to the fd or file, or additional work before publishing: FD_PREPARE(fdf, O_CLOEXEC, sync_file->file); if (fdf.err) { fput(sync_file->file); return fdf.err; } data.fence = fd_prepare_fd(fdf); if (copy_to_user((void __user *)arg, &data, sizeof(data))) return -EFAULT; return fd_publish(fdf); The primitives are centered around struct fd_prepare. FD_PREPARE() encapsulates all allocation and cleanup logic and must be followed by a call to fd_publish() which associates the fd with the file and installs it into the caller's fdtable. If fd_publish() isn't called, both are deallocated automatically. FD_ADD() is a shorthand that does fd_publish() immediately and never exposes the struct to the caller. I've implemented this in a way that it's compatible with the cleanup infrastructure while also being usable separately. IOW, it's centered around struct fd_prepare which is aliased to class_fd_prepare_t and so we can make use of all the basica guard infrastructure" * tag 'vfs-6.19-rc1.fd_prepare.fs' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: (42 commits) io_uring: convert io_create_mock_file() to FD_PREPARE() file: convert replace_fd() to FD_PREPARE() vfio: convert vfio_group_ioctl_get_device_fd() to FD_ADD() tty: convert ptm_open_peer() to FD_ADD() ntsync: convert ntsync_obj_get_fd() to FD_PREPARE() media: convert media_request_alloc() to FD_PREPARE() hv: convert mshv_ioctl_create_partition() to FD_ADD() gpio: convert linehandle_create() to FD_PREPARE() pseries: port papr_rtas_setup_file_interface() to FD_ADD() pseries: convert papr_platform_dump_create_handle() to FD_ADD() spufs: convert spufs_gang_open() to FD_PREPARE() papr-hvpipe: convert papr_hvpipe_dev_create_handle() to FD_PREPARE() spufs: convert spufs_context_open() to FD_PREPARE() net/socket: convert __sys_accept4_file() to FD_ADD() net/socket: convert sock_map_fd() to FD_ADD() net/kcm: convert kcm_ioctl() to FD_PREPARE() net/handshake: convert handshake_nl_accept_doit() to FD_PREPARE() secretmem: convert memfd_secret() to FD_ADD() memfd: convert memfd_create() to FD_ADD() bpf: convert bpf_token_create() to FD_PREPARE() ...
Diffstat (limited to 'net/socket.c')
-rw-r--r--net/socket.c34
1 files changed, 6 insertions, 28 deletions
diff --git a/net/socket.c b/net/socket.c
index e8892b218708..e1bf93508f05 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -503,21 +503,12 @@ EXPORT_SYMBOL(sock_alloc_file);
static int sock_map_fd(struct socket *sock, int flags)
{
- struct file *newfile;
- int fd = get_unused_fd_flags(flags);
- if (unlikely(fd < 0)) {
- sock_release(sock);
- return fd;
- }
-
- newfile = sock_alloc_file(sock, flags, NULL);
- if (!IS_ERR(newfile)) {
- fd_install(fd, newfile);
- return fd;
- }
+ int fd;
- put_unused_fd(fd);
- return PTR_ERR(newfile);
+ fd = FD_ADD(flags, sock_alloc_file(sock, flags, NULL));
+ if (fd < 0)
+ sock_release(sock);
+ return fd;
}
/**
@@ -2012,8 +2003,6 @@ static int __sys_accept4_file(struct file *file, struct sockaddr __user *upeer_s
int __user *upeer_addrlen, int flags)
{
struct proto_accept_arg arg = { };
- struct file *newfile;
- int newfd;
if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
return -EINVAL;
@@ -2021,18 +2010,7 @@ static int __sys_accept4_file(struct file *file, struct sockaddr __user *upeer_s
if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
- newfd = get_unused_fd_flags(flags);
- if (unlikely(newfd < 0))
- return newfd;
-
- newfile = do_accept(file, &arg, upeer_sockaddr, upeer_addrlen,
- flags);
- if (IS_ERR(newfile)) {
- put_unused_fd(newfd);
- return PTR_ERR(newfile);
- }
- fd_install(newfd, newfile);
- return newfd;
+ return FD_ADD(flags, do_accept(file, &arg, upeer_sockaddr, upeer_addrlen, flags));
}
/*