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