xref: /minix3/sys/fs/v7fs/v7fs_superblock.c (revision 9f988b79349f9b89ecc822458c30ec8897558560)
1*9f988b79SJean-Baptiste Boric /*	$NetBSD: v7fs_superblock.c,v 1.2 2011/07/18 21:51:49 apb Exp $	*/
2*9f988b79SJean-Baptiste Boric 
3*9f988b79SJean-Baptiste Boric /*-
4*9f988b79SJean-Baptiste Boric  * Copyright (c) 2011 The NetBSD Foundation, Inc.
5*9f988b79SJean-Baptiste Boric  * All rights reserved.
6*9f988b79SJean-Baptiste Boric  *
7*9f988b79SJean-Baptiste Boric  * This code is derived from software contributed to The NetBSD Foundation
8*9f988b79SJean-Baptiste Boric  * by UCHIYAMA Yasushi.
9*9f988b79SJean-Baptiste Boric  *
10*9f988b79SJean-Baptiste Boric  * Redistribution and use in source and binary forms, with or without
11*9f988b79SJean-Baptiste Boric  * modification, are permitted provided that the following conditions
12*9f988b79SJean-Baptiste Boric  * are met:
13*9f988b79SJean-Baptiste Boric  * 1. Redistributions of source code must retain the above copyright
14*9f988b79SJean-Baptiste Boric  *    notice, this list of conditions and the following disclaimer.
15*9f988b79SJean-Baptiste Boric  * 2. Redistributions in binary form must reproduce the above copyright
16*9f988b79SJean-Baptiste Boric  *    notice, this list of conditions and the following disclaimer in the
17*9f988b79SJean-Baptiste Boric  *    documentation and/or other materials provided with the distribution.
18*9f988b79SJean-Baptiste Boric  *
19*9f988b79SJean-Baptiste Boric  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20*9f988b79SJean-Baptiste Boric  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21*9f988b79SJean-Baptiste Boric  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22*9f988b79SJean-Baptiste Boric  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23*9f988b79SJean-Baptiste Boric  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24*9f988b79SJean-Baptiste Boric  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25*9f988b79SJean-Baptiste Boric  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26*9f988b79SJean-Baptiste Boric  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27*9f988b79SJean-Baptiste Boric  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28*9f988b79SJean-Baptiste Boric  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29*9f988b79SJean-Baptiste Boric  * POSSIBILITY OF SUCH DAMAGE.
30*9f988b79SJean-Baptiste Boric  */
31*9f988b79SJean-Baptiste Boric 
32*9f988b79SJean-Baptiste Boric #if HAVE_NBTOOL_CONFIG_H
33*9f988b79SJean-Baptiste Boric #include "nbtool_config.h"
34*9f988b79SJean-Baptiste Boric #endif
35*9f988b79SJean-Baptiste Boric 
36*9f988b79SJean-Baptiste Boric #include <sys/cdefs.h>
37*9f988b79SJean-Baptiste Boric __KERNEL_RCSID(0, "$NetBSD: v7fs_superblock.c,v 1.2 2011/07/18 21:51:49 apb Exp $");
38*9f988b79SJean-Baptiste Boric #if defined _KERNEL_OPT
39*9f988b79SJean-Baptiste Boric #include "opt_v7fs.h"
40*9f988b79SJean-Baptiste Boric #endif
41*9f988b79SJean-Baptiste Boric 
42*9f988b79SJean-Baptiste Boric #ifdef _KERNEL
43*9f988b79SJean-Baptiste Boric #include <sys/systm.h>
44*9f988b79SJean-Baptiste Boric #include <sys/param.h>	/* errno */
45*9f988b79SJean-Baptiste Boric #else
46*9f988b79SJean-Baptiste Boric #include <stdio.h>
47*9f988b79SJean-Baptiste Boric #include <string.h>
48*9f988b79SJean-Baptiste Boric #include <errno.h>
49*9f988b79SJean-Baptiste Boric #endif
50*9f988b79SJean-Baptiste Boric 
51*9f988b79SJean-Baptiste Boric #include "v7fs.h"
52*9f988b79SJean-Baptiste Boric #include "v7fs_impl.h"
53*9f988b79SJean-Baptiste Boric #include "v7fs_endian.h"
54*9f988b79SJean-Baptiste Boric #include "v7fs_superblock.h"
55*9f988b79SJean-Baptiste Boric #include "v7fs_inode.h"
56*9f988b79SJean-Baptiste Boric #include "v7fs_datablock.h"
57*9f988b79SJean-Baptiste Boric 
58*9f988b79SJean-Baptiste Boric #ifdef V7FS_SUPERBLOCK_DEBUG
59*9f988b79SJean-Baptiste Boric #define	DPRINTF(fmt, args...)	printf("%s: " fmt, __func__, ##args)
60*9f988b79SJean-Baptiste Boric #define	DPRINTF_(fmt, args...)	printf(fmt, ##args)
61*9f988b79SJean-Baptiste Boric #else
62*9f988b79SJean-Baptiste Boric #define	DPRINTF(fmt, args...)	((void)0)
63*9f988b79SJean-Baptiste Boric #define	DPRINTF_(fmt, args...)	((void)0)
64*9f988b79SJean-Baptiste Boric #endif
65*9f988b79SJean-Baptiste Boric 
66*9f988b79SJean-Baptiste Boric static void v7fs_superblock_endian_convert(struct v7fs_self *,
67*9f988b79SJean-Baptiste Boric     struct v7fs_superblock *, struct v7fs_superblock *);
68*9f988b79SJean-Baptiste Boric static int v7fs_superblock_sanity(struct v7fs_self *);
69*9f988b79SJean-Baptiste Boric 
70*9f988b79SJean-Baptiste Boric /* Load superblock from disk. */
71*9f988b79SJean-Baptiste Boric int
v7fs_superblock_load(struct v7fs_self * fs)72*9f988b79SJean-Baptiste Boric v7fs_superblock_load(struct v7fs_self *fs)
73*9f988b79SJean-Baptiste Boric {
74*9f988b79SJean-Baptiste Boric 	struct v7fs_superblock *disksb;
75*9f988b79SJean-Baptiste Boric 	void *buf;
76*9f988b79SJean-Baptiste Boric 	int error;
77*9f988b79SJean-Baptiste Boric 
78*9f988b79SJean-Baptiste Boric 	if (!(buf = scratch_read(fs, V7FS_SUPERBLOCK_SECTOR)))
79*9f988b79SJean-Baptiste Boric 		return EIO;
80*9f988b79SJean-Baptiste Boric 	disksb = (struct v7fs_superblock *)buf;
81*9f988b79SJean-Baptiste Boric 	v7fs_superblock_endian_convert(fs, &fs->superblock, disksb);
82*9f988b79SJean-Baptiste Boric 	scratch_free(fs, buf);
83*9f988b79SJean-Baptiste Boric 
84*9f988b79SJean-Baptiste Boric 	if ((error = v7fs_superblock_sanity(fs)))
85*9f988b79SJean-Baptiste Boric 		return error;
86*9f988b79SJean-Baptiste Boric 
87*9f988b79SJean-Baptiste Boric 	return 0;
88*9f988b79SJean-Baptiste Boric }
89*9f988b79SJean-Baptiste Boric 
90*9f988b79SJean-Baptiste Boric /* Writeback superblock to disk. */
91*9f988b79SJean-Baptiste Boric int
v7fs_superblock_writeback(struct v7fs_self * fs)92*9f988b79SJean-Baptiste Boric v7fs_superblock_writeback(struct v7fs_self *fs)
93*9f988b79SJean-Baptiste Boric {
94*9f988b79SJean-Baptiste Boric 	struct v7fs_superblock *memsb = &fs->superblock;
95*9f988b79SJean-Baptiste Boric 	struct v7fs_superblock *disksb;
96*9f988b79SJean-Baptiste Boric 	void *buf;
97*9f988b79SJean-Baptiste Boric 	int error = 0;
98*9f988b79SJean-Baptiste Boric 
99*9f988b79SJean-Baptiste Boric 	if (!memsb->modified)
100*9f988b79SJean-Baptiste Boric 		return 0;
101*9f988b79SJean-Baptiste Boric 
102*9f988b79SJean-Baptiste Boric 	if (!(buf = scratch_read(fs, V7FS_SUPERBLOCK_SECTOR)))
103*9f988b79SJean-Baptiste Boric 		return EIO;
104*9f988b79SJean-Baptiste Boric 	disksb = (struct v7fs_superblock *)buf;
105*9f988b79SJean-Baptiste Boric 	v7fs_superblock_endian_convert(fs, disksb, memsb);
106*9f988b79SJean-Baptiste Boric 	if (!fs->io.write(fs->io.cookie, buf, V7FS_SUPERBLOCK_SECTOR))
107*9f988b79SJean-Baptiste Boric 		error = EIO;
108*9f988b79SJean-Baptiste Boric 	scratch_free(fs, buf);
109*9f988b79SJean-Baptiste Boric 
110*9f988b79SJean-Baptiste Boric 	memsb->modified = 0;
111*9f988b79SJean-Baptiste Boric 	DPRINTF("done. %d\n", error);
112*9f988b79SJean-Baptiste Boric 
113*9f988b79SJean-Baptiste Boric 	return error;
114*9f988b79SJean-Baptiste Boric }
115*9f988b79SJean-Baptiste Boric 
116*9f988b79SJean-Baptiste Boric /* Check endian mismatch. */
117*9f988b79SJean-Baptiste Boric static int
v7fs_superblock_sanity(struct v7fs_self * fs)118*9f988b79SJean-Baptiste Boric v7fs_superblock_sanity(struct v7fs_self *fs)
119*9f988b79SJean-Baptiste Boric {
120*9f988b79SJean-Baptiste Boric 	const struct v7fs_superblock *sb = &fs->superblock;
121*9f988b79SJean-Baptiste Boric 	void *buf = 0;
122*9f988b79SJean-Baptiste Boric 
123*9f988b79SJean-Baptiste Boric 	if ((sb->volume_size < 128) || /* smaller than 64KB. */
124*9f988b79SJean-Baptiste Boric 	    (sb->datablock_start_sector > sb->volume_size) ||
125*9f988b79SJean-Baptiste Boric 	    (sb->nfreeinode > V7FS_MAX_FREEINODE) ||
126*9f988b79SJean-Baptiste Boric 	    (sb->nfreeblock > V7FS_MAX_FREEBLOCK) ||
127*9f988b79SJean-Baptiste Boric 	    (sb->update_time < 0) ||
128*9f988b79SJean-Baptiste Boric 	    (sb->total_freeblock > sb->volume_size) ||
129*9f988b79SJean-Baptiste Boric 	    ((sb->nfreeinode == 0) && (sb->nfreeblock == 0) &&
130*9f988b79SJean-Baptiste Boric 		(sb->total_freeblock == 0) && (sb->total_freeinode == 0)) ||
131*9f988b79SJean-Baptiste Boric 	    (!(buf = scratch_read(fs, sb->volume_size - 1)))) {
132*9f988b79SJean-Baptiste Boric 		DPRINTF("invalid super block.\n");
133*9f988b79SJean-Baptiste Boric 		return EINVAL;
134*9f988b79SJean-Baptiste Boric 	}
135*9f988b79SJean-Baptiste Boric 	if (buf)
136*9f988b79SJean-Baptiste Boric 		scratch_free(fs, buf);
137*9f988b79SJean-Baptiste Boric 
138*9f988b79SJean-Baptiste Boric 	return 0;
139*9f988b79SJean-Baptiste Boric }
140*9f988b79SJean-Baptiste Boric 
141*9f988b79SJean-Baptiste Boric /* Fill free block to superblock cache. */
142*9f988b79SJean-Baptiste Boric int
v7fs_freeblock_update(struct v7fs_self * fs,v7fs_daddr_t blk)143*9f988b79SJean-Baptiste Boric v7fs_freeblock_update(struct v7fs_self *fs, v7fs_daddr_t blk)
144*9f988b79SJean-Baptiste Boric {
145*9f988b79SJean-Baptiste Boric 	/* Assume superblock is locked by caller. */
146*9f988b79SJean-Baptiste Boric 	struct v7fs_superblock *sb = &fs->superblock;
147*9f988b79SJean-Baptiste Boric 	struct v7fs_freeblock *fb;
148*9f988b79SJean-Baptiste Boric 	void *buf;
149*9f988b79SJean-Baptiste Boric 	int error;
150*9f988b79SJean-Baptiste Boric 
151*9f988b79SJean-Baptiste Boric 	/* Read next freeblock table from disk. */
152*9f988b79SJean-Baptiste Boric 	if (!datablock_number_sanity(fs, blk) || !(buf = scratch_read(fs, blk)))
153*9f988b79SJean-Baptiste Boric 		return EIO;
154*9f988b79SJean-Baptiste Boric 
155*9f988b79SJean-Baptiste Boric 	/* Update in-core superblock freelist. */
156*9f988b79SJean-Baptiste Boric 	fb = (struct v7fs_freeblock *)buf;
157*9f988b79SJean-Baptiste Boric 	if ((error = v7fs_freeblock_endian_convert(fs, fb))) {
158*9f988b79SJean-Baptiste Boric 		scratch_free(fs, buf);
159*9f988b79SJean-Baptiste Boric 		return error;
160*9f988b79SJean-Baptiste Boric 	}
161*9f988b79SJean-Baptiste Boric 	DPRINTF("freeblock table#%d, nfree=%d\n", blk, fb->nfreeblock);
162*9f988b79SJean-Baptiste Boric 
163*9f988b79SJean-Baptiste Boric 	memcpy(sb->freeblock, fb->freeblock, sizeof(blk) * fb->nfreeblock);
164*9f988b79SJean-Baptiste Boric 	sb->nfreeblock = fb->nfreeblock;
165*9f988b79SJean-Baptiste Boric 	sb->modified = true;
166*9f988b79SJean-Baptiste Boric 	scratch_free(fs, buf);
167*9f988b79SJean-Baptiste Boric 
168*9f988b79SJean-Baptiste Boric 	return 0;
169*9f988b79SJean-Baptiste Boric }
170*9f988b79SJean-Baptiste Boric 
171*9f988b79SJean-Baptiste Boric int
v7fs_freeblock_endian_convert(struct v7fs_self * fs __unused,struct v7fs_freeblock * fb __unused)172*9f988b79SJean-Baptiste Boric v7fs_freeblock_endian_convert(struct v7fs_self *fs __unused,
173*9f988b79SJean-Baptiste Boric     struct v7fs_freeblock *fb __unused)
174*9f988b79SJean-Baptiste Boric {
175*9f988b79SJean-Baptiste Boric #ifdef V7FS_EI
176*9f988b79SJean-Baptiste Boric 	int i;
177*9f988b79SJean-Baptiste Boric 	int16_t nfree;
178*9f988b79SJean-Baptiste Boric 
179*9f988b79SJean-Baptiste Boric 	nfree = V7FS_VAL16(fs, fb->nfreeblock);
180*9f988b79SJean-Baptiste Boric 	if (nfree <= 0 || nfree > V7FS_MAX_FREEBLOCK) {
181*9f988b79SJean-Baptiste Boric 		DPRINTF("invalid freeblock list. %d (max=%d)\n", nfree,
182*9f988b79SJean-Baptiste Boric 		    V7FS_MAX_FREEBLOCK);
183*9f988b79SJean-Baptiste Boric 		return ENOSPC;
184*9f988b79SJean-Baptiste Boric 	}
185*9f988b79SJean-Baptiste Boric 	fb->nfreeblock = nfree;
186*9f988b79SJean-Baptiste Boric 
187*9f988b79SJean-Baptiste Boric 	for (i = 0; i < nfree; i++) {
188*9f988b79SJean-Baptiste Boric 		fb->freeblock[i] = V7FS_VAL32(fs, fb->freeblock[i]);
189*9f988b79SJean-Baptiste Boric 	}
190*9f988b79SJean-Baptiste Boric #endif /* V7FS_EI */
191*9f988b79SJean-Baptiste Boric 
192*9f988b79SJean-Baptiste Boric 	return 0;
193*9f988b79SJean-Baptiste Boric }
194*9f988b79SJean-Baptiste Boric 
195*9f988b79SJean-Baptiste Boric /* Fill free inode to superblock cache. */
196*9f988b79SJean-Baptiste Boric int
v7fs_freeinode_update(struct v7fs_self * fs)197*9f988b79SJean-Baptiste Boric v7fs_freeinode_update(struct v7fs_self *fs)
198*9f988b79SJean-Baptiste Boric {
199*9f988b79SJean-Baptiste Boric 	/* Assume superblock is locked by caller. */
200*9f988b79SJean-Baptiste Boric 	struct v7fs_superblock *sb = &fs->superblock;
201*9f988b79SJean-Baptiste Boric 	v7fs_ino_t *freeinode = sb->freeinode;
202*9f988b79SJean-Baptiste Boric 	size_t i, j, k;
203*9f988b79SJean-Baptiste Boric 	v7fs_ino_t ino;
204*9f988b79SJean-Baptiste Boric 
205*9f988b79SJean-Baptiste Boric 	/* Loop over all inode list. */
206*9f988b79SJean-Baptiste Boric 	for (i = V7FS_ILIST_SECTOR, ino = 1/* inode start from 1*/, k = 0;
207*9f988b79SJean-Baptiste Boric 	    i < sb->datablock_start_sector; i++) {
208*9f988b79SJean-Baptiste Boric 		struct v7fs_inode_diskimage *di;
209*9f988b79SJean-Baptiste Boric 		void *buf;
210*9f988b79SJean-Baptiste Boric 		if (!(buf = scratch_read(fs, i))) {
211*9f988b79SJean-Baptiste Boric 			DPRINTF("block %zu I/O error.\n", i);
212*9f988b79SJean-Baptiste Boric 			ino += V7FS_INODE_PER_BLOCK;
213*9f988b79SJean-Baptiste Boric 			continue;
214*9f988b79SJean-Baptiste Boric 		}
215*9f988b79SJean-Baptiste Boric 		di = (struct v7fs_inode_diskimage *)buf;
216*9f988b79SJean-Baptiste Boric 
217*9f988b79SJean-Baptiste Boric 		for (j = 0;
218*9f988b79SJean-Baptiste Boric 		    (j < V7FS_INODE_PER_BLOCK) && (k < V7FS_MAX_FREEINODE);
219*9f988b79SJean-Baptiste Boric 		    j++, di++, ino++) {
220*9f988b79SJean-Baptiste Boric 			if (v7fs_inode_allocated(di))
221*9f988b79SJean-Baptiste Boric 				continue;
222*9f988b79SJean-Baptiste Boric 			DPRINTF("free inode%d\n", ino);
223*9f988b79SJean-Baptiste Boric 			freeinode[k++] = ino;
224*9f988b79SJean-Baptiste Boric 		}
225*9f988b79SJean-Baptiste Boric 		scratch_free(fs, buf);
226*9f988b79SJean-Baptiste Boric 	}
227*9f988b79SJean-Baptiste Boric 	sb->nfreeinode = k;
228*9f988b79SJean-Baptiste Boric 
229*9f988b79SJean-Baptiste Boric 	return 0;
230*9f988b79SJean-Baptiste Boric }
231*9f988b79SJean-Baptiste Boric 
232*9f988b79SJean-Baptiste Boric static void
v7fs_superblock_endian_convert(struct v7fs_self * fs __unused,struct v7fs_superblock * to,struct v7fs_superblock * from)233*9f988b79SJean-Baptiste Boric v7fs_superblock_endian_convert(struct v7fs_self *fs __unused,
234*9f988b79SJean-Baptiste Boric     struct v7fs_superblock *to,  struct v7fs_superblock *from)
235*9f988b79SJean-Baptiste Boric {
236*9f988b79SJean-Baptiste Boric #ifdef V7FS_EI
237*9f988b79SJean-Baptiste Boric #define	conv16(m)	(to->m = V7FS_VAL16(fs, from->m))
238*9f988b79SJean-Baptiste Boric #define	conv32(m)	(to->m = V7FS_VAL32(fs, from->m))
239*9f988b79SJean-Baptiste Boric 	int i;
240*9f988b79SJean-Baptiste Boric 
241*9f988b79SJean-Baptiste Boric 	conv16(datablock_start_sector);
242*9f988b79SJean-Baptiste Boric 	conv32(volume_size);
243*9f988b79SJean-Baptiste Boric 	conv16(nfreeblock);
244*9f988b79SJean-Baptiste Boric 	v7fs_daddr_t *dfrom = from->freeblock;
245*9f988b79SJean-Baptiste Boric 	v7fs_daddr_t *dto = to->freeblock;
246*9f988b79SJean-Baptiste Boric 	for (i = 0; i < V7FS_MAX_FREEBLOCK; i++, dfrom++, dto++)
247*9f988b79SJean-Baptiste Boric 		*dto = V7FS_VAL32(fs, *dfrom);
248*9f988b79SJean-Baptiste Boric 
249*9f988b79SJean-Baptiste Boric 	conv16(nfreeinode);
250*9f988b79SJean-Baptiste Boric 	v7fs_ino_t *ifrom = from->freeinode;
251*9f988b79SJean-Baptiste Boric 	v7fs_ino_t *ito = to->freeinode;
252*9f988b79SJean-Baptiste Boric 	for (i = 0; i < V7FS_MAX_FREEINODE; i++, ifrom++, ito++)
253*9f988b79SJean-Baptiste Boric 		*ito = V7FS_VAL16(fs, *ifrom);
254*9f988b79SJean-Baptiste Boric 
255*9f988b79SJean-Baptiste Boric 	conv32(update_time);
256*9f988b79SJean-Baptiste Boric 	conv32(total_freeblock);
257*9f988b79SJean-Baptiste Boric 	conv16(total_freeinode);
258*9f988b79SJean-Baptiste Boric #undef conv16
259*9f988b79SJean-Baptiste Boric #undef conv32
260*9f988b79SJean-Baptiste Boric #else /* V7FS_EI */
261*9f988b79SJean-Baptiste Boric 	memcpy(to, from , sizeof(*to));
262*9f988b79SJean-Baptiste Boric #endif /* V7FS_EI */
263*9f988b79SJean-Baptiste Boric }
264