summaryrefslogtreecommitdiffstats
path: root/sys/ufs/ffs
diff options
context:
space:
mode:
authorjulian <julian@FreeBSD.org>1998-03-08 09:59:44 +0000
committerjulian <julian@FreeBSD.org>1998-03-08 09:59:44 +0000
commit10c5ccc30ae8155c4d8bd25aeffd9ed0e476c387 (patch)
treed2ed60b6b9462fe6eebf4796c39dfcf3cec39874 /sys/ufs/ffs
parent1d108bde84c6b5fa5d119363c4f401cc3dcc8110 (diff)
downloadFreeBSD-src-10c5ccc30ae8155c4d8bd25aeffd9ed0e476c387.zip
FreeBSD-src-10c5ccc30ae8155c4d8bd25aeffd9ed0e476c387.tar.gz
Reviewed by: dyson@freebsd.org (john Dyson), dg@root.com (david greenman)
Submitted by: Kirk McKusick (mcKusick@mckusick.com) Obtained from: WHistle development tree
Diffstat (limited to 'sys/ufs/ffs')
-rw-r--r--sys/ufs/ffs/ffs_alloc.c93
-rw-r--r--sys/ufs/ffs/ffs_balloc.c92
-rw-r--r--sys/ufs/ffs/ffs_extern.h34
-rw-r--r--sys/ufs/ffs/ffs_inode.c56
-rw-r--r--sys/ufs/ffs/ffs_subr.c26
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c85
-rw-r--r--sys/ufs/ffs/ffs_vnops.c97
-rw-r--r--sys/ufs/ffs/fs.h16
8 files changed, 386 insertions, 113 deletions
diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c
index f2e6a74..8eab25a 100644
--- a/sys/ufs/ffs/ffs_alloc.c
+++ b/sys/ufs/ffs/ffs_alloc.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ffs_alloc.c 8.18 (Berkeley) 5/26/95
- * $Id: ffs_alloc.c,v 1.46 1998/02/04 22:33:27 eivind Exp $
+ * $Id: ffs_alloc.c,v 1.47 1998/02/06 12:14:13 eivind Exp $
*/
#include "opt_quota.h"
@@ -57,7 +57,8 @@ typedef ufs_daddr_t allocfcn_t __P((struct inode *ip, int cg, ufs_daddr_t bpref,
int size));
static ufs_daddr_t ffs_alloccg __P((struct inode *, int, ufs_daddr_t, int));
-static ufs_daddr_t ffs_alloccgblk __P((struct fs *, struct cg *, ufs_daddr_t));
+static ufs_daddr_t
+ ffs_alloccgblk __P((struct inode *, struct buf *, ufs_daddr_t));
#ifdef DIAGNOSTIC
static int ffs_checkblk __P((struct inode *, ufs_daddr_t, long));
#endif
@@ -292,7 +293,8 @@ ffs_realloccg(ip, lbprev, bpref, osize, nsize, cred, bpp)
ffs_alloccg);
if (bno > 0) {
bp->b_blkno = fsbtodb(fs, bno);
- ffs_blkfree(ip, bprev, (long)osize);
+ if (!DOINGSOFTDEP(ITOV(ip)))
+ ffs_blkfree(ip, bprev, (long)osize);
if (nsize < request)
ffs_blkfree(ip, bno + numfrags(fs, nsize),
(long)(request - nsize));
@@ -455,8 +457,10 @@ ffs_reallocblks(ap)
#endif
blkno = newblk;
for (bap = &sbap[soff], i = 0; i < len; i++, blkno += fs->fs_frag) {
- if (i == ssize)
+ if (i == ssize) {
bap = ebap;
+ soff = -i;
+ }
#ifdef DIAGNOSTIC
if (!ffs_checkblk(ip,
dbtofsb(fs, buflist->bs_children[i]->b_blkno), fs->fs_bsize))
@@ -468,6 +472,16 @@ ffs_reallocblks(ap)
if (prtrealloc)
printf(" %d,", *bap);
#endif
+ if (DOINGSOFTDEP(vp)) {
+ if (sbap == &ip->i_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;
}
/*
@@ -509,8 +523,10 @@ ffs_reallocblks(ap)
printf("\n\tnew:");
#endif
for (blkno = newblk, i = 0; i < len; i++, blkno += fs->fs_frag) {
- ffs_blkfree(ip, dbtofsb(fs, buflist->bs_children[i]->b_blkno),
- fs->fs_bsize);
+ if (!DOINGSOFTDEP(vp))
+ ffs_blkfree(ip,
+ dbtofsb(fs, buflist->bs_children[i]->b_blkno),
+ fs->fs_bsize);
buflist->bs_children[i]->b_blkno = fsbtodb(fs, blkno);
#ifdef DEBUG
if (!ffs_checkblk(ip,
@@ -847,6 +863,8 @@ ffs_fragextend(ip, cg, bprev, osize, nsize)
fs->fs_cs(fs, cg).cs_nffree--;
}
fs->fs_fmod = 1;
+ if (DOINGSOFTDEP(ITOV(ip)))
+ softdep_setup_blkmapdep(bp, fs, bprev);
bdwrite(bp);
return (bprev);
}
@@ -868,7 +886,8 @@ ffs_alloccg(ip, cg, bpref, size)
register struct cg *cgp;
struct buf *bp;
register int i;
- int error, bno, frags, allocsiz;
+ ufs_daddr_t bno, blkno;
+ int allocsiz, error, frags;
fs = ip->i_fs;
if (fs->fs_cs(fs, cg).cs_nbfree == 0 && size == fs->fs_bsize)
@@ -887,7 +906,7 @@ ffs_alloccg(ip, cg, bpref, size)
}
cgp->cg_time = time.tv_sec;
if (size == fs->fs_bsize) {
- bno = ffs_alloccgblk(fs, cgp, bpref);
+ bno = ffs_alloccgblk(ip, bp, bpref);
bdwrite(bp);
return (bno);
}
@@ -909,7 +928,7 @@ ffs_alloccg(ip, cg, bpref, size)
brelse(bp);
return (0);
}
- bno = ffs_alloccgblk(fs, cgp, bpref);
+ bno = ffs_alloccgblk(ip, bp, bpref);
bpref = dtogd(fs, bno);
for (i = frags; i < fs->fs_frag; i++)
setbit(cg_blksfree(cgp), bpref + i);
@@ -936,8 +955,11 @@ ffs_alloccg(ip, cg, bpref, size)
cgp->cg_frsum[allocsiz]--;
if (frags != allocsiz)
cgp->cg_frsum[allocsiz - frags]++;
+ blkno = cg * fs->fs_fpg + bno;
+ if (DOINGSOFTDEP(ITOV(ip)))
+ softdep_setup_blkmapdep(bp, fs, blkno);
bdwrite(bp);
- return (cg * fs->fs_fpg + bno);
+ return ((u_long)blkno);
}
/*
@@ -952,16 +974,20 @@ ffs_alloccg(ip, cg, bpref, size)
* blocks may be fragmented by the routine that allocates them.
*/
static ufs_daddr_t
-ffs_alloccgblk(fs, cgp, bpref)
- register struct fs *fs;
- register struct cg *cgp;
+ffs_alloccgblk(ip, bp, bpref)
+ struct inode *ip;
+ struct buf *bp;
ufs_daddr_t bpref;
{
+ struct fs *fs;
+ struct cg *cgp;
ufs_daddr_t bno, blkno;
int cylno, pos, delta;
short *cylbp;
register int i;
+ fs = ip->i_fs;
+ cgp = (struct cg *)bp->b_data;
if (bpref == 0 || dtog(fs, bpref) != cgp->cg_cgx) {
bpref = cgp->cg_rotor;
goto norot;
@@ -1052,7 +1078,10 @@ gotit:
cg_blks(fs, cgp, cylno)[cbtorpos(fs, bno)]--;
cg_blktot(cgp)[cylno]--;
fs->fs_fmod = 1;
- return (cgp->cg_cgx * fs->fs_fpg + bno);
+ blkno = cgp->cg_cgx * fs->fs_fpg + bno;
+ if (DOINGSOFTDEP(ITOV(ip)))
+ softdep_setup_blkmapdep(bp, fs, blkno);
+ return (blkno);
}
#ifdef notyet
@@ -1155,7 +1184,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(fs, cgp, bno + i)) != bno + i)
+ if ((got = ffs_alloccgblk(ip, bp, bno + i)) != bno + i)
panic("ffs_clusteralloc: lost block");
bdwrite(bp);
return (bno);
@@ -1234,6 +1263,8 @@ ffs_nodealloccg(ip, cg, ipref, mode)
panic("ffs_nodealloccg: block not in map");
/* NOTREACHED */
gotit:
+ if (DOINGSOFTDEP(ITOV(ip)))
+ softdep_setup_inomapdep(bp, ip, cg * fs->fs_ipg + ipref);
setbit(cg_inosused(cgp), ipref);
cgp->cg_cs.cs_nifree--;
fs->fs_cstotal.cs_nifree--;
@@ -1268,9 +1299,10 @@ ffs_blkfree(ip, bno, size)
int i, error, cg, blk, frags, bbase;
fs = ip->i_fs;
- if ((u_int)size > fs->fs_bsize || fragoff(fs, size) != 0) {
- printf("dev = 0x%lx, bsize = %ld, size = %ld, fs = %s\n",
- (u_long)ip->i_dev, fs->fs_bsize, size, fs->fs_fsmnt);
+ if ((u_int)size > fs->fs_bsize || fragoff(fs, size) != 0 ||
+ fragnum(fs, bno) + numfrags(fs, size) > fs->fs_frag) {
+ printf("dev=0x%lx, bno = %d, bsize = %d, size = %ld, fs = %s\n",
+ (u_long)ip->i_dev, bno, fs->fs_bsize, size, fs->fs_fsmnt);
panic("ffs_blkfree: bad size");
}
cg = dtog(fs, bno);
@@ -1294,7 +1326,7 @@ ffs_blkfree(ip, bno, size)
bno = dtogd(fs, bno);
if (size == fs->fs_bsize) {
blkno = fragstoblks(fs, bno);
- if (ffs_isblock(fs, cg_blksfree(cgp), blkno)) {
+ if (!ffs_isfreeblock(fs, cg_blksfree(cgp), blkno)) {
printf("dev = 0x%lx, block = %ld, fs = %s\n",
(u_long) ip->i_dev, bno, fs->fs_fsmnt);
panic("ffs_blkfree: freeing free block");
@@ -1404,11 +1436,26 @@ ffs_checkblk(ip, bno, size)
/*
* Free an inode.
- *
- * The specified inode is placed back in the free map.
*/
int
-ffs_vfree(pvp, ino, mode)
+ffs_vfree( pvp, ino, mode)
+ struct vnode *pvp;
+ ino_t ino;
+ int mode;
+{
+ if (DOINGSOFTDEP(pvp)) {
+ softdep_freefile(pvp, ino, mode);
+ return (0);
+ }
+ return (ffs_freefile(pvp, ino, mode));
+}
+
+/*
+ * Do the actual free operation.
+ * The specified inode is placed back in the free map.
+ */
+ int
+ ffs_freefile( pvp, ino, mode)
struct vnode *pvp;
ino_t ino;
int mode;
@@ -1429,7 +1476,7 @@ ffs_vfree(pvp, ino, mode)
(int)fs->fs_cgsize, NOCRED, &bp);
if (error) {
brelse(bp);
- return (0);
+ return (error);
}
cgp = (struct cg *)bp->b_data;
if (!cg_chkmagic(cgp)) {
diff --git a/sys/ufs/ffs/ffs_balloc.c b/sys/ufs/ffs/ffs_balloc.c
index 60d2037..cf253b7 100644
--- a/sys/ufs/ffs/ffs_balloc.c
+++ b/sys/ufs/ffs/ffs_balloc.c
@@ -31,13 +31,14 @@
* SUCH DAMAGE.
*
* @(#)ffs_balloc.c 8.8 (Berkeley) 6/16/95
- * $Id: ffs_balloc.c,v 1.18 1998/02/04 22:33:31 eivind Exp $
+ * $Id: ffs_balloc.c,v 1.19 1998/02/06 12:14:14 eivind Exp $
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/buf.h>
#include <sys/lock.h>
+#include <sys/mount.h>
#include <sys/vnode.h>
#include <ufs/ufs/quota.h>
@@ -53,16 +54,23 @@
* the inode and the logical block number in a file.
*/
int
-ffs_balloc(ip, lbn, size, cred, bpp, flags)
+ffs_balloc(ap)
+ struct vop_balloc_args /* {
+ struct inode *a_ip;
+ ufs_daddr_t a_lbn;
+ int a_size;
+ struct ucred *a_cred;
+ int a_flags;
+ struct buf *a_bpp;
+ } */ *ap;
+{
register struct inode *ip;
register ufs_daddr_t lbn;
int size;
struct ucred *cred;
- struct buf **bpp;
int flags;
-{
- register struct fs *fs;
- register ufs_daddr_t nb;
+ struct fs *fs;
+ ufs_daddr_t nb;
struct buf *bp, *nbp;
struct vnode *vp = ITOV(ip);
struct indir indirs[NIADDR + 2];
@@ -70,10 +78,18 @@ ffs_balloc(ip, lbn, size, cred, bpp, flags)
int deallocated, osize, nsize, num, i, error;
ufs_daddr_t *allocib, *blkp, *allocblk, allociblk[NIADDR + 1];
- *bpp = NULL;
+ vp = ap->a_vp;
+ ip = VTOI(vp);
+ fs = ip->i_fs;
+ lbn = lblkno(fs, ap->a_startoffset);
+ size = blkoff(fs, ap->a_startoffset) + ap->a_size;
+ if (size > fs->fs_bsize)
+ panic("ffs_balloc: blk too big");
+ *ap->a_bpp = NULL;
if (lbn < 0)
return (EFBIG);
- fs = ip->i_fs;
+ cred = ap->a_cred;
+ flags = ap->a_flags;
/*
* If the next write will extend the file into a new block,
@@ -89,6 +105,10 @@ ffs_balloc(ip, lbn, size, cred, bpp, flags)
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],
+ fs->fs_bsize, osize, bp);
ip->i_size = smalllblktosize(fs, nb + 1);
ip->i_db[nb] = dbtofsb(fs, bp->b_blkno);
ip->i_flag |= IN_CHANGE | IN_UPDATE;
@@ -110,7 +130,7 @@ ffs_balloc(ip, lbn, size, cred, bpp, flags)
return (error);
}
bp->b_blkno = fsbtodb(fs, nb);
- *bpp = bp;
+ *ap->a_bpp = bp;
return (0);
}
if (nb != 0) {
@@ -132,6 +152,10 @@ ffs_balloc(ip, lbn, size, cred, bpp, flags)
&ip->i_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))
@@ -147,10 +171,13 @@ ffs_balloc(ip, lbn, size, cred, bpp, flags)
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_db[lbn] = dbtofsb(fs, bp->b_blkno);
ip->i_flag |= IN_CHANGE | IN_UPDATE;
- *bpp = bp;
+ *ap->a_bpp = bp;
return (0);
}
/*
@@ -180,12 +207,18 @@ ffs_balloc(ip, lbn, size, cred, bpp, flags)
bp = getblk(vp, indirs[1].in_lbn, fs->fs_bsize, 0, 0);
bp->b_blkno = fsbtodb(fs, nb);
vfs_bio_clrbuf(bp);
- /*
- * Write synchronously so that indirect blocks
- * never point at garbage.
- */
- if (error = bwrite(bp))
- goto fail;
+ 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 (error = bwrite(bp))
+ goto fail;
+ }
allocib = &ip->i_ib[indirs[0].in_off];
*allocib = nb;
ip->i_flag |= IN_CHANGE | IN_UPDATE;
@@ -221,13 +254,19 @@ ffs_balloc(ip, lbn, size, cred, bpp, flags)
nbp = getblk(vp, indirs[i].in_lbn, fs->fs_bsize, 0, 0);
nbp->b_blkno = fsbtodb(fs, nb);
vfs_bio_clrbuf(nbp);
- /*
- * Write synchronously so that indirect blocks
- * never point at garbage.
- */
- if (error = bwrite(nbp)) {
- brelse(bp);
- goto fail;
+ 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)) {
+ brelse(bp);
+ goto fail;
+ }
}
bap[indirs[i - 1].in_off] = nb;
/*
@@ -259,6 +298,9 @@ ffs_balloc(ip, lbn, size, cred, bpp, flags)
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
@@ -271,7 +313,7 @@ ffs_balloc(ip, lbn, size, cred, bpp, flags)
bp->b_flags |= B_CLUSTEROK;
bdwrite(bp);
}
- *bpp = nbp;
+ *ap->a_bpp = nbp;
return (0);
}
brelse(bp);
@@ -285,7 +327,7 @@ ffs_balloc(ip, lbn, size, cred, bpp, flags)
nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0);
nbp->b_blkno = fsbtodb(fs, nb);
}
- *bpp = nbp;
+ *ap->a_bpp = nbp;
return (0);
fail:
/*
diff --git a/sys/ufs/ffs/ffs_extern.h b/sys/ufs/ffs/ffs_extern.h
index dad97d3..90cb38c 100644
--- a/sys/ufs/ffs/ffs_extern.h
+++ b/sys/ufs/ffs/ffs_extern.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ffs_extern.h 8.6 (Berkeley) 3/30/95
- * $Id: ffs_extern.h,v 1.21 1997/11/22 08:35:45 bde Exp $
+ * $Id: ffs_extern.h,v 1.22 1998/02/03 21:52:00 bde Exp $
*/
#ifndef _UFS_FFS_EXTERN_H
@@ -68,8 +68,7 @@ struct vop_reallocblks_args;
int ffs_alloc __P((struct inode *,
ufs_daddr_t, ufs_daddr_t, int, struct ucred *, ufs_daddr_t *));
-int ffs_balloc __P((struct inode *,
- ufs_daddr_t, int, struct ucred *, struct buf **, int));
+int ffs_balloc __P((struct vop_balloc_args *));
int ffs_blkatoff __P((struct vnode *, off_t, char **, struct buf **));
void ffs_blkfree __P((struct inode *, ufs_daddr_t, long));
ufs_daddr_t ffs_blkpref __P((struct inode *, ufs_daddr_t, int, ufs_daddr_t *));
@@ -79,7 +78,9 @@ int ffs_fhtovp __P((struct mount *, struct fid *, struct sockaddr *,
struct vnode **, int *, struct ucred **));
int ffs_flushfiles __P((struct mount *, int, struct proc *));
void ffs_fragacct __P((struct fs *, int, int32_t [], int));
+int ffs_freefile __P(( struct vnode *, ino_t, int ));
int ffs_isblock __P((struct fs *, u_char *, ufs_daddr_t));
+int ffs_isfreeblock __P((struct fs *, unsigned char *, ufs_daddr_t));
int ffs_mountfs __P((struct vnode *, struct mount *, struct proc *,
struct malloc_type *));
int ffs_mountroot __P((void));
@@ -102,4 +103,31 @@ extern vop_t **ffs_vnodeop_p;
extern vop_t **ffs_specop_p;
extern vop_t **ffs_fifoop_p;
+/*
+ * Soft update function prototypes.
+ */
+void softdep_initialize __P((void));
+int softdep_process_worklist __P((struct mount *));
+int softdep_mount __P((struct vnode *, struct mount *, struct fs *,
+ struct ucred *));
+int softdep_flushfiles __P((struct mount *, int, struct proc *));
+void softdep_update_inodeblock __P((struct inode *, struct buf *, int));
+void softdep_load_inodeblock __P((struct inode *));
+int softdep_fsync __P((struct vnode *));
+void softdep_freefile __P((struct vnode *, ino_t, int));
+void softdep_setup_freeblocks __P((struct inode *, off_t));
+void softdep_deallocate_dependencies __P((struct buf *));
+void softdep_setup_inomapdep __P((struct buf *, struct inode *, ino_t));
+void softdep_setup_blkmapdep __P((struct buf *, struct fs *, ufs_daddr_t));
+void softdep_setup_allocdirect __P((struct inode *, ufs_lbn_t, ufs_daddr_t,
+ ufs_daddr_t, long, long, struct buf *));
+void softdep_setup_allocindir_meta __P((struct buf *, struct inode *,
+ struct buf *, int, ufs_daddr_t));
+void softdep_setup_allocindir_page __P((struct inode *, ufs_lbn_t,
+ struct buf *, int, ufs_daddr_t, ufs_daddr_t, struct buf *));
+void softdep_disk_io_initiation __P((struct buf *));
+void softdep_disk_write_complete __P((struct buf *));
+int softdep_sync_metadata __P((struct vop_fsync_args *));
+
#endif /* !_UFS_FFS_EXTERN_H */
+
diff --git a/sys/ufs/ffs/ffs_inode.c b/sys/ufs/ffs/ffs_inode.c
index cf1c043..d1364a1 100644
--- a/sys/ufs/ffs/ffs_inode.c
+++ b/sys/ufs/ffs/ffs_inode.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ffs_inode.c 8.13 (Berkeley) 4/21/95
- * $Id: ffs_inode.c,v 1.34 1998/02/06 12:14:14 eivind Exp $
+ * $Id: ffs_inode.c,v 1.35 1998/03/07 21:36:33 dyson Exp $
*/
#include "opt_quota.h"
@@ -87,8 +87,9 @@ ffs_update(vp, access, modify, waitfor)
~(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE);
return (0);
}
- if ((ip->i_flag &
- (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0)
+ if (((ip->i_flag &
+ (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0) &&
+ (waitfor != MNT_WAIT))
return (0);
/*
* Use a copy of the current time to get consistent timestamps
@@ -129,11 +130,15 @@ ffs_update(vp, access, modify, waitfor)
brelse(bp);
return (error);
}
+ if (DOINGSOFTDEP(vp))
+ 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 (waitfor && (vp->v_mount->mnt_flag & MNT_ASYNC) == 0)
+ if (waitfor && (vp->v_mount->mnt_flag & MNT_ASYNC) == 0) {
return (bwrite(bp));
- else {
+ } else {
if (bp->b_bufsize == fs->fs_bsize)
bp->b_flags |= B_CLUSTEROK;
bdwrite(bp);
@@ -171,6 +176,8 @@ ffs_truncate(vp, length, flags, cred, p)
off_t osize;
oip = VTOI(ovp);
+ if (oip->i_size == length)
+ return (0);
fs = oip->i_fs;
if (length < 0)
return (EINVAL);
@@ -197,6 +204,31 @@ ffs_truncate(vp, length, flags, cred, p)
if (error)
return (error);
#endif
+ ovp->v_lasta = ovp->v_clen = ovp->v_cstart = ovp->v_lastw = 0;
+ if (DOINGSOFTDEP(ovp)) {
+ if (length > 0) {
+ /*
+ * If a file is only partially truncated, then
+ * we have to clean up the data structures
+ * describing the allocation past the truncation
+ * point. Finding and deallocating those structures
+ * is a lot of work. Since partial truncation occurs
+ * rarely, we solve the problem by syncing the file
+ * so that it will have no data structures left.
+ */
+ if ((error = VOP_FSYNC(ovp, cred, MNT_WAIT,
+ p)) != 0)
+ return (error);
+ } else {
+#ifdef QUOTA
+ (void) chkdq(oip, -oip->i_blocks, NOCRED, 0);
+#endif
+ softdep_setup_freeblocks(oip, length);
+ (void) vinvalbuf(ovp, 0, cred, p, 0, 0);
+ oip->i_flag |= IN_CHANGE | IN_UPDATE;
+ return (ffs_update(ovp, &tv, &tv, 0));
+ }
+ }
osize = oip->i_size;
/*
* Lengthen the size of the file. We must ensure that the
@@ -205,13 +237,15 @@ ffs_truncate(vp, length, flags, cred, p)
*/
if (osize < length) {
vnode_pager_setsize(ovp, length);
+#if 0
offset = blkoff(fs, length - 1);
lbn = lblkno(fs, length - 1);
+#endif
aflags = B_CLRBUF;
if (flags & IO_SYNC)
aflags |= B_SYNC;
- error = ffs_balloc(oip, lbn, offset + 1, cred,
- &bp, aflags);
+ error = VOP_BALLOC(ovp, length - 1, 1,
+ cred, aflags, &bp);
if (error)
return (error);
oip->i_size = length;
@@ -241,9 +275,13 @@ ffs_truncate(vp, length, flags, cred, p)
aflags = B_CLRBUF;
if (flags & IO_SYNC)
aflags |= B_SYNC;
- error = ffs_balloc(oip, lbn, offset, cred, &bp, aflags);
- if (error)
+ error = VOP_BALLOC(ovp, length - 1, 1, cred, aflags, &bp);
+ if (error) {
+#if 0 /* kirk's version had this */
+ vnode_pager_setsize(ovp, (u_long)osize);
+#endif
return (error);
+ }
oip->i_size = length;
size = blksize(fs, oip, lbn);
bzero((char *)bp->b_data + offset, (u_int)(size - offset));
diff --git a/sys/ufs/ffs/ffs_subr.c b/sys/ufs/ffs/ffs_subr.c
index 601a4cf..7d7de14 100644
--- a/sys/ufs/ffs/ffs_subr.c
+++ b/sys/ufs/ffs/ffs_subr.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ffs_subr.c 8.5 (Berkeley) 3/21/95
- * $Id: ffs_subr.c,v 1.18 1998/02/06 12:14:14 eivind Exp $
+ * $Id: ffs_subr.c,v 1.19 1998/02/13 00:20:36 bde Exp $
*/
#include <sys/param.h>
@@ -191,6 +191,30 @@ ffs_isblock(fs, cp, h)
}
/*
+ * check if a block is free
+ */
+int
+ffs_isfreeblock(fs, cp, h)
+ struct fs *fs;
+ unsigned char *cp;
+ ufs_daddr_t h;
+{
+
+ switch ((int)fs->fs_frag) {
+ case 8:
+ return (cp[h] == 0);
+ case 4:
+ return ((cp[h >> 1] & (0x0f << ((h & 0x1) << 2))) == 0);
+ case 2:
+ return ((cp[h >> 2] & (0x03 << ((h & 0x3) << 1))) == 0);
+ case 1:
+ return ((cp[h >> 3] & (0x01 << (h & 0x7))) == 0);
+ default:
+ panic("ffs_isfreeblock");
+ }
+}
+
+/*
* take a block out of the map
*/
void
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index edfe0e6..71a451d 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ffs_vfsops.c 8.31 (Berkeley) 5/20/95
- * $Id: ffs_vfsops.c,v 1.74 1998/03/07 14:59:44 bde Exp $
+ * $Id: ffs_vfsops.c,v 1.75 1998/03/07 21:36:36 dyson Exp $
*/
#include "opt_quota.h"
@@ -203,7 +203,11 @@ ffs_mount( mp, path, data, ndp, p)
flags = WRITECLOSE;
if (mp->mnt_flag & MNT_FORCE)
flags |= FORCECLOSE;
- err = ffs_flushfiles(mp, flags, p);
+ if (mp->mnt_flag & MNT_SOFTDEP) {
+ err = softdep_flushfiles(mp, flags, p);
+ } else {
+ err = ffs_flushfiles(mp, flags, p);
+ }
}
if (!err && (mp->mnt_flag & MNT_RELOAD))
err = ffs_reload(mp, ndp->ni_cnd.cn_cred, p);
@@ -410,7 +414,10 @@ ffs_reload(mp, cred, p)
* Step 1: invalidate all cached meta-data.
*/
devvp = VFSTOUFS(mp)->um_devvp;
- if (vinvalbuf(devvp, 0, cred, p, 0, 0))
+ vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
+ error = vinvalbuf(devvp, 0, cred, p, 0, 0);
+ VOP_UNLOCK(devvp, 0, p);
+ if (error)
panic("ffs_reload: dirty1");
dev = devvp->v_rdev;
@@ -516,6 +523,7 @@ loop:
}
ip->i_din = *((struct dinode *)bp->b_data +
ino_to_fsbo(fs, ip->i_number));
+ ip->i_effnlink = ip->i_nlink;
brelse(bp);
vput(vp);
simple_lock(&mntvnode_slock);
@@ -537,10 +545,12 @@ ffs_mountfs(devvp, mp, p, malloctype)
register struct ufsmount *ump;
struct buf *bp;
register struct fs *fs;
+ struct cg *cgp;
dev_t dev;
struct partinfo dpart;
+ struct csum cstotal;
caddr_t base, space;
- int error, i, blks, size, ronly;
+ int error, i, cyl, blks, size, ronly;
int32_t *lp;
struct ucred *cred;
u_int64_t maxfilesize; /* XXX */
@@ -562,7 +572,10 @@ ffs_mountfs(devvp, mp, p, malloctype)
if (ncount > 1 && devvp != rootvp)
return (EBUSY);
- if (error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0))
+ vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
+ error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0);
+ VOP_UNLOCK(devvp, 0, p);
+ if (error)
return (error);
/*
@@ -674,7 +687,7 @@ ffs_mountfs(devvp, mp, p, malloctype)
ump->um_seqinc = fs->fs_frag;
for (i = 0; i < MAXQUOTAS; i++)
ump->um_quotas[i] = NULLVP;
- devvp->v_specflags |= SI_MOUNTEDON;
+ devvp->v_specmountpoint = mp;
ffs_oldfscompat(fs);
/*
@@ -700,11 +713,17 @@ ffs_mountfs(devvp, mp, p, malloctype)
if (fs->fs_maxfilesize > maxfilesize) /* XXX */
fs->fs_maxfilesize = maxfilesize; /* XXX */
if (ronly == 0) {
+ if ((fs->fs_flags & FS_DOSOFTDEP) &&
+ (error = softdep_mount(devvp, mp, fs, cred)) != 0) {
+ free(base, M_UFSMNT);
+ goto out;
+ }
fs->fs_clean = 0;
(void) ffs_sbupdate(ump, MNT_WAIT);
}
return (0);
out:
+ devvp->v_specmountpoint = NULL;
if (bp)
brelse(bp);
(void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p);
@@ -765,9 +784,13 @@ ffs_unmount(mp, mntflags, p)
if (mntflags & MNT_FORCE) {
flags |= FORCECLOSE;
}
- error = ffs_flushfiles(mp, flags, p);
- if (error)
- return (error);
+ if (mp->mnt_flag & MNT_SOFTDEP) {
+ if ((error = softdep_flushfiles(mp, flags, p)) != 0)
+ return (error);
+ } else {
+ if ((error = ffs_flushfiles(mp, flags, p)) != 0)
+ return (error);
+ }
ump = VFSTOUFS(mp);
fs = ump->um_fs;
if (fs->fs_ronly == 0) {
@@ -778,7 +801,7 @@ ffs_unmount(mp, mntflags, p)
return (error);
}
}
- ump->um_devvp->v_specflags &= ~SI_MOUNTEDON;
+ ump->um_devvp->v_specmountpoint = NULL;
vinvalbuf(ump->um_devvp, V_SAVE, NOCRED, p, 0, 0);
error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE,
@@ -824,7 +847,17 @@ ffs_flushfiles(mp, flags, p)
*/
}
#endif
- error = vflush(mp, NULLVP, flags);
+ /*
+ * Flush all the files.
+ */
+ if ((error = vflush(mp, NULL, flags)) != 0)
+ return (error);
+ /*
+ * Flush filesystem metadata.
+ */
+ vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p);
+ error = VOP_FSYNC(ump->um_devvp, p->p_ucred, MNT_WAIT, p);
+ VOP_UNLOCK(ump->um_devvp, 0, p);
return (error);
}
@@ -903,9 +936,9 @@ loop:
simple_lock(&vp->v_interlock);
nvp = vp->v_mntvnodes.le_next;
ip = VTOI(vp);
- if (((ip->i_flag &
+ if ((vp->v_type == VNON) || ((ip->i_flag &
(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0) &&
- vp->v_dirtyblkhd.lh_first == NULL) {
+ ((vp->v_dirtyblkhd.lh_first == NULL) || (waitfor == MNT_LAZY))) {
simple_unlock(&vp->v_interlock);
continue;
}
@@ -937,21 +970,22 @@ loop:
/*
* Force stale file system control information to be flushed.
*/
- error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p);
- if (error)
- allerror = error;
+ if (waitfor != MNT_LAZY) {
+ if (ump->um_mountp->mnt_flag & MNT_SOFTDEP)
+ waitfor = MNT_NOWAIT;
+ vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p);
+ if ((error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p)) != 0)
+ allerror = error;
+ VOP_UNLOCK(ump->um_devvp, 0, p);
+ }
#ifdef QUOTA
qsync(mp);
#endif
/*
* Write back modified superblock.
*/
- if (fs->fs_fmod != 0) {
- fs->fs_fmod = 0;
- fs->fs_time = time.tv_sec;
- if (error = ffs_sbupdate(ump, waitfor))
- allerror = error;
- }
+ if (fs->fs_fmod != 0 && (error = ffs_sbupdate(ump, waitfor)) != 0)
+ allerror = error;
return (allerror);
}
@@ -1060,6 +1094,10 @@ restart:
return (error);
}
ip->i_din = *((struct dinode *)bp->b_data + ino_to_fsbo(fs, ino));
+ if (DOINGSOFTDEP(vp))
+ softdep_load_inodeblock(ip);
+ else
+ ip->i_effnlink = ip->i_nlink;
bqrelse(bp);
/*
@@ -1157,6 +1195,7 @@ ffs_init(vfsp)
struct vfsconf *vfsp;
{
+ softdep_initialize();
return (ufs_init(vfsp));
}
@@ -1200,6 +1239,8 @@ ffs_sbupdate(mp, waitfor)
if (allerror)
return (allerror);
bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize, 0, 0);
+ fs->fs_fmod = 0;
+ fs->fs_time = time.tv_sec;
bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize);
/* Restore compatibility to old file systems. XXX */
dfs = (struct fs *)bp->b_data; /* XXX */
diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c
index 0210d61..44db8f4 100644
--- a/sys/ufs/ffs/ffs_vnops.c
+++ b/sys/ufs/ffs/ffs_vnops.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ffs_vnops.c 8.15 (Berkeley) 5/14/95
- * $Id: ffs_vnops.c,v 1.42 1998/02/06 12:14:16 eivind Exp $
+ * $Id: ffs_vnops.c,v 1.43 1998/02/26 06:39:38 msmith Exp $
*/
#include <sys/param.h>
@@ -74,6 +74,7 @@ static struct vnodeopv_entry_desc ffs_vnodeop_entries[] = {
{ &vop_getpages_desc, (vop_t *) ffs_getpages },
{ &vop_putpages_desc, (vop_t *) ffs_putpages },
{ &vop_read_desc, (vop_t *) ffs_read },
+ { &vop_balloc_desc, (vop_t *) ffs_balloc },
{ &vop_reallocblks_desc, (vop_t *) ffs_reallocblks },
{ &vop_write_desc, (vop_t *) ffs_write },
{ NULL, NULL }
@@ -120,12 +121,11 @@ ffs_fsync(ap)
struct proc *a_p;
} */ *ap;
{
- register struct vnode *vp = ap->a_vp;
- register struct buf *bp;
+ struct vnode *vp = ap->a_vp;
+ struct buf *bp;
struct timeval tv;
struct buf *nbp;
- int pass;
- int s;
+ int s, error, passes, skipmeta;
daddr_t lbn;
@@ -137,31 +137,45 @@ ffs_fsync(ap)
lbn = lblkno(ip->i_fs, (ip->i_size + ip->i_fs->fs_bsize - 1));
}
- pass = 0;
/*
* Flush all dirty buffers associated with a vnode.
*/
+ passes = NIADDR;
+ skipmeta = 0;
+ if (ap->a_waitfor == MNT_WAIT)
+ skipmeta = 1;
loop:
s = splbio();
+loop2:
for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) {
nbp = bp->b_vnbufs.le_next;
- if ((bp->b_flags & B_BUSY) || (pass == 0 && (bp->b_lblkno < 0)))
+ /*
+ * First time through on a synchronous call,
+ * or if it's already scheduled, skip to the next
+ * buffer
+ */
+ if ((bp->b_flags & B_BUSY) ||
+ ((skipmeta == 1) && (bp->b_lblkno < 0)))
continue;
if ((bp->b_flags & B_DELWRI) == 0)
panic("ffs_fsync: not dirty");
-
- if (((bp->b_vp != vp) || (ap->a_waitfor != MNT_NOWAIT)) ||
- ((vp->v_type != VREG) && (vp->v_type != VBLK))) {
-
+ /*
+ * If data is outstanding to another vnode, or we were
+ * asked to wait for everything, or it's not a file or BDEV,
+ * start the IO on this buffer immediatly.
+ */
+ if (((bp->b_vp != vp) || (ap->a_waitfor == MNT_WAIT)) ||
+ ((vp->v_type != VREG) && (vp->v_type != VBLK))) {
bremfree(bp);
bp->b_flags |= B_BUSY;
splx(s);
/*
- * Wait for I/O associated with indirect blocks to complete,
- * since there is no way to quickly wait for them below.
+ * Wait for I/O associated with indirect blocks to
+ * complete, since there is no way to quickly wait
+ * for them below.
*/
- if ((bp->b_vp == vp) && (ap->a_waitfor == MNT_NOWAIT)) {
+ if ((bp->b_vp == vp) || (ap->a_waitfor != MNT_WAIT)) {
if (bp->b_flags & B_CLUSTEROK) {
bdwrite(bp);
(void) vfs_bio_awrite(bp);
@@ -171,26 +185,30 @@ loop:
} else {
(void) bwrite(bp);
}
-
} else if ((vp->v_type == VREG) && (bp->b_lblkno >= lbn)) {
-
+ /*
+ * If the buffer is for data that has been truncated
+ * off the file, then throw it away.
+ */
bremfree(bp);
bp->b_flags |= B_BUSY | B_INVAL | B_NOCACHE;
brelse(bp);
splx(s);
-
} else {
vfs_bio_awrite(bp);
splx(s);
}
goto loop;
}
- splx(s);
-
- if (pass == 0) {
- pass = 1;
- goto loop;
+ /*
+ * If we were asked to do this synchronously, then go back for
+ * another pass, this time doing the metadata.
+ */
+ if (skipmeta) {
+ skipmeta = 0;
+ goto loop2; /* stay within the splbio() */
}
+ splx(s);
if (ap->a_waitfor == MNT_WAIT) {
s = splbio();
@@ -198,15 +216,38 @@ loop:
vp->v_flag |= VBWAIT;
(void) tsleep((caddr_t)&vp->v_numoutput, PRIBIO + 1, "ffsfsn", 0);
}
+ /*
+ * Ensure that any filesystem metatdata associated
+ * with the vnode has been written.
+ */
splx(s);
-#ifdef DIAGNOSTIC
+ if ((error = softdep_sync_metadata(ap)) != 0)
+ return (error);
+ s = splbio();
if (vp->v_dirtyblkhd.lh_first) {
- vprint("ffs_fsync: dirty", vp);
- goto loop;
- }
+ /*
+ * Block devices associated with filesystems may
+ * have new I/O requests posted for them even if
+ * the vnode is locked, so no amount of trying will
+ * get them clean. Thus we give block devices a
+ * good effort, then just give up. For all other file
+ * types, go around and try again until it is clean.
+ */
+ if (passes > 0) {
+ passes -= 1;
+ goto loop2;
+ }
+#ifdef DIAGNOSTIC
+ if (vp->v_type != VBLK)
+ vprint("ffs_fsync: dirty", vp);
#endif
+ }
}
-
gettime(&tv);
- return (UFS_UPDATE(ap->a_vp, &tv, &tv, ap->a_waitfor == MNT_WAIT));
+ error = UFS_UPDATE(ap->a_vp, &tv, &tv, (ap->a_waitfor == MNT_WAIT));
+ if (error)
+ return (error);
+ if (DOINGSOFTDEP(vp) && ap->a_waitfor == MNT_WAIT)
+ error = softdep_fsync(vp);
+ return (error);
}
diff --git a/sys/ufs/ffs/fs.h b/sys/ufs/ffs/fs.h
index 98a9b06..9f99731 100644
--- a/sys/ufs/ffs/fs.h
+++ b/sys/ufs/ffs/fs.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)fs.h 8.13 (Berkeley) 3/21/95
- * $Id: fs.h,v 1.11 1997/03/23 20:08:22 guido Exp $
+ * $Id: fs.h,v 1.12 1997/03/24 03:19:37 bde Exp $
*/
#ifndef _UFS_FFS_FS_H_
@@ -222,7 +222,7 @@ struct fs {
int8_t fs_fmod; /* super block modified flag */
int8_t fs_clean; /* file system is clean flag */
int8_t fs_ronly; /* mounted read-only flag */
- int8_t fs_flags; /* currently unused flag */
+ int8_t fs_flags; /* see FS_ flags below */
u_char fs_fsmnt[MAXMNTLEN]; /* name mounted on */
/* these fields retain the current block allocation info */
int32_t fs_cgrotor; /* last cg searched */
@@ -254,6 +254,7 @@ struct fs {
#define FS_OKAY 0x7c269d38 /* superblock checksum */
#define FS_42INODEFMT -1 /* 4.2BSD inode format */
#define FS_44INODEFMT 2 /* 4.4BSD inode format */
+
/*
* Preference for optimization.
*/
@@ -261,6 +262,12 @@ struct fs {
#define FS_OPTSPACE 1 /* minimize disk fragmentation */
/*
+ * Filesystem flags.
+ */
+#define FS_UNCLEAN 0x01 /* filesystem not clean at mount */
+#define FS_DOSOFTDEP 0x02 /* filesystem using soft dependencies */
+
+/*
* Rotational layout table format types
*/
#define FS_42POSTBLFMT -1 /* 4.2BSD rotational table format */
@@ -485,6 +492,11 @@ struct ocg {
(((lbn) >= NDADDR || (dip)->di_size >= 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 \
+ : (fragroundup(fs, blkoff(fs, (size)))))
+
/*
* Number of disk sectors per block/fragment; assumes DEV_BSIZE byte
OpenPOWER on IntegriCloud