]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - mkfs/proto.c
9ff855482e78d09a6fd71f1d5bc728fd602cc8de
[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 "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)(mp->m_ialloc_blks + (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 = NULL;
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 goto out_fail;
63 }
64
65 buf = malloc(size + 1);
66 if (read(fd, buf, size) < size) {
67 fprintf(stderr, _("%s: read failed on %s: %s\n"),
68 progname, fname, strerror(errno));
69 goto out_fail;
70 }
71 if (buf[size - 1] != '\n') {
72 fprintf(stderr, _("%s: proto file %s premature EOF\n"),
73 progname, fname);
74 goto out_fail;
75 }
76 buf[size] = '\0';
77 /*
78 * Skip past the stuff there for compatibility, a string and 2 numbers.
79 */
80 (void)getstr(&buf); /* boot image name */
81 (void)getnum(&buf); /* block count */
82 (void)getnum(&buf); /* inode count */
83 close(fd);
84 return buf;
85
86 out_fail:
87 if (fd >= 0)
88 close(fd);
89 free(buf);
90 exit(1);
91 }
92
93 static long
94 getnum(
95 char **pp)
96 {
97 char *s;
98
99 s = getstr(pp);
100 return atol(s);
101 }
102
103 static void
104 fail(
105 char *msg,
106 int i)
107 {
108 fprintf(stderr, "%s: %s [%d - %s]\n", progname, msg, i, strerror(i));
109 exit(1);
110 }
111
112 void
113 res_failed(
114 int i)
115 {
116 fail(_("cannot reserve space"), i);
117 }
118
119 static void
120 getres(
121 xfs_trans_t *tp,
122 uint blocks)
123 {
124 int i;
125 xfs_mount_t *mp;
126 uint r;
127
128 mp = tp->t_mountp;
129 for (i = 0, r = MKFS_BLOCKRES(blocks); r >= blocks; r--) {
130 struct xfs_trans_res tres = {0};
131
132 i = -libxfs_trans_reserve(tp, &tres, r, 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 char 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 != '\0') {
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
201 ip->i_d.di_mode &= ~S_ISUID;
202
203 /*
204 * Note that we don't have to worry about mandatory
205 * file locking being disabled here because we only
206 * clear the S_ISGID bit if the Group execute bit is
207 * on, but if it was on then mandatory locking wouldn't
208 * have been enabled.
209 */
210 if (ip->i_d.di_mode & S_IXGRP)
211 ip->i_d.di_mode &= ~S_ISGID;
212
213 libxfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
214
215 ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC;
216
217 libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
218 libxfs_trans_commit(tp);
219 }
220
221 static int
222 newfile(
223 xfs_trans_t *tp,
224 xfs_inode_t *ip,
225 xfs_bmap_free_t *flist,
226 xfs_fsblock_t *first,
227 int dolocal,
228 int logit,
229 char *buf,
230 int len)
231 {
232 xfs_buf_t *bp;
233 xfs_daddr_t d;
234 int error;
235 int flags;
236 xfs_bmbt_irec_t map;
237 xfs_mount_t *mp;
238 xfs_extlen_t nb;
239 int nmap;
240
241 flags = 0;
242 mp = ip->i_mount;
243 if (dolocal && len <= XFS_IFORK_DSIZE(ip)) {
244 libxfs_idata_realloc(ip, len, XFS_DATA_FORK);
245 if (buf)
246 memmove(ip->i_df.if_u1.if_data, buf, len);
247 ip->i_d.di_size = len;
248 ip->i_df.if_flags &= ~XFS_IFEXTENTS;
249 ip->i_df.if_flags |= XFS_IFINLINE;
250 ip->i_d.di_format = XFS_DINODE_FMT_LOCAL;
251 flags = XFS_ILOG_DDATA;
252 } else if (len > 0) {
253 nb = XFS_B_TO_FSB(mp, len);
254 nmap = 1;
255 error = -libxfs_bmapi_write(tp, ip, 0, nb, 0, first, nb,
256 &map, &nmap, flist);
257 if (error) {
258 fail(_("error allocating space for a file"), error);
259 }
260 if (nmap != 1) {
261 fprintf(stderr,
262 _("%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 memmove(XFS_BUF_PTR(bp), buf, len);
270 if (len < XFS_BUF_COUNT(bp))
271 memset(XFS_BUF_PTR(bp) + len, 0, 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, LIBXFS_EXIT_ON_FAILURE);
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 struct xfs_name *name,
316 xfs_ino_t inum,
317 xfs_fsblock_t *first,
318 xfs_bmap_free_t *flist)
319 {
320 int error;
321 int rsv;
322
323 rsv = XFS_DIRENTER_SPACE_RES(mp, name->len);
324
325 error = -libxfs_dir_createname(tp, pip, name, inum, first, flist, rsv);
326 if (error)
327 fail(_("directory createname error"), error);
328 }
329
330 static void
331 newdirectory(
332 xfs_mount_t *mp,
333 xfs_trans_t *tp,
334 xfs_inode_t *dp,
335 xfs_inode_t *pdp)
336 {
337 int error;
338
339 error = -libxfs_dir_init(tp, dp, pdp);
340 if (error)
341 fail(_("directory create error"), error);
342 }
343
344 static void
345 parseproto(
346 xfs_mount_t *mp,
347 xfs_inode_t *pip,
348 struct fsxattr *fsxp,
349 char **pp,
350 char *name)
351 {
352 #define IF_REGULAR 0
353 #define IF_RESERVED 1
354 #define IF_BLOCK 2
355 #define IF_CHAR 3
356 #define IF_DIRECTORY 4
357 #define IF_SYMLINK 5
358 #define IF_FIFO 6
359
360 char *buf;
361 int error;
362 xfs_fsblock_t first;
363 int flags;
364 xfs_bmap_free_t flist;
365 int fmt;
366 int i;
367 xfs_inode_t *ip;
368 int len;
369 long long llen;
370 int majdev;
371 int mindev;
372 int mode;
373 char *mstr;
374 xfs_trans_t *tp;
375 int val;
376 int isroot = 0;
377 cred_t creds;
378 char *value;
379 struct xfs_name xname;
380
381 memset(&creds, 0, sizeof(creds));
382 mstr = getstr(pp);
383 switch (mstr[0]) {
384 case '-':
385 fmt = IF_REGULAR;
386 break;
387 case 'r':
388 fmt = IF_RESERVED;
389 break;
390 case 'b':
391 fmt = IF_BLOCK;
392 break;
393 case 'c':
394 fmt = IF_CHAR;
395 break;
396 case 'd':
397 fmt = IF_DIRECTORY;
398 break;
399 case 'l':
400 fmt = IF_SYMLINK;
401 break;
402 case 'p':
403 fmt = IF_FIFO;
404 break;
405 default:
406 fprintf(stderr, _("%s: bad format string %s\n"),
407 progname, mstr);
408 exit(1);
409 }
410 mode = 0;
411 switch (mstr[1]) {
412 case '-':
413 break;
414 case 'u':
415 mode |= S_ISUID;
416 break;
417 default:
418 fprintf(stderr, _("%s: bad format string %s\n"),
419 progname, mstr);
420 exit(1);
421 }
422 switch (mstr[2]) {
423 case '-':
424 break;
425 case 'g':
426 mode |= S_ISGID;
427 break;
428 default:
429 fprintf(stderr, _("%s: bad format string %s\n"),
430 progname, mstr);
431 exit(1);
432 }
433 val = 0;
434 for (i = 3; i < 6; i++) {
435 if (mstr[i] < '0' || mstr[i] > '7') {
436 fprintf(stderr, _("%s: bad format string %s\n"),
437 progname, mstr);
438 exit(1);
439 }
440 val = val * 8 + mstr[i] - '0';
441 }
442 mode |= val;
443 creds.cr_uid = (int)getnum(pp);
444 creds.cr_gid = (int)getnum(pp);
445 xname.name = (unsigned char *)name;
446 xname.len = name ? strlen(name) : 0;
447 xname.type = 0;
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|S_IFREG, 1, 0,
456 &creds, fsxp, &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 xname.type = XFS_DIR3_FT_REG_FILE;
464 newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &flist);
465 break;
466
467 case IF_RESERVED: /* pre-allocated space only */
468 value = getstr(pp);
469 llen = cvtnum(mp->m_sb.sb_blocksize, mp->m_sb.sb_sectsize, value);
470 getres(tp, XFS_B_TO_FSB(mp, llen));
471
472 error = -libxfs_inode_alloc(&tp, pip, mode|S_IFREG, 1, 0,
473 &creds, fsxp, &ip);
474 if (error)
475 fail(_("Inode pre-allocation failed"), error);
476
477 libxfs_trans_ijoin(tp, pip, 0);
478
479 xname.type = XFS_DIR3_FT_REG_FILE;
480 newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &flist);
481 libxfs_trans_log_inode(tp, ip, flags);
482
483 error = -libxfs_bmap_finish(&tp, &flist, ip);
484 if (error)
485 fail(_("Pre-allocated file creation failed"), error);
486 libxfs_trans_commit(tp);
487 rsvfile(mp, ip, llen);
488 IRELE(ip);
489 return;
490
491 case IF_BLOCK:
492 getres(tp, 0);
493 majdev = (int)getnum(pp);
494 mindev = (int)getnum(pp);
495 error = -libxfs_inode_alloc(&tp, pip, mode|S_IFBLK, 1,
496 IRIX_MKDEV(majdev, mindev), &creds, fsxp, &ip);
497 if (error) {
498 fail(_("Inode allocation failed"), error);
499 }
500 libxfs_trans_ijoin(tp, pip, 0);
501 xname.type = XFS_DIR3_FT_BLKDEV;
502 newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &flist);
503 flags |= XFS_ILOG_DEV;
504 break;
505
506 case IF_CHAR:
507 getres(tp, 0);
508 majdev = (int)getnum(pp);
509 mindev = (int)getnum(pp);
510 error = -libxfs_inode_alloc(&tp, pip, mode|S_IFCHR, 1,
511 IRIX_MKDEV(majdev, mindev), &creds, fsxp, &ip);
512 if (error)
513 fail(_("Inode allocation failed"), error);
514 libxfs_trans_ijoin(tp, pip, 0);
515 xname.type = XFS_DIR3_FT_CHRDEV;
516 newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &flist);
517 flags |= XFS_ILOG_DEV;
518 break;
519
520 case IF_FIFO:
521 getres(tp, 0);
522 error = -libxfs_inode_alloc(&tp, pip, mode|S_IFIFO, 1, 0,
523 &creds, fsxp, &ip);
524 if (error)
525 fail(_("Inode allocation failed"), error);
526 libxfs_trans_ijoin(tp, pip, 0);
527 xname.type = XFS_DIR3_FT_FIFO;
528 newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &flist);
529 break;
530 case IF_SYMLINK:
531 buf = getstr(pp);
532 len = (int)strlen(buf);
533 getres(tp, XFS_B_TO_FSB(mp, len));
534 error = -libxfs_inode_alloc(&tp, pip, mode|S_IFLNK, 1, 0,
535 &creds, fsxp, &ip);
536 if (error)
537 fail(_("Inode allocation failed"), error);
538 flags |= newfile(tp, ip, &flist, &first, 1, 1, buf, len);
539 libxfs_trans_ijoin(tp, pip, 0);
540 xname.type = XFS_DIR3_FT_SYMLINK;
541 newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &flist);
542 break;
543 case IF_DIRECTORY:
544 getres(tp, 0);
545 error = -libxfs_inode_alloc(&tp, pip, mode|S_IFDIR, 1, 0,
546 &creds, fsxp, &ip);
547 if (error)
548 fail(_("Inode allocation failed"), error);
549 inc_nlink(VFS_I(ip)); /* account for . */
550 if (!pip) {
551 pip = ip;
552 mp->m_sb.sb_rootino = ip->i_ino;
553 libxfs_log_sb(tp);
554 isroot = 1;
555 } else {
556 libxfs_trans_ijoin(tp, pip, 0);
557 xname.type = XFS_DIR3_FT_DIR;
558 newdirent(mp, tp, pip, &xname, ip->i_ino,
559 &first, &flist);
560 inc_nlink(VFS_I(pip));
561 libxfs_trans_log_inode(tp, pip, XFS_ILOG_CORE);
562 }
563 newdirectory(mp, tp, ip, pip);
564 libxfs_trans_log_inode(tp, ip, flags);
565 error = -libxfs_bmap_finish(&tp, &flist, ip);
566 if (error)
567 fail(_("Directory creation failed"), error);
568 libxfs_trans_commit(tp);
569 /*
570 * RT initialization. Do this here to ensure that
571 * the RT inodes get placed after the root inode.
572 */
573 if (isroot)
574 rtinit(mp);
575 tp = NULL;
576 for (;;) {
577 name = getstr(pp);
578 if (!name)
579 break;
580 if (strcmp(name, "$") == 0)
581 break;
582 parseproto(mp, ip, fsxp, pp, name);
583 }
584 IRELE(ip);
585 return;
586 default:
587 ASSERT(0);
588 fail(_("Unknown format"), EINVAL);
589 }
590 libxfs_trans_log_inode(tp, ip, flags);
591 error = -libxfs_bmap_finish(&tp, &flist, ip);
592 if (error) {
593 fail(_("Error encountered creating file from prototype file"),
594 error);
595 }
596 libxfs_trans_commit(tp);
597 IRELE(ip);
598 }
599
600 void
601 parse_proto(
602 xfs_mount_t *mp,
603 struct fsxattr *fsx,
604 char **pp)
605 {
606 parseproto(mp, NULL, fsx, pp, NULL);
607 }
608
609 /*
610 * Allocate the realtime bitmap and summary inodes, and fill in data if any.
611 */
612 static void
613 rtinit(
614 xfs_mount_t *mp)
615 {
616 xfs_fileoff_t bno;
617 xfs_fileoff_t ebno;
618 xfs_bmbt_irec_t *ep;
619 int error;
620 xfs_fsblock_t first;
621 xfs_bmap_free_t flist;
622 int i;
623 xfs_bmbt_irec_t map[XFS_BMAP_MAX_NMAP];
624 xfs_extlen_t nsumblocks;
625 int nmap;
626 xfs_inode_t *rbmip;
627 xfs_inode_t *rsumip;
628 xfs_trans_t *tp;
629 struct cred creds;
630 struct fsxattr fsxattrs;
631 struct xfs_trans_res tres = {0};
632
633 /*
634 * First, allocate the inodes.
635 */
636 tp = libxfs_trans_alloc(mp, 0);
637 i = -libxfs_trans_reserve(tp, &tres, MKFS_BLOCKRES_INODE, 0);
638 if (i)
639 res_failed(i);
640
641 memset(&creds, 0, sizeof(creds));
642 memset(&fsxattrs, 0, sizeof(fsxattrs));
643 error = -libxfs_inode_alloc(&tp, NULL, S_IFREG, 1, 0,
644 &creds, &fsxattrs, &rbmip);
645 if (error) {
646 fail(_("Realtime bitmap inode allocation failed"), error);
647 }
648 /*
649 * Do our thing with rbmip before allocating rsumip,
650 * because the next call to ialloc() may
651 * commit the transaction in which rbmip was allocated.
652 */
653 mp->m_sb.sb_rbmino = rbmip->i_ino;
654 rbmip->i_d.di_size = mp->m_sb.sb_rbmblocks * mp->m_sb.sb_blocksize;
655 rbmip->i_d.di_flags = XFS_DIFLAG_NEWRTBM;
656 *(__uint64_t *)&VFS_I(mp->m_rbmip)->i_atime = 0;
657 libxfs_trans_log_inode(tp, rbmip, XFS_ILOG_CORE);
658 libxfs_log_sb(tp);
659 mp->m_rbmip = rbmip;
660 error = -libxfs_inode_alloc(&tp, NULL, S_IFREG, 1, 0,
661 &creds, &fsxattrs, &rsumip);
662 if (error) {
663 fail(_("Realtime summary inode allocation failed"), error);
664 }
665 mp->m_sb.sb_rsumino = rsumip->i_ino;
666 rsumip->i_d.di_size = mp->m_rsumsize;
667 libxfs_trans_log_inode(tp, rsumip, XFS_ILOG_CORE);
668 libxfs_log_sb(tp);
669 libxfs_trans_commit(tp);
670 mp->m_rsumip = rsumip;
671 /*
672 * Next, give the bitmap file some zero-filled blocks.
673 */
674 tp = libxfs_trans_alloc(mp, 0);
675 i = -libxfs_trans_reserve(tp, &tres, mp->m_sb.sb_rbmblocks +
676 (XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1), 0);
677 if (i)
678 res_failed(i);
679
680 libxfs_trans_ijoin(tp, rbmip, 0);
681 bno = 0;
682 xfs_bmap_init(&flist, &first);
683 while (bno < mp->m_sb.sb_rbmblocks) {
684 nmap = XFS_BMAP_MAX_NMAP;
685 error = -libxfs_bmapi_write(tp, rbmip, bno,
686 (xfs_extlen_t)(mp->m_sb.sb_rbmblocks - bno),
687 0, &first, mp->m_sb.sb_rbmblocks,
688 map, &nmap, &flist);
689 if (error) {
690 fail(_("Allocation of the realtime bitmap failed"),
691 error);
692 }
693 for (i = 0, ep = map; i < nmap; i++, ep++) {
694 libxfs_device_zero(mp->m_ddev_targp,
695 XFS_FSB_TO_DADDR(mp, ep->br_startblock),
696 XFS_FSB_TO_BB(mp, ep->br_blockcount));
697 bno += ep->br_blockcount;
698 }
699 }
700
701 error = -libxfs_bmap_finish(&tp, &flist, rbmip);
702 if (error) {
703 fail(_("Completion of the realtime bitmap failed"), error);
704 }
705 libxfs_trans_commit(tp);
706
707 /*
708 * Give the summary file some zero-filled blocks.
709 */
710 tp = libxfs_trans_alloc(mp, 0);
711 nsumblocks = mp->m_rsumsize >> mp->m_sb.sb_blocklog;
712 i = -libxfs_trans_reserve(tp, &tres, nsumblocks +
713 (XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1), 0);
714 if (i)
715 res_failed(i);
716 libxfs_trans_ijoin(tp, rsumip, 0);
717 bno = 0;
718 xfs_bmap_init(&flist, &first);
719 while (bno < nsumblocks) {
720 nmap = XFS_BMAP_MAX_NMAP;
721 error = -libxfs_bmapi_write(tp, rsumip, bno,
722 (xfs_extlen_t)(nsumblocks - bno),
723 0, &first, nsumblocks,
724 map, &nmap, &flist);
725 if (error) {
726 fail(_("Allocation of the realtime summary failed"),
727 error);
728 }
729 for (i = 0, ep = map; i < nmap; i++, ep++) {
730 libxfs_device_zero(mp->m_ddev_targp,
731 XFS_FSB_TO_DADDR(mp, ep->br_startblock),
732 XFS_FSB_TO_BB(mp, ep->br_blockcount));
733 bno += ep->br_blockcount;
734 }
735 }
736 error = -libxfs_bmap_finish(&tp, &flist, rsumip);
737 if (error) {
738 fail(_("Completion of the realtime summary failed"), error);
739 }
740 libxfs_trans_commit(tp);
741
742 /*
743 * Free the whole area using transactions.
744 * Do one transaction per bitmap block.
745 */
746 for (bno = 0; bno < mp->m_sb.sb_rextents; bno = ebno) {
747 tp = libxfs_trans_alloc(mp, 0);
748 i = -libxfs_trans_reserve(tp, &tres, 0, 0);
749 if (i)
750 res_failed(i);
751 libxfs_trans_ijoin(tp, rbmip, 0);
752 xfs_bmap_init(&flist, &first);
753 ebno = XFS_RTMIN(mp->m_sb.sb_rextents,
754 bno + NBBY * mp->m_sb.sb_blocksize);
755 error = -libxfs_rtfree_extent(tp, bno, (xfs_extlen_t)(ebno-bno));
756 if (error) {
757 fail(_("Error initializing the realtime space"),
758 error);
759 }
760 error = -libxfs_bmap_finish(&tp, &flist, rbmip);
761 if (error) {
762 fail(_("Error completing the realtime space"), error);
763 }
764 libxfs_trans_commit(tp);
765 }
766 }
767
768 static long
769 filesize(
770 int fd)
771 {
772 struct stat64 stb;
773
774 if (fstat64(fd, &stb) < 0)
775 return -1;
776 return (long)stb.st_size;
777 }