Home | History | Annotate | Line # | Download | only in lfs
lfs_syscalls.c revision 1.7
      1  1.7  mycroft /*	$NetBSD: lfs_syscalls.c,v 1.7 1994/12/14 13:03:48 mycroft Exp $	*/
      2  1.3      cgd 
      3  1.1  mycroft /*-
      4  1.1  mycroft  * Copyright (c) 1991, 1993, 1994
      5  1.1  mycroft  *	The Regents of the University of California.  All rights reserved.
      6  1.1  mycroft  *
      7  1.1  mycroft  * Redistribution and use in source and binary forms, with or without
      8  1.1  mycroft  * modification, are permitted provided that the following conditions
      9  1.1  mycroft  * are met:
     10  1.1  mycroft  * 1. Redistributions of source code must retain the above copyright
     11  1.1  mycroft  *    notice, this list of conditions and the following disclaimer.
     12  1.1  mycroft  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.1  mycroft  *    notice, this list of conditions and the following disclaimer in the
     14  1.1  mycroft  *    documentation and/or other materials provided with the distribution.
     15  1.1  mycroft  * 3. All advertising materials mentioning features or use of this software
     16  1.1  mycroft  *    must display the following acknowledgement:
     17  1.1  mycroft  *	This product includes software developed by the University of
     18  1.1  mycroft  *	California, Berkeley and its contributors.
     19  1.1  mycroft  * 4. Neither the name of the University nor the names of its contributors
     20  1.1  mycroft  *    may be used to endorse or promote products derived from this software
     21  1.1  mycroft  *    without specific prior written permission.
     22  1.1  mycroft  *
     23  1.1  mycroft  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24  1.1  mycroft  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  1.1  mycroft  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  1.1  mycroft  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27  1.1  mycroft  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  1.1  mycroft  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  1.1  mycroft  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  1.1  mycroft  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  1.1  mycroft  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  1.1  mycroft  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  1.1  mycroft  * SUCH DAMAGE.
     34  1.1  mycroft  *
     35  1.7  mycroft  *	@(#)lfs_syscalls.c	8.6 (Berkeley) 6/16/94
     36  1.1  mycroft  */
     37  1.1  mycroft 
     38  1.1  mycroft #include <sys/param.h>
     39  1.5      cgd #include <sys/systm.h>
     40  1.1  mycroft #include <sys/proc.h>
     41  1.1  mycroft #include <sys/buf.h>
     42  1.1  mycroft #include <sys/mount.h>
     43  1.1  mycroft #include <sys/vnode.h>
     44  1.1  mycroft #include <sys/malloc.h>
     45  1.1  mycroft #include <sys/kernel.h>
     46  1.1  mycroft 
     47  1.5      cgd #include <sys/syscallargs.h>
     48  1.5      cgd 
     49  1.1  mycroft #include <ufs/ufs/quota.h>
     50  1.1  mycroft #include <ufs/ufs/inode.h>
     51  1.1  mycroft #include <ufs/ufs/ufsmount.h>
     52  1.1  mycroft #include <ufs/ufs/ufs_extern.h>
     53  1.1  mycroft 
     54  1.1  mycroft #include <ufs/lfs/lfs.h>
     55  1.1  mycroft #include <ufs/lfs/lfs_extern.h>
     56  1.1  mycroft #define BUMP_FIP(SP) \
     57  1.1  mycroft 	(SP)->fip = (FINFO *) (&(SP)->fip->fi_blocks[(SP)->fip->fi_nblocks])
     58  1.1  mycroft 
     59  1.1  mycroft #define INC_FINFO(SP) ++((SEGSUM *)((SP)->segsum))->ss_nfinfo
     60  1.1  mycroft #define DEC_FINFO(SP) --((SEGSUM *)((SP)->segsum))->ss_nfinfo
     61  1.1  mycroft 
     62  1.1  mycroft /*
     63  1.1  mycroft  * Before committing to add something to a segment summary, make sure there
     64  1.1  mycroft  * is enough room.  S is the bytes added to the summary.
     65  1.1  mycroft  */
     66  1.1  mycroft #define	CHECK_SEG(s)			\
     67  1.1  mycroft if (sp->sum_bytes_left < (s)) {		\
     68  1.1  mycroft 	(void) lfs_writeseg(fs, sp);	\
     69  1.1  mycroft }
     70  1.1  mycroft struct buf *lfs_fakebuf __P((struct vnode *, int, size_t, caddr_t));
     71  1.1  mycroft 
     72  1.1  mycroft /*
     73  1.1  mycroft  * lfs_markv:
     74  1.1  mycroft  *
     75  1.1  mycroft  * This will mark inodes and blocks dirty, so they are written into the log.
     76  1.1  mycroft  * It will block until all the blocks have been written.  The segment create
     77  1.1  mycroft  * time passed in the block_info and inode_info structures is used to decide
     78  1.1  mycroft  * if the data is valid for each block (in case some process dirtied a block
     79  1.1  mycroft  * or inode that is being cleaned between the determination that a block is
     80  1.1  mycroft  * live and the lfs_markv call).
     81  1.1  mycroft  *
     82  1.1  mycroft  *  0 on success
     83  1.1  mycroft  * -1/errno is return on error.
     84  1.1  mycroft  */
     85  1.1  mycroft int
     86  1.1  mycroft lfs_markv(p, uap, retval)
     87  1.1  mycroft 	struct proc *p;
     88  1.5      cgd 	struct lfs_markv_args /* {
     89  1.5      cgd 		syscallarg(fsid_t *) fsidp;
     90  1.5      cgd 		syscallarg(struct block_info *) blkiov;
     91  1.5      cgd 		syscallarg(int) blkcnt;
     92  1.5      cgd 	} */ *uap;
     93  1.5      cgd 	register_t *retval;
     94  1.1  mycroft {
     95  1.1  mycroft 	struct segment *sp;
     96  1.1  mycroft 	BLOCK_INFO *blkp;
     97  1.1  mycroft 	IFILE *ifp;
     98  1.1  mycroft 	struct buf *bp, **bpp;
     99  1.1  mycroft 	struct inode *ip;
    100  1.1  mycroft 	struct lfs *fs;
    101  1.1  mycroft 	struct mount *mntp;
    102  1.1  mycroft 	struct vnode *vp;
    103  1.1  mycroft 	fsid_t fsid;
    104  1.1  mycroft 	void *start;
    105  1.1  mycroft 	ino_t lastino;
    106  1.1  mycroft 	daddr_t b_daddr, v_daddr;
    107  1.1  mycroft 	u_long bsize;
    108  1.1  mycroft 	int cnt, error;
    109  1.1  mycroft 
    110  1.1  mycroft 	if (error = suser(p->p_ucred, &p->p_acflag))
    111  1.1  mycroft 		return (error);
    112  1.1  mycroft 
    113  1.5      cgd 	if (error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t)))
    114  1.1  mycroft 		return (error);
    115  1.1  mycroft 	if ((mntp = getvfs(&fsid)) == NULL)
    116  1.1  mycroft 		return (EINVAL);
    117  1.1  mycroft 
    118  1.5      cgd 	cnt = SCARG(uap, blkcnt);
    119  1.1  mycroft 	start = malloc(cnt * sizeof(BLOCK_INFO), M_SEGMENT, M_WAITOK);
    120  1.5      cgd 	if (error = copyin(SCARG(uap, blkiov), start, cnt * sizeof(BLOCK_INFO)))
    121  1.1  mycroft 		goto err1;
    122  1.1  mycroft 
    123  1.1  mycroft 	/* Mark blocks/inodes dirty.  */
    124  1.1  mycroft 	fs = VFSTOUFS(mntp)->um_lfs;
    125  1.1  mycroft 	bsize = fs->lfs_bsize;
    126  1.1  mycroft 	error = 0;
    127  1.1  mycroft 
    128  1.1  mycroft 	lfs_seglock(fs, SEGM_SYNC | SEGM_CLEAN);
    129  1.1  mycroft 	sp = fs->lfs_sp;
    130  1.1  mycroft 	for (v_daddr = LFS_UNUSED_DADDR, lastino = LFS_UNUSED_INUM,
    131  1.1  mycroft 	    blkp = start; cnt--; ++blkp) {
    132  1.1  mycroft 		/*
    133  1.1  mycroft 		 * Get the IFILE entry (only once) and see if the file still
    134  1.1  mycroft 		 * exists.
    135  1.1  mycroft 		 */
    136  1.1  mycroft 		if (lastino != blkp->bi_inode) {
    137  1.1  mycroft 			if (lastino != LFS_UNUSED_INUM) {
    138  1.1  mycroft 				/* Finish up last file */
    139  1.1  mycroft 				if (sp->fip->fi_nblocks == 0) {
    140  1.1  mycroft 					DEC_FINFO(sp);
    141  1.1  mycroft 					sp->sum_bytes_left +=
    142  1.1  mycroft 					    sizeof(FINFO) - sizeof(daddr_t);
    143  1.1  mycroft 				} else {
    144  1.1  mycroft 					lfs_updatemeta(sp);
    145  1.1  mycroft 					BUMP_FIP(sp);
    146  1.1  mycroft 				}
    147  1.1  mycroft 
    148  1.1  mycroft 				lfs_writeinode(fs, sp, ip);
    149  1.1  mycroft 				lfs_vunref(vp);
    150  1.1  mycroft 			}
    151  1.1  mycroft 
    152  1.1  mycroft 			/* Start a new file */
    153  1.1  mycroft 			CHECK_SEG(sizeof(FINFO));
    154  1.1  mycroft 			sp->sum_bytes_left -= sizeof(FINFO) - sizeof(daddr_t);
    155  1.1  mycroft 			INC_FINFO(sp);
    156  1.1  mycroft 			sp->start_lbp = &sp->fip->fi_blocks[0];
    157  1.1  mycroft 			sp->vp = NULL;
    158  1.1  mycroft 			sp->fip->fi_version = blkp->bi_version;
    159  1.1  mycroft 			sp->fip->fi_nblocks = 0;
    160  1.1  mycroft 			sp->fip->fi_ino = blkp->bi_inode;
    161  1.1  mycroft 			lastino = blkp->bi_inode;
    162  1.1  mycroft 			if (blkp->bi_inode == LFS_IFILE_INUM)
    163  1.1  mycroft 				v_daddr = fs->lfs_idaddr;
    164  1.1  mycroft 			else {
    165  1.1  mycroft 				LFS_IENTRY(ifp, fs, blkp->bi_inode, bp);
    166  1.1  mycroft 				v_daddr = ifp->if_daddr;
    167  1.1  mycroft 				brelse(bp);
    168  1.1  mycroft 			}
    169  1.1  mycroft 			if (v_daddr == LFS_UNUSED_DADDR)
    170  1.1  mycroft 				continue;
    171  1.1  mycroft 
    172  1.1  mycroft 			/* Get the vnode/inode. */
    173  1.1  mycroft 			if (lfs_fastvget(mntp, blkp->bi_inode, v_daddr, &vp,
    174  1.1  mycroft 			    blkp->bi_lbn == LFS_UNUSED_LBN ?
    175  1.1  mycroft 			    blkp->bi_bp : NULL)) {
    176  1.1  mycroft #ifdef DIAGNOSTIC
    177  1.1  mycroft 				printf("lfs_markv: VFS_VGET failed (%d)\n",
    178  1.1  mycroft 				    blkp->bi_inode);
    179  1.1  mycroft #endif
    180  1.1  mycroft 				lastino = LFS_UNUSED_INUM;
    181  1.1  mycroft 				v_daddr = LFS_UNUSED_DADDR;
    182  1.1  mycroft 				continue;
    183  1.1  mycroft 			}
    184  1.1  mycroft 			sp->vp = vp;
    185  1.1  mycroft 			ip = VTOI(vp);
    186  1.1  mycroft 		} else if (v_daddr == LFS_UNUSED_DADDR)
    187  1.1  mycroft 			continue;
    188  1.1  mycroft 
    189  1.1  mycroft 		/* If this BLOCK_INFO didn't contain a block, keep going. */
    190  1.1  mycroft 		if (blkp->bi_lbn == LFS_UNUSED_LBN)
    191  1.1  mycroft 			continue;
    192  1.1  mycroft 		if (VOP_BMAP(vp, blkp->bi_lbn, NULL, &b_daddr, NULL) ||
    193  1.1  mycroft 		    b_daddr != blkp->bi_daddr)
    194  1.1  mycroft 			continue;
    195  1.1  mycroft 		/*
    196  1.1  mycroft 		 * If we got to here, then we are keeping the block.  If it
    197  1.1  mycroft 		 * is an indirect block, we want to actually put it in the
    198  1.1  mycroft 		 * buffer cache so that it can be updated in the finish_meta
    199  1.1  mycroft 		 * section.  If it's not, we need to allocate a fake buffer
    200  1.1  mycroft 		 * so that writeseg can perform the copyin and write the buffer.
    201  1.1  mycroft 		 */
    202  1.1  mycroft 		if (blkp->bi_lbn >= 0)	/* Data Block */
    203  1.1  mycroft 			bp = lfs_fakebuf(vp, blkp->bi_lbn, bsize,
    204  1.1  mycroft 			    blkp->bi_bp);
    205  1.1  mycroft 		else {
    206  1.1  mycroft 			bp = getblk(vp, blkp->bi_lbn, bsize, 0, 0);
    207  1.1  mycroft 			if (!(bp->b_flags & (B_DELWRI | B_DONE | B_CACHE)) &&
    208  1.1  mycroft 			    (error = copyin(blkp->bi_bp, bp->b_data,
    209  1.1  mycroft 			    bsize)))
    210  1.1  mycroft 				goto err2;
    211  1.1  mycroft 			if (error = VOP_BWRITE(bp))
    212  1.1  mycroft 				goto err2;
    213  1.1  mycroft 		}
    214  1.1  mycroft 		while (lfs_gatherblock(sp, bp, NULL));
    215  1.1  mycroft 	}
    216  1.1  mycroft 	if (sp->vp) {
    217  1.1  mycroft 		if (sp->fip->fi_nblocks == 0) {
    218  1.1  mycroft 			DEC_FINFO(sp);
    219  1.1  mycroft 			sp->sum_bytes_left +=
    220  1.1  mycroft 			    sizeof(FINFO) - sizeof(daddr_t);
    221  1.1  mycroft 		} else
    222  1.1  mycroft 			lfs_updatemeta(sp);
    223  1.1  mycroft 
    224  1.1  mycroft 		lfs_writeinode(fs, sp, ip);
    225  1.1  mycroft 		lfs_vunref(vp);
    226  1.1  mycroft 	}
    227  1.1  mycroft 	(void) lfs_writeseg(fs, sp);
    228  1.1  mycroft 	lfs_segunlock(fs);
    229  1.1  mycroft 	free(start, M_SEGMENT);
    230  1.1  mycroft 	return (error);
    231  1.1  mycroft 
    232  1.1  mycroft /*
    233  1.1  mycroft  * XXX
    234  1.1  mycroft  * If we come in to error 2, we might have indirect blocks that were
    235  1.1  mycroft  * updated and now have bad block pointers.  I don't know what to do
    236  1.1  mycroft  * about this.
    237  1.1  mycroft  */
    238  1.1  mycroft 
    239  1.1  mycroft err2:	lfs_vunref(vp);
    240  1.1  mycroft 	/* Free up fakebuffers */
    241  1.1  mycroft 	for (bpp = --sp->cbpp; bpp >= sp->bpp; --bpp)
    242  1.1  mycroft 		if ((*bpp)->b_flags & B_CALL) {
    243  1.1  mycroft 			brelvp(*bpp);
    244  1.1  mycroft 			free(*bpp, M_SEGMENT);
    245  1.1  mycroft 		} else
    246  1.1  mycroft 			brelse(*bpp);
    247  1.1  mycroft 	lfs_segunlock(fs);
    248  1.1  mycroft err1:
    249  1.1  mycroft 	free(start, M_SEGMENT);
    250  1.1  mycroft 	return (error);
    251  1.1  mycroft }
    252  1.1  mycroft 
    253  1.1  mycroft /*
    254  1.1  mycroft  * lfs_bmapv:
    255  1.1  mycroft  *
    256  1.1  mycroft  * This will fill in the current disk address for arrays of blocks.
    257  1.1  mycroft  *
    258  1.1  mycroft  *  0 on success
    259  1.1  mycroft  * -1/errno is return on error.
    260  1.1  mycroft  */
    261  1.1  mycroft int
    262  1.1  mycroft lfs_bmapv(p, uap, retval)
    263  1.1  mycroft 	struct proc *p;
    264  1.5      cgd 	struct lfs_bmapv_args /* {
    265  1.5      cgd 		syscallarg(fsid_t *) fsidp;
    266  1.5      cgd 		syscallarg(struct block_info *) blkiov;
    267  1.5      cgd 		syscallarg(int) blkcnt;
    268  1.5      cgd 	} */ *uap;
    269  1.5      cgd 	register_t *retval;
    270  1.1  mycroft {
    271  1.1  mycroft 	BLOCK_INFO *blkp;
    272  1.1  mycroft 	struct mount *mntp;
    273  1.1  mycroft 	struct vnode *vp;
    274  1.1  mycroft 	fsid_t fsid;
    275  1.1  mycroft 	void *start;
    276  1.1  mycroft 	daddr_t daddr;
    277  1.1  mycroft 	int cnt, error, step;
    278  1.1  mycroft 
    279  1.1  mycroft 	if (error = suser(p->p_ucred, &p->p_acflag))
    280  1.1  mycroft 		return (error);
    281  1.1  mycroft 
    282  1.5      cgd 	if (error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t)))
    283  1.1  mycroft 		return (error);
    284  1.1  mycroft 	if ((mntp = getvfs(&fsid)) == NULL)
    285  1.1  mycroft 		return (EINVAL);
    286  1.1  mycroft 
    287  1.5      cgd 	cnt = SCARG(uap, blkcnt);
    288  1.1  mycroft 	start = blkp = malloc(cnt * sizeof(BLOCK_INFO), M_SEGMENT, M_WAITOK);
    289  1.5      cgd 	if (error = copyin(SCARG(uap, blkiov), blkp,
    290  1.5      cgd 	    cnt * sizeof(BLOCK_INFO))) {
    291  1.1  mycroft 		free(blkp, M_SEGMENT);
    292  1.1  mycroft 		return (error);
    293  1.1  mycroft 	}
    294  1.1  mycroft 
    295  1.1  mycroft 	for (step = cnt; step--; ++blkp) {
    296  1.1  mycroft 		if (blkp->bi_lbn == LFS_UNUSED_LBN)
    297  1.1  mycroft 			continue;
    298  1.1  mycroft 		/* Could be a deadlock ? */
    299  1.1  mycroft 		if (VFS_VGET(mntp, blkp->bi_inode, &vp))
    300  1.1  mycroft 			daddr = LFS_UNUSED_DADDR;
    301  1.1  mycroft 		else {
    302  1.1  mycroft 			if (VOP_BMAP(vp, blkp->bi_lbn, NULL, &daddr, NULL))
    303  1.1  mycroft 				daddr = LFS_UNUSED_DADDR;
    304  1.1  mycroft 			vput(vp);
    305  1.1  mycroft 		}
    306  1.1  mycroft 		blkp->bi_daddr = daddr;
    307  1.1  mycroft         }
    308  1.5      cgd 	copyout(start, SCARG(uap, blkiov), cnt * sizeof(BLOCK_INFO));
    309  1.1  mycroft 	free(start, M_SEGMENT);
    310  1.1  mycroft 	return (0);
    311  1.1  mycroft }
    312  1.1  mycroft 
    313  1.1  mycroft /*
    314  1.1  mycroft  * lfs_segclean:
    315  1.1  mycroft  *
    316  1.1  mycroft  * Mark the segment clean.
    317  1.1  mycroft  *
    318  1.1  mycroft  *  0 on success
    319  1.1  mycroft  * -1/errno is return on error.
    320  1.1  mycroft  */
    321  1.1  mycroft int
    322  1.1  mycroft lfs_segclean(p, uap, retval)
    323  1.1  mycroft 	struct proc *p;
    324  1.5      cgd 	struct lfs_segclean_args /* {
    325  1.5      cgd 		syscallarg(fsid_t *) fsidp;
    326  1.5      cgd 		syscallarg(u_long) segment;
    327  1.5      cgd 	} */ *uap;
    328  1.5      cgd 	register_t *retval;
    329  1.1  mycroft {
    330  1.1  mycroft 	CLEANERINFO *cip;
    331  1.1  mycroft 	SEGUSE *sup;
    332  1.1  mycroft 	struct buf *bp;
    333  1.1  mycroft 	struct mount *mntp;
    334  1.1  mycroft 	struct lfs *fs;
    335  1.1  mycroft 	fsid_t fsid;
    336  1.1  mycroft 	int error;
    337  1.1  mycroft 
    338  1.1  mycroft 	if (error = suser(p->p_ucred, &p->p_acflag))
    339  1.1  mycroft 		return (error);
    340  1.1  mycroft 
    341  1.5      cgd 	if (error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t)))
    342  1.1  mycroft 		return (error);
    343  1.1  mycroft 	if ((mntp = getvfs(&fsid)) == NULL)
    344  1.1  mycroft 		return (EINVAL);
    345  1.1  mycroft 
    346  1.1  mycroft 	fs = VFSTOUFS(mntp)->um_lfs;
    347  1.1  mycroft 
    348  1.5      cgd 	if (datosn(fs, fs->lfs_curseg) == SCARG(uap, segment))
    349  1.1  mycroft 		return (EBUSY);
    350  1.1  mycroft 
    351  1.5      cgd 	LFS_SEGENTRY(sup, fs, SCARG(uap, segment), bp);
    352  1.1  mycroft 	if (sup->su_flags & SEGUSE_ACTIVE) {
    353  1.1  mycroft 		brelse(bp);
    354  1.1  mycroft 		return (EBUSY);
    355  1.1  mycroft 	}
    356  1.1  mycroft 	fs->lfs_avail += fsbtodb(fs, fs->lfs_ssize) - 1;
    357  1.1  mycroft 	fs->lfs_bfree += (sup->su_nsums * LFS_SUMMARY_SIZE / DEV_BSIZE) +
    358  1.1  mycroft 	    sup->su_ninos * btodb(fs->lfs_bsize);
    359  1.1  mycroft 	sup->su_flags &= ~SEGUSE_DIRTY;
    360  1.1  mycroft 	(void) VOP_BWRITE(bp);
    361  1.1  mycroft 
    362  1.1  mycroft 	LFS_CLEANERINFO(cip, fs, bp);
    363  1.1  mycroft 	++cip->clean;
    364  1.1  mycroft 	--cip->dirty;
    365  1.1  mycroft 	(void) VOP_BWRITE(bp);
    366  1.1  mycroft 	wakeup(&fs->lfs_avail);
    367  1.1  mycroft 	return (0);
    368  1.1  mycroft }
    369  1.1  mycroft 
    370  1.1  mycroft /*
    371  1.1  mycroft  * lfs_segwait:
    372  1.1  mycroft  *
    373  1.1  mycroft  * This will block until a segment in file system fsid is written.  A timeout
    374  1.1  mycroft  * in milliseconds may be specified which will awake the cleaner automatically.
    375  1.1  mycroft  * An fsid of -1 means any file system, and a timeout of 0 means forever.
    376  1.1  mycroft  *
    377  1.1  mycroft  *  0 on success
    378  1.1  mycroft  *  1 on timeout
    379  1.1  mycroft  * -1/errno is return on error.
    380  1.1  mycroft  */
    381  1.1  mycroft int
    382  1.1  mycroft lfs_segwait(p, uap, retval)
    383  1.1  mycroft 	struct proc *p;
    384  1.5      cgd 	struct lfs_segwait_args /* {
    385  1.5      cgd 		syscallarg(fsid_t *) fsidp;
    386  1.5      cgd 		syscallarg(struct timeval *) tv;
    387  1.5      cgd 	} */ *uap;
    388  1.5      cgd 	register_t *retval;
    389  1.1  mycroft {
    390  1.1  mycroft 	extern int lfs_allclean_wakeup;
    391  1.1  mycroft 	struct mount *mntp;
    392  1.1  mycroft 	struct timeval atv;
    393  1.1  mycroft 	fsid_t fsid;
    394  1.1  mycroft 	void *addr;
    395  1.1  mycroft 	u_long timeout;
    396  1.1  mycroft 	int error, s;
    397  1.1  mycroft 
    398  1.1  mycroft 	if (error = suser(p->p_ucred, &p->p_acflag)) {
    399  1.1  mycroft 		return (error);
    400  1.1  mycroft }
    401  1.1  mycroft #ifdef WHEN_QUADS_WORK
    402  1.5      cgd 	if (error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t)))
    403  1.1  mycroft 		return (error);
    404  1.1  mycroft 	if (fsid == (fsid_t)-1)
    405  1.1  mycroft 		addr = &lfs_allclean_wakeup;
    406  1.1  mycroft 	else {
    407  1.1  mycroft 		if ((mntp = getvfs(&fsid)) == NULL)
    408  1.1  mycroft 			return (EINVAL);
    409  1.1  mycroft 		addr = &VFSTOUFS(mntp)->um_lfs->lfs_nextseg;
    410  1.1  mycroft 	}
    411  1.1  mycroft #else
    412  1.5      cgd 	if (error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t)))
    413  1.1  mycroft 		return (error);
    414  1.1  mycroft 	if ((mntp = getvfs(&fsid)) == NULL)
    415  1.1  mycroft 		addr = &lfs_allclean_wakeup;
    416  1.1  mycroft 	else
    417  1.1  mycroft 		addr = &VFSTOUFS(mntp)->um_lfs->lfs_nextseg;
    418  1.1  mycroft #endif
    419  1.1  mycroft 
    420  1.5      cgd 	if (SCARG(uap, tv)) {
    421  1.5      cgd 		if (error =
    422  1.5      cgd 		    copyin(SCARG(uap, tv), &atv, sizeof(struct timeval)))
    423  1.1  mycroft 			return (error);
    424  1.1  mycroft 		if (itimerfix(&atv))
    425  1.1  mycroft 			return (EINVAL);
    426  1.1  mycroft 		s = splclock();
    427  1.6  mycroft 		__timeradd(&atv, &time);
    428  1.1  mycroft 		timeout = hzto(&atv);
    429  1.1  mycroft 		splx(s);
    430  1.1  mycroft 	} else
    431  1.1  mycroft 		timeout = 0;
    432  1.1  mycroft 
    433  1.1  mycroft 	error = tsleep(addr, PCATCH | PUSER, "segment", timeout);
    434  1.1  mycroft 	return (error == ERESTART ? EINTR : 0);
    435  1.1  mycroft }
    436  1.1  mycroft 
    437  1.1  mycroft /*
    438  1.1  mycroft  * VFS_VGET call specialized for the cleaner.  The cleaner already knows the
    439  1.1  mycroft  * daddr from the ifile, so don't look it up again.  If the cleaner is
    440  1.1  mycroft  * processing IINFO structures, it may have the ondisk inode already, so
    441  1.1  mycroft  * don't go retrieving it again.
    442  1.1  mycroft  */
    443  1.1  mycroft int
    444  1.1  mycroft lfs_fastvget(mp, ino, daddr, vpp, dinp)
    445  1.1  mycroft 	struct mount *mp;
    446  1.1  mycroft 	ino_t ino;
    447  1.1  mycroft 	daddr_t daddr;
    448  1.1  mycroft 	struct vnode **vpp;
    449  1.1  mycroft 	struct dinode *dinp;
    450  1.1  mycroft {
    451  1.1  mycroft 	register struct inode *ip;
    452  1.1  mycroft 	struct vnode *vp;
    453  1.1  mycroft 	struct ufsmount *ump;
    454  1.1  mycroft 	struct buf *bp;
    455  1.1  mycroft 	dev_t dev;
    456  1.1  mycroft 	int error;
    457  1.1  mycroft 
    458  1.1  mycroft 	ump = VFSTOUFS(mp);
    459  1.1  mycroft 	dev = ump->um_dev;
    460  1.1  mycroft 	/*
    461  1.1  mycroft 	 * This is playing fast and loose.  Someone may have the inode
    462  1.1  mycroft 	 * locked, in which case they are going to be distinctly unhappy
    463  1.1  mycroft 	 * if we trash something.
    464  1.1  mycroft 	 */
    465  1.1  mycroft 	if ((*vpp = ufs_ihashlookup(dev, ino)) != NULL) {
    466  1.1  mycroft 		lfs_vref(*vpp);
    467  1.1  mycroft 		if ((*vpp)->v_flag & VXLOCK)
    468  1.1  mycroft 			printf ("Cleaned vnode VXLOCKED\n");
    469  1.1  mycroft 		ip = VTOI(*vpp);
    470  1.2  mycroft 		if (ip->i_flag & IN_LOCKED)
    471  1.1  mycroft 			printf("cleaned vnode locked\n");
    472  1.1  mycroft 		if (!(ip->i_flag & IN_MODIFIED)) {
    473  1.1  mycroft 			++ump->um_lfs->lfs_uinodes;
    474  1.1  mycroft 			ip->i_flag |= IN_MODIFIED;
    475  1.1  mycroft 		}
    476  1.1  mycroft 		ip->i_flag |= IN_MODIFIED;
    477  1.1  mycroft 		return (0);
    478  1.1  mycroft 	}
    479  1.1  mycroft 
    480  1.1  mycroft 	/* Allocate new vnode/inode. */
    481  1.1  mycroft 	if (error = lfs_vcreate(mp, ino, &vp)) {
    482  1.1  mycroft 		*vpp = NULL;
    483  1.1  mycroft 		return (error);
    484  1.1  mycroft 	}
    485  1.1  mycroft 
    486  1.1  mycroft 	/*
    487  1.1  mycroft 	 * Put it onto its hash chain and lock it so that other requests for
    488  1.1  mycroft 	 * this inode will block if they arrive while we are sleeping waiting
    489  1.1  mycroft 	 * for old data structures to be purged or for the contents of the
    490  1.1  mycroft 	 * disk portion of this inode to be read.
    491  1.1  mycroft 	 */
    492  1.1  mycroft 	ip = VTOI(vp);
    493  1.1  mycroft 	ufs_ihashins(ip);
    494  1.1  mycroft 
    495  1.1  mycroft 	/*
    496  1.1  mycroft 	 * XXX
    497  1.1  mycroft 	 * This may not need to be here, logically it should go down with
    498  1.1  mycroft 	 * the i_devvp initialization.
    499  1.1  mycroft 	 * Ask Kirk.
    500  1.1  mycroft 	 */
    501  1.1  mycroft 	ip->i_lfs = ump->um_lfs;
    502  1.1  mycroft 
    503  1.1  mycroft 	/* Read in the disk contents for the inode, copy into the inode. */
    504  1.1  mycroft 	if (dinp)
    505  1.1  mycroft 		if (error = copyin(dinp, &ip->i_din, sizeof(struct dinode)))
    506  1.1  mycroft 			return (error);
    507  1.1  mycroft 	else {
    508  1.1  mycroft 		if (error = bread(ump->um_devvp, daddr,
    509  1.1  mycroft 		    (int)ump->um_lfs->lfs_bsize, NOCRED, &bp)) {
    510  1.1  mycroft 			/*
    511  1.1  mycroft 			 * The inode does not contain anything useful, so it
    512  1.1  mycroft 			 * would be misleading to leave it on its hash chain.
    513  1.1  mycroft 			 * Iput() will return it to the free list.
    514  1.1  mycroft 			 */
    515  1.1  mycroft 			ufs_ihashrem(ip);
    516  1.1  mycroft 
    517  1.1  mycroft 			/* Unlock and discard unneeded inode. */
    518  1.1  mycroft 			lfs_vunref(vp);
    519  1.1  mycroft 			brelse(bp);
    520  1.1  mycroft 			*vpp = NULL;
    521  1.1  mycroft 			return (error);
    522  1.1  mycroft 		}
    523  1.1  mycroft 		ip->i_din =
    524  1.1  mycroft 		    *lfs_ifind(ump->um_lfs, ino, (struct dinode *)bp->b_data);
    525  1.1  mycroft 		brelse(bp);
    526  1.1  mycroft 	}
    527  1.1  mycroft 
    528  1.1  mycroft 	/* Inode was just read from user space or disk, make sure it's locked */
    529  1.1  mycroft 	ip->i_flag |= IN_LOCKED;
    530  1.1  mycroft 
    531  1.1  mycroft 	/*
    532  1.1  mycroft 	 * Initialize the vnode from the inode, check for aliases.  In all
    533  1.1  mycroft 	 * cases re-init ip, the underlying vnode/inode may have changed.
    534  1.1  mycroft 	 */
    535  1.1  mycroft 	if (error = ufs_vinit(mp, lfs_specop_p, LFS_FIFOOPS, &vp)) {
    536  1.1  mycroft 		lfs_vunref(vp);
    537  1.1  mycroft 		*vpp = NULL;
    538  1.1  mycroft 		return (error);
    539  1.1  mycroft 	}
    540  1.1  mycroft 	/*
    541  1.1  mycroft 	 * Finish inode initialization now that aliasing has been resolved.
    542  1.1  mycroft 	 */
    543  1.1  mycroft 	ip->i_devvp = ump->um_devvp;
    544  1.1  mycroft 	ip->i_flag |= IN_MODIFIED;
    545  1.1  mycroft 	++ump->um_lfs->lfs_uinodes;
    546  1.1  mycroft 	VREF(ip->i_devvp);
    547  1.1  mycroft 	*vpp = vp;
    548  1.1  mycroft 	return (0);
    549  1.1  mycroft }
    550  1.1  mycroft struct buf *
    551  1.1  mycroft lfs_fakebuf(vp, lbn, size, uaddr)
    552  1.1  mycroft 	struct vnode *vp;
    553  1.1  mycroft 	int lbn;
    554  1.1  mycroft 	size_t size;
    555  1.1  mycroft 	caddr_t uaddr;
    556  1.1  mycroft {
    557  1.1  mycroft 	struct buf *bp;
    558  1.1  mycroft 
    559  1.1  mycroft 	bp = lfs_newbuf(vp, lbn, 0);
    560  1.1  mycroft 	bp->b_saveaddr = uaddr;
    561  1.1  mycroft 	bp->b_bufsize = size;
    562  1.1  mycroft 	bp->b_bcount = size;
    563  1.1  mycroft 	bp->b_flags |= B_INVAL;
    564  1.1  mycroft 	return (bp);
    565  1.1  mycroft }
    566