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 38d485c77fSKonstantin Belousov #include <ufs/ufs/extattr.h> 39d485c77fSKonstantin Belousov #include <ufs/ufs/quota.h> 4020938dbfSJuli Mallett #include <ufs/ufs/ufsmount.h> 4120938dbfSJuli Mallett #include <ufs/ufs/dinode.h> 4220938dbfSJuli Mallett #include <ufs/ffs/fs.h> 4320938dbfSJuli Mallett 4420938dbfSJuli Mallett #include <errno.h> 4520938dbfSJuli Mallett #include <stdio.h> 4620938dbfSJuli Mallett #include <string.h> 47113db2ddSJeff Roberson #include <stdlib.h> 4820938dbfSJuli Mallett #include <unistd.h> 4920938dbfSJuli Mallett 5020938dbfSJuli Mallett #include <libufs.h> 5120938dbfSJuli Mallett 52*82e72f1dSKirk McKusick static int handle_disk_read(struct uufsd *, struct fs *, int); 53*82e72f1dSKirk McKusick 54*82e72f1dSKirk McKusick /* 55*82e72f1dSKirk McKusick * Read the standard superblock. 56*82e72f1dSKirk McKusick */ 5720938dbfSJuli Mallett int 5820938dbfSJuli Mallett sbread(struct uufsd *disk) 5920938dbfSJuli Mallett { 6020938dbfSJuli Mallett struct fs *fs; 61*82e72f1dSKirk McKusick int error; 62*82e72f1dSKirk McKusick 63*82e72f1dSKirk McKusick error = sbget(disk->d_fd, &fs, disk->d_sblockloc); 64*82e72f1dSKirk McKusick return (handle_disk_read(disk, fs, error)); 65*82e72f1dSKirk McKusick } 66*82e72f1dSKirk McKusick 67*82e72f1dSKirk McKusick static int 68*82e72f1dSKirk McKusick handle_disk_read(struct uufsd *disk, struct fs *fs, int error) 69*82e72f1dSKirk McKusick { 7020938dbfSJuli Mallett 7149b2a686SJuli Mallett ERROR(disk, NULL); 72*82e72f1dSKirk McKusick if (error != 0) { 73*82e72f1dSKirk McKusick switch (error) { 74dffce215SKirk McKusick case EIO: 7549b2a686SJuli Mallett ERROR(disk, "non-existent or truncated superblock"); 76dffce215SKirk McKusick break; 77dffce215SKirk McKusick case ENOENT: 78dffce215SKirk McKusick ERROR(disk, "no usable known superblock found"); 79dffce215SKirk McKusick break; 80*82e72f1dSKirk McKusick case EINTEGRITY: 81*82e72f1dSKirk McKusick ERROR(disk, "superblock check-hash failure"); 82*82e72f1dSKirk McKusick break; 83dffce215SKirk McKusick case ENOSPC: 84dffce215SKirk McKusick ERROR(disk, "failed to allocate space for superblock " 85dffce215SKirk McKusick "information"); 86dffce215SKirk McKusick break; 87dffce215SKirk McKusick case EINVAL: 88dffce215SKirk McKusick ERROR(disk, "The previous newfs operation on this " 89dffce215SKirk McKusick "volume did not complete.\nYou must complete " 90dffce215SKirk McKusick "newfs before using this volume."); 91dffce215SKirk McKusick break; 92dffce215SKirk McKusick default: 93dffce215SKirk McKusick ERROR(disk, "unknown superblock read error"); 94dffce215SKirk McKusick errno = EIO; 9520938dbfSJuli Mallett break; 9620938dbfSJuli Mallett } 9720938dbfSJuli Mallett disk->d_ufs = 0; 981081253fSJuli Mallett return (-1); 9920938dbfSJuli Mallett } 100dffce215SKirk McKusick memcpy(&disk->d_fs, fs, fs->fs_sbsize); 101dffce215SKirk McKusick free(fs); 102dffce215SKirk McKusick fs = &disk->d_fs; 103dffce215SKirk McKusick if (fs->fs_magic == FS_UFS1_MAGIC) 104dffce215SKirk McKusick disk->d_ufs = 1; 105dffce215SKirk McKusick if (fs->fs_magic == FS_UFS2_MAGIC) 106dffce215SKirk McKusick disk->d_ufs = 2; 10720938dbfSJuli Mallett disk->d_bsize = fs->fs_fsize / fsbtodb(fs, 1); 108dffce215SKirk McKusick disk->d_sblock = fs->fs_sblockloc / disk->d_bsize; 10992c839a1SKirk McKusick disk->d_si = fs->fs_si; 1101081253fSJuli Mallett return (0); 11120938dbfSJuli Mallett } 11220938dbfSJuli Mallett 11320938dbfSJuli Mallett int 11420938dbfSJuli Mallett sbwrite(struct uufsd *disk, int all) 11520938dbfSJuli Mallett { 11620938dbfSJuli Mallett struct fs *fs; 1178a9493deSKirk McKusick int rv; 11820938dbfSJuli Mallett 11949b2a686SJuli Mallett ERROR(disk, NULL); 120585e5402SJuli Mallett 1218a9493deSKirk McKusick rv = ufs_disk_write(disk); 1228a9493deSKirk McKusick if (rv == -1) { 1238a9493deSKirk McKusick ERROR(disk, "failed to open disk for writing"); 1248a9493deSKirk McKusick return (-1); 1258a9493deSKirk McKusick } 1268a9493deSKirk McKusick 12720938dbfSJuli Mallett fs = &disk->d_fs; 128dffce215SKirk McKusick if ((errno = sbput(disk->d_fd, fs, all ? fs->fs_ncg : 0)) != 0) { 129dffce215SKirk McKusick switch (errno) { 130dffce215SKirk McKusick case EIO: 13149b2a686SJuli Mallett ERROR(disk, "failed to write superblock"); 132dffce215SKirk McKusick break; 133dffce215SKirk McKusick default: 134dffce215SKirk McKusick ERROR(disk, "unknown superblock write error"); 135dffce215SKirk McKusick errno = EIO; 136dffce215SKirk McKusick break; 137dffce215SKirk McKusick } 1381081253fSJuli Mallett return (-1); 13920938dbfSJuli Mallett } 140dffce215SKirk McKusick return (0); 141dffce215SKirk McKusick } 142dffce215SKirk McKusick 143113db2ddSJeff Roberson /* 144dffce215SKirk McKusick * These are the low-level functions that actually read and write 145dffce215SKirk McKusick * the superblock and its associated data. The actual work is done by 146dffce215SKirk McKusick * the functions ffs_sbget and ffs_sbput in /sys/ufs/ffs/ffs_subr.c. 147113db2ddSJeff Roberson */ 148dffce215SKirk McKusick static int use_pread(void *devfd, off_t loc, void **bufp, int size); 149dffce215SKirk McKusick static int use_pwrite(void *devfd, off_t loc, void *buf, int size); 150dffce215SKirk McKusick 151dffce215SKirk McKusick /* 152dffce215SKirk McKusick * Read a superblock from the devfd device allocating memory returned 153dffce215SKirk McKusick * in fsp. Also read the superblock summary information. 154dffce215SKirk McKusick */ 155dffce215SKirk McKusick int 156dffce215SKirk McKusick sbget(int devfd, struct fs **fsp, off_t sblockloc) 157dffce215SKirk McKusick { 158dffce215SKirk McKusick 159dffce215SKirk McKusick return (ffs_sbget(&devfd, fsp, sblockloc, "user", use_pread)); 160113db2ddSJeff Roberson } 161dffce215SKirk McKusick 162dffce215SKirk McKusick /* 163dffce215SKirk McKusick * A read function for use by user-level programs using libufs. 164dffce215SKirk McKusick */ 165dffce215SKirk McKusick static int 166dffce215SKirk McKusick use_pread(void *devfd, off_t loc, void **bufp, int size) 167dffce215SKirk McKusick { 168dffce215SKirk McKusick int fd; 169dffce215SKirk McKusick 170dffce215SKirk McKusick fd = *(int *)devfd; 171dffce215SKirk McKusick if ((*bufp = malloc(size)) == NULL) 172dffce215SKirk McKusick return (ENOSPC); 173dffce215SKirk McKusick if (pread(fd, *bufp, size, loc) != size) 174dffce215SKirk McKusick return (EIO); 175dffce215SKirk McKusick return (0); 176113db2ddSJeff Roberson } 177dffce215SKirk McKusick 178dffce215SKirk McKusick /* 179dffce215SKirk McKusick * Write a superblock to the devfd device from the memory pointed to by fs. 180dffce215SKirk McKusick * Also write out the superblock summary information but do not free the 181dffce215SKirk McKusick * summary information memory. 182dffce215SKirk McKusick * 183dffce215SKirk McKusick * Additionally write out numaltwrite of the alternate superblocks. Use 184dffce215SKirk McKusick * fs->fs_ncg to write out all of the alternate superblocks. 185dffce215SKirk McKusick */ 186dffce215SKirk McKusick int 187dffce215SKirk McKusick sbput(int devfd, struct fs *fs, int numaltwrite) 188dffce215SKirk McKusick { 189dffce215SKirk McKusick struct csum *savedcsp; 190dffce215SKirk McKusick off_t savedactualloc; 191dffce215SKirk McKusick int i, error; 192dffce215SKirk McKusick 193dffce215SKirk McKusick if ((error = ffs_sbput(&devfd, fs, fs->fs_sblockactualloc, 194dffce215SKirk McKusick use_pwrite)) != 0) 195dffce215SKirk McKusick return (error); 196dffce215SKirk McKusick if (numaltwrite == 0) 197dffce215SKirk McKusick return (0); 198dffce215SKirk McKusick savedactualloc = fs->fs_sblockactualloc; 199dffce215SKirk McKusick savedcsp = fs->fs_csp; 200dffce215SKirk McKusick fs->fs_csp = NULL; 201dffce215SKirk McKusick for (i = 0; i < numaltwrite; i++) { 202dffce215SKirk McKusick fs->fs_sblockactualloc = dbtob(fsbtodb(fs, cgsblock(fs, i))); 203dffce215SKirk McKusick if ((error = ffs_sbput(&devfd, fs, fs->fs_sblockactualloc, 204dffce215SKirk McKusick use_pwrite)) != 0) { 205dffce215SKirk McKusick fs->fs_sblockactualloc = savedactualloc; 206dffce215SKirk McKusick fs->fs_csp = savedcsp; 20785ee267aSKirk McKusick return (error); 20820938dbfSJuli Mallett } 20920938dbfSJuli Mallett } 210dffce215SKirk McKusick fs->fs_sblockactualloc = savedactualloc; 211dffce215SKirk McKusick fs->fs_csp = savedcsp; 212dffce215SKirk McKusick return (0); 213dffce215SKirk McKusick } 214dffce215SKirk McKusick 215dffce215SKirk McKusick /* 216dffce215SKirk McKusick * A write function for use by user-level programs using sbput in libufs. 217dffce215SKirk McKusick */ 218dffce215SKirk McKusick static int 219dffce215SKirk McKusick use_pwrite(void *devfd, off_t loc, void *buf, int size) 220dffce215SKirk McKusick { 221dffce215SKirk McKusick int fd; 222dffce215SKirk McKusick 223dffce215SKirk McKusick fd = *(int *)devfd; 224dffce215SKirk McKusick if (pwrite(fd, buf, size, loc) != size) 225dffce215SKirk McKusick return (EIO); 2261081253fSJuli Mallett return (0); 22720938dbfSJuli Mallett } 228