diff options
author | Thordur I. Bjornsson <thib@cvs.openbsd.org> | 2011-08-16 14:36:40 +0000 |
---|---|---|
committer | Thordur I. Bjornsson <thib@cvs.openbsd.org> | 2011-08-16 14:36:40 +0000 |
commit | 524fc0c212ac7546522d7841e92f53d52d9af4de (patch) | |
tree | ac07c420966344a5df65a63808fff8331478024c /sys/ufs | |
parent | 0a0374b98dce4aacafc7cfb36bd4012cafd95829 (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.c | 23 | ||||
-rw-r--r-- | sys/ufs/ffs/ffs_softdep.c | 11 | ||||
-rw-r--r-- | sys/ufs/ffs/ffs_vnops.c | 25 |
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); } |