]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - mkfs/proto.c
insert (experimental) rtcp binary - for eric/others working on realtime
[thirdparty/xfsprogs-dev.git] / mkfs / proto.c
1 /*
2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
3 *
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.
7 *
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.
11 *
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.
18 *
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.
22 *
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
25 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31 */
32
33 #include <libxfs.h>
34 #include "proto.h"
35
36 /*
37 * Prototypes for internal functions.
38 */
39 extern long long cvtnum(int blocksize, char *s);
40 extern void parseproto(xfs_mount_t *mp, xfs_inode_t *pip, char **pp,
41 char *name);
42 static long getnum(char **pp);
43 static char *getstr(char **pp);
44 static void fail(char *msg, int i);
45 static void getres(xfs_trans_t *tp, uint blocks);
46 static void rsvfile(xfs_mount_t *mp, xfs_inode_t *ip, long long len);
47 static int newfile(xfs_trans_t *tp, xfs_inode_t *ip, xfs_bmap_free_t *flist,
48 xfs_fsblock_t *first, int dolocal, int logit, char *buf, int len);
49 static char *newregfile(char **pp, int *len);
50 static void rtinit(xfs_mount_t *mp);
51 static long filesize(int fd);
52
53 /*
54 * Use this for block reservations needed for mkfs's conditions
55 * (basically no fragmentation).
56 */
57 #define MKFS_BLOCKRES_INODE \
58 ((uint)(XFS_IALLOC_BLOCKS(mp) + (XFS_IN_MAXLEVELS(mp) - 1)))
59 #define MKFS_BLOCKRES(rb) \
60 ((uint)(MKFS_BLOCKRES_INODE + XFS_DA_NODE_MAXDEPTH + \
61 (XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1) + (rb)))
62
63
64 char *
65 setup_proto(
66 char *fname)
67 {
68 char *buf;
69 static char dflt[] = "d--755 0 0 $";
70 int fd;
71 long size;
72
73 if (!fname)
74 return dflt;
75 if ((fd = open(fname, O_RDONLY)) < 0 || (size = filesize(fd)) < 0) {
76 fprintf(stderr, "%s: failed to open %s: %s\n",
77 progname, fname, strerror(errno));
78 exit(1);
79 }
80 buf = malloc(size + 1);
81 if (read(fd, buf, size) < size) {
82 fprintf(stderr, "%s: read failed on %s: %s\n",
83 progname, fname, strerror(errno));
84 exit(1);
85 }
86 if (buf[size - 1] != '\n') {
87 fprintf(stderr, "%s: proto file %s premature EOF\n",
88 progname, fname);
89 exit(1);
90 }
91 buf[size] = '\0';
92 /*
93 * Skip past the stuff there for compatibility, a string and 2 numbers.
94 */
95 (void)getstr(&buf); /* boot image name */
96 (void)getnum(&buf); /* block count */
97 (void)getnum(&buf); /* inode count */
98 return buf;
99 }
100
101 static long
102 getnum(
103 char **pp)
104 {
105 char *s;
106
107 s = getstr(pp);
108 return atol(s);
109 }
110
111 static void
112 fail(
113 char *msg,
114 int i)
115 {
116 fprintf(stderr, "%s: %s %d\n", progname, msg, i);
117 ASSERT(0);
118 exit(1);
119 }
120
121 static void
122 getres(
123 xfs_trans_t *tp,
124 uint blocks)
125 {
126 int i;
127 xfs_mount_t *mp;
128 uint r;
129
130 mp = tp->t_mountp;
131 for (i = 0, r = MKFS_BLOCKRES(blocks); r >= blocks; r--) {
132 i = libxfs_trans_reserve(tp, r, 0, 0, 0, 0);
133 if (i == 0)
134 return;
135 }
136 res_failed(i);
137 /* NOTREACHED */
138 }
139
140 static char *
141 getstr(
142 char **pp)
143 {
144 int c;
145 char *p;
146 char *rval;
147
148 p = *pp;
149 while ((c = *p)) {
150 switch (c) {
151 case ' ':
152 case '\t':
153 case '\n':
154 p++;
155 continue;
156 case ':':
157 p++;
158 while (*p++ != '\n')
159 ;
160 continue;
161 default:
162 rval = p;
163 while (c != ' ' && c != '\t' && c != '\n' && c != '\0')
164 c = *++p;
165 *p++ = '\0';
166 *pp = p;
167 return rval;
168 }
169 }
170 if (!c) {
171 fprintf(stderr, "%s: premature EOF in prototype file\n",
172 progname);
173 exit(1);
174 }
175 return NULL;
176 }
177
178 static void
179 rsvfile(
180 xfs_mount_t *mp,
181 xfs_inode_t *ip,
182 long long llen)
183 {
184 int error;
185 xfs_trans_t *tp;
186
187 error = libxfs_alloc_file_space(ip, 0, llen, 1, 0);
188
189 if (error) {
190 fail("error reserving space for a file", error);
191 exit(1);
192 }
193
194 /*
195 * update the inode timestamp, mode, and prealloc flag bits
196 */
197 tp = libxfs_trans_alloc(mp, 0);
198
199 libxfs_trans_ijoin(tp, ip, 0);
200 libxfs_trans_ihold(tp, ip);
201
202 ip->i_d.di_mode &= ~ISUID;
203
204 /*
205 * Note that we don't have to worry about mandatory
206 * file locking being disabled here because we only
207 * clear the ISGID bit if the Group execute bit is
208 * on, but if it was on then mandatory locking wouldn't
209 * have been enabled.
210 */
211 if (ip->i_d.di_mode & (IEXEC >> 3))
212 ip->i_d.di_mode &= ~ISGID;
213
214 libxfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
215
216 ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC;
217
218 libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
219 libxfs_trans_commit(tp, 0, NULL);
220 }
221
222 static int
223 newfile(
224 xfs_trans_t *tp,
225 xfs_inode_t *ip,
226 xfs_bmap_free_t *flist,
227 xfs_fsblock_t *first,
228 int dolocal,
229 int logit,
230 char *buf,
231 int len)
232 {
233 xfs_buf_t *bp;
234 xfs_daddr_t d;
235 int error;
236 int flags;
237 xfs_bmbt_irec_t map;
238 xfs_mount_t *mp;
239 xfs_extlen_t nb;
240 int nmap;
241
242 flags = 0;
243 mp = ip->i_mount;
244 if (dolocal && len <= XFS_IFORK_DSIZE(ip)) {
245 libxfs_idata_realloc(ip, len, XFS_DATA_FORK);
246 if (buf)
247 bcopy(buf, ip->i_df.if_u1.if_data, len);
248 ip->i_d.di_size = len;
249 ip->i_df.if_flags &= ~XFS_IFEXTENTS;
250 ip->i_df.if_flags |= XFS_IFINLINE;
251 ip->i_d.di_format = XFS_DINODE_FMT_LOCAL;
252 flags = XFS_ILOG_DDATA;
253 } else if (len > 0) {
254 nb = XFS_B_TO_FSB(mp, len);
255 nmap = 1;
256 error = libxfs_bmapi(tp, ip, 0, nb, XFS_BMAPI_WRITE, first, nb,
257 &map, &nmap, flist);
258 if (error) {
259 fail("error allocating space for a file", error);
260 }
261 if (nmap != 1) {
262 fprintf(stderr, "%s: cannot allocate space for file\n",
263 progname);
264 exit(1);
265 }
266 d = XFS_FSB_TO_DADDR(mp, map.br_startblock);
267 bp = libxfs_trans_get_buf(logit ? tp : 0, mp->m_dev, d,
268 nb << mp->m_blkbb_log, 0);
269 bcopy(buf, XFS_BUF_PTR(bp), len);
270 if (len < XFS_BUF_COUNT(bp))
271 bzero(XFS_BUF_PTR(bp) + len, XFS_BUF_COUNT(bp) - len);
272 if (logit)
273 libxfs_trans_log_buf(tp, bp, 0, XFS_BUF_COUNT(bp) - 1);
274 else
275 libxfs_writebuf(bp, 1);
276 }
277 ip->i_d.di_size = len;
278 return flags;
279 }
280
281 static char *
282 newregfile(
283 char **pp,
284 int *len)
285 {
286 char *buf;
287 int fd;
288 char *fname;
289 long size;
290
291 fname = getstr(pp);
292 if ((fd = open(fname, O_RDONLY)) < 0 || (size = filesize(fd)) < 0) {
293 fprintf(stderr, "%s: cannot open %s: %s\n",
294 progname, fname, strerror(errno));
295 exit(1);
296 }
297 if ((*len = (int)size)) {
298 buf = malloc(size);
299 if (read(fd, buf, size) < size) {
300 fprintf(stderr, "%s: read failed on %s: %s\n",
301 progname, fname, strerror(errno));
302 exit(1);
303 }
304 } else
305 buf = 0;
306 close(fd);
307 return buf;
308 }
309
310 static void
311 newdirent(
312 xfs_mount_t *mp,
313 xfs_trans_t *tp,
314 xfs_inode_t *pip,
315 char *name,
316 int namelen,
317 xfs_ino_t inum,
318 xfs_fsblock_t *first,
319 xfs_bmap_free_t *flist,
320 xfs_extlen_t total)
321 {
322 int error;
323
324 if (XFS_SB_VERSION_HASDIRV2(&mp->m_sb))
325 error = libxfs_dir2_createname(tp, pip, name, namelen,
326 inum, first, flist, total);
327 else
328 error = libxfs_dir_createname(tp, pip, name, namelen,
329 inum, first, flist, total);
330 if (error)
331 fail("directory createname error", error);
332 }
333
334 static void
335 newdirectory(
336 xfs_mount_t *mp,
337 xfs_trans_t *tp,
338 xfs_inode_t *dp,
339 xfs_inode_t *pdp)
340 {
341 int error;
342
343 if (XFS_SB_VERSION_HASDIRV2(&mp->m_sb))
344 error = libxfs_dir2_init(tp, dp, pdp);
345 else
346 error = libxfs_dir_init(tp, dp, pdp);
347 if (error)
348 fail("directory create error", error);
349 }
350
351 void
352 parseproto(
353 xfs_mount_t *mp,
354 xfs_inode_t *pip,
355 char **pp,
356 char *name)
357 {
358 #define IF_REGULAR 0
359 #define IF_RESERVED 1
360 #define IF_BLOCK 2
361 #define IF_CHAR 3
362 #define IF_DIRECTORY 4
363 #define IF_SYMLINK 5
364 #define IF_FIFO 6
365
366 char *buf;
367 int committed;
368 int error;
369 xfs_fsblock_t first;
370 int flags;
371 xfs_bmap_free_t flist;
372 int fmt;
373 int i;
374 xfs_inode_t *ip;
375 int len;
376 long long llen;
377 int majdev;
378 int mindev;
379 int mode;
380 char *mstr;
381 xfs_trans_t *tp;
382 int val;
383 int isroot = 0;
384 cred_t creds;
385 char *value;
386
387 bzero(&creds, sizeof(creds));
388 mstr = getstr(pp);
389 switch (mstr[0]) {
390 case '-':
391 fmt = IF_REGULAR;
392 break;
393 case 'r':
394 fmt = IF_RESERVED;
395 break;
396 case 'b':
397 fmt = IF_BLOCK;
398 break;
399 case 'c':
400 fmt = IF_CHAR;
401 break;
402 case 'd':
403 fmt = IF_DIRECTORY;
404 break;
405 case 'l':
406 fmt = IF_SYMLINK;
407 break;
408 case 'p':
409 fmt = IF_FIFO;
410 break;
411 default:
412 fprintf(stderr, "%s: bad format string %s\n", progname, mstr);
413 exit(1);
414 }
415 mode = 0;
416 switch (mstr[1]) {
417 case '-':
418 break;
419 case 'u':
420 mode |= ISUID;
421 break;
422 default:
423 fprintf(stderr, "%s: bad format string %s\n", progname, mstr);
424 exit(1);
425 }
426 switch (mstr[2]) {
427 case '-':
428 break;
429 case 'g':
430 mode |= ISGID;
431 break;
432 default:
433 fprintf(stderr, "%s: bad format string %s\n", progname, mstr);
434 exit(1);
435 }
436 val = 0;
437 for (i = 3; i < 6; i++) {
438 if (mstr[i] < '0' || mstr[i] > '7') {
439 fprintf(stderr, "%s: bad format string %s\n",
440 progname, mstr);
441 exit(1);
442 }
443 val = val * 8 + mstr[i] - '0';
444 }
445 mode |= val;
446 creds.cr_uid = (int)getnum(pp);
447 creds.cr_gid = (int)getnum(pp);
448 tp = libxfs_trans_alloc(mp, 0);
449 flags = XFS_ILOG_CORE;
450 XFS_BMAP_INIT(&flist, &first);
451 switch (fmt) {
452 case IF_REGULAR:
453 buf = newregfile(pp, &len);
454 getres(tp, XFS_B_TO_FSB(mp, len));
455 error = libxfs_inode_alloc(&tp, pip, mode|IFREG, 1,
456 mp->m_dev, &creds, &ip);
457 if (error)
458 fail("Inode allocation failed", error);
459 flags |= newfile(tp, ip, &flist, &first, 0, 0, buf, len);
460 if (buf)
461 free(buf);
462 libxfs_trans_ijoin(tp, pip, 0);
463 i = strlen(name);
464 newdirent(mp, tp, pip, name, i, ip->i_ino, &first, &flist, 1);
465 libxfs_trans_ihold(tp, pip);
466 break;
467
468 case IF_RESERVED: /* pre-allocated space only */
469 value = getstr(pp);
470 llen = cvtnum(mp->m_sb.sb_blocksize, value);
471 getres(tp, XFS_B_TO_FSB(mp, llen));
472
473 error = libxfs_inode_alloc(&tp, pip, mode|IFREG, 1,
474 mp->m_dev, &creds, &ip);
475 if (error)
476 fail("Inode pre-allocation failed", error);
477
478 libxfs_trans_ijoin(tp, pip, 0);
479
480 i = strlen(name);
481 newdirent(mp, tp, pip, name, i, ip->i_ino, &first, &flist, 1);
482 libxfs_trans_ihold(tp, pip);
483 libxfs_trans_log_inode(tp, ip, flags);
484
485 error = libxfs_bmap_finish(&tp, &flist, first, &committed);
486 if (error)
487 fail("Pre-allocated file creation failed", error);
488 libxfs_trans_commit(tp, 0, NULL);
489 rsvfile(mp, ip, llen);
490 return;
491
492 case IF_BLOCK:
493 getres(tp, 0);
494 majdev = (int)getnum(pp);
495 mindev = (int)getnum(pp);
496 error = libxfs_inode_alloc(&tp, pip, mode|IFBLK, 1,
497 makedev(majdev, mindev), &creds, &ip);
498 if (error) {
499 fail("Inode allocation failed", error);
500 }
501 libxfs_trans_ijoin(tp, pip, 0);
502 i = strlen(name);
503 newdirent(mp, tp, pip, name, i, ip->i_ino, &first, &flist, 1);
504 libxfs_trans_ihold(tp, pip);
505 flags |= XFS_ILOG_DEV;
506 break;
507
508 case IF_CHAR:
509 getres(tp, 0);
510 majdev = (int)getnum(pp);
511 mindev = (int)getnum(pp);
512 error = libxfs_inode_alloc(&tp, pip, mode|IFCHR, 1,
513 makedev(majdev, mindev), &creds, &ip);
514 if (error)
515 fail("Inode allocation failed", error);
516 libxfs_trans_ijoin(tp, pip, 0);
517 i = strlen(name);
518 newdirent(mp, tp, pip, name, i, ip->i_ino, &first, &flist, 1);
519 libxfs_trans_ihold(tp, pip);
520 flags |= XFS_ILOG_DEV;
521 break;
522
523 case IF_FIFO:
524 getres(tp, 0);
525 error = libxfs_inode_alloc(&tp, pip, mode|IFIFO, 1,
526 mp->m_dev, &creds, &ip);
527 if (error)
528 fail("Inode allocation failed", error);
529 libxfs_trans_ijoin(tp, pip, 0);
530 i = strlen(name);
531 newdirent(mp, tp, pip, name, i, ip->i_ino, &first, &flist, 1);
532 libxfs_trans_ihold(tp, pip);
533 break;
534 case IF_SYMLINK:
535 buf = getstr(pp);
536 len = (int)strlen(buf);
537 getres(tp, XFS_B_TO_FSB(mp, len));
538 error = libxfs_inode_alloc(&tp, pip, mode|IFLNK, 1,
539 mp->m_dev, &creds, &ip);
540 if (error)
541 fail("Inode allocation failed", error);
542 flags |= newfile(tp, ip, &flist, &first, 1, 1, buf, len);
543 libxfs_trans_ijoin(tp, pip, 0);
544 i = strlen(name);
545 newdirent(mp, tp, pip, name, i, ip->i_ino, &first, &flist, 1);
546 libxfs_trans_ihold(tp, pip);
547 break;
548 case IF_DIRECTORY:
549 getres(tp, 0);
550 error = libxfs_inode_alloc(&tp, pip, mode|IFDIR, 1,
551 mp->m_dev, &creds, &ip);
552 if (error)
553 fail("Inode allocation failed", error);
554 ip->i_d.di_nlink++; /* account for . */
555 if (!pip) {
556 pip = ip;
557 mp->m_sb.sb_rootino = ip->i_ino;
558 libxfs_mod_sb(tp, XFS_SB_ROOTINO);
559 mp->m_rootip = ip;
560 isroot = 1;
561 } else {
562 libxfs_trans_ijoin(tp, pip, 0);
563 i = strlen(name);
564 newdirent(mp, tp, pip, name, i, ip->i_ino,
565 &first, &flist, 1);
566 pip->i_d.di_nlink++;
567 libxfs_trans_ihold(tp, pip);
568 libxfs_trans_log_inode(tp, pip, XFS_ILOG_CORE);
569 }
570 newdirectory(mp, tp, ip, pip);
571 libxfs_trans_log_inode(tp, ip, flags);
572 error = libxfs_bmap_finish(&tp, &flist, first, &committed);
573 if (error)
574 fail("Directory creation failed", error);
575 libxfs_trans_ihold(tp, ip);
576 libxfs_trans_commit(tp, 0, NULL);
577 /*
578 * RT initialization. Do this here to ensure that
579 * the RT inodes get placed after the root inode.
580 */
581 if (isroot)
582 rtinit(mp);
583 tp = NULL;
584 for (;;) {
585 name = getstr(pp);
586 if (strcmp(name, "$") == 0)
587 break;
588 parseproto(mp, ip, pp, name);
589 }
590 libxfs_iput(ip, 0);
591 return;
592 }
593 libxfs_trans_log_inode(tp, ip, flags);
594 error = libxfs_bmap_finish(&tp, &flist, first, &committed);
595 if (error) {
596 fail("Error encountered creating file from prototype", error);
597 }
598 libxfs_trans_commit(tp, 0, NULL);
599 }
600
601 /*
602 * Allocate the realtime bitmap and summary inodes, and fill in data if any.
603 */
604 static void
605 rtinit(
606 xfs_mount_t *mp)
607 {
608 xfs_dfiloff_t bno;
609 int committed;
610 xfs_dfiloff_t ebno;
611 xfs_bmbt_irec_t *ep;
612 int error;
613 xfs_fsblock_t first;
614 xfs_bmap_free_t flist;
615 int i;
616 xfs_bmbt_irec_t map[XFS_BMAP_MAX_NMAP];
617 xfs_extlen_t nsumblocks;
618 int nmap;
619 xfs_inode_t *rbmip;
620 xfs_inode_t *rsumip;
621 xfs_trans_t *tp;
622 cred_t creds;
623
624 /*
625 * First, allocate the inodes.
626 */
627 tp = libxfs_trans_alloc(mp, 0);
628 if ((i = libxfs_trans_reserve(tp, MKFS_BLOCKRES_INODE, 0, 0, 0, 0)))
629 res_failed(i);
630 bzero(&creds, sizeof(creds));
631 error = libxfs_inode_alloc(&tp, mp->m_rootip, IFREG, 1,
632 mp->m_dev, &creds, &rbmip);
633 if (error) {
634 fail("Realtime bitmap inode allocation failed", error);
635 }
636 /*
637 * Do our thing with rbmip before allocating rsumip,
638 * because the next call to ialloc() may
639 * commit the transaction in which rbmip was allocated.
640 */
641 mp->m_sb.sb_rbmino = rbmip->i_ino;
642 rbmip->i_d.di_size = mp->m_sb.sb_rbmblocks * mp->m_sb.sb_blocksize;
643 rbmip->i_d.di_flags = XFS_DIFLAG_NEWRTBM;
644 *(__uint64_t *)&rbmip->i_d.di_atime = 0;
645 libxfs_trans_log_inode(tp, rbmip, XFS_ILOG_CORE);
646 libxfs_mod_sb(tp, XFS_SB_RBMINO);
647 libxfs_trans_ihold(tp, rbmip);
648 mp->m_rbmip = rbmip;
649 error = libxfs_inode_alloc(&tp, mp->m_rootip, IFREG, 1,
650 mp->m_dev, &creds, &rsumip);
651 if (error) {
652 fail("Realtime bitmap inode allocation failed", error);
653 }
654 mp->m_sb.sb_rsumino = rsumip->i_ino;
655 rsumip->i_d.di_size = mp->m_rsumsize;
656 libxfs_trans_log_inode(tp, rsumip, XFS_ILOG_CORE);
657 libxfs_mod_sb(tp, XFS_SB_RSUMINO);
658 libxfs_trans_ihold(tp, rsumip);
659 libxfs_trans_commit(tp, 0, NULL);
660 mp->m_rsumip = rsumip;
661 /*
662 * Next, give the bitmap file some zero-filled blocks.
663 */
664 tp = libxfs_trans_alloc(mp, 0);
665 if ((i = libxfs_trans_reserve(tp, mp->m_sb.sb_rbmblocks +
666 (XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1), 0, 0, 0, 0)))
667 res_failed(i);
668 libxfs_trans_ijoin(tp, rbmip, 0);
669 bno = 0;
670 XFS_BMAP_INIT(&flist, &first);
671 while (bno < mp->m_sb.sb_rbmblocks) {
672 nmap = XFS_BMAP_MAX_NMAP;
673 error = libxfs_bmapi(tp, rbmip, bno,
674 (xfs_extlen_t)(mp->m_sb.sb_rbmblocks - bno),
675 XFS_BMAPI_WRITE, &first, mp->m_sb.sb_rbmblocks,
676 map, &nmap, &flist);
677 if (error) {
678 fail("Allocation of the realtime bitmap failed", error);
679 }
680 for (i = 0, ep = map; i < nmap; i++, ep++) {
681 libxfs_device_zero(mp->m_dev,
682 XFS_FSB_TO_DADDR(mp, ep->br_startblock),
683 XFS_FSB_TO_BB(mp, ep->br_blockcount));
684 bno += ep->br_blockcount;
685 }
686 }
687
688 error = libxfs_bmap_finish(&tp, &flist, first, &committed);
689 if (error) {
690 fail("Allocation of the realtime bitmap failed", error);
691 }
692 libxfs_trans_commit(tp, 0, NULL);
693 /*
694 * Give the summary file some zero-filled blocks.
695 */
696 tp = libxfs_trans_alloc(mp, 0);
697 nsumblocks = mp->m_rsumsize >> mp->m_sb.sb_blocklog;
698 if ((i = libxfs_trans_reserve(tp,
699 nsumblocks + (XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1),
700 0, 0, 0, 0)))
701 res_failed(i);
702 libxfs_trans_ijoin(tp, rsumip, 0);
703 bno = 0;
704 XFS_BMAP_INIT(&flist, &first);
705 while (bno < nsumblocks) {
706 nmap = XFS_BMAP_MAX_NMAP;
707 error = libxfs_bmapi(tp, rsumip, bno,
708 (xfs_extlen_t)(nsumblocks - bno),
709 XFS_BMAPI_WRITE, &first, nsumblocks,
710 map, &nmap, &flist);
711 if (error) {
712 fail("Allocation of the realtime bitmap failed", error);
713 }
714 for (i = 0, ep = map; i < nmap; i++, ep++) {
715 libxfs_device_zero(mp->m_dev,
716 XFS_FSB_TO_DADDR(mp, ep->br_startblock),
717 XFS_FSB_TO_BB(mp, ep->br_blockcount));
718 bno += ep->br_blockcount;
719 }
720 }
721 error = libxfs_bmap_finish(&tp, &flist, first, &committed);
722 if (error) {
723 fail("Allocation of the realtime bitmap failed", error);
724 }
725 libxfs_trans_commit(tp, 0, NULL);
726 /*
727 * Free the whole area using transactions.
728 * Do one transaction per bitmap block.
729 */
730 for (bno = 0; bno < mp->m_sb.sb_rextents; bno = ebno) {
731 tp = libxfs_trans_alloc(mp, 0);
732 if ((i = libxfs_trans_reserve(tp, 0, 0, 0, 0, 0)))
733 res_failed(i);
734 XFS_BMAP_INIT(&flist, &first);
735 ebno = XFS_RTMIN(mp->m_sb.sb_rextents,
736 bno + NBBY * mp->m_sb.sb_blocksize);
737 error = libxfs_rtfree_extent(tp, bno, (xfs_extlen_t)(ebno-bno));
738 if (error) {
739 fail("Error initializing the realtime bitmap", error);
740 }
741 error = libxfs_bmap_finish(&tp, &flist, first, &committed);
742 if (error) {
743 fail("Error initializing the realtime bitmap", error);
744 }
745 libxfs_trans_commit(tp, 0, NULL);
746 }
747 }
748
749 void
750 res_failed(
751 int err)
752 {
753 fprintf(stderr, "%s: ran out of disk space!\n", progname);
754 ASSERT(0);
755 exit(1);
756 }
757
758 static long
759 filesize(
760 int fd)
761 {
762 struct stat64 stb;
763
764 if (fstat64(fd, &stb) < 0)
765 return -1;
766 return (long)stb.st_size;
767 }