]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - mkfs/proto.c
1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
9 #include "xfs_multidisk.h"
12 * Prototypes for internal functions.
14 static char *getstr(char **pp
);
15 static void fail(char *msg
, int i
);
16 static struct xfs_trans
* getres(struct xfs_mount
*mp
, uint blocks
);
17 static void rsvfile(xfs_mount_t
*mp
, xfs_inode_t
*ip
, long long len
);
18 static int newfile(xfs_trans_t
*tp
, xfs_inode_t
*ip
, int symlink
, int logit
,
20 static char *newregfile(char **pp
, int *len
);
21 static void rtinit(xfs_mount_t
*mp
);
22 static long filesize(int fd
);
25 * Use this for block reservations needed for mkfs's conditions
26 * (basically no fragmentation).
28 #define MKFS_BLOCKRES_INODE \
29 ((uint)(mp->m_ialloc_blks + (mp->m_in_maxlevels - 1)))
30 #define MKFS_BLOCKRES(rb) \
31 ((uint)(MKFS_BLOCKRES_INODE + XFS_DA_NODE_MAXDEPTH + \
32 (XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1) + (rb)))
38 unsigned int sectsize
,
45 return cvtnum(blksize
, sectsize
, str
);
47 i
= strtoll(str
, &sp
, 0);
48 if (i
== 0 && sp
== str
)
51 return -1LL; /* trailing garbage */
60 static char dflt
[] = "d--755 0 0 $";
66 if ((fd
= open(fname
, O_RDONLY
)) < 0 || (size
= filesize(fd
)) < 0) {
67 fprintf(stderr
, _("%s: failed to open %s: %s\n"),
68 progname
, fname
, strerror(errno
));
72 buf
= malloc(size
+ 1);
73 if (read(fd
, buf
, size
) < size
) {
74 fprintf(stderr
, _("%s: read failed on %s: %s\n"),
75 progname
, fname
, strerror(errno
));
78 if (buf
[size
- 1] != '\n') {
79 fprintf(stderr
, _("%s: proto file %s premature EOF\n"),
85 * Skip past the stuff there for compatibility, a string and 2 numbers.
87 (void)getstr(&buf
); /* boot image name */
88 (void)getnum(getstr(&buf
), 0, 0, false); /* block count */
89 (void)getnum(getstr(&buf
), 0, 0, false); /* inode count */
105 fprintf(stderr
, "%s: %s [%d - %s]\n", progname
, msg
, i
, strerror(i
));
113 fail(_("cannot reserve space"), i
);
116 static struct xfs_trans
*
118 struct xfs_mount
*mp
,
121 struct xfs_trans
*tp
;
125 for (i
= 0, r
= MKFS_BLOCKRES(blocks
); r
>= blocks
; r
--) {
126 i
= -libxfs_trans_alloc_rollable(mp
, r
, &tp
);
158 while (c
!= ' ' && c
!= '\t' && c
!= '\n' && c
!= '\0')
166 fprintf(stderr
, _("%s: premature EOF in prototype file\n"),
182 error
= -libxfs_alloc_file_space(ip
, 0, llen
, 1, 0);
185 fail(_("error reserving space for a file"), error
);
190 * update the inode timestamp, mode, and prealloc flag bits
192 error
= -libxfs_trans_alloc_rollable(mp
, 0, &tp
);
194 fail(_("allocating transaction for a file"), error
);
195 libxfs_trans_ijoin(tp
, ip
, 0);
197 VFS_I(ip
)->i_mode
&= ~S_ISUID
;
200 * Note that we don't have to worry about mandatory
201 * file locking being disabled here because we only
202 * clear the S_ISGID bit if the Group execute bit is
203 * on, but if it was on then mandatory locking wouldn't
206 if (VFS_I(ip
)->i_mode
& S_IXGRP
)
207 VFS_I(ip
)->i_mode
&= ~S_ISGID
;
209 libxfs_trans_ichgtime(tp
, ip
, XFS_ICHGTIME_MOD
| XFS_ICHGTIME_CHG
);
211 ip
->i_d
.di_flags
|= XFS_DIFLAG_PREALLOC
;
213 libxfs_trans_log_inode(tp
, ip
, XFS_ILOG_CORE
);
214 error
= -libxfs_trans_commit(tp
);
216 fail(_("committing space for a file failed"), error
);
239 if (symlink
&& len
<= XFS_IFORK_DSIZE(ip
)) {
240 libxfs_init_local_fork(ip
, XFS_DATA_FORK
, buf
, len
);
241 ip
->i_d
.di_format
= XFS_DINODE_FMT_LOCAL
;
242 flags
= XFS_ILOG_DDATA
;
243 } else if (len
> 0) {
244 nb
= XFS_B_TO_FSB(mp
, len
);
246 error
= -libxfs_bmapi_write(tp
, ip
, 0, nb
, 0, nb
, &map
, &nmap
);
248 fail(_("error allocating space for a file"), error
);
252 _("%s: cannot allocate space for file\n"),
256 d
= XFS_FSB_TO_DADDR(mp
, map
.br_startblock
);
257 bp
= libxfs_trans_get_buf(logit
? tp
: NULL
, mp
->m_dev
, d
,
258 nb
<< mp
->m_blkbb_log
, 0);
259 memmove(bp
->b_addr
, buf
, len
);
260 if (len
< bp
->b_bcount
)
261 memset((char *)bp
->b_addr
+ len
, 0, bp
->b_bcount
- len
);
263 libxfs_trans_log_buf(tp
, bp
, 0, bp
->b_bcount
- 1);
265 libxfs_writebuf(bp
, LIBXFS_EXIT_ON_FAILURE
);
267 ip
->i_d
.di_size
= len
;
282 if ((fd
= open(fname
, O_RDONLY
)) < 0 || (size
= filesize(fd
)) < 0) {
283 fprintf(stderr
, _("%s: cannot open %s: %s\n"),
284 progname
, fname
, strerror(errno
));
287 if ((*len
= (int)size
)) {
289 if (read(fd
, buf
, size
) < size
) {
290 fprintf(stderr
, _("%s: read failed on %s: %s\n"),
291 progname
, fname
, strerror(errno
));
305 struct xfs_name
*name
,
311 rsv
= XFS_DIRENTER_SPACE_RES(mp
, name
->len
);
313 error
= -libxfs_dir_createname(tp
, pip
, name
, inum
, rsv
);
315 fail(_("directory createname error"), error
);
327 error
= -libxfs_dir_init(tp
, dp
, pdp
);
329 fail(_("directory create error"), error
);
336 struct fsxattr
*fsxp
,
341 #define IF_RESERVED 1
344 #define IF_DIRECTORY 4
365 struct xfs_name xname
;
367 memset(&creds
, 0, sizeof(creds
));
392 fprintf(stderr
, _("%s: bad format string %s\n"),
404 fprintf(stderr
, _("%s: bad format string %s\n"),
415 fprintf(stderr
, _("%s: bad format string %s\n"),
420 for (i
= 3; i
< 6; i
++) {
421 if (mstr
[i
] < '0' || mstr
[i
] > '7') {
422 fprintf(stderr
, _("%s: bad format string %s\n"),
426 val
= val
* 8 + mstr
[i
] - '0';
429 creds
.cr_uid
= (int)getnum(getstr(pp
), 0, 0, false);
430 creds
.cr_gid
= (int)getnum(getstr(pp
), 0, 0, false);
431 xname
.name
= (unsigned char *)name
;
432 xname
.len
= name
? strlen(name
) : 0;
434 flags
= XFS_ILOG_CORE
;
437 buf
= newregfile(pp
, &len
);
438 tp
= getres(mp
, XFS_B_TO_FSB(mp
, len
));
439 error
= -libxfs_inode_alloc(&tp
, pip
, mode
|S_IFREG
, 1, 0,
442 fail(_("Inode allocation failed"), error
);
443 flags
|= newfile(tp
, ip
, 0, 0, buf
, len
);
446 libxfs_trans_ijoin(tp
, pip
, 0);
447 xname
.type
= XFS_DIR3_FT_REG_FILE
;
448 newdirent(mp
, tp
, pip
, &xname
, ip
->i_ino
);
451 case IF_RESERVED
: /* pre-allocated space only */
453 llen
= getnum(value
, mp
->m_sb
.sb_blocksize
,
454 mp
->m_sb
.sb_sectsize
, true);
457 _("%s: Bad value %s for proto file %s\n"),
458 progname
, value
, name
);
461 tp
= getres(mp
, XFS_B_TO_FSB(mp
, llen
));
463 error
= -libxfs_inode_alloc(&tp
, pip
, mode
|S_IFREG
, 1, 0,
466 fail(_("Inode pre-allocation failed"), error
);
468 libxfs_trans_ijoin(tp
, pip
, 0);
470 xname
.type
= XFS_DIR3_FT_REG_FILE
;
471 newdirent(mp
, tp
, pip
, &xname
, ip
->i_ino
);
472 libxfs_trans_log_inode(tp
, ip
, flags
);
473 error
= -libxfs_trans_commit(tp
);
475 fail(_("Space preallocation failed."), error
);
476 rsvfile(mp
, ip
, llen
);
482 majdev
= getnum(getstr(pp
), 0, 0, false);
483 mindev
= getnum(getstr(pp
), 0, 0, false);
484 error
= -libxfs_inode_alloc(&tp
, pip
, mode
|S_IFBLK
, 1,
485 IRIX_MKDEV(majdev
, mindev
), &creds
, fsxp
, &ip
);
487 fail(_("Inode allocation failed"), error
);
489 libxfs_trans_ijoin(tp
, pip
, 0);
490 xname
.type
= XFS_DIR3_FT_BLKDEV
;
491 newdirent(mp
, tp
, pip
, &xname
, ip
->i_ino
);
492 flags
|= XFS_ILOG_DEV
;
497 majdev
= getnum(getstr(pp
), 0, 0, false);
498 mindev
= getnum(getstr(pp
), 0, 0, false);
499 error
= -libxfs_inode_alloc(&tp
, pip
, mode
|S_IFCHR
, 1,
500 IRIX_MKDEV(majdev
, mindev
), &creds
, fsxp
, &ip
);
502 fail(_("Inode allocation failed"), error
);
503 libxfs_trans_ijoin(tp
, pip
, 0);
504 xname
.type
= XFS_DIR3_FT_CHRDEV
;
505 newdirent(mp
, tp
, pip
, &xname
, ip
->i_ino
);
506 flags
|= XFS_ILOG_DEV
;
511 error
= -libxfs_inode_alloc(&tp
, pip
, mode
|S_IFIFO
, 1, 0,
514 fail(_("Inode allocation failed"), error
);
515 libxfs_trans_ijoin(tp
, pip
, 0);
516 xname
.type
= XFS_DIR3_FT_FIFO
;
517 newdirent(mp
, tp
, pip
, &xname
, ip
->i_ino
);
521 len
= (int)strlen(buf
);
522 tp
= getres(mp
, XFS_B_TO_FSB(mp
, len
));
523 error
= -libxfs_inode_alloc(&tp
, pip
, mode
|S_IFLNK
, 1, 0,
526 fail(_("Inode allocation failed"), error
);
527 flags
|= newfile(tp
, ip
, 1, 1, buf
, len
);
528 libxfs_trans_ijoin(tp
, pip
, 0);
529 xname
.type
= XFS_DIR3_FT_SYMLINK
;
530 newdirent(mp
, tp
, pip
, &xname
, ip
->i_ino
);
534 error
= -libxfs_inode_alloc(&tp
, pip
, mode
|S_IFDIR
, 1, 0,
537 fail(_("Inode allocation failed"), error
);
538 inc_nlink(VFS_I(ip
)); /* account for . */
541 mp
->m_sb
.sb_rootino
= ip
->i_ino
;
545 libxfs_trans_ijoin(tp
, pip
, 0);
546 xname
.type
= XFS_DIR3_FT_DIR
;
547 newdirent(mp
, tp
, pip
, &xname
, ip
->i_ino
);
548 inc_nlink(VFS_I(pip
));
549 libxfs_trans_log_inode(tp
, pip
, XFS_ILOG_CORE
);
551 newdirectory(mp
, tp
, ip
, pip
);
552 libxfs_trans_log_inode(tp
, ip
, flags
);
553 error
= -libxfs_trans_commit(tp
);
555 fail(_("Directory inode allocation failed."), error
);
557 * RT initialization. Do this here to ensure that
558 * the RT inodes get placed after the root inode.
567 if (strcmp(name
, "$") == 0)
569 parseproto(mp
, ip
, fsxp
, pp
, name
);
575 fail(_("Unknown format"), EINVAL
);
577 libxfs_trans_log_inode(tp
, ip
, flags
);
578 error
= -libxfs_trans_commit(tp
);
580 fail(_("Error encountered creating file from prototype file"),
592 parseproto(mp
, NULL
, fsx
, pp
, NULL
);
596 * Allocate the realtime bitmap and summary inodes, and fill in data if any.
607 xfs_bmbt_irec_t map
[XFS_BMAP_MAX_NMAP
];
608 xfs_extlen_t nsumblocks
;
615 struct fsxattr fsxattrs
;
618 * First, allocate the inodes.
620 i
= -libxfs_trans_alloc_rollable(mp
, MKFS_BLOCKRES_INODE
, &tp
);
624 memset(&creds
, 0, sizeof(creds
));
625 memset(&fsxattrs
, 0, sizeof(fsxattrs
));
626 error
= -libxfs_inode_alloc(&tp
, NULL
, S_IFREG
, 1, 0,
627 &creds
, &fsxattrs
, &rbmip
);
629 fail(_("Realtime bitmap inode allocation failed"), error
);
632 * Do our thing with rbmip before allocating rsumip,
633 * because the next call to ialloc() may
634 * commit the transaction in which rbmip was allocated.
636 mp
->m_sb
.sb_rbmino
= rbmip
->i_ino
;
637 rbmip
->i_d
.di_size
= mp
->m_sb
.sb_rbmblocks
* mp
->m_sb
.sb_blocksize
;
638 rbmip
->i_d
.di_flags
= XFS_DIFLAG_NEWRTBM
;
639 *(uint64_t *)&VFS_I(rbmip
)->i_atime
= 0;
640 libxfs_trans_log_inode(tp
, rbmip
, XFS_ILOG_CORE
);
643 error
= -libxfs_inode_alloc(&tp
, NULL
, S_IFREG
, 1, 0,
644 &creds
, &fsxattrs
, &rsumip
);
646 fail(_("Realtime summary inode allocation failed"), error
);
648 mp
->m_sb
.sb_rsumino
= rsumip
->i_ino
;
649 rsumip
->i_d
.di_size
= mp
->m_rsumsize
;
650 libxfs_trans_log_inode(tp
, rsumip
, XFS_ILOG_CORE
);
652 error
= -libxfs_trans_commit(tp
);
654 fail(_("Completion of the realtime summary inode failed"),
656 mp
->m_rsumip
= rsumip
;
658 * Next, give the bitmap file some zero-filled blocks.
660 blocks
= mp
->m_sb
.sb_rbmblocks
+
661 XFS_BM_MAXLEVELS(mp
, XFS_DATA_FORK
) - 1;
662 i
= -libxfs_trans_alloc_rollable(mp
, blocks
, &tp
);
666 libxfs_trans_ijoin(tp
, rbmip
, 0);
668 while (bno
< mp
->m_sb
.sb_rbmblocks
) {
669 nmap
= XFS_BMAP_MAX_NMAP
;
670 error
= -libxfs_bmapi_write(tp
, rbmip
, bno
,
671 (xfs_extlen_t
)(mp
->m_sb
.sb_rbmblocks
- bno
),
672 0, mp
->m_sb
.sb_rbmblocks
, map
, &nmap
);
674 fail(_("Allocation of the realtime bitmap failed"),
677 for (i
= 0, ep
= map
; i
< nmap
; i
++, ep
++) {
678 libxfs_device_zero(mp
->m_ddev_targp
,
679 XFS_FSB_TO_DADDR(mp
, ep
->br_startblock
),
680 XFS_FSB_TO_BB(mp
, ep
->br_blockcount
));
681 bno
+= ep
->br_blockcount
;
685 error
= -libxfs_trans_commit(tp
);
687 fail(_("Block allocation of the realtime bitmap inode failed"),
691 * Give the summary file some zero-filled blocks.
693 nsumblocks
= mp
->m_rsumsize
>> mp
->m_sb
.sb_blocklog
;
694 blocks
= nsumblocks
+ XFS_BM_MAXLEVELS(mp
, XFS_DATA_FORK
) - 1;
695 i
= -libxfs_trans_alloc_rollable(mp
, blocks
, &tp
);
698 libxfs_trans_ijoin(tp
, rsumip
, 0);
700 while (bno
< nsumblocks
) {
701 nmap
= XFS_BMAP_MAX_NMAP
;
702 error
= -libxfs_bmapi_write(tp
, rsumip
, bno
,
703 (xfs_extlen_t
)(nsumblocks
- bno
),
704 0, nsumblocks
, map
, &nmap
);
706 fail(_("Allocation of the realtime summary 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
;
716 error
= -libxfs_trans_commit(tp
);
718 fail(_("Block allocation of the realtime summary inode failed"),
722 * Free the whole area using transactions.
723 * Do one transaction per bitmap block.
725 for (bno
= 0; bno
< mp
->m_sb
.sb_rextents
; bno
= ebno
) {
726 i
= -libxfs_trans_alloc(mp
, &M_RES(mp
)->tr_itruncate
,
730 libxfs_trans_ijoin(tp
, rbmip
, 0);
731 ebno
= XFS_RTMIN(mp
->m_sb
.sb_rextents
,
732 bno
+ NBBY
* mp
->m_sb
.sb_blocksize
);
733 error
= -libxfs_rtfree_extent(tp
, bno
, (xfs_extlen_t
)(ebno
-bno
));
735 fail(_("Error initializing the realtime space"),
738 error
= -libxfs_trans_commit(tp
);
740 fail(_("Initialization of the realtime space failed"),
751 if (fstat(fd
, &stb
) < 0)
753 return (long)stb
.st_size
;