2 * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
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.
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.
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.
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.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
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.
42 #include <xfs/libxfs.h>
43 #include <xfs/xfs_log.h>
44 #include <xfs/xfs_log_priv.h>
49 fprintf(stderr,"Usage: loggen\n"
50 " set up parameters before writing record(s):\n"
51 " -f f - set format\n"
55 " -C c - set tail cycle\n"
56 " -B b - set tail block\n"
57 " write log record(s):\n"
58 " -z n - write n zero block(s) (1BB)\n"
59 " -e n - write n empty record(s) (2BB)\n"
60 " -m n - write n unmount record(s) (2BB)\n"
62 " redirect stdout to external log partition, or pipe to\n"
63 " dd with appropriate parameters to stuff into internal log.\n"
72 int param_tail_cycle = 1;
73 int param_tail_block = 0;
74 int param_fmt = XLOG_FMT;
75 uuid_t param_uuid = {0};
78 loggen_alloc(int blocks)
80 if (!(buf=realloc(buf, blocks*BBSIZE))) {
81 fprintf(stderr,"failed to allocate %d block(s)\n", blocks);
84 memset(buf, 0, blocks*BBSIZE);
92 fprintf(stderr,"no buffer allocated\n");
96 if (fwrite(buf, BBSIZE, bufblocks, stdout) != bufblocks) {
104 loggen_zero(int count)
108 fprintf(stderr," *** zero block (1BB) x %d\n", count);
115 loggen_unmount(int count)
117 xlog_rec_header_t *head;
118 xlog_op_header_t *op;
119 /* the data section must be 32 bit size aligned */
123 __uint32_t pad2; /* may as well make it 64 bits */
124 } magic = { XLOG_UNMOUNT_TYPE, 0, 0 };
128 fprintf(stderr," *** unmount record (2BB) x %d\n", count);
131 head = (xlog_rec_header_t *)buf;
132 op = (xlog_op_header_t *)(((char*)buf)+BBSIZE);
134 /* note that oh_tid actually contains the cycle number
135 * and the tid is stored in h_cycle_data[0] - that's the
136 * way things end up on disk.
139 INT_SET(head->h_magicno, ARCH_CONVERT, XLOG_HEADER_MAGIC_NUM);
140 INT_SET(head->h_cycle, ARCH_CONVERT, param_cycle);
141 INT_SET(head->h_version, ARCH_CONVERT, 1);
142 INT_SET(head->h_len, ARCH_CONVERT, 20);
143 INT_SET(head->h_chksum, ARCH_CONVERT, 0);
144 INT_SET(head->h_prev_block, ARCH_CONVERT, -1);
145 INT_SET(head->h_num_logops, ARCH_CONVERT, 1);
146 INT_SET(head->h_cycle_data[0], ARCH_CONVERT, 0xb0c0d0d0);
147 INT_SET(head->h_fmt, ARCH_CONVERT, param_fmt);
149 ASSIGN_ANY_LSN(head->h_tail_lsn,
150 param_tail_cycle, param_tail_block, ARCH_CONVERT);
152 memcpy(head->h_fs_uuid, param_uuid, sizeof(uuid_t));
154 /* now a log unmount op */
155 INT_SET(op->oh_tid, ARCH_CONVERT, param_cycle);
156 INT_SET(op->oh_len, ARCH_CONVERT, sizeof(magic));
157 INT_SET(op->oh_clientid, ARCH_CONVERT, XFS_LOG);
158 INT_SET(op->oh_flags, ARCH_CONVERT, XLOG_UNMOUNT_TRANS);
159 INT_SET(op->oh_res2, ARCH_CONVERT, 0);
161 /* and the data for this op */
163 memcpy(op+1, &magic, sizeof(magic));
166 ASSIGN_ANY_LSN(head->h_lsn,
167 param_cycle, param_block++, ARCH_CONVERT);
174 loggen_empty(int count)
176 xlog_rec_header_t *head;
177 xlog_op_header_t *op1, *op2, *op3, *op4, *op5;
178 xfs_trans_header_t *trans;
179 xfs_buf_log_format_t *blf;
185 fprintf(stderr," *** empty record (2BB) x %d\n", count);
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);
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.
204 INT_SET(head->h_magicno, ARCH_CONVERT, XLOG_HEADER_MAGIC_NUM);
205 INT_SET(head->h_cycle, ARCH_CONVERT, param_cycle);
206 INT_SET(head->h_version, ARCH_CONVERT, 1);
207 INT_SET(head->h_len, ARCH_CONVERT, 5*sizeof(xlog_op_header_t) +
208 sizeof(xfs_trans_header_t)+
209 sizeof(xfs_buf_log_format_t)+
211 INT_SET(head->h_chksum, ARCH_CONVERT, 0);
212 INT_SET(head->h_prev_block, ARCH_CONVERT, -1);
213 INT_SET(head->h_num_logops, ARCH_CONVERT, 5);
214 INT_SET(head->h_cycle_data[0], ARCH_CONVERT, 0xb0c0d0d0);
215 INT_SET(head->h_fmt, ARCH_CONVERT, param_fmt);
217 ASSIGN_ANY_LSN(head->h_tail_lsn,
218 param_tail_cycle, param_tail_block, ARCH_CONVERT);
220 memcpy(head->h_fs_uuid, param_uuid, sizeof(uuid_t));
223 INT_SET(op1->oh_tid, ARCH_CONVERT, 1);
224 INT_SET(op1->oh_len, ARCH_CONVERT, 0);
225 INT_SET(op1->oh_clientid, ARCH_CONVERT, XFS_TRANSACTION);
226 INT_SET(op1->oh_flags, ARCH_CONVERT, XLOG_START_TRANS);
227 INT_SET(op1->oh_res2, ARCH_CONVERT, 0);
229 INT_SET(op2->oh_tid, ARCH_CONVERT, 0xb0c0d0d0);
230 INT_SET(op2->oh_len, ARCH_CONVERT, sizeof(xfs_trans_header_t));
231 INT_SET(op2->oh_clientid, ARCH_CONVERT, XFS_TRANSACTION);
232 INT_SET(op2->oh_flags, ARCH_CONVERT, 0);
233 INT_SET(op2->oh_res2, ARCH_CONVERT, 0);
234 /* dummy transaction - this stuff doesn't get endian converted */
235 trans->th_magic = XFS_TRANS_MAGIC;
236 trans->th_type = XFS_TRANS_DUMMY1;
238 trans->th_num_items = 1;
240 INT_SET(op3->oh_tid, ARCH_CONVERT, 0xb0c0d0d0);
241 INT_SET(op3->oh_len, ARCH_CONVERT, sizeof(xfs_buf_log_format_t));
242 INT_SET(op3->oh_clientid, ARCH_CONVERT, XFS_TRANSACTION);
243 INT_SET(op3->oh_flags, ARCH_CONVERT, 0);
244 INT_SET(op3->oh_res2, ARCH_CONVERT, 0);
245 /* an empty buffer too */
246 blf->blf_type = XFS_LI_BUF;
248 blf->blf_flags = XFS_BLI_CANCEL;
250 blf->blf_map_size = 1;
251 blf->blf_data_map[0]= 0;
253 INT_SET(op4->oh_tid, ARCH_CONVERT, 0xb0c0d0d0);
254 INT_SET(op4->oh_len, ARCH_CONVERT, sizeof(int));
255 INT_SET(op4->oh_clientid, ARCH_CONVERT, XFS_TRANSACTION);
256 INT_SET(op4->oh_flags, ARCH_CONVERT, 0);
257 INT_SET(op4->oh_res2, ARCH_CONVERT, 0);
259 *data=*(int*)(char*)"FISH"; /* this won't get written (I hope) */
261 INT_SET(op5->oh_tid, ARCH_CONVERT, 0xb0c0d0d0);
262 INT_SET(op5->oh_len, ARCH_CONVERT, 0);
263 INT_SET(op5->oh_clientid, ARCH_CONVERT, XFS_TRANSACTION);
264 INT_SET(op5->oh_flags, ARCH_CONVERT, XLOG_COMMIT_TRANS);
265 INT_SET(op5->oh_res2, ARCH_CONVERT, 0);
268 ASSIGN_ANY_LSN(head->h_lsn,
269 param_cycle, param_block++, ARCH_CONVERT);
276 main(int argc, char *argv[])
280 fprintf(stderr,"*** loggen\n");
284 while ((c = getopt(argc, argv, "f:u:c:b:C:B:z:e:m:")) != -1) {
287 param_fmt=atoi(optarg);
290 memset(param_uuid, atoi(optarg), sizeof(param_uuid));
293 param_cycle=atoi(optarg);
296 param_block=atoi(optarg);
299 param_tail_cycle=atoi(optarg);
302 param_tail_block=atoi(optarg);
306 loggen_zero(atoi(optarg));
309 loggen_empty(atoi(optarg));
312 loggen_unmount(atoi(optarg));
316 fprintf(stderr, "unknown option\n");