]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - mkfs/proto.c
09a9439f0205cb1112716f6435377511744eb499
2 * Copyright (c) 2000-2001,2005 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 #include "xfs_multidisk.h"
24 * Prototypes for internal functions.
26 static char *getstr(char **pp
);
27 static void fail(char *msg
, int i
);
28 static void getres(xfs_trans_t
*tp
, uint blocks
);
29 static void rsvfile(xfs_mount_t
*mp
, xfs_inode_t
*ip
, long long len
);
30 static int newfile(xfs_trans_t
*tp
, xfs_inode_t
*ip
, xfs_bmap_free_t
*flist
,
31 xfs_fsblock_t
*first
, int dolocal
, int logit
, char *buf
, int len
);
32 static char *newregfile(char **pp
, int *len
);
33 static void rtinit(xfs_mount_t
*mp
);
34 static long filesize(int fd
);
37 * Use this for block reservations needed for mkfs's conditions
38 * (basically no fragmentation).
40 #define MKFS_BLOCKRES_INODE \
41 ((uint)(mp->m_ialloc_blks + (mp->m_in_maxlevels - 1)))
42 #define MKFS_BLOCKRES(rb) \
43 ((uint)(MKFS_BLOCKRES_INODE + XFS_DA_NODE_MAXDEPTH + \
44 (XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1) + (rb)))
50 unsigned int sectsize
,
57 return cvtnum(blksize
, sectsize
, str
);
59 i
= strtoll(str
, &sp
, 0);
60 if (i
== 0 && sp
== str
)
63 return -1LL; /* trailing garbage */
72 static char dflt
[] = "d--755 0 0 $";
78 if ((fd
= open(fname
, O_RDONLY
)) < 0 || (size
= filesize(fd
)) < 0) {
79 fprintf(stderr
, _("%s: failed to open %s: %s\n"),
80 progname
, fname
, strerror(errno
));
84 buf
= malloc(size
+ 1);
85 if (read(fd
, buf
, size
) < size
) {
86 fprintf(stderr
, _("%s: read failed on %s: %s\n"),
87 progname
, fname
, strerror(errno
));
90 if (buf
[size
- 1] != '\n') {
91 fprintf(stderr
, _("%s: proto file %s premature EOF\n"),
97 * Skip past the stuff there for compatibility, a string and 2 numbers.
99 (void)getstr(&buf
); /* boot image name */
100 (void)getnum(getstr(&buf
), 0, 0, false); /* block count */
101 (void)getnum(getstr(&buf
), 0, 0, false); /* inode count */
117 fprintf(stderr
, "%s: %s [%d - %s]\n", progname
, msg
, i
, strerror(i
));
125 fail(_("cannot reserve space"), i
);
138 for (i
= 0, r
= MKFS_BLOCKRES(blocks
); r
>= blocks
; r
--) {
139 struct xfs_trans_res tres
= {0};
141 i
= -libxfs_trans_reserve(tp
, &tres
, r
, 0);
172 while (c
!= ' ' && c
!= '\t' && c
!= '\n' && c
!= '\0')
180 fprintf(stderr
, _("%s: premature EOF in prototype file\n"),
196 error
= -libxfs_alloc_file_space(ip
, 0, llen
, 1, 0);
199 fail(_("error reserving space for a file"), error
);
204 * update the inode timestamp, mode, and prealloc flag bits
206 tp
= libxfs_trans_alloc(mp
, 0);
208 libxfs_trans_ijoin(tp
, ip
, 0);
210 VFS_I(ip
)->i_mode
&= ~S_ISUID
;
213 * Note that we don't have to worry about mandatory
214 * file locking being disabled here because we only
215 * clear the S_ISGID bit if the Group execute bit is
216 * on, but if it was on then mandatory locking wouldn't
219 if (VFS_I(ip
)->i_mode
& S_IXGRP
)
220 VFS_I(ip
)->i_mode
&= ~S_ISGID
;
222 libxfs_trans_ichgtime(tp
, ip
, XFS_ICHGTIME_MOD
| XFS_ICHGTIME_CHG
);
224 ip
->i_d
.di_flags
|= XFS_DIFLAG_PREALLOC
;
226 libxfs_trans_log_inode(tp
, ip
, XFS_ILOG_CORE
);
227 libxfs_trans_commit(tp
);
234 xfs_bmap_free_t
*flist
,
235 xfs_fsblock_t
*first
,
252 if (dolocal
&& len
<= XFS_IFORK_DSIZE(ip
)) {
253 libxfs_idata_realloc(ip
, len
, XFS_DATA_FORK
);
255 memmove(ip
->i_df
.if_u1
.if_data
, buf
, len
);
256 ip
->i_d
.di_size
= len
;
257 ip
->i_df
.if_flags
&= ~XFS_IFEXTENTS
;
258 ip
->i_df
.if_flags
|= XFS_IFINLINE
;
259 ip
->i_d
.di_format
= XFS_DINODE_FMT_LOCAL
;
260 flags
= XFS_ILOG_DDATA
;
261 } else if (len
> 0) {
262 nb
= XFS_B_TO_FSB(mp
, len
);
264 error
= -libxfs_bmapi_write(tp
, ip
, 0, nb
, 0, first
, nb
,
267 fail(_("error allocating space for a file"), error
);
271 _("%s: cannot allocate space for file\n"),
275 d
= XFS_FSB_TO_DADDR(mp
, map
.br_startblock
);
276 bp
= libxfs_trans_get_buf(logit
? tp
: 0, mp
->m_dev
, d
,
277 nb
<< mp
->m_blkbb_log
, 0);
278 memmove(XFS_BUF_PTR(bp
), buf
, len
);
279 if (len
< XFS_BUF_COUNT(bp
))
280 memset(XFS_BUF_PTR(bp
) + len
, 0, XFS_BUF_COUNT(bp
) - len
);
282 libxfs_trans_log_buf(tp
, bp
, 0, XFS_BUF_COUNT(bp
) - 1);
284 libxfs_writebuf(bp
, LIBXFS_EXIT_ON_FAILURE
);
286 ip
->i_d
.di_size
= len
;
301 if ((fd
= open(fname
, O_RDONLY
)) < 0 || (size
= filesize(fd
)) < 0) {
302 fprintf(stderr
, _("%s: cannot open %s: %s\n"),
303 progname
, fname
, strerror(errno
));
306 if ((*len
= (int)size
)) {
308 if (read(fd
, buf
, size
) < size
) {
309 fprintf(stderr
, _("%s: read failed on %s: %s\n"),
310 progname
, fname
, strerror(errno
));
324 struct xfs_name
*name
,
326 xfs_fsblock_t
*first
,
327 xfs_bmap_free_t
*flist
)
332 rsv
= XFS_DIRENTER_SPACE_RES(mp
, name
->len
);
334 error
= -libxfs_dir_createname(tp
, pip
, name
, inum
, first
, flist
, rsv
);
336 fail(_("directory createname error"), error
);
348 error
= -libxfs_dir_init(tp
, dp
, pdp
);
350 fail(_("directory create error"), error
);
357 struct fsxattr
*fsxp
,
362 #define IF_RESERVED 1
365 #define IF_DIRECTORY 4
373 xfs_bmap_free_t flist
;
388 struct xfs_name xname
;
390 memset(&creds
, 0, sizeof(creds
));
415 fprintf(stderr
, _("%s: bad format string %s\n"),
427 fprintf(stderr
, _("%s: bad format string %s\n"),
438 fprintf(stderr
, _("%s: bad format string %s\n"),
443 for (i
= 3; i
< 6; i
++) {
444 if (mstr
[i
] < '0' || mstr
[i
] > '7') {
445 fprintf(stderr
, _("%s: bad format string %s\n"),
449 val
= val
* 8 + mstr
[i
] - '0';
452 creds
.cr_uid
= (int)getnum(getstr(pp
), 0, 0, false);
453 creds
.cr_gid
= (int)getnum(getstr(pp
), 0, 0, false);
454 xname
.name
= (unsigned char *)name
;
455 xname
.len
= name
? strlen(name
) : 0;
457 tp
= libxfs_trans_alloc(mp
, 0);
458 flags
= XFS_ILOG_CORE
;
459 xfs_bmap_init(&flist
, &first
);
462 buf
= newregfile(pp
, &len
);
463 getres(tp
, XFS_B_TO_FSB(mp
, len
));
464 error
= -libxfs_inode_alloc(&tp
, pip
, mode
|S_IFREG
, 1, 0,
467 fail(_("Inode allocation failed"), error
);
468 flags
|= newfile(tp
, ip
, &flist
, &first
, 0, 0, buf
, len
);
471 libxfs_trans_ijoin(tp
, pip
, 0);
472 xname
.type
= XFS_DIR3_FT_REG_FILE
;
473 newdirent(mp
, tp
, pip
, &xname
, ip
->i_ino
, &first
, &flist
);
476 case IF_RESERVED
: /* pre-allocated space only */
478 llen
= getnum(value
, mp
->m_sb
.sb_blocksize
,
479 mp
->m_sb
.sb_sectsize
, true);
482 _("%s: Bad value %s for proto file %s\n"),
483 progname
, value
, name
);
486 getres(tp
, XFS_B_TO_FSB(mp
, llen
));
488 error
= -libxfs_inode_alloc(&tp
, pip
, mode
|S_IFREG
, 1, 0,
491 fail(_("Inode pre-allocation failed"), error
);
493 libxfs_trans_ijoin(tp
, pip
, 0);
495 xname
.type
= XFS_DIR3_FT_REG_FILE
;
496 newdirent(mp
, tp
, pip
, &xname
, ip
->i_ino
, &first
, &flist
);
497 libxfs_trans_log_inode(tp
, ip
, flags
);
499 error
= -libxfs_bmap_finish(&tp
, &flist
, ip
);
501 fail(_("Pre-allocated file creation failed"), error
);
502 libxfs_trans_commit(tp
);
503 rsvfile(mp
, ip
, llen
);
509 majdev
= getnum(getstr(pp
), 0, 0, false);
510 mindev
= getnum(getstr(pp
), 0, 0, false);
511 error
= -libxfs_inode_alloc(&tp
, pip
, mode
|S_IFBLK
, 1,
512 IRIX_MKDEV(majdev
, mindev
), &creds
, fsxp
, &ip
);
514 fail(_("Inode allocation failed"), error
);
516 libxfs_trans_ijoin(tp
, pip
, 0);
517 xname
.type
= XFS_DIR3_FT_BLKDEV
;
518 newdirent(mp
, tp
, pip
, &xname
, ip
->i_ino
, &first
, &flist
);
519 flags
|= XFS_ILOG_DEV
;
524 majdev
= getnum(getstr(pp
), 0, 0, false);
525 mindev
= getnum(getstr(pp
), 0, 0, false);
526 error
= -libxfs_inode_alloc(&tp
, pip
, mode
|S_IFCHR
, 1,
527 IRIX_MKDEV(majdev
, mindev
), &creds
, fsxp
, &ip
);
529 fail(_("Inode allocation failed"), error
);
530 libxfs_trans_ijoin(tp
, pip
, 0);
531 xname
.type
= XFS_DIR3_FT_CHRDEV
;
532 newdirent(mp
, tp
, pip
, &xname
, ip
->i_ino
, &first
, &flist
);
533 flags
|= XFS_ILOG_DEV
;
538 error
= -libxfs_inode_alloc(&tp
, pip
, mode
|S_IFIFO
, 1, 0,
541 fail(_("Inode allocation failed"), error
);
542 libxfs_trans_ijoin(tp
, pip
, 0);
543 xname
.type
= XFS_DIR3_FT_FIFO
;
544 newdirent(mp
, tp
, pip
, &xname
, ip
->i_ino
, &first
, &flist
);
548 len
= (int)strlen(buf
);
549 getres(tp
, XFS_B_TO_FSB(mp
, len
));
550 error
= -libxfs_inode_alloc(&tp
, pip
, mode
|S_IFLNK
, 1, 0,
553 fail(_("Inode allocation failed"), error
);
554 flags
|= newfile(tp
, ip
, &flist
, &first
, 1, 1, buf
, len
);
555 libxfs_trans_ijoin(tp
, pip
, 0);
556 xname
.type
= XFS_DIR3_FT_SYMLINK
;
557 newdirent(mp
, tp
, pip
, &xname
, ip
->i_ino
, &first
, &flist
);
561 error
= -libxfs_inode_alloc(&tp
, pip
, mode
|S_IFDIR
, 1, 0,
564 fail(_("Inode allocation failed"), error
);
565 inc_nlink(VFS_I(ip
)); /* account for . */
568 mp
->m_sb
.sb_rootino
= ip
->i_ino
;
572 libxfs_trans_ijoin(tp
, pip
, 0);
573 xname
.type
= XFS_DIR3_FT_DIR
;
574 newdirent(mp
, tp
, pip
, &xname
, ip
->i_ino
,
576 inc_nlink(VFS_I(pip
));
577 libxfs_trans_log_inode(tp
, pip
, XFS_ILOG_CORE
);
579 newdirectory(mp
, tp
, ip
, pip
);
580 libxfs_trans_log_inode(tp
, ip
, flags
);
581 error
= -libxfs_bmap_finish(&tp
, &flist
, ip
);
583 fail(_("Directory creation failed"), error
);
584 libxfs_trans_commit(tp
);
586 * RT initialization. Do this here to ensure that
587 * the RT inodes get placed after the root inode.
596 if (strcmp(name
, "$") == 0)
598 parseproto(mp
, ip
, fsxp
, pp
, name
);
604 fail(_("Unknown format"), EINVAL
);
606 libxfs_trans_log_inode(tp
, ip
, flags
);
607 error
= -libxfs_bmap_finish(&tp
, &flist
, ip
);
609 fail(_("Error encountered creating file from prototype file"),
612 libxfs_trans_commit(tp
);
622 parseproto(mp
, NULL
, fsx
, pp
, NULL
);
626 * Allocate the realtime bitmap and summary inodes, and fill in data if any.
637 xfs_bmap_free_t flist
;
639 xfs_bmbt_irec_t map
[XFS_BMAP_MAX_NMAP
];
640 xfs_extlen_t nsumblocks
;
646 struct fsxattr fsxattrs
;
647 struct xfs_trans_res tres
= {0};
650 * First, allocate the inodes.
652 tp
= libxfs_trans_alloc(mp
, 0);
653 i
= -libxfs_trans_reserve(tp
, &tres
, MKFS_BLOCKRES_INODE
, 0);
657 memset(&creds
, 0, sizeof(creds
));
658 memset(&fsxattrs
, 0, sizeof(fsxattrs
));
659 error
= -libxfs_inode_alloc(&tp
, NULL
, S_IFREG
, 1, 0,
660 &creds
, &fsxattrs
, &rbmip
);
662 fail(_("Realtime bitmap inode allocation failed"), error
);
665 * Do our thing with rbmip before allocating rsumip,
666 * because the next call to ialloc() may
667 * commit the transaction in which rbmip was allocated.
669 mp
->m_sb
.sb_rbmino
= rbmip
->i_ino
;
670 rbmip
->i_d
.di_size
= mp
->m_sb
.sb_rbmblocks
* mp
->m_sb
.sb_blocksize
;
671 rbmip
->i_d
.di_flags
= XFS_DIFLAG_NEWRTBM
;
672 *(__uint64_t
*)&VFS_I(rbmip
)->i_atime
= 0;
673 libxfs_trans_log_inode(tp
, rbmip
, XFS_ILOG_CORE
);
676 error
= -libxfs_inode_alloc(&tp
, NULL
, S_IFREG
, 1, 0,
677 &creds
, &fsxattrs
, &rsumip
);
679 fail(_("Realtime summary inode allocation failed"), error
);
681 mp
->m_sb
.sb_rsumino
= rsumip
->i_ino
;
682 rsumip
->i_d
.di_size
= mp
->m_rsumsize
;
683 libxfs_trans_log_inode(tp
, rsumip
, XFS_ILOG_CORE
);
685 libxfs_trans_commit(tp
);
686 mp
->m_rsumip
= rsumip
;
688 * Next, give the bitmap file some zero-filled blocks.
690 tp
= libxfs_trans_alloc(mp
, 0);
691 i
= -libxfs_trans_reserve(tp
, &tres
, mp
->m_sb
.sb_rbmblocks
+
692 (XFS_BM_MAXLEVELS(mp
, XFS_DATA_FORK
) - 1), 0);
696 libxfs_trans_ijoin(tp
, rbmip
, 0);
698 xfs_bmap_init(&flist
, &first
);
699 while (bno
< mp
->m_sb
.sb_rbmblocks
) {
700 nmap
= XFS_BMAP_MAX_NMAP
;
701 error
= -libxfs_bmapi_write(tp
, rbmip
, bno
,
702 (xfs_extlen_t
)(mp
->m_sb
.sb_rbmblocks
- bno
),
703 0, &first
, mp
->m_sb
.sb_rbmblocks
,
706 fail(_("Allocation of the realtime bitmap failed"),
709 for (i
= 0, ep
= map
; i
< nmap
; i
++, ep
++) {
710 libxfs_device_zero(mp
->m_ddev_targp
,
711 XFS_FSB_TO_DADDR(mp
, ep
->br_startblock
),
712 XFS_FSB_TO_BB(mp
, ep
->br_blockcount
));
713 bno
+= ep
->br_blockcount
;
717 error
= -libxfs_bmap_finish(&tp
, &flist
, rbmip
);
719 fail(_("Completion of the realtime bitmap failed"), error
);
721 libxfs_trans_commit(tp
);
724 * Give the summary file some zero-filled blocks.
726 tp
= libxfs_trans_alloc(mp
, 0);
727 nsumblocks
= mp
->m_rsumsize
>> mp
->m_sb
.sb_blocklog
;
728 i
= -libxfs_trans_reserve(tp
, &tres
, nsumblocks
+
729 (XFS_BM_MAXLEVELS(mp
, XFS_DATA_FORK
) - 1), 0);
732 libxfs_trans_ijoin(tp
, rsumip
, 0);
734 xfs_bmap_init(&flist
, &first
);
735 while (bno
< nsumblocks
) {
736 nmap
= XFS_BMAP_MAX_NMAP
;
737 error
= -libxfs_bmapi_write(tp
, rsumip
, bno
,
738 (xfs_extlen_t
)(nsumblocks
- bno
),
739 0, &first
, nsumblocks
,
742 fail(_("Allocation of the realtime summary failed"),
745 for (i
= 0, ep
= map
; i
< nmap
; i
++, ep
++) {
746 libxfs_device_zero(mp
->m_ddev_targp
,
747 XFS_FSB_TO_DADDR(mp
, ep
->br_startblock
),
748 XFS_FSB_TO_BB(mp
, ep
->br_blockcount
));
749 bno
+= ep
->br_blockcount
;
752 error
= -libxfs_bmap_finish(&tp
, &flist
, rsumip
);
754 fail(_("Completion of the realtime summary failed"), error
);
756 libxfs_trans_commit(tp
);
759 * Free the whole area using transactions.
760 * Do one transaction per bitmap block.
762 for (bno
= 0; bno
< mp
->m_sb
.sb_rextents
; bno
= ebno
) {
763 tp
= libxfs_trans_alloc(mp
, 0);
764 i
= -libxfs_trans_reserve(tp
, &tres
, 0, 0);
767 libxfs_trans_ijoin(tp
, rbmip
, 0);
768 xfs_bmap_init(&flist
, &first
);
769 ebno
= XFS_RTMIN(mp
->m_sb
.sb_rextents
,
770 bno
+ NBBY
* mp
->m_sb
.sb_blocksize
);
771 error
= -libxfs_rtfree_extent(tp
, bno
, (xfs_extlen_t
)(ebno
-bno
));
773 fail(_("Error initializing the realtime space"),
776 error
= -libxfs_bmap_finish(&tp
, &flist
, rbmip
);
778 fail(_("Error completing the realtime space"), error
);
780 libxfs_trans_commit(tp
);
790 if (fstat64(fd
, &stb
) < 0)
792 return (long)stb
.st_size
;