cmd/xfs/stress/001 1.6 Renamed to cmd/xfstests/001
[xfstests-dev.git] / src / loggen.c
1 /*
2  * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of version 2 of the GNU General Public License as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it would be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11  *
12  * Further, this software is distributed without any warranty that it is
13  * free of the rightful claim of any third person regarding infringement
14  * or the like.  Any license provided herein, whether implied or
15  * otherwise, applies only to this software file.  Patent licenses, if
16  * any, provided herein do not apply to combinations of this program with
17  * other software, or any other product whatsoever.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write the Free Software Foundation, Inc., 59
21  * Temple Place - Suite 330, Boston MA 02111-1307, USA.
22  *
23  * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24  * Mountain View, CA  94043, or:
25  *
26  * http://www.sgi.com
27  *
28  * For further information regarding this notice, see:
29  *
30  * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31  */
32  
33 /*
34  *
35  * loggen: Generate log entries. Very much incomplete. The empty log
36  *         record is a bit of a misnomer since we need to jump through
37  *         hoops to get a log record that parses ok yet does nothing.
38  *
39  *                                                  - dxm 29/09/00
40  */
41
42 #include <libxfs.h>
43 #include <malloc.h>
44 #include <errno.h>
45 #include <fcntl.h>
46
47 #include <xfs_log.h>
48 #include <xfs_log_priv.h>
49
50 void
51 usage()
52 {
53     fprintf(stderr,"Usage: loggen\n"
54                    "           set up parameters before writing record(s):\n"
55                    "               -f f     - set format\n"
56                    "               -u u     - set uuid\n"
57                    "               -c c     - set cycle\n"
58                    "               -b b     - set block\n"
59                    "               -C c     - set tail cycle\n"
60                    "               -B b     - set tail block\n"
61                    "           write log record(s):\n"
62                    "               -z n     - write n zero block(s)     (1BB)\n"
63                    "               -e n     - write n empty record(s)   (2BB)\n"
64                    "               -m n     - write n unmount record(s) (2BB)\n"
65                    "\n"
66                    "            redirect stdout to external log partition, or pipe to\n"
67                    "            dd with appropriate parameters to stuff into internal log.\n"
68     );
69     exit(1);
70 }
71
72 int         bufblocks            = 0;
73 void        *buf                 = NULL;
74 int         param_cycle          = 1;
75 int         param_block          = 0;
76 int         param_tail_cycle     = 1;
77 int         param_tail_block     = 0;
78 int         param_fmt            = XLOG_FMT;
79 uuid_t      param_uuid           = {0};
80
81 void
82 loggen_alloc(int blocks)
83 {
84     if (!(buf=realloc(buf, blocks*BBSIZE))) {
85         fprintf(stderr,"failed to allocate %d block(s)\n", blocks);
86         exit(1);
87     }
88     memset(buf, 0, blocks*BBSIZE);
89     bufblocks=blocks;
90 }
91
92 void
93 loggen_write()
94 {         
95     if (!buf) {
96         fprintf(stderr,"no buffer allocated\n");
97         exit(1);
98     }
99
100     if (fwrite(buf, BBSIZE, bufblocks, stdout) != bufblocks) {
101         perror("fwrite");
102         exit(1);
103     }
104
105 }
106
107 void
108 loggen_zero(int count)
109 {
110     if (!count) count=1;
111     
112     fprintf(stderr,"   *** zero block (1BB) x %d\n", count);
113     loggen_alloc(1);
114     while (count--)
115         loggen_write(count);
116 }      
117       
118 void
119 loggen_unmount(int count)
120 {
121     xlog_rec_header_t       *head;
122     xlog_op_header_t        *op;
123     /* the data section must be 32 bit size aligned */
124     struct {
125         __uint16_t magic;
126         __uint16_t pad1;
127         __uint32_t pad2; /* may as well make it 64 bits */
128     } magic = { XLOG_UNMOUNT_TYPE, 0, 0 };
129     
130     if (!count) count=1;
131     
132     fprintf(stderr,"   *** unmount record (2BB) x %d\n", count);
133     loggen_alloc(2);
134     
135     head = (xlog_rec_header_t *)buf;
136     op   = (xlog_op_header_t  *)(((char*)buf)+BBSIZE);
137
138     /* note that oh_tid actually contains the cycle number
139      * and the tid is stored in h_cycle_data[0] - that's the
140      * way things end up on disk.
141      */
142
143     INT_SET(head->h_magicno,        ARCH_CONVERT, XLOG_HEADER_MAGIC_NUM);
144     INT_SET(head->h_cycle,          ARCH_CONVERT, param_cycle);
145     INT_SET(head->h_version,        ARCH_CONVERT, 1);
146     INT_SET(head->h_len,            ARCH_CONVERT, 20);
147     INT_SET(head->h_chksum,         ARCH_CONVERT, 0);
148     INT_SET(head->h_prev_block,     ARCH_CONVERT, -1);
149     INT_SET(head->h_num_logops,     ARCH_CONVERT, 1);
150     INT_SET(head->h_cycle_data[0],  ARCH_CONVERT, 0xb0c0d0d0);
151     INT_SET(head->h_fmt,            ARCH_CONVERT, param_fmt);
152     
153     ASSIGN_ANY_LSN(head->h_tail_lsn,    
154             param_tail_cycle, param_tail_block, ARCH_CONVERT);
155
156     memcpy(head->h_fs_uuid,  param_uuid, sizeof(uuid_t));
157
158     /* now a log unmount op */
159     INT_SET(op->oh_tid,             ARCH_CONVERT, param_cycle);
160     INT_SET(op->oh_len,             ARCH_CONVERT, sizeof(magic));
161     INT_SET(op->oh_clientid,        ARCH_CONVERT, XFS_LOG);
162     INT_SET(op->oh_flags,           ARCH_CONVERT, XLOG_UNMOUNT_TRANS);
163     INT_SET(op->oh_res2,            ARCH_CONVERT, 0);
164
165     /* and the data for this op */
166
167     memcpy(op+1, &magic, sizeof(magic));
168     
169     while (count--) {
170         ASSIGN_ANY_LSN(head->h_lsn,         
171                 param_cycle, param_block++, ARCH_CONVERT);
172         
173         loggen_write(count);
174     }
175
176   
177 void
178 loggen_empty(int count)
179 {
180     xlog_rec_header_t       *head;
181     xlog_op_header_t        *op1, *op2, *op3, *op4, *op5;
182     xfs_trans_header_t      *trans;
183     xfs_buf_log_format_t    *blf;
184     int                     *data;
185     char                    *p;
186     
187     if (!count) count=1;
188     
189     fprintf(stderr,"   *** empty record (2BB) x %d\n", count);
190     loggen_alloc(2);
191     
192     p=(char*)buf;
193     head  = (xlog_rec_header_t   *)p;         p+=BBSIZE;
194     op1   = (xlog_op_header_t    *)p;         p+=sizeof(xlog_op_header_t);
195     op2   = (xlog_op_header_t    *)p;         p+=sizeof(xlog_op_header_t);
196     trans = (xfs_trans_header_t  *)p;         p+=sizeof(xfs_trans_header_t);
197     op3   = (xlog_op_header_t    *)p;         p+=sizeof(xlog_op_header_t);
198     blf   = (xfs_buf_log_format_t*)p;         p+=sizeof(xfs_buf_log_format_t);
199     op4   = (xlog_op_header_t    *)p;         p+=sizeof(xlog_op_header_t);
200     data  = (int                 *)p;         p+=sizeof(int);
201     op5   = (xlog_op_header_t    *)p;         p+=sizeof(xlog_op_header_t);
202
203     /* note that oh_tid actually contains the cycle number
204      * and the tid is stored in h_cycle_data[0] - that's the
205      * way things end up on disk.
206      */
207
208     INT_SET(head->h_magicno,        ARCH_CONVERT, XLOG_HEADER_MAGIC_NUM);
209     INT_SET(head->h_cycle,          ARCH_CONVERT, param_cycle);
210     INT_SET(head->h_version,        ARCH_CONVERT, 1);
211     INT_SET(head->h_len,            ARCH_CONVERT, 5*sizeof(xlog_op_header_t) +
212                                                     sizeof(xfs_trans_header_t)+
213                                                     sizeof(xfs_buf_log_format_t)+
214                                                     sizeof(int));
215     INT_SET(head->h_chksum,         ARCH_CONVERT, 0);
216     INT_SET(head->h_prev_block,     ARCH_CONVERT, -1);
217     INT_SET(head->h_num_logops,     ARCH_CONVERT, 5);
218     INT_SET(head->h_cycle_data[0],  ARCH_CONVERT, 0xb0c0d0d0);
219     INT_SET(head->h_fmt,            ARCH_CONVERT, param_fmt);
220     
221     ASSIGN_ANY_LSN(head->h_tail_lsn,    
222             param_tail_cycle, param_tail_block, ARCH_CONVERT);
223
224     memcpy(head->h_fs_uuid,  param_uuid, sizeof(uuid_t));
225
226     /* start */
227     INT_SET(op1->oh_tid,            ARCH_CONVERT, 1);
228     INT_SET(op1->oh_len,            ARCH_CONVERT, 0);
229     INT_SET(op1->oh_clientid,       ARCH_CONVERT, XFS_TRANSACTION);
230     INT_SET(op1->oh_flags,          ARCH_CONVERT, XLOG_START_TRANS);
231     INT_SET(op1->oh_res2,           ARCH_CONVERT, 0);
232     /* dummy */
233     INT_SET(op2->oh_tid,            ARCH_CONVERT, 0xb0c0d0d0);
234     INT_SET(op2->oh_len,            ARCH_CONVERT, sizeof(xfs_trans_header_t));
235     INT_SET(op2->oh_clientid,       ARCH_CONVERT, XFS_TRANSACTION);
236     INT_SET(op2->oh_flags,          ARCH_CONVERT, 0);
237     INT_SET(op2->oh_res2,           ARCH_CONVERT, 0);
238     /* dummy transaction - this stuff doesn't get endian converted */
239     trans->th_magic     = XFS_TRANS_MAGIC;
240     trans->th_type      = XFS_TRANS_DUMMY1;
241     trans->th_tid       = 0;
242     trans->th_num_items = 1;
243     /* buffer */
244     INT_SET(op3->oh_tid,            ARCH_CONVERT, 0xb0c0d0d0);
245     INT_SET(op3->oh_len,            ARCH_CONVERT, sizeof(xfs_buf_log_format_t));
246     INT_SET(op3->oh_clientid,       ARCH_CONVERT, XFS_TRANSACTION);
247     INT_SET(op3->oh_flags,          ARCH_CONVERT, 0);
248     INT_SET(op3->oh_res2,           ARCH_CONVERT, 0);
249     /* an empty buffer too */
250     blf->blf_type       = XFS_LI_BUF;
251     blf->blf_size       = 2;
252     blf->blf_flags      = XFS_BLI_CANCEL;
253     blf->blf_blkno      = 1;
254     blf->blf_map_size   = 1;
255     blf->blf_data_map[0]= 0;
256     /* commit */
257     INT_SET(op4->oh_tid,            ARCH_CONVERT, 0xb0c0d0d0);
258     INT_SET(op4->oh_len,            ARCH_CONVERT, sizeof(int));
259     INT_SET(op4->oh_clientid,       ARCH_CONVERT, XFS_TRANSACTION);
260     INT_SET(op4->oh_flags,          ARCH_CONVERT, 0);
261     INT_SET(op4->oh_res2,           ARCH_CONVERT, 0);
262     /* and the data */
263     *data=*(int*)(char*)"FISH"; /* this won't get written (I hope) */
264     /* commit */
265     INT_SET(op5->oh_tid,            ARCH_CONVERT, 0xb0c0d0d0);
266     INT_SET(op5->oh_len,            ARCH_CONVERT, 0);
267     INT_SET(op5->oh_clientid,       ARCH_CONVERT, XFS_TRANSACTION);
268     INT_SET(op5->oh_flags,          ARCH_CONVERT, XLOG_COMMIT_TRANS);
269     INT_SET(op5->oh_res2,           ARCH_CONVERT, 0);
270
271     while (count--) {
272         ASSIGN_ANY_LSN(head->h_lsn,         
273                 param_cycle, param_block++, ARCH_CONVERT);
274         
275         loggen_write(count);
276     }
277 }   
278
279 int
280 main(int argc, char *argv[])
281 {
282     int c;
283     
284     fprintf(stderr,"*** loggen\n");
285     
286     if (argc<2) usage();
287     
288     while ((c = getopt(argc, argv, "f:u:c:b:C:B:z:e:m:")) != -1) {
289         switch (c) {
290             case 'f':
291                 param_fmt=atoi(optarg);
292                 break;
293             case 'u':
294                 memset(param_uuid, atoi(optarg), sizeof(param_uuid));
295                 break;
296             case 'c':
297                 param_cycle=atoi(optarg);
298                 break;
299             case 'b':
300                 param_block=atoi(optarg);
301                 break;
302             case 'C':
303                 param_tail_cycle=atoi(optarg);
304                 break;
305             case 'B':
306                 param_tail_block=atoi(optarg);
307                 break;
308                 
309             case 'z':
310                 loggen_zero(atoi(optarg));
311                 break;
312             case 'e':
313                 loggen_empty(atoi(optarg));
314                 break;
315             case 'm':
316                 loggen_unmount(atoi(optarg));
317                 break;
318                 
319             default:
320                 fprintf(stderr, "unknown option\n");
321                 usage();
322         }
323     }
324     return 0;   
325 }
326
327