120938dbfSJuli Mallett /* 220938dbfSJuli Mallett * Copyright (c) 2002 Juli Mallett. All rights reserved. 320938dbfSJuli Mallett * 420938dbfSJuli Mallett * This software was written by Juli Mallett <jmallett@FreeBSD.org> for the 520938dbfSJuli Mallett * FreeBSD project. Redistribution and use in source and binary forms, with 620938dbfSJuli Mallett * or without modification, are permitted provided that the following 720938dbfSJuli Mallett * conditions are met: 820938dbfSJuli Mallett * 920938dbfSJuli Mallett * 1. Redistribution of source code must retain the above copyright notice, 1020938dbfSJuli Mallett * this list of conditions and the following disclaimer. 1120938dbfSJuli Mallett * 2. Redistribution in binary form must reproduce the above copyright 1220938dbfSJuli Mallett * notice, this list of conditions and the following disclaimer in the 1320938dbfSJuli Mallett * documentation and/or other materials provided with the distribution. 1420938dbfSJuli Mallett * 1520938dbfSJuli Mallett * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1620938dbfSJuli Mallett * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 1720938dbfSJuli Mallett * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 1820938dbfSJuli Mallett * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 1920938dbfSJuli Mallett * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 2020938dbfSJuli Mallett * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 2120938dbfSJuli Mallett * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2220938dbfSJuli Mallett * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 2320938dbfSJuli Mallett * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 2420938dbfSJuli Mallett * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2520938dbfSJuli Mallett * POSSIBILITY OF SUCH DAMAGE. 2620938dbfSJuli Mallett */ 2720938dbfSJuli Mallett 2820938dbfSJuli Mallett #include <sys/cdefs.h> 2920938dbfSJuli Mallett __FBSDID("$FreeBSD$"); 3020938dbfSJuli Mallett 3120938dbfSJuli Mallett #include <sys/param.h> 3220938dbfSJuli Mallett #include <sys/mount.h> 3320938dbfSJuli Mallett #include <sys/disklabel.h> 3420938dbfSJuli Mallett #include <sys/stat.h> 3520938dbfSJuli Mallett 3620938dbfSJuli Mallett #include <ufs/ufs/ufsmount.h> 3720938dbfSJuli Mallett #include <ufs/ufs/dinode.h> 3820938dbfSJuli Mallett #include <ufs/ffs/fs.h> 3920938dbfSJuli Mallett 4020938dbfSJuli Mallett #include <errno.h> 4120938dbfSJuli Mallett #include <stdio.h> 4220938dbfSJuli Mallett #include <string.h> 43*113db2ddSJeff Roberson #include <stdlib.h> 4420938dbfSJuli Mallett #include <unistd.h> 4520938dbfSJuli Mallett 4620938dbfSJuli Mallett #include <libufs.h> 4720938dbfSJuli Mallett 4820938dbfSJuli Mallett static int superblocks[] = SBLOCKSEARCH; 4920938dbfSJuli Mallett 5020938dbfSJuli Mallett int 5120938dbfSJuli Mallett sbread(struct uufsd *disk) 5220938dbfSJuli Mallett { 53*113db2ddSJeff Roberson uint8_t block[MAXBSIZE]; 5420938dbfSJuli Mallett struct fs *fs; 5520938dbfSJuli Mallett int sb, superblock; 56*113db2ddSJeff Roberson int i, size, blks; 57*113db2ddSJeff Roberson uint8_t *space; 5820938dbfSJuli Mallett 5949b2a686SJuli Mallett ERROR(disk, NULL); 6020938dbfSJuli Mallett 6120938dbfSJuli Mallett fs = &disk->d_fs; 6220938dbfSJuli Mallett superblock = superblocks[0]; 6320938dbfSJuli Mallett 6420938dbfSJuli Mallett for (sb = 0; (superblock = superblocks[sb]) != -1; sb++) { 6520938dbfSJuli Mallett if (bread(disk, superblock, disk->d_sb, SBLOCKSIZE) == -1) { 6649b2a686SJuli Mallett ERROR(disk, "non-existent or truncated superblock"); 671081253fSJuli Mallett return (-1); 6820938dbfSJuli Mallett } 6920938dbfSJuli Mallett if (fs->fs_magic == FS_UFS1_MAGIC) 7020938dbfSJuli Mallett disk->d_ufs = 1; 71a506dcdaSJuli Mallett if (fs->fs_magic == FS_UFS2_MAGIC && 72a506dcdaSJuli Mallett fs->fs_sblockloc == superblock) 7320938dbfSJuli Mallett disk->d_ufs = 2; 74a506dcdaSJuli Mallett if (fs->fs_bsize <= MAXBSIZE && 75a506dcdaSJuli Mallett (size_t)fs->fs_bsize >= sizeof(*fs)) { 7620938dbfSJuli Mallett if (disk->d_ufs) 7720938dbfSJuli Mallett break; 7820938dbfSJuli Mallett } 7920938dbfSJuli Mallett disk->d_ufs = 0; 8020938dbfSJuli Mallett } 8120938dbfSJuli Mallett if (superblock == -1 || disk->d_ufs == 0) { 8220938dbfSJuli Mallett /* 8320938dbfSJuli Mallett * Other error cases will result in errno being set, here we 8420938dbfSJuli Mallett * must set it to indicate no superblock could be found with 8520938dbfSJuli Mallett * which to associate this disk/filesystem. 8620938dbfSJuli Mallett */ 8749b2a686SJuli Mallett ERROR(disk, "no usable known superblock found"); 8820938dbfSJuli Mallett errno = ENOENT; 891081253fSJuli Mallett return (-1); 9020938dbfSJuli Mallett } 9120938dbfSJuli Mallett disk->d_bsize = fs->fs_fsize / fsbtodb(fs, 1); 9220938dbfSJuli Mallett disk->d_sblock = superblock / disk->d_bsize; 93*113db2ddSJeff Roberson /* 94*113db2ddSJeff Roberson * Read in the superblock summary information. 95*113db2ddSJeff Roberson */ 96*113db2ddSJeff Roberson size = fs->fs_cssize; 97*113db2ddSJeff Roberson blks = howmany(size, fs->fs_fsize); 98*113db2ddSJeff Roberson size += fs->fs_ncg * sizeof(int32_t); 99*113db2ddSJeff Roberson space = malloc(size); 100*113db2ddSJeff Roberson if (space == NULL) { 101*113db2ddSJeff Roberson ERROR(disk, "failed to allocate space for summary information"); 102*113db2ddSJeff Roberson return (-1); 103*113db2ddSJeff Roberson } 104*113db2ddSJeff Roberson fs->fs_csp = (struct csum *)space; 105*113db2ddSJeff Roberson for (i = 0; i < blks; i += fs->fs_frag) { 106*113db2ddSJeff Roberson size = fs->fs_bsize; 107*113db2ddSJeff Roberson if (i + fs->fs_frag > blks) 108*113db2ddSJeff Roberson size = (blks - i) * fs->fs_fsize; 109*113db2ddSJeff Roberson if (bread(disk, fsbtodb(fs, fs->fs_csaddr + i), block, size) 110*113db2ddSJeff Roberson == -1) { 111*113db2ddSJeff Roberson ERROR(disk, "Failed to read sb summary information"); 112*113db2ddSJeff Roberson free(fs->fs_csp); 113*113db2ddSJeff Roberson return (-1); 114*113db2ddSJeff Roberson } 115*113db2ddSJeff Roberson bcopy(block, space, size); 116*113db2ddSJeff Roberson space += size; 117*113db2ddSJeff Roberson } 118*113db2ddSJeff Roberson fs->fs_maxcluster = (uint32_t *)space; 119*113db2ddSJeff Roberson disk->d_sbcsum = fs->fs_csp; 120*113db2ddSJeff Roberson 1211081253fSJuli Mallett return (0); 12220938dbfSJuli Mallett } 12320938dbfSJuli Mallett 12420938dbfSJuli Mallett int 12520938dbfSJuli Mallett sbwrite(struct uufsd *disk, int all) 12620938dbfSJuli Mallett { 12720938dbfSJuli Mallett struct fs *fs; 128*113db2ddSJeff Roberson int blks, size; 129*113db2ddSJeff Roberson uint8_t *space; 130f634c395SWarner Losh unsigned i; 13120938dbfSJuli Mallett 13249b2a686SJuli Mallett ERROR(disk, NULL); 133585e5402SJuli Mallett 13420938dbfSJuli Mallett fs = &disk->d_fs; 13520938dbfSJuli Mallett 136fe8b86a0SJuli Mallett if (!disk->d_sblock) { 137fe8b86a0SJuli Mallett disk->d_sblock = disk->d_fs.fs_sblockloc / disk->d_bsize; 138fe8b86a0SJuli Mallett } 139fe8b86a0SJuli Mallett 14020938dbfSJuli Mallett if (bwrite(disk, disk->d_sblock, fs, SBLOCKSIZE) == -1) { 14149b2a686SJuli Mallett ERROR(disk, "failed to write superblock"); 1421081253fSJuli Mallett return (-1); 14320938dbfSJuli Mallett } 144*113db2ddSJeff Roberson /* 145*113db2ddSJeff Roberson * Write superblock summary information. 146*113db2ddSJeff Roberson */ 147*113db2ddSJeff Roberson blks = howmany(fs->fs_cssize, fs->fs_fsize); 148*113db2ddSJeff Roberson space = (uint8_t *)disk->d_sbcsum; 149*113db2ddSJeff Roberson for (i = 0; i < blks; i += fs->fs_frag) { 150*113db2ddSJeff Roberson size = fs->fs_bsize; 151*113db2ddSJeff Roberson if (i + fs->fs_frag > blks) 152*113db2ddSJeff Roberson size = (blks - i) * fs->fs_fsize; 153*113db2ddSJeff Roberson if (bwrite(disk, fsbtodb(fs, fs->fs_csaddr + i), space, size) 154*113db2ddSJeff Roberson == -1) { 155*113db2ddSJeff Roberson ERROR(disk, "Failed to write sb summary information"); 156*113db2ddSJeff Roberson return (-1); 157*113db2ddSJeff Roberson } 158*113db2ddSJeff Roberson space += size; 159*113db2ddSJeff Roberson } 16020938dbfSJuli Mallett if (all) { 16120938dbfSJuli Mallett for (i = 0; i < fs->fs_ncg; i++) 16220938dbfSJuli Mallett if (bwrite(disk, fsbtodb(fs, cgsblock(fs, i)), 16320938dbfSJuli Mallett fs, SBLOCKSIZE) == -1) { 16449b2a686SJuli Mallett ERROR(disk, "failed to update a superblock"); 1651081253fSJuli Mallett return (-1); 16620938dbfSJuli Mallett } 16720938dbfSJuli Mallett } 1681081253fSJuli Mallett return (0); 16920938dbfSJuli Mallett } 170