1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2003 Cluster File Systems, Inc.
5 * Author: Eric Barton <eeb@clusterfs.com>
7 * This file is part of Lustre, http://www.lustre.org.
9 * Lustre is free software; you can redistribute it and/or
10 * modify it under the terms of version 2 of the GNU General Public
11 * License as published by the Free Software Foundation.
13 * Lustre is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with Lustre; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 #include <sys/ioctl.h>
30 #include <sys/types.h>
33 #include <liblustre.h>
37 obdio_iocinit (struct obdio_conn *conn)
39 memset (&conn->oc_data, 0, sizeof (conn->oc_data));
40 conn->oc_data.ioc_version = OBD_IOCTL_VERSION;
41 conn->oc_data.ioc_dev = conn->oc_device;
42 conn->oc_data.ioc_len = sizeof (conn->oc_data);
46 obdio_ioctl (struct obdio_conn *conn, int cmd)
48 char *buf = conn->oc_buffer;
52 rc = obd_ioctl_pack (&conn->oc_data, &buf, sizeof (conn->oc_buffer));
54 fprintf(stderr, "%s: obd_ioctl_pack: %d (%s)\n",
55 __FUNCTION__, rc, strerror(errno));
59 rc = ioctl (conn->oc_fd, cmd, buf);
63 rc2 = obd_ioctl_unpack (&conn->oc_data, buf, sizeof (conn->oc_buffer));
65 fprintf(stderr, "%s: obd_ioctl_unpack: %d (%s)\n",
66 __FUNCTION__, rc2, strerror(errno));
74 obdio_connect (int device)
76 struct obdio_conn *conn;
78 conn = malloc (sizeof (*conn));
80 fprintf (stderr, "%s: no memory\n", __FUNCTION__);
83 memset (conn, 0, sizeof (*conn));
85 conn->oc_fd = open ("/dev/obd", O_RDWR);
86 if (conn->oc_fd < 0) {
87 fprintf(stderr, "%s: Can't open /dev/obd: %s\n",
88 __FUNCTION__, strerror(errno));
92 conn->oc_device = device;
101 obdio_disconnect (struct obdio_conn *conn, int flags)
104 /* obdclass will automatically close on last ref */
109 obdio_pread (struct obdio_conn *conn, uint64_t oid,
110 void *buffer, uint32_t count, uint64_t offset)
112 obdio_iocinit (conn);
114 conn->oc_data.ioc_obdo1.o_id = oid;
115 conn->oc_data.ioc_obdo1.o_mode = S_IFREG;
116 conn->oc_data.ioc_obdo1.o_valid =
117 OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
119 conn->oc_data.ioc_pbuf2 = buffer;
120 conn->oc_data.ioc_plen2 = count;
121 conn->oc_data.ioc_count = count;
122 conn->oc_data.ioc_offset = offset;
124 return (obdio_ioctl (conn, OBD_IOC_BRW_READ));
128 obdio_pwrite (struct obdio_conn *conn, uint64_t oid,
129 void *buffer, uint32_t count, uint64_t offset)
131 obdio_iocinit (conn);
133 conn->oc_data.ioc_obdo1.o_id = oid;
134 conn->oc_data.ioc_obdo1.o_mode = S_IFREG;
135 conn->oc_data.ioc_obdo1.o_valid =
136 OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
138 conn->oc_data.ioc_pbuf2 = buffer;
139 conn->oc_data.ioc_plen2 = count;
140 conn->oc_data.ioc_count = count;
141 conn->oc_data.ioc_offset = offset;
143 return (obdio_ioctl (conn, OBD_IOC_BRW_WRITE));
147 obdio_enqueue (struct obdio_conn *conn, uint64_t oid,
148 int mode, uint64_t offset, uint32_t count,
149 struct lustre_handle *lh)
153 obdio_iocinit (conn);
155 conn->oc_data.ioc_obdo1.o_id = oid;
156 conn->oc_data.ioc_obdo1.o_mode = S_IFREG;
157 conn->oc_data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
159 conn->oc_data.ioc_conn1 = mode;
160 conn->oc_data.ioc_count = count;
161 conn->oc_data.ioc_offset = offset;
163 rc = obdio_ioctl (conn, ECHO_IOC_ENQUEUE);
166 memcpy (lh, obdo_handle (&conn->oc_data.ioc_obdo1), sizeof (*lh));
172 obdio_cancel (struct obdio_conn *conn, struct lustre_handle *lh)
174 obdio_iocinit (conn);
176 memcpy (obdo_handle (&conn->oc_data.ioc_obdo1), lh, sizeof (*lh));
177 conn->oc_data.ioc_obdo1.o_valid = OBD_MD_FLHANDLE;
179 return (obdio_ioctl (conn, ECHO_IOC_CANCEL));
183 obdio_alloc_aligned_buffer (void **spacep, int size)
185 int pagemask = getpagesize() - 1;
186 void *space = malloc(size + pagemask);
191 *spacep = (void *)(((unsigned long)space + pagemask) & ~pagemask);
195 struct obdio_barrier *
196 obdio_new_barrier (uint64_t oid, uint64_t id, int npeers)
198 struct obdio_barrier *b;
200 b = malloc(sizeof(*b));
202 fprintf(stderr, "%s "LPX64": Can't allocate\n",
209 b->ob_npeers = npeers;
216 obdio_setup_barrier (struct obdio_conn *conn, struct obdio_barrier *b)
218 struct lustre_handle lh;
221 void *space, *fileptr;
222 struct obdio_barrier *fileb;
224 if (b->ob_ordinal != 0 ||
226 fprintf(stderr, "%s: invalid parameter\n", __FUNCTION__);
230 space = obdio_alloc_aligned_buffer(&fileptr, getpagesize());
232 fprintf(stderr, "%s "LPX64": Can't allocate page buffer\n",
233 __FUNCTION__, b->ob_oid);
238 memset(fileb, 0, getpagesize());
241 rc = obdio_enqueue(conn, b->ob_oid, LCK_PW, 0, getpagesize(), &lh);
243 fprintf(stderr, "%s "LPX64": Error on enqueue: %s\n",
244 __FUNCTION__, b->ob_oid, strerror(errno));
248 rc = obdio_pwrite(conn, b->ob_oid, fileb, getpagesize(), 0);
250 fprintf(stderr, "%s "LPX64": Error on write: %s\n",
251 __FUNCTION__, b->ob_oid, strerror(errno));
253 rc2 = obdio_cancel (conn, &lh);
254 if (rc == 0 && rc2 != 0) {
255 fprintf(stderr, "%s "LPX64": Error on cancel: %s\n",
256 __FUNCTION__, b->ob_oid, strerror(errno));
265 obdio_barrier (struct obdio_conn *conn, struct obdio_barrier *b)
267 struct lustre_handle lh;
270 void *space, *fileptr;
271 struct obdio_barrier *fileb;
274 space = obdio_alloc_aligned_buffer(&fileptr, getpagesize());
276 fprintf(stderr, "%s "LPX64": Can't allocate page buffer\n",
277 __FUNCTION__, b->ob_oid);
281 rc = obdio_enqueue(conn, b->ob_oid, LCK_PW, 0, getpagesize(), &lh);
283 fprintf(stderr, "%s "LPX64": Error on PW enqueue: %s\n",
284 __FUNCTION__, b->ob_oid, strerror(errno));
289 memset(fileb, 0xeb, getpagesize());
290 rc = obdio_pread(conn, b->ob_oid, fileb, getpagesize(), 0);
292 fprintf(stderr, "%s "LPX64": Error on initial read: %s\n",
293 __FUNCTION__, b->ob_oid, strerror(errno));
297 if (fileb->ob_id != b->ob_id ||
298 fileb->ob_oid != b->ob_oid ||
299 fileb->ob_npeers != b->ob_npeers ||
300 fileb->ob_count >= b->ob_npeers ||
301 fileb->ob_ordinal != b->ob_ordinal) {
302 fprintf(stderr, "%s "LPX64": corrupt on initial read\n",
303 __FUNCTION__, b->ob_id);
305 " got ["LPX64","LPX64","LPX64","LPX64","LPX64"]\n",
306 fileb->ob_id, fileb->ob_oid, fileb->ob_npeers,
307 fileb->ob_ordinal, fileb->ob_count);
309 " expected ["LPX64","LPX64","LPX64","LPX64","LPX64"]\n",
310 b->ob_id, b->ob_oid, b->ob_npeers,
311 b->ob_ordinal, b->ob_count);
317 if (fileb->ob_count == fileb->ob_npeers) { /* I'm the last joiner */
318 fileb->ob_count = 0; /* join count for next barrier */
319 fileb->ob_ordinal++; /* signal all joined */
322 rc = obdio_pwrite(conn, b->ob_oid, fileb, getpagesize(), 0);
324 fprintf (stderr, "%s "LPX64": Error on initial write: %s\n",
325 __FUNCTION__, b->ob_oid, strerror(errno));
330 b->ob_ordinal++; /* now I wait... */
331 while (fileb->ob_ordinal != b->ob_ordinal) {
332 rc = obdio_cancel (conn, &lh);
334 fprintf(stderr, "%s "LPX64": Error on %s cancel: %s\n",
335 __FUNCTION__, b->ob_oid, mode, strerror(errno));
340 rc = obdio_enqueue(conn, b->ob_oid, LCK_PR,0,getpagesize(),&lh);
342 fprintf(stderr, "%s "LPX64": Error on PR enqueue: %s\n",
343 __FUNCTION__, b->ob_oid, strerror(errno));
347 memset (fileb, 0xeb, getpagesize());
348 rc = obdio_pread(conn, b->ob_oid, fileb, getpagesize(), 0);
350 fprintf(stderr, "%s "LPX64": Error on read: %s\n",
351 __FUNCTION__, b->ob_oid, strerror(errno));
355 if (fileb->ob_id != b->ob_id ||
356 fileb->ob_oid != b->ob_oid ||
357 fileb->ob_npeers != b->ob_npeers ||
358 fileb->ob_count >= b->ob_npeers ||
359 (fileb->ob_ordinal != b->ob_ordinal - 1 &&
360 fileb->ob_ordinal != b->ob_ordinal)) {
361 fprintf(stderr, "%s "LPX64": corrupt\n",
362 __FUNCTION__, b->ob_id);
363 fprintf(stderr, " got ["LPX64","LPX64","LPX64","
365 fileb->ob_id, fileb->ob_oid, fileb->ob_npeers,
366 fileb->ob_ordinal, fileb->ob_count);
367 fprintf(stderr, " expected ["LPX64","LPX64","LPX64
368 ","LPX64","LPX64"]\n",
369 b->ob_id, b->ob_oid, b->ob_npeers,
370 b->ob_ordinal, b->ob_count);
377 rc2 = obdio_cancel (conn, &lh);
378 if (rc == 0 && rc2 != 0) {
379 fprintf(stderr, "%s "LPX64": Error on cancel: %s\n",
380 __FUNCTION__, b->ob_oid, strerror(errno));