sblock.c revision 256281
1154133Sharti/*
2154133Sharti * Copyright (c) 2002 Juli Mallett.  All rights reserved.
3154133Sharti *
4154133Sharti * This software was written by Juli Mallett <jmallett@FreeBSD.org> for the
5154133Sharti * FreeBSD project.  Redistribution and use in source and binary forms, with
6154133Sharti * or without modification, are permitted provided that the following
7154133Sharti * conditions are met:
8154133Sharti *
9154133Sharti * 1. Redistribution of source code must retain the above copyright notice,
10154133Sharti *    this list of conditions and the following disclaimer.
11154133Sharti * 2. Redistribution in binary form must reproduce the above copyright
12154133Sharti *    notice, this list of conditions and the following disclaimer in the
13154133Sharti *    documentation and/or other materials provided with the distribution.
14154133Sharti *
15154133Sharti * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16154133Sharti * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17154133Sharti * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18154133Sharti * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19154133Sharti * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20154133Sharti * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21154133Sharti * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22154133Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23154133Sharti * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24154133Sharti * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25154133Sharti * POSSIBILITY OF SUCH DAMAGE.
26154133Sharti */
27154133Sharti
28154133Sharti#include <sys/cdefs.h>
29154133Sharti__FBSDID("$FreeBSD: stable/10/lib/libufs/sblock.c 207141 2010-04-24 07:05:35Z jeff $");
30154133Sharti
31154133Sharti#include <sys/param.h>
32154133Sharti#include <sys/mount.h>
33154133Sharti#include <sys/disklabel.h>
34154133Sharti#include <sys/stat.h>
35154133Sharti
36154133Sharti#include <ufs/ufs/ufsmount.h>
37154133Sharti#include <ufs/ufs/dinode.h>
38154133Sharti#include <ufs/ffs/fs.h>
39154133Sharti
40154133Sharti#include <errno.h>
41154133Sharti#include <stdio.h>
42154133Sharti#include <string.h>
43154133Sharti#include <stdlib.h>
44154133Sharti#include <unistd.h>
45154133Sharti
46160341Sharti#include <libufs.h>
47154133Sharti
48154133Shartistatic int superblocks[] = SBLOCKSEARCH;
49154133Sharti
50154133Shartiint
51154133Shartisbread(struct uufsd *disk)
52160341Sharti{
53160341Sharti	uint8_t block[MAXBSIZE];
54160341Sharti	struct fs *fs;
55160341Sharti	int sb, superblock;
56160341Sharti	int i, size, blks;
57160341Sharti	uint8_t *space;
58160341Sharti
59154133Sharti	ERROR(disk, NULL);
60154133Sharti
61154133Sharti	fs = &disk->d_fs;
62154133Sharti	superblock = superblocks[0];
63154133Sharti
64154133Sharti	for (sb = 0; (superblock = superblocks[sb]) != -1; sb++) {
65154133Sharti		if (bread(disk, superblock, disk->d_sb, SBLOCKSIZE) == -1) {
66154133Sharti			ERROR(disk, "non-existent or truncated superblock");
67154133Sharti			return (-1);
68154133Sharti		}
69154133Sharti		if (fs->fs_magic == FS_UFS1_MAGIC)
70154133Sharti			disk->d_ufs = 1;
71154133Sharti		if (fs->fs_magic == FS_UFS2_MAGIC &&
72154133Sharti		    fs->fs_sblockloc == superblock)
73154133Sharti			disk->d_ufs = 2;
74154133Sharti		if (fs->fs_bsize <= MAXBSIZE &&
75154133Sharti		    (size_t)fs->fs_bsize >= sizeof(*fs)) {
76154133Sharti			if (disk->d_ufs)
77154133Sharti				break;
78154133Sharti		}
79154133Sharti		disk->d_ufs = 0;
80154133Sharti	}
81154133Sharti	if (superblock == -1 || disk->d_ufs == 0) {
82154133Sharti		/*
83154133Sharti		 * Other error cases will result in errno being set, here we
84154133Sharti		 * must set it to indicate no superblock could be found with
85154133Sharti		 * which to associate this disk/filesystem.
86154133Sharti		 */
87154133Sharti		ERROR(disk, "no usable known superblock found");
88154133Sharti		errno = ENOENT;
89154133Sharti		return (-1);
90154133Sharti	}
91154133Sharti	disk->d_bsize = fs->fs_fsize / fsbtodb(fs, 1);
92154133Sharti	disk->d_sblock = superblock / disk->d_bsize;
93154133Sharti	/*
94154133Sharti	 * Read in the superblock summary information.
95154133Sharti	 */
96154133Sharti	size = fs->fs_cssize;
97154133Sharti	blks = howmany(size, fs->fs_fsize);
98154133Sharti	size += fs->fs_ncg * sizeof(int32_t);
99154133Sharti	space = malloc(size);
100154133Sharti	if (space == NULL) {
101154133Sharti		ERROR(disk, "failed to allocate space for summary information");
102154133Sharti		return (-1);
103160341Sharti	}
104160341Sharti	fs->fs_csp = (struct csum *)space;
105160341Sharti	for (i = 0; i < blks; i += fs->fs_frag) {
106160341Sharti		size = fs->fs_bsize;
107154133Sharti		if (i + fs->fs_frag > blks)
108154133Sharti			size = (blks - i) * fs->fs_fsize;
109154133Sharti		if (bread(disk, fsbtodb(fs, fs->fs_csaddr + i), block, size)
110154133Sharti		    == -1) {
111154133Sharti			ERROR(disk, "Failed to read sb summary information");
112154133Sharti			free(fs->fs_csp);
113160341Sharti			return (-1);
114160341Sharti		}
115160341Sharti		bcopy(block, space, size);
116154133Sharti		space += size;
117154133Sharti	}
118154133Sharti	fs->fs_maxcluster = (uint32_t *)space;
119154133Sharti	disk->d_sbcsum = fs->fs_csp;
120154133Sharti
121160341Sharti	return (0);
122154133Sharti}
123154133Sharti
124154133Shartiint
125154133Shartisbwrite(struct uufsd *disk, int all)
126154133Sharti{
127154133Sharti	struct fs *fs;
128160341Sharti	int blks, size;
129160341Sharti	uint8_t *space;
130160341Sharti	unsigned i;
131160341Sharti
132160341Sharti	ERROR(disk, NULL);
133160341Sharti
134160341Sharti	fs = &disk->d_fs;
135160341Sharti
136154133Sharti	if (!disk->d_sblock) {
137154133Sharti		disk->d_sblock = disk->d_fs.fs_sblockloc / disk->d_bsize;
138154133Sharti	}
139154133Sharti
140154133Sharti	if (bwrite(disk, disk->d_sblock, fs, SBLOCKSIZE) == -1) {
141154133Sharti		ERROR(disk, "failed to write superblock");
142154133Sharti		return (-1);
143160341Sharti	}
144160341Sharti	/*
145160341Sharti	 * Write superblock summary information.
146160341Sharti	 */
147160341Sharti	blks = howmany(fs->fs_cssize, fs->fs_fsize);
148160341Sharti	space = (uint8_t *)disk->d_sbcsum;
149160341Sharti	for (i = 0; i < blks; i += fs->fs_frag) {
150160341Sharti		size = fs->fs_bsize;
151160341Sharti		if (i + fs->fs_frag > blks)
152160341Sharti			size = (blks - i) * fs->fs_fsize;
153160341Sharti		if (bwrite(disk, fsbtodb(fs, fs->fs_csaddr + i), space, size)
154160341Sharti		    == -1) {
155160341Sharti			ERROR(disk, "Failed to write sb summary information");
156160341Sharti			return (-1);
157160341Sharti		}
158160341Sharti		space += size;
159160341Sharti	}
160160341Sharti	if (all) {
161160341Sharti		for (i = 0; i < fs->fs_ncg; i++)
162160341Sharti			if (bwrite(disk, fsbtodb(fs, cgsblock(fs, i)),
163160341Sharti			    fs, SBLOCKSIZE) == -1) {
164160341Sharti				ERROR(disk, "failed to update a superblock");
165160341Sharti				return (-1);
166154133Sharti			}
167154133Sharti	}
168160341Sharti	return (0);
169160341Sharti}
170154133Sharti