mirror of
https://github.com/torvalds/linux
synced 2026-07-22 02:00:44 +09:00
Convert RDS socket's getsockopt implementation to use the new getsockopt_iter callback with sockopt_t. Key changes: - Replace (char __user *optval, int __user *optlen) with sockopt_t *opt - Use opt->optlen for buffer length (input) and returned size (output) - Use copy_to_iter() instead of put_user()/copy_to_user() The RDS_INFO_* snapshot path in rds_info_getsockopt() used to pin the userspace buffer with pin_user_pages_fast() on the raw optval address; the info producers then memcpy into those pages under a spinlock via kmap_atomic() and so must not fault. Obtain the same page array and starting offset from opt->iter_out with iov_iter_extract_pages(), which pins for write because iter_out is ITER_DEST. The page array is preallocated here (sized with iov_iter_npages()) and passed in, so iov_iter_extract_pages() fills it in place rather than allocating one for us; RDS therefore keeps ownership of the array on every return path and frees it itself. The rds_info_iterator / rds_info_copy machinery and all producer callbacks are unchanged. Kernel buffers (ITER_KVEC) are not page-backed in a way the info producers can use, so the RDS_INFO path returns -EOPNOTSUPP for them; this matches the previous behaviour, where a kernel-buffer getsockopt hit the WARN_ONCE() path in do_sock_getsockopt() and returned -EOPNOTSUPP. The simple RDS_RECVERR and SO_RDS_TRANSPORT options keep working for kernel buffers via copy_to_iter(). Signed-off-by: Breno Leitao <leitao@debian.org> Reviewed-by: Allison Henderson <achender@kernel.org> Link: https://patch.msgid.link/20260608-getsock_more-v3-2-706ecf2ea332@debian.org Signed-off-by: Paolo Abeni <pabeni@redhat.com>
31 lines
945 B
C
31 lines
945 B
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef _RDS_INFO_H
|
|
#define _RDS_INFO_H
|
|
|
|
struct rds_info_lengths {
|
|
unsigned int nr;
|
|
unsigned int each;
|
|
};
|
|
|
|
struct rds_info_iterator;
|
|
|
|
/*
|
|
* These functions must fill in the fields of @lens to reflect the size
|
|
* of the available info source. If the snapshot fits in @len then it
|
|
* should be copied using @iter. The caller will deduce if it was copied
|
|
* or not by comparing the lengths.
|
|
*/
|
|
typedef void (*rds_info_func)(struct socket *sock, unsigned int len,
|
|
struct rds_info_iterator *iter,
|
|
struct rds_info_lengths *lens);
|
|
|
|
void rds_info_register_func(int optname, rds_info_func func);
|
|
void rds_info_deregister_func(int optname, rds_info_func func);
|
|
int rds_info_getsockopt(struct socket *sock, int optname, sockopt_t *opt);
|
|
void rds_info_copy(struct rds_info_iterator *iter, void *data,
|
|
unsigned long bytes);
|
|
void rds_info_iter_unmap(struct rds_info_iterator *iter);
|
|
|
|
|
|
#endif
|