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.
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 */
39 #ifndef ASSIGN_ANY_LSN_DISK
40 #define ASSIGN_ANY_LSN_DISK(lsn,cycle,block) \
42 INT_SET(((uint *)&(lsn))[0], ARCH_CONVERT, (cycle)); \
43 INT_SET(((uint *)&(lsn))[1], ARCH_CONVERT, (block)); \
50 fprintf(stderr,"Usage: loggen\n"
51 " set up parameters before writing record(s):\n"
52 " -f f - set format\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"
63 " redirect stdout to external log partition, or pipe to\n"
64 " dd with appropriate parameters to stuff into internal log.\n"
73 int param_tail_cycle = 1;
74 int param_tail_block = 0;
75 int param_fmt = XLOG_FMT;
76 uuid_t param_uuid = {0};
79 loggen_alloc(int blocks)
81 if (!(buf=realloc(buf, blocks*BBSIZE))) {
82 fprintf(stderr,"failed to allocate %d block(s)\n", blocks);
85 memset(buf, 0, blocks*BBSIZE);
93 fprintf(stderr,"no buffer allocated\n");
97 if (fwrite(buf, BBSIZE, bufblocks, stdout) != bufblocks) {
105 loggen_zero(int count)
109 fprintf(stderr," *** zero block (1BB) x %d\n", count);
116 loggen_unmount(int count)
118 xlog_rec_header_t *head;
119 xlog_op_header_t *op;
120 /* the data section must be 32 bit size aligned */
124 __uint32_t pad2; /* may as well make it 64 bits */
125 } magic = { XLOG_UNMOUNT_TYPE, 0, 0 };
129 fprintf(stderr," *** unmount record (2BB) x %d\n", count);
132 head = (xlog_rec_header_t *)buf;
133 op = (xlog_op_header_t *)(((char*)buf)+BBSIZE);
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.
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);
149 head->h_tail_lsn = cpu_to_be64(xlog_assign_lsn(param_tail_cycle,
152 memcpy(head->h_fs_uuid, param_uuid, sizeof(uuid_t));
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);
161 /* and the data for this op */
163 memcpy(op+1, &magic, sizeof(magic));
166 head->h_lsn = cpu_to_be64(xlog_assign_lsn(param_cycle, param_block++));
173 loggen_empty(int count)
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;
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 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)+
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);
216 head->h_tail_lsn = cpu_to_be64(xlog_assign_lsn(param_tail_cycle,
219 memcpy(head->h_fs_uuid, param_uuid, sizeof(uuid_t));
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);
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;
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;
237 trans->th_num_items = 1;
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;
243 op3->oh_res2 = cpu_to_be16(0);
244 /* an empty buffer too */
245 blfs.blf_type = XFS_LI_BUF;
247 #ifdef XFS_BLF_CANCEL
248 blfs.blf_flags = XFS_BLF_CANCEL;
250 blfs.blf_flags = XFS_BLI_CANCEL;
254 blfs.blf_map_size = 1;
255 blfs.blf_data_map[0]= 0;
256 memcpy(blf, &blfs, sizeof(blfs));
258 op4->oh_tid = cpu_to_be32(0xb0c0d0d0);
259 op4->oh_len = cpu_to_be32(sizeof(int));
260 op4->oh_clientid = XFS_TRANSACTION;
262 op4->oh_res2 = cpu_to_be16(0);
264 *data=*(int*)(char*)"FISH"; /* this won't get written (I hope) */
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);
273 head->h_lsn = cpu_to_be64(xlog_assign_lsn(param_cycle, param_block++));
280 main(int argc, char *argv[])
284 fprintf(stderr,"*** loggen\n");
288 while ((c = getopt(argc, argv, "f:u:c:b:C:B:z:e:m:")) != -1) {
291 param_fmt=atoi(optarg);
294 memset(param_uuid, atoi(optarg), sizeof(param_uuid));
297 param_cycle=atoi(optarg);
300 param_block=atoi(optarg);
303 param_tail_cycle=atoi(optarg);
306 param_tail_block=atoi(optarg);
310 loggen_zero(atoi(optarg));
313 loggen_empty(atoi(optarg));
316 loggen_unmount(atoi(optarg));
320 fprintf(stderr, "unknown option\n");