converted all backends to new common format
[tridge/dbench.git] / nfsio.c
1 /* 
2    Copyright (C) by Ronnie Sahlberg <sahlberg@samba.org> 2008
3    
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 3 of the License, or
7    (at your option) any later version.
8    
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13    
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #define _GNU_SOURCE
19 #include <stdio.h>
20 #undef _GNU_SOURCE
21
22 #include "mount.h"
23 #include "nfs.h"
24 #include "libnfs.h"
25 #include "dbench.h"
26
27 #define discard_const(ptr) ((void *)((intptr_t)(ptr)))
28
29 #define MAX_FILES 200
30
31 static char rw_buf[65536];
32
33
34 struct cb_data {
35         struct nfsio *nfsio;
36         char *dirname;
37 };
38
39 static void nfs3_deltree(struct dbench_op *op);
40
41 static void nfs3_cleanup(struct child_struct *child)
42 {
43         char *dname;
44         struct dbench_op op;
45         ZERO_STRUCT(op);
46
47         asprintf(&dname, "/clients/client%d", child->id);
48         op.fname = dname;
49         op.child = child;
50         nfs3_deltree(&op);
51         free(dname);
52 }
53
54 static void nfs3_setup(struct child_struct *child)
55 {
56         const char *status = "0x00000000";
57
58         child->rate.last_time = timeval_current();
59         child->rate.last_bytes = 0;
60
61
62         srandom(getpid() ^ time(NULL));
63         child->private = nfsio_connect(options.server, options.export, options.protocol);
64
65         if (child->private == NULL) {
66                 child->failed = 1;
67                 printf("nfsio_connect() failed\n");
68                 exit(10);
69         }
70 }
71
72
73 static void dirent_cb(struct entryplus3 *e, void *private_data)
74 {
75         struct cb_data *cbd = private_data;
76         nfsstat3 res;
77         char *objname;
78
79         if (!strcmp(cbd->dirname,".")) {
80                 return;
81         }
82         if (!strcmp(cbd->dirname,"..")) {
83                 return;
84         }
85
86         asprintf(&objname, "%s/%s", cbd->dirname, e->name);
87         if (objname == NULL) {
88                 printf("Failed to talloc ne object name in dirent_cb\n");
89                 exit(10);
90         }
91
92         if (e->name_attributes.post_op_attr_u.attributes.type == NF3DIR) {
93                 struct cb_data *new_cbd = malloc(sizeof(struct cb_data));
94
95                 new_cbd->nfsio = cbd->nfsio;
96                 new_cbd->dirname = strdup(objname);
97
98                 nfsio_readdirplus(cbd->nfsio, objname, dirent_cb, new_cbd);
99                 
100                 res = nfsio_rmdir(cbd->nfsio, objname);
101                 if (res != NFS3_OK) {
102                         printf("Failed to remove object : \"%s\"  %s (%d)\n", objname, nfs_error(res), res);
103                         free(objname);
104                         free(new_cbd->dirname);
105                         free(new_cbd);
106                         exit(10);
107                 }
108
109
110                 free(objname);
111                 free(new_cbd->dirname);
112                 free(new_cbd);
113                 return;
114         }
115
116         res = nfsio_remove(cbd->nfsio, objname);
117         if (res != NFS3_OK) {
118                 printf("Failed to remove object : \"%s\" %s %d\n", objname, nfs_error(res), res);
119                 free(objname);
120                 exit(10);
121         }
122
123         free(objname);
124 }
125
126 static void nfs3_deltree(struct dbench_op *op)
127 {
128         struct cb_data *cbd;
129         nfsstat3 res;
130         
131         cbd = malloc(sizeof(struct cb_data));
132
133         cbd->nfsio = op->child->private;
134         cbd->dirname = discard_const(op->fname);
135
136         res = nfsio_lookup(cbd->nfsio, cbd->dirname, NULL);
137         if (res != NFS3ERR_NOENT) {
138                 nfsio_readdirplus(cbd->nfsio, cbd->dirname, dirent_cb, cbd);
139                 nfsio_rmdir(cbd->nfsio, cbd->dirname);
140         }
141
142         res = nfsio_lookup(cbd->nfsio, cbd->dirname, NULL);
143         if (res != NFS3ERR_NOENT) {
144                 printf("Directory \"%s\" not empty. Aborting\n");
145                 free(cbd);
146                 exit(10);
147         }
148         free(cbd);
149 }
150
151 static int expected_status(const char *status)
152 {
153         if (strncmp(status, "0x", 2) == 0) {
154                 return strtol(status, NULL, 16);
155         }
156 }
157
158 static void failed(struct child_struct *child)
159 {
160         child->failed = 1;
161         printf("ERROR: child %d failed at line %d\n", child->id, child->line);
162         exit(1);
163 }
164
165 static void nfs3_getattr(struct dbench_op *op)
166 {
167         nfsstat3 res;
168
169         res = nfsio_getattr(op->child->private, op->fname, NULL);
170         if (res != expected_status(op->status)) {
171                 printf("[%d] GETATTR \"%s\" failed (%x) - expected %x\n", 
172                        op->child->line, op->fname, res, expected_status(op->status));
173                 failed(op->child);
174         }
175 }
176
177
178 static void nfs3_lookup(struct dbench_op *op)
179 {
180         nfsstat3 res;
181
182         res = nfsio_lookup(op->child->private, op->fname, NULL);
183         if (res != expected_status(op->status)) {
184                 printf("[%d] LOOKUP \"%s\" failed (%x) - expected %x\n", 
185                        op->child->line, op->fname, res, expected_status(op->status));
186                 failed(op->child);
187         }
188 }
189
190 static void nfs3_create(struct dbench_op *op)
191 {
192         nfsstat3 res;
193
194         res = nfsio_create(op->child->private, op->fname);
195         if (res != expected_status(op->status)) {
196                 printf("[%d] CREATE \"%s\" failed (%x) - expected %x\n", 
197                        op->child->line, op->fname, res, expected_status(op->status));
198                 failed(op->child);
199         }
200 }
201
202 static void nfs3_write(struct dbench_op *op)
203 {
204         int offset = op->params[0];
205         int len = op->params[1];
206         int stable = op->params[2];
207         nfsstat3 res;
208
209         res = nfsio_write(op->child->private, op->fname, rw_buf, offset, len, stable);
210         if (res != expected_status(op->status)) {
211                 printf("[%d] WRITE \"%s\" failed (%x) - expected %x\n", 
212                        op->child->line, op->fname,
213                        res, expected_status(op->status));
214                 failed(op->child);
215         }
216         op->child->bytes += len;
217 }
218
219 static void nfs3_commit(struct dbench_op *op)
220 {
221         nfsstat3 res;
222
223         res = nfsio_commit(op->child->private, op->fname);
224         if (res != expected_status(op->status)) {
225                 printf("[%d] COMMIT \"%s\" failed (%x) - expected %x\n", 
226                        op->child->line, op->fname, res, expected_status(op->status));
227                 failed(op->child);
228         }
229 }
230
231
232 static void nfs3_read(struct dbench_op *op)
233 {
234         int offset = op->params[0];
235         int len = op->params[1];
236         nfsstat3 res = 0;
237
238         res = nfsio_read(op->child->private, op->fname, rw_buf, offset, len, NULL, NULL);
239         if (res != expected_status(op->status)) {
240                 printf("[%d] READ \"%s\" failed (%x) - expected %x\n", 
241                        op->child->line, op->fname,
242                        res, expected_status(op->status));
243                 failed(op->child);
244         }
245         op->child->bytes += len;
246 }
247
248 static void nfs3_access(struct dbench_op *op)
249 {
250         nfsstat3 res;
251
252         res = nfsio_access(op->child->private, op->fname, 0, NULL);
253         if (res != expected_status(op->status)) {
254                 printf("[%d] ACCESS \"%s\" failed (%x) - expected %x\n", 
255                        op->child->line, op->fname, res, expected_status(op->status));
256                 failed(op->child);
257         }
258 }
259
260 static void nfs3_mkdir(struct dbench_op *op)
261 {
262         nfsstat3 res;
263
264         res = nfsio_mkdir(op->child->private, op->fname);
265         if (res != expected_status(op->status)) {
266                 printf("[%d] MKDIR \"%s\" failed (%x) - expected %x\n", 
267                        op->child->line, op->fname, res, expected_status(op->status));
268                 failed(op->child);
269         }
270 }
271
272 static void nfs3_rmdir(struct dbench_op *op)
273 {
274         nfsstat3 res;
275
276         res = nfsio_rmdir(op->child->private, op->fname);
277         if (res != expected_status(op->status)) {
278                 printf("[%d] RMDIR \"%s\" failed (%x) - expected %x\n", 
279                        op->child->line, op->fname, res, expected_status(op->status));
280                 failed(op->child);
281         }
282 }
283
284 static void nfs3_fsstat(struct dbench_op *op)
285 {
286         nfsstat3 res;
287
288         res = nfsio_fsstat(op->child->private);
289         if (res != expected_status(op->status)) {
290                 printf("[%d] FSSTAT failed (%x) - expected %x\n", 
291                        op->child->line, res, expected_status(op->status));
292                 failed(op->child);
293         }
294 }
295
296 static void nfs3_fsinfo(struct dbench_op *op)
297 {
298         nfsstat3 res;
299
300         res = nfsio_fsinfo(op->child->private);
301         if (res != expected_status(op->status)) {
302                 printf("[%d] FSINFO failed (%x) - expected %x\n", 
303                        op->child->line, res, expected_status(op->status));
304                 failed(op->child);
305         }
306 }
307
308 static void nfs3_symlink(struct dbench_op *op)
309 {
310         nfsstat3 res;
311
312         res = nfsio_symlink(op->child->private, op->fname, op->fname2);
313         if (res != expected_status(op->status)) {
314                 printf("[%d] SYMLINK \"%s\"->\"%s\" failed (%x) - expected %x\n", 
315                        op->child->line, op->fname, op->fname2,
316                        res, expected_status(op->status));
317                 failed(op->child);
318         }
319 }
320
321 static void nfs3_remove(struct dbench_op *op)
322 {
323         nfsstat3 res;
324
325         res = nfsio_remove(op->child->private, op->fname);
326         if (res != expected_status(op->status)) {
327                 printf("[%d] REMOVE \"%s\" failed (%x) - expected %x\n", 
328                        op->child->line, op->fname, res, expected_status(op->status));
329                 failed(op->child);
330         }
331 }
332
333 static void nfs3_readdirplus(struct dbench_op *op)
334 {
335         nfsstat3 res;
336
337         res = nfsio_readdirplus(op->child->private, op->fname, NULL, NULL);
338         if (res != expected_status(op->status)) {
339                 printf("[%d] READDIRPLUS \"%s\" failed (%x) - expected %x\n", 
340                        op->child->line, op->fname, res, expected_status(op->status));
341                 failed(op->child);
342         }
343 }
344
345 static void nfs3_link(struct dbench_op *op)
346 {
347         nfsstat3 res;
348
349         res = nfsio_link(op->child->private, op->fname, op->fname2);
350         if (res != expected_status(op->status)) {
351                 printf("[%d] LINK \"%s\"->\"%s\" failed (%x) - expected %x\n", 
352                        op->child->line, op->fname, op->fname2,
353                        res, expected_status(op->status));
354                 failed(op->child);
355         }
356 }
357
358 static void nfs3_rename(struct dbench_op *op)
359 {
360         nfsstat3 res;
361
362         res = nfsio_rename(op->child->private, op->fname, op->fname2);
363         if (res != expected_status(op->status)) {
364                 printf("[%d] RENAME \"%s\"->\"%s\" failed (%x) - expected %x\n", 
365                        op->child->line, op->fname, op->fname2,
366                        res, expected_status(op->status));
367                 failed(op->child);
368         }
369 }
370
371 static struct backend_op ops[] = {
372         { "Deltree",  nfs3_deltree },
373         { "GETATTR3", nfs3_getattr },
374         { "LOOKUP3",  nfs3_lookup },
375         { "CREATE3",  nfs3_create },
376         { "WRITE3",   nfs3_write },
377         { "COMMIT3",  nfs3_commit },
378         { "READ3",    nfs3_read },
379         { "ACCESS3",  nfs3_access },
380         { "MKDIR3",   nfs3_mkdir },
381         { "RMDIR3",   nfs3_rmdir },
382         { "FSSTAT3",  nfs3_fsstat },
383         { "FSINFO3",  nfs3_fsinfo },
384         { "SYMLINK3", nfs3_symlink },
385         { "REMOVE3",  nfs3_remove },
386         { "READDIRPLUS3", nfs3_readdirplus },
387         { "RENAME3",  nfs3_rename },
388         { "LINK3",    nfs3_link },
389         { NULL, NULL}
390 };
391
392 struct nb_operations nb_ops = {
393         .backend_name = "nfsbench",
394         .setup        = nfs3_setup,
395         .cleanup      = nfs3_cleanup,
396         .ops          = ops
397 };