summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
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