aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKirk McKusick <mckusick@FreeBSD.org>2002-06-21 06:18:05 +0000
committerKirk McKusick <mckusick@FreeBSD.org>2002-06-21 06:18:05 +0000
commit1c85e6a35d93195e896b030d9a55f7ac4ccee2c3 (patch)
treef1364dbfb9835934a3879b5904f7ff9a1495744c
parent27168693db756b7c8dabe3830a804bf72def2a6d (diff)
downloadsrc-1c85e6a35d93195e896b030d9a55f7ac4ccee2c3.tar.gz
src-1c85e6a35d93195e896b030d9a55f7ac4ccee2c3.zip
This commit adds basic support for the UFS2 filesystem. The UFS2
filesystem expands the inode to 256 bytes to make space for 64-bit block pointers. It also adds a file-creation time field, an ability to use jumbo blocks per inode to allow extent like pointer density, and space for extended attributes (up to twice the filesystem block size worth of attributes, e.g., on a 16K filesystem, there is space for 32K of attributes). UFS2 fully supports and runs existing UFS1 filesystems. New filesystems built using newfs can be built in either UFS1 or UFS2 format using the -O option. In this commit UFS1 is the default format, so if you want to build UFS2 format filesystems, you must specify -O 2. This default will be changed to UFS2 when UFS2 proves itself to be stable. In this commit the boot code for reading UFS2 filesystems is not compiled (see /sys/boot/common/ufsread.c) as there is insufficient space in the boot block. Once the size of the boot block is increased, this code can be defined. Things to note: the definition of SBSIZE has changed to SBLOCKSIZE. The header file <ufs/ufs/dinode.h> must be included before <ufs/ffs/fs.h> so as to get the definitions of ufs2_daddr_t and ufs_lbn_t. Still TODO: Verify that the first level bootstraps work for all the architectures. Convert the utility ffsinfo to understand UFS2 and test growfs. Add support for the extended attribute storage. Update soft updates to ensure integrity of extended attribute storage. Switch the current extended attribute interfaces to use the extended attribute storage. Add the extent like functionality (framework is there, but is currently never used). Sponsored by: DARPA & NAI Labs. Reviewed by: Poul-Henning Kamp <phk@freebsd.org>
Notes
Notes: svn path=/head/; revision=98542
-rw-r--r--include/protocols/dumprestore.h47
-rw-r--r--lib/libstand/ufs.c185
-rw-r--r--release/picobsd/build/write_mfs_in_kernel.c26
-rw-r--r--sbin/Makefile1
-rw-r--r--sbin/badsect/badsect.c24
-rw-r--r--sbin/clri/clri.c67
-rw-r--r--sbin/dump/dump.h18
-rw-r--r--sbin/dump/itime.c8
-rw-r--r--sbin/dump/main.c53
-rw-r--r--sbin/dump/optr.c2
-rw-r--r--sbin/dump/tape.c22
-rw-r--r--sbin/dump/traverse.c270
-rw-r--r--sbin/dumpfs/dumpfs.c234
-rw-r--r--sbin/fsck_ffs/dir.c86
-rw-r--r--sbin/fsck_ffs/fsck.h95
-rw-r--r--sbin/fsck_ffs/fsutil.c28
-rw-r--r--sbin/fsck_ffs/inode.c189
-rw-r--r--sbin/fsck_ffs/main.c20
-rw-r--r--sbin/fsck_ffs/pass1.c125
-rw-r--r--sbin/fsck_ffs/pass1b.c4
-rw-r--r--sbin/fsck_ffs/pass2.c38
-rw-r--r--sbin/fsck_ffs/pass4.c6
-rw-r--r--sbin/fsck_ffs/pass5.c149
-rw-r--r--sbin/fsck_ffs/setup.c111
-rw-r--r--sbin/fsdb/fsdb.c72
-rw-r--r--sbin/fsdb/fsdb.h10
-rw-r--r--sbin/fsdb/fsdbutil.c103
-rw-r--r--sbin/fsirand/fsirand.c117
-rw-r--r--sbin/growfs/growfs.c711
-rw-r--r--sbin/newfs/mkfs.c797
-rw-r--r--sbin/newfs/newfs.838
-rw-r--r--sbin/newfs/newfs.c102
-rw-r--r--sbin/newfs/newfs.h22
-rw-r--r--sbin/quotacheck/quotacheck.c80
-rw-r--r--sbin/restore/dirs.c114
-rw-r--r--sbin/restore/main.c7
-rw-r--r--sbin/restore/restore.c4
-rw-r--r--sbin/restore/restore.h17
-rw-r--r--sbin/restore/tape.c277
-rw-r--r--sbin/tunefs/tunefs.841
-rw-r--r--sbin/tunefs/tunefs.c64
-rw-r--r--sys/amd64/Makefile1
-rw-r--r--sys/boot/common/ufsread.c215
-rw-r--r--sys/boot/i386/Makefile2
-rw-r--r--sys/boot/i386/boot2/Makefile2
-rw-r--r--sys/boot/i386/boot2/boot2.c84
-rw-r--r--sys/boot/i386/gptboot/Makefile2
-rw-r--r--sys/boot/i386/gptboot/gptboot.c84
-rw-r--r--sys/boot/i386/libi386/Makefile11
-rw-r--r--sys/boot/i386/loader/Makefile2
-rw-r--r--sys/i386/Makefile1
-rw-r--r--sys/kern/subr_disklabel.c11
-rw-r--r--sys/kern/subr_diskslice.c10
-rw-r--r--sys/kern/vfs_bio.c17
-rw-r--r--sys/kern/vfs_cluster.c15
-rw-r--r--sys/kern/vfs_extattr.c4
-rw-r--r--sys/kern/vfs_syscalls.c4
-rw-r--r--sys/kern/vfs_vnops.c4
-rw-r--r--sys/sys/stat.h6
-rw-r--r--sys/sys/types.h2
-rw-r--r--sys/sys/vnode.h1
-rw-r--r--sys/ufs/ffs/ffs_alloc.c677
-rw-r--r--sys/ufs/ffs/ffs_balloc.c442
-rw-r--r--sys/ufs/ffs/ffs_extern.h38
-rw-r--r--sys/ufs/ffs/ffs_inode.c138
-rw-r--r--sys/ufs/ffs/ffs_snapshot.c611
-rw-r--r--sys/ufs/ffs/ffs_softdep.c455
-rw-r--r--sys/ufs/ffs/ffs_softdep_stub.c12
-rw-r--r--sys/ufs/ffs/ffs_subr.c71
-rw-r--r--sys/ufs/ffs/ffs_tables.c1
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c277
-rw-r--r--sys/ufs/ffs/ffs_vnops.c2
-rw-r--r--sys/ufs/ffs/fs.h271
-rw-r--r--sys/ufs/ffs/softdep.h38
-rw-r--r--sys/ufs/ufs/dinode.h135
-rw-r--r--sys/ufs/ufs/inode.h68
-rw-r--r--sys/ufs/ufs/quota.h8
-rw-r--r--sys/ufs/ufs/ufs_acl.c3
-rw-r--r--sys/ufs/ufs/ufs_bmap.c85
-rw-r--r--sys/ufs/ufs/ufs_extattr.c4
-rw-r--r--sys/ufs/ufs/ufs_extern.h9
-rw-r--r--sys/ufs/ufs/ufs_inode.c16
-rw-r--r--sys/ufs/ufs/ufs_lookup.c20
-rw-r--r--sys/ufs/ufs/ufs_quota.c25
-rw-r--r--sys/ufs/ufs/ufs_readwrite.c14
-rw-r--r--sys/ufs/ufs/ufs_vnops.c133
-rw-r--r--sys/ufs/ufs/ufsmount.h9
-rw-r--r--usr.bin/fstat/fstat.c4
-rw-r--r--usr.sbin/quot/quot.c140
89 files changed, 5199 insertions, 3369 deletions
diff --git a/include/protocols/dumprestore.h b/include/protocols/dumprestore.h
index ebc700d3d975..6daecc11723a 100644
--- a/include/protocols/dumprestore.h
+++ b/include/protocols/dumprestore.h
@@ -64,20 +64,48 @@
#define OFS_MAGIC (int)60011
#define NFS_MAGIC (int)60012
+#ifndef FS_UFS2_MAGIC
+#define FS_UFS2_MAGIC (int)0x19540119
+#endif
#define CHECKSUM (int)84446
union u_spcl {
char dummy[TP_BSIZE];
struct s_spcl {
int32_t c_type; /* record type (see below) */
- int32_t c_date; /* date of this dump */
- int32_t c_ddate; /* date of previous dump */
+ int32_t c_old_date; /* date of this dump */
+ int32_t c_old_ddate; /* date of previous dump */
int32_t c_volume; /* dump volume number */
- int32_t c_tapea; /* logical block of this record */
+ int32_t c_old_tapea; /* logical block of this record */
ino_t c_inumber; /* number of inode */
int32_t c_magic; /* magic number (see above) */
int32_t c_checksum; /* record checksum */
- struct dinode c_dinode; /* ownership and mode of inode */
+ /*
+ * Start old dinode structure, expanded for binary
+ * compatibility with UFS1.
+ */
+ u_int16_t c_mode; /* file mode */
+ int16_t c_spare1[3]; /* old nlink, ids */
+ u_int64_t c_size; /* file byte count */
+ int32_t c_old_atime; /* old last access time, seconds */
+ int32_t c_atimensec; /* last access time, nanoseconds */
+ int32_t c_old_mtime; /* old last modified time, secs */
+ int32_t c_mtimensec; /* last modified time, nanosecs */
+ int32_t c_spare2[2]; /* old ctime */
+ int32_t c_rdev; /* for devices, device number */
+ int32_t c_createtimensec; /* creation time, nanosecs */
+ int64_t c_createtime; /* creation time, seconds */
+ int64_t c_atime; /* last access time, seconds */
+ int64_t c_mtime; /* last modified time, seconds */
+ int32_t c_spare4[7]; /* old block pointers */
+ u_int32_t c_file_flags; /* status flags (chflags) */
+ int32_t c_spare5[2]; /* old blocks, generation number */
+ u_int32_t c_uid; /* file owner */
+ u_int32_t c_gid; /* file group */
+ int32_t c_spare6[2]; /* previously unused spares */
+ /*
+ * End old dinode structure.
+ */
int32_t c_count; /* number of valid c_addr entries */
char c_addr[TP_NINDIR]; /* 1 => data; 0 => hole in inode */
char c_label[LBLSIZE]; /* dump label */
@@ -86,8 +114,12 @@ union u_spcl {
char c_dev[NAMELEN]; /* name of dumpped device */
char c_host[NAMELEN]; /* name of dumpped host */
int32_t c_flags; /* additional information */
- int32_t c_firstrec; /* first record on volume */
- int32_t c_spare[32]; /* reserved for future uses */
+ int32_t c_old_firstrec; /* first record on volume */
+ int64_t c_date; /* date of this dump */
+ int64_t c_ddate; /* date of previous dump */
+ int64_t c_tapea; /* logical block of this record */
+ int64_t c_firstrec; /* first record on volume */
+ int32_t c_spare[24]; /* reserved for future uses */
} s_spcl;
} u_spcl;
#define spcl u_spcl.s_spcl
@@ -104,8 +136,7 @@ union u_spcl {
/*
* flag values
*/
-#define DR_NEWHEADER 0x0001 /* new format tape header */
-#define DR_NEWINODEFMT 0x0002 /* new format inodes on tape */
+/* None at the moment */
#define DUMPOUTFMT "%-32s %c %s" /* for printf */
/* name, level, ctime(date) */
diff --git a/lib/libstand/ufs.c b/lib/libstand/ufs.c
index 2bd9d178b98a..8993d6cecbc5 100644
--- a/lib/libstand/ufs.c
+++ b/lib/libstand/ufs.c
@@ -1,7 +1,16 @@
/* $NetBSD: ufs.c,v 1.20 1998/03/01 07:15:39 ross Exp $ */
/*-
- * Copyright (c) 1993
+ * Copyright (c) 2002 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by Marshall
+ * Kirk McKusick and Network Associates Laboratories, the Security
+ * Research Division of Network Associates, Inc. under DARPA/SPAWAR
+ * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
+ * research program
+ *
+ * Copyright (c) 1982, 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -107,7 +116,10 @@ struct fs_ops ufs_fsops = {
struct file {
off_t f_seekp; /* seek pointer */
struct fs *f_fs; /* pointer to super-block */
- struct dinode f_di; /* copy of on-disk inode */
+ union dinode {
+ struct ufs1_dinode di1;
+ struct ufs2_dinode di2;
+ } f_di; /* copy of on-disk inode */
int f_nindir[NIADDR];
/* number of blocks mapped by
indirect block at level i */
@@ -115,20 +127,20 @@ struct file {
level i */
size_t f_blksize[NIADDR];
/* size of buffer */
- daddr_t f_blkno[NIADDR];/* disk address of block in buffer */
+ ufs2_daddr_t f_blkno[NIADDR];/* disk address of block in buffer */
+ ufs2_daddr_t f_buf_blkno; /* block number of data block */
char *f_buf; /* buffer for data block */
size_t f_buf_size; /* size of data block */
- daddr_t f_buf_blkno; /* block number of data block */
};
+#define DIP(fp, field) \
+ ((fp)->f_fs->fs_magic == FS_UFS1_MAGIC ? \
+ (fp)->f_di.di1.field : (fp)->f_di.di2.field)
static int read_inode(ino_t, struct open_file *);
-static int block_map(struct open_file *, daddr_t, daddr_t *);
+static int block_map(struct open_file *, ufs2_daddr_t, ufs2_daddr_t *);
static int buf_read_file(struct open_file *, char **, size_t *);
static int buf_write_file(struct open_file *, char *, size_t *);
static int search_directory(char *, struct open_file *, ino_t *);
-#ifdef COMPAT_UFS
-static void ffs_oldfscompat(struct fs *);
-#endif
/*
* Read a new inode into a file structure.
@@ -162,12 +174,12 @@ read_inode(inumber, f)
goto out;
}
- {
- struct dinode *dp;
-
- dp = (struct dinode *)buf;
- fp->f_di = dp[ino_to_fsbo(fs, inumber)];
- }
+ if (fp->f_fs->fs_magic == FS_UFS1_MAGIC)
+ fp->f_di.di1 = ((struct ufs1_dinode *)buf)
+ [ino_to_fsbo(fs, inumber)];
+ else
+ fp->f_di.di2 = ((struct ufs2_dinode *)buf)
+ [ino_to_fsbo(fs, inumber)];
/*
* Clear out the old buffers
@@ -191,15 +203,14 @@ out:
static int
block_map(f, file_block, disk_block_p)
struct open_file *f;
- daddr_t file_block;
- daddr_t *disk_block_p; /* out */
+ ufs2_daddr_t file_block;
+ ufs2_daddr_t *disk_block_p; /* out */
{
struct file *fp = (struct file *)f->f_fsdata;
struct fs *fs = fp->f_fs;
int level;
int idx;
- daddr_t ind_block_num;
- u_int32_t *ind_p;
+ ufs2_daddr_t ind_block_num;
int rc;
/*
@@ -227,7 +238,7 @@ block_map(f, file_block, disk_block_p)
if (file_block < NDADDR) {
/* Direct block. */
- *disk_block_p = fp->f_di.di_db[file_block];
+ *disk_block_p = DIP(fp, di_db[file_block]);
return (0);
}
@@ -249,7 +260,7 @@ block_map(f, file_block, disk_block_p)
return (EFBIG);
}
- ind_block_num = fp->f_di.di_ib[level];
+ ind_block_num = DIP(fp, di_ib[level]);
for (; level >= 0; level--) {
if (ind_block_num == 0) {
@@ -274,15 +285,16 @@ block_map(f, file_block, disk_block_p)
fp->f_blkno[level] = ind_block_num;
}
- ind_p = (u_int32_t *)fp->f_blk[level];
-
if (level > 0) {
idx = file_block / fp->f_nindir[level - 1];
file_block %= fp->f_nindir[level - 1];
} else
idx = file_block;
- ind_block_num = ind_p[idx];
+ if (fp->f_fs->fs_magic == FS_UFS1_MAGIC)
+ ind_block_num = ((ufs1_daddr_t *)fp->f_blk[level])[idx];
+ else
+ ind_block_num = ((ufs2_daddr_t *)fp->f_blk[level])[idx];
}
*disk_block_p = ind_block_num;
@@ -302,8 +314,8 @@ buf_write_file(f, buf_p, size_p)
struct file *fp = (struct file *)f->f_fsdata;
struct fs *fs = fp->f_fs;
long off;
- daddr_t file_block;
- daddr_t disk_block;
+ ufs_lbn_t file_block;
+ ufs2_daddr_t disk_block;
size_t block_size;
int rc;
@@ -312,21 +324,22 @@ buf_write_file(f, buf_p, size_p)
*/
off = blkoff(fs, fp->f_seekp);
file_block = lblkno(fs, fp->f_seekp);
- block_size = dblksize(fs, &fp->f_di, file_block);
+ block_size = sblksize(fs, DIP(fp, di_size), file_block);
rc = block_map(f, file_block, &disk_block);
if (rc)
return (rc);
if (disk_block == 0)
- return (EFBIG); /* Because we can't allocate space on the drive */
+ /* Because we can't allocate space on the drive */
+ return (EFBIG);
/*
* Truncate buffer at end of file, and at the end of
* this block.
*/
- if (*size_p > fp->f_di.di_size - fp->f_seekp)
- *size_p = fp->f_di.di_size - fp->f_seekp;
+ if (*size_p > DIP(fp, di_size) - fp->f_seekp)
+ *size_p = DIP(fp, di_size) - fp->f_seekp;
if (*size_p > block_size - off)
*size_p = block_size - off;
@@ -353,7 +366,7 @@ buf_write_file(f, buf_p, size_p)
/*
* Copy the user data into the cached block.
*/
- bcopy(buf_p,fp->f_buf + off,*size_p);
+ bcopy(buf_p, fp->f_buf + off, *size_p);
/*
* Write the block out to storage.
@@ -379,14 +392,14 @@ buf_read_file(f, buf_p, size_p)
struct file *fp = (struct file *)f->f_fsdata;
struct fs *fs = fp->f_fs;
long off;
- daddr_t file_block;
- daddr_t disk_block;
+ ufs_lbn_t file_block;
+ ufs2_daddr_t disk_block;
size_t block_size;
int rc;
off = blkoff(fs, fp->f_seekp);
file_block = lblkno(fs, fp->f_seekp);
- block_size = dblksize(fs, &fp->f_di, file_block);
+ block_size = sblksize(fs, DIP(fp, di_size), file_block);
if (file_block != fp->f_buf_blkno) {
if (fp->f_buf == (char *)0)
@@ -422,8 +435,8 @@ buf_read_file(f, buf_p, size_p)
/*
* But truncate buffer at end of file.
*/
- if (*size_p > fp->f_di.di_size - fp->f_seekp)
- *size_p = fp->f_di.di_size - fp->f_seekp;
+ if (*size_p > DIP(fp, di_size) - fp->f_seekp)
+ *size_p = DIP(fp, di_size) - fp->f_seekp;
return (0);
}
@@ -449,7 +462,7 @@ search_directory(name, f, inumber_p)
length = strlen(name);
fp->f_seekp = 0;
- while (fp->f_seekp < fp->f_di.di_size) {
+ while (fp->f_seekp < DIP(fp, di_size)) {
rc = buf_read_file(f, &buf, &buf_size);
if (rc)
return (rc);
@@ -479,6 +492,8 @@ search_directory(name, f, inumber_p)
return (ENOENT);
}
+static int sblock_try[] = SBLOCKSEARCH;
+
/*
* Open a file.
*/
@@ -492,7 +507,7 @@ ufs_open(upath, f)
ino_t inumber, parent_inumber;
struct file *fp;
struct fs *fs;
- int rc;
+ int i, rc;
size_t buf_size;
int nlinks = 0;
char namebuf[MAXPATHLEN+1];
@@ -505,28 +520,35 @@ ufs_open(upath, f)
f->f_fsdata = (void *)fp;
/* allocate space and read super block */
- fs = malloc(SBSIZE);
+ fs = malloc(SBLOCKSIZE);
fp->f_fs = fs;
twiddle();
- rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
- SBLOCK, SBSIZE, (char *)fs, &buf_size);
- if (rc)
- goto out;
-
- if (buf_size != SBSIZE || fs->fs_magic != FS_MAGIC ||
- fs->fs_bsize > MAXBSIZE || fs->fs_bsize < sizeof(struct fs)) {
+ /*
+ * Try reading the superblock in each of its possible locations.
+ */
+ for (i = 0; sblock_try[i] != -1; i++) {
+ rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
+ sblock_try[i] / DEV_BSIZE, SBLOCKSIZE,
+ (char *)fs, &buf_size);
+ if (rc)
+ goto out;
+ if ((fs->fs_magic == FS_UFS1_MAGIC ||
+ (fs->fs_magic == FS_UFS2_MAGIC &&
+ fs->fs_sblockloc == numfrags(fs, sblock_try[i]))) &&
+ buf_size == SBLOCKSIZE &&
+ fs->fs_bsize <= MAXBSIZE &&
+ fs->fs_bsize >= sizeof(struct fs))
+ break;
+ }
+ if (sblock_try[i] == -1) {
rc = EINVAL;
goto out;
}
-#ifdef COMPAT_UFS
- ffs_oldfscompat(fs);
-#endif
-
/*
* Calculate indirect block levels.
*/
{
- int mult;
+ ufs2_daddr_t mult;
int level;
mult = 1;
@@ -558,7 +580,7 @@ ufs_open(upath, f)
/*
* Check that current node is a directory.
*/
- if ((fp->f_di.di_mode & IFMT) != IFDIR) {
+ if ((DIP(fp, di_mode) & IFMT) != IFDIR) {
rc = ENOTDIR;
goto out;
}
@@ -600,8 +622,8 @@ ufs_open(upath, f)
/*
* Check for symbolic link.
*/
- if ((fp->f_di.di_mode & IFMT) == IFLNK) {
- int link_len = fp->f_di.di_size;
+ if ((DIP(fp, di_mode) & IFMT) == IFLNK) {
+ int link_len = DIP(fp, di_size);
int len;
len = strlen(cp);
@@ -615,19 +637,22 @@ ufs_open(upath, f)
bcopy(cp, &namebuf[link_len], len + 1);
if (link_len < fs->fs_maxsymlinklen) {
- bcopy(fp->f_di.di_shortlink, namebuf,
- (unsigned) link_len);
+ if (fp->f_fs->fs_magic == FS_UFS1_MAGIC)
+ cp = (caddr_t)(fp->f_di.di1.di_db);
+ else
+ cp = (caddr_t)(fp->f_di.di2.di_db);
+ bcopy(cp, namebuf, (unsigned) link_len);
} else {
/*
* Read file for symbolic link
*/
size_t buf_size;
- daddr_t disk_block;
+ ufs2_daddr_t disk_block;
struct fs *fs = fp->f_fs;
if (!buf)
buf = malloc(fs->fs_bsize);
- rc = block_map(f, (daddr_t)0, &disk_block);
+ rc = block_map(f, (ufs2_daddr_t)0, &disk_block);
if (rc)
goto out;
@@ -715,7 +740,7 @@ ufs_read(f, start, size, resid)
char *addr = start;
while (size != 0) {
- if (fp->f_seekp >= fp->f_di.di_size)
+ if (fp->f_seekp >= DIP(fp, di_size))
break;
rc = buf_read_file(f, &buf, &buf_size);
@@ -756,7 +781,7 @@ ufs_write(f, start, size, resid)
csize = size;
while ((size != 0) && (csize != 0)) {
- if (fp->f_seekp >= fp->f_di.di_size)
+ if (fp->f_seekp >= DIP(fp, di_size))
break;
if (csize >= 512) csize = 512; /* XXX */
@@ -790,7 +815,7 @@ ufs_seek(f, offset, where)
fp->f_seekp += offset;
break;
case SEEK_END:
- fp->f_seekp = fp->f_di.di_size - offset;
+ fp->f_seekp = DIP(fp, di_size) - offset;
break;
default:
return (-1);
@@ -806,10 +831,10 @@ ufs_stat(f, sb)
struct file *fp = (struct file *)f->f_fsdata;
/* only important stuff */
- sb->st_mode = fp->f_di.di_mode;
- sb->st_uid = fp->f_di.di_uid;
- sb->st_gid = fp->f_di.di_gid;
- sb->st_size = fp->f_di.di_size;
+ sb->st_mode = DIP(fp, di_mode);
+ sb->st_uid = DIP(fp, di_uid);
+ sb->st_gid = DIP(fp, di_gid);
+ sb->st_size = DIP(fp, di_size);
return (0);
}
@@ -826,7 +851,7 @@ ufs_readdir(struct open_file *f, struct dirent *d)
* assume that a directory entry will not be split across blocks
*/
again:
- if (fp->f_seekp >= fp->f_di.di_size)
+ if (fp->f_seekp >= DIP(fp, di_size))
return (ENOENT);
error = buf_read_file(f, &buf, &buf_size);
if (error)
@@ -839,33 +864,3 @@ again:
strcpy(d->d_name, dp->d_name);
return (0);
}
-
-#ifdef COMPAT_UFS
-/*
- * Sanity checks for old file systems.
- *
- * XXX - goes away some day.
- */
-static void
-ffs_oldfscompat(fs)
- struct fs *fs;
-{
- int i;
-
- fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect); /* XXX */
- fs->fs_interleave = max(fs->fs_interleave, 1); /* XXX */
- if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
- fs->fs_nrpos = 8; /* XXX */
- if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
- quad_t sizepb = fs->fs_bsize; /* XXX */
- /* XXX */
- fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */
- for (i = 0; i < NIADDR; i++) { /* XXX */
- sizepb *= NINDIR(fs); /* XXX */
- fs->fs_maxfilesize += sizepb; /* XXX */
- } /* XXX */
- fs->fs_qbmask = ~fs->fs_bmask; /* XXX */
- fs->fs_qfmask = ~fs->fs_fmask; /* XXX */
- } /* XXX */
-}
-#endif
diff --git a/release/picobsd/build/write_mfs_in_kernel.c b/release/picobsd/build/write_mfs_in_kernel.c
index ba2fb609f3d8..06403c8573c9 100644
--- a/release/picobsd/build/write_mfs_in_kernel.c
+++ b/release/picobsd/build/write_mfs_in_kernel.c
@@ -19,8 +19,11 @@
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
+#include <sys/disklabel.h>
+#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
+static int sblock_try[] = SBLOCKSEARCH;
static int force = 0; /* don't check for zeros, may corrupt kernel */
int
@@ -29,7 +32,8 @@ main(int argc, char **argv)
unsigned char *buf_kernel, *buf_fs, *p,*q, *prog;
int fd_kernel, fd_fs, ch, errs=0;
struct stat st_kernel, st_fs;
- u_long l;
+ struct fs *fs;
+ u_long l, sboff;
prog= *argv;
while ((ch = getopt(argc, argv, "f")) != EOF)
@@ -68,17 +72,31 @@ main(int argc, char **argv)
fprintf(stderr,"MFS filesystem signature not found in %s\n",argv[1]);
exit(1);
found:
+ for (l = 0; sblock_try[l] != -1; l++) {
+ sboff = sblock_try[l];
+ fs = (struct fs *)(buf_fs + sboff);
+ if ((fs->fs_magic == FS_UFS1_MAGIC ||
+ (fs->fs_magic == FS_UFS2_MAGIC &&
+ fs->fs_sblockloc == numfrags(fs, sblock_try[l]))) &&
+ fs->fs_bsize <= MAXBSIZE &&
+ fs->fs_bsize >= sizeof(struct fs))
+ break;
+ }
+ if (sblock_try[l] == -1) {
+ fprintf(stderr, "Cannot find filesystem\n");
+ exit(2);
+ }
if (!force)
- for(l=0,q= p + SBOFF; l < st_fs.st_size - SBOFF ; l++,q++ )
+ for(l=0,q= p + sboff; l < st_fs.st_size - sboff ; l++,q++ )
if (*q)
goto fail;
- memcpy(p+SBOFF,buf_fs+SBOFF,st_fs.st_size-SBOFF);
+ memcpy(p+sboff,buf_fs+sboff,st_fs.st_size-sboff);
lseek(fd_kernel,0L,SEEK_SET);
if (st_kernel.st_size != write(fd_kernel,buf_kernel,st_kernel.st_size))
{ perror(argv[1]); exit(2); }
exit(0);
fail:
- l += SBOFF;
+ l += sboff;
fprintf(stderr,"Obstruction in kernel after %ld bytes (%ld Kbyte)\n",
l, l/1024);
fprintf(stderr,"Filesystem is %ld bytes (%ld Kbyte)\n",
diff --git a/sbin/Makefile b/sbin/Makefile
index bbd2f6b246df..dd04507e7cd0 100644
--- a/sbin/Makefile
+++ b/sbin/Makefile
@@ -18,7 +18,6 @@ SUBDIR= adjkerntz \
dump \
dumpfs \
dumpon \
- ffsinfo \
fsck \
fsck_ffs \
fsck_msdosfs \
diff --git a/sbin/badsect/badsect.c b/sbin/badsect/badsect.c
index 6094db2e0330..94f90238987f 100644
--- a/sbin/badsect/badsect.c
+++ b/sbin/badsect/badsect.c
@@ -59,8 +59,8 @@ static const char rcsid[] =
#include <sys/stat.h>
#include <sys/disklabel.h>
-#include <ufs/ffs/fs.h>
#include <ufs/ufs/dinode.h>
+#include <ufs/ffs/fs.h>
#include <err.h>
#include <dirent.h>
@@ -73,7 +73,7 @@ static const char rcsid[] =
union {
struct fs fs;
- char fsx[SBSIZE];
+ char fsx[SBLOCKSIZE];
} ufs;
#define sblock ufs.fs
union {
@@ -91,6 +91,11 @@ char buf[MAXBSIZE];
void rdfs(daddr_t, int, char *);
int chkuse(daddr_t, int);
+/*
+ * Possible superblock locations ordered from most to least likely.
+ */
+static int sblock_try[] = SBLOCKSEARCH;
+
static void
usage(void)
{
@@ -108,6 +113,7 @@ main(int argc, char *argv[])
DIR *dirp;
char name[2 * MAXPATHLEN];
char *name_dir_end;
+ int i;
if (argc < 3)
usage();
@@ -134,7 +140,19 @@ main(int argc, char *argv[])
if ((fsi = open(name, O_RDONLY)) < 0)
err(6, "%s", name);
fs = &sblock;
- rdfs(SBOFF, SBSIZE, (char *)fs);
+ for (i = 0; sblock_try[i] != -1; i++) {
+ rdfs(sblock_try[i] / dev_bsize, SBLOCKSIZE, (char *)fs);
+ if ((fs->fs_magic == FS_UFS1_MAGIC ||
+ (fs->fs_magic == FS_UFS2_MAGIC &&
+ fs->fs_sblockloc == numfrags(fs, sblock_try[i]))) &&
+ fs->fs_bsize <= MAXBSIZE &&
+ fs->fs_bsize >= sizeof(struct fs))
+ break;
+ }
+ if (sblock_try[i] == -1) {
+ printf("Cannot find filesystem\n");
+ exit(7);
+ }
dev_bsize = fs->fs_fsize / fsbtodb(fs, 1);
for (argc -= 2, argv += 2; argc > 0; argc--, argv++) {
number = atol(*argv);
diff --git a/sbin/clri/clri.c b/sbin/clri/clri.c
index 2dd6b2df6085..3a42177e95cd 100644
--- a/sbin/clri/clri.c
+++ b/sbin/clri/clri.c
@@ -61,6 +61,11 @@ static const char rcsid[] =
#include <stdio.h>
#include <unistd.h>
+/*
+ * Possible superblock locations ordered from most to least likely.
+ */
+static int sblock_try[] = SBLOCKSEARCH;
+
static void
usage(void)
{
@@ -74,13 +79,13 @@ main(argc, argv)
char *argv[];
{
struct fs *sbp;
- struct dinode *ip;
- int fd;
- struct dinode ibuf[MAXBSIZE / sizeof (struct dinode)];
+ struct ufs1_dinode *dp1;
+ struct ufs2_dinode *dp2;
+ char *ibuf[MAXBSIZE];
long generation, bsize;
off_t offset;
- int inonum;
- char *fs, sblock[SBSIZE];
+ int i, fd, inonum;
+ char *fs, sblock[SBLOCKSIZE];
if (argc < 3)
usage();
@@ -90,15 +95,23 @@ main(argc, argv)
/* get the superblock. */
if ((fd = open(fs, O_RDWR, 0)) < 0)
err(1, "%s", fs);
- if (lseek(fd, (off_t)(SBLOCK * DEV_BSIZE), SEEK_SET) < 0)
- err(1, "%s", fs);
- if (read(fd, sblock, sizeof(sblock)) != sizeof(sblock))
- errx(1, "%s: can't read superblock", fs);
-
- sbp = (struct fs *)sblock;
- if (sbp->fs_magic != FS_MAGIC)
- errx(1, "%s: superblock magic number 0x%x, not 0x%x",
- fs, sbp->fs_magic, FS_MAGIC);
+ for (i = 0; sblock_try[i] != -1; i++) {
+ if (lseek(fd, (off_t)(sblock_try[i]), SEEK_SET) < 0)
+ err(1, "%s", fs);
+ if (read(fd, sblock, sizeof(sblock)) != sizeof(sblock))
+ errx(1, "%s: can't read superblock", fs);
+ sbp = (struct fs *)sblock;
+ if ((sbp->fs_magic == FS_UFS1_MAGIC ||
+ (sbp->fs_magic == FS_UFS2_MAGIC &&
+ sbp->fs_sblockloc == numfrags(sbp, sblock_try[i]))) &&
+ sbp->fs_bsize <= MAXBSIZE &&
+ sbp->fs_bsize >= sizeof(struct fs))
+ break;
+ }
+ if (sblock_try[i] == -1) {
+ fprintf(stderr, "Cannot find filesystem\n");
+ exit(2);
+ }
bsize = sbp->fs_bsize;
/* remaining arguments are inode numbers. */
@@ -119,13 +132,25 @@ main(argc, argv)
if (read(fd, ibuf, bsize) != bsize)
err(1, "%s", fs);
- /* get the inode within the block. */
- ip = &ibuf[ino_to_fsbo(sbp, inonum)];
-
- /* clear the inode, and bump the generation count. */
- generation = ip->di_gen + 1;
- memset(ip, 0, sizeof(*ip));
- ip->di_gen = generation;
+ if (sbp->fs_magic == FS_UFS2_MAGIC) {
+ /* get the inode within the block. */
+ dp2 = &(((struct ufs2_dinode *)ibuf)
+ [ino_to_fsbo(sbp, inonum)]);
+
+ /* clear the inode, and bump the generation count. */
+ generation = dp2->di_gen + 1;
+ memset(dp2, 0, sizeof(*dp2));
+ dp2->di_gen = generation;
+ } else {
+ /* get the inode within the block. */
+ dp1 = &(((struct ufs1_dinode *)ibuf)
+ [ino_to_fsbo(sbp, inonum)]);
+
+ /* clear the inode, and bump the generation count. */
+ generation = dp1->di_gen + 1;
+ memset(dp1, 0, sizeof(*dp1));
+ dp1->di_gen = generation;
+ }
/* backup and write the block */
if (lseek(fd, (off_t)-bsize, SEEK_CUR) < 0)
diff --git a/sbin/dump/dump.h b/sbin/dump/dump.h
index 4b4275533c39..cd84596933e3 100644
--- a/sbin/dump/dump.h
+++ b/sbin/dump/dump.h
@@ -35,9 +35,6 @@
* $FreeBSD$
*/
-#define MAXINOPB (MAXBSIZE / sizeof(struct dinode))
-#define MAXNINDIR (MAXBSIZE / sizeof(ufs_daddr_t))
-
/*
* Dump maps used to describe what is to be dumped.
*/
@@ -102,22 +99,23 @@ void timeest(void);
time_t unctime(char *str);
/* mapping rouintes */
-struct dinode;
-long blockest(struct dinode *dp);
+union dinode;
+long blockest(union dinode *dp);
int mapfiles(ino_t maxino, long *tapesize);
int mapdirs(ino_t maxino, long *tapesize);
/* file dumping routines */
-void blksout(ufs_daddr_t *blkp, int frags, ino_t ino);
-void bread(ufs_daddr_t blkno, char *buf, int size);
-void dumpino(struct dinode *dp, ino_t ino);
+void ufs1_blksout(ufs1_daddr_t *blkp, int frags, ino_t ino);
+void ufs2_blksout(ufs2_daddr_t *blkp, int frags, ino_t ino);
+void bread(ufs2_daddr_t blkno, char *buf, int size);
+void dumpino(union dinode *dp, ino_t ino);
void dumpmap(char *map, int type, ino_t ino);
void writeheader(ino_t ino);
/* tape writing routines */
int alloctape(void);
void close_rewind(void);
-void dumpblock(ufs_daddr_t blkno, int size);
+void dumpblock(ufs2_daddr_t blkno, int size);
void startnewtape(int top);
void trewind(void);
void writerec(char *dp, int isspcl);
@@ -127,7 +125,7 @@ void dumpabort(int signo);
void getfstab(void);
char *rawname(char *cp);
-struct dinode *getino(ino_t inum);
+union dinode *getino(ino_t inum, int *mode);
/* rdump routines */
#ifdef RDUMP
diff --git a/sbin/dump/itime.c b/sbin/dump/itime.c
index b4c8f98feadb..c875013ec997 100644
--- a/sbin/dump/itime.c
+++ b/sbin/dump/itime.c
@@ -152,9 +152,9 @@ getdumptime(void)
continue;
if (ddp->dd_level >= level)
continue;
- if (ddp->dd_ddate <= _time32_to_time(spcl.c_ddate))
+ if (ddp->dd_ddate <= _time64_to_time(spcl.c_ddate))
continue;
- spcl.c_ddate = _time_to_time32(ddp->dd_ddate);
+ spcl.c_ddate = _time_to_time64(ddp->dd_ddate);
lastlevel = ddp->dd_level;
}
}
@@ -202,7 +202,7 @@ putdumptime(void)
found:
(void) strncpy(dtwalk->dd_name, fname, sizeof (dtwalk->dd_name));
dtwalk->dd_level = level;
- dtwalk->dd_ddate = _time32_to_time(spcl.c_date);
+ dtwalk->dd_ddate = _time64_to_time(spcl.c_date);
ITITERATE(i, dtwalk) {
dumprecout(df, dtwalk);
@@ -215,7 +215,7 @@ putdumptime(void)
if (spcl.c_date == 0) {
tmsg = "the epoch\n";
} else {
- time_t t = _time32_to_time(spcl.c_date);
+ time_t t = _time64_to_time(spcl.c_date);
tmsg = ctime(&t);
}
msg("level %c dump on %s", level, tmsg);
diff --git a/sbin/dump/main.c b/sbin/dump/main.c
index 860457b6f402..270ea81dff58 100644
--- a/sbin/dump/main.c
+++ b/sbin/dump/main.c
@@ -68,10 +68,6 @@ static const char rcsid[] =
#include "dump.h"
#include "pathnames.h"
-#ifndef SBOFF
-#define SBOFF (SBLOCK * DEV_BSIZE)
-#endif
-
int notify = 0; /* notify operator flag */
int blockswritten = 0; /* number of blocks written on current tape */
int tapeno = 0; /* current tape number */
@@ -83,6 +79,11 @@ long dev_bsize = 1; /* recalculated below */
long blocksperfile; /* output blocks per file */
char *host = NULL; /* remote host (if any) */
+/*
+ * Possible superblock locations ordered from most to least likely.
+ */
+static int sblock_try[] = SBLOCKSEARCH;
+
static long numarg(const char *, long, long);
static void obsolete(int *, char **[]);
static void usage(void) __dead2;
@@ -93,17 +94,17 @@ main(int argc, char *argv[])
struct stat sb;
ino_t ino;
int dirty;
- struct dinode *dp;
+ union dinode *dp;
struct fstab *dt;
char *map;
- int ch;
+ int ch, mode;
int i, anydirskipped, bflag = 0, Tflag = 0, honorlevel = 1;
int just_estimate = 0;
ino_t maxino;
char *tmsg;
time_t t;
- spcl.c_date = _time_to_time32(time(NULL));
+ spcl.c_date = _time_to_time64(time(NULL));
tsize = 0; /* Default later, based on 'c' option for cart tapes */
if ((tape = getenv("TAPE")) == NULL)
@@ -316,14 +317,14 @@ main(int argc, char *argv[])
if (spcl.c_date == 0) {
tmsg = "the epoch\n";
} else {
- time_t t = _time32_to_time(spcl.c_date);
+ time_t t = _time64_to_time(spcl.c_date);
tmsg = ctime(&t);
}
msg("Date of this level %c dump: %s", level, tmsg);
if (spcl.c_ddate == 0) {
tmsg = "the epoch\n";
} else {
- time_t t = _time32_to_time(spcl.c_ddate);
+ time_t t = _time64_to_time(spcl.c_ddate);
tmsg = ctime(&t);
}
msg("Date of last level %c dump: %s", lastlevel, tmsg);
@@ -343,9 +344,18 @@ main(int argc, char *argv[])
errx(X_STARTUP, "%s: unknown filesystem", disk);
sync();
sblock = (struct fs *)sblock_buf;
- bread(SBOFF, (char *) sblock, SBSIZE);
- if (sblock->fs_magic != FS_MAGIC)
- quit("bad sblock magic number\n");
+ for (i = 0; sblock_try[i] != -1; i++) {
+ bread(sblock_try[i] >> dev_bshift, (char *) sblock, SBLOCKSIZE);
+ if ((sblock->fs_magic == FS_UFS1_MAGIC ||
+ (sblock->fs_magic == FS_UFS2_MAGIC &&
+ sblock->fs_sblockloc ==
+ numfrags(sblock, sblock_try[i]))) &&
+ sblock->fs_bsize <= MAXBSIZE &&
+ sblock->fs_bsize >= sizeof(struct fs))
+ break;
+ }
+ if (sblock_try[i] == -1)
+ quit("Cannot find filesystem superblock\n");
dev_bsize = sblock->fs_fsize / fsbtodb(sblock, 1);
dev_bshift = ffs(dev_bsize) - 1;
if (dev_bsize != (1 << dev_bshift))
@@ -353,10 +363,6 @@ main(int argc, char *argv[])
tp_bshift = ffs(TP_BSIZE) - 1;
if (TP_BSIZE != (1 << tp_bshift))
quit("TP_BSIZE (%d) is not a power of 2", TP_BSIZE);
-#ifdef FS_44INODEFMT
- if (sblock->fs_inodefmt >= FS_44INODEFMT)
- spcl.c_flags |= DR_NEWINODEFMT;
-#endif
maxino = sblock->fs_ipg * sblock->fs_ncg;
mapsize = roundup(howmany(maxino, NBBY), TP_BSIZE);
usedinomap = (char *)calloc((unsigned) mapsize, sizeof(char));
@@ -456,8 +462,8 @@ main(int argc, char *argv[])
/*
* Skip directory inodes deleted and maybe reallocated
*/
- dp = getino(ino);
- if ((dp->di_mode & IFMT) != IFDIR)
+ dp = getino(ino, &mode);
+ if (mode != IFDIR)
continue;
(void)dumpino(dp, ino);
}
@@ -466,8 +472,6 @@ main(int argc, char *argv[])
setproctitle("%s: pass 4: regular files", disk);
msg("dumping (Pass IV) [regular files]\n");
for (map = dumpinomap, ino = 1; ino < maxino; ino++) {
- int mode;
-
if (((ino - 1) % NBBY) == 0) /* map is offset by 1 */
dirty = *map++;
else
@@ -477,8 +481,7 @@ main(int argc, char *argv[])
/*
* Skip inodes deleted and reallocated as directories.
*/
- dp = getino(ino);
- mode = dp->di_mode & IFMT;
+ dp = getino(ino, &mode);
if (mode == IFDIR)
continue;
(void)dumpino(dp, ino);
@@ -489,9 +492,9 @@ main(int argc, char *argv[])
for (i = 0; i < ntrec; i++)
writeheader(maxino - 1);
if (pipeout)
- msg("DUMP: %ld tape blocks\n", spcl.c_tapea);
+ msg("DUMP: %qd tape blocks\n", spcl.c_tapea);
else
- msg("DUMP: %ld tape blocks on %d volume%s\n",
+ msg("DUMP: %qd tape blocks on %d volume%s\n",
spcl.c_tapea, spcl.c_volume,
(spcl.c_volume == 1) ? "" : "s");
@@ -499,7 +502,7 @@ main(int argc, char *argv[])
if (tend_writing - tstart_writing == 0)
msg("finished in less than a second\n");
else
- msg("finished in %d seconds, throughput %d KBytes/sec\n",
+ msg("finished in %d seconds, throughput %qd KBytes/sec\n",
tend_writing - tstart_writing,
spcl.c_tapea / (tend_writing - tstart_writing));
diff --git a/sbin/dump/optr.c b/sbin/dump/optr.c
index b0ff473482ca..5fa1a02eee9b 100644
--- a/sbin/dump/optr.c
+++ b/sbin/dump/optr.c
@@ -44,6 +44,8 @@ static const char rcsid[] =
#include <sys/wait.h>
#include <sys/time.h>
+#include <ufs/ufs/dinode.h>
+
#include <errno.h>
#include <fstab.h>
#include <grp.h>
diff --git a/sbin/dump/tape.c b/sbin/dump/tape.c
index 215d73b26c50..d13142e0013e 100644
--- a/sbin/dump/tape.c
+++ b/sbin/dump/tape.c
@@ -62,7 +62,7 @@ static const char rcsid[] =
#include "dump.h"
int writesize; /* size of malloc()ed buffer for tape */
-long lastspclrec = -1; /* tape block number of last written header */
+int64_t lastspclrec = -1; /* tape block number of last written header */
int trecno = 0; /* next record to write in current block */
extern long blocksperfile; /* number of blocks per output file */
long blocksthisvol; /* number of blocks on current output file */
@@ -87,21 +87,21 @@ static void rollforward(void);
* The following structure defines the instruction packets sent to slaves.
*/
struct req {
- ufs_daddr_t dblk;
+ ufs2_daddr_t dblk;
int count;
};
int reqsiz;
#define SLAVES 3 /* 1 slave writing, 1 reading, 1 for slack */
struct slave {
- int tapea; /* header number at start of this chunk */
+ int64_t tapea; /* header number at start of this chunk */
+ int64_t firstrec; /* record number of this block */
int count; /* count to next header (used for TS_TAPE */
/* after EOT) */
int inode; /* inode that we are currently dealing with */
int fd; /* FD for this slave */
int pid; /* PID for this slave */
int sent; /* 1 == we've sent this slave requests */
- int firstrec; /* record number of this block */
char (*tblock)[TP_BSIZE]; /* buffer for data blocks */
struct req *req; /* buffer for requests */
} slaves[SLAVES+1];
@@ -161,7 +161,7 @@ void
writerec(char *dp, int isspcl)
{
- slp->req[trecno].dblk = (ufs_daddr_t)0;
+ slp->req[trecno].dblk = (ufs2_daddr_t)0;
slp->req[trecno].count = 1;
/* Can't do a structure assignment due to alignment problems */
bcopy(dp, *(nextblock)++, sizeof (union u_spcl));
@@ -174,9 +174,10 @@ writerec(char *dp, int isspcl)
}
void
-dumpblock(ufs_daddr_t blkno, int size)
+dumpblock(ufs2_daddr_t blkno, int size)
{
- int avail, tpblks, dblkno;
+ int avail, tpblks;
+ ufs2_daddr_t dblkno;
dblkno = fsbtodb(sblock, blkno);
tpblks = size >> tp_bshift;
@@ -226,7 +227,7 @@ static void
flushtape(void)
{
int i, blks, got;
- long lastfirstrec;
+ int64_t lastfirstrec;
int siz = (char *)nextblock - (char *)slp->req;
@@ -385,7 +386,8 @@ rollforward(void)
{
struct req *p, *q, *prev;
struct slave *tslp;
- int i, size, savedtapea, got;
+ int i, size, got;
+ int64_t savedtapea;
union u_spcl *ntb, *otb;
tslp = &slaves[SLAVES];
ntb = (union u_spcl *)tslp->tblock[1];
@@ -618,9 +620,7 @@ restore_check_point:
spcl.c_firstrec = slp->firstrec;
spcl.c_volume++;
spcl.c_type = TS_TAPE;
- spcl.c_flags |= DR_NEWHEADER;
writeheader((ino_t)slp->inode);
- spcl.c_flags &=~ DR_NEWHEADER;
if (tapeno > 1)
msg("Volume %d begins with blocks from inode %d\n",
tapeno, slp->inode);
diff --git a/sbin/dump/traverse.c b/sbin/dump/traverse.c
index 622e32eb3998..e5842b8898a5 100644
--- a/sbin/dump/traverse.c
+++ b/sbin/dump/traverse.c
@@ -53,22 +53,25 @@ static const char rcsid[] =
#include <errno.h>
#include <string.h>
#include <unistd.h>
+#include <stdlib.h>
#include "dump.h"
+union dinode {
+ struct ufs1_dinode dp1;
+ struct ufs2_dinode dp2;
+};
+#define DIP(dp, field) \
+ ((sblock->fs_magic == FS_UFS1_MAGIC) ? \
+ (dp)->dp1.field : (dp)->dp2.field)
+
#define HASDUMPEDFILE 0x1
#define HASSUBDIRS 0x2
-#ifdef FS_44INODEFMT
-typedef quad_t fsizeT;
-#else
-typedef long fsizeT;
-#endif
-
-static int dirindir(ino_t ino, ufs_daddr_t blkno, int level, long *size,
+static int dirindir(ino_t ino, ufs2_daddr_t blkno, int level, long *size,
long *tapesize, int nodump);
-static void dmpindir(ino_t ino, ufs_daddr_t blk, int level, fsizeT *size);
-static int searchdir(ino_t ino, ufs_daddr_t blkno, long size, long filesize,
+static void dmpindir(ino_t ino, ufs2_daddr_t blk, int level, off_t *size);
+static int searchdir(ino_t ino, ufs2_daddr_t blkno, long size, long filesize,
long *tapesize, int nodump);
/*
@@ -79,7 +82,7 @@ static int searchdir(ino_t ino, ufs_daddr_t blkno, long size, long filesize,
* hence the estimate may be high.
*/
long
-blockest(struct dinode *dp)
+blockest(union dinode *dp)
{
long blkest, sizeest;
@@ -97,11 +100,11 @@ blockest(struct dinode *dp)
* dump blocks (sizeest vs. blkest in the indirect block
* calculation).
*/
- blkest = howmany(dbtob(dp->di_blocks), TP_BSIZE);
- sizeest = howmany(dp->di_size, TP_BSIZE);
+ blkest = howmany(dbtob(DIP(dp, di_blocks)), TP_BSIZE);
+ sizeest = howmany(DIP(dp, di_size), TP_BSIZE);
if (blkest > sizeest)
blkest = sizeest;
- if (dp->di_size > sblock->fs_bsize * NDADDR) {
+ if (DIP(dp, di_size) > sblock->fs_bsize * NDADDR) {
/* calculate the number of indirect blocks on the dump tape */
blkest +=
howmany(sizeest - NDADDR * sblock->fs_bsize / TP_BSIZE,
@@ -112,13 +115,13 @@ blockest(struct dinode *dp)
/* Auxiliary macro to pick up files changed since previous dump. */
#define CHANGEDSINCE(dp, t) \
- ((dp)->di_mtime >= (t) || (dp)->di_ctime >= (t))
+ (DIP(dp, di_mtime) >= (t) || DIP(dp, di_ctime) >= (t))
/* The WANTTODUMP macro decides whether a file should be dumped. */
#ifdef UF_NODUMP
#define WANTTODUMP(dp) \
(CHANGEDSINCE(dp, spcl.c_ddate) && \
- (nonodump || ((dp)->di_flags & UF_NODUMP) != UF_NODUMP))
+ (nonodump || (DIP(dp, di_flags) & UF_NODUMP) != UF_NODUMP))
#else
#define WANTTODUMP(dp) CHANGEDSINCE(dp, spcl.c_ddate)
#endif
@@ -135,12 +138,12 @@ mapfiles(ino_t maxino, long *tapesize)
{
int mode;
ino_t ino;
- struct dinode *dp;
+ union dinode *dp;
int anydirskipped = 0;
for (ino = ROOTINO; ino < maxino; ino++) {
- dp = getino(ino);
- if ((mode = (dp->di_mode & IFMT)) == 0)
+ dp = getino(ino, &mode);
+ if (mode == 0)
continue;
/*
* Everything must go in usedinomap so that a check
@@ -160,7 +163,7 @@ mapfiles(ino_t maxino, long *tapesize)
continue;
}
if (mode == IFDIR) {
- if (!nonodump && (dp->di_flags & UF_NODUMP))
+ if (!nonodump && (DIP(dp, di_flags) & UF_NODUMP))
CLRINO(ino, usedinomap);
anydirskipped = 1;
}
@@ -188,11 +191,11 @@ mapfiles(ino_t maxino, long *tapesize)
int
mapdirs(ino_t maxino, long *tapesize)
{
- struct dinode *dp;
+ union dinode *dp;
int i, isdir, nodump;
char *map;
ino_t ino;
- struct dinode di;
+ union dinode di;
long filesize;
int ret, change = 0;
@@ -212,23 +215,29 @@ mapdirs(ino_t maxino, long *tapesize)
nodump = !nonodump && (TSTINO(ino, usedinomap) == 0);
if ((isdir & 1) == 0 || (TSTINO(ino, dumpinomap) && !nodump))
continue;
- dp = getino(ino);
- di = *dp; /* inode buf may change in searchdir(). */
- filesize = di.di_size;
+ dp = getino(ino, &i);
+ /*
+ * inode buf may change in searchdir().
+ */
+ if (sblock->fs_magic == FS_UFS1_MAGIC)
+ di.dp1 = dp->dp1;
+ else
+ di.dp2 = dp->dp2;
+ filesize = DIP(&di, di_size);
for (ret = 0, i = 0; filesize > 0 && i < NDADDR; i++) {
- if (di.di_db[i] != 0)
- ret |= searchdir(ino, di.di_db[i],
- (long)dblksize(sblock, dp, i),
- filesize, tapesize, nodump);
+ if (DIP(&di, di_db[i]) != 0)
+ ret |= searchdir(ino, DIP(&di, di_db[i]),
+ (long)sblksize(sblock, DIP(dp, di_size), i),
+ filesize, tapesize, nodump);
if (ret & HASDUMPEDFILE)
filesize = 0;
else
filesize -= sblock->fs_bsize;
}
for (i = 0; filesize > 0 && i < NIADDR; i++) {
- if (di.di_ib[i] == 0)
+ if (DIP(&di, di_ib[i]) == 0)
continue;
- ret |= dirindir(ino, di.di_ib[i], i, &filesize,
+ ret |= dirindir(ino, DIP(&di, di_ib[i]), i, &filesize,
tapesize, nodump);
}
if (ret & HASDUMPEDFILE) {
@@ -256,17 +265,27 @@ mapdirs(ino_t maxino, long *tapesize)
* require the directory to be dumped.
*/
static int
-dirindir(ino_t ino, ufs_daddr_t blkno, int ind_level, long *filesize,
- long *tapesize, int nodump)
+dirindir(
+ ino_t ino,
+ ufs2_daddr_t blkno,
+ int ind_level,
+ long *filesize,
+ long *tapesize,
+ int nodump)
{
int ret = 0;
int i;
- ufs_daddr_t idblk[MAXNINDIR];
+ static caddr_t idblk;
- bread(fsbtodb(sblock, blkno), (char *)idblk, (int)sblock->fs_bsize);
+ if (idblk == NULL && (idblk = malloc(sblock->fs_bsize)) == NULL)
+ quit("dirindir: cannot allocate indirect memory.\n");
+ bread(fsbtodb(sblock, blkno), idblk, (int)sblock->fs_bsize);
if (ind_level <= 0) {
for (i = 0; *filesize > 0 && i < NINDIR(sblock); i++) {
- blkno = idblk[i];
+ if (sblock->fs_magic == FS_UFS1_MAGIC)
+ blkno = ((ufs1_daddr_t *)idblk)[i];
+ else
+ blkno = ((ufs2_daddr_t *)idblk)[i];
if (blkno != 0)
ret |= searchdir(ino, blkno, sblock->fs_bsize,
*filesize, tapesize, nodump);
@@ -279,7 +298,10 @@ dirindir(ino_t ino, ufs_daddr_t blkno, int ind_level, long *filesize,
}
ind_level--;
for (i = 0; *filesize > 0 && i < NINDIR(sblock); i++) {
- blkno = idblk[i];
+ if (sblock->fs_magic == FS_UFS1_MAGIC)
+ blkno = ((ufs1_daddr_t *)idblk)[i];
+ else
+ blkno = ((ufs2_daddr_t *)idblk)[i];
if (blkno != 0)
ret |= dirindir(ino, blkno, ind_level, filesize,
tapesize, nodump);
@@ -293,14 +315,22 @@ dirindir(ino_t ino, ufs_daddr_t blkno, int ind_level, long *filesize,
* contains any subdirectories.
*/
static int
-searchdir(ino_t ino, ufs_daddr_t blkno, long size, long filesize,
- long *tapesize, int nodump)
+searchdir(
+ ino_t ino,
+ ufs2_daddr_t blkno,
+ long size,
+ long filesize,
+ long *tapesize,
+ int nodump)
{
+ int mode;
struct direct *dp;
- struct dinode *ip;
+ union dinode *ip;
long loc, ret = 0;
- char dblk[MAXBSIZE];
+ static caddr_t dblk;
+ if (dblk == NULL && (dblk = malloc(sblock->fs_bsize)) == NULL)
+ quit("searchdir: cannot allocate indirect memory.\n");
bread(fsbtodb(sblock, blkno), dblk, (int)size);
if (filesize < size)
size = filesize;
@@ -320,7 +350,7 @@ searchdir(ino_t ino, ufs_daddr_t blkno, long size, long filesize,
continue;
}
if (nodump) {
- ip = getino(dp->d_ino);
+ ip = getino(dp->d_ino, &mode);
if (TSTINO(dp->d_ino, dumpinomap)) {
CLRINO(dp->d_ino, dumpinomap);
*tapesize -= blockest(ip);
@@ -329,7 +359,7 @@ searchdir(ino_t ino, ufs_daddr_t blkno, long size, long filesize,
* Add back to dumpdirmap and remove from usedinomap
* to propagate nodump.
*/
- if ((ip->di_mode & IFMT) == IFDIR) {
+ if (mode == IFDIR) {
SETINO(dp->d_ino, dumpdirmap);
CLRINO(dp->d_ino, usedinomap);
ret |= HASSUBDIRS;
@@ -356,10 +386,12 @@ searchdir(ino_t ino, ufs_daddr_t blkno, long size, long filesize,
* Dump the contents of an inode to tape.
*/
void
-dumpino(struct dinode *dp, ino_t ino)
+dumpino(union dinode *dp, ino_t ino)
{
+ struct ufs1_dinode *dp1;
+ struct ufs2_dinode *dp2;
int ind_level, cnt;
- fsizeT size;
+ off_t size;
char buf[TP_BSIZE];
if (newtape) {
@@ -367,10 +399,36 @@ dumpino(struct dinode *dp, ino_t ino)
dumpmap(dumpinomap, TS_BITS, ino);
}
CLRINO(ino, dumpinomap);
- spcl.c_dinode = *dp;
+ if (sblock->fs_magic == FS_UFS1_MAGIC) {
+ spcl.c_mode = dp->dp1.di_mode;
+ spcl.c_size = dp->dp1.di_size;
+ spcl.c_atime = _time32_to_time(dp->dp1.di_atime);
+ spcl.c_atimensec = dp->dp1.di_atimensec;
+ spcl.c_mtime = _time32_to_time(dp->dp1.di_mtime);
+ spcl.c_mtimensec = dp->dp1.di_mtimensec;
+ spcl.c_createtime = 0;
+ spcl.c_createtimensec = 0;
+ spcl.c_rdev = dp->dp1.di_rdev;
+ spcl.c_file_flags = dp->dp1.di_flags;
+ spcl.c_uid = dp->dp1.di_uid;
+ spcl.c_gid = dp->dp1.di_gid;
+ } else {
+ spcl.c_mode = dp->dp2.di_mode;
+ spcl.c_size = dp->dp2.di_size;
+ spcl.c_atime = _time64_to_time(dp->dp2.di_atime);
+ spcl.c_atimensec = dp->dp2.di_atimensec;
+ spcl.c_mtime = _time64_to_time(dp->dp2.di_mtime);
+ spcl.c_mtimensec = dp->dp2.di_mtimensec;
+ spcl.c_createtime = _time64_to_time(dp->dp2.di_createtime);
+ spcl.c_createtimensec = dp->dp2.di_creatensec;
+ spcl.c_rdev = dp->dp2.di_rdev;
+ spcl.c_file_flags = dp->dp2.di_flags;
+ spcl.c_uid = dp->dp2.di_uid;
+ spcl.c_gid = dp->dp2.di_gid;
+ }
spcl.c_type = TS_INODE;
spcl.c_count = 0;
- switch (dp->di_mode & S_IFMT) {
+ switch (DIP(dp, di_mode) & S_IFMT) {
case 0:
/*
@@ -383,13 +441,18 @@ dumpino(struct dinode *dp, ino_t ino)
* Check for short symbolic link.
*/
#ifdef FS_44INODEFMT
- if (dp->di_size > 0 &&
- dp->di_size < sblock->fs_maxsymlinklen) {
+ if (DIP(dp, di_size) > 0 &&
+ DIP(dp, di_size) < sblock->fs_maxsymlinklen) {
spcl.c_addr[0] = 1;
spcl.c_count = 1;
writeheader(ino);
- memmove(buf, dp->di_shortlink, (u_long)dp->di_size);
- buf[dp->di_size] = '\0';
+ if (sblock->fs_magic == FS_UFS1_MAGIC)
+ memmove(buf, (caddr_t)dp->dp1.di_db,
+ (u_long)DIP(dp, di_size));
+ else
+ memmove(buf, (caddr_t)dp->dp2.di_db,
+ (u_long)DIP(dp, di_size));
+ buf[DIP(dp, di_size)] = '\0';
writerec(buf, 0);
return;
}
@@ -398,7 +461,7 @@ dumpino(struct dinode *dp, ino_t ino)
case S_IFDIR:
case S_IFREG:
- if (dp->di_size > 0)
+ if (DIP(dp, di_size) > 0)
break;
/* fall through */
@@ -410,18 +473,22 @@ dumpino(struct dinode *dp, ino_t ino)
return;
default:
- msg("Warning: undefined file type 0%o\n", dp->di_mode & IFMT);
+ msg("Warning: undefined file type 0%o\n",
+ DIP(dp, di_mode) & IFMT);
return;
}
- if (dp->di_size > NDADDR * sblock->fs_bsize)
+ if (DIP(dp, di_size) > NDADDR * sblock->fs_bsize)
cnt = NDADDR * sblock->fs_frag;
else
- cnt = howmany(dp->di_size, sblock->fs_fsize);
- blksout(&dp->di_db[0], cnt, ino);
- if ((size = dp->di_size - NDADDR * sblock->fs_bsize) <= 0)
+ cnt = howmany(DIP(dp, di_size), sblock->fs_fsize);
+ if (sblock->fs_magic == FS_UFS1_MAGIC)
+ ufs1_blksout(&dp->dp1.di_db[0], cnt, ino);
+ else
+ ufs2_blksout(&dp->dp2.di_db[0], cnt, ino);
+ if ((size = DIP(dp, di_size) - NDADDR * sblock->fs_bsize) <= 0)
return;
for (ind_level = 0; ind_level < NIADDR; ind_level++) {
- dmpindir(ino, dp->di_ib[ind_level], ind_level, &size);
+ dmpindir(ino, DIP(dp, di_ib[ind_level]), ind_level, &size);
if (size <= 0)
return;
}
@@ -431,13 +498,15 @@ dumpino(struct dinode *dp, ino_t ino)
* Read indirect blocks, and pass the data blocks to be dumped.
*/
static void
-dmpindir(ino_t ino, ufs_daddr_t blk, int ind_level, fsizeT *size)
+dmpindir(ino_t ino, ufs2_daddr_t blk, int ind_level, off_t *size)
{
int i, cnt;
- ufs_daddr_t idblk[MAXNINDIR];
+ static caddr_t idblk;
+ if (idblk == NULL && (idblk = malloc(sblock->fs_bsize)) == NULL)
+ quit("dmpindir: cannot allocate indirect memory.\n");
if (blk != 0)
- bread(fsbtodb(sblock, blk), (char *)idblk, (int) sblock->fs_bsize);
+ bread(fsbtodb(sblock, blk), idblk, (int) sblock->fs_bsize);
else
memset(idblk, 0, (int)sblock->fs_bsize);
if (ind_level <= 0) {
@@ -446,12 +515,20 @@ dmpindir(ino_t ino, ufs_daddr_t blk, int ind_level, fsizeT *size)
else
cnt = NINDIR(sblock) * sblock->fs_frag;
*size -= NINDIR(sblock) * sblock->fs_bsize;
- blksout(&idblk[0], cnt, ino);
+ if (sblock->fs_magic == FS_UFS1_MAGIC)
+ ufs1_blksout((ufs1_daddr_t *)idblk, cnt, ino);
+ else
+ ufs2_blksout((ufs2_daddr_t *)idblk, cnt, ino);
return;
}
ind_level--;
for (i = 0; i < NINDIR(sblock); i++) {
- dmpindir(ino, idblk[i], ind_level, size);
+ if (sblock->fs_magic == FS_UFS1_MAGIC)
+ dmpindir(ino, ((ufs1_daddr_t *)idblk)[i], ind_level,
+ size);
+ else
+ dmpindir(ino, ((ufs2_daddr_t *)idblk)[i], ind_level,
+ size);
if (*size <= 0)
return;
}
@@ -461,9 +538,44 @@ dmpindir(ino_t ino, ufs_daddr_t blk, int ind_level, fsizeT *size)
* Collect up the data into tape record sized buffers and output them.
*/
void
-blksout(ufs_daddr_t *blkp, int frags, ino_t ino)
+ufs1_blksout(ufs1_daddr_t *blkp, int frags, ino_t ino)
{
- ufs_daddr_t *bp;
+ ufs1_daddr_t *bp;
+ int i, j, count, blks, tbperdb;
+
+ blks = howmany(frags * sblock->fs_fsize, TP_BSIZE);
+ tbperdb = sblock->fs_bsize >> tp_bshift;
+ for (i = 0; i < blks; i += TP_NINDIR) {
+ if (i + TP_NINDIR > blks)
+ count = blks;
+ else
+ count = i + TP_NINDIR;
+ for (j = i; j < count; j++)
+ if (blkp[j / tbperdb] != 0)
+ spcl.c_addr[j - i] = 1;
+ else
+ spcl.c_addr[j - i] = 0;
+ spcl.c_count = count - i;
+ writeheader(ino);
+ bp = &blkp[i / tbperdb];
+ for (j = i; j < count; j += tbperdb, bp++)
+ if (*bp != 0) {
+ if (j + tbperdb <= count)
+ dumpblock(*bp, (int)sblock->fs_bsize);
+ else
+ dumpblock(*bp, (count - j) * TP_BSIZE);
+ }
+ spcl.c_type = TS_ADDR;
+ }
+}
+
+/*
+ * Collect up the data into tape record sized buffers and output them.
+ */
+void
+ufs2_blksout(ufs2_daddr_t *blkp, int frags, ino_t ino)
+{
+ ufs2_daddr_t *bp;
int i, j, count, blks, tbperdb;
blks = howmany(frags * sblock->fs_fsize, TP_BSIZE);
@@ -517,7 +629,7 @@ writeheader(ino_t ino)
int32_t sum, cnt, *lp;
spcl.c_inumber = ino;
- spcl.c_magic = NFS_MAGIC;
+ spcl.c_magic = FS_UFS2_MAGIC;
spcl.c_checksum = 0;
lp = (int32_t *)&spcl;
sum = 0;
@@ -532,20 +644,32 @@ writeheader(ino_t ino)
writerec((char *)&spcl, 1);
}
-struct dinode *
-getino(ino_t inum)
+union dinode *
+getino(ino_t inum, int *modep)
{
- static ufs_daddr_t minino, maxino;
- static struct dinode inoblock[MAXINOPB];
+ static ino_t minino, maxino;
+ static caddr_t inoblock;
+ struct ufs1_dinode *dp1;
+ struct ufs2_dinode *dp2;
+ if (inoblock == NULL && (inoblock = malloc(sblock->fs_bsize)) == NULL)
+ quit("cannot allocate inode memory.\n");
curino = inum;
if (inum >= minino && inum < maxino)
- return (&inoblock[inum - minino]);
- bread(fsbtodb(sblock, ino_to_fsba(sblock, inum)), (char *)inoblock,
+ goto gotit;
+ bread(fsbtodb(sblock, ino_to_fsba(sblock, inum)), inoblock,
(int)sblock->fs_bsize);
minino = inum - (inum % INOPB(sblock));
maxino = minino + INOPB(sblock);
- return (&inoblock[inum - minino]);
+gotit:
+ if (sblock->fs_magic == FS_UFS1_MAGIC) {
+ dp1 = &((struct ufs1_dinode *)inoblock)[inum - minino];
+ *modep = (dp1->di_mode & IFMT);
+ return ((union dinode *)dp1);
+ }
+ dp2 = &((struct ufs2_dinode *)inoblock)[inum - minino];
+ *modep = (dp2->di_mode & IFMT);
+ return ((union dinode *)dp2);
}
/*
@@ -558,7 +682,7 @@ int breaderrors = 0;
#define BREADEMAX 32
void
-bread(ufs_daddr_t blkno, char *buf, int size)
+bread(ufs2_daddr_t blkno, char *buf, int size)
{
int cnt, i;
diff --git a/sbin/dumpfs/dumpfs.c b/sbin/dumpfs/dumpfs.c
index dd18313337db..aae7e1e97db7 100644
--- a/sbin/dumpfs/dumpfs.c
+++ b/sbin/dumpfs/dumpfs.c
@@ -1,4 +1,16 @@
/*
+ * Copyright (c) 2002 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by Marshall
+ * Kirk McKusick and Network Associates Laboratories, the Security
+ * Research Division of Network Associates, Inc. under DARPA/SPAWAR
+ * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
+ * research program
+ *
+ * Copyright (c) 1982, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
* Copyright (c) 1983, 1992, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -49,6 +61,7 @@ static const char rcsid[] =
#include <sys/time.h>
#include <sys/disklabel.h>
+#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#include <err.h>
@@ -72,6 +85,11 @@ union {
long dev_bsize = 1;
+/*
+ * Possible superblock locations ordered from most to least likely.
+ */
+static int sblock_try[] = SBLOCKSEARCH;
+
int dumpfs(const char *);
int dumpcg(const char *, int, int);
void pbits(void *, int);
@@ -107,67 +125,94 @@ int
dumpfs(const char *name)
{
ssize_t n;
+ time_t time;
+ int64_t fssize;
int fd, c, i, j, k, size;
if ((fd = open(name, O_RDONLY, 0)) < 0)
goto err;
- if (lseek(fd, (off_t)SBOFF, SEEK_SET) == (off_t)-1)
- goto err;
- if ((n = read(fd, &afs, SBSIZE)) == -1)
- goto err;
-
- if (n != SBSIZE) {
- warnx("%s: non-existent or truncated superblock, skipped",
- name);
- (void)close(fd);
- return (1);
+ for (i = 0; sblock_try[i] != -1; i++) {
+ if (lseek(fd, (off_t)sblock_try[i], SEEK_SET) == (off_t)-1)
+ goto err;
+ if ((n = read(fd, &afs, SBLOCKSIZE)) == -1)
+ goto err;
+ if ((afs.fs_magic == FS_UFS1_MAGIC ||
+ (afs.fs_magic == FS_UFS2_MAGIC &&
+ afs.fs_sblockloc == numfrags(&afs, sblock_try[i]))) &&
+ afs.fs_bsize <= MAXBSIZE &&
+ afs.fs_bsize >= sizeof(struct fs))
+ break;
+ }
+ if (sblock_try[i] == -1) {
+ fprintf(stderr, "Cannot find filesystem superblock\n");
+ return (1);
}
- if (afs.fs_magic != FS_MAGIC) {
- warnx("%s: superblock has bad magic number, skipped", name);
- (void)close(fd);
- return (1);
- }
- if (afs.fs_postblformat == FS_42POSTBLFMT)
- afs.fs_nrpos = 8;
dev_bsize = afs.fs_fsize / fsbtodb(&afs, 1);
- printf("magic\t%x\ttime\t%s", afs.fs_magic,
- ctime(&afs.fs_time));
- printf("id\t[ %x %x ]\n", afs.fs_id[0], afs.fs_id[1]);
- printf("cylgrp\t%s\tinodes\t%s\n",
- afs.fs_postblformat == FS_42POSTBLFMT ? "static" : "dynamic",
- afs.fs_inodefmt < FS_44INODEFMT ? "4.2/4.3BSD" : "4.4BSD");
- printf("nbfree\t%d\tndir\t%d\tnifree\t%d\tnffree\t%d\n",
- afs.fs_cstotal.cs_nbfree, afs.fs_cstotal.cs_ndir,
- afs.fs_cstotal.cs_nifree, afs.fs_cstotal.cs_nffree);
- printf("ncg\t%d\tncyl\t%d\tsize\t%d\tblocks\t%d\n",
- afs.fs_ncg, afs.fs_ncyl, afs.fs_size, afs.fs_dsize);
+ if (afs.fs_magic == FS_UFS2_MAGIC) {
+ fssize = afs.fs_size;
+ time = afs.fs_time;
+ printf("magic\t%x (UFS2)\ttime\t%s",
+ afs.fs_magic, ctime(&time));
+ printf("offset\t%qd\tid\t[ %x %x ]\n",
+ afs.fs_sblockloc, afs.fs_id[0], afs.fs_id[1]);
+ printf("ncg\t%d\tsize\t%qd\tblocks\t%d\n",
+ afs.fs_ncg, fssize, afs.fs_dsize);
+ } else {
+ fssize = afs.fs_old_size;
+ printf("magic\t%x (UFS1)\ttime\t%s",
+ afs.fs_magic, ctime(&afs.fs_old_time));
+ printf("id\t[ %x %x ]\n", afs.fs_id[0], afs.fs_id[1]);
+ printf("ncg\t%d\tsize\t%qd\tblocks\t%d\n",
+ afs.fs_ncg, fssize, afs.fs_dsize);
+ }
printf("bsize\t%d\tshift\t%d\tmask\t0x%08x\n",
afs.fs_bsize, afs.fs_bshift, afs.fs_bmask);
printf("fsize\t%d\tshift\t%d\tmask\t0x%08x\n",
afs.fs_fsize, afs.fs_fshift, afs.fs_fmask);
printf("frag\t%d\tshift\t%d\tfsbtodb\t%d\n",
afs.fs_frag, afs.fs_fragshift, afs.fs_fsbtodb);
- printf("cpg\t%d\tbpg\t%d\tfpg\t%d\tipg\t%d\n",
- afs.fs_cpg, afs.fs_fpg / afs.fs_frag, afs.fs_fpg, afs.fs_ipg);
- printf("minfree\t%d%%\toptim\t%s\tmaxcontig %d\tmaxbpg\t%d\n",
+ printf("minfree\t%d%%\toptim\t%s\tsymlinklen %d\n",
afs.fs_minfree, afs.fs_optim == FS_OPTSPACE ? "space" : "time",
- afs.fs_maxcontig, afs.fs_maxbpg);
- printf("rotdelay %dms\trps\t%d\n",
- afs.fs_rotdelay, afs.fs_rps);
- printf("ntrak\t%d\tnsect\t%d\tnpsect\t%d\tspc\t%d\n",
- afs.fs_ntrak, afs.fs_nsect, afs.fs_npsect, afs.fs_spc);
- printf("symlinklen %d\ttrackskew %d\tinterleave %d\tcontigsumsize %d\n",
- afs.fs_maxsymlinklen, afs.fs_trackskew, afs.fs_interleave,
- afs.fs_contigsumsize);
- printf("nindir\t%d\tinopb\t%d\tnspf\t%d\tmaxfilesize\t%qu\n",
- afs.fs_nindir, afs.fs_inopb, afs.fs_nspf, afs.fs_maxfilesize);
+ afs.fs_maxsymlinklen);
+ if (afs.fs_magic == FS_UFS2_MAGIC) {
+ printf("%s %d\tmaxbpg\t%d\tmaxcontig %d\tcontigsumsize %d\n",
+ "maxbsize", afs.fs_maxbsize, afs.fs_maxbpg,
+ afs.fs_maxcontig, afs.fs_contigsumsize);
+ printf("nbfree\t%qd\tndir\t%qd\tnifree\t%qd\tnffree\t%qd\n",
+ afs.fs_cstotal.cs_nbfree, afs.fs_cstotal.cs_ndir,
+ afs.fs_cstotal.cs_nifree, afs.fs_cstotal.cs_nffree);
+ printf("bpg\t%d\tfpg\t%d\tipg\t%d\n",
+ afs.fs_fpg / afs.fs_frag, afs.fs_fpg, afs.fs_ipg);
+ printf("nindir\t%d\tinopb\t%d\tmaxfilesize\t%qu\n",
+ afs.fs_nindir, afs.fs_inopb, afs.fs_maxfilesize);
+ printf("sbsize\t%d\tcgsize\t%d\tcsaddr\t%d\tcssize\t%d\n",
+ afs.fs_sbsize, afs.fs_cgsize, afs.fs_csaddr, afs.fs_cssize);
+ } else {
+ printf("maxbpg\t%d\tmaxcontig %d\tcontigsumsize %d\n",
+ afs.fs_maxbpg, afs.fs_maxcontig, afs.fs_contigsumsize);
+ printf("nbfree\t%d\tndir\t%d\tnifree\t%d\tnffree\t%d\n",
+ afs.fs_old_cstotal.cs_nbfree, afs.fs_old_cstotal.cs_ndir,
+ afs.fs_old_cstotal.cs_nifree, afs.fs_old_cstotal.cs_nffree);
+ printf("cpg\t%d\tbpg\t%d\tfpg\t%d\tipg\t%d\n",
+ afs.fs_old_cpg, afs.fs_fpg / afs.fs_frag, afs.fs_fpg,
+ afs.fs_ipg);
+ printf("nindir\t%d\tinopb\t%d\tnspf\t%d\tmaxfilesize\t%qu\n",
+ afs.fs_nindir, afs.fs_inopb, afs.fs_old_nspf,
+ afs.fs_maxfilesize);
+ printf("sbsize\t%d\tcgsize\t%d\tcgoffset %d\tcgmask\t0x%08x\n",
+ afs.fs_sbsize, afs.fs_cgsize, afs.fs_old_cgoffset,
+ afs.fs_old_cgmask);
+ printf("csaddr\t%d\tcssize\t%d\n",
+ afs.fs_old_csaddr, afs.fs_cssize);
+ printf("rotdelay %dms\trps\t%d\ttrackskew %d\tinterleave %d\n",
+ afs.fs_old_rotdelay, afs.fs_old_rps, afs.fs_old_trackskew,
+ afs.fs_old_interleave);
+ printf("nsect\t%d\tnpsect\t%d\tspc\t%d\n",
+ afs.fs_old_nsect, afs.fs_old_npsect, afs.fs_old_spc);
+ }
printf("sblkno\t%d\tcblkno\t%d\tiblkno\t%d\tdblkno\t%d\n",
afs.fs_sblkno, afs.fs_cblkno, afs.fs_iblkno, afs.fs_dblkno);
- printf("sbsize\t%d\tcgsize\t%d\tcgoffset %d\tcgmask\t0x%08x\n",
- afs.fs_sbsize, afs.fs_cgsize, afs.fs_cgoffset, afs.fs_cgmask);
- printf("csaddr\t%d\tcssize\t%d\tshift\t%d\tmask\t0x%08x\n",
- afs.fs_csaddr, afs.fs_cssize, afs.fs_csshift, afs.fs_csmask);
printf("cgrotor\t%d\tfmod\t%d\tronly\t%d\tclean\t%d\n",
afs.fs_cgrotor, afs.fs_fmod, afs.fs_ronly, afs.fs_clean);
printf("flags\t");
@@ -177,43 +222,24 @@ dumpfs(const char *name)
printf("unclean ");
if (afs.fs_flags & FS_DOSOFTDEP)
printf("soft-updates ");
- if ((afs.fs_flags & ~(FS_UNCLEAN | FS_DOSOFTDEP)) != 0)
- printf("unknown flags (%#x)",
- afs.fs_flags & ~(FS_UNCLEAN | FS_DOSOFTDEP));
+ if (afs.fs_flags & FS_NEEDSFSCK)
+ printf("needs fsck run ");
+ if (afs.fs_flags & FS_INDEXDIRS)
+ printf("indexed directories ");
+ if ((afs.fs_flags &
+ ~(FS_UNCLEAN | FS_DOSOFTDEP | FS_NEEDSFSCK | FS_INDEXDIRS)) != 0)
+ printf("unknown flags (%#x)", afs.fs_flags &
+ ~(FS_UNCLEAN | FS_DOSOFTDEP |
+ FS_NEEDSFSCK | FS_INDEXDIRS));
putchar('\n');
- if (afs.fs_cpc != 0)
- printf("blocks available in each of %d rotational positions",
- afs.fs_nrpos);
- else
- printf("(no rotational position table)\n");
- for (c = 0; c < afs.fs_cpc; c++) {
- printf("\ncylinder number %d:", c);
- for (i = 0; i < afs.fs_nrpos; i++) {
- if (fs_postbl(&afs, c)[i] == -1)
- continue;
- printf("\n position %d:\t", i);
- for (j = fs_postbl(&afs, c)[i], k = 1; ;
- j += fs_rotbl(&afs)[j], k++) {
- printf("%5d", j);
- if (k % 12 == 0)
- printf("\n\t\t");
- if (fs_rotbl(&afs)[j] == 0)
- break;
- }
- }
- }
printf("\ncs[].cs_(nbfree,ndir,nifree,nffree):\n\t");
afs.fs_csp = calloc(1, afs.fs_cssize);
- for (i = 0, j = 0; i < afs.fs_cssize; i += afs.fs_bsize, j++) {
- size = afs.fs_cssize - i < afs.fs_bsize ?
- afs.fs_cssize - i : afs.fs_bsize;
- if (lseek(fd,
- (off_t)(fsbtodb(&afs, (afs.fs_csaddr + j * afs.fs_frag))) *
- (off_t)dev_bsize, SEEK_SET) == (off_t)-1)
- goto err;
- if (read(fd, (char *)afs.fs_csp + i, size) != size)
- goto err;
- }
+ if (lseek(fd,
+ (off_t)(fsbtodb(&afs, afs.fs_csaddr)) * (off_t)dev_bsize,
+ SEEK_SET) == (off_t)-1)
+ goto err;
+ if (read(fd, (char *)afs.fs_csp, afs.fs_cssize) != afs.fs_cssize)
+ goto err;
for (i = 0; i < afs.fs_ncg; i++) {
struct csum *cs = &afs.fs_cs(&afs, i);
if (i && i % 4 == 0)
@@ -222,13 +248,14 @@ dumpfs(const char *name)
cs->cs_nbfree, cs->cs_ndir, cs->cs_nifree, cs->cs_nffree);
}
printf("\n");
- if (afs.fs_ncyl % afs.fs_cpg) {
- printf("cylinders in last group %d\n",
- i = afs.fs_ncyl % afs.fs_cpg);
- printf("blocks in last group %d\n",
- i * afs.fs_spc / NSPB(&afs));
+ if (fssize % afs.fs_fpg) {
+ if (afs.fs_magic == FS_UFS1_MAGIC)
+ printf("cylinders in last group %d\n",
+ howmany(afs.fs_old_size % afs.fs_fpg,
+ afs.fs_old_spc / afs.fs_old_nspf));
+ printf("blocks in last group %d\n\n",
+ (fssize % afs.fs_fpg) / afs.fs_frag);
}
- printf("\n");
for (i = 0; i < afs.fs_ncg; i++)
if (dumpcg(name, fd, i))
goto err;
@@ -244,6 +271,7 @@ err: if (fd != -1)
int
dumpcg(const char *name, int fd, int c)
{
+ time_t time;
off_t cur;
int i, j;
@@ -255,12 +283,19 @@ dumpcg(const char *name, int fd, int c)
warnx("%s: error reading cg", name);
return (1);
}
- printf("magic\t%x\ttell\t%qx\ttime\t%s",
- afs.fs_postblformat == FS_42POSTBLFMT ?
- ((struct ocg *)&acg)->cg_magic : acg.cg_magic,
- cur, ctime(&acg.cg_time));
- printf("cgx\t%d\tncyl\t%d\tniblk\t%d\tndblk\t%d\n",
- acg.cg_cgx, acg.cg_ncyl, acg.cg_niblk, acg.cg_ndblk);
+ if (afs.fs_magic == FS_UFS2_MAGIC) {
+ time = acg.cg_time;
+ printf("magic\t%x\ttell\t%qx\ttime\t%s",
+ acg.cg_magic, cur, ctime(&time));
+ printf("cgx\t%d\tndblk\t%d\tniblk\t%d\tinitiblk %d\n",
+ acg.cg_cgx, acg.cg_ndblk, acg.cg_niblk, acg.cg_initediblk);
+ } else {
+ printf("magic\t%x\ttell\t%qx\ttime\t%s",
+ acg.cg_magic, cur, ctime(&acg.cg_old_time));
+ printf("cgx\t%d\tncyl\t%d\tniblk\t%d\tndblk\t%d\n",
+ acg.cg_cgx, acg.cg_old_ncyl, acg.cg_old_niblk,
+ acg.cg_ndblk);
+ }
printf("nbfree\t%d\tndir\t%d\tnifree\t%d\tnffree\t%d\n",
acg.cg_cs.cs_nbfree, acg.cg_cs.cs_ndir,
acg.cg_cs.cs_nifree, acg.cg_cs.cs_nffree);
@@ -286,23 +321,10 @@ dumpcg(const char *name, int fd, int c)
pbits(cg_clustersfree(&acg), acg.cg_nclusterblks);
} else
printf("\n");
- printf("iused:\t");
+ printf("inodes used:\t");
pbits(cg_inosused(&acg), afs.fs_ipg);
- printf("free:\t");
+ printf("blks free:\t");
pbits(cg_blksfree(&acg), afs.fs_fpg);
- printf("b:\n");
- for (i = 0; i < afs.fs_cpg; i++) {
- if (cg_blktot(&acg)[i] == 0)
- continue;
- printf(" c%d:\t(%d)\t", i, cg_blktot(&acg)[i]);
- for (j = 0; j < afs.fs_nrpos; j++) {
- if (afs.fs_cpc > 0 &&
- fs_postbl(&afs, i % afs.fs_cpc)[j] == -1)
- continue;
- printf(" %d", cg_blks(&afs, &acg, i)[j]);
- }
- printf("\n");
- }
return (0);
};
diff --git a/sbin/fsck_ffs/dir.c b/sbin/fsck_ffs/dir.c
index 9a3eee42f508..7ab051d8bd2b 100644
--- a/sbin/fsck_ffs/dir.c
+++ b/sbin/fsck_ffs/dir.c
@@ -69,10 +69,10 @@ struct odirtemplate odirhead = {
static int chgino(struct inodesc *);
static int dircheck(struct inodesc *, struct direct *);
-static int expanddir(struct dinode *dp, char *name);
+static int expanddir(union dinode *dp, char *name);
static void freedir(ino_t ino, ino_t parent);
static struct direct *fsck_readdir(struct inodesc *);
-static struct bufarea *getdirblk(ufs_daddr_t blkno, long size);
+static struct bufarea *getdirblk(ufs2_daddr_t blkno, long size);
static int lftempname(char *bufp, ino_t ino);
static int mkentry(struct inodesc *);
@@ -255,7 +255,7 @@ direrror(ino_t ino, char *errmesg)
void
fileerror(ino_t cwd, ino_t ino, char *errmesg)
{
- struct dinode *dp;
+ union dinode *dp;
char pathbuf[MAXPATHLEN + 1];
pwarn("%s ", errmesg);
@@ -269,7 +269,8 @@ fileerror(ino_t cwd, ino_t ino, char *errmesg)
dp = ginode(ino);
if (ftypeok(dp))
pfatal("%s=%s\n",
- (dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE", pathbuf);
+ (DIP(dp, di_mode) & IFMT) == IFDIR ? "DIR" : "FILE",
+ pathbuf);
else
pfatal("NAME=%s\n", pathbuf);
}
@@ -277,11 +278,11 @@ fileerror(ino_t cwd, ino_t ino, char *errmesg)
void
adjust(struct inodesc *idesc, int lcnt)
{
- struct dinode *dp;
+ union dinode *dp;
int saveresolved;
dp = ginode(idesc->id_number);
- if (dp->di_nlink == lcnt) {
+ if (DIP(dp, di_nlink) == lcnt) {
/*
* If we have not hit any unresolved problems, are running
* in preen mode, and are on a filesystem using soft updates,
@@ -312,10 +313,10 @@ adjust(struct inodesc *idesc, int lcnt)
}
if (lcnt != 0) {
pwarn("LINK COUNT %s", (lfdir == idesc->id_number) ? lfname :
- ((dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE"));
+ ((DIP(dp, di_mode) & IFMT) == IFDIR ? "DIR" : "FILE"));
pinode(idesc->id_number);
printf(" COUNT %d SHOULD BE %d",
- dp->di_nlink, dp->di_nlink - lcnt);
+ DIP(dp, di_nlink), DIP(dp, di_nlink) - lcnt);
if (preen || usedsoftdep) {
if (lcnt < 0) {
printf("\n");
@@ -326,7 +327,7 @@ adjust(struct inodesc *idesc, int lcnt)
}
if (preen || reply("ADJUST") == 1) {
if (bkgrdflag == 0) {
- dp->di_nlink -= lcnt;
+ DIP(dp, di_nlink) -= lcnt;
inodirty();
} else {
cmd.value = idesc->id_number;
@@ -383,7 +384,7 @@ chgino(struct inodesc *idesc)
int
linkup(ino_t orphan, ino_t parentdir, char *name)
{
- struct dinode *dp;
+ union dinode *dp;
int lostdir;
ino_t oldlfdir;
struct inodesc idesc;
@@ -391,10 +392,10 @@ linkup(ino_t orphan, ino_t parentdir, char *name)
memset(&idesc, 0, sizeof(struct inodesc));
dp = ginode(orphan);
- lostdir = (dp->di_mode & IFMT) == IFDIR;
+ lostdir = (DIP(dp, di_mode) & IFMT) == IFDIR;
pwarn("UNREF %s ", lostdir ? "DIR" : "FILE");
pinode(orphan);
- if (preen && dp->di_size == 0)
+ if (preen && DIP(dp, di_size) == 0)
return (0);
if (cursnapshot != 0) {
pfatal("FILE LINKUP IN SNAPSHOT");
@@ -438,7 +439,7 @@ linkup(ino_t orphan, ino_t parentdir, char *name)
}
}
dp = ginode(lfdir);
- if ((dp->di_mode & IFMT) != IFDIR) {
+ if ((DIP(dp, di_mode) & IFMT) != IFDIR) {
pfatal("lost+found IS NOT A DIRECTORY");
if (reply("REALLOCATE") == 0)
return (0);
@@ -475,7 +476,7 @@ linkup(ino_t orphan, ino_t parentdir, char *name)
parentdir != (ino_t)-1)
(void)makeentry(orphan, lfdir, "..");
dp = ginode(lfdir);
- dp->di_nlink++;
+ DIP(dp, di_nlink)++;
inodirty();
inoinfo(lfdir)->ino_linkcnt++;
pwarn("DIR I=%lu CONNECTED. ", (u_long)orphan);
@@ -520,7 +521,7 @@ changeino(ino_t dir, char *name, ino_t newnum)
int
makeentry(ino_t parent, ino_t ino, char *name)
{
- struct dinode *dp;
+ union dinode *dp;
struct inodesc idesc;
char pathbuf[MAXPATHLEN + 1];
@@ -535,8 +536,8 @@ makeentry(ino_t parent, ino_t ino, char *name)
idesc.id_fix = DONTKNOW;
idesc.id_name = name;
dp = ginode(parent);
- if (dp->di_size % DIRBLKSIZ) {
- dp->di_size = roundup(dp->di_size, DIRBLKSIZ);
+ if (DIP(dp, di_size) % DIRBLKSIZ) {
+ DIP(dp, di_size) = roundup(DIP(dp, di_size), DIRBLKSIZ);
inodirty();
}
if ((ckinode(dp, &idesc) & ALTERED) != 0)
@@ -552,23 +553,24 @@ makeentry(ino_t parent, ino_t ino, char *name)
* Attempt to expand the size of a directory
*/
static int
-expanddir(struct dinode *dp, char *name)
+expanddir(union dinode *dp, char *name)
{
- ufs_daddr_t lastbn, newblk;
+ ufs2_daddr_t lastbn, newblk;
struct bufarea *bp;
char *cp, firstblk[DIRBLKSIZ];
- lastbn = lblkno(&sblock, dp->di_size);
- if (lastbn >= NDADDR - 1 || dp->di_db[lastbn] == 0 || dp->di_size == 0)
+ lastbn = lblkno(&sblock, DIP(dp, di_size));
+ if (lastbn >= NDADDR - 1 || DIP(dp, di_db[lastbn]) == 0 ||
+ DIP(dp, di_size) == 0)
return (0);
if ((newblk = allocblk(sblock.fs_frag)) == 0)
return (0);
- dp->di_db[lastbn + 1] = dp->di_db[lastbn];
- dp->di_db[lastbn] = newblk;
- dp->di_size += sblock.fs_bsize;
- dp->di_blocks += btodb(sblock.fs_bsize);
- bp = getdirblk(dp->di_db[lastbn + 1],
- (long)dblksize(&sblock, dp, lastbn + 1));
+ DIP(dp, di_db[lastbn + 1]) = DIP(dp, di_db[lastbn]);
+ DIP(dp, di_db[lastbn]) = newblk;
+ DIP(dp, di_size) += sblock.fs_bsize;
+ DIP(dp, di_blocks) += btodb(sblock.fs_bsize);
+ bp = getdirblk(DIP(dp, di_db[lastbn + 1]),
+ sblksize(&sblock, DIP(dp, di_size), lastbn + 1));
if (bp->b_errs)
goto bad;
memmove(firstblk, bp->b_un.b_buf, DIRBLKSIZ);
@@ -581,8 +583,8 @@ expanddir(struct dinode *dp, char *name)
cp += DIRBLKSIZ)
memmove(cp, &emptydir, sizeof emptydir);
dirty(bp);
- bp = getdirblk(dp->di_db[lastbn + 1],
- (long)dblksize(&sblock, dp, lastbn + 1));
+ bp = getdirblk(DIP(dp, di_db[lastbn + 1]),
+ sblksize(&sblock, DIP(dp, di_size), lastbn + 1));
if (bp->b_errs)
goto bad;
memmove(bp->b_un.b_buf, &emptydir, sizeof emptydir);
@@ -595,10 +597,10 @@ expanddir(struct dinode *dp, char *name)
inodirty();
return (1);
bad:
- dp->di_db[lastbn] = dp->di_db[lastbn + 1];
- dp->di_db[lastbn + 1] = 0;
- dp->di_size -= sblock.fs_bsize;
- dp->di_blocks -= btodb(sblock.fs_bsize);
+ DIP(dp, di_db[lastbn]) = DIP(dp, di_db[lastbn + 1]);
+ DIP(dp, di_db[lastbn + 1]) = 0;
+ DIP(dp, di_size) -= sblock.fs_bsize;
+ DIP(dp, di_blocks) -= btodb(sblock.fs_bsize);
freeblk(newblk, sblock.fs_frag);
return (0);
}
@@ -611,7 +613,7 @@ allocdir(ino_t parent, ino_t request, int mode)
{
ino_t ino;
char *cp;
- struct dinode *dp;
+ union dinode *dp;
struct bufarea *bp;
struct inoinfo *inp;
struct dirtemplate *dirp;
@@ -621,7 +623,7 @@ allocdir(ino_t parent, ino_t request, int mode)
dirp->dot_ino = ino;
dirp->dotdot_ino = parent;
dp = ginode(ino);
- bp = getdirblk(dp->di_db[0], sblock.fs_fsize);
+ bp = getdirblk(DIP(dp, di_db[0]), sblock.fs_fsize);
if (bp->b_errs) {
freeino(ino);
return (0);
@@ -632,10 +634,10 @@ allocdir(ino_t parent, ino_t request, int mode)
cp += DIRBLKSIZ)
memmove(cp, &emptydir, sizeof emptydir);
dirty(bp);
- dp->di_nlink = 2;
+ DIP(dp, di_nlink) = 2;
inodirty();
if (ino == ROOTINO) {
- inoinfo(ino)->ino_linkcnt = dp->di_nlink;
+ inoinfo(ino)->ino_linkcnt = DIP(dp, di_nlink);
cacheino(dp, ino);
return(ino);
}
@@ -650,11 +652,11 @@ allocdir(ino_t parent, ino_t request, int mode)
inp->i_dotdot = parent;
inoinfo(ino)->ino_state = inoinfo(parent)->ino_state;
if (inoinfo(ino)->ino_state == DSTATE) {
- inoinfo(ino)->ino_linkcnt = dp->di_nlink;
+ inoinfo(ino)->ino_linkcnt = DIP(dp, di_nlink);
inoinfo(parent)->ino_linkcnt++;
}
dp = ginode(parent);
- dp->di_nlink++;
+ DIP(dp, di_nlink)++;
inodirty();
return (ino);
}
@@ -665,11 +667,11 @@ allocdir(ino_t parent, ino_t request, int mode)
static void
freedir(ino_t ino, ino_t parent)
{
- struct dinode *dp;
+ union dinode *dp;
if (ino != parent) {
dp = ginode(parent);
- dp->di_nlink--;
+ DIP(dp, di_nlink)--;
inodirty();
}
freeino(ino);
@@ -704,7 +706,7 @@ lftempname(char *bufp, ino_t ino)
* Insure that it is held until another is requested.
*/
static struct bufarea *
-getdirblk(ufs_daddr_t blkno, long size)
+getdirblk(ufs2_daddr_t blkno, long size)
{
if (pdirbp != 0)
diff --git a/sbin/fsck_ffs/fsck.h b/sbin/fsck_ffs/fsck.h
index 2df0cd8d7796..efe7fb570178 100644
--- a/sbin/fsck_ffs/fsck.h
+++ b/sbin/fsck_ffs/fsck.h
@@ -1,4 +1,16 @@
/*
+ * Copyright (c) 2002 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by Marshall
+ * Kirk McKusick and Network Associates Laboratories, the Security
+ * Research Division of Network Associates, Inc. under DARPA/SPAWAR
+ * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
+ * research program
+ *
+ * Copyright (c) 1982, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
* Copyright (c) 1980, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -43,6 +55,14 @@
#define MAXBUFSPACE 40*1024 /* maximum space to allocate to buffers */
#define INOBUFSIZE 56*1024 /* size of buffer to read inodes in pass1 */
+union dinode {
+ struct ufs1_dinode dp1;
+ struct ufs2_dinode dp2;
+};
+#define DIP(dp, field) \
+ ((sblock.fs_magic == FS_UFS1_MAGIC) ? \
+ (dp)->dp1.field : (dp)->dp2.field)
+
/*
* Each inode on the filesystem is described by the following structure.
* The linkcnt is initially set to the value in the inode. Each time it
@@ -79,19 +99,24 @@ struct inostatlist {
struct bufarea {
struct bufarea *b_next; /* free list queue */
struct bufarea *b_prev; /* free list queue */
- ufs_daddr_t b_bno;
+ ufs2_daddr_t b_bno;
int b_size;
int b_errs;
int b_flags;
union {
char *b_buf; /* buffer space */
- ufs_daddr_t *b_indir; /* indirect block */
+ ufs1_daddr_t *b_indir1; /* UFS1 indirect block */
+ ufs2_daddr_t *b_indir2; /* UFS2 indirect block */
struct fs *b_fs; /* super block */
struct cg *b_cg; /* cylinder group */
- struct dinode *b_dinode; /* inode block */
+ struct ufs1_dinode *b_dinode1; /* UFS1 inode block */
+ struct ufs2_dinode *b_dinode2; /* UFS2 inode block */
} b_un;
char b_dirty;
};
+#define IBLK(bp, i) \
+ ((sblock.fs_magic == FS_UFS1_MAGIC) ? \
+ (bp)->b_un.b_indir1[i] : (bp)->b_un.b_indir2[i])
#define B_INUSE 1
@@ -110,7 +135,7 @@ struct bufarea *pbp; /* current inode block */
} while (0)
#define initbarea(bp) do { \
(bp)->b_dirty = 0; \
- (bp)->b_bno = (ufs_daddr_t)-1; \
+ (bp)->b_bno = (ufs2_daddr_t)-1; \
(bp)->b_flags = 0; \
} while (0)
@@ -127,12 +152,12 @@ struct inodesc {
int (*id_func)(); /* function to be applied to blocks of inode */
ino_t id_number; /* inode number described */
ino_t id_parent; /* for DATA nodes, their parent */
- int id_lbn; /* logical block number of current block */
- ufs_daddr_t id_blkno; /* current block number being examined */
+ ufs_lbn_t id_lbn; /* logical block number of current block */
+ ufs2_daddr_t id_blkno; /* current block number being examined */
int id_numfrags; /* number of frags contained in block */
- quad_t id_filesize; /* for DATA nodes, the size of the directory */
+ off_t id_filesize; /* for DATA nodes, the size of the directory */
+ ufs2_daddr_t id_entryno;/* for DATA nodes, current entry number */
int id_loc; /* for DATA nodes, current location in dir */
- int id_entryno; /* for DATA nodes, current entry number */
struct direct *id_dirp; /* for DATA nodes, ptr to current entry */
char *id_name; /* for DATA nodes, name to find or enter */
char id_type; /* type of descriptor, DATA or ADDR */
@@ -165,7 +190,7 @@ struct inodesc {
*/
struct dups {
struct dups *next;
- ufs_daddr_t dup;
+ ufs2_daddr_t dup;
};
struct dups *duplist; /* head of dup list */
struct dups *muldup; /* end of unique duplicate dup block numbers */
@@ -189,7 +214,7 @@ struct inoinfo {
ino_t i_dotdot; /* inode number of `..' */
size_t i_isize; /* size of inode */
u_int i_numblks; /* size of block array in bytes */
- ufs_daddr_t i_blks[1]; /* actually longer */
+ ufs2_daddr_t i_blks[1]; /* actually longer */
} **inphead, **inpsort;
long numdirs, dirhash, listmax, inplast;
long countdirs; /* number of directories we actually found */
@@ -223,7 +248,7 @@ int fsmodified; /* 1 => write done to filesystem */
int fsreadfd; /* file descriptor for reading filesystem */
int fswritefd; /* file descriptor for writing filesystem */
-ufs_daddr_t maxfsblock; /* number of blocks in the filesystem */
+ufs2_daddr_t maxfsblock; /* number of blocks in the filesystem */
char *blockmap; /* ptr to primary blk allocation map */
ino_t maxino; /* number of inodes in filesystem */
@@ -231,13 +256,19 @@ ino_t lfdir; /* lost & found directory inode number */
char *lfname; /* lost & found directory name */
int lfmode; /* lost & found directory creation mode */
-ufs_daddr_t n_blks; /* number of blocks in use */
-ufs_daddr_t n_files; /* number of files in use */
+ufs2_daddr_t n_blks; /* number of blocks in use */
+ino_t n_files; /* number of files in use */
int got_siginfo; /* received a SIGINFO */
-#define clearinode(dp) (*(dp) = zino)
-struct dinode zino;
+#define clearinode(dp) \
+ if (sblock.fs_magic == FS_UFS1_MAGIC) { \
+ (dp)->dp1 = ufs1_zino; \
+ } else { \
+ (dp)->dp2 = ufs2_zino; \
+ }
+struct ufs1_dinode ufs1_zino;
+struct ufs2_dinode ufs2_zino;
#define setbmap(blkno) setbit(blockmap, blkno)
#define testbmap(blkno) isset(blockmap, blkno)
@@ -255,44 +286,44 @@ struct fstab;
void adjust(struct inodesc *, int lcnt);
-ufs_daddr_t allocblk(long frags);
+ufs2_daddr_t allocblk(long frags);
ino_t allocdir(ino_t parent, ino_t request, int mode);
ino_t allocino(ino_t request, int type);
-void blkerror(ino_t ino, char *type, ufs_daddr_t blk);
+void blkerror(ino_t ino, char *type, ufs2_daddr_t blk);
char *blockcheck(char *name);
-int bread(int fd, char *buf, ufs_daddr_t blk, long size);
+int bread(int fd, char *buf, ufs2_daddr_t blk, long size);
void bufinit(void);
-void bwrite(int fd, char *buf, ufs_daddr_t blk, long size);
-void cacheino(struct dinode *dp, ino_t inumber);
+void bwrite(int fd, char *buf, ufs2_daddr_t blk, long size);
+void cacheino(union dinode *dp, ino_t inumber);
void catch(int);
void catchquit(int);
int changeino(ino_t dir, char *name, ino_t newnum);
-int chkrange(ufs_daddr_t blk, int cnt);
+int chkrange(ufs2_daddr_t blk, int cnt);
void ckfini(int markclean);
-int ckinode(struct dinode *dp, struct inodesc *);
+int ckinode(union dinode *dp, struct inodesc *);
void clri(struct inodesc *, char *type, int flag);
int clearentry(struct inodesc *);
void direrror(ino_t ino, char *errmesg);
int dirscan(struct inodesc *);
int dofix(struct inodesc *, char *msg);
-void ffs_clrblock(struct fs *, u_char *, ufs_daddr_t);
+void ffs_clrblock(struct fs *, u_char *, ufs1_daddr_t);
void ffs_fragacct(struct fs *, int, int32_t [], int);
-int ffs_isblock(struct fs *, u_char *, ufs_daddr_t);
-void ffs_setblock(struct fs *, u_char *, ufs_daddr_t);
+int ffs_isblock(struct fs *, u_char *, ufs1_daddr_t);
+void ffs_setblock(struct fs *, u_char *, ufs1_daddr_t);
void fileerror(ino_t cwd, ino_t ino, char *errmesg);
int findino(struct inodesc *);
int findname(struct inodesc *);
void flush(int fd, struct bufarea *bp);
-void freeblk(ufs_daddr_t blkno, long frags);
+void freeblk(ufs2_daddr_t blkno, long frags);
void freeino(ino_t ino);
void freeinodebuf(void);
-int ftypeok(struct dinode *dp);
-void getblk(struct bufarea *bp, ufs_daddr_t blk, long size);
-struct bufarea *getdatablk(ufs_daddr_t blkno, long size);
+int ftypeok(union dinode *dp);
+void getblk(struct bufarea *bp, ufs2_daddr_t blk, long size);
+struct bufarea *getdatablk(ufs2_daddr_t blkno, long size);
struct inoinfo *getinoinfo(ino_t inumber);
-struct dinode *getnextinode(ino_t inumber);
+union dinode *getnextinode(ino_t inumber);
void getpathname(char *namebuf, ino_t curdir, ino_t ino);
-struct dinode *ginode(ino_t inumber);
+union dinode *ginode(ino_t inumber);
void infohandler(int sig);
void inocleanup(void);
void inodirty(void);
@@ -314,7 +345,7 @@ void propagate(void);
void pwarn(const char *fmt, ...) __printflike(1, 2);
int readsb(int listerr);
int reply(char *question);
-void rwerror(char *mesg, ufs_daddr_t blk);
+void rwerror(char *mesg, ufs2_daddr_t blk);
void sblock_init(void);
void setinodebuf(ino_t);
int setup(char *dev);
diff --git a/sbin/fsck_ffs/fsutil.c b/sbin/fsck_ffs/fsutil.c
index bf6c7fe6757e..18e5eed3c0fd 100644
--- a/sbin/fsck_ffs/fsutil.c
+++ b/sbin/fsck_ffs/fsutil.c
@@ -42,6 +42,7 @@ static const char rcsid[] =
#include <sys/param.h>
#include <sys/types.h>
#include <sys/sysctl.h>
+#include <sys/disklabel.h>
#include <sys/stat.h>
#include <sys/disklabel.h>
@@ -63,9 +64,9 @@ static const char rcsid[] =
long diskreads, totalreads; /* Disk cache statistics */
int
-ftypeok(struct dinode *dp)
+ftypeok(union dinode *dp)
{
- switch (dp->di_mode & IFMT) {
+ switch (DIP(dp, di_mode) & IFMT) {
case IFDIR:
case IFREG:
@@ -78,7 +79,7 @@ ftypeok(struct dinode *dp)
default:
if (debug)
- printf("bad file type 0%o\n", dp->di_mode);
+ printf("bad file type 0%o\n", DIP(dp, di_mode));
return (0);
}
}
@@ -181,7 +182,7 @@ bufinit(void)
* Manage a cache of directory blocks.
*/
struct bufarea *
-getdatablk(ufs_daddr_t blkno, long size)
+getdatablk(ufs2_daddr_t blkno, long size)
{
struct bufarea *bp;
@@ -207,9 +208,9 @@ foundit:
}
void
-getblk(struct bufarea *bp, ufs_daddr_t blk, long size)
+getblk(struct bufarea *bp, ufs2_daddr_t blk, long size)
{
- ufs_daddr_t dblk;
+ ufs2_daddr_t dblk;
totalreads++;
dblk = fsbtodb(&sblock, blk);
@@ -251,7 +252,7 @@ flush(int fd, struct bufarea *bp)
}
void
-rwerror(char *mesg, ufs_daddr_t blk)
+rwerror(char *mesg, ufs2_daddr_t blk)
{
if (bkgrdcheck)
@@ -293,9 +294,10 @@ ckfini(int markclean)
return;
}
flush(fswritefd, &sblk);
- if (havesb && sblk.b_bno != SBOFF / dev_bsize && cursnapshot == 0 &&
+ if (havesb && cursnapshot == 0 && sblock.fs_magic == FS_UFS2_MAGIC &&
+ sblk.b_bno != fsbtodb(&sblock, sblock.fs_sblockloc) &&
!preen && reply("UPDATE STANDARD SUPERBLOCK")) {
- sblk.b_bno = SBOFF / dev_bsize;
+ sblk.b_bno = fsbtodb(&sblock, sblock.fs_sblockloc);
sbdirty();
flush(fswritefd, &sblk);
}
@@ -336,7 +338,7 @@ ckfini(int markclean)
}
int
-bread(int fd, char *buf, ufs_daddr_t blk, long size)
+bread(int fd, char *buf, ufs2_daddr_t blk, long size)
{
char *cp;
int i, errs;
@@ -373,7 +375,7 @@ bread(int fd, char *buf, ufs_daddr_t blk, long size)
}
void
-bwrite(int fd, char *buf, ufs_daddr_t blk, long size)
+bwrite(int fd, char *buf, ufs2_daddr_t blk, long size)
{
int i;
char *cp;
@@ -406,7 +408,7 @@ bwrite(int fd, char *buf, ufs_daddr_t blk, long size)
/*
* allocate a data block with the specified number of fragments
*/
-ufs_daddr_t
+ufs2_daddr_t
allocblk(long frags)
{
int i, j, k, cg, baseblk;
@@ -450,7 +452,7 @@ allocblk(long frags)
* Free a previously allocated block
*/
void
-freeblk(ufs_daddr_t blkno, long frags)
+freeblk(ufs2_daddr_t blkno, long frags)
{
struct inodesc idesc;
diff --git a/sbin/fsck_ffs/inode.c b/sbin/fsck_ffs/inode.c
index 0050ae16f023..636daa67468c 100644
--- a/sbin/fsck_ffs/inode.c
+++ b/sbin/fsck_ffs/inode.c
@@ -40,6 +40,7 @@ static const char rcsid[] =
#endif /* not lint */
#include <sys/param.h>
+#include <sys/stdint.h>
#include <sys/time.h>
#include <sys/sysctl.h>
@@ -55,16 +56,15 @@ static const char rcsid[] =
static ino_t startinum;
-static int iblock(struct inodesc *, long ilevel, quad_t isize);
+static int iblock(struct inodesc *, long ilevel, off_t isize);
int
-ckinode(struct dinode *dp, struct inodesc *idesc)
+ckinode(union dinode *dp, struct inodesc *idesc)
{
- ufs_daddr_t *ap;
- int ret;
- long n, ndb, offset;
- struct dinode dino;
- quad_t remsize, sizepb;
+ off_t remsize, sizepb;
+ int i, offset, ret;
+ union dinode dino;
+ ufs2_daddr_t ndb;
mode_t mode;
char pathbuf[MAXPATHLEN + 1];
@@ -72,21 +72,25 @@ ckinode(struct dinode *dp, struct inodesc *idesc)
idesc->id_fix = DONTKNOW;
idesc->id_lbn = -1;
idesc->id_entryno = 0;
- idesc->id_filesize = dp->di_size;
- mode = dp->di_mode & IFMT;
+ idesc->id_filesize = DIP(dp, di_size);
+ mode = DIP(dp, di_mode) & IFMT;
if (mode == IFBLK || mode == IFCHR || (mode == IFLNK &&
- dp->di_size < (unsigned)sblock.fs_maxsymlinklen))
+ DIP(dp, di_size) < (unsigned)sblock.fs_maxsymlinklen))
return (KEEPON);
- dino = *dp;
- ndb = howmany(dino.di_size, sblock.fs_bsize);
- for (ap = &dino.di_db[0]; ap < &dino.di_db[NDADDR]; ap++) {
+ if (sblock.fs_magic == FS_UFS1_MAGIC)
+ dino.dp1 = dp->dp1;
+ else
+ dino.dp2 = dp->dp2;
+ ndb = howmany(DIP(&dino, di_size), sblock.fs_bsize);
+ for (i = 0; i < NDADDR; i++) {
idesc->id_lbn++;
- if (--ndb == 0 && (offset = blkoff(&sblock, dino.di_size)) != 0)
+ if (--ndb == 0 &&
+ (offset = blkoff(&sblock, DIP(&dino, di_size))) != 0)
idesc->id_numfrags =
numfrags(&sblock, fragroundup(&sblock, offset));
else
idesc->id_numfrags = sblock.fs_frag;
- if (*ap == 0) {
+ if (DIP(&dino, di_db[i]) == 0) {
if (idesc->id_type == DATA && ndb >= 0) {
/* An empty block in a directory XXX */
getpathname(pathbuf, idesc->id_number,
@@ -95,8 +99,7 @@ ckinode(struct dinode *dp, struct inodesc *idesc)
pathbuf);
if (reply("ADJUST LENGTH") == 1) {
dp = ginode(idesc->id_number);
- dp->di_size = (ap - &dino.di_db[0]) *
- sblock.fs_bsize;
+ DIP(dp, di_size) = i * sblock.fs_bsize;
printf(
"YOU MUST RERUN FSCK AFTERWARDS\n");
rerun = 1;
@@ -106,7 +109,7 @@ ckinode(struct dinode *dp, struct inodesc *idesc)
}
continue;
}
- idesc->id_blkno = *ap;
+ idesc->id_blkno = DIP(&dino, di_db[i]);
if (idesc->id_type != DATA)
ret = (*idesc->id_func)(idesc);
else
@@ -115,13 +118,13 @@ ckinode(struct dinode *dp, struct inodesc *idesc)
return (ret);
}
idesc->id_numfrags = sblock.fs_frag;
- remsize = dino.di_size - sblock.fs_bsize * NDADDR;
+ remsize = DIP(&dino, di_size) - sblock.fs_bsize * NDADDR;
sizepb = sblock.fs_bsize;
- for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) {
+ for (i = 0; i < NIADDR; i++) {
sizepb *= NINDIR(&sblock);
- if (*ap) {
- idesc->id_blkno = *ap;
- ret = iblock(idesc, n, remsize);
+ if (DIP(&dino, di_ib[i])) {
+ idesc->id_blkno = DIP(&dino, di_ib[i]);
+ ret = iblock(idesc, i + 1, remsize);
if (ret & STOP)
return (ret);
} else {
@@ -134,7 +137,7 @@ ckinode(struct dinode *dp, struct inodesc *idesc)
pathbuf);
if (reply("ADJUST LENGTH") == 1) {
dp = ginode(idesc->id_number);
- dp->di_size -= remsize;
+ DIP(dp, di_size) -= remsize;
remsize = 0;
printf(
"YOU MUST RERUN FSCK AFTERWARDS\n");
@@ -150,16 +153,14 @@ ckinode(struct dinode *dp, struct inodesc *idesc)
}
static int
-iblock(struct inodesc *idesc, long ilevel, quad_t isize)
+iblock(struct inodesc *idesc, long ilevel, off_t isize)
{
- ufs_daddr_t *ap;
- ufs_daddr_t *aplim;
struct bufarea *bp;
int i, n, (*func)(), nif;
- quad_t sizepb;
+ off_t sizepb;
char buf[BUFSIZ];
char pathbuf[MAXPATHLEN + 1];
- struct dinode *dp;
+ union dinode *dp;
if (idesc->id_type != DATA) {
func = idesc->id_func;
@@ -173,31 +174,30 @@ iblock(struct inodesc *idesc, long ilevel, quad_t isize)
ilevel--;
for (sizepb = sblock.fs_bsize, i = 0; i < ilevel; i++)
sizepb *= NINDIR(&sblock);
- nif = howmany(isize , sizepb);
- if (nif > NINDIR(&sblock))
+ if (howmany(isize, sizepb) > NINDIR(&sblock))
nif = NINDIR(&sblock);
+ else
+ nif = howmany(isize, sizepb);
if (idesc->id_func == pass1check && nif < NINDIR(&sblock)) {
- aplim = &bp->b_un.b_indir[NINDIR(&sblock)];
- for (ap = &bp->b_un.b_indir[nif]; ap < aplim; ap++) {
- if (*ap == 0)
+ for (i = nif; i < NINDIR(&sblock); i++) {
+ if (IBLK(bp, i) == 0)
continue;
(void)sprintf(buf, "PARTIALLY TRUNCATED INODE I=%lu",
(u_long)idesc->id_number);
if (preen) {
pfatal("%s", buf);
} else if (dofix(idesc, buf)) {
- *ap = 0;
+ IBLK(bp, i) = 0;
dirty(bp);
}
}
flush(fswritefd, bp);
}
- aplim = &bp->b_un.b_indir[nif];
- for (ap = bp->b_un.b_indir; ap < aplim; ap++) {
+ for (i = 0; i < nif; i++) {
if (ilevel == 0)
idesc->id_lbn++;
- if (*ap) {
- idesc->id_blkno = *ap;
+ if (IBLK(bp, i)) {
+ idesc->id_blkno = IBLK(bp, i);
if (ilevel == 0)
n = (*func)(idesc);
else
@@ -215,7 +215,7 @@ iblock(struct inodesc *idesc, long ilevel, quad_t isize)
pathbuf);
if (reply("ADJUST LENGTH") == 1) {
dp = ginode(idesc->id_number);
- dp->di_size -= isize;
+ DIP(dp, di_size) -= isize;
isize = 0;
printf(
"YOU MUST RERUN FSCK AFTERWARDS\n");
@@ -237,7 +237,7 @@ iblock(struct inodesc *idesc, long ilevel, quad_t isize)
* Return 0 if in range, 1 if out of range.
*/
int
-chkrange(ufs_daddr_t blk, int cnt)
+chkrange(ufs2_daddr_t blk, int cnt)
{
int c;
@@ -280,10 +280,10 @@ chkrange(ufs_daddr_t blk, int cnt)
/*
* General purpose interface for reading inodes.
*/
-struct dinode *
+union dinode *
ginode(ino_t inumber)
{
- ufs_daddr_t iblk;
+ ufs2_daddr_t iblk;
if (inumber < ROOTINO || inumber > maxino)
errx(EEXIT, "bad inode number %d to ginode", inumber);
@@ -295,7 +295,10 @@ ginode(ino_t inumber)
pbp = getdatablk(iblk, sblock.fs_bsize);
startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock);
}
- return (&pbp->b_un.b_dinode[inumber % INOPB(&sblock)]);
+ if (sblock.fs_magic == FS_UFS1_MAGIC)
+ return ((union dinode *)
+ &pbp->b_un.b_dinode1[inumber % INOPB(&sblock)]);
+ return ((union dinode *)&pbp->b_un.b_dinode2[inumber % INOPB(&sblock)]);
}
/*
@@ -304,14 +307,15 @@ ginode(ino_t inumber)
*/
static ino_t nextino, lastinum, lastvalidinum;
static long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize;
-static struct dinode *inodebuf;
+static caddr_t inodebuf;
-struct dinode *
+union dinode *
getnextinode(ino_t inumber)
{
long size;
- ufs_daddr_t dblk;
- static struct dinode *dp;
+ ufs2_daddr_t dblk;
+ union dinode *dp;
+ static caddr_t nextinop;
if (inumber != nextino++ || inumber > lastvalidinum)
errx(EEXIT, "bad inode number %d to nextinode", inumber);
@@ -329,10 +333,15 @@ getnextinode(ino_t inumber)
* If bread returns an error, it will already have zeroed
* out the buffer, so we do not need to do so here.
*/
- (void)bread(fsreadfd, (char *)inodebuf, dblk, size);
- dp = inodebuf;
+ (void)bread(fsreadfd, inodebuf, dblk, size);
+ nextinop = inodebuf;
}
- return (dp++);
+ dp = (union dinode *)nextinop;
+ if (sblock.fs_magic == FS_UFS1_MAGIC)
+ nextinop += sizeof(struct ufs1_dinode);
+ else
+ nextinop += sizeof(struct ufs2_dinode);
+ return (dp);
}
void
@@ -349,17 +358,19 @@ setinodebuf(ino_t inum)
if (inodebuf != NULL)
return;
inobufsize = blkroundup(&sblock, INOBUFSIZE);
- fullcnt = inobufsize / sizeof(struct dinode);
+ fullcnt = inobufsize / ((sblock.fs_magic == FS_UFS1_MAGIC) ?
+ sizeof(struct ufs1_dinode) : sizeof(struct ufs2_dinode));
readpercg = sblock.fs_ipg / fullcnt;
partialcnt = sblock.fs_ipg % fullcnt;
- partialsize = partialcnt * sizeof(struct dinode);
+ partialsize = partialcnt * ((sblock.fs_magic == FS_UFS1_MAGIC) ?
+ sizeof(struct ufs1_dinode) : sizeof(struct ufs2_dinode));
if (partialcnt != 0) {
readpercg++;
} else {
partialcnt = fullcnt;
partialsize = inobufsize;
}
- if ((inodebuf = (struct dinode *)malloc((unsigned)inobufsize)) == NULL)
+ if ((inodebuf = malloc((unsigned)inobufsize)) == NULL)
errx(EEXIT, "cannot allocate space for inode buffer");
}
@@ -380,17 +391,17 @@ freeinodebuf(void)
* Enter inodes into the cache.
*/
void
-cacheino(struct dinode *dp, ino_t inumber)
+cacheino(union dinode *dp, ino_t inumber)
{
- struct inoinfo *inp;
- struct inoinfo **inpp;
- int blks;
+ struct inoinfo *inp, **inpp;
+ int i, blks;
- blks = howmany(dp->di_size, sblock.fs_bsize);
- if (blks > NDADDR)
+ if (howmany(DIP(dp, di_size), sblock.fs_bsize) > NDADDR)
blks = NDADDR + NIADDR;
+ else
+ blks = howmany(DIP(dp, di_size), sblock.fs_bsize);
inp = (struct inoinfo *)
- malloc(sizeof(*inp) + (blks - 1) * sizeof(ufs_daddr_t));
+ malloc(sizeof(*inp) + (blks - 1) * sizeof(ufs2_daddr_t));
if (inp == NULL)
errx(EEXIT, "cannot increase directory list");
inpp = &inphead[inumber % dirhash];
@@ -399,9 +410,13 @@ cacheino(struct dinode *dp, ino_t inumber)
inp->i_parent = inumber == ROOTINO ? ROOTINO : (ino_t)0;
inp->i_dotdot = (ino_t)0;
inp->i_number = inumber;
- inp->i_isize = dp->di_size;
- inp->i_numblks = blks * sizeof(ufs_daddr_t);
- memmove(&inp->i_blks[0], &dp->di_db[0], (size_t)inp->i_numblks);
+ inp->i_isize = DIP(dp, di_size);
+ inp->i_numblks = blks;
+ for (i = 0; i < (blks < NDADDR ? blks : NDADDR); i++)
+ inp->i_blks[i] = DIP(dp, di_db[i]);
+ if (blks > NDADDR)
+ for (i = 0; i < NIADDR; i++)
+ inp->i_blks[NDADDR + i] = DIP(dp, di_ib[i]);
if (inplast == listmax) {
listmax += 100;
inpsort = (struct inoinfo **)realloc((char *)inpsort,
@@ -456,12 +471,12 @@ inodirty(void)
void
clri(struct inodesc *idesc, char *type, int flag)
{
- struct dinode *dp;
+ union dinode *dp;
dp = ginode(idesc->id_number);
if (flag == 1) {
pwarn("%s %s", type,
- (dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE");
+ (DIP(dp, di_mode) & IFMT) == IFDIR ? "DIR" : "FILE");
pinode(idesc->id_number);
}
if (preen || reply("CLEAR") == 1) {
@@ -475,7 +490,7 @@ clri(struct inodesc *idesc, char *type, int flag)
inodirty();
} else {
cmd.value = idesc->id_number;
- cmd.size = -dp->di_nlink;
+ cmd.size = -DIP(dp, di_nlink);
if (debug)
printf("adjrefcnt ino %ld amt %ld\n",
(long)cmd.value, cmd.size);
@@ -530,7 +545,7 @@ clearentry(struct inodesc *idesc)
void
pinode(ino_t ino)
{
- struct dinode *dp;
+ union dinode *dp;
char *p;
struct passwd *pw;
time_t t;
@@ -540,24 +555,24 @@ pinode(ino_t ino)
return;
dp = ginode(ino);
printf(" OWNER=");
- if ((pw = getpwuid((int)dp->di_uid)) != 0)
+ if ((pw = getpwuid((int)DIP(dp, di_uid))) != 0)
printf("%s ", pw->pw_name);
else
- printf("%u ", (unsigned)dp->di_uid);
- printf("MODE=%o\n", dp->di_mode);
+ printf("%u ", (unsigned)DIP(dp, di_uid));
+ printf("MODE=%o\n", DIP(dp, di_mode));
if (preen)
printf("%s: ", cdevname);
- printf("SIZE=%qu ", dp->di_size);
- t = dp->di_mtime;
+ printf("SIZE=%qu ", DIP(dp, di_size));
+ t = DIP(dp, di_mtime);
p = ctime(&t);
printf("MTIME=%12.12s %4.4s ", &p[4], &p[20]);
}
void
-blkerror(ino_t ino, char *type, ufs_daddr_t blk)
+blkerror(ino_t ino, char *type, ufs2_daddr_t blk)
{
- pfatal("%ld %s I=%lu", (long)blk, type, (u_long)ino);
+ pfatal("%lld %s I=%lu", (intmax_t)blk, type, (u_long)ino);
printf("\n");
switch (inoinfo(ino)->ino_state) {
@@ -586,7 +601,7 @@ ino_t
allocino(ino_t request, int type)
{
ino_t ino;
- struct dinode *dp;
+ union dinode *dp;
struct cg *cgp = &cgrp;
int cg;
@@ -619,18 +634,20 @@ allocino(ino_t request, int type)
}
cgdirty();
dp = ginode(ino);
- dp->di_db[0] = allocblk((long)1);
- if (dp->di_db[0] == 0) {
+ DIP(dp, di_db[0]) = allocblk((long)1);
+ if (DIP(dp, di_db[0]) == 0) {
inoinfo(ino)->ino_state = USTATE;
return (0);
}
- dp->di_mode = type;
- dp->di_flags = 0;
- dp->di_atime = time(NULL);
- dp->di_mtime = dp->di_ctime = dp->di_atime;
- dp->di_mtimensec = dp->di_ctimensec = dp->di_atimensec = 0;
- dp->di_size = sblock.fs_fsize;
- dp->di_blocks = btodb(sblock.fs_fsize);
+ DIP(dp, di_mode) = type;
+ DIP(dp, di_flags) = 0;
+ DIP(dp, di_atime) = time(NULL);
+ DIP(dp, di_mtime) = DIP(dp, di_ctime) = DIP(dp, di_atime);
+ DIP(dp, di_mtimensec) = 0;
+ DIP(dp, di_ctimensec) = 0;
+ DIP(dp, di_atimensec) = 0;
+ DIP(dp, di_size) = sblock.fs_fsize;
+ DIP(dp, di_blocks) = btodb(sblock.fs_fsize);
n_files++;
inodirty();
inoinfo(ino)->ino_type = IFTODT(type);
@@ -644,7 +661,7 @@ void
freeino(ino_t ino)
{
struct inodesc idesc;
- struct dinode *dp;
+ union dinode *dp;
memset(&idesc, 0, sizeof(struct inodesc));
idesc.id_type = ADDR;
diff --git a/sbin/fsck_ffs/main.c b/sbin/fsck_ffs/main.c
index 73364a7f7fdd..c69e9d3441ea 100644
--- a/sbin/fsck_ffs/main.c
+++ b/sbin/fsck_ffs/main.c
@@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mount.h>
#include <sys/resource.h>
#include <sys/sysctl.h>
+#include <sys/disklabel.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/ufsmount.h>
@@ -95,6 +96,9 @@ main(int argc, char *argv[])
case 'c':
skipclean = 0;
cvtlevel = argtoi('c', "conversion level", optarg, 10);
+ if (cvtlevel < 3)
+ errx(EEXIT, "cannot do level %d conversion",
+ cvtlevel);
break;
case 'd':
@@ -180,14 +184,14 @@ argtoi(int flag, char *req, char *str, int base)
static int
checkfilesys(char *filesys)
{
- ufs_daddr_t n_ffree, n_bfree;
+ ufs2_daddr_t n_ffree, n_bfree;
struct ufs_args args;
struct dups *dp;
struct statfs *mntp;
struct zlncnt *zlnp;
- ufs_daddr_t blks;
- ufs_daddr_t files;
+ ufs2_daddr_t blks;
int cylno, size;
+ ino_t files;
cdevname = filesys;
if (debug && preen)
@@ -367,10 +371,9 @@ checkfilesys(char *filesys)
pwarn("Reclaimed: %ld directories, %ld files, %d fragments\n",
countdirs, (long)files - countdirs, blks);
}
- pwarn("%ld files, %ld used, %ld free ",
- (long)n_files, (long)n_blks, (long)(n_ffree +
- sblock.fs_frag * n_bfree));
- printf("(%d frags, %d blocks, %.1f%% fragmentation)\n",
+ pwarn("%ld files, %ld used, %qu free ",
+ (long)n_files, (long)n_blks, n_ffree + sblock.fs_frag * n_bfree);
+ printf("(%qu frags, %qu blocks, %.1f%% fragmentation)\n",
n_ffree, n_bfree, n_ffree * 100.0 / sblock.fs_dsize);
if (debug) {
if (files < 0)
@@ -404,7 +407,8 @@ checkfilesys(char *filesys)
*/
for (cylno = 0; cylno < sblock.fs_ncg; cylno++)
bwrite(fswritefd, (char *)&sblock,
- fsbtodb(&sblock, cgsblock(&sblock, cylno)), SBSIZE);
+ fsbtodb(&sblock, cgsblock(&sblock, cylno)),
+ SBLOCKSIZE);
}
if (rerun)
resolved = 0;
diff --git a/sbin/fsck_ffs/pass1.c b/sbin/fsck_ffs/pass1.c
index cfb8af8c1278..10f03eb26983 100644
--- a/sbin/fsck_ffs/pass1.c
+++ b/sbin/fsck_ffs/pass1.c
@@ -52,8 +52,8 @@ static const char rcsid[] =
#include "fsck.h"
-static ufs_daddr_t badblk;
-static ufs_daddr_t dupblk;
+static ufs2_daddr_t badblk;
+static ufs2_daddr_t dupblk;
static ino_t lastino; /* last inode in use */
static void checkinode(ino_t inumber, struct inodesc *);
@@ -61,11 +61,12 @@ static void checkinode(ino_t inumber, struct inodesc *);
void
pass1(void)
{
- u_int8_t *cp;
- ino_t inumber;
- int c, i, cgd, inosused;
struct inostat *info;
struct inodesc idesc;
+ ino_t inumber, inosused;
+ ufs2_daddr_t i, cgd;
+ u_int8_t *cp;
+ int c;
/*
* Set filesystem reserved blocks in used block map.
@@ -93,7 +94,11 @@ pass1(void)
for (c = 0; c < sblock.fs_ncg; c++) {
inumber = c * sblock.fs_ipg;
setinodebuf(inumber);
- inosused = sblock.fs_ipg;
+ getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize);
+ if (sblock.fs_magic == FS_UFS2_MAGIC)
+ inosused = cgrp.cg_initediblk;
+ else
+ inosused = sblock.fs_ipg;
if (got_siginfo) {
printf("%s: phase 1: cyl group %d of %d (%d%%)\n",
cdevname, c, sblock.fs_ncg,
@@ -108,10 +113,9 @@ pass1(void)
* read only those inodes in from disk.
*/
if (preen && usedsoftdep) {
- getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize);
if (!cg_chkmagic(&cgrp))
pfatal("CG %d: BAD MAGIC NUMBER\n", c);
- cp = &cg_inosused(&cgrp)[(sblock.fs_ipg - 1) / NBBY];
+ cp = &cg_inosused(&cgrp)[(inosused - 1) / NBBY];
for ( ; inosused > 0; inosused -= NBBY, cp--) {
if (*cp == 0)
continue;
@@ -157,9 +161,10 @@ pass1(void)
* to the size necessary to describe the inodes that we
* really found.
*/
- inosused = lastino - (c * sblock.fs_ipg);
- if (inosused < 0)
+ if (lastino < (c * sblock.fs_ipg))
inosused = 0;
+ else
+ inosused = lastino - (c * sblock.fs_ipg);
inostathead[c].il_numalloced = inosused;
if (inosused == 0) {
free(inostathead[c].il_stat);
@@ -180,21 +185,29 @@ pass1(void)
static void
checkinode(ino_t inumber, struct inodesc *idesc)
{
- struct dinode *dp;
+ union dinode *dp;
struct zlncnt *zlnp;
- u_int64_t kernmaxfilesize;
- ufs_daddr_t ndb, j;
+ off_t kernmaxfilesize;
+ ufs2_daddr_t ndb;
mode_t mode;
char *symbuf;
+ int j;
dp = getnextinode(inumber);
- mode = dp->di_mode & IFMT;
+ mode = DIP(dp, di_mode) & IFMT;
if (mode == 0) {
- if (memcmp(dp->di_db, zino.di_db,
- NDADDR * sizeof(ufs_daddr_t)) ||
- memcmp(dp->di_ib, zino.di_ib,
- NIADDR * sizeof(ufs_daddr_t)) ||
- dp->di_mode || dp->di_size) {
+ if ((sblock.fs_magic == FS_UFS1_MAGIC &&
+ (memcmp(dp->dp1.di_db, ufs1_zino.di_db,
+ NDADDR * sizeof(ufs1_daddr_t)) ||
+ memcmp(dp->dp1.di_ib, ufs1_zino.di_ib,
+ NIADDR * sizeof(ufs1_daddr_t)) ||
+ dp->dp1.di_mode || dp->dp1.di_size)) ||
+ (sblock.fs_magic == FS_UFS2_MAGIC &&
+ (memcmp(dp->dp2.di_db, ufs2_zino.di_db,
+ NDADDR * sizeof(ufs2_daddr_t)) ||
+ memcmp(dp->dp2.di_ib, ufs2_zino.di_ib,
+ NIADDR * sizeof(ufs2_daddr_t)) ||
+ dp->dp2.di_mode || dp->dp2.di_size))) {
pfatal("PARTIALLY ALLOCATED INODE I=%lu",
(u_long)inumber);
if (reply("CLEAR") == 1) {
@@ -208,36 +221,37 @@ checkinode(ino_t inumber, struct inodesc *idesc)
}
lastino = inumber;
/* This should match the file size limit in ffs_mountfs(). */
- kernmaxfilesize = (u_int64_t)0x40000000 * sblock.fs_bsize - 1;
- if (dp->di_size > kernmaxfilesize ||
- dp->di_size > sblock.fs_maxfilesize ||
- (mode == IFDIR && dp->di_size > MAXDIRSIZE)) {
+ kernmaxfilesize = (off_t)0x40000000 * sblock.fs_bsize - 1;
+ if (DIP(dp, di_size) > kernmaxfilesize ||
+ DIP(dp, di_size) > sblock.fs_maxfilesize ||
+ (mode == IFDIR && DIP(dp, di_size) > MAXDIRSIZE)) {
if (debug)
- printf("bad size %qu:", dp->di_size);
+ printf("bad size %qu:", DIP(dp, di_size));
goto unknown;
}
if (!preen && mode == IFMT && reply("HOLD BAD BLOCK") == 1) {
dp = ginode(inumber);
- dp->di_size = sblock.fs_fsize;
- dp->di_mode = IFREG|0600;
+ DIP(dp, di_size) = sblock.fs_fsize;
+ DIP(dp, di_mode) = IFREG|0600;
inodirty();
}
if ((mode == IFBLK || mode == IFCHR || mode == IFIFO ||
- mode == IFSOCK) && dp->di_size != 0) {
+ mode == IFSOCK) && DIP(dp, di_size) != 0) {
if (debug)
- printf("bad special-file size %qu:", dp->di_size);
+ printf("bad special-file size %qu:", DIP(dp, di_size));
goto unknown;
}
- if ((mode == IFBLK || mode == IFCHR) && (dev_t)dp->di_rdev == NODEV) {
+ if ((mode == IFBLK || mode == IFCHR) &&
+ (dev_t)DIP(dp, di_rdev) == NODEV) {
if (debug)
printf("bad special-file rdev NODEV:");
goto unknown;
}
- ndb = howmany(dp->di_size, sblock.fs_bsize);
+ ndb = howmany(DIP(dp, di_size), sblock.fs_bsize);
if (ndb < 0) {
if (debug)
- printf("bad size %qu ndb %d:",
- dp->di_size, ndb);
+ printf("bad size %qu ndb %qu:",
+ DIP(dp, di_size), ndb);
goto unknown;
}
if (mode == IFBLK || mode == IFCHR)
@@ -247,8 +261,13 @@ checkinode(ino_t inumber, struct inodesc *idesc)
* Fake ndb value so direct/indirect block checks below
* will detect any garbage after symlink string.
*/
- if (dp->di_size < (u_int64_t)sblock.fs_maxsymlinklen) {
- ndb = howmany(dp->di_size, sizeof(ufs_daddr_t));
+ if (DIP(dp, di_size) < (off_t)sblock.fs_maxsymlinklen) {
+ if (sblock.fs_magic == FS_UFS1_MAGIC)
+ ndb = howmany(DIP(dp, di_size),
+ sizeof(ufs1_daddr_t));
+ else
+ ndb = howmany(DIP(dp, di_size),
+ sizeof(ufs2_daddr_t));
if (ndb > NDADDR) {
j = ndb - NDADDR;
for (ndb = 1; j > 1; j--)
@@ -258,26 +277,26 @@ checkinode(ino_t inumber, struct inodesc *idesc)
}
}
for (j = ndb; j < NDADDR; j++)
- if (dp->di_db[j] != 0) {
+ if (DIP(dp, di_db[j]) != 0) {
if (debug)
- printf("bad direct addr: %ld\n",
- (long)dp->di_db[j]);
+ printf("bad direct addr[%d]: %qu\n", j,
+ (ufs2_daddr_t)DIP(dp, di_db[j]));
goto unknown;
}
for (j = 0, ndb -= NDADDR; ndb > 0; j++)
ndb /= NINDIR(&sblock);
for (; j < NIADDR; j++)
- if (dp->di_ib[j] != 0) {
+ if (DIP(dp, di_ib[j]) != 0) {
if (debug)
- printf("bad indirect addr: %ld\n",
- (long)dp->di_ib[j]);
+ printf("bad indirect addr: %qu\n",
+ DIP(dp, di_ib[j]));
goto unknown;
}
if (ftypeok(dp) == 0)
goto unknown;
n_files++;
- inoinfo(inumber)->ino_linkcnt = dp->di_nlink;
- if (dp->di_nlink <= 0) {
+ inoinfo(inumber)->ino_linkcnt = DIP(dp, di_nlink);
+ if (DIP(dp, di_nlink) <= 0) {
zlnp = (struct zlncnt *)malloc(sizeof *zlnp);
if (zlnp == NULL) {
pfatal("LINK COUNT TABLE OVERFLOW");
@@ -292,7 +311,7 @@ checkinode(ino_t inumber, struct inodesc *idesc)
}
}
if (mode == IFDIR) {
- if (dp->di_size == 0)
+ if (DIP(dp, di_size) == 0)
inoinfo(inumber)->ino_state = DCLEAR;
else
inoinfo(inumber)->ino_state = DSTATE;
@@ -303,30 +322,30 @@ checkinode(ino_t inumber, struct inodesc *idesc)
inoinfo(inumber)->ino_type = IFTODT(mode);
badblk = dupblk = 0;
idesc->id_number = inumber;
- if (dp->di_flags & SF_SNAPSHOT)
+ if (DIP(dp, di_flags) & SF_SNAPSHOT)
idesc->id_type = SNAP;
else
idesc->id_type = ADDR;
(void)ckinode(dp, idesc);
idesc->id_entryno *= btodb(sblock.fs_fsize);
- if (dp->di_blocks != idesc->id_entryno) {
- pwarn("INCORRECT BLOCK COUNT I=%lu (%ld should be %ld)",
- (u_long)inumber, (long)dp->di_blocks,
- (long)idesc->id_entryno);
+ if (DIP(dp, di_blocks) != idesc->id_entryno) {
+ pwarn("INCORRECT BLOCK COUNT I=%lu (%qu should be %qu)",
+ (u_long)inumber, DIP(dp, di_blocks),
+ idesc->id_entryno);
if (preen)
printf(" (CORRECTED)\n");
else if (reply("CORRECT") == 0)
return;
if (bkgrdflag == 0) {
dp = ginode(inumber);
- dp->di_blocks = idesc->id_entryno;
+ DIP(dp, di_blocks) = idesc->id_entryno;
inodirty();
} else {
cmd.value = idesc->id_number;
- cmd.size = idesc->id_entryno - dp->di_blocks;
+ cmd.size = idesc->id_entryno - DIP(dp, di_blocks);
if (debug)
- printf("adjblkcnt ino %ld amount %ld\n",
- (long)cmd.value, cmd.size);
+ printf("adjblkcnt ino %qu amount %ld\n",
+ cmd.value, cmd.size);
if (sysctl(adjblkcnt, MIBSIZE, 0, 0,
&cmd, sizeof cmd) == -1)
rwerror("ADJUST INODE BLOCK COUNT", cmd.value);
@@ -349,7 +368,7 @@ pass1check(struct inodesc *idesc)
{
int res = KEEPON;
int anyout, nfrags;
- ufs_daddr_t blkno = idesc->id_blkno;
+ ufs2_daddr_t blkno = idesc->id_blkno;
struct dups *dlp;
struct dups *new;
diff --git a/sbin/fsck_ffs/pass1b.c b/sbin/fsck_ffs/pass1b.c
index dbb401b49998..b30a2b1dff4f 100644
--- a/sbin/fsck_ffs/pass1b.c
+++ b/sbin/fsck_ffs/pass1b.c
@@ -55,7 +55,7 @@ void
pass1b(void)
{
int c, i;
- struct dinode *dp;
+ union dinode *dp;
struct inodesc idesc;
ino_t inumber;
@@ -90,7 +90,7 @@ pass1bcheck(struct inodesc *idesc)
{
struct dups *dlp;
int nfrags, res = KEEPON;
- ufs_daddr_t blkno = idesc->id_blkno;
+ ufs2_daddr_t blkno = idesc->id_blkno;
for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) {
if (chkrange(blkno, 1))
diff --git a/sbin/fsck_ffs/pass2.c b/sbin/fsck_ffs/pass2.c
index 2347f76922ae..34fda7639759 100644
--- a/sbin/fsck_ffs/pass2.c
+++ b/sbin/fsck_ffs/pass2.c
@@ -58,11 +58,12 @@ static int pass2check(struct inodesc *);
void
pass2(void)
{
- struct dinode *dp;
+ union dinode *dp;
struct inoinfo **inpp, *inp;
struct inoinfo **inpend;
struct inodesc curino;
- struct dinode dino;
+ union dinode dino;
+ int i;
char pathbuf[MAXPATHLEN + 1];
switch (inoinfo(ROOTINO)->ino_state) {
@@ -105,8 +106,8 @@ pass2(void)
exit(EEXIT);
}
dp = ginode(ROOTINO);
- dp->di_mode &= ~IFMT;
- dp->di_mode |= IFDIR;
+ DIP(dp, di_mode) &= ~IFMT;
+ DIP(dp, di_mode) |= IFDIR;
inodirty();
break;
@@ -130,7 +131,6 @@ pass2(void)
memset(&curino, 0, sizeof(struct inodesc));
curino.id_type = DATA;
curino.id_func = pass2check;
- dp = &dino;
inpend = &inpsort[inplast];
for (inpp = inpsort; inpp < inpend; inpp++) {
if (got_siginfo) {
@@ -147,9 +147,8 @@ pass2(void)
inp->i_isize = roundup(MINDIRSIZE, DIRBLKSIZ);
if (reply("FIX") == 1) {
dp = ginode(inp->i_number);
- dp->di_size = inp->i_isize;
+ DIP(dp, di_size) = inp->i_isize;
inodirty();
- dp = &dino;
}
} else if ((inp->i_isize & (DIRBLKSIZ - 1)) != 0) {
getpathname(pathbuf, inp->i_number, inp->i_number);
@@ -166,15 +165,22 @@ pass2(void)
inp->i_isize = roundup(inp->i_isize, DIRBLKSIZ);
if (preen || reply("ADJUST") == 1) {
dp = ginode(inp->i_number);
- dp->di_size = roundup(inp->i_isize, DIRBLKSIZ);
+ DIP(dp, di_size) =
+ roundup(inp->i_isize, DIRBLKSIZ);
inodirty();
- dp = &dino;
}
}
- memset(&dino, 0, sizeof(struct dinode));
- dino.di_mode = IFDIR;
- dp->di_size = inp->i_isize;
- memmove(&dp->di_db[0], &inp->i_blks[0], (size_t)inp->i_numblks);
+ dp = &dino;
+ memset(dp, 0, sizeof(struct ufs2_dinode));
+ DIP(dp, di_mode) = IFDIR;
+ DIP(dp, di_size) = inp->i_isize;
+ for (i = 0;
+ i < (inp->i_numblks<NDADDR ? inp->i_numblks : NDADDR);
+ i++)
+ DIP(dp, di_db[i]) = inp->i_blks[i];
+ if (inp->i_numblks > NDADDR)
+ for (i = 0; i < NIADDR; i++)
+ DIP(dp, di_ib[i]) = inp->i_blks[NDADDR + i];
curino.id_number = inp->i_number;
curino.id_parent = inp->i_parent;
(void)ckinode(dp, &curino);
@@ -223,7 +229,7 @@ pass2check(struct inodesc *idesc)
struct direct *dirp = idesc->id_dirp;
struct inoinfo *inp;
int n, entrysize, ret = 0;
- struct dinode *dp;
+ union dinode *dp;
char *errmsg;
struct direct proto;
char namebuf[MAXPATHLEN + 1];
@@ -392,8 +398,8 @@ again:
break;
dp = ginode(dirp->d_ino);
inoinfo(dirp->d_ino)->ino_state =
- (dp->di_mode & IFMT) == IFDIR ? DSTATE : FSTATE;
- inoinfo(dirp->d_ino)->ino_linkcnt = dp->di_nlink;
+ (DIP(dp, di_mode) & IFMT) == IFDIR ? DSTATE : FSTATE;
+ inoinfo(dirp->d_ino)->ino_linkcnt = DIP(dp, di_nlink);
goto again;
case DSTATE:
diff --git a/sbin/fsck_ffs/pass4.c b/sbin/fsck_ffs/pass4.c
index 6683ae417c82..da298040f2cd 100644
--- a/sbin/fsck_ffs/pass4.c
+++ b/sbin/fsck_ffs/pass4.c
@@ -54,7 +54,7 @@ pass4(void)
{
ino_t inumber;
struct zlncnt *zlnp;
- struct dinode *dp;
+ union dinode *dp;
struct inodesc idesc;
int i, n, cg;
@@ -100,7 +100,7 @@ pass4(void)
case DCLEAR:
dp = ginode(inumber);
- if (dp->di_size == 0) {
+ if (DIP(dp, di_size) == 0) {
clri(&idesc, "ZERO LENGTH", 1);
break;
}
@@ -125,7 +125,7 @@ pass4check(struct inodesc *idesc)
{
struct dups *dlp;
int nfrags, res = KEEPON;
- ufs_daddr_t blkno = idesc->id_blkno;
+ ufs2_daddr_t blkno = idesc->id_blkno;
for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) {
if (chkrange(blkno, 1)) {
diff --git a/sbin/fsck_ffs/pass5.c b/sbin/fsck_ffs/pass5.c
index f2ab2a819697..707872b9dd52 100644
--- a/sbin/fsck_ffs/pass5.c
+++ b/sbin/fsck_ffs/pass5.c
@@ -55,18 +55,17 @@ static void check_maps(u_char *, u_char *, int, int, char *, int *, int, int);
void
pass5(void)
{
- int c, blk, frags, basesize, sumsize, mapsize, savednrpos = 0;
+ int c, i, j, blk, frags, basesize, mapsize;
int inomapsize, blkmapsize;
struct fs *fs = &sblock;
struct cg *cg = &cgrp;
- ufs_daddr_t dbase, dmax, d;
- int i, j, excessdirs, rewritecg = 0;
+ ufs2_daddr_t d, dbase, dmax;
+ int excessdirs, rewritecg = 0;
struct csum *cs;
- struct csum cstotal;
+ struct csum_total cstotal;
struct inodesc idesc[3];
char buf[MAXBSIZE];
struct cg *newcg = (struct cg *)buf;
- struct ocg *ocg = (struct ocg *)buf;
inoinfo(WINO)->ino_state = USTATE;
memset(newcg, 0, (size_t)fs->fs_cgsize);
@@ -110,63 +109,46 @@ pass5(void)
}
}
}
- switch ((int)fs->fs_postblformat) {
-
- case FS_42POSTBLFMT:
- basesize = (char *)(&ocg->cg_btot[0]) -
- (char *)(&ocg->cg_firstfield);
- sumsize = &ocg->cg_iused[0] - (u_int8_t *)(&ocg->cg_btot[0]);
- mapsize = &ocg->cg_free[howmany(fs->fs_fpg, NBBY)] -
- (u_char *)&ocg->cg_iused[0];
- blkmapsize = howmany(fs->fs_fpg, NBBY);
- inomapsize = &ocg->cg_free[0] - (u_char *)&ocg->cg_iused[0];
- ocg->cg_magic = CG_MAGIC;
- savednrpos = fs->fs_nrpos;
- fs->fs_nrpos = 8;
- break;
-
- case FS_DYNAMICPOSTBLFMT:
- newcg->cg_btotoff =
- &newcg->cg_space[0] - (u_char *)(&newcg->cg_firstfield);
- newcg->cg_boff =
- newcg->cg_btotoff + fs->fs_cpg * sizeof(int32_t);
- newcg->cg_iusedoff = newcg->cg_boff +
- fs->fs_cpg * fs->fs_nrpos * sizeof(u_int16_t);
- newcg->cg_freeoff =
- newcg->cg_iusedoff + howmany(fs->fs_ipg, NBBY);
- inomapsize = newcg->cg_freeoff - newcg->cg_iusedoff;
- newcg->cg_nextfreeoff = newcg->cg_freeoff +
- howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY);
- blkmapsize = newcg->cg_nextfreeoff - newcg->cg_freeoff;
- if (fs->fs_contigsumsize > 0) {
- newcg->cg_clustersumoff = newcg->cg_nextfreeoff -
- sizeof(u_int32_t);
- newcg->cg_clustersumoff =
- roundup(newcg->cg_clustersumoff, sizeof(u_int32_t));
- newcg->cg_clusteroff = newcg->cg_clustersumoff +
- (fs->fs_contigsumsize + 1) * sizeof(u_int32_t);
- newcg->cg_nextfreeoff = newcg->cg_clusteroff +
- howmany(fs->fs_cpg * fs->fs_spc / NSPB(fs), NBBY);
- }
- newcg->cg_magic = CG_MAGIC;
- basesize = &newcg->cg_space[0] -
- (u_char *)(&newcg->cg_firstfield);
- sumsize = newcg->cg_iusedoff - newcg->cg_btotoff;
- mapsize = newcg->cg_nextfreeoff - newcg->cg_iusedoff;
- break;
-
- default:
- inomapsize = blkmapsize = sumsize = 0; /* keep lint happy */
- errx(EEXIT, "UNKNOWN ROTATIONAL TABLE FORMAT %d",
- fs->fs_postblformat);
+ basesize = &newcg->cg_space[0] - (u_char *)(&newcg->cg_firstfield);
+ if (sblock.fs_magic == FS_UFS2_MAGIC) {
+ newcg->cg_iusedoff = basesize;
+ } else {
+ /*
+ * We reserve the space for the old rotation summary
+ * tables for the benefit of old kernels, but do not
+ * maintain them in modern kernels. In time, they can
+ * go away.
+ */
+ newcg->cg_old_btotoff = basesize;
+ newcg->cg_old_boff = newcg->cg_old_btotoff +
+ fs->fs_old_cpg * sizeof(int32_t);
+ newcg->cg_iusedoff = newcg->cg_old_boff +
+ fs->fs_old_cpg * fs->fs_old_nrpos * sizeof(u_int16_t);
+ memset(&newcg->cg_space[0], 0, newcg->cg_iusedoff - basesize);
+ }
+ inomapsize = howmany(fs->fs_ipg, NBBY);
+ newcg->cg_freeoff = newcg->cg_iusedoff + inomapsize;
+ blkmapsize = howmany(fs->fs_fpg, NBBY);
+ newcg->cg_nextfreeoff = newcg->cg_freeoff + blkmapsize;
+ if (fs->fs_contigsumsize > 0) {
+ newcg->cg_clustersumoff = newcg->cg_nextfreeoff -
+ sizeof(u_int32_t);
+ newcg->cg_clustersumoff =
+ roundup(newcg->cg_clustersumoff, sizeof(u_int32_t));
+ newcg->cg_clusteroff = newcg->cg_clustersumoff +
+ (fs->fs_contigsumsize + 1) * sizeof(u_int32_t);
+ newcg->cg_nextfreeoff = newcg->cg_clusteroff +
+ howmany(fragstoblks(fs, fs->fs_fpg), NBBY);
}
+ newcg->cg_magic = CG_MAGIC;
+ mapsize = newcg->cg_nextfreeoff - newcg->cg_iusedoff;
memset(&idesc[0], 0, sizeof idesc);
for (i = 0; i < 3; i++)
idesc[i].id_type = ADDR;
- memset(&cstotal, 0, sizeof(struct csum));
- j = blknum(fs, fs->fs_size + fs->fs_frag - 1);
- for (i = fs->fs_size; i < j; i++)
- setbmap(i);
+ memset(&cstotal, 0, sizeof(struct csum_total));
+ dmax = blknum(fs, fs->fs_size + fs->fs_frag - 1);
+ for (d = fs->fs_size; d < dmax; d++)
+ setbmap(d);
for (c = 0; c < fs->fs_ncg; c++) {
if (got_siginfo) {
printf("%s: phase 5: cyl group %d of %d (%d%%)\n",
@@ -177,17 +159,23 @@ pass5(void)
getblk(&cgblk, cgtod(fs, c), fs->fs_cgsize);
if (!cg_chkmagic(cg))
pfatal("CG %d: BAD MAGIC NUMBER\n", c);
+ newcg->cg_time = cg->cg_time;
+ newcg->cg_old_time = cg->cg_old_time;
+ newcg->cg_cgx = c;
dbase = cgbase(fs, c);
dmax = dbase + fs->fs_fpg;
if (dmax > fs->fs_size)
dmax = fs->fs_size;
- newcg->cg_time = cg->cg_time;
- newcg->cg_cgx = c;
- if (c == fs->fs_ncg - 1 && fs->fs_ncyl % fs->fs_cpg > 0)
- newcg->cg_ncyl = fs->fs_ncyl % fs->fs_cpg;
- else
- newcg->cg_ncyl = fs->fs_cpg;
newcg->cg_ndblk = dmax - dbase;
+ if (fs->fs_magic == FS_UFS1_MAGIC) {
+ if (c == fs->fs_ncg - 1)
+ newcg->cg_old_ncyl = howmany(newcg->cg_ndblk,
+ fs->fs_fpg / fs->fs_old_cpg);
+ else
+ newcg->cg_old_ncyl = fs->fs_old_cpg;
+ newcg->cg_old_niblk = fs->fs_ipg;
+ newcg->cg_niblk = 0;
+ }
if (fs->fs_contigsumsize > 0)
newcg->cg_nclusterblks = newcg->cg_ndblk / fs->fs_frag;
newcg->cg_cs.cs_ndir = 0;
@@ -206,11 +194,16 @@ pass5(void)
newcg->cg_irotor = cg->cg_irotor;
else
newcg->cg_irotor = 0;
+ if (fs->fs_magic == FS_UFS1_MAGIC) {
+ newcg->cg_initediblk = 0;
+ } else {
+ if ((unsigned)cg->cg_initediblk > fs->fs_ipg)
+ newcg->cg_initediblk = fs->fs_ipg;
+ else
+ newcg->cg_initediblk = cg->cg_initediblk;
+ }
memset(&newcg->cg_frsum[0], 0, sizeof newcg->cg_frsum);
- memset(&cg_blktot(newcg)[0], 0,
- (size_t)(sumsize + mapsize));
- if (fs->fs_postblformat == FS_42POSTBLFMT)
- ocg->cg_magic = CG_MAGIC;
+ memset(cg_inosused(newcg), 0, (size_t)(mapsize));
j = fs->fs_ipg * c;
for (i = 0; i < inostathead[c].il_numalloced; j++, i++) {
switch (inoinfo(j)->ino_state) {
@@ -254,9 +247,6 @@ pass5(void)
}
if (frags == fs->fs_frag) {
newcg->cg_cs.cs_nbfree++;
- j = cbtocylno(fs, i);
- cg_blktot(newcg)[j]++;
- cg_blks(fs, newcg, j)[cbtorpos(fs, i)]++;
if (fs->fs_contigsumsize > 0)
setbit(cg_clustersfree(newcg),
i / fs->fs_frag);
@@ -312,13 +302,9 @@ pass5(void)
continue;
}
if (cursnapshot == 0 &&
- (memcmp(newcg, cg, basesize) != 0 ||
- memcmp(&cg_blktot(newcg)[0],
- &cg_blktot(cg)[0], sumsize) != 0) &&
+ memcmp(newcg, cg, basesize) != 0 &&
dofix(&idesc[2], "SUMMARY INFORMATION BAD")) {
memmove(cg, newcg, (size_t)basesize);
- memmove(&cg_blktot(cg)[0],
- &cg_blktot(newcg)[0], (size_t)sumsize);
cgdirty();
}
if (bkgrdflag != 0 || usedsoftdep || debug) {
@@ -346,12 +332,10 @@ pass5(void)
cgdirty();
}
}
- if (fs->fs_postblformat == FS_42POSTBLFMT)
- fs->fs_nrpos = savednrpos;
if (cursnapshot == 0 &&
- memcmp(&cstotal, &fs->fs_cstotal, sizeof *cs) != 0
- && dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) {
- memmove(&fs->fs_cstotal, &cstotal, sizeof *cs);
+ memcmp(&cstotal, &fs->fs_cstotal, sizeof cstotal) != 0
+ && dofix(&idesc[0], "SUMMARY BLK COUNT(S) WRONG IN SUPERBLK")) {
+ memmove(&fs->fs_cstotal, &cstotal, sizeof cstotal);
fs->fs_ronly = 0;
fs->fs_fmod = 0;
sbdirty();
@@ -398,6 +382,7 @@ check_maps(
aend = n;
continue;
}
+ returntosingle = 1;
if (astart == aend)
(*msg)("ALLOCATED %s %d MARKED FREE\n",
name, astart);
@@ -434,6 +419,7 @@ check_maps(
pwarn("%s %sS %d-%ld MARKED USED\n",
"UNALLOCATED", name, ustart,
ustart + size - 1);
+ returntosingle = 1;
if (bkgrdflag != 0) {
cmd.value = ustart;
cmd.size = size;
@@ -476,6 +462,7 @@ check_maps(
pwarn("UNALLOCATED %sS %d-%ld MARKED USED\n",
name, ustart, ustart + size - 1);
}
+ returntosingle = 1;
if (bkgrdflag != 0) {
cmd.value = ustart;
cmd.size = size;
diff --git a/sbin/fsck_ffs/setup.c b/sbin/fsck_ffs/setup.c
index 107ded23c025..243edbec7f3a 100644
--- a/sbin/fsck_ffs/setup.c
+++ b/sbin/fsck_ffs/setup.c
@@ -210,7 +210,8 @@ setup(char *dev)
sbdirty();
}
}
- if (sblock.fs_inodefmt < FS_44INODEFMT) {
+ if (sblock.fs_magic == FS_UFS1_MAGIC &&
+ sblock.fs_old_inodefmt < FS_44INODEFMT) {
pwarn("Format of filesystem is too old.\n");
pwarn("Must update to modern format using a version of fsck\n");
pfatal("from before 2002 with the command ``fsck -c 2''\n");
@@ -286,28 +287,43 @@ badsb:
}
/*
+ * Possible superblock locations ordered from most to least likely.
+ */
+static int sblock_try[] = SBLOCKSEARCH;
+
+/*
* Read in the super block and its summary info.
*/
int
readsb(int listerr)
{
- ufs_daddr_t super = bflag ? bflag : SBOFF / dev_bsize;
+ ufs2_daddr_t super;
+ int i;
- if (bread(fsreadfd, (char *)&sblock, super, (long)SBSIZE) != 0)
- return (0);
- sblk.b_bno = super;
- sblk.b_size = SBSIZE;
- /*
- * run a few consistency checks of the super block
- */
- if (sblock.fs_magic != FS_MAGIC)
- { badsb(listerr, "MAGIC NUMBER WRONG"); return (0); }
- if (sblock.fs_ncg < 1)
- { badsb(listerr, "NCG OUT OF RANGE"); return (0); }
- if (sblock.fs_cpg < 1)
- { badsb(listerr, "CPG OUT OF RANGE"); return (0); }
- if (sblock.fs_sbsize > SBSIZE)
- { badsb(listerr, "SIZE PREPOSTEROUSLY LARGE"); return (0); }
+ if (bflag) {
+ super = bflag;
+ if ((bread(fsreadfd, (char *)&sblock, super, (long)SBLOCKSIZE)))
+ return (0);
+ } else {
+ for (i = 0; sblock_try[i] != -1; i++) {
+ super = sblock_try[i] / dev_bsize;
+ if ((bread(fsreadfd, (char *)&sblock, super,
+ (long)SBLOCKSIZE)))
+ return (0);
+ if ((sblock.fs_magic == FS_UFS1_MAGIC ||
+ (sblock.fs_magic == FS_UFS2_MAGIC &&
+ sblock.fs_sblockloc ==
+ numfrags(&sblock, sblock_try[i]))) &&
+ sblock.fs_ncg >= 1 &&
+ sblock.fs_bsize >= SBLOCKSIZE &&
+ sblock.fs_bsize >= sizeof(struct fs))
+ break;
+ }
+ if (sblock_try[i] == -1) {
+ fprintf(stderr, "Cannot find filesystem superblock\n");
+ return (0);
+ }
+ }
/*
* Compute block size that the filesystem is based on,
* according to fsbtodb, and adjust superblock block number
@@ -316,6 +332,7 @@ readsb(int listerr)
super *= dev_bsize;
dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1);
sblk.b_bno = super / dev_bsize;
+ sblk.b_size = SBLOCKSIZE;
if (bflag) {
havesb = 1;
return (1);
@@ -331,8 +348,6 @@ readsb(int listerr)
altsblock.fs_cblkno != sblock.fs_cblkno ||
altsblock.fs_iblkno != sblock.fs_iblkno ||
altsblock.fs_dblkno != sblock.fs_dblkno ||
- altsblock.fs_cgoffset != sblock.fs_cgoffset ||
- altsblock.fs_cgmask != sblock.fs_cgmask ||
altsblock.fs_ncg != sblock.fs_ncg ||
altsblock.fs_bsize != sblock.fs_bsize ||
altsblock.fs_fsize != sblock.fs_fsize ||
@@ -347,7 +362,6 @@ readsb(int listerr)
altsblock.fs_nindir != sblock.fs_nindir ||
altsblock.fs_inopb != sblock.fs_inopb ||
altsblock.fs_cssize != sblock.fs_cssize ||
- altsblock.fs_cpg != sblock.fs_cpg ||
altsblock.fs_ipg != sblock.fs_ipg ||
altsblock.fs_fpg != sblock.fs_fpg ||
altsblock.fs_magic != sblock.fs_magic) {
@@ -355,6 +369,21 @@ readsb(int listerr)
"VALUES IN SUPER BLOCK DISAGREE WITH THOSE IN FIRST ALTERNATE");
return (0);
}
+ /*
+ * If not yet done, update UFS1 superblock with new wider fields.
+ */
+ if (sblock.fs_magic == FS_UFS1_MAGIC &&
+ sblock.fs_maxbsize != sblock.fs_bsize) {
+ sblock.fs_maxbsize = sblock.fs_bsize;
+ sblock.fs_time = sblock.fs_old_time;
+ sblock.fs_size = sblock.fs_old_size;
+ sblock.fs_dsize = sblock.fs_old_dsize;
+ sblock.fs_csaddr = sblock.fs_old_csaddr;
+ sblock.fs_cstotal.cs_ndir = sblock.fs_old_cstotal.cs_ndir;
+ sblock.fs_cstotal.cs_nbfree = sblock.fs_old_cstotal.cs_nbfree;
+ sblock.fs_cstotal.cs_nifree = sblock.fs_old_cstotal.cs_nifree;
+ sblock.fs_cstotal.cs_nffree = sblock.fs_old_cstotal.cs_nffree;
+ }
havesb = 1;
return (1);
}
@@ -380,8 +409,8 @@ sblock_init(void)
lfdir = 0;
initbarea(&sblk);
initbarea(&asblk);
- sblk.b_un.b_buf = malloc(SBSIZE);
- asblk.b_un.b_buf = malloc(SBSIZE);
+ sblk.b_un.b_buf = malloc(SBLOCKSIZE);
+ asblk.b_un.b_buf = malloc(SBLOCKSIZE);
if (sblk.b_un.b_buf == NULL || asblk.b_un.b_buf == NULL)
errx(EEXIT, "cannot allocate space for superblock");
if ((lp = getdisklabel(NULL, fsreadfd)))
@@ -402,7 +431,7 @@ calcsb(char *dev, int devfd, struct fs *fs)
struct disklabel *lp;
struct partition *pp;
char *cp;
- int i;
+ int i, nspf;
cp = strchr(dev, '\0') - 1;
if (cp == (char *)-1 || ((*cp < 'a' || *cp > 'h') && !isdigit(*cp))) {
@@ -430,24 +459,30 @@ calcsb(char *dev, int devfd, struct fs *fs)
memset(fs, 0, sizeof(struct fs));
fs->fs_fsize = pp->p_fsize;
fs->fs_frag = pp->p_frag;
- fs->fs_cpg = pp->p_cpg;
fs->fs_size = pp->p_size;
- fs->fs_ntrak = lp->d_ntracks;
- fs->fs_nsect = lp->d_nsectors;
- fs->fs_spc = lp->d_secpercyl;
- fs->fs_nspf = fs->fs_fsize / lp->d_secsize;
- fs->fs_cgmask = 0xffffffff;
- for (i = fs->fs_ntrak; i > 1; i >>= 1)
- fs->fs_cgmask <<= 1;
- if (!POWEROF2(fs->fs_ntrak))
- fs->fs_cgmask <<= 1;
- fs->fs_cgoffset = roundup(
- howmany(fs->fs_nsect, NSPF(fs)), fs->fs_frag);
- fs->fs_fpg = (fs->fs_cpg * fs->fs_spc) / NSPF(fs);
- fs->fs_ncg = howmany(fs->fs_size / fs->fs_spc, fs->fs_cpg);
- for (fs->fs_fsbtodb = 0, i = NSPF(fs); i > 1; i >>= 1)
+ fs->fs_sblkno = roundup(
+ howmany(lp->d_bbsize + lp->d_sbsize, fs->fs_fsize),
+ fs->fs_frag);
+ nspf = fs->fs_fsize / lp->d_secsize;
+ for (fs->fs_fsbtodb = 0, i = nspf; i > 1; i >>= 1)
fs->fs_fsbtodb++;
dev_bsize = lp->d_secsize;
+ if (fs->fs_magic == FS_UFS2_MAGIC) {
+ fs->fs_fpg = pp->p_cpg;
+ fs->fs_ncg = howmany(fs->fs_size, fs->fs_fpg);
+ } else /* if (fs->fs_magic == FS_UFS1_MAGIC) */ {
+ fs->fs_old_cpg = pp->p_cpg;
+ fs->fs_old_cgmask = 0xffffffff;
+ for (i = lp->d_ntracks; i > 1; i >>= 1)
+ fs->fs_old_cgmask <<= 1;
+ if (!POWEROF2(lp->d_ntracks))
+ fs->fs_old_cgmask <<= 1;
+ fs->fs_old_cgoffset = roundup(howmany(lp->d_nsectors, nspf),
+ fs->fs_frag);
+ fs->fs_fpg = (fs->fs_old_cpg * lp->d_secpercyl) / nspf;
+ fs->fs_ncg = howmany(fs->fs_size / lp->d_secpercyl,
+ fs->fs_old_cpg);
+ }
return (1);
}
diff --git a/sbin/fsdb/fsdb.c b/sbin/fsdb/fsdb.c
index 0f32762a1be7..9971b7c69dc8 100644
--- a/sbin/fsdb/fsdb.c
+++ b/sbin/fsdb/fsdb.c
@@ -280,7 +280,7 @@ cmdloop(void)
return rval;
}
-struct dinode *curinode;
+union dinode *curinode;
ino_t curinum, ocurrent;
#define GETINUM(ac,inum) inum = strtoul(argv[ac], &cp, 0); \
@@ -317,7 +317,7 @@ CMDFUNCSTART(back)
CMDFUNCSTART(zapi)
{
ino_t inum;
- struct dinode *dp;
+ union dinode *dp;
char *cp;
GETINUM(1,inum);
@@ -350,7 +350,8 @@ CMDFUNCSTART(uplink)
{
if (!checkactive())
return 1;
- printf("inode %d link count now %d\n", curinum, ++curinode->di_nlink);
+ DIP(curinode, di_nlink) += 1;
+ printf("inode %d link count now %d\n", curinum, DIP(curinode, di_nlink));
inodirty();
return 0;
}
@@ -359,7 +360,8 @@ CMDFUNCSTART(downlink)
{
if (!checkactive())
return 1;
- printf("inode %d link count now %d\n", curinum, --curinode->di_nlink);
+ DIP(curinode, di_nlink) -= 1;
+ printf("inode %d link count now %d\n", curinum, DIP(curinode, di_nlink));
inodirty();
return 0;
}
@@ -617,7 +619,7 @@ CMDFUNCSTART(newtype)
if (!checkactive())
return 1;
- type = curinode->di_mode & IFMT;
+ type = DIP(curinode, di_mode) & IFMT;
for (tp = typenamemap;
tp < &typenamemap[sizeof(typenamemap)/sizeof(*typenamemap)];
tp++) {
@@ -632,8 +634,8 @@ CMDFUNCSTART(newtype)
warnx("try one of `file', `dir', `socket', `fifo'");
return 1;
}
- curinode->di_mode &= ~IFMT;
- curinode->di_mode |= type;
+ DIP(curinode, di_mode) &= ~IFMT;
+ DIP(curinode, di_mode) |= type;
inodirty();
printactive(0);
return 0;
@@ -654,7 +656,7 @@ CMDFUNCSTART(chlen)
return 1;
}
- curinode->di_size = len;
+ DIP(curinode, di_size) = len;
inodirty();
printactive(0);
return rval;
@@ -675,8 +677,8 @@ CMDFUNCSTART(chmode)
return 1;
}
- curinode->di_mode &= ~07777;
- curinode->di_mode |= modebits;
+ DIP(curinode, di_mode) &= ~07777;
+ DIP(curinode, di_mode) |= modebits;
inodirty();
printactive(0);
return rval;
@@ -701,7 +703,7 @@ CMDFUNCSTART(chaflags)
warnx("flags set beyond 32-bit range of field (%lx)\n", flags);
return(1);
}
- curinode->di_flags = flags;
+ DIP(curinode, di_flags) = flags;
inodirty();
printactive(0);
return rval;
@@ -726,7 +728,7 @@ CMDFUNCSTART(chgen)
warnx("gen set beyond 32-bit range of field (%lx)\n", gen);
return(1);
}
- curinode->di_gen = gen;
+ DIP(curinode, di_gen) = gen;
inodirty();
printactive(0);
return rval;
@@ -751,7 +753,7 @@ CMDFUNCSTART(linkcount)
return 1;
}
- curinode->di_nlink = lcnt;
+ DIP(curinode, di_nlink) = lcnt;
inodirty();
printactive(0);
return rval;
@@ -778,7 +780,7 @@ CMDFUNCSTART(chowner)
}
}
- curinode->di_uid = uid;
+ DIP(curinode, di_uid) = uid;
inodirty();
printactive(0);
return rval;
@@ -804,18 +806,17 @@ CMDFUNCSTART(chgroup)
}
}
- curinode->di_gid = gid;
+ DIP(curinode, di_gid) = gid;
inodirty();
printactive(0);
return rval;
}
int
-dotime(char *name, struct timespec *rts)
+dotime(char *name, time_t *secp, int32_t *nsecp)
{
char *p, *val;
struct tm t;
- int32_t sec;
int32_t nsec;
p = strchr(name, '.');
if (p) {
@@ -832,6 +833,7 @@ badformat:
warnx("date format: YYYYMMDDHHMMSS[.nsec]");
return 1;
}
+ *nsecp = nsec;
for (p = name; *p; p++)
if (*p < '0' || *p > '9')
@@ -855,20 +857,26 @@ badformat:
t.tm_sec = VAL() + t.tm_sec * 10;
t.tm_isdst = -1;
- sec = mktime(&t);
- if (sec == -1) {
+ *secp = mktime(&t);
+ if (*secp == -1) {
warnx("date/time out of range");
return 1;
}
- rts->tv_sec = sec;
- rts->tv_nsec = nsec;
return 0;
}
CMDFUNCSTART(chmtime)
{
- if (dotime(argv[1], &curinode->di_ctime))
+ time_t secs;
+ int32_t nsecs;
+
+ if (dotime(argv[1], &secs, &nsecs))
return 1;
+ if (sblock.fs_magic == FS_UFS1_MAGIC)
+ curinode->dp1.di_mtime = _time_to_time32(secs);
+ else
+ curinode->dp2.di_mtime = _time_to_time64(secs);
+ DIP(curinode, di_mtimensec) = nsecs;
inodirty();
printactive(0);
return 0;
@@ -876,8 +884,16 @@ CMDFUNCSTART(chmtime)
CMDFUNCSTART(chatime)
{
- if (dotime(argv[1], &curinode->di_ctime))
+ time_t secs;
+ int32_t nsecs;
+
+ if (dotime(argv[1], &secs, &nsecs))
return 1;
+ if (sblock.fs_magic == FS_UFS1_MAGIC)
+ curinode->dp1.di_atime = _time_to_time32(secs);
+ else
+ curinode->dp2.di_atime = _time_to_time64(secs);
+ DIP(curinode, di_atimensec) = nsecs;
inodirty();
printactive(0);
return 0;
@@ -885,8 +901,16 @@ CMDFUNCSTART(chatime)
CMDFUNCSTART(chctime)
{
- if (dotime(argv[1], &curinode->di_ctime))
+ time_t secs;
+ int32_t nsecs;
+
+ if (dotime(argv[1], &secs, &nsecs))
return 1;
+ if (sblock.fs_magic == FS_UFS1_MAGIC)
+ curinode->dp1.di_ctime = _time_to_time32(secs);
+ else
+ curinode->dp2.di_ctime = _time_to_time64(secs);
+ DIP(curinode, di_ctimensec) = nsecs;
inodirty();
printactive(0);
return 0;
diff --git a/sbin/fsdb/fsdb.h b/sbin/fsdb/fsdb.h
index be1601627e7f..442ae12d6683 100644
--- a/sbin/fsdb/fsdb.h
+++ b/sbin/fsdb/fsdb.h
@@ -30,9 +30,9 @@
* $FreeBSD$
*/
-extern int bread(int fd, char *buf, ufs_daddr_t blk, long size);
-extern void bwrite(int fd, char *buf, ufs_daddr_t blk, long size);
-extern void rwerror(char *mesg, ufs_daddr_t blk);
+extern int bread(int fd, char *buf, ufs2_daddr_t blk, long size);
+extern void bwrite(int fd, char *buf, ufs2_daddr_t blk, long size);
+extern void rwerror(char *mesg, ufs2_daddr_t blk);
extern int reply(char *question);
extern long dev_bsize;
@@ -50,13 +50,13 @@ struct cmdtable {
#define FL_WR 0x0001 /* wants to write */
int (*handler)(int argc, char *argv[]);
};
-extern struct dinode *curinode;
+extern union dinode *curinode;
extern ino_t curinum;
int argcount(struct cmdtable *cmdp, int argc, char *argv[]);
char **crack(char *line, int *argc);
char **recrack(char *line, int *argc, int argc_max);
-void printstat(const char *cp, ino_t inum, struct dinode *dp);
+void printstat(const char *cp, ino_t inum, union dinode *dp);
int printactive(int doblocks);
int checkactive(void);
int checkactivedir(void);
diff --git a/sbin/fsdb/fsdbutil.c b/sbin/fsdb/fsdbutil.c
index 96c48b0e77c9..b0d4c1244829 100644
--- a/sbin/fsdb/fsdbutil.c
+++ b/sbin/fsdb/fsdbutil.c
@@ -50,8 +50,8 @@ static const char rcsid[] =
#include "fsck.h"
static int charsperline(void);
-static int printindir(ufs_daddr_t blk, int level, char *bufp);
-static void printblocks(ino_t inum, struct dinode *dp);
+static int printindir(ufs2_daddr_t blk, int level, char *bufp);
+static void printblocks(ino_t inum, union dinode *dp);
char **
crack(char *line, int *argc)
@@ -106,15 +106,17 @@ argcount(struct cmdtable *cmdp, int argc, char *argv[])
}
void
-printstat(const char *cp, ino_t inum, struct dinode *dp)
+printstat(const char *cp, ino_t inum, union dinode *dp)
{
struct group *grp;
struct passwd *pw;
+ ufs2_daddr_t blocks;
+ int64_t gen;
char *p;
time_t t;
printf("%s: ", cp);
- switch (dp->di_mode & IFMT) {
+ switch (DIP(dp, di_mode) & IFMT) {
case IFDIR:
puts("directory");
break;
@@ -123,19 +125,25 @@ printstat(const char *cp, ino_t inum, struct dinode *dp)
break;
case IFBLK:
printf("block special (%d,%d)",
- major(dp->di_rdev), minor(dp->di_rdev));
+ major(DIP(dp, di_rdev)), minor(DIP(dp, di_rdev)));
break;
case IFCHR:
printf("character special (%d,%d)",
- major(dp->di_rdev), minor(dp->di_rdev));
+ major(DIP(dp, di_rdev)), minor(DIP(dp, di_rdev)));
break;
case IFLNK:
fputs("symlink",stdout);
- if (dp->di_size > 0 && dp->di_size < MAXSYMLINKLEN &&
- dp->di_blocks == 0)
- printf(" to `%.*s'\n", (int) dp->di_size, (char *)dp->di_shortlink);
- else
- putchar('\n');
+ if (DIP(dp, di_size) > 0 &&
+ DIP(dp, di_size) < sblock.fs_maxsymlinklen &&
+ DIP(dp, di_blocks) == 0) {
+ if (sblock.fs_magic == FS_UFS1_MAGIC)
+ p = (caddr_t)dp->dp1.di_db;
+ else
+ p = (caddr_t)dp->dp2.di_db;
+ printf(" to `%.*s'\n", (int) DIP(dp, di_size), p);
+ } else {
+ putchar('\n');
+ }
break;
case IFSOCK:
puts("socket");
@@ -144,31 +152,43 @@ printstat(const char *cp, ino_t inum, struct dinode *dp)
puts("fifo");
break;
}
- printf("I=%lu MODE=%o SIZE=%qu", (u_long)inum, dp->di_mode, dp->di_size);
- t = dp->di_mtime;
+ printf("I=%lu MODE=%o SIZE=%qu", (u_long)inum, DIP(dp, di_mode),
+ DIP(dp, di_size));
+ if (sblock.fs_magic == FS_UFS1_MAGIC)
+ t = _time32_to_time(dp->dp1.di_mtime);
+ else
+ t = _time64_to_time(dp->dp2.di_mtime);
p = ctime(&t);
printf("\n\tMTIME=%15.15s %4.4s [%d nsec]", &p[4], &p[20],
- dp->di_mtimensec);
- t = dp->di_ctime;
+ DIP(dp, di_mtimensec));
+ if (sblock.fs_magic == FS_UFS1_MAGIC)
+ t = _time32_to_time(dp->dp1.di_ctime);
+ else
+ t = _time64_to_time(dp->dp2.di_ctime);
p = ctime(&t);
printf("\n\tCTIME=%15.15s %4.4s [%d nsec]", &p[4], &p[20],
- dp->di_ctimensec);
- t = dp->di_atime;
+ DIP(dp, di_ctimensec));
+ if (sblock.fs_magic == FS_UFS1_MAGIC)
+ t = _time32_to_time(dp->dp1.di_atime);
+ else
+ t = _time64_to_time(dp->dp2.di_atime);
p = ctime(&t);
printf("\n\tATIME=%15.15s %4.4s [%d nsec]\n", &p[4], &p[20],
- dp->di_atimensec);
+ DIP(dp, di_atimensec));
- if ((pw = getpwuid(dp->di_uid)))
+ if ((pw = getpwuid(DIP(dp, di_uid))))
printf("OWNER=%s ", pw->pw_name);
else
- printf("OWNUID=%u ", dp->di_uid);
- if ((grp = getgrgid(dp->di_gid)))
+ printf("OWNUID=%u ", DIP(dp, di_uid));
+ if ((grp = getgrgid(DIP(dp, di_gid))))
printf("GRP=%s ", grp->gr_name);
else
- printf("GID=%u ", dp->di_gid);
+ printf("GID=%u ", DIP(dp, di_gid));
- printf("LINKCNT=%hd FLAGS=%#x BLKCNT=%x GEN=%x\n", dp->di_nlink, dp->di_flags,
- dp->di_blocks, dp->di_gen);
+ blocks = DIP(dp, di_blocks);
+ gen = DIP(dp, di_gen);
+ printf("LINKCNT=%hd FLAGS=%#x BLKCNT=%qx GEN=%qx\n", DIP(dp, di_nlink),
+ DIP(dp, di_flags), blocks, gen);
}
@@ -199,12 +219,12 @@ charsperline(void)
* Recursively print a list of indirect blocks.
*/
static int
-printindir(ufs_daddr_t blk, int level, char *bufp)
+printindir(ufs2_daddr_t blk, int level, char *bufp)
{
struct bufarea buf, *bp;
- char tempbuf[32]; /* enough to print an ufs_daddr_t */
+ char tempbuf[32]; /* enough to print an ufs2_daddr_t */
int i, j, cpl, charssofar;
- ufs_daddr_t blkno;
+ ufs2_daddr_t blkno;
if (level == 0) {
/* for the final indirect level, don't use the cache */
@@ -219,13 +239,16 @@ printindir(ufs_daddr_t blk, int level, char *bufp)
cpl = charsperline();
for (i = charssofar = 0; i < NINDIR(&sblock); i++) {
- blkno = bp->b_un.b_indir[i];
+ if (sblock.fs_magic == FS_UFS1_MAGIC)
+ blkno = bp->b_un.b_indir1[i];
+ else
+ blkno = bp->b_un.b_indir2[i];
if (blkno == 0) {
if (level == 0)
putchar('\n');
return 0;
}
- j = sprintf(tempbuf, "%d", blkno);
+ j = sprintf(tempbuf, "%qd", blkno);
if (level == 0) {
charssofar += j;
if (charssofar >= cpl - 2) {
@@ -253,30 +276,32 @@ printindir(ufs_daddr_t blk, int level, char *bufp)
* Print the block pointers for one inode.
*/
static void
-printblocks(ino_t inum, struct dinode *dp)
+printblocks(ino_t inum, union dinode *dp)
{
char *bufp;
int i, j, nfrags;
long ndb, offset;
+ ufs2_daddr_t blkno;
printf("Blocks for inode %d:\n", inum);
printf("Direct blocks:\n");
- ndb = howmany(dp->di_size, sblock.fs_bsize);
+ ndb = howmany(DIP(dp, di_size), sblock.fs_bsize);
for (i = 0; i < NDADDR; i++) {
- if (dp->di_db[i] == 0) {
+ if (DIP(dp, di_db[i]) == 0) {
putchar('\n');
return;
}
if (i > 0)
printf(", ");
- printf("%d", dp->di_db[i]);
- if (--ndb == 0 && (offset = blkoff(&sblock, dp->di_size)) != 0) {
+ blkno = DIP(dp, di_db[i]);
+ printf("%qd", blkno);
+ if (--ndb == 0 && (offset = blkoff(&sblock, DIP(dp, di_size))) != 0) {
nfrags = numfrags(&sblock, fragroundup(&sblock, offset));
printf(" (%d frag%s)", nfrags, nfrags > 1? "s": "");
}
}
putchar('\n');
- if (dp->di_ib[0] == 0)
+ if (DIP(dp, di_ib[0]) == 0)
return;
bufp = malloc((unsigned int)sblock.fs_bsize);
@@ -284,7 +309,7 @@ printblocks(ino_t inum, struct dinode *dp)
errx(EEXIT, "cannot allocate indirect block buffer");
printf("Indirect blocks:\n");
for (i = 0; i < NIADDR; i++)
- if (printindir(dp->di_ib[i], i, bufp) == 0)
+ if (printindir(DIP(dp, di_ib[i]), i, bufp) == 0)
break;
free(bufp);
}
@@ -307,7 +332,7 @@ checkactivedir(void)
warnx("no current inode\n");
return 0;
}
- if ((curinode->di_mode & IFMT) != IFDIR) {
+ if ((DIP(curinode, di_mode) & IFMT) != IFDIR) {
warnx("inode %d not a directory", curinum);
return 0;
}
@@ -319,7 +344,7 @@ printactive(int doblocks)
{
if (!checkactive())
return 1;
- switch (curinode->di_mode & IFMT) {
+ switch (DIP(curinode, di_mode) & IFMT) {
case IFDIR:
case IFREG:
case IFBLK:
@@ -337,7 +362,7 @@ printactive(int doblocks)
break;
default:
printf("current inode %d: screwy itype 0%o (mode 0%o)?\n",
- curinum, curinode->di_mode & IFMT, curinode->di_mode);
+ curinum, DIP(curinode, di_mode) & IFMT, DIP(curinode, di_mode));
break;
}
return 0;
diff --git a/sbin/fsirand/fsirand.c b/sbin/fsirand/fsirand.c
index e908f2aba71a..2e555be6c6cb 100644
--- a/sbin/fsirand/fsirand.c
+++ b/sbin/fsirand/fsirand.c
@@ -40,8 +40,8 @@ static const char rcsid[] =
#include <sys/time.h>
#include <sys/resource.h>
-#include <ufs/ffs/fs.h>
#include <ufs/ufs/dinode.h>
+#include <ufs/ffs/fs.h>
#include <err.h>
#include <errno.h>
@@ -54,6 +54,11 @@ static const char rcsid[] =
static void usage(void) __dead2;
int fsirand(char *);
+/*
+ * Possible superblock locations ordered from most to least likely.
+ */
+static int sblock_try[] = SBLOCKSEARCH;
+
int printonly = 0, force = 0, ignorelabel = 0;
int
@@ -104,14 +109,15 @@ main(int argc, char *argv[])
int
fsirand(char *device)
{
- static struct dinode *inodebuf;
- static size_t oldibufsize;
+ struct ufs1_dinode *dp1;
+ struct ufs2_dinode *dp2;
+ caddr_t inodebuf;
size_t ibufsize;
struct fs *sblock;
ino_t inumber, maxino;
- daddr_t dblk;
- char sbuf[SBSIZE], sbuftmp[SBSIZE];
- int devfd, n, cg;
+ ufs2_daddr_t sblockloc, dblk;
+ char sbuf[SBLOCKSIZE], sbuftmp[SBLOCKSIZE];
+ int i, devfd, n, cg;
u_int32_t bsize = DEV_BSIZE;
struct disklabel label;
@@ -132,27 +138,34 @@ fsirand(char *device)
/* Read in master superblock */
(void)memset(&sbuf, 0, sizeof(sbuf));
sblock = (struct fs *)&sbuf;
- if (lseek(devfd, SBOFF, SEEK_SET) == -1) {
- warn("can't seek to superblock (%qd) on %s", SBOFF, device);
- return (1);
+ for (i = 0; sblock_try[i] != -1; i++) {
+ sblockloc = sblock_try[i];
+ if (lseek(devfd, sblockloc, SEEK_SET) == -1) {
+ warn("can't seek to superblock (%qd) on %s",
+ sblockloc, device);
+ return (1);
+ }
+ if ((n = read(devfd, (void *)sblock, SBLOCKSIZE))!=SBLOCKSIZE) {
+ warnx("can't read superblock on %s: %s", device,
+ (n < SBLOCKSIZE) ? "short read" : strerror(errno));
+ return (1);
+ }
+ if ((sblock->fs_magic == FS_UFS1_MAGIC ||
+ (sblock->fs_magic == FS_UFS2_MAGIC &&
+ sblock->fs_sblockloc ==
+ numfrags(sblock, sblock_try[i]))) &&
+ sblock->fs_bsize <= MAXBSIZE &&
+ sblock->fs_bsize >= sizeof(struct fs))
+ break;
}
- if ((n = read(devfd, (void *)sblock, SBSIZE)) != SBSIZE) {
- warnx("can't read superblock on %s: %s", device,
- (n < SBSIZE) ? "short read" : strerror(errno));
+ if (sblock_try[i] == -1) {
+ fprintf(stderr, "Cannot find filesystem superblock\n");
return (1);
}
maxino = sblock->fs_ncg * sblock->fs_ipg;
- /* Simple sanity checks on the superblock */
- if (sblock->fs_magic != FS_MAGIC) {
- warnx("bad magic number in superblock");
- return (1);
- }
- if (sblock->fs_sbsize > SBSIZE) {
- warnx("superblock size is preposterous");
- return (1);
- }
- if (sblock->fs_postblformat == FS_42POSTBLFMT) {
+ if (sblock->fs_magic == FS_UFS1_MAGIC &&
+ sblock->fs_old_inodefmt < FS_44INODEFMT) {
warnx("filesystem format is too old, sorry");
return (1);
}
@@ -168,18 +181,19 @@ fsirand(char *device)
if (lseek(devfd, (off_t)dblk * bsize, SEEK_SET) < 0) {
warn("can't seek to %qd", (off_t)dblk * bsize);
return (1);
- } else if ((n = write(devfd, (void *)sblock, SBSIZE)) != SBSIZE) {
+ } else if ((n = write(devfd, (void *)sblock, SBLOCKSIZE)) != SBLOCKSIZE) {
warn("can't read backup superblock %d on %s: %s",
- cg + 1, device, (n < SBSIZE) ? "short write"
+ cg + 1, device, (n < SBLOCKSIZE) ? "short write"
: strerror(errno));
return (1);
}
- if (sblock->fs_magic != FS_MAGIC) {
+ if (sblock->fs_magic != FS_UFS1_MAGIC &&
+ sblock->fs_magic != FS_UFS2_MAGIC) {
warnx("bad magic number in backup superblock %d on %s",
cg + 1, device);
return (1);
}
- if (sblock->fs_sbsize > SBSIZE) {
+ if (sblock->fs_sbsize > SBLOCKSIZE) {
warnx("size of backup superblock %d on %s is preposterous",
cg + 1, device);
return (1);
@@ -188,15 +202,15 @@ fsirand(char *device)
sblock = (struct fs *)&sbuf;
/* XXX - should really cap buffer at 512kb or so */
- ibufsize = sizeof(struct dinode) * sblock->fs_ipg;
- if (oldibufsize < ibufsize) {
- if ((inodebuf = realloc(inodebuf, ibufsize)) == NULL)
- errx(1, "can't allocate memory for inode buffer");
- oldibufsize = ibufsize;
- }
+ if (sblock->fs_magic == FS_UFS1_MAGIC)
+ ibufsize = sizeof(struct ufs1_dinode) * sblock->fs_ipg;
+ else
+ ibufsize = sizeof(struct ufs2_dinode) * sblock->fs_ipg;
+ if ((inodebuf = malloc(ibufsize)) == NULL)
+ errx(1, "can't allocate memory for inode buffer");
if (printonly && (sblock->fs_id[0] || sblock->fs_id[1])) {
- if (sblock->fs_inodefmt >= FS_44INODEFMT && sblock->fs_id[0])
+ if (sblock->fs_id[0])
(void)printf("%s was randomized on %s", device,
ctime((const time_t *)&(sblock->fs_id[0])));
(void)printf("fsid: %x %x\n", sblock->fs_id[0],
@@ -204,19 +218,20 @@ fsirand(char *device)
}
/* Randomize fs_id unless old 4.2BSD filesystem */
- if ((sblock->fs_inodefmt >= FS_44INODEFMT) && !printonly) {
+ if (!printonly) {
/* Randomize fs_id and write out new sblock and backups */
sblock->fs_id[0] = (u_int32_t)time(NULL);
sblock->fs_id[1] = random();
- if (lseek(devfd, SBOFF, SEEK_SET) == -1) {
- warn("can't seek to superblock (%qd) on %s", SBOFF,
+ if (lseek(devfd, sblockloc, SEEK_SET) == -1) {
+ warn("can't seek to superblock (%qd) on %s", sblockloc,
device);
return (1);
}
- if ((n = write(devfd, (void *)sblock, SBSIZE)) != SBSIZE) {
- warn("can't read superblock on %s: %s", device,
- (n < SBSIZE) ? "short write" : strerror(errno));
+ if ((n = write(devfd, (void *)sblock, SBLOCKSIZE)) !=
+ SBLOCKSIZE) {
+ warn("can't write superblock on %s: %s", device,
+ (n < SBLOCKSIZE) ? "short write" : strerror(errno));
return (1);
}
}
@@ -224,15 +239,16 @@ fsirand(char *device)
/* For each cylinder group, randomize inodes and update backup sblock */
for (cg = 0, inumber = 0; cg < sblock->fs_ncg; cg++) {
/* Update superblock if appropriate */
- if ((sblock->fs_inodefmt >= FS_44INODEFMT) && !printonly) {
+ if (!printonly) {
dblk = fsbtodb(sblock, cgsblock(sblock, cg));
if (lseek(devfd, (off_t)dblk * bsize, SEEK_SET) < 0) {
warn("can't seek to %qd", (off_t)dblk * bsize);
return (1);
- } else if ((n = write(devfd, (void *)sblock, SBSIZE)) != SBSIZE) {
- warn("can't read backup superblock %d on %s: %s",
- cg + 1, device, (n < SBSIZE) ? "short write"
- : strerror(errno));
+ } else if ((n = write(devfd, (void *)sblock,
+ SBLOCKSIZE)) != SBLOCKSIZE) {
+ warn("can't write backup superblock %d on %s: %s",
+ cg + 1, device, (n < SBLOCKSIZE) ?
+ "short write" : strerror(errno));
return (1);
}
}
@@ -249,12 +265,19 @@ fsirand(char *device)
}
for (n = 0; n < sblock->fs_ipg; n++, inumber++) {
+ if (sblock->fs_magic == FS_UFS1_MAGIC)
+ dp1 = &((struct ufs1_dinode *)inodebuf)[n];
+ else
+ dp2 = &((struct ufs2_dinode *)inodebuf)[n];
if (inumber >= ROOTINO) {
if (printonly)
- (void)printf("ino %d gen %x\n", inumber,
- inodebuf[n].di_gen);
+ (void)printf("ino %d gen %qx\n",
+ inumber,
+ sblock->fs_magic == FS_UFS1_MAGIC ?
+ (quad_t)dp1->di_gen : dp2->di_gen);
else
- inodebuf[n].di_gen = random();
+ (sblock->fs_magic == FS_UFS1_MAGIC ?
+ dp1->di_gen : dp2->di_gen) = random();
}
}
diff --git a/sbin/growfs/growfs.c b/sbin/growfs/growfs.c
index d11dc98ca0ef..48cfad95f381 100644
--- a/sbin/growfs/growfs.c
+++ b/sbin/growfs/growfs.c
@@ -77,11 +77,17 @@ int _dbg_lvl_ = (DL_INFO); /* DL_TRC */
static union {
struct fs fs;
- char pad[SBSIZE];
+ char pad[SBLOCKSIZE];
} fsun1, fsun2;
#define sblock fsun1.fs /* the new superblock */
#define osblock fsun2.fs /* the old superblock */
+/*
+ * Possible superblock locations ordered from most to least likely.
+ */
+static int sblock_try[] = SBLOCKSEARCH;
+static ufs2_daddr_t sblockloc;
+
static union {
struct cg cg;
char pad[MAXBSIZE];
@@ -89,25 +95,20 @@ static union {
#define acg cgun1.cg /* a cylinder cgroup (new) */
#define aocg cgun2.cg /* an old cylinder group */
-static char ablk[MAXBSIZE]; /* a block */
-static char i1blk[MAXBSIZE]; /* some indirect blocks */
-static char i2blk[MAXBSIZE];
-static char i3blk[MAXBSIZE];
+static char ablk[MAXBSIZE]; /* a block */
- /* where to write back updated blocks */
-static daddr_t in_src, i1_src, i2_src, i3_src;
+static struct csum *fscs; /* cylinder summary */
- /* what object contains the reference */
-enum pointer_source {
- GFS_PS_INODE,
- GFS_PS_IND_BLK_LVL1,
- GFS_PS_IND_BLK_LVL2,
- GFS_PS_IND_BLK_LVL3
+union dinode {
+ struct ufs1_dinode dp1;
+ struct ufs2_dinode dp2;
};
-
-static struct csum *fscs; /* cylinder summary */
-
-static struct dinode zino[MAXBSIZE/sizeof(struct dinode)]; /* some inodes */
+#define DIP(dp, field) \
+ ((sblock.fs_magic == FS_UFS1_MAGIC) ? \
+ (dp)->dp1.field : (dp)->dp2.field)
+static ufs2_daddr_t inoblk; /* inode block address */
+static char inobuf[MAXBSIZE]; /* inode block */
+static int maxino; /* last valid inode */
/*
* An array of elements of type struct gfs_bpp describes all blocks to
@@ -115,8 +116,8 @@ static struct dinode zino[MAXBSIZE/sizeof(struct dinode)]; /* some inodes */
* summary for all cylinder groups located in the first cylinder group.
*/
struct gfs_bpp {
- daddr_t old; /* old block number */
- daddr_t new; /* new block number */
+ ufs2_daddr_t old; /* old block number */
+ ufs2_daddr_t new; /* new block number */
#define GFS_FL_FIRST 1
#define GFS_FL_LAST 2
unsigned int flags; /* special handling required */
@@ -125,9 +126,9 @@ struct gfs_bpp {
/* ******************************************************** PROTOTYPES ***** */
static void growfs(int, int, unsigned int);
-static void rdfs(daddr_t, size_t, void *, int);
-static void wtfs(daddr_t, size_t, void *, int, unsigned int);
-static daddr_t alloc(void);
+static void rdfs(ufs2_daddr_t, size_t, void *, int);
+static void wtfs(ufs2_daddr_t, size_t, void *, int, unsigned int);
+static ufs2_daddr_t alloc(void);
static int charsperline(void);
static void usage(void);
static int isblock(struct fs *, unsigned char *, int);
@@ -138,12 +139,14 @@ static void updjcg(int, time_t, int, int, unsigned int);
static void updcsloc(time_t, int, int, unsigned int);
static struct disklabel *get_disklabel(int);
static void return_disklabel(int, struct disklabel *, unsigned int);
-static struct dinode *ginode(ino_t, int, int);
-static void frag_adjust(daddr_t, int);
-static void cond_bl_upd(ufs_daddr_t *, struct gfs_bpp *,
- enum pointer_source, int, unsigned int);
+static union dinode *ginode(ino_t, int, int);
+static void frag_adjust(ufs2_daddr_t, int);
+static int cond_bl_upd(ufs2_daddr_t *, struct gfs_bpp *, int, int,
+ unsigned int);
static void updclst(int);
static void updrefs(int, ino_t, struct gfs_bpp *, int, int, unsigned int);
+static void indirchk(ufs_lbn_t, ufs_lbn_t, ufs2_daddr_t, ufs_lbn_t,
+ struct gfs_bpp *, int, int, unsigned int);
/* ************************************************************ growfs ***** */
/*
@@ -221,16 +224,16 @@ growfs(int fsi, int fso, unsigned int Nflag)
/*
* Dump out summary information about filesystem.
*/
- printf("growfs:\t%d sectors in %d %s of %d tracks, %d sectors\n",
- sblock.fs_size * NSPF(&sblock), sblock.fs_ncyl,
- "cylinders", sblock.fs_ntrak, sblock.fs_nsect);
-#define B2MBFACTOR (1 / (1024.0 * 1024.0))
- printf("\t%.1fMB in %d cyl groups (%d c/g, %.2fMB/g, %d i/g)\n",
+# define B2MBFACTOR (1 / (1024.0 * 1024.0))
+ printf("growfs: %.1fMB (%qd sectors) block size %d, fragment size %d\n",
(float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR,
- sblock.fs_ncg, sblock.fs_cpg,
- (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR,
- sblock.fs_ipg);
-#undef B2MBFACTOR
+ fsbtodb(&sblock, sblock.fs_size), sblock.fs_bsize, sblock.fs_fsize);
+ printf("\tusing %d cylinder groups of %.2fMB, %d blks, %d inodes.\n",
+ sblock.fs_ncg, (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR,
+ sblock.fs_fpg / sblock.fs_frag, sblock.fs_ipg);
+ if (sblock.fs_flags & FS_DOSOFTDEP)
+ printf("\twith soft updates\n");
+# undef B2MBFACTOR
/*
* Now build the cylinders group blocks and
@@ -295,8 +298,7 @@ growfs(int fsi, int fso, unsigned int Nflag)
* Now write the new superblock back to disk.
*/
sblock.fs_time = utime;
- wtfs((daddr_t)(SBOFF / DEV_BSIZE), (size_t)SBSIZE, (void *)&sblock,
- fso, Nflag);
+ wtfs(sblockloc, (size_t)SBLOCKSIZE, (void *)&sblock, fso, Nflag);
DBG_PRINT0("sblock written\n");
DBG_DUMP_FS(&sblock,
"new initial sblock");
@@ -338,7 +340,7 @@ growfs(int fsi, int fso, unsigned int Nflag)
*/
for (cylno = 0; cylno < sblock.fs_ncg; cylno++) {
wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)),
- (size_t)SBSIZE, (void *)&sblock, fso, Nflag);
+ (size_t)SBLOCKSIZE, (void *)&sblock, fso, Nflag);
}
DBG_PRINT0("sblock copies written\n");
DBG_DUMP_FS(&sblock,
@@ -359,96 +361,110 @@ static void
initcg(int cylno, time_t utime, int fso, unsigned int Nflag)
{
DBG_FUNC("initcg")
- daddr_t cbase, d, dlower, dupper, dmax, blkno;
- int i;
+ static caddr_t iobuf;
+ long i, j, d, dlower, dupper, blkno, start;
+ ufs2_daddr_t cbase, dmax;
+ struct ufs1_dinode *dp1;
+ struct ufs2_dinode *dp2;
struct csum *cs;
-#ifdef FSIRAND
- int j;
-#endif
-
- DBG_ENTER;
+ if (iobuf == NULL && (iobuf = malloc(sblock.fs_bsize)) == NULL) {
+ errx(37, "panic: cannot allocate I/O buffer");
+ }
/*
* Determine block bounds for cylinder group.
+ * Allow space for super block summary information in first
+ * cylinder group.
*/
cbase = cgbase(&sblock, cylno);
dmax = cbase + sblock.fs_fpg;
- if (dmax > sblock.fs_size) {
+ if (dmax > sblock.fs_size)
dmax = sblock.fs_size;
- }
dlower = cgsblock(&sblock, cylno) - cbase;
dupper = cgdmin(&sblock, cylno) - cbase;
- if (cylno == 0) { /* XXX fscs may be relocated */
+ if (cylno == 0) /* XXX fscs may be relocated */
dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
- }
- cs = fscs + cylno;
- memset(&acg, 0, (size_t)sblock.fs_cgsize);
+ cs = &fscs[cylno];
+ memset(&acg, 0, sblock.fs_cgsize);
acg.cg_time = utime;
acg.cg_magic = CG_MAGIC;
acg.cg_cgx = cylno;
- if (cylno == sblock.fs_ncg - 1) {
- acg.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg;
- } else {
- acg.cg_ncyl = sblock.fs_cpg;
- }
acg.cg_niblk = sblock.fs_ipg;
+ acg.cg_initediblk = sblock.fs_ipg;
acg.cg_ndblk = dmax - cbase;
- if (sblock.fs_contigsumsize > 0) {
+ if (sblock.fs_contigsumsize > 0)
acg.cg_nclusterblks = acg.cg_ndblk / sblock.fs_frag;
+ start = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield);
+ if (sblock.fs_magic == FS_UFS2_MAGIC) {
+ acg.cg_iusedoff = start;
+ } else {
+ acg.cg_old_ncyl = sblock.fs_old_cpg;
+ acg.cg_old_time = acg.cg_time;
+ acg.cg_time = 0;
+ acg.cg_old_niblk = acg.cg_niblk;
+ acg.cg_niblk = 0;
+ acg.cg_initediblk = 0;
+ acg.cg_old_btotoff = start;
+ acg.cg_old_boff = acg.cg_old_btotoff +
+ sblock.fs_old_cpg * sizeof(int32_t);
+ acg.cg_iusedoff = acg.cg_old_boff +
+ sblock.fs_old_cpg * sizeof(u_int16_t);
}
- acg.cg_btotoff = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield);
- acg.cg_boff = acg.cg_btotoff + sblock.fs_cpg * sizeof(int32_t);
- acg.cg_iusedoff = acg.cg_boff +
- sblock.fs_cpg * sblock.fs_nrpos * sizeof(u_int16_t);
acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, NBBY);
- if (sblock.fs_contigsumsize <= 0) {
- acg.cg_nextfreeoff = acg.cg_freeoff +
- howmany(sblock.fs_cpg* sblock.fs_spc/ NSPF(&sblock), NBBY);
- } else {
- acg.cg_clustersumoff = acg.cg_freeoff + howmany
- (sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), NBBY) -
- sizeof(u_int32_t);
+ acg.cg_nextfreeoff = acg.cg_freeoff + howmany(sblock.fs_fpg, NBBY);
+ if (sblock.fs_contigsumsize > 0) {
acg.cg_clustersumoff =
- roundup(acg.cg_clustersumoff, sizeof(u_int32_t));
+ roundup(acg.cg_nextfreeoff, sizeof(u_int32_t));
+ acg.cg_clustersumoff -= sizeof(u_int32_t);
acg.cg_clusteroff = acg.cg_clustersumoff +
(sblock.fs_contigsumsize + 1) * sizeof(u_int32_t);
- acg.cg_nextfreeoff = acg.cg_clusteroff + howmany
- (sblock.fs_cpg * sblock.fs_spc / NSPB(&sblock), NBBY);
+ acg.cg_nextfreeoff = acg.cg_clusteroff +
+ howmany(fragstoblks(&sblock, sblock.fs_fpg), NBBY);
}
- if (acg.cg_nextfreeoff-(int)(&acg.cg_firstfield) > sblock.fs_cgsize) {
+ if (acg.cg_nextfreeoff > sblock.fs_cgsize) {
/*
- * XXX This should never happen as we would have had that panic
- * already on filesystem creation
+ * This should never happen as we would have had that panic
+ * already on filesystem creation
*/
errx(37, "panic: cylinder group too big");
}
acg.cg_cs.cs_nifree += sblock.fs_ipg;
if (cylno == 0)
- for (i = 0; (size_t)i < ROOTINO; i++) {
+ for (i = 0; i < ROOTINO; i++) {
setbit(cg_inosused(&acg), i);
acg.cg_cs.cs_nifree--;
}
+ bzero(iobuf, sblock.fs_bsize);
for (i = 0; i < sblock.fs_ipg / INOPF(&sblock); i += sblock.fs_frag) {
+ dp1 = (struct ufs1_dinode *)iobuf;
+ dp2 = (struct ufs2_dinode *)iobuf;
#ifdef FSIRAND
- for (j = 0; j < sblock.fs_bsize / sizeof(struct dinode); j++) {
- zino[j].di_gen = random();
- }
+ for (j = 0; j < INOPB(&sblock); j++)
+ if (sblock.fs_magic == FS_UFS1_MAGIC) {
+ dp1->di_gen = random();
+ dp1++;
+ } else {
+ dp2->di_gen = random();
+ dp2++;
+ }
#endif
wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i),
- (size_t)sblock.fs_bsize, (void *)zino, fso, Nflag);
+ sblock.fs_bsize, iobuf, fso, Nflag);
}
- for (d = 0; d < dlower; d += sblock.fs_frag) {
- blkno = d / sblock.fs_frag;
- setblock(&sblock, cg_blksfree(&acg), blkno);
- if (sblock.fs_contigsumsize > 0) {
- setbit(cg_clustersfree(&acg), blkno);
+ if (cylno > 0) {
+ /*
+ * In cylno 0, beginning space is reserved
+ * for boot and super blocks.
+ */
+ for (d = 0; d < dlower; d += sblock.fs_frag) {
+ blkno = d / sblock.fs_frag;
+ setblock(&sblock, cg_blksfree(&acg), blkno);
+ if (sblock.fs_contigsumsize > 0)
+ setbit(cg_clustersfree(&acg), blkno);
+ acg.cg_cs.cs_nbfree++;
}
- acg.cg_cs.cs_nbfree++;
- cg_blktot(&acg)[cbtocylno(&sblock, d)]++;
- cg_blks(&sblock, &acg, cbtocylno(&sblock, d))
- [cbtorpos(&sblock, d)]++;
+ sblock.fs_dsize += dlower;
}
- sblock.fs_dsize += dlower;
sblock.fs_dsize += acg.cg_ndblk - dupper;
if ((i = dupper % sblock.fs_frag)) {
acg.cg_frsum[sblock.fs_frag - i]++;
@@ -457,53 +473,47 @@ initcg(int cylno, time_t utime, int fso, unsigned int Nflag)
acg.cg_cs.cs_nffree++;
}
}
- for (d = dupper; d + sblock.fs_frag <= dmax - cbase; ) {
+ for (d = dupper; d + sblock.fs_frag <= acg.cg_ndblk;
+ d += sblock.fs_frag) {
blkno = d / sblock.fs_frag;
setblock(&sblock, cg_blksfree(&acg), blkno);
- if (sblock.fs_contigsumsize > 0) {
+ if (sblock.fs_contigsumsize > 0)
setbit(cg_clustersfree(&acg), blkno);
- }
acg.cg_cs.cs_nbfree++;
- cg_blktot(&acg)[cbtocylno(&sblock, d)]++;
- cg_blks(&sblock, &acg, cbtocylno(&sblock, d))
- [cbtorpos(&sblock, d)]++;
- d += sblock.fs_frag;
- }
- if (d < dmax - cbase) {
- acg.cg_frsum[dmax - cbase - d]++;
- for (; d < dmax - cbase; d++) {
+ }
+ if (d < acg.cg_ndblk) {
+ acg.cg_frsum[acg.cg_ndblk - d]++;
+ for (; d < acg.cg_ndblk; d++) {
setbit(cg_blksfree(&acg), d);
acg.cg_cs.cs_nffree++;
}
}
if (sblock.fs_contigsumsize > 0) {
- int32_t *sump = cg_clustersum(&acg);
- u_char *mapp = cg_clustersfree(&acg);
- int map = *mapp++;
- int bit = 1;
- int run = 0;
+ int32_t *sump = cg_clustersum(&acg);
+ u_char *mapp = cg_clustersfree(&acg);
+ int map = *mapp++;
+ int bit = 1;
+ int run = 0;
for (i = 0; i < acg.cg_nclusterblks; i++) {
- if ((map & bit) != 0) {
+ if ((map & bit) != 0)
run++;
- } else if (run != 0) {
- if (run > sblock.fs_contigsumsize) {
+ else if (run != 0) {
+ if (run > sblock.fs_contigsumsize)
run = sblock.fs_contigsumsize;
- }
sump[run]++;
run = 0;
}
- if ((i & (NBBY - 1)) != (NBBY - 1)) {
+ if ((i & (NBBY - 1)) != NBBY - 1)
bit <<= 1;
- } else {
+ else {
map = *mapp++;
bit = 1;
}
}
if (run != 0) {
- if (run > sblock.fs_contigsumsize) {
+ if (run > sblock.fs_contigsumsize)
run = sblock.fs_contigsumsize;
- }
sump[run]++;
}
}
@@ -513,7 +523,7 @@ initcg(int cylno, time_t utime, int fso, unsigned int Nflag)
sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree;
*cs = acg.cg_cs;
wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)),
- (size_t)sblock.fs_bsize, (void *)&acg, fso, Nflag);
+ sblock.fs_bsize, (char *)&acg, fso, Nflag);
DBG_DUMP_CG(&sblock,
"new cg",
&acg);
@@ -530,7 +540,7 @@ initcg(int cylno, time_t utime, int fso, unsigned int Nflag)
* statistic, which seems to be otherwise an rather complex operation.
*/
static void
-frag_adjust(daddr_t frag, int sign)
+frag_adjust(ufs2_daddr_t frag, int sign)
{
DBG_FUNC("frag_adjust")
int fragsize;
@@ -590,72 +600,57 @@ frag_adjust(daddr_t frag, int sign)
* as there is no easy way for our general block reading engine to figure
* out if a write back operation is needed.
*/
-static void
-cond_bl_upd(ufs_daddr_t *block, struct gfs_bpp *field,
- enum pointer_source source, int fso, unsigned int Nflag)
+static int
+cond_bl_upd(ufs2_daddr_t *block, struct gfs_bpp *field, int fsi, int fso,
+ unsigned int Nflag)
{
DBG_FUNC("cond_bl_upd")
- struct gfs_bpp *f;
- char *src;
- daddr_t dst=0;
+ struct gfs_bpp *f;
+ ufs2_daddr_t src, dst;
+ int fragnum;
+ void *ibuf;
DBG_ENTER;
- f=field;
- while(f->old) { /* for all old blocks */
- if(*block/sblock.fs_frag == f->old) {
- /*
- * The fragment is part of the block, so update.
- */
- *block=(f->new*sblock.fs_frag+(*block%sblock.fs_frag));
- f->found++;
- DBG_PRINT3("scg (%d->%d)[%d] reference updated\n",
- f->old,
- f->new,
- *block%sblock.fs_frag);
-
- /* Write the block back to disk immediately */
- switch (source) {
- case GFS_PS_INODE:
- src=ablk;
- dst=in_src;
- break;
- case GFS_PS_IND_BLK_LVL1:
- src=i1blk;
- dst=i1_src;
- break;
- case GFS_PS_IND_BLK_LVL2:
- src=i2blk;
- dst=i2_src;
- break;
- case GFS_PS_IND_BLK_LVL3:
- src=i3blk;
- dst=i3_src;
- break;
- default: /* error */
- src=NULL;
- break;
- }
- if(src) {
- /*
- * XXX If src is not of type inode we have to
- * implement copy on write here in case
- * of active snapshots.
- */
- wtfs(dst, (size_t)sblock.fs_bsize, (void *)src,
- fso, Nflag);
- }
+ f = field;
+ for (f = field; f->old != 0; f++) {
+ src = *block;
+ if (fragstoblks(&sblock, src) != f->old)
+ continue;
+ /*
+ * The fragment is part of the block, so update.
+ */
+ dst = blkstofrags(&sblock, f->new);
+ fragnum = fragnum(&sblock, src);
+ *block = dst + fragnum;
+ f->found++;
+ DBG_PRINT3("scg (%d->%d)[%d] reference updated\n",
+ f->old,
+ f->new,
+ fragnum);
- /*
- * The same block can't be found again in this loop.
- */
- break;
- }
- f++;
+ /*
+ * Copy the block back immediately.
+ *
+ * XXX If src is is from an indirect block we have
+ * to implement copy on write here in case of
+ * active snapshots.
+ */
+ ibuf = malloc(sblock.fs_bsize);
+ if (!ibuf)
+ errx(1, "malloc failed");
+ src -= fragnum;
+ rdfs(fsbtodb(&sblock, src), (size_t)sblock.fs_bsize, ibuf, fsi);
+ wtfs(dst, (size_t)sblock.fs_bsize, ibuf, fso, Nflag);
+ free(ibuf);
+ /*
+ * The same block can't be found again in this loop.
+ */
+ return (1);
}
DBG_LEAVE;
- return;
+ return (0);
}
/* ************************************************************ updjcg ***** */
@@ -674,7 +669,7 @@ static void
updjcg(int cylno, time_t utime, int fsi, int fso, unsigned int Nflag)
{
DBG_FUNC("updjcg")
- daddr_t cbase, dmax, dupper;
+ ufs2_daddr_t cbase, dmax, dupper;
struct csum *cs;
int i,k;
int j=0;
@@ -703,7 +698,8 @@ updjcg(int cylno, time_t utime, int fsi, int fso, unsigned int Nflag)
*/
if(cgbase(&osblock, cylno+1) == osblock.fs_size) {
- acg.cg_ncyl=sblock.fs_cpg;
+ if (sblock.fs_magic == FS_UFS1_MAGIC)
+ acg.cg_old_ncyl=sblock.fs_old_cpg;
wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)),
(size_t)sblock.fs_cgsize, (void *)&acg, fso, Nflag);
@@ -742,15 +738,20 @@ updjcg(int cylno, time_t utime, int fsi, int fso, unsigned int Nflag)
/*
* This is still the last cylinder group.
*/
- acg.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg;
+ if (sblock.fs_magic == FS_UFS1_MAGIC)
+ acg.cg_old_ncyl =
+ sblock.fs_old_ncyl % sblock.fs_old_cpg;
} else {
- acg.cg_ncyl = sblock.fs_cpg;
+ acg.cg_old_ncyl = sblock.fs_old_cpg;
}
- DBG_PRINT4("jcg dbg: %d %u %d %u\n",
+ DBG_PRINT2("jcg dbg: %d %u",
cylno,
- sblock.fs_ncg,
- acg.cg_ncyl,
- sblock.fs_cpg);
+ sblock.fs_ncg);
+ if (sblock.fs_magic == FS_UFS1_MAGIC)
+ DBG_PRINT2("%d %u",
+ acg.cg_old_ncyl,
+ sblock.fs_old_cpg);
+ DBG_PRINT0("\n");
acg.cg_ndblk = dmax - cbase;
sblock.fs_dsize += acg.cg_ndblk-aocg.cg_ndblk;
if (sblock.fs_contigsumsize > 0) {
@@ -801,9 +802,6 @@ updjcg(int cylno, time_t utime, int fsi, int fso, unsigned int Nflag)
acg.cg_cs.cs_nffree-=sblock.fs_frag;
k=rounddown(osblock.fs_size-cbase,
sblock.fs_frag);
- cg_blktot(&acg)[cbtocylno(&sblock, k)]++;
- cg_blks(&sblock, &acg, cbtocylno(&sblock, k))
- [cbtorpos(&sblock, k)]++;
updclst((osblock.fs_size-cbase)/sblock.fs_frag);
} else {
/*
@@ -861,9 +859,6 @@ updjcg(int cylno, time_t utime, int fsi, int fso, unsigned int Nflag)
setblock(&sblock, cg_blksfree(&acg), j);
updclst(j);
acg.cg_cs.cs_nbfree++;
- cg_blktot(&acg)[cbtocylno(&sblock, i)]++;
- cg_blks(&sblock, &acg, cbtocylno(&sblock, i))
- [cbtorpos(&sblock, i)]++;
}
/*
@@ -930,7 +925,7 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag)
struct csum *cs;
int ocscg, ncscg;
int blocks;
- daddr_t cbase, dupper, odupper, d, f, g;
+ ufs2_daddr_t cbase, dupper, odupper, d, f, g;
int ind;
int cylno, inc;
struct gfs_bpp *bp;
@@ -1062,11 +1057,6 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag)
acg.cg_cs.cs_nbfree++;
sblock.fs_cstotal.cs_nffree-=sblock.fs_frag;
sblock.fs_cstotal.cs_nbfree++;
- cg_blktot(&acg)[cbtocylno(&sblock,
- d%sblock.fs_fpg)]++;
- cg_blks(&sblock, &acg, cbtocylno(&sblock,
- d%sblock.fs_fpg))[cbtorpos(&sblock,
- d%sblock.fs_fpg)]++;
if(sblock.fs_contigsumsize > 0) {
setbit(cg_clustersfree(&acg),
(d%sblock.fs_fpg)/sblock.fs_frag);
@@ -1098,10 +1088,6 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag)
(d%sblock.fs_fpg)/sblock.fs_frag);
acg.cg_cs.cs_nbfree++;
sblock.fs_cstotal.cs_nbfree++;
- cg_blktot(&acg)[cbtocylno(&sblock, d%sblock.fs_fpg)]++;
- cg_blks(&sblock, &acg, cbtocylno(&sblock,
- d%sblock.fs_fpg))[cbtorpos(&sblock,
- d%sblock.fs_fpg)]++;
if(sblock.fs_contigsumsize > 0) {
setbit(cg_clustersfree(&acg),
(d%sblock.fs_fpg)/sblock.fs_frag);
@@ -1174,10 +1160,6 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag)
(d%sblock.fs_fpg)/sblock.fs_frag);
acg.cg_cs.cs_nbfree--;
sblock.fs_cstotal.cs_nbfree--;
- cg_blktot(&acg)[cbtocylno(&sblock, d%sblock.fs_fpg)]--;
- cg_blks(&sblock, &acg, cbtocylno(&sblock,
- d%sblock.fs_fpg))[cbtorpos(&sblock,
- d%sblock.fs_fpg)]--;
if(sblock.fs_contigsumsize > 0) {
clrbit(cg_clustersfree(&acg),
(d%sblock.fs_fpg)/sblock.fs_frag);
@@ -1200,10 +1182,6 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag)
acg.cg_cs.cs_nffree+=sblock.fs_frag;
sblock.fs_cstotal.cs_nbfree--;
sblock.fs_cstotal.cs_nffree+=sblock.fs_frag;
- cg_blktot(&acg)[cbtocylno(&sblock, d%sblock.fs_fpg)]--;
- cg_blks(&sblock, &acg, cbtocylno(&sblock,
- d%sblock.fs_fpg))[cbtorpos(&sblock,
- d%sblock.fs_fpg)]--;
if(sblock.fs_contigsumsize > 0) {
clrbit(cg_clustersfree(&acg),
(d%sblock.fs_fpg)/sblock.fs_frag);
@@ -1323,9 +1301,6 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag)
clrblock(&sblock, cg_blksfree(&acg), d/sblock.fs_frag);
acg.cg_cs.cs_nbfree--;
sblock.fs_cstotal.cs_nbfree--;
- cg_blktot(&acg)[cbtocylno(&sblock, d)]--;
- cg_blks(&sblock, &acg, cbtocylno(&sblock, d))
- [cbtorpos(&sblock, d)]--;
if(sblock.fs_contigsumsize > 0) {
clrbit(cg_clustersfree(&acg), d/sblock.fs_frag);
for(lcs=0, l=(d/sblock.fs_frag)+1;
@@ -1360,9 +1335,6 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag)
sblock.fs_cstotal.cs_nbfree--;
acg.cg_cs.cs_nffree+=sblock.fs_frag;
sblock.fs_cstotal.cs_nffree+=sblock.fs_frag;
- cg_blktot(&acg)[cbtocylno(&sblock, d)]--;
- cg_blks(&sblock, &acg, cbtocylno(&sblock, d))
- [cbtorpos(&sblock, d)]--;
if(sblock.fs_contigsumsize > 0) {
clrbit(cg_clustersfree(&acg), d/sblock.fs_frag);
for(lcs=0, l=(d/sblock.fs_frag)+1;
@@ -1559,7 +1531,7 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag)
* Here we read some block(s) from disk.
*/
static void
-rdfs(daddr_t bno, size_t size, void *bf, int fsi)
+rdfs(ufs2_daddr_t bno, size_t size, void *bf, int fsi)
{
DBG_FUNC("rdfs")
ssize_t n;
@@ -1583,7 +1555,7 @@ rdfs(daddr_t bno, size_t size, void *bf, int fsi)
* Here we write some block(s) to disk.
*/
static void
-wtfs(daddr_t bno, size_t size, void *bf, int fso, unsigned int Nflag)
+wtfs(ufs2_daddr_t bno, size_t size, void *bf, int fso, unsigned int Nflag)
{
DBG_FUNC("wtfs")
ssize_t n;
@@ -1612,11 +1584,11 @@ wtfs(daddr_t bno, size_t size, void *bf, int fso, unsigned int Nflag)
* that acg contains the current cylinder group. As we may take a block from
* somewhere in the filesystem we have to handle cluster summary here.
*/
-static daddr_t
+static ufs2_daddr_t
alloc(void)
{
DBG_FUNC("alloc")
- daddr_t d, blkno;
+ ufs2_daddr_t d, blkno;
int lcs1, lcs2;
int l;
int csmin, csmax;
@@ -1735,8 +1707,6 @@ alloc(void)
*/
acg.cg_cs.cs_nbfree--;
sblock.fs_cstotal.cs_nbfree--;
- cg_blktot(&acg)[cbtocylno(&sblock, d)]--;
- cg_blks(&sblock, &acg, cbtocylno(&sblock, d))[cbtorpos(&sblock, d)]--;
DBG_LEAVE;
return (d);
@@ -1857,32 +1827,29 @@ setblock(struct fs *fs, unsigned char *cp, int h)
* not read the same block again and again if we iterate linearly over all
* inodes.
*/
-static struct dinode *
+static union dinode *
ginode(ino_t inumber, int fsi, int cg)
{
DBG_FUNC("ginode")
- ufs_daddr_t iblk;
- static ino_t startinum=0; /* first inode in cached block */
- struct dinode *pi;
+ static ino_t startinum = 0; /* first inode in cached block */
DBG_ENTER;
- pi=(struct dinode *)(void *)ablk;
- inumber+=(cg * sblock.fs_ipg);
- if (startinum == 0 || inumber < startinum ||
- inumber >= startinum + INOPB(&sblock)) {
- /*
- * The block needed is not cached, so we have to read it from
- * disk now.
- */
- iblk = ino_to_fsba(&sblock, inumber);
- in_src=fsbtodb(&sblock, iblk);
- rdfs(in_src, (size_t)sblock.fs_bsize, (void *)&ablk, fsi);
+ inumber += (cg * sblock.fs_ipg);
+ if (inumber < ROOTINO || inumber > maxino)
+ errx(8, "bad inode number %d to ginode", inumber);
+ if (startinum == 0 ||
+ inumber < startinum || inumber >= startinum + INOPB(&sblock)) {
+ inoblk = fsbtodb(&sblock, ino_to_fsba(&sblock, inumber));
+ rdfs(inoblk, (size_t)sblock.fs_bsize, inobuf, fsi);
startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock);
}
-
DBG_LEAVE;
- return (&(pi[inumber % INOPB(&sblock)]));
+ if (sblock.fs_magic == FS_UFS1_MAGIC)
+ return ((union dinode *)
+ &((struct ufs1_dinode *)inobuf)[inumber % INOPB(&sblock)]);
+ return ((union dinode *)
+ &((struct ufs2_dinode *)inobuf)[inumber % INOPB(&sblock)]);
}
/* ****************************************************** charsperline ***** */
@@ -1952,7 +1919,7 @@ main(int argc, char **argv)
struct stat st;
struct disklabel *lp;
struct partition *pp;
- int fsi,fso;
+ int i,fsi,fso;
char reply[5];
#ifdef FSMAXSNAP
int j;
@@ -2075,12 +2042,22 @@ main(int argc, char **argv)
/*
* Read the current superblock, and take a backup.
*/
- rdfs((daddr_t)(SBOFF/DEV_BSIZE), (size_t)SBSIZE, (void *)&(osblock),
- fsi);
- if (osblock.fs_magic != FS_MAGIC) {
+ for (i = 0; sblock_try[i] != -1; i++) {
+ sblockloc = sblock_try[i] / DEV_BSIZE;
+ rdfs(sblockloc, (size_t)SBLOCKSIZE, (void *)&(osblock), fsi);
+ if ((osblock.fs_magic == FS_UFS1_MAGIC ||
+ (osblock.fs_magic == FS_UFS2_MAGIC &&
+ osblock.fs_sblockloc ==
+ numfrags(&osblock, sblock_try[i]))) &&
+ osblock.fs_bsize <= MAXBSIZE &&
+ osblock.fs_bsize >= sizeof(struct fs))
+ break;
+ }
+ if (sblock_try[i] == -1) {
errx(1, "superblock not recognized");
}
memcpy((void *)&fsun1, (void *)&fsun2, sizeof(fsun2));
+ maxino = sblock.fs_ncg * sblock.fs_ipg;
DBG_OPEN("/tmp/growfs.debug"); /* already here we need a superblock */
DBG_DUMP_FS(&sblock,
@@ -2144,8 +2121,8 @@ main(int argc, char **argv)
* later on realize we have to abort our operation, on that block
* there should be no data, so we can't destroy something yet.
*/
- wtfs((daddr_t)pp->p_size-1, (size_t)DEV_BSIZE, (void *)&sblock, fso,
- Nflag);
+ wtfs((ufs2_daddr_t)pp->p_size-1, (size_t)DEV_BSIZE, (void *)&sblock,
+ fso, Nflag);
/*
* Now calculate new superblock values and check for reasonable
@@ -2158,40 +2135,30 @@ main(int argc, char **argv)
*/
/*
- * Update the number of cylinders in the filesystem.
- */
- sblock.fs_ncyl = sblock.fs_size * NSPF(&sblock) / sblock.fs_spc;
- if (sblock.fs_size * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_spc) {
- sblock.fs_ncyl++;
- }
-
- /*
- * Update the number of cylinder groups in the filesystem.
+ * Update the number of cylinders and cylinder groups in the filesystem.
*/
- sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg;
- if (sblock.fs_ncyl % sblock.fs_cpg) {
- sblock.fs_ncg++;
- }
-
- if ((sblock.fs_size - (sblock.fs_ncg-1) * sblock.fs_fpg) <
- sblock.fs_fpg && cgdmin(&sblock, (sblock.fs_ncg-1))-
- cgbase(&sblock, (sblock.fs_ncg-1)) > (sblock.fs_size -
- (sblock.fs_ncg-1) * sblock.fs_fpg )) {
+ if (sblock.fs_magic == FS_UFS1_MAGIC) {
+ sblock.fs_old_ncyl =
+ sblock.fs_size * sblock.fs_old_nspf / sblock.fs_old_spc;
+ if (sblock.fs_size * sblock.fs_old_nspf >
+ sblock.fs_old_ncyl * sblock.fs_old_spc)
+ sblock.fs_old_ncyl++;
+ }
+ sblock.fs_ncg = howmany(sblock.fs_size, sblock.fs_fpg);
+ maxino = sblock.fs_ncg * sblock.fs_ipg;
+
+ if (sblock.fs_size % sblock.fs_fpg != 0 &&
+ sblock.fs_size % sblock.fs_fpg < cgdmin(&sblock, sblock.fs_ncg)) {
/*
* The space in the new last cylinder group is too small,
* so revert back.
*/
sblock.fs_ncg--;
-#if 1 /* this is a bit more safe */
- sblock.fs_ncyl = sblock.fs_ncg * sblock.fs_cpg;
-#else
- sblock.fs_ncyl -= sblock.fs_ncyl % sblock.fs_cpg;
-#endif
- sblock.fs_ncyl -= sblock.fs_ncyl % sblock.fs_cpg;
- printf( "Warning: %d sector(s) cannot be allocated.\n",
- (sblock.fs_size-(sblock.fs_ncg)*sblock.fs_fpg) *
- NSPF(&sblock));
- sblock.fs_size = sblock.fs_ncyl * sblock.fs_spc / NSPF(&sblock);
+ if (sblock.fs_magic == FS_UFS1_MAGIC)
+ sblock.fs_old_ncyl = sblock.fs_ncg * sblock.fs_old_cpg;
+ printf("Warning: %d sector(s) cannot be allocated.\n",
+ fsbtodb(&sblock, sblock.fs_size % sblock.fs_fpg));
+ sblock.fs_size = sblock.fs_ncg * sblock.fs_fpg;
}
/*
@@ -2217,7 +2184,7 @@ main(int argc, char **argv)
*/
pp->p_fsize = sblock.fs_fsize;
pp->p_frag = sblock.fs_frag;
- pp->p_cpg = sblock.fs_cpg;
+ pp->p_cpg = sblock.fs_fpg;
return_disklabel(fso, lp, Nflag);
DBG_PRINT0("label rewritten\n");
@@ -2370,32 +2337,33 @@ updrefs(int cg, ino_t in, struct gfs_bpp *bp, int fsi, int fso, unsigned int
Nflag)
{
DBG_FUNC("updrefs")
- unsigned int ictr, ind2ctr, ind3ctr;
- ufs_daddr_t *iptr, *ind2ptr, *ind3ptr;
- struct dinode *ino;
- int remaining_blocks;
+ ufs_lbn_t len, lbn, numblks;
+ ufs2_daddr_t iptr, blksperindir;
+ union dinode *ino;
+ int i, mode, remaining_blocks, inodeupdated;
DBG_ENTER;
/*
- * XXX We should skip unused inodes even from beeing read from disk
+ * XXX We should skip unused inodes even from being read from disk
* here by using the bitmap.
*/
- ino=ginode(in, fsi, cg);
- if(!((ino->di_mode & IFMT)==IFDIR || (ino->di_mode & IFMT)==IFREG ||
- (ino->di_mode & IFMT)==IFLNK)) {
+ ino = ginode(in, fsi, cg);
+ mode = DIP(ino, di_mode) & IFMT;
+ if (mode != IFDIR && mode != IFREG && mode != IFLNK) {
DBG_LEAVE;
return; /* only check DIR, FILE, LINK */
}
- if(((ino->di_mode & IFMT)==IFLNK) && (ino->di_size<MAXSYMLINKLEN)) {
+ if (mode == IFLNK && DIP(ino, di_size) < sblock.fs_maxsymlinklen) {
DBG_LEAVE;
return; /* skip short symlinks */
}
- if(!ino->di_size) {
+ numblks = howmany(DIP(ino, di_size), sblock.fs_bsize);
+ if (numblks == 0) {
DBG_LEAVE;
return; /* skip empty file */
}
- if(!ino->di_blocks) {
+ if (DIP(ino, di_blocks) == 0) {
DBG_LEAVE;
return; /* skip empty swiss cheesy file or old fastlink */
}
@@ -2404,134 +2372,87 @@ updrefs(int cg, ino_t in, struct gfs_bpp *bp, int fsi, int fso, unsigned int
cg);
/*
- * Start checking all direct blocks.
+ * Check all the blocks.
*/
- remaining_blocks=howmany(ino->di_size, sblock.fs_bsize);
- for(ictr=0; ictr < MIN(NDADDR, (unsigned int)remaining_blocks);
- ictr++) {
- iptr=&(ino->di_db[ictr]);
- if(*iptr) {
- cond_bl_upd(iptr, bp, GFS_PS_INODE, fso, Nflag);
+ inodeupdated = 0;
+ len = numblks < NDADDR ? numblks : NDADDR;
+ for (i = 0; i < len; i++) {
+ iptr = DIP(ino, di_db[i]);
+ if (iptr == 0)
+ continue;
+ if (cond_bl_upd(&iptr, bp, fsi, fso, Nflag)) {
+ DIP(ino, di_db[i]) = iptr;
+ inodeupdated++;
}
}
DBG_PRINT0("~~scg direct blocks checked\n");
- remaining_blocks-=NDADDR;
- if(remaining_blocks<0) {
- DBG_LEAVE;
- return;
- }
- if(ino->di_ib[0]) {
- /*
- * Start checking first indirect block
- */
- cond_bl_upd(&(ino->di_ib[0]), bp, GFS_PS_INODE, fso, Nflag);
- i1_src=fsbtodb(&sblock, ino->di_ib[0]);
- rdfs(i1_src, (size_t)sblock.fs_bsize, (void *)&i1blk, fsi);
- for(ictr=0; ictr < MIN(howmany(sblock.fs_bsize,
- sizeof(ufs_daddr_t)), (unsigned int)remaining_blocks);
- ictr++) {
- iptr=&((ufs_daddr_t *)(void *)&i1blk)[ictr];
- if(*iptr) {
- cond_bl_upd(iptr, bp, GFS_PS_IND_BLK_LVL1,
- fso, Nflag);
- }
+ blksperindir = 1;
+ len = numblks - NDADDR;
+ lbn = NDADDR;
+ for (i = 0; len > 0 && i < NIADDR; i++) {
+ iptr = DIP(ino, di_ib[i]);
+ if (iptr == 0)
+ continue;
+ if (cond_bl_upd(&iptr, bp, fsi, fso, Nflag)) {
+ DIP(ino, di_ib[i]) = iptr;
+ inodeupdated++;
}
+ indirchk(blksperindir, lbn, iptr, numblks, bp, fsi, fso, Nflag);
+ blksperindir *= NINDIR(&sblock);
+ lbn += blksperindir;
+ len -= blksperindir;
+ DBG_PRINT1("scg indirect_%d blocks checked\n", i + 1);
}
- DBG_PRINT0("scg indirect_1 blocks checked\n");
+ if (inodeupdated)
+ wtfs(inoblk, sblock.fs_bsize, inobuf, fso, Nflag);
- remaining_blocks-= howmany(sblock.fs_bsize, sizeof(ufs_daddr_t));
- if(remaining_blocks<0) {
- DBG_LEAVE;
- return;
- }
- if(ino->di_ib[1]) {
- /*
- * Start checking second indirect block
- */
- cond_bl_upd(&(ino->di_ib[1]), bp, GFS_PS_INODE, fso, Nflag);
- i2_src=fsbtodb(&sblock, ino->di_ib[1]);
- rdfs(i2_src, (size_t)sblock.fs_bsize, (void *)&i2blk, fsi);
- for(ind2ctr=0; ind2ctr < howmany(sblock.fs_bsize,
- sizeof(ufs_daddr_t)); ind2ctr++) {
- ind2ptr=&((ufs_daddr_t *)(void *)&i2blk)[ind2ctr];
- if(!*ind2ptr) {
- continue;
- }
- cond_bl_upd(ind2ptr, bp, GFS_PS_IND_BLK_LVL2, fso,
- Nflag);
- i1_src=fsbtodb(&sblock, *ind2ptr);
- rdfs(i1_src, (size_t)sblock.fs_bsize, (void *)&i1blk,
- fsi);
- for(ictr=0; ictr<MIN(howmany((unsigned int)
- sblock.fs_bsize, sizeof(ufs_daddr_t)),
- (unsigned int)remaining_blocks); ictr++) {
- iptr=&((ufs_daddr_t *)(void *)&i1blk)[ictr];
- if(*iptr) {
- cond_bl_upd(iptr, bp,
- GFS_PS_IND_BLK_LVL1, fso, Nflag);
- }
- }
- }
- }
- DBG_PRINT0("scg indirect_2 blocks checked\n");
+ DBG_LEAVE;
+ return;
+}
-#define SQUARE(a) ((a)*(a))
- remaining_blocks-=SQUARE(howmany(sblock.fs_bsize, sizeof(ufs_daddr_t)));
-#undef SQUARE
- if(remaining_blocks<0) {
- DBG_LEAVE;
- return;
- }
-
- if(ino->di_ib[2]) {
- /*
- * Start checking third indirect block
- */
- cond_bl_upd(&(ino->di_ib[2]), bp, GFS_PS_INODE, fso, Nflag);
- i3_src=fsbtodb(&sblock, ino->di_ib[2]);
- rdfs(i3_src, (size_t)sblock.fs_bsize, (void *)&i3blk, fsi);
- for(ind3ctr=0; ind3ctr < howmany(sblock.fs_bsize,
- sizeof(ufs_daddr_t)); ind3ctr ++) {
- ind3ptr=&((ufs_daddr_t *)(void *)&i3blk)[ind3ctr];
- if(!*ind3ptr) {
- continue;
- }
- cond_bl_upd(ind3ptr, bp, GFS_PS_IND_BLK_LVL3, fso,
- Nflag);
- i2_src=fsbtodb(&sblock, *ind3ptr);
- rdfs(i2_src, (size_t)sblock.fs_bsize, (void *)&i2blk,
- fsi);
- for(ind2ctr=0; ind2ctr < howmany(sblock.fs_bsize,
- sizeof(ufs_daddr_t)); ind2ctr ++) {
- ind2ptr=&((ufs_daddr_t *)(void *)&i2blk)
- [ind2ctr];
- if(!*ind2ptr) {
- continue;
- }
- cond_bl_upd(ind2ptr, bp, GFS_PS_IND_BLK_LVL2,
- fso, Nflag);
- i1_src=fsbtodb(&sblock, *ind2ptr);
- rdfs(i1_src, (size_t)sblock.fs_bsize,
- (void *)&i1blk, fsi);
- for(ictr=0; ictr < MIN(howmany(sblock.fs_bsize,
- sizeof(ufs_daddr_t)),
- (unsigned int)remaining_blocks); ictr++) {
- iptr=&((ufs_daddr_t *)(void *)&i1blk)
- [ictr];
- if(*iptr) {
- cond_bl_upd(iptr, bp,
- GFS_PS_IND_BLK_LVL1, fso,
- Nflag);
- }
- }
- }
+/*
+ * Recursively check all the indirect blocks.
+ */
+static void
+indirchk(ufs_lbn_t blksperindir, ufs_lbn_t lbn, ufs2_daddr_t blkno,
+ ufs_lbn_t lastlbn, struct gfs_bpp *bp, int fsi, int fso, unsigned int Nflag)
+{
+ DBG_FUNC("indirchk")
+ void *ibuf;
+ off_t offset;
+ int i, last;
+ ufs2_daddr_t iptr;
+
+ DBG_ENTER;
+
+ /* read in the indirect block. */
+ ibuf = malloc(sblock.fs_bsize);
+ if (!ibuf)
+ errx(1, "malloc failed");
+ rdfs(fsbtodb(&sblock, blkno), (size_t)sblock.fs_bsize, ibuf, fsi);
+ last = howmany(lastlbn - lbn, blksperindir) < NINDIR(&sblock) ?
+ howmany(lastlbn - lbn, blksperindir) : NINDIR(&sblock);
+ for (i = 0; i < last; i++) {
+ if (sblock.fs_magic == FS_UFS1_MAGIC)
+ iptr = ((ufs1_daddr_t *)ibuf)[i];
+ else
+ iptr = ((ufs2_daddr_t *)ibuf)[i];
+ if (iptr == 0)
+ continue;
+ if (cond_bl_upd(&iptr, bp, fsi, fso, Nflag)) {
+ if (sblock.fs_magic == FS_UFS1_MAGIC)
+ ((ufs1_daddr_t *)ibuf)[i] = iptr;
+ else
+ ((ufs2_daddr_t *)ibuf)[i] = iptr;
}
+ if (blksperindir == 1)
+ continue;
+ indirchk(blksperindir / NINDIR(&sblock), lbn + blksperindir * i,
+ iptr, lastlbn, bp, fsi, fso, Nflag);
}
-
- DBG_PRINT0("scg indirect_3 blocks checked\n");
+ free(ibuf);
DBG_LEAVE;
return;
}
-
diff --git a/sbin/newfs/mkfs.c b/sbin/newfs/mkfs.c
index 16e7de732037..03c76f6608c4 100644
--- a/sbin/newfs/mkfs.c
+++ b/sbin/newfs/mkfs.c
@@ -1,4 +1,16 @@
/*
+ * Copyright (c) 2002 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by Marshall
+ * Kirk McKusick and Network Associates Laboratories, the Security
+ * Research Division of Network Associates, Inc. under DARPA/SPAWAR
+ * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
+ * research program
+ *
+ * Copyright (c) 1982, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
* Copyright (c) 1980, 1989, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -63,23 +75,12 @@ static const char rcsid[] =
/*
* make filesystem for cylinder-group style filesystems
*/
-
-/*
- * We limit the size of the inode map to be no more than a
- * third of the cylinder group space, since we must leave at
- * least an equal amount of space for the block map.
- *
- * N.B.: MAXIPG must be a multiple of INOPB(fs).
- */
-#define MAXIPG(fs) roundup((fs)->fs_bsize * NBBY / 3, INOPB(fs))
-
#define UMASK 0755
-#define MAXINOPB (MAXBSIZE / sizeof(struct dinode))
#define POWEROF2(num) (((num) & ((num) - 1)) == 0)
static union {
struct fs fs;
- char pad[SBSIZE];
+ char pad[SBLOCKSIZE];
} fsun;
#define sblock fsun.fs
static struct csum *fscs;
@@ -90,32 +91,36 @@ static union {
} cgun;
#define acg cgun.cg
-static struct dinode zino[MAXBSIZE / sizeof(struct dinode)];
+union dinode {
+ struct ufs1_dinode dp1;
+ struct ufs2_dinode dp2;
+};
+#define DIP(dp, field) \
+ ((sblock.fs_magic == FS_UFS1_MAGIC) ? \
+ (dp)->dp1.field : (dp)->dp2.field)
static int randinit;
-static daddr_t alloc(int size, int mode);
-static long calcipg(long lcpg, long bpcg, off_t *usedbp);
+static caddr_t iobuf;
+static long iobufsize;
+static ufs2_daddr_t alloc(int size, int mode);
static int charsperline(void);
static void clrblock(struct fs *, unsigned char *, int);
static void fsinit(time_t);
static int ilog2(int);
static void initcg(int, time_t);
static int isblock(struct fs *, unsigned char *, int);
-static void iput(struct dinode *, ino_t);
+static void iput(union dinode *, ino_t);
static int makedir(struct direct *, int);
-static void rdfs(daddr_t, int, char *);
+static void rdfs(ufs2_daddr_t, int, char *);
static void setblock(struct fs *, unsigned char *, int);
-static void wtfs(daddr_t, int, char *);
+static void wtfs(ufs2_daddr_t, int, char *);
static void wtfsflush(void);
void
mkfs(struct partition *pp, char *fsys)
{
- long i, mincpc, mincpg, inospercg;
- long cylno, j, lwarn = 0;
- long used, mincpgcnt, bpcg;
- off_t usedb;
- long mapcramped, inodecramped;
+ int fragsperinode, optimalfpg, origdensity, minfpg, lastminfpg;
+ long i, j, cylno, csfrags;
time_t utime;
quad_t sizepb;
int width;
@@ -129,26 +134,34 @@ mkfs(struct partition *pp, char *fsys)
randinit = 1;
srandomdev();
}
- sblock.fs_inodefmt = FS_44INODEFMT;
- sblock.fs_maxsymlinklen = MAXSYMLINKLEN;
+ /*
+ * allocate space for superblock, cylinder group map, and
+ * two sets of inode blocks.
+ */
+ if (bsize < SBLOCKSIZE)
+ iobufsize = SBLOCKSIZE + 3 * bsize;
+ else
+ iobufsize = 4 * bsize;
+ if ((iobuf = malloc(iobufsize)) == 0) {
+ printf("Cannot allocate I/O buffer\n");
+ exit(38);
+ }
+ bzero(iobuf, iobufsize);
+ sblock.fs_flags = 0;
if (Uflag)
sblock.fs_flags |= FS_DOSOFTDEP;
/*
* Validate the given filesystem size.
* Verify that its last block can actually be accessed.
+ * Convert to filesystem fragment sized units.
*/
- if (fssize <= 0)
- printf("preposterous size %d\n", fssize), exit(13);
+ if (fssize <= 0) {
+ printf("preposterous size %qd\n", fssize);
+ exit(13);
+ }
wtfs(fssize - (realsectorsize / DEV_BSIZE), realsectorsize,
(char *)&sblock);
/*
- * collect and verify the sector and track info
- */
- sblock.fs_nsect = secpercyl;
- sblock.fs_ntrak = 1;
- if (sblock.fs_nsect <= 0)
- printf("preposterous nsect %d\n", sblock.fs_nsect), exit(15);
- /*
* collect and verify the filesystem density info
*/
sblock.fs_avgfilesize = avgfilesize;
@@ -195,6 +208,22 @@ mkfs(struct partition *pp, char *fsys)
sblock.fs_fsize, MAXFRAG, sblock.fs_bsize / MAXFRAG);
sblock.fs_fsize = sblock.fs_bsize / MAXFRAG;
}
+ if (maxbsize < bsize || !POWEROF2(maxbsize)) {
+ sblock.fs_maxbsize = sblock.fs_bsize;
+ printf("Extent size set to %d\n", sblock.fs_maxbsize);
+ } else if (sblock.fs_maxbsize > FS_MAXCONTIG * sblock.fs_bsize) {
+ sblock.fs_maxbsize = FS_MAXCONTIG * sblock.fs_bsize;
+ printf("Extent size reduced to %d\n", sblock.fs_maxbsize);
+ } else {
+ sblock.fs_maxbsize = maxbsize;
+ }
+ sblock.fs_maxcontig = maxcontig;
+ if (sblock.fs_maxcontig < sblock.fs_maxbsize / sblock.fs_bsize) {
+ sblock.fs_maxcontig = sblock.fs_maxbsize / sblock.fs_bsize;
+ printf("Maxcontig raised to %d\n", sblock.fs_maxbsize);
+ }
+ if (sblock.fs_maxcontig > 1)
+ sblock.fs_contigsumsize = MIN(sblock.fs_maxcontig,FS_MAXCONTIG);
sblock.fs_bmask = ~(sblock.fs_bsize - 1);
sblock.fs_fmask = ~(sblock.fs_fsize - 1);
sblock.fs_qbmask = ~sblock.fs_bmask;
@@ -208,257 +237,138 @@ mkfs(struct partition *pp, char *fsys)
sblock.fs_bsize / MAXFRAG);
exit(21);
}
- sblock.fs_nrpos = 1;
- sblock.fs_nindir = sblock.fs_bsize / sizeof(daddr_t);
- sblock.fs_inopb = sblock.fs_bsize / sizeof(struct dinode);
- sblock.fs_nspf = sblock.fs_fsize / sectorsize;
- sblock.fs_fsbtodb = ilog2(NSPF(&sblock));
+ sblock.fs_fsbtodb = ilog2(sblock.fs_fsize / sectorsize);
+ sblock.fs_size = fssize = dbtofsb(&sblock, fssize);
+ if (Oflag == 1) {
+ sblock.fs_magic = FS_UFS1_MAGIC;
+ sblock.fs_sblockloc = numfrags(&sblock, SBLOCK_UFS1);
+ sblock.fs_nindir = sblock.fs_bsize / sizeof(ufs1_daddr_t);
+ sblock.fs_inopb = sblock.fs_bsize / sizeof(struct ufs1_dinode);
+ sblock.fs_maxsymlinklen = ((NDADDR + NIADDR) *
+ sizeof(ufs1_daddr_t));
+ sblock.fs_old_inodefmt = FS_44INODEFMT;
+ sblock.fs_old_cgoffset = 0;
+ sblock.fs_old_cgmask = 0xffffffff;
+ sblock.fs_old_size = sblock.fs_size;
+ sblock.fs_old_rotdelay = 0;
+ sblock.fs_old_rps = 60;
+ sblock.fs_old_nspf = sblock.fs_fsize / sectorsize;
+ sblock.fs_old_cpg = 1;
+ sblock.fs_old_interleave = 1;
+ sblock.fs_old_trackskew = 0;
+ sblock.fs_old_cpc = 0;
+ sblock.fs_old_postblformat = 1;
+ sblock.fs_old_nrpos = 1;
+ } else {
+ sblock.fs_magic = FS_UFS2_MAGIC;
+ sblock.fs_sblockloc = numfrags(&sblock, SBLOCK_UFS2);
+ sblock.fs_nindir = sblock.fs_bsize / sizeof(ufs2_daddr_t);
+ sblock.fs_inopb = sblock.fs_bsize / sizeof(struct ufs2_dinode);
+ sblock.fs_maxsymlinklen = ((NDADDR + NIADDR) *
+ sizeof(ufs2_daddr_t));
+ }
sblock.fs_sblkno =
- roundup(howmany(BBSIZE + SBSIZE, sblock.fs_fsize), sblock.fs_frag);
- sblock.fs_cblkno = (daddr_t)(sblock.fs_sblkno +
- roundup(howmany(SBSIZE, sblock.fs_fsize), sblock.fs_frag));
+ roundup(howmany(lfragtosize(&sblock, sblock.fs_sblockloc) +
+ SBLOCKSIZE, sblock.fs_fsize), sblock.fs_frag);
+ sblock.fs_cblkno = sblock.fs_sblkno +
+ roundup(howmany(SBLOCKSIZE, sblock.fs_fsize), sblock.fs_frag);
sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag;
- sblock.fs_cgoffset =
- roundup(howmany(sblock.fs_nsect, NSPF(&sblock)), sblock.fs_frag);
- sblock.fs_cgmask = 0xffffffff;
sblock.fs_maxfilesize = sblock.fs_bsize * NDADDR - 1;
for (sizepb = sblock.fs_bsize, i = 0; i < NIADDR; i++) {
sizepb *= NINDIR(&sblock);
sblock.fs_maxfilesize += sizepb;
}
/*
- * Validate specified/determined secpercyl
- * and calculate minimum cylinders per group.
- */
- sblock.fs_spc = secpercyl;
- for (sblock.fs_cpc = NSPB(&sblock), i = sblock.fs_spc;
- sblock.fs_cpc > 1 && (i & 1) == 0;
- sblock.fs_cpc >>= 1, i >>= 1)
- /* void */;
- mincpc = sblock.fs_cpc;
- bpcg = sblock.fs_spc * sectorsize;
- inospercg = roundup(bpcg / sizeof(struct dinode), INOPB(&sblock));
- if (inospercg > MAXIPG(&sblock))
- inospercg = MAXIPG(&sblock);
- used = (sblock.fs_iblkno + inospercg / INOPF(&sblock)) * NSPF(&sblock);
- mincpgcnt = howmany(sblock.fs_cgoffset * (~sblock.fs_cgmask) + used,
- sblock.fs_spc);
- mincpg = roundup(mincpgcnt, mincpc);
- /*
- * Ensure that cylinder group with mincpg has enough space
- * for block maps.
+ * Calculate the number of blocks to put into each cylinder group.
+ *
+ * This algorithm selects the number of blocks per cylinder
+ * group. The first goal is to have at least enough data blocks
+ * in each cylinder group to meet the density requirement. Once
+ * this goal is achieved we try to expand to have at least
+ * MINCYLGRPS cylinder groups. Once this goal is achieved, we
+ * pack as many blocks into each cylinder group map as will fit.
+ *
+ * We start by calculating the smallest number of blocks that we
+ * can put into each cylinder group. If this is too big, we reduce
+ * the density until it fits.
*/
- sblock.fs_cpg = mincpg;
- sblock.fs_ipg = inospercg;
- if (maxcontig > 1)
- sblock.fs_contigsumsize = MIN(maxcontig, FS_MAXCONTIG);
- mapcramped = 0;
- while (CGSIZE(&sblock) > sblock.fs_bsize) {
- mapcramped = 1;
- if (sblock.fs_bsize < MAXBSIZE) {
- sblock.fs_bsize <<= 1;
- if ((i & 1) == 0)
- i >>= 1;
- else {
- sblock.fs_cpc <<= 1;
- mincpc <<= 1;
- mincpg = roundup(mincpgcnt, mincpc);
- sblock.fs_cpg = mincpg;
- }
- sblock.fs_frag <<= 1;
- sblock.fs_fragshift += 1;
- if (sblock.fs_frag <= MAXFRAG)
- continue;
- }
- if (sblock.fs_fsize == sblock.fs_bsize) {
- printf("There is no block size that");
- printf(" can support this disk\n");
- exit(22);
- }
- sblock.fs_frag >>= 1;
- sblock.fs_fragshift -= 1;
- sblock.fs_fsize <<= 1;
- sblock.fs_nspf <<= 1;
+ origdensity = density;
+ for (;;) {
+ fragsperinode = numfrags(&sblock, density);
+ minfpg = fragsperinode * INOPB(&sblock);
+ if (minfpg > sblock.fs_size)
+ minfpg = sblock.fs_size;
+ sblock.fs_ipg = INOPB(&sblock);
+ sblock.fs_fpg = roundup(sblock.fs_iblkno +
+ sblock.fs_ipg / INOPF(&sblock), sblock.fs_frag);
+ if (sblock.fs_fpg < minfpg)
+ sblock.fs_fpg = minfpg;
+ sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode),
+ INOPB(&sblock));
+ sblock.fs_fpg = roundup(sblock.fs_iblkno +
+ sblock.fs_ipg / INOPF(&sblock), sblock.fs_frag);
+ if (sblock.fs_fpg < minfpg)
+ sblock.fs_fpg = minfpg;
+ sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode),
+ INOPB(&sblock));
+ if (CGSIZE(&sblock) < (unsigned long)sblock.fs_bsize)
+ break;
+ density -= sblock.fs_fsize;
}
+ if (density != origdensity)
+ printf("density reduced from %d to %d\n", origdensity, density);
/*
- * Ensure that cylinder group with mincpg has enough space for inodes.
+ * Start packing more blocks into the cylinder group until
+ * it cannot grow any larger, the number of cylinder groups
+ * drops below MINCYLGRPS, or we reach the size requested.
*/
- inodecramped = 0;
- inospercg = calcipg(mincpg, bpcg, &usedb);
- sblock.fs_ipg = inospercg;
- while (inospercg > MAXIPG(&sblock)) {
- inodecramped = 1;
- if (mincpc == 1 || sblock.fs_frag == 1 ||
- sblock.fs_bsize == MINBSIZE)
+ for ( ; sblock.fs_fpg < maxblkspercg; sblock.fs_fpg += sblock.fs_frag) {
+ sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode),
+ INOPB(&sblock));
+ if (sblock.fs_size / sblock.fs_fpg < MINCYLGRPS)
break;
- printf("With a block size of %d %s %d\n", sblock.fs_bsize,
- "minimum bytes per inode is",
- (int)((mincpg * (off_t)bpcg - usedb) /
- MAXIPG(&sblock) + 1));
- sblock.fs_bsize >>= 1;
- sblock.fs_frag >>= 1;
- sblock.fs_fragshift -= 1;
- mincpc >>= 1;
- sblock.fs_cpg = roundup(mincpgcnt, mincpc);
- if (CGSIZE(&sblock) > sblock.fs_bsize) {
- sblock.fs_bsize <<= 1;
+ if (CGSIZE(&sblock) < (unsigned long)sblock.fs_bsize)
+ continue;
+ if (CGSIZE(&sblock) == (unsigned long)sblock.fs_bsize)
break;
- }
- mincpg = sblock.fs_cpg;
- inospercg = calcipg(mincpg, bpcg, &usedb);
- sblock.fs_ipg = inospercg;
- }
- if (inodecramped) {
- if (inospercg > MAXIPG(&sblock)) {
- printf("Minimum bytes per inode is %d\n",
- (int)((mincpg * (off_t)bpcg - usedb) /
- MAXIPG(&sblock) + 1));
- } else if (!mapcramped) {
- printf("With %d bytes per inode, ", density);
- printf("minimum cylinders per group is %ld\n", mincpg);
- }
- }
- if (mapcramped) {
- printf("With %d sectors per cylinder, ", sblock.fs_spc);
- printf("minimum cylinders per group is %ld\n", mincpg);
- }
- if (inodecramped || mapcramped) {
- if (sblock.fs_bsize != bsize)
- printf("%s to be changed from %d to %d\n",
- "This requires the block size",
- bsize, sblock.fs_bsize);
- if (sblock.fs_fsize != fsize)
- printf("\t%s to be changed from %d to %d\n",
- "and the fragment size", fsize, sblock.fs_fsize);
- exit(23);
- }
- /*
- * Calculate the number of cylinders per group
- */
- sblock.fs_cpg = cpg;
- if (sblock.fs_cpg % mincpc != 0) {
- printf("%s groups must have a multiple of %ld cylinders\n",
- cpgflg ? "Cylinder" : "Warning: cylinder", mincpc);
- sblock.fs_cpg = roundup(sblock.fs_cpg, mincpc);
- if (!cpgflg)
- cpg = sblock.fs_cpg;
- }
- /*
- * Must ensure there is enough space for inodes.
- */
- sblock.fs_ipg = calcipg(sblock.fs_cpg, bpcg, &usedb);
- while (sblock.fs_ipg > MAXIPG(&sblock)) {
- inodecramped = 1;
- sblock.fs_cpg -= mincpc;
- sblock.fs_ipg = calcipg(sblock.fs_cpg, bpcg, &usedb);
+ sblock.fs_fpg -= sblock.fs_frag;
+ sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode),
+ INOPB(&sblock));
+ break;
}
/*
- * Must ensure there is enough space to hold block map.
+ * Check to be sure that the last cylinder group has enough blocks
+ * to be viable. If it is too small, reduce the number of blocks
+ * per cylinder group which will have the effect of moving more
+ * blocks into the last cylinder group.
*/
- while (CGSIZE(&sblock) > sblock.fs_bsize) {
- mapcramped = 1;
- sblock.fs_cpg -= mincpc;
- sblock.fs_ipg = calcipg(sblock.fs_cpg, bpcg, &usedb);
- }
- sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock);
- if ((sblock.fs_cpg * sblock.fs_spc) % NSPB(&sblock) != 0) {
- printf("panic (fs_cpg * fs_spc) %% NSPF != 0");
- exit(24);
- }
- if (sblock.fs_cpg < mincpg) {
- printf("cylinder groups must have at least %ld cylinders\n",
- mincpg);
- exit(25);
- } else if (cpgflg && sblock.fs_cpg != cpg) {
- if (!mapcramped && !inodecramped)
- exit(26);
- if (mapcramped && inodecramped)
- printf("Block size and bytes per inode restrict");
- else if (mapcramped)
- printf("Block size restricts");
- else
- printf("Bytes per inode restrict");
- printf(" cylinders per group to %d.\n", sblock.fs_cpg);
- if (cpgflg)
- exit(27);
+ optimalfpg = sblock.fs_fpg;
+ for (;;) {
+ sblock.fs_ncg = howmany(sblock.fs_size, sblock.fs_fpg);
+ lastminfpg = roundup(sblock.fs_iblkno +
+ sblock.fs_ipg / INOPF(&sblock), sblock.fs_frag);
+ if (sblock.fs_size < lastminfpg) {
+ printf("Filesystem size %qd < minimum size of %d\n",
+ sblock.fs_size, lastminfpg);
+ exit(28);
+ }
+ if (sblock.fs_size % sblock.fs_fpg >= lastminfpg ||
+ sblock.fs_size % sblock.fs_fpg == 0)
+ break;
+ sblock.fs_fpg -= sblock.fs_frag;
+ sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode),
+ INOPB(&sblock));
}
+ if (optimalfpg != sblock.fs_fpg)
+ printf("Reduced frags per cylinder group from %d to %d %s\n",
+ optimalfpg, sblock.fs_fpg, "to enlarge last cyl group");
sblock.fs_cgsize = fragroundup(&sblock, CGSIZE(&sblock));
- /*
- * Now have size for filesystem and nsect and ntrak.
- * Determine number of cylinders and blocks in the filesystem.
- */
- sblock.fs_size = fssize = dbtofsb(&sblock, fssize);
- sblock.fs_ncyl = fssize * NSPF(&sblock) / sblock.fs_spc;
- if (fssize * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_spc) {
- sblock.fs_ncyl++;
- lwarn = 1;
- }
- if (sblock.fs_ncyl < 1) {
- printf("filesystems must have at least one cylinder\n");
- exit(28);
- }
- /*
- * Determine feasability/values of rotational layout tables.
- *
- * The size of the rotational layout tables is limited by the
- * size of the superblock, SBSIZE. The amount of space available
- * for tables is calculated as (SBSIZE - sizeof (struct fs)).
- * The size of these tables is inversely proportional to the block
- * size of the filesystem. The size increases if sectors per track
- * are not powers of two, because more cylinders must be described
- * by the tables before the rotational pattern repeats (fs_cpc).
- */
- sblock.fs_interleave = 1;
- sblock.fs_trackskew = 0;
- sblock.fs_npsect = secpercyl;
- sblock.fs_postblformat = FS_DYNAMICPOSTBLFMT;
- sblock.fs_sbsize = fragroundup(&sblock, sizeof(struct fs));
- if (sblock.fs_sbsize > SBSIZE)
- sblock.fs_sbsize = SBSIZE;
- sblock.fs_cpc = 0;
- /*
- * Compute/validate number of cylinder groups.
- */
- sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg;
- if (sblock.fs_ncyl % sblock.fs_cpg)
- sblock.fs_ncg++;
sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock);
- i = MIN(~sblock.fs_cgmask, sblock.fs_ncg - 1);
- if (cgdmin(&sblock, i) - cgbase(&sblock, i) >= sblock.fs_fpg) {
- printf("inode blocks/cyl group (%ld) >= data blocks (%ld)\n",
- cgdmin(&sblock, i) - cgbase(&sblock, i) / sblock.fs_frag,
- (long)(sblock.fs_fpg / sblock.fs_frag));
- printf("number of cylinders per cylinder group (%d) %s.\n",
- sblock.fs_cpg, "must be increased");
- exit(29);
- }
- j = sblock.fs_ncg - 1;
- if ((i = fssize - j * sblock.fs_fpg) < sblock.fs_fpg &&
- cgdmin(&sblock, j) - cgbase(&sblock, j) > i) {
- if (j == 0) {
- printf("Filesystem must have at least %d sectors\n",
- NSPF(&sblock) *
- (cgdmin(&sblock, 0) + 3 * sblock.fs_frag));
- exit(30);
- }
- printf(
-"Warning: inode blocks/cyl group (%ld) >= data blocks (%ld) in last\n",
- (cgdmin(&sblock, j) - cgbase(&sblock, j)) / sblock.fs_frag,
- i / sblock.fs_frag);
- printf(
-" cylinder group. This implies %ld sector(s) cannot be allocated.\n",
- i * NSPF(&sblock));
- sblock.fs_ncg--;
- sblock.fs_ncyl -= sblock.fs_ncyl % sblock.fs_cpg;
- sblock.fs_size = fssize = sblock.fs_ncyl * sblock.fs_spc /
- NSPF(&sblock);
- lwarn = 0;
- }
- if (lwarn) {
- printf("Warning: %d sector(s) in last cylinder unallocated\n",
- sblock.fs_spc -
- (fssize * NSPF(&sblock) - (sblock.fs_ncyl - 1) *
- sblock.fs_spc));
+ if (Oflag == 1) {
+ sblock.fs_old_spc = sblock.fs_fpg * sblock.fs_old_nspf;
+ sblock.fs_old_nsect = sblock.fs_old_spc;
+ sblock.fs_old_npsect = sblock.fs_old_spc;
+ sblock.fs_old_ncyl = sblock.fs_ncg;
}
/*
* fill in remaining fields of the super block
@@ -466,49 +376,59 @@ mkfs(struct partition *pp, char *fsys)
sblock.fs_csaddr = cgdmin(&sblock, 0);
sblock.fs_cssize =
fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum));
- /*
- * The superblock fields 'fs_csmask' and 'fs_csshift' are no
- * longer used. However, we still initialise them so that the
- * filesystem remains compatible with old kernels.
- */
- i = sblock.fs_bsize / sizeof(struct csum);
- sblock.fs_csmask = ~(i - 1);
- sblock.fs_csshift = ilog2(i);
fscs = (struct csum *)calloc(1, sblock.fs_cssize);
if (fscs == NULL)
errx(31, "calloc failed");
- sblock.fs_magic = FS_MAGIC;
- sblock.fs_rotdelay = 0;
+ sblock.fs_sbsize = fragroundup(&sblock, sizeof(struct fs));
sblock.fs_minfree = minfree;
- sblock.fs_maxcontig = maxcontig;
sblock.fs_maxbpg = maxbpg;
- sblock.fs_rps = 60;
sblock.fs_optim = opt;
sblock.fs_cgrotor = 0;
- sblock.fs_cstotal.cs_ndir = 0;
- sblock.fs_cstotal.cs_nbfree = 0;
- sblock.fs_cstotal.cs_nifree = 0;
- sblock.fs_cstotal.cs_nffree = 0;
+ sblock.fs_pendingblocks = 0;
+ sblock.fs_pendinginodes = 0;
sblock.fs_fmod = 0;
sblock.fs_ronly = 0;
+ sblock.fs_state = 0;
sblock.fs_clean = 1;
sblock.fs_id[0] = (long)utime;
sblock.fs_id[1] = random();
+ sblock.fs_fsmnt[0] = '\0';
+ csfrags = howmany(sblock.fs_cssize, sblock.fs_fsize);
+ sblock.fs_dsize = sblock.fs_size - sblock.fs_sblkno -
+ sblock.fs_ncg * (sblock.fs_dblkno - sblock.fs_sblkno);
+ sblock.fs_cstotal.cs_nbfree =
+ fragstoblks(&sblock, sblock.fs_dsize) -
+ howmany(csfrags, sblock.fs_frag);
+ sblock.fs_cstotal.cs_nffree =
+ fragnum(&sblock, sblock.fs_size) +
+ (csfrags > 0 ? sblock.fs_frag - csfrags : 0);
+ sblock.fs_cstotal.cs_nifree = sblock.fs_ncg * sblock.fs_ipg - ROOTINO;
+ sblock.fs_cstotal.cs_ndir = 0;
+ sblock.fs_dsize -= csfrags;
+ sblock.fs_time = utime;
+ if (Oflag == 1) {
+ sblock.fs_old_time = utime;
+ sblock.fs_old_dsize = sblock.fs_dsize;
+ sblock.fs_old_csaddr = sblock.fs_csaddr;
+ sblock.fs_old_cstotal.cs_ndir = sblock.fs_cstotal.cs_ndir;
+ sblock.fs_old_cstotal.cs_nbfree = sblock.fs_cstotal.cs_nbfree;
+ sblock.fs_old_cstotal.cs_nifree = sblock.fs_cstotal.cs_nifree;
+ sblock.fs_old_cstotal.cs_nffree = sblock.fs_cstotal.cs_nffree;
+ }
/*
* Dump out summary information about filesystem.
*/
- printf("%s:\t%d sectors in %d %s of %d tracks, %d sectors\n",
- fsys, sblock.fs_size * NSPF(&sblock), sblock.fs_ncyl,
- "cylinders", sblock.fs_ntrak, sblock.fs_nsect);
-#define B2MBFACTOR (1 / (1024.0 * 1024.0))
- printf("\t%.1fMB in %d cyl groups (%d c/g, %.2fMB/g, %d i/g)%s\n",
- (float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR,
- sblock.fs_ncg, sblock.fs_cpg,
- (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR,
- sblock.fs_ipg,
- sblock.fs_flags & FS_DOSOFTDEP ? " SOFTUPDATES" : "");
-#undef B2MBFACTOR
+# define B2MBFACTOR (1 / (1024.0 * 1024.0))
+ printf("%s: %.1fMB (%qd sectors) block size %d, fragment size %d\n",
+ fsys, (float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR,
+ fsbtodb(&sblock, sblock.fs_size), sblock.fs_bsize, sblock.fs_fsize);
+ printf("\tusing %d cylinder groups of %.2fMB, %d blks, %d inodes.\n",
+ sblock.fs_ncg, (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR,
+ sblock.fs_fpg / sblock.fs_frag, sblock.fs_ipg);
+ if (sblock.fs_flags & FS_DOSOFTDEP)
+ printf("\twith soft updates\n");
+# undef B2MBFACTOR
/*
* Now build the cylinders group blocks and
* then print out indices of cylinder groups.
@@ -516,9 +436,14 @@ mkfs(struct partition *pp, char *fsys)
printf("super-block backups (for fsck -b #) at:\n");
i = 0;
width = charsperline();
+ /*
+ * Make a copy of the superblock into the buffer that we will be
+ * writing out in each cylinder group.
+ */
+ bcopy((char *)&sblock, iobuf, SBLOCKSIZE);
for (cylno = 0; cylno < sblock.fs_ncg; cylno++) {
initcg(cylno, utime);
- j = snprintf(tmpbuf, sizeof(tmpbuf), " %ld%s",
+ j = snprintf(tmpbuf, sizeof(tmpbuf), " %qd%s",
fsbtodb(&sblock, cgsblock(&sblock, cylno)),
cylno < (sblock.fs_ncg-1) ? "," : "");
if (j < 0)
@@ -535,23 +460,30 @@ mkfs(struct partition *pp, char *fsys)
if (Nflag)
exit(0);
/*
+ * Zero out the boot area to avoid old superblocks from being
+ * found by mistake. Skip over the disklabel area.
+ */
+ bzero(iobuf, sblock.fs_bsize);
+ for (i = 1; i < sblock.fs_sblkno; i += sblock.fs_frag)
+ wtfs(fsbtodb(&sblock, i), sblock.fs_bsize, iobuf);
+ /*
* Now construct the initial filesystem,
* then write out the super-block.
*/
fsinit(utime);
- sblock.fs_time = utime;
- wtfs((int)SBOFF / sectorsize, SBSIZE, (char *)&sblock);
+ if (Oflag == 1) {
+ sblock.fs_old_cstotal.cs_ndir = sblock.fs_cstotal.cs_ndir;
+ sblock.fs_old_cstotal.cs_nbfree = sblock.fs_cstotal.cs_nbfree;
+ sblock.fs_old_cstotal.cs_nifree = sblock.fs_cstotal.cs_nifree;
+ sblock.fs_old_cstotal.cs_nffree = sblock.fs_cstotal.cs_nffree;
+ }
+ wtfs(lfragtosize(&sblock, sblock.fs_sblockloc) / sectorsize,
+ SBLOCKSIZE, (char *)&sblock);
for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize)
wtfs(fsbtodb(&sblock, sblock.fs_csaddr + numfrags(&sblock, i)),
sblock.fs_cssize - i < sblock.fs_bsize ?
sblock.fs_cssize - i : sblock.fs_bsize,
((char *)fscs) + i);
- /*
- * Write out the duplicate super blocks
- */
- for (cylno = 0; cylno < sblock.fs_ncg; cylno++)
- wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)),
- SBSIZE, (char *)&sblock);
wtfsflush();
/*
* Update information about this partion in pack
@@ -561,7 +493,7 @@ mkfs(struct partition *pp, char *fsys)
pp->p_fstype = FS_BSDFFS;
pp->p_fsize = sblock.fs_fsize;
pp->p_frag = sblock.fs_frag;
- pp->p_cpg = sblock.fs_cpg;
+ pp->p_cpg = sblock.fs_fpg;
}
}
@@ -571,9 +503,11 @@ mkfs(struct partition *pp, char *fsys)
void
initcg(int cylno, time_t utime)
{
- daddr_t cbase, d, dlower, dupper, dmax, blkno;
+ long i, j, d, dlower, dupper, blkno, start;
+ ufs2_daddr_t cbase, dmax;
+ struct ufs1_dinode *dp1;
+ struct ufs2_dinode *dp2;
struct csum *cs;
- long i, j;
/*
* Determine block bounds for cylinder group.
@@ -588,56 +522,54 @@ initcg(int cylno, time_t utime)
dupper = cgdmin(&sblock, cylno) - cbase;
if (cylno == 0)
dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
- cs = fscs + cylno;
+ cs = &fscs[cylno];
memset(&acg, 0, sblock.fs_cgsize);
acg.cg_time = utime;
acg.cg_magic = CG_MAGIC;
acg.cg_cgx = cylno;
- if (cylno == sblock.fs_ncg - 1)
- acg.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg;
- else
- acg.cg_ncyl = sblock.fs_cpg;
acg.cg_niblk = sblock.fs_ipg;
+ acg.cg_initediblk = sblock.fs_ipg < 2 * INOPB(&sblock) ?
+ sblock.fs_ipg : 2 * INOPB(&sblock);
acg.cg_ndblk = dmax - cbase;
if (sblock.fs_contigsumsize > 0)
acg.cg_nclusterblks = acg.cg_ndblk / sblock.fs_frag;
- acg.cg_btotoff = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield);
- acg.cg_boff = acg.cg_btotoff + sblock.fs_cpg * sizeof(int32_t);
- acg.cg_iusedoff = acg.cg_boff +
- sblock.fs_cpg * sizeof(u_int16_t);
- acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, NBBY);
- if (sblock.fs_contigsumsize <= 0) {
- acg.cg_nextfreeoff = acg.cg_freeoff +
- howmany(sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock),
- NBBY);
+ start = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield);
+ if (Oflag == 2) {
+ acg.cg_iusedoff = start;
} else {
- acg.cg_clustersumoff = acg.cg_freeoff + howmany
- (sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), NBBY) -
- sizeof(u_int32_t);
+ acg.cg_old_ncyl = sblock.fs_old_cpg;
+ acg.cg_old_time = acg.cg_time;
+ acg.cg_time = 0;
+ acg.cg_old_niblk = acg.cg_niblk;
+ acg.cg_niblk = 0;
+ acg.cg_initediblk = 0;
+ acg.cg_old_btotoff = start;
+ acg.cg_old_boff = acg.cg_old_btotoff +
+ sblock.fs_old_cpg * sizeof(int32_t);
+ acg.cg_iusedoff = acg.cg_old_boff +
+ sblock.fs_old_cpg * sizeof(u_int16_t);
+ }
+ acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, NBBY);
+ acg.cg_nextfreeoff = acg.cg_freeoff + howmany(sblock.fs_fpg, NBBY);
+ if (sblock.fs_contigsumsize > 0) {
acg.cg_clustersumoff =
- roundup(acg.cg_clustersumoff, sizeof(u_int32_t));
+ roundup(acg.cg_nextfreeoff, sizeof(u_int32_t));
+ acg.cg_clustersumoff -= sizeof(u_int32_t);
acg.cg_clusteroff = acg.cg_clustersumoff +
(sblock.fs_contigsumsize + 1) * sizeof(u_int32_t);
- acg.cg_nextfreeoff = acg.cg_clusteroff + howmany
- (sblock.fs_cpg * sblock.fs_spc / NSPB(&sblock), NBBY);
+ acg.cg_nextfreeoff = acg.cg_clusteroff +
+ howmany(fragstoblks(&sblock, sblock.fs_fpg), NBBY);
}
- if (acg.cg_nextfreeoff - (long)(&acg.cg_firstfield) >
- sblock.fs_cgsize) {
+ if (acg.cg_nextfreeoff > sblock.fs_cgsize) {
printf("Panic: cylinder group too big\n");
exit(37);
}
acg.cg_cs.cs_nifree += sblock.fs_ipg;
if (cylno == 0)
- for (i = 0; i < ROOTINO; i++) {
+ for (i = 0; i < (long)ROOTINO; i++) {
setbit(cg_inosused(&acg), i);
acg.cg_cs.cs_nifree--;
}
- for (i = 0; i < sblock.fs_ipg / INOPF(&sblock); i += sblock.fs_frag) {
- for (j = 0; j < sblock.fs_bsize / sizeof(struct dinode); j++)
- zino[j].di_gen = random();
- wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i),
- sblock.fs_bsize, (char *)zino);
- }
if (cylno > 0) {
/*
* In cylno 0, beginning space is reserved
@@ -649,13 +581,8 @@ initcg(int cylno, time_t utime)
if (sblock.fs_contigsumsize > 0)
setbit(cg_clustersfree(&acg), blkno);
acg.cg_cs.cs_nbfree++;
- cg_blktot(&acg)[cbtocylno(&sblock, d)]++;
- cg_blks(&sblock, &acg, cbtocylno(&sblock, d))
- [cbtorpos(&sblock, d)]++;
}
- sblock.fs_dsize += dlower;
}
- sblock.fs_dsize += acg.cg_ndblk - dupper;
if ((i = dupper % sblock.fs_frag)) {
acg.cg_frsum[sblock.fs_frag - i]++;
for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) {
@@ -663,20 +590,17 @@ initcg(int cylno, time_t utime)
acg.cg_cs.cs_nffree++;
}
}
- for (d = dupper; d + sblock.fs_frag <= dmax - cbase;) {
+ for (d = dupper; d + sblock.fs_frag <= acg.cg_ndblk;
+ d += sblock.fs_frag) {
blkno = d / sblock.fs_frag;
setblock(&sblock, cg_blksfree(&acg), blkno);
if (sblock.fs_contigsumsize > 0)
setbit(cg_clustersfree(&acg), blkno);
acg.cg_cs.cs_nbfree++;
- cg_blktot(&acg)[cbtocylno(&sblock, d)]++;
- cg_blks(&sblock, &acg, cbtocylno(&sblock, d))
- [cbtorpos(&sblock, d)]++;
- d += sblock.fs_frag;
}
- if (d < dmax - cbase) {
- acg.cg_frsum[dmax - cbase - d]++;
- for (; d < dmax - cbase; d++) {
+ if (d < acg.cg_ndblk) {
+ acg.cg_frsum[acg.cg_ndblk - d]++;
+ for (; d < acg.cg_ndblk; d++) {
setbit(cg_blksfree(&acg), d);
acg.cg_cs.cs_nffree++;
}
@@ -710,61 +634,103 @@ initcg(int cylno, time_t utime)
sump[run]++;
}
}
- sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir;
- sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree;
- sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree;
- sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree;
*cs = acg.cg_cs;
- wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)),
- sblock.fs_bsize, (char *)&acg);
+ /*
+ * Write out the duplicate super block, the cylinder group map
+ * and two blocks worth of inodes in a single write.
+ */
+ start = sblock.fs_bsize > SBLOCKSIZE ? sblock.fs_bsize : SBLOCKSIZE;
+ bcopy((char *)&acg, &iobuf[start], sblock.fs_cgsize);
+ start += sblock.fs_bsize;
+ dp1 = (struct ufs1_dinode *)(&iobuf[start]);
+ dp2 = (struct ufs2_dinode *)(&iobuf[start]);
+ for (i = 0; i < acg.cg_initediblk; i++) {
+ if (sblock.fs_magic == FS_UFS1_MAGIC) {
+ dp1->di_gen = random();
+ dp1++;
+ } else {
+ dp2->di_gen = random();
+ dp2++;
+ }
+ }
+ wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)), iobufsize, iobuf);
+ /*
+ * For the old filesystem, we have to initialize all the inodes.
+ */
+ if (Oflag == 1) {
+ for (i = 2 * sblock.fs_frag;
+ i < sblock.fs_ipg / INOPF(&sblock);
+ i += sblock.fs_frag) {
+ dp1 = (struct ufs1_dinode *)(&iobuf[start]);
+ for (j = 0; j < INOPB(&sblock); j++) {
+ dp1->di_gen = random();
+ dp1++;
+ }
+ wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i),
+ sblock.fs_bsize, &iobuf[start]);
+ }
+ }
}
/*
* initialize the filesystem
*/
-struct dinode node;
-
#define PREDEFDIR 2
struct direct root_dir[] = {
{ ROOTINO, sizeof(struct direct), DT_DIR, 1, "." },
{ ROOTINO, sizeof(struct direct), DT_DIR, 2, ".." },
};
-struct odirect {
- u_long d_ino;
- u_short d_reclen;
- u_short d_namlen;
- u_char d_name[MAXNAMLEN + 1];
-} oroot_dir[] = {
- { ROOTINO, sizeof(struct direct), 1, "." },
- { ROOTINO, sizeof(struct direct), 2, ".." },
-};
-char buf[MAXBSIZE];
void
fsinit(time_t utime)
{
+ union dinode node;
- /*
- * initialize the node
- */
- node.di_atime = utime;
- node.di_mtime = utime;
- node.di_ctime = utime;
- /*
- * create the root directory
- */
- node.di_mode = IFDIR | UMASK;
- node.di_nlink = PREDEFDIR;
- node.di_size = makedir(root_dir, PREDEFDIR);
- node.di_db[0] = alloc(sblock.fs_fsize, node.di_mode);
- node.di_blocks = btodb(fragroundup(&sblock, node.di_size));
- wtfs(fsbtodb(&sblock, node.di_db[0]), sblock.fs_fsize, buf);
+ memset(&node, 0, sizeof node);
+ if (sblock.fs_magic == FS_UFS1_MAGIC) {
+ /*
+ * initialize the node
+ */
+ node.dp1.di_atime = utime;
+ node.dp1.di_mtime = utime;
+ node.dp1.di_ctime = utime;
+ /*
+ * create the root directory
+ */
+ node.dp1.di_mode = IFDIR | UMASK;
+ node.dp1.di_nlink = PREDEFDIR;
+ node.dp1.di_size = makedir(root_dir, PREDEFDIR);
+ node.dp1.di_db[0] = alloc(sblock.fs_fsize, node.dp1.di_mode);
+ node.dp1.di_blocks =
+ btodb(fragroundup(&sblock, node.dp1.di_size));
+ wtfs(fsbtodb(&sblock, node.dp1.di_db[0]), sblock.fs_fsize,
+ iobuf);
+ } else {
+ /*
+ * initialize the node
+ */
+ node.dp2.di_atime = utime;
+ node.dp2.di_mtime = utime;
+ node.dp2.di_ctime = utime;
+ node.dp2.di_createtime = utime;
+ /*
+ * create the root directory
+ */
+ node.dp2.di_mode = IFDIR | UMASK;
+ node.dp2.di_nlink = PREDEFDIR;
+ node.dp2.di_size = makedir(root_dir, PREDEFDIR);
+ node.dp2.di_db[0] = alloc(sblock.fs_fsize, node.dp2.di_mode);
+ node.dp2.di_blocks =
+ btodb(fragroundup(&sblock, node.dp2.di_size));
+ wtfs(fsbtodb(&sblock, node.dp2.di_db[0]), sblock.fs_fsize,
+ iobuf);
+ }
iput(&node, ROOTINO);
}
/*
- * construct a set of directory entries in "buf".
+ * construct a set of directory entries in "iobuf".
* return size of directory.
*/
int
@@ -774,7 +740,8 @@ makedir(struct direct *protodir, int entries)
int i, spcleft;
spcleft = DIRBLKSIZ;
- for (cp = buf, i = 0; i < entries - 1; i++) {
+ memset(iobuf, 0, DIRBLKSIZ);
+ for (cp = iobuf, i = 0; i < entries - 1; i++) {
protodir[i].d_reclen = DIRSIZ(0, &protodir[i]);
memmove(cp, &protodir[i], protodir[i].d_reclen);
cp += protodir[i].d_reclen;
@@ -788,11 +755,10 @@ makedir(struct direct *protodir, int entries)
/*
* allocate a block or frag
*/
-daddr_t
+ufs2_daddr_t
alloc(int size, int mode)
{
- int i, frag;
- daddr_t d, blkno;
+ int i, d, blkno, frag;
rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize,
(char *)&acg);
@@ -822,8 +788,6 @@ goth:
sblock.fs_cstotal.cs_ndir++;
fscs[0].cs_ndir++;
}
- cg_blktot(&acg)[cbtocylno(&sblock, d)]--;
- cg_blks(&sblock, &acg, cbtocylno(&sblock, d))[cbtorpos(&sblock, d)]--;
if (size != sblock.fs_bsize) {
frag = howmany(size, sblock.fs_fsize);
fscs[0].cs_nffree += sblock.fs_frag - frag;
@@ -835,54 +799,18 @@ goth:
}
wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize,
(char *)&acg);
- return (d);
-}
-
-/*
- * Calculate number of inodes per group.
- */
-long
-calcipg(long lcpg, long bpcg, off_t *usedbp)
-{
- int i;
- long ipg, new_ipg, ncg, ncyl;
- off_t usedb;
-
- /*
- * Prepare to scale by fssize / (number of sectors in cylinder groups).
- * Note that fssize is still in sectors, not filesystem blocks.
- */
- ncyl = howmany(fssize, (u_int)secpercyl);
- ncg = howmany(ncyl, lcpg);
- /*
- * Iterate a few times to allow for ipg depending on itself.
- */
- ipg = 0;
- for (i = 0; i < 10; i++) {
- usedb = (sblock.fs_iblkno + ipg / INOPF(&sblock)) *
- NSPF(&sblock) * (off_t)sectorsize;
- new_ipg = (lcpg * (quad_t)bpcg - usedb) / density *
- fssize / ncg / secpercyl / lcpg;
- new_ipg = roundup(new_ipg, INOPB(&sblock));
- if (new_ipg == ipg)
- break;
- ipg = new_ipg;
- }
- *usedbp = usedb;
- return (ipg);
+ return ((ufs2_daddr_t)d);
}
/*
* Allocate an inode on the disk
*/
void
-iput(struct dinode *ip, ino_t ino)
+iput(union dinode *ip, ino_t ino)
{
- struct dinode lbuf[MAXINOPB];
- daddr_t d;
+ ufs2_daddr_t d;
int c;
- ip->di_gen = random();
c = ino_to_cg(&sblock, ino);
rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize,
(char *)&acg);
@@ -896,21 +824,26 @@ iput(struct dinode *ip, ino_t ino)
(char *)&acg);
sblock.fs_cstotal.cs_nifree--;
fscs[0].cs_nifree--;
- if (ino >= sblock.fs_ipg * sblock.fs_ncg) {
+ if (ino >= (unsigned long)sblock.fs_ipg * sblock.fs_ncg) {
printf("fsinit: inode value out of range (%d).\n", ino);
exit(32);
}
d = fsbtodb(&sblock, ino_to_fsba(&sblock, ino));
- rdfs(d, sblock.fs_bsize, (char *)lbuf);
- lbuf[ino_to_fsbo(&sblock, ino)] = *ip;
- wtfs(d, sblock.fs_bsize, (char *)lbuf);
+ rdfs(d, sblock.fs_bsize, (char *)iobuf);
+ if (sblock.fs_magic == FS_UFS1_MAGIC)
+ ((struct ufs1_dinode *)iobuf)[ino_to_fsbo(&sblock, ino)] =
+ ip->dp1;
+ else
+ ((struct ufs2_dinode *)iobuf)[ino_to_fsbo(&sblock, ino)] =
+ ip->dp2;
+ wtfs(d, sblock.fs_bsize, (char *)iobuf);
}
/*
* read a block from the filesystem
*/
void
-rdfs(daddr_t bno, int size, char *bf)
+rdfs(ufs2_daddr_t bno, int size, char *bf)
{
int n;
@@ -927,7 +860,7 @@ rdfs(daddr_t bno, int size, char *bf)
}
#define WCSIZE (128 * 1024)
-daddr_t wc_sect; /* units of sectorsize */
+ufs2_daddr_t wc_sect; /* units of sectorsize */
int wc_end; /* bytes */
static char wc[WCSIZE]; /* bytes */
@@ -956,7 +889,7 @@ wtfsflush()
* write a block to the filesystem
*/
static void
-wtfs(daddr_t bno, int size, char *bf)
+wtfs(ufs2_daddr_t bno, int size, char *bf)
{
int done, n;
diff --git a/sbin/newfs/newfs.8 b/sbin/newfs/newfs.8
index 9ca6337b7ab2..c20fe1526aa6 100644
--- a/sbin/newfs/newfs.8
+++ b/sbin/newfs/newfs.8
@@ -32,7 +32,7 @@
.\" @(#)newfs.8 8.6 (Berkeley) 5/3/95
.\" $FreeBSD$
.\"
-.Dd May 29, 2001
+.Dd May 18, 2002
.Dt NEWFS 8
.Os
.Sh NAME
@@ -40,12 +40,14 @@
.Nd construct a new filesystem
.Sh SYNOPSIS
.Nm
-.Op Fl NOU
+.Op Fl NU
+.Op Fl O Ar filesystem-type
.Op Fl S Ar sector-size
.Op Fl T Ar disktype
.Op Fl a Ar maxcontig
.Op Fl b Ar block-size
-.Op Fl c Ar cylinders
+.Op Fl c Ar blocks-per-cylinder-group
+.Op Fl d Ar max-extent-size
.Op Fl e Ar maxbpg
.Op Fl f Ar frag-size
.Op Fl g Ar avgfilesize
@@ -54,7 +56,6 @@
.Op Fl m Ar free space
.Op Fl o Ar optimization
.Op Fl s Ar size
-.Op Fl u Ar sectors
.Ar special
.Sh DESCRIPTION
.Nm Newfs
@@ -82,12 +83,16 @@ For backward compatibility.
.It Fl N
Cause the filesystem parameters to be printed out
without really creating the filesystem.
+.It Fl O
+Use 1 to specify that a UFS1 format filesystem be built;
+use 2 to specify that a UFS2 format filesystem be built.
+The default is UFS1 format, but will eventually be changed to UFS2.
.It Fl U
Enables soft updates on the new filesystem.
.It Fl a Ar maxcontig
Specify the maximum number of contiguous blocks that will be
laid out before forcing a rotational delay.
-The default value is 1.
+The default value is 16.
See
.Xr tunefs 8
for more details on how to set this option.
@@ -96,12 +101,17 @@ The block size of the filesystem, in bytes. It must be a power of 2. The
default size is 16384 bytes, and the smallest allowable size is 4096 bytes.
The optimal block:fragment ratio is 8:1.
Other ratios are possible, but are not recommended,
-and may produce unpredictable results.
-.It Fl c Ar #cylinders/group
-The number of cylinders per cylinder group in a filesystem. The default
+and may produce poor results.
+.It Fl c Ar number of blocks per cylinders group
+The number of blocks per cylinder group in a filesystem. The default
is to compute the maximum allowed by the other parameters. This value is
dependent on a number of other parameters, in particular the block size
and the number of bytes per inode.
+.It Fl d Ar max extent size
+The filesystem may choose to store large files using extents.
+This parameter specifies the largest extent size that may be used.
+It is presently limited to its default value which is 16 times
+the filesystem blocksize.
.It Fl e Ar maxbpg
Indicate the maximum number of blocks any single file can
allocate out of a cylinder group before it is forced to begin
@@ -178,11 +188,6 @@ to find the alternate superblocks if the standard superblock is lost.
.Bl -tag -width indent
.It Fl S Ar sector-size
The size of a sector in bytes (almost never anything but 512).
-.It Fl u Ar sectors/cylinders
-The number of sectors per cylinder available for data allocation by the file
-system.
-The default is 4096.
-If zero is specified, the value from the disklabel will be used.
.El
.Sh EXAMPLES
.Dl newfs /dev/ad3s1a
@@ -191,13 +196,12 @@ Creates a new ufs filesystem on
.Pa ad3s1a .
.Nm
will use a block size of 16384 bytes, a fragment size of 2048 bytes
-and the largest possible number of cylinders per group.
+and the largest possible number of blocks per cylinders group.
These values tend to produce better performance for most applications
than the historical defaults
(8192 byte block size and 1024 byte fragment size).
-This large fragment size
-may lead to large amounts of wasted space
-on filesystems that contain a large number of small files.
+This large fragment size may lead to much wasted space
+on filesystems that contain many small files.
.Sh SEE ALSO
.Xr fdformat 1 ,
.Xr disktab 5 ,
diff --git a/sbin/newfs/newfs.c b/sbin/newfs/newfs.c
index f6b9e71811d9..6c43a375d84b 100644
--- a/sbin/newfs/newfs.c
+++ b/sbin/newfs/newfs.c
@@ -1,4 +1,16 @@
/*
+ * Copyright (c) 2002 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by Marshall
+ * Kirk McKusick and Network Associates Laboratories, the Security
+ * Research Division of Network Associates, Inc. under DARPA/SPAWAR
+ * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
+ * research program
+ *
+ * Copyright (c) 1982, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
* Copyright (c) 1983, 1989, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
@@ -84,19 +96,19 @@ static const char rcsid[] =
#define DFL_BLKSIZE 16384
/*
- * Cylinder groups may have up to many cylinders. The actual
+ * Cylinder groups may have up to MAXBLKSPERCG blocks. The actual
* number used depends upon how much information can be stored
- * on a single cylinder. The default is to use as many as possible
- * cylinders per group.
+ * in a cylinder group map which must fit in a single filesystem
+ * block. The default is to use as many as possible blocks per group.
*/
-#define DESCPG 65536 /* desired fs_cpg ("infinity") */
+#define MAXBLKSPERCG 0x7fffffff /* desired fs_fpg ("infinity") */
/*
* MAXBLKPG determines the maximum number of data blocks which are
* placed in a single cylinder group. The default is one indirect
* block worth of data blocks.
*/
-#define MAXBLKPG(bsize) ((bsize) / sizeof(daddr_t))
+#define MAXBLKPG(bsize) ((bsize) / sizeof(ufs2_daddr_t))
/*
* Each filesystem has a number of inodes statically allocated.
@@ -105,26 +117,17 @@ static const char rcsid[] =
*/
#define NFPI 4
-/*
- * About the same time as the above, we knew what went where on the disks.
- * no longer so, so kill the code which finds the different platters too...
- * We do this by saying one head, with a lot of sectors on it.
- * The number of sectors are used to determine the size of a cyl-group.
- * Kirk suggested one or two meg per "cylinder" so we say two.
- */
-#define NSECTORS 4096 /* number of sectors */
-
int Nflag; /* run without writing filesystem */
+int Oflag = 1; /* filesystem format (1 => UFS1, 2 => UFS2) */
int Rflag; /* regression test */
int Uflag; /* enable soft updates for filesystem */
-u_int fssize; /* filesystem size */
-u_int secpercyl = NSECTORS; /* sectors per cylinder */
-u_int sectorsize; /* bytes/sector */
+quad_t fssize; /* file system size */
+int sectorsize; /* bytes/sector */
int realsectorsize; /* bytes/sector in hardware */
int fsize = 0; /* fragment size */
int bsize = 0; /* block size */
-int cpg = DESCPG; /* cylinders/cylinder group */
-int cpgflg; /* cylinders/cylinder group flag was given */
+int maxbsize = 0; /* maximum clustering */
+int maxblkspercg = MAXBLKSPERCG; /* maximum blocks per cylinder group */
int minfree = MINFREE; /* free space threshold */
int opt = DEFAULTOPT; /* optimization preference (space or time) */
int density; /* number of bytes per inode */
@@ -136,7 +139,6 @@ int fso; /* filedescriptor to device */
static char device[MAXPATHLEN];
static char *disktype;
-static int t_or_u_flag; /* user has specified -t or -u */
static int unlabeled;
static struct disklabel *getdisklabel(char *s);
@@ -151,15 +153,20 @@ main(int argc, char *argv[])
struct partition oldpartition;
struct stat st;
char *cp, *special;
- int ch, n;
+ int ch;
off_t mediasize;
while ((ch = getopt(argc, argv,
- "NRS:T:Ua:b:c:e:f:g:h:i:m:o:s:u:")) != -1)
+ "NO:RS:T:Ua:b:c:d:e:f:g:h:i:m:o:s:")) != -1)
switch (ch) {
case 'N':
Nflag = 1;
break;
+ case 'O':
+ if ((Oflag = atoi(optarg)) < 1 || Oflag > 2)
+ errx(1, "%s: bad filesystem format value",
+ optarg);
+ break;
case 'R':
Rflag = 1;
break;
@@ -183,13 +190,17 @@ main(int argc, char *argv[])
errx(1, "%s: bad block size", optarg);
break;
case 'c':
- if ((cpg = atoi(optarg)) <= 0)
- errx(1, "%s: bad cylinders/group", optarg);
- cpgflg++;
+ if ((maxblkspercg = atoi(optarg)) <= 0)
+ errx(1, "%s: bad blocks per cylinder group",
+ optarg);
+ break;
+ case 'd':
+ if ((maxbsize = atoi(optarg)) < MINBSIZE)
+ errx(1, "%s: bad extent block size", optarg);
break;
case 'e':
if ((maxbpg = atoi(optarg)) <= 0)
- errx(1, "%s: bad blocks per file in a cylinder group",
+ errx(1, "%s: bad blocks per file in a cylinder group",
optarg);
break;
case 'f':
@@ -202,7 +213,7 @@ main(int argc, char *argv[])
break;
case 'h':
if ((avgfilesperdir = atoi(optarg)) <= 0)
- errx(1, "%s: bad average files per dir", optarg);
+ errx(1, "%s: bad average files per dir", optarg);
break;
case 'i':
if ((density = atoi(optarg)) <= 0)
@@ -226,12 +237,6 @@ main(int argc, char *argv[])
if ((fssize = atoi(optarg)) <= 0)
errx(1, "%s: bad filesystem size", optarg);
break;
- case 'u':
- t_or_u_flag++;
- if ((n = atoi(optarg)) < 0)
- errx(1, "%s: bad sectors/track", optarg);
- secpercyl = n;
- break;
case '?':
default:
usage();
@@ -293,8 +298,6 @@ main(int argc, char *argv[])
if (fssize > pp->p_size)
errx(1,
"%s: maximum filesystem size %d", special, pp->p_size);
- if (secpercyl == 0)
- secpercyl = lp->d_nsectors;
if (sectorsize == 0)
sectorsize = lp->d_secsize;
if (fsize == 0)
@@ -308,8 +311,8 @@ main(int argc, char *argv[])
fsize = MAX(DFL_FRAGSIZE, sectorsize);
if (bsize <= 0)
bsize = MIN(DFL_BLKSIZE, 8 * fsize);
- if (secpercyl <= 0)
- errx(1, "%s: no default #sectors/track", special);
+ if (maxbsize == 0)
+ maxbsize = bsize;
/*
* Maxcontig sets the default for the maximum number of blocks
* that may be allocated sequentially. With filesystem clustering
@@ -317,7 +320,7 @@ main(int argc, char *argv[])
* transfer size permitted by the controller or buffering.
*/
if (maxcontig == 0)
- maxcontig = MAX(1, MAXPHYS / bsize - 1);
+ maxcontig = MAX(1, MAXPHYS / bsize);
if (density == 0)
density = NFPI * fsize;
if (minfree < MINFREE && opt != FS_OPTSPACE) {
@@ -325,15 +328,6 @@ main(int argc, char *argv[])
fprintf(stderr, "because minfree is less than %d%%\n", MINFREE);
opt = FS_OPTSPACE;
}
- /*
- * Only complain if -t or -u have been specified; the default
- * case (4096 sectors per cylinder) is intended to disagree
- * with the disklabel.
- */
- if (t_or_u_flag && lp != NULL && secpercyl != lp->d_secpercyl)
- fprintf(stderr, "%s (%d) %s (%lu)\n",
- "Warning: calculated sectors per cylinder", secpercyl,
- "disagrees with disk label", (u_long)lp->d_secpercyl);
if (maxbpg == 0)
maxbpg = MAXBLKPG(bsize);
realsectorsize = sectorsize;
@@ -341,7 +335,6 @@ main(int argc, char *argv[])
int secperblk = sectorsize / DEV_BSIZE;
sectorsize = DEV_BSIZE;
- secpercyl *= secperblk;
fssize *= secperblk;
if (pp != NULL);
pp->p_size *= secperblk;
@@ -349,7 +342,7 @@ main(int argc, char *argv[])
mkfs(pp, special);
if (!unlabeled) {
if (realsectorsize != DEV_BSIZE)
- pp->p_size /= realsectorsize /DEV_BSIZE;
+ pp->p_size /= realsectorsize / DEV_BSIZE;
if (!Nflag && bcmp(pp, &oldpartition, sizeof(oldpartition)))
rewritelabel(special, lp);
}
@@ -357,8 +350,6 @@ main(int argc, char *argv[])
exit(0);
}
-const char lmsg[] = "%s: can't read disk label; disk type must be specified";
-
struct disklabel *
getdisklabel(char *s)
{
@@ -399,13 +390,15 @@ usage()
fprintf(stderr, "where fsoptions are:\n");
fprintf(stderr,
"\t-N do not create filesystem, just print out parameters\n");
+ fprintf(stderr, "\t-O filesystem format: 1 => UFS1, 2 => UFS2\n");
fprintf(stderr, "\t-R regression test, supress random factors\n");
fprintf(stderr, "\t-S sector size\n");
fprintf(stderr, "\t-T disktype\n");
fprintf(stderr, "\t-U enable soft updates\n");
fprintf(stderr, "\t-a maximum contiguous blocks\n");
fprintf(stderr, "\t-b block size\n");
- fprintf(stderr, "\t-c cylinders/group\n");
+ fprintf(stderr, "\t-c blocks per cylinders group\n");
+ fprintf(stderr, "\t-d maximum extent size\n");
fprintf(stderr, "\t-e maximum blocks per file in a cylinder group\n");
fprintf(stderr, "\t-f frag size\n");
fprintf(stderr, "\t-g average file size\n");
@@ -413,9 +406,6 @@ usage()
fprintf(stderr, "\t-i number of bytes per inode\n");
fprintf(stderr, "\t-m minimum free space %%\n");
fprintf(stderr, "\t-o optimization preference (`space' or `time')\n");
- fprintf(stderr, "\t-s filesystem size (sectors)\n");
- fprintf(stderr, "\t-u sectors/cylinder\n");
- fprintf(stderr,
- "\t-v do not attempt to determine partition name from device name\n");
+ fprintf(stderr, "\t-s file systemsize (sectors)\n");
exit(1);
}
diff --git a/sbin/newfs/newfs.h b/sbin/newfs/newfs.h
index d5fec76ce316..636c112598a8 100644
--- a/sbin/newfs/newfs.h
+++ b/sbin/newfs/newfs.h
@@ -1,4 +1,16 @@
/*
+ * Copyright (c) 2002 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by Marshall
+ * Kirk McKusick and Network Associates Laboratories, the Security
+ * Research Division of Network Associates, Inc. under DARPA/SPAWAR
+ * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
+ * research program
+ *
+ * Copyright (c) 1982, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
* Copyright (c) 1980, 1989, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -38,16 +50,16 @@
* variables set up by front end.
*/
extern int Nflag; /* run mkfs without writing filesystem */
+extern int Oflag; /* build UFS1 format filesystem */
extern int Rflag; /* regression test */
extern int Uflag; /* enable soft updates for filesystem */
-extern u_int fssize; /* filesystem size */
-extern u_int secpercyl; /* sectors per cylinder */
-extern u_int sectorsize; /* bytes/sector */
+extern quad_t fssize; /* file system size */
+extern int sectorsize; /* bytes/sector */
extern int realsectorsize; /* bytes/sector in hardware*/
extern int fsize; /* fragment size */
extern int bsize; /* block size */
-extern int cpg; /* cylinders/cylinder group */
-extern int cpgflg; /* cylinders/cylinder group flag was given */
+extern int maxbsize; /* maximum clustering */
+extern int maxblkspercg; /* maximum blocks per cylinder group */
extern int minfree; /* free space threshold */
extern int opt; /* optimization preference (space or time) */
extern int density; /* number of bytes per inode */
diff --git a/sbin/quotacheck/quotacheck.c b/sbin/quotacheck/quotacheck.c
index 54339e7a70e0..8407676f7f5d 100644
--- a/sbin/quotacheck/quotacheck.c
+++ b/sbin/quotacheck/quotacheck.c
@@ -82,6 +82,14 @@ union {
long dev_bsize = 1;
ino_t maxino;
+union dinode {
+ struct ufs1_dinode dp1;
+ struct ufs2_dinode dp2;
+};
+#define DIP(dp, field) \
+ ((sblock.fs_magic == FS_UFS1_MAGIC) ? \
+ (dp)->dp1.field : (dp)->dp2.field)
+
struct quotaname {
long flags;
char grpqfname[MAXPATHLEN + 1];
@@ -116,7 +124,7 @@ extern int checkfstab(int, int, void * (*)(struct fstab *),
int (*)(char *, char *, struct quotaname *));
int chkquota(char *, char *, struct quotaname *);
void freeinodebuf(void);
-struct dinode *
+union dinode *
getnextinode(ino_t);
int getquotagid(void);
int hasquota(struct fstab *, int, char **);
@@ -241,6 +249,11 @@ needchk(fs)
}
/*
+ * Possible superblock locations ordered from most to least likely.
+ */
+static int sblock_try[] = SBLOCKSEARCH;
+
+/*
* Scan the specified filesystem to check quota(s) present on it.
*/
int
@@ -249,7 +262,7 @@ chkquota(fsname, mntpt, qnp)
struct quotaname *qnp;
{
struct fileusage *fup;
- struct dinode *dp;
+ union dinode *dp;
int cg, i, mode, errs = 0;
ino_t ino;
@@ -268,7 +281,20 @@ chkquota(fsname, mntpt, qnp)
}
sync();
dev_bsize = 1;
- bread(SBOFF, (char *)&sblock, (long)SBSIZE);
+ for (i = 0; sblock_try[i] != -1; i++) {
+ bread(sblock_try[i], (char *)&sblock, (long)SBLOCKSIZE);
+ if ((sblock.fs_magic == FS_UFS1_MAGIC ||
+ (sblock.fs_magic == FS_UFS2_MAGIC &&
+ sblock.fs_sblockloc ==
+ numfrags(&sblock, sblock_try[i]))) &&
+ sblock.fs_bsize <= MAXBSIZE &&
+ sblock.fs_bsize >= sizeof(struct fs))
+ break;
+ }
+ if (sblock_try[i] == -1) {
+ warn("Cannot find filesystem superblock");
+ return (1);
+ }
dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1);
maxino = sblock.fs_ncg * sblock.fs_ipg;
resetinodebuf();
@@ -278,23 +304,23 @@ chkquota(fsname, mntpt, qnp)
continue;
if ((dp = getnextinode(ino)) == NULL)
continue;
- if ((mode = dp->di_mode & IFMT) == 0)
+ if ((mode = DIP(dp, di_mode) & IFMT) == 0)
continue;
if (qnp->flags & HASGRP) {
- fup = addid((u_long)dp->di_gid, GRPQUOTA,
+ fup = addid((u_long)DIP(dp, di_gid), GRPQUOTA,
(char *)0);
fup->fu_curinodes++;
if (mode == IFREG || mode == IFDIR ||
mode == IFLNK)
- fup->fu_curblocks += dp->di_blocks;
+ fup->fu_curblocks += DIP(dp, di_blocks);
}
if (qnp->flags & HASUSR) {
- fup = addid((u_long)dp->di_uid, USRQUOTA,
+ fup = addid((u_long)DIP(dp, di_uid), USRQUOTA,
(char *)0);
fup->fu_curinodes++;
if (mode == IFREG || mode == IFDIR ||
mode == IFLNK)
- fup->fu_curblocks += dp->di_blocks;
+ fup->fu_curblocks += DIP(dp, di_blocks);
}
}
}
@@ -536,20 +562,21 @@ addid(id, type, name)
* Special purpose version of ginode used to optimize pass
* over all the inodes in numerical order.
*/
-ino_t nextino, lastinum;
-long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize;
-struct dinode *inodebuf;
-#define INOBUFSIZE 56*1024 /* size of buffer to read inodes */
+static ino_t nextino, lastinum, lastvalidinum;
+static long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize;
+static caddr_t inodebuf;
+#define INOBUFSIZE 56*1024 /* size of buffer to read inodes */
-struct dinode *
+union dinode *
getnextinode(inumber)
ino_t inumber;
{
long size;
- daddr_t dblk;
- static struct dinode *dp;
+ ufs2_daddr_t dblk;
+ union dinode *dp;
+ static caddr_t nextinop;
- if (inumber != nextino++ || inumber > maxino)
+ if (inumber != nextino++ || inumber > lastvalidinum)
errx(1, "bad inode number %d to nextinode", inumber);
if (inumber >= lastinum) {
readcnt++;
@@ -561,10 +588,19 @@ getnextinode(inumber)
size = inobufsize;
lastinum += fullcnt;
}
- bread(dblk, (char *)inodebuf, size);
- dp = inodebuf;
+ /*
+ * If bread returns an error, it will already have zeroed
+ * out the buffer, so we do not need to do so here.
+ */
+ bread(dblk, inodebuf, size);
+ nextinop = inodebuf;
}
- return (dp++);
+ dp = (union dinode *)nextinop;
+ if (sblock.fs_magic == FS_UFS1_MAGIC)
+ nextinop += sizeof(struct ufs1_dinode);
+ else
+ nextinop += sizeof(struct ufs2_dinode);
+ return (dp);
}
/*
@@ -578,10 +614,12 @@ resetinodebuf()
lastinum = 0;
readcnt = 0;
inobufsize = blkroundup(&sblock, INOBUFSIZE);
- fullcnt = inobufsize / sizeof(struct dinode);
+ fullcnt = inobufsize / ((sblock.fs_magic == FS_UFS1_MAGIC) ?
+ sizeof(struct ufs1_dinode) : sizeof(struct ufs2_dinode));
readpercg = sblock.fs_ipg / fullcnt;
partialcnt = sblock.fs_ipg % fullcnt;
- partialsize = partialcnt * sizeof(struct dinode);
+ partialsize = partialcnt * ((sblock.fs_magic == FS_UFS1_MAGIC) ?
+ sizeof(struct ufs1_dinode) : sizeof(struct ufs2_dinode));
if (partialcnt != 0) {
readpercg++;
} else {
diff --git a/sbin/restore/dirs.c b/sbin/restore/dirs.c
index 32da860b0de9..323e9ff6bc1a 100644
--- a/sbin/restore/dirs.c
+++ b/sbin/restore/dirs.c
@@ -120,7 +120,7 @@ struct odirect {
char d_name[ODIRSIZ];
};
-static struct inotab *allocinotab(ino_t, struct dinode *, long);
+static struct inotab *allocinotab(struct context *, long);
static void dcvt(struct odirect *, struct direct *);
static void flushent(void);
static struct inotab *inotablookup(ino_t);
@@ -140,11 +140,9 @@ static struct direct *searchdir(ino_t, char *);
void
extractdirs(int genmode)
{
- int i;
- struct dinode *ip;
struct inotab *itp;
struct direct nulldir;
- int fd;
+ int i, fd;
const char *tmpdir;
vprintf(stdout, "Extract directories from tape\n");
@@ -184,8 +182,7 @@ extractdirs(int genmode)
for (;;) {
curfile.name = "<directory file - name unknown>";
curfile.action = USING;
- ip = curfile.dip;
- if (ip == NULL || (ip->di_mode & IFMT) != IFDIR) {
+ if (curfile.mode == 0 || (curfile.mode & IFMT) != IFDIR) {
(void) fclose(df);
dirp = opendirfile(dirfile);
if (dirp == NULL)
@@ -198,7 +195,7 @@ extractdirs(int genmode)
panic("Root directory is not on tape\n");
return;
}
- itp = allocinotab(curfile.ino, ip, seekpt);
+ itp = allocinotab(&curfile, seekpt);
getfile(putdir, xtrnull);
putent(&nulldir);
flushent();
@@ -213,7 +210,7 @@ void
skipdirs(void)
{
- while (curfile.dip && (curfile.dip->di_mode & IFMT) == IFDIR) {
+ while (curfile.ino && (curfile.mode & IFMT) == IFDIR) {
skipfile();
}
}
@@ -343,53 +340,34 @@ putdir(char *buf, long size)
struct direct *dp;
long loc, i;
- if (cvtflag) {
- eodp = (struct odirect *)&buf[size];
- for (odp = (struct odirect *)buf; odp < eodp; odp++)
- if (odp->d_ino != 0) {
- dcvt(odp, &cvtbuf);
- putent(&cvtbuf);
- }
- } else {
- for (loc = 0; loc < size; ) {
- dp = (struct direct *)(buf + loc);
- if (Bcvt)
- swabst((u_char *)"ls", (u_char *) dp);
- if (oldinofmt && dp->d_ino != 0) {
-# if BYTE_ORDER == BIG_ENDIAN
- if (Bcvt)
- dp->d_namlen = dp->d_type;
-# else
- if (!Bcvt)
- dp->d_namlen = dp->d_type;
-# endif
- dp->d_type = DT_UNKNOWN;
- }
- i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1));
- if ((dp->d_reclen & 0x3) != 0 ||
- dp->d_reclen > i ||
- dp->d_reclen < DIRSIZ(0, dp) ||
- dp->d_namlen > NAME_MAX) {
- vprintf(stdout, "Mangled directory: ");
- if ((dp->d_reclen & 0x3) != 0)
- vprintf(stdout,
- "reclen not multiple of 4 ");
- if (dp->d_reclen < DIRSIZ(0, dp))
- vprintf(stdout,
- "reclen less than DIRSIZ (%d < %d) ",
- dp->d_reclen, DIRSIZ(0, dp));
- if (dp->d_namlen > NAME_MAX)
- vprintf(stdout,
- "reclen name too big (%d > %d) ",
- dp->d_namlen, NAME_MAX);
- vprintf(stdout, "\n");
- loc += i;
- continue;
- }
- loc += dp->d_reclen;
- if (dp->d_ino != 0) {
- putent(dp);
- }
+ for (loc = 0; loc < size; ) {
+ dp = (struct direct *)(buf + loc);
+ if (Bcvt)
+ swabst((u_char *)"ls", (u_char *) dp);
+ i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1));
+ if ((dp->d_reclen & 0x3) != 0 ||
+ dp->d_reclen > i ||
+ dp->d_reclen < DIRSIZ(0, dp) ||
+ dp->d_namlen > NAME_MAX) {
+ vprintf(stdout, "Mangled directory: ");
+ if ((dp->d_reclen & 0x3) != 0)
+ vprintf(stdout,
+ "reclen not multiple of 4 ");
+ if (dp->d_reclen < DIRSIZ(0, dp))
+ vprintf(stdout,
+ "reclen less than DIRSIZ (%d < %d) ",
+ dp->d_reclen, DIRSIZ(0, dp));
+ if (dp->d_namlen > NAME_MAX)
+ vprintf(stdout,
+ "reclen name too big (%d > %d) ",
+ dp->d_namlen, NAME_MAX);
+ vprintf(stdout, "\n");
+ loc += i;
+ continue;
+ }
+ loc += dp->d_reclen;
+ if (dp->d_ino != 0) {
+ putent(dp);
}
}
}
@@ -692,7 +670,7 @@ inodetype(ino_t ino)
* If requested, save its pertinent mode, owner, and time info.
*/
static struct inotab *
-allocinotab(ino_t ino, struct dinode *dip, long seekpt)
+allocinotab(struct context *ctxp, long seekpt)
{
struct inotab *itp;
struct modeinfo node;
@@ -700,21 +678,21 @@ allocinotab(ino_t ino, struct dinode *dip, long seekpt)
itp = calloc(1, sizeof(struct inotab));
if (itp == NULL)
panic("no memory directory table\n");
- itp->t_next = inotab[INOHASH(ino)];
- inotab[INOHASH(ino)] = itp;
- itp->t_ino = ino;
+ itp->t_next = inotab[INOHASH(ctxp->ino)];
+ inotab[INOHASH(ctxp->ino)] = itp;
+ itp->t_ino = ctxp->ino;
itp->t_seekpt = seekpt;
if (mf == NULL)
return (itp);
- node.ino = ino;
- node.timep[0].tv_sec = dip->di_atime;
- node.timep[0].tv_usec = dip->di_atimensec / 1000;
- node.timep[1].tv_sec = dip->di_mtime;
- node.timep[1].tv_usec = dip->di_mtimensec / 1000;
- node.mode = dip->di_mode;
- node.flags = dip->di_flags;
- node.uid = dip->di_uid;
- node.gid = dip->di_gid;
+ node.ino = ctxp->ino;
+ node.timep[0].tv_sec = ctxp->atime_sec;
+ node.timep[0].tv_usec = ctxp->atime_nsec / 1000;
+ node.timep[1].tv_sec = ctxp->mtime_sec;
+ node.timep[1].tv_usec = ctxp->mtime_nsec / 1000;
+ node.mode = ctxp->mode;
+ node.flags = ctxp->file_flags;
+ node.uid = ctxp->uid;
+ node.gid = ctxp->gid;
(void) fwrite((char *)&node, 1, sizeof(struct modeinfo), mf);
return (itp);
}
diff --git a/sbin/restore/main.c b/sbin/restore/main.c
index 0c7b363a04eb..ef3df7a79ae7 100644
--- a/sbin/restore/main.c
+++ b/sbin/restore/main.c
@@ -98,9 +98,9 @@ main(int argc, char *argv[])
inputdev = _PATH_DEFTAPE;
obsolete(&argc, &argv);
#ifdef KERBEROS
-#define optlist "b:cdf:hikmNRrs:tuvxy"
+#define optlist "b:df:hikmNRrs:tuvxy"
#else
-#define optlist "b:cdf:himNRrs:tuvxy"
+#define optlist "b:df:himNRrs:tuvxy"
#endif
while ((ch = getopt(argc, argv, optlist)) != -1)
switch(ch) {
@@ -113,9 +113,6 @@ main(int argc, char *argv[])
if (ntrec <= 0)
errx(1, "block size must be greater than 0");
break;
- case 'c':
- cvtflag = 1;
- break;
case 'd':
dflag = 1;
break;
diff --git a/sbin/restore/restore.c b/sbin/restore/restore.c
index 46e208bc43fc..0a3647d4855a 100644
--- a/sbin/restore/restore.c
+++ b/sbin/restore/restore.c
@@ -41,11 +41,11 @@ static const char rcsid[] =
#include <sys/types.h>
-#include <ufs/ufs/dinode.h>
-
#include <stdio.h>
#include <string.h>
+#include <ufs/ufs/dinode.h>
+
#include "restore.h"
#include "extern.h"
diff --git a/sbin/restore/restore.h b/sbin/restore/restore.h
index 1e71330ca34b..cb10d8169e5c 100644
--- a/sbin/restore/restore.h
+++ b/sbin/restore/restore.h
@@ -42,7 +42,6 @@
/*
* Flags
*/
-extern int cvtflag; /* convert from old to new tape format */
extern int bflag; /* set input block size */
extern int dflag; /* print out debugging info */
extern int hflag; /* restore heirarchies */
@@ -64,7 +63,6 @@ extern time_t dumptime; /* time that this dump begins */
extern time_t dumpdate; /* time that this dump was made */
extern char command; /* opration being performed */
extern FILE *terminal; /* file descriptor for the terminal input */
-extern int oldinofmt; /* reading tape with old format inodes */
extern int Bcvt; /* need byte swapping on inodes and dirs */
/*
@@ -106,10 +104,19 @@ struct entry {
* The entry describes the next file available on the tape
*/
struct context {
- char *name; /* name of file */
+ short action; /* action being taken on this file */
+ mode_t mode; /* mode of file */
ino_t ino; /* inumber of file */
- struct dinode *dip; /* pointer to inode */
- char action; /* action being taken on this file */
+ uid_t uid; /* file owner */
+ gid_t gid; /* file group */
+ int file_flags; /* status flags (chflags) */
+ int rdev; /* device number of file */
+ time_t atime_sec; /* access time seconds */
+ time_t mtime_sec; /* modified time seconds */
+ int atime_nsec; /* access time nanoseconds */
+ int mtime_nsec; /* modified time nanoseconds */
+ off_t size; /* size of file */
+ char *name; /* name of file */
} curfile;
/* actions */
#define USING 1 /* extracting from the tape */
diff --git a/sbin/restore/tape.c b/sbin/restore/tape.c
index c40c7a9d0211..2b2ab916c470 100644
--- a/sbin/restore/tape.c
+++ b/sbin/restore/tape.c
@@ -74,20 +74,19 @@ static int numtrec;
static char *tapebuf;
static union u_spcl endoftapemark;
static long blksread; /* blocks read since last header */
-static long tapeaddr = 0; /* current TP_BSIZE tape record */
+static int64_t tapeaddr = 0; /* current TP_BSIZE tape record */
static long tapesread;
static jmp_buf restart;
static int gettingfile = 0; /* restart has a valid frame */
static char *host = NULL;
+static int readmapflag;
static int ofile;
static char *map;
static char lnkbuf[MAXPATHLEN + 1];
static int pathlen;
-int oldinofmt; /* old inode format conversion required */
-int Bcvt; /* Swap Bytes (for CCI or sun) */
-static int Qcvt; /* Swap quads (for sun) */
+int Bcvt; /* Swap Bytes */
#define FLUSHTAPEBUF() blkcnt = ntrec + 1
@@ -109,8 +108,6 @@ static void xtrmap(char *, long);
static void xtrmapskip(char *, long);
static void xtrskip(char *, long);
-static int readmapflag;
-
/*
* Set up an input source
*/
@@ -207,17 +204,11 @@ setup(void)
if (!pipein && !bflag)
findtapeblksize();
if (gethead(&spcl) == FAIL) {
- blkcnt--; /* push back this block */
- blksread--;
- cvtflag++;
- if (gethead(&spcl) == FAIL) {
- fprintf(stderr, "Tape is not a dump tape\n");
- done(1);
- }
- fprintf(stderr, "Converting to new filesystem format.\n");
+ fprintf(stderr, "Tape is not a dump tape\n");
+ done(1);
}
if (pipein) {
- endoftapemark.s_spcl.c_magic = cvtflag ? OFS_MAGIC : NFS_MAGIC;
+ endoftapemark.s_spcl.c_magic = FS_UFS2_MAGIC;
endoftapemark.s_spcl.c_type = TS_END;
ip = (int *)&endoftapemark;
j = sizeof(union u_spcl) / sizeof(int);
@@ -229,8 +220,8 @@ setup(void)
}
if (vflag || command == 't')
printdumpinfo();
- dumptime = _time32_to_time(spcl.c_ddate);
- dumpdate = _time32_to_time(spcl.c_date);
+ dumptime = _time64_to_time(spcl.c_ddate);
+ dumpdate = _time64_to_time(spcl.c_date);
if (stat(".", &stbuf) < 0) {
fprintf(stderr, "cannot stat .: %s\n", strerror(errno));
done(1);
@@ -279,8 +270,7 @@ setup(void)
* whiteout inode exists, so that the whiteout entries can be
* extracted.
*/
- if (oldinofmt == 0)
- SETINO(WINO, dumpmap);
+ SETINO(WINO, dumpmap);
/* 'r' restores don't call getvol() for tape 1, so mark it as read. */
if (command == 'r')
tapesread = 1;
@@ -296,7 +286,8 @@ setup(void)
void
getvol(long nextvol)
{
- long newvol, prevtapea, savecnt, i;
+ int64_t prevtapea;
+ long i, newvol, savecnt;
union u_spcl tmpspcl;
# define tmpbuf tmpspcl.s_spcl
char buf[TP_BSIZE];
@@ -403,9 +394,9 @@ gethdr:
volno = 0;
goto again;
}
- if (_time32_to_time(tmpbuf.c_date) != dumpdate ||
- _time32_to_time(tmpbuf.c_ddate) != dumptime) {
- time_t t = _time32_to_time(tmpbuf.c_date);
+ if (_time64_to_time(tmpbuf.c_date) != dumpdate ||
+ _time64_to_time(tmpbuf.c_ddate) != dumptime) {
+ time_t t = _time64_to_time(tmpbuf.c_date);
fprintf(stderr, "Wrong dump date\n\tgot: %s", ctime(&t));
fprintf(stderr, "\twanted: %s", ctime(&dumpdate));
volno = 0;
@@ -420,9 +411,9 @@ gethdr:
* If coming to this volume at random, skip to the beginning
* of the next record.
*/
- dprintf(stdout, "last rec %ld, tape starts with %ld\n", prevtapea,
+ dprintf(stdout, "last rec %qd, tape starts with %qd\n", prevtapea,
tmpbuf.c_tapea);
- if (tmpbuf.c_type == TS_TAPE && (tmpbuf.c_flags & DR_NEWHEADER)) {
+ if (tmpbuf.c_type == TS_TAPE) {
if (curfile.action != USING) {
/*
* XXX Dump incorrectly sets c_count to 1 in the
@@ -475,7 +466,7 @@ terminateinput(void)
}
curfile.name = "<name unknown>";
curfile.action = UNKNOWN;
- curfile.dip = NULL;
+ curfile.mode = 0;
curfile.ino = maxino;
if (gettingfile) {
gettingfile = 0;
@@ -513,9 +504,9 @@ void
printdumpinfo(void)
{
time_t t;
- t = _time32_to_time(spcl.c_date);
+ t = _time64_to_time(spcl.c_date);
fprintf(stdout, "Dump date: %s", ctime(&t));
- t = _time32_to_time(spcl.c_ddate);
+ t = _time64_to_time(spcl.c_ddate);
fprintf(stdout, "Dumped from: %s",
(spcl.c_ddate == 0) ? "the epoch\n" : ctime(&t));
if (spcl.c_host[0] == '\0')
@@ -529,22 +520,18 @@ int
extractfile(char *name)
{
int flags;
- uid_t uid;
- gid_t gid;
mode_t mode;
struct timeval timep[2];
struct entry *ep;
curfile.name = name;
curfile.action = USING;
- timep[0].tv_sec = curfile.dip->di_atime;
- timep[0].tv_usec = curfile.dip->di_atimensec / 1000;
- timep[1].tv_sec = curfile.dip->di_mtime;
- timep[1].tv_usec = curfile.dip->di_mtimensec / 1000;
- uid = curfile.dip->di_uid;
- gid = curfile.dip->di_gid;
- mode = curfile.dip->di_mode;
- flags = curfile.dip->di_flags;
+ timep[0].tv_sec = curfile.atime_sec;
+ timep[0].tv_usec = curfile.atime_nsec / 1000;
+ timep[1].tv_sec = curfile.mtime_sec;
+ timep[1].tv_usec = curfile.mtime_nsec / 1000;
+ mode = curfile.mode;
+ flags = curfile.file_flags;
switch (mode & IFMT) {
default:
@@ -578,7 +565,7 @@ extractfile(char *name)
return (GOOD);
}
if (linkit(lnkbuf, name, SYMLINK) == GOOD) {
- (void) lchown(name, uid, gid);
+ (void) lchown(name, curfile.uid, curfile.gid);
(void) lchmod(name, mode);
(void) lutimes(name, timep);
return (GOOD);
@@ -599,7 +586,7 @@ extractfile(char *name)
skipfile();
return (FAIL);
}
- (void) chown(name, uid, gid);
+ (void) chown(name, curfile.uid, curfile.gid);
(void) chmod(name, mode);
(void) utimes(name, timep);
(void) chflags(name, flags);
@@ -615,13 +602,13 @@ extractfile(char *name)
}
if (uflag)
(void)unlink(name);
- if (mknod(name, mode, (int)curfile.dip->di_rdev) < 0) {
+ if (mknod(name, mode, (int)curfile.rdev) < 0) {
fprintf(stderr, "%s: cannot create special file: %s\n",
name, strerror(errno));
skipfile();
return (FAIL);
}
- (void) chown(name, uid, gid);
+ (void) chown(name, curfile.uid, curfile.gid);
(void) chmod(name, mode);
(void) utimes(name, timep);
(void) chflags(name, flags);
@@ -643,7 +630,7 @@ extractfile(char *name)
skipfile();
return (FAIL);
}
- (void) fchown(ofile, uid, gid);
+ (void) fchown(ofile, curfile.uid, curfile.gid);
(void) fchmod(ofile, mode);
getfile(xtrfile, xtrskip);
(void) close(ofile);
@@ -687,14 +674,14 @@ getfile(void (*fill)(char *, long), void (*skip)(char *, long))
{
int i;
int curblk = 0;
- quad_t size = spcl.c_dinode.di_size;
+ quad_t size = spcl.c_size;
static char clearedbuf[MAXBSIZE];
char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE];
char junk[TP_BSIZE];
if (spcl.c_type == TS_END)
panic("ran off end of tape\n");
- if (spcl.c_magic != NFS_MAGIC)
+ if (spcl.c_magic != FS_UFS2_MAGIC)
panic("not at beginning of a file\n");
if (!gettingfile && setjmp(restart) != 0)
return;
@@ -1000,106 +987,43 @@ closemt(void)
/*
* Read the next block from the tape.
- * Check to see if it is one of several vintage headers.
- * If it is an old style header, convert it to a new style header.
* If it is not any valid header, return an error.
*/
static int
gethead(struct s_spcl *buf)
{
long i;
- union {
- quad_t qval;
- int32_t val[2];
- } qcvt;
- union u_ospcl {
- char dummy[TP_BSIZE];
- struct s_ospcl {
- int32_t c_type;
- int32_t c_date;
- int32_t c_ddate;
- int32_t c_volume;
- int32_t c_tapea;
- u_short c_inumber;
- int32_t c_magic;
- int32_t c_checksum;
- struct odinode {
- unsigned short odi_mode;
- u_short odi_nlink;
- u_short odi_uid;
- u_short odi_gid;
- int32_t odi_size;
- int32_t odi_rdev;
- char odi_addr[36];
- int32_t odi_atime;
- int32_t odi_mtime;
- int32_t odi_ctime;
- } c_dinode;
- int32_t c_count;
- char c_addr[256];
- } s_ospcl;
- } u_ospcl;
-
- if (!cvtflag) {
- readtape((char *)buf);
- if (buf->c_magic != NFS_MAGIC) {
- if (swabl(buf->c_magic) != NFS_MAGIC)
- return (FAIL);
- if (!Bcvt) {
- vprintf(stdout, "Note: Doing Byte swapping\n");
- Bcvt = 1;
- }
+
+ readtape((char *)buf);
+ if (buf->c_magic != FS_UFS2_MAGIC && buf->c_magic != NFS_MAGIC) {
+ if (buf->c_magic == OFS_MAGIC) {
+ fprintf(stderr,
+ "Format of dump tape is too old. Must use\n");
+ fprintf(stderr,
+ "a version of restore from before 2002.\n");
+ return (FAIL);
}
- if (checksum((int *)buf) == FAIL)
+ if (swabl(buf->c_magic) != FS_UFS2_MAGIC &&
+ buf->c_magic != NFS_MAGIC) {
+ if (buf->c_magic == OFS_MAGIC) {
+ fprintf(stderr,
+ "Format of dump tape is too old. Must use\n");
+ fprintf(stderr,
+ "a version of restore from before 2002.\n");
+ }
return (FAIL);
- if (Bcvt) {
- swabst((u_char *)"8l4s31l", (u_char *)buf);
- swabst((u_char *)"l",(u_char *) &buf->c_level);
- swabst((u_char *)"2l",(u_char *) &buf->c_flags);
}
- goto good;
- }
- readtape((char *)(&u_ospcl.s_ospcl));
- memset(buf, 0, (long)TP_BSIZE);
- buf->c_type = u_ospcl.s_ospcl.c_type;
- buf->c_date = u_ospcl.s_ospcl.c_date;
- buf->c_ddate = u_ospcl.s_ospcl.c_ddate;
- buf->c_volume = u_ospcl.s_ospcl.c_volume;
- buf->c_tapea = u_ospcl.s_ospcl.c_tapea;
- buf->c_inumber = u_ospcl.s_ospcl.c_inumber;
- buf->c_checksum = u_ospcl.s_ospcl.c_checksum;
- buf->c_magic = u_ospcl.s_ospcl.c_magic;
- buf->c_dinode.di_mode = u_ospcl.s_ospcl.c_dinode.odi_mode;
- buf->c_dinode.di_nlink = u_ospcl.s_ospcl.c_dinode.odi_nlink;
- buf->c_dinode.di_uid = u_ospcl.s_ospcl.c_dinode.odi_uid;
- buf->c_dinode.di_gid = u_ospcl.s_ospcl.c_dinode.odi_gid;
- buf->c_dinode.di_size = u_ospcl.s_ospcl.c_dinode.odi_size;
- buf->c_dinode.di_rdev = u_ospcl.s_ospcl.c_dinode.odi_rdev;
- buf->c_dinode.di_atime = u_ospcl.s_ospcl.c_dinode.odi_atime;
- buf->c_dinode.di_mtime = u_ospcl.s_ospcl.c_dinode.odi_mtime;
- buf->c_dinode.di_ctime = u_ospcl.s_ospcl.c_dinode.odi_ctime;
- buf->c_count = u_ospcl.s_ospcl.c_count;
- memmove(buf->c_addr, u_ospcl.s_ospcl.c_addr, (long)256);
- if (u_ospcl.s_ospcl.c_magic != OFS_MAGIC ||
- checksum((int *)(&u_ospcl.s_ospcl)) == FAIL)
- return(FAIL);
- buf->c_magic = NFS_MAGIC;
-
-good:
- if ((buf->c_dinode.di_size == 0 || buf->c_dinode.di_size > 0xfffffff) &&
- (buf->c_dinode.di_mode & IFMT) == IFDIR && Qcvt == 0) {
- qcvt.qval = buf->c_dinode.di_size;
- if (qcvt.val[0] || qcvt.val[1]) {
- printf("Note: Doing Quad swapping\n");
- Qcvt = 1;
+ if (!Bcvt) {
+ vprintf(stdout, "Note: Doing Byte swapping\n");
+ Bcvt = 1;
}
}
- if (Qcvt) {
- qcvt.qval = buf->c_dinode.di_size;
- i = qcvt.val[1];
- qcvt.val[1] = qcvt.val[0];
- qcvt.val[0] = i;
- buf->c_dinode.di_size = qcvt.qval;
+ if (checksum((int *)buf) == FAIL)
+ return (FAIL);
+ if (Bcvt) {
+ swabst((u_char *)"8l4s1q8l2q17l", (u_char *)buf);
+ swabst((u_char *)"l",(u_char *) &buf->c_level);
+ swabst((u_char *)"2l4q",(u_char *) &buf->c_flags);
}
readmapflag = 0;
@@ -1111,7 +1035,7 @@ good:
* Have to patch up missing information in bit map headers
*/
buf->c_inumber = 0;
- buf->c_dinode.di_size = buf->c_count * TP_BSIZE;
+ buf->c_size = buf->c_count * TP_BSIZE;
if (buf->c_count > TP_NINDIR)
readmapflag = 1;
else
@@ -1120,14 +1044,25 @@ good:
break;
case TS_TAPE:
- if ((buf->c_flags & DR_NEWINODEFMT) == 0)
- oldinofmt = 1;
- /* fall through */
case TS_END:
buf->c_inumber = 0;
break;
case TS_INODE:
+ /*
+ * For old dump tapes, have to copy up old fields to
+ * new locations.
+ */
+ if (buf->c_magic == NFS_MAGIC) {
+ buf->c_tapea = buf->c_old_tapea;
+ buf->c_firstrec = buf->c_old_firstrec;
+ buf->c_date = _time32_to_time(buf->c_old_date);
+ buf->c_ddate = _time32_to_time(buf->c_old_ddate);
+ buf->c_atime = _time32_to_time(buf->c_old_atime);
+ buf->c_mtime = _time32_to_time(buf->c_old_mtime);
+ }
+ break;
+
case TS_ADDR:
break;
@@ -1135,14 +1070,7 @@ good:
panic("gethead: unknown inode type %d\n", buf->c_type);
break;
}
- /*
- * If we are restoring a filesystem with old format inodes,
- * copy the uid/gid to the new location.
- */
- if (oldinofmt) {
- buf->c_dinode.di_uid = buf->c_dinode.di_ouid;
- buf->c_dinode.di_gid = buf->c_dinode.di_ogid;
- }
+ buf->c_magic = FS_UFS2_MAGIC;
tapeaddr = buf->c_tapea;
if (dflag)
accthdr(buf);
@@ -1161,10 +1089,9 @@ accthdr(struct s_spcl *header)
long blks, i;
if (header->c_type == TS_TAPE) {
- fprintf(stderr, "Volume header (%s inode format) ",
- oldinofmt ? "old" : "new");
+ fprintf(stderr, "Volume header ");
if (header->c_firstrec)
- fprintf(stderr, "begins with record %ld",
+ fprintf(stderr, "begins with record %qd",
header->c_firstrec);
fprintf(stderr, "\n");
previno = 0x7fffffff;
@@ -1219,15 +1146,9 @@ findinode(struct s_spcl *header)
curfile.name = "<name unknown>";
curfile.action = UNKNOWN;
- curfile.dip = NULL;
+ curfile.mode = 0;
curfile.ino = 0;
do {
- if (header->c_magic != NFS_MAGIC) {
- skipcnt++;
- while (gethead(header) == FAIL ||
- _time32_to_time(header->c_date) != dumpdate)
- skipcnt++;
- }
htype = header->c_type;
switch (htype) {
@@ -1239,12 +1160,21 @@ findinode(struct s_spcl *header)
if (header->c_addr[i])
readtape(buf);
while (gethead(header) == FAIL ||
- _time32_to_time(header->c_date) != dumpdate)
+ _time64_to_time(header->c_date) != dumpdate)
skipcnt++;
break;
case TS_INODE:
- curfile.dip = &header->c_dinode;
+ curfile.mode = header->c_mode;
+ curfile.uid = header->c_uid;
+ curfile.gid = header->c_gid;
+ curfile.file_flags = header->c_file_flags;
+ curfile.rdev = header->c_rdev;
+ curfile.atime_sec = header->c_atime;
+ curfile.atime_nsec = header->c_atimensec;
+ curfile.mtime_sec = header->c_mtime;
+ curfile.mtime_nsec = header->c_mtimensec;
+ curfile.size = header->c_size;
curfile.ino = header->c_inumber;
break;
@@ -1288,7 +1218,7 @@ checksum(int *buf)
j = sizeof(union u_spcl) / sizeof(int);
i = 0;
- if(!Bcvt) {
+ if (!Bcvt) {
do
i += *buf++;
while (--j);
@@ -1346,6 +1276,21 @@ swablong(u_char *sp, int n)
return (sp);
}
+static u_char *
+swabquad(u_char *sp, int n)
+{
+ char c;
+
+ while (--n >= 0) {
+ c = sp[0]; sp[0] = sp[7]; sp[7] = c;
+ c = sp[1]; sp[1] = sp[6]; sp[6] = c;
+ c = sp[2]; sp[2] = sp[5]; sp[5] = c;
+ c = sp[3]; sp[3] = sp[4]; sp[4] = c;
+ sp += 8;
+ }
+ return (sp);
+}
+
void
swabst(u_char *cp, u_char *sp)
{
@@ -1370,11 +1315,23 @@ swabst(u_char *cp, u_char *sp)
sp = swablong(sp, n);
break;
- default: /* Any other character, like 'b' counts as byte. */
+ case 'q':
+ if (n == 0)
+ n = 1;
+ sp = swabquad(sp, n);
+ break;
+
+ case 'b':
if (n == 0)
n = 1;
sp += n;
break;
+
+ default:
+ fprintf(stderr, "Unknown conversion character: %c\n",
+ *cp);
+ done(0);
+ break;
}
cp++;
n = 0;
diff --git a/sbin/tunefs/tunefs.8 b/sbin/tunefs/tunefs.8
index 3480397cb112..424e2098e749 100644
--- a/sbin/tunefs/tunefs.8
+++ b/sbin/tunefs/tunefs.8
@@ -32,7 +32,7 @@
.\" @(#)tunefs.8 8.2 (Berkeley) 12/11/93
.\" $FreeBSD$
.\"
-.Dd December 11, 1993
+.Dd May 18, 2002
.Dt TUNEFS 8
.Os
.Sh NAME
@@ -42,7 +42,6 @@
.Nm
.Op Fl A
.Op Fl a Ar maxcontig
-.Op Fl d Ar rotdelay
.Op Fl e Ar maxbpg
.Op Fl f Ar avgfilesize
.Op Fl m Ar minfree
@@ -57,6 +56,13 @@
.Nm Tunefs
is designed to change the dynamic parameters of a filesystem
which affect the layout policies.
+The
+.Nm
+program cannot be run on an active filesystem.
+To change an active filesystem,
+you must either downgrade the filesystem to read-only
+or unmount it.
+.Pp
The parameters which are to be changed are indicated by the flags
given below:
.Bl -tag -width indent
@@ -66,19 +72,8 @@ this option will cause all backups to be modified as well as the
primary super-block. This is potentially dangerous - use with caution.
.It Fl a Ar maxcontig
Specify the maximum number of contiguous blocks that will
-be laid out before forcing a rotational delay (see
-.Fl d
-below).
-The default value is one, since most device drivers require
-an interrupt per disk transfer.
-Device drivers that can chain several buffers together in a single
-transfer should set this to the maximum chain length.
-.It Fl d Ar rotdelay
-Specify the expected time (in milliseconds)
-to service a transfer completion
-interrupt and initiate a new transfer on the same disk.
-It is used to decide how much rotational spacing to place between
-successive blocks in a file.
+be laid out before allowing a rotational delay.
+The default value is 16.
.It Fl e Ar maxbpg
Indicate the maximum number of blocks any single file can
allocate out of a cylinder group before it is forced to begin
@@ -131,9 +126,11 @@ the percent fragmentation changes on the filesystem.
.It Fl p
Show a summary of what the current tunable settings
are on the selected filesystem. More detailed information can be
-obtained in the
+obtained from the
.Xr dumpfs 8
-manual page.
+or
+.Xr ffsinfo 8
+programs.
.It Fl s Ar avgfpdir
Specify the expected number of files per directory.
.El
@@ -148,6 +145,7 @@ specified mount point.
.Sh SEE ALSO
.Xr fs 5 ,
.Xr dumpfs 8 ,
+.Xr ffsinfo 8 ,
.Xr newfs 8
.Rs
.%A M. McKusick
@@ -162,13 +160,8 @@ specified mount point.
.%O "(reprinted in the BSD System Manager's Manual, SMM:5)"
.Re
.Sh BUGS
-This program should work on mounted and active filesystems.
-Because the super-block is not kept in the buffer cache,
-the changes will only take effect if the program
-is run on dismounted filesystems.
-To change the root filesystem, the system must be rebooted
-after the filesystem is tuned.
-.\" Take this out and a Unix Demon will dog your steps from now until
+This program should work on active filesystems.
+.\" Take this out and a Unix Daemon will dog your steps from now until
.\" the time_t's wrap around.
.Pp
You can tune a filesystem, but you can't tune a fish.
diff --git a/sbin/tunefs/tunefs.c b/sbin/tunefs/tunefs.c
index b40c8cbccf5b..e272446633a6 100644
--- a/sbin/tunefs/tunefs.c
+++ b/sbin/tunefs/tunefs.c
@@ -53,8 +53,9 @@ static const char rcsid[] =
#include <sys/disklabel.h>
#include <sys/stat.h>
-#include <ufs/ffs/fs.h>
#include <ufs/ufs/ufsmount.h>
+#include <ufs/ufs/dinode.h>
+#include <ufs/ffs/fs.h>
#include <err.h>
#include <fcntl.h>
@@ -77,8 +78,8 @@ union {
int fi;
long dev_bsize = 1;
-void bwrite(daddr_t, const char *, int);
-int bread(daddr_t, char *, int);
+void bwrite(ufs2_daddr_t, const char *, int);
+int bread(ufs2_daddr_t, char *, int);
void getsb(struct fs *, const char *);
void putsb(struct fs *, const char *, int);
void usage(void);
@@ -93,9 +94,9 @@ main(argc, argv)
const char *name;
struct stat st;
int Aflag = 0, active = 0;
- int aflag = 0, dflag = 0, eflag = 0, fflag = 0, mflag = 0;
+ int aflag = 0, eflag = 0, fflag = 0, mflag = 0;
int nflag = 0, oflag = 0, pflag = 0, sflag = 0;
- int avalue = 0, dvalue = 0, evalue = 0, fvalue = 0;
+ int avalue = 0, evalue = 0, fvalue = 0;
int mvalue = 0, ovalue = 0, svalue = 0;
char *nvalue = NULL;
struct fstab *fs;
@@ -108,7 +109,7 @@ main(argc, argv)
if (argc < 3)
usage();
found_arg = 0; /* at least one arg is required */
- while ((ch = getopt(argc, argv, "Aa:d:e:f:m:n:o:ps:")) != -1)
+ while ((ch = getopt(argc, argv, "Aa:e:f:m:n:o:ps:")) != -1)
switch (ch) {
case 'A':
found_arg = 1;
@@ -122,12 +123,6 @@ main(argc, argv)
errx(10, "%s must be >= 1 (was %s)", name, optarg);
aflag = 1;
break;
- case 'd':
- found_arg = 1;
- name = "rotational delay between contiguous blocks";
- dvalue = atoi(optarg);
- dflag = 1;
- break;
case 'e':
found_arg = 1;
name = "maximum blocks per file in a cylinder group";
@@ -237,17 +232,6 @@ again:
sblock.fs_maxcontig = avalue;
}
}
- if (dflag) {
- name = "rotational delay between contiguous blocks";
- if (sblock.fs_rotdelay == dvalue) {
- warnx("%s remains unchanged as %dms", name, dvalue);
- }
- else {
- warnx("%s changes from %dms to %dms",
- name, sblock.fs_rotdelay, dvalue);
- sblock.fs_rotdelay = dvalue;
- }
- }
if (eflag) {
name = "maximum blocks per file in a cylinder group";
if (sblock.fs_maxbpg == evalue) {
@@ -358,20 +342,36 @@ usage()
exit(2);
}
+/*
+ * Possible superblock locations ordered from most to least likely.
+ */
+static int sblock_try[] = SBLOCKSEARCH;
+static ufs2_daddr_t sblockloc;
+
void
getsb(fs, file)
struct fs *fs;
const char *file;
{
+ int i;
fi = open(file, O_RDONLY);
if (fi < 0)
err(3, "cannot open %s", file);
- if (bread((daddr_t)SBOFF, (char *)fs, SBSIZE))
- err(4, "%s: bad super block", file);
- if (fs->fs_magic != FS_MAGIC)
- errx(5, "%s: bad magic number", file);
+ for (i = 0; sblock_try[i] != -1; i++) {
+ if (bread(sblock_try[i], (char *)fs, SBLOCKSIZE))
+ err(4, "%s: bad super block", file);
+ if ((fs->fs_magic == FS_UFS1_MAGIC ||
+ (fs->fs_magic == FS_UFS2_MAGIC &&
+ fs->fs_sblockloc == numfrags(fs, sblock_try[i]))) &&
+ fs->fs_bsize <= MAXBSIZE &&
+ fs->fs_bsize >= sizeof(struct fs))
+ break;
+ }
+ if (sblock_try[i] == -1)
+ err(5, "Cannot find filesystem superblock");
dev_bsize = fs->fs_fsize / fsbtodb(fs, 1);
+ sblockloc = sblock_try[i] / dev_bsize;
}
void
@@ -392,11 +392,11 @@ putsb(fs, file, all)
close(i);
if (fi < 0)
err(3, "cannot open %s", file);
- bwrite((daddr_t)SBOFF / dev_bsize, (const char *)fs, SBSIZE);
+ bwrite(sblockloc, (const char *)fs, SBLOCKSIZE);
if (all)
for (i = 0; i < fs->fs_ncg; i++)
bwrite(fsbtodb(fs, cgsblock(fs, i)),
- (const char *)fs, SBSIZE);
+ (const char *)fs, SBLOCKSIZE);
close(fi);
}
@@ -407,8 +407,6 @@ printfs()
(sblock.fs_flags & FS_DOSOFTDEP)? "enabled" : "disabled");
warnx("maximum contiguous block count: (-a) %d",
sblock.fs_maxcontig);
- warnx("rotational delay between contiguous blocks: (-d) %d ms",
- sblock.fs_rotdelay);
warnx("maximum blocks per file in a cylinder group: (-e) %d",
sblock.fs_maxbpg);
warnx("average file size: (-f) %d",
@@ -429,7 +427,7 @@ printfs()
void
bwrite(blk, buf, size)
- daddr_t blk;
+ ufs2_daddr_t blk;
const char *buf;
int size;
{
@@ -442,7 +440,7 @@ bwrite(blk, buf, size)
int
bread(bno, buf, cnt)
- daddr_t bno;
+ ufs2_daddr_t bno;
char *buf;
int cnt;
{
diff --git a/sys/amd64/Makefile b/sys/amd64/Makefile
index 14ba0b34ba44..b7d021a7d3d1 100644
--- a/sys/amd64/Makefile
+++ b/sys/amd64/Makefile
@@ -5,6 +5,7 @@
# SYS is normally set in Make.tags.inc
# SYS=/sys
+SYS=/nsys
TAGDIR= i386
diff --git a/sys/boot/common/ufsread.c b/sys/boot/common/ufsread.c
index 053dbe001495..b0a1547c301c 100644
--- a/sys/boot/common/ufsread.c
+++ b/sys/boot/common/ufsread.c
@@ -1,4 +1,13 @@
/*
+ * Copyright (c) 2002 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by Marshall
+ * Kirk McKusick and Network Associates Laboratories, the Security
+ * Research Division of Network Associates, Inc. under DARPA/SPAWAR
+ * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
+ * research program
+ *
* Copyright (c) 1998 Robert Nordier
* All rights reserved.
*
@@ -17,31 +26,33 @@
* $FreeBSD$
*/
-#include <ufs/ffs/fs.h>
#include <ufs/ufs/dinode.h>
+#include <ufs/ffs/fs.h>
/*
* We use 4k `virtual' blocks for filesystem data, whatever the actual
* filesystem block size. FFS blocks are always a multiple of 4k.
*/
#define VBLKSIZE 4096
+#define VBLKSHIFT 12
#define VBLKMASK (VBLKSIZE - 1)
#define DBPERVBLK (VBLKSIZE / DEV_BSIZE)
-#define IPERVBLK (VBLKSIZE / sizeof(struct dinode))
-#define INDIRPERVBLK (VBLKSIZE / sizeof(ufs_daddr_t))
-#define INO_TO_VBA(fs, x) (fsbtodb(fs, ino_to_fsba(fs, x)) + \
- (ino_to_fsbo(fs, x) / IPERVBLK) * DBPERVBLK)
-#define INO_TO_VBO(fs, x) (ino_to_fsbo(fs, x) % IPERVBLK)
+#define INDIRPERVBLK(fs) (NINDIR(fs) / ((fs)->fs_bsize / VBLKSIZE))
+#define IPERVBLK(fs) (INOPB(fs) / ((fs)->fs_bsize / VBLKSIZE))
+#define INO_TO_VBA(fs, ipervblk, x) \
+ (fsbtodb(fs, cgimin(fs, ino_to_cg(fs, x))) + \
+ (((x) % (fs)->fs_ipg) / (ipervblk) * DBPERVBLK))
+#define INO_TO_VBO(ipervblk, x) ((x) % ipervblk)
#define FS_TO_VBA(fs, fsb, off) (fsbtodb(fs, fsb) + \
((off) / VBLKSIZE) * DBPERVBLK)
#define FS_TO_VBO(fs, fsb, off) ((off) & VBLKMASK)
/* Buffers that must not span a 64k boundary. */
struct dmadat {
- char blkbuf[VBLKSIZE]; /* filesystem blocks */
- ufs_daddr_t indbuf[VBLKSIZE / sizeof(ufs_daddr_t)]; /* indir blocks */
- char sbbuf[SBSIZE]; /* superblock */
- char secbuf[DEV_BSIZE]; /* for MBR/disklabel */
+ char blkbuf[VBLKSIZE]; /* filesystem blocks */
+ char indbuf[VBLKSIZE]; /* indir blocks */
+ char sbbuf[SBLOCKSIZE]; /* superblock */
+ char secbuf[DEV_BSIZE]; /* for MBR/disklabel */
};
static struct dmadat *dmadat;
@@ -61,16 +72,16 @@ fsfind(const char *name, ino_t * ino)
fs_off = 0;
while ((n = fsread(*ino, buf, DEV_BSIZE)) > 0)
- for (s = buf; s < buf + DEV_BSIZE;) {
- d = (void *)s;
- if (ls)
- printf("%s ", d->d_name);
- else if (!strcmp(name, d->d_name)) {
- *ino = d->d_fileno;
- return d->d_type;
+ for (s = buf; s < buf + DEV_BSIZE;) {
+ d = (void *)s;
+ if (ls)
+ printf("%s ", d->d_name);
+ else if (!strcmp(name, d->d_name)) {
+ *ino = d->d_fileno;
+ return d->d_type;
+ }
+ s += d->d_reclen;
}
- s += d->d_reclen;
- }
if (n != -1 && ls)
printf("\n");
return 0;
@@ -95,8 +106,8 @@ lookup(const char *path)
if (!*path)
break;
for (s = path; *s && *s != '/'; s++);
- if ((n = s - path) > MAXNAMLEN)
- return 0;
+ if ((n = s - path) > MAXNAMLEN)
+ return 0;
ls = *path == '?' && n == 1 && !*s;
memcpy(name, path, n);
name[n] = 0;
@@ -111,28 +122,31 @@ lookup(const char *path)
return dt == DT_REG ? ino : 0;
}
+#define UFS1_ONLY
+#ifdef UFS1_ONLY
+
static ssize_t
fsread(ino_t inode, void *buf, size_t nbyte)
{
- static struct dinode din;
+ static struct ufs1_dinode dp1;
static ino_t inomap;
- static daddr_t blkmap, indmap;
char *blkbuf;
- ufs_daddr_t *indbuf;
+ caddr_t indbuf;
struct fs *fs;
char *s;
- ufs_daddr_t lbn, addr;
- daddr_t vbaddr;
- size_t n, nb, off, vboff;
+ size_t n, nb, size, off, vboff;
+ long lbn;
+ ufs1_daddr_t addr, vbaddr;
+ static ufs1_daddr_t blkmap, indmap;
blkbuf = dmadat->blkbuf;
indbuf = dmadat->indbuf;
fs = (struct fs *)dmadat->sbbuf;
if (!dsk_meta) {
inomap = 0;
- if (dskread(fs, SBOFF / DEV_BSIZE, SBSIZE / DEV_BSIZE))
+ if (dskread(fs, SBLOCK_UFS1 / DEV_BSIZE, SBLOCKSIZE / DEV_BSIZE))
return -1;
- if (fs->fs_magic != FS_MAGIC) {
+ if (fs->fs_magic != FS_UFS1_MAGIC) {
printf("Not ufs\n");
return -1;
}
@@ -141,35 +155,40 @@ fsread(ino_t inode, void *buf, size_t nbyte)
if (!inode)
return 0;
if (inomap != inode) {
- if (dskread(blkbuf, INO_TO_VBA(fs, inode), DBPERVBLK))
+ n = IPERVBLK(fs);
+ if (dskread(blkbuf, INO_TO_VBA(fs, n, inode), DBPERVBLK))
return -1;
- din = ((struct dinode *)blkbuf)[INO_TO_VBO(fs, inode)];
+ dp1 = ((struct ufs1_dinode *)blkbuf)[INO_TO_VBO(n, inode)];
inomap = inode;
fs_off = 0;
blkmap = indmap = 0;
}
s = buf;
- if (nbyte > (n = din.di_size - fs_off))
+ size = dp1.di_size;
+ n = size - fs_off;
+ if (nbyte > n)
nbyte = n;
nb = nbyte;
while (nb) {
lbn = lblkno(fs, fs_off);
off = blkoff(fs, fs_off);
- if (lbn < NDADDR)
- addr = din.di_db[lbn];
- else {
- vbaddr = FS_TO_VBA(fs, din.di_ib[0], sizeof(indbuf[0]) *
- ((lbn - NDADDR) % NINDIR(fs)));
+ if (lbn < NDADDR) {
+ addr = dp1.di_db[lbn];
+ } else {
+ n = INDIRPERVBLK(fs);
+ addr = dp1.di_ib[0];
+ vbaddr = fsbtodb(fs, addr) +
+ (lbn - NDADDR) / n * DBPERVBLK;
if (indmap != vbaddr) {
if (dskread(indbuf, vbaddr, DBPERVBLK))
return -1;
indmap = vbaddr;
}
- addr = indbuf[(lbn - NDADDR) % INDIRPERVBLK];
+ addr = ((ufs1_daddr_t *)indbuf)[(lbn - NDADDR) % n];
}
- vbaddr = FS_TO_VBA(fs, addr, off);
- vboff = FS_TO_VBO(fs, addr, off);
- n = dblksize(fs, &din, lbn) - (off & ~VBLKMASK);
+ vbaddr = fsbtodb(fs, addr) + (off >> VBLKSHIFT) * DBPERVBLK;
+ vboff = off & VBLKMASK;
+ n = sblksize(fs, size, lbn) - (off & ~VBLKMASK);
if (n > VBLKSIZE)
n = VBLKSIZE;
if (blkmap != vbaddr) {
@@ -187,3 +206,117 @@ fsread(ino_t inode, void *buf, size_t nbyte)
}
return nbyte;
}
+
+#else /* UFS1_AND_UFS2 */
+
+/*
+ * Possible superblock locations ordered from most to least likely.
+ */
+static int sblock_try[] = SBLOCKSEARCH;
+
+#define DIP(field) fs->fs_magic == FS_UFS1_MAGIC ? dp1.field : dp2.field
+
+static ssize_t
+fsread(ino_t inode, void *buf, size_t nbyte)
+{
+ static struct ufs1_dinode dp1;
+ static struct ufs2_dinode dp2;
+ static ino_t inomap;
+ char *blkbuf;
+ caddr_t indbuf;
+ struct fs *fs;
+ char *s;
+ size_t n, nb, size, off, vboff;
+ ufs_lbn_t lbn;
+ ufs2_daddr_t addr, vbaddr;
+ static ufs2_daddr_t blkmap, indmap;
+
+ blkbuf = dmadat->blkbuf;
+ indbuf = dmadat->indbuf;
+ fs = (struct fs *)dmadat->sbbuf;
+ if (!dsk_meta) {
+ inomap = 0;
+ for (n = 0; sblock_try[n] != -1; n++) {
+ if (dskread(fs, sblock_try[n] / DEV_BSIZE,
+ SBLOCKSIZE / DEV_BSIZE))
+ return -1;
+ if ((fs->fs_magic == FS_UFS1_MAGIC ||
+ (fs->fs_magic == FS_UFS2_MAGIC &&
+ fs->fs_sblockloc == numfrags(fs, sblock_try[n]))) &&
+ fs->fs_bsize <= MAXBSIZE &&
+ fs->fs_bsize >= sizeof(struct fs))
+ break;
+ }
+ if (sblock_try[n] == -1) {
+ printf("Not ufs\n");
+ return -1;
+ }
+ dsk_meta++;
+ }
+ if (!inode)
+ return 0;
+ if (inomap != inode) {
+ n = IPERVBLK(fs);
+ if (dskread(blkbuf, INO_TO_VBA(fs, n, inode), DBPERVBLK))
+ return -1;
+ n = INO_TO_VBO(n, inode);
+ if (fs->fs_magic == FS_UFS1_MAGIC)
+ dp1 = ((struct ufs1_dinode *)blkbuf)[n];
+ else
+ dp2 = ((struct ufs2_dinode *)blkbuf)[n];
+ inomap = inode;
+ fs_off = 0;
+ blkmap = indmap = 0;
+ }
+ s = buf;
+ size = DIP(di_size);
+ n = size - fs_off;
+ if (nbyte > n)
+ nbyte = n;
+ nb = nbyte;
+ while (nb) {
+ lbn = lblkno(fs, fs_off);
+ off = blkoff(fs, fs_off);
+ if (lbn < NDADDR) {
+ addr = DIP(di_db[lbn]);
+ } else if (lbn < NDADDR + NINDIR(fs)) {
+ n = INDIRPERVBLK(fs);
+ addr = DIP(di_ib[0]);
+ vbaddr = fsbtodb(fs, addr) +
+ (lbn - NDADDR) / n * DBPERVBLK;
+ if (indmap != vbaddr) {
+ if (dskread(indbuf, vbaddr, DBPERVBLK))
+ return -1;
+ indmap = vbaddr;
+ }
+ n = (lbn - NDADDR) % n;
+ if (fs->fs_magic == FS_UFS1_MAGIC)
+ addr = ((ufs1_daddr_t *)indbuf)[n];
+ else
+ addr = ((ufs2_daddr_t *)indbuf)[n];
+ } else {
+ printf("file too big\n");
+ return -1;
+ }
+ vbaddr = fsbtodb(fs, addr) + (off >> VBLKSHIFT) * DBPERVBLK;
+ vboff = off & VBLKMASK;
+ n = sblksize(fs, size, lbn) - (off & ~VBLKMASK);
+ if (n > VBLKSIZE)
+ n = VBLKSIZE;
+ if (blkmap != vbaddr) {
+ if (dskread(blkbuf, vbaddr, n >> DEV_BSHIFT))
+ return -1;
+ blkmap = vbaddr;
+ }
+ n -= vboff;
+ if (n > nb)
+ n = nb;
+ memcpy(s, blkbuf + vboff, n);
+ s += n;
+ fs_off += n;
+ nb -= n;
+ }
+ return nbyte;
+}
+
+#endif /* UFS1_AND_UFS2 */
diff --git a/sys/boot/i386/Makefile b/sys/boot/i386/Makefile
index 4fd94475f11f..3fbdc45e63c0 100644
--- a/sys/boot/i386/Makefile
+++ b/sys/boot/i386/Makefile
@@ -1,6 +1,6 @@
# $FreeBSD$
-SUBDIR= mbr boot0 btx boot2 cdboot kgzldr libi386 loader
+SUBDIR= libi386 mbr boot0 btx boot2 cdboot kgzldr loader
# special boot programs, 'self-extracting boot2+loader'
SUBDIR+= pxeldr
diff --git a/sys/boot/i386/boot2/Makefile b/sys/boot/i386/boot2/Makefile
index 2883b9315788..75e4fe3fcf3e 100644
--- a/sys/boot/i386/boot2/Makefile
+++ b/sys/boot/i386/boot2/Makefile
@@ -75,7 +75,7 @@ boot2.bin: boot2.out
boot2.out: boot2.o sio.o
${LD} ${LDFLAGS} -Ttext ${ORG2} -o ${.TARGET} \
- ${BTX}/lib/crt0.o boot2.o sio.o
+ ${BTX}/lib/crt0.o boot2.o sio.o ../libi386/libi386.a
boot2.o: boot2.h
diff --git a/sys/boot/i386/boot2/boot2.c b/sys/boot/i386/boot2/boot2.c
index fa82999e3063..e506c290c76e 100644
--- a/sys/boot/i386/boot2/boot2.c
+++ b/sys/boot/i386/boot2/boot2.c
@@ -73,9 +73,10 @@
#define TYPE_AD 0
#define TYPE_WD 1
-#define TYPE_WFD 2
-#define TYPE_FD 3
-#define TYPE_DA 4
+#define TYPE_DA 2
+#define TYPE_MAXHARD TYPE_DA
+#define TYPE_WFD 3
+#define TYPE_FD 4
extern uint32_t _end;
@@ -97,8 +98,8 @@ static const unsigned char flags[NOPT] = {
RBX_VERBOSE
};
-static const char *const dev_nm[] = {"ad", "wd", " ", "fd", "da"};
-static const unsigned dev_maj[] = {30, 0, 1, 2, 4};
+static const char *const dev_nm[NDEV] = {"ad", "wd", "da", " ", "fd"};
+static const unsigned char dev_maj[NDEV] = {30, 0, 4, 1, 2};
static struct dsk {
unsigned drive;
@@ -111,16 +112,14 @@ static struct dsk {
} dsk;
static char cmd[512];
static char kname[1024];
-static uint32_t opts;
+static uint32_t opts = RB_BOOTINFO;
static struct bootinfo bootinfo;
static uint8_t ioctrl = IO_KEYBOARD;
void exit(int);
static void load(const char *);
static int parse(char *);
-static ino_t lookup(const char *);
static int xfsread(ino_t, void *, size_t);
-static ssize_t fsread(ino_t, void *, size_t);
static int dskread(void *, unsigned, unsigned);
static int printf(const char *,...);
static int putchar(int);
@@ -131,16 +130,17 @@ static int xputc(int);
static int xgetc(int);
static int getc(int);
+#if 1
#define memcpy __builtin_memcpy
-
-static inline void
-readfile(const char *fname, void *buf, size_t size)
+#else
+static void memcpy(char *, const char *, int);
+static void
+memcpy(char *dst, const char *src, int len)
{
- ino_t ino;
-
- if ((ino = lookup(fname)))
- fsread(ino, buf, size);
+ while (len--)
+ *dst++ = *src++;
}
+#endif
static inline int
strcmp(const char *s1, const char *s2)
@@ -151,15 +151,14 @@ strcmp(const char *s1, const char *s2)
#include "ufsread.c"
-static inline int
-getchar(void)
+static int
+xfsread(ino_t inode, void *buf, size_t nbyte)
{
- int c;
-
- c = xgetc(0);
- if (c == '\r')
- c = '\n';
- return c;
+ if (fsread(inode, buf, nbyte) != nbyte) {
+ printf("Invalid %s\n", "format");
+ return -1;
+ }
+ return 0;
}
static inline void
@@ -169,12 +168,13 @@ getstr(char *str, int size)
int c;
s = str;
- do {
- switch (c = getchar()) {
+ for (;;) {
+ switch (c = xgetc(0)) {
case 0:
break;
- case '\b':
case '\177':
+ c = '\b';
+ case '\b':
if (s > str) {
s--;
putchar('\b');
@@ -183,15 +183,16 @@ getstr(char *str, int size)
c = 0;
break;
case '\n':
+ case '\r':
*s = 0;
- break;
+ return;
default:
if (s - str < size - 1)
*s++ = c;
}
if (c)
putchar(c);
- } while (c != '\n');
+ }
}
static inline uint32_t
@@ -220,6 +221,7 @@ int
main(void)
{
int autoboot, i;
+ ino_t ino;
dmadat = (void *)(roundup2(__base + _end, 0x10000) - __base);
v86.ctl = V86_FLAGS;
@@ -238,7 +240,10 @@ main(void)
/* Process configuration file */
autoboot = 1;
- readfile(PATH_CONFIG, cmd, sizeof(cmd));
+
+ if ((ino = lookup(PATH_CONFIG)))
+ fsread(ino, cmd, sizeof(cmd));
+
if (*cmd) {
printf("%s: %s", PATH_CONFIG, cmd);
if (parse(cmd))
@@ -328,7 +333,7 @@ load(const char *fname)
return;
p += hdr.ex.a_data + roundup2(hdr.ex.a_bss, PAGE_SIZE);
bootinfo.bi_symtab = VTOP(p);
- memcpy(p, &hdr.ex.a_syms, sizeof(hdr.ex.a_syms));
+ memcpy(p, (char *)&hdr.ex.a_syms, sizeof(hdr.ex.a_syms));
p += sizeof(hdr.ex.a_syms);
if (hdr.ex.a_syms) {
if (xfsread(ino, p, hdr.ex.a_syms))
@@ -365,7 +370,7 @@ load(const char *fname)
if (xfsread(ino, &es, sizeof(es)))
return;
for (i = 0; i < 2; i++) {
- memcpy(p, &es[i].sh_size, sizeof(es[i].sh_size));
+ memcpy(p, (char *)&es[i].sh_size, sizeof(es[i].sh_size));
p += sizeof(es[i].sh_size);
fs_off = es[i].sh_offset;
if (xfsread(ino, p, es[i].sh_size))
@@ -378,7 +383,7 @@ load(const char *fname)
bootinfo.bi_esymtab = VTOP(p);
bootinfo.bi_kernelname = VTOP(fname);
bootinfo.bi_bios_dev = dsk.drive;
- __exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK),
+ __exec((caddr_t)addr, opts & RBX_MASK,
MAKEBOOTDEV(dev_maj[dsk.type], 0, dsk.slice, dsk.unit, dsk.part),
0, 0, 0, VTOP(&bootinfo));
}
@@ -449,9 +454,8 @@ parse(char *arg)
arg += 2;
if (drv == -1)
drv = dsk.unit;
- dsk.drive = (dsk.type == TYPE_WD ||
- dsk.type == TYPE_AD ||
- dsk.type == TYPE_DA ? DRV_HARD : 0) + drv;
+ dsk.drive = (dsk.type <= TYPE_MAXHARD
+ ? DRV_HARD : 0) + drv;
dsk_meta = 0;
fsread(0, NULL, 0);
}
@@ -467,16 +471,6 @@ parse(char *arg)
}
static int
-xfsread(ino_t inode, void *buf, size_t nbyte)
-{
- if (fsread(inode, buf, nbyte) != nbyte) {
- printf("Invalid %s\n", "format");
- return -1;
- }
- return 0;
-}
-
-static int
dskread(void *buf, unsigned lba, unsigned nblk)
{
struct dos_partition *dp;
diff --git a/sys/boot/i386/gptboot/Makefile b/sys/boot/i386/gptboot/Makefile
index 2883b9315788..75e4fe3fcf3e 100644
--- a/sys/boot/i386/gptboot/Makefile
+++ b/sys/boot/i386/gptboot/Makefile
@@ -75,7 +75,7 @@ boot2.bin: boot2.out
boot2.out: boot2.o sio.o
${LD} ${LDFLAGS} -Ttext ${ORG2} -o ${.TARGET} \
- ${BTX}/lib/crt0.o boot2.o sio.o
+ ${BTX}/lib/crt0.o boot2.o sio.o ../libi386/libi386.a
boot2.o: boot2.h
diff --git a/sys/boot/i386/gptboot/gptboot.c b/sys/boot/i386/gptboot/gptboot.c
index fa82999e3063..e506c290c76e 100644
--- a/sys/boot/i386/gptboot/gptboot.c
+++ b/sys/boot/i386/gptboot/gptboot.c
@@ -73,9 +73,10 @@
#define TYPE_AD 0
#define TYPE_WD 1
-#define TYPE_WFD 2
-#define TYPE_FD 3
-#define TYPE_DA 4
+#define TYPE_DA 2
+#define TYPE_MAXHARD TYPE_DA
+#define TYPE_WFD 3
+#define TYPE_FD 4
extern uint32_t _end;
@@ -97,8 +98,8 @@ static const unsigned char flags[NOPT] = {
RBX_VERBOSE
};
-static const char *const dev_nm[] = {"ad", "wd", " ", "fd", "da"};
-static const unsigned dev_maj[] = {30, 0, 1, 2, 4};
+static const char *const dev_nm[NDEV] = {"ad", "wd", "da", " ", "fd"};
+static const unsigned char dev_maj[NDEV] = {30, 0, 4, 1, 2};
static struct dsk {
unsigned drive;
@@ -111,16 +112,14 @@ static struct dsk {
} dsk;
static char cmd[512];
static char kname[1024];
-static uint32_t opts;
+static uint32_t opts = RB_BOOTINFO;
static struct bootinfo bootinfo;
static uint8_t ioctrl = IO_KEYBOARD;
void exit(int);
static void load(const char *);
static int parse(char *);
-static ino_t lookup(const char *);
static int xfsread(ino_t, void *, size_t);
-static ssize_t fsread(ino_t, void *, size_t);
static int dskread(void *, unsigned, unsigned);
static int printf(const char *,...);
static int putchar(int);
@@ -131,16 +130,17 @@ static int xputc(int);
static int xgetc(int);
static int getc(int);
+#if 1
#define memcpy __builtin_memcpy
-
-static inline void
-readfile(const char *fname, void *buf, size_t size)
+#else
+static void memcpy(char *, const char *, int);
+static void
+memcpy(char *dst, const char *src, int len)
{
- ino_t ino;
-
- if ((ino = lookup(fname)))
- fsread(ino, buf, size);
+ while (len--)
+ *dst++ = *src++;
}
+#endif
static inline int
strcmp(const char *s1, const char *s2)
@@ -151,15 +151,14 @@ strcmp(const char *s1, const char *s2)
#include "ufsread.c"
-static inline int
-getchar(void)
+static int
+xfsread(ino_t inode, void *buf, size_t nbyte)
{
- int c;
-
- c = xgetc(0);
- if (c == '\r')
- c = '\n';
- return c;
+ if (fsread(inode, buf, nbyte) != nbyte) {
+ printf("Invalid %s\n", "format");
+ return -1;
+ }
+ return 0;
}
static inline void
@@ -169,12 +168,13 @@ getstr(char *str, int size)
int c;
s = str;
- do {
- switch (c = getchar()) {
+ for (;;) {
+ switch (c = xgetc(0)) {
case 0:
break;
- case '\b':
case '\177':
+ c = '\b';
+ case '\b':
if (s > str) {
s--;
putchar('\b');
@@ -183,15 +183,16 @@ getstr(char *str, int size)
c = 0;
break;
case '\n':
+ case '\r':
*s = 0;
- break;
+ return;
default:
if (s - str < size - 1)
*s++ = c;
}
if (c)
putchar(c);
- } while (c != '\n');
+ }
}
static inline uint32_t
@@ -220,6 +221,7 @@ int
main(void)
{
int autoboot, i;
+ ino_t ino;
dmadat = (void *)(roundup2(__base + _end, 0x10000) - __base);
v86.ctl = V86_FLAGS;
@@ -238,7 +240,10 @@ main(void)
/* Process configuration file */
autoboot = 1;
- readfile(PATH_CONFIG, cmd, sizeof(cmd));
+
+ if ((ino = lookup(PATH_CONFIG)))
+ fsread(ino, cmd, sizeof(cmd));
+
if (*cmd) {
printf("%s: %s", PATH_CONFIG, cmd);
if (parse(cmd))
@@ -328,7 +333,7 @@ load(const char *fname)
return;
p += hdr.ex.a_data + roundup2(hdr.ex.a_bss, PAGE_SIZE);
bootinfo.bi_symtab = VTOP(p);
- memcpy(p, &hdr.ex.a_syms, sizeof(hdr.ex.a_syms));
+ memcpy(p, (char *)&hdr.ex.a_syms, sizeof(hdr.ex.a_syms));
p += sizeof(hdr.ex.a_syms);
if (hdr.ex.a_syms) {
if (xfsread(ino, p, hdr.ex.a_syms))
@@ -365,7 +370,7 @@ load(const char *fname)
if (xfsread(ino, &es, sizeof(es)))
return;
for (i = 0; i < 2; i++) {
- memcpy(p, &es[i].sh_size, sizeof(es[i].sh_size));
+ memcpy(p, (char *)&es[i].sh_size, sizeof(es[i].sh_size));
p += sizeof(es[i].sh_size);
fs_off = es[i].sh_offset;
if (xfsread(ino, p, es[i].sh_size))
@@ -378,7 +383,7 @@ load(const char *fname)
bootinfo.bi_esymtab = VTOP(p);
bootinfo.bi_kernelname = VTOP(fname);
bootinfo.bi_bios_dev = dsk.drive;
- __exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK),
+ __exec((caddr_t)addr, opts & RBX_MASK,
MAKEBOOTDEV(dev_maj[dsk.type], 0, dsk.slice, dsk.unit, dsk.part),
0, 0, 0, VTOP(&bootinfo));
}
@@ -449,9 +454,8 @@ parse(char *arg)
arg += 2;
if (drv == -1)
drv = dsk.unit;
- dsk.drive = (dsk.type == TYPE_WD ||
- dsk.type == TYPE_AD ||
- dsk.type == TYPE_DA ? DRV_HARD : 0) + drv;
+ dsk.drive = (dsk.type <= TYPE_MAXHARD
+ ? DRV_HARD : 0) + drv;
dsk_meta = 0;
fsread(0, NULL, 0);
}
@@ -467,16 +471,6 @@ parse(char *arg)
}
static int
-xfsread(ino_t inode, void *buf, size_t nbyte)
-{
- if (fsread(inode, buf, nbyte) != nbyte) {
- printf("Invalid %s\n", "format");
- return -1;
- }
- return 0;
-}
-
-static int
dskread(void *buf, unsigned lba, unsigned nblk)
{
struct dos_partition *dp;
diff --git a/sys/boot/i386/libi386/Makefile b/sys/boot/i386/libi386/Makefile
index 1268e02eb5ad..5c5292b527cf 100644
--- a/sys/boot/i386/libi386/Makefile
+++ b/sys/boot/i386/libi386/Makefile
@@ -4,9 +4,9 @@ LIB= i386
INTERNALLIB= true
SRCS= aout_freebsd.c biosacpi.c bioscd.c biosdisk.c biosmem.c biospnp.c \
- biospci.c bootinfo.c comconsole.c devicename.c elf_freebsd.c gatea20.c \
- i386_copy.c i386_module.c nullconsole.c pxe.c pxetramp.s \
- time.c vidconsole.c
+ biospci.c bootinfo.c comconsole.c devicename.c divdi3.c elf_freebsd.c \
+ gatea20.c i386_copy.c i386_module.c moddi3.c nullconsole.c pxe.c \
+ pxetramp.s qdivrem.c time.c vidconsole.c
CFLAGS+= -ffreestanding
BOOT_COMCONSOLE_PORT?= 0x3f8
@@ -39,9 +39,12 @@ beforedepend ${OBJS}: machine
machine:
ln -sf ${.CURDIR}/../../../i386/include machine
+ ln -sf ${.CURDIR}/../../../../lib/libc/quad/divdi3.c divdi3.c
+ ln -sf ${.CURDIR}/../../../../lib/libc/quad/moddi3.c moddi3.c
+ ln -sf ${.CURDIR}/../../../../lib/libc/quad/qdivrem.c qdivrem.c
.endif
-CLEANFILES+= machine
+CLEANFILES+= machine divdi3.c moddi3.c qdivrem.c
.include <bsd.lib.mk>
diff --git a/sys/boot/i386/loader/Makefile b/sys/boot/i386/loader/Makefile
index 0ad12764afe4..8ff477920ce8 100644
--- a/sys/boot/i386/loader/Makefile
+++ b/sys/boot/i386/loader/Makefile
@@ -119,7 +119,7 @@ FILES+= loader.rc
${BASE}.sym: ${OBJS} ${LIBI386} ${LIBSTAND} ${LIBFICL} vers.o
${CC} ${LDFLAGS} -o ${.TARGET} ${BTXCRT} ${OBJS} vers.o \
- ${LIBFICL} ${LIBI386} ${LIBSTAND}
+ ${LIBFICL} ${LIBI386} ${LIBSTAND} ${LIBI386}
# If it's not there, don't consider it a target
.if exists(${.CURDIR}/../../../i386/include)
diff --git a/sys/i386/Makefile b/sys/i386/Makefile
index 14ba0b34ba44..b7d021a7d3d1 100644
--- a/sys/i386/Makefile
+++ b/sys/i386/Makefile
@@ -5,6 +5,7 @@
# SYS is normally set in Make.tags.inc
# SYS=/sys
+SYS=/nsys
TAGDIR= i386
diff --git a/sys/kern/subr_disklabel.c b/sys/kern/subr_disklabel.c
index 176dafee082b..3bedc9c6c4ef 100644
--- a/sys/kern/subr_disklabel.c
+++ b/sys/kern/subr_disklabel.c
@@ -41,6 +41,7 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/stdint.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/conf.h>
@@ -398,11 +399,11 @@ diskerr(bp, what, blkdone, lp)
bp->bio_cmd == BIO_READ ? "read" : "writ");
sn = bp->bio_blkno;
if (bp->bio_bcount <= DEV_BSIZE)
- printf("%ld", (long)sn);
+ printf("%lld", (intmax_t)sn);
else {
if (blkdone >= 0) {
sn += blkdone;
- printf("%ld of ", (long)sn);
+ printf("%lld of ", (intmax_t)sn);
}
printf("%ld-%ld", (long)bp->bio_blkno,
(long)(bp->bio_blkno + (bp->bio_bcount - 1) / DEV_BSIZE));
@@ -416,9 +417,9 @@ diskerr(bp, what, blkdone, lp)
* independent of slices, labels and bad sector remapping,
* but some drivers don't set bp->b_pblkno.
*/
- printf(" (%s bn %ld; cn %ld", sname, (long)sn,
- (long)(sn / lp->d_secpercyl));
- sn %= (long)lp->d_secpercyl;
+ printf(" (%s bn %lld; cn %lld", sname, (intmax_t)sn,
+ (intmax_t)(sn / lp->d_secpercyl));
+ sn %= lp->d_secpercyl;
printf(" tn %ld sn %ld)", (long)(sn / lp->d_nsectors),
(long)(sn % lp->d_nsectors));
}
diff --git a/sys/kern/subr_diskslice.c b/sys/kern/subr_diskslice.c
index a52e301a9736..ec6099ecde9e 100644
--- a/sys/kern/subr_diskslice.c
+++ b/sys/kern/subr_diskslice.c
@@ -152,15 +152,15 @@ dscheck(bp, ssp)
struct bio *bp;
struct diskslices *ssp;
{
- daddr_t blkno;
- u_long endsecno;
- daddr_t labelsect;
+ daddr_t blkno;
+ daddr_t endsecno;
+ daddr_t labelsect;
struct disklabel *lp;
char *msg;
long nsec;
struct partition *pp;
- daddr_t secno;
- daddr_t slicerel_secno;
+ daddr_t secno;
+ daddr_t slicerel_secno;
struct diskslice *sp;
blkno = bp->bio_blkno;
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index be0778b007f8..100aebfef45a 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -29,6 +29,7 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/stdint.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/eventhandler.h>
@@ -2368,7 +2369,7 @@ loop:
else
bsize = size;
- offset = (off_t)blkno * bsize;
+ offset = blkno * bsize;
vmio = (VOP_GETVOBJECT(vp, NULL) == 0) && (vp->v_flag & VOBJBUF);
maxsize = vmio ? size + (offset & PAGE_MASK) : size;
maxsize = imax(maxsize, bsize);
@@ -2946,13 +2947,13 @@ bufdone(struct buf *bp)
(int) m->pindex, (int)(foff >> 32),
(int) foff & 0xffffffff, resid, i);
if (!vn_isdisk(vp, NULL))
- printf(" iosize: %ld, lblkno: %d, flags: 0x%lx, npages: %d\n",
+ printf(" iosize: %ld, lblkno: %lld, flags: 0x%lx, npages: %d\n",
bp->b_vp->v_mount->mnt_stat.f_iosize,
- (int) bp->b_lblkno,
+ (intmax_t) bp->b_lblkno,
bp->b_flags, bp->b_npages);
else
- printf(" VDEV, lblkno: %d, flags: 0x%lx, npages: %d\n",
- (int) bp->b_lblkno,
+ printf(" VDEV, lblkno: %lld, flags: 0x%lx, npages: %d\n",
+ (intmax_t) bp->b_lblkno,
bp->b_flags, bp->b_npages);
printf(" valid: 0x%x, dirty: 0x%x, wired: %d\n",
m->valid, m->dirty, m->wire_count);
@@ -3336,8 +3337,8 @@ vm_hold_free_pages(struct buf * bp, vm_offset_t from, vm_offset_t to)
if (p->busy) {
printf(
"vm_hold_free_pages: blkno: %lld, lblkno: %lld\n",
- (long long)bp->b_blkno,
- (long long)bp->b_lblkno);
+ (intmax_t)bp->b_blkno,
+ (intmax_t)bp->b_lblkno);
}
bp->b_pages[index] = NULL;
pmap_qremove(pg, 1);
@@ -3371,7 +3372,7 @@ DB_SHOW_COMMAND(buffer, db_show_buffer)
"b_dev = (%d,%d), b_data = %p, b_blkno = %lld, b_pblkno = %lld\n",
bp->b_error, bp->b_bufsize, bp->b_bcount, bp->b_resid,
major(bp->b_dev), minor(bp->b_dev), bp->b_data,
- (long long)bp->b_blkno, (long long)bp->b_pblkno);
+ (intmax_t)bp->b_blkno, (intmax_t)bp->b_pblkno);
if (bp->b_npages) {
int i;
db_printf("b_npages = %d, pages(OBJ, IDX, PA): ", bp->b_npages);
diff --git a/sys/kern/vfs_cluster.c b/sys/kern/vfs_cluster.c
index c0eed780222f..4c11952ab9b2 100644
--- a/sys/kern/vfs_cluster.c
+++ b/sys/kern/vfs_cluster.c
@@ -40,6 +40,7 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/stdint.h>
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/bio.h>
@@ -280,15 +281,13 @@ single_block_read:
#if defined(CLUSTERDEBUG)
if (rcluster) {
if (bp)
- printf("A+(%ld,%ld,%ld,%d) ",
- (long)rbp->b_lblkno, rbp->b_bcount,
- (long)(rbp->b_lblkno - origblkno),
- seqcount);
+ printf("A+");
else
- printf("A(%ld,%ld,%ld,%d) ",
- (long)rbp->b_lblkno, rbp->b_bcount,
- (long)(rbp->b_lblkno - origblkno),
- seqcount);
+ printf("A");
+ printf("(%lld,%ld,%lld,%d) ",
+ (intmax_t)rbp->b_lblkno, rbp->b_bcount,
+ (intmax_t)(rbp->b_lblkno - origblkno),
+ seqcount);
}
#endif
diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c
index 5c732241745f..d66417e58eb1 100644
--- a/sys/kern/vfs_extattr.c
+++ b/sys/kern/vfs_extattr.c
@@ -2631,8 +2631,8 @@ cvtnstat(sb, nsb)
nsb->st_blksize = sb->st_blksize;
nsb->st_flags = sb->st_flags;
nsb->st_gen = sb->st_gen;
- nsb->st_qspare[0] = sb->st_qspare[0];
- nsb->st_qspare[1] = sb->st_qspare[1];
+ nsb->st_createtimespec = sb->st_createtimespec;
+ nsb->st_qspare = sb->st_qspare;
}
#ifndef _SYS_SYSPROTO_H_
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 5c732241745f..d66417e58eb1 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -2631,8 +2631,8 @@ cvtnstat(sb, nsb)
nsb->st_blksize = sb->st_blksize;
nsb->st_flags = sb->st_flags;
nsb->st_gen = sb->st_gen;
- nsb->st_qspare[0] = sb->st_qspare[0];
- nsb->st_qspare[1] = sb->st_qspare[1];
+ nsb->st_createtimespec = sb->st_createtimespec;
+ nsb->st_qspare = sb->st_qspare;
}
#ifndef _SYS_SYSPROTO_H_
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index 64e26be32ff3..8dcf5c38c49f 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -563,8 +563,7 @@ vn_stat(vp, sb, td)
* Zero the spare stat fields
*/
sb->st_lspare = 0;
- sb->st_qspare[0] = 0;
- sb->st_qspare[1] = 0;
+ sb->st_qspare = 0;
/*
* Copy from vattr table
@@ -616,6 +615,7 @@ vn_stat(vp, sb, td)
sb->st_atimespec = vap->va_atime;
sb->st_mtimespec = vap->va_mtime;
sb->st_ctimespec = vap->va_ctime;
+ sb->st_createtimespec = vap->va_createtime;
/*
* According to www.opengroup.org, the meaning of st_blksize is
diff --git a/sys/sys/stat.h b/sys/sys/stat.h
index 00c8de0b8252..ce48cef2f75e 100644
--- a/sys/sys/stat.h
+++ b/sys/sys/stat.h
@@ -109,8 +109,9 @@ struct stat {
u_int32_t st_blksize; /* optimal blocksize for I/O */
fflags_t st_flags; /* user defined flags for file */
u_int32_t st_gen; /* file generation number */
+ struct timespec st_createtimespec; /* time of file creation */
int32_t st_lspare;
- int64_t st_qspare[2];
+ int64_t st_qspare;
};
#ifndef _POSIX_SOURCE
@@ -139,7 +140,8 @@ struct nstat {
u_int32_t st_blksize; /* optimal blocksize for I/O */
fflags_t st_flags; /* user defined flags for file */
u_int32_t st_gen; /* file generation number */
- int64_t st_qspare[2];
+ struct timespec st_createtimespec; /* time of file creation */
+ int64_t st_qspare;
};
#endif
diff --git a/sys/sys/types.h b/sys/sys/types.h
index 439074378a77..ded6f7749d75 100644
--- a/sys/sys/types.h
+++ b/sys/sys/types.h
@@ -148,8 +148,6 @@ typedef _BSD_SEGSZ_T_ segsz_t; /* segment size (in pages) */
#endif
typedef int32_t swblk_t; /* swap offset */
-typedef int32_t ufs_daddr_t;
-typedef int32_t ufs_time_t;
#ifdef _BSD_UID_T_
typedef _BSD_UID_T_ uid_t; /* user id */
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
index 182854af82f0..be774bd1d672 100644
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -203,6 +203,7 @@ struct vattr {
struct timespec va_atime; /* time of last access */
struct timespec va_mtime; /* time of last modification */
struct timespec va_ctime; /* time file changed */
+ struct timespec va_createtime; /* time file created */
u_long va_gen; /* generation number of file */
u_long va_flags; /* flags defined for file */
udev_t va_rdev; /* device the special file represents */
diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c
index 2dbb487df871..dbd757ed926a 100644
--- a/sys/ufs/ffs/ffs_alloc.c
+++ b/sys/ufs/ffs/ffs_alloc.c
@@ -1,4 +1,16 @@
/*
+ * Copyright (c) 2002 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by Marshall
+ * Kirk McKusick and Network Associates Laboratories, the Security
+ * Research Division of Network Associates, Inc. under DARPA/SPAWAR
+ * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
+ * research program
+ *
+ * Copyright (c) 1982, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
* Copyright (c) 1982, 1986, 1989, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -46,6 +58,7 @@
#include <sys/vnode.h>
#include <sys/mount.h>
#include <sys/kernel.h>
+#include <sys/stdint.h>
#include <sys/sysctl.h>
#include <sys/syslog.h>
@@ -58,23 +71,25 @@
#include <ufs/ffs/fs.h>
#include <ufs/ffs/ffs_extern.h>
-typedef ufs_daddr_t allocfcn_t(struct inode *ip, int cg, ufs_daddr_t bpref,
+typedef ufs2_daddr_t allocfcn_t(struct inode *ip, int cg, ufs2_daddr_t bpref,
int size);
-static ufs_daddr_t ffs_alloccg(struct inode *, int, ufs_daddr_t, int);
-static ufs_daddr_t
- ffs_alloccgblk(struct inode *, struct buf *, ufs_daddr_t);
+static ufs2_daddr_t ffs_alloccg(struct inode *, int, ufs2_daddr_t, int);
+static ufs2_daddr_t
+ ffs_alloccgblk(struct inode *, struct buf *, ufs2_daddr_t);
#ifdef DIAGNOSTIC
-static int ffs_checkblk(struct inode *, ufs_daddr_t, long);
+static int ffs_checkblk(struct inode *, ufs2_daddr_t, long);
#endif
-static ufs_daddr_t ffs_clusteralloc(struct inode *, int, ufs_daddr_t, int);
+static ufs2_daddr_t ffs_clusteralloc(struct inode *, int, ufs2_daddr_t, int);
static ino_t ffs_dirpref(struct inode *);
-static ufs_daddr_t ffs_fragextend(struct inode *, int, long, int, int);
+static ufs2_daddr_t ffs_fragextend(struct inode *, int, ufs2_daddr_t, int, int);
static void ffs_fserr(struct fs *, ino_t, char *);
-static u_long ffs_hashalloc
- (struct inode *, int, long, int, allocfcn_t *);
-static ino_t ffs_nodealloccg(struct inode *, int, ufs_daddr_t, int);
-static ufs_daddr_t ffs_mapsearch(struct fs *, struct cg *, ufs_daddr_t, int);
+static ufs2_daddr_t ffs_hashalloc
+ (struct inode *, int, ufs2_daddr_t, int, allocfcn_t *);
+static ino_t ffs_nodealloccg(struct inode *, int, ufs2_daddr_t, int);
+static ufs1_daddr_t ffs_mapsearch(struct fs *, struct cg *, ufs2_daddr_t, int);
+static int ffs_reallocblks_ufs1(struct vop_reallocblks_args *);
+static int ffs_reallocblks_ufs2(struct vop_reallocblks_args *);
/*
* Allocate a block in the filesystem.
@@ -98,13 +113,13 @@ static ufs_daddr_t ffs_mapsearch(struct fs *, struct cg *, ufs_daddr_t, int);
int
ffs_alloc(ip, lbn, bpref, size, cred, bnp)
struct inode *ip;
- ufs_daddr_t lbn, bpref;
+ ufs2_daddr_t lbn, bpref;
int size;
struct ucred *cred;
- ufs_daddr_t *bnp;
+ ufs2_daddr_t *bnp;
{
struct fs *fs;
- ufs_daddr_t bno;
+ ufs2_daddr_t bno;
int cg, reclaimed;
#ifdef QUOTA
int error;
@@ -130,7 +145,7 @@ retry:
freespace(fs, fs->fs_minfree) - numfrags(fs, size) < 0)
goto nospace;
#ifdef QUOTA
- error = chkdq(ip, (long)btodb(size), cred, 0);
+ error = chkdq(ip, btodb(size), cred, 0);
if (error)
return (error);
#endif
@@ -140,10 +155,9 @@ retry:
cg = ino_to_cg(fs, ip->i_number);
else
cg = dtog(fs, bpref);
- bno = (ufs_daddr_t)ffs_hashalloc(ip, cg, (long)bpref, size,
- ffs_alloccg);
+ bno = ffs_hashalloc(ip, cg, bpref, size, ffs_alloccg);
if (bno > 0) {
- ip->i_blocks += btodb(size);
+ DIP(ip, i_blocks) += btodb(size);
ip->i_flag |= IN_CHANGE | IN_UPDATE;
*bnp = bno;
return (0);
@@ -152,7 +166,7 @@ retry:
/*
* Restore user's disk quota because allocation failed.
*/
- (void) chkdq(ip, (long)-btodb(size), cred, FORCE);
+ (void) chkdq(ip, -btodb(size), cred, FORCE);
#endif
nospace:
if (fs->fs_pendingblocks > 0 && reclaimed == 0) {
@@ -176,8 +190,8 @@ nospace:
int
ffs_realloccg(ip, lbprev, bpref, osize, nsize, cred, bpp)
struct inode *ip;
- ufs_daddr_t lbprev;
- ufs_daddr_t bpref;
+ ufs2_daddr_t lbprev;
+ ufs2_daddr_t bpref;
int osize, nsize;
struct ucred *cred;
struct buf **bpp;
@@ -186,7 +200,7 @@ ffs_realloccg(ip, lbprev, bpref, osize, nsize, cred, bpp)
struct fs *fs;
struct buf *bp;
int cg, request, error, reclaimed;
- ufs_daddr_t bprev, bno;
+ ufs2_daddr_t bprev, bno;
*bpp = 0;
vp = ITOV(ip);
@@ -210,9 +224,9 @@ retry:
if (suser_cred(cred, PRISON_ROOT) &&
freespace(fs, fs->fs_minfree) - numfrags(fs, nsize - osize) < 0)
goto nospace;
- if ((bprev = ip->i_db[lbprev]) == 0) {
- printf("dev = %s, bsize = %ld, bprev = %ld, fs = %s\n",
- devtoname(ip->i_dev), (long)fs->fs_bsize, (long)bprev,
+ if ((bprev = DIP(ip, i_db[lbprev])) == 0) {
+ printf("dev = %s, bsize = %ld, bprev = %lld, fs = %s\n",
+ devtoname(ip->i_dev), (long)fs->fs_bsize, (intmax_t)bprev,
fs->fs_fsmnt);
panic("ffs_realloccg: bad bprev");
}
@@ -225,14 +239,14 @@ retry:
return (error);
}
- if( bp->b_blkno == bp->b_lblkno) {
- if( lbprev >= NDADDR)
+ if (bp->b_blkno == bp->b_lblkno) {
+ if (lbprev >= NDADDR)
panic("ffs_realloccg: lbprev out of range");
bp->b_blkno = fsbtodb(fs, bprev);
}
#ifdef QUOTA
- error = chkdq(ip, (long)btodb(nsize - osize), cred, 0);
+ error = chkdq(ip, btodb(nsize - osize), cred, 0);
if (error) {
brelse(bp);
return (error);
@@ -242,11 +256,11 @@ retry:
* Check for extension in the existing location.
*/
cg = dtog(fs, bprev);
- bno = ffs_fragextend(ip, cg, (long)bprev, osize, nsize);
+ bno = ffs_fragextend(ip, cg, bprev, osize, nsize);
if (bno) {
if (bp->b_blkno != fsbtodb(fs, bno))
panic("ffs_realloccg: bad blockno");
- ip->i_blocks += btodb(nsize - osize);
+ DIP(ip, i_blocks) += btodb(nsize - osize);
ip->i_flag |= IN_CHANGE | IN_UPDATE;
allocbuf(bp, nsize);
bp->b_flags |= B_DONE;
@@ -302,8 +316,7 @@ retry:
panic("ffs_realloccg: bad optim");
/* NOTREACHED */
}
- bno = (ufs_daddr_t)ffs_hashalloc(ip, cg, (long)bpref, request,
- ffs_alloccg);
+ bno = ffs_hashalloc(ip, cg, bpref, request, ffs_alloccg);
if (bno > 0) {
bp->b_blkno = fsbtodb(fs, bno);
if (!DOINGSOFTDEP(vp))
@@ -312,7 +325,7 @@ retry:
if (nsize < request)
ffs_blkfree(fs, ip->i_devvp, bno + numfrags(fs, nsize),
(long)(request - nsize), ip->i_number);
- ip->i_blocks += btodb(nsize - osize);
+ DIP(ip, i_blocks) += btodb(nsize - osize);
ip->i_flag |= IN_CHANGE | IN_UPDATE;
allocbuf(bp, nsize);
bp->b_flags |= B_DONE;
@@ -324,7 +337,7 @@ retry:
/*
* Restore user's disk quota because allocation failed.
*/
- (void) chkdq(ip, (long)-btodb(nsize - osize), cred, FORCE);
+ (void) chkdq(ip, -btodb(nsize - osize), cred, FORCE);
#endif
brelse(bp);
nospace:
@@ -346,14 +359,14 @@ nospace:
*
* The vnode and an array of buffer pointers for a range of sequential
* logical blocks to be made contiguous is given. The allocator attempts
- * to find a range of sequential blocks starting as close as possible to
- * an fs_rotdelay offset from the end of the allocation for the logical
- * block immediately preceding the current range. If successful, the
- * physical block numbers in the buffer pointers and in the inode are
- * changed to reflect the new allocation. If unsuccessful, the allocation
- * is left unchanged. The success in doing the reallocation is returned.
- * Note that the error return is not reflected back to the user. Rather
- * the previous block allocation will be used.
+ * to find a range of sequential blocks starting as close as possible
+ * from the end of the allocation for the logical block immediately
+ * preceding the current range. If successful, the physical block numbers
+ * in the buffer pointers and in the inode are changed to reflect the new
+ * allocation. If unsuccessful, the allocation is left unchanged. The
+ * success in doing the reallocation is returned. Note that the error
+ * return is not reflected back to the user. Rather the previous block
+ * allocation will be used.
*/
SYSCTL_NODE(_vfs, OID_AUTO, ffs, CTLFLAG_RW, 0, "FFS filesystem");
@@ -375,18 +388,33 @@ ffs_reallocblks(ap)
struct cluster_save *a_buflist;
} */ *ap;
{
+
+ if (doreallocblks == 0)
+ return (ENOSPC);
+ if (VTOI(ap->a_vp)->i_ump->um_fstype == UFS1)
+ return (ffs_reallocblks_ufs1(ap));
+ return (ffs_reallocblks_ufs2(ap));
+}
+
+static int
+ffs_reallocblks_ufs1(ap)
+ struct vop_reallocblks_args /* {
+ struct vnode *a_vp;
+ struct cluster_save *a_buflist;
+ } */ *ap;
+{
struct fs *fs;
struct inode *ip;
struct vnode *vp;
struct buf *sbp, *ebp;
- ufs_daddr_t *bap, *sbap, *ebap = 0;
+ ufs1_daddr_t *bap, *sbap, *ebap = 0;
struct cluster_save *buflist;
- ufs_daddr_t start_lbn, end_lbn, soff, newblk, blkno;
+ ufs_lbn_t start_lbn, end_lbn;
+ ufs1_daddr_t soff, newblk, blkno;
+ ufs2_daddr_t pref;
struct indir start_ap[NIADDR + 1], end_ap[NIADDR + 1], *idp;
- int i, len, start_lvl, end_lvl, pref, ssize;
+ int i, len, start_lvl, end_lvl, ssize;
- if (doreallocblks == 0)
- return (ENOSPC);
vp = ap->a_vp;
ip = VTOI(vp);
fs = ip->i_fs;
@@ -425,7 +453,7 @@ ffs_reallocblks(ap)
* Get the starting offset and block map for the first block.
*/
if (start_lvl == 0) {
- sbap = &ip->i_db[0];
+ sbap = &ip->i_din1->di_db[0];
soff = start_lbn;
} else {
idp = &start_ap[start_lvl - 1];
@@ -433,13 +461,13 @@ ffs_reallocblks(ap)
brelse(sbp);
return (ENOSPC);
}
- sbap = (ufs_daddr_t *)sbp->b_data;
+ sbap = (ufs1_daddr_t *)sbp->b_data;
soff = idp->in_off;
}
/*
* Find the preferred location for the cluster.
*/
- pref = ffs_blkpref(ip, start_lbn, soff, sbap);
+ pref = ffs_blkpref_ufs1(ip, start_lbn, soff, sbap);
/*
* If the block range spans two block maps, get the second map.
*/
@@ -453,12 +481,12 @@ ffs_reallocblks(ap)
ssize = len - (idp->in_off + 1);
if (bread(vp, idp->in_lbn, (int)fs->fs_bsize, NOCRED, &ebp))
goto fail;
- ebap = (ufs_daddr_t *)ebp->b_data;
+ ebap = (ufs1_daddr_t *)ebp->b_data;
}
/*
* Search the block map looking for an allocation of the desired size.
*/
- if ((newblk = (ufs_daddr_t)ffs_hashalloc(ip, dtog(fs, pref), (long)pref,
+ if ((newblk = ffs_hashalloc(ip, dtog(fs, pref), pref,
len, ffs_clusteralloc)) == 0)
goto fail;
/*
@@ -470,8 +498,8 @@ ffs_reallocblks(ap)
*/
#ifdef DEBUG
if (prtrealloc)
- printf("realloc: ino %d, lbns %d-%d\n\told:", ip->i_number,
- start_lbn, end_lbn);
+ printf("realloc: ino %d, lbns %lld-%lld\n\told:", ip->i_number,
+ (intmax_t)start_lbn, (intmax_t)end_lbn);
#endif
blkno = newblk;
for (bap = &sbap[soff], i = 0; i < len; i++, blkno += fs->fs_frag) {
@@ -491,7 +519,7 @@ ffs_reallocblks(ap)
printf(" %d,", *bap);
#endif
if (DOINGSOFTDEP(vp)) {
- if (sbap == &ip->i_db[0] && i < ssize)
+ if (sbap == &ip->i_din1->di_db[0] && i < ssize)
softdep_setup_allocdirect(ip, start_lbn + i,
blkno, *bap, fs->fs_bsize, fs->fs_bsize,
buflist->bs_children[i]);
@@ -516,7 +544,7 @@ ffs_reallocblks(ap)
* We can then check below to see if it is set, and do the
* synchronous write only when it has been cleared.
*/
- if (sbap != &ip->i_db[0]) {
+ if (sbap != &ip->i_din1->di_db[0]) {
if (doasyncfree)
bdwrite(sbp);
else
@@ -566,7 +594,209 @@ ffs_reallocblks(ap)
fail:
if (ssize < len)
brelse(ebp);
- if (sbap != &ip->i_db[0])
+ if (sbap != &ip->i_din1->di_db[0])
+ brelse(sbp);
+ return (ENOSPC);
+}
+
+static int
+ffs_reallocblks_ufs2(ap)
+ struct vop_reallocblks_args /* {
+ struct vnode *a_vp;
+ struct cluster_save *a_buflist;
+ } */ *ap;
+{
+ struct fs *fs;
+ struct inode *ip;
+ struct vnode *vp;
+ struct buf *sbp, *ebp;
+ ufs2_daddr_t *bap, *sbap, *ebap = 0;
+ struct cluster_save *buflist;
+ ufs_lbn_t start_lbn, end_lbn;
+ ufs2_daddr_t soff, newblk, blkno, pref;
+ struct indir start_ap[NIADDR + 1], end_ap[NIADDR + 1], *idp;
+ int i, len, start_lvl, end_lvl, ssize;
+
+ vp = ap->a_vp;
+ ip = VTOI(vp);
+ fs = ip->i_fs;
+ if (fs->fs_contigsumsize <= 0)
+ return (ENOSPC);
+ buflist = ap->a_buflist;
+ len = buflist->bs_nchildren;
+ start_lbn = buflist->bs_children[0]->b_lblkno;
+ end_lbn = start_lbn + len - 1;
+#ifdef DIAGNOSTIC
+ for (i = 0; i < len; i++)
+ if (!ffs_checkblk(ip,
+ dbtofsb(fs, buflist->bs_children[i]->b_blkno), fs->fs_bsize))
+ panic("ffs_reallocblks: unallocated block 1");
+ for (i = 1; i < len; i++)
+ if (buflist->bs_children[i]->b_lblkno != start_lbn + i)
+ panic("ffs_reallocblks: non-logical cluster");
+ blkno = buflist->bs_children[0]->b_blkno;
+ ssize = fsbtodb(fs, fs->fs_frag);
+ for (i = 1; i < len - 1; i++)
+ if (buflist->bs_children[i]->b_blkno != blkno + (i * ssize))
+ panic("ffs_reallocblks: non-physical cluster %d", i);
+#endif
+ /*
+ * If the latest allocation is in a new cylinder group, assume that
+ * the filesystem has decided to move and do not force it back to
+ * the previous cylinder group.
+ */
+ if (dtog(fs, dbtofsb(fs, buflist->bs_children[0]->b_blkno)) !=
+ dtog(fs, dbtofsb(fs, buflist->bs_children[len - 1]->b_blkno)))
+ return (ENOSPC);
+ if (ufs_getlbns(vp, start_lbn, start_ap, &start_lvl) ||
+ ufs_getlbns(vp, end_lbn, end_ap, &end_lvl))
+ return (ENOSPC);
+ /*
+ * Get the starting offset and block map for the first block.
+ */
+ if (start_lvl == 0) {
+ sbap = &ip->i_din2->di_db[0];
+ soff = start_lbn;
+ } else {
+ idp = &start_ap[start_lvl - 1];
+ if (bread(vp, idp->in_lbn, (int)fs->fs_bsize, NOCRED, &sbp)) {
+ brelse(sbp);
+ return (ENOSPC);
+ }
+ sbap = (ufs2_daddr_t *)sbp->b_data;
+ soff = idp->in_off;
+ }
+ /*
+ * Find the preferred location for the cluster.
+ */
+ pref = ffs_blkpref_ufs2(ip, start_lbn, soff, sbap);
+ /*
+ * If the block range spans two block maps, get the second map.
+ */
+ if (end_lvl == 0 || (idp = &end_ap[end_lvl - 1])->in_off + 1 >= len) {
+ ssize = len;
+ } else {
+#ifdef DIAGNOSTIC
+ if (start_ap[start_lvl-1].in_lbn == idp->in_lbn)
+ panic("ffs_reallocblk: start == end");
+#endif
+ ssize = len - (idp->in_off + 1);
+ if (bread(vp, idp->in_lbn, (int)fs->fs_bsize, NOCRED, &ebp))
+ goto fail;
+ ebap = (ufs2_daddr_t *)ebp->b_data;
+ }
+ /*
+ * Search the block map looking for an allocation of the desired size.
+ */
+ if ((newblk = ffs_hashalloc(ip, dtog(fs, pref), pref,
+ len, ffs_clusteralloc)) == 0)
+ goto fail;
+ /*
+ * We have found a new contiguous block.
+ *
+ * First we have to replace the old block pointers with the new
+ * block pointers in the inode and indirect blocks associated
+ * with the file.
+ */
+#ifdef DEBUG
+ if (prtrealloc)
+ printf("realloc: ino %d, lbns %lld-%lld\n\told:", ip->i_number,
+ (intmax_t)start_lbn, (intmax_t)end_lbn);
+#endif
+ blkno = newblk;
+ for (bap = &sbap[soff], i = 0; i < len; i++, blkno += fs->fs_frag) {
+ if (i == ssize) {
+ bap = ebap;
+ soff = -i;
+ }
+#ifdef DIAGNOSTIC
+ if (!ffs_checkblk(ip,
+ dbtofsb(fs, buflist->bs_children[i]->b_blkno), fs->fs_bsize))
+ panic("ffs_reallocblks: unallocated block 2");
+ if (dbtofsb(fs, buflist->bs_children[i]->b_blkno) != *bap)
+ panic("ffs_reallocblks: alloc mismatch");
+#endif
+#ifdef DEBUG
+ if (prtrealloc)
+ printf(" %lld,", (intmax_t)*bap);
+#endif
+ if (DOINGSOFTDEP(vp)) {
+ if (sbap == &ip->i_din2->di_db[0] && i < ssize)
+ softdep_setup_allocdirect(ip, start_lbn + i,
+ blkno, *bap, fs->fs_bsize, fs->fs_bsize,
+ buflist->bs_children[i]);
+ else
+ softdep_setup_allocindir_page(ip, start_lbn + i,
+ i < ssize ? sbp : ebp, soff + i, blkno,
+ *bap, buflist->bs_children[i]);
+ }
+ *bap++ = blkno;
+ }
+ /*
+ * Next we must write out the modified inode and indirect blocks.
+ * For strict correctness, the writes should be synchronous since
+ * the old block values may have been written to disk. In practise
+ * they are almost never written, but if we are concerned about
+ * strict correctness, the `doasyncfree' flag should be set to zero.
+ *
+ * The test on `doasyncfree' should be changed to test a flag
+ * that shows whether the associated buffers and inodes have
+ * been written. The flag should be set when the cluster is
+ * started and cleared whenever the buffer or inode is flushed.
+ * We can then check below to see if it is set, and do the
+ * synchronous write only when it has been cleared.
+ */
+ if (sbap != &ip->i_din2->di_db[0]) {
+ if (doasyncfree)
+ bdwrite(sbp);
+ else
+ bwrite(sbp);
+ } else {
+ ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ if (!doasyncfree)
+ UFS_UPDATE(vp, 1);
+ }
+ if (ssize < len) {
+ if (doasyncfree)
+ bdwrite(ebp);
+ else
+ bwrite(ebp);
+ }
+ /*
+ * Last, free the old blocks and assign the new blocks to the buffers.
+ */
+#ifdef DEBUG
+ if (prtrealloc)
+ printf("\n\tnew:");
+#endif
+ for (blkno = newblk, i = 0; i < len; i++, blkno += fs->fs_frag) {
+ if (!DOINGSOFTDEP(vp))
+ ffs_blkfree(fs, ip->i_devvp,
+ dbtofsb(fs, buflist->bs_children[i]->b_blkno),
+ fs->fs_bsize, ip->i_number);
+ buflist->bs_children[i]->b_blkno = fsbtodb(fs, blkno);
+#ifdef DIAGNOSTIC
+ if (!ffs_checkblk(ip,
+ dbtofsb(fs, buflist->bs_children[i]->b_blkno), fs->fs_bsize))
+ panic("ffs_reallocblks: unallocated block 3");
+#endif
+#ifdef DEBUG
+ if (prtrealloc)
+ printf(" %d,", blkno);
+#endif
+ }
+#ifdef DEBUG
+ if (prtrealloc) {
+ prtrealloc--;
+ printf("\n");
+ }
+#endif
+ return (0);
+
+fail:
+ if (ssize < len)
+ brelse(ebp);
+ if (sbap != &ip->i_din2->di_db[0])
brelse(sbp);
return (ENOSPC);
}
@@ -596,6 +826,7 @@ ffs_valloc(pvp, mode, cred, vpp)
struct inode *pip;
struct fs *fs;
struct inode *ip;
+ struct timespec ts;
ino_t ino, ipref;
int cg, error;
@@ -623,7 +854,7 @@ ffs_valloc(pvp, mode, cred, vpp)
if (fs->fs_contigdirs[cg] > 0)
fs->fs_contigdirs[cg]--;
}
- ino = (ino_t)ffs_hashalloc(pip, cg, (long)ipref, mode,
+ ino = (ino_t)ffs_hashalloc(pip, cg, ipref, mode,
(allocfcn_t *)ffs_nodealloccg);
if (ino == 0)
goto noinodes;
@@ -638,17 +869,24 @@ ffs_valloc(pvp, mode, cred, vpp)
ip->i_mode, (u_long)ip->i_number, fs->fs_fsmnt);
panic("ffs_valloc: dup alloc");
}
- if (ip->i_blocks && (fs->fs_flags & FS_UNCLEAN) == 0) { /* XXX */
+ if (DIP(ip, i_blocks) && (fs->fs_flags & FS_UNCLEAN) == 0) { /* XXX */
printf("free inode %s/%lu had %ld blocks\n",
- fs->fs_fsmnt, (u_long)ino, (long)ip->i_blocks);
- ip->i_blocks = 0;
+ fs->fs_fsmnt, (u_long)ino, (long)DIP(ip, i_blocks));
+ DIP(ip, i_blocks) = 0;
}
ip->i_flags = 0;
+ DIP(ip, i_flags) = 0;
/*
* Set up a new generation number for this inode.
*/
if (ip->i_gen == 0 || ++ip->i_gen == 0)
ip->i_gen = random() / 2 + 1;
+ DIP(ip, i_gen) = ip->i_gen;
+ if (fs->fs_magic == FS_UFS2_MAGIC) {
+ vfs_timestamp(&ts);
+ ip->i_din2->di_createtime = ts.tv_sec;
+ ip->i_din2->di_creatensec = ts.tv_nsec;
+ }
return (0);
noinodes:
ffs_fserr(fs, pip->i_number, "out of inodes");
@@ -785,23 +1023,20 @@ ffs_dirpref(pip)
* allocated.
*
* If a section is already partially allocated, the policy is to
- * contiguously allocate fs_maxcontig blocks. The end of one of these
- * contiguous blocks and the beginning of the next is physically separated
- * so that the disk head will be in transit between them for at least
- * fs_rotdelay milliseconds. This is to allow time for the processor to
- * schedule another I/O transfer.
+ * contiguously allocate fs_maxcontig blocks. The end of one of these
+ * contiguous blocks and the beginning of the next is laid out
+ * contiguously if possible.
*/
-ufs_daddr_t
-ffs_blkpref(ip, lbn, indx, bap)
+ufs2_daddr_t
+ffs_blkpref_ufs1(ip, lbn, indx, bap)
struct inode *ip;
- ufs_daddr_t lbn;
+ ufs_lbn_t lbn;
int indx;
- ufs_daddr_t *bap;
+ ufs1_daddr_t *bap;
{
struct fs *fs;
int cg;
int avgbfree, startcg;
- ufs_daddr_t nextblk;
fs = ip->i_fs;
if (indx % fs->fs_maxbpg == 0 || bap[indx - 1] == 0) {
@@ -833,25 +1068,58 @@ ffs_blkpref(ip, lbn, indx, bap)
return (0);
}
/*
- * One or more previous blocks have been laid out. If less
- * than fs_maxcontig previous blocks are contiguous, the
- * next block is requested contiguously, otherwise it is
- * requested rotationally delayed by fs_rotdelay milliseconds.
+ * We just always try to lay things out contiguously.
*/
- nextblk = bap[indx - 1] + fs->fs_frag;
- if (fs->fs_rotdelay == 0 || indx < fs->fs_maxcontig ||
- bap[indx - fs->fs_maxcontig] +
- blkstofrags(fs, fs->fs_maxcontig) != nextblk)
- return (nextblk);
+ return (bap[indx - 1] + fs->fs_frag);
+}
+
+/*
+ * Same as above, but for UFS2
+ */
+ufs2_daddr_t
+ffs_blkpref_ufs2(ip, lbn, indx, bap)
+ struct inode *ip;
+ ufs_lbn_t lbn;
+ int indx;
+ ufs2_daddr_t *bap;
+{
+ struct fs *fs;
+ int cg;
+ int avgbfree, startcg;
+
+ fs = ip->i_fs;
+ if (indx % fs->fs_maxbpg == 0 || bap[indx - 1] == 0) {
+ if (lbn < NDADDR + NINDIR(fs)) {
+ cg = ino_to_cg(fs, ip->i_number);
+ return (fs->fs_fpg * cg + fs->fs_frag);
+ }
+ /*
+ * Find a cylinder with greater than average number of
+ * unused data blocks.
+ */
+ if (indx == 0 || bap[indx - 1] == 0)
+ startcg =
+ ino_to_cg(fs, ip->i_number) + lbn / fs->fs_maxbpg;
+ else
+ startcg = dtog(fs, bap[indx - 1]) + 1;
+ startcg %= fs->fs_ncg;
+ avgbfree = fs->fs_cstotal.cs_nbfree / fs->fs_ncg;
+ for (cg = startcg; cg < fs->fs_ncg; cg++)
+ if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) {
+ fs->fs_cgrotor = cg;
+ return (fs->fs_fpg * cg + fs->fs_frag);
+ }
+ for (cg = 0; cg <= startcg; cg++)
+ if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) {
+ fs->fs_cgrotor = cg;
+ return (fs->fs_fpg * cg + fs->fs_frag);
+ }
+ return (0);
+ }
/*
- * Here we convert ms of delay to frags as:
- * (frags) = (ms) * (rev/sec) * (sect/rev) /
- * ((sect/frag) * (ms/sec))
- * then round up to the next block.
+ * We just always try to lay things out contiguously.
*/
- nextblk += roundup(fs->fs_rotdelay * fs->fs_rps * fs->fs_nsect /
- (NSPF(fs) * 1000), fs->fs_frag);
- return (nextblk);
+ return (bap[indx - 1] + fs->fs_frag);
}
/*
@@ -863,16 +1131,16 @@ ffs_blkpref(ip, lbn, indx, bap)
* 3) brute force search for a free block.
*/
/*VARARGS5*/
-static u_long
+static ufs2_daddr_t
ffs_hashalloc(ip, cg, pref, size, allocator)
struct inode *ip;
int cg;
- long pref;
+ ufs2_daddr_t pref;
int size; /* size for data blocks, mode for inodes */
allocfcn_t *allocator;
{
struct fs *fs;
- long result; /* XXX why not same type as we return? */
+ ufs2_daddr_t result;
int i, icg = cg;
#ifdef DIAGNOSTIC
@@ -920,11 +1188,11 @@ ffs_hashalloc(ip, cg, pref, size, allocator)
* Check to see if the necessary fragments are available, and
* if they are, allocate them.
*/
-static ufs_daddr_t
+static ufs2_daddr_t
ffs_fragextend(ip, cg, bprev, osize, nsize)
struct inode *ip;
int cg;
- long bprev;
+ ufs2_daddr_t bprev;
int osize, nsize;
{
struct fs *fs;
@@ -956,7 +1224,7 @@ ffs_fragextend(ip, cg, bprev, osize, nsize)
return (0);
}
bp->b_xflags |= BX_BKGRDWRITE;
- cgp->cg_time = time_second;
+ cgp->cg_old_time = cgp->cg_time = time_second;
bno = dtogd(fs, bprev);
blksfree = cg_blksfree(cgp);
for (i = numfrags(fs, osize); i < frags; i++)
@@ -997,19 +1265,19 @@ ffs_fragextend(ip, cg, bprev, osize, nsize)
* Check to see if a block of the appropriate size is available,
* and if it is, allocate it.
*/
-static ufs_daddr_t
+static ufs2_daddr_t
ffs_alloccg(ip, cg, bpref, size)
struct inode *ip;
int cg;
- ufs_daddr_t bpref;
+ ufs2_daddr_t bpref;
int size;
{
struct fs *fs;
struct cg *cgp;
struct buf *bp;
- int i;
- ufs_daddr_t bno, blkno;
- int allocsiz, error, frags;
+ ufs1_daddr_t bno;
+ ufs2_daddr_t blkno;
+ int i, allocsiz, error, frags;
u_int8_t *blksfree;
fs = ip->i_fs;
@@ -1028,13 +1296,13 @@ ffs_alloccg(ip, cg, bpref, size)
return (0);
}
bp->b_xflags |= BX_BKGRDWRITE;
- cgp->cg_time = time_second;
+ cgp->cg_old_time = cgp->cg_time = time_second;
if (size == fs->fs_bsize) {
- bno = ffs_alloccgblk(ip, bp, bpref);
+ blkno = ffs_alloccgblk(ip, bp, bpref);
if (fs->fs_active != 0)
atomic_clear_int(&ACTIVECGNUM(fs, cg), ACTIVECGOFF(cg));
bdwrite(bp);
- return (bno);
+ return (blkno);
}
/*
* check to see if any fragments are already available
@@ -1055,10 +1323,10 @@ ffs_alloccg(ip, cg, bpref, size)
brelse(bp);
return (0);
}
- bno = ffs_alloccgblk(ip, bp, bpref);
- bpref = dtogd(fs, bno);
+ blkno = ffs_alloccgblk(ip, bp, bpref);
+ bno = dtogd(fs, blkno);
for (i = frags; i < fs->fs_frag; i++)
- setbit(blksfree, bpref + i);
+ setbit(blksfree, bno + i);
i = fs->fs_frag - frags;
cgp->cg_cs.cs_nffree += i;
fs->fs_cstotal.cs_nffree += i;
@@ -1068,7 +1336,7 @@ ffs_alloccg(ip, cg, bpref, size)
if (fs->fs_active != 0)
atomic_clear_int(&ACTIVECGNUM(fs, cg), ACTIVECGOFF(cg));
bdwrite(bp);
- return (bno);
+ return (blkno);
}
bno = ffs_mapsearch(fs, cgp, bpref, allocsiz);
if (bno < 0) {
@@ -1090,7 +1358,7 @@ ffs_alloccg(ip, cg, bpref, size)
if (fs->fs_active != 0)
atomic_clear_int(&ACTIVECGNUM(fs, cg), ACTIVECGOFF(cg));
bdwrite(bp);
- return ((u_long)blkno);
+ return (blkno);
}
/*
@@ -1104,18 +1372,16 @@ ffs_alloccg(ip, cg, bpref, size)
* Note that this routine only allocates fs_bsize blocks; these
* blocks may be fragmented by the routine that allocates them.
*/
-static ufs_daddr_t
+static ufs2_daddr_t
ffs_alloccgblk(ip, bp, bpref)
struct inode *ip;
struct buf *bp;
- ufs_daddr_t bpref;
+ ufs2_daddr_t bpref;
{
struct fs *fs;
struct cg *cgp;
- ufs_daddr_t bno, blkno;
- int cylno, pos, delta;
- short *cylbp;
- int i;
+ ufs1_daddr_t bno;
+ ufs2_daddr_t blkno;
u_int8_t *blksfree;
fs = ip->i_fs;
@@ -1123,78 +1389,17 @@ ffs_alloccgblk(ip, bp, bpref)
blksfree = cg_blksfree(cgp);
if (bpref == 0 || dtog(fs, bpref) != cgp->cg_cgx) {
bpref = cgp->cg_rotor;
- goto norot;
- }
- bpref = blknum(fs, bpref);
- bpref = dtogd(fs, bpref);
- /*
- * if the requested block is available, use it
- */
- if (ffs_isblock(fs, blksfree, fragstoblks(fs, bpref))) {
- bno = bpref;
- goto gotit;
- }
- if (fs->fs_nrpos <= 1 || fs->fs_cpc == 0) {
- /*
- * Block layout information is not available.
- * Leaving bpref unchanged means we take the
- * next available free block following the one
- * we just allocated. Hopefully this will at
- * least hit a track cache on drives of unknown
- * geometry (e.g. SCSI).
- */
- goto norot;
- }
- /*
- * check for a block available on the same cylinder
- */
- cylno = cbtocylno(fs, bpref);
- if (cg_blktot(cgp)[cylno] == 0)
- goto norot;
- /*
- * check the summary information to see if a block is
- * available in the requested cylinder starting at the
- * requested rotational position and proceeding around.
- */
- cylbp = cg_blks(fs, cgp, cylno);
- pos = cbtorpos(fs, bpref);
- for (i = pos; i < fs->fs_nrpos; i++)
- if (cylbp[i] > 0)
- break;
- if (i == fs->fs_nrpos)
- for (i = 0; i < pos; i++)
- if (cylbp[i] > 0)
- break;
- if (cylbp[i] > 0) {
+ } else {
+ bpref = blknum(fs, bpref);
+ bno = dtogd(fs, bpref);
/*
- * found a rotational position, now find the actual
- * block. A panic if none is actually there.
+ * if the requested block is available, use it
*/
- pos = cylno % fs->fs_cpc;
- bno = (cylno - pos) * fs->fs_spc / NSPB(fs);
- if (fs_postbl(fs, pos)[i] == -1) {
- printf("pos = %d, i = %d, fs = %s\n",
- pos, i, fs->fs_fsmnt);
- panic("ffs_alloccgblk: cyl groups corrupted");
- }
- for (i = fs_postbl(fs, pos)[i];; ) {
- if (ffs_isblock(fs, blksfree, bno + i)) {
- bno = blkstofrags(fs, (bno + i));
- goto gotit;
- }
- delta = fs_rotbl(fs)[i];
- if (delta <= 0 ||
- delta + i > fragstoblks(fs, fs->fs_fpg))
- break;
- i += delta;
- }
- printf("pos = %d, i = %d, fs = %s\n", pos, i, fs->fs_fsmnt);
- panic("ffs_alloccgblk: can't find blk in cyl");
+ if (ffs_isblock(fs, blksfree, fragstoblks(fs, bno)))
+ goto gotit;
}
-norot:
/*
- * no blocks in the requested cylinder, so take next
- * available one in this cylinder group.
+ * Take the next available block in this cylinder group.
*/
bno = ffs_mapsearch(fs, cgp, bpref, (int)fs->fs_frag);
if (bno < 0)
@@ -1207,9 +1412,6 @@ gotit:
cgp->cg_cs.cs_nbfree--;
fs->fs_cstotal.cs_nbfree--;
fs->fs_cs(fs, cgp->cg_cgx).cs_nbfree--;
- cylno = cbtocylno(fs, bno);
- cg_blks(fs, cgp, cylno)[cbtorpos(fs, bno)]--;
- cg_blktot(cgp)[cylno]--;
fs->fs_fmod = 1;
blkno = cgp->cg_cgx * fs->fs_fpg + bno;
if (DOINGSOFTDEP(ITOV(ip)))
@@ -1224,17 +1426,18 @@ gotit:
* are multiple choices in the same cylinder group. Instead we just
* take the first one that we find following bpref.
*/
-static ufs_daddr_t
+static ufs2_daddr_t
ffs_clusteralloc(ip, cg, bpref, len)
struct inode *ip;
int cg;
- ufs_daddr_t bpref;
+ ufs2_daddr_t bpref;
int len;
{
struct fs *fs;
struct cg *cgp;
struct buf *bp;
- int i, got, run, bno, bit, map;
+ int i, run, bit, map, got;
+ ufs2_daddr_t bno;
u_char *mapp;
int32_t *lp;
u_int8_t *blksfree;
@@ -1319,7 +1522,7 @@ ffs_clusteralloc(ip, cg, bpref, len)
panic("ffs_clusteralloc: allocated out of group");
len = blkstofrags(fs, len);
for (i = 0; i < len; i += fs->fs_frag)
- if ((got = ffs_alloccgblk(ip, bp, bno + i)) != bno + i)
+ if (ffs_alloccgblk(ip, bp, bno + i) != bno + i)
panic("ffs_clusteralloc: lost block");
if (fs->fs_active != 0)
atomic_clear_int(&ACTIVECGNUM(fs, cg), ACTIVECGOFF(cg));
@@ -1344,13 +1547,14 @@ static ino_t
ffs_nodealloccg(ip, cg, ipref, mode)
struct inode *ip;
int cg;
- ufs_daddr_t ipref;
+ ufs2_daddr_t ipref;
int mode;
{
struct fs *fs;
struct cg *cgp;
- struct buf *bp;
+ struct buf *bp, *ibp;
u_int8_t *inosused;
+ struct ufs2_dinode *dp2;
int error, start, len, loc, map, i;
fs = ip->i_fs;
@@ -1368,7 +1572,7 @@ ffs_nodealloccg(ip, cg, ipref, mode)
return (0);
}
bp->b_xflags |= BX_BKGRDWRITE;
- cgp->cg_time = time_second;
+ cgp->cg_old_time = cgp->cg_time = time_second;
inosused = cg_inosused(cgp);
if (ipref) {
ipref %= fs->fs_ipg;
@@ -1414,6 +1618,24 @@ gotit:
fs->fs_cstotal.cs_ndir++;
fs->fs_cs(fs, cg).cs_ndir++;
}
+ /*
+ * Check to see if we need to initialize more inodes.
+ */
+ if (fs->fs_magic == FS_UFS2_MAGIC &&
+ ipref + INOPB(fs) > cgp->cg_initediblk &&
+ cgp->cg_initediblk < cgp->cg_niblk) {
+ ibp = getblk(ip->i_devvp, fsbtodb(fs,
+ ino_to_fsba(fs, cg * fs->fs_ipg + cgp->cg_initediblk)),
+ (int)fs->fs_bsize, 0, 0);
+ bzero(ibp->b_data, (int)fs->fs_bsize);
+ dp2 = (struct ufs2_dinode *)(ibp->b_data);
+ for (i = 0; i < INOPB(fs); i++) {
+ dp2->di_gen = random() / 2 + 1;
+ dp2++;
+ }
+ bawrite(ibp);
+ cgp->cg_initediblk += INOPB(fs);
+ }
if (fs->fs_active != 0)
atomic_clear_int(&ACTIVECGNUM(fs, cg), ACTIVECGOFF(cg));
bdwrite(bp);
@@ -1431,13 +1653,14 @@ void
ffs_blkfree(fs, devvp, bno, size, inum)
struct fs *fs;
struct vnode *devvp;
- ufs_daddr_t bno;
+ ufs2_daddr_t bno;
long size;
ino_t inum;
{
struct cg *cgp;
struct buf *bp;
- ufs_daddr_t fragno, cgbno;
+ ufs1_daddr_t fragno, cgbno;
+ ufs2_daddr_t cgblkno;
int i, error, cg, blk, frags, bbase;
u_int8_t *blksfree;
dev_t dev;
@@ -1446,11 +1669,11 @@ ffs_blkfree(fs, devvp, bno, size, inum)
if (devvp->v_type != VCHR) {
/* devvp is a snapshot */
dev = VTOI(devvp)->i_devvp->v_rdev;
- cgbno = fragstoblks(fs, cgtod(fs, cg));
+ cgblkno = fragstoblks(fs, cgtod(fs, cg));
} else {
/* devvp is a normal disk device */
dev = devvp->v_rdev;
- cgbno = fsbtodb(fs, cgtod(fs, cg));
+ cgblkno = fsbtodb(fs, cgtod(fs, cg));
if ((devvp->v_flag & VCOPYONWRITE) &&
ffs_snapblkfree(fs, devvp, bno, size, inum))
return;
@@ -1462,18 +1685,19 @@ ffs_blkfree(fs, devvp, bno, size, inum)
panic("ffs_blkfree: deallocation on suspended filesystem");
if ((u_int)size > fs->fs_bsize || fragoff(fs, size) != 0 ||
fragnum(fs, bno) + numfrags(fs, size) > fs->fs_frag) {
- printf("dev=%s, bno = %ld, bsize = %ld, size = %ld, fs = %s\n",
- devtoname(dev), (long)bno, (long)fs->fs_bsize,
+ printf("dev=%s, bno = %lld, bsize = %ld, size = %ld, fs = %s\n",
+ devtoname(dev), (intmax_t)bno, (long)fs->fs_bsize,
size, fs->fs_fsmnt);
panic("ffs_blkfree: bad size");
}
#endif
if ((u_int)bno >= fs->fs_size) {
- printf("bad block %ld, ino %lu\n", (long)bno, (u_long)inum);
+ printf("bad block %lld, ino %lu\n", (intmax_t)bno,
+ (u_long)inum);
ffs_fserr(fs, inum, "bad block");
return;
}
- if ((error = bread(devvp, cgbno, (int)fs->fs_cgsize, NOCRED, &bp))) {
+ if ((error = bread(devvp, cgblkno, (int)fs->fs_cgsize, NOCRED, &bp))) {
brelse(bp);
return;
}
@@ -1483,7 +1707,7 @@ ffs_blkfree(fs, devvp, bno, size, inum)
return;
}
bp->b_xflags |= BX_BKGRDWRITE;
- cgp->cg_time = time_second;
+ cgp->cg_old_time = cgp->cg_time = time_second;
cgbno = dtogd(fs, bno);
blksfree = cg_blksfree(cgp);
if (size == fs->fs_bsize) {
@@ -1494,8 +1718,8 @@ ffs_blkfree(fs, devvp, bno, size, inum)
brelse(bp);
return;
}
- printf("dev = %s, block = %ld, fs = %s\n",
- devtoname(dev), (long)bno, fs->fs_fsmnt);
+ printf("dev = %s, block = %lld, fs = %s\n",
+ devtoname(dev), (intmax_t)bno, fs->fs_fsmnt);
panic("ffs_blkfree: freeing free block");
}
ffs_setblock(fs, blksfree, fragno);
@@ -1503,9 +1727,6 @@ ffs_blkfree(fs, devvp, bno, size, inum)
cgp->cg_cs.cs_nbfree++;
fs->fs_cstotal.cs_nbfree++;
fs->fs_cs(fs, cg).cs_nbfree++;
- i = cbtocylno(fs, cgbno);
- cg_blks(fs, cgp, i)[cbtorpos(fs, cgbno)]++;
- cg_blktot(cgp)[i]++;
} else {
bbase = cgbno - fragnum(fs, cgbno);
/*
@@ -1519,8 +1740,8 @@ ffs_blkfree(fs, devvp, bno, size, inum)
frags = numfrags(fs, size);
for (i = 0; i < frags; i++) {
if (isset(blksfree, cgbno + i)) {
- printf("dev = %s, block = %ld, fs = %s\n",
- devtoname(dev), (long)(bno + i),
+ printf("dev = %s, block = %lld, fs = %s\n",
+ devtoname(dev), (intmax_t)(bno + i),
fs->fs_fsmnt);
panic("ffs_blkfree: freeing free frag");
}
@@ -1546,9 +1767,6 @@ ffs_blkfree(fs, devvp, bno, size, inum)
cgp->cg_cs.cs_nbfree++;
fs->fs_cstotal.cs_nbfree++;
fs->fs_cs(fs, cg).cs_nbfree++;
- i = cbtocylno(fs, bbase);
- cg_blks(fs, cgp, i)[cbtorpos(fs, bbase)]++;
- cg_blktot(cgp)[i]++;
}
}
fs->fs_fmod = 1;
@@ -1565,12 +1783,13 @@ ffs_blkfree(fs, devvp, bno, size, inum)
static int
ffs_checkblk(ip, bno, size)
struct inode *ip;
- ufs_daddr_t bno;
+ ufs2_daddr_t bno;
long size;
{
struct fs *fs;
struct cg *cgp;
struct buf *bp;
+ ufs1_daddr_t cgbno;
int i, error, frags, free;
u_int8_t *blksfree;
@@ -1581,7 +1800,7 @@ ffs_checkblk(ip, bno, size)
panic("ffs_checkblk: bad size");
}
if ((u_int)bno >= fs->fs_size)
- panic("ffs_checkblk: bad block %d", bno);
+ panic("ffs_checkblk: bad block %lld", (intmax_t)bno);
error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, dtog(fs, bno))),
(int)fs->fs_cgsize, NOCRED, &bp);
if (error)
@@ -1591,13 +1810,13 @@ ffs_checkblk(ip, bno, size)
panic("ffs_checkblk: cg magic mismatch");
bp->b_xflags |= BX_BKGRDWRITE;
blksfree = cg_blksfree(cgp);
- bno = dtogd(fs, bno);
+ cgbno = dtogd(fs, bno);
if (size == fs->fs_bsize) {
- free = ffs_isblock(fs, blksfree, fragstoblks(fs, bno));
+ free = ffs_isblock(fs, blksfree, fragstoblks(fs, cgbno));
} else {
frags = numfrags(fs, size);
for (free = 0, i = 0; i < frags; i++)
- if (isset(blksfree, bno + i))
+ if (isset(blksfree, cgbno + i))
free++;
if (free != 0 && free != frags)
panic("ffs_checkblk: partially free fragment");
@@ -1636,7 +1855,8 @@ ffs_freefile(fs, devvp, ino, mode)
{
struct cg *cgp;
struct buf *bp;
- int error, cgbno, cg;
+ ufs2_daddr_t cgbno;
+ int error, cg;
u_int8_t *inosused;
dev_t dev;
@@ -1663,7 +1883,7 @@ ffs_freefile(fs, devvp, ino, mode)
return (0);
}
bp->b_xflags |= BX_BKGRDWRITE;
- cgp->cg_time = time_second;
+ cgp->cg_old_time = cgp->cg_time = time_second;
inosused = cg_inosused(cgp);
ino %= fs->fs_ipg;
if (isclr(inosused, ino)) {
@@ -1696,14 +1916,14 @@ ffs_freefile(fs, devvp, ino, mode)
* It is a panic if a request is made to find a block if none are
* available.
*/
-static ufs_daddr_t
+static ufs1_daddr_t
ffs_mapsearch(fs, cgp, bpref, allocsiz)
struct fs *fs;
struct cg *cgp;
- ufs_daddr_t bpref;
+ ufs2_daddr_t bpref;
int allocsiz;
{
- ufs_daddr_t bno;
+ ufs1_daddr_t bno;
int start, len, loc, i;
int blk, field, subfield, pos;
u_int8_t *blksfree;
@@ -1766,7 +1986,7 @@ void
ffs_clusteracct(fs, cgp, blkno, cnt)
struct fs *fs;
struct cg *cgp;
- ufs_daddr_t blkno;
+ ufs1_daddr_t blkno;
int cnt;
{
int32_t *sump;
@@ -1925,7 +2145,7 @@ sysctl_ffs_fsck(SYSCTL_HANDLER_ARGS)
struct inode *ip;
struct mount *mp;
struct fs *fs;
- ufs_daddr_t blkno;
+ ufs2_daddr_t blkno;
long blkcnt, blksize;
struct file *fp;
int filetype, error;
@@ -1979,6 +2199,7 @@ sysctl_ffs_fsck(SYSCTL_HANDLER_ARGS)
break;
ip = VTOI(vp);
ip->i_nlink += cmd.size;
+ DIP(ip, i_nlink) = ip->i_nlink;
ip->i_effnlink += cmd.size;
ip->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(vp))
@@ -1997,7 +2218,7 @@ sysctl_ffs_fsck(SYSCTL_HANDLER_ARGS)
if ((error = VFS_VGET(mp, (ino_t)cmd.value, LK_EXCLUSIVE, &vp)))
break;
ip = VTOI(vp);
- ip->i_blocks += cmd.size;
+ DIP(ip, i_blocks) += cmd.size;
ip->i_flag |= IN_CHANGE;
vput(vp);
break;
@@ -2035,17 +2256,17 @@ sysctl_ffs_fsck(SYSCTL_HANDLER_ARGS)
#ifdef DEBUG
if (fsckcmds) {
if (cmd.size == 1)
- printf("%s: free block %d\n",
+ printf("%s: free block %lld\n",
mp->mnt_stat.f_mntonname,
- (ufs_daddr_t)cmd.value);
+ (intmax_t)cmd.value);
else
- printf("%s: free blocks %d-%ld\n",
+ printf("%s: free blocks %lld-%lld\n",
mp->mnt_stat.f_mntonname,
- (ufs_daddr_t)cmd.value,
- (ufs_daddr_t)cmd.value + cmd.size - 1);
+ (intmax_t)cmd.value,
+ (intmax_t)cmd.value + cmd.size - 1);
}
#endif /* DEBUG */
- blkno = (ufs_daddr_t)cmd.value;
+ blkno = cmd.value;
blkcnt = cmd.size;
blksize = fs->fs_frag - (blkno % fs->fs_frag);
while (blkcnt > 0) {
diff --git a/sys/ufs/ffs/ffs_balloc.c b/sys/ufs/ffs/ffs_balloc.c
index b2e3595dd026..6b00abd84000 100644
--- a/sys/ufs/ffs/ffs_balloc.c
+++ b/sys/ufs/ffs/ffs_balloc.c
@@ -1,4 +1,16 @@
/*
+ * Copyright (c) 2002 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by Marshall
+ * Kirk McKusick and Network Associates Laboratories, the Security
+ * Research Division of Network Associates, Inc. under DARPA/SPAWAR
+ * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
+ * research program
+ *
+ * Copyright (c) 1982, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
* Copyright (c) 1982, 1986, 1989, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -53,60 +65,402 @@
* Balloc defines the structure of filesystem storage
* by allocating the physical blocks on a device given
* the inode and the logical block number in a file.
+ * This is the allocation strategy for UFS1. Below is
+ * the allocation strategy for UFS2.
+ */
+int
+ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size,
+ struct ucred *cred, int flags, struct buf **bpp)
+{
+ struct inode *ip;
+ ufs_lbn_t lbn, lastlbn;
+ struct fs *fs;
+ ufs1_daddr_t nb;
+ struct buf *bp, *nbp;
+ struct indir indirs[NIADDR + 2];
+ int deallocated, osize, nsize, num, i, error;
+ ufs2_daddr_t newb;
+ ufs1_daddr_t *bap, pref;
+ ufs1_daddr_t *allocib, *blkp, *allocblk, allociblk[NIADDR + 1];
+ int unwindidx = -1;
+ struct thread *td = curthread; /* XXX */
+
+ ip = VTOI(vp);
+ fs = ip->i_fs;
+ lbn = lblkno(fs, startoffset);
+ size = blkoff(fs, startoffset) + size;
+ if (size > fs->fs_bsize)
+ panic("ffs_balloc_ufs1: blk too big");
+ *bpp = NULL;
+ if (lbn < 0)
+ return (EFBIG);
+
+ /*
+ * If the next write will extend the file into a new block,
+ * and the file is currently composed of a fragment
+ * this fragment has to be extended to be a full block.
+ */
+ lastlbn = lblkno(fs, ip->i_size);
+ if (lastlbn < NDADDR && lastlbn < lbn) {
+ nb = lastlbn;
+ osize = blksize(fs, ip, nb);
+ if (osize < fs->fs_bsize && osize > 0) {
+ error = ffs_realloccg(ip, nb,
+ ffs_blkpref_ufs1(ip, lastlbn, (int)nb,
+ &ip->i_din1->di_db[0]),
+ osize, (int)fs->fs_bsize, cred, &bp);
+ if (error)
+ return (error);
+ if (DOINGSOFTDEP(vp))
+ softdep_setup_allocdirect(ip, nb,
+ dbtofsb(fs, bp->b_blkno),
+ ip->i_din1->di_db[nb],
+ fs->fs_bsize, osize, bp);
+ ip->i_size = smalllblktosize(fs, nb + 1);
+ ip->i_din1->di_size = ip->i_size;
+ ip->i_din1->di_db[nb] = dbtofsb(fs, bp->b_blkno);
+ ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ if (flags & B_SYNC)
+ bwrite(bp);
+ else
+ bawrite(bp);
+ }
+ }
+ /*
+ * The first NDADDR blocks are direct blocks
+ */
+ if (lbn < NDADDR) {
+ if (flags & B_METAONLY)
+ panic("ffs_balloc_ufs1: B_METAONLY for direct block");
+ nb = ip->i_din1->di_db[lbn];
+ if (nb != 0 && ip->i_size >= smalllblktosize(fs, lbn + 1)) {
+ error = bread(vp, lbn, fs->fs_bsize, NOCRED, &bp);
+ if (error) {
+ brelse(bp);
+ return (error);
+ }
+ bp->b_blkno = fsbtodb(fs, nb);
+ *bpp = bp;
+ return (0);
+ }
+ if (nb != 0) {
+ /*
+ * Consider need to reallocate a fragment.
+ */
+ osize = fragroundup(fs, blkoff(fs, ip->i_size));
+ nsize = fragroundup(fs, size);
+ if (nsize <= osize) {
+ error = bread(vp, lbn, osize, NOCRED, &bp);
+ if (error) {
+ brelse(bp);
+ return (error);
+ }
+ bp->b_blkno = fsbtodb(fs, nb);
+ } else {
+ error = ffs_realloccg(ip, lbn,
+ ffs_blkpref_ufs1(ip, lbn, (int)lbn,
+ &ip->i_din1->di_db[0]),
+ osize, nsize, cred, &bp);
+ if (error)
+ return (error);
+ if (DOINGSOFTDEP(vp))
+ softdep_setup_allocdirect(ip, lbn,
+ dbtofsb(fs, bp->b_blkno), nb,
+ nsize, osize, bp);
+ }
+ } else {
+ if (ip->i_size < smalllblktosize(fs, lbn + 1))
+ nsize = fragroundup(fs, size);
+ else
+ nsize = fs->fs_bsize;
+ error = ffs_alloc(ip, lbn,
+ ffs_blkpref_ufs1(ip, lbn, (int)lbn,
+ &ip->i_din1->di_db[0]),
+ nsize, cred, &newb);
+ if (error)
+ return (error);
+ bp = getblk(vp, lbn, nsize, 0, 0);
+ bp->b_blkno = fsbtodb(fs, newb);
+ if (flags & B_CLRBUF)
+ vfs_bio_clrbuf(bp);
+ if (DOINGSOFTDEP(vp))
+ softdep_setup_allocdirect(ip, lbn, newb, 0,
+ nsize, 0, bp);
+ }
+ ip->i_din1->di_db[lbn] = dbtofsb(fs, bp->b_blkno);
+ ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ *bpp = bp;
+ return (0);
+ }
+ /*
+ * Determine the number of levels of indirection.
+ */
+ pref = 0;
+ if ((error = ufs_getlbns(vp, lbn, indirs, &num)) != 0)
+ return(error);
+#ifdef DIAGNOSTIC
+ if (num < 1)
+ panic ("ffs_balloc_ufs1: ufs_getlbns returned indirect block");
+#endif
+ /*
+ * Fetch the first indirect block allocating if necessary.
+ */
+ --num;
+ nb = ip->i_din1->di_ib[indirs[0].in_off];
+ allocib = NULL;
+ allocblk = allociblk;
+ if (nb == 0) {
+ pref = ffs_blkpref_ufs1(ip, lbn, 0, (ufs1_daddr_t *)0);
+ if ((error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize,
+ cred, &newb)) != 0)
+ return (error);
+ nb = newb;
+ *allocblk++ = nb;
+ bp = getblk(vp, indirs[1].in_lbn, fs->fs_bsize, 0, 0);
+ bp->b_blkno = fsbtodb(fs, nb);
+ vfs_bio_clrbuf(bp);
+ if (DOINGSOFTDEP(vp)) {
+ softdep_setup_allocdirect(ip, NDADDR + indirs[0].in_off,
+ newb, 0, fs->fs_bsize, 0, bp);
+ bdwrite(bp);
+ } else {
+ /*
+ * Write synchronously so that indirect blocks
+ * never point at garbage.
+ */
+ if (DOINGASYNC(vp))
+ bdwrite(bp);
+ else if ((error = bwrite(bp)) != 0)
+ goto fail;
+ }
+ allocib = &ip->i_din1->di_ib[indirs[0].in_off];
+ *allocib = nb;
+ ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ }
+ /*
+ * Fetch through the indirect blocks, allocating as necessary.
+ */
+ for (i = 1;;) {
+ error = bread(vp,
+ indirs[i].in_lbn, (int)fs->fs_bsize, NOCRED, &bp);
+ if (error) {
+ brelse(bp);
+ goto fail;
+ }
+ bap = (ufs1_daddr_t *)bp->b_data;
+ nb = bap[indirs[i].in_off];
+ if (i == num)
+ break;
+ i += 1;
+ if (nb != 0) {
+ bqrelse(bp);
+ continue;
+ }
+ if (pref == 0)
+ pref = ffs_blkpref_ufs1(ip, lbn, 0, (ufs1_daddr_t *)0);
+ if ((error =
+ ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred, &newb)) != 0) {
+ brelse(bp);
+ goto fail;
+ }
+ nb = newb;
+ *allocblk++ = nb;
+ nbp = getblk(vp, indirs[i].in_lbn, fs->fs_bsize, 0, 0);
+ nbp->b_blkno = fsbtodb(fs, nb);
+ vfs_bio_clrbuf(nbp);
+ if (DOINGSOFTDEP(vp)) {
+ softdep_setup_allocindir_meta(nbp, ip, bp,
+ indirs[i - 1].in_off, nb);
+ bdwrite(nbp);
+ } else {
+ /*
+ * Write synchronously so that indirect blocks
+ * never point at garbage.
+ */
+ if ((error = bwrite(nbp)) != 0) {
+ brelse(bp);
+ goto fail;
+ }
+ }
+ bap[indirs[i - 1].in_off] = nb;
+ if (allocib == NULL && unwindidx < 0)
+ unwindidx = i - 1;
+ /*
+ * If required, write synchronously, otherwise use
+ * delayed write.
+ */
+ if (flags & B_SYNC) {
+ bwrite(bp);
+ } else {
+ if (bp->b_bufsize == fs->fs_bsize)
+ bp->b_flags |= B_CLUSTEROK;
+ bdwrite(bp);
+ }
+ }
+ /*
+ * If asked only for the indirect block, then return it.
+ */
+ if (flags & B_METAONLY) {
+ *bpp = bp;
+ return (0);
+ }
+ /*
+ * Get the data block, allocating if necessary.
+ */
+ if (nb == 0) {
+ pref = ffs_blkpref_ufs1(ip, lbn, indirs[i].in_off, &bap[0]);
+ error = ffs_alloc(ip,
+ lbn, pref, (int)fs->fs_bsize, cred, &newb);
+ if (error) {
+ brelse(bp);
+ goto fail;
+ }
+ nb = newb;
+ *allocblk++ = nb;
+ nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0);
+ nbp->b_blkno = fsbtodb(fs, nb);
+ if (flags & B_CLRBUF)
+ vfs_bio_clrbuf(nbp);
+ if (DOINGSOFTDEP(vp))
+ softdep_setup_allocindir_page(ip, lbn, bp,
+ indirs[i].in_off, nb, 0, nbp);
+ bap[indirs[i].in_off] = nb;
+ /*
+ * If required, write synchronously, otherwise use
+ * delayed write.
+ */
+ if (flags & B_SYNC) {
+ bwrite(bp);
+ } else {
+ if (bp->b_bufsize == fs->fs_bsize)
+ bp->b_flags |= B_CLUSTEROK;
+ bdwrite(bp);
+ }
+ *bpp = nbp;
+ return (0);
+ }
+ brelse(bp);
+ if (flags & B_CLRBUF) {
+ error = bread(vp, lbn, (int)fs->fs_bsize, NOCRED, &nbp);
+ if (error) {
+ brelse(nbp);
+ goto fail;
+ }
+ } else {
+ nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0);
+ nbp->b_blkno = fsbtodb(fs, nb);
+ }
+ *bpp = nbp;
+ return (0);
+fail:
+ /*
+ * If we have failed part way through block allocation, we
+ * have to deallocate any indirect blocks that we have allocated.
+ * We have to fsync the file before we start to get rid of all
+ * of its dependencies so that we do not leave them dangling.
+ * We have to sync it at the end so that the soft updates code
+ * does not find any untracked changes. Although this is really
+ * slow, running out of disk space is not expected to be a common
+ * occurence. The error return from fsync is ignored as we already
+ * have an error to return to the user.
+ */
+ (void) VOP_FSYNC(vp, cred, MNT_WAIT, td);
+ for (deallocated = 0, blkp = allociblk; blkp < allocblk; blkp++) {
+ ffs_blkfree(fs, ip->i_devvp, *blkp, fs->fs_bsize, ip->i_number);
+ deallocated += fs->fs_bsize;
+ }
+ if (allocib != NULL) {
+ *allocib = 0;
+ } else if (unwindidx >= 0) {
+ int r;
+
+ r = bread(vp, indirs[unwindidx].in_lbn,
+ (int)fs->fs_bsize, NOCRED, &bp);
+ if (r) {
+ panic("Could not unwind indirect block, error %d", r);
+ brelse(bp);
+ } else {
+ bap = (ufs1_daddr_t *)bp->b_data;
+ bap[indirs[unwindidx].in_off] = 0;
+ if (flags & B_SYNC) {
+ bwrite(bp);
+ } else {
+ if (bp->b_bufsize == fs->fs_bsize)
+ bp->b_flags |= B_CLUSTEROK;
+ bdwrite(bp);
+ }
+ }
+ }
+ if (deallocated) {
+#ifdef QUOTA
+ /*
+ * Restore user's disk quota because allocation failed.
+ */
+ (void) chkdq(ip, -btodb(deallocated), cred, FORCE);
+#endif
+ ip->i_din1->di_blocks -= btodb(deallocated);
+ ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ }
+ (void) VOP_FSYNC(vp, cred, MNT_WAIT, td);
+ return (error);
+}
+
+/*
+ * Balloc defines the structure of file system storage
+ * by allocating the physical blocks on a device given
+ * the inode and the logical block number in a file.
+ * This is the allocation strategy for UFS2. Above is
+ * the allocation strategy for UFS1.
*/
int
-ffs_balloc(struct vnode *a_vp, off_t a_startoffset, int a_size,
- struct ucred *a_cred, int a_flags, struct buf **a_bpp)
+ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size,
+ struct ucred *cred, int flags, struct buf **bpp)
{
struct inode *ip;
- ufs_daddr_t lbn;
- int size;
- struct ucred *cred;
- int flags;
+ ufs_lbn_t lbn, lastlbn;
struct fs *fs;
- ufs_daddr_t nb;
struct buf *bp, *nbp;
- struct vnode *vp;
struct indir indirs[NIADDR + 2];
- ufs_daddr_t newb, *bap, pref;
+ ufs2_daddr_t nb, newb, *bap, pref;
+ ufs2_daddr_t *allocib, *blkp, *allocblk, allociblk[NIADDR + 1];
int deallocated, osize, nsize, num, i, error;
- ufs_daddr_t *allocib, *blkp, *allocblk, allociblk[NIADDR + 1];
int unwindidx = -1;
struct thread *td = curthread; /* XXX */
- vp = a_vp;
ip = VTOI(vp);
fs = ip->i_fs;
- lbn = lblkno(fs, a_startoffset);
- size = blkoff(fs, a_startoffset) + a_size;
+ lbn = lblkno(fs, startoffset);
+ size = blkoff(fs, startoffset) + size;
if (size > fs->fs_bsize)
- panic("ffs_balloc: blk too big");
- *a_bpp = NULL;
+ panic("ffs_balloc_ufs2: blk too big");
+ *bpp = NULL;
if (lbn < 0)
return (EFBIG);
- cred = a_cred;
- flags = a_flags;
/*
* If the next write will extend the file into a new block,
* and the file is currently composed of a fragment
* this fragment has to be extended to be a full block.
*/
- nb = lblkno(fs, ip->i_size);
- if (nb < NDADDR && nb < lbn) {
+ lastlbn = lblkno(fs, ip->i_size);
+ if (lastlbn < NDADDR && lastlbn < lbn) {
+ nb = lastlbn;
osize = blksize(fs, ip, nb);
if (osize < fs->fs_bsize && osize > 0) {
error = ffs_realloccg(ip, nb,
- ffs_blkpref(ip, nb, (int)nb, &ip->i_db[0]),
+ ffs_blkpref_ufs2(ip, lastlbn, (int)nb,
+ &ip->i_din2->di_db[0]),
osize, (int)fs->fs_bsize, cred, &bp);
if (error)
return (error);
if (DOINGSOFTDEP(vp))
softdep_setup_allocdirect(ip, nb,
- dbtofsb(fs, bp->b_blkno), ip->i_db[nb],
+ dbtofsb(fs, bp->b_blkno),
+ ip->i_din2->di_db[nb],
fs->fs_bsize, osize, bp);
ip->i_size = smalllblktosize(fs, nb + 1);
- ip->i_db[nb] = dbtofsb(fs, bp->b_blkno);
+ ip->i_din2->di_size = ip->i_size;
+ ip->i_din2->di_db[nb] = dbtofsb(fs, bp->b_blkno);
ip->i_flag |= IN_CHANGE | IN_UPDATE;
if (flags & B_SYNC)
bwrite(bp);
@@ -119,8 +473,8 @@ ffs_balloc(struct vnode *a_vp, off_t a_startoffset, int a_size,
*/
if (lbn < NDADDR) {
if (flags & B_METAONLY)
- panic("ffs_balloc: B_METAONLY for direct block");
- nb = ip->i_db[lbn];
+ panic("ffs_balloc_ufs2: B_METAONLY for direct block");
+ nb = ip->i_din2->di_db[lbn];
if (nb != 0 && ip->i_size >= smalllblktosize(fs, lbn + 1)) {
error = bread(vp, lbn, fs->fs_bsize, NOCRED, &bp);
if (error) {
@@ -128,7 +482,7 @@ ffs_balloc(struct vnode *a_vp, off_t a_startoffset, int a_size,
return (error);
}
bp->b_blkno = fsbtodb(fs, nb);
- *a_bpp = bp;
+ *bpp = bp;
return (0);
}
if (nb != 0) {
@@ -146,8 +500,9 @@ ffs_balloc(struct vnode *a_vp, off_t a_startoffset, int a_size,
bp->b_blkno = fsbtodb(fs, nb);
} else {
error = ffs_realloccg(ip, lbn,
- ffs_blkpref(ip, lbn, (int)lbn,
- &ip->i_db[0]), osize, nsize, cred, &bp);
+ ffs_blkpref_ufs2(ip, lbn, (int)lbn,
+ &ip->i_din2->di_db[0]),
+ osize, nsize, cred, &bp);
if (error)
return (error);
if (DOINGSOFTDEP(vp))
@@ -161,7 +516,8 @@ ffs_balloc(struct vnode *a_vp, off_t a_startoffset, int a_size,
else
nsize = fs->fs_bsize;
error = ffs_alloc(ip, lbn,
- ffs_blkpref(ip, lbn, (int)lbn, &ip->i_db[0]),
+ ffs_blkpref_ufs2(ip, lbn, (int)lbn,
+ &ip->i_din2->di_db[0]),
nsize, cred, &newb);
if (error)
return (error);
@@ -173,9 +529,9 @@ ffs_balloc(struct vnode *a_vp, off_t a_startoffset, int a_size,
softdep_setup_allocdirect(ip, lbn, newb, 0,
nsize, 0, bp);
}
- ip->i_db[lbn] = dbtofsb(fs, bp->b_blkno);
+ ip->i_din2->di_db[lbn] = dbtofsb(fs, bp->b_blkno);
ip->i_flag |= IN_CHANGE | IN_UPDATE;
- *a_bpp = bp;
+ *bpp = bp;
return (0);
}
/*
@@ -186,17 +542,17 @@ ffs_balloc(struct vnode *a_vp, off_t a_startoffset, int a_size,
return(error);
#ifdef DIAGNOSTIC
if (num < 1)
- panic ("ffs_balloc: ufs_bmaparray returned indirect block");
+ panic ("ffs_balloc_ufs2: ufs_getlbns returned indirect block");
#endif
/*
* Fetch the first indirect block allocating if necessary.
*/
--num;
- nb = ip->i_ib[indirs[0].in_off];
+ nb = ip->i_din2->di_ib[indirs[0].in_off];
allocib = NULL;
allocblk = allociblk;
if (nb == 0) {
- pref = ffs_blkpref(ip, lbn, 0, (ufs_daddr_t *)0);
+ pref = ffs_blkpref_ufs2(ip, lbn, 0, (ufs2_daddr_t *)0);
if ((error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize,
cred, &newb)) != 0)
return (error);
@@ -219,7 +575,7 @@ ffs_balloc(struct vnode *a_vp, off_t a_startoffset, int a_size,
else if ((error = bwrite(bp)) != 0)
goto fail;
}
- allocib = &ip->i_ib[indirs[0].in_off];
+ allocib = &ip->i_din2->di_ib[indirs[0].in_off];
*allocib = nb;
ip->i_flag |= IN_CHANGE | IN_UPDATE;
}
@@ -233,7 +589,7 @@ ffs_balloc(struct vnode *a_vp, off_t a_startoffset, int a_size,
brelse(bp);
goto fail;
}
- bap = (ufs_daddr_t *)bp->b_data;
+ bap = (ufs2_daddr_t *)bp->b_data;
nb = bap[indirs[i].in_off];
if (i == num)
break;
@@ -243,7 +599,7 @@ ffs_balloc(struct vnode *a_vp, off_t a_startoffset, int a_size,
continue;
}
if (pref == 0)
- pref = ffs_blkpref(ip, lbn, 0, (ufs_daddr_t *)0);
+ pref = ffs_blkpref_ufs2(ip, lbn, 0, (ufs2_daddr_t *)0);
if ((error =
ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred, &newb)) != 0) {
brelse(bp);
@@ -287,14 +643,14 @@ ffs_balloc(struct vnode *a_vp, off_t a_startoffset, int a_size,
* If asked only for the indirect block, then return it.
*/
if (flags & B_METAONLY) {
- *a_bpp = bp;
+ *bpp = bp;
return (0);
}
/*
* Get the data block, allocating if necessary.
*/
if (nb == 0) {
- pref = ffs_blkpref(ip, lbn, indirs[i].in_off, &bap[0]);
+ pref = ffs_blkpref_ufs2(ip, lbn, indirs[i].in_off, &bap[0]);
error = ffs_alloc(ip,
lbn, pref, (int)fs->fs_bsize, cred, &newb);
if (error) {
@@ -322,7 +678,7 @@ ffs_balloc(struct vnode *a_vp, off_t a_startoffset, int a_size,
bp->b_flags |= B_CLUSTEROK;
bdwrite(bp);
}
- *a_bpp = nbp;
+ *bpp = nbp;
return (0);
}
brelse(bp);
@@ -336,7 +692,7 @@ ffs_balloc(struct vnode *a_vp, off_t a_startoffset, int a_size,
nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0);
nbp->b_blkno = fsbtodb(fs, nb);
}
- *a_bpp = nbp;
+ *bpp = nbp;
return (0);
fail:
/*
@@ -366,7 +722,7 @@ fail:
panic("Could not unwind indirect block, error %d", r);
brelse(bp);
} else {
- bap = (ufs_daddr_t *)bp->b_data;
+ bap = (ufs2_daddr_t *)bp->b_data;
bap[indirs[unwindidx].in_off] = 0;
if (flags & B_SYNC) {
bwrite(bp);
@@ -382,9 +738,9 @@ fail:
/*
* Restore user's disk quota because allocation failed.
*/
- (void) chkdq(ip, (long)-btodb(deallocated), cred, FORCE);
+ (void) chkdq(ip, -btodb(deallocated), cred, FORCE);
#endif
- ip->i_blocks -= btodb(deallocated);
+ ip->i_din2->di_blocks -= btodb(deallocated);
ip->i_flag |= IN_CHANGE | IN_UPDATE;
}
(void) VOP_FSYNC(vp, cred, MNT_WAIT, td);
diff --git a/sys/ufs/ffs/ffs_extern.h b/sys/ufs/ffs/ffs_extern.h
index bbb12ab384fa..8274765ef89d 100644
--- a/sys/ufs/ffs/ffs_extern.h
+++ b/sys/ufs/ffs/ffs_extern.h
@@ -49,26 +49,30 @@ struct sockaddr;
struct statfs;
struct ucred;
struct vnode;
-struct vop_balloc_args;
struct vop_fsync_args;
struct vop_reallocblks_args;
struct vop_copyonwrite_args;
int ffs_alloc(struct inode *,
- ufs_daddr_t, ufs_daddr_t, int, struct ucred *, ufs_daddr_t *);
-int ffs_balloc(struct vnode *a_vp, off_t a_startoffset, int a_size,
+ ufs2_daddr_t, ufs2_daddr_t, int, struct ucred *, ufs2_daddr_t *);
+int ffs_balloc_ufs1(struct vnode *a_vp, off_t a_startoffset, int a_size,
+ struct ucred *a_cred, int a_flags, struct buf **a_bpp);
+int ffs_balloc_ufs2(struct vnode *a_vp, off_t a_startoffset, int a_size,
struct ucred *a_cred, int a_flags, struct buf **a_bpp);
int ffs_blkatoff(struct vnode *, off_t, char **, struct buf **);
-void ffs_blkfree(struct fs *, struct vnode *, ufs_daddr_t, long, ino_t);
-ufs_daddr_t ffs_blkpref(struct inode *, ufs_daddr_t, int, ufs_daddr_t *);
-void ffs_clrblock(struct fs *, u_char *, ufs_daddr_t);
-void ffs_clusteracct (struct fs *, struct cg *, ufs_daddr_t, int);
+void ffs_blkfree(struct fs *, struct vnode *, ufs2_daddr_t, long, ino_t);
+ufs2_daddr_t ffs_blkpref_ufs1(struct inode *, ufs_lbn_t, int, ufs1_daddr_t *);
+ufs2_daddr_t ffs_blkpref_ufs2(struct inode *, ufs_lbn_t, int, ufs2_daddr_t *);
+void ffs_clrblock(struct fs *, u_char *, ufs1_daddr_t);
+void ffs_clusteracct (struct fs *, struct cg *, ufs1_daddr_t, int);
int ffs_fhtovp(struct mount *, struct fid *, struct vnode **);
int ffs_flushfiles(struct mount *, int, struct thread *);
void ffs_fragacct(struct fs *, int, int32_t [], int);
int ffs_freefile(struct fs *, struct vnode *, ino_t, int );
-int ffs_isblock(struct fs *, u_char *, ufs_daddr_t);
-int ffs_isfreeblock(struct fs *, unsigned char *, ufs_daddr_t);
+int ffs_isblock(struct fs *, u_char *, ufs1_daddr_t);
+int ffs_isfreeblock(struct fs *, unsigned char *, ufs1_daddr_t);
+void ffs_load_inode(struct buf *, struct inode *, struct malloc_type *,
+ struct fs *, ino_t);
int ffs_mountfs(struct vnode *, struct mount *, struct thread *,
struct malloc_type *);
int ffs_mountroot(void);
@@ -76,9 +80,9 @@ int ffs_mount(struct mount *, char *, caddr_t, struct nameidata *,
struct thread *);
int ffs_reallocblks(struct vop_reallocblks_args *);
int ffs_realloccg(struct inode *,
- ufs_daddr_t, ufs_daddr_t, int, int, struct ucred *, struct buf **);
-void ffs_setblock(struct fs *, u_char *, ufs_daddr_t);
-int ffs_snapblkfree(struct fs *, struct vnode *, ufs_daddr_t, long, ino_t);
+ ufs2_daddr_t, ufs2_daddr_t, int, int, struct ucred *, struct buf **);
+void ffs_setblock(struct fs *, u_char *, ufs1_daddr_t);
+int ffs_snapblkfree(struct fs *, struct vnode *, ufs2_daddr_t, long, ino_t);
void ffs_snapremove(struct vnode *vp);
int ffs_snapshot(struct mount *mp, char *snapfile);
void ffs_snapshot_mount(struct mount *mp);
@@ -112,13 +116,13 @@ void softdep_freefile(struct vnode *, ino_t, int);
int softdep_request_cleanup(struct fs *, struct vnode *);
void softdep_setup_freeblocks(struct inode *, off_t);
void softdep_setup_inomapdep(struct buf *, struct inode *, ino_t);
-void softdep_setup_blkmapdep(struct buf *, struct fs *, ufs_daddr_t);
-void softdep_setup_allocdirect(struct inode *, ufs_lbn_t, ufs_daddr_t,
- ufs_daddr_t, long, long, struct buf *);
+void softdep_setup_blkmapdep(struct buf *, struct fs *, ufs2_daddr_t);
+void softdep_setup_allocdirect(struct inode *, ufs_lbn_t, ufs2_daddr_t,
+ ufs2_daddr_t, long, long, struct buf *);
void softdep_setup_allocindir_meta(struct buf *, struct inode *,
- struct buf *, int, ufs_daddr_t);
+ struct buf *, int, ufs2_daddr_t);
void softdep_setup_allocindir_page(struct inode *, ufs_lbn_t,
- struct buf *, int, ufs_daddr_t, ufs_daddr_t, struct buf *);
+ struct buf *, int, ufs2_daddr_t, ufs2_daddr_t, struct buf *);
void softdep_fsync_mountdev(struct vnode *);
int softdep_sync_metadata(struct vop_fsync_args *);
/* XXX incorrectly moved to mount.h - should be indirect function */
diff --git a/sys/ufs/ffs/ffs_inode.c b/sys/ufs/ffs/ffs_inode.c
index 215cc851ff69..fe9af1ea722b 100644
--- a/sys/ufs/ffs/ffs_inode.c
+++ b/sys/ufs/ffs/ffs_inode.c
@@ -60,8 +60,8 @@
#include <ufs/ffs/fs.h>
#include <ufs/ffs/ffs_extern.h>
-static int ffs_indirtrunc(struct inode *, ufs_daddr_t, ufs_daddr_t,
- ufs_daddr_t, int, long *);
+static int ffs_indirtrunc(struct inode *, ufs2_daddr_t, ufs2_daddr_t,
+ ufs2_daddr_t, int, ufs2_daddr_t *);
/*
* Update the access, modified, and inode change times as specified by the
@@ -94,9 +94,10 @@ ffs_update(vp, waitfor)
* Ensure that uid and gid are correct. This is a temporary
* fix until fsck has been changed to do the update.
*/
- if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
- ip->i_din.di_ouid = ip->i_uid; /* XXX */
- ip->i_din.di_ogid = ip->i_gid; /* XXX */
+ if (fs->fs_magic == FS_UFS1_MAGIC && /* XXX */
+ fs->fs_old_inodefmt < FS_44INODEFMT) { /* XXX */
+ ip->i_din1->di_ouid = ip->i_uid; /* XXX */
+ ip->i_din1->di_ogid = ip->i_gid; /* XXX */
} /* XXX */
error = bread(ip->i_devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
(int)fs->fs_bsize, NOCRED, &bp);
@@ -108,8 +109,12 @@ ffs_update(vp, waitfor)
softdep_update_inodeblock(ip, bp, waitfor);
else if (ip->i_effnlink != ip->i_nlink)
panic("ffs_update: bad link cnt");
- *((struct dinode *)bp->b_data +
- ino_to_fsbo(fs, ip->i_number)) = ip->i_din;
+ if (ip->i_ump->um_fstype == UFS1)
+ *((struct ufs1_dinode *)bp->b_data +
+ ino_to_fsbo(fs, ip->i_number)) = *ip->i_din1;
+ else
+ *((struct ufs2_dinode *)bp->b_data +
+ ino_to_fsbo(fs, ip->i_number)) = *ip->i_din2;
if (waitfor && !DOINGASYNC(vp)) {
return (bwrite(bp));
} else if (vm_page_count_severe() || buf_dirty_count_severe()) {
@@ -138,16 +143,14 @@ ffs_truncate(vp, length, flags, cred, td)
struct thread *td;
{
struct vnode *ovp = vp;
- ufs_daddr_t lastblock;
struct inode *oip;
- ufs_daddr_t bn, lbn, lastiblock[NIADDR], indir_lbn[NIADDR];
- ufs_daddr_t oldblks[NDADDR + NIADDR], newblks[NDADDR + NIADDR];
+ ufs2_daddr_t bn, lbn, lastblock, lastiblock[NIADDR], indir_lbn[NIADDR];
+ ufs2_daddr_t oldblks[NDADDR + NIADDR], newblks[NDADDR + NIADDR];
+ ufs2_daddr_t count, blocksreleased = 0;
struct fs *fs;
struct buf *bp;
- int offset, size, level;
- long count, nblocks, blocksreleased = 0;
- int i;
- int aflags, error, allerror;
+ int offset, size, level, nblocks;
+ int i, aflags, error, allerror;
off_t osize;
oip = VTOI(ovp);
@@ -157,13 +160,15 @@ ffs_truncate(vp, length, flags, cred, td)
if (length > fs->fs_maxfilesize)
return (EFBIG);
if (ovp->v_type == VLNK &&
- (oip->i_size < ovp->v_mount->mnt_maxsymlinklen || oip->i_din.di_blocks == 0)) {
+ (oip->i_size < ovp->v_mount->mnt_maxsymlinklen ||
+ DIP(oip, i_blocks) == 0)) {
#ifdef DIAGNOSTIC
if (length != 0)
panic("ffs_truncate: partial truncate of symlink");
#endif
- bzero((char *)&oip->i_shortlink, (u_int)oip->i_size);
+ bzero(SHORTLINK(oip), (u_int)oip->i_size);
oip->i_size = 0;
+ DIP(oip, i_size) = 0;
oip->i_flag |= IN_CHANGE | IN_UPDATE;
return (UFS_UPDATE(ovp, 1));
}
@@ -196,10 +201,10 @@ ffs_truncate(vp, length, flags, cred, td)
td)) != 0)
return (error);
if (oip->i_flag & IN_SPACECOUNTED)
- fs->fs_pendingblocks -= oip->i_blocks;
+ fs->fs_pendingblocks -= DIP(oip, i_blocks);
} else {
#ifdef QUOTA
- (void) chkdq(oip, -oip->i_blocks, NOCRED, 0);
+ (void) chkdq(oip, -DIP(oip, i_blocks), NOCRED, 0);
#endif
softdep_setup_freeblocks(oip, length);
vinvalbuf(ovp, 0, cred, td, 0, 0);
@@ -223,6 +228,7 @@ ffs_truncate(vp, length, flags, cred, td)
if (error)
return (error);
oip->i_size = length;
+ DIP(oip, i_size) = length;
if (bp->b_bufsize == fs->fs_bsize)
bp->b_flags |= B_CLUSTEROK;
if (aflags & B_SYNC)
@@ -243,6 +249,7 @@ ffs_truncate(vp, length, flags, cred, td)
offset = blkoff(fs, length);
if (offset == 0) {
oip->i_size = length;
+ DIP(oip, i_size) = length;
} else {
lbn = lblkno(fs, length);
aflags = B_CLRBUF;
@@ -265,6 +272,7 @@ ffs_truncate(vp, length, flags, cred, td)
(error = VOP_FSYNC(ovp, cred, MNT_WAIT, td)) != 0)
return (error);
oip->i_size = length;
+ DIP(oip, i_size) = length;
size = blksize(fs, oip, lbn);
if (ovp->v_type != VDIR)
bzero((char *)bp->b_data + offset,
@@ -295,14 +303,18 @@ ffs_truncate(vp, length, flags, cred, td)
* will be returned to the free list. lastiblock values are also
* normalized to -1 for calls to ffs_indirtrunc below.
*/
- bcopy((caddr_t)&oip->i_db[0], (caddr_t)oldblks, sizeof oldblks);
- for (level = TRIPLE; level >= SINGLE; level--)
+ for (level = TRIPLE; level >= SINGLE; level--) {
+ oldblks[NDADDR + level] = DIP(oip, i_ib[level]);
if (lastiblock[level] < 0) {
- oip->i_ib[level] = 0;
+ DIP(oip, i_ib[level]) = 0;
lastiblock[level] = -1;
}
- for (i = NDADDR - 1; i > lastblock; i--)
- oip->i_db[i] = 0;
+ }
+ for (i = 0; i < NDADDR; i++) {
+ oldblks[i] = DIP(oip, i_db[i]);
+ if (i > lastblock)
+ DIP(oip, i_db[i]) = 0;
+ }
oip->i_flag |= IN_CHANGE | IN_UPDATE;
allerror = UFS_UPDATE(ovp, 1);
@@ -312,9 +324,16 @@ ffs_truncate(vp, length, flags, cred, td)
* Note that we save the new block configuration so we can check it
* when we are done.
*/
- bcopy((caddr_t)&oip->i_db[0], (caddr_t)newblks, sizeof newblks);
- bcopy((caddr_t)oldblks, (caddr_t)&oip->i_db[0], sizeof oldblks);
+ for (i = 0; i < NDADDR; i++) {
+ newblks[i] = DIP(oip, i_db[i]);
+ DIP(oip, i_db[i]) = oldblks[i];
+ }
+ for (i = 0; i < NIADDR; i++) {
+ newblks[NDADDR + i] = DIP(oip, i_ib[i]);
+ DIP(oip, i_ib[i]) = oldblks[NDADDR + i];
+ }
oip->i_size = osize;
+ DIP(oip, i_size) = osize;
error = vtruncbuf(ovp, cred, td, length, fs->fs_bsize);
if (error && (allerror == 0))
@@ -327,7 +346,7 @@ ffs_truncate(vp, length, flags, cred, td)
indir_lbn[DOUBLE] = indir_lbn[SINGLE] - NINDIR(fs) - 1;
indir_lbn[TRIPLE] = indir_lbn[DOUBLE] - NINDIR(fs) * NINDIR(fs) - 1;
for (level = TRIPLE; level >= SINGLE; level--) {
- bn = oip->i_ib[level];
+ bn = DIP(oip, i_ib[level]);
if (bn != 0) {
error = ffs_indirtrunc(oip, indir_lbn[level],
fsbtodb(fs, bn), lastiblock[level], level, &count);
@@ -335,7 +354,7 @@ ffs_truncate(vp, length, flags, cred, td)
allerror = error;
blocksreleased += count;
if (lastiblock[level] < 0) {
- oip->i_ib[level] = 0;
+ DIP(oip, i_ib[level]) = 0;
ffs_blkfree(fs, oip->i_devvp, bn, fs->fs_bsize,
oip->i_number);
blocksreleased += nblocks;
@@ -351,10 +370,10 @@ ffs_truncate(vp, length, flags, cred, td)
for (i = NDADDR - 1; i > lastblock; i--) {
long bsize;
- bn = oip->i_db[i];
+ bn = DIP(oip, i_db[i]);
if (bn == 0)
continue;
- oip->i_db[i] = 0;
+ DIP(oip, i_db[i]) = 0;
bsize = blksize(fs, oip, i);
ffs_blkfree(fs, oip->i_devvp, bn, bsize, oip->i_number);
blocksreleased += btodb(bsize);
@@ -366,7 +385,7 @@ ffs_truncate(vp, length, flags, cred, td)
* Finally, look for a change in size of the
* last direct block; release any frags.
*/
- bn = oip->i_db[lastblock];
+ bn = DIP(oip, i_db[lastblock]);
if (bn != 0) {
long oldspace, newspace;
@@ -376,6 +395,7 @@ ffs_truncate(vp, length, flags, cred, td)
*/
oldspace = blksize(fs, oip, lastblock);
oip->i_size = length;
+ DIP(oip, i_size) = length;
newspace = blksize(fs, oip, lastblock);
if (newspace == 0)
panic("ffs_truncate: newspace");
@@ -394,10 +414,10 @@ ffs_truncate(vp, length, flags, cred, td)
done:
#ifdef DIAGNOSTIC
for (level = SINGLE; level <= TRIPLE; level++)
- if (newblks[NDADDR + level] != oip->i_ib[level])
+ if (newblks[NDADDR + level] != DIP(oip, i_ib[level]))
panic("ffs_truncate1");
for (i = 0; i < NDADDR; i++)
- if (newblks[i] != oip->i_db[i])
+ if (newblks[i] != DIP(oip, i_db[i]))
panic("ffs_truncate2");
if (length == 0 &&
(!TAILQ_EMPTY(&ovp->v_dirtyblkhd) ||
@@ -408,10 +428,11 @@ done:
* Put back the real size.
*/
oip->i_size = length;
- oip->i_blocks -= blocksreleased;
+ DIP(oip, i_size) = length;
+ DIP(oip, i_blocks) -= blocksreleased;
- if (oip->i_blocks < 0) /* sanity */
- oip->i_blocks = 0;
+ if (DIP(oip, i_blocks) < 0) /* sanity */
+ DIP(oip, i_blocks) = 0;
oip->i_flag |= IN_CHANGE;
#ifdef QUOTA
(void) chkdq(oip, -blocksreleased, NOCRED, 0);
@@ -425,26 +446,25 @@ done:
* lastbn. If level is greater than SINGLE, the block is an indirect block
* and recursive calls to indirtrunc must be used to cleanse other indirect
* blocks.
- *
- * NB: triple indirect blocks are untested.
*/
static int
ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp)
struct inode *ip;
- ufs_daddr_t lbn, lastbn;
- ufs_daddr_t dbn;
+ ufs2_daddr_t lbn, lastbn;
+ ufs2_daddr_t dbn;
int level;
- long *countp;
+ ufs2_daddr_t *countp;
{
- int i;
struct buf *bp;
struct fs *fs = ip->i_fs;
- ufs_daddr_t *bap;
struct vnode *vp;
- ufs_daddr_t *copy = NULL, nb, nlbn, last;
- long blkcount, factor;
- int nblocks, blocksreleased = 0;
- int error = 0, allerror = 0;
+ caddr_t copy = NULL;
+ int i, nblocks, error = 0, allerror = 0;
+ ufs2_daddr_t nb, nlbn, last;
+ ufs2_daddr_t blkcount, factor, blocksreleased = 0;
+ ufs1_daddr_t *bap1 = NULL;
+ ufs2_daddr_t *bap2 = NULL;
+# define BAP(ip, i) (((ip)->i_ump->um_fstype == UFS1) ? bap1[i] : bap2[i])
/*
* Calculate index in current block of last
@@ -486,12 +506,15 @@ ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp)
return (error);
}
- bap = (ufs_daddr_t *)bp->b_data;
+ if (ip->i_ump->um_fstype == UFS1)
+ bap1 = (ufs1_daddr_t *)bp->b_data;
+ else
+ bap2 = (ufs2_daddr_t *)bp->b_data;
if (lastbn != -1) {
- MALLOC(copy, ufs_daddr_t *, fs->fs_bsize, M_TEMP, M_WAITOK);
- bcopy((caddr_t)bap, (caddr_t)copy, (u_int)fs->fs_bsize);
- bzero((caddr_t)&bap[last + 1],
- (u_int)(NINDIR(fs) - (last + 1)) * sizeof (ufs_daddr_t));
+ MALLOC(copy, caddr_t, fs->fs_bsize, M_TEMP, M_WAITOK);
+ bcopy((caddr_t)bp->b_data, copy, (u_int)fs->fs_bsize);
+ for (i = last + 1; i < NINDIR(fs); i++)
+ BAP(ip, i) = 0;
if (DOINGASYNC(vp)) {
bawrite(bp);
} else {
@@ -499,7 +522,10 @@ ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp)
if (error)
allerror = error;
}
- bap = copy;
+ if (ip->i_ump->um_fstype == UFS1)
+ bap1 = (ufs1_daddr_t *)copy;
+ else
+ bap2 = (ufs2_daddr_t *)copy;
}
/*
@@ -507,12 +533,12 @@ ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp)
*/
for (i = NINDIR(fs) - 1, nlbn = lbn + 1 - i * factor; i > last;
i--, nlbn += factor) {
- nb = bap[i];
+ nb = BAP(ip, i);
if (nb == 0)
continue;
if (level > SINGLE) {
if ((error = ffs_indirtrunc(ip, nlbn, fsbtodb(fs, nb),
- (ufs_daddr_t)-1, level - 1, &blkcount)) != 0)
+ (ufs2_daddr_t)-1, level - 1, &blkcount)) != 0)
allerror = error;
blocksreleased += blkcount;
}
@@ -525,7 +551,7 @@ ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp)
*/
if (level > SINGLE && lastbn >= 0) {
last = lastbn % factor;
- nb = bap[i];
+ nb = BAP(ip, i);
if (nb != 0) {
error = ffs_indirtrunc(ip, nlbn, fsbtodb(fs, nb),
last, level - 1, &blkcount);
@@ -540,7 +566,7 @@ ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp)
bp->b_flags |= B_INVAL | B_NOCACHE;
brelse(bp);
}
-
+
*countp = blocksreleased;
return (allerror);
}
diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c
index 7965211d72ec..7bc46563d9ee 100644
--- a/sys/ufs/ffs/ffs_snapshot.c
+++ b/sys/ufs/ffs/ffs_snapshot.c
@@ -35,6 +35,7 @@
*/
#include <sys/param.h>
+#include <sys/stdint.h>
#include <sys/systm.h>
#include <sys/conf.h>
#include <sys/disklabel.h>
@@ -47,6 +48,7 @@
#include <sys/mount.h>
#include <sys/resource.h>
#include <sys/resourcevar.h>
+#include <sys/disklabel.h>
#include <sys/vnode.h>
#include <ufs/ufs/extattr.h>
@@ -62,20 +64,34 @@
#define DEBUG 1
static int cgaccount(int, struct vnode *, struct buf *, int);
-static int expunge(struct vnode *, struct inode *, struct fs *,
- int (*)(struct vnode *, ufs_daddr_t *, ufs_daddr_t *, struct fs *,
- ufs_daddr_t, int), int);
-static int indiracct(struct vnode *, struct vnode *, int, ufs_daddr_t,
- int, int, int, int, struct fs *, int (*)(struct vnode *,
- ufs_daddr_t *, ufs_daddr_t *, struct fs *, ufs_daddr_t, int), int);
-static int fullacct(struct vnode *, ufs_daddr_t *, ufs_daddr_t *,
- struct fs *, ufs_daddr_t, int);
-static int snapacct(struct vnode *, ufs_daddr_t *, ufs_daddr_t *,
- struct fs *, ufs_daddr_t, int);
-static int mapacct(struct vnode *, ufs_daddr_t *, ufs_daddr_t *,
- struct fs *, ufs_daddr_t, int);
+static int expunge_ufs1(struct vnode *, struct inode *, struct fs *,
+ int (*)(struct vnode *, ufs1_daddr_t *, ufs1_daddr_t *, struct fs *,
+ ufs_lbn_t, int), int);
+static int indiracct_ufs1(struct vnode *, struct vnode *, int,
+ ufs1_daddr_t, ufs_lbn_t, ufs_lbn_t, ufs_lbn_t, ufs_lbn_t, struct fs *,
+ int (*)(struct vnode *, ufs1_daddr_t *, ufs1_daddr_t *, struct fs *,
+ ufs_lbn_t, int), int);
+static int fullacct_ufs1(struct vnode *, ufs1_daddr_t *, ufs1_daddr_t *,
+ struct fs *, ufs_lbn_t, int);
+static int snapacct_ufs1(struct vnode *, ufs1_daddr_t *, ufs1_daddr_t *,
+ struct fs *, ufs_lbn_t, int);
+static int mapacct_ufs1(struct vnode *, ufs1_daddr_t *, ufs1_daddr_t *,
+ struct fs *, ufs_lbn_t, int);
+static int expunge_ufs2(struct vnode *, struct inode *, struct fs *,
+ int (*)(struct vnode *, ufs2_daddr_t *, ufs2_daddr_t *, struct fs *,
+ ufs_lbn_t, int), int);
+static int indiracct_ufs2(struct vnode *, struct vnode *, int,
+ ufs2_daddr_t, ufs_lbn_t, ufs_lbn_t, ufs_lbn_t, ufs_lbn_t, struct fs *,
+ int (*)(struct vnode *, ufs2_daddr_t *, ufs2_daddr_t *, struct fs *,
+ ufs_lbn_t, int), int);
+static int fullacct_ufs2(struct vnode *, ufs2_daddr_t *, ufs2_daddr_t *,
+ struct fs *, ufs_lbn_t, int);
+static int snapacct_ufs2(struct vnode *, ufs2_daddr_t *, ufs2_daddr_t *,
+ struct fs *, ufs_lbn_t, int);
+static int mapacct_ufs2(struct vnode *, ufs2_daddr_t *, ufs2_daddr_t *,
+ struct fs *, ufs_lbn_t, int);
static int ffs_copyonwrite(struct vnode *, struct buf *);
-static int readblock(struct buf *, daddr_t);
+static int readblock(struct buf *, ufs2_daddr_t);
/*
* To ensure the consistency of snapshots across crashes, we must
@@ -104,8 +120,8 @@ ffs_snapshot(mp, snapfile)
struct mount *mp;
char *snapfile;
{
- ufs_daddr_t blkno;
- int error, cg, snaploc, numblks;
+ ufs2_daddr_t numblks, blkno;
+ int error, cg, snaploc;
int i, size, len, loc;
int flag = mp->mnt_flag;
struct timespec starttime = {0, 0}, endtime;
@@ -191,6 +207,7 @@ restart:
if (error)
goto out;
ip->i_size = lblktosize(fs, (off_t)numblks);
+ DIP(ip, i_size) = ip->i_size;
ip->i_flag |= IN_CHANGE | IN_UPDATE;
if ((error = readblock(bp, numblks - 1)) != 0)
goto out;
@@ -216,7 +233,8 @@ restart:
/*
* Allocate copies for the superblock and its summary information.
*/
- error = UFS_BALLOC(vp, (off_t)(SBOFF), SBSIZE, KERNCRED, 0, &nbp);
+ error = UFS_BALLOC(vp, lfragtosize(fs, fs->fs_sblockloc),
+ fs->fs_sbsize, KERNCRED, 0, &nbp);
if (error)
goto out;
bawrite(nbp);
@@ -266,6 +284,7 @@ restart:
* Change inode to snapshot type file.
*/
ip->i_flags |= SF_SNAPSHOT;
+ DIP(ip, i_flags) = ip->i_flags;
ip->i_flag |= IN_CHANGE | IN_UPDATE;
/*
* Ensure that the snapshot is completely on disk.
@@ -315,19 +334,21 @@ restart:
* Grab a copy of the superblock and its summary information.
* We delay writing it until the suspension is released below.
*/
- error = bread(vp, lblkno(fs, SBOFF), fs->fs_bsize, KERNCRED, &sbp);
+ error = bread(vp, fragstoblks(fs, fs->fs_sblockloc), fs->fs_bsize,
+ KERNCRED, &sbp);
if (error) {
brelse(sbp);
sbp = NULL;
goto out1;
}
- copy_fs = (struct fs *)(sbp->b_data + blkoff(fs, SBOFF));
+ loc = blkoff(fs, lfragtosize(fs, fs->fs_sblockloc));
+ copy_fs = (struct fs *)(sbp->b_data + loc);
bcopy(fs, copy_fs, fs->fs_sbsize);
if ((fs->fs_flags & (FS_UNCLEAN | FS_NEEDSFSCK)) == 0)
copy_fs->fs_clean = 1;
- if (fs->fs_sbsize < SBSIZE)
- bzero(&sbp->b_data[blkoff(fs, SBOFF) + fs->fs_sbsize],
- SBSIZE - fs->fs_sbsize);
+ if (fs->fs_sbsize < SBLOCKSIZE)
+ bzero(&sbp->b_data[loc + fs->fs_sbsize],
+ SBLOCKSIZE - fs->fs_sbsize);
size = blkroundup(fs, fs->fs_cssize);
if (fs->fs_contigsumsize > 0)
size += fs->fs_ncg * sizeof(int32_t);
@@ -399,15 +420,20 @@ loop:
if (loc < NDADDR) {
len = fragroundup(fs, blkoff(fs, xp->i_size));
if (len < fs->fs_bsize) {
- ffs_blkfree(copy_fs, vp, xp->i_db[loc], len,
- xp->i_number);
- blkno = xp->i_db[loc];
- xp->i_db[loc] = 0;
+ ffs_blkfree(copy_fs, vp, DIP(xp, i_db[loc]),
+ len, xp->i_number);
+ blkno = DIP(xp, i_db[loc]);
+ DIP(xp, i_db[loc]) = 0;
}
}
- error = expunge(vp, xp, copy_fs, fullacct, BLK_NOCOPY);
+ if (xp->i_ump->um_fstype == UFS1)
+ error = expunge_ufs1(vp, xp, copy_fs, fullacct_ufs1,
+ BLK_NOCOPY);
+ else
+ error = expunge_ufs2(vp, xp, copy_fs, fullacct_ufs2,
+ BLK_NOCOPY);
if (blkno)
- xp->i_db[loc] = blkno;
+ DIP(xp, i_db[loc]) = blkno;
if (!error)
error = ffs_freefile(copy_fs, vp, xp->i_number,
xp->i_mode);
@@ -458,7 +484,13 @@ out1:
TAILQ_FOREACH(xp, snaphead, i_nextsnap) {
if (xp == ip)
break;
- if ((error = expunge(vp, xp, fs, snapacct, BLK_SNAP)) != 0) {
+ if (xp->i_ump->um_fstype == UFS1)
+ error = expunge_ufs1(vp, xp, fs, snapacct_ufs1,
+ BLK_SNAP);
+ else
+ error = expunge_ufs2(vp, xp, fs, snapacct_ufs2,
+ BLK_SNAP);
+ if (error) {
fs->fs_snapinum[snaploc] = 0;
goto done;
}
@@ -467,7 +499,11 @@ out1:
* Expunge the blocks used by the snapshots from the set of
* blocks marked as used in the snapshot bitmaps.
*/
- if ((error = expunge(vp, ip, copy_fs, mapacct, BLK_SNAP)) != 0) {
+ if (ip->i_ump->um_fstype == UFS1)
+ error = expunge_ufs1(vp, ip, copy_fs, mapacct_ufs1, BLK_SNAP);
+ else
+ error = expunge_ufs2(vp, ip, copy_fs, mapacct_ufs2, BLK_SNAP);
+ if (error) {
fs->fs_snapinum[snaploc] = 0;
goto done;
}
@@ -528,7 +564,8 @@ cgaccount(cg, vp, nbp, passno)
struct inode *ip;
struct cg *cgp;
struct fs *fs;
- int error, numblks, base, len, loc, indiroff;
+ ufs2_daddr_t base, numblks;
+ int error, len, loc, indiroff;
ip = VTOI(vp);
fs = ip->i_fs;
@@ -559,10 +596,10 @@ cgaccount(cg, vp, nbp, passno)
if (base < NDADDR) {
for ( ; loc < NDADDR; loc++) {
if (ffs_isblock(fs, cg_blksfree(cgp), loc))
- ip->i_db[loc] = BLK_NOCOPY;
- else if (passno == 2 && ip->i_db[loc] == BLK_NOCOPY)
- ip->i_db[loc] = 0;
- else if (passno == 1 && ip->i_db[loc] == BLK_NOCOPY)
+ DIP(ip, i_db[loc]) = BLK_NOCOPY;
+ else if (passno == 2 && DIP(ip, i_db[loc])== BLK_NOCOPY)
+ DIP(ip, i_db[loc]) = 0;
+ else if (passno == 1 && DIP(ip, i_db[loc])== BLK_NOCOPY)
panic("ffs_snapshot: lost direct block");
}
}
@@ -587,13 +624,25 @@ cgaccount(cg, vp, nbp, passno)
}
indiroff = 0;
}
+ if (ip->i_ump->um_fstype == UFS1) {
+ if (ffs_isblock(fs, cg_blksfree(cgp), loc))
+ ((ufs1_daddr_t *)(ibp->b_data))[indiroff] =
+ BLK_NOCOPY;
+ else if (passno == 2 && ((ufs1_daddr_t *)(ibp->b_data))
+ [indiroff] == BLK_NOCOPY)
+ ((ufs1_daddr_t *)(ibp->b_data))[indiroff] = 0;
+ else if (passno == 1 && ((ufs1_daddr_t *)(ibp->b_data))
+ [indiroff] == BLK_NOCOPY)
+ panic("ffs_snapshot: lost indirect block");
+ continue;
+ }
if (ffs_isblock(fs, cg_blksfree(cgp), loc))
- ((ufs_daddr_t *)(ibp->b_data))[indiroff] = BLK_NOCOPY;
+ ((ufs2_daddr_t *)(ibp->b_data))[indiroff] = BLK_NOCOPY;
else if (passno == 2 &&
- ((ufs_daddr_t *)(ibp->b_data))[indiroff] == BLK_NOCOPY)
- ((ufs_daddr_t *)(ibp->b_data))[indiroff] = 0;
+ ((ufs2_daddr_t *)(ibp->b_data)) [indiroff] == BLK_NOCOPY)
+ ((ufs2_daddr_t *)(ibp->b_data))[indiroff] = 0;
else if (passno == 1 &&
- ((ufs_daddr_t *)(ibp->b_data))[indiroff] == BLK_NOCOPY)
+ ((ufs2_daddr_t *)(ibp->b_data)) [indiroff] == BLK_NOCOPY)
panic("ffs_snapshot: lost indirect block");
}
bqrelse(bp);
@@ -608,34 +657,37 @@ cgaccount(cg, vp, nbp, passno)
* blocks that it claims with BLK_SNAP so that fsck will
* be able to account for those blocks properly and so
* that this snapshot knows that it need not copy them
- * if the other snapshot holding them is freed.
+ * if the other snapshot holding them is freed. This code
+ * is reproduced once each for UFS1 and UFS2.
*/
static int
-expunge(snapvp, cancelip, fs, acctfunc, expungetype)
+expunge_ufs1(snapvp, cancelip, fs, acctfunc, expungetype)
struct vnode *snapvp;
struct inode *cancelip;
struct fs *fs;
- int (*acctfunc)(struct vnode *, ufs_daddr_t *, ufs_daddr_t *,
- struct fs *, ufs_daddr_t, int);
+ int (*acctfunc)(struct vnode *, ufs1_daddr_t *, ufs1_daddr_t *,
+ struct fs *, ufs_lbn_t, int);
int expungetype;
{
- int i, len, error, numblks, blksperindir;
- ufs_daddr_t lbn, rlbn, blkno, indiroff;
+ int i, error, indiroff;
+ ufs_lbn_t lbn, rlbn;
+ ufs2_daddr_t len, blkno, numblks, blksperindir;
+ struct ufs1_dinode *dip;
struct thread *td = curthread;
- struct dinode *dip;
struct buf *bp;
numblks = howmany(cancelip->i_size, fs->fs_bsize);
- if ((error = (*acctfunc)(snapvp, &cancelip->i_db[0],
- &cancelip->i_ib[NIADDR], fs, 0, expungetype)))
+ if ((error = (*acctfunc)(snapvp, &cancelip->i_din1->di_db[0],
+ &cancelip->i_din1->di_ib[NIADDR], fs, 0, expungetype)))
return (error);
blksperindir = 1;
lbn = -NDADDR;
len = numblks - NDADDR;
rlbn = NDADDR;
for (i = 0; len > 0 && i < NIADDR; i++) {
- error = indiracct(snapvp, ITOV(cancelip), i, cancelip->i_ib[i],
- lbn, rlbn, len, blksperindir, fs, acctfunc, expungetype);
+ error = indiracct_ufs1(snapvp, ITOV(cancelip), i,
+ cancelip->i_din1->di_ib[i], lbn, rlbn, len,
+ blksperindir, fs, acctfunc, expungetype);
if (error)
return (error);
blksperindir *= NINDIR(fs);
@@ -650,7 +702,7 @@ expunge(snapvp, cancelip, fs, acctfunc, expungetype)
lbn = fragstoblks(fs, ino_to_fsba(fs, cancelip->i_number));
blkno = 0;
if (lbn < NDADDR) {
- blkno = cancelip->i_db[lbn];
+ blkno = cancelip->i_din1->di_db[lbn];
} else {
td->td_proc->p_flag |= P_COWINPROGRESS;
error = UFS_BALLOC(snapvp, lblktosize(fs, (off_t)lbn),
@@ -659,7 +711,7 @@ expunge(snapvp, cancelip, fs, acctfunc, expungetype)
if (error)
return (error);
indiroff = (lbn - NDADDR) % NINDIR(fs);
- blkno = ((ufs_daddr_t *)(bp->b_data))[indiroff];
+ blkno = ((ufs1_daddr_t *)(bp->b_data))[indiroff];
bqrelse(bp);
}
error = UFS_BALLOC(snapvp, lblktosize(fs, (off_t)lbn),
@@ -672,13 +724,14 @@ expunge(snapvp, cancelip, fs, acctfunc, expungetype)
* Set a snapshot inode to be a zero length file, regular files
* to be completely unallocated.
*/
- dip = (struct dinode *)bp->b_data + ino_to_fsbo(fs, cancelip->i_number);
+ dip = (struct ufs1_dinode *)bp->b_data +
+ ino_to_fsbo(fs, cancelip->i_number);
if (expungetype == BLK_NOCOPY)
dip->di_mode = 0;
dip->di_size = 0;
dip->di_blocks = 0;
dip->di_flags &= ~SF_SNAPSHOT;
- bzero(&dip->di_db[0], (NDADDR + NIADDR) * sizeof(ufs_daddr_t));
+ bzero(&dip->di_db[0], (NDADDR + NIADDR) * sizeof(ufs1_daddr_t));
bdwrite(bp);
return (0);
}
@@ -688,24 +741,25 @@ expunge(snapvp, cancelip, fs, acctfunc, expungetype)
* its indirect blocks in snapvp.
*/
static int
-indiracct(snapvp, cancelvp, level, blkno, lbn, rlbn, remblks, blksperindir, fs,
- acctfunc, expungetype)
+indiracct_ufs1(snapvp, cancelvp, level, blkno, lbn, rlbn, remblks,
+ blksperindir, fs, acctfunc, expungetype)
struct vnode *snapvp;
struct vnode *cancelvp;
int level;
- ufs_daddr_t blkno;
- int lbn;
- int rlbn;
- int remblks;
- int blksperindir;
+ ufs1_daddr_t blkno;
+ ufs_lbn_t lbn;
+ ufs_lbn_t rlbn;
+ ufs_lbn_t remblks;
+ ufs_lbn_t blksperindir;
struct fs *fs;
- int (*acctfunc)(struct vnode *, ufs_daddr_t *, ufs_daddr_t *,
- struct fs *, ufs_daddr_t, int);
+ int (*acctfunc)(struct vnode *, ufs1_daddr_t *, ufs1_daddr_t *,
+ struct fs *, ufs_lbn_t, int);
int expungetype;
{
- int subblksperindir, error, last, num, i;
+ int error, num, i;
+ ufs_lbn_t subblksperindir;
struct indir indirs[NIADDR + 2];
- ufs_daddr_t *bap;
+ ufs1_daddr_t last, *bap;
struct buf *bp;
if ((error = ufs_getlbns(cancelvp, rlbn, indirs, &num)) != 0)
@@ -729,7 +783,7 @@ indiracct(snapvp, cancelvp, level, blkno, lbn, rlbn, remblks, blksperindir, fs,
last = howmany(remblks, blksperindir);
if (last > NINDIR(fs))
last = NINDIR(fs);
- MALLOC(bap, ufs_daddr_t *, fs->fs_bsize, M_DEVBUF, M_WAITOK);
+ MALLOC(bap, ufs1_daddr_t *, fs->fs_bsize, M_DEVBUF, M_WAITOK);
bcopy(bp->b_data, (caddr_t)bap, fs->fs_bsize);
bqrelse(bp);
error = (*acctfunc)(snapvp, &bap[0], &bap[last], fs, rlbn, expungetype);
@@ -741,7 +795,7 @@ indiracct(snapvp, cancelvp, level, blkno, lbn, rlbn, remblks, blksperindir, fs,
*/
subblksperindir = blksperindir / NINDIR(fs);
for (lbn++, level--, i = 0; i < last; i++) {
- error = indiracct(snapvp, cancelvp, level, bap[i], lbn,
+ error = indiracct_ufs1(snapvp, cancelvp, level, bap[i], lbn,
rlbn, remblks, subblksperindir, fs, acctfunc, expungetype);
if (error)
goto out;
@@ -758,33 +812,287 @@ out:
* Do both snap accounting and map accounting.
*/
static int
-fullacct(vp, oldblkp, lastblkp, fs, lblkno, expungetype)
+fullacct_ufs1(vp, oldblkp, lastblkp, fs, lblkno, exptype)
+ struct vnode *vp;
+ ufs1_daddr_t *oldblkp, *lastblkp;
+ struct fs *fs;
+ ufs_lbn_t lblkno;
+ int exptype; /* BLK_SNAP or BLK_NOCOPY */
+{
+ int error;
+
+ if ((error = snapacct_ufs1(vp, oldblkp, lastblkp, fs, lblkno, exptype)))
+ return (error);
+ return (mapacct_ufs1(vp, oldblkp, lastblkp, fs, lblkno, exptype));
+}
+
+/*
+ * Identify a set of blocks allocated in a snapshot inode.
+ */
+static int
+snapacct_ufs1(vp, oldblkp, lastblkp, fs, lblkno, expungetype)
struct vnode *vp;
- ufs_daddr_t *oldblkp, *lastblkp;
+ ufs1_daddr_t *oldblkp, *lastblkp;
struct fs *fs;
- ufs_daddr_t lblkno;
+ ufs_lbn_t lblkno;
int expungetype; /* BLK_SNAP or BLK_NOCOPY */
{
+ struct inode *ip = VTOI(vp);
+ ufs1_daddr_t blkno, *blkp;
+ ufs_lbn_t lbn;
+ struct buf *ibp;
+ int error;
+
+ for ( ; oldblkp < lastblkp; oldblkp++) {
+ blkno = *oldblkp;
+ if (blkno == 0 || blkno == BLK_NOCOPY || blkno == BLK_SNAP)
+ continue;
+ lbn = fragstoblks(fs, blkno);
+ if (lbn < NDADDR) {
+ blkp = &ip->i_din1->di_db[lbn];
+ ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ } else {
+ error = UFS_BALLOC(vp, lblktosize(fs, (off_t)lbn),
+ fs->fs_bsize, KERNCRED, B_METAONLY, &ibp);
+ if (error)
+ return (error);
+ blkp = &((ufs1_daddr_t *)(ibp->b_data))
+ [(lbn - NDADDR) % NINDIR(fs)];
+ }
+ /*
+ * If we are expunging a snapshot vnode and we
+ * find a block marked BLK_NOCOPY, then it is
+ * one that has been allocated to this snapshot after
+ * we took our current snapshot and can be ignored.
+ */
+ if (expungetype == BLK_SNAP && *blkp == BLK_NOCOPY) {
+ if (lbn >= NDADDR)
+ brelse(ibp);
+ } else {
+ if (*blkp != 0)
+ panic("snapacct: bad block");
+ *blkp = expungetype;
+ if (lbn >= NDADDR)
+ bdwrite(ibp);
+ }
+ }
+ return (0);
+}
+
+/*
+ * Account for a set of blocks allocated in a snapshot inode.
+ */
+static int
+mapacct_ufs1(vp, oldblkp, lastblkp, fs, lblkno, expungetype)
+ struct vnode *vp;
+ ufs1_daddr_t *oldblkp, *lastblkp;
+ struct fs *fs;
+ ufs_lbn_t lblkno;
+ int expungetype;
+{
+ ufs1_daddr_t blkno;
+ ino_t inum;
+
+ inum = VTOI(vp)->i_number;
+ for ( ; oldblkp < lastblkp; oldblkp++, lblkno++) {
+ blkno = *oldblkp;
+ if (blkno == 0 || blkno == BLK_NOCOPY)
+ continue;
+ if (blkno == BLK_SNAP)
+ blkno = blkstofrags(fs, lblkno);
+ ffs_blkfree(fs, vp, blkno, fs->fs_bsize, inum);
+ }
+ return (0);
+}
+
+/*
+ * Before expunging a snapshot inode, note all the
+ * blocks that it claims with BLK_SNAP so that fsck will
+ * be able to account for those blocks properly and so
+ * that this snapshot knows that it need not copy them
+ * if the other snapshot holding them is freed. This code
+ * is reproduced once each for UFS1 and UFS2.
+ */
+static int
+expunge_ufs2(snapvp, cancelip, fs, acctfunc, expungetype)
+ struct vnode *snapvp;
+ struct inode *cancelip;
+ struct fs *fs;
+ int (*acctfunc)(struct vnode *, ufs2_daddr_t *, ufs2_daddr_t *,
+ struct fs *, ufs_lbn_t, int);
+ int expungetype;
+{
+ int i, error, indiroff;
+ ufs_lbn_t lbn, rlbn;
+ ufs2_daddr_t len, blkno, numblks, blksperindir;
+ struct ufs2_dinode *dip;
+ struct thread *td = curthread;
+ struct buf *bp;
+
+ numblks = howmany(cancelip->i_size, fs->fs_bsize);
+ if ((error = (*acctfunc)(snapvp, &cancelip->i_din2->di_db[0],
+ &cancelip->i_din2->di_ib[NIADDR], fs, 0, expungetype)))
+ return (error);
+ blksperindir = 1;
+ lbn = -NDADDR;
+ len = numblks - NDADDR;
+ rlbn = NDADDR;
+ for (i = 0; len > 0 && i < NIADDR; i++) {
+ error = indiracct_ufs2(snapvp, ITOV(cancelip), i,
+ cancelip->i_din2->di_ib[i], lbn, rlbn, len,
+ blksperindir, fs, acctfunc, expungetype);
+ if (error)
+ return (error);
+ blksperindir *= NINDIR(fs);
+ lbn -= blksperindir + 1;
+ len -= blksperindir;
+ rlbn += blksperindir;
+ }
+ /*
+ * Prepare to expunge the inode. If its inode block has not
+ * yet been copied, then allocate and fill the copy.
+ */
+ lbn = fragstoblks(fs, ino_to_fsba(fs, cancelip->i_number));
+ blkno = 0;
+ if (lbn < NDADDR) {
+ blkno = cancelip->i_din2->di_db[lbn];
+ } else {
+ td->td_proc->p_flag |= P_COWINPROGRESS;
+ error = UFS_BALLOC(snapvp, lblktosize(fs, (off_t)lbn),
+ fs->fs_bsize, KERNCRED, B_METAONLY, &bp);
+ td->td_proc->p_flag &= ~P_COWINPROGRESS;
+ if (error)
+ return (error);
+ indiroff = (lbn - NDADDR) % NINDIR(fs);
+ blkno = ((ufs2_daddr_t *)(bp->b_data))[indiroff];
+ bqrelse(bp);
+ }
+ error = UFS_BALLOC(snapvp, lblktosize(fs, (off_t)lbn),
+ fs->fs_bsize, KERNCRED, 0, &bp);
+ if (error)
+ return (error);
+ if (blkno == 0 && (error = readblock(bp, lbn)))
+ return (error);
+ /*
+ * Set a snapshot inode to be a zero length file, regular files
+ * to be completely unallocated.
+ */
+ dip = (struct ufs2_dinode *)bp->b_data +
+ ino_to_fsbo(fs, cancelip->i_number);
+ if (expungetype == BLK_NOCOPY)
+ dip->di_mode = 0;
+ dip->di_size = 0;
+ dip->di_blocks = 0;
+ dip->di_flags &= ~SF_SNAPSHOT;
+ bzero(&dip->di_db[0], (NDADDR + NIADDR) * sizeof(ufs2_daddr_t));
+ bdwrite(bp);
+ return (0);
+}
+
+/*
+ * Descend an indirect block chain for vnode cancelvp accounting for all
+ * its indirect blocks in snapvp.
+ */
+static int
+indiracct_ufs2(snapvp, cancelvp, level, blkno, lbn, rlbn, remblks,
+ blksperindir, fs, acctfunc, expungetype)
+ struct vnode *snapvp;
+ struct vnode *cancelvp;
+ int level;
+ ufs2_daddr_t blkno;
+ ufs_lbn_t lbn;
+ ufs_lbn_t rlbn;
+ ufs_lbn_t remblks;
+ ufs_lbn_t blksperindir;
+ struct fs *fs;
+ int (*acctfunc)(struct vnode *, ufs2_daddr_t *, ufs2_daddr_t *,
+ struct fs *, ufs_lbn_t, int);
+ int expungetype;
+{
+ int error, num, i;
+ ufs_lbn_t subblksperindir;
+ struct indir indirs[NIADDR + 2];
+ ufs2_daddr_t last, *bap;
+ struct buf *bp;
+
+ if ((error = ufs_getlbns(cancelvp, rlbn, indirs, &num)) != 0)
+ return (error);
+ if (lbn != indirs[num - 1 - level].in_lbn || blkno == 0 || num < 2)
+ panic("indiracct: botched params");
+ /*
+ * We have to expand bread here since it will deadlock looking
+ * up the block number for any blocks that are not in the cache.
+ */
+ bp = getblk(cancelvp, lbn, fs->fs_bsize, 0, 0);
+ bp->b_blkno = fsbtodb(fs, blkno);
+ if ((bp->b_flags & (B_DONE | B_DELWRI)) == 0 &&
+ (error = readblock(bp, fragstoblks(fs, blkno)))) {
+ brelse(bp);
+ return (error);
+ }
+ /*
+ * Account for the block pointers in this indirect block.
+ */
+ last = howmany(remblks, blksperindir);
+ if (last > NINDIR(fs))
+ last = NINDIR(fs);
+ MALLOC(bap, ufs2_daddr_t *, fs->fs_bsize, M_DEVBUF, M_WAITOK);
+ bcopy(bp->b_data, (caddr_t)bap, fs->fs_bsize);
+ bqrelse(bp);
+ error = (*acctfunc)(snapvp, &bap[0], &bap[last], fs, rlbn, expungetype);
+ if (error || level == 0)
+ goto out;
+ /*
+ * Account for the block pointers in each of the indirect blocks
+ * in the levels below us.
+ */
+ subblksperindir = blksperindir / NINDIR(fs);
+ for (lbn++, level--, i = 0; i < last; i++) {
+ error = indiracct_ufs2(snapvp, cancelvp, level, bap[i], lbn,
+ rlbn, remblks, subblksperindir, fs, acctfunc, expungetype);
+ if (error)
+ goto out;
+ rlbn += blksperindir;
+ lbn -= blksperindir;
+ remblks -= blksperindir;
+ }
+out:
+ FREE(bap, M_DEVBUF);
+ return (error);
+}
+
+/*
+ * Do both snap accounting and map accounting.
+ */
+static int
+fullacct_ufs2(vp, oldblkp, lastblkp, fs, lblkno, exptype)
+ struct vnode *vp;
+ ufs2_daddr_t *oldblkp, *lastblkp;
+ struct fs *fs;
+ ufs_lbn_t lblkno;
+ int exptype; /* BLK_SNAP or BLK_NOCOPY */
+{
int error;
- if ((error = snapacct(vp, oldblkp, lastblkp, fs, lblkno, expungetype)))
+ if ((error = snapacct_ufs2(vp, oldblkp, lastblkp, fs, lblkno, exptype)))
return (error);
- return (mapacct(vp, oldblkp, lastblkp, fs, lblkno, expungetype));
+ return (mapacct_ufs2(vp, oldblkp, lastblkp, fs, lblkno, exptype));
}
/*
* Identify a set of blocks allocated in a snapshot inode.
*/
static int
-snapacct(vp, oldblkp, lastblkp, fs, lblkno, expungetype)
+snapacct_ufs2(vp, oldblkp, lastblkp, fs, lblkno, expungetype)
struct vnode *vp;
- ufs_daddr_t *oldblkp, *lastblkp;
+ ufs2_daddr_t *oldblkp, *lastblkp;
struct fs *fs;
- ufs_daddr_t lblkno;
+ ufs_lbn_t lblkno;
int expungetype; /* BLK_SNAP or BLK_NOCOPY */
{
struct inode *ip = VTOI(vp);
- ufs_daddr_t lbn, blkno, *blkp;
+ ufs2_daddr_t blkno, *blkp;
+ ufs_lbn_t lbn;
struct buf *ibp;
int error;
@@ -794,14 +1102,14 @@ snapacct(vp, oldblkp, lastblkp, fs, lblkno, expungetype)
continue;
lbn = fragstoblks(fs, blkno);
if (lbn < NDADDR) {
- blkp = &ip->i_db[lbn];
+ blkp = &ip->i_din2->di_db[lbn];
ip->i_flag |= IN_CHANGE | IN_UPDATE;
} else {
error = UFS_BALLOC(vp, lblktosize(fs, (off_t)lbn),
fs->fs_bsize, KERNCRED, B_METAONLY, &ibp);
if (error)
return (error);
- blkp = &((ufs_daddr_t *)(ibp->b_data))
+ blkp = &((ufs2_daddr_t *)(ibp->b_data))
[(lbn - NDADDR) % NINDIR(fs)];
}
/*
@@ -828,14 +1136,14 @@ snapacct(vp, oldblkp, lastblkp, fs, lblkno, expungetype)
* Account for a set of blocks allocated in a snapshot inode.
*/
static int
-mapacct(vp, oldblkp, lastblkp, fs, lblkno, expungetype)
+mapacct_ufs2(vp, oldblkp, lastblkp, fs, lblkno, expungetype)
struct vnode *vp;
- ufs_daddr_t *oldblkp, *lastblkp;
+ ufs2_daddr_t *oldblkp, *lastblkp;
struct fs *fs;
- ufs_daddr_t lblkno;
+ ufs_lbn_t lblkno;
int expungetype;
{
- ufs_daddr_t blkno;
+ ufs2_daddr_t blkno;
ino_t inum;
inum = VTOI(vp)->i_number;
@@ -901,8 +1209,8 @@ ffs_snapremove(vp)
struct vnode *devvp;
struct buf *ibp;
struct fs *fs;
- ufs_daddr_t blkno, dblk;
- int error, numblks, loc, last;
+ ufs2_daddr_t numblks, blkno, dblk;
+ int error, loc, last;
ip = VTOI(vp);
fs = ip->i_fs;
@@ -927,14 +1235,14 @@ ffs_snapremove(vp)
* snapshots that want them (see ffs_snapblkfree below).
*/
for (blkno = 1; blkno < NDADDR; blkno++) {
- dblk = ip->i_db[blkno];
+ dblk = DIP(ip, i_db[blkno]);
if (dblk == BLK_NOCOPY || dblk == BLK_SNAP)
- ip->i_db[blkno] = 0;
+ DIP(ip, i_db[blkno]) = 0;
else if ((dblk == blkstofrags(fs, blkno) &&
ffs_snapblkfree(fs, ip->i_devvp, dblk, fs->fs_bsize,
ip->i_number))) {
- ip->i_blocks -= btodb(fs->fs_bsize);
- ip->i_db[blkno] = 0;
+ DIP(ip, i_blocks) -= btodb(fs->fs_bsize);
+ DIP(ip, i_db[blkno]) = 0;
}
}
numblks = howmany(ip->i_size, fs->fs_bsize);
@@ -943,17 +1251,32 @@ ffs_snapremove(vp)
fs->fs_bsize, KERNCRED, B_METAONLY, &ibp);
if (error)
continue;
- if ((last = fs->fs_size - blkno) > NINDIR(fs))
+ if (fs->fs_size - blkno > NINDIR(fs))
last = NINDIR(fs);
+ else
+ last = fs->fs_size - blkno;
for (loc = 0; loc < last; loc++) {
- dblk = ((ufs_daddr_t *)(ibp->b_data))[loc];
+ if (ip->i_ump->um_fstype == UFS1) {
+ dblk = ((ufs1_daddr_t *)(ibp->b_data))[loc];
+ if (dblk == BLK_NOCOPY || dblk == BLK_SNAP)
+ ((ufs1_daddr_t *)(ibp->b_data))[loc]= 0;
+ else if ((dblk == blkstofrags(fs, blkno) &&
+ ffs_snapblkfree(fs, ip->i_devvp, dblk,
+ fs->fs_bsize, ip->i_number))) {
+ ip->i_din1->di_blocks -=
+ btodb(fs->fs_bsize);
+ ((ufs1_daddr_t *)(ibp->b_data))[loc]= 0;
+ }
+ continue;
+ }
+ dblk = ((ufs2_daddr_t *)(ibp->b_data))[loc];
if (dblk == BLK_NOCOPY || dblk == BLK_SNAP)
- ((ufs_daddr_t *)(ibp->b_data))[loc] = 0;
+ ((ufs2_daddr_t *)(ibp->b_data))[loc] = 0;
else if ((dblk == blkstofrags(fs, blkno) &&
ffs_snapblkfree(fs, ip->i_devvp, dblk,
fs->fs_bsize, ip->i_number))) {
- ip->i_blocks -= btodb(fs->fs_bsize);
- ((ufs_daddr_t *)(ibp->b_data))[loc] = 0;
+ ip->i_din2->di_blocks -= btodb(fs->fs_bsize);
+ ((ufs2_daddr_t *)(ibp->b_data))[loc] = 0;
}
}
bawrite(ibp);
@@ -962,6 +1285,7 @@ ffs_snapremove(vp)
* Clear snapshot flag and drop reference.
*/
ip->i_flags &= ~SF_SNAPSHOT;
+ DIP(ip, i_flags) = ip->i_flags;
ip->i_flag |= IN_CHANGE | IN_UPDATE;
}
@@ -987,7 +1311,7 @@ int
ffs_snapblkfree(fs, devvp, bno, size, inum)
struct fs *fs;
struct vnode *devvp;
- ufs_daddr_t bno;
+ ufs2_daddr_t bno;
long size;
ino_t inum;
{
@@ -995,7 +1319,8 @@ ffs_snapblkfree(fs, devvp, bno, size, inum)
struct thread *td = curthread;
struct inode *ip;
struct vnode *vp;
- ufs_daddr_t lbn, blkno;
+ ufs_lbn_t lbn;
+ ufs2_daddr_t blkno;
int indiroff = 0, error = 0, claimedblk = 0;
struct snaphead *snaphead;
@@ -1007,7 +1332,7 @@ ffs_snapblkfree(fs, devvp, bno, size, inum)
* Lookup block being written.
*/
if (lbn < NDADDR) {
- blkno = ip->i_db[lbn];
+ blkno = DIP(ip, i_db[lbn]);
} else {
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
td->td_proc->p_flag |= P_COWINPROGRESS;
@@ -1018,46 +1343,52 @@ ffs_snapblkfree(fs, devvp, bno, size, inum)
if (error)
break;
indiroff = (lbn - NDADDR) % NINDIR(fs);
- blkno = ((ufs_daddr_t *)(ibp->b_data))[indiroff];
+ if (ip->i_ump->um_fstype == UFS1)
+ blkno=((ufs1_daddr_t *)(ibp->b_data))[indiroff];
+ else
+ blkno=((ufs2_daddr_t *)(ibp->b_data))[indiroff];
}
/*
* Check to see if block needs to be copied.
*/
- switch (blkno) {
- /*
- * If the snapshot has already copied the block (default),
- * or does not care about the block, it is not needed.
- */
- default:
- case BLK_NOCOPY:
- if (lbn >= NDADDR)
- bqrelse(ibp);
- continue;
- /*
- * No previous snapshot claimed the block, so it will be
- * freed and become a BLK_NOCOPY (don't care) for us.
- */
- case BLK_SNAP:
+ if (blkno == 0) {
+ /*
+ * A block that we map is being freed. If it has not
+ * been claimed yet, we will claim or copy it (below).
+ */
+ claimedblk = 1;
+ } else if (blkno == BLK_SNAP) {
+ /*
+ * No previous snapshot claimed the block,
+ * so it will be * freed and become a BLK_NOCOPY
+ * (don't care) for us.
+ */
if (claimedblk)
panic("snapblkfree: inconsistent block type");
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
if (lbn < NDADDR) {
- ip->i_db[lbn] = BLK_NOCOPY;
+ DIP(ip, i_db[lbn]) = BLK_NOCOPY;
ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ } else if (ip->i_ump->um_fstype == UFS1) {
+ ((ufs1_daddr_t *)(ibp->b_data))[indiroff] =
+ BLK_NOCOPY;
+ bdwrite(ibp);
} else {
- ((ufs_daddr_t *)(ibp->b_data))[indiroff] =
+ ((ufs2_daddr_t *)(ibp->b_data))[indiroff] =
BLK_NOCOPY;
bdwrite(ibp);
}
VOP_UNLOCK(vp, 0, td);
continue;
- /*
- * A block that we map is being freed. If it has not been
- * claimed yet, we will claim or copy it (below).
- */
- case 0:
- claimedblk = 1;
- break;
+ } else /* BLK_NOCOPY or default */ {
+ /*
+ * If the snapshot has already copied the block
+ * (default), or does not care about the block,
+ * it is not needed.
+ */
+ if (lbn >= NDADDR)
+ bqrelse(ibp);
+ continue;
}
/*
* If this is a full size block, we will just grab it
@@ -1069,18 +1400,21 @@ ffs_snapblkfree(fs, devvp, bno, size, inum)
if (size == fs->fs_bsize) {
#ifdef DEBUG
if (snapdebug)
- printf("%s %d lbn %d from inum %d\n",
- "Grabonremove: snapino", ip->i_number, lbn,
- inum);
+ printf("%s %d lbn %lld from inum %d\n",
+ "Grabonremove: snapino", ip->i_number,
+ (intmax_t)lbn, inum);
#endif
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
if (lbn < NDADDR) {
- ip->i_db[lbn] = bno;
+ DIP(ip, i_db[lbn]) = bno;
+ } else if (ip->i_ump->um_fstype == UFS1) {
+ ((ufs1_daddr_t *)(ibp->b_data))[indiroff] = bno;
+ bdwrite(ibp);
} else {
- ((ufs_daddr_t *)(ibp->b_data))[indiroff] = bno;
+ ((ufs2_daddr_t *)(ibp->b_data))[indiroff] = bno;
bdwrite(ibp);
}
- ip->i_blocks += btodb(size);
+ DIP(ip, i_blocks) += btodb(size);
ip->i_flag |= IN_CHANGE | IN_UPDATE;
VOP_UNLOCK(vp, 0, td);
return (1);
@@ -1103,10 +1437,10 @@ ffs_snapblkfree(fs, devvp, bno, size, inum)
}
#ifdef DEBUG
if (snapdebug)
- printf(
-"Copyonremove: snapino %lu lbn %ld for inum %lu size %ld to blkno %lld\n",
- (unsigned long)ip->i_number, (long)lbn,
- (unsigned long)inum, size, (long long)cbp->b_blkno);
+ printf("%s%d lbn %lld %s %d size %ld to blkno %lld\n",
+ "Copyonremove: snapino ", ip->i_number,
+ (intmax_t)lbn, "for inum", inum, size,
+ (intmax_t)cbp->b_blkno);
#endif
/*
* If we have already read the old block contents, then
@@ -1245,7 +1579,7 @@ ffs_copyonwrite(devvp, bp)
struct fs *fs;
struct inode *ip;
struct vnode *vp;
- ufs_daddr_t lbn, blkno;
+ ufs2_daddr_t lbn, blkno;
int indiroff, error = 0;
fs = TAILQ_FIRST(&devvp->v_rdev->si_snapshots)->i_fs;
@@ -1273,7 +1607,7 @@ ffs_copyonwrite(devvp, bp)
retry:
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
if (lbn < NDADDR) {
- blkno = ip->i_db[lbn];
+ blkno = DIP(ip, i_db[lbn]);
} else {
td->td_proc->p_flag |= P_COWINPROGRESS;
error = UFS_BALLOC(vp, lblktosize(fs, (off_t)lbn),
@@ -1287,7 +1621,10 @@ retry:
goto retry;
}
indiroff = (lbn - NDADDR) % NINDIR(fs);
- blkno = ((ufs_daddr_t *)(ibp->b_data))[indiroff];
+ if (ip->i_ump->um_fstype == UFS1)
+ blkno=((ufs1_daddr_t *)(ibp->b_data))[indiroff];
+ else
+ blkno=((ufs2_daddr_t *)(ibp->b_data))[indiroff];
bqrelse(ibp);
}
#ifdef DIAGNOSTIC
@@ -1316,14 +1653,14 @@ retry:
}
#ifdef DEBUG
if (snapdebug) {
- printf("Copyonwrite: snapino %d lbn %d for ",
- ip->i_number, lbn);
+ printf("Copyonwrite: snapino %d lbn %lld for ",
+ ip->i_number, (intmax_t)lbn);
if (bp->b_vp == devvp)
printf("fs metadata");
else
printf("inum %d", VTOI(bp->b_vp)->i_number);
printf(" lblkno %lld to blkno %lld\n",
- (long long)bp->b_lblkno, (long long)cbp->b_blkno);
+ (intmax_t)bp->b_lblkno, (intmax_t)cbp->b_blkno);
}
#endif
/*
@@ -1379,7 +1716,7 @@ retry:
static int
readblock(bp, lbn)
struct buf *bp;
- daddr_t lbn;
+ ufs2_daddr_t lbn;
{
struct uio auio;
struct iovec aiov;
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index a1422acfcf46..345bfdececa8 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
+#include <sys/stdint.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/malloc.h>
@@ -163,7 +164,8 @@ static void handle_allocdirect_partdone(struct allocdirect *);
static void handle_allocindir_partdone(struct allocindir *);
static void initiate_write_filepage(struct pagedep *, struct buf *);
static void handle_written_mkdir(struct mkdir *, int);
-static void initiate_write_inodeblock(struct inodedep *, struct buf *);
+static void initiate_write_inodeblock_ufs1(struct inodedep *, struct buf *);
+static void initiate_write_inodeblock_ufs2(struct inodedep *, struct buf *);
static void handle_workitem_freefile(struct freefile *);
static void handle_workitem_remove(struct dirrem *, struct vnode *);
static struct dirrem *newdirrem(struct buf *, struct inode *,
@@ -171,7 +173,8 @@ static struct dirrem *newdirrem(struct buf *, struct inode *,
static void free_diradd(struct diradd *);
static void free_allocindir(struct allocindir *, struct inodedep *);
static void free_newdirblk(struct newdirblk *);
-static int indir_trunc(struct freeblks *, ufs_daddr_t, int, ufs_lbn_t, long *);
+static int indir_trunc(struct freeblks *, ufs2_daddr_t, int, ufs_lbn_t,
+ ufs2_daddr_t *);
static void deallocate_dependencies(struct buf *, struct inodedep *);
static void free_allocdirect(struct allocdirectlst *,
struct allocdirect *, int);
@@ -181,14 +184,14 @@ static void handle_workitem_freeblocks(struct freeblks *, int);
static void merge_inode_lists(struct inodedep *);
static void setup_allocindir_phase2(struct buf *, struct inode *,
struct allocindir *);
-static struct allocindir *newallocindir(struct inode *, int, ufs_daddr_t,
- ufs_daddr_t);
+static struct allocindir *newallocindir(struct inode *, int, ufs2_daddr_t,
+ ufs2_daddr_t);
static void handle_workitem_freefrag(struct freefrag *);
-static struct freefrag *newfreefrag(struct inode *, ufs_daddr_t, long);
+static struct freefrag *newfreefrag(struct inode *, ufs2_daddr_t, long);
static void allocdirect_merge(struct allocdirectlst *,
struct allocdirect *, struct allocdirect *);
static struct bmsafemap *bmsafemap_lookup(struct buf *);
-static int newblk_lookup(struct fs *, ufs_daddr_t, int, struct newblk **);
+static int newblk_lookup(struct fs *, ufs2_daddr_t, int, struct newblk **);
static int inodedep_lookup(struct fs *, ino_t, int, struct inodedep **);
static int pagedep_lookup(struct inode *, ufs_lbn_t, int, struct pagedep **);
static void pause_timer(void *);
@@ -1036,7 +1039,7 @@ top:
inodedep->id_ino = inum;
inodedep->id_state = ALLCOMPLETE;
inodedep->id_nlinkdelta = 0;
- inodedep->id_savedino = NULL;
+ inodedep->id_savedino1 = NULL;
inodedep->id_savedsize = -1;
inodedep->id_buf = NULL;
LIST_INIT(&inodedep->id_pendinghd);
@@ -1068,7 +1071,7 @@ static struct sema newblk_in_progress;
static int
newblk_lookup(fs, newblkno, flags, newblkpp)
struct fs *fs;
- ufs_daddr_t newblkno;
+ ufs2_daddr_t newblkno;
int flags;
struct newblk **newblkpp;
{
@@ -1139,7 +1142,7 @@ softdep_mount(devvp, mp, fs, cred)
struct fs *fs;
struct ucred *cred;
{
- struct csum cstotal;
+ struct csum_total cstotal;
struct cg *cgp;
struct buf *bp;
int error, cyl;
@@ -1246,7 +1249,7 @@ void
softdep_setup_blkmapdep(bp, fs, newblkno)
struct buf *bp; /* buffer for cylgroup block with block map */
struct fs *fs; /* filesystem doing allocation */
- ufs_daddr_t newblkno; /* number of newly allocated block */
+ ufs2_daddr_t newblkno; /* number of newly allocated block */
{
struct newblk *newblk;
struct bmsafemap *bmsafemap;
@@ -1332,8 +1335,8 @@ void
softdep_setup_allocdirect(ip, lbn, newblkno, oldblkno, newsize, oldsize, bp)
struct inode *ip; /* inode to which block is being added */
ufs_lbn_t lbn; /* block pointer within inode */
- ufs_daddr_t newblkno; /* disk block number being added */
- ufs_daddr_t oldblkno; /* previous block number, 0 unless frag */
+ ufs2_daddr_t newblkno; /* disk block number being added */
+ ufs2_daddr_t oldblkno; /* previous block number, 0 unless frag */
long newsize; /* size of new block */
long oldsize; /* size of new block */
struct buf *bp; /* bp for allocated block */
@@ -1457,9 +1460,11 @@ allocdirect_merge(adphead, newadp, oldadp)
newadp->ad_oldsize != oldadp->ad_newsize ||
newadp->ad_lbn >= NDADDR) {
FREE_LOCK(&lk);
- panic("allocdirect_merge: old %d != new %d || lbn %ld >= %d",
- newadp->ad_oldblkno, oldadp->ad_newblkno, newadp->ad_lbn,
- NDADDR);
+ panic("%s %lld != new %lld || old size %ld != new %ld",
+ "allocdirect_merge: old blkno",
+ (intmax_t)newadp->ad_oldblkno,
+ (intmax_t)oldadp->ad_newblkno,
+ newadp->ad_oldsize, oldadp->ad_newsize);
}
newadp->ad_oldblkno = oldadp->ad_oldblkno;
newadp->ad_oldsize = oldadp->ad_oldsize;
@@ -1504,7 +1509,7 @@ allocdirect_merge(adphead, newadp, oldadp)
static struct freefrag *
newfreefrag(ip, blkno, size)
struct inode *ip;
- ufs_daddr_t blkno;
+ ufs2_daddr_t blkno;
long size;
{
struct freefrag *freefrag;
@@ -1521,7 +1526,6 @@ newfreefrag(ip, blkno, size)
freefrag->ff_state = 0;
freefrag->ff_inum = ip->i_number;
freefrag->ff_mnt = ITOV(ip)->v_mount;
- freefrag->ff_devvp = ip->i_devvp;
freefrag->ff_blkno = blkno;
freefrag->ff_fragsize = size;
return (freefrag);
@@ -1535,9 +1539,10 @@ static void
handle_workitem_freefrag(freefrag)
struct freefrag *freefrag;
{
+ struct ufsmount *ump = VFSTOUFS(freefrag->ff_mnt);
- ffs_blkfree(VFSTOUFS(freefrag->ff_mnt)->um_fs, freefrag->ff_devvp,
- freefrag->ff_blkno, freefrag->ff_fragsize, freefrag->ff_inum);
+ ffs_blkfree(ump->um_fs, ump->um_devvp, freefrag->ff_blkno,
+ freefrag->ff_fragsize, freefrag->ff_inum);
FREE(freefrag, M_FREEFRAG);
}
@@ -1573,8 +1578,8 @@ static struct allocindir *
newallocindir(ip, ptrno, newblkno, oldblkno)
struct inode *ip; /* inode for file being extended */
int ptrno; /* offset of pointer in indirect block */
- ufs_daddr_t newblkno; /* disk block number being added */
- ufs_daddr_t oldblkno; /* previous block number, 0 if none */
+ ufs2_daddr_t newblkno; /* disk block number being added */
+ ufs2_daddr_t oldblkno; /* previous block number, 0 if none */
{
struct allocindir *aip;
@@ -1599,8 +1604,8 @@ softdep_setup_allocindir_page(ip, lbn, bp, ptrno, newblkno, oldblkno, nbp)
ufs_lbn_t lbn; /* allocated block number within file */
struct buf *bp; /* buffer with indirect blk referencing page */
int ptrno; /* offset of pointer in indirect block */
- ufs_daddr_t newblkno; /* disk block number being added */
- ufs_daddr_t oldblkno; /* previous block number, 0 if none */
+ ufs2_daddr_t newblkno; /* disk block number being added */
+ ufs2_daddr_t oldblkno; /* previous block number, 0 if none */
struct buf *nbp; /* buffer holding allocated page */
{
struct allocindir *aip;
@@ -1631,7 +1636,7 @@ softdep_setup_allocindir_meta(nbp, ip, bp, ptrno, newblkno)
struct inode *ip; /* inode for file being extended */
struct buf *bp; /* indirect block referencing allocated block */
int ptrno; /* offset of pointer in indirect block */
- ufs_daddr_t newblkno; /* disk block number being added */
+ ufs2_daddr_t newblkno; /* disk block number being added */
{
struct allocindir *aip;
@@ -1658,7 +1663,7 @@ setup_allocindir_phase2(bp, ip, aip)
struct allocindir *oldaip;
struct freefrag *freefrag;
struct newblk *newblk;
- ufs_daddr_t blkno;
+ ufs2_daddr_t blkno;
if (bp->b_lblkno >= 0)
panic("setup_allocindir_phase2: not indir blk");
@@ -1719,8 +1724,12 @@ setup_allocindir_phase2(bp, ip, aip)
free_allocindir(oldaip, NULL);
}
LIST_INSERT_HEAD(&indirdep->ir_deplisthd, aip, ai_next);
- ((ufs_daddr_t *)indirdep->ir_savebp->b_data)
- [aip->ai_offset] = aip->ai_oldblkno;
+ if (ip->i_ump->um_fstype == UFS1)
+ ((ufs1_daddr_t *)indirdep->ir_savebp->b_data)
+ [aip->ai_offset] = aip->ai_oldblkno;
+ else
+ ((ufs2_daddr_t *)indirdep->ir_savebp->b_data)
+ [aip->ai_offset] = aip->ai_oldblkno;
FREE_LOCK(&lk);
if (freefrag != NULL)
handle_workitem_freefrag(freefrag);
@@ -1736,6 +1745,8 @@ setup_allocindir_phase2(bp, ip, aip)
M_INDIRDEP, M_SOFTDEP_FLAGS);
newindirdep->ir_list.wk_type = D_INDIRDEP;
newindirdep->ir_state = ATTACHED;
+ if (ip->i_ump->um_fstype == UFS1)
+ newindirdep->ir_state |= UFS1FMT;
LIST_INIT(&newindirdep->ir_deplisthd);
LIST_INIT(&newindirdep->ir_donehd);
if (bp->b_blkno == bp->b_lblkno) {
@@ -1803,17 +1814,18 @@ softdep_setup_freeblocks(ip, length)
freeblks->fb_mnt = ITOV(ip)->v_mount;
freeblks->fb_oldsize = ip->i_size;
freeblks->fb_newsize = length;
- freeblks->fb_chkcnt = ip->i_blocks;
+ freeblks->fb_chkcnt = DIP(ip, i_blocks);
for (i = 0; i < NDADDR; i++) {
- freeblks->fb_dblks[i] = ip->i_db[i];
- ip->i_db[i] = 0;
+ freeblks->fb_dblks[i] = DIP(ip, i_db[i]);
+ DIP(ip, i_db[i]) = 0;
}
for (i = 0; i < NIADDR; i++) {
- freeblks->fb_iblks[i] = ip->i_ib[i];
- ip->i_ib[i] = 0;
+ freeblks->fb_iblks[i] = DIP(ip, i_ib[i]);
+ DIP(ip, i_ib[i]) = 0;
}
- ip->i_blocks = 0;
+ DIP(ip, i_blocks) = 0;
ip->i_size = 0;
+ DIP(ip, i_size) = 0;
/*
* If the file was removed, then the space being freed was
* accounted for then (see softdep_filereleased()). If the
@@ -1832,8 +1844,12 @@ softdep_setup_freeblocks(ip, length)
brelse(bp);
softdep_error("softdep_setup_freeblocks", error);
}
- *((struct dinode *)bp->b_data + ino_to_fsbo(fs, ip->i_number)) =
- ip->i_din;
+ if (ip->i_ump->um_fstype == UFS1)
+ *((struct ufs1_dinode *)bp->b_data +
+ ino_to_fsbo(fs, ip->i_number)) = *ip->i_din1;
+ else
+ *((struct ufs2_dinode *)bp->b_data +
+ ino_to_fsbo(fs, ip->i_number)) = *ip->i_din2;
/*
* Find and eliminate any inode dependencies.
*/
@@ -2116,9 +2132,9 @@ free_newdirblk(newdirblk)
*/
void
softdep_freefile(pvp, ino, mode)
- struct vnode *pvp;
- ino_t ino;
- int mode;
+ struct vnode *pvp;
+ ino_t ino;
+ int mode;
{
struct inode *ip = VTOI(pvp);
struct inodedep *inodedep;
@@ -2188,9 +2204,9 @@ check_inode_unwritten(inodedep)
inodedep->id_buf = NULL;
if (inodedep->id_state & ONWORKLIST)
WORKLIST_REMOVE(&inodedep->id_list);
- if (inodedep->id_savedino != NULL) {
- FREE(inodedep->id_savedino, M_INODEDEP);
- inodedep->id_savedino = NULL;
+ if (inodedep->id_savedino1 != NULL) {
+ FREE(inodedep->id_savedino1, M_INODEDEP);
+ inodedep->id_savedino1 = NULL;
}
if (free_inodedep(inodedep) == 0) {
FREE_LOCK(&lk);
@@ -2214,7 +2230,7 @@ free_inodedep(inodedep)
LIST_FIRST(&inodedep->id_inowait) != NULL ||
TAILQ_FIRST(&inodedep->id_inoupdt) != NULL ||
TAILQ_FIRST(&inodedep->id_newinoupdt) != NULL ||
- inodedep->id_nlinkdelta != 0 || inodedep->id_savedino != NULL)
+ inodedep->id_nlinkdelta != 0 || inodedep->id_savedino1 != NULL)
return (0);
LIST_REMOVE(inodedep, id_hash);
WORKITEM_FREE(inodedep, D_INODEDEP);
@@ -2237,10 +2253,9 @@ handle_workitem_freeblocks(freeblks, flags)
{
struct inode *ip;
struct vnode *vp;
- ufs_daddr_t bn;
struct fs *fs;
- int i, level, bsize;
- long nblocks, blocksreleased = 0;
+ int i, nblocks, level, bsize;
+ ufs2_daddr_t bn, blocksreleased = 0;
int error, allerror = 0;
ufs_lbn_t baselbns[NIADDR], tmpval;
@@ -2288,7 +2303,7 @@ handle_workitem_freeblocks(freeblks, flags)
VFS_VGET(freeblks->fb_mnt, freeblks->fb_previousinum,
(flags & LK_NOWAIT) | LK_EXCLUSIVE, &vp) == 0) {
ip = VTOI(vp);
- ip->i_blocks += freeblks->fb_chkcnt - blocksreleased;
+ DIP(ip, i_blocks) += freeblks->fb_chkcnt - blocksreleased;
ip->i_flag |= IN_CHANGE;
vput(vp);
}
@@ -2313,18 +2328,19 @@ handle_workitem_freeblocks(freeblks, flags)
static int
indir_trunc(freeblks, dbn, level, lbn, countp)
struct freeblks *freeblks;
- ufs_daddr_t dbn;
+ ufs2_daddr_t dbn;
int level;
ufs_lbn_t lbn;
- long *countp;
+ ufs2_daddr_t *countp;
{
struct buf *bp;
- ufs_daddr_t *bap;
- ufs_daddr_t nb;
struct fs *fs;
struct worklist *wk;
struct indirdep *indirdep;
- int i, lbnadd, nblocks;
+ ufs1_daddr_t *bap1 = 0;
+ ufs2_daddr_t nb, *bap2 = 0;
+ ufs_lbn_t lbnadd;
+ int i, nblocks, ufs1fmt;
int error, allerror = 0;
fs = VFSTOUFS(freeblks->fb_mnt)->um_fs;
@@ -2371,10 +2387,20 @@ indir_trunc(freeblks, dbn, level, lbn, countp)
/*
* Recursively free indirect blocks.
*/
- bap = (ufs_daddr_t *)bp->b_data;
+ if (VFSTOUFS(freeblks->fb_mnt)->um_fstype == UFS1) {
+ ufs1fmt = 1;
+ bap1 = (ufs1_daddr_t *)bp->b_data;
+ } else {
+ ufs1fmt = 0;
+ bap2 = (ufs2_daddr_t *)bp->b_data;
+ }
nblocks = btodb(fs->fs_bsize);
for (i = NINDIR(fs) - 1; i >= 0; i--) {
- if ((nb = bap[i]) == 0)
+ if (ufs1fmt)
+ nb = bap1[i];
+ else
+ nb = bap2[i];
+ if (nb == 0)
continue;
if (level != 0) {
if ((error = indir_trunc(freeblks, fsbtodb(fs, nb),
@@ -2449,7 +2475,7 @@ softdep_setup_directory_add(bp, dp, diroffset, newinum, newdirbp, isnewblk)
struct buf *bp; /* buffer containing directory block */
struct inode *dp; /* inode for directory */
off_t diroffset; /* offset of new entry in directory */
- long newinum; /* inode referenced by new directory entry */
+ ino_t newinum; /* inode referenced by new directory entry */
struct buf *newdirbp; /* non-NULL => contents of new mkdir */
int isnewblk; /* entry is in a newly allocated block */
{
@@ -2868,7 +2894,7 @@ softdep_setup_directory_change(bp, dp, ip, newinum, isrmdir)
struct buf *bp; /* buffer containing directory block */
struct inode *dp; /* inode for the directory being modified */
struct inode *ip; /* inode for directory entry being removed */
- long newinum; /* new inode number for changed entry */
+ ino_t newinum; /* new inode number for changed entry */
int isrmdir; /* indicates if doing RMDIR */
{
int offset;
@@ -3028,7 +3054,7 @@ softdep_releasefile(ip)
if ((inodedep_lookup(ip->i_fs, ip->i_number, 0, &inodedep)))
inodedep->id_state |= SPACECOUNTED;
FREE_LOCK(&lk);
- ip->i_fs->fs_pendingblocks += ip->i_blocks;
+ ip->i_fs->fs_pendingblocks += DIP(ip, i_blocks);
ip->i_fs->fs_pendinginodes += 1;
ip->i_flag |= IN_SPACECOUNTED;
}
@@ -3066,6 +3092,7 @@ handle_workitem_remove(dirrem, xp)
*/
if ((dirrem->dm_state & RMDIR) == 0) {
ip->i_nlink--;
+ DIP(ip, i_nlink) = ip->i_nlink;
ip->i_flag |= IN_CHANGE;
if (ip->i_nlink < ip->i_effnlink) {
FREE_LOCK(&lk);
@@ -3086,6 +3113,7 @@ handle_workitem_remove(dirrem, xp)
* the parent decremented to account for the loss of "..".
*/
ip->i_nlink -= 2;
+ DIP(ip, i_nlink) = ip->i_nlink;
ip->i_flag |= IN_CHANGE;
if (ip->i_nlink < ip->i_effnlink) {
FREE_LOCK(&lk);
@@ -3193,6 +3221,7 @@ softdep_disk_io_initiation(bp)
{
struct worklist *wk, *nextwk;
struct indirdep *indirdep;
+ struct inodedep *inodedep;
/*
* We only care about write operations. There should never
@@ -3212,7 +3241,11 @@ softdep_disk_io_initiation(bp)
continue;
case D_INODEDEP:
- initiate_write_inodeblock(WK_INODEDEP(wk), bp);
+ inodedep = WK_INODEDEP(wk);
+ if (inodedep->id_fs->fs_magic == FS_UFS1_MAGIC)
+ initiate_write_inodeblock_ufs1(inodedep, bp);
+ else
+ initiate_write_inodeblock_ufs2(inodedep, bp);
continue;
case D_INDIRDEP:
@@ -3309,39 +3342,43 @@ initiate_write_filepage(pagedep, bp)
}
/*
+ * Version of initiate_write_inodeblock that handles UFS1 dinodes.
+ * Note that any bug fixes made to this routine must be done in the
+ * version found below.
+ *
* Called from within the procedure above to deal with unsatisfied
* allocation dependencies in an inodeblock. The buffer must be
* locked, thus, no I/O completion operations can occur while we
* are manipulating its associated dependencies.
*/
static void
-initiate_write_inodeblock(inodedep, bp)
+initiate_write_inodeblock_ufs1(inodedep, bp)
struct inodedep *inodedep;
struct buf *bp; /* The inode block */
{
struct allocdirect *adp, *lastadp;
- struct dinode *dp;
+ struct ufs1_dinode *dp;
struct fs *fs;
- ufs_lbn_t prevlbn = 0;
- int i, deplist;
+ ufs_lbn_t i, prevlbn = 0;
+ int deplist;
if (inodedep->id_state & IOSTARTED)
- panic("initiate_write_inodeblock: already started");
+ panic("initiate_write_inodeblock_ufs1: already started");
inodedep->id_state |= IOSTARTED;
fs = inodedep->id_fs;
- dp = (struct dinode *)bp->b_data +
+ dp = (struct ufs1_dinode *)bp->b_data +
ino_to_fsbo(fs, inodedep->id_ino);
/*
* If the bitmap is not yet written, then the allocated
* inode cannot be written to disk.
*/
if ((inodedep->id_state & DEPCOMPLETE) == 0) {
- if (inodedep->id_savedino != NULL)
- panic("initiate_write_inodeblock: already doing I/O");
- MALLOC(inodedep->id_savedino, struct dinode *,
- sizeof(struct dinode), M_INODEDEP, M_SOFTDEP_FLAGS);
- *inodedep->id_savedino = *dp;
- bzero((caddr_t)dp, sizeof(struct dinode));
+ if (inodedep->id_savedino1 != NULL)
+ panic("initiate_write_inodeblock_ufs1: I/O underway");
+ MALLOC(inodedep->id_savedino1, struct ufs1_dinode *,
+ sizeof(struct ufs1_dinode), M_INODEDEP, M_SOFTDEP_FLAGS);
+ *inodedep->id_savedino1 = *dp;
+ bzero((caddr_t)dp, sizeof(struct ufs1_dinode));
return;
}
/*
@@ -3365,16 +3402,172 @@ initiate_write_inodeblock(inodedep, bp)
if (adp->ad_lbn < NDADDR &&
dp->di_db[adp->ad_lbn] != adp->ad_newblkno) {
FREE_LOCK(&lk);
- panic("%s: direct pointer #%ld mismatch %d != %d",
- "softdep_write_inodeblock", adp->ad_lbn,
- dp->di_db[adp->ad_lbn], adp->ad_newblkno);
+ panic("%s: direct pointer #%lld mismatch %d != %lld",
+ "softdep_write_inodeblock",
+ (intmax_t)adp->ad_lbn,
+ dp->di_db[adp->ad_lbn],
+ (intmax_t)adp->ad_newblkno);
}
if (adp->ad_lbn >= NDADDR &&
dp->di_ib[adp->ad_lbn - NDADDR] != adp->ad_newblkno) {
FREE_LOCK(&lk);
- panic("%s: indirect pointer #%ld mismatch %d != %d",
- "softdep_write_inodeblock", adp->ad_lbn - NDADDR,
- dp->di_ib[adp->ad_lbn - NDADDR], adp->ad_newblkno);
+ panic("%s: indirect pointer #%lld mismatch %d != %lld",
+ "softdep_write_inodeblock",
+ (intmax_t)adp->ad_lbn - NDADDR,
+ dp->di_ib[adp->ad_lbn - NDADDR],
+ (intmax_t)adp->ad_newblkno);
+ }
+ deplist |= 1 << adp->ad_lbn;
+ if ((adp->ad_state & ATTACHED) == 0) {
+ FREE_LOCK(&lk);
+ panic("softdep_write_inodeblock: Unknown state 0x%x",
+ adp->ad_state);
+ }
+#endif /* DIAGNOSTIC */
+ adp->ad_state &= ~ATTACHED;
+ adp->ad_state |= UNDONE;
+ }
+ /*
+ * The on-disk inode cannot claim to be any larger than the last
+ * fragment that has been written. Otherwise, the on-disk inode
+ * might have fragments that were not the last block in the file
+ * which would corrupt the filesystem.
+ */
+ for (lastadp = NULL, adp = TAILQ_FIRST(&inodedep->id_inoupdt); adp;
+ lastadp = adp, adp = TAILQ_NEXT(adp, ad_next)) {
+ if (adp->ad_lbn >= NDADDR)
+ break;
+ dp->di_db[adp->ad_lbn] = adp->ad_oldblkno;
+ /* keep going until hitting a rollback to a frag */
+ if (adp->ad_oldsize == 0 || adp->ad_oldsize == fs->fs_bsize)
+ continue;
+ dp->di_size = fs->fs_bsize * adp->ad_lbn + adp->ad_oldsize;
+ for (i = adp->ad_lbn + 1; i < NDADDR; i++) {
+#ifdef DIAGNOSTIC
+ if (dp->di_db[i] != 0 && (deplist & (1 << i)) == 0) {
+ FREE_LOCK(&lk);
+ panic("softdep_write_inodeblock: lost dep1");
+ }
+#endif /* DIAGNOSTIC */
+ dp->di_db[i] = 0;
+ }
+ for (i = 0; i < NIADDR; i++) {
+#ifdef DIAGNOSTIC
+ if (dp->di_ib[i] != 0 &&
+ (deplist & ((1 << NDADDR) << i)) == 0) {
+ FREE_LOCK(&lk);
+ panic("softdep_write_inodeblock: lost dep2");
+ }
+#endif /* DIAGNOSTIC */
+ dp->di_ib[i] = 0;
+ }
+ FREE_LOCK(&lk);
+ return;
+ }
+ /*
+ * If we have zero'ed out the last allocated block of the file,
+ * roll back the size to the last currently allocated block.
+ * We know that this last allocated block is a full-sized as
+ * we already checked for fragments in the loop above.
+ */
+ if (lastadp != NULL &&
+ dp->di_size <= (lastadp->ad_lbn + 1) * fs->fs_bsize) {
+ for (i = lastadp->ad_lbn; i >= 0; i--)
+ if (dp->di_db[i] != 0)
+ break;
+ dp->di_size = (i + 1) * fs->fs_bsize;
+ }
+ /*
+ * The only dependencies are for indirect blocks.
+ *
+ * The file size for indirect block additions is not guaranteed.
+ * Such a guarantee would be non-trivial to achieve. The conventional
+ * synchronous write implementation also does not make this guarantee.
+ * Fsck should catch and fix discrepancies. Arguably, the file size
+ * can be over-estimated without destroying integrity when the file
+ * moves into the indirect blocks (i.e., is large). If we want to
+ * postpone fsck, we are stuck with this argument.
+ */
+ for (; adp; adp = TAILQ_NEXT(adp, ad_next))
+ dp->di_ib[adp->ad_lbn - NDADDR] = 0;
+ FREE_LOCK(&lk);
+}
+
+/*
+ * Version of initiate_write_inodeblock that handles UFS2 dinodes.
+ * Note that any bug fixes made to this routine must be done in the
+ * version found above.
+ *
+ * Called from within the procedure above to deal with unsatisfied
+ * allocation dependencies in an inodeblock. The buffer must be
+ * locked, thus, no I/O completion operations can occur while we
+ * are manipulating its associated dependencies.
+ */
+static void
+initiate_write_inodeblock_ufs2(inodedep, bp)
+ struct inodedep *inodedep;
+ struct buf *bp; /* The inode block */
+{
+ struct allocdirect *adp, *lastadp;
+ struct ufs2_dinode *dp;
+ struct fs *fs;
+ ufs_lbn_t i, prevlbn = 0;
+ int deplist;
+
+ if (inodedep->id_state & IOSTARTED)
+ panic("initiate_write_inodeblock_ufs2: already started");
+ inodedep->id_state |= IOSTARTED;
+ fs = inodedep->id_fs;
+ dp = (struct ufs2_dinode *)bp->b_data +
+ ino_to_fsbo(fs, inodedep->id_ino);
+ /*
+ * If the bitmap is not yet written, then the allocated
+ * inode cannot be written to disk.
+ */
+ if ((inodedep->id_state & DEPCOMPLETE) == 0) {
+ if (inodedep->id_savedino2 != NULL)
+ panic("initiate_write_inodeblock_ufs2: I/O underway");
+ MALLOC(inodedep->id_savedino2, struct ufs2_dinode *,
+ sizeof(struct ufs2_dinode), M_INODEDEP, M_SOFTDEP_FLAGS);
+ *inodedep->id_savedino2 = *dp;
+ bzero((caddr_t)dp, sizeof(struct ufs2_dinode));
+ return;
+ }
+ /*
+ * If no dependencies, then there is nothing to roll back.
+ */
+ inodedep->id_savedsize = dp->di_size;
+ if (TAILQ_FIRST(&inodedep->id_inoupdt) == NULL)
+ return;
+ /*
+ * Set the dependencies to busy.
+ */
+ ACQUIRE_LOCK(&lk);
+ for (deplist = 0, adp = TAILQ_FIRST(&inodedep->id_inoupdt); adp;
+ adp = TAILQ_NEXT(adp, ad_next)) {
+#ifdef DIAGNOSTIC
+ if (deplist != 0 && prevlbn >= adp->ad_lbn) {
+ FREE_LOCK(&lk);
+ panic("softdep_write_inodeblock: lbn order");
+ }
+ prevlbn = adp->ad_lbn;
+ if (adp->ad_lbn < NDADDR &&
+ dp->di_db[adp->ad_lbn] != adp->ad_newblkno) {
+ FREE_LOCK(&lk);
+ panic("%s: direct pointer #%lld mismatch %lld != %lld",
+ "softdep_write_inodeblock",
+ (intmax_t)adp->ad_lbn,
+ (intmax_t)dp->di_db[adp->ad_lbn],
+ (intmax_t)adp->ad_newblkno);
+ }
+ if (adp->ad_lbn >= NDADDR &&
+ dp->di_ib[adp->ad_lbn - NDADDR] != adp->ad_newblkno) {
+ FREE_LOCK(&lk);
+ panic("%s indirect pointer #%lld mismatch %lld != %lld",
+ "softdep_write_inodeblock:",
+ (intmax_t)adp->ad_lbn - NDADDR,
+ (intmax_t)dp->di_ib[adp->ad_lbn - NDADDR],
+ (intmax_t)adp->ad_newblkno);
}
deplist |= 1 << adp->ad_lbn;
if ((adp->ad_state & ATTACHED) == 0) {
@@ -3683,8 +3876,12 @@ handle_allocindir_partdone(aip)
LIST_INSERT_HEAD(&indirdep->ir_donehd, aip, ai_next);
return;
}
- ((ufs_daddr_t *)indirdep->ir_savebp->b_data)[aip->ai_offset] =
- aip->ai_newblkno;
+ if (indirdep->ir_state & UFS1FMT)
+ ((ufs1_daddr_t *)indirdep->ir_savebp->b_data)[aip->ai_offset] =
+ aip->ai_newblkno;
+ else
+ ((ufs2_daddr_t *)indirdep->ir_savebp->b_data)[aip->ai_offset] =
+ aip->ai_newblkno;
LIST_REMOVE(aip, ai_next);
if (aip->ai_freefrag != NULL)
add_to_worklist(&aip->ai_freefrag->ff_list);
@@ -3704,8 +3901,9 @@ handle_written_inodeblock(inodedep, bp)
{
struct worklist *wk, *filefree;
struct allocdirect *adp, *nextadp;
- struct dinode *dp;
- int hadchanges;
+ struct ufs1_dinode *dp1 = NULL;
+ struct ufs2_dinode *dp2 = NULL;
+ int hadchanges, fstype;
if ((inodedep->id_state & IOSTARTED) == 0) {
lk.lkt_held = NOHOLDER;
@@ -3713,8 +3911,15 @@ handle_written_inodeblock(inodedep, bp)
}
inodedep->id_state &= ~IOSTARTED;
inodedep->id_state |= COMPLETE;
- dp = (struct dinode *)bp->b_data +
- ino_to_fsbo(inodedep->id_fs, inodedep->id_ino);
+ if (inodedep->id_fs->fs_magic == FS_UFS1_MAGIC) {
+ fstype = UFS1;
+ dp1 = (struct ufs1_dinode *)bp->b_data +
+ ino_to_fsbo(inodedep->id_fs, inodedep->id_ino);
+ } else {
+ fstype = UFS2;
+ dp2 = (struct ufs2_dinode *)bp->b_data +
+ ino_to_fsbo(inodedep->id_fs, inodedep->id_ino);
+ }
/*
* If we had to rollback the inode allocation because of
* bitmaps being incomplete, then simply restore it.
@@ -3722,10 +3927,13 @@ handle_written_inodeblock(inodedep, bp)
* all associated dependencies have been cleared and the
* corresponding updates written to disk.
*/
- if (inodedep->id_savedino != NULL) {
- *dp = *inodedep->id_savedino;
- FREE(inodedep->id_savedino, M_INODEDEP);
- inodedep->id_savedino = NULL;
+ if (inodedep->id_savedino1 != NULL) {
+ if (fstype == UFS1)
+ *dp1 = *inodedep->id_savedino1;
+ else
+ *dp2 = *inodedep->id_savedino2;
+ FREE(inodedep->id_savedino1, M_INODEDEP);
+ inodedep->id_savedino1 = NULL;
if ((bp->b_flags & B_DELWRI) == 0)
stat_inode_bitmap++;
bdirty(bp);
@@ -3742,24 +3950,55 @@ handle_written_inodeblock(inodedep, bp)
lk.lkt_held = NOHOLDER;
panic("handle_written_inodeblock: new entry");
}
- if (adp->ad_lbn < NDADDR) {
- if (dp->di_db[adp->ad_lbn] != adp->ad_oldblkno) {
- lk.lkt_held = NOHOLDER;
- panic("%s: %s #%ld mismatch %d != %d",
- "handle_written_inodeblock",
- "direct pointer", adp->ad_lbn,
- dp->di_db[adp->ad_lbn], adp->ad_oldblkno);
+ if (fstype == UFS1) {
+ if (adp->ad_lbn < NDADDR) {
+ if (dp1->di_db[adp->ad_lbn]!=adp->ad_oldblkno) {
+ lk.lkt_held = NOHOLDER;
+ panic("%s %s #%lld mismatch %d != %lld",
+ "handle_written_inodeblock:",
+ "direct pointer",
+ (intmax_t)adp->ad_lbn,
+ dp1->di_db[adp->ad_lbn],
+ (intmax_t)adp->ad_oldblkno);
+ }
+ dp1->di_db[adp->ad_lbn] = adp->ad_newblkno;
+ } else {
+ if (dp1->di_ib[adp->ad_lbn - NDADDR] != 0) {
+ lk.lkt_held = NOHOLDER;
+ panic("%s: %s #%lld allocated as %d",
+ "handle_written_inodeblock",
+ "indirect pointer",
+ (intmax_t)adp->ad_lbn - NDADDR,
+ dp1->di_ib[adp->ad_lbn - NDADDR]);
+ }
+ dp1->di_ib[adp->ad_lbn - NDADDR] =
+ adp->ad_newblkno;
}
- dp->di_db[adp->ad_lbn] = adp->ad_newblkno;
} else {
- if (dp->di_ib[adp->ad_lbn - NDADDR] != 0) {
- lk.lkt_held = NOHOLDER;
- panic("%s: %s #%ld allocated as %d",
- "handle_written_inodeblock",
- "indirect pointer", adp->ad_lbn - NDADDR,
- dp->di_ib[adp->ad_lbn - NDADDR]);
+ if (adp->ad_lbn < NDADDR) {
+ if (dp2->di_db[adp->ad_lbn]!=adp->ad_oldblkno) {
+ lk.lkt_held = NOHOLDER;
+ panic("%s: %s #%lld %s %lld != %lld",
+ "handle_written_inodeblock",
+ "direct pointer",
+ (intmax_t)adp->ad_lbn, "mismatch",
+ (intmax_t)dp2->di_db[adp->ad_lbn],
+ (intmax_t)adp->ad_oldblkno);
+ }
+ dp2->di_db[adp->ad_lbn] = adp->ad_newblkno;
+ } else {
+ if (dp2->di_ib[adp->ad_lbn - NDADDR] != 0) {
+ lk.lkt_held = NOHOLDER;
+ panic("%s: %s #%lld allocated as %lld",
+ "handle_written_inodeblock",
+ "indirect pointer",
+ (intmax_t)adp->ad_lbn - NDADDR,
+ (intmax_t)
+ dp2->di_ib[adp->ad_lbn - NDADDR]);
+ }
+ dp2->di_ib[adp->ad_lbn - NDADDR] =
+ adp->ad_newblkno;
}
- dp->di_ib[adp->ad_lbn - NDADDR] = adp->ad_newblkno;
}
adp->ad_state &= ~UNDONE;
adp->ad_state |= ATTACHED;
@@ -3774,9 +4013,16 @@ handle_written_inodeblock(inodedep, bp)
lk.lkt_held = NOHOLDER;
panic("handle_written_inodeblock: bad size");
}
- if (dp->di_size != inodedep->id_savedsize) {
- dp->di_size = inodedep->id_savedsize;
- hadchanges = 1;
+ if (fstype == UFS1) {
+ if (dp1->di_size != inodedep->id_savedsize) {
+ dp1->di_size = inodedep->id_savedsize;
+ hadchanges = 1;
+ }
+ } else {
+ if (dp2->di_size != inodedep->id_savedsize) {
+ dp2->di_size = inodedep->id_savedsize;
+ hadchanges = 1;
+ }
}
inodedep->id_savedsize = -1;
/*
@@ -4859,7 +5105,8 @@ softdep_request_cleanup(fs, vp)
struct fs *fs;
struct vnode *vp;
{
- long starttime, needed;
+ long starttime;
+ ufs2_daddr_t needed;
needed = fs->fs_cstotal.cs_nbfree + fs->fs_contigsumsize;
starttime = time_second + tickdelay;
diff --git a/sys/ufs/ffs/ffs_softdep_stub.c b/sys/ufs/ffs/ffs_softdep_stub.c
index 36585f82a249..4bf0189be9ba 100644
--- a/sys/ufs/ffs/ffs_softdep_stub.c
+++ b/sys/ufs/ffs/ffs_softdep_stub.c
@@ -96,7 +96,7 @@ void
softdep_setup_blkmapdep(bp, fs, newblkno)
struct buf *bp;
struct fs *fs;
- ufs_daddr_t newblkno;
+ ufs2_daddr_t newblkno;
{
panic("softdep_setup_blkmapdep called");
@@ -106,8 +106,8 @@ void
softdep_setup_allocdirect(ip, lbn, newblkno, oldblkno, newsize, oldsize, bp)
struct inode *ip;
ufs_lbn_t lbn;
- ufs_daddr_t newblkno;
- ufs_daddr_t oldblkno;
+ ufs2_daddr_t newblkno;
+ ufs2_daddr_t oldblkno;
long newsize;
long oldsize;
struct buf *bp;
@@ -122,8 +122,8 @@ softdep_setup_allocindir_page(ip, lbn, bp, ptrno, newblkno, oldblkno, nbp)
ufs_lbn_t lbn;
struct buf *bp;
int ptrno;
- ufs_daddr_t newblkno;
- ufs_daddr_t oldblkno;
+ ufs2_daddr_t newblkno;
+ ufs2_daddr_t oldblkno;
struct buf *nbp;
{
@@ -136,7 +136,7 @@ softdep_setup_allocindir_meta(nbp, ip, bp, ptrno, newblkno)
struct inode *ip;
struct buf *bp;
int ptrno;
- ufs_daddr_t newblkno;
+ ufs2_daddr_t newblkno;
{
panic("softdep_setup_allocindir_meta called");
diff --git a/sys/ufs/ffs/ffs_subr.c b/sys/ufs/ffs/ffs_subr.c
index f484090bb766..773a8d31afdc 100644
--- a/sys/ufs/ffs/ffs_subr.c
+++ b/sys/ufs/ffs/ffs_subr.c
@@ -35,15 +35,18 @@
*/
#include <sys/param.h>
-#include <ufs/ffs/fs.h>
#ifndef _KERNEL
#include <ufs/ufs/dinode.h>
+#include <ufs/ffs/fs.h>
#else
#include "opt_ddb.h"
#include <sys/systm.h>
+#include <sys/stdint.h>
#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mount.h>
#include <sys/vnode.h>
#include <sys/bio.h>
#include <sys/buf.h>
@@ -51,7 +54,11 @@
#include <ufs/ufs/quota.h>
#include <ufs/ufs/inode.h>
+#include <ufs/ufs/extattr.h>
+#include <ufs/ufs/ufsmount.h>
+#include <ufs/ufs/ufs_extern.h>
#include <ufs/ffs/ffs_extern.h>
+#include <ufs/ffs/fs.h>
#ifdef DDB
void ffs_checkoverlap(struct buf *, struct inode *);
@@ -72,7 +79,7 @@ ffs_blkatoff(vp, offset, res, bpp)
struct inode *ip;
struct fs *fs;
struct buf *bp;
- ufs_daddr_t lbn;
+ ufs_lbn_t lbn;
int bsize, error;
ip = VTOI(vp);
@@ -91,7 +98,49 @@ ffs_blkatoff(vp, offset, res, bpp)
*bpp = bp;
return (0);
}
-#endif
+
+/*
+ * Load up the contents of an inode and copy the appropriate pieces
+ * to the incore copy.
+ */
+void
+ffs_load_inode(bp, ip, mtype, fs, ino)
+ struct buf *bp;
+ struct inode *ip;
+ struct malloc_type *mtype;
+ struct fs *fs;
+ ino_t ino;
+{
+
+ if (ip->i_ump->um_fstype == UFS1) {
+ if (mtype != NULL)
+ MALLOC(ip->i_din1, struct ufs1_dinode *,
+ sizeof(struct ufs1_dinode), mtype, M_WAITOK);
+ *ip->i_din1 =
+ *((struct ufs1_dinode *)bp->b_data + ino_to_fsbo(fs, ino));
+ ip->i_mode = ip->i_din1->di_mode;
+ ip->i_nlink = ip->i_din1->di_nlink;
+ ip->i_size = ip->i_din1->di_size;
+ ip->i_flags = ip->i_din1->di_flags;
+ ip->i_gen = ip->i_din1->di_gen;
+ ip->i_uid = ip->i_din1->di_uid;
+ ip->i_gid = ip->i_din1->di_gid;
+ } else {
+ if (mtype != NULL)
+ MALLOC(ip->i_din2, struct ufs2_dinode *,
+ sizeof(struct ufs2_dinode), mtype, M_WAITOK);
+ *ip->i_din2 =
+ *((struct ufs2_dinode *)bp->b_data + ino_to_fsbo(fs, ino));
+ ip->i_mode = ip->i_din2->di_mode;
+ ip->i_nlink = ip->i_din2->di_nlink;
+ ip->i_size = ip->i_din2->di_size;
+ ip->i_flags = ip->i_din2->di_flags;
+ ip->i_gen = ip->i_din2->di_gen;
+ ip->i_uid = ip->i_din2->di_uid;
+ ip->i_gid = ip->i_din2->di_gid;
+ }
+}
+#endif /* KERNEL */
/*
* Update the frsum fields to reflect addition or deletion
@@ -135,7 +184,7 @@ ffs_checkoverlap(bp, ip)
struct inode *ip;
{
struct buf *ebp, *ep;
- ufs_daddr_t start, last;
+ ufs2_daddr_t start, last;
struct vnode *vp;
ebp = &buf[nbuf];
@@ -151,9 +200,9 @@ ffs_checkoverlap(bp, ip)
ep->b_blkno + btodb(ep->b_bcount) <= start)
continue;
vprint("Disk overlap", vp);
- (void)printf("\tstart %lu, end %lu overlap start %lu, end %lu\n",
- (u_long)start, (u_long)last, (u_long)ep->b_blkno,
- (u_long)(ep->b_blkno + btodb(ep->b_bcount) - 1));
+ printf("\tstart %llu, end %llu overlap start %llu, end %llu\n",
+ (intmax_t)start, (intmax_t)last, (intmax_t)ep->b_blkno,
+ (intmax_t)(ep->b_blkno + btodb(ep->b_bcount) - 1));
panic("ffs_checkoverlap: Disk buffer overlap");
}
}
@@ -168,7 +217,7 @@ int
ffs_isblock(fs, cp, h)
struct fs *fs;
unsigned char *cp;
- ufs_daddr_t h;
+ ufs1_daddr_t h;
{
unsigned char mask;
@@ -197,7 +246,7 @@ int
ffs_isfreeblock(fs, cp, h)
struct fs *fs;
unsigned char *cp;
- ufs_daddr_t h;
+ ufs1_daddr_t h;
{
switch ((int)fs->fs_frag) {
@@ -222,7 +271,7 @@ void
ffs_clrblock(fs, cp, h)
struct fs *fs;
u_char *cp;
- ufs_daddr_t h;
+ ufs1_daddr_t h;
{
switch ((int)fs->fs_frag) {
@@ -250,7 +299,7 @@ void
ffs_setblock(fs, cp, h)
struct fs *fs;
unsigned char *cp;
- ufs_daddr_t h;
+ ufs1_daddr_t h;
{
switch ((int)fs->fs_frag) {
diff --git a/sys/ufs/ffs/ffs_tables.c b/sys/ufs/ffs/ffs_tables.c
index 1ffae90e4776..b86a9ac64b25 100644
--- a/sys/ufs/ffs/ffs_tables.c
+++ b/sys/ufs/ffs/ffs_tables.c
@@ -35,6 +35,7 @@
*/
#include <sys/param.h>
+#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
/*
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index ed52815e586c..53a1ea5be61f 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -39,6 +39,7 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/stdint.h>
#include <sys/namei.h>
#include <sys/proc.h>
#include <sys/kernel.h>
@@ -67,8 +68,10 @@
static MALLOC_DEFINE(M_FFSNODE, "FFS node", "FFS vnode private part");
static int ffs_sbupdate(struct ufsmount *, int);
-int ffs_reload(struct mount *,struct ucred *,struct thread *);
-static int ffs_oldfscompat(struct fs *);
+ int ffs_reload(struct mount *,struct ucred *,struct thread *);
+static void ffs_oldfscompat_read(struct fs *, struct ufsmount *,
+ ufs2_daddr_t);
+static void ffs_oldfscompat_write(struct fs *, struct ufsmount *);
static int ffs_init(struct vfsconf *);
static struct vfsops ufs_vfsops = {
@@ -139,8 +142,8 @@ ffs_mount(mp, path, data, ndp, td)
struct nameidata *ndp; /* mount point credentials*/
struct thread *td; /* process requesting mount*/
{
- size_t size;
- struct vnode *devvp;
+ size_t size;
+ struct vnode *devvp;
struct ufs_args args;
struct ufsmount *ump = 0;
struct fs *fs;
@@ -201,8 +204,9 @@ ffs_mount(mp, path, data, ndp, td)
}
if (fs->fs_pendingblocks != 0 ||
fs->fs_pendinginodes != 0) {
- printf("%s: update error: blocks %d files %d\n",
- fs->fs_fsmnt, fs->fs_pendingblocks,
+ printf("%s: %s: blocks %lld files %d\n",
+ fs->fs_fsmnt, "update error",
+ (intmax_t)fs->fs_pendingblocks,
fs->fs_pendinginodes);
fs->fs_pendingblocks = 0;
fs->fs_pendinginodes = 0;
@@ -384,9 +388,9 @@ ffs_reload(mp, cred, td)
struct buf *bp;
struct fs *fs, *newfs;
dev_t dev;
+ ufs2_daddr_t sblockloc;
int i, blks, size, error;
int32_t *lp;
- u_int sectorsize;
if ((mp->mnt_flag & MNT_RDONLY) == 0)
return (EINVAL);
@@ -416,20 +420,18 @@ ffs_reload(mp, cred, td)
/*
* Step 2: re-read superblock from disk.
*/
- if (VOP_IOCTL(devvp, DIOCGSECTORSIZE, (caddr_t)&sectorsize,
- FREAD, NOCRED, td) != 0)
- size = DEV_BSIZE;
- else
- size = sectorsize;
- if ((error = bread(devvp, (ufs_daddr_t)(SBOFF/size), SBSIZE, NOCRED,&bp)) != 0)
+ fs = VFSTOUFS(mp)->um_fs;
+ if ((error = bread(devvp, fsbtodb(fs, fs->fs_sblockloc), fs->fs_sbsize,
+ NOCRED, &bp)) != 0)
return (error);
newfs = (struct fs *)bp->b_data;
- if (newfs->fs_magic != FS_MAGIC || newfs->fs_bsize > MAXBSIZE ||
- newfs->fs_bsize < sizeof(struct fs)) {
+ if ((newfs->fs_magic != FS_UFS1_MAGIC &&
+ newfs->fs_magic != FS_UFS2_MAGIC) ||
+ newfs->fs_bsize > MAXBSIZE ||
+ newfs->fs_bsize < sizeof(struct fs)) {
brelse(bp);
return (EIO); /* XXX needs translation */
}
- fs = VFSTOUFS(mp)->um_fs;
/*
* Copy pointer fields back into superblock before copying in XXX
* new superblock. These should really be in the ufsmount. XXX
@@ -439,20 +441,15 @@ ffs_reload(mp, cred, td)
newfs->fs_maxcluster = fs->fs_maxcluster;
newfs->fs_contigdirs = fs->fs_contigdirs;
newfs->fs_active = fs->fs_active;
+ sblockloc = fs->fs_sblockloc;
bcopy(newfs, fs, (u_int)fs->fs_sbsize);
- if (fs->fs_sbsize < SBSIZE)
- bp->b_flags |= B_INVAL | B_NOCACHE;
brelse(bp);
mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
- ffs_oldfscompat(fs);
- /* An old fsck may have zeroed these fields, so recheck them. */
- if (fs->fs_avgfilesize <= 0) /* XXX */
- fs->fs_avgfilesize = AVFILESIZ; /* XXX */
- if (fs->fs_avgfpdir <= 0) /* XXX */
- fs->fs_avgfpdir = AFPDIR; /* XXX */
+ ffs_oldfscompat_read(fs, VFSTOUFS(mp), sblockloc);
if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) {
- printf("%s: reload pending error: blocks %d files %d\n",
- fs->fs_fsmnt, fs->fs_pendingblocks, fs->fs_pendinginodes);
+ printf("%s: reload pending error: blocks %lld files %d\n",
+ fs->fs_fsmnt, (intmax_t)fs->fs_pendingblocks,
+ fs->fs_pendinginodes);
fs->fs_pendingblocks = 0;
fs->fs_pendinginodes = 0;
}
@@ -517,8 +514,7 @@ loop:
vput(vp);
return (error);
}
- ip->i_din = *((struct dinode *)bp->b_data +
- ino_to_fsbo(fs, ip->i_number));
+ ffs_load_inode(bp, ip, NULL, fs, ip->i_number);
ip->i_effnlink = ip->i_nlink;
brelse(bp);
vput(vp);
@@ -528,9 +524,10 @@ loop:
return (0);
}
-#include <sys/sysctl.h>
-int bigcgs = 0;
-SYSCTL_INT(_debug, OID_AUTO, bigcgs, CTLFLAG_RW, &bigcgs, 0, "");
+/*
+ * Possible superblock locations ordered from most to least likely.
+ */
+static int sblock_try[] = SBLOCKSEARCH;
/*
* Common code for mount and mountroot
@@ -547,10 +544,10 @@ ffs_mountfs(devvp, mp, td, malloctype)
struct fs *fs;
dev_t dev;
void *space;
+ ufs2_daddr_t sblockloc;
int error, i, blks, size, ronly;
int32_t *lp;
struct ucred *cred;
- u_int64_t maxfilesize; /* XXX */
size_t strsize;
int ncount;
u_int sectorsize;
@@ -617,15 +614,32 @@ ffs_mountfs(devvp, mp, td, malloctype)
bp = NULL;
ump = NULL;
- if ((error = bread(devvp, SBLOCK, SBSIZE, cred, &bp)) != 0)
- goto out;
- fs = (struct fs *)bp->b_data;
- if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
- fs->fs_bsize < sizeof(struct fs)) {
+ fs = NULL;
+ sblockloc = 0;
+ /*
+ * Try reading the superblock in each of its possible locations.
+ */
+ for (i = 0; sblock_try[i] != -1; i++) {
+ if ((error = bread(devvp, sblock_try[i] / size, SBLOCKSIZE,
+ cred, &bp)) != 0)
+ goto out;
+ fs = (struct fs *)bp->b_data;
+ sblockloc = numfrags(fs, sblock_try[i]);
+ if ((fs->fs_magic == FS_UFS1_MAGIC ||
+ (fs->fs_magic == FS_UFS2_MAGIC &&
+ fs->fs_sblockloc == sblockloc)) &&
+ fs->fs_bsize <= MAXBSIZE &&
+ fs->fs_bsize >= sizeof(struct fs))
+ break;
+ brelse(bp);
+ bp = NULL;
+ }
+ if (sblock_try[i] == -1) {
error = EINVAL; /* XXX needs translation */
goto out;
}
fs->fs_fmod = 0;
+ fs->fs_flags &= ~FS_INDEXDIRS; /* no support for directory indicies */
fs->fs_flags &= ~FS_UNCLEAN;
if (fs->fs_clean == 0) {
fs->fs_flags |= FS_UNCLEAN;
@@ -642,40 +656,45 @@ ffs_mountfs(devvp, mp, td, malloctype)
error = EPERM;
goto out;
}
- if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) {
- printf("%s: lost blocks %d files %d\n", fs->fs_fsmnt,
- fs->fs_pendingblocks, fs->fs_pendinginodes);
+ if ((fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) &&
+ (mp->mnt_flag & MNT_FORCE)) {
+ printf("%s: lost blocks %lld files %d\n", fs->fs_fsmnt,
+ (intmax_t)fs->fs_pendingblocks,
+ fs->fs_pendinginodes);
fs->fs_pendingblocks = 0;
fs->fs_pendinginodes = 0;
}
}
if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) {
- printf("%s: mount pending error: blocks %d files %d\n",
- fs->fs_fsmnt, fs->fs_pendingblocks, fs->fs_pendinginodes);
+ printf("%s: mount pending error: blocks %lld files %d\n",
+ fs->fs_fsmnt, (intmax_t)fs->fs_pendingblocks,
+ fs->fs_pendinginodes);
fs->fs_pendingblocks = 0;
fs->fs_pendinginodes = 0;
}
- /* XXX updating 4.2 FFS superblocks trashes rotational layout tables */
- if (fs->fs_postblformat == FS_42POSTBLFMT && !ronly) {
- error = EROFS; /* needs translation */
- goto out;
- }
ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK | M_ZERO);
ump->um_malloctype = malloctype;
ump->um_fs = malloc((u_long)fs->fs_sbsize, M_UFSMNT,
M_WAITOK);
+ if (fs->fs_magic == FS_UFS1_MAGIC) {
+ ump->um_fstype = UFS1;
+ ump->um_balloc = ffs_balloc_ufs1;
+ } else {
+ ump->um_fstype = UFS2;
+ ump->um_balloc = ffs_balloc_ufs2;
+ }
ump->um_blkatoff = ffs_blkatoff;
ump->um_truncate = ffs_truncate;
ump->um_update = ffs_update;
ump->um_valloc = ffs_valloc;
ump->um_vfree = ffs_vfree;
- ump->um_balloc = ffs_balloc;
bcopy(bp->b_data, ump->um_fs, (u_int)fs->fs_sbsize);
- if (fs->fs_sbsize < SBSIZE)
+ if (fs->fs_sbsize < SBLOCKSIZE)
bp->b_flags |= B_INVAL | B_NOCACHE;
brelse(bp);
bp = NULL;
fs = ump->um_fs;
+ ffs_oldfscompat_read(fs, ump, sblockloc);
fs->fs_ronly = ronly;
size = fs->fs_cssize;
blks = howmany(size, fs->fs_fsize);
@@ -708,11 +727,6 @@ ffs_mountfs(devvp, mp, td, malloctype)
fs->fs_contigdirs = (u_int8_t *)space;
bzero(fs->fs_contigdirs, size);
fs->fs_active = NULL;
- /* Compatibility for old filesystems XXX */
- if (fs->fs_avgfilesize <= 0) /* XXX */
- fs->fs_avgfilesize = AVFILESIZ; /* XXX */
- if (fs->fs_avgfpdir <= 0) /* XXX */
- fs->fs_avgfpdir = AFPDIR; /* XXX */
mp->mnt_data = (qaddr_t)ump;
mp->mnt_stat.f_fsid.val[0] = fs->fs_id[0];
mp->mnt_stat.f_fsid.val[1] = fs->fs_id[1];
@@ -733,7 +747,6 @@ ffs_mountfs(devvp, mp, td, malloctype)
ufs_extattr_uepm_init(&ump->um_extattr);
#endif
devvp->v_rdev->si_mountpoint = mp;
- ffs_oldfscompat(fs);
/*
* Set FS local "last mounted on" information (NULL pad)
@@ -753,15 +766,6 @@ ffs_mountfs(devvp, mp, td, malloctype)
mp->mnt_time = fs->fs_time;
}
- ump->um_savedmaxfilesize = fs->fs_maxfilesize; /* XXX */
- maxfilesize = (u_int64_t)0x40000000 * fs->fs_bsize - 1; /* XXX */
- if (fs->fs_maxfilesize > maxfilesize) /* XXX */
- fs->fs_maxfilesize = maxfilesize; /* XXX */
- if (bigcgs) {
- if (fs->fs_sparecon[0] <= 0)
- fs->fs_sparecon[0] = fs->fs_cgsize;
- fs->fs_cgsize = fs->fs_bsize;
- }
if (ronly == 0) {
if ((fs->fs_flags & FS_DOSOFTDEP) &&
(error = softdep_mount(devvp, mp, fs, cred)) != 0) {
@@ -808,36 +812,90 @@ out:
return (error);
}
+#include <sys/sysctl.h>
+int bigcgs = 0;
+SYSCTL_INT(_debug, OID_AUTO, bigcgs, CTLFLAG_RW, &bigcgs, 0, "");
+
/*
- * Sanity checks for old filesystems.
+ * Sanity checks for loading old filesystem superblocks.
+ * See ffs_oldfscompat_write below for unwound actions.
*
- * XXX - goes away some day.
+ * XXX - Parts get retired eventually.
+ * Unfortunately new bits get added.
*/
-static int
-ffs_oldfscompat(fs)
+static void
+ffs_oldfscompat_read(fs, ump, sblockloc)
struct fs *fs;
+ struct ufsmount *ump;
+ ufs2_daddr_t sblockloc;
{
+ off_t maxfilesize;
- fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect); /* XXX */
- fs->fs_interleave = max(fs->fs_interleave, 1); /* XXX */
- if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
- fs->fs_nrpos = 8; /* XXX */
- if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
-#if 0
- int i; /* XXX */
- u_int64_t sizepb = fs->fs_bsize; /* XXX */
- /* XXX */
- fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */
- for (i = 0; i < NIADDR; i++) { /* XXX */
- sizepb *= NINDIR(fs); /* XXX */
- fs->fs_maxfilesize += sizepb; /* XXX */
- } /* XXX */
-#endif
+ /*
+ * If not yet done, update UFS1 superblock with new wider fields.
+ */
+ if (fs->fs_magic == FS_UFS1_MAGIC &&
+ fs->fs_sblockloc != sblockloc) {
+ fs->fs_maxbsize = fs->fs_bsize;
+ fs->fs_sblockloc = sblockloc;
+ fs->fs_time = fs->fs_old_time;
+ fs->fs_size = fs->fs_old_size;
+ fs->fs_dsize = fs->fs_old_dsize;
+ fs->fs_csaddr = fs->fs_old_csaddr;
+ fs->fs_cstotal.cs_ndir = fs->fs_old_cstotal.cs_ndir;
+ fs->fs_cstotal.cs_nbfree = fs->fs_old_cstotal.cs_nbfree;
+ fs->fs_cstotal.cs_nifree = fs->fs_old_cstotal.cs_nifree;
+ fs->fs_cstotal.cs_nffree = fs->fs_old_cstotal.cs_nffree;
+ }
+ if (fs->fs_magic == FS_UFS1_MAGIC &&
+ fs->fs_old_inodefmt < FS_44INODEFMT) {
fs->fs_maxfilesize = (u_quad_t) 1LL << 39;
- fs->fs_qbmask = ~fs->fs_bmask; /* XXX */
- fs->fs_qfmask = ~fs->fs_fmask; /* XXX */
- } /* XXX */
- return (0);
+ fs->fs_qbmask = ~fs->fs_bmask;
+ fs->fs_qfmask = ~fs->fs_fmask;
+ }
+ ump->um_savedmaxfilesize = fs->fs_maxfilesize;
+ maxfilesize = (u_int64_t)0x40000000 * fs->fs_bsize - 1;
+ if (fs->fs_maxfilesize > maxfilesize)
+ fs->fs_maxfilesize = maxfilesize;
+ /* Compatibility for old filesystems */
+ if (fs->fs_avgfilesize <= 0)
+ fs->fs_avgfilesize = AVFILESIZ;
+ if (fs->fs_avgfpdir <= 0)
+ fs->fs_avgfpdir = AFPDIR;
+ if (bigcgs) {
+ fs->fs_save_cgsize = fs->fs_cgsize;
+ fs->fs_cgsize = fs->fs_bsize;
+ }
+}
+
+/*
+ * Unwinding superblock updates for old filesystems.
+ * See ffs_oldfscompat_read above for details.
+ *
+ * XXX - Parts get retired eventually.
+ * Unfortunately new bits get added.
+ */
+static void
+ffs_oldfscompat_write(fs, ump)
+ struct fs *fs;
+ struct ufsmount *ump;
+{
+
+ /*
+ * Copy back UFS2 updated fields that UFS1 inspects.
+ */
+ if (fs->fs_magic == FS_UFS1_MAGIC) {
+ fs->fs_old_time = fs->fs_time;
+ fs->fs_old_cstotal.cs_ndir = fs->fs_cstotal.cs_ndir;
+ fs->fs_old_cstotal.cs_nbfree = fs->fs_cstotal.cs_nbfree;
+ fs->fs_old_cstotal.cs_nifree = fs->fs_cstotal.cs_nifree;
+ fs->fs_old_cstotal.cs_nffree = fs->fs_cstotal.cs_nffree;
+ }
+ fs->fs_maxfilesize = ump->um_savedmaxfilesize;
+ if (bigcgs) {
+ fs->fs_cgsize = fs->fs_save_cgsize;
+ fs->fs_save_cgsize = 0;
+ }
}
/*
@@ -874,13 +932,10 @@ ffs_unmount(mp, mntflags, td)
return (error);
}
fs = ump->um_fs;
- if (bigcgs) {
- fs->fs_cgsize = fs->fs_sparecon[0];
- fs->fs_sparecon[0] = 0;
- }
if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) {
- printf("%s: unmount pending error: blocks %d files %d\n",
- fs->fs_fsmnt, fs->fs_pendingblocks, fs->fs_pendinginodes);
+ printf("%s: unmount pending error: blocks %lld files %d\n",
+ fs->fs_fsmnt, (intmax_t)fs->fs_pendingblocks,
+ fs->fs_pendinginodes);
fs->fs_pendingblocks = 0;
fs->fs_pendinginodes = 0;
}
@@ -980,7 +1035,7 @@ ffs_statfs(mp, sbp, td)
ump = VFSTOUFS(mp);
fs = ump->um_fs;
- if (fs->fs_magic != FS_MAGIC)
+ if (fs->fs_magic != FS_UFS1_MAGIC && fs->fs_magic != FS_UFS2_MAGIC)
panic("ffs_statfs");
sbp->f_bsize = fs->fs_fsize;
sbp->f_iosize = fs->fs_bsize;
@@ -1173,6 +1228,7 @@ ffs_vget(mp, ino, flags, vpp)
lockinit(vp->v_vnlock, PINOD, "inode", VLKTIMEOUT, LK_CANRECURSE);
vp->v_data = ip;
ip->i_vnode = vp;
+ ip->i_ump = ump;
ip->i_fs = fs = ump->um_fs;
ip->i_dev = dev;
ip->i_number = ino;
@@ -1222,7 +1278,7 @@ ffs_vget(mp, ino, flags, vpp)
*vpp = NULL;
return (error);
}
- ip->i_din = *((struct dinode *)bp->b_data + ino_to_fsbo(fs, ino));
+ ffs_load_inode(bp, ip, ump->um_malloctype, fs, ino);
if (DOINGSOFTDEP(vp))
softdep_load_inodeblock(ip);
else
@@ -1250,16 +1306,19 @@ ffs_vget(mp, ino, flags, vpp)
*/
if (ip->i_gen == 0) {
ip->i_gen = random() / 2 + 1;
- if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
+ if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
ip->i_flag |= IN_MODIFIED;
+ DIP(ip, i_gen) = ip->i_gen;
+ }
}
/*
* Ensure that uid and gid are correct. This is a temporary
* fix until fsck has been changed to do the update.
*/
- if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
- ip->i_uid = ip->i_din.di_ouid; /* XXX */
- ip->i_gid = ip->i_din.di_ogid; /* XXX */
+ if (fs->fs_magic == FS_UFS1_MAGIC && /* XXX */
+ fs->fs_old_inodefmt < FS_44INODEFMT) { /* XXX */
+ ip->i_uid = ip->i_din1->di_ouid; /* XXX */
+ ip->i_gid = ip->i_din1->di_ogid; /* XXX */
} /* XXX */
*vpp = vp;
@@ -1333,7 +1392,7 @@ ffs_sbupdate(mp, waitfor)
struct ufsmount *mp;
int waitfor;
{
- struct fs *dfs, *fs = mp->um_fs;
+ struct fs *fs = mp->um_fs;
struct buf *bp;
int blks;
void *space;
@@ -1364,24 +1423,12 @@ ffs_sbupdate(mp, waitfor)
*/
if (allerror)
return (allerror);
- bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize, 0, 0);
+ bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_sblockloc),
+ (int)fs->fs_sbsize, 0, 0);
fs->fs_fmod = 0;
fs->fs_time = time_second;
bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize);
- /* Restore compatibility to old filesystems. XXX */
- dfs = (struct fs *)bp->b_data; /* XXX */
- if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
- dfs->fs_nrpos = -1; /* XXX */
- if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
- int32_t *lp, tmp; /* XXX */
- /* XXX */
- lp = (int32_t *)&dfs->fs_qbmask; /* XXX */
- tmp = lp[4]; /* XXX */
- for (i = 4; i > 0; i--) /* XXX */
- lp[i] = lp[i-1]; /* XXX */
- lp[0] = tmp; /* XXX */
- } /* XXX */
- dfs->fs_maxfilesize = mp->um_savedmaxfilesize; /* XXX */
+ ffs_oldfscompat_write((struct fs *)bp->b_data, mp);
if (waitfor != MNT_WAIT)
bawrite(bp);
else if ((error = bwrite(bp)) != 0)
diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c
index 6615222acd59..0c5e8c4402c9 100644
--- a/sys/ufs/ffs/ffs_vnops.c
+++ b/sys/ufs/ffs/ffs_vnops.c
@@ -126,7 +126,7 @@ ffs_fsync(ap)
struct buf *bp;
struct buf *nbp;
int s, error, wait, passes, skipmeta;
- daddr_t lbn;
+ ufs_lbn_t lbn;
wait = (ap->a_waitfor == MNT_WAIT);
if (vn_isdisk(vp, NULL)) {
diff --git a/sys/ufs/ffs/fs.h b/sys/ufs/ffs/fs.h
index 837f902dc209..822f4eb7bbc1 100644
--- a/sys/ufs/ffs/fs.h
+++ b/sys/ufs/ffs/fs.h
@@ -58,14 +58,30 @@
* The beginning of cylinder group cg in fs, is given by
* the ``cgbase(fs, cg)'' macro.
*
- * The size and offset of the super-block in sector-size neutral bytes.
+ * Depending on the architecture and the media, the superblock may
+ * reside in any one of four places. For tiny media where every block
+ * counts, it is placed at the very front of the partition. Historically,
+ * UFS1 placed it 8K from the front to leave room for the disk label and
+ * a small bootstrap. For UFS2 it got moved to 64K from the front to leave
+ * room for the disk label and a bigger bootstrap, and for really piggy
+ * systems we check at 256K from the front if the first three fail. In
+ * all cases the size of the superblock will be SBLOCKSIZE. All values are
+ * given in byte-offset form, so they do not imply a sector size. The
+ * SBLOCKSEARCH specifies the order in which the locations should be searched.
+ */
+#define SBLOCK_FLOPPY 0
+#define SBLOCK_UFS1 8192
+#define SBLOCK_UFS2 65536
+#define SBLOCK_PIGGY 262144
+#define SBLOCKSIZE 8192
+#define SBLOCKSEARCH \
+ { SBLOCK_UFS2, SBLOCK_UFS1, SBLOCK_FLOPPY, SBLOCK_PIGGY, -1 }
+
+/*
+ * Max number of fragments per block. This value is NOT tweakable.
*/
-#define SBSIZE 8192
-#define SBOFF ((off_t)(BBSIZE))
-#define SBLOCK ((ufs_daddr_t)(SBOFF / DEV_BSIZE))
-
-/* Max number of fragments per block, this is not tweakable */
#define MAXFRAG 8
+
/*
* Addresses stored in inodes are capable of addressing fragments
* of `blocks'. File system blocks of at most size MAXBSIZE can
@@ -176,8 +192,8 @@
* identify blocks that are in use by other snapshots (which are
* expunged from this snapshot).
*/
-#define BLK_NOCOPY ((ufs_daddr_t)(1))
-#define BLK_SNAP ((ufs_daddr_t)(2))
+#define BLK_NOCOPY ((ufs2_daddr_t)(1))
+#define BLK_SNAP ((ufs2_daddr_t)(2))
/*
* Sysctl values for the fast filesystem.
@@ -193,12 +209,13 @@
/*
* Command structure passed in to the filesystem to adjust filesystem values.
*/
-#define FFS_CMD_VERSION 0x05181979 /* version ID */
+#define FFS_CMD_VERSION 0x19790518 /* version ID */
struct fsck_cmd {
- int version; /* version of command structure */
- int handle; /* reference to filesystem to be changed */
- off_t value; /* inode or block number to be affected */
- long size; /* amount or range to be adjusted */
+ int32_t version; /* version of command structure */
+ int32_t handle; /* reference to filesystem to be changed */
+ int64_t value; /* inode or block number to be affected */
+ int64_t size; /* amount or range to be adjusted */
+ int64_t spare; /* reserved for future use */
};
/*
@@ -213,6 +230,14 @@ struct csum {
int32_t cs_nifree; /* number of free inodes */
int32_t cs_nffree; /* number of free frags */
};
+struct csum_total {
+ int64_t cs_ndir; /* number of directories */
+ int64_t cs_nbfree; /* number of free blocks */
+ int64_t cs_nifree; /* number of free inodes */
+ int64_t cs_nffree; /* number of free frags */
+ int64_t cs_numclusters; /* number of free clusters */
+ int64_t cs_spare[3]; /* future expansion */
+};
/*
* Super block for an FFS filesystem.
@@ -220,23 +245,23 @@ struct csum {
struct fs {
int32_t fs_firstfield; /* historic filesystem linked list, */
int32_t fs_unused_1; /* used for incore super blocks */
- ufs_daddr_t fs_sblkno; /* addr of super-block in filesys */
- ufs_daddr_t fs_cblkno; /* offset of cyl-block in filesys */
- ufs_daddr_t fs_iblkno; /* offset of inode-blocks in filesys */
- ufs_daddr_t fs_dblkno; /* offset of first data after cg */
- int32_t fs_cgoffset; /* cylinder group offset in cylinder */
- int32_t fs_cgmask; /* used to calc mod fs_ntrak */
- ufs_time_t fs_time; /* last time written */
- int32_t fs_size; /* number of blocks in fs */
- int32_t fs_dsize; /* number of data blocks in fs */
+ int32_t fs_sblkno; /* offset of super-block in filesys */
+ int32_t fs_cblkno; /* offset of cyl-block in filesys */
+ int32_t fs_iblkno; /* offset of inode-blocks in filesys */
+ int32_t fs_dblkno; /* offset of first data after cg */
+ int32_t fs_old_cgoffset; /* cylinder group offset in cylinder */
+ int32_t fs_old_cgmask; /* used to calc mod fs_ntrak */
+ int32_t fs_old_time; /* last time written */
+ int32_t fs_old_size; /* number of blocks in fs */
+ int32_t fs_old_dsize; /* number of data blocks in fs */
int32_t fs_ncg; /* number of cylinder groups */
int32_t fs_bsize; /* size of basic blocks in fs */
int32_t fs_fsize; /* size of frag blocks in fs */
int32_t fs_frag; /* number of frags in a block in fs */
/* these are configuration parameters */
int32_t fs_minfree; /* minimum percentage of free blocks */
- int32_t fs_rotdelay; /* num of ms for optimal next block */
- int32_t fs_rps; /* disk revolutions per second */
+ int32_t fs_old_rotdelay; /* num of ms for optimal next block */
+ int32_t fs_old_rps; /* disk revolutions per second */
/* these fields can be computed from the others */
int32_t fs_bmask; /* ``blkoff'' calc of blk offsets */
int32_t fs_fmask; /* ``fragoff'' calc of frag offsets */
@@ -249,35 +274,30 @@ struct fs {
int32_t fs_fragshift; /* block to frag shift */
int32_t fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */
int32_t fs_sbsize; /* actual size of super block */
- int32_t fs_csmask; /* csum block offset (now unused) */
- int32_t fs_csshift; /* csum block number (now unused) */
+ int32_t fs_spare1[2]; /* old fs_csmask */
+ /* old fs_csshift */
int32_t fs_nindir; /* value of NINDIR */
int32_t fs_inopb; /* value of INOPB */
- int32_t fs_nspf; /* value of NSPF */
+ int32_t fs_old_nspf; /* value of NSPF */
/* yet another configuration parameter */
int32_t fs_optim; /* optimization preference, see below */
-/* these fields are derived from the hardware */
- int32_t fs_npsect; /* # sectors/track including spares */
- int32_t fs_interleave; /* hardware sector interleave */
- int32_t fs_trackskew; /* sector 0 skew, per track */
-/* fs_id takes the space of the unused fs_headswitch and fs_trkseek fields */
+ int32_t fs_old_npsect; /* # sectors/track including spares */
+ int32_t fs_old_interleave; /* hardware sector interleave */
+ int32_t fs_old_trackskew; /* sector 0 skew, per track */
int32_t fs_id[2]; /* unique filesystem id */
/* sizes determined by number of cylinder groups and their sizes */
- ufs_daddr_t fs_csaddr; /* blk addr of cyl grp summary area */
+ int32_t fs_old_csaddr; /* blk addr of cyl grp summary area */
int32_t fs_cssize; /* size of cyl grp summary area */
int32_t fs_cgsize; /* cylinder group size */
-/* these fields are derived from the hardware */
- int32_t fs_ntrak; /* tracks per cylinder */
- int32_t fs_nsect; /* sectors per track */
- int32_t fs_spc; /* sectors per cylinder */
-/* this comes from the disk driver partitioning */
- int32_t fs_ncyl; /* cylinders in filesystem */
-/* these fields can be computed from the others */
- int32_t fs_cpg; /* cylinders per group */
- int32_t fs_ipg; /* inodes per group */
- int32_t fs_fpg; /* blocks per group * fs_frag */
+ int32_t fs_spare2; /* old fs_ntrak */
+ int32_t fs_old_nsect; /* sectors per track */
+ int32_t fs_old_spc; /* sectors per cylinder */
+ int32_t fs_old_ncyl; /* cylinders in filesystem */
+ int32_t fs_old_cpg; /* cylinders per group */
+ int32_t fs_ipg; /* inodes per group */
+ int32_t fs_fpg; /* blocks per group * fs_frag */
/* this data must be re-computed after crashes */
- struct csum fs_cstotal; /* cylinder summary information */
+ struct csum fs_old_cstotal; /* cylinder summary information */
/* these fields are cleared at mount time */
int8_t fs_fmod; /* super block modified flag */
int8_t fs_clean; /* filesystem is clean flag */
@@ -288,37 +308,44 @@ struct fs {
int32_t fs_cgrotor; /* last cg searched */
void *fs_ocsp[NOCSPTRS]; /* padding; was list of fs_cs buffers */
u_int8_t *fs_contigdirs; /* # of contiguously allocated dirs */
- struct csum *fs_csp; /* cg summary info buffer for fs_cs */
+ struct csum *fs_csp; /* cg summary info buffer for fs_cs */
int32_t *fs_maxcluster; /* max cluster in each cyl group */
u_int *fs_active; /* used by snapshots to track fs */
- int32_t fs_cpc; /* cyl per cycle in postbl */
- int16_t fs_opostbl[16][8]; /* old rotation block list head */
+ int32_t fs_old_cpc; /* cyl per cycle in postbl */
+ int32_t fs_maxbsize; /* maximum blocking factor permitted */
+ int64_t fs_sparecon64[17]; /* old rotation block list head */
+ int64_t fs_sblockloc; /* location of standard superblock */
+ struct csum_total fs_cstotal; /* cylinder summary information */
+ ufs_time_t fs_time; /* last time written */
+ int64_t fs_size; /* number of blocks in fs */
+ int64_t fs_dsize; /* number of data blocks in fs */
+ ufs2_daddr_t fs_csaddr; /* blk addr of cyl grp summary area */
+ int64_t fs_pendingblocks; /* blocks in process of being freed */
+ int32_t fs_pendinginodes; /* inodes in process of being freed */
int32_t fs_snapinum[FSMAXSNAP];/* list of snapshot inode numbers */
int32_t fs_avgfilesize; /* expected average file size */
int32_t fs_avgfpdir; /* expected # of files per directory */
- int32_t fs_sparecon[26]; /* reserved for future constants */
- int32_t fs_pendingblocks; /* blocks in process of being freed */
- int32_t fs_pendinginodes; /* inodes in process of being freed */
+ int32_t fs_save_cgsize; /* save real cg size to use fs_bsize */
+ int32_t fs_sparecon32[27]; /* reserved for future constants */
int32_t fs_contigsumsize; /* size of cluster summary array */
int32_t fs_maxsymlinklen; /* max length of an internal symlink */
- int32_t fs_inodefmt; /* format of on-disk inodes */
+ int32_t fs_old_inodefmt; /* format of on-disk inodes */
u_int64_t fs_maxfilesize; /* maximum representable file size */
int64_t fs_qbmask; /* ~fs_bmask for use with 64-bit size */
int64_t fs_qfmask; /* ~fs_fmask for use with 64-bit size */
int32_t fs_state; /* validate fs_clean field */
- int32_t fs_postblformat; /* format of positional layout tables */
- int32_t fs_nrpos; /* number of rotational positions */
- int32_t fs_postbloff; /* (u_int16) rotation block list head */
- int32_t fs_rotbloff; /* (u_int8) blocks for each rotation */
+ int32_t fs_old_postblformat; /* format of positional layout tables */
+ int32_t fs_old_nrpos; /* number of rotational positions */
+ int32_t fs_spare5[2]; /* old fs_postbloff */
+ /* old fs_rotbloff */
int32_t fs_magic; /* magic number */
- u_int8_t fs_space[1]; /* list of blocks for each rotation */
-/* actually longer */
};
/*
* Filesystem identification
*/
-#define FS_MAGIC 0x011954 /* the fast filesystem magic number */
+#define FS_UFS1_MAGIC 0x011954 /* UFS1 fast filesystem magic number */
+#define FS_UFS2_MAGIC 0x19540119 /* UFS2 fast filesystem magic number */
#define FS_OKAY 0x7c269d38 /* superblock checksum */
#define FS_42INODEFMT -1 /* 4.2BSD inode format */
#define FS_44INODEFMT 2 /* 4.4BSD inode format */
@@ -332,6 +359,9 @@ struct fs {
/*
* Filesystem flags.
*
+ * The FS_UNCLEAN flag is set by the kernel when the filesystem was
+ * mounted with fs_clean set to zero. The FS_DOSOFTDEP flag indicates
+ * that the filesystem should be managed by the soft updates code.
* Note that the FS_NEEDSFSCK flag is set and cleared only by the
* fsck utility. It is set when background fsck finds an unexpected
* inconsistency which requires a traditional foreground fsck to be
@@ -339,28 +369,16 @@ struct fs {
* disk error. A foreground fsck will clear the FS_NEEDSFSCK flag when
* it has successfully cleaned up the filesystem. The kernel uses this
* flag to enforce that inconsistent filesystems be mounted read-only.
+ * The FS_INDEXDIRS flag when set indicates that the kernel maintains
+ * on-disk auxiliary indexes (such as B-trees) for speeding directory
+ * accesses. Kernels that do not support auxiliary indicies clear the
+ * flag to indicate that the indicies need to be rebuilt (by fsck) before
+ * they can be used.
*/
#define FS_UNCLEAN 0x01 /* filesystem not clean at mount */
#define FS_DOSOFTDEP 0x02 /* filesystem using soft dependencies */
#define FS_NEEDSFSCK 0x04 /* filesystem needs sync fsck before mount */
-
-/*
- * Rotational layout table format types
- */
-#define FS_42POSTBLFMT -1 /* 4.2BSD rotational table format */
-#define FS_DYNAMICPOSTBLFMT 1 /* dynamic rotational table format */
-/*
- * Macros for access to superblock array structures
- */
-#define fs_postbl(fs, cylno) \
- (((fs)->fs_postblformat == FS_42POSTBLFMT) \
- ? ((fs)->fs_opostbl[cylno]) \
- : ((int16_t *)((u_int8_t *)(fs) + \
- (fs)->fs_postbloff) + (cylno) * (fs)->fs_nrpos))
-#define fs_rotbl(fs) \
- (((fs)->fs_postblformat == FS_42POSTBLFMT) \
- ? ((fs)->fs_space) \
- : ((u_int8_t *)((u_int8_t *)(fs) + (fs)->fs_rotbloff)))
+#define FS_INDEXDIRS 0x08 /* kernel supports indexed directories */
/*
* Macros to access bits in the fs_active array.
@@ -376,13 +394,18 @@ struct fs {
*/
#define CGSIZE(fs) \
/* base cg */ (sizeof(struct cg) + sizeof(int32_t) + \
- /* blktot size */ (fs)->fs_cpg * sizeof(int32_t) + \
- /* blks size */ (fs)->fs_cpg * (fs)->fs_nrpos * sizeof(int16_t) + \
+ /* old btotoff */ (fs)->fs_old_cpg * sizeof(int32_t) + \
+ /* old boff */ (fs)->fs_old_cpg * sizeof(u_int16_t) + \
/* inode map */ howmany((fs)->fs_ipg, NBBY) + \
- /* block map */ howmany((fs)->fs_cpg * (fs)->fs_spc / NSPF(fs), NBBY) +\
+ /* block map */ howmany((fs)->fs_fpg, NBBY) +\
/* if present */ ((fs)->fs_contigsumsize <= 0 ? 0 : \
/* cluster sum */ (fs)->fs_contigsumsize * sizeof(int32_t) + \
- /* cluster map */ howmany((fs)->fs_cpg * (fs)->fs_spc / NSPB(fs), NBBY)))
+ /* cluster map */ howmany(fragstoblks(fs, (fs)->fs_fpg), NBBY)))
+
+/*
+ * The minimal number of cylinder groups that should be created.
+ */
+#define MINCYLGRPS 4
/*
* Convert cylinder group to base address of its global summary info.
@@ -396,25 +419,29 @@ struct fs {
struct cg {
int32_t cg_firstfield; /* historic cyl groups linked list */
int32_t cg_magic; /* magic number */
- ufs_time_t cg_time; /* time last written */
+ int32_t cg_old_time; /* time last written */
int32_t cg_cgx; /* we are the cgx'th cylinder group */
- int16_t cg_ncyl; /* number of cyl's this cg */
- int16_t cg_niblk; /* number of inode blocks this cg */
+ int16_t cg_old_ncyl; /* number of cyl's this cg */
+ int16_t cg_old_niblk; /* number of inode blocks this cg */
int32_t cg_ndblk; /* number of data blocks this cg */
struct csum cg_cs; /* cylinder summary information */
int32_t cg_rotor; /* position of last used block */
int32_t cg_frotor; /* position of last used frag */
int32_t cg_irotor; /* position of last used inode */
int32_t cg_frsum[MAXFRAG]; /* counts of available frags */
- int32_t cg_btotoff; /* (int32) block totals per cylinder */
- int32_t cg_boff; /* (u_int16) free block positions */
+ int32_t cg_old_btotoff; /* (int32) block totals per cylinder */
+ int32_t cg_old_boff; /* (u_int16) free block positions */
int32_t cg_iusedoff; /* (u_int8) used inode map */
int32_t cg_freeoff; /* (u_int8) free block map */
int32_t cg_nextfreeoff; /* (u_int8) next available space */
int32_t cg_clustersumoff; /* (u_int32) counts of avail clusters */
int32_t cg_clusteroff; /* (u_int8) free cluster map */
int32_t cg_nclusterblks; /* number of clusters this cg */
- int32_t cg_sparecon[13]; /* reserved for future use */
+ int32_t cg_niblk; /* number of inode blocks this cg */
+ int32_t cg_initediblk; /* last initialized inode */
+ int32_t cg_sparecon32[3]; /* reserved for future use */
+ ufs_time_t cg_time; /* time last written */
+ int64_t cg_sparecon64[3]; /* reserved for future use */
u_int8_t cg_space[1]; /* space for cylinder group maps */
/* actually longer */
};
@@ -422,56 +449,17 @@ struct cg {
/*
* Macros for access to cylinder group array structures
*/
-#define cg_blktot(cgp) \
- (((cgp)->cg_magic != CG_MAGIC) \
- ? (((struct ocg *)(cgp))->cg_btot) \
- : ((int32_t *)((u_int8_t *)(cgp) + (cgp)->cg_btotoff)))
-#define cg_blks(fs, cgp, cylno) \
- (((cgp)->cg_magic != CG_MAGIC) \
- ? (((struct ocg *)(cgp))->cg_b[cylno]) \
- : ((int16_t *)((u_int8_t *)(cgp) + \
- (cgp)->cg_boff) + (cylno) * (fs)->fs_nrpos))
+#define cg_chkmagic(cgp) ((cgp)->cg_magic == CG_MAGIC)
#define cg_inosused(cgp) \
- (((cgp)->cg_magic != CG_MAGIC) \
- ? (((struct ocg *)(cgp))->cg_iused) \
- : ((u_int8_t *)((u_int8_t *)(cgp) + (cgp)->cg_iusedoff)))
+ ((u_int8_t *)((u_int8_t *)(cgp) + (cgp)->cg_iusedoff))
#define cg_blksfree(cgp) \
- (((cgp)->cg_magic != CG_MAGIC) \
- ? (((struct ocg *)(cgp))->cg_free) \
- : ((u_int8_t *)((u_int8_t *)(cgp) + (cgp)->cg_freeoff)))
-#define cg_chkmagic(cgp) \
- ((cgp)->cg_magic == CG_MAGIC || ((struct ocg *)(cgp))->cg_magic == CG_MAGIC)
+ ((u_int8_t *)((u_int8_t *)(cgp) + (cgp)->cg_freeoff))
#define cg_clustersfree(cgp) \
((u_int8_t *)((u_int8_t *)(cgp) + (cgp)->cg_clusteroff))
#define cg_clustersum(cgp) \
((int32_t *)((u_int8_t *)(cgp) + (cgp)->cg_clustersumoff))
/*
- * The following structure is defined
- * for compatibility with old filesystems.
- */
-struct ocg {
- int32_t cg_firstfield; /* historic linked list of cyl groups */
- int32_t cg_unused_1; /* used for incore cyl groups */
- ufs_time_t cg_time; /* time last written */
- int32_t cg_cgx; /* we are the cgx'th cylinder group */
- int16_t cg_ncyl; /* number of cyl's this cg */
- int16_t cg_niblk; /* number of inode blocks this cg */
- int32_t cg_ndblk; /* number of data blocks this cg */
- struct csum cg_cs; /* cylinder summary information */
- int32_t cg_rotor; /* position of last used block */
- int32_t cg_frotor; /* position of last used frag */
- int32_t cg_irotor; /* position of last used inode */
- int32_t cg_frsum[8]; /* counts of available frags */
- int32_t cg_btot[32]; /* block totals per cylinder */
- int16_t cg_b[32][8]; /* positions of free blocks */
- u_int8_t cg_iused[256]; /* used inode map */
- int32_t cg_magic; /* magic number */
- u_int8_t cg_free[1]; /* free block map */
-/* actually longer */
-};
-
-/*
* Turn filesystem block numbers into disk block addresses.
* This maps filesystem blocks to device size blocks.
*/
@@ -482,13 +470,14 @@ struct ocg {
* Cylinder group macros to locate things in cylinder groups.
* They calc filesystem addresses of cylinder group data structures.
*/
-#define cgbase(fs, c) ((ufs_daddr_t)((fs)->fs_fpg * (c)))
+#define cgbase(fs, c) ((ufs2_daddr_t)((fs)->fs_fpg * (c)))
#define cgdmin(fs, c) (cgstart(fs, c) + (fs)->fs_dblkno) /* 1st data */
#define cgimin(fs, c) (cgstart(fs, c) + (fs)->fs_iblkno) /* inode blk */
#define cgsblock(fs, c) (cgstart(fs, c) + (fs)->fs_sblkno) /* super blk */
#define cgtod(fs, c) (cgstart(fs, c) + (fs)->fs_cblkno) /* cg block */
#define cgstart(fs, c) \
- (cgbase(fs, c) + (fs)->fs_cgoffset * ((c) & ~((fs)->fs_cgmask)))
+ ((fs)->fs_magic == FS_UFS2_MAGIC ? cgbase(fs, c) : \
+ (cgbase(fs, c) + (fs)->fs_old_cgoffset * ((c) & ~((fs)->fs_old_cgmask))))
/*
* Macros for handling inode numbers:
@@ -498,7 +487,7 @@ struct ocg {
*/
#define ino_to_cg(fs, x) ((x) / (fs)->fs_ipg)
#define ino_to_fsba(fs, x) \
- ((ufs_daddr_t)(cgimin(fs, ino_to_cg(fs, x)) + \
+ ((ufs2_daddr_t)(cgimin(fs, ino_to_cg(fs, x)) + \
(blkstofrags((fs), (((x) % (fs)->fs_ipg) / INOPB(fs))))))
#define ino_to_fsbo(fs, x) ((x) % INOPB(fs))
@@ -515,12 +504,6 @@ struct ocg {
*/
#define blkmap(fs, map, loc) \
(((map)[(loc) / NBBY] >> ((loc) % NBBY)) & (0xff >> (NBBY - (fs)->fs_frag)))
-#define cbtocylno(fs, bno) \
- ((bno) * NSPF(fs) / (fs)->fs_spc)
-#define cbtorpos(fs, bno) \
- (((bno) * NSPF(fs) % (fs)->fs_spc / (fs)->fs_nsect * (fs)->fs_trackskew + \
- (bno) * NSPF(fs) % (fs)->fs_spc % (fs)->fs_nsect * (fs)->fs_interleave) % \
- (fs)->fs_nsect * (fs)->fs_nrpos / (fs)->fs_npsect)
/*
* The following macros optimize certain frequently calculated
@@ -531,6 +514,8 @@ struct ocg {
((loc) & (fs)->fs_qbmask)
#define fragoff(fs, loc) /* calculates (loc % fs->fs_fsize) */ \
((loc) & (fs)->fs_qfmask)
+#define lfragtosize(fs, frag) /* calculates ((off_t)frag * fs->fs_fsize) */ \
+ ((off_t)(frag) << (fs)->fs_fshift)
#define lblktosize(fs, blk) /* calculates ((off_t)blk * fs->fs_bsize) */ \
((off_t)(blk) << (fs)->fs_bshift)
/* Use this only when `blk' is known to be small, e.g., < NDADDR. */
@@ -569,11 +554,6 @@ struct ocg {
(((lbn) >= NDADDR || (ip)->i_size >= smalllblktosize(fs, (lbn) + 1)) \
? (fs)->fs_bsize \
: (fragroundup(fs, blkoff(fs, (ip)->i_size))))
-#define dblksize(fs, dip, lbn) \
- (((lbn) >= NDADDR || \
- (dip)->di_size >= (u_int64_t)smalllblktosize(fs, (lbn) + 1)) \
- ? (fs)->fs_bsize \
- : (fragroundup(fs, blkoff(fs, (dip)->di_size))))
#define sblksize(fs, size, lbn) \
(((lbn) >= NDADDR || (size) >= ((lbn) + 1) << (fs)->fs_bshift) \
? (fs)->fs_bsize \
@@ -581,13 +561,6 @@ struct ocg {
/*
- * Number of disk sectors per block/fragment; assumes DEV_BSIZE byte
- * sector size.
- */
-#define NSPB(fs) ((fs)->fs_nspf << (fs)->fs_fragshift)
-#define NSPF(fs) ((fs)->fs_nspf)
-
-/*
* Number of inodes in a secondary storage block/fragment.
*/
#define INOPB(fs) ((fs)->fs_inopb)
diff --git a/sys/ufs/ffs/softdep.h b/sys/ufs/ffs/softdep.h
index cdb1f6898b3b..cbee51b5a84f 100644
--- a/sys/ufs/ffs/softdep.h
+++ b/sys/ufs/ffs/softdep.h
@@ -86,8 +86,11 @@
* says that the files space has been accounted to the pending free
* space count. The NEWBLOCK flag marks pagedep structures that have
* just been allocated, so must be claimed by the inode before all
- * dependencies are complete. The ONWORKLIST flag shows whether the
- * structure is currently linked onto a worklist.
+ * dependencies are complete. The INPROGRESS flag marks worklist
+ * structures that are still on the worklist, but are being considered
+ * for action by some process. The UFS1FMT flag indicates that the
+ * inode being processed is a ufs1 format. The ONWORKLIST flag shows
+ * whether the structure is currently linked onto a worklist.
*/
#define ATTACHED 0x0001
#define UNDONE 0x0002
@@ -102,6 +105,7 @@
#define SPACECOUNTED 0x0400 /* inodedep only */
#define NEWBLOCK 0x0800 /* pagedep only */
#define INPROGRESS 0x1000 /* dirrem, freeblks, freefrag, freefile only */
+#define UFS1FMT 0x2000 /* indirdep only */
#define ONWORKLIST 0x8000
#define ALLCOMPLETE (ATTACHED | COMPLETE | DEPCOMPLETE)
@@ -177,7 +181,7 @@ TAILQ_HEAD(allocdirectlst, allocdirect);
* list, any removed operations are done, and the dependency structure
* is freed.
*/
-#define DAHASHSZ 6
+#define DAHASHSZ 5
#define DIRADDHASH(offset) (((offset) >> 2) % DAHASHSZ)
struct pagedep {
struct worklist pd_list; /* page buffer */
@@ -245,7 +249,6 @@ struct inodedep {
struct fs *id_fs; /* associated filesystem */
ino_t id_ino; /* dependent inode */
nlink_t id_nlinkdelta; /* saved effective link count */
- struct dinode *id_savedino; /* saved dinode contents */
LIST_ENTRY(inodedep) id_deps; /* bmsafemap's list of inodedep's */
struct buf *id_buf; /* related bmsafemap (if pending) */
off_t id_savedsize; /* file size saved during rollback */
@@ -254,7 +257,13 @@ struct inodedep {
struct workhead id_inowait; /* operations waiting inode update */
struct allocdirectlst id_inoupdt; /* updates before inode written */
struct allocdirectlst id_newinoupdt; /* updates when inode written */
+ union {
+ struct ufs1_dinode *idu_savedino1; /* saved ufs1_dinode contents */
+ struct ufs2_dinode *idu_savedino2; /* saved ufs2_dinode contents */
+ } id_un;
};
+#define id_savedino1 id_un.idu_savedino1
+#define id_savedino2 id_un.idu_savedino2
/*
* A "newblk" structure is attached to a bmsafemap structure when a block
@@ -267,8 +276,8 @@ struct inodedep {
struct newblk {
LIST_ENTRY(newblk) nb_hash; /* hashed lookup */
struct fs *nb_fs; /* associated filesystem */
- ufs_daddr_t nb_newblkno; /* allocated block number */
int nb_state; /* state of bitmap dependency */
+ ufs2_daddr_t nb_newblkno; /* allocated block number */
LIST_ENTRY(newblk) nb_deps; /* bmsafemap's list of newblk's */
struct bmsafemap *nb_bmsafemap; /* associated bmsafemap */
};
@@ -324,8 +333,8 @@ struct allocdirect {
# define ad_state ad_list.wk_state /* block pointer state */
TAILQ_ENTRY(allocdirect) ad_next; /* inodedep's list of allocdirect's */
ufs_lbn_t ad_lbn; /* block within file */
- ufs_daddr_t ad_newblkno; /* new value of block pointer */
- ufs_daddr_t ad_oldblkno; /* old value of block pointer */
+ ufs2_daddr_t ad_newblkno; /* new value of block pointer */
+ ufs2_daddr_t ad_oldblkno; /* old value of block pointer */
long ad_newsize; /* size of new block */
long ad_oldsize; /* size of old block */
LIST_ENTRY(allocdirect) ad_deps; /* bmsafemap's list of allocdirect's */
@@ -379,8 +388,8 @@ struct allocindir {
# define ai_state ai_list.wk_state /* indirect block pointer state */
LIST_ENTRY(allocindir) ai_next; /* indirdep's list of allocindir's */
int ai_offset; /* pointer offset in indirect block */
- ufs_daddr_t ai_newblkno; /* new block pointer value */
- ufs_daddr_t ai_oldblkno; /* old block pointer value */
+ ufs2_daddr_t ai_newblkno; /* new block pointer value */
+ ufs2_daddr_t ai_oldblkno; /* old block pointer value */
struct freefrag *ai_freefrag; /* block to be freed when complete */
struct indirdep *ai_indirdep; /* address of associated indirdep */
LIST_ENTRY(allocindir) ai_deps; /* bmsafemap's list of allocindir's */
@@ -400,9 +409,8 @@ struct allocindir {
struct freefrag {
struct worklist ff_list; /* id_inowait or delayed worklist */
# define ff_state ff_list.wk_state /* owning user; should be uid_t */
- struct vnode *ff_devvp; /* filesystem device vnode */
struct mount *ff_mnt; /* associated mount point */
- ufs_daddr_t ff_blkno; /* fragment physical block number */
+ ufs2_daddr_t ff_blkno; /* fragment physical block number */
long ff_fragsize; /* size of fragment being deleted */
ino_t ff_inum; /* owning inode number */
};
@@ -416,14 +424,14 @@ struct freefrag {
struct freeblks {
struct worklist fb_list; /* id_inowait or delayed worklist */
ino_t fb_previousinum; /* inode of previous owner of blocks */
+ uid_t fb_uid; /* uid of previous owner of blocks */
struct vnode *fb_devvp; /* filesystem device vnode */
struct mount *fb_mnt; /* associated mount point */
off_t fb_oldsize; /* previous file size */
off_t fb_newsize; /* new file size */
- int fb_chkcnt; /* used to check cnt of blks released */
- uid_t fb_uid; /* uid of previous owner of blocks */
- ufs_daddr_t fb_dblks[NDADDR]; /* direct blk ptrs to deallocate */
- ufs_daddr_t fb_iblks[NIADDR]; /* indirect blk ptrs to deallocate */
+ ufs2_daddr_t fb_chkcnt; /* used to check cnt of blks released */
+ ufs2_daddr_t fb_dblks[NDADDR]; /* direct blk ptrs to deallocate */
+ ufs2_daddr_t fb_iblks[NIADDR]; /* indirect blk ptrs to deallocate */
};
/*
diff --git a/sys/ufs/ufs/dinode.h b/sys/ufs/ufs/dinode.h
index 016879795185..5caea85bf927 100644
--- a/sys/ufs/ufs/dinode.h
+++ b/sys/ufs/ufs/dinode.h
@@ -1,4 +1,13 @@
/*
+ * Copyright (c) 2002 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by Marshall
+ * Kirk McKusick and Network Associates Laboratories, the Security
+ * Research Division of Network Associates, Inc. under DARPA/SPAWAR
+ * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
+ * research program
+ *
* Copyright (c) 1982, 1989, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
@@ -15,18 +24,14 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
+ * 3. The names of the authors may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
*
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
@@ -40,7 +45,7 @@
*/
#ifndef _UFS_UFS_DINODE_H_
-#define _UFS_UFS_DINODE_H_
+#define _UFS_UFS_DINODE_H_
/*
* The root inode is the root of the filesystem. Inode 0 can't be used for
@@ -59,17 +64,85 @@
#define WINO ((ino_t)1)
/*
- * A dinode contains all the meta-data associated with a UFS file.
+ * The size of physical and logical block numbers and time fields in UFS.
+ */
+typedef int32_t ufs1_daddr_t;
+typedef int64_t ufs2_daddr_t;
+typedef int64_t ufs_lbn_t;
+typedef int64_t ufs_time_t;
+
+/* File permissions. */
+#define IEXEC 0000100 /* Executable. */
+#define IWRITE 0000200 /* Writeable. */
+#define IREAD 0000400 /* Readable. */
+#define ISVTX 0001000 /* Sticky bit. */
+#define ISGID 0002000 /* Set-gid. */
+#define ISUID 0004000 /* Set-uid. */
+
+/* File types. */
+#define IFMT 0170000 /* Mask of file type. */
+#define IFIFO 0010000 /* Named pipe (fifo). */
+#define IFCHR 0020000 /* Character device. */
+#define IFDIR 0040000 /* Directory file. */
+#define IFBLK 0060000 /* Block device. */
+#define IFREG 0100000 /* Regular file. */
+#define IFLNK 0120000 /* Symbolic link. */
+#define IFSOCK 0140000 /* UNIX domain socket. */
+#define IFWHT 0160000 /* Whiteout. */
+
+/*
+ * A dinode contains all the meta-data associated with a UFS2 file.
* This structure defines the on-disk format of a dinode. Since
* this structure describes an on-disk structure, all its fields
* are defined by types with precise widths.
*/
-/* typedef int32_t ufs_daddr_t; */
+#define NXADDR 2 /* External addresses in inode. */
#define NDADDR 12 /* Direct addresses in inode. */
#define NIADDR 3 /* Indirect addresses in inode. */
-struct dinode {
+struct ufs2_dinode {
+ u_int16_t di_mode; /* 0: IFMT, permissions; see below. */
+ int16_t di_nlink; /* 2: File link count. */
+ u_int32_t di_uid; /* 4: File owner. */
+ u_int32_t di_gid; /* 8: File group. */
+ u_int32_t di_blksize; /* 12: Inode blocksize. */
+ u_int64_t di_size; /* 16: File byte count. */
+ u_int64_t di_blocks; /* 24: Bytes actually held. */
+ ufs_time_t di_atime; /* 32: Last access time. */
+ ufs_time_t di_mtime; /* 40: Last modified time. */
+ ufs_time_t di_ctime; /* 48: Last inode change time. */
+ ufs_time_t di_createtime; /* 56: Last inode change time. */
+ int32_t di_mtimensec; /* 64: Last modified time. */
+ int32_t di_atimensec; /* 68: Last access time. */
+ int32_t di_ctimensec; /* 72: Last inode change time. */
+ int32_t di_creatensec; /* 76: Last inode change time. */
+ int32_t di_gen; /* 80: Generation number. */
+ u_int32_t di_kernflags; /* 84: Kernel flags. */
+ u_int32_t di_flags; /* 88: Status flags (chflags). */
+ int32_t di_extsize; /* 92: External attributes block. */
+ ufs2_daddr_t di_extb[NXADDR];/* 96: External attributes block. */
+ ufs2_daddr_t di_db[NDADDR]; /* 112: Direct disk blocks. */
+ ufs2_daddr_t di_ib[NIADDR]; /* 208: Indirect disk blocks. */
+ int64_t di_spare[3]; /* 232: Reserved; currently unused */
+};
+
+/*
+ * The di_db fields may be overlaid with other information for
+ * file types that do not have associated disk storage. Block
+ * and character devices overlay the first data block with their
+ * dev_t value. Short symbolic links place their path in the
+ * di_db area.
+ */
+#define di_rdev di_db[0]
+
+/*
+ * A UFS1 dinode contains all the meta-data associated with a UFS1 file.
+ * This structure defines the on-disk format of a UFS1 dinode. Since
+ * this structure describes an on-disk structure, all its fields
+ * are defined by types with precise widths.
+ */
+struct ufs1_dinode {
u_int16_t di_mode; /* 0: IFMT, permissions; see below. */
int16_t di_nlink; /* 2: File link count. */
union {
@@ -82,8 +155,8 @@ struct dinode {
int32_t di_mtimensec; /* 28: Last modified time. */
int32_t di_ctime; /* 32: Last inode change time. */
int32_t di_ctimensec; /* 36: Last inode change time. */
- ufs_daddr_t di_db[NDADDR]; /* 40: Direct disk blocks. */
- ufs_daddr_t di_ib[NIADDR]; /* 88: Indirect disk blocks. */
+ ufs1_daddr_t di_db[NDADDR]; /* 40: Direct disk blocks. */
+ ufs1_daddr_t di_ib[NIADDR]; /* 88: Indirect disk blocks. */
u_int32_t di_flags; /* 100: Status flags (chflags). */
int32_t di_blocks; /* 104: Blocks actually held. */
int32_t di_gen; /* 108: Generation number. */
@@ -91,37 +164,7 @@ struct dinode {
u_int32_t di_gid; /* 116: File group. */
int32_t di_spare[2]; /* 120: Reserved; currently unused */
};
-
-/*
- * The di_db fields may be overlaid with other information for
- * file types that do not have associated disk storage. Block
- * and character devices overlay the first data block with their
- * dev_t value. Short symbolic links place their path in the
- * di_db area.
- */
#define di_ogid di_u.oldids[1]
#define di_ouid di_u.oldids[0]
-#define di_rdev di_db[0]
-#define di_shortlink di_db
-#define MAXSYMLINKLEN ((NDADDR + NIADDR) * sizeof(ufs_daddr_t))
-
-/* File permissions. */
-#define IEXEC 0000100 /* Executable. */
-#define IWRITE 0000200 /* Writeable. */
-#define IREAD 0000400 /* Readable. */
-#define ISVTX 0001000 /* Sticky bit. */
-#define ISGID 0002000 /* Set-gid. */
-#define ISUID 0004000 /* Set-uid. */
-
-/* File types. */
-#define IFMT 0170000 /* Mask of file type. */
-#define IFIFO 0010000 /* Named pipe (fifo). */
-#define IFCHR 0020000 /* Character device. */
-#define IFDIR 0040000 /* Directory file. */
-#define IFBLK 0060000 /* Block device. */
-#define IFREG 0100000 /* Regular file. */
-#define IFLNK 0120000 /* Symbolic link. */
-#define IFSOCK 0140000 /* UNIX domain socket. */
-#define IFWHT 0160000 /* Whiteout. */
-#endif
+#endif /* _UFS_UFS_DINODE_H_ */
diff --git a/sys/ufs/ufs/inode.h b/sys/ufs/ufs/inode.h
index 5a327c852169..02fa951fc2bc 100644
--- a/sys/ufs/ufs/inode.h
+++ b/sys/ufs/ufs/inode.h
@@ -47,11 +47,6 @@
#include <ufs/ufs/dinode.h>
/*
- * The size of a logical block number.
- */
-typedef long ufs_lbn_t;
-
-/*
* This must agree with the definition in <ufs/ufs/dir.h>.
*/
#define doff_t int32_t
@@ -69,6 +64,7 @@ struct inode {
LIST_ENTRY(inode) i_hash;/* Hash chain. */
TAILQ_ENTRY(inode) i_nextsnap; /* snapshot file list */
struct vnode *i_vnode;/* Vnode associated with this inode. */
+ struct ufsmount *i_ump;/* Ufsmount point associated with this inode. */
struct vnode *i_devvp;/* Vnode for block I/O. */
u_int32_t i_flag; /* flags, see below */
dev_t i_dev; /* Device associated with the inode. */
@@ -91,31 +87,26 @@ struct inode {
struct dirhash *i_dirhash; /* Hashing for large directories */
/*
- * The on-disk dinode itself.
+ * Copies from the on-disk dinode itself.
*/
- struct dinode i_din; /* 128 bytes of the on-disk dinode. */
+ u_int16_t i_mode; /* IFMT, permissions; see below. */
+ int16_t i_nlink; /* File link count. */
+ u_int64_t i_size; /* File byte count. */
+ u_int32_t i_flags; /* Status flags (chflags). */
+ int64_t i_gen; /* Generation number. */
+ u_int32_t i_uid; /* File owner. */
+ u_int32_t i_gid; /* File group. */
+ /*
+ * The real copy of the on-disk inode.
+ */
+ union {
+ struct ufs1_dinode *din1; /* UFS1 on-disk dinode. */
+ struct ufs2_dinode *din2; /* UFS2 on-disk dinode. */
+ } dinode_u;
};
-
-#define i_atime i_din.di_atime
-#define i_atimensec i_din.di_atimensec
-#define i_blocks i_din.di_blocks
-#define i_ctime i_din.di_ctime
-#define i_ctimensec i_din.di_ctimensec
-#define i_db i_din.di_db
-#define i_flags i_din.di_flags
-#define i_gen i_din.di_gen
-#define i_gid i_din.di_gid
-#define i_ib i_din.di_ib
-#define i_mode i_din.di_mode
-#define i_mtime i_din.di_mtime
-#define i_mtimensec i_din.di_mtimensec
-#define i_nlink i_din.di_nlink
-#define i_rdev i_din.di_rdev
-#define i_shortlink i_din.di_shortlink
-#define i_size i_din.di_size
-#define i_uid i_din.di_uid
-
-/* These flags are kept in i_flag. */
+/*
+ * These flags are kept in i_flag.
+ */
#define IN_ACCESS 0x0001 /* Access time update request. */
#define IN_CHANGE 0x0002 /* Inode change time update request. */
#define IN_UPDATE 0x0004 /* Modification time update request. */
@@ -125,13 +116,32 @@ struct inode {
#define IN_LAZYMOD 0x0040 /* Modified, but don't write yet. */
#define IN_SPACECOUNTED 0x0080 /* Blocks to be freed in free count. */
+#define i_din1 dinode_u.din1
+#define i_din2 dinode_u.din2
+
#ifdef _KERNEL
/*
+ * The DIP macro is used to access fields in the dinode that are
+ * not cached in the inode itself.
+ */
+#define DIP(ip, field) \
+ (((ip)->i_ump->um_fstype == UFS1) ? \
+ (ip)->i_din1->d##field : (ip)->i_din2->d##field)
+
+#define MAXSYMLINKLEN(ip) \
+ ((ip)->i_ump->um_fstype == UFS1) ? \
+ ((NDADDR + NIADDR) * sizeof(ufs1_daddr_t)) : \
+ ((NDADDR + NIADDR) * sizeof(ufs2_daddr_t))
+#define SHORTLINK(ip) \
+ (((ip)->i_ump->um_fstype == UFS1) ? \
+ (caddr_t)(ip)->i_din1->di_db : (caddr_t)(ip)->i_din2->di_db)
+
+/*
* Structure used to pass around logical block paths generated by
* ufs_getlbns and used by truncate and bmap code.
*/
struct indir {
- ufs_daddr_t in_lbn; /* Logical block number. */
+ ufs2_daddr_t in_lbn; /* Logical block number. */
int in_off; /* Offset in buffer. */
int in_exists; /* Flag if the block exists. */
};
diff --git a/sys/ufs/ufs/quota.h b/sys/ufs/ufs/quota.h
index 5737088ea442..15f512c17995 100644
--- a/sys/ufs/ufs/quota.h
+++ b/sys/ufs/ufs/quota.h
@@ -104,8 +104,8 @@ struct dqblk {
u_int32_t dqb_ihardlimit; /* maximum # allocated inodes + 1 */
u_int32_t dqb_isoftlimit; /* preferred inode limit */
u_int32_t dqb_curinodes; /* current # allocated inodes */
- ufs_time_t dqb_btime; /* time limit for excessive disk use */
- ufs_time_t dqb_itime; /* time limit for excessive files */
+ int32_t dqb_btime; /* time limit for excessive disk use */
+ int32_t dqb_itime; /* time limit for excessive files */
};
#ifdef _KERNEL
@@ -178,8 +178,8 @@ struct thread;
struct ucred;
struct vnode;
-int chkdq(struct inode *, long, struct ucred *, int);
-int chkiq(struct inode *, long, struct ucred *, int);
+int chkdq(struct inode *, int64_t, struct ucred *, int);
+int chkiq(struct inode *, ino_t, struct ucred *, int);
void dqinit(void);
void dqrele(struct vnode *, struct dquot *);
int getinoquota(struct inode *);
diff --git a/sys/ufs/ufs/ufs_acl.c b/sys/ufs/ufs/ufs_acl.c
index 5869cafb4820..390e0db85d62 100644
--- a/sys/ufs/ufs/ufs_acl.c
+++ b/sys/ufs/ufs/ufs_acl.c
@@ -191,6 +191,7 @@ ufs_sync_inode_from_acl(struct acl *acl, struct inode *ip,
ip->i_mode &= ~(S_IRWXU|S_IRWXG|S_IRWXO);
ip->i_mode |= acl_posix1e_perms_to_mode(acl_user_obj,
acl_group_obj, acl_other);
+ DIP(ip, i_mode) = ip->i_mode;
} else {
/*
* Use the ACL_MASK entry.
@@ -198,8 +199,10 @@ ufs_sync_inode_from_acl(struct acl *acl, struct inode *ip,
ip->i_mode &= ~(S_IRWXU|S_IRWXG|S_IRWXO);
ip->i_mode |= acl_posix1e_perms_to_mode(acl_user_obj,
acl_mask, acl_other);
+ DIP(ip, i_mode) = ip->i_mode;
}
ip->i_mode |= preserve_mode;
+ DIP(ip, i_mode) = ip->i_mode;
}
/*
diff --git a/sys/ufs/ufs/ufs_bmap.c b/sys/ufs/ufs/ufs_bmap.c
index 2bd312ffd5da..abe2bea0cd87 100644
--- a/sys/ufs/ufs/ufs_bmap.c
+++ b/sys/ufs/ufs/ufs_bmap.c
@@ -71,7 +71,7 @@ ufs_bmap(ap)
int *a_runb;
} */ *ap;
{
- ufs_daddr_t blkno;
+ ufs2_daddr_t blkno;
int error;
/*
@@ -106,8 +106,8 @@ ufs_bmap(ap)
int
ufs_bmaparray(vp, bn, bnp, runp, runb)
struct vnode *vp;
- ufs_daddr_t bn;
- ufs_daddr_t *bnp;
+ ufs2_daddr_t bn;
+ ufs2_daddr_t *bnp;
int *runp;
int *runb;
{
@@ -117,8 +117,8 @@ ufs_bmaparray(vp, bn, bnp, runp, runb)
struct mount *mp;
struct vnode *devvp;
struct indir a[NIADDR+1], *ap;
- ufs_daddr_t daddr;
- long metalbn;
+ ufs2_daddr_t daddr;
+ ufs_lbn_t metalbn;
int error, num, maxrun = 0;
int *nump;
@@ -146,7 +146,7 @@ ufs_bmaparray(vp, bn, bnp, runp, runb)
num = *nump;
if (num == 0) {
- *bnp = blkptrtodb(ump, ip->i_db[bn]);
+ *bnp = blkptrtodb(ump, DIP(ip, i_db[bn]));
/*
* Since this is FFS independent code, we are out of
* scope for the definitions of BLK_NOCOPY and
@@ -155,8 +155,8 @@ ufs_bmaparray(vp, bn, bnp, runp, runb)
* return a request for a zeroed out buffer if attempts
* are made to read a BLK_NOCOPY or BLK_SNAP block.
*/
- if ((ip->i_flags & SF_SNAPSHOT) &&
- ip->i_db[bn] > 0 && ip->i_db[bn] < ump->um_seqinc) {
+ if ((ip->i_flags & SF_SNAPSHOT) && DIP(ip, i_db[bn]) > 0 &&
+ DIP(ip, i_db[bn]) < ump->um_seqinc) {
*bnp = -1;
} else if (*bnp == 0) {
if (ip->i_flags & SF_SNAPSHOT)
@@ -164,15 +164,16 @@ ufs_bmaparray(vp, bn, bnp, runp, runb)
else
*bnp = -1;
} else if (runp) {
- daddr_t bnb = bn;
+ ufs2_daddr_t bnb = bn;
for (++bn; bn < NDADDR && *runp < maxrun &&
- is_sequential(ump, ip->i_db[bn - 1], ip->i_db[bn]);
+ is_sequential(ump, DIP(ip, i_db[bn - 1]),
+ DIP(ip, i_db[bn]));
++bn, ++*runp);
bn = bnb;
if (runb && (bn > 0)) {
for (--bn; (bn >= 0) && (*runb < maxrun) &&
- is_sequential(ump, ip->i_db[bn],
- ip->i_db[bn+1]);
+ is_sequential(ump, DIP(ip, i_db[bn]),
+ DIP(ip, i_db[bn+1]));
--bn, ++*runb);
}
}
@@ -181,7 +182,7 @@ ufs_bmaparray(vp, bn, bnp, runp, runb)
/* Get disk address out of indirect block array */
- daddr = ip->i_ib[ap->in_off];
+ daddr = DIP(ip, i_ib[ap->in_off]);
for (bp = NULL, ++ap; --num; ++ap) {
/*
@@ -221,21 +222,41 @@ ufs_bmaparray(vp, bn, bnp, runp, runb)
}
}
- daddr = ((ufs_daddr_t *)bp->b_data)[ap->in_off];
+ if (ip->i_ump->um_fstype == UFS1) {
+ daddr = ((ufs1_daddr_t *)bp->b_data)[ap->in_off];
+ if (num == 1 && daddr && runp) {
+ for (bn = ap->in_off + 1;
+ bn < MNINDIR(ump) && *runp < maxrun &&
+ is_sequential(ump,
+ ((ufs1_daddr_t *)bp->b_data)[bn - 1],
+ ((ufs1_daddr_t *)bp->b_data)[bn]);
+ ++bn, ++*runp);
+ bn = ap->in_off;
+ if (runb && bn) {
+ for (--bn; bn >= 0 && *runb < maxrun &&
+ is_sequential(ump,
+ ((ufs1_daddr_t *)bp->b_data)[bn],
+ ((ufs1_daddr_t *)bp->b_data)[bn+1]);
+ --bn, ++*runb);
+ }
+ }
+ continue;
+ }
+ daddr = ((ufs2_daddr_t *)bp->b_data)[ap->in_off];
if (num == 1 && daddr && runp) {
for (bn = ap->in_off + 1;
bn < MNINDIR(ump) && *runp < maxrun &&
is_sequential(ump,
- ((ufs_daddr_t *)bp->b_data)[bn - 1],
- ((ufs_daddr_t *)bp->b_data)[bn]);
+ ((ufs2_daddr_t *)bp->b_data)[bn - 1],
+ ((ufs2_daddr_t *)bp->b_data)[bn]);
++bn, ++*runp);
bn = ap->in_off;
if (runb && bn) {
- for(--bn; bn >= 0 && *runb < maxrun &&
- is_sequential(ump,
- ((ufs_daddr_t *)bp->b_data)[bn],
- ((ufs_daddr_t *)bp->b_data)[bn+1]);
- --bn, ++*runb);
+ for (--bn; bn >= 0 && *runb < maxrun &&
+ is_sequential(ump,
+ ((ufs2_daddr_t *)bp->b_data)[bn],
+ ((ufs2_daddr_t *)bp->b_data)[bn + 1]);
+ --bn, ++*runb);
}
}
}
@@ -275,22 +296,22 @@ ufs_bmaparray(vp, bn, bnp, runp, runb)
int
ufs_getlbns(vp, bn, ap, nump)
struct vnode *vp;
- ufs_daddr_t bn;
+ ufs2_daddr_t bn;
struct indir *ap;
int *nump;
{
- long blockcnt, metalbn, realbn;
+ ufs2_daddr_t blockcnt;
+ ufs_lbn_t metalbn, realbn;
struct ufsmount *ump;
int i, numlevels, off;
- int64_t qblockcnt;
ump = VFSTOUFS(vp->v_mount);
if (nump)
*nump = 0;
numlevels = 0;
realbn = bn;
- if ((long)bn < 0)
- bn = -(long)bn;
+ if (bn < 0)
+ bn = -bn;
/* The first NDADDR blocks are direct blocks. */
if (bn < NDADDR)
@@ -305,15 +326,9 @@ ufs_getlbns(vp, bn, ap, nump)
for (blockcnt = 1, i = NIADDR, bn -= NDADDR;; i--, bn -= blockcnt) {
if (i == 0)
return (EFBIG);
- /*
- * Use int64_t's here to avoid overflow for triple indirect
- * blocks when longs have 32 bits and the block size is more
- * than 4K.
- */
- qblockcnt = (int64_t)blockcnt * MNINDIR(ump);
- if (bn < qblockcnt)
+ blockcnt *= MNINDIR(ump);
+ if (bn < blockcnt)
break;
- blockcnt = qblockcnt;
}
/* Calculate the address of the first meta-block. */
@@ -337,6 +352,7 @@ ufs_getlbns(vp, bn, ap, nump)
if (metalbn == realbn)
break;
+ blockcnt /= MNINDIR(ump);
off = (bn / blockcnt) % MNINDIR(ump);
++numlevels;
@@ -346,7 +362,6 @@ ufs_getlbns(vp, bn, ap, nump)
++ap;
metalbn -= -1 + off * blockcnt;
- blockcnt /= MNINDIR(ump);
}
if (nump)
*nump = numlevels;
diff --git a/sys/ufs/ufs/ufs_extattr.c b/sys/ufs/ufs/ufs_extattr.c
index 69df5ad1287b..486263a18e1c 100644
--- a/sys/ufs/ufs/ufs_extattr.c
+++ b/sys/ufs/ufs/ufs_extattr.c
@@ -947,7 +947,7 @@ ufs_extattr_get(struct vnode *vp, int attrnamespace, const char *name,
* is to coerce this to undefined, and let it get cleaned
* up by the next write or extattrctl clean.
*/
- printf("ufs_extattr_get (%s): inode number inconsistency (%d, %d)\n",
+ printf("ufs_extattr_get (%s): inode number inconsistency (%d, %lld)\n",
mp->mnt_stat.f_mntonname, ueh.ueh_i_gen, ip->i_gen);
error = ENOATTR;
goto vopunlock_exit;
@@ -1226,7 +1226,7 @@ ufs_extattr_rm(struct vnode *vp, int attrnamespace, const char *name,
* coerce this to undefined, and let it get cleaned up by
* the next write or extattrctl clean.
*/
- printf("ufs_extattr_rm (%s): inode number inconsistency (%d, %d)\n",
+ printf("ufs_extattr_rm (%s): inode number inconsistency (%d, %lld)\n",
mp->mnt_stat.f_mntonname, ueh.ueh_i_gen, ip->i_gen);
error = ENOATTR;
goto vopunlock_exit;
diff --git a/sys/ufs/ufs/ufs_extern.h b/sys/ufs/ufs/ufs_extern.h
index 49e25db6383d..b961df3e318e 100644
--- a/sys/ufs/ufs/ufs_extern.h
+++ b/sys/ufs/ufs/ufs_extern.h
@@ -60,7 +60,8 @@ int ufs_vnoperatefifo(struct vop_generic_args *);
int ufs_vnoperatespec(struct vop_generic_args *);
int ufs_bmap(struct vop_bmap_args *);
-int ufs_bmaparray(struct vnode *, ufs_daddr_t, ufs_daddr_t *, int *, int *);
+int ufs_bmaparray(struct vnode *, ufs2_daddr_t, ufs2_daddr_t *, int *,
+ int *);
int ufs_fhtovp(struct mount *, struct ufid *, struct vnode **);
int ufs_checkpath(struct inode *, struct inode *, struct ucred *);
void ufs_dirbad(struct inode *, doff_t, char *);
@@ -72,7 +73,7 @@ int ufs_direnter(struct vnode *, struct vnode *, struct direct *,
struct componentname *, struct buf *);
int ufs_dirremove(struct vnode *, struct inode *, int, int);
int ufs_dirrewrite(struct inode *, struct inode *, ino_t, int, int);
-int ufs_getlbns(struct vnode *, ufs_daddr_t, struct indir *, int *);
+int ufs_getlbns(struct vnode *, ufs2_daddr_t, struct indir *, int *);
int ufs_ihashget(dev_t, ino_t, int, struct vnode **);
void ufs_ihashinit(void);
int ufs_ihashins(struct inode *, int, struct vnode **);
@@ -94,12 +95,12 @@ int ufs_vinit(struct mount *, vop_t **, vop_t **, struct vnode **);
* Soft update function prototypes.
*/
int softdep_setup_directory_add(struct buf *, struct inode *, off_t,
- long, struct buf *, int);
+ ino_t, struct buf *, int);
void softdep_change_directoryentry_offset(struct inode *, caddr_t,
caddr_t, caddr_t, int);
void softdep_setup_remove(struct buf *,struct inode *, struct inode *, int);
void softdep_setup_directory_change(struct buf *, struct inode *,
- struct inode *, long, int);
+ struct inode *, ino_t, int);
void softdep_change_linkcnt(struct inode *);
void softdep_releasefile(struct inode *);
int softdep_slowdown(struct vnode *);
diff --git a/sys/ufs/ufs/ufs_inode.c b/sys/ufs/ufs/ufs_inode.c
index 55f91282a1c1..b9bbe9e992b7 100644
--- a/sys/ufs/ufs/ufs_inode.c
+++ b/sys/ufs/ufs/ufs_inode.c
@@ -73,7 +73,8 @@ ufs_inactive(ap)
struct vnode *vp = ap->a_vp;
struct inode *ip = VTOI(vp);
struct thread *td = ap->a_td;
- int mode, error = 0;
+ mode_t mode;
+ int error = 0;
if (prtactive && vp->v_usecount != 0)
vprint("ufs_inactive: pushing active", vp);
@@ -101,9 +102,10 @@ ufs_inactive(ap)
* So, rather than creating a new entry point to do the
* same thing, we just use softdep_change_linkcnt().
*/
- ip->i_rdev = 0;
+ DIP(ip, i_rdev) = 0;
mode = ip->i_mode;
ip->i_mode = 0;
+ DIP(ip, i_mode) = 0;
ip->i_flag |= IN_CHANGE | IN_UPDATE;
if (DOINGSOFTDEP(vp))
softdep_change_linkcnt(ip);
@@ -139,15 +141,15 @@ ufs_reclaim(ap)
struct thread *a_td;
} */ *ap;
{
- struct inode *ip;
struct vnode *vp = ap->a_vp;
+ struct inode *ip = VTOI(vp);
+ struct ufsmount *ump = ip->i_ump;
#ifdef QUOTA
int i;
#endif
if (prtactive && vp->v_usecount != 0)
vprint("ufs_reclaim: pushing active", vp);
- ip = VTOI(vp);
if (ip->i_flag & IN_LAZYMOD) {
ip->i_flag |= IN_MODIFIED;
UFS_UPDATE(vp, 0);
@@ -177,7 +179,11 @@ ufs_reclaim(ap)
if (ip->i_dirhash != NULL)
ufsdirhash_free(ip);
#endif
- FREE(vp->v_data, VFSTOUFS(vp->v_mount)->um_malloctype);
+ if (ump->um_fstype == UFS1)
+ FREE(ip->i_din1, ump->um_malloctype);
+ else
+ FREE(ip->i_din2, ump->um_malloctype);
+ FREE(vp->v_data, ump->um_malloctype);
vp->v_data = 0;
return (0);
}
diff --git a/sys/ufs/ufs/ufs_lookup.c b/sys/ufs/ufs/ufs_lookup.c
index 7b37f54e3e36..16089fa3e6bd 100644
--- a/sys/ufs/ufs/ufs_lookup.c
+++ b/sys/ufs/ufs/ufs_lookup.c
@@ -131,8 +131,8 @@ ufs_lookup(ap)
struct componentname *a_cnp;
} */ *ap;
{
- struct vnode *vdp; /* vnode for directory being searched */
- struct inode *dp; /* inode for directory being searched */
+ struct vnode *vdp; /* vnode for directory being searched */
+ struct inode *dp; /* inode for directory being searched */
struct buf *bp; /* a buffer of directory entries */
struct direct *ep; /* the current directory entry */
int entryoffsetinblock; /* offset of ep in bp's buffer */
@@ -467,6 +467,7 @@ found:
if (dp->i_offset + DIRSIZ(OFSFMT(vdp), ep) > dp->i_size) {
ufs_dirbad(dp, dp->i_offset, "i_size too small");
dp->i_size = dp->i_offset + DIRSIZ(OFSFMT(vdp), ep);
+ DIP(dp, i_size) = dp->i_size;
dp->i_flag |= IN_CHANGE | IN_UPDATE;
}
brelse(bp);
@@ -644,8 +645,7 @@ ufs_dirbadentry(dp, ep, entryoffsetinblock)
struct direct *ep;
int entryoffsetinblock;
{
- int i;
- int namlen;
+ int i, namlen;
# if (BYTE_ORDER == LITTLE_ENDIAN)
if (OFSFMT(dp))
@@ -760,6 +760,7 @@ ufs_direnter(dvp, tvp, dirp, cnp, newdirbp)
return (error);
}
dp->i_size = dp->i_offset + DIRBLKSIZ;
+ DIP(dp, i_size) = dp->i_size;
dp->i_flag |= IN_CHANGE | IN_UPDATE;
vnode_pager_setsize(dvp, (u_long)dp->i_size);
dirp->d_reclen = DIRBLKSIZ;
@@ -838,8 +839,10 @@ ufs_direnter(dvp, tvp, dirp, cnp, newdirbp)
*
* N.B. - THIS IS AN ARTIFACT OF 4.2 AND SHOULD NEVER HAPPEN.
*/
- if (dp->i_offset + dp->i_count > dp->i_size)
+ if (dp->i_offset + dp->i_count > dp->i_size) {
dp->i_size = dp->i_offset + dp->i_count;
+ DIP(dp, i_size) = dp->i_size;
+ }
/*
* Get the block containing the space for the new directory entry.
*/
@@ -1049,6 +1052,7 @@ out:
if (ip) {
ip->i_effnlink--;
ip->i_nlink--;
+ DIP(ip, i_nlink) = ip->i_nlink;
ip->i_flag |= IN_CHANGE;
}
if (flags & DOWHITEOUT)
@@ -1102,6 +1106,7 @@ ufs_dirrewrite(dp, oip, newinum, newtype, isrmdir)
bdwrite(bp);
} else {
oip->i_nlink--;
+ DIP(oip, i_nlink) = oip->i_nlink;
oip->i_flag |= IN_CHANGE;
if (DOINGASYNC(vdp)) {
bdwrite(bp);
@@ -1138,7 +1143,7 @@ ufs_dirempty(ip, parentino, cred)
ino_t parentino;
struct ucred *cred;
{
- off_t off;
+ doff_t off;
struct dirtemplate dbuf;
struct direct *dp = (struct direct *)&dbuf;
int error, count, namlen;
@@ -1197,7 +1202,8 @@ ufs_checkpath(source, target, cred)
struct ucred *cred;
{
struct vnode *vp;
- int error, rootino, namlen;
+ int error, namlen;
+ ino_t rootino;
struct dirtemplate dirbuf;
vp = ITOV(target);
diff --git a/sys/ufs/ufs/ufs_quota.c b/sys/ufs/ufs/ufs_quota.c
index ab4a0af7500e..3bc4287ad9a1 100644
--- a/sys/ufs/ufs/ufs_quota.c
+++ b/sys/ufs/ufs/ufs_quota.c
@@ -54,6 +54,7 @@
#include <ufs/ufs/quota.h>
#include <ufs/ufs/inode.h>
#include <ufs/ufs/ufsmount.h>
+#include <ufs/ufs/ufs_extern.h>
static MALLOC_DEFINE(M_DQUOT, "UFS quota", "UFS quota entries");
@@ -62,8 +63,8 @@ static MALLOC_DEFINE(M_DQUOT, "UFS quota", "UFS quota entries");
*/
static char *quotatypes[] = INITQFNAMES;
-static int chkdqchg(struct inode *, long, struct ucred *, int);
-static int chkiqchg(struct inode *, long, struct ucred *, int);
+static int chkdqchg(struct inode *, ufs2_daddr_t, struct ucred *, int);
+static int chkiqchg(struct inode *, ino_t, struct ucred *, int);
static int dqget(struct vnode *,
u_long, struct ufsmount *, int, struct dquot **);
static int dqsync(struct vnode *, struct dquot *);
@@ -118,13 +119,13 @@ getinoquota(ip)
int
chkdq(ip, change, cred, flags)
struct inode *ip;
- long change;
+ ufs2_daddr_t change;
struct ucred *cred;
int flags;
{
struct dquot *dq;
- int i;
- int ncurblocks, error;
+ ufs2_daddr_t ncurblocks;
+ int i, error;
#ifdef DIAGNOSTIC
if ((flags & CHOWN) == 0)
@@ -184,12 +185,12 @@ chkdq(ip, change, cred, flags)
static int
chkdqchg(ip, change, cred, type)
struct inode *ip;
- long change;
+ ufs2_daddr_t change;
struct ucred *cred;
int type;
{
struct dquot *dq = ip->i_dquot[type];
- long ncurblocks = dq->dq_curblocks + change;
+ ufs2_daddr_t ncurblocks = dq->dq_curblocks + change;
/*
* If user would exceed their hard limit, disallow space allocation.
@@ -239,13 +240,13 @@ chkdqchg(ip, change, cred, type)
int
chkiq(ip, change, cred, flags)
struct inode *ip;
- long change;
+ ino_t change;
struct ucred *cred;
int flags;
{
struct dquot *dq;
- int i;
- int ncurinodes, error;
+ ino_t ncurinodes;
+ int i, error;
#ifdef DIAGNOSTIC
if ((flags & CHOWN) == 0)
@@ -305,12 +306,12 @@ chkiq(ip, change, cred, flags)
static int
chkiqchg(ip, change, cred, type)
struct inode *ip;
- long change;
+ ino_t change;
struct ucred *cred;
int type;
{
struct dquot *dq = ip->i_dquot[type];
- long ncurinodes = dq->dq_curinodes + change;
+ ino_t ncurinodes = dq->dq_curinodes + change;
/*
* If user would exceed their hard limit, disallow inode allocation.
diff --git a/sys/ufs/ufs/ufs_readwrite.c b/sys/ufs/ufs/ufs_readwrite.c
index c76081f5bd62..527b3399316c 100644
--- a/sys/ufs/ufs/ufs_readwrite.c
+++ b/sys/ufs/ufs/ufs_readwrite.c
@@ -68,11 +68,11 @@ READ(ap)
struct uio *uio;
FS *fs;
struct buf *bp;
- daddr_t lbn, nextlbn;
+ ufs_lbn_t lbn, nextlbn;
off_t bytesinfile;
long size, xfersize, blkoffset;
int error, orig_resid;
- u_short mode;
+ mode_t mode;
int seqcount;
int ioflag;
vm_object_t object;
@@ -394,7 +394,7 @@ WRITE(ap)
FS *fs;
struct buf *bp;
struct thread *td;
- ufs_daddr_t lbn;
+ ufs_lbn_t lbn;
off_t osize;
int seqcount;
int blkoffset, error, extended, flags, ioflag, resid, size, xfersize;
@@ -519,6 +519,7 @@ WRITE(ap)
if (uio->uio_offset + xfersize > ip->i_size) {
ip->i_size = uio->uio_offset + xfersize;
+ DIP(ip, i_size) = ip->i_size;
extended = 1;
}
@@ -571,8 +572,10 @@ WRITE(ap)
* tampering.
*/
if (resid > uio->uio_resid && ap->a_cred &&
- suser_cred(ap->a_cred, PRISON_ROOT))
+ suser_cred(ap->a_cred, PRISON_ROOT)) {
ip->i_mode &= ~(ISUID | ISGID);
+ DIP(ip, i_mode) = ip->i_mode;
+ }
if (resid > uio->uio_resid)
VN_KNOTE(vp, NOTE_WRITE | (extended ? NOTE_EXTEND : 0));
if (error) {
@@ -609,8 +612,7 @@ ffs_getpages(ap)
int bbackwards, bforwards;
int pbackwards, pforwards;
int firstpage;
- int reqlblkno;
- ufs_daddr_t reqblkno;
+ ufs2_daddr_t reqblkno, reqlblkno;
int poff;
int pcount;
int rtval;
diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c
index 19d785aa3b12..45fa7f7cbf1a 100644
--- a/sys/ufs/ufs/ufs_vnops.c
+++ b/sys/ufs/ufs/ufs_vnops.c
@@ -162,17 +162,17 @@ ufs_itimes(vp)
if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
vfs_timestamp(&ts);
if (ip->i_flag & IN_ACCESS) {
- ip->i_atime = ts.tv_sec;
- ip->i_atimensec = ts.tv_nsec;
+ DIP(ip, i_atime) = ts.tv_sec;
+ DIP(ip, i_atimensec) = ts.tv_nsec;
}
if (ip->i_flag & IN_UPDATE) {
- ip->i_mtime = ts.tv_sec;
- ip->i_mtimensec = ts.tv_nsec;
+ DIP(ip, i_mtime) = ts.tv_sec;
+ DIP(ip, i_mtimensec) = ts.tv_nsec;
ip->i_modrev++;
}
if (ip->i_flag & IN_CHANGE) {
- ip->i_ctime = ts.tv_sec;
- ip->i_ctimensec = ts.tv_nsec;
+ DIP(ip, i_ctime) = ts.tv_sec;
+ DIP(ip, i_ctimensec) = ts.tv_nsec;
}
}
ip->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE);
@@ -232,7 +232,7 @@ ufs_mknod(ap)
* Want to be able to use this to make badblock
* inodes, so don't truncate the dev number.
*/
- ip->i_rdev = vap->va_rdev;
+ DIP(ip, i_rdev) = vap->va_rdev;
}
/*
* Remove inode, then reload it through VFS_VGET so it is
@@ -419,18 +419,34 @@ ufs_getattr(ap)
vap->va_nlink = ip->i_effnlink;
vap->va_uid = ip->i_uid;
vap->va_gid = ip->i_gid;
- vap->va_rdev = ip->i_rdev;
- vap->va_size = ip->i_din.di_size;
- vap->va_atime.tv_sec = ip->i_atime;
- vap->va_atime.tv_nsec = ip->i_atimensec;
- vap->va_mtime.tv_sec = ip->i_mtime;
- vap->va_mtime.tv_nsec = ip->i_mtimensec;
- vap->va_ctime.tv_sec = ip->i_ctime;
- vap->va_ctime.tv_nsec = ip->i_ctimensec;
+ if (ip->i_ump->um_fstype == UFS1) {
+ vap->va_rdev = ip->i_din1->di_rdev;
+ vap->va_size = ip->i_din1->di_size;
+ vap->va_atime.tv_sec = ip->i_din1->di_atime;
+ vap->va_atime.tv_nsec = ip->i_din1->di_atimensec;
+ vap->va_mtime.tv_sec = ip->i_din1->di_mtime;
+ vap->va_mtime.tv_nsec = ip->i_din1->di_mtimensec;
+ vap->va_ctime.tv_sec = ip->i_din1->di_ctime;
+ vap->va_ctime.tv_nsec = ip->i_din1->di_ctimensec;
+ vap->va_createtime.tv_sec = 0;
+ vap->va_createtime.tv_nsec = 0;
+ vap->va_bytes = dbtob((u_quad_t)ip->i_din1->di_blocks);
+ } else {
+ vap->va_rdev = ip->i_din2->di_rdev;
+ vap->va_size = ip->i_din2->di_size;
+ vap->va_atime.tv_sec = ip->i_din2->di_atime;
+ vap->va_atime.tv_nsec = ip->i_din2->di_atimensec;
+ vap->va_mtime.tv_sec = ip->i_din2->di_mtime;
+ vap->va_mtime.tv_nsec = ip->i_din2->di_mtimensec;
+ vap->va_ctime.tv_sec = ip->i_din2->di_ctime;
+ vap->va_ctime.tv_nsec = ip->i_din2->di_ctimensec;
+ vap->va_createtime.tv_sec = ip->i_din2->di_createtime;
+ vap->va_createtime.tv_nsec = ip->i_din2->di_creatensec;
+ vap->va_bytes = dbtob((u_quad_t)ip->i_din2->di_blocks);
+ }
vap->va_flags = ip->i_flags;
vap->va_gen = ip->i_gen;
vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize;
- vap->va_bytes = dbtob((u_quad_t)ip->i_blocks);
vap->va_type = IFTOVT(ip->i_mode);
vap->va_filerev = ip->i_modrev;
return (0);
@@ -494,6 +510,7 @@ ufs_setattr(ap)
(ip->i_flags & SF_SNAPSHOT) != 0))
return (EPERM);
ip->i_flags = vap->va_flags;
+ DIP(ip, i_flags) = vap->va_flags;
} else {
if (ip->i_flags
& (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND) ||
@@ -501,6 +518,7 @@ ufs_setattr(ap)
return (EPERM);
ip->i_flags &= SF_SETTABLE;
ip->i_flags |= (vap->va_flags & UF_SETTABLE);
+ DIP(ip, i_flags) = ip->i_flags;
}
ip->i_flag |= IN_CHANGE;
if (vap->va_flags & (IMMUTABLE | APPEND))
@@ -563,12 +581,12 @@ ufs_setattr(ap)
ip->i_flag |= IN_CHANGE | IN_UPDATE;
ufs_itimes(vp);
if (vap->va_atime.tv_sec != VNOVAL) {
- ip->i_atime = vap->va_atime.tv_sec;
- ip->i_atimensec = vap->va_atime.tv_nsec;
+ DIP(ip, i_atime) = vap->va_atime.tv_sec;
+ DIP(ip, i_atimensec) = vap->va_atime.tv_nsec;
}
if (vap->va_mtime.tv_sec != VNOVAL) {
- ip->i_mtime = vap->va_mtime.tv_sec;
- ip->i_mtimensec = vap->va_mtime.tv_nsec;
+ DIP(ip, i_mtime) = vap->va_mtime.tv_sec;
+ DIP(ip, i_mtimensec) = vap->va_mtime.tv_nsec;
}
error = UFS_UPDATE(vp, 0);
if (error)
@@ -620,6 +638,7 @@ ufs_chmod(vp, mode, cred, td)
}
ip->i_mode &= ~ALLPERMS;
ip->i_mode |= (mode & ALLPERMS);
+ DIP(ip, i_mode) = ip->i_mode;
ip->i_flag |= IN_CHANGE;
return (0);
}
@@ -642,7 +661,7 @@ ufs_chown(vp, uid, gid, cred, td)
int error = 0;
#ifdef QUOTA
int i;
- long change;
+ ufs2_daddr_t change;
#endif
if (uid == (uid_t)VNOVAL)
@@ -677,7 +696,7 @@ ufs_chown(vp, uid, gid, cred, td)
dqrele(vp, ip->i_dquot[GRPQUOTA]);
ip->i_dquot[GRPQUOTA] = NODQUOT;
}
- change = ip->i_blocks;
+ change = DIP(ip, i_blocks);
(void) chkdq(ip, -change, cred, CHOWN);
(void) chkiq(ip, -1, cred, CHOWN);
for (i = 0; i < MAXQUOTAS; i++) {
@@ -686,7 +705,9 @@ ufs_chown(vp, uid, gid, cred, td)
}
#endif
ip->i_gid = gid;
+ DIP(ip, i_gid) = gid;
ip->i_uid = uid;
+ DIP(ip, i_uid) = uid;
#ifdef QUOTA
if ((error = getinoquota(ip)) == 0) {
if (ouid == uid) {
@@ -709,7 +730,9 @@ ufs_chown(vp, uid, gid, cred, td)
}
}
ip->i_gid = ogid;
+ DIP(ip, i_gid) = ogid;
ip->i_uid = ouid;
+ DIP(ip, i_uid) = ouid;
if (getinoquota(ip) == 0) {
if (ouid == uid) {
dqrele(vp, ip->i_dquot[USRQUOTA]);
@@ -729,8 +752,10 @@ good:
panic("ufs_chown: lost quota");
#endif /* QUOTA */
ip->i_flag |= IN_CHANGE;
- if (suser_cred(cred, PRISON_ROOT) && (ouid != uid || ogid != gid))
+ if (suser_cred(cred, PRISON_ROOT) && (ouid != uid || ogid != gid)) {
ip->i_mode &= ~(ISUID | ISGID);
+ DIP(ip, i_mode) = ip->i_mode;
+ }
return (0);
}
@@ -803,6 +828,7 @@ ufs_link(ap)
}
ip->i_effnlink++;
ip->i_nlink++;
+ DIP(ip, i_nlink) = ip->i_nlink;
ip->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(vp))
softdep_change_linkcnt(ip);
@@ -815,6 +841,7 @@ ufs_link(ap)
if (error) {
ip->i_effnlink--;
ip->i_nlink--;
+ DIP(ip, i_nlink) = ip->i_nlink;
ip->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(vp))
softdep_change_linkcnt(ip);
@@ -1065,6 +1092,7 @@ abortit:
*/
ip->i_effnlink++;
ip->i_nlink++;
+ DIP(ip, i_nlink) = ip->i_nlink;
ip->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(fvp))
softdep_change_linkcnt(ip);
@@ -1130,6 +1158,7 @@ abortit:
}
dp->i_effnlink++;
dp->i_nlink++;
+ DIP(dp, i_nlink) = dp->i_nlink;
dp->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(tdvp))
softdep_change_linkcnt(dp);
@@ -1144,6 +1173,7 @@ abortit:
if (doingdirectory && newparent) {
dp->i_effnlink--;
dp->i_nlink--;
+ DIP(dp, i_nlink) = dp->i_nlink;
dp->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(tdvp))
softdep_change_linkcnt(dp);
@@ -1222,9 +1252,11 @@ abortit:
*/
if (!newparent) {
dp->i_nlink--;
+ DIP(dp, i_nlink) = dp->i_nlink;
dp->i_flag |= IN_CHANGE;
}
xp->i_nlink--;
+ DIP(xp, i_nlink) = xp->i_nlink;
xp->i_flag |= IN_CHANGE;
ioflag = DOINGASYNC(tvp) ? 0 : IO_SYNC;
if ((error = UFS_TRUNCATE(tvp, (off_t)0, ioflag,
@@ -1321,6 +1353,7 @@ out:
if (vn_lock(fvp, LK_EXCLUSIVE, td) == 0) {
ip->i_effnlink--;
ip->i_nlink--;
+ DIP(ip, i_nlink) = ip->i_nlink;
ip->i_flag |= IN_CHANGE;
ip->i_flag &= ~IN_RENAME;
if (DOINGSOFTDEP(fvp))
@@ -1378,6 +1411,7 @@ ufs_mkdir(ap)
goto out;
ip = VTOI(tvp);
ip->i_gid = dp->i_gid;
+ DIP(ip, i_gid) = dp->i_gid;
#ifdef SUIDDIR
{
#ifdef QUOTA
@@ -1396,6 +1430,7 @@ ufs_mkdir(ap)
(dp->i_mode & ISUID) && dp->i_uid) {
dmode |= ISUID;
ip->i_uid = dp->i_uid;
+ DIP(ip, i_uid) = dp->i_uid;
#ifdef QUOTA
if (dp->i_uid != cnp->cn_cred->cr_uid) {
/*
@@ -1412,8 +1447,10 @@ ufs_mkdir(ap)
ucp = &ucred;
}
#endif
- } else
+ } else {
ip->i_uid = cnp->cn_cred->cr_uid;
+ DIP(ip, i_uid) = ip->i_uid;
+ }
#ifdef QUOTA
if ((error = getinoquota(ip)) ||
(error = chkiq(ip, 1, ucp, 0))) {
@@ -1425,6 +1462,7 @@ ufs_mkdir(ap)
}
#else /* !SUIDDIR */
ip->i_uid = cnp->cn_cred->cr_uid;
+ DIP(ip, i_uid) = ip->i_uid;
#ifdef QUOTA
if ((error = getinoquota(ip)) ||
(error = chkiq(ip, 1, cnp->cn_cred, 0))) {
@@ -1459,6 +1497,7 @@ ufs_mkdir(ap)
* not defined case.
*/
ip->i_mode = dmode;
+ DIP(ip, i_mode) = dmode;
*dacl = *acl;
ufs_sync_acl_from_inode(ip, acl);
break;
@@ -1470,6 +1509,7 @@ ufs_mkdir(ap)
* Just use the mode as-is.
*/
ip->i_mode = dmode;
+ DIP(ip, i_mode) = dmode;
FREE(acl, M_ACL);
FREE(dacl, M_ACL);
dacl = acl = NULL;
@@ -1482,14 +1522,18 @@ ufs_mkdir(ap)
}
#else /* !UFS_ACL */
ip->i_mode = dmode;
+ DIP(ip, i_mode) = dmode;
#endif /* !UFS_ACL */
tvp->v_type = VDIR; /* Rest init'd in getnewvnode(). */
ip->i_effnlink = 2;
ip->i_nlink = 2;
+ DIP(ip, i_nlink) = 2;
if (DOINGSOFTDEP(tvp))
softdep_change_linkcnt(ip);
- if (cnp->cn_flags & ISWHITEOUT)
+ if (cnp->cn_flags & ISWHITEOUT) {
ip->i_flags |= UF_OPAQUE;
+ DIP(ip, i_flags) = ip->i_flags;
+ }
/*
* Bump link count in parent directory to reflect work done below.
@@ -1498,6 +1542,7 @@ ufs_mkdir(ap)
*/
dp->i_effnlink++;
dp->i_nlink++;
+ DIP(dp, i_nlink) = dp->i_nlink;
dp->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(dvp))
softdep_change_linkcnt(dp);
@@ -1555,6 +1600,7 @@ ufs_mkdir(ap)
B_CLRBUF, &bp)) != 0)
goto bad;
ip->i_size = DIRBLKSIZ;
+ DIP(ip, i_size) = DIRBLKSIZ;
ip->i_flag |= IN_CHANGE | IN_UPDATE;
vnode_pager_setsize(tvp, (u_long)ip->i_size);
bcopy((caddr_t)&dirtemplate, (caddr_t)bp->b_data, sizeof dirtemplate);
@@ -1602,6 +1648,7 @@ bad:
} else {
dp->i_effnlink--;
dp->i_nlink--;
+ DIP(dp, i_nlink) = dp->i_nlink;
dp->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(dvp))
softdep_change_linkcnt(dp);
@@ -1611,6 +1658,7 @@ bad:
*/
ip->i_effnlink = 0;
ip->i_nlink = 0;
+ DIP(ip, i_nlink) = 0;
ip->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(tvp))
softdep_change_linkcnt(ip);
@@ -1699,8 +1747,10 @@ ufs_rmdir(ap)
*/
if (!DOINGSOFTDEP(vp)) {
dp->i_nlink--;
+ DIP(dp, i_nlink) = dp->i_nlink;
dp->i_flag |= IN_CHANGE;
ip->i_nlink--;
+ DIP(ip, i_nlink) = ip->i_nlink;
ip->i_flag |= IN_CHANGE;
ioflag = DOINGASYNC(vp) ? 0 : IO_SYNC;
error = UFS_TRUNCATE(vp, (off_t)0, ioflag, cnp->cn_cred,
@@ -1743,8 +1793,9 @@ ufs_symlink(ap)
len = strlen(ap->a_target);
if (len < vp->v_mount->mnt_maxsymlinklen) {
ip = VTOI(vp);
- bcopy(ap->a_target, (char *)ip->i_shortlink, len);
+ bcopy(ap->a_target, SHORTLINK(ip), len);
ip->i_size = len;
+ DIP(ip, i_size) = len;
ip->i_flag |= IN_CHANGE | IN_UPDATE;
} else
error = vn_rdwr(UIO_WRITE, vp, ap->a_target, len, (off_t)0,
@@ -1884,12 +1935,12 @@ ufs_readlink(ap)
{
struct vnode *vp = ap->a_vp;
struct inode *ip = VTOI(vp);
- int isize;
+ doff_t isize;
isize = ip->i_size;
if ((isize < vp->v_mount->mnt_maxsymlinklen) ||
- (ip->i_din.di_blocks == 0)) { /* XXX - for old fastlink support */
- uiomove((char *)ip->i_shortlink, isize, ap->a_uio);
+ DIP(ip, i_blocks) == 0) { /* XXX - for old fastlink support */
+ uiomove(SHORTLINK(ip), isize, ap->a_uio);
return (0);
}
return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred));
@@ -1912,7 +1963,7 @@ ufs_strategy(ap)
struct buf *bp = ap->a_bp;
struct vnode *vp = ap->a_vp;
struct inode *ip;
- ufs_daddr_t blkno;
+ ufs2_daddr_t blkno;
int error;
ip = VTOI(vp);
@@ -2206,7 +2257,7 @@ ufs_vinit(mntp, specops, fifoops, vpp)
case VCHR:
case VBLK:
vp->v_op = specops;
- vp = addaliasu(vp, ip->i_rdev);
+ vp = addaliasu(vp, DIP(ip, i_rdev));
ip->i_vnode = vp;
break;
case VFIFO:
@@ -2261,6 +2312,7 @@ ufs_makeinode(mode, dvp, vpp, cnp)
return (error);
ip = VTOI(tvp);
ip->i_gid = pdir->i_gid;
+ DIP(ip, i_gid) = pdir->i_gid;
#ifdef SUIDDIR
{
#ifdef QUOTA
@@ -2278,6 +2330,7 @@ ufs_makeinode(mode, dvp, vpp, cnp)
(pdir->i_mode & ISUID) &&
(pdir->i_uid != cnp->cn_cred->cr_uid) && pdir->i_uid) {
ip->i_uid = pdir->i_uid;
+ DIP(ip, i_uid) = ip->i_uid;
mode &= ~07111;
#ifdef QUOTA
/*
@@ -2293,8 +2346,10 @@ ufs_makeinode(mode, dvp, vpp, cnp)
ucred.cr_groups[0] = pdir->i_gid;
ucp = &ucred;
#endif
- } else
+ } else {
ip->i_uid = cnp->cn_cred->cr_uid;
+ DIP(ip, i_uid) = ip->i_uid;
+ }
#ifdef QUOTA
if ((error = getinoquota(ip)) ||
@@ -2307,6 +2362,7 @@ ufs_makeinode(mode, dvp, vpp, cnp)
}
#else /* !SUIDDIR */
ip->i_uid = cnp->cn_cred->cr_uid;
+ DIP(ip, i_uid) = ip->i_uid;
#ifdef QUOTA
if ((error = getinoquota(ip)) ||
(error = chkiq(ip, 1, cnp->cn_cred, 0))) {
@@ -2339,6 +2395,7 @@ ufs_makeinode(mode, dvp, vpp, cnp)
* not defined case.
*/
ip->i_mode = mode;
+ DIP(ip, i_mode) = mode;
ufs_sync_acl_from_inode(ip, acl);
break;
}
@@ -2348,6 +2405,7 @@ ufs_makeinode(mode, dvp, vpp, cnp)
* Just use the mode as-is.
*/
ip->i_mode = mode;
+ DIP(ip, i_mode) = mode;
FREE(acl, M_ACL);
acl = NULL;
break;
@@ -2359,18 +2417,24 @@ ufs_makeinode(mode, dvp, vpp, cnp)
}
#else /* !UFS_ACL */
ip->i_mode = mode;
+ DIP(ip, i_mode) = mode;
#endif /* !UFS_ACL */
tvp->v_type = IFTOVT(mode); /* Rest init'd in getnewvnode(). */
ip->i_effnlink = 1;
ip->i_nlink = 1;
+ DIP(ip, i_nlink) = 1;
if (DOINGSOFTDEP(tvp))
softdep_change_linkcnt(ip);
if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, cnp->cn_cred) &&
- suser_cred(cnp->cn_cred, PRISON_ROOT))
+ suser_cred(cnp->cn_cred, PRISON_ROOT)) {
ip->i_mode &= ~ISGID;
+ DIP(ip, i_mode) = ip->i_mode;
+ }
- if (cnp->cn_flags & ISWHITEOUT)
+ if (cnp->cn_flags & ISWHITEOUT) {
ip->i_flags |= UF_OPAQUE;
+ DIP(ip, i_flags) = ip->i_flags;
+ }
/*
* Make sure inode goes to disk before directory entry.
@@ -2422,6 +2486,7 @@ bad:
*/
ip->i_effnlink = 0;
ip->i_nlink = 0;
+ DIP(ip, i_nlink) = 0;
ip->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(tvp))
softdep_change_linkcnt(ip);
diff --git a/sys/ufs/ufs/ufsmount.h b/sys/ufs/ufs/ufsmount.h
index dc995b46938f..99d60787ebb7 100644
--- a/sys/ufs/ufs/ufsmount.h
+++ b/sys/ufs/ufs/ufsmount.h
@@ -65,9 +65,8 @@ struct ufsmount {
struct mount *um_mountp; /* filesystem vfs structure */
dev_t um_dev; /* device mounted */
struct vnode *um_devvp; /* block device mounted vnode */
-
+ u_long um_fstype; /* type of filesystem */
struct fs *um_fs; /* pointer to superblock */
-
struct vnode *um_quotas[MAXQUOTAS]; /* pointer to quota files */
struct ucred *um_cred[MAXQUOTAS]; /* quota file access cred */
struct ufs_extattr_per_mount um_extattr; /* extended attrs */
@@ -95,6 +94,12 @@ struct ufsmount {
#define UFS_VFREE(aa, bb, cc) VFSTOUFS((aa)->v_mount)->um_vfree(aa, bb, cc)
/*
+ * Filesystem types
+ */
+#define UFS1 1
+#define UFS2 2
+
+/*
* Flags describing the state of quotas.
*/
#define QTF_OPENING 0x01 /* Q_QUOTAON in progress */
diff --git a/usr.bin/fstat/fstat.c b/usr.bin/fstat/fstat.c
index 3a08f64e61cd..9d26aeae51a3 100644
--- a/usr.bin/fstat/fstat.c
+++ b/usr.bin/fstat/fstat.c
@@ -599,7 +599,11 @@ ufs_filestat(vp, fsp)
fsp->fileid = (long)inode.i_number;
fsp->mode = (mode_t)inode.i_mode;
fsp->size = (u_long)inode.i_size;
+#if should_be_but_is_hard
fsp->rdev = inode.i_rdev;
+#else
+ fsp->rdev = 0;
+#endif
return 1;
}
diff --git a/usr.sbin/quot/quot.c b/usr.sbin/quot/quot.c
index f5e91826ac0b..42148448cdc2 100644
--- a/usr.sbin/quot/quot.c
+++ b/usr.sbin/quot/quot.c
@@ -39,9 +39,8 @@ static const char rcsid[] =
#include <sys/mount.h>
#include <sys/disklabel.h>
#include <sys/time.h>
+#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
-#include <ufs/ufs/quota.h>
-#include <ufs/ufs/inode.h>
#include <err.h>
#include <fcntl.h>
@@ -63,9 +62,9 @@ static long blocksize;
static char *header;
static int headerlen;
-static struct dinode *get_inode(int, struct fs *, ino_t);
-static int virtualblocks(struct fs *, struct dinode *);
-static int isfree(struct dinode *);
+static union dinode *get_inode(int, struct fs *, ino_t);
+static int virtualblocks(struct fs *, union dinode *);
+static int isfree(struct fs *, union dinode *);
static void inituser(void);
static void usrrehash(void);
static struct user *user(uid_t);
@@ -96,51 +95,65 @@ static void quot(char *, char *);
#endif
#define INOCNT(fs) ((fs)->fs_ipg)
-#define INOSZ(fs) (sizeof(struct dinode) * INOCNT(fs))
+#define INOSZ(fs) \
+ (((fs)->fs_magic == FS_UFS1_MAGIC ? sizeof(struct ufs1_dinode) : \
+ sizeof(struct ufs2_dinode)) * INOCNT(fs))
-static struct dinode *
+union dinode {
+ struct ufs1_dinode dp1;
+ struct ufs2_dinode dp2;
+};
+#define DIP(fs, dp, field) \
+ (((fs)->fs_magic == FS_UFS1_MAGIC) ? \
+ (dp)->dp1.field : (dp)->dp2.field)
+
+static union dinode *
get_inode(fd,super,ino)
int fd;
struct fs *super;
ino_t ino;
{
- static struct dinode *ip;
+ static caddr_t ipbuf;
static ino_t last;
if (fd < 0) { /* flush cache */
- if (ip) {
- free(ip);
- ip = 0;
+ if (ipbuf) {
+ free(ipbuf);
+ ipbuf = 0;
}
return 0;
}
- if (!ip || ino < last || ino >= last + INOCNT(super)) {
- if (!ip
- && !(ip = (struct dinode *)malloc(INOSZ(super))))
+ if (!ipbuf || ino < last || ino >= last + INOCNT(super)) {
+ if (!ipbuf
+ && !(ipbuf = malloc(INOSZ(super))))
errx(1, "allocate inodes");
last = (ino / INOCNT(super)) * INOCNT(super);
if (lseek(fd, (off_t)ino_to_fsba(super, last) << super->fs_fshift, 0) < (off_t)0
- || read(fd,ip,INOSZ(super)) != (ssize_t)INOSZ(super))
+ || read(fd, ipbuf, INOSZ(super)) != (ssize_t)INOSZ(super))
err(1, "read inodes");
}
- return ip + ino % INOCNT(super);
+ if (super->fs_magic == FS_UFS1_MAGIC)
+ return ((union dinode *)
+ &((struct ufs1_dinode *)ipbuf)[ino % INOCNT(super)]);
+ return ((union dinode *)
+ &((struct ufs2_dinode *)ipbuf)[ino % INOCNT(super)]);
}
#ifdef COMPAT
-#define actualblocks(super,ip) ((ip)->di_blocks/2)
+#define actualblocks(fs, dp) (DIP(fs, dp, di_blocks) / 2)
#else
-#define actualblocks(super,ip) ((ip)->di_blocks)
+#define actualblocks(fs, dp) DIP(fs, dp, di_blocks)
#endif
-static int virtualblocks(super,ip)
+static int virtualblocks(super, dp)
struct fs *super;
- struct dinode *ip;
+ union dinode *dp;
{
register off_t nblk, sz;
- sz = ip->di_size;
+ sz = DIP(super, dp, di_size);
#ifdef COMPAT
if (lblkno(super,sz) >= NDADDR) {
nblk = blkroundup(super,sz);
@@ -169,14 +182,15 @@ static int virtualblocks(super,ip)
}
static int
-isfree(ip)
- struct dinode *ip;
+isfree(super, dp)
+ struct fs *super;
+ union dinode *dp;
{
#ifdef COMPAT
- return (ip->di_mode&IFMT) == 0;
+ return (DIP(super, dp, di_mode) & IFMT) == 0;
#else /* COMPAT */
- switch (ip->di_mode&IFMT) {
+ switch (DIP(super, dp, di_mode) & IFMT) {
case IFIFO:
case IFLNK: /* should check FASTSYMLINK? */
case IFDIR:
@@ -341,13 +355,13 @@ initfsizes()
}
static void
-dofsizes(fd,super,name)
+dofsizes(fd, super, name)
int fd;
struct fs *super;
char *name;
{
ino_t inode, maxino;
- struct dinode *ip;
+ union dinode *dp;
daddr_t sz, ksz;
struct fsizes *fp, **fsp;
register int i;
@@ -359,16 +373,16 @@ dofsizes(fd,super,name)
#endif /* COMPAT */
for (inode = 0; inode < maxino; inode++) {
errno = 0;
- if ((ip = get_inode(fd,super,inode))
+ if ((dp = get_inode(fd,super,inode))
#ifdef COMPAT
- && ((ip->di_mode&IFMT) == IFREG
- || (ip->di_mode&IFMT) == IFDIR)
+ && ((DIP(super, dp, di_mode) & IFMT) == IFREG
+ || (DIP(super, dp, di_mode) & IFMT) == IFDIR)
#else /* COMPAT */
- && !isfree(ip)
+ && !isfree(super, dp)
#endif /* COMPAT */
) {
- sz = estimate ? virtualblocks(super,ip) :
- actualblocks(super,ip);
+ sz = estimate ? virtualblocks(super, dp) :
+ actualblocks(super, dp);
#ifdef COMPAT
if (sz >= FSZCNT) {
fsizes->fsz_count[FSZCNT-1]++;
@@ -416,25 +430,25 @@ dofsizes(fd,super,name)
}
static void
-douser(fd,super,name)
+douser(fd, super, name)
int fd;
struct fs *super;
char *name;
{
ino_t inode, maxino;
struct user *usr, *usrs;
- struct dinode *ip;
+ union dinode *dp;
register int n;
maxino = super->fs_ncg * super->fs_ipg - 1;
for (inode = 0; inode < maxino; inode++) {
errno = 0;
- if ((ip = get_inode(fd,super,inode))
- && !isfree(ip))
- uses(ip->di_uid,
- estimate ? virtualblocks(super,ip) :
- actualblocks(super,ip),
- ip->di_atime);
+ if ((dp = get_inode(fd,super,inode))
+ && !isfree(super, dp))
+ uses(DIP(super, dp, di_uid),
+ estimate ? virtualblocks(super, dp) :
+ actualblocks(super, dp),
+ DIP(super, dp, di_atime));
else if (errno) {
err(1, "%s", name);
}
@@ -459,7 +473,7 @@ douser(fd,super,name)
}
static void
-donames(fd,super,name)
+donames(fd, super, name)
int fd;
struct fs *super;
char *name;
@@ -467,7 +481,7 @@ donames(fd,super,name)
int c;
ino_t inode, inode1;
ino_t maxino;
- struct dinode *ip;
+ union dinode *dp;
maxino = super->fs_ncg * super->fs_ipg - 1;
/* first skip the name of the filesystem */
@@ -481,9 +495,9 @@ donames(fd,super,name)
return;
}
errno = 0;
- if ((ip = get_inode(fd,super,inode))
- && !isfree(ip)) {
- printf("%s\t",user(ip->di_uid)->name);
+ if ((dp = get_inode(fd,super,inode))
+ && !isfree(super, dp)) {
+ printf("%s\t",user(DIP(super, dp, di_uid))->name);
/* now skip whitespace */
while ((c = getchar()) == ' ' || c == '\t');
/* and print out the remainder of the input line */
@@ -516,25 +530,45 @@ usage()
exit(1);
}
-static char superblock[SBSIZE];
+/*
+ * Possible superblock locations ordered from most to least likely.
+ */
+static int sblock_try[] = SBLOCKSEARCH;
+static char superblock[SBLOCKSIZE];
void
quot(name,mp)
char *name, *mp;
{
- int fd;
+ int i, fd;
+ struct fs *fs;
get_inode(-1, NULL, 0); /* flush cache */
inituser();
initfsizes();
- if ((fd = open(name,0)) < 0
- || lseek(fd,SBOFF,0) != SBOFF
- || read(fd,superblock,SBSIZE) != SBSIZE) {
+ if ((fd = open(name,0)) < 0) {
warn("%s", name);
close(fd);
return;
}
- if (((struct fs *)superblock)->fs_magic != FS_MAGIC) {
+ for (i = 0; sblock_try[i] != -1; i++) {
+ if (lseek(fd, sblock_try[i], 0) != sblock_try[i]) {
+ close(fd);
+ return;
+ }
+ if (read(fd, superblock, SBLOCKSIZE) != SBLOCKSIZE) {
+ close(fd);
+ return;
+ }
+ fs = (struct fs *)superblock;
+ if ((fs->fs_magic == FS_UFS1_MAGIC ||
+ (fs->fs_magic == FS_UFS2_MAGIC &&
+ fs->fs_sblockloc == numfrags(fs, sblock_try[i]))) &&
+ fs->fs_bsize <= MAXBSIZE &&
+ fs->fs_bsize >= sizeof(struct fs))
+ break;
+ }
+ if (sblock_try[i] == -1) {
warnx("%s: not a BSD filesystem",name);
close(fd);
return;
@@ -543,7 +577,7 @@ quot(name,mp)
if (mp)
printf(" (%s)",mp);
putchar('\n');
- (*func)(fd,(struct fs *)superblock,name);
+ (*func)(fd, fs, name);
close(fd);
}