Whamcloud - gitweb
LU-4423 ptlrpc: Fix function prototypes
[fs/lustre-release.git] / lustre / utils / obdiolib.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
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.
9  *
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).
15  *
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
19  *
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
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2013, Intel Corporation.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lustre/utils/obdiolib.c
37  *
38  * Author: Eric Barton <eeb@clusterfs.com>
39  */
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <errno.h>
44 #include <string.h>
45 #include <fcntl.h>
46 #include <sys/ioctl.h>
47 #include <sys/types.h>
48 #include <sys/stat.h>
49
50 #include <liblustre.h>
51 #include "obdiolib.h"
52
53 void
54 obdio_iocinit (struct obdio_conn *conn)
55 {
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);
60 }
61
62 int
63 obdio_ioctl (struct obdio_conn *conn, int cmd)
64 {
65         char *buf = conn->oc_buffer;
66         int   rc;
67         int   rc2;
68
69         rc = obd_ioctl_pack (&conn->oc_data, &buf, sizeof (conn->oc_buffer));
70         if (rc != 0) {
71                 fprintf(stderr, "%s: obd_ioctl_pack: %d (%s)\n",
72                         __FUNCTION__, rc, strerror(errno));
73                 abort();
74         }
75
76         rc = ioctl (conn->oc_fd, cmd, buf);
77         if (rc != 0)
78                 return (rc);
79
80         rc2 = obd_ioctl_unpack (&conn->oc_data, buf, sizeof (conn->oc_buffer));
81         if (rc2 != 0) {
82                 fprintf(stderr, "%s: obd_ioctl_unpack: %d (%s)\n",
83                         __FUNCTION__, rc2, strerror(errno));
84                 abort ();
85         }
86
87         return (rc);
88 }
89
90 struct obdio_conn *
91 obdio_connect (int device)
92 {
93         struct obdio_conn  *conn;
94
95         conn = malloc (sizeof (*conn));
96         if (conn == NULL) {
97                 fprintf (stderr, "%s: no memory\n", __FUNCTION__);
98                 return (NULL);
99         }
100         memset (conn, 0, sizeof (*conn));
101
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));
106                 goto failed;
107         }
108
109         conn->oc_device = device;
110         return (conn);
111
112  failed:
113         free (conn);
114         return (NULL);
115 }
116
117 void
118 obdio_disconnect (struct obdio_conn *conn, int flags)
119 {
120         close (conn->oc_fd);
121         /* obdclass will automatically close on last ref */
122         free (conn);
123 }
124
125 int
126 obdio_pread (struct obdio_conn *conn, __u64 oid,
127              void *buffer, __u32 count, __u64 offset)
128 {
129         obdio_iocinit (conn);
130
131         ostid_set_id(&conn->oc_data.ioc_obdo1.o_oi, 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;
135
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;
140
141         return (obdio_ioctl (conn, OBD_IOC_BRW_READ));
142 }
143
144 int
145 obdio_pwrite (struct obdio_conn *conn, __u64 oid,
146               void *buffer, __u32 count, __u64 offset)
147 {
148         obdio_iocinit (conn);
149
150         ostid_set_id(&conn->oc_data.ioc_obdo1.o_oi, 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;
154
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;
161
162         return (obdio_ioctl (conn, OBD_IOC_BRW_WRITE));
163 }
164
165 int
166 obdio_enqueue (struct obdio_conn *conn, __u64 oid,
167                int mode, __u64 offset, __u32 count,
168                struct lustre_handle *lh)
169 {
170         int   rc;
171
172         obdio_iocinit (conn);
173
174         ostid_set_id(&conn->oc_data.ioc_obdo1.o_oi, oid);
175         conn->oc_data.ioc_obdo1.o_mode = S_IFREG;
176         conn->oc_data.ioc_obdo1.o_valid =
177                 OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
178
179         conn->oc_data.ioc_conn1 = mode;
180         conn->oc_data.ioc_count = count;
181         conn->oc_data.ioc_offset = offset;
182
183         rc = obdio_ioctl (conn, ECHO_IOC_ENQUEUE);
184
185         if (rc == 0)
186                 *lh = conn->oc_data.ioc_obdo1.o_handle;
187
188         return (rc);
189 }
190
191 int
192 obdio_cancel (struct obdio_conn *conn, struct lustre_handle *lh)
193 {
194         obdio_iocinit (conn);
195
196         conn->oc_data.ioc_obdo1.o_handle = *lh;
197         conn->oc_data.ioc_obdo1.o_valid = OBD_MD_FLHANDLE;
198
199         return (obdio_ioctl (conn, ECHO_IOC_CANCEL));
200 }
201
202 void *
203 obdio_alloc_aligned_buffer (void **spacep, int size)
204 {
205         int   pagemask = getpagesize() - 1;
206         void *space = malloc(size + pagemask);
207
208         if (space == NULL)
209                 return (NULL);
210
211         *spacep = (void *)(((unsigned long)space + pagemask) & ~pagemask);
212         return space;
213 }
214
215 struct obdio_barrier *
216 obdio_new_barrier (__u64 oid, __u64 id, int npeers)
217 {
218         struct obdio_barrier *b;
219
220         b = malloc(sizeof(*b));
221         if (b == NULL) {
222                 fprintf(stderr, "%s "LPX64": Can't allocate\n",
223                         __FUNCTION__, oid);
224                 return(NULL);
225         }
226
227         b->ob_id = id;
228         b->ob_oid = oid;
229         b->ob_npeers = npeers;
230         b->ob_ordinal = 0;
231         b->ob_count = 0;
232         return (b);
233 }
234
235 int
236 obdio_setup_barrier (struct obdio_conn *conn, struct obdio_barrier *b)
237 {
238         struct lustre_handle    lh;
239         int                     rc;
240         int                     rc2;
241         void                   *space, *fileptr;
242         struct obdio_barrier   *fileb;
243
244         if (b->ob_ordinal != 0 ||
245             b->ob_count != 0) {
246                 fprintf(stderr, "%s: invalid parameter\n", __FUNCTION__);
247                 abort ();
248         }
249
250         space = obdio_alloc_aligned_buffer(&fileptr, getpagesize());
251         if (space == NULL) {
252                 fprintf(stderr, "%s "LPX64": Can't allocate page buffer\n",
253                         __FUNCTION__, b->ob_oid);
254                 return (-1);
255         }
256
257         fileb = fileptr;
258         memset(fileb, 0, getpagesize());
259         *fileb = *b;
260
261         rc = obdio_enqueue(conn, b->ob_oid, LCK_PW, 0, getpagesize(), &lh);
262         if (rc != 0) {
263                 fprintf(stderr, "%s "LPX64": Error on enqueue: %s\n",
264                         __FUNCTION__, b->ob_oid, strerror(errno));
265                 goto out;
266         }
267
268         rc = obdio_pwrite(conn, b->ob_oid, fileb, getpagesize(), 0);
269         if (rc != 0)
270                 fprintf(stderr, "%s "LPX64": Error on write: %s\n",
271                         __FUNCTION__, b->ob_oid, strerror(errno));
272
273         rc2 = obdio_cancel (conn, &lh);
274         if (rc == 0 && rc2 != 0) {
275                 fprintf(stderr, "%s "LPX64": Error on cancel: %s\n",
276                         __FUNCTION__, b->ob_oid, strerror(errno));
277                 rc = rc2;
278         }
279  out:
280         free (space);
281         return (rc);
282 }
283
284 int
285 obdio_barrier (struct obdio_conn *conn, struct obdio_barrier *b)
286 {
287         struct lustre_handle   lh;
288         int                    rc;
289         int                    rc2;
290         void                  *space, *fileptr;
291         struct obdio_barrier  *fileb;
292         char                  *mode;
293
294         space = obdio_alloc_aligned_buffer(&fileptr, getpagesize());
295         if (space == NULL) {
296                 fprintf(stderr, "%s "LPX64": Can't allocate page buffer\n",
297                         __FUNCTION__, b->ob_oid);
298                 return (-1);
299         }
300
301         rc = obdio_enqueue(conn, b->ob_oid, LCK_PW, 0, getpagesize(), &lh);
302         if (rc != 0) {
303                 fprintf(stderr, "%s "LPX64": Error on PW enqueue: %s\n",
304                         __FUNCTION__, b->ob_oid, strerror(errno));
305                 goto out_1;
306         }
307
308         fileb = fileptr;
309         memset(fileb, 0xeb, getpagesize());
310         rc = obdio_pread(conn, b->ob_oid, fileb, getpagesize(), 0);
311         if (rc != 0) {
312                 fprintf(stderr, "%s "LPX64": Error on initial read: %s\n",
313                         __FUNCTION__, b->ob_oid, strerror(errno));
314                 goto out_2;
315         }
316
317         if (fileb->ob_id != b->ob_id ||
318             fileb->ob_oid != b->ob_oid ||
319             fileb->ob_npeers != b->ob_npeers ||
320             fileb->ob_count >= b->ob_npeers ||
321             fileb->ob_ordinal != b->ob_ordinal) {
322                 fprintf(stderr, "%s "LPX64": corrupt on initial read\n",
323                         __FUNCTION__, b->ob_id);
324                 fprintf(stderr,
325                         "  got ["LPX64","LPX64","LPX64","LPX64","LPX64"]\n",
326                         fileb->ob_id, fileb->ob_oid, fileb->ob_npeers,
327                         fileb->ob_ordinal, fileb->ob_count);
328                 fprintf(stderr,
329                        "  expected ["LPX64","LPX64","LPX64","LPX64","LPX64"]\n",
330                         b->ob_id, b->ob_oid, b->ob_npeers,
331                         b->ob_ordinal, b->ob_count);
332                 rc = -1;
333                 goto out_2;
334         }
335
336         fileb->ob_count++;
337         if (fileb->ob_count == fileb->ob_npeers) { /* I'm the last joiner */
338                 fileb->ob_count = 0;       /* join count for next barrier */
339                 fileb->ob_ordinal++;                 /* signal all joined */
340         }
341
342         rc = obdio_pwrite(conn, b->ob_oid, fileb, getpagesize(), 0);
343         if (rc != 0) {
344                 fprintf (stderr, "%s "LPX64": Error on initial write: %s\n",
345                          __FUNCTION__, b->ob_oid, strerror(errno));
346                 goto out_2;
347         }
348
349         mode = "PW";
350         b->ob_ordinal++;           /* now I wait... */
351         while (fileb->ob_ordinal != b->ob_ordinal) {
352                 rc = obdio_cancel (conn, &lh);
353                 if (rc != 0) {
354                         fprintf(stderr, "%s "LPX64": Error on %s cancel: %s\n",
355                                 __FUNCTION__, b->ob_oid, mode, strerror(errno));
356                         goto out_1;
357                 }
358
359                 mode = "PR";
360                 rc = obdio_enqueue(conn, b->ob_oid, LCK_PR,0,getpagesize(),&lh);
361                 if (rc != 0) {
362                         fprintf(stderr, "%s "LPX64": Error on PR enqueue: %s\n",
363                                 __FUNCTION__, b->ob_oid, strerror(errno));
364                         goto out_1;
365                 }
366
367                 memset (fileb, 0xeb, getpagesize());
368                 rc = obdio_pread(conn, b->ob_oid, fileb, getpagesize(), 0);
369                 if (rc != 0) {
370                         fprintf(stderr, "%s "LPX64": Error on read: %s\n",
371                                 __FUNCTION__, b->ob_oid, strerror(errno));
372                         goto out_2;
373                 }
374
375                 if (fileb->ob_id != b->ob_id ||
376                     fileb->ob_oid != b->ob_oid ||
377                     fileb->ob_npeers != b->ob_npeers ||
378                     fileb->ob_count >= b->ob_npeers ||
379                     (fileb->ob_ordinal != b->ob_ordinal - 1 &&
380                      fileb->ob_ordinal != b->ob_ordinal)) {
381                         fprintf(stderr, "%s "LPX64": corrupt\n",
382                                 __FUNCTION__, b->ob_id);
383                         fprintf(stderr, "  got ["LPX64","LPX64","LPX64","
384                                 LPX64","LPX64"]\n",
385                                 fileb->ob_id, fileb->ob_oid, fileb->ob_npeers,
386                                 fileb->ob_ordinal, fileb->ob_count);
387                         fprintf(stderr, "  expected ["LPX64","LPX64","LPX64
388                                 ","LPX64","LPX64"]\n",
389                                 b->ob_id, b->ob_oid, b->ob_npeers,
390                                 b->ob_ordinal, b->ob_count);
391                         rc = -1;
392                         goto out_2;
393                 }
394         }
395
396  out_2:
397         rc2 = obdio_cancel (conn, &lh);
398         if (rc == 0 && rc2 != 0) {
399                 fprintf(stderr, "%s "LPX64": Error on cancel: %s\n",
400                         __FUNCTION__, b->ob_oid, strerror(errno));
401                 rc = rc2;
402         }
403  out_1:
404         free (space);
405         return (rc);
406 }