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