xref: /csrg-svn/sys/ufs/lfs/lfs_subr.c (revision 69291)
151500Sbostic /*
263375Sbostic  * Copyright (c) 1991, 1993
363375Sbostic  *	The Regents of the University of California.  All rights reserved.
451500Sbostic  *
551500Sbostic  * %sccs.include.redist.c%
651500Sbostic  *
7*69291Smckusick  *	@(#)lfs_subr.c	8.4 (Berkeley) 05/08/95
851500Sbostic  */
951500Sbostic 
1051500Sbostic #include <sys/param.h>
1151500Sbostic #include <sys/namei.h>
1251500Sbostic #include <sys/vnode.h>
1351500Sbostic #include <sys/buf.h>
1454264Sbostic #include <sys/mount.h>
1557064Smargo #include <sys/malloc.h>
1657064Smargo #include <sys/proc.h>
1751500Sbostic 
1851500Sbostic #include <ufs/ufs/quota.h>
1951500Sbostic #include <ufs/ufs/inode.h>
2051500Sbostic #include <ufs/lfs/lfs.h>
2151500Sbostic #include <ufs/lfs/lfs_extern.h>
2251500Sbostic 
2351500Sbostic /*
2451500Sbostic  * Return buffer with the contents of block "offset" from the beginning of
2551500Sbostic  * directory "ip".  If "res" is non-zero, fill it in with a pointer to the
2651500Sbostic  * remaining space in the directory.
2751500Sbostic  */
2851500Sbostic int
lfs_blkatoff(ap)2954691Sbostic lfs_blkatoff(ap)
3054691Sbostic 	struct vop_blkatoff_args /* {
3154691Sbostic 		struct vnode *a_vp;
3254691Sbostic 		off_t a_offset;
3354691Sbostic 		char **a_res;
3454691Sbostic 		struct buf **a_bpp;
3554691Sbostic 	} */ *ap;
3651500Sbostic {
3751500Sbostic 	register struct lfs *fs;
3851557Smckusick 	struct inode *ip;
3951500Sbostic 	struct buf *bp;
4068550Smckusick 	ufs_daddr_t lbn;
4151500Sbostic 	int bsize, error;
4251500Sbostic 
4353592Sheideman 	ip = VTOI(ap->a_vp);
4451500Sbostic 	fs = ip->i_lfs;
4553592Sheideman 	lbn = lblkno(fs, ap->a_offset);
46*69291Smckusick 	bsize = blksize(fs, ip, lbn);
4751500Sbostic 
4853592Sheideman 	*ap->a_bpp = NULL;
4953592Sheideman 	if (error = bread(ap->a_vp, lbn, bsize, NOCRED, &bp)) {
5051500Sbostic 		brelse(bp);
5151500Sbostic 		return (error);
5251500Sbostic 	}
5353592Sheideman 	if (ap->a_res)
5464520Sbostic 		*ap->a_res = (char *)bp->b_data + blkoff(fs, ap->a_offset);
5553592Sheideman 	*ap->a_bpp = bp;
5651500Sbostic 	return (0);
5751500Sbostic }
5854264Sbostic 
5957064Smargo 
6054691Sbostic /*
6154691Sbostic  * lfs_seglock --
6254691Sbostic  *	Single thread the segment writer.
6354691Sbostic  */
6454691Sbostic void
lfs_seglock(fs,flags)6557064Smargo lfs_seglock(fs, flags)
6654691Sbostic 	struct lfs *fs;
6757064Smargo 	unsigned long flags;
6854264Sbostic {
6957064Smargo 	struct segment *sp;
7057064Smargo 	int s;
7157064Smargo 
7257064Smargo 	if (fs->lfs_seglock)
7357064Smargo 		if (fs->lfs_lockpid == curproc->p_pid) {
7457064Smargo 			++fs->lfs_seglock;
7557064Smargo 			fs->lfs_sp->seg_flags |= flags;
7657064Smargo 			return;
7757064Smargo 		} else while (fs->lfs_seglock)
7857064Smargo 			(void)tsleep(&fs->lfs_seglock, PRIBIO + 1,
7957064Smargo 			    "lfs seglock", 0);
8057064Smargo 
8154691Sbostic 	fs->lfs_seglock = 1;
8257064Smargo 	fs->lfs_lockpid = curproc->p_pid;
8357064Smargo 
8457064Smargo 	sp = fs->lfs_sp = malloc(sizeof(struct segment), M_SEGMENT, M_WAITOK);
8557064Smargo 	sp->bpp = malloc(((LFS_SUMMARY_SIZE - sizeof(SEGSUM)) /
8668550Smckusick 	    sizeof(ufs_daddr_t) + 1) * sizeof(struct buf *),
8768550Smckusick 	    M_SEGMENT, M_WAITOK);
8857064Smargo 	sp->seg_flags = flags;
8957064Smargo 	sp->vp = NULL;
9057064Smargo 	(void) lfs_initseg(fs);
9157064Smargo 
9257064Smargo 	/*
9357064Smargo 	 * Keep a cumulative count of the outstanding I/O operations.  If the
9457064Smargo 	 * disk drive catches up with us it could go to zero before we finish,
9557064Smargo 	 * so we artificially increment it by one until we've scheduled all of
9657064Smargo 	 * the writes we intend to do.
9757064Smargo 	 */
9857064Smargo 	s = splbio();
9957064Smargo 	++fs->lfs_iocount;
10057064Smargo 	splx(s);
10154264Sbostic }
10254264Sbostic /*
10354691Sbostic  * lfs_segunlock --
10454691Sbostic  *	Single thread the segment writer.
10554264Sbostic  */
10654691Sbostic void
lfs_segunlock(fs)10754691Sbostic lfs_segunlock(fs)
10854691Sbostic 	struct lfs *fs;
10954264Sbostic {
11057064Smargo 	struct segment *sp;
11157064Smargo 	unsigned long sync, ckp;
11257064Smargo 	int s;
11357064Smargo 
11457064Smargo 	if (fs->lfs_seglock == 1) {
11557064Smargo 
11657064Smargo 		sp = fs->lfs_sp;
11757064Smargo 		sync = sp->seg_flags & SEGM_SYNC;
11857064Smargo 		ckp = sp->seg_flags & SEGM_CKP;
11957064Smargo 		if (sp->bpp != sp->cbpp) {
12057064Smargo 			/* Free allocated segment summary */
12157064Smargo 			fs->lfs_offset -= LFS_SUMMARY_SIZE / DEV_BSIZE;
12257064Smargo 			brelvp(*sp->bpp);
12364520Sbostic 			free((*sp->bpp)->b_data, M_SEGMENT);
12457064Smargo 			free(*sp->bpp, M_SEGMENT);
12557064Smargo 		} else
12657064Smargo 			printf ("unlock to 0 with no summary");
12757064Smargo 		free(sp->bpp, M_SEGMENT);
12857064Smargo 		free(sp, M_SEGMENT);
12957064Smargo 
13057064Smargo 		/*
13157064Smargo 		 * If the I/O count is non-zero, sleep until it reaches zero.
13257064Smargo 		 * At the moment, the user's process hangs around so we can
13357064Smargo 		 * sleep.
13457064Smargo 		 */
13557064Smargo 		s = splbio();
13657064Smargo 		--fs->lfs_iocount;
13757064Smargo 		/*
13857064Smargo 		 * We let checkpoints happen asynchronously.  That means
13957064Smargo 		 * that during recovery, we have to roll forward between
14057064Smargo 		 * the two segments described by the first and second
14157064Smargo 		 * superblocks to make sure that the checkpoint described
14257064Smargo 		 * by a superblock completed.
14357064Smargo 		 */
14457064Smargo 		if (sync && fs->lfs_iocount)
14557064Smargo 		    (void)tsleep(&fs->lfs_iocount, PRIBIO + 1, "lfs vflush", 0);
14657064Smargo 		splx(s);
14757064Smargo 		if (ckp) {
14857064Smargo 			fs->lfs_nactive = 0;
14957064Smargo 			lfs_writesuper(fs);
15057064Smargo 		}
15157064Smargo 		--fs->lfs_seglock;
15257064Smargo 		fs->lfs_lockpid = 0;
15357064Smargo 		wakeup(&fs->lfs_seglock);
15457064Smargo 	} else if (fs->lfs_seglock == 0) {
15557064Smargo 		panic ("Seglock not held");
15657064Smargo 	} else {
15757064Smargo 		--fs->lfs_seglock;
15857064Smargo 	}
15954264Sbostic }
160