summaryrefslogtreecommitdiff
path: root/sys/ufs
diff options
context:
space:
mode:
authorThordur I. Bjornsson <thib@cvs.openbsd.org>2011-08-16 14:36:40 +0000
committerThordur I. Bjornsson <thib@cvs.openbsd.org>2011-08-16 14:36:40 +0000
commit524fc0c212ac7546522d7841e92f53d52d9af4de (patch)
treeac07c420966344a5df65a63808fff8331478024c /sys/ufs
parent0a0374b98dce4aacafc7cfb36bd4012cafd95829 (diff)
Put back the pedro diff for VOP_FSYNC of softdep when its
limit is reached. Added twist, clamp the max_softdeps to 64 as it is still possible to exhaust bufkva.
Diffstat (limited to 'sys/ufs')
-rw-r--r--sys/ufs/ffs/ffs_inode.c23
-rw-r--r--sys/ufs/ffs/ffs_softdep.c11
-rw-r--r--sys/ufs/ffs/ffs_vnops.c25
3 files changed, 51 insertions, 8 deletions
diff --git a/sys/ufs/ffs/ffs_inode.c b/sys/ufs/ffs/ffs_inode.c
index 3e47f0a98f3..597bd4ecca4 100644
--- a/sys/ufs/ffs/ffs_inode.c
+++ b/sys/ufs/ffs/ffs_inode.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ffs_inode.c,v 1.59 2011/08/03 20:21:19 beck Exp $ */
+/* $OpenBSD: ffs_inode.c,v 1.60 2011/08/16 14:36:39 thib Exp $ */
/* $NetBSD: ffs_inode.c,v 1.10 1996/05/11 18:27:19 mycroft Exp $ */
/*
@@ -164,8 +164,10 @@ ffs_truncate(struct inode *oip, off_t length, int flags, struct ucred *cred)
struct buf *bp;
int offset, size, level;
long count, nblocks, vflags, blocksreleased = 0;
- int i, aflags, error, allerror;
+ int i, aflags, error, allerror, indirect = 0;
off_t osize;
+ extern int num_indirdep;
+ extern int max_indirdep;
if (length < 0)
return (EINVAL);
@@ -241,6 +243,8 @@ ffs_truncate(struct inode *oip, off_t length, int flags, struct ucred *cred)
cred, aflags, &bp);
if (error)
return (error);
+ if (bp->b_lblkno >= NDADDR)
+ indirect = 1;
DIP_ASSIGN(oip, size, length);
uvm_vnp_setsize(ovp, length);
(void) uvm_vnp_uncache(ovp);
@@ -249,7 +253,20 @@ ffs_truncate(struct inode *oip, off_t length, int flags, struct ucred *cred)
else
bawrite(bp);
oip->i_flag |= IN_CHANGE | IN_UPDATE;
- return (UFS_UPDATE(oip, MNT_WAIT));
+ error = UFS_UPDATE(oip, MNT_WAIT);
+ if (DOINGSOFTDEP(ovp) && num_indirdep > max_indirdep)
+ if (indirect) {
+ /*
+ * If the number of pending indirect block
+ * dependencies is sufficiently close to the
+ * maximum number of simultaneously mappable
+ * buffers force a sync on the vnode to prevent
+ * buffer cache exhaustion.
+ */
+ VOP_FSYNC(ovp, curproc->p_ucred, MNT_WAIT,
+ curproc);
+ }
+ return (error);
}
uvm_vnp_setsize(ovp, length);
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index c42c64499bf..80d9da3d25f 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ffs_softdep.c,v 1.108 2011/08/03 20:21:19 beck Exp $ */
+/* $OpenBSD: ffs_softdep.c,v 1.109 2011/08/16 14:36:39 thib Exp $ */
/*
* Copyright 1998, 2000 Marshall Kirk McKusick. All Rights Reserved.
@@ -526,6 +526,8 @@ workitem_free(struct worklist *item)
STATIC struct workhead softdep_workitem_pending;
STATIC struct worklist *worklist_tail;
STATIC int num_on_worklist; /* number of worklist items to be processed */
+STATIC int num_indirdep; /* number of indirdep items to be processed */
+STATIC int max_indirdep; /* maximum number of indirdep items allowed */
STATIC int softdep_worklist_busy; /* 1 => trying to do unmount */
STATIC int softdep_worklist_req; /* serialized waiters */
STATIC int max_softdeps; /* maximum number of structs before slowdown */
@@ -1140,6 +1142,8 @@ top:
void
softdep_initialize(void)
{
+ extern vsize_t bufkvm;
+ max_indirdep = (int)bufkvm / MAXPHYS * 80 / 100;
bioops.io_start = softdep_disk_io_initiation;
bioops.io_complete = softdep_disk_write_complete;
@@ -1155,6 +1159,7 @@ softdep_initialize(void)
#else
max_softdeps = desiredvnodes * 4;
#endif
+ max_softdeps = 64;
pagedep_hashtbl = hashinit(desiredvnodes / 5, M_PAGEDEP, M_WAITOK,
&pagedep_hash);
sema_init(&pagedep_in_progress, "pagedep", PRIBIO, 0);
@@ -1815,12 +1820,14 @@ setup_allocindir_phase2(struct buf *bp, struct inode *ip,
if (indirdep->ir_savebp != NULL)
brelse(newindirdep->ir_savebp);
WORKITEM_FREE(newindirdep, D_INDIRDEP);
+ num_indirdep--;
}
if (indirdep)
break;
newindirdep = pool_get(&indirdep_pool, PR_WAITOK);
newindirdep->ir_list.wk_type = D_INDIRDEP;
newindirdep->ir_state = ATTACHED;
+ num_indirdep++;
if (ip->i_ump->um_fstype == UM_UFS1)
newindirdep->ir_state |= UFS1FMT;
LIST_INIT(&newindirdep->ir_deplisthd);
@@ -2440,6 +2447,7 @@ indir_trunc(struct inode *ip, daddr64_t dbn, int level, daddr64_t lbn,
}
WORKLIST_REMOVE(wk);
WORKITEM_FREE(indirdep, D_INDIRDEP);
+ num_indirdep--;
if (LIST_FIRST(&bp->b_dep) != NULL) {
FREE_LOCK(&lk);
panic("indir_trunc: dangling dep");
@@ -3281,6 +3289,7 @@ softdep_disk_io_initiation(struct buf *bp)
wk->wk_state &= ~ONWORKLIST;
LIST_REMOVE(wk, wk_list);
WORKITEM_FREE(indirdep, D_INDIRDEP);
+ num_indirdep--;
FREE_LOCK(&lk);
brelse(sbp);
ACQUIRE_LOCK(&lk);
diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c
index 94bd8788910..66a7cc0e43a 100644
--- a/sys/ufs/ffs/ffs_vnops.c
+++ b/sys/ufs/ffs/ffs_vnops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ffs_vnops.c,v 1.66 2011/08/03 20:21:19 beck Exp $ */
+/* $OpenBSD: ffs_vnops.c,v 1.67 2011/08/16 14:36:39 thib Exp $ */
/* $NetBSD: ffs_vnops.c,v 1.7 1996/05/11 18:27:24 mycroft Exp $ */
/*
@@ -299,6 +299,7 @@ ffs_write(void *v)
daddr64_t lbn;
off_t osize;
int blkoffset, error, extended, flags, ioflag, resid, size, xfersize;
+ extern int num_indirdep, max_indirdep;
extended = 0;
ioflag = ap->a_ioflag;
@@ -372,7 +373,11 @@ ffs_write(void *v)
if (uio->uio_offset + xfersize > DIP(ip, size)) {
DIP_ASSIGN(ip, size, uio->uio_offset + xfersize);
uvm_vnp_setsize(vp, DIP(ip, size));
- extended = 1;
+ /* Are we extending into an indirect block? */
+ if (bp->b_lblkno < NDADDR)
+ extended = 1;
+ else
+ extended = 2;
}
(void)uvm_vnp_uncache(vp);
@@ -416,8 +421,20 @@ ffs_write(void *v)
uio->uio_offset -= resid - uio->uio_resid;
uio->uio_resid = resid;
}
- } else if (resid > uio->uio_resid && (ioflag & IO_SYNC)) {
- error = UFS_UPDATE(ip, MNT_WAIT);
+ } else if (resid > uio->uio_resid) {
+ if (ioflag & IO_SYNC)
+ error = UFS_UPDATE(ip, MNT_WAIT);
+ if (DOINGSOFTDEP(vp) && num_indirdep > max_indirdep)
+ if (extended > 1) {
+ /*
+ * If the number of pending indirect block
+ * dependencies is sufficiently close to the
+ * maximum number of simultaneously mappable
+ * buffers force a sync on the vnode to prevent
+ * buffer cache exhaustion.
+ */
+ VOP_FSYNC(vp, NULL, MNT_WAIT, p);
+ }
}
return (error);
}