4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
27 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
31 * This file is part of Lustre, http://www.lustre.org/
32 * Lustre is a trademark of Sun Microsystems, Inc.
34 * lustre/utils/obdiolib.c
36 * Author: Eric Barton <eeb@clusterfs.com>
44 #include <sys/ioctl.h>
45 #include <sys/types.h>
48 #include <liblustre.h>
52 obdio_iocinit (struct obdio_conn *conn)
54 memset (&conn->oc_data, 0, sizeof (conn->oc_data));
55 conn->oc_data.ioc_version = OBD_IOCTL_VERSION;
56 conn->oc_data.ioc_dev = conn->oc_device;
57 conn->oc_data.ioc_len = sizeof (conn->oc_data);
61 obdio_ioctl (struct obdio_conn *conn, int cmd)
63 char *buf = conn->oc_buffer;
67 rc = obd_ioctl_pack (&conn->oc_data, &buf, sizeof (conn->oc_buffer));
69 fprintf(stderr, "%s: obd_ioctl_pack: %d (%s)\n",
70 __FUNCTION__, rc, strerror(errno));
74 rc = ioctl (conn->oc_fd, cmd, buf);
78 rc2 = obd_ioctl_unpack (&conn->oc_data, buf, sizeof (conn->oc_buffer));
80 fprintf(stderr, "%s: obd_ioctl_unpack: %d (%s)\n",
81 __FUNCTION__, rc2, strerror(errno));
89 obdio_connect (int device)
91 struct obdio_conn *conn;
93 conn = malloc (sizeof (*conn));
95 fprintf (stderr, "%s: no memory\n", __FUNCTION__);
98 memset (conn, 0, sizeof (*conn));
100 conn->oc_fd = open ("/dev/obd", O_RDWR);
101 if (conn->oc_fd < 0) {
102 fprintf(stderr, "%s: Can't open /dev/obd: %s\n",
103 __FUNCTION__, strerror(errno));
107 conn->oc_device = device;
116 obdio_disconnect (struct obdio_conn *conn, int flags)
119 /* obdclass will automatically close on last ref */
124 obdio_pread (struct obdio_conn *conn, __u64 oid,
125 void *buffer, __u32 count, __u64 offset)
127 obdio_iocinit (conn);
129 ostid_set_id(&conn->oc_data.ioc_obdo1.o_oi, oid);
130 conn->oc_data.ioc_obdo1.o_mode = S_IFREG;
131 conn->oc_data.ioc_obdo1.o_valid =
132 OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
134 conn->oc_data.ioc_pbuf2 = buffer;
135 conn->oc_data.ioc_plen2 = count;
136 conn->oc_data.ioc_count = count;
137 conn->oc_data.ioc_offset = offset;
139 return (obdio_ioctl (conn, OBD_IOC_BRW_READ));
143 obdio_pwrite (struct obdio_conn *conn, __u64 oid,
144 void *buffer, __u32 count, __u64 offset)
146 obdio_iocinit (conn);
148 ostid_set_id(&conn->oc_data.ioc_obdo1.o_oi, oid);
149 conn->oc_data.ioc_obdo1.o_mode = S_IFREG;
150 conn->oc_data.ioc_obdo1.o_valid =
151 OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
153 conn->oc_data.ioc_pbuf1 = (void*)1;
154 conn->oc_data.ioc_plen1 = 1;
155 conn->oc_data.ioc_pbuf2 = buffer;
156 conn->oc_data.ioc_plen2 = count;
157 conn->oc_data.ioc_count = count;
158 conn->oc_data.ioc_offset = offset;
160 return (obdio_ioctl (conn, OBD_IOC_BRW_WRITE));
164 obdio_enqueue (struct obdio_conn *conn, __u64 oid,
165 int mode, __u64 offset, __u32 count,
166 struct lustre_handle *lh)
170 obdio_iocinit (conn);
172 ostid_set_id(&conn->oc_data.ioc_obdo1.o_oi, oid);
173 conn->oc_data.ioc_obdo1.o_mode = S_IFREG;
174 conn->oc_data.ioc_obdo1.o_valid =
175 OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
177 conn->oc_data.ioc_conn1 = mode;
178 conn->oc_data.ioc_count = count;
179 conn->oc_data.ioc_offset = offset;
181 rc = obdio_ioctl (conn, ECHO_IOC_ENQUEUE);
184 *lh = conn->oc_data.ioc_obdo1.o_handle;
190 obdio_cancel (struct obdio_conn *conn, struct lustre_handle *lh)
192 obdio_iocinit (conn);
194 conn->oc_data.ioc_obdo1.o_handle = *lh;
195 conn->oc_data.ioc_obdo1.o_valid = OBD_MD_FLHANDLE;
197 return (obdio_ioctl (conn, ECHO_IOC_CANCEL));
201 obdio_alloc_aligned_buffer (void **spacep, int size)
203 int pagemask = getpagesize() - 1;
204 void *space = malloc(size + pagemask);
209 *spacep = (void *)(((unsigned long)space + pagemask) & ~pagemask);
213 struct obdio_barrier *
214 obdio_new_barrier (__u64 oid, __u64 id, int npeers)
216 struct obdio_barrier *b;
218 b = malloc(sizeof(*b));
220 fprintf(stderr, "%s "LPX64": Can't allocate\n",
227 b->ob_npeers = npeers;
234 obdio_setup_barrier (struct obdio_conn *conn, struct obdio_barrier *b)
236 struct lustre_handle lh;
239 void *space, *fileptr;
240 struct obdio_barrier *fileb;
242 if (b->ob_ordinal != 0 ||
244 fprintf(stderr, "%s: invalid parameter\n", __FUNCTION__);
248 space = obdio_alloc_aligned_buffer(&fileptr, getpagesize());
250 fprintf(stderr, "%s "LPX64": Can't allocate page buffer\n",
251 __FUNCTION__, b->ob_oid);
256 memset(fileb, 0, getpagesize());
259 rc = obdio_enqueue(conn, b->ob_oid, LCK_PW, 0, getpagesize(), &lh);
261 fprintf(stderr, "%s "LPX64": Error on enqueue: %s\n",
262 __FUNCTION__, b->ob_oid, strerror(errno));
266 rc = obdio_pwrite(conn, b->ob_oid, fileb, getpagesize(), 0);
268 fprintf(stderr, "%s "LPX64": Error on write: %s\n",
269 __FUNCTION__, b->ob_oid, strerror(errno));
271 rc2 = obdio_cancel (conn, &lh);
272 if (rc == 0 && rc2 != 0) {
273 fprintf(stderr, "%s "LPX64": Error on cancel: %s\n",
274 __FUNCTION__, b->ob_oid, strerror(errno));
283 obdio_barrier (struct obdio_conn *conn, struct obdio_barrier *b)
285 struct lustre_handle lh;
288 void *space, *fileptr;
289 struct obdio_barrier *fileb;
292 space = obdio_alloc_aligned_buffer(&fileptr, getpagesize());
294 fprintf(stderr, "%s "LPX64": Can't allocate page buffer\n",
295 __FUNCTION__, b->ob_oid);
299 rc = obdio_enqueue(conn, b->ob_oid, LCK_PW, 0, getpagesize(), &lh);
301 fprintf(stderr, "%s "LPX64": Error on PW enqueue: %s\n",
302 __FUNCTION__, b->ob_oid, strerror(errno));
307 memset(fileb, 0xeb, getpagesize());
308 rc = obdio_pread(conn, b->ob_oid, fileb, getpagesize(), 0);
310 fprintf(stderr, "%s "LPX64": Error on initial read: %s\n",
311 __FUNCTION__, b->ob_oid, strerror(errno));
315 if (fileb->ob_id != b->ob_id ||
316 fileb->ob_oid != b->ob_oid ||
317 fileb->ob_npeers != b->ob_npeers ||
318 fileb->ob_count >= b->ob_npeers ||
319 fileb->ob_ordinal != b->ob_ordinal) {
320 fprintf(stderr, "%s "LPX64": corrupt on initial read\n",
321 __FUNCTION__, b->ob_id);
323 " got ["LPX64","LPX64","LPX64","LPX64","LPX64"]\n",
324 fileb->ob_id, fileb->ob_oid, fileb->ob_npeers,
325 fileb->ob_ordinal, fileb->ob_count);
327 " expected ["LPX64","LPX64","LPX64","LPX64","LPX64"]\n",
328 b->ob_id, b->ob_oid, b->ob_npeers,
329 b->ob_ordinal, b->ob_count);
335 if (fileb->ob_count == fileb->ob_npeers) { /* I'm the last joiner */
336 fileb->ob_count = 0; /* join count for next barrier */
337 fileb->ob_ordinal++; /* signal all joined */
340 rc = obdio_pwrite(conn, b->ob_oid, fileb, getpagesize(), 0);
342 fprintf (stderr, "%s "LPX64": Error on initial write: %s\n",
343 __FUNCTION__, b->ob_oid, strerror(errno));
348 b->ob_ordinal++; /* now I wait... */
349 while (fileb->ob_ordinal != b->ob_ordinal) {
350 rc = obdio_cancel (conn, &lh);
352 fprintf(stderr, "%s "LPX64": Error on %s cancel: %s\n",
353 __FUNCTION__, b->ob_oid, mode, strerror(errno));
358 rc = obdio_enqueue(conn, b->ob_oid, LCK_PR,0,getpagesize(),&lh);
360 fprintf(stderr, "%s "LPX64": Error on PR enqueue: %s\n",
361 __FUNCTION__, b->ob_oid, strerror(errno));
365 memset (fileb, 0xeb, getpagesize());
366 rc = obdio_pread(conn, b->ob_oid, fileb, getpagesize(), 0);
368 fprintf(stderr, "%s "LPX64": Error on read: %s\n",
369 __FUNCTION__, b->ob_oid, strerror(errno));
373 if (fileb->ob_id != b->ob_id ||
374 fileb->ob_oid != b->ob_oid ||
375 fileb->ob_npeers != b->ob_npeers ||
376 fileb->ob_count >= b->ob_npeers ||
377 (fileb->ob_ordinal != b->ob_ordinal - 1 &&
378 fileb->ob_ordinal != b->ob_ordinal)) {
379 fprintf(stderr, "%s "LPX64": corrupt\n",
380 __FUNCTION__, b->ob_id);
381 fprintf(stderr, " got ["LPX64","LPX64","LPX64","
383 fileb->ob_id, fileb->ob_oid, fileb->ob_npeers,
384 fileb->ob_ordinal, fileb->ob_count);
385 fprintf(stderr, " expected ["LPX64","LPX64","LPX64
386 ","LPX64","LPX64"]\n",
387 b->ob_id, b->ob_oid, b->ob_npeers,
388 b->ob_ordinal, b->ob_count);
395 rc2 = obdio_cancel (conn, &lh);
396 if (rc == 0 && rc2 != 0) {
397 fprintf(stderr, "%s "LPX64": Error on cancel: %s\n",
398 __FUNCTION__, b->ob_oid, strerror(errno));