]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - mkfs/proto.c
2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
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.
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.
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.
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.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
37 * Prototypes for internal functions.
39 extern long long cvtnum(int blocksize
, char *s
);
40 extern void parseproto(xfs_mount_t
*mp
, xfs_inode_t
*pip
, char **pp
,
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
);
54 * Use this for block reservations needed for mkfs's conditions
55 * (basically no fragmentation).
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)))
69 static char dflt
[] = "d--755 0 0 $";
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
));
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
));
86 if (buf
[size
- 1] != '\n') {
87 fprintf(stderr
, "%s: proto file %s premature EOF\n",
93 * Skip past the stuff there for compatibility, a string and 2 numbers.
95 (void)getstr(&buf
); /* boot image name */
96 (void)getnum(&buf
); /* block count */
97 (void)getnum(&buf
); /* inode count */
116 fprintf(stderr
, "%s: %s %d\n", progname
, msg
, i
);
131 for (i
= 0, r
= MKFS_BLOCKRES(blocks
); r
>= blocks
; r
--) {
132 i
= libxfs_trans_reserve(tp
, r
, 0, 0, 0, 0);
163 while (c
!= ' ' && c
!= '\t' && c
!= '\n' && c
!= '\0')
171 fprintf(stderr
, "%s: premature EOF in prototype file\n",
187 error
= libxfs_alloc_file_space(ip
, 0, llen
, 1, 0);
190 fail("error reserving space for a file", error
);
195 * update the inode timestamp, mode, and prealloc flag bits
197 tp
= libxfs_trans_alloc(mp
, 0);
199 libxfs_trans_ijoin(tp
, ip
, 0);
200 libxfs_trans_ihold(tp
, ip
);
202 ip
->i_d
.di_mode
&= ~ISUID
;
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
211 if (ip
->i_d
.di_mode
& (IEXEC
>> 3))
212 ip
->i_d
.di_mode
&= ~ISGID
;
214 libxfs_ichgtime(ip
, XFS_ICHGTIME_MOD
| XFS_ICHGTIME_CHG
);
216 ip
->i_d
.di_flags
|= XFS_DIFLAG_PREALLOC
;
218 libxfs_trans_log_inode(tp
, ip
, XFS_ILOG_CORE
);
219 libxfs_trans_commit(tp
, 0, NULL
);
226 xfs_bmap_free_t
*flist
,
227 xfs_fsblock_t
*first
,
244 if (dolocal
&& len
<= XFS_IFORK_DSIZE(ip
)) {
245 libxfs_idata_realloc(ip
, len
, XFS_DATA_FORK
);
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
);
256 error
= libxfs_bmapi(tp
, ip
, 0, nb
, XFS_BMAPI_WRITE
, first
, nb
,
259 fail("error allocating space for a file", error
);
262 fprintf(stderr
, "%s: cannot allocate space for file\n",
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
);
273 libxfs_trans_log_buf(tp
, bp
, 0, XFS_BUF_COUNT(bp
) - 1);
275 libxfs_writebuf(bp
, 1);
277 ip
->i_d
.di_size
= len
;
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
));
297 if ((*len
= (int)size
)) {
299 if (read(fd
, buf
, size
) < size
) {
300 fprintf(stderr
, "%s: read failed on %s: %s\n",
301 progname
, fname
, strerror(errno
));
318 xfs_fsblock_t
*first
,
319 xfs_bmap_free_t
*flist
,
324 if (XFS_SB_VERSION_HASDIRV2(&mp
->m_sb
))
325 error
= libxfs_dir2_createname(tp
, pip
, name
, namelen
,
326 inum
, first
, flist
, total
);
328 error
= libxfs_dir_createname(tp
, pip
, name
, namelen
,
329 inum
, first
, flist
, total
);
331 fail("directory createname error", error
);
343 if (XFS_SB_VERSION_HASDIRV2(&mp
->m_sb
))
344 error
= libxfs_dir2_init(tp
, dp
, pdp
);
346 error
= libxfs_dir_init(tp
, dp
, pdp
);
348 fail("directory create error", error
);
359 #define IF_RESERVED 1
362 #define IF_DIRECTORY 4
371 xfs_bmap_free_t flist
;
387 bzero(&creds
, sizeof(creds
));
412 fprintf(stderr
, "%s: bad format string %s\n", progname
, mstr
);
423 fprintf(stderr
, "%s: bad format string %s\n", progname
, mstr
);
433 fprintf(stderr
, "%s: bad format string %s\n", progname
, mstr
);
437 for (i
= 3; i
< 6; i
++) {
438 if (mstr
[i
] < '0' || mstr
[i
] > '7') {
439 fprintf(stderr
, "%s: bad format string %s\n",
443 val
= val
* 8 + mstr
[i
] - '0';
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
);
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
);
458 fail("Inode allocation failed", error
);
459 flags
|= newfile(tp
, ip
, &flist
, &first
, 0, 0, buf
, len
);
462 libxfs_trans_ijoin(tp
, pip
, 0);
464 newdirent(mp
, tp
, pip
, name
, i
, ip
->i_ino
, &first
, &flist
, 1);
465 libxfs_trans_ihold(tp
, pip
);
468 case IF_RESERVED
: /* pre-allocated space only */
470 llen
= cvtnum(mp
->m_sb
.sb_blocksize
, value
);
471 getres(tp
, XFS_B_TO_FSB(mp
, llen
));
473 error
= libxfs_inode_alloc(&tp
, pip
, mode
|IFREG
, 1,
474 mp
->m_dev
, &creds
, &ip
);
476 fail("Inode pre-allocation failed", error
);
478 libxfs_trans_ijoin(tp
, pip
, 0);
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
);
485 error
= libxfs_bmap_finish(&tp
, &flist
, first
, &committed
);
487 fail("Pre-allocated file creation failed", error
);
488 libxfs_trans_commit(tp
, 0, NULL
);
489 rsvfile(mp
, ip
, llen
);
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
);
499 fail("Inode allocation failed", error
);
501 libxfs_trans_ijoin(tp
, pip
, 0);
503 newdirent(mp
, tp
, pip
, name
, i
, ip
->i_ino
, &first
, &flist
, 1);
504 libxfs_trans_ihold(tp
, pip
);
505 flags
|= XFS_ILOG_DEV
;
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
);
515 fail("Inode allocation failed", error
);
516 libxfs_trans_ijoin(tp
, pip
, 0);
518 newdirent(mp
, tp
, pip
, name
, i
, ip
->i_ino
, &first
, &flist
, 1);
519 libxfs_trans_ihold(tp
, pip
);
520 flags
|= XFS_ILOG_DEV
;
525 error
= libxfs_inode_alloc(&tp
, pip
, mode
|IFIFO
, 1,
526 mp
->m_dev
, &creds
, &ip
);
528 fail("Inode allocation failed", error
);
529 libxfs_trans_ijoin(tp
, pip
, 0);
531 newdirent(mp
, tp
, pip
, name
, i
, ip
->i_ino
, &first
, &flist
, 1);
532 libxfs_trans_ihold(tp
, pip
);
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
);
541 fail("Inode allocation failed", error
);
542 flags
|= newfile(tp
, ip
, &flist
, &first
, 1, 1, buf
, len
);
543 libxfs_trans_ijoin(tp
, pip
, 0);
545 newdirent(mp
, tp
, pip
, name
, i
, ip
->i_ino
, &first
, &flist
, 1);
546 libxfs_trans_ihold(tp
, pip
);
550 error
= libxfs_inode_alloc(&tp
, pip
, mode
|IFDIR
, 1,
551 mp
->m_dev
, &creds
, &ip
);
553 fail("Inode allocation failed", error
);
554 ip
->i_d
.di_nlink
++; /* account for . */
557 mp
->m_sb
.sb_rootino
= ip
->i_ino
;
558 libxfs_mod_sb(tp
, XFS_SB_ROOTINO
);
562 libxfs_trans_ijoin(tp
, pip
, 0);
564 newdirent(mp
, tp
, pip
, name
, i
, ip
->i_ino
,
567 libxfs_trans_ihold(tp
, pip
);
568 libxfs_trans_log_inode(tp
, pip
, XFS_ILOG_CORE
);
570 newdirectory(mp
, tp
, ip
, pip
);
571 libxfs_trans_log_inode(tp
, ip
, flags
);
572 error
= libxfs_bmap_finish(&tp
, &flist
, first
, &committed
);
574 fail("Directory creation failed", error
);
575 libxfs_trans_ihold(tp
, ip
);
576 libxfs_trans_commit(tp
, 0, NULL
);
578 * RT initialization. Do this here to ensure that
579 * the RT inodes get placed after the root inode.
586 if (strcmp(name
, "$") == 0)
588 parseproto(mp
, ip
, pp
, name
);
593 libxfs_trans_log_inode(tp
, ip
, flags
);
594 error
= libxfs_bmap_finish(&tp
, &flist
, first
, &committed
);
596 fail("Error encountered creating file from prototype", error
);
598 libxfs_trans_commit(tp
, 0, NULL
);
602 * Allocate the realtime bitmap and summary inodes, and fill in data if any.
614 xfs_bmap_free_t flist
;
616 xfs_bmbt_irec_t map
[XFS_BMAP_MAX_NMAP
];
617 xfs_extlen_t nsumblocks
;
625 * First, allocate the inodes.
627 tp
= libxfs_trans_alloc(mp
, 0);
628 if ((i
= libxfs_trans_reserve(tp
, MKFS_BLOCKRES_INODE
, 0, 0, 0, 0)))
630 bzero(&creds
, sizeof(creds
));
631 error
= libxfs_inode_alloc(&tp
, mp
->m_rootip
, IFREG
, 1,
632 mp
->m_dev
, &creds
, &rbmip
);
634 fail("Realtime bitmap inode allocation failed", error
);
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.
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
);
649 error
= libxfs_inode_alloc(&tp
, mp
->m_rootip
, IFREG
, 1,
650 mp
->m_dev
, &creds
, &rsumip
);
652 fail("Realtime bitmap inode allocation failed", error
);
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
;
662 * Next, give the bitmap file some zero-filled blocks.
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)))
668 libxfs_trans_ijoin(tp
, rbmip
, 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
,
678 fail("Allocation of the realtime bitmap failed", error
);
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
;
688 error
= libxfs_bmap_finish(&tp
, &flist
, first
, &committed
);
690 fail("Allocation of the realtime bitmap failed", error
);
692 libxfs_trans_commit(tp
, 0, NULL
);
694 * Give the summary file some zero-filled blocks.
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),
702 libxfs_trans_ijoin(tp
, rsumip
, 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
,
712 fail("Allocation of the realtime bitmap failed", error
);
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
;
721 error
= libxfs_bmap_finish(&tp
, &flist
, first
, &committed
);
723 fail("Allocation of the realtime bitmap failed", error
);
725 libxfs_trans_commit(tp
, 0, NULL
);
727 * Free the whole area using transactions.
728 * Do one transaction per bitmap block.
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)))
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
));
739 fail("Error initializing the realtime bitmap", error
);
741 error
= libxfs_bmap_finish(&tp
, &flist
, first
, &committed
);
743 fail("Error initializing the realtime bitmap", error
);
745 libxfs_trans_commit(tp
, 0, NULL
);
753 fprintf(stderr
, "%s: ran out of disk space!\n", progname
);
764 if (fstat64(fd
, &stb
) < 0)
766 return (long)stb
.st_size
;