Whamcloud - gitweb
merge b_devel into HEAD, which will become 0.7.3
[fs/lustre-release.git] / lustre / utils / obdio.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (C) 2002 Cluster File Systems, Inc.
5  *   Author: Eric Barton <eeb@clusterfs.com>
6  *
7  *   This file is part of Lustre, http://www.lustre.org.
8  *
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.
12  *
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.
17  *
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.
21  *
22  */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <errno.h>
27 #include <string.h>
28
29 #include <liblustre.h>
30 #include "obdiolib.h"
31
32 int
33 obdio_test_fixed_extent (struct obdio_conn *conn,
34                          uint32_t myhid, uint32_t mypid,
35                          int reps, int locked, uint64_t oid,
36                          uint64_t offset, uint32_t size)
37 {
38         struct lustre_handle fh;
39         struct lustre_handle lh;
40         void                *space;
41         void                *buffer;
42         uint32_t            *ibuf;
43         int                  i;
44         int                  j;
45         int                  rc;
46         int                  rc2;
47
48         rc = obdio_open (conn, oid, &fh);
49         if (rc != 0) {
50                 fprintf (stderr, "Failed to open object "LPX64": %s\n",
51                          oid, strerror (errno));
52                 return (rc);
53         }
54
55         buffer = obdio_alloc_aligned_buffer (&space, size);
56         if (buffer == NULL) {
57                 fprintf (stderr, "Can't allocate buffer size %d\n", size);
58                 rc = -1;
59                 goto out_0;
60         }
61
62         for (i = 0; i < reps; i++) {
63                 ibuf = (uint32_t *) buffer;
64                 for (j = 0; j < size / (4 * sizeof (*ibuf)); j++) {
65                         ibuf[0] = myhid;
66                         ibuf[1] = mypid;
67                         ibuf[2] = i;
68                         ibuf[3] = j;
69                         ibuf += 4;
70                 }
71
72                 if (locked) {
73                         rc = obdio_enqueue (conn, oid, LCK_PW, offset, size, &lh);
74                         if (rc != 0) {
75                                 fprintf (stderr, "Error on enqueue "LPX64" @ "LPU64" for %u: %s\n",
76                                          oid, offset, size, strerror (errno));
77                                 goto out_1;
78                         }
79                 }
80
81                 rc = obdio_pwrite (conn, oid, buffer, size, offset);
82                 if (rc != 0) {
83                         fprintf (stderr, "Error writing "LPX64" @ "LPU64" for %u: %s\n",
84                                  oid, offset, size, strerror (errno));
85                         if (locked)
86                                 obdio_cancel (conn, &lh);
87                         rc = -1;
88                         goto out_1;
89                 }
90
91                 memset (buffer, 0xbb, size);
92
93                 rc = obdio_pread (conn, oid, buffer, size, offset);
94                 if (rc != 0) {
95                         fprintf (stderr, "Error reading "LPX64" @ "LPU64" for %u: %s\n",
96                                  oid, offset, size, strerror (errno));
97                         if (locked)
98                                 obdio_cancel (conn, &lh);
99                         rc = -1;
100                         goto out_1;
101                 }
102
103                 if (locked) {
104                         rc = obdio_cancel (conn, &lh);
105                         if (rc != 0) {
106                                 fprintf (stderr, "Error on cancel "LPX64" @ "LPU64" for %u: %s\n",
107                                          oid, offset, size, strerror (errno));
108                                 rc = -1;
109                                 goto out_1;
110                         }
111                 }
112
113                 ibuf = (uint32_t *) buffer;
114                 for (j = 0; j < size / (4 * sizeof (*ibuf)); j++) {
115                         if (ibuf[0] != myhid ||
116                             ibuf[1] != mypid ||
117                             ibuf[2] != i ||
118                             ibuf[3] != j) {
119                                 fprintf (stderr, "Error checking "LPX64" @ "LPU64" for %u, chunk %d\n",
120                                          oid, offset, size, j);
121                                 fprintf (stderr, "Expected [%x,%x,%x,%x], got [%x,%x,%x,%x]\n",
122                                          myhid, mypid, i, j, ibuf[0], ibuf[1], ibuf[2], ibuf[3]);
123                                 rc = -1;
124                                 goto out_1;
125                         }
126                         ibuf += 4;
127                 }
128         }
129  out_1:
130         free (space);
131  out_0:
132         rc2 = obdio_close (conn, oid, &fh);
133         if (rc2 != 0)
134                 fprintf (stderr, "Error closing object "LPX64": %s\n",
135                          oid, strerror (errno));
136         return (rc);
137 }
138
139 int
140 parse_kmg (uint64_t *valp, char *str)
141 {
142         uint64_t        val;
143         char            mod[32];
144
145         switch (sscanf (str, LPU64"%1[gGmMkK]", &val, mod))
146         {
147         default:
148                 return (-1);
149
150         case 1:
151                 *valp = val;
152                 return (0);
153
154         case 2:
155                 switch (*mod)
156                 {
157                 case 'g':
158                 case 'G':
159                         *valp = val << 30;
160                         return (0);
161
162                 case 'm':
163                 case 'M':
164                         *valp = val << 20;
165                         return (0);
166
167                 case 'k':
168                 case 'K':
169                         *valp = val << 10;
170                         return (0);
171
172                 default:
173                         *valp = val;
174                         return (0);
175                 }
176         }
177 }
178
179 void
180 usage (char *cmdname, int help)
181 {
182         char *name = strrchr (cmdname, '/');
183
184         if (name == NULL)
185                 name = cmdname;
186
187         fprintf (help ? stdout : stderr,
188                  "usage: %s -d device -s size -o offset [-i id][-n reps][-l] oid\n",
189                  name);
190 }
191
192 int
193 main (int argc, char **argv)
194 {
195         uint32_t           mypid = getpid ();
196         uint32_t           myhid = gethostid ();
197         uint64_t           oid;
198         uint64_t           base_offset = 0;
199         uint32_t           size = 0;
200         int                set_size = 0;
201         int                device = -1;
202         int                reps = 1;
203         int                locked = 0;
204         char              *end;
205         struct obdio_conn *conn;
206         uint64_t           val;
207         int                v1;
208         int                v2;
209         int                rc;
210         int                c;
211
212         while ((c = getopt (argc, argv, "hi:s:o:d:n:l")) != -1)
213                 switch (c) {
214                 case 'h':
215                         usage (argv[0], 1);
216                         return (0);
217
218                 case 'i':
219                         switch (sscanf (optarg, "%i.%i", &v1, &v2)) {
220                         case 1:
221                                 mypid = v1;
222                                 break;
223                         case 2:
224                                 myhid = v1;
225                                 mypid = v2;
226                                 break;
227                         default:
228                                 fprintf (stderr, "Can't parse id %s\n",
229                                          optarg);
230                                 return (1);
231                         }
232                         break;
233
234                 case 's':
235                         if (parse_kmg (&val, optarg) != 0) {
236                                 fprintf (stderr, "Can't parse size %s\n",
237                                          optarg);
238                                 return (1);
239                         }
240                         size = (uint32_t)val;
241                         set_size++;
242                         break;
243
244                 case 'o':
245                         if (parse_kmg (&val, optarg) != 0) {
246                                 fprintf (stderr, "Can't parse offset %s\n",
247                                          optarg);
248                                 return (1);
249                         }
250                         base_offset = val;
251                         break;
252
253                 case 'd':
254                         device = strtol (optarg, &end, 0);
255                         if (end == optarg || *end != 0 || device < 0) {
256                                 fprintf (stderr, "Can't parse device %s\n",
257                                          optarg);
258                                 return (1);
259                         }
260                         break;
261                 case 'n':
262                         if (parse_kmg (&val, optarg) != 0) {
263                                 fprintf (stderr, "Can't parse reps %s\n",
264                                          optarg);
265                                 return (1);
266                         }
267                         reps = (int)val;
268                         break;
269                 case 'l':
270                         locked = 1;
271                         break;
272                 default:
273                         usage (argv[0], 0);
274                         return (1);
275         }
276
277         if (!set_size ||
278             device < 0 ||
279             optind == argc) {
280                 fprintf (stderr, "No %s specified\n",
281                          !set_size ? "size" :
282                          device < 0 ? "device" : "object id");
283                 return (1);
284         }
285
286         oid = strtoull (argv[optind], &end, 0);
287         if (end == argv[optind] || *end != 0) {
288                 fprintf (stderr, "Can't parse object id %s\n",
289                          argv[optind]);
290                 return (1);
291         }
292
293         conn = obdio_connect (device);
294         if (conn == NULL)
295                 return (1);
296
297         rc = obdio_test_fixed_extent(conn, myhid, mypid, reps, locked,
298                                      oid, base_offset, size);
299
300         obdio_disconnect(conn, 0);
301
302         return (rc == 0 ? 0 : 1);
303 }
304
305