xfs/{111,137}: replace open-coded calls to repair with _scratch_xfs_repair
[xfstests-dev.git] / src / loggen.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2000-2003 Silicon Graphics, Inc.
4  * All Rights Reserved.
5  */
6  
7 /*
8  *
9  * loggen: Generate log entries. Very much incomplete. The empty log
10  *         record is a bit of a misnomer since we need to jump through
11  *         hoops to get a log record that parses ok yet does nothing.
12  *
13  *                                                  - dxm 29/09/00
14  */
15
16 #include <config.h>
17
18 #include <xfs/libxfs.h>
19 #ifdef HAVE_XFS_XFS_LOG_FORMAT_H
20 #include <xfs/xfs_log_format.h>
21 #define XFS_TRANS_MAGIC XFS_TRANS_HEADER_MAGIC
22 #else /* HAVE_XFS_XFS_LOG_FORMAT_H */
23 #include <xfs/xfs_log.h>
24 #include <xfs/xfs_log_priv.h>
25 #endif /* HAVE_XFS_XFS_LOG_FORMAT_H */
26
27 #ifndef ASSIGN_ANY_LSN_DISK
28 #define ASSIGN_ANY_LSN_DISK(lsn,cycle,block)  \
29     { \
30         INT_SET(((uint *)&(lsn))[0], ARCH_CONVERT, (cycle)); \
31         INT_SET(((uint *)&(lsn))[1], ARCH_CONVERT, (block)); \
32     }
33 #endif
34
35 void
36 usage(void)
37 {
38     fprintf(stderr,"Usage: loggen\n"
39                    "           set up parameters before writing record(s):\n"
40                    "               -f f     - set format\n"
41                    "               -u u     - set uuid\n"
42                    "               -c c     - set cycle\n"
43                    "               -b b     - set block\n"
44                    "               -C c     - set tail cycle\n"
45                    "               -B b     - set tail block\n"
46                    "           write log record(s):\n"
47                    "               -z n     - write n zero block(s)     (1BB)\n"
48                    "               -e n     - write n empty record(s)   (2BB)\n"
49                    "               -m n     - write n unmount record(s) (2BB)\n"
50                    "\n"
51                    "            redirect stdout to external log partition, or pipe to\n"
52                    "            dd with appropriate parameters to stuff into internal log.\n"
53     );
54     exit(1);
55 }
56
57 int         bufblocks            = 0;
58 void        *buf                 = NULL;
59 int         param_cycle          = 1;
60 int         param_block          = 0;
61 int         param_tail_cycle     = 1;
62 int         param_tail_block     = 0;
63 int         param_fmt            = XLOG_FMT;
64 uuid_t      param_uuid           = {0};
65
66 void
67 loggen_alloc(int blocks)
68 {
69     if (!(buf=realloc(buf, blocks*BBSIZE))) {
70         fprintf(stderr,"failed to allocate %d block(s)\n", blocks);
71         exit(1);
72     }
73     memset(buf, 0, blocks*BBSIZE);
74     bufblocks=blocks;
75 }
76
77 void
78 loggen_write(void)
79 {         
80     if (!buf) {
81         fprintf(stderr,"no buffer allocated\n");
82         exit(1);
83     }
84
85     if (fwrite(buf, BBSIZE, bufblocks, stdout) != bufblocks) {
86         perror("fwrite");
87         exit(1);
88     }
89
90 }
91
92 void
93 loggen_zero(int count)
94 {
95     if (!count) count=1;
96     
97     fprintf(stderr,"   *** zero block (1BB) x %d\n", count);
98     loggen_alloc(1);
99     while (count--)
100         loggen_write();
101 }      
102       
103 void
104 loggen_unmount(int count)
105 {
106     xlog_rec_header_t       *head;
107     xlog_op_header_t        *op;
108     /* the data section must be 32 bit size aligned */
109     struct {
110         uint16_t magic;
111         uint16_t pad1;
112         uint32_t pad2; /* may as well make it 64 bits */
113     } magic = { XLOG_UNMOUNT_TYPE, 0, 0 };
114     
115     if (!count) count=1;
116     
117     fprintf(stderr,"   *** unmount record (2BB) x %d\n", count);
118     loggen_alloc(2);
119     
120     head = (xlog_rec_header_t *)buf;
121     op   = (xlog_op_header_t  *)(((char*)buf)+BBSIZE);
122
123     /* note that oh_tid actually contains the cycle number
124      * and the tid is stored in h_cycle_data[0] - that's the
125      * way things end up on disk.
126      */
127
128     head->h_magicno = cpu_to_be32(XLOG_HEADER_MAGIC_NUM);
129     head->h_cycle = cpu_to_be32(param_cycle);
130     head->h_version = cpu_to_be32(1);
131     head->h_len = cpu_to_be32(20);
132     head->h_prev_block = cpu_to_be32(-1);
133     head->h_num_logops = cpu_to_be32(1);
134     head->h_cycle_data[0] = cpu_to_be32(0xb0c0d0d0);
135     head->h_fmt = cpu_to_be32(param_fmt);
136
137     head->h_tail_lsn = cpu_to_be64(xlog_assign_lsn(param_tail_cycle,
138                                                         param_tail_block));
139
140     memcpy(head->h_fs_uuid,  param_uuid, sizeof(uuid_t));
141
142     /* now a log unmount op */
143     op->oh_tid = cpu_to_be32(param_cycle);
144     op->oh_len = cpu_to_be32(sizeof(magic));
145     op->oh_clientid = XFS_LOG;
146     op->oh_flags = XLOG_UNMOUNT_TRANS;
147     op->oh_res2 = cpu_to_be16(0);
148
149     /* and the data for this op */
150
151     memcpy(op+1, &magic, sizeof(magic));
152     
153     while (count--) {
154         head->h_lsn = cpu_to_be64(xlog_assign_lsn(param_cycle, param_block++));
155         
156         loggen_write();
157     }
158
159   
160 void
161 loggen_empty(int count)
162 {
163     xlog_rec_header_t       *head;
164     xlog_op_header_t        *op1, *op2, *op3, *op4, *op5;
165     xfs_trans_header_t      *trans;
166     xfs_buf_log_format_t    blfs;
167     xfs_buf_log_format_t    *blf;
168     int                     *data;
169     char                    *p;
170     
171     if (!count) count=1;
172     
173     fprintf(stderr,"   *** empty record (2BB) x %d\n", count);
174     loggen_alloc(2);
175     
176     p=(char*)buf;
177     head  = (xlog_rec_header_t   *)p;         p+=BBSIZE;
178     op1   = (xlog_op_header_t    *)p;         p+=sizeof(xlog_op_header_t);
179     op2   = (xlog_op_header_t    *)p;         p+=sizeof(xlog_op_header_t);
180     trans = (xfs_trans_header_t  *)p;         p+=sizeof(xfs_trans_header_t);
181     op3   = (xlog_op_header_t    *)p;         p+=sizeof(xlog_op_header_t);
182     blf   = (xfs_buf_log_format_t*)p;         p+=sizeof(xfs_buf_log_format_t);
183     op4   = (xlog_op_header_t    *)p;         p+=sizeof(xlog_op_header_t);
184     data  = (int                 *)p;         p+=sizeof(int);
185     op5   = (xlog_op_header_t    *)p;         p+=sizeof(xlog_op_header_t);
186
187     /* note that oh_tid actually contains the cycle number
188      * and the tid is stored in h_cycle_data[0] - that's the
189      * way things end up on disk.
190      */
191
192     head->h_magicno        = cpu_to_be32(XLOG_HEADER_MAGIC_NUM);
193     head->h_cycle          = cpu_to_be32(param_cycle);
194     head->h_version        = cpu_to_be32(1);
195     head->h_len            = cpu_to_be32(5*sizeof(xlog_op_header_t) +
196                                                     sizeof(xfs_trans_header_t)+
197                                                     sizeof(xfs_buf_log_format_t)+
198                                                     sizeof(int));
199     head->h_prev_block     = cpu_to_be32(-1);
200     head->h_num_logops     = cpu_to_be32(5);
201     head->h_cycle_data[0]  = cpu_to_be32(0xb0c0d0d0);
202     head->h_fmt            = cpu_to_be32(param_fmt);
203     
204     head->h_tail_lsn = cpu_to_be64(xlog_assign_lsn(param_tail_cycle,
205                                                         param_tail_block));
206
207     memcpy(head->h_fs_uuid, param_uuid, sizeof(uuid_t));
208
209     /* start */
210     op1->oh_tid            = cpu_to_be32(1);
211     op1->oh_len            = cpu_to_be32(0);
212     op1->oh_clientid       = XFS_TRANSACTION;
213     op1->oh_flags          = XLOG_START_TRANS;
214     op1->oh_res2           = cpu_to_be16(0);
215     /* dummy */
216     op2->oh_tid            = cpu_to_be32(0xb0c0d0d0);
217     op2->oh_len            = cpu_to_be32(sizeof(xfs_trans_header_t));
218     op2->oh_clientid       = XFS_TRANSACTION;
219     op2->oh_flags          = 0;
220     op2->oh_res2           = cpu_to_be16(0);
221     /* dummy transaction - this stuff doesn't get endian converted */
222     trans->th_magic     = XFS_TRANS_MAGIC;
223     trans->th_type      = XFS_TRANS_DUMMY1;
224     trans->th_tid       = 0;
225     trans->th_num_items = 1;
226     /* buffer */
227     op3->oh_tid            = cpu_to_be32(0xb0c0d0d0);
228     op3->oh_len            = cpu_to_be32(sizeof(xfs_buf_log_format_t));
229     op3->oh_clientid       = XFS_TRANSACTION;
230     op3->oh_flags          = 0;
231     op3->oh_res2           = cpu_to_be16(0);
232     /* an empty buffer too */
233     blfs.blf_type       = XFS_LI_BUF;
234     blfs.blf_size       = 2;
235 #ifdef XFS_BLF_CANCEL
236     blfs.blf_flags      = XFS_BLF_CANCEL;
237 #else
238     blfs.blf_flags      = XFS_BLI_CANCEL;
239 #endif
240     blfs.blf_len        = 0;
241     blfs.blf_blkno      = 1;
242     blfs.blf_map_size   = 1;
243     blfs.blf_data_map[0]= 0;
244     memcpy(blf, &blfs, sizeof(blfs));
245     /* commit */
246     op4->oh_tid            = cpu_to_be32(0xb0c0d0d0);
247     op4->oh_len            = cpu_to_be32(sizeof(int));
248     op4->oh_clientid       = XFS_TRANSACTION;
249     op4->oh_flags          = 0;
250     op4->oh_res2           = cpu_to_be16(0);
251     /* and the data */
252     *data=*(int*)(char*)"FISH"; /* this won't get written (I hope) */
253     /* commit */
254     op5->oh_tid            = cpu_to_be32(0xb0c0d0d0);
255     op5->oh_len            = cpu_to_be32(0);
256     op5->oh_clientid       = XFS_TRANSACTION;
257     op5->oh_flags          = XLOG_COMMIT_TRANS;
258     op5->oh_res2           = cpu_to_be16(0);
259
260     while (count--) {
261         head->h_lsn = cpu_to_be64(xlog_assign_lsn(param_cycle, param_block++));
262         
263         loggen_write();
264     }
265 }   
266
267 int
268 main(int argc, char *argv[])
269 {
270     int c;
271     
272     fprintf(stderr,"*** loggen\n");
273     
274     if (argc<2) usage();
275     
276     while ((c = getopt(argc, argv, "f:u:c:b:C:B:z:e:m:")) != -1) {
277         switch (c) {
278             case 'f':
279                 param_fmt=atoi(optarg);
280                 break;
281             case 'u':
282                 memset(param_uuid, atoi(optarg), sizeof(param_uuid));
283                 break;
284             case 'c':
285                 param_cycle=atoi(optarg);
286                 break;
287             case 'b':
288                 param_block=atoi(optarg);
289                 break;
290             case 'C':
291                 param_tail_cycle=atoi(optarg);
292                 break;
293             case 'B':
294                 param_tail_block=atoi(optarg);
295                 break;
296                 
297             case 'z':
298                 loggen_zero(atoi(optarg));
299                 break;
300             case 'e':
301                 loggen_empty(atoi(optarg));
302                 break;
303             case 'm':
304                 loggen_unmount(atoi(optarg));
305                 break;
306                 
307             default:
308                 fprintf(stderr, "unknown option\n");
309                 usage();
310         }
311     }
312     return 0;   
313 }