summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authormckusick <mckusick@FreeBSD.org>2002-06-21 06:18:05 +0000
committermckusick <mckusick@FreeBSD.org>2002-06-21 06:18:05 +0000
commit88d85c15ef183c06524d6ca695f62c0c0672b00c (patch)
treef1364dbfb9835934a3879b5904f7ff9a1495744c /sys
parenteacb69b0197a8553d5004aa99532cabad8778e36 (diff)
downloadFreeBSD-src-88d85c15ef183c06524d6ca695f62c0c0672b00c.zip
FreeBSD-src-88d85c15ef183c06524d6ca695f62c0c0672b00c.tar.gz
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>
Diffstat (limited to 'sys')
-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
46 files changed, 2797 insertions, 1243 deletions
diff --git a/sys/amd64/Makefile b/sys/amd64/Makefile
index 14ba0b3..b7d021a 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 053dbe0..b0a1547 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 4fd9447..3fbdc45 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 2883b93..75e4fe3 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 fa82999..e506c29 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 2883b93..75e4fe3 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 fa82999..e506c29 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 1268e02..5c5292b 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 0ad1276..8ff4779 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 14ba0b3..b7d021a 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 176dafe..3bedc9c 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 a52e301..ec6099e 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 be0778b..100aebf 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 c0eed78..4c11952 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 5c73224..d66417e 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 5c73224..d66417e 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 64e26be..8dcf5c3 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 00c8de0..ce48cef 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 4390743..ded6f77 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 182854a..be774bd 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 2dbb487..dbd757e 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 b2e3595..6b00abd 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 bbb12ab..8274765 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 215cc85..fe9af1e 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 7965211..7bc4656 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 a1422ac..345bfde 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 36585f8..4bf0189 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 f484090..773a8d3 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 1ffae90..b86a9ac 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 ed52815..53a1ea5 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 6615222..0c5e8c4 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 837f902..822f4eb 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 cdb1f68..cbee51b 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 0168797..5caea85 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 5a327c8..02fa951 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 5737088..15f512c 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 5869caf..390e0db 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 2bd312f..abe2bea 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 69df5ad..486263a 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 49e25db..b961df3 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 55f9128..b9bbe9e 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 7b37f54..16089fa 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 ab4a0af..3bc4287 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 c76081f..527b339 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 19d785a..45fa7f7 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 dc995b4..99d6078 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 */
OpenPOWER on IntegriCloud