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