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