info.c revision 12198:4db936bda957
10Sstevel@tonic-gate/*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
53066Sjg * Common Development and Distribution License (the "License").
63066Sjg * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate/*
220Sstevel@tonic-gate * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate */
243066Sjg
250Sstevel@tonic-gate/*
260Sstevel@tonic-gate * Copyright (c) 2006 Oracle.  All rights reserved.
273066Sjg *
280Sstevel@tonic-gate * This software is available to you under a choice of one of two
290Sstevel@tonic-gate * licenses.  You may choose to be licensed under the terms of the GNU
300Sstevel@tonic-gate * General Public License (GPL) Version 2, available from the file
310Sstevel@tonic-gate * COPYING in the main directory of this source tree, or the
320Sstevel@tonic-gate * OpenIB.org BSD license below:
330Sstevel@tonic-gate *
340Sstevel@tonic-gate *     Redistribution and use in source and binary forms, with or
350Sstevel@tonic-gate *     without modification, are permitted provided that the following
360Sstevel@tonic-gate *     conditions are met:
370Sstevel@tonic-gate *
380Sstevel@tonic-gate *      - Redistributions of source code must retain the above
390Sstevel@tonic-gate *        copyright notice, this list of conditions and the following
400Sstevel@tonic-gate *        disclaimer.
410Sstevel@tonic-gate *
420Sstevel@tonic-gate *      - Redistributions in binary form must reproduce the above
430Sstevel@tonic-gate *        copyright notice, this list of conditions and the following
440Sstevel@tonic-gate *        disclaimer in the documentation and/or other materials
450Sstevel@tonic-gate *        provided with the distribution.
460Sstevel@tonic-gate *
470Sstevel@tonic-gate * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
480Sstevel@tonic-gate * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
490Sstevel@tonic-gate * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
500Sstevel@tonic-gate * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
510Sstevel@tonic-gate * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
520Sstevel@tonic-gate * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
530Sstevel@tonic-gate * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
540Sstevel@tonic-gate * SOFTWARE.
550Sstevel@tonic-gate *
560Sstevel@tonic-gate */
570Sstevel@tonic-gate#include <sys/rds.h>
580Sstevel@tonic-gate
593066Sjg#include <sys/ib/clients/rdsv3/rdsv3.h>
603066Sjg
613066Sjg/*
623066Sjg * This file implements a getsockopt() call which copies a set of fixed
633066Sjg * sized structs into a user-specified buffer as a means of providing
643066Sjg * read-only information about RDS.
653066Sjg *
663066Sjg * For a given information source there are a given number of fixed sized
673066Sjg * structs at a given time.  The structs are only copied if the user-specified
680Sstevel@tonic-gate * buffer is big enough.  The destination pages that make up the buffer
690Sstevel@tonic-gate * are pinned for the duration of the copy.
700Sstevel@tonic-gate *
710Sstevel@tonic-gate * This gives us the following benefits:
720Sstevel@tonic-gate *
730Sstevel@tonic-gate * - simple implementation, no copy "position" across multiple calls
740Sstevel@tonic-gate * - consistent snapshot of an info source
750Sstevel@tonic-gate * - atomic copy works well with whatever locking info source has
760Sstevel@tonic-gate * - one portable tool to get rds info across implementations
770Sstevel@tonic-gate * - long-lived tool can get info without allocating
780Sstevel@tonic-gate *
790Sstevel@tonic-gate * at the following costs:
800Sstevel@tonic-gate *
810Sstevel@tonic-gate * - info source copy must be pinned, may be "large"
820Sstevel@tonic-gate */
830Sstevel@tonic-gate
840Sstevel@tonic-gatestatic kmutex_t rdsv3_info_lock;
850Sstevel@tonic-gatestatic rdsv3_info_func rdsv3_info_funcs[RDSV3_INFO_LAST - RDSV3_INFO_FIRST + 1];
860Sstevel@tonic-gate
870Sstevel@tonic-gatevoid
880Sstevel@tonic-gaterdsv3_info_register_func(int optname, rdsv3_info_func func)
890Sstevel@tonic-gate{
900Sstevel@tonic-gate	int offset = optname - RDSV3_INFO_FIRST;
910Sstevel@tonic-gate
92	ASSERT(optname >= RDSV3_INFO_FIRST && optname <= RDSV3_INFO_LAST);
93
94	mutex_enter(&rdsv3_info_lock);
95	rdsv3_info_funcs[offset] = func;
96	mutex_exit(&rdsv3_info_lock);
97}
98
99/* ARGSUSED */
100void
101rdsv3_info_deregister_func(int optname, rdsv3_info_func func)
102{
103	int offset = optname - RDSV3_INFO_FIRST;
104
105	ASSERT(optname >= RDSV3_INFO_FIRST && optname <= RDSV3_INFO_LAST);
106
107	mutex_enter(&rdsv3_info_lock);
108	rdsv3_info_funcs[offset] = NULL;
109	mutex_exit(&rdsv3_info_lock);
110}
111
112/*
113 * @optval points to the userspace buffer that the information snapshot
114 * will be copied into.
115 *
116 * @optlen on input is the size of the buffer in userspace.  @optlen
117 * on output is the size of the requested snapshot in bytes.
118 *
119 * This function returns -errno if there is a failure, particularly -ENOSPC
120 * if the given userspace buffer was not large enough to fit the snapshot.
121 * On success it returns the positive number of bytes of each array element
122 * in the snapshot.
123 */
124int
125rdsv3_info_getsockopt(struct rsock *sock, int optname, char *optval,
126    socklen_t *optlen)
127{
128	struct rdsv3_info_iterator iter;
129	struct rdsv3_info_lengths lens;
130	rdsv3_info_func func;
131
132	func = rdsv3_info_funcs[optname - RDSV3_INFO_FIRST];
133	if (func == NULL) {
134		return (-ENOPROTOOPT);
135	}
136
137	if (*optlen == sizeof (struct rdsv3_info_lengths)) {
138		iter.addr = NULL;
139	} else {
140		iter.addr = optval;
141	}
142
143	iter.offset = 0;
144
145	func(sock, *optlen, &iter, &lens);
146	ASSERT(lens.each != 0);
147
148	if (iter.addr == NULL) {
149		bcopy(&lens, optval, sizeof (struct rdsv3_info_lengths));
150	} else {
151		*optlen = lens.nr * lens.each;
152	}
153
154	return (0);
155}
156