2 * Copyright (c) 2000-2003 Silicon Graphics, Inc.
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.
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.
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
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.
28 #include <xfs/libxfs.h>
29 #include <xfs/xfs_log.h>
30 #include <xfs/xfs_log_priv.h>
35 fprintf(stderr,"Usage: loggen\n"
36 " set up parameters before writing record(s):\n"
37 " -f f - set format\n"
41 " -C c - set tail cycle\n"
42 " -B b - set tail block\n"
43 " write log record(s):\n"
44 " -z n - write n zero block(s) (1BB)\n"
45 " -e n - write n empty record(s) (2BB)\n"
46 " -m n - write n unmount record(s) (2BB)\n"
48 " redirect stdout to external log partition, or pipe to\n"
49 " dd with appropriate parameters to stuff into internal log.\n"
58 int param_tail_cycle = 1;
59 int param_tail_block = 0;
60 int param_fmt = XLOG_FMT;
61 uuid_t param_uuid = {0};
64 loggen_alloc(int blocks)
66 if (!(buf=realloc(buf, blocks*BBSIZE))) {
67 fprintf(stderr,"failed to allocate %d block(s)\n", blocks);
70 memset(buf, 0, blocks*BBSIZE);
78 fprintf(stderr,"no buffer allocated\n");
82 if (fwrite(buf, BBSIZE, bufblocks, stdout) != bufblocks) {
90 loggen_zero(int count)
94 fprintf(stderr," *** zero block (1BB) x %d\n", count);
101 loggen_unmount(int count)
103 xlog_rec_header_t *head;
104 xlog_op_header_t *op;
105 /* the data section must be 32 bit size aligned */
109 __uint32_t pad2; /* may as well make it 64 bits */
110 } magic = { XLOG_UNMOUNT_TYPE, 0, 0 };
114 fprintf(stderr," *** unmount record (2BB) x %d\n", count);
117 head = (xlog_rec_header_t *)buf;
118 op = (xlog_op_header_t *)(((char*)buf)+BBSIZE);
120 /* note that oh_tid actually contains the cycle number
121 * and the tid is stored in h_cycle_data[0] - that's the
122 * way things end up on disk.
125 INT_SET(head->h_magicno, ARCH_CONVERT, XLOG_HEADER_MAGIC_NUM);
126 INT_SET(head->h_cycle, ARCH_CONVERT, param_cycle);
127 INT_SET(head->h_version, ARCH_CONVERT, 1);
128 INT_SET(head->h_len, ARCH_CONVERT, 20);
129 INT_SET(head->h_chksum, ARCH_CONVERT, 0);
130 INT_SET(head->h_prev_block, ARCH_CONVERT, -1);
131 INT_SET(head->h_num_logops, ARCH_CONVERT, 1);
132 INT_SET(head->h_cycle_data[0], ARCH_CONVERT, 0xb0c0d0d0);
133 INT_SET(head->h_fmt, ARCH_CONVERT, param_fmt);
135 ASSIGN_ANY_LSN_DISK(head->h_tail_lsn, param_tail_cycle, param_tail_block);
137 memcpy(head->h_fs_uuid, param_uuid, sizeof(uuid_t));
139 /* now a log unmount op */
140 INT_SET(op->oh_tid, ARCH_CONVERT, param_cycle);
141 INT_SET(op->oh_len, ARCH_CONVERT, sizeof(magic));
142 INT_SET(op->oh_clientid, ARCH_CONVERT, XFS_LOG);
143 INT_SET(op->oh_flags, ARCH_CONVERT, XLOG_UNMOUNT_TRANS);
144 INT_SET(op->oh_res2, ARCH_CONVERT, 0);
146 /* and the data for this op */
148 memcpy(op+1, &magic, sizeof(magic));
151 ASSIGN_ANY_LSN_DISK(head->h_lsn,
152 param_cycle, param_block++);
159 loggen_empty(int count)
161 xlog_rec_header_t *head;
162 xlog_op_header_t *op1, *op2, *op3, *op4, *op5;
163 xfs_trans_header_t *trans;
164 xfs_buf_log_format_t *blf;
170 fprintf(stderr," *** empty record (2BB) x %d\n", count);
174 head = (xlog_rec_header_t *)p; p+=BBSIZE;
175 op1 = (xlog_op_header_t *)p; p+=sizeof(xlog_op_header_t);
176 op2 = (xlog_op_header_t *)p; p+=sizeof(xlog_op_header_t);
177 trans = (xfs_trans_header_t *)p; p+=sizeof(xfs_trans_header_t);
178 op3 = (xlog_op_header_t *)p; p+=sizeof(xlog_op_header_t);
179 blf = (xfs_buf_log_format_t*)p; p+=sizeof(xfs_buf_log_format_t);
180 op4 = (xlog_op_header_t *)p; p+=sizeof(xlog_op_header_t);
181 data = (int *)p; p+=sizeof(int);
182 op5 = (xlog_op_header_t *)p; p+=sizeof(xlog_op_header_t);
184 /* note that oh_tid actually contains the cycle number
185 * and the tid is stored in h_cycle_data[0] - that's the
186 * way things end up on disk.
189 INT_SET(head->h_magicno, ARCH_CONVERT, XLOG_HEADER_MAGIC_NUM);
190 INT_SET(head->h_cycle, ARCH_CONVERT, param_cycle);
191 INT_SET(head->h_version, ARCH_CONVERT, 1);
192 INT_SET(head->h_len, ARCH_CONVERT, 5*sizeof(xlog_op_header_t) +
193 sizeof(xfs_trans_header_t)+
194 sizeof(xfs_buf_log_format_t)+
196 INT_SET(head->h_chksum, ARCH_CONVERT, 0);
197 INT_SET(head->h_prev_block, ARCH_CONVERT, -1);
198 INT_SET(head->h_num_logops, ARCH_CONVERT, 5);
199 INT_SET(head->h_cycle_data[0], ARCH_CONVERT, 0xb0c0d0d0);
200 INT_SET(head->h_fmt, ARCH_CONVERT, param_fmt);
202 ASSIGN_ANY_LSN_DISK(head->h_tail_lsn,
203 param_tail_cycle, param_tail_block);
205 memcpy(head->h_fs_uuid, param_uuid, sizeof(uuid_t));
208 INT_SET(op1->oh_tid, ARCH_CONVERT, 1);
209 INT_SET(op1->oh_len, ARCH_CONVERT, 0);
210 INT_SET(op1->oh_clientid, ARCH_CONVERT, XFS_TRANSACTION);
211 INT_SET(op1->oh_flags, ARCH_CONVERT, XLOG_START_TRANS);
212 INT_SET(op1->oh_res2, ARCH_CONVERT, 0);
214 INT_SET(op2->oh_tid, ARCH_CONVERT, 0xb0c0d0d0);
215 INT_SET(op2->oh_len, ARCH_CONVERT, sizeof(xfs_trans_header_t));
216 INT_SET(op2->oh_clientid, ARCH_CONVERT, XFS_TRANSACTION);
217 INT_SET(op2->oh_flags, ARCH_CONVERT, 0);
218 INT_SET(op2->oh_res2, ARCH_CONVERT, 0);
219 /* dummy transaction - this stuff doesn't get endian converted */
220 trans->th_magic = XFS_TRANS_MAGIC;
221 trans->th_type = XFS_TRANS_DUMMY1;
223 trans->th_num_items = 1;
225 INT_SET(op3->oh_tid, ARCH_CONVERT, 0xb0c0d0d0);
226 INT_SET(op3->oh_len, ARCH_CONVERT, sizeof(xfs_buf_log_format_t));
227 INT_SET(op3->oh_clientid, ARCH_CONVERT, XFS_TRANSACTION);
228 INT_SET(op3->oh_flags, ARCH_CONVERT, 0);
229 INT_SET(op3->oh_res2, ARCH_CONVERT, 0);
230 /* an empty buffer too */
231 blf->blf_type = XFS_LI_BUF;
233 blf->blf_flags = XFS_BLI_CANCEL;
235 blf->blf_map_size = 1;
236 blf->blf_data_map[0]= 0;
238 INT_SET(op4->oh_tid, ARCH_CONVERT, 0xb0c0d0d0);
239 INT_SET(op4->oh_len, ARCH_CONVERT, sizeof(int));
240 INT_SET(op4->oh_clientid, ARCH_CONVERT, XFS_TRANSACTION);
241 INT_SET(op4->oh_flags, ARCH_CONVERT, 0);
242 INT_SET(op4->oh_res2, ARCH_CONVERT, 0);
244 *data=*(int*)(char*)"FISH"; /* this won't get written (I hope) */
246 INT_SET(op5->oh_tid, ARCH_CONVERT, 0xb0c0d0d0);
247 INT_SET(op5->oh_len, ARCH_CONVERT, 0);
248 INT_SET(op5->oh_clientid, ARCH_CONVERT, XFS_TRANSACTION);
249 INT_SET(op5->oh_flags, ARCH_CONVERT, XLOG_COMMIT_TRANS);
250 INT_SET(op5->oh_res2, ARCH_CONVERT, 0);
253 ASSIGN_ANY_LSN_DISK(head->h_lsn,
254 param_cycle, param_block++);
261 main(int argc, char *argv[])
265 fprintf(stderr,"*** loggen\n");
269 while ((c = getopt(argc, argv, "f:u:c:b:C:B:z:e:m:")) != -1) {
272 param_fmt=atoi(optarg);
275 memset(param_uuid, atoi(optarg), sizeof(param_uuid));
278 param_cycle=atoi(optarg);
281 param_block=atoi(optarg);
284 param_tail_cycle=atoi(optarg);
287 param_tail_block=atoi(optarg);
291 loggen_zero(atoi(optarg));
294 loggen_empty(atoi(optarg));
297 loggen_unmount(atoi(optarg));
301 fprintf(stderr, "unknown option\n");