aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Elischer <julian@FreeBSD.org>1998-05-19 23:07:25 +0000
committerJulian Elischer <julian@FreeBSD.org>1998-05-19 23:07:25 +0000
commit25db4e8a667ad9bdce0aaa23abf1512c99f19887 (patch)
tree9fed6360c01da53d94a157e41f90046bc595f1c9
parent46e752be057fa715c2251113b9f118dfba903634 (diff)
downloadsrc-25db4e8a667ad9bdce0aaa23abf1512c99f19887.tar.gz
src-25db4e8a667ad9bdce0aaa23abf1512c99f19887.zip
Bring up-to-date with Whistle's current version
Includes some debugging code.
Notes
Notes: svn path=/head/; revision=36234
-rw-r--r--contrib/sys/softupdates/ffs_softdep.c88
-rw-r--r--contrib/sys/softupdates/softdep.h3
-rw-r--r--sys/contrib/softupdates/ffs_softdep.c88
-rw-r--r--sys/contrib/softupdates/softdep.h3
-rw-r--r--sys/ufs/ffs/ffs_softdep.c88
-rw-r--r--sys/ufs/ffs/softdep.h3
6 files changed, 255 insertions, 18 deletions
diff --git a/contrib/sys/softupdates/ffs_softdep.c b/contrib/sys/softupdates/ffs_softdep.c
index 25acbd2dae95..4123e33f6618 100644
--- a/contrib/sys/softupdates/ffs_softdep.c
+++ b/contrib/sys/softupdates/ffs_softdep.c
@@ -54,6 +54,7 @@
* SUCH DAMAGE.
*
* @(#)ffs_softdep.c 9.23 (McKusick) 2/20/98
+ * $Id:$
*/
/*
@@ -65,6 +66,7 @@
#ifndef DEBUG
#define DEBUG
#endif
+#define NEWINODE 0x4000
#include <sys/param.h>
#include <sys/buf.h>
@@ -954,6 +956,7 @@ softdep_mount(devvp, mp, fs, cred)
struct buf *bp;
int error, cyl;
+ mp->mnt_flag &= ~MNT_ASYNC;
mp->mnt_flag |= MNT_SOFTDEP;
/*
* When doing soft updates, the counters in the
@@ -1040,6 +1043,7 @@ softdep_setup_inomapdep(bp, ip, newinum)
panic("softdep_setup_inomapdep: found inode");
inodedep->id_buf = bp;
inodedep->id_state &= ~DEPCOMPLETE;
+inodedep->id_state |= NEWINODE;
bmsafemap = bmsafemap_lookup(bp);
LIST_INSERT_HEAD(&bmsafemap->sm_inodedephd, inodedep, id_deps);
FREE_LOCK(&lk);
@@ -1528,11 +1532,20 @@ setup_allocindir_phase2(bp, ip, aip)
newindirdep->ir_state = ATTACHED;
LIST_INIT(&newindirdep->ir_deplisthd);
LIST_INIT(&newindirdep->ir_donehd);
- newindirdep->ir_saveddata = (ufs_daddr_t *)bp->b_data;
+#ifdef __FreeBSD__
+ if (bp->b_blkno == bp->b_lblkno) {
+#if 0 /* we know this happens.. research suggested.. */
+ printf("setup_allocindir_phase2: need bmap, blk %d\n",
+ bp->b_lblkno);
+#endif
+ VOP_BMAP(bp->b_vp, bp->b_lblkno, NULL, &bp->b_blkno,
+ NULL, NULL);
+ }
+#endif /* __FreeBSD__ */
newindirdep->ir_savebp =
getblk(ip->i_devvp, bp->b_blkno, bp->b_bcount, 0, 0);
- bcopy((caddr_t)newindirdep->ir_saveddata,
- newindirdep->ir_savebp->b_data, bp->b_bcount);
+ bp->b_flags |= B_XXX;
+ bcopy(bp->b_data, newindirdep->ir_savebp->b_data, bp->b_bcount);
}
}
@@ -1716,6 +1729,8 @@ deallocate_dependencies(bp, inodedep)
panic("deallocate_dependencies: not indir");
bcopy(bp->b_data, indirdep->ir_savebp->b_data,
bp->b_bcount);
+if ((indirdep->ir_savebp->b_flags & B_BUSY) == 0 || (bp->b_flags & B_BUSY) == 0)
+panic("deallocate_dependencies: buffer unlocked");
WORKLIST_REMOVE(wk);
WORKLIST_INSERT(&indirdep->ir_savebp->b_dep, wk);
continue;
@@ -1980,6 +1995,7 @@ indir_trunc(ip, dbn, level, lbn, countp)
struct indirdep *indirdep;
int i, lbnadd, nblocks;
int error, allerror = 0;
+int debug;
fs = ip->i_fs;
lbnadd = 1;
@@ -2000,6 +2016,7 @@ indir_trunc(ip, dbn, level, lbn, countp)
ACQUIRE_LOCK(&lk);
if ((bp = incore(ip->i_devvp, dbn)) != NULL &&
(wk = LIST_FIRST(&bp->b_dep)) != NULL) {
+debug = 1;
if (wk->wk_type != D_INDIRDEP ||
(indirdep = WK_INDIRDEP(wk))->ir_savebp != bp ||
(indirdep->ir_state & GOINGAWAY) == 0)
@@ -2010,11 +2027,14 @@ indir_trunc(ip, dbn, level, lbn, countp)
panic("indir_trunc: dangling dep");
FREE_LOCK(&lk);
} else {
+debug = 2;
FREE_LOCK(&lk);
error = bread(ip->i_devvp, dbn, (int)fs->fs_bsize, NOCRED, &bp);
if (error)
return (error);
}
+if ((bp->b_flags & B_BUSY) == 0)
+panic("indir_trunc: unlocked buf");
/*
* Recursively free indirect blocks.
*/
@@ -2031,7 +2051,10 @@ indir_trunc(ip, dbn, level, lbn, countp)
ffs_blkfree(ip, nb, fs->fs_bsize);
*countp += nblocks;
}
+if (debug == i)
+printf("debug %d\n", debug);
bp->b_flags |= B_INVAL;
+ bp->b_flags &= ~B_XXX;
brelse(bp);
return (allerror);
}
@@ -2615,6 +2638,8 @@ softdep_disk_io_initiation(bp)
* dependency can be freed.
*/
if (LIST_FIRST(&indirdep->ir_deplisthd) == NULL) {
+ indirdep->ir_savebp->b_flags &= ~B_XXX;
+ indirdep->ir_savebp->b_flags |= B_INVAL;
brelse(indirdep->ir_savebp);
/* inline expand WORKLIST_REMOVE(wk); */
wk->wk_state &= ~ONWORKLIST;
@@ -2628,7 +2653,11 @@ softdep_disk_io_initiation(bp)
ACQUIRE_LOCK(&lk);
indirdep->ir_state &= ~ATTACHED;
indirdep->ir_state |= UNDONE;
- bp->b_data = indirdep->ir_savebp->b_data;
+ MALLOC(indirdep->ir_saveddata, caddr_t, bp->b_bcount,
+ M_INDIRDEP, M_WAITOK);
+ bcopy(bp->b_data, indirdep->ir_saveddata, bp->b_bcount);
+ bcopy(indirdep->ir_savebp->b_data, bp->b_data,
+ bp->b_bcount);
FREE_LOCK(&lk);
continue;
@@ -2646,6 +2675,30 @@ softdep_disk_io_initiation(bp)
}
}
+void
+scan_page(bp)
+ struct buf *bp;
+{
+ struct inodedep *inodedep;
+ struct direct *dp;
+ struct fs *fs;
+ caddr_t cp;
+
+ fs = VTOI(bp->b_vp)->i_fs;
+ for (cp = bp->b_data; cp < &bp->b_data[bp->b_bcount];
+ cp += dp->d_reclen) {
+ dp = (struct direct *)cp;
+ if (dp->d_reclen <= 0)
+ break;
+ if (dp->d_ino == 0)
+ continue;
+ if (inodedep_lookup(fs, dp->d_ino, 0, &inodedep) == 0)
+ continue;
+ if (inodedep->id_state & NEWINODE)
+ panic("scan_page: unallocated inode");
+ }
+}
+
/*
* Called from within the procedure above to deal with unsatisfied
* allocation dependencies in a directory. The buffer must be locked,
@@ -2689,6 +2742,7 @@ initiate_write_filepage(pagedep, bp)
dap->da_state |= UNDONE;
}
}
+/*scan_page(bp);*/
FREE_LOCK(&lk);
}
@@ -2913,7 +2967,9 @@ softdep_disk_write_complete(bp)
indirdep = WK_INDIRDEP(wk);
if (indirdep->ir_state & GOINGAWAY)
panic("disk_write_complete: indirdep gone");
- bp->b_data = (caddr_t)indirdep->ir_saveddata;
+ bcopy(indirdep->ir_saveddata, bp->b_data, bp->b_bcount);
+ FREE(indirdep->ir_saveddata, M_INDIRDEP);
+ indirdep->ir_saveddata = 0;
indirdep->ir_state &= ~UNDONE;
indirdep->ir_state |= ATTACHED;
while ((aip = LIST_FIRST(&indirdep->ir_donehd)) != 0) {
@@ -3081,6 +3137,7 @@ handle_written_inodeblock(inodedep, bp)
bdirty(bp);
return (1);
}
+inodedep->id_state &= ~NEWINODE;
/*
* Roll forward anything that had to be rolled back before
* the inode could be updated.
@@ -3201,6 +3258,8 @@ diradd_inode_written(dap, inodedep)
{
struct pagedep *pagedep;
+if (inodedep->id_state & NEWINODE)
+panic("diradd_inode_written: unallocated inode");
dap->da_state |= COMPLETE;
if ((dap->da_state & ALLCOMPLETE) == ALLCOMPLETE) {
if (dap->da_state & DIRCHG)
@@ -3570,7 +3629,11 @@ softdep_fsync(vp)
}
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
if (flushparent) {
+#ifndef __FreeBSD__
tv = time;
+#else
+ getmicrotime(&tv);
+#endif /* __FreeBSD__ */
if (error = UFS_UPDATE(pvp, &tv, &tv, MNT_WAIT)) {
vput(pvp);
return (error);
@@ -3654,6 +3717,13 @@ softdep_sync_metadata(ap)
waitfor = MNT_NOWAIT;
top:
if (getdirtybuf(&LIST_FIRST(&vp->v_dirtyblkhd), MNT_WAIT) == 0) {
+ while (vp->v_numoutput) {
+ vp->v_flag |= VBWAIT;
+ FREE_LOCK_INTERLOCKED(&lk);
+ tsleep((caddr_t)&vp->v_numoutput, PRIBIO + 1,
+ "sdsynm", 0);
+ ACQUIRE_LOCK_INTERLOCKED(&lk);
+ }
FREE_LOCK(&lk);
return (0);
}
@@ -3931,7 +4001,11 @@ flush_pagedep_deps(pvp, mp, diraddhdp)
* has a MKDIR_PARENT dependency.
*/
if (dap->da_state & MKDIR_PARENT) {
+#ifndef __FreeBSD__
tv = time;
+#else
+ getmicrotime(&tv);
+#endif /* __FreeBSD__ */
FREE_LOCK(&lk);
if (error = UFS_UPDATE(pvp, &tv, &tv, MNT_WAIT))
break;
@@ -4015,7 +4089,11 @@ flush_pagedep_deps(pvp, mp, diraddhdp)
}
FREE_LOCK(&lk);
}
+#ifndef __FreeBSD__
tv = time;
+#else
+ getmicrotime(&tv);
+#endif /* __FreeBSD__ */
error = UFS_UPDATE(vp, &tv, &tv, MNT_WAIT);
vput(vp);
if (error)
diff --git a/contrib/sys/softupdates/softdep.h b/contrib/sys/softupdates/softdep.h
index 3435f6304173..71bb7fa4f706 100644
--- a/contrib/sys/softupdates/softdep.h
+++ b/contrib/sys/softupdates/softdep.h
@@ -53,6 +53,7 @@
* SUCH DAMAGE.
*
* @(#)softdep.h 9.5 (McKusick) 2/11/98
+ * $Id:$
*/
#include <sys/queue.h>
@@ -352,7 +353,7 @@ struct allocdirect {
struct indirdep {
struct worklist ir_list; /* buffer holding indirect block */
# define ir_state ir_list.wk_state /* indirect block pointer state */
- ufs_daddr_t *ir_saveddata; /* buffer cache contents */
+ caddr_t ir_saveddata; /* buffer cache contents */
struct buf *ir_savebp; /* buffer holding safe copy */
struct allocindirhd ir_donehd; /* done waiting to update safecopy */
struct allocindirhd ir_deplisthd; /* allocindir deps for this block */
diff --git a/sys/contrib/softupdates/ffs_softdep.c b/sys/contrib/softupdates/ffs_softdep.c
index 25acbd2dae95..4123e33f6618 100644
--- a/sys/contrib/softupdates/ffs_softdep.c
+++ b/sys/contrib/softupdates/ffs_softdep.c
@@ -54,6 +54,7 @@
* SUCH DAMAGE.
*
* @(#)ffs_softdep.c 9.23 (McKusick) 2/20/98
+ * $Id:$
*/
/*
@@ -65,6 +66,7 @@
#ifndef DEBUG
#define DEBUG
#endif
+#define NEWINODE 0x4000
#include <sys/param.h>
#include <sys/buf.h>
@@ -954,6 +956,7 @@ softdep_mount(devvp, mp, fs, cred)
struct buf *bp;
int error, cyl;
+ mp->mnt_flag &= ~MNT_ASYNC;
mp->mnt_flag |= MNT_SOFTDEP;
/*
* When doing soft updates, the counters in the
@@ -1040,6 +1043,7 @@ softdep_setup_inomapdep(bp, ip, newinum)
panic("softdep_setup_inomapdep: found inode");
inodedep->id_buf = bp;
inodedep->id_state &= ~DEPCOMPLETE;
+inodedep->id_state |= NEWINODE;
bmsafemap = bmsafemap_lookup(bp);
LIST_INSERT_HEAD(&bmsafemap->sm_inodedephd, inodedep, id_deps);
FREE_LOCK(&lk);
@@ -1528,11 +1532,20 @@ setup_allocindir_phase2(bp, ip, aip)
newindirdep->ir_state = ATTACHED;
LIST_INIT(&newindirdep->ir_deplisthd);
LIST_INIT(&newindirdep->ir_donehd);
- newindirdep->ir_saveddata = (ufs_daddr_t *)bp->b_data;
+#ifdef __FreeBSD__
+ if (bp->b_blkno == bp->b_lblkno) {
+#if 0 /* we know this happens.. research suggested.. */
+ printf("setup_allocindir_phase2: need bmap, blk %d\n",
+ bp->b_lblkno);
+#endif
+ VOP_BMAP(bp->b_vp, bp->b_lblkno, NULL, &bp->b_blkno,
+ NULL, NULL);
+ }
+#endif /* __FreeBSD__ */
newindirdep->ir_savebp =
getblk(ip->i_devvp, bp->b_blkno, bp->b_bcount, 0, 0);
- bcopy((caddr_t)newindirdep->ir_saveddata,
- newindirdep->ir_savebp->b_data, bp->b_bcount);
+ bp->b_flags |= B_XXX;
+ bcopy(bp->b_data, newindirdep->ir_savebp->b_data, bp->b_bcount);
}
}
@@ -1716,6 +1729,8 @@ deallocate_dependencies(bp, inodedep)
panic("deallocate_dependencies: not indir");
bcopy(bp->b_data, indirdep->ir_savebp->b_data,
bp->b_bcount);
+if ((indirdep->ir_savebp->b_flags & B_BUSY) == 0 || (bp->b_flags & B_BUSY) == 0)
+panic("deallocate_dependencies: buffer unlocked");
WORKLIST_REMOVE(wk);
WORKLIST_INSERT(&indirdep->ir_savebp->b_dep, wk);
continue;
@@ -1980,6 +1995,7 @@ indir_trunc(ip, dbn, level, lbn, countp)
struct indirdep *indirdep;
int i, lbnadd, nblocks;
int error, allerror = 0;
+int debug;
fs = ip->i_fs;
lbnadd = 1;
@@ -2000,6 +2016,7 @@ indir_trunc(ip, dbn, level, lbn, countp)
ACQUIRE_LOCK(&lk);
if ((bp = incore(ip->i_devvp, dbn)) != NULL &&
(wk = LIST_FIRST(&bp->b_dep)) != NULL) {
+debug = 1;
if (wk->wk_type != D_INDIRDEP ||
(indirdep = WK_INDIRDEP(wk))->ir_savebp != bp ||
(indirdep->ir_state & GOINGAWAY) == 0)
@@ -2010,11 +2027,14 @@ indir_trunc(ip, dbn, level, lbn, countp)
panic("indir_trunc: dangling dep");
FREE_LOCK(&lk);
} else {
+debug = 2;
FREE_LOCK(&lk);
error = bread(ip->i_devvp, dbn, (int)fs->fs_bsize, NOCRED, &bp);
if (error)
return (error);
}
+if ((bp->b_flags & B_BUSY) == 0)
+panic("indir_trunc: unlocked buf");
/*
* Recursively free indirect blocks.
*/
@@ -2031,7 +2051,10 @@ indir_trunc(ip, dbn, level, lbn, countp)
ffs_blkfree(ip, nb, fs->fs_bsize);
*countp += nblocks;
}
+if (debug == i)
+printf("debug %d\n", debug);
bp->b_flags |= B_INVAL;
+ bp->b_flags &= ~B_XXX;
brelse(bp);
return (allerror);
}
@@ -2615,6 +2638,8 @@ softdep_disk_io_initiation(bp)
* dependency can be freed.
*/
if (LIST_FIRST(&indirdep->ir_deplisthd) == NULL) {
+ indirdep->ir_savebp->b_flags &= ~B_XXX;
+ indirdep->ir_savebp->b_flags |= B_INVAL;
brelse(indirdep->ir_savebp);
/* inline expand WORKLIST_REMOVE(wk); */
wk->wk_state &= ~ONWORKLIST;
@@ -2628,7 +2653,11 @@ softdep_disk_io_initiation(bp)
ACQUIRE_LOCK(&lk);
indirdep->ir_state &= ~ATTACHED;
indirdep->ir_state |= UNDONE;
- bp->b_data = indirdep->ir_savebp->b_data;
+ MALLOC(indirdep->ir_saveddata, caddr_t, bp->b_bcount,
+ M_INDIRDEP, M_WAITOK);
+ bcopy(bp->b_data, indirdep->ir_saveddata, bp->b_bcount);
+ bcopy(indirdep->ir_savebp->b_data, bp->b_data,
+ bp->b_bcount);
FREE_LOCK(&lk);
continue;
@@ -2646,6 +2675,30 @@ softdep_disk_io_initiation(bp)
}
}
+void
+scan_page(bp)
+ struct buf *bp;
+{
+ struct inodedep *inodedep;
+ struct direct *dp;
+ struct fs *fs;
+ caddr_t cp;
+
+ fs = VTOI(bp->b_vp)->i_fs;
+ for (cp = bp->b_data; cp < &bp->b_data[bp->b_bcount];
+ cp += dp->d_reclen) {
+ dp = (struct direct *)cp;
+ if (dp->d_reclen <= 0)
+ break;
+ if (dp->d_ino == 0)
+ continue;
+ if (inodedep_lookup(fs, dp->d_ino, 0, &inodedep) == 0)
+ continue;
+ if (inodedep->id_state & NEWINODE)
+ panic("scan_page: unallocated inode");
+ }
+}
+
/*
* Called from within the procedure above to deal with unsatisfied
* allocation dependencies in a directory. The buffer must be locked,
@@ -2689,6 +2742,7 @@ initiate_write_filepage(pagedep, bp)
dap->da_state |= UNDONE;
}
}
+/*scan_page(bp);*/
FREE_LOCK(&lk);
}
@@ -2913,7 +2967,9 @@ softdep_disk_write_complete(bp)
indirdep = WK_INDIRDEP(wk);
if (indirdep->ir_state & GOINGAWAY)
panic("disk_write_complete: indirdep gone");
- bp->b_data = (caddr_t)indirdep->ir_saveddata;
+ bcopy(indirdep->ir_saveddata, bp->b_data, bp->b_bcount);
+ FREE(indirdep->ir_saveddata, M_INDIRDEP);
+ indirdep->ir_saveddata = 0;
indirdep->ir_state &= ~UNDONE;
indirdep->ir_state |= ATTACHED;
while ((aip = LIST_FIRST(&indirdep->ir_donehd)) != 0) {
@@ -3081,6 +3137,7 @@ handle_written_inodeblock(inodedep, bp)
bdirty(bp);
return (1);
}
+inodedep->id_state &= ~NEWINODE;
/*
* Roll forward anything that had to be rolled back before
* the inode could be updated.
@@ -3201,6 +3258,8 @@ diradd_inode_written(dap, inodedep)
{
struct pagedep *pagedep;
+if (inodedep->id_state & NEWINODE)
+panic("diradd_inode_written: unallocated inode");
dap->da_state |= COMPLETE;
if ((dap->da_state & ALLCOMPLETE) == ALLCOMPLETE) {
if (dap->da_state & DIRCHG)
@@ -3570,7 +3629,11 @@ softdep_fsync(vp)
}
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
if (flushparent) {
+#ifndef __FreeBSD__
tv = time;
+#else
+ getmicrotime(&tv);
+#endif /* __FreeBSD__ */
if (error = UFS_UPDATE(pvp, &tv, &tv, MNT_WAIT)) {
vput(pvp);
return (error);
@@ -3654,6 +3717,13 @@ softdep_sync_metadata(ap)
waitfor = MNT_NOWAIT;
top:
if (getdirtybuf(&LIST_FIRST(&vp->v_dirtyblkhd), MNT_WAIT) == 0) {
+ while (vp->v_numoutput) {
+ vp->v_flag |= VBWAIT;
+ FREE_LOCK_INTERLOCKED(&lk);
+ tsleep((caddr_t)&vp->v_numoutput, PRIBIO + 1,
+ "sdsynm", 0);
+ ACQUIRE_LOCK_INTERLOCKED(&lk);
+ }
FREE_LOCK(&lk);
return (0);
}
@@ -3931,7 +4001,11 @@ flush_pagedep_deps(pvp, mp, diraddhdp)
* has a MKDIR_PARENT dependency.
*/
if (dap->da_state & MKDIR_PARENT) {
+#ifndef __FreeBSD__
tv = time;
+#else
+ getmicrotime(&tv);
+#endif /* __FreeBSD__ */
FREE_LOCK(&lk);
if (error = UFS_UPDATE(pvp, &tv, &tv, MNT_WAIT))
break;
@@ -4015,7 +4089,11 @@ flush_pagedep_deps(pvp, mp, diraddhdp)
}
FREE_LOCK(&lk);
}
+#ifndef __FreeBSD__
tv = time;
+#else
+ getmicrotime(&tv);
+#endif /* __FreeBSD__ */
error = UFS_UPDATE(vp, &tv, &tv, MNT_WAIT);
vput(vp);
if (error)
diff --git a/sys/contrib/softupdates/softdep.h b/sys/contrib/softupdates/softdep.h
index 3435f6304173..71bb7fa4f706 100644
--- a/sys/contrib/softupdates/softdep.h
+++ b/sys/contrib/softupdates/softdep.h
@@ -53,6 +53,7 @@
* SUCH DAMAGE.
*
* @(#)softdep.h 9.5 (McKusick) 2/11/98
+ * $Id:$
*/
#include <sys/queue.h>
@@ -352,7 +353,7 @@ struct allocdirect {
struct indirdep {
struct worklist ir_list; /* buffer holding indirect block */
# define ir_state ir_list.wk_state /* indirect block pointer state */
- ufs_daddr_t *ir_saveddata; /* buffer cache contents */
+ caddr_t ir_saveddata; /* buffer cache contents */
struct buf *ir_savebp; /* buffer holding safe copy */
struct allocindirhd ir_donehd; /* done waiting to update safecopy */
struct allocindirhd ir_deplisthd; /* allocindir deps for this block */
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index 25acbd2dae95..4123e33f6618 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -54,6 +54,7 @@
* SUCH DAMAGE.
*
* @(#)ffs_softdep.c 9.23 (McKusick) 2/20/98
+ * $Id:$
*/
/*
@@ -65,6 +66,7 @@
#ifndef DEBUG
#define DEBUG
#endif
+#define NEWINODE 0x4000
#include <sys/param.h>
#include <sys/buf.h>
@@ -954,6 +956,7 @@ softdep_mount(devvp, mp, fs, cred)
struct buf *bp;
int error, cyl;
+ mp->mnt_flag &= ~MNT_ASYNC;
mp->mnt_flag |= MNT_SOFTDEP;
/*
* When doing soft updates, the counters in the
@@ -1040,6 +1043,7 @@ softdep_setup_inomapdep(bp, ip, newinum)
panic("softdep_setup_inomapdep: found inode");
inodedep->id_buf = bp;
inodedep->id_state &= ~DEPCOMPLETE;
+inodedep->id_state |= NEWINODE;
bmsafemap = bmsafemap_lookup(bp);
LIST_INSERT_HEAD(&bmsafemap->sm_inodedephd, inodedep, id_deps);
FREE_LOCK(&lk);
@@ -1528,11 +1532,20 @@ setup_allocindir_phase2(bp, ip, aip)
newindirdep->ir_state = ATTACHED;
LIST_INIT(&newindirdep->ir_deplisthd);
LIST_INIT(&newindirdep->ir_donehd);
- newindirdep->ir_saveddata = (ufs_daddr_t *)bp->b_data;
+#ifdef __FreeBSD__
+ if (bp->b_blkno == bp->b_lblkno) {
+#if 0 /* we know this happens.. research suggested.. */
+ printf("setup_allocindir_phase2: need bmap, blk %d\n",
+ bp->b_lblkno);
+#endif
+ VOP_BMAP(bp->b_vp, bp->b_lblkno, NULL, &bp->b_blkno,
+ NULL, NULL);
+ }
+#endif /* __FreeBSD__ */
newindirdep->ir_savebp =
getblk(ip->i_devvp, bp->b_blkno, bp->b_bcount, 0, 0);
- bcopy((caddr_t)newindirdep->ir_saveddata,
- newindirdep->ir_savebp->b_data, bp->b_bcount);
+ bp->b_flags |= B_XXX;
+ bcopy(bp->b_data, newindirdep->ir_savebp->b_data, bp->b_bcount);
}
}
@@ -1716,6 +1729,8 @@ deallocate_dependencies(bp, inodedep)
panic("deallocate_dependencies: not indir");
bcopy(bp->b_data, indirdep->ir_savebp->b_data,
bp->b_bcount);
+if ((indirdep->ir_savebp->b_flags & B_BUSY) == 0 || (bp->b_flags & B_BUSY) == 0)
+panic("deallocate_dependencies: buffer unlocked");
WORKLIST_REMOVE(wk);
WORKLIST_INSERT(&indirdep->ir_savebp->b_dep, wk);
continue;
@@ -1980,6 +1995,7 @@ indir_trunc(ip, dbn, level, lbn, countp)
struct indirdep *indirdep;
int i, lbnadd, nblocks;
int error, allerror = 0;
+int debug;
fs = ip->i_fs;
lbnadd = 1;
@@ -2000,6 +2016,7 @@ indir_trunc(ip, dbn, level, lbn, countp)
ACQUIRE_LOCK(&lk);
if ((bp = incore(ip->i_devvp, dbn)) != NULL &&
(wk = LIST_FIRST(&bp->b_dep)) != NULL) {
+debug = 1;
if (wk->wk_type != D_INDIRDEP ||
(indirdep = WK_INDIRDEP(wk))->ir_savebp != bp ||
(indirdep->ir_state & GOINGAWAY) == 0)
@@ -2010,11 +2027,14 @@ indir_trunc(ip, dbn, level, lbn, countp)
panic("indir_trunc: dangling dep");
FREE_LOCK(&lk);
} else {
+debug = 2;
FREE_LOCK(&lk);
error = bread(ip->i_devvp, dbn, (int)fs->fs_bsize, NOCRED, &bp);
if (error)
return (error);
}
+if ((bp->b_flags & B_BUSY) == 0)
+panic("indir_trunc: unlocked buf");
/*
* Recursively free indirect blocks.
*/
@@ -2031,7 +2051,10 @@ indir_trunc(ip, dbn, level, lbn, countp)
ffs_blkfree(ip, nb, fs->fs_bsize);
*countp += nblocks;
}
+if (debug == i)
+printf("debug %d\n", debug);
bp->b_flags |= B_INVAL;
+ bp->b_flags &= ~B_XXX;
brelse(bp);
return (allerror);
}
@@ -2615,6 +2638,8 @@ softdep_disk_io_initiation(bp)
* dependency can be freed.
*/
if (LIST_FIRST(&indirdep->ir_deplisthd) == NULL) {
+ indirdep->ir_savebp->b_flags &= ~B_XXX;
+ indirdep->ir_savebp->b_flags |= B_INVAL;
brelse(indirdep->ir_savebp);
/* inline expand WORKLIST_REMOVE(wk); */
wk->wk_state &= ~ONWORKLIST;
@@ -2628,7 +2653,11 @@ softdep_disk_io_initiation(bp)
ACQUIRE_LOCK(&lk);
indirdep->ir_state &= ~ATTACHED;
indirdep->ir_state |= UNDONE;
- bp->b_data = indirdep->ir_savebp->b_data;
+ MALLOC(indirdep->ir_saveddata, caddr_t, bp->b_bcount,
+ M_INDIRDEP, M_WAITOK);
+ bcopy(bp->b_data, indirdep->ir_saveddata, bp->b_bcount);
+ bcopy(indirdep->ir_savebp->b_data, bp->b_data,
+ bp->b_bcount);
FREE_LOCK(&lk);
continue;
@@ -2646,6 +2675,30 @@ softdep_disk_io_initiation(bp)
}
}
+void
+scan_page(bp)
+ struct buf *bp;
+{
+ struct inodedep *inodedep;
+ struct direct *dp;
+ struct fs *fs;
+ caddr_t cp;
+
+ fs = VTOI(bp->b_vp)->i_fs;
+ for (cp = bp->b_data; cp < &bp->b_data[bp->b_bcount];
+ cp += dp->d_reclen) {
+ dp = (struct direct *)cp;
+ if (dp->d_reclen <= 0)
+ break;
+ if (dp->d_ino == 0)
+ continue;
+ if (inodedep_lookup(fs, dp->d_ino, 0, &inodedep) == 0)
+ continue;
+ if (inodedep->id_state & NEWINODE)
+ panic("scan_page: unallocated inode");
+ }
+}
+
/*
* Called from within the procedure above to deal with unsatisfied
* allocation dependencies in a directory. The buffer must be locked,
@@ -2689,6 +2742,7 @@ initiate_write_filepage(pagedep, bp)
dap->da_state |= UNDONE;
}
}
+/*scan_page(bp);*/
FREE_LOCK(&lk);
}
@@ -2913,7 +2967,9 @@ softdep_disk_write_complete(bp)
indirdep = WK_INDIRDEP(wk);
if (indirdep->ir_state & GOINGAWAY)
panic("disk_write_complete: indirdep gone");
- bp->b_data = (caddr_t)indirdep->ir_saveddata;
+ bcopy(indirdep->ir_saveddata, bp->b_data, bp->b_bcount);
+ FREE(indirdep->ir_saveddata, M_INDIRDEP);
+ indirdep->ir_saveddata = 0;
indirdep->ir_state &= ~UNDONE;
indirdep->ir_state |= ATTACHED;
while ((aip = LIST_FIRST(&indirdep->ir_donehd)) != 0) {
@@ -3081,6 +3137,7 @@ handle_written_inodeblock(inodedep, bp)
bdirty(bp);
return (1);
}
+inodedep->id_state &= ~NEWINODE;
/*
* Roll forward anything that had to be rolled back before
* the inode could be updated.
@@ -3201,6 +3258,8 @@ diradd_inode_written(dap, inodedep)
{
struct pagedep *pagedep;
+if (inodedep->id_state & NEWINODE)
+panic("diradd_inode_written: unallocated inode");
dap->da_state |= COMPLETE;
if ((dap->da_state & ALLCOMPLETE) == ALLCOMPLETE) {
if (dap->da_state & DIRCHG)
@@ -3570,7 +3629,11 @@ softdep_fsync(vp)
}
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
if (flushparent) {
+#ifndef __FreeBSD__
tv = time;
+#else
+ getmicrotime(&tv);
+#endif /* __FreeBSD__ */
if (error = UFS_UPDATE(pvp, &tv, &tv, MNT_WAIT)) {
vput(pvp);
return (error);
@@ -3654,6 +3717,13 @@ softdep_sync_metadata(ap)
waitfor = MNT_NOWAIT;
top:
if (getdirtybuf(&LIST_FIRST(&vp->v_dirtyblkhd), MNT_WAIT) == 0) {
+ while (vp->v_numoutput) {
+ vp->v_flag |= VBWAIT;
+ FREE_LOCK_INTERLOCKED(&lk);
+ tsleep((caddr_t)&vp->v_numoutput, PRIBIO + 1,
+ "sdsynm", 0);
+ ACQUIRE_LOCK_INTERLOCKED(&lk);
+ }
FREE_LOCK(&lk);
return (0);
}
@@ -3931,7 +4001,11 @@ flush_pagedep_deps(pvp, mp, diraddhdp)
* has a MKDIR_PARENT dependency.
*/
if (dap->da_state & MKDIR_PARENT) {
+#ifndef __FreeBSD__
tv = time;
+#else
+ getmicrotime(&tv);
+#endif /* __FreeBSD__ */
FREE_LOCK(&lk);
if (error = UFS_UPDATE(pvp, &tv, &tv, MNT_WAIT))
break;
@@ -4015,7 +4089,11 @@ flush_pagedep_deps(pvp, mp, diraddhdp)
}
FREE_LOCK(&lk);
}
+#ifndef __FreeBSD__
tv = time;
+#else
+ getmicrotime(&tv);
+#endif /* __FreeBSD__ */
error = UFS_UPDATE(vp, &tv, &tv, MNT_WAIT);
vput(vp);
if (error)
diff --git a/sys/ufs/ffs/softdep.h b/sys/ufs/ffs/softdep.h
index 3435f6304173..71bb7fa4f706 100644
--- a/sys/ufs/ffs/softdep.h
+++ b/sys/ufs/ffs/softdep.h
@@ -53,6 +53,7 @@
* SUCH DAMAGE.
*
* @(#)softdep.h 9.5 (McKusick) 2/11/98
+ * $Id:$
*/
#include <sys/queue.h>
@@ -352,7 +353,7 @@ struct allocdirect {
struct indirdep {
struct worklist ir_list; /* buffer holding indirect block */
# define ir_state ir_list.wk_state /* indirect block pointer state */
- ufs_daddr_t *ir_saveddata; /* buffer cache contents */
+ caddr_t ir_saveddata; /* buffer cache contents */
struct buf *ir_savebp; /* buffer holding safe copy */
struct allocindirhd ir_donehd; /* done waiting to update safecopy */
struct allocindirhd ir_deplisthd; /* allocindir deps for this block */