15e53a4f9SPedro F. Giffuni /*- 25e53a4f9SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 35e53a4f9SPedro F. Giffuni * 420938dbfSJuli Mallett * Copyright (c) 2002 Juli Mallett. All rights reserved. 520938dbfSJuli Mallett * 620938dbfSJuli Mallett * This software was written by Juli Mallett <jmallett@FreeBSD.org> for the 720938dbfSJuli Mallett * FreeBSD project. Redistribution and use in source and binary forms, with 820938dbfSJuli Mallett * or without modification, are permitted provided that the following 920938dbfSJuli Mallett * conditions are met: 1020938dbfSJuli Mallett * 1120938dbfSJuli Mallett * 1. Redistribution of source code must retain the above copyright notice, 1220938dbfSJuli Mallett * this list of conditions and the following disclaimer. 1320938dbfSJuli Mallett * 2. Redistribution in binary form must reproduce the above copyright 1420938dbfSJuli Mallett * notice, this list of conditions and the following disclaimer in the 1520938dbfSJuli Mallett * documentation and/or other materials provided with the distribution. 1620938dbfSJuli Mallett * 1720938dbfSJuli Mallett * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1820938dbfSJuli Mallett * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 1920938dbfSJuli Mallett * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 2020938dbfSJuli Mallett * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 2120938dbfSJuli Mallett * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 2220938dbfSJuli Mallett * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 2320938dbfSJuli Mallett * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2420938dbfSJuli Mallett * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 2520938dbfSJuli Mallett * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 2620938dbfSJuli Mallett * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2720938dbfSJuli Mallett * POSSIBILITY OF SUCH DAMAGE. 2820938dbfSJuli Mallett */ 2920938dbfSJuli Mallett 3020938dbfSJuli Mallett #include <sys/cdefs.h> 3120938dbfSJuli Mallett __FBSDID("$FreeBSD$"); 3220938dbfSJuli Mallett 3320938dbfSJuli Mallett #include <sys/param.h> 3420938dbfSJuli Mallett #include <sys/mount.h> 3520938dbfSJuli Mallett #include <sys/disklabel.h> 3620938dbfSJuli Mallett #include <sys/stat.h> 3720938dbfSJuli Mallett 3820938dbfSJuli Mallett #include <ufs/ufs/ufsmount.h> 3920938dbfSJuli Mallett #include <ufs/ufs/dinode.h> 4020938dbfSJuli Mallett #include <ufs/ffs/fs.h> 4120938dbfSJuli Mallett 4220938dbfSJuli Mallett #include <errno.h> 4320938dbfSJuli Mallett #include <stdio.h> 4420938dbfSJuli Mallett #include <string.h> 45113db2ddSJeff Roberson #include <stdlib.h> 4620938dbfSJuli Mallett #include <unistd.h> 4720938dbfSJuli Mallett 4820938dbfSJuli Mallett #include <libufs.h> 4920938dbfSJuli Mallett 5020938dbfSJuli Mallett int 5120938dbfSJuli Mallett sbread(struct uufsd *disk) 5220938dbfSJuli Mallett { 5320938dbfSJuli Mallett struct fs *fs; 5420938dbfSJuli Mallett 5549b2a686SJuli Mallett ERROR(disk, NULL); 5620938dbfSJuli Mallett 57*dffce215SKirk McKusick if ((errno = sbget(disk->d_fd, &fs, -1)) != 0) { 58*dffce215SKirk McKusick switch (errno) { 59*dffce215SKirk McKusick case EIO: 6049b2a686SJuli Mallett ERROR(disk, "non-existent or truncated superblock"); 61*dffce215SKirk McKusick break; 62*dffce215SKirk McKusick case ENOENT: 63*dffce215SKirk McKusick ERROR(disk, "no usable known superblock found"); 64*dffce215SKirk McKusick break; 65*dffce215SKirk McKusick case ENOSPC: 66*dffce215SKirk McKusick ERROR(disk, "failed to allocate space for superblock " 67*dffce215SKirk McKusick "information"); 68*dffce215SKirk McKusick break; 69*dffce215SKirk McKusick case EINVAL: 70*dffce215SKirk McKusick ERROR(disk, "The previous newfs operation on this " 71*dffce215SKirk McKusick "volume did not complete.\nYou must complete " 72*dffce215SKirk McKusick "newfs before using this volume."); 73*dffce215SKirk McKusick break; 74*dffce215SKirk McKusick default: 75*dffce215SKirk McKusick ERROR(disk, "unknown superblock read error"); 76*dffce215SKirk McKusick errno = EIO; 7720938dbfSJuli Mallett break; 7820938dbfSJuli Mallett } 7920938dbfSJuli Mallett disk->d_ufs = 0; 801081253fSJuli Mallett return (-1); 8120938dbfSJuli Mallett } 82*dffce215SKirk McKusick memcpy(&disk->d_fs, fs, fs->fs_sbsize); 83*dffce215SKirk McKusick free(fs); 84*dffce215SKirk McKusick fs = &disk->d_fs; 85*dffce215SKirk McKusick if (fs->fs_magic == FS_UFS1_MAGIC) 86*dffce215SKirk McKusick disk->d_ufs = 1; 87*dffce215SKirk McKusick if (fs->fs_magic == FS_UFS2_MAGIC) 88*dffce215SKirk McKusick disk->d_ufs = 2; 8920938dbfSJuli Mallett disk->d_bsize = fs->fs_fsize / fsbtodb(fs, 1); 90*dffce215SKirk McKusick disk->d_sblock = fs->fs_sblockloc / disk->d_bsize; 91113db2ddSJeff Roberson disk->d_sbcsum = fs->fs_csp; 921081253fSJuli Mallett return (0); 9320938dbfSJuli Mallett } 9420938dbfSJuli Mallett 9520938dbfSJuli Mallett int 9620938dbfSJuli Mallett sbwrite(struct uufsd *disk, int all) 9720938dbfSJuli Mallett { 9820938dbfSJuli Mallett struct fs *fs; 9920938dbfSJuli Mallett 10049b2a686SJuli Mallett ERROR(disk, NULL); 101585e5402SJuli Mallett 10220938dbfSJuli Mallett fs = &disk->d_fs; 103*dffce215SKirk McKusick if ((errno = sbput(disk->d_fd, fs, all ? fs->fs_ncg : 0)) != 0) { 104*dffce215SKirk McKusick switch (errno) { 105*dffce215SKirk McKusick case EIO: 10649b2a686SJuli Mallett ERROR(disk, "failed to write superblock"); 107*dffce215SKirk McKusick break; 108*dffce215SKirk McKusick default: 109*dffce215SKirk McKusick ERROR(disk, "unknown superblock write error"); 110*dffce215SKirk McKusick errno = EIO; 111*dffce215SKirk McKusick break; 112*dffce215SKirk McKusick } 1131081253fSJuli Mallett return (-1); 11420938dbfSJuli Mallett } 115*dffce215SKirk McKusick return (0); 116*dffce215SKirk McKusick } 117*dffce215SKirk McKusick 118113db2ddSJeff Roberson /* 119*dffce215SKirk McKusick * These are the low-level functions that actually read and write 120*dffce215SKirk McKusick * the superblock and its associated data. The actual work is done by 121*dffce215SKirk McKusick * the functions ffs_sbget and ffs_sbput in /sys/ufs/ffs/ffs_subr.c. 122113db2ddSJeff Roberson */ 123*dffce215SKirk McKusick static int use_pread(void *devfd, off_t loc, void **bufp, int size); 124*dffce215SKirk McKusick static int use_pwrite(void *devfd, off_t loc, void *buf, int size); 125*dffce215SKirk McKusick 126*dffce215SKirk McKusick /* 127*dffce215SKirk McKusick * Read a superblock from the devfd device allocating memory returned 128*dffce215SKirk McKusick * in fsp. Also read the superblock summary information. 129*dffce215SKirk McKusick */ 130*dffce215SKirk McKusick int 131*dffce215SKirk McKusick sbget(int devfd, struct fs **fsp, off_t sblockloc) 132*dffce215SKirk McKusick { 133*dffce215SKirk McKusick 134*dffce215SKirk McKusick return (ffs_sbget(&devfd, fsp, sblockloc, "user", use_pread)); 135113db2ddSJeff Roberson } 136*dffce215SKirk McKusick 137*dffce215SKirk McKusick /* 138*dffce215SKirk McKusick * A read function for use by user-level programs using libufs. 139*dffce215SKirk McKusick */ 140*dffce215SKirk McKusick static int 141*dffce215SKirk McKusick use_pread(void *devfd, off_t loc, void **bufp, int size) 142*dffce215SKirk McKusick { 143*dffce215SKirk McKusick int fd; 144*dffce215SKirk McKusick 145*dffce215SKirk McKusick fd = *(int *)devfd; 146*dffce215SKirk McKusick if ((*bufp = malloc(size)) == NULL) 147*dffce215SKirk McKusick return (ENOSPC); 148*dffce215SKirk McKusick if (pread(fd, *bufp, size, loc) != size) 149*dffce215SKirk McKusick return (EIO); 150*dffce215SKirk McKusick return (0); 151113db2ddSJeff Roberson } 152*dffce215SKirk McKusick 153*dffce215SKirk McKusick /* 154*dffce215SKirk McKusick * Write a superblock to the devfd device from the memory pointed to by fs. 155*dffce215SKirk McKusick * Also write out the superblock summary information but do not free the 156*dffce215SKirk McKusick * summary information memory. 157*dffce215SKirk McKusick * 158*dffce215SKirk McKusick * Additionally write out numaltwrite of the alternate superblocks. Use 159*dffce215SKirk McKusick * fs->fs_ncg to write out all of the alternate superblocks. 160*dffce215SKirk McKusick */ 161*dffce215SKirk McKusick int 162*dffce215SKirk McKusick sbput(int devfd, struct fs *fs, int numaltwrite) 163*dffce215SKirk McKusick { 164*dffce215SKirk McKusick struct csum *savedcsp; 165*dffce215SKirk McKusick off_t savedactualloc; 166*dffce215SKirk McKusick int i, error; 167*dffce215SKirk McKusick 168*dffce215SKirk McKusick if ((error = ffs_sbput(&devfd, fs, fs->fs_sblockactualloc, 169*dffce215SKirk McKusick use_pwrite)) != 0) 170*dffce215SKirk McKusick return (error); 171*dffce215SKirk McKusick if (numaltwrite == 0) 172*dffce215SKirk McKusick return (0); 173*dffce215SKirk McKusick savedactualloc = fs->fs_sblockactualloc; 174*dffce215SKirk McKusick savedcsp = fs->fs_csp; 175*dffce215SKirk McKusick fs->fs_csp = NULL; 176*dffce215SKirk McKusick for (i = 0; i < numaltwrite; i++) { 177*dffce215SKirk McKusick fs->fs_sblockactualloc = dbtob(fsbtodb(fs, cgsblock(fs, i))); 178*dffce215SKirk McKusick if ((error = ffs_sbput(&devfd, fs, fs->fs_sblockactualloc, 179*dffce215SKirk McKusick use_pwrite)) != 0) { 180*dffce215SKirk McKusick fs->fs_sblockactualloc = savedactualloc; 181*dffce215SKirk McKusick fs->fs_csp = savedcsp; 1821081253fSJuli Mallett return (-1); 18320938dbfSJuli Mallett } 18420938dbfSJuli Mallett } 185*dffce215SKirk McKusick fs->fs_sblockactualloc = savedactualloc; 186*dffce215SKirk McKusick fs->fs_csp = savedcsp; 187*dffce215SKirk McKusick return (0); 188*dffce215SKirk McKusick } 189*dffce215SKirk McKusick 190*dffce215SKirk McKusick /* 191*dffce215SKirk McKusick * A write function for use by user-level programs using sbput in libufs. 192*dffce215SKirk McKusick */ 193*dffce215SKirk McKusick static int 194*dffce215SKirk McKusick use_pwrite(void *devfd, off_t loc, void *buf, int size) 195*dffce215SKirk McKusick { 196*dffce215SKirk McKusick int fd; 197*dffce215SKirk McKusick 198*dffce215SKirk McKusick fd = *(int *)devfd; 199*dffce215SKirk McKusick if (pwrite(fd, buf, size, loc) != size) 200*dffce215SKirk McKusick return (EIO); 2011081253fSJuli Mallett return (0); 20220938dbfSJuli Mallett } 203