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