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 <linux/lustre/lustre_ver.h>
44 #include <lustre_ioctl_old.h>
46 #include "lustreapi_internal.h"
48 int llapi_ioctl_pack(struct obd_ioctl_data *data, char **pbuf, int max_len)
50 struct obd_ioctl_data *overlay;
53 data->ioc_len = obd_ioctl_packlen(data);
54 data->ioc_version = OBD_IOCTL_VERSION;
56 if (*pbuf != NULL && data->ioc_len > max_len) {
57 llapi_error(LLAPI_MSG_ERROR, -EINVAL,
58 "pbuf = %p, ioc_len = %u, max_len = %d",
59 *pbuf, data->ioc_len, max_len);
64 *pbuf = malloc(data->ioc_len);
69 overlay = (struct obd_ioctl_data *)*pbuf;
70 memcpy(*pbuf, data, sizeof(*data));
72 ptr = overlay->ioc_bulk;
73 if (data->ioc_inlbuf1) {
74 memcpy(ptr, data->ioc_inlbuf1, data->ioc_inllen1);
75 ptr += __ALIGN_KERNEL(data->ioc_inllen1, 8);
78 if (data->ioc_inlbuf2) {
79 memcpy(ptr, data->ioc_inlbuf2, data->ioc_inllen2);
80 ptr += __ALIGN_KERNEL(data->ioc_inllen2, 8);
83 if (data->ioc_inlbuf3) {
84 memcpy(ptr, data->ioc_inlbuf3, data->ioc_inllen3);
85 ptr += __ALIGN_KERNEL(data->ioc_inllen3, 8);
88 if (data->ioc_inlbuf4) {
89 memcpy(ptr, data->ioc_inlbuf4, data->ioc_inllen4);
90 ptr += __ALIGN_KERNEL(data->ioc_inllen4, 8);
97 * Remap OBD device ioctl cmd to old one in case running with older modules.
98 * Replaces callers that use "l_ioctl(OBD_DEV_ID, ...)".
100 * \param dev_id Lustre device number (from 'lctl dl')
101 * \param cmd ioctl command
102 * \param buf ioctl data argument, usually obd_ioctl_data
104 int llapi_ioctl_dev(int dev_id, unsigned int cmd, void *buf)
109 /* common case, ioctl works as expected */
110 rc = l_ioctl(dev_id, cmd, buf);
111 if (rc >= 0 || errno != ENOTTY)
116 * Use #ifdef instead of version check to minimize the places that a
117 * version change might cause a compiler error in the future.
119 * Version in comment is to allow finding this code for later removal.
121 #ifdef OBD_IOC_BARRIER /* < OBD_OCD_VERSION(2, 19, 53, 0) */
122 case OBD_IOC_BARRIER_V2:
123 oldcmd = OBD_IOC_BARRIER;
126 #ifdef IOC_OSC_SET_ACTIVE /* < OBD_OCD_VERSION(2, 19, 53, 0) */
127 case OBD_IOC_SET_ACTIVE:
128 oldcmd = IOC_OSC_SET_ACTIVE;
136 rc = l_ioctl(dev_id, oldcmd, buf);
142 * Remap regular file ioctl cmd to old one in case running with older modules.
143 * Replaces callers that use "ioctl(fd, ...)".
145 * \param fd open file descriptor
146 * \param cmd ioctl command
147 * \param buf ioctl data argument
149 int llapi_ioctl(int fd, unsigned int cmd, void *buf)
157 /* common case, ioctl works as expected */
158 rc = ioctl(fd, cmd, buf);
159 if (rc >= 0 || errno != ENOTTY)
164 * Use #ifdef instead of version check to minimize the places that a
165 * version change might cause a compiler error in the future.
167 * Version in comment is to allow finding this code for later removal.
169 #ifdef OBD_IOC_GETNAME_OLD /* < OBD_OCD_VERSION(2, 18, 53, 0) */
170 case OBD_IOC_GETDTNAME:
171 oldcmd = OBD_IOC_GETNAME_OLD;
179 rc = ioctl(fd, oldcmd, buf);
184 int llapi_ioctl_unpack(struct obd_ioctl_data *data, char *pbuf, int max_len)
186 struct obd_ioctl_data *overlay;
192 overlay = (struct obd_ioctl_data *)pbuf;
194 /* Preserve the caller's buffer pointers */
195 overlay->ioc_inlbuf1 = data->ioc_inlbuf1;
196 overlay->ioc_inlbuf2 = data->ioc_inlbuf2;
197 overlay->ioc_inlbuf3 = data->ioc_inlbuf3;
198 overlay->ioc_inlbuf4 = data->ioc_inlbuf4;
200 memcpy(data, pbuf, sizeof(*data));
202 ptr = overlay->ioc_bulk;
203 if (data->ioc_inlbuf1) {
204 memcpy(data->ioc_inlbuf1, ptr, data->ioc_inllen1);
205 ptr += __ALIGN_KERNEL(data->ioc_inllen1, 8);
208 if (data->ioc_inlbuf2) {
209 memcpy(data->ioc_inlbuf2, ptr, data->ioc_inllen2);
210 ptr += __ALIGN_KERNEL(data->ioc_inllen2, 8);
213 if (data->ioc_inlbuf3) {
214 memcpy(data->ioc_inlbuf3, ptr, data->ioc_inllen3);
215 ptr += __ALIGN_KERNEL(data->ioc_inllen3, 8);
218 if (data->ioc_inlbuf4) {
219 memcpy(data->ioc_inlbuf4, ptr, data->ioc_inllen4);
220 ptr += __ALIGN_KERNEL(data->ioc_inllen4, 8);