1 /* $NetBSD: main.c,v 1.10 2011/08/10 11:31:49 uch Exp $ */
4 * Copyright (c) 2011 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #if HAVE_NBTOOL_CONFIG_H
33 #include "nbtool_config.h"
36 #include <sys/cdefs.h>
38 __RCSID("$NetBSD: main.c,v 1.10 2011/08/10 11:31:49 uch Exp $");
41 #include <sys/param.h>
49 #include "v7fs_impl.h"
50 #include "v7fs_endian.h"
51 #include "v7fs_superblock.h"
52 #include "v7fs_inode.h"
53 #include "v7fs_datablock.h" /*v7fs_datablock_expand/last */
54 #include "newfs_v7fs.h"
55 #include "progress.h" /*../sbin/fsck */
57 #define VPRINTF(lv, fmt, args...) { if (v7fs_newfs_verbose >= lv) \
58 printf(fmt, ##args); }
61 determine_ilist_size(v7fs_daddr_t volume_size
, int32_t files
)
63 v7fs_daddr_t ilist_size
;
66 ilist_size
= howmany(files
, V7FS_INODE_PER_BLOCK
);
68 ilist_size
= volume_size
/ 25; /* 4% */
69 if (ilist_size
> (v7fs_daddr_t
)V7FS_ILISTBLK_MAX
)
70 ilist_size
= V7FS_ILISTBLK_MAX
;
76 partition_check(struct v7fs_self
*fs
)
78 struct v7fs_superblock
*sb
= &fs
->superblock
;
81 if ((error
= v7fs_superblock_load(fs
))) {
82 if (error
!= EINVAL
) {
83 /* Invalid superblock information is OK. */
84 warnx("Can't read superblock sector.");
88 if ((error
= v7fs_superblock_writeback(fs
))) {
90 warnx("Overwriting disk label? ");
92 warnx("Can't write superblock sector.");
99 make_root(struct v7fs_self
*fs
)
101 struct v7fs_inode inode
;
102 struct v7fs_dirent
*dir
;
105 /* INO 1 badblk (don't used) */
106 memset(&inode
, 0, sizeof(inode
));
107 inode
.inode_number
= 1;
108 inode
.mode
= V7FS_IFREG
; /* V7 manner */
109 v7fs_inode_writeback(fs
, &inode
);
113 if ((error
= v7fs_inode_allocate(fs
, &ino
))) {
115 warn("Can't allocate / inode");
119 memset(&inode
, 0, sizeof(inode
));
120 inode
.inode_number
= ino
;
121 inode
.mode
= 0777 | V7FS_IFDIR
;
124 inode
.nlink
= 2; /* . + .. */
125 inode
.atime
= inode
.mtime
= inode
.ctime
= time(0);
128 v7fs_datablock_expand(fs
, &inode
, sizeof(*dir
) * 2);
129 v7fs_daddr_t blk
= inode
.addr
[0];
131 if (!(buf
= scratch_read(fs
, blk
))) {
132 v7fs_inode_deallocate(fs
, ino
);
134 warn("Can't read / dirent.");
137 dir
= (struct v7fs_dirent
*)buf
; /*disk endian */
139 strcpy(dir
[0].name
, ".");
140 dir
[0].inode_number
= V7FS_VAL16(fs
, ino
);
141 strcpy(dir
[1].name
, "..");
142 dir
[1].inode_number
= V7FS_VAL16(fs
, ino
);
143 if (!fs
->io
.write(fs
->io
.cookie
, buf
, blk
)) {/*writeback */
144 scratch_free(fs
, buf
);
146 warn("Can't write / dirent.");
149 scratch_free(fs
, buf
);
150 v7fs_inode_writeback(fs
, &inode
);
151 if ((error
= v7fs_superblock_writeback(fs
))) {
153 warnx("Can't write superblock.");
160 make_freeblocklist(struct v7fs_self
*fs
, v7fs_daddr_t listblk
, uint8_t *buf
)
162 uint32_t (*val32
)(uint32_t) = fs
->val
.conv32
;
163 uint16_t (*val16
)(uint16_t) = fs
->val
.conv16
;
164 struct v7fs_freeblock
*fb
= (struct v7fs_freeblock
*)buf
;
167 memset(buf
, 0, V7FS_BSIZE
);
169 for (i
= V7FS_MAX_FREEBLOCK
- 1, j
= listblk
+ 1, k
= 0; i
>= 0;
172 if (j
== (int32_t)fs
->superblock
.volume_size
)
174 VPRINTF(4, "\nlast freeblock #%d\n",
175 (*val32
)(fb
->freeblock
[i
+ 1]));
177 memmove(fb
->freeblock
+ 1, fb
->freeblock
+ i
+ 1, k
*
178 sizeof(v7fs_daddr_t
));
179 fb
->freeblock
[0] = 0; /* Terminate link; */
180 fb
->nfreeblock
= (*val16
)(k
+ 1);
181 VPRINTF(4, "last freeblock contains #%d\n",
182 (*val16
)(fb
->nfreeblock
));
183 fs
->io
.write(fs
->io
.cookie
, buf
, listblk
);
186 fb
->freeblock
[i
] = (*val32
)(j
);
188 fb
->nfreeblock
= (*val16
)(k
);
190 if (!fs
->io
.write(fs
->io
.cookie
, buf
, listblk
)) {
192 warn("blk=%ld", (long)listblk
);
196 /* Return next link block */
197 return (*val32
)(fb
->freeblock
[0]);
201 make_filesystem(struct v7fs_self
*fs
, v7fs_daddr_t volume_size
,
202 v7fs_daddr_t ilist_size
)
204 struct v7fs_superblock
*sb
;
206 uint8_t buf
[V7FS_BSIZE
];
210 /* Setup ilist. (ilist must be zero filled. becuase of they are free) */
211 VPRINTF(4, "Zero clear ilist.\n");
212 progress(&(struct progress_arg
){ .label
= "zero ilist", .tick
=
213 ilist_size
/ PROGRESS_BAR_GRANULE
});
214 memset(buf
, 0, sizeof buf
);
215 for (i
= V7FS_ILIST_SECTOR
; i
< (int32_t)ilist_size
; i
++) {
216 fs
->io
.write(fs
->io
.cookie
, buf
, i
);
219 #ifndef HAVE_NBTOOL_CONFIG_H
224 /* Construct superblock */
225 sb
= &fs
->superblock
;
226 sb
->volume_size
= volume_size
;
227 sb
->datablock_start_sector
= ilist_size
+ V7FS_ILIST_SECTOR
;
228 sb
->update_time
= time(NULL
);
230 /* fill free inode cache. */
231 VPRINTF(4, "Setup inode cache.\n");
232 sb
->nfreeinode
= V7FS_MAX_FREEINODE
;
233 for (i
= V7FS_MAX_FREEINODE
- 1, j
= V7FS_ROOT_INODE
; i
>= 0; i
--, j
++)
234 sb
->freeinode
[i
] = j
;
235 sb
->total_freeinode
= ilist_size
* V7FS_INODE_PER_BLOCK
- 1;
237 /* fill free block cache. */
238 VPRINTF(4, "Setup free block cache.\n");
239 sb
->nfreeblock
= V7FS_MAX_FREEBLOCK
;
240 for (i
= V7FS_MAX_FREEBLOCK
- 1, j
= sb
->datablock_start_sector
; i
>= 0;
242 sb
->freeblock
[i
] = j
;
244 sb
->total_freeblock
= volume_size
- sb
->datablock_start_sector
;
246 /* Write superblock. */
248 if ((error
= v7fs_superblock_writeback(fs
))) {
250 warn("Can't write back superblock.");
254 /* Construct freeblock list */
255 VPRINTF(4, "Setup whole freeblock list.\n");
256 progress(&(struct progress_arg
){ .label
= "freeblock list", .tick
=
257 (volume_size
- sb
->datablock_start_sector
) / PROGRESS_BAR_GRANULE
});
258 blk
= sb
->freeblock
[0];
259 while ((blk
= make_freeblocklist(fs
, blk
, buf
)))
261 #ifndef HAVE_NBTOOL_CONFIG_H
265 VPRINTF(4, "done.\n");
271 v7fs_newfs(const struct v7fs_mount_device
*mount
, int32_t maxfile
)
273 struct v7fs_self
*fs
;
274 v7fs_daddr_t ilist_size
;
276 v7fs_daddr_t volume_size
= mount
->sectors
;
278 /* Check and determine ilistblock, datablock size. */
279 if (volume_size
> V7FS_DADDR_MAX
+ 1) {
280 warnx("volume size %d over v7fs limit %d. truncated.",
281 volume_size
, V7FS_DADDR_MAX
+ 1);
282 volume_size
= V7FS_DADDR_MAX
+ 1;
285 ilist_size
= determine_ilist_size(volume_size
, maxfile
);
287 VPRINTF(1, "volume size=%d, ilist size=%d, endian=%d, NAME_MAX=%d\n",
288 volume_size
, ilist_size
, mount
->endian
, V7FS_NAME_MAX
);
291 if ((error
= v7fs_io_init(&fs
, mount
, V7FS_BSIZE
))) {
293 warn("I/O setup failed.");
296 fs
->endian
= mount
->endian
;
297 v7fs_endian_init(fs
);
299 if ((error
= partition_check(fs
))) {
303 /* Construct filesystem. */
304 if ((error
= make_filesystem(fs
, volume_size
, ilist_size
))) {
309 if ((error
= make_root(fs
))) {