For synchronous writes, keep separate i/o counters for each write, so
processes don't have to wait for one another to finish (e.g., nfsd seems to be a little happier now, though I haven't measured the difference). Synchronous checkpoints, however, must always wait for all i/o to finish. Take the contents of the callback functions and have them run in thread context instead (aiodoned thread). lfs_iocount no longer has to be protected in splbio(), and quite a bit less of the segment construction loop needs to be in splbio() as well. If lfs_markv is handed a block that is not the correct size according to the inode, refuse to process it. (Formerly it was extended to the "correct" size.) This is possibly more prone to deadlock, but less prone to corruption. lfs_segclean now outright refuses to clean segments that appear to have live bytes in them. Again this may be more prone to deadlock but avoids corruption. Replace ufsspec_close and ufsfifo_close with LFS equivalents; this means that no UFS functions need to know about LFS_ITIMES any more. Remove the reference from ufs/inode.h. Tested on i386, test-compiled on alpha.
This commit is contained in:
parent
9ed8a29685
commit
ddfb1dbb92
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: lfs.h,v 1.39 2002/05/14 20:03:53 perseant Exp $ */
|
||||
/* $NetBSD: lfs.h,v 1.40 2002/06/16 00:13:15 perseant Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
|
||||
@ -765,6 +765,7 @@ struct segment {
|
||||
#define SEGM_SYNC 0x04 /* wait for segment */
|
||||
#define SEGM_PROT 0x08 /* don't inactivate at segunlock */
|
||||
u_int16_t seg_flags; /* run-time flags for this segment */
|
||||
u_int32_t seg_iocount; /* number of ios pending */
|
||||
};
|
||||
|
||||
struct lfs_cluster {
|
||||
@ -773,8 +774,10 @@ struct lfs_cluster {
|
||||
size_t bufsize; /* Size of kept data */
|
||||
#define LFS_CL_MALLOC 0x00000001
|
||||
#define LFS_CL_SHIFT 0x00000002
|
||||
#define LFS_CL_SYNC 0x00000004
|
||||
u_int32_t flags; /* Flags */
|
||||
struct lfs *fs; /* LFS that this belongs to */
|
||||
struct segment *seg; /* Segment structure, for LFS_CL_SYNC */
|
||||
void *saveaddr; /* Original contents of saveaddr */
|
||||
char *olddata; /* Original b_data, if LFS_CL_MALLOC */
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: lfs_cksum.c,v 1.19 2001/11/15 09:48:29 lukem Exp $ */
|
||||
/* $NetBSD: lfs_cksum.c,v 1.20 2002/06/16 00:13:15 perseant Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
|
||||
@ -71,7 +71,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: lfs_cksum.c,v 1.19 2001/11/15 09:48:29 lukem Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: lfs_cksum.c,v 1.20 2002/06/16 00:13:15 perseant Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#ifdef _KERNEL
|
||||
@ -83,6 +83,7 @@ __KERNEL_RCSID(0, "$NetBSD: lfs_cksum.c,v 1.19 2001/11/15 09:48:29 lukem Exp $")
|
||||
#include <sys/mount.h>
|
||||
#include <ufs/ufs/inode.h>
|
||||
#include <ufs/lfs/lfs.h>
|
||||
#include <ufs/lfs/lfs_extern.h>
|
||||
|
||||
/*
|
||||
* Simple, general purpose, fast checksum. Data must be short-aligned.
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: lfs_extern.h,v 1.30 2002/05/14 20:03:53 perseant Exp $ */
|
||||
/* $NetBSD: lfs_extern.h,v 1.31 2002/06/16 00:13:15 perseant Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
|
||||
@ -209,8 +209,8 @@ int lfs_valloc (void *);
|
||||
int lfs_vfree (void *);
|
||||
int lfs_bwrite (void *);
|
||||
int lfs_update (void *);
|
||||
int lfs_truncate(void *);
|
||||
int lfs_blkatoff(void *);
|
||||
int lfs_truncate (void *);
|
||||
int lfs_blkatoff (void *);
|
||||
int lfs_fsync (void *);
|
||||
int lfs_symlink (void *);
|
||||
int lfs_mknod (void *);
|
||||
@ -224,12 +224,14 @@ int lfs_rename (void *);
|
||||
int lfs_getattr (void *);
|
||||
int lfs_setattr (void *);
|
||||
int lfs_close (void *);
|
||||
int lfs_inactive(void *);
|
||||
int lfsspec_close(void *);
|
||||
int lfsfifo_close(void *);
|
||||
int lfs_inactive (void *);
|
||||
int lfs_reclaim (void *);
|
||||
int lfs_write (void *);
|
||||
int lfs_whiteout(void *);
|
||||
int lfs_getpages(void *);
|
||||
int lfs_putpages(void *);
|
||||
int lfs_whiteout (void *);
|
||||
int lfs_getpages (void *);
|
||||
int lfs_putpages (void *);
|
||||
|
||||
__END_DECLS
|
||||
extern int lfs_mount_type;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: lfs_segment.c,v 1.78 2002/05/24 22:13:57 perseant Exp $ */
|
||||
/* $NetBSD: lfs_segment.c,v 1.79 2002/06/16 00:13:15 perseant Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
|
||||
@ -71,7 +71,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: lfs_segment.c,v 1.78 2002/05/24 22:13:57 perseant Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: lfs_segment.c,v 1.79 2002/06/16 00:13:15 perseant Exp $");
|
||||
|
||||
#define ivndebug(vp,str) printf("ino %d: %s\n",VTOI(vp)->i_number,(str))
|
||||
|
||||
@ -104,11 +104,15 @@ __KERNEL_RCSID(0, "$NetBSD: lfs_segment.c,v 1.78 2002/05/24 22:13:57 perseant Ex
|
||||
#include <ufs/lfs/lfs.h>
|
||||
#include <ufs/lfs/lfs_extern.h>
|
||||
|
||||
#include <uvm/uvm.h>
|
||||
#include <uvm/uvm_extern.h>
|
||||
|
||||
extern int count_lock_queue(void);
|
||||
extern struct simplelock vnode_free_list_slock; /* XXX */
|
||||
|
||||
static void lfs_generic_callback(struct buf *, void (*)(struct buf *));
|
||||
static void lfs_super_aiodone(struct buf *);
|
||||
static void lfs_cluster_aiodone(struct buf *);
|
||||
static void lfs_cluster_callback(struct buf *);
|
||||
static struct buf **lookahead_pagemove(struct buf **, int, size_t *);
|
||||
|
||||
@ -290,8 +294,9 @@ lfs_vflush(struct vnode *vp)
|
||||
}
|
||||
|
||||
SET_FLUSHING(fs,vp);
|
||||
if (fs->lfs_nactive > LFS_MAX_ACTIVE) {
|
||||
error = lfs_segwrite(vp->v_mount, SEGM_SYNC|SEGM_CKP);
|
||||
if (fs->lfs_nactive > LFS_MAX_ACTIVE ||
|
||||
(fs->lfs_sp->seg_flags & SEGM_CKP)) {
|
||||
error = lfs_segwrite(vp->v_mount, SEGM_CKP | SEGM_SYNC);
|
||||
CLR_FLUSHING(fs,vp);
|
||||
lfs_segunlock(fs);
|
||||
return error;
|
||||
@ -351,11 +356,9 @@ lfs_vflush(struct vnode *vp)
|
||||
* artificially incremented by lfs_seglock().
|
||||
*/
|
||||
if (fs->lfs_seglock > 1) {
|
||||
s = splbio();
|
||||
while (fs->lfs_iocount > 1)
|
||||
(void)tsleep(&fs->lfs_iocount, PRIBIO + 1,
|
||||
"lfs_vflush", 0);
|
||||
splx(s);
|
||||
}
|
||||
lfs_segunlock(fs);
|
||||
|
||||
@ -692,8 +695,8 @@ lfs_segwrite(struct mount *mp, int flags)
|
||||
* Take the flags off of the segment so that lfs_segunlock
|
||||
* doesn't have to write the superblock either.
|
||||
*/
|
||||
if (did_ckp == 0) {
|
||||
sp->seg_flags &= ~(SEGM_SYNC|SEGM_CKP);
|
||||
if (do_ckp && !did_ckp) {
|
||||
sp->seg_flags &= ~SEGM_CKP;
|
||||
/* if (do_ckp) printf("lfs_segwrite: no checkpoint\n"); */
|
||||
}
|
||||
|
||||
@ -1443,12 +1446,20 @@ lfs_newclusterbuf(struct lfs *fs, struct vnode *vp, daddr_t addr, int n)
|
||||
|
||||
cl = (struct lfs_cluster *)malloc(sizeof(*cl), M_SEGMENT, M_WAITOK);
|
||||
bpp = (struct buf **)malloc(n*sizeof(*bpp), M_SEGMENT, M_WAITOK);
|
||||
memset(cl,0,sizeof(*cl));
|
||||
memset(cl, 0, sizeof(*cl));
|
||||
cl->fs = fs;
|
||||
cl->bpp = bpp;
|
||||
cl->bufcount = 0;
|
||||
cl->bufsize = 0;
|
||||
|
||||
/* If this segment is being written synchronously, note that */
|
||||
if (fs->lfs_sp->seg_flags & SEGM_SYNC) {
|
||||
cl->flags |= LFS_CL_SYNC;
|
||||
cl->seg = fs->lfs_sp;
|
||||
++cl->seg->seg_iocount;
|
||||
/* printf("+ %x => %d\n", cl->seg, cl->seg->seg_iocount); */
|
||||
}
|
||||
|
||||
/* Get an empty buffer header, or maybe one with something on it */
|
||||
s = splbio();
|
||||
if((bp = bufqueues[BQ_EMPTY].tqh_first) != NULL) {
|
||||
@ -1791,7 +1802,6 @@ lfs_writeseg(struct lfs *fs, struct segment *sp)
|
||||
/*
|
||||
* Construct the cluster.
|
||||
*/
|
||||
s = splbio();
|
||||
while (fs->lfs_iocount >= LFS_THROTTLE) {
|
||||
#ifdef DEBUG_LFS
|
||||
printf("[%d]", fs->lfs_iocount);
|
||||
@ -1841,7 +1851,9 @@ lfs_writeseg(struct lfs *fs, struct segment *sp)
|
||||
bp->b_flags &= ~(B_ERROR | B_READ | B_DELWRI | B_DONE);
|
||||
cl->bpp[cl->bufcount++] = bp;
|
||||
vp = bp->b_vp;
|
||||
s = splbio();
|
||||
++vp->v_numoutput;
|
||||
splx(s);
|
||||
|
||||
/*
|
||||
* Although it cannot be freed for reuse before the
|
||||
@ -1875,6 +1887,7 @@ lfs_writeseg(struct lfs *fs, struct segment *sp)
|
||||
* XXX KS - Shouldn't we set *both* if both types
|
||||
* of blocks are present (traverse the dirty list?)
|
||||
*/
|
||||
s = splbio();
|
||||
if ((i == 1 ||
|
||||
(i > 1 && vp && *bpp && (*bpp)->b_vp != vp)) &&
|
||||
(bp = LIST_FIRST(&vp->v_dirtyblkhd)) != NULL &&
|
||||
@ -1890,8 +1903,10 @@ lfs_writeseg(struct lfs *fs, struct segment *sp)
|
||||
else
|
||||
LFS_SET_UINO(ip, IN_MODIFIED);
|
||||
}
|
||||
splx(s);
|
||||
wakeup(vp);
|
||||
}
|
||||
s = splbio();
|
||||
++cbp->b_vp->v_numoutput;
|
||||
splx(s);
|
||||
/*
|
||||
@ -1967,8 +1982,8 @@ lfs_writesuper(struct lfs *fs, daddr_t daddr)
|
||||
vop_strategy_a.a_bp = bp;
|
||||
s = splbio();
|
||||
++bp->b_vp->v_numoutput;
|
||||
++fs->lfs_iocount;
|
||||
splx(s);
|
||||
++fs->lfs_iocount;
|
||||
(strategy)(&vop_strategy_a);
|
||||
}
|
||||
|
||||
@ -2030,8 +2045,8 @@ lfs_callback(struct buf *bp)
|
||||
lfs_freebuf(bp);
|
||||
}
|
||||
|
||||
void
|
||||
lfs_supercallback(struct buf *bp)
|
||||
static void
|
||||
lfs_super_aiodone(struct buf *bp)
|
||||
{
|
||||
struct lfs *fs;
|
||||
|
||||
@ -2044,13 +2059,13 @@ lfs_supercallback(struct buf *bp)
|
||||
}
|
||||
|
||||
static void
|
||||
lfs_cluster_callback(struct buf *bp)
|
||||
lfs_cluster_aiodone(struct buf *bp)
|
||||
{
|
||||
struct lfs_cluster *cl;
|
||||
struct lfs *fs;
|
||||
struct buf *tbp;
|
||||
struct vnode *vp;
|
||||
int error=0;
|
||||
int s, error=0;
|
||||
char *cp;
|
||||
extern int locked_queue_count;
|
||||
extern long locked_queue_bytes;
|
||||
@ -2101,8 +2116,10 @@ lfs_cluster_callback(struct buf *bp)
|
||||
tbp->b_flags |= B_INVAL;
|
||||
if(!(tbp->b_flags & B_CALL)) {
|
||||
bremfree(tbp);
|
||||
s = splbio();
|
||||
if(vp)
|
||||
reassignbuf(tbp, vp);
|
||||
splx(s);
|
||||
tbp->b_flags |= B_ASYNC; /* for biodone */
|
||||
}
|
||||
#ifdef DIAGNOSTIC
|
||||
@ -2112,27 +2129,7 @@ lfs_cluster_callback(struct buf *bp)
|
||||
}
|
||||
#endif
|
||||
if (tbp->b_flags & (B_BUSY | B_CALL)) {
|
||||
/*
|
||||
* Prevent vp from being moved between hold list
|
||||
* and free list by giving it an extra hold,
|
||||
* and then inline HOLDRELE, minus the TAILQ
|
||||
* manipulation.
|
||||
*
|
||||
* lfs_vunref() will put the vnode back on the
|
||||
* appropriate free list the next time it is
|
||||
* called (in thread context).
|
||||
*/
|
||||
if (vp)
|
||||
VHOLD(vp);
|
||||
biodone(tbp);
|
||||
if (vp) {
|
||||
simple_lock(&vp->v_interlock);
|
||||
if (vp->v_holdcnt <= 0)
|
||||
panic("lfs_cluster_callback: "
|
||||
"holdcnt vp %p", vp);
|
||||
vp->v_holdcnt--;
|
||||
simple_unlock(&vp->v_interlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2151,23 +2148,26 @@ lfs_cluster_callback(struct buf *bp)
|
||||
bp->b_iodone = NULL;
|
||||
bp->b_flags &= ~B_DELWRI;
|
||||
bp->b_flags |= B_DONE;
|
||||
s = splbio();
|
||||
reassignbuf(bp, bp->b_vp);
|
||||
splx(s);
|
||||
brelse(bp);
|
||||
|
||||
free(cl->bpp, M_SEGMENT);
|
||||
free(cl, M_SEGMENT);
|
||||
|
||||
/* Note i/o done */
|
||||
if (cl->flags & LFS_CL_SYNC) {
|
||||
if (--cl->seg->seg_iocount == 0)
|
||||
wakeup(&cl->seg->seg_iocount);
|
||||
/* printf("- %x => %d\n", cl->seg, cl->seg->seg_iocount); */
|
||||
}
|
||||
#ifdef DIAGNOSTIC
|
||||
if (fs->lfs_iocount == 0)
|
||||
panic("lfs_callback: zero iocount\n");
|
||||
panic("lfs_cluster_aiodone: zero iocount\n");
|
||||
#endif
|
||||
if (--fs->lfs_iocount < LFS_THROTTLE)
|
||||
wakeup(&fs->lfs_iocount);
|
||||
#if 0
|
||||
if (fs->lfs_iocount == 0) {
|
||||
/*
|
||||
* XXX - do we really want to do this in a callback?
|
||||
*
|
||||
* Vinvalbuf can move locked buffers off the locked queue
|
||||
* and we have no way of knowing about this. So, after
|
||||
* doing a big write, we recalculate how many buffers are
|
||||
@ -2177,6 +2177,33 @@ lfs_cluster_callback(struct buf *bp)
|
||||
wakeup(&locked_queue_count);
|
||||
}
|
||||
#endif
|
||||
|
||||
free(cl->bpp, M_SEGMENT);
|
||||
free(cl, M_SEGMENT);
|
||||
}
|
||||
|
||||
static void
|
||||
lfs_generic_callback(struct buf *bp, void (*aiodone)(struct buf *))
|
||||
{
|
||||
/* reset b_iodone for when this is a single-buf i/o. */
|
||||
bp->b_iodone = aiodone;
|
||||
|
||||
simple_lock(&uvm.aiodoned_lock); /* locks uvm.aio_done */
|
||||
TAILQ_INSERT_TAIL(&uvm.aio_done, bp, b_freelist);
|
||||
wakeup(&uvm.aiodoned);
|
||||
simple_unlock(&uvm.aiodoned_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
lfs_cluster_callback(struct buf *bp)
|
||||
{
|
||||
lfs_generic_callback(bp, lfs_cluster_aiodone);
|
||||
}
|
||||
|
||||
void
|
||||
lfs_supercallback(struct buf *bp)
|
||||
{
|
||||
lfs_generic_callback(bp, lfs_super_aiodone);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: lfs_subr.c,v 1.25 2002/05/24 22:13:57 perseant Exp $ */
|
||||
/* $NetBSD: lfs_subr.c,v 1.26 2002/06/16 00:13:15 perseant Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
|
||||
@ -71,7 +71,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: lfs_subr.c,v 1.25 2002/05/24 22:13:57 perseant Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: lfs_subr.c,v 1.26 2002/06/16 00:13:15 perseant Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -131,7 +131,6 @@ void
|
||||
lfs_seglock(struct lfs *fs, unsigned long flags)
|
||||
{
|
||||
struct segment *sp;
|
||||
int s;
|
||||
|
||||
if (fs->lfs_seglock) {
|
||||
if (fs->lfs_lockpid == curproc->p_pid) {
|
||||
@ -152,6 +151,7 @@ lfs_seglock(struct lfs *fs, unsigned long flags)
|
||||
M_SEGMENT, M_WAITOK);
|
||||
sp->seg_flags = flags;
|
||||
sp->vp = NULL;
|
||||
sp->seg_iocount = 0;
|
||||
(void) lfs_initseg(fs);
|
||||
|
||||
/*
|
||||
@ -160,9 +160,7 @@ lfs_seglock(struct lfs *fs, unsigned long flags)
|
||||
* so we artificially increment it by one until we've scheduled all of
|
||||
* the writes we intend to do.
|
||||
*/
|
||||
s = splbio();
|
||||
++fs->lfs_iocount;
|
||||
splx(s);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -174,7 +172,6 @@ lfs_segunlock(struct lfs *fs)
|
||||
{
|
||||
struct segment *sp;
|
||||
unsigned long sync, ckp;
|
||||
int s;
|
||||
struct buf *bp;
|
||||
struct vnode *vp, *nvp;
|
||||
struct mount *mp;
|
||||
@ -265,6 +262,8 @@ lfs_segunlock(struct lfs *fs)
|
||||
|
||||
free(sp->bpp, M_SEGMENT);
|
||||
sp->bpp = NULL;
|
||||
/* The sync case holds a reference in `sp' to be freed below */
|
||||
if (!sync)
|
||||
free(sp, M_SEGMENT);
|
||||
fs->lfs_sp = NULL;
|
||||
|
||||
@ -273,7 +272,6 @@ lfs_segunlock(struct lfs *fs)
|
||||
* At the moment, the user's process hangs around so we can
|
||||
* sleep.
|
||||
*/
|
||||
s = splbio();
|
||||
if (--fs->lfs_iocount < LFS_THROTTLE)
|
||||
wakeup(&fs->lfs_iocount);
|
||||
if(fs->lfs_iocount == 0) {
|
||||
@ -282,6 +280,16 @@ lfs_segunlock(struct lfs *fs)
|
||||
wakeup(&locked_queue_count);
|
||||
wakeup(&fs->lfs_iocount);
|
||||
}
|
||||
/*
|
||||
* If we're not checkpointing, we don't have to block
|
||||
* other processes to wait for a synchronous write
|
||||
* to complete.
|
||||
*/
|
||||
if (!ckp) {
|
||||
--fs->lfs_seglock;
|
||||
fs->lfs_lockpid = 0;
|
||||
wakeup(&fs->lfs_seglock);
|
||||
}
|
||||
/*
|
||||
* We let checkpoints happen asynchronously. That means
|
||||
* that during recovery, we have to roll forward between
|
||||
@ -289,10 +297,16 @@ lfs_segunlock(struct lfs *fs)
|
||||
* superblocks to make sure that the checkpoint described
|
||||
* by a superblock completed.
|
||||
*/
|
||||
while (sync && fs->lfs_iocount)
|
||||
while (ckp && sync && fs->lfs_iocount)
|
||||
(void)tsleep(&fs->lfs_iocount, PRIBIO + 1,
|
||||
"lfs vflush", 0);
|
||||
splx(s);
|
||||
"lfs_iocount", 0);
|
||||
while (sync && sp->seg_iocount) {
|
||||
(void)tsleep(&sp->seg_iocount, PRIBIO + 1,
|
||||
"seg_iocount", 0);
|
||||
/* printf("sleeping on iocount %x == %d\n", sp, sp->seg_iocount); */
|
||||
}
|
||||
if (sync)
|
||||
free(sp, M_SEGMENT);
|
||||
if (ckp) {
|
||||
fs->lfs_nactive = 0;
|
||||
/* If we *know* everything's on disk, write both sbs */
|
||||
@ -300,10 +314,11 @@ lfs_segunlock(struct lfs *fs)
|
||||
lfs_writesuper(fs,fs->lfs_sboffs[fs->lfs_activesb]);
|
||||
fs->lfs_activesb = 1 - fs->lfs_activesb;
|
||||
lfs_writesuper(fs,fs->lfs_sboffs[fs->lfs_activesb]);
|
||||
}
|
||||
|
||||
--fs->lfs_seglock;
|
||||
fs->lfs_lockpid = 0;
|
||||
wakeup(&fs->lfs_seglock);
|
||||
}
|
||||
} else if (fs->lfs_seglock == 0) {
|
||||
panic ("Seglock not held");
|
||||
} else {
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: lfs_syscalls.c,v 1.66 2002/06/06 00:46:24 perseant Exp $ */
|
||||
/* $NetBSD: lfs_syscalls.c,v 1.67 2002/06/16 00:13:16 perseant Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
|
||||
@ -71,7 +71,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: lfs_syscalls.c,v 1.66 2002/06/06 00:46:24 perseant Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: lfs_syscalls.c,v 1.67 2002/06/16 00:13:16 perseant Exp $");
|
||||
|
||||
#define LFS /* for prototypes in syscallargs.h */
|
||||
|
||||
@ -282,7 +282,7 @@ lfs_markv(struct proc *p, fsid_t *fsidp, BLOCK_INFO *blkiov, int blkcnt)
|
||||
* any Ifile blocks that we might be asked to clean will never get
|
||||
* to the disk.
|
||||
*/
|
||||
lfs_seglock(fs, SEGM_SYNC|SEGM_CLEAN|SEGM_CKP);
|
||||
lfs_seglock(fs, SEGM_CLEAN | SEGM_CKP | SEGM_SYNC);
|
||||
|
||||
/* Mark blocks/inodes dirty. */
|
||||
error = 0;
|
||||
@ -444,6 +444,7 @@ lfs_markv(struct proc *p, fsid_t *fsidp, BLOCK_INFO *blkiov, int blkcnt)
|
||||
printf("lfs_markv: wrong da same seg: %x vs %x\n",
|
||||
blkp->bi_daddr, dbtofsb(fs, b_daddr));
|
||||
}
|
||||
do_again++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -465,9 +466,13 @@ lfs_markv(struct proc *p, fsid_t *fsidp, BLOCK_INFO *blkiov, int blkcnt)
|
||||
s = splbio();
|
||||
bp = incore(vp, blkp->bi_lbn);
|
||||
if (bp && bp->b_bcount > blkp->bi_size) {
|
||||
printf("lfs_markv: %ld > %d (fixed)\n",
|
||||
splx(s);
|
||||
printf("lfs_markv: ino %d lbn %d fragment size changed (%ld > %d), try again\n",
|
||||
blkp->bi_inode, blkp->bi_lbn,
|
||||
bp->b_bcount, blkp->bi_size);
|
||||
blkp->bi_size = bp->b_bcount;
|
||||
do_again++;
|
||||
continue;
|
||||
/* blkp->bi_size = bp->b_bcount; */
|
||||
}
|
||||
splx(s);
|
||||
}
|
||||
@ -524,7 +529,7 @@ lfs_markv(struct proc *p, fsid_t *fsidp, BLOCK_INFO *blkiov, int blkcnt)
|
||||
* over the newly cleaned data contained in a checkpoint, and then
|
||||
* we'd be unhappy at recovery time.
|
||||
*/
|
||||
lfs_segwrite(mntp, SEGM_SYNC|SEGM_CLEAN|SEGM_CKP);
|
||||
lfs_segwrite(mntp, SEGM_CLEAN | SEGM_CKP | SEGM_SYNC);
|
||||
|
||||
lfs_segunlock(fs);
|
||||
|
||||
@ -884,6 +889,7 @@ sys_lfs_segclean(struct proc *p, void *v, register_t *retval)
|
||||
struct lfs *fs;
|
||||
fsid_t fsid;
|
||||
int error;
|
||||
unsigned long segnum;
|
||||
|
||||
if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
|
||||
return (error);
|
||||
@ -894,8 +900,9 @@ sys_lfs_segclean(struct proc *p, void *v, register_t *retval)
|
||||
return (ENOENT);
|
||||
|
||||
fs = VFSTOUFS(mntp)->um_lfs;
|
||||
segnum = SCARG(uap, segment);
|
||||
|
||||
if (dtosn(fs, fs->lfs_curseg) == SCARG(uap, segment))
|
||||
if (dtosn(fs, fs->lfs_curseg) == segnum)
|
||||
return (EBUSY);
|
||||
|
||||
if ((error = vfs_busy(mntp, LK_NOWAIT, NULL)) != 0)
|
||||
@ -903,7 +910,17 @@ sys_lfs_segclean(struct proc *p, void *v, register_t *retval)
|
||||
#ifdef LFS_AGGRESSIVE_SEGLOCK
|
||||
lfs_seglock(fs, SEGM_PROT);
|
||||
#endif
|
||||
LFS_SEGENTRY(sup, fs, SCARG(uap, segment), bp);
|
||||
LFS_SEGENTRY(sup, fs, segnum, bp);
|
||||
if (sup->su_nbytes) {
|
||||
printf("lfs_segclean: not cleaning segment %lu: %d live bytes\n",
|
||||
segnum, sup->su_nbytes);
|
||||
brelse(bp);
|
||||
#ifdef LFS_AGGRESSIVE_SEGLOCK
|
||||
lfs_segunlock(fs);
|
||||
#endif
|
||||
vfs_unbusy(mntp);
|
||||
return (EBUSY);
|
||||
}
|
||||
if (sup->su_flags & SEGUSE_ACTIVE) {
|
||||
brelse(bp);
|
||||
#ifdef LFS_AGGRESSIVE_SEGLOCK
|
||||
@ -924,7 +941,7 @@ sys_lfs_segclean(struct proc *p, void *v, register_t *retval)
|
||||
fs->lfs_avail += segtod(fs, 1);
|
||||
if (sup->su_flags & SEGUSE_SUPERBLOCK)
|
||||
fs->lfs_avail -= btofsb(fs, LFS_SBPAD);
|
||||
if (fs->lfs_version > 1 && SCARG(uap, segment) == 0 &&
|
||||
if (fs->lfs_version > 1 && segnum == 0 &&
|
||||
fs->lfs_start < btofsb(fs, LFS_LABELPAD))
|
||||
fs->lfs_avail -= btofsb(fs, LFS_LABELPAD) - fs->lfs_start;
|
||||
fs->lfs_bfree += sup->su_nsums * btofsb(fs, fs->lfs_sumsize) +
|
||||
@ -1240,9 +1257,7 @@ lfs_fakebuf(struct lfs *fs, struct vnode *vp, int lbn, size_t size, caddr_t uadd
|
||||
#endif
|
||||
#if 0
|
||||
bp->b_saveaddr = (caddr_t)fs;
|
||||
s = splbio();
|
||||
++fs->lfs_iocount;
|
||||
splx(s);
|
||||
#endif
|
||||
bp->b_bufsize = size;
|
||||
bp->b_bcount = size;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: lfs_vfsops.c,v 1.76 2002/05/17 21:42:38 perseant Exp $ */
|
||||
/* $NetBSD: lfs_vfsops.c,v 1.77 2002/06/16 00:13:16 perseant Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
|
||||
@ -71,7 +71,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: lfs_vfsops.c,v 1.76 2002/05/17 21:42:38 perseant Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: lfs_vfsops.c,v 1.77 2002/06/16 00:13:16 perseant Exp $");
|
||||
|
||||
#if defined(_KERNEL_OPT)
|
||||
#include "opt_quota.h"
|
||||
@ -1174,7 +1174,7 @@ lfs_unmount(struct mount *mp, int mntflags, struct proc *p)
|
||||
{
|
||||
struct ufsmount *ump;
|
||||
struct lfs *fs;
|
||||
int error, flags, ronly, s;
|
||||
int error, flags, ronly;
|
||||
|
||||
flags = 0;
|
||||
if (mntflags & MNT_FORCE)
|
||||
@ -1231,10 +1231,8 @@ lfs_unmount(struct mount *mp, int mntflags, struct proc *p)
|
||||
vgone(fs->lfs_ivnode);
|
||||
|
||||
/* Wait for superblock writes to complete */
|
||||
s = splbio();
|
||||
while (fs->lfs_iocount)
|
||||
tsleep(&fs->lfs_iocount, PRIBIO + 1, "lfs_umount", 0);
|
||||
splx(s);
|
||||
|
||||
ronly = !fs->lfs_ronly;
|
||||
if (ump->um_devvp->v_type != VBAD)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: lfs_vnops.c,v 1.64 2002/05/17 21:42:38 perseant Exp $ */
|
||||
/* $NetBSD: lfs_vnops.c,v 1.65 2002/06/16 00:13:16 perseant Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
|
||||
@ -71,7 +71,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: lfs_vnops.c,v 1.64 2002/05/17 21:42:38 perseant Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: lfs_vnops.c,v 1.65 2002/06/16 00:13:16 perseant Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -164,7 +164,7 @@ const struct vnodeopv_entry_desc lfs_specop_entries[] = {
|
||||
{ &vop_create_desc, spec_create }, /* create */
|
||||
{ &vop_mknod_desc, spec_mknod }, /* mknod */
|
||||
{ &vop_open_desc, spec_open }, /* open */
|
||||
{ &vop_close_desc, ufsspec_close }, /* close */
|
||||
{ &vop_close_desc, lfsspec_close }, /* close */
|
||||
{ &vop_access_desc, ufs_access }, /* access */
|
||||
{ &vop_getattr_desc, lfs_getattr }, /* getattr */
|
||||
{ &vop_setattr_desc, lfs_setattr }, /* setattr */
|
||||
@ -217,7 +217,7 @@ const struct vnodeopv_entry_desc lfs_fifoop_entries[] = {
|
||||
{ &vop_create_desc, fifo_create }, /* create */
|
||||
{ &vop_mknod_desc, fifo_mknod }, /* mknod */
|
||||
{ &vop_open_desc, fifo_open }, /* open */
|
||||
{ &vop_close_desc, ufsfifo_close }, /* close */
|
||||
{ &vop_close_desc, lfsfifo_close }, /* close */
|
||||
{ &vop_access_desc, ufs_access }, /* access */
|
||||
{ &vop_getattr_desc, lfs_getattr }, /* getattr */
|
||||
{ &vop_setattr_desc, lfs_setattr }, /* setattr */
|
||||
@ -864,15 +864,67 @@ lfs_close(void *v)
|
||||
struct inode *ip = VTOI(vp);
|
||||
struct timespec ts;
|
||||
|
||||
simple_lock(&vp->v_interlock);
|
||||
if (vp->v_usecount > 1) {
|
||||
TIMEVAL_TO_TIMESPEC(&time, &ts);
|
||||
LFS_ITIMES(ip, &ts, &ts, &ts);
|
||||
}
|
||||
simple_unlock(&vp->v_interlock);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Close wrapper for special devices.
|
||||
*
|
||||
* Update the times on the inode then do device close.
|
||||
*/
|
||||
int
|
||||
lfsspec_close(void *v)
|
||||
{
|
||||
struct vop_close_args /* {
|
||||
struct vnode *a_vp;
|
||||
int a_fflag;
|
||||
struct ucred *a_cred;
|
||||
struct proc *a_p;
|
||||
} */ *ap = v;
|
||||
struct vnode *vp;
|
||||
struct inode *ip;
|
||||
struct timespec ts;
|
||||
|
||||
vp = ap->a_vp;
|
||||
ip = VTOI(vp);
|
||||
if (vp->v_usecount > 1) {
|
||||
TIMEVAL_TO_TIMESPEC(&time, &ts);
|
||||
LFS_ITIMES(ip, &ts, &ts, &ts);
|
||||
}
|
||||
return (VOCALL (spec_vnodeop_p, VOFFSET(vop_close), ap));
|
||||
}
|
||||
|
||||
/*
|
||||
* Close wrapper for fifo's.
|
||||
*
|
||||
* Update the times on the inode then do device close.
|
||||
*/
|
||||
int
|
||||
lfsfifo_close(void *v)
|
||||
{
|
||||
struct vop_close_args /* {
|
||||
struct vnode *a_vp;
|
||||
int a_fflag;
|
||||
struct ucred *a_cred;
|
||||
struct proc *a_p;
|
||||
} */ *ap = v;
|
||||
struct vnode *vp;
|
||||
struct inode *ip;
|
||||
struct timespec ts;
|
||||
|
||||
vp = ap->a_vp;
|
||||
ip = VTOI(vp);
|
||||
if (ap->a_vp->v_usecount > 1) {
|
||||
TIMEVAL_TO_TIMESPEC(&time, &ts);
|
||||
LFS_ITIMES(ip, &ts, &ts, &ts);
|
||||
}
|
||||
return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_close), ap));
|
||||
}
|
||||
|
||||
/*
|
||||
* Reclaim an inode so that it can be used for other purposes.
|
||||
*/
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: inode.h,v 1.27 2001/12/18 10:57:23 fvdl Exp $ */
|
||||
/* $NetBSD: inode.h,v 1.28 2002/06/16 00:13:17 perseant Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1989, 1993
|
||||
@ -45,7 +45,6 @@
|
||||
#include <ufs/ufs/dir.h>
|
||||
#include <ufs/ufs/quota.h>
|
||||
#include <ufs/ext2fs/ext2fs_dinode.h>
|
||||
#include <ufs/lfs/lfs_extern.h>
|
||||
#include <miscfs/genfs/genfs_node.h>
|
||||
|
||||
/*
|
||||
@ -176,9 +175,6 @@ struct inode {
|
||||
#define IN_SPACECOUNTED 0x0400 /* Blocks to be freed in free count. */
|
||||
|
||||
#if defined(_KERNEL)
|
||||
#if defined(_KERNEL_OPT)
|
||||
#include "fs_lfs.h" /* for ITIMES */
|
||||
#endif /* _KERNEL_OPT */
|
||||
/*
|
||||
* Structure used to pass around logical block paths generated by
|
||||
* ufs_getlbns and used by truncate and bmap code.
|
||||
@ -234,23 +230,12 @@ struct indir {
|
||||
} \
|
||||
}
|
||||
|
||||
#ifdef LFS
|
||||
#define ITIMES(ip, acc, mod, cre) { \
|
||||
if (IS_EXT2_VNODE((ip)->i_vnode)) \
|
||||
EXT2FS_ITIMES(ip, acc, mod, cre) \
|
||||
else if(IS_LFS_VNODE((ip)->i_vnode)) \
|
||||
lfs_itimes(ip, acc, mod, cre); \
|
||||
else \
|
||||
FFS_ITIMES(ip, acc, mod, cre) \
|
||||
}
|
||||
#else /* ! LFS */
|
||||
#define ITIMES(ip, acc, mod, cre) { \
|
||||
if (IS_EXT2_VNODE((ip)->i_vnode)) \
|
||||
EXT2FS_ITIMES(ip, acc, mod, cre) \
|
||||
else \
|
||||
FFS_ITIMES(ip, acc, mod, cre) \
|
||||
}
|
||||
#endif /* ! LFS */
|
||||
|
||||
/* Determine if soft dependencies are being done */
|
||||
#define DOINGSOFTDEP(vp) ((vp)->v_mount->mnt_flag & MNT_SOFTDEP)
|
||||
|
Loading…
Reference in New Issue
Block a user