1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 only,
10 * as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License version 2 for more details (a copy is included
16 * in the LICENSE file that accompanied this code).
18 * You should have received a copy of the GNU General Public License
19 * version 2 along with this program; If not, see
20 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
22 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23 * CA 95054 USA or visit www.sun.com if you need additional information or
29 * Copyright 2008 Sun Microsystems, Inc. All rights reserved
30 * Use is subject to license terms.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
36 * lustre/utils/obdiolib.c
38 * Author: Eric Barton <eeb@clusterfs.com>
46 #include <sys/ioctl.h>
47 #include <sys/types.h>
50 #include <liblustre.h>
54 obdio_iocinit (struct obdio_conn *conn)
56 memset (&conn->oc_data, 0, sizeof (conn->oc_data));
57 conn->oc_data.ioc_version = OBD_IOCTL_VERSION;
58 conn->oc_data.ioc_dev = conn->oc_device;
59 conn->oc_data.ioc_len = sizeof (conn->oc_data);
63 obdio_ioctl (struct obdio_conn *conn, int cmd)
65 char *buf = conn->oc_buffer;
69 rc = obd_ioctl_pack (&conn->oc_data, &buf, sizeof (conn->oc_buffer));
71 fprintf(stderr, "%s: obd_ioctl_pack: %d (%s)\n",
72 __FUNCTION__, rc, strerror(errno));
76 rc = ioctl (conn->oc_fd, cmd, buf);
80 rc2 = obd_ioctl_unpack (&conn->oc_data, buf, sizeof (conn->oc_buffer));
82 fprintf(stderr, "%s: obd_ioctl_unpack: %d (%s)\n",
83 __FUNCTION__, rc2, strerror(errno));
91 obdio_connect (int device)
93 struct obdio_conn *conn;
95 conn = malloc (sizeof (*conn));
97 fprintf (stderr, "%s: no memory\n", __FUNCTION__);
100 memset (conn, 0, sizeof (*conn));
102 conn->oc_fd = open ("/dev/obd", O_RDWR);
103 if (conn->oc_fd < 0) {
104 fprintf(stderr, "%s: Can't open /dev/obd: %s\n",
105 __FUNCTION__, strerror(errno));
109 conn->oc_device = device;
118 obdio_disconnect (struct obdio_conn *conn, int flags)
121 /* obdclass will automatically close on last ref */
126 obdio_pread (struct obdio_conn *conn, __u64 oid,
127 void *buffer, __u32 count, __u64 offset)
129 obdio_iocinit (conn);
131 conn->oc_data.ioc_obdo1.o_id = oid;
132 conn->oc_data.ioc_obdo1.o_mode = S_IFREG;
133 conn->oc_data.ioc_obdo1.o_valid =
134 OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
136 conn->oc_data.ioc_pbuf2 = buffer;
137 conn->oc_data.ioc_plen2 = count;
138 conn->oc_data.ioc_count = count;
139 conn->oc_data.ioc_offset = offset;
141 return (obdio_ioctl (conn, OBD_IOC_BRW_READ));
145 obdio_pwrite (struct obdio_conn *conn, __u64 oid,
146 void *buffer, __u32 count, __u64 offset)
148 obdio_iocinit (conn);
150 conn->oc_data.ioc_obdo1.o_id = oid;
151 conn->oc_data.ioc_obdo1.o_mode = S_IFREG;
152 conn->oc_data.ioc_obdo1.o_valid =
153 OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
155 conn->oc_data.ioc_pbuf1 = (void*)1;
156 conn->oc_data.ioc_plen1 = 1;
157 conn->oc_data.ioc_pbuf2 = buffer;
158 conn->oc_data.ioc_plen2 = count;
159 conn->oc_data.ioc_count = count;
160 conn->oc_data.ioc_offset = offset;
162 return (obdio_ioctl (conn, OBD_IOC_BRW_WRITE));
166 obdio_enqueue (struct obdio_conn *conn, __u64 oid,
167 int mode, __u64 offset, __u32 count,
168 struct lustre_handle *lh)
172 obdio_iocinit (conn);
174 conn->oc_data.ioc_obdo1.o_id = oid;
175 conn->oc_data.ioc_obdo1.o_mode = S_IFREG;
176 conn->oc_data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
178 conn->oc_data.ioc_conn1 = mode;
179 conn->oc_data.ioc_count = count;
180 conn->oc_data.ioc_offset = offset;
182 rc = obdio_ioctl (conn, ECHO_IOC_ENQUEUE);
185 *lh = conn->oc_data.ioc_obdo1.o_handle;
191 obdio_cancel (struct obdio_conn *conn, struct lustre_handle *lh)
193 obdio_iocinit (conn);
195 conn->oc_data.ioc_obdo1.o_handle = *lh;
196 conn->oc_data.ioc_obdo1.o_valid = OBD_MD_FLHANDLE;
198 return (obdio_ioctl (conn, ECHO_IOC_CANCEL));
202 obdio_alloc_aligned_buffer (void **spacep, int size)
204 int pagemask = getpagesize() - 1;
205 void *space = malloc(size + pagemask);
210 *spacep = (void *)(((unsigned long)space + pagemask) & ~pagemask);
214 struct obdio_barrier *
215 obdio_new_barrier (__u64 oid, __u64 id, int npeers)
217 struct obdio_barrier *b;
219 b = malloc(sizeof(*b));
221 fprintf(stderr, "%s "LPX64": Can't allocate\n",
228 b->ob_npeers = npeers;
235 obdio_setup_barrier (struct obdio_conn *conn, struct obdio_barrier *b)
237 struct lustre_handle lh;
240 void *space, *fileptr;
241 struct obdio_barrier *fileb;
243 if (b->ob_ordinal != 0 ||
245 fprintf(stderr, "%s: invalid parameter\n", __FUNCTION__);
249 space = obdio_alloc_aligned_buffer(&fileptr, getpagesize());
251 fprintf(stderr, "%s "LPX64": Can't allocate page buffer\n",
252 __FUNCTION__, b->ob_oid);
257 memset(fileb, 0, getpagesize());
260 rc = obdio_enqueue(conn, b->ob_oid, LCK_PW, 0, getpagesize(), &lh);
262 fprintf(stderr, "%s "LPX64": Error on enqueue: %s\n",
263 __FUNCTION__, b->ob_oid, strerror(errno));
267 rc = obdio_pwrite(conn, b->ob_oid, fileb, getpagesize(), 0);
269 fprintf(stderr, "%s "LPX64": Error on write: %s\n",
270 __FUNCTION__, b->ob_oid, strerror(errno));
272 rc2 = obdio_cancel (conn, &lh);
273 if (rc == 0 && rc2 != 0) {
274 fprintf(stderr, "%s "LPX64": Error on cancel: %s\n",
275 __FUNCTION__, b->ob_oid, strerror(errno));
284 obdio_barrier (struct obdio_conn *conn, struct obdio_barrier *b)
286 struct lustre_handle lh;
289 void *space, *fileptr;
290 struct obdio_barrier *fileb;
293 space = obdio_alloc_aligned_buffer(&fileptr, getpagesize());
295 fprintf(stderr, "%s "LPX64": Can't allocate page buffer\n",
296 __FUNCTION__, b->ob_oid);
300 rc = obdio_enqueue(conn, b->ob_oid, LCK_PW, 0, getpagesize(), &lh);
302 fprintf(stderr, "%s "LPX64": Error on PW enqueue: %s\n",
303 __FUNCTION__, b->ob_oid, strerror(errno));
308 memset(fileb, 0xeb, getpagesize());
309 rc = obdio_pread(conn, b->ob_oid, fileb, getpagesize(), 0);
311 fprintf(stderr, "%s "LPX64": Error on initial read: %s\n",
312 __FUNCTION__, b->ob_oid, strerror(errno));
316 if (fileb->ob_id != b->ob_id ||
317 fileb->ob_oid != b->ob_oid ||
318 fileb->ob_npeers != b->ob_npeers ||
319 fileb->ob_count >= b->ob_npeers ||
320 fileb->ob_ordinal != b->ob_ordinal) {
321 fprintf(stderr, "%s "LPX64": corrupt on initial read\n",
322 __FUNCTION__, b->ob_id);
324 " got ["LPX64","LPX64","LPX64","LPX64","LPX64"]\n",
325 fileb->ob_id, fileb->ob_oid, fileb->ob_npeers,
326 fileb->ob_ordinal, fileb->ob_count);
328 " expected ["LPX64","LPX64","LPX64","LPX64","LPX64"]\n",
329 b->ob_id, b->ob_oid, b->ob_npeers,
330 b->ob_ordinal, b->ob_count);
336 if (fileb->ob_count == fileb->ob_npeers) { /* I'm the last joiner */
337 fileb->ob_count = 0; /* join count for next barrier */
338 fileb->ob_ordinal++; /* signal all joined */
341 rc = obdio_pwrite(conn, b->ob_oid, fileb, getpagesize(), 0);
343 fprintf (stderr, "%s "LPX64": Error on initial write: %s\n",
344 __FUNCTION__, b->ob_oid, strerror(errno));
349 b->ob_ordinal++; /* now I wait... */
350 while (fileb->ob_ordinal != b->ob_ordinal) {
351 rc = obdio_cancel (conn, &lh);
353 fprintf(stderr, "%s "LPX64": Error on %s cancel: %s\n",
354 __FUNCTION__, b->ob_oid, mode, strerror(errno));
359 rc = obdio_enqueue(conn, b->ob_oid, LCK_PR,0,getpagesize(),&lh);
361 fprintf(stderr, "%s "LPX64": Error on PR enqueue: %s\n",
362 __FUNCTION__, b->ob_oid, strerror(errno));
366 memset (fileb, 0xeb, getpagesize());
367 rc = obdio_pread(conn, b->ob_oid, fileb, getpagesize(), 0);
369 fprintf(stderr, "%s "LPX64": Error on read: %s\n",
370 __FUNCTION__, b->ob_oid, strerror(errno));
374 if (fileb->ob_id != b->ob_id ||
375 fileb->ob_oid != b->ob_oid ||
376 fileb->ob_npeers != b->ob_npeers ||
377 fileb->ob_count >= b->ob_npeers ||
378 (fileb->ob_ordinal != b->ob_ordinal - 1 &&
379 fileb->ob_ordinal != b->ob_ordinal)) {
380 fprintf(stderr, "%s "LPX64": corrupt\n",
381 __FUNCTION__, b->ob_id);
382 fprintf(stderr, " got ["LPX64","LPX64","LPX64","
384 fileb->ob_id, fileb->ob_oid, fileb->ob_npeers,
385 fileb->ob_ordinal, fileb->ob_count);
386 fprintf(stderr, " expected ["LPX64","LPX64","LPX64
387 ","LPX64","LPX64"]\n",
388 b->ob_id, b->ob_oid, b->ob_npeers,
389 b->ob_ordinal, b->ob_count);
396 rc2 = obdio_cancel (conn, &lh);
397 if (rc == 0 && rc2 != 0) {
398 fprintf(stderr, "%s "LPX64": Error on cancel: %s\n",
399 __FUNCTION__, b->ob_oid, strerror(errno));