4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * All rights reserved. This program and the accompanying materials
7 * are made available under the terms of the GNU Lesser General Public License
8 * (LGPL) version 2.1 or (at your discretion) any later version.
9 * (LGPL) version 2.1 accompanies this distribution, and is available at
10 * http://www.gnu.org/licenses/lgpl-2.1.html
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
20 * This file is part of Lustre, http://www.lustre.org/
22 * lustre/utils/liblustreapi_ioctl.c
24 * lustreapi library for packing/unpacking obd_ioctl_data structure to
25 * send commands to different OBD devices. Mostly for internal use.
27 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
30 * Copyright (c) 2011, 2017, Intel Corporation.
32 * Copyright (c) 2023, DataDirect Networks Storage.
37 #include <sys/ioctl.h>
40 #include <lustre/lustreapi.h>
41 #include <libcfs/util/ioctl.h>
42 #include <linux/lustre/lustre_ioctl.h>
43 #include <lustre_ioctl_old.h>
44 #include <linux/lustre/lustre_ver.h>
46 int llapi_ioctl_pack(struct obd_ioctl_data *data, char **pbuf, int max_len)
48 struct obd_ioctl_data *overlay;
51 data->ioc_len = obd_ioctl_packlen(data);
52 data->ioc_version = OBD_IOCTL_VERSION;
54 if (*pbuf != NULL && data->ioc_len > max_len) {
55 llapi_error(LLAPI_MSG_ERROR, -EINVAL,
56 "pbuf = %p, ioc_len = %u, max_len = %d",
57 *pbuf, data->ioc_len, max_len);
62 *pbuf = malloc(data->ioc_len);
67 overlay = (struct obd_ioctl_data *)*pbuf;
68 memcpy(*pbuf, data, sizeof(*data));
70 ptr = overlay->ioc_bulk;
71 if (data->ioc_inlbuf1) {
72 memcpy(ptr, data->ioc_inlbuf1, data->ioc_inllen1);
73 ptr += __ALIGN_KERNEL(data->ioc_inllen1, 8);
76 if (data->ioc_inlbuf2) {
77 memcpy(ptr, data->ioc_inlbuf2, data->ioc_inllen2);
78 ptr += __ALIGN_KERNEL(data->ioc_inllen2, 8);
81 if (data->ioc_inlbuf3) {
82 memcpy(ptr, data->ioc_inlbuf3, data->ioc_inllen3);
83 ptr += __ALIGN_KERNEL(data->ioc_inllen3, 8);
86 if (data->ioc_inlbuf4) {
87 memcpy(ptr, data->ioc_inlbuf4, data->ioc_inllen4);
88 ptr += __ALIGN_KERNEL(data->ioc_inllen4, 8);
95 * Remap OBD device ioctl cmd to old one in case running with older modules.
96 * Replaces callers that use "l_ioctl(OBD_DEV_ID, ...)".
98 * \param dev_id Lustre device number (from 'lctl dl')
99 * \param cmd ioctl command
100 * \param buf ioctl data argument, usually obd_ioctl_data
102 int llapi_ioctl_dev(unsigned int dev_id, unsigned int cmd, void *buf)
107 /* common case, ioctl works as expected */
108 rc = l_ioctl(dev_id, cmd, buf);
109 if (rc >= 0 || errno != ENOTTY)
114 * Use #ifdef instead of version check to minimize the places that a
115 * version change might cause a compiler error in the future.
117 * Version in comment is to allow finding this code for later removal.
119 #ifdef OBD_IOC_BARRIER /* < OBD_OCD_VERSION(2, 19, 53, 0) */
120 case OBD_IOC_BARRIER_V2:
121 oldcmd = OBD_IOC_BARRIER;
124 #ifdef IOC_OSC_SET_ACTIVE /* < OBD_OCD_VERSION(2, 19, 53, 0) */
125 case OBD_IOC_SET_ACTIVE:
126 oldcmd = IOC_OSC_SET_ACTIVE;
134 rc = l_ioctl(dev_id, oldcmd, buf);
140 * Remap regular file ioctl cmd to old one in case running with older modules.
141 * Replaces callers that use "ioctl(fd, ...)".
143 * \param fd open file descriptor
144 * \param cmd ioctl command
145 * \param buf ioctl data argument
147 int llapi_ioctl(int fd, unsigned int cmd, void *buf)
155 /* common case, ioctl works as expected */
156 rc = ioctl(fd, cmd, buf);
157 if (rc >= 0 || errno != ENOTTY)
162 * Use #ifdef instead of version check to minimize the places that a
163 * version change might cause a compiler error in the future.
165 * Version in comment is to allow finding this code for later removal.
167 #ifdef OBD_IOC_GETNAME_OLD /* < OBD_OCD_VERSION(2, 18, 53, 0) */
168 case OBD_IOC_GETMDNAME:
169 oldcmd = OBD_IOC_GETNAME_OLD;
177 rc = ioctl(fd, oldcmd, buf);
182 int llapi_ioctl_unpack(struct obd_ioctl_data *data, char *pbuf, int max_len)
184 struct obd_ioctl_data *overlay;
190 overlay = (struct obd_ioctl_data *)pbuf;
192 /* Preserve the caller's buffer pointers */
193 overlay->ioc_inlbuf1 = data->ioc_inlbuf1;
194 overlay->ioc_inlbuf2 = data->ioc_inlbuf2;
195 overlay->ioc_inlbuf3 = data->ioc_inlbuf3;
196 overlay->ioc_inlbuf4 = data->ioc_inlbuf4;
198 memcpy(data, pbuf, sizeof(*data));
200 ptr = overlay->ioc_bulk;
201 if (data->ioc_inlbuf1) {
202 memcpy(data->ioc_inlbuf1, ptr, data->ioc_inllen1);
203 ptr += __ALIGN_KERNEL(data->ioc_inllen1, 8);
206 if (data->ioc_inlbuf2) {
207 memcpy(data->ioc_inlbuf2, ptr, data->ioc_inllen2);
208 ptr += __ALIGN_KERNEL(data->ioc_inllen2, 8);
211 if (data->ioc_inlbuf3) {
212 memcpy(data->ioc_inlbuf3, ptr, data->ioc_inllen3);
213 ptr += __ALIGN_KERNEL(data->ioc_inllen3, 8);
216 if (data->ioc_inlbuf4) {
217 memcpy(data->ioc_inlbuf4, ptr, data->ioc_inllen4);
218 ptr += __ALIGN_KERNEL(data->ioc_inllen4, 8);